mirror of
https://github.com/aharabada/glitchy-engine-beef.git
synced 2026-09-05 21:01:52 +00:00
DX11: Automatically validate input layouts against vertex shaders
This commit is contained in:
@@ -15,7 +15,6 @@ namespace GlitchyEngine.Renderer
|
||||
internal uint32[DirectX.D3D11.D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT] bufferStrides;
|
||||
internal uint32[DirectX.D3D11.D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT] bufferOffsets;
|
||||
|
||||
internal ID3D11InputLayout* nativeVertexLayout;
|
||||
internal ID3D11Buffer* nativeIndexBuffer;
|
||||
|
||||
public ~this()
|
||||
@@ -25,7 +24,6 @@ namespace GlitchyEngine.Renderer
|
||||
buffer?.Release();
|
||||
}
|
||||
|
||||
nativeVertexLayout?.Release();
|
||||
nativeIndexBuffer?.Release();
|
||||
}
|
||||
|
||||
@@ -61,10 +59,6 @@ namespace GlitchyEngine.Renderer
|
||||
|
||||
protected override void PlatformSetVertexLayout(VertexLayout vertexLayout)
|
||||
{
|
||||
Debug.Profiler.ProfileResourceFunction!();
|
||||
|
||||
nativeVertexLayout?.Release();
|
||||
nativeVertexLayout = vertexLayout?.nativeLayout..AddRef();
|
||||
}
|
||||
|
||||
protected override void PlatformSetIndexBuffer(IndexBuffer indexBuffer)
|
||||
@@ -88,7 +82,7 @@ namespace GlitchyEngine.Renderer
|
||||
Debug.Profiler.ProfileRendererFunction!();
|
||||
|
||||
NativeContext.InputAssembler.SetVertexBuffers(0, nativeBuffers.Count, &nativeBuffers, &bufferStrides, &bufferOffsets);
|
||||
NativeContext.InputAssembler.SetInputLayout(_vertexLayout.nativeLayout);
|
||||
GraphicsContext.Get().SetVertexLayout(_vertexLayout);
|
||||
NativeContext.InputAssembler.SetPrimitiveTopology((.)_primitiveTopology);
|
||||
|
||||
if(_indexBuffer != null)
|
||||
|
||||
@@ -34,6 +34,11 @@ namespace GlitchyEngine.Renderer
|
||||
|
||||
private const uint32 MaxRTVCount = DirectX.D3D11.D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT;
|
||||
|
||||
// current vertex layout and vertex shader needed for validation.
|
||||
ID3D11InputLayout* _currentInputLayout ~ _?.Release();
|
||||
VertexLayout _currentVertexLayout ~ _?.ReleaseRef();
|
||||
VertexShader _currentVertexShader ~ _?.ReleaseRef();
|
||||
|
||||
//public static override uint32 MaxRenderTargetCount() => MaxRTVCount;
|
||||
|
||||
public this(Windows.HWnd windowHandle)
|
||||
@@ -168,16 +173,39 @@ namespace GlitchyEngine.Renderer
|
||||
NativeContext.InputAssembler.SetVertexBuffers(slot, 1, &buffer.nativeBuffer, &stride, &offset);
|
||||
}
|
||||
|
||||
[Inline]
|
||||
private void BindInputLayout()
|
||||
{
|
||||
if (_currentInputLayout == null)
|
||||
{
|
||||
_currentInputLayout = _currentVertexLayout.GetNativeVertexLayout(_currentVertexShader.nativeCode);
|
||||
_currentInputLayout.AddRef();
|
||||
|
||||
NativeContext.InputAssembler.SetInputLayout(_currentInputLayout);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Draw(uint32 vertexCount, uint32 startVertexIndex = 0)
|
||||
{
|
||||
BindInputLayout();
|
||||
|
||||
NativeContext.Draw(vertexCount, startVertexIndex);
|
||||
}
|
||||
|
||||
public override void DrawIndexed(uint32 indexCount, uint32 startIndexLocation = 0, int32 vertexOffset = 0)
|
||||
{
|
||||
BindInputLayout();
|
||||
|
||||
NativeContext.DrawIndexed(indexCount, startIndexLocation, vertexOffset);
|
||||
}
|
||||
|
||||
public override void DrawIndexedInstanced(uint32 indexCountPerInstance, uint32 instanceCount, uint32 startIndexLocation, int32 baseVertexLocation, uint32 startInstanceLocation)
|
||||
{
|
||||
BindInputLayout();
|
||||
|
||||
NativeContext.DrawIndexedInstanced(indexCountPerInstance, instanceCount, startIndexLocation, baseVertexLocation, startInstanceLocation);
|
||||
}
|
||||
|
||||
public override void SetIndexBuffer(Buffer buffer, IndexFormat indexFormat = .Index16Bit, uint32 byteOffset = 0)
|
||||
{
|
||||
NativeContext.InputAssembler.SetIndexBuffer(buffer.nativeBuffer, indexFormat == .Index32Bit ? .R32_UInt : .R16_UInt, byteOffset);
|
||||
@@ -190,7 +218,12 @@ namespace GlitchyEngine.Renderer
|
||||
|
||||
public override void SetVertexLayout(VertexLayout vertexLayout)
|
||||
{
|
||||
NativeContext.InputAssembler.SetInputLayout(vertexLayout.nativeLayout);
|
||||
if (_currentVertexLayout != vertexLayout)
|
||||
{
|
||||
SetReference!(_currentVertexLayout, vertexLayout);
|
||||
_currentInputLayout?.Release();
|
||||
_currentInputLayout = null;
|
||||
}
|
||||
}
|
||||
|
||||
public override void SetPrimitiveTopology(GlitchyEngine.Renderer.PrimitiveTopology primitiveTopology)
|
||||
@@ -252,7 +285,7 @@ namespace GlitchyEngine.Renderer
|
||||
}
|
||||
|
||||
shader.Buffers.PlatformFetchNativeBuffers();
|
||||
|
||||
|
||||
switch(typeof(TShader))
|
||||
{
|
||||
// TODO: Add remaining shader stages
|
||||
@@ -262,6 +295,14 @@ namespace GlitchyEngine.Renderer
|
||||
case typeof(VertexShader):
|
||||
NativeContext.VertexShader.SetConstantBuffers(0, shader.Buffers.nativeBuffers.Count, &shader.Buffers.nativeBuffers);
|
||||
NativeContext.VertexShader.SetShader((ID3D11VertexShader*)shader.nativeShader);
|
||||
|
||||
if (VertexShader vs = shader as VertexShader)
|
||||
{
|
||||
SetReference!(_currentVertexShader, vs);
|
||||
_currentInputLayout?.Release();
|
||||
_currentInputLayout = null;
|
||||
}
|
||||
|
||||
default:
|
||||
Runtime.FatalError(scope $"Shader stage \"{typeof(TShader)}\" not implemented.");
|
||||
}
|
||||
|
||||
@@ -216,7 +216,7 @@ namespace GlitchyEngine.Renderer
|
||||
{
|
||||
Debug.Profiler.ProfileRendererFunction!();
|
||||
|
||||
NativeContext.DrawIndexedInstanced(geometry.IndexCount, geometry.InstanceCount, geometry.IndexByteOffset, 0, 0);
|
||||
_context.DrawIndexedInstanced(geometry.IndexCount, geometry.InstanceCount, geometry.IndexByteOffset, 0, 0);
|
||||
}
|
||||
|
||||
public override void SetViewport(Viewport viewport)
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Diagnostics;
|
||||
using DirectX.Common;
|
||||
using DirectX.D3D11;
|
||||
using GlitchyEngine.Platform.DX11;
|
||||
using System.Collections;
|
||||
|
||||
using internal GlitchyEngine.Renderer;
|
||||
using internal GlitchyEngine.Platform.DX11;
|
||||
@@ -13,19 +14,19 @@ namespace GlitchyEngine.Renderer
|
||||
{
|
||||
public extension VertexLayout
|
||||
{
|
||||
internal ID3D11InputLayout* nativeLayout ~ _?.Release();
|
||||
private Dictionary<ID3DBlob*, ID3D11InputLayout*> _validatedShaders = new .() ~
|
||||
{
|
||||
if (_ != null)
|
||||
{
|
||||
for (let entry in _)
|
||||
{
|
||||
entry.key.Release();
|
||||
entry.value.Release();
|
||||
}
|
||||
|
||||
public ID3DBlob* nativeShaderCode ~ _?.Release();
|
||||
|
||||
public this(VertexElement[] elements, bool ownsElements, VertexShader vertexShader)
|
||||
{
|
||||
nativeShaderCode = vertexShader.nativeCode..AddRef();
|
||||
|
||||
_elements = elements;
|
||||
_ownsElements = ownsElements;
|
||||
|
||||
CreateNativeLayout();
|
||||
}
|
||||
delete _;
|
||||
}
|
||||
};
|
||||
|
||||
private void ToNativeLayout(VertexElement[] input, InputElementDescription[] output)
|
||||
{
|
||||
@@ -35,19 +36,30 @@ namespace GlitchyEngine.Renderer
|
||||
output[i] = .(input[i].SemanticName, input[i].SemanticIndex, input[i].Format, input[i].InputSlot, input[i].AlignedByteOffset, (.)input[i].InputSlotClass, input[i].InstanceDataStepRate);
|
||||
}
|
||||
|
||||
protected override void CreateNativeLayout()
|
||||
/// Validates or gets the validated input layout for the given vertexshader.
|
||||
internal ID3D11InputLayout* GetNativeVertexLayout(ID3DBlob* vertexShaderCode)
|
||||
{
|
||||
Debug.Profiler.ProfileResourceFunction!();
|
||||
|
||||
var nativeElements = scope InputElementDescription[_elements.Count];
|
||||
ID3D11InputLayout* layout = null;
|
||||
|
||||
ToNativeLayout(_elements, nativeElements);
|
||||
|
||||
var result = NativeDevice.CreateInputLayout(nativeElements.CArray(), (.)nativeElements.Count, nativeShaderCode.GetBufferPointer(), nativeShaderCode.GetBufferSize(), &nativeLayout);
|
||||
if(result.Failed)
|
||||
if (!_validatedShaders.TryGetValue(vertexShaderCode, out layout))
|
||||
{
|
||||
Log.EngineLogger.Error($"Failed to create D3D11 input layout: Message({(int)result}): {result}");
|
||||
var nativeElements = scope InputElementDescription[_elements.Count];
|
||||
|
||||
ToNativeLayout(_elements, nativeElements);
|
||||
|
||||
var result = NativeDevice.CreateInputLayout(nativeElements.CArray(), (.)nativeElements.Count, vertexShaderCode.GetBufferPointer(), vertexShaderCode.GetBufferSize(), &layout);
|
||||
if(result.Failed)
|
||||
{
|
||||
Log.EngineLogger.Error($"Failed to create D3D11 input layout: Message({(int)result}): {result}");
|
||||
Debug.FatalError();
|
||||
}
|
||||
|
||||
_validatedShaders[vertexShaderCode..AddRef()] = layout;
|
||||
}
|
||||
|
||||
return layout;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user