From 07b639da6fb1e082dddd9118fe14c118fbdaeb2c Mon Sep 17 00:00:00 2001 From: Robert Phillips Date: Mon, 7 Feb 2022 10:24:16 -0500 Subject: [PATCH] [graphite] Consolidate functionality in the SkShaderCodeDictionary At some point we'll need to go through the dictionary for user provided SkSL Bug: skia:12701 Change-Id: I484ae30626dad64f2bce1e0948071380d9f8282e Reviewed-on: https://skia-review.googlesource.com/c/skia/+/504596 Reviewed-by: Michael Ludwig Commit-Queue: Robert Phillips --- experimental/graphite/src/Context.cpp | 3 +- experimental/graphite/src/ContextUtils.cpp | 111 -------------- experimental/graphite/src/ContextUtils.h | 8 -- experimental/graphite/src/PaintParams.cpp | 4 +- .../graphite/src/mtl/MtlGraphicsPipeline.mm | 8 +- include/private/SkPaintParamsKey.h | 2 +- include/private/SkShaderCodeDictionary.h | 14 ++ src/core/SkBlendModeBlender.cpp | 4 +- src/core/SkKeyHelpers.cpp | 93 ++++++------ src/core/SkKeyHelpers.h | 27 +++- src/core/SkPaintPriv.cpp | 4 +- src/core/SkShaderCodeDictionary.cpp | 135 +++++++++++++++++- src/shaders/SkColorShader.cpp | 4 +- src/shaders/SkComposeShader.cpp | 2 +- src/shaders/SkImageShader.cpp | 2 +- src/shaders/SkShader.cpp | 4 +- src/shaders/gradients/SkLinearGradient.cpp | 2 +- src/shaders/gradients/SkRadialGradient.cpp | 2 +- src/shaders/gradients/SkSweepGradient.cpp | 2 +- .../gradients/SkTwoPointConicalGradient.cpp | 2 +- tests/graphite/CommandBufferTest.cpp | 5 +- tests/graphite/UniformTest.cpp | 4 +- 22 files changed, 242 insertions(+), 200 deletions(-) diff --git a/experimental/graphite/src/Context.cpp b/experimental/graphite/src/Context.cpp index e2170582e6..f1899a56f5 100644 --- a/experimental/graphite/src/Context.cpp +++ b/experimental/graphite/src/Context.cpp @@ -78,7 +78,8 @@ void Context::preCompile(const PaintCombo& paintCombo) { for (auto& shaderCombo: paintCombo.fShaders) { for (auto shaderType: shaderCombo.fTypes) { for (auto tm: shaderCombo.fTileModes) { - SkPaintParamsKey key = CreateKey(SkBackend::kGraphite, shaderType, tm, bm); + SkPaintParamsKey key = CreateKey(fGlobalCache->shaderCodeDictionary(), + SkBackend::kGraphite, shaderType, tm, bm); GraphicsPipelineDesc desc; diff --git a/experimental/graphite/src/ContextUtils.cpp b/experimental/graphite/src/ContextUtils.cpp index 21fe9351e5..8e5b7bb1d9 100644 --- a/experimental/graphite/src/ContextUtils.cpp +++ b/experimental/graphite/src/ContextUtils.cpp @@ -21,79 +21,6 @@ namespace skgpu { -using GradientData = GradientShaderBlocks::GradientData; - -namespace { - -//-------------------------------------------------------------------------------------------------- -// TODO: For the sprint we unify all the gradient uniforms into a standard set of 6: -// kMaxStops colors -// kMaxStops offsets -// 2 points -// 2 radii -static constexpr int kNumGradientUniforms = 6; -static constexpr SkUniform kGradientUniforms[kNumGradientUniforms] = { - { "colors", SkSLType::kHalf4, GradientData::kMaxStops }, - { "offsets", SkSLType::kFloat, GradientData::kMaxStops }, - { "point0", SkSLType::kFloat2 }, - { "point1", SkSLType::kFloat2 }, - { "radius0", SkSLType::kFloat }, - { "radius1", SkSLType::kFloat }, -}; - -static const char *kLinearGradient4Name = "linear_grad_4_shader"; -static const char *kLinearGradient4SkSL = - // TODO: This should use local coords - "half4 linear_grad_4_shader() {\n" - " float2 pos = sk_FragCoord.xy;\n" - " float2 delta = point1 - point0;\n" - " float2 pt = pos - point0;\n" - " float t = dot(pt, delta) / dot(delta, delta);\n" - " float4 result = colors[0];\n" - " result = mix(result, colors[1],\n" - " clamp((t-offsets[0])/(offsets[1]-offsets[0]),\n" - " 0, 1));\n" - " result = mix(result, colors[2],\n" - " clamp((t-offsets[1])/(offsets[2]-offsets[1]),\n" - " 0, 1));\n" - " result = mix(result, colors[3],\n" - " clamp((t-offsets[2])/(offsets[3]-offsets[2]),\n" - " 0, 1));\n" - " return half4(result);\n" - "}\n"; - -//-------------------------------------------------------------------------------------------------- -static constexpr int kNumSolidUniforms = 1; -static constexpr SkUniform kSolidUniforms[kNumSolidUniforms] = { - { "color", SkSLType::kFloat4 } -}; - -static const char* kSolidColorName = "solid_shader"; -static const char* kSolidColorSkSL = - "half4 solid_shader() {\n" - " return half4(color);\n" - "}\n"; - -//-------------------------------------------------------------------------------------------------- -static constexpr int kNumImageUniforms = 0; -static constexpr SkUniform kImageUniforms[kNumImageUniforms] = { -}; - -static const char* kImageName = "image_shader"; -static const char* kImageSkSL = - "half4 image_shader() {\n" - " float r = fract(abs(sk_FragCoord.x/10.0));\n" - " return half4(r, 0.0, 0.0, 1.0);\n" - "}\n"; - -//-------------------------------------------------------------------------------------------------- -// TODO: kNone is for depth-only draws, so should actually have a fragment output type -// that only defines a [[depth]] attribute but no color calculation. -static const char* kNoneName = "none"; -static const char* kNoneSkSL = "outColor = half4(0.0, 0.0, 1.0, 1.0);\n"; - -} // anonymous namespace - std::tuple> ExtractPaintData( SkShaderCodeDictionary* dictionary, const PaintParams& p) { @@ -108,42 +35,4 @@ std::tuple> ExtractPaintD return { entry->uniqueID(), std::move(block) }; } -SkSpan GetUniforms(CodeSnippetID snippetID) { - switch (snippetID) { - case CodeSnippetID::kDepthStencilOnlyDraw: - return {nullptr, 0}; - case CodeSnippetID::kLinearGradientShader: [[fallthrough]]; - case CodeSnippetID::kRadialGradientShader: [[fallthrough]]; - case CodeSnippetID::kSweepGradientShader: [[fallthrough]]; - case CodeSnippetID::kConicalGradientShader: - return SkMakeSpan(kGradientUniforms, kNumGradientUniforms); - case CodeSnippetID::kImageShader: - return SkMakeSpan(kImageUniforms, kNumImageUniforms); - case CodeSnippetID::kSolidColorShader: [[fallthrough]]; - default: - return SkMakeSpan(kSolidUniforms, kNumSolidUniforms); - } -} - -// TODO: move this to the dictionary -std::tuple GetShaderSkSL(CodeSnippetID snippetID) { - switch (snippetID) { - case CodeSnippetID::kDepthStencilOnlyDraw: - return { kNoneName, kNoneSkSL}; - case CodeSnippetID::kLinearGradientShader: [[fallthrough]]; - case CodeSnippetID::kRadialGradientShader: [[fallthrough]]; - case CodeSnippetID::kSweepGradientShader: [[fallthrough]]; - case CodeSnippetID::kConicalGradientShader: - return { kLinearGradient4Name, kLinearGradient4SkSL }; - case CodeSnippetID::kImageShader: - return { kImageName, kImageSkSL }; - case CodeSnippetID::kSolidColorShader: [[fallthrough]]; - default: - return { kSolidColorName, kSolidColorSkSL }; - } -} - - - - } // namespace skgpu diff --git a/experimental/graphite/src/ContextUtils.h b/experimental/graphite/src/ContextUtils.h index bd08d7f835..443e0e1781 100644 --- a/experimental/graphite/src/ContextUtils.h +++ b/experimental/graphite/src/ContextUtils.h @@ -26,14 +26,6 @@ class PaintParams; std::tuple> ExtractPaintData( SkShaderCodeDictionary*, const PaintParams&); -SkSpan GetUniforms(CodeSnippetID); - -// TODO: Temporary way to get at SkSL snippet for handling the given shader type, which will be -// embedded in the fragment function's body. It has access to the vertex output via a "interpolated" -// variable, and must have a statement that writes to a float4 "out.color". Its uniforms (as defined -// by GetUniforms(type)) are available as a variable named "uniforms". -std::tuple GetShaderSkSL(CodeSnippetID); - } // namespace skgpu #endif // skgpu_ContextUtils_DEFINED diff --git a/experimental/graphite/src/PaintParams.cpp b/experimental/graphite/src/PaintParams.cpp index 3a1c868286..1b5a8fa2ed 100644 --- a/experimental/graphite/src/PaintParams.cpp +++ b/experimental/graphite/src/PaintParams.cpp @@ -48,13 +48,13 @@ void PaintParams::toKey(SkShaderCodeDictionary* dict, if (fShader) { as_SB(fShader)->addToKey(dict, backend, key, uniformBlock); } else { - SolidColorShaderBlock::AddToKey(backend, key, uniformBlock, fColor); + SolidColorShaderBlock::AddToKey(dict, backend, key, uniformBlock, fColor); } if (fBlender) { as_BB(fBlender)->addToKey(dict, backend, key, uniformBlock); } else { - BlendModeBlock::AddToKey(backend, key, uniformBlock, SkBlendMode::kSrcOver); + BlendModeBlock::AddToKey(dict, backend, key, uniformBlock, SkBlendMode::kSrcOver); } SkASSERT(key->sizeInBytes() > 0); diff --git a/experimental/graphite/src/mtl/MtlGraphicsPipeline.mm b/experimental/graphite/src/mtl/MtlGraphicsPipeline.mm index 519f5ce31b..9e8b3a69bf 100644 --- a/experimental/graphite/src/mtl/MtlGraphicsPipeline.mm +++ b/experimental/graphite/src/mtl/MtlGraphicsPipeline.mm @@ -169,13 +169,13 @@ std::string get_sksl_vs(const GraphicsPipelineDesc& desc) { return sksl; } -std::string get_sksl_fs(const SkShaderCodeDictionary* dictionary, +std::string get_sksl_fs(const SkShaderCodeDictionary* dict, const GraphicsPipelineDesc& desc, bool* writesColor) { std::string sksl; SkPaintParamsKey key; - auto entry = dictionary->lookup(desc.paintParamsID()); + auto entry = dict->lookup(desc.paintParamsID()); if (entry) { key = entry->paintParamsKey(); } @@ -192,12 +192,12 @@ std::string get_sksl_fs(const SkShaderCodeDictionary* dictionary, } // Typedefs needed for painting - auto paintUniforms = GetUniforms(codeSnippetID); + auto paintUniforms = dict->getUniforms(codeSnippetID); if (!paintUniforms.empty()) { sksl += emit_SKSL_uniforms(2, "FS", paintUniforms); } - auto [name, code] = GetShaderSkSL(codeSnippetID); + auto [name, code] = dict->getShaderSkSL(codeSnippetID); sksl += code; sksl += "layout(location = 0, index = 0) out half4 sk_FragColor;\n"; diff --git a/include/private/SkPaintParamsKey.h b/include/private/SkPaintParamsKey.h index 726da83bd3..c827a51645 100644 --- a/include/private/SkPaintParamsKey.h +++ b/include/private/SkPaintParamsKey.h @@ -19,7 +19,7 @@ enum class SkBackend : uint8_t { }; // TODO: this needs to be expanded into a more flexible dictionary (esp. for user-supplied SkSL) -// TODO: should this enum actually be in ShaderCodeDictionary.h? +// TODO: rename to SkBuiltInCodeSnippetID and move to its own header enum class CodeSnippetID : uint8_t { // TODO: It seems like this requires some refinement. Fundamentally this doesn't seem like a // draw that originated from a PaintParams. diff --git a/include/private/SkShaderCodeDictionary.h b/include/private/SkShaderCodeDictionary.h index 1eb86fb87e..4890d4efb8 100644 --- a/include/private/SkShaderCodeDictionary.h +++ b/include/private/SkShaderCodeDictionary.h @@ -8,11 +8,14 @@ #ifndef SkShaderCodeDictionary_DEFINED #define SkShaderCodeDictionary_DEFINED +#include #include +#include "include/core/SkSpan.h" #include "include/private/SkPaintParamsKey.h" #include "include/private/SkSpinlock.h" #include "include/private/SkUniquePaintParamsID.h" #include "src/core/SkArenaAlloc.h" +#include "src/core/SkUniform.h" class SkShaderCodeDictionary { public: @@ -44,6 +47,9 @@ public: const Entry* lookup(SkUniquePaintParamsID) const SK_EXCLUDES(fSpinLock); + SkSpan getUniforms(CodeSnippetID) const; + std::tuple getShaderSkSL(CodeSnippetID) const; + private: Entry* makeEntry(const SkPaintParamsKey&); @@ -51,6 +57,14 @@ private: size_t operator()(const SkPaintParamsKey&) const; }; + struct SnippetEntry { + SkSpan fUniforms; + const char* fName; + const char* fCode; + }; + + std::array fCodeSnippets; + // TODO: can we do something better given this should have write-seldom/read-often behavior? mutable SkSpinlock fSpinLock; diff --git a/src/core/SkBlendModeBlender.cpp b/src/core/SkBlendModeBlender.cpp index c3503b9e30..8ddc62dd87 100644 --- a/src/core/SkBlendModeBlender.cpp +++ b/src/core/SkBlendModeBlender.cpp @@ -66,9 +66,9 @@ void SkBlenderBase::addToKey(SkShaderCodeDictionary* dict, SkUniformBlock* uniformBlock) const { if (std::optional bm = as_BB(this)->asBlendMode(); bm.has_value()) { - BlendModeBlock::AddToKey(backend, key, uniformBlock, bm.value()); + BlendModeBlock::AddToKey(dict, backend, key, uniformBlock, bm.value()); } else { - BlendModeBlock::AddToKey(backend, key, uniformBlock, SkBlendMode::kSrcOver); + BlendModeBlock::AddToKey(dict, backend, key, uniformBlock, SkBlendMode::kSrcOver); } } diff --git a/src/core/SkKeyHelpers.cpp b/src/core/SkKeyHelpers.cpp index 44c0979f94..35a1951e46 100644 --- a/src/core/SkKeyHelpers.cpp +++ b/src/core/SkKeyHelpers.cpp @@ -8,6 +8,7 @@ #include "src/core/SkKeyHelpers.h" #include "include/private/SkPaintParamsKey.h" +#include "include/private/SkShaderCodeDictionary.h" #include "src/core/SkDebugUtils.h" #include "src/core/SkUniform.h" #include "src/core/SkUniformData.h" @@ -17,10 +18,6 @@ #include "experimental/graphite/src/UniformManager.h" #endif -namespace skgpu { -SkSpan GetUniforms(CodeSnippetID snippetID); -} - namespace { #if defined(SK_DEBUG) && defined(SK_GRAPHITE_ENABLED) @@ -68,7 +65,8 @@ namespace DepthStencilOnlyBlock { static const int kBlockDataSize = 0; -void AddToKey(SkBackend /* backend */, +void AddToKey(SkShaderCodeDictionary* /* dict */, + SkBackend /* backend */, SkPaintParamsKey* key, SkUniformBlock* /* uniformBlock */) { int headerOffset = key->beginBlock(CodeSnippetID::kDepthStencilOnlyDraw); @@ -97,10 +95,10 @@ namespace { #ifdef SK_GRAPHITE_ENABLED static const int kBlockDataSize = 0; -sk_sp make_solid_uniform_data(SkColor4f color) { +sk_sp make_solid_uniform_data(SkShaderCodeDictionary* dict, SkColor4f color) { static constexpr size_t kExpectedNumUniforms = 1; - SkSpan uniforms = skgpu::GetUniforms(CodeSnippetID::kSolidColorShader); + SkSpan uniforms = dict->getUniforms(CodeSnippetID::kSolidColorShader); SkASSERT(uniforms.size() == kExpectedNumUniforms); skgpu::UniformManager mgr(skgpu::Layout::kMetal); @@ -118,7 +116,8 @@ sk_sp make_solid_uniform_data(SkColor4f color) { } // anonymous namespace -void AddToKey(SkBackend backend, +void AddToKey(SkShaderCodeDictionary* dict, + SkBackend backend, SkPaintParamsKey* key, SkUniformBlock* uniformBlock, const SkColor4f& color) { @@ -132,7 +131,7 @@ void AddToKey(SkBackend backend, CodeSnippetID::kSolidColorShader, kBlockDataSize); if (uniformBlock) { - uniformBlock->add(make_solid_uniform_data(color)); + uniformBlock->add(make_solid_uniform_data(dict, color)); } return; } @@ -183,9 +182,10 @@ sk_sp make_gradient_uniform_data_common( return result; } -sk_sp make_linear_gradient_uniform_data(const GradientData& gradData) { +sk_sp make_linear_gradient_uniform_data(SkShaderCodeDictionary* dict, + const GradientData& gradData) { - SkSpan uniforms = skgpu::GetUniforms(CodeSnippetID::kLinearGradientShader); + SkSpan uniforms = dict->getUniforms(CodeSnippetID::kLinearGradientShader); SkASSERT(uniforms.size() == kExpectedNumGradientUniforms); const void* srcs[kExpectedNumGradientUniforms] = { @@ -200,9 +200,10 @@ sk_sp make_linear_gradient_uniform_data(const GradientData& gradD return make_gradient_uniform_data_common(uniforms, srcs); }; -sk_sp make_radial_gradient_uniform_data(const GradientData& gradData) { +sk_sp make_radial_gradient_uniform_data(SkShaderCodeDictionary* dict, + const GradientData& gradData) { - SkSpan uniforms = skgpu::GetUniforms(CodeSnippetID::kRadialGradientShader); + SkSpan uniforms = dict->getUniforms(CodeSnippetID::kRadialGradientShader); SkASSERT(uniforms.size() == kExpectedNumGradientUniforms); const void* srcs[kExpectedNumGradientUniforms] = { @@ -217,9 +218,10 @@ sk_sp make_radial_gradient_uniform_data(const GradientData& gradD return make_gradient_uniform_data_common(uniforms, srcs); }; -sk_sp make_sweep_gradient_uniform_data(const GradientData& gradData) { +sk_sp make_sweep_gradient_uniform_data(SkShaderCodeDictionary* dict, + const GradientData& gradData) { - SkSpan uniforms = skgpu::GetUniforms(CodeSnippetID::kSweepGradientShader); + SkSpan uniforms = dict->getUniforms(CodeSnippetID::kSweepGradientShader); SkASSERT(uniforms.size() == kExpectedNumGradientUniforms); const void* srcs[kExpectedNumGradientUniforms] = { @@ -234,9 +236,10 @@ sk_sp make_sweep_gradient_uniform_data(const GradientData& gradDa return make_gradient_uniform_data_common(uniforms, srcs); }; -sk_sp make_conical_gradient_uniform_data(const GradientData& gradData) { +sk_sp make_conical_gradient_uniform_data(SkShaderCodeDictionary* dict, + const GradientData& gradData) { - SkSpan uniforms = skgpu::GetUniforms(CodeSnippetID::kConicalGradientShader); + SkSpan uniforms = dict->getUniforms(CodeSnippetID::kConicalGradientShader); SkASSERT(uniforms.size() == kExpectedNumGradientUniforms); const void* srcs[kExpectedNumGradientUniforms] = { @@ -300,7 +303,8 @@ GradientData::GradientData(SkShader::GradientType type, } } -void AddToKey(SkBackend backend, +void AddToKey(SkShaderCodeDictionary* dict, + SkBackend backend, SkPaintParamsKey *key, SkUniformBlock* uniformBlock, const GradientData& gradData) { @@ -312,25 +316,25 @@ void AddToKey(SkBackend backend, case SkShader::kLinear_GradientType: codeSnippetID = CodeSnippetID::kLinearGradientShader; if (uniformBlock) { - uniformBlock->add(make_linear_gradient_uniform_data(gradData)); + uniformBlock->add(make_linear_gradient_uniform_data(dict, gradData)); } break; case SkShader::kRadial_GradientType: codeSnippetID = CodeSnippetID::kRadialGradientShader; if (uniformBlock) { - uniformBlock->add(make_radial_gradient_uniform_data(gradData)); + uniformBlock->add(make_radial_gradient_uniform_data(dict, gradData)); } break; case SkShader::kSweep_GradientType: codeSnippetID = CodeSnippetID::kSweepGradientShader; if (uniformBlock) { - uniformBlock->add(make_sweep_gradient_uniform_data(gradData)); + uniformBlock->add(make_sweep_gradient_uniform_data(dict, gradData)); } break; case SkShader::GradientType::kConical_GradientType: codeSnippetID = CodeSnippetID::kConicalGradientShader; if (uniformBlock) { - uniformBlock->add(make_conical_gradient_uniform_data(gradData)); + uniformBlock->add(make_conical_gradient_uniform_data(dict, gradData)); } break; case SkShader::GradientType::kColor_GradientType: @@ -354,7 +358,7 @@ void AddToKey(SkBackend backend, if (backend == SkBackend::kSkVM || backend == SkBackend::kGanesh) { // TODO: add implementation of other backends - SolidColorShaderBlock::AddToKey(backend, key, uniformBlock, SkColors::kRed); + SolidColorShaderBlock::AddToKey(dict, backend, key, uniformBlock, SkColors::kRed); } } @@ -440,10 +444,11 @@ ImageData ExtractFromKey(const SkPaintParamsKey& key, uint32_t headerOffset) { } #endif // SK_DEBUG -sk_sp make_image_uniform_data(const ImageData& imgData) { +sk_sp make_image_uniform_data(SkShaderCodeDictionary* dict, + const ImageData& imgData) { SkDEBUGCODE(static constexpr size_t kExpectedNumUniforms = 0;) - SkSpan uniforms = skgpu::GetUniforms(CodeSnippetID::kImageShader); + SkSpan uniforms = dict->getUniforms(CodeSnippetID::kImageShader); SkASSERT(uniforms.size() == kExpectedNumUniforms); skgpu::UniformManager mgr(skgpu::Layout::kMetal); @@ -462,7 +467,8 @@ sk_sp make_image_uniform_data(const ImageData& imgData) { } // anonymous namespace -void AddToKey(SkBackend backend, +void AddToKey(SkShaderCodeDictionary* dict, + SkBackend backend, SkPaintParamsKey* key, SkUniformBlock* uniformBlock, const ImageData& imgData) { @@ -482,7 +488,7 @@ void AddToKey(SkBackend backend, SkASSERT(imgData == ExtractFromKey(*key, headerOffset)); if (uniformBlock) { - uniformBlock->add(make_image_uniform_data(imgData)); + uniformBlock->add(make_image_uniform_data(dict, imgData)); } return; } @@ -490,7 +496,7 @@ void AddToKey(SkBackend backend, if (backend == SkBackend::kSkVM || backend == SkBackend::kGanesh) { // TODO: add implementation for other backends - SolidColorShaderBlock::AddToKey(backend, key, uniformBlock, SkColors::kRed); + SolidColorShaderBlock::AddToKey(dict, backend, key, uniformBlock, SkColors::kRed); } } @@ -513,7 +519,8 @@ void Dump(const SkPaintParamsKey& key, int headerOffset) { //-------------------------------------------------------------------------------------------------- namespace BlendShaderBlock { -void AddToKey(SkBackend backend, +void AddToKey(SkShaderCodeDictionary* dict, + SkBackend backend, SkPaintParamsKey *key, SkUniformBlock* uniformBlock, const BlendData& blendData) { @@ -524,11 +531,11 @@ void AddToKey(SkBackend backend, add_blendmode_to_key(key, blendData.fBM); int start = key->sizeInBytes(); - as_SB(blendData.fDst)->addToKey(nullptr, backend, key, uniformBlock); + as_SB(blendData.fDst)->addToKey(dict, backend, key, uniformBlock); int firstShaderSize = key->sizeInBytes() - start; start = key->sizeInBytes(); - as_SB(blendData.fSrc)->addToKey(nullptr, backend, key, uniformBlock); + as_SB(blendData.fSrc)->addToKey(dict, backend, key, uniformBlock); int secondShaderSize = key->sizeInBytes() - start; key->endBlock(headerOffset, CodeSnippetID::kBlendShader); @@ -541,7 +548,7 @@ void AddToKey(SkBackend backend, if (backend == SkBackend::kSkVM || backend == SkBackend::kGanesh) { // TODO: add implementation for other backends - SolidColorShaderBlock::AddToKey(backend, key, uniformBlock, SkColors::kRed); + SolidColorShaderBlock::AddToKey(dict, backend, key, uniformBlock, SkColors::kRed); } } @@ -582,7 +589,8 @@ namespace BlendModeBlock { static const int kBlockDataSize = 1; #endif -void AddToKey(SkBackend backend, +void AddToKey(SkShaderCodeDictionary* dict, + SkBackend backend, SkPaintParamsKey *key, SkUniformBlock* uniformBlock, SkBlendMode bm) { @@ -601,7 +609,7 @@ void AddToKey(SkBackend backend, if (backend == SkBackend::kSkVM || backend == SkBackend::kGanesh) { // TODO: add implementation for other backends - SolidColorShaderBlock::AddToKey(backend, key, uniformBlock, SkColors::kRed); + SolidColorShaderBlock::AddToKey(dict, backend, key, uniformBlock, SkColors::kRed); } } @@ -631,7 +639,8 @@ void Dump(const SkPaintParamsKey& key, int headerOffset) { //-------------------------------------------------------------------------------------------------- #ifdef SK_GRAPHITE_ENABLED -SkPaintParamsKey CreateKey(SkBackend backend, +SkPaintParamsKey CreateKey(SkShaderCodeDictionary* dict, + SkBackend backend, skgpu::ShaderCombo::ShaderType s, SkTileMode tm, SkBlendMode bm) { @@ -639,30 +648,30 @@ SkPaintParamsKey CreateKey(SkBackend backend, switch (s) { case skgpu::ShaderCombo::ShaderType::kNone: - DepthStencilOnlyBlock::AddToKey(backend, &key, nullptr); + DepthStencilOnlyBlock::AddToKey(dict, backend, &key, nullptr); break; case skgpu::ShaderCombo::ShaderType::kSolidColor: - SolidColorShaderBlock::AddToKey(backend, &key, nullptr, SkColors::kRed); + SolidColorShaderBlock::AddToKey(dict, backend, &key, nullptr, SkColors::kRed); break; case skgpu::ShaderCombo::ShaderType::kLinearGradient: - GradientShaderBlocks::AddToKey(backend, &key, nullptr, + GradientShaderBlocks::AddToKey(dict, backend, &key, nullptr, { SkShader::kLinear_GradientType, tm, 0 }); break; case skgpu::ShaderCombo::ShaderType::kRadialGradient: - GradientShaderBlocks::AddToKey(backend, &key, nullptr, + GradientShaderBlocks::AddToKey(dict, backend, &key, nullptr, { SkShader::kRadial_GradientType, tm, 0 }); break; case skgpu::ShaderCombo::ShaderType::kSweepGradient: - GradientShaderBlocks::AddToKey(backend, &key, nullptr, + GradientShaderBlocks::AddToKey(dict, backend, &key, nullptr, { SkShader::kSweep_GradientType, tm, 0 }); break; case skgpu::ShaderCombo::ShaderType::kConicalGradient: - GradientShaderBlocks::AddToKey(backend, &key, nullptr, + GradientShaderBlocks::AddToKey(dict, backend, &key, nullptr, { SkShader::kConical_GradientType, tm, 0 }); break; } - BlendModeBlock::AddToKey(backend, &key, nullptr, bm); + BlendModeBlock::AddToKey(dict, backend, &key, nullptr, bm); return key; } #endif diff --git a/src/core/SkKeyHelpers.h b/src/core/SkKeyHelpers.h index 1277cf3be9..5603ce9a6c 100644 --- a/src/core/SkKeyHelpers.h +++ b/src/core/SkKeyHelpers.h @@ -18,13 +18,14 @@ enum class SkBackend : uint8_t; class SkPaintParamsKey; +class SkShaderCodeDictionary; class SkUniformBlock; // The KeyHelpers can be used to manually construct an SkPaintParamsKey namespace DepthStencilOnlyBlock { - void AddToKey(SkBackend, SkPaintParamsKey*, SkUniformBlock*); + void AddToKey(SkShaderCodeDictionary*, SkBackend, SkPaintParamsKey*, SkUniformBlock*); #ifdef SK_DEBUG void Dump(const SkPaintParamsKey&, int headerOffset); #endif @@ -33,7 +34,8 @@ namespace DepthStencilOnlyBlock { namespace SolidColorShaderBlock { - void AddToKey(SkBackend, + void AddToKey(SkShaderCodeDictionary*, + SkBackend, SkPaintParamsKey*, SkUniformBlock*, const SkColor4f&); @@ -89,7 +91,8 @@ namespace GradientShaderBlocks { float fOffsets[kMaxStops]; }; - void AddToKey(SkBackend, + void AddToKey(SkShaderCodeDictionary*, + SkBackend, SkPaintParamsKey*, SkUniformBlock*, const GradientData&); @@ -113,7 +116,8 @@ namespace ImageShaderBlock { SkTileMode fTileModes[2]; }; - void AddToKey(SkBackend, + void AddToKey(SkShaderCodeDictionary*, + SkBackend, SkPaintParamsKey*, SkUniformBlock*, const ImageData&); @@ -132,7 +136,8 @@ namespace BlendShaderBlock { SkBlendMode fBM; }; - void AddToKey(SkBackend, + void AddToKey(SkShaderCodeDictionary*, + SkBackend, SkPaintParamsKey*, SkUniformBlock*, const BlendData&); @@ -144,7 +149,11 @@ namespace BlendShaderBlock { namespace BlendModeBlock { - void AddToKey(SkBackend, SkPaintParamsKey*, SkUniformBlock*, SkBlendMode); + void AddToKey(SkShaderCodeDictionary*, + SkBackend, + SkPaintParamsKey*, + SkUniformBlock*, + SkBlendMode); #ifdef SK_DEBUG void Dump(const SkPaintParamsKey&, int headerOffset); #endif @@ -153,7 +162,11 @@ namespace BlendModeBlock { #ifdef SK_GRAPHITE_ENABLED // Bridge between the combinations system and the SkPaintParamsKey -SkPaintParamsKey CreateKey(SkBackend, skgpu::ShaderCombo::ShaderType, SkTileMode, SkBlendMode); +SkPaintParamsKey CreateKey(SkShaderCodeDictionary*, + SkBackend, + skgpu::ShaderCombo::ShaderType, + SkTileMode, + SkBlendMode); #endif #endif // SkKeyHelpers_DEFINED diff --git a/src/core/SkPaintPriv.cpp b/src/core/SkPaintPriv.cpp index 14e7893981..54334727ff 100644 --- a/src/core/SkPaintPriv.cpp +++ b/src/core/SkPaintPriv.cpp @@ -138,13 +138,13 @@ std::vector SkPaintPriv::ToKeys(const SkPaint& paint, if (paint.getShader()) { as_SB(paint.getShader())->addToKey(dict, backend, &key, nullptr); } else { - SolidColorShaderBlock::AddToKey(backend, &key, nullptr, paint.getColor4f()); + SolidColorShaderBlock::AddToKey(dict, backend, &key, nullptr, paint.getColor4f()); } if (paint.getBlender()) { as_BB(paint.getBlender())->addToKey(dict, backend, &key, nullptr); } else { - BlendModeBlock::AddToKey(backend, &key, nullptr, SkBlendMode::kSrcOver); + BlendModeBlock::AddToKey(dict, backend, &key, nullptr, SkBlendMode::kSrcOver); } SkASSERT(key.sizeInBytes() > 0); diff --git a/src/core/SkShaderCodeDictionary.cpp b/src/core/SkShaderCodeDictionary.cpp index d56af71e32..88e437d220 100644 --- a/src/core/SkShaderCodeDictionary.cpp +++ b/src/core/SkShaderCodeDictionary.cpp @@ -8,11 +8,6 @@ #include "include/private/SkShaderCodeDictionary.h" #include "src/core/SkOpts.h" -SkShaderCodeDictionary::SkShaderCodeDictionary() { - // The 0th index is reserved as invalid - fEntryVector.push_back(nullptr); -} - SkShaderCodeDictionary::Entry* SkShaderCodeDictionary::makeEntry(const SkPaintParamsKey& key) { return fArena.make([&](void *ptr) { return new(ptr) Entry(key); }); } @@ -21,7 +16,8 @@ size_t SkShaderCodeDictionary::Hash::operator()(const SkPaintParamsKey& key) con return SkOpts::hash_fn(key.data(), key.sizeInBytes(), 0); } -const SkShaderCodeDictionary::Entry* SkShaderCodeDictionary::findOrCreate(const SkPaintParamsKey& key) { +const SkShaderCodeDictionary::Entry* SkShaderCodeDictionary::findOrCreate( + const SkPaintParamsKey& key) { SkAutoSpinlock lock{fSpinLock}; auto iter = fHash.find(key); @@ -51,3 +47,130 @@ const SkShaderCodeDictionary::Entry* SkShaderCodeDictionary::lookup( return fEntryVector[codeID.asUInt()]; } + +SkSpan SkShaderCodeDictionary::getUniforms(CodeSnippetID id) const { + return fCodeSnippets[(int) id].fUniforms; +} + +std::tuple SkShaderCodeDictionary::getShaderSkSL( + CodeSnippetID id) const { + if (fCodeSnippets[(int) id].fCode) { + return { fCodeSnippets[(int) id].fName, fCodeSnippets[(int) id].fCode }; + } + + // If we're missing a code snippet just draw solid blue + return this->getShaderSkSL(CodeSnippetID::kDepthStencilOnlyDraw); +} + +//-------------------------------------------------------------------------------------------------- +namespace { + +static constexpr int kFourStopGradient = 4; + +// TODO: For the sprint we unify all the gradient uniforms into a standard set of 6: +// kMaxStops colors +// kMaxStops offsets +// 2 points +// 2 radii +static constexpr int kNumGradientUniforms = 6; +static constexpr SkUniform kGradientUniforms[kNumGradientUniforms] = { + { "colors", SkSLType::kHalf4, kFourStopGradient }, + { "offsets", SkSLType::kFloat, kFourStopGradient }, + { "point0", SkSLType::kFloat2 }, + { "point1", SkSLType::kFloat2 }, + { "radius0", SkSLType::kFloat }, + { "radius1", SkSLType::kFloat }, +}; + +static const char *kLinearGradient4Name = "linear_grad_4_shader"; +static const char *kLinearGradient4SkSL = + // TODO: This should use local coords + "half4 linear_grad_4_shader() {\n" + " float2 pos = sk_FragCoord.xy;\n" + " float2 delta = point1 - point0;\n" + " float2 pt = pos - point0;\n" + " float t = dot(pt, delta) / dot(delta, delta);\n" + " float4 result = colors[0];\n" + " result = mix(result, colors[1],\n" + " clamp((t-offsets[0])/(offsets[1]-offsets[0]),\n" + " 0, 1));\n" + " result = mix(result, colors[2],\n" + " clamp((t-offsets[1])/(offsets[2]-offsets[1]),\n" + " 0, 1));\n" + " result = mix(result, colors[3],\n" + " clamp((t-offsets[2])/(offsets[3]-offsets[2]),\n" + " 0, 1));\n" + " return half4(result);\n" + "}\n"; + +//-------------------------------------------------------------------------------------------------- +static constexpr int kNumSolidUniforms = 1; +static constexpr SkUniform kSolidUniforms[kNumSolidUniforms] = { + { "color", SkSLType::kFloat4 } +}; + +static const char* kSolidColorName = "solid_shader"; +static const char* kSolidColorSkSL = + "half4 solid_shader() {\n" + " return half4(color);\n" + "}\n"; + +//-------------------------------------------------------------------------------------------------- +static constexpr int kNumImageUniforms = 0; + +static const char* kImageName = "image_shader"; +static const char* kImageSkSL = + "half4 image_shader() {\n" + " float r = fract(abs(sk_FragCoord.x/10.0));\n" + " return half4(r, 0.0, 0.0, 1.0);\n" + "}\n"; + +//-------------------------------------------------------------------------------------------------- +// TODO: kNone is for depth-only draws, so should actually have a fragment output type +// that only defines a [[depth]] attribute but no color calculation. +static const char* kNoneName = "none"; +static const char* kNoneSkSL = + "half4 none() {\n" + " return half4(0.0, 0.0, 1.0, 1.0);\n" + "}\n"; + +} // anonymous namespace + +SkShaderCodeDictionary::SkShaderCodeDictionary() { + // The 0th index is reserved as invalid + fEntryVector.push_back(nullptr); + + fCodeSnippets[(int) CodeSnippetID::kDepthStencilOnlyDraw] = { + {}, kNoneName, kNoneSkSL + }; + fCodeSnippets[(int) CodeSnippetID::kSolidColorShader] = { + SkMakeSpan(kSolidUniforms, kNumSolidUniforms), + kSolidColorName, kSolidColorSkSL + }; + fCodeSnippets[(int) CodeSnippetID::kLinearGradientShader] = { + SkMakeSpan(kGradientUniforms, kNumGradientUniforms), + kLinearGradient4Name, kLinearGradient4SkSL + }; + fCodeSnippets[(int) CodeSnippetID::kRadialGradientShader] = { + SkMakeSpan(kGradientUniforms, kNumGradientUniforms), + kLinearGradient4Name, kLinearGradient4SkSL + }; + fCodeSnippets[(int) CodeSnippetID::kSweepGradientShader] = { + SkMakeSpan(kGradientUniforms, kNumGradientUniforms), + kLinearGradient4Name, kLinearGradient4SkSL + }; + fCodeSnippets[(int) CodeSnippetID::kConicalGradientShader] = { + SkMakeSpan(kGradientUniforms, kNumGradientUniforms), + kLinearGradient4Name, kLinearGradient4SkSL + }; + fCodeSnippets[(int) CodeSnippetID::kImageShader] = { + { nullptr, kNumImageUniforms }, + kImageName, kImageSkSL + }; + fCodeSnippets[(int) CodeSnippetID::kBlendShader] = { + {}, nullptr, nullptr + }; + fCodeSnippets[(int) CodeSnippetID::kSimpleBlendMode] = { + {}, nullptr, nullptr + }; +} diff --git a/src/shaders/SkColorShader.cpp b/src/shaders/SkColorShader.cpp index 4af9ecb1a1..28091ac722 100644 --- a/src/shaders/SkColorShader.cpp +++ b/src/shaders/SkColorShader.cpp @@ -141,12 +141,12 @@ void SkColorShader::addToKey(SkShaderCodeDictionary* dict, SkBackend backend, SkPaintParamsKey* key, SkUniformBlock* uniformBlock) const { - SolidColorShaderBlock::AddToKey(backend, key, uniformBlock, SkColor4f::FromColor(fColor)); + SolidColorShaderBlock::AddToKey(dict, backend, key, uniformBlock, SkColor4f::FromColor(fColor)); } void SkColor4Shader::addToKey(SkShaderCodeDictionary* dict, SkBackend backend, SkPaintParamsKey* key, SkUniformBlock* uniformBlock) const { - SolidColorShaderBlock::AddToKey(backend, key, uniformBlock, fColor); + SolidColorShaderBlock::AddToKey(dict, backend, key, uniformBlock, fColor); } diff --git a/src/shaders/SkComposeShader.cpp b/src/shaders/SkComposeShader.cpp index 5ee76f6462..224740d536 100644 --- a/src/shaders/SkComposeShader.cpp +++ b/src/shaders/SkComposeShader.cpp @@ -196,5 +196,5 @@ void SkShader_Blend::addToKey(SkShaderCodeDictionary* dict, // TODO: add blender support SkASSERT(!fBlender); - BlendShaderBlock::AddToKey(backend, key, uniformBlock, { fDst.get(), fSrc.get(), fMode }); + BlendShaderBlock::AddToKey(dict, backend, key, uniformBlock, { fDst.get(), fSrc.get(), fMode }); } diff --git a/src/shaders/SkImageShader.cpp b/src/shaders/SkImageShader.cpp index d202a8106d..e373e9d993 100755 --- a/src/shaders/SkImageShader.cpp +++ b/src/shaders/SkImageShader.cpp @@ -377,7 +377,7 @@ void SkImageShader::addToKey(SkShaderCodeDictionary* dict, SkBackend backend, SkPaintParamsKey* key, SkUniformBlock* uniformBlock) const { - ImageShaderBlock::AddToKey(backend, key, uniformBlock, { fTileModeX, fTileModeY }); + ImageShaderBlock::AddToKey(dict, backend, key, uniformBlock, { fTileModeX, fTileModeY }); } /////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/shaders/SkShader.cpp b/src/shaders/SkShader.cpp index 820f090af6..74f9842e37 100644 --- a/src/shaders/SkShader.cpp +++ b/src/shaders/SkShader.cpp @@ -150,11 +150,11 @@ SkUpdatableShader* SkShaderBase::onUpdatableShader(SkArenaAlloc* alloc) const { } // TODO: add implementations for derived classes -void SkShaderBase::addToKey(SkShaderCodeDictionary* dictionary, +void SkShaderBase::addToKey(SkShaderCodeDictionary* dict, SkBackend backend, SkPaintParamsKey* key, SkUniformBlock* uniformBlock) const { - SolidColorShaderBlock::AddToKey(backend, key, uniformBlock, SkColors::kRed); + SolidColorShaderBlock::AddToKey(dict, backend, key, uniformBlock, SkColors::kRed); } sk_sp SkShaders::Empty() { return sk_make_sp(); } diff --git a/src/shaders/gradients/SkLinearGradient.cpp b/src/shaders/gradients/SkLinearGradient.cpp index 0fc3b482ea..b339fc08d7 100644 --- a/src/shaders/gradients/SkLinearGradient.cpp +++ b/src/shaders/gradients/SkLinearGradient.cpp @@ -116,5 +116,5 @@ void SkLinearGradient::addToKey(SkShaderCodeDictionary* dict, fOrigColors4f, fOrigPos); - GradientShaderBlocks::AddToKey(backend, key, uniformBlock, data); + GradientShaderBlocks::AddToKey(dict, backend, key, uniformBlock, data); } diff --git a/src/shaders/gradients/SkRadialGradient.cpp b/src/shaders/gradients/SkRadialGradient.cpp index 24aa76abcb..d0cc51c982 100644 --- a/src/shaders/gradients/SkRadialGradient.cpp +++ b/src/shaders/gradients/SkRadialGradient.cpp @@ -95,5 +95,5 @@ void SkRadialGradient::addToKey(SkShaderCodeDictionary* dict, fOrigColors4f, fOrigPos); - GradientShaderBlocks::AddToKey(backend, key, uniformBlock, data); + GradientShaderBlocks::AddToKey(dict, backend, key, uniformBlock, data); } diff --git a/src/shaders/gradients/SkSweepGradient.cpp b/src/shaders/gradients/SkSweepGradient.cpp index 93ef8d133d..ce07c79a0a 100644 --- a/src/shaders/gradients/SkSweepGradient.cpp +++ b/src/shaders/gradients/SkSweepGradient.cpp @@ -119,5 +119,5 @@ void SkSweepGradient::addToKey(SkShaderCodeDictionary* dict, fOrigColors4f, fOrigPos); - GradientShaderBlocks::AddToKey(backend, key, uniformBlock, data); + GradientShaderBlocks::AddToKey(dict, backend, key, uniformBlock, data); } diff --git a/src/shaders/gradients/SkTwoPointConicalGradient.cpp b/src/shaders/gradients/SkTwoPointConicalGradient.cpp index 042376e887..e73ac05975 100644 --- a/src/shaders/gradients/SkTwoPointConicalGradient.cpp +++ b/src/shaders/gradients/SkTwoPointConicalGradient.cpp @@ -289,5 +289,5 @@ void SkTwoPointConicalGradient::addToKey(SkShaderCodeDictionary* dict, fOrigColors4f, fOrigPos); - GradientShaderBlocks::AddToKey(backend, key, uniformBlock, data); + GradientShaderBlocks::AddToKey(dict, backend, key, uniformBlock, data); } diff --git a/tests/graphite/CommandBufferTest.cpp b/tests/graphite/CommandBufferTest.cpp index 11366eb818..8140fb72b3 100644 --- a/tests/graphite/CommandBufferTest.cpp +++ b/tests/graphite/CommandBufferTest.cpp @@ -237,6 +237,7 @@ DEF_GRAPHITE_TEST_FOR_CONTEXTS(CommandBufferTest, reporter, context) { #endif auto recorder = context->makeRecorder(); auto resourceProvider = recorder->priv().resourceProvider(); + auto dict = resourceProvider->shaderCodeDictionary(); auto commandBuffer = resourceProvider->createCommandBuffer(); SkISize textureSize = { kTextureWidth, kTextureHeight }; @@ -254,12 +255,12 @@ DEF_GRAPHITE_TEST_FOR_CONTEXTS(CommandBufferTest, reporter, context) { TextureInfo textureInfo; #endif - SkPaintParamsKey key = CreateKey(SkBackend::kGraphite, + SkPaintParamsKey key = CreateKey(dict, + SkBackend::kGraphite, ShaderCombo::ShaderType::kSolidColor, SkTileMode::kClamp, SkBlendMode::kSrc); - auto dict = resourceProvider->shaderCodeDictionary(); auto entry = dict->findOrCreate(key); auto target = sk_sp(new TextureProxy(textureSize, textureInfo)); diff --git a/tests/graphite/UniformTest.cpp b/tests/graphite/UniformTest.cpp index f06bedee64..6dfbb200ce 100644 --- a/tests/graphite/UniformTest.cpp +++ b/tests/graphite/UniformTest.cpp @@ -73,6 +73,7 @@ DEF_GRAPHITE_TEST_FOR_CONTEXTS(UniformTest, reporter, context) { using namespace skgpu; auto recorder = context->makeRecorder(); + auto dict = recorder->priv().resourceProvider()->shaderCodeDictionary(); // Intentionally does not include ShaderType::kNone, which represents no fragment shading stage // and is thus not relevant to uniform extraction/caching. @@ -90,10 +91,9 @@ DEF_GRAPHITE_TEST_FOR_CONTEXTS(UniformTest, reporter, context) { } for (auto bm : { SkBlendMode::kSrc, SkBlendMode::kSrcOver }) { - SkPaintParamsKey expected = CreateKey(SkBackend::kGraphite, s, tm, bm); + SkPaintParamsKey expected = CreateKey(dict, SkBackend::kGraphite, s, tm, bm); auto [ p, expectedNumUniforms ] = create_paint(s, tm, bm); - auto dict = recorder->priv().resourceProvider()->shaderCodeDictionary(); auto [ actualID, uniformBlock] = ExtractPaintData(dict, PaintParams(p)); int actualNumUniforms = uniformBlock->count();