diff --git a/src/renderer/wg_engine/tvgWgCommon.cpp b/src/renderer/wg_engine/tvgWgCommon.cpp index d26cd0a3..08f216ea 100644 --- a/src/renderer/wg_engine/tvgWgCommon.cpp +++ b/src/renderer/wg_engine/tvgWgCommon.cpp @@ -550,7 +550,8 @@ void WgPipeline::destroyShaderModule(WGPUShaderModule& shaderModule) void WgRenderPipeline::allocate(WGPUDevice device, WgPipelineBlendType blendType, WGPUVertexBufferLayout vertexBufferLayouts[], uint32_t attribsCount, WGPUBindGroupLayout bindGroupLayouts[], uint32_t bindGroupsCount, - WGPUCompareFunction stencilCompareFunction, WGPUStencilOperation stencilOperation, + WGPUCompareFunction compareFront, WGPUStencilOperation operationFront, + WGPUCompareFunction compareBack, WGPUStencilOperation operationBack, const char* shaderSource, const char* shaderLabel, const char* pipelineLabel) { mShaderModule = createShaderModule(device, shaderSource, shaderLabel); @@ -561,7 +562,8 @@ void WgRenderPipeline::allocate(WGPUDevice device, WgPipelineBlendType blendType mRenderPipeline = createRenderPipeline(device, blendType, vertexBufferLayouts, attribsCount, - stencilCompareFunction, stencilOperation, + compareFront, operationFront, + compareBack, operationBack, mPipelineLayout, mShaderModule, pipelineLabel); assert(mRenderPipeline); } @@ -670,21 +672,21 @@ WGPUPrimitiveState WgRenderPipeline::makePrimitiveState() } -WGPUDepthStencilState WgRenderPipeline::makeDepthStencilState(WGPUCompareFunction compare, WGPUStencilOperation operation) +WGPUDepthStencilState WgRenderPipeline::makeDepthStencilState(WGPUCompareFunction compareFront, WGPUStencilOperation operationFront, WGPUCompareFunction compareBack, WGPUStencilOperation operationBack) { WGPUDepthStencilState depthStencilState{}; depthStencilState.nextInChain = nullptr; depthStencilState.format = WGPUTextureFormat_Stencil8; depthStencilState.depthWriteEnabled = false; depthStencilState.depthCompare = WGPUCompareFunction_Always; - depthStencilState.stencilFront.compare = compare; - depthStencilState.stencilFront.failOp = operation; - depthStencilState.stencilFront.depthFailOp = operation; - depthStencilState.stencilFront.passOp = operation; - depthStencilState.stencilBack.compare = compare; - depthStencilState.stencilBack.failOp = operation; - depthStencilState.stencilBack.depthFailOp = operation; - depthStencilState.stencilBack.passOp = operation; + depthStencilState.stencilFront.compare = compareFront; + depthStencilState.stencilFront.failOp = operationFront; + depthStencilState.stencilFront.depthFailOp = operationFront; + depthStencilState.stencilFront.passOp = operationFront; + depthStencilState.stencilBack.compare = compareBack; + depthStencilState.stencilBack.failOp = operationBack; + depthStencilState.stencilBack.depthFailOp = operationBack; + depthStencilState.stencilBack.passOp = operationBack; depthStencilState.stencilReadMask = 0xFFFFFFFF; depthStencilState.stencilWriteMask = 0xFFFFFFFF; depthStencilState.depthBias = 0; @@ -721,7 +723,8 @@ WGPUFragmentState WgRenderPipeline::makeFragmentState(WGPUShaderModule shaderMod WGPURenderPipeline WgRenderPipeline::createRenderPipeline(WGPUDevice device, WgPipelineBlendType blendType, WGPUVertexBufferLayout vertexBufferLayouts[], uint32_t attribsCount, - WGPUCompareFunction stencilCompareFunction, WGPUStencilOperation stencilOperation, + WGPUCompareFunction compareFront, WGPUStencilOperation operationFront, + WGPUCompareFunction compareBack, WGPUStencilOperation operationBack, WGPUPipelineLayout pipelineLayout, WGPUShaderModule shaderModule, const char* pipelineName) { @@ -732,7 +735,7 @@ WGPURenderPipeline WgRenderPipeline::createRenderPipeline(WGPUDevice device, WgP WGPUVertexState vertexState = makeVertexState(shaderModule, vertexBufferLayouts, attribsCount); WGPUPrimitiveState primitiveState = makePrimitiveState(); - WGPUDepthStencilState depthStencilState = makeDepthStencilState(stencilCompareFunction, stencilOperation); + WGPUDepthStencilState depthStencilState = makeDepthStencilState(compareFront, operationFront, compareBack, operationBack); WGPUMultisampleState multisampleState = makeMultisampleState(); WGPUFragmentState fragmentState = makeFragmentState(shaderModule, colorTargetStates, 1); diff --git a/src/renderer/wg_engine/tvgWgCommon.h b/src/renderer/wg_engine/tvgWgCommon.h index 668552a9..41410108 100644 --- a/src/renderer/wg_engine/tvgWgCommon.h +++ b/src/renderer/wg_engine/tvgWgCommon.h @@ -128,7 +128,8 @@ protected: void allocate(WGPUDevice device, WgPipelineBlendType blendType, WGPUVertexBufferLayout vertexBufferLayouts[], uint32_t attribsCount, WGPUBindGroupLayout bindGroupLayouts[], uint32_t bindGroupsCount, - WGPUCompareFunction stencilCompareFunction, WGPUStencilOperation stencilOperation, + WGPUCompareFunction compareFront, WGPUStencilOperation operationFront, + WGPUCompareFunction compareBack, WGPUStencilOperation operationBack, const char* shaderSource, const char* shaderLabel, const char* pipelineLabel); public: void release() override; @@ -139,13 +140,14 @@ public: static WGPUVertexBufferLayout makeVertexBufferLayout(const WGPUVertexAttribute* vertexAttributes, uint32_t count, uint64_t stride); static WGPUVertexState makeVertexState(WGPUShaderModule shaderModule, const WGPUVertexBufferLayout* buffers, uint32_t count); static WGPUPrimitiveState makePrimitiveState(); - static WGPUDepthStencilState makeDepthStencilState(WGPUCompareFunction compare, WGPUStencilOperation operation); + static WGPUDepthStencilState makeDepthStencilState(WGPUCompareFunction compareFront, WGPUStencilOperation operationFront, WGPUCompareFunction compareBack, WGPUStencilOperation operationBack); static WGPUMultisampleState makeMultisampleState(); static WGPUFragmentState makeFragmentState(WGPUShaderModule shaderModule, WGPUColorTargetState* targets, uint32_t size); static WGPURenderPipeline createRenderPipeline(WGPUDevice device, WgPipelineBlendType blendType, WGPUVertexBufferLayout vertexBufferLayouts[], uint32_t attribsCount, - WGPUCompareFunction stencilCompareFunction, WGPUStencilOperation stencilOperation, + WGPUCompareFunction compareFront, WGPUStencilOperation operationFront, + WGPUCompareFunction compareBack, WGPUStencilOperation operationBack, WGPUPipelineLayout pipelineLayout, WGPUShaderModule shaderModule, const char* pipelineLabel); static void destroyRenderPipeline(WGPURenderPipeline& renderPipeline); diff --git a/src/renderer/wg_engine/tvgWgPipelines.cpp b/src/renderer/wg_engine/tvgWgPipelines.cpp index de969815..b9e03851 100644 --- a/src/renderer/wg_engine/tvgWgPipelines.cpp +++ b/src/renderer/wg_engine/tvgWgPipelines.cpp @@ -29,7 +29,7 @@ // graphics pipelines //************************************************************************ -void WgPipelineFillShape::initialize(WGPUDevice device) +void WgPipelineFillShapeWinding::initialize(WGPUDevice device) { // vertex attributes settings WGPUVertexAttribute vertexAttributesPos = { WGPUVertexFormat_Float32x2, sizeof(float) * 0, 0 }; @@ -44,19 +44,55 @@ void WgPipelineFillShape::initialize(WGPUDevice device) }; // stencil function - WGPUCompareFunction stencilFuncion = WGPUCompareFunction_Always; - WGPUStencilOperation stencilOperation = WGPUStencilOperation_Invert; + WGPUCompareFunction stencilFuncionFront = WGPUCompareFunction_Always; + WGPUStencilOperation stencilOperationFront = WGPUStencilOperation_IncrementWrap; + WGPUCompareFunction stencilFuncionBack = WGPUCompareFunction_Always; + WGPUStencilOperation stencilOperationBack = WGPUStencilOperation_DecrementWrap; // sheder source and labels auto shaderSource = cShaderSource_PipelineFill; auto shaderLabel = "The shader fill"; - auto pipelineLabel = "The render pipeline fill shape"; + auto pipelineLabel = "The render pipeline fill shape winding"; // allocate all pipeline handles allocate(device, WgPipelineBlendType::Src, vertexBufferLayouts, ARRAY_ELEMENTS_COUNT(vertexBufferLayouts), bindGroupLayouts, ARRAY_ELEMENTS_COUNT(bindGroupLayouts), - stencilFuncion, stencilOperation, + stencilFuncionFront, stencilOperationFront, stencilFuncionBack, stencilOperationBack, + shaderSource, shaderLabel, pipelineLabel); +} + + +void WgPipelineFillShapeEvenOdd::initialize(WGPUDevice device) +{ + // vertex attributes settings + WGPUVertexAttribute vertexAttributesPos = { WGPUVertexFormat_Float32x2, sizeof(float) * 0, 0 }; + WGPUVertexBufferLayout vertexBufferLayouts[] = { + makeVertexBufferLayout(&vertexAttributesPos, 1, sizeof(float) * 2) + }; + + // bind groups + WGPUBindGroupLayout bindGroupLayouts[] = { + WgBindGroupCanvas::getLayout(device), + WgBindGroupPaint::getLayout(device) + }; + + // stencil function + WGPUCompareFunction stencilFuncionFront = WGPUCompareFunction_Always; + WGPUStencilOperation stencilOperationFront = WGPUStencilOperation_Invert; + WGPUCompareFunction stencilFuncionBack = WGPUCompareFunction_Always; + WGPUStencilOperation stencilOperationBack = WGPUStencilOperation_Invert; + + // sheder source and labels + auto shaderSource = cShaderSource_PipelineFill; + auto shaderLabel = "The shader fill"; + auto pipelineLabel = "The render pipeline fill shape Even Odd"; + + // allocate all pipeline handles + allocate(device, WgPipelineBlendType::Src, + vertexBufferLayouts, ARRAY_ELEMENTS_COUNT(vertexBufferLayouts), + bindGroupLayouts, ARRAY_ELEMENTS_COUNT(bindGroupLayouts), + stencilFuncionFront, stencilOperationFront, stencilFuncionBack, stencilOperationBack, shaderSource, shaderLabel, pipelineLabel); } @@ -88,7 +124,7 @@ void WgPipelineFillStroke::initialize(WGPUDevice device) allocate(device, WgPipelineBlendType::Src, vertexBufferLayouts, ARRAY_ELEMENTS_COUNT(vertexBufferLayouts), bindGroupLayouts, ARRAY_ELEMENTS_COUNT(bindGroupLayouts), - stencilFuncion, stencilOperation, + stencilFuncion, stencilOperation, stencilFuncion, stencilOperation, shaderSource, shaderLabel, pipelineLabel); } @@ -121,7 +157,7 @@ void WgPipelineSolid::initialize(WGPUDevice device, WgPipelineBlendType blendTyp allocate(device, blendType, vertexBufferLayouts, ARRAY_ELEMENTS_COUNT(vertexBufferLayouts), bindGroupLayouts, ARRAY_ELEMENTS_COUNT(bindGroupLayouts), - stencilFuncion, stencilOperation, + stencilFuncion, stencilOperation, stencilFuncion, stencilOperation, shaderSource, shaderLabel, pipelineLabel); } @@ -154,7 +190,7 @@ void WgPipelineLinear::initialize(WGPUDevice device, WgPipelineBlendType blendTy allocate(device, blendType, vertexBufferLayouts, ARRAY_ELEMENTS_COUNT(vertexBufferLayouts), bindGroupLayouts, ARRAY_ELEMENTS_COUNT(bindGroupLayouts), - stencilFuncion, stencilOperation, + stencilFuncion, stencilOperation, stencilFuncion, stencilOperation, shaderSource, shaderLabel, pipelineLabel); } @@ -187,7 +223,7 @@ void WgPipelineRadial::initialize(WGPUDevice device, WgPipelineBlendType blendTy allocate(device, blendType, vertexBufferLayouts, ARRAY_ELEMENTS_COUNT(vertexBufferLayouts), bindGroupLayouts, ARRAY_ELEMENTS_COUNT(bindGroupLayouts), - stencilFuncion, stencilOperation, + stencilFuncion, stencilOperation, stencilFuncion, stencilOperation, shaderSource, shaderLabel, pipelineLabel); } @@ -222,7 +258,7 @@ void WgPipelineImage::initialize(WGPUDevice device, WgPipelineBlendType blendTyp allocate(device, blendType, vertexBufferLayouts, ARRAY_ELEMENTS_COUNT(vertexBufferLayouts), bindGroupLayouts, ARRAY_ELEMENTS_COUNT(bindGroupLayouts), - stencilFuncion, stencilOperation, + stencilFuncion, stencilOperation, stencilFuncion, stencilOperation, shaderSource, shaderLabel, pipelineLabel); } @@ -340,7 +376,8 @@ void WgPipelineAntiAliasing::initialize(WGPUDevice device) void WgPipelines::initialize(WgContext& context) { // fill pipelines - fillShape.initialize(context.device); + fillShapeWinding.initialize(context.device); + fillShapeEvenOdd.initialize(context.device); fillStroke.initialize(context.device); for (uint8_t type = (uint8_t)WgPipelineBlendType::Src; type <= (uint8_t)WgPipelineBlendType::Max; type++) { solid[type].initialize(context.device, (WgPipelineBlendType)type); @@ -386,7 +423,8 @@ void WgPipelines::release() solid[type].release(); } fillStroke.release(); - fillShape.release(); + fillShapeEvenOdd.release(); + fillShapeWinding.release(); } diff --git a/src/renderer/wg_engine/tvgWgPipelines.h b/src/renderer/wg_engine/tvgWgPipelines.h index 8d477dd1..7a90d768 100644 --- a/src/renderer/wg_engine/tvgWgPipelines.h +++ b/src/renderer/wg_engine/tvgWgPipelines.h @@ -29,7 +29,18 @@ // render pipelines //***************************************************************************** -struct WgPipelineFillShape: public WgRenderPipeline +struct WgPipelineFillShapeWinding: public WgRenderPipeline +{ + void initialize(WGPUDevice device) override; + void use(WGPURenderPassEncoder encoder, WgBindGroupCanvas& groupCanvas, WgBindGroupPaint& groupPaint) + { + set(encoder); + groupCanvas.set(encoder, 0); + groupPaint.set(encoder, 1); + } +}; + +struct WgPipelineFillShapeEvenOdd: public WgRenderPipeline { void initialize(WGPUDevice device) override; void use(WGPURenderPassEncoder encoder, WgBindGroupCanvas& groupCanvas, WgBindGroupPaint& groupPaint) @@ -177,7 +188,8 @@ struct WgPipelineAntiAliasing: public WgComputePipeline struct WgPipelines { // render pipelines - WgPipelineFillShape fillShape; + WgPipelineFillShapeWinding fillShapeWinding; + WgPipelineFillShapeEvenOdd fillShapeEvenOdd; WgPipelineFillStroke fillStroke; // fill pipelines WgPipelineSolid solid[6]; diff --git a/src/renderer/wg_engine/tvgWgRenderTarget.cpp b/src/renderer/wg_engine/tvgWgRenderTarget.cpp index 1b41a206..e11ef2bf 100644 --- a/src/renderer/wg_engine/tvgWgRenderTarget.cpp +++ b/src/renderer/wg_engine/tvgWgRenderTarget.cpp @@ -117,7 +117,7 @@ void WgRenderStorage::drawShapeWinding(WgContext& context, WgRenderDataShape* re wgpuRenderPassEncoderSetStencilReference(mRenderPassEncoder, 0); for (uint32_t i = 0; i < renderData->meshGroupShapes.meshes.count; i++) { // draw to stencil (first pass) - mPipelines->fillShape.use(mRenderPassEncoder, mBindGroupCanvas, renderData->bindGroupPaint); + mPipelines->fillShapeWinding.use(mRenderPassEncoder, mBindGroupCanvas, renderData->bindGroupPaint); renderData->meshGroupShapes.meshes[i]->drawFan(context, mRenderPassEncoder); // fill shape (second pass) WgRenderSettings& settings = renderData->renderSettingsShape; @@ -140,7 +140,7 @@ void WgRenderStorage::drawShapeEvenOdd(WgContext& context, WgRenderDataShape* re // draw shape geometry wgpuRenderPassEncoderSetStencilReference(mRenderPassEncoder, 0); // draw to stencil (first pass) - mPipelines->fillShape.use(mRenderPassEncoder, mBindGroupCanvas, renderData->bindGroupPaint); + mPipelines->fillShapeEvenOdd.use(mRenderPassEncoder, mBindGroupCanvas, renderData->bindGroupPaint); for (uint32_t i = 0; i < renderData->meshGroupShapes.meshes.count; i++) renderData->meshGroupShapes.meshes[i]->drawFan(context, mRenderPassEncoder); // fill shape geometry (second pass)