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