SPV: Handle GLSL bool loads from a uniform buffer as a conversion from int -> bool.

SPIR-V bool is abstract; it has no bit pattern for storage with transparent memory.
OpenGL's convention is a bool in a uniform buffer is 32-bit int with non-0 being 'true'.
This commit is contained in:
John Kessenich 2016-02-08 21:38:15 -07:00
parent 10110596a3
commit 103bef9d74
4 changed files with 96 additions and 51 deletions

View File

@ -1570,7 +1570,12 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
spvType = builder.makeFloatType(64); spvType = builder.makeFloatType(64);
break; break;
case glslang::EbtBool: case glslang::EbtBool:
spvType = builder.makeBoolType(); // "transparent" bool doesn't exist in SPIR-V. The GLSL convention is
// a 32-bit int where non-0 means true.
if (explicitLayout != glslang::ElpNone)
spvType = builder.makeUintType(32);
else
spvType = builder.makeBoolType();
break; break;
case glslang::EbtInt: case glslang::EbtInt:
spvType = builder.makeIntType(32); spvType = builder.makeIntType(32);
@ -1764,9 +1769,21 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
return spvType; return spvType;
} }
// Wrap the builder's accessChainLoad to:
// - localize handling of RelaxedPrecision
// - use the SPIR-V inferred type instead of another conversion of the glslang type
// (avoids unnecessary work and possible type punning for structures)
// - do conversion of concrete to abstract type
spv::Id TGlslangToSpvTraverser::accessChainLoad(const glslang::TType& type) spv::Id TGlslangToSpvTraverser::accessChainLoad(const glslang::TType& type)
{ {
return builder.accessChainLoad(TranslatePrecisionDecoration(type), convertGlslangToSpvType(type)); spv::Id nominalTypeId = builder.accessChainGetInferredType();
spv::Id loadedId = builder.accessChainLoad(TranslatePrecisionDecoration(type), nominalTypeId);
// Need to convert to abstract types when necessary
if (builder.isScalarType(nominalTypeId) && type.getBasicType() == glslang::EbtBool && nominalTypeId != builder.makeBoolType())
loadedId = builder.createBinOp(spv::OpINotEqual, builder.makeBoolType(), loadedId, builder.makeUintConstant(0));
return loadedId;
} }
// Decide whether or not this type should be // Decide whether or not this type should be

View File

