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 "src/base/SkHalf.h"
11 #include "src/gpu/ganesh/GrShaderVar.h"
12
13 // ensure that these types are the sizes the uniform data is expecting
14 static_assert(sizeof(int32_t) == 4);
15 static_assert(sizeof(float) == 4);
16 static_assert(sizeof(short) == 2);
17 static_assert(sizeof(SkHalf) == 2);
18
GrUniformDataManager(uint32_t uniformCount,uint32_t uniformSize)19 GrUniformDataManager::GrUniformDataManager(uint32_t uniformCount, uint32_t uniformSize)
20 : fUniformSize(uniformSize)
21 , fUniformsDirty(false) {
22 fUniformData.reset(uniformSize);
23 fUniforms.push_back_n(uniformCount);
24 // subclasses fill in the uniforms in their constructor
25 }
26
getBufferPtrAndMarkDirty(const Uniform & uni) const27 void* GrUniformDataManager::getBufferPtrAndMarkDirty(const Uniform& uni) const {
28 fUniformsDirty = true;
29 return static_cast<char*>(fUniformData.get()) + uni.fOffset;
30 }
31
copyUniforms(void * dest,const void * src,int numUniforms,SkSLType uniformType) const32 int GrUniformDataManager::copyUniforms(void* dest,
33 const void* src,
34 int numUniforms,
35 SkSLType uniformType) const {
36 if (fWrite16BitUniforms) {
37 switch (uniformType) {
38 case SkSLType::kHalf:
39 case SkSLType::kHalf2:
40 case SkSLType::kHalf3:
41 case SkSLType::kHalf4:
42 case SkSLType::kHalf2x2:
43 case SkSLType::kHalf3x3:
44 case SkSLType::kHalf4x4: {
45 const float* floatBits = static_cast<const float*>(src);
46 SkHalf* halfBits = static_cast<SkHalf*>(dest);
47 while (numUniforms-- > 0) {
48 *halfBits++ = SkFloatToHalf(*floatBits++);
49 }
50 return 2;
51 }
52
53 case SkSLType::kShort:
54 case SkSLType::kShort2:
55 case SkSLType::kShort3:
56 case SkSLType::kShort4:
57 case SkSLType::kUShort:
58 case SkSLType::kUShort2:
59 case SkSLType::kUShort3:
60 case SkSLType::kUShort4: {
61 const int32_t* intBits = static_cast<const int32_t*>(src);
62 short* shortBits = static_cast<short*>(dest);
63 while (numUniforms-- > 0) {
64 *shortBits++ = (short)(*intBits++);
65 }
66 return 2;
67 }
68
69 default:
70 // Fall through to memcpy below.
71 break;
72 }
73 }
74
75 memcpy(dest, src, numUniforms * 4);
76 return 4;
77 }
78
79 template <int N, SkSLType FullType, SkSLType HalfType>
set(UniformHandle u,const void * v) const80 void GrUniformDataManager::set(UniformHandle u, const void* v) const {
81 const Uniform& uni = fUniforms[u.toIndex()];
82 SkASSERT(uni.fType == FullType || uni.fType == HalfType);
83 SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
84 void* buffer = this->getBufferPtrAndMarkDirty(uni);
85 this->copyUniforms(buffer, v, N, uni.fType);
86 }
87
88 template <int N, SkSLType FullType, SkSLType HalfType>
setv(UniformHandle u,int arrayCount,const void * v) const89 void GrUniformDataManager::setv(UniformHandle u, int arrayCount, const void* v) const {
90 const Uniform& uni = fUniforms[u.toIndex()];
91 SkASSERT(uni.fType == FullType || uni.fType == HalfType);
92 SkASSERT(arrayCount > 0);
93 SkASSERT(arrayCount <= uni.fArrayCount ||
94 (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
95
96 void* buffer = this->getBufferPtrAndMarkDirty(uni);
97 if constexpr (N == 4) {
98 this->copyUniforms(buffer, v, arrayCount * 4, uni.fType);
99 } else {
100 for (int i = 0; i < arrayCount; ++i) {
101 int uniformSize = this->copyUniforms(buffer, v, N, uni.fType);
102 buffer = SkTAddOffset<void>(buffer, /*numUniforms*/4 * uniformSize);
103 v = static_cast<const char*>(v) + N * 4;
104 }
105 }
106 }
107
set1i(UniformHandle u,int32_t i0) const108 void GrUniformDataManager::set1i(UniformHandle u, int32_t i0) const {
109 this->set<1, SkSLType::kInt, SkSLType::kShort>(u, &i0);
110 }
111
set1iv(UniformHandle u,int arrayCount,const int32_t v[]) const112 void GrUniformDataManager::set1iv(UniformHandle u,
113 int arrayCount,
114 const int32_t v[]) const {
115 this->setv<1, SkSLType::kInt, SkSLType::kShort>(u, arrayCount, v);
116 }
117
set1f(UniformHandle u,float v0) const118 void GrUniformDataManager::set1f(UniformHandle u, float v0) const {
119 this->set<1, SkSLType::kFloat, SkSLType::kHalf>(u, &v0);
120 }
121
set1fv(UniformHandle u,int arrayCount,const float v[]) const122 void GrUniformDataManager::set1fv(UniformHandle u,
123 int arrayCount,
124 const float v[]) const {
125 this->setv<1, SkSLType::kFloat, SkSLType::kHalf>(u, arrayCount, v);
126 }
127
set2i(UniformHandle u,int32_t i0,int32_t i1) const128 void GrUniformDataManager::set2i(UniformHandle u, int32_t i0, int32_t i1) const {
129 int32_t v[2] = { i0, i1 };
130 this->set<2, SkSLType::kInt2, SkSLType::kShort2>(u, v);
131 }
132
set2iv(UniformHandle u,int arrayCount,const int32_t v[]) const133 void GrUniformDataManager::set2iv(UniformHandle u,
134 int arrayCount,
135 const int32_t v[]) const {
136 this->setv<2, SkSLType::kInt2, SkSLType::kShort2>(u, arrayCount, v);
137 }
138
set2f(UniformHandle u,float v0,float v1) const139 void GrUniformDataManager::set2f(UniformHandle u, float v0, float v1) const {
140 float v[2] = { v0, v1 };
141 this->set<2, SkSLType::kFloat2, SkSLType::kHalf2>(u, v);
142 }
143
set2fv(UniformHandle u,int arrayCount,const float v[]) const144 void GrUniformDataManager::set2fv(UniformHandle u,
145 int arrayCount,
146 const float v[]) const {
147 this->setv<2, SkSLType::kFloat2, SkSLType::kHalf2>(u, arrayCount, v);
148 }
149
set3i(UniformHandle u,int32_t i0,int32_t i1,int32_t i2) const150 void GrUniformDataManager::set3i(UniformHandle u,
151 int32_t i0,
152 int32_t i1,
153 int32_t i2) const {
154 int32_t v[3] = { i0, i1, i2 };
155 this->set<3, SkSLType::kInt3, SkSLType::kShort3>(u, v);
156 }
157
set3iv(UniformHandle u,int arrayCount,const int32_t v[]) const158 void GrUniformDataManager::set3iv(UniformHandle u,
159 int arrayCount,
160 const int32_t v[]) const {
161 this->setv<3, SkSLType::kInt3, SkSLType::kShort3>(u, arrayCount, v);
162 }
163
set3f(UniformHandle u,float v0,float v1,float v2) const164 void GrUniformDataManager::set3f(UniformHandle u, float v0, float v1, float v2) const {
165 float v[3] = { v0, v1, v2 };
166 this->set<3, SkSLType::kFloat3, SkSLType::kHalf3>(u, v);
167 }
168
set3fv(UniformHandle u,int arrayCount,const float v[]) const169 void GrUniformDataManager::set3fv(UniformHandle u,
170 int arrayCount,
171 const float v[]) const {
172 this->setv<3, SkSLType::kFloat3, SkSLType::kHalf3>(u, arrayCount, v);
173 }
174
set4i(UniformHandle u,int32_t i0,int32_t i1,int32_t i2,int32_t i3) const175 void GrUniformDataManager::set4i(UniformHandle u,
176 int32_t i0,
177 int32_t i1,
178 int32_t i2,
179 int32_t i3) const {
180 int32_t v[4] = { i0, i1, i2, i3 };
181 this->set<4, SkSLType::kInt4, SkSLType::kShort4>(u, v);
182 }
183
set4iv(UniformHandle u,int arrayCount,const int32_t v[]) const184 void GrUniformDataManager::set4iv(UniformHandle u,
185 int arrayCount,
186 const int32_t v[]) const {
187 this->setv<4, SkSLType::kInt4, SkSLType::kShort4>(u, arrayCount, v);
188 }
189
set4f(UniformHandle u,float v0,float v1,float v2,float v3) const190 void GrUniformDataManager::set4f(UniformHandle u,
191 float v0,
192 float v1,
193 float v2,
194 float v3) const {
195 float v[4] = { v0, v1, v2, v3 };
196 this->set<4, SkSLType::kFloat4, SkSLType::kHalf4>(u, v);
197 }
198
set4fv(UniformHandle u,int arrayCount,const float v[]) const199 void GrUniformDataManager::set4fv(UniformHandle u,
200 int arrayCount,
201 const float v[]) const {
202 this->setv<4, SkSLType::kFloat4, SkSLType::kHalf4>(u, arrayCount, v);
203 }
204
setMatrix2f(UniformHandle u,const float matrix[]) const205 void GrUniformDataManager::setMatrix2f(UniformHandle u, const float matrix[]) const {
206 this->setMatrices<2, SkSLType::kFloat2x2, SkSLType::kHalf2x2>(u, 1, matrix);
207 }
208
setMatrix2fv(UniformHandle u,int arrayCount,const float m[]) const209 void GrUniformDataManager::setMatrix2fv(UniformHandle u, int arrayCount, const float m[]) const {
210 this->setMatrices<2, SkSLType::kFloat2x2, SkSLType::kHalf2x2>(u, arrayCount, m);
211 }
212
setMatrix3f(UniformHandle u,const float matrix[]) const213 void GrUniformDataManager::setMatrix3f(UniformHandle u, const float matrix[]) const {
214 this->setMatrices<3, SkSLType::kFloat3x3, SkSLType::kHalf3x3>(u, 1, matrix);
215 }
216
setMatrix3fv(UniformHandle u,int arrayCount,const float m[]) const217 void GrUniformDataManager::setMatrix3fv(UniformHandle u, int arrayCount, const float m[]) const {
218 this->setMatrices<3, SkSLType::kFloat3x3, SkSLType::kHalf3x3>(u, arrayCount, m);
219 }
220
setMatrix4f(UniformHandle u,const float matrix[]) const221 void GrUniformDataManager::setMatrix4f(UniformHandle u, const float matrix[]) const {
222 this->setMatrices<4, SkSLType::kFloat4x4, SkSLType::kHalf4x4>(u, 1, matrix);
223 }
224
setMatrix4fv(UniformHandle u,int arrayCount,const float m[]) const225 void GrUniformDataManager::setMatrix4fv(UniformHandle u, int arrayCount, const float m[]) const {
226 this->setMatrices<4, SkSLType::kFloat4x4, SkSLType::kHalf4x4>(u, arrayCount, m);
227 }
228
229 template <int N, SkSLType FullType, SkSLType HalfType>
setMatrices(UniformHandle u,int arrayCount,const float matrices[]) const230 inline void GrUniformDataManager::setMatrices(UniformHandle u,
231 int arrayCount,
232 const float matrices[]) const {
233 const Uniform& uni = fUniforms[u.toIndex()];
234 SkASSERT(uni.fType == FullType || uni.fType == HalfType);
235 SkASSERT(arrayCount > 0);
236 SkASSERT(arrayCount <= uni.fArrayCount ||
237 (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
238
239 void* buffer = this->getBufferPtrAndMarkDirty(uni);
240 if constexpr (N == 4) {
241 this->copyUniforms(buffer, matrices, arrayCount * 16, uni.fType);
242 } else {
243 for (int i = 0; i < arrayCount; ++i) {
244 const float* matrix = &matrices[N * N * i];
245 for (int j = 0; j < N; ++j) {
246 int uniformSize = this->copyUniforms(buffer, &matrix[j * N], N, uni.fType);
247 buffer = SkTAddOffset<void>(buffer, /*numUniforms*/4 * uniformSize);
248 }
249 }
250 }
251 }
252