wg_engine: wrong gradient transformation fixed

issue: https://github.com/thorvg/thorvg/issues/2620
This commit is contained in:
Sergii Liebodkin 2024-09-13 07:36:21 +03:00 committed by GitHub
parent 91a538d1f2
commit 7a6a89cf26
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 49 additions and 10 deletions

View file

@ -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) WGPUBindGroup WgBindGroupLayouts::createBindGroupStrorage1WO(WGPUTextureView texView)
{ {
const WGPUBindGroupEntry bindGroupEntrys[] = { const WGPUBindGroupEntry bindGroupEntrys[] = {
@ -164,6 +177,18 @@ void WgBindGroupLayouts::initialize(WgContext& context)
assert(layoutTexSampledBuff1Un); 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 { // bind group layout tex storage 1 WO
const WGPUBindGroupLayoutEntry bindGroupLayoutEntries[] { const WGPUBindGroupLayoutEntry bindGroupLayoutEntries[] {
{ .binding = 0, .visibility = visibility_frag, .storageTexture = storageTextureWO } { .binding = 0, .visibility = visibility_frag, .storageTexture = storageTextureWO }

View file

@ -31,6 +31,7 @@ private:
public: public:
WGPUBindGroupLayout layoutTexSampled{}; WGPUBindGroupLayout layoutTexSampled{};
WGPUBindGroupLayout layoutTexSampledBuff1Un{}; WGPUBindGroupLayout layoutTexSampledBuff1Un{};
WGPUBindGroupLayout layoutTexSampledBuff2Un{};
WGPUBindGroupLayout layoutTexStrorage1WO{}; WGPUBindGroupLayout layoutTexStrorage1WO{};
WGPUBindGroupLayout layoutTexStrorage1RO{}; WGPUBindGroupLayout layoutTexStrorage1RO{};
WGPUBindGroupLayout layoutTexStrorage2RO{}; WGPUBindGroupLayout layoutTexStrorage2RO{};
@ -41,6 +42,7 @@ public:
public: public:
WGPUBindGroup createBindGroupTexSampled(WGPUSampler sampler, WGPUTextureView texView); WGPUBindGroup createBindGroupTexSampled(WGPUSampler sampler, WGPUTextureView texView);
WGPUBindGroup createBindGroupTexSampledBuff1Un(WGPUSampler sampler, WGPUTextureView texView, WGPUBuffer buff); WGPUBindGroup createBindGroupTexSampledBuff1Un(WGPUSampler sampler, WGPUTextureView texView, WGPUBuffer buff);
WGPUBindGroup createBindGroupTexSampledBuff2Un(WGPUSampler sampler, WGPUTextureView texView, WGPUBuffer buff0, WGPUBuffer buff1);
WGPUBindGroup createBindGroupStrorage1WO(WGPUTextureView texView); WGPUBindGroup createBindGroupStrorage1WO(WGPUTextureView texView);
WGPUBindGroup createBindGroupStrorage1RO(WGPUTextureView texView); WGPUBindGroup createBindGroupStrorage1RO(WGPUTextureView texView);
WGPUBindGroup createBindGroupStrorage2RO(WGPUTextureView texView0, WGPUTextureView texView1); WGPUBindGroup createBindGroupStrorage2RO(WGPUTextureView texView0, WGPUTextureView texView1);

View file

@ -176,7 +176,7 @@ void WgPipelines::initialize(WgContext& context)
const WGPUBindGroupLayout bindGroupLayoutsGradient[] = { const WGPUBindGroupLayout bindGroupLayoutsGradient[] = {
layouts.layoutBuffer1Un, layouts.layoutBuffer1Un,
layouts.layoutBuffer2Un, layouts.layoutBuffer2Un,
layouts.layoutTexSampledBuff1Un layouts.layoutTexSampledBuff2Un
}; };
const WGPUBindGroupLayout bindGroupLayoutsImage[] = { const WGPUBindGroupLayout bindGroupLayoutsImage[] = {
layouts.layoutBuffer1Un, layouts.layoutBuffer1Un,

View file

@ -212,6 +212,13 @@ void WgRenderSettings::update(WgContext& context, const Fill* fill, const uint8_
// setup fill properties // setup fill properties
if ((flags & (RenderUpdateFlag::Gradient)) && fill) { if ((flags & (RenderUpdateFlag::Gradient)) && fill) {
rasterType = WgRenderRasterType::Gradient; 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; WgShaderTypeGradient gradient;
if (fill->type() == Type::LinearGradient) { if (fill->type() == Type::LinearGradient) {
gradient.update((LinearGradient*)fill); gradient.update((LinearGradient*)fill);
@ -222,8 +229,9 @@ void WgRenderSettings::update(WgContext& context, const Fill* fill, const uint8_
} }
// update gpu assets // update gpu assets
bool bufferGradientSettingsChanged = context.allocateBufferUniform(bufferGroupGradient, &gradient.settings, sizeof(gradient.settings)); 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); bool textureGradientChanged = context.allocateTexture(texGradient, WG_TEXTURE_GRADIENT_SIZE, 1, WGPUTextureFormat_RGBA8Unorm, gradient.texData);
if (bufferGradientSettingsChanged || textureGradientChanged) { if (bufferGradientSettingsChanged || textureGradientChanged || bufferGradientTransformChanged) {
// update texture view // update texture view
context.releaseTextureView(texViewGradient); context.releaseTextureView(texViewGradient);
texViewGradient = context.createTextureView(texGradient); 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; if (fill->spread() == FillSpread::Repeat) sampler = context.samplerLinearRepeat;
// update bind group // update bind group
context.pipelines->layouts.releaseBindGroup(bindGroupGradient); context.pipelines->layouts.releaseBindGroup(bindGroupGradient);
bindGroupGradient = context.pipelines->layouts.createBindGroupTexSampledBuff1Un( bindGroupGradient = context.pipelines->layouts.createBindGroupTexSampledBuff2Un(
sampler, texViewGradient, bufferGroupGradient); sampler, texViewGradient, bufferGroupGradient, bufferGroupTransfromGrad);
} }
skip = false; skip = false;
} else if ((flags & (RenderUpdateFlag::Color)) && !fill) { } else if ((flags & (RenderUpdateFlag::Color)) && !fill) {
@ -256,6 +264,7 @@ void WgRenderSettings::release(WgContext& context)
context.pipelines->layouts.releaseBindGroup(bindGroupGradient); context.pipelines->layouts.releaseBindGroup(bindGroupGradient);
context.releaseBuffer(bufferGroupSolid); context.releaseBuffer(bufferGroupSolid);
context.releaseBuffer(bufferGroupGradient); context.releaseBuffer(bufferGroupGradient);
context.releaseBuffer(bufferGroupTransfromGrad);
context.releaseTexture(texGradient); context.releaseTexture(texGradient);
context.releaseTextureView(texViewGradient); context.releaseTextureView(texViewGradient);
}; };

View file

@ -82,6 +82,7 @@ struct WgRenderSettings
WGPUTexture texGradient{}; WGPUTexture texGradient{};
WGPUTextureView texViewGradient{}; WGPUTextureView texViewGradient{};
WGPUBuffer bufferGroupGradient{}; WGPUBuffer bufferGroupGradient{};
WGPUBuffer bufferGroupTransfromGrad{};
WGPUBindGroup bindGroupGradient{}; WGPUBindGroup bindGroupGradient{};
WgRenderSettingsType fillType{}; WgRenderSettingsType fillType{};
WgRenderRasterType rasterType{}; WgRenderRasterType rasterType{};

View file

@ -84,7 +84,7 @@ 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) vScreenCoord : vec2f }; struct VertexOutput { @builtin(position) position : vec4f, @location(0) vScreenCoord : vec4f };
// uniforms // uniforms
@group(0) @binding(0) var<uniform> uViewMat : mat4x4f; @group(0) @binding(0) var<uniform> 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(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(2) var<uniform> uSettingGrad : vec4f;
@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 * 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; return out;
} }
@fragment @fragment
fn fs_main(in: VertexOutput) -> @location(0) vec4f { fn fs_main(in: VertexOutput) -> @location(0) vec4f {
let pos = in.vScreenCoord; let pos = in.vScreenCoord.xy;
let st = uSettingGrad.xy; let st = uSettingGrad.xy;
let ed = uSettingGrad.zw; let ed = uSettingGrad.zw;
let ba = ed - st; let ba = ed - st;
@ -121,7 +122,7 @@ 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) vScreenCoord : vec2f }; struct VertexOutput { @builtin(position) position : vec4f, @location(0) vScreenCoord : 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> 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(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(2) var<uniform> uSettingGrad : vec4f;
@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 * 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; return out;
} }
@fragment @fragment
fn fs_main(in: VertexOutput) -> @location(0) vec4f { 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 Sc = textureSample(uTextureGrad, uSamplerGrad, vec2f(t, 0.5));
let So = uBlendSettings.a; let So = uBlendSettings.a;
return vec4f(Sc.rgb * Sc.a * So, Sc.a * So); return vec4f(Sc.rgb * Sc.a * So, Sc.a * So);