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:
@@ -177,22 +177,28 @@ GPUShaderProgram* GPUShader::GetShader(ShaderStage stage, const StringAnsiView&
|
|||||||
return shader;
|
return shader;
|
||||||
}
|
}
|
||||||
|
|
||||||
GPUVertexLayout* GPUShader::ReadVertexLayout(MemoryReadStream& stream)
|
void GPUShader::ReadVertexLayout(MemoryReadStream& stream, GPUVertexLayout*& inputLayout, GPUVertexLayout*& vertexLayout)
|
||||||
{
|
{
|
||||||
|
inputLayout = vertexLayout = nullptr;
|
||||||
|
|
||||||
|
// Read input layout (based on shader reflection)
|
||||||
|
GPUVertexLayout::Elements elements;
|
||||||
|
stream.Read(elements);
|
||||||
|
inputLayout = GPUVertexLayout::Get(elements);
|
||||||
|
|
||||||
// [Deprecated in v1.10]
|
// [Deprecated in v1.10]
|
||||||
byte inputLayoutSize;
|
byte inputLayoutSize;
|
||||||
stream.ReadByte(&inputLayoutSize);
|
stream.ReadByte(&inputLayoutSize);
|
||||||
if (inputLayoutSize == 0)
|
if (inputLayoutSize == 0)
|
||||||
return nullptr;
|
return;
|
||||||
void* elementsData = stream.Move(sizeof(VertexElement) * inputLayoutSize);
|
void* elementsData = stream.Move(sizeof(VertexElement) * inputLayoutSize);
|
||||||
if (inputLayoutSize > GPU_MAX_VS_ELEMENTS)
|
if (inputLayoutSize > GPU_MAX_VS_ELEMENTS)
|
||||||
{
|
{
|
||||||
LOG(Error, "Incorrect input layout size.");
|
LOG(Error, "Incorrect input layout size.");
|
||||||
return nullptr;
|
return;
|
||||||
}
|
}
|
||||||
GPUVertexLayout::Elements elements;
|
|
||||||
elements.Set((VertexElement*)elementsData, inputLayoutSize);
|
elements.Set((VertexElement*)elementsData, inputLayoutSize);
|
||||||
return GPUVertexLayout::Get(elements);
|
vertexLayout = GPUVertexLayout::Get(elements);
|
||||||
}
|
}
|
||||||
|
|
||||||
GPUResourceType GPUShader::GetResourceType() const
|
GPUResourceType GPUShader::GetResourceType() const
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ class GPUShaderProgram;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The runtime version of the shaders cache supported by the all graphics back-ends. The same for all the shader cache formats (easier to sync and validate).
|
/// The runtime version of the shaders cache supported by the all graphics back-ends. The same for all the shader cache formats (easier to sync and validate).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
#define GPU_SHADER_CACHE_VERSION 11
|
#define GPU_SHADER_CACHE_VERSION 12
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The GPU resource with shader programs that can run on the GPU and are able to perform rendering calculation using textures, vertices and other resources.
|
/// The GPU resource with shader programs that can run on the GPU and are able to perform rendering calculation using textures, vertices and other resources.
|
||||||
@@ -135,7 +135,7 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
GPUShaderProgram* GetShader(ShaderStage stage, const StringAnsiView& name, int32 permutationIndex) const;
|
GPUShaderProgram* GetShader(ShaderStage stage, const StringAnsiView& name, int32 permutationIndex) const;
|
||||||
virtual GPUShaderProgram* CreateGPUShaderProgram(ShaderStage type, const GPUShaderProgramInitializer& initializer, Span<byte> bytecode, MemoryReadStream& stream) = 0;
|
virtual GPUShaderProgram* CreateGPUShaderProgram(ShaderStage type, const GPUShaderProgramInitializer& initializer, Span<byte> bytecode, MemoryReadStream& stream) = 0;
|
||||||
static GPUVertexLayout* ReadVertexLayout(MemoryReadStream& stream);
|
static void ReadVertexLayout(MemoryReadStream& stream, GPUVertexLayout*& inputLayout, GPUVertexLayout*& vertexLayout);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// [GPUResource]
|
// [GPUResource]
|
||||||
|
|||||||
@@ -136,6 +136,9 @@ public:
|
|||||||
// [Deprecated in v1.10]
|
// [Deprecated in v1.10]
|
||||||
GPUVertexLayout* Layout = nullptr;
|
GPUVertexLayout* Layout = nullptr;
|
||||||
|
|
||||||
|
// Vertex shader inputs layout. Used to ensure that binded vertex buffers provide all required elements.
|
||||||
|
GPUVertexLayout* InputLayout = nullptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// [GPUShaderProgram]
|
// [GPUShaderProgram]
|
||||||
ShaderStage GetStage() const override
|
ShaderStage GetStage() const override
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ ID3D11InputLayout* GPUShaderProgramVSDX11::GetInputLayout(GPUVertexLayoutDX11* v
|
|||||||
{
|
{
|
||||||
if (vertexLayout && vertexLayout->InputElementsCount)
|
if (vertexLayout && vertexLayout->InputElementsCount)
|
||||||
{
|
{
|
||||||
auto mergedVertexLayout = (GPUVertexLayoutDX11*)GPUVertexLayout::Merge(vertexLayout, Layout);
|
auto mergedVertexLayout = (GPUVertexLayoutDX11*)GPUVertexLayout::Merge(vertexLayout, Layout ? Layout : InputLayout);
|
||||||
LOG_DIRECTX_RESULT(vertexLayout->GetDevice()->GetDevice()->CreateInputLayout(mergedVertexLayout->InputElements, mergedVertexLayout->InputElementsCount, Bytecode.Get(), Bytecode.Length(), &inputLayout));
|
LOG_DIRECTX_RESULT(vertexLayout->GetDevice()->GetDevice()->CreateInputLayout(mergedVertexLayout->InputElements, mergedVertexLayout->InputElementsCount, Bytecode.Get(), Bytecode.Length(), &inputLayout));
|
||||||
}
|
}
|
||||||
_cache.Add(vertexLayout, inputLayout);
|
_cache.Add(vertexLayout, inputLayout);
|
||||||
@@ -42,42 +42,30 @@ GPUShaderProgram* GPUShaderDX11::CreateGPUShaderProgram(ShaderStage type, const
|
|||||||
{
|
{
|
||||||
case ShaderStage::Vertex:
|
case ShaderStage::Vertex:
|
||||||
{
|
{
|
||||||
// Load Input Layout
|
GPUVertexLayout* inputLayout, *vertexLayout;
|
||||||
GPUVertexLayout* vertexLayout = ReadVertexLayout(stream);
|
ReadVertexLayout(stream, inputLayout, vertexLayout);
|
||||||
|
|
||||||
// Create shader
|
|
||||||
ID3D11VertexShader* buffer = nullptr;
|
ID3D11VertexShader* buffer = nullptr;
|
||||||
result = _device->GetDevice()->CreateVertexShader(bytecode.Get(), bytecode.Length(), nullptr, &buffer);
|
result = _device->GetDevice()->CreateVertexShader(bytecode.Get(), bytecode.Length(), nullptr, &buffer);
|
||||||
LOG_DIRECTX_RESULT_WITH_RETURN(result, nullptr);
|
LOG_DIRECTX_RESULT_WITH_RETURN(result, nullptr);
|
||||||
|
shader = New<GPUShaderProgramVSDX11>(initializer, buffer, inputLayout, vertexLayout, bytecode);
|
||||||
// Create object
|
|
||||||
shader = New<GPUShaderProgramVSDX11>(initializer, buffer, vertexLayout, bytecode);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#if GPU_ALLOW_TESSELLATION_SHADERS
|
#if GPU_ALLOW_TESSELLATION_SHADERS
|
||||||
case ShaderStage::Hull:
|
case ShaderStage::Hull:
|
||||||
{
|
{
|
||||||
// Read control points
|
|
||||||
int32 controlPointsCount;
|
int32 controlPointsCount;
|
||||||
stream.ReadInt32(&controlPointsCount);
|
stream.ReadInt32(&controlPointsCount);
|
||||||
|
|
||||||
// Create shader
|
|
||||||
ID3D11HullShader* buffer = nullptr;
|
ID3D11HullShader* buffer = nullptr;
|
||||||
result = _device->GetDevice()->CreateHullShader(bytecode.Get(), bytecode.Length(), nullptr, &buffer);
|
result = _device->GetDevice()->CreateHullShader(bytecode.Get(), bytecode.Length(), nullptr, &buffer);
|
||||||
LOG_DIRECTX_RESULT_WITH_RETURN(result, nullptr);
|
LOG_DIRECTX_RESULT_WITH_RETURN(result, nullptr);
|
||||||
|
|
||||||
// Create object
|
|
||||||
shader = New<GPUShaderProgramHSDX11>(initializer, buffer, controlPointsCount);
|
shader = New<GPUShaderProgramHSDX11>(initializer, buffer, controlPointsCount);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ShaderStage::Domain:
|
case ShaderStage::Domain:
|
||||||
{
|
{
|
||||||
// Create shader
|
|
||||||
ID3D11DomainShader* buffer = nullptr;
|
ID3D11DomainShader* buffer = nullptr;
|
||||||
result = _device->GetDevice()->CreateDomainShader(bytecode.Get(), bytecode.Length(), nullptr, &buffer);
|
result = _device->GetDevice()->CreateDomainShader(bytecode.Get(), bytecode.Length(), nullptr, &buffer);
|
||||||
LOG_DIRECTX_RESULT_WITH_RETURN(result, nullptr);
|
LOG_DIRECTX_RESULT_WITH_RETURN(result, nullptr);
|
||||||
|
|
||||||
// Create object
|
|
||||||
shader = New<GPUShaderProgramDSDX11>(initializer, buffer);
|
shader = New<GPUShaderProgramDSDX11>(initializer, buffer);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -92,35 +80,26 @@ GPUShaderProgram* GPUShaderDX11::CreateGPUShaderProgram(ShaderStage type, const
|
|||||||
#if GPU_ALLOW_GEOMETRY_SHADERS
|
#if GPU_ALLOW_GEOMETRY_SHADERS
|
||||||
case ShaderStage::Geometry:
|
case ShaderStage::Geometry:
|
||||||
{
|
{
|
||||||
// Create shader
|
|
||||||
ID3D11GeometryShader* buffer = nullptr;
|
ID3D11GeometryShader* buffer = nullptr;
|
||||||
result = _device->GetDevice()->CreateGeometryShader(bytecode.Get(), bytecode.Length(), nullptr, &buffer);
|
result = _device->GetDevice()->CreateGeometryShader(bytecode.Get(), bytecode.Length(), nullptr, &buffer);
|
||||||
LOG_DIRECTX_RESULT_WITH_RETURN(result, nullptr);
|
LOG_DIRECTX_RESULT_WITH_RETURN(result, nullptr);
|
||||||
|
|
||||||
// Create object
|
|
||||||
shader = New<GPUShaderProgramGSDX11>(initializer, buffer);
|
shader = New<GPUShaderProgramGSDX11>(initializer, buffer);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
case ShaderStage::Pixel:
|
case ShaderStage::Pixel:
|
||||||
{
|
{
|
||||||
// Create shader
|
|
||||||
ID3D11PixelShader* buffer = nullptr;
|
ID3D11PixelShader* buffer = nullptr;
|
||||||
result = _device->GetDevice()->CreatePixelShader(bytecode.Get(), bytecode.Length(), nullptr, &buffer);
|
result = _device->GetDevice()->CreatePixelShader(bytecode.Get(), bytecode.Length(), nullptr, &buffer);
|
||||||
LOG_DIRECTX_RESULT_WITH_RETURN(result, nullptr);
|
LOG_DIRECTX_RESULT_WITH_RETURN(result, nullptr);
|
||||||
|
|
||||||
// Create object
|
|
||||||
shader = New<GPUShaderProgramPSDX11>(initializer, buffer);
|
shader = New<GPUShaderProgramPSDX11>(initializer, buffer);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ShaderStage::Compute:
|
case ShaderStage::Compute:
|
||||||
{
|
{
|
||||||
// Create shader
|
|
||||||
ID3D11ComputeShader* buffer = nullptr;
|
ID3D11ComputeShader* buffer = nullptr;
|
||||||
result = _device->GetDevice()->CreateComputeShader(bytecode.Get(), bytecode.Length(), nullptr, &buffer);
|
result = _device->GetDevice()->CreateComputeShader(bytecode.Get(), bytecode.Length(), nullptr, &buffer);
|
||||||
LOG_DIRECTX_RESULT_WITH_RETURN(result, nullptr);
|
LOG_DIRECTX_RESULT_WITH_RETURN(result, nullptr);
|
||||||
|
|
||||||
// Create object
|
|
||||||
shader = New<GPUShaderProgramCSDX11>(initializer, buffer);
|
shader = New<GPUShaderProgramCSDX11>(initializer, buffer);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,9 +58,10 @@ private:
|
|||||||
Dictionary<class GPUVertexLayoutDX11*, ID3D11InputLayout*> _cache;
|
Dictionary<class GPUVertexLayoutDX11*, ID3D11InputLayout*> _cache;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GPUShaderProgramVSDX11(const GPUShaderProgramInitializer& initializer, ID3D11VertexShader* buffer, GPUVertexLayout* vertexLayout, Span<byte> bytecode)
|
GPUShaderProgramVSDX11(const GPUShaderProgramInitializer& initializer, ID3D11VertexShader* buffer, GPUVertexLayout* inputLayout, GPUVertexLayout* vertexLayout, Span<byte> bytecode)
|
||||||
: GPUShaderProgramDX11(initializer, buffer)
|
: GPUShaderProgramDX11(initializer, buffer)
|
||||||
{
|
{
|
||||||
|
InputLayout = inputLayout;
|
||||||
Layout = vertexLayout;
|
Layout = vertexLayout;
|
||||||
Bytecode.Copy(bytecode);
|
Bytecode.Copy(bytecode);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ void DescriptorHeapWithSlotsDX12::ReleaseSlot(uint32 index)
|
|||||||
{
|
{
|
||||||
uint32& value = _usage[index / 32];
|
uint32& value = _usage[index / 32];
|
||||||
const uint32 mask = 1 << (index & 31);
|
const uint32 mask = 1 << (index & 31);
|
||||||
ASSERT_LOW_LAYER((value & mask) == mask);
|
//ASSERT_LOW_LAYER((value & mask) == mask);
|
||||||
value &= ~mask;
|
value &= ~mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ bool GPUPipelineStateDX12::Init(const Description& desc)
|
|||||||
INIT_SHADER_STAGE(PS, GPUShaderProgramPSDX12);
|
INIT_SHADER_STAGE(PS, GPUShaderProgramPSDX12);
|
||||||
|
|
||||||
// Input Assembly
|
// Input Assembly
|
||||||
VertexLayout = desc.VS ? (GPUVertexLayoutDX12*)desc.VS->Layout : nullptr;
|
VertexLayout = desc.VS ? (GPUVertexLayoutDX12*)(desc.VS->Layout ? desc.VS->Layout : desc.VS->InputLayout) : nullptr;
|
||||||
const D3D12_PRIMITIVE_TOPOLOGY_TYPE primTypes1[] =
|
const D3D12_PRIMITIVE_TOPOLOGY_TYPE primTypes1[] =
|
||||||
{
|
{
|
||||||
D3D12_PRIMITIVE_TOPOLOGY_TYPE_UNDEFINED,
|
D3D12_PRIMITIVE_TOPOLOGY_TYPE_UNDEFINED,
|
||||||
|
|||||||
@@ -19,8 +19,9 @@ GPUShaderProgram* GPUShaderDX12::CreateGPUShaderProgram(ShaderStage type, const
|
|||||||
{
|
{
|
||||||
case ShaderStage::Vertex:
|
case ShaderStage::Vertex:
|
||||||
{
|
{
|
||||||
GPUVertexLayout* vertexLayout = ReadVertexLayout(stream);
|
GPUVertexLayout* inputLayout, *vertexLayout;
|
||||||
shader = New<GPUShaderProgramVSDX12>(initializer, header, bytecode, vertexLayout);
|
ReadVertexLayout(stream, inputLayout, vertexLayout);
|
||||||
|
shader = New<GPUShaderProgramVSDX12>(initializer, header, bytecode, inputLayout, vertexLayout);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#if GPU_ALLOW_TESSELLATION_SHADERS
|
#if GPU_ALLOW_TESSELLATION_SHADERS
|
||||||
|
|||||||
@@ -46,9 +46,10 @@ public:
|
|||||||
class GPUShaderProgramVSDX12 : public GPUShaderProgramDX12<GPUShaderProgramVS>
|
class GPUShaderProgramVSDX12 : public GPUShaderProgramDX12<GPUShaderProgramVS>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GPUShaderProgramVSDX12(const GPUShaderProgramInitializer& initializer, const DxShaderHeader* header, Span<byte> bytecode, GPUVertexLayout* vertexLayout)
|
GPUShaderProgramVSDX12(const GPUShaderProgramInitializer& initializer, const DxShaderHeader* header, Span<byte> bytecode, GPUVertexLayout* inputLayout, GPUVertexLayout* vertexLayout)
|
||||||
: GPUShaderProgramDX12(initializer, header, bytecode)
|
: GPUShaderProgramDX12(initializer, header, bytecode)
|
||||||
{
|
{
|
||||||
|
InputLayout = inputLayout;
|
||||||
Layout = vertexLayout;
|
Layout = vertexLayout;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -320,7 +320,7 @@ bool GPUPipelineStateVulkan::Init(const Description& desc)
|
|||||||
_desc.pStages = _shaderStages;
|
_desc.pStages = _shaderStages;
|
||||||
|
|
||||||
// Input Assembly
|
// Input Assembly
|
||||||
VertexShaderLayout = desc.VS ? (GPUVertexLayoutVulkan*)desc.VS->Layout : nullptr;
|
VertexShaderLayout = desc.VS ? (GPUVertexLayoutVulkan*)(desc.VS->Layout ? desc.VS->Layout : desc.VS->InputLayout) : nullptr;
|
||||||
RenderToolsVulkan::ZeroStruct(_descInputAssembly, VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO);;
|
RenderToolsVulkan::ZeroStruct(_descInputAssembly, VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO);;
|
||||||
switch (desc.PrimitiveTopology)
|
switch (desc.PrimitiveTopology)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -66,9 +66,10 @@ public:
|
|||||||
class GPUShaderProgramVSVulkan : public GPUShaderProgramVulkan<GPUShaderProgramVS>
|
class GPUShaderProgramVSVulkan : public GPUShaderProgramVulkan<GPUShaderProgramVS>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GPUShaderProgramVSVulkan(GPUDeviceVulkan* device, const GPUShaderProgramInitializer& initializer, const SpirvShaderDescriptorInfo& descriptorInfo, VkShaderModule shaderModule, GPUVertexLayout* vertexLayout)
|
GPUShaderProgramVSVulkan(GPUDeviceVulkan* device, const GPUShaderProgramInitializer& initializer, const SpirvShaderDescriptorInfo& descriptorInfo, VkShaderModule shaderModule, GPUVertexLayout* inputLayout, GPUVertexLayout* vertexLayout)
|
||||||
: GPUShaderProgramVulkan(device, initializer, descriptorInfo, shaderModule)
|
: GPUShaderProgramVulkan(device, initializer, descriptorInfo, shaderModule)
|
||||||
{
|
{
|
||||||
|
InputLayout = inputLayout;
|
||||||
Layout = vertexLayout;
|
Layout = vertexLayout;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -138,8 +138,9 @@ GPUShaderProgram* GPUShaderVulkan::CreateGPUShaderProgram(ShaderStage type, cons
|
|||||||
{
|
{
|
||||||
case ShaderStage::Vertex:
|
case ShaderStage::Vertex:
|
||||||
{
|
{
|
||||||
GPUVertexLayout* vertexLayout = ReadVertexLayout(stream);
|
GPUVertexLayout* inputLayout, *vertexLayout;
|
||||||
shader = New<GPUShaderProgramVSVulkan>(_device, initializer, header->DescriptorInfo, shaderModule, vertexLayout);
|
ReadVertexLayout(stream, inputLayout, vertexLayout);
|
||||||
|
shader = New<GPUShaderProgramVSVulkan>(_device, initializer, header->DescriptorInfo, shaderModule, inputLayout, vertexLayout);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#if GPU_ALLOW_TESSELLATION_SHADERS
|
#if GPU_ALLOW_TESSELLATION_SHADERS
|
||||||
|
|||||||
@@ -16,11 +16,9 @@
|
|||||||
class IncludeD3D : public ID3DInclude
|
class IncludeD3D : public ID3DInclude
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
ShaderCompilationContext* _context;
|
ShaderCompilationContext* _context;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
IncludeD3D(ShaderCompilationContext* context)
|
IncludeD3D(ShaderCompilationContext* context)
|
||||||
{
|
{
|
||||||
_context = context;
|
_context = context;
|
||||||
@@ -84,14 +82,9 @@ namespace
|
|||||||
// Extract constant buffers usage information
|
// Extract constant buffers usage information
|
||||||
for (uint32 a = 0; a < desc.ConstantBuffers; a++)
|
for (uint32 a = 0; a < desc.ConstantBuffers; a++)
|
||||||
{
|
{
|
||||||
// Get CB
|
|
||||||
auto cb = reflector->GetConstantBufferByIndex(a);
|
auto cb = reflector->GetConstantBufferByIndex(a);
|
||||||
|
|
||||||
// Get CB description
|
|
||||||
D3D11_SHADER_BUFFER_DESC cbDesc;
|
D3D11_SHADER_BUFFER_DESC cbDesc;
|
||||||
cb->GetDesc(&cbDesc);
|
cb->GetDesc(&cbDesc);
|
||||||
|
|
||||||
// Check buffer type
|
|
||||||
if (cbDesc.Type == D3D_CT_CBUFFER)
|
if (cbDesc.Type == D3D_CT_CBUFFER)
|
||||||
{
|
{
|
||||||
// Find CB slot index
|
// Find CB slot index
|
||||||
@@ -132,22 +125,20 @@ namespace
|
|||||||
// Extract resources usage
|
// Extract resources usage
|
||||||
for (uint32 i = 0; i < desc.BoundResources; i++)
|
for (uint32 i = 0; i < desc.BoundResources; i++)
|
||||||
{
|
{
|
||||||
// Get resource description
|
|
||||||
D3D11_SHADER_INPUT_BIND_DESC resDesc;
|
D3D11_SHADER_INPUT_BIND_DESC resDesc;
|
||||||
reflector->GetResourceBindingDesc(i, &resDesc);
|
reflector->GetResourceBindingDesc(i, &resDesc);
|
||||||
|
|
||||||
switch (resDesc.Type)
|
switch (resDesc.Type)
|
||||||
{
|
{
|
||||||
// Sampler
|
// Sampler
|
||||||
case D3D_SIT_SAMPLER:
|
case D3D_SIT_SAMPLER:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Constant Buffer
|
// Constant Buffer
|
||||||
case D3D_SIT_CBUFFER:
|
case D3D_SIT_CBUFFER:
|
||||||
case D3D_SIT_TBUFFER:
|
case D3D_SIT_TBUFFER:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Shader Resource
|
// Shader Resource
|
||||||
case D3D_SIT_TEXTURE:
|
case D3D_SIT_TEXTURE:
|
||||||
case D3D_SIT_STRUCTURED:
|
case D3D_SIT_STRUCTURED:
|
||||||
case D3D_SIT_BYTEADDRESS:
|
case D3D_SIT_BYTEADDRESS:
|
||||||
@@ -155,7 +146,7 @@ namespace
|
|||||||
bindings.UsedSRsMask |= 1 << (resDesc.BindPoint + shift);
|
bindings.UsedSRsMask |= 1 << (resDesc.BindPoint + shift);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Unordered Access
|
// Unordered Access
|
||||||
case D3D_SIT_UAV_RWTYPED:
|
case D3D_SIT_UAV_RWTYPED:
|
||||||
case D3D_SIT_UAV_RWSTRUCTURED:
|
case D3D_SIT_UAV_RWSTRUCTURED:
|
||||||
case D3D_SIT_UAV_RWBYTEADDRESS:
|
case D3D_SIT_UAV_RWBYTEADDRESS:
|
||||||
@@ -212,7 +203,6 @@ bool ShaderCompilerD3D::CompileShader(ShaderFunctionMeta& meta, WritePermutation
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
profileName += "_4_0";
|
profileName += "_4_0";
|
||||||
|
|
||||||
if (type == ShaderStage::Domain || type == ShaderStage::Hull)
|
if (type == ShaderStage::Domain || type == ShaderStage::Hull)
|
||||||
{
|
{
|
||||||
_context->OnError("Tessellation is not supported on DirectX 10");
|
_context->OnError("Tessellation is not supported on DirectX 10");
|
||||||
@@ -221,6 +211,7 @@ bool ShaderCompilerD3D::CompileShader(ShaderFunctionMeta& meta, WritePermutation
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Compile all shader function permutations
|
// Compile all shader function permutations
|
||||||
|
AdditionalDataVS additionalDataVS;
|
||||||
for (int32 permutationIndex = 0; permutationIndex < meta.Permutations.Count(); permutationIndex++)
|
for (int32 permutationIndex = 0; permutationIndex < meta.Permutations.Count(); permutationIndex++)
|
||||||
{
|
{
|
||||||
_macros.Clear();
|
_macros.Clear();
|
||||||
@@ -253,8 +244,6 @@ bool ShaderCompilerD3D::CompileShader(ShaderFunctionMeta& meta, WritePermutation
|
|||||||
0,
|
0,
|
||||||
&shader,
|
&shader,
|
||||||
&errors);
|
&errors);
|
||||||
|
|
||||||
// Check compilation result
|
|
||||||
if (FAILED(result))
|
if (FAILED(result))
|
||||||
{
|
{
|
||||||
const auto msg = static_cast<const char*>(errors->GetBufferPointer());
|
const auto msg = static_cast<const char*>(errors->GetBufferPointer());
|
||||||
@@ -279,24 +268,68 @@ bool ShaderCompilerD3D::CompileShader(ShaderFunctionMeta& meta, WritePermutation
|
|||||||
reflector->GetDesc(&desc);
|
reflector->GetDesc(&desc);
|
||||||
|
|
||||||
// Process shader reflection data
|
// 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 };
|
ShaderBindings bindings = { desc.InstructionCount, 0, 0, 0 };
|
||||||
if (ProcessShader(_context, _constantBuffers, reflector.Get(), desc, bindings))
|
if (ProcessShader(_context, _constantBuffers, reflector.Get(), desc, bindings))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
#ifdef GPU_USE_SHADERS_DEBUG_LAYER
|
#ifdef GPU_USE_SHADERS_DEBUG_LAYER
|
||||||
|
|
||||||
// Generate debug information
|
// Generate debug information
|
||||||
if (ProcessDebugInfo(_context, meta, permutationIndex, shaderBuffer, shaderBufferSize))
|
if (ProcessDebugInfo(_context, meta, permutationIndex, shaderBuffer, shaderBufferSize))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Strip shader bytecode for an optimization
|
// Strip shader bytecode for an optimization
|
||||||
ComPtr<ID3DBlob> shaderStripped;
|
ComPtr<ID3DBlob> shaderStripped;
|
||||||
if (!options->GenerateDebugData)
|
if (!options->GenerateDebugData)
|
||||||
{
|
{
|
||||||
//auto prevShaderBufferSize = shaderBufferSize;
|
|
||||||
|
|
||||||
// Strip shader bytes
|
// Strip shader bytes
|
||||||
result = D3DStripShader(
|
result = D3DStripShader(
|
||||||
shaderBuffer,
|
shaderBuffer,
|
||||||
@@ -312,15 +345,12 @@ bool ShaderCompilerD3D::CompileShader(ShaderFunctionMeta& meta, WritePermutation
|
|||||||
// Set new buffer
|
// Set new buffer
|
||||||
shaderBuffer = shaderStripped->GetBufferPointer();
|
shaderBuffer = shaderStripped->GetBufferPointer();
|
||||||
shaderBufferSize = static_cast<int32>(shaderStripped->GetBufferSize());
|
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))
|
if (WriteShaderFunctionPermutation(_context, meta, permutationIndex, bindings, shaderBuffer, shaderBufferSize))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (customDataWrite && customDataWrite(_context, meta, permutationIndex, _macros))
|
if (customDataWrite && customDataWrite(_context, meta, permutationIndex, _macros, additionalData))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,12 +12,10 @@
|
|||||||
class ShaderCompilerD3D : public ShaderCompiler
|
class ShaderCompilerD3D : public ShaderCompiler
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Array<char> _funcNameDefineBuffer;
|
Array<char> _funcNameDefineBuffer;
|
||||||
uint32 _flags;
|
uint32 _flags;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="ShaderCompilerD3D"/> class.
|
/// Initializes a new instance of the <see cref="ShaderCompilerD3D"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -25,7 +23,6 @@ public:
|
|||||||
ShaderCompilerD3D(ShaderProfile profile);
|
ShaderCompilerD3D(ShaderProfile profile);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// [ShaderCompiler]
|
// [ShaderCompiler]
|
||||||
bool CompileShader(ShaderFunctionMeta& meta, WritePermutationData customDataWrite = nullptr) override;
|
bool CompileShader(ShaderFunctionMeta& meta, WritePermutationData customDataWrite = nullptr) override;
|
||||||
bool OnCompileBegin() override;
|
bool OnCompileBegin() override;
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
#include "ShaderCompilerDX.h"
|
#include "ShaderCompilerDX.h"
|
||||||
#include "Engine/Core/Log.h"
|
#include "Engine/Core/Log.h"
|
||||||
#include "Engine/Threading/Threading.h"
|
|
||||||
#include "Engine/Engine/Globals.h"
|
#include "Engine/Engine/Globals.h"
|
||||||
#include "Engine/Graphics/Config.h"
|
#include "Engine/Graphics/Config.h"
|
||||||
#include "Engine/GraphicsDevice/DirectX/DX12/Types.h"
|
#include "Engine/GraphicsDevice/DirectX/DX12/Types.h"
|
||||||
@@ -22,12 +21,10 @@
|
|||||||
class IncludeDX : public IDxcIncludeHandler
|
class IncludeDX : public IDxcIncludeHandler
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
ShaderCompilationContext* _context;
|
ShaderCompilationContext* _context;
|
||||||
IDxcLibrary* _library;
|
IDxcLibrary* _library;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
IncludeDX(ShaderCompilationContext* context, IDxcLibrary* library)
|
IncludeDX(ShaderCompilationContext* context, IDxcLibrary* library)
|
||||||
{
|
{
|
||||||
_context = context;
|
_context = context;
|
||||||
@@ -185,6 +182,7 @@ bool ShaderCompilerDX::CompileShader(ShaderFunctionMeta& meta, WritePermutationD
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Compile all shader function permutations
|
// Compile all shader function permutations
|
||||||
|
AdditionalDataVS additionalDataVS;
|
||||||
for (int32 permutationIndex = 0; permutationIndex < meta.Permutations.Count(); permutationIndex++)
|
for (int32 permutationIndex = 0; permutationIndex < meta.Permutations.Count(); permutationIndex++)
|
||||||
{
|
{
|
||||||
_macros.Clear();
|
_macros.Clear();
|
||||||
@@ -320,6 +318,54 @@ bool ShaderCompilerDX::CompileShader(ShaderFunctionMeta& meta, WritePermutationD
|
|||||||
shaderReflection->GetDesc(&desc);
|
shaderReflection->GetDesc(&desc);
|
||||||
|
|
||||||
// Process shader reflection data
|
// 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;
|
DxShaderHeader header;
|
||||||
Platform::MemoryClear(&header, sizeof(header));
|
Platform::MemoryClear(&header, sizeof(header));
|
||||||
ShaderBindings bindings = { desc.InstructionCount, 0, 0, 0 };
|
ShaderBindings bindings = { desc.InstructionCount, 0, 0, 0 };
|
||||||
@@ -370,16 +416,16 @@ bool ShaderCompilerDX::CompileShader(ShaderFunctionMeta& meta, WritePermutationD
|
|||||||
shaderReflection->GetResourceBindingDesc(i, &resDesc);
|
shaderReflection->GetResourceBindingDesc(i, &resDesc);
|
||||||
switch (resDesc.Type)
|
switch (resDesc.Type)
|
||||||
{
|
{
|
||||||
// Sampler
|
// Sampler
|
||||||
case D3D_SIT_SAMPLER:
|
case D3D_SIT_SAMPLER:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Constant Buffer
|
// Constant Buffer
|
||||||
case D3D_SIT_CBUFFER:
|
case D3D_SIT_CBUFFER:
|
||||||
case D3D_SIT_TBUFFER:
|
case D3D_SIT_TBUFFER:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Shader Resource
|
// Shader Resource
|
||||||
case D3D_SIT_TEXTURE:
|
case D3D_SIT_TEXTURE:
|
||||||
for (UINT shift = 0; shift < resDesc.BindCount; shift++)
|
for (UINT shift = 0; shift < resDesc.BindCount; shift++)
|
||||||
{
|
{
|
||||||
@@ -396,7 +442,7 @@ bool ShaderCompilerDX::CompileShader(ShaderFunctionMeta& meta, WritePermutationD
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Unordered Access
|
// Unordered Access
|
||||||
case D3D_SIT_UAV_RWTYPED:
|
case D3D_SIT_UAV_RWTYPED:
|
||||||
case D3D_SIT_UAV_RWSTRUCTURED:
|
case D3D_SIT_UAV_RWSTRUCTURED:
|
||||||
case D3D_SIT_UAV_RWBYTEADDRESS:
|
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()))
|
if (WriteShaderFunctionPermutation(_context, meta, permutationIndex, bindings, &header, sizeof(header), shaderBuffer->GetBufferPointer(), (int32)shaderBuffer->GetBufferSize()))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (customDataWrite && customDataWrite(_context, meta, permutationIndex, _macros))
|
if (customDataWrite && customDataWrite(_context, meta, permutationIndex, _macros, additionalData))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,14 +12,12 @@
|
|||||||
class ShaderCompilerDX : public ShaderCompiler
|
class ShaderCompilerDX : public ShaderCompiler
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Array<char> _funcNameDefineBuffer;
|
Array<char> _funcNameDefineBuffer;
|
||||||
void* _compiler;
|
void* _compiler;
|
||||||
void* _library;
|
void* _library;
|
||||||
void* _containerReflection;
|
void* _containerReflection;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="ShaderCompilerDX"/> class.
|
/// Initializes a new instance of the <see cref="ShaderCompilerDX"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -32,7 +30,6 @@ public:
|
|||||||
~ShaderCompilerDX();
|
~ShaderCompilerDX();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// [ShaderCompiler]
|
// [ShaderCompiler]
|
||||||
bool CompileShader(ShaderFunctionMeta& meta, WritePermutationData customDataWrite = nullptr) override;
|
bool CompileShader(ShaderFunctionMeta& meta, WritePermutationData customDataWrite = nullptr) override;
|
||||||
bool OnCompileBegin() override;
|
bool OnCompileBegin() override;
|
||||||
|
|||||||
@@ -271,7 +271,6 @@ bool ShaderCompiler::WriteShaderFunctionBegin(ShaderCompilationContext* context,
|
|||||||
bool ShaderCompiler::WriteShaderFunctionPermutation(ShaderCompilationContext* context, ShaderFunctionMeta& meta, int32 permutationIndex, const ShaderBindings& bindings, const void* header, int32 headerSize, const void* cache, int32 cacheSize)
|
bool ShaderCompiler::WriteShaderFunctionPermutation(ShaderCompilationContext* context, ShaderFunctionMeta& meta, int32 permutationIndex, const ShaderBindings& bindings, const void* header, int32 headerSize, const void* cache, int32 cacheSize)
|
||||||
{
|
{
|
||||||
auto output = context->Output;
|
auto output = context->Output;
|
||||||
|
|
||||||
output->Write((uint32)(cacheSize + headerSize));
|
output->Write((uint32)(cacheSize + headerSize));
|
||||||
output->WriteBytes(header, headerSize);
|
output->WriteBytes(header, headerSize);
|
||||||
output->WriteBytes(cache, cacheSize);
|
output->WriteBytes(cache, cacheSize);
|
||||||
@@ -293,18 +292,22 @@ bool ShaderCompiler::WriteShaderFunctionEnd(ShaderCompilationContext* context, S
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ShaderCompiler::WriteCustomDataVS(ShaderCompilationContext* context, ShaderFunctionMeta& meta, int32 permutationIndex, const Array<ShaderMacro>& macros)
|
bool ShaderCompiler::WriteCustomDataVS(ShaderCompilationContext* context, ShaderFunctionMeta& meta, int32 permutationIndex, const Array<ShaderMacro>& macros, void* additionalData)
|
||||||
{
|
{
|
||||||
// [Deprecated in v1.10]
|
|
||||||
auto output = context->Output;
|
auto output = context->Output;
|
||||||
|
|
||||||
|
// Write vertex shader inputs (based on compiled shader reflection) to bind any missing vertex buffer streaming at runtime (during drawing - see usage of GPUVertexLayout::Merge)
|
||||||
|
if (auto* additionalDataVS = (AdditionalDataVS*)additionalData)
|
||||||
|
output->Write(additionalDataVS->Inputs);
|
||||||
|
else
|
||||||
|
output->WriteInt32(0);
|
||||||
|
|
||||||
|
// [Deprecated in v1.10]
|
||||||
auto& metaVS = *(VertexShaderMeta*)&meta;
|
auto& metaVS = *(VertexShaderMeta*)&meta;
|
||||||
auto& layout = metaVS.InputLayout;
|
auto& layout = metaVS.InputLayout;
|
||||||
#if FLAXENGINE_VERSION_MAJOR > 2 || (FLAXENGINE_VERSION_MAJOR == 2 && FLAXENGINE_VERSION_MINOR >= 1)
|
#if FLAXENGINE_VERSION_MAJOR > 2 || (FLAXENGINE_VERSION_MAJOR == 2 && FLAXENGINE_VERSION_MINOR >= 1)
|
||||||
if (layout.HasItems())
|
if (layout.HasItems())
|
||||||
LOG(Warning, "Vertex Shader '{}' (asset '{}') uses explicit vertex layout via 'META_VS_IN_ELEMENT' macros which has been deprecated. Remove this code and migrate to GPUVertexLayout with VertexElement array in code (assigned to vertex buffer).", String(meta.Name), context->Options->TargetName);
|
LOG(Warning, "Vertex Shader '{}' (asset '{}') uses explicit vertex layout via 'META_VS_IN_ELEMENT' macros which has been deprecated. Remove this code and migrate to GPUVertexLayout with VertexElement array in code (assigned to vertex buffer).", String(meta.Name), context->Options->TargetName);
|
||||||
#elif FLAXENGINE_VERSION_MAJOR == 1 && FLAXENGINE_VERSION_MINOR >= 11
|
|
||||||
if (layout.HasItems())
|
|
||||||
LOG(Warning, "Vertex Shader '{}' (asset '{}') uses explicit vertex layout via 'META_VS_IN_ELEMENT' macros which has been deprecated. Remove this code and migrate to GPUVertexLayout with VertexElement array in code (assigned to vertex buffer).", String(meta.Name), context->Options->TargetName);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Get visible entries (based on `visible` flag switch)
|
// Get visible entries (based on `visible` flag switch)
|
||||||
@@ -443,7 +446,7 @@ bool ShaderCompiler::WriteCustomDataVS(ShaderCompilationContext* context, Shader
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ShaderCompiler::WriteCustomDataHS(ShaderCompilationContext* context, ShaderFunctionMeta& meta, int32 permutationIndex, const Array<ShaderMacro>& macros)
|
bool ShaderCompiler::WriteCustomDataHS(ShaderCompilationContext* context, ShaderFunctionMeta& meta, int32 permutationIndex, const Array<ShaderMacro>& macros, void* additionalData)
|
||||||
{
|
{
|
||||||
auto output = context->Output;
|
auto output = context->Output;
|
||||||
auto& metaHS = *(HullShaderMeta*)&meta;
|
auto& metaHS = *(HullShaderMeta*)&meta;
|
||||||
@@ -457,7 +460,7 @@ bool ShaderCompiler::WriteCustomDataHS(ShaderCompilationContext* context, Shader
|
|||||||
void ShaderCompiler::GetDefineForFunction(ShaderFunctionMeta& meta, Array<ShaderMacro>& macros)
|
void ShaderCompiler::GetDefineForFunction(ShaderFunctionMeta& meta, Array<ShaderMacro>& macros)
|
||||||
{
|
{
|
||||||
auto& functionName = meta.Name;
|
auto& functionName = meta.Name;
|
||||||
const int32 functionNameLength = static_cast<int32>(functionName.Length());
|
const int32 functionNameLength = functionName.Length();
|
||||||
_funcNameDefineBuffer.Clear();
|
_funcNameDefineBuffer.Clear();
|
||||||
_funcNameDefineBuffer.EnsureCapacity(functionNameLength + 2);
|
_funcNameDefineBuffer.EnsureCapacity(functionNameLength + 2);
|
||||||
_funcNameDefineBuffer.Add('_');
|
_funcNameDefineBuffer.Add('_');
|
||||||
@@ -466,4 +469,35 @@ void ShaderCompiler::GetDefineForFunction(ShaderFunctionMeta& meta, Array<Shader
|
|||||||
macros.Add({ _funcNameDefineBuffer.Get(), "1" });
|
macros.Add({ _funcNameDefineBuffer.Get(), "1" });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VertexElement::Types ShaderCompiler::ParseVertexElementType(StringAnsiView semantic, uint32 index)
|
||||||
|
{
|
||||||
|
if (semantic.HasChars() && StringUtils::IsDigit(semantic[semantic.Length() - 1]))
|
||||||
|
{
|
||||||
|
// Get index from end of the name
|
||||||
|
index = semantic[semantic.Length() - 1] - '0';
|
||||||
|
semantic = StringAnsiView(semantic.Get(), semantic.Length() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (semantic == "POSITION")
|
||||||
|
return VertexElement::Types::Position;
|
||||||
|
if (semantic == "COLOR")
|
||||||
|
return VertexElement::Types::Color;
|
||||||
|
if (semantic == "NORMAL")
|
||||||
|
return VertexElement::Types::Normal;
|
||||||
|
if (semantic == "TANGENT")
|
||||||
|
return VertexElement::Types::Tangent;
|
||||||
|
if (semantic == "BLENDINDICES")
|
||||||
|
return VertexElement::Types::BlendIndices;
|
||||||
|
if (semantic == "BLENDWEIGHTS" ||
|
||||||
|
semantic == "BLENDWEIGHT") // [Deprecated in v1.10]
|
||||||
|
return VertexElement::Types::BlendWeights;
|
||||||
|
if (semantic == "TEXCOORD" && index < 8)
|
||||||
|
return (VertexElement::Types)((int32)VertexElement::Types::TexCoord0 + index);
|
||||||
|
if (semantic == "ATTRIBUTE" && index < 4)
|
||||||
|
return (VertexElement::Types)((int32)VertexElement::Types::Attribute0 + index);
|
||||||
|
|
||||||
|
LOG(Warning, "Unsupported vertex shader input element semantic {}{}", semantic.ToString(), index);
|
||||||
|
return VertexElement::Types::Unknown;;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include "ShaderCompilationContext.h"
|
#include "ShaderCompilationContext.h"
|
||||||
#include "Parser/ShaderMeta.h"
|
#include "Parser/ShaderMeta.h"
|
||||||
#include "Engine/Graphics/Shaders/GPUShaderProgram.h"
|
#include "Engine/Graphics/Shaders/GPUShaderProgram.h"
|
||||||
|
#include "Engine/Graphics/Shaders/GPUVertexLayout.h"
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Base class for the objects that can compile shaders source code.
|
/// Base class for the objects that can compile shaders source code.
|
||||||
@@ -14,7 +15,6 @@
|
|||||||
class ShaderCompiler
|
class ShaderCompiler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
struct ShaderResourceBuffer
|
struct ShaderResourceBuffer
|
||||||
{
|
{
|
||||||
byte Slot;
|
byte Slot;
|
||||||
@@ -23,11 +23,9 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Array<char> _funcNameDefineBuffer;
|
Array<char> _funcNameDefineBuffer;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
ShaderProfile _profile;
|
ShaderProfile _profile;
|
||||||
ShaderCompilationContext* _context = nullptr;
|
ShaderCompilationContext* _context = nullptr;
|
||||||
Array<ShaderMacro> _globalMacros;
|
Array<ShaderMacro> _globalMacros;
|
||||||
@@ -35,7 +33,6 @@ protected:
|
|||||||
Array<ShaderResourceBuffer> _constantBuffers;
|
Array<ShaderResourceBuffer> _constantBuffers;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="ShaderCompiler"/> class.
|
/// Initializes a new instance of the <see cref="ShaderCompiler"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -51,7 +48,6 @@ public:
|
|||||||
virtual ~ShaderCompiler() = default;
|
virtual ~ShaderCompiler() = default;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets shader profile supported by this compiler.
|
/// Gets shader profile supported by this compiler.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -85,8 +81,13 @@ public:
|
|||||||
static void DisposeIncludedFilesCache();
|
static void DisposeIncludedFilesCache();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
// Input elements read from reflection after shader compilation. Rough approx or attributes without exact format nor bind slot (only semantics and value dimensions match).
|
||||||
|
struct AdditionalDataVS
|
||||||
|
{
|
||||||
|
GPUVertexLayout::Elements Inputs;
|
||||||
|
};
|
||||||
|
|
||||||
typedef bool (*WritePermutationData)(ShaderCompilationContext*, ShaderFunctionMeta&, int32, const Array<ShaderMacro>&);
|
typedef bool (*WritePermutationData)(ShaderCompilationContext*, ShaderFunctionMeta&, int32, const Array<ShaderMacro>&, void*);
|
||||||
|
|
||||||
virtual bool CompileShader(ShaderFunctionMeta& meta, WritePermutationData customDataWrite = nullptr) = 0;
|
virtual bool CompileShader(ShaderFunctionMeta& meta, WritePermutationData customDataWrite = nullptr) = 0;
|
||||||
|
|
||||||
@@ -99,9 +100,11 @@ protected:
|
|||||||
static bool WriteShaderFunctionPermutation(ShaderCompilationContext* context, ShaderFunctionMeta& meta, int32 permutationIndex, const ShaderBindings& bindings, const void* header, int32 headerSize, const void* cache, int32 cacheSize);
|
static bool WriteShaderFunctionPermutation(ShaderCompilationContext* context, ShaderFunctionMeta& meta, int32 permutationIndex, const ShaderBindings& bindings, const void* header, int32 headerSize, const void* cache, int32 cacheSize);
|
||||||
static bool WriteShaderFunctionPermutation(ShaderCompilationContext* context, ShaderFunctionMeta& meta, int32 permutationIndex, const ShaderBindings& bindings, const void* cache, int32 cacheSize);
|
static bool WriteShaderFunctionPermutation(ShaderCompilationContext* context, ShaderFunctionMeta& meta, int32 permutationIndex, const ShaderBindings& bindings, const void* cache, int32 cacheSize);
|
||||||
static bool WriteShaderFunctionEnd(ShaderCompilationContext* context, ShaderFunctionMeta& meta);
|
static bool WriteShaderFunctionEnd(ShaderCompilationContext* context, ShaderFunctionMeta& meta);
|
||||||
static bool WriteCustomDataVS(ShaderCompilationContext* context, ShaderFunctionMeta& meta, int32 permutationIndex, const Array<ShaderMacro>& macros);
|
static bool WriteCustomDataVS(ShaderCompilationContext* context, ShaderFunctionMeta& meta, int32 permutationIndex, const Array<ShaderMacro>& macros, void* additionalData);
|
||||||
static bool WriteCustomDataHS(ShaderCompilationContext* context, ShaderFunctionMeta& meta, int32 permutationIndex, const Array<ShaderMacro>& macros);
|
static bool WriteCustomDataHS(ShaderCompilationContext* context, ShaderFunctionMeta& meta, int32 permutationIndex, const Array<ShaderMacro>& macros, void* additionalData);
|
||||||
void GetDefineForFunction(ShaderFunctionMeta& meta, Array<ShaderMacro>& macros);
|
void GetDefineForFunction(ShaderFunctionMeta& meta, Array<ShaderMacro>& macros);
|
||||||
|
|
||||||
|
static VertexElement::Types ParseVertexElementType(StringAnsiView semantic, uint32 index = 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -234,14 +234,14 @@ SpirvShaderResourceType GetTextureType(const glslang::TSampler& sampler)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PixelFormat GetResourceFormat(const glslang::TSampler& sampler)
|
PixelFormat GetResourceFormat(glslang::TBasicType basicType, uint32 vectorSize)
|
||||||
{
|
{
|
||||||
switch (sampler.type)
|
switch (basicType)
|
||||||
{
|
{
|
||||||
case glslang::EbtVoid:
|
case glslang::EbtVoid:
|
||||||
return PixelFormat::Unknown;
|
return PixelFormat::Unknown;
|
||||||
case glslang::EbtFloat:
|
case glslang::EbtFloat:
|
||||||
switch (sampler.vectorSize)
|
switch (vectorSize)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
return PixelFormat::R32_Float;
|
return PixelFormat::R32_Float;
|
||||||
@@ -254,7 +254,7 @@ PixelFormat GetResourceFormat(const glslang::TSampler& sampler)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case glslang::EbtFloat16:
|
case glslang::EbtFloat16:
|
||||||
switch (sampler.vectorSize)
|
switch (vectorSize)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
return PixelFormat::R16_Float;
|
return PixelFormat::R16_Float;
|
||||||
@@ -265,7 +265,7 @@ PixelFormat GetResourceFormat(const glslang::TSampler& sampler)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case glslang::EbtUint:
|
case glslang::EbtUint:
|
||||||
switch (sampler.vectorSize)
|
switch (vectorSize)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
return PixelFormat::R32_UInt;
|
return PixelFormat::R32_UInt;
|
||||||
@@ -278,7 +278,7 @@ PixelFormat GetResourceFormat(const glslang::TSampler& sampler)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case glslang::EbtInt:
|
case glslang::EbtInt:
|
||||||
switch (sampler.vectorSize)
|
switch (vectorSize)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
return PixelFormat::R32_SInt;
|
return PixelFormat::R32_SInt;
|
||||||
@@ -291,7 +291,7 @@ PixelFormat GetResourceFormat(const glslang::TSampler& sampler)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case glslang::EbtUint8:
|
case glslang::EbtUint8:
|
||||||
switch (sampler.vectorSize)
|
switch (vectorSize)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
return PixelFormat::R8_UInt;
|
return PixelFormat::R8_UInt;
|
||||||
@@ -302,7 +302,7 @@ PixelFormat GetResourceFormat(const glslang::TSampler& sampler)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case glslang::EbtInt8:
|
case glslang::EbtInt8:
|
||||||
switch (sampler.vectorSize)
|
switch (vectorSize)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
return PixelFormat::R8_SInt;
|
return PixelFormat::R8_SInt;
|
||||||
@@ -313,7 +313,7 @@ PixelFormat GetResourceFormat(const glslang::TSampler& sampler)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case glslang::EbtUint16:
|
case glslang::EbtUint16:
|
||||||
switch (sampler.vectorSize)
|
switch (vectorSize)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
return PixelFormat::R16_UInt;
|
return PixelFormat::R16_UInt;
|
||||||
@@ -324,7 +324,7 @@ PixelFormat GetResourceFormat(const glslang::TSampler& sampler)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case glslang::EbtInt16:
|
case glslang::EbtInt16:
|
||||||
switch (sampler.vectorSize)
|
switch (vectorSize)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
return PixelFormat::R16_SInt;
|
return PixelFormat::R16_SInt;
|
||||||
@@ -340,6 +340,16 @@ PixelFormat GetResourceFormat(const glslang::TSampler& sampler)
|
|||||||
return PixelFormat::Unknown;
|
return PixelFormat::Unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PixelFormat GetResourceFormat(const glslang::TSampler& sampler)
|
||||||
|
{
|
||||||
|
return GetResourceFormat(sampler.type, sampler.vectorSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
PixelFormat GetResourceFormat(const glslang::TType& type)
|
||||||
|
{
|
||||||
|
return GetResourceFormat(type.getBasicType(), type.getVectorSize());
|
||||||
|
}
|
||||||
|
|
||||||
bool IsUavType(const glslang::TType& type)
|
bool IsUavType(const glslang::TType& type)
|
||||||
{
|
{
|
||||||
if (type.getQualifier().isReadOnly())
|
if (type.getQualifier().isReadOnly())
|
||||||
@@ -611,6 +621,7 @@ bool ShaderCompilerVulkan::CompileShader(ShaderFunctionMeta& meta, WritePermutat
|
|||||||
EShMessages messages = (EShMessages)(EShMsgReadHlsl | EShMsgSpvRules | EShMsgVulkanRules);
|
EShMessages messages = (EShMessages)(EShMsgReadHlsl | EShMsgSpvRules | EShMsgVulkanRules);
|
||||||
|
|
||||||
// Compile all shader function permutations
|
// Compile all shader function permutations
|
||||||
|
AdditionalDataVS additionalDataVS;
|
||||||
for (int32 permutationIndex = 0; permutationIndex < meta.Permutations.Count(); permutationIndex++)
|
for (int32 permutationIndex = 0; permutationIndex < meta.Permutations.Count(); permutationIndex++)
|
||||||
{
|
{
|
||||||
#if PRINT_DESCRIPTORS
|
#if PRINT_DESCRIPTORS
|
||||||
@@ -721,157 +732,167 @@ bool ShaderCompilerVulkan::CompileShader(ShaderFunctionMeta& meta, WritePermutat
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Process shader reflection data
|
// Process shader reflection data
|
||||||
|
void* additionalData = nullptr;
|
||||||
SpirvShaderHeader header;
|
SpirvShaderHeader header;
|
||||||
Platform::MemoryClear(&header, sizeof(header));
|
Platform::MemoryClear(&header, sizeof(header));
|
||||||
ShaderBindings bindings = { 0, 0, 0, 0 };
|
ShaderBindings bindings = { 0, 0, 0, 0 };
|
||||||
|
if (type == ShaderStage::Vertex)
|
||||||
{
|
{
|
||||||
// Extract constant buffers usage information
|
additionalData = &additionalDataVS;
|
||||||
for (int blockIndex = 0; blockIndex < program.getNumLiveUniformBlocks(); blockIndex++)
|
additionalDataVS.Inputs.Clear();
|
||||||
|
for (int inputIndex = 0; inputIndex < program.getNumPipeInputs(); inputIndex++)
|
||||||
{
|
{
|
||||||
auto size = program.getUniformBlockSize(blockIndex);
|
const glslang::TObjectReflection& input = program.getPipeInput(inputIndex);
|
||||||
auto uniform = program.getUniformBlockTType(blockIndex);
|
if (!input.getType() || input.getType()->containsBuiltIn())
|
||||||
auto& qualifier = uniform->getQualifier();
|
|
||||||
auto binding = (int32)qualifier.layoutBinding;
|
|
||||||
|
|
||||||
if (!qualifier.hasBinding())
|
|
||||||
{
|
|
||||||
// Each uniform must have a valid binding
|
|
||||||
//LOG(Warning, "Found a uniform block \'{0}\' without a binding qualifier. Each uniform block must have an explicitly defined binding number.", String(uniform->getTypeName().c_str()));
|
|
||||||
continue;
|
continue;
|
||||||
}
|
additionalDataVS.Inputs.Add({ ParseVertexElementType(input.getType()->getQualifier().semanticName), 0, 0, 0, GetResourceFormat(*input.getType()) });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int blockIndex = 0; blockIndex < program.getNumLiveUniformBlocks(); blockIndex++)
|
||||||
|
{
|
||||||
|
auto size = program.getUniformBlockSize(blockIndex);
|
||||||
|
auto uniform = program.getUniformBlockTType(blockIndex);
|
||||||
|
auto& qualifier = uniform->getQualifier();
|
||||||
|
auto binding = (int32)qualifier.layoutBinding;
|
||||||
|
|
||||||
// Shared storage buffer
|
if (!qualifier.hasBinding())
|
||||||
if (qualifier.storage == glslang::EvqBuffer)
|
{
|
||||||
|
// Each uniform must have a valid binding
|
||||||
|
//LOG(Warning, "Found a uniform block \'{0}\' without a binding qualifier. Each uniform block must have an explicitly defined binding number.", String(uniform->getTypeName().c_str()));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shared storage buffer
|
||||||
|
if (qualifier.storage == glslang::EvqBuffer)
|
||||||
|
{
|
||||||
|
// RWBuffer
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Uniform buffer
|
||||||
|
bool found = false;
|
||||||
|
for (int32 i = 0; i < descriptorsCollector.DescriptorsCount; i++)
|
||||||
{
|
{
|
||||||
// RWBuffer
|
auto& descriptor = descriptorsCollector.Descriptors[i];
|
||||||
|
if (descriptor.BindingType == SpirvShaderResourceBindingType::CB && descriptor.Binding == binding)
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
descriptor.Size = size;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
if (!found)
|
||||||
{
|
{
|
||||||
// Uniform buffer
|
LOG(Warning, "Failed to find descriptor for the uniform block \'{0}\' of size {1} (bytes), binding: {2}.", String(uniform->getTypeName().c_str()), size, binding);
|
||||||
bool found = false;
|
|
||||||
for (int32 i = 0; i < descriptorsCollector.DescriptorsCount; i++)
|
|
||||||
{
|
|
||||||
auto& descriptor = descriptorsCollector.Descriptors[i];
|
|
||||||
if (descriptor.BindingType == SpirvShaderResourceBindingType::CB && descriptor.Binding == binding)
|
|
||||||
{
|
|
||||||
found = true;
|
|
||||||
descriptor.Size = size;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!found)
|
|
||||||
{
|
|
||||||
LOG(Warning, "Failed to find descriptor for the uniform block \'{0}\' of size {1} (bytes), binding: {2}.", String(uniform->getTypeName().c_str()), size, binding);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if PRINT_UNIFORMS
|
#if PRINT_UNIFORMS
|
||||||
// Debug printing all uniforms
|
// Debug printing all uniforms
|
||||||
for (int32 index = 0; index < program.getNumLiveUniformVariables(); index++)
|
for (int32 index = 0; index < program.getNumLiveUniformVariables(); index++)
|
||||||
{
|
{
|
||||||
auto uniform = program.getUniformTType(index);
|
auto uniform = program.getUniformTType(index);
|
||||||
auto qualifier = uniform->getQualifier();
|
auto qualifier = uniform->getQualifier();
|
||||||
if (!uniform->isArray())
|
if (!uniform->isArray())
|
||||||
LOG(Warning, "Shader {0}:{1} - uniform: {2} {3} at binding {4}",
|
LOG(Warning, "Shader {0}:{1} - uniform: {2} {3} at binding {4}",
|
||||||
_context->TargetNameAnsi,
|
_context->TargetNameAnsi,
|
||||||
String(meta.Name),
|
String(meta.Name),
|
||||||
uniform->getCompleteString().c_str(),
|
uniform->getCompleteString().c_str(),
|
||||||
program.getUniformName(index),
|
program.getUniformName(index),
|
||||||
qualifier.layoutBinding
|
qualifier.layoutBinding
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Process all descriptors
|
// Process all descriptors
|
||||||
header.DescriptorInfo.ImageInfosCount = descriptorsCollector.Images;
|
header.DescriptorInfo.ImageInfosCount = descriptorsCollector.Images;
|
||||||
header.DescriptorInfo.BufferInfosCount = descriptorsCollector.Buffers;
|
header.DescriptorInfo.BufferInfosCount = descriptorsCollector.Buffers;
|
||||||
header.DescriptorInfo.TexelBufferViewsCount = descriptorsCollector.TexelBuffers;
|
header.DescriptorInfo.TexelBufferViewsCount = descriptorsCollector.TexelBuffers;
|
||||||
for (int32 i = 0; i < descriptorsCollector.DescriptorsCount; i++)
|
for (int32 i = 0; i < descriptorsCollector.DescriptorsCount; i++)
|
||||||
|
{
|
||||||
|
auto& descriptor = descriptorsCollector.Descriptors[i];
|
||||||
|
|
||||||
|
// Skip cases (eg. AppendStructuredBuffer counter buffer)
|
||||||
|
if (descriptor.Slot == MAX_uint16)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto& d = header.DescriptorInfo.DescriptorTypes[header.DescriptorInfo.DescriptorTypesCount++];
|
||||||
|
d.Binding = descriptor.Binding;
|
||||||
|
d.Set = stageSet;
|
||||||
|
d.Slot = descriptor.Slot;
|
||||||
|
d.BindingType = descriptor.BindingType;
|
||||||
|
d.DescriptorType = descriptor.DescriptorType;
|
||||||
|
d.ResourceType = descriptor.ResourceType;
|
||||||
|
d.ResourceFormat = descriptor.ResourceFormat;
|
||||||
|
d.Count = descriptor.Count;
|
||||||
|
|
||||||
|
switch (descriptor.BindingType)
|
||||||
{
|
{
|
||||||
auto& descriptor = descriptorsCollector.Descriptors[i];
|
case SpirvShaderResourceBindingType::CB:
|
||||||
|
ASSERT_LOW_LAYER(descriptor.Slot >= 0 && descriptor.Slot < GPU_MAX_CB_BINDED);
|
||||||
|
bindings.UsedCBsMask |= 1 << descriptor.Slot;
|
||||||
|
break;
|
||||||
|
case SpirvShaderResourceBindingType::SRV:
|
||||||
|
ASSERT_LOW_LAYER(descriptor.Slot >= 0 && descriptor.Slot < GPU_MAX_SR_BINDED);
|
||||||
|
bindings.UsedSRsMask |= 1 << descriptor.Slot;
|
||||||
|
break;
|
||||||
|
case SpirvShaderResourceBindingType::UAV:
|
||||||
|
ASSERT_LOW_LAYER(descriptor.Slot >= 0 && descriptor.Slot < GPU_MAX_UA_BINDED);
|
||||||
|
bindings.UsedUAsMask |= 1 << descriptor.Slot;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// Skip cases (eg. AppendStructuredBuffer counter buffer)
|
if (descriptor.BindingType == SpirvShaderResourceBindingType::CB)
|
||||||
if (descriptor.Slot == MAX_uint16)
|
{
|
||||||
|
if (descriptor.Size == -1)
|
||||||
|
{
|
||||||
|
// Skip unused constant buffers
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
auto& d = header.DescriptorInfo.DescriptorTypes[header.DescriptorInfo.DescriptorTypesCount++];
|
if (descriptor.Size == 0)
|
||||||
d.Binding = descriptor.Binding;
|
|
||||||
d.Set = stageSet;
|
|
||||||
d.Slot = descriptor.Slot;
|
|
||||||
d.BindingType = descriptor.BindingType;
|
|
||||||
d.DescriptorType = descriptor.DescriptorType;
|
|
||||||
d.ResourceType = descriptor.ResourceType;
|
|
||||||
d.ResourceFormat = descriptor.ResourceFormat;
|
|
||||||
d.Count = descriptor.Count;
|
|
||||||
|
|
||||||
switch (descriptor.BindingType)
|
|
||||||
{
|
{
|
||||||
case SpirvShaderResourceBindingType::CB:
|
LOG(Warning, "Found constant buffer \'{1}\' at slot {0} but it's not used or has no valid size.", descriptor.Slot, String(descriptor.Name.c_str()));
|
||||||
ASSERT_LOW_LAYER(descriptor.Slot >= 0 && descriptor.Slot < GPU_MAX_CB_BINDED);
|
continue;
|
||||||
bindings.UsedCBsMask |= 1 << descriptor.Slot;
|
|
||||||
break;
|
|
||||||
case SpirvShaderResourceBindingType::SRV:
|
|
||||||
ASSERT_LOW_LAYER(descriptor.Slot >= 0 && descriptor.Slot < GPU_MAX_SR_BINDED);
|
|
||||||
bindings.UsedSRsMask |= 1 << descriptor.Slot;
|
|
||||||
break;
|
|
||||||
case SpirvShaderResourceBindingType::UAV:
|
|
||||||
ASSERT_LOW_LAYER(descriptor.Slot >= 0 && descriptor.Slot < GPU_MAX_UA_BINDED);
|
|
||||||
bindings.UsedUAsMask |= 1 << descriptor.Slot;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (descriptor.BindingType == SpirvShaderResourceBindingType::CB)
|
for (int32 b = 0; b < _constantBuffers.Count(); b++)
|
||||||
{
|
{
|
||||||
if (descriptor.Size == -1)
|
auto& cc = _constantBuffers[b];
|
||||||
|
if (cc.Slot == descriptor.Slot)
|
||||||
{
|
{
|
||||||
// Skip unused constant buffers
|
// Mark as used and cache some data
|
||||||
continue;
|
cc.IsUsed = true;
|
||||||
}
|
cc.Size = descriptor.Size;
|
||||||
if (descriptor.Size == 0)
|
break;
|
||||||
{
|
|
||||||
LOG(Warning, "Found constant buffer \'{1}\' at slot {0} but it's not used or has no valid size.", descriptor.Slot, String(descriptor.Name.c_str()));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int32 b = 0; b < _constantBuffers.Count(); b++)
|
|
||||||
{
|
|
||||||
auto& cc = _constantBuffers[b];
|
|
||||||
if (cc.Slot == descriptor.Slot)
|
|
||||||
{
|
|
||||||
// Mark as used and cache some data
|
|
||||||
cc.IsUsed = true;
|
|
||||||
cc.Size = descriptor.Size;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if PRINT_DESCRIPTORS
|
#if PRINT_DESCRIPTORS
|
||||||
String type;
|
String type;
|
||||||
switch (descriptor.BindingType)
|
switch (descriptor.BindingType)
|
||||||
{
|
{
|
||||||
case SpirvShaderResourceBindingType::INVALID:
|
case SpirvShaderResourceBindingType::INVALID:
|
||||||
type = TEXT("INVALID");
|
type = TEXT("INVALID");
|
||||||
break;
|
break;
|
||||||
case SpirvShaderResourceBindingType::CB:
|
case SpirvShaderResourceBindingType::CB:
|
||||||
type = TEXT("CB");
|
type = TEXT("CB");
|
||||||
break;
|
break;
|
||||||
case SpirvShaderResourceBindingType::SAMPLER:
|
case SpirvShaderResourceBindingType::SAMPLER:
|
||||||
type = TEXT("SAMPLER");
|
type = TEXT("SAMPLER");
|
||||||
break;
|
break;
|
||||||
case SpirvShaderResourceBindingType::SRV:
|
case SpirvShaderResourceBindingType::SRV:
|
||||||
type = TEXT("SRV");
|
type = TEXT("SRV");
|
||||||
break;
|
break;
|
||||||
case SpirvShaderResourceBindingType::UAV:
|
case SpirvShaderResourceBindingType::UAV:
|
||||||
type = TEXT("UAV");
|
type = TEXT("UAV");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
type = TEXT("?");
|
type = TEXT("?");
|
||||||
}
|
|
||||||
LOG(Warning, "VULKAN SHADER RESOURCE: slot: {1}, binding: {2}, name: {0}, type: {3}", String(descriptor.Name.c_str()), descriptor.Slot, descriptor.Binding, type);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
LOG(Warning, "VULKAN SHADER RESOURCE: slot: {1}, binding: {2}, name: {0}, type: {3}", String(descriptor.Name.c_str()), descriptor.Slot, descriptor.Binding, type);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate SPIR-V (optimize it at the same time)
|
// Generate SPIR-V (optimize it at the same time)
|
||||||
@@ -916,7 +937,7 @@ bool ShaderCompilerVulkan::CompileShader(ShaderFunctionMeta& meta, WritePermutat
|
|||||||
if (WriteShaderFunctionPermutation(_context, meta, permutationIndex, bindings, &header, sizeof(header), &spirv[0], spirvBytesCount))
|
if (WriteShaderFunctionPermutation(_context, meta, permutationIndex, bindings, &header, sizeof(header), &spirv[0], spirvBytesCount))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (customDataWrite && customDataWrite(_context, meta, permutationIndex, _macros))
|
if (customDataWrite && customDataWrite(_context, meta, permutationIndex, _macros, additionalData))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,11 +12,9 @@
|
|||||||
class ShaderCompilerVulkan : public ShaderCompiler
|
class ShaderCompilerVulkan : public ShaderCompiler
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Array<char> _funcNameDefineBuffer;
|
Array<char> _funcNameDefineBuffer;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="ShaderCompilerVulkan"/> class.
|
/// Initializes a new instance of the <see cref="ShaderCompilerVulkan"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -29,7 +27,6 @@ public:
|
|||||||
~ShaderCompilerVulkan();
|
~ShaderCompilerVulkan();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// [ShaderCompiler]
|
// [ShaderCompiler]
|
||||||
bool CompileShader(ShaderFunctionMeta& meta, WritePermutationData customDataWrite = nullptr) override;
|
bool CompileShader(ShaderFunctionMeta& meta, WritePermutationData customDataWrite = nullptr) override;
|
||||||
bool OnCompileBegin() override;
|
bool OnCompileBegin() override;
|
||||||
|
|||||||
Reference in New Issue
Block a user