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 {
.usage = WGPUTextureUsage_CopySrc | WGPUTextureUsage_CopyDst | WGPUTextureUsage_TextureBinding | WGPUTextureUsage_StorageBinding | WGPUTextureUsage_RenderAttachment,
.dimension = WGPUTextureDimension_2D, .size = { width, height, 1 },
.format = format, .mipLevelCount = 1, .sampleCount = sc
.format = format, .mipLevelCount = 1, .sampleCount = 1
};
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 {
.usage = WGPUTextureUsage_RenderAttachment,

View file

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

View file

@ -37,9 +37,11 @@ class WgCompositor
private:
// pipelines (external handle, do not release)
WgPipelines* pipelines{};
// global stencil buffer handles
WGPUTexture texStencil{};
WGPUTextureView texViewStencil{};
// global stencil/depth buffer handles
WGPUTexture texDepthStencil{};
WGPUTextureView texViewDepthStencil{};
WGPUTexture texDepthStencilMS{};
WGPUTextureView texViewDepthStencilMS{};
// global view matrix handles
WGPUBuffer bufferViewMat{};
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 vertexBufferLayoutsShape[] { vertexBufferLayoutPos };
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;
// blend states
@ -452,7 +453,7 @@ void WgPipelines::initialize(WgContext& context)
WGPUColorWriteMask_All, context.preferredFormat,
WGPUCompareFunction_Always, WGPUStencilOperation_Zero,
WGPUCompareFunction_Always, WGPUStencilOperation_Zero,
WGPUCompareFunction_Always, false, multisampleState, blendStateSrc);
WGPUCompareFunction_Always, false, multisampleStateX1, blendStateSrc);
}
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->height = height;
texture = context.createTexStorage(width, height, WGPUTextureFormat_RGBA8Unorm);
textureMS = context.createTexAttachement(width, height, WGPUTextureFormat_RGBA8Unorm, 4);
texView = context.createTextureView(texture);
texViewMS = context.createTextureView(textureMS);
bindGroupRead = context.pipelines->layouts.createBindGroupStrorage1RO(texView);
bindGroupWrite = context.pipelines->layouts.createBindGroupStrorage1WO(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(bindGroupWrite);
context.pipelines->layouts.releaseBindGroup(bindGroupRead);
context.releaseTextureView(texViewMS);
context.releaseTexture(textureMS);
context.releaseTextureView(texView);
context.releaseTexture(texture);
height = 0;

View file

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