mirror of
https://github.com/aharabada/glitchy-engine-beef.git
synced 2026-09-05 13:01:52 +00:00
DX11: Automatically validate input layouts against vertex shaders
This commit is contained in:
@@ -12,7 +12,7 @@ namespace GlitchyEngine.Content
|
||||
{
|
||||
static readonly Matrix RightToLeftHand = .Scaling(1, 1, -1);
|
||||
|
||||
public static EcsEntity LoadModel(String filename, Effect validationEffect, Material material, EcsWorld world,
|
||||
public static EcsEntity LoadModel(String filename, Material material, EcsWorld world,
|
||||
List<AnimationClip> outClips, StringView entityName = StringView())
|
||||
{
|
||||
CGLTF.Options options = .();
|
||||
@@ -29,7 +29,7 @@ namespace GlitchyEngine.Content
|
||||
|
||||
for(var node in data.Scenes[0].Nodes)
|
||||
{
|
||||
NodesToEntities(data, node, entity, world, validationEffect, material, outClips);
|
||||
NodesToEntities(data, node, entity, world, material, outClips);
|
||||
}
|
||||
|
||||
CGLTF.Free(data);
|
||||
@@ -63,7 +63,7 @@ namespace GlitchyEngine.Content
|
||||
return (entity, childTransform);
|
||||
}
|
||||
|
||||
private static void NodesToEntities(CGLTF.Data* data, CGLTF.Node* node, EcsEntity parentEntity, EcsWorld world, Effect validationEffect, Material material, List<AnimationClip> clips)
|
||||
private static void NodesToEntities(CGLTF.Data* data, CGLTF.Node* node, EcsEntity parentEntity, EcsWorld world, Material material, List<AnimationClip> clips)
|
||||
{
|
||||
(EcsEntity entity, TransformComponent* childTransform) = CreateEntity(world, node.Name == null ? null : StringView(node.Name), parentEntity);
|
||||
|
||||
@@ -109,7 +109,7 @@ namespace GlitchyEngine.Content
|
||||
{
|
||||
var mesh = world.AssignComponent<MeshComponent>(entity);
|
||||
|
||||
using (var geo = PrimitiveToGeoBinding(node.Mesh.Primitives[0], validationEffect))
|
||||
using (var geo = PrimitiveToGeoBinding(node.Mesh.Primitives[0]))
|
||||
{
|
||||
mesh.Mesh = geo;
|
||||
}
|
||||
@@ -137,7 +137,7 @@ namespace GlitchyEngine.Content
|
||||
meshParent.Entity = entity;
|
||||
|
||||
var mesh = world.AssignComponent<MeshComponent>(meshEntity);
|
||||
mesh.Mesh = PrimitiveToGeoBinding(primitive, validationEffect);
|
||||
mesh.Mesh = PrimitiveToGeoBinding(primitive);
|
||||
|
||||
if(skeleton == null)
|
||||
{
|
||||
@@ -158,11 +158,11 @@ namespace GlitchyEngine.Content
|
||||
|
||||
for(var child in node.Children)
|
||||
{
|
||||
NodesToEntities(data, child, entity, world, validationEffect, material, clips);
|
||||
NodesToEntities(data, child, entity, world, material, clips);
|
||||
}
|
||||
}
|
||||
|
||||
public static GeometryBinding PrimitiveToGeoBinding(CGLTF.Primitive primitive, Effect validationEffect)
|
||||
public static GeometryBinding PrimitiveToGeoBinding(CGLTF.Primitive primitive)
|
||||
{
|
||||
GeometryBinding binding = new GeometryBinding();
|
||||
|
||||
@@ -327,7 +327,7 @@ namespace GlitchyEngine.Content
|
||||
vertexElements[i] = elements[i];
|
||||
}
|
||||
|
||||
VertexLayout layout = new VertexLayout(vertexElements, true, validationEffect.VertexShader);
|
||||
VertexLayout layout = new VertexLayout(vertexElements, true);
|
||||
binding.SetVertexLayout(layout..ReleaseRefNoDelete());
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,6 +79,8 @@ namespace GlitchyEngine.Renderer
|
||||
public extern void Draw(uint32 vertexCount, uint32 startVertexIndex = 0);
|
||||
|
||||
public extern void DrawIndexed(uint32 indexCount, uint32 startIndexLocation = 0, int32 vertexOffset = 0);
|
||||
|
||||
public extern void DrawIndexedInstanced(uint32 indexCountPerInstance, uint32 instanceCount, uint32 startIndexLocation, int32 baseVertexLocation, uint32 startInstanceLocation);
|
||||
|
||||
public void SetIndexBuffer(IndexBuffer indexBuffer, uint32 byteOffset = 0)
|
||||
{
|
||||
|
||||
@@ -210,7 +210,7 @@ namespace GlitchyEngine.Renderer
|
||||
|
||||
VertexElement[] vertexElements = new VertexElement[1];
|
||||
vertexElements[0] = .(.R32G32B32_Float, "POSITION");
|
||||
VertexLayout layout = new VertexLayout(vertexElements, true, LineEffect.VertexShader);
|
||||
VertexLayout layout = new VertexLayout(vertexElements, true);
|
||||
LineGeometry.SetVertexLayout(layout..ReleaseRefNoDelete());
|
||||
}
|
||||
|
||||
@@ -258,7 +258,7 @@ namespace GlitchyEngine.Renderer
|
||||
VertexElement(.R32G32_Float, "TEXCOORD")
|
||||
);
|
||||
|
||||
using (var quadBatchLayout = new VertexLayout(vertexElements, true, TestFullscreenEffect.VertexShader))
|
||||
using (var quadBatchLayout = new VertexLayout(vertexElements, true))
|
||||
{
|
||||
s_fullscreenQuadGeometry.SetVertexLayout(quadBatchLayout);
|
||||
}
|
||||
|
||||
@@ -184,7 +184,7 @@ namespace GlitchyEngine.Renderer
|
||||
0, 1, 2,
|
||||
2, 3, 0
|
||||
);
|
||||
|
||||
|
||||
quadIndices.SetData(indices);
|
||||
s_quadGeometry.SetIndexBuffer(quadIndices);
|
||||
}
|
||||
@@ -211,7 +211,7 @@ namespace GlitchyEngine.Renderer
|
||||
s_quadBatchBinding = new GeometryBinding();
|
||||
s_quadBatchBinding.SetPrimitiveTopology(.TriangleList);
|
||||
|
||||
using (var quadBatchLayout = new VertexLayout(vertexElements, true, s_batchEffect.VertexShader))
|
||||
using (var quadBatchLayout = new VertexLayout(vertexElements, true))
|
||||
{
|
||||
s_quadBatchBinding.SetVertexLayout(quadBatchLayout);
|
||||
}
|
||||
@@ -238,7 +238,7 @@ namespace GlitchyEngine.Renderer
|
||||
s_circleBatchBinding = new GeometryBinding();
|
||||
s_circleBatchBinding.SetPrimitiveTopology(.TriangleList);
|
||||
|
||||
using (var circleBatchLayout = new VertexLayout(vertexElements, true, s_circleBatchEffect.VertexShader))
|
||||
using (var circleBatchLayout = new VertexLayout(vertexElements, true))
|
||||
{
|
||||
s_circleBatchBinding.SetVertexLayout(circleBatchLayout);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ using GlitchyEngine.Core;
|
||||
|
||||
namespace GlitchyEngine.Renderer
|
||||
{
|
||||
|
||||
/**
|
||||
* Type of data contained in an input slot.
|
||||
*/
|
||||
@@ -86,6 +85,12 @@ namespace GlitchyEngine.Renderer
|
||||
|
||||
public VertexElement[] Elements => _elements;
|
||||
|
||||
public this(VertexElement[] elements, bool ownsElements)
|
||||
{
|
||||
_elements = elements;
|
||||
_ownsElements = ownsElements;
|
||||
}
|
||||
|
||||
public ~this()
|
||||
{
|
||||
if(_ownsElements)
|
||||
@@ -99,8 +104,6 @@ namespace GlitchyEngine.Renderer
|
||||
delete _elements;
|
||||
}
|
||||
}
|
||||
|
||||
protected extern void CreateNativeLayout();
|
||||
}
|
||||
|
||||
public interface IVertexData
|
||||
|
||||
Reference in New Issue
Block a user