diff --git a/Test/baseResults/spv.offsets.frag.out b/Test/baseResults/spv.offsets.frag.out new file mode 100755 index 00000000..b0091eaa --- /dev/null +++ b/Test/baseResults/spv.offsets.frag.out @@ -0,0 +1,59 @@ +spv.offsets.frag +Warning, version 450 is not yet complete; most version-specific features are present, but some are missing. + + +Linked fragment stage: + + +// Module Version 10000 +// Generated by (magic number): 80001 +// Id's are bound by 15 + + Capability Shader + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint Fragment 4 "main" + ExecutionMode 4 OriginUpperLeft + Source GLSL 450 + Name 4 "main" + Name 7 "n1" + MemberName 7(n1) 0 "a" + MemberName 7(n1) 1 "b" + MemberName 7(n1) 2 "c" + MemberName 7(n1) 3 "d" + Name 9 "i1" + Name 12 "n2" + MemberName 12(n2) 0 "e" + MemberName 12(n2) 1 "f" + MemberName 12(n2) 2 "g" + MemberName 12(n2) 3 "h" + Name 14 "i2" + MemberDecorate 7(n1) 0 Offset 8 + MemberDecorate 7(n1) 1 Offset 4 + MemberDecorate 7(n1) 2 Offset 0 + MemberDecorate 7(n1) 3 Offset 12 + Decorate 7(n1) Block + Decorate 9(i1) DescriptorSet 0 + Decorate 9(i1) Binding 0 + MemberDecorate 12(n2) 0 Offset 32 + MemberDecorate 12(n2) 1 Offset 48 + MemberDecorate 12(n2) 2 Offset 16 + MemberDecorate 12(n2) 3 Offset 0 + Decorate 12(n2) BufferBlock + Decorate 14(i2) DescriptorSet 0 + Decorate 14(i2) Binding 1 + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeInt 32 1 + 7(n1): TypeStruct 6(int) 6(int) 6(int) 6(int) + 8: TypePointer Uniform 7(n1) + 9(i1): 8(ptr) Variable Uniform + 10: TypeFloat 32 + 11: TypeVector 10(float) 3 + 12(n2): TypeStruct 11(fvec3) 11(fvec3) 11(fvec3) 11(fvec3) + 13: TypePointer Uniform 12(n2) + 14(i2): 13(ptr) Variable Uniform + 4(main): 2 Function None 3 + 5: Label + Return + FunctionEnd diff --git a/Test/spv.offsets.frag b/Test/spv.offsets.frag new file mode 100755 index 00000000..0a1c008c --- /dev/null +++ b/Test/spv.offsets.frag @@ -0,0 +1,17 @@ +#version 450 + +layout(set = 0, binding = 0, std140) uniform n1 { + layout(offset = 8) int a; + layout(offset = 4) int b; + layout(offset = 0) int c; + layout(offset = 12) int d; +} i1; + +layout(set = 0, binding = 1, std430) buffer n2 { + layout(offset = 32) vec3 e; + vec3 f; + layout(offset = 16) vec3 g; + layout(offset = 0) vec3 h; +} i2; + +void main() {} \ No newline at end of file diff --git a/glslang/Include/revision.h b/glslang/Include/revision.h index 4224a0a6..0521e2e8 100644 --- a/glslang/Include/revision.h +++ b/glslang/Include/revision.h @@ -2,5 +2,5 @@ // For the version, it uses the latest git tag followed by the number of commits. // For the date, it uses the current date (when then script is run). -#define GLSLANG_REVISION "Overload400-PrecQual.1559" -#define GLSLANG_DATE "06-Oct-2016" +#define GLSLANG_REVISION "Overload400-PrecQual.1560" +#define GLSLANG_DATE "07-Oct-2016" diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index 13f277d7..68d070c7 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -5946,16 +5946,23 @@ void TParseContext::fixBlockUniformOffsets(TQualifier& qualifier, TTypeList& typ if (! IsMultipleOfPow2(memberQualifier.layoutOffset, memberAlignment)) error(memberLoc, "must be a multiple of the member's alignment", "offset", ""); - // "It is a compile-time error to specify an offset that is smaller than the offset of the previous + // GLSL: "It is a compile-time error to specify an offset that is smaller than the offset of the previous // member in the block or that lies within the previous member of the block" - if (memberQualifier.layoutOffset < offset) - error(memberLoc, "cannot lie in previous members", "offset", ""); + if (spvVersion.spv == 0) { + if (memberQualifier.layoutOffset < offset) + error(memberLoc, "cannot lie in previous members", "offset", ""); - // "The offset qualifier forces the qualified member to start at or after the specified - // integral-constant expression, which will be its byte offset from the beginning of the buffer. - // "The actual offset of a member is computed as - // follows: If offset was declared, start with that offset, otherwise start with the next available offset." - offset = std::max(offset, memberQualifier.layoutOffset); + // "The offset qualifier forces the qualified member to start at or after the specified + // integral-constant expression, which will be its byte offset from the beginning of the buffer. + // "The actual offset of a member is computed as + // follows: If offset was declared, start with that offset, otherwise start with the next available offset." + offset = std::max(offset, memberQualifier.layoutOffset); + } else { + // TODO: Vulkan: "It is a compile-time error to have any offset, explicit or assigned, + // that lies within another member of the block." + + offset = memberQualifier.layoutOffset; + } } // "The actual alignment of a member will be the greater of the specified align alignment and the standard diff --git a/gtests/Spv.FromFile.cpp b/gtests/Spv.FromFile.cpp index 533733df..f109911e 100644 --- a/gtests/Spv.FromFile.cpp +++ b/gtests/Spv.FromFile.cpp @@ -230,6 +230,7 @@ INSTANTIATE_TEST_CASE_P( "spv.newTexture.frag", "spv.noDeadDecorations.vert", "spv.nonSquare.vert", + "spv.offsets.frag", "spv.Operations.frag", "spv.intOps.vert", "spv.precision.frag", diff --git a/hlsl/hlslParseHelper.cpp b/hlsl/hlslParseHelper.cpp index 066426d4..1fe40929 100755 --- a/hlsl/hlslParseHelper.cpp +++ b/hlsl/hlslParseHelper.cpp @@ -4731,11 +4731,6 @@ void HlslParseContext::fixBlockUniformOffsets(const TQualifier& qualifier, TType if (! IsMultipleOfPow2(memberQualifier.layoutOffset, memberAlignment)) error(memberLoc, "must be a multiple of the member's alignment", "offset", ""); - // "It is a compile-time error to specify an offset that is smaller than the offset of the previous - // member in the block or that lies within the previous member of the block" - if (memberQualifier.layoutOffset < offset) - error(memberLoc, "cannot lie in previous members", "offset", ""); - // "The offset qualifier forces the qualified member to start at or after the specified // integral-constant expression, which will be its byte offset from the beginning of the buffer. // "The actual offset of a member is computed as