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(¤tOffset, kFloat2_GrSLType, 0); 311cb93a386Sopenharmony_ci} 312