thorvg/src/renderer/wg_engine/tvgWgPipelines.cpp

537 lines
28 KiB
C++

/*
* Copyright (c) 2023 - 2025 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"
#include <cstring>
#include <cassert>
WGPUShaderModule WgPipelines::createShaderModule(WGPUDevice device, const char* label, const char* code)
{
WGPUShaderModuleWGSLDescriptor shaderModuleWGSLDesc{};
shaderModuleWGSLDesc.chain.sType = WGPUSType_ShaderModuleWGSLDescriptor;
shaderModuleWGSLDesc.code = code;
const WGPUShaderModuleDescriptor shaderModuleDesc { .nextInChain = &shaderModuleWGSLDesc.chain, .label = label };
return wgpuDeviceCreateShaderModule(device, &shaderModuleDesc);
}
WGPUPipelineLayout WgPipelines::createPipelineLayout(WGPUDevice device, const WGPUBindGroupLayout* bindGroupLayouts, const uint32_t bindGroupLayoutsCount)
{
const WGPUPipelineLayoutDescriptor pipelineLayoutDesc { .bindGroupLayoutCount = bindGroupLayoutsCount, .bindGroupLayouts = bindGroupLayouts };
return wgpuDeviceCreatePipelineLayout(device, &pipelineLayoutDesc);
}
WGPURenderPipeline WgPipelines::createRenderPipeline(
WGPUDevice device, const char* pipelineLabel,
const WGPUShaderModule shaderModule, const char* vsEntryPoint, const char* fsEntryPoint,
const WGPUPipelineLayout pipelineLayout,
const WGPUVertexBufferLayout *vertexBufferLayouts, const uint32_t vertexBufferLayoutsCount,
const WGPUColorWriteMaskFlags writeMask, const WGPUTextureFormat colorTargetFormat, const WGPUBlendState blendState,
const WGPUDepthStencilState depthStencilState, const WGPUMultisampleState multisampleState)
{
const WGPUColorTargetState colorTargetState { .format = colorTargetFormat, .blend = &blendState, .writeMask = writeMask };
const WGPUColorTargetState colorTargetStates[] { colorTargetState };
const WGPUPrimitiveState primitiveState { .topology = WGPUPrimitiveTopology_TriangleList };
const WGPUVertexState vertexState { .module = shaderModule, .entryPoint = vsEntryPoint, .bufferCount = vertexBufferLayoutsCount, .buffers = vertexBufferLayouts };
const WGPUFragmentState fragmentState { .module = shaderModule, .entryPoint = fsEntryPoint, .targetCount = 1, .targets = colorTargetStates };
const WGPURenderPipelineDescriptor renderPipelineDesc {
.label = pipelineLabel,
.layout = pipelineLayout,
.vertex = vertexState,
.primitive = primitiveState,
.depthStencil = &depthStencilState,
.multisample = multisampleState,
.fragment = &fragmentState
};
return wgpuDeviceCreateRenderPipeline(device, &renderPipelineDesc);
}
WGPUComputePipeline WgPipelines::createComputePipeline(
WGPUDevice device, const char* pipelineLabel,
const WGPUShaderModule shaderModule, const char* entryPoint,
const WGPUPipelineLayout pipelineLayout)
{
const WGPUComputePipelineDescriptor computePipelineDesc{
.label = pipelineLabel,
.layout = pipelineLayout,
.compute = {
.module = shaderModule,
.entryPoint = entryPoint
}
};
return wgpuDeviceCreateComputePipeline(device, &computePipelineDesc);
}
void WgPipelines::releaseComputePipeline(WGPUComputePipeline& computePipeline)
{
if (computePipeline) {
wgpuComputePipelineRelease(computePipeline);
computePipeline = nullptr;
}
}
void WgPipelines::releaseRenderPipeline(WGPURenderPipeline& renderPipeline)
{
if (renderPipeline) {
wgpuRenderPipelineRelease(renderPipeline);
renderPipeline = nullptr;
}
}
void WgPipelines::releasePipelineLayout(WGPUPipelineLayout& pipelineLayout)
{
if (pipelineLayout) {
wgpuPipelineLayoutRelease(pipelineLayout);
pipelineLayout = nullptr;
}
}
void WgPipelines::releaseShaderModule(WGPUShaderModule& shaderModule)
{
if (shaderModule) {
wgpuShaderModuleRelease(shaderModule);
shaderModule = nullptr;
}
}
WGPUDepthStencilState WgPipelines::makeDepthStencilState(
const WGPUCompareFunction depthCompare, WGPUBool depthWriteEnabled,
const WGPUCompareFunction stencilFunction, const WGPUStencilOperation stencilOperation)
{
return makeDepthStencilState(depthCompare, depthWriteEnabled, stencilFunction, stencilOperation, stencilFunction, stencilOperation);
}
WGPUDepthStencilState WgPipelines::makeDepthStencilState(
const WGPUCompareFunction depthCompare, WGPUBool depthWriteEnabled,
const WGPUCompareFunction stencilFunctionFrnt, const WGPUStencilOperation stencilOperationFrnt,
const WGPUCompareFunction stencilFunctionBack, const WGPUStencilOperation stencilOperationBack)
{
const WGPUDepthStencilState depthStencilState {
.format = WGPUTextureFormat_Depth24PlusStencil8, .depthWriteEnabled = depthWriteEnabled, .depthCompare = depthCompare,
.stencilFront = { .compare = stencilFunctionFrnt, .failOp = stencilOperationFrnt, .depthFailOp = WGPUStencilOperation_Zero, .passOp = stencilOperationFrnt },
.stencilBack = { .compare = stencilFunctionBack, .failOp = stencilOperationBack, .depthFailOp = WGPUStencilOperation_Zero, .passOp = stencilOperationBack },
.stencilReadMask = 0xFFFFFFFF, .stencilWriteMask = 0xFFFFFFFF
};
return depthStencilState;
}
void WgPipelines::initialize(WgContext& context)
{
// common pipeline settings
const WGPUVertexAttribute vertexAttributePos { .format = WGPUVertexFormat_Float32x2, .offset = 0, .shaderLocation = 0 };
const WGPUVertexAttribute vertexAttributeTex { .format = WGPUVertexFormat_Float32x2, .offset = 0, .shaderLocation = 1 };
const WGPUVertexAttribute vertexAttributesPos[] { vertexAttributePos };
const WGPUVertexAttribute vertexAttributesTex[] { vertexAttributeTex };
const WGPUVertexBufferLayout vertexBufferLayoutPos { .arrayStride = 8, .stepMode = WGPUVertexStepMode_Vertex, .attributeCount = 1, .attributes = vertexAttributesPos };
const WGPUVertexBufferLayout vertexBufferLayoutTex { .arrayStride = 8, .stepMode = WGPUVertexStepMode_Vertex, .attributeCount = 1, .attributes = vertexAttributesTex };
const WGPUVertexBufferLayout vertexBufferLayoutsShape[] { vertexBufferLayoutPos };
const WGPUVertexBufferLayout vertexBufferLayoutsImage[] { vertexBufferLayoutPos, vertexBufferLayoutTex };
const WGPUMultisampleState multisampleState { .count = 4, .mask = 0xFFFFFFFF, .alphaToCoverageEnabled = false };
const WGPUMultisampleState multisampleStateX1 { .count = 1, .mask = 0xFFFFFFFF, .alphaToCoverageEnabled = false };
const WGPUTextureFormat offscreenTargetFormat = WGPUTextureFormat_RGBA8Unorm;
// blend states
WGPUBlendComponent blendComponentSrc { .operation = WGPUBlendOperation_Add, .srcFactor = WGPUBlendFactor_One, .dstFactor = WGPUBlendFactor_Zero };
WGPUBlendComponent blendComponentNrm { .operation = WGPUBlendOperation_Add, .srcFactor = WGPUBlendFactor_One, .dstFactor = WGPUBlendFactor_OneMinusSrcAlpha };
const WGPUBlendState blendStateSrc { .color = blendComponentSrc, .alpha = blendComponentSrc };
const WGPUBlendState blendStateNrm { .color = blendComponentNrm, .alpha = blendComponentNrm };
const WgBindGroupLayouts& layouts = context.layouts;
// bind group layouts helpers
const WGPUBindGroupLayout bindGroupLayoutsStencil[] { layouts.layoutBuffer1Un, layouts.layoutBuffer2Un };
const WGPUBindGroupLayout bindGroupLayoutsDepth[] { layouts.layoutBuffer1Un, layouts.layoutBuffer2Un, layouts.layoutBuffer1Un };
// bind group layouts normal blend
const WGPUBindGroupLayout bindGroupLayoutsSolid[] { layouts.layoutBuffer1Un, layouts.layoutBuffer2Un, layouts.layoutBuffer1Un };
const WGPUBindGroupLayout bindGroupLayoutsGradient[] { layouts.layoutBuffer1Un, layouts.layoutBuffer2Un, layouts.layoutTexSampledBuff2Un };
const WGPUBindGroupLayout bindGroupLayoutsImage[] { layouts.layoutBuffer1Un, layouts.layoutBuffer2Un, layouts.layoutTexSampled };
const WGPUBindGroupLayout bindGroupLayoutsScene[] { layouts.layoutTexSampled, layouts.layoutBuffer1Un };
// bind group layouts custom blend
const WGPUBindGroupLayout bindGroupLayoutsSolidBlend[] { layouts.layoutBuffer1Un, layouts.layoutBuffer2Un, layouts.layoutBuffer1Un, layouts.layoutTexSampled };
const WGPUBindGroupLayout bindGroupLayoutsGradientBlend[] { layouts.layoutBuffer1Un, layouts.layoutBuffer2Un, layouts.layoutTexSampledBuff2Un, layouts.layoutTexSampled };
const WGPUBindGroupLayout bindGroupLayoutsImageBlend[] { layouts.layoutBuffer1Un, layouts.layoutBuffer2Un, layouts.layoutTexSampled, layouts.layoutTexSampled };
const WGPUBindGroupLayout bindGroupLayoutsSceneBlend[] { layouts.layoutTexSampled, layouts.layoutTexSampled, layouts.layoutBuffer1Un };
// bind group layouts scene compose
const WGPUBindGroupLayout bindGroupLayoutsSceneCompose[] { layouts.layoutTexSampled, layouts.layoutTexSampled };
// bind group layouts blit
const WGPUBindGroupLayout bindGroupLayoutsBlit[] { layouts.layoutTexSampled };
// bind group layouts effects
const WGPUBindGroupLayout bindGroupLayoutsGauss[] { layouts.layoutTexStrorage1RO, layouts.layoutTexStrorage1WO, layouts.layoutBuffer1Un, layouts.layoutBuffer1Un };
const WGPUBindGroupLayout bindGroupLayoutsEffects[] { layouts.layoutTexStrorage2RO, layouts.layoutTexStrorage1WO, layouts.layoutBuffer1Un, layouts.layoutBuffer1Un };
// depth stencil state markup
const WGPUDepthStencilState depthStencilStateNonZero = makeDepthStencilState(WGPUCompareFunction_Always, false, WGPUCompareFunction_Always, WGPUStencilOperation_IncrementWrap, WGPUCompareFunction_Always, WGPUStencilOperation_DecrementWrap);
const WGPUDepthStencilState depthStencilStateEvenOdd = makeDepthStencilState(WGPUCompareFunction_Always, false, WGPUCompareFunction_Always, WGPUStencilOperation_Invert);
const WGPUDepthStencilState depthStencilStateDirect = makeDepthStencilState(WGPUCompareFunction_Always, false, WGPUCompareFunction_Always, WGPUStencilOperation_Replace);
// depth stencil state clip path
const WGPUDepthStencilState depthStencilStateCopyStencilToDepth = makeDepthStencilState(WGPUCompareFunction_Always, true, WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero);
const WGPUDepthStencilState depthStencilStateCopyStencilToDepthInt = makeDepthStencilState(WGPUCompareFunction_Greater, true, WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero);
const WGPUDepthStencilState depthStencilStateCopyDepthToStencil = makeDepthStencilState(WGPUCompareFunction_Equal, false, WGPUCompareFunction_Always, WGPUStencilOperation_Replace);
const WGPUDepthStencilState depthStencilStateMergeDepthStencil = makeDepthStencilState(WGPUCompareFunction_Equal, true, WGPUCompareFunction_Always, WGPUStencilOperation_Keep);
const WGPUDepthStencilState depthStencilStateClearDepth = makeDepthStencilState(WGPUCompareFunction_Always, true, WGPUCompareFunction_Always, WGPUStencilOperation_Keep);
// depth stencil state blend, compose and blit
const WGPUDepthStencilState depthStencilStateShape = makeDepthStencilState(WGPUCompareFunction_Always, false, WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero);
const WGPUDepthStencilState depthStencilStateScene = makeDepthStencilState(WGPUCompareFunction_Always, false, WGPUCompareFunction_Always, WGPUStencilOperation_Zero);
// shaders
char shaderSourceBuff[16384]{};
shader_stencil = createShaderModule(context.device, "The shader stencil", cShaderSrc_Stencil);
shader_depth = createShaderModule(context.device, "The shader depth", cShaderSrc_Depth);
// shader normal blend
shader_solid = createShaderModule(context.device, "The shader solid", cShaderSrc_Solid);
shader_radial = createShaderModule(context.device, "The shader radial", cShaderSrc_Radial);
shader_linear = createShaderModule(context.device, "The shader linear", cShaderSrc_Linear);
shader_image = createShaderModule(context.device, "The shader image", cShaderSrc_Image);
shader_scene = createShaderModule(context.device, "The shader scene", cShaderSrc_Scene);
// shader custom blend
shader_solid_blend = createShaderModule(context.device, "The shader blend solid", strcat(strcpy(shaderSourceBuff, cShaderSrc_Solid_Blend), cShaderSrc_BlendFuncs));
shader_linear_blend = createShaderModule(context.device, "The shader blend linear", strcat(strcpy(shaderSourceBuff, cShaderSrc_Linear_Blend), cShaderSrc_BlendFuncs));
shader_radial_blend = createShaderModule(context.device, "The shader blend radial", strcat(strcpy(shaderSourceBuff, cShaderSrc_Radial_Blend), cShaderSrc_BlendFuncs));
shader_image_blend = createShaderModule(context.device, "The shader blend image", strcat(strcpy(shaderSourceBuff, cShaderSrc_Image_Blend), cShaderSrc_BlendFuncs));
shader_scene_blend = createShaderModule(context.device, "The shader blend scene", strcat(strcpy(shaderSourceBuff, cShaderSrc_Scene_Blend), cShaderSrc_BlendFuncs));
// shader compose
shader_scene_compose = createShaderModule(context.device, "The shader scene composition", cShaderSrc_Scene_Compose);
// shader blit
shader_blit = createShaderModule(context.device, "The shader blit", cShaderSrc_Blit);
// shader effects
shader_gauss = createShaderModule(context.device, "The shader effects", cShaderSrc_GaussianBlur);
shader_effects = createShaderModule(context.device, "The shader effects", cShaderSrc_Effects);
// layouts
layout_stencil = createPipelineLayout(context.device, bindGroupLayoutsStencil, 2);
layout_depth = createPipelineLayout(context.device, bindGroupLayoutsDepth, 3);
// layouts normal blend
layout_solid = createPipelineLayout(context.device, bindGroupLayoutsSolid, 3);
layout_gradient = createPipelineLayout(context.device, bindGroupLayoutsGradient, 3);
layout_image = createPipelineLayout(context.device, bindGroupLayoutsImage, 3);
layout_scene = createPipelineLayout(context.device, bindGroupLayoutsScene, 2);
// layouts custom blend
layout_solid_blend = createPipelineLayout(context.device, bindGroupLayoutsSolidBlend, 4);
layout_gradient_blend = createPipelineLayout(context.device, bindGroupLayoutsGradientBlend, 4);
layout_image_blend = createPipelineLayout(context.device, bindGroupLayoutsImageBlend, 4);
layout_scene_blend = createPipelineLayout(context.device, bindGroupLayoutsSceneBlend, 3);
// layout compose
layout_scene_compose = createPipelineLayout(context.device, bindGroupLayoutsSceneCompose, 2);
// layout blit
layout_blit = createPipelineLayout(context.device, bindGroupLayoutsBlit, 1);
// layout effects
layout_gauss = createPipelineLayout(context.device, bindGroupLayoutsGauss, 4);
layout_effects = createPipelineLayout(context.device, bindGroupLayoutsEffects, 4);
// render pipeline nonzero
nonzero = createRenderPipeline(
context.device, "The render pipeline nonzero",
shader_stencil, "vs_main", "fs_main",
layout_stencil, vertexBufferLayoutsShape, 1,
WGPUColorWriteMask_None, offscreenTargetFormat, blendStateSrc,
depthStencilStateNonZero, multisampleState);
// render pipeline even-odd
evenodd = createRenderPipeline(
context.device, "The render pipeline even-odd",
shader_stencil, "vs_main", "fs_main",
layout_stencil, vertexBufferLayoutsShape, 1,
WGPUColorWriteMask_None, offscreenTargetFormat, blendStateSrc,
depthStencilStateEvenOdd, multisampleState);
// render pipeline direct
direct = createRenderPipeline(
context.device, "The render pipeline direct",
shader_stencil, "vs_main", "fs_main",
layout_stencil, vertexBufferLayoutsShape, 1,
WGPUColorWriteMask_None, offscreenTargetFormat, blendStateSrc,
depthStencilStateDirect, multisampleState);
// render pipeline copy stencil to depth (front)
copy_stencil_to_depth = createRenderPipeline(
context.device, "The render pipeline copy stencil to depth front",
shader_depth, "vs_main", "fs_main",
layout_depth, vertexBufferLayoutsShape, 1,
WGPUColorWriteMask_None, offscreenTargetFormat, blendStateSrc,
depthStencilStateCopyStencilToDepth , multisampleState);
// render pipeline copy stencil to depth (intermidiate)
copy_stencil_to_depth_interm = createRenderPipeline(
context.device, "The render pipeline copy stencil to depth intermidiate",
shader_depth, "vs_main", "fs_main",
layout_depth, vertexBufferLayoutsShape, 1,
WGPUColorWriteMask_None, offscreenTargetFormat, blendStateSrc,
depthStencilStateCopyStencilToDepthInt, multisampleState);
// render pipeline depth to stencil
copy_depth_to_stencil = createRenderPipeline(
context.device, "The render pipeline depth to stencil",
shader_depth, "vs_main", "fs_main",
layout_depth, vertexBufferLayoutsShape, 1,
WGPUColorWriteMask_None, offscreenTargetFormat, blendStateSrc,
depthStencilStateCopyDepthToStencil, multisampleState);
// render pipeline merge depth with stencil
merge_depth_stencil = createRenderPipeline(
context.device, "The render pipeline merge depth with stencil",
shader_depth, "vs_main", "fs_main",
layout_depth, vertexBufferLayoutsShape, 1,
WGPUColorWriteMask_None, offscreenTargetFormat, blendStateSrc,
depthStencilStateMergeDepthStencil, multisampleState);
// render pipeline clear depth
clear_depth = createRenderPipeline(
context.device, "The render pipeline clear depth",
shader_depth, "vs_main", "fs_main",
layout_depth, vertexBufferLayoutsShape, 1,
WGPUColorWriteMask_None, offscreenTargetFormat, blendStateSrc,
depthStencilStateClearDepth, multisampleState);
// render pipeline solid
solid = createRenderPipeline(
context.device, "The render pipeline solid",
shader_solid, "vs_main", "fs_main",
layout_solid, vertexBufferLayoutsShape, 1,
WGPUColorWriteMask_All, offscreenTargetFormat, blendStateNrm,
depthStencilStateShape, multisampleState);
// render pipeline radial
radial = createRenderPipeline(
context.device, "The render pipeline radial",
shader_radial, "vs_main", "fs_main",
layout_gradient, vertexBufferLayoutsShape, 1,
WGPUColorWriteMask_All, offscreenTargetFormat, blendStateNrm,
depthStencilStateShape, multisampleState);
// render pipeline linear
linear = createRenderPipeline(
context.device, "The render pipeline linear",
shader_linear, "vs_main", "fs_main",
layout_gradient, vertexBufferLayoutsShape, 1,
WGPUColorWriteMask_All, offscreenTargetFormat, blendStateNrm,
depthStencilStateShape, multisampleState);
// render pipeline image
image = createRenderPipeline(
context.device, "The render pipeline image",
shader_image, "vs_main", "fs_main",
layout_image, vertexBufferLayoutsImage, 2,
WGPUColorWriteMask_All, offscreenTargetFormat, blendStateNrm,
depthStencilStateShape, multisampleState);
// render pipeline scene
scene = createRenderPipeline(
context.device, "The render pipeline scene",
shader_scene, "vs_main", "fs_main",
layout_scene, vertexBufferLayoutsImage, 2,
WGPUColorWriteMask_All, offscreenTargetFormat, blendStateNrm,
depthStencilStateScene, multisampleState);
// blend shader names
const char* shaderBlendNames[] {
"fs_main_Normal",
"fs_main_Multiply",
"fs_main_Screen",
"fs_main_Overlay",
"fs_main_Darken",
"fs_main_Lighten",
"fs_main_ColorDodge",
"fs_main_ColorBurn",
"fs_main_HardLight",
"fs_main_SoftLight",
"fs_main_Difference",
"fs_main_Exclusion",
"fs_main_Normal", //TODO: a padding for reserved Hue.
"fs_main_Normal", //TODO: a padding for reserved Saturation.
"fs_main_Normal", //TODO: a padding for reserved Color.
"fs_main_Normal", //TODO: a padding for reserved Luminosity.
"fs_main_Add",
"fs_main_Normal" //TODO: a padding for reserved Hardmix.
};
// render pipeline shape blend
for (uint32_t i = 0; i < 18; i++) {
// blend solid
solid_blend[i] = createRenderPipeline(
context.device, "The render pipeline solid blend",
shader_solid_blend, "vs_main", shaderBlendNames[i],
layout_solid_blend, vertexBufferLayoutsShape, 1,
WGPUColorWriteMask_All, offscreenTargetFormat, blendStateSrc,
depthStencilStateShape, multisampleState);
// blend radial
radial_blend[i] = createRenderPipeline(
context.device, "The render pipeline radial blend",
shader_radial_blend, "vs_main", shaderBlendNames[i],
layout_gradient_blend, vertexBufferLayoutsShape, 1,
WGPUColorWriteMask_All, offscreenTargetFormat, blendStateSrc,
depthStencilStateShape, multisampleState);
// blend linear
linear_blend[i] = createRenderPipeline(
context.device, "The render pipeline linear blend",
shader_linear_blend, "vs_main", shaderBlendNames[i],
layout_gradient_blend, vertexBufferLayoutsShape, 1,
WGPUColorWriteMask_All, offscreenTargetFormat, blendStateSrc,
depthStencilStateShape, multisampleState);
// blend image
image_blend[i] = createRenderPipeline(
context.device, "The render pipeline image blend",
shader_image_blend, "vs_main", shaderBlendNames[i],
layout_image_blend, vertexBufferLayoutsImage, 2,
WGPUColorWriteMask_All, offscreenTargetFormat, blendStateSrc,
depthStencilStateShape, multisampleState);
// blend scene
scene_blend[i] = createRenderPipeline(
context.device, "The render pipeline scene blend",
shader_scene_blend, "vs_main", shaderBlendNames[i],
layout_scene_blend, vertexBufferLayoutsImage, 2,
WGPUColorWriteMask_All, offscreenTargetFormat, blendStateSrc,
depthStencilStateScene, multisampleState);
}
// compose shader names
const char* shaderComposeNames[] {
"fs_main_None",
"fs_main_AlphaMask",
"fs_main_InvAlphaMask",
"fs_main_LumaMask",
"fs_main_InvLumaMask",
"fs_main_AddMask",
"fs_main_SubtractMask",
"fs_main_IntersectMask",
"fs_main_DifferenceMask",
"fs_main_LightenMask",
"fs_main_DarkenMask"
};
// compose shader blend states
const WGPUBlendState composeBlends[] {
blendStateNrm, // None
blendStateNrm, // AlphaMask
blendStateNrm, // InvAlphaMask
blendStateNrm, // LumaMask
blendStateNrm, // InvLumaMask
blendStateSrc, // AddMask
blendStateSrc, // SubtractMask
blendStateSrc, // IntersectMask
blendStateSrc, // DifferenceMask
blendStateSrc, // LightenMask
blendStateSrc // DarkenMask
};
// render pipeline scene composition
for (uint32_t i = 0; i < 11; i++) {
scene_compose[i] = createRenderPipeline(
context.device, "The render pipeline scene composition",
shader_scene_compose, "vs_main", shaderComposeNames[i],
layout_scene_compose, vertexBufferLayoutsImage, 2,
WGPUColorWriteMask_All, offscreenTargetFormat, composeBlends[i],
depthStencilStateScene, multisampleState);
}
// render pipeline blit
blit = createRenderPipeline(
context.device, "The render pipeline blit",
shader_blit, "vs_main", "fs_main",
layout_blit, vertexBufferLayoutsImage, 2,
WGPUColorWriteMask_All, context.preferredFormat, blendStateSrc, // must be preferred screen pixel format
depthStencilStateScene, multisampleStateX1);
// compute pipeline gaussian blur
gaussian_horz = createComputePipeline(context.device, "The compute pipeline gaussian blur horizontal", shader_gauss, "cs_main_horz", layout_gauss);
gaussian_vert = createComputePipeline(context.device, "The compute pipeline gaussian blur vertical", shader_gauss, "cs_main_vert", layout_gauss);
dropshadow = createComputePipeline(context.device, "The compute pipeline drop shadow blend", shader_effects, "cs_main_drop_shadow", layout_effects);
fill_effect = createComputePipeline(context.device, "The compute pipeline fill effect", shader_effects, "cs_main_fill", layout_effects);
tint_effect = createComputePipeline(context.device, "The compute pipeline tint effect", shader_effects, "cs_main_tint", layout_effects);
tritone_effect= createComputePipeline(context.device, "The compute pipeline tritone effect", shader_effects, "cs_main_tritone", layout_effects);
}
void WgPipelines::releaseGraphicHandles(WgContext& context)
{
// pipeline effects
releaseComputePipeline(tritone_effect);
releaseComputePipeline(tint_effect);
releaseComputePipeline(fill_effect);
releaseComputePipeline(dropshadow);
releaseComputePipeline(gaussian_vert);
releaseComputePipeline(gaussian_horz);
// pipeline blit
releaseRenderPipeline(blit);
// pipelines compose
for (uint32_t i = 0; i < 11; i++)
releaseRenderPipeline(scene_compose[i]);
// pipelines custom blend
for (uint32_t i = 0; i < 18; i++) {
releaseRenderPipeline(scene_blend[i]);
releaseRenderPipeline(image_blend[i]);
releaseRenderPipeline(linear_blend[i]);
releaseRenderPipeline(radial_blend[i]);
releaseRenderPipeline(solid_blend[i]);
}
// pipelines normal blend
releaseRenderPipeline(scene);
releaseRenderPipeline(image);
releaseRenderPipeline(linear);
releaseRenderPipeline(radial);
releaseRenderPipeline(solid);
// pipelines clip path markup
releaseRenderPipeline(clear_depth);
releaseRenderPipeline(merge_depth_stencil);
releaseRenderPipeline(copy_depth_to_stencil);
releaseRenderPipeline(copy_stencil_to_depth_interm);
releaseRenderPipeline(copy_stencil_to_depth);
// pipelines stencil markup
releaseRenderPipeline(direct);
releaseRenderPipeline(evenodd);
releaseRenderPipeline(nonzero);
// layouts
releasePipelineLayout(layout_effects);
releasePipelineLayout(layout_gauss);
releasePipelineLayout(layout_blit);
releasePipelineLayout(layout_scene_compose);
releasePipelineLayout(layout_scene_blend);
releasePipelineLayout(layout_image_blend);
releasePipelineLayout(layout_gradient_blend);
releasePipelineLayout(layout_solid_blend);
releasePipelineLayout(layout_scene);
releasePipelineLayout(layout_image);
releasePipelineLayout(layout_gradient);
releasePipelineLayout(layout_solid);
releasePipelineLayout(layout_depth);
releasePipelineLayout(layout_stencil);
// shaders
releaseShaderModule(shader_effects);
releaseShaderModule(shader_gauss);
releaseShaderModule(shader_blit);
releaseShaderModule(shader_scene_compose);
releaseShaderModule(shader_scene_blend);
releaseShaderModule(shader_image_blend);
releaseShaderModule(shader_linear_blend);
releaseShaderModule(shader_radial_blend);
releaseShaderModule(shader_solid_blend);
releaseShaderModule(shader_scene);
releaseShaderModule(shader_image);
releaseShaderModule(shader_linear);
releaseShaderModule(shader_radial);
releaseShaderModule(shader_solid);
releaseShaderModule(shader_depth);
releaseShaderModule(shader_stencil);
}
void WgPipelines::release(WgContext& context)
{
releaseGraphicHandles(context);
}