mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-14 03:54:25 +00:00
wg_engine: uniform stage buffers implementation
Introduced stage buffer for uniforms to reduce number of memory shafles from cpu to gpu memory https://github.com/thorvg/thorvg/issues/3505
This commit is contained in:
parent
4c3c5d9d06
commit
92e3c243ec
11 changed files with 354 additions and 300 deletions
|
@ -103,9 +103,15 @@ WGPUBindGroup WgBindGroupLayouts::createBindGroupStrorage3RO(WGPUTextureView tex
|
|||
|
||||
|
||||
WGPUBindGroup WgBindGroupLayouts::createBindGroupBuffer1Un(WGPUBuffer buff)
|
||||
{
|
||||
return createBindGroupBuffer1Un(buff, 0, wgpuBufferGetSize(buff));
|
||||
}
|
||||
|
||||
|
||||
WGPUBindGroup WgBindGroupLayouts::createBindGroupBuffer1Un(WGPUBuffer buff, uint64_t offset, uint64_t size)
|
||||
{
|
||||
const WGPUBindGroupEntry bindGroupEntrys[] = {
|
||||
{ .binding = 0, .buffer = buff, .size = wgpuBufferGetSize(buff) }
|
||||
{ .binding = 0, .buffer = buff, .offset = offset, .size = size }
|
||||
};
|
||||
const WGPUBindGroupDescriptor bindGroupDesc { .layout = layoutBuffer1Un, .entryCount = 1, .entries = bindGroupEntrys };
|
||||
return wgpuDeviceCreateBindGroup(device, &bindGroupDesc);
|
||||
|
|
|
@ -49,6 +49,7 @@ public:
|
|||
WGPUBindGroup createBindGroupStrorage2RO(WGPUTextureView texView0, WGPUTextureView texView1);
|
||||
WGPUBindGroup createBindGroupStrorage3RO(WGPUTextureView texView0, WGPUTextureView texView1, WGPUTextureView texView2);
|
||||
WGPUBindGroup createBindGroupBuffer1Un(WGPUBuffer buff);
|
||||
WGPUBindGroup createBindGroupBuffer1Un(WGPUBuffer buff, uint64_t offset, uint64_t size);
|
||||
WGPUBindGroup createBindGroupBuffer2Un(WGPUBuffer buff0, WGPUBuffer buff1);
|
||||
WGPUBindGroup createBindGroupBuffer3Un(WGPUBuffer buff0, WGPUBuffer buff1, WGPUBuffer buff2);
|
||||
void releaseBindGroup(WGPUBindGroup& bindGroup);
|
||||
|
|
|
@ -28,7 +28,7 @@ void WgCompositor::initialize(WgContext& context, uint32_t width, uint32_t heigh
|
|||
{
|
||||
// pipelines (external handle, do not release)
|
||||
pipelines.initialize(context);
|
||||
stageBuffer.initialize(context);
|
||||
stageBufferGeometry.initialize(context);
|
||||
// initialize opacity pool
|
||||
initPools(context);
|
||||
// allocate global view matrix handles
|
||||
|
@ -64,7 +64,8 @@ void WgCompositor::release(WgContext& context)
|
|||
context.layouts.releaseBindGroup(bindGroupViewMat);
|
||||
context.releaseBuffer(bufferViewMat);
|
||||
// release stage buffer
|
||||
stageBuffer.release(context);
|
||||
stageBufferPaint.release(context);
|
||||
stageBufferGeometry.release(context);
|
||||
// release pipelines
|
||||
pipelines.release(context);
|
||||
}
|
||||
|
@ -190,28 +191,35 @@ void WgCompositor::endRenderPass()
|
|||
|
||||
void WgCompositor::reset(WgContext& context)
|
||||
{
|
||||
stageBuffer.clear();
|
||||
stageBufferGeometry.clear();
|
||||
stageBufferPaint.clear();
|
||||
}
|
||||
|
||||
|
||||
void WgCompositor::flush(WgContext& context)
|
||||
{
|
||||
stageBuffer.append(&meshDataBlit);
|
||||
stageBuffer.flush(context);
|
||||
stageBufferGeometry.append(&meshDataBlit);
|
||||
stageBufferGeometry.flush(context);
|
||||
stageBufferPaint.flush(context);
|
||||
}
|
||||
|
||||
|
||||
void WgCompositor::requestShape(WgRenderDataShape* renderData)
|
||||
{
|
||||
stageBuffer.append(renderData);
|
||||
// TODO: expand for fill settings
|
||||
stageBufferGeometry.append(renderData);
|
||||
renderData->renderSettingsShape.bindGroupInd = stageBufferPaint.append(renderData->renderSettingsShape.settings);
|
||||
renderData->renderSettingsStroke.bindGroupInd = stageBufferPaint.append(renderData->renderSettingsStroke.settings);
|
||||
ARRAY_FOREACH(p, renderData->clips)
|
||||
requestShape((WgRenderDataShape* )(*p));
|
||||
}
|
||||
|
||||
|
||||
void WgCompositor::requestImage(WgRenderDataPicture* renderData)
|
||||
{
|
||||
stageBuffer.append(renderData);
|
||||
// TODO: expand for fill settings
|
||||
stageBufferGeometry.append(renderData);
|
||||
renderData->renderSettings.bindGroupInd = stageBufferPaint.append(renderData->renderSettings.settings);
|
||||
ARRAY_FOREACH(p, renderData->clips)
|
||||
requestShape((WgRenderDataShape* )(*p));
|
||||
}
|
||||
|
||||
|
||||
|
@ -332,8 +340,8 @@ void WgCompositor::drawMesh(WgContext& context, WgMeshData* meshData)
|
|||
uint64_t icount = meshData->ibuffer.count;
|
||||
uint64_t vsize = meshData->vbuffer.count * sizeof(Point);
|
||||
uint64_t isize = icount * sizeof(uint32_t);
|
||||
wgpuRenderPassEncoderSetVertexBuffer(renderPassEncoder, 0, stageBuffer.vbuffer_gpu, meshData->voffset, vsize);
|
||||
wgpuRenderPassEncoderSetIndexBuffer(renderPassEncoder, stageBuffer.ibuffer_gpu, WGPUIndexFormat_Uint32, meshData->ioffset, isize);
|
||||
wgpuRenderPassEncoderSetVertexBuffer(renderPassEncoder, 0, stageBufferGeometry.vbuffer_gpu, meshData->voffset, vsize);
|
||||
wgpuRenderPassEncoderSetIndexBuffer(renderPassEncoder, stageBufferGeometry.ibuffer_gpu, WGPUIndexFormat_Uint32, meshData->ioffset, isize);
|
||||
wgpuRenderPassEncoderDrawIndexed(renderPassEncoder, icount, 1, 0, 0, 0);
|
||||
};
|
||||
|
||||
|
@ -345,7 +353,7 @@ void WgCompositor::drawMeshFan(WgContext& context, WgMeshData* meshData)
|
|||
uint64_t icount = (meshData->vbuffer.count - 2) * 3;
|
||||
uint64_t vsize = meshData->vbuffer.count * sizeof(Point);
|
||||
uint64_t isize = icount * sizeof(uint32_t);
|
||||
wgpuRenderPassEncoderSetVertexBuffer(renderPassEncoder, 0, stageBuffer.vbuffer_gpu, meshData->voffset, vsize);
|
||||
wgpuRenderPassEncoderSetVertexBuffer(renderPassEncoder, 0, stageBufferGeometry.vbuffer_gpu, meshData->voffset, vsize);
|
||||
wgpuRenderPassEncoderSetIndexBuffer(renderPassEncoder, context.bufferIndexFan, WGPUIndexFormat_Uint32, 0, isize);
|
||||
wgpuRenderPassEncoderDrawIndexed(renderPassEncoder, icount, 1, 0, 0, 0);
|
||||
};
|
||||
|
@ -358,9 +366,9 @@ void WgCompositor::drawMeshImage(WgContext& context, WgMeshData* meshData)
|
|||
uint64_t icount = meshData->ibuffer.count;
|
||||
uint64_t vsize = meshData->vbuffer.count * sizeof(Point);
|
||||
uint64_t isize = icount * sizeof(uint32_t);
|
||||
wgpuRenderPassEncoderSetVertexBuffer(renderPassEncoder, 0, stageBuffer.vbuffer_gpu, meshData->voffset, vsize);
|
||||
wgpuRenderPassEncoderSetVertexBuffer(renderPassEncoder, 1, stageBuffer.vbuffer_gpu, meshData->toffset, vsize);
|
||||
wgpuRenderPassEncoderSetIndexBuffer(renderPassEncoder, stageBuffer.ibuffer_gpu, WGPUIndexFormat_Uint32, meshData->ioffset, isize);
|
||||
wgpuRenderPassEncoderSetVertexBuffer(renderPassEncoder, 0, stageBufferGeometry.vbuffer_gpu, meshData->voffset, vsize);
|
||||
wgpuRenderPassEncoderSetVertexBuffer(renderPassEncoder, 1, stageBufferGeometry.vbuffer_gpu, meshData->toffset, vsize);
|
||||
wgpuRenderPassEncoderSetIndexBuffer(renderPassEncoder, stageBufferGeometry.ibuffer_gpu, WGPUIndexFormat_Uint32, meshData->ioffset, isize);
|
||||
wgpuRenderPassEncoderDrawIndexed(renderPassEncoder, icount, 1, 0, 0, 0);
|
||||
};
|
||||
|
||||
|
@ -371,12 +379,13 @@ void WgCompositor::drawShape(WgContext& context, WgRenderDataShape* renderData)
|
|||
assert(renderPassEncoder);
|
||||
assert(renderData->meshGroupShapes.meshes.count == renderData->meshGroupShapesBBox.meshes.count);
|
||||
if (renderData->renderSettingsShape.skip || renderData->meshGroupShapes.meshes.count == 0 || renderData->viewport.invalid()) return;
|
||||
WgRenderSettings& settings = renderData->renderSettingsShape;
|
||||
wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, renderData->viewport.x(), renderData->viewport.y(), renderData->viewport.w(), renderData->viewport.h());
|
||||
// setup stencil rules
|
||||
WGPURenderPipeline stencilPipeline = (renderData->fillRule == FillRule::NonZero) ? pipelines.nonzero : pipelines.evenodd;
|
||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, stencilPipeline);
|
||||
// draw to stencil (first pass)
|
||||
ARRAY_FOREACH(p, renderData->meshGroupShapes.meshes)
|
||||
|
@ -384,16 +393,15 @@ void WgCompositor::drawShape(WgContext& context, WgRenderDataShape* renderData)
|
|||
// setup fill rules
|
||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr);
|
||||
WgRenderSettings& settings = renderData->renderSettingsShape;
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||
if (settings.fillType == WgRenderSettingsType::Solid) {
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, settings.bindGroupSolid, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.solid);
|
||||
} else if (settings.fillType == WgRenderSettingsType::Linear) {
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, settings.bindGroupGradient, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, settings.gradientData.bindGroup, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.linear);
|
||||
} else if (settings.fillType == WgRenderSettingsType::Radial) {
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, settings.bindGroupGradient, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, settings.gradientData.bindGroup, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.radial);
|
||||
}
|
||||
// draw to color (second pass)
|
||||
|
@ -407,6 +415,7 @@ void WgCompositor::blendShape(WgContext& context, WgRenderDataShape* renderData,
|
|||
assert(renderPassEncoder);
|
||||
assert(renderData->meshGroupShapes.meshes.count == renderData->meshGroupShapesBBox.meshes.count);
|
||||
if (renderData->renderSettingsShape.skip || renderData->meshGroupShapes.meshes.count == 0 || renderData->viewport.invalid()) return;
|
||||
WgRenderSettings& settings = renderData->renderSettingsShape;
|
||||
// copy current render target data to dst target
|
||||
WgRenderTarget *target = currentTarget;
|
||||
endRenderPass();
|
||||
|
@ -418,7 +427,7 @@ void WgCompositor::blendShape(WgContext& context, WgRenderDataShape* renderData,
|
|||
WGPURenderPipeline stencilPipeline = (renderData->fillRule == FillRule::NonZero) ? pipelines.nonzero : pipelines.evenodd;
|
||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, stencilPipeline);
|
||||
// draw to stencil (first pass)
|
||||
ARRAY_FOREACH(p, renderData->meshGroupShapes.meshes)
|
||||
|
@ -426,18 +435,17 @@ void WgCompositor::blendShape(WgContext& context, WgRenderDataShape* renderData,
|
|||
// setup fill rules
|
||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 3, targetTemp0.bindGroupTexure, 0, nullptr);
|
||||
uint32_t blendMethodInd = (uint32_t)blendMethod;
|
||||
WgRenderSettings& settings = renderData->renderSettingsShape;
|
||||
if (settings.fillType == WgRenderSettingsType::Solid) {
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, settings.bindGroupSolid, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.solid_blend[blendMethodInd]);
|
||||
} else if (settings.fillType == WgRenderSettingsType::Linear) {
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, settings.bindGroupGradient, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, settings.gradientData.bindGroup, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.linear_blend[blendMethodInd]);
|
||||
} else if (settings.fillType == WgRenderSettingsType::Radial) {
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, settings.bindGroupGradient, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, settings.gradientData.bindGroup, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.radial_blend[blendMethodInd]);
|
||||
}
|
||||
// draw to color (second pass)
|
||||
|
@ -451,13 +459,13 @@ void WgCompositor::clipShape(WgContext& context, WgRenderDataShape* renderData)
|
|||
assert(renderPassEncoder);
|
||||
assert(renderData->meshGroupShapes.meshes.count == renderData->meshGroupShapesBBox.meshes.count);
|
||||
if (renderData->renderSettingsShape.skip || renderData->meshGroupShapes.meshes.count == 0 || renderData->viewport.invalid()) return;
|
||||
|
||||
WgRenderSettings& settings = renderData->renderSettingsShape;
|
||||
wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, renderData->viewport.x(), renderData->viewport.y(), renderData->viewport.w(), renderData->viewport.h());
|
||||
// setup stencil rules
|
||||
WGPURenderPipeline stencilPipeline = (renderData->fillRule == FillRule::NonZero) ? pipelines.nonzero : pipelines.evenodd;
|
||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, stencilPipeline);
|
||||
// draw to stencil (first pass)
|
||||
ARRAY_FOREACH(p, renderData->meshGroupShapes.meshes)
|
||||
|
@ -470,16 +478,15 @@ void WgCompositor::clipShape(WgContext& context, WgRenderDataShape* renderData)
|
|||
// setup fill rules
|
||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr);
|
||||
WgRenderSettings& settings = renderData->renderSettingsShape;
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||
if (settings.fillType == WgRenderSettingsType::Solid) {
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, settings.bindGroupSolid, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.solid);
|
||||
} else if (settings.fillType == WgRenderSettingsType::Linear) {
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, settings.bindGroupGradient, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, settings.gradientData.bindGroup, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.linear);
|
||||
} else if (settings.fillType == WgRenderSettingsType::Radial) {
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, settings.bindGroupGradient, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, settings.gradientData.bindGroup, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.radial);
|
||||
}
|
||||
// draw to color (second pass)
|
||||
|
@ -493,30 +500,29 @@ void WgCompositor::drawStrokes(WgContext& context, WgRenderDataShape* renderData
|
|||
assert(renderPassEncoder);
|
||||
assert(renderData->meshGroupStrokes.meshes.count == renderData->meshGroupStrokesBBox.meshes.count);
|
||||
if (renderData->renderSettingsStroke.skip || renderData->meshGroupStrokes.meshes.count == 0 || renderData->viewport.invalid()) return;
|
||||
|
||||
WgRenderSettings& settings = renderData->renderSettingsStroke;
|
||||
wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, renderData->viewport.x(), renderData->viewport.y(), renderData->viewport.w(), renderData->viewport.h());
|
||||
// draw strokes to stencil (first pass)
|
||||
for (uint32_t i = 0; i < renderData->meshGroupStrokes.meshes.count; i++) {
|
||||
// setup stencil rules
|
||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 255);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.direct);
|
||||
// draw to stencil (first pass)
|
||||
drawMesh(context, renderData->meshGroupStrokes.meshes[i]);
|
||||
// setup fill rules
|
||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr);
|
||||
WgRenderSettings& settings = renderData->renderSettingsStroke;
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||
if (settings.fillType == WgRenderSettingsType::Solid) {
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, settings.bindGroupSolid, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.solid);
|
||||
} else if (settings.fillType == WgRenderSettingsType::Linear) {
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, settings.bindGroupGradient, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, settings.gradientData.bindGroup, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.linear);
|
||||
} else if (settings.fillType == WgRenderSettingsType::Radial) {
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, settings.bindGroupGradient, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, settings.gradientData.bindGroup, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.radial);
|
||||
}
|
||||
// draw to color (second pass)
|
||||
|
@ -531,7 +537,7 @@ void WgCompositor::blendStrokes(WgContext& context, WgRenderDataShape* renderDat
|
|||
assert(renderPassEncoder);
|
||||
assert(renderData->meshGroupStrokes.meshes.count == renderData->meshGroupStrokesBBox.meshes.count);
|
||||
if (renderData->renderSettingsStroke.skip || renderData->meshGroupStrokes.meshes.count == 0 || renderData->viewport.invalid()) return;
|
||||
|
||||
WgRenderSettings& settings = renderData->renderSettingsStroke;
|
||||
// copy current render target data to dst target
|
||||
WgRenderTarget *target = currentTarget;
|
||||
endRenderPass();
|
||||
|
@ -543,25 +549,24 @@ void WgCompositor::blendStrokes(WgContext& context, WgRenderDataShape* renderDat
|
|||
// setup stencil rules
|
||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 255);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.direct);
|
||||
// draw to stencil (first pass)
|
||||
drawMesh(context, renderData->meshGroupStrokes.meshes[i]);
|
||||
// setup fill rules
|
||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 3, targetTemp0.bindGroupTexure, 0, nullptr);
|
||||
uint32_t blendMethodInd = (uint32_t)blendMethod;
|
||||
WgRenderSettings& settings = renderData->renderSettingsStroke;
|
||||
if (settings.fillType == WgRenderSettingsType::Solid) {
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, settings.bindGroupSolid, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.solid_blend[blendMethodInd]);
|
||||
} else if (settings.fillType == WgRenderSettingsType::Linear) {
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, settings.bindGroupGradient, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, settings.gradientData.bindGroup, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.linear_blend[blendMethodInd]);
|
||||
} else if (settings.fillType == WgRenderSettingsType::Radial) {
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, settings.bindGroupGradient, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, settings.gradientData.bindGroup, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.radial_blend[blendMethodInd]);
|
||||
}
|
||||
// draw to color (second pass)
|
||||
|
@ -578,13 +583,14 @@ void WgCompositor::clipStrokes(WgContext& context, WgRenderDataShape* renderData
|
|||
if (renderData->renderSettingsStroke.skip) return;
|
||||
if (renderData->meshGroupStrokes.meshes.count == 0) return;
|
||||
if (renderData->viewport.invalid()) return;
|
||||
WgRenderSettings& settings = renderData->renderSettingsStroke;
|
||||
wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, renderData->viewport.x(), renderData->viewport.y(), renderData->viewport.w(), renderData->viewport.h());
|
||||
// draw strokes to stencil (first pass)
|
||||
for (uint32_t i = 0; i < renderData->meshGroupStrokes.meshes.count; i++) {
|
||||
// setup stencil rules
|
||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 255);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.direct);
|
||||
// draw to stencil (first pass)
|
||||
drawMesh(context, renderData->meshGroupStrokes.meshes[i]);
|
||||
|
@ -596,16 +602,15 @@ void WgCompositor::clipStrokes(WgContext& context, WgRenderDataShape* renderData
|
|||
// setup fill rules
|
||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr);
|
||||
WgRenderSettings& settings = renderData->renderSettingsStroke;
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||
if (settings.fillType == WgRenderSettingsType::Solid) {
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, settings.bindGroupSolid, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.solid);
|
||||
} else if (settings.fillType == WgRenderSettingsType::Linear) {
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, settings.bindGroupGradient, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, settings.gradientData.bindGroup, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.linear);
|
||||
} else if (settings.fillType == WgRenderSettingsType::Radial) {
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, settings.bindGroupGradient, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, settings.gradientData.bindGroup, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.radial);
|
||||
}
|
||||
// draw to color (second pass)
|
||||
|
@ -619,18 +624,19 @@ void WgCompositor::drawImage(WgContext& context, WgRenderDataPicture* renderData
|
|||
assert(renderData);
|
||||
assert(renderPassEncoder);
|
||||
if (renderData->viewport.invalid()) return;
|
||||
WgRenderSettings& settings = renderData->renderSettings;
|
||||
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);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.direct);
|
||||
drawMeshImage(context, &renderData->meshData);
|
||||
// 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);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, renderData->imageData.bindGroup, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.image);
|
||||
drawMeshImage(context, &renderData->meshData);
|
||||
}
|
||||
|
@ -641,6 +647,7 @@ void WgCompositor::blendImage(WgContext& context, WgRenderDataPicture* renderDat
|
|||
assert(renderData);
|
||||
assert(renderPassEncoder);
|
||||
if (renderData->viewport.invalid()) return;
|
||||
WgRenderSettings& settings = renderData->renderSettings;
|
||||
wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, renderData->viewport.x(), renderData->viewport.y(), renderData->viewport.w(), renderData->viewport.h());
|
||||
// copy current render target data to dst target
|
||||
WgRenderTarget *target = currentTarget;
|
||||
|
@ -650,15 +657,15 @@ void WgCompositor::blendImage(WgContext& context, WgRenderDataPicture* renderDat
|
|||
// setup stencil rules
|
||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 255);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.direct);
|
||||
drawMeshImage(context, &renderData->meshData);
|
||||
// blend image
|
||||
uint32_t blendMethodInd = (uint32_t)blendMethod;
|
||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, renderData->bindGroupPicture, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, renderData->imageData.bindGroup, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 3, targetTemp0.bindGroupTexure, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.image_blend[blendMethodInd]);
|
||||
drawMeshImage(context, &renderData->meshData);
|
||||
|
@ -670,11 +677,12 @@ void WgCompositor::clipImage(WgContext& context, WgRenderDataPicture* renderData
|
|||
assert(renderData);
|
||||
assert(renderPassEncoder);
|
||||
if (renderData->viewport.invalid()) return;
|
||||
WgRenderSettings& settings = renderData->renderSettings;
|
||||
wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, renderData->viewport.x(), renderData->viewport.y(), renderData->viewport.w(), renderData->viewport.h());
|
||||
// setup stencil rules
|
||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 255);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.direct);
|
||||
drawMeshImage(context, &renderData->meshData);
|
||||
// merge depth and stencil buffer
|
||||
|
@ -685,8 +693,8 @@ void WgCompositor::clipImage(WgContext& context, WgRenderDataPicture* renderData
|
|||
// 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);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, renderData->imageData.bindGroup, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.image);
|
||||
drawMeshImage(context, &renderData->meshData);
|
||||
}
|
||||
|
@ -734,16 +742,19 @@ void WgCompositor::blendScene(WgContext& context, WgRenderTarget* scene, WgCompo
|
|||
void WgCompositor::markupClipPath(WgContext& context, WgRenderDataShape* renderData)
|
||||
{
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr);
|
||||
// markup stencil
|
||||
if (renderData->meshGroupStrokes.meshes.count > 0) {
|
||||
WgRenderSettings& settings = renderData->renderSettingsStroke;
|
||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 255);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.direct);
|
||||
ARRAY_FOREACH(p, renderData->meshGroupStrokes.meshes)
|
||||
drawMesh(context, (*p));
|
||||
} else {
|
||||
WGPURenderPipeline stencilPipeline = (renderData->fillRule == FillRule::NonZero) ? pipelines.nonzero : pipelines.evenodd;
|
||||
WgRenderSettings& settings = renderData->renderSettingsShape;
|
||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, stencilPipeline);
|
||||
ARRAY_FOREACH(p, renderData->meshGroupShapes.meshes)
|
||||
drawMeshFan(context, (*p));
|
||||
|
@ -760,12 +771,13 @@ void WgCompositor::renderClipPath(WgContext& context, WgRenderDataPaint* paint)
|
|||
wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, 0, 0, width, height);
|
||||
// get render data
|
||||
WgRenderDataShape* renderData0 = (WgRenderDataShape*)paint->clips[0];
|
||||
WgRenderSettings& settings0 = renderData0->renderSettingsShape;
|
||||
// markup stencil
|
||||
markupClipPath(context, renderData0);
|
||||
// copy stencil to depth
|
||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData0->bindGroupPaint, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, stageBufferPaint[settings0.bindGroupInd], 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, bindGroupOpacities[128], 0, nullptr);
|
||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.copy_stencil_to_depth);
|
||||
drawMeshFan(context, &renderData0->meshDataBBox);
|
||||
|
@ -773,35 +785,36 @@ void WgCompositor::renderClipPath(WgContext& context, WgRenderDataPaint* paint)
|
|||
for (auto p = paint->clips.begin() + 1; p < paint->clips.end(); ++p) {
|
||||
// get render data
|
||||
WgRenderDataShape* renderData = (WgRenderDataShape*)(*p);
|
||||
WgRenderSettings& settings = renderData->renderSettingsShape;
|
||||
// markup stencil
|
||||
markupClipPath(context, renderData);
|
||||
// copy stencil to depth (clear stencil)
|
||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, bindGroupOpacities[190], 0, nullptr);
|
||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.copy_stencil_to_depth_interm);
|
||||
drawMeshFan(context, &renderData->meshDataBBox);
|
||||
// copy depth to stencil
|
||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 1);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, bindGroupOpacities[190], 0, nullptr);
|
||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.copy_depth_to_stencil);
|
||||
drawMeshFan(context, &renderData->meshDataBBox);
|
||||
// clear depth current (keep stencil)
|
||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, bindGroupOpacities[255], 0, nullptr);
|
||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.clear_depth);
|
||||
drawMeshFan(context, &renderData->meshDataBBox);
|
||||
// clear depth original (keep stencil)
|
||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData0->bindGroupPaint, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, stageBufferPaint[settings0.bindGroupInd], 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, bindGroupOpacities[255], 0, nullptr);
|
||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.clear_depth);
|
||||
drawMeshFan(context, &renderData0->meshDataBBox);
|
||||
// copy stencil to depth (clear stencil)
|
||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, bindGroupOpacities[128], 0, nullptr);
|
||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.copy_stencil_to_depth);
|
||||
drawMeshFan(context, &renderData->meshDataBBox);
|
||||
|
@ -819,10 +832,11 @@ void WgCompositor::clearClipPath(WgContext& context, WgRenderDataPaint* paint)
|
|||
// get render data
|
||||
ARRAY_FOREACH(p, paint->clips) {
|
||||
WgRenderDataShape* renderData = (WgRenderDataShape*)(*p);
|
||||
WgRenderSettings& settings = renderData->renderSettingsShape;
|
||||
// set transformations
|
||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, bindGroupOpacities[255], 0, nullptr);
|
||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.clear_depth);
|
||||
drawMeshFan(context, &renderData->meshDataBBox);
|
||||
|
|
|
@ -39,7 +39,8 @@ private:
|
|||
// pipelines
|
||||
WgPipelines pipelines{};
|
||||
// stage buffers
|
||||
WgRenderDataStageBuffer stageBuffer{};
|
||||
WgStageBufferGeometry stageBufferGeometry{};
|
||||
WgStageBufferUniform<WgShaderTypePaintSettings> stageBufferPaint;
|
||||
// global stencil/depth buffer handles
|
||||
WGPUTexture texDepthStencil{};
|
||||
WGPUTextureView texViewDepthStencil{};
|
||||
|
|
|
@ -167,17 +167,17 @@ void WgPipelines::initialize(WgContext& context)
|
|||
|
||||
const WgBindGroupLayouts& layouts = context.layouts;
|
||||
// bind group layouts helpers
|
||||
const WGPUBindGroupLayout bindGroupLayoutsStencil[] { layouts.layoutBuffer1Un, layouts.layoutBuffer2Un };
|
||||
const WGPUBindGroupLayout bindGroupLayoutsDepth[] { layouts.layoutBuffer1Un, layouts.layoutBuffer2Un, layouts.layoutBuffer1Un };
|
||||
const WGPUBindGroupLayout bindGroupLayoutsStencil[] { layouts.layoutBuffer1Un, layouts.layoutBuffer1Un };
|
||||
const WGPUBindGroupLayout bindGroupLayoutsDepth[] { layouts.layoutBuffer1Un, layouts.layoutBuffer1Un, layouts.layoutBuffer1Un };
|
||||
// bind group layouts normal blend
|
||||
const WGPUBindGroupLayout bindGroupLayoutsSolid[] { layouts.layoutBuffer1Un, layouts.layoutBuffer2Un, layouts.layoutBuffer1Un };
|
||||
const WGPUBindGroupLayout bindGroupLayoutsGradient[] { layouts.layoutBuffer1Un, layouts.layoutBuffer2Un, layouts.layoutTexSampledBuff2Un };
|
||||
const WGPUBindGroupLayout bindGroupLayoutsImage[] { layouts.layoutBuffer1Un, layouts.layoutBuffer2Un, layouts.layoutTexSampled };
|
||||
const WGPUBindGroupLayout bindGroupLayoutsSolid[] { layouts.layoutBuffer1Un, layouts.layoutBuffer1Un };
|
||||
const WGPUBindGroupLayout bindGroupLayoutsGradient[] { layouts.layoutBuffer1Un, layouts.layoutBuffer1Un, layouts.layoutTexSampled };
|
||||
const WGPUBindGroupLayout bindGroupLayoutsImage[] { layouts.layoutBuffer1Un, layouts.layoutBuffer1Un, layouts.layoutTexSampled };
|
||||
const WGPUBindGroupLayout bindGroupLayoutsScene[] { layouts.layoutTexSampled, layouts.layoutBuffer1Un };
|
||||
// bind group layouts custom blend
|
||||
const WGPUBindGroupLayout bindGroupLayoutsSolidBlend[] { layouts.layoutBuffer1Un, layouts.layoutBuffer2Un, layouts.layoutBuffer1Un, layouts.layoutTexSampled };
|
||||
const WGPUBindGroupLayout bindGroupLayoutsGradientBlend[] { layouts.layoutBuffer1Un, layouts.layoutBuffer2Un, layouts.layoutTexSampledBuff2Un, layouts.layoutTexSampled };
|
||||
const WGPUBindGroupLayout bindGroupLayoutsImageBlend[] { layouts.layoutBuffer1Un, layouts.layoutBuffer2Un, layouts.layoutTexSampled, layouts.layoutTexSampled };
|
||||
const WGPUBindGroupLayout bindGroupLayoutsSolidBlend[] { layouts.layoutBuffer1Un, layouts.layoutBuffer1Un, layouts.layoutBuffer1Un, layouts.layoutTexSampled };
|
||||
const WGPUBindGroupLayout bindGroupLayoutsGradientBlend[] { layouts.layoutBuffer1Un, layouts.layoutBuffer1Un, layouts.layoutTexSampled, layouts.layoutTexSampled };
|
||||
const WGPUBindGroupLayout bindGroupLayoutsImageBlend[] { layouts.layoutBuffer1Un, layouts.layoutBuffer1Un, layouts.layoutTexSampled, layouts.layoutTexSampled };
|
||||
const WGPUBindGroupLayout bindGroupLayoutsSceneBlend[] { layouts.layoutTexSampled, layouts.layoutTexSampled, layouts.layoutBuffer1Un };
|
||||
// bind group layouts scene compose
|
||||
const WGPUBindGroupLayout bindGroupLayoutsSceneCompose[] { layouts.layoutTexSampled, layouts.layoutTexSampled };
|
||||
|
@ -229,7 +229,7 @@ void WgPipelines::initialize(WgContext& context)
|
|||
layout_stencil = createPipelineLayout(context.device, bindGroupLayoutsStencil, 2);
|
||||
layout_depth = createPipelineLayout(context.device, bindGroupLayoutsDepth, 3);
|
||||
// layouts normal blend
|
||||
layout_solid = createPipelineLayout(context.device, bindGroupLayoutsSolid, 3);
|
||||
layout_solid = createPipelineLayout(context.device, bindGroupLayoutsSolid, 2);
|
||||
layout_gradient = createPipelineLayout(context.device, bindGroupLayoutsGradient, 3);
|
||||
layout_image = createPipelineLayout(context.device, bindGroupLayoutsImage, 3);
|
||||
layout_scene = createPipelineLayout(context.device, bindGroupLayoutsScene, 2);
|
||||
|
|
|
@ -202,12 +202,38 @@ void WgImageData::update(WgContext& context, const RenderSurface* surface)
|
|||
if (texHandleChanged) {
|
||||
context.releaseTextureView(textureView);
|
||||
textureView = context.createTextureView(texture);
|
||||
// update bind group
|
||||
context.layouts.releaseBindGroup(bindGroup);
|
||||
bindGroup = context.layouts.createBindGroupTexSampled(context.samplerLinearRepeat, textureView);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void WgImageData::update(WgContext& context, const Fill* fill)
|
||||
{
|
||||
// compute gradient data
|
||||
WgShaderTypeGradientData gradientData;
|
||||
gradientData.update(fill);
|
||||
// allocate new texture handle
|
||||
bool texHandleChanged = context.allocateTexture(texture, WG_TEXTURE_GRADIENT_SIZE, 1, WGPUTextureFormat_RGBA8Unorm, gradientData.data);
|
||||
// update texture view of texture handle was changed
|
||||
if (texHandleChanged) {
|
||||
context.releaseTextureView(textureView);
|
||||
textureView = context.createTextureView(texture);
|
||||
// get sampler by spread type
|
||||
WGPUSampler sampler = context.samplerLinearClamp;
|
||||
if (fill->spread() == FillSpread::Reflect) sampler = context.samplerLinearMirror;
|
||||
if (fill->spread() == FillSpread::Repeat) sampler = context.samplerLinearRepeat;
|
||||
// update bind group
|
||||
context.layouts.releaseBindGroup(bindGroup);
|
||||
bindGroup = context.layouts.createBindGroupTexSampled(sampler, textureView);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void WgImageData::release(WgContext& context)
|
||||
{
|
||||
context.layouts.releaseBindGroup(bindGroup);
|
||||
context.releaseTextureView(textureView);
|
||||
context.releaseTexture(texture);
|
||||
};
|
||||
|
@ -216,52 +242,31 @@ void WgImageData::release(WgContext& context)
|
|||
// WgRenderSettings
|
||||
//***********************************************************************
|
||||
|
||||
void WgRenderSettings::updateFill(WgContext& context, const Fill* fill)
|
||||
void WgRenderSettings::update(WgContext& context, const tvg::Matrix& transform, tvg::ColorSpace cs, uint8_t opacity)
|
||||
{
|
||||
rasterType = WgRenderRasterType::Gradient;
|
||||
// get gradient transfrom matrix
|
||||
Matrix invFillTransform;
|
||||
WgShaderTypeMat4x4f gradientTrans; // identity by default
|
||||
if (inverse(&fill->transform(), &invFillTransform))
|
||||
gradientTrans.update(invFillTransform);
|
||||
settings.transform.update(transform);
|
||||
settings.options.update(cs, opacity);
|
||||
}
|
||||
|
||||
void WgRenderSettings::update(WgContext& context, const Fill* fill)
|
||||
{
|
||||
assert(fill);
|
||||
settings.gradient.update(fill);
|
||||
gradientData.update(context, fill);
|
||||
// get gradient rasterisation settings
|
||||
WgShaderTypeGradient gradient;
|
||||
if (fill->type() == Type::LinearGradient) {
|
||||
gradient.update((LinearGradient*)fill);
|
||||
rasterType = WgRenderRasterType::Gradient;
|
||||
if (fill->type() == Type::LinearGradient)
|
||||
fillType = WgRenderSettingsType::Linear;
|
||||
} else if (fill->type() == Type::RadialGradient) {
|
||||
gradient.update((RadialGradient*)fill);
|
||||
else if (fill->type() == Type::RadialGradient)
|
||||
fillType = WgRenderSettingsType::Radial;
|
||||
}
|
||||
// update gpu assets
|
||||
bool bufferGradientSettingsChanged = context.allocateBufferUniform(bufferGroupGradient, &gradient.settings, sizeof(gradient.settings));
|
||||
bool bufferGradientTransformChanged = context.allocateBufferUniform(bufferGroupTransfromGrad, &gradientTrans.mat, sizeof(gradientTrans.mat));
|
||||
bool textureGradientChanged = context.allocateTexture(texGradient, WG_TEXTURE_GRADIENT_SIZE, 1, WGPUTextureFormat_RGBA8Unorm, gradient.texData);
|
||||
if (bufferGradientSettingsChanged || textureGradientChanged || bufferGradientTransformChanged) {
|
||||
// update texture view
|
||||
context.releaseTextureView(texViewGradient);
|
||||
texViewGradient = context.createTextureView(texGradient);
|
||||
// get sampler by spread type
|
||||
WGPUSampler sampler = context.samplerLinearClamp;
|
||||
if (fill->spread() == FillSpread::Reflect) sampler = context.samplerLinearMirror;
|
||||
if (fill->spread() == FillSpread::Repeat) sampler = context.samplerLinearRepeat;
|
||||
// update bind group
|
||||
context.layouts.releaseBindGroup(bindGroupGradient);
|
||||
bindGroupGradient = context.layouts.createBindGroupTexSampledBuff2Un(
|
||||
sampler, texViewGradient, bufferGroupGradient, bufferGroupTransfromGrad);
|
||||
}
|
||||
skip = false;
|
||||
};
|
||||
|
||||
|
||||
void WgRenderSettings::updateColor(WgContext& context, const RenderColor& c)
|
||||
void WgRenderSettings::update(WgContext& context, const RenderColor& c)
|
||||
{
|
||||
settings.color.update(c);
|
||||
rasterType = WgRenderRasterType::Solid;
|
||||
WgShaderTypeVec4f solidColor(c);
|
||||
if (context.allocateBufferUniform(bufferGroupSolid, &solidColor, sizeof(solidColor))) {
|
||||
context.layouts.releaseBindGroup(bindGroupSolid);
|
||||
bindGroupSolid = context.layouts.createBindGroupBuffer1Un(bufferGroupSolid);
|
||||
}
|
||||
fillType = WgRenderSettingsType::Solid;
|
||||
skip = (c.a == 0);
|
||||
};
|
||||
|
@ -269,13 +274,7 @@ void WgRenderSettings::updateColor(WgContext& context, const RenderColor& c)
|
|||
|
||||
void WgRenderSettings::release(WgContext& context)
|
||||
{
|
||||
context.layouts.releaseBindGroup(bindGroupSolid);
|
||||
context.layouts.releaseBindGroup(bindGroupGradient);
|
||||
context.releaseBuffer(bufferGroupSolid);
|
||||
context.releaseBuffer(bufferGroupGradient);
|
||||
context.releaseBuffer(bufferGroupTransfromGrad);
|
||||
context.releaseTexture(texGradient);
|
||||
context.releaseTextureView(texViewGradient);
|
||||
gradientData.release(context);
|
||||
};
|
||||
|
||||
//***********************************************************************
|
||||
|
@ -284,26 +283,10 @@ void WgRenderSettings::release(WgContext& context)
|
|||
|
||||
void WgRenderDataPaint::release(WgContext& context)
|
||||
{
|
||||
context.layouts.releaseBindGroup(bindGroupPaint);
|
||||
context.releaseBuffer(bufferModelMat);
|
||||
context.releaseBuffer(bufferBlendSettings);
|
||||
clips.clear();
|
||||
};
|
||||
|
||||
|
||||
void WgRenderDataPaint::update(WgContext& context, const tvg::Matrix& transform, tvg::ColorSpace cs, uint8_t opacity)
|
||||
{
|
||||
WgShaderTypeMat4x4f modelMat(transform);
|
||||
WgShaderTypeVec4f blendSettings(cs, opacity);
|
||||
bool bufferModelMatChanged = context.allocateBufferUniform(bufferModelMat, &modelMat, sizeof(modelMat));
|
||||
bool bufferBlendSettingsChanged = context.allocateBufferUniform(bufferBlendSettings, &blendSettings, sizeof(blendSettings));
|
||||
if (bufferModelMatChanged || bufferBlendSettingsChanged) {
|
||||
context.layouts.releaseBindGroup(bindGroupPaint);
|
||||
bindGroupPaint = context.layouts.createBindGroupBuffer2Un(bufferModelMat, bufferBlendSettings);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void WgRenderDataPaint::updateClips(tvg::Array<tvg::RenderData> &clips) {
|
||||
this->clips.clear();
|
||||
ARRAY_FOREACH(p, clips) {
|
||||
|
@ -467,17 +450,12 @@ void WgRenderDataPicture::updateSurface(WgContext& context, const RenderSurface*
|
|||
meshData.imageBox(context, surface->w, surface->h);
|
||||
// update texture data
|
||||
imageData.update(context, surface);
|
||||
// update texture bind group
|
||||
context.layouts.releaseBindGroup(bindGroupPicture);
|
||||
bindGroupPicture = context.layouts.createBindGroupTexSampled(
|
||||
context.samplerLinearRepeat, imageData.textureView
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
void WgRenderDataPicture::release(WgContext& context)
|
||||
{
|
||||
context.layouts.releaseBindGroup(bindGroupPicture);
|
||||
renderSettings.release(context);
|
||||
imageData.release(context);
|
||||
meshData.release(context);
|
||||
WgRenderDataPaint::release(context);
|
||||
|
@ -676,10 +654,10 @@ void WgRenderDataEffectParamsPool::release(WgContext& context)
|
|||
}
|
||||
|
||||
//***********************************************************************
|
||||
// WgRenderDataStageBuffer
|
||||
// WgStageBufferGeometry
|
||||
//***********************************************************************
|
||||
|
||||
void WgRenderDataStageBuffer::append(WgMeshData* meshData)
|
||||
void WgStageBufferGeometry::append(WgMeshData* meshData)
|
||||
{
|
||||
assert(meshData);
|
||||
uint32_t vsize = meshData->vbuffer.count * sizeof(meshData->vbuffer[0]);
|
||||
|
@ -712,54 +690,50 @@ void WgRenderDataStageBuffer::append(WgMeshData* meshData)
|
|||
}
|
||||
|
||||
|
||||
void WgRenderDataStageBuffer::append(WgMeshDataGroup* meshDataGroup)
|
||||
void WgStageBufferGeometry::append(WgMeshDataGroup* meshDataGroup)
|
||||
{
|
||||
ARRAY_FOREACH(p, meshDataGroup->meshes) append(*p);
|
||||
}
|
||||
|
||||
|
||||
void WgRenderDataStageBuffer::append(WgRenderDataShape* renderDataShape)
|
||||
void WgStageBufferGeometry::append(WgRenderDataShape* renderDataShape)
|
||||
{
|
||||
append(&renderDataShape->meshGroupShapes);
|
||||
append(&renderDataShape->meshGroupShapesBBox);
|
||||
append(&renderDataShape->meshGroupStrokes);
|
||||
append(&renderDataShape->meshGroupStrokesBBox);
|
||||
append(&renderDataShape->meshDataBBox);
|
||||
ARRAY_FOREACH(p, renderDataShape->clips)
|
||||
append((WgRenderDataShape* )(*p));
|
||||
}
|
||||
|
||||
|
||||
void WgRenderDataStageBuffer::append(WgRenderDataPicture* renderDataPicture)
|
||||
void WgStageBufferGeometry::append(WgRenderDataPicture* renderDataPicture)
|
||||
{
|
||||
append(&renderDataPicture->meshData);
|
||||
ARRAY_FOREACH(p, renderDataPicture->clips)
|
||||
append((WgRenderDataShape* )(*p));
|
||||
}
|
||||
|
||||
|
||||
void WgRenderDataStageBuffer::release(WgContext& context)
|
||||
void WgStageBufferGeometry::release(WgContext& context)
|
||||
{
|
||||
context.releaseBuffer(vbuffer_gpu);
|
||||
context.releaseBuffer(ibuffer_gpu);
|
||||
}
|
||||
|
||||
|
||||
void WgRenderDataStageBuffer::clear()
|
||||
void WgStageBufferGeometry::clear()
|
||||
{
|
||||
vbuffer.clear();
|
||||
ibuffer.clear();
|
||||
}
|
||||
|
||||
|
||||
void WgRenderDataStageBuffer::flush(WgContext& context)
|
||||
void WgStageBufferGeometry::flush(WgContext& context)
|
||||
{
|
||||
context.allocateBufferVertex(vbuffer_gpu, (float *)vbuffer.data, vbuffer.count);
|
||||
context.allocateBufferIndex(ibuffer_gpu, (uint32_t *)ibuffer.data, ibuffer.count);
|
||||
}
|
||||
|
||||
|
||||
void WgRenderDataStageBuffer::bind(WGPURenderPassEncoder renderPass, size_t voffset, size_t toffset)
|
||||
void WgStageBufferGeometry::bind(WGPURenderPassEncoder renderPass, size_t voffset, size_t toffset)
|
||||
{
|
||||
wgpuRenderPassEncoderSetVertexBuffer(renderPass, 0, vbuffer_gpu, voffset, vbuffer.count - voffset);
|
||||
wgpuRenderPassEncoderSetVertexBuffer(renderPass, 1, vbuffer_gpu, toffset, vbuffer.count - toffset);
|
||||
|
|
|
@ -66,8 +66,10 @@ struct WgMeshDataGroup {
|
|||
struct WgImageData {
|
||||
WGPUTexture texture{};
|
||||
WGPUTextureView textureView{};
|
||||
WGPUBindGroup bindGroup{};
|
||||
|
||||
void update(WgContext& context, const RenderSurface* surface);
|
||||
void update(WgContext& context, const Fill* fill);
|
||||
void release(WgContext& context);
|
||||
};
|
||||
|
||||
|
@ -76,37 +78,29 @@ enum class WgRenderRasterType { Solid = 0, Gradient, Image };
|
|||
|
||||
struct WgRenderSettings
|
||||
{
|
||||
WGPUBuffer bufferGroupSolid{};
|
||||
WGPUBindGroup bindGroupSolid{};
|
||||
WGPUTexture texGradient{};
|
||||
WGPUTextureView texViewGradient{};
|
||||
WGPUBuffer bufferGroupGradient{};
|
||||
WGPUBuffer bufferGroupTransfromGrad{};
|
||||
WGPUBindGroup bindGroupGradient{};
|
||||
uint32_t bindGroupInd{};
|
||||
WgShaderTypePaintSettings settings;
|
||||
WgImageData gradientData;
|
||||
WgRenderSettingsType fillType{};
|
||||
WgRenderRasterType rasterType{};
|
||||
bool skip{};
|
||||
|
||||
void updateFill(WgContext& context, const Fill* fill);
|
||||
void updateColor(WgContext& context, const RenderColor& c);
|
||||
void update(WgContext& context, const tvg::Matrix& transform, tvg::ColorSpace cs, uint8_t opacity);
|
||||
void update(WgContext& context, const Fill* fill);
|
||||
void update(WgContext& context, const RenderColor& c);
|
||||
void release(WgContext& context);
|
||||
};
|
||||
|
||||
struct WgRenderDataPaint
|
||||
{
|
||||
WGPUBuffer bufferModelMat{};
|
||||
WGPUBuffer bufferBlendSettings{};
|
||||
WGPUBindGroup bindGroupPaint{};
|
||||
RenderRegion viewport{};
|
||||
BBox aabb{{},{}};
|
||||
float opacity{};
|
||||
RenderRegion viewport{};
|
||||
Array<WgRenderDataPaint*> clips;
|
||||
|
||||
virtual ~WgRenderDataPaint() {};
|
||||
virtual void release(WgContext& context);
|
||||
virtual Type type() { return Type::Undefined; };
|
||||
|
||||
void update(WgContext& context, const tvg::Matrix& transform, tvg::ColorSpace cs, uint8_t opacity);
|
||||
void updateClips(tvg::Array<tvg::RenderData> &clips);
|
||||
};
|
||||
|
||||
|
@ -147,7 +141,7 @@ public:
|
|||
|
||||
struct WgRenderDataPicture: public WgRenderDataPaint
|
||||
{
|
||||
WGPUBindGroup bindGroupPicture{};
|
||||
WgRenderSettings renderSettings{};
|
||||
WgImageData imageData{};
|
||||
WgMeshData meshData{};
|
||||
|
||||
|
@ -221,7 +215,7 @@ public:
|
|||
void release(WgContext& context);
|
||||
};
|
||||
|
||||
class WgRenderDataStageBuffer {
|
||||
class WgStageBufferGeometry {
|
||||
private:
|
||||
Array<uint8_t> vbuffer;
|
||||
Array<uint8_t> ibuffer;
|
||||
|
@ -240,4 +234,50 @@ public:
|
|||
void bind(WGPURenderPassEncoder renderPass, size_t voffset, size_t toffset);
|
||||
};
|
||||
|
||||
// typed uniform stage buffer with related bind groups handling
|
||||
template<typename T>
|
||||
class WgStageBufferUniform {
|
||||
private:
|
||||
Array<T> ubuffer;
|
||||
WGPUBuffer ubuffer_gpu{};
|
||||
Array<WGPUBindGroup> bbuffer;
|
||||
public:
|
||||
// append uniform data to cpu staged buffer and return related bind group index
|
||||
uint32_t append(const T& value) {
|
||||
ubuffer.push(value);
|
||||
return ubuffer.count - 1;
|
||||
}
|
||||
|
||||
void flush(WgContext& context) {
|
||||
// flush data to gpu buffer from cpu memory including reserved data to prevent future gpu buffer reallocations
|
||||
bool bufferChanged = context.allocateBufferUniform(ubuffer_gpu, (void*)ubuffer.data, ubuffer.reserved*sizeof(T));
|
||||
// if gpu buffer handle was changed we must to remove all created binding groups
|
||||
if (bufferChanged) releaseBindGroups(context);
|
||||
// allocate bind groups for all new data items
|
||||
for (uint32_t i = bbuffer.count; i < ubuffer.count; i++)
|
||||
bbuffer.push(context.layouts.createBindGroupBuffer1Un(ubuffer_gpu, i*sizeof(T), sizeof(T)));
|
||||
assert(bbuffer.count >= ubuffer.count);
|
||||
}
|
||||
|
||||
// please, use index that was returned from append method
|
||||
WGPUBindGroup operator[](const uint32_t index) const {
|
||||
return bbuffer[index];
|
||||
}
|
||||
|
||||
void clear() {
|
||||
ubuffer.clear();
|
||||
}
|
||||
|
||||
void release(WgContext& context) {
|
||||
context.releaseBuffer(ubuffer_gpu);
|
||||
releaseBindGroups(context);
|
||||
}
|
||||
|
||||
void releaseBindGroups(WgContext& context) {
|
||||
ARRAY_FOREACH(p, bbuffer)
|
||||
context.layouts.releaseBindGroup(*p);
|
||||
bbuffer.clear();
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _TVG_WG_RENDER_DATA_H_
|
||||
|
|
|
@ -147,18 +147,18 @@ RenderData WgRenderer::prepare(const RenderShape& rshape, RenderData data, const
|
|||
|
||||
// update paint settings
|
||||
if ((!data) || (flags & (RenderUpdateFlag::Transform | RenderUpdateFlag::Blend))) {
|
||||
renderDataShape->update(mContext, transform, mTargetSurface.cs, opacity);
|
||||
renderDataShape->renderSettingsShape.update(mContext, transform, mTargetSurface.cs, opacity);
|
||||
renderDataShape->renderSettingsStroke.update(mContext, transform, mTargetSurface.cs, opacity);
|
||||
renderDataShape->fillRule = rshape.rule;
|
||||
}
|
||||
|
||||
// setup fill settings
|
||||
renderDataShape->viewport = mViewport;
|
||||
renderDataShape->opacity = opacity;
|
||||
if (flags & RenderUpdateFlag::Gradient && rshape.fill) renderDataShape->renderSettingsShape.updateFill(mContext, rshape.fill);
|
||||
else if (flags & RenderUpdateFlag::Color) renderDataShape->renderSettingsShape.updateColor(mContext, rshape.color);
|
||||
if (flags & RenderUpdateFlag::Gradient && rshape.fill) renderDataShape->renderSettingsShape.update(mContext, rshape.fill);
|
||||
else if (flags & RenderUpdateFlag::Color) renderDataShape->renderSettingsShape.update(mContext, rshape.color);
|
||||
if (rshape.stroke) {
|
||||
if (flags & RenderUpdateFlag::GradientStroke && rshape.stroke->fill) renderDataShape->renderSettingsStroke.updateFill(mContext, rshape.stroke->fill);
|
||||
else if (flags & RenderUpdateFlag::Stroke) renderDataShape->renderSettingsStroke.updateColor(mContext, rshape.stroke->color);
|
||||
if (flags & RenderUpdateFlag::GradientStroke && rshape.stroke->fill) renderDataShape->renderSettingsStroke.update(mContext, rshape.stroke->fill);
|
||||
else if (flags & RenderUpdateFlag::Stroke) renderDataShape->renderSettingsStroke.update(mContext, rshape.stroke->color);
|
||||
}
|
||||
|
||||
// store clips data
|
||||
|
@ -177,9 +177,8 @@ RenderData WgRenderer::prepare(RenderSurface* surface, RenderData data, const Ma
|
|||
|
||||
// update paint settings
|
||||
renderDataPicture->viewport = mViewport;
|
||||
renderDataPicture->opacity = opacity;
|
||||
if (flags & (RenderUpdateFlag::Transform | RenderUpdateFlag::Blend)) {
|
||||
renderDataPicture->update(mContext, transform, surface->cs, opacity);
|
||||
renderDataPicture->renderSettings.update(mContext, transform, surface->cs, opacity);
|
||||
}
|
||||
|
||||
// update image data
|
||||
|
@ -193,6 +192,7 @@ RenderData WgRenderer::prepare(RenderSurface* surface, RenderData data, const Ma
|
|||
return renderDataPicture;
|
||||
}
|
||||
|
||||
|
||||
bool WgRenderer::preRender()
|
||||
{
|
||||
// invalidate context
|
||||
|
|
|
@ -23,8 +23,6 @@
|
|||
#include "tvgWgShaderSrc.h"
|
||||
#include <string>
|
||||
|
||||
#define WG_SHADER_SOURCE(...) #__VA_ARGS__
|
||||
|
||||
//************************************************************************
|
||||
// graphics shader source: stencil
|
||||
//************************************************************************
|
||||
|
@ -32,14 +30,15 @@
|
|||
const char* cShaderSrc_Stencil = R"(
|
||||
struct VertexInput { @location(0) position: vec2f };
|
||||
struct VertexOutput { @builtin(position) position: vec4f };
|
||||
struct PaintSettings { transform: mat4x4f };
|
||||
|
||||
@group(0) @binding(0) var<uniform> uViewMat : mat4x4f;
|
||||
@group(1) @binding(0) var<uniform> uModelMat : mat4x4f;
|
||||
@group(1) @binding(0) var<uniform> uPaintSettings : PaintSettings;
|
||||
|
||||
@vertex
|
||||
fn vs_main(in: VertexInput) -> VertexOutput {
|
||||
var out: VertexOutput;
|
||||
out.position = uViewMat * uModelMat * vec4f(in.position.xy, 0.0, 1.0);
|
||||
out.position = uViewMat * uPaintSettings.transform * vec4f(in.position.xy, 0.0, 1.0);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
@ -56,15 +55,16 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4f {
|
|||
const char* cShaderSrc_Depth = R"(
|
||||
struct VertexInput { @location(0) position: vec2f };
|
||||
struct VertexOutput { @builtin(position) position: vec4f };
|
||||
struct PaintSettings { transform: mat4x4f };
|
||||
|
||||
@group(0) @binding(0) var<uniform> uViewMat : mat4x4f;
|
||||
@group(1) @binding(0) var<uniform> uModelMat : mat4x4f;
|
||||
@group(1) @binding(0) var<uniform> uPaintSettings : PaintSettings;
|
||||
@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 = uViewMat * uPaintSettings.transform * vec4f(in.position.xy, 0.0, 1.0);
|
||||
out.position.z = uDepth;
|
||||
return out;
|
||||
}
|
||||
|
@ -82,23 +82,22 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4f {
|
|||
const char* cShaderSrc_Solid = R"(
|
||||
struct VertexInput { @location(0) position: vec2f };
|
||||
struct VertexOutput { @builtin(position) position: vec4f };
|
||||
struct PaintSettings { transform: mat4x4f, options: vec4f, color: vec4f };
|
||||
|
||||
@group(0) @binding(0) var<uniform> uViewMat : mat4x4f;
|
||||
@group(1) @binding(0) var<uniform> uModelMat : mat4x4f;
|
||||
@group(1) @binding(1) var<uniform> uBlendSettings : vec4f;
|
||||
@group(2) @binding(0) var<uniform> uSolidColor : vec4f;
|
||||
@group(1) @binding(0) var<uniform> uPaintSettings : PaintSettings;
|
||||
|
||||
@vertex
|
||||
fn vs_main(in: VertexInput) -> VertexOutput {
|
||||
var out: VertexOutput;
|
||||
out.position = uViewMat * uModelMat * vec4f(in.position.xy, 0.0, 1.0);
|
||||
out.position = uViewMat * uPaintSettings.transform * vec4f(in.position.xy, 0.0, 1.0);
|
||||
return out;
|
||||
}
|
||||
|
||||
@fragment
|
||||
fn fs_main(in: VertexOutput) -> @location(0) vec4f {
|
||||
let Sc = uSolidColor;
|
||||
let So = uBlendSettings.a;
|
||||
let Sc = uPaintSettings.color;
|
||||
let So = uPaintSettings.options.a;
|
||||
return vec4f(Sc.rgb * Sc.a * So, Sc.a * So);
|
||||
}
|
||||
)";
|
||||
|
@ -110,34 +109,32 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4f {
|
|||
const char* cShaderSrc_Linear = R"(
|
||||
struct VertexInput { @location(0) position: vec2f };
|
||||
struct VertexOutput { @builtin(position) position : vec4f, @location(0) vGradCoord : vec4f };
|
||||
struct GradSettings { settings: vec4f, focal: vec4f };
|
||||
struct GradSettings { transform: mat4x4f, coords: vec4f, focal: vec4f };
|
||||
struct PaintSettings { transform: mat4x4f, options: vec4f, color: vec4f, gradient: GradSettings };
|
||||
|
||||
// uniforms
|
||||
@group(0) @binding(0) var<uniform> uViewMat : mat4x4f;
|
||||
@group(1) @binding(0) var<uniform> uModelMat : mat4x4f;
|
||||
@group(1) @binding(1) var<uniform> uBlendSettings : vec4f;
|
||||
@group(1) @binding(0) var<uniform> uPaintSettings : PaintSettings;
|
||||
@group(2) @binding(0) var uSamplerGrad : sampler;
|
||||
@group(2) @binding(1) var uTextureGrad : texture_2d<f32>;
|
||||
@group(2) @binding(2) var<uniform> uSettingGrad : GradSettings;
|
||||
@group(2) @binding(3) var<uniform> uTransformGrad : mat4x4f;
|
||||
|
||||
@vertex
|
||||
fn vs_main(in: VertexInput) -> VertexOutput {
|
||||
var out: VertexOutput;
|
||||
out.position = uViewMat * uModelMat * vec4f(in.position.xy, 0.0, 1.0);
|
||||
out.vGradCoord = uTransformGrad * vec4f(in.position.xy, 0.0, 1.0);
|
||||
out.position = uViewMat * uPaintSettings.transform * vec4f(in.position.xy, 0.0, 1.0);
|
||||
out.vGradCoord = uPaintSettings.gradient.transform * vec4f(in.position.xy, 0.0, 1.0);
|
||||
return out;
|
||||
}
|
||||
|
||||
@fragment
|
||||
fn fs_main(in: VertexOutput) -> @location(0) vec4f {
|
||||
let pos = in.vGradCoord.xy;
|
||||
let st = uSettingGrad.settings.xy;
|
||||
let ed = uSettingGrad.settings.zw;
|
||||
let st = uPaintSettings.gradient.coords.xy;
|
||||
let ed = uPaintSettings.gradient.coords.zw;
|
||||
let ba = ed - st;
|
||||
let t = dot(pos - st, ba) / dot(ba, ba);
|
||||
let Sc = textureSample(uTextureGrad, uSamplerGrad, vec2f(t, 0.5));
|
||||
let So = uBlendSettings.a;
|
||||
let So = uPaintSettings.options.a;
|
||||
return vec4f(Sc.rgb * Sc.a * So, Sc.a * So);
|
||||
}
|
||||
)";
|
||||
|
@ -149,37 +146,35 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4f {
|
|||
const char* cShaderSrc_Radial = R"(
|
||||
struct VertexInput { @location(0) position: vec2f };
|
||||
struct VertexOutput { @builtin(position) position : vec4f, @location(0) vGradCoord : vec4f };
|
||||
struct GradSettings { settings: vec4f, focal: vec4f };
|
||||
struct GradSettings { transform: mat4x4f, coords: vec4f, focal: vec4f };
|
||||
struct PaintSettings { transform: mat4x4f, options: vec4f, color: vec4f, gradient: GradSettings };
|
||||
|
||||
@group(0) @binding(0) var<uniform> uViewMat : mat4x4f;
|
||||
@group(1) @binding(0) var<uniform> uModelMat : mat4x4f;
|
||||
@group(1) @binding(1) var<uniform> uBlendSettings : vec4f;
|
||||
@group(1) @binding(0) var<uniform> uPaintSettings : PaintSettings;
|
||||
@group(2) @binding(0) var uSamplerGrad : sampler;
|
||||
@group(2) @binding(1) var uTextureGrad : texture_2d<f32>;
|
||||
@group(2) @binding(2) var<uniform> uSettingGrad : GradSettings;
|
||||
@group(2) @binding(3) var<uniform> uTransformGrad : mat4x4f;
|
||||
|
||||
@vertex
|
||||
fn vs_main(in: VertexInput) -> VertexOutput {
|
||||
var out: VertexOutput;
|
||||
out.position = uViewMat * uModelMat * vec4f(in.position.xy, 0.0, 1.0);
|
||||
out.vGradCoord = uTransformGrad * vec4f(in.position.xy, 0.0, 1.0);
|
||||
out.position = uViewMat * uPaintSettings.transform * vec4f(in.position.xy, 0.0, 1.0);
|
||||
out.vGradCoord = uPaintSettings.gradient.transform * vec4f(in.position.xy, 0.0, 1.0);
|
||||
return out;
|
||||
}
|
||||
|
||||
@fragment
|
||||
fn fs_main(in: VertexOutput) -> @location(0) vec4f {
|
||||
// orignal data
|
||||
let d0 = in.vGradCoord.xy - uSettingGrad.settings.xy;
|
||||
let d1 = uSettingGrad.settings.xy - uSettingGrad.focal.xy;
|
||||
let r0 = uSettingGrad.settings.z;
|
||||
let rd = uSettingGrad.focal.z - uSettingGrad.settings.z;
|
||||
let d0 = in.vGradCoord.xy - uPaintSettings.gradient.coords.xy;
|
||||
let d1 = uPaintSettings.gradient.coords.xy - uPaintSettings.gradient.focal.xy;
|
||||
let r0 = uPaintSettings.gradient.coords.z;
|
||||
let rd = uPaintSettings.gradient.focal.z - uPaintSettings.gradient.coords.z;
|
||||
let a = 1.0*dot(d1, d1) - 1.0*rd*rd;
|
||||
let b = 2.0*dot(d0, d1) - 2.0*r0*rd;
|
||||
let c = 1.0*dot(d0, d0) - 1.0*r0*r0;
|
||||
let t = (-b + sqrt(b*b - 4*a*c))/(2*a);
|
||||
let Sc = textureSample(uTextureGrad, uSamplerGrad, vec2f(1.0 - t, 0.5));
|
||||
let So = uBlendSettings.a;
|
||||
let So = uPaintSettings.options.a;
|
||||
return vec4f(Sc.rgb * Sc.a * So, Sc.a * So);
|
||||
}
|
||||
)";
|
||||
|
@ -191,17 +186,17 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4f {
|
|||
const char* cShaderSrc_Image = R"(
|
||||
struct VertexInput { @location(0) position: vec2f, @location(1) texCoord: vec2f };
|
||||
struct VertexOutput { @builtin(position) position: vec4f, @location(0) vTexCoord: vec2f };
|
||||
struct PaintSettings { transform: mat4x4f, options: vec4f };
|
||||
|
||||
@group(0) @binding(0) var<uniform> uViewMat : mat4x4f;
|
||||
@group(1) @binding(0) var<uniform> uModelMat : mat4x4f;
|
||||
@group(1) @binding(1) var<uniform> uBlendSettings : vec4f;
|
||||
@group(1) @binding(0) var<uniform> uPaintSettings : PaintSettings;
|
||||
@group(2) @binding(0) var uSampler : sampler;
|
||||
@group(2) @binding(1) var uTextureView : texture_2d<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 = uViewMat * uPaintSettings.transform * vec4f(in.position.xy, 0.0, 1.0);
|
||||
out.vTexCoord = in.texCoord;
|
||||
return out;
|
||||
}
|
||||
|
@ -209,7 +204,7 @@ fn vs_main(in: VertexInput) -> VertexOutput {
|
|||
@fragment
|
||||
fn fs_main(in: VertexOutput) -> @location(0) vec4f {
|
||||
var Sc: vec4f = textureSample(uTextureView, uSampler, in.vTexCoord.xy);
|
||||
let So: f32 = uBlendSettings.a;
|
||||
let So: f32 = uPaintSettings.options.a;
|
||||
return vec4f(Sc.rgb * Sc.a * So, Sc.a * So);
|
||||
};
|
||||
)";
|
||||
|
@ -248,18 +243,18 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4f {
|
|||
const char* cShaderSrc_Solid_Blend = R"(
|
||||
struct VertexInput { @location(0) position: vec2f };
|
||||
struct VertexOutput { @builtin(position) position: vec4f, @location(1) vScrCoord: vec2f };
|
||||
struct PaintSettings { transform: mat4x4f, options: vec4f, color: vec4f };
|
||||
|
||||
@group(0) @binding(0) var<uniform> uViewMat : mat4x4f;
|
||||
@group(1) @binding(0) var<uniform> uModelMat : mat4x4f;
|
||||
@group(1) @binding(1) var<uniform> uBlendSettings : vec4f;
|
||||
@group(2) @binding(0) var<uniform> uSolidColor : vec4f;
|
||||
@group(1) @binding(0) var<uniform> uPaintSettings : PaintSettings;
|
||||
// @group(2) - empty
|
||||
@group(3) @binding(0) var uSamplerDst : sampler;
|
||||
@group(3) @binding(1) var uTextureDst : texture_2d<f32>;
|
||||
|
||||
@vertex
|
||||
fn vs_main(in: VertexInput) -> VertexOutput {
|
||||
var out: VertexOutput;
|
||||
let pos = uViewMat * uModelMat * vec4f(in.position.xy, 0.0, 1.0);
|
||||
let pos = uViewMat * uPaintSettings.transform * vec4f(in.position.xy, 0.0, 1.0);
|
||||
out.position = pos;
|
||||
out.vScrCoord = vec2f(0.5 + pos.x * 0.5, 0.5 - pos.y * 0.5);
|
||||
return out;
|
||||
|
@ -268,13 +263,13 @@ fn vs_main(in: VertexInput) -> VertexOutput {
|
|||
struct FragData { Sc: vec3f, Sa: f32, So: f32, Dc: vec3f, Da: f32 };
|
||||
fn getFragData(in: VertexOutput) -> FragData {
|
||||
// get source data
|
||||
let colorSrc = uSolidColor;
|
||||
let colorSrc = uPaintSettings.color;
|
||||
let colorDst = textureSample(uTextureDst, uSamplerDst, in.vScrCoord.xy);
|
||||
// fill fragment data
|
||||
var data: FragData;
|
||||
data.Sc = colorSrc.rgb;
|
||||
data.Sa = colorSrc.a;
|
||||
data.So = uBlendSettings.a;
|
||||
data.So = uPaintSettings.options.a;
|
||||
data.Dc = colorDst.rgb;
|
||||
data.Da = colorDst.a;
|
||||
data.Sc = data.Sa * data.So * data.Sc;
|
||||
|
@ -288,24 +283,22 @@ fn postProcess(d: FragData, R: vec4f) -> vec4f { return R; };
|
|||
const char* cShaderSrc_Linear_Blend = R"(
|
||||
struct VertexInput { @location(0) position: vec2f };
|
||||
struct VertexOutput { @builtin(position) position: vec4f, @location(0) vGradCoord : vec4f, @location(1) vScrCoord: vec2f };
|
||||
struct GradSettings { settings: vec4f, focal: vec4f };
|
||||
struct GradSettings { transform: mat4x4f, coords: vec4f, focal: vec4f };
|
||||
struct PaintSettings { transform: mat4x4f, options: vec4f, color: vec4f, gradient: GradSettings };
|
||||
|
||||
@group(0) @binding(0) var<uniform> uViewMat : mat4x4f;
|
||||
@group(1) @binding(0) var<uniform> uModelMat : mat4x4f;
|
||||
@group(1) @binding(1) var<uniform> uBlendSettings : vec4f;
|
||||
@group(1) @binding(0) var<uniform> uPaintSettings : PaintSettings;
|
||||
@group(2) @binding(0) var uSamplerGrad : sampler;
|
||||
@group(2) @binding(1) var uTextureGrad : texture_2d<f32>;
|
||||
@group(2) @binding(2) var<uniform> uSettingGrad : vec4f;
|
||||
@group(2) @binding(3) var<uniform> uTransformGrad : mat4x4f;
|
||||
@group(3) @binding(0) var uSamplerDst : sampler;
|
||||
@group(3) @binding(1) var uTextureDst : texture_2d<f32>;
|
||||
|
||||
@vertex
|
||||
fn vs_main(in: VertexInput) -> VertexOutput {
|
||||
var out: VertexOutput;
|
||||
let pos = uViewMat * uModelMat * vec4f(in.position.xy, 0.0, 1.0);
|
||||
let pos = uViewMat * uPaintSettings.transform * vec4f(in.position.xy, 0.0, 1.0);
|
||||
out.position = pos;
|
||||
out.vGradCoord = uTransformGrad * vec4f(in.position.xy, 0.0, 1.0);
|
||||
out.vGradCoord = uPaintSettings.gradient.transform * vec4f(in.position.xy, 0.0, 1.0);
|
||||
out.vScrCoord = vec2f(0.5 + pos.x * 0.5, 0.5 - pos.y * 0.5);
|
||||
return out;
|
||||
}
|
||||
|
@ -314,8 +307,8 @@ struct FragData { Sc: vec3f, Sa: f32, So: f32, Dc: vec3f, Da: f32 };
|
|||
fn getFragData(in: VertexOutput) -> FragData {
|
||||
// get source data
|
||||
let pos = in.vGradCoord.xy;
|
||||
let st = uSettingGrad.xy;
|
||||
let ed = uSettingGrad.zw;
|
||||
let st = uPaintSettings.gradient.coords.xy;
|
||||
let ed = uPaintSettings.gradient.coords.zw;
|
||||
let ba = ed - st;
|
||||
let t = dot(pos - st, ba) / dot(ba, ba);
|
||||
let colorSrc = textureSample(uTextureGrad, uSamplerGrad, vec2f(t, 0.5));
|
||||
|
@ -324,7 +317,7 @@ fn getFragData(in: VertexOutput) -> FragData {
|
|||
var data: FragData;
|
||||
data.Sc = colorSrc.rgb;
|
||||
data.Sa = colorSrc.a;
|
||||
data.So = uBlendSettings.a;
|
||||
data.So = uPaintSettings.options.a;
|
||||
data.Dc = colorDst.rgb;
|
||||
data.Da = colorDst.a;
|
||||
data.Sc = mix(data.Dc, data.Sc, data.Sa * data.So);
|
||||
|
@ -338,34 +331,32 @@ fn postProcess(d: FragData, R: vec4f) -> vec4f { return R; };
|
|||
const char* cShaderSrc_Radial_Blend = R"(
|
||||
struct VertexInput { @location(0) position: vec2f };
|
||||
struct VertexOutput { @builtin(position) position: vec4f, @location(0) vGradCoord : vec4f, @location(1) vScrCoord: vec2f };
|
||||
struct GradSettings { settings: vec4f, focal: vec4f };
|
||||
struct GradSettings { transform: mat4x4f, coords: vec4f, focal: vec4f };
|
||||
struct PaintSettings { transform: mat4x4f, options: vec4f, color: vec4f, gradient: GradSettings };
|
||||
|
||||
@group(0) @binding(0) var<uniform> uViewMat : mat4x4f;
|
||||
@group(1) @binding(0) var<uniform> uModelMat : mat4x4f;
|
||||
@group(1) @binding(1) var<uniform> uBlendSettings : vec4f;
|
||||
@group(1) @binding(0) var<uniform> uPaintSettings : PaintSettings;
|
||||
@group(2) @binding(0) var uSamplerGrad : sampler;
|
||||
@group(2) @binding(1) var uTextureGrad : texture_2d<f32>;
|
||||
@group(2) @binding(2) var<uniform> uSettingGrad : GradSettings;
|
||||
@group(2) @binding(3) var<uniform> uTransformGrad : mat4x4f;
|
||||
@group(3) @binding(0) var uSamplerDst : sampler;
|
||||
@group(3) @binding(1) var uTextureDst : texture_2d<f32>;
|
||||
|
||||
@vertex
|
||||
fn vs_main(in: VertexInput) -> VertexOutput {
|
||||
var out: VertexOutput;
|
||||
let pos = uViewMat * uModelMat * vec4f(in.position.xy, 0.0, 1.0);
|
||||
let pos = uViewMat * uPaintSettings.transform * vec4f(in.position.xy, 0.0, 1.0);
|
||||
out.position = pos;
|
||||
out.vGradCoord = uTransformGrad * vec4f(in.position.xy, 0.0, 1.0);
|
||||
out.vGradCoord = uPaintSettings.gradient.transform * vec4f(in.position.xy, 0.0, 1.0);
|
||||
out.vScrCoord = vec2f(0.5 + pos.x * 0.5, 0.5 - pos.y * 0.5);
|
||||
return out;
|
||||
}
|
||||
|
||||
struct FragData { Sc: vec3f, Sa: f32, So: f32, Dc: vec3f, Da: f32 };
|
||||
fn getFragData(in: VertexOutput) -> FragData {
|
||||
let d0 = in.vGradCoord.xy - uSettingGrad.settings.xy;
|
||||
let d1 = uSettingGrad.settings.xy - uSettingGrad.focal.xy;
|
||||
let r0 = uSettingGrad.settings.z;
|
||||
let rd = uSettingGrad.focal.z - uSettingGrad.settings.z;
|
||||
let d0 = in.vGradCoord.xy - uPaintSettings.gradient.coords.xy;
|
||||
let d1 = uPaintSettings.gradient.coords.xy - uPaintSettings.gradient.focal.xy;
|
||||
let r0 = uPaintSettings.gradient.coords.z;
|
||||
let rd = uPaintSettings.gradient.focal.z - uPaintSettings.gradient.coords.z;
|
||||
let a = 1.0*dot(d1, d1) - 1.0*rd*rd;
|
||||
let b = 2.0*dot(d0, d1) - 2.0*r0*rd;
|
||||
let c = 1.0*dot(d0, d0) - 1.0*r0*r0;
|
||||
|
@ -376,7 +367,7 @@ fn getFragData(in: VertexOutput) -> FragData {
|
|||
var data: FragData;
|
||||
data.Sc = colorSrc.rgb;
|
||||
data.Sa = colorSrc.a;
|
||||
data.So = uBlendSettings.a;
|
||||
data.So = uPaintSettings.options.a;
|
||||
data.Dc = colorDst.rgb;
|
||||
data.Da = colorDst.a;
|
||||
data.Sc = mix(data.Dc, data.Sc, data.Sa * data.So);
|
||||
|
@ -390,11 +381,11 @@ fn postProcess(d: FragData, R: vec4f) -> vec4f { return R; };
|
|||
const char* cShaderSrc_Image_Blend = R"(
|
||||
struct VertexInput { @location(0) position: vec2f, @location(1) texCoord: vec2f };
|
||||
struct VertexOutput { @builtin(position) position: vec4f, @location(0) vTexCoord : vec2f, @location(1) vScrCoord: vec2f };
|
||||
struct PaintSettings { transform: mat4x4f, options: vec4f };
|
||||
|
||||
@group(0) @binding(0) var<uniform> uViewMat : mat4x4f;
|
||||
@group(1) @binding(0) var<uniform> uModelMat : mat4x4f;
|
||||
@group(1) @binding(1) var<uniform> uBlendSettings : vec4f;
|
||||
@group(2) @binding(0) var uSamplerSrc : sampler;
|
||||
@group(1) @binding(0) var<uniform> uPaintSettings : PaintSettings;
|
||||
@group(2) @binding(0) var uSamplerSrc : sampler;
|
||||
@group(2) @binding(1) var uTextureSrc : texture_2d<f32>;
|
||||
@group(3) @binding(0) var uSamplerDst : sampler;
|
||||
@group(3) @binding(1) var uTextureDst : texture_2d<f32>;
|
||||
|
@ -402,7 +393,7 @@ struct VertexOutput { @builtin(position) position: vec4f, @location(0) vTexCoord
|
|||
@vertex
|
||||
fn vs_main(in: VertexInput) -> VertexOutput {
|
||||
var out: VertexOutput;
|
||||
let pos = uViewMat * uModelMat * vec4f(in.position.xy, 0.0, 1.0);
|
||||
let pos = uViewMat * uPaintSettings.transform * vec4f(in.position.xy, 0.0, 1.0);
|
||||
out.position = pos;
|
||||
out.vTexCoord = in.texCoord;
|
||||
out.vScrCoord = vec2f(0.5 + pos.x * 0.5, 0.5 - pos.y * 0.5);
|
||||
|
@ -418,7 +409,7 @@ fn getFragData(in: VertexOutput) -> FragData {
|
|||
var data: FragData;
|
||||
data.Sc = colorSrc.rgb;
|
||||
data.Sa = colorSrc.a;
|
||||
data.So = uBlendSettings.a;
|
||||
data.So = uPaintSettings.options.a;
|
||||
data.Dc = colorDst.rgb;
|
||||
data.Da = colorDst.a;
|
||||
data.Sc = data.Sc * data.So;
|
||||
|
|
|
@ -125,35 +125,34 @@ void WgShaderTypeVec4f::update(const RenderRegion& r)
|
|||
}
|
||||
|
||||
//************************************************************************
|
||||
// WgShaderTypeGradient
|
||||
// WgShaderTypeGradSettings
|
||||
//************************************************************************
|
||||
|
||||
void WgShaderTypeGradient::update(const LinearGradient* linearGradient)
|
||||
void WgShaderTypeGradSettings::update(const Fill* fill)
|
||||
{
|
||||
// update gradient data
|
||||
assert(fill);
|
||||
// update transform matrix
|
||||
Matrix invTransform;
|
||||
if (inverse(&fill->transform(), &invTransform))
|
||||
transform.update(invTransform);
|
||||
else transform.identity();
|
||||
// update gradient base points
|
||||
if (fill->type() == Type::LinearGradient)
|
||||
((LinearGradient*)fill)->linear(&coords.vec[0], &coords.vec[1], &coords.vec[2], &coords.vec[3]);
|
||||
else if (fill->type() == Type::RadialGradient)
|
||||
((RadialGradient*)fill)->radial(&coords.vec[0], &coords.vec[1], &coords.vec[2], &focal.vec[0], &focal.vec[1], &focal.vec[2]);
|
||||
}
|
||||
|
||||
//************************************************************************
|
||||
// WgShaderTypeGradientData
|
||||
//************************************************************************
|
||||
|
||||
void WgShaderTypeGradientData::update(const Fill* fill)
|
||||
{
|
||||
if (!fill) return;
|
||||
const Fill::ColorStop* stops = nullptr;
|
||||
auto stopCnt = linearGradient->colorStops(&stops);
|
||||
updateTexData(stops, stopCnt);
|
||||
// update base points
|
||||
linearGradient->linear(&settings[0], &settings[1], &settings[2], &settings[3]);
|
||||
};
|
||||
|
||||
|
||||
void WgShaderTypeGradient::update(const RadialGradient* radialGradient)
|
||||
{
|
||||
// update gradient data
|
||||
const Fill::ColorStop* stops = nullptr;
|
||||
auto stopCnt = radialGradient->colorStops(&stops);
|
||||
updateTexData(stops, stopCnt);
|
||||
// update base points
|
||||
radialGradient->radial(&settings[0], &settings[1], &settings[2], &settings[4], &settings[5], &settings[6]);
|
||||
};
|
||||
|
||||
|
||||
void WgShaderTypeGradient::updateTexData(const Fill::ColorStop* stops, uint32_t stopCnt)
|
||||
{
|
||||
auto stopCnt = fill->colorStops(&stops);
|
||||
if (stopCnt == 0) return;
|
||||
|
||||
static Array<Fill::ColorStop> sstops(stopCnt);
|
||||
sstops.clear();
|
||||
sstops.push(stops[0]);
|
||||
|
@ -167,10 +166,10 @@ void WgShaderTypeGradient::updateTexData(const Fill::ColorStop* stops, uint32_t
|
|||
uint32_t range_s = 0;
|
||||
uint32_t range_e = uint32_t(sstops[0].offset * (WG_TEXTURE_GRADIENT_SIZE-1));
|
||||
for (uint32_t ti = range_s; (ti < range_e) && (ti < WG_TEXTURE_GRADIENT_SIZE); ti++) {
|
||||
texData[ti * 4 + 0] = sstops[0].r;
|
||||
texData[ti * 4 + 1] = sstops[0].g;
|
||||
texData[ti * 4 + 2] = sstops[0].b;
|
||||
texData[ti * 4 + 3] = sstops[0].a;
|
||||
data[ti * 4 + 0] = sstops[0].r;
|
||||
data[ti * 4 + 1] = sstops[0].g;
|
||||
data[ti * 4 + 2] = sstops[0].b;
|
||||
data[ti * 4 + 3] = sstops[0].a;
|
||||
}
|
||||
// body
|
||||
for (uint32_t di = 1; di < sstops.count; di++) {
|
||||
|
@ -179,10 +178,10 @@ void WgShaderTypeGradient::updateTexData(const Fill::ColorStop* stops, uint32_t
|
|||
float delta = 1.0f/(range_e - range_s);
|
||||
for (uint32_t ti = range_s; (ti < range_e) && (ti < WG_TEXTURE_GRADIENT_SIZE); ti++) {
|
||||
float t = (ti - range_s) * delta;
|
||||
texData[ti * 4 + 0] = tvg::lerp(sstops[di-1].r, sstops[di].r, t);
|
||||
texData[ti * 4 + 1] = tvg::lerp(sstops[di-1].g, sstops[di].g, t);
|
||||
texData[ti * 4 + 2] = tvg::lerp(sstops[di-1].b, sstops[di].b, t);
|
||||
texData[ti * 4 + 3] = tvg::lerp(sstops[di-1].a, sstops[di].a, t);
|
||||
data[ti * 4 + 0] = tvg::lerp(sstops[di-1].r, sstops[di].r, t);
|
||||
data[ti * 4 + 1] = tvg::lerp(sstops[di-1].g, sstops[di].g, t);
|
||||
data[ti * 4 + 2] = tvg::lerp(sstops[di-1].b, sstops[di].b, t);
|
||||
data[ti * 4 + 3] = tvg::lerp(sstops[di-1].a, sstops[di].a, t);
|
||||
}
|
||||
}
|
||||
// tail
|
||||
|
@ -190,10 +189,10 @@ void WgShaderTypeGradient::updateTexData(const Fill::ColorStop* stops, uint32_t
|
|||
range_s = uint32_t(colorStopLast.offset * (WG_TEXTURE_GRADIENT_SIZE-1));
|
||||
range_e = WG_TEXTURE_GRADIENT_SIZE;
|
||||
for (uint32_t ti = range_s; ti < range_e; ti++) {
|
||||
texData[ti * 4 + 0] = colorStopLast.r;
|
||||
texData[ti * 4 + 1] = colorStopLast.g;
|
||||
texData[ti * 4 + 2] = colorStopLast.b;
|
||||
texData[ti * 4 + 3] = colorStopLast.a;
|
||||
data[ti * 4 + 0] = colorStopLast.r;
|
||||
data[ti * 4 + 1] = colorStopLast.g;
|
||||
data[ti * 4 + 2] = colorStopLast.b;
|
||||
data[ti * 4 + 3] = colorStopLast.a;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -55,16 +55,44 @@ struct WgShaderTypeVec4f
|
|||
void update(const RenderRegion& r);
|
||||
};
|
||||
|
||||
// sampler, texture, vec4f
|
||||
#define WG_TEXTURE_GRADIENT_SIZE 512
|
||||
struct WgShaderTypeGradient
|
||||
// WGSL: struct GradSettings { transform: mat4x4f, coords: vec4f, focal: vec4f };
|
||||
struct WgShaderTypeGradSettings
|
||||
{
|
||||
float settings[4+4]{}; // WGSL: struct GradSettings { settings: vec4f, focal: vec4f; transform: mat4f };
|
||||
uint8_t texData[WG_TEXTURE_GRADIENT_SIZE * 4];
|
||||
// gradient transform matrix
|
||||
WgShaderTypeMat4x4f transform;
|
||||
// linear: [0] - x1, [1] - y1, [2] - x2, [3] - y2
|
||||
// radial: [0] - cx, [1] - cy, [2] - cr
|
||||
WgShaderTypeVec4f coords;
|
||||
// radial: [0] - fx, [1] - fy, [2] - fr
|
||||
WgShaderTypeVec4f focal;
|
||||
|
||||
void update(const Fill* fill);
|
||||
};
|
||||
|
||||
void update(const LinearGradient* linearGradient);
|
||||
void update(const RadialGradient* radialGradient);
|
||||
void updateTexData(const Fill::ColorStop* stops, uint32_t stopCnt);
|
||||
// WGSL: struct PaintSettings { transform: mat4x4f, options: vec4f, color: vec4f, gradient: GradSettings };
|
||||
struct WgShaderTypePaintSettings
|
||||
{
|
||||
// paint transform matrix (must be at offset 0)
|
||||
WgShaderTypeMat4x4f transform;
|
||||
// [0] - color space, [3] - opacity
|
||||
WgShaderTypeVec4f options;
|
||||
// solid color
|
||||
WgShaderTypeVec4f color;
|
||||
// gradient settings (linear/radial)
|
||||
WgShaderTypeGradSettings gradient;
|
||||
// align to 256 bytes (see webgpu spec: minUniformBufferOffsetAlignment)
|
||||
uint8_t _padding[256 - sizeof(transform) - sizeof(options) - sizeof(color) - sizeof(gradient)];
|
||||
};
|
||||
// see webgpu spec: 3.6.2. Limits - minUniformBufferOffsetAlignment (256)
|
||||
static_assert(sizeof(WgShaderTypePaintSettings) == 256, "Uniform shader data type size must be aligned to 256 bytes");
|
||||
|
||||
// gradient color map
|
||||
#define WG_TEXTURE_GRADIENT_SIZE 512
|
||||
struct WgShaderTypeGradientData
|
||||
{
|
||||
uint8_t data[WG_TEXTURE_GRADIENT_SIZE * 4];
|
||||
|
||||
void update(const Fill* fill);
|
||||
};
|
||||
|
||||
// gaussian params: sigma, scale, extend
|
||||
|
|
Loading…
Add table
Reference in a new issue