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