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 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);
}
}
//************************************************************************
// 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 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<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_

View file

@ -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;

View file

@ -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);
};

View file

@ -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();

View file

@ -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);

View file

@ -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();
};

View file

@ -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<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

View file

@ -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();

View file

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

View file

@ -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<f32>;
@group(0) @binding(0) var uSamplerSrc : sampler;
@group(0) @binding(1) var uTextureViewSrc : texture_2d<f32>;
@group(1) @binding(0) var<uniform> 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);
};
)";