Beispiel #1
0
bool CollectVariables::visitAggregate(Visit, TIntermAggregate *node)
{
    bool visitChildren = true;

    switch (node->getOp())
    {
      case EOpDeclaration:
        {
            const TIntermSequence &sequence = *(node->getSequence());
            ASSERT(!sequence.empty());

            const TIntermTyped &typedNode = *(sequence.front()->getAsTyped());
            TQualifier qualifier = typedNode.getQualifier();

            if (typedNode.getBasicType() == EbtInterfaceBlock)
            {
                visitInfoList(sequence, mInterfaceBlocks);
                visitChildren = false;
            }
            else if (qualifier == EvqAttribute || qualifier == EvqVertexIn ||
                     qualifier == EvqFragmentOut || qualifier == EvqUniform ||
                     IsVarying(qualifier))
            {
                switch (qualifier)
                {
                  case EvqAttribute:
                  case EvqVertexIn:
                    visitInfoList(sequence, mAttribs);
                    break;
                  case EvqFragmentOut:
                    visitInfoList(sequence, mOutputVariables);
                    break;
                  case EvqUniform:
                    visitInfoList(sequence, mUniforms);
                    break;
                  default:
                    visitInfoList(sequence, mVaryings);
                    break;
                }

                visitChildren = false;
            }
            break;
        }
      default: break;
    }

    return visitChildren;
}
Beispiel #2
0
// We want to check whether a uniform/varying is statically used
// because we only count the used ones in packing computing.
// Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count
// toward varying counting if they are statically used in a fragment
// shader.
void CollectVariables::visitSymbol(TIntermSymbol *symbol)
{
    ASSERT(symbol != NULL);
    ShaderVariable *var = NULL;
    const TString &symbolName = symbol->getSymbol();

    if (IsVarying(symbol->getQualifier()))
    {
        var = FindVariable(symbolName, mVaryings);
    }
    else if (symbol->getType().getBasicType() == EbtInterfaceBlock)
    {
        UNREACHABLE();
    }
    else if (symbolName == "gl_DepthRange")
    {
        ASSERT(symbol->getQualifier() == EvqUniform);

        if (!mDepthRangeAdded)
        {
            Uniform info;
            const char kName[] = "gl_DepthRange";
            info.name = kName;
            info.mappedName = kName;
            info.type = GL_STRUCT_ANGLEX;
            info.arraySize = 0;
            info.precision = GL_NONE;
            info.staticUse = true;

            ShaderVariable nearInfo;
            const char kNearName[] = "near";
            nearInfo.name = kNearName;
            nearInfo.mappedName = kNearName;
            nearInfo.type = GL_FLOAT;
            nearInfo.arraySize = 0;
            nearInfo.precision = GL_HIGH_FLOAT;
            nearInfo.staticUse = true;

            ShaderVariable farInfo;
            const char kFarName[] = "far";
            farInfo.name = kFarName;
            farInfo.mappedName = kFarName;
            farInfo.type = GL_FLOAT;
            farInfo.arraySize = 0;
            farInfo.precision = GL_HIGH_FLOAT;
            farInfo.staticUse = true;

            ShaderVariable diffInfo;
            const char kDiffName[] = "diff";
            diffInfo.name = kDiffName;
            diffInfo.mappedName = kDiffName;
            diffInfo.type = GL_FLOAT;
            diffInfo.arraySize = 0;
            diffInfo.precision = GL_HIGH_FLOAT;
            diffInfo.staticUse = true;

            info.fields.push_back(nearInfo);
            info.fields.push_back(farInfo);
            info.fields.push_back(diffInfo);

            mUniforms->push_back(info);
            mDepthRangeAdded = true;
        }
    }
    else
    {
        switch (symbol->getQualifier())
        {
          case EvqAttribute:
          case EvqVertexIn:
            var = FindVariable(symbolName, mAttribs);
            break;
          case EvqFragmentOut:
            var = FindVariable(symbolName, mOutputVariables);
            break;
          case EvqUniform:
            {
                const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock();
                if (interfaceBlock)
                {
                    InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), mInterfaceBlocks);
                    ASSERT(namedBlock);
                    var = FindVariable(symbolName, &namedBlock->fields);

                    // Set static use on the parent interface block here
                    namedBlock->staticUse = true;
                }
                else
                {
                    var = FindVariable(symbolName, mUniforms);
                }

                // It's an internal error to reference an undefined user uniform
                ASSERT(symbolName.compare(0, 3, "gl_") != 0 || var);
            }
            break;
          case EvqFragCoord:
            if (!mFragCoordAdded)
            {
                Varying info;
                const char kName[] = "gl_FragCoord";
                info.name = kName;
                info.mappedName = kName;
                info.type = GL_FLOAT_VEC4;
                info.arraySize = 0;
                info.precision = GL_MEDIUM_FLOAT;  // Defined by spec.
                info.staticUse = true;
                info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
                mVaryings->push_back(info);
                mFragCoordAdded = true;
            }
            return;
          case EvqFrontFacing:
            if (!mFrontFacingAdded)
            {
                Varying info;
                const char kName[] = "gl_FrontFacing";
                info.name = kName;
                info.mappedName = kName;
                info.type = GL_BOOL;
                info.arraySize = 0;
                info.precision = GL_NONE;
                info.staticUse = true;
                info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
                mVaryings->push_back(info);
                mFrontFacingAdded = true;
            }
            return;
          case EvqPointCoord:
            if (!mPointCoordAdded)
            {
                Varying info;
                const char kName[] = "gl_PointCoord";
                info.name = kName;
                info.mappedName = kName;
                info.type = GL_FLOAT_VEC2;
                info.arraySize = 0;
                info.precision = GL_MEDIUM_FLOAT;  // Defined by spec.
                info.staticUse = true;
                info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
                mVaryings->push_back(info);
                mPointCoordAdded = true;
            }
            return;
          case EvqInstanceID:
            if (!mInstanceIDAdded)
            {
                Attribute info;
                const char kName[] = "gl_InstanceID";
                info.name = kName;
                info.mappedName = kName;
                info.type = GL_INT;
                info.arraySize = 0;
                info.precision = GL_HIGH_INT;  // Defined by spec.
                info.staticUse = true;
                info.location = -1;
                mAttribs->push_back(info);
                mInstanceIDAdded = true;
            }
            return;
          case EvqPosition:
            if (!mPositionAdded)
            {
                Varying info;
                const char kName[] = "gl_Position";
                info.name = kName;
                info.mappedName = kName;
                info.type = GL_FLOAT_VEC4;
                info.arraySize = 0;
                info.precision = GL_HIGH_FLOAT;  // Defined by spec.
                info.staticUse = true;
                info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
                mVaryings->push_back(info);
                mPositionAdded = true;
            }
            return;
          case EvqPointSize:
            if (!mPointSizeAdded)
            {
                Varying info;
                const char kName[] = "gl_PointSize";
                info.name = kName;
                info.mappedName = kName;
                info.type = GL_FLOAT;
                info.arraySize = 0;
                info.precision = GL_MEDIUM_FLOAT;  // Defined by spec.
                info.staticUse = true;
                info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
                mVaryings->push_back(info);
                mPointSizeAdded = true;
            }
            return;
          case EvqLastFragData:
            if (!mLastFragDataAdded)
            {
                Varying info;
                const char kName[] = "gl_LastFragData";
                info.name = kName;
                info.mappedName = kName;
                info.type = GL_FLOAT_VEC4;
                info.arraySize = static_cast<const TVariable*>(mSymbolTable.findBuiltIn("gl_MaxDrawBuffers", 100))->getConstPointer()->getIConst();
                info.precision = GL_MEDIUM_FLOAT;  // Defined by spec.
                info.staticUse = true;
                info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
                mVaryings->push_back(info);
                mLastFragDataAdded = true;
            }
            return;
          case EvqFragColor:
              if (!mFragColorAdded)
              {
                  Attribute info;
                  const char kName[] = "gl_FragColor";
                  info.name          = kName;
                  info.mappedName    = kName;
                  info.type          = GL_FLOAT_VEC4;
                  info.arraySize     = 0;
                  info.precision     = GL_MEDIUM_FLOAT;  // Defined by spec.
                  info.staticUse = true;
                  mOutputVariables->push_back(info);
                  mFragColorAdded = true;
              }
              return;
          case EvqFragData:
              if (!mFragDataAdded)
              {
                  Attribute info;
                  const char kName[] = "gl_FragData";
                  info.name          = kName;
                  info.mappedName    = kName;
                  info.type          = GL_FLOAT_VEC4;
                  info.arraySize = static_cast<const TVariable *>(
                                       mSymbolTable.findBuiltIn("gl_MaxDrawBuffers", 100))
                                       ->getConstPointer()
                                       ->getIConst();
                  info.precision = GL_MEDIUM_FLOAT;  // Defined by spec.
                  info.staticUse = true;
                  mOutputVariables->push_back(info);
                  mFragDataAdded = true;
              }
              return;
          case EvqFragDepthEXT:
              if (!mFragDepthEXTAdded)
              {
                  Attribute info;
                  const char kName[] = "gl_FragDepthEXT";
                  info.name          = kName;
                  info.mappedName    = kName;
                  info.type          = GL_FLOAT;
                  info.arraySize = 0;
                  info.precision =
                      GLVariablePrecision(static_cast<const TVariable *>(
                                              mSymbolTable.findBuiltIn("gl_FragDepthEXT", 100))
                                              ->getType());
                  info.staticUse = true;
                  mOutputVariables->push_back(info);
                  mFragDepthEXTAdded = true;
              }
              return;
          case EvqFragDepth:
              if (!mFragDepthAdded)
              {
                  Attribute info;
                  const char kName[] = "gl_FragDepth";
                  info.name          = kName;
                  info.mappedName    = kName;
                  info.type          = GL_FLOAT;
                  info.arraySize     = 0;
                  info.precision     = GL_HIGH_FLOAT;
                  info.staticUse = true;
                  mOutputVariables->push_back(info);
                  mFragDepthAdded = true;
              }
              return;

          default:
            break;
        }
    }
    if (var)
    {
        var->staticUse = true;
    }
}
Beispiel #3
0
// TODO(jmadill): This is not complete.
void TOutputVulkanGLSL::writeLayoutQualifier(TIntermTyped *variable)
{
    const TType &type = variable->getType();

    bool needsCustomLayout =
        (type.getQualifier() == EvqAttribute || type.getQualifier() == EvqFragmentOut ||
         type.getQualifier() == EvqVertexIn || IsVarying(type.getQualifier()) ||
         IsSampler(type.getBasicType()) || type.isInterfaceBlock());

    if (!NeedsToWriteLayoutQualifier(type) && !needsCustomLayout)
    {
        return;
    }

    TInfoSinkBase &out                      = objSink();
    const TLayoutQualifier &layoutQualifier = type.getLayoutQualifier();

    // This isn't super clean, but it gets the job done.
    // See corresponding code in GlslangWrapper.cpp.
    TIntermSymbol *symbol = variable->getAsSymbolNode();
    ASSERT(symbol);

    ImmutableString name      = symbol->getName();
    const char *blockStorage  = nullptr;
    const char *matrixPacking = nullptr;

    // For interface blocks, use the block name instead.  When the layout qualifier is being
    // replaced in the backend, that would be the name that's available.
    if (type.isInterfaceBlock())
    {
        const TInterfaceBlock *interfaceBlock = type.getInterfaceBlock();
        name                                  = interfaceBlock->name();
        TLayoutBlockStorage storage           = interfaceBlock->blockStorage();

        // Make sure block storage format is specified.
        if (storage != EbsStd430)
        {
            // Change interface block layout qualifiers to std140 for any layout that is not
            // explicitly set to std430.  This is to comply with GL_KHR_vulkan_glsl where shared and
            // packed are not allowed (and std140 could be used instead) and unspecified layouts can
            // assume either std140 or std430 (and we choose std140 as std430 is not yet universally
            // supported).
            storage = EbsStd140;
        }

        blockStorage = getBlockStorageString(storage);
    }

    // Specify matrix packing if necessary.
    if (layoutQualifier.matrixPacking != EmpUnspecified)
    {
        matrixPacking = getMatrixPackingString(layoutQualifier.matrixPacking);
    }

    if (needsCustomLayout)
    {
        out << "@@ LAYOUT-" << name << "(";
    }
    else
    {
        out << "layout(";
    }

    // Output the list of qualifiers already known at this stage, i.e. everything other than
    // `location` and `set`/`binding`.
    std::string otherQualifiers = getCommonLayoutQualifiers(variable);

    const char *separator = "";
    if (blockStorage)
    {
        out << separator << blockStorage;
        separator = ", ";
    }
    if (matrixPacking)
    {
        out << separator << matrixPacking;
        separator = ", ";
    }
    if (!otherQualifiers.empty())
    {
        out << separator << otherQualifiers;
    }

    out << ") ";
    if (needsCustomLayout)
    {
        out << "@@";
    }
}