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