SPV: Further refine OpenGL vs. Vulkan differences for SPIR-V.

Includes adding test cases to verify the differences.
This commit is contained in:
John Kessenich 2016-07-07 17:46:42 -06:00
parent 2d0cc786f3
commit 91e4aa5900
23 changed files with 305 additions and 27 deletions

View File

@ -4078,6 +4078,9 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol
if (symbol->getQualifier().hasXfbOffset())
builder.addDecoration(id, spv::DecorationOffset, symbol->getQualifier().layoutXfbOffset);
}
// atomic counters use this:
if (symbol->getQualifier().hasOffset())
builder.addDecoration(id, spv::DecorationOffset, symbol->getQualifier().layoutOffset);
}
if (symbol->getQualifier().hasLocation())

View File

@ -222,7 +222,13 @@ void ProcessArguments(int argc, char* argv[])
switch (argv[0][1]) {
case 'H':
Options |= EOptionHumanReadableSpv;
// fall through to -V
if ((Options & EOptionSpv) == 0) {
// default to Vulkan
Options |= EOptionSpv;
Options |= EOptionVulkanRules;
Options |= EOptionLinkProgram;
}
break;
case 'V':
Options |= EOptionSpv;
Options |= EOptionVulkanRules;
@ -231,6 +237,8 @@ void ProcessArguments(int argc, char* argv[])
case 'G':
Options |= EOptionSpv;
Options |= EOptionLinkProgram;
// undo a -H default to Vulkan
Options &= ~EOptionVulkanRules;
break;
case 'E':
Options |= EOptionOutputPreprocessed;

View File

@ -0,0 +1,11 @@
glspv.esversion.vert
ERROR: #version: ES shaders for OpenGL SPIR-V are not supported
Warning, version 310 is not yet complete; most version-specific features are present, but some are missing.
ERROR: 1 compilation errors. No code generated.
Linked vertex stage:
SPIR-V is not generated for failed compile or link

13
Test/baseResults/glspv.frag.out Executable file
View File

@ -0,0 +1,13 @@
glspv.frag
ERROR: 0:4: '#error' : GL_SPIRV is set ( correct , not an error )
ERROR: 0:6: '#error' : GL_SPIR is 100
ERROR: 0:14: 'input_attachment_index' : only allowed when using GLSL for Vulkan
ERROR: 0:14: '' : syntax error
ERROR: 4 compilation errors. No code generated.
Linked fragment stage:
SPIR-V is not generated for failed compile or link

View File

@ -0,0 +1,24 @@
glspv.version.frag
ERROR: #version: compilation for SPIR-V does not support the compatibility profile
Linked fragment stage:
// Module Version 10000
// Generated by (magic number): 80001
// Id's are bound by 6
Capability Shader
1: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450
EntryPoint Fragment 4 "main"
ExecutionMode 4 OriginLowerLeft
Source GLSL 330
Name 4 "main"
2: TypeVoid
3: TypeFunction 2
4(main): 2 Function None 3
5: Label
Return
FunctionEnd

View File

@ -0,0 +1,10 @@
glspv.version.vert
ERROR: #version: Desktop shaders for OpenGL SPIR-V require version 330 or higher
ERROR: 1 compilation errors. No code generated.
Linked vertex stage:
SPIR-V is not generated for failed compile or link

18
Test/baseResults/glspv.vert.out Executable file
View File

@ -0,0 +1,18 @@
glspv.vert
Warning, version 450 is not yet complete; most version-specific features are present, but some are missing.
ERROR: 0:3: 'push_constant' : only allowed when using GLSL for Vulkan
ERROR: 0:6: 'descriptor set' : only allowed when using GLSL for Vulkan
ERROR: 0:8: 'shared' : not allowed when generating SPIR-V
ERROR: 0:9: 'packed' : not allowed when generating SPIR-V
ERROR: 0:13: 'gl_VertexIndex' : undeclared identifier
ERROR: 0:14: 'gl_InstanceIndex' : undeclared identifier
ERROR: 0:17: 'gl_DepthRangeParameters' : undeclared identifier
ERROR: 0:20: '' : syntax error
ERROR: 8 compilation errors. No code generated.
Linked vertex stage:
SPIR-V is not generated for failed compile or link

View File

@ -35,7 +35,9 @@ Linked compute stage:
Name 70 "arrX"
Name 71 "arrY"
Name 72 "arrZ"
Decorate 20(counter) Offset 0
Decorate 20(counter) Binding 0
Decorate 27(countArr) Offset 4
Decorate 27(countArr) Binding 0
MemberDecorate 60(dataSSB) 0 Restrict
MemberDecorate 60(dataSSB) 0 Offset 0

View File

@ -0,0 +1,30 @@
spv.glFragColor.frag
Linked fragment stage:
// Module Version 10000
// Generated by (magic number): 80001
// Id's are bound by 12
Capability Shader
1: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450
EntryPoint Fragment 4 "main" 9
ExecutionMode 4 OriginLowerLeft
Source GLSL 330
Name 4 "main"
Name 9 "gl_FragColor"
2: TypeVoid
3: TypeFunction 2
6: TypeFloat 32
7: TypeVector 6(float) 4
8: TypePointer Output 7(fvec4)
9(gl_FragColor): 8(ptr) Variable Output
10: 6(float) Constant 1065353216
11: 7(fvec4) ConstantComposite 10 10 10 10
4(main): 2 Function None 3
5: Label
Store 9(gl_FragColor) 11
Return
FunctionEnd

View File

@ -0,0 +1,61 @@
spv.specConst.vert
Warning, version 450 is not yet complete; most version-specific features are present, but some are missing.
Linked vertex stage:
// Module Version 10000
// Generated by (magic number): 80001
// Id's are bound by 27
Capability Shader
1: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450
EntryPoint Vertex 4 "main" 13 25 26
Source GLSL 450
Name 4 "main"
Name 11 "gl_PerVertex"
MemberName 11(gl_PerVertex) 0 "gl_Position"
MemberName 11(gl_PerVertex) 1 "gl_PointSize"
MemberName 11(gl_PerVertex) 2 "gl_ClipDistance"
MemberName 11(gl_PerVertex) 3 "gl_CullDistance"
Name 13 ""
Name 25 "gl_VertexID"
Name 26 "gl_InstanceID"
MemberDecorate 11(gl_PerVertex) 0 BuiltIn Position
MemberDecorate 11(gl_PerVertex) 1 BuiltIn PointSize
MemberDecorate 11(gl_PerVertex) 2 BuiltIn ClipDistance
MemberDecorate 11(gl_PerVertex) 3 BuiltIn CullDistance
Decorate 11(gl_PerVertex) Block
Decorate 18 SpecId 11
Decorate 25(gl_VertexID) BuiltIn VertexId
Decorate 26(gl_InstanceID) BuiltIn InstanceId
2: TypeVoid
3: TypeFunction 2
6: TypeFloat 32
7: TypeVector 6(float) 4
8: TypeInt 32 0
9: 8(int) Constant 1
10: TypeArray 6(float) 9
11(gl_PerVertex): TypeStruct 7(fvec4) 6(float) 10 10
12: TypePointer Output 11(gl_PerVertex)
13: 12(ptr) Variable Output
14: TypeInt 32 1
15: 14(int) Constant 0
16: 6(float) Constant 1065353216
17: 7(fvec4) ConstantComposite 16 16 16 16
18: 14(int) SpecConstant 8
22: TypePointer Output 7(fvec4)
24: TypePointer Input 14(int)
25(gl_VertexID): 24(ptr) Variable Input
26(gl_InstanceID): 24(ptr) Variable Input
4(main): 2 Function None 3
5: Label
19: 6(float) ConvertSToF 18
20: 7(fvec4) CompositeConstruct 19 19 19 19
21: 7(fvec4) FDiv 17 20
23: 22(ptr) AccessChain 13 15
Store 23 21
Return
FunctionEnd

View File

@ -0,0 +1,5 @@
#version 310 es
void main()
{
}

14
Test/glspv.frag Normal file
View File

@ -0,0 +1,14 @@
#version 330
#ifdef GL_SPIRV
#error GL_SPIRV is set ( correct, not an error )
#if GL_SPIRV == 100
#error GL_SPIR is 100
#endif
#endif
void main()
{
}
layout(input_attachment_index = 1) uniform subpassInput sub; // ERROR, no inputs

5
Test/glspv.version.frag Normal file
View File

@ -0,0 +1,5 @@
#version 330 compatibility
void main()
{
}

5
Test/glspv.version.vert Normal file
View File

@ -0,0 +1,5 @@
#version 150
void main()
{
}

20
Test/glspv.vert Normal file
View File

@ -0,0 +1,20 @@
#version 450
layout(push_constant) uniform Material { int a; } mat; // ERROR, can't use push_constant
layout(set = 0, binding = 0, std140) uniform Bt1 { int a; } bt1;
layout(set = 1, binding = 0, std140) uniform Bt2 { int a; } bt2; // ERROR, set has to be 0
layout(shared) uniform Bt3 { int a; } bt3; // ERROR, no shared
layout(packed) uniform Bt4 { int a; } bt4; // ERROR, no shared
void main()
{
gl_VertexIndex; // ERROR, not preset
gl_InstanceIndex; // ERROR, not present
gl_VertexID;
gl_InstanceID;
gl_DepthRangeParameters; // ERROR, not present
}
uniform sampler s; // ERROR, no sampler

View File

@ -0,0 +1,6 @@
#version 330
void main()
{
gl_FragColor = vec4(1.0);
}

8
Test/spv.specConst.vert Normal file
View File

@ -0,0 +1,8 @@
#version 450
layout(constant_id = 11) const int a = 8;
void main()
{
gl_Position = vec4(1.0) / a;
}

View File

@ -1985,17 +1985,14 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
"\n");
}
if (version >= 130 && spvVersion.vulkan == 0)
// gl_spirv TODO
stageBuiltins[EShLangVertex].append(
"int gl_VertexID;" // needs qualifier fixed later
);
if (version >= 140 && spvVersion.vulkan == 0)
// gl_spirv TODO
stageBuiltins[EShLangVertex].append(
"int gl_InstanceID;" // needs qualifier fixed later
);
if (spvVersion.vulkan >= 100 && version >= 140)
// gl_spirv TODO
stageBuiltins[EShLangVertex].append(
"in int gl_VertexIndex;"
"in int gl_InstanceIndex;"
@ -2016,13 +2013,11 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
);
} else {
if (spvVersion.vulkan == 0)
// gl_spirv TODO
stageBuiltins[EShLangVertex].append(
"in highp int gl_VertexID;" // needs qualifier fixed later
"in highp int gl_InstanceID;" // needs qualifier fixed later
);
if (spvVersion.vulkan >= 100)
// gl_spirv TODO
stageBuiltins[EShLangVertex].append(
"in highp int gl_VertexIndex;"
"in highp int gl_InstanceIndex;"
@ -3633,13 +3628,14 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
}
if (spvVersion.vulkan == 0) {
// gl_spirv TODO
SpecialQualifier("gl_VertexID", EvqVertexId, EbvVertexId, symbolTable);
SpecialQualifier("gl_InstanceID", EvqInstanceId, EbvInstanceId, symbolTable);
}
if (spvVersion.vulkan >= 100) {
BuiltInVariable("gl_VertexIndex", EbvVertexIndex, symbolTable);
BuiltInVariable("gl_InstanceIndex", EbvInstanceIndex, symbolTable);
}
// Fall through

View File

@ -4109,7 +4109,10 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi
std::transform(id.begin(), id.end(), id.begin(), ::tolower);
if (id == "offset") {
const char* feature = "uniform offset";
// "offset" can be for either
// - uniform offsets
// - atomic_uint offsets
const char* feature = "offset";
requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, feature);
const char* exts[2] = { E_GL_ARB_enhanced_layouts, E_GL_ARB_shader_atomic_counters };
profileRequires(loc, ECoreProfile | ECompatibilityProfile, 420, 2, exts, feature);
@ -4140,6 +4143,8 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi
error(loc, "set is too large", id.c_str(), "");
else
publicType.qualifier.layoutSet = value;
if (value != 0)
requireVulkan(loc, "descriptor set");
return;
} else if (id == "binding") {
profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, "binding");

View File

@ -468,7 +468,11 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo
infoSink.info.message(EPrefixError, "#version: ES shaders for Vulkan SPIR-V require version 310 or higher");
version = 310;
}
// gl_spirv TODO: test versions
if (spvVersion.openGl >= 100) {
correct = false;
infoSink.info.message(EPrefixError, "#version: ES shaders for OpenGL SPIR-V are not supported");
version = 310;
}
break;
case ECompatibilityProfile:
infoSink.info.message(EPrefixError, "#version: compilation for SPIR-V does not support the compatibility profile");
@ -479,7 +483,11 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo
infoSink.info.message(EPrefixError, "#version: Desktop shaders for Vulkan SPIR-V require version 140 or higher");
version = 140;
}
// gl_spirv TODO: test versions
if (spvVersion.openGl >= 100 && version < 330) {
correct = false;
infoSink.info.message(EPrefixError, "#version: Desktop shaders for OpenGL SPIR-V require version 330 or higher");
version = 330;
}
break;
}
}
@ -623,6 +631,10 @@ bool ProcessDeferred(
if (messages & EShMsgSpvRules)
spvVersion.spv = 0x00010000; // TODO: eventually have this come from the outside
EShSource source = (messages & EShMsgReadHlsl) ? EShSourceHlsl : EShSourceGlsl;
if (messages & EShMsgVulkanRules)
spvVersion.vulkan = 100; // TODO: eventually have this come from the outside
else if (spvVersion.spv != 0)
spvVersion.openGl = 100; // TODO: eventually have this come from the outside
bool goodVersion = DeduceVersionProfile(compiler->infoSink, compiler->getLanguage(), versionNotFirst, defaultVersion, source, version, profile, spvVersion);
bool versionWillBeError = (versionNotFound || (profile == EEsProfile && version >= 300 && versionNotFirst));
bool warnVersionNotFirst = false;
@ -633,10 +645,6 @@ bool ProcessDeferred(
versionWillBeError = true;
}
if (messages & EShMsgVulkanRules)
spvVersion.vulkan = 100; // TODO: eventually have this come from the outside
else if (spvVersion.spv != 0)
spvVersion.openGl = 100;
intermediate.setSource(source);
intermediate.setVersion(version);
intermediate.setProfile(profile);

View File

@ -176,7 +176,6 @@ void TParseVersions::initializeExtensionBehavior()
extensionBehavior[E_GL_ARB_shader_texture_image_samples] = EBhDisable;
extensionBehavior[E_GL_ARB_viewport_array] = EBhDisable;
extensionBehavior[E_GL_ARB_gpu_shader_int64] = EBhDisable;
extensionBehavior[E_GL_ARB_gl_spirv] = EBhDisable;
extensionBehavior[E_GL_ARB_shader_ballot] = EBhDisable;
extensionBehavior[E_GL_ARB_sparse_texture2] = EBhDisable;
extensionBehavior[E_GL_ARB_sparse_texture_clamp] = EBhDisable;
@ -282,7 +281,6 @@ void TParseVersions::getPreamble(std::string& preamble)
"#define GL_ARB_shader_texture_image_samples 1\n"
"#define GL_ARB_viewport_array 1\n"
"#define GL_ARB_gpu_shader_int64 1\n"
"#define GL_ARB_gl_spirv 1\n"
"#define GL_ARB_shader_ballot 1\n"
"#define GL_ARB_sparse_texture2 1\n"
"#define GL_ARB_sparse_texture_clamp 1\n"
@ -298,14 +296,22 @@ void TParseVersions::getPreamble(std::string& preamble)
;
// #define VULKAN XXXX
const int numberBufSize = 12;
char numberBuf[numberBufSize];
if (spvVersion.vulkan > 0) {
preamble += "#define VULKAN ";
char number[12];
snprintf(number, 12, "%d", spvVersion.vulkan);
preamble += number;
snprintf(numberBuf, numberBufSize, "%d", spvVersion.vulkan);
preamble += numberBuf;
preamble += "\n";
}
// gl_spirv TODO
// #define GL_SPIRV XXXX
if (spvVersion.openGl > 0) {
preamble += "#define GL_SPIRV ";
snprintf(numberBuf, numberBufSize, "%d", spvVersion.openGl);
preamble += numberBuf;
preamble += "\n";
}
}
//

View File

@ -79,7 +79,7 @@ struct SpvVersion {
SpvVersion() : spv(0), vulkan(0), openGl(0) {}
unsigned int spv; // the version of the targeted SPIR-V, as defined by SPIR-V in word 1 of the SPIR-V binary header
int vulkan; // the version of semantics for Vulkan; e.g., for GLSL from KHR_vulkan_glsl "#define VULKAN"
int openGl; // the version of semantics for OpenGL; gl_spirv TODO
int openGl; // the version of semantics for OpenGL; e.g., for GLSL from KHR_vulkan_glsl "#define GL_SPIRV"
};
//
@ -124,7 +124,6 @@ const char* const E_GL_ARB_derivative_control = "GL_ARB_derivative_con
const char* const E_GL_ARB_shader_texture_image_samples = "GL_ARB_shader_texture_image_samples";
const char* const E_GL_ARB_viewport_array = "GL_ARB_viewport_array";
const char* const E_GL_ARB_gpu_shader_int64 = "GL_ARB_gpu_shader_int64";
const char* const E_GL_ARB_gl_spirv = "GL_ARB_gl_spirv";
const char* const E_GL_ARB_shader_ballot = "GL_ARB_shader_ballot";
const char* const E_GL_ARB_sparse_texture2 = "GL_ARB_sparse_texture2";
const char* const E_GL_ARB_sparse_texture_clamp = "GL_ARB_sparse_texture_clamp";

View File

@ -44,6 +44,7 @@ namespace {
using CompileVulkanToSpirvTest = GlslangTest<::testing::TestWithParam<std::string>>;
using CompileOpenGLToSpirvTest = GlslangTest<::testing::TestWithParam<std::string>>;
using VulkanSemantics = GlslangTest<::testing::TestWithParam<std::string>>;
using OpenGLSemantics = GlslangTest<::testing::TestWithParam<std::string>>;
using VulkanAstSemantics = GlslangTest<::testing::TestWithParam<std::string>>;
// Compiling GLSL to SPIR-V under Vulkan semantics. Expected to successfully
@ -73,6 +74,15 @@ TEST_P(VulkanSemantics, FromFile)
Target::Spv);
}
// GLSL-level Vulkan semantics test. Expected to error out before generating
// SPIR-V.
TEST_P(OpenGLSemantics, FromFile)
{
loadFileCompileAndCheck(GLSLANG_TEST_DIRECTORY, GetParam(),
Source::GLSL, Semantics::OpenGL,
Target::Spv);
}
// GLSL-level Vulkan semantics test that need to see the AST for validation.
TEST_P(VulkanAstSemantics, FromFile)
{
@ -206,10 +216,9 @@ INSTANTIATE_TEST_CASE_P(
INSTANTIATE_TEST_CASE_P(
Glsl, CompileOpenGLToSpirvTest,
::testing::ValuesIn(std::vector<std::string>({
// Test looping constructs.
// No tests yet for making sure break and continue from a nested loop
// goes to the innermost target.
"spv.atomic.comp",
"spv.glFragColor.frag",
"spv.specConst.vert",
})),
FileNameAsCustomTestSuffix
);
@ -224,6 +233,18 @@ INSTANTIATE_TEST_CASE_P(
FileNameAsCustomTestSuffix
);
INSTANTIATE_TEST_CASE_P(
Glsl, OpenGLSemantics,
::testing::ValuesIn(std::vector<std::string>({
"glspv.esversion.vert",
"glspv.version.frag",
"glspv.version.vert",
"glspv.frag",
"glspv.vert",
})),
FileNameAsCustomTestSuffix
);
INSTANTIATE_TEST_CASE_P(
Glsl, VulkanAstSemantics,
::testing::ValuesIn(std::vector<std::string>({