SPV: Fix #807: use --hlsl-offsets to allow hlsl-style offsets in a buffer.
Corresponds to the EShMsgHlslOffsets flag in messages.
Works for both GLSL and HLSL.
diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp
index 1e03909..aae3f49 100755
--- a/SPIRV/GlslangToSpv.cpp
+++ b/SPIRV/GlslangToSpv.cpp
@@ -2728,7 +2728,23 @@
int memberSize;
int dummyStride;
int memberAlignment = glslangIntermediate->getBaseAlignment(memberType, memberSize, dummyStride, explicitLayout == glslang::ElpStd140, matrixLayout == glslang::ElmRowMajor);
+
+ // Adjust alignment for HLSL rules
+ if (glslangIntermediate->usingHlslOFfsets() &&
+ ! memberType.isArray() && memberType.isVector()) {
+ int dummySize;
+ int componentAlignment = glslangIntermediate->getBaseAlignmentScalar(memberType, dummySize);
+ if (componentAlignment <= 4)
+ memberAlignment = componentAlignment;
+ }
+
+ // Bump up to member alignment
glslang::RoundToPow2(currentOffset, memberAlignment);
+
+ // Bump up to vec4 if there is a bad straddle
+ if (glslangIntermediate->improperStraddle(memberType, memberSize, currentOffset))
+ glslang::RoundToPow2(currentOffset, 16);
+
nextOffset = currentOffset + memberSize;
}
diff --git a/StandAlone/StandAlone.cpp b/StandAlone/StandAlone.cpp
index 56d6619..60dbc4d 100644
--- a/StandAlone/StandAlone.cpp
+++ b/StandAlone/StandAlone.cpp
@@ -86,6 +86,7 @@
EOptionFlattenUniformArrays = (1 << 20),
EOptionNoStorageFormat = (1 << 21),
EOptionKeepUncalled = (1 << 22),
+ EOptionHlslOffsets = (1 << 23),
};
//
@@ -311,8 +312,7 @@
} else
Error("no <C-variable-name> provided for --variable-name");
break;
- }
- else if (lowerword == "source-entrypoint" || // synonyms
+ } else if (lowerword == "source-entrypoint" || // synonyms
lowerword == "sep") {
sourceEntryPointName = argv[1];
if (argc > 0) {
@@ -324,6 +324,8 @@
} else if (lowerword == "keep-uncalled" || // synonyms
lowerword == "ku") {
Options |= EOptionKeepUncalled;
+ } else if (lowerword == "hlsl-offsets") {
+ Options |= EOptionHlslOffsets;
} else {
usage();
}
@@ -471,6 +473,8 @@
messages = (EShMessages)(messages | EShMsgCascadingErrors);
if (Options & EOptionKeepUncalled)
messages = (EShMessages)(messages | EShMsgKeepUncalled);
+ if (Options & EOptionHlslOffsets)
+ messages = (EShMessages)(messages | EShMsgHlslOffsets);
}
//
@@ -998,8 +1002,13 @@
"\n"
" --keep-uncalled don't eliminate uncalled functions when linking\n"
" --ku synonym for --keep-uncalled\n"
- " --variable-name <name> Creates a C header file that contains a uint32_t array named <name> initialized with the shader binary code.\n"
- " --vn <name> synonym for --variable-name <name>.\n"
+ "\n"
+ " --variable-name <name> Creates a C header file that contains a uint32_t array named <name>\n"
+ " initialized with the shader binary code.\n"
+ " --vn <name> synonym for --variable-name <name>\n"
+ "\n"
+ " --hlsl-offsets Allow block offsets to follow HLSL rules instead of GLSL rules.\n"
+ " Works independently of source language.\n"
);
exit(EFailUsage);
diff --git a/Test/baseResults/hlsl.hlslOffset.vert.out b/Test/baseResults/hlsl.hlslOffset.vert.out
new file mode 100644
index 0000000..380a086
--- /dev/null
+++ b/Test/baseResults/hlsl.hlslOffset.vert.out
@@ -0,0 +1,84 @@
+hlsl.hlslOffset.vert
+Shader version: 450
+0:? Sequence
+0:20 Function Definition: @main( ( temp void)
+0:20 Function Parameters:
+0:20 Function Definition: main( ( temp void)
+0:20 Function Parameters:
+0:? Sequence
+0:20 Function Call: @main( ( temp void)
+0:? Linker Objects
+0:? 'anon@0' (layout( row_major std140) uniform block{layout( row_major std140) uniform float m0, layout( row_major std140) uniform 3-component vector of float m4, layout( row_major std140) uniform float m16, layout( row_major std140 offset=20) uniform 3-component vector of float m20, layout( row_major std140 offset=36) uniform 3-component vector of float m36, layout( row_major std140 offset=56) uniform 2-component vector of float m56, layout( row_major std140) uniform float m64, layout( row_major std140) uniform 2-component vector of float m68, layout( row_major std140) uniform float m76, layout( row_major std140) uniform float m80, layout( row_major std140) uniform 1-element array of 2-component vector of float m96})
+
+
+Linked vertex stage:
+
+
+Shader version: 450
+0:? Sequence
+0:20 Function Definition: @main( ( temp void)
+0:20 Function Parameters:
+0:20 Function Definition: main( ( temp void)
+0:20 Function Parameters:
+0:? Sequence
+0:20 Function Call: @main( ( temp void)
+0:? Linker Objects
+0:? 'anon@0' (layout( row_major std140) uniform block{layout( row_major std140) uniform float m0, layout( row_major std140) uniform 3-component vector of float m4, layout( row_major std140) uniform float m16, layout( row_major std140 offset=20) uniform 3-component vector of float m20, layout( row_major std140 offset=36) uniform 3-component vector of float m36, layout( row_major std140 offset=56) uniform 2-component vector of float m56, layout( row_major std140) uniform float m64, layout( row_major std140) uniform 2-component vector of float m68, layout( row_major std140) uniform float m76, layout( row_major std140) uniform float m80, layout( row_major std140) uniform 1-element array of 2-component vector of float m96})
+
+// Module Version 10000
+// Generated by (magic number): 80001
+// Id's are bound by 18
+
+ Capability Shader
+ 1: ExtInstImport "GLSL.std.450"
+ MemoryModel Logical GLSL450
+ EntryPoint Vertex 4 "main"
+ Name 4 "main"
+ Name 6 "@main("
+ Name 15 "b"
+ MemberName 15(b) 0 "m0"
+ MemberName 15(b) 1 "m4"
+ MemberName 15(b) 2 "m16"
+ MemberName 15(b) 3 "m20"
+ MemberName 15(b) 4 "m36"
+ MemberName 15(b) 5 "m56"
+ MemberName 15(b) 6 "m64"
+ MemberName 15(b) 7 "m68"
+ MemberName 15(b) 8 "m76"
+ MemberName 15(b) 9 "m80"
+ MemberName 15(b) 10 "m96"
+ Name 17 ""
+ Decorate 14 ArrayStride 16
+ MemberDecorate 15(b) 0 Offset 0
+ MemberDecorate 15(b) 1 Offset 4
+ MemberDecorate 15(b) 2 Offset 16
+ MemberDecorate 15(b) 3 Offset 20
+ MemberDecorate 15(b) 4 Offset 36
+ MemberDecorate 15(b) 5 Offset 56
+ MemberDecorate 15(b) 6 Offset 64
+ MemberDecorate 15(b) 7 Offset 68
+ MemberDecorate 15(b) 8 Offset 76
+ MemberDecorate 15(b) 9 Offset 80
+ MemberDecorate 15(b) 10 Offset 96
+ Decorate 15(b) Block
+ Decorate 17 DescriptorSet 0
+ 2: TypeVoid
+ 3: TypeFunction 2
+ 9: TypeFloat 32
+ 10: TypeVector 9(float) 3
+ 11: TypeVector 9(float) 2
+ 12: TypeInt 32 0
+ 13: 12(int) Constant 1
+ 14: TypeArray 11(fvec2) 13
+ 15(b): TypeStruct 9(float) 10(fvec3) 9(float) 10(fvec3) 10(fvec3) 11(fvec2) 9(float) 11(fvec2) 9(float) 9(float) 14
+ 16: TypePointer Uniform 15(b)
+ 17: 16(ptr) Variable Uniform
+ 4(main): 2 Function None 3
+ 5: Label
+ 8: 2 FunctionCall 6(@main()
+ Return
+ FunctionEnd
+ 6(@main(): 2 Function None 3
+ 7: Label
+ Return
+ FunctionEnd
diff --git a/Test/baseResults/spv.hlslOffsets.vert.out b/Test/baseResults/spv.hlslOffsets.vert.out
new file mode 100644
index 0000000..c1f6cb2
--- /dev/null
+++ b/Test/baseResults/spv.hlslOffsets.vert.out
@@ -0,0 +1,78 @@
+spv.hlslOffsets.vert
+Warning, version 450 is not yet complete; most version-specific features are present, but some are missing.
+
+Shader version: 450
+0:? Sequence
+0:27 Function Definition: main( ( global void)
+0:27 Function Parameters:
+0:? Linker Objects
+0:? 'anon@0' (layout( column_major std430) buffer block{layout( column_major std430) buffer highp float m0, layout( column_major std430) buffer highp 3-component vector of float m4, layout( column_major std430) buffer highp float m16, layout( column_major std430 offset=20) buffer highp 3-component vector of float m20, layout( column_major std430) buffer highp 3-component vector of float m32, layout( column_major std430) buffer highp 2-component vector of float m48, layout( column_major std430) buffer highp 2-component vector of float m56, layout( column_major std430) buffer highp float m64, layout( column_major std430) buffer highp 2-component vector of float m68, layout( column_major std430) buffer highp float m76, layout( column_major std430) buffer highp float m80, layout( column_major std430 offset=88) buffer highp 2-component vector of float m88, layout( column_major std430) buffer highp 2-component vector of float m96, layout( column_major std430) buffer 2-component vector of double m112})
+
+
+Linked vertex stage:
+
+
+Shader version: 450
+0:? Sequence
+0:27 Function Definition: main( ( global void)
+0:27 Function Parameters:
+0:? Linker Objects
+0:? 'anon@0' (layout( column_major std430) buffer block{layout( column_major std430) buffer highp float m0, layout( column_major std430) buffer highp 3-component vector of float m4, layout( column_major std430) buffer highp float m16, layout( column_major std430 offset=20) buffer highp 3-component vector of float m20, layout( column_major std430) buffer highp 3-component vector of float m32, layout( column_major std430) buffer highp 2-component vector of float m48, layout( column_major std430) buffer highp 2-component vector of float m56, layout( column_major std430) buffer highp float m64, layout( column_major std430) buffer highp 2-component vector of float m68, layout( column_major std430) buffer highp float m76, layout( column_major std430) buffer highp float m80, layout( column_major std430 offset=88) buffer highp 2-component vector of float m88, layout( column_major std430) buffer highp 2-component vector of float m96, layout( column_major std430) buffer 2-component vector of double m112})
+
+// Module Version 10000
+// Generated by (magic number): 80001
+// Id's are bound by 14
+
+ Capability Shader
+ Capability Float64
+ 1: ExtInstImport "GLSL.std.450"
+ MemoryModel Logical GLSL450
+ EntryPoint Vertex 4 "main"
+ Source GLSL 450
+ Name 4 "main"
+ Name 11 "block"
+ MemberName 11(block) 0 "m0"
+ MemberName 11(block) 1 "m4"
+ MemberName 11(block) 2 "m16"
+ MemberName 11(block) 3 "m20"
+ MemberName 11(block) 4 "m32"
+ MemberName 11(block) 5 "m48"
+ MemberName 11(block) 6 "m56"
+ MemberName 11(block) 7 "m64"
+ MemberName 11(block) 8 "m68"
+ MemberName 11(block) 9 "m76"
+ MemberName 11(block) 10 "m80"
+ MemberName 11(block) 11 "m88"
+ MemberName 11(block) 12 "m96"
+ MemberName 11(block) 13 "m112"
+ Name 13 ""
+ MemberDecorate 11(block) 0 Offset 0
+ MemberDecorate 11(block) 1 Offset 4
+ MemberDecorate 11(block) 2 Offset 16
+ MemberDecorate 11(block) 3 Offset 20
+ MemberDecorate 11(block) 4 Offset 32
+ MemberDecorate 11(block) 5 Offset 48
+ MemberDecorate 11(block) 6 Offset 56
+ MemberDecorate 11(block) 7 Offset 64
+ MemberDecorate 11(block) 8 Offset 68
+ MemberDecorate 11(block) 9 Offset 76
+ MemberDecorate 11(block) 10 Offset 80
+ MemberDecorate 11(block) 11 Offset 88
+ MemberDecorate 11(block) 12 Offset 96
+ MemberDecorate 11(block) 13 Offset 112
+ Decorate 11(block) BufferBlock
+ Decorate 13 DescriptorSet 0
+ 2: TypeVoid
+ 3: TypeFunction 2
+ 6: TypeFloat 32
+ 7: TypeVector 6(float) 3
+ 8: TypeVector 6(float) 2
+ 9: TypeFloat 64
+ 10: TypeVector 9(float) 2
+ 11(block): TypeStruct 6(float) 7(fvec3) 6(float) 7(fvec3) 7(fvec3) 8(fvec2) 8(fvec2) 6(float) 8(fvec2) 6(float) 6(float) 8(fvec2) 8(fvec2) 10(fvec2)
+ 12: TypePointer Uniform 11(block)
+ 13: 12(ptr) Variable Uniform
+ 4(main): 2 Function None 3
+ 5: Label
+ Return
+ FunctionEnd
diff --git a/Test/hlsl.hlslOffset.vert b/Test/hlsl.hlslOffset.vert
new file mode 100755
index 0000000..aa95f6a
--- /dev/null
+++ b/Test/hlsl.hlslOffset.vert
@@ -0,0 +1,20 @@
+cbuffer b {
+ float m0;
+ float3 m4;
+ //////
+ float m16;
+ float3 m20 : packoffset(c1.y);
+ /////
+ float3 m36 : packoffset(c2.y);
+ /////
+ float2 m56 : packoffset(c3.z);
+ /////
+ float m64;
+ float2 m68;
+ float m76;
+ //////
+ float m80;
+ float2 m96[1];
+};
+
+void main() {}
diff --git a/Test/runtests b/Test/runtests
index 86ffef3..efc449d 100755
--- a/Test/runtests
+++ b/Test/runtests
@@ -73,6 +73,20 @@
$EXE -i -S vert nosuffix > $TARGETDIR/nosuffix.out
diff -b $BASEDIR/nosuffix.out $TARGETDIR/nosuffix.out || HASERROR=1
+#
+# Testing --hlsl-offsets
+#
+echo Running hlsl offsets
+$EXE -i --hlsl-offsets -H spv.hlslOffsets.vert > $TARGETDIR/spv.hlslOffsets.vert.out
+diff -b $BASEDIR/spv.hlslOffsets.vert.out $TARGETDIR/spv.hlslOffsets.vert.out || HASERROR=1
+
+echo Running hlsl offsets
+$EXE -i --hlsl-offsets -D -e main -H hlsl.hlslOffset.vert > $TARGETDIR/hlsl.hlslOffset.vert.out
+diff -b $BASEDIR/hlsl.hlslOffset.vert.out $TARGETDIR/hlsl.hlslOffset.vert.out || HASERROR=1
+
+#
+# Final checking
+#
if [ $HASERROR -eq 0 ]
then
echo Tests Succeeded.
diff --git a/Test/spv.hlslOffsets.vert b/Test/spv.hlslOffsets.vert
new file mode 100755
index 0000000..87e32a7
--- /dev/null
+++ b/Test/spv.hlslOffsets.vert
@@ -0,0 +1,27 @@
+#version 450
+
+buffer block {
+ float m0;
+ vec3 m4;
+ //////
+ float m16;
+ layout(offset=20) vec3 m20;
+ /////
+ vec3 m32;
+ /////
+ vec2 m48;
+ vec2 m56;
+ ////
+ float m64;
+ vec2 m68;
+ float m76;
+ //////
+ float m80;
+ layout(offset=88) vec2 m88;
+ //////
+ vec2 m96;
+ ///////
+ dvec2 m112;
+};
+
+void main() {}
\ No newline at end of file
diff --git a/glslang/Include/revision.h b/glslang/Include/revision.h
index 2704df3..8632bea 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.1974"
-#define GLSLANG_DATE "04-Apr-2017"
+#define GLSLANG_REVISION "Overload400-PrecQual.1978"
+#define GLSLANG_DATE "05-Apr-2017"
diff --git a/glslang/MachineIndependent/ShaderLang.cpp b/glslang/MachineIndependent/ShaderLang.cpp
index 5a8f679..f7596d9 100644
--- a/glslang/MachineIndependent/ShaderLang.cpp
+++ b/glslang/MachineIndependent/ShaderLang.cpp
@@ -726,6 +726,8 @@
intermediate.setSpv(spvVersion);
if (spvVersion.vulkan >= 100)
intermediate.setOriginUpperLeft();
+ if (messages & EShMsgHlslOffsets) // source-language independent
+ intermediate.setHlslOffsets();
SetupBuiltinSymbolTable(version, profile, spvVersion, source);
TSymbolTable* cachedTable = SharedSymbolTables[MapVersionToIndex(version)]
diff --git a/glslang/MachineIndependent/linkValidate.cpp b/glslang/MachineIndependent/linkValidate.cpp
index 0328009..4bb2951 100644
--- a/glslang/MachineIndependent/linkValidate.cpp
+++ b/glslang/MachineIndependent/linkValidate.cpp
@@ -1047,9 +1047,9 @@
const int baseAlignmentVec4Std140 = 16;
-// Return the size and alignment of a scalar.
+// Return the size and alignment of a component of the given type.
// The size is returned in the 'size' parameter
-// Return value is the alignment of the type.
+// Return value is the alignment..
int TIntermediate::getBaseAlignmentScalar(const TType& type, int& size)
{
switch (type.getBasicType()) {
@@ -1219,4 +1219,14 @@
return baseAlignmentVec4Std140;
}
+// To aid the basic HLSL rule about crossing vec4 boundaries.
+bool TIntermediate::improperStraddle(const TType& type, int size, int offset)
+{
+ if (! type.isVector() || type.isArray())
+ return false;
+
+ return size <= 16 ? offset / 16 != (offset + size - 1) / 16
+ : offset % 16 != 0;
+}
+
} // end namespace glslang
diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h
index 5460dd5..2cd912b 100644
--- a/glslang/MachineIndependent/localintermediate.h
+++ b/glslang/MachineIndependent/localintermediate.h
@@ -177,7 +177,8 @@
shiftSsboBinding(0),
autoMapBindings(false),
flattenUniformArrays(false),
- useUnknownFormat(false)
+ useUnknownFormat(false),
+ hlslOffsets(false)
{
localSize[0] = 1;
localSize[1] = 1;
@@ -216,6 +217,8 @@
bool getFlattenUniformArrays() const { return flattenUniformArrays; }
void setNoStorageFormat(bool b) { useUnknownFormat = b; }
bool getNoStorageFormat() const { return useUnknownFormat; }
+ void setHlslOffsets() { hlslOffsets = true; }
+ bool usingHlslOFfsets() const { return hlslOffsets; }
void setVersion(int v) { version = v; }
int getVersion() const { return version; }
@@ -413,7 +416,9 @@
}
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 bool improperStraddle(const TType& type, int size, int offset);
bool promote(TIntermOperator*);
#ifdef NV_EXTENSIONS
@@ -443,7 +448,6 @@
void inOutLocationCheck(TInfoSink&);
TIntermSequence& findLinkerObjects() const;
bool userOutputUsed() const;
- static int getBaseAlignmentScalar(const TType&, int& size);
bool isSpecializationOperation(const TIntermOperator&) const;
bool promoteUnary(TIntermUnary&);
bool promoteBinary(TIntermBinary&);
@@ -499,6 +503,7 @@
bool autoMapBindings;
bool flattenUniformArrays;
bool useUnknownFormat;
+ bool hlslOffsets;
typedef std::list<TCall> TGraph;
TGraph callGraph;
diff --git a/glslang/Public/ShaderLang.h b/glslang/Public/ShaderLang.h
index 8d8abd7..ace20cb 100644
--- a/glslang/Public/ShaderLang.h
+++ b/glslang/Public/ShaderLang.h
@@ -147,6 +147,7 @@
EShMsgReadHlsl = (1 << 6), // use HLSL parsing rules and semantics
EShMsgCascadingErrors = (1 << 7), // get cascading errors; risks error-recovery issues, instead of an early exit
EShMsgKeepUncalled = (1 << 8), // for testing, don't eliminate uncalled functions
+ EShMsgHlslOffsets = (1 << 9), // allow block offsets to follow HLSL rules instead of GLSL rules
};
//