From 08153667637376669e59c6125487c836642d350b Mon Sep 17 00:00:00 2001 From: Sergii Liebodkin Date: Tue, 22 Oct 2024 09:23:15 +0000 Subject: [PATCH] wg_engine: clippath optimization Full review of clipping workflow. Before we are used separate render target for each clip path and compute shader to find clip path intersections with AND logic. Now we are using depth buffer and transactions from depth to stencil and back to get AND logic intersections, Compute shaders, layouts and pipelines was removed --- src/renderer/wg_engine/tvgWgCompositor.cpp | 344 +++++++++++++-------- src/renderer/wg_engine/tvgWgCompositor.h | 15 +- src/renderer/wg_engine/tvgWgPipelines.cpp | 140 +++++---- src/renderer/wg_engine/tvgWgPipelines.h | 18 +- src/renderer/wg_engine/tvgWgShaderSrc.cpp | 26 ++ src/renderer/wg_engine/tvgWgShaderSrc.h | 1 + 6 files changed, 330 insertions(+), 214 deletions(-) diff --git a/src/renderer/wg_engine/tvgWgCompositor.cpp b/src/renderer/wg_engine/tvgWgCompositor.cpp index 8b42ef0c..79aed684 100755 --- a/src/renderer/wg_engine/tvgWgCompositor.cpp +++ b/src/renderer/wg_engine/tvgWgCompositor.cpp @@ -31,7 +31,7 @@ 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_Stencil8); + texStencil = context.createTexStencil(width, height, WGPUTextureFormat_Depth24PlusStencil8); texViewStencil = context.createTextureView(texStencil); // allocate global view matrix handles WgShaderTypeMat4x4f viewMat(width, height); @@ -44,8 +44,6 @@ void WgCompositor::initialize(WgContext& context, uint32_t width, uint32_t heigh bindGroupOpacities[i] = pipelines->layouts.createBindGroupBuffer1Un(bufferOpacities[i]); } // initialize intermediate render storages - storageClipPath.initialize(context, width, height); - storageInterm.initialize(context, width, height); storageDstCopy.initialize(context, width, height); // composition and blend geometries meshData.blitBox(context); @@ -57,9 +55,7 @@ void WgCompositor::release(WgContext& context) // composition and blend geometries meshData.release(context); // release intermediate render storages - storageInterm.release(context); storageDstCopy.release(context); - storageClipPath.release(context); // release opacity pool for (uint32_t i = 0; i < 256; i++) { context.pipelines->layouts.releaseBindGroup(bindGroupOpacities[i]); @@ -94,7 +90,12 @@ void WgCompositor::beginRenderPass(WGPUCommandEncoder commandEncoder, WgRenderSt assert(target); this->currentTarget = target; this->commandEncoder = commandEncoder; - WGPURenderPassDepthStencilAttachment depthStencilAttachment{ .view = texViewStencil, .stencilLoadOp = WGPULoadOp_Clear, .stencilStoreOp = WGPUStoreOp_Discard }; + const WGPURenderPassDepthStencilAttachment depthStencilAttachment{ + .view = texViewStencil, + .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.loadOp = clear ? WGPULoadOp_Clear : WGPULoadOp_Load, @@ -124,14 +125,15 @@ void WgCompositor::renderShape(WgContext& context, WgRenderDataShape* renderData assert(renderPassEncoder); // apply clip path if neccessary if (renderData->clips.count != 0) { - renderClipPath(context, renderData, &storageClipPath); + renderClipPath(context, renderData); if (renderData->strokeFirst) { - clipStrokes(context, renderData, &storageClipPath); - clipShape(context, renderData, &storageClipPath); + clipStrokes(context, renderData); + clipShape(context, renderData); } else { - clipShape(context, renderData, &storageClipPath); - clipStrokes(context, renderData, &storageClipPath); + clipShape(context, renderData); + clipStrokes(context, renderData); } + clearClipPath(context, renderData); // use custom blending } else if (blendMethod != BlendMethod::Normal) { if (renderData->strokeFirst) { @@ -160,8 +162,9 @@ void WgCompositor::renderImage(WgContext& context, WgRenderDataPicture* renderDa assert(renderPassEncoder); // apply clip path if neccessary if (renderData->clips.count != 0) { - renderClipPath(context, renderData, &storageClipPath); - clipImage(context, renderData, &storageClipPath); + renderClipPath(context, renderData); + clipImage(context, renderData); + clearClipPath(context, renderData); // use custom blending } else if (blendMethod != BlendMethod::Normal) blendImage(context, renderData, blendMethod); @@ -200,12 +203,16 @@ void WgCompositor::composeScene(WgContext& context, WgRenderStorage* src, WgRend void WgCompositor::blit(WgContext& context, WGPUCommandEncoder encoder, WgRenderStorage* src, WGPUTextureView dstView) { - WGPURenderPassDepthStencilAttachment depthStencilAttachment{ .view = texViewStencil, .stencilLoadOp = WGPULoadOp_Load, .stencilStoreOp = WGPUStoreOp_Discard }; + const WGPURenderPassDepthStencilAttachment depthStencilAttachment{ + .view = texViewStencil, + .depthLoadOp = WGPULoadOp_Load, .depthStoreOp = WGPUStoreOp_Discard, + .stencilLoadOp = WGPULoadOp_Load, .stencilStoreOp = WGPUStoreOp_Discard + }; WGPURenderPassColorAttachment colorAttachment { .view = dstView, .loadOp = WGPULoadOp_Load, .storeOp = WGPUStoreOp_Store }; #ifdef __EMSCRIPTEN__ colorAttachment.depthSlice = WGPU_DEPTH_SLICE_UNDEFINED; #endif - WGPURenderPassDescriptor renderPassDesc{ .colorAttachmentCount = 1, .colorAttachments = &colorAttachment, .depthStencilAttachment = &depthStencilAttachment }; + const WGPURenderPassDescriptor renderPassDesc{ .colorAttachmentCount = 1, .colorAttachments = &colorAttachment, .depthStencilAttachment = &depthStencilAttachment }; WGPURenderPassEncoder renderPass = wgpuCommandEncoderBeginRenderPass(encoder, &renderPassDesc); wgpuRenderPassEncoderSetBindGroup(renderPass, 0, src->bindGroupTexure, 0, nullptr); wgpuRenderPassEncoderSetPipeline(renderPass, pipelines->blit); @@ -302,26 +309,46 @@ void WgCompositor::blendShape(WgContext& context, WgRenderDataShape* renderData, } -void WgCompositor::clipShape(WgContext& context, WgRenderDataShape* renderData, WgRenderStorage* mask) +void WgCompositor::clipShape(WgContext& context, WgRenderDataShape* renderData) { - assert(mask); assert(renderData); - assert(commandEncoder); - assert(currentTarget); - // skip shape composing if shape do not exist + assert(renderPassEncoder); + assert(renderData->meshGroupShapes.meshes.count == renderData->meshGroupShapesBBox.meshes.count); if (renderData->renderSettingsShape.skip) return; if (renderData->meshGroupShapes.meshes.count == 0) return; - // store current render pass - WgRenderStorage *target = currentTarget; - endRenderPass(); - // render into intermediate buffer - beginRenderPass(commandEncoder, &storageInterm, true); - drawShape(context, renderData); - endRenderPass(); - // restore current render pass - beginRenderPass(commandEncoder, target, false); - RenderRegion rect = shrinkRenderRegion(renderData->aabb); - clipRegion(context, &storageInterm, mask, rect); + if ((renderData->viewport.w <= 0) || (renderData->viewport.h <= 0)) return; + wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, renderData->viewport.x, renderData->viewport.y, renderData->viewport.w, renderData->viewport.h); + // setup stencil rules + WGPURenderPipeline stencilPipeline = (renderData->fillRule == FillRule::Winding) ? pipelines->winding : pipelines->evenodd; + wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0); + wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr); + wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr); + wgpuRenderPassEncoderSetPipeline(renderPassEncoder, stencilPipeline); + // draw to stencil (first pass) + for (uint32_t i = 0; i < renderData->meshGroupShapes.meshes.count; i++) + renderData->meshGroupShapes.meshes[i]->drawFan(context, renderPassEncoder); + // merge depth and stencil buffer + wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0); + wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, bindGroupOpacities[128], 0, nullptr); + wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines->merge_depth_stencil); + renderData->meshDataBBox.drawFan(context, renderPassEncoder); + // setup fill rules + wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0); + wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr); + wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr); + WgRenderSettings& settings = renderData->renderSettingsShape; + if (settings.fillType == WgRenderSettingsType::Solid) { + wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, settings.bindGroupSolid, 0, nullptr); + wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines->solid); + } else if (settings.fillType == WgRenderSettingsType::Linear) { + wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, settings.bindGroupGradient, 0, nullptr); + wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines->linear); + } else if (settings.fillType == WgRenderSettingsType::Radial) { + wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, settings.bindGroupGradient, 0, nullptr); + wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines->radial); + } + // draw to color (second pass) + renderData->meshDataBBox.drawFan(context, renderPassEncoder); } @@ -413,26 +440,47 @@ void WgCompositor::blendStrokes(WgContext& context, WgRenderDataShape* renderDat }; -void WgCompositor::clipStrokes(WgContext& context, WgRenderDataShape* renderData, WgRenderStorage* mask) +void WgCompositor::clipStrokes(WgContext& context, WgRenderDataShape* renderData) { - assert(mask); assert(renderData); - assert(commandEncoder); - assert(currentTarget); - // skip shape composing if strokes do not exist + assert(renderPassEncoder); + assert(renderData->meshGroupStrokes.meshes.count == renderData->meshGroupStrokesBBox.meshes.count); if (renderData->renderSettingsStroke.skip) return; if (renderData->meshGroupStrokes.meshes.count == 0) return; - // store current render pass - WgRenderStorage *target = currentTarget; - endRenderPass(); - // render into intermediate buffer - beginRenderPass(commandEncoder, &storageInterm, true); - drawStrokes(context, renderData); - endRenderPass(); - // restore current render pass - beginRenderPass(commandEncoder, target, false); - RenderRegion rect = shrinkRenderRegion(renderData->aabb); - clipRegion(context, &storageInterm, mask, rect); + if ((renderData->viewport.w <= 0) || (renderData->viewport.h <= 0)) return; + wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, renderData->viewport.x, renderData->viewport.y, renderData->viewport.w, renderData->viewport.h); + // draw strokes to stencil (first pass) + for (uint32_t i = 0; i < renderData->meshGroupStrokes.meshes.count; i++) { + // setup stencil rules + wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 255); + wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr); + wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr); + wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines->direct); + // draw to stencil (first pass) + renderData->meshGroupStrokes.meshes[i]->draw(context, renderPassEncoder); + // merge depth and stencil buffer + wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0); + wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, bindGroupOpacities[128], 0, nullptr); + wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines->merge_depth_stencil); + renderData->meshDataBBox.drawFan(context, renderPassEncoder); + // setup fill rules + wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0); + wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr); + wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr); + WgRenderSettings& settings = renderData->renderSettingsStroke; + if (settings.fillType == WgRenderSettingsType::Solid) { + wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, settings.bindGroupSolid, 0, nullptr); + wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines->solid); + } else if (settings.fillType == WgRenderSettingsType::Linear) { + wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, settings.bindGroupGradient, 0, nullptr); + wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines->linear); + } else if (settings.fillType == WgRenderSettingsType::Radial) { + wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, settings.bindGroupGradient, 0, nullptr); + wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines->radial); + } + // draw to color (second pass) + renderData->meshGroupStrokesBBox.meshes[i]->drawFan(context, renderPassEncoder); + } } @@ -442,6 +490,13 @@ void WgCompositor::drawImage(WgContext& context, WgRenderDataPicture* renderData assert(renderPassEncoder); if ((renderData->viewport.w <= 0) || (renderData->viewport.h <= 0)) return; wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, renderData->viewport.x, renderData->viewport.y, renderData->viewport.w, renderData->viewport.h); + // draw stencil + wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 255); + wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr); + wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr); + wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines->direct); + renderData->meshData.drawImage(context, renderPassEncoder); + // draw image wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0); wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr); wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr); @@ -456,6 +511,7 @@ void WgCompositor::blendImage(WgContext& context, WgRenderDataPicture* renderDat assert(renderData); assert(renderPassEncoder); if ((renderData->viewport.w <= 0) || (renderData->viewport.h <= 0)) return; + wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, renderData->viewport.x, renderData->viewport.y, renderData->viewport.w, renderData->viewport.h); // copy current render target data to dst storage WgRenderStorage *target = currentTarget; endRenderPass(); @@ -464,9 +520,14 @@ void WgCompositor::blendImage(WgContext& context, WgRenderDataPicture* renderDat const WGPUExtent3D copySize { .width = width, .height = height, .depthOrArrayLayers = 1 }; wgpuCommandEncoderCopyTextureToTexture(commandEncoder, &texSrc, &texDst, ©Size); beginRenderPass(commandEncoder, target, false); + // setup stencil rules + wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 255); + wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr); + wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr); + wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines->direct); + renderData->meshData.drawImage(context, renderPassEncoder); // blend image uint32_t blendMethodInd = (uint32_t)blendMethod; - wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, renderData->viewport.x, renderData->viewport.y, renderData->viewport.w, renderData->viewport.h); wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0); wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr); wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr); @@ -477,23 +538,30 @@ void WgCompositor::blendImage(WgContext& context, WgRenderDataPicture* renderDat }; -void WgCompositor::clipImage(WgContext& context, WgRenderDataPicture* renderData, WgRenderStorage* mask) +void WgCompositor::clipImage(WgContext& context, WgRenderDataPicture* renderData) { - assert(mask); assert(renderData); - assert(commandEncoder); - assert(currentTarget); - // store current render pass - WgRenderStorage *target = currentTarget; - endRenderPass(); - // render into intermediate buffer - beginRenderPass(commandEncoder, &storageInterm, true); - drawImage(context, renderData); - endRenderPass(); - // restore current render pass - beginRenderPass(commandEncoder, target, false); - RenderRegion rect { 0, 0, (int32_t)width, (int32_t)height }; - clipRegion(context, &storageInterm, mask, rect); + assert(renderPassEncoder); + if ((renderData->viewport.w <= 0) || (renderData->viewport.h <= 0)) return; + wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, renderData->viewport.x, renderData->viewport.y, renderData->viewport.w, renderData->viewport.h); + // setup stencil rules + wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 255); + wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr); + wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr); + wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines->direct); + renderData->meshData.drawImage(context, renderPassEncoder); + // merge depth and stencil buffer + wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0); + wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, bindGroupOpacities[128], 0, nullptr); + wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines->merge_depth_stencil); + renderData->meshData.drawImage(context, renderPassEncoder); + // draw image + wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0); + wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr); + wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr); + wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, renderData->bindGroupPicture, 0, nullptr); + wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines->image); + renderData->meshData.drawImage(context, renderPassEncoder); } @@ -539,85 +607,91 @@ void WgCompositor::blendScene(WgContext& context, WgRenderStorage* scene, WgComp } -void WgCompositor::drawClipPath(WgContext& context, WgRenderDataShape* renderData) +void WgCompositor::renderClipPath(WgContext& context, WgRenderDataPaint* paint) { - assert(renderData); + assert(paint); assert(renderPassEncoder); - assert(renderData->meshGroupShapes.meshes.count == renderData->meshGroupShapesBBox.meshes.count); - if ((renderData->viewport.w <= 0) || (renderData->viewport.h <= 0)) return; - wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, renderData->viewport.x, renderData->viewport.y, renderData->viewport.w, renderData->viewport.h); - // setup stencil rules - WGPURenderPipeline stencilPipeline = (renderData->fillRule == FillRule::Winding) ? pipelines->winding : pipelines->evenodd; - wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0); + assert(paint->clips.count > 0); + // reset scissor recr to full screen + wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, 0, 0, width, height); + // get render data + WgRenderDataShape* renderData0 = (WgRenderDataShape*)paint->clips[0]; + // set transformations wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr); - wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr); + // markup stencil + WGPURenderPipeline stencilPipeline = (renderData0->fillRule == FillRule::Winding) ? pipelines->winding : pipelines->evenodd; + wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0); + wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData0->bindGroupPaint, 0, nullptr); wgpuRenderPassEncoderSetPipeline(renderPassEncoder, stencilPipeline); - // draw to stencil (first pass) - for (uint32_t i = 0; i < renderData->meshGroupShapes.meshes.count; i++) - renderData->meshGroupShapes.meshes[i]->drawFan(context, renderPassEncoder); - // setup fill rules + for (uint32_t i = 0; i < renderData0->meshGroupShapes.meshes.count; i++) + renderData0->meshGroupShapes.meshes[i]->drawFan(context, renderPassEncoder); + // copy stencil to depth wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0); - wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr); - wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr); - wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines->clip_path); - // draw to color (second pass) - renderData->meshDataBBox.drawFan(context, renderPassEncoder); -} - - -void WgCompositor::clipRegion(WgContext& context, WgRenderStorage* src, WgRenderStorage* mask, RenderRegion& rect) -{ - wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, rect.x, rect.y, rect.w, rect.h); - wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0); - wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, storageInterm.bindGroupTexure, 0, nullptr); - wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, mask->bindGroupTexure, 0, nullptr); - wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines->scene_clip); - meshData.drawImage(context, renderPassEncoder); -} - - -void WgCompositor::renderClipPath(WgContext& context, WgRenderDataPaint* renderData, WgRenderStorage* dst) -{ - assert(renderData); - if (renderData->clips.count == 0) return; - // store current render pass - WgRenderStorage *target = currentTarget; - endRenderPass(); - // render first clip path - beginRenderPass(commandEncoder, dst, true); - drawClipPath(context, (WgRenderDataShape*)(renderData->clips[0])); - endRenderPass(); - // render amd merge clip paths - for (uint32_t i = 1 ; i < renderData->clips.count; i++) { - // render clip path - beginRenderPass(commandEncoder, &storageInterm, true); - drawClipPath(context, (WgRenderDataShape*)(renderData->clips[i])); - endRenderPass(); - // merge masks - mergeMasks(commandEncoder, &storageInterm, dst); + wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData0->bindGroupPaint, 0, nullptr); + wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, bindGroupOpacities[128], 0, nullptr); + wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines->copy_stencil_to_depth); + renderData0->meshDataBBox.drawFan(context, renderPassEncoder); + // merge clip pathes with AND logic + for (uint32_t clipIndex = 1; clipIndex < paint->clips.count; clipIndex++) { + // get render data + WgRenderDataShape* renderData = (WgRenderDataShape*)paint->clips[clipIndex]; + // markup stencil + WGPURenderPipeline stencilPipeline = (renderData->fillRule == FillRule::Winding) ? pipelines->winding : pipelines->evenodd; + wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0); + wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr); + wgpuRenderPassEncoderSetPipeline(renderPassEncoder, stencilPipeline); + for (uint32_t i = 0; i < renderData->meshGroupShapes.meshes.count; i++) + renderData->meshGroupShapes.meshes[i]->drawFan(context, renderPassEncoder); + // copy stencil to depth (clear stencil) + wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0); + wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr); + wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, bindGroupOpacities[190], 0, nullptr); + wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines->copy_stencil_to_depth_interm); + renderData->meshDataBBox.drawFan(context, renderPassEncoder); + // copy depth to stencil + wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 1); + wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr); + wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, bindGroupOpacities[190], 0, nullptr); + wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines->copy_depth_to_stencil); + renderData->meshDataBBox.drawFan(context, renderPassEncoder); + // clear depth current (keep stencil) + wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0); + wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr); + wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, bindGroupOpacities[255], 0, nullptr); + wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines->clear_depth); + renderData->meshDataBBox.drawFan(context, renderPassEncoder); + // clear depth original (keep stencil) + wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0); + wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData0->bindGroupPaint, 0, nullptr); + wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, bindGroupOpacities[255], 0, nullptr); + wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines->clear_depth); + renderData0->meshDataBBox.drawFan(context, renderPassEncoder); + // copy stencil to depth (clear stencil) + wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0); + wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr); + wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, bindGroupOpacities[128], 0, nullptr); + wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines->copy_stencil_to_depth); + renderData->meshDataBBox.drawFan(context, renderPassEncoder); } - // restore current render pass - beginRenderPass(commandEncoder, target, false); } -void WgCompositor::mergeMasks(WGPUCommandEncoder encoder, WgRenderStorage* mask0, WgRenderStorage* mask1) +void WgCompositor::clearClipPath(WgContext& context, WgRenderDataPaint* paint) { - assert(mask0); - assert(mask1); - assert(!renderPassEncoder); - // copy dst storage to temporary read only storage - const WGPUImageCopyTexture texSrc { .texture = mask1->texture }; - const WGPUImageCopyTexture texDst { .texture = storageDstCopy.texture }; - const WGPUExtent3D copySize { .width = width, .height = height, .depthOrArrayLayers = 1 }; - wgpuCommandEncoderCopyTextureToTexture(encoder, &texSrc, &texDst, ©Size); - // execute compose shader - const WGPUComputePassDescriptor computePassDescriptor{}; - WGPUComputePassEncoder computePassEncoder = wgpuCommandEncoderBeginComputePass(encoder, &computePassDescriptor); - wgpuComputePassEncoderSetBindGroup(computePassEncoder, 0, mask0->bindGroupRead, 0, nullptr); - wgpuComputePassEncoderSetBindGroup(computePassEncoder, 1, storageDstCopy.bindGroupRead, 0, nullptr); - wgpuComputePassEncoderSetBindGroup(computePassEncoder, 2, mask1->bindGroupWrite, 0, nullptr); - wgpuComputePassEncoderSetPipeline(computePassEncoder, pipelines->merge_masks); - wgpuComputePassEncoderDispatchWorkgroups(computePassEncoder, (width + 7) / 8, (height + 7) / 8, 1); - wgpuComputePassEncoderEnd(computePassEncoder); -} + assert(paint); + assert(renderPassEncoder); + assert(paint->clips.count > 0); + // reset scissor recr to full screen + wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, 0, 0, width, height); + // get render data + for (uint32_t clipIndex = 0; clipIndex < paint->clips.count; clipIndex++) { + WgRenderDataShape* renderData = (WgRenderDataShape*)paint->clips[clipIndex]; + // set transformations + wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0); + wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr); + wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr); + wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, bindGroupOpacities[255], 0, nullptr); + wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines->clear_depth); + renderData->meshDataBBox.drawFan(context, renderPassEncoder); + } +} \ No newline at end of file diff --git a/src/renderer/wg_engine/tvgWgCompositor.h b/src/renderer/wg_engine/tvgWgCompositor.h index e4d84290..dd5d467a 100755 --- a/src/renderer/wg_engine/tvgWgCompositor.h +++ b/src/renderer/wg_engine/tvgWgCompositor.h @@ -51,8 +51,6 @@ private: WGPUCommandEncoder commandEncoder{}; WgRenderStorage* currentTarget{}; // intermediate render storages - WgRenderStorage storageInterm; - WgRenderStorage storageClipPath; WgRenderStorage storageDstCopy; // composition and blend geometries WgMeshData meshData; @@ -82,27 +80,24 @@ private: // shapes void drawShape(WgContext& context, WgRenderDataShape* renderData); void blendShape(WgContext& context, WgRenderDataShape* renderData, BlendMethod blendMethod); - void clipShape(WgContext& context, WgRenderDataShape* renderData, WgRenderStorage* mask); // TODO: optimize + void clipShape(WgContext& context, WgRenderDataShape* renderData); // strokes void drawStrokes(WgContext& context, WgRenderDataShape* renderData); void blendStrokes(WgContext& context, WgRenderDataShape* renderData, BlendMethod blendMethod); - void clipStrokes(WgContext& context, WgRenderDataShape* renderData, WgRenderStorage* mask); // TODO: optimize + void clipStrokes(WgContext& context, WgRenderDataShape* renderData); // images void drawImage(WgContext& context, WgRenderDataPicture* renderData); void blendImage(WgContext& context, WgRenderDataPicture* renderData, BlendMethod blendMethod); - void clipImage(WgContext& context, WgRenderDataPicture* renderData, WgRenderStorage* mask); // TODO: optimize + void clipImage(WgContext& context, WgRenderDataPicture* renderData); // scenes void drawScene(WgContext& context, WgRenderStorage* scene, WgCompose* compose); void blendScene(WgContext& context, WgRenderStorage* src, WgCompose* compose); private: - // clip path utils (TODO: optimize) - void drawClipPath(WgContext& context, WgRenderDataShape* renderData); - void clipRegion(WgContext& context, WgRenderStorage* src, WgRenderStorage* mask, RenderRegion& rect); - void renderClipPath(WgContext& context, WgRenderDataPaint* renderData, WgRenderStorage* dst); - void mergeMasks(WGPUCommandEncoder encoder, WgRenderStorage* mask0, WgRenderStorage* mask1); + void renderClipPath(WgContext& context, WgRenderDataPaint* paint); + void clearClipPath(WgContext& context, WgRenderDataPaint* paint); }; #endif // _TVG_WG_COMPOSITOR_H_ diff --git a/src/renderer/wg_engine/tvgWgPipelines.cpp b/src/renderer/wg_engine/tvgWgPipelines.cpp index 7c8fa199..c1630f73 100755 --- a/src/renderer/wg_engine/tvgWgPipelines.cpp +++ b/src/renderer/wg_engine/tvgWgPipelines.cpp @@ -49,14 +49,15 @@ WGPURenderPipeline WgPipelines::createRenderPipeline( const WGPUColorWriteMaskFlags writeMask, const WGPUTextureFormat colorTargetFormat, const WGPUCompareFunction stencilFunctionFrnt, const WGPUStencilOperation stencilOperationFrnt, const WGPUCompareFunction stencilFunctionBack, const WGPUStencilOperation stencilOperationBack, - const WGPUPrimitiveState primitiveState, const WGPUMultisampleState multisampleState, const WGPUBlendState blendState) + const WGPUCompareFunction depthCompare, WGPUBool depthWriteEnabled, const WGPUMultisampleState multisampleState, const WGPUBlendState blendState) { const WGPUColorTargetState colorTargetState { .format = colorTargetFormat, .blend = &blendState, .writeMask = writeMask }; const WGPUColorTargetState colorTargetStates[] { colorTargetState }; + const WGPUPrimitiveState primitiveState { .topology = WGPUPrimitiveTopology_TriangleList }; const WGPUDepthStencilState depthStencilState { - .format = WGPUTextureFormat_Stencil8, .depthCompare = WGPUCompareFunction_Always, - .stencilFront = { .compare = stencilFunctionFrnt, .failOp = stencilOperationFrnt, .depthFailOp = stencilOperationFrnt, .passOp = stencilOperationFrnt }, - .stencilBack = { .compare = stencilFunctionBack, .failOp = stencilOperationBack, .depthFailOp = stencilOperationBack, .passOp = stencilOperationBack }, + .format = WGPUTextureFormat_Depth24PlusStencil8, .depthWriteEnabled = depthWriteEnabled, .depthCompare = depthCompare, + .stencilFront = { .compare = stencilFunctionFrnt, .failOp = stencilOperationFrnt, .depthFailOp = WGPUStencilOperation_Zero, .passOp = stencilOperationFrnt }, + .stencilBack = { .compare = stencilFunctionBack, .failOp = stencilOperationBack, .depthFailOp = WGPUStencilOperation_Zero, .passOp = stencilOperationBack }, .stencilReadMask = 0xFFFFFFFF, .stencilWriteMask = 0xFFFFFFFF }; const WGPUVertexState vertexState { .module = shaderModule, .entryPoint = vsEntryPoint, .bufferCount = vertexBufferLayoutsCount, .buffers = vertexBufferLayouts }; @@ -145,7 +146,6 @@ 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 WGPUPrimitiveState primitiveState { .topology = WGPUPrimitiveTopology_TriangleList }; const WGPUMultisampleState multisampleState { .count = 1, .mask = 0xFFFFFFFF, .alphaToCoverageEnabled = false }; const WGPUTextureFormat offscreenTargetFormat = WGPUTextureFormat_RGBA8Unorm; @@ -161,6 +161,7 @@ void WgPipelines::initialize(WgContext& context) // bind group layouts helpers const WGPUBindGroupLayout bindGroupLayoutsStencil[] = { layouts.layoutBuffer1Un, layouts.layoutBuffer2Un }; + const WGPUBindGroupLayout bindGroupLayoutsDepth[] = { layouts.layoutBuffer1Un, layouts.layoutBuffer2Un, layouts.layoutBuffer1Un }; // bind group layouts normal blend const WGPUBindGroupLayout bindGroupLayoutsSolid[] { layouts.layoutBuffer1Un, layouts.layoutBuffer2Un, layouts.layoutBuffer1Un }; const WGPUBindGroupLayout bindGroupLayoutsGradient[] { layouts.layoutBuffer1Un, layouts.layoutBuffer2Un, layouts.layoutTexSampledBuff2Un }; @@ -173,13 +174,13 @@ void WgPipelines::initialize(WgContext& context) const WGPUBindGroupLayout bindGroupLayoutsSceneBlend[] { layouts.layoutTexSampled, layouts.layoutTexSampled, layouts.layoutBuffer1Un }; // bind group layouts scene compose const WGPUBindGroupLayout bindGroupLayoutsSceneCompose[] { layouts.layoutTexSampled, layouts.layoutTexSampled }; - const WGPUBindGroupLayout bindGroupLayoutsMergeMasks[] { layouts.layoutTexStrorage1RO, layouts.layoutTexStrorage1RO, layouts.layoutTexStrorage1WO }; // bind group layouts blit const WGPUBindGroupLayout bindGroupLayoutsBlit[] { layouts.layoutTexSampled }; // shaders char shaderSourceBuff[16384]{}; shader_stencil = createShaderModule(context.device, "The shader stencil", cShaderSrc_Stencil); + shader_depth = createShaderModule(context.device, "The shader depth", cShaderSrc_Depth); // shader normal blend shader_solid = createShaderModule(context.device, "The shader solid", cShaderSrc_Solid); shader_radial = createShaderModule(context.device, "The shader radial", cShaderSrc_Radial); @@ -194,12 +195,12 @@ void WgPipelines::initialize(WgContext& context) shader_scene_blend = createShaderModule(context.device, "The shader blend scene", strcat(strcpy(shaderSourceBuff, cShaderSrc_Scene_Blend), cShaderSrc_BlendFuncs)); // shader compose shader_scene_compose = createShaderModule(context.device, "The shader scene composition", cShaderSrc_Scene_Compose); - shader_merge_masks = createShaderModule(context.device, "The shader merge mask", cShaderSrc_MergeMasks); // shader blit shader_blit = createShaderModule(context.device, "The shader blit", cShaderSrc_Blit); // layouts layout_stencil = createPipelineLayout(context.device, bindGroupLayoutsStencil, 2); + layout_depth = createPipelineLayout(context.device, bindGroupLayoutsDepth, 3); // layouts normal blend layout_solid = createPipelineLayout(context.device, bindGroupLayoutsSolid, 3); layout_gradient = createPipelineLayout(context.device, bindGroupLayoutsGradient, 3); @@ -212,7 +213,6 @@ void WgPipelines::initialize(WgContext& context) layout_scene_blend = createPipelineLayout(context.device, bindGroupLayoutsSceneBlend, 3); // layout compose layout_scene_compose = createPipelineLayout(context.device, bindGroupLayoutsSceneCompose, 2); - layout_merge_masks = createPipelineLayout(context.device, bindGroupLayoutsMergeMasks, 3); // layout blit layout_blit = createPipelineLayout(context.device, bindGroupLayoutsBlit, 1); @@ -224,7 +224,7 @@ void WgPipelines::initialize(WgContext& context) WGPUColorWriteMask_None, offscreenTargetFormat, WGPUCompareFunction_Always, WGPUStencilOperation_IncrementWrap, WGPUCompareFunction_Always, WGPUStencilOperation_DecrementWrap, - primitiveState, multisampleState, blendStateSrc); + WGPUCompareFunction_Always, false, multisampleState, blendStateSrc); // render pipeline even-odd evenodd = createRenderPipeline( context.device, "The render pipeline even-odd", @@ -233,7 +233,7 @@ void WgPipelines::initialize(WgContext& context) WGPUColorWriteMask_None, offscreenTargetFormat, WGPUCompareFunction_Always, WGPUStencilOperation_Invert, WGPUCompareFunction_Always, WGPUStencilOperation_Invert, - primitiveState, multisampleState, blendStateSrc); + WGPUCompareFunction_Always, false, multisampleState, blendStateSrc); // render pipeline direct direct = createRenderPipeline( context.device, "The render pipeline direct", @@ -242,16 +242,53 @@ void WgPipelines::initialize(WgContext& context) WGPUColorWriteMask_None, offscreenTargetFormat, WGPUCompareFunction_Always, WGPUStencilOperation_Replace, WGPUCompareFunction_Always, WGPUStencilOperation_Replace, - primitiveState, multisampleState, blendStateSrc); - // render pipeline clip path - clip_path = createRenderPipeline( - context.device, "The render pipeline clip path", - shader_stencil, "vs_main", "fs_main", layout_stencil, + WGPUCompareFunction_Always, false, multisampleState, blendStateSrc); + + // render pipeline copy stencil to depth (front) + copy_stencil_to_depth = createRenderPipeline( + context.device, "The render pipeline copy stencil to depth front", + shader_depth, "vs_main", "fs_main", layout_depth, vertexBufferLayoutsShape, 1, - WGPUColorWriteMask_All, offscreenTargetFormat, + WGPUColorWriteMask_None, offscreenTargetFormat, WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero, WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero, - primitiveState, multisampleState, blendStateSrc); + WGPUCompareFunction_Always, true, multisampleState, blendStateSrc); + // render pipeline copy stencil to depth (intermidiate) + copy_stencil_to_depth_interm = createRenderPipeline( + context.device, "The render pipeline copy stencil to depth intermidiate", + shader_depth, "vs_main", "fs_main", layout_depth, + vertexBufferLayoutsShape, 1, + WGPUColorWriteMask_None, offscreenTargetFormat, + WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero, + WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero, + WGPUCompareFunction_Greater, true, multisampleState, blendStateSrc); + // render pipeline depth to stencil + copy_depth_to_stencil = createRenderPipeline( + context.device, "The render pipeline depth to stencil", + shader_depth, "vs_main", "fs_main", layout_depth, + vertexBufferLayoutsShape, 1, + WGPUColorWriteMask_None, offscreenTargetFormat, + WGPUCompareFunction_Always, WGPUStencilOperation_Replace, + WGPUCompareFunction_Always, WGPUStencilOperation_Replace, + WGPUCompareFunction_Equal, false, multisampleState, blendStateSrc); + // render pipeline merge depth with stencil + merge_depth_stencil = createRenderPipeline( + context.device, "The render pipeline merge depth with stencil", + shader_depth, "vs_main", "fs_main", layout_depth, + vertexBufferLayoutsShape, 1, + WGPUColorWriteMask_None, offscreenTargetFormat, + WGPUCompareFunction_Always, WGPUStencilOperation_Keep, + WGPUCompareFunction_Always, WGPUStencilOperation_Keep, + WGPUCompareFunction_Equal, true, multisampleState, blendStateSrc); + // render pipeline clear depth + clear_depth = createRenderPipeline( + context.device, "The render pipeline clear depth", + shader_depth, "vs_main", "fs_main", layout_depth, + vertexBufferLayoutsShape, 1, + WGPUColorWriteMask_None, offscreenTargetFormat, + WGPUCompareFunction_Always, WGPUStencilOperation_Keep, + WGPUCompareFunction_Always, WGPUStencilOperation_Keep, + WGPUCompareFunction_Always, true, multisampleState, blendStateSrc); // render pipeline solid solid = createRenderPipeline( @@ -261,7 +298,7 @@ void WgPipelines::initialize(WgContext& context) WGPUColorWriteMask_All, offscreenTargetFormat, WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero, WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero, - primitiveState, multisampleState, blendStateNrm); + WGPUCompareFunction_Always, false, multisampleState, blendStateNrm); // render pipeline radial radial = createRenderPipeline( context.device, "The render pipeline radial", @@ -270,7 +307,7 @@ void WgPipelines::initialize(WgContext& context) WGPUColorWriteMask_All, offscreenTargetFormat, WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero, WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero, - primitiveState, multisampleState, blendStateNrm); + WGPUCompareFunction_Always, false, multisampleState, blendStateNrm); // render pipeline linear linear = createRenderPipeline( context.device, "The render pipeline linear", @@ -279,16 +316,16 @@ void WgPipelines::initialize(WgContext& context) WGPUColorWriteMask_All, offscreenTargetFormat, WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero, WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero, - primitiveState, multisampleState, blendStateNrm); + WGPUCompareFunction_Always, false, multisampleState, blendStateNrm); // render pipeline image image = createRenderPipeline( context.device, "The render pipeline image", shader_image, "vs_main", "fs_main", layout_image, vertexBufferLayoutsImage, 2, WGPUColorWriteMask_All, offscreenTargetFormat, - WGPUCompareFunction_Always, WGPUStencilOperation_Zero, - WGPUCompareFunction_Always, WGPUStencilOperation_Zero, - primitiveState, multisampleState, blendStateNrm); + WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero, + WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero, + WGPUCompareFunction_Always, false, multisampleState, blendStateNrm); // render pipeline scene scene = createRenderPipeline( context.device, "The render pipeline scene", @@ -297,7 +334,7 @@ void WgPipelines::initialize(WgContext& context) WGPUColorWriteMask_All, offscreenTargetFormat, WGPUCompareFunction_Always, WGPUStencilOperation_Zero, WGPUCompareFunction_Always, WGPUStencilOperation_Zero, - primitiveState, multisampleState, blendStateNrm); + WGPUCompareFunction_Always, false, multisampleState, blendStateNrm); // blend shader names const char* shaderBlendNames[] { @@ -330,7 +367,7 @@ void WgPipelines::initialize(WgContext& context) WGPUColorWriteMask_All, offscreenTargetFormat, WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero, WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero, - primitiveState, multisampleState, blendStateSrc); + WGPUCompareFunction_Always, false, multisampleState, blendStateSrc); // blend radial radial_blend[i] = createRenderPipeline(context.device, "The render pipeline radial blend", shader_radial_blend, "vs_main", shaderBlendNames[i], layout_gradient_blend, @@ -338,7 +375,7 @@ void WgPipelines::initialize(WgContext& context) WGPUColorWriteMask_All, offscreenTargetFormat, WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero, WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero, - primitiveState, multisampleState, blendStateSrc); + WGPUCompareFunction_Always, false, multisampleState, blendStateSrc); // blend linear linear_blend[i] = createRenderPipeline(context.device, "The render pipeline linear blend", shader_linear_blend, "vs_main", shaderBlendNames[i], layout_gradient_blend, @@ -346,15 +383,15 @@ void WgPipelines::initialize(WgContext& context) WGPUColorWriteMask_All, offscreenTargetFormat, WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero, WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero, - primitiveState, multisampleState, blendStateSrc); + WGPUCompareFunction_Always, false, multisampleState, blendStateSrc); // blend image image_blend[i] = createRenderPipeline(context.device, "The render pipeline image blend", shader_image_blend, "vs_main", shaderBlendNames[i], layout_image_blend, vertexBufferLayoutsImage, 2, WGPUColorWriteMask_All, offscreenTargetFormat, - WGPUCompareFunction_Always, WGPUStencilOperation_Zero, - WGPUCompareFunction_Always, WGPUStencilOperation_Zero, - primitiveState, multisampleState, blendStateSrc); + WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero, + WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero, + WGPUCompareFunction_Always, false, multisampleState, blendStateSrc); // blend scene scene_blend[i] = createRenderPipeline(context.device, "The render pipeline scene blend", shader_scene_blend, "vs_main", shaderBlendNames[i], layout_scene_blend, @@ -362,7 +399,7 @@ void WgPipelines::initialize(WgContext& context) WGPUColorWriteMask_All, offscreenTargetFormat, WGPUCompareFunction_Always, WGPUStencilOperation_Zero, WGPUCompareFunction_Always, WGPUStencilOperation_Zero, - primitiveState, multisampleState, blendStateSrc); + WGPUCompareFunction_Always, false, multisampleState, blendStateSrc); } // compose shader names @@ -404,24 +441,9 @@ void WgPipelines::initialize(WgContext& context) WGPUColorWriteMask_All, offscreenTargetFormat, WGPUCompareFunction_Always, WGPUStencilOperation_Zero, WGPUCompareFunction_Always, WGPUStencilOperation_Zero, - primitiveState, multisampleState, composeBlends[i]); + WGPUCompareFunction_Always, false, multisampleState, composeBlends[i]); } - // render pipeline scene clip path - scene_clip = createRenderPipeline( - context.device, "The render pipeline scene clip path", - shader_scene_compose, "vs_main", "fs_main_ClipPath", layout_scene_compose, - vertexBufferLayoutsImage, 2, - WGPUColorWriteMask_All, offscreenTargetFormat, - WGPUCompareFunction_Always, WGPUStencilOperation_Zero, - WGPUCompareFunction_Always, WGPUStencilOperation_Zero, - primitiveState, multisampleState, blendStateNrm); - - // compute pipelines - merge_masks = createComputePipeline( - context.device, "The compute pipeline merge masks", - shader_merge_masks, "cs_main", layout_merge_masks); - // render pipeline blit blit = createRenderPipeline(context.device, "The render pipeline blit", shader_blit, "vs_main", "fs_main", layout_blit, @@ -430,7 +452,7 @@ void WgPipelines::initialize(WgContext& context) WGPUColorWriteMask_All, context.preferredFormat, WGPUCompareFunction_Always, WGPUStencilOperation_Zero, WGPUCompareFunction_Always, WGPUStencilOperation_Zero, - primitiveState, multisampleState, blendStateSrc); + WGPUCompareFunction_Always, false, multisampleState, blendStateSrc); } void WgPipelines::releaseGraphicHandles(WgContext& context) @@ -438,7 +460,6 @@ void WgPipelines::releaseGraphicHandles(WgContext& context) // pipeline blit releaseRenderPipeline(blit); // pipelines compose - releaseRenderPipeline(scene_clip); for (uint32_t i = 0; i < 11; i++) releaseRenderPipeline(scene_compose[i]); // pipelines custom blend @@ -455,14 +476,18 @@ void WgPipelines::releaseGraphicHandles(WgContext& context) releaseRenderPipeline(linear); releaseRenderPipeline(radial); releaseRenderPipeline(solid); - // pipelines helpers - releaseRenderPipeline(clip_path); + // pipelines clip path markup + releaseRenderPipeline(clear_depth); + releaseRenderPipeline(merge_depth_stencil); + releaseRenderPipeline(copy_depth_to_stencil); + releaseRenderPipeline(copy_stencil_to_depth_interm); + releaseRenderPipeline(copy_stencil_to_depth); + // pipelines stencil markup releaseRenderPipeline(direct); releaseRenderPipeline(evenodd); releaseRenderPipeline(winding); // layouts releasePipelineLayout(layout_blit); - releasePipelineLayout(layout_merge_masks); releasePipelineLayout(layout_scene_compose); releasePipelineLayout(layout_scene_blend); releasePipelineLayout(layout_image_blend); @@ -472,10 +497,10 @@ void WgPipelines::releaseGraphicHandles(WgContext& context) releasePipelineLayout(layout_image); releasePipelineLayout(layout_gradient); releasePipelineLayout(layout_solid); + releasePipelineLayout(layout_depth); releasePipelineLayout(layout_stencil); // shaders releaseShaderModule(shader_blit); - releaseShaderModule(shader_merge_masks); releaseShaderModule(shader_scene_compose); releaseShaderModule(shader_scene_blend); releaseShaderModule(shader_image_blend); @@ -487,20 +512,13 @@ void WgPipelines::releaseGraphicHandles(WgContext& context) releaseShaderModule(shader_linear); releaseShaderModule(shader_radial); releaseShaderModule(shader_solid); + releaseShaderModule(shader_depth); releaseShaderModule(shader_stencil); } -void WgPipelines::releaseComputeHandles(WgContext& context) -{ - releaseComputePipeline(merge_masks); - releasePipelineLayout(layout_merge_masks); - releaseShaderModule(shader_merge_masks); -} - void WgPipelines::release(WgContext& context) { - releaseComputeHandles(context); releaseGraphicHandles(context); layouts.release(context); } diff --git a/src/renderer/wg_engine/tvgWgPipelines.h b/src/renderer/wg_engine/tvgWgPipelines.h index 264bb2c8..3fd5b37d 100755 --- a/src/renderer/wg_engine/tvgWgPipelines.h +++ b/src/renderer/wg_engine/tvgWgPipelines.h @@ -29,6 +29,7 @@ class WgPipelines { private: // shaders helpers WGPUShaderModule shader_stencil{}; + WGPUShaderModule shader_depth{}; // shaders normal blend WGPUShaderModule shader_solid{}; WGPUShaderModule shader_radial{}; @@ -43,12 +44,12 @@ private: WGPUShaderModule shader_scene_blend{}; // shader scene compose WGPUShaderModule shader_scene_compose{}; - WGPUShaderModule shader_merge_masks; // shader blit WGPUShaderModule shader_blit{}; private: // layouts helpers WGPUPipelineLayout layout_stencil{}; + WGPUPipelineLayout layout_depth{}; // layouts normal blend WGPUPipelineLayout layout_solid{}; WGPUPipelineLayout layout_gradient{}; @@ -61,15 +62,19 @@ private: WGPUPipelineLayout layout_scene_blend{}; // layouts scene compose WGPUPipelineLayout layout_scene_compose{}; - WGPUPipelineLayout layout_merge_masks{}; // layouts blit WGPUPipelineLayout layout_blit{}; public: - // pipelines helpers + // pipelines stencil markup WGPURenderPipeline winding{}; WGPURenderPipeline evenodd{}; WGPURenderPipeline direct{}; - WGPURenderPipeline clip_path{}; + // pipelines clip path markup + WGPURenderPipeline copy_stencil_to_depth{}; // depth 0.50, clear stencil + WGPURenderPipeline copy_stencil_to_depth_interm{}; // depth 0.75, clear stencil + WGPURenderPipeline copy_depth_to_stencil{}; // depth 0.50 and 0.75, update stencil + WGPURenderPipeline merge_depth_stencil{}; // depth 0.75, update stencil + WGPURenderPipeline clear_depth{}; // depth 1.00, clear ctencil // pipelines normal blend WGPURenderPipeline solid{}; WGPURenderPipeline radial{}; @@ -84,8 +89,6 @@ public: WGPURenderPipeline scene_blend[18]{}; // pipelines compose WGPURenderPipeline scene_compose[11]{}; - WGPURenderPipeline scene_clip{}; - WGPUComputePipeline merge_masks{}; // pipeline blit WGPURenderPipeline blit{}; public: @@ -93,7 +96,6 @@ public: WgBindGroupLayouts layouts; private: void releaseGraphicHandles(WgContext& context); - void releaseComputeHandles(WgContext& context); private: WGPUShaderModule createShaderModule(WGPUDevice device, const char* label, const char* code); WGPUPipelineLayout createPipelineLayout(WGPUDevice device, const WGPUBindGroupLayout* bindGroupLayouts, const uint32_t bindGroupLayoutsCount); @@ -105,7 +107,7 @@ private: const WGPUColorWriteMaskFlags writeMask, const WGPUTextureFormat colorTargetFormat, const WGPUCompareFunction stencilFunctionFrnt, const WGPUStencilOperation stencilOperationFrnt, const WGPUCompareFunction stencilFunctionBack, const WGPUStencilOperation stencilOperationBack, - const WGPUPrimitiveState primitiveState, const WGPUMultisampleState multisampleState, const WGPUBlendState blendState); + const WGPUCompareFunction depthCompare, WGPUBool depthWriteEnabled, const WGPUMultisampleState multisampleState, const WGPUBlendState blendState); WGPUComputePipeline createComputePipeline( WGPUDevice device, const char* pipelineLabel, const WGPUShaderModule shaderModule, const char* entryPoint, diff --git a/src/renderer/wg_engine/tvgWgShaderSrc.cpp b/src/renderer/wg_engine/tvgWgShaderSrc.cpp index 2e2f8134..cd8baf10 100755 --- a/src/renderer/wg_engine/tvgWgShaderSrc.cpp +++ b/src/renderer/wg_engine/tvgWgShaderSrc.cpp @@ -49,6 +49,32 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4f { } )"; +//************************************************************************ +// graphics shader source: depth +//************************************************************************ + +const char* cShaderSrc_Depth = R"( +struct VertexInput { @location(0) position: vec2f }; +struct VertexOutput { @builtin(position) position: vec4f }; + +@group(0) @binding(0) var uViewMat : mat4x4f; +@group(1) @binding(0) var uModelMat : mat4x4f; +@group(2) @binding(0) var uDepth : f32; + +@vertex +fn vs_main(in: VertexInput) -> VertexOutput { + var out: VertexOutput; + out.position = uViewMat * uModelMat * vec4f(in.position.xy, 0.0, 1.0); + out.position.z = uDepth; + return out; +} + +@fragment +fn fs_main(in: VertexOutput) -> @location(0) vec4f { + return vec4f(1.0, 0.5, 0.0, 1.0); +} +)"; + //************************************************************************ // graphics shader source: solid normal blend //************************************************************************ diff --git a/src/renderer/wg_engine/tvgWgShaderSrc.h b/src/renderer/wg_engine/tvgWgShaderSrc.h index 0af1192d..d161d239 100755 --- a/src/renderer/wg_engine/tvgWgShaderSrc.h +++ b/src/renderer/wg_engine/tvgWgShaderSrc.h @@ -25,6 +25,7 @@ // helper shaders extern const char* cShaderSrc_Stencil; +extern const char* cShaderSrc_Depth; // shaders normal blend extern const char* cShaderSrc_Solid; extern const char* cShaderSrc_Linear;