[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 <michaelludwig@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
This commit is contained in:
Robert Phillips 2022-02-07 10:24:16 -05:00 committed by SkCQ
parent 8d646c127a
commit 07b639da6f
22 changed files with 242 additions and 200 deletions

View File

@ -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;

View File

@ -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<SkUniquePaintParamsID, std::unique_ptr<SkUniformBlock>> ExtractPaintData(
SkShaderCodeDictionary* dictionary,
const PaintParams& p) {
@ -108,42 +35,4 @@ std::tuple<SkUniquePaintParamsID, std::unique_ptr<SkUniformBlock>> ExtractPaintD
return { entry->uniqueID(), std::move(block) };
}
SkSpan<const SkUniform> 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<const char*, const char*> 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

View File

@ -26,14 +26,6 @@ class PaintParams;
std::tuple<SkUniquePaintParamsID, std::unique_ptr<SkUniformBlock>> ExtractPaintData(
SkShaderCodeDictionary*, const PaintParams&);
SkSpan<const SkUniform> 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<const char*, const char*> GetShaderSkSL(CodeSnippetID);
} // namespace skgpu
#endif // skgpu_ContextUtils_DEFINED

View File

@ -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);

View File

@ -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";

View File

@ -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.

View File

@ -8,11 +8,14 @@
#ifndef SkShaderCodeDictionary_DEFINED
#define SkShaderCodeDictionary_DEFINED
#include <array>
#include <unordered_map>
#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<const SkUniform> getUniforms(CodeSnippetID) const;
std::tuple<const char*, const char*> getShaderSkSL(CodeSnippetID) const;
private:
Entry* makeEntry(const SkPaintParamsKey&);
@ -51,6 +57,14 @@ private:
size_t operator()(const SkPaintParamsKey&) const;
};
struct SnippetEntry {
SkSpan<const SkUniform> fUniforms;
const char* fName;
const char* fCode;
};
std::array<SnippetEntry, kCodeSnippetIDCount> fCodeSnippets;
// TODO: can we do something better given this should have write-seldom/read-often behavior?
mutable SkSpinlock fSpinLock;

View File

@ -66,9 +66,9 @@ void SkBlenderBase::addToKey(SkShaderCodeDictionary* dict,
SkUniformBlock* uniformBlock) const {
if (std::optional<SkBlendMode> 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);
}
}

View File

@ -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<const SkUniform> 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<SkUniformData> make_solid_uniform_data(SkColor4f color) {
sk_sp<SkUniformData> make_solid_uniform_data(SkShaderCodeDictionary* dict, SkColor4f color) {
static constexpr size_t kExpectedNumUniforms = 1;
SkSpan<const SkUniform> uniforms = skgpu::GetUniforms(CodeSnippetID::kSolidColorShader);
SkSpan<const SkUniform> uniforms = dict->getUniforms(CodeSnippetID::kSolidColorShader);
SkASSERT(uniforms.size() == kExpectedNumUniforms);
skgpu::UniformManager mgr(skgpu::Layout::kMetal);
@ -118,7 +116,8 @@ sk_sp<SkUniformData> 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<SkUniformData> make_gradient_uniform_data_common(
return result;
}
sk_sp<SkUniformData> make_linear_gradient_uniform_data(const GradientData& gradData) {
sk_sp<SkUniformData> make_linear_gradient_uniform_data(SkShaderCodeDictionary* dict,
const GradientData& gradData) {
SkSpan<const SkUniform> uniforms = skgpu::GetUniforms(CodeSnippetID::kLinearGradientShader);
SkSpan<const SkUniform> uniforms = dict->getUniforms(CodeSnippetID::kLinearGradientShader);
SkASSERT(uniforms.size() == kExpectedNumGradientUniforms);
const void* srcs[kExpectedNumGradientUniforms] = {
@ -200,9 +200,10 @@ sk_sp<SkUniformData> make_linear_gradient_uniform_data(const GradientData& gradD
return make_gradient_uniform_data_common(uniforms, srcs);
};
sk_sp<SkUniformData> make_radial_gradient_uniform_data(const GradientData& gradData) {
sk_sp<SkUniformData> make_radial_gradient_uniform_data(SkShaderCodeDictionary* dict,
const GradientData& gradData) {
SkSpan<const SkUniform> uniforms = skgpu::GetUniforms(CodeSnippetID::kRadialGradientShader);
SkSpan<const SkUniform> uniforms = dict->getUniforms(CodeSnippetID::kRadialGradientShader);
SkASSERT(uniforms.size() == kExpectedNumGradientUniforms);
const void* srcs[kExpectedNumGradientUniforms] = {
@ -217,9 +218,10 @@ sk_sp<SkUniformData> make_radial_gradient_uniform_data(const GradientData& gradD
return make_gradient_uniform_data_common(uniforms, srcs);
};
sk_sp<SkUniformData> make_sweep_gradient_uniform_data(const GradientData& gradData) {
sk_sp<SkUniformData> make_sweep_gradient_uniform_data(SkShaderCodeDictionary* dict,
const GradientData& gradData) {
SkSpan<const SkUniform> uniforms = skgpu::GetUniforms(CodeSnippetID::kSweepGradientShader);
SkSpan<const SkUniform> uniforms = dict->getUniforms(CodeSnippetID::kSweepGradientShader);
SkASSERT(uniforms.size() == kExpectedNumGradientUniforms);
const void* srcs[kExpectedNumGradientUniforms] = {
@ -234,9 +236,10 @@ sk_sp<SkUniformData> make_sweep_gradient_uniform_data(const GradientData& gradDa
return make_gradient_uniform_data_common(uniforms, srcs);
};
sk_sp<SkUniformData> make_conical_gradient_uniform_data(const GradientData& gradData) {
sk_sp<SkUniformData> make_conical_gradient_uniform_data(SkShaderCodeDictionary* dict,
const GradientData& gradData) {
SkSpan<const SkUniform> uniforms = skgpu::GetUniforms(CodeSnippetID::kConicalGradientShader);
SkSpan<const SkUniform> 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<SkUniformData> make_image_uniform_data(const ImageData& imgData) {
sk_sp<SkUniformData> make_image_uniform_data(SkShaderCodeDictionary* dict,
const ImageData& imgData) {
SkDEBUGCODE(static constexpr size_t kExpectedNumUniforms = 0;)
SkSpan<const SkUniform> uniforms = skgpu::GetUniforms(CodeSnippetID::kImageShader);
SkSpan<const SkUniform> uniforms = dict->getUniforms(CodeSnippetID::kImageShader);
SkASSERT(uniforms.size() == kExpectedNumUniforms);
skgpu::UniformManager mgr(skgpu::Layout::kMetal);
@ -462,7 +467,8 @@ sk_sp<SkUniformData> 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

View File

@ -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

View File

@ -138,13 +138,13 @@ std::vector<SkPaintParamsKey> 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);

View File

@ -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<const SkUniform> SkShaderCodeDictionary::getUniforms(CodeSnippetID id) const {
return fCodeSnippets[(int) id].fUniforms;
}
std::tuple<const char*, const char*> 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
};
}

View File

@ -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);
}

View File

@ -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 });
}

View File

@ -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 });
}
///////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -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<SkShader> SkShaders::Empty() { return sk_make_sp<SkEmptyShader>(); }

View File

@ -116,5 +116,5 @@ void SkLinearGradient::addToKey(SkShaderCodeDictionary* dict,
fOrigColors4f,
fOrigPos);
GradientShaderBlocks::AddToKey(backend, key, uniformBlock, data);
GradientShaderBlocks::AddToKey(dict, backend, key, uniformBlock, data);
}

View File

@ -95,5 +95,5 @@ void SkRadialGradient::addToKey(SkShaderCodeDictionary* dict,
fOrigColors4f,
fOrigPos);
GradientShaderBlocks::AddToKey(backend, key, uniformBlock, data);
GradientShaderBlocks::AddToKey(dict, backend, key, uniformBlock, data);
}

View File

@ -119,5 +119,5 @@ void SkSweepGradient::addToKey(SkShaderCodeDictionary* dict,
fOrigColors4f,
fOrigPos);
GradientShaderBlocks::AddToKey(backend, key, uniformBlock, data);
GradientShaderBlocks::AddToKey(dict, backend, key, uniformBlock, data);
}

View File

@ -289,5 +289,5 @@ void SkTwoPointConicalGradient::addToKey(SkShaderCodeDictionary* dict,
fOrigColors4f,
fOrigPos);
GradientShaderBlocks::AddToKey(backend, key, uniformBlock, data);
GradientShaderBlocks::AddToKey(dict, backend, key, uniformBlock, data);
}

View File

@ -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<TextureProxy>(new TextureProxy(textureSize, textureInfo));

View File

@ -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();