Add shader compiler for WebGPU

Use existing Vulkan compiler to generate SPIR-V and convert it into WGSL with tint compiler
https://github.com/google/dawn/releases/tag/v20260219.200501
This commit is contained in:
Wojtek Figat
2026-02-24 17:55:26 +01:00
parent 9158e1c270
commit 9be8589437
17 changed files with 337 additions and 50 deletions

View File

@@ -5,6 +5,9 @@
#include "GPUShaderWebGPU.h"
#include "GPUShaderProgramWebGPU.h"
#include "GPUVertexLayoutWebGPU.h"
#include "Engine/Core/Log.h"
#include "Engine/Core/Types/DataContainer.h"
#include "Engine/GraphicsDevice/Vulkan/Types.h"
#include "Engine/Serialization/MemoryReadStream.h"
GPUConstantBufferWebGPU::GPUConstantBufferWebGPU(GPUDeviceWebGPU* device, uint32 size, WGPUBuffer buffer, const StringView& name) noexcept
@@ -31,6 +34,34 @@ void GPUConstantBufferWebGPU::OnReleaseGPU()
GPUShaderProgram* GPUShaderWebGPU::CreateGPUShaderProgram(ShaderStage type, const GPUShaderProgramInitializer& initializer, Span<byte> bytecode, MemoryReadStream& stream)
{
// Extract the SPIR-V shader header from the cache
SpirvShaderHeader* header = (SpirvShaderHeader*)bytecode.Get();
bytecode = bytecode.Slice(sizeof(SpirvShaderHeader));
// Extract the WGSL shader
BytesContainer wgsl;
ASSERT(header->Type == SpirvShaderHeader::Types::WGSL);
wgsl.Link(bytecode);
// Create a shader module
WGPUShaderSourceWGSL shaderCodeDesc = WGPU_SHADER_SOURCE_WGSL_INIT;
shaderCodeDesc.code = { (const char*)wgsl.Get(), (size_t)wgsl.Length() - 1 };
WGPUShaderModuleDescriptor shaderDesc = WGPU_SHADER_MODULE_DESCRIPTOR_INIT;
shaderDesc.nextInChain = &shaderCodeDesc.chain;
#if GPU_ENABLE_RESOURCE_NAMING
shaderDesc.label = { initializer.Name.Get(), (size_t)initializer.Name.Length() };
#endif
WGPUShaderModule shaderModule = wgpuDeviceCreateShaderModule(_device->Device, &shaderDesc);
if (!shaderModule)
{
LOG(Error, "Failed to create a shader module");
#if GPU_ENABLE_DIAGNOSTICS
LOG_STR(Warning, String((char*)wgsl.Get(), wgsl.Length()));
#endif
return nullptr;
}
// Create a shader program
GPUShaderProgram* shader = nullptr;
switch (type)
{
@@ -38,14 +69,12 @@ GPUShaderProgram* GPUShaderWebGPU::CreateGPUShaderProgram(ShaderStage type, cons
{
GPUVertexLayout* inputLayout, *vertexLayout;
ReadVertexLayout(stream, inputLayout, vertexLayout);
MISSING_CODE("create vertex shader");
shader = New<GPUShaderProgramVSWebGPU>(initializer, inputLayout, vertexLayout, bytecode);
shader = New<GPUShaderProgramVSWebGPU>(initializer, inputLayout, vertexLayout, header->DescriptorInfo, shaderModule);
break;
}
case ShaderStage::Pixel:
{
MISSING_CODE("create pixel shader");
shader = New<GPUShaderProgramPSWebGPU>(initializer);
shader = New<GPUShaderProgramPSWebGPU>(initializer, header->DescriptorInfo, shaderModule);
break;
}
}