xref: /aosp_15_r20/external/skia/src/gpu/ganesh/GrUniformDataManager.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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