Vulkan: Finish semantics for what creates spec-const-semantics.

Note: This required adding a new test mode to see the AST for vulkan tests.
This also required reworking some deeper parts of type creation, regarding
when storage qualification and constness is deduced bottom-up or dictated
top-down.
This commit is contained in:
John Kessenich 2016-05-23 16:07:07 -06:00
parent 87a94fc0fa
commit d82c906378
16 changed files with 610 additions and 245 deletions

View file

@ -922,6 +922,7 @@ TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* true
TIntermConstantUnion* TIntermediate::addConstantUnion(const TConstUnionArray& unionArray, const TType& t, const TSourceLoc& loc, bool literal) const
{
TIntermConstantUnion* node = new TIntermConstantUnion(unionArray, t);
node->getQualifier().storage = EvqConst;
node->setLoc(loc);
if (literal)
node->setLiteral();
@ -1165,20 +1166,44 @@ void TIntermediate::removeTree()
//
// "5.x Specialization Constant Operations"
//
// ...
// Only some operations discussed in this section may be applied to a
// specialization constant and still yield a result that is as
// specialization constant. The operations allowed are listed below.
// When a specialization constant is operated on with one of these
// operators and with another constant or specialization constant, the
// result is implicitly a specialization constant.
//
// It also needs to allow basic construction, swizzling, and indexing
// operations.
// - int(), uint(), and bool() constructors for type conversions
// from any of the following types to any of the following types:
// * int
// * uint
// * bool
// - vector versions of the above conversion constructors
// - allowed implicit conversions of the above
// - swizzles (e.g., foo.yx)
// - The following when applied to integer or unsigned integer types:
// * unary negative ( - )
// * binary operations ( + , - , * , / , % )
// * shift ( <<, >> )
// * bitwise operations ( & , | , ^ )
// - The following when applied to integer or unsigned integer scalar types:
// * comparison ( == , != , > , >= , < , <= )
// - The following when applied to the Boolean scalar type:
// * not ( ! )
// * logical operations ( && , || , ^^ )
// * comparison ( == , != )"
//
// This function just handles binary and unary nodes. Construction
// rules are handled in construction paths that are not covered by the unary
// and binary paths, while required conversions will still show up here
// as unary converters in the from a construction operator.
//
bool TIntermediate::isSpecializationOperation(const TIntermOperator& node) const
{
// allow construction
if (node.isConstructor())
return true;
// The set for floating point is quite limited
if (node.getBasicType() == EbtFloat ||
node.getBasicType() == EbtDouble) {
// The operations resulting in floating point are quite limited
// (However, some floating-point operations result in bool, like ">",
// so are handled later.)
if (node.getType().isFloatingDomain()) {
switch (node.getOp()) {
case EOpIndexDirect:
case EOpIndexIndirect:
@ -1190,7 +1215,14 @@ bool TIntermediate::isSpecializationOperation(const TIntermOperator& node) const
}
}
// Floating-point is out of the way.
// Check for floating-point arguments
if (const TIntermBinary* bin = node.getAsBinaryNode())
if (bin->getLeft() ->getType().isFloatingDomain() ||
bin->getRight()->getType().isFloatingDomain())
return false;
// So, for now, we can assume everything left is non-floating-point...
// Now check for integer/bool-based operations
switch (node.getOp()) {