bool FunctionInvocation::FunctionInvocationLessThan::operator ()(FunctionInvocation const& lhs, FunctionInvocation const& rhs) const { // Check the function names first if (lhs.getFunctionName() < rhs.getFunctionName()) return true; // Next check the return type if (lhs.getReturnType() < rhs.getReturnType()) return true; // Check the number of operands if (lhs.mOperands.size() < rhs.mOperands.size()) return true; // Now that we've gotten past the two quick tests, iterate over operands // Check the semantic and type. The operands must be in the same order as well. OperandVector::const_iterator itLHSOps = lhs.mOperands.begin(); OperandVector::const_iterator itRHSOps = rhs.mOperands.begin(); for ( ; itLHSOps != lhs.mOperands.end(), itRHSOps != rhs.mOperands.end(); ++itLHSOps, ++itRHSOps) { if (itLHSOps->getSemantic() < itRHSOps->getSemantic()) return true; if (itLHSOps->getParameter()->getType() < itRHSOps->getParameter()->getType()) return true; } return false; }
bool FunctionInvocation::FunctionInvocationCompare::operator ()(FunctionInvocation const& lhs, FunctionInvocation const& rhs) const { // Check the function names first if (lhs.getFunctionName() != rhs.getFunctionName()) return false; // Next check the return type if (lhs.getReturnType() != rhs.getReturnType()) return false; // Check the number of operands if (lhs.mOperands.size() != rhs.mOperands.size()) return false; // Now that we've gotten past the two quick tests, iterate over operands // Check the semantic and type. The operands must be in the same order as well. OperandVector::const_iterator itLHSOps = lhs.mOperands.begin(); OperandVector::const_iterator itRHSOps = rhs.mOperands.begin(); for ( ; ((itLHSOps != lhs.mOperands.end()) && (itRHSOps != rhs.mOperands.end())); ++itLHSOps, ++itRHSOps) { if (itLHSOps->getSemantic() != itRHSOps->getSemantic()) return false; GpuConstantType leftType = itLHSOps->getParameter()->getType(); GpuConstantType rightType = itRHSOps->getParameter()->getType(); if (Ogre::Root::getSingletonPtr()->getRenderSystem()->getName().find("OpenGL ES 2") != String::npos) { if (leftType == GCT_SAMPLER1D) leftType = GCT_SAMPLER2D; if (rightType == GCT_SAMPLER1D) rightType = GCT_SAMPLER2D; } // If a swizzle mask is being applied to the parameter, generate the GpuConstantType to // perform the parameter type comparison the way that the compiler will see it. if ((itLHSOps->getFloatCount(itLHSOps->getMask()) > 0) || (itRHSOps->getFloatCount(itRHSOps->getMask()) > 0)) { if (itLHSOps->getFloatCount(itLHSOps->getMask()) > 0) { leftType = (GpuConstantType)((itLHSOps->getParameter()->getType() - itLHSOps->getParameter()->getType()) + itLHSOps->getFloatCount(itLHSOps->getMask())); } if (itRHSOps->getFloatCount(itRHSOps->getMask()) > 0) { rightType = (GpuConstantType)((itRHSOps->getParameter()->getType() - itRHSOps->getParameter()->getType()) + itRHSOps->getFloatCount(itRHSOps->getMask())); } } if (leftType != rightType) return false; } // Passed all tests, they are the same return true; }
bool FunctionInvocation::FunctionInvocationLessThan::operator ()(FunctionInvocation const& lhs, FunctionInvocation const& rhs) const { // Check the function names first // Adding an exception to std::string sorting. I feel that functions beginning with an underscore should be placed before // functions beginning with an alphanumeric character. By default strings are sorted based on the ASCII value of each character. // Underscores have an ASCII value in between capital and lowercase characters. This is why the exception is needed. if (lhs.getFunctionName() < rhs.getFunctionName()) { if(rhs.getFunctionName().at(0) == '_') return false; else return true; } if (lhs.getFunctionName() > rhs.getFunctionName()) { if(lhs.getFunctionName().at(0) == '_') return true; else return false; } // Next check the return type if (lhs.getReturnType() < rhs.getReturnType()) return true; if (lhs.getReturnType() > rhs.getReturnType()) return false; // Check the number of operands if (lhs.mOperands.size() < rhs.mOperands.size()) return true; if (lhs.mOperands.size() > rhs.mOperands.size()) return false; // Now that we've gotten past the two quick tests, iterate over operands // Check the semantic and type. The operands must be in the same order as well. OperandVector::const_iterator itLHSOps = lhs.mOperands.begin(); OperandVector::const_iterator itRHSOps = rhs.mOperands.begin(); for ( ; itLHSOps != lhs.mOperands.end(), itRHSOps != rhs.mOperands.end(); ++itLHSOps, ++itRHSOps) { if (itLHSOps->getSemantic() < itRHSOps->getSemantic()) return true; if (itLHSOps->getSemantic() > itRHSOps->getSemantic()) return false; if (itLHSOps->getParameter()->getType() < itRHSOps->getParameter()->getType()) return true; if (itLHSOps->getParameter()->getType() > itRHSOps->getParameter()->getType()) return false; } return true; }
bool FunctionInvocation::FunctionInvocationLessThan::operator ()(FunctionInvocation const& lhs, FunctionInvocation const& rhs) const { // Check the function names first // Adding an exception to std::string sorting. I feel that functions beginning with an underscore should be placed before // functions beginning with an alphanumeric character. By default strings are sorted based on the ASCII value of each character. // Underscores have an ASCII value in between capital and lowercase characters. This is why the exception is needed. if (lhs.getFunctionName() < rhs.getFunctionName()) { if(rhs.getFunctionName().at(0) == '_') return false; else return true; } if (lhs.getFunctionName() > rhs.getFunctionName()) { if(lhs.getFunctionName().at(0) == '_') return true; else return false; } // Next check the return type if (lhs.getReturnType() < rhs.getReturnType()) return true; if (lhs.getReturnType() > rhs.getReturnType()) return false; // Check the number of operands if (lhs.mOperands.size() < rhs.mOperands.size()) return true; if (lhs.mOperands.size() > rhs.mOperands.size()) return false; // Now that we've gotten past the two quick tests, iterate over operands // Check the semantic and type. The operands must be in the same order as well. OperandVector::const_iterator itLHSOps = lhs.mOperands.begin(); OperandVector::const_iterator itRHSOps = rhs.mOperands.begin(); for ( ; ((itLHSOps != lhs.mOperands.end()) && (itRHSOps != rhs.mOperands.end())); ++itLHSOps, ++itRHSOps) { if (itLHSOps->getSemantic() < itRHSOps->getSemantic()) return true; if (itLHSOps->getSemantic() > itRHSOps->getSemantic()) return false; GpuConstantType leftType = itLHSOps->getParameter()->getType(); GpuConstantType rightType = itRHSOps->getParameter()->getType(); if (Ogre::Root::getSingletonPtr()->getRenderSystem()->getName().find("OpenGL ES 2") != String::npos) { if (leftType == GCT_SAMPLER1D) leftType = GCT_SAMPLER2D; if (rightType == GCT_SAMPLER1D) rightType = GCT_SAMPLER2D; } // If a swizzle mask is being applied to the parameter, generate the GpuConstantType to // perform the parameter type comparison the way that the compiler will see it. if ((itLHSOps->getFloatCount(itLHSOps->getMask()) > 0) || (itRHSOps->getFloatCount(itRHSOps->getMask()) > 0)) { if (itLHSOps->getFloatCount(itLHSOps->getMask()) > 0) { leftType = (GpuConstantType)((itLHSOps->getParameter()->getType() - itLHSOps->getParameter()->getType()) + itLHSOps->getFloatCount(itLHSOps->getMask())); } if (itRHSOps->getFloatCount(itRHSOps->getMask()) > 0) { rightType = (GpuConstantType)((itRHSOps->getParameter()->getType() - itRHSOps->getParameter()->getType()) + itRHSOps->getFloatCount(itRHSOps->getMask())); } } if (leftType < rightType) return true; if (leftType > rightType) return false; } return false; }
//----------------------------------------------------------------------- void GLSLProgramWriter::writeForwardDeclarations(std::ostream& os, Program* program) { os << "//-----------------------------------------------------------------------------" << std::endl; os << "// FORWARD DECLARATIONS" << std::endl; os << "//-----------------------------------------------------------------------------" << std::endl; StringVector forwardDecl; // holds all generated function declarations const ShaderFunctionList& functionList = program->getFunctions(); ShaderFunctionConstIterator itFunction; // Iterate over all functions in the current program (in our case this is always the main() function) for ( itFunction = functionList.begin(); itFunction != functionList.end(); ++itFunction) { Function* curFunction = *itFunction; const FunctionAtomInstanceList& atomInstances = curFunction->getAtomInstances(); FunctionAtomInstanceConstIterator itAtom = atomInstances.begin(); FunctionAtomInstanceConstIterator itAtomEnd = atomInstances.end(); // Now iterate over all function atoms for ( ; itAtom != itAtomEnd; ++itAtom) { // Skip non function invocation atoms. if ((*itAtom)->getFunctionAtomType() != FunctionInvocation::Type) continue; FunctionInvocation* pFuncInvoc = static_cast<FunctionInvocation*>(*itAtom); FunctionInvocation::OperandVector::iterator itOperator = pFuncInvoc->getOperandList().begin(); FunctionInvocation::OperandVector::iterator itOperatorEnd = pFuncInvoc->getOperandList().end(); // Start with function declaration String funcDecl = pFuncInvoc->getReturnType() + " " + pFuncInvoc->getFunctionName() + "("; // Now iterate overall operands for (; itOperator != itOperatorEnd; ) { ParameterPtr pParam = (*itOperator).getParameter(); Operand::OpSemantic opSemantic = (*itOperator).getSemantic(); int opMask = (*itOperator).getMask(); GpuConstantType gpuType = GCT_UNKNOWN; // Write the semantic in, out, inout switch(opSemantic) { case Operand::OPS_IN: funcDecl += "in "; break; case Operand::OPS_OUT: funcDecl += "out "; break; case Operand::OPS_INOUT: funcDecl += "inout "; break; default: break; } // Swizzle masks are only defined for types like vec2, vec3, vec4. if (opMask == Operand::OPM_ALL) { gpuType = pParam->getType(); } else { // Now we have to convert the mask to operator gpuType = Operand::getGpuConstantType(opMask); } // We need a valid type otherwise glsl compilation will not work if (gpuType == GCT_UNKNOWN) { OGRE_EXCEPT( Exception::ERR_INTERNAL_ERROR, "Can not convert Operand::OpMask to GpuConstantType", "GLSLProgramWriter::writeForwardDeclarations" ); } // Write the operand type. funcDecl += mGpuConstTypeMap[gpuType]; ++itOperator; //move over all operators with indirection while ((itOperator != itOperatorEnd) && (itOperator->getIndirectionLevel() != 0)) { ++itOperator; } // Prepare for the next operand if (itOperator != itOperatorEnd) { funcDecl += ", "; } } // Write function call closer. funcDecl += ");\n"; // Push the generated declaration into the vector // duplicate declarations will be removed later. forwardDecl.push_back(funcDecl); } } // Now remove duplicate declaration, first we have to sort the vector. std::sort(forwardDecl.begin(), forwardDecl.end()); StringVector::iterator endIt = std::unique(forwardDecl.begin(), forwardDecl.end()); // Finally write all function declarations to the shader file for (StringVector::iterator it = forwardDecl.begin(); it != endIt; it++) { os << *it; } }