Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
KeyTest.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2022 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "tests/Test.h"
9
10
15
16using namespace skgpu::graphite;
17
18namespace {
19
20void add_block(PaintParamsKeyBuilder* builder, int snippetID) {
21 builder->beginBlock(snippetID);
22 builder->endBlock();
23}
24
25PaintParamsKey create_key(const ShaderCodeDictionary* dict, int snippetID, SkArenaAlloc* arena) {
27 add_block(&builder, snippetID);
28
30 return keyView->clone(arena);
31}
32
33bool coeff_equal(SkBlendModeCoeff skCoeff, skgpu::BlendCoeff gpuCoeff) {
34 switch(skCoeff) {
36 case SkBlendModeCoeff::kOne: return skgpu::BlendCoeff::kOne == gpuCoeff;
37 case SkBlendModeCoeff::kSC: return skgpu::BlendCoeff::kSC == gpuCoeff;
38 case SkBlendModeCoeff::kISC: return skgpu::BlendCoeff::kISC == gpuCoeff;
39 case SkBlendModeCoeff::kDC: return skgpu::BlendCoeff::kDC == gpuCoeff;
40 case SkBlendModeCoeff::kIDC: return skgpu::BlendCoeff::kIDC == gpuCoeff;
41 case SkBlendModeCoeff::kSA: return skgpu::BlendCoeff::kSA == gpuCoeff;
42 case SkBlendModeCoeff::kISA: return skgpu::BlendCoeff::kISA == gpuCoeff;
43 case SkBlendModeCoeff::kDA: return skgpu::BlendCoeff::kDA == gpuCoeff;
44 case SkBlendModeCoeff::kIDA: return skgpu::BlendCoeff::kIDA == gpuCoeff;
45 default: return false;
46 }
47}
48
49} // anonymous namespace
50
51// These are intended to be unit tests of the PaintParamsKeyBuilder and PaintParamsKey.
52DEF_GRAPHITE_TEST_FOR_ALL_CONTEXTS(KeyWithInvalidCodeSnippetIDTest, reporter, context,
54 SkArenaAlloc arena{256};
55 ShaderCodeDictionary* dict = context->priv().shaderCodeDictionary();
56
57 // A builder without any data is invalid. The Builder and the PaintParamKeys can include
58 // invalid IDs without themselves becoming invalid. Normally adding an invalid ID triggers an
59 // assert in debug builds, since the properly functioning key system should never encounter an
60 // invalid ID.
61 PaintParamsKeyBuilder builder(dict);
62 AutoLockBuilderAsKey keyView{&builder};
63 REPORTER_ASSERT(reporter, !keyView->isValid());
65
66 // However, if the program gets in a malformed state on release builds, the key
67 // could contain an invalid ID. In that case the invalid snippet IDs are detected when
68 // reconstructing the key into an effect tree for SkSL generation. To test this, we manually
69 // construct an invalid span and test that it returns a null shader node tree when treated as
70 // a PaintParamsKey.
71 // NOTE: This is intentionally abusing memory to create a corrupt scenario and is dependent on
72 // the structure of PaintParamsKey (just SkSpan<const int32_t>).
73 int32_t invalidKeyData[3] = {(int32_t) BuiltInCodeSnippetID::kSolidColorShader,
75 (int32_t) BuiltInCodeSnippetID::kFixedFunctionSrcBlendMode};
76 SkSpan<const int32_t> invalidKeySpan{invalidKeyData, std::size(invalidKeyData)*sizeof(int32_t)};
77 const PaintParamsKey* fakeKey = reinterpret_cast<const PaintParamsKey*>(&invalidKeySpan);
78 REPORTER_ASSERT(reporter, fakeKey->getRootNodes(dict, &arena).empty());
79}
80
81DEF_GRAPHITE_TEST_FOR_ALL_CONTEXTS(KeyEqualityChecksSnippetID, reporter, context,
83 SkArenaAlloc arena{256};
84 ShaderCodeDictionary* dict = context->priv().shaderCodeDictionary();
85
86 int userSnippetID1 = dict->addRuntimeEffectSnippet("key1");
87 int userSnippetID2 = dict->addRuntimeEffectSnippet("key2");
88
89 PaintParamsKey keyA = create_key(dict, userSnippetID1, &arena);
90 PaintParamsKey keyB = create_key(dict, userSnippetID1, &arena);
91 PaintParamsKey keyC = create_key(dict, userSnippetID2, &arena);
92
93 // Verify that keyA matches keyB, and that it does not match keyC.
94 REPORTER_ASSERT(reporter, keyA == keyB);
95 REPORTER_ASSERT(reporter, keyA != keyC);
96 REPORTER_ASSERT(reporter, !(keyA == keyC));
97 REPORTER_ASSERT(reporter, !(keyA != keyB));
98}
99
100DEF_GRAPHITE_TEST_FOR_ALL_CONTEXTS(ShaderInfoDetectsFixedFunctionBlend, reporter, context,
102 ShaderCodeDictionary* dict = context->priv().shaderCodeDictionary();
103
104 for (int bm = 0; bm <= (int) SkBlendMode::kLastCoeffMode; ++bm) {
105 PaintParamsKeyBuilder builder(dict);
107 UniquePaintParamsID paintID = dict->findOrCreate(&builder);
108
109 ShaderInfo shaderInfo{paintID, dict, /*rteDict=*/nullptr, /*ssboIndex=*/""};
110
111 SkBlendModeCoeff expectedSrc, expectedDst;
113 &expectedSrc, &expectedDst));
114 REPORTER_ASSERT(reporter, coeff_equal(expectedSrc, shaderInfo.blendInfo().fSrcBlend));
115 REPORTER_ASSERT(reporter, coeff_equal(expectedDst, shaderInfo.blendInfo().fDstBlend));
116 REPORTER_ASSERT(reporter, shaderInfo.blendInfo().fEquation == skgpu::BlendEquation::kAdd);
117 REPORTER_ASSERT(reporter, shaderInfo.blendInfo().fBlendConstant == SK_PMColor4fTRANSPARENT);
118
119 bool expectedWriteColor = BlendModifiesDst(skgpu::BlendEquation::kAdd,
120 shaderInfo.blendInfo().fSrcBlend,
121 shaderInfo.blendInfo().fDstBlend);
122 REPORTER_ASSERT(reporter, shaderInfo.blendInfo().fWritesColor == expectedWriteColor);
123 }
124}
125
126// TODO: Add unit tests for converting a complex key to a ShaderInfo
reporter
SK_API bool SkBlendMode_AsCoeff(SkBlendMode mode, SkBlendModeCoeff *src, SkBlendModeCoeff *dst)
SkBlendMode
Definition SkBlendMode.h:38
@ kLastCoeffMode
last porter duff blend mode
SkBlendModeCoeff
Definition SkBlendMode.h:84
static size_t add_block(SkSBlockAllocator< N > &pool)
constexpr SkPMColor4f SK_PMColor4fTRANSPARENT
#define DEF_GRAPHITE_TEST_FOR_ALL_CONTEXTS(name, reporter, graphite_ctx, ctsEnforcement)
Definition Test.h:373
#define REPORTER_ASSERT(r, cond,...)
Definition Test.h:286
Type::kYUV Type::kRGBA() int(0.7 *637)
static constexpr PaintParamsKey Invalid()
SkSpan< const ShaderNode * > getRootNodes(const ShaderCodeDictionary *, SkArenaAlloc *) const
UniquePaintParamsID findOrCreate(PaintParamsKeyBuilder *) SK_EXCLUDES(fSpinLock)
static constexpr int kSkiaBuiltInReservedCnt
static constexpr int kFixedFunctionBlendModeIDOffset
BlendCoeff
Definition Blend.h:60