mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-10 06:34:01 +00:00
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:
parent
780f30bfcc
commit
96e0794a67
11 changed files with 331 additions and 157 deletions
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
)";
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue