From 427f4647fc993c62a75146b89eb8b9cf558f8885 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Mon, 16 Mar 2026 16:39:18 +0100 Subject: [PATCH] Fix various issues in WebGPU backend --- Source/Engine/Graphics/GPUDevice.cpp | 13 +++++++++++-- Source/Engine/Graphics/Graphics.cpp | 7 +++++++ Source/Engine/Graphics/RenderTask.cpp | 6 ++++++ .../GraphicsDevice/WebGPU/GPUBufferWebGPU.cpp | 1 + .../WebGPU/GPUPipelineStateWebGPU.cpp | 2 +- .../GraphicsDevice/WebGPU/GPUShaderWebGPU.cpp | 10 ++++++++++ .../GraphicsDevice/WebGPU/GPUSwapChainWebGPU.cpp | 13 ++++++++++++- .../GraphicsDevice/WebGPU/GPUTextureWebGPU.cpp | 4 ++++ Source/Engine/Renderer/Renderer.cpp | 2 +- 9 files changed, 53 insertions(+), 5 deletions(-) diff --git a/Source/Engine/Graphics/GPUDevice.cpp b/Source/Engine/Graphics/GPUDevice.cpp index 911f2d834..b16ed7c74 100644 --- a/Source/Engine/Graphics/GPUDevice.cpp +++ b/Source/Engine/Graphics/GPUDevice.cpp @@ -256,8 +256,6 @@ uint64 GPUResource::GetMemoryUsage() const return _memoryUsage; } -static_assert((GPU_ENABLE_RESOURCE_NAMING) == (!BUILD_RELEASE), "Update build condition on around GPUResource Name property getter/setter."); - #if GPU_ENABLE_RESOURCE_NAMING StringView GPUResource::GetName() const @@ -282,6 +280,17 @@ void GPUResource::SetName(const StringView& name) } } +#elif !BUILD_RELEASE + +StringView GPUResource::GetName() const +{ + return StringView::Empty; +} + +void GPUResource::SetName(const StringView& name) +{ +} + #endif void GPUResource::ReleaseGPU() diff --git a/Source/Engine/Graphics/Graphics.cpp b/Source/Engine/Graphics/Graphics.cpp index f463df2fe..f3395c02d 100644 --- a/Source/Engine/Graphics/Graphics.cpp +++ b/Source/Engine/Graphics/Graphics.cpp @@ -244,3 +244,10 @@ void GraphicsService::Dispose() { // Device is disposed AFTER Content (faster and safer because there is no assets so there is less gpu resources to cleanup) } + +#if PLATFORM_WEB && !GRAPHICS_API_WEBGPU +// Fix missing method when using Null backend on Web +void SetWebGPUTextureViewSampler(GPUTextureView* view, uint32 samplerType) +{ +} +#endif diff --git a/Source/Engine/Graphics/RenderTask.cpp b/Source/Engine/Graphics/RenderTask.cpp index ac969ad2d..0786a2e7d 100644 --- a/Source/Engine/Graphics/RenderTask.cpp +++ b/Source/Engine/Graphics/RenderTask.cpp @@ -362,7 +362,13 @@ Viewport SceneRenderTask::GetOutputViewport() const if (Output && Output->IsAllocated()) return Viewport(0, 0, static_cast(Output->Width()), static_cast(Output->Height())); if (SwapChain) + { +#if PLATFORM_WEB + // Hack fix for Web where swapchain texture might have different size than actual current size of the backbuffer, just precache it (GetBackBufferView might resize internally) + SwapChain->GetBackBufferView(); +#endif return Viewport(0, 0, static_cast(SwapChain->GetWidth()), static_cast(SwapChain->GetHeight())); + } return GetViewport(); } diff --git a/Source/Engine/GraphicsDevice/WebGPU/GPUBufferWebGPU.cpp b/Source/Engine/GraphicsDevice/WebGPU/GPUBufferWebGPU.cpp index 6219ba38e..5274e3bff 100644 --- a/Source/Engine/GraphicsDevice/WebGPU/GPUBufferWebGPU.cpp +++ b/Source/Engine/GraphicsDevice/WebGPU/GPUBufferWebGPU.cpp @@ -128,6 +128,7 @@ void GPUBufferWebGPU::OnReleaseGPU() #if GPU_ENABLE_RESOURCE_NAMING _name.Clear(); #endif + _view.Ptr.Version++; // Base GPUBuffer::OnReleaseGPU(); diff --git a/Source/Engine/GraphicsDevice/WebGPU/GPUPipelineStateWebGPU.cpp b/Source/Engine/GraphicsDevice/WebGPU/GPUPipelineStateWebGPU.cpp index 2babbc855..55519d637 100644 --- a/Source/Engine/GraphicsDevice/WebGPU/GPUPipelineStateWebGPU.cpp +++ b/Source/Engine/GraphicsDevice/WebGPU/GPUPipelineStateWebGPU.cpp @@ -554,6 +554,7 @@ WGPURenderPipeline GPUPipelineStateWebGPU::GetPipeline(const PipelineKey& key, c _colorTargets[i].format = (WGPUTextureFormat)key.RenderTargetFormats[i]; } WGPUVertexBufferLayout buffers[GPU_MAX_VB_BINDED]; + WGPUVertexAttribute attributes[GPU_MAX_VS_ELEMENTS]; if (key.VertexLayout) { // Combine input layout of Vertex Buffers with the destination layout used by the Vertex Shader @@ -564,7 +565,6 @@ WGPURenderPipeline GPUPipelineStateWebGPU::GetPipeline(const PipelineKey& key, c mergedVertexLayout = (GPUVertexLayoutWebGPU*)GPUVertexLayout::Merge(mergedVertexLayout, VS->InputLayout, true, true, -1, true); // Build attributes list - WGPUVertexAttribute attributes[GPU_MAX_VS_ELEMENTS]; desc.vertex.bufferCount = 0; desc.vertex.buffers = buffers; int32 attributeIndex = 0; diff --git a/Source/Engine/GraphicsDevice/WebGPU/GPUShaderWebGPU.cpp b/Source/Engine/GraphicsDevice/WebGPU/GPUShaderWebGPU.cpp index c3fcf0baa..402229465 100644 --- a/Source/Engine/GraphicsDevice/WebGPU/GPUShaderWebGPU.cpp +++ b/Source/Engine/GraphicsDevice/WebGPU/GPUShaderWebGPU.cpp @@ -20,6 +20,16 @@ GPUConstantBufferWebGPU::GPUConstantBufferWebGPU(GPUDeviceWebGPU* device, uint32 GPUShaderProgram* GPUShaderWebGPU::CreateGPUShaderProgram(ShaderStage type, const GPUShaderProgramInitializer& initializer, Span bytecode, MemoryReadStream& stream) { + // Fix issue with unaligned loads if bytecode + // TODO: fix issue at cook time by adding padding before shader bytecode to ensure it's aligned (eg. to 8 bytes) + BytesContainer bytecoddAligned; + uintptr align = (uintptr)bytecode.Get() % sizeof(uintptr); + if (align != 0) + { + bytecoddAligned.Copy(bytecode); + bytecode = bytecoddAligned; + } + // Extract the SPIR-V shader header from the cache SpirvShaderHeader* header = (SpirvShaderHeader*)bytecode.Get(); bytecode = bytecode.Slice(sizeof(SpirvShaderHeader)); diff --git a/Source/Engine/GraphicsDevice/WebGPU/GPUSwapChainWebGPU.cpp b/Source/Engine/GraphicsDevice/WebGPU/GPUSwapChainWebGPU.cpp index 2414f3906..e92a999db 100644 --- a/Source/Engine/GraphicsDevice/WebGPU/GPUSwapChainWebGPU.cpp +++ b/Source/Engine/GraphicsDevice/WebGPU/GPUSwapChainWebGPU.cpp @@ -11,7 +11,6 @@ #include "Engine/Graphics/RenderTools.h" #include "Engine/Profiler/ProfilerCPU.h" #include "Engine/Profiler/ProfilerMemory.h" -#include "Engine/Scripting/Enums.h" GPUSwapChainWebGPU::GPUSwapChainWebGPU(GPUDeviceWebGPU* device, Window* window) : GPUResourceWebGPU(device, StringView::Empty) @@ -59,6 +58,18 @@ GPUTextureView* GPUSwapChainWebGPU::GetBackBufferView() ASSERT(hasSurfaceTexture); _surfaceView.Texture = surfaceTexture.texture; + // Fix up the size (in case underlying texture is different than the engine resize it to) + const uint32 width = wgpuTextureGetWidth(surfaceTexture.texture); + const uint32 height = wgpuTextureGetHeight(surfaceTexture.texture); + if (_width != width || _height != height) + { + PROFILE_MEM_DEC(Graphics, _memoryUsage); + _width = width; + _height = height; + _memoryUsage = RenderTools::CalculateTextureMemoryUsage(_format, _width, _height, 1); + PROFILE_MEM_INC(Graphics, _memoryUsage); + } + // Create view WGPUTextureViewDescriptor viewDesc = WGPU_TEXTURE_VIEW_DESCRIPTOR_INIT; #if GPU_ENABLE_RESOURCE_NAMING diff --git a/Source/Engine/GraphicsDevice/WebGPU/GPUTextureWebGPU.cpp b/Source/Engine/GraphicsDevice/WebGPU/GPUTextureWebGPU.cpp index 58cea6317..14affdef7 100644 --- a/Source/Engine/GraphicsDevice/WebGPU/GPUTextureWebGPU.cpp +++ b/Source/Engine/GraphicsDevice/WebGPU/GPUTextureWebGPU.cpp @@ -115,6 +115,10 @@ void GPUTextureViewWebGPU::Release() View = nullptr; } Texture = nullptr; + HasStencil = false; + ReadOnly = false; + DepthSlice = WGPU_DEPTH_SLICE_UNDEFINED; + Ptr.Version++; } bool GPUTextureWebGPU::OnInit() diff --git a/Source/Engine/Renderer/Renderer.cpp b/Source/Engine/Renderer/Renderer.cpp index ddbb8573e..29a80b435 100644 --- a/Source/Engine/Renderer/Renderer.cpp +++ b/Source/Engine/Renderer/Renderer.cpp @@ -142,7 +142,7 @@ void RenderAntiAliasingPass(RenderContext& renderContext, GPUTexture* input, GPU // AA -> CAS -> Output auto tmpImage = RenderTargetPool::Get(input->GetDescription()); RENDER_TARGET_POOL_SET_NAME(tmpImage, "TmpImage"); - context->SetViewportAndScissors((float)input->Width(), (float)input->Height()); + context->SetViewportAndScissors((float)tmpImage->Width(), (float)tmpImage->Height()); if (aaMode == AntialiasingMode::FastApproximateAntialiasing) FXAA::Instance()->Render(renderContext, input, tmpImage->View()); else