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 |