switch (type.getQualifier().layoutPacking) {
case glslang::ElpStd140:
case glslang::ElpStd430:
+ case glslang::ElpScalar:
return type.getQualifier().layoutPacking;
default:
return glslang::ElpNone;
{
int size;
int stride;
- glslangIntermediate->getBaseAlignment(arrayType, size, stride, explicitLayout == glslang::ElpStd140, matrixLayout == glslang::ElmRowMajor);
+ glslangIntermediate->getMemberAlignment(arrayType, size, stride, explicitLayout, matrixLayout == glslang::ElmRowMajor);
return stride;
}
int size;
int stride;
- glslangIntermediate->getBaseAlignment(elementType, size, stride, explicitLayout == glslang::ElpStd140, matrixLayout == glslang::ElmRowMajor);
+ glslangIntermediate->getMemberAlignment(elementType, size, stride, explicitLayout, matrixLayout == glslang::ElmRowMajor);
return stride;
}
int memberSize;
int dummyStride;
- int memberAlignment = glslangIntermediate->getBaseAlignment(memberType, memberSize, dummyStride, explicitLayout == glslang::ElpStd140, matrixLayout == glslang::ElmRowMajor);
+ int memberAlignment = glslangIntermediate->getMemberAlignment(memberType, memberSize, dummyStride, explicitLayout, matrixLayout == glslang::ElmRowMajor);
// Adjust alignment for HLSL rules
// TODO: make this consistent in early phases of code:
glslang::RoundToPow2(currentOffset, memberAlignment);
// Bump up to vec4 if there is a bad straddle
- if (glslangIntermediate->improperStraddle(memberType, memberSize, currentOffset))
+ if (explicitLayout != glslang::ElpScalar && glslangIntermediate->improperStraddle(memberType, memberSize, currentOffset))
glslang::RoundToPow2(currentOffset, 16);
nextOffset = currentOffset + memberSize;
ERROR: 0:169: 'Bblock' : cannot add storage, auxiliary, memory, interpolation, layout, or precision qualifier to an existing variable
ERROR: 0:170: 'Bfoo' : cannot add storage, auxiliary, memory, interpolation, layout, or precision qualifier to an existing variable
ERROR: 0:172: 'std430' : not supported for this version or the enabled extensions
-ERROR: 0:172: 'std430' : requires the 'buffer' storage qualifier
+ERROR: 0:172: 'std430 requires the buffer storage qualifier' : required extension not requested: GL_EXT_scalar_block_layout
ERROR: 0:175: '' : array size required
ERROR: 0:185: 'assign' : cannot convert from ' temp 4-element array of highp float' to ' temp 3-element array of highp float'
ERROR: 0:186: 'assign' : cannot convert from ' temp 3-element array of highp float' to ' temp 4-element array of highp float'
ERROR: 0:79: 'vertex-shader array-of-struct output' : not supported with this profile: es
ERROR: 0:81: 'vertex-shader struct output containing an array' : not supported with this profile: es
ERROR: 0:83: 'vertex-shader struct output containing structure' : not supported with this profile: es
-ERROR: 0:85: 'std430' : requires the 'buffer' storage qualifier
+ERROR: 0:85: 'std430 requires the buffer storage qualifier' : required extension not requested: GL_EXT_scalar_block_layout
ERROR: 0:97: 's' : member of block cannot be or contain a sampler, image, or atomic_uint type
ERROR: 0:105: 'location' : overlapping use of location 12
ERROR: 0:107: 'input block' : not supported in this stage: vertex
ERROR: 0:143: 'rgba32ui' : does not apply to signed integer images
ERROR: 0:144: 'r8ui' : does not apply to signed integer images
ERROR: 0:147: 'offset on block member' : not supported for this version or the enabled extensions
-ERROR: 0:147: 'offset/align' : can only be used with std140 or std430 layout packing
+ERROR: 0:147: 'offset/align' : can only be used with std140, std430, or scalar layout packing
ERROR: 0:157: 'textureQueryLevels' : no matching overloaded function found
ERROR: 0:157: 'assign' : cannot convert from ' const float' to ' temp int'
ERROR: 0:158: 'textureQueryLevels' : no matching overloaded function found
ERROR: 0:65: 'uniform buffer-member align' : not supported for this version or the enabled extensions
ERROR: 0:65: 'offset on block member' : not supported for this version or the enabled extensions
ERROR: 0:66: 'offset on block member' : not supported for this version or the enabled extensions
-ERROR: 0:64: 'align' : can only be used with std140 or std430 layout packing
-ERROR: 0:65: 'offset/align' : can only be used with std140 or std430 layout packing
-ERROR: 0:66: 'offset/align' : can only be used with std140 or std430 layout packing
+ERROR: 0:64: 'align' : can only be used with std140, std430, or scalar layout packing
+ERROR: 0:65: 'offset/align' : can only be used with std140, std430, or scalar layout packing
+ERROR: 0:66: 'offset/align' : can only be used with std140, std430, or scalar layout packing
ERROR: 0:71: 'offset on block member' : not supported for this version or the enabled extensions
ERROR: 0:74: 'gl_MaxTransformFeedbackBuffers' : required extension not requested: GL_ARB_enhanced_layouts
ERROR: 0:75: 'gl_MaxTransformFeedbackInterleavedComponents' : required extension not requested: GL_ARB_enhanced_layouts
ERROR: 0:39: 'output block' : not supported in this stage: fragment
ERROR: 0:39: 'layout' : offset/align can only be used on a uniform or buffer
ERROR: 0:39: 'offset' : only applies to block members, not blocks
-ERROR: 0:42: 'align' : can only be used with std140 or std430 layout packing
-ERROR: 0:43: 'align' : can only be used with std140 or std430 layout packing
+ERROR: 0:42: 'align' : can only be used with std140, std430, or scalar layout packing
+ERROR: 0:43: 'align' : can only be used with std140, std430, or scalar layout packing
ERROR: 0:43: 'layout' : offset/align can only be used on a uniform or buffer
ERROR: 0:44: 'output block' : not supported in this stage: fragment
-ERROR: 0:44: 'align' : can only be used with std140 or std430 layout packing
+ERROR: 0:44: 'align' : can only be used with std140, std430, or scalar layout packing
ERROR: 0:44: 'layout' : offset/align can only be used on a uniform or buffer
ERROR: 0:46: 'offset' : cannot specify on a variable declaration
ERROR: 0:47: 'layout' : offset/align can only be used on a uniform or buffer
ERROR: 0:54: 'layout' : matrix or packing qualifiers can only be used on a uniform or buffer
ERROR: 0:55: 'layout' : cannot specify packing on a variable declaration
ERROR: 0:57: 'align' : must be a power of 2
-ERROR: 0:58: 'offset/align' : can only be used with std140 or std430 layout packing
-ERROR: 0:62: 'offset/align' : can only be used with std140 or std430 layout packing
-ERROR: 0:63: 'offset/align' : can only be used with std140 or std430 layout packing
+ERROR: 0:58: 'offset/align' : can only be used with std140, std430, or scalar layout packing
+ERROR: 0:62: 'offset/align' : can only be used with std140, std430, or scalar layout packing
+ERROR: 0:63: 'offset/align' : can only be used with std140, std430, or scalar layout packing
ERROR: 0:62: 'layout' : offset/align can only be used on a uniform or buffer
ERROR: 0:63: 'layout' : offset/align can only be used on a uniform or buffer
ERROR: 0:84: 'align' : must be a power of 2
--- /dev/null
+spv.scalarlayout.frag
+error: SPIRV-Tools Validation Errors
+error: Structure id 17 decorated as Block for variable in Uniform storage class must follow standard uniform buffer layout rules: member 1 at offset 4 is not aligned to 8
+ %B1 = OpTypeStruct %float %v2float %v3float %_arr_float_uint_2 %mat2v3float %_arr_mat2v3float_uint_2 %float %S %_arr_S_uint_2
+
+// Module Version 10000
+// Generated by (magic number): 80007
+// Id's are bound by 20
+
+ Capability Shader
+ Capability Float64
+ 1: ExtInstImport "GLSL.std.450"
+ MemoryModel Logical GLSL450
+ EntryPoint Fragment 4 "main"
+ ExecutionMode 4 OriginUpperLeft
+ Source GLSL 450
+ SourceExtension "GL_EXT_scalar_block_layout"
+ Name 4 "main"
+ Name 15 "S"
+ MemberName 15(S) 0 "a"
+ MemberName 15(S) 1 "b"
+ MemberName 15(S) 2 "c"
+ MemberName 15(S) 3 "d"
+ MemberName 15(S) 4 "e"
+ MemberName 15(S) 5 "f"
+ Name 17 "B1"
+ MemberName 17(B1) 0 "a"
+ MemberName 17(B1) 1 "b"
+ MemberName 17(B1) 2 "c"
+ MemberName 17(B1) 3 "d"
+ MemberName 17(B1) 4 "e"
+ MemberName 17(B1) 5 "f"
+ MemberName 17(B1) 6 "g"
+ MemberName 17(B1) 7 "h"
+ MemberName 17(B1) 8 "i"
+ Name 19 ""
+ Decorate 11 ArrayStride 4
+ Decorate 13 ArrayStride 24
+ MemberDecorate 15(S) 0 Offset 0
+ MemberDecorate 15(S) 1 Offset 4
+ MemberDecorate 15(S) 2 Offset 16
+ MemberDecorate 15(S) 3 Offset 24
+ MemberDecorate 15(S) 4 Offset 28
+ MemberDecorate 15(S) 5 Offset 40
+ Decorate 16 ArrayStride 48
+ MemberDecorate 17(B1) 0 Offset 0
+ MemberDecorate 17(B1) 1 Offset 4
+ MemberDecorate 17(B1) 2 Offset 12
+ MemberDecorate 17(B1) 3 Offset 24
+ MemberDecorate 17(B1) 4 ColMajor
+ MemberDecorate 17(B1) 4 Offset 32
+ MemberDecorate 17(B1) 4 MatrixStride 12
+ MemberDecorate 17(B1) 5 ColMajor
+ MemberDecorate 17(B1) 5 Offset 56
+ MemberDecorate 17(B1) 5 MatrixStride 12
+ MemberDecorate 17(B1) 6 Offset 104
+ MemberDecorate 17(B1) 7 Offset 112
+ MemberDecorate 17(B1) 8 Offset 160
+ Decorate 17(B1) Block
+ Decorate 19 DescriptorSet 0
+ 2: TypeVoid
+ 3: TypeFunction 2
+ 6: TypeFloat 32
+ 7: TypeVector 6(float) 2
+ 8: TypeVector 6(float) 3
+ 9: TypeInt 32 0
+ 10: 9(int) Constant 2
+ 11: TypeArray 6(float) 10
+ 12: TypeMatrix 8(fvec3) 2
+ 13: TypeArray 12 10
+ 14: TypeFloat 64
+ 15(S): TypeStruct 6(float) 7(fvec2) 14(float64_t) 6(float) 8(fvec3) 6(float)
+ 16: TypeArray 15(S) 10
+ 17(B1): TypeStruct 6(float) 7(fvec2) 8(fvec3) 11 12 13 6(float) 15(S) 16
+ 18: TypePointer Uniform 17(B1)
+ 19: 18(ptr) Variable Uniform
+ 4(main): 2 Function None 3
+ 5: Label
+ Return
+ FunctionEnd
--- /dev/null
+spv.scalarlayoutfloat16.frag
+error: SPIRV-Tools Validation Errors
+error: Structure id 15 decorated as Block for variable in Uniform storage class must follow standard uniform buffer layout rules: member 1 at offset 2 is not aligned to 4
+ %B1 = OpTypeStruct %half %v2half %v3half %_arr_half_uint_2 %half %S %_arr_S_uint_2
+
+// Module Version 10000
+// Generated by (magic number): 80007
+// Id's are bound by 18
+
+ Capability Shader
+ Capability Float64
+ Capability StorageUniform16
+ Extension "SPV_KHR_16bit_storage"
+ 1: ExtInstImport "GLSL.std.450"
+ MemoryModel Logical GLSL450
+ EntryPoint Fragment 4 "main"
+ ExecutionMode 4 OriginUpperLeft
+ Source GLSL 450
+ SourceExtension "GL_EXT_scalar_block_layout"
+ SourceExtension "GL_EXT_shader_16bit_storage"
+ Name 4 "main"
+ Name 13 "S"
+ MemberName 13(S) 0 "a"
+ MemberName 13(S) 1 "b"
+ MemberName 13(S) 2 "c"
+ MemberName 13(S) 3 "d"
+ MemberName 13(S) 4 "e"
+ MemberName 13(S) 5 "f"
+ Name 15 "B1"
+ MemberName 15(B1) 0 "a"
+ MemberName 15(B1) 1 "b"
+ MemberName 15(B1) 2 "c"
+ MemberName 15(B1) 3 "d"
+ MemberName 15(B1) 4 "g"
+ MemberName 15(B1) 5 "h"
+ MemberName 15(B1) 6 "i"
+ Name 17 ""
+ Decorate 11 ArrayStride 2
+ MemberDecorate 13(S) 0 Offset 0
+ MemberDecorate 13(S) 1 Offset 2
+ MemberDecorate 13(S) 2 Offset 8
+ MemberDecorate 13(S) 3 Offset 16
+ MemberDecorate 13(S) 4 Offset 18
+ MemberDecorate 13(S) 5 Offset 24
+ Decorate 14 ArrayStride 32
+ MemberDecorate 15(B1) 0 Offset 0
+ MemberDecorate 15(B1) 1 Offset 2
+ MemberDecorate 15(B1) 2 Offset 6
+ MemberDecorate 15(B1) 3 Offset 12
+ MemberDecorate 15(B1) 4 Offset 16
+ MemberDecorate 15(B1) 5 Offset 24
+ MemberDecorate 15(B1) 6 Offset 56
+ Decorate 15(B1) Block
+ Decorate 17 DescriptorSet 0
+ 2: TypeVoid
+ 3: TypeFunction 2
+ 6: TypeFloat 16
+ 7: TypeVector 6(float16_t) 2
+ 8: TypeVector 6(float16_t) 3
+ 9: TypeInt 32 0
+ 10: 9(int) Constant 2
+ 11: TypeArray 6(float16_t) 10
+ 12: TypeFloat 64
+ 13(S): TypeStruct 6(float16_t) 7(f16vec2) 12(float64_t) 6(float16_t) 8(f16vec3) 6(float16_t)
+ 14: TypeArray 13(S) 10
+ 15(B1): TypeStruct 6(float16_t) 7(f16vec2) 8(f16vec3) 11 6(float16_t) 13(S) 14
+ 16: TypePointer Uniform 15(B1)
+ 17: 16(ptr) Variable Uniform
+ 4(main): 2 Function None 3
+ 5: Label
+ Return
+ FunctionEnd
--- /dev/null
+#version 450 core\r
+\r
+#extension GL_EXT_scalar_block_layout : enable\r
+\r
+// Block memory layout\r
+struct S\r
+{\r
+ float a; // offset 0\r
+ vec2 b; // offset 4\r
+ double c; // offset 16\r
+ float d; // offset 24\r
+ vec3 e; // offset 28\r
+ float f; // offset 40\r
+ // size = 44, align = 8\r
+};\r
+\r
+layout(column_major, scalar) uniform B1\r
+{\r
+ float a; // offset = 0\r
+ vec2 b; // offset = 4\r
+ vec3 c; // offset = 12\r
+ float d[2]; // offset = 24\r
+ mat2x3 e; // offset = 32, takes 24 bytes, matrixstride = 12\r
+ mat2x3 f[2]; // offset = 56, takes 48 bytes, matrixstride = 12, arraystride = 24\r
+ float g; // offset = 104\r
+ S h; // offset = 112 (aligned to multiple of 8)\r
+ S i[2]; // offset = 160 (aligned to multiple of 8) stride = 48\r
+};\r
+\r
+void main()\r
+{\r
+}\r
--- /dev/null
+#version 450 core\r
+\r
+#extension GL_EXT_shader_16bit_storage: enable\r
+#extension GL_EXT_scalar_block_layout : enable\r
+\r
+// Block memory layout\r
+struct S\r
+{\r
+ float16_t a; // offset 0\r
+ f16vec2 b; // offset 2\r
+ double c; // offset 8\r
+ float16_t d; // offset 16\r
+ f16vec3 e; // offset 18\r
+ float16_t f; // offset 24\r
+ // size = 26, align = 8\r
+};\r
+\r
+layout(column_major, scalar) uniform B1\r
+{\r
+ float16_t a; // offset = 0\r
+ f16vec2 b; // offset = 2\r
+ f16vec3 c; // offset = 6\r
+ float16_t d[2]; // offset = 12 stride = 2\r
+ float16_t g; // offset = 16\r
+ S h; // offset = 24 (aligned to multiple of 8)\r
+ S i[2]; // offset = 56 (aligned to multiple of 8) stride = 32\r
+};\r
+\r
+void main()\r
+{\r
+}\r
ElpStd140,
ElpStd430,
ElpPacked,
+ ElpScalar,
ElpCount // If expanding, see bitfield width below
};
case ElpShared: return "shared";
case ElpStd140: return "std140";
case ElpStd430: return "std430";
+ case ElpScalar: return "scalar";
default: return "none";
}
}
publicType.qualifier.layoutPacking = ElpStd430;
return;
}
+ if (id == TQualifier::getLayoutPackingString(ElpScalar)) {
+ requireVulkan(loc, "scalar");
+ requireExtensions(loc, 1, &E_GL_EXT_scalar_block_layout, "scalar block layout");
+ publicType.qualifier.layoutPacking = ElpScalar;
+ return;
+ }
// TODO: compile-time performance: may need to stop doing linear searches
for (TLayoutFormat format = (TLayoutFormat)(ElfNone + 1); format < ElfCount; format = (TLayoutFormat)(format + 1)) {
if (id == TQualifier::getLayoutFormatString(format)) {
// "The align qualifier can only be used on blocks or block members, and only for blocks declared with std140 or std430 layouts."
if (currentBlockQualifier.hasAlign()) {
- if (defaultQualification.layoutPacking != ElpStd140 && defaultQualification.layoutPacking != ElpStd430) {
- error(loc, "can only be used with std140 or std430 layout packing", "align", "");
+ if (defaultQualification.layoutPacking != ElpStd140 &&
+ defaultQualification.layoutPacking != ElpStd430 &&
+ defaultQualification.layoutPacking != ElpScalar) {
+ error(loc, "can only be used with std140, std430, or scalar layout packing", "align", "");
defaultQualification.layoutAlign = -1;
}
}
// "The offset qualifier can only be used on block members of blocks declared with std140 or std430 layouts."
// "The align qualifier can only be used on blocks or block members, and only for blocks declared with std140 or std430 layouts."
if (memberQualifier.hasAlign() || memberQualifier.hasOffset()) {
- if (defaultQualification.layoutPacking != ElpStd140 && defaultQualification.layoutPacking != ElpStd430)
- error(memberLoc, "can only be used with std140 or std430 layout packing", "offset/align", "");
+ if (defaultQualification.layoutPacking != ElpStd140 &&
+ defaultQualification.layoutPacking != ElpStd430 &&
+ defaultQualification.layoutPacking != ElpScalar)
+ error(memberLoc, "can only be used with std140, std430, or scalar layout packing", "offset/align", "");
}
#ifdef NV_EXTENSIONS
profileRequires(loc, EEsProfile, 300, nullptr, "uniform block");
profileRequires(loc, ENoProfile, 140, nullptr, "uniform block");
if (currentBlockQualifier.layoutPacking == ElpStd430 && ! currentBlockQualifier.layoutPushConstant)
- error(loc, "requires the 'buffer' storage qualifier", "std430", "");
+ requireExtensions(loc, 1, &E_GL_EXT_scalar_block_layout, "std430 requires the buffer storage qualifier");
break;
case EvqBuffer:
requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, "buffer block");
{
if (!qualifier.isUniformOrBuffer() && !qualifier.isTaskMemory())
return;
- if (qualifier.layoutPacking != ElpStd140 && qualifier.layoutPacking != ElpStd430)
+ if (qualifier.layoutPacking != ElpStd140 && qualifier.layoutPacking != ElpStd430 && qualifier.layoutPacking != ElpScalar)
return;
int offset = 0;
// modify just the children's view of matrix layout, if there is one for this member
TLayoutMatrix subMatrixLayout = typeList[member].type->getQualifier().layoutMatrix;
int dummyStride;
- int memberAlignment = intermediate.getBaseAlignment(*typeList[member].type, memberSize, dummyStride, qualifier.layoutPacking == ElpStd140,
- subMatrixLayout != ElmNone ? subMatrixLayout == ElmRowMajor : qualifier.layoutMatrix == ElmRowMajor);
+ int memberAlignment = intermediate.getMemberAlignment(*typeList[member].type, memberSize, dummyStride, qualifier.layoutPacking,
+ subMatrixLayout != ElmNone ? subMatrixLayout == ElmRowMajor : qualifier.layoutMatrix == ElmRowMajor);
if (memberQualifier.hasOffset()) {
// "The specified offset must be a multiple
// of the base alignment of the type of the block member it qualifies, or a compile-time error results."
extensionBehavior[E_GL_EXT_control_flow_attributes] = EBhDisable;
extensionBehavior[E_GL_EXT_nonuniform_qualifier] = EBhDisable;
extensionBehavior[E_GL_EXT_samplerless_texture_functions] = EBhDisable;
+ extensionBehavior[E_GL_EXT_scalar_block_layout] = EBhDisable;
extensionBehavior[E_GL_EXT_shader_16bit_storage] = EBhDisable;
extensionBehavior[E_GL_EXT_shader_8bit_storage] = EBhDisable;
"#define GL_EXT_shader_16bit_storage 1\n"
"#define GL_EXT_shader_8bit_storage 1\n"
"#define GL_EXT_samplerless_texture_functions 1\n"
+ "#define GL_EXT_scalar_block_layout 1\n"
// GL_KHR_shader_subgroup
"#define GL_KHR_shader_subgroup_basic 1\n"
const char* const E_GL_EXT_control_flow_attributes = "GL_EXT_control_flow_attributes";
const char* const E_GL_EXT_nonuniform_qualifier = "GL_EXT_nonuniform_qualifier";
const char* const E_GL_EXT_samplerless_texture_functions = "GL_EXT_samplerless_texture_functions";
+const char* const E_GL_EXT_scalar_block_layout = "GL_EXT_scalar_block_layout";
// Arrays of extensions for the above viewportEXTs duplications
// stride comes from the flattening down to vectors.
//
// Return value is the alignment of the type.
-int TIntermediate::getBaseAlignment(const TType& type, int& size, int& stride, bool std140, bool rowMajor)
+int TIntermediate::getBaseAlignment(const TType& type, int& size, int& stride, TLayoutPacking layoutPacking, bool rowMajor)
{
int alignment;
+ bool std140 = layoutPacking == glslang::ElpStd140;
// When using the std140 storage layout, structures will be laid out in buffer
// storage with its members stored in monotonically increasing order based on their
// location in the declaration. A structure and each structure member have a base
if (type.isArray()) {
// TODO: perf: this might be flattened by using getCumulativeArraySize(), and a deref that discards all arrayness
TType derefType(type, 0);
- alignment = getBaseAlignment(derefType, size, dummyStride, std140, rowMajor);
+ alignment = getBaseAlignment(derefType, size, dummyStride, layoutPacking, rowMajor);
if (std140)
alignment = std::max(baseAlignmentVec4Std140, alignment);
RoundToPow2(size, alignment);
int memberSize;
// modify just the children's view of matrix layout, if there is one for this member
TLayoutMatrix subMatrixLayout = memberList[m].type->getQualifier().layoutMatrix;
- int memberAlignment = getBaseAlignment(*memberList[m].type, memberSize, dummyStride, std140,
+ int memberAlignment = getBaseAlignment(*memberList[m].type, memberSize, dummyStride, layoutPacking,
(subMatrixLayout != ElmNone) ? (subMatrixLayout == ElmRowMajor) : rowMajor);
maxAlignment = std::max(maxAlignment, memberAlignment);
RoundToPow2(size, memberAlignment);
// rule 5: deref to row, not to column, meaning the size of vector is num columns instead of num rows
TType derefType(type, 0, rowMajor);
- alignment = getBaseAlignment(derefType, size, dummyStride, std140, rowMajor);
+ alignment = getBaseAlignment(derefType, size, dummyStride, layoutPacking, rowMajor);
if (std140)
alignment = std::max(baseAlignmentVec4Std140, alignment);
RoundToPow2(size, alignment);
: offset % 16 != 0;
}
+int TIntermediate::getScalarAlignment(const TType& type, int& size, int& stride, bool rowMajor)
+{
+ int alignment;
+
+ stride = 0;
+ int dummyStride;
+
+ if (type.isArray()) {
+ TType derefType(type, 0);
+ alignment = getScalarAlignment(derefType, size, dummyStride, rowMajor);
+
+ stride = size;
+ RoundToPow2(stride, alignment);
+
+ size = stride * (type.getOuterArraySize() - 1) + size;
+ return alignment;
+ }
+
+ if (type.getBasicType() == EbtStruct) {
+ const TTypeList& memberList = *type.getStruct();
+
+ size = 0;
+ int maxAlignment = 0;
+ for (size_t m = 0; m < memberList.size(); ++m) {
+ int memberSize;
+ // modify just the children's view of matrix layout, if there is one for this member
+ TLayoutMatrix subMatrixLayout = memberList[m].type->getQualifier().layoutMatrix;
+ int memberAlignment = getScalarAlignment(*memberList[m].type, memberSize, dummyStride,
+ (subMatrixLayout != ElmNone) ? (subMatrixLayout == ElmRowMajor) : rowMajor);
+ maxAlignment = std::max(maxAlignment, memberAlignment);
+ RoundToPow2(size, memberAlignment);
+ size += memberSize;
+ }
+
+ return maxAlignment;
+ }
+
+ if (type.isScalar())
+ return getBaseAlignmentScalar(type, size);
+
+ if (type.isVector()) {
+ int scalarAlign = getBaseAlignmentScalar(type, size);
+
+ size *= type.getVectorSize();
+ return scalarAlign;
+ }
+
+ if (type.isMatrix()) {
+ TType derefType(type, 0, rowMajor);
+
+ alignment = getScalarAlignment(derefType, size, dummyStride, rowMajor);
+
+ stride = size; // use intra-matrix stride for stride of a just a matrix
+ if (rowMajor)
+ size = stride * type.getMatrixRows();
+ else
+ size = stride * type.getMatrixCols();
+
+ return alignment;
+ }
+
+ assert(0); // all cases should be covered above
+ size = 1;
+ return 1;
+}
+
+int TIntermediate::getMemberAlignment(const TType& type, int& size, int& stride, TLayoutPacking layoutPacking, bool rowMajor)
+{
+ if (layoutPacking == glslang::ElpScalar) {
+ return getScalarAlignment(type, size, stride, rowMajor);
+ } else {
+ return getBaseAlignment(type, size, stride, layoutPacking, rowMajor);
+ }
+}
+
} // end namespace glslang
int addXfbBufferOffset(const TType&);
unsigned int computeTypeXfbSize(const TType&, bool& containsDouble) const;
static int getBaseAlignmentScalar(const TType&, int& size);
- static int getBaseAlignment(const TType&, int& size, int& stride, bool std140, bool rowMajor);
+ static int getBaseAlignment(const TType&, int& size, int& stride, TLayoutPacking layoutPacking, bool rowMajor);
+ static int getScalarAlignment(const TType&, int& size, int& stride, bool rowMajor);
+ static int getMemberAlignment(const TType&, int& size, int& stride, TLayoutPacking layoutPacking, bool rowMajor);
static bool improperStraddle(const TType& type, int size, int offset);
bool promote(TIntermOperator*);
for (int m = 0; m <= index; ++m) {
// modify just the children's view of matrix layout, if there is one for this member
TLayoutMatrix subMatrixLayout = memberList[m].type->getQualifier().layoutMatrix;
- int memberAlignment = intermediate.getBaseAlignment(*memberList[m].type, memberSize, dummyStride,
- type.getQualifier().layoutPacking == ElpStd140,
- subMatrixLayout != ElmNone
- ? subMatrixLayout == ElmRowMajor
- : type.getQualifier().layoutMatrix == ElmRowMajor);
+ int memberAlignment = intermediate.getMemberAlignment(*memberList[m].type, memberSize, dummyStride,
+ type.getQualifier().layoutPacking,
+ subMatrixLayout != ElmNone
+ ? subMatrixLayout == ElmRowMajor
+ : type.getQualifier().layoutMatrix == ElmRowMajor);
RoundToPow2(offset, memberAlignment);
if (m < index)
offset += memberSize;
int lastMemberSize;
int dummyStride;
- intermediate.getBaseAlignment(*memberList[lastIndex].type, lastMemberSize, dummyStride,
- blockType.getQualifier().layoutPacking == ElpStd140,
- blockType.getQualifier().layoutMatrix == ElmRowMajor);
+ intermediate.getMemberAlignment(*memberList[lastIndex].type, lastMemberSize, dummyStride,
+ blockType.getQualifier().layoutPacking,
+ blockType.getQualifier().layoutMatrix == ElmRowMajor);
return lastOffset + lastMemberSize;
}
"spv.sampleId.frag",
"spv.samplePosition.frag",
"spv.sampleMaskOverrideCoverage.frag",
+ "spv.scalarlayout.frag",
+ "spv.scalarlayoutfloat16.frag",
"spv.shaderBallot.comp",
"spv.shaderDrawParams.vert",
"spv.shaderGroupVote.comp",
if (argStride != nullptr) {
int size;
int stride;
- intermediate.getBaseAlignment(argArray->getType(), size, stride, false,
- argArray->getType().getQualifier().layoutMatrix == ElmRowMajor);
+ intermediate.getMemberAlignment(argArray->getType(), size, stride, argArray->getType().getQualifier().layoutPacking,
+ argArray->getType().getQualifier().layoutMatrix == ElmRowMajor);
TIntermTyped* assign = intermediate.addAssign(EOpAssign, argStride,
intermediate.addConstantUnion(stride, loc, true), loc);
{
if (! qualifier.isUniformOrBuffer())
return;
- if (qualifier.layoutPacking != ElpStd140 && qualifier.layoutPacking != ElpStd430)
+ if (qualifier.layoutPacking != ElpStd140 && qualifier.layoutPacking != ElpStd430 && qualifier.layoutPacking != ElpScalar)
return;
int offset = 0;
// modify just the children's view of matrix layout, if there is one for this member
TLayoutMatrix subMatrixLayout = typeList[member].type->getQualifier().layoutMatrix;
int dummyStride;
- int memberAlignment = intermediate.getBaseAlignment(*typeList[member].type, memberSize, dummyStride,
- qualifier.layoutPacking == ElpStd140,
- subMatrixLayout != ElmNone
- ? subMatrixLayout == ElmRowMajor
- : qualifier.layoutMatrix == ElmRowMajor);
+ int memberAlignment = intermediate.getMemberAlignment(*typeList[member].type, memberSize, dummyStride,
+ qualifier.layoutPacking,
+ subMatrixLayout != ElmNone
+ ? subMatrixLayout == ElmRowMajor
+ : qualifier.layoutMatrix == ElmRowMajor);
if (memberQualifier.hasOffset()) {
// "The specified offset must be a multiple
// of the base alignment of the type of the block member it qualifies, or a compile-time error results."