Example #1
0
//----------------------------------------------------------------------------
bool FxCompiler::Process (const Program& program, InputArray& inputs,
    OutputArray& outputs, ConstantArray& constants, SamplerArray& samplers)
{
    // Variable lines are one of the following:
    //   var TYPE NAME : $vin.SEMANTIC  : inputType           : index : 1
    //   var TYPE NAME : $vout.SEMANTIC : outputType          : index : 1
    //   var TYPE NAME :                : c[REGISTER]         : index : 1
    //   var TYPE NAME :                : c[REGISTER], NUMREG : index : 1
    //   var TYPE NAME :                : texunit UNITNUMBER  : -1    : 1
    // The last field is "used", a value of "0" or "1".  However, the parser
    // stored in 'program' only those variables with a used value "1".  The
    // all-capitals identifiers are needed by the Wild Magic FX system.

    TokenArrays::const_iterator iter = program.Variables.begin();
    TokenArrays::const_iterator end = program.Variables.end();
    for (/**/; iter != end; ++iter)
    {
        const TokenArray& tokens = *iter;

        // The token array has 10 or 11 tokens.
        if (tokens.size() < 10 || tokens.size() > 11)
        {
            ReportError("Invalid number of tokens", &tokens);
            return false;
        }

        // Get the variable type.
        Shader::VariableType vartype = Shader::VT_NONE;
        Shader::SamplerType samtype = Shader::ST_NONE;
        std::string::size_type begin = tokens[1].find("sampler", 0);
        if (begin != std::string::npos)
        {
            SamplerTypeMap::iterator iter = mSamplerTypes.find(tokens[1]);
            if (iter == mSamplerTypes.end())
            {
                ReportError("Invalid sampler type", &tokens);
                return false;
            }
            samtype = iter->second;
        }
        else
        {
            VariableTypeMap::iterator iter = mVariableTypes.find(tokens[1]);
            if (iter == mVariableTypes.end())
            {
                ReportError("Invalid variable type", &tokens);
                return false;
            }
            vartype = iter->second;
        }

        // Get the variable name.
        std::string name = tokens[2];

        // Test whether the variable is a singleton or was declared as an
        // array.  If it is an array, we need to determine how many registers
        // it uses.  This requires processing variable lines with the same
        // variable index.
        bool varArray;
        begin = name.find("[", 0);
        if (begin != std::string::npos)
        {
            varArray = true;
            name = name.substr(0, begin);  // strip off "[register]"
        }
        else
        {
            varArray = false;
        }

        // Get the separator before the classifier.
        if (tokens[3] != ":")
        {
            ReportError("Expecting separator character at index 3", &tokens);
            return false;
        }

        // Get the classifier.
        begin = tokens[4].find("$vin.", 0);
        if (begin != std::string::npos)
        {
            // The variable is a shader input.
            if (!GetInput(tokens, name, vartype, inputs))
            {
                return false;
            }
            continue;
        }

        begin = tokens[4].find("$vout.", 0);
        if (begin != std::string::npos)
        {
            // The variable is a shader output.
            if (!GetOutput(tokens, name, vartype, outputs))
            {
                return false;
            }
            continue;
        }

        if (tokens[4] == ":")
        {
            begin = tokens[1].find("sampler", 0);
            if (begin != std::string::npos)
            {
                // The variable is a shader sampler.
                if (!GetSampler(tokens, name, samtype, samplers))
                {
                    return false;
                }
            }
            else
            {
                // The variable is a shader constant.
                if (varArray)
                {
                    if (constants.size() > 0 && name == constants.back().Name)
                    {
                        // This is another occurrence of the array variable.
                        // Just increment the register count.
                        ++constants.back().NumRegistersUsed;
                    }
                    else
                    {
                        // Create the constant with the first occurrence of
                        // the array variable.
                        if (!GetConstant(tokens, name, vartype, constants))
                        {
                            return false;
                        }
                    }
                }
                else
                {
                    if (!GetConstant(tokens, name, vartype, constants))
                    {
                        return false;
                    }
                }
            }
            continue;
        }

        ReportError("Failed to find classifier", &tokens);
        return false;
    }

    return true;
}