Fix binding various resources to shaders in WebGPU
This commit is contained in:
@@ -66,7 +66,7 @@ bool GPUBufferWebGPU::OnInit()
|
||||
bufferDesc.usage |= WGPUBufferUsage_Vertex;
|
||||
else if (EnumHasAllFlags(_desc.Flags, GPUBufferFlags::Argument))
|
||||
bufferDesc.usage |= WGPUBufferUsage_Indirect;
|
||||
if (IsUnorderedAccess())
|
||||
if (IsUnorderedAccess() || IsShaderResource()) // SRV buffers need to be bind as read-only storage
|
||||
bufferDesc.usage |= WGPUBufferUsage_Storage;
|
||||
switch (_desc.Usage)
|
||||
{
|
||||
|
||||
@@ -347,8 +347,10 @@ void GPUContextWebGPU::UpdateCB(GPUConstantBuffer* cb, const void* data)
|
||||
if (size != 0)
|
||||
{
|
||||
// Allocate a chunk of memory in a shared page allocator
|
||||
auto allocation = _device->DataUploader.Allocate(size, WGPUBufferUsage_Uniform | WGPUBufferUsage_CopyDst, _minUniformBufferOffsetAlignment);
|
||||
uint32 alignedSize = Math::AlignUp<uint32>(size, 16); // Uniform buffers must be aligned to 16 bytes
|
||||
auto allocation = _device->DataUploader.Allocate(alignedSize, WGPUBufferUsage_Uniform | WGPUBufferUsage_CopyDst, _minUniformBufferOffsetAlignment);
|
||||
cbWebGPU->Allocation = allocation;
|
||||
cbWebGPU->AllocationSize = alignedSize;
|
||||
// TODO: consider holding CPU-side staging buffer and copying data to the GPU buffer in a single batch for all uniforms (before flushing the active command encoder)
|
||||
wgpuQueueWriteBuffer(_device->Queue, allocation.Buffer, allocation.Offset, data, size);
|
||||
_bindGroupDirty = true;
|
||||
@@ -944,7 +946,13 @@ void GPUContextWebGPU::FlushBindGroup()
|
||||
if (!entry.textureView)
|
||||
{
|
||||
// Fallback
|
||||
view = _device->DefaultTexture->View(0);
|
||||
auto defaultTexture = _device->DefaultTexture[(int32)descriptor.ResourceType];
|
||||
if (!defaultTexture)
|
||||
{
|
||||
LOG(Error, "Missing resource {} at slot {} of binding space {}", (int32)descriptor.ResourceType, descriptor.Slot, (int32)descriptor.BindingType);
|
||||
CRASH;
|
||||
}
|
||||
view = defaultTexture->View(0);
|
||||
ptr = (GPUResourceViewPtrWebGPU*)view->GetNativePtr();
|
||||
entry.textureView = ptr->TextureView->View;
|
||||
}
|
||||
@@ -974,7 +982,7 @@ void GPUContextWebGPU::FlushBindGroup()
|
||||
if (uniform && uniform->Allocation.Buffer)
|
||||
{
|
||||
entry.buffer = uniform->Allocation.Buffer;
|
||||
entry.size = uniform->GetSize();
|
||||
entry.size = uniform->AllocationSize;
|
||||
_dynamicOffsets.Add(uniform->Allocation.Offset);
|
||||
}
|
||||
else
|
||||
@@ -988,7 +996,7 @@ void GPUContextWebGPU::FlushBindGroup()
|
||||
{
|
||||
entry.buffer = uniform->Allocation.Buffer;
|
||||
entry.offset = uniform->Allocation.Offset;
|
||||
entry.size = uniform->GetSize();
|
||||
entry.size = uniform->AllocationSize;
|
||||
}
|
||||
else
|
||||
CRASH; // TODO: add dummy buffer as fallback
|
||||
|
||||
@@ -75,6 +75,10 @@ private:
|
||||
Array<PendingClear, FixedAllocation<16>> _pendingClears;
|
||||
GPUResourceView* _shaderResources[GPU_MAX_SR_BINDED];
|
||||
GPUResourceView* _storageResources[GPU_MAX_SR_BINDED];
|
||||
GPUResourceView** _resourceTables[(int32)SpirvShaderResourceBindingType::MAX];
|
||||
#if ENABLE_ASSERTION
|
||||
uint32 _resourceTableSizes[(int32)SpirvShaderResourceBindingType::MAX];
|
||||
#endif
|
||||
|
||||
public:
|
||||
GPUContextWebGPU(GPUDeviceWebGPU* device);
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#if BUILD_DEBUG
|
||||
#include "Engine/Core/Collections/Sorting.h"
|
||||
#endif
|
||||
#include "Engine/GraphicsDevice/Vulkan/Types.h"
|
||||
#include "Engine/Graphics/PixelFormatExtensions.h"
|
||||
#include "Engine/Engine/Engine.h"
|
||||
#include "Engine/Profiler/ProfilerMemory.h"
|
||||
@@ -182,8 +183,11 @@ bool GPUDeviceWebGPU::Init()
|
||||
if (wgpuAdapterGetLimits(Adapter->Adapter, &limits) == WGPUStatus_Success)
|
||||
{
|
||||
MinUniformBufferOffsetAlignment = limits.minUniformBufferOffsetAlignment;
|
||||
Limits.HasDepthAsSRV = true;
|
||||
Limits.HasReadOnlyDepth = true;
|
||||
Limits.HasDepthClip = features.Contains(WGPUFeatureName_DepthClipControl);
|
||||
Limits.HasReadOnlyDepth = true;
|
||||
Limits.MaximumSamplerAnisotropy = 4;
|
||||
Limits.MaximumTexture1DSize = Math::Min<int32>(GPU_MAX_TEXTURE_SIZE, limits.maxTextureDimension1D);
|
||||
Limits.MaximumTexture2DSize = Math::Min<int32>(GPU_MAX_TEXTURE_SIZE, limits.maxTextureDimension2D);
|
||||
Limits.MaximumTexture3DSize = Math::Min<int32>(GPU_MAX_TEXTURE_SIZE, limits.maxTextureDimension3D);
|
||||
@@ -492,11 +496,20 @@ void GPUDeviceWebGPU::DrawBegin()
|
||||
DataUploader.DrawBegin();
|
||||
|
||||
// Create default texture
|
||||
if (!DefaultTexture)
|
||||
static_assert(ARRAY_COUNT(DefaultTexture) == (int32)SpirvShaderResourceType::MAX, "Invalid size of default textures");
|
||||
if (!DefaultTexture[(int32)SpirvShaderResourceType::Texture2D])
|
||||
{
|
||||
DefaultTexture = New<GPUTextureWebGPU>(this, TEXT("DefaultTexture"));
|
||||
DefaultTexture->Init(GPUTextureDescription::New2D(1, 1, PixelFormat::R8G8B8A8_UNorm, GPUTextureFlags::ShaderResource));
|
||||
DefaultTexture->SetResidentMipLevels(1);
|
||||
GPUTextureWebGPU* texture;
|
||||
#define INIT_TEXTURE(type, desc) \
|
||||
texture = New<GPUTextureWebGPU>(this, TEXT("DefaultTexture")); \
|
||||
DefaultTexture[(int32)SpirvShaderResourceType::type] = texture; \
|
||||
texture->Init(desc); \
|
||||
texture->SetResidentMipLevels(1)
|
||||
INIT_TEXTURE(Texture2D, GPUTextureDescription::New2D(1, 1, PixelFormat::R8G8B8A8_UNorm, GPUTextureFlags::ShaderResource));
|
||||
INIT_TEXTURE(Texture3D, GPUTextureDescription::New3D(1, 1, 1, PixelFormat::R8G8B8A8_UNorm, GPUTextureFlags::ShaderResource));
|
||||
INIT_TEXTURE(TextureCube, GPUTextureDescription::NewCube(1, 1, PixelFormat::R8G8B8A8_UNorm, GPUTextureFlags::ShaderResource));
|
||||
#undef INIT_TEXTURE
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -573,7 +586,7 @@ void GPUDeviceWebGPU::Dispose()
|
||||
|
||||
// Clear device resources
|
||||
DataUploader.ReleaseGPU();
|
||||
SAFE_DELETE_GPU_RESOURCE(DefaultTexture);
|
||||
SAFE_DELETE_GPU_RESOURCES(DefaultTexture);
|
||||
SAFE_DELETE_GPU_RESOURCES(DefaultSamplers);
|
||||
SAFE_DELETE(_mainContext);
|
||||
SAFE_DELETE(Adapter);
|
||||
|
||||
@@ -80,7 +80,7 @@ public:
|
||||
WGPUDevice Device = nullptr;
|
||||
WGPUQueue Queue = nullptr;
|
||||
GPUSamplerWebGPU* DefaultSamplers[6] = {};
|
||||
GPUTextureWebGPU* DefaultTexture = nullptr;
|
||||
GPUTextureWebGPU* DefaultTexture[10] = {};
|
||||
GPUDataUploaderWebGPU DataUploader;
|
||||
uint32 MinUniformBufferOffsetAlignment = 1;
|
||||
|
||||
|
||||
@@ -258,9 +258,15 @@ bool GPUPipelineStateWebGPU::Init(const Description& desc)
|
||||
PipelineDesc.fragment = &_fragmentDesc;
|
||||
_fragmentDesc = WGPU_FRAGMENT_STATE_INIT;
|
||||
_fragmentDesc.targets = _colorTargets;
|
||||
_blendState = WGPU_BLEND_STATE_INIT;
|
||||
_blendState.color = ToBlendComponent(desc.BlendMode.BlendOp, desc.BlendMode.SrcBlend, desc.BlendMode.DestBlend);
|
||||
_blendState.alpha = ToBlendComponent(desc.BlendMode.BlendOpAlpha, desc.BlendMode.SrcBlendAlpha, desc.BlendMode.DestBlendAlpha);
|
||||
Platform::MemoryClear(&_colorTargets, sizeof(_colorTargets));
|
||||
if (desc.BlendMode.BlendEnable)
|
||||
{
|
||||
_blendState = WGPU_BLEND_STATE_INIT;
|
||||
_blendState.color = ToBlendComponent(desc.BlendMode.BlendOp, desc.BlendMode.SrcBlend, desc.BlendMode.DestBlend);
|
||||
_blendState.alpha = ToBlendComponent(desc.BlendMode.BlendOpAlpha, desc.BlendMode.SrcBlendAlpha, desc.BlendMode.DestBlendAlpha);
|
||||
for (auto& e : _colorTargets)
|
||||
e.blend = &_blendState;
|
||||
}
|
||||
WGPUColorWriteMask writeMask = WGPUColorWriteMask_All;
|
||||
if (desc.BlendMode.RenderTargetWriteMask != BlendingMode::ColorWrite::All)
|
||||
{
|
||||
@@ -274,12 +280,10 @@ bool GPUPipelineStateWebGPU::Init(const Description& desc)
|
||||
if (EnumHasAllFlags(desc.BlendMode.RenderTargetWriteMask, BlendingMode::ColorWrite::Alpha))
|
||||
writeMask |= WGPUColorWriteMask_Alpha;
|
||||
}
|
||||
for (auto& e : _colorTargets)
|
||||
if (PS)
|
||||
{
|
||||
e = WGPU_COLOR_TARGET_STATE_INIT;
|
||||
if (desc.BlendMode.BlendEnable)
|
||||
e.blend = &_blendState;
|
||||
e.writeMask = writeMask;
|
||||
for (int32 rtIndex = 0; rtIndex < PS->GetBindings().OutputsCount; rtIndex++)
|
||||
_colorTargets[rtIndex].writeMask = writeMask;
|
||||
}
|
||||
|
||||
// Cache shaders
|
||||
|
||||
@@ -14,6 +14,7 @@ GPUConstantBufferWebGPU::GPUConstantBufferWebGPU(GPUDeviceWebGPU* device, uint32
|
||||
: GPUResourceWebGPU(device, name)
|
||||
{
|
||||
_size = _memoryUsage = size;
|
||||
AllocationSize = 0;
|
||||
}
|
||||
|
||||
GPUShaderProgram* GPUShaderWebGPU::CreateGPUShaderProgram(ShaderStage type, const GPUShaderProgramInitializer& initializer, Span<byte> bytecode, MemoryReadStream& stream)
|
||||
|
||||
@@ -18,6 +18,7 @@ public:
|
||||
|
||||
public:
|
||||
GPUDataUploaderWebGPU::Allocation Allocation;
|
||||
uint32 AllocationSize;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user