[graphite] Switch PaintParamsKey over to a builder/result model

This will leave the PaintParamsKeys more clearly immutable and manage more of the cruft of key creation (e.g., beginBlock/endBlock pairing).

Bug: skia:12701
Change-Id: I1944397465f845e974e950f47cedb90c3f1895b1
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/506881
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
This commit is contained in:
Robert Phillips 2022-02-16 09:56:32 -05:00 committed by SkCQ
parent 05a4b12dbd
commit c4f1d16390
38 changed files with 456 additions and 233 deletions

View File

@ -73,20 +73,21 @@ void Context::preCompile(const PaintCombo& paintCombo) {
&Renderer::StencilAndFillPath(SkPathFillType::kInverseEvenOdd)
};
SkShaderCodeDictionary* dict = fGlobalCache->shaderCodeDictionary();
for (auto bm: paintCombo.fBlendModes) {
for (auto& shaderCombo: paintCombo.fShaders) {
for (auto shaderType: shaderCombo.fTypes) {
for (auto tm: shaderCombo.fTileModes) {
SkPaintParamsKey key = CreateKey(fGlobalCache->shaderCodeDictionary(),
SkBackend::kGraphite, shaderType, tm, bm);
std::unique_ptr<SkPaintParamsKey> key = CreateKey(dict, SkBackend::kGraphite,
shaderType, tm, bm);
auto entry = dict->findOrCreate(std::move(key));
GraphicsPipelineDesc desc;
for (const Renderer* r : kRenderers) {
for (auto&& s : r->steps()) {
if (s->performsShading()) {
auto entry =
fGlobalCache->shaderCodeDictionary()->findOrCreate(key);
desc.setProgram(s, entry->uniqueID());
}
// TODO: Combine with renderpass description set to generate full

View File

@ -7,6 +7,7 @@
#include "experimental/graphite/src/ContextPriv.h"
#include "experimental/graphite/src/GlobalCache.h"
#include "experimental/graphite/src/Gpu.h"
namespace skgpu {
@ -19,4 +20,8 @@ const Gpu* ContextPriv::gpu() const {
return fContext->fGpu.get();
}
SkShaderCodeDictionary* ContextPriv::shaderCodeDictionary() {
return fContext->fGlobalCache->shaderCodeDictionary();
}
} // namespace skgpu

View File

@ -10,6 +10,8 @@
#include "experimental/graphite/include/Context.h"
class SkShaderCodeDictionary;
namespace skgpu {
class GlobalCache;
@ -24,6 +26,8 @@ public:
Gpu* gpu();
const Gpu* gpu() const;
SkShaderCodeDictionary* shaderCodeDictionary();
private:
friend class Context; // to construct/copy this type.

View File

@ -22,15 +22,17 @@
namespace skgpu {
std::tuple<SkUniquePaintParamsID, std::unique_ptr<SkUniformBlock>> ExtractPaintData(
SkShaderCodeDictionary* dictionary,
SkShaderCodeDictionary* dict,
const PaintParams& p) {
SkPaintParamsKey key;
SkPaintParamsKeyBuilder builder(dict);
std::unique_ptr<SkUniformBlock> block = std::make_unique<SkUniformBlock>();
p.toKey(dictionary, SkBackend::kGraphite, &key, block.get());
p.toKey(dict, SkBackend::kGraphite, &builder, block.get());
auto entry = dictionary->findOrCreate(key);
std::unique_ptr<SkPaintParamsKey> key = builder.snap();
auto entry = dict->findOrCreate(std::move(key));
return { entry->uniqueID(), std::move(block) };
}

View File

@ -42,22 +42,22 @@ sk_sp<SkShader> PaintParams::refShader() const { return fShader; }
void PaintParams::toKey(SkShaderCodeDictionary* dict,
SkBackend backend,
SkPaintParamsKey* key,
SkPaintParamsKeyBuilder* builder,
SkUniformBlock* uniformBlock) const {
if (fShader) {
as_SB(fShader)->addToKey(dict, backend, key, uniformBlock);
as_SB(fShader)->addToKey(dict, backend, builder, uniformBlock);
} else {
SolidColorShaderBlock::AddToKey(dict, backend, key, uniformBlock, fColor);
SolidColorShaderBlock::AddToKey(dict, backend, builder, uniformBlock, fColor);
}
if (fBlender) {
as_BB(fBlender)->addToKey(dict, backend, key, uniformBlock);
as_BB(fBlender)->addToKey(dict, backend, builder, uniformBlock);
} else {
BlendModeBlock::AddToKey(dict, backend, key, uniformBlock, SkBlendMode::kSrcOver);
BlendModeBlock::AddToKey(dict, backend, builder, uniformBlock, SkBlendMode::kSrcOver);
}
SkASSERT(key->sizeInBytes() > 0);
SkASSERT(builder->sizeInBytes() > 0);
}
} // namespace skgpu

View File

@ -12,7 +12,7 @@
#include "include/core/SkPaint.h"
enum class SkBackend : uint8_t;
class SkPaintParamsKey;
class SkPaintParamsKeyBuilder;
class SkShader;
class SkShaderCodeDictionary;
class SkUniformBlock;
@ -46,7 +46,7 @@ public:
void toKey(SkShaderCodeDictionary*,
SkBackend,
SkPaintParamsKey*,
SkPaintParamsKeyBuilder*,
SkUniformBlock*) const;
private:

View File

@ -337,6 +337,7 @@ graphite_tests_sources = [
"$_tests/graphite/ComboTest.cpp",
"$_tests/graphite/CommandBufferTest.cpp",
"$_tests/graphite/IntersectionTreeTest.cpp",
"$_tests/graphite/KeyTest.cpp",
"$_tests/graphite/MaskTest.cpp",
"$_tests/graphite/RecorderTest.cpp",
"$_tests/graphite/RectTest.cpp",

View File

@ -62,13 +62,13 @@ sk_sp<SkBlender> SkBlender::Mode(SkBlendMode mode) {
void SkBlenderBase::addToKey(SkShaderCodeDictionary* dict,
SkBackend backend,
SkPaintParamsKey* key,
SkPaintParamsKeyBuilder* builder,
SkUniformBlock* uniformBlock) const {
if (std::optional<SkBlendMode> bm = as_BB(this)->asBlendMode(); bm.has_value()) {
BlendModeBlock::AddToKey(dict, backend, key, uniformBlock, bm.value());
BlendModeBlock::AddToKey(dict, backend, builder, uniformBlock, bm.value());
} else {
BlendModeBlock::AddToKey(dict, backend, key, uniformBlock, SkBlendMode::kSrcOver);
BlendModeBlock::AddToKey(dict, backend, builder, uniformBlock, SkBlendMode::kSrcOver);
}
}

View File

@ -18,7 +18,7 @@
enum class SkBackend : uint8_t;
struct GrFPArgs;
class GrFragmentProcessor;
class SkPaintParamsKey;
class SkPaintParamsKeyBuilder;
class SkRuntimeEffect;
class SkShaderCodeDictionary;
class SkUniformBlock;
@ -60,7 +60,7 @@ public:
// TODO: make pure virtual
virtual void addToKey(SkShaderCodeDictionary*,
SkBackend,
SkPaintParamsKey*,
SkPaintParamsKeyBuilder*,
SkUniformBlock*) const;
static SkFlattenable::Type GetFlattenableType() { return kSkBlender_Type; }

View File

@ -16,6 +16,8 @@ enum class SkBuiltInCodeSnippetID : uint8_t {
// draw that originated from a PaintParams.
kDepthStencilOnlyDraw,
kError,
// SkShader code snippets
kSolidColorShader,
kLinearGradientShader,

View File

@ -28,20 +28,32 @@ SkBuiltInCodeSnippetID read_code_snippet_id(const SkPaintParamsKey& key, int hea
return static_cast<SkBuiltInCodeSnippetID>(byte);
}
#endif
// This can be used to catch errors in blocks that have a fixed, known block data size
void validate_block_header(const SkPaintParamsKey& key, int headerOffset,
SkBuiltInCodeSnippetID codeSnippetID, int blockDataSize) {
void validate_block_header_key(const SkPaintParamsKey& key,
int headerOffset,
SkBuiltInCodeSnippetID codeSnippetID,
int blockDataSize) {
SkASSERT(key.byte(headerOffset) == static_cast<int>(codeSnippetID));
SkASSERT(key.byte(headerOffset+SkPaintParamsKey::kBlockSizeOffsetInBytes) ==
SkPaintParamsKey::kBlockHeaderSizeInBytes + blockDataSize);
}
#endif
// This can be used to catch errors in blocks that have a fixed, known block data size
void validate_block_header(const SkPaintParamsKeyBuilder* builder,
SkBuiltInCodeSnippetID codeSnippetID,
int blockDataSize) {
SkDEBUGCODE(int fullBlockSize = SkPaintParamsKey::kBlockHeaderSizeInBytes + blockDataSize;)
SkDEBUGCODE(int headerOffset = builder->sizeInBytes() - fullBlockSize;)
SkASSERT(builder->byte(headerOffset) == static_cast<int>(codeSnippetID));
SkASSERT(builder->byte(headerOffset+SkPaintParamsKey::kBlockSizeOffsetInBytes) ==
fullBlockSize);
}
#ifdef SK_GRAPHITE_ENABLED
void add_blendmode_to_key(SkPaintParamsKey* key, SkBlendMode bm) {
void add_blendmode_to_key(SkPaintParamsKeyBuilder* builder, SkBlendMode bm) {
SkASSERT(static_cast<int>(bm) <= std::numeric_limits<uint8_t>::max());
key->addByte(static_cast<uint8_t>(bm));
builder->addByte(static_cast<uint8_t>(bm));
}
#ifdef SK_DEBUG
@ -67,27 +79,28 @@ static const int kBlockDataSize = 0;
void AddToKey(SkShaderCodeDictionary* /* dict */,
SkBackend /* backend */,
SkPaintParamsKey* key,
SkPaintParamsKeyBuilder* builder,
SkUniformBlock* /* uniformBlock */) {
int headerOffset = key->beginBlock(SkBuiltInCodeSnippetID::kDepthStencilOnlyDraw);
key->endBlock(headerOffset, SkBuiltInCodeSnippetID::kDepthStencilOnlyDraw);
builder->beginBlock(SkBuiltInCodeSnippetID::kDepthStencilOnlyDraw);
builder->endBlock();
validate_block_header(*key,
headerOffset,
validate_block_header(builder,
SkBuiltInCodeSnippetID::kDepthStencilOnlyDraw,
kBlockDataSize);
}
#ifdef SK_DEBUG
void Dump(const SkPaintParamsKey& key, int headerOffset) {
validate_block_header(key,
headerOffset,
SkBuiltInCodeSnippetID::kDepthStencilOnlyDraw,
kBlockDataSize);
#ifdef SK_GRAPHITE_ENABLED
validate_block_header_key(key,
headerOffset,
SkBuiltInCodeSnippetID::kDepthStencilOnlyDraw,
kBlockDataSize);
SkDebugf("kDepthStencilOnlyDraw\n");
#endif // SK_GRAPHITE_ENABLED
}
#endif
#endif // SK_DEBUG
} // namespace DepthStencilOnlyBlock
@ -122,17 +135,16 @@ sk_sp<SkUniformData> make_solid_uniform_data(SkShaderCodeDictionary* dict, SkCol
void AddToKey(SkShaderCodeDictionary* dict,
SkBackend backend,
SkPaintParamsKey* key,
SkPaintParamsKeyBuilder* builder,
SkUniformBlock* uniformBlock,
const SkColor4f& color) {
#ifdef SK_GRAPHITE_ENABLED
if (backend == SkBackend::kGraphite) {
int headerOffset = key->beginBlock(SkBuiltInCodeSnippetID::kSolidColorShader);
key->endBlock(headerOffset, SkBuiltInCodeSnippetID::kSolidColorShader);
builder->beginBlock(SkBuiltInCodeSnippetID::kSolidColorShader);
builder->endBlock();
validate_block_header(*key,
headerOffset,
validate_block_header(builder,
SkBuiltInCodeSnippetID::kSolidColorShader,
kBlockDataSize);
@ -153,10 +165,10 @@ void AddToKey(SkShaderCodeDictionary* dict,
void Dump(const SkPaintParamsKey& key, int headerOffset) {
#ifdef SK_GRAPHITE_ENABLED
validate_block_header(key,
headerOffset,
SkBuiltInCodeSnippetID::kSolidColorShader,
kBlockDataSize);
validate_block_header_key(key,
headerOffset,
SkBuiltInCodeSnippetID::kSolidColorShader,
kBlockDataSize);
SkDebugf("kSolidColorShader\n");
#endif
@ -321,7 +333,7 @@ GradientData::GradientData(SkShader::GradientType type,
void AddToKey(SkShaderCodeDictionary* dict,
SkBackend backend,
SkPaintParamsKey *key,
SkPaintParamsKeyBuilder *builder,
SkUniformBlock* uniformBlock,
const GradientData& gradData) {
@ -360,21 +372,21 @@ void AddToKey(SkShaderCodeDictionary* dict,
break;
}
int headerOffset = key->beginBlock(codeSnippetID);
builder->beginBlock(codeSnippetID);
SkASSERT(static_cast<int>(gradData.fTM) <= std::numeric_limits<uint8_t>::max());
key->addByte(static_cast<uint8_t>(gradData.fTM));
builder->addByte(static_cast<uint8_t>(gradData.fTM));
key->endBlock(headerOffset, codeSnippetID);
builder->endBlock();
validate_block_header(*key, headerOffset, codeSnippetID, kBlockDataSize);
validate_block_header(builder, codeSnippetID, kBlockDataSize);
return;
}
#endif // SK_GRAPHITE_ENABLED
if (backend == SkBackend::kSkVM || backend == SkBackend::kGanesh) {
// TODO: add implementation of other backends
SolidColorShaderBlock::AddToKey(dict, backend, key, uniformBlock, SkColors::kRed);
SolidColorShaderBlock::AddToKey(dict, backend, builder, uniformBlock, SkColors::kRed);
}
}
@ -448,10 +460,10 @@ static const int kBlockDataSize = 1;
inline static constexpr int kTileModeMask = 0x3;
ImageData ExtractFromKey(const SkPaintParamsKey& key, uint32_t headerOffset) {
validate_block_header(key,
headerOffset,
SkBuiltInCodeSnippetID::kImageShader,
kBlockDataSize);
validate_block_header_key(key,
headerOffset,
SkBuiltInCodeSnippetID::kImageShader,
kBlockDataSize);
uint8_t data = key.byte(headerOffset+SkPaintParamsKey::kBlockHeaderSizeInBytes);
@ -487,7 +499,7 @@ sk_sp<SkUniformData> make_image_uniform_data(SkShaderCodeDictionary* dict,
void AddToKey(SkShaderCodeDictionary* dict,
SkBackend backend,
SkPaintParamsKey* key,
SkPaintParamsKeyBuilder* builder,
SkUniformBlock* uniformBlock,
const ImageData& imgData) {
@ -497,13 +509,11 @@ void AddToKey(SkShaderCodeDictionary* dict,
uint8_t data = (static_cast<uint8_t>(imgData.fTileModes[0]) << kXTileModeShift) |
(static_cast<uint8_t>(imgData.fTileModes[1]) << kYTileModeShift);
int headerOffset = key->beginBlock(SkBuiltInCodeSnippetID::kImageShader);
builder->beginBlock(SkBuiltInCodeSnippetID::kImageShader);
key->addByte(data);
builder->addByte(data);
key->endBlock(headerOffset, SkBuiltInCodeSnippetID::kImageShader);
SkASSERT(imgData == ExtractFromKey(*key, headerOffset));
builder->endBlock();
if (uniformBlock) {
uniformBlock->add(make_image_uniform_data(dict, imgData));
@ -514,7 +524,7 @@ void AddToKey(SkShaderCodeDictionary* dict,
if (backend == SkBackend::kSkVM || backend == SkBackend::kGanesh) {
// TODO: add implementation for other backends
SolidColorShaderBlock::AddToKey(dict, backend, key, uniformBlock, SkColors::kRed);
SolidColorShaderBlock::AddToKey(dict, backend, builder, uniformBlock, SkColors::kRed);
}
}
@ -539,30 +549,31 @@ namespace BlendShaderBlock {
void AddToKey(SkShaderCodeDictionary* dict,
SkBackend backend,
SkPaintParamsKey *key,
SkPaintParamsKeyBuilder *builder,
SkUniformBlock* uniformBlock,
const BlendData& blendData) {
#ifdef SK_GRAPHITE_ENABLED
if (backend == SkBackend::kGraphite) {
int headerOffset = key->beginBlock(SkBuiltInCodeSnippetID::kBlendShader);
builder->beginBlock(SkBuiltInCodeSnippetID::kBlendShader);
// Child blocks always go right after the parent block's header
int start = key->sizeInBytes();
as_SB(blendData.fDst)->addToKey(dict, backend, key, uniformBlock);
int firstShaderSize = key->sizeInBytes() - start;
// TODO: add startChild/endChild entry points to SkPaintParamsKeyBuilder. They could be
// used to compute and store the number of children w/in a block's header.
int start = builder->sizeInBytes();
as_SB(blendData.fDst)->addToKey(dict, backend, builder, uniformBlock);
int firstShaderSize = builder->sizeInBytes() - start;
start = key->sizeInBytes();
as_SB(blendData.fSrc)->addToKey(dict, backend, key, uniformBlock);
int secondShaderSize = key->sizeInBytes() - start;
start = builder->sizeInBytes();
as_SB(blendData.fSrc)->addToKey(dict, backend, builder, uniformBlock);
int secondShaderSize = builder->sizeInBytes() - start;
add_blendmode_to_key(key, blendData.fBM);
add_blendmode_to_key(builder, blendData.fBM);
key->endBlock(headerOffset, SkBuiltInCodeSnippetID::kBlendShader);
builder->endBlock();
int expectedBlockSize = 1 + firstShaderSize + secondShaderSize;
validate_block_header(*key,
headerOffset,
validate_block_header(builder,
SkBuiltInCodeSnippetID::kBlendShader,
expectedBlockSize);
return;
@ -571,7 +582,7 @@ void AddToKey(SkShaderCodeDictionary* dict,
if (backend == SkBackend::kSkVM || backend == SkBackend::kGanesh) {
// TODO: add implementation for other backends
SolidColorShaderBlock::AddToKey(dict, backend, key, uniformBlock, SkColors::kRed);
SolidColorShaderBlock::AddToKey(dict, backend, builder, uniformBlock, SkColors::kRed);
}
}
@ -615,18 +626,17 @@ static const int kBlockDataSize = 1;
void AddToKey(SkShaderCodeDictionary* dict,
SkBackend backend,
SkPaintParamsKey *key,
SkPaintParamsKeyBuilder *builder,
SkUniformBlock* uniformBlock,
SkBlendMode bm) {
#ifdef SK_GRAPHITE_ENABLED
if (backend == SkBackend::kGraphite) {
int headerOffset = key->beginBlock(SkBuiltInCodeSnippetID::kSimpleBlendMode);
add_blendmode_to_key(key, bm);
key->endBlock(headerOffset, SkBuiltInCodeSnippetID::kSimpleBlendMode);
builder->beginBlock(SkBuiltInCodeSnippetID::kSimpleBlendMode);
add_blendmode_to_key(builder, bm);
builder->endBlock();
validate_block_header(*key,
headerOffset,
validate_block_header(builder,
SkBuiltInCodeSnippetID::kSimpleBlendMode,
kBlockDataSize);
return;
@ -635,7 +645,7 @@ void AddToKey(SkShaderCodeDictionary* dict,
if (backend == SkBackend::kSkVM || backend == SkBackend::kGanesh) {
// TODO: add implementation for other backends
SolidColorShaderBlock::AddToKey(dict, backend, key, uniformBlock, SkColors::kRed);
SolidColorShaderBlock::AddToKey(dict, backend, builder, uniformBlock, SkColors::kRed);
}
}
@ -643,10 +653,10 @@ void AddToKey(SkShaderCodeDictionary* dict,
#ifdef SK_GRAPHITE_ENABLED
SkBlendMode ExtractFromKey(const SkPaintParamsKey& key, uint32_t headerOffset) {
validate_block_header(key,
headerOffset,
SkBuiltInCodeSnippetID::kSimpleBlendMode,
kBlockDataSize);
validate_block_header_key(key,
headerOffset,
SkBuiltInCodeSnippetID::kSimpleBlendMode,
kBlockDataSize);
uint8_t data = key.byte(headerOffset + SkPaintParamsKey::kBlockHeaderSizeInBytes);
return to_blendmode(data);
@ -668,39 +678,39 @@ void Dump(const SkPaintParamsKey& key, int headerOffset) {
//--------------------------------------------------------------------------------------------------
#ifdef SK_GRAPHITE_ENABLED
SkPaintParamsKey CreateKey(SkShaderCodeDictionary* dict,
SkBackend backend,
skgpu::ShaderCombo::ShaderType s,
SkTileMode tm,
SkBlendMode bm) {
SkPaintParamsKey key;
std::unique_ptr<SkPaintParamsKey> CreateKey(SkShaderCodeDictionary* dict,
SkBackend backend,
skgpu::ShaderCombo::ShaderType s,
SkTileMode tm,
SkBlendMode bm) {
SkPaintParamsKeyBuilder builder(dict);
switch (s) {
case skgpu::ShaderCombo::ShaderType::kNone:
DepthStencilOnlyBlock::AddToKey(dict, backend, &key, nullptr);
DepthStencilOnlyBlock::AddToKey(dict, backend, &builder, nullptr);
break;
case skgpu::ShaderCombo::ShaderType::kSolidColor:
SolidColorShaderBlock::AddToKey(dict, backend, &key, nullptr, SkColors::kRed);
SolidColorShaderBlock::AddToKey(dict, backend, &builder, nullptr, SkColors::kRed);
break;
case skgpu::ShaderCombo::ShaderType::kLinearGradient:
GradientShaderBlocks::AddToKey(dict, backend, &key, nullptr,
GradientShaderBlocks::AddToKey(dict, backend, &builder, nullptr,
{ SkShader::kLinear_GradientType, tm, 0 });
break;
case skgpu::ShaderCombo::ShaderType::kRadialGradient:
GradientShaderBlocks::AddToKey(dict, backend, &key, nullptr,
GradientShaderBlocks::AddToKey(dict, backend, &builder, nullptr,
{ SkShader::kRadial_GradientType, tm, 0 });
break;
case skgpu::ShaderCombo::ShaderType::kSweepGradient:
GradientShaderBlocks::AddToKey(dict, backend, &key, nullptr,
GradientShaderBlocks::AddToKey(dict, backend, &builder, nullptr,
{ SkShader::kSweep_GradientType, tm, 0 });
break;
case skgpu::ShaderCombo::ShaderType::kConicalGradient:
GradientShaderBlocks::AddToKey(dict, backend, &key, nullptr,
GradientShaderBlocks::AddToKey(dict, backend, &builder, nullptr,
{ SkShader::kConical_GradientType, tm, 0 });
break;
}
BlendModeBlock::AddToKey(dict, backend, &key, nullptr, bm);
return key;
BlendModeBlock::AddToKey(dict, backend, &builder, nullptr, bm);
return builder.snap();
}
#endif

View File

@ -18,6 +18,7 @@
enum class SkBackend : uint8_t;
class SkPaintParamsKey;
class SkPaintParamsKeyBuilder;
class SkShaderCodeDictionary;
class SkUniformBlock;
@ -25,7 +26,10 @@ class SkUniformBlock;
namespace DepthStencilOnlyBlock {
void AddToKey(SkShaderCodeDictionary*, SkBackend, SkPaintParamsKey*, SkUniformBlock*);
void AddToKey(SkShaderCodeDictionary*,
SkBackend,
SkPaintParamsKeyBuilder*,
SkUniformBlock*);
#ifdef SK_DEBUG
void Dump(const SkPaintParamsKey&, int headerOffset);
#endif
@ -36,7 +40,7 @@ namespace SolidColorShaderBlock {
void AddToKey(SkShaderCodeDictionary*,
SkBackend,
SkPaintParamsKey*,
SkPaintParamsKeyBuilder*,
SkUniformBlock*,
const SkColor4f&);
#ifdef SK_DEBUG
@ -93,7 +97,7 @@ namespace GradientShaderBlocks {
void AddToKey(SkShaderCodeDictionary*,
SkBackend,
SkPaintParamsKey*,
SkPaintParamsKeyBuilder*,
SkUniformBlock*,
const GradientData&);
#ifdef SK_DEBUG
@ -118,7 +122,7 @@ namespace ImageShaderBlock {
void AddToKey(SkShaderCodeDictionary*,
SkBackend,
SkPaintParamsKey*,
SkPaintParamsKeyBuilder*,
SkUniformBlock*,
const ImageData&);
#ifdef SK_DEBUG
@ -138,7 +142,7 @@ namespace BlendShaderBlock {
void AddToKey(SkShaderCodeDictionary*,
SkBackend,
SkPaintParamsKey*,
SkPaintParamsKeyBuilder*,
SkUniformBlock*,
const BlendData&);
#ifdef SK_DEBUG
@ -151,7 +155,7 @@ namespace BlendModeBlock {
void AddToKey(SkShaderCodeDictionary*,
SkBackend,
SkPaintParamsKey*,
SkPaintParamsKeyBuilder*,
SkUniformBlock*,
SkBlendMode);
#ifdef SK_DEBUG
@ -162,11 +166,11 @@ namespace BlendModeBlock {
#ifdef SK_GRAPHITE_ENABLED
// Bridge between the combinations system and the SkPaintParamsKey
SkPaintParamsKey CreateKey(SkShaderCodeDictionary*,
SkBackend,
skgpu::ShaderCombo::ShaderType,
SkTileMode,
SkBlendMode);
std::unique_ptr<SkPaintParamsKey> CreateKey(SkShaderCodeDictionary*,
SkBackend,
skgpu::ShaderCombo::ShaderType,
SkTileMode,
SkBlendMode);
#endif
#endif // SkKeyHelpers_DEFINED

View File

@ -11,9 +11,99 @@
#include "src/core/SkKeyHelpers.h"
#include "src/core/SkShaderCodeDictionary.h"
//--------------------------------------------------------------------------------------------------
SkPaintParamsKeyBuilder::SkPaintParamsKeyBuilder(const SkShaderCodeDictionary* dict)
: fDict(dict) {
}
// Block headers have the following structure:
// 1st byte: codeSnippetID
// 2nd byte: total blockSize in bytes
// This call stores the header's offset in the key on the stack to be used in 'endBlock'
void SkPaintParamsKeyBuilder::beginBlock(int codeSnippetID) {
if (!this->isValid()) {
return;
}
if (codeSnippetID < 0 || codeSnippetID > fDict->maxCodeSnippetID()) {
this->makeInvalid();
return;
}
fData.reserve_back(SkPaintParamsKey::kBlockHeaderSizeInBytes);
fStack.push_back({ codeSnippetID, this->sizeInBytes() });
this->addByte(SkTo<uint8_t>(codeSnippetID));
this->addByte(0); // this needs to be patched up with a call to endBlock
}
// Update the size byte of a block header
void SkPaintParamsKeyBuilder::endBlock() {
if (!this->isValid()) {
return;
}
if (fStack.empty()) {
SkASSERT(0);
this->makeInvalid();
return;
}
int headerOffset = fStack.back().fHeaderOffset;
SkASSERT(fData[headerOffset] == fStack.back().fCodeSnippetID);
SkASSERT(fData[headerOffset+SkPaintParamsKey::kBlockSizeOffsetInBytes] == 0);
int blockSize = this->sizeInBytes() - headerOffset;
if (blockSize > SkPaintParamsKey::kMaxBlockSize) {
this->makeInvalid();
return;
}
fData[headerOffset+SkPaintParamsKey::kBlockSizeOffsetInBytes] = blockSize;
fStack.pop_back();
}
void SkPaintParamsKeyBuilder::addBytes(uint32_t numBytes, const uint8_t* data) {
if (!this->isValid()) {
return;
}
fData.push_back_n(numBytes, data);
}
std::unique_ptr<SkPaintParamsKey> SkPaintParamsKeyBuilder::snap() {
if (!fStack.empty()) {
this->makeInvalid(); // fall through
}
auto key = std::unique_ptr<SkPaintParamsKey>(new SkPaintParamsKey(std::move(fData)));
// Reset for reuse
fIsValid = true;
fStack.clear();
return key;
}
void SkPaintParamsKeyBuilder::makeInvalid() {
SkASSERT(fIsValid);
fStack.clear();
fData.reset();
this->beginBlock(SkBuiltInCodeSnippetID::kError);
this->endBlock();
SkASSERT(fIsValid);
fIsValid = false;
}
//--------------------------------------------------------------------------------------------------
SkPaintParamsKey::SkPaintParamsKey(SkTArray<uint8_t, true>&& data) : fData(std::move(data)) {}
bool SkPaintParamsKey::operator==(const SkPaintParamsKey& that) const {
return fNumBytes == that.fNumBytes &&
!memcmp(fData.data(), that.fData.data(), fNumBytes);
return fData == that.fData;
}
#ifdef SK_DEBUG

View File

@ -8,19 +8,63 @@
#ifndef SkPaintParamsKey_DEFINED
#define SkPaintParamsKey_DEFINED
#include "include/core/SkTypes.h"
#include "include/private/SkTArray.h"
#include "src/core/SkBuiltInCodeSnippetID.h"
#include <array>
#include <limits>
#include "include/core/SkTypes.h"
#include "src/core/SkBuiltInCodeSnippetID.h"
#include <vector>
enum class SkBackend : uint8_t {
kGanesh,
kGraphite,
kSkVM
};
class SkPaintParamsKey;
class SkShaderCodeDictionary;
class SkShaderInfo;
class SkPaintParamsKeyBuilder {
public:
SkPaintParamsKeyBuilder(const SkShaderCodeDictionary*);
void beginBlock(int codeSnippetID);
void beginBlock(SkBuiltInCodeSnippetID id) { this->beginBlock(static_cast<int>(id)); }
void endBlock();
void addBytes(uint32_t numBytes, const uint8_t* data);
void addByte(uint8_t data) {
this->addBytes(1, &data);
}
#ifdef SK_DEBUG
uint8_t byte(int offset) const { return fData[offset]; }
#endif
std::unique_ptr<SkPaintParamsKey> snap();
int sizeInBytes() const { return fData.count(); }
bool isValid() const { return fIsValid; }
private:
void makeInvalid();
struct StackFrame {
int fCodeSnippetID;
int fHeaderOffset;
};
bool fIsValid = true;
const SkShaderCodeDictionary* fDict;
std::vector<StackFrame> fStack;
// TODO: It is probably overkill but we could encode the SkBackend in the first byte of
// the key.
SkTArray<uint8_t, true> fData;
};
// This class is a compact representation of the shader needed to implement a given
// PaintParams. Its structure is a series of blocks where each block has a
// header that consists of 2-bytes:
@ -33,29 +77,10 @@ class SkPaintParamsKey {
public:
static const int kBlockHeaderSizeInBytes = 2;
static const int kBlockSizeOffsetInBytes = 1; // offset to the block size w/in the header
// Block headers have the following structure:
// 1st byte: codeSnippetID
// 2nd byte: total blockSize in bytes
// Returns the header's offset in the key - to be passed back into endBlock
int beginBlock(SkBuiltInCodeSnippetID codeSnippetID) {
SkASSERT(fNumBytes < kMaxKeySize);
this->addByte((uint8_t) codeSnippetID);
this->addByte(0); // this needs to be patched up with a call to endBlock
return fNumBytes - kBlockHeaderSizeInBytes;
}
// Update the size byte of a block header
void endBlock(int headerOffset, SkBuiltInCodeSnippetID codeSnippetID) {
SkASSERT(fData[headerOffset] == (uint32_t) codeSnippetID);
int blockSize = fNumBytes - headerOffset;
SkASSERT(blockSize <= kMaxBlockSize);
fData[headerOffset+1] = blockSize;
}
static const int kMaxBlockSize = std::numeric_limits<uint8_t>::max();
std::pair<SkBuiltInCodeSnippetID, uint8_t> readCodeSnippetID(int headerOffset) const {
SkASSERT(headerOffset < kMaxKeySize - kBlockHeaderSizeInBytes);
SkASSERT(headerOffset < this->sizeInBytes() - kBlockHeaderSizeInBytes);
SkBuiltInCodeSnippetID id = static_cast<SkBuiltInCodeSnippetID>(fData[headerOffset]);
uint8_t blockSize = fData[headerOffset+1];
@ -64,39 +89,33 @@ public:
return { id, blockSize };
}
void addByte(uint8_t byte) {
SkASSERT(fNumBytes < kMaxKeySize);
fData[fNumBytes++] = byte;
}
#ifdef SK_DEBUG
uint8_t byte(int offset) const {
SkASSERT(offset < this->sizeInBytes());
return fData[offset];
}
static int DumpBlock(const SkPaintParamsKey&, int headerOffset);
void dump() const;
#endif
void toShaderInfo(SkShaderCodeDictionary*, SkShaderInfo*) const;
uint8_t byte(int offset) const { SkASSERT(offset < fNumBytes); return fData[offset]; }
const void* data() const { return fData.data(); }
int sizeInBytes() const { return fNumBytes; }
int sizeInBytes() const { return fData.count(); }
bool operator==(const SkPaintParamsKey& that) const;
bool operator!=(const SkPaintParamsKey& that) const { return !(*this == that); }
private:
friend class SkPaintParamsKeyBuilder;
SkPaintParamsKey(SkTArray<uint8_t, true>&&);
static int AddBlockToShaderInfo(SkShaderCodeDictionary*,
const SkPaintParamsKey&,
int headerOffset,
SkShaderInfo*);
// TODO: need to make it so the key can can dynamically grow
static const int kMaxKeySize = 32;
static const int kMaxBlockSize = std::numeric_limits<uint8_t>::max();
// TODO: It is probably overkill but we could encode the SkBackend in the first byte of
// the key.
int fNumBytes = 0;
std::array<uint8_t, kMaxKeySize> fData;
SkTArray<uint8_t, true> fData;
};
#endif // SkPaintParamsKey_DEFINED

View File

@ -124,33 +124,33 @@ SkScalar SkPaintPriv::ComputeResScaleForStroking(const SkMatrix& matrix) {
return 1;
}
std::vector<SkPaintParamsKey> SkPaintPriv::ToKeys(const SkPaint& paint,
SkShaderCodeDictionary* dict,
SkBackend backend) {
std::vector<SkPaintParamsKey> keys;
std::vector<std::unique_ptr<SkPaintParamsKey>> SkPaintPriv::ToKeys(const SkPaint& paint,
SkShaderCodeDictionary* dict,
SkBackend backend) {
std::vector<std::unique_ptr<SkPaintParamsKey>> keys;
// TODO: actually split the SkPaint into multiple PaintParams and generate the keys
// for them separately.
// TODO: actually collect and return the SkUniformData vector for each PaintParams derived
// from the SkPaint
{
SkPaintParamsKey key;
SkPaintParamsKeyBuilder builder(dict);
if (paint.getShader()) {
as_SB(paint.getShader())->addToKey(dict, backend, &key, nullptr);
as_SB(paint.getShader())->addToKey(dict, backend, &builder, nullptr);
} else {
SolidColorShaderBlock::AddToKey(dict, backend, &key, nullptr, paint.getColor4f());
SolidColorShaderBlock::AddToKey(dict, backend, &builder, nullptr, paint.getColor4f());
}
if (paint.getBlender()) {
as_BB(paint.getBlender())->addToKey(dict, backend, &key, nullptr);
as_BB(paint.getBlender())->addToKey(dict, backend, &builder, nullptr);
} else {
BlendModeBlock::AddToKey(dict, backend, &key, nullptr, SkBlendMode::kSrcOver);
BlendModeBlock::AddToKey(dict, backend, &builder, nullptr, SkBlendMode::kSrcOver);
}
SkASSERT(key.sizeInBytes() > 0);
SkASSERT(builder.sizeInBytes() > 0);
keys.push_back(key);
keys.push_back(builder.snap());
}
return keys;

View File

@ -72,9 +72,9 @@ public:
@param backend the backend that would be carrying out the drawing
@return the SkPaintParamsKeys that would be needed to draw this paint
*/
static std::vector<SkPaintParamsKey> ToKeys(const SkPaint& paint,
SkShaderCodeDictionary* dictionary,
SkBackend backend);
static std::vector<std::unique_ptr<SkPaintParamsKey>> ToKeys(const SkPaint& paint,
SkShaderCodeDictionary* dictionary,
SkBackend backend);
};
#endif

View File

@ -113,25 +113,26 @@ std::string SkShaderInfo::toSkSL() const {
}
#endif
SkShaderCodeDictionary::Entry* SkShaderCodeDictionary::makeEntry(const SkPaintParamsKey& key) {
return fArena.make([&](void *ptr) { return new(ptr) Entry(key); });
SkShaderCodeDictionary::Entry* SkShaderCodeDictionary::makeEntry(
std::unique_ptr<SkPaintParamsKey> key) {
return fArena.make([&](void *ptr) { return new(ptr) Entry(std::move(key)); });
}
size_t SkShaderCodeDictionary::Hash::operator()(const SkPaintParamsKey& key) const {
return SkOpts::hash_fn(key.data(), key.sizeInBytes(), 0);
size_t SkShaderCodeDictionary::Hash::operator()(const SkPaintParamsKey* key) const {
return SkOpts::hash_fn(key->data(), key->sizeInBytes(), 0);
}
const SkShaderCodeDictionary::Entry* SkShaderCodeDictionary::findOrCreate(
const SkPaintParamsKey& key) {
std::unique_ptr<SkPaintParamsKey> key) {
SkAutoSpinlock lock{fSpinLock};
auto iter = fHash.find(key);
auto iter = fHash.find(key.get());
if (iter != fHash.end()) {
SkASSERT(fEntryVector[iter->second->uniqueID().asUInt()] == iter->second);
return iter->second;
}
Entry* newEntry = this->makeEntry(key);
Entry* newEntry = this->makeEntry(std::move(key));
newEntry->setUniqueID(fEntryVector.size());
fHash.insert(std::make_pair(newEntry->paintParamsKey(), newEntry));
fEntryVector.push_back(newEntry);
@ -154,18 +155,24 @@ const SkShaderCodeDictionary::Entry* SkShaderCodeDictionary::lookup(
}
SkSpan<const SkUniform> SkShaderCodeDictionary::getUniforms(SkBuiltInCodeSnippetID id) const {
return fCodeSnippets[(int) id].fUniforms;
return fBuiltInCodeSnippets[(int) id].fUniforms;
}
const SkShaderInfo::SnippetEntry* SkShaderCodeDictionary::getEntry(SkBuiltInCodeSnippetID id) const {
return &fCodeSnippets[(int) id];
return &fBuiltInCodeSnippets[(int) id];
}
void SkShaderCodeDictionary::getShaderInfo(SkUniquePaintParamsID uniqueID, SkShaderInfo* info) {
auto entry = this->lookup(uniqueID);
entry->paintParamsKey().toShaderInfo(this, info);
entry->paintParamsKey()->toShaderInfo(this, info);
}
int SkShaderCodeDictionary::addUserDefinedSnippet() {
fUserDefinedCodeSnippets.push_back({});
return kBuiltInCodeSnippetIDCount + fUserDefinedCodeSnippets.size() - 1;
}
//--------------------------------------------------------------------------------------------------
namespace {
@ -373,55 +380,62 @@ SkShaderCodeDictionary::SkShaderCodeDictionary() {
// The 0th index is reserved as invalid
fEntryVector.push_back(nullptr);
fCodeSnippets[(int) SkBuiltInCodeSnippetID::kDepthStencilOnlyDraw] = {
fBuiltInCodeSnippets[(int) SkBuiltInCodeSnippetID::kDepthStencilOnlyDraw] = {
{ nullptr, kNumErrorUniforms },
kErrorName, kErrorSkSL,
GenerateDefaultGlueCode,
kNoChildren
};
fCodeSnippets[(int) SkBuiltInCodeSnippetID::kSolidColorShader] = {
fBuiltInCodeSnippets[(int) SkBuiltInCodeSnippetID::kError] = {
{ nullptr, kNumErrorUniforms },
kErrorName, kErrorSkSL,
GenerateDefaultGlueCode,
kNoChildren
};
fBuiltInCodeSnippets[(int) SkBuiltInCodeSnippetID::kSolidColorShader] = {
SkMakeSpan(kSolidShaderUniforms, kNumSolidShaderUniforms),
kSolidShaderName, kSolidShaderSkSL,
GenerateDefaultGlueCode,
kNoChildren
};
fCodeSnippets[(int) SkBuiltInCodeSnippetID::kLinearGradientShader] = {
fBuiltInCodeSnippets[(int) SkBuiltInCodeSnippetID::kLinearGradientShader] = {
SkMakeSpan(kGradientUniforms, kNumGradientUniforms),
kLinearGradient4Name, kLinearGradient4SkSL,
GenerateDefaultGlueCode,
kNoChildren
};
fCodeSnippets[(int) SkBuiltInCodeSnippetID::kRadialGradientShader] = {
fBuiltInCodeSnippets[(int) SkBuiltInCodeSnippetID::kRadialGradientShader] = {
SkMakeSpan(kGradientUniforms, kNumGradientUniforms),
kLinearGradient4Name, kLinearGradient4SkSL,
GenerateDefaultGlueCode,
kNoChildren
};
fCodeSnippets[(int) SkBuiltInCodeSnippetID::kSweepGradientShader] = {
fBuiltInCodeSnippets[(int) SkBuiltInCodeSnippetID::kSweepGradientShader] = {
SkMakeSpan(kGradientUniforms, kNumGradientUniforms),
kLinearGradient4Name, kLinearGradient4SkSL,
GenerateDefaultGlueCode,
kNoChildren
};
fCodeSnippets[(int) SkBuiltInCodeSnippetID::kConicalGradientShader] = {
fBuiltInCodeSnippets[(int) SkBuiltInCodeSnippetID::kConicalGradientShader] = {
SkMakeSpan(kGradientUniforms, kNumGradientUniforms),
kLinearGradient4Name, kLinearGradient4SkSL,
GenerateDefaultGlueCode,
kNoChildren
};
fCodeSnippets[(int) SkBuiltInCodeSnippetID::kImageShader] = {
fBuiltInCodeSnippets[(int) SkBuiltInCodeSnippetID::kImageShader] = {
{ nullptr, kNumImageShaderUniforms },
kImageShaderName, kImageShaderSkSL,
GenerateDefaultGlueCode,
kNoChildren
};
fCodeSnippets[(int) SkBuiltInCodeSnippetID::kBlendShader] = {
fBuiltInCodeSnippets[(int) SkBuiltInCodeSnippetID::kBlendShader] = {
{ nullptr, kNumBlendShaderUniforms },
kBlendShaderName, kBlendShaderSkSL,
GenerateBlendShaderGlueCode,
kNumBlendShaderChildren
};
fCodeSnippets[(int) SkBuiltInCodeSnippetID::kSimpleBlendMode] = {
fBuiltInCodeSnippets[(int) SkBuiltInCodeSnippetID::kSimpleBlendMode] = {
{ nullptr, kNumErrorUniforms },
kErrorName, kErrorSkSL,
GenerateDefaultGlueCode,

View File

@ -65,12 +65,12 @@ public:
SkASSERT(fUniqueID.isValid());
return fUniqueID;
}
const SkPaintParamsKey& paintParamsKey() const { return fPaintParamsKey; }
const SkPaintParamsKey* paintParamsKey() const { return fKey.get(); }
private:
friend class SkShaderCodeDictionary;
Entry(const SkPaintParamsKey& paintParamsKey) : fPaintParamsKey(paintParamsKey) {}
Entry(std::unique_ptr<SkPaintParamsKey> key) : fKey(std::move(key)) {}
void setUniqueID(uint32_t newID) {
SkASSERT(!fUniqueID.isValid());
@ -78,10 +78,10 @@ public:
}
SkUniquePaintParamsID fUniqueID; // fixed-size (uint32_t) unique ID assigned to a key
SkPaintParamsKey fPaintParamsKey; // variable-length paint key descriptor
std::unique_ptr<SkPaintParamsKey> fKey; // variable-length paint key descriptor
};
const Entry* findOrCreate(const SkPaintParamsKey&) SK_EXCLUDES(fSpinLock);
const Entry* findOrCreate(std::unique_ptr<SkPaintParamsKey>) SK_EXCLUDES(fSpinLock);
const Entry* lookup(SkUniquePaintParamsID) const SK_EXCLUDES(fSpinLock);
@ -90,19 +90,29 @@ public:
void getShaderInfo(SkUniquePaintParamsID, SkShaderInfo*);
int maxCodeSnippetID() const {
return static_cast<int>(SkBuiltInCodeSnippetID::kLast) + fUserDefinedCodeSnippets.size();
}
// TODO: this is still experimental but, most likely, it will need to be made thread-safe
// It returns the code snippet ID to use to identify the supplied user-defined code
// TODO: add hooks for user to actually provide code.
int addUserDefinedSnippet();
private:
Entry* makeEntry(const SkPaintParamsKey&);
Entry* makeEntry(std::unique_ptr<SkPaintParamsKey>);
struct Hash {
size_t operator()(const SkPaintParamsKey&) const;
size_t operator()(const SkPaintParamsKey*) const;
};
std::array<SkShaderInfo::SnippetEntry, kBuiltInCodeSnippetIDCount> fCodeSnippets;
std::array<SkShaderInfo::SnippetEntry, kBuiltInCodeSnippetIDCount> fBuiltInCodeSnippets;
std::vector<SkShaderInfo::SnippetEntry> fUserDefinedCodeSnippets;
// TODO: can we do something better given this should have write-seldom/read-often behavior?
mutable SkSpinlock fSpinLock;
std::unordered_map<SkPaintParamsKey, Entry*, Hash> fHash SK_GUARDED_BY(fSpinLock);
std::unordered_map<const SkPaintParamsKey*, Entry*, Hash> fHash SK_GUARDED_BY(fSpinLock);
std::vector<Entry*> fEntryVector SK_GUARDED_BY(fSpinLock);
SkArenaAlloc fArena{256};

View File

@ -139,14 +139,15 @@ std::unique_ptr<GrFragmentProcessor> SkColor4Shader::asFragmentProcessor(
void SkColorShader::addToKey(SkShaderCodeDictionary* dict,
SkBackend backend,
SkPaintParamsKey* key,
SkPaintParamsKeyBuilder* builder,
SkUniformBlock* uniformBlock) const {
SolidColorShaderBlock::AddToKey(dict, backend, key, uniformBlock, SkColor4f::FromColor(fColor));
SolidColorShaderBlock::AddToKey(dict, backend, builder, uniformBlock,
SkColor4f::FromColor(fColor));
}
void SkColor4Shader::addToKey(SkShaderCodeDictionary* dict,
SkBackend backend,
SkPaintParamsKey* key,
SkPaintParamsKeyBuilder* builder,
SkUniformBlock* uniformBlock) const {
SolidColorShaderBlock::AddToKey(dict, backend, key, uniformBlock, fColor);
SolidColorShaderBlock::AddToKey(dict, backend, builder, uniformBlock, fColor);
}

View File

@ -33,7 +33,7 @@ public:
#endif
void addToKey(SkShaderCodeDictionary*,
SkBackend,
SkPaintParamsKey*,
SkPaintParamsKeyBuilder*,
SkUniformBlock*) const override;
private:
@ -67,7 +67,7 @@ public:
#endif
void addToKey(SkShaderCodeDictionary*,
SkBackend,
SkPaintParamsKey*,
SkPaintParamsKeyBuilder*,
SkUniformBlock*) const override;
private:

View File

@ -191,10 +191,11 @@ std::unique_ptr<GrFragmentProcessor> SkShader_Blend::asFragmentProcessor(
void SkShader_Blend::addToKey(SkShaderCodeDictionary* dict,
SkBackend backend,
SkPaintParamsKey* key,
SkPaintParamsKeyBuilder* builder,
SkUniformBlock* uniformBlock) const {
// TODO: add blender support
SkASSERT(!fBlender);
BlendShaderBlock::AddToKey(dict, backend, key, uniformBlock, { fDst.get(), fSrc.get(), fMode });
BlendShaderBlock::AddToKey(dict, backend, builder, uniformBlock,
{ fDst.get(), fSrc.get(), fMode });
}

View File

@ -30,7 +30,7 @@ public:
void addToKey(SkShaderCodeDictionary*,
SkBackend,
SkPaintParamsKey*,
SkPaintParamsKeyBuilder*,
SkUniformBlock*) const override;
protected:

View File

@ -375,9 +375,9 @@ std::unique_ptr<GrFragmentProcessor> SkImageShader::asFragmentProcessor(
void SkImageShader::addToKey(SkShaderCodeDictionary* dict,
SkBackend backend,
SkPaintParamsKey* key,
SkPaintParamsKeyBuilder* builder,
SkUniformBlock* uniformBlock) const {
ImageShaderBlock::AddToKey(dict, backend, key, uniformBlock, { fTileModeX, fTileModeY });
ImageShaderBlock::AddToKey(dict, backend, builder, uniformBlock, { fTileModeX, fTileModeY });
}
///////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -46,7 +46,7 @@ public:
void addToKey(SkShaderCodeDictionary*,
SkBackend,
SkPaintParamsKey*,
SkPaintParamsKeyBuilder*,
SkUniformBlock*) const override;
static SkM44 CubicResamplerMatrix(float B, float C);

View File

@ -152,9 +152,9 @@ SkUpdatableShader* SkShaderBase::onUpdatableShader(SkArenaAlloc* alloc) const {
// TODO: add implementations for derived classes
void SkShaderBase::addToKey(SkShaderCodeDictionary* dict,
SkBackend backend,
SkPaintParamsKey* key,
SkPaintParamsKeyBuilder* builder,
SkUniformBlock* uniformBlock) const {
SolidColorShaderBlock::AddToKey(dict, backend, key, uniformBlock, SkColors::kRed);
SolidColorShaderBlock::AddToKey(dict, backend, builder, uniformBlock, SkColors::kRed);
}
sk_sp<SkShader> SkShaders::Empty() { return sk_make_sp<SkEmptyShader>(); }

View File

@ -29,7 +29,7 @@ class SkColorSpace;
class SkImage;
struct SkImageInfo;
class SkPaint;
class SkPaintParamsKey;
class SkPaintParamsKeyBuilder;
class SkRasterPipeline;
class SkRuntimeEffect;
class SkShaderCodeDictionary;
@ -220,12 +220,12 @@ public:
@param dictionary dictionary of code fragments available to be used in the key
@param backend the backend that would be carrying out the drawing
@param key destination for implementation details of this SkShader
@param builder builder for creating the key for this SkShader
@param uniformBlock if non-null, storage for this shader's uniform data
*/
virtual void addToKey(SkShaderCodeDictionary* dictionary,
SkBackend backend,
SkPaintParamsKey* key,
SkPaintParamsKeyBuilder* builder,
SkUniformBlock* uniformBlock) const;
protected:

View File

@ -106,7 +106,7 @@ std::unique_ptr<GrFragmentProcessor> SkLinearGradient::asFragmentProcessor(
void SkLinearGradient::addToKey(SkShaderCodeDictionary* dict,
SkBackend backend,
SkPaintParamsKey* key,
SkPaintParamsKeyBuilder* builder,
SkUniformBlock* uniformBlock) const {
GradientShaderBlocks::GradientData data(kLinear_GradientType,
fStart, fEnd,
@ -116,5 +116,5 @@ void SkLinearGradient::addToKey(SkShaderCodeDictionary* dict,
fOrigColors4f,
fOrigPos);
GradientShaderBlocks::AddToKey(dict, backend, key, uniformBlock, data);
GradientShaderBlocks::AddToKey(dict, backend, builder, uniformBlock, data);
}

View File

@ -20,7 +20,7 @@ public:
#endif
void addToKey(SkShaderCodeDictionary*,
SkBackend,
SkPaintParamsKey*,
SkPaintParamsKeyBuilder*,
SkUniformBlock*) const override;
protected:

View File

@ -85,7 +85,7 @@ std::unique_ptr<GrFragmentProcessor> SkRadialGradient::asFragmentProcessor(
void SkRadialGradient::addToKey(SkShaderCodeDictionary* dict,
SkBackend backend,
SkPaintParamsKey* key,
SkPaintParamsKeyBuilder* builder,
SkUniformBlock* uniformBlock) const {
GradientShaderBlocks::GradientData data(kRadial_GradientType,
fCenter, { 0.0f, 0.0f },
@ -95,5 +95,5 @@ void SkRadialGradient::addToKey(SkShaderCodeDictionary* dict,
fOrigColors4f,
fOrigPos);
GradientShaderBlocks::AddToKey(dict, backend, key, uniformBlock, data);
GradientShaderBlocks::AddToKey(dict, backend, builder, uniformBlock, data);
}

View File

@ -20,7 +20,7 @@ public:
#endif
void addToKey(SkShaderCodeDictionary*,
SkBackend,
SkPaintParamsKey*,
SkPaintParamsKeyBuilder*,
SkUniformBlock*) const override;
protected:

View File

@ -109,7 +109,7 @@ std::unique_ptr<GrFragmentProcessor> SkSweepGradient::asFragmentProcessor(
void SkSweepGradient::addToKey(SkShaderCodeDictionary* dict,
SkBackend backend,
SkPaintParamsKey* key,
SkPaintParamsKeyBuilder* builder,
SkUniformBlock* uniformBlock) const {
GradientShaderBlocks::GradientData data(kSweep_GradientType,
fCenter, { 0.0f, 0.0f },
@ -119,5 +119,5 @@ void SkSweepGradient::addToKey(SkShaderCodeDictionary* dict,
fOrigColors4f,
fOrigPos);
GradientShaderBlocks::AddToKey(dict, backend, key, uniformBlock, data);
GradientShaderBlocks::AddToKey(dict, backend, builder, uniformBlock, data);
}

View File

@ -21,7 +21,7 @@ public:
#endif
void addToKey(SkShaderCodeDictionary*,
SkBackend,
SkPaintParamsKey*,
SkPaintParamsKeyBuilder*,
SkUniformBlock*) const override;
SkScalar getTBias() const { return fTBias; }

View File

@ -279,7 +279,7 @@ std::unique_ptr<GrFragmentProcessor> SkTwoPointConicalGradient::asFragmentProces
void SkTwoPointConicalGradient::addToKey(SkShaderCodeDictionary* dict,
SkBackend backend,
SkPaintParamsKey* key,
SkPaintParamsKeyBuilder* builder,
SkUniformBlock* uniformBlock) const {
GradientShaderBlocks::GradientData data(kConical_GradientType,
fCenter1, fCenter2,
@ -289,5 +289,5 @@ void SkTwoPointConicalGradient::addToKey(SkShaderCodeDictionary* dict,
fOrigColors4f,
fOrigPos);
GradientShaderBlocks::AddToKey(dict, backend, key, uniformBlock, data);
GradientShaderBlocks::AddToKey(dict, backend, builder, uniformBlock, data);
}

View File

@ -53,7 +53,7 @@ public:
#endif
void addToKey(SkShaderCodeDictionary*,
SkBackend,
SkPaintParamsKey*,
SkPaintParamsKeyBuilder*,
SkUniformBlock*) const override;
bool isOpaque() const override;

View File

@ -43,9 +43,9 @@ void dump_keys(SkShaderCodeDictionary *dict, const SkPaint &paint) {
#ifdef SK_DEBUG
auto keys = SkPaintPriv::ToKeys(paint, dict, SkBackend::kGraphite);
for (auto k: keys) {
for (const auto& k : keys) {
// TODO: we need a better way to assess that key creation succeeded
k.dump();
k->dump();
}
#endif
}

View File

@ -254,13 +254,13 @@ DEF_GRAPHITE_TEST_FOR_CONTEXTS(CommandBufferTest, reporter, context) {
TextureInfo textureInfo;
#endif
SkPaintParamsKey key = CreateKey(dict,
SkBackend::kGraphite,
ShaderCombo::ShaderType::kSolidColor,
SkTileMode::kClamp,
SkBlendMode::kSrc);
std::unique_ptr<SkPaintParamsKey> key = CreateKey(dict,
SkBackend::kGraphite,
ShaderCombo::ShaderType::kSolidColor,
SkTileMode::kClamp,
SkBlendMode::kSrc);
auto entry = dict->findOrCreate(key);
auto entry = dict->findOrCreate(std::move(key));
auto target = sk_sp<TextureProxy>(new TextureProxy(textureSize, textureInfo));
REPORTER_ASSERT(reporter, target);

View File

@ -0,0 +1,58 @@
/*
* Copyright 2022 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "tests/Test.h"
#include "src/core/SkPaintParamsKey.h"
#include "src/core/SkShaderCodeDictionary.h"
#include "experimental/graphite/src/ContextPriv.h"
namespace {
std::unique_ptr<SkPaintParamsKey> create_key(SkShaderCodeDictionary* dict,
int dummySnippetID,
int size) {
SkPaintParamsKeyBuilder builder(dict);
builder.beginBlock(dummySnippetID);
for (int i = 0; i < size; ++i) {
builder.addByte(i % 256);
}
builder.endBlock();
return builder.snap();
}
} // anonymous namespace
DEF_GRAPHITE_TEST_FOR_CONTEXTS(KeyTest, reporter, context) {
auto dict = context->priv().shaderCodeDictionary();
static const int kMaxBlockDataSize = SkPaintParamsKey::kMaxBlockSize -
SkPaintParamsKey::kBlockHeaderSizeInBytes;
std::unique_ptr<SkPaintParamsKey> key;
// invalid code snippet ID
key = create_key(dict, kBuiltInCodeSnippetIDCount, kMaxBlockDataSize);
REPORTER_ASSERT(reporter, key->sizeInBytes() == SkPaintParamsKey::kBlockHeaderSizeInBytes);
int dummySnippetID = dict->addUserDefinedSnippet();
// _Just_ on the edge of being too big
key = create_key(dict, dummySnippetID, kMaxBlockDataSize);
REPORTER_ASSERT(reporter, key->sizeInBytes() == SkPaintParamsKey::kMaxBlockSize);
// Too big
key = create_key(dict, dummySnippetID, 1024);
REPORTER_ASSERT(reporter, key->sizeInBytes() == SkPaintParamsKey::kBlockHeaderSizeInBytes);
}

View File

@ -91,7 +91,8 @@ DEF_GRAPHITE_TEST_FOR_CONTEXTS(UniformTest, reporter, context) {
}
for (auto bm : { SkBlendMode::kSrc, SkBlendMode::kSrcOver }) {
SkPaintParamsKey expected = CreateKey(dict, SkBackend::kGraphite, s, tm, bm);
std::unique_ptr<SkPaintParamsKey> expected = CreateKey(dict, SkBackend::kGraphite,
s, tm, bm);
auto [ p, expectedNumUniforms ] = create_paint(s, tm, bm);
auto [ actualID, uniformBlock] = ExtractPaintData(dict, PaintParams(p));
@ -100,7 +101,7 @@ DEF_GRAPHITE_TEST_FOR_CONTEXTS(UniformTest, reporter, context) {
auto entry = dict->lookup(actualID);
REPORTER_ASSERT(reporter, expected == entry->paintParamsKey());
REPORTER_ASSERT(reporter, *expected == *entry->paintParamsKey());
REPORTER_ASSERT(reporter, expectedNumUniforms == actualNumUniforms);
for (auto& u : *uniformBlock) {
for (int i = 0; i < u->count(); ++i) {