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 12GrSPIRVUniformHandler::GrSPIRVUniformHandler(GrGLSLProgramBuilder* program) 13 : INHERITED(program) 14 , fUniforms(kUniformsPerBlock) 15 , fSamplers(kUniformsPerBlock) 16 , fTextures(kUniformsPerBlock) 17{ 18} 19 20const GrShaderVar& GrSPIRVUniformHandler::getUniformVariable(UniformHandle u) const { 21 return fUniforms.item(u.toIndex()).fVariable; 22} 23 24const 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. 29namespace { 30 31uint32_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 94static 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 164uint32_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 188GrGLSLUniformHandler::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 227GrGLSLUniformHandler::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 274const char* GrSPIRVUniformHandler::samplerVariable( 275 GrGLSLUniformHandler::SamplerHandle handle) const { 276 return fSamplerReferences[handle.toIndex()].c_str(); 277} 278 279GrSwizzle GrSPIRVUniformHandler::samplerSwizzle(GrGLSLUniformHandler::SamplerHandle handle) const { 280 return fSamplerSwizzles[handle.toIndex()]; 281} 282 283void 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 308uint32_t GrSPIRVUniformHandler::getRTFlipOffset() const { 309 uint32_t currentOffset = fCurrentUBOOffset; 310 return get_ubo_offset(¤tOffset, kFloat2_GrSLType, 0); 311} 312