1 /*
2 * Copyright 2020 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 "src/gpu/ganesh/GrUniformDataManager.h"
9
10 #include "include/private/base/SkAssert.h"
11 #include "include/private/base/SkTemplates.h"
12 #include "src/base/SkHalf.h"
13 #include "src/core/SkSLTypeShared.h"
14 #include "src/gpu/ganesh/GrShaderVar.h"
15
16 #include <cstring>
17
18 // ensure that these types are the sizes the uniform data is expecting
19 static_assert(sizeof(int32_t) == 4);
20 static_assert(sizeof(float) == 4);
21 static_assert(sizeof(short) == 2);
22 static_assert(sizeof(SkHalf) == 2);
23
GrUniformDataManager(uint32_t uniformCount,uint32_t uniformSize)24 GrUniformDataManager::GrUniformDataManager(uint32_t uniformCount, uint32_t uniformSize)
25 : fUniformSize(uniformSize)
26 , fUniformsDirty(false) {
27 fUniformData.reset(uniformSize);
28 fUniforms.push_back_n(uniformCount);
29 // subclasses fill in the uniforms in their constructor
30 }
31
getBufferPtrAndMarkDirty(const Uniform & uni) const32 void* GrUniformDataManager::getBufferPtrAndMarkDirty(const Uniform& uni) const {
33 fUniformsDirty = true;
34 return static_cast<char*>(fUniformData.get()) + uni.fOffset;
35 }
36
copyUniforms(void * dest,const void * src,int numUniforms,SkSLType uniformType) const37 int GrUniformDataManager::copyUniforms(void* dest,
38 const void* src,
39 int numUniforms,
40 SkSLType uniformType) const {
41 if (fWrite16BitUniforms) {
42 switch (uniformType) {
43 case SkSLType::kHalf:
44 case SkSLType::kHalf2:
45 case SkSLType::kHalf3:
46 case SkSLType::kHalf4:
47 case SkSLType::kHalf2x2:
48 case SkSLType::kHalf3x3:
49 case SkSLType::kHalf4x4: {
50 const float* floatBits = static_cast<const float*>(src);
51 SkHalf* halfBits = static_cast<SkHalf*>(dest);
52 while (numUniforms-- > 0) {
53 *halfBits++ = SkFloatToHalf(*floatBits++);
54 }
55 return 2;
56 }
57
58 case SkSLType::kShort:
59 case SkSLType::kShort2:
60 case SkSLType::kShort3:
61 case SkSLType::kShort4:
62 case SkSLType::kUShort:
63 case SkSLType::kUShort2:
64 case SkSLType::kUShort3:
65 case SkSLType::kUShort4: {
66 const int32_t* intBits = static_cast<const int32_t*>(src);
67 short* shortBits = static_cast<short*>(dest);
68 while (numUniforms-- > 0) {
69 *shortBits++ = (short)(*intBits++);
70 }
71 return 2;
72 }
73
74 default:
75 // Fall through to memcpy below.
76 break;
77 }
78 }
79
80 memcpy(dest, src, numUniforms * 4);
81 return 4;
82 }
83
84 template <int N, SkSLType FullType, SkSLType HalfType>
set(UniformHandle u,const void * v) const85 void GrUniformDataManager::set(UniformHandle u, const void* v) const {
86 const Uniform& uni = fUniforms[u.toIndex()];
87 SkASSERT(uni.fType == FullType || uni.fType == HalfType);
88 SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
89 void* buffer = this->getBufferPtrAndMarkDirty(uni);
90 this->copyUniforms(buffer, v, N, uni.fType);
91 }
92
93 template <int N, SkSLType FullType, SkSLType HalfType>
setv(UniformHandle u,int arrayCount,const void * v) const94 void GrUniformDataManager::setv(UniformHandle u, int arrayCount, const void* v) const {
95 const Uniform& uni = fUniforms[u.toIndex()];
96 SkASSERT(uni.fType == FullType || uni.fType == HalfType);
97 SkASSERT(arrayCount > 0);
98 SkASSERT(arrayCount <= uni.fArrayCount ||
99 (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
100
101 void* buffer = this->getBufferPtrAndMarkDirty(uni);
102 if constexpr (N == 4) {
103 this->copyUniforms(buffer, v, arrayCount * 4, uni.fType);
104 } else {
105 for (int i = 0; i < arrayCount; ++i) {
106 int uniformSize = this->copyUniforms(buffer, v, N, uni.fType);
107 buffer = SkTAddOffset<void>(buffer, /*numUniforms*/4 * uniformSize);
108 v = static_cast<const char*>(v) + N * 4;
109 }
110 }
111 }
112
set1i(UniformHandle u,int32_t i0) const113 void GrUniformDataManager::set1i(UniformHandle u, int32_t i0) const {
114 this->set<1, SkSLType::kInt, SkSLType::kShort>(u, &i0);
115 }
116
set1iv(UniformHandle u,int arrayCount,const int32_t v[]) const117 void GrUniformDataManager::set1iv(UniformHandle u,
118 int arrayCount,
119 const int32_t v[]) const {
120 this->setv<1, SkSLType::kInt, SkSLType::kShort>(u, arrayCount, v);
121 }
122
set1f(UniformHandle u,float v0) const123 void GrUniformDataManager::set1f(UniformHandle u, float v0) const {
124 this->set<1, SkSLType::kFloat, SkSLType::kHalf>(u, &v0);
125 }
126
set1fv(UniformHandle u,int arrayCount,const float v[]) const127 void GrUniformDataManager::set1fv(UniformHandle u,
128 int arrayCount,
129 const float v[]) const {
130 this->setv<1, SkSLType::kFloat, SkSLType::kHalf>(u, arrayCount, v);
131 }
132
set2i(UniformHandle u,int32_t i0,int32_t i1) const133 void GrUniformDataManager::set2i(UniformHandle u, int32_t i0, int32_t i1) const {
134 int32_t v[2] = { i0, i1 };
135 this->set<2, SkSLType::kInt2, SkSLType::kShort2>(u, v);
136 }
137
set2iv(UniformHandle u,int arrayCount,const int32_t v[]) const138 void GrUniformDataManager::set2iv(UniformHandle u,
139 int arrayCount,
140 const int32_t v[]) const {
141 this->setv<2, SkSLType::kInt2, SkSLType::kShort2>(u, arrayCount, v);
142 }
143
set2f(UniformHandle u,float v0,float v1) const144 void GrUniformDataManager::set2f(UniformHandle u, float v0, float v1) const {
145 float v[2] = { v0, v1 };
146 this->set<2, SkSLType::kFloat2, SkSLType::kHalf2>(u, v);
147 }
148
set2fv(UniformHandle u,int arrayCount,const float v[]) const149 void GrUniformDataManager::set2fv(UniformHandle u,
150 int arrayCount,
151 const float v[]) const {
152 this->setv<2, SkSLType::kFloat2, SkSLType::kHalf2>(u, arrayCount, v);
153 }
154
set3i(UniformHandle u,int32_t i0,int32_t i1,int32_t i2) const155 void GrUniformDataManager::set3i(UniformHandle u,
156 int32_t i0,
157 int32_t i1,
158 int32_t i2) const {
159 int32_t v[3] = { i0, i1, i2 };
160 this->set<3, SkSLType::kInt3, SkSLType::kShort3>(u, v);
161 }
162
set3iv(UniformHandle u,int arrayCount,const int32_t v[]) const163 void GrUniformDataManager::set3iv(UniformHandle u,
164 int arrayCount,
165 const int32_t v[]) const {
166 this->setv<3, SkSLType::kInt3, SkSLType::kShort3>(u, arrayCount, v);
167 }
168
set3f(UniformHandle u,float v0,float v1,float v2) const169 void GrUniformDataManager::set3f(UniformHandle u, float v0, float v1, float v2) const {
170 float v[3] = { v0, v1, v2 };
171 this->set<3, SkSLType::kFloat3, SkSLType::kHalf3>(u, v);
172 }
173
set3fv(UniformHandle u,int arrayCount,const float v[]) const174 void GrUniformDataManager::set3fv(UniformHandle u,
175 int arrayCount,
176 const float v[]) const {
177 this->setv<3, SkSLType::kFloat3, SkSLType::kHalf3>(u, arrayCount, v);
178 }
179
set4i(UniformHandle u,int32_t i0,int32_t i1,int32_t i2,int32_t i3) const180 void GrUniformDataManager::set4i(UniformHandle u,
181 int32_t i0,
182 int32_t i1,
183 int32_t i2,
184 int32_t i3) const {
185 int32_t v[4] = { i0, i1, i2, i3 };
186 this->set<4, SkSLType::kInt4, SkSLType::kShort4>(u, v);
187 }
188
set4iv(UniformHandle u,int arrayCount,const int32_t v[]) const189 void GrUniformDataManager::set4iv(UniformHandle u,
190 int arrayCount,
191 const int32_t v[]) const {
192 this->setv<4, SkSLType::kInt4, SkSLType::kShort4>(u, arrayCount, v);
193 }
194
set4f(UniformHandle u,float v0,float v1,float v2,float v3) const195 void GrUniformDataManager::set4f(UniformHandle u,
196 float v0,
197 float v1,
198 float v2,
199 float v3) const {
200 float v[4] = { v0, v1, v2, v3 };
201 this->set<4, SkSLType::kFloat4, SkSLType::kHalf4>(u, v);
202 }
203
set4fv(UniformHandle u,int arrayCount,const float v[]) const204 void GrUniformDataManager::set4fv(UniformHandle u,
205 int arrayCount,
206 const float v[]) const {
207 this->setv<4, SkSLType::kFloat4, SkSLType::kHalf4>(u, arrayCount, v);
208 }
209
setMatrix2f(UniformHandle u,const float matrix[]) const210 void GrUniformDataManager::setMatrix2f(UniformHandle u, const float matrix[]) const {
211 this->setMatrices<2, SkSLType::kFloat2x2, SkSLType::kHalf2x2>(u, 1, matrix);
212 }
213
setMatrix2fv(UniformHandle u,int arrayCount,const float m[]) const214 void GrUniformDataManager::setMatrix2fv(UniformHandle u, int arrayCount, const float m[]) const {
215 this->setMatrices<2, SkSLType::kFloat2x2, SkSLType::kHalf2x2>(u, arrayCount, m);
216 }
217
setMatrix3f(UniformHandle u,const float matrix[]) const218 void GrUniformDataManager::setMatrix3f(UniformHandle u, const float matrix[]) const {
219 this->setMatrices<3, SkSLType::kFloat3x3, SkSLType::kHalf3x3>(u, 1, matrix);
220 }
221
setMatrix3fv(UniformHandle u,int arrayCount,const float m[]) const222 void GrUniformDataManager::setMatrix3fv(UniformHandle u, int arrayCount, const float m[]) const {
223 this->setMatrices<3, SkSLType::kFloat3x3, SkSLType::kHalf3x3>(u, arrayCount, m);
224 }
225
setMatrix4f(UniformHandle u,const float matrix[]) const226 void GrUniformDataManager::setMatrix4f(UniformHandle u, const float matrix[]) const {
227 this->setMatrices<4, SkSLType::kFloat4x4, SkSLType::kHalf4x4>(u, 1, matrix);
228 }
229
setMatrix4fv(UniformHandle u,int arrayCount,const float m[]) const230 void GrUniformDataManager::setMatrix4fv(UniformHandle u, int arrayCount, const float m[]) const {
231 this->setMatrices<4, SkSLType::kFloat4x4, SkSLType::kHalf4x4>(u, arrayCount, m);
232 }
233
234 template <int N, SkSLType FullType, SkSLType HalfType>
setMatrices(UniformHandle u,int arrayCount,const float matrices[]) const235 inline void GrUniformDataManager::setMatrices(UniformHandle u,
236 int arrayCount,
237 const float matrices[]) const {
238 const Uniform& uni = fUniforms[u.toIndex()];
239 SkASSERT(uni.fType == FullType || uni.fType == HalfType);
240 SkASSERT(arrayCount > 0);
241 SkASSERT(arrayCount <= uni.fArrayCount ||
242 (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
243
244 void* buffer = this->getBufferPtrAndMarkDirty(uni);
245 if constexpr (N == 4) {
246 this->copyUniforms(buffer, matrices, arrayCount * 16, uni.fType);
247 } else {
248 for (int i = 0; i < arrayCount; ++i) {
249 const float* matrix = &matrices[N * N * i];
250 for (int j = 0; j < N; ++j) {
251 int uniformSize = this->copyUniforms(buffer, &matrix[j * N], N, uni.fType);
252 buffer = SkTAddOffset<void>(buffer, /*numUniforms*/4 * uniformSize);
253 }
254 }
255 }
256 }
257