1 /*
2 * Copyright 2015 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 "gl/GrGLUniformHandler.h"
9
10 #include "gl/GrGLCaps.h"
11 #include "gl/GrGLGpu.h"
12 #include "gl/builders/GrGLProgramBuilder.h"
13
14 #define GL_CALL(X) GR_GL_CALL(this->glGpu()->glInterface(), X)
15 #define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->glGpu()->glInterface(), R, X)
16
internalAddUniformArray(uint32_t visibility,GrSLType type,GrSLPrecision precision,const char * name,bool mangleName,int arrayCount,const char ** outName)17 GrGLSLUniformHandler::UniformHandle GrGLUniformHandler::internalAddUniformArray(
18 uint32_t visibility,
19 GrSLType type,
20 GrSLPrecision precision,
21 const char* name,
22 bool mangleName,
23 int arrayCount,
24 const char** outName) {
25 SkASSERT(name && strlen(name));
26 SkASSERT(0 != visibility);
27 SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeAcceptsPrecision(type));
28
29 UniformInfo& uni = fUniforms.push_back();
30 uni.fVariable.setType(type);
31 uni.fVariable.setTypeModifier(GrShaderVar::kUniform_TypeModifier);
32 // TODO this is a bit hacky, lets think of a better way. Basically we need to be able to use
33 // the uniform view matrix name in the GP, and the GP is immutable so it has to tell the PB
34 // exactly what name it wants to use for the uniform view matrix. If we prefix anythings, then
35 // the names will mismatch. I think the correct solution is to have all GPs which need the
36 // uniform view matrix, they should upload the view matrix in their setData along with regular
37 // uniforms.
38 char prefix = 'u';
39 if ('u' == name[0]) {
40 prefix = '\0';
41 }
42 fProgramBuilder->nameVariable(uni.fVariable.accessName(), prefix, name, mangleName);
43 uni.fVariable.setArrayCount(arrayCount);
44 uni.fVisibility = visibility;
45 uni.fVariable.setPrecision(precision);
46 uni.fLocation = -1;
47
48 if (outName) {
49 *outName = uni.fVariable.c_str();
50 }
51 return GrGLSLUniformHandler::UniformHandle(fUniforms.count() - 1);
52 }
53
addSampler(uint32_t visibility,GrSwizzle swizzle,GrSLType type,GrSLPrecision precision,const char * name)54 GrGLSLUniformHandler::SamplerHandle GrGLUniformHandler::addSampler(uint32_t visibility,
55 GrSwizzle swizzle,
56 GrSLType type,
57 GrSLPrecision precision,
58 const char* name) {
59 SkASSERT(name && strlen(name));
60 SkASSERT(0 != visibility);
61
62 SkString mangleName;
63 char prefix = 'u';
64 fProgramBuilder->nameVariable(&mangleName, prefix, name, true);
65
66 UniformInfo& sampler = fSamplers.push_back();
67 SkASSERT(GrSLTypeIsCombinedSamplerType(type));
68 sampler.fVariable.setType(type);
69 sampler.fVariable.setTypeModifier(GrShaderVar::kUniform_TypeModifier);
70 sampler.fVariable.setPrecision(precision);
71 sampler.fVariable.setName(mangleName);
72 sampler.fLocation = -1;
73 sampler.fVisibility = visibility;
74 fSamplerSwizzles.push_back(swizzle);
75 SkASSERT(fSamplers.count() == fSamplerSwizzles.count());
76 return GrGLSLUniformHandler::SamplerHandle(fSamplers.count() - 1);
77 }
78
addImageStorage(uint32_t visibility,GrSLType type,GrImageStorageFormat format,GrSLMemoryModel model,GrSLRestrict restrict,GrIOType ioType,const char * name)79 GrGLSLUniformHandler::ImageStorageHandle GrGLUniformHandler::addImageStorage(
80 uint32_t visibility, GrSLType type, GrImageStorageFormat format, GrSLMemoryModel model,
81 GrSLRestrict restrict, GrIOType ioType, const char* name) {
82 SkASSERT(name && strlen(name));
83 SkASSERT(0 != visibility);
84 SkString mangleName;
85 char prefix = 'u';
86 fProgramBuilder->nameVariable(&mangleName, prefix, name, true);
87
88 UniformInfo& imageStorage = fImageStorages.push_back();
89 imageStorage.fVariable.setName(mangleName);
90
91 SkASSERT(GrSLTypeIsImageStorage(type));
92 imageStorage.fVariable.setType(type);
93 imageStorage.fVariable.setTypeModifier(GrShaderVar::kUniform_TypeModifier);
94 imageStorage.fVariable.setImageStorageFormat(format);
95 imageStorage.fVariable.setMemoryModel(model);
96 imageStorage.fVariable.setRestrict(restrict);
97 imageStorage.fVariable.setIOType(ioType);
98 imageStorage.fVariable.setPrecision(kHigh_GrSLPrecision);
99 imageStorage.fLocation = -1;
100 imageStorage.fVisibility = visibility;
101 return GrGLSLUniformHandler::ImageStorageHandle(fImageStorages.count() - 1);
102 }
103
appendUniformDecls(GrShaderFlags visibility,SkString * out) const104 void GrGLUniformHandler::appendUniformDecls(GrShaderFlags visibility, SkString* out) const {
105 for (int i = 0; i < fUniforms.count(); ++i) {
106 if (fUniforms[i].fVisibility & visibility) {
107 fUniforms[i].fVariable.appendDecl(fProgramBuilder->shaderCaps(), out);
108 out->append(";");
109 }
110 }
111 for (int i = 0; i < fSamplers.count(); ++i) {
112 if (fSamplers[i].fVisibility & visibility) {
113 fSamplers[i].fVariable.appendDecl(fProgramBuilder->shaderCaps(), out);
114 out->append(";\n");
115 }
116 }
117 for (int i = 0; i < fImageStorages.count(); ++i) {
118 if (fImageStorages[i].fVisibility & visibility) {
119 fImageStorages[i].fVariable.appendDecl(fProgramBuilder->shaderCaps(), out);
120 out->append(";");
121 }
122 }
123 }
124
bindUniformLocations(GrGLuint programID,const GrGLCaps & caps)125 void GrGLUniformHandler::bindUniformLocations(GrGLuint programID, const GrGLCaps& caps) {
126 if (caps.bindUniformLocationSupport()) {
127 int currUniform = 0;
128 for (int i = 0; i < fUniforms.count(); ++i, ++currUniform) {
129 GL_CALL(BindUniformLocation(programID, currUniform, fUniforms[i].fVariable.c_str()));
130 fUniforms[i].fLocation = currUniform;
131 }
132 for (int i = 0; i < fSamplers.count(); ++i, ++currUniform) {
133 GL_CALL(BindUniformLocation(programID, currUniform, fSamplers[i].fVariable.c_str()));
134 fSamplers[i].fLocation = currUniform;
135 }
136 for (int i = 0; i < fImageStorages.count(); ++i) {
137 GL_CALL(BindUniformLocation(programID, currUniform,
138 fImageStorages[i].fVariable.c_str()));
139 fImageStorages[i].fLocation = currUniform;
140 }
141 }
142 }
143
getUniformLocations(GrGLuint programID,const GrGLCaps & caps)144 void GrGLUniformHandler::getUniformLocations(GrGLuint programID, const GrGLCaps& caps) {
145 if (!caps.bindUniformLocationSupport()) {
146 int count = fUniforms.count();
147 for (int i = 0; i < count; ++i) {
148 GrGLint location;
149 GL_CALL_RET(location, GetUniformLocation(programID, fUniforms[i].fVariable.c_str()));
150 fUniforms[i].fLocation = location;
151 }
152 for (int i = 0; i < fSamplers.count(); ++i) {
153 GrGLint location;
154 GL_CALL_RET(location, GetUniformLocation(programID, fSamplers[i].fVariable.c_str()));
155 fSamplers[i].fLocation = location;
156 }
157 for (int i = 0; i < fImageStorages.count(); ++i) {
158 GrGLint location;
159 GL_CALL_RET(location, GetUniformLocation(programID,
160 fImageStorages[i].fVariable.c_str()));
161 fImageStorages[i].fLocation = location;
162 }
163 }
164 }
165
glGpu() const166 const GrGLGpu* GrGLUniformHandler::glGpu() const {
167 GrGLProgramBuilder* glPB = (GrGLProgramBuilder*) fProgramBuilder;
168 return glPB->gpu();
169 }
170