@ -1990,6 +1990,39 @@ Id Builder::accessChainGetLValue()
return lvalue; return lvalue;
} }
// comment in header
Id Builder::accessChainGetInferredType()
{
// anything to operate on?
if (accessChain.base == NoResult)
return NoType;
Id type = getTypeId(accessChain.base);
// do initial dereference
if (! accessChain.isRValue)
type = getContainedTypeId(type);
// dereference each index
for (auto deref : accessChain.indexChain) {
if (isStructType(type))
type = getContainedTypeId(type, getConstantScalar(deref));
else
type = getContainedTypeId(type);
}
// dereference swizzle
if (accessChain.swizzle.size() == 1)
type = getContainedTypeId(type);
else if (accessChain.swizzle.size() > 1)
type = makeVectorType(getContainedTypeId(type), accessChain.swizzle.size());
// dereference component selection
if (accessChain.component)
type = getContainedTypeId(type);
return type;
}
void Builder::dump(std::vector<unsigned int>& out) const void Builder::dump(std::vector<unsigned int>& out) const
{ {
// Header, before first instructions: // Header, before first instructions:

View File

@ -506,6 +506,10 @@ public:
// get the direct pointer for an l-value // get the direct pointer for an l-value
Id accessChainGetLValue(); Id accessChainGetLValue();
// Get the inferred SPIR-V type of the result of the current access chain,
// based on the type of the base and the chain of dereferences.
Id accessChainGetInferredType();
void dump(std::vector<unsigned int>&) const; void dump(std::vector<unsigned int>&) const;
void createBranch(Block* block); void createBranch(Block* block);

View File

@ -7,12 +7,12 @@ Linked fragment stage:
// Module Version 10000 // Module Version 10000
// Generated by (magic number): 80001 // Generated by (magic number): 80001
// Id's are bound by 380 // Id's are bound by 378
Capability Shader Capability Shader
1: ExtInstImport "GLSL.std.450" 1: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450 MemoryModel Logical GLSL450
EntryPoint Fragment 4 "main" 16 41 90 376 EntryPoint Fragment 4 "main" 16 41 90 374
ExecutionMode 4 OriginLowerLeft ExecutionMode 4 OriginLowerLeft
Source GLSL 450 Source GLSL 450
Name 4 "main" Name 4 "main"
@ -42,15 +42,8 @@ Linked fragment stage:
Name 343 "bn" Name 343 "bn"
MemberName 343(bn) 0 "foo2a" MemberName 343(bn) 0 "foo2a"
Name 345 "bi" Name 345 "bi"
Name 347 "s1" Name 374 "color"
MemberName 347(s1) 0 "i" Name 377 "foo1"
MemberName 347(s1) 1 "f"
Name 348 "s2"
MemberName 348(s2) 0 "i"
MemberName 348(s2) 1 "f"
MemberName 348(s2) 2 "s1_1"
Name 376 "color"
Name 379 "foo1"
MemberDecorate 341(s1) 0 Offset 0 MemberDecorate 341(s1) 0 Offset 0
MemberDecorate 341(s1) 1 Offset 4 MemberDecorate 341(s1) 1 Offset 4
MemberDecorate 342(s2) 0 Offset 0 MemberDecorate 342(s2) 0 Offset 0
@ -108,14 +101,12 @@ Linked fragment stage:
344: TypePointer Uniform 343(bn) 344: TypePointer Uniform 343(bn)
345(bi): 344(ptr) Variable Uniform 345(bi): 344(ptr) Variable Uniform
346: 6(int) Constant 0 346: 6(int) Constant 0
347(s1): TypeStruct 6(int) 7(float) 347: TypePointer Uniform 342(s2)
348(s2): TypeStruct 6(int) 7(float) 347(s1) 370: 7(float) Constant 1090519040
349: TypePointer Uniform 342(s2) 373: TypePointer Output 14(fvec4)
372: 7(float) Constant 1090519040 374(color): 373(ptr) Variable Output
375: TypePointer Output 14(fvec4) 376: TypePointer UniformConstant 8(s1)
376(color): 375(ptr) Variable Output 377(foo1): 376(ptr) Variable UniformConstant
378: TypePointer UniformConstant 8(s1)
379(foo1): 378(ptr) Variable UniformConstant
4(main): 2 Function None 3 4(main): 2 Function None 3
5: Label 5: Label
13(a): 12(ptr) Variable Function 13(a): 12(ptr) Variable Function
@ -439,35 +430,35 @@ Linked fragment stage:
Store 82(v) 340 Store 82(v) 340
Branch 337 Branch 337
337: Label 337: Label
350: 349(ptr) AccessChain 345(bi) 346 348: 347(ptr) AccessChain 345(bi) 346
351: 342(s2) Load 350 349: 342(s2) Load 348
352: 55(s2) Load 57(foo2a) 350: 55(s2) Load 57(foo2a)
353: 6(int) CompositeExtract 351 0 351: 6(int) CompositeExtract 349 0
354: 6(int) CompositeExtract 352 0 352: 6(int) CompositeExtract 350 0
355: 61(bool) INotEqual 353 354 353: 61(bool) INotEqual 351 352
356: 7(float) CompositeExtract 351 1 354: 7(float) CompositeExtract 349 1
357: 7(float) CompositeExtract 352 1 355: 7(float) CompositeExtract 350 1
358: 61(bool) FOrdNotEqual 356 357 356: 61(bool) FOrdNotEqual 354 355
359: 61(bool) LogicalOr 355 358 357: 61(bool) LogicalOr 353 356
360: 341(s1) CompositeExtract 351 2 358: 341(s1) CompositeExtract 349 2
361: 8(s1) CompositeExtract 352 2 359: 8(s1) CompositeExtract 350 2
362: 6(int) CompositeExtract 360 0 360: 6(int) CompositeExtract 358 0
363: 6(int) CompositeExtract 361 0 361: 6(int) CompositeExtract 359 0
364: 61(bool) INotEqual 362 363 362: 61(bool) INotEqual 360 361
365: 7(float) CompositeExtract 360 1 363: 7(float) CompositeExtract 358 1
366: 7(float) CompositeExtract 361 1 364: 7(float) CompositeExtract 359 1
367: 61(bool) FOrdNotEqual 365 366 365: 61(bool) FOrdNotEqual 363 364
368: 61(bool) LogicalOr 364 367 366: 61(bool) LogicalOr 362 365
369: 61(bool) LogicalOr 359 368 367: 61(bool) LogicalOr 357 366
SelectionMerge 371 None SelectionMerge 369 None
BranchConditional 369 370 371 BranchConditional 367 368 369
370: Label 368: Label
373: 14(fvec4) Load 82(v) 371: 14(fvec4) Load 82(v)
374: 14(fvec4) VectorTimesScalar 373 372 372: 14(fvec4) VectorTimesScalar 371 370
Store 82(v) 374 Store 82(v) 372
Branch 371 Branch 369
371: Label 369: Label
377: 14(fvec4) Load 82(v) 375: 14(fvec4) Load 82(v)
Store 376(color) 377 Store 374(color) 375
Return Return
FunctionEnd FunctionEnd