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
8 #include "include/core/SkMatrix.h"
9 #include "src/gpu/ganesh/gl/GrGLGpu.h"
10 #include "src/gpu/ganesh/gl/GrGLProgramDataManager.h"
11 #include "src/gpu/ganesh/glsl/GrGLSLUniformHandler.h"
12
13 #define ASSERT_ARRAY_UPLOAD_IN_BOUNDS(UNI, COUNT) \
14 SkASSERT((COUNT) <= (UNI).fArrayCount || \
15 (1 == (COUNT) && GrShaderVar::kNonArray == (UNI).fArrayCount))
16
GrGLProgramDataManager(GrGLGpu * gpu,const UniformInfoArray & uniforms)17 GrGLProgramDataManager::GrGLProgramDataManager(GrGLGpu* gpu, const UniformInfoArray& uniforms)
18 : fGpu(gpu) {
19 fUniforms.push_back_n(uniforms.count());
20 int i = 0;
21 for (const GLUniformInfo& builderUniform : uniforms.items()) {
22 Uniform& uniform = fUniforms[i++];
23 SkASSERT(GrShaderVar::kNonArray == builderUniform.fVariable.getArrayCount() ||
24 builderUniform.fVariable.getArrayCount() > 0);
25 SkDEBUGCODE(
26 uniform.fArrayCount = builderUniform.fVariable.getArrayCount();
27 uniform.fType = builderUniform.fVariable.getType();
28 )
29 uniform.fLocation = builderUniform.fLocation;
30 }
31 }
32
setSamplerUniforms(const UniformInfoArray & samplers,int startUnit) const33 void GrGLProgramDataManager::setSamplerUniforms(const UniformInfoArray& samplers,
34 int startUnit) const {
35 int i = 0;
36 for (const GLUniformInfo& sampler : samplers.items()) {
37 SkASSERT(sampler.fVisibility);
38 if (kUnusedUniform != sampler.fLocation) {
39 GR_GL_CALL(fGpu->glInterface(), Uniform1i(sampler.fLocation, i + startUnit));
40 }
41 ++i;
42 }
43 }
44
set1i(UniformHandle u,int32_t i) const45 void GrGLProgramDataManager::set1i(UniformHandle u, int32_t i) const {
46 const Uniform& uni = fUniforms[u.toIndex()];
47 SkASSERT(uni.fType == SkSLType::kInt || uni.fType == SkSLType::kShort);
48 SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
49 if (kUnusedUniform != uni.fLocation) {
50 GR_GL_CALL(fGpu->glInterface(), Uniform1i(uni.fLocation, i));
51 }
52 }
53
set1iv(UniformHandle u,int arrayCount,const int32_t v[]) const54 void GrGLProgramDataManager::set1iv(UniformHandle u,
55 int arrayCount,
56 const int32_t v[]) const {
57 const Uniform& uni = fUniforms[u.toIndex()];
58 SkASSERT(uni.fType == SkSLType::kInt || uni.fType == SkSLType::kShort);
59 SkASSERT(arrayCount > 0);
60 ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
61 if (kUnusedUniform != uni.fLocation) {
62 GR_GL_CALL(fGpu->glInterface(), Uniform1iv(uni.fLocation, arrayCount, v));
63 }
64 }
65
set1f(UniformHandle u,float v0) const66 void GrGLProgramDataManager::set1f(UniformHandle u, float v0) const {
67 const Uniform& uni = fUniforms[u.toIndex()];
68 SkASSERT(uni.fType == SkSLType::kFloat || uni.fType == SkSLType::kHalf);
69 SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
70 if (kUnusedUniform != uni.fLocation) {
71 GR_GL_CALL(fGpu->glInterface(), Uniform1f(uni.fLocation, v0));
72 }
73 }
74
set1fv(UniformHandle u,int arrayCount,const float v[]) const75 void GrGLProgramDataManager::set1fv(UniformHandle u,
76 int arrayCount,
77 const float v[]) const {
78 const Uniform& uni = fUniforms[u.toIndex()];
79 SkASSERT(uni.fType == SkSLType::kFloat || uni.fType == SkSLType::kHalf);
80 SkASSERT(arrayCount > 0);
81 ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
82 // This assert fires in some instances of the two-pt gradient for its VSParams.
83 // Once the uniform manager is responsible for inserting the duplicate uniform
84 // arrays in VS and FS driver bug workaround, this can be enabled.
85 // this->printUni(uni);
86 if (kUnusedUniform != uni.fLocation) {
87 GR_GL_CALL(fGpu->glInterface(), Uniform1fv(uni.fLocation, arrayCount, v));
88 }
89 }
90
set2i(UniformHandle u,int32_t i0,int32_t i1) const91 void GrGLProgramDataManager::set2i(UniformHandle u, int32_t i0, int32_t i1) const {
92 const Uniform& uni = fUniforms[u.toIndex()];
93 SkASSERT(uni.fType == SkSLType::kInt2 || uni.fType == SkSLType::kShort2);
94 SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
95 if (kUnusedUniform != uni.fLocation) {
96 GR_GL_CALL(fGpu->glInterface(), Uniform2i(uni.fLocation, i0, i1));
97 }
98 }
99
set2iv(UniformHandle u,int arrayCount,const int32_t v[]) const100 void GrGLProgramDataManager::set2iv(UniformHandle u,
101 int arrayCount,
102 const int32_t v[]) const {
103 const Uniform& uni = fUniforms[u.toIndex()];
104 SkASSERT(uni.fType == SkSLType::kInt2 || uni.fType == SkSLType::kShort2);
105 SkASSERT(arrayCount > 0);
106 ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
107 if (kUnusedUniform != uni.fLocation) {
108 GR_GL_CALL(fGpu->glInterface(), Uniform2iv(uni.fLocation, arrayCount, v));
109 }
110 }
111
set2f(UniformHandle u,float v0,float v1) const112 void GrGLProgramDataManager::set2f(UniformHandle u, float v0, float v1) const {
113 const Uniform& uni = fUniforms[u.toIndex()];
114 SkASSERT(uni.fType == SkSLType::kFloat2 || uni.fType == SkSLType::kHalf2);
115 SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
116 if (kUnusedUniform != uni.fLocation) {
117 GR_GL_CALL(fGpu->glInterface(), Uniform2f(uni.fLocation, v0, v1));
118 }
119 }
120
set2fv(UniformHandle u,int arrayCount,const float v[]) const121 void GrGLProgramDataManager::set2fv(UniformHandle u,
122 int arrayCount,
123 const float v[]) const {
124 const Uniform& uni = fUniforms[u.toIndex()];
125 SkASSERT(uni.fType == SkSLType::kFloat2 || uni.fType == SkSLType::kHalf2);
126 SkASSERT(arrayCount > 0);
127 ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
128 if (kUnusedUniform != uni.fLocation) {
129 GR_GL_CALL(fGpu->glInterface(), Uniform2fv(uni.fLocation, arrayCount, v));
130 }
131 }
132
set3i(UniformHandle u,int32_t i0,int32_t i1,int32_t i2) const133 void GrGLProgramDataManager::set3i(UniformHandle u, int32_t i0, int32_t i1, int32_t i2) const {
134 const Uniform& uni = fUniforms[u.toIndex()];
135 SkASSERT(uni.fType == SkSLType::kInt3 || uni.fType == SkSLType::kShort3);
136 SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
137 if (kUnusedUniform != uni.fLocation) {
138 GR_GL_CALL(fGpu->glInterface(), Uniform3i(uni.fLocation, i0, i1, i2));
139 }
140 }
141
set3iv(UniformHandle u,int arrayCount,const int32_t v[]) const142 void GrGLProgramDataManager::set3iv(UniformHandle u,
143 int arrayCount,
144 const int32_t v[]) const {
145 const Uniform& uni = fUniforms[u.toIndex()];
146 SkASSERT(uni.fType == SkSLType::kInt3 || uni.fType == SkSLType::kShort3);
147 SkASSERT(arrayCount > 0);
148 ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
149 if (kUnusedUniform != uni.fLocation) {
150 GR_GL_CALL(fGpu->glInterface(), Uniform3iv(uni.fLocation, arrayCount, v));
151 }
152 }
153
set3f(UniformHandle u,float v0,float v1,float v2) const154 void GrGLProgramDataManager::set3f(UniformHandle u, float v0, float v1, float v2) const {
155 const Uniform& uni = fUniforms[u.toIndex()];
156 SkASSERT(uni.fType == SkSLType::kFloat3 || uni.fType == SkSLType::kHalf3);
157 SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
158 if (kUnusedUniform != uni.fLocation) {
159 GR_GL_CALL(fGpu->glInterface(), Uniform3f(uni.fLocation, v0, v1, v2));
160 }
161 }
162
set3fv(UniformHandle u,int arrayCount,const float v[]) const163 void GrGLProgramDataManager::set3fv(UniformHandle u,
164 int arrayCount,
165 const float v[]) const {
166 const Uniform& uni = fUniforms[u.toIndex()];
167 SkASSERT(uni.fType == SkSLType::kFloat3 || uni.fType == SkSLType::kHalf3);
168 SkASSERT(arrayCount > 0);
169 ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
170 if (kUnusedUniform != uni.fLocation) {
171 GR_GL_CALL(fGpu->glInterface(), Uniform3fv(uni.fLocation, arrayCount, v));
172 }
173 }
174
set4i(UniformHandle u,int32_t i0,int32_t i1,int32_t i2,int32_t i3) const175 void GrGLProgramDataManager::set4i(UniformHandle u,
176 int32_t i0,
177 int32_t i1,
178 int32_t i2,
179 int32_t i3) const {
180 const Uniform& uni = fUniforms[u.toIndex()];
181 SkASSERT(uni.fType == SkSLType::kInt4 || uni.fType == SkSLType::kShort4);
182 SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
183 if (kUnusedUniform != uni.fLocation) {
184 GR_GL_CALL(fGpu->glInterface(), Uniform4i(uni.fLocation, i0, i1, i2, i3));
185 }
186 }
187
set4iv(UniformHandle u,int arrayCount,const int32_t v[]) const188 void GrGLProgramDataManager::set4iv(UniformHandle u,
189 int arrayCount,
190 const int32_t v[]) const {
191 const Uniform& uni = fUniforms[u.toIndex()];
192 SkASSERT(uni.fType == SkSLType::kInt4 || uni.fType == SkSLType::kShort4);
193 SkASSERT(arrayCount > 0);
194 ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
195 if (kUnusedUniform != uni.fLocation) {
196 GR_GL_CALL(fGpu->glInterface(), Uniform4iv(uni.fLocation, arrayCount, v));
197 }
198 }
199
set4f(UniformHandle u,float v0,float v1,float v2,float v3) const200 void GrGLProgramDataManager::set4f(UniformHandle u,
201 float v0,
202 float v1,
203 float v2,
204 float v3) const {
205 const Uniform& uni = fUniforms[u.toIndex()];
206 SkASSERT(uni.fType == SkSLType::kFloat4 || uni.fType == SkSLType::kHalf4);
207 SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
208 if (kUnusedUniform != uni.fLocation) {
209 GR_GL_CALL(fGpu->glInterface(), Uniform4f(uni.fLocation, v0, v1, v2, v3));
210 }
211 }
212
set4fv(UniformHandle u,int arrayCount,const float v[]) const213 void GrGLProgramDataManager::set4fv(UniformHandle u,
214 int arrayCount,
215 const float v[]) const {
216 const Uniform& uni = fUniforms[u.toIndex()];
217 SkASSERT(uni.fType == SkSLType::kFloat4 || uni.fType == SkSLType::kHalf4);
218 SkASSERT(arrayCount > 0);
219 ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
220 if (kUnusedUniform != uni.fLocation) {
221 GR_GL_CALL(fGpu->glInterface(), Uniform4fv(uni.fLocation, arrayCount, v));
222 }
223 }
224
setMatrix2f(UniformHandle u,const float matrix[]) const225 void GrGLProgramDataManager::setMatrix2f(UniformHandle u, const float matrix[]) const {
226 this->setMatrices<2>(u, 1, matrix);
227 }
228
setMatrix3f(UniformHandle u,const float matrix[]) const229 void GrGLProgramDataManager::setMatrix3f(UniformHandle u, const float matrix[]) const {
230 this->setMatrices<3>(u, 1, matrix);
231 }
232
setMatrix4f(UniformHandle u,const float matrix[]) const233 void GrGLProgramDataManager::setMatrix4f(UniformHandle u, const float matrix[]) const {
234 this->setMatrices<4>(u, 1, matrix);
235 }
236
setMatrix2fv(UniformHandle u,int arrayCount,const float m[]) const237 void GrGLProgramDataManager::setMatrix2fv(UniformHandle u, int arrayCount, const float m[]) const {
238 this->setMatrices<2>(u, arrayCount, m);
239 }
240
setMatrix3fv(UniformHandle u,int arrayCount,const float m[]) const241 void GrGLProgramDataManager::setMatrix3fv(UniformHandle u, int arrayCount, const float m[]) const {
242 this->setMatrices<3>(u, arrayCount, m);
243 }
244
setMatrix4fv(UniformHandle u,int arrayCount,const float m[]) const245 void GrGLProgramDataManager::setMatrix4fv(UniformHandle u, int arrayCount, const float m[]) const {
246 this->setMatrices<4>(u, arrayCount, m);
247 }
248
249 template<int N> struct set_uniform_matrix;
250
setMatrices(UniformHandle u,int arrayCount,const float matrices[]) const251 template<int N> inline void GrGLProgramDataManager::setMatrices(UniformHandle u,
252 int arrayCount,
253 const float matrices[]) const {
254 const Uniform& uni = fUniforms[u.toIndex()];
255 SkASSERT(static_cast<int>(uni.fType) == static_cast<int>(SkSLType::kFloat2x2) + (N - 2) ||
256 static_cast<int>(uni.fType) == static_cast<int>(SkSLType::kHalf2x2) + (N - 2));
257 SkASSERT(arrayCount > 0);
258 ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
259 if (kUnusedUniform != uni.fLocation) {
260 set_uniform_matrix<N>::set(fGpu->glInterface(), uni.fLocation, arrayCount, matrices);
261 }
262 }
263
264 template<> struct set_uniform_matrix<2> {
setset_uniform_matrix265 inline static void set(const GrGLInterface* gli, const GrGLint loc, int cnt, const float m[]) {
266 GR_GL_CALL(gli, UniformMatrix2fv(loc, cnt, false, m));
267 }
268 };
269
270 template<> struct set_uniform_matrix<3> {
setset_uniform_matrix271 inline static void set(const GrGLInterface* gli, const GrGLint loc, int cnt, const float m[]) {
272 GR_GL_CALL(gli, UniformMatrix3fv(loc, cnt, false, m));
273 }
274 };
275
276 template<> struct set_uniform_matrix<4> {
setset_uniform_matrix277 inline static void set(const GrGLInterface* gli, const GrGLint loc, int cnt, const float m[]) {
278 GR_GL_CALL(gli, UniformMatrix4fv(loc, cnt, false, m));
279 }
280 };
281