1 /*
2 * Copyright 2012 Google Inc.
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 #include "src/gpu/ganesh/gl/GrGLProgramDataManager.h"
8
9 #include "include/gpu/ganesh/gl/GrGLFunctions.h"
10 #include "include/gpu/ganesh/gl/GrGLInterface.h"
11 #include "include/private/base/SkAssert.h"
12 #include "src/core/SkSLTypeShared.h"
13 #include "src/gpu/ganesh/gl/GrGLGpu.h"
14 #include "src/gpu/ganesh/gl/GrGLUtil.h"
15
16 #define ASSERT_ARRAY_UPLOAD_IN_BOUNDS(UNI, COUNT) \
17 SkASSERT((COUNT) <= (UNI).fArrayCount || \
18 (1 == (COUNT) && GrShaderVar::kNonArray == (UNI).fArrayCount))
19
20 static constexpr GrGLint kUnusedUniform = -1;
21
GrGLProgramDataManager(GrGLGpu * gpu,const UniformInfoArray & uniforms)22 GrGLProgramDataManager::GrGLProgramDataManager(GrGLGpu* gpu, const UniformInfoArray& uniforms)
23 : fGpu(gpu) {
24 fUniforms.push_back_n(uniforms.count());
25 int i = 0;
26 for (const GLUniformInfo& builderUniform : uniforms.items()) {
27 Uniform& uniform = fUniforms[i++];
28 SkASSERT(GrShaderVar::kNonArray == builderUniform.fVariable.getArrayCount() ||
29 builderUniform.fVariable.getArrayCount() > 0);
30 SkDEBUGCODE(
31 uniform.fArrayCount = builderUniform.fVariable.getArrayCount();
32 uniform.fType = builderUniform.fVariable.getType();
33 )
34 uniform.fLocation = builderUniform.fLocation;
35 }
36 }
37
setSamplerUniforms(const UniformInfoArray & samplers,int startUnit) const38 void GrGLProgramDataManager::setSamplerUniforms(const UniformInfoArray& samplers,
39 int startUnit) const {
40 int i = 0;
41 for (const GLUniformInfo& sampler : samplers.items()) {
42 SkASSERT(sampler.fVisibility);
43 if (kUnusedUniform != sampler.fLocation) {
44 GR_GL_CALL(fGpu->glInterface(), Uniform1i(sampler.fLocation, i + startUnit));
45 }
46 ++i;
47 }
48 }
49
set1i(UniformHandle u,int32_t i) const50 void GrGLProgramDataManager::set1i(UniformHandle u, int32_t i) const {
51 const Uniform& uni = fUniforms[u.toIndex()];
52 SkASSERT(uni.fType == SkSLType::kInt || uni.fType == SkSLType::kShort);
53 SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
54 if (kUnusedUniform != uni.fLocation) {
55 GR_GL_CALL(fGpu->glInterface(), Uniform1i(uni.fLocation, i));
56 }
57 }
58
set1iv(UniformHandle u,int arrayCount,const int32_t v[]) const59 void GrGLProgramDataManager::set1iv(UniformHandle u,
60 int arrayCount,
61 const int32_t v[]) const {
62 const Uniform& uni = fUniforms[u.toIndex()];
63 SkASSERT(uni.fType == SkSLType::kInt || uni.fType == SkSLType::kShort);
64 SkASSERT(arrayCount > 0);
65 ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
66 if (kUnusedUniform != uni.fLocation) {
67 GR_GL_CALL(fGpu->glInterface(), Uniform1iv(uni.fLocation, arrayCount, v));
68 }
69 }
70
set1f(UniformHandle u,float v0) const71 void GrGLProgramDataManager::set1f(UniformHandle u, float v0) const {
72 const Uniform& uni = fUniforms[u.toIndex()];
73 SkASSERT(uni.fType == SkSLType::kFloat || uni.fType == SkSLType::kHalf);
74 SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
75 if (kUnusedUniform != uni.fLocation) {
76 GR_GL_CALL(fGpu->glInterface(), Uniform1f(uni.fLocation, v0));
77 }
78 }
79
set1fv(UniformHandle u,int arrayCount,const float v[]) const80 void GrGLProgramDataManager::set1fv(UniformHandle u,
81 int arrayCount,
82 const float v[]) const {
83 const Uniform& uni = fUniforms[u.toIndex()];
84 SkASSERT(uni.fType == SkSLType::kFloat || uni.fType == SkSLType::kHalf);
85 SkASSERT(arrayCount > 0);
86 ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
87 // This assert fires in some instances of the two-pt gradient for its VSParams.
88 // Once the uniform manager is responsible for inserting the duplicate uniform
89 // arrays in VS and FS driver bug workaround, this can be enabled.
90 // this->printUni(uni);
91 if (kUnusedUniform != uni.fLocation) {
92 GR_GL_CALL(fGpu->glInterface(), Uniform1fv(uni.fLocation, arrayCount, v));
93 }
94 }
95
set2i(UniformHandle u,int32_t i0,int32_t i1) const96 void GrGLProgramDataManager::set2i(UniformHandle u, int32_t i0, int32_t i1) const {
97 const Uniform& uni = fUniforms[u.toIndex()];
98 SkASSERT(uni.fType == SkSLType::kInt2 || uni.fType == SkSLType::kShort2);
99 SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
100 if (kUnusedUniform != uni.fLocation) {
101 GR_GL_CALL(fGpu->glInterface(), Uniform2i(uni.fLocation, i0, i1));
102 }
103 }
104
set2iv(UniformHandle u,int arrayCount,const int32_t v[]) const105 void GrGLProgramDataManager::set2iv(UniformHandle u,
106 int arrayCount,
107 const int32_t v[]) const {
108 const Uniform& uni = fUniforms[u.toIndex()];
109 SkASSERT(uni.fType == SkSLType::kInt2 || uni.fType == SkSLType::kShort2);
110 SkASSERT(arrayCount > 0);
111 ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
112 if (kUnusedUniform != uni.fLocation) {
113 GR_GL_CALL(fGpu->glInterface(), Uniform2iv(uni.fLocation, arrayCount, v));
114 }
115 }
116
set2f(UniformHandle u,float v0,float v1) const117 void GrGLProgramDataManager::set2f(UniformHandle u, float v0, float v1) const {
118 const Uniform& uni = fUniforms[u.toIndex()];
119 SkASSERT(uni.fType == SkSLType::kFloat2 || uni.fType == SkSLType::kHalf2);
120 SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
121 if (kUnusedUniform != uni.fLocation) {
122 GR_GL_CALL(fGpu->glInterface(), Uniform2f(uni.fLocation, v0, v1));
123 }
124 }
125
set2fv(UniformHandle u,int arrayCount,const float v[]) const126 void GrGLProgramDataManager::set2fv(UniformHandle u,
127 int arrayCount,
128 const float v[]) const {
129 const Uniform& uni = fUniforms[u.toIndex()];
130 SkASSERT(uni.fType == SkSLType::kFloat2 || uni.fType == SkSLType::kHalf2);
131 SkASSERT(arrayCount > 0);
132 ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
133 if (kUnusedUniform != uni.fLocation) {
134 GR_GL_CALL(fGpu->glInterface(), Uniform2fv(uni.fLocation, arrayCount, v));
135 }
136 }
137
set3i(UniformHandle u,int32_t i0,int32_t i1,int32_t i2) const138 void GrGLProgramDataManager::set3i(UniformHandle u, int32_t i0, int32_t i1, int32_t i2) const {
139 const Uniform& uni = fUniforms[u.toIndex()];
140 SkASSERT(uni.fType == SkSLType::kInt3 || uni.fType == SkSLType::kShort3);
141 SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
142 if (kUnusedUniform != uni.fLocation) {
143 GR_GL_CALL(fGpu->glInterface(), Uniform3i(uni.fLocation, i0, i1, i2));
144 }
145 }
146
set3iv(UniformHandle u,int arrayCount,const int32_t v[]) const147 void GrGLProgramDataManager::set3iv(UniformHandle u,
148 int arrayCount,
149 const int32_t v[]) const {
150 const Uniform& uni = fUniforms[u.toIndex()];
151 SkASSERT(uni.fType == SkSLType::kInt3 || uni.fType == SkSLType::kShort3);
152 SkASSERT(arrayCount > 0);
153 ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
154 if (kUnusedUniform != uni.fLocation) {
155 GR_GL_CALL(fGpu->glInterface(), Uniform3iv(uni.fLocation, arrayCount, v));
156 }
157 }
158
set3f(UniformHandle u,float v0,float v1,float v2) const159 void GrGLProgramDataManager::set3f(UniformHandle u, float v0, float v1, float v2) const {
160 const Uniform& uni = fUniforms[u.toIndex()];
161 SkASSERT(uni.fType == SkSLType::kFloat3 || uni.fType == SkSLType::kHalf3);
162 SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
163 if (kUnusedUniform != uni.fLocation) {
164 GR_GL_CALL(fGpu->glInterface(), Uniform3f(uni.fLocation, v0, v1, v2));
165 }
166 }
167
set3fv(UniformHandle u,int arrayCount,const float v[]) const168 void GrGLProgramDataManager::set3fv(UniformHandle u,
169 int arrayCount,
170 const float v[]) const {
171 const Uniform& uni = fUniforms[u.toIndex()];
172 SkASSERT(uni.fType == SkSLType::kFloat3 || uni.fType == SkSLType::kHalf3);
173 SkASSERT(arrayCount > 0);
174 ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
175 if (kUnusedUniform != uni.fLocation) {
176 GR_GL_CALL(fGpu->glInterface(), Uniform3fv(uni.fLocation, arrayCount, v));
177 }
178 }
179
set4i(UniformHandle u,int32_t i0,int32_t i1,int32_t i2,int32_t i3) const180 void GrGLProgramDataManager::set4i(UniformHandle u,
181 int32_t i0,
182 int32_t i1,
183 int32_t i2,
184 int32_t i3) const {
185 const Uniform& uni = fUniforms[u.toIndex()];
186 SkASSERT(uni.fType == SkSLType::kInt4 || uni.fType == SkSLType::kShort4);
187 SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
188 if (kUnusedUniform != uni.fLocation) {
189 GR_GL_CALL(fGpu->glInterface(), Uniform4i(uni.fLocation, i0, i1, i2, i3));
190 }
191 }
192
set4iv(UniformHandle u,int arrayCount,const int32_t v[]) const193 void GrGLProgramDataManager::set4iv(UniformHandle u,
194 int arrayCount,
195 const int32_t v[]) const {
196 const Uniform& uni = fUniforms[u.toIndex()];
197 SkASSERT(uni.fType == SkSLType::kInt4 || uni.fType == SkSLType::kShort4);
198 SkASSERT(arrayCount > 0);
199 ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
200 if (kUnusedUniform != uni.fLocation) {
201 GR_GL_CALL(fGpu->glInterface(), Uniform4iv(uni.fLocation, arrayCount, v));
202 }
203 }
204
set4f(UniformHandle u,float v0,float v1,float v2,float v3) const205 void GrGLProgramDataManager::set4f(UniformHandle u,
206 float v0,
207 float v1,
208 float v2,
209 float v3) const {
210 const Uniform& uni = fUniforms[u.toIndex()];
211 SkASSERT(uni.fType == SkSLType::kFloat4 || uni.fType == SkSLType::kHalf4);
212 SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
213 if (kUnusedUniform != uni.fLocation) {
214 GR_GL_CALL(fGpu->glInterface(), Uniform4f(uni.fLocation, v0, v1, v2, v3));
215 }
216 }
217
set4fv(UniformHandle u,int arrayCount,const float v[]) const218 void GrGLProgramDataManager::set4fv(UniformHandle u,
219 int arrayCount,
220 const float v[]) const {
221 const Uniform& uni = fUniforms[u.toIndex()];
222 SkASSERT(uni.fType == SkSLType::kFloat4 || uni.fType == SkSLType::kHalf4);
223 SkASSERT(arrayCount > 0);
224 ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
225 if (kUnusedUniform != uni.fLocation) {
226 GR_GL_CALL(fGpu->glInterface(), Uniform4fv(uni.fLocation, arrayCount, v));
227 }
228 }
229
setMatrix2f(UniformHandle u,const float matrix[]) const230 void GrGLProgramDataManager::setMatrix2f(UniformHandle u, const float matrix[]) const {
231 this->setMatrices<2>(u, 1, matrix);
232 }
233
setMatrix3f(UniformHandle u,const float matrix[]) const234 void GrGLProgramDataManager::setMatrix3f(UniformHandle u, const float matrix[]) const {
235 this->setMatrices<3>(u, 1, matrix);
236 }
237
setMatrix4f(UniformHandle u,const float matrix[]) const238 void GrGLProgramDataManager::setMatrix4f(UniformHandle u, const float matrix[]) const {
239 this->setMatrices<4>(u, 1, matrix);
240 }
241
setMatrix2fv(UniformHandle u,int arrayCount,const float m[]) const242 void GrGLProgramDataManager::setMatrix2fv(UniformHandle u, int arrayCount, const float m[]) const {
243 this->setMatrices<2>(u, arrayCount, m);
244 }
245
setMatrix3fv(UniformHandle u,int arrayCount,const float m[]) const246 void GrGLProgramDataManager::setMatrix3fv(UniformHandle u, int arrayCount, const float m[]) const {
247 this->setMatrices<3>(u, arrayCount, m);
248 }
249
setMatrix4fv(UniformHandle u,int arrayCount,const float m[]) const250 void GrGLProgramDataManager::setMatrix4fv(UniformHandle u, int arrayCount, const float m[]) const {
251 this->setMatrices<4>(u, arrayCount, m);
252 }
253
254 template<int N> struct set_uniform_matrix;
255
setMatrices(UniformHandle u,int arrayCount,const float matrices[]) const256 template<int N> inline void GrGLProgramDataManager::setMatrices(UniformHandle u,
257 int arrayCount,
258 const float matrices[]) const {
259 const Uniform& uni = fUniforms[u.toIndex()];
260 SkASSERT(static_cast<int>(uni.fType) == static_cast<int>(SkSLType::kFloat2x2) + (N - 2) ||
261 static_cast<int>(uni.fType) == static_cast<int>(SkSLType::kHalf2x2) + (N - 2));
262 SkASSERT(arrayCount > 0);
263 ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
264 if (kUnusedUniform != uni.fLocation) {
265 set_uniform_matrix<N>::set(fGpu->glInterface(), uni.fLocation, arrayCount, matrices);
266 }
267 }
268
269 template<> struct set_uniform_matrix<2> {
setset_uniform_matrix270 inline static void set(const GrGLInterface* gli, const GrGLint loc, int cnt, const float m[]) {
271 GR_GL_CALL(gli, UniformMatrix2fv(loc, cnt, false, m));
272 }
273 };
274
275 template<> struct set_uniform_matrix<3> {
setset_uniform_matrix276 inline static void set(const GrGLInterface* gli, const GrGLint loc, int cnt, const float m[]) {
277 GR_GL_CALL(gli, UniformMatrix3fv(loc, cnt, false, m));
278 }
279 };
280
281 template<> struct set_uniform_matrix<4> {
setset_uniform_matrix282 inline static void set(const GrGLInterface* gli, const GrGLint loc, int cnt, const float m[]) {
283 GR_GL_CALL(gli, UniformMatrix4fv(loc, cnt, false, m));
284 }
285 };
286