From 7a6a89cf26139afaf7e33dc596f457db2b63c36a Mon Sep 17 00:00:00 2001 From: Sergii Liebodkin Date: Fri, 13 Sep 2024 07:36:21 +0300 Subject: [PATCH] wg_engine: wrong gradient transformation fixed issue: https://github.com/thorvg/thorvg/issues/2620 --- src/renderer/wg_engine/tvgWgBindGroups.cpp | 25 ++++++++++++++++++++++ src/renderer/wg_engine/tvgWgBindGroups.h | 2 ++ src/renderer/wg_engine/tvgWgPipelines.cpp | 2 +- src/renderer/wg_engine/tvgWgRenderData.cpp | 15 ++++++++++--- src/renderer/wg_engine/tvgWgRenderData.h | 1 + src/renderer/wg_engine/tvgWgShaderSrc.cpp | 14 ++++++------ 6 files changed, 49 insertions(+), 10 deletions(-) diff --git a/src/renderer/wg_engine/tvgWgBindGroups.cpp b/src/renderer/wg_engine/tvgWgBindGroups.cpp index 58f8061c..f3373fdb 100755 --- a/src/renderer/wg_engine/tvgWgBindGroups.cpp +++ b/src/renderer/wg_engine/tvgWgBindGroups.cpp @@ -45,6 +45,19 @@ WGPUBindGroup WgBindGroupLayouts::createBindGroupTexSampledBuff1Un(WGPUSampler s } +WGPUBindGroup WgBindGroupLayouts::createBindGroupTexSampledBuff2Un(WGPUSampler sampler, WGPUTextureView texView, WGPUBuffer buff0, WGPUBuffer buff1) +{ + const WGPUBindGroupEntry bindGroupEntrys[] = { + { .binding = 0, .sampler = sampler }, + { .binding = 1, .textureView = texView }, + { .binding = 2, .buffer = buff0, .size = wgpuBufferGetSize(buff0) }, + { .binding = 3, .buffer = buff1, .size = wgpuBufferGetSize(buff1) } + }; + const WGPUBindGroupDescriptor bindGroupDesc { .layout = layoutTexSampledBuff2Un, .entryCount = 4, .entries = bindGroupEntrys }; + return wgpuDeviceCreateBindGroup(device, &bindGroupDesc); +} + + WGPUBindGroup WgBindGroupLayouts::createBindGroupStrorage1WO(WGPUTextureView texView) { const WGPUBindGroupEntry bindGroupEntrys[] = { @@ -164,6 +177,18 @@ void WgBindGroupLayouts::initialize(WgContext& context) assert(layoutTexSampledBuff1Un); } + { // bind group layout tex sampled with buffer uniforms + const WGPUBindGroupLayoutEntry bindGroupLayoutEntries[] { + { .binding = 0, .visibility = visibility_frag, .sampler = sampler }, + { .binding = 1, .visibility = visibility_frag, .texture = texture }, + { .binding = 2, .visibility = visibility_vert, .buffer = bufferUniform }, + { .binding = 3, .visibility = visibility_vert, .buffer = bufferUniform } + }; + const WGPUBindGroupLayoutDescriptor bindGroupLayoutDesc { .entryCount = 4, .entries = bindGroupLayoutEntries }; + layoutTexSampledBuff2Un = wgpuDeviceCreateBindGroupLayout(device, &bindGroupLayoutDesc); + assert(layoutTexSampledBuff1Un); + } + { // bind group layout tex storage 1 WO const WGPUBindGroupLayoutEntry bindGroupLayoutEntries[] { { .binding = 0, .visibility = visibility_frag, .storageTexture = storageTextureWO } diff --git a/src/renderer/wg_engine/tvgWgBindGroups.h b/src/renderer/wg_engine/tvgWgBindGroups.h index 82a31eff..ee587b60 100755 --- a/src/renderer/wg_engine/tvgWgBindGroups.h +++ b/src/renderer/wg_engine/tvgWgBindGroups.h @@ -31,6 +31,7 @@ private: public: WGPUBindGroupLayout layoutTexSampled{}; WGPUBindGroupLayout layoutTexSampledBuff1Un{}; + WGPUBindGroupLayout layoutTexSampledBuff2Un{}; WGPUBindGroupLayout layoutTexStrorage1WO{}; WGPUBindGroupLayout layoutTexStrorage1RO{}; WGPUBindGroupLayout layoutTexStrorage2RO{}; @@ -41,6 +42,7 @@ public: public: WGPUBindGroup createBindGroupTexSampled(WGPUSampler sampler, WGPUTextureView texView); WGPUBindGroup createBindGroupTexSampledBuff1Un(WGPUSampler sampler, WGPUTextureView texView, WGPUBuffer buff); + WGPUBindGroup createBindGroupTexSampledBuff2Un(WGPUSampler sampler, WGPUTextureView texView, WGPUBuffer buff0, WGPUBuffer buff1); WGPUBindGroup createBindGroupStrorage1WO(WGPUTextureView texView); WGPUBindGroup createBindGroupStrorage1RO(WGPUTextureView texView); WGPUBindGroup createBindGroupStrorage2RO(WGPUTextureView texView0, WGPUTextureView texView1); diff --git a/src/renderer/wg_engine/tvgWgPipelines.cpp b/src/renderer/wg_engine/tvgWgPipelines.cpp index 061587b0..8924d048 100755 --- a/src/renderer/wg_engine/tvgWgPipelines.cpp +++ b/src/renderer/wg_engine/tvgWgPipelines.cpp @@ -176,7 +176,7 @@ void WgPipelines::initialize(WgContext& context) const WGPUBindGroupLayout bindGroupLayoutsGradient[] = { layouts.layoutBuffer1Un, layouts.layoutBuffer2Un, - layouts.layoutTexSampledBuff1Un + layouts.layoutTexSampledBuff2Un }; const WGPUBindGroupLayout bindGroupLayoutsImage[] = { layouts.layoutBuffer1Un, diff --git a/src/renderer/wg_engine/tvgWgRenderData.cpp b/src/renderer/wg_engine/tvgWgRenderData.cpp index 16840b63..5f058c03 100755 --- a/src/renderer/wg_engine/tvgWgRenderData.cpp +++ b/src/renderer/wg_engine/tvgWgRenderData.cpp @@ -212,6 +212,13 @@ void WgRenderSettings::update(WgContext& context, const Fill* fill, const uint8_ // setup fill properties if ((flags & (RenderUpdateFlag::Gradient)) && fill) { rasterType = WgRenderRasterType::Gradient; + // get gradient transfrom matrix + Matrix fillTransform = fill->transform(); + Matrix invFillTransform; + WgShaderTypeMat4x4f gradientTrans; // identity by default + if (inverse(&fillTransform, &invFillTransform)) + gradientTrans.update(invFillTransform); + // get gradient rasterisation settings WgShaderTypeGradient gradient; if (fill->type() == Type::LinearGradient) { gradient.update((LinearGradient*)fill); @@ -222,8 +229,9 @@ void WgRenderSettings::update(WgContext& context, const Fill* fill, const uint8_ } // 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) { + if (bufferGradientSettingsChanged || textureGradientChanged || bufferGradientTransformChanged) { // update texture view context.releaseTextureView(texViewGradient); texViewGradient = context.createTextureView(texGradient); @@ -233,8 +241,8 @@ void WgRenderSettings::update(WgContext& context, const Fill* fill, const uint8_ if (fill->spread() == FillSpread::Repeat) sampler = context.samplerLinearRepeat; // update bind group context.pipelines->layouts.releaseBindGroup(bindGroupGradient); - bindGroupGradient = context.pipelines->layouts.createBindGroupTexSampledBuff1Un( - sampler, texViewGradient, bufferGroupGradient); + bindGroupGradient = context.pipelines->layouts.createBindGroupTexSampledBuff2Un( + sampler, texViewGradient, bufferGroupGradient, bufferGroupTransfromGrad); } skip = false; } else if ((flags & (RenderUpdateFlag::Color)) && !fill) { @@ -256,6 +264,7 @@ void WgRenderSettings::release(WgContext& context) context.pipelines->layouts.releaseBindGroup(bindGroupGradient); context.releaseBuffer(bufferGroupSolid); context.releaseBuffer(bufferGroupGradient); + context.releaseBuffer(bufferGroupTransfromGrad); context.releaseTexture(texGradient); context.releaseTextureView(texViewGradient); }; diff --git a/src/renderer/wg_engine/tvgWgRenderData.h b/src/renderer/wg_engine/tvgWgRenderData.h index ed8afc1b..8a066b53 100755 --- a/src/renderer/wg_engine/tvgWgRenderData.h +++ b/src/renderer/wg_engine/tvgWgRenderData.h @@ -82,6 +82,7 @@ struct WgRenderSettings WGPUTexture texGradient{}; WGPUTextureView texViewGradient{}; WGPUBuffer bufferGroupGradient{}; + WGPUBuffer bufferGroupTransfromGrad{}; WGPUBindGroup bindGroupGradient{}; WgRenderSettingsType fillType{}; WgRenderRasterType rasterType{}; diff --git a/src/renderer/wg_engine/tvgWgShaderSrc.cpp b/src/renderer/wg_engine/tvgWgShaderSrc.cpp index 199aa1b6..219ecdeb 100755 --- a/src/renderer/wg_engine/tvgWgShaderSrc.cpp +++ b/src/renderer/wg_engine/tvgWgShaderSrc.cpp @@ -84,7 +84,7 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4f { const char* cShaderSrc_Linear = R"( struct VertexInput { @location(0) position: vec2f }; -struct VertexOutput { @builtin(position) position : vec4f, @location(0) vScreenCoord : vec2f }; +struct VertexOutput { @builtin(position) position : vec4f, @location(0) vScreenCoord : vec4f }; // uniforms @group(0) @binding(0) var uViewMat : mat4x4f; @@ -93,18 +93,19 @@ struct VertexOutput { @builtin(position) position : vec4f, @location(0) vScreenC @group(2) @binding(0) var uSamplerGrad : sampler; @group(2) @binding(1) var uTextureGrad : texture_2d; @group(2) @binding(2) var uSettingGrad : vec4f; +@group(2) @binding(3) var uTransformGrad : mat4x4f; @vertex fn vs_main(in: VertexInput) -> VertexOutput { var out: VertexOutput; out.position = uViewMat * uModelMat * vec4f(in.position.xy, 0.0, 1.0); - out.vScreenCoord = in.position.xy; + out.vScreenCoord = uTransformGrad * vec4f(in.position.xy, 0.0, 1.0); return out; } @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4f { - let pos = in.vScreenCoord; + let pos = in.vScreenCoord.xy; let st = uSettingGrad.xy; let ed = uSettingGrad.zw; let ba = ed - st; @@ -121,7 +122,7 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4f { const char* cShaderSrc_Radial = R"( struct VertexInput { @location(0) position: vec2f }; -struct VertexOutput { @builtin(position) position : vec4f, @location(0) vScreenCoord : vec2f }; +struct VertexOutput { @builtin(position) position : vec4f, @location(0) vScreenCoord : vec4f }; @group(0) @binding(0) var uViewMat : mat4x4f; @group(1) @binding(0) var uModelMat : mat4x4f; @@ -129,18 +130,19 @@ struct VertexOutput { @builtin(position) position : vec4f, @location(0) vScreenC @group(2) @binding(0) var uSamplerGrad : sampler; @group(2) @binding(1) var uTextureGrad : texture_2d; @group(2) @binding(2) var uSettingGrad : vec4f; +@group(2) @binding(3) var uTransformGrad : mat4x4f; @vertex fn vs_main(in: VertexInput) -> VertexOutput { var out: VertexOutput; out.position = uViewMat * uModelMat * vec4f(in.position.xy, 0.0, 1.0); - out.vScreenCoord = in.position.xy; + out.vScreenCoord = uTransformGrad * vec4f(in.position.xy, 0.0, 1.0); return out; } @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4f { - let t: f32 = distance(uSettingGrad.zw, in.vScreenCoord) / uSettingGrad.r; + let t: f32 = distance(uSettingGrad.zw, in.vScreenCoord.xy) / uSettingGrad.r; let Sc = textureSample(uTextureGrad, uSamplerGrad, vec2f(t, 0.5)); let So = uBlendSettings.a; return vec4f(Sc.rgb * Sc.a * So, Sc.a * So);