Add vertex shader input layout reading via shader compiler reflection to handle missing vertex elements binding when explicit layout got deprecated

This commit is contained in:
Wojtek Figat
2025-01-07 23:26:06 +01:00
parent 7f0d852f49
commit 7aa240e5eb
20 changed files with 350 additions and 232 deletions

View File

@@ -16,11 +16,9 @@
class IncludeD3D : public ID3DInclude
{
private:
ShaderCompilationContext* _context;
public:
IncludeD3D(ShaderCompilationContext* context)
{
_context = context;
@@ -84,14 +82,9 @@ namespace
// Extract constant buffers usage information
for (uint32 a = 0; a < desc.ConstantBuffers; a++)
{
// Get CB
auto cb = reflector->GetConstantBufferByIndex(a);
// Get CB description
D3D11_SHADER_BUFFER_DESC cbDesc;
cb->GetDesc(&cbDesc);
// Check buffer type
if (cbDesc.Type == D3D_CT_CBUFFER)
{
// Find CB slot index
@@ -132,22 +125,20 @@ namespace
// Extract resources usage
for (uint32 i = 0; i < desc.BoundResources; i++)
{
// Get resource description
D3D11_SHADER_INPUT_BIND_DESC resDesc;
reflector->GetResourceBindingDesc(i, &resDesc);
switch (resDesc.Type)
{
// Sampler
// Sampler
case D3D_SIT_SAMPLER:
break;
// Constant Buffer
// Constant Buffer
case D3D_SIT_CBUFFER:
case D3D_SIT_TBUFFER:
break;
// Shader Resource
// Shader Resource
case D3D_SIT_TEXTURE:
case D3D_SIT_STRUCTURED:
case D3D_SIT_BYTEADDRESS:
@@ -155,7 +146,7 @@ namespace
bindings.UsedSRsMask |= 1 << (resDesc.BindPoint + shift);
break;
// Unordered Access
// Unordered Access
case D3D_SIT_UAV_RWTYPED:
case D3D_SIT_UAV_RWSTRUCTURED:
case D3D_SIT_UAV_RWBYTEADDRESS:
@@ -212,7 +203,6 @@ bool ShaderCompilerD3D::CompileShader(ShaderFunctionMeta& meta, WritePermutation
else
{
profileName += "_4_0";
if (type == ShaderStage::Domain || type == ShaderStage::Hull)
{
_context->OnError("Tessellation is not supported on DirectX 10");
@@ -221,6 +211,7 @@ bool ShaderCompilerD3D::CompileShader(ShaderFunctionMeta& meta, WritePermutation
}
// Compile all shader function permutations
AdditionalDataVS additionalDataVS;
for (int32 permutationIndex = 0; permutationIndex < meta.Permutations.Count(); permutationIndex++)
{
_macros.Clear();
@@ -253,8 +244,6 @@ bool ShaderCompilerD3D::CompileShader(ShaderFunctionMeta& meta, WritePermutation
0,
&shader,
&errors);
// Check compilation result
if (FAILED(result))
{
const auto msg = static_cast<const char*>(errors->GetBufferPointer());
@@ -279,24 +268,68 @@ bool ShaderCompilerD3D::CompileShader(ShaderFunctionMeta& meta, WritePermutation
reflector->GetDesc(&desc);
// Process shader reflection data
void* additionalData = nullptr;
if (type == ShaderStage::Vertex)
{
additionalData = &additionalDataVS;
additionalDataVS.Inputs.Clear();
for (UINT inputIdx = 0; inputIdx < desc.InputParameters; inputIdx++)
{
D3D11_SIGNATURE_PARAMETER_DESC inputDesc;
reflector->GetInputParameterDesc(inputIdx, &inputDesc);
if (inputDesc.ReadWriteMask == 0 || inputDesc.SystemValueType != D3D10_NAME_UNDEFINED)
continue;
auto format = PixelFormat::Unknown;
switch (inputDesc.ComponentType)
{
case D3D_REGISTER_COMPONENT_UINT32:
if (inputDesc.Mask >= 0b1111)
format = PixelFormat::R32G32B32A32_UInt;
else if (inputDesc.Mask >= 0b111)
format = PixelFormat::R32G32B32_UInt;
else if (inputDesc.Mask >= 0b11)
format = PixelFormat::R32G32_UInt;
else
format = PixelFormat::R32_UInt;
break;
case D3D_REGISTER_COMPONENT_SINT32:
if (inputDesc.Mask >= 0b1111)
format = PixelFormat::R32G32B32A32_SInt;
else if (inputDesc.Mask >= 0b111)
format = PixelFormat::R32G32B32_SInt;
else if (inputDesc.Mask >= 0b11)
format = PixelFormat::R32G32_SInt;
else
format = PixelFormat::R32_SInt;
break;
case D3D_REGISTER_COMPONENT_FLOAT32:
if (inputDesc.Mask >= 0b1111)
format = PixelFormat::R32G32B32A32_Float;
else if (inputDesc.Mask >= 0b111)
format = PixelFormat::R32G32B32_Float;
else if (inputDesc.Mask >= 0b11)
format = PixelFormat::R32G32_Float;
else
format = PixelFormat::R32_Float;
break;
}
additionalDataVS.Inputs.Add({ ParseVertexElementType(inputDesc.SemanticName, inputDesc.SemanticIndex), 0, 0, 0, format });
}
}
ShaderBindings bindings = { desc.InstructionCount, 0, 0, 0 };
if (ProcessShader(_context, _constantBuffers, reflector.Get(), desc, bindings))
return true;
#ifdef GPU_USE_SHADERS_DEBUG_LAYER
// Generate debug information
if (ProcessDebugInfo(_context, meta, permutationIndex, shaderBuffer, shaderBufferSize))
return true;
#endif
// Strip shader bytecode for an optimization
ComPtr<ID3DBlob> shaderStripped;
if (!options->GenerateDebugData)
{
//auto prevShaderBufferSize = shaderBufferSize;
// Strip shader bytes
result = D3DStripShader(
shaderBuffer,
@@ -312,15 +345,12 @@ bool ShaderCompilerD3D::CompileShader(ShaderFunctionMeta& meta, WritePermutation
// Set new buffer
shaderBuffer = shaderStripped->GetBufferPointer();
shaderBufferSize = static_cast<int32>(shaderStripped->GetBufferSize());
//auto strippedBytes = prevShaderBufferSize - shaderBufferSize;
//auto strippedBytesPercentage = Math::FloorToInt(strippedBytes * 100.0f / prevShaderBufferSize);
}
if (WriteShaderFunctionPermutation(_context, meta, permutationIndex, bindings, shaderBuffer, shaderBufferSize))
return true;
if (customDataWrite && customDataWrite(_context, meta, permutationIndex, _macros))
if (customDataWrite && customDataWrite(_context, meta, permutationIndex, _macros, additionalData))
return true;
}

View File

@@ -12,12 +12,10 @@
class ShaderCompilerD3D : public ShaderCompiler
{
private:
Array<char> _funcNameDefineBuffer;
uint32 _flags;
public:
/// <summary>
/// Initializes a new instance of the <see cref="ShaderCompilerD3D"/> class.
/// </summary>
@@ -25,7 +23,6 @@ public:
ShaderCompilerD3D(ShaderProfile profile);
protected:
// [ShaderCompiler]
bool CompileShader(ShaderFunctionMeta& meta, WritePermutationData customDataWrite = nullptr) override;
bool OnCompileBegin() override;

View File

@@ -4,7 +4,6 @@
#include "ShaderCompilerDX.h"
#include "Engine/Core/Log.h"
#include "Engine/Threading/Threading.h"
#include "Engine/Engine/Globals.h"
#include "Engine/Graphics/Config.h"
#include "Engine/GraphicsDevice/DirectX/DX12/Types.h"
@@ -22,12 +21,10 @@
class IncludeDX : public IDxcIncludeHandler
{
private:
ShaderCompilationContext* _context;
IDxcLibrary* _library;
public:
IncludeDX(ShaderCompilationContext* context, IDxcLibrary* library)
{
_context = context;
@@ -185,6 +182,7 @@ bool ShaderCompilerDX::CompileShader(ShaderFunctionMeta& meta, WritePermutationD
}
// Compile all shader function permutations
AdditionalDataVS additionalDataVS;
for (int32 permutationIndex = 0; permutationIndex < meta.Permutations.Count(); permutationIndex++)
{
_macros.Clear();
@@ -320,6 +318,54 @@ bool ShaderCompilerDX::CompileShader(ShaderFunctionMeta& meta, WritePermutationD
shaderReflection->GetDesc(&desc);
// Process shader reflection data
void* additionalData = nullptr;
if (type == ShaderStage::Vertex)
{
additionalData = &additionalDataVS;
additionalDataVS.Inputs.Clear();
for (UINT inputIdx = 0; inputIdx < desc.InputParameters; inputIdx++)
{
D3D12_SIGNATURE_PARAMETER_DESC inputDesc;
shaderReflection->GetInputParameterDesc(inputIdx, &inputDesc);
if (inputDesc.ReadWriteMask == 0 || inputDesc.SystemValueType != D3D10_NAME_UNDEFINED)
continue;
auto format = PixelFormat::Unknown;
switch (inputDesc.ComponentType)
{
case D3D_REGISTER_COMPONENT_UINT32:
if (inputDesc.Mask >= 0b1111)
format = PixelFormat::R32G32B32A32_UInt;
else if (inputDesc.Mask >= 0b111)
format = PixelFormat::R32G32B32_UInt;
else if (inputDesc.Mask >= 0b11)
format = PixelFormat::R32G32_UInt;
else
format = PixelFormat::R32_UInt;
break;
case D3D_REGISTER_COMPONENT_SINT32:
if (inputDesc.Mask >= 0b1111)
format = PixelFormat::R32G32B32A32_SInt;
else if (inputDesc.Mask >= 0b111)
format = PixelFormat::R32G32B32_SInt;
else if (inputDesc.Mask >= 0b11)
format = PixelFormat::R32G32_SInt;
else
format = PixelFormat::R32_SInt;
break;
case D3D_REGISTER_COMPONENT_FLOAT32:
if (inputDesc.Mask >= 0b1111)
format = PixelFormat::R32G32B32A32_Float;
else if (inputDesc.Mask >= 0b111)
format = PixelFormat::R32G32B32_Float;
else if (inputDesc.Mask >= 0b11)
format = PixelFormat::R32G32_Float;
else
format = PixelFormat::R32_Float;
break;
}
additionalDataVS.Inputs.Add({ ParseVertexElementType(inputDesc.SemanticName, inputDesc.SemanticIndex), 0, 0, 0, format });
}
}
DxShaderHeader header;
Platform::MemoryClear(&header, sizeof(header));
ShaderBindings bindings = { desc.InstructionCount, 0, 0, 0 };
@@ -370,16 +416,16 @@ bool ShaderCompilerDX::CompileShader(ShaderFunctionMeta& meta, WritePermutationD
shaderReflection->GetResourceBindingDesc(i, &resDesc);
switch (resDesc.Type)
{
// Sampler
// Sampler
case D3D_SIT_SAMPLER:
break;
// Constant Buffer
// Constant Buffer
case D3D_SIT_CBUFFER:
case D3D_SIT_TBUFFER:
break;
// Shader Resource
// Shader Resource
case D3D_SIT_TEXTURE:
for (UINT shift = 0; shift < resDesc.BindCount; shift++)
{
@@ -396,7 +442,7 @@ bool ShaderCompilerDX::CompileShader(ShaderFunctionMeta& meta, WritePermutationD
}
break;
// Unordered Access
// Unordered Access
case D3D_SIT_UAV_RWTYPED:
case D3D_SIT_UAV_RWSTRUCTURED:
case D3D_SIT_UAV_RWBYTEADDRESS:
@@ -415,7 +461,7 @@ bool ShaderCompilerDX::CompileShader(ShaderFunctionMeta& meta, WritePermutationD
if (WriteShaderFunctionPermutation(_context, meta, permutationIndex, bindings, &header, sizeof(header), shaderBuffer->GetBufferPointer(), (int32)shaderBuffer->GetBufferSize()))
return true;
if (customDataWrite && customDataWrite(_context, meta, permutationIndex, _macros))
if (customDataWrite && customDataWrite(_context, meta, permutationIndex, _macros, additionalData))
return true;
}

View File

@@ -12,14 +12,12 @@
class ShaderCompilerDX : public ShaderCompiler
{
private:
Array<char> _funcNameDefineBuffer;
void* _compiler;
void* _library;
void* _containerReflection;
public:
/// <summary>
/// Initializes a new instance of the <see cref="ShaderCompilerDX"/> class.
/// </summary>
@@ -32,7 +30,6 @@ public:
~ShaderCompilerDX();
protected:
// [ShaderCompiler]
bool CompileShader(ShaderFunctionMeta& meta, WritePermutationData customDataWrite = nullptr) override;
bool OnCompileBegin() override;