void VaryingPacking::enableBuiltins(ShaderType shaderType,
                                    const ProgramD3DMetadata &programMetadata)
{
    int majorShaderModel = programMetadata.getRendererMajorShaderModel();
    bool position        = programMetadata.usesTransformFeedbackGLPosition();
    bool fragCoord       = programMetadata.usesFragCoord();
    bool pointCoord = shaderType == SHADER_VERTEX ? programMetadata.addsPointCoordToVertexShader()
                                                  : programMetadata.usesPointCoord();
    bool pointSize                  = programMetadata.usesSystemValuePointSize();
    bool hlsl4                      = (majorShaderModel >= 4);
    const std::string &userSemantic = GetVaryingSemantic(majorShaderModel, pointSize);

    unsigned int reservedSemanticIndex = getMaxSemanticIndex();

    BuiltinInfo *builtins = &mBuiltinInfo[shaderType];

    if (hlsl4)
    {
        builtins->dxPosition.enableSystem("SV_Position");
    }
    else if (shaderType == SHADER_PIXEL)
    {
        builtins->dxPosition.enableSystem("VPOS");
    }
    else
    {
        builtins->dxPosition.enableSystem("POSITION");
    }

    if (position)
    {
        builtins->glPosition.enable(userSemantic, reservedSemanticIndex++);
    }

    if (fragCoord)
    {
        builtins->glFragCoord.enable(userSemantic, reservedSemanticIndex++);
    }

    if (pointCoord)
    {
        // SM3 reserves the TEXCOORD semantic for point sprite texcoords (gl_PointCoord)
        // In D3D11 we manually compute gl_PointCoord in the GS.
        if (hlsl4)
        {
            builtins->glPointCoord.enable(userSemantic, reservedSemanticIndex++);
        }
        else
        {
            builtins->glPointCoord.enable("TEXCOORD", 0);
        }
    }

    // Special case: do not include PSIZE semantic in HLSL 3 pixel shaders
    if (pointSize && (shaderType != SHADER_PIXEL || hlsl4))
    {
        builtins->glPointSize.enableSystem("PSIZE");
    }
}
void DynamicHLSL::generateVaryingHLSL(const VaryingPacking &varyingPacking,
                                      std::stringstream &hlslStream) const
{
    std::string varyingSemantic =
        GetVaryingSemantic(mRenderer->getMajorShaderModel(), varyingPacking.usesPointSize());

    for (const PackedVaryingRegister &registerInfo : varyingPacking.getRegisterList())
    {
        const auto &varying = *registerInfo.packedVarying->varying;
        ASSERT(!varying.isStruct());

        // TODO: Add checks to ensure D3D interpolation modifiers don't result in too many
        // registers being used.
        // For example, if there are N registers, and we have N vec3 varyings and 1 float
        // varying, then D3D will pack them into N registers.
        // If the float varying has the 'nointerpolation' modifier on it then we would need
        // N + 1 registers, and D3D compilation will fail.

        switch (registerInfo.packedVarying->interpolation)
        {
            case sh::INTERPOLATION_SMOOTH:
                hlslStream << "    ";
                break;
            case sh::INTERPOLATION_FLAT:
                hlslStream << "    nointerpolation ";
                break;
            case sh::INTERPOLATION_CENTROID:
                hlslStream << "    centroid ";
                break;
            default:
                UNREACHABLE();
        }

        GLenum transposedType = gl::TransposeMatrixType(varying.type);
        GLenum componentType  = gl::VariableComponentType(transposedType);
        int columnCount = gl::VariableColumnCount(transposedType);
        hlslStream << HLSLComponentTypeString(componentType, columnCount);
        unsigned int semanticIndex = registerInfo.semanticIndex;
        hlslStream << " v" << semanticIndex << " : " << varyingSemantic << semanticIndex << ";\n";
    }
}