Exemplo n.º 1
0
bool EmulatePrecision::visitBinary(Visit visit, TIntermBinary *node)
{
    bool visitChildren = true;

    TOperator op = node->getOp();

    // RHS of initialize is not being declared.
    if (op == EOpInitialize && visit == InVisit)
        mDeclaringVariables = false;

    if ((op == EOpIndexDirectStruct) && visit == InVisit)
        visitChildren = false;

    if (visit != PreVisit)
        return visitChildren;

    const TType &type = node->getType();
    bool roundFloat   = canRoundFloat(type);

    if (roundFloat)
    {
        switch (op)
        {
            // Math operators that can result in a float may need to apply rounding to the return
            // value. Note that in the case of assignment, the rounding is applied to its return
            // value here, not the value being assigned.
            case EOpAssign:
            case EOpAdd:
            case EOpSub:
            case EOpMul:
            case EOpDiv:
            case EOpVectorTimesScalar:
            case EOpVectorTimesMatrix:
            case EOpMatrixTimesVector:
            case EOpMatrixTimesScalar:
            case EOpMatrixTimesMatrix:
            {
                TIntermNode *parent = getParentNode();
                if (!ParentUsesResult(parent, node) ||
                    ParentConstructorTakesCareOfRounding(parent, node))
                {
                    break;
                }
                TIntermNode *replacement = createRoundingFunctionCallNode(node);
                queueReplacement(replacement, OriginalNode::BECOMES_CHILD);
                break;
            }

            // Compound assignment cases need to replace the operator with a function call.
            case EOpAddAssign:
            {
                mEmulateCompoundAdd.insert(
                    TypePair(type.getBuiltInTypeNameString(),
                             node->getRight()->getType().getBuiltInTypeNameString()));
                TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(
                    node->getLeft(), node->getRight(), "add");
                queueReplacement(replacement, OriginalNode::IS_DROPPED);
                break;
            }
            case EOpSubAssign:
            {
                mEmulateCompoundSub.insert(
                    TypePair(type.getBuiltInTypeNameString(),
                             node->getRight()->getType().getBuiltInTypeNameString()));
                TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(
                    node->getLeft(), node->getRight(), "sub");
                queueReplacement(replacement, OriginalNode::IS_DROPPED);
                break;
            }
            case EOpMulAssign:
            case EOpVectorTimesMatrixAssign:
            case EOpVectorTimesScalarAssign:
            case EOpMatrixTimesScalarAssign:
            case EOpMatrixTimesMatrixAssign:
            {
                mEmulateCompoundMul.insert(
                    TypePair(type.getBuiltInTypeNameString(),
                             node->getRight()->getType().getBuiltInTypeNameString()));
                TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(
                    node->getLeft(), node->getRight(), "mul");
                queueReplacement(replacement, OriginalNode::IS_DROPPED);
                break;
            }
            case EOpDivAssign:
            {
                mEmulateCompoundDiv.insert(
                    TypePair(type.getBuiltInTypeNameString(),
                             node->getRight()->getType().getBuiltInTypeNameString()));
                TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(
                    node->getLeft(), node->getRight(), "div");
                queueReplacement(replacement, OriginalNode::IS_DROPPED);
                break;
            }
            default:
                // The rest of the binary operations should not need precision emulation.
                break;
        }
    }
    return visitChildren;
}
Exemplo n.º 2
0
bool EmulatePrecision::visitBinary(Visit visit, TIntermBinary *node)
{
    bool visitChildren = true;

    if (node->isAssignment())
    {
        if (visit == PreVisit)
            mInLValue = true;
        else if (visit == InVisit)
            mInLValue = false;
    }

    TOperator op = node->getOp();

    // RHS of initialize is not being declared.
    if (op == EOpInitialize && visit == InVisit)
        mDeclaringVariables = false;

    if ((op == EOpIndexDirectStruct || op == EOpVectorSwizzle) && visit == InVisit)
        visitChildren = false;

    if (visit != PreVisit)
        return visitChildren;

    const TType& type = node->getType();
    bool roundFloat = canRoundFloat(type);

    if (roundFloat) {
        switch (op) {
          // Math operators that can result in a float may need to apply rounding to the return
          // value. Note that in the case of assignment, the rounding is applied to its return
          // value here, not the value being assigned.
          case EOpAssign:
          case EOpAdd:
          case EOpSub:
          case EOpMul:
          case EOpDiv:
          case EOpVectorTimesScalar:
          case EOpVectorTimesMatrix:
          case EOpMatrixTimesVector:
          case EOpMatrixTimesScalar:
          case EOpMatrixTimesMatrix:
          {
            TIntermNode *parent = getParentNode();
            if (!parentUsesResult(parent, node))
            {
                break;
            }
            TIntermNode *replacement = createRoundingFunctionCallNode(node);
            mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, true));
            break;
          }

          // Compound assignment cases need to replace the operator with a function call.
          case EOpAddAssign:
          {
            mEmulateCompoundAdd.insert(TypePair(getFloatTypeStr(type), getFloatTypeStr(node->getRight()->getType())));
            TIntermNode *parent = getParentNode();
            TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(node->getLeft(), node->getRight(), "add");
            mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, false));
            break;
          }
          case EOpSubAssign:
          {
            mEmulateCompoundSub.insert(TypePair(getFloatTypeStr(type), getFloatTypeStr(node->getRight()->getType())));
            TIntermNode *parent = getParentNode();
            TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(node->getLeft(), node->getRight(), "sub");
            mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, false));
            break;
          }
          case EOpMulAssign:
          case EOpVectorTimesMatrixAssign:
          case EOpVectorTimesScalarAssign:
          case EOpMatrixTimesScalarAssign:
          case EOpMatrixTimesMatrixAssign:
          {
            mEmulateCompoundMul.insert(TypePair(getFloatTypeStr(type), getFloatTypeStr(node->getRight()->getType())));
            TIntermNode *parent = getParentNode();
            TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(node->getLeft(), node->getRight(), "mul");
            mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, false));
            break;
          }
          case EOpDivAssign:
          {
            mEmulateCompoundDiv.insert(TypePair(getFloatTypeStr(type), getFloatTypeStr(node->getRight()->getType())));
            TIntermNode *parent = getParentNode();
            TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(node->getLeft(), node->getRight(), "div");
            mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, false));
            break;
          }
          default:
            // The rest of the binary operations should not need precision emulation.
            break;
        }
    }
    return visitChildren;
}