Various changes for WebGPU and hardware instancing support
This commit is contained in:
@@ -319,9 +319,10 @@ void GPUContextWebGPU::BindVB(const Span<GPUBuffer*>& vertexBuffers, const uint3
|
||||
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;
|
||||
if (vbWebGPU)
|
||||
_vertexBuffers[i] = { vbWebGPU->Buffer, vbWebGPU->GetSize(), vertexBuffersOffsets ? vertexBuffersOffsets[i] : 0 };
|
||||
else
|
||||
_vertexBuffers[i] = { _device->DefaultBuffer, 64, 0 }; // Fallback
|
||||
}
|
||||
}
|
||||
|
||||
@@ -969,7 +970,8 @@ void GPUContextWebGPU::FlushBindGroup()
|
||||
|
||||
// Build descriptors for the bind group
|
||||
auto entriesCount = descriptors->DescriptorTypesCount;
|
||||
_dynamicOffsets.Clear();
|
||||
uint32 dynamicOffsets[4];
|
||||
uint32 dynamicOffsetsCount = 0;
|
||||
static_assert(ARRAY_COUNT(key.Entries) == SpirvShaderDescriptorInfo::MaxDescriptors, "Invalid size of bind group entries array.");
|
||||
static_assert(ARRAY_COUNT(key.Versions) == SpirvShaderDescriptorInfo::MaxDescriptors, "Invalid size of bind group versions array.");
|
||||
key.EntriesCount = entriesCount;
|
||||
@@ -1060,7 +1062,7 @@ void GPUContextWebGPU::FlushBindGroup()
|
||||
if (descriptor.DescriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER)
|
||||
entry.offset = uniform->Allocation.Offset;
|
||||
else
|
||||
_dynamicOffsets.Add(uniform->Allocation.Offset);
|
||||
dynamicOffsets[dynamicOffsetsCount++] = uniform->Allocation.Offset;
|
||||
}
|
||||
else
|
||||
LOG(Fatal, "Missing constant buffer at slot {}", descriptor.Slot);
|
||||
@@ -1089,11 +1091,12 @@ void GPUContextWebGPU::FlushBindGroup()
|
||||
LOG(Error, " > buffer: {}", (uint32)e.buffer);
|
||||
}
|
||||
}
|
||||
ASSERT(dynamicOffsetsCount <= ARRAY_COUNT(dynamicOffsets));
|
||||
#endif
|
||||
|
||||
// Bind group
|
||||
WGPUBindGroup bindGroup = _pipelineState->GetBindGroup(key);
|
||||
wgpuRenderPassEncoderSetBindGroup(_renderPass, groupIndex, bindGroup, _dynamicOffsets.Count(), _dynamicOffsets.Get());
|
||||
wgpuRenderPassEncoderSetBindGroup(_renderPass, groupIndex, bindGroup, dynamicOffsetsCount, dynamicOffsets);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -43,19 +43,18 @@ private:
|
||||
|
||||
GPUDeviceWebGPU* _device;
|
||||
uint32 _minUniformBufferOffsetAlignment;
|
||||
Array<uint32> _dynamicOffsets;
|
||||
|
||||
// State tracking
|
||||
int32 _renderPassDirty : 1;
|
||||
int32 _pipelineDirty : 1;
|
||||
int32 _bindGroupDirty : 1;
|
||||
int32 _vertexBufferDirty : 1;
|
||||
int32 _indexBufferDirty : 1;
|
||||
int32 _indexBuffer32Bit : 1;
|
||||
int32 _blendFactorDirty : 1;
|
||||
int32 _blendFactorSet : 1;
|
||||
int32 _renderTargetCount : 4;
|
||||
int32 _vertexBufferCount : 3;
|
||||
uint32 _renderPassDirty : 1;
|
||||
uint32 _pipelineDirty : 1;
|
||||
uint32 _bindGroupDirty : 1;
|
||||
uint32 _vertexBufferDirty : 1;
|
||||
uint32 _indexBufferDirty : 1;
|
||||
uint32 _indexBuffer32Bit : 1;
|
||||
uint32 _blendFactorDirty : 1;
|
||||
uint32 _blendFactorSet : 1;
|
||||
uint32 _renderTargetCount : 4;
|
||||
uint32 _vertexBufferCount : 4;
|
||||
uint32 _stencilRef;
|
||||
Float4 _blendFactor;
|
||||
Viewport _viewport;
|
||||
|
||||
@@ -167,6 +167,7 @@ bool GPUDeviceWebGPU::Init()
|
||||
if (wgpuAdapterGetLimits(Adapter->Adapter, &limits) == WGPUStatus_Success)
|
||||
{
|
||||
MinUniformBufferOffsetAlignment = limits.minUniformBufferOffsetAlignment;
|
||||
Limits.HasInstancing = true;
|
||||
Limits.HasDrawIndirect = true;
|
||||
Limits.HasDepthAsSRV = true;
|
||||
Limits.HasReadOnlyDepth = true;
|
||||
@@ -446,7 +447,7 @@ bool GPUDeviceWebGPU::Init()
|
||||
}
|
||||
static int32 LogSpamLeft = 20;
|
||||
if (LogSpamLeft-- < 0)
|
||||
CRASH; // Too many errors
|
||||
LOG(Fatal, "Too many WebGPU errors");
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -500,7 +501,7 @@ bool GPUDeviceWebGPU::Init()
|
||||
#if GPU_ENABLE_RESOURCE_NAMING
|
||||
bufferDesc.label = WEBGPU_STR("DefaultBuffer");
|
||||
#endif
|
||||
bufferDesc.usage = WGPUBufferUsage_Storage;
|
||||
bufferDesc.usage = WGPUBufferUsage_Storage | WGPUBufferUsage_Vertex;
|
||||
bufferDesc.size = 64;
|
||||
DefaultBuffer = wgpuDeviceCreateBuffer(Device, &bufferDesc);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
|
||||
#if GRAPHICS_API_WEBGPU
|
||||
|
||||
#define WEBGPU_LOG_PSO 0
|
||||
//#define WEBGPU_LOG_PSO_NAME "PS_GBuffer" // Debug log for PSOs with specific name
|
||||
#define WEBGPU_LOG_BIND_GROUPS 0
|
||||
|
||||
#include "GPUPipelineStateWebGPU.h"
|
||||
#include "GPUTextureWebGPU.h"
|
||||
#include "GPUVertexLayoutWebGPU.h"
|
||||
@@ -12,9 +16,9 @@
|
||||
#include "Engine/Profiler/ProfilerMemory.h"
|
||||
#include "Engine/Graphics/PixelFormatExtensions.h"
|
||||
#include "Engine/Utilities/Crc.h"
|
||||
|
||||
#define WEBGPU_LOG_PSO 0
|
||||
#define WEBGPU_LOG_BIND_GROUPS 0
|
||||
#if WEBGPU_LOG_PSO
|
||||
#include "Engine/Scripting/Enums.h"
|
||||
#endif
|
||||
|
||||
WGPUCompareFunction ToCompareFunction(ComparisonFunc value)
|
||||
{
|
||||
@@ -198,6 +202,11 @@ WGPURenderPipeline GPUPipelineStateWebGPU::GetPipeline(const PipelineKey& key, G
|
||||
#endif
|
||||
#if WEBGPU_LOG_PSO
|
||||
LOG(Info, "[WebGPU] GetPipeline: '{}'", String(_debugName.Get(), _debugName.Count() - 1));
|
||||
#ifdef WEBGPU_LOG_PSO_NAME
|
||||
const bool log = StringAnsiView(_debugName.Get(), _debugName.Count() - 1).Contains(WEBGPU_LOG_PSO_NAME);
|
||||
#else
|
||||
const bool log = true;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Lazy-init layout (cannot do it during Init as texture samplers that access eg. depth need to explicitly use UnfilterableFloat)
|
||||
@@ -222,7 +231,7 @@ WGPURenderPipeline GPUPipelineStateWebGPU::GetPipeline(const PipelineKey& key, G
|
||||
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);
|
||||
mergedVertexLayout = (GPUVertexLayoutWebGPU*)GPUVertexLayout::Merge(mergedVertexLayout, VS->InputLayout, true, true, -1, true);
|
||||
|
||||
// Build attributes list
|
||||
WGPUVertexAttribute attributes[GPU_MAX_VS_ELEMENTS];
|
||||
@@ -230,6 +239,10 @@ WGPURenderPipeline GPUPipelineStateWebGPU::GetPipeline(const PipelineKey& key, G
|
||||
PipelineDesc.vertex.buffers = buffers;
|
||||
int32 attributeIndex = 0;
|
||||
auto& elements = mergedVertexLayout->GetElements();
|
||||
#if WEBGPU_LOG_PSO
|
||||
if (log)
|
||||
LOG(Info, " > Vertex elements: {}", elements.Count());
|
||||
#endif
|
||||
for (int32 bufferIndex = 0; bufferIndex < GPU_MAX_VB_BINDED; bufferIndex++)
|
||||
{
|
||||
auto& buffer = buffers[bufferIndex];
|
||||
@@ -253,6 +266,10 @@ WGPURenderPipeline GPUPipelineStateWebGPU::GetPipeline(const PipelineKey& key, G
|
||||
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);
|
||||
#if WEBGPU_LOG_PSO
|
||||
if (log)
|
||||
LOG(Info, " > [{}] slot {}: {} ({} bytes at offset {}) at shader location: {} (per-instance: {})", attributeIndex - 1, element.Slot, ScriptingEnum::ToString(element.Format), PixelFormatExtensions::SizeInBytes(element.Format), element.Offset, dst.shaderLocation, element.PerInstance);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -366,7 +383,7 @@ WGPUBindGroup GPUPipelineStateWebGPU::GetBindGroup(BindGroupKey& key)
|
||||
}
|
||||
}
|
||||
if (collisions > 1)
|
||||
LOG(Error, "> Hash colllision! {}/{} (capacity: {}), equalLayout: {}, equalEntries: {}, equalVersions: {}", collisions, _bindGroups.Count(), _bindGroups.Capacity(), equalLayout, equalEntries, equalVersions);
|
||||
LOG(Error, "> Hash collision! {}/{} (capacity: {}), equalLayout: {}, equalEntries: {}, equalVersions: {}", collisions, _bindGroups.Count(), _bindGroups.Capacity(), equalLayout, equalEntries, equalVersions);
|
||||
#endif
|
||||
|
||||
// Cache it
|
||||
@@ -377,8 +394,11 @@ WGPUBindGroup GPUPipelineStateWebGPU::GetBindGroup(BindGroupKey& key)
|
||||
void GPUPipelineStateWebGPU::InitLayout(GPUResourceView* shaderResources[GPU_MAX_SR_BINDED])
|
||||
{
|
||||
#if WEBGPU_LOG_PSO
|
||||
// Debug log for PSOs with specific name
|
||||
const bool log = true;// StringAnsiView(_debugName.Get(), _debugName.Count() - 1).Contains("PS_HalfDepth");
|
||||
#ifdef WEBGPU_LOG_PSO_NAME
|
||||
const bool log = StringAnsiView(_debugName.Get(), _debugName.Count() - 1).Contains(WEBGPU_LOG_PSO_NAME);
|
||||
#else
|
||||
const bool log = true;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Count the biggest bind group entries (for all shaders) to allocate reused memory
|
||||
|
||||
@@ -265,22 +265,16 @@ void GPUTextureWebGPU::InitHandles()
|
||||
|
||||
// Init per slice views
|
||||
_handlesPerSlice.Resize(Depth(), false);
|
||||
//viewDesc.dimension = WGPUTextureViewDimension_2DArray;
|
||||
if (_desc.HasPerSliceViews() && IsRenderTarget())
|
||||
{
|
||||
for (int32 sliceIndex = 0; sliceIndex < Depth(); sliceIndex++)
|
||||
{
|
||||
//viewDesc.baseArrayLayer = sliceIndex;
|
||||
//viewDesc.arrayLayerCount = 1;
|
||||
auto& view = _handlesPerSlice[sliceIndex];
|
||||
view.Init(this, format, msaa);
|
||||
view.Create(Texture, viewDesc);
|
||||
view.DepthSlice = sliceIndex;
|
||||
}
|
||||
}
|
||||
//viewDesc.baseArrayLayer = 0;
|
||||
//viewDesc.arrayLayerCount = MipLevels();
|
||||
//viewDesc.dimension = _viewDimension;
|
||||
}
|
||||
else if (IsArray())
|
||||
{
|
||||
@@ -370,7 +364,7 @@ void GPUTextureWebGPU::InitHandles()
|
||||
|
||||
bool GPUTextureWebGPU::GetData(int32 arrayIndex, int32 mipMapIndex, TextureMipData& data, uint32 mipRowPitch)
|
||||
{
|
||||
// TODO: no implemented
|
||||
// TODO: not implemented
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user