diff --git a/src/renderer/wg_engine/tvgWgBindGroups.cpp b/src/renderer/wg_engine/tvgWgBindGroups.cpp index 7ecb4a92..625bd5ee 100644 --- a/src/renderer/wg_engine/tvgWgBindGroups.cpp +++ b/src/renderer/wg_engine/tvgWgBindGroups.cpp @@ -29,6 +29,7 @@ WGPUBindGroupLayout WgBindGroupSolidColor::layout = nullptr; WGPUBindGroupLayout WgBindGroupLinearGradient::layout = nullptr; WGPUBindGroupLayout WgBindGroupRadialGradient::layout = nullptr; WGPUBindGroupLayout WgBindGroupPicture::layout = nullptr; +WGPUBindGroupLayout WgBindGroupOpacity::layout = nullptr; WGPUBindGroupLayout WgBindGroupBlit::layout = nullptr; @@ -258,6 +259,50 @@ void WgBindGroupPicture::release() } +WGPUBindGroupLayout WgBindGroupOpacity::getLayout(WGPUDevice device) +{ + if (layout) return layout; + const WGPUBindGroupLayoutEntry bindGroupLayoutEntries[] { + makeBindGroupLayoutEntryBuffer(0) + }; + layout = createBindGroupLayout(device, bindGroupLayoutEntries, 1); + assert(layout); + return layout; +} + + +void WgBindGroupOpacity::releaseLayout() +{ + releaseBindGroupLayout(layout); +} + + +void WgBindGroupOpacity::initialize(WGPUDevice device, WGPUQueue queue, uint32_t uOpacity) +{ + release(); + float opacity = uOpacity / 255.0f; + uBufferOpacity = createBuffer(device, queue, &opacity, sizeof(float)); + const WGPUBindGroupEntry bindGroupEntries[] { + makeBindGroupEntryBuffer(0, uBufferOpacity) + }; + mBindGroup = createBindGroup(device, getLayout(device), bindGroupEntries, 1); + assert(mBindGroup); +} + + +void WgBindGroupOpacity::update(WGPUDevice device, WGPUQueue queue, uint32_t uOpacity) { + float opacity = uOpacity / 255.0f; + wgpuQueueWriteBuffer(queue, uBufferOpacity, 0, &opacity, sizeof(float)); +} + + +void WgBindGroupOpacity::release() +{ + releaseBuffer(uBufferOpacity); + releaseBindGroup(mBindGroup); +} + + WGPUBindGroupLayout WgBindGroupBlit::getLayout(WGPUDevice device) { if (layout) return layout; @@ -292,4 +337,46 @@ void WgBindGroupBlit::initialize(WGPUDevice device, WGPUQueue queue, WGPUSampler void WgBindGroupBlit::release() { releaseBindGroup(mBindGroup); -} \ No newline at end of file +} + +//************************************************************************ +// bind groups pools +//************************************************************************ + +WgBindGroupOpacity* WgBindGroupOpacityPool::allocate(WgContext& context, uint32_t opacity) +{ + WgBindGroupOpacity* bindGroup{}; + if (mPool.count == 0) { + bindGroup = new WgBindGroupOpacity; + bindGroup->initialize(context.device, context.queue, opacity); + mUsed.push(bindGroup); + mList.push(bindGroup); + } else { + bindGroup = mPool.last(); + bindGroup->update(context.device, context.queue, opacity); + mUsed.push(bindGroup); + mPool.pop(); + } + return bindGroup; +} + + +void WgBindGroupOpacityPool::reset() +{ + for (uint32_t i = 0; i < mUsed.count; i++) + mPool.push(mUsed[i]); + mUsed.clear(); +} + + +void WgBindGroupOpacityPool::release() +{ + for (uint32_t i = 0; i < mList.count; i++) { + mList[i]->release(); + delete mList[i]; + } + mList.clear(); + mUsed.clear(); + mPool.clear(); +} + diff --git a/src/renderer/wg_engine/tvgWgBindGroups.h b/src/renderer/wg_engine/tvgWgBindGroups.h index a637f6e1..b8bc0d16 100644 --- a/src/renderer/wg_engine/tvgWgBindGroups.h +++ b/src/renderer/wg_engine/tvgWgBindGroups.h @@ -62,7 +62,7 @@ struct WgBindGroupSolidColor : public WgBindGroup static WGPUBindGroupLayout getLayout(WGPUDevice device); static void releaseLayout(); - WGPUBuffer uBufferSolidColor; + WGPUBuffer uBufferSolidColor{}; void initialize(WGPUDevice device, WGPUQueue queue, WgShaderTypeSolidColor &uSolidColor); void release(); @@ -75,7 +75,7 @@ struct WgBindGroupLinearGradient : public WgBindGroup static WGPUBindGroupLayout getLayout(WGPUDevice device); static void releaseLayout(); - WGPUBuffer uBufferLinearGradient; + WGPUBuffer uBufferLinearGradient{}; void initialize(WGPUDevice device, WGPUQueue queue, WgShaderTypeLinearGradient &uLinearGradient); void release(); @@ -88,7 +88,7 @@ struct WgBindGroupRadialGradient : public WgBindGroup static WGPUBindGroupLayout getLayout(WGPUDevice device); static void releaseLayout(); - WGPUBuffer uBufferRadialGradient; + WGPUBuffer uBufferRadialGradient{}; void initialize(WGPUDevice device, WGPUQueue queue, WgShaderTypeRadialGradient &uRadialGradient); void release(); @@ -107,6 +107,19 @@ struct WgBindGroupPicture : public WgBindGroup void release(); }; +// @group(1 or 2) +struct WgBindGroupOpacity : public WgBindGroup +{ + static WGPUBindGroupLayout layout; + static WGPUBindGroupLayout getLayout(WGPUDevice device); + static void releaseLayout(); + + WGPUBuffer uBufferOpacity{}; + void initialize(WGPUDevice device, WGPUQueue queue, uint32_t uOpacity); + void update(WGPUDevice device, WGPUQueue queue, uint32_t uOpacity); + void release(); +}; + // @group(0 or 1) struct WgBindGroupBlit : public WgBindGroup { @@ -120,4 +133,20 @@ struct WgBindGroupBlit : public WgBindGroup void release(); }; +//************************************************************************ +// bind group pools +//************************************************************************ + +class WgBindGroupOpacityPool +{ +private: + Array mList; + Array mPool; + Array mUsed; +public: + WgBindGroupOpacity* allocate(WgContext& context, uint32_t opacity); + void reset(); + void release(); +}; + #endif // _TVG_WG_BIND_GROUPS_H_ diff --git a/src/renderer/wg_engine/tvgWgCommon.cpp b/src/renderer/wg_engine/tvgWgCommon.cpp index 25f56ff1..4f00f6fe 100644 --- a/src/renderer/wg_engine/tvgWgCommon.cpp +++ b/src/renderer/wg_engine/tvgWgCommon.cpp @@ -272,7 +272,57 @@ void WgBindGroup::releaseBindGroupLayout(WGPUBindGroupLayout& bindGroupLayout) // pipeline //***************************************************************************** -void WgPipeline::allocate(WGPUDevice device, +void WgPipeline::release() +{ + destroyShaderModule(mShaderModule); + destroyPipelineLayout(mPipelineLayout); +} + + +WGPUPipelineLayout WgPipeline::createPipelineLayout(WGPUDevice device, const WGPUBindGroupLayout* bindGroupLayouts, uint32_t count) +{ + WGPUPipelineLayoutDescriptor pipelineLayoutDesc{}; + pipelineLayoutDesc.nextInChain = nullptr; + pipelineLayoutDesc.label = "The Pipeline layout"; + pipelineLayoutDesc.bindGroupLayoutCount = count; + pipelineLayoutDesc.bindGroupLayouts = bindGroupLayouts; + return wgpuDeviceCreatePipelineLayout(device, &pipelineLayoutDesc); +} + + +WGPUShaderModule WgPipeline::createShaderModule(WGPUDevice device, const char* code, const char* label) +{ + WGPUShaderModuleWGSLDescriptor shaderModuleWGSLDesc{}; + shaderModuleWGSLDesc.chain.next = nullptr; + shaderModuleWGSLDesc.chain.sType = WGPUSType_ShaderModuleWGSLDescriptor; + shaderModuleWGSLDesc.code = code; + WGPUShaderModuleDescriptor shaderModuleDesc{}; + shaderModuleDesc.nextInChain = &shaderModuleWGSLDesc.chain; + shaderModuleDesc.label = label; + shaderModuleDesc.hintCount = 0; + shaderModuleDesc.hints = nullptr; + return wgpuDeviceCreateShaderModule(device, &shaderModuleDesc); +} + + +void WgPipeline::destroyPipelineLayout(WGPUPipelineLayout& pipelineLayout) +{ + if (pipelineLayout) wgpuPipelineLayoutRelease(pipelineLayout); + pipelineLayout = nullptr; +} + + +void WgPipeline::destroyShaderModule(WGPUShaderModule& shaderModule) +{ + if (shaderModule) wgpuShaderModuleRelease(shaderModule); + shaderModule = nullptr; +} + +//***************************************************************************** +// render pipeline +//***************************************************************************** + +void WgRenderPipeline::allocate(WGPUDevice device, WGPUVertexBufferLayout vertexBufferLayouts[], uint32_t attribsCount, WGPUBindGroupLayout bindGroupLayouts[], uint32_t bindGroupsCount, WGPUCompareFunction stencilCompareFunction, WGPUStencilOperation stencilOperation, @@ -292,21 +342,20 @@ void WgPipeline::allocate(WGPUDevice device, } -void WgPipeline::release() +void WgRenderPipeline::release() { destroyRenderPipeline(mRenderPipeline); - destroyShaderModule(mShaderModule); - destroyPipelineLayout(mPipelineLayout); + WgPipeline::release(); } -void WgPipeline::set(WGPURenderPassEncoder renderPassEncoder) +void WgRenderPipeline::set(WGPURenderPassEncoder renderPassEncoder) { wgpuRenderPassEncoderSetPipeline(renderPassEncoder, mRenderPipeline); }; -WGPUBlendState WgPipeline::makeBlendState() +WGPUBlendState WgRenderPipeline::makeBlendState() { WGPUBlendState blendState{}; blendState.color.operation = WGPUBlendOperation_Add; @@ -314,12 +363,12 @@ WGPUBlendState WgPipeline::makeBlendState() blendState.color.dstFactor = WGPUBlendFactor_OneMinusSrcAlpha; blendState.alpha.operation = WGPUBlendOperation_Add; blendState.alpha.srcFactor = WGPUBlendFactor_One; - blendState.alpha.dstFactor = WGPUBlendFactor_Zero; + blendState.alpha.dstFactor = WGPUBlendFactor_One; return blendState; } -WGPUColorTargetState WgPipeline::makeColorTargetState(const WGPUBlendState* blendState) +WGPUColorTargetState WgRenderPipeline::makeColorTargetState(const WGPUBlendState* blendState) { WGPUColorTargetState colorTargetState{}; colorTargetState.nextInChain = nullptr; @@ -330,7 +379,7 @@ WGPUColorTargetState WgPipeline::makeColorTargetState(const WGPUBlendState* blen } -WGPUVertexBufferLayout WgPipeline::makeVertexBufferLayout(const WGPUVertexAttribute* vertexAttributes, uint32_t count, uint64_t stride) +WGPUVertexBufferLayout WgRenderPipeline::makeVertexBufferLayout(const WGPUVertexAttribute* vertexAttributes, uint32_t count, uint64_t stride) { WGPUVertexBufferLayout vertexBufferLayoutPos{}; vertexBufferLayoutPos.arrayStride = stride; @@ -341,7 +390,7 @@ WGPUVertexBufferLayout WgPipeline::makeVertexBufferLayout(const WGPUVertexAttrib } -WGPUVertexState WgPipeline::makeVertexState(WGPUShaderModule shaderModule, const WGPUVertexBufferLayout* buffers, uint32_t count) +WGPUVertexState WgRenderPipeline::makeVertexState(WGPUShaderModule shaderModule, const WGPUVertexBufferLayout* buffers, uint32_t count) { WGPUVertexState vertexState{}; vertexState.nextInChain = nullptr; @@ -355,7 +404,7 @@ WGPUVertexState WgPipeline::makeVertexState(WGPUShaderModule shaderModule, const } -WGPUPrimitiveState WgPipeline::makePrimitiveState() +WGPUPrimitiveState WgRenderPipeline::makePrimitiveState() { WGPUPrimitiveState primitiveState{}; primitiveState.nextInChain = nullptr; @@ -366,7 +415,7 @@ WGPUPrimitiveState WgPipeline::makePrimitiveState() return primitiveState; } -WGPUDepthStencilState WgPipeline::makeDepthStencilState(WGPUCompareFunction compare, WGPUStencilOperation operation) +WGPUDepthStencilState WgRenderPipeline::makeDepthStencilState(WGPUCompareFunction compare, WGPUStencilOperation operation) { WGPUDepthStencilState depthStencilState{}; depthStencilState.nextInChain = nullptr; @@ -390,7 +439,7 @@ WGPUDepthStencilState WgPipeline::makeDepthStencilState(WGPUCompareFunction comp } -WGPUMultisampleState WgPipeline::makeMultisampleState() +WGPUMultisampleState WgRenderPipeline::makeMultisampleState() { WGPUMultisampleState multisampleState{}; multisampleState.nextInChain = nullptr; @@ -401,7 +450,7 @@ WGPUMultisampleState WgPipeline::makeMultisampleState() } -WGPUFragmentState WgPipeline::makeFragmentState(WGPUShaderModule shaderModule, WGPUColorTargetState* targets, uint32_t size) +WGPUFragmentState WgRenderPipeline::makeFragmentState(WGPUShaderModule shaderModule, WGPUColorTargetState* targets, uint32_t size) { WGPUFragmentState fragmentState{}; fragmentState.nextInChain = nullptr; @@ -414,34 +463,7 @@ WGPUFragmentState WgPipeline::makeFragmentState(WGPUShaderModule shaderModule, W return fragmentState; } - -WGPUPipelineLayout WgPipeline::createPipelineLayout(WGPUDevice device, const WGPUBindGroupLayout* bindGroupLayouts, uint32_t count) -{ - WGPUPipelineLayoutDescriptor pipelineLayoutDesc{}; - pipelineLayoutDesc.nextInChain = nullptr; - pipelineLayoutDesc.label = "The Pipeline layout"; - pipelineLayoutDesc.bindGroupLayoutCount = count; - pipelineLayoutDesc.bindGroupLayouts = bindGroupLayouts; - return wgpuDeviceCreatePipelineLayout(device, &pipelineLayoutDesc); -} - - -WGPUShaderModule WgPipeline::createShaderModule(WGPUDevice device, const char* code, const char* label) -{ - WGPUShaderModuleWGSLDescriptor shaderModuleWGSLDesc{}; - shaderModuleWGSLDesc.chain.next = nullptr; - shaderModuleWGSLDesc.chain.sType = WGPUSType_ShaderModuleWGSLDescriptor; - shaderModuleWGSLDesc.code = code; - WGPUShaderModuleDescriptor shaderModuleDesc{}; - shaderModuleDesc.nextInChain = &shaderModuleWGSLDesc.chain; - shaderModuleDesc.label = label; - shaderModuleDesc.hintCount = 0; - shaderModuleDesc.hints = nullptr; - return wgpuDeviceCreateShaderModule(device, &shaderModuleDesc); -} - - -WGPURenderPipeline WgPipeline::createRenderPipeline(WGPUDevice device, +WGPURenderPipeline WgRenderPipeline::createRenderPipeline(WGPUDevice device, WGPUVertexBufferLayout vertexBufferLayouts[], uint32_t attribsCount, WGPUCompareFunction stencilCompareFunction, WGPUStencilOperation stencilOperation, WGPUPipelineLayout pipelineLayout, WGPUShaderModule shaderModule, @@ -470,22 +492,7 @@ WGPURenderPipeline WgPipeline::createRenderPipeline(WGPUDevice device, return wgpuDeviceCreateRenderPipeline(device, &renderPipelineDesc); } - -void WgPipeline::destroyPipelineLayout(WGPUPipelineLayout& pipelineLayout) -{ - if (pipelineLayout) wgpuPipelineLayoutRelease(pipelineLayout); - pipelineLayout = nullptr; -} - - -void WgPipeline::destroyShaderModule(WGPUShaderModule& shaderModule) -{ - if (shaderModule) wgpuShaderModuleRelease(shaderModule); - shaderModule = nullptr; -} - - -void WgPipeline::destroyRenderPipeline(WGPURenderPipeline& renderPipeline) +void WgRenderPipeline::destroyRenderPipeline(WGPURenderPipeline& renderPipeline) { if (renderPipeline) wgpuRenderPipelineRelease(renderPipeline); renderPipeline = nullptr; diff --git a/src/renderer/wg_engine/tvgWgCommon.h b/src/renderer/wg_engine/tvgWgCommon.h index 6b644803..45349dce 100644 --- a/src/renderer/wg_engine/tvgWgCommon.h +++ b/src/renderer/wg_engine/tvgWgCommon.h @@ -28,6 +28,8 @@ #include "tvgCommon.h" #include "tvgRender.h" +struct WgPipelines; + struct WgContext { WGPUInstance instance{}; WGPUAdapter adapter{}; @@ -37,6 +39,8 @@ struct WgContext { WGPUFeatureName featureNames[32]{}; WGPUAdapterProperties adapterProperties{}; WGPUSupportedLimits supportedLimits{}; + + WgPipelines* pipelines{}; // external handle (do not release) void initialize(); void release(); @@ -70,17 +74,29 @@ struct WgBindGroup struct WgPipeline { protected: + WGPUPipelineLayout mPipelineLayout{}; + WGPUShaderModule mShaderModule{}; +public: + virtual void initialize(WGPUDevice device) = 0; + virtual void release(); + + static WGPUPipelineLayout createPipelineLayout(WGPUDevice device, const WGPUBindGroupLayout* bindGroupLayouts, uint32_t count); + static WGPUShaderModule createShaderModule(WGPUDevice device, const char* code, const char* label); + static void destroyPipelineLayout(WGPUPipelineLayout& pipelineLayout); + static void destroyShaderModule(WGPUShaderModule& shaderModule); +}; + +struct WgRenderPipeline: public WgPipeline +{ +protected: + WGPURenderPipeline mRenderPipeline{}; void allocate(WGPUDevice device, WGPUVertexBufferLayout vertexBufferLayouts[], uint32_t attribsCount, WGPUBindGroupLayout bindGroupLayouts[], uint32_t bindGroupsCount, WGPUCompareFunction stencilCompareFunction, WGPUStencilOperation stencilOperation, const char* shaderSource, const char* shaderLabel, const char* pipelineLabel); - WGPUPipelineLayout mPipelineLayout{}; - WGPUShaderModule mShaderModule{}; - WGPURenderPipeline mRenderPipeline{}; public: - virtual void initialize(WGPUDevice device) = 0; - virtual void release(); + void release() override; void set(WGPURenderPassEncoder renderPassEncoder); static WGPUBlendState makeBlendState(); @@ -92,15 +108,11 @@ public: static WGPUMultisampleState makeMultisampleState(); static WGPUFragmentState makeFragmentState(WGPUShaderModule shaderModule, WGPUColorTargetState* targets, uint32_t size); - static WGPUPipelineLayout createPipelineLayout(WGPUDevice device, const WGPUBindGroupLayout* bindGroupLayouts, uint32_t count); - static WGPUShaderModule createShaderModule(WGPUDevice device, const char* code, const char* label); static WGPURenderPipeline createRenderPipeline(WGPUDevice device, WGPUVertexBufferLayout vertexBufferLayouts[], uint32_t attribsCount, WGPUCompareFunction stencilCompareFunction, WGPUStencilOperation stencilOperation, WGPUPipelineLayout pipelineLayout, WGPUShaderModule shaderModule, const char* pipelineLabel); - static void destroyPipelineLayout(WGPUPipelineLayout& pipelineLayout); - static void destroyShaderModule(WGPUShaderModule& shaderModule); static void destroyRenderPipeline(WGPURenderPipeline& renderPipeline); }; diff --git a/src/renderer/wg_engine/tvgWgPipelines.cpp b/src/renderer/wg_engine/tvgWgPipelines.cpp index 9e16a4d8..74bd9250 100644 --- a/src/renderer/wg_engine/tvgWgPipelines.cpp +++ b/src/renderer/wg_engine/tvgWgPipelines.cpp @@ -235,7 +235,8 @@ void WgPipelineBlit::initialize(WGPUDevice device) // bind groups and layouts WGPUBindGroupLayout bindGroupLayouts[] = { - WgBindGroupBlit::getLayout(device) + WgBindGroupBlit::getLayout(device), + WgBindGroupOpacity::getLayout(device) }; // stencil function @@ -326,35 +327,39 @@ void WgPipelineComposition::initialize(WGPUDevice device, const char* shaderSrc) // pipelines //************************************************************************ -void WgPipelines::initialize(WGPUDevice device) +void WgPipelines::initialize(WgContext& context) { - fillShape.initialize(device); - fillStroke.initialize(device); - solid.initialize(device); - linear.initialize(device); - radial.initialize(device); - image.initialize(device); - blit.initialize(device); - blitColor.initialize(device); + fillShape.initialize(context.device); + fillStroke.initialize(context.device); + solid.initialize(context.device); + linear.initialize(context.device); + radial.initialize(context.device); + image.initialize(context.device); + blit.initialize(context.device); + blitColor.initialize(context.device); // composition pipelines - compAlphaMask.initialize(device, cShaderSource_PipelineCompAlphaMask); - compInvAlphaMask.initialize(device, cShaderSource_PipelineCompInvAlphaMask); - compLumaMask.initialize(device, cShaderSource_PipelineCompLumaMask); - compInvLumaMask.initialize(device, cShaderSource_PipelineCompInvLumaMask); - compAddMask.initialize(device, cShaderSource_PipelineCompAddMask); - compSubtractMask.initialize(device, cShaderSource_PipelineCompSubtractMask); - compIntersectMask.initialize(device, cShaderSource_PipelineCompIntersectMask); - compDifferenceMask.initialize(device, cShaderSource_PipelineCompDifferenceMask); + compAlphaMask.initialize(context.device, cShaderSource_PipelineCompAlphaMask); + compInvAlphaMask.initialize(context.device, cShaderSource_PipelineCompInvAlphaMask); + compLumaMask.initialize(context.device, cShaderSource_PipelineCompLumaMask); + compInvLumaMask.initialize(context.device, cShaderSource_PipelineCompInvLumaMask); + compAddMask.initialize(context.device, cShaderSource_PipelineCompAddMask); + compSubtractMask.initialize(context.device, cShaderSource_PipelineCompSubtractMask); + compIntersectMask.initialize(context.device, cShaderSource_PipelineCompIntersectMask); + compDifferenceMask.initialize(context.device, cShaderSource_PipelineCompDifferenceMask); + // store pipelines to context + context.pipelines = this; } void WgPipelines::release() { WgBindGroupBlit::releaseLayout(); + WgBindGroupOpacity::releaseLayout(); WgBindGroupPicture::releaseLayout(); WgBindGroupRadialGradient::releaseLayout(); WgBindGroupLinearGradient::releaseLayout(); WgBindGroupSolidColor::releaseLayout(); + WgBindGroupPaint::releaseLayout(); WgBindGroupCanvas::releaseLayout(); compDifferenceMask.release(); compIntersectMask.release(); diff --git a/src/renderer/wg_engine/tvgWgPipelines.h b/src/renderer/wg_engine/tvgWgPipelines.h index 6b5274f0..ec60f8d8 100644 --- a/src/renderer/wg_engine/tvgWgPipelines.h +++ b/src/renderer/wg_engine/tvgWgPipelines.h @@ -25,7 +25,7 @@ #include "tvgWgBindGroups.h" -struct WgPipelineFillShape: public WgPipeline +struct WgPipelineFillShape: public WgRenderPipeline { void initialize(WGPUDevice device) override; void use(WGPURenderPassEncoder encoder, WgBindGroupCanvas& groupCanvas, WgBindGroupPaint& groupPaint) @@ -36,7 +36,7 @@ struct WgPipelineFillShape: public WgPipeline } }; -struct WgPipelineFillStroke: public WgPipeline +struct WgPipelineFillStroke: public WgRenderPipeline { void initialize(WGPUDevice device) override; void use(WGPURenderPassEncoder encoder, WgBindGroupCanvas& groupCanvas, WgBindGroupPaint& groupPaint) @@ -47,7 +47,7 @@ struct WgPipelineFillStroke: public WgPipeline } }; -struct WgPipelineSolid: public WgPipeline +struct WgPipelineSolid: public WgRenderPipeline { void initialize(WGPUDevice device) override; void use(WGPURenderPassEncoder encoder, WgBindGroupCanvas& groupCanvas,WgBindGroupPaint& groupPaint, WgBindGroupSolidColor& groupSolid) @@ -59,7 +59,7 @@ struct WgPipelineSolid: public WgPipeline } }; -struct WgPipelineLinear: public WgPipeline +struct WgPipelineLinear: public WgRenderPipeline { void initialize(WGPUDevice device) override; void use(WGPURenderPassEncoder encoder, WgBindGroupCanvas& groupCanvas, WgBindGroupPaint& groupPaint, WgBindGroupLinearGradient& groupLinear) @@ -71,7 +71,7 @@ struct WgPipelineLinear: public WgPipeline } }; -struct WgPipelineRadial: public WgPipeline +struct WgPipelineRadial: public WgRenderPipeline { void initialize(WGPUDevice device) override; void use(WGPURenderPassEncoder encoder, WgBindGroupCanvas& groupCanvas, WgBindGroupPaint& groupPaint, WgBindGroupRadialGradient& groupRadial) @@ -83,7 +83,7 @@ struct WgPipelineRadial: public WgPipeline } }; -struct WgPipelineImage: public WgPipeline +struct WgPipelineImage: public WgRenderPipeline { void initialize(WGPUDevice device) override; void use(WGPURenderPassEncoder encoder, WgBindGroupCanvas& groupCanvas, WgBindGroupPaint& groupPaint, WgBindGroupPicture& groupPicture) @@ -95,7 +95,20 @@ struct WgPipelineImage: public WgPipeline } }; -struct WgPipelineBlit: public WgPipeline +struct WgPipelineBlit: public WgRenderPipeline +{ + void initialize(WGPUDevice device) override; + void use(WGPURenderPassEncoder encoder, + WgBindGroupBlit& groupBlit, + WgBindGroupOpacity& groupOpacity) + { + set(encoder); + groupBlit.set(encoder, 0); + groupOpacity.set(encoder, 1); + } +}; + +struct WgPipelineBlitColor: public WgRenderPipeline { void initialize(WGPUDevice device) override; void use(WGPURenderPassEncoder encoder, WgBindGroupBlit& groupBlit) @@ -105,17 +118,7 @@ struct WgPipelineBlit: public WgPipeline } }; -struct WgPipelineBlitColor: public WgPipeline -{ - void initialize(WGPUDevice device) override; - void use(WGPURenderPassEncoder encoder, WgBindGroupBlit& groupBlit) - { - set(encoder); - groupBlit.set(encoder, 0); - } -}; - -struct WgPipelineComposition: public WgPipeline +struct WgPipelineComposition: public WgRenderPipeline { void initialize(WGPUDevice device) override {}; void initialize(WGPUDevice device, const char* shaderSrc); @@ -147,7 +150,7 @@ struct WgPipelines WgPipelineComposition compIntersectMask; WgPipelineComposition compDifferenceMask; - void initialize(WGPUDevice device); + void initialize(WgContext& context); void release(); WgPipelineComposition* getCompositionPipeline(CompositeMethod method); diff --git a/src/renderer/wg_engine/tvgWgRenderTarget.cpp b/src/renderer/wg_engine/tvgWgRenderTarget.cpp index e493854f..3f664488 100644 --- a/src/renderer/wg_engine/tvgWgRenderTarget.cpp +++ b/src/renderer/wg_engine/tvgWgRenderTarget.cpp @@ -22,7 +22,7 @@ #include "tvgWgRenderTarget.h" -void WgRenderTarget::initialize(WgContext& context, WgPipelines& pipelines, uint32_t w, uint32_t h) +void WgRenderTarget::initialize(WgContext& context, uint32_t w, uint32_t h) { release(context); // sampler descriptor @@ -45,7 +45,7 @@ void WgRenderTarget::initialize(WgContext& context, WgPipelines& pipelines, uint WGPUTextureDescriptor textureDescColor{}; textureDescColor.nextInChain = nullptr; textureDescColor.label = "The target texture color"; - textureDescColor.usage = WGPUTextureUsage_RenderAttachment | WGPUTextureUsage_TextureBinding | WGPUTextureUsage_CopyDst; + textureDescColor.usage = WGPUTextureUsage_RenderAttachment | WGPUTextureUsage_TextureBinding | WGPUTextureUsage_CopyDst | WGPUTextureUsage_StorageBinding; textureDescColor.dimension = WGPUTextureDimension_2D; textureDescColor.size = { w, h, 1 }; textureDescColor.format = WGPUTextureFormat_BGRA8Unorm; @@ -103,7 +103,7 @@ void WgRenderTarget::initialize(WgContext& context, WgPipelines& pipelines, uint WgGeometryData geometryDataWnd; geometryDataWnd.appendBlitBox(); mMeshDataCanvasWnd.update(context, &geometryDataWnd); - mPipelines = &pipelines; + mPipelines = context.pipelines; } @@ -248,10 +248,10 @@ void WgRenderTarget::renderPicture(WgRenderDataPicture* renderData) } -void WgRenderTarget::blit(WgContext& context, WgRenderTarget* renderTargetSrc) +void WgRenderTarget::blit(WgContext& context, WgRenderTarget* renderTargetSrc, WgBindGroupOpacity* mBindGroupOpacity) { assert(mRenderPassEncoder); - mPipelines->blit.use(mRenderPassEncoder, renderTargetSrc->bindGroupBlit); + mPipelines->blit.use(mRenderPassEncoder, renderTargetSrc->bindGroupBlit, *mBindGroupOpacity); mMeshDataCanvasWnd.drawImage(mRenderPassEncoder); } @@ -272,3 +272,37 @@ void WgRenderTarget::compose(WgContext& context, WgRenderTarget* renderTargetSrc pipeline->use(mRenderPassEncoder, renderTargetSrc->bindGroupBlit, renderTargetMsk->bindGroupBlit); mMeshDataCanvasWnd.drawImage(mRenderPassEncoder); } + +//***************************************************************************** +// render terget pool +//***************************************************************************** + +WgRenderTarget* WgRenderTargetPool::allocate(WgContext& context, uint32_t w, uint32_t h) +{ + WgRenderTarget* renderTarget{}; + if (mPool.count > 0) { + renderTarget = mPool.last(); + mPool.pop(); + } else { + renderTarget = new WgRenderTarget; + renderTarget->initialize(context, w, h); + mList.push(renderTarget); + } + return renderTarget; +}; + + +void WgRenderTargetPool::free(WgContext& context, WgRenderTarget* renderTarget) { + mPool.push(renderTarget); +}; + + +void WgRenderTargetPool::release(WgContext& context) +{ + for (uint32_t i = 0; i < mList.count; i++) { + mList[i]->release(context); + delete mList[i]; + } + mList.clear(); + mPool.clear(); +}; diff --git a/src/renderer/wg_engine/tvgWgRenderTarget.h b/src/renderer/wg_engine/tvgWgRenderTarget.h index ff81a994..e06d9997 100644 --- a/src/renderer/wg_engine/tvgWgRenderTarget.h +++ b/src/renderer/wg_engine/tvgWgRenderTarget.h @@ -43,7 +43,7 @@ public: WGPUTextureView textureViewStencil{}; WgBindGroupBlit bindGroupBlit; public: - void initialize(WgContext& context, WgPipelines& pipelines, uint32_t w, uint32_t h); + void initialize(WgContext& context, uint32_t w, uint32_t h); void release(WgContext& context); void beginRenderPass(WGPUCommandEncoder commandEncoder, WGPUTextureView colorAttachement, bool clear); @@ -54,9 +54,21 @@ public: void renderStroke(WgRenderDataShape* renderData); void renderPicture(WgRenderDataPicture* renderData); - void blit(WgContext& context, WgRenderTarget* renderTargetSrc); + void blit(WgContext& context, WgRenderTarget* renderTargetSrc, WgBindGroupOpacity* bindGroupOpacity); void blitColor(WgContext& context, WgRenderTarget* renderTargetSrc); void compose(WgContext& context, WgRenderTarget* renderTargetSrc, WgRenderTarget* renderTargetMsk, CompositeMethod method); }; + +class WgRenderTargetPool { +private: + Array mList; + Array mPool; +public: + WgRenderTarget* allocate(WgContext& context, uint32_t w, uint32_t h); + void free(WgContext& context, WgRenderTarget* renderTarget); + void release(WgContext& context); +}; + + #endif diff --git a/src/renderer/wg_engine/tvgWgRenderer.cpp b/src/renderer/wg_engine/tvgWgRenderer.cpp index 47edcf48..21c14fd8 100644 --- a/src/renderer/wg_engine/tvgWgRenderer.cpp +++ b/src/renderer/wg_engine/tvgWgRenderer.cpp @@ -42,18 +42,16 @@ WgRenderer::~WgRenderer() void WgRenderer::initialize() { mContext.initialize(); - mPipelines.initialize(mContext.device); + mPipelines.initialize(mContext); } void WgRenderer::release() { - // clear render targets - for (uint32_t i = 0; i < mRenderTargetPool.count; i++) { - mRenderTargetPool[i]->release(mContext); - delete mRenderTargetPool[i]; - } - mRenderTargetPool.clear(); + mCompositorStack.clear(); + mRenderTargetStack.clear(); + mBindGroupOpacityPool.release(); + mRenderTargetPool.release(mContext); mRenderTargetRoot.release(mContext); mRenderTargetWnd.release(mContext); if (mSwapChain) wgpuSwapChainRelease(mSwapChain); @@ -161,6 +159,7 @@ bool WgRenderer::postRender() { mRenderTargetRoot.endRenderPass(); mRenderTargetStack.pop(); + mBindGroupOpacityPool.reset(); mContext.executeCommandEncoder(mCommandEncoder); wgpuCommandEncoderRelease(mCommandEncoder); return true; @@ -235,7 +234,7 @@ bool WgRenderer::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t mTargetSurface.w = w; mTargetSurface.h = h; - mRenderTargetRoot.initialize(mContext, mPipelines, w, h); + mRenderTargetRoot.initialize(mContext, w, h); return true; } @@ -275,8 +274,8 @@ bool WgRenderer::target(void* window, uint32_t w, uint32_t h) mSwapChain = wgpuDeviceCreateSwapChain(mContext.device, mSurface, &swapChainDesc); assert(mSwapChain); - mRenderTargetWnd.initialize(mContext, mPipelines, w, h); - mRenderTargetRoot.initialize(mContext, mPipelines, w, h); + mRenderTargetWnd.initialize(mContext, w, h); + mRenderTargetRoot.initialize(mContext, w, h); return true; } @@ -298,7 +297,7 @@ bool WgRenderer::beginComposite(TVG_UNUSED Compositor* cmp, TVG_UNUSED Composite mRenderTargetStack.last()->endRenderPass(); // create new render target and begin new render pass - WgRenderTarget* renderTarget = allocateRenderTarget(); + WgRenderTarget* renderTarget = mRenderTargetPool.allocate(mContext, mTargetSurface.w, mTargetSurface.h); renderTarget->beginRenderPass(mCommandEncoder, true); mRenderTargetStack.push(renderTarget); @@ -319,10 +318,13 @@ bool WgRenderer::endComposite(TVG_UNUSED Compositor* cmp) // apply current render target WgRenderTarget* renderTarget = mRenderTargetStack.last(); renderTarget->beginRenderPass(mCommandEncoder, false); - renderTarget->blit(mContext, renderTargetSrc); + + // blit scene to current render tartget + WgBindGroupOpacity* mBindGroupOpacity = mBindGroupOpacityPool.allocate(mContext, cmp->opacity); + renderTarget->blit(mContext, renderTargetSrc, mBindGroupOpacity); // back render targets to the pool - releaseRenderTarget(renderTargetSrc); + mRenderTargetPool.free(mContext, renderTargetSrc); } else { // end current render pass mRenderTargetStack.last()->endRenderPass(); @@ -339,8 +341,8 @@ bool WgRenderer::endComposite(TVG_UNUSED Compositor* cmp) renderTarget->compose(mContext, renderTargetSrc, renderTargetMsk, cmp->method); // back render targets to the pool - releaseRenderTarget(renderTargetSrc); - releaseRenderTarget(renderTargetMsk); + mRenderTargetPool.free(mContext, renderTargetSrc); + mRenderTargetPool.free(mContext, renderTargetMsk); } // delete current compositor @@ -351,26 +353,6 @@ bool WgRenderer::endComposite(TVG_UNUSED Compositor* cmp) } -WgRenderTarget* WgRenderer::allocateRenderTarget() -{ - WgRenderTarget* renderTarget = nullptr; - if (mRenderTargetPool.count > 0) { - renderTarget = mRenderTargetPool.last(); - mRenderTargetPool.pop(); - } else { - renderTarget = new WgRenderTarget; - renderTarget->initialize(mContext, mPipelines, mTargetSurface.w, mTargetSurface.h); - } - return renderTarget; -} - - -void WgRenderer::releaseRenderTarget(WgRenderTarget* renderTarget) -{ - mRenderTargetPool.push(renderTarget); -} - - WgRenderer* WgRenderer::gen() { return new WgRenderer(); diff --git a/src/renderer/wg_engine/tvgWgRenderer.h b/src/renderer/wg_engine/tvgWgRenderer.h index 31b85c08..004390b1 100644 --- a/src/renderer/wg_engine/tvgWgRenderer.h +++ b/src/renderer/wg_engine/tvgWgRenderer.h @@ -62,12 +62,12 @@ public: // render handles WGPUCommandEncoder mCommandEncoder{}; - Array mRenderTargetStack; - Array mRenderTargetPool; Array mCompositorStack; + Array mRenderTargetStack; - WgRenderTarget* allocateRenderTarget(); - void releaseRenderTarget(WgRenderTarget* renderTarget); + // render object pools + WgRenderTargetPool mRenderTargetPool; + WgBindGroupOpacityPool mBindGroupOpacityPool; private: WgContext mContext; WgPipelines mPipelines; diff --git a/src/renderer/wg_engine/tvgWgShaderSrc.cpp b/src/renderer/wg_engine/tvgWgShaderSrc.cpp index 6ab2fafb..74201fc7 100644 --- a/src/renderer/wg_engine/tvgWgShaderSrc.cpp +++ b/src/renderer/wg_engine/tvgWgShaderSrc.cpp @@ -352,8 +352,9 @@ struct VertexOutput { @location(0) texCoord: vec2f }; -@group(0) @binding(0) var uSamplerSrc : sampler; -@group(0) @binding(1) var uTextureViewSrc : texture_2d; +@group(0) @binding(0) var uSamplerSrc : sampler; +@group(0) @binding(1) var uTextureViewSrc : texture_2d; +@group(1) @binding(0) var uOpacity : f32; @vertex fn vs_main(in: VertexInput) -> VertexOutput { @@ -366,7 +367,9 @@ fn vs_main(in: VertexInput) -> VertexOutput { @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4f { - return textureSample(uTextureViewSrc, uSamplerSrc, in.texCoord.xy); + let color: vec4f = textureSample(uTextureViewSrc, uSamplerSrc, in.texCoord.xy); + return vec4f(color.rgb, uOpacity); + //return vec4f(color.rgb, 0.5); }; )";