Flutter Engine
The Flutter Engine
GrSPIRVUniformHandler.cpp
Go to the documentation of this file.
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
9
12
13GrSPIRVUniformHandler::GrSPIRVUniformHandler(GrGLSLProgramBuilder* program)
14 : INHERITED(program)
15 , fUniforms(kUniformsPerBlock)
16 , fSamplers(kUniformsPerBlock) {}
17
19 return fUniforms.item(u.toIndex()).fVariable;
20}
21
23 return fUniforms.item(u.toIndex()).fVariable.getName().c_str();
24}
25
26// FIXME: this code was ripped from GrVkUniformHandler; should be refactored.
27namespace {
28
30 switch(type) {
31 case SkSLType::kShort: // fall through
33 return 0x1;
34 case SkSLType::kShort2: // fall through
36 return 0x3;
37 case SkSLType::kShort3: // fall through
41 return 0x7;
42 case SkSLType::kInt:
43 case SkSLType::kUInt:
44 return 0x3;
45 case SkSLType::kInt2:
47 return 0x7;
48 case SkSLType::kInt3:
50 case SkSLType::kInt4:
52 return 0xF;
53 case SkSLType::kHalf: // fall through
55 return 0x3;
56 case SkSLType::kHalf2: // fall through
58 return 0x7;
59 case SkSLType::kHalf3: // fall through
61 return 0xF;
62 case SkSLType::kHalf4: // fall through
64 return 0xF;
65 case SkSLType::kHalf2x2: // fall through
67 return 0x7;
68 case SkSLType::kHalf3x3: // fall through
70 return 0xF;
71 case SkSLType::kHalf4x4: // fall through
73 return 0xF;
74
75 // This query is only valid for certain types.
76 case SkSLType::kVoid:
77 case SkSLType::kBool:
87 break;
88 }
89 SK_ABORT("Unexpected type");
90}
91
92static inline uint32_t sksltype_to_size(SkSLType type) {
93 switch(type) {
95 return sizeof(int16_t);
97 return 2 * sizeof(int16_t);
99 return 3 * sizeof(int16_t);
101 return 4 * sizeof(int16_t);
103 return sizeof(uint16_t);
105 return 2 * sizeof(uint16_t);
107 return 3 * sizeof(uint16_t);
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
115 return 2 * sizeof(float);
116 case SkSLType::kHalf3: // fall through
118 return 3 * sizeof(float);
119 case SkSLType::kHalf4: // fall through
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
136 //TODO: this will be 4 * szof(float) on std430.
137 return 8 * sizeof(float);
138 case SkSLType::kHalf3x3: // fall through
140 return 12 * sizeof(float);
141 case SkSLType::kHalf4x4: // fall through
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:
156 case SkSLType::kInput:
157 break;
158 }
159 SK_ABORT("Unexpected type");
160}
161
162uint32_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
188GrGLSLUniformHandler::UniformHandle GrSPIRVUniformHandler::internalAddUniformArray(
189 const GrProcessor* owner,
190 uint32_t visibility,
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,
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
227GrGLSLUniformHandler::SamplerHandle GrSPIRVUniformHandler::addSampler(
228 const GrBackendFormat& backendFormat,
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",
240 binding,
241 binding + 1);
242
243 SPIRVUniformInfo& uniformInfo = fSamplers.emplace_back();
244 uniformInfo.fVariable =
245 GrShaderVar{std::move(mangleName),
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
263const char* GrSPIRVUniformHandler::samplerVariable(
264 GrGLSLUniformHandler::SamplerHandle handle) const {
265 return fSamplers.item(handle.toIndex()).fVariable.getName().c_str();
266}
267
268skgpu::Swizzle GrSPIRVUniformHandler::samplerSwizzle(
269 GrGLSLUniformHandler::SamplerHandle handle) const {
270 return fSamplerSwizzles[handle.toIndex()];
271}
272
273void 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) {
284 uniformsString.append(";\n");
285 }
286 }
287 if (!uniformsString.isEmpty()) {
288 out->appendf("layout (set = %d, binding = %d) uniform UniformBuffer\n{\n",
290 out->appendf("%s\n};\n", uniformsString.c_str());
291 }
292}
293
295 uint32_t currentOffset = fCurrentUBOOffset;
296 return get_ubo_offset(&currentOffset, SkSLType::kFloat2, 0);
297}
#define GR_NO_MANGLE_PREFIX
static GR_NORETAIN_BEGIN uint32_t sksltype_to_alignment_mask(SkSLType type)
GrShaderFlags
Definition: GrTypesPriv.h:284
@ kFragment_GrShaderFlag
Definition: GrTypesPriv.h:287
static SkSLType SkSLCombinedSamplerTypeForTextureType(GrTextureType type)
Definition: GrUtil.h:50
#define SK_ABORT(message,...)
Definition: SkAssert.h:70
#define SkASSERT(cond)
Definition: SkAssert.h:116
#define INHERITED(method,...)
Definition: SkRecorder.cpp:128
SkSLType
@ kTextureExternalSampler
@ kTexture2DSampler
@ kTexture2DRectSampler
SK_API SkString SkStringPrintf(const char *format,...) SK_PRINTF_LIKE(1
Creates a new string and writes into it using a printf()-style format.
GLenum type
GrTextureType textureType() const
SkString nameVariable(char prefix, const char *name, bool mangle=true)
const GrShaderCaps * shaderCaps() const
GrGLSLProgramBuilder * fProgramBuilder
GrGLSLProgramDataManager::UniformHandle UniformHandle
UniformInfo & uniform(int idx) override
const GrShaderVar & getUniformVariable(UniformHandle u) const override
const char * getUniformCStr(UniformHandle u) const override
const char * c_str() const
Definition: GrShaderVar.h:94
const SkString & getName() const
Definition: GrShaderVar.h:91
void appendDecl(const GrShaderCaps *, SkString *out) const
Definition: GrShaderVar.cpp:23
bool isEmpty() const
Definition: SkString.h:130
void append(const char text[])
Definition: SkString.h:203
const char * c_str() const
Definition: SkString.h:133
void void void appendf(const char format[],...) SK_PRINTF_LIKE(2
Definition: SkString.cpp:550
T & item(int i)
Definition: SkTBlockList.h:217
T & push_back()
Definition: SkTBlockList.h:90
int count() const
Definition: SkTBlockList.h:167
T & emplace_back(Args &&... args)
Definition: SkTBlockList.h:101
int size() const
Definition: SkTArray.h:421
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32
SeparatedVector2 offset