mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-21 15:32:49 +00:00
wg_engine: clippath optimization
Full review of clipping workflow. Before we are used separate render target for each clip path and compute shader to find clip path intersections with AND logic. Now we are using depth buffer and transactions from depth to stencil and back to get AND logic intersections, Compute shaders, layouts and pipelines was removed
This commit is contained in:
parent
a1296960eb
commit
0815366763
6 changed files with 330 additions and 214 deletions
|
@ -31,7 +31,7 @@ void WgCompositor::initialize(WgContext& context, uint32_t width, uint32_t heigh
|
||||||
this->width = width;
|
this->width = width;
|
||||||
this->height = height;
|
this->height = height;
|
||||||
// allocate global stencil buffer handles
|
// allocate global stencil buffer handles
|
||||||
texStencil = context.createTexStencil(width, height, WGPUTextureFormat_Stencil8);
|
texStencil = context.createTexStencil(width, height, WGPUTextureFormat_Depth24PlusStencil8);
|
||||||
texViewStencil = context.createTextureView(texStencil);
|
texViewStencil = context.createTextureView(texStencil);
|
||||||
// allocate global view matrix handles
|
// allocate global view matrix handles
|
||||||
WgShaderTypeMat4x4f viewMat(width, height);
|
WgShaderTypeMat4x4f viewMat(width, height);
|
||||||
|
@ -44,8 +44,6 @@ void WgCompositor::initialize(WgContext& context, uint32_t width, uint32_t heigh
|
||||||
bindGroupOpacities[i] = pipelines->layouts.createBindGroupBuffer1Un(bufferOpacities[i]);
|
bindGroupOpacities[i] = pipelines->layouts.createBindGroupBuffer1Un(bufferOpacities[i]);
|
||||||
}
|
}
|
||||||
// initialize intermediate render storages
|
// initialize intermediate render storages
|
||||||
storageClipPath.initialize(context, width, height);
|
|
||||||
storageInterm.initialize(context, width, height);
|
|
||||||
storageDstCopy.initialize(context, width, height);
|
storageDstCopy.initialize(context, width, height);
|
||||||
// composition and blend geometries
|
// composition and blend geometries
|
||||||
meshData.blitBox(context);
|
meshData.blitBox(context);
|
||||||
|
@ -57,9 +55,7 @@ void WgCompositor::release(WgContext& context)
|
||||||
// composition and blend geometries
|
// composition and blend geometries
|
||||||
meshData.release(context);
|
meshData.release(context);
|
||||||
// release intermediate render storages
|
// release intermediate render storages
|
||||||
storageInterm.release(context);
|
|
||||||
storageDstCopy.release(context);
|
storageDstCopy.release(context);
|
||||||
storageClipPath.release(context);
|
|
||||||
// release opacity pool
|
// release opacity pool
|
||||||
for (uint32_t i = 0; i < 256; i++) {
|
for (uint32_t i = 0; i < 256; i++) {
|
||||||
context.pipelines->layouts.releaseBindGroup(bindGroupOpacities[i]);
|
context.pipelines->layouts.releaseBindGroup(bindGroupOpacities[i]);
|
||||||
|
@ -94,7 +90,12 @@ void WgCompositor::beginRenderPass(WGPUCommandEncoder commandEncoder, WgRenderSt
|
||||||
assert(target);
|
assert(target);
|
||||||
this->currentTarget = target;
|
this->currentTarget = target;
|
||||||
this->commandEncoder = commandEncoder;
|
this->commandEncoder = commandEncoder;
|
||||||
WGPURenderPassDepthStencilAttachment depthStencilAttachment{ .view = texViewStencil, .stencilLoadOp = WGPULoadOp_Clear, .stencilStoreOp = WGPUStoreOp_Discard };
|
const WGPURenderPassDepthStencilAttachment depthStencilAttachment{
|
||||||
|
.view = texViewStencil,
|
||||||
|
.depthLoadOp = WGPULoadOp_Load, .depthStoreOp = WGPUStoreOp_Discard, .depthClearValue = 1.0f,
|
||||||
|
.stencilLoadOp = WGPULoadOp_Load, .stencilStoreOp = WGPUStoreOp_Discard, .stencilClearValue = 0
|
||||||
|
};
|
||||||
|
//WGPURenderPassDepthStencilAttachment depthStencilAttachment{ .view = texViewStencil, .depthClearValue = 1.0f, .stencilLoadOp = WGPULoadOp_Clear, .stencilStoreOp = WGPUStoreOp_Discard };
|
||||||
WGPURenderPassColorAttachment colorAttachment{};
|
WGPURenderPassColorAttachment colorAttachment{};
|
||||||
colorAttachment.view = target->texView,
|
colorAttachment.view = target->texView,
|
||||||
colorAttachment.loadOp = clear ? WGPULoadOp_Clear : WGPULoadOp_Load,
|
colorAttachment.loadOp = clear ? WGPULoadOp_Clear : WGPULoadOp_Load,
|
||||||
|
@ -124,14 +125,15 @@ void WgCompositor::renderShape(WgContext& context, WgRenderDataShape* renderData
|
||||||
assert(renderPassEncoder);
|
assert(renderPassEncoder);
|
||||||
// apply clip path if neccessary
|
// apply clip path if neccessary
|
||||||
if (renderData->clips.count != 0) {
|
if (renderData->clips.count != 0) {
|
||||||
renderClipPath(context, renderData, &storageClipPath);
|
renderClipPath(context, renderData);
|
||||||
if (renderData->strokeFirst) {
|
if (renderData->strokeFirst) {
|
||||||
clipStrokes(context, renderData, &storageClipPath);
|
clipStrokes(context, renderData);
|
||||||
clipShape(context, renderData, &storageClipPath);
|
clipShape(context, renderData);
|
||||||
} else {
|
} else {
|
||||||
clipShape(context, renderData, &storageClipPath);
|
clipShape(context, renderData);
|
||||||
clipStrokes(context, renderData, &storageClipPath);
|
clipStrokes(context, renderData);
|
||||||
}
|
}
|
||||||
|
clearClipPath(context, renderData);
|
||||||
// use custom blending
|
// use custom blending
|
||||||
} else if (blendMethod != BlendMethod::Normal) {
|
} else if (blendMethod != BlendMethod::Normal) {
|
||||||
if (renderData->strokeFirst) {
|
if (renderData->strokeFirst) {
|
||||||
|
@ -160,8 +162,9 @@ void WgCompositor::renderImage(WgContext& context, WgRenderDataPicture* renderDa
|
||||||
assert(renderPassEncoder);
|
assert(renderPassEncoder);
|
||||||
// apply clip path if neccessary
|
// apply clip path if neccessary
|
||||||
if (renderData->clips.count != 0) {
|
if (renderData->clips.count != 0) {
|
||||||
renderClipPath(context, renderData, &storageClipPath);
|
renderClipPath(context, renderData);
|
||||||
clipImage(context, renderData, &storageClipPath);
|
clipImage(context, renderData);
|
||||||
|
clearClipPath(context, renderData);
|
||||||
// use custom blending
|
// use custom blending
|
||||||
} else if (blendMethod != BlendMethod::Normal)
|
} else if (blendMethod != BlendMethod::Normal)
|
||||||
blendImage(context, renderData, blendMethod);
|
blendImage(context, renderData, blendMethod);
|
||||||
|
@ -200,12 +203,16 @@ void WgCompositor::composeScene(WgContext& context, WgRenderStorage* src, WgRend
|
||||||
|
|
||||||
|
|
||||||
void WgCompositor::blit(WgContext& context, WGPUCommandEncoder encoder, WgRenderStorage* src, WGPUTextureView dstView) {
|
void WgCompositor::blit(WgContext& context, WGPUCommandEncoder encoder, WgRenderStorage* src, WGPUTextureView dstView) {
|
||||||
WGPURenderPassDepthStencilAttachment depthStencilAttachment{ .view = texViewStencil, .stencilLoadOp = WGPULoadOp_Load, .stencilStoreOp = WGPUStoreOp_Discard };
|
const WGPURenderPassDepthStencilAttachment depthStencilAttachment{
|
||||||
|
.view = texViewStencil,
|
||||||
|
.depthLoadOp = WGPULoadOp_Load, .depthStoreOp = WGPUStoreOp_Discard,
|
||||||
|
.stencilLoadOp = WGPULoadOp_Load, .stencilStoreOp = WGPUStoreOp_Discard
|
||||||
|
};
|
||||||
WGPURenderPassColorAttachment colorAttachment { .view = dstView, .loadOp = WGPULoadOp_Load, .storeOp = WGPUStoreOp_Store };
|
WGPURenderPassColorAttachment colorAttachment { .view = dstView, .loadOp = WGPULoadOp_Load, .storeOp = WGPUStoreOp_Store };
|
||||||
#ifdef __EMSCRIPTEN__
|
#ifdef __EMSCRIPTEN__
|
||||||
colorAttachment.depthSlice = WGPU_DEPTH_SLICE_UNDEFINED;
|
colorAttachment.depthSlice = WGPU_DEPTH_SLICE_UNDEFINED;
|
||||||
#endif
|
#endif
|
||||||
WGPURenderPassDescriptor renderPassDesc{ .colorAttachmentCount = 1, .colorAttachments = &colorAttachment, .depthStencilAttachment = &depthStencilAttachment };
|
const WGPURenderPassDescriptor renderPassDesc{ .colorAttachmentCount = 1, .colorAttachments = &colorAttachment, .depthStencilAttachment = &depthStencilAttachment };
|
||||||
WGPURenderPassEncoder renderPass = wgpuCommandEncoderBeginRenderPass(encoder, &renderPassDesc);
|
WGPURenderPassEncoder renderPass = wgpuCommandEncoderBeginRenderPass(encoder, &renderPassDesc);
|
||||||
wgpuRenderPassEncoderSetBindGroup(renderPass, 0, src->bindGroupTexure, 0, nullptr);
|
wgpuRenderPassEncoderSetBindGroup(renderPass, 0, src->bindGroupTexure, 0, nullptr);
|
||||||
wgpuRenderPassEncoderSetPipeline(renderPass, pipelines->blit);
|
wgpuRenderPassEncoderSetPipeline(renderPass, pipelines->blit);
|
||||||
|
@ -302,26 +309,46 @@ void WgCompositor::blendShape(WgContext& context, WgRenderDataShape* renderData,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void WgCompositor::clipShape(WgContext& context, WgRenderDataShape* renderData, WgRenderStorage* mask)
|
void WgCompositor::clipShape(WgContext& context, WgRenderDataShape* renderData)
|
||||||
{
|
{
|
||||||
assert(mask);
|
|
||||||
assert(renderData);
|
assert(renderData);
|
||||||
assert(commandEncoder);
|
assert(renderPassEncoder);
|
||||||
assert(currentTarget);
|
assert(renderData->meshGroupShapes.meshes.count == renderData->meshGroupShapesBBox.meshes.count);
|
||||||
// skip shape composing if shape do not exist
|
|
||||||
if (renderData->renderSettingsShape.skip) return;
|
if (renderData->renderSettingsShape.skip) return;
|
||||||
if (renderData->meshGroupShapes.meshes.count == 0) return;
|
if (renderData->meshGroupShapes.meshes.count == 0) return;
|
||||||
// store current render pass
|
if ((renderData->viewport.w <= 0) || (renderData->viewport.h <= 0)) return;
|
||||||
WgRenderStorage *target = currentTarget;
|
wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, renderData->viewport.x, renderData->viewport.y, renderData->viewport.w, renderData->viewport.h);
|
||||||
endRenderPass();
|
// setup stencil rules
|
||||||
// render into intermediate buffer
|
WGPURenderPipeline stencilPipeline = (renderData->fillRule == FillRule::Winding) ? pipelines->winding : pipelines->evenodd;
|
||||||
beginRenderPass(commandEncoder, &storageInterm, true);
|
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
||||||
drawShape(context, renderData);
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr);
|
||||||
endRenderPass();
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr);
|
||||||
// restore current render pass
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, stencilPipeline);
|
||||||
beginRenderPass(commandEncoder, target, false);
|
// draw to stencil (first pass)
|
||||||
RenderRegion rect = shrinkRenderRegion(renderData->aabb);
|
for (uint32_t i = 0; i < renderData->meshGroupShapes.meshes.count; i++)
|
||||||
clipRegion(context, &storageInterm, mask, rect);
|
renderData->meshGroupShapes.meshes[i]->drawFan(context, renderPassEncoder);
|
||||||
|
// merge depth and stencil buffer
|
||||||
|
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
||||||
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, bindGroupOpacities[128], 0, nullptr);
|
||||||
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines->merge_depth_stencil);
|
||||||
|
renderData->meshDataBBox.drawFan(context, renderPassEncoder);
|
||||||
|
// setup fill rules
|
||||||
|
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
||||||
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr);
|
||||||
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr);
|
||||||
|
WgRenderSettings& settings = renderData->renderSettingsShape;
|
||||||
|
if (settings.fillType == WgRenderSettingsType::Solid) {
|
||||||
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, settings.bindGroupSolid, 0, nullptr);
|
||||||
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines->solid);
|
||||||
|
} else if (settings.fillType == WgRenderSettingsType::Linear) {
|
||||||
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, settings.bindGroupGradient, 0, nullptr);
|
||||||
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines->linear);
|
||||||
|
} else if (settings.fillType == WgRenderSettingsType::Radial) {
|
||||||
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, settings.bindGroupGradient, 0, nullptr);
|
||||||
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines->radial);
|
||||||
|
}
|
||||||
|
// draw to color (second pass)
|
||||||
|
renderData->meshDataBBox.drawFan(context, renderPassEncoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -413,26 +440,47 @@ void WgCompositor::blendStrokes(WgContext& context, WgRenderDataShape* renderDat
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
void WgCompositor::clipStrokes(WgContext& context, WgRenderDataShape* renderData, WgRenderStorage* mask)
|
void WgCompositor::clipStrokes(WgContext& context, WgRenderDataShape* renderData)
|
||||||
{
|
{
|
||||||
assert(mask);
|
|
||||||
assert(renderData);
|
assert(renderData);
|
||||||
assert(commandEncoder);
|
assert(renderPassEncoder);
|
||||||
assert(currentTarget);
|
assert(renderData->meshGroupStrokes.meshes.count == renderData->meshGroupStrokesBBox.meshes.count);
|
||||||
// skip shape composing if strokes do not exist
|
|
||||||
if (renderData->renderSettingsStroke.skip) return;
|
if (renderData->renderSettingsStroke.skip) return;
|
||||||
if (renderData->meshGroupStrokes.meshes.count == 0) return;
|
if (renderData->meshGroupStrokes.meshes.count == 0) return;
|
||||||
// store current render pass
|
if ((renderData->viewport.w <= 0) || (renderData->viewport.h <= 0)) return;
|
||||||
WgRenderStorage *target = currentTarget;
|
wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, renderData->viewport.x, renderData->viewport.y, renderData->viewport.w, renderData->viewport.h);
|
||||||
endRenderPass();
|
// draw strokes to stencil (first pass)
|
||||||
// render into intermediate buffer
|
for (uint32_t i = 0; i < renderData->meshGroupStrokes.meshes.count; i++) {
|
||||||
beginRenderPass(commandEncoder, &storageInterm, true);
|
// setup stencil rules
|
||||||
drawStrokes(context, renderData);
|
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 255);
|
||||||
endRenderPass();
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr);
|
||||||
// restore current render pass
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr);
|
||||||
beginRenderPass(commandEncoder, target, false);
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines->direct);
|
||||||
RenderRegion rect = shrinkRenderRegion(renderData->aabb);
|
// draw to stencil (first pass)
|
||||||
clipRegion(context, &storageInterm, mask, rect);
|
renderData->meshGroupStrokes.meshes[i]->draw(context, renderPassEncoder);
|
||||||
|
// merge depth and stencil buffer
|
||||||
|
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
||||||
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, bindGroupOpacities[128], 0, nullptr);
|
||||||
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines->merge_depth_stencil);
|
||||||
|
renderData->meshDataBBox.drawFan(context, renderPassEncoder);
|
||||||
|
// setup fill rules
|
||||||
|
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
||||||
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr);
|
||||||
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr);
|
||||||
|
WgRenderSettings& settings = renderData->renderSettingsStroke;
|
||||||
|
if (settings.fillType == WgRenderSettingsType::Solid) {
|
||||||
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, settings.bindGroupSolid, 0, nullptr);
|
||||||
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines->solid);
|
||||||
|
} else if (settings.fillType == WgRenderSettingsType::Linear) {
|
||||||
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, settings.bindGroupGradient, 0, nullptr);
|
||||||
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines->linear);
|
||||||
|
} else if (settings.fillType == WgRenderSettingsType::Radial) {
|
||||||
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, settings.bindGroupGradient, 0, nullptr);
|
||||||
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines->radial);
|
||||||
|
}
|
||||||
|
// draw to color (second pass)
|
||||||
|
renderData->meshGroupStrokesBBox.meshes[i]->drawFan(context, renderPassEncoder);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -442,6 +490,13 @@ void WgCompositor::drawImage(WgContext& context, WgRenderDataPicture* renderData
|
||||||
assert(renderPassEncoder);
|
assert(renderPassEncoder);
|
||||||
if ((renderData->viewport.w <= 0) || (renderData->viewport.h <= 0)) return;
|
if ((renderData->viewport.w <= 0) || (renderData->viewport.h <= 0)) return;
|
||||||
wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, renderData->viewport.x, renderData->viewport.y, renderData->viewport.w, renderData->viewport.h);
|
wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, renderData->viewport.x, renderData->viewport.y, renderData->viewport.w, renderData->viewport.h);
|
||||||
|
// draw stencil
|
||||||
|
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 255);
|
||||||
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr);
|
||||||
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr);
|
||||||
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines->direct);
|
||||||
|
renderData->meshData.drawImage(context, renderPassEncoder);
|
||||||
|
// draw image
|
||||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
||||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr);
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr);
|
||||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr);
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr);
|
||||||
|
@ -456,6 +511,7 @@ void WgCompositor::blendImage(WgContext& context, WgRenderDataPicture* renderDat
|
||||||
assert(renderData);
|
assert(renderData);
|
||||||
assert(renderPassEncoder);
|
assert(renderPassEncoder);
|
||||||
if ((renderData->viewport.w <= 0) || (renderData->viewport.h <= 0)) return;
|
if ((renderData->viewport.w <= 0) || (renderData->viewport.h <= 0)) return;
|
||||||
|
wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, renderData->viewport.x, renderData->viewport.y, renderData->viewport.w, renderData->viewport.h);
|
||||||
// copy current render target data to dst storage
|
// copy current render target data to dst storage
|
||||||
WgRenderStorage *target = currentTarget;
|
WgRenderStorage *target = currentTarget;
|
||||||
endRenderPass();
|
endRenderPass();
|
||||||
|
@ -464,9 +520,14 @@ void WgCompositor::blendImage(WgContext& context, WgRenderDataPicture* renderDat
|
||||||
const WGPUExtent3D copySize { .width = width, .height = height, .depthOrArrayLayers = 1 };
|
const WGPUExtent3D copySize { .width = width, .height = height, .depthOrArrayLayers = 1 };
|
||||||
wgpuCommandEncoderCopyTextureToTexture(commandEncoder, &texSrc, &texDst, ©Size);
|
wgpuCommandEncoderCopyTextureToTexture(commandEncoder, &texSrc, &texDst, ©Size);
|
||||||
beginRenderPass(commandEncoder, target, false);
|
beginRenderPass(commandEncoder, target, false);
|
||||||
|
// setup stencil rules
|
||||||
|
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 255);
|
||||||
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr);
|
||||||
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr);
|
||||||
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines->direct);
|
||||||
|
renderData->meshData.drawImage(context, renderPassEncoder);
|
||||||
// blend image
|
// blend image
|
||||||
uint32_t blendMethodInd = (uint32_t)blendMethod;
|
uint32_t blendMethodInd = (uint32_t)blendMethod;
|
||||||
wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, renderData->viewport.x, renderData->viewport.y, renderData->viewport.w, renderData->viewport.h);
|
|
||||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
||||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr);
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr);
|
||||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr);
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr);
|
||||||
|
@ -477,23 +538,30 @@ void WgCompositor::blendImage(WgContext& context, WgRenderDataPicture* renderDat
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
void WgCompositor::clipImage(WgContext& context, WgRenderDataPicture* renderData, WgRenderStorage* mask)
|
void WgCompositor::clipImage(WgContext& context, WgRenderDataPicture* renderData)
|
||||||
{
|
{
|
||||||
assert(mask);
|
|
||||||
assert(renderData);
|
assert(renderData);
|
||||||
assert(commandEncoder);
|
assert(renderPassEncoder);
|
||||||
assert(currentTarget);
|
if ((renderData->viewport.w <= 0) || (renderData->viewport.h <= 0)) return;
|
||||||
// store current render pass
|
wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, renderData->viewport.x, renderData->viewport.y, renderData->viewport.w, renderData->viewport.h);
|
||||||
WgRenderStorage *target = currentTarget;
|
// setup stencil rules
|
||||||
endRenderPass();
|
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 255);
|
||||||
// render into intermediate buffer
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr);
|
||||||
beginRenderPass(commandEncoder, &storageInterm, true);
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr);
|
||||||
drawImage(context, renderData);
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines->direct);
|
||||||
endRenderPass();
|
renderData->meshData.drawImage(context, renderPassEncoder);
|
||||||
// restore current render pass
|
// merge depth and stencil buffer
|
||||||
beginRenderPass(commandEncoder, target, false);
|
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
||||||
RenderRegion rect { 0, 0, (int32_t)width, (int32_t)height };
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, bindGroupOpacities[128], 0, nullptr);
|
||||||
clipRegion(context, &storageInterm, mask, rect);
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines->merge_depth_stencil);
|
||||||
|
renderData->meshData.drawImage(context, renderPassEncoder);
|
||||||
|
// draw image
|
||||||
|
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
||||||
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr);
|
||||||
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr);
|
||||||
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, renderData->bindGroupPicture, 0, nullptr);
|
||||||
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines->image);
|
||||||
|
renderData->meshData.drawImage(context, renderPassEncoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -539,85 +607,91 @@ void WgCompositor::blendScene(WgContext& context, WgRenderStorage* scene, WgComp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void WgCompositor::drawClipPath(WgContext& context, WgRenderDataShape* renderData)
|
void WgCompositor::renderClipPath(WgContext& context, WgRenderDataPaint* paint)
|
||||||
{
|
{
|
||||||
assert(renderData);
|
assert(paint);
|
||||||
assert(renderPassEncoder);
|
assert(renderPassEncoder);
|
||||||
assert(renderData->meshGroupShapes.meshes.count == renderData->meshGroupShapesBBox.meshes.count);
|
assert(paint->clips.count > 0);
|
||||||
if ((renderData->viewport.w <= 0) || (renderData->viewport.h <= 0)) return;
|
// reset scissor recr to full screen
|
||||||
wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, renderData->viewport.x, renderData->viewport.y, renderData->viewport.w, renderData->viewport.h);
|
wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, 0, 0, width, height);
|
||||||
// setup stencil rules
|
// get render data
|
||||||
WGPURenderPipeline stencilPipeline = (renderData->fillRule == FillRule::Winding) ? pipelines->winding : pipelines->evenodd;
|
WgRenderDataShape* renderData0 = (WgRenderDataShape*)paint->clips[0];
|
||||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
// set transformations
|
||||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr);
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr);
|
||||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr);
|
// markup stencil
|
||||||
|
WGPURenderPipeline stencilPipeline = (renderData0->fillRule == FillRule::Winding) ? pipelines->winding : pipelines->evenodd;
|
||||||
|
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
||||||
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData0->bindGroupPaint, 0, nullptr);
|
||||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, stencilPipeline);
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, stencilPipeline);
|
||||||
// draw to stencil (first pass)
|
for (uint32_t i = 0; i < renderData0->meshGroupShapes.meshes.count; i++)
|
||||||
for (uint32_t i = 0; i < renderData->meshGroupShapes.meshes.count; i++)
|
renderData0->meshGroupShapes.meshes[i]->drawFan(context, renderPassEncoder);
|
||||||
renderData->meshGroupShapes.meshes[i]->drawFan(context, renderPassEncoder);
|
// copy stencil to depth
|
||||||
// setup fill rules
|
|
||||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
||||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr);
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData0->bindGroupPaint, 0, nullptr);
|
||||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr);
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, bindGroupOpacities[128], 0, nullptr);
|
||||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines->clip_path);
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines->copy_stencil_to_depth);
|
||||||
// draw to color (second pass)
|
renderData0->meshDataBBox.drawFan(context, renderPassEncoder);
|
||||||
renderData->meshDataBBox.drawFan(context, renderPassEncoder);
|
// merge clip pathes with AND logic
|
||||||
}
|
for (uint32_t clipIndex = 1; clipIndex < paint->clips.count; clipIndex++) {
|
||||||
|
// get render data
|
||||||
|
WgRenderDataShape* renderData = (WgRenderDataShape*)paint->clips[clipIndex];
|
||||||
void WgCompositor::clipRegion(WgContext& context, WgRenderStorage* src, WgRenderStorage* mask, RenderRegion& rect)
|
// markup stencil
|
||||||
{
|
WGPURenderPipeline stencilPipeline = (renderData->fillRule == FillRule::Winding) ? pipelines->winding : pipelines->evenodd;
|
||||||
wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, rect.x, rect.y, rect.w, rect.h);
|
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
||||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr);
|
||||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, storageInterm.bindGroupTexure, 0, nullptr);
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, stencilPipeline);
|
||||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, mask->bindGroupTexure, 0, nullptr);
|
for (uint32_t i = 0; i < renderData->meshGroupShapes.meshes.count; i++)
|
||||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines->scene_clip);
|
renderData->meshGroupShapes.meshes[i]->drawFan(context, renderPassEncoder);
|
||||||
meshData.drawImage(context, renderPassEncoder);
|
// copy stencil to depth (clear stencil)
|
||||||
}
|
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
||||||
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr);
|
||||||
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, bindGroupOpacities[190], 0, nullptr);
|
||||||
void WgCompositor::renderClipPath(WgContext& context, WgRenderDataPaint* renderData, WgRenderStorage* dst)
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines->copy_stencil_to_depth_interm);
|
||||||
{
|
renderData->meshDataBBox.drawFan(context, renderPassEncoder);
|
||||||
assert(renderData);
|
// copy depth to stencil
|
||||||
if (renderData->clips.count == 0) return;
|
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 1);
|
||||||
// store current render pass
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr);
|
||||||
WgRenderStorage *target = currentTarget;
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, bindGroupOpacities[190], 0, nullptr);
|
||||||
endRenderPass();
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines->copy_depth_to_stencil);
|
||||||
// render first clip path
|
renderData->meshDataBBox.drawFan(context, renderPassEncoder);
|
||||||
beginRenderPass(commandEncoder, dst, true);
|
// clear depth current (keep stencil)
|
||||||
drawClipPath(context, (WgRenderDataShape*)(renderData->clips[0]));
|
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
||||||
endRenderPass();
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr);
|
||||||
// render amd merge clip paths
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, bindGroupOpacities[255], 0, nullptr);
|
||||||
for (uint32_t i = 1 ; i < renderData->clips.count; i++) {
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines->clear_depth);
|
||||||
// render clip path
|
renderData->meshDataBBox.drawFan(context, renderPassEncoder);
|
||||||
beginRenderPass(commandEncoder, &storageInterm, true);
|
// clear depth original (keep stencil)
|
||||||
drawClipPath(context, (WgRenderDataShape*)(renderData->clips[i]));
|
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
||||||
endRenderPass();
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData0->bindGroupPaint, 0, nullptr);
|
||||||
// merge masks
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, bindGroupOpacities[255], 0, nullptr);
|
||||||
mergeMasks(commandEncoder, &storageInterm, dst);
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines->clear_depth);
|
||||||
|
renderData0->meshDataBBox.drawFan(context, renderPassEncoder);
|
||||||
|
// copy stencil to depth (clear stencil)
|
||||||
|
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
||||||
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr);
|
||||||
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, bindGroupOpacities[128], 0, nullptr);
|
||||||
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines->copy_stencil_to_depth);
|
||||||
|
renderData->meshDataBBox.drawFan(context, renderPassEncoder);
|
||||||
}
|
}
|
||||||
// restore current render pass
|
|
||||||
beginRenderPass(commandEncoder, target, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void WgCompositor::mergeMasks(WGPUCommandEncoder encoder, WgRenderStorage* mask0, WgRenderStorage* mask1)
|
void WgCompositor::clearClipPath(WgContext& context, WgRenderDataPaint* paint)
|
||||||
{
|
{
|
||||||
assert(mask0);
|
assert(paint);
|
||||||
assert(mask1);
|
assert(renderPassEncoder);
|
||||||
assert(!renderPassEncoder);
|
assert(paint->clips.count > 0);
|
||||||
// copy dst storage to temporary read only storage
|
// reset scissor recr to full screen
|
||||||
const WGPUImageCopyTexture texSrc { .texture = mask1->texture };
|
wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, 0, 0, width, height);
|
||||||
const WGPUImageCopyTexture texDst { .texture = storageDstCopy.texture };
|
// get render data
|
||||||
const WGPUExtent3D copySize { .width = width, .height = height, .depthOrArrayLayers = 1 };
|
for (uint32_t clipIndex = 0; clipIndex < paint->clips.count; clipIndex++) {
|
||||||
wgpuCommandEncoderCopyTextureToTexture(encoder, &texSrc, &texDst, ©Size);
|
WgRenderDataShape* renderData = (WgRenderDataShape*)paint->clips[clipIndex];
|
||||||
// execute compose shader
|
// set transformations
|
||||||
const WGPUComputePassDescriptor computePassDescriptor{};
|
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
||||||
WGPUComputePassEncoder computePassEncoder = wgpuCommandEncoderBeginComputePass(encoder, &computePassDescriptor);
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr);
|
||||||
wgpuComputePassEncoderSetBindGroup(computePassEncoder, 0, mask0->bindGroupRead, 0, nullptr);
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr);
|
||||||
wgpuComputePassEncoderSetBindGroup(computePassEncoder, 1, storageDstCopy.bindGroupRead, 0, nullptr);
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, bindGroupOpacities[255], 0, nullptr);
|
||||||
wgpuComputePassEncoderSetBindGroup(computePassEncoder, 2, mask1->bindGroupWrite, 0, nullptr);
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines->clear_depth);
|
||||||
wgpuComputePassEncoderSetPipeline(computePassEncoder, pipelines->merge_masks);
|
renderData->meshDataBBox.drawFan(context, renderPassEncoder);
|
||||||
wgpuComputePassEncoderDispatchWorkgroups(computePassEncoder, (width + 7) / 8, (height + 7) / 8, 1);
|
}
|
||||||
wgpuComputePassEncoderEnd(computePassEncoder);
|
}
|
||||||
}
|
|
|
@ -51,8 +51,6 @@ private:
|
||||||
WGPUCommandEncoder commandEncoder{};
|
WGPUCommandEncoder commandEncoder{};
|
||||||
WgRenderStorage* currentTarget{};
|
WgRenderStorage* currentTarget{};
|
||||||
// intermediate render storages
|
// intermediate render storages
|
||||||
WgRenderStorage storageInterm;
|
|
||||||
WgRenderStorage storageClipPath;
|
|
||||||
WgRenderStorage storageDstCopy;
|
WgRenderStorage storageDstCopy;
|
||||||
// composition and blend geometries
|
// composition and blend geometries
|
||||||
WgMeshData meshData;
|
WgMeshData meshData;
|
||||||
|
@ -82,27 +80,24 @@ private:
|
||||||
// shapes
|
// shapes
|
||||||
void drawShape(WgContext& context, WgRenderDataShape* renderData);
|
void drawShape(WgContext& context, WgRenderDataShape* renderData);
|
||||||
void blendShape(WgContext& context, WgRenderDataShape* renderData, BlendMethod blendMethod);
|
void blendShape(WgContext& context, WgRenderDataShape* renderData, BlendMethod blendMethod);
|
||||||
void clipShape(WgContext& context, WgRenderDataShape* renderData, WgRenderStorage* mask); // TODO: optimize
|
void clipShape(WgContext& context, WgRenderDataShape* renderData);
|
||||||
|
|
||||||
// strokes
|
// strokes
|
||||||
void drawStrokes(WgContext& context, WgRenderDataShape* renderData);
|
void drawStrokes(WgContext& context, WgRenderDataShape* renderData);
|
||||||
void blendStrokes(WgContext& context, WgRenderDataShape* renderData, BlendMethod blendMethod);
|
void blendStrokes(WgContext& context, WgRenderDataShape* renderData, BlendMethod blendMethod);
|
||||||
void clipStrokes(WgContext& context, WgRenderDataShape* renderData, WgRenderStorage* mask); // TODO: optimize
|
void clipStrokes(WgContext& context, WgRenderDataShape* renderData);
|
||||||
|
|
||||||
// images
|
// images
|
||||||
void drawImage(WgContext& context, WgRenderDataPicture* renderData);
|
void drawImage(WgContext& context, WgRenderDataPicture* renderData);
|
||||||
void blendImage(WgContext& context, WgRenderDataPicture* renderData, BlendMethod blendMethod);
|
void blendImage(WgContext& context, WgRenderDataPicture* renderData, BlendMethod blendMethod);
|
||||||
void clipImage(WgContext& context, WgRenderDataPicture* renderData, WgRenderStorage* mask); // TODO: optimize
|
void clipImage(WgContext& context, WgRenderDataPicture* renderData);
|
||||||
|
|
||||||
// scenes
|
// scenes
|
||||||
void drawScene(WgContext& context, WgRenderStorage* scene, WgCompose* compose);
|
void drawScene(WgContext& context, WgRenderStorage* scene, WgCompose* compose);
|
||||||
void blendScene(WgContext& context, WgRenderStorage* src, WgCompose* compose);
|
void blendScene(WgContext& context, WgRenderStorage* src, WgCompose* compose);
|
||||||
private:
|
private:
|
||||||
// clip path utils (TODO: optimize)
|
void renderClipPath(WgContext& context, WgRenderDataPaint* paint);
|
||||||
void drawClipPath(WgContext& context, WgRenderDataShape* renderData);
|
void clearClipPath(WgContext& context, WgRenderDataPaint* paint);
|
||||||
void clipRegion(WgContext& context, WgRenderStorage* src, WgRenderStorage* mask, RenderRegion& rect);
|
|
||||||
void renderClipPath(WgContext& context, WgRenderDataPaint* renderData, WgRenderStorage* dst);
|
|
||||||
void mergeMasks(WGPUCommandEncoder encoder, WgRenderStorage* mask0, WgRenderStorage* mask1);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _TVG_WG_COMPOSITOR_H_
|
#endif // _TVG_WG_COMPOSITOR_H_
|
||||||
|
|
|
@ -49,14 +49,15 @@ WGPURenderPipeline WgPipelines::createRenderPipeline(
|
||||||
const WGPUColorWriteMaskFlags writeMask, const WGPUTextureFormat colorTargetFormat,
|
const WGPUColorWriteMaskFlags writeMask, const WGPUTextureFormat colorTargetFormat,
|
||||||
const WGPUCompareFunction stencilFunctionFrnt, const WGPUStencilOperation stencilOperationFrnt,
|
const WGPUCompareFunction stencilFunctionFrnt, const WGPUStencilOperation stencilOperationFrnt,
|
||||||
const WGPUCompareFunction stencilFunctionBack, const WGPUStencilOperation stencilOperationBack,
|
const WGPUCompareFunction stencilFunctionBack, const WGPUStencilOperation stencilOperationBack,
|
||||||
const WGPUPrimitiveState primitiveState, const WGPUMultisampleState multisampleState, const WGPUBlendState blendState)
|
const WGPUCompareFunction depthCompare, WGPUBool depthWriteEnabled, const WGPUMultisampleState multisampleState, const WGPUBlendState blendState)
|
||||||
{
|
{
|
||||||
const WGPUColorTargetState colorTargetState { .format = colorTargetFormat, .blend = &blendState, .writeMask = writeMask };
|
const WGPUColorTargetState colorTargetState { .format = colorTargetFormat, .blend = &blendState, .writeMask = writeMask };
|
||||||
const WGPUColorTargetState colorTargetStates[] { colorTargetState };
|
const WGPUColorTargetState colorTargetStates[] { colorTargetState };
|
||||||
|
const WGPUPrimitiveState primitiveState { .topology = WGPUPrimitiveTopology_TriangleList };
|
||||||
const WGPUDepthStencilState depthStencilState {
|
const WGPUDepthStencilState depthStencilState {
|
||||||
.format = WGPUTextureFormat_Stencil8, .depthCompare = WGPUCompareFunction_Always,
|
.format = WGPUTextureFormat_Depth24PlusStencil8, .depthWriteEnabled = depthWriteEnabled, .depthCompare = depthCompare,
|
||||||
.stencilFront = { .compare = stencilFunctionFrnt, .failOp = stencilOperationFrnt, .depthFailOp = stencilOperationFrnt, .passOp = stencilOperationFrnt },
|
.stencilFront = { .compare = stencilFunctionFrnt, .failOp = stencilOperationFrnt, .depthFailOp = WGPUStencilOperation_Zero, .passOp = stencilOperationFrnt },
|
||||||
.stencilBack = { .compare = stencilFunctionBack, .failOp = stencilOperationBack, .depthFailOp = stencilOperationBack, .passOp = stencilOperationBack },
|
.stencilBack = { .compare = stencilFunctionBack, .failOp = stencilOperationBack, .depthFailOp = WGPUStencilOperation_Zero, .passOp = stencilOperationBack },
|
||||||
.stencilReadMask = 0xFFFFFFFF, .stencilWriteMask = 0xFFFFFFFF
|
.stencilReadMask = 0xFFFFFFFF, .stencilWriteMask = 0xFFFFFFFF
|
||||||
};
|
};
|
||||||
const WGPUVertexState vertexState { .module = shaderModule, .entryPoint = vsEntryPoint, .bufferCount = vertexBufferLayoutsCount, .buffers = vertexBufferLayouts };
|
const WGPUVertexState vertexState { .module = shaderModule, .entryPoint = vsEntryPoint, .bufferCount = vertexBufferLayoutsCount, .buffers = vertexBufferLayouts };
|
||||||
|
@ -145,7 +146,6 @@ void WgPipelines::initialize(WgContext& context)
|
||||||
const WGPUVertexBufferLayout vertexBufferLayoutTex { .arrayStride = 8, .stepMode = WGPUVertexStepMode_Vertex, .attributeCount = 1, .attributes = vertexAttributesTex };
|
const WGPUVertexBufferLayout vertexBufferLayoutTex { .arrayStride = 8, .stepMode = WGPUVertexStepMode_Vertex, .attributeCount = 1, .attributes = vertexAttributesTex };
|
||||||
const WGPUVertexBufferLayout vertexBufferLayoutsShape[] { vertexBufferLayoutPos };
|
const WGPUVertexBufferLayout vertexBufferLayoutsShape[] { vertexBufferLayoutPos };
|
||||||
const WGPUVertexBufferLayout vertexBufferLayoutsImage[] { vertexBufferLayoutPos, vertexBufferLayoutTex };
|
const WGPUVertexBufferLayout vertexBufferLayoutsImage[] { vertexBufferLayoutPos, vertexBufferLayoutTex };
|
||||||
const WGPUPrimitiveState primitiveState { .topology = WGPUPrimitiveTopology_TriangleList };
|
|
||||||
const WGPUMultisampleState multisampleState { .count = 1, .mask = 0xFFFFFFFF, .alphaToCoverageEnabled = false };
|
const WGPUMultisampleState multisampleState { .count = 1, .mask = 0xFFFFFFFF, .alphaToCoverageEnabled = false };
|
||||||
const WGPUTextureFormat offscreenTargetFormat = WGPUTextureFormat_RGBA8Unorm;
|
const WGPUTextureFormat offscreenTargetFormat = WGPUTextureFormat_RGBA8Unorm;
|
||||||
|
|
||||||
|
@ -161,6 +161,7 @@ void WgPipelines::initialize(WgContext& context)
|
||||||
|
|
||||||
// bind group layouts helpers
|
// bind group layouts helpers
|
||||||
const WGPUBindGroupLayout bindGroupLayoutsStencil[] = { layouts.layoutBuffer1Un, layouts.layoutBuffer2Un };
|
const WGPUBindGroupLayout bindGroupLayoutsStencil[] = { layouts.layoutBuffer1Un, layouts.layoutBuffer2Un };
|
||||||
|
const WGPUBindGroupLayout bindGroupLayoutsDepth[] = { layouts.layoutBuffer1Un, layouts.layoutBuffer2Un, layouts.layoutBuffer1Un };
|
||||||
// bind group layouts normal blend
|
// bind group layouts normal blend
|
||||||
const WGPUBindGroupLayout bindGroupLayoutsSolid[] { layouts.layoutBuffer1Un, layouts.layoutBuffer2Un, layouts.layoutBuffer1Un };
|
const WGPUBindGroupLayout bindGroupLayoutsSolid[] { layouts.layoutBuffer1Un, layouts.layoutBuffer2Un, layouts.layoutBuffer1Un };
|
||||||
const WGPUBindGroupLayout bindGroupLayoutsGradient[] { layouts.layoutBuffer1Un, layouts.layoutBuffer2Un, layouts.layoutTexSampledBuff2Un };
|
const WGPUBindGroupLayout bindGroupLayoutsGradient[] { layouts.layoutBuffer1Un, layouts.layoutBuffer2Un, layouts.layoutTexSampledBuff2Un };
|
||||||
|
@ -173,13 +174,13 @@ void WgPipelines::initialize(WgContext& context)
|
||||||
const WGPUBindGroupLayout bindGroupLayoutsSceneBlend[] { layouts.layoutTexSampled, layouts.layoutTexSampled, layouts.layoutBuffer1Un };
|
const WGPUBindGroupLayout bindGroupLayoutsSceneBlend[] { layouts.layoutTexSampled, layouts.layoutTexSampled, layouts.layoutBuffer1Un };
|
||||||
// bind group layouts scene compose
|
// bind group layouts scene compose
|
||||||
const WGPUBindGroupLayout bindGroupLayoutsSceneCompose[] { layouts.layoutTexSampled, layouts.layoutTexSampled };
|
const WGPUBindGroupLayout bindGroupLayoutsSceneCompose[] { layouts.layoutTexSampled, layouts.layoutTexSampled };
|
||||||
const WGPUBindGroupLayout bindGroupLayoutsMergeMasks[] { layouts.layoutTexStrorage1RO, layouts.layoutTexStrorage1RO, layouts.layoutTexStrorage1WO };
|
|
||||||
// bind group layouts blit
|
// bind group layouts blit
|
||||||
const WGPUBindGroupLayout bindGroupLayoutsBlit[] { layouts.layoutTexSampled };
|
const WGPUBindGroupLayout bindGroupLayoutsBlit[] { layouts.layoutTexSampled };
|
||||||
|
|
||||||
// shaders
|
// shaders
|
||||||
char shaderSourceBuff[16384]{};
|
char shaderSourceBuff[16384]{};
|
||||||
shader_stencil = createShaderModule(context.device, "The shader stencil", cShaderSrc_Stencil);
|
shader_stencil = createShaderModule(context.device, "The shader stencil", cShaderSrc_Stencil);
|
||||||
|
shader_depth = createShaderModule(context.device, "The shader depth", cShaderSrc_Depth);
|
||||||
// shader normal blend
|
// shader normal blend
|
||||||
shader_solid = createShaderModule(context.device, "The shader solid", cShaderSrc_Solid);
|
shader_solid = createShaderModule(context.device, "The shader solid", cShaderSrc_Solid);
|
||||||
shader_radial = createShaderModule(context.device, "The shader radial", cShaderSrc_Radial);
|
shader_radial = createShaderModule(context.device, "The shader radial", cShaderSrc_Radial);
|
||||||
|
@ -194,12 +195,12 @@ void WgPipelines::initialize(WgContext& context)
|
||||||
shader_scene_blend = createShaderModule(context.device, "The shader blend scene", strcat(strcpy(shaderSourceBuff, cShaderSrc_Scene_Blend), cShaderSrc_BlendFuncs));
|
shader_scene_blend = createShaderModule(context.device, "The shader blend scene", strcat(strcpy(shaderSourceBuff, cShaderSrc_Scene_Blend), cShaderSrc_BlendFuncs));
|
||||||
// shader compose
|
// shader compose
|
||||||
shader_scene_compose = createShaderModule(context.device, "The shader scene composition", cShaderSrc_Scene_Compose);
|
shader_scene_compose = createShaderModule(context.device, "The shader scene composition", cShaderSrc_Scene_Compose);
|
||||||
shader_merge_masks = createShaderModule(context.device, "The shader merge mask", cShaderSrc_MergeMasks);
|
|
||||||
// shader blit
|
// shader blit
|
||||||
shader_blit = createShaderModule(context.device, "The shader blit", cShaderSrc_Blit);
|
shader_blit = createShaderModule(context.device, "The shader blit", cShaderSrc_Blit);
|
||||||
|
|
||||||
// layouts
|
// layouts
|
||||||
layout_stencil = createPipelineLayout(context.device, bindGroupLayoutsStencil, 2);
|
layout_stencil = createPipelineLayout(context.device, bindGroupLayoutsStencil, 2);
|
||||||
|
layout_depth = createPipelineLayout(context.device, bindGroupLayoutsDepth, 3);
|
||||||
// layouts normal blend
|
// layouts normal blend
|
||||||
layout_solid = createPipelineLayout(context.device, bindGroupLayoutsSolid, 3);
|
layout_solid = createPipelineLayout(context.device, bindGroupLayoutsSolid, 3);
|
||||||
layout_gradient = createPipelineLayout(context.device, bindGroupLayoutsGradient, 3);
|
layout_gradient = createPipelineLayout(context.device, bindGroupLayoutsGradient, 3);
|
||||||
|
@ -212,7 +213,6 @@ void WgPipelines::initialize(WgContext& context)
|
||||||
layout_scene_blend = createPipelineLayout(context.device, bindGroupLayoutsSceneBlend, 3);
|
layout_scene_blend = createPipelineLayout(context.device, bindGroupLayoutsSceneBlend, 3);
|
||||||
// layout compose
|
// layout compose
|
||||||
layout_scene_compose = createPipelineLayout(context.device, bindGroupLayoutsSceneCompose, 2);
|
layout_scene_compose = createPipelineLayout(context.device, bindGroupLayoutsSceneCompose, 2);
|
||||||
layout_merge_masks = createPipelineLayout(context.device, bindGroupLayoutsMergeMasks, 3);
|
|
||||||
// layout blit
|
// layout blit
|
||||||
layout_blit = createPipelineLayout(context.device, bindGroupLayoutsBlit, 1);
|
layout_blit = createPipelineLayout(context.device, bindGroupLayoutsBlit, 1);
|
||||||
|
|
||||||
|
@ -224,7 +224,7 @@ void WgPipelines::initialize(WgContext& context)
|
||||||
WGPUColorWriteMask_None, offscreenTargetFormat,
|
WGPUColorWriteMask_None, offscreenTargetFormat,
|
||||||
WGPUCompareFunction_Always, WGPUStencilOperation_IncrementWrap,
|
WGPUCompareFunction_Always, WGPUStencilOperation_IncrementWrap,
|
||||||
WGPUCompareFunction_Always, WGPUStencilOperation_DecrementWrap,
|
WGPUCompareFunction_Always, WGPUStencilOperation_DecrementWrap,
|
||||||
primitiveState, multisampleState, blendStateSrc);
|
WGPUCompareFunction_Always, false, multisampleState, blendStateSrc);
|
||||||
// render pipeline even-odd
|
// render pipeline even-odd
|
||||||
evenodd = createRenderPipeline(
|
evenodd = createRenderPipeline(
|
||||||
context.device, "The render pipeline even-odd",
|
context.device, "The render pipeline even-odd",
|
||||||
|
@ -233,7 +233,7 @@ void WgPipelines::initialize(WgContext& context)
|
||||||
WGPUColorWriteMask_None, offscreenTargetFormat,
|
WGPUColorWriteMask_None, offscreenTargetFormat,
|
||||||
WGPUCompareFunction_Always, WGPUStencilOperation_Invert,
|
WGPUCompareFunction_Always, WGPUStencilOperation_Invert,
|
||||||
WGPUCompareFunction_Always, WGPUStencilOperation_Invert,
|
WGPUCompareFunction_Always, WGPUStencilOperation_Invert,
|
||||||
primitiveState, multisampleState, blendStateSrc);
|
WGPUCompareFunction_Always, false, multisampleState, blendStateSrc);
|
||||||
// render pipeline direct
|
// render pipeline direct
|
||||||
direct = createRenderPipeline(
|
direct = createRenderPipeline(
|
||||||
context.device, "The render pipeline direct",
|
context.device, "The render pipeline direct",
|
||||||
|
@ -242,16 +242,53 @@ void WgPipelines::initialize(WgContext& context)
|
||||||
WGPUColorWriteMask_None, offscreenTargetFormat,
|
WGPUColorWriteMask_None, offscreenTargetFormat,
|
||||||
WGPUCompareFunction_Always, WGPUStencilOperation_Replace,
|
WGPUCompareFunction_Always, WGPUStencilOperation_Replace,
|
||||||
WGPUCompareFunction_Always, WGPUStencilOperation_Replace,
|
WGPUCompareFunction_Always, WGPUStencilOperation_Replace,
|
||||||
primitiveState, multisampleState, blendStateSrc);
|
WGPUCompareFunction_Always, false, multisampleState, blendStateSrc);
|
||||||
// render pipeline clip path
|
|
||||||
clip_path = createRenderPipeline(
|
// render pipeline copy stencil to depth (front)
|
||||||
context.device, "The render pipeline clip path",
|
copy_stencil_to_depth = createRenderPipeline(
|
||||||
shader_stencil, "vs_main", "fs_main", layout_stencil,
|
context.device, "The render pipeline copy stencil to depth front",
|
||||||
|
shader_depth, "vs_main", "fs_main", layout_depth,
|
||||||
vertexBufferLayoutsShape, 1,
|
vertexBufferLayoutsShape, 1,
|
||||||
WGPUColorWriteMask_All, offscreenTargetFormat,
|
WGPUColorWriteMask_None, offscreenTargetFormat,
|
||||||
WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero,
|
WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero,
|
||||||
WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero,
|
WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero,
|
||||||
primitiveState, multisampleState, blendStateSrc);
|
WGPUCompareFunction_Always, true, multisampleState, blendStateSrc);
|
||||||
|
// 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,
|
||||||
|
WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero,
|
||||||
|
WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero,
|
||||||
|
WGPUCompareFunction_Greater, true, multisampleState, blendStateSrc);
|
||||||
|
// 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,
|
||||||
|
WGPUCompareFunction_Always, WGPUStencilOperation_Replace,
|
||||||
|
WGPUCompareFunction_Always, WGPUStencilOperation_Replace,
|
||||||
|
WGPUCompareFunction_Equal, false, multisampleState, blendStateSrc);
|
||||||
|
// 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,
|
||||||
|
WGPUCompareFunction_Always, WGPUStencilOperation_Keep,
|
||||||
|
WGPUCompareFunction_Always, WGPUStencilOperation_Keep,
|
||||||
|
WGPUCompareFunction_Equal, true, multisampleState, blendStateSrc);
|
||||||
|
// 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,
|
||||||
|
WGPUCompareFunction_Always, WGPUStencilOperation_Keep,
|
||||||
|
WGPUCompareFunction_Always, WGPUStencilOperation_Keep,
|
||||||
|
WGPUCompareFunction_Always, true, multisampleState, blendStateSrc);
|
||||||
|
|
||||||
// render pipeline solid
|
// render pipeline solid
|
||||||
solid = createRenderPipeline(
|
solid = createRenderPipeline(
|
||||||
|
@ -261,7 +298,7 @@ void WgPipelines::initialize(WgContext& context)
|
||||||
WGPUColorWriteMask_All, offscreenTargetFormat,
|
WGPUColorWriteMask_All, offscreenTargetFormat,
|
||||||
WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero,
|
WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero,
|
||||||
WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero,
|
WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero,
|
||||||
primitiveState, multisampleState, blendStateNrm);
|
WGPUCompareFunction_Always, false, multisampleState, blendStateNrm);
|
||||||
// render pipeline radial
|
// render pipeline radial
|
||||||
radial = createRenderPipeline(
|
radial = createRenderPipeline(
|
||||||
context.device, "The render pipeline radial",
|
context.device, "The render pipeline radial",
|
||||||
|
@ -270,7 +307,7 @@ void WgPipelines::initialize(WgContext& context)
|
||||||
WGPUColorWriteMask_All, offscreenTargetFormat,
|
WGPUColorWriteMask_All, offscreenTargetFormat,
|
||||||
WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero,
|
WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero,
|
||||||
WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero,
|
WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero,
|
||||||
primitiveState, multisampleState, blendStateNrm);
|
WGPUCompareFunction_Always, false, multisampleState, blendStateNrm);
|
||||||
// render pipeline linear
|
// render pipeline linear
|
||||||
linear = createRenderPipeline(
|
linear = createRenderPipeline(
|
||||||
context.device, "The render pipeline linear",
|
context.device, "The render pipeline linear",
|
||||||
|
@ -279,16 +316,16 @@ void WgPipelines::initialize(WgContext& context)
|
||||||
WGPUColorWriteMask_All, offscreenTargetFormat,
|
WGPUColorWriteMask_All, offscreenTargetFormat,
|
||||||
WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero,
|
WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero,
|
||||||
WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero,
|
WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero,
|
||||||
primitiveState, multisampleState, blendStateNrm);
|
WGPUCompareFunction_Always, false, multisampleState, blendStateNrm);
|
||||||
// render pipeline image
|
// render pipeline image
|
||||||
image = createRenderPipeline(
|
image = createRenderPipeline(
|
||||||
context.device, "The render pipeline image",
|
context.device, "The render pipeline image",
|
||||||
shader_image, "vs_main", "fs_main", layout_image,
|
shader_image, "vs_main", "fs_main", layout_image,
|
||||||
vertexBufferLayoutsImage, 2,
|
vertexBufferLayoutsImage, 2,
|
||||||
WGPUColorWriteMask_All, offscreenTargetFormat,
|
WGPUColorWriteMask_All, offscreenTargetFormat,
|
||||||
WGPUCompareFunction_Always, WGPUStencilOperation_Zero,
|
WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero,
|
||||||
WGPUCompareFunction_Always, WGPUStencilOperation_Zero,
|
WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero,
|
||||||
primitiveState, multisampleState, blendStateNrm);
|
WGPUCompareFunction_Always, false, multisampleState, blendStateNrm);
|
||||||
// render pipeline scene
|
// render pipeline scene
|
||||||
scene = createRenderPipeline(
|
scene = createRenderPipeline(
|
||||||
context.device, "The render pipeline scene",
|
context.device, "The render pipeline scene",
|
||||||
|
@ -297,7 +334,7 @@ void WgPipelines::initialize(WgContext& context)
|
||||||
WGPUColorWriteMask_All, offscreenTargetFormat,
|
WGPUColorWriteMask_All, offscreenTargetFormat,
|
||||||
WGPUCompareFunction_Always, WGPUStencilOperation_Zero,
|
WGPUCompareFunction_Always, WGPUStencilOperation_Zero,
|
||||||
WGPUCompareFunction_Always, WGPUStencilOperation_Zero,
|
WGPUCompareFunction_Always, WGPUStencilOperation_Zero,
|
||||||
primitiveState, multisampleState, blendStateNrm);
|
WGPUCompareFunction_Always, false, multisampleState, blendStateNrm);
|
||||||
|
|
||||||
// blend shader names
|
// blend shader names
|
||||||
const char* shaderBlendNames[] {
|
const char* shaderBlendNames[] {
|
||||||
|
@ -330,7 +367,7 @@ void WgPipelines::initialize(WgContext& context)
|
||||||
WGPUColorWriteMask_All, offscreenTargetFormat,
|
WGPUColorWriteMask_All, offscreenTargetFormat,
|
||||||
WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero,
|
WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero,
|
||||||
WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero,
|
WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero,
|
||||||
primitiveState, multisampleState, blendStateSrc);
|
WGPUCompareFunction_Always, false, multisampleState, blendStateSrc);
|
||||||
// blend radial
|
// blend radial
|
||||||
radial_blend[i] = createRenderPipeline(context.device, "The render pipeline radial blend",
|
radial_blend[i] = createRenderPipeline(context.device, "The render pipeline radial blend",
|
||||||
shader_radial_blend, "vs_main", shaderBlendNames[i], layout_gradient_blend,
|
shader_radial_blend, "vs_main", shaderBlendNames[i], layout_gradient_blend,
|
||||||
|
@ -338,7 +375,7 @@ void WgPipelines::initialize(WgContext& context)
|
||||||
WGPUColorWriteMask_All, offscreenTargetFormat,
|
WGPUColorWriteMask_All, offscreenTargetFormat,
|
||||||
WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero,
|
WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero,
|
||||||
WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero,
|
WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero,
|
||||||
primitiveState, multisampleState, blendStateSrc);
|
WGPUCompareFunction_Always, false, multisampleState, blendStateSrc);
|
||||||
// blend linear
|
// blend linear
|
||||||
linear_blend[i] = createRenderPipeline(context.device, "The render pipeline linear blend",
|
linear_blend[i] = createRenderPipeline(context.device, "The render pipeline linear blend",
|
||||||
shader_linear_blend, "vs_main", shaderBlendNames[i], layout_gradient_blend,
|
shader_linear_blend, "vs_main", shaderBlendNames[i], layout_gradient_blend,
|
||||||
|
@ -346,15 +383,15 @@ void WgPipelines::initialize(WgContext& context)
|
||||||
WGPUColorWriteMask_All, offscreenTargetFormat,
|
WGPUColorWriteMask_All, offscreenTargetFormat,
|
||||||
WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero,
|
WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero,
|
||||||
WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero,
|
WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero,
|
||||||
primitiveState, multisampleState, blendStateSrc);
|
WGPUCompareFunction_Always, false, multisampleState, blendStateSrc);
|
||||||
// blend image
|
// blend image
|
||||||
image_blend[i] = createRenderPipeline(context.device, "The render pipeline image blend",
|
image_blend[i] = createRenderPipeline(context.device, "The render pipeline image blend",
|
||||||
shader_image_blend, "vs_main", shaderBlendNames[i], layout_image_blend,
|
shader_image_blend, "vs_main", shaderBlendNames[i], layout_image_blend,
|
||||||
vertexBufferLayoutsImage, 2,
|
vertexBufferLayoutsImage, 2,
|
||||||
WGPUColorWriteMask_All, offscreenTargetFormat,
|
WGPUColorWriteMask_All, offscreenTargetFormat,
|
||||||
WGPUCompareFunction_Always, WGPUStencilOperation_Zero,
|
WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero,
|
||||||
WGPUCompareFunction_Always, WGPUStencilOperation_Zero,
|
WGPUCompareFunction_NotEqual, WGPUStencilOperation_Zero,
|
||||||
primitiveState, multisampleState, blendStateSrc);
|
WGPUCompareFunction_Always, false, multisampleState, blendStateSrc);
|
||||||
// blend scene
|
// blend scene
|
||||||
scene_blend[i] = createRenderPipeline(context.device, "The render pipeline scene blend",
|
scene_blend[i] = createRenderPipeline(context.device, "The render pipeline scene blend",
|
||||||
shader_scene_blend, "vs_main", shaderBlendNames[i], layout_scene_blend,
|
shader_scene_blend, "vs_main", shaderBlendNames[i], layout_scene_blend,
|
||||||
|
@ -362,7 +399,7 @@ void WgPipelines::initialize(WgContext& context)
|
||||||
WGPUColorWriteMask_All, offscreenTargetFormat,
|
WGPUColorWriteMask_All, offscreenTargetFormat,
|
||||||
WGPUCompareFunction_Always, WGPUStencilOperation_Zero,
|
WGPUCompareFunction_Always, WGPUStencilOperation_Zero,
|
||||||
WGPUCompareFunction_Always, WGPUStencilOperation_Zero,
|
WGPUCompareFunction_Always, WGPUStencilOperation_Zero,
|
||||||
primitiveState, multisampleState, blendStateSrc);
|
WGPUCompareFunction_Always, false, multisampleState, blendStateSrc);
|
||||||
}
|
}
|
||||||
|
|
||||||
// compose shader names
|
// compose shader names
|
||||||
|
@ -404,24 +441,9 @@ void WgPipelines::initialize(WgContext& context)
|
||||||
WGPUColorWriteMask_All, offscreenTargetFormat,
|
WGPUColorWriteMask_All, offscreenTargetFormat,
|
||||||
WGPUCompareFunction_Always, WGPUStencilOperation_Zero,
|
WGPUCompareFunction_Always, WGPUStencilOperation_Zero,
|
||||||
WGPUCompareFunction_Always, WGPUStencilOperation_Zero,
|
WGPUCompareFunction_Always, WGPUStencilOperation_Zero,
|
||||||
primitiveState, multisampleState, composeBlends[i]);
|
WGPUCompareFunction_Always, false, multisampleState, composeBlends[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// render pipeline scene clip path
|
|
||||||
scene_clip = createRenderPipeline(
|
|
||||||
context.device, "The render pipeline scene clip path",
|
|
||||||
shader_scene_compose, "vs_main", "fs_main_ClipPath", layout_scene_compose,
|
|
||||||
vertexBufferLayoutsImage, 2,
|
|
||||||
WGPUColorWriteMask_All, offscreenTargetFormat,
|
|
||||||
WGPUCompareFunction_Always, WGPUStencilOperation_Zero,
|
|
||||||
WGPUCompareFunction_Always, WGPUStencilOperation_Zero,
|
|
||||||
primitiveState, multisampleState, blendStateNrm);
|
|
||||||
|
|
||||||
// compute pipelines
|
|
||||||
merge_masks = createComputePipeline(
|
|
||||||
context.device, "The compute pipeline merge masks",
|
|
||||||
shader_merge_masks, "cs_main", layout_merge_masks);
|
|
||||||
|
|
||||||
// render pipeline blit
|
// render pipeline blit
|
||||||
blit = createRenderPipeline(context.device, "The render pipeline blit",
|
blit = createRenderPipeline(context.device, "The render pipeline blit",
|
||||||
shader_blit, "vs_main", "fs_main", layout_blit,
|
shader_blit, "vs_main", "fs_main", layout_blit,
|
||||||
|
@ -430,7 +452,7 @@ void WgPipelines::initialize(WgContext& context)
|
||||||
WGPUColorWriteMask_All, context.preferredFormat,
|
WGPUColorWriteMask_All, context.preferredFormat,
|
||||||
WGPUCompareFunction_Always, WGPUStencilOperation_Zero,
|
WGPUCompareFunction_Always, WGPUStencilOperation_Zero,
|
||||||
WGPUCompareFunction_Always, WGPUStencilOperation_Zero,
|
WGPUCompareFunction_Always, WGPUStencilOperation_Zero,
|
||||||
primitiveState, multisampleState, blendStateSrc);
|
WGPUCompareFunction_Always, false, multisampleState, blendStateSrc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WgPipelines::releaseGraphicHandles(WgContext& context)
|
void WgPipelines::releaseGraphicHandles(WgContext& context)
|
||||||
|
@ -438,7 +460,6 @@ void WgPipelines::releaseGraphicHandles(WgContext& context)
|
||||||
// pipeline blit
|
// pipeline blit
|
||||||
releaseRenderPipeline(blit);
|
releaseRenderPipeline(blit);
|
||||||
// pipelines compose
|
// pipelines compose
|
||||||
releaseRenderPipeline(scene_clip);
|
|
||||||
for (uint32_t i = 0; i < 11; i++)
|
for (uint32_t i = 0; i < 11; i++)
|
||||||
releaseRenderPipeline(scene_compose[i]);
|
releaseRenderPipeline(scene_compose[i]);
|
||||||
// pipelines custom blend
|
// pipelines custom blend
|
||||||
|
@ -455,14 +476,18 @@ void WgPipelines::releaseGraphicHandles(WgContext& context)
|
||||||
releaseRenderPipeline(linear);
|
releaseRenderPipeline(linear);
|
||||||
releaseRenderPipeline(radial);
|
releaseRenderPipeline(radial);
|
||||||
releaseRenderPipeline(solid);
|
releaseRenderPipeline(solid);
|
||||||
// pipelines helpers
|
// pipelines clip path markup
|
||||||
releaseRenderPipeline(clip_path);
|
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(direct);
|
||||||
releaseRenderPipeline(evenodd);
|
releaseRenderPipeline(evenodd);
|
||||||
releaseRenderPipeline(winding);
|
releaseRenderPipeline(winding);
|
||||||
// layouts
|
// layouts
|
||||||
releasePipelineLayout(layout_blit);
|
releasePipelineLayout(layout_blit);
|
||||||
releasePipelineLayout(layout_merge_masks);
|
|
||||||
releasePipelineLayout(layout_scene_compose);
|
releasePipelineLayout(layout_scene_compose);
|
||||||
releasePipelineLayout(layout_scene_blend);
|
releasePipelineLayout(layout_scene_blend);
|
||||||
releasePipelineLayout(layout_image_blend);
|
releasePipelineLayout(layout_image_blend);
|
||||||
|
@ -472,10 +497,10 @@ void WgPipelines::releaseGraphicHandles(WgContext& context)
|
||||||
releasePipelineLayout(layout_image);
|
releasePipelineLayout(layout_image);
|
||||||
releasePipelineLayout(layout_gradient);
|
releasePipelineLayout(layout_gradient);
|
||||||
releasePipelineLayout(layout_solid);
|
releasePipelineLayout(layout_solid);
|
||||||
|
releasePipelineLayout(layout_depth);
|
||||||
releasePipelineLayout(layout_stencil);
|
releasePipelineLayout(layout_stencil);
|
||||||
// shaders
|
// shaders
|
||||||
releaseShaderModule(shader_blit);
|
releaseShaderModule(shader_blit);
|
||||||
releaseShaderModule(shader_merge_masks);
|
|
||||||
releaseShaderModule(shader_scene_compose);
|
releaseShaderModule(shader_scene_compose);
|
||||||
releaseShaderModule(shader_scene_blend);
|
releaseShaderModule(shader_scene_blend);
|
||||||
releaseShaderModule(shader_image_blend);
|
releaseShaderModule(shader_image_blend);
|
||||||
|
@ -487,20 +512,13 @@ void WgPipelines::releaseGraphicHandles(WgContext& context)
|
||||||
releaseShaderModule(shader_linear);
|
releaseShaderModule(shader_linear);
|
||||||
releaseShaderModule(shader_radial);
|
releaseShaderModule(shader_radial);
|
||||||
releaseShaderModule(shader_solid);
|
releaseShaderModule(shader_solid);
|
||||||
|
releaseShaderModule(shader_depth);
|
||||||
releaseShaderModule(shader_stencil);
|
releaseShaderModule(shader_stencil);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void WgPipelines::releaseComputeHandles(WgContext& context)
|
|
||||||
{
|
|
||||||
releaseComputePipeline(merge_masks);
|
|
||||||
releasePipelineLayout(layout_merge_masks);
|
|
||||||
releaseShaderModule(shader_merge_masks);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WgPipelines::release(WgContext& context)
|
void WgPipelines::release(WgContext& context)
|
||||||
{
|
{
|
||||||
releaseComputeHandles(context);
|
|
||||||
releaseGraphicHandles(context);
|
releaseGraphicHandles(context);
|
||||||
layouts.release(context);
|
layouts.release(context);
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ class WgPipelines {
|
||||||
private:
|
private:
|
||||||
// shaders helpers
|
// shaders helpers
|
||||||
WGPUShaderModule shader_stencil{};
|
WGPUShaderModule shader_stencil{};
|
||||||
|
WGPUShaderModule shader_depth{};
|
||||||
// shaders normal blend
|
// shaders normal blend
|
||||||
WGPUShaderModule shader_solid{};
|
WGPUShaderModule shader_solid{};
|
||||||
WGPUShaderModule shader_radial{};
|
WGPUShaderModule shader_radial{};
|
||||||
|
@ -43,12 +44,12 @@ private:
|
||||||
WGPUShaderModule shader_scene_blend{};
|
WGPUShaderModule shader_scene_blend{};
|
||||||
// shader scene compose
|
// shader scene compose
|
||||||
WGPUShaderModule shader_scene_compose{};
|
WGPUShaderModule shader_scene_compose{};
|
||||||
WGPUShaderModule shader_merge_masks;
|
|
||||||
// shader blit
|
// shader blit
|
||||||
WGPUShaderModule shader_blit{};
|
WGPUShaderModule shader_blit{};
|
||||||
private:
|
private:
|
||||||
// layouts helpers
|
// layouts helpers
|
||||||
WGPUPipelineLayout layout_stencil{};
|
WGPUPipelineLayout layout_stencil{};
|
||||||
|
WGPUPipelineLayout layout_depth{};
|
||||||
// layouts normal blend
|
// layouts normal blend
|
||||||
WGPUPipelineLayout layout_solid{};
|
WGPUPipelineLayout layout_solid{};
|
||||||
WGPUPipelineLayout layout_gradient{};
|
WGPUPipelineLayout layout_gradient{};
|
||||||
|
@ -61,15 +62,19 @@ private:
|
||||||
WGPUPipelineLayout layout_scene_blend{};
|
WGPUPipelineLayout layout_scene_blend{};
|
||||||
// layouts scene compose
|
// layouts scene compose
|
||||||
WGPUPipelineLayout layout_scene_compose{};
|
WGPUPipelineLayout layout_scene_compose{};
|
||||||
WGPUPipelineLayout layout_merge_masks{};
|
|
||||||
// layouts blit
|
// layouts blit
|
||||||
WGPUPipelineLayout layout_blit{};
|
WGPUPipelineLayout layout_blit{};
|
||||||
public:
|
public:
|
||||||
// pipelines helpers
|
// pipelines stencil markup
|
||||||
WGPURenderPipeline winding{};
|
WGPURenderPipeline winding{};
|
||||||
WGPURenderPipeline evenodd{};
|
WGPURenderPipeline evenodd{};
|
||||||
WGPURenderPipeline direct{};
|
WGPURenderPipeline direct{};
|
||||||
WGPURenderPipeline clip_path{};
|
// pipelines clip path markup
|
||||||
|
WGPURenderPipeline copy_stencil_to_depth{}; // depth 0.50, clear stencil
|
||||||
|
WGPURenderPipeline copy_stencil_to_depth_interm{}; // depth 0.75, clear stencil
|
||||||
|
WGPURenderPipeline copy_depth_to_stencil{}; // depth 0.50 and 0.75, update stencil
|
||||||
|
WGPURenderPipeline merge_depth_stencil{}; // depth 0.75, update stencil
|
||||||
|
WGPURenderPipeline clear_depth{}; // depth 1.00, clear ctencil
|
||||||
// pipelines normal blend
|
// pipelines normal blend
|
||||||
WGPURenderPipeline solid{};
|
WGPURenderPipeline solid{};
|
||||||
WGPURenderPipeline radial{};
|
WGPURenderPipeline radial{};
|
||||||
|
@ -84,8 +89,6 @@ public:
|
||||||
WGPURenderPipeline scene_blend[18]{};
|
WGPURenderPipeline scene_blend[18]{};
|
||||||
// pipelines compose
|
// pipelines compose
|
||||||
WGPURenderPipeline scene_compose[11]{};
|
WGPURenderPipeline scene_compose[11]{};
|
||||||
WGPURenderPipeline scene_clip{};
|
|
||||||
WGPUComputePipeline merge_masks{};
|
|
||||||
// pipeline blit
|
// pipeline blit
|
||||||
WGPURenderPipeline blit{};
|
WGPURenderPipeline blit{};
|
||||||
public:
|
public:
|
||||||
|
@ -93,7 +96,6 @@ public:
|
||||||
WgBindGroupLayouts layouts;
|
WgBindGroupLayouts layouts;
|
||||||
private:
|
private:
|
||||||
void releaseGraphicHandles(WgContext& context);
|
void releaseGraphicHandles(WgContext& context);
|
||||||
void releaseComputeHandles(WgContext& context);
|
|
||||||
private:
|
private:
|
||||||
WGPUShaderModule createShaderModule(WGPUDevice device, const char* label, const char* code);
|
WGPUShaderModule createShaderModule(WGPUDevice device, const char* label, const char* code);
|
||||||
WGPUPipelineLayout createPipelineLayout(WGPUDevice device, const WGPUBindGroupLayout* bindGroupLayouts, const uint32_t bindGroupLayoutsCount);
|
WGPUPipelineLayout createPipelineLayout(WGPUDevice device, const WGPUBindGroupLayout* bindGroupLayouts, const uint32_t bindGroupLayoutsCount);
|
||||||
|
@ -105,7 +107,7 @@ private:
|
||||||
const WGPUColorWriteMaskFlags writeMask, const WGPUTextureFormat colorTargetFormat,
|
const WGPUColorWriteMaskFlags writeMask, const WGPUTextureFormat colorTargetFormat,
|
||||||
const WGPUCompareFunction stencilFunctionFrnt, const WGPUStencilOperation stencilOperationFrnt,
|
const WGPUCompareFunction stencilFunctionFrnt, const WGPUStencilOperation stencilOperationFrnt,
|
||||||
const WGPUCompareFunction stencilFunctionBack, const WGPUStencilOperation stencilOperationBack,
|
const WGPUCompareFunction stencilFunctionBack, const WGPUStencilOperation stencilOperationBack,
|
||||||
const WGPUPrimitiveState primitiveState, const WGPUMultisampleState multisampleState, const WGPUBlendState blendState);
|
const WGPUCompareFunction depthCompare, WGPUBool depthWriteEnabled, const WGPUMultisampleState multisampleState, const WGPUBlendState blendState);
|
||||||
WGPUComputePipeline createComputePipeline(
|
WGPUComputePipeline createComputePipeline(
|
||||||
WGPUDevice device, const char* pipelineLabel,
|
WGPUDevice device, const char* pipelineLabel,
|
||||||
const WGPUShaderModule shaderModule, const char* entryPoint,
|
const WGPUShaderModule shaderModule, const char* entryPoint,
|
||||||
|
|
|
@ -49,6 +49,32 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4f {
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
|
||||||
|
//************************************************************************
|
||||||
|
// graphics shader source: depth
|
||||||
|
//************************************************************************
|
||||||
|
|
||||||
|
const char* cShaderSrc_Depth = R"(
|
||||||
|
struct VertexInput { @location(0) position: vec2f };
|
||||||
|
struct VertexOutput { @builtin(position) position: vec4f };
|
||||||
|
|
||||||
|
@group(0) @binding(0) var<uniform> uViewMat : mat4x4f;
|
||||||
|
@group(1) @binding(0) var<uniform> uModelMat : mat4x4f;
|
||||||
|
@group(2) @binding(0) var<uniform> uDepth : f32;
|
||||||
|
|
||||||
|
@vertex
|
||||||
|
fn vs_main(in: VertexInput) -> VertexOutput {
|
||||||
|
var out: VertexOutput;
|
||||||
|
out.position = uViewMat * uModelMat * vec4f(in.position.xy, 0.0, 1.0);
|
||||||
|
out.position.z = uDepth;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@fragment
|
||||||
|
fn fs_main(in: VertexOutput) -> @location(0) vec4f {
|
||||||
|
return vec4f(1.0, 0.5, 0.0, 1.0);
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
//************************************************************************
|
//************************************************************************
|
||||||
// graphics shader source: solid normal blend
|
// graphics shader source: solid normal blend
|
||||||
//************************************************************************
|
//************************************************************************
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
// helper shaders
|
// helper shaders
|
||||||
extern const char* cShaderSrc_Stencil;
|
extern const char* cShaderSrc_Stencil;
|
||||||
|
extern const char* cShaderSrc_Depth;
|
||||||
// shaders normal blend
|
// shaders normal blend
|
||||||
extern const char* cShaderSrc_Solid;
|
extern const char* cShaderSrc_Solid;
|
||||||
extern const char* cShaderSrc_Linear;
|
extern const char* cShaderSrc_Linear;
|
||||||
|
|
Loading…
Add table
Reference in a new issue