Non-functional: Fix some comments English and brace formatting in recent merges.
This commit is contained in:
@@ -1891,8 +1891,7 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
|
|||||||
addMemberDecoration(spvType, member, TranslateLayoutDecoration(glslangType, subQualifier.layoutMatrix));
|
addMemberDecoration(spvType, member, TranslateLayoutDecoration(glslangType, subQualifier.layoutMatrix));
|
||||||
addMemberDecoration(spvType, member, TranslatePrecisionDecoration(glslangType));
|
addMemberDecoration(spvType, member, TranslatePrecisionDecoration(glslangType));
|
||||||
// Add interpolation decorations only to top-level members of Input and Output storage classes
|
// Add interpolation decorations only to top-level members of Input and Output storage classes
|
||||||
if (type.getQualifier().storage == glslang::EvqVaryingIn || type.getQualifier().storage == glslang::EvqVaryingOut)
|
if (type.getQualifier().storage == glslang::EvqVaryingIn || type.getQualifier().storage == glslang::EvqVaryingOut) {
|
||||||
{
|
|
||||||
addMemberDecoration(spvType, member, TranslateInterpolationDecoration(subQualifier));
|
addMemberDecoration(spvType, member, TranslateInterpolationDecoration(subQualifier));
|
||||||
}
|
}
|
||||||
addMemberDecoration(spvType, member, TranslateInvariantDecoration(subQualifier));
|
addMemberDecoration(spvType, member, TranslateInvariantDecoration(subQualifier));
|
||||||
@@ -1909,14 +1908,11 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
|
|||||||
// probably move to the linker stage of the front end proper, and just have the
|
// probably move to the linker stage of the front end proper, and just have the
|
||||||
// answer sitting already distributed throughout the individual member locations.
|
// answer sitting already distributed throughout the individual member locations.
|
||||||
int location = -1; // will only decorate if present or inherited
|
int location = -1; // will only decorate if present or inherited
|
||||||
if (subQualifier.hasLocation()) // no inheritance, or override of inheritance
|
if (subQualifier.hasLocation()) { // no inheritance, or override of inheritance
|
||||||
{
|
|
||||||
// struct members should not have explicit locations
|
// struct members should not have explicit locations
|
||||||
assert(type.getBasicType() != glslang::EbtStruct);
|
assert(type.getBasicType() != glslang::EbtStruct);
|
||||||
location = subQualifier.layoutLocation;
|
location = subQualifier.layoutLocation;
|
||||||
}
|
} else if (type.getBasicType() != glslang::EbtBlock) {
|
||||||
else if (type.getBasicType() != glslang::EbtBlock)
|
|
||||||
{
|
|
||||||
// If it is a not a Block, (...) Its members are assigned consecutive locations (...)
|
// If it is a not a Block, (...) Its members are assigned consecutive locations (...)
|
||||||
// The members, and their nested types, must not themselves have Location decorations.
|
// The members, and their nested types, must not themselves have Location decorations.
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@
|
|||||||
|
|
||||||
//
|
//
|
||||||
// Visit the nodes in the glslang intermediate tree representation to
|
// Visit the nodes in the glslang intermediate tree representation to
|
||||||
// propagate 'noContraction' qualifier.
|
// propagate the 'noContraction' qualifier.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "propagateNoContraction.h"
|
#include "propagateNoContraction.h"
|
||||||
@@ -48,16 +48,16 @@
|
|||||||
#include "localintermediate.h"
|
#include "localintermediate.h"
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
// Use string to hold the accesschain information, as in most cases the
|
// Use a string to hold the access chain information, as in most cases the
|
||||||
// accesschain is short and may contain only one element, which is the symbol
|
// access chain is short and may contain only one element, which is the symbol
|
||||||
// ID.
|
// ID.
|
||||||
// Example: struct {float a; float b;} s;
|
// Example: struct {float a; float b;} s;
|
||||||
// Object s.a will be represented with: <symbol ID of s>/0
|
// Object s.a will be represented with: <symbol ID of s>/0
|
||||||
// Object s.b will be represented with: <symbol ID of s>/1
|
// Object s.b will be represented with: <symbol ID of s>/1
|
||||||
// Object s will be representend with: <symbol ID of s>
|
// Object s will be represented with: <symbol ID of s>
|
||||||
// For members of vector, matrix and arrays, they will be represented with the
|
// For members of vector, matrix and arrays, they will be represented with the
|
||||||
// same symbol ID of their container symbol objects. This is because their
|
// same symbol ID of their container symbol objects. This is because their
|
||||||
// precise'ness is always the same as their container symbol objects.
|
// preciseness is always the same as their container symbol objects.
|
||||||
typedef std::string ObjectAccessChain;
|
typedef std::string ObjectAccessChain;
|
||||||
|
|
||||||
// The delimiter used in the ObjectAccessChain string to separate symbol ID and
|
// The delimiter used in the ObjectAccessChain string to separate symbol ID and
|
||||||
@@ -67,7 +67,7 @@ const char ObjectAccesschainDelimiter = '/';
|
|||||||
// Mapping from Symbol IDs of symbol nodes, to their defining operation
|
// Mapping from Symbol IDs of symbol nodes, to their defining operation
|
||||||
// nodes.
|
// nodes.
|
||||||
typedef std::unordered_multimap<ObjectAccessChain, glslang::TIntermOperator*> NodeMapping;
|
typedef std::unordered_multimap<ObjectAccessChain, glslang::TIntermOperator*> NodeMapping;
|
||||||
// Mapping from object nodes to their accesschain info string.
|
// Mapping from object nodes to their access chain info string.
|
||||||
typedef std::unordered_map<glslang::TIntermTyped*, ObjectAccessChain> AccessChainMapping;
|
typedef std::unordered_map<glslang::TIntermTyped*, ObjectAccessChain> AccessChainMapping;
|
||||||
|
|
||||||
// Set of object IDs.
|
// Set of object IDs.
|
||||||
@@ -127,7 +127,7 @@ bool isAssignOperation(glslang::TOperator op)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// A helper function to get the unsigned int from a given constant union node.
|
// A helper function to get the unsigned int from a given constant union node.
|
||||||
// Note the node should only holds a uint scalar.
|
// Note the node should only hold a uint scalar.
|
||||||
unsigned getStructIndexFromConstantUnion(glslang::TIntermTyped* node)
|
unsigned getStructIndexFromConstantUnion(glslang::TIntermTyped* node)
|
||||||
{
|
{
|
||||||
assert(node->getAsConstantUnion() && node->getAsConstantUnion()->isScalar());
|
assert(node->getAsConstantUnion() && node->getAsConstantUnion()->isScalar());
|
||||||
@@ -144,7 +144,7 @@ ObjectAccessChain generateSymbolLabel(glslang::TIntermSymbol* node)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if the operation is an arithmetic operation and valid for
|
// Returns true if the operation is an arithmetic operation and valid for
|
||||||
// 'NoContraction' decoration.
|
// the 'NoContraction' decoration.
|
||||||
bool isArithmeticOperation(glslang::TOperator op)
|
bool isArithmeticOperation(glslang::TOperator op)
|
||||||
{
|
{
|
||||||
switch (op) {
|
switch (op) {
|
||||||
@@ -184,7 +184,7 @@ bool isArithmeticOperation(glslang::TOperator op)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// A helper class to help managing populating_initial_no_contraction_ flag.
|
// A helper class to help manage the populating_initial_no_contraction_ flag.
|
||||||
template <typename T> class StateSettingGuard {
|
template <typename T> class StateSettingGuard {
|
||||||
public:
|
public:
|
||||||
StateSettingGuard(T* state_ptr, T new_state_value)
|
StateSettingGuard(T* state_ptr, T new_state_value)
|
||||||
@@ -208,14 +208,14 @@ ObjectAccessChain getFrontElement(const ObjectAccessChain& chain)
|
|||||||
return pos_delimiter == std::string::npos ? chain : chain.substr(0, pos_delimiter);
|
return pos_delimiter == std::string::npos ? chain : chain.substr(0, pos_delimiter);
|
||||||
}
|
}
|
||||||
|
|
||||||
// A helper function to get the accesschain starting from the second element.
|
// A helper function to get the access chain starting from the second element.
|
||||||
ObjectAccessChain subAccessChainFromSecondElement(const ObjectAccessChain& chain)
|
ObjectAccessChain subAccessChainFromSecondElement(const ObjectAccessChain& chain)
|
||||||
{
|
{
|
||||||
size_t pos_delimiter = chain.find(ObjectAccesschainDelimiter);
|
size_t pos_delimiter = chain.find(ObjectAccesschainDelimiter);
|
||||||
return pos_delimiter == std::string::npos ? "" : chain.substr(pos_delimiter + 1);
|
return pos_delimiter == std::string::npos ? "" : chain.substr(pos_delimiter + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// A helper function to get the accesschain after removing a given prefix.
|
// A helper function to get the access chain after removing a given prefix.
|
||||||
ObjectAccessChain getSubAccessChainAfterPrefix(const ObjectAccessChain& chain,
|
ObjectAccessChain getSubAccessChainAfterPrefix(const ObjectAccessChain& chain,
|
||||||
const ObjectAccessChain& prefix)
|
const ObjectAccessChain& prefix)
|
||||||
{
|
{
|
||||||
@@ -228,7 +228,7 @@ ObjectAccessChain getSubAccessChainAfterPrefix(const ObjectAccessChain& chain,
|
|||||||
//
|
//
|
||||||
// A traverser which traverses the whole AST and populates:
|
// A traverser which traverses the whole AST and populates:
|
||||||
// 1) A mapping from symbol nodes' IDs to their defining operation nodes.
|
// 1) A mapping from symbol nodes' IDs to their defining operation nodes.
|
||||||
// 2) A set of accesschains of the initial precise object nodes.
|
// 2) A set of access chains of the initial precise object nodes.
|
||||||
//
|
//
|
||||||
class TSymbolDefinitionCollectingTraverser : public glslang::TIntermTraverser {
|
class TSymbolDefinitionCollectingTraverser : public glslang::TIntermTraverser {
|
||||||
public:
|
public:
|
||||||
@@ -255,12 +255,12 @@ protected:
|
|||||||
// A temporary cache of the symbol node whose defining node is to be found
|
// A temporary cache of the symbol node whose defining node is to be found
|
||||||
// currently along traversing the AST.
|
// currently along traversing the AST.
|
||||||
ObjectAccessChain current_object_;
|
ObjectAccessChain current_object_;
|
||||||
// A map from object node to its accesschain. This traverser stores
|
// A map from object node to its access chain. This traverser stores
|
||||||
// the built accesschains into this map for each object node it has
|
// the built access chains into this map for each object node it has
|
||||||
// visited.
|
// visited.
|
||||||
AccessChainMapping& accesschain_mapping_;
|
AccessChainMapping& accesschain_mapping_;
|
||||||
// The pointer to the Function Definition node, so we can get the
|
// The pointer to the Function Definition node, so we can get the
|
||||||
// precise'ness of the return expression from it when we traverse the
|
// preciseness of the return expression from it when we traverse the
|
||||||
// return branch node.
|
// return branch node.
|
||||||
glslang::TIntermAggregate* current_function_definition_node_;
|
glslang::TIntermAggregate* current_function_definition_node_;
|
||||||
};
|
};
|
||||||
@@ -288,14 +288,14 @@ void TSymbolDefinitionCollectingTraverser::visitSymbol(glslang::TIntermSymbol* n
|
|||||||
bool TSymbolDefinitionCollectingTraverser::visitAggregate(glslang::TVisit,
|
bool TSymbolDefinitionCollectingTraverser::visitAggregate(glslang::TVisit,
|
||||||
glslang::TIntermAggregate* node)
|
glslang::TIntermAggregate* node)
|
||||||
{
|
{
|
||||||
// This aggreagate node might be a function definition node, in which case we need to
|
// This aggregate node might be a function definition node, in which case we need to
|
||||||
// cache this node, so we can get the precise'ness information of the return value
|
// cache this node, so we can get the preciseness information of the return value
|
||||||
// of this function later.
|
// of this function later.
|
||||||
StateSettingGuard<glslang::TIntermAggregate*> current_function_definition_node_setting_guard(
|
StateSettingGuard<glslang::TIntermAggregate*> current_function_definition_node_setting_guard(
|
||||||
¤t_function_definition_node_);
|
¤t_function_definition_node_);
|
||||||
if (node->getOp() == glslang::EOpFunction) {
|
if (node->getOp() == glslang::EOpFunction) {
|
||||||
// This is function definition node, we need to cache this node so that we can
|
// This is function definition node, we need to cache this node so that we can
|
||||||
// get the precise'ness of the return value later.
|
// get the preciseness of the return value later.
|
||||||
current_function_definition_node_setting_guard.setState(node);
|
current_function_definition_node_setting_guard.setState(node);
|
||||||
}
|
}
|
||||||
// Traverse the items in the sequence.
|
// Traverse the items in the sequence.
|
||||||
@@ -313,7 +313,7 @@ bool TSymbolDefinitionCollectingTraverser::visitBranch(glslang::TVisit,
|
|||||||
if (node->getFlowOp() == glslang::EOpReturn && node->getExpression() &&
|
if (node->getFlowOp() == glslang::EOpReturn && node->getExpression() &&
|
||||||
current_function_definition_node_ &&
|
current_function_definition_node_ &&
|
||||||
current_function_definition_node_->getType().getQualifier().noContraction) {
|
current_function_definition_node_->getType().getQualifier().noContraction) {
|
||||||
// This node is a return node with expression, and its function has
|
// This node is a return node with an expression, and its function has a
|
||||||
// precise return value. We need to find the involved objects in its
|
// precise return value. We need to find the involved objects in its
|
||||||
// expression and add them to the set of initial precise objects.
|
// expression and add them to the set of initial precise objects.
|
||||||
precise_return_nodes_.insert(node);
|
precise_return_nodes_.insert(node);
|
||||||
@@ -322,71 +322,71 @@ bool TSymbolDefinitionCollectingTraverser::visitBranch(glslang::TVisit,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Visits an unary node. This might be an implicit assignment like i++, i--. etc.
|
// Visits a unary node. This might be an implicit assignment like i++, i--. etc.
|
||||||
bool TSymbolDefinitionCollectingTraverser::visitUnary(glslang::TVisit /* visit */,
|
bool TSymbolDefinitionCollectingTraverser::visitUnary(glslang::TVisit /* visit */,
|
||||||
glslang::TIntermUnary* node)
|
glslang::TIntermUnary* node)
|
||||||
{
|
{
|
||||||
current_object_.clear();
|
current_object_.clear();
|
||||||
node->getOperand()->traverse(this);
|
node->getOperand()->traverse(this);
|
||||||
if (isAssignOperation(node->getOp())) {
|
if (isAssignOperation(node->getOp())) {
|
||||||
// We should always be able to get an accesschain of the operand node.
|
// We should always be able to get an access chain of the operand node.
|
||||||
assert(!current_object_.empty());
|
assert(!current_object_.empty());
|
||||||
|
|
||||||
// If the operand node object is 'precise', we collect its accesschain
|
// If the operand node object is 'precise', we collect its access chain
|
||||||
// for the initial set of 'precise' objects.
|
// for the initial set of 'precise' objects.
|
||||||
if (isPreciseObjectNode(node->getOperand())) {
|
if (isPreciseObjectNode(node->getOperand())) {
|
||||||
// The operand node is an 'precise' object node, add its
|
// The operand node is an 'precise' object node, add its
|
||||||
// accesschain to the set of 'precise' objects. This is to collect
|
// access chain to the set of 'precise' objects. This is to collect
|
||||||
// the initial set of 'precise' objects.
|
// the initial set of 'precise' objects.
|
||||||
precise_objects_.insert(current_object_);
|
precise_objects_.insert(current_object_);
|
||||||
}
|
}
|
||||||
// Gets the symbol ID from the object's accesschain.
|
// Gets the symbol ID from the object's access chain.
|
||||||
ObjectAccessChain id_symbol = getFrontElement(current_object_);
|
ObjectAccessChain id_symbol = getFrontElement(current_object_);
|
||||||
// Add a mapping from the symbol ID to this assignment operation node.
|
// Add a mapping from the symbol ID to this assignment operation node.
|
||||||
symbol_definition_mapping_.insert(std::make_pair(id_symbol, node));
|
symbol_definition_mapping_.insert(std::make_pair(id_symbol, node));
|
||||||
}
|
}
|
||||||
// Unary node is not a dereference node, so we clear the accesschain which
|
// A unary node is not a dereference node, so we clear the access chain which
|
||||||
// is under construction.
|
// is under construction.
|
||||||
current_object_.clear();
|
current_object_.clear();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Visits a binary node and updates the mapping from symbol IDs to the definition
|
// Visits a binary node and updates the mapping from symbol IDs to the definition
|
||||||
// nodes. Also collects the accesschains for the initial precise objects.
|
// nodes. Also collects the access chains for the initial precise objects.
|
||||||
bool TSymbolDefinitionCollectingTraverser::visitBinary(glslang::TVisit /* visit */,
|
bool TSymbolDefinitionCollectingTraverser::visitBinary(glslang::TVisit /* visit */,
|
||||||
glslang::TIntermBinary* node)
|
glslang::TIntermBinary* node)
|
||||||
{
|
{
|
||||||
// Traverses the left node to build the accesschain info for the object.
|
// Traverses the left node to build the access chain info for the object.
|
||||||
current_object_.clear();
|
current_object_.clear();
|
||||||
node->getLeft()->traverse(this);
|
node->getLeft()->traverse(this);
|
||||||
|
|
||||||
if (isAssignOperation(node->getOp())) {
|
if (isAssignOperation(node->getOp())) {
|
||||||
// We should always be able to get an accesschain for the left node.
|
// We should always be able to get an access chain for the left node.
|
||||||
assert(!current_object_.empty());
|
assert(!current_object_.empty());
|
||||||
|
|
||||||
// If the left node object is 'precise', it is an initial precise object
|
// If the left node object is 'precise', it is an initial precise object
|
||||||
// specified in the shader source. Adds it to the initial worklist to
|
// specified in the shader source. Adds it to the initial work list to
|
||||||
// process later.
|
// process later.
|
||||||
if (isPreciseObjectNode(node->getLeft())) {
|
if (isPreciseObjectNode(node->getLeft())) {
|
||||||
// The left node is an 'precise' object node, add its accesschain to
|
// The left node is an 'precise' object node, add its access chain to
|
||||||
// the set of 'precise' objects. This is to collect the initial set
|
// the set of 'precise' objects. This is to collect the initial set
|
||||||
// of 'precise' objects.
|
// of 'precise' objects.
|
||||||
precise_objects_.insert(current_object_);
|
precise_objects_.insert(current_object_);
|
||||||
}
|
}
|
||||||
// Gets the symbol ID from the object accesschain, which should be the
|
// Gets the symbol ID from the object access chain, which should be the
|
||||||
// first element recorded in the accesschain.
|
// first element recorded in the access chain.
|
||||||
ObjectAccessChain id_symbol = getFrontElement(current_object_);
|
ObjectAccessChain id_symbol = getFrontElement(current_object_);
|
||||||
// Adds a mapping from the symbol ID to this assignment operation node.
|
// Adds a mapping from the symbol ID to this assignment operation node.
|
||||||
symbol_definition_mapping_.insert(std::make_pair(id_symbol, node));
|
symbol_definition_mapping_.insert(std::make_pair(id_symbol, node));
|
||||||
|
|
||||||
// Traverses the right node, there may be other 'assignment'
|
// Traverses the right node, there may be other 'assignment'
|
||||||
// operatrions in the right.
|
// operations in the right.
|
||||||
current_object_.clear();
|
current_object_.clear();
|
||||||
node->getRight()->traverse(this);
|
node->getRight()->traverse(this);
|
||||||
|
|
||||||
} else if (isDereferenceOperation(node->getOp())) {
|
} else if (isDereferenceOperation(node->getOp())) {
|
||||||
// The left node (parent node) is a struct type object. We need to
|
// The left node (parent node) is a struct type object. We need to
|
||||||
// record the accesschain information of the current node into its
|
// record the access chain information of the current node into its
|
||||||
// object id.
|
// object id.
|
||||||
if (node->getOp() == glslang::EOpIndexDirectStruct) {
|
if (node->getOp() == glslang::EOpIndexDirectStruct) {
|
||||||
unsigned struct_dereference_index = getStructIndexFromConstantUnion(node->getRight());
|
unsigned struct_dereference_index = getStructIndexFromConstantUnion(node->getRight());
|
||||||
@@ -395,7 +395,7 @@ bool TSymbolDefinitionCollectingTraverser::visitBinary(glslang::TVisit /* visit
|
|||||||
}
|
}
|
||||||
accesschain_mapping_[node] = current_object_;
|
accesschain_mapping_[node] = current_object_;
|
||||||
|
|
||||||
// For dereference node, there is no need to traverse the right child
|
// For a dereference node, there is no need to traverse the right child
|
||||||
// node as the right node should always be an integer type object.
|
// node as the right node should always be an integer type object.
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@@ -408,8 +408,8 @@ bool TSymbolDefinitionCollectingTraverser::visitBinary(glslang::TVisit /* visit
|
|||||||
|
|
||||||
// Traverses the AST and returns a tuple of four members:
|
// Traverses the AST and returns a tuple of four members:
|
||||||
// 1) a mapping from symbol IDs to the definition nodes (aka. assignment nodes) of these symbols.
|
// 1) a mapping from symbol IDs to the definition nodes (aka. assignment nodes) of these symbols.
|
||||||
// 2) a mapping from object nodes in the AST to the accesschains of these objects.
|
// 2) a mapping from object nodes in the AST to the access chains of these objects.
|
||||||
// 3) a set of accesschains of precise objects.
|
// 3) a set of access chains of precise objects.
|
||||||
// 4) a set of return nodes with precise expressions.
|
// 4) a set of return nodes with precise expressions.
|
||||||
std::tuple<NodeMapping, AccessChainMapping, ObjectAccesschainSet, ReturnBranchNodeSet>
|
std::tuple<NodeMapping, AccessChainMapping, ObjectAccesschainSet, ReturnBranchNodeSet>
|
||||||
getSymbolToDefinitionMappingAndPreciseSymbolIDs(const glslang::TIntermediate& intermediate)
|
getSymbolToDefinitionMappingAndPreciseSymbolIDs(const glslang::TIntermediate& intermediate)
|
||||||
@@ -437,15 +437,15 @@ getSymbolToDefinitionMappingAndPreciseSymbolIDs(const glslang::TIntermediate& in
|
|||||||
//
|
//
|
||||||
// A traverser that determine whether the left node (or operand node for unary
|
// A traverser that determine whether the left node (or operand node for unary
|
||||||
// node) of an assignment node is 'precise', containing 'precise' or not,
|
// node) of an assignment node is 'precise', containing 'precise' or not,
|
||||||
// according to the accesschain a given precise object which share the same
|
// according to the access chain a given precise object which share the same
|
||||||
// symbol as the left node.
|
// symbol as the left node.
|
||||||
//
|
//
|
||||||
// Post-orderly traverses the left node subtree of an binary assignment node and:
|
// Post-orderly traverses the left node subtree of an binary assignment node and:
|
||||||
//
|
//
|
||||||
// 1) Propagates the 'precise' from the left object nodes to this object node.
|
// 1) Propagates the 'precise' from the left object nodes to this object node.
|
||||||
//
|
//
|
||||||
// 2) Builds object accesschain along the traversal, and also compares with
|
// 2) Builds object access chain along the traversal, and also compares with
|
||||||
// the accesschain of the given 'precise' object along with the traversal to
|
// the access chain of the given 'precise' object along with the traversal to
|
||||||
// tell if the node to be defined is 'precise' or not.
|
// tell if the node to be defined is 'precise' or not.
|
||||||
//
|
//
|
||||||
class TNoContractionAssigneeCheckingTraverser : public glslang::TIntermTraverser {
|
class TNoContractionAssigneeCheckingTraverser : public glslang::TIntermTraverser {
|
||||||
@@ -464,18 +464,18 @@ public:
|
|||||||
: TIntermTraverser(true, false, false), accesschain_mapping_(accesschain_mapping),
|
: TIntermTraverser(true, false, false), accesschain_mapping_(accesschain_mapping),
|
||||||
precise_object_(nullptr) {}
|
precise_object_(nullptr) {}
|
||||||
|
|
||||||
// Checks the precise'ness of a given assignment node with a precise object
|
// Checks the preciseness of a given assignment node with a precise object
|
||||||
// represented as accesschain. The precise object shares the same symbol
|
// represented as access chain. The precise object shares the same symbol
|
||||||
// with the assignee of the given assignment node. Return a tuple of two:
|
// with the assignee of the given assignment node. Return a tuple of two:
|
||||||
//
|
//
|
||||||
// 1) The precise'ness of the assignee node of this assignment node. True
|
// 1) The preciseness of the assignee node of this assignment node. True
|
||||||
// if the assignee contains 'precise' objects or is 'precise', false if
|
// if the assignee contains 'precise' objects or is 'precise', false if
|
||||||
// the assignee is not 'precise' according to the accesschain of the given
|
// the assignee is not 'precise' according to the access chain of the given
|
||||||
// precise object.
|
// precise object.
|
||||||
//
|
//
|
||||||
// 2) The incremental accesschain from the assignee node to its nested
|
// 2) The incremental access chain from the assignee node to its nested
|
||||||
// 'precise' object, according to the accesschain of the given precise
|
// 'precise' object, according to the access chain of the given precise
|
||||||
// object. This incremental accesschain can be empty, which means the
|
// object. This incremental access chain can be empty, which means the
|
||||||
// assignee is 'precise'. Otherwise it shows the path to the nested
|
// assignee is 'precise'. Otherwise it shows the path to the nested
|
||||||
// precise object.
|
// precise object.
|
||||||
std::tuple<bool, ObjectAccessChain>
|
std::tuple<bool, ObjectAccessChain>
|
||||||
@@ -487,7 +487,7 @@ public:
|
|||||||
ObjectAccessChain assignee_object;
|
ObjectAccessChain assignee_object;
|
||||||
if (glslang::TIntermBinary* BN = node->getAsBinaryNode()) {
|
if (glslang::TIntermBinary* BN = node->getAsBinaryNode()) {
|
||||||
// This is a binary assignment node, we need to check the
|
// This is a binary assignment node, we need to check the
|
||||||
// precise'ness of the left node.
|
// preciseness of the left node.
|
||||||
assert(accesschain_mapping_.count(BN->getLeft()));
|
assert(accesschain_mapping_.count(BN->getLeft()));
|
||||||
// The left node (assignee node) is an object node, traverse the
|
// The left node (assignee node) is an object node, traverse the
|
||||||
// node to let the 'precise' of nesting objects being transfered to
|
// node to let the 'precise' of nesting objects being transfered to
|
||||||
@@ -498,14 +498,14 @@ public:
|
|||||||
if (isPreciseObjectNode(BN->getLeft())) {
|
if (isPreciseObjectNode(BN->getLeft())) {
|
||||||
return make_tuple(true, ObjectAccessChain());
|
return make_tuple(true, ObjectAccessChain());
|
||||||
}
|
}
|
||||||
// If the precise'ness of the left node (assignee node) can not
|
// If the preciseness of the left node (assignee node) can not
|
||||||
// be determined by now, we need to compare the accesschain string
|
// be determined by now, we need to compare the access chain string
|
||||||
// of the assignee object with the given precise object.
|
// of the assignee object with the given precise object.
|
||||||
assignee_object = accesschain_mapping_.at(BN->getLeft());
|
assignee_object = accesschain_mapping_.at(BN->getLeft());
|
||||||
|
|
||||||
} else if (glslang::TIntermUnary* UN = node->getAsUnaryNode()) {
|
} else if (glslang::TIntermUnary* UN = node->getAsUnaryNode()) {
|
||||||
// This is a unary assignment node, we need to check the
|
// This is a unary assignment node, we need to check the
|
||||||
// precise'ness of the operand node. For unary assignment node, the
|
// preciseness of the operand node. For unary assignment node, the
|
||||||
// operand node should always be an object node.
|
// operand node should always be an object node.
|
||||||
assert(accesschain_mapping_.count(UN->getOperand()));
|
assert(accesschain_mapping_.count(UN->getOperand()));
|
||||||
// Traverse the operand node to let the 'precise' being propagated
|
// Traverse the operand node to let the 'precise' being propagated
|
||||||
@@ -516,8 +516,8 @@ public:
|
|||||||
if (isPreciseObjectNode(UN->getOperand())) {
|
if (isPreciseObjectNode(UN->getOperand())) {
|
||||||
return make_tuple(true, ObjectAccessChain());
|
return make_tuple(true, ObjectAccessChain());
|
||||||
}
|
}
|
||||||
// If the precise'ness of the operand node (assignee node) can not
|
// If the preciseness of the operand node (assignee node) can not
|
||||||
// be determined by now, we need to compare the accesschain string
|
// be determined by now, we need to compare the access chain string
|
||||||
// of the assignee object with the given precise object.
|
// of the assignee object with the given precise object.
|
||||||
assignee_object = accesschain_mapping_.at(UN->getOperand());
|
assignee_object = accesschain_mapping_.at(UN->getOperand());
|
||||||
} else {
|
} else {
|
||||||
@@ -525,23 +525,23 @@ public:
|
|||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compare the accesschain string of the assignee node with the given
|
// Compare the access chain string of the assignee node with the given
|
||||||
// precise object to determine if this assignment should propagate
|
// precise object to determine if this assignment should propagate
|
||||||
// 'precise'.
|
// 'precise'.
|
||||||
if (assignee_object.find(precise_object) == 0) {
|
if (assignee_object.find(precise_object) == 0) {
|
||||||
// The accesschain string of the given precise object is a prefix
|
// The access chain string of the given precise object is a prefix
|
||||||
// of assignee's accesschain string. The assignee should be
|
// of assignee's access chain string. The assignee should be
|
||||||
// 'precise'.
|
// 'precise'.
|
||||||
return make_tuple(true, ObjectAccessChain());
|
return make_tuple(true, ObjectAccessChain());
|
||||||
} else if (precise_object.find(assignee_object) == 0) {
|
} else if (precise_object.find(assignee_object) == 0) {
|
||||||
// The assignee's accesschain string is a prefix of the given
|
// The assignee's access chain string is a prefix of the given
|
||||||
// precise object, the assignee object contains 'precise' object,
|
// precise object, the assignee object contains 'precise' object,
|
||||||
// and we need to pass the remained accesschain to the object nodes
|
// and we need to pass the remained access chain to the object nodes
|
||||||
// in the right.
|
// in the right.
|
||||||
return make_tuple(true, getSubAccessChainAfterPrefix(precise_object, assignee_object));
|
return make_tuple(true, getSubAccessChainAfterPrefix(precise_object, assignee_object));
|
||||||
} else {
|
} else {
|
||||||
// The accesschain strings do not match, the assignee object can
|
// The access chain strings do not match, the assignee object can
|
||||||
// not be labelled as 'precise' according to the given precise
|
// not be labeled as 'precise' according to the given precise
|
||||||
// object.
|
// object.
|
||||||
return make_tuple(false, ObjectAccessChain());
|
return make_tuple(false, ObjectAccessChain());
|
||||||
}
|
}
|
||||||
@@ -551,9 +551,9 @@ protected:
|
|||||||
bool visitBinary(glslang::TVisit, glslang::TIntermBinary* node) override;
|
bool visitBinary(glslang::TVisit, glslang::TIntermBinary* node) override;
|
||||||
void visitSymbol(glslang::TIntermSymbol* node) override;
|
void visitSymbol(glslang::TIntermSymbol* node) override;
|
||||||
|
|
||||||
// A map from object nodes to their accesschain string (used as object ID).
|
// A map from object nodes to their access chain string (used as object ID).
|
||||||
const AccessChainMapping& accesschain_mapping_;
|
const AccessChainMapping& accesschain_mapping_;
|
||||||
// A given precise object, represented in it accesschain string. This
|
// A given precise object, represented in it access chain string. This
|
||||||
// precise object is used to be compared with the assignee node to tell if
|
// precise object is used to be compared with the assignee node to tell if
|
||||||
// the assignee node is 'precise', contains 'precise' object or not
|
// the assignee node is 'precise', contains 'precise' object or not
|
||||||
// 'precise'.
|
// 'precise'.
|
||||||
@@ -576,7 +576,7 @@ bool TNoContractionAssigneeCheckingTraverser::visitBinary(glslang::TVisit,
|
|||||||
assert(isDereferenceOperation(node->getOp()));
|
assert(isDereferenceOperation(node->getOp()));
|
||||||
// If the left node is 'precise', this node should also be precise,
|
// If the left node is 'precise', this node should also be precise,
|
||||||
// otherwise, compare with the given precise_object_. If the
|
// otherwise, compare with the given precise_object_. If the
|
||||||
// accesschain of this node matches with the given precise_object_,
|
// access chain of this node matches with the given precise_object_,
|
||||||
// this node should be marked as 'precise'.
|
// this node should be marked as 'precise'.
|
||||||
if (isPreciseObjectNode(node->getLeft())) {
|
if (isPreciseObjectNode(node->getLeft())) {
|
||||||
node->getWritableType().getQualifier().noContraction = true;
|
node->getWritableType().getQualifier().noContraction = true;
|
||||||
@@ -587,12 +587,12 @@ bool TNoContractionAssigneeCheckingTraverser::visitBinary(glslang::TVisit,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Visits a symbol node, if the symbol node ID (its accesschain string) matches
|
// Visits a symbol node, if the symbol node ID (its access chain string) matches
|
||||||
// with the given precise object, this node should be 'precise'.
|
// with the given precise object, this node should be 'precise'.
|
||||||
void TNoContractionAssigneeCheckingTraverser::visitSymbol(glslang::TIntermSymbol* node)
|
void TNoContractionAssigneeCheckingTraverser::visitSymbol(glslang::TIntermSymbol* node)
|
||||||
{
|
{
|
||||||
// A symbol node should always be an object node, and should have been added
|
// A symbol node should always be an object node, and should have been added
|
||||||
// to the map from object nodes to their accesschain strings.
|
// to the map from object nodes to their access chain strings.
|
||||||
assert(accesschain_mapping_.count(node));
|
assert(accesschain_mapping_.count(node));
|
||||||
if (accesschain_mapping_.at(node) == *precise_object_) {
|
if (accesschain_mapping_.at(node) == *precise_object_) {
|
||||||
node->getWritableType().getQualifier().noContraction = true;
|
node->getWritableType().getQualifier().noContraction = true;
|
||||||
@@ -603,10 +603,10 @@ void TNoContractionAssigneeCheckingTraverser::visitSymbol(glslang::TIntermSymbol
|
|||||||
// A traverser that only traverses the right side of binary assignment nodes
|
// A traverser that only traverses the right side of binary assignment nodes
|
||||||
// and the operand node of unary assignment nodes.
|
// and the operand node of unary assignment nodes.
|
||||||
//
|
//
|
||||||
// 1) Marks arithmetic operations 'NoContraction'.
|
// 1) Marks arithmetic operations as 'NoContraction'.
|
||||||
//
|
//
|
||||||
// 2) Find the object which should be marked as 'precise' in the right and
|
// 2) Find the object which should be marked as 'precise' in the right and
|
||||||
// update the 'precise' object worklist.
|
// update the 'precise' object work list.
|
||||||
//
|
//
|
||||||
class TNoContractionPropagator : public glslang::TIntermTraverser {
|
class TNoContractionPropagator : public glslang::TIntermTraverser {
|
||||||
public:
|
public:
|
||||||
@@ -617,7 +617,7 @@ public:
|
|||||||
added_precise_object_ids_() {}
|
added_precise_object_ids_() {}
|
||||||
|
|
||||||
// Propagates 'precise' in the right nodes of a given assignment node with
|
// Propagates 'precise' in the right nodes of a given assignment node with
|
||||||
// accesschain record from the assignee node to a 'precise' object it
|
// access chain record from the assignee node to a 'precise' object it
|
||||||
// contains.
|
// contains.
|
||||||
void
|
void
|
||||||
propagateNoContractionInOneExpression(glslang::TIntermTyped* defining_node,
|
propagateNoContractionInOneExpression(glslang::TIntermTyped* defining_node,
|
||||||
@@ -650,26 +650,26 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
// Visits an aggregate node. The node can be a initializer list, in which
|
// Visits an aggregate node. The node can be a initializer list, in which
|
||||||
// case we need to find the 'precise' or 'precise' containing object node
|
// case we need to find the 'precise' or 'precise' containing object node
|
||||||
// with the accesschain record. In other cases, just need to traverse all
|
// with the access chain record. In other cases, just need to traverse all
|
||||||
// the children nodes.
|
// the children nodes.
|
||||||
bool visitAggregate(glslang::TVisit, glslang::TIntermAggregate* node) override
|
bool visitAggregate(glslang::TVisit, glslang::TIntermAggregate* node) override
|
||||||
{
|
{
|
||||||
if (!remained_accesschain_.empty() && node->getOp() == glslang::EOpConstructStruct) {
|
if (!remained_accesschain_.empty() && node->getOp() == glslang::EOpConstructStruct) {
|
||||||
// This is a struct initializer node, and the remained
|
// This is a struct initializer node, and the remained
|
||||||
// accesschain is not empty, we need to refer to the
|
// access chain is not empty, we need to refer to the
|
||||||
// assignee_remained_access_chain_ to find the nested
|
// assignee_remained_access_chain_ to find the nested
|
||||||
// 'precise' object. And we don't need to visit other nodes in this
|
// 'precise' object. And we don't need to visit other nodes in this
|
||||||
// aggreagate node.
|
// aggregate node.
|
||||||
|
|
||||||
// Gets the struct dereference index that leads to 'precise' object.
|
// Gets the struct dereference index that leads to 'precise' object.
|
||||||
ObjectAccessChain precise_accesschain_index_str =
|
ObjectAccessChain precise_accesschain_index_str =
|
||||||
getFrontElement(remained_accesschain_);
|
getFrontElement(remained_accesschain_);
|
||||||
unsigned precise_accesschain_index = strtoul(precise_accesschain_index_str.c_str(), nullptr, 10);
|
unsigned precise_accesschain_index = strtoul(precise_accesschain_index_str.c_str(), nullptr, 10);
|
||||||
// Gets the node pointed by the accesschain index extracted before.
|
// Gets the node pointed by the access chain index extracted before.
|
||||||
glslang::TIntermTyped* potential_precise_node =
|
glslang::TIntermTyped* potential_precise_node =
|
||||||
node->getSequence()[precise_accesschain_index]->getAsTyped();
|
node->getSequence()[precise_accesschain_index]->getAsTyped();
|
||||||
assert(potential_precise_node);
|
assert(potential_precise_node);
|
||||||
// Pop the front accesschain index from the path, and visit the nested node.
|
// Pop the front access chain index from the path, and visit the nested node.
|
||||||
{
|
{
|
||||||
ObjectAccessChain next_level_accesschain =
|
ObjectAccessChain next_level_accesschain =
|
||||||
subAccessChainFromSecondElement(remained_accesschain_);
|
subAccessChainFromSecondElement(remained_accesschain_);
|
||||||
@@ -684,7 +684,7 @@ protected:
|
|||||||
|
|
||||||
// Visits a binary node. A binary node can be an object node, e.g. a dereference node.
|
// Visits a binary node. A binary node can be an object node, e.g. a dereference node.
|
||||||
// As only the top object nodes in the right side of an assignment needs to be visited
|
// As only the top object nodes in the right side of an assignment needs to be visited
|
||||||
// and added to 'precise' worklist, this traverser won't visit the children nodes of
|
// and added to 'precise' work list, this traverser won't visit the children nodes of
|
||||||
// an object node. If the binary node does not represent an object node, it should
|
// an object node. If the binary node does not represent an object node, it should
|
||||||
// go on to traverse its children nodes and if it is an arithmetic operation node, this
|
// go on to traverse its children nodes and if it is an arithmetic operation node, this
|
||||||
// operation should be marked as 'noContraction'.
|
// operation should be marked as 'noContraction'.
|
||||||
@@ -692,16 +692,16 @@ protected:
|
|||||||
{
|
{
|
||||||
if (isDereferenceOperation(node->getOp())) {
|
if (isDereferenceOperation(node->getOp())) {
|
||||||
// This binary node is an object node. Need to update the precise
|
// This binary node is an object node. Need to update the precise
|
||||||
// object set with the accesschain of this node + remained
|
// object set with the access chain of this node + remained
|
||||||
// accesschain .
|
// access chain .
|
||||||
ObjectAccessChain new_precise_accesschain = accesschain_mapping_.at(node);
|
ObjectAccessChain new_precise_accesschain = accesschain_mapping_.at(node);
|
||||||
if (remained_accesschain_.empty()) {
|
if (remained_accesschain_.empty()) {
|
||||||
node->getWritableType().getQualifier().noContraction = true;
|
node->getWritableType().getQualifier().noContraction = true;
|
||||||
} else {
|
} else {
|
||||||
new_precise_accesschain += ObjectAccesschainDelimiter + remained_accesschain_;
|
new_precise_accesschain += ObjectAccesschainDelimiter + remained_accesschain_;
|
||||||
}
|
}
|
||||||
// Cache the accesschain as added precise object, so we won't add the
|
// Cache the access chain as added precise object, so we won't add the
|
||||||
// same object to the worklist again.
|
// same object to the work list again.
|
||||||
if (!added_precise_object_ids_.count(new_precise_accesschain)) {
|
if (!added_precise_object_ids_.count(new_precise_accesschain)) {
|
||||||
precise_objects_.insert(new_precise_accesschain);
|
precise_objects_.insert(new_precise_accesschain);
|
||||||
added_precise_object_ids_.insert(new_precise_accesschain);
|
added_precise_object_ids_.insert(new_precise_accesschain);
|
||||||
@@ -718,7 +718,7 @@ protected:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Visits an unary node. An unary node can not be an object node. If the operation
|
// Visits a unary node. A unary node can not be an object node. If the operation
|
||||||
// is an arithmetic operation, need to mark this node as 'noContraction'.
|
// is an arithmetic operation, need to mark this node as 'noContraction'.
|
||||||
bool visitUnary(glslang::TVisit /* visit */, glslang::TIntermUnary* node) override
|
bool visitUnary(glslang::TVisit /* visit */, glslang::TIntermUnary* node) override
|
||||||
{
|
{
|
||||||
@@ -730,26 +730,26 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Visits a symbol node. A symbol node is always an object node. So we
|
// Visits a symbol node. A symbol node is always an object node. So we
|
||||||
// should always be able to find its in our colected mapping from object
|
// should always be able to find its in our collected mapping from object
|
||||||
// nodes to accesschains. As an object node, a symbol node can be either
|
// nodes to access chains. As an object node, a symbol node can be either
|
||||||
// 'precise' or containing 'precise' objects according to unused
|
// 'precise' or containing 'precise' objects according to unused
|
||||||
// accesschain information we have when we visit this node.
|
// access chain information we have when we visit this node.
|
||||||
void visitSymbol(glslang::TIntermSymbol* node) override
|
void visitSymbol(glslang::TIntermSymbol* node) override
|
||||||
{
|
{
|
||||||
// Symbol nodes are object nodes and should always have an
|
// Symbol nodes are object nodes and should always have an
|
||||||
// accesschain collected before matches with it.
|
// access chain collected before matches with it.
|
||||||
assert(accesschain_mapping_.count(node));
|
assert(accesschain_mapping_.count(node));
|
||||||
ObjectAccessChain new_precise_accesschain = accesschain_mapping_.at(node);
|
ObjectAccessChain new_precise_accesschain = accesschain_mapping_.at(node);
|
||||||
// If the unused accesschain is empty, this symbol node should be
|
// If the unused access chain is empty, this symbol node should be
|
||||||
// marked as 'precise'. Otherwise, the unused accesschain should be
|
// marked as 'precise'. Otherwise, the unused access chain should be
|
||||||
// appended to the symbol ID to build a new accesschain which points to
|
// appended to the symbol ID to build a new access chain which points to
|
||||||
// the nested 'precise' object in this symbol object.
|
// the nested 'precise' object in this symbol object.
|
||||||
if (remained_accesschain_.empty()) {
|
if (remained_accesschain_.empty()) {
|
||||||
node->getWritableType().getQualifier().noContraction = true;
|
node->getWritableType().getQualifier().noContraction = true;
|
||||||
} else {
|
} else {
|
||||||
new_precise_accesschain += ObjectAccesschainDelimiter + remained_accesschain_;
|
new_precise_accesschain += ObjectAccesschainDelimiter + remained_accesschain_;
|
||||||
}
|
}
|
||||||
// Add the new 'precise' accesschain to the worklist and make sure we
|
// Add the new 'precise' access chain to the work list and make sure we
|
||||||
// don't visit it again.
|
// don't visit it again.
|
||||||
if (!added_precise_object_ids_.count(new_precise_accesschain)) {
|
if (!added_precise_object_ids_.count(new_precise_accesschain)) {
|
||||||
precise_objects_.insert(new_precise_accesschain);
|
precise_objects_.insert(new_precise_accesschain);
|
||||||
@@ -757,7 +757,7 @@ protected:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// A set of precise objects, represented as accesschains.
|
// A set of precise objects, represented as access chains.
|
||||||
ObjectAccesschainSet& precise_objects_;
|
ObjectAccesschainSet& precise_objects_;
|
||||||
// Visited symbol nodes, should not revisit these nodes.
|
// Visited symbol nodes, should not revisit these nodes.
|
||||||
ObjectAccesschainSet added_precise_object_ids_;
|
ObjectAccesschainSet added_precise_object_ids_;
|
||||||
@@ -767,7 +767,7 @@ protected:
|
|||||||
// the right. So we need the path from the left node to its nested 'precise' node to
|
// the right. So we need the path from the left node to its nested 'precise' node to
|
||||||
// tell us how to find the corresponding 'precise' node in the right.
|
// tell us how to find the corresponding 'precise' node in the right.
|
||||||
ObjectAccessChain remained_accesschain_;
|
ObjectAccessChain remained_accesschain_;
|
||||||
// A map from node pointers to their accesschains.
|
// A map from node pointers to their access chains.
|
||||||
const AccessChainMapping& accesschain_mapping_;
|
const AccessChainMapping& accesschain_mapping_;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -787,35 +787,35 @@ void PropagateNoContraction(const glslang::TIntermediate& intermediate)
|
|||||||
// traversing the tree again.
|
// traversing the tree again.
|
||||||
NodeMapping& symbol_definition_mapping = std::get<0>(mappings_and_precise_objects);
|
NodeMapping& symbol_definition_mapping = std::get<0>(mappings_and_precise_objects);
|
||||||
|
|
||||||
// The mapping of object nodes to their accesschains recorded.
|
// The mapping of object nodes to their access chains recorded.
|
||||||
AccessChainMapping& accesschain_mapping = std::get<1>(mappings_and_precise_objects);
|
AccessChainMapping& accesschain_mapping = std::get<1>(mappings_and_precise_objects);
|
||||||
|
|
||||||
// The initial set of 'precise' objects which are represented as the
|
// The initial set of 'precise' objects which are represented as the
|
||||||
// accesschain toward them.
|
// access chain toward them.
|
||||||
ObjectAccesschainSet& precise_object_accesschains = std::get<2>(mappings_and_precise_objects);
|
ObjectAccesschainSet& precise_object_accesschains = std::get<2>(mappings_and_precise_objects);
|
||||||
|
|
||||||
// The set of 'precise' return nodes.
|
// The set of 'precise' return nodes.
|
||||||
ReturnBranchNodeSet& precise_return_nodes = std::get<3>(mappings_and_precise_objects);
|
ReturnBranchNodeSet& precise_return_nodes = std::get<3>(mappings_and_precise_objects);
|
||||||
|
|
||||||
// Second, uses the initial set of precise objects as a worklist, pops an
|
// Second, uses the initial set of precise objects as a work list, pops an
|
||||||
// accesschain, extract the symbol ID from it. Then:
|
// access chain, extract the symbol ID from it. Then:
|
||||||
// 1) Check the assignee object, see if it is 'precise' object node or
|
// 1) Check the assignee object, see if it is 'precise' object node or
|
||||||
// contains 'precise' object. Obtain the incremental accesschain from the
|
// contains 'precise' object. Obtain the incremental access chain from the
|
||||||
// assignee node to its nested 'precise' node (if any).
|
// assignee node to its nested 'precise' node (if any).
|
||||||
// 2) If the assignee object node is 'precise' or it contains 'precise'
|
// 2) If the assignee object node is 'precise' or it contains 'precise'
|
||||||
// objects, traverses the right side of the assignment operation
|
// objects, traverses the right side of the assignment operation
|
||||||
// expression to mark arithmetic operations as 'noContration' and update
|
// expression to mark arithmetic operations as 'noContration' and update
|
||||||
// 'precise' accesschain worklist with new found object nodes.
|
// 'precise' access chain work list with new found object nodes.
|
||||||
// Repeat above steps until the worklist is empty.
|
// Repeat above steps until the work list is empty.
|
||||||
TNoContractionAssigneeCheckingTraverser checker(accesschain_mapping);
|
TNoContractionAssigneeCheckingTraverser checker(accesschain_mapping);
|
||||||
TNoContractionPropagator propagator(&precise_object_accesschains, accesschain_mapping);
|
TNoContractionPropagator propagator(&precise_object_accesschains, accesschain_mapping);
|
||||||
|
|
||||||
// We have two initial precise worklists to handle:
|
// We have two initial precise work lists to handle:
|
||||||
// 1) precise return nodes
|
// 1) precise return nodes
|
||||||
// 2) precise object accesschains
|
// 2) precise object access chains
|
||||||
// We should process the precise return nodes first and the involved
|
// We should process the precise return nodes first and the involved
|
||||||
// objects in the return expression should be added to the precise object
|
// objects in the return expression should be added to the precise object
|
||||||
// accesschain set.
|
// access chain set.
|
||||||
while (!precise_return_nodes.empty()) {
|
while (!precise_return_nodes.empty()) {
|
||||||
glslang::TIntermBranch* precise_return_node = *precise_return_nodes.begin();
|
glslang::TIntermBranch* precise_return_node = *precise_return_nodes.begin();
|
||||||
propagator.propagateNoContractionInReturnNode(precise_return_node);
|
propagator.propagateNoContractionInReturnNode(precise_return_node);
|
||||||
@@ -823,9 +823,9 @@ void PropagateNoContraction(const glslang::TIntermediate& intermediate)
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (!precise_object_accesschains.empty()) {
|
while (!precise_object_accesschains.empty()) {
|
||||||
// Get the accesschain of a precise object from the worklist.
|
// Get the access chain of a precise object from the work list.
|
||||||
ObjectAccessChain precise_object_accesschain = *precise_object_accesschains.begin();
|
ObjectAccessChain precise_object_accesschain = *precise_object_accesschains.begin();
|
||||||
// Get the symbol id from the accesschain.
|
// Get the symbol id from the access chain.
|
||||||
ObjectAccessChain symbol_id = getFrontElement(precise_object_accesschain);
|
ObjectAccessChain symbol_id = getFrontElement(precise_object_accesschain);
|
||||||
// Get all the defining nodes of that symbol ID.
|
// Get all the defining nodes of that symbol ID.
|
||||||
std::pair<NodeMapping::iterator, NodeMapping::iterator> range =
|
std::pair<NodeMapping::iterator, NodeMapping::iterator> range =
|
||||||
@@ -833,9 +833,9 @@ void PropagateNoContraction(const glslang::TIntermediate& intermediate)
|
|||||||
// Visits all the assignment nodes of that symbol ID and
|
// Visits all the assignment nodes of that symbol ID and
|
||||||
// 1) Check if the assignee node is 'precise' or contains 'precise'
|
// 1) Check if the assignee node is 'precise' or contains 'precise'
|
||||||
// objects.
|
// objects.
|
||||||
// 2) Propagate the 'precise' to the top layer object ndoes
|
// 2) Propagate the 'precise' to the top layer object nodes
|
||||||
// in the right side of the assignment operation, update the 'precise'
|
// in the right side of the assignment operation, update the 'precise'
|
||||||
// worklist with new accesschains representing the new 'precise'
|
// work list with new access chains representing the new 'precise'
|
||||||
// objects, and mark arithmetic operations as 'noContraction'.
|
// objects, and mark arithmetic operations as 'noContraction'.
|
||||||
for (NodeMapping::iterator defining_node_iter = range.first;
|
for (NodeMapping::iterator defining_node_iter = range.first;
|
||||||
defining_node_iter != range.second; defining_node_iter++) {
|
defining_node_iter != range.second; defining_node_iter++) {
|
||||||
@@ -852,7 +852,7 @@ void PropagateNoContraction(const glslang::TIntermediate& intermediate)
|
|||||||
remained_accesschain);
|
remained_accesschain);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Remove the last processed 'precise' object from the worklist.
|
// Remove the last processed 'precise' object from the work list.
|
||||||
precise_object_accesschains.erase(precise_object_accesschain);
|
precise_object_accesschains.erase(precise_object_accesschain);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
// from this software without specific prior written permission.
|
// from this software without specific prior written permission.
|
||||||
//
|
//
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
|||||||
Reference in New Issue
Block a user