Refactor vertex shaders to use GPUShaderProgramVS::InputElement for input layout data
This commit is contained in:
@@ -122,6 +122,19 @@ public:
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
class GPUShaderProgramVS : public GPUShaderProgram
|
class GPUShaderProgramVS : public GPUShaderProgram
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
// Input element run-time data (see VertexShaderMeta::InputElement for compile-time data)
|
||||||
|
PACK_STRUCT(struct InputElement
|
||||||
|
{
|
||||||
|
byte Type; // VertexShaderMeta::InputType
|
||||||
|
byte Index;
|
||||||
|
byte Format; // PixelFormat
|
||||||
|
byte InputSlot;
|
||||||
|
uint32 AlignedByteOffset; // Fixed value or INPUT_LAYOUT_ELEMENT_ALIGN if auto
|
||||||
|
byte InputSlotClass; // INPUT_LAYOUT_ELEMENT_PER_VERTEX_DATA or INPUT_LAYOUT_ELEMENT_PER_INSTANCE_DATA
|
||||||
|
uint32 InstanceDataStepRate; // 0 if per-vertex
|
||||||
|
});
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets input layout description handle (platform dependent).
|
/// Gets input layout description handle (platform dependent).
|
||||||
|
|||||||
@@ -15,32 +15,21 @@ GPUShaderProgram* GPUShaderDX11::CreateGPUShaderProgram(ShaderStage type, const
|
|||||||
{
|
{
|
||||||
case ShaderStage::Vertex:
|
case ShaderStage::Vertex:
|
||||||
{
|
{
|
||||||
D3D11_INPUT_ELEMENT_DESC inputLayoutDesc[VERTEX_SHADER_MAX_INPUT_ELEMENTS];
|
// Load Input Layout
|
||||||
|
|
||||||
// Temporary variables
|
|
||||||
byte Type, Format, Index, InputSlot, InputSlotClass;
|
|
||||||
uint32 AlignedByteOffset, InstanceDataStepRate;
|
|
||||||
|
|
||||||
// Load Input Layout (it may be empty)
|
|
||||||
byte inputLayoutSize;
|
byte inputLayoutSize;
|
||||||
stream.ReadByte(&inputLayoutSize);
|
stream.ReadByte(&inputLayoutSize);
|
||||||
ASSERT(inputLayoutSize <= VERTEX_SHADER_MAX_INPUT_ELEMENTS);
|
ASSERT(inputLayoutSize <= VERTEX_SHADER_MAX_INPUT_ELEMENTS);
|
||||||
|
D3D11_INPUT_ELEMENT_DESC inputLayoutDesc[VERTEX_SHADER_MAX_INPUT_ELEMENTS];
|
||||||
for (int32 a = 0; a < inputLayoutSize; a++)
|
for (int32 a = 0; a < inputLayoutSize; a++)
|
||||||
{
|
{
|
||||||
// Read description
|
// Read description
|
||||||
// TODO: maybe use struct and load at once?
|
GPUShaderProgramVS::InputElement inputElement;
|
||||||
stream.ReadByte(&Type);
|
stream.Read(inputElement);
|
||||||
stream.ReadByte(&Index);
|
|
||||||
stream.ReadByte(&Format);
|
|
||||||
stream.ReadByte(&InputSlot);
|
|
||||||
stream.ReadUint32(&AlignedByteOffset);
|
|
||||||
stream.ReadByte(&InputSlotClass);
|
|
||||||
stream.ReadUint32(&InstanceDataStepRate);
|
|
||||||
|
|
||||||
// Get semantic name
|
// Get semantic name
|
||||||
const char* semanticName = nullptr;
|
const char* semanticName = nullptr;
|
||||||
// TODO: maybe use enum+mapping ?
|
// TODO: maybe use enum+mapping ?
|
||||||
switch (Type)
|
switch (inputElement.Type)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
semanticName = "POSITION";
|
semanticName = "POSITION";
|
||||||
@@ -70,7 +59,7 @@ GPUShaderProgram* GPUShaderDX11::CreateGPUShaderProgram(ShaderStage type, const
|
|||||||
semanticName = "BLENDWEIGHT";
|
semanticName = "BLENDWEIGHT";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOG(Fatal, "Invalid vertex shader element semantic type: {0}", Type);
|
LOG(Fatal, "Invalid vertex shader element semantic type: {0}", inputElement.Type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,12 +67,12 @@ GPUShaderProgram* GPUShaderDX11::CreateGPUShaderProgram(ShaderStage type, const
|
|||||||
inputLayoutDesc[a] =
|
inputLayoutDesc[a] =
|
||||||
{
|
{
|
||||||
semanticName,
|
semanticName,
|
||||||
static_cast<UINT>(Index),
|
static_cast<UINT>(inputElement.Index),
|
||||||
static_cast<DXGI_FORMAT>(Format),
|
static_cast<DXGI_FORMAT>(inputElement.Format),
|
||||||
static_cast<UINT>(InputSlot),
|
static_cast<UINT>(inputElement.InputSlot),
|
||||||
static_cast<UINT>(AlignedByteOffset),
|
static_cast<UINT>(inputElement.AlignedByteOffset),
|
||||||
static_cast<D3D11_INPUT_CLASSIFICATION>(InputSlotClass),
|
static_cast<D3D11_INPUT_CLASSIFICATION>(inputElement.InputSlotClass),
|
||||||
static_cast<UINT>(InstanceDataStepRate)
|
static_cast<UINT>(inputElement.InstanceDataStepRate)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,32 +20,21 @@ GPUShaderProgram* GPUShaderDX12::CreateGPUShaderProgram(ShaderStage type, const
|
|||||||
{
|
{
|
||||||
case ShaderStage::Vertex:
|
case ShaderStage::Vertex:
|
||||||
{
|
{
|
||||||
D3D12_INPUT_ELEMENT_DESC inputLayout[VERTEX_SHADER_MAX_INPUT_ELEMENTS];
|
|
||||||
|
|
||||||
// Temporary variables
|
|
||||||
byte Type, Format, Index, InputSlot, InputSlotClass;
|
|
||||||
uint32 AlignedByteOffset, InstanceDataStepRate;
|
|
||||||
|
|
||||||
// Load Input Layout (it may be empty)
|
// Load Input Layout (it may be empty)
|
||||||
byte inputLayoutSize;
|
byte inputLayoutSize;
|
||||||
stream.ReadByte(&inputLayoutSize);
|
stream.ReadByte(&inputLayoutSize);
|
||||||
ASSERT(inputLayoutSize <= VERTEX_SHADER_MAX_INPUT_ELEMENTS);
|
ASSERT(inputLayoutSize <= VERTEX_SHADER_MAX_INPUT_ELEMENTS);
|
||||||
|
D3D12_INPUT_ELEMENT_DESC inputLayout[VERTEX_SHADER_MAX_INPUT_ELEMENTS];
|
||||||
for (int32 a = 0; a < inputLayoutSize; a++)
|
for (int32 a = 0; a < inputLayoutSize; a++)
|
||||||
{
|
{
|
||||||
// Read description
|
// Read description
|
||||||
// TODO: maybe use struct and load at once?
|
GPUShaderProgramVS::InputElement inputElement;
|
||||||
stream.ReadByte(&Type);
|
stream.Read(inputElement);
|
||||||
stream.ReadByte(&Index);
|
|
||||||
stream.ReadByte(&Format);
|
|
||||||
stream.ReadByte(&InputSlot);
|
|
||||||
stream.ReadUint32(&AlignedByteOffset);
|
|
||||||
stream.ReadByte(&InputSlotClass);
|
|
||||||
stream.ReadUint32(&InstanceDataStepRate);
|
|
||||||
|
|
||||||
// Get semantic name
|
// Get semantic name
|
||||||
const char* semanticName = nullptr;
|
const char* semanticName = nullptr;
|
||||||
// TODO: maybe use enum+mapping ?
|
// TODO: maybe use enum+mapping ?
|
||||||
switch (Type)
|
switch (inputElement.Type)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
semanticName = "POSITION";
|
semanticName = "POSITION";
|
||||||
@@ -75,7 +64,7 @@ GPUShaderProgram* GPUShaderDX12::CreateGPUShaderProgram(ShaderStage type, const
|
|||||||
semanticName = "BLENDWEIGHT";
|
semanticName = "BLENDWEIGHT";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOG(Fatal, "Invalid vertex shader element semantic type: {0}", Type);
|
LOG(Fatal, "Invalid vertex shader element semantic type: {0}", inputElement.Type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,12 +72,12 @@ GPUShaderProgram* GPUShaderDX12::CreateGPUShaderProgram(ShaderStage type, const
|
|||||||
inputLayout[a] =
|
inputLayout[a] =
|
||||||
{
|
{
|
||||||
semanticName,
|
semanticName,
|
||||||
static_cast<UINT>(Index),
|
static_cast<UINT>(inputElement.Index),
|
||||||
static_cast<DXGI_FORMAT>(Format),
|
static_cast<DXGI_FORMAT>(inputElement.Format),
|
||||||
static_cast<UINT>(InputSlot),
|
static_cast<UINT>(inputElement.InputSlot),
|
||||||
static_cast<UINT>(AlignedByteOffset),
|
static_cast<UINT>(inputElement.AlignedByteOffset),
|
||||||
static_cast<D3D12_INPUT_CLASSIFICATION>(InputSlotClass),
|
static_cast<D3D12_INPUT_CLASSIFICATION>(inputElement.InputSlotClass),
|
||||||
static_cast<UINT>(InstanceDataStepRate)
|
static_cast<UINT>(inputElement.InstanceDataStepRate)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,9 +14,9 @@
|
|||||||
#include "Engine/Graphics/PixelFormatExtensions.h"
|
#include "Engine/Graphics/PixelFormatExtensions.h"
|
||||||
|
|
||||||
#if PLATFORM_DESKTOP
|
#if PLATFORM_DESKTOP
|
||||||
#define VULKAN_UNIFORM_RING_BUFFER_SIZE 24 * 1024 * 1024
|
#define VULKAN_UNIFORM_RING_BUFFER_SIZE (24 * 1024 * 1024)
|
||||||
#else
|
#else
|
||||||
#define VULKAN_UNIFORM_RING_BUFFER_SIZE 8 * 1024 * 1024
|
#define VULKAN_UNIFORM_RING_BUFFER_SIZE (8 * 1024 * 1024)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
UniformBufferUploaderVulkan::UniformBufferUploaderVulkan(GPUDeviceVulkan* device)
|
UniformBufferUploaderVulkan::UniformBufferUploaderVulkan(GPUDeviceVulkan* device)
|
||||||
@@ -153,10 +153,6 @@ GPUShaderProgram* GPUShaderVulkan::CreateGPUShaderProgram(ShaderStage type, cons
|
|||||||
vertexBindingDescriptions[i].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
vertexBindingDescriptions[i].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Temporary variables
|
|
||||||
byte Type, Format, Index, InputSlot, InputSlotClass;
|
|
||||||
uint32 AlignedByteOffset, InstanceDataStepRate;
|
|
||||||
|
|
||||||
// Load Input Layout (it may be empty)
|
// Load Input Layout (it may be empty)
|
||||||
byte inputLayoutSize;
|
byte inputLayoutSize;
|
||||||
stream.ReadByte(&inputLayoutSize);
|
stream.ReadByte(&inputLayoutSize);
|
||||||
@@ -167,32 +163,26 @@ GPUShaderProgram* GPUShaderVulkan::CreateGPUShaderProgram(ShaderStage type, cons
|
|||||||
for (int32 a = 0; a < inputLayoutSize; a++)
|
for (int32 a = 0; a < inputLayoutSize; a++)
|
||||||
{
|
{
|
||||||
// Read description
|
// Read description
|
||||||
// TODO: maybe use struct and load at once?
|
GPUShaderProgramVS::InputElement inputElement;
|
||||||
stream.ReadByte(&Type);
|
stream.Read(inputElement);
|
||||||
stream.ReadByte(&Index);
|
|
||||||
stream.ReadByte(&Format);
|
|
||||||
stream.ReadByte(&InputSlot);
|
|
||||||
stream.ReadUint32(&AlignedByteOffset);
|
|
||||||
stream.ReadByte(&InputSlotClass);
|
|
||||||
stream.ReadUint32(&InstanceDataStepRate);
|
|
||||||
|
|
||||||
const auto size = PixelFormatExtensions::SizeInBytes((PixelFormat)Format);
|
const auto size = PixelFormatExtensions::SizeInBytes((PixelFormat)inputElement.Format);
|
||||||
if (AlignedByteOffset != INPUT_LAYOUT_ELEMENT_ALIGN)
|
if (inputElement.AlignedByteOffset != INPUT_LAYOUT_ELEMENT_ALIGN)
|
||||||
offset = AlignedByteOffset;
|
offset = inputElement.AlignedByteOffset;
|
||||||
|
|
||||||
auto& vertexBindingDescription = vertexBindingDescriptions[InputSlot];
|
auto& vertexBindingDescription = vertexBindingDescriptions[inputElement.InputSlot];
|
||||||
vertexBindingDescription.binding = InputSlot;
|
vertexBindingDescription.binding = inputElement.InputSlot;
|
||||||
vertexBindingDescription.stride = Math::Max(vertexBindingDescription.stride, (uint32_t)(offset + size));
|
vertexBindingDescription.stride = Math::Max(vertexBindingDescription.stride, (uint32_t)(offset + size));
|
||||||
vertexBindingDescription.inputRate = InputSlotClass == INPUT_LAYOUT_ELEMENT_PER_VERTEX_DATA ? VK_VERTEX_INPUT_RATE_VERTEX : VK_VERTEX_INPUT_RATE_INSTANCE;
|
vertexBindingDescription.inputRate = inputElement.InputSlotClass == INPUT_LAYOUT_ELEMENT_PER_VERTEX_DATA ? VK_VERTEX_INPUT_RATE_VERTEX : VK_VERTEX_INPUT_RATE_INSTANCE;
|
||||||
ASSERT(InstanceDataStepRate == 0 || InstanceDataStepRate == 1);
|
ASSERT(inputElement.InstanceDataStepRate == 0 || inputElement.InstanceDataStepRate == 1);
|
||||||
|
|
||||||
auto& vertexAttributeDescription = vertexAttributeDescriptions[a];
|
auto& vertexAttributeDescription = vertexAttributeDescriptions[a];
|
||||||
vertexAttributeDescription.location = a;
|
vertexAttributeDescription.location = a;
|
||||||
vertexAttributeDescription.binding = InputSlot;
|
vertexAttributeDescription.binding = inputElement.InputSlot;
|
||||||
vertexAttributeDescription.format = RenderToolsVulkan::ToVulkanFormat((PixelFormat)Format);
|
vertexAttributeDescription.format = RenderToolsVulkan::ToVulkanFormat((PixelFormat)inputElement.Format);
|
||||||
vertexAttributeDescription.offset = offset;
|
vertexAttributeDescription.offset = offset;
|
||||||
|
|
||||||
bindingsCount = Math::Max(bindingsCount, (uint32)InputSlot + 1);
|
bindingsCount = Math::Max(bindingsCount, (uint32)inputElement.InputSlot + 1);
|
||||||
offset += size;
|
offset += size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -460,16 +460,15 @@ bool ShaderCompiler::WriteCustomDataVS(ShaderCompilationContext* context, Shader
|
|||||||
auto& element = layout[a];
|
auto& element = layout[a];
|
||||||
if (!layoutVisible[a])
|
if (!layoutVisible[a])
|
||||||
continue;
|
continue;
|
||||||
|
GPUShaderProgramVS::InputElement data;
|
||||||
// TODO: serialize whole struct?
|
data.Type = static_cast<byte>(element.Type);
|
||||||
|
data.Index = element.Index;
|
||||||
output->WriteByte(static_cast<byte>(element.Type));
|
data.Format = static_cast<byte>(element.Format);
|
||||||
output->WriteByte(element.Index);
|
data.InputSlot = element.InputSlot;
|
||||||
output->WriteByte(static_cast<byte>(element.Format));
|
data.AlignedByteOffset = element.AlignedByteOffset;
|
||||||
output->WriteByte(element.InputSlot);
|
data.InputSlotClass = element.InputSlotClass;
|
||||||
output->WriteUint32(element.AlignedByteOffset);
|
data.InstanceDataStepRate = element.InstanceDataStepRate;
|
||||||
output->WriteByte(element.InputSlotClass);
|
output->Write(data);
|
||||||
output->WriteUint32(element.InstanceDataStepRate);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
Reference in New Issue
Block a user