From 9742cfe293f5261d25a34576ebec703178e59080 Mon Sep 17 00:00:00 2001 From: Sergii Liebodkin Date: Wed, 13 Dec 2023 12:37:58 +0200 Subject: [PATCH] wg_engine: pipelines and bind groups refactoring - shader and system types synchronized - pipelens and bind groups description separated - pipelines description simplified --- src/renderer/wg_engine/meson.build | 20 +- src/renderer/wg_engine/tvgWgBindGroups.cpp | 239 ++++++++++ src/renderer/wg_engine/tvgWgBindGroups.h | 116 +++++ src/renderer/wg_engine/tvgWgCommon.cpp | 343 +++++++++++++++ src/renderer/wg_engine/tvgWgCommon.h | 59 +++ src/renderer/wg_engine/tvgWgPipelineBase.cpp | 73 --- src/renderer/wg_engine/tvgWgPipelineBase.h | 56 --- src/renderer/wg_engine/tvgWgPipelineEmpty.cpp | 243 ---------- src/renderer/wg_engine/tvgWgPipelineEmpty.h | 63 --- src/renderer/wg_engine/tvgWgPipelineImage.cpp | 415 ------------------ src/renderer/wg_engine/tvgWgPipelineImage.h | 63 --- .../wg_engine/tvgWgPipelineLinear.cpp | 305 ------------- src/renderer/wg_engine/tvgWgPipelineLinear.h | 61 --- .../wg_engine/tvgWgPipelineRadial.cpp | 303 ------------- src/renderer/wg_engine/tvgWgPipelineRadial.h | 61 --- src/renderer/wg_engine/tvgWgPipelineSolid.cpp | 289 ------------ src/renderer/wg_engine/tvgWgPipelineSolid.h | 56 --- .../wg_engine/tvgWgPipelineStroke.cpp | 243 ---------- src/renderer/wg_engine/tvgWgPipelineStroke.h | 46 -- src/renderer/wg_engine/tvgWgPipelines.cpp | 246 +++++++++++ src/renderer/wg_engine/tvgWgPipelines.h | 114 +++++ src/renderer/wg_engine/tvgWgRenderData.cpp | 143 ++++-- src/renderer/wg_engine/tvgWgRenderData.h | 45 +- src/renderer/wg_engine/tvgWgRenderer.cpp | 155 +++---- src/renderer/wg_engine/tvgWgRenderer.h | 17 +- src/renderer/wg_engine/tvgWgShaderSrc.cpp | 245 ++++++----- src/renderer/wg_engine/tvgWgShaderSrc.h | 16 +- src/renderer/wg_engine/tvgWgShaderTypes.cpp | 141 ++++++ src/renderer/wg_engine/tvgWgShaderTypes.h | 111 +++++ 29 files changed, 1748 insertions(+), 2539 deletions(-) create mode 100644 src/renderer/wg_engine/tvgWgBindGroups.cpp create mode 100644 src/renderer/wg_engine/tvgWgBindGroups.h create mode 100644 src/renderer/wg_engine/tvgWgCommon.cpp delete mode 100644 src/renderer/wg_engine/tvgWgPipelineBase.cpp delete mode 100644 src/renderer/wg_engine/tvgWgPipelineBase.h delete mode 100644 src/renderer/wg_engine/tvgWgPipelineEmpty.cpp delete mode 100644 src/renderer/wg_engine/tvgWgPipelineEmpty.h delete mode 100644 src/renderer/wg_engine/tvgWgPipelineImage.cpp delete mode 100644 src/renderer/wg_engine/tvgWgPipelineImage.h delete mode 100644 src/renderer/wg_engine/tvgWgPipelineLinear.cpp delete mode 100644 src/renderer/wg_engine/tvgWgPipelineLinear.h delete mode 100644 src/renderer/wg_engine/tvgWgPipelineRadial.cpp delete mode 100644 src/renderer/wg_engine/tvgWgPipelineRadial.h delete mode 100644 src/renderer/wg_engine/tvgWgPipelineSolid.cpp delete mode 100644 src/renderer/wg_engine/tvgWgPipelineSolid.h delete mode 100644 src/renderer/wg_engine/tvgWgPipelineStroke.cpp delete mode 100644 src/renderer/wg_engine/tvgWgPipelineStroke.h create mode 100644 src/renderer/wg_engine/tvgWgPipelines.cpp create mode 100644 src/renderer/wg_engine/tvgWgPipelines.h create mode 100644 src/renderer/wg_engine/tvgWgShaderTypes.cpp create mode 100644 src/renderer/wg_engine/tvgWgShaderTypes.h diff --git a/src/renderer/wg_engine/meson.build b/src/renderer/wg_engine/meson.build index 451edfaf..5e33e2f5 100644 --- a/src/renderer/wg_engine/meson.build +++ b/src/renderer/wg_engine/meson.build @@ -1,14 +1,20 @@ source_file = [ + 'tvgWgBindGroups.h', + 'tvgWgCommon.h', + 'tvgWgGeometry.h', + 'tvgWgPipelines.h', + 'tvgWgRenderData.h', + 'tvgWgRenderer.h', + 'tvgWgShaderSrc.h', + 'tvgWgShaderTypes.h' + 'tvgWgBindGroups.cpp', + 'tvgWgCommon.cpp', 'tvgWgGeometry.cpp', - 'tvgWgPipelineBase.cpp', - 'tvgWgPipelineEmpty.cpp', - 'tvgWgPipelineLinear.cpp', - 'tvgWgPipelineSolid.cpp', - 'tvgWgPipelineRadial.cpp', - 'tvgWgPipelineStroke.cpp', + 'tvgWgPipelines.cpp', 'tvgWgRenderData.cpp', 'tvgWgRenderer.cpp', - 'tvgWgShaderSrc.cpp' + 'tvgWgShaderSrc.cpp', + 'tvgWgShaderTypes.cpp' ] engine_dep += [declare_dependency( diff --git a/src/renderer/wg_engine/tvgWgBindGroups.cpp b/src/renderer/wg_engine/tvgWgBindGroups.cpp new file mode 100644 index 00000000..49bf7739 --- /dev/null +++ b/src/renderer/wg_engine/tvgWgBindGroups.cpp @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "tvgWgBindGroups.h" + +WGPUBindGroupLayout WgBindGroupCanvas::layout = nullptr; +WGPUBindGroupLayout WgBindGroupCanvas::getLayout(WGPUDevice device) { + if (layout) return layout; + const WGPUBindGroupLayoutEntry bindGroupLayoutEntries[] { + makeBindGroupLayoutEntryBuffer(0) + }; + layout = createBindGroupLayout(device, bindGroupLayoutEntries, 1); + assert(layout); + return layout; +} + +void WgBindGroupCanvas::releaseLayout() { + releaseBindGroupLayout(layout); +}; + +void WgBindGroupCanvas::initialize(WGPUDevice device, WGPUQueue queue, WgShaderTypeMat4x4f& uViewMat) { + release(); + uBufferViewMat = createBuffer(device, queue, &uViewMat, sizeof(uViewMat)); + const WGPUBindGroupEntry bindGroupEntries[] { + makeBindGroupEntryBuffer(0, uBufferViewMat) + }; + mBindGroup = createBindGroup(device, getLayout(device), bindGroupEntries, 1); + assert(mBindGroup); +} + +void WgBindGroupCanvas::release() { + releaseBindGroup(mBindGroup); + releaseBuffer(uBufferViewMat); +} + +WGPUBindGroupLayout WgBindGroupPaint::layout = nullptr; +WGPUBindGroupLayout WgBindGroupPaint::getLayout(WGPUDevice device) { + if (layout) return layout; + const WGPUBindGroupLayoutEntry bindGroupLayoutEntries[] { + makeBindGroupLayoutEntryBuffer(0), + makeBindGroupLayoutEntryBuffer(1) + }; + layout = createBindGroupLayout(device, bindGroupLayoutEntries, 2); + assert(layout); + return layout; +} + +void WgBindGroupPaint::releaseLayout() { + releaseBindGroupLayout(layout); +}; + +void WgBindGroupPaint::initialize(WGPUDevice device, WGPUQueue queue, WgShaderTypeMat4x4f& uModelMat, WgShaderTypeBlendSettings& uBlendSettings) { + release(); + uBufferModelMat = createBuffer(device, queue, &uModelMat, sizeof(uModelMat)); + uBufferBlendSettings = createBuffer(device, queue, &uBlendSettings, sizeof(uBlendSettings)); + const WGPUBindGroupEntry bindGroupEntries[] { + makeBindGroupEntryBuffer(0, uBufferModelMat), + makeBindGroupEntryBuffer(1, uBufferBlendSettings) + }; + mBindGroup = createBindGroup(device, getLayout(device), bindGroupEntries, 2); + assert(mBindGroup); +} + +void WgBindGroupPaint::release() { + releaseBindGroup(mBindGroup); + releaseBuffer(uBufferBlendSettings); + releaseBuffer(uBufferModelMat); +} + +WGPUBindGroupLayout WgBindGroupSolidColor::layout = nullptr; +WGPUBindGroupLayout WgBindGroupSolidColor::getLayout(WGPUDevice device) { + if (layout) return layout; + const WGPUBindGroupLayoutEntry bindGroupLayoutEntries[] { + makeBindGroupLayoutEntryBuffer(0) + }; + layout = createBindGroupLayout(device, bindGroupLayoutEntries, 1); + assert(layout); + return layout; +} + +void WgBindGroupSolidColor::releaseLayout() { + releaseBindGroupLayout(layout); +}; + +void WgBindGroupSolidColor::initialize(WGPUDevice device, WGPUQueue queue, WgShaderTypeSolidColor &uSolidColor) { + release(); + uBufferSolidColor = createBuffer(device, queue, &uSolidColor, sizeof(uSolidColor)); + const WGPUBindGroupEntry bindGroupEntries[] { + makeBindGroupEntryBuffer(0, uBufferSolidColor) + }; + mBindGroup = createBindGroup(device, getLayout(device), bindGroupEntries, 1); + assert(mBindGroup); +} + +void WgBindGroupSolidColor::release() { + releaseBindGroup(mBindGroup); + releaseBuffer(uBufferSolidColor); +} + +WGPUBindGroupLayout WgBindGroupLinearGradient::layout = nullptr; +WGPUBindGroupLayout WgBindGroupLinearGradient::getLayout(WGPUDevice device) { + if (layout) return layout; + const WGPUBindGroupLayoutEntry bindGroupLayoutEntries[] { + makeBindGroupLayoutEntryBuffer(0) + }; + layout = createBindGroupLayout(device, bindGroupLayoutEntries, 1); + assert(layout); + return layout; +} + +void WgBindGroupLinearGradient::releaseLayout() { + releaseBindGroupLayout(layout); +}; + +void WgBindGroupLinearGradient::initialize(WGPUDevice device, WGPUQueue queue, WgShaderTypeLinearGradient &uLinearGradient) { + release(); + uBufferLinearGradient = createBuffer(device, queue, &uLinearGradient, sizeof(uLinearGradient)); + const WGPUBindGroupEntry bindGroupEntries[] { + makeBindGroupEntryBuffer(0, uBufferLinearGradient) + }; + mBindGroup = createBindGroup(device, getLayout(device), bindGroupEntries, 1); + assert(mBindGroup); +} + +void WgBindGroupLinearGradient::release() { + releaseBindGroup(mBindGroup); + releaseBuffer(uBufferLinearGradient); +} + +WGPUBindGroupLayout WgBindGroupRadialGradient::layout = nullptr; +WGPUBindGroupLayout WgBindGroupRadialGradient::getLayout(WGPUDevice device) { + if (layout) return layout; + const WGPUBindGroupLayoutEntry bindGroupLayoutEntries[] { + makeBindGroupLayoutEntryBuffer(0) + }; + layout = createBindGroupLayout(device, bindGroupLayoutEntries, 1); + assert(layout); + return layout; +} + +void WgBindGroupRadialGradient::releaseLayout() { + releaseBindGroupLayout(layout); +}; + +void WgBindGroupRadialGradient::initialize(WGPUDevice device, WGPUQueue queue, WgShaderTypeRadialGradient &uRadialGradient) { + release(); + uBufferRadialGradient = createBuffer(device, queue, &uRadialGradient, sizeof(uRadialGradient)); + const WGPUBindGroupEntry bindGroupEntries[] { + makeBindGroupEntryBuffer(0, uBufferRadialGradient) + }; + mBindGroup = createBindGroup(device, getLayout(device), bindGroupEntries, 1); + assert(mBindGroup); +} + +void WgBindGroupRadialGradient::release() { + releaseBuffer(uBufferRadialGradient); + releaseBindGroup(mBindGroup); +} + +WGPUBindGroupLayout WgBindGroupPicture::layout = nullptr; +WGPUBindGroupLayout WgBindGroupPicture::getLayout(WGPUDevice device) { + if (layout) return layout; + const WGPUBindGroupLayoutEntry bindGroupLayoutEntries[] { + makeBindGroupLayoutEntrySampler(0), + makeBindGroupLayoutEntryTextureView(1) + }; + layout = createBindGroupLayout(device, bindGroupLayoutEntries, 2); + assert(layout); + return layout; +} + +void WgBindGroupPicture::releaseLayout() { + releaseBindGroupLayout(layout); +}; + +void WgBindGroupPicture::initialize(WGPUDevice device, WGPUQueue queue, WGPUSampler uSampler, WGPUTextureView uTextureView) { + release(); + const WGPUBindGroupEntry bindGroupEntries[] { + makeBindGroupEntrySampler(0, uSampler), + makeBindGroupEntryTextureView(1, uTextureView) + }; + mBindGroup = createBindGroup(device, getLayout(device), bindGroupEntries, 2); + assert(mBindGroup); +} + +void WgBindGroupPicture::release() { + releaseBindGroup(mBindGroup); +} + +WGPUBindGroupLayout WgBindGroupCompose::layout = nullptr; +WGPUBindGroupLayout WgBindGroupCompose::getLayout(WGPUDevice device) { + if (layout) return layout; + const WGPUBindGroupLayoutEntry bindGroupLayoutEntries[] { + makeBindGroupLayoutEntrySampler(0), + makeBindGroupLayoutEntryTextureView(1), + makeBindGroupLayoutEntryTextureView(2) + }; + layout = createBindGroupLayout(device, bindGroupLayoutEntries, 3); + assert(layout); + return layout; +} + +void WgBindGroupCompose::releaseLayout() { + releaseBindGroupLayout(layout); +}; + +void WgBindGroupCompose::initialize(WGPUDevice device, WGPUQueue queue, WGPUSampler uSampler, WGPUTextureView uTextureSrc, WGPUTextureView uTextureDst) { + release(); + const WGPUBindGroupEntry bindGroupEntries[] { + makeBindGroupEntrySampler(0, uSampler), + makeBindGroupEntryTextureView(1, uTextureSrc), + makeBindGroupEntryTextureView(2, uTextureDst) + }; + mBindGroup = createBindGroup(device, getLayout(device), bindGroupEntries, 3); + assert(mBindGroup); +} + +void WgBindGroupCompose::release() { + releaseBindGroup(mBindGroup); +} diff --git a/src/renderer/wg_engine/tvgWgBindGroups.h b/src/renderer/wg_engine/tvgWgBindGroups.h new file mode 100644 index 00000000..c6379377 --- /dev/null +++ b/src/renderer/wg_engine/tvgWgBindGroups.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef _TVG_WG_BIND_GROUPS_H_ +#define _TVG_WG_BIND_GROUPS_H_ + +#include "tvgWgCommon.h" +#include "tvgWgShaderTypes.h" + +// @group(0) +struct WgBindGroupCanvas: public WgBindGroup { + static WGPUBindGroupLayout layout; + static WGPUBindGroupLayout getLayout(WGPUDevice device); + static void releaseLayout(); + + WGPUBuffer uBufferViewMat{}; + void initialize(WGPUDevice device, WGPUQueue queue, + WgShaderTypeMat4x4f& uViewMat); + void release(); +}; + +// @group(1) +struct WgBindGroupPaint: public WgBindGroup { + static WGPUBindGroupLayout layout; + static WGPUBindGroupLayout getLayout(WGPUDevice device); + static void releaseLayout(); + + WGPUBuffer uBufferModelMat{}; + WGPUBuffer uBufferBlendSettings{}; + void initialize(WGPUDevice device, WGPUQueue queue, + WgShaderTypeMat4x4f& uModelMat, + WgShaderTypeBlendSettings& uBlendSettings); + void release(); +}; + +// @group(2) +struct WgBindGroupSolidColor: public WgBindGroup { + static WGPUBindGroupLayout layout; + static WGPUBindGroupLayout getLayout(WGPUDevice device); + static void releaseLayout(); + + WGPUBuffer uBufferSolidColor; + void initialize(WGPUDevice device, WGPUQueue queue, + WgShaderTypeSolidColor &uSolidColor); + void release(); +}; + +// @group(2) +struct WgBindGroupLinearGradient: public WgBindGroup { + static WGPUBindGroupLayout layout; + static WGPUBindGroupLayout getLayout(WGPUDevice device); + static void releaseLayout(); + + WGPUBuffer uBufferLinearGradient; + void initialize(WGPUDevice device, WGPUQueue queue, + WgShaderTypeLinearGradient &uLinearGradient); + void release(); +}; + +// @group(2) +struct WgBindGroupRadialGradient: public WgBindGroup { + static WGPUBindGroupLayout layout; + static WGPUBindGroupLayout getLayout(WGPUDevice device); + static void releaseLayout(); + + WGPUBuffer uBufferRadialGradient; + void initialize(WGPUDevice device, WGPUQueue queue, + WgShaderTypeRadialGradient &uRadialGradient); + void release(); +}; + +// @group(2) +struct WgBindGroupPicture: public WgBindGroup { + static WGPUBindGroupLayout layout; + static WGPUBindGroupLayout getLayout(WGPUDevice device); + static void releaseLayout(); + + void initialize(WGPUDevice device, WGPUQueue queue, + WGPUSampler uSampler, + WGPUTextureView uTextureView); + void release(); +}; + +// @group(2) +struct WgBindGroupCompose: public WgBindGroup { + static WGPUBindGroupLayout layout; + static WGPUBindGroupLayout getLayout(WGPUDevice device); + static void releaseLayout(); + + void initialize(WGPUDevice device, WGPUQueue queue, + WGPUSampler uSampler, + WGPUTextureView uTextureSrc, + WGPUTextureView uTextureDst); + void release(); +}; + +#endif // _TVG_WG_BIND_GROUPS_H_ diff --git a/src/renderer/wg_engine/tvgWgCommon.cpp b/src/renderer/wg_engine/tvgWgCommon.cpp new file mode 100644 index 00000000..c9ee8803 --- /dev/null +++ b/src/renderer/wg_engine/tvgWgCommon.cpp @@ -0,0 +1,343 @@ +/* + * Copyright (c) 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "tvgWgCommon.h" + +//***************************************************************************** +// bind group +//***************************************************************************** + +void WgBindGroup::set(WGPURenderPassEncoder encoder, uint32_t groupIndex) { + wgpuRenderPassEncoderSetBindGroup(encoder, groupIndex, mBindGroup, 0, nullptr); +} + +WGPUBindGroupEntry WgBindGroup::makeBindGroupEntryBuffer(uint32_t binding, WGPUBuffer buffer) { + WGPUBindGroupEntry bindGroupEntry{}; + bindGroupEntry.nextInChain = nullptr; + bindGroupEntry.binding = binding; + bindGroupEntry.buffer = buffer; + bindGroupEntry.offset = 0; + bindGroupEntry.size = wgpuBufferGetSize(buffer); + bindGroupEntry.sampler = nullptr; + bindGroupEntry.textureView = nullptr; + return bindGroupEntry; +} + +WGPUBindGroupEntry WgBindGroup::makeBindGroupEntrySampler(uint32_t binding, WGPUSampler sampler) { + WGPUBindGroupEntry bindGroupEntry{}; + bindGroupEntry.nextInChain = nullptr; + bindGroupEntry.binding = binding; + bindGroupEntry.buffer = nullptr; + bindGroupEntry.offset = 0; + bindGroupEntry.size = 0; + bindGroupEntry.sampler = sampler; + bindGroupEntry.textureView = nullptr; + return bindGroupEntry; +} + +WGPUBindGroupEntry WgBindGroup::makeBindGroupEntryTextureView(uint32_t binding, WGPUTextureView textureView) { + WGPUBindGroupEntry bindGroupEntry{}; + bindGroupEntry.nextInChain = nullptr; + bindGroupEntry.binding = binding; + bindGroupEntry.buffer = nullptr; + bindGroupEntry.offset = 0; + bindGroupEntry.size = 0; + bindGroupEntry.sampler = nullptr; + bindGroupEntry.textureView = textureView; + return bindGroupEntry; +} + +WGPUBindGroupLayoutEntry WgBindGroup::makeBindGroupLayoutEntryBuffer(uint32_t binding) { + WGPUBindGroupLayoutEntry bindGroupLayoutEntry{}; + bindGroupLayoutEntry.nextInChain = nullptr; + bindGroupLayoutEntry.binding = binding; + bindGroupLayoutEntry.visibility = WGPUShaderStage_Vertex | WGPUShaderStage_Fragment; + bindGroupLayoutEntry.buffer.nextInChain = nullptr; + bindGroupLayoutEntry.buffer.type = WGPUBufferBindingType_Uniform; + bindGroupLayoutEntry.buffer.hasDynamicOffset = false; + bindGroupLayoutEntry.buffer.minBindingSize = 0; + return bindGroupLayoutEntry; +} + +WGPUBindGroupLayoutEntry WgBindGroup::makeBindGroupLayoutEntrySampler(uint32_t binding) { + WGPUBindGroupLayoutEntry bindGroupLayoutEntry{}; + bindGroupLayoutEntry.nextInChain = nullptr; + bindGroupLayoutEntry.binding = binding; + bindGroupLayoutEntry.visibility = WGPUShaderStage_Fragment; + bindGroupLayoutEntry.sampler.nextInChain = nullptr; + bindGroupLayoutEntry.sampler.type = WGPUSamplerBindingType_Filtering; + return bindGroupLayoutEntry; +} + +WGPUBindGroupLayoutEntry WgBindGroup::makeBindGroupLayoutEntryTextureView(uint32_t binding) { + WGPUBindGroupLayoutEntry bindGroupLayoutEntry{}; + bindGroupLayoutEntry.nextInChain = nullptr; + bindGroupLayoutEntry.binding = binding; + bindGroupLayoutEntry.visibility = WGPUShaderStage_Fragment; + bindGroupLayoutEntry.texture.nextInChain = nullptr; + bindGroupLayoutEntry.texture.sampleType = WGPUTextureSampleType_Float; + bindGroupLayoutEntry.texture.viewDimension = WGPUTextureViewDimension_2D; + bindGroupLayoutEntry.texture.multisampled = false; + return bindGroupLayoutEntry; +} + +WGPUBuffer WgBindGroup::createBuffer(WGPUDevice device, WGPUQueue queue, const void *data, size_t size) { + WGPUBufferDescriptor bufferDescriptor{}; + bufferDescriptor.nextInChain = nullptr; + bufferDescriptor.label = "The uniform buffer"; + bufferDescriptor.usage = WGPUBufferUsage_CopyDst | WGPUBufferUsage_Uniform; + bufferDescriptor.size = size; + bufferDescriptor.mappedAtCreation = false; + WGPUBuffer buffer = wgpuDeviceCreateBuffer(device, &bufferDescriptor); + assert(buffer); + wgpuQueueWriteBuffer(queue, buffer, 0, data, size); + return buffer; +} + +WGPUBindGroup WgBindGroup::createBindGroup(WGPUDevice device, WGPUBindGroupLayout layout, const WGPUBindGroupEntry* bindGroupEntries, uint32_t count) { + WGPUBindGroupDescriptor bindGroupDesc{}; + bindGroupDesc.nextInChain = nullptr; + bindGroupDesc.label = "The binding group sampler"; + bindGroupDesc.layout = layout; + bindGroupDesc.entryCount = count; + bindGroupDesc.entries = bindGroupEntries; + return wgpuDeviceCreateBindGroup(device, &bindGroupDesc); +} + +WGPUBindGroupLayout WgBindGroup::createBindGroupLayout(WGPUDevice device, const WGPUBindGroupLayoutEntry* bindGroupLayoutEntries, uint32_t count) { + WGPUBindGroupLayoutDescriptor bindGroupLayoutDesc{}; + bindGroupLayoutDesc.nextInChain = nullptr; + bindGroupLayoutDesc.label = "The bind group layout"; + bindGroupLayoutDesc.entryCount = count; + bindGroupLayoutDesc.entries = bindGroupLayoutEntries; // @binding + return wgpuDeviceCreateBindGroupLayout(device, &bindGroupLayoutDesc); +} + +void WgBindGroup::releaseBuffer(WGPUBuffer& buffer) { + if (buffer) { + wgpuBufferDestroy(buffer); + wgpuBufferRelease(buffer); + buffer = nullptr; + } +} + +void WgBindGroup::releaseBindGroup(WGPUBindGroup& bindGroup) { + if (bindGroup) wgpuBindGroupRelease(bindGroup); + bindGroup = nullptr; +} + +void WgBindGroup::releaseBindGroupLayout(WGPUBindGroupLayout& bindGroupLayout) { + if (bindGroupLayout) wgpuBindGroupLayoutRelease(bindGroupLayout); + bindGroupLayout = nullptr; +} + +//***************************************************************************** +// pipeline +//***************************************************************************** + +void WgPipeline::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) +{ + mShaderModule = createShaderModule(device, shaderSource, shaderLabel); + assert(mShaderModule); + + mPipelineLayout = createPipelineLayout(device, bindGroupLayouts, bindGroupsCount); + assert(mPipelineLayout); + + mRenderPipeline = createRenderPipeline(device, + vertexBufferLayouts, attribsCount, + stencilCompareFunction, stencilOperation, + mPipelineLayout, mShaderModule, pipelineLabel); + assert(mRenderPipeline); +} + +void WgPipeline::release() { + destroyRenderPipeline(mRenderPipeline); + destroyShaderModule(mShaderModule); + destroyPipelineLayout(mPipelineLayout); +} + +void WgPipeline::set(WGPURenderPassEncoder renderPassEncoder) { + wgpuRenderPassEncoderSetPipeline(renderPassEncoder, mRenderPipeline); +}; + +WGPUBlendState WgPipeline::makeBlendState() { + WGPUBlendState blendState{}; + blendState.color.operation = WGPUBlendOperation_Add; + blendState.color.srcFactor = WGPUBlendFactor_SrcAlpha; + blendState.color.dstFactor = WGPUBlendFactor_OneMinusSrcAlpha; + blendState.alpha.operation = WGPUBlendOperation_Add; + blendState.alpha.srcFactor = WGPUBlendFactor_Zero; + blendState.alpha.dstFactor = WGPUBlendFactor_One; + return blendState; +} + +WGPUColorTargetState WgPipeline::makeColorTargetState(const WGPUBlendState* blendState) { + WGPUColorTargetState colorTargetState{}; + colorTargetState.nextInChain = nullptr; + colorTargetState.format = WGPUTextureFormat_BGRA8Unorm; // (WGPUTextureFormat_BGRA8UnormSrgb) + colorTargetState.blend = blendState; + colorTargetState.writeMask = WGPUColorWriteMask_All; + return colorTargetState; +} + +WGPUVertexBufferLayout WgPipeline::makeVertexBufferLayout(const WGPUVertexAttribute* vertexAttributes, uint32_t count, uint64_t stride) { + WGPUVertexBufferLayout vertexBufferLayoutPos{}; + vertexBufferLayoutPos.arrayStride = stride; + vertexBufferLayoutPos.stepMode = WGPUVertexStepMode_Vertex; + vertexBufferLayoutPos.attributeCount = count; + vertexBufferLayoutPos.attributes = vertexAttributes; + return vertexBufferLayoutPos; +} + +WGPUVertexState WgPipeline::makeVertexState(WGPUShaderModule shaderModule, const WGPUVertexBufferLayout* buffers, uint32_t count) { + WGPUVertexState vertexState{}; + vertexState.nextInChain = nullptr; + vertexState.module = shaderModule; + vertexState.entryPoint = "vs_main"; + vertexState.constantCount = 0; + vertexState.constants = nullptr; + vertexState.bufferCount = count; + vertexState.buffers = buffers; + return vertexState; +} + +WGPUPrimitiveState WgPipeline::makePrimitiveState() { + WGPUPrimitiveState primitiveState{}; + primitiveState.nextInChain = nullptr; + primitiveState.topology = WGPUPrimitiveTopology_TriangleList; + primitiveState.stripIndexFormat = WGPUIndexFormat_Undefined; + primitiveState.frontFace = WGPUFrontFace_CCW; + primitiveState.cullMode = WGPUCullMode_None; + return primitiveState; +} + +WGPUDepthStencilState WgPipeline::makeDepthStencilState(WGPUCompareFunction compare, WGPUStencilOperation operation) { + WGPUDepthStencilState depthStencilState{}; + depthStencilState.nextInChain = nullptr; + depthStencilState.format = WGPUTextureFormat_Stencil8; + depthStencilState.depthWriteEnabled = false; + depthStencilState.depthCompare = WGPUCompareFunction_Always; + depthStencilState.stencilFront.compare = compare; + depthStencilState.stencilFront.failOp = operation; + depthStencilState.stencilFront.depthFailOp = operation; + depthStencilState.stencilFront.passOp = operation; + depthStencilState.stencilBack.compare = compare; + depthStencilState.stencilBack.failOp = operation; + depthStencilState.stencilBack.depthFailOp = operation; + depthStencilState.stencilBack.passOp = operation; + depthStencilState.stencilReadMask = 0xFFFFFFFF; + depthStencilState.stencilWriteMask = 0xFFFFFFFF; + depthStencilState.depthBias = 0; + depthStencilState.depthBiasSlopeScale = 0.0f; + depthStencilState.depthBiasClamp = 0.0f; + return depthStencilState; +} + +WGPUMultisampleState WgPipeline::makeMultisampleState() { + WGPUMultisampleState multisampleState{}; + multisampleState.nextInChain = nullptr; + multisampleState.count = 1; + multisampleState.mask = 0xFFFFFFFF; + multisampleState.alphaToCoverageEnabled = false; + return multisampleState; +} + +WGPUFragmentState WgPipeline::makeFragmentState(WGPUShaderModule shaderModule, WGPUColorTargetState* targets, uint32_t size) { + WGPUFragmentState fragmentState{}; + fragmentState.nextInChain = nullptr; + fragmentState.module = shaderModule; + fragmentState.entryPoint = "fs_main"; + fragmentState.constantCount = 0; + fragmentState.constants = nullptr; + fragmentState.targetCount = size; + fragmentState.targets = targets; + 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, + WGPUVertexBufferLayout vertexBufferLayouts[], uint32_t attribsCount, + WGPUCompareFunction stencilCompareFunction, WGPUStencilOperation stencilOperation, + WGPUPipelineLayout pipelineLayout, WGPUShaderModule shaderModule, + const char* pipelineName) { + WGPUBlendState blendState = makeBlendState(); + WGPUColorTargetState colorTargetStates[] = { + makeColorTargetState(&blendState) + }; + + WGPUVertexState vertexState = makeVertexState(shaderModule, vertexBufferLayouts, attribsCount); + WGPUPrimitiveState primitiveState = makePrimitiveState(); + WGPUDepthStencilState depthStencilState = makeDepthStencilState(stencilCompareFunction, stencilOperation); + WGPUMultisampleState multisampleState = makeMultisampleState(); + WGPUFragmentState fragmentState = makeFragmentState(shaderModule, colorTargetStates, 1); + + WGPURenderPipelineDescriptor renderPipelineDesc{}; + renderPipelineDesc.nextInChain = nullptr; + renderPipelineDesc.label = pipelineName; + renderPipelineDesc.layout = pipelineLayout; + renderPipelineDesc.vertex = vertexState; + renderPipelineDesc.primitive = primitiveState; + renderPipelineDesc.depthStencil = &depthStencilState; + renderPipelineDesc.multisample = multisampleState; + renderPipelineDesc.fragment = &fragmentState; + 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) { + if (renderPipeline) wgpuRenderPipelineRelease(renderPipeline); + renderPipeline = nullptr; +} \ No newline at end of file diff --git a/src/renderer/wg_engine/tvgWgCommon.h b/src/renderer/wg_engine/tvgWgCommon.h index bcc4a79b..b428ff5f 100644 --- a/src/renderer/wg_engine/tvgWgCommon.h +++ b/src/renderer/wg_engine/tvgWgCommon.h @@ -28,4 +28,63 @@ #include "tvgCommon.h" #include "tvgRender.h" +struct WgBindGroup { + WGPUBindGroup mBindGroup{}; + + void set(WGPURenderPassEncoder encoder, uint32_t groupIndex); + + static WGPUBindGroupEntry makeBindGroupEntryBuffer(uint32_t binding, WGPUBuffer buffer); + static WGPUBindGroupEntry makeBindGroupEntrySampler(uint32_t binding, WGPUSampler sampler); + static WGPUBindGroupEntry makeBindGroupEntryTextureView(uint32_t binding, WGPUTextureView textureView); + + static WGPUBindGroupLayoutEntry makeBindGroupLayoutEntryBuffer(uint32_t binding); + static WGPUBindGroupLayoutEntry makeBindGroupLayoutEntrySampler(uint32_t binding); + static WGPUBindGroupLayoutEntry makeBindGroupLayoutEntryTextureView(uint32_t binding); + + static WGPUBuffer createBuffer(WGPUDevice device, WGPUQueue queue, const void *data, size_t size); + static WGPUBindGroup createBindGroup(WGPUDevice device, WGPUBindGroupLayout layout, const WGPUBindGroupEntry* bindGroupEntries, uint32_t count); + static WGPUBindGroupLayout createBindGroupLayout(WGPUDevice device, const WGPUBindGroupLayoutEntry* bindGroupLayoutEntries, uint32_t count); + + static void releaseBuffer(WGPUBuffer& buffer); + static void releaseBindGroup(WGPUBindGroup& bindGroup); + static void releaseBindGroupLayout(WGPUBindGroupLayout& bindGroupLayout); +}; + +struct WgPipeline { +protected: + 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 set(WGPURenderPassEncoder renderPassEncoder); + + static WGPUBlendState makeBlendState(); + static WGPUColorTargetState makeColorTargetState(const WGPUBlendState* blendState); + static WGPUVertexBufferLayout makeVertexBufferLayout(const WGPUVertexAttribute* vertexAttributes, uint32_t count, uint64_t stride); + static WGPUVertexState makeVertexState(WGPUShaderModule shaderModule, const WGPUVertexBufferLayout* buffers, uint32_t count); + static WGPUPrimitiveState makePrimitiveState(); + static WGPUDepthStencilState makeDepthStencilState(WGPUCompareFunction compare, WGPUStencilOperation operation); + static 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); +}; + #endif // _TVG_WG_COMMON_H_ diff --git a/src/renderer/wg_engine/tvgWgPipelineBase.cpp b/src/renderer/wg_engine/tvgWgPipelineBase.cpp deleted file mode 100644 index befc12cb..00000000 --- a/src/renderer/wg_engine/tvgWgPipelineBase.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2023 the ThorVG project. All rights reserved. - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "tvgWgPipelineBase.h" - -/************************************************************************/ -// WgPipelineData -/************************************************************************/ - -void WgPipelineData::updateMatrix(const float* viewMatrix, const RenderTransform* transform) { - float modelMatrix[16]{}; - if (transform) { - modelMatrix[0] = transform->m.e11; - modelMatrix[1] = transform->m.e21; - modelMatrix[3] = transform->m.e31; - modelMatrix[4] = transform->m.e12; - modelMatrix[5] = transform->m.e22; - modelMatrix[7] = transform->m.e32; - modelMatrix[10] = 1.0f; - modelMatrix[12] = transform->m.e13; - modelMatrix[13] = transform->m.e23; - modelMatrix[15] = transform->m.e33; - } else { - modelMatrix[0] = 1.0f; - modelMatrix[5] = 1.0f; - modelMatrix[10] = 1.0f; - modelMatrix[15] = 1.0f; - } - // matrix multiply - for(auto i = 0; i < 4; ++i) { - for(auto j = 0; j < 4; ++j) { - float sum = 0.0; - for (auto k = 0; k < 4; ++k) - sum += viewMatrix[k*4+i] * modelMatrix[j*4+k]; - uMatrix.transform[j*4+i] = sum; - } - } -} - -/************************************************************************/ -// WgPipelineBindGroup -/************************************************************************/ - -void WgPipelineBindGroup::bind(WGPURenderPassEncoder renderPassEncoder, uint32_t groupIndex) { - wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, groupIndex, mBindGroup, 0, nullptr); -} - -/************************************************************************/ -// WgPipelinePipeline -/************************************************************************/ - -void WgPipelineBase::set(WGPURenderPassEncoder renderPassEncoder) { - wgpuRenderPassEncoderSetPipeline(renderPassEncoder, mRenderPipeline); -} diff --git a/src/renderer/wg_engine/tvgWgPipelineBase.h b/src/renderer/wg_engine/tvgWgPipelineBase.h deleted file mode 100644 index 4078bbb4..00000000 --- a/src/renderer/wg_engine/tvgWgPipelineBase.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2023 the ThorVG project. All rights reserved. - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef _TVG_WG_PIPELINE_BASE_H_ -#define _TVG_WG_PIPELINE_BASE_H_ - -#include "tvgWgCommon.h" - -struct WgPipelineMatrix { - float transform[4*4]{}; -}; - -struct WgPipelineData { - WgPipelineMatrix uMatrix{}; // @binding(0) - void updateMatrix(const float* viewMatrix, const RenderTransform* transform); -}; - -struct WgPipelineBindGroup { - WGPUBuffer uBufferMatrix{}; - WGPUBindGroup mBindGroup{}; - void bind(WGPURenderPassEncoder renderPassEncoder, uint32_t groupIndex); -}; - -class WgPipelineBase { -public: - WGPUBindGroupLayout mBindGroupLayout{}; // @group(0) - WGPUPipelineLayout mPipelineLayout{}; - WGPUShaderModule mShaderModule{}; - WGPURenderPipeline mRenderPipeline{}; -public: - virtual void initialize(WGPUDevice device) = 0; - virtual void release() = 0; - - void set(WGPURenderPassEncoder renderPassEncoder); -}; - -#endif // _TVG_WG_PIPELINE_BASE_H_ diff --git a/src/renderer/wg_engine/tvgWgPipelineEmpty.cpp b/src/renderer/wg_engine/tvgWgPipelineEmpty.cpp deleted file mode 100644 index 61d07f7c..00000000 --- a/src/renderer/wg_engine/tvgWgPipelineEmpty.cpp +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright (c) 2023 the ThorVG project. All rights reserved. - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "tvgWgPipelineEmpty.h" -#include "tvgWgShaderSrc.h" - -//************************************************************************ -// WgPipelineBindGroupEmpty -//************************************************************************ - -void WgPipelineBindGroupEmpty::initialize(WGPUDevice device, WgPipelineEmpty& pipelinePipelineEmpty) { - // buffer uniform uMatrix - WGPUBufferDescriptor bufferUniformDesc_uMatrix{}; - bufferUniformDesc_uMatrix.nextInChain = nullptr; - bufferUniformDesc_uMatrix.label = "Buffer uniform pipeline empty uMatrix"; - bufferUniformDesc_uMatrix.usage = WGPUBufferUsage_CopyDst | WGPUBufferUsage_Uniform; - bufferUniformDesc_uMatrix.size = sizeof(WgPipelineMatrix); - bufferUniformDesc_uMatrix.mappedAtCreation = false; - uBufferMatrix = wgpuDeviceCreateBuffer(device, &bufferUniformDesc_uMatrix); - assert(uBufferMatrix); - - // bind group entry @binding(0) uMatrix - WGPUBindGroupEntry bindGroupEntry_uMatrix{}; - bindGroupEntry_uMatrix.nextInChain = nullptr; - bindGroupEntry_uMatrix.binding = 0; - bindGroupEntry_uMatrix.buffer = uBufferMatrix; - bindGroupEntry_uMatrix.offset = 0; - bindGroupEntry_uMatrix.size = sizeof(WgPipelineMatrix); - bindGroupEntry_uMatrix.sampler = nullptr; - bindGroupEntry_uMatrix.textureView = nullptr; - // bind group entries - WGPUBindGroupEntry bindGroupEntries[] { - bindGroupEntry_uMatrix // @binding(0) uMatrix - }; - // bind group descriptor - WGPUBindGroupDescriptor bindGroupDescPipeline{}; - bindGroupDescPipeline.nextInChain = nullptr; - bindGroupDescPipeline.label = "The binding group pipeline empty"; - bindGroupDescPipeline.layout = pipelinePipelineEmpty.mBindGroupLayout; - bindGroupDescPipeline.entryCount = 1; - bindGroupDescPipeline.entries = bindGroupEntries; - mBindGroup = wgpuDeviceCreateBindGroup(device, &bindGroupDescPipeline); - assert(mBindGroup); -} - -void WgPipelineBindGroupEmpty::release() { - if (uBufferMatrix) { - wgpuBufferDestroy(uBufferMatrix); - wgpuBufferRelease(uBufferMatrix); - uBufferMatrix = nullptr; - } - if (mBindGroup) { - wgpuBindGroupRelease(mBindGroup); - mBindGroup = nullptr; - } -} - -void WgPipelineBindGroupEmpty::update(WGPUQueue queue, WgPipelineDataEmpty& pipelineDataEmpty) { - wgpuQueueWriteBuffer(queue, uBufferMatrix, 0, &pipelineDataEmpty.uMatrix, sizeof(pipelineDataEmpty.uMatrix)); -} - -//************************************************************************ -// WgPipelineEmpty -//************************************************************************ - -void WgPipelineEmpty::initialize(WGPUDevice device) { - // bind group layout group 0 - // bind group layout descriptor @group(0) @binding(0) uMatrix - WGPUBindGroupLayoutEntry bindGroupLayoutEntry_uMatrix{}; - bindGroupLayoutEntry_uMatrix.nextInChain = nullptr; - bindGroupLayoutEntry_uMatrix.binding = 0; - bindGroupLayoutEntry_uMatrix.visibility = WGPUShaderStage_Vertex | WGPUShaderStage_Fragment; - bindGroupLayoutEntry_uMatrix.buffer.nextInChain = nullptr; - bindGroupLayoutEntry_uMatrix.buffer.type = WGPUBufferBindingType_Uniform; - bindGroupLayoutEntry_uMatrix.buffer.hasDynamicOffset = false; - bindGroupLayoutEntry_uMatrix.buffer.minBindingSize = 0; - // bind group layout entries @group(0) - WGPUBindGroupLayoutEntry bindGroupLayoutEntries[] { - bindGroupLayoutEntry_uMatrix - }; - // bind group layout descriptor scene @group(0) - WGPUBindGroupLayoutDescriptor bindGroupLayoutDesc{}; - bindGroupLayoutDesc.nextInChain = nullptr; - bindGroupLayoutDesc.label = "Bind group layout pipeline empty"; - bindGroupLayoutDesc.entryCount = 1; - bindGroupLayoutDesc.entries = bindGroupLayoutEntries; // @binding - mBindGroupLayout = wgpuDeviceCreateBindGroupLayout(device, &bindGroupLayoutDesc); - assert(mBindGroupLayout); - - // pipeline layout - - // bind group layout descriptors - WGPUBindGroupLayout mBindGroupLayouts[] { - mBindGroupLayout - }; - // pipeline layout descriptor - WGPUPipelineLayoutDescriptor pipelineLayoutDesc{}; - pipelineLayoutDesc.nextInChain = nullptr; - pipelineLayoutDesc.label = "Pipeline pipeline layout empty"; - pipelineLayoutDesc.bindGroupLayoutCount = 1; - pipelineLayoutDesc.bindGroupLayouts = mBindGroupLayouts; - mPipelineLayout = wgpuDeviceCreatePipelineLayout(device, &pipelineLayoutDesc); - assert(mPipelineLayout); - - // depth stencil state - WGPUDepthStencilState depthStencilState{}; - depthStencilState.nextInChain = nullptr; - depthStencilState.format = WGPUTextureFormat_Stencil8; - depthStencilState.depthWriteEnabled = false; - depthStencilState.depthCompare = WGPUCompareFunction_Always; - // depthStencilState.stencilFront - depthStencilState.stencilFront.compare = WGPUCompareFunction_Always; - depthStencilState.stencilFront.failOp = WGPUStencilOperation_Invert; - depthStencilState.stencilFront.depthFailOp = WGPUStencilOperation_Invert; - depthStencilState.stencilFront.passOp = WGPUStencilOperation_Invert; - // depthStencilState.stencilBack - depthStencilState.stencilBack.compare = WGPUCompareFunction_Always; - depthStencilState.stencilBack.failOp = WGPUStencilOperation_Invert; - depthStencilState.stencilBack.depthFailOp = WGPUStencilOperation_Invert; - depthStencilState.stencilBack.passOp = WGPUStencilOperation_Invert; - // stencil mask - depthStencilState.stencilReadMask = 0xFFFFFFFF; - depthStencilState.stencilWriteMask = 0xFFFFFFFF; - // depth bias - depthStencilState.depthBias = 0; - depthStencilState.depthBiasSlopeScale = 0.0f; - depthStencilState.depthBiasClamp = 0.0f; - - // shader module wgsl descriptor - WGPUShaderModuleWGSLDescriptor shaderModuleWGSLDesc{}; - shaderModuleWGSLDesc.chain.next = nullptr; - shaderModuleWGSLDesc.chain.sType = WGPUSType_ShaderModuleWGSLDescriptor; - shaderModuleWGSLDesc.code = cShaderSource_PipelineEmpty; - // shader module descriptor - WGPUShaderModuleDescriptor shaderModuleDesc{}; - shaderModuleDesc.nextInChain = &shaderModuleWGSLDesc.chain; - shaderModuleDesc.label = "The shader module pipeline empty"; - shaderModuleDesc.hintCount = 0; - shaderModuleDesc.hints = nullptr; - mShaderModule = wgpuDeviceCreateShaderModule(device, &shaderModuleDesc); - assert(mShaderModule); - - // vertex attributes - WGPUVertexAttribute vertexAttributes[] = { - { WGPUVertexFormat_Float32x2, sizeof(float) * 0, 0 }, // position - }; - // vertex buffer layout - WGPUVertexBufferLayout vertexBufferLayout{}; - vertexBufferLayout.arrayStride = sizeof(float) * 2; // position - vertexBufferLayout.stepMode = WGPUVertexStepMode_Vertex; - vertexBufferLayout.attributeCount = 1; // position - vertexBufferLayout.attributes = vertexAttributes; - - // blend state - WGPUBlendState blendState{}; - // blendState.color - blendState.color.operation = WGPUBlendOperation_Add; - blendState.color.srcFactor = WGPUBlendFactor_SrcAlpha; - blendState.color.dstFactor = WGPUBlendFactor_OneMinusSrcAlpha; - // blendState.alpha - blendState.alpha.operation = WGPUBlendOperation_Add; - blendState.alpha.srcFactor = WGPUBlendFactor_Zero; - blendState.alpha.dstFactor = WGPUBlendFactor_One; - - // color target state (WGPUTextureFormat_BGRA8UnormSrgb) - WGPUColorTargetState colorTargetState0{}; - colorTargetState0.nextInChain = nullptr; - colorTargetState0.format = WGPUTextureFormat_BGRA8Unorm; - //colorTargetState0.format = WGPUTextureFormat_BGRA8UnormSrgb; - colorTargetState0.blend = &blendState; - colorTargetState0.writeMask = WGPUColorWriteMask_All; - // color target states - WGPUColorTargetState colorTargetStates[] = { - colorTargetState0 - }; - // fragmanet state - WGPUFragmentState fragmentState{}; - fragmentState.nextInChain = nullptr; - fragmentState.module = mShaderModule; - fragmentState.entryPoint = "fs_main"; - fragmentState.constantCount = 0; - fragmentState.constants = nullptr; - fragmentState.targetCount = 1; - fragmentState.targets = colorTargetStates; // render target index - - // render pipeline descriptor - WGPURenderPipelineDescriptor renderPipelineDesc{}; - renderPipelineDesc.nextInChain = nullptr; - renderPipelineDesc.label = "Render pipeline pipeline empty"; - // renderPipelineDesc.layout - renderPipelineDesc.layout = mPipelineLayout; - // renderPipelineDesc.vertex - renderPipelineDesc.vertex.nextInChain = nullptr; - renderPipelineDesc.vertex.module = mShaderModule; - renderPipelineDesc.vertex.entryPoint = "vs_main"; - renderPipelineDesc.vertex.constantCount = 0; - renderPipelineDesc.vertex.constants = nullptr; - renderPipelineDesc.vertex.bufferCount = 1; - renderPipelineDesc.vertex.buffers = &vertexBufferLayout; // buffer index - // renderPipelineDesc.primitive - renderPipelineDesc.primitive.nextInChain = nullptr; - renderPipelineDesc.primitive.topology = WGPUPrimitiveTopology_TriangleList; - renderPipelineDesc.primitive.stripIndexFormat = WGPUIndexFormat_Undefined; - renderPipelineDesc.primitive.frontFace = WGPUFrontFace_CCW; - renderPipelineDesc.primitive.cullMode = WGPUCullMode_None; - // renderPipelineDesc.depthStencil - renderPipelineDesc.depthStencil = &depthStencilState; - // renderPipelineDesc.multisample - renderPipelineDesc.multisample.nextInChain = nullptr; - renderPipelineDesc.multisample.count = 1; - renderPipelineDesc.multisample.mask = 0xFFFFFFFF; - renderPipelineDesc.multisample.alphaToCoverageEnabled = false; - // renderPipelineDesc.fragment - renderPipelineDesc.fragment = &fragmentState; - mRenderPipeline = wgpuDeviceCreateRenderPipeline(device, &renderPipelineDesc); - assert(mRenderPipeline); -} - -void WgPipelineEmpty::release() { - wgpuRenderPipelineRelease(mRenderPipeline); - wgpuShaderModuleRelease(mShaderModule); - wgpuPipelineLayoutRelease(mPipelineLayout); - wgpuBindGroupLayoutRelease(mBindGroupLayout); -} diff --git a/src/renderer/wg_engine/tvgWgPipelineEmpty.h b/src/renderer/wg_engine/tvgWgPipelineEmpty.h deleted file mode 100644 index 3f90f085..00000000 --- a/src/renderer/wg_engine/tvgWgPipelineEmpty.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2023 the ThorVG project. All rights reserved. - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef _TVG_WG_PIPELINE_EMPTY_H_ -#define _TVG_WG_PIPELINE_EMPTY_H_ - -#include "tvgWgPipelineBase.h" - -class WgPipelineEmpty; - -struct WgPipelineDataEmpty: WgPipelineData {}; - -class WgPipelineBindGroupEmpty: public WgPipelineBindGroup { -public: - void initialize(WGPUDevice device, WgPipelineEmpty& pipelinePipelineEmpty); - void release(); - - void update(WGPUQueue mQueue, WgPipelineDataEmpty& pipelineDataSolid); -}; - -/* -* This pipeline is used for drawing filled, concave polygons using the stencil buffer -* This can be done using the stencil buffer, with a two-pass algorithm. -* -* First, clear the stencil buffer and disable writing into the color buffer. Next, draw each of the triangles in turn, using the INVERT function in the stencil buffer. (For best performance, use triangle fans.) -* This flips the value between zero and a nonzero value every time a triangle is drawn that covers a pixel. -* -* After all the triangles are drawn, if a pixel is covered an even number of times, the value in the stencil buffers is zero; otherwise, it's nonzero. -* Finally, draw a large polygon over the whole region (or redraw the triangles), but allow drawing only where the stencil buffer is nonzero. -* -* There is a link to the solution, how to draw filled, concave polygons using the stencil buffer: -* https://www.glprogramming.com/red/chapter14.html#name13 -* -* The benefit of this solution is to don`t use complex tesselation to fill self intersected or concave poligons. -* -* This pipeline implements the first pass of this solution. It`s did not write anything into color buffer but fills the stencil buffer using invert strategy -*/ -class WgPipelineEmpty: public WgPipelineBase { -public: - void initialize(WGPUDevice device) override; - void release() override; -}; - -#endif // _TVG_WG_PIPELINE_EMPTY_H_ diff --git a/src/renderer/wg_engine/tvgWgPipelineImage.cpp b/src/renderer/wg_engine/tvgWgPipelineImage.cpp deleted file mode 100644 index 8af7e003..00000000 --- a/src/renderer/wg_engine/tvgWgPipelineImage.cpp +++ /dev/null @@ -1,415 +0,0 @@ -/* - * Copyright (c) 2023 the ThorVG project. All rights reserved. - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "tvgWgPipelineImage.h" -#include "tvgWgShaderSrc.h" - -//************************************************************************ -// WgPipelineDataImage -//************************************************************************ - -void WgPipelineDataImage::updateFormat(const ColorSpace format) { - uColorInfo.format = (uint32_t)format; -} - -void WgPipelineDataImage::updateOpacity(const uint8_t opacity) { - uColorInfo.opacity = opacity / 255.0f; // alpha -} - -//************************************************************************ -// WgPipelineBindGroupImage -//************************************************************************ - -void WgPipelineBindGroupImage::initialize(WGPUDevice device, WgPipelineImage& pipelineImage, Surface* surface) { - // buffer uniform uMatrix - WGPUBufferDescriptor bufferUniformDesc_uMatrix{}; - bufferUniformDesc_uMatrix.nextInChain = nullptr; - bufferUniformDesc_uMatrix.label = "Buffer uniform pipeline image uMatrix"; - bufferUniformDesc_uMatrix.usage = WGPUBufferUsage_CopyDst | WGPUBufferUsage_Uniform; - bufferUniformDesc_uMatrix.size = sizeof(WgPipelineMatrix); - bufferUniformDesc_uMatrix.mappedAtCreation = false; - uBufferMatrix = wgpuDeviceCreateBuffer(device, &bufferUniformDesc_uMatrix); - assert(uBufferMatrix); - // buffer uniform uColorInfo - WGPUBufferDescriptor bufferUniformDesc_uColorInfo{}; - bufferUniformDesc_uColorInfo.nextInChain = nullptr; - bufferUniformDesc_uColorInfo.label = "Buffer uniform pipeline image uColorInfo"; - bufferUniformDesc_uColorInfo.usage = WGPUBufferUsage_CopyDst | WGPUBufferUsage_Uniform; - bufferUniformDesc_uColorInfo.size = sizeof(WgPipelineImageColorInfo); - bufferUniformDesc_uColorInfo.mappedAtCreation = false; - uBufferColorInfo = wgpuDeviceCreateBuffer(device, &bufferUniformDesc_uColorInfo); - assert(uBufferColorInfo); - // sampler uniform uSamplerBase - WGPUSamplerDescriptor samplerDesc_uSamplerBase{}; - samplerDesc_uSamplerBase.nextInChain = nullptr; - samplerDesc_uSamplerBase.label = "Sampler uniform pipeline image uSamplerBase"; - samplerDesc_uSamplerBase.addressModeU = WGPUAddressMode_ClampToEdge; - samplerDesc_uSamplerBase.addressModeV = WGPUAddressMode_ClampToEdge; - samplerDesc_uSamplerBase.addressModeW = WGPUAddressMode_ClampToEdge; - samplerDesc_uSamplerBase.magFilter = WGPUFilterMode_Nearest; - samplerDesc_uSamplerBase.minFilter = WGPUFilterMode_Nearest; - samplerDesc_uSamplerBase.mipmapFilter = WGPUMipmapFilterMode_Nearest; - samplerDesc_uSamplerBase.lodMinClamp = 0.0f; - samplerDesc_uSamplerBase.lodMaxClamp = 32.0f; - samplerDesc_uSamplerBase.compare = WGPUCompareFunction_Undefined; - samplerDesc_uSamplerBase.maxAnisotropy = 1; - uSamplerBase = wgpuDeviceCreateSampler(device, &samplerDesc_uSamplerBase); - assert(uSamplerBase); - // webgpu texture data holder - WGPUTextureDescriptor textureDesc{}; - textureDesc.nextInChain = nullptr; - textureDesc.label = "Texture base pipeline image"; - textureDesc.usage = WGPUTextureUsage_TextureBinding | WGPUTextureUsage_CopyDst; - textureDesc.dimension = WGPUTextureDimension_2D; - textureDesc.size = { surface->w, surface->h, 1 }; - textureDesc.format = WGPUTextureFormat_RGBA8Unorm; - textureDesc.mipLevelCount = 1; - textureDesc.sampleCount = 1; - textureDesc.viewFormatCount = 0; - textureDesc.viewFormats = nullptr; - mTextureBase = wgpuDeviceCreateTexture(device, &textureDesc); - assert(mTextureBase); - // texture view uniform uTextureViewBase - WGPUTextureViewDescriptor textureViewDesc{}; - textureViewDesc.nextInChain = nullptr; - textureViewDesc.label = "The depth-stencil texture view"; - textureViewDesc.format = WGPUTextureFormat_RGBA8Unorm; - textureViewDesc.dimension = WGPUTextureViewDimension_2D; - textureViewDesc.baseMipLevel = 0; - textureViewDesc.mipLevelCount = 1; - textureViewDesc.baseArrayLayer = 0; - textureViewDesc.arrayLayerCount = 1; - textureViewDesc.aspect = WGPUTextureAspect_All; - uTextureViewBase = wgpuTextureCreateView(mTextureBase, &textureViewDesc); - assert(uTextureViewBase); - - // bind group entry @binding(0) uMatrix - WGPUBindGroupEntry bindGroupEntry_uMatrix{}; - bindGroupEntry_uMatrix.nextInChain = nullptr; - bindGroupEntry_uMatrix.binding = 0; - bindGroupEntry_uMatrix.buffer = uBufferMatrix; - bindGroupEntry_uMatrix.offset = 0; - bindGroupEntry_uMatrix.size = sizeof(WgPipelineMatrix); - bindGroupEntry_uMatrix.sampler = nullptr; - bindGroupEntry_uMatrix.textureView = nullptr; - // bind group entry @binding(1) uColorInfo - WGPUBindGroupEntry bindGroupEntry_uColorInfo{}; - bindGroupEntry_uColorInfo.nextInChain = nullptr; - bindGroupEntry_uColorInfo.binding = 1; - bindGroupEntry_uColorInfo.buffer = uBufferColorInfo; - bindGroupEntry_uColorInfo.offset = 0; - bindGroupEntry_uColorInfo.size = sizeof(WgPipelineImageColorInfo); - bindGroupEntry_uColorInfo.sampler = nullptr; - bindGroupEntry_uColorInfo.textureView = nullptr; - // bind group entry @binding(2) uSamplerBase - WGPUBindGroupEntry bindGroupEntry_uSamplerBase{}; - bindGroupEntry_uSamplerBase.nextInChain = nullptr; - bindGroupEntry_uSamplerBase.binding = 2; - bindGroupEntry_uSamplerBase.buffer = nullptr; - bindGroupEntry_uSamplerBase.offset = 0; - bindGroupEntry_uSamplerBase.size = 0; - bindGroupEntry_uSamplerBase.sampler = uSamplerBase; - bindGroupEntry_uSamplerBase.textureView = nullptr; - // bind group entry @binding(3) uTextureViewBase - WGPUBindGroupEntry bindGroupEntry_uTextureViewBase{}; - bindGroupEntry_uTextureViewBase.nextInChain = nullptr; - bindGroupEntry_uTextureViewBase.binding = 3; - bindGroupEntry_uTextureViewBase.buffer = nullptr; - bindGroupEntry_uTextureViewBase.offset = 0; - bindGroupEntry_uTextureViewBase.size = 0; - bindGroupEntry_uTextureViewBase.sampler = nullptr; - bindGroupEntry_uTextureViewBase.textureView = uTextureViewBase; - // bind group entries - WGPUBindGroupEntry bindGroupEntries[] { - bindGroupEntry_uMatrix, // @binding(0) uMatrix - bindGroupEntry_uColorInfo, // @binding(1) uColorInfo - bindGroupEntry_uSamplerBase, // @binding(2) uSamplerBase - bindGroupEntry_uTextureViewBase // @binding(3) uTextureViewBase - }; - // bind group descriptor - WGPUBindGroupDescriptor bindGroupDescPipeline{}; - bindGroupDescPipeline.nextInChain = nullptr; - bindGroupDescPipeline.label = "The binding group pipeline image"; - bindGroupDescPipeline.layout = pipelineImage.mBindGroupLayout; - bindGroupDescPipeline.entryCount = 4; - bindGroupDescPipeline.entries = bindGroupEntries; - mBindGroup = wgpuDeviceCreateBindGroup(device, &bindGroupDescPipeline); - assert(mBindGroup); -} - -void WgPipelineBindGroupImage::release() { - if (uTextureViewBase) { - wgpuTextureViewRelease(uTextureViewBase); - uTextureViewBase = nullptr; - } - if (mTextureBase) { - wgpuTextureDestroy(mTextureBase); - wgpuTextureRelease(mTextureBase); - mTextureBase = nullptr; - } - if (uSamplerBase) { - wgpuSamplerRelease(uSamplerBase); - uSamplerBase = nullptr; - } - if (uBufferColorInfo) { - wgpuBufferDestroy(uBufferColorInfo); - wgpuBufferRelease(uBufferColorInfo); - uBufferColorInfo = nullptr; - } - if (uBufferMatrix) { - wgpuBufferDestroy(uBufferMatrix); - wgpuBufferRelease(uBufferMatrix); - uBufferMatrix = nullptr; - } - if (mBindGroup) { - wgpuBindGroupRelease(mBindGroup); - mBindGroup = nullptr; - } -} - -void WgPipelineBindGroupImage::update(WGPUQueue queue, WgPipelineDataImage& pipelineDataImage, Surface* surface) { - wgpuQueueWriteBuffer(queue, uBufferMatrix, 0, &pipelineDataImage.uMatrix, sizeof(pipelineDataImage.uMatrix)); - wgpuQueueWriteBuffer(queue, uBufferColorInfo, 0, &pipelineDataImage.uColorInfo, sizeof(pipelineDataImage.uColorInfo)); - WGPUImageCopyTexture imageCopyTexture{}; - imageCopyTexture.nextInChain = nullptr; - imageCopyTexture.texture = mTextureBase; - imageCopyTexture.mipLevel = 0; - imageCopyTexture.origin = { 0, 0, 0 }; - imageCopyTexture.aspect = WGPUTextureAspect_All; - WGPUTextureDataLayout textureDataLayout{}; - textureDataLayout.nextInChain = nullptr; - textureDataLayout.offset = 0; - textureDataLayout.bytesPerRow = 4 * surface->w; - textureDataLayout.rowsPerImage = surface->h; - WGPUExtent3D writeSize{}; - writeSize.width = surface->w; - writeSize.height = surface->h; - writeSize.depthOrArrayLayers = 1; - wgpuQueueWriteTexture(queue, &imageCopyTexture, surface->data, 4 * surface->w * surface->h, &textureDataLayout, &writeSize); -} - -//************************************************************************ -// WgPipelineImage -//************************************************************************ - -void WgPipelineImage::initialize(WGPUDevice device) { - // bind group layout group 0 - // bind group layout descriptor @group(0) @binding(0) uMatrix - WGPUBindGroupLayoutEntry bindGroupLayoutEntry_uMatrix{}; - bindGroupLayoutEntry_uMatrix.nextInChain = nullptr; - bindGroupLayoutEntry_uMatrix.binding = 0; - bindGroupLayoutEntry_uMatrix.visibility = WGPUShaderStage_Vertex | WGPUShaderStage_Fragment; - bindGroupLayoutEntry_uMatrix.buffer.nextInChain = nullptr; - bindGroupLayoutEntry_uMatrix.buffer.type = WGPUBufferBindingType_Uniform; - bindGroupLayoutEntry_uMatrix.buffer.hasDynamicOffset = false; - bindGroupLayoutEntry_uMatrix.buffer.minBindingSize = 0; - // bind group layout descriptor @group(0) @binding(1) uColorInfo - WGPUBindGroupLayoutEntry bindGroupLayoutEntry_uColorInfo{}; - bindGroupLayoutEntry_uColorInfo.nextInChain = nullptr; - bindGroupLayoutEntry_uColorInfo.binding = 1; - bindGroupLayoutEntry_uColorInfo.visibility = WGPUShaderStage_Vertex | WGPUShaderStage_Fragment; - bindGroupLayoutEntry_uColorInfo.buffer.nextInChain = nullptr; - bindGroupLayoutEntry_uColorInfo.buffer.type = WGPUBufferBindingType_Uniform; - bindGroupLayoutEntry_uColorInfo.buffer.hasDynamicOffset = false; - bindGroupLayoutEntry_uColorInfo.buffer.minBindingSize = 0; - // bind group layout descriptor @group(0) @binding(2) uSamplerBase - WGPUBindGroupLayoutEntry bindGroupLayoutEntry_uSamplerBase{}; - bindGroupLayoutEntry_uSamplerBase.nextInChain = nullptr; - bindGroupLayoutEntry_uSamplerBase.binding = 2; - bindGroupLayoutEntry_uSamplerBase.visibility = WGPUShaderStage_Fragment; - bindGroupLayoutEntry_uSamplerBase.sampler.nextInChain = nullptr; - bindGroupLayoutEntry_uSamplerBase.sampler.type = WGPUSamplerBindingType_Filtering; - // bind group layout descriptor @group(0) @binding(3) uTextureViewBase - WGPUBindGroupLayoutEntry bindGroupLayoutEntry_uTextureViewBase{}; - bindGroupLayoutEntry_uTextureViewBase.nextInChain = nullptr; - bindGroupLayoutEntry_uTextureViewBase.binding = 3; - bindGroupLayoutEntry_uTextureViewBase.visibility = WGPUShaderStage_Fragment; - bindGroupLayoutEntry_uTextureViewBase.texture.nextInChain = nullptr; - bindGroupLayoutEntry_uTextureViewBase.texture.sampleType = WGPUTextureSampleType_Float; - bindGroupLayoutEntry_uTextureViewBase.texture.viewDimension = WGPUTextureViewDimension_2D; - bindGroupLayoutEntry_uTextureViewBase.texture.multisampled = false; - // bind group layout entries @group(0) - WGPUBindGroupLayoutEntry bindGroupLayoutEntries[] { - bindGroupLayoutEntry_uMatrix, - bindGroupLayoutEntry_uColorInfo, - bindGroupLayoutEntry_uSamplerBase, - bindGroupLayoutEntry_uTextureViewBase - }; - // bind group layout descriptor scene @group(0) - WGPUBindGroupLayoutDescriptor bindGroupLayoutDesc{}; - bindGroupLayoutDesc.nextInChain = nullptr; - bindGroupLayoutDesc.label = "Bind group layout pipeline image"; - bindGroupLayoutDesc.entryCount = 4; - bindGroupLayoutDesc.entries = bindGroupLayoutEntries; // @binding - mBindGroupLayout = wgpuDeviceCreateBindGroupLayout(device, &bindGroupLayoutDesc); - assert(mBindGroupLayout); - - // pipeline layout - - // bind group layout descriptors - WGPUBindGroupLayout mBindGroupLayouts[] { - mBindGroupLayout - }; - // pipeline layout descriptor - WGPUPipelineLayoutDescriptor pipelineLayoutDesc{}; - pipelineLayoutDesc.nextInChain = nullptr; - pipelineLayoutDesc.label = "Pipeline pipeline layout image"; - pipelineLayoutDesc.bindGroupLayoutCount = 1; - pipelineLayoutDesc.bindGroupLayouts = mBindGroupLayouts; - mPipelineLayout = wgpuDeviceCreatePipelineLayout(device, &pipelineLayoutDesc); - assert(mPipelineLayout); - - // depth stencil state - WGPUDepthStencilState depthStencilState{}; - depthStencilState.nextInChain = nullptr; - depthStencilState.format = WGPUTextureFormat_Stencil8; - depthStencilState.depthWriteEnabled = false; - depthStencilState.depthCompare = WGPUCompareFunction_Always; - // depthStencilState.stencilFront - depthStencilState.stencilFront.compare = WGPUCompareFunction_Always; - depthStencilState.stencilFront.failOp = WGPUStencilOperation_Zero; - depthStencilState.stencilFront.depthFailOp = WGPUStencilOperation_Zero; - depthStencilState.stencilFront.passOp = WGPUStencilOperation_Zero; - // depthStencilState.stencilBack - depthStencilState.stencilBack.compare = WGPUCompareFunction_Always; - depthStencilState.stencilBack.failOp = WGPUStencilOperation_Zero; - depthStencilState.stencilBack.depthFailOp = WGPUStencilOperation_Zero; - depthStencilState.stencilBack.passOp = WGPUStencilOperation_Zero; - // stencil mask - depthStencilState.stencilReadMask = 0xFFFFFFFF; - depthStencilState.stencilWriteMask = 0xFFFFFFFF; - // depth bias - depthStencilState.depthBias = 0; - depthStencilState.depthBiasSlopeScale = 0.0f; - depthStencilState.depthBiasClamp = 0.0f; - - // shader module wgsl descriptor - WGPUShaderModuleWGSLDescriptor shaderModuleWGSLDesc{}; - shaderModuleWGSLDesc.chain.next = nullptr; - shaderModuleWGSLDesc.chain.sType = WGPUSType_ShaderModuleWGSLDescriptor; - shaderModuleWGSLDesc.code = cShaderSource_PipelineImage; - // shader module descriptor - WGPUShaderModuleDescriptor shaderModuleDesc{}; - shaderModuleDesc.nextInChain = &shaderModuleWGSLDesc.chain; - shaderModuleDesc.label = "The shader module pipeline image"; - shaderModuleDesc.hintCount = 0; - shaderModuleDesc.hints = nullptr; - mShaderModule = wgpuDeviceCreateShaderModule(device, &shaderModuleDesc); - assert(mShaderModule); - - // vertex attributes - WGPUVertexAttribute vertexAttributesPos[] = { - { WGPUVertexFormat_Float32x2, sizeof(float) * 0, 0 } // position - }; - // vertex buffer layout position - WGPUVertexBufferLayout vertexBufferLayoutPos{}; - vertexBufferLayoutPos.arrayStride = sizeof(float) * 2; // position - vertexBufferLayoutPos.stepMode = WGPUVertexStepMode_Vertex; - vertexBufferLayoutPos.attributeCount = 1; // position - vertexBufferLayoutPos.attributes = vertexAttributesPos; - // vertex attributes - WGPUVertexAttribute vertexAttributesTex[] = { - { WGPUVertexFormat_Float32x2, sizeof(float) * 0, 1 } // tex coords - }; - // vertex buffer layout tex coords - WGPUVertexBufferLayout vertexBufferLayoutTex{}; - vertexBufferLayoutTex.arrayStride = sizeof(float) * 2; // tex coords - vertexBufferLayoutTex.stepMode = WGPUVertexStepMode_Vertex; - vertexBufferLayoutTex.attributeCount = 1; // tex coords - vertexBufferLayoutTex.attributes = vertexAttributesTex; - // vertex attributes - WGPUVertexBufferLayout vertexBufferLayouts[] = { - vertexBufferLayoutPos, - vertexBufferLayoutTex - }; - - // blend state - WGPUBlendState blendState{}; - // blendState.color - blendState.color.operation = WGPUBlendOperation_Add; - blendState.color.srcFactor = WGPUBlendFactor_SrcAlpha; - blendState.color.dstFactor = WGPUBlendFactor_OneMinusSrcAlpha; - // blendState.alpha - blendState.alpha.operation = WGPUBlendOperation_Add; - blendState.alpha.srcFactor = WGPUBlendFactor_Zero; - blendState.alpha.dstFactor = WGPUBlendFactor_One; - - // color target state (WGPUTextureFormat_BGRA8UnormSrgb) - WGPUColorTargetState colorTargetState0{}; - colorTargetState0.nextInChain = nullptr; - colorTargetState0.format = WGPUTextureFormat_BGRA8Unorm; - //colorTargetState0.format = WGPUTextureFormat_BGRA8UnormSrgb; - colorTargetState0.blend = &blendState; - colorTargetState0.writeMask = WGPUColorWriteMask_All; - // color target states - WGPUColorTargetState colorTargetStates[] = { - colorTargetState0 - }; - // fragmanet state - WGPUFragmentState fragmentState{}; - fragmentState.nextInChain = nullptr; - fragmentState.module = mShaderModule; - fragmentState.entryPoint = "fs_main"; - fragmentState.constantCount = 0; - fragmentState.constants = nullptr; - fragmentState.targetCount = 1; - fragmentState.targets = colorTargetStates; // render target index - - // render pipeline descriptor - WGPURenderPipelineDescriptor renderPipelineDesc{}; - renderPipelineDesc.nextInChain = nullptr; - renderPipelineDesc.label = "Render pipeline pipeline image"; - // renderPipelineDesc.layout - renderPipelineDesc.layout = mPipelineLayout; - // renderPipelineDesc.vertex - renderPipelineDesc.vertex.nextInChain = nullptr; - renderPipelineDesc.vertex.module = mShaderModule; - renderPipelineDesc.vertex.entryPoint = "vs_main"; - renderPipelineDesc.vertex.constantCount = 0; - renderPipelineDesc.vertex.constants = nullptr; - renderPipelineDesc.vertex.bufferCount = 2; - renderPipelineDesc.vertex.buffers = vertexBufferLayouts; // buffer index - // renderPipelineDesc.primitive - renderPipelineDesc.primitive.nextInChain = nullptr; - renderPipelineDesc.primitive.topology = WGPUPrimitiveTopology_TriangleList; - renderPipelineDesc.primitive.stripIndexFormat = WGPUIndexFormat_Undefined; - renderPipelineDesc.primitive.frontFace = WGPUFrontFace_CCW; - renderPipelineDesc.primitive.cullMode = WGPUCullMode_None; - // renderPipelineDesc.depthStencil - renderPipelineDesc.depthStencil = &depthStencilState; - // renderPipelineDesc.multisample - renderPipelineDesc.multisample.nextInChain = nullptr; - renderPipelineDesc.multisample.count = 1; - renderPipelineDesc.multisample.mask = 0xFFFFFFFF; - renderPipelineDesc.multisample.alphaToCoverageEnabled = false; - // renderPipelineDesc.fragment - renderPipelineDesc.fragment = &fragmentState; - mRenderPipeline = wgpuDeviceCreateRenderPipeline(device, &renderPipelineDesc); - assert(mRenderPipeline); -} - -void WgPipelineImage::release() { - wgpuRenderPipelineRelease(mRenderPipeline); - wgpuShaderModuleRelease(mShaderModule); - wgpuPipelineLayoutRelease(mPipelineLayout); - wgpuBindGroupLayoutRelease(mBindGroupLayout); -} diff --git a/src/renderer/wg_engine/tvgWgPipelineImage.h b/src/renderer/wg_engine/tvgWgPipelineImage.h deleted file mode 100644 index 1abf72bb..00000000 --- a/src/renderer/wg_engine/tvgWgPipelineImage.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2023 the ThorVG project. All rights reserved. - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef _TVG_WG_PIPELINE_IMAGE_H_ -#define _TVG_WG_PIPELINE_IMAGE_H_ - -#include "tvgWgPipelineBase.h" - -class WgPipelineImage; - -struct WgPipelineImageColorInfo { - uint32_t format{}; - float dummy0{}; - float dummy1{}; - float opacity{}; -}; - -struct WgPipelineDataImage: WgPipelineData { - WgPipelineImageColorInfo uColorInfo{}; // @binding(1) - - void updateFormat(const ColorSpace format); - void updateOpacity(const uint8_t opacity); -}; - -class WgPipelineBindGroupImage: public WgPipelineBindGroup { -private: - WGPUBuffer uBufferColorInfo{}; // @binding(1) - WGPUSampler uSamplerBase{}; // @binding(2) - WGPUTextureView uTextureViewBase{}; // @binding(3) - WGPUTexture mTextureBase{}; // gpu texture data -public: - void initialize(WGPUDevice device, WgPipelineImage& pipelineImage, Surface* surface); - void release(); - - void update(WGPUQueue mQueue, WgPipelineDataImage& pipelineDataImage, Surface* surface); -}; - -class WgPipelineImage: public WgPipelineBase { -public: - void initialize(WGPUDevice device) override; - void release() override; -}; - -#endif //_TVG_WG_PIPELINE_IMAGE_H_ diff --git a/src/renderer/wg_engine/tvgWgPipelineLinear.cpp b/src/renderer/wg_engine/tvgWgPipelineLinear.cpp deleted file mode 100644 index 67db9c36..00000000 --- a/src/renderer/wg_engine/tvgWgPipelineLinear.cpp +++ /dev/null @@ -1,305 +0,0 @@ -/* - * Copyright (c) 2023 the ThorVG project. All rights reserved. - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "tvgWgPipelineLinear.h" -#include "tvgWgShaderSrc.h" - -//************************************************************************ -// WgPipelineBindGroupLinear -//************************************************************************ - -void WgPipelineDataLinear::updateGradient(LinearGradient* linearGradient) { - - const Fill::ColorStop* stops = nullptr; - auto stopCnt = linearGradient->colorStops(&stops); - - uGradientInfo.nStops[0] = stopCnt; - uGradientInfo.nStops[1] = 0.5f; - - for (uint32_t i = 0; i < stopCnt; ++i) { - uGradientInfo.stopPoints[i] = stops[i].offset; - uGradientInfo.stopColors[i * 4 + 0] = stops[i].r / 255.f; - uGradientInfo.stopColors[i * 4 + 1] = stops[i].g / 255.f; - uGradientInfo.stopColors[i * 4 + 2] = stops[i].b / 255.f; - uGradientInfo.stopColors[i * 4 + 3] = stops[i].a / 255.f; - } - - linearGradient->linear( - &uGradientInfo.startPos[0], - &uGradientInfo.startPos[1], - &uGradientInfo.endPos[0], - &uGradientInfo.endPos[1]); -} - -//************************************************************************ -// WgPipelineBindGroupLinear -//************************************************************************ - -void WgPipelineBindGroupLinear::initialize(WGPUDevice device, WgPipelineLinear& pipelinePipelineLinear) { - // buffer uniform uMatrix - WGPUBufferDescriptor bufferUniformDesc_uMatrix{}; - bufferUniformDesc_uMatrix.nextInChain = nullptr; - bufferUniformDesc_uMatrix.label = "Buffer uniform pipeline linear uMatrix"; - bufferUniformDesc_uMatrix.usage = WGPUBufferUsage_CopyDst | WGPUBufferUsage_Uniform; - bufferUniformDesc_uMatrix.size = sizeof(WgPipelineMatrix); - bufferUniformDesc_uMatrix.mappedAtCreation = false; - uBufferMatrix = wgpuDeviceCreateBuffer(device, &bufferUniformDesc_uMatrix); - assert(uBufferMatrix); - // buffer uniform uColorInfo - WGPUBufferDescriptor bufferUniformDesc_uGradientInfo{}; - bufferUniformDesc_uGradientInfo.nextInChain = nullptr; - bufferUniformDesc_uGradientInfo.label = "Buffer uniform pipeline linear uGradientInfo"; - bufferUniformDesc_uGradientInfo.usage = WGPUBufferUsage_CopyDst | WGPUBufferUsage_Uniform; - bufferUniformDesc_uGradientInfo.size = sizeof(WgPipelineLinearGradientInfo); - bufferUniformDesc_uGradientInfo.mappedAtCreation = false; - uBufferGradientInfo = wgpuDeviceCreateBuffer(device, &bufferUniformDesc_uGradientInfo); - assert(uBufferGradientInfo); - - // bind group entry @binding(0) uMatrix - WGPUBindGroupEntry bindGroupEntry_uMatrix{}; - bindGroupEntry_uMatrix.nextInChain = nullptr; - bindGroupEntry_uMatrix.binding = 0; - bindGroupEntry_uMatrix.buffer = uBufferMatrix; - bindGroupEntry_uMatrix.offset = 0; - bindGroupEntry_uMatrix.size = sizeof(WgPipelineMatrix); - bindGroupEntry_uMatrix.sampler = nullptr; - bindGroupEntry_uMatrix.textureView = nullptr; - // bind group entry @binding(1) uGradientInfo - WGPUBindGroupEntry bindGroupEntry_uGradientInfo{}; - bindGroupEntry_uGradientInfo.nextInChain = nullptr; - bindGroupEntry_uGradientInfo.binding = 1; - bindGroupEntry_uGradientInfo.buffer = uBufferGradientInfo; - bindGroupEntry_uGradientInfo.offset = 0; - bindGroupEntry_uGradientInfo.size = sizeof(WgPipelineLinearGradientInfo); - bindGroupEntry_uGradientInfo.sampler = nullptr; - bindGroupEntry_uGradientInfo.textureView = nullptr; - // bind group entries - WGPUBindGroupEntry bindGroupEntries[] { - bindGroupEntry_uMatrix, // @binding(0) uMatrix - bindGroupEntry_uGradientInfo // @binding(1) uGradientInfo - }; - // bind group descriptor - WGPUBindGroupDescriptor bindGroupDescPipeline{}; - bindGroupDescPipeline.nextInChain = nullptr; - bindGroupDescPipeline.label = "The binding group pipeline linear"; - bindGroupDescPipeline.layout = pipelinePipelineLinear.mBindGroupLayout; - bindGroupDescPipeline.entryCount = 2; - bindGroupDescPipeline.entries = bindGroupEntries; - mBindGroup = wgpuDeviceCreateBindGroup(device, &bindGroupDescPipeline); - assert(mBindGroup); -} - -void WgPipelineBindGroupLinear::release() { - if (uBufferGradientInfo) { - wgpuBufferDestroy(uBufferGradientInfo); - wgpuBufferRelease(uBufferGradientInfo); - uBufferGradientInfo = nullptr; - } - if (uBufferMatrix) { - wgpuBufferDestroy(uBufferMatrix); - wgpuBufferRelease(uBufferMatrix); - uBufferMatrix = nullptr; - } - if (mBindGroup) { - wgpuBindGroupRelease(mBindGroup); - mBindGroup = nullptr; - } -} - -void WgPipelineBindGroupLinear::update(WGPUQueue queue, WgPipelineDataLinear& pipelineDataLinear) { - wgpuQueueWriteBuffer(queue, uBufferMatrix, 0, &pipelineDataLinear.uMatrix, sizeof(pipelineDataLinear.uMatrix)); - wgpuQueueWriteBuffer(queue, uBufferGradientInfo, 0, &pipelineDataLinear.uGradientInfo, sizeof(pipelineDataLinear.uGradientInfo)); -} - -//************************************************************************ -// WgPipelineLinear -//************************************************************************ - -void WgPipelineLinear::initialize(WGPUDevice device) { - // bind group layout group 0 - // bind group layout descriptor @group(0) @binding(0) uMatrix - WGPUBindGroupLayoutEntry bindGroupLayoutEntry_uMatrix{}; - bindGroupLayoutEntry_uMatrix.nextInChain = nullptr; - bindGroupLayoutEntry_uMatrix.binding = 0; - bindGroupLayoutEntry_uMatrix.visibility = WGPUShaderStage_Vertex | WGPUShaderStage_Fragment; - bindGroupLayoutEntry_uMatrix.buffer.nextInChain = nullptr; - bindGroupLayoutEntry_uMatrix.buffer.type = WGPUBufferBindingType_Uniform; - bindGroupLayoutEntry_uMatrix.buffer.hasDynamicOffset = false; - bindGroupLayoutEntry_uMatrix.buffer.minBindingSize = 0; - // bind group layout descriptor @group(0) @binding(1) uColorInfo - WGPUBindGroupLayoutEntry bindGroupLayoutEntry_uColorInfo{}; - bindGroupLayoutEntry_uColorInfo.nextInChain = nullptr; - bindGroupLayoutEntry_uColorInfo.binding = 1; - bindGroupLayoutEntry_uColorInfo.visibility = WGPUShaderStage_Vertex | WGPUShaderStage_Fragment; - bindGroupLayoutEntry_uColorInfo.buffer.nextInChain = nullptr; - bindGroupLayoutEntry_uColorInfo.buffer.type = WGPUBufferBindingType_Uniform; - bindGroupLayoutEntry_uColorInfo.buffer.hasDynamicOffset = false; - bindGroupLayoutEntry_uColorInfo.buffer.minBindingSize = 0; - // bind group layout entries @group(0) - WGPUBindGroupLayoutEntry bindGroupLayoutEntries[] { - bindGroupLayoutEntry_uMatrix, - bindGroupLayoutEntry_uColorInfo - }; - // bind group layout descriptor scene @group(0) - WGPUBindGroupLayoutDescriptor bindGroupLayoutDesc{}; - bindGroupLayoutDesc.nextInChain = nullptr; - bindGroupLayoutDesc.label = "Bind group layout pipeline linear"; - bindGroupLayoutDesc.entryCount = 2; - bindGroupLayoutDesc.entries = bindGroupLayoutEntries; // @binding - mBindGroupLayout = wgpuDeviceCreateBindGroupLayout(device, &bindGroupLayoutDesc); - assert(mBindGroupLayout); - - // pipeline layout - - // bind group layout descriptors - WGPUBindGroupLayout mBindGroupLayouts[] { - mBindGroupLayout - }; - // pipeline layout descriptor - WGPUPipelineLayoutDescriptor pipelineLayoutDesc{}; - pipelineLayoutDesc.nextInChain = nullptr; - pipelineLayoutDesc.label = "Pipeline pipeline layout linear"; - pipelineLayoutDesc.bindGroupLayoutCount = 1; - pipelineLayoutDesc.bindGroupLayouts = mBindGroupLayouts; - mPipelineLayout = wgpuDeviceCreatePipelineLayout(device, &pipelineLayoutDesc); - assert(mPipelineLayout); - - // depth stencil state - WGPUDepthStencilState depthStencilState{}; - depthStencilState.nextInChain = nullptr; - depthStencilState.format = WGPUTextureFormat_Stencil8; - depthStencilState.depthWriteEnabled = false; - depthStencilState.depthCompare = WGPUCompareFunction_Always; - // depthStencilState.stencilFront - depthStencilState.stencilFront.compare = WGPUCompareFunction_NotEqual; - depthStencilState.stencilFront.failOp = WGPUStencilOperation_Zero; - depthStencilState.stencilFront.depthFailOp = WGPUStencilOperation_Zero; - depthStencilState.stencilFront.passOp = WGPUStencilOperation_Zero; - // depthStencilState.stencilBack - depthStencilState.stencilBack.compare = WGPUCompareFunction_NotEqual; - depthStencilState.stencilBack.failOp = WGPUStencilOperation_Zero; - depthStencilState.stencilBack.depthFailOp = WGPUStencilOperation_Zero; - depthStencilState.stencilBack.passOp = WGPUStencilOperation_Zero; - // stencil mask - depthStencilState.stencilReadMask = 0xFFFFFFFF; - depthStencilState.stencilWriteMask = 0xFFFFFFFF; - // depth bias - depthStencilState.depthBias = 0; - depthStencilState.depthBiasSlopeScale = 0.0f; - depthStencilState.depthBiasClamp = 0.0f; - - // shader module wgsl descriptor - WGPUShaderModuleWGSLDescriptor shaderModuleWGSLDesc{}; - shaderModuleWGSLDesc.chain.next = nullptr; - shaderModuleWGSLDesc.chain.sType = WGPUSType_ShaderModuleWGSLDescriptor; - shaderModuleWGSLDesc.code = cShaderSource_PipelineLinear; - // shader module descriptor - WGPUShaderModuleDescriptor shaderModuleDesc{}; - shaderModuleDesc.nextInChain = &shaderModuleWGSLDesc.chain; - shaderModuleDesc.label = "The shader module pipeline linear"; - shaderModuleDesc.hintCount = 0; - shaderModuleDesc.hints = nullptr; - mShaderModule = wgpuDeviceCreateShaderModule(device, &shaderModuleDesc); - assert(mShaderModule); - - // vertex attributes - WGPUVertexAttribute vertexAttributes[] = { - { WGPUVertexFormat_Float32x2, sizeof(float) * 0, 0 }, // position - }; - // vertex buffer layout - WGPUVertexBufferLayout vertexBufferLayout{}; - vertexBufferLayout.arrayStride = sizeof(float) * 2; // position - vertexBufferLayout.stepMode = WGPUVertexStepMode_Vertex; - vertexBufferLayout.attributeCount = 1; // position - vertexBufferLayout.attributes = vertexAttributes; - - // blend state - WGPUBlendState blendState{}; - // blendState.color - blendState.color.operation = WGPUBlendOperation_Add; - blendState.color.srcFactor = WGPUBlendFactor_SrcAlpha; - blendState.color.dstFactor = WGPUBlendFactor_OneMinusSrcAlpha; - // blendState.alpha - blendState.alpha.operation = WGPUBlendOperation_Add; - blendState.alpha.srcFactor = WGPUBlendFactor_Zero; - blendState.alpha.dstFactor = WGPUBlendFactor_One; - - // color target state (WGPUTextureFormat_BGRA8UnormSrgb) - WGPUColorTargetState colorTargetState0{}; - colorTargetState0.nextInChain = nullptr; - colorTargetState0.format = WGPUTextureFormat_BGRA8Unorm; - //colorTargetState0.format = WGPUTextureFormat_BGRA8UnormSrgb; - colorTargetState0.blend = &blendState; - colorTargetState0.writeMask = WGPUColorWriteMask_All; - // color target states - WGPUColorTargetState colorTargetStates[] = { - colorTargetState0 - }; - // fragmanet state - WGPUFragmentState fragmentState{}; - fragmentState.nextInChain = nullptr; - fragmentState.module = mShaderModule; - fragmentState.entryPoint = "fs_main"; - fragmentState.constantCount = 0; - fragmentState.constants = nullptr; - fragmentState.targetCount = 1; - fragmentState.targets = colorTargetStates; // render target index - - // render pipeline descriptor - WGPURenderPipelineDescriptor renderPipelineDesc{}; - renderPipelineDesc.nextInChain = nullptr; - renderPipelineDesc.label = "Render pipeline pipeline linear"; - // renderPipelineDesc.layout - renderPipelineDesc.layout = mPipelineLayout; - // renderPipelineDesc.vertex - renderPipelineDesc.vertex.nextInChain = nullptr; - renderPipelineDesc.vertex.module = mShaderModule; - renderPipelineDesc.vertex.entryPoint = "vs_main"; - renderPipelineDesc.vertex.constantCount = 0; - renderPipelineDesc.vertex.constants = nullptr; - renderPipelineDesc.vertex.bufferCount = 1; - renderPipelineDesc.vertex.buffers = &vertexBufferLayout; // buffer index - // renderPipelineDesc.primitive - renderPipelineDesc.primitive.nextInChain = nullptr; - renderPipelineDesc.primitive.topology = WGPUPrimitiveTopology_TriangleList; - renderPipelineDesc.primitive.stripIndexFormat = WGPUIndexFormat_Undefined; - renderPipelineDesc.primitive.frontFace = WGPUFrontFace_CCW; - renderPipelineDesc.primitive.cullMode = WGPUCullMode_None; - // renderPipelineDesc.depthStencil - renderPipelineDesc.depthStencil = &depthStencilState; - // renderPipelineDesc.multisample - renderPipelineDesc.multisample.nextInChain = nullptr; - renderPipelineDesc.multisample.count = 1; - renderPipelineDesc.multisample.mask = 0xFFFFFFFF; - renderPipelineDesc.multisample.alphaToCoverageEnabled = false; - // renderPipelineDesc.fragment - renderPipelineDesc.fragment = &fragmentState; - mRenderPipeline = wgpuDeviceCreateRenderPipeline(device, &renderPipelineDesc); - assert(mRenderPipeline); -} - -void WgPipelineLinear::release() { - wgpuRenderPipelineRelease(mRenderPipeline); - wgpuShaderModuleRelease(mShaderModule); - wgpuPipelineLayoutRelease(mPipelineLayout); - wgpuBindGroupLayoutRelease(mBindGroupLayout); -} diff --git a/src/renderer/wg_engine/tvgWgPipelineLinear.h b/src/renderer/wg_engine/tvgWgPipelineLinear.h deleted file mode 100644 index 6d964334..00000000 --- a/src/renderer/wg_engine/tvgWgPipelineLinear.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2023 the ThorVG project. All rights reserved. - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef _TVG_WG_PIPELINE_LINEAR_H_ -#define _TVG_WG_PIPELINE_LINEAR_H_ - -#include "tvgWgPipelineBase.h" - -class WgPipelineLinear; - -#define MAX_LINEAR_GRADIENT_STOPS 4 -struct WgPipelineLinearGradientInfo { - alignas(16) float nStops[4]{}; - alignas(16) float startPos[2]{}; - alignas(8) float endPos[2]{}; - alignas(8) float stopPoints[MAX_LINEAR_GRADIENT_STOPS]{}; - alignas(16) float stopColors[4 * MAX_LINEAR_GRADIENT_STOPS]{}; -}; - -struct WgPipelineDataLinear: WgPipelineData { - WgPipelineLinearGradientInfo uGradientInfo{}; // @binding(1) - - void updateGradient(LinearGradient* linearGradient); -}; - -class WgPipelineBindGroupLinear: public WgPipelineBindGroup { -private: - WGPUBuffer uBufferGradientInfo{}; // @binding(1) -public: - void initialize(WGPUDevice device, WgPipelineLinear& pipelinePipelineLinear); - void release(); - - void update(WGPUQueue mQueue, WgPipelineDataLinear& pipelineDataLinear); -}; - -class WgPipelineLinear: public WgPipelineBase { -public: - void initialize(WGPUDevice device) override; - void release() override; -}; - -#endif //_TVG_WG_PIPELINE_LINEAR_H_ diff --git a/src/renderer/wg_engine/tvgWgPipelineRadial.cpp b/src/renderer/wg_engine/tvgWgPipelineRadial.cpp deleted file mode 100644 index 7fc8ccef..00000000 --- a/src/renderer/wg_engine/tvgWgPipelineRadial.cpp +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Copyright (c) 2023 the ThorVG project. All rights reserved. - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "tvgWgPipelineRadial.h" -#include "tvgWgShaderSrc.h" - -//************************************************************************ -// WgPipelineBindGroupRadial -//************************************************************************ - -void WgPipelineDataRadial::updateGradient(RadialGradient* radialGradient) { - const Fill::ColorStop* stops = nullptr; - auto stopCnt = radialGradient->colorStops(&stops); - - uGradientInfo.nStops[0] = stopCnt; - uGradientInfo.nStops[1] = 0.5f; - - for (uint32_t i = 0; i < stopCnt; ++i) { - uGradientInfo.stopPoints[i] = stops[i].offset; - uGradientInfo.stopColors[i * 4 + 0] = stops[i].r / 255.f; - uGradientInfo.stopColors[i * 4 + 1] = stops[i].g / 255.f; - uGradientInfo.stopColors[i * 4 + 2] = stops[i].b / 255.f; - uGradientInfo.stopColors[i * 4 + 3] = stops[i].a / 255.f; - } - - radialGradient->radial( - &uGradientInfo.centerPos[0], - &uGradientInfo.centerPos[1], - &uGradientInfo.radius[0]); -} - -//************************************************************************ -// WgPipelineBindGroupRadial -//************************************************************************ - -void WgPipelineBindGroupRadial::initialize(WGPUDevice device, WgPipelineRadial& pipelinePipelineRadial) { - // buffer uniform uMatrix - WGPUBufferDescriptor bufferUniformDesc_uMatrix{}; - bufferUniformDesc_uMatrix.nextInChain = nullptr; - bufferUniformDesc_uMatrix.label = "Buffer uniform pipeline radial uMatrix"; - bufferUniformDesc_uMatrix.usage = WGPUBufferUsage_CopyDst | WGPUBufferUsage_Uniform; - bufferUniformDesc_uMatrix.size = sizeof(WgPipelineMatrix); - bufferUniformDesc_uMatrix.mappedAtCreation = false; - uBufferMatrix = wgpuDeviceCreateBuffer(device, &bufferUniformDesc_uMatrix); - assert(uBufferMatrix); - // buffer uniform uColorInfo - WGPUBufferDescriptor bufferUniformDesc_uGradientInfo{}; - bufferUniformDesc_uGradientInfo.nextInChain = nullptr; - bufferUniformDesc_uGradientInfo.label = "Buffer uniform pipeline radial uGradientInfo"; - bufferUniformDesc_uGradientInfo.usage = WGPUBufferUsage_CopyDst | WGPUBufferUsage_Uniform; - bufferUniformDesc_uGradientInfo.size = sizeof(WgPipelineRadialGradientInfo); - bufferUniformDesc_uGradientInfo.mappedAtCreation = false; - uBufferGradientInfo = wgpuDeviceCreateBuffer(device, &bufferUniformDesc_uGradientInfo); - assert(uBufferGradientInfo); - - // bind group entry @binding(0) uMatrix - WGPUBindGroupEntry bindGroupEntry_uMatrix{}; - bindGroupEntry_uMatrix.nextInChain = nullptr; - bindGroupEntry_uMatrix.binding = 0; - bindGroupEntry_uMatrix.buffer = uBufferMatrix; - bindGroupEntry_uMatrix.offset = 0; - bindGroupEntry_uMatrix.size = sizeof(WgPipelineMatrix); - bindGroupEntry_uMatrix.sampler = nullptr; - bindGroupEntry_uMatrix.textureView = nullptr; - // bind group entry @binding(1) uGradientInfo - WGPUBindGroupEntry bindGroupEntry_uGradientInfo{}; - bindGroupEntry_uGradientInfo.nextInChain = nullptr; - bindGroupEntry_uGradientInfo.binding = 1; - bindGroupEntry_uGradientInfo.buffer = uBufferGradientInfo; - bindGroupEntry_uGradientInfo.offset = 0; - bindGroupEntry_uGradientInfo.size = sizeof(WgPipelineRadialGradientInfo); - bindGroupEntry_uGradientInfo.sampler = nullptr; - bindGroupEntry_uGradientInfo.textureView = nullptr; - // bind group entries - WGPUBindGroupEntry bindGroupEntries[] { - bindGroupEntry_uMatrix, // @binding(0) uMatrix - bindGroupEntry_uGradientInfo // @binding(1) uGradientInfo - }; - // bind group descriptor - WGPUBindGroupDescriptor bindGroupDescPipeline{}; - bindGroupDescPipeline.nextInChain = nullptr; - bindGroupDescPipeline.label = "The binding group pipeline radial"; - bindGroupDescPipeline.layout = pipelinePipelineRadial.mBindGroupLayout; - bindGroupDescPipeline.entryCount = 2; - bindGroupDescPipeline.entries = bindGroupEntries; - mBindGroup = wgpuDeviceCreateBindGroup(device, &bindGroupDescPipeline); - assert(mBindGroup); -} - -void WgPipelineBindGroupRadial::release() { - if (uBufferGradientInfo) { - wgpuBufferDestroy(uBufferGradientInfo); - wgpuBufferRelease(uBufferGradientInfo); - uBufferGradientInfo = nullptr; - } - if (uBufferMatrix) { - wgpuBufferDestroy(uBufferMatrix); - wgpuBufferRelease(uBufferMatrix); - uBufferMatrix = nullptr; - } - if (mBindGroup) { - wgpuBindGroupRelease(mBindGroup); - mBindGroup = nullptr; - } -} - -void WgPipelineBindGroupRadial::update(WGPUQueue queue, WgPipelineDataRadial& pipelineDataRadial) { - wgpuQueueWriteBuffer(queue, uBufferMatrix, 0, &pipelineDataRadial.uMatrix, sizeof(pipelineDataRadial.uMatrix)); - wgpuQueueWriteBuffer(queue, uBufferGradientInfo, 0, &pipelineDataRadial.uGradientInfo, sizeof(pipelineDataRadial.uGradientInfo)); -} - -//************************************************************************ -// WgPipelineRadial -//************************************************************************ - -void WgPipelineRadial::initialize(WGPUDevice device) { - // bind group layout group 0 - // bind group layout descriptor @group(0) @binding(0) uMatrix - WGPUBindGroupLayoutEntry bindGroupLayoutEntry_uMatrix{}; - bindGroupLayoutEntry_uMatrix.nextInChain = nullptr; - bindGroupLayoutEntry_uMatrix.binding = 0; - bindGroupLayoutEntry_uMatrix.visibility = WGPUShaderStage_Vertex | WGPUShaderStage_Fragment; - bindGroupLayoutEntry_uMatrix.buffer.nextInChain = nullptr; - bindGroupLayoutEntry_uMatrix.buffer.type = WGPUBufferBindingType_Uniform; - bindGroupLayoutEntry_uMatrix.buffer.hasDynamicOffset = false; - bindGroupLayoutEntry_uMatrix.buffer.minBindingSize = 0; - // bind group layout descriptor @group(0) @binding(1) uColorInfo - WGPUBindGroupLayoutEntry bindGroupLayoutEntry_uColorInfo{}; - bindGroupLayoutEntry_uColorInfo.nextInChain = nullptr; - bindGroupLayoutEntry_uColorInfo.binding = 1; - bindGroupLayoutEntry_uColorInfo.visibility = WGPUShaderStage_Vertex | WGPUShaderStage_Fragment; - bindGroupLayoutEntry_uColorInfo.buffer.nextInChain = nullptr; - bindGroupLayoutEntry_uColorInfo.buffer.type = WGPUBufferBindingType_Uniform; - bindGroupLayoutEntry_uColorInfo.buffer.hasDynamicOffset = false; - bindGroupLayoutEntry_uColorInfo.buffer.minBindingSize = 0; - // bind group layout entries @group(0) - WGPUBindGroupLayoutEntry bindGroupLayoutEntries[] { - bindGroupLayoutEntry_uMatrix, - bindGroupLayoutEntry_uColorInfo - }; - // bind group layout descriptor scene @group(0) - WGPUBindGroupLayoutDescriptor bindGroupLayoutDesc{}; - bindGroupLayoutDesc.nextInChain = nullptr; - bindGroupLayoutDesc.label = "Bind group layout pipeline radial"; - bindGroupLayoutDesc.entryCount = 2; - bindGroupLayoutDesc.entries = bindGroupLayoutEntries; // @binding - mBindGroupLayout = wgpuDeviceCreateBindGroupLayout(device, &bindGroupLayoutDesc); - assert(mBindGroupLayout); - - // pipeline layout - - // bind group layout descriptors - WGPUBindGroupLayout mBindGroupLayouts[] { - mBindGroupLayout - }; - // pipeline layout descriptor - WGPUPipelineLayoutDescriptor pipelineLayoutDesc{}; - pipelineLayoutDesc.nextInChain = nullptr; - pipelineLayoutDesc.label = "Pipeline pipeline layout radial"; - pipelineLayoutDesc.bindGroupLayoutCount = 1; - pipelineLayoutDesc.bindGroupLayouts = mBindGroupLayouts; - mPipelineLayout = wgpuDeviceCreatePipelineLayout(device, &pipelineLayoutDesc); - assert(mPipelineLayout); - - // depth stencil state - WGPUDepthStencilState depthStencilState{}; - depthStencilState.nextInChain = nullptr; - depthStencilState.format = WGPUTextureFormat_Stencil8; - depthStencilState.depthWriteEnabled = false; - depthStencilState.depthCompare = WGPUCompareFunction_Always; - // depthStencilState.stencilFront - depthStencilState.stencilFront.compare = WGPUCompareFunction_NotEqual; - depthStencilState.stencilFront.failOp = WGPUStencilOperation_Zero; - depthStencilState.stencilFront.depthFailOp = WGPUStencilOperation_Zero; - depthStencilState.stencilFront.passOp = WGPUStencilOperation_Zero; - // depthStencilState.stencilBack - depthStencilState.stencilBack.compare = WGPUCompareFunction_NotEqual; - depthStencilState.stencilBack.failOp = WGPUStencilOperation_Zero; - depthStencilState.stencilBack.depthFailOp = WGPUStencilOperation_Zero; - depthStencilState.stencilBack.passOp = WGPUStencilOperation_Zero; - // stencil mask - depthStencilState.stencilReadMask = 0xFFFFFFFF; - depthStencilState.stencilWriteMask = 0xFFFFFFFF; - // depth bias - depthStencilState.depthBias = 0; - depthStencilState.depthBiasSlopeScale = 0.0f; - depthStencilState.depthBiasClamp = 0.0f; - - // shader module wgsl descriptor - WGPUShaderModuleWGSLDescriptor shaderModuleWGSLDesc{}; - shaderModuleWGSLDesc.chain.next = nullptr; - shaderModuleWGSLDesc.chain.sType = WGPUSType_ShaderModuleWGSLDescriptor; - shaderModuleWGSLDesc.code = cShaderSource_PipelineRadial; - // shader module descriptor - WGPUShaderModuleDescriptor shaderModuleDesc{}; - shaderModuleDesc.nextInChain = &shaderModuleWGSLDesc.chain; - shaderModuleDesc.label = "The shader module pipeline radial"; - shaderModuleDesc.hintCount = 0; - shaderModuleDesc.hints = nullptr; - mShaderModule = wgpuDeviceCreateShaderModule(device, &shaderModuleDesc); - assert(mShaderModule); - - // vertex attributes - WGPUVertexAttribute vertexAttributes[] = { - { WGPUVertexFormat_Float32x2, sizeof(float) * 0, 0 }, // position - }; - // vertex buffer layout - WGPUVertexBufferLayout vertexBufferLayout{}; - vertexBufferLayout.arrayStride = sizeof(float) * 2; // position - vertexBufferLayout.stepMode = WGPUVertexStepMode_Vertex; - vertexBufferLayout.attributeCount = 1; // position - vertexBufferLayout.attributes = vertexAttributes; - - // blend state - WGPUBlendState blendState{}; - // blendState.color - blendState.color.operation = WGPUBlendOperation_Add; - blendState.color.srcFactor = WGPUBlendFactor_SrcAlpha; - blendState.color.dstFactor = WGPUBlendFactor_OneMinusSrcAlpha; - // blendState.alpha - blendState.alpha.operation = WGPUBlendOperation_Add; - blendState.alpha.srcFactor = WGPUBlendFactor_Zero; - blendState.alpha.dstFactor = WGPUBlendFactor_One; - - // color target state (WGPUTextureFormat_BGRA8UnormSrgb) - WGPUColorTargetState colorTargetState0{}; - colorTargetState0.nextInChain = nullptr; - colorTargetState0.format = WGPUTextureFormat_BGRA8Unorm; - //colorTargetState0.format = WGPUTextureFormat_BGRA8UnormSrgb; - colorTargetState0.blend = &blendState; - colorTargetState0.writeMask = WGPUColorWriteMask_All; - // color target states - WGPUColorTargetState colorTargetStates[] = { - colorTargetState0 - }; - // fragmanet state - WGPUFragmentState fragmentState{}; - fragmentState.nextInChain = nullptr; - fragmentState.module = mShaderModule; - fragmentState.entryPoint = "fs_main"; - fragmentState.constantCount = 0; - fragmentState.constants = nullptr; - fragmentState.targetCount = 1; - fragmentState.targets = colorTargetStates; // render target index - - // render pipeline descriptor - WGPURenderPipelineDescriptor renderPipelineDesc{}; - renderPipelineDesc.nextInChain = nullptr; - renderPipelineDesc.label = "Render pipeline pipeline radial"; - // renderPipelineDesc.layout - renderPipelineDesc.layout = mPipelineLayout; - // renderPipelineDesc.vertex - renderPipelineDesc.vertex.nextInChain = nullptr; - renderPipelineDesc.vertex.module = mShaderModule; - renderPipelineDesc.vertex.entryPoint = "vs_main"; - renderPipelineDesc.vertex.constantCount = 0; - renderPipelineDesc.vertex.constants = nullptr; - renderPipelineDesc.vertex.bufferCount = 1; - renderPipelineDesc.vertex.buffers = &vertexBufferLayout; // buffer index - // renderPipelineDesc.primitive - renderPipelineDesc.primitive.nextInChain = nullptr; - renderPipelineDesc.primitive.topology = WGPUPrimitiveTopology_TriangleList; - renderPipelineDesc.primitive.stripIndexFormat = WGPUIndexFormat_Undefined; - renderPipelineDesc.primitive.frontFace = WGPUFrontFace_CCW; - renderPipelineDesc.primitive.cullMode = WGPUCullMode_None; - // renderPipelineDesc.depthStencil - renderPipelineDesc.depthStencil = &depthStencilState; - // renderPipelineDesc.multisample - renderPipelineDesc.multisample.nextInChain = nullptr; - renderPipelineDesc.multisample.count = 1; - renderPipelineDesc.multisample.mask = 0xFFFFFFFF; - renderPipelineDesc.multisample.alphaToCoverageEnabled = false; - // renderPipelineDesc.fragment - renderPipelineDesc.fragment = &fragmentState; - mRenderPipeline = wgpuDeviceCreateRenderPipeline(device, &renderPipelineDesc); - assert(mRenderPipeline); -} - -void WgPipelineRadial::release() { - wgpuRenderPipelineRelease(mRenderPipeline); - wgpuShaderModuleRelease(mShaderModule); - wgpuPipelineLayoutRelease(mPipelineLayout); - wgpuBindGroupLayoutRelease(mBindGroupLayout); -} diff --git a/src/renderer/wg_engine/tvgWgPipelineRadial.h b/src/renderer/wg_engine/tvgWgPipelineRadial.h deleted file mode 100644 index f04e12c3..00000000 --- a/src/renderer/wg_engine/tvgWgPipelineRadial.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2023 the ThorVG project. All rights reserved. - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef _TVG_WG_PIPELINE_RADIAL_H_ -#define _TVG_WG_PIPELINE_RADIAL_H_ - -#include "tvgWgPipelineBase.h" - -class WgPipelineRadial; - -#define MAX_RADIAL_GRADIENT_STOPS 4 -struct WgPipelineRadialGradientInfo { - alignas(16) float nStops[4]{}; - alignas(16) float centerPos[2]{}; - alignas(8) float radius[2]{}; - alignas(8) float stopPoints[MAX_RADIAL_GRADIENT_STOPS]{}; - alignas(16) float stopColors[4 * MAX_RADIAL_GRADIENT_STOPS]{}; -}; - -struct WgPipelineDataRadial: WgPipelineData { - WgPipelineRadialGradientInfo uGradientInfo{}; // @binding(1) - - void updateGradient(RadialGradient* radialGradient); -}; - -class WgPipelineBindGroupRadial: public WgPipelineBindGroup { -private: - WGPUBuffer uBufferGradientInfo{}; // @binding(1) -public: - void initialize(WGPUDevice device, WgPipelineRadial& pipelinePipelineRadial); - void release(); - - void update(WGPUQueue mQueue, WgPipelineDataRadial& pipelineDataRadial); -}; - -class WgPipelineRadial: public WgPipelineBase { -public: - void initialize(WGPUDevice device) override; - void release() override; -}; - -#endif //_TVG_WG_PIPELINE_RADIAL_H_ diff --git a/src/renderer/wg_engine/tvgWgPipelineSolid.cpp b/src/renderer/wg_engine/tvgWgPipelineSolid.cpp deleted file mode 100644 index bfa4e447..00000000 --- a/src/renderer/wg_engine/tvgWgPipelineSolid.cpp +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Copyright (c) 2023 the ThorVG project. All rights reserved. - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "tvgWgPipelineSolid.h" -#include "tvgWgShaderSrc.h" - -//************************************************************************ -// WgPipelineDataSolid -//************************************************************************ - -void WgPipelineDataSolid::updateColor(const uint8_t* color) { - uColorInfo.color[0] = color[0] / 255.0f; // red - uColorInfo.color[1] = color[1] / 255.0f; // green - uColorInfo.color[2] = color[2] / 255.0f; // blue - uColorInfo.color[3] = color[3] / 255.0f; // alpha -} - -//************************************************************************ -// WgPipelineBindGroupSolid -//************************************************************************ - -void WgPipelineBindGroupSolid::initialize(WGPUDevice device, WgPipelineSolid& pipelinePipelineSolid) { - // buffer uniform uMatrix - WGPUBufferDescriptor bufferUniformDesc_uMatrix{}; - bufferUniformDesc_uMatrix.nextInChain = nullptr; - bufferUniformDesc_uMatrix.label = "Buffer uniform pipeline solid uMatrix"; - bufferUniformDesc_uMatrix.usage = WGPUBufferUsage_CopyDst | WGPUBufferUsage_Uniform; - bufferUniformDesc_uMatrix.size = sizeof(WgPipelineMatrix); - bufferUniformDesc_uMatrix.mappedAtCreation = false; - uBufferMatrix = wgpuDeviceCreateBuffer(device, &bufferUniformDesc_uMatrix); - assert(uBufferMatrix); - // buffer uniform uColorInfo - WGPUBufferDescriptor bufferUniformDesc_uColorInfo{}; - bufferUniformDesc_uColorInfo.nextInChain = nullptr; - bufferUniformDesc_uColorInfo.label = "Buffer uniform pipeline solid uColorInfo"; - bufferUniformDesc_uColorInfo.usage = WGPUBufferUsage_CopyDst | WGPUBufferUsage_Uniform; - bufferUniformDesc_uColorInfo.size = sizeof(WgPipelineSolidColorInfo); - bufferUniformDesc_uColorInfo.mappedAtCreation = false; - uBufferColorInfo = wgpuDeviceCreateBuffer(device, &bufferUniformDesc_uColorInfo); - assert(uBufferColorInfo); - - // bind group entry @binding(0) uMatrix - WGPUBindGroupEntry bindGroupEntry_uMatrix{}; - bindGroupEntry_uMatrix.nextInChain = nullptr; - bindGroupEntry_uMatrix.binding = 0; - bindGroupEntry_uMatrix.buffer = uBufferMatrix; - bindGroupEntry_uMatrix.offset = 0; - bindGroupEntry_uMatrix.size = sizeof(WgPipelineMatrix); - bindGroupEntry_uMatrix.sampler = nullptr; - bindGroupEntry_uMatrix.textureView = nullptr; - // bind group entry @binding(1) uColorInfo - WGPUBindGroupEntry bindGroupEntry_uColorInfo{}; - bindGroupEntry_uColorInfo.nextInChain = nullptr; - bindGroupEntry_uColorInfo.binding = 1; - bindGroupEntry_uColorInfo.buffer = uBufferColorInfo; - bindGroupEntry_uColorInfo.offset = 0; - bindGroupEntry_uColorInfo.size = sizeof(WgPipelineSolidColorInfo); - bindGroupEntry_uColorInfo.sampler = nullptr; - bindGroupEntry_uColorInfo.textureView = nullptr; - // bind group entries - WGPUBindGroupEntry bindGroupEntries[] { - bindGroupEntry_uMatrix, // @binding(0) uMatrix - bindGroupEntry_uColorInfo // @binding(1) uColorInfo - }; - // bind group descriptor - WGPUBindGroupDescriptor bindGroupDescPipeline{}; - bindGroupDescPipeline.nextInChain = nullptr; - bindGroupDescPipeline.label = "The binding group pipeline solid"; - bindGroupDescPipeline.layout = pipelinePipelineSolid.mBindGroupLayout; - bindGroupDescPipeline.entryCount = 2; - bindGroupDescPipeline.entries = bindGroupEntries; - mBindGroup = wgpuDeviceCreateBindGroup(device, &bindGroupDescPipeline); - assert(mBindGroup); -} - -void WgPipelineBindGroupSolid::release() { - if (uBufferColorInfo) { - wgpuBufferDestroy(uBufferColorInfo); - wgpuBufferRelease(uBufferColorInfo); - uBufferColorInfo = nullptr; - } - if (uBufferMatrix) { - wgpuBufferDestroy(uBufferMatrix); - wgpuBufferRelease(uBufferMatrix); - uBufferMatrix = nullptr; - } - if (mBindGroup) { - wgpuBindGroupRelease(mBindGroup); - mBindGroup = nullptr; - } -} - -void WgPipelineBindGroupSolid::update(WGPUQueue queue, WgPipelineDataSolid& pipelineDataSolid) { - wgpuQueueWriteBuffer(queue, uBufferMatrix, 0, &pipelineDataSolid.uMatrix, sizeof(pipelineDataSolid.uMatrix)); - wgpuQueueWriteBuffer(queue, uBufferColorInfo, 0, &pipelineDataSolid.uColorInfo, sizeof(pipelineDataSolid.uColorInfo)); -} - -//************************************************************************ -// WgPipelineSolid -//************************************************************************ - -void WgPipelineSolid::initialize(WGPUDevice device) { - // bind group layout group 0 - // bind group layout descriptor @group(0) @binding(0) uMatrix - WGPUBindGroupLayoutEntry bindGroupLayoutEntry_uMatrix{}; - bindGroupLayoutEntry_uMatrix.nextInChain = nullptr; - bindGroupLayoutEntry_uMatrix.binding = 0; - bindGroupLayoutEntry_uMatrix.visibility = WGPUShaderStage_Vertex | WGPUShaderStage_Fragment; - bindGroupLayoutEntry_uMatrix.buffer.nextInChain = nullptr; - bindGroupLayoutEntry_uMatrix.buffer.type = WGPUBufferBindingType_Uniform; - bindGroupLayoutEntry_uMatrix.buffer.hasDynamicOffset = false; - bindGroupLayoutEntry_uMatrix.buffer.minBindingSize = 0; - // bind group layout descriptor @group(0) @binding(1) uColorInfo - WGPUBindGroupLayoutEntry bindGroupLayoutEntry_uColorInfo{}; - bindGroupLayoutEntry_uColorInfo.nextInChain = nullptr; - bindGroupLayoutEntry_uColorInfo.binding = 1; - bindGroupLayoutEntry_uColorInfo.visibility = WGPUShaderStage_Vertex | WGPUShaderStage_Fragment; - bindGroupLayoutEntry_uColorInfo.buffer.nextInChain = nullptr; - bindGroupLayoutEntry_uColorInfo.buffer.type = WGPUBufferBindingType_Uniform; - bindGroupLayoutEntry_uColorInfo.buffer.hasDynamicOffset = false; - bindGroupLayoutEntry_uColorInfo.buffer.minBindingSize = 0; - // bind group layout entries @group(0) - WGPUBindGroupLayoutEntry bindGroupLayoutEntries[] { - bindGroupLayoutEntry_uMatrix, - bindGroupLayoutEntry_uColorInfo - }; - // bind group layout descriptor scene @group(0) - WGPUBindGroupLayoutDescriptor bindGroupLayoutDesc{}; - bindGroupLayoutDesc.nextInChain = nullptr; - bindGroupLayoutDesc.label = "Bind group layout pipeline solid"; - bindGroupLayoutDesc.entryCount = 2; - bindGroupLayoutDesc.entries = bindGroupLayoutEntries; // @binding - mBindGroupLayout = wgpuDeviceCreateBindGroupLayout(device, &bindGroupLayoutDesc); - assert(mBindGroupLayout); - - // pipeline layout - - // bind group layout descriptors - WGPUBindGroupLayout mBindGroupLayouts[] { - mBindGroupLayout - }; - // pipeline layout descriptor - WGPUPipelineLayoutDescriptor pipelineLayoutDesc{}; - pipelineLayoutDesc.nextInChain = nullptr; - pipelineLayoutDesc.label = "Pipeline pipeline layout solid"; - pipelineLayoutDesc.bindGroupLayoutCount = 1; - pipelineLayoutDesc.bindGroupLayouts = mBindGroupLayouts; - mPipelineLayout = wgpuDeviceCreatePipelineLayout(device, &pipelineLayoutDesc); - assert(mPipelineLayout); - - // depth stencil state - WGPUDepthStencilState depthStencilState{}; - depthStencilState.nextInChain = nullptr; - depthStencilState.format = WGPUTextureFormat_Stencil8; - depthStencilState.depthWriteEnabled = false; - depthStencilState.depthCompare = WGPUCompareFunction_Always; - // depthStencilState.stencilFront - depthStencilState.stencilFront.compare = WGPUCompareFunction_NotEqual; - depthStencilState.stencilFront.failOp = WGPUStencilOperation_Zero; - depthStencilState.stencilFront.depthFailOp = WGPUStencilOperation_Zero; - depthStencilState.stencilFront.passOp = WGPUStencilOperation_Zero; - // depthStencilState.stencilBack - depthStencilState.stencilBack.compare = WGPUCompareFunction_NotEqual; - depthStencilState.stencilBack.failOp = WGPUStencilOperation_Zero; - depthStencilState.stencilBack.depthFailOp = WGPUStencilOperation_Zero; - depthStencilState.stencilBack.passOp = WGPUStencilOperation_Zero; - // stencil mask - depthStencilState.stencilReadMask = 0xFFFFFFFF; - depthStencilState.stencilWriteMask = 0xFFFFFFFF; - // depth bias - depthStencilState.depthBias = 0; - depthStencilState.depthBiasSlopeScale = 0.0f; - depthStencilState.depthBiasClamp = 0.0f; - - // shader module wgsl descriptor - WGPUShaderModuleWGSLDescriptor shaderModuleWGSLDesc{}; - shaderModuleWGSLDesc.chain.next = nullptr; - shaderModuleWGSLDesc.chain.sType = WGPUSType_ShaderModuleWGSLDescriptor; - shaderModuleWGSLDesc.code = cShaderSource_PipelineSolid; - // shader module descriptor - WGPUShaderModuleDescriptor shaderModuleDesc{}; - shaderModuleDesc.nextInChain = &shaderModuleWGSLDesc.chain; - shaderModuleDesc.label = "The shader module pipeline solid"; - shaderModuleDesc.hintCount = 0; - shaderModuleDesc.hints = nullptr; - mShaderModule = wgpuDeviceCreateShaderModule(device, &shaderModuleDesc); - assert(mShaderModule); - - // vertex attributes - WGPUVertexAttribute vertexAttributes[] = { - { WGPUVertexFormat_Float32x2, sizeof(float) * 0, 0 }, // position - }; - // vertex buffer layout - WGPUVertexBufferLayout vertexBufferLayout{}; - vertexBufferLayout.arrayStride = sizeof(float) * 2; // position - vertexBufferLayout.stepMode = WGPUVertexStepMode_Vertex; - vertexBufferLayout.attributeCount = 1; // position - vertexBufferLayout.attributes = vertexAttributes; - - // blend state - WGPUBlendState blendState{}; - // blendState.color - blendState.color.operation = WGPUBlendOperation_Add; - blendState.color.srcFactor = WGPUBlendFactor_SrcAlpha; - blendState.color.dstFactor = WGPUBlendFactor_OneMinusSrcAlpha; - // blendState.alpha - blendState.alpha.operation = WGPUBlendOperation_Add; - blendState.alpha.srcFactor = WGPUBlendFactor_Zero; - blendState.alpha.dstFactor = WGPUBlendFactor_One; - - // color target state (WGPUTextureFormat_BGRA8UnormSrgb) - WGPUColorTargetState colorTargetState0{}; - colorTargetState0.nextInChain = nullptr; - colorTargetState0.format = WGPUTextureFormat_BGRA8Unorm; - //colorTargetState0.format = WGPUTextureFormat_BGRA8UnormSrgb; - colorTargetState0.blend = &blendState; - colorTargetState0.writeMask = WGPUColorWriteMask_All; - // color target states - WGPUColorTargetState colorTargetStates[] = { - colorTargetState0 - }; - // fragmanet state - WGPUFragmentState fragmentState{}; - fragmentState.nextInChain = nullptr; - fragmentState.module = mShaderModule; - fragmentState.entryPoint = "fs_main"; - fragmentState.constantCount = 0; - fragmentState.constants = nullptr; - fragmentState.targetCount = 1; - fragmentState.targets = colorTargetStates; // render target index - - // render pipeline descriptor - WGPURenderPipelineDescriptor renderPipelineDesc{}; - renderPipelineDesc.nextInChain = nullptr; - renderPipelineDesc.label = "Render pipeline pipeline solid"; - // renderPipelineDesc.layout - renderPipelineDesc.layout = mPipelineLayout; - // renderPipelineDesc.vertex - renderPipelineDesc.vertex.nextInChain = nullptr; - renderPipelineDesc.vertex.module = mShaderModule; - renderPipelineDesc.vertex.entryPoint = "vs_main"; - renderPipelineDesc.vertex.constantCount = 0; - renderPipelineDesc.vertex.constants = nullptr; - renderPipelineDesc.vertex.bufferCount = 1; - renderPipelineDesc.vertex.buffers = &vertexBufferLayout; // buffer index - // renderPipelineDesc.primitive - renderPipelineDesc.primitive.nextInChain = nullptr; - renderPipelineDesc.primitive.topology = WGPUPrimitiveTopology_TriangleList; - renderPipelineDesc.primitive.stripIndexFormat = WGPUIndexFormat_Undefined; - renderPipelineDesc.primitive.frontFace = WGPUFrontFace_CCW; - renderPipelineDesc.primitive.cullMode = WGPUCullMode_None; - // renderPipelineDesc.depthStencil - renderPipelineDesc.depthStencil = &depthStencilState; - // renderPipelineDesc.multisample - renderPipelineDesc.multisample.nextInChain = nullptr; - renderPipelineDesc.multisample.count = 1; - renderPipelineDesc.multisample.mask = 0xFFFFFFFF; - renderPipelineDesc.multisample.alphaToCoverageEnabled = false; - // renderPipelineDesc.fragment - renderPipelineDesc.fragment = &fragmentState; - mRenderPipeline = wgpuDeviceCreateRenderPipeline(device, &renderPipelineDesc); - assert(mRenderPipeline); -} - -void WgPipelineSolid::release() { - wgpuRenderPipelineRelease(mRenderPipeline); - wgpuShaderModuleRelease(mShaderModule); - wgpuPipelineLayoutRelease(mPipelineLayout); - wgpuBindGroupLayoutRelease(mBindGroupLayout); -} diff --git a/src/renderer/wg_engine/tvgWgPipelineSolid.h b/src/renderer/wg_engine/tvgWgPipelineSolid.h deleted file mode 100644 index 4fffcc6b..00000000 --- a/src/renderer/wg_engine/tvgWgPipelineSolid.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2023 the ThorVG project. All rights reserved. - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef _TVG_WG_PIPELINE_SOLID_H_ -#define _TVG_WG_PIPELINE_SOLID_H_ - -#include "tvgWgPipelineBase.h" - -class WgPipelineSolid; - -struct WgPipelineSolidColorInfo { - float color[4]{}; -}; - -struct WgPipelineDataSolid: WgPipelineData { - WgPipelineSolidColorInfo uColorInfo{}; // @binding(1) - - void updateColor(const uint8_t* color); -}; - -class WgPipelineBindGroupSolid: public WgPipelineBindGroup { -private: - WGPUBuffer uBufferColorInfo{}; // @binding(1) -public: - void initialize(WGPUDevice device, WgPipelineSolid& pipelinePipelineSolid); - void release(); - - void update(WGPUQueue mQueue, WgPipelineDataSolid& pipelineDataSolid); -}; - -class WgPipelineSolid: public WgPipelineBase { -public: - void initialize(WGPUDevice device) override; - void release() override; -}; - -#endif //_TVG_WG_PIPELINE_SOLID_H_ diff --git a/src/renderer/wg_engine/tvgWgPipelineStroke.cpp b/src/renderer/wg_engine/tvgWgPipelineStroke.cpp deleted file mode 100644 index bf75cb4d..00000000 --- a/src/renderer/wg_engine/tvgWgPipelineStroke.cpp +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright (c) 2023 the ThorVG project. All rights reserved. - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "tvgWgPipelineStroke.h" -#include "tvgWgShaderSrc.h" - -//************************************************************************ -// WgPipelineBindGroupStroke -//************************************************************************ - -void WgPipelineBindGroupStroke::initialize(WGPUDevice device, WgPipelineStroke& pipelinePipelineStroke) { - // buffer uniform uMatrix - WGPUBufferDescriptor bufferUniformDesc_uMatrix{}; - bufferUniformDesc_uMatrix.nextInChain = nullptr; - bufferUniformDesc_uMatrix.label = "Buffer uniform pipeline Stroke uMatrix"; - bufferUniformDesc_uMatrix.usage = WGPUBufferUsage_CopyDst | WGPUBufferUsage_Uniform; - bufferUniformDesc_uMatrix.size = sizeof(WgPipelineMatrix); - bufferUniformDesc_uMatrix.mappedAtCreation = false; - uBufferMatrix = wgpuDeviceCreateBuffer(device, &bufferUniformDesc_uMatrix); - assert(uBufferMatrix); - - // bind group entry @binding(0) uMatrix - WGPUBindGroupEntry bindGroupEntry_uMatrix{}; - bindGroupEntry_uMatrix.nextInChain = nullptr; - bindGroupEntry_uMatrix.binding = 0; - bindGroupEntry_uMatrix.buffer = uBufferMatrix; - bindGroupEntry_uMatrix.offset = 0; - bindGroupEntry_uMatrix.size = sizeof(WgPipelineMatrix); - bindGroupEntry_uMatrix.sampler = nullptr; - bindGroupEntry_uMatrix.textureView = nullptr; - // bind group entries - WGPUBindGroupEntry bindGroupEntries[] { - bindGroupEntry_uMatrix // @binding(0) uMatrix - }; - // bind group descriptor - WGPUBindGroupDescriptor bindGroupDescPipeline{}; - bindGroupDescPipeline.nextInChain = nullptr; - bindGroupDescPipeline.label = "The binding group pipeline stroke"; - bindGroupDescPipeline.layout = pipelinePipelineStroke.mBindGroupLayout; - bindGroupDescPipeline.entryCount = 1; - bindGroupDescPipeline.entries = bindGroupEntries; - mBindGroup = wgpuDeviceCreateBindGroup(device, &bindGroupDescPipeline); - assert(mBindGroup); -} - -void WgPipelineBindGroupStroke::release() { - if (uBufferMatrix) { - wgpuBufferDestroy(uBufferMatrix); - wgpuBufferRelease(uBufferMatrix); - uBufferMatrix = nullptr; - } - if (mBindGroup) { - wgpuBindGroupRelease(mBindGroup); - mBindGroup = nullptr; - } -} - -void WgPipelineBindGroupStroke::update(WGPUQueue queue, WgPipelineDataStroke& pipelineDataStroke) { - wgpuQueueWriteBuffer(queue, uBufferMatrix, 0, &pipelineDataStroke.uMatrix, sizeof(pipelineDataStroke.uMatrix)); -} - -//************************************************************************ -// WgPipelineStroke -//************************************************************************ - -void WgPipelineStroke::initialize(WGPUDevice device) { - // bind group layout group 0 - // bind group layout descriptor @group(0) @binding(0) uMatrix - WGPUBindGroupLayoutEntry bindGroupLayoutEntry_uMatrix{}; - bindGroupLayoutEntry_uMatrix.nextInChain = nullptr; - bindGroupLayoutEntry_uMatrix.binding = 0; - bindGroupLayoutEntry_uMatrix.visibility = WGPUShaderStage_Vertex | WGPUShaderStage_Fragment; - bindGroupLayoutEntry_uMatrix.buffer.nextInChain = nullptr; - bindGroupLayoutEntry_uMatrix.buffer.type = WGPUBufferBindingType_Uniform; - bindGroupLayoutEntry_uMatrix.buffer.hasDynamicOffset = false; - bindGroupLayoutEntry_uMatrix.buffer.minBindingSize = 0; - // bind group layout entries @group(0) - WGPUBindGroupLayoutEntry bindGroupLayoutEntries[] { - bindGroupLayoutEntry_uMatrix - }; - // bind group layout descriptor scene @group(0) - WGPUBindGroupLayoutDescriptor bindGroupLayoutDesc{}; - bindGroupLayoutDesc.nextInChain = nullptr; - bindGroupLayoutDesc.label = "Bind group layout pipeline stroke"; - bindGroupLayoutDesc.entryCount = 1; - bindGroupLayoutDesc.entries = bindGroupLayoutEntries; // @binding - mBindGroupLayout = wgpuDeviceCreateBindGroupLayout(device, &bindGroupLayoutDesc); - assert(mBindGroupLayout); - - // pipeline layout - - // bind group layout descriptors - WGPUBindGroupLayout mBindGroupLayouts[] { - mBindGroupLayout - }; - // pipeline layout descriptor - WGPUPipelineLayoutDescriptor pipelineLayoutDesc{}; - pipelineLayoutDesc.nextInChain = nullptr; - pipelineLayoutDesc.label = "Pipeline pipeline layout stroke"; - pipelineLayoutDesc.bindGroupLayoutCount = 1; - pipelineLayoutDesc.bindGroupLayouts = mBindGroupLayouts; - mPipelineLayout = wgpuDeviceCreatePipelineLayout(device, &pipelineLayoutDesc); - assert(mPipelineLayout); - - // depth stencil state - WGPUDepthStencilState depthStencilState{}; - depthStencilState.nextInChain = nullptr; - depthStencilState.format = WGPUTextureFormat_Stencil8; - depthStencilState.depthWriteEnabled = false; - depthStencilState.depthCompare = WGPUCompareFunction_Always; - // depthStencilState.stencilFront - depthStencilState.stencilFront.compare = WGPUCompareFunction_Always; - depthStencilState.stencilFront.failOp = WGPUStencilOperation_Replace; - depthStencilState.stencilFront.depthFailOp = WGPUStencilOperation_Replace; - depthStencilState.stencilFront.passOp = WGPUStencilOperation_Replace; - // depthStencilState.stencilBack - depthStencilState.stencilBack.compare = WGPUCompareFunction_Always; - depthStencilState.stencilBack.failOp = WGPUStencilOperation_Replace; - depthStencilState.stencilBack.depthFailOp = WGPUStencilOperation_Replace; - depthStencilState.stencilBack.passOp = WGPUStencilOperation_Replace; - // stencil mask - depthStencilState.stencilReadMask = 0xFFFFFFFF; - depthStencilState.stencilWriteMask = 0xFFFFFFFF; - // depth bias - depthStencilState.depthBias = 0; - depthStencilState.depthBiasSlopeScale = 0.0f; - depthStencilState.depthBiasClamp = 0.0f; - - // shader module wgsl descriptor - WGPUShaderModuleWGSLDescriptor shaderModuleWGSLDesc{}; - shaderModuleWGSLDesc.chain.next = nullptr; - shaderModuleWGSLDesc.chain.sType = WGPUSType_ShaderModuleWGSLDescriptor; - shaderModuleWGSLDesc.code = cShaderSource_PipelineEmpty; - // shader module descriptor - WGPUShaderModuleDescriptor shaderModuleDesc{}; - shaderModuleDesc.nextInChain = &shaderModuleWGSLDesc.chain; - shaderModuleDesc.label = "The shader module pipeline Stroke"; - shaderModuleDesc.hintCount = 0; - shaderModuleDesc.hints = nullptr; - mShaderModule = wgpuDeviceCreateShaderModule(device, &shaderModuleDesc); - assert(mShaderModule); - - // vertex attributes - WGPUVertexAttribute vertexAttributes[] = { - { WGPUVertexFormat_Float32x2, sizeof(float) * 0, 0 }, // position - }; - // vertex buffer layout - WGPUVertexBufferLayout vertexBufferLayout{}; - vertexBufferLayout.arrayStride = sizeof(float) * 2; // position - vertexBufferLayout.stepMode = WGPUVertexStepMode_Vertex; - vertexBufferLayout.attributeCount = 1; // position - vertexBufferLayout.attributes = vertexAttributes; - - // blend state - WGPUBlendState blendState{}; - // blendState.color - blendState.color.operation = WGPUBlendOperation_Add; - blendState.color.srcFactor = WGPUBlendFactor_SrcAlpha; - blendState.color.dstFactor = WGPUBlendFactor_OneMinusSrcAlpha; - // blendState.alpha - blendState.alpha.operation = WGPUBlendOperation_Add; - blendState.alpha.srcFactor = WGPUBlendFactor_Zero; - blendState.alpha.dstFactor = WGPUBlendFactor_One; - - // color target state (WGPUTextureFormat_BGRA8UnormSrgb) - WGPUColorTargetState colorTargetState0{}; - colorTargetState0.nextInChain = nullptr; - colorTargetState0.format = WGPUTextureFormat_BGRA8Unorm; - //colorTargetState0.format = WGPUTextureFormat_BGRA8UnormSrgb; - colorTargetState0.blend = &blendState; - colorTargetState0.writeMask = WGPUColorWriteMask_All; - // color target states - WGPUColorTargetState colorTargetStates[] = { - colorTargetState0 - }; - // fragmanet state - WGPUFragmentState fragmentState{}; - fragmentState.nextInChain = nullptr; - fragmentState.module = mShaderModule; - fragmentState.entryPoint = "fs_main"; - fragmentState.constantCount = 0; - fragmentState.constants = nullptr; - fragmentState.targetCount = 1; - fragmentState.targets = colorTargetStates; // render target index - - // render pipeline descriptor - WGPURenderPipelineDescriptor renderPipelineDesc{}; - renderPipelineDesc.nextInChain = nullptr; - renderPipelineDesc.label = "Render pipeline pipeline stroke"; - // renderPipelineDesc.layout - renderPipelineDesc.layout = mPipelineLayout; - // renderPipelineDesc.vertex - renderPipelineDesc.vertex.nextInChain = nullptr; - renderPipelineDesc.vertex.module = mShaderModule; - renderPipelineDesc.vertex.entryPoint = "vs_main"; - renderPipelineDesc.vertex.constantCount = 0; - renderPipelineDesc.vertex.constants = nullptr; - renderPipelineDesc.vertex.bufferCount = 1; - renderPipelineDesc.vertex.buffers = &vertexBufferLayout; // buffer index - // renderPipelineDesc.primitive - renderPipelineDesc.primitive.nextInChain = nullptr; - renderPipelineDesc.primitive.topology = WGPUPrimitiveTopology_TriangleList; - renderPipelineDesc.primitive.stripIndexFormat = WGPUIndexFormat_Undefined; - renderPipelineDesc.primitive.frontFace = WGPUFrontFace_CCW; - renderPipelineDesc.primitive.cullMode = WGPUCullMode_None; - // renderPipelineDesc.depthStencil - renderPipelineDesc.depthStencil = &depthStencilState; - // renderPipelineDesc.multisample - renderPipelineDesc.multisample.nextInChain = nullptr; - renderPipelineDesc.multisample.count = 1; - renderPipelineDesc.multisample.mask = 0xFFFFFFFF; - renderPipelineDesc.multisample.alphaToCoverageEnabled = false; - // renderPipelineDesc.fragment - renderPipelineDesc.fragment = &fragmentState; - mRenderPipeline = wgpuDeviceCreateRenderPipeline(device, &renderPipelineDesc); - assert(mRenderPipeline); -} - -void WgPipelineStroke::release() { - wgpuRenderPipelineRelease(mRenderPipeline); - wgpuShaderModuleRelease(mShaderModule); - wgpuPipelineLayoutRelease(mPipelineLayout); - wgpuBindGroupLayoutRelease(mBindGroupLayout); -} diff --git a/src/renderer/wg_engine/tvgWgPipelineStroke.h b/src/renderer/wg_engine/tvgWgPipelineStroke.h deleted file mode 100644 index 83e90f90..00000000 --- a/src/renderer/wg_engine/tvgWgPipelineStroke.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2023 the ThorVG project. All rights reserved. - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef _TVG_WG_PIPELINE_STROKE_H_ -#define _TVG_WG_PIPELINE_STROKE_H_ - -#include "tvgWgPipelineBase.h" - -class WgPipelineStroke; - -struct WgPipelineDataStroke: WgPipelineData {}; - -class WgPipelineBindGroupStroke: public WgPipelineBindGroup { -public: - void initialize(WGPUDevice device, WgPipelineStroke& pipelinePipelineStroke); - void release(); - - void update(WGPUQueue mQueue, WgPipelineDataStroke& pipelineDataSolid); -}; - -class WgPipelineStroke: public WgPipelineBase { -public: - void initialize(WGPUDevice device) override; - void release() override; -}; - -#endif // _TVG_WG_PIPELINE_STROKE_H_ diff --git a/src/renderer/wg_engine/tvgWgPipelines.cpp b/src/renderer/wg_engine/tvgWgPipelines.cpp new file mode 100644 index 00000000..0903dc82 --- /dev/null +++ b/src/renderer/wg_engine/tvgWgPipelines.cpp @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "tvgWgPipelines.h" +#include "tvgWgShaderSrc.h" + +#define ARRAY_ELEMENTS_COUNT(arr) sizeof(arr)/sizeof(arr[0]) + +void WgPipelineFillShape::initialize(WGPUDevice device) { + // vertex attributes settings + WGPUVertexAttribute vertexAttributesPos = { WGPUVertexFormat_Float32x2, sizeof(float) * 0, 0 }; + WGPUVertexBufferLayout vertexBufferLayouts[] = { + makeVertexBufferLayout(&vertexAttributesPos, 1, sizeof(float) * 2) + }; + + // bind groups + WGPUBindGroupLayout bindGroupLayouts[] = { + WgBindGroupCanvas::getLayout(device), + WgBindGroupPaint::getLayout(device) + }; + + // stencil function + WGPUCompareFunction stencilFuncion = WGPUCompareFunction_Always; + WGPUStencilOperation stencilOperation = WGPUStencilOperation_Invert; + + // sheder source and labels + const char* shaderSource = cShaderSource_PipelineFill; + const char* shaderLabel = "The shader fill"; + const char* pipelineLabel = "The render pipeline fill shape"; + + // allocate all pipeline handles + allocate( + device, + vertexBufferLayouts, ARRAY_ELEMENTS_COUNT(vertexBufferLayouts), + bindGroupLayouts, ARRAY_ELEMENTS_COUNT(bindGroupLayouts), + stencilFuncion, stencilOperation, + shaderSource, shaderLabel, pipelineLabel); +}; + +void WgPipelineFillStroke::initialize(WGPUDevice device) { + // vertex and buffers settings + WGPUVertexAttribute vertexAttributesPos = { WGPUVertexFormat_Float32x2, sizeof(float) * 0, 0 }; + WGPUVertexBufferLayout vertexBufferLayouts[] = { + makeVertexBufferLayout(&vertexAttributesPos, 1, sizeof(float) * 2) + }; + + // bind groups and layouts + WGPUBindGroupLayout bindGroupLayouts[] = { + WgBindGroupCanvas::getLayout(device), + WgBindGroupPaint::getLayout(device) + }; + + // stencil function + WGPUCompareFunction stencilFuncion = WGPUCompareFunction_Always; + WGPUStencilOperation stencilOperation = WGPUStencilOperation_Replace; + + // sheder source and labels + const char* shaderSource = cShaderSource_PipelineFill; + const char* shaderLabel = "The shader fill"; + const char* pipelineLabel = "The render pipeline fill stroke"; + + // allocate all pipeline handles + allocate( + device, + vertexBufferLayouts, ARRAY_ELEMENTS_COUNT(vertexBufferLayouts), + bindGroupLayouts, ARRAY_ELEMENTS_COUNT(bindGroupLayouts), + stencilFuncion, stencilOperation, + shaderSource, shaderLabel, pipelineLabel); +}; + +void WgPipelineSolid::initialize(WGPUDevice device) { + // vertex and buffers settings + WGPUVertexAttribute vertexAttributesPos = { WGPUVertexFormat_Float32x2, sizeof(float) * 0, 0 }; + WGPUVertexBufferLayout vertexBufferLayouts[] = { + makeVertexBufferLayout(&vertexAttributesPos, 1, sizeof(float) * 2) + }; + + // bind groups and layouts + WGPUBindGroupLayout bindGroupLayouts[] = { + WgBindGroupCanvas::getLayout(device), + WgBindGroupPaint::getLayout(device), + WgBindGroupSolidColor::getLayout(device) + }; + + // stencil function + WGPUCompareFunction stencilFuncion = WGPUCompareFunction_NotEqual; + WGPUStencilOperation stencilOperation = WGPUStencilOperation_Zero; + + // sheder source and labels + const char* shaderSource = cShaderSource_PipelineSolid; + const char* shaderLabel = "The shader solid color"; + const char* pipelineLabel = "The render pipeline solid color"; + + // allocate all pipeline handles + allocate( + device, + vertexBufferLayouts, ARRAY_ELEMENTS_COUNT(vertexBufferLayouts), + bindGroupLayouts, ARRAY_ELEMENTS_COUNT(bindGroupLayouts), + stencilFuncion, stencilOperation, + shaderSource, shaderLabel, pipelineLabel); +}; + +void WgPipelineLinear::initialize(WGPUDevice device) { + // vertex and buffers settings + WGPUVertexAttribute vertexAttributesPos = { WGPUVertexFormat_Float32x2, sizeof(float) * 0, 0 }; + WGPUVertexBufferLayout vertexBufferLayouts[] = { + makeVertexBufferLayout(&vertexAttributesPos, 1, sizeof(float) * 2) + }; + + // bind groups and layouts + WGPUBindGroupLayout bindGroupLayouts[] = { + WgBindGroupCanvas::getLayout(device), + WgBindGroupPaint::getLayout(device), + WgBindGroupLinearGradient::getLayout(device) + }; + + // stencil function + WGPUCompareFunction stencilFuncion = WGPUCompareFunction_NotEqual; + WGPUStencilOperation stencilOperation = WGPUStencilOperation_Zero; + + // sheder source and labels + const char* shaderSource = cShaderSource_PipelineLinear; + const char* shaderLabel = "The shader linear gradient"; + const char* pipelineLabel = "The render pipeline linear gradient"; + + // allocate all pipeline handles + allocate( + device, + vertexBufferLayouts, ARRAY_ELEMENTS_COUNT(vertexBufferLayouts), + bindGroupLayouts, ARRAY_ELEMENTS_COUNT(bindGroupLayouts), + stencilFuncion, stencilOperation, + shaderSource, shaderLabel, pipelineLabel); +}; + +void WgPipelineRadial::initialize(WGPUDevice device) { + // vertex and buffers settings + WGPUVertexAttribute vertexAttributesPos = { WGPUVertexFormat_Float32x2, sizeof(float) * 0, 0 }; + WGPUVertexBufferLayout vertexBufferLayouts[] = { + makeVertexBufferLayout(&vertexAttributesPos, 1, sizeof(float) * 2) + }; + + // bind groups and layouts + WGPUBindGroupLayout bindGroupLayouts[] = { + WgBindGroupCanvas::getLayout(device), + WgBindGroupPaint::getLayout(device), + WgBindGroupRadialGradient::getLayout(device) + }; + + // stencil function + WGPUCompareFunction stencilFuncion = WGPUCompareFunction_NotEqual; + WGPUStencilOperation stencilOperation = WGPUStencilOperation_Zero; + + // sheder source and labels + const char* shaderSource = cShaderSource_PipelineRadial; + const char* shaderLabel = "The shader radial gradient"; + const char* pipelineLabel = "The render pipeline radial gradient"; + + // allocate all pipeline handles + allocate( + device, + vertexBufferLayouts, ARRAY_ELEMENTS_COUNT(vertexBufferLayouts), + bindGroupLayouts, ARRAY_ELEMENTS_COUNT(bindGroupLayouts), + stencilFuncion, stencilOperation, + shaderSource, shaderLabel, pipelineLabel); +}; + +void WgPipelineImage::initialize(WGPUDevice device) { + // vertex and buffers settings + WGPUVertexAttribute vertexAttributesPos = { WGPUVertexFormat_Float32x2, sizeof(float) * 0, 0 }; + WGPUVertexAttribute vertexAttributesTex = { WGPUVertexFormat_Float32x2, sizeof(float) * 0, 1 }; + WGPUVertexBufferLayout vertexBufferLayouts[] = { + makeVertexBufferLayout(&vertexAttributesPos, 1, sizeof(float) * 2), + makeVertexBufferLayout(&vertexAttributesTex, 1, sizeof(float) * 2) + }; + + // bind groups and layouts + WGPUBindGroupLayout bindGroupLayouts[] = { + WgBindGroupCanvas::getLayout(device), + WgBindGroupPaint::getLayout(device), + WgBindGroupPicture::getLayout(device) + }; + + // stencil function + WGPUCompareFunction stencilFuncion = WGPUCompareFunction_Always; + WGPUStencilOperation stencilOperation = WGPUStencilOperation_Zero; + + // sheder source and labels + const char* shaderSource = cShaderSource_PipelineImage; + const char* shaderLabel = "The shader image"; + const char* pipelineLabel = "The render pipeline image"; + + // allocate all pipeline handles + allocate( + device, + vertexBufferLayouts, ARRAY_ELEMENTS_COUNT(vertexBufferLayouts), + bindGroupLayouts, ARRAY_ELEMENTS_COUNT(bindGroupLayouts), + stencilFuncion, stencilOperation, + shaderSource, shaderLabel, pipelineLabel); +}; + +//************************************************************************ +// pipelines +//************************************************************************ + +void WgPipelines::initialize(WGPUDevice device) { + mPipelineFillShape.initialize(device); + mPipelineFillStroke.initialize(device); + mPipelineSolid.initialize(device); + mPipelineLinear.initialize(device); + mPipelineRadial.initialize(device); + mPipelineImage.initialize(device); +} + +void WgPipelines::release() { + WgBindGroupCompose::releaseLayout(); + WgBindGroupPicture::releaseLayout(); + WgBindGroupRadialGradient::releaseLayout(); + WgBindGroupLinearGradient::releaseLayout(); + WgBindGroupSolidColor::releaseLayout(); + WgBindGroupCanvas::releaseLayout(); + mPipelineImage.release(); + mPipelineRadial.release(); + mPipelineLinear.release(); + mPipelineSolid.release(); + mPipelineFillStroke.release(); + mPipelineFillShape.release(); +} \ No newline at end of file diff --git a/src/renderer/wg_engine/tvgWgPipelines.h b/src/renderer/wg_engine/tvgWgPipelines.h new file mode 100644 index 00000000..0cd43efc --- /dev/null +++ b/src/renderer/wg_engine/tvgWgPipelines.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef _TVG_WG_PIPELINES_H_ +#define _TVG_WG_PIPELINES_H_ + +#include "tvgWgBindGroups.h" + +struct WgPipelineFillShape: public WgPipeline { + void initialize(WGPUDevice device) override; + void use(WGPURenderPassEncoder encoder, + WgBindGroupCanvas& groupCanvas, + WgBindGroupPaint& groupPaint) { + set(encoder); + groupCanvas.set(encoder, 0); + groupPaint.set(encoder, 1); + } +}; + +struct WgPipelineFillStroke: public WgPipeline { + void initialize(WGPUDevice device) override; + void use(WGPURenderPassEncoder encoder, + WgBindGroupCanvas& groupCanvas, + WgBindGroupPaint& groupPaint) { + set(encoder); + groupCanvas.set(encoder, 0); + groupPaint.set(encoder, 1); + } +}; + +struct WgPipelineSolid: public WgPipeline { + void initialize(WGPUDevice device) override; + void use(WGPURenderPassEncoder encoder, + WgBindGroupCanvas& groupCanvas, + WgBindGroupPaint& groupPaint, + WgBindGroupSolidColor& groupSolid) { + set(encoder); + groupCanvas.set(encoder, 0); + groupPaint.set(encoder, 1); + groupSolid.set(encoder, 2); + } +}; + +struct WgPipelineLinear: public WgPipeline { + void initialize(WGPUDevice device) override; + void use(WGPURenderPassEncoder encoder, + WgBindGroupCanvas& groupCanvas, + WgBindGroupPaint& groupPaint, + WgBindGroupLinearGradient& groupLinear) { + set(encoder); + groupCanvas.set(encoder, 0); + groupPaint.set(encoder, 1); + groupLinear.set(encoder, 2); + } +}; + +struct WgPipelineRadial: public WgPipeline { + void initialize(WGPUDevice device) override; + void use(WGPURenderPassEncoder encoder, + WgBindGroupCanvas& groupCanvas, + WgBindGroupPaint& groupPaint, + WgBindGroupRadialGradient& groupRadial) { + set(encoder); + groupCanvas.set(encoder, 0); + groupPaint.set(encoder, 1); + groupRadial.set(encoder, 2); + } +}; + +struct WgPipelineImage: public WgPipeline { + void initialize(WGPUDevice device) override; + void use(WGPURenderPassEncoder encoder, + WgBindGroupCanvas& groupCanvas, + WgBindGroupPaint& groupPaint, + WgBindGroupPicture& groupPicture) { + set(encoder); + groupCanvas.set(encoder, 0); + groupPaint.set(encoder, 1); + groupPicture.set(encoder, 2); + } +}; + +struct WgPipelines { + WgPipelineFillShape mPipelineFillShape; + WgPipelineFillStroke mPipelineFillStroke; + WgPipelineSolid mPipelineSolid; + WgPipelineLinear mPipelineLinear; + WgPipelineRadial mPipelineRadial; + WgPipelineImage mPipelineImage; + + void initialize(WGPUDevice device); + void release(); +}; + +#endif // _TVG_WG_PIPELINES_H_ diff --git a/src/renderer/wg_engine/tvgWgRenderData.cpp b/src/renderer/wg_engine/tvgWgRenderData.cpp index fff7a5ec..6f919b96 100644 --- a/src/renderer/wg_engine/tvgWgRenderData.cpp +++ b/src/renderer/wg_engine/tvgWgRenderData.cpp @@ -108,51 +108,121 @@ void WgGeometryData::release() { } } +//*********************************************************************** +// WgImageData +//*********************************************************************** + +void WgImageData::update(WGPUDevice device, WGPUQueue queue, Surface* surface) { + release(); + // sampler descriptor + WGPUSamplerDescriptor samplerDesc{}; + samplerDesc.nextInChain = nullptr; + samplerDesc.label = "The shape sampler"; + samplerDesc.addressModeU = WGPUAddressMode_ClampToEdge; + samplerDesc.addressModeV = WGPUAddressMode_ClampToEdge; + samplerDesc.addressModeW = WGPUAddressMode_ClampToEdge; + samplerDesc.magFilter = WGPUFilterMode_Nearest; + samplerDesc.minFilter = WGPUFilterMode_Nearest; + samplerDesc.mipmapFilter = WGPUMipmapFilterMode_Nearest; + samplerDesc.lodMinClamp = 0.0f; + samplerDesc.lodMaxClamp = 32.0f; + samplerDesc.compare = WGPUCompareFunction_Undefined; + samplerDesc.maxAnisotropy = 1; + mSampler = wgpuDeviceCreateSampler(device, &samplerDesc); + assert(mSampler); + // texture descriptor + WGPUTextureDescriptor textureDesc{}; + textureDesc.nextInChain = nullptr; + textureDesc.label = "The shape texture"; + textureDesc.usage = WGPUTextureUsage_TextureBinding | WGPUTextureUsage_CopyDst; + textureDesc.dimension = WGPUTextureDimension_2D; + textureDesc.size = { surface->w, surface->h, 1 }; + textureDesc.format = WGPUTextureFormat_RGBA8Unorm; + textureDesc.mipLevelCount = 1; + textureDesc.sampleCount = 1; + textureDesc.viewFormatCount = 0; + textureDesc.viewFormats = nullptr; + mTexture = wgpuDeviceCreateTexture(device, &textureDesc); + assert(mTexture); + // texture view descriptor + WGPUTextureViewDescriptor textureViewDesc{}; + textureViewDesc.nextInChain = nullptr; + textureViewDesc.label = "The shape texture view"; + textureViewDesc.format = WGPUTextureFormat_RGBA8Unorm; + textureViewDesc.dimension = WGPUTextureViewDimension_2D; + textureViewDesc.baseMipLevel = 0; + textureViewDesc.mipLevelCount = 1; + textureViewDesc.baseArrayLayer = 0; + textureViewDesc.arrayLayerCount = 1; + textureViewDesc.aspect = WGPUTextureAspect_All; + mTextureView = wgpuTextureCreateView(mTexture, &textureViewDesc); + assert(mTextureView); + // update texture data + WGPUImageCopyTexture imageCopyTexture{}; + imageCopyTexture.nextInChain = nullptr; + imageCopyTexture.texture = mTexture; + imageCopyTexture.mipLevel = 0; + imageCopyTexture.origin = { 0, 0, 0 }; + imageCopyTexture.aspect = WGPUTextureAspect_All; + WGPUTextureDataLayout textureDataLayout{}; + textureDataLayout.nextInChain = nullptr; + textureDataLayout.offset = 0; + textureDataLayout.bytesPerRow = 4 * surface->w; + textureDataLayout.rowsPerImage = surface->h; + WGPUExtent3D writeSize{}; + writeSize.width = surface->w; + writeSize.height = surface->h; + writeSize.depthOrArrayLayers = 1; + wgpuQueueWriteTexture(queue, &imageCopyTexture, surface->data, 4 * surface->w * surface->h, &textureDataLayout, &writeSize); +} + +void WgImageData::release() { + if (mTexture) { + wgpuTextureDestroy(mTexture); + wgpuTextureRelease(mTexture); + mTexture = nullptr; + } + if (mTextureView) { + wgpuTextureViewRelease(mTextureView); + mTextureView = nullptr; + } + if (mSampler) { + wgpuSamplerRelease(mSampler); + mSampler = nullptr; + } +} + //*********************************************************************** // WgRenderDataShapeSettings //*********************************************************************** -void WgRenderDataShapeSettings::update(WGPUQueue queue, const Fill* fill, const RenderUpdateFlag flags, - const RenderTransform* transform, const float* viewMatrix, const uint8_t* color, - WgPipelineLinear& linear, WgPipelineRadial& radial, WgPipelineSolid& solid) +void WgRenderDataShapeSettings::update(WGPUDevice device, WGPUQueue queue, + const Fill* fill, const uint8_t* color, + const RenderUpdateFlag flags) { // setup fill properties - if ((flags & (RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform)) && fill) { + if ((flags & (RenderUpdateFlag::Gradient)) && fill) { // setup linear fill properties if (fill->identifier() == TVG_CLASS_ID_LINEAR) { - WgPipelineDataLinear brushDataLinear{}; - brushDataLinear.updateMatrix(viewMatrix, transform); - brushDataLinear.updateGradient((LinearGradient*)fill); - mPipelineBindGroupLinear.update(queue, brushDataLinear); - - mPipelineBindGroup = &mPipelineBindGroupLinear; - mPipelineBase = &linear; - } // setup radial fill properties - else if (fill->identifier() == TVG_CLASS_ID_RADIAL) { - WgPipelineDataRadial brushDataRadial{}; - brushDataRadial.updateMatrix(viewMatrix, transform); - brushDataRadial.updateGradient((RadialGradient*)fill); - mPipelineBindGroupRadial.update(queue, brushDataRadial); - - mPipelineBindGroup = &mPipelineBindGroupRadial; - mPipelineBase = &radial; + WgShaderTypeLinearGradient linearGradient((LinearGradient*)fill); + mBindGroupLinear.initialize(device, queue, linearGradient); + mFillType = WgRenderDataShapeFillType::Linear; + } else if (fill->identifier() == TVG_CLASS_ID_RADIAL) { + WgShaderTypeRadialGradient radialGradient((RadialGradient*)fill); + mBindGroupRadial.initialize(device, queue, radialGradient); + mFillType = WgRenderDataShapeFillType::Radial; } - } // setup solid fill properties - else if ((flags & (RenderUpdateFlag::Color | RenderUpdateFlag::Transform)) && !fill) { - WgPipelineDataSolid pipelineDataSolid{}; - pipelineDataSolid.updateMatrix(viewMatrix, transform); - pipelineDataSolid.updateColor(color); - mPipelineBindGroupSolid.update(queue, pipelineDataSolid); - - mPipelineBindGroup = &mPipelineBindGroupSolid; - mPipelineBase = &solid; + } else if ((flags & (RenderUpdateFlag::Color)) && !fill) { + WgShaderTypeSolidColor solidColor(color); + mBindGroupSolid.initialize(device, queue, solidColor); + mFillType = WgRenderDataShapeFillType::Solid; } } void WgRenderDataShapeSettings::release() { - mPipelineBindGroupSolid.release(); - mPipelineBindGroupLinear.release(); - mPipelineBindGroupRadial.release(); + mBindGroupSolid.release(); + mBindGroupLinear.release(); + mBindGroupRadial.release(); } //*********************************************************************** @@ -161,9 +231,11 @@ void WgRenderDataShapeSettings::release() { void WgRenderDataShape::release() { releaseRenderData(); + mImageData.release(); + mBindGroupPaint.release(); mRenderSettingsShape.release(); mRenderSettingsStroke.release(); - mPipelineBindGroupImage.release(); + mBindGroupPicture.release(); } void WgRenderDataShape::releaseRenderData() { @@ -227,6 +299,9 @@ void WgRenderDataShape::tesselate(WGPUDevice device, WGPUQueue queue, Surface* s (float *)vertexList.data, (float *)texCoordsList.data, vertexList.count, indexList.data, indexList.count); mGeometryDataImage.push(geometryData); + + // update image data + mImageData.update(device, queue, surface); } void WgRenderDataShape::tesselate(WGPUDevice device, WGPUQueue queue, const RenderShape& rshape) { @@ -479,4 +554,4 @@ void WgRenderDataShape::strokeSublines(const RenderShape& rshape, Array mGeometryDataShape; Array mGeometryDataStroke; Array mGeometryDataImage; + WgImageData mImageData; + // shader settings + WgBindGroupPaint mBindGroupPaint; WgRenderDataShapeSettings mRenderSettingsShape; WgRenderDataShapeSettings mRenderSettingsStroke; - WgPipelineBindGroupImage mPipelineBindGroupImage; + WgBindGroupPicture mBindGroupPicture; public: WgRenderDataShape() {} diff --git a/src/renderer/wg_engine/tvgWgRenderer.cpp b/src/renderer/wg_engine/tvgWgRenderer.cpp index 5cee42c3..7441778f 100644 --- a/src/renderer/wg_engine/tvgWgRenderer.cpp +++ b/src/renderer/wg_engine/tvgWgRenderer.cpp @@ -103,15 +103,7 @@ void WgRenderer::initialize() { assert(mQueue); // create pipelines - mPipelineEmpty.initialize(mDevice); - mPipelineStroke.initialize(mDevice); - mPipelineSolid.initialize(mDevice); - mPipelineLinear.initialize(mDevice); - mPipelineRadial.initialize(mDevice); - mPipelineImage.initialize(mDevice); - mPipelineBindGroupEmpty.initialize(mDevice, mPipelineEmpty); - mPipelineBindGroupStroke.initialize(mDevice, mPipelineStroke); - mGeometryDataWindow.initialize(mDevice); + mPipelines.initialize(mDevice); } void WgRenderer::release() { @@ -122,15 +114,10 @@ void WgRenderer::release() { if (mStencilTexView) wgpuTextureViewRelease(mStencilTexView); if (mSwapChain) wgpuSwapChainRelease(mSwapChain); if (mSurface) wgpuSurfaceRelease(mSurface); - mGeometryDataWindow.release(); - mPipelineBindGroupStroke.release(); - mPipelineBindGroupEmpty.release(); - mPipelineImage.release(); - mPipelineRadial.release(); - mPipelineLinear.release(); - mPipelineSolid.release(); - mPipelineStroke.release(); - mPipelineEmpty.release(); + mBindGroupCanvasWnd.release(); + mBindGroupPaintWnd.release(); + mGeometryDataWnd.release(); + mPipelines.release(); if (mDevice) { wgpuDeviceDestroy(mDevice); wgpuDeviceRelease(mDevice); @@ -145,31 +132,26 @@ RenderData WgRenderer::prepare(const RenderShape& rshape, RenderData data, const if (!renderDataShape) { renderDataShape = new WgRenderDataShape(); renderDataShape->initialize(mDevice); - renderDataShape->mRenderSettingsShape.mPipelineBindGroupSolid.initialize(mDevice, mPipelineSolid); - renderDataShape->mRenderSettingsShape.mPipelineBindGroupLinear.initialize(mDevice, mPipelineLinear); - renderDataShape->mRenderSettingsShape.mPipelineBindGroupRadial.initialize(mDevice, mPipelineRadial); - renderDataShape->mRenderSettingsStroke.mPipelineBindGroupSolid.initialize(mDevice, mPipelineSolid); - renderDataShape->mRenderSettingsStroke.mPipelineBindGroupLinear.initialize(mDevice, mPipelineLinear); - renderDataShape->mRenderSettingsStroke.mPipelineBindGroupRadial.initialize(mDevice, mPipelineRadial); } - if (flags & (RenderUpdateFlag::Path | RenderUpdateFlag::Stroke)) + // update geometry + if (flags & (RenderUpdateFlag::Path | RenderUpdateFlag::Stroke)) { renderDataShape->releaseRenderData(); - - if (flags & RenderUpdateFlag::Path) renderDataShape->tesselate(mDevice, mQueue, rshape); - - if (flags & RenderUpdateFlag::Stroke) renderDataShape->stroke(mDevice, mQueue, rshape); + } - // setup shape fill properties - renderDataShape->mRenderSettingsShape.update(mQueue, rshape.fill, flags, transform, mViewMatrix, rshape.color, - mPipelineLinear, mPipelineRadial, mPipelineSolid); + // update paint settings + if (flags & (RenderUpdateFlag::Transform | RenderUpdateFlag::Blend)) { + WgShaderTypeMat4x4f modelMat(transform); + WgShaderTypeBlendSettings blendSettings(mTargetSurface.cs); + renderDataShape->mBindGroupPaint.initialize(mDevice, mQueue, modelMat, blendSettings); + } - // setup stroke fill properties + // setup fill settings + renderDataShape->mRenderSettingsShape.update(mDevice, mQueue, rshape.fill, rshape.color, flags); if (rshape.stroke) - renderDataShape->mRenderSettingsStroke.update(mQueue, rshape.stroke->fill, flags, transform, mViewMatrix, rshape.stroke->color, - mPipelineLinear, mPipelineRadial, mPipelineSolid); + renderDataShape->mRenderSettingsStroke.update(mDevice, mQueue, rshape.stroke->fill, rshape.stroke->color, flags); return renderDataShape; } @@ -184,16 +166,25 @@ RenderData WgRenderer::prepare(Surface* surface, const RenderMesh* mesh, RenderD if (!renderDataShape) { renderDataShape = new WgRenderDataShape(); renderDataShape->initialize(mDevice); - renderDataShape->mPipelineBindGroupImage.initialize(mDevice, mPipelineImage, surface); } - if (flags & (RenderUpdateFlag::Color | RenderUpdateFlag::Image | RenderUpdateFlag::Transform)) { - WgPipelineDataImage pipelineDataImage{}; - pipelineDataImage.updateMatrix(mViewMatrix, transform); - pipelineDataImage.updateFormat(surface->cs); - pipelineDataImage.updateOpacity(opacity); - renderDataShape->mPipelineBindGroupImage.update(mQueue, pipelineDataImage, surface); + + // update paint settings + if (flags & (RenderUpdateFlag::Transform | RenderUpdateFlag::Blend)) { + WgShaderTypeMat4x4f modelMat(transform); + WgShaderTypeBlendSettings blendSettings(surface->cs); + renderDataShape->mBindGroupPaint.initialize(mDevice, mQueue, modelMat, blendSettings); + } + + // update image data + if (flags & (RenderUpdateFlag::Path | RenderUpdateFlag::Image)) { + renderDataShape->releaseRenderData(); renderDataShape->tesselate(mDevice, mQueue, surface, mesh); + renderDataShape->mBindGroupPicture.initialize( + mDevice, mQueue, + renderDataShape->mImageData.mSampler, + renderDataShape->mImageData.mTextureView); } + return renderDataShape; } @@ -274,7 +265,12 @@ bool WgRenderer::sync() { WGPURenderPassColorAttachment colorAttachment{}; colorAttachment.view = backBufferView; colorAttachment.resolveTarget = nullptr; - colorAttachment.loadOp = WGPULoadOp_Clear; + if (mClearBuffer) { + colorAttachment.loadOp = WGPULoadOp_Clear; + colorAttachment.clearValue = {0, 0, 0, 0}; + } else { + colorAttachment.loadOp = WGPULoadOp_Load; + } colorAttachment.storeOp = WGPUStoreOp_Store; colorAttachment.clearValue = { 0.0f, 0.0f, 0.0f, 1.0 }; // render pass descriptor @@ -298,39 +294,50 @@ bool WgRenderer::sync() { wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0); for (uint32_t j = 0; j < renderData->mGeometryDataShape.count; j++) { // draw to stencil (first pass) - mPipelineEmpty.set(renderPassEncoder); - mPipelineBindGroupEmpty.bind(renderPassEncoder, 0); + mPipelines.mPipelineFillShape.use(renderPassEncoder, mBindGroupCanvasWnd, renderData->mBindGroupPaint); renderData->mGeometryDataShape[j]->draw(renderPassEncoder); - // fill shape (second pass) - renderData->mRenderSettingsShape.mPipelineBase->set(renderPassEncoder); - renderData->mRenderSettingsShape.mPipelineBindGroup->bind(renderPassEncoder, 0); - mGeometryDataWindow.draw(renderPassEncoder); + WgRenderDataShapeSettings& settings = renderData->mRenderSettingsShape; + if (settings.mFillType == WgRenderDataShapeFillType::Solid) + mPipelines.mPipelineSolid.use(renderPassEncoder, mBindGroupCanvasWnd, mBindGroupPaintWnd, settings.mBindGroupSolid); + else if (settings.mFillType == WgRenderDataShapeFillType::Linear) + mPipelines.mPipelineLinear.use(renderPassEncoder, mBindGroupCanvasWnd, mBindGroupPaintWnd, settings.mBindGroupLinear); + else if (settings.mFillType == WgRenderDataShapeFillType::Radial) + mPipelines.mPipelineRadial.use(renderPassEncoder, mBindGroupCanvasWnd, mBindGroupPaintWnd, settings.mBindGroupRadial); + mGeometryDataWnd.draw(renderPassEncoder); } // draw stroke geometry - if (renderData->mRenderSettingsStroke.mPipelineBase) { + if (renderData->mGeometryDataStroke.count > 0) { // draw strokes to stencil (first pass) wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 255); for (uint32_t j = 0; j < renderData->mGeometryDataStroke.count; j++) { - mPipelineStroke.set(renderPassEncoder); - mPipelineBindGroupStroke.bind(renderPassEncoder, 0); + mPipelines.mPipelineFillStroke.use(renderPassEncoder, mBindGroupCanvasWnd, renderData->mBindGroupPaint); renderData->mGeometryDataStroke[j]->draw(renderPassEncoder); } - - // fill strokes (second pass) + // fill shape (second pass) wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0); - renderData->mRenderSettingsStroke.mPipelineBase->set(renderPassEncoder); - renderData->mRenderSettingsStroke.mPipelineBindGroup->bind(renderPassEncoder, 0); - mGeometryDataWindow.draw(renderPassEncoder); + WgRenderDataShapeSettings& settings = renderData->mRenderSettingsStroke; + if (settings.mFillType == WgRenderDataShapeFillType::Solid) + mPipelines.mPipelineSolid.use(renderPassEncoder, mBindGroupCanvasWnd, mBindGroupPaintWnd, settings.mBindGroupSolid); + else if (settings.mFillType == WgRenderDataShapeFillType::Linear) + mPipelines.mPipelineLinear.use(renderPassEncoder, mBindGroupCanvasWnd, mBindGroupPaintWnd, settings.mBindGroupLinear); + else if (settings.mFillType == WgRenderDataShapeFillType::Radial) + mPipelines.mPipelineRadial.use(renderPassEncoder, mBindGroupCanvasWnd, mBindGroupPaintWnd, settings.mBindGroupRadial); + mGeometryDataWnd.draw(renderPassEncoder); } - // draw image geometry - wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0); - for (uint32_t j = 0; j < renderData->mGeometryDataImage.count; j++) { - mPipelineImage.set(renderPassEncoder); - renderData->mPipelineBindGroupImage.bind(renderPassEncoder, 0); - renderData->mGeometryDataImage[j]->drawImage(renderPassEncoder); + // render image + if (renderData->mGeometryDataImage.count > 0) { + wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0); + for (uint32_t j = 0; j < renderData->mGeometryDataImage.count; j++) { + mPipelines.mPipelineImage.use( + renderPassEncoder, + mBindGroupCanvasWnd, + renderData->mBindGroupPaint, + renderData->mBindGroupPicture); + renderData->mGeometryDataImage[j]->drawImage(renderPassEncoder); + } } } } @@ -439,22 +446,16 @@ bool WgRenderer::target(void* window, uint32_t w, uint32_t h) { mStencilTexView = wgpuTextureCreateView(mStencilTex, &textureViewDesc); assert(mStencilTexView); + // initialize window binding groups + WgShaderTypeMat4x4f viewMat(w, h); + mBindGroupCanvasWnd.initialize(mDevice, mQueue, viewMat); + WgShaderTypeMat4x4f modelMat; + WgShaderTypeBlendSettings blendSettings(ColorSpace::ABGR8888); + mBindGroupPaintWnd.initialize(mDevice, mQueue, modelMat, blendSettings); // update pipeline geometry data WgVertexList wnd; - wnd.appendRect( - WgPoint(0.0f, 0.0f), WgPoint(w, 0.0f), - WgPoint(0.0f, h), WgPoint(w, h) - ); - // update render data pipeline empty and stroke - mGeometryDataWindow.update(mDevice, mQueue, &wnd); - // update bind group pipeline empty - WgPipelineDataEmpty pipelineDataEmpty{}; - pipelineDataEmpty.updateMatrix(mViewMatrix, nullptr); - mPipelineBindGroupEmpty.update(mQueue, pipelineDataEmpty); - // update bind group pipeline stroke - WgPipelineDataStroke pipelineDataStroke{}; - pipelineDataStroke.updateMatrix(mViewMatrix, nullptr); - mPipelineBindGroupStroke.update(mQueue, pipelineDataStroke); + wnd.appendRect(WgPoint(0.0f, 0.0f), WgPoint(w, 0.0f), WgPoint(0.0f, h), WgPoint(w, h)); + mGeometryDataWnd.update(mDevice, mQueue, &wnd); return true; } diff --git a/src/renderer/wg_engine/tvgWgRenderer.h b/src/renderer/wg_engine/tvgWgRenderer.h index 93cd880d..a0a521e0 100644 --- a/src/renderer/wg_engine/tvgWgRenderer.h +++ b/src/renderer/wg_engine/tvgWgRenderer.h @@ -23,8 +23,6 @@ #ifndef _TVG_WG_RENDERER_H_ #define _TVG_WG_RENDERER_H_ -#include "tvgWgPipelineEmpty.h" -#include "tvgWgPipelineStroke.h" #include "tvgWgRenderData.h" class WgRenderer : public RenderMethod @@ -77,16 +75,13 @@ private: WGPUSwapChain mSwapChain{}; WGPUTexture mStencilTex{}; WGPUTextureView mStencilTexView{}; + WgBindGroupCanvas mBindGroupCanvasWnd; + WgBindGroupPaint mBindGroupPaintWnd; + WgGeometryData mGeometryDataWnd; private: - WgPipelineEmpty mPipelineEmpty; - WgPipelineStroke mPipelineStroke; - WgPipelineSolid mPipelineSolid; - WgPipelineLinear mPipelineLinear; - WgPipelineRadial mPipelineRadial; - WgPipelineImage mPipelineImage; - WgGeometryData mGeometryDataWindow; - WgPipelineBindGroupEmpty mPipelineBindGroupEmpty; - WgPipelineBindGroupStroke mPipelineBindGroupStroke; + WgPipelines mPipelines; + + bool mClearBuffer; }; #endif /* _TVG_WG_RENDERER_H_ */ diff --git a/src/renderer/wg_engine/tvgWgShaderSrc.cpp b/src/renderer/wg_engine/tvgWgShaderSrc.cpp index 5978ad80..6b359451 100644 --- a/src/renderer/wg_engine/tvgWgShaderSrc.cpp +++ b/src/renderer/wg_engine/tvgWgShaderSrc.cpp @@ -24,18 +24,21 @@ #include //************************************************************************ -// cShaderSource_PipelineEmpty +// shader pipeline fill //************************************************************************ -const char* cShaderSource_PipelineEmpty = R"( +const char* cShaderSource_PipelineFill = R"( // vertex input struct VertexInput { @location(0) position: vec2f }; -// Matrix -struct Matrix { - transform: mat4x4f +// BlendSettigs +struct BlendSettigs { + format : u32, // ColorSpace + dummy0 : f32, + dummy1 : f32, + dummy2 : f32 }; // vertex output @@ -43,24 +46,27 @@ struct VertexOutput { @builtin(position) position: vec4f }; -// uMatrix -@group(0) @binding(0) var uMatrix: Matrix; +// uniforms +@group(0) @binding(0) var uViewMat : mat4x4f; +@group(1) @binding(0) var uModelMat : mat4x4f; +@group(1) @binding(1) var uBlendSettigs : BlendSettigs; @vertex fn vs_main(in: VertexInput) -> VertexOutput { // fill output var out: VertexOutput; - out.position = uMatrix.transform * vec4f(in.position.xy, 0.0, 1.0); + out.position = uViewMat * uModelMat * vec4f(in.position.xy, 0.0, 1.0); return out; } @fragment fn fs_main(in: VertexOutput) -> void { // nothing to draw, just stencil value -})"; +} +)"; //************************************************************************ -// cShaderSource_PipelineSolid +// shader pipeline solid //************************************************************************ const char* cShaderSource_PipelineSolid = R"( @@ -69,14 +75,12 @@ struct VertexInput { @location(0) position: vec2f }; -// Matrix -struct Matrix { - transform: mat4x4f -}; - -// ColorInfo -struct ColorInfo { - color: vec4f +// BlendSettigs +struct BlendSettigs { + format : u32, // ColorSpace + dummy0 : f32, + dummy1 : f32, + dummy2 : f32 }; // vertex output @@ -84,27 +88,34 @@ struct VertexOutput { @builtin(position) position: vec4f }; -// uMatrix -@group(0) @binding(0) var uMatrix: Matrix; -// uColorInfo -@group(0) @binding(1) var uColorInfo: ColorInfo; +// uniforms +@group(0) @binding(0) var uViewMat : mat4x4f; +@group(1) @binding(0) var uModelMat : mat4x4f; +@group(1) @binding(1) var uBlendSettigs : BlendSettigs; +@group(2) @binding(0) var uSolidColor : vec4f; @vertex fn vs_main(in: VertexInput) -> VertexOutput { // fill output var out: VertexOutput; - out.position = uMatrix.transform * vec4f(in.position.xy, 0.0, 1.0); - //out.position = vec4f(in.position.xy, 0.0, 1.0); + out.position = uViewMat * uModelMat * vec4f(in.position.xy, 0.0, 1.0); return out; } @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4f { - return uColorInfo.color; -})"; + // resulting color + var color = vec4(1.0); + + // get color + color = uSolidColor; + + return vec4f(color.rgb, color.a); +} +)"; //************************************************************************ -// cShaderSource_PipelineLinear +// shader pipeline linear //************************************************************************ const char* cShaderSource_PipelineLinear = R"( @@ -113,46 +124,53 @@ struct VertexInput { @location(0) position: vec2f }; -// Matrix -struct Matrix { - transform: mat4x4f +// BlendSettigs +struct BlendSettigs { + format : u32, // ColorSpace + dummy0 : f32, + dummy1 : f32, + dummy2 : f32 }; -// GradientInfo -const MAX_STOP_COUNT = 4; -struct GradientInfo { +// LinearGradient +const MAX_LINEAR_GRADIENT_STOPS = 4; +struct LinearGradient { nStops : vec4f, gradStartPos : vec2f, gradEndPos : vec2f, stopPoints : vec4f, - stopColors : array + stopColors : array }; // vertex output struct VertexOutput { - @builtin(position) position: vec4f, - @location(0) vScreenCoord: vec2f + @builtin(position) position : vec4f, + @location(0) vScreenCoord : vec2f }; -// uMatrix -@group(0) @binding(0) var uMatrix: Matrix; -// uGradientInfo -@group(0) @binding(1) var uGradientInfo: GradientInfo; +// uniforms +@group(0) @binding(0) var uViewMat : mat4x4f; +@group(1) @binding(0) var uModelMat : mat4x4f; +@group(1) @binding(1) var uBlendSettigs : BlendSettigs; +@group(2) @binding(0) var uLinearGradient : LinearGradient; @vertex fn vs_main(in: VertexInput) -> VertexOutput { // fill output var out: VertexOutput; - out.position = uMatrix.transform * vec4f(in.position.xy, 0.0, 1.0); + out.position = uViewMat * uModelMat * vec4f(in.position.xy, 0.0, 1.0); out.vScreenCoord = in.position.xy; return out; } @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4f { + // resulting color + var color = vec4(1.0); + let pos: vec2f = in.vScreenCoord; - let st: vec2f = uGradientInfo.gradStartPos; - let ed: vec2f = uGradientInfo.gradEndPos; + let st: vec2f = uLinearGradient.gradStartPos; + let ed: vec2f = uLinearGradient.gradEndPos; let ba: vec2f = ed - st; @@ -160,36 +178,34 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4f { let t: f32 = clamp(dot(pos - st, ba) / dot(ba, ba), 0.0, 1.0); // get stops count - let last: i32 = i32(uGradientInfo.nStops[0]) - 1; - - // resulting color - var color = vec4(1.0); + let last: i32 = i32(uLinearGradient.nStops[0]) - 1; // closer than first stop - if (t <= uGradientInfo.stopPoints[0]) { - color = uGradientInfo.stopColors[0]; + if (t <= uLinearGradient.stopPoints[0]) { + color = uLinearGradient.stopColors[0]; } // further than last stop - if (t >= uGradientInfo.stopPoints[last]) { - color = uGradientInfo.stopColors[last]; + if (t >= uLinearGradient.stopPoints[last]) { + color = uLinearGradient.stopColors[last]; } // look in the middle for (var i = 0i; i < last; i++) { - let strt = uGradientInfo.stopPoints[i]; - let stop = uGradientInfo.stopPoints[i+1]; + let strt = uLinearGradient.stopPoints[i]; + let stop = uLinearGradient.stopPoints[i+1]; if ((t > strt) && (t < stop)) { let step: f32 = (t - strt) / (stop - strt); - color = mix(uGradientInfo.stopColors[i], uGradientInfo.stopColors[i+1], step); + color = mix(uLinearGradient.stopColors[i], uLinearGradient.stopColors[i+1], step); } } - return color; -})"; + return vec4f(color.rgb, color.a); +} +)"; //************************************************************************ -// cShaderSource_PipelineRadial +// shader pipeline radial //************************************************************************ const char* cShaderSource_PipelineRadial = R"( @@ -198,125 +214,125 @@ struct VertexInput { @location(0) position: vec2f }; -// Matrix -struct Matrix { - transform: mat4x4f +// BlendSettigs +struct BlendSettigs { + format : u32, // ColorSpace + dummy0 : f32, + dummy1 : f32, + dummy2 : f32 }; -// GradientInfo -const MAX_STOP_COUNT = 4; -struct GradientInfo { +// RadialGradient +const MAX_RADIAL_GRADIENT_STOPS = 4; +struct RadialGradient { nStops : vec4f, centerPos : vec2f, radius : vec2f, stopPoints : vec4f, - stopColors : array + stopColors : array }; // vertex output struct VertexOutput { - @builtin(position) position: vec4f, - @location(0) vScreenCoord: vec2f + @builtin(position) position : vec4f, + @location(0) vScreenCoord : vec2f }; -// uMatrix -@group(0) @binding(0) var uMatrix: Matrix; -// uGradientInfo -@group(0) @binding(1) var uGradientInfo: GradientInfo; +// uniforms +@group(0) @binding(0) var uViewMat : mat4x4f; +@group(1) @binding(0) var uModelMat : mat4x4f; +@group(1) @binding(1) var uBlendSettigs : BlendSettigs; +@group(2) @binding(0) var uRadialGradient : RadialGradient; @vertex fn vs_main(in: VertexInput) -> VertexOutput { // fill output var out: VertexOutput; - out.position = uMatrix.transform * vec4f(in.position.xy, 0.0, 1.0); + out.position = uViewMat * uModelMat * vec4f(in.position.xy, 0.0, 1.0); out.vScreenCoord = in.position.xy; return out; } @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4f { - // get interpolation factor - let t: f32 = clamp(distance(uGradientInfo.centerPos, in.vScreenCoord) / uGradientInfo.radius.x, 0.0, 1.0); - - // get stops count - let last: i32 = i32(uGradientInfo.nStops[0]) - 1; - // resulting color var color = vec4(1.0); + // get interpolation factor + let t: f32 = clamp(distance(uRadialGradient.centerPos, in.vScreenCoord) / uRadialGradient.radius.x, 0.0, 1.0); + + // get stops count + let last: i32 = i32(uRadialGradient.nStops[0]) - 1; + // closer than first stop - if (t <= uGradientInfo.stopPoints[0]) { - color = uGradientInfo.stopColors[0]; + if (t <= uRadialGradient.stopPoints[0]) { + color = uRadialGradient.stopColors[0]; } // further than last stop - if (t >= uGradientInfo.stopPoints[last]) { - color = uGradientInfo.stopColors[last]; + if (t >= uRadialGradient.stopPoints[last]) { + color = uRadialGradient.stopColors[last]; } // look in the middle for (var i = 0i; i < last; i++) { - let strt = uGradientInfo.stopPoints[i]; - let stop = uGradientInfo.stopPoints[i+1]; + let strt = uRadialGradient.stopPoints[i]; + let stop = uRadialGradient.stopPoints[i+1]; if ((t > strt) && (t < stop)) { let step: f32 = (t - strt) / (stop - strt); - color = mix(uGradientInfo.stopColors[i], uGradientInfo.stopColors[i+1], step); + color = mix(uRadialGradient.stopColors[i], uRadialGradient.stopColors[i+1], step); } } - return color; -})"; + return vec4f(color.rgb, color.a); +} +)"; + +//************************************************************************ +// cShaderSource_PipelineImage +//************************************************************************ const char* cShaderSource_PipelineImage = R"( // vertex input struct VertexInput { @location(0) position: vec2f, - @location(1) texCoords: vec2f + @location(1) texCoord: vec2f }; -// Matrix -struct Matrix { - transform: mat4x4f -}; - -// ColorInfo -struct ColorInfo { - format: u32, - dummy0: f32, - dummy1: f32, - opacity: f32 +// BlendSettigs +struct BlendSettigs { + format : u32, // ColorSpace + dummy0 : f32, + dummy1 : f32, + dummy2 : f32 }; // vertex output struct VertexOutput { @builtin(position) position: vec4f, - @location(0) texCoords: vec2f, + @location(0) texCoord: vec2f }; -// uMatrix -@group(0) @binding(0) var uMatrix: Matrix; -// uColorInfo -@group(0) @binding(1) var uColorInfo: ColorInfo; -// uSamplerBase -@group(0) @binding(2) var uSamplerBase: sampler; -// uTextureViewBase -@group(0) @binding(3) var uTextureViewBase: texture_2d; - +@group(0) @binding(0) var uViewMat : mat4x4f; +@group(1) @binding(0) var uModelMat : mat4x4f; +@group(1) @binding(1) var uBlendSettigs : BlendSettigs; +@group(2) @binding(0) var uSampler : sampler; +@group(2) @binding(1) var uTextureView : texture_2d; @vertex fn vs_main(in: VertexInput) -> VertexOutput { // fill output var out: VertexOutput; - out.position = uMatrix.transform * vec4f(in.position.xy, 0.0, 1.0); - out.texCoords = in.texCoords; + out.position = uViewMat * uModelMat * vec4f(in.position.xy, 0.0, 1.0); + out.texCoord = in.texCoord; return out; } @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4f { - var color: vec4f = textureSample(uTextureViewBase, uSamplerBase, in.texCoords.xy); + var color: vec4f = textureSample(uTextureView, uSampler, in.texCoord.xy); var result: vec4f = color; - var format: u32 = uColorInfo.format; + var format: u32 = uBlendSettigs.format; if (format == 1u) { /* FMT_ARGB8888 */ result = color.bgra; } else if (format == 2u) { /* FMT_ABGR8888S */ @@ -324,5 +340,6 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4f { } else if (format == 3u) { /* FMT_ARGB8888S */ result = vec4(color.bgr * color.a, color.a); } - return vec4f(result.rgb, result.a * uColorInfo.opacity); -})"; + return vec4f(result.rgb, result.a); +}; +)"; diff --git a/src/renderer/wg_engine/tvgWgShaderSrc.h b/src/renderer/wg_engine/tvgWgShaderSrc.h index 00a21c80..9099cf87 100644 --- a/src/renderer/wg_engine/tvgWgShaderSrc.h +++ b/src/renderer/wg_engine/tvgWgShaderSrc.h @@ -25,8 +25,8 @@ #ifndef _TVG_WG_SHADER_SRC_H_ #define _TVG_WG_SHADER_SRC_H_ -// pipeline shader module empty -extern const char* cShaderSource_PipelineEmpty; +// pipeline shader module fill +extern const char* cShaderSource_PipelineFill; // pipeline shader module solid extern const char* cShaderSource_PipelineSolid; @@ -40,4 +40,16 @@ extern const char* cShaderSource_PipelineRadial; // pipeline shader module image extern const char* cShaderSource_PipelineImage; +extern const char* MASK_ALPHA_FRAG_SHADER; +extern const char* MASK_INV_ALPHA_FRAG_SHADER; +extern const char* MASK_LUMA_FRAG_SHADER; +extern const char* MASK_INV_LUMA_FRAG_SHADER; +extern const char* MASK_ADD_FRAG_SHADER; +extern const char* MASK_SUB_FRAG_SHADER; +extern const char* MASK_INTERSECT_FRAG_SHADER; +extern const char* MASK_DIFF_FRAG_SHADER; + +// pipeline shader module compose +extern const char* cShaderSource_Pipeline; + #endif // _TVG_WG_SHADER_SRC_H_ diff --git a/src/renderer/wg_engine/tvgWgShaderTypes.cpp b/src/renderer/wg_engine/tvgWgShaderTypes.cpp new file mode 100644 index 00000000..16411694 --- /dev/null +++ b/src/renderer/wg_engine/tvgWgShaderTypes.cpp @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "tvgWgShaderTypes.h" + +/////////////////////////////////////////////////////////////////////////////// +// shader types +/////////////////////////////////////////////////////////////////////////////// + +WgShaderTypeMat4x4f::WgShaderTypeMat4x4f() { + identity(); +} + +WgShaderTypeMat4x4f::WgShaderTypeMat4x4f(const RenderTransform* transform) { + update(transform); +} + +void WgShaderTypeMat4x4f::identity() { + mat[0] = 1.0f; mat[1] = 0.0f; mat[2] = 0.0f; mat[3] = 0.0f; + mat[4] = 0.0f; mat[5] = 1.0f; mat[6] = 0.0f; mat[7] = 0.0f; + mat[8] = 0.0f; mat[9] = 0.0f; mat[10] = 1.0f; mat[11] = 0.0f; + mat[12] = 0.0f; mat[13] = 0.0f; mat[14] = 0.0f; mat[15] = 1.0f; +} + +WgShaderTypeMat4x4f::WgShaderTypeMat4x4f(size_t w, size_t h) { + update(w, h); +} + +void WgShaderTypeMat4x4f::update(const RenderTransform* transform) { + identity(); + if (transform) { + mat[0] = transform->m.e11; + mat[1] = transform->m.e21; + mat[2] = 0.0f; + mat[3] = transform->m.e31; + mat[4] = transform->m.e12; + mat[5] = transform->m.e22; + mat[6] = 0.0f; + mat[7] = transform->m.e32; + mat[8] = 0.0f; + mat[9] = 0.0f; + mat[10] = 1.0f; + mat[11] = 0.0f; + mat[12] = transform->m.e13; + mat[13] = transform->m.e23; + mat[14] = 0.0f; + mat[15] = transform->m.e33; + }; +}; + +void WgShaderTypeMat4x4f::update(size_t w, size_t h) { + mat[0] = +2.0f / w; mat[1] = +0.0f; mat[2] = +0.0f; mat[3] = +0.0f; + mat[4] = +0.0f; mat[5] = -2.0f / h; mat[6] = +0.0f; mat[7] = +0.0f; + mat[8] = +0.0f; mat[9] = +0.0f; mat[10] = -1.0f; mat[11] = +0.0f; + mat[12] = -1.0f; mat[13] = +1.0f; mat[14] = +0.0f; mat[15] = +1.0f; +}; + +WgShaderTypeBlendSettings::WgShaderTypeBlendSettings(const ColorSpace colorSpace) { + update(colorSpace); +} + +void WgShaderTypeBlendSettings::update(const ColorSpace colorSpace) { + format = (uint32_t)colorSpace; + dummy0 = 0.0f; + dummy1 = 0.0f; + dummy2 = 0.0f; +}; + +WgShaderTypeSolidColor::WgShaderTypeSolidColor(const uint8_t* c) { + update(c); +} + +void WgShaderTypeSolidColor::update(const uint8_t* c) { + color[0] = c[0] / 255.0f; // red + color[1] = c[1] / 255.0f; // green + color[2] = c[2] / 255.0f; // blue + color[3] = c[3] / 255.0f; // alpha +}; + +WgShaderTypeLinearGradient::WgShaderTypeLinearGradient(const LinearGradient* linearGradient) { + update(linearGradient); +} + +void WgShaderTypeLinearGradient::update(const LinearGradient* linearGradient) { + const Fill::ColorStop* stops = nullptr; + auto stopCnt = linearGradient->colorStops(&stops); + + nStops[0] = stopCnt; + nStops[1] = 0.5f; + + for (uint32_t i = 0; i < stopCnt; ++i) { + stopPoints[i] = stops[i].offset; + stopColors[i * 4 + 0] = stops[i].r / 255.f; + stopColors[i * 4 + 1] = stops[i].g / 255.f; + stopColors[i * 4 + 2] = stops[i].b / 255.f; + stopColors[i * 4 + 3] = stops[i].a / 255.f; + } + + linearGradient->linear(&startPos[0], &startPos[1], &endPos[0], &endPos[1]); +}; + +WgShaderTypeRadialGradient::WgShaderTypeRadialGradient(const RadialGradient* radialGradient) { + update(radialGradient); +} + +void WgShaderTypeRadialGradient::update(const RadialGradient* radialGradient) { + const Fill::ColorStop* stops = nullptr; + auto stopCnt = radialGradient->colorStops(&stops); + + nStops[0] = stopCnt; + nStops[1] = 0.5f; + + for (uint32_t i = 0; i < stopCnt; ++i) { + stopPoints[i] = stops[i].offset; + stopColors[i * 4 + 0] = stops[i].r / 255.f; + stopColors[i * 4 + 1] = stops[i].g / 255.f; + stopColors[i * 4 + 2] = stops[i].b / 255.f; + stopColors[i * 4 + 3] = stops[i].a / 255.f; + } + + radialGradient->radial(¢erPos[0], ¢erPos[1], &radius[0]); +}; diff --git a/src/renderer/wg_engine/tvgWgShaderTypes.h b/src/renderer/wg_engine/tvgWgShaderTypes.h new file mode 100644 index 00000000..3872aff9 --- /dev/null +++ b/src/renderer/wg_engine/tvgWgShaderTypes.h @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef _TVG_WG_SHADER_TYPES_H_ +#define _TVG_WG_SHADER_TYPES_H_ + +#include "tvgWgCommon.h" + +/////////////////////////////////////////////////////////////////////////////// +// shader types +/////////////////////////////////////////////////////////////////////////////// + +// mat4x4f +struct WgShaderTypeMat4x4f { + float mat[16]{}; + + WgShaderTypeMat4x4f(); + WgShaderTypeMat4x4f(const RenderTransform* transform); + WgShaderTypeMat4x4f(size_t w, size_t h); + void identity(); + void update(const RenderTransform* transform); + void update(size_t w, size_t h); +}; + +// struct BlendSettigs { +// format : u32, // ColorSpace +// dummy0 : f32, +// dummy1 : f32, +// opacity : f32 +// }; +struct WgShaderTypeBlendSettings { + uint32_t format{}; // ColorSpace + float dummy0{}; + float dummy1{}; + float dummy2{}; + + WgShaderTypeBlendSettings() {}; + WgShaderTypeBlendSettings(const ColorSpace colorSpace); + void update(const ColorSpace colorSpace); +}; + +// struct SolidColor { +// color: vec4f +// }; +struct WgShaderTypeSolidColor { + float color[4]{}; + + WgShaderTypeSolidColor(const uint8_t* c); + void update(const uint8_t* c); +}; + +// const MAX_LINEAR_GRADIENT_STOPS = 4; +// struct LinearGradient { +// nStops : vec4f, +// gradStartPos : vec2f, +// gradEndPos : vec2f, +// stopPoints : vec4f, +// stopColors : array +// }; +#define MAX_LINEAR_GRADIENT_STOPS 4 +struct WgShaderTypeLinearGradient { + alignas(16) float nStops[4]{}; + alignas(16) float startPos[2]{}; + alignas(8) float endPos[2]{}; + alignas(8) float stopPoints[MAX_LINEAR_GRADIENT_STOPS]{}; + alignas(16) float stopColors[4 * MAX_LINEAR_GRADIENT_STOPS]{}; + + WgShaderTypeLinearGradient(const LinearGradient* linearGradient); + void update(const LinearGradient* linearGradient); +}; + +// const MAX_RADIAL_GRADIENT_STOPS = 4; +// struct RadialGradient { +// nStops : vec4f, +// centerPos : vec2f, +// radius : vec2f, +// stopPoints : vec4f, +// stopColors : array +// }; +#define MAX_RADIAL_GRADIENT_STOPS 4 +struct WgShaderTypeRadialGradient { + alignas(16) float nStops[4]{}; + alignas(16) float centerPos[2]{}; + alignas(8) float radius[2]{}; + alignas(8) float stopPoints[MAX_RADIAL_GRADIENT_STOPS]{}; + alignas(16) float stopColors[4 * MAX_RADIAL_GRADIENT_STOPS]{}; + + WgShaderTypeRadialGradient(const RadialGradient* radialGradient); + void update(const RadialGradient* radialGradient); +}; + +#endif // _TVG_WG_SHADER_TYPES_H_