wg_engine: multisampling support

Used native hardware MSAA x4

Full multisampling support including custom blend and compositions.
Must be verified on web and 4K resolution for performance issues
This commit is contained in:
Sergii Liebodkin 2024-10-24 10:04:08 +00:00 committed by Hermet Park
parent bace4e3e9e
commit c57e2e6c9f
7 changed files with 31 additions and 17 deletions

View file

@ -111,18 +111,18 @@ WGPUTexture WgContext::createTexture(uint32_t width, uint32_t height, WGPUTextur
} }
WGPUTexture WgContext::createTexStorage(uint32_t width, uint32_t height, WGPUTextureFormat format, uint32_t sc) WGPUTexture WgContext::createTexStorage(uint32_t width, uint32_t height, WGPUTextureFormat format)
{ {
const WGPUTextureDescriptor textureDesc { const WGPUTextureDescriptor textureDesc {
.usage = WGPUTextureUsage_CopySrc | WGPUTextureUsage_CopyDst | WGPUTextureUsage_TextureBinding | WGPUTextureUsage_StorageBinding | WGPUTextureUsage_RenderAttachment, .usage = WGPUTextureUsage_CopySrc | WGPUTextureUsage_CopyDst | WGPUTextureUsage_TextureBinding | WGPUTextureUsage_StorageBinding | WGPUTextureUsage_RenderAttachment,
.dimension = WGPUTextureDimension_2D, .size = { width, height, 1 }, .dimension = WGPUTextureDimension_2D, .size = { width, height, 1 },
.format = format, .mipLevelCount = 1, .sampleCount = sc .format = format, .mipLevelCount = 1, .sampleCount = 1
}; };
return wgpuDeviceCreateTexture(device, &textureDesc); return wgpuDeviceCreateTexture(device, &textureDesc);
} }
WGPUTexture WgContext::createTexStencil(uint32_t width, uint32_t height, WGPUTextureFormat format, uint32_t sc) WGPUTexture WgContext::createTexAttachement(uint32_t width, uint32_t height, WGPUTextureFormat format, uint32_t sc)
{ {
const WGPUTextureDescriptor textureDesc { const WGPUTextureDescriptor textureDesc {
.usage = WGPUTextureUsage_RenderAttachment, .usage = WGPUTextureUsage_RenderAttachment,

View file

@ -54,8 +54,8 @@ struct WgContext {
// create common objects // create common objects
WGPUSampler createSampler(WGPUFilterMode filter, WGPUMipmapFilterMode mipmapFilter, WGPUAddressMode addrMode); WGPUSampler createSampler(WGPUFilterMode filter, WGPUMipmapFilterMode mipmapFilter, WGPUAddressMode addrMode);
WGPUTexture createTexture(uint32_t width, uint32_t height, WGPUTextureFormat format); WGPUTexture createTexture(uint32_t width, uint32_t height, WGPUTextureFormat format);
WGPUTexture createTexStorage(uint32_t width, uint32_t height, WGPUTextureFormat format, uint32_t sc = 1); WGPUTexture createTexStorage(uint32_t width, uint32_t height, WGPUTextureFormat format);
WGPUTexture createTexStencil(uint32_t width, uint32_t height, WGPUTextureFormat format, uint32_t sc = 1); WGPUTexture createTexAttachement(uint32_t width, uint32_t height, WGPUTextureFormat format, uint32_t sc);
WGPUTextureView createTextureView(WGPUTexture texture); WGPUTextureView createTextureView(WGPUTexture texture);
bool allocateTexture(WGPUTexture& texture, uint32_t width, uint32_t height, WGPUTextureFormat format, void* data); bool allocateTexture(WGPUTexture& texture, uint32_t width, uint32_t height, WGPUTextureFormat format, void* data);

View file

@ -31,8 +31,10 @@ void WgCompositor::initialize(WgContext& context, uint32_t width, uint32_t heigh
this->width = width; this->width = width;
this->height = height; this->height = height;
// allocate global stencil buffer handles // allocate global stencil buffer handles
texStencil = context.createTexStencil(width, height, WGPUTextureFormat_Depth24PlusStencil8); texDepthStencil = context.createTexAttachement(width, height, WGPUTextureFormat_Depth24PlusStencil8, 1);
texViewStencil = context.createTextureView(texStencil); texViewDepthStencil = context.createTextureView(texDepthStencil);
texDepthStencilMS = context.createTexAttachement(width, height, WGPUTextureFormat_Depth24PlusStencil8, 4);
texViewDepthStencilMS = context.createTextureView(texDepthStencilMS);
// allocate global view matrix handles // allocate global view matrix handles
WgShaderTypeMat4x4f viewMat(width, height); WgShaderTypeMat4x4f viewMat(width, height);
context.allocateBufferUniform(bufferViewMat, &viewMat, sizeof(viewMat)); context.allocateBufferUniform(bufferViewMat, &viewMat, sizeof(viewMat));
@ -65,8 +67,10 @@ void WgCompositor::release(WgContext& context)
context.pipelines->layouts.releaseBindGroup(bindGroupViewMat); context.pipelines->layouts.releaseBindGroup(bindGroupViewMat);
context.releaseBuffer(bufferViewMat); context.releaseBuffer(bufferViewMat);
// release global stencil buffer handles // release global stencil buffer handles
context.releaseTextureView(texViewStencil); context.releaseTextureView(texViewDepthStencilMS);
context.releaseTexture(texStencil); context.releaseTexture(texDepthStencilMS);
context.releaseTextureView(texViewDepthStencil);
context.releaseTexture(texDepthStencil);
height = 0; height = 0;
width = 0; width = 0;
pipelines = nullptr; pipelines = nullptr;
@ -91,15 +95,16 @@ void WgCompositor::beginRenderPass(WGPUCommandEncoder commandEncoder, WgRenderSt
this->currentTarget = target; this->currentTarget = target;
this->commandEncoder = commandEncoder; this->commandEncoder = commandEncoder;
const WGPURenderPassDepthStencilAttachment depthStencilAttachment{ const WGPURenderPassDepthStencilAttachment depthStencilAttachment{
.view = texViewStencil, .view = texViewDepthStencilMS,
.depthLoadOp = WGPULoadOp_Load, .depthStoreOp = WGPUStoreOp_Discard, .depthClearValue = 1.0f, .depthLoadOp = WGPULoadOp_Load, .depthStoreOp = WGPUStoreOp_Discard, .depthClearValue = 1.0f,
.stencilLoadOp = WGPULoadOp_Load, .stencilStoreOp = WGPUStoreOp_Discard, .stencilClearValue = 0 .stencilLoadOp = WGPULoadOp_Load, .stencilStoreOp = WGPUStoreOp_Discard, .stencilClearValue = 0
}; };
//WGPURenderPassDepthStencilAttachment depthStencilAttachment{ .view = texViewStencil, .depthClearValue = 1.0f, .stencilLoadOp = WGPULoadOp_Clear, .stencilStoreOp = WGPUStoreOp_Discard }; //WGPURenderPassDepthStencilAttachment depthStencilAttachment{ .view = texViewStencil, .depthClearValue = 1.0f, .stencilLoadOp = WGPULoadOp_Clear, .stencilStoreOp = WGPUStoreOp_Discard };
WGPURenderPassColorAttachment colorAttachment{}; WGPURenderPassColorAttachment colorAttachment{};
colorAttachment.view = target->texView, colorAttachment.view = target->texViewMS,
colorAttachment.loadOp = clear ? WGPULoadOp_Clear : WGPULoadOp_Load, colorAttachment.loadOp = clear ? WGPULoadOp_Clear : WGPULoadOp_Load,
colorAttachment.storeOp = WGPUStoreOp_Store; colorAttachment.storeOp = WGPUStoreOp_Store;
colorAttachment.resolveTarget = target->texView;
#ifdef __EMSCRIPTEN__ #ifdef __EMSCRIPTEN__
colorAttachment.depthSlice = WGPU_DEPTH_SLICE_UNDEFINED; colorAttachment.depthSlice = WGPU_DEPTH_SLICE_UNDEFINED;
#endif #endif
@ -204,7 +209,7 @@ void WgCompositor::composeScene(WgContext& context, WgRenderStorage* src, WgRend
void WgCompositor::blit(WgContext& context, WGPUCommandEncoder encoder, WgRenderStorage* src, WGPUTextureView dstView) { void WgCompositor::blit(WgContext& context, WGPUCommandEncoder encoder, WgRenderStorage* src, WGPUTextureView dstView) {
const WGPURenderPassDepthStencilAttachment depthStencilAttachment{ const WGPURenderPassDepthStencilAttachment depthStencilAttachment{
.view = texViewStencil, .view = texViewDepthStencil,
.depthLoadOp = WGPULoadOp_Load, .depthStoreOp = WGPUStoreOp_Discard, .depthLoadOp = WGPULoadOp_Load, .depthStoreOp = WGPUStoreOp_Discard,
.stencilLoadOp = WGPULoadOp_Load, .stencilStoreOp = WGPUStoreOp_Discard .stencilLoadOp = WGPULoadOp_Load, .stencilStoreOp = WGPUStoreOp_Discard
}; };

View file

@ -37,9 +37,11 @@ class WgCompositor
private: private:
// pipelines (external handle, do not release) // pipelines (external handle, do not release)
WgPipelines* pipelines{}; WgPipelines* pipelines{};
// global stencil buffer handles // global stencil/depth buffer handles
WGPUTexture texStencil{}; WGPUTexture texDepthStencil{};
WGPUTextureView texViewStencil{}; WGPUTextureView texViewDepthStencil{};
WGPUTexture texDepthStencilMS{};
WGPUTextureView texViewDepthStencilMS{};
// global view matrix handles // global view matrix handles
WGPUBuffer bufferViewMat{}; WGPUBuffer bufferViewMat{};
WGPUBindGroup bindGroupViewMat{}; WGPUBindGroup bindGroupViewMat{};

View file

@ -146,7 +146,8 @@ void WgPipelines::initialize(WgContext& context)
const WGPUVertexBufferLayout vertexBufferLayoutTex { .arrayStride = 8, .stepMode = WGPUVertexStepMode_Vertex, .attributeCount = 1, .attributes = vertexAttributesTex }; const WGPUVertexBufferLayout vertexBufferLayoutTex { .arrayStride = 8, .stepMode = WGPUVertexStepMode_Vertex, .attributeCount = 1, .attributes = vertexAttributesTex };
const WGPUVertexBufferLayout vertexBufferLayoutsShape[] { vertexBufferLayoutPos }; const WGPUVertexBufferLayout vertexBufferLayoutsShape[] { vertexBufferLayoutPos };
const WGPUVertexBufferLayout vertexBufferLayoutsImage[] { vertexBufferLayoutPos, vertexBufferLayoutTex }; const WGPUVertexBufferLayout vertexBufferLayoutsImage[] { vertexBufferLayoutPos, vertexBufferLayoutTex };
const WGPUMultisampleState multisampleState { .count = 1, .mask = 0xFFFFFFFF, .alphaToCoverageEnabled = false }; const WGPUMultisampleState multisampleState { .count = 4, .mask = 0xFFFFFFFF, .alphaToCoverageEnabled = false };
const WGPUMultisampleState multisampleStateX1 { .count = 1, .mask = 0xFFFFFFFF, .alphaToCoverageEnabled = false };
const WGPUTextureFormat offscreenTargetFormat = WGPUTextureFormat_RGBA8Unorm; const WGPUTextureFormat offscreenTargetFormat = WGPUTextureFormat_RGBA8Unorm;
// blend states // blend states
@ -452,7 +453,7 @@ void WgPipelines::initialize(WgContext& context)
WGPUColorWriteMask_All, context.preferredFormat, WGPUColorWriteMask_All, context.preferredFormat,
WGPUCompareFunction_Always, WGPUStencilOperation_Zero, WGPUCompareFunction_Always, WGPUStencilOperation_Zero,
WGPUCompareFunction_Always, WGPUStencilOperation_Zero, WGPUCompareFunction_Always, WGPUStencilOperation_Zero,
WGPUCompareFunction_Always, false, multisampleState, blendStateSrc); WGPUCompareFunction_Always, false, multisampleStateX1, blendStateSrc);
} }
void WgPipelines::releaseGraphicHandles(WgContext& context) void WgPipelines::releaseGraphicHandles(WgContext& context)

View file

@ -27,7 +27,9 @@ void WgRenderStorage::initialize(WgContext& context, uint32_t width, uint32_t he
this->width = width; this->width = width;
this->height = height; this->height = height;
texture = context.createTexStorage(width, height, WGPUTextureFormat_RGBA8Unorm); texture = context.createTexStorage(width, height, WGPUTextureFormat_RGBA8Unorm);
textureMS = context.createTexAttachement(width, height, WGPUTextureFormat_RGBA8Unorm, 4);
texView = context.createTextureView(texture); texView = context.createTextureView(texture);
texViewMS = context.createTextureView(textureMS);
bindGroupRead = context.pipelines->layouts.createBindGroupStrorage1RO(texView); bindGroupRead = context.pipelines->layouts.createBindGroupStrorage1RO(texView);
bindGroupWrite = context.pipelines->layouts.createBindGroupStrorage1WO(texView); bindGroupWrite = context.pipelines->layouts.createBindGroupStrorage1WO(texView);
bindGroupTexure = context.pipelines->layouts.createBindGroupTexSampled(context.samplerNearestRepeat, texView); bindGroupTexure = context.pipelines->layouts.createBindGroupTexSampled(context.samplerNearestRepeat, texView);
@ -39,6 +41,8 @@ void WgRenderStorage::release(WgContext& context)
context.pipelines->layouts.releaseBindGroup(bindGroupTexure); context.pipelines->layouts.releaseBindGroup(bindGroupTexure);
context.pipelines->layouts.releaseBindGroup(bindGroupWrite); context.pipelines->layouts.releaseBindGroup(bindGroupWrite);
context.pipelines->layouts.releaseBindGroup(bindGroupRead); context.pipelines->layouts.releaseBindGroup(bindGroupRead);
context.releaseTextureView(texViewMS);
context.releaseTexture(textureMS);
context.releaseTextureView(texView); context.releaseTextureView(texView);
context.releaseTexture(texture); context.releaseTexture(texture);
height = 0; height = 0;

View file

@ -28,7 +28,9 @@
struct WgRenderStorage { struct WgRenderStorage {
WGPUTexture texture{}; WGPUTexture texture{};
WGPUTexture textureMS{};
WGPUTextureView texView{}; WGPUTextureView texView{};
WGPUTextureView texViewMS{};
WGPUBindGroup bindGroupRead{}; WGPUBindGroup bindGroupRead{};
WGPUBindGroup bindGroupWrite{}; WGPUBindGroup bindGroupWrite{};
WGPUBindGroup bindGroupTexure{}; WGPUBindGroup bindGroupTexure{};