mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-14 12:04:29 +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)
|
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[] = {
|
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 };
|
const WGPUBindGroupDescriptor bindGroupDesc { .layout = layoutBuffer1Un, .entryCount = 1, .entries = bindGroupEntrys };
|
||||||
return wgpuDeviceCreateBindGroup(device, &bindGroupDesc);
|
return wgpuDeviceCreateBindGroup(device, &bindGroupDesc);
|
||||||
|
|
|
@ -49,6 +49,7 @@ public:
|
||||||
WGPUBindGroup createBindGroupStrorage2RO(WGPUTextureView texView0, WGPUTextureView texView1);
|
WGPUBindGroup createBindGroupStrorage2RO(WGPUTextureView texView0, WGPUTextureView texView1);
|
||||||
WGPUBindGroup createBindGroupStrorage3RO(WGPUTextureView texView0, WGPUTextureView texView1, WGPUTextureView texView2);
|
WGPUBindGroup createBindGroupStrorage3RO(WGPUTextureView texView0, WGPUTextureView texView1, WGPUTextureView texView2);
|
||||||
WGPUBindGroup createBindGroupBuffer1Un(WGPUBuffer buff);
|
WGPUBindGroup createBindGroupBuffer1Un(WGPUBuffer buff);
|
||||||
|
WGPUBindGroup createBindGroupBuffer1Un(WGPUBuffer buff, uint64_t offset, uint64_t size);
|
||||||
WGPUBindGroup createBindGroupBuffer2Un(WGPUBuffer buff0, WGPUBuffer buff1);
|
WGPUBindGroup createBindGroupBuffer2Un(WGPUBuffer buff0, WGPUBuffer buff1);
|
||||||
WGPUBindGroup createBindGroupBuffer3Un(WGPUBuffer buff0, WGPUBuffer buff1, WGPUBuffer buff2);
|
WGPUBindGroup createBindGroupBuffer3Un(WGPUBuffer buff0, WGPUBuffer buff1, WGPUBuffer buff2);
|
||||||
void releaseBindGroup(WGPUBindGroup& bindGroup);
|
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 (external handle, do not release)
|
||||||
pipelines.initialize(context);
|
pipelines.initialize(context);
|
||||||
stageBuffer.initialize(context);
|
stageBufferGeometry.initialize(context);
|
||||||
// initialize opacity pool
|
// initialize opacity pool
|
||||||
initPools(context);
|
initPools(context);
|
||||||
// allocate global view matrix handles
|
// allocate global view matrix handles
|
||||||
|
@ -64,7 +64,8 @@ void WgCompositor::release(WgContext& context)
|
||||||
context.layouts.releaseBindGroup(bindGroupViewMat);
|
context.layouts.releaseBindGroup(bindGroupViewMat);
|
||||||
context.releaseBuffer(bufferViewMat);
|
context.releaseBuffer(bufferViewMat);
|
||||||
// release stage buffer
|
// release stage buffer
|
||||||
stageBuffer.release(context);
|
stageBufferPaint.release(context);
|
||||||
|
stageBufferGeometry.release(context);
|
||||||
// release pipelines
|
// release pipelines
|
||||||
pipelines.release(context);
|
pipelines.release(context);
|
||||||
}
|
}
|
||||||
|
@ -190,28 +191,35 @@ void WgCompositor::endRenderPass()
|
||||||
|
|
||||||
void WgCompositor::reset(WgContext& context)
|
void WgCompositor::reset(WgContext& context)
|
||||||
{
|
{
|
||||||
stageBuffer.clear();
|
stageBufferGeometry.clear();
|
||||||
|
stageBufferPaint.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void WgCompositor::flush(WgContext& context)
|
void WgCompositor::flush(WgContext& context)
|
||||||
{
|
{
|
||||||
stageBuffer.append(&meshDataBlit);
|
stageBufferGeometry.append(&meshDataBlit);
|
||||||
stageBuffer.flush(context);
|
stageBufferGeometry.flush(context);
|
||||||
|
stageBufferPaint.flush(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void WgCompositor::requestShape(WgRenderDataShape* renderData)
|
void WgCompositor::requestShape(WgRenderDataShape* renderData)
|
||||||
{
|
{
|
||||||
stageBuffer.append(renderData);
|
stageBufferGeometry.append(renderData);
|
||||||
// TODO: expand for fill settings
|
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)
|
void WgCompositor::requestImage(WgRenderDataPicture* renderData)
|
||||||
{
|
{
|
||||||
stageBuffer.append(renderData);
|
stageBufferGeometry.append(renderData);
|
||||||
// TODO: expand for fill settings
|
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 icount = meshData->ibuffer.count;
|
||||||
uint64_t vsize = meshData->vbuffer.count * sizeof(Point);
|
uint64_t vsize = meshData->vbuffer.count * sizeof(Point);
|
||||||
uint64_t isize = icount * sizeof(uint32_t);
|
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, stageBuffer.ibuffer_gpu, WGPUIndexFormat_Uint32, meshData->ioffset, isize);
|
wgpuRenderPassEncoderSetIndexBuffer(renderPassEncoder, stageBufferGeometry.ibuffer_gpu, WGPUIndexFormat_Uint32, meshData->ioffset, isize);
|
||||||
wgpuRenderPassEncoderDrawIndexed(renderPassEncoder, icount, 1, 0, 0, 0);
|
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 icount = (meshData->vbuffer.count - 2) * 3;
|
||||||
uint64_t vsize = meshData->vbuffer.count * sizeof(Point);
|
uint64_t vsize = meshData->vbuffer.count * sizeof(Point);
|
||||||
uint64_t isize = icount * sizeof(uint32_t);
|
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);
|
wgpuRenderPassEncoderSetIndexBuffer(renderPassEncoder, context.bufferIndexFan, WGPUIndexFormat_Uint32, 0, isize);
|
||||||
wgpuRenderPassEncoderDrawIndexed(renderPassEncoder, icount, 1, 0, 0, 0);
|
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 icount = meshData->ibuffer.count;
|
||||||
uint64_t vsize = meshData->vbuffer.count * sizeof(Point);
|
uint64_t vsize = meshData->vbuffer.count * sizeof(Point);
|
||||||
uint64_t isize = icount * sizeof(uint32_t);
|
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);
|
||||||
wgpuRenderPassEncoderSetVertexBuffer(renderPassEncoder, 1, stageBuffer.vbuffer_gpu, meshData->toffset, vsize);
|
wgpuRenderPassEncoderSetVertexBuffer(renderPassEncoder, 1, stageBufferGeometry.vbuffer_gpu, meshData->toffset, vsize);
|
||||||
wgpuRenderPassEncoderSetIndexBuffer(renderPassEncoder, stageBuffer.ibuffer_gpu, WGPUIndexFormat_Uint32, meshData->ioffset, isize);
|
wgpuRenderPassEncoderSetIndexBuffer(renderPassEncoder, stageBufferGeometry.ibuffer_gpu, WGPUIndexFormat_Uint32, meshData->ioffset, isize);
|
||||||
wgpuRenderPassEncoderDrawIndexed(renderPassEncoder, icount, 1, 0, 0, 0);
|
wgpuRenderPassEncoderDrawIndexed(renderPassEncoder, icount, 1, 0, 0, 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -371,12 +379,13 @@ void WgCompositor::drawShape(WgContext& context, WgRenderDataShape* renderData)
|
||||||
assert(renderPassEncoder);
|
assert(renderPassEncoder);
|
||||||
assert(renderData->meshGroupShapes.meshes.count == renderData->meshGroupShapesBBox.meshes.count);
|
assert(renderData->meshGroupShapes.meshes.count == renderData->meshGroupShapesBBox.meshes.count);
|
||||||
if (renderData->renderSettingsShape.skip || renderData->meshGroupShapes.meshes.count == 0 || renderData->viewport.invalid()) return;
|
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());
|
wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, renderData->viewport.x(), renderData->viewport.y(), renderData->viewport.w(), renderData->viewport.h());
|
||||||
// setup stencil rules
|
// setup stencil rules
|
||||||
WGPURenderPipeline stencilPipeline = (renderData->fillRule == FillRule::NonZero) ? pipelines.nonzero : pipelines.evenodd;
|
WGPURenderPipeline stencilPipeline = (renderData->fillRule == FillRule::NonZero) ? pipelines.nonzero : pipelines.evenodd;
|
||||||
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, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, stencilPipeline);
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, stencilPipeline);
|
||||||
// draw to stencil (first pass)
|
// draw to stencil (first pass)
|
||||||
ARRAY_FOREACH(p, renderData->meshGroupShapes.meshes)
|
ARRAY_FOREACH(p, renderData->meshGroupShapes.meshes)
|
||||||
|
@ -384,16 +393,15 @@ void WgCompositor::drawShape(WgContext& context, WgRenderDataShape* renderData)
|
||||||
// setup fill rules
|
// setup fill rules
|
||||||
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, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||||
WgRenderSettings& settings = renderData->renderSettingsShape;
|
|
||||||
if (settings.fillType == WgRenderSettingsType::Solid) {
|
if (settings.fillType == WgRenderSettingsType::Solid) {
|
||||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, settings.bindGroupSolid, 0, nullptr);
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.solid);
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.solid);
|
||||||
} else if (settings.fillType == WgRenderSettingsType::Linear) {
|
} 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);
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.linear);
|
||||||
} else if (settings.fillType == WgRenderSettingsType::Radial) {
|
} 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);
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.radial);
|
||||||
}
|
}
|
||||||
// draw to color (second pass)
|
// draw to color (second pass)
|
||||||
|
@ -407,6 +415,7 @@ void WgCompositor::blendShape(WgContext& context, WgRenderDataShape* renderData,
|
||||||
assert(renderPassEncoder);
|
assert(renderPassEncoder);
|
||||||
assert(renderData->meshGroupShapes.meshes.count == renderData->meshGroupShapesBBox.meshes.count);
|
assert(renderData->meshGroupShapes.meshes.count == renderData->meshGroupShapesBBox.meshes.count);
|
||||||
if (renderData->renderSettingsShape.skip || renderData->meshGroupShapes.meshes.count == 0 || renderData->viewport.invalid()) return;
|
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
|
// copy current render target data to dst target
|
||||||
WgRenderTarget *target = currentTarget;
|
WgRenderTarget *target = currentTarget;
|
||||||
endRenderPass();
|
endRenderPass();
|
||||||
|
@ -418,7 +427,7 @@ void WgCompositor::blendShape(WgContext& context, WgRenderDataShape* renderData,
|
||||||
WGPURenderPipeline stencilPipeline = (renderData->fillRule == FillRule::NonZero) ? pipelines.nonzero : pipelines.evenodd;
|
WGPURenderPipeline stencilPipeline = (renderData->fillRule == FillRule::NonZero) ? pipelines.nonzero : pipelines.evenodd;
|
||||||
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, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, stencilPipeline);
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, stencilPipeline);
|
||||||
// draw to stencil (first pass)
|
// draw to stencil (first pass)
|
||||||
ARRAY_FOREACH(p, renderData->meshGroupShapes.meshes)
|
ARRAY_FOREACH(p, renderData->meshGroupShapes.meshes)
|
||||||
|
@ -426,18 +435,17 @@ void WgCompositor::blendShape(WgContext& context, WgRenderDataShape* renderData,
|
||||||
// setup fill rules
|
// setup fill rules
|
||||||
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, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 3, targetTemp0.bindGroupTexure, 0, nullptr);
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 3, targetTemp0.bindGroupTexure, 0, nullptr);
|
||||||
uint32_t blendMethodInd = (uint32_t)blendMethod;
|
uint32_t blendMethodInd = (uint32_t)blendMethod;
|
||||||
WgRenderSettings& settings = renderData->renderSettingsShape;
|
|
||||||
if (settings.fillType == WgRenderSettingsType::Solid) {
|
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]);
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.solid_blend[blendMethodInd]);
|
||||||
} else if (settings.fillType == WgRenderSettingsType::Linear) {
|
} 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]);
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.linear_blend[blendMethodInd]);
|
||||||
} else if (settings.fillType == WgRenderSettingsType::Radial) {
|
} 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]);
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.radial_blend[blendMethodInd]);
|
||||||
}
|
}
|
||||||
// draw to color (second pass)
|
// draw to color (second pass)
|
||||||
|
@ -451,13 +459,13 @@ void WgCompositor::clipShape(WgContext& context, WgRenderDataShape* renderData)
|
||||||
assert(renderPassEncoder);
|
assert(renderPassEncoder);
|
||||||
assert(renderData->meshGroupShapes.meshes.count == renderData->meshGroupShapesBBox.meshes.count);
|
assert(renderData->meshGroupShapes.meshes.count == renderData->meshGroupShapesBBox.meshes.count);
|
||||||
if (renderData->renderSettingsShape.skip || renderData->meshGroupShapes.meshes.count == 0 || renderData->viewport.invalid()) return;
|
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());
|
wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, renderData->viewport.x(), renderData->viewport.y(), renderData->viewport.w(), renderData->viewport.h());
|
||||||
// setup stencil rules
|
// setup stencil rules
|
||||||
WGPURenderPipeline stencilPipeline = (renderData->fillRule == FillRule::NonZero) ? pipelines.nonzero : pipelines.evenodd;
|
WGPURenderPipeline stencilPipeline = (renderData->fillRule == FillRule::NonZero) ? pipelines.nonzero : pipelines.evenodd;
|
||||||
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, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, stencilPipeline);
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, stencilPipeline);
|
||||||
// draw to stencil (first pass)
|
// draw to stencil (first pass)
|
||||||
ARRAY_FOREACH(p, renderData->meshGroupShapes.meshes)
|
ARRAY_FOREACH(p, renderData->meshGroupShapes.meshes)
|
||||||
|
@ -470,16 +478,15 @@ void WgCompositor::clipShape(WgContext& context, WgRenderDataShape* renderData)
|
||||||
// setup fill rules
|
// setup fill rules
|
||||||
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, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||||
WgRenderSettings& settings = renderData->renderSettingsShape;
|
|
||||||
if (settings.fillType == WgRenderSettingsType::Solid) {
|
if (settings.fillType == WgRenderSettingsType::Solid) {
|
||||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, settings.bindGroupSolid, 0, nullptr);
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.solid);
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.solid);
|
||||||
} else if (settings.fillType == WgRenderSettingsType::Linear) {
|
} 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);
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.linear);
|
||||||
} else if (settings.fillType == WgRenderSettingsType::Radial) {
|
} 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);
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.radial);
|
||||||
}
|
}
|
||||||
// draw to color (second pass)
|
// draw to color (second pass)
|
||||||
|
@ -493,30 +500,29 @@ void WgCompositor::drawStrokes(WgContext& context, WgRenderDataShape* renderData
|
||||||
assert(renderPassEncoder);
|
assert(renderPassEncoder);
|
||||||
assert(renderData->meshGroupStrokes.meshes.count == renderData->meshGroupStrokesBBox.meshes.count);
|
assert(renderData->meshGroupStrokes.meshes.count == renderData->meshGroupStrokesBBox.meshes.count);
|
||||||
if (renderData->renderSettingsStroke.skip || renderData->meshGroupStrokes.meshes.count == 0 || renderData->viewport.invalid()) return;
|
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());
|
wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, renderData->viewport.x(), renderData->viewport.y(), renderData->viewport.w(), renderData->viewport.h());
|
||||||
// draw strokes to stencil (first pass)
|
// draw strokes to stencil (first pass)
|
||||||
for (uint32_t i = 0; i < renderData->meshGroupStrokes.meshes.count; i++) {
|
for (uint32_t i = 0; i < renderData->meshGroupStrokes.meshes.count; i++) {
|
||||||
// setup stencil rules
|
// setup stencil rules
|
||||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 255);
|
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 255);
|
||||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr);
|
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);
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.direct);
|
||||||
// draw to stencil (first pass)
|
// draw to stencil (first pass)
|
||||||
drawMesh(context, renderData->meshGroupStrokes.meshes[i]);
|
drawMesh(context, renderData->meshGroupStrokes.meshes[i]);
|
||||||
// setup fill rules
|
// setup fill rules
|
||||||
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, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||||
WgRenderSettings& settings = renderData->renderSettingsStroke;
|
|
||||||
if (settings.fillType == WgRenderSettingsType::Solid) {
|
if (settings.fillType == WgRenderSettingsType::Solid) {
|
||||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, settings.bindGroupSolid, 0, nullptr);
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.solid);
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.solid);
|
||||||
} else if (settings.fillType == WgRenderSettingsType::Linear) {
|
} 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);
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.linear);
|
||||||
} else if (settings.fillType == WgRenderSettingsType::Radial) {
|
} 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);
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.radial);
|
||||||
}
|
}
|
||||||
// draw to color (second pass)
|
// draw to color (second pass)
|
||||||
|
@ -531,7 +537,7 @@ void WgCompositor::blendStrokes(WgContext& context, WgRenderDataShape* renderDat
|
||||||
assert(renderPassEncoder);
|
assert(renderPassEncoder);
|
||||||
assert(renderData->meshGroupStrokes.meshes.count == renderData->meshGroupStrokesBBox.meshes.count);
|
assert(renderData->meshGroupStrokes.meshes.count == renderData->meshGroupStrokesBBox.meshes.count);
|
||||||
if (renderData->renderSettingsStroke.skip || renderData->meshGroupStrokes.meshes.count == 0 || renderData->viewport.invalid()) return;
|
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
|
// copy current render target data to dst target
|
||||||
WgRenderTarget *target = currentTarget;
|
WgRenderTarget *target = currentTarget;
|
||||||
endRenderPass();
|
endRenderPass();
|
||||||
|
@ -543,25 +549,24 @@ void WgCompositor::blendStrokes(WgContext& context, WgRenderDataShape* renderDat
|
||||||
// setup stencil rules
|
// setup stencil rules
|
||||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 255);
|
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 255);
|
||||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr);
|
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);
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.direct);
|
||||||
// draw to stencil (first pass)
|
// draw to stencil (first pass)
|
||||||
drawMesh(context, renderData->meshGroupStrokes.meshes[i]);
|
drawMesh(context, renderData->meshGroupStrokes.meshes[i]);
|
||||||
// setup fill rules
|
// setup fill rules
|
||||||
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, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 3, targetTemp0.bindGroupTexure, 0, nullptr);
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 3, targetTemp0.bindGroupTexure, 0, nullptr);
|
||||||
uint32_t blendMethodInd = (uint32_t)blendMethod;
|
uint32_t blendMethodInd = (uint32_t)blendMethod;
|
||||||
WgRenderSettings& settings = renderData->renderSettingsStroke;
|
|
||||||
if (settings.fillType == WgRenderSettingsType::Solid) {
|
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]);
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.solid_blend[blendMethodInd]);
|
||||||
} else if (settings.fillType == WgRenderSettingsType::Linear) {
|
} 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]);
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.linear_blend[blendMethodInd]);
|
||||||
} else if (settings.fillType == WgRenderSettingsType::Radial) {
|
} 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]);
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.radial_blend[blendMethodInd]);
|
||||||
}
|
}
|
||||||
// draw to color (second pass)
|
// draw to color (second pass)
|
||||||
|
@ -578,13 +583,14 @@ void WgCompositor::clipStrokes(WgContext& context, WgRenderDataShape* renderData
|
||||||
if (renderData->renderSettingsStroke.skip) return;
|
if (renderData->renderSettingsStroke.skip) return;
|
||||||
if (renderData->meshGroupStrokes.meshes.count == 0) return;
|
if (renderData->meshGroupStrokes.meshes.count == 0) return;
|
||||||
if (renderData->viewport.invalid()) return;
|
if (renderData->viewport.invalid()) return;
|
||||||
|
WgRenderSettings& settings = renderData->renderSettingsStroke;
|
||||||
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 strokes to stencil (first pass)
|
// draw strokes to stencil (first pass)
|
||||||
for (uint32_t i = 0; i < renderData->meshGroupStrokes.meshes.count; i++) {
|
for (uint32_t i = 0; i < renderData->meshGroupStrokes.meshes.count; i++) {
|
||||||
// setup stencil rules
|
// setup stencil rules
|
||||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 255);
|
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 255);
|
||||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr);
|
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);
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.direct);
|
||||||
// draw to stencil (first pass)
|
// draw to stencil (first pass)
|
||||||
drawMesh(context, renderData->meshGroupStrokes.meshes[i]);
|
drawMesh(context, renderData->meshGroupStrokes.meshes[i]);
|
||||||
|
@ -596,16 +602,15 @@ void WgCompositor::clipStrokes(WgContext& context, WgRenderDataShape* renderData
|
||||||
// setup fill rules
|
// setup fill rules
|
||||||
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, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||||
WgRenderSettings& settings = renderData->renderSettingsStroke;
|
|
||||||
if (settings.fillType == WgRenderSettingsType::Solid) {
|
if (settings.fillType == WgRenderSettingsType::Solid) {
|
||||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, settings.bindGroupSolid, 0, nullptr);
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.solid);
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.solid);
|
||||||
} else if (settings.fillType == WgRenderSettingsType::Linear) {
|
} 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);
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.linear);
|
||||||
} else if (settings.fillType == WgRenderSettingsType::Radial) {
|
} 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);
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.radial);
|
||||||
}
|
}
|
||||||
// draw to color (second pass)
|
// draw to color (second pass)
|
||||||
|
@ -619,18 +624,19 @@ void WgCompositor::drawImage(WgContext& context, WgRenderDataPicture* renderData
|
||||||
assert(renderData);
|
assert(renderData);
|
||||||
assert(renderPassEncoder);
|
assert(renderPassEncoder);
|
||||||
if (renderData->viewport.invalid()) return;
|
if (renderData->viewport.invalid()) return;
|
||||||
|
WgRenderSettings& settings = renderData->renderSettings;
|
||||||
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
|
// draw stencil
|
||||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 255);
|
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 255);
|
||||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr);
|
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);
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.direct);
|
||||||
drawMeshImage(context, &renderData->meshData);
|
drawMeshImage(context, &renderData->meshData);
|
||||||
// draw image
|
// 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, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, renderData->bindGroupPicture, 0, nullptr);
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, renderData->imageData.bindGroup, 0, nullptr);
|
||||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.image);
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.image);
|
||||||
drawMeshImage(context, &renderData->meshData);
|
drawMeshImage(context, &renderData->meshData);
|
||||||
}
|
}
|
||||||
|
@ -641,6 +647,7 @@ void WgCompositor::blendImage(WgContext& context, WgRenderDataPicture* renderDat
|
||||||
assert(renderData);
|
assert(renderData);
|
||||||
assert(renderPassEncoder);
|
assert(renderPassEncoder);
|
||||||
if (renderData->viewport.invalid()) return;
|
if (renderData->viewport.invalid()) return;
|
||||||
|
WgRenderSettings& settings = renderData->renderSettings;
|
||||||
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());
|
||||||
// copy current render target data to dst target
|
// copy current render target data to dst target
|
||||||
WgRenderTarget *target = currentTarget;
|
WgRenderTarget *target = currentTarget;
|
||||||
|
@ -650,15 +657,15 @@ void WgCompositor::blendImage(WgContext& context, WgRenderDataPicture* renderDat
|
||||||
// setup stencil rules
|
// setup stencil rules
|
||||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 255);
|
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 255);
|
||||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr);
|
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);
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.direct);
|
||||||
drawMeshImage(context, &renderData->meshData);
|
drawMeshImage(context, &renderData->meshData);
|
||||||
// blend image
|
// blend image
|
||||||
uint32_t blendMethodInd = (uint32_t)blendMethod;
|
uint32_t blendMethodInd = (uint32_t)blendMethod;
|
||||||
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, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, renderData->bindGroupPicture, 0, nullptr);
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, renderData->imageData.bindGroup, 0, nullptr);
|
||||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 3, targetTemp0.bindGroupTexure, 0, nullptr);
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 3, targetTemp0.bindGroupTexure, 0, nullptr);
|
||||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.image_blend[blendMethodInd]);
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.image_blend[blendMethodInd]);
|
||||||
drawMeshImage(context, &renderData->meshData);
|
drawMeshImage(context, &renderData->meshData);
|
||||||
|
@ -670,11 +677,12 @@ void WgCompositor::clipImage(WgContext& context, WgRenderDataPicture* renderData
|
||||||
assert(renderData);
|
assert(renderData);
|
||||||
assert(renderPassEncoder);
|
assert(renderPassEncoder);
|
||||||
if (renderData->viewport.invalid()) return;
|
if (renderData->viewport.invalid()) return;
|
||||||
|
WgRenderSettings& settings = renderData->renderSettings;
|
||||||
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());
|
||||||
// setup stencil rules
|
// setup stencil rules
|
||||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 255);
|
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 255);
|
||||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr);
|
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);
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.direct);
|
||||||
drawMeshImage(context, &renderData->meshData);
|
drawMeshImage(context, &renderData->meshData);
|
||||||
// merge depth and stencil buffer
|
// merge depth and stencil buffer
|
||||||
|
@ -685,8 +693,8 @@ void WgCompositor::clipImage(WgContext& context, WgRenderDataPicture* renderData
|
||||||
// draw image
|
// 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, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, renderData->bindGroupPicture, 0, nullptr);
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, renderData->imageData.bindGroup, 0, nullptr);
|
||||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.image);
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.image);
|
||||||
drawMeshImage(context, &renderData->meshData);
|
drawMeshImage(context, &renderData->meshData);
|
||||||
}
|
}
|
||||||
|
@ -734,16 +742,19 @@ void WgCompositor::blendScene(WgContext& context, WgRenderTarget* scene, WgCompo
|
||||||
void WgCompositor::markupClipPath(WgContext& context, WgRenderDataShape* renderData)
|
void WgCompositor::markupClipPath(WgContext& context, WgRenderDataShape* renderData)
|
||||||
{
|
{
|
||||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr);
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr);
|
||||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, renderData->bindGroupPaint, 0, nullptr);
|
|
||||||
// markup stencil
|
// markup stencil
|
||||||
if (renderData->meshGroupStrokes.meshes.count > 0) {
|
if (renderData->meshGroupStrokes.meshes.count > 0) {
|
||||||
|
WgRenderSettings& settings = renderData->renderSettingsStroke;
|
||||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 255);
|
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 255);
|
||||||
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.direct);
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.direct);
|
||||||
ARRAY_FOREACH(p, renderData->meshGroupStrokes.meshes)
|
ARRAY_FOREACH(p, renderData->meshGroupStrokes.meshes)
|
||||||
drawMesh(context, (*p));
|
drawMesh(context, (*p));
|
||||||
} else {
|
} else {
|
||||||
WGPURenderPipeline stencilPipeline = (renderData->fillRule == FillRule::NonZero) ? pipelines.nonzero : pipelines.evenodd;
|
WGPURenderPipeline stencilPipeline = (renderData->fillRule == FillRule::NonZero) ? pipelines.nonzero : pipelines.evenodd;
|
||||||
|
WgRenderSettings& settings = renderData->renderSettingsShape;
|
||||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
||||||
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, stencilPipeline);
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, stencilPipeline);
|
||||||
ARRAY_FOREACH(p, renderData->meshGroupShapes.meshes)
|
ARRAY_FOREACH(p, renderData->meshGroupShapes.meshes)
|
||||||
drawMeshFan(context, (*p));
|
drawMeshFan(context, (*p));
|
||||||
|
@ -760,12 +771,13 @@ void WgCompositor::renderClipPath(WgContext& context, WgRenderDataPaint* paint)
|
||||||
wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, 0, 0, width, height);
|
wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, 0, 0, width, height);
|
||||||
// get render data
|
// get render data
|
||||||
WgRenderDataShape* renderData0 = (WgRenderDataShape*)paint->clips[0];
|
WgRenderDataShape* renderData0 = (WgRenderDataShape*)paint->clips[0];
|
||||||
|
WgRenderSettings& settings0 = renderData0->renderSettingsShape;
|
||||||
// markup stencil
|
// markup stencil
|
||||||
markupClipPath(context, renderData0);
|
markupClipPath(context, renderData0);
|
||||||
// copy stencil to depth
|
// copy stencil to depth
|
||||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
||||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr);
|
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);
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, bindGroupOpacities[128], 0, nullptr);
|
||||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.copy_stencil_to_depth);
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.copy_stencil_to_depth);
|
||||||
drawMeshFan(context, &renderData0->meshDataBBox);
|
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) {
|
for (auto p = paint->clips.begin() + 1; p < paint->clips.end(); ++p) {
|
||||||
// get render data
|
// get render data
|
||||||
WgRenderDataShape* renderData = (WgRenderDataShape*)(*p);
|
WgRenderDataShape* renderData = (WgRenderDataShape*)(*p);
|
||||||
|
WgRenderSettings& settings = renderData->renderSettingsShape;
|
||||||
// markup stencil
|
// markup stencil
|
||||||
markupClipPath(context, renderData);
|
markupClipPath(context, renderData);
|
||||||
// copy stencil to depth (clear stencil)
|
// copy stencil to depth (clear stencil)
|
||||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
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);
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, bindGroupOpacities[190], 0, nullptr);
|
||||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.copy_stencil_to_depth_interm);
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.copy_stencil_to_depth_interm);
|
||||||
drawMeshFan(context, &renderData->meshDataBBox);
|
drawMeshFan(context, &renderData->meshDataBBox);
|
||||||
// copy depth to stencil
|
// copy depth to stencil
|
||||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 1);
|
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);
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, bindGroupOpacities[190], 0, nullptr);
|
||||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.copy_depth_to_stencil);
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.copy_depth_to_stencil);
|
||||||
drawMeshFan(context, &renderData->meshDataBBox);
|
drawMeshFan(context, &renderData->meshDataBBox);
|
||||||
// clear depth current (keep stencil)
|
// clear depth current (keep stencil)
|
||||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
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);
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, bindGroupOpacities[255], 0, nullptr);
|
||||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.clear_depth);
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.clear_depth);
|
||||||
drawMeshFan(context, &renderData->meshDataBBox);
|
drawMeshFan(context, &renderData->meshDataBBox);
|
||||||
// clear depth original (keep stencil)
|
// clear depth original (keep stencil)
|
||||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
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);
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, bindGroupOpacities[255], 0, nullptr);
|
||||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.clear_depth);
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.clear_depth);
|
||||||
drawMeshFan(context, &renderData0->meshDataBBox);
|
drawMeshFan(context, &renderData0->meshDataBBox);
|
||||||
// copy stencil to depth (clear stencil)
|
// copy stencil to depth (clear stencil)
|
||||||
wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0);
|
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);
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, bindGroupOpacities[128], 0, nullptr);
|
||||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.copy_stencil_to_depth);
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.copy_stencil_to_depth);
|
||||||
drawMeshFan(context, &renderData->meshDataBBox);
|
drawMeshFan(context, &renderData->meshDataBBox);
|
||||||
|
@ -819,10 +832,11 @@ void WgCompositor::clearClipPath(WgContext& context, WgRenderDataPaint* paint)
|
||||||
// get render data
|
// get render data
|
||||||
ARRAY_FOREACH(p, paint->clips) {
|
ARRAY_FOREACH(p, paint->clips) {
|
||||||
WgRenderDataShape* renderData = (WgRenderDataShape*)(*p);
|
WgRenderDataShape* renderData = (WgRenderDataShape*)(*p);
|
||||||
|
WgRenderSettings& settings = renderData->renderSettingsShape;
|
||||||
// set transformations
|
// set transformations
|
||||||
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, stageBufferPaint[settings.bindGroupInd], 0, nullptr);
|
||||||
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, bindGroupOpacities[255], 0, nullptr);
|
wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 2, bindGroupOpacities[255], 0, nullptr);
|
||||||
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.clear_depth);
|
wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelines.clear_depth);
|
||||||
drawMeshFan(context, &renderData->meshDataBBox);
|
drawMeshFan(context, &renderData->meshDataBBox);
|
||||||
|
|
|
@ -39,7 +39,8 @@ private:
|
||||||
// pipelines
|
// pipelines
|
||||||
WgPipelines pipelines{};
|
WgPipelines pipelines{};
|
||||||
// stage buffers
|
// stage buffers
|
||||||
WgRenderDataStageBuffer stageBuffer{};
|
WgStageBufferGeometry stageBufferGeometry{};
|
||||||
|
WgStageBufferUniform<WgShaderTypePaintSettings> stageBufferPaint;
|
||||||
// global stencil/depth buffer handles
|
// global stencil/depth buffer handles
|
||||||
WGPUTexture texDepthStencil{};
|
WGPUTexture texDepthStencil{};
|
||||||
WGPUTextureView texViewDepthStencil{};
|
WGPUTextureView texViewDepthStencil{};
|
||||||
|
|
|
@ -167,17 +167,17 @@ void WgPipelines::initialize(WgContext& context)
|
||||||
|
|
||||||
const WgBindGroupLayouts& layouts = context.layouts;
|
const WgBindGroupLayouts& layouts = context.layouts;
|
||||||
// bind group layouts helpers
|
// bind group layouts helpers
|
||||||
const WGPUBindGroupLayout bindGroupLayoutsStencil[] { layouts.layoutBuffer1Un, layouts.layoutBuffer2Un };
|
const WGPUBindGroupLayout bindGroupLayoutsStencil[] { layouts.layoutBuffer1Un, layouts.layoutBuffer1Un };
|
||||||
const WGPUBindGroupLayout bindGroupLayoutsDepth[] { layouts.layoutBuffer1Un, layouts.layoutBuffer2Un, layouts.layoutBuffer1Un };
|
const WGPUBindGroupLayout bindGroupLayoutsDepth[] { layouts.layoutBuffer1Un, layouts.layoutBuffer1Un, 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.layoutBuffer1Un };
|
||||||
const WGPUBindGroupLayout bindGroupLayoutsGradient[] { layouts.layoutBuffer1Un, layouts.layoutBuffer2Un, layouts.layoutTexSampledBuff2Un };
|
const WGPUBindGroupLayout bindGroupLayoutsGradient[] { layouts.layoutBuffer1Un, layouts.layoutBuffer1Un, layouts.layoutTexSampled };
|
||||||
const WGPUBindGroupLayout bindGroupLayoutsImage[] { layouts.layoutBuffer1Un, layouts.layoutBuffer2Un, layouts.layoutTexSampled };
|
const WGPUBindGroupLayout bindGroupLayoutsImage[] { layouts.layoutBuffer1Un, layouts.layoutBuffer1Un, layouts.layoutTexSampled };
|
||||||
const WGPUBindGroupLayout bindGroupLayoutsScene[] { layouts.layoutTexSampled, layouts.layoutBuffer1Un };
|
const WGPUBindGroupLayout bindGroupLayoutsScene[] { layouts.layoutTexSampled, layouts.layoutBuffer1Un };
|
||||||
// bind group layouts custom blend
|
// bind group layouts custom blend
|
||||||
const WGPUBindGroupLayout bindGroupLayoutsSolidBlend[] { layouts.layoutBuffer1Un, layouts.layoutBuffer2Un, layouts.layoutBuffer1Un, layouts.layoutTexSampled };
|
const WGPUBindGroupLayout bindGroupLayoutsSolidBlend[] { layouts.layoutBuffer1Un, layouts.layoutBuffer1Un, layouts.layoutBuffer1Un, layouts.layoutTexSampled };
|
||||||
const WGPUBindGroupLayout bindGroupLayoutsGradientBlend[] { layouts.layoutBuffer1Un, layouts.layoutBuffer2Un, layouts.layoutTexSampledBuff2Un, layouts.layoutTexSampled };
|
const WGPUBindGroupLayout bindGroupLayoutsGradientBlend[] { layouts.layoutBuffer1Un, layouts.layoutBuffer1Un, layouts.layoutTexSampled, layouts.layoutTexSampled };
|
||||||
const WGPUBindGroupLayout bindGroupLayoutsImageBlend[] { layouts.layoutBuffer1Un, layouts.layoutBuffer2Un, layouts.layoutTexSampled, layouts.layoutTexSampled };
|
const WGPUBindGroupLayout bindGroupLayoutsImageBlend[] { layouts.layoutBuffer1Un, layouts.layoutBuffer1Un, layouts.layoutTexSampled, layouts.layoutTexSampled };
|
||||||
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 };
|
||||||
|
@ -229,7 +229,7 @@ void WgPipelines::initialize(WgContext& context)
|
||||||
layout_stencil = createPipelineLayout(context.device, bindGroupLayoutsStencil, 2);
|
layout_stencil = createPipelineLayout(context.device, bindGroupLayoutsStencil, 2);
|
||||||
layout_depth = createPipelineLayout(context.device, bindGroupLayoutsDepth, 3);
|
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, 2);
|
||||||
layout_gradient = createPipelineLayout(context.device, bindGroupLayoutsGradient, 3);
|
layout_gradient = createPipelineLayout(context.device, bindGroupLayoutsGradient, 3);
|
||||||
layout_image = createPipelineLayout(context.device, bindGroupLayoutsImage, 3);
|
layout_image = createPipelineLayout(context.device, bindGroupLayoutsImage, 3);
|
||||||
layout_scene = createPipelineLayout(context.device, bindGroupLayoutsScene, 2);
|
layout_scene = createPipelineLayout(context.device, bindGroupLayoutsScene, 2);
|
||||||
|
|
|
@ -202,12 +202,38 @@ void WgImageData::update(WgContext& context, const RenderSurface* surface)
|
||||||
if (texHandleChanged) {
|
if (texHandleChanged) {
|
||||||
context.releaseTextureView(textureView);
|
context.releaseTextureView(textureView);
|
||||||
textureView = context.createTextureView(texture);
|
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)
|
void WgImageData::release(WgContext& context)
|
||||||
{
|
{
|
||||||
|
context.layouts.releaseBindGroup(bindGroup);
|
||||||
context.releaseTextureView(textureView);
|
context.releaseTextureView(textureView);
|
||||||
context.releaseTexture(texture);
|
context.releaseTexture(texture);
|
||||||
};
|
};
|
||||||
|
@ -216,52 +242,31 @@ void WgImageData::release(WgContext& context)
|
||||||
// WgRenderSettings
|
// 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;
|
settings.transform.update(transform);
|
||||||
// get gradient transfrom matrix
|
settings.options.update(cs, opacity);
|
||||||
Matrix invFillTransform;
|
}
|
||||||
WgShaderTypeMat4x4f gradientTrans; // identity by default
|
|
||||||
if (inverse(&fill->transform(), &invFillTransform))
|
void WgRenderSettings::update(WgContext& context, const Fill* fill)
|
||||||
gradientTrans.update(invFillTransform);
|
{
|
||||||
|
assert(fill);
|
||||||
|
settings.gradient.update(fill);
|
||||||
|
gradientData.update(context, fill);
|
||||||
// get gradient rasterisation settings
|
// get gradient rasterisation settings
|
||||||
WgShaderTypeGradient gradient;
|
rasterType = WgRenderRasterType::Gradient;
|
||||||
if (fill->type() == Type::LinearGradient) {
|
if (fill->type() == Type::LinearGradient)
|
||||||
gradient.update((LinearGradient*)fill);
|
|
||||||
fillType = WgRenderSettingsType::Linear;
|
fillType = WgRenderSettingsType::Linear;
|
||||||
} else if (fill->type() == Type::RadialGradient) {
|
else if (fill->type() == Type::RadialGradient)
|
||||||
gradient.update((RadialGradient*)fill);
|
|
||||||
fillType = WgRenderSettingsType::Radial;
|
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;
|
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;
|
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;
|
fillType = WgRenderSettingsType::Solid;
|
||||||
skip = (c.a == 0);
|
skip = (c.a == 0);
|
||||||
};
|
};
|
||||||
|
@ -269,13 +274,7 @@ void WgRenderSettings::updateColor(WgContext& context, const RenderColor& c)
|
||||||
|
|
||||||
void WgRenderSettings::release(WgContext& context)
|
void WgRenderSettings::release(WgContext& context)
|
||||||
{
|
{
|
||||||
context.layouts.releaseBindGroup(bindGroupSolid);
|
gradientData.release(context);
|
||||||
context.layouts.releaseBindGroup(bindGroupGradient);
|
|
||||||
context.releaseBuffer(bufferGroupSolid);
|
|
||||||
context.releaseBuffer(bufferGroupGradient);
|
|
||||||
context.releaseBuffer(bufferGroupTransfromGrad);
|
|
||||||
context.releaseTexture(texGradient);
|
|
||||||
context.releaseTextureView(texViewGradient);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//***********************************************************************
|
//***********************************************************************
|
||||||
|
@ -284,26 +283,10 @@ void WgRenderSettings::release(WgContext& context)
|
||||||
|
|
||||||
void WgRenderDataPaint::release(WgContext& context)
|
void WgRenderDataPaint::release(WgContext& context)
|
||||||
{
|
{
|
||||||
context.layouts.releaseBindGroup(bindGroupPaint);
|
|
||||||
context.releaseBuffer(bufferModelMat);
|
|
||||||
context.releaseBuffer(bufferBlendSettings);
|
|
||||||
clips.clear();
|
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) {
|
void WgRenderDataPaint::updateClips(tvg::Array<tvg::RenderData> &clips) {
|
||||||
this->clips.clear();
|
this->clips.clear();
|
||||||
ARRAY_FOREACH(p, clips) {
|
ARRAY_FOREACH(p, clips) {
|
||||||
|
@ -467,17 +450,12 @@ void WgRenderDataPicture::updateSurface(WgContext& context, const RenderSurface*
|
||||||
meshData.imageBox(context, surface->w, surface->h);
|
meshData.imageBox(context, surface->w, surface->h);
|
||||||
// update texture data
|
// update texture data
|
||||||
imageData.update(context, surface);
|
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)
|
void WgRenderDataPicture::release(WgContext& context)
|
||||||
{
|
{
|
||||||
context.layouts.releaseBindGroup(bindGroupPicture);
|
renderSettings.release(context);
|
||||||
imageData.release(context);
|
imageData.release(context);
|
||||||
meshData.release(context);
|
meshData.release(context);
|
||||||
WgRenderDataPaint::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);
|
assert(meshData);
|
||||||
uint32_t vsize = meshData->vbuffer.count * sizeof(meshData->vbuffer[0]);
|
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);
|
ARRAY_FOREACH(p, meshDataGroup->meshes) append(*p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void WgRenderDataStageBuffer::append(WgRenderDataShape* renderDataShape)
|
void WgStageBufferGeometry::append(WgRenderDataShape* renderDataShape)
|
||||||
{
|
{
|
||||||
append(&renderDataShape->meshGroupShapes);
|
append(&renderDataShape->meshGroupShapes);
|
||||||
append(&renderDataShape->meshGroupShapesBBox);
|
append(&renderDataShape->meshGroupShapesBBox);
|
||||||
append(&renderDataShape->meshGroupStrokes);
|
append(&renderDataShape->meshGroupStrokes);
|
||||||
append(&renderDataShape->meshGroupStrokesBBox);
|
append(&renderDataShape->meshGroupStrokesBBox);
|
||||||
append(&renderDataShape->meshDataBBox);
|
append(&renderDataShape->meshDataBBox);
|
||||||
ARRAY_FOREACH(p, renderDataShape->clips)
|
|
||||||
append((WgRenderDataShape* )(*p));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void WgRenderDataStageBuffer::append(WgRenderDataPicture* renderDataPicture)
|
void WgStageBufferGeometry::append(WgRenderDataPicture* renderDataPicture)
|
||||||
{
|
{
|
||||||
append(&renderDataPicture->meshData);
|
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(vbuffer_gpu);
|
||||||
context.releaseBuffer(ibuffer_gpu);
|
context.releaseBuffer(ibuffer_gpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void WgRenderDataStageBuffer::clear()
|
void WgStageBufferGeometry::clear()
|
||||||
{
|
{
|
||||||
vbuffer.clear();
|
vbuffer.clear();
|
||||||
ibuffer.clear();
|
ibuffer.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void WgRenderDataStageBuffer::flush(WgContext& context)
|
void WgStageBufferGeometry::flush(WgContext& context)
|
||||||
{
|
{
|
||||||
context.allocateBufferVertex(vbuffer_gpu, (float *)vbuffer.data, vbuffer.count);
|
context.allocateBufferVertex(vbuffer_gpu, (float *)vbuffer.data, vbuffer.count);
|
||||||
context.allocateBufferIndex(ibuffer_gpu, (uint32_t *)ibuffer.data, ibuffer.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, 0, vbuffer_gpu, voffset, vbuffer.count - voffset);
|
||||||
wgpuRenderPassEncoderSetVertexBuffer(renderPass, 1, vbuffer_gpu, toffset, vbuffer.count - toffset);
|
wgpuRenderPassEncoderSetVertexBuffer(renderPass, 1, vbuffer_gpu, toffset, vbuffer.count - toffset);
|
||||||
|
|
|
@ -66,8 +66,10 @@ struct WgMeshDataGroup {
|
||||||
struct WgImageData {
|
struct WgImageData {
|
||||||
WGPUTexture texture{};
|
WGPUTexture texture{};
|
||||||
WGPUTextureView textureView{};
|
WGPUTextureView textureView{};
|
||||||
|
WGPUBindGroup bindGroup{};
|
||||||
|
|
||||||
void update(WgContext& context, const RenderSurface* surface);
|
void update(WgContext& context, const RenderSurface* surface);
|
||||||
|
void update(WgContext& context, const Fill* fill);
|
||||||
void release(WgContext& context);
|
void release(WgContext& context);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -76,37 +78,29 @@ enum class WgRenderRasterType { Solid = 0, Gradient, Image };
|
||||||
|
|
||||||
struct WgRenderSettings
|
struct WgRenderSettings
|
||||||
{
|
{
|
||||||
WGPUBuffer bufferGroupSolid{};
|
uint32_t bindGroupInd{};
|
||||||
WGPUBindGroup bindGroupSolid{};
|
WgShaderTypePaintSettings settings;
|
||||||
WGPUTexture texGradient{};
|
WgImageData gradientData;
|
||||||
WGPUTextureView texViewGradient{};
|
|
||||||
WGPUBuffer bufferGroupGradient{};
|
|
||||||
WGPUBuffer bufferGroupTransfromGrad{};
|
|
||||||
WGPUBindGroup bindGroupGradient{};
|
|
||||||
WgRenderSettingsType fillType{};
|
WgRenderSettingsType fillType{};
|
||||||
WgRenderRasterType rasterType{};
|
WgRenderRasterType rasterType{};
|
||||||
bool skip{};
|
bool skip{};
|
||||||
|
|
||||||
void updateFill(WgContext& context, const Fill* fill);
|
void update(WgContext& context, const tvg::Matrix& transform, tvg::ColorSpace cs, uint8_t opacity);
|
||||||
void updateColor(WgContext& context, const RenderColor& c);
|
void update(WgContext& context, const Fill* fill);
|
||||||
|
void update(WgContext& context, const RenderColor& c);
|
||||||
void release(WgContext& context);
|
void release(WgContext& context);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WgRenderDataPaint
|
struct WgRenderDataPaint
|
||||||
{
|
{
|
||||||
WGPUBuffer bufferModelMat{};
|
|
||||||
WGPUBuffer bufferBlendSettings{};
|
|
||||||
WGPUBindGroup bindGroupPaint{};
|
|
||||||
RenderRegion viewport{};
|
|
||||||
BBox aabb{{},{}};
|
BBox aabb{{},{}};
|
||||||
float opacity{};
|
RenderRegion viewport{};
|
||||||
Array<WgRenderDataPaint*> clips;
|
Array<WgRenderDataPaint*> clips;
|
||||||
|
|
||||||
virtual ~WgRenderDataPaint() {};
|
virtual ~WgRenderDataPaint() {};
|
||||||
virtual void release(WgContext& context);
|
virtual void release(WgContext& context);
|
||||||
virtual Type type() { return Type::Undefined; };
|
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);
|
void updateClips(tvg::Array<tvg::RenderData> &clips);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -147,7 +141,7 @@ public:
|
||||||
|
|
||||||
struct WgRenderDataPicture: public WgRenderDataPaint
|
struct WgRenderDataPicture: public WgRenderDataPaint
|
||||||
{
|
{
|
||||||
WGPUBindGroup bindGroupPicture{};
|
WgRenderSettings renderSettings{};
|
||||||
WgImageData imageData{};
|
WgImageData imageData{};
|
||||||
WgMeshData meshData{};
|
WgMeshData meshData{};
|
||||||
|
|
||||||
|
@ -221,7 +215,7 @@ public:
|
||||||
void release(WgContext& context);
|
void release(WgContext& context);
|
||||||
};
|
};
|
||||||
|
|
||||||
class WgRenderDataStageBuffer {
|
class WgStageBufferGeometry {
|
||||||
private:
|
private:
|
||||||
Array<uint8_t> vbuffer;
|
Array<uint8_t> vbuffer;
|
||||||
Array<uint8_t> ibuffer;
|
Array<uint8_t> ibuffer;
|
||||||
|
@ -240,4 +234,50 @@ public:
|
||||||
void bind(WGPURenderPassEncoder renderPass, size_t voffset, size_t toffset);
|
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_
|
#endif // _TVG_WG_RENDER_DATA_H_
|
||||||
|
|
|
@ -147,18 +147,18 @@ RenderData WgRenderer::prepare(const RenderShape& rshape, RenderData data, const
|
||||||
|
|
||||||
// update paint settings
|
// update paint settings
|
||||||
if ((!data) || (flags & (RenderUpdateFlag::Transform | RenderUpdateFlag::Blend))) {
|
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;
|
renderDataShape->fillRule = rshape.rule;
|
||||||
}
|
}
|
||||||
|
|
||||||
// setup fill settings
|
// setup fill settings
|
||||||
renderDataShape->viewport = mViewport;
|
renderDataShape->viewport = mViewport;
|
||||||
renderDataShape->opacity = opacity;
|
if (flags & RenderUpdateFlag::Gradient && rshape.fill) renderDataShape->renderSettingsShape.update(mContext, rshape.fill);
|
||||||
if (flags & RenderUpdateFlag::Gradient && rshape.fill) renderDataShape->renderSettingsShape.updateFill(mContext, rshape.fill);
|
else if (flags & RenderUpdateFlag::Color) renderDataShape->renderSettingsShape.update(mContext, rshape.color);
|
||||||
else if (flags & RenderUpdateFlag::Color) renderDataShape->renderSettingsShape.updateColor(mContext, rshape.color);
|
|
||||||
if (rshape.stroke) {
|
if (rshape.stroke) {
|
||||||
if (flags & RenderUpdateFlag::GradientStroke && rshape.stroke->fill) renderDataShape->renderSettingsStroke.updateFill(mContext, rshape.stroke->fill);
|
if (flags & RenderUpdateFlag::GradientStroke && rshape.stroke->fill) renderDataShape->renderSettingsStroke.update(mContext, rshape.stroke->fill);
|
||||||
else if (flags & RenderUpdateFlag::Stroke) renderDataShape->renderSettingsStroke.updateColor(mContext, rshape.stroke->color);
|
else if (flags & RenderUpdateFlag::Stroke) renderDataShape->renderSettingsStroke.update(mContext, rshape.stroke->color);
|
||||||
}
|
}
|
||||||
|
|
||||||
// store clips data
|
// store clips data
|
||||||
|
@ -177,9 +177,8 @@ RenderData WgRenderer::prepare(RenderSurface* surface, RenderData data, const Ma
|
||||||
|
|
||||||
// update paint settings
|
// update paint settings
|
||||||
renderDataPicture->viewport = mViewport;
|
renderDataPicture->viewport = mViewport;
|
||||||
renderDataPicture->opacity = opacity;
|
|
||||||
if (flags & (RenderUpdateFlag::Transform | RenderUpdateFlag::Blend)) {
|
if (flags & (RenderUpdateFlag::Transform | RenderUpdateFlag::Blend)) {
|
||||||
renderDataPicture->update(mContext, transform, surface->cs, opacity);
|
renderDataPicture->renderSettings.update(mContext, transform, surface->cs, opacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
// update image data
|
// update image data
|
||||||
|
@ -193,6 +192,7 @@ RenderData WgRenderer::prepare(RenderSurface* surface, RenderData data, const Ma
|
||||||
return renderDataPicture;
|
return renderDataPicture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool WgRenderer::preRender()
|
bool WgRenderer::preRender()
|
||||||
{
|
{
|
||||||
// invalidate context
|
// invalidate context
|
||||||
|
|
|
@ -23,8 +23,6 @@
|
||||||
#include "tvgWgShaderSrc.h"
|
#include "tvgWgShaderSrc.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#define WG_SHADER_SOURCE(...) #__VA_ARGS__
|
|
||||||
|
|
||||||
//************************************************************************
|
//************************************************************************
|
||||||
// graphics shader source: stencil
|
// graphics shader source: stencil
|
||||||
//************************************************************************
|
//************************************************************************
|
||||||
|
@ -32,14 +30,15 @@
|
||||||
const char* cShaderSrc_Stencil = R"(
|
const char* cShaderSrc_Stencil = R"(
|
||||||
struct VertexInput { @location(0) position: vec2f };
|
struct VertexInput { @location(0) position: vec2f };
|
||||||
struct VertexOutput { @builtin(position) position: vec4f };
|
struct VertexOutput { @builtin(position) position: vec4f };
|
||||||
|
struct PaintSettings { transform: mat4x4f };
|
||||||
|
|
||||||
@group(0) @binding(0) var<uniform> uViewMat : 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
|
@vertex
|
||||||
fn vs_main(in: VertexInput) -> VertexOutput {
|
fn vs_main(in: VertexInput) -> VertexOutput {
|
||||||
var out: 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;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,15 +55,16 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4f {
|
||||||
const char* cShaderSrc_Depth = R"(
|
const char* cShaderSrc_Depth = R"(
|
||||||
struct VertexInput { @location(0) position: vec2f };
|
struct VertexInput { @location(0) position: vec2f };
|
||||||
struct VertexOutput { @builtin(position) position: vec4f };
|
struct VertexOutput { @builtin(position) position: vec4f };
|
||||||
|
struct PaintSettings { transform: mat4x4f };
|
||||||
|
|
||||||
@group(0) @binding(0) var<uniform> uViewMat : 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;
|
@group(2) @binding(0) var<uniform> uDepth : f32;
|
||||||
|
|
||||||
@vertex
|
@vertex
|
||||||
fn vs_main(in: VertexInput) -> VertexOutput {
|
fn vs_main(in: VertexInput) -> VertexOutput {
|
||||||
var out: 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;
|
out.position.z = uDepth;
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
@ -82,23 +82,22 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4f {
|
||||||
const char* cShaderSrc_Solid = R"(
|
const char* cShaderSrc_Solid = R"(
|
||||||
struct VertexInput { @location(0) position: vec2f };
|
struct VertexInput { @location(0) position: vec2f };
|
||||||
struct VertexOutput { @builtin(position) position: vec4f };
|
struct VertexOutput { @builtin(position) position: vec4f };
|
||||||
|
struct PaintSettings { transform: mat4x4f, options: vec4f, color: vec4f };
|
||||||
|
|
||||||
@group(0) @binding(0) var<uniform> uViewMat : 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(1) @binding(1) var<uniform> uBlendSettings : vec4f;
|
|
||||||
@group(2) @binding(0) var<uniform> uSolidColor : vec4f;
|
|
||||||
|
|
||||||
@vertex
|
@vertex
|
||||||
fn vs_main(in: VertexInput) -> VertexOutput {
|
fn vs_main(in: VertexInput) -> VertexOutput {
|
||||||
var out: 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;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@fragment
|
@fragment
|
||||||
fn fs_main(in: VertexOutput) -> @location(0) vec4f {
|
fn fs_main(in: VertexOutput) -> @location(0) vec4f {
|
||||||
let Sc = uSolidColor;
|
let Sc = uPaintSettings.color;
|
||||||
let So = uBlendSettings.a;
|
let So = uPaintSettings.options.a;
|
||||||
return vec4f(Sc.rgb * Sc.a * So, Sc.a * So);
|
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"(
|
const char* cShaderSrc_Linear = R"(
|
||||||
struct VertexInput { @location(0) position: vec2f };
|
struct VertexInput { @location(0) position: vec2f };
|
||||||
struct VertexOutput { @builtin(position) position : vec4f, @location(0) vGradCoord : vec4f };
|
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
|
// uniforms
|
||||||
@group(0) @binding(0) var<uniform> uViewMat : 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(1) @binding(1) var<uniform> uBlendSettings : vec4f;
|
|
||||||
@group(2) @binding(0) var uSamplerGrad : sampler;
|
@group(2) @binding(0) var uSamplerGrad : sampler;
|
||||||
@group(2) @binding(1) var uTextureGrad : texture_2d<f32>;
|
@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
|
@vertex
|
||||||
fn vs_main(in: VertexInput) -> VertexOutput {
|
fn vs_main(in: VertexInput) -> VertexOutput {
|
||||||
var out: 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.vGradCoord = uTransformGrad * vec4f(in.position.xy, 0.0, 1.0);
|
out.vGradCoord = uPaintSettings.gradient.transform * vec4f(in.position.xy, 0.0, 1.0);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@fragment
|
@fragment
|
||||||
fn fs_main(in: VertexOutput) -> @location(0) vec4f {
|
fn fs_main(in: VertexOutput) -> @location(0) vec4f {
|
||||||
let pos = in.vGradCoord.xy;
|
let pos = in.vGradCoord.xy;
|
||||||
let st = uSettingGrad.settings.xy;
|
let st = uPaintSettings.gradient.coords.xy;
|
||||||
let ed = uSettingGrad.settings.zw;
|
let ed = uPaintSettings.gradient.coords.zw;
|
||||||
let ba = ed - st;
|
let ba = ed - st;
|
||||||
let t = dot(pos - st, ba) / dot(ba, ba);
|
let t = dot(pos - st, ba) / dot(ba, ba);
|
||||||
let Sc = textureSample(uTextureGrad, uSamplerGrad, vec2f(t, 0.5));
|
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);
|
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"(
|
const char* cShaderSrc_Radial = R"(
|
||||||
struct VertexInput { @location(0) position: vec2f };
|
struct VertexInput { @location(0) position: vec2f };
|
||||||
struct VertexOutput { @builtin(position) position : vec4f, @location(0) vGradCoord : vec4f };
|
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(0) @binding(0) var<uniform> uViewMat : mat4x4f;
|
||||||
@group(1) @binding(0) var<uniform> uModelMat : mat4x4f;
|
@group(1) @binding(0) var<uniform> uPaintSettings : PaintSettings;
|
||||||
@group(1) @binding(1) var<uniform> uBlendSettings : vec4f;
|
|
||||||
@group(2) @binding(0) var uSamplerGrad : sampler;
|
@group(2) @binding(0) var uSamplerGrad : sampler;
|
||||||
@group(2) @binding(1) var uTextureGrad : texture_2d<f32>;
|
@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
|
@vertex
|
||||||
fn vs_main(in: VertexInput) -> VertexOutput {
|
fn vs_main(in: VertexInput) -> VertexOutput {
|
||||||
var out: 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.vGradCoord = uTransformGrad * vec4f(in.position.xy, 0.0, 1.0);
|
out.vGradCoord = uPaintSettings.gradient.transform * vec4f(in.position.xy, 0.0, 1.0);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@fragment
|
@fragment
|
||||||
fn fs_main(in: VertexOutput) -> @location(0) vec4f {
|
fn fs_main(in: VertexOutput) -> @location(0) vec4f {
|
||||||
// orignal data
|
// orignal data
|
||||||
let d0 = in.vGradCoord.xy - uSettingGrad.settings.xy;
|
let d0 = in.vGradCoord.xy - uPaintSettings.gradient.coords.xy;
|
||||||
let d1 = uSettingGrad.settings.xy - uSettingGrad.focal.xy;
|
let d1 = uPaintSettings.gradient.coords.xy - uPaintSettings.gradient.focal.xy;
|
||||||
let r0 = uSettingGrad.settings.z;
|
let r0 = uPaintSettings.gradient.coords.z;
|
||||||
let rd = uSettingGrad.focal.z - uSettingGrad.settings.z;
|
let rd = uPaintSettings.gradient.focal.z - uPaintSettings.gradient.coords.z;
|
||||||
let a = 1.0*dot(d1, d1) - 1.0*rd*rd;
|
let a = 1.0*dot(d1, d1) - 1.0*rd*rd;
|
||||||
let b = 2.0*dot(d0, d1) - 2.0*r0*rd;
|
let b = 2.0*dot(d0, d1) - 2.0*r0*rd;
|
||||||
let c = 1.0*dot(d0, d0) - 1.0*r0*r0;
|
let c = 1.0*dot(d0, d0) - 1.0*r0*r0;
|
||||||
let t = (-b + sqrt(b*b - 4*a*c))/(2*a);
|
let t = (-b + sqrt(b*b - 4*a*c))/(2*a);
|
||||||
let Sc = textureSample(uTextureGrad, uSamplerGrad, vec2f(1.0 - t, 0.5));
|
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);
|
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"(
|
const char* cShaderSrc_Image = R"(
|
||||||
struct VertexInput { @location(0) position: vec2f, @location(1) texCoord: vec2f };
|
struct VertexInput { @location(0) position: vec2f, @location(1) texCoord: vec2f };
|
||||||
struct VertexOutput { @builtin(position) position: vec4f, @location(0) vTexCoord: 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(0) @binding(0) var<uniform> uViewMat : mat4x4f;
|
||||||
@group(1) @binding(0) var<uniform> uModelMat : mat4x4f;
|
@group(1) @binding(0) var<uniform> uPaintSettings : PaintSettings;
|
||||||
@group(1) @binding(1) var<uniform> uBlendSettings : vec4f;
|
|
||||||
@group(2) @binding(0) var uSampler : sampler;
|
@group(2) @binding(0) var uSampler : sampler;
|
||||||
@group(2) @binding(1) var uTextureView : texture_2d<f32>;
|
@group(2) @binding(1) var uTextureView : texture_2d<f32>;
|
||||||
|
|
||||||
@vertex
|
@vertex
|
||||||
fn vs_main(in: VertexInput) -> VertexOutput {
|
fn vs_main(in: VertexInput) -> VertexOutput {
|
||||||
var out: 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;
|
out.vTexCoord = in.texCoord;
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
@ -209,7 +204,7 @@ fn vs_main(in: VertexInput) -> VertexOutput {
|
||||||
@fragment
|
@fragment
|
||||||
fn fs_main(in: VertexOutput) -> @location(0) vec4f {
|
fn fs_main(in: VertexOutput) -> @location(0) vec4f {
|
||||||
var Sc: vec4f = textureSample(uTextureView, uSampler, in.vTexCoord.xy);
|
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);
|
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"(
|
const char* cShaderSrc_Solid_Blend = R"(
|
||||||
struct VertexInput { @location(0) position: vec2f };
|
struct VertexInput { @location(0) position: vec2f };
|
||||||
struct VertexOutput { @builtin(position) position: vec4f, @location(1) vScrCoord: 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(0) @binding(0) var<uniform> uViewMat : mat4x4f;
|
||||||
@group(1) @binding(0) var<uniform> uModelMat : mat4x4f;
|
@group(1) @binding(0) var<uniform> uPaintSettings : PaintSettings;
|
||||||
@group(1) @binding(1) var<uniform> uBlendSettings : vec4f;
|
// @group(2) - empty
|
||||||
@group(2) @binding(0) var<uniform> uSolidColor : vec4f;
|
|
||||||
@group(3) @binding(0) var uSamplerDst : sampler;
|
@group(3) @binding(0) var uSamplerDst : sampler;
|
||||||
@group(3) @binding(1) var uTextureDst : texture_2d<f32>;
|
@group(3) @binding(1) var uTextureDst : texture_2d<f32>;
|
||||||
|
|
||||||
@vertex
|
@vertex
|
||||||
fn vs_main(in: VertexInput) -> VertexOutput {
|
fn vs_main(in: VertexInput) -> VertexOutput {
|
||||||
var out: 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.position = pos;
|
||||||
out.vScrCoord = vec2f(0.5 + pos.x * 0.5, 0.5 - pos.y * 0.5);
|
out.vScrCoord = vec2f(0.5 + pos.x * 0.5, 0.5 - pos.y * 0.5);
|
||||||
return out;
|
return out;
|
||||||
|
@ -268,13 +263,13 @@ fn vs_main(in: VertexInput) -> VertexOutput {
|
||||||
struct FragData { Sc: vec3f, Sa: f32, So: f32, Dc: vec3f, Da: f32 };
|
struct FragData { Sc: vec3f, Sa: f32, So: f32, Dc: vec3f, Da: f32 };
|
||||||
fn getFragData(in: VertexOutput) -> FragData {
|
fn getFragData(in: VertexOutput) -> FragData {
|
||||||
// get source data
|
// get source data
|
||||||
let colorSrc = uSolidColor;
|
let colorSrc = uPaintSettings.color;
|
||||||
let colorDst = textureSample(uTextureDst, uSamplerDst, in.vScrCoord.xy);
|
let colorDst = textureSample(uTextureDst, uSamplerDst, in.vScrCoord.xy);
|
||||||
// fill fragment data
|
// fill fragment data
|
||||||
var data: FragData;
|
var data: FragData;
|
||||||
data.Sc = colorSrc.rgb;
|
data.Sc = colorSrc.rgb;
|
||||||
data.Sa = colorSrc.a;
|
data.Sa = colorSrc.a;
|
||||||
data.So = uBlendSettings.a;
|
data.So = uPaintSettings.options.a;
|
||||||
data.Dc = colorDst.rgb;
|
data.Dc = colorDst.rgb;
|
||||||
data.Da = colorDst.a;
|
data.Da = colorDst.a;
|
||||||
data.Sc = data.Sa * data.So * data.Sc;
|
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"(
|
const char* cShaderSrc_Linear_Blend = R"(
|
||||||
struct VertexInput { @location(0) position: vec2f };
|
struct VertexInput { @location(0) position: vec2f };
|
||||||
struct VertexOutput { @builtin(position) position: vec4f, @location(0) vGradCoord : vec4f, @location(1) vScrCoord: 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(0) @binding(0) var<uniform> uViewMat : mat4x4f;
|
||||||
@group(1) @binding(0) var<uniform> uModelMat : mat4x4f;
|
@group(1) @binding(0) var<uniform> uPaintSettings : PaintSettings;
|
||||||
@group(1) @binding(1) var<uniform> uBlendSettings : vec4f;
|
|
||||||
@group(2) @binding(0) var uSamplerGrad : sampler;
|
@group(2) @binding(0) var uSamplerGrad : sampler;
|
||||||
@group(2) @binding(1) var uTextureGrad : texture_2d<f32>;
|
@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(0) var uSamplerDst : sampler;
|
||||||
@group(3) @binding(1) var uTextureDst : texture_2d<f32>;
|
@group(3) @binding(1) var uTextureDst : texture_2d<f32>;
|
||||||
|
|
||||||
@vertex
|
@vertex
|
||||||
fn vs_main(in: VertexInput) -> VertexOutput {
|
fn vs_main(in: VertexInput) -> VertexOutput {
|
||||||
var out: 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.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);
|
out.vScrCoord = vec2f(0.5 + pos.x * 0.5, 0.5 - pos.y * 0.5);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
@ -314,8 +307,8 @@ struct FragData { Sc: vec3f, Sa: f32, So: f32, Dc: vec3f, Da: f32 };
|
||||||
fn getFragData(in: VertexOutput) -> FragData {
|
fn getFragData(in: VertexOutput) -> FragData {
|
||||||
// get source data
|
// get source data
|
||||||
let pos = in.vGradCoord.xy;
|
let pos = in.vGradCoord.xy;
|
||||||
let st = uSettingGrad.xy;
|
let st = uPaintSettings.gradient.coords.xy;
|
||||||
let ed = uSettingGrad.zw;
|
let ed = uPaintSettings.gradient.coords.zw;
|
||||||
let ba = ed - st;
|
let ba = ed - st;
|
||||||
let t = dot(pos - st, ba) / dot(ba, ba);
|
let t = dot(pos - st, ba) / dot(ba, ba);
|
||||||
let colorSrc = textureSample(uTextureGrad, uSamplerGrad, vec2f(t, 0.5));
|
let colorSrc = textureSample(uTextureGrad, uSamplerGrad, vec2f(t, 0.5));
|
||||||
|
@ -324,7 +317,7 @@ fn getFragData(in: VertexOutput) -> FragData {
|
||||||
var data: FragData;
|
var data: FragData;
|
||||||
data.Sc = colorSrc.rgb;
|
data.Sc = colorSrc.rgb;
|
||||||
data.Sa = colorSrc.a;
|
data.Sa = colorSrc.a;
|
||||||
data.So = uBlendSettings.a;
|
data.So = uPaintSettings.options.a;
|
||||||
data.Dc = colorDst.rgb;
|
data.Dc = colorDst.rgb;
|
||||||
data.Da = colorDst.a;
|
data.Da = colorDst.a;
|
||||||
data.Sc = mix(data.Dc, data.Sc, data.Sa * data.So);
|
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"(
|
const char* cShaderSrc_Radial_Blend = R"(
|
||||||
struct VertexInput { @location(0) position: vec2f };
|
struct VertexInput { @location(0) position: vec2f };
|
||||||
struct VertexOutput { @builtin(position) position: vec4f, @location(0) vGradCoord : vec4f, @location(1) vScrCoord: 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(0) @binding(0) var<uniform> uViewMat : mat4x4f;
|
||||||
@group(1) @binding(0) var<uniform> uModelMat : mat4x4f;
|
@group(1) @binding(0) var<uniform> uPaintSettings : PaintSettings;
|
||||||
@group(1) @binding(1) var<uniform> uBlendSettings : vec4f;
|
|
||||||
@group(2) @binding(0) var uSamplerGrad : sampler;
|
@group(2) @binding(0) var uSamplerGrad : sampler;
|
||||||
@group(2) @binding(1) var uTextureGrad : texture_2d<f32>;
|
@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(0) var uSamplerDst : sampler;
|
||||||
@group(3) @binding(1) var uTextureDst : texture_2d<f32>;
|
@group(3) @binding(1) var uTextureDst : texture_2d<f32>;
|
||||||
|
|
||||||
@vertex
|
@vertex
|
||||||
fn vs_main(in: VertexInput) -> VertexOutput {
|
fn vs_main(in: VertexInput) -> VertexOutput {
|
||||||
var out: 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.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);
|
out.vScrCoord = vec2f(0.5 + pos.x * 0.5, 0.5 - pos.y * 0.5);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FragData { Sc: vec3f, Sa: f32, So: f32, Dc: vec3f, Da: f32 };
|
struct FragData { Sc: vec3f, Sa: f32, So: f32, Dc: vec3f, Da: f32 };
|
||||||
fn getFragData(in: VertexOutput) -> FragData {
|
fn getFragData(in: VertexOutput) -> FragData {
|
||||||
let d0 = in.vGradCoord.xy - uSettingGrad.settings.xy;
|
let d0 = in.vGradCoord.xy - uPaintSettings.gradient.coords.xy;
|
||||||
let d1 = uSettingGrad.settings.xy - uSettingGrad.focal.xy;
|
let d1 = uPaintSettings.gradient.coords.xy - uPaintSettings.gradient.focal.xy;
|
||||||
let r0 = uSettingGrad.settings.z;
|
let r0 = uPaintSettings.gradient.coords.z;
|
||||||
let rd = uSettingGrad.focal.z - uSettingGrad.settings.z;
|
let rd = uPaintSettings.gradient.focal.z - uPaintSettings.gradient.coords.z;
|
||||||
let a = 1.0*dot(d1, d1) - 1.0*rd*rd;
|
let a = 1.0*dot(d1, d1) - 1.0*rd*rd;
|
||||||
let b = 2.0*dot(d0, d1) - 2.0*r0*rd;
|
let b = 2.0*dot(d0, d1) - 2.0*r0*rd;
|
||||||
let c = 1.0*dot(d0, d0) - 1.0*r0*r0;
|
let c = 1.0*dot(d0, d0) - 1.0*r0*r0;
|
||||||
|
@ -376,7 +367,7 @@ fn getFragData(in: VertexOutput) -> FragData {
|
||||||
var data: FragData;
|
var data: FragData;
|
||||||
data.Sc = colorSrc.rgb;
|
data.Sc = colorSrc.rgb;
|
||||||
data.Sa = colorSrc.a;
|
data.Sa = colorSrc.a;
|
||||||
data.So = uBlendSettings.a;
|
data.So = uPaintSettings.options.a;
|
||||||
data.Dc = colorDst.rgb;
|
data.Dc = colorDst.rgb;
|
||||||
data.Da = colorDst.a;
|
data.Da = colorDst.a;
|
||||||
data.Sc = mix(data.Dc, data.Sc, data.Sa * data.So);
|
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"(
|
const char* cShaderSrc_Image_Blend = R"(
|
||||||
struct VertexInput { @location(0) position: vec2f, @location(1) texCoord: vec2f };
|
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 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(0) @binding(0) var<uniform> uViewMat : mat4x4f;
|
||||||
@group(1) @binding(0) var<uniform> uModelMat : mat4x4f;
|
@group(1) @binding(0) var<uniform> uPaintSettings : PaintSettings;
|
||||||
@group(1) @binding(1) var<uniform> uBlendSettings : vec4f;
|
@group(2) @binding(0) var uSamplerSrc : sampler;
|
||||||
@group(2) @binding(0) var uSamplerSrc : sampler;
|
|
||||||
@group(2) @binding(1) var uTextureSrc : texture_2d<f32>;
|
@group(2) @binding(1) var uTextureSrc : texture_2d<f32>;
|
||||||
@group(3) @binding(0) var uSamplerDst : sampler;
|
@group(3) @binding(0) var uSamplerDst : sampler;
|
||||||
@group(3) @binding(1) var uTextureDst : texture_2d<f32>;
|
@group(3) @binding(1) var uTextureDst : texture_2d<f32>;
|
||||||
|
@ -402,7 +393,7 @@ struct VertexOutput { @builtin(position) position: vec4f, @location(0) vTexCoord
|
||||||
@vertex
|
@vertex
|
||||||
fn vs_main(in: VertexInput) -> VertexOutput {
|
fn vs_main(in: VertexInput) -> VertexOutput {
|
||||||
var out: 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.position = pos;
|
||||||
out.vTexCoord = in.texCoord;
|
out.vTexCoord = in.texCoord;
|
||||||
out.vScrCoord = vec2f(0.5 + pos.x * 0.5, 0.5 - pos.y * 0.5);
|
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;
|
var data: FragData;
|
||||||
data.Sc = colorSrc.rgb;
|
data.Sc = colorSrc.rgb;
|
||||||
data.Sa = colorSrc.a;
|
data.Sa = colorSrc.a;
|
||||||
data.So = uBlendSettings.a;
|
data.So = uPaintSettings.options.a;
|
||||||
data.Dc = colorDst.rgb;
|
data.Dc = colorDst.rgb;
|
||||||
data.Da = colorDst.a;
|
data.Da = colorDst.a;
|
||||||
data.Sc = data.Sc * data.So;
|
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;
|
const Fill::ColorStop* stops = nullptr;
|
||||||
auto stopCnt = linearGradient->colorStops(&stops);
|
auto stopCnt = fill->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)
|
|
||||||
{
|
|
||||||
if (stopCnt == 0) return;
|
if (stopCnt == 0) return;
|
||||||
|
|
||||||
static Array<Fill::ColorStop> sstops(stopCnt);
|
static Array<Fill::ColorStop> sstops(stopCnt);
|
||||||
sstops.clear();
|
sstops.clear();
|
||||||
sstops.push(stops[0]);
|
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_s = 0;
|
||||||
uint32_t range_e = uint32_t(sstops[0].offset * (WG_TEXTURE_GRADIENT_SIZE-1));
|
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++) {
|
for (uint32_t ti = range_s; (ti < range_e) && (ti < WG_TEXTURE_GRADIENT_SIZE); ti++) {
|
||||||
texData[ti * 4 + 0] = sstops[0].r;
|
data[ti * 4 + 0] = sstops[0].r;
|
||||||
texData[ti * 4 + 1] = sstops[0].g;
|
data[ti * 4 + 1] = sstops[0].g;
|
||||||
texData[ti * 4 + 2] = sstops[0].b;
|
data[ti * 4 + 2] = sstops[0].b;
|
||||||
texData[ti * 4 + 3] = sstops[0].a;
|
data[ti * 4 + 3] = sstops[0].a;
|
||||||
}
|
}
|
||||||
// body
|
// body
|
||||||
for (uint32_t di = 1; di < sstops.count; di++) {
|
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);
|
float delta = 1.0f/(range_e - range_s);
|
||||||
for (uint32_t ti = range_s; (ti < range_e) && (ti < WG_TEXTURE_GRADIENT_SIZE); ti++) {
|
for (uint32_t ti = range_s; (ti < range_e) && (ti < WG_TEXTURE_GRADIENT_SIZE); ti++) {
|
||||||
float t = (ti - range_s) * delta;
|
float t = (ti - range_s) * delta;
|
||||||
texData[ti * 4 + 0] = tvg::lerp(sstops[di-1].r, sstops[di].r, t);
|
data[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);
|
data[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);
|
data[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 + 3] = tvg::lerp(sstops[di-1].a, sstops[di].a, t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// tail
|
// 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_s = uint32_t(colorStopLast.offset * (WG_TEXTURE_GRADIENT_SIZE-1));
|
||||||
range_e = WG_TEXTURE_GRADIENT_SIZE;
|
range_e = WG_TEXTURE_GRADIENT_SIZE;
|
||||||
for (uint32_t ti = range_s; ti < range_e; ti++) {
|
for (uint32_t ti = range_s; ti < range_e; ti++) {
|
||||||
texData[ti * 4 + 0] = colorStopLast.r;
|
data[ti * 4 + 0] = colorStopLast.r;
|
||||||
texData[ti * 4 + 1] = colorStopLast.g;
|
data[ti * 4 + 1] = colorStopLast.g;
|
||||||
texData[ti * 4 + 2] = colorStopLast.b;
|
data[ti * 4 + 2] = colorStopLast.b;
|
||||||
texData[ti * 4 + 3] = colorStopLast.a;
|
data[ti * 4 + 3] = colorStopLast.a;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,16 +55,44 @@ struct WgShaderTypeVec4f
|
||||||
void update(const RenderRegion& r);
|
void update(const RenderRegion& r);
|
||||||
};
|
};
|
||||||
|
|
||||||
// sampler, texture, vec4f
|
// WGSL: struct GradSettings { transform: mat4x4f, coords: vec4f, focal: vec4f };
|
||||||
#define WG_TEXTURE_GRADIENT_SIZE 512
|
struct WgShaderTypeGradSettings
|
||||||
struct WgShaderTypeGradient
|
|
||||||
{
|
{
|
||||||
float settings[4+4]{}; // WGSL: struct GradSettings { settings: vec4f, focal: vec4f; transform: mat4f };
|
// gradient transform matrix
|
||||||
uint8_t texData[WG_TEXTURE_GRADIENT_SIZE * 4];
|
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);
|
// WGSL: struct PaintSettings { transform: mat4x4f, options: vec4f, color: vec4f, gradient: GradSettings };
|
||||||
void update(const RadialGradient* radialGradient);
|
struct WgShaderTypePaintSettings
|
||||||
void updateTexData(const Fill::ColorStop* stops, uint32_t stopCnt);
|
{
|
||||||
|
// 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
|
// gaussian params: sigma, scale, extend
|
||||||
|
|
Loading…
Add table
Reference in a new issue