• 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/ganesh/GrSPIRVUniformHandler.h"
9 
10 #include "src/gpu/ganesh/GrUtil.h"
11 #include "src/gpu/ganesh/glsl/GrGLSLProgramBuilder.h"
12 
GrSPIRVUniformHandler(GrGLSLProgramBuilder * program)13 GrSPIRVUniformHandler::GrSPIRVUniformHandler(GrGLSLProgramBuilder* program)
14     : INHERITED(program)
15     , fUniforms(kUniformsPerBlock)
16     , fSamplers(kUniformsPerBlock) {}
17 
getUniformVariable(UniformHandle u) const18 const GrShaderVar& GrSPIRVUniformHandler::getUniformVariable(UniformHandle u) const {
19     return fUniforms.item(u.toIndex()).fVariable;
20 }
21 
getUniformCStr(UniformHandle u) const22 const char* GrSPIRVUniformHandler::getUniformCStr(UniformHandle u) const {
23     return fUniforms.item(u.toIndex()).fVariable.getName().c_str();
24 }
25 
26 // FIXME: this code was ripped from GrVkUniformHandler; should be refactored.
27 namespace {
28 
sksltype_to_alignment_mask(SkSLType type)29 uint32_t sksltype_to_alignment_mask(SkSLType type) {
30     switch(type) {
31         case SkSLType::kShort: // fall through
32         case SkSLType::kUShort:
33             return 0x1;
34         case SkSLType::kShort2: // fall through
35         case SkSLType::kUShort2:
36             return 0x3;
37         case SkSLType::kShort3: // fall through
38         case SkSLType::kShort4:
39         case SkSLType::kUShort3:
40         case SkSLType::kUShort4:
41             return 0x7;
42         case SkSLType::kInt:
43         case SkSLType::kUInt:
44             return 0x3;
45         case SkSLType::kInt2:
46         case SkSLType::kUInt2:
47             return 0x7;
48         case SkSLType::kInt3:
49         case SkSLType::kUInt3:
50         case SkSLType::kInt4:
51         case SkSLType::kUInt4:
52             return 0xF;
53         case SkSLType::kHalf: // fall through
54         case SkSLType::kFloat:
55             return 0x3;
56         case SkSLType::kHalf2: // fall through
57         case SkSLType::kFloat2:
58             return 0x7;
59         case SkSLType::kHalf3: // fall through
60         case SkSLType::kFloat3:
61             return 0xF;
62         case SkSLType::kHalf4: // fall through
63         case SkSLType::kFloat4:
64             return 0xF;
65         case SkSLType::kHalf2x2: // fall through
66         case SkSLType::kFloat2x2:
67             return 0x7;
68         case SkSLType::kHalf3x3: // fall through
69         case SkSLType::kFloat3x3:
70             return 0xF;
71         case SkSLType::kHalf4x4: // fall through
72         case SkSLType::kFloat4x4:
73             return 0xF;
74 
75         // This query is only valid for certain types.
76         case SkSLType::kVoid:
77         case SkSLType::kBool:
78         case SkSLType::kBool2:
79         case SkSLType::kBool3:
80         case SkSLType::kBool4:
81         case SkSLType::kTexture2DSampler:
82         case SkSLType::kTextureExternalSampler:
83         case SkSLType::kTexture2DRectSampler:
84         case SkSLType::kTexture2D:
85         case SkSLType::kSampler:
86         case SkSLType::kInput:
87             break;
88     }
89     SK_ABORT("Unexpected type");
90 }
91 
sksltype_to_size(SkSLType type)92 static inline uint32_t sksltype_to_size(SkSLType type) {
93     switch(type) {
94         case SkSLType::kShort:
95             return sizeof(int16_t);
96         case SkSLType::kShort2:
97             return 2 * sizeof(int16_t);
98         case SkSLType::kShort3:
99             return 3 * sizeof(int16_t);
100         case SkSLType::kShort4:
101             return 4 * sizeof(int16_t);
102         case SkSLType::kUShort:
103             return sizeof(uint16_t);
104         case SkSLType::kUShort2:
105             return 2 * sizeof(uint16_t);
106         case SkSLType::kUShort3:
107             return 3 * sizeof(uint16_t);
108         case SkSLType::kUShort4:
109             return 4 * sizeof(uint16_t);
110         case SkSLType::kHalf: // fall through
111         case SkSLType::kFloat:
112             return sizeof(float);
113         case SkSLType::kHalf2: // fall through
114         case SkSLType::kFloat2:
115             return 2 * sizeof(float);
116         case SkSLType::kHalf3: // fall through
117         case SkSLType::kFloat3:
118             return 3 * sizeof(float);
119         case SkSLType::kHalf4: // fall through
120         case SkSLType::kFloat4:
121             return 4 * sizeof(float);
122         case SkSLType::kInt: // fall through
123         case SkSLType::kUInt:
124             return sizeof(int32_t);
125         case SkSLType::kInt2: // fall through
126         case SkSLType::kUInt2:
127             return 2 * sizeof(int32_t);
128         case SkSLType::kInt3: // fall through
129         case SkSLType::kUInt3:
130             return 3 * sizeof(int32_t);
131         case SkSLType::kInt4: // fall through
132         case SkSLType::kUInt4:
133             return 4 * sizeof(int32_t);
134         case SkSLType::kHalf2x2: // fall through
135         case SkSLType::kFloat2x2:
136             //TODO: this will be 4 * szof(float) on std430.
137             return 8 * sizeof(float);
138         case SkSLType::kHalf3x3: // fall through
139         case SkSLType::kFloat3x3:
140             return 12 * sizeof(float);
141         case SkSLType::kHalf4x4: // fall through
142         case SkSLType::kFloat4x4:
143             return 16 * sizeof(float);
144 
145         // This query is only valid for certain types.
146         case SkSLType::kVoid:
147         case SkSLType::kBool:
148         case SkSLType::kBool2:
149         case SkSLType::kBool3:
150         case SkSLType::kBool4:
151         case SkSLType::kTexture2DSampler:
152         case SkSLType::kTextureExternalSampler:
153         case SkSLType::kTexture2DRectSampler:
154         case SkSLType::kTexture2D:
155         case SkSLType::kSampler:
156         case SkSLType::kInput:
157             break;
158     }
159     SK_ABORT("Unexpected type");
160 }
161 
get_ubo_offset(uint32_t * currentOffset,SkSLType type,int arrayCount)162 uint32_t get_ubo_offset(uint32_t* currentOffset, SkSLType type, int arrayCount) {
163     uint32_t alignmentMask = sksltype_to_alignment_mask(type);
164     // We want to use the std140 layout here, so we must make arrays align to 16 bytes.
165     // TODO(skia:13380): make sure 2x3 and 3x2 matrices are handled properly once SkSLType adds
166     // support for non-square matrices
167     if (arrayCount || type == SkSLType::kFloat2x2 || type == SkSLType::kHalf2x2) {
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, sksltype_to_size(type));
178         SkASSERT(0 == (elementSize & 0xF));
179         *currentOffset = uniformOffset + elementSize * arrayCount;
180     } else {
181         *currentOffset = uniformOffset + sksltype_to_size(type);
182     }
183     return uniformOffset;
184 }
185 
186 }  // namespace
187 
internalAddUniformArray(const GrProcessor * owner,uint32_t visibility,SkSLType type,const char * name,bool mangleName,int arrayCount,const char ** outName)188 GrGLSLUniformHandler::UniformHandle GrSPIRVUniformHandler::internalAddUniformArray(
189         const GrProcessor* owner,
190         uint32_t visibility,
191         SkSLType 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 & backendFormat,GrSamplerState,const skgpu::Swizzle & swizzle,const char * name,const GrShaderCaps * caps)227 GrGLSLUniformHandler::SamplerHandle GrSPIRVUniformHandler::addSampler(
228         const GrBackendFormat& backendFormat,
229         GrSamplerState,
230         const skgpu::Swizzle& swizzle,
231         const char* name,
232         const GrShaderCaps* caps) {
233     SkASSERT(name && strlen(name));
234 
235     int binding = fSamplers.count() * 2;
236 
237     SkString mangleName = fProgramBuilder->nameVariable('u', name, /*mangle=*/true);
238     SkString layoutQualifier = SkStringPrintf("direct3d, set = %d, sampler = %d, texture = %d",
239                                               kSamplerTextureDescriptorSet,
240                                               binding,
241                                               binding + 1);
242 
243     SPIRVUniformInfo& uniformInfo = fSamplers.emplace_back();
244     uniformInfo.fVariable =
245             GrShaderVar{std::move(mangleName),
246                         SkSLCombinedSamplerTypeForTextureType(backendFormat.textureType()),
247                         GrShaderVar::TypeModifier::None,
248                         GrShaderVar::kNonArray,
249                         std::move(layoutQualifier),
250                         SkString()};
251 
252     uniformInfo.fVisibility = kFragment_GrShaderFlag;
253     uniformInfo.fOwner      = nullptr;
254     uniformInfo.fRawName    = SkString(name);
255     uniformInfo.fUBOOffset  = 0;
256 
257     fSamplerSwizzles.push_back(swizzle);
258     SkASSERT(fSamplerSwizzles.size() == fSamplers.count());
259 
260     return GrGLSLUniformHandler::SamplerHandle(fSamplers.count() - 1);
261 }
262 
samplerVariable(GrGLSLUniformHandler::SamplerHandle handle) const263 const char* GrSPIRVUniformHandler::samplerVariable(
264         GrGLSLUniformHandler::SamplerHandle handle) const {
265     return fSamplers.item(handle.toIndex()).fVariable.getName().c_str();
266 }
267 
samplerSwizzle(GrGLSLUniformHandler::SamplerHandle handle) const268 skgpu::Swizzle GrSPIRVUniformHandler::samplerSwizzle(
269         GrGLSLUniformHandler::SamplerHandle handle) const {
270     return fSamplerSwizzles[handle.toIndex()];
271 }
272 
appendUniformDecls(GrShaderFlags visibility,SkString * out) const273 void GrSPIRVUniformHandler::appendUniformDecls(GrShaderFlags visibility, SkString* out) const {
274     for (const SPIRVUniformInfo& sampler : fSamplers.items()) {
275         if (sampler.fVisibility & visibility) {
276             sampler.fVariable.appendDecl(fProgramBuilder->shaderCaps(), out);
277             out->append(";\n");
278         }
279     }
280     SkString uniformsString;
281     for (const UniformInfo& uniform : fUniforms.items()) {
282         if (uniform.fVisibility & visibility) {
283             uniform.fVariable.appendDecl(fProgramBuilder->shaderCaps(), &uniformsString);
284             uniformsString.append(";\n");
285         }
286     }
287     if (!uniformsString.isEmpty()) {
288         out->appendf("layout (set = %d, binding = %d) uniform UniformBuffer\n{\n",
289                      kUniformDescriptorSet, kUniformBinding);
290         out->appendf("%s\n};\n", uniformsString.c_str());
291     }
292 }
293 
getRTFlipOffset() const294 uint32_t GrSPIRVUniformHandler::getRTFlipOffset() const {
295     uint32_t currentOffset = fCurrentUBOOffset;
296     return get_ubo_offset(&currentOffset, SkSLType::kFloat2, 0);
297 }
298