Refactor Vertex Shader input vertex layout to use GPUVertexLayout defined on Vertex Buffer rather than Vertex Shader
#3044 #2667
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
#include "GPUBufferVulkan.h"
|
||||
#include "GPUShaderVulkan.h"
|
||||
#include "GPUSamplerVulkan.h"
|
||||
#include "GPUVertexLayoutVulkan.h"
|
||||
#include "GPUPipelineStateVulkan.h"
|
||||
#include "Engine/Profiler/RenderStats.h"
|
||||
#include "GPUShaderProgramVulkan.h"
|
||||
@@ -650,8 +651,14 @@ void GPUContextVulkan::OnDrawCall()
|
||||
}
|
||||
|
||||
// Bind any missing vertex buffers to null if required by the current state
|
||||
const auto vertexInputState = pipelineState->GetVertexInputState();
|
||||
const int32 missingVBs = vertexInputState->vertexBindingDescriptionCount - _vbCount;
|
||||
GPUVertexLayoutVulkan* vertexLayout = _vertexLayout ? _vertexLayout : pipelineState->VertexShaderLayout;
|
||||
#if GPU_ENABLE_ASSERTION_LOW_LAYERS
|
||||
if (!vertexLayout && pipelineState && !pipelineState->VertexShaderLayout && (pipelineState->UsedStagesMask & (1 << (int32)DescriptorSet::Vertex)) != 0 && !_vertexLayout && _vbCount)
|
||||
{
|
||||
LOG(Error, "Missing Vertex Layout (not assigned to GPUBuffer). Vertex Shader won't read valid data resulting incorrect visuals.");
|
||||
}
|
||||
#endif
|
||||
const int32 missingVBs = vertexLayout ? (int32)vertexLayout->CreateInfo.vertexBindingDescriptionCount - _vbCount : 0;
|
||||
if (missingVBs > 0)
|
||||
{
|
||||
VkBuffer buffers[GPU_MAX_VB_BINDED];
|
||||
@@ -676,7 +683,7 @@ void GPUContextVulkan::OnDrawCall()
|
||||
{
|
||||
_psDirtyFlag = false;
|
||||
const auto cmdBuffer = _cmdBufferManager->GetCmdBuffer();
|
||||
const auto pipeline = pipelineState->GetState(_renderPass);
|
||||
const auto pipeline = pipelineState->GetState(_renderPass, _vertexLayout);
|
||||
vkCmdBindPipeline(cmdBuffer->GetHandle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
||||
RENDER_STAT_PS_STATE_CHANGE();
|
||||
}
|
||||
@@ -715,6 +722,7 @@ void GPUContextVulkan::FrameBegin()
|
||||
_stencilRef = 0;
|
||||
_renderPass = nullptr;
|
||||
_currentState = nullptr;
|
||||
_vertexLayout = nullptr;
|
||||
_rtDepth = nullptr;
|
||||
Platform::MemoryClear(_rtHandles, sizeof(_rtHandles));
|
||||
Platform::MemoryClear(_cbHandles, sizeof(_cbHandles));
|
||||
@@ -1023,9 +1031,10 @@ void GPUContextVulkan::BindUA(int32 slot, GPUResourceView* view)
|
||||
}
|
||||
}
|
||||
|
||||
void GPUContextVulkan::BindVB(const Span<GPUBuffer*>& vertexBuffers, const uint32* vertexBuffersOffsets)
|
||||
void GPUContextVulkan::BindVB(const Span<GPUBuffer*>& vertexBuffers, const uint32* vertexBuffersOffsets, GPUVertexLayout* vertexLayout)
|
||||
{
|
||||
_vbCount = vertexBuffers.Length();
|
||||
_vertexLayout = (GPUVertexLayoutVulkan*)(vertexLayout ? vertexLayout : GPUVertexLayout::Get(vertexBuffers));
|
||||
if (vertexBuffers.Length() == 0)
|
||||
return;
|
||||
const auto cmdBuffer = _cmdBufferManager->GetCmdBuffer();
|
||||
|
||||
@@ -14,6 +14,7 @@ class CmdBufferManagerVulkan;
|
||||
class ResourceOwnerVulkan;
|
||||
class GPUTextureViewVulkan;
|
||||
class GPUBufferVulkan;
|
||||
class GPUVertexLayoutVulkan;
|
||||
class GPUPipelineStateVulkan;
|
||||
class ComputePipelineStateVulkan;
|
||||
class GPUConstantBufferVulkan;
|
||||
@@ -82,6 +83,7 @@ private:
|
||||
|
||||
RenderPassVulkan* _renderPass;
|
||||
GPUPipelineStateVulkan* _currentState;
|
||||
GPUVertexLayoutVulkan* _vertexLayout;
|
||||
GPUTextureViewVulkan* _rtDepth;
|
||||
GPUTextureViewVulkan* _rtHandles[GPU_MAX_RT_BINDED];
|
||||
DescriptorOwnerResourceVulkan* _cbHandles[GPU_MAX_CB_BINDED];
|
||||
@@ -168,7 +170,7 @@ public:
|
||||
void BindCB(int32 slot, GPUConstantBuffer* cb) override;
|
||||
void BindSR(int32 slot, GPUResourceView* view) override;
|
||||
void BindUA(int32 slot, GPUResourceView* view) override;
|
||||
void BindVB(const Span<GPUBuffer*>& vertexBuffers, const uint32* vertexBuffersOffsets = nullptr) override;
|
||||
void BindVB(const Span<GPUBuffer*>& vertexBuffers, const uint32* vertexBuffersOffsets = nullptr, GPUVertexLayout* vertexLayout = nullptr) override;
|
||||
void BindIB(GPUBuffer* indexBuffer) override;
|
||||
void BindSampler(int32 slot, GPUSampler* sampler) override;
|
||||
void UpdateCB(GPUConstantBuffer* cb, const void* data) override;
|
||||
|
||||
@@ -922,10 +922,10 @@ GPUTextureVulkan* HelperResourcesVulkan::GetDummyTexture(SpirvShaderResourceType
|
||||
|
||||
GPUBufferVulkan* HelperResourcesVulkan::GetDummyBuffer(PixelFormat format)
|
||||
{
|
||||
if (_dummyBuffers.IsEmpty())
|
||||
if (!_dummyBuffers)
|
||||
{
|
||||
_dummyBuffers.Resize((int32)PixelFormat::MAX);
|
||||
Platform::MemoryClear((void*)_dummyBuffers.Get(), (int32)PixelFormat::MAX * sizeof(void*));
|
||||
_dummyBuffers = (GPUBufferVulkan**)Allocator::Allocate((int32)PixelFormat::MAX * sizeof(void*));
|
||||
Platform::MemoryClear(_dummyBuffers, (int32)PixelFormat::MAX * sizeof(void*));
|
||||
}
|
||||
auto& dummyBuffer = _dummyBuffers[(int32)format];
|
||||
if (!dummyBuffer)
|
||||
@@ -941,7 +941,7 @@ GPUBufferVulkan* HelperResourcesVulkan::GetDummyVertexBuffer()
|
||||
if (!_dummyVB)
|
||||
{
|
||||
_dummyVB = (GPUBufferVulkan*)_device->CreateBuffer(TEXT("DummyVertexBuffer"));
|
||||
_dummyVB->Init(GPUBufferDescription::Vertex(sizeof(Color32), 1, &Color32::Transparent));
|
||||
_dummyVB->Init(GPUBufferDescription::Vertex(nullptr, sizeof(Color32), 1, &Color32::Transparent));
|
||||
}
|
||||
return _dummyVB;
|
||||
}
|
||||
@@ -950,9 +950,16 @@ void HelperResourcesVulkan::Dispose()
|
||||
{
|
||||
SAFE_DELETE_GPU_RESOURCES(_dummyTextures);
|
||||
SAFE_DELETE_GPU_RESOURCE(_dummyVB);
|
||||
for (GPUBuffer* buffer : _dummyBuffers)
|
||||
Delete(buffer);
|
||||
_dummyBuffers.Clear();
|
||||
if (_dummyBuffers)
|
||||
{
|
||||
for (int32 i = 0; i < (int32)PixelFormat::MAX; i++)
|
||||
{
|
||||
if (GPUBufferVulkan* buffer = _dummyBuffers[i])
|
||||
Delete(buffer);
|
||||
}
|
||||
Allocator::Free(_dummyBuffers);
|
||||
_dummyBuffers = nullptr;
|
||||
}
|
||||
|
||||
for (int32 i = 0; i < ARRAY_COUNT(_staticSamplers); i++)
|
||||
{
|
||||
|
||||
@@ -308,7 +308,7 @@ class HelperResourcesVulkan
|
||||
private:
|
||||
GPUDeviceVulkan* _device;
|
||||
GPUTextureVulkan* _dummyTextures[6];
|
||||
Array<GPUBufferVulkan*> _dummyBuffers;
|
||||
GPUBufferVulkan** _dummyBuffers = nullptr;
|
||||
GPUBufferVulkan* _dummyVB;
|
||||
VkSampler _staticSamplers[GPU_STATIC_SAMPLERS_COUNT];
|
||||
|
||||
|
||||
@@ -3,10 +3,12 @@
|
||||
#if GRAPHICS_API_VULKAN
|
||||
|
||||
#include "GPUPipelineStateVulkan.h"
|
||||
#include "GPUVertexLayoutVulkan.h"
|
||||
#include "RenderToolsVulkan.h"
|
||||
#include "DescriptorSetVulkan.h"
|
||||
#include "GPUShaderProgramVulkan.h"
|
||||
#include "Engine/Core/Log.h"
|
||||
#include "Engine/Core/Types/Pair.h"
|
||||
#include "Engine/Profiler/ProfilerCPU.h"
|
||||
|
||||
static VkStencilOp ToVulkanStencilOp(const StencilOperation value)
|
||||
@@ -169,7 +171,6 @@ ComputePipelineStateVulkan::~ComputePipelineStateVulkan()
|
||||
|
||||
GPUPipelineStateVulkan::GPUPipelineStateVulkan(GPUDeviceVulkan* device)
|
||||
: GPUResourceVulkan<GPUPipelineState>(device, StringView::Empty)
|
||||
, _pipelines(16)
|
||||
, _layout(nullptr)
|
||||
{
|
||||
}
|
||||
@@ -201,25 +202,30 @@ PipelineLayoutVulkan* GPUPipelineStateVulkan::GetLayout()
|
||||
return _layout;
|
||||
}
|
||||
|
||||
VkPipeline GPUPipelineStateVulkan::GetState(RenderPassVulkan* renderPass)
|
||||
VkPipeline GPUPipelineStateVulkan::GetState(RenderPassVulkan* renderPass, GPUVertexLayoutVulkan* vertexLayout)
|
||||
{
|
||||
ASSERT(renderPass);
|
||||
if (!vertexLayout)
|
||||
vertexLayout = VertexShaderLayout;
|
||||
|
||||
// Try reuse cached version
|
||||
VkPipeline pipeline = VK_NULL_HANDLE;
|
||||
if (_pipelines.TryGet(renderPass, pipeline))
|
||||
const Pair<RenderPassVulkan*, GPUVertexLayoutVulkan*> key(renderPass, vertexLayout);
|
||||
if (_pipelines.TryGet(key, pipeline))
|
||||
{
|
||||
#if BUILD_DEBUG
|
||||
// Verify
|
||||
RenderPassVulkan* refKey = nullptr;
|
||||
Pair<RenderPassVulkan*, GPUVertexLayoutVulkan*> refKey(nullptr, nullptr);
|
||||
_pipelines.KeyOf(pipeline, &refKey);
|
||||
ASSERT(refKey == renderPass);
|
||||
ASSERT(refKey == key);
|
||||
#endif
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
PROFILE_CPU_NAMED("Create Pipeline");
|
||||
|
||||
// Bind vertex input
|
||||
_desc.pVertexInputState = vertexLayout ? &vertexLayout->CreateInfo : nullptr;
|
||||
|
||||
// Update description to match the pipeline
|
||||
_descColorBlend.attachmentCount = renderPass->Layout.RTsCount;
|
||||
_descMultisample.rasterizationSamples = (VkSampleCountFlagBits)renderPass->Layout.MSAA;
|
||||
@@ -245,7 +251,7 @@ VkPipeline GPUPipelineStateVulkan::GetState(RenderPassVulkan* renderPass)
|
||||
}
|
||||
|
||||
// Cache it
|
||||
_pipelines.Add(renderPass, pipeline);
|
||||
_pipelines.Add(key, pipeline);
|
||||
|
||||
return pipeline;
|
||||
}
|
||||
@@ -278,12 +284,9 @@ bool GPUPipelineStateVulkan::Init(const Description& desc)
|
||||
{
|
||||
ASSERT(!IsValid());
|
||||
|
||||
// Create description
|
||||
// Reset description
|
||||
RenderToolsVulkan::ZeroStruct(_desc, VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO);
|
||||
|
||||
// Vertex Input
|
||||
_desc.pVertexInputState = (VkPipelineVertexInputStateCreateInfo*)desc.VS->GetInputLayout();
|
||||
|
||||
// Stages
|
||||
UsedStagesMask = 0;
|
||||
HasDescriptorsPerStageMask = 0;
|
||||
@@ -318,6 +321,7 @@ bool GPUPipelineStateVulkan::Init(const Description& desc)
|
||||
_desc.pStages = _shaderStages;
|
||||
|
||||
// Input Assembly
|
||||
VertexShaderLayout = desc.VS ? (GPUVertexLayoutVulkan*)desc.VS->Layout : nullptr;
|
||||
RenderToolsVulkan::ZeroStruct(_descInputAssembly, VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO);;
|
||||
switch (desc.PrimitiveTopology)
|
||||
{
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#if GRAPHICS_API_VULKAN
|
||||
|
||||
class GPUVertexLayoutVulkan;
|
||||
class PipelineLayoutVulkan;
|
||||
|
||||
class ComputePipelineStateVulkan
|
||||
@@ -89,7 +90,7 @@ public:
|
||||
class GPUPipelineStateVulkan : public GPUResourceVulkan<GPUPipelineState>
|
||||
{
|
||||
private:
|
||||
Dictionary<RenderPassVulkan*, VkPipeline> _pipelines;
|
||||
Dictionary<Pair<RenderPassVulkan*, GPUVertexLayoutVulkan*>, VkPipeline> _pipelines;
|
||||
VkGraphicsPipelineCreateInfo _desc;
|
||||
VkPipelineShaderStageCreateInfo _shaderStages[ShaderStage_Count - 1];
|
||||
VkPipelineInputAssemblyStateCreateInfo _descInputAssembly;
|
||||
@@ -140,18 +141,13 @@ public:
|
||||
/// </summary>
|
||||
const SpirvShaderDescriptorInfo* DescriptorInfoPerStage[DescriptorSet::GraphicsStagesCount];
|
||||
|
||||
const VkPipelineVertexInputStateCreateInfo* GetVertexInputState() const
|
||||
{
|
||||
return _desc.pVertexInputState;
|
||||
}
|
||||
|
||||
DescriptorSetWriteContainerVulkan DSWriteContainer;
|
||||
DescriptorSetWriterVulkan DSWriter[DescriptorSet::GraphicsStagesCount];
|
||||
|
||||
const DescriptorSetLayoutVulkan* DescriptorSetsLayout = nullptr;
|
||||
TypedDescriptorPoolSetVulkan* CurrentTypedDescriptorPoolSet = nullptr;
|
||||
GPUVertexLayoutVulkan* VertexShaderLayout = nullptr;
|
||||
Array<VkDescriptorSet> DescriptorSetHandles;
|
||||
|
||||
Array<uint32> DynamicOffsets;
|
||||
|
||||
public:
|
||||
@@ -184,8 +180,9 @@ public:
|
||||
/// Gets the Vulkan graphics pipeline object for the given rendering state. Uses depth buffer and render targets formats and multi-sample levels to setup a proper PSO. Uses caching.
|
||||
/// </summary>
|
||||
/// <param name="renderPass">The render pass.</param>
|
||||
/// <param name="vertexLayout">The vertex layout.</param>
|
||||
/// <returns>Vulkan graphics pipeline object.</returns>
|
||||
VkPipeline GetState(RenderPassVulkan* renderPass);
|
||||
VkPipeline GetState(RenderPassVulkan* renderPass, GPUVertexLayoutVulkan* vertexLayout);
|
||||
|
||||
public:
|
||||
// [GPUPipelineState]
|
||||
|
||||
@@ -21,13 +21,6 @@ protected:
|
||||
GPUDeviceVulkan* _device;
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GPUShaderProgramVulkan"/> class.
|
||||
/// </summary>
|
||||
/// <param name="device">The graphics device.</param>
|
||||
/// <param name="initializer">The program initialization data.</param>
|
||||
/// <param name="descriptorInfo">The program descriptors usage info.</param>
|
||||
/// <param name="shaderModule">The shader module object.</param>
|
||||
GPUShaderProgramVulkan(GPUDeviceVulkan* device, const GPUShaderProgramInitializer& initializer, const SpirvShaderDescriptorInfo& descriptorInfo, VkShaderModule shaderModule)
|
||||
: _device(device)
|
||||
, ShaderModule(shaderModule)
|
||||
@@ -36,9 +29,6 @@ public:
|
||||
BaseType::Init(initializer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finalizes an instance of the <see cref="GPUShaderProgramVulkan"/> class.
|
||||
/// </summary>
|
||||
~GPUShaderProgramVulkan()
|
||||
{
|
||||
if (ShaderModule)
|
||||
@@ -64,7 +54,6 @@ public:
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* GetBufferHandle() const override
|
||||
{
|
||||
return (void*)ShaderModule;
|
||||
@@ -77,33 +66,10 @@ public:
|
||||
class GPUShaderProgramVSVulkan : public GPUShaderProgramVulkan<GPUShaderProgramVS>
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GPUShaderProgramVSVulkan"/> class.
|
||||
/// </summary>
|
||||
/// <param name="device">The graphics device.</param>
|
||||
/// <param name="initializer">The program initialization data.</param>
|
||||
/// <param name="descriptorInfo">The program descriptors usage info.</param>
|
||||
/// <param name="shaderModule">The shader module object.</param>
|
||||
GPUShaderProgramVSVulkan(GPUDeviceVulkan* device, const GPUShaderProgramInitializer& initializer, const SpirvShaderDescriptorInfo& descriptorInfo, VkShaderModule shaderModule)
|
||||
GPUShaderProgramVSVulkan(GPUDeviceVulkan* device, const GPUShaderProgramInitializer& initializer, const SpirvShaderDescriptorInfo& descriptorInfo, VkShaderModule shaderModule, GPUVertexLayout* vertexLayout)
|
||||
: GPUShaderProgramVulkan(device, initializer, descriptorInfo, shaderModule)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
VkPipelineVertexInputStateCreateInfo VertexInputState;
|
||||
VkVertexInputBindingDescription VertexBindingDescriptions[VERTEX_SHADER_MAX_INPUT_ELEMENTS];
|
||||
VkVertexInputAttributeDescription VertexAttributeDescriptions[VERTEX_SHADER_MAX_INPUT_ELEMENTS];
|
||||
|
||||
public:
|
||||
// [GPUShaderProgramVulkan]
|
||||
void* GetInputLayout() const override
|
||||
{
|
||||
return (void*)&VertexInputState;
|
||||
}
|
||||
|
||||
byte GetInputLayoutSize() const override
|
||||
{
|
||||
return 0;
|
||||
Layout = vertexLayout;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -114,14 +80,6 @@ public:
|
||||
class GPUShaderProgramHSVulkan : public GPUShaderProgramVulkan<GPUShaderProgramHS>
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GPUShaderProgramHSVulkan"/> class.
|
||||
/// </summary>
|
||||
/// <param name="device">The graphics device.</param>
|
||||
/// <param name="initializer">The program initialization data.</param>
|
||||
/// <param name="descriptorInfo">The program descriptors usage info.</param>
|
||||
/// <param name="shaderModule">The shader module object.</param>
|
||||
/// <param name="controlPointsCount">The control points used by the hull shader for processing.</param>
|
||||
GPUShaderProgramHSVulkan(GPUDeviceVulkan* device, const GPUShaderProgramInitializer& initializer, const SpirvShaderDescriptorInfo& descriptorInfo, VkShaderModule shaderModule, int32 controlPointsCount)
|
||||
: GPUShaderProgramVulkan(device, initializer, descriptorInfo, shaderModule)
|
||||
{
|
||||
@@ -135,13 +93,6 @@ public:
|
||||
class GPUShaderProgramDSVulkan : public GPUShaderProgramVulkan<GPUShaderProgramDS>
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GPUShaderProgramDSVulkan"/> class.
|
||||
/// </summary>
|
||||
/// <param name="device">The graphics device.</param>
|
||||
/// <param name="initializer">The program initialization data.</param>
|
||||
/// <param name="descriptorInfo">The program descriptors usage info.</param>
|
||||
/// <param name="shaderModule">The shader module object.</param>
|
||||
GPUShaderProgramDSVulkan(GPUDeviceVulkan* device, const GPUShaderProgramInitializer& initializer, const SpirvShaderDescriptorInfo& descriptorInfo, VkShaderModule shaderModule)
|
||||
: GPUShaderProgramVulkan(device, initializer, descriptorInfo, shaderModule)
|
||||
{
|
||||
@@ -156,13 +107,6 @@ public:
|
||||
class GPUShaderProgramGSVulkan : public GPUShaderProgramVulkan<GPUShaderProgramGS>
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GPUShaderProgramGSVulkan"/> class.
|
||||
/// </summary>
|
||||
/// <param name="device">The graphics device.</param>
|
||||
/// <param name="initializer">The program initialization data.</param>
|
||||
/// <param name="descriptorInfo">The program descriptors usage info.</param>
|
||||
/// <param name="shaderModule">The shader module object.</param>
|
||||
GPUShaderProgramGSVulkan(GPUDeviceVulkan* device, const GPUShaderProgramInitializer& initializer, const SpirvShaderDescriptorInfo& descriptorInfo, VkShaderModule shaderModule)
|
||||
: GPUShaderProgramVulkan(device, initializer, descriptorInfo, shaderModule)
|
||||
{
|
||||
@@ -176,13 +120,6 @@ public:
|
||||
class GPUShaderProgramPSVulkan : public GPUShaderProgramVulkan<GPUShaderProgramPS>
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GPUShaderProgramPSVulkan"/> class.
|
||||
/// </summary>
|
||||
/// <param name="device">The graphics device.</param>
|
||||
/// <param name="initializer">The program initialization data.</param>
|
||||
/// <param name="descriptorInfo">The program descriptors usage info.</param>
|
||||
/// <param name="shaderModule">The shader module object.</param>
|
||||
GPUShaderProgramPSVulkan(GPUDeviceVulkan* device, const GPUShaderProgramInitializer& initializer, const SpirvShaderDescriptorInfo& descriptorInfo, VkShaderModule shaderModule)
|
||||
: GPUShaderProgramVulkan(device, initializer, descriptorInfo, shaderModule)
|
||||
{
|
||||
@@ -198,29 +135,18 @@ private:
|
||||
ComputePipelineStateVulkan* _pipelineState;
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GPUShaderProgramCSVulkan"/> class.
|
||||
/// </summary>
|
||||
/// <param name="device">The graphics device.</param>
|
||||
/// <param name="initializer">The program initialization data.</param>
|
||||
/// <param name="descriptorInfo">The program descriptors usage info.</param>
|
||||
/// <param name="shaderModule">The shader module object.</param>
|
||||
GPUShaderProgramCSVulkan(GPUDeviceVulkan* device, const GPUShaderProgramInitializer& initializer, const SpirvShaderDescriptorInfo& descriptorInfo, VkShaderModule shaderModule)
|
||||
: GPUShaderProgramVulkan(device, initializer, descriptorInfo, shaderModule)
|
||||
, _pipelineState(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finalizes an instance of the <see cref="GPUShaderProgramCSVulkan"/> class.
|
||||
/// </summary>
|
||||
~GPUShaderProgramCSVulkan();
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Gets the state of the pipeline for the compute shader execution or creates a new one if missing.
|
||||
/// </summary>
|
||||
/// <returns>The compute pipeline state.</returns>
|
||||
ComputePipelineStateVulkan* GetOrCreateState();
|
||||
};
|
||||
|
||||
|
||||
@@ -98,17 +98,16 @@ void UniformBufferUploaderVulkan::OnReleaseGPU()
|
||||
}
|
||||
}
|
||||
|
||||
GPUShaderProgram* GPUShaderVulkan::CreateGPUShaderProgram(ShaderStage type, const GPUShaderProgramInitializer& initializer, byte* cacheBytes, uint32 cacheSize, MemoryReadStream& stream)
|
||||
GPUShaderProgram* GPUShaderVulkan::CreateGPUShaderProgram(ShaderStage type, const GPUShaderProgramInitializer& initializer, Span<byte> bytecode, MemoryReadStream& stream)
|
||||
{
|
||||
// Extract the SPIR-V shader header from the cache
|
||||
SpirvShaderHeader* header = (SpirvShaderHeader*)cacheBytes;
|
||||
cacheBytes += sizeof(SpirvShaderHeader);
|
||||
cacheSize -= sizeof(SpirvShaderHeader);
|
||||
SpirvShaderHeader* header = (SpirvShaderHeader*)bytecode.Get();
|
||||
bytecode = Span<byte>(bytecode.Get() + sizeof(SpirvShaderHeader), bytecode.Length() - sizeof(SpirvShaderHeader));
|
||||
|
||||
// Extract the SPIR-V bytecode
|
||||
BytesContainer spirv;
|
||||
ASSERT(header->Type == SpirvShaderHeader::Types::Raw);
|
||||
spirv.Link(cacheBytes, cacheSize);
|
||||
spirv.Link(bytecode);
|
||||
|
||||
// Create shader module from SPIR-V bytecode
|
||||
VkShaderModule shaderModule = VK_NULL_HANDLE;
|
||||
@@ -139,59 +138,8 @@ GPUShaderProgram* GPUShaderVulkan::CreateGPUShaderProgram(ShaderStage type, cons
|
||||
{
|
||||
case ShaderStage::Vertex:
|
||||
{
|
||||
// Create object
|
||||
auto vsShader = New<GPUShaderProgramVSVulkan>(_device, initializer, header->DescriptorInfo, shaderModule);
|
||||
shader = vsShader;
|
||||
VkPipelineVertexInputStateCreateInfo& inputState = vsShader->VertexInputState;
|
||||
VkVertexInputBindingDescription* vertexBindingDescriptions = vsShader->VertexBindingDescriptions;
|
||||
VkVertexInputAttributeDescription* vertexAttributeDescriptions = vsShader->VertexAttributeDescriptions;
|
||||
RenderToolsVulkan::ZeroStruct(inputState, VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO);
|
||||
for (int32 i = 0; i < VERTEX_SHADER_MAX_INPUT_ELEMENTS; i++)
|
||||
{
|
||||
vertexBindingDescriptions[i].binding = i;
|
||||
vertexBindingDescriptions[i].stride = 0;
|
||||
vertexBindingDescriptions[i].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
||||
}
|
||||
|
||||
// Load Input Layout (it may be empty)
|
||||
byte inputLayoutSize;
|
||||
stream.ReadByte(&inputLayoutSize);
|
||||
ASSERT(inputLayoutSize <= VERTEX_SHADER_MAX_INPUT_ELEMENTS);
|
||||
uint32 attributesCount = inputLayoutSize;
|
||||
uint32 bindingsCount = 0;
|
||||
int32 offset = 0;
|
||||
for (int32 a = 0; a < inputLayoutSize; a++)
|
||||
{
|
||||
// Read description
|
||||
GPUShaderProgramVS::InputElement inputElement;
|
||||
stream.Read(inputElement);
|
||||
|
||||
const auto size = PixelFormatExtensions::SizeInBytes((PixelFormat)inputElement.Format);
|
||||
if (inputElement.AlignedByteOffset != INPUT_LAYOUT_ELEMENT_ALIGN)
|
||||
offset = inputElement.AlignedByteOffset;
|
||||
|
||||
auto& vertexBindingDescription = vertexBindingDescriptions[inputElement.InputSlot];
|
||||
vertexBindingDescription.binding = inputElement.InputSlot;
|
||||
vertexBindingDescription.stride = Math::Max(vertexBindingDescription.stride, (uint32_t)(offset + size));
|
||||
vertexBindingDescription.inputRate = inputElement.InputSlotClass == INPUT_LAYOUT_ELEMENT_PER_VERTEX_DATA ? VK_VERTEX_INPUT_RATE_VERTEX : VK_VERTEX_INPUT_RATE_INSTANCE;
|
||||
ASSERT(inputElement.InstanceDataStepRate == 0 || inputElement.InstanceDataStepRate == 1);
|
||||
|
||||
auto& vertexAttributeDescription = vertexAttributeDescriptions[a];
|
||||
vertexAttributeDescription.location = a;
|
||||
vertexAttributeDescription.binding = inputElement.InputSlot;
|
||||
vertexAttributeDescription.format = RenderToolsVulkan::ToVulkanFormat((PixelFormat)inputElement.Format);
|
||||
vertexAttributeDescription.offset = offset;
|
||||
|
||||
bindingsCount = Math::Max(bindingsCount, (uint32)inputElement.InputSlot + 1);
|
||||
offset += size;
|
||||
}
|
||||
|
||||
inputState.vertexBindingDescriptionCount = bindingsCount;
|
||||
inputState.pVertexBindingDescriptions = vertexBindingDescriptions;
|
||||
|
||||
inputState.vertexAttributeDescriptionCount = attributesCount;
|
||||
inputState.pVertexAttributeDescriptions = vertexAttributeDescriptions;
|
||||
|
||||
GPUVertexLayout* vertexLayout = ReadVertexLayout(stream);
|
||||
shader = New<GPUShaderProgramVSVulkan>(_device, initializer, header->DescriptorInfo, shaderModule, vertexLayout);
|
||||
break;
|
||||
}
|
||||
#if GPU_ALLOW_TESSELLATION_SHADERS
|
||||
|
||||
@@ -130,7 +130,7 @@ public:
|
||||
|
||||
protected:
|
||||
// [GPUShader]
|
||||
GPUShaderProgram* CreateGPUShaderProgram(ShaderStage type, const GPUShaderProgramInitializer& initializer, byte* cacheBytes, uint32 cacheSize, MemoryReadStream& stream) override;
|
||||
GPUShaderProgram* CreateGPUShaderProgram(ShaderStage type, const GPUShaderProgramInitializer& initializer, Span<byte> bytecode, MemoryReadStream& stream) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user