TString TOutputGLSLBase::getTypeName(const TType &type)
{
    if (type.getBasicType() == EbtStruct)
        return hashName(type.getStruct()->name());
    else
        return type.getBuiltInTypeNameString();
}
BuiltInFunctionEmulator::TBuiltInFunction
BuiltInFunctionEmulator::IdentifyFunction(
    TOperator op, const TType& param)
{
    if (param.getNominalSize() > 4 || param.getSecondarySize() > 4)
        return TFunctionUnknown;
    unsigned int function = TFunctionUnknown;
    switch (op) {
        case EOpCos:
            function = TFunctionCos1;
            break;
        case EOpLength:
            function = TFunctionLength1;
            break;
        case EOpNormalize:
            function = TFunctionNormalize1;
            break;
        default:
            break;
    }
    if (function == TFunctionUnknown)
        return TFunctionUnknown;
    if (param.isVector())
        function += param.getNominalSize() - 1;
    return static_cast<TBuiltInFunction>(function);
}
Example #3
0
void TOutputVulkanGLSL::writeQualifier(TQualifier qualifier,
                                       const TType &type,
                                       const TSymbol *symbol)
{
    if (qualifier != EvqUniform && qualifier != EvqAttribute && qualifier != EvqVertexIn &&
        !sh::IsVarying(qualifier))
    {
        TOutputGLSLBase::writeQualifier(qualifier, type, symbol);
        return;
    }

    if (symbol == nullptr)
    {
        return;
    }

    ImmutableString name = symbol->name();

    // For interface blocks, use the block name instead.  When the qualifier is being replaced in
    // the backend, that would be the name that's available.
    if (type.isInterfaceBlock())
    {
        name = type.getInterfaceBlock()->name();
    }

    TInfoSinkBase &out = objSink();
    out << "@@ QUALIFIER-" << name.data() << " @@ ";
}
Example #4
0
bool OutputSpecification(TIntermSpecification* node, TIntermTraverser* it)
{
    TOutputTraverser* oit = static_cast<TOutputTraverser*>(it);
    TInfoSink& out = oit->infoSink;

    OutputExtensionText(out, node);
    OutputTreeText(out, node, oit->depth);

    TType* t = node->getType();

    out.debug << "specify '" << t->getTypeName().c_str() << "' (" << t->getCompleteString() << ")\n";

    return true;

#if 0
    TTypeList* tl = t->getStruct();
    TTypeList::iterator iter = tl->begin();
    for(; iter < tl->end(); iter++) {
        out.debug << FormatSourceRange(iter->line);
        for (i = 0; i < (oit->depth+1); ++i) out.debug << "  ";
        out.debug << "'" << iter->type->getFieldName().c_str() << "' (" <<
                  iter->type->getCompleteString().c_str() << ")\n";
    }
#endif
}
Example #5
0
void GetVariableTraverser::traverse(const TType &type, const TString &name, std::vector<VarT> *output)
{
    const TStructure *structure = type.getStruct();

    VarT variable;
    variable.name = name.c_str();
    variable.arraySize = static_cast<unsigned int>(type.getArraySize());

    if (!structure)
    {
        variable.type = GLVariableType(type);
        variable.precision = GLVariablePrecision(type);
    }
    else
    {
        // Note: this enum value is not exposed outside ANGLE
        variable.type = GL_STRUCT_ANGLEX;
        variable.structName = structure->name().c_str();

        const TFieldList &fields = structure->fields();

        for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
        {
            TField *field = fields[fieldIndex];
            traverse(*field->type(), field->name(), &variable.fields);
        }
    }

    visitVariable(&variable);

    ASSERT(output);
    output->push_back(variable);
}
Example #6
0
    int resolveInOutLocation(EShLanguage /*stage*/, const char* /*name*/, const TType& type, bool /*is_live*/) override
    {
        // kick out of not doing this
        if (!doAutoLocationMapping)
            return -1;

        // no locations added if already present, or a built-in variable
        if (type.getQualifier().hasLocation() || type.isBuiltIn())
            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;
        }

        // Placeholder.
        // TODO: It would be nice to flesh this out using 
        // intermediate->computeTypeLocationSize(type), or functions that call it like
        // intermediate->addUsedLocation()
        // These in turn would want the intermediate, which is not available here, but
        // is available in many places, and a lot of copying from it could be saved if
        // it were just available.
        return 0;
    }
Example #7
0
TType *TCodeGenerator::EmitSimpleExpression(void)
{
    TType      *pOperandType;      // ptr to operand's type
    TType      *pResultType;       // ptr to result type
    TTokenCode  op;                // operator
    TTokenCode  unaryOp = tcPlus;  // unary operator

    //--Unary + or -
    if (TokenIn(token, tlUnaryOps)) {
	unaryOp = token;
	GetToken();
    }

    //--Emit code for the first term.
    pResultType = EmitTerm();

    //--If there was a unary operator, negate in integer value in ax
    //--with the neg instruction, or negate a real value in dx:ax
    //--by calling _FloatNegate.
    if (unaryOp == tcMinus) {
	if (pResultType->Base() == pIntegerType) Emit1(neg, Reg(ax))
	else if (pResultType == pRealType) {
	    EmitPushOperand(pResultType);
	    Emit1(call, NameLit(FLOAT_NEGATE));
	    Emit2(add,  Reg(sp), IntegerLit(4));
	}
    }

    //--Loop to execute subsequent additive operators and terms.
    while (TokenIn(token, tlAddOps)) {
	op = token;
	pResultType = pResultType->Base();
	EmitPushOperand(pResultType);

	GetToken();
	pOperandType = EmitTerm()->Base();

	//--Perform the operation, and push the resulting value
	//--onto the stack.
	if (op == tcOR) {

	    //--boolean OR boolean => boolean
	    //--ax = ax OR dx
	    Emit1(pop, Reg(dx));
	    Emit2(or,  Reg(ax), Reg(dx));
	    pResultType = pBooleanType;
	}
	else if ((pResultType  == pIntegerType) &&
		 (pOperandType == pIntegerType)) {

	    //--integer +|- integer => integer
	    Emit1(pop, Reg(dx));
	    if (op == tcPlus) Emit2(add, Reg(ax), Reg(dx))
	    else {
		Emit2(sub, Reg(dx), Reg(ax));
		Emit2(mov, Reg(ax), Reg(dx));
	    }
	    pResultType = pIntegerType;
	}
	else {
Example #8
0
//
// This function returns an element of an array accessed from a constant array. The values are retrieved from
// the symbol table and parse-tree is built for the type of the element. The input 
// to the function could either be a symbol node (a[0] where a is a constant array)that represents a 
// constant array or it could be the tree representation of the constant array (s.a1[0] where s is a constant structure)
//
TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TSourceLoc line)
{
    TIntermTyped* typedNode;
    TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
    TType arrayElementType = node->getType();
    arrayElementType.clearArrayness();

    if (index >= node->getType().getArraySize()) {
        error(line, "", "[", "array field selection out of range '%d'", index);
        recover();
        index = 0;
    }

    int arrayElementSize = arrayElementType.getObjectSize();

    if (tempConstantNode) {
         ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer();
         typedNode = intermediate.addConstantUnion(&unionArray[arrayElementSize * index], tempConstantNode->getType(), line);
    } else {
        error(line, "Cannot offset into the array", "Error", "");
        recover();

        return 0;
    }

    return typedNode;
}
Example #9
0
TString ArrayString(const TType &type)
{
    if (!type.isArray())
    {
        return "";
    }

    return "[" + str(type.getArraySize()) + "]";
}
Example #10
0
bool TParseContext::parameterSamplerErrorCheck(int line, TQualifier qualifier, const TType& type)
{
    if ((qualifier == EvqOut || qualifier == EvqInOut) && 
             type.getBasicType() != EbtStruct && IsSampler(type.getBasicType())) {
        error(line, "samplers cannot be output parameters", type.getBasicString(), "");
        return true;
    }

    return false;
}
void TOutputGLSLBase::writeLayoutQualifier(const TType &type)
{
    if (type.getQualifier() == EvqFragmentOut || type.getQualifier() == EvqVertexIn)
    {
        const TLayoutQualifier &layoutQualifier = type.getLayoutQualifier();
        if (layoutQualifier.location >= 0)
        {
            TInfoSinkBase &out = objSink();
            out << "layout(location = " << layoutQualifier.location << ") ";
        }
    }
}
Example #12
0
void UniformHLSL::outputHLSL4_0_FL9_3Sampler(TInfoSinkBase &out,
                                             const TType &type,
                                             const TName &name,
                                             const unsigned int registerIndex)
{
    out << "uniform " << SamplerString(type.getBasicType()) << " sampler_"
        << DecorateUniform(name, type) << ArrayString(type) << " : register(s" << str(registerIndex)
        << ");\n";
    out << "uniform " << TextureString(type.getBasicType()) << " texture_"
        << DecorateUniform(name, type) << ArrayString(type) << " : register(t" << str(registerIndex)
        << ");\n";
}
void RegenerateStructNames::visitSymbol(TIntermSymbol *symbol)
{
    ASSERT(symbol);
    TType *type = symbol->getTypePointer();
    ASSERT(type);
    TStructure *userType = type->getStruct();
    if (!userType)
        return;

    if (mSymbolTable.findBuiltIn(userType->name(), mShaderVersion))
    {
        // Built-in struct, do not touch it.
        return;
    }

    int uniqueId = userType->uniqueId();

    ASSERT(mScopeDepth > 0);
    if (mScopeDepth == 1)
    {
        // If a struct is defined at global scope, we don't map its name.
        // This is because at global level, the struct might be used to
        // declare a uniform, so the same name needs to stay the same for
        // vertex/fragment shaders. However, our mapping uses internal ID,
        // which will be different for the same struct in vertex/fragment
        // shaders.
        // This is OK because names for any structs defined in other scopes
        // will begin with "_webgl", which is reserved. So there will be
        // no conflicts among unmapped struct names from global scope and
        // mapped struct names from other scopes.
        // However, we need to keep track of these global structs, so if a
        // variable is used in a local scope, we don't try to modify the
        // struct name through that variable.
        mDeclaredGlobalStructs.insert(uniqueId);
        return;
    }
    if (mDeclaredGlobalStructs.count(uniqueId) > 0)
        return;
    // Map {name} to _webgl_struct_{uniqueId}_{name}.
    const char kPrefix[] = "_webgl_struct_";
    if (userType->name().find(kPrefix) == 0)
    {
        // The name has already been regenerated.
        return;
    }
    std::string id = Str(uniqueId);
    TString tmp = kPrefix + TString(id.c_str());
    tmp += "_" + userType->name();
    userType->setName(tmp);
}
Example #14
0
TString TOutputGLSLBase::getTypeName(const TType& type)
{
    TInfoSinkBase out;
    if (type.isMatrix())
    {
        out << "mat";
        out << type.getNominalSize();
    }
    else if (type.isVector())
    {
        switch (type.getBasicType())
        {
            case EbtFloat: out << "vec"; break;
            case EbtInt: out << "ivec"; break;
            case EbtBool: out << "bvec"; break;
            default: UNREACHABLE(); break;
        }
        out << type.getNominalSize();
    }
    else
    {
        if (type.getBasicType() == EbtStruct)
            out << hashName(type.getTypeName());
        else
            out << type.getBasicString();
    }
    return TString(out.c_str());
}
BuiltInFunctionEmulator::TBuiltInFunction
BuiltInFunctionEmulator::IdentifyFunction(
    TOperator op, const TType& param1, const TType& param2)
{
    // Right now for all the emulated functions with two parameters, the two
    // parameters have the same type.
    if (param1.getNominalSize()     != param2.getNominalSize()   ||
        param1.getSecondarySize()   != param2.getSecondarySize() ||
        param1.getNominalSize() > 4 || param1.getSecondarySize() > 4)
        return TFunctionUnknown;

    unsigned int function = TFunctionUnknown;
    switch (op) {
        case EOpDistance:
            function = TFunctionDistance1_1;
            break;
        case EOpDot:
            function = TFunctionDot1_1;
            break;
        case EOpReflect:
            function = TFunctionReflect1_1;
            break;
        default:
            break;
    }
    if (function == TFunctionUnknown)
        return TFunctionUnknown;
    if (param1.isVector())
        function += param1.getNominalSize() - 1;
    return static_cast<TBuiltInFunction>(function);
}
Example #16
0
void TOutputGLSLBase::writeVariableType(const TType& type)
{
    TInfoSinkBase& out = objSink();
    TQualifier qualifier = type.getQualifier();
    // TODO(alokp): Validate qualifier for variable declarations.
    if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal))
        out << type.getQualifierString() << " ";
    // Declare the struct if we have not done so already.
    if ((type.getBasicType() == EbtStruct) &&
        (mDeclaredStructs.find(type.getTypeName()) == mDeclaredStructs.end()))
    {
        out << "struct " << type.getTypeName() << "{\n";
        const TTypeList* structure = type.getStruct();
        ASSERT(structure != NULL);
        for (size_t i = 0; i < structure->size(); ++i)
        {
            const TType* fieldType = (*structure)[i].type;
            ASSERT(fieldType != NULL);
            if (writeVariablePrecision(fieldType->getPrecision()))
                out << " ";
            out << getTypeName(*fieldType) << " " << fieldType->getFieldName();
            if (fieldType->isArray())
                out << arrayBrackets(*fieldType);
            out << ";\n";
        }
        out << "}";
        mDeclaredStructs.insert(type.getTypeName());
    }
    else
    {
        if (writeVariablePrecision(type.getPrecision()))
            out << " ";
        out << getTypeName(type);
    }
}
Example #17
0
void TSamplerTraverser::traverseSymbol( TIntermSymbol *node, TIntermTraverser *it )
{
   TSamplerTraverser* sit = static_cast<TSamplerTraverser*>(it);

   if (sit->abort)
      return;

   if (sit->typing && sit->id == node->getId())
   {
      TType* type = node->getTypePointer();
      // Technically most of these should never happen
	  type->setBasicType (sit->sampType);
   }
}
Example #18
0
bool TParseContext::containsSampler(TType& type)
{
    if (IsSampler(type.getBasicType()))
        return true;

    if (type.getBasicType() == EbtStruct) {
        TTypeList& structure = *type.getStruct();
        for (unsigned int i = 0; i < structure.size(); ++i) {
            if (containsSampler(*structure[i].type))
                return true;
        }
    }

    return false;
}
TString ScalarizeVecAndMatConstructorArgs::createTempVariable(TIntermTyped *original)
{
    TString tempVarName = "_webgl_tmp_";
    if (original->isScalar())
    {
        tempVarName += "scalar_";
    }
    else if (original->isVector())
    {
        tempVarName += "vec_";
    }
    else
    {
        ASSERT(original->isMatrix());
        tempVarName += "mat_";
    }
    tempVarName += Str(mTempVarCount).c_str();
    mTempVarCount++;

    ASSERT(original);
    TType type = original->getType();
    type.setQualifier(EvqTemporary);

    if (mShaderType == GL_FRAGMENT_SHADER &&
        type.getBasicType() == EbtFloat &&
        type.getPrecision() == EbpUndefined)
    {
        // We use the highest available precision for the temporary variable
        // to avoid computing the actual precision using the rules defined
        // in GLSL ES 1.0 Section 4.5.2.
        type.setPrecision(mFragmentPrecisionHigh ? EbpHigh : EbpMedium);
    }

    TIntermBinary *init = new TIntermBinary(EOpInitialize);
    TIntermSymbol *symbolNode = new TIntermSymbol(-1, tempVarName, type);
    init->setLeft(symbolNode);
    init->setRight(original);
    init->setType(type);

    TIntermAggregate *decl = new TIntermAggregate(EOpDeclaration);
    decl->getSequence()->push_back(init);

    ASSERT(mSequenceStack.size() > 0);
    TIntermSequence &sequence = mSequenceStack.back();
    sequence.push_back(decl);

    return tempVarName;
}
Example #20
0
TString TextureString(const TType &type)
{
    switch (type.getBasicType())
    {
      case EbtSampler2D:            return "Texture2D";
      case EbtSamplerCube:          return "TextureCube";
      case EbtSamplerExternalOES:   return "Texture2D";
      case EbtSampler2DArray:       return "Texture2DArray";
      case EbtSampler3D:            return "Texture3D";
      case EbtISampler2D:           return "Texture2D<int4>";
      case EbtISampler3D:           return "Texture3D<int4>";
      case EbtISamplerCube:         return "Texture2DArray<int4>";
      case EbtISampler2DArray:      return "Texture2DArray<int4>";
      case EbtUSampler2D:           return "Texture2D<uint4>";
      case EbtUSampler3D:           return "Texture3D<uint4>";
      case EbtUSamplerCube:         return "Texture2DArray<uint4>";
      case EbtUSampler2DArray:      return "Texture2DArray<uint4>";
      case EbtSampler2DShadow:      return "Texture2D";
      case EbtSamplerCubeShadow:    return "TextureCube";
      case EbtSampler2DArrayShadow: return "Texture2DArray";
      default: UNREACHABLE();
    }

    return "<unknown texture type>";
}
Example #21
0
unsigned int UniformHLSL::assignSamplerInStructUniformRegister(const TType &type,
                                                               const TString &name,
                                                               unsigned int *outRegisterCount)
{
    // Sampler that is a field of a uniform structure.
    ASSERT(IsSampler(type.getBasicType()));
    unsigned int registerIndex = mSamplerRegister;
    mUniformRegisterMap[std::string(name.c_str())] = registerIndex;
    unsigned int registerCount                     = type.isArray() ? type.getArraySize() : 1u;
    mSamplerRegister += registerCount;
    if (outRegisterCount)
    {
        *outRegisterCount = registerCount;
    }
    return registerIndex;
}
Example #22
0
unsigned int UniformHLSL::assignUniformRegister(const TType &type,
                                                const TString &name,
                                                unsigned int *outRegisterCount)
{
    unsigned int registerIndex = (IsSampler(type.getBasicType()) ? mSamplerRegister : mUniformRegister);

    const Uniform *uniform = findUniformByName(name);
    ASSERT(uniform);

    mUniformRegisterMap[uniform->name] = registerIndex;

    unsigned int registerCount = HLSLVariableRegisterCount(*uniform, mOutputType);

    if (gl::IsSamplerType(uniform->type))
    {
        mSamplerRegister += registerCount;
    }
    else
    {
        mUniformRegister += registerCount;
    }
    if (outRegisterCount)
    {
        *outRegisterCount = registerCount;
    }
    return registerIndex;
}
Example #23
0
TString buildArrayConstructorString(const TType& type) {
	std::stringstream constructor;
	constructor << getTypeString(translateType(&type))
				<< '[' << type.getArraySize() << ']';

	return TString(constructor.str().c_str());
}
Example #24
0
TString Std140PaddingHelper::postPaddingString(const TType &type, bool useHLSLRowMajorPacking)
{
    if (!type.isMatrix() && !type.isArray() && type.getBasicType() != EbtStruct)
    {
        return "";
    }

    int numComponents = 0;
    TStructure *structure = type.getStruct();

    if (type.isMatrix())
    {
        // This method can also be called from structureString, which does not use layout qualifiers.
        // Thus, use the method parameter for determining the matrix packing.
        //
        // Note HLSL row major packing corresponds to GL API column-major, and vice-versa, since we
        // wish to always transpose GL matrices to play well with HLSL's matrix array indexing.
        //
        const bool isRowMajorMatrix = !useHLSLRowMajorPacking;
        const GLenum glType = GLVariableType(type);
        numComponents = gl::MatrixComponentCount(glType, isRowMajorMatrix);
    }
    else if (structure)
    {
        const TString &structName = QualifiedStructNameString(*structure,
                                                              useHLSLRowMajorPacking, true);
        numComponents = mStructElementIndexes->find(structName)->second;

        if (numComponents == 0)
        {
            return "";
        }
    }
    else
    {
        const GLenum glType = GLVariableType(type);
        numComponents = gl::VariableComponentCount(glType);
    }

    TString padding;
    for (int paddingOffset = numComponents; paddingOffset < 4; paddingOffset++)
    {
        padding += "    float pad_" + next() + ";\n";
    }
    return padding;
}
Example #25
0
bool TParseContext::arraySetMaxSize(TIntermSymbol *node, TType* type, int size, bool updateFlag, TSourceLoc line)
{
    bool builtIn = false;
    TSymbol* symbol = symbolTable.find(node->getSymbol(), &builtIn);
    if (symbol == 0) {
        error(line, " undeclared identifier", node->getSymbol().c_str(), "");
        return true;
    }
    TVariable* variable = static_cast<TVariable*>(symbol);

    type->setArrayInformationType(variable->getArrayInformationType());
    variable->updateArrayInformationType(type);

    // special casing to test index value of gl_FragData. If the accessed index is >= gl_MaxDrawBuffers
    // its an error
    if (node->getSymbol() == "gl_FragData") {
        TSymbol* fragData = symbolTable.find("gl_MaxDrawBuffers", &builtIn);
        if (fragData == 0) {
            infoSink.info.message(EPrefixInternalError, "gl_MaxDrawBuffers not defined", line);
            return true;
        }

        int fragDataValue = static_cast<TVariable*>(fragData)->getConstPointer()[0].getIConst();
        if (fragDataValue <= size) {
            error(line, "", "[", "gl_FragData can only have a max array size of up to gl_MaxDrawBuffers", "");
            return true;
        }
    }

    // we dont want to update the maxArraySize when this flag is not set, we just want to include this 
    // node type in the chain of node types so that its updated when a higher maxArraySize comes in.
    if (!updateFlag)
        return false;

    size++;
    variable->getType().setMaxArraySize(size);
    type->setMaxArraySize(size);
    TType* tt = type;

    while(tt->getArrayInformationType() != 0) {
        tt = tt->getArrayInformationType();
        tt->setMaxArraySize(size);
    }

    return false;
}
Example #26
0
// Return the size and alignment of a scalar.
// The size is returned in the 'size' parameter
// Return value is the alignment of the type.
int TIntermediate::getBaseAlignmentScalar(const TType& type, int& size)
{
    switch (type.getBasicType()) {
    case EbtInt64:
    case EbtUint64:
    case EbtDouble:  size = 8; return 8;
    default:         size = 4; return 4;
    }
}
bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
{
    if (leftNodeType.isArray()) {
        TType typeWithoutArrayness = leftNodeType;
        typeWithoutArrayness.clearArrayness();

        int arraySize = leftNodeType.getArraySize();

        for (int i = 0; i < arraySize; ++i) {
            int offset = typeWithoutArrayness.getObjectSize() * i;
            if (!CompareStruct(typeWithoutArrayness, &rightUnionArray[offset], &leftUnionArray[offset]))
                return false;
        }
    } else
        return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray);

    return true;
}
Example #28
0
TString DecorateUniform(const TString &string, const TType &type)
{
    if (type.getBasicType() == EbtSamplerExternalOES)
    {
        return "ex_" + string;
    }

    return Decorate(string);
}
Example #29
0
TString DecorateUniform(const TName &name, const TType &type)
{
    if (type.getBasicType() == EbtSamplerExternalOES)
    {
        return "ex_" + name.getString();
    }

    return DecorateIfNeeded(name);
}
Example #30
0
bool TConstTraverser::visitUnary(Visit visit, TIntermUnary* node)
{
    TString buf;
    buf.append("'constructor' : assigning non-constant to ");
    buf.append(type.getCompleteString());
    infoSink.info.message(EPrefixError, node->getLine(), buf.c_str());
    error = true;
    return false;  
}