Index: src/gpu/vk/GrVkUniformHandler.cpp |
diff --git a/src/gpu/vk/GrVkUniformHandler.cpp b/src/gpu/vk/GrVkUniformHandler.cpp |
index 20ef9c6c400bc353c451bdf36c70cafdf4378538..55b41abf49c64197489825dc4e02dacfdf38dedc 100644 |
--- a/src/gpu/vk/GrVkUniformHandler.cpp |
+++ b/src/gpu/vk/GrVkUniformHandler.cpp |
@@ -11,6 +11,9 @@ |
// To determine whether a current offset is aligned, we can just 'and' the lowest bits with the |
// alignment mask. A value of 0 means aligned, any other value is how many bytes past alignment we |
// are. This works since all alignments are powers of 2. The mask is always (alignment - 1). |
+// This alignment mask will give correct alignments for using the std430 block layout. If you want |
+// the std140 alignment, you can use this, but then make sure if you have an array type it is |
+// aligned to 16 bytes (i.e. has mask of 0xF). |
uint32_t grsltype_to_alignment_mask(GrSLType type) { |
SkASSERT(GrSLTypeIsFloatType(type)); |
static const uint32_t kAlignments[kGrSLTypeCount] = { |
@@ -37,6 +40,44 @@ uint32_t grsltype_to_alignment_mask(GrSLType type) { |
return kAlignments[type]; |
} |
+/** Returns the size in bytes taken up in vulkanbuffers for floating point GrSLTypes. |
+ For non floating point type returns 0 */ |
+static inline uint32_t grsltype_to_vk_size(GrSLType type) { |
+ SkASSERT(GrSLTypeIsFloatType(type)); |
+ static const uint32_t kSizes[] = { |
+ 0, // kVoid_GrSLType |
+ sizeof(float), // kFloat_GrSLType |
+ 2 * sizeof(float), // kVec2f_GrSLType |
+ 3 * sizeof(float), // kVec3f_GrSLType |
+ 4 * sizeof(float), // kVec4f_GrSLType |
+ 12 * sizeof(float), // kMat33f_GrSLType |
+ 16 * sizeof(float), // kMat44f_GrSLType |
+ 0, // kSampler2D_GrSLType |
+ 0, // kSamplerExternal_GrSLType |
+ 0, // kSampler2DRect_GrSLType |
+ 0, // kBool_GrSLType |
+ 0, // kInt_GrSLType |
+ 0, // kUint_GrSLType |
+ }; |
+ return kSizes[type]; |
+ |
+ GR_STATIC_ASSERT(0 == kVoid_GrSLType); |
+ GR_STATIC_ASSERT(1 == kFloat_GrSLType); |
+ GR_STATIC_ASSERT(2 == kVec2f_GrSLType); |
+ GR_STATIC_ASSERT(3 == kVec3f_GrSLType); |
+ GR_STATIC_ASSERT(4 == kVec4f_GrSLType); |
+ GR_STATIC_ASSERT(5 == kMat33f_GrSLType); |
+ GR_STATIC_ASSERT(6 == kMat44f_GrSLType); |
+ GR_STATIC_ASSERT(7 == kSampler2D_GrSLType); |
+ GR_STATIC_ASSERT(8 == kSamplerExternal_GrSLType); |
+ GR_STATIC_ASSERT(9 == kSampler2DRect_GrSLType); |
+ GR_STATIC_ASSERT(10 == kBool_GrSLType); |
+ GR_STATIC_ASSERT(11 == kInt_GrSLType); |
+ GR_STATIC_ASSERT(12 == kUint_GrSLType); |
+ GR_STATIC_ASSERT(13 == kGrSLTypeCount); |
+} |
+ |
+ |
// Given the current offset into the ubo, calculate the offset for the uniform we're trying to add |
// taking into consideration all alignment requirements. The uniformOffset is set to the offset for |
// the new uniform, and currentOffset is updated to be the offset to the end of the new uniform. |
@@ -45,16 +86,23 @@ void get_ubo_aligned_offset(uint32_t* uniformOffset, |
GrSLType type, |
int arrayCount) { |
uint32_t alignmentMask = grsltype_to_alignment_mask(type); |
+ // We want to use the std140 layout here, so we must make arrays align to 16 bytes. |
+ if (arrayCount) { |
+ alignmentMask = 0xF; |
+ } |
uint32_t offsetDiff = *currentOffset & alignmentMask; |
if (offsetDiff != 0) { |
offsetDiff = alignmentMask - offsetDiff + 1; |
} |
*uniformOffset = *currentOffset + offsetDiff; |
SkASSERT(sizeof(float) == 4); |
- // We use a 0 arrayCount to indicate it is not an array type but we still need to count the one |
- // object. |
- int count = arrayCount ? arrayCount : 1; |
- *currentOffset = *uniformOffset + count * (uint32_t)GrSLTypeSize(type); |
+ if (arrayCount) { |
+ uint32_t elementSize = SkTMax<uint32_t>(16, grsltype_to_vk_size(type)); |
+ SkASSERT(0 == (elementSize & 0xF)); |
+ *currentOffset = *uniformOffset + elementSize * arrayCount; |
+ } else { |
+ *currentOffset = *uniformOffset + grsltype_to_vk_size(type); |
+ } |
} |
GrGLSLUniformHandler::UniformHandle GrVkUniformHandler::internalAddUniformArray( |
@@ -146,4 +194,5 @@ void GrVkUniformHandler::appendUniformDecls(GrShaderFlags visibility, SkString* |
kUniformBufferDescSet, uniformBinding, stage); |
out->appendf("%s\n};\n", uniformsString.c_str()); |
} |
-} |
+} |
+ |