Fix vertex layouts binding to match vertex shader inputs on WebGPU
This commit is contained in:
@@ -41,7 +41,6 @@ GPUContextWebGPU::GPUContextWebGPU(GPUDeviceWebGPU* device)
|
||||
: GPUContext(device)
|
||||
, _device(device)
|
||||
{
|
||||
_vertexBufferNullLayout = WGPU_VERTEX_BUFFER_LAYOUT_INIT;
|
||||
_minUniformBufferOffsetAlignment = device->MinUniformBufferOffsetAlignment;
|
||||
|
||||
// Setup descriptor handles tables lookup cache
|
||||
@@ -307,14 +306,13 @@ void GPUContextWebGPU::BindVB(const Span<GPUBuffer*>& vertexBuffers, const uint3
|
||||
ASSERT(vertexBuffers.Length() <= GPU_MAX_VB_BINDED);
|
||||
_vertexBufferDirty = true;
|
||||
_vertexBufferCount = vertexBuffers.Length();
|
||||
_pipelineKey.VertexBufferCount = vertexBuffers.Length();
|
||||
_pipelineKey.VertexLayout = (GPUVertexLayoutWebGPU*)(vertexLayout ? vertexLayout : GPUVertexLayout::Get(vertexBuffers));
|
||||
for (int32 i = 0; i < vertexBuffers.Length(); i++)
|
||||
{
|
||||
auto vbWebGPU = (GPUBufferWebGPU*)vertexBuffers.Get()[i];
|
||||
_vertexBuffers[i].Buffer = vbWebGPU ? vbWebGPU->Buffer : nullptr;
|
||||
_vertexBuffers[i].Offset = vertexBuffersOffsets ? vertexBuffersOffsets[i] : 0;
|
||||
_vertexBuffers[i].Size = vbWebGPU ? vbWebGPU->GetSize() : 0;
|
||||
_pipelineKey.VertexBuffers[i] = vbWebGPU && vbWebGPU->GetVertexLayout() ? &((GPUVertexLayoutWebGPU*)vbWebGPU->GetVertexLayout())->Layout : &_vertexBufferNullLayout;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,6 @@ private:
|
||||
};
|
||||
|
||||
GPUDeviceWebGPU* _device;
|
||||
WGPUVertexBufferLayout _vertexBufferNullLayout;
|
||||
uint32 _minUniformBufferOffsetAlignment;
|
||||
Array<WGPUBindGroupEntry> _bindGroupEntries;
|
||||
Array<uint32> _dynamicOffsets;
|
||||
|
||||
@@ -4,9 +4,11 @@
|
||||
|
||||
#include "GPUPipelineStateWebGPU.h"
|
||||
#include "GPUVertexLayoutWebGPU.h"
|
||||
#include "RenderToolsWebGPU.h"
|
||||
#include "Engine/Core/Log.h"
|
||||
#include "Engine/Profiler/ProfilerCPU.h"
|
||||
#include "Engine/Profiler/ProfilerMemory.h"
|
||||
#include "Engine/Graphics/PixelFormatExtensions.h"
|
||||
|
||||
WGPUCompareFunction ToCompareFunction(ComparisonFunc value)
|
||||
{
|
||||
@@ -179,15 +181,53 @@ WGPURenderPipeline GPUPipelineStateWebGPU::GetPipeline(const Key& key)
|
||||
for (int32 i = 0; i < _fragmentDesc.targetCount; i++)
|
||||
_colorTargets[i].format = (WGPUTextureFormat)key.RenderTargetFormats[i];
|
||||
WGPUVertexBufferLayout buffers[GPU_MAX_VB_BINDED];
|
||||
PipelineDesc.vertex.bufferCount = key.VertexBufferCount;
|
||||
int32 shaderLocation = 0;
|
||||
for (int32 i = 0; i < PipelineDesc.vertex.bufferCount; i++)
|
||||
if (key.VertexLayout)
|
||||
{
|
||||
buffers[i] = *key.VertexBuffers[i];
|
||||
for (int32 j = 0; j < buffers[i].attributeCount; j++)
|
||||
((WGPUVertexAttribute&)buffers[i].attributes[j]).shaderLocation = shaderLocation++;
|
||||
// Combine input layout of Vertex Buffers with the destination layout used by the Vertex Shader
|
||||
GPUVertexLayoutWebGPU* mergedVertexLayout = key.VertexLayout;
|
||||
if (!mergedVertexLayout)
|
||||
mergedVertexLayout = (GPUVertexLayoutWebGPU*)VS->Layout; // Fallback to shader-specified layout (if using old APIs)
|
||||
if (VS->InputLayout)
|
||||
mergedVertexLayout = (GPUVertexLayoutWebGPU*)GPUVertexLayout::Merge(mergedVertexLayout, VS->InputLayout, false, true, -1, true);
|
||||
|
||||
// Build attributes list
|
||||
WGPUVertexAttribute attributes[GPU_MAX_VS_ELEMENTS];
|
||||
PipelineDesc.vertex.bufferCount = 0;
|
||||
PipelineDesc.vertex.buffers = buffers;
|
||||
int32 attributeIndex = 0;
|
||||
auto& elements = mergedVertexLayout->GetElements();
|
||||
for (int32 bufferIndex = 0; bufferIndex < GPU_MAX_VB_BINDED; bufferIndex++)
|
||||
{
|
||||
auto& buffer = buffers[bufferIndex];
|
||||
buffer.nextInChain = nullptr;
|
||||
buffer.stepMode = WGPUVertexStepMode_Vertex;
|
||||
buffer.arrayStride = 0;
|
||||
buffer.attributeCount = 0;
|
||||
buffer.attributes = attributes + attributeIndex;
|
||||
for (int32 i = 0; i < elements.Count(); i++)
|
||||
{
|
||||
const VertexElement& element = elements[i];
|
||||
if (element.Slot != bufferIndex)
|
||||
continue;
|
||||
WGPUVertexAttribute& dst = attributes[attributeIndex++];
|
||||
buffer.attributeCount++;
|
||||
dst.nextInChain = nullptr;
|
||||
dst.format = RenderToolsWebGPU::ToVertexFormat(element.Format);
|
||||
dst.offset = element.Offset;
|
||||
dst.shaderLocation = i; // Elements are sorted to match Input Layout order of Vertex Shader as provided by GPUVertexLayout::Merge
|
||||
if (element.PerInstance)
|
||||
buffer.stepMode = WGPUVertexStepMode_Instance;
|
||||
buffer.arrayStride = Math::Max<uint64>(buffer.arrayStride, element.Offset + PixelFormatExtensions::SizeInBytes(element.Format));
|
||||
PipelineDesc.vertex.bufferCount = Math::Max<size_t>(PipelineDesc.vertex.bufferCount, bufferIndex + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// No vertex input
|
||||
PipelineDesc.vertex.bufferCount = 0;
|
||||
PipelineDesc.vertex.buffers = nullptr;
|
||||
}
|
||||
PipelineDesc.vertex.buffers = buffers;
|
||||
|
||||
// Create object
|
||||
pipeline = wgpuDeviceCreateRenderPipeline(_device->Device, &PipelineDesc);
|
||||
@@ -280,9 +320,10 @@ bool GPUPipelineStateWebGPU::Init(const Description& desc)
|
||||
if (EnumHasAllFlags(desc.BlendMode.RenderTargetWriteMask, BlendingMode::ColorWrite::Alpha))
|
||||
writeMask |= WGPUColorWriteMask_Alpha;
|
||||
}
|
||||
if (PS)
|
||||
if (desc.PS)
|
||||
{
|
||||
for (int32 rtIndex = 0; rtIndex < PS->GetBindings().OutputsCount; rtIndex++)
|
||||
uint16 outputsCount = desc.PS->GetBindings().OutputsCount;
|
||||
for (uint16 rtIndex = 0; rtIndex < outputsCount; rtIndex++)
|
||||
_colorTargets[rtIndex].writeMask = writeMask;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,9 +25,8 @@ public:
|
||||
uint16 DepthStencilFormat : 7;
|
||||
uint16 MultiSampleCount : 3;
|
||||
uint16 RenderTargetCount : 3;
|
||||
uint16 VertexBufferCount : 3;
|
||||
uint8 RenderTargetFormats[GPU_MAX_RT_BINDED];
|
||||
struct WGPUVertexBufferLayout* VertexBuffers[GPU_MAX_VB_BINDED];
|
||||
class GPUVertexLayoutWebGPU* VertexLayout;
|
||||
};
|
||||
uint64 Packed[4];
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user