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;