Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
UniformManager.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2021 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
9
11
12// ensure that these types are the sizes the uniform data is expecting
13static_assert(sizeof(int32_t) == 4);
14static_assert(sizeof(float) == 4);
15static_assert(sizeof(SkHalf) == 2);
16
17namespace skgpu::graphite {
18
21
22 int dimension = SkSLTypeMatrixSize(type);
23 if (dimension > 0) {
24 // All SkSL matrices are square and can be interpreted as an array of column vectors
25 count = std::max(count, 1) * dimension;
26 } else {
27 dimension = SkSLTypeVecLength(type);
28 }
29 SkASSERT(1 <= dimension && dimension <= 4);
30
31 // Bump dimension up to 4 if the array or vec3 consumes 4 primitives per element
32 // NOTE: This affects the size, alignment already rounds up to a power of 2 automatically.
33 const bool isArray = count > Uniform::kNonArray;
34 if ((isArray && LayoutRules::AlignArraysAsVec4(fLayout)) ||
35 (dimension == 3 && (isArray || LayoutRules::PadVec3Size(fLayout)))) {
36 dimension = 4;
37 }
38
39 const int primitiveSize = LayoutRules::UseFullPrecision(fLayout) ||
41 const int align = SkNextPow2(dimension) * primitiveSize;
42 const int alignedOffset = SkAlignTo(fOffset, align);
43 fOffset = alignedOffset + dimension * primitiveSize * std::max(count, 1);
44 fReqAlignment = std::max(fReqAlignment, align);
45
46 return alignedOffset;
47}
48
49//////////////////////////////////////////////////////////////////////////////
50
52 size_t size = SkAlignTo(fStorage.size(), fReqAlignment);
53 size_t paddingSize = size - fStorage.size();
54 if (paddingSize > 0) {
55 char* padding = fStorage.append(paddingSize);
56 memset(padding, 0, paddingSize);
57 }
58 return UniformDataBlock(SkSpan(fStorage.begin(), size));
59}
60
62 fStorage.clear();
63 fLayout = layout;
64 fReqAlignment = 0;
65 fWrotePaintColor = false;
66
67#ifdef SK_DEBUG
68 fOffsetCalculator = UniformOffsetCalculator(layout, 0);
69 fExpectedUniforms = {};
70 fExpectedUniformIndex = 0;
71#endif
72}
73
74static std::pair<SkSLType, int> adjust_for_matrix_type(SkSLType type, int count) {
75 // All Layouts flatten matrices and arrays of matrices into arrays of columns, so update
76 // 'type' to be the column type and either multiply 'count' by the number of columns for
77 // arrays of matrices, or set to exactly the number of columns for a "non-array" matrix.
78 switch(type) {
79 case SkSLType::kFloat2x2: return {SkSLType::kFloat2, 2*std::max(1, count)};
80 case SkSLType::kFloat3x3: return {SkSLType::kFloat3, 3*std::max(1, count)};
81 case SkSLType::kFloat4x4: return {SkSLType::kFloat4, 4*std::max(1, count)};
82
83 case SkSLType::kHalf2x2: return {SkSLType::kHalf2, 2*std::max(1, count)};
84 case SkSLType::kHalf3x3: return {SkSLType::kHalf3, 3*std::max(1, count)};
85 case SkSLType::kHalf4x4: return {SkSLType::kHalf4, 4*std::max(1, count)};
86
87 // Otherwise leave type and count alone.
88 default: return {type, count};
89 }
90}
91
92void UniformManager::write(const Uniform& u, const void* data) {
94 SkASSERT(!u.isPaintColor()); // Must go through writePaintColor()
95
96 auto [type, count] = adjust_for_matrix_type(u.type(), u.count());
97 SkASSERT(SkSLTypeMatrixSize(type) < 0); // Matrix types should have been flattened
98
99 const bool fullPrecision = LayoutRules::UseFullPrecision(fLayout) || !IsHalfVector(type);
100 if (count == Uniform::kNonArray) {
101 if (fullPrecision) {
102 switch(SkSLTypeVecLength(type)) {
103 case 1: this->write<1, /*Half=*/false>(data, type); break;
104 case 2: this->write<2, /*Half=*/false>(data, type); break;
105 case 3: this->write<3, /*Half=*/false>(data, type); break;
106 case 4: this->write<4, /*Half=*/false>(data, type); break;
107 }
108 } else {
109 switch(SkSLTypeVecLength(type)) {
110 case 1: this->write<1, /*Half=*/true>(data, type); break;
111 case 2: this->write<2, /*Half=*/true>(data, type); break;
112 case 3: this->write<3, /*Half=*/true>(data, type); break;
113 case 4: this->write<4, /*Half=*/true>(data, type); break;
114 }
115 }
116 } else {
117 if (fullPrecision) {
118 switch(SkSLTypeVecLength(type)) {
119 case 1: this->writeArray<1, /*Half=*/false>(data, count, type); break;
120 case 2: this->writeArray<2, /*Half=*/false>(data, count, type); break;
121 case 3: this->writeArray<3, /*Half=*/false>(data, count, type); break;
122 case 4: this->writeArray<4, /*Half=*/false>(data, count, type); break;
123 }
124 } else {
125 switch(SkSLTypeVecLength(type)) {
126 case 1: this->writeArray<1, /*Half=*/true>(data, count, type); break;
127 case 2: this->writeArray<2, /*Half=*/true>(data, count, type); break;
128 case 3: this->writeArray<3, /*Half=*/true>(data, count, type); break;
129 case 4: this->writeArray<4, /*Half=*/true>(data, count, type); break;
130 }
131 }
132 }
133}
134
135#ifdef SK_DEBUG
136
137bool UniformManager::checkExpected(const void* dst, SkSLType type, int count) {
138 if (fExpectedUniformIndex >= (int) fExpectedUniforms.size()) {
139 // A write() outside of a UniformExpectationsVisitor or too many uniforms written for what
140 // is expected.
141 return false;
142 }
143
144 const Uniform& expected = fExpectedUniforms[fExpectedUniformIndex++];
145 if (!SkSLTypeCanBeUniformValue(expected.type())) {
146 // Not all types are supported as uniforms or supported by UniformManager
147 return false;
148 }
149
150 auto [expectedType, expectedCount] = adjust_for_matrix_type(expected.type(), expected.count());
151 if (expectedType != type || expectedCount != count) {
152 return false;
153 }
154
155 if (dst) {
156 // If we have 'dst', it's the aligned starting offset of the uniform being checked, so
157 // subtracting the address of the first byte in fStorage gives us the offset.
158 int offset = static_cast<int>(reinterpret_cast<intptr_t>(dst) -
159 reinterpret_cast<intptr_t>(fStorage.data()));
160 // Pass original expected type and count to the offset calculator for validation.
161 if (offset != fOffsetCalculator.advanceOffset(expected.type(), expected.count())) {
162 return false;
163 }
164 if (fReqAlignment != fOffsetCalculator.requiredAlignment()) {
165 return false;
166 }
167 // And if it is the paint color uniform, we should not have already written it
168 return !(fWrotePaintColor && expected.isPaintColor());
169 } else {
170 // If 'dst' is null, it's an already-visited paint color uniform, so it's not being written
171 // and not changing the offset.
172 SkASSERT(fWrotePaintColor);
173 return expected.isPaintColor();
174 }
175}
176
177bool UniformManager::isReset() const {
178 return fStorage.empty();
179}
180
181void UniformManager::setExpectedUniforms(SkSpan<const Uniform> expected) {
182 fExpectedUniforms = expected;
183 fExpectedUniformIndex = 0;
184}
185
186void UniformManager::doneWithExpectedUniforms() {
187 SkASSERT(fExpectedUniformIndex == static_cast<int>(fExpectedUniforms.size()));
188 fExpectedUniforms = {};
189}
190
191#endif // SK_DEBUG
192
193} // namespace skgpu::graphite
int count
static constexpr size_t SkAlignTo(size_t x, size_t alignment)
Definition SkAlign.h:33
#define SkASSERT(cond)
Definition SkAssert.h:116
uint16_t SkHalf
Definition SkHalf.h:16
static int SkNextPow2(int value)
Definition SkMathPriv.h:272
int SkSLTypeMatrixSize(SkSLType type)
bool SkSLTypeIsFullPrecisionNumericType(SkSLType type)
static constexpr bool SkSLTypeCanBeUniformValue(SkSLType type)
SkSLType
static constexpr int SkSLTypeVecLength(SkSLType type)
int size() const
Definition SkTDArray.h:138
bool empty() const
Definition SkTDArray.h:135
T * data()
Definition SkTDArray.h:148
T * begin()
Definition SkTDArray.h:150
T * append()
Definition SkTDArray.h:191
void clear()
Definition SkTDArray.h:175
void writeArray(SkSpan< const SkV4 > v)
UniformDataBlock finishUniformDataBlock()
void resetWithNewLayout(Layout layout)
int advanceOffset(SkSLType type, int count=Uniform::kNonArray)
constexpr SkSLType type() const
Definition Uniform.h:43
constexpr bool isPaintColor() const
Definition Uniform.h:46
constexpr int count() const
Definition Uniform.h:44
dst
Definition cp.py:12
static constexpr bool UseFullPrecision(Layout layout)
static constexpr bool AlignArraysAsVec4(Layout layout)
static constexpr bool PadVec3Size(Layout layout)
static std::pair< SkSLType, int > adjust_for_matrix_type(SkSLType type, int count)
Point offset