1 /*
2 * Copyright 2019 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 "src/gpu/dawn/GrDawnUniformHandler.h"
9 #include "src/gpu/glsl/GrGLSLProgramBuilder.h"
10
GrDawnUniformHandler(GrGLSLProgramBuilder * program)11 GrDawnUniformHandler::GrDawnUniformHandler(GrGLSLProgramBuilder* program)
12 : INHERITED(program)
13 , fUniforms(kUniformsPerBlock)
14 , fSamplers(kUniformsPerBlock)
15 , fTextures(kUniformsPerBlock)
16 {
17 }
18
getUniformVariable(UniformHandle u) const19 const GrShaderVar& GrDawnUniformHandler::getUniformVariable(UniformHandle u) const {
20 return fUniforms[u.toIndex()].fVar;
21 }
22
getUniformCStr(UniformHandle u) const23 const char* GrDawnUniformHandler::getUniformCStr(UniformHandle u) const {
24 return fUniforms[u.toIndex()].fVar.getName().c_str();
25 }
26
27 // FIXME: this code was ripped from GrVkUniformHandler; should be refactored.
28 namespace {
29
grsltype_to_alignment_mask(GrSLType type)30 uint32_t grsltype_to_alignment_mask(GrSLType type) {
31 switch(type) {
32 case kByte_GrSLType: // fall through
33 case kUByte_GrSLType:
34 return 0x0;
35 case kByte2_GrSLType: // fall through
36 case kUByte2_GrSLType:
37 return 0x1;
38 case kByte3_GrSLType: // fall through
39 case kByte4_GrSLType:
40 case kUByte3_GrSLType:
41 case kUByte4_GrSLType:
42 return 0x3;
43 case kShort_GrSLType: // fall through
44 case kUShort_GrSLType:
45 return 0x1;
46 case kShort2_GrSLType: // fall through
47 case kUShort2_GrSLType:
48 return 0x3;
49 case kShort3_GrSLType: // fall through
50 case kShort4_GrSLType:
51 case kUShort3_GrSLType:
52 case kUShort4_GrSLType:
53 return 0x7;
54 case kInt_GrSLType:
55 case kUint_GrSLType:
56 return 0x3;
57 case kHalf_GrSLType: // fall through
58 case kFloat_GrSLType:
59 return 0x3;
60 case kHalf2_GrSLType: // fall through
61 case kFloat2_GrSLType:
62 return 0x7;
63 case kHalf3_GrSLType: // fall through
64 case kFloat3_GrSLType:
65 return 0xF;
66 case kHalf4_GrSLType: // fall through
67 case kFloat4_GrSLType:
68 return 0xF;
69 case kUint2_GrSLType:
70 return 0x7;
71 case kInt2_GrSLType:
72 return 0x7;
73 case kInt3_GrSLType:
74 return 0xF;
75 case kInt4_GrSLType:
76 return 0xF;
77 case kHalf2x2_GrSLType: // fall through
78 case kFloat2x2_GrSLType:
79 return 0x7;
80 case kHalf3x3_GrSLType: // fall through
81 case kFloat3x3_GrSLType:
82 return 0xF;
83 case kHalf4x4_GrSLType: // fall through
84 case kFloat4x4_GrSLType:
85 return 0xF;
86
87 // This query is only valid for certain types.
88 case kVoid_GrSLType:
89 case kBool_GrSLType:
90 case kTexture2DSampler_GrSLType:
91 case kTextureExternalSampler_GrSLType:
92 case kTexture2DRectSampler_GrSLType:
93 case kTexture2D_GrSLType:
94 case kSampler_GrSLType:
95 break;
96 }
97 SK_ABORT("Unexpected type");
98 }
99
grsltype_to_size(GrSLType type)100 static inline uint32_t grsltype_to_size(GrSLType type) {
101 switch(type) {
102 case kByte_GrSLType:
103 case kUByte_GrSLType:
104 return 1;
105 case kByte2_GrSLType:
106 case kUByte2_GrSLType:
107 return 2;
108 case kByte3_GrSLType:
109 case kUByte3_GrSLType:
110 return 3;
111 case kByte4_GrSLType:
112 case kUByte4_GrSLType:
113 return 4;
114 case kShort_GrSLType:
115 return sizeof(int16_t);
116 case kShort2_GrSLType:
117 return 2 * sizeof(int16_t);
118 case kShort3_GrSLType:
119 return 3 * sizeof(int16_t);
120 case kShort4_GrSLType:
121 return 4 * sizeof(int16_t);
122 case kUShort_GrSLType:
123 return sizeof(uint16_t);
124 case kUShort2_GrSLType:
125 return 2 * sizeof(uint16_t);
126 case kUShort3_GrSLType:
127 return 3 * sizeof(uint16_t);
128 case kUShort4_GrSLType:
129 return 4 * sizeof(uint16_t);
130 case kInt_GrSLType:
131 return sizeof(int32_t);
132 case kUint_GrSLType:
133 return sizeof(int32_t);
134 case kHalf_GrSLType: // fall through
135 case kFloat_GrSLType:
136 return sizeof(float);
137 case kHalf2_GrSLType: // fall through
138 case kFloat2_GrSLType:
139 return 2 * sizeof(float);
140 case kHalf3_GrSLType: // fall through
141 case kFloat3_GrSLType:
142 return 3 * sizeof(float);
143 case kHalf4_GrSLType: // fall through
144 case kFloat4_GrSLType:
145 return 4 * sizeof(float);
146 case kUint2_GrSLType:
147 return 2 * sizeof(uint32_t);
148 case kInt2_GrSLType:
149 return 2 * sizeof(int32_t);
150 case kInt3_GrSLType:
151 return 3 * sizeof(int32_t);
152 case kInt4_GrSLType:
153 return 4 * sizeof(int32_t);
154 case kHalf2x2_GrSLType: // fall through
155 case kFloat2x2_GrSLType:
156 //TODO: this will be 4 * szof(float) on std430.
157 return 8 * sizeof(float);
158 case kHalf3x3_GrSLType: // fall through
159 case kFloat3x3_GrSLType:
160 return 12 * sizeof(float);
161 case kHalf4x4_GrSLType: // fall through
162 case kFloat4x4_GrSLType:
163 return 16 * sizeof(float);
164
165 // This query is only valid for certain types.
166 case kVoid_GrSLType:
167 case kBool_GrSLType:
168 case kTexture2DSampler_GrSLType:
169 case kTextureExternalSampler_GrSLType:
170 case kTexture2DRectSampler_GrSLType:
171 case kTexture2D_GrSLType:
172 case kSampler_GrSLType:
173 break;
174 }
175 SK_ABORT("Unexpected type");
176 }
177
get_ubo_offset(uint32_t * currentOffset,GrSLType type,int arrayCount)178 uint32_t get_ubo_offset(uint32_t* currentOffset,
179 GrSLType type,
180 int arrayCount) {
181 uint32_t alignmentMask = grsltype_to_alignment_mask(type);
182 // We want to use the std140 layout here, so we must make arrays align to 16 bytes.
183 if (arrayCount || type == kFloat2x2_GrSLType) {
184 alignmentMask = 0xF;
185 }
186 uint32_t offsetDiff = *currentOffset & alignmentMask;
187 if (offsetDiff != 0) {
188 offsetDiff = alignmentMask - offsetDiff + 1;
189 }
190 uint32_t uniformOffset = *currentOffset + offsetDiff;
191 SkASSERT(sizeof(float) == 4);
192 if (arrayCount) {
193 uint32_t elementSize = SkTMax<uint32_t>(16, grsltype_to_size(type));
194 SkASSERT(0 == (elementSize & 0xF));
195 *currentOffset = uniformOffset + elementSize * arrayCount;
196 } else {
197 *currentOffset = uniformOffset + grsltype_to_size(type);
198 }
199 return uniformOffset;
200 }
201
202 }
203
internalAddUniformArray(uint32_t visibility,GrSLType type,const char * name,bool mangleName,int arrayCount,const char ** outName)204 GrGLSLUniformHandler::UniformHandle GrDawnUniformHandler::internalAddUniformArray(
205 uint32_t visibility,
206 GrSLType type,
207 const char* name,
208 bool mangleName,
209 int arrayCount,
210 const char** outName) {
211 UniformInfo& info = fUniforms.push_back();
212 info.fVisibility = visibility;
213 if (visibility == kFragment_GrShaderFlag) {
214 info.fUBOOffset = get_ubo_offset(&fCurrentFragmentUBOOffset, type, arrayCount);
215 } else {
216 info.fUBOOffset = get_ubo_offset(&fCurrentGeometryUBOOffset, type, arrayCount);
217 }
218 GrShaderVar& var = info.fVar;
219 char prefix = 'u';
220 if ('u' == name[0] || !strncmp(name, GR_NO_MANGLE_PREFIX, strlen(GR_NO_MANGLE_PREFIX))) {
221 prefix = '\0';
222 }
223 fProgramBuilder->nameVariable(var.accessName(), prefix, name, mangleName);
224 var.setType(type);
225 var.setTypeModifier(GrShaderVar::kNone_TypeModifier);
226 var.setArrayCount(arrayCount);
227 SkString layoutQualifier;
228 layoutQualifier.appendf("offset = %d", info.fUBOOffset);
229 var.addLayoutQualifier(layoutQualifier.c_str());
230 if (outName) {
231 *outName = var.c_str();
232 }
233 return GrGLSLUniformHandler::UniformHandle(fUniforms.count() - 1);
234 }
235
addSampler(const GrTexture * texture,const GrSamplerState &,const GrSwizzle & swizzle,const char * name,const GrShaderCaps * caps)236 GrGLSLUniformHandler::SamplerHandle GrDawnUniformHandler::addSampler(const GrTexture* texture,
237 const GrSamplerState&,
238 const GrSwizzle& swizzle,
239 const char* name,
240 const GrShaderCaps* caps) {
241 SkString mangleName;
242 char prefix = 's';
243 fProgramBuilder->nameVariable(&mangleName, prefix, name, true);
244
245 GrSLType samplerType = kSampler_GrSLType, textureType = kTexture2D_GrSLType;
246 int binding = kSamplerBindingBase + fSamplers.count() * 2;
247 UniformInfo& info = fSamplers.push_back();
248 info.fVar.setType(samplerType);
249 info.fVar.setTypeModifier(GrShaderVar::kUniform_TypeModifier);
250 info.fVar.setName(mangleName);
251 SkString layoutQualifier;
252 layoutQualifier.appendf("set = 0, binding = %d", binding);
253 info.fVar.addLayoutQualifier(layoutQualifier.c_str());
254 info.fVisibility = kFragment_GrShaderFlag;
255 info.fUBOOffset = 0;
256 fSamplerSwizzles.push_back(swizzle);
257 SkASSERT(fSamplerSwizzles.count() == fSamplers.count());
258
259 SkString mangleTexName;
260 char texPrefix = 't';
261 fProgramBuilder->nameVariable(&mangleTexName, texPrefix, name, true);
262 UniformInfo& texInfo = fTextures.push_back();
263 texInfo.fVar.setType(textureType);
264 texInfo.fVar.setTypeModifier(GrShaderVar::kUniform_TypeModifier);
265 texInfo.fVar.setName(mangleTexName);
266 SkString texLayoutQualifier;
267 texLayoutQualifier.appendf("set = 0, binding = %d", binding + 1);
268 texInfo.fVar.addLayoutQualifier(texLayoutQualifier.c_str());
269 texInfo.fVisibility = kFragment_GrShaderFlag;
270 texInfo.fUBOOffset = 0;
271
272 SkString reference;
273 reference.printf("makeSampler2D(%s, %s)", texInfo.fVar.getName().c_str(),
274 info.fVar.getName().c_str());
275 fSamplerReferences.push_back() = reference;
276 return GrGLSLUniformHandler::SamplerHandle(fSamplers.count() - 1);
277 }
278
samplerVariable(GrGLSLUniformHandler::SamplerHandle handle) const279 const char* GrDawnUniformHandler::samplerVariable(
280 GrGLSLUniformHandler::SamplerHandle handle) const {
281 return fSamplerReferences[handle.toIndex()].c_str();
282 }
283
samplerSwizzle(GrGLSLUniformHandler::SamplerHandle handle) const284 GrSwizzle GrDawnUniformHandler::samplerSwizzle(GrGLSLUniformHandler::SamplerHandle handle) const {
285 return fSamplerSwizzles[handle.toIndex()];
286 }
287
appendUniformDecls(GrShaderFlags visibility,SkString * out) const288 void GrDawnUniformHandler::appendUniformDecls(GrShaderFlags visibility, SkString* out) const {
289 for (int i = 0; i < fSamplers.count(); ++i) {
290 if (fSamplers[i].fVisibility & visibility) {
291 fSamplers[i].fVar.appendDecl(fProgramBuilder->shaderCaps(), out);
292 out->append(";\n");
293 fTextures[i].fVar.appendDecl(fProgramBuilder->shaderCaps(), out);
294 out->append(";\n");
295 }
296 }
297 SkString uniformsString;
298 for (int i = 0; i < fUniforms.count(); ++i) {
299 if (fUniforms[i].fVisibility & visibility) {
300 fUniforms[i].fVar.appendDecl(fProgramBuilder->shaderCaps(), &uniformsString);
301 uniformsString.append(";\n");
302 }
303 }
304 if (!uniformsString.isEmpty()) {
305 uint32_t uniformBinding;
306 const char* stage;
307 if (kVertex_GrShaderFlag == visibility) {
308 uniformBinding = kGeometryBinding;
309 stage = "vertex";
310 } else if (kGeometry_GrShaderFlag == visibility) {
311 uniformBinding = kGeometryBinding;
312 stage = "geometry";
313 } else {
314 SkASSERT(kFragment_GrShaderFlag == visibility);
315 uniformBinding = kFragBinding;
316 stage = "fragment";
317 }
318 out->appendf("layout (set = 0, binding = %d) uniform %sUniformBuffer\n{\n",
319 uniformBinding, stage);
320 out->appendf("%s\n};\n", uniformsString.c_str());
321 }
322 }
323