SPV: Add auto location mapping of non-opaque non-block uniform variables.
Fix #1019.
This commit is contained in:
parent
8268a35504
commit
82e95a3aa5
@ -1,10 +1,9 @@
|
|||||||
glspv.frag
|
glspv.frag
|
||||||
ERROR: 0:4: '#error' : GL_SPIRV is set ( correct , not an error )
|
ERROR: 0:4: '#error' : GL_SPIRV is set ( correct , not an error )
|
||||||
ERROR: 0:6: '#error' : GL_SPIR is 100
|
ERROR: 0:6: '#error' : GL_SPIR is 100
|
||||||
ERROR: 0:14: 'f' : non-opaque uniform variables need a layout(location=L)
|
|
||||||
ERROR: 0:19: 'input_attachment_index' : only allowed when using GLSL for Vulkan
|
ERROR: 0:19: 'input_attachment_index' : only allowed when using GLSL for Vulkan
|
||||||
ERROR: 0:19: '' : syntax error, unexpected IDENTIFIER, expecting LEFT_BRACE or COMMA or SEMICOLON
|
ERROR: 0:19: '' : syntax error, unexpected IDENTIFIER, expecting LEFT_BRACE or COMMA or SEMICOLON
|
||||||
ERROR: 5 compilation errors. No code generated.
|
ERROR: 4 compilation errors. No code generated.
|
||||||
|
|
||||||
|
|
||||||
SPIR-V is not generated for failed compile or link
|
SPIR-V is not generated for failed compile or link
|
||||||
|
8
Test/baseResults/spv.looseUniformNoLoc.vert.out
Normal file
8
Test/baseResults/spv.looseUniformNoLoc.vert.out
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
spv.looseUniformNoLoc.vert
|
||||||
|
ERROR: spv.looseUniformNoLoc.vert:9: 'uv' : non-opaque uniform variables need a layout(location=L)
|
||||||
|
ERROR: 1 compilation errors. No code generated.
|
||||||
|
|
||||||
|
|
||||||
|
ERROR: Linking vertex stage: Missing entry point: Each stage requires one entry point
|
||||||
|
|
||||||
|
SPIR-V is not generated for failed compile or link
|
@ -1,12 +1,12 @@
|
|||||||
spv.noBuiltInLoc.vert
|
spv.noBuiltInLoc.vert
|
||||||
// Module Version 10000
|
// Module Version 10000
|
||||||
// Generated by (magic number): 80001
|
// Generated by (magic number): 80001
|
||||||
// Id's are bound by 23
|
// Id's are bound by 33
|
||||||
|
|
||||||
Capability Shader
|
Capability Shader
|
||||||
1: ExtInstImport "GLSL.std.450"
|
1: ExtInstImport "GLSL.std.450"
|
||||||
MemoryModel Logical GLSL450
|
MemoryModel Logical GLSL450
|
||||||
EntryPoint Vertex 4 "main" 9 11 18
|
EntryPoint Vertex 4 "main" 9 11 18 31 32
|
||||||
Source GLSL 450
|
Source GLSL 450
|
||||||
Name 4 "main"
|
Name 4 "main"
|
||||||
Name 9 "bar"
|
Name 9 "bar"
|
||||||
@ -17,6 +17,11 @@ spv.noBuiltInLoc.vert
|
|||||||
MemberName 16(gl_PerVertex) 2 "gl_ClipDistance"
|
MemberName 16(gl_PerVertex) 2 "gl_ClipDistance"
|
||||||
MemberName 16(gl_PerVertex) 3 "gl_CullDistance"
|
MemberName 16(gl_PerVertex) 3 "gl_CullDistance"
|
||||||
Name 18 ""
|
Name 18 ""
|
||||||
|
Name 24 "uv1"
|
||||||
|
Name 26 "uv2"
|
||||||
|
Name 29 "uv3"
|
||||||
|
Name 31 "gl_VertexID"
|
||||||
|
Name 32 "gl_InstanceID"
|
||||||
Decorate 9(bar) Location 0
|
Decorate 9(bar) Location 0
|
||||||
Decorate 11(foo) Location 0
|
Decorate 11(foo) Location 0
|
||||||
MemberDecorate 16(gl_PerVertex) 0 BuiltIn Position
|
MemberDecorate 16(gl_PerVertex) 0 BuiltIn Position
|
||||||
@ -24,6 +29,14 @@ spv.noBuiltInLoc.vert
|
|||||||
MemberDecorate 16(gl_PerVertex) 2 BuiltIn ClipDistance
|
MemberDecorate 16(gl_PerVertex) 2 BuiltIn ClipDistance
|
||||||
MemberDecorate 16(gl_PerVertex) 3 BuiltIn CullDistance
|
MemberDecorate 16(gl_PerVertex) 3 BuiltIn CullDistance
|
||||||
Decorate 16(gl_PerVertex) Block
|
Decorate 16(gl_PerVertex) Block
|
||||||
|
Decorate 24(uv1) Location 0
|
||||||
|
Decorate 24(uv1) DescriptorSet 0
|
||||||
|
Decorate 26(uv2) Location 1
|
||||||
|
Decorate 26(uv2) DescriptorSet 0
|
||||||
|
Decorate 29(uv3) Location 2
|
||||||
|
Decorate 29(uv3) DescriptorSet 0
|
||||||
|
Decorate 31(gl_VertexID) BuiltIn VertexId
|
||||||
|
Decorate 32(gl_InstanceID) BuiltIn InstanceId
|
||||||
2: TypeVoid
|
2: TypeVoid
|
||||||
3: TypeFunction 2
|
3: TypeFunction 2
|
||||||
6: TypeFloat 32
|
6: TypeFloat 32
|
||||||
@ -40,6 +53,16 @@ spv.noBuiltInLoc.vert
|
|||||||
18: 17(ptr) Variable Output
|
18: 17(ptr) Variable Output
|
||||||
19: TypeInt 32 1
|
19: TypeInt 32 1
|
||||||
20: 19(int) Constant 0
|
20: 19(int) Constant 0
|
||||||
|
23: TypePointer UniformConstant 7(fvec4)
|
||||||
|
24(uv1): 23(ptr) Variable UniformConstant
|
||||||
|
25: TypePointer UniformConstant 6(float)
|
||||||
|
26(uv2): 25(ptr) Variable UniformConstant
|
||||||
|
27: TypeVector 6(float) 3
|
||||||
|
28: TypePointer UniformConstant 27(fvec3)
|
||||||
|
29(uv3): 28(ptr) Variable UniformConstant
|
||||||
|
30: TypePointer Input 19(int)
|
||||||
|
31(gl_VertexID): 30(ptr) Variable Input
|
||||||
|
32(gl_InstanceID): 30(ptr) Variable Input
|
||||||
4(main): 2 Function None 3
|
4(main): 2 Function None 3
|
||||||
5: Label
|
5: Label
|
||||||
12: 7(fvec4) Load 11(foo)
|
12: 7(fvec4) Load 11(foo)
|
||||||
|
@ -109,8 +109,10 @@ diff -b $BASEDIR/hlsl.explicitDescriptorSet-2.frag.out $TARGETDIR/hlsl.explicitD
|
|||||||
echo Testing SPV no location
|
echo Testing SPV no location
|
||||||
$EXE -V -C spv.noLocation.vert > $TARGETDIR/spv.noLocation.vert.out
|
$EXE -V -C spv.noLocation.vert > $TARGETDIR/spv.noLocation.vert.out
|
||||||
diff -b $BASEDIR/spv.noLocation.vert.out $TARGETDIR/spv.noLocation.vert.out || HASERROR=1
|
diff -b $BASEDIR/spv.noLocation.vert.out $TARGETDIR/spv.noLocation.vert.out || HASERROR=1
|
||||||
$EXE -H --aml spv.noBuiltInLoc.vert > $TARGETDIR/spv.noBuiltInLoc.vert.out
|
$EXE -G -H --aml spv.noBuiltInLoc.vert > $TARGETDIR/spv.noBuiltInLoc.vert.out
|
||||||
diff -b $BASEDIR/spv.noBuiltInLoc.vert.out $TARGETDIR/spv.noBuiltInLoc.vert.out || HASERROR=1
|
diff -b $BASEDIR/spv.noBuiltInLoc.vert.out $TARGETDIR/spv.noBuiltInLoc.vert.out || HASERROR=1
|
||||||
|
$EXE -G spv.looseUniformNoLoc.vert > $TARGETDIR/spv.looseUniformNoLoc.vert.out
|
||||||
|
diff -b $BASEDIR/spv.looseUniformNoLoc.vert.out $TARGETDIR/spv.looseUniformNoLoc.vert.out || HASERROR=1
|
||||||
|
|
||||||
#
|
#
|
||||||
# Testing debug information
|
# Testing debug information
|
||||||
|
15
Test/spv.looseUniformNoLoc.vert
Normal file
15
Test/spv.looseUniformNoLoc.vert
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#version 450 core
|
||||||
|
|
||||||
|
layout(location = 0)
|
||||||
|
in vec4 foo;
|
||||||
|
|
||||||
|
layout(location = 0)
|
||||||
|
out vec4 bar;
|
||||||
|
|
||||||
|
uniform vec4 uv;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
bar = foo;
|
||||||
|
gl_Position = foo;
|
||||||
|
}
|
@ -6,6 +6,10 @@ in vec4 foo;
|
|||||||
layout(location = 0)
|
layout(location = 0)
|
||||||
out vec4 bar;
|
out vec4 bar;
|
||||||
|
|
||||||
|
uniform vec4 uv1;
|
||||||
|
uniform float uv2;
|
||||||
|
uniform vec3 uv3;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
bar = foo;
|
bar = foo;
|
||||||
|
@ -2493,8 +2493,8 @@ void TParseContext::transparentOpaqueCheck(const TSourceLoc& loc, const TType& t
|
|||||||
// Vulkan doesn't allow transparent uniforms outside of blocks
|
// Vulkan doesn't allow transparent uniforms outside of blocks
|
||||||
if (spvVersion.vulkan > 0)
|
if (spvVersion.vulkan > 0)
|
||||||
vulkanRemoved(loc, "non-opaque uniforms outside a block");
|
vulkanRemoved(loc, "non-opaque uniforms outside a block");
|
||||||
// OpenGL wants locations on these
|
// OpenGL wants locations on these (unless they are getting automapped)
|
||||||
if (spvVersion.openGl > 0 && !type.getQualifier().hasLocation())
|
if (spvVersion.openGl > 0 && !type.getQualifier().hasLocation() && !intermediate.getAutoMapLocations())
|
||||||
error(loc, "non-opaque uniform variables need a layout(location=L)", identifier.c_str(), "");
|
error(loc, "non-opaque uniform variables need a layout(location=L)", identifier.c_str(), "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -253,10 +253,14 @@ struct TResolverUniformAdaptor
|
|||||||
ent.newBinding = -1;
|
ent.newBinding = -1;
|
||||||
ent.newSet = -1;
|
ent.newSet = -1;
|
||||||
ent.newIndex = -1;
|
ent.newIndex = -1;
|
||||||
const bool isValid = resolver.validateBinding(stage, ent.symbol->getName().c_str(), ent.symbol->getType(), ent.live);
|
const bool isValid = resolver.validateBinding(stage, ent.symbol->getName().c_str(), ent.symbol->getType(),
|
||||||
|
ent.live);
|
||||||
if (isValid) {
|
if (isValid) {
|
||||||
ent.newBinding = resolver.resolveBinding(stage, ent.symbol->getName().c_str(), ent.symbol->getType(), ent.live);
|
ent.newBinding = resolver.resolveBinding(stage, ent.symbol->getName().c_str(), ent.symbol->getType(),
|
||||||
|
ent.live);
|
||||||
ent.newSet = resolver.resolveSet(stage, ent.symbol->getName().c_str(), ent.symbol->getType(), ent.live);
|
ent.newSet = resolver.resolveSet(stage, ent.symbol->getName().c_str(), ent.symbol->getType(), ent.live);
|
||||||
|
ent.newLocation = resolver.resolveUniformLocation(stage, ent.symbol->getName().c_str(),
|
||||||
|
ent.symbol->getType(), ent.live);
|
||||||
|
|
||||||
if (ent.newBinding != -1) {
|
if (ent.newBinding != -1) {
|
||||||
if (ent.newBinding >= int(TQualifier::layoutBindingEnd)) {
|
if (ent.newBinding >= int(TQualifier::layoutBindingEnd)) {
|
||||||
@ -356,6 +360,7 @@ struct TDefaultIoResolverBase : public glslang::TIoMapResolver
|
|||||||
std::vector<std::string> baseResourceSetBinding;
|
std::vector<std::string> baseResourceSetBinding;
|
||||||
bool doAutoBindingMapping;
|
bool doAutoBindingMapping;
|
||||||
bool doAutoLocationMapping;
|
bool doAutoLocationMapping;
|
||||||
|
int nextUniformLocation;
|
||||||
typedef std::vector<int> TSlotSet;
|
typedef std::vector<int> TSlotSet;
|
||||||
typedef std::unordered_map<int, TSlotSet> TSlotSetMap;
|
typedef std::unordered_map<int, TSlotSet> TSlotSetMap;
|
||||||
TSlotSetMap slots;
|
TSlotSetMap slots;
|
||||||
@ -411,7 +416,27 @@ struct TDefaultIoResolverBase : public glslang::TIoMapResolver
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
int resolveUniformLocation(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& type, bool is_live) override
|
||||||
|
{
|
||||||
|
// kick out of not doing this
|
||||||
|
if (!doAutoLocationMapping)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
// no locations added if already present, a built-in variable, a block, or an opaque
|
||||||
|
if (type.getQualifier().hasLocation() || type.isBuiltIn() ||
|
||||||
|
type.getBasicType() == EbtBlock || type.containsOpaque())
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
// no locations on blocks of built-in variables
|
||||||
|
if (type.isStruct()) {
|
||||||
|
if (type.getStruct()->size() < 1)
|
||||||
|
return -1;
|
||||||
|
if ((*type.getStruct())[0].type->isBuiltIn())
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nextUniformLocation++;
|
||||||
|
}
|
||||||
bool validateInOut(EShLanguage /*stage*/, const char* /*name*/, const TType& /*type*/, bool /*is_live*/) override
|
bool validateInOut(EShLanguage /*stage*/, const char* /*name*/, const TType& /*type*/, bool /*is_live*/) override
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
@ -700,6 +725,7 @@ bool TIoMapper::addStage(EShLanguage stage, TIntermediate &intermediate, TInfoSi
|
|||||||
resolverBase->baseResourceSetBinding = intermediate.getResourceSetBinding();
|
resolverBase->baseResourceSetBinding = intermediate.getResourceSetBinding();
|
||||||
resolverBase->doAutoBindingMapping = intermediate.getAutoMapBindings();
|
resolverBase->doAutoBindingMapping = intermediate.getAutoMapBindings();
|
||||||
resolverBase->doAutoLocationMapping = intermediate.getAutoMapLocations();
|
resolverBase->doAutoLocationMapping = intermediate.getAutoMapLocations();
|
||||||
|
resolverBase->nextUniformLocation = 0;
|
||||||
|
|
||||||
resolver = resolverBase;
|
resolver = resolverBase;
|
||||||
}
|
}
|
||||||
|
@ -533,9 +533,10 @@ class TIoMapper;
|
|||||||
|
|
||||||
// Allows to customize the binding layout after linking.
|
// Allows to customize the binding layout after linking.
|
||||||
// All used uniform variables will invoke at least validateBinding.
|
// All used uniform variables will invoke at least validateBinding.
|
||||||
// If validateBinding returned true then the other resolveBinding
|
// If validateBinding returned true then the other resolveBinding,
|
||||||
// and resolveSet are invoked to resolve the binding and descriptor
|
// resolveSet, and resolveLocation are invoked to resolve the binding
|
||||||
// set index respectively.
|
// and descriptor set index respectively.
|
||||||
|
//
|
||||||
// Invocations happen in a particular order:
|
// Invocations happen in a particular order:
|
||||||
// 1) all shader inputs
|
// 1) all shader inputs
|
||||||
// 2) all shader outputs
|
// 2) all shader outputs
|
||||||
@ -567,6 +568,9 @@ public:
|
|||||||
// Should return a value >= 0 if the current set should be overridden.
|
// Should return a value >= 0 if the current set should be overridden.
|
||||||
// Return -1 if the current set (including no set) should be kept.
|
// Return -1 if the current set (including no set) should be kept.
|
||||||
virtual int resolveSet(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0;
|
virtual int resolveSet(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0;
|
||||||
|
// Should return a value >= 0 if the current location should be overridden.
|
||||||
|
// Return -1 if the current location (including no location) should be kept.
|
||||||
|
virtual int resolveUniformLocation(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0;
|
||||||
// Should return true if the resulting/current setup would be okay.
|
// Should return true if the resulting/current setup would be okay.
|
||||||
// Basic idea is to do aliasing checks and reject invalid semantic names.
|
// Basic idea is to do aliasing checks and reject invalid semantic names.
|
||||||
virtual bool validateInOut(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0;
|
virtual bool validateInOut(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user