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:
@@ -166,8 +166,14 @@ 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++)
|
||||
{
|
||||
buffers[i] = *key.VertexBuffers[i];
|
||||
for (int32 j = 0; j < buffers[i].attributeCount; j++)
|
||||
((WGPUVertexAttribute&)buffers[i].attributes[j]).shaderLocation = shaderLocation++;
|
||||
}
|
||||
PipelineDesc.vertex.buffers = buffers;
|
||||
|
||||
// Create object
|
||||
@@ -196,13 +202,10 @@ bool GPUPipelineStateWebGPU::Init(const Description& desc)
|
||||
if (IsValid())
|
||||
OnReleaseGPU();
|
||||
|
||||
// Cache shaders
|
||||
VS = (GPUShaderProgramVSWebGPU*)desc.VS;
|
||||
PS = (GPUShaderProgramPSWebGPU*)desc.PS;
|
||||
|
||||
// Initialize description (without dynamic state from context such as render targets, vertex buffers, etc.)
|
||||
PipelineDesc = WGPU_RENDER_PIPELINE_DESCRIPTOR_INIT;
|
||||
#if GPU_ENABLE_RESOURCE_NAMING
|
||||
DebugDesc = desc;
|
||||
GetDebugName(_debugName);
|
||||
PipelineDesc.label = { _debugName.Get(), (size_t)_debugName.Count() - 1 };
|
||||
#endif
|
||||
@@ -257,17 +260,24 @@ bool GPUPipelineStateWebGPU::Init(const Description& desc)
|
||||
writeMask |= WGPUColorWriteMask_Blue;
|
||||
if (EnumHasAllFlags(desc.BlendMode.RenderTargetWriteMask, BlendingMode::ColorWrite::Alpha))
|
||||
writeMask |= WGPUColorWriteMask_Alpha;
|
||||
}
|
||||
for (auto& e : _colorTargets)
|
||||
} for (auto& e : _colorTargets)
|
||||
{
|
||||
e = WGPU_COLOR_TARGET_STATE_INIT;
|
||||
e.blend = &_blendState;
|
||||
if (desc.BlendMode.BlendEnable)
|
||||
e.blend = &_blendState;
|
||||
e.writeMask = writeMask;
|
||||
}
|
||||
|
||||
// Cache shaders
|
||||
VS = (GPUShaderProgramVSWebGPU*)desc.VS;
|
||||
PipelineDesc.vertex.module = VS->ShaderModule;
|
||||
PS = (GPUShaderProgramPSWebGPU*)desc.PS;
|
||||
if (PS)
|
||||
{
|
||||
_fragmentDesc.module = PS->ShaderModule;
|
||||
}
|
||||
|
||||
// TODO: set resources binding into PipelineDesc.layout
|
||||
// TODO: set vertex shader into PipelineDesc.vertex
|
||||
// TODO: set pixel shader into PipelineDesc.fragment
|
||||
|
||||
_memoryUsage = 1;
|
||||
return GPUPipelineState::Init(desc);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Engine/Core/Collections/Dictionary.h"
|
||||
#include "Engine/Graphics/GPUPipelineState.h"
|
||||
#include "GPUShaderProgramWebGPU.h"
|
||||
#include "GPUDeviceWebGPU.h"
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Engine/Graphics/Shaders/GPUShaderProgram.h"
|
||||
#include "Engine/Core/Types/DataContainer.h"
|
||||
#include "Engine/Core/Collections/Dictionary.h"
|
||||
|
||||
#if GRAPHICS_API_WEBGPU
|
||||
|
||||
#include "Engine/Graphics/Shaders/GPUShaderProgram.h"
|
||||
#include "Engine/GraphicsDevice/Vulkan/Types.h"
|
||||
#include <webgpu/webgpu.h>
|
||||
|
||||
/// <summary>
|
||||
/// Shaders base class for Web GPU backend.
|
||||
/// </summary>
|
||||
@@ -15,15 +15,22 @@ template<typename BaseType>
|
||||
class GPUShaderProgramWebGPU : public BaseType
|
||||
{
|
||||
public:
|
||||
GPUShaderProgramWebGPU(const GPUShaderProgramInitializer& initializer)
|
||||
GPUShaderProgramWebGPU(const GPUShaderProgramInitializer& initializer, const SpirvShaderDescriptorInfo& descriptorInfo, WGPUShaderModule shaderModule)
|
||||
: DescriptorInfo(descriptorInfo)
|
||||
, ShaderModule(shaderModule)
|
||||
{
|
||||
BaseType::Init(initializer);
|
||||
}
|
||||
|
||||
~GPUShaderProgramWebGPU()
|
||||
{
|
||||
wgpuShaderModuleRelease(ShaderModule);
|
||||
}
|
||||
|
||||
public:
|
||||
SpirvShaderDescriptorInfo DescriptorInfo;
|
||||
WGPUShaderModule ShaderModule;
|
||||
|
||||
public:
|
||||
// [BaseType]
|
||||
uint32 GetBufferSize() const override
|
||||
@@ -32,7 +39,7 @@ public:
|
||||
}
|
||||
void* GetBufferHandle() const override
|
||||
{
|
||||
return nullptr;
|
||||
return ShaderModule;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -42,8 +49,8 @@ public:
|
||||
class GPUShaderProgramVSWebGPU : public GPUShaderProgramWebGPU<GPUShaderProgramVS>
|
||||
{
|
||||
public:
|
||||
GPUShaderProgramVSWebGPU(const GPUShaderProgramInitializer& initializer, GPUVertexLayout* inputLayout, GPUVertexLayout* vertexLayout, Span<byte> bytecode)
|
||||
: GPUShaderProgramWebGPU(initializer)
|
||||
GPUShaderProgramVSWebGPU(const GPUShaderProgramInitializer& initializer, GPUVertexLayout* inputLayout, GPUVertexLayout* vertexLayout, const SpirvShaderDescriptorInfo& descriptorInfo, WGPUShaderModule shaderModule)
|
||||
: GPUShaderProgramWebGPU(initializer, descriptorInfo, shaderModule)
|
||||
{
|
||||
InputLayout = inputLayout;
|
||||
Layout = vertexLayout;
|
||||
@@ -56,8 +63,8 @@ public:
|
||||
class GPUShaderProgramPSWebGPU : public GPUShaderProgramWebGPU<GPUShaderProgramPS>
|
||||
{
|
||||
public:
|
||||
GPUShaderProgramPSWebGPU(const GPUShaderProgramInitializer& initializer)
|
||||
: GPUShaderProgramWebGPU(initializer)
|
||||
GPUShaderProgramPSWebGPU(const GPUShaderProgramInitializer& initializer, const SpirvShaderDescriptorInfo& descriptorInfo, WGPUShaderModule shaderModule)
|
||||
: GPUShaderProgramWebGPU(initializer, descriptorInfo, shaderModule)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user