[graphite] Split out CombinationBuilder tests
Bug: skia:12701 Change-Id: Ibf7b4ac280eb853e3f5d786bd188ae0ac208609b Reviewed-on: https://skia-review.googlesource.com/c/skia/+/545367 Reviewed-by: Michael Ludwig <michaelludwig@google.com> Reviewed-by: Greg Daniel <egdaniel@google.com> Commit-Queue: Robert Phillips <robertphillips@google.com>
This commit is contained in:
parent
f8c1c459b1
commit
c42960d4f2
127
dm/DMSrcSink.cpp
127
dm/DMSrcSink.cpp
@ -2135,133 +2135,6 @@ Result RasterSink::draw(const Src& src, SkBitmap* dst, SkWStream*, SkString*) co
|
||||
namespace {
|
||||
|
||||
void precompile(skgpu::graphite::Context* context) {
|
||||
SkCombinationBuilder builder(context);
|
||||
|
||||
static constexpr int kMinNumStops = 4;
|
||||
static constexpr int kMaxNumStops = 8;
|
||||
|
||||
// The resulting number of combinations are in braces
|
||||
//
|
||||
// builder {428}
|
||||
// |- {107} sweepGrad_0 {5} | blendShader_0 {102}
|
||||
// | 0 {6}: linearGrad_0 {5} | solid_0 {1}
|
||||
// | 1 {17}: linearGrad_1 {5} | blendShader_1 {12}
|
||||
// | 0 {6}: radGrad_0 {5} | solid_1 {1}
|
||||
// | 1 {2}: imageShader_0 {2}
|
||||
// |
|
||||
// |- {4} 4-built-in-blend-modes {4}
|
||||
{
|
||||
// first, shaders. First top-level option (sweepGrad_0)
|
||||
[[maybe_unused]] auto sweepGrad_0 = builder.addOption(SkShaderType::kSweepGradient,
|
||||
kMinNumStops, kMaxNumStops);
|
||||
|
||||
// Second top-level option (blendShader_0)
|
||||
auto blendShader_0 = builder.addOption(SkShaderType::kBlendShader);
|
||||
|
||||
// first child slot of blendShader_0
|
||||
{
|
||||
// first option (linearGrad_0)
|
||||
[[maybe_unused]] auto linearGrad_0 = blendShader_0.addChildOption(
|
||||
0, SkShaderType::kLinearGradient,
|
||||
kMinNumStops, kMaxNumStops);
|
||||
|
||||
// second option (solid_0)
|
||||
[[maybe_unused]] auto solid_0 = blendShader_0.addChildOption(0,
|
||||
SkShaderType::kSolidColor);
|
||||
}
|
||||
|
||||
// second child slot of blendShader_0
|
||||
{
|
||||
// first option (linearGrad_1)
|
||||
{
|
||||
[[maybe_unused]] auto linearGrad_1 = blendShader_0.addChildOption(
|
||||
1, SkShaderType::kLinearGradient,
|
||||
kMinNumStops, kMaxNumStops);
|
||||
}
|
||||
|
||||
// second option (blendShader_1)
|
||||
{
|
||||
auto blendShader_1 = blendShader_0.addChildOption(1, SkShaderType::kBlendShader);
|
||||
|
||||
// nested: first child slot of blendShader_1
|
||||
{
|
||||
// first option (radialGrad_0)
|
||||
[[maybe_unused]] auto radialGrad_0 = blendShader_1.addChildOption(
|
||||
0, SkShaderType::kRadialGradient,
|
||||
kMinNumStops, kMaxNumStops);
|
||||
|
||||
// second option (solid_1)
|
||||
[[maybe_unused]] auto solid_1 = blendShader_1.addChildOption(
|
||||
0, SkShaderType::kSolidColor);
|
||||
}
|
||||
|
||||
// nested: second child slot of blendShader_1
|
||||
{
|
||||
SkTileModePair tilingOptions[] = {
|
||||
{ SkTileMode::kRepeat, SkTileMode::kRepeat },
|
||||
{ SkTileMode::kClamp, SkTileMode::kClamp }
|
||||
};
|
||||
|
||||
// only option (imageShader_0)
|
||||
[[maybe_unused]] auto imageShader_0 = blendShader_1.addChildOption(
|
||||
1, SkShaderType::kImage,
|
||||
SkMakeSpan(tilingOptions));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// now, blend modes
|
||||
builder.addOption(SkBlendMode::kSrcOver);
|
||||
builder.addOption(SkBlendMode::kSrc);
|
||||
builder.addOption(SkBlendMode::kDstOver);
|
||||
builder.addOption(SkBlendMode::kDst);
|
||||
|
||||
SkASSERT(builder.numCombinations() == 428);
|
||||
|
||||
// TODO: re-enable - right now blocked on BlendShader children
|
||||
// context->precompile(builder);
|
||||
}
|
||||
|
||||
builder.reset();
|
||||
|
||||
{
|
||||
builder.addOption(SkShaderType::kSolidColor);
|
||||
builder.addOption(SkBlendMode::kSrcOver);
|
||||
builder.addOption(SkBlendMode::kSrc);
|
||||
|
||||
SkASSERT(builder.numCombinations() == 2);
|
||||
|
||||
context->precompile(builder);
|
||||
}
|
||||
|
||||
builder.reset();
|
||||
|
||||
{
|
||||
builder.addOption(SkShaderType::kLinearGradient, kMinNumStops, kMaxNumStops);
|
||||
builder.addOption(SkBlendMode::kSrcOver);
|
||||
builder.addOption(SkBlendMode::kSrc);
|
||||
|
||||
SkASSERT(builder.numCombinations() == 10);
|
||||
|
||||
context->precompile(builder);
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
// TODO: move this to CombinationBuilderTest
|
||||
builder.reset();
|
||||
|
||||
// Check that epochs are updated upon builder reset
|
||||
{
|
||||
SkCombinationOption solid_0 = builder.addOption(SkShaderType::kSolidColor);
|
||||
|
||||
int optionEpoch = solid_0.epoch();
|
||||
SkASSERT(optionEpoch == builder.epoch());
|
||||
|
||||
builder.reset();
|
||||
|
||||
SkASSERT(optionEpoch != builder.epoch());
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
@ -332,6 +332,7 @@ metal_tests_sources = [
|
||||
|
||||
graphite_tests_sources = [
|
||||
"$_tests/graphite/BackendTextureTest.cpp",
|
||||
"$_tests/graphite/CombinationBuilderTest.cpp",
|
||||
"$_tests/graphite/CommandBufferTest.cpp",
|
||||
"$_tests/graphite/GraphiteResourceCacheTest.cpp",
|
||||
"$_tests/graphite/IntersectionTreeTest.cpp",
|
||||
|
@ -95,17 +95,19 @@ public:
|
||||
SkSpan<SkTileModePair> tileModes);
|
||||
|
||||
bool isValid() const { return fDataInArena; }
|
||||
SkShaderType type() const;
|
||||
int numChildSlots() const;
|
||||
SkDEBUGCODE(int epoch() const;)
|
||||
|
||||
private:
|
||||
friend class SkCombinationBuilder; // for ctor
|
||||
friend class CombinationBuilderTestAccess;
|
||||
|
||||
SkCombinationOption(SkCombinationBuilder* builder, SkOption* dataInArena)
|
||||
: fBuilder(builder)
|
||||
, fDataInArena(dataInArena) {}
|
||||
|
||||
SkShaderType type() const;
|
||||
int numChildSlots() const;
|
||||
SkDEBUGCODE(int epoch() const;)
|
||||
|
||||
SkCombinationBuilder* fBuilder;
|
||||
SkOption* fDataInArena;
|
||||
};
|
||||
@ -124,6 +126,7 @@ public:
|
||||
#else
|
||||
SkCombinationBuilder(SkShaderCodeDictionary*);
|
||||
#endif
|
||||
~SkCombinationBuilder();
|
||||
|
||||
// Blend Modes
|
||||
void addOption(SkBlendMode);
|
||||
@ -140,17 +143,22 @@ public:
|
||||
|
||||
void reset();
|
||||
|
||||
int numCombinations();
|
||||
private:
|
||||
friend class skgpu::graphite::Context; // for access to 'buildCombinations'
|
||||
friend class SkCombinationOption; // for 'addOptionInternal' and 'arena'
|
||||
friend class CombinationBuilderTestAccess; // for 'num*Combinations' and 'epoch'
|
||||
|
||||
int numShaderCombinations() const;
|
||||
int numBlendModeCombinations() const;
|
||||
int numCombinations() {
|
||||
return this->numShaderCombinations() * this->numBlendModeCombinations();
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
void dump() const;
|
||||
int epoch() const { return fEpoch; }
|
||||
#endif
|
||||
|
||||
private:
|
||||
friend class skgpu::graphite::Context; // for access to buildCombinations
|
||||
friend class SkCombinationOption; // for 'addOptionInternal' and 'arena'
|
||||
|
||||
SkArenaAllocWithReset* arena() { return fArena.get(); }
|
||||
|
||||
template<typename T, typename... Args>
|
||||
@ -161,7 +169,7 @@ private:
|
||||
SkOption* addOptionInternal(SkShaderType, SkSpan<SkTileModePair> tileModes);
|
||||
|
||||
void buildCombinations(SkShaderCodeDictionary*,
|
||||
const std::function<void(SkUniquePaintParamsID)>&) const;
|
||||
const std::function<void(SkUniquePaintParamsID)>&);
|
||||
|
||||
SkShaderCodeDictionary* fDictionary;
|
||||
std::unique_ptr<SkArenaAllocWithReset> fArena;
|
||||
|
@ -58,7 +58,7 @@ public:
|
||||
// TODO: add "SkColorFilterID addUserDefinedColorFilter(sk_sp<SkRuntimeEffect>)" here
|
||||
SkBlenderID addUserDefinedBlender(sk_sp<SkRuntimeEffect>);
|
||||
|
||||
void precompile(const SkCombinationBuilder&);
|
||||
void precompile(SkCombinationBuilder*);
|
||||
|
||||
/**
|
||||
* Creates a new backend gpu texture matching the dimensinos and TextureInfo. If an invalid
|
||||
|
@ -377,6 +377,9 @@ SkCombinationBuilder::SkCombinationBuilder(SkShaderCodeDictionary* dict)
|
||||
}
|
||||
#endif
|
||||
|
||||
SkCombinationBuilder::~SkCombinationBuilder() = default;
|
||||
|
||||
|
||||
template<typename T, typename... Args>
|
||||
SkOption* SkCombinationBuilder::allocInArena(Args&&... args) {
|
||||
SkOption* arenaObject = fArena->make<T>(T{{ T::kType, T::kNumChildSlots },
|
||||
@ -517,13 +520,21 @@ void SkCombinationBuilder::reset() {
|
||||
SkDEBUGCODE(++fEpoch;)
|
||||
}
|
||||
|
||||
int SkCombinationBuilder::numCombinations() {
|
||||
int SkCombinationBuilder::numShaderCombinations() const {
|
||||
int numShaderCombinations = 0;
|
||||
for (SkOption* s : fShaderOptions) {
|
||||
numShaderCombinations += s->numCombinations();
|
||||
}
|
||||
|
||||
return numShaderCombinations * (SkPopCount(fBlendModes) + fBlenders.count());
|
||||
// If no shader option is specified the builder will add a solid color shader option
|
||||
return numShaderCombinations ? numShaderCombinations : 1;
|
||||
}
|
||||
|
||||
int SkCombinationBuilder::numBlendModeCombinations() const {
|
||||
int numBlendModeCombinations = SkPopCount(fBlendModes) + fBlenders.count();
|
||||
|
||||
// If no blend mode options are specified the builder will add kSrcOver as an option
|
||||
return numBlendModeCombinations ? numBlendModeCombinations : 1;
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
@ -537,10 +548,20 @@ void SkCombinationBuilder::dump() const {
|
||||
|
||||
void SkCombinationBuilder::buildCombinations(
|
||||
SkShaderCodeDictionary* dict,
|
||||
const std::function<void(SkUniquePaintParamsID)>& func) const {
|
||||
const std::function<void(SkUniquePaintParamsID)>& func) {
|
||||
SkKeyContext keyContext(dict);
|
||||
SkPaintParamsKeyBuilder builder(dict, SkBackend::kGraphite);
|
||||
|
||||
// Supply a default kSrcOver if no other blend mode option is provided
|
||||
if (fBlendModes == 0 && fBlenders.empty()) {
|
||||
this->addOption(SkBlendMode::kSrcOver);
|
||||
}
|
||||
|
||||
// Supply a default solid color shader if no other shader option is provided
|
||||
if (fShaderOptions.empty()){
|
||||
this->addOption(SkShaderType::kSolidColor);
|
||||
}
|
||||
|
||||
for (int i = 0; i < kSkBlendModeCount; ++i) {
|
||||
if (!(fBlendModes & (0x1 << i))) {
|
||||
continue;
|
||||
|
@ -95,7 +95,7 @@ SkBlenderID Context::addUserDefinedBlender(sk_sp<SkRuntimeEffect> effect) {
|
||||
return dict->addUserDefinedBlender(std::move(effect));
|
||||
}
|
||||
|
||||
void Context::precompile(const SkCombinationBuilder& combinationBuilder) {
|
||||
void Context::precompile(SkCombinationBuilder* combinationBuilder) {
|
||||
static const Renderer* kRenderers[] = {
|
||||
&Renderer::StencilTessellatedCurvesAndTris(SkPathFillType::kWinding),
|
||||
&Renderer::StencilTessellatedCurvesAndTris(SkPathFillType::kEvenOdd),
|
||||
@ -109,7 +109,7 @@ void Context::precompile(const SkCombinationBuilder& combinationBuilder) {
|
||||
|
||||
SkShaderCodeDictionary* dict = fGlobalCache->shaderCodeDictionary();
|
||||
|
||||
combinationBuilder.buildCombinations(
|
||||
combinationBuilder->buildCombinations(
|
||||
dict,
|
||||
[&](SkUniquePaintParamsID uniqueID) {
|
||||
GraphicsPipelineDesc desc;
|
||||
|
170
tests/graphite/CombinationBuilderTest.cpp
Normal file
170
tests/graphite/CombinationBuilderTest.cpp
Normal file
@ -0,0 +1,170 @@
|
||||
/*
|
||||
* 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 "include/core/SkCombinationBuilder.h"
|
||||
|
||||
using namespace::skgpu::graphite;
|
||||
|
||||
class CombinationBuilderTestAccess {
|
||||
public:
|
||||
static int NumCombinations(SkCombinationBuilder* builder) {
|
||||
return builder->numCombinations();
|
||||
}
|
||||
#ifdef SK_DEBUG
|
||||
static int Epoch(const SkCombinationBuilder& builder) {
|
||||
return builder.epoch();
|
||||
}
|
||||
static int Epoch(const SkCombinationOption& option) {
|
||||
return option.epoch();
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
namespace {
|
||||
|
||||
// For an entirely empty combination builder, both solid color shader and kSrcOver options
|
||||
// will be added
|
||||
void empty_test(Context *context, skiatest::Reporter* reporter) {
|
||||
SkCombinationBuilder builder(context);
|
||||
|
||||
REPORTER_ASSERT(reporter, CombinationBuilderTestAccess::NumCombinations(&builder) == 1);
|
||||
}
|
||||
|
||||
// It is expected that the builder will supply a default solid color shader if no other shader
|
||||
// option is provided
|
||||
void no_shader_option_test(Context *context, skiatest::Reporter* reporter) {
|
||||
SkCombinationBuilder builder(context);
|
||||
|
||||
builder.addOption(SkBlendMode::kSrcOver);
|
||||
|
||||
REPORTER_ASSERT(reporter, CombinationBuilderTestAccess::NumCombinations(&builder) == 1);
|
||||
}
|
||||
|
||||
// It is expected that the builder will supply a default kSrcOver blend mode if no other
|
||||
// options are added
|
||||
void no_blend_mode_option_test(Context *context, skiatest::Reporter* reporter) {
|
||||
SkCombinationBuilder builder(context);
|
||||
|
||||
builder.addOption(SkShaderType::kSolidColor);
|
||||
|
||||
REPORTER_ASSERT(reporter, CombinationBuilderTestAccess::NumCombinations(&builder) == 1);
|
||||
}
|
||||
|
||||
void big_test(Context *context, skiatest::Reporter* reporter) {
|
||||
SkCombinationBuilder builder(context);
|
||||
|
||||
static constexpr int kMinNumStops = 4;
|
||||
static constexpr int kMaxNumStops = 8;
|
||||
|
||||
// The resulting number of combinations are in braces
|
||||
//
|
||||
// builder {428}
|
||||
// |- {107} sweepGrad_0 {5} | blendShader_0 {102}
|
||||
// | 0 {6}: linearGrad_0 {5} | solid_0 {1}
|
||||
// | 1 {17}: linearGrad_1 {5} | blendShader_1 {12}
|
||||
// | 0 {6}: radGrad_0 {5} | solid_1 {1}
|
||||
// | 1 {2}: imageShader_0 {2}
|
||||
// |
|
||||
// |- {4} 4-built-in-blend-modes {4}
|
||||
|
||||
// first, shaders. First top-level option (sweepGrad_0)
|
||||
[[maybe_unused]] auto sweepGrad_0 = builder.addOption(SkShaderType::kSweepGradient,
|
||||
kMinNumStops, kMaxNumStops);
|
||||
|
||||
// Second top-level option (blendShader_0)
|
||||
auto blendShader_0 = builder.addOption(SkShaderType::kBlendShader);
|
||||
|
||||
// first child slot of blendShader_0
|
||||
{
|
||||
// first option (linearGrad_0)
|
||||
[[maybe_unused]] auto linearGrad_0 = blendShader_0.addChildOption(
|
||||
0, SkShaderType::kLinearGradient,
|
||||
kMinNumStops, kMaxNumStops);
|
||||
|
||||
// second option (solid_0)
|
||||
[[maybe_unused]] auto solid_0 = blendShader_0.addChildOption(0,
|
||||
SkShaderType::kSolidColor);
|
||||
}
|
||||
|
||||
// second child slot of blendShader_0
|
||||
{
|
||||
// first option (linearGrad_1)
|
||||
{
|
||||
[[maybe_unused]] auto linearGrad_1 = blendShader_0.addChildOption(
|
||||
1, SkShaderType::kLinearGradient,
|
||||
kMinNumStops, kMaxNumStops);
|
||||
}
|
||||
|
||||
// second option (blendShader_1)
|
||||
{
|
||||
auto blendShader_1 = blendShader_0.addChildOption(1, SkShaderType::kBlendShader);
|
||||
|
||||
// nested: first child slot of blendShader_1
|
||||
{
|
||||
// first option (radialGrad_0)
|
||||
[[maybe_unused]] auto radialGrad_0 = blendShader_1.addChildOption(
|
||||
0, SkShaderType::kRadialGradient,
|
||||
kMinNumStops, kMaxNumStops);
|
||||
|
||||
// second option (solid_1)
|
||||
[[maybe_unused]] auto solid_1 = blendShader_1.addChildOption(
|
||||
0, SkShaderType::kSolidColor);
|
||||
}
|
||||
|
||||
// nested: second child slot of blendShader_1
|
||||
{
|
||||
SkTileModePair tilingOptions[] = {
|
||||
{ SkTileMode::kRepeat, SkTileMode::kRepeat },
|
||||
{ SkTileMode::kClamp, SkTileMode::kClamp }
|
||||
};
|
||||
|
||||
// only option (imageShader_0)
|
||||
[[maybe_unused]] auto imageShader_0 = blendShader_1.addChildOption(
|
||||
1, SkShaderType::kImage,
|
||||
SkMakeSpan(tilingOptions));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// now, blend modes
|
||||
builder.addOption(SkBlendMode::kSrcOver);
|
||||
builder.addOption(SkBlendMode::kSrc);
|
||||
builder.addOption(SkBlendMode::kDstOver);
|
||||
builder.addOption(SkBlendMode::kDst);
|
||||
|
||||
REPORTER_ASSERT(reporter, CombinationBuilderTestAccess::NumCombinations(&builder) == 428);
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
void epoch_test(Context *context, skiatest::Reporter* reporter) {
|
||||
SkCombinationBuilder builder(context);
|
||||
|
||||
// Check that epochs are updated upon builder reset
|
||||
{
|
||||
SkCombinationOption solid_0 = builder.addOption(SkShaderType::kSolidColor);
|
||||
|
||||
int optionEpoch = CombinationBuilderTestAccess::Epoch(solid_0);
|
||||
REPORTER_ASSERT(reporter, optionEpoch == CombinationBuilderTestAccess::Epoch(builder));
|
||||
|
||||
builder.reset();
|
||||
|
||||
REPORTER_ASSERT(reporter, optionEpoch != CombinationBuilderTestAccess::Epoch(builder));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
DEF_GRAPHITE_TEST_FOR_CONTEXTS(CombinationBuilderTest, reporter, context) {
|
||||
empty_test(context, reporter);
|
||||
no_shader_option_test(context, reporter);
|
||||
no_blend_mode_option_test(context, reporter);
|
||||
big_test(context, reporter);
|
||||
SkDEBUGCODE(epoch_test(context, reporter));
|
||||
}
|
Loading…
Reference in New Issue
Block a user