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:
Sergii Liebodkin 2024-10-22 09:23:15 +00:00 committed by Hermet Park
parent a1296960eb
commit 0815366763
6 changed files with 330 additions and 214 deletions

View file

@ -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, &copySize); wgpuCommandEncoderCopyTextureToTexture(commandEncoder, &texSrc, &texDst, &copySize);
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, &copySize); 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); }
}

View file

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

View file

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

View file

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

View file

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

View file

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