| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright 2016 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 "GrVkUniformHandler.h" | |
| 9 #include "glsl/GrGLSLProgramBuilder.h" | |
| 10 | |
| 11 // To determine whether a current offset is aligned, we can just 'and' the lowes
t bits with the | |
| 12 // alignment mask. A value of 0 means aligned, any other value is how many bytes
past alignment we | |
| 13 // are. This works since all alignments are powers of 2. The mask is always (ali
gnment - 1). | |
| 14 uint32_t grsltype_to_alignment_mask(GrSLType type) { | |
| 15 SkASSERT(GrSLTypeIsFloatType(type)); | |
| 16 static const uint32_t kAlignments[kGrSLTypeCount] = { | |
| 17 0x0, // kVoid_GrSLType, should never return this | |
| 18 0x3, // kFloat_GrSLType | |
| 19 0x7, // kVec2f_GrSLType | |
| 20 0xF, // kVec3f_GrSLType | |
| 21 0xF, // kVec4f_GrSLType | |
| 22 0xF, // kMat33f_GrSLType | |
| 23 0xF, // kMat44f_GrSLType | |
| 24 0x0, // Sampler2D_GrSLType, should never return this | |
| 25 0x0, // SamplerExternal_GrSLType, should never return this | |
| 26 }; | |
| 27 GR_STATIC_ASSERT(0 == kVoid_GrSLType); | |
| 28 GR_STATIC_ASSERT(1 == kFloat_GrSLType); | |
| 29 GR_STATIC_ASSERT(2 == kVec2f_GrSLType); | |
| 30 GR_STATIC_ASSERT(3 == kVec3f_GrSLType); | |
| 31 GR_STATIC_ASSERT(4 == kVec4f_GrSLType); | |
| 32 GR_STATIC_ASSERT(5 == kMat33f_GrSLType); | |
| 33 GR_STATIC_ASSERT(6 == kMat44f_GrSLType); | |
| 34 GR_STATIC_ASSERT(7 == kSampler2D_GrSLType); | |
| 35 GR_STATIC_ASSERT(8 == kSamplerExternal_GrSLType); | |
| 36 GR_STATIC_ASSERT(SK_ARRAY_COUNT(kAlignments) == kGrSLTypeCount); | |
| 37 return kAlignments[type]; | |
| 38 } | |
| 39 | |
| 40 // Given the current offset into the ubo, calculate the offset for the uniform w
e're trying to add | |
| 41 // taking into consideration all alignment requirements. The uniformOffset is se
t to the offset for | |
| 42 // the new uniform, and currentOffset is updated to be the offset to the end of
the new uniform. | |
| 43 void get_ubo_aligned_offset(uint32_t* uniformOffset, | |
| 44 uint32_t* currentOffset, | |
| 45 GrSLType type, | |
| 46 int arrayCount) { | |
| 47 uint32_t alignmentMask = grsltype_to_alignment_mask(type); | |
| 48 uint32_t offsetDiff = *currentOffset & alignmentMask; | |
| 49 if (offsetDiff != 0) { | |
| 50 offsetDiff = alignmentMask - offsetDiff + 1; | |
| 51 } | |
| 52 *uniformOffset = *currentOffset + offsetDiff; | |
| 53 SkASSERT(sizeof(float) == 4); | |
| 54 // We use a 0 arrayCount to indicate it is not an array type but we still ne
ed to count the one | |
| 55 // object. | |
| 56 int count = arrayCount ? arrayCount : 1; | |
| 57 *currentOffset = *uniformOffset + count * (uint32_t)GrSLTypeSize(type); | |
| 58 } | |
| 59 | |
| 60 GrGLSLUniformHandler::UniformHandle GrVkUniformHandler::internalAddUniformArray( | |
| 61 uint
32_t visibility, | |
| 62 GrSL
Type type, | |
| 63 GrSL
Precision precision, | |
| 64 cons
t char* name, | |
| 65 bool
mangleName, | |
| 66 int
arrayCount, | |
| 67 cons
t char** outName) { | |
| 68 SkASSERT(name && strlen(name)); | |
| 69 SkDEBUGCODE(static const uint32_t kVisibilityMask = kVertex_GrShaderFlag|kFr
agment_GrShaderFlag); | |
| 70 SkASSERT(0 == (~kVisibilityMask & visibility)); | |
| 71 SkASSERT(0 != visibility); | |
| 72 SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeIsFloatType(type)); | |
| 73 | |
| 74 UniformInfo& uni = fUniforms.push_back(); | |
| 75 uni.fVariable.setType(type); | |
| 76 // TODO this is a bit hacky, lets think of a better way. Basically we need
to be able to use | |
| 77 // the uniform view matrix name in the GP, and the GP is immutable so it has
to tell the PB | |
| 78 // exactly what name it wants to use for the uniform view matrix. If we pre
fix anythings, then | |
| 79 // the names will mismatch. I think the correct solution is to have all GPs
which need the | |
| 80 // uniform view matrix, they should upload the view matrix in their setData
along with regular | |
| 81 // uniforms. | |
| 82 char prefix = 'u'; | |
| 83 if ('u' == name[0]) { | |
| 84 prefix = '\0'; | |
| 85 } | |
| 86 fProgramBuilder->nameVariable(uni.fVariable.accessName(), prefix, name, mang
leName); | |
| 87 uni.fVariable.setArrayCount(arrayCount); | |
| 88 // For now asserting the the visibility is either only vertex or only fragme
nt | |
| 89 SkASSERT(kVertex_GrShaderFlag == visibility || kFragment_GrShaderFlag == vis
ibility); | |
| 90 uni.fVisibility = visibility; | |
| 91 uni.fVariable.setPrecision(precision); | |
| 92 if (GrSLTypeIsFloatType(type)) { | |
| 93 // When outputing the GLSL, only the outer uniform block will get the Un
iform modifier. Thus | |
| 94 // we set the modifier to none for all uniforms declared inside the bloc
k. | |
| 95 uni.fVariable.setTypeModifier(GrGLSLShaderVar::kNone_TypeModifier); | |
| 96 | |
| 97 uint32_t* currentOffset = kVertex_GrShaderFlag == visibility ? &fCurrent
VertexUBOOffset | |
| 98 : &fCurrent
FragmentUBOOffset; | |
| 99 get_ubo_aligned_offset(&uni.fUBOffset, currentOffset, type, arrayCount); | |
| 100 uni.fSetNumber = kUniformBufferDescSet; | |
| 101 uni.fBinding = kVertex_GrShaderFlag == visibility ? kVertexBinding : kFr
agBinding; | |
| 102 | |
| 103 if (outName) { | |
| 104 *outName = uni.fVariable.c_str(); | |
| 105 } | |
| 106 } else { | |
| 107 SkASSERT(type == kSampler2D_GrSLType); | |
| 108 uni.fVariable.setTypeModifier(GrGLSLShaderVar::kUniform_TypeModifier); | |
| 109 | |
| 110 uni.fSetNumber = kSamplerDescSet; | |
| 111 uni.fBinding = fCurrentSamplerBinding++; | |
| 112 uni.fUBOffset = 0; // This value will be ignored, but initializing to av
oid any errors. | |
| 113 SkString layoutQualifier; | |
| 114 layoutQualifier.appendf("set=%d, binding=%d", uni.fSetNumber, uni.fBindi
ng); | |
| 115 uni.fVariable.setLayoutQualifier(layoutQualifier.c_str()); | |
| 116 } | |
| 117 | |
| 118 return GrGLSLUniformHandler::UniformHandle(fUniforms.count() - 1); | |
| 119 } | |
| 120 | |
| 121 void GrVkUniformHandler::appendUniformDecls(GrShaderFlags visibility, SkString*
out) const { | |
| 122 SkTArray<UniformInfo*> uniformBufferUniform; | |
| 123 // Used to collect all the variables that will be place inside the uniform b
uffer | |
| 124 SkString uniformsString; | |
| 125 SkASSERT(kVertex_GrShaderFlag == visibility || kFragment_GrShaderFlag == vis
ibility); | |
| 126 uint32_t uniformBinding = (visibility == kVertex_GrShaderFlag) ? kVertexBind
ing : kFragBinding; | |
| 127 for (int i = 0; i < fUniforms.count(); ++i) { | |
| 128 const UniformInfo& localUniform = fUniforms[i]; | |
| 129 if (visibility == localUniform.fVisibility) { | |
| 130 if (GrSLTypeIsFloatType(localUniform.fVariable.getType())) { | |
| 131 SkASSERT(uniformBinding == localUniform.fBinding); | |
| 132 SkASSERT(kUniformBufferDescSet == localUniform.fSetNumber); | |
| 133 localUniform.fVariable.appendDecl(fProgramBuilder->glslCaps(), &
uniformsString); | |
| 134 uniformsString.append(";\n"); | |
| 135 } else { | |
| 136 SkASSERT(localUniform.fVariable.getType() == kSampler2D_GrSLType
); | |
| 137 SkASSERT(kSamplerDescSet == localUniform.fSetNumber); | |
| 138 localUniform.fVariable.appendDecl(fProgramBuilder->glslCaps(), o
ut); | |
| 139 out->append(";\n"); | |
| 140 } | |
| 141 } | |
| 142 } | |
| 143 if (!uniformsString.isEmpty()) { | |
| 144 const char* stage = (visibility == kVertex_GrShaderFlag) ? "vertex" : "f
ragment"; | |
| 145 out->appendf("layout (set=%d, binding=%d) uniform %sUniformBuffer\n{\n", | |
| 146 kUniformBufferDescSet, uniformBinding, stage); | |
| 147 out->appendf("%s\n};\n", uniformsString.c_str()); | |
| 148 } | |
| 149 } | |
| OLD | NEW |