wg_engine: introduced scene opacity

[issues 1479: opacity](#1479)

Supported opacity value for scene

Usage example:

    //Create a Scene
    auto scene = tvg::Scene::gen();
    scene->opacity(100);

    //Prepare Circle
    auto shape1 = tvg::Shape::gen();
    shape1->appendCircle(400, 400, 250, 250);
    shape1->fill(255, 255, 0);
    shape1->opacity(100);
    scene->push(std::move(shape1));

    //Round rectangle
    auto shape2 = tvg::Shape::gen();
    shape2->appendRect(450, 100, 200, 200, 50, 50);
    shape2->fill(0, 255, 0);
    shape2->strokeWidth(10);
    shape2->strokeFill(255, 255, 255);
    scene->push(std::move(shape2));

    canvas->push(std::move(scene));
This commit is contained in:
Sergii Liebodkin 2024-01-18 10:44:12 +02:00 committed by Hermet Park
parent 780f30bfcc
commit 96e0794a67
11 changed files with 331 additions and 157 deletions

View file

@ -29,6 +29,7 @@ WGPUBindGroupLayout WgBindGroupSolidColor::layout = nullptr;
WGPUBindGroupLayout WgBindGroupLinearGradient::layout = nullptr; WGPUBindGroupLayout WgBindGroupLinearGradient::layout = nullptr;
WGPUBindGroupLayout WgBindGroupRadialGradient::layout = nullptr; WGPUBindGroupLayout WgBindGroupRadialGradient::layout = nullptr;
WGPUBindGroupLayout WgBindGroupPicture::layout = nullptr; WGPUBindGroupLayout WgBindGroupPicture::layout = nullptr;
WGPUBindGroupLayout WgBindGroupOpacity::layout = nullptr;
WGPUBindGroupLayout WgBindGroupBlit::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) WGPUBindGroupLayout WgBindGroupBlit::getLayout(WGPUDevice device)
{ {
if (layout) return layout; if (layout) return layout;
@ -292,4 +337,46 @@ void WgBindGroupBlit::initialize(WGPUDevice device, WGPUQueue queue, WGPUSampler
void WgBindGroupBlit::release() void WgBindGroupBlit::release()
{ {
releaseBindGroup(mBindGroup); releaseBindGroup(mBindGroup);
} }
//************************************************************************
// 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();
}

View file

@ -62,7 +62,7 @@ struct WgBindGroupSolidColor : public WgBindGroup
static WGPUBindGroupLayout getLayout(WGPUDevice device); static WGPUBindGroupLayout getLayout(WGPUDevice device);
static void releaseLayout(); static void releaseLayout();
WGPUBuffer uBufferSolidColor; WGPUBuffer uBufferSolidColor{};
void initialize(WGPUDevice device, WGPUQueue queue, void initialize(WGPUDevice device, WGPUQueue queue,
WgShaderTypeSolidColor &uSolidColor); WgShaderTypeSolidColor &uSolidColor);
void release(); void release();
@ -75,7 +75,7 @@ struct WgBindGroupLinearGradient : public WgBindGroup
static WGPUBindGroupLayout getLayout(WGPUDevice device); static WGPUBindGroupLayout getLayout(WGPUDevice device);
static void releaseLayout(); static void releaseLayout();
WGPUBuffer uBufferLinearGradient; WGPUBuffer uBufferLinearGradient{};
void initialize(WGPUDevice device, WGPUQueue queue, void initialize(WGPUDevice device, WGPUQueue queue,
WgShaderTypeLinearGradient &uLinearGradient); WgShaderTypeLinearGradient &uLinearGradient);
void release(); void release();
@ -88,7 +88,7 @@ struct WgBindGroupRadialGradient : public WgBindGroup
static WGPUBindGroupLayout getLayout(WGPUDevice device); static WGPUBindGroupLayout getLayout(WGPUDevice device);
static void releaseLayout(); static void releaseLayout();
WGPUBuffer uBufferRadialGradient; WGPUBuffer uBufferRadialGradient{};
void initialize(WGPUDevice device, WGPUQueue queue, void initialize(WGPUDevice device, WGPUQueue queue,
WgShaderTypeRadialGradient &uRadialGradient); WgShaderTypeRadialGradient &uRadialGradient);
void release(); void release();
@ -107,6 +107,19 @@ struct WgBindGroupPicture : public WgBindGroup
void release(); 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) // @group(0 or 1)
struct WgBindGroupBlit : public WgBindGroup struct WgBindGroupBlit : public WgBindGroup
{ {
@ -120,4 +133,20 @@ struct WgBindGroupBlit : public WgBindGroup
void release(); void release();
}; };
//************************************************************************
// bind group pools
//************************************************************************
class WgBindGroupOpacityPool
{
private:
Array<WgBindGroupOpacity*> mList;
Array<WgBindGroupOpacity*> mPool;
Array<WgBindGroupOpacity*> mUsed;
public:
WgBindGroupOpacity* allocate(WgContext& context, uint32_t opacity);
void reset();
void release();
};
#endif // _TVG_WG_BIND_GROUPS_H_ #endif // _TVG_WG_BIND_GROUPS_H_

View file

@ -272,7 +272,57 @@ void WgBindGroup::releaseBindGroupLayout(WGPUBindGroupLayout& bindGroupLayout)
// pipeline // 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, WGPUVertexBufferLayout vertexBufferLayouts[], uint32_t attribsCount,
WGPUBindGroupLayout bindGroupLayouts[], uint32_t bindGroupsCount, WGPUBindGroupLayout bindGroupLayouts[], uint32_t bindGroupsCount,
WGPUCompareFunction stencilCompareFunction, WGPUStencilOperation stencilOperation, WGPUCompareFunction stencilCompareFunction, WGPUStencilOperation stencilOperation,
@ -292,21 +342,20 @@ void WgPipeline::allocate(WGPUDevice device,
} }
void WgPipeline::release() void WgRenderPipeline::release()
{ {
destroyRenderPipeline(mRenderPipeline); destroyRenderPipeline(mRenderPipeline);
destroyShaderModule(mShaderModule); WgPipeline::release();
destroyPipelineLayout(mPipelineLayout);
} }
void WgPipeline::set(WGPURenderPassEncoder renderPassEncoder) void WgRenderPipeline::set(WGPURenderPassEncoder renderPassEncoder)
{ {
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, mRenderPipeline); wgpuRenderPassEncoderSetPipeline(renderPassEncoder, mRenderPipeline);
}; };
WGPUBlendState WgPipeline::makeBlendState() WGPUBlendState WgRenderPipeline::makeBlendState()
{ {
WGPUBlendState blendState{}; WGPUBlendState blendState{};
blendState.color.operation = WGPUBlendOperation_Add; blendState.color.operation = WGPUBlendOperation_Add;
@ -314,12 +363,12 @@ WGPUBlendState WgPipeline::makeBlendState()
blendState.color.dstFactor = WGPUBlendFactor_OneMinusSrcAlpha; blendState.color.dstFactor = WGPUBlendFactor_OneMinusSrcAlpha;
blendState.alpha.operation = WGPUBlendOperation_Add; blendState.alpha.operation = WGPUBlendOperation_Add;
blendState.alpha.srcFactor = WGPUBlendFactor_One; blendState.alpha.srcFactor = WGPUBlendFactor_One;
blendState.alpha.dstFactor = WGPUBlendFactor_Zero; blendState.alpha.dstFactor = WGPUBlendFactor_One;
return blendState; return blendState;
} }
WGPUColorTargetState WgPipeline::makeColorTargetState(const WGPUBlendState* blendState) WGPUColorTargetState WgRenderPipeline::makeColorTargetState(const WGPUBlendState* blendState)
{ {
WGPUColorTargetState colorTargetState{}; WGPUColorTargetState colorTargetState{};
colorTargetState.nextInChain = nullptr; 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{}; WGPUVertexBufferLayout vertexBufferLayoutPos{};
vertexBufferLayoutPos.arrayStride = stride; 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{}; WGPUVertexState vertexState{};
vertexState.nextInChain = nullptr; vertexState.nextInChain = nullptr;
@ -355,7 +404,7 @@ WGPUVertexState WgPipeline::makeVertexState(WGPUShaderModule shaderModule, const
} }
WGPUPrimitiveState WgPipeline::makePrimitiveState() WGPUPrimitiveState WgRenderPipeline::makePrimitiveState()
{ {
WGPUPrimitiveState primitiveState{}; WGPUPrimitiveState primitiveState{};
primitiveState.nextInChain = nullptr; primitiveState.nextInChain = nullptr;
@ -366,7 +415,7 @@ WGPUPrimitiveState WgPipeline::makePrimitiveState()
return primitiveState; return primitiveState;
} }
WGPUDepthStencilState WgPipeline::makeDepthStencilState(WGPUCompareFunction compare, WGPUStencilOperation operation) WGPUDepthStencilState WgRenderPipeline::makeDepthStencilState(WGPUCompareFunction compare, WGPUStencilOperation operation)
{ {
WGPUDepthStencilState depthStencilState{}; WGPUDepthStencilState depthStencilState{};
depthStencilState.nextInChain = nullptr; depthStencilState.nextInChain = nullptr;
@ -390,7 +439,7 @@ WGPUDepthStencilState WgPipeline::makeDepthStencilState(WGPUCompareFunction comp
} }
WGPUMultisampleState WgPipeline::makeMultisampleState() WGPUMultisampleState WgRenderPipeline::makeMultisampleState()
{ {
WGPUMultisampleState multisampleState{}; WGPUMultisampleState multisampleState{};
multisampleState.nextInChain = nullptr; 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{}; WGPUFragmentState fragmentState{};
fragmentState.nextInChain = nullptr; fragmentState.nextInChain = nullptr;
@ -414,34 +463,7 @@ WGPUFragmentState WgPipeline::makeFragmentState(WGPUShaderModule shaderModule, W
return fragmentState; return fragmentState;
} }
WGPURenderPipeline WgRenderPipeline::createRenderPipeline(WGPUDevice device,
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,
WGPUVertexBufferLayout vertexBufferLayouts[], uint32_t attribsCount, WGPUVertexBufferLayout vertexBufferLayouts[], uint32_t attribsCount,
WGPUCompareFunction stencilCompareFunction, WGPUStencilOperation stencilOperation, WGPUCompareFunction stencilCompareFunction, WGPUStencilOperation stencilOperation,
WGPUPipelineLayout pipelineLayout, WGPUShaderModule shaderModule, WGPUPipelineLayout pipelineLayout, WGPUShaderModule shaderModule,
@ -470,22 +492,7 @@ WGPURenderPipeline WgPipeline::createRenderPipeline(WGPUDevice device,
return wgpuDeviceCreateRenderPipeline(device, &renderPipelineDesc); return wgpuDeviceCreateRenderPipeline(device, &renderPipelineDesc);
} }
void WgRenderPipeline::destroyRenderPipeline(WGPURenderPipeline& renderPipeline)
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)
{ {
if (renderPipeline) wgpuRenderPipelineRelease(renderPipeline); if (renderPipeline) wgpuRenderPipelineRelease(renderPipeline);
renderPipeline = nullptr; renderPipeline = nullptr;

View file

@ -28,6 +28,8 @@
#include "tvgCommon.h" #include "tvgCommon.h"
#include "tvgRender.h" #include "tvgRender.h"
struct WgPipelines;
struct WgContext { struct WgContext {
WGPUInstance instance{}; WGPUInstance instance{};
WGPUAdapter adapter{}; WGPUAdapter adapter{};
@ -37,6 +39,8 @@ struct WgContext {
WGPUFeatureName featureNames[32]{}; WGPUFeatureName featureNames[32]{};
WGPUAdapterProperties adapterProperties{}; WGPUAdapterProperties adapterProperties{};
WGPUSupportedLimits supportedLimits{}; WGPUSupportedLimits supportedLimits{};
WgPipelines* pipelines{}; // external handle (do not release)
void initialize(); void initialize();
void release(); void release();
@ -70,17 +74,29 @@ struct WgBindGroup
struct WgPipeline struct WgPipeline
{ {
protected: 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, void allocate(WGPUDevice device,
WGPUVertexBufferLayout vertexBufferLayouts[], uint32_t attribsCount, WGPUVertexBufferLayout vertexBufferLayouts[], uint32_t attribsCount,
WGPUBindGroupLayout bindGroupLayouts[], uint32_t bindGroupsCount, WGPUBindGroupLayout bindGroupLayouts[], uint32_t bindGroupsCount,
WGPUCompareFunction stencilCompareFunction, WGPUStencilOperation stencilOperation, WGPUCompareFunction stencilCompareFunction, WGPUStencilOperation stencilOperation,
const char* shaderSource, const char* shaderLabel, const char* pipelineLabel); const char* shaderSource, const char* shaderLabel, const char* pipelineLabel);
WGPUPipelineLayout mPipelineLayout{};
WGPUShaderModule mShaderModule{};
WGPURenderPipeline mRenderPipeline{};
public: public:
virtual void initialize(WGPUDevice device) = 0; void release() override;
virtual void release();
void set(WGPURenderPassEncoder renderPassEncoder); void set(WGPURenderPassEncoder renderPassEncoder);
static WGPUBlendState makeBlendState(); static WGPUBlendState makeBlendState();
@ -92,15 +108,11 @@ public:
static WGPUMultisampleState makeMultisampleState(); static WGPUMultisampleState makeMultisampleState();
static WGPUFragmentState makeFragmentState(WGPUShaderModule shaderModule, WGPUColorTargetState* targets, uint32_t size); 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, static WGPURenderPipeline createRenderPipeline(WGPUDevice device,
WGPUVertexBufferLayout vertexBufferLayouts[], uint32_t attribsCount, WGPUVertexBufferLayout vertexBufferLayouts[], uint32_t attribsCount,
WGPUCompareFunction stencilCompareFunction, WGPUStencilOperation stencilOperation, WGPUCompareFunction stencilCompareFunction, WGPUStencilOperation stencilOperation,
WGPUPipelineLayout pipelineLayout, WGPUShaderModule shaderModule, WGPUPipelineLayout pipelineLayout, WGPUShaderModule shaderModule,
const char* pipelineLabel); const char* pipelineLabel);
static void destroyPipelineLayout(WGPUPipelineLayout& pipelineLayout);
static void destroyShaderModule(WGPUShaderModule& shaderModule);
static void destroyRenderPipeline(WGPURenderPipeline& renderPipeline); static void destroyRenderPipeline(WGPURenderPipeline& renderPipeline);
}; };

View file

@ -235,7 +235,8 @@ void WgPipelineBlit::initialize(WGPUDevice device)
// bind groups and layouts // bind groups and layouts
WGPUBindGroupLayout bindGroupLayouts[] = { WGPUBindGroupLayout bindGroupLayouts[] = {
WgBindGroupBlit::getLayout(device) WgBindGroupBlit::getLayout(device),
WgBindGroupOpacity::getLayout(device)
}; };
// stencil function // stencil function
@ -326,35 +327,39 @@ void WgPipelineComposition::initialize(WGPUDevice device, const char* shaderSrc)
// pipelines // pipelines
//************************************************************************ //************************************************************************
void WgPipelines::initialize(WGPUDevice device) void WgPipelines::initialize(WgContext& context)
{ {
fillShape.initialize(device); fillShape.initialize(context.device);
fillStroke.initialize(device); fillStroke.initialize(context.device);
solid.initialize(device); solid.initialize(context.device);
linear.initialize(device); linear.initialize(context.device);
radial.initialize(device); radial.initialize(context.device);
image.initialize(device); image.initialize(context.device);
blit.initialize(device); blit.initialize(context.device);
blitColor.initialize(device); blitColor.initialize(context.device);
// composition pipelines // composition pipelines
compAlphaMask.initialize(device, cShaderSource_PipelineCompAlphaMask); compAlphaMask.initialize(context.device, cShaderSource_PipelineCompAlphaMask);
compInvAlphaMask.initialize(device, cShaderSource_PipelineCompInvAlphaMask); compInvAlphaMask.initialize(context.device, cShaderSource_PipelineCompInvAlphaMask);
compLumaMask.initialize(device, cShaderSource_PipelineCompLumaMask); compLumaMask.initialize(context.device, cShaderSource_PipelineCompLumaMask);
compInvLumaMask.initialize(device, cShaderSource_PipelineCompInvLumaMask); compInvLumaMask.initialize(context.device, cShaderSource_PipelineCompInvLumaMask);
compAddMask.initialize(device, cShaderSource_PipelineCompAddMask); compAddMask.initialize(context.device, cShaderSource_PipelineCompAddMask);
compSubtractMask.initialize(device, cShaderSource_PipelineCompSubtractMask); compSubtractMask.initialize(context.device, cShaderSource_PipelineCompSubtractMask);
compIntersectMask.initialize(device, cShaderSource_PipelineCompIntersectMask); compIntersectMask.initialize(context.device, cShaderSource_PipelineCompIntersectMask);
compDifferenceMask.initialize(device, cShaderSource_PipelineCompDifferenceMask); compDifferenceMask.initialize(context.device, cShaderSource_PipelineCompDifferenceMask);
// store pipelines to context
context.pipelines = this;
} }
void WgPipelines::release() void WgPipelines::release()
{ {
WgBindGroupBlit::releaseLayout(); WgBindGroupBlit::releaseLayout();
WgBindGroupOpacity::releaseLayout();
WgBindGroupPicture::releaseLayout(); WgBindGroupPicture::releaseLayout();
WgBindGroupRadialGradient::releaseLayout(); WgBindGroupRadialGradient::releaseLayout();
WgBindGroupLinearGradient::releaseLayout(); WgBindGroupLinearGradient::releaseLayout();
WgBindGroupSolidColor::releaseLayout(); WgBindGroupSolidColor::releaseLayout();
WgBindGroupPaint::releaseLayout();
WgBindGroupCanvas::releaseLayout(); WgBindGroupCanvas::releaseLayout();
compDifferenceMask.release(); compDifferenceMask.release();
compIntersectMask.release(); compIntersectMask.release();

View file

@ -25,7 +25,7 @@
#include "tvgWgBindGroups.h" #include "tvgWgBindGroups.h"
struct WgPipelineFillShape: public WgPipeline struct WgPipelineFillShape: public WgRenderPipeline
{ {
void initialize(WGPUDevice device) override; void initialize(WGPUDevice device) override;
void use(WGPURenderPassEncoder encoder, WgBindGroupCanvas& groupCanvas, WgBindGroupPaint& groupPaint) 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 initialize(WGPUDevice device) override;
void use(WGPURenderPassEncoder encoder, WgBindGroupCanvas& groupCanvas, WgBindGroupPaint& groupPaint) 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 initialize(WGPUDevice device) override;
void use(WGPURenderPassEncoder encoder, WgBindGroupCanvas& groupCanvas,WgBindGroupPaint& groupPaint, WgBindGroupSolidColor& groupSolid) 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 initialize(WGPUDevice device) override;
void use(WGPURenderPassEncoder encoder, WgBindGroupCanvas& groupCanvas, WgBindGroupPaint& groupPaint, WgBindGroupLinearGradient& groupLinear) 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 initialize(WGPUDevice device) override;
void use(WGPURenderPassEncoder encoder, WgBindGroupCanvas& groupCanvas, WgBindGroupPaint& groupPaint, WgBindGroupRadialGradient& groupRadial) 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 initialize(WGPUDevice device) override;
void use(WGPURenderPassEncoder encoder, WgBindGroupCanvas& groupCanvas, WgBindGroupPaint& groupPaint, WgBindGroupPicture& groupPicture) 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 initialize(WGPUDevice device) override;
void use(WGPURenderPassEncoder encoder, WgBindGroupBlit& groupBlit) void use(WGPURenderPassEncoder encoder, WgBindGroupBlit& groupBlit)
@ -105,17 +118,7 @@ struct WgPipelineBlit: public WgPipeline
} }
}; };
struct WgPipelineBlitColor: public WgPipeline struct WgPipelineComposition: public WgRenderPipeline
{
void initialize(WGPUDevice device) override;
void use(WGPURenderPassEncoder encoder, WgBindGroupBlit& groupBlit)
{
set(encoder);
groupBlit.set(encoder, 0);
}
};
struct WgPipelineComposition: public WgPipeline
{ {
void initialize(WGPUDevice device) override {}; void initialize(WGPUDevice device) override {};
void initialize(WGPUDevice device, const char* shaderSrc); void initialize(WGPUDevice device, const char* shaderSrc);
@ -147,7 +150,7 @@ struct WgPipelines
WgPipelineComposition compIntersectMask; WgPipelineComposition compIntersectMask;
WgPipelineComposition compDifferenceMask; WgPipelineComposition compDifferenceMask;
void initialize(WGPUDevice device); void initialize(WgContext& context);
void release(); void release();
WgPipelineComposition* getCompositionPipeline(CompositeMethod method); WgPipelineComposition* getCompositionPipeline(CompositeMethod method);

View file

@ -22,7 +22,7 @@
#include "tvgWgRenderTarget.h" #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); release(context);
// sampler descriptor // sampler descriptor
@ -45,7 +45,7 @@ void WgRenderTarget::initialize(WgContext& context, WgPipelines& pipelines, uint
WGPUTextureDescriptor textureDescColor{}; WGPUTextureDescriptor textureDescColor{};
textureDescColor.nextInChain = nullptr; textureDescColor.nextInChain = nullptr;
textureDescColor.label = "The target texture color"; 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.dimension = WGPUTextureDimension_2D;
textureDescColor.size = { w, h, 1 }; textureDescColor.size = { w, h, 1 };
textureDescColor.format = WGPUTextureFormat_BGRA8Unorm; textureDescColor.format = WGPUTextureFormat_BGRA8Unorm;
@ -103,7 +103,7 @@ void WgRenderTarget::initialize(WgContext& context, WgPipelines& pipelines, uint
WgGeometryData geometryDataWnd; WgGeometryData geometryDataWnd;
geometryDataWnd.appendBlitBox(); geometryDataWnd.appendBlitBox();
mMeshDataCanvasWnd.update(context, &geometryDataWnd); 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); assert(mRenderPassEncoder);
mPipelines->blit.use(mRenderPassEncoder, renderTargetSrc->bindGroupBlit); mPipelines->blit.use(mRenderPassEncoder, renderTargetSrc->bindGroupBlit, *mBindGroupOpacity);
mMeshDataCanvasWnd.drawImage(mRenderPassEncoder); mMeshDataCanvasWnd.drawImage(mRenderPassEncoder);
} }
@ -272,3 +272,37 @@ void WgRenderTarget::compose(WgContext& context, WgRenderTarget* renderTargetSrc
pipeline->use(mRenderPassEncoder, renderTargetSrc->bindGroupBlit, renderTargetMsk->bindGroupBlit); pipeline->use(mRenderPassEncoder, renderTargetSrc->bindGroupBlit, renderTargetMsk->bindGroupBlit);
mMeshDataCanvasWnd.drawImage(mRenderPassEncoder); 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();
};

View file

@ -43,7 +43,7 @@ public:
WGPUTextureView textureViewStencil{}; WGPUTextureView textureViewStencil{};
WgBindGroupBlit bindGroupBlit; WgBindGroupBlit bindGroupBlit;
public: 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 release(WgContext& context);
void beginRenderPass(WGPUCommandEncoder commandEncoder, WGPUTextureView colorAttachement, bool clear); void beginRenderPass(WGPUCommandEncoder commandEncoder, WGPUTextureView colorAttachement, bool clear);
@ -54,9 +54,21 @@ public:
void renderStroke(WgRenderDataShape* renderData); void renderStroke(WgRenderDataShape* renderData);
void renderPicture(WgRenderDataPicture* 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 blitColor(WgContext& context, WgRenderTarget* renderTargetSrc);
void compose(WgContext& context, WgRenderTarget* renderTargetSrc, WgRenderTarget* renderTargetMsk, CompositeMethod method); void compose(WgContext& context, WgRenderTarget* renderTargetSrc, WgRenderTarget* renderTargetMsk, CompositeMethod method);
}; };
class WgRenderTargetPool {
private:
Array<WgRenderTarget*> mList;
Array<WgRenderTarget*> mPool;
public:
WgRenderTarget* allocate(WgContext& context, uint32_t w, uint32_t h);
void free(WgContext& context, WgRenderTarget* renderTarget);
void release(WgContext& context);
};
#endif #endif

View file

@ -42,18 +42,16 @@ WgRenderer::~WgRenderer()
void WgRenderer::initialize() void WgRenderer::initialize()
{ {
mContext.initialize(); mContext.initialize();
mPipelines.initialize(mContext.device); mPipelines.initialize(mContext);
} }
void WgRenderer::release() void WgRenderer::release()
{ {
// clear render targets mCompositorStack.clear();
for (uint32_t i = 0; i < mRenderTargetPool.count; i++) { mRenderTargetStack.clear();
mRenderTargetPool[i]->release(mContext); mBindGroupOpacityPool.release();
delete mRenderTargetPool[i]; mRenderTargetPool.release(mContext);
}
mRenderTargetPool.clear();
mRenderTargetRoot.release(mContext); mRenderTargetRoot.release(mContext);
mRenderTargetWnd.release(mContext); mRenderTargetWnd.release(mContext);
if (mSwapChain) wgpuSwapChainRelease(mSwapChain); if (mSwapChain) wgpuSwapChainRelease(mSwapChain);
@ -161,6 +159,7 @@ bool WgRenderer::postRender()
{ {
mRenderTargetRoot.endRenderPass(); mRenderTargetRoot.endRenderPass();
mRenderTargetStack.pop(); mRenderTargetStack.pop();
mBindGroupOpacityPool.reset();
mContext.executeCommandEncoder(mCommandEncoder); mContext.executeCommandEncoder(mCommandEncoder);
wgpuCommandEncoderRelease(mCommandEncoder); wgpuCommandEncoderRelease(mCommandEncoder);
return true; return true;
@ -235,7 +234,7 @@ bool WgRenderer::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t
mTargetSurface.w = w; mTargetSurface.w = w;
mTargetSurface.h = h; mTargetSurface.h = h;
mRenderTargetRoot.initialize(mContext, mPipelines, w, h); mRenderTargetRoot.initialize(mContext, w, h);
return true; return true;
} }
@ -275,8 +274,8 @@ bool WgRenderer::target(void* window, uint32_t w, uint32_t h)
mSwapChain = wgpuDeviceCreateSwapChain(mContext.device, mSurface, &swapChainDesc); mSwapChain = wgpuDeviceCreateSwapChain(mContext.device, mSurface, &swapChainDesc);
assert(mSwapChain); assert(mSwapChain);
mRenderTargetWnd.initialize(mContext, mPipelines, w, h); mRenderTargetWnd.initialize(mContext, w, h);
mRenderTargetRoot.initialize(mContext, mPipelines, w, h); mRenderTargetRoot.initialize(mContext, w, h);
return true; return true;
} }
@ -298,7 +297,7 @@ bool WgRenderer::beginComposite(TVG_UNUSED Compositor* cmp, TVG_UNUSED Composite
mRenderTargetStack.last()->endRenderPass(); mRenderTargetStack.last()->endRenderPass();
// create new render target and begin new render pass // 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); renderTarget->beginRenderPass(mCommandEncoder, true);
mRenderTargetStack.push(renderTarget); mRenderTargetStack.push(renderTarget);
@ -319,10 +318,13 @@ bool WgRenderer::endComposite(TVG_UNUSED Compositor* cmp)
// apply current render target // apply current render target
WgRenderTarget* renderTarget = mRenderTargetStack.last(); WgRenderTarget* renderTarget = mRenderTargetStack.last();
renderTarget->beginRenderPass(mCommandEncoder, false); 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 // back render targets to the pool
releaseRenderTarget(renderTargetSrc); mRenderTargetPool.free(mContext, renderTargetSrc);
} else { } else {
// end current render pass // end current render pass
mRenderTargetStack.last()->endRenderPass(); mRenderTargetStack.last()->endRenderPass();
@ -339,8 +341,8 @@ bool WgRenderer::endComposite(TVG_UNUSED Compositor* cmp)
renderTarget->compose(mContext, renderTargetSrc, renderTargetMsk, cmp->method); renderTarget->compose(mContext, renderTargetSrc, renderTargetMsk, cmp->method);
// back render targets to the pool // back render targets to the pool
releaseRenderTarget(renderTargetSrc); mRenderTargetPool.free(mContext, renderTargetSrc);
releaseRenderTarget(renderTargetMsk); mRenderTargetPool.free(mContext, renderTargetMsk);
} }
// delete current compositor // 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() WgRenderer* WgRenderer::gen()
{ {
return new WgRenderer(); return new WgRenderer();

View file

@ -62,12 +62,12 @@ public:
// render handles // render handles
WGPUCommandEncoder mCommandEncoder{}; WGPUCommandEncoder mCommandEncoder{};
Array<WgRenderTarget*> mRenderTargetStack;
Array<WgRenderTarget*> mRenderTargetPool;
Array<Compositor*> mCompositorStack; Array<Compositor*> mCompositorStack;
Array<WgRenderTarget*> mRenderTargetStack;
WgRenderTarget* allocateRenderTarget(); // render object pools
void releaseRenderTarget(WgRenderTarget* renderTarget); WgRenderTargetPool mRenderTargetPool;
WgBindGroupOpacityPool mBindGroupOpacityPool;
private: private:
WgContext mContext; WgContext mContext;
WgPipelines mPipelines; WgPipelines mPipelines;

View file

@ -352,8 +352,9 @@ struct VertexOutput {
@location(0) texCoord: vec2f @location(0) texCoord: vec2f
}; };
@group(0) @binding(0) var uSamplerSrc : sampler; @group(0) @binding(0) var uSamplerSrc : sampler;
@group(0) @binding(1) var uTextureViewSrc : texture_2d<f32>; @group(0) @binding(1) var uTextureViewSrc : texture_2d<f32>;
@group(1) @binding(0) var<uniform> uOpacity : f32;
@vertex @vertex
fn vs_main(in: VertexInput) -> VertexOutput { fn vs_main(in: VertexInput) -> VertexOutput {
@ -366,7 +367,9 @@ fn vs_main(in: VertexInput) -> VertexOutput {
@fragment @fragment
fn fs_main(in: VertexOutput) -> @location(0) vec4f { 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);
}; };
)"; )";