From cdab015e4485481aaa7a6a63412c715a4dffb925 Mon Sep 17 00:00:00 2001 From: Brian Salomon Date: Fri, 29 Jul 2022 12:55:47 -0400 Subject: [ganesh] Fix double application of local matrices to runtime shaders. Bug: skia:13598 Change-Id: Iddfb4f43940fd18a10dc7910f111e1f8f49e8e4c Reviewed-on: https://skia-review.googlesource.com/c/skia/+/563122 Commit-Queue: Brian Salomon Reviewed-by: Brian Osman Bug: 240718331 Test: I63f23f412d1b16643053dbcc041ca8f8c800f158 Change-Id: I6c660da30962c76462f70731d075762a9e16beed Merged-In: Ic90fdcfc89f653caca519ea5655848f309a51312 --- gm/runtimeshader.cpp | 47 ++++++++++++++++++++++++++++++++++++++++++++ src/core/SkRuntimeEffect.cpp | 5 ++++- 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/gm/runtimeshader.cpp b/gm/runtimeshader.cpp index 94b3e0d4c2..bd865ceabe 100644 --- a/gm/runtimeshader.cpp +++ b/gm/runtimeshader.cpp @@ -889,3 +889,50 @@ DEF_SIMPLE_GM(lit_shader_linear_rt, canvas, 512, 256) { // Now draw the offscreen surface back to our original canvas: canvas->drawImage(surface->makeImageSnapshot(), 0, 0); } + +// skbug.com/13598 GPU was double applying the local matrix. +DEF_SIMPLE_GM(local_matrix_shader_rt, canvas, 256, 256) { + SkString passthrough(R"( + uniform shader s; + half4 main(float2 p) { return s.eval(p); } + )"); + auto [rte, error] = SkRuntimeEffect::MakeForShader(passthrough, {}); + if (!rte) { + SkDebugf("%s\n", error.c_str()); + return; + } + + auto image = GetResourceAsImage("images/mandrill_128.png"); + auto imgShader = image->makeShader(SkSamplingOptions{}); + + auto r = SkRect::MakeWH(image->width(), image->height()); + + auto lm = SkMatrix::RotateDeg(90.f, {image->width()/2.f, image->height()/2.f}); + + SkPaint paint; + + // image + paint.setShader(imgShader); + canvas->drawRect(r, paint); + + // passthrough(image) + canvas->save(); + canvas->translate(image->width(), 0); + paint.setShader(rte->makeShader(nullptr, &imgShader, 1)); + canvas->drawRect(r, paint); + canvas->restore(); + + // localmatrix(image) + canvas->save(); + canvas->translate(0, image->height()); + paint.setShader(imgShader->makeWithLocalMatrix(lm)); + canvas->drawRect(r, paint); + canvas->restore(); + + // localmatrix(passthrough(image)) This was the bug. + canvas->save(); + canvas->translate(image->width(), image->height()); + paint.setShader(rte->makeShader(nullptr, &imgShader, 1)->makeWithLocalMatrix(lm)); + canvas->drawRect(r, paint); + canvas->restore(); +} diff --git a/src/core/SkRuntimeEffect.cpp b/src/core/SkRuntimeEffect.cpp index 3e5543cad1..1c08fb84d4 100644 --- a/src/core/SkRuntimeEffect.cpp +++ b/src/core/SkRuntimeEffect.cpp @@ -1133,13 +1133,16 @@ public: get_xformed_uniforms(fEffect.get(), fUniforms, args.fDstColorInfo->colorSpace()); SkASSERT(uniforms); + // We handle the pre-local matrix at this level so strip it out. + GrFPArgs fpArgs = args; + fpArgs.fPreLocalMatrix = nullptr; auto [success, fp] = make_effect_fp(fEffect, "runtime_shader", std::move(uniforms), /*inputFP=*/nullptr, /*destColorFP=*/nullptr, SkMakeSpan(fChildren), - args); + fpArgs); if (!success) { return nullptr; } -- cgit v1.2.3