static void writeAnnotatedConstructorType(A2PWriter writer, A2PType constructorType){ A2PConstructorType t = (A2PConstructorType) constructorType->theType; char *name = t->name; int nameLength = dataArraySize(name); HTHashtable hashtable = t->declaredAnnotations; HTIterator iterator = HTcreateIterator(hashtable); int nrOfAnnotations = HTsize(hashtable); HTEntry *nextAnnotation; writeByteToBuffer(writer->buffer, PDB_ANNOTATED_CONSTRUCTOR_TYPE_HEADER); printInteger(writer->buffer, nameLength); writeDataToBuffer(writer->buffer, name, nameLength); writeType(writer, t->children); writeType(writer, t->adt); printInteger(writer->buffer, nrOfAnnotations); while((nextAnnotation = HTgetNext(iterator)) != NULL){ char *label = (char*) nextAnnotation->key; int labelLength = dataArraySize(label); printInteger(writer->buffer, labelLength); writeDataToBuffer(writer->buffer, label, labelLength); writeType(writer, (A2PType) nextAnnotation->value); } }
static void writeTupleType(A2PWriter writer, A2PType tupleType){ A2PTupleType t = (A2PTupleType) tupleType->theType; A2PType *fieldTypes = t->fieldTypes; char **fieldNames = t->fieldNames; int nrOfFields = typeArraySize(fieldTypes); int hasFieldNames = (fieldNames == NULL) ? 0 : 1; int i; if(hasFieldNames == 0){ writeByteToBuffer(writer->buffer, PDB_TUPLE_TYPE_HEADER); printInteger(writer->buffer, nrOfFields); for(i = 0; i < nrOfFields; i++){ writeType(writer, t->fieldTypes[i]); } }else{ writeByteToBuffer(writer->buffer, PDB_TUPLE_TYPE_HEADER | PDB_HAS_FIELD_NAMES); printInteger(writer->buffer, nrOfFields); for(i = 0; i < nrOfFields; i++){ char *fieldName = fieldNames[i]; int fieldNameLength = dataArraySize(fieldName); writeType(writer, t->fieldTypes[i]); printInteger(writer->buffer, fieldNameLength); writeDataToBuffer(writer->buffer, fieldName, fieldNameLength); } } }
//------------------------------------------------------------ // BinaryWriter //------------------------------------------------------------ void BinaryWriter::writeString(const XCHAR * pszStr) { if (pszStr) { // Not text? append a null at the end. if (!m_pTextEncoding->isNeedConvert()) { int32 nLen = _tcslen(pszStr); writeType(nLen); write(pszStr, nLen * sizeof(XCHAR)); } else { ByteBuffer buf; m_pTextEncoding->getBytes(buf, pszStr); if (buf.getLength() > 0) { writeType(buf.getLength()); write(buf.base(), buf.getLength()); } } } else { writeType<XCHAR>(0); } }
static void writeMapType(A2PWriter writer, A2PType mapType){ A2PMapType t = (A2PMapType) mapType->theType; writeByteToBuffer(writer->buffer, PDB_MAP_TYPE_HEADER); writeType(writer, t->keyType); writeType(writer, t->valueType); }
static void writeAliasType(A2PWriter writer, A2PType aliasType){ A2PAliasType t = (A2PAliasType) aliasType->theType; char *name = t->name; int nameLength = dataArraySize(name); writeByteToBuffer(writer->buffer, PDB_ALIAS_TYPE_HEADER); printInteger(writer->buffer, nameLength); writeDataToBuffer(writer->buffer, name, nameLength); writeType(writer, t->aliased); writeType(writer, t->parametersTuple); }
static void writeConstructorType(A2PWriter writer, A2PType constructorType){ A2PConstructorType t = (A2PConstructorType) constructorType->theType; char *name = t->name; int nameLength = dataArraySize(name); writeByteToBuffer(writer->buffer, PDB_CONSTRUCTOR_TYPE_HEADER); printInteger(writer->buffer, nameLength); writeDataToBuffer(writer->buffer, name, nameLength); writeType(writer, t->children); writeType(writer, t->adt); }
static void writeRelationType(A2PWriter writer, A2PType relationType){ A2PRelationType t = (A2PRelationType) relationType->theType; writeByteToBuffer(writer->buffer, PDB_RELATION_TYPE_HEADER); writeType(writer, t->tupleType); }
static void writeSetType(A2PWriter writer, A2PType setType){ A2PSetType t = (A2PSetType) setType->theType; writeByteToBuffer(writer->buffer, PDB_SET_TYPE_HEADER); writeType(writer, t->elementType); }
static void writeListType(A2PWriter writer, A2PType listType){ A2PListType t = (A2PListType) listType->theType; writeByteToBuffer(writer->buffer, PDB_LIST_TYPE_HEADER); writeType(writer, t->elementType); }
void GlslSymbol::writeDecl (std::stringstream &out, bool local, bool skipUniform) { switch (qual) { case EqtNone: break; case EqtUniform: if (!skipUniform) out << "uniform "; break; case EqtMutableUniform: if (!local) out << "uniform "; break; case EqtConst: out << "const "; break; case EqtIn: out << "in "; break; case EqtOut: out << "out "; break; case EqtInOut: out << "inout "; break; } writeType (out, type, structPtr, precision); out << " " << (local ? mutableMangledName : mangledName); if (arraySize) out << "[" << arraySize << "]"; if (local && qual == EqtMutableUniform) out << " = " << mangledName; }
void BinWriter::writeModules(json_t *json) { // modules json_t *module_array = json_object_get(json, "modules"); bytes.writeInt((int)json_array_size(module_array)); for (UTsize i = 0; i < json_array_size(module_array); i++) { json_t *jmodule = json_array_get(module_array, i); int itype = poolJString(json_object_get(jmodule, "type")); int iname = poolJString(json_object_get(jmodule, "name")); int iversion = poolJString(json_object_get(jmodule, "version")); bytes.writeInt(itype); bytes.writeInt(iname); bytes.writeInt(iversion); // types json_t *type_array = json_object_get(jmodule, "types"); bytes.writeInt((int)json_array_size(type_array)); for (UTsize j = 0; j < json_array_size(type_array); j++) { json_t *jtype = json_array_get(type_array, j); writeType(jtype); } } }
/*! */ void BvhSettingNode::writeData(std::ostream* data_stream) const noexcept { writeType(data_stream); // Write properties zisc::write(&bvh_type_, data_stream); if (parameters_) parameters_->writeData(data_stream); }
/*! */ void CameraSettingNode::writeData(std::ostream* data_stream) const noexcept { writeType(data_stream); // Write properties zisc::write(&type_, data_stream); zisc::write(&jittering_, data_stream); if (parameters_) parameters_->writeData(data_stream); }
static void writeADTType(A2PWriter writer, A2PType adtType){ A2PAbstractDataType t = (A2PAbstractDataType) adtType->theType; char *name = t->name; int nameLength = dataArraySize(name); writeByteToBuffer(writer->buffer, PDB_ADT_TYPE_HEADER); printInteger(writer->buffer, nameLength); writeDataToBuffer(writer->buffer, name, nameLength); writeType(writer, A2PvoidType()); }
static void writeParameterType(A2PWriter writer, A2PType parameterType){ A2PParameterType t = (A2PParameterType) parameterType->theType; char *name = t->name; int nameLength = dataArraySize(name); writeByteToBuffer(writer->buffer, PDB_PARAMETER_TYPE_HEADER); printInteger(writer->buffer, nameLength); writeDataToBuffer(writer->buffer, name, nameLength); writeType(writer, t->bound); }
/*! */ void GroupObjectSettingNode::writeData(std::ostream* data_stream) const noexcept { writeType(data_stream); // Write properties { const auto& object_list = objectList(); const uint32 size = zisc::cast<uint32>(object_list.size()); zisc::write(&size, data_stream); for (const auto object : object_list) object->writeData(data_stream); } }
void HlslLinker::emitMainStart(const HlslCrossCompiler* compiler, const EGlslSymbolType retType, GlslFunction* funcMain, unsigned options, bool usePrecision, std::stringstream& preamble, const std::vector<GlslSymbol*>& constants) { preamble << "void main() {\n"; // initialize mutable uniforms with the original uniform values const unsigned n_constants = constants.size(); for (unsigned i = 0; i != n_constants; ++i) { GlslSymbol* s = constants[i]; if (s->getIsMutable()) { s->writeDecl(preamble, GlslSymbol::kWriteDeclMutableInit); preamble << ";\n"; } } std::string arrayInit = compiler->m_DeferredArrayInit.str(); if (!arrayInit.empty()) { const bool emit_120_arrays = (m_Target >= ETargetGLSL_120); const bool emit_old_arrays = !emit_120_arrays || (options & ETranslateOpEmitGLSL120ArrayInitWorkaround); const bool emit_both = emit_120_arrays && emit_old_arrays; if (emit_both) preamble << "#if defined(HLSL2GLSL_ENABLE_ARRAY_120_WORKAROUND)" << std::endl; preamble << arrayInit; if (emit_both) preamble << "\n#endif" << std::endl; } std::string matrixInit = compiler->m_DeferredMatrixInit.str(); if (!matrixInit.empty()) { preamble << matrixInit; } if (retType == EgstStruct) { GlslStruct* retStruct = funcMain->getStruct(); assert(retStruct); preamble << " " << retStruct->getName() << " xl_retval;\n"; } else if (retType != EgstVoid) { preamble << " "; writeType (preamble, retType, NULL, usePrecision?funcMain->getPrecision():EbpUndefined); preamble << " xl_retval;\n"; } }
void HlslLinker::emitOutputNonStructParam(GlslSymbol* sym, EShLanguage lang, bool usePrecision, EAttribSemantic attrSem, std::stringstream& varying, std::stringstream& preamble, std::stringstream& postamble, std::stringstream& call) { std::string name, ctor; int pad; if (!getArgumentData( sym, lang==EShLangVertex ? EClassVarOut : EClassRes, name, ctor, pad)) { //should deal with fall through cases here assert(0); infoSink.info << "Unsupported type for shader entry parameter ("; infoSink.info << getTypeString(sym->getType()) << ")\n"; return; } // For "inout" parameters, the preamble was already written so no need to do it here. if (sym->getQualifier() != EqtInOut) { preamble << " "; // UNITY CUSTOM: for vprog output with position semantic - force highp TPrecision prec = usePrecision ? sym->getPrecision() : EbpUndefined; if(sym->hasSemantic() && usePrecision) { const char* str = sym->getSemantic().c_str(); int len = sym->getSemantic().length(); extern bool IsPositionSemantics(const char* sem, int len); if(IsPositionSemantics(str, len)) prec = EbpHigh; } writeType (preamble, sym->getType(), NULL,prec); preamble << " xlt_" << sym->getName() << ";\n"; } // In vertex shader, add to varyings if (lang == EShLangVertex) AddVertexOutput (varying, m_Target, sym->getPrecision(), ctor, name); call << "xlt_" << sym->getName(); postamble << " "; postamble << name << " = "; emitSymbolWithPad (postamble, ctor, "xlt_"+sym->getName(), pad); postamble << ";\n"; }
void writeConstantConstructor( std::stringstream& out, EGlslSymbolType t, TPrecision prec, TIntermConstant *c, GlslStruct *structure = 0 ) { unsigned n_elems = getElements(t); bool construct = n_elems > 1 || structure != 0; if (construct) { writeType (out, t, structure, EbpUndefined); out << "("; } if (structure) { // compound type unsigned n_members = structure->memberCount(); for (unsigned i = 0; i != n_members; ++i) { const GlslStruct::member &m = structure->getMember(i); if (construct && i > 0) out << ", "; writeConstantConstructor (out, m.type, m.precision, c); } } else { // simple type unsigned n_constants = c->getCount(); for (unsigned i = 0; i != n_elems; ++i) { unsigned v = Min(i, n_constants - 1); if (construct && i > 0) out << ", "; switch (c->getBasicType()) { case EbtBool: out << (c->toBool(v) ? "true" : "false"); break; case EbtInt: out << c->toInt(v); break; case EbtFloat: GlslSymbol::writeFloat(out, c->toFloat(v)); break; default: assert(0); } } } if (construct) out << ")"; }
std::string GlslFunction::getPrototype() const { std::stringstream out; writeType (out, returnType, structPtr, precision); out << " " << name << "( "; for (std::vector<GlslSymbol*>::const_iterator it = parameters.begin(), itEnd = parameters.end(); it != itEnd; ++it) { if (it != parameters.begin()) out << ", "; (*it)->writeDecl(out,GlslSymbol::kWriteDeclDefault); } out << " )"; return out.str(); }
void TypeObjectGenerator::extract(const QString &data) { QDir().mkpath(m_dst); QMap<QString, QList<GeneratorTypes::TypeStruct> > types = extractTypes(data, "object", QString(), "types"); QMapIterator<QString, QList<GeneratorTypes::TypeStruct> > i(types); while(i.hasNext()) { i.next(); const QString &name = i.key(); const QList<GeneratorTypes::TypeStruct> &types = i.value(); writeType(name, types); } writePri(types.keys()); writeMainHeader(types.keys()); writeQmlRegister(types.keys()); copyEmbeds(); }
static void writeAnnotatedNodeType(A2PWriter writer, A2PType nodeType){ A2PNodeType t = (A2PNodeType) nodeType->theType; HTHashtable hashtable = t->declaredAnnotations; HTIterator iterator = HTcreateIterator(hashtable); int nrOfAnnotations = HTsize(hashtable); HTEntry *nextAnnotation; writeByteToBuffer(writer->buffer, PDB_ANNOTATED_NODE_TYPE_HEADER); printInteger(writer->buffer, nrOfAnnotations); while((nextAnnotation = HTgetNext(iterator)) != NULL){ char *label = (char*) nextAnnotation->key; int labelLength = dataArraySize(label); printInteger(writer->buffer, labelLength); writeDataToBuffer(writer->buffer, label, labelLength); writeType(writer, (A2PType) nextAnnotation->value); } }
void HlslLinker::emitInputNonStructParam(GlslSymbol* sym, EShLanguage lang, bool usePrecision, EAttribSemantic attrSem, std::stringstream& attrib, std::stringstream& varying, std::stringstream& preamble, std::stringstream& call) { std::string name, ctor; int pad; if (!getArgumentData (sym, lang==EShLangVertex ? EClassAttrib : EClassVarIn, name, ctor, pad)) { // should deal with fall through cases here assert(0); infoSink.info << "Unsupported type for shader entry parameter ("; infoSink.info << getTypeString(sym->getType()) << ")\n"; return; } // In fragment shader, pass zero for POSITION inputs if (lang == EShLangFragment && attrSem == EAttrSemPosition) { call << ctor << "(0.0)"; return; // noting more to do } // For "in" parameters, just call directly to the main else if ( sym->getQualifier() != EqtInOut ) { emitSymbolWithPad (call, ctor, name, pad); } // For "inout" parameters, declare a temp and initialize it else { preamble << " "; writeType (preamble, sym->getType(), NULL, usePrecision?sym->getPrecision():EbpUndefined); preamble << " xlt_" << sym->getName() << " = "; emitSymbolWithPad (preamble, ctor, name, pad); preamble << ";\n"; } if (!sym->outputSuppressedBy()) emitSingleInputVariable (lang, m_Target, name, ctor, sym->getType(), sym->getPrecision(), attrib, varying); }
std::string GlslStruct::getDecl() const { std::stringstream out; out << "struct " << name << " {\n"; for (std::vector<member>::const_iterator it = memberList.begin(); it != memberList.end(); it++) { out << " "; writeType (out, it->type, it->structType, it->precision); out << " " << it->name; if (it->arraySize > 0) out << "[" << it->arraySize << "]"; out << ";\n"; } out << "};\n"; return out.str(); }
/* * Writes the stub implementation */ void generateStubImpl(const QString &idl, const QString &header, const QString & /*headerBase*/, const QString &filename, QDomElement de) { QFile impl(filename); if(!impl.open(IO_WriteOnly)) qFatal("Could not write to %s", filename.latin1()); QTextStream str(&impl); str << "/****************************************************************************" << endl; str << "**" << endl; str << "** DCOP Stub Implementation created by dcopidl2cpp from " << idl << endl; str << "**" << endl; str << "** WARNING! All changes made in this file will be lost!" << endl; str << "**" << endl; str << "*****************************************************************************/" << endl; str << endl; str << "#include \"" << header << "\"" << endl; str << "#include <dcopclient.h>" << endl << endl; str << "#include <qdatastream.h>" << endl; QDomElement e = de.firstChild().toElement(); for(; !e.isNull(); e = e.nextSibling().toElement()) { if(e.tagName() != "CLASS") continue; QDomElement n = e.firstChild().toElement(); Q_ASSERT(n.tagName() == "NAME"); QString classNameBase = n.firstChild().toText().data(); QString className_stub = classNameBase + "_stub"; QString classNameFull = className_stub; // class name with possible namespaces prepended // namespaces will be removed from className now int namespace_count = 0; QString namespace_tmp = className_stub; str << endl; for(;;) { int pos = namespace_tmp.find("::"); if(pos < 0) { className_stub = namespace_tmp; break; } str << "namespace " << namespace_tmp.left(pos) << " {" << endl; ++namespace_count; namespace_tmp = namespace_tmp.mid(pos + 2); } str << endl; // Write constructors str << className_stub << "::" << className_stub << "( const QCString& app, const QCString& obj )" << endl; str << " : "; // Always explicitly call DCOPStub constructor, because it's virtual base class. // Calling other ones doesn't matter, as they don't do anything important. str << "DCOPStub( app, obj )" << endl; str << "{" << endl; str << "}" << endl << endl; str << className_stub << "::" << className_stub << "( DCOPClient* client, const QCString& app, const QCString& obj )" << endl; str << " : "; str << "DCOPStub( client, app, obj )" << endl; str << "{" << endl; str << "}" << endl << endl; str << className_stub << "::" << className_stub << "( const DCOPRef& ref )" << endl; str << " : "; str << "DCOPStub( ref )" << endl; str << "{" << endl; str << "}" << endl << endl; // Write marshalling code QDomElement s = e.firstChild().toElement(); for(; !s.isNull(); s = s.nextSibling().toElement()) { if(s.tagName() != "FUNC") continue; QDomElement r = s.firstChild().toElement(); Q_ASSERT(r.tagName() == "TYPE"); QString result = r.firstChild().toText().data(); bool async = result == "ASYNC"; if(async) { result = "void"; str << result << " "; } else result = writeType(str, r); r = r.nextSibling().toElement(); Q_ASSERT(r.tagName() == "NAME"); QString funcName = r.firstChild().toText().data(); str << className_stub << "::" << funcName << "("; QStringList args; QStringList argtypes; bool first = true; r = r.nextSibling().toElement(); for(; !r.isNull(); r = r.nextSibling().toElement()) { if(!first) str << ", "; else str << " "; first = false; Q_ASSERT(r.tagName() == "ARG"); QDomElement a = r.firstChild().toElement(); QString type = writeType(str, a); argtypes.append(type); args.append(QString("arg") + QString::number(args.count())); str << args.last(); } if(!first) str << " "; str << ")"; // const methods in a stub can't compile, they need to call setStatus() // if ( s.hasAttribute("qual") ) // str << " " << s.attribute("qual"); str << endl; str << "{" << endl; funcName += "("; first = true; for(QStringList::Iterator it = argtypes.begin(); it != argtypes.end(); ++it) { if(!first) funcName += ","; first = false; funcName += *it; } funcName += ")"; if(async) { str << " if ( !dcopClient() ) {" << endl; str << "\tsetStatus( CallFailed );" << endl; str << "\treturn;" << endl; str << " }" << endl; str << " QByteArray data;" << endl; if(!args.isEmpty()) { str << " QDataStream arg( data, IO_WriteOnly );" << endl; for(QStringList::Iterator args_count = args.begin(); args_count != args.end(); ++args_count) { str << " arg << " << *args_count << ";" << endl; } } str << " dcopClient()->send( app(), obj(), \"" << funcName << "\", data );" << endl; str << " setStatus( CallSucceeded );" << endl; } else { if(result != "void") { str << " " << result << " result"; if(isIntType(result)) str << " = 0"; else if(result == "float" || result == "double") str << " = 0.0"; else if(result == "bool") str << " = false"; str << ";" << endl; } str << " if ( !dcopClient() ) {" << endl; str << "\tsetStatus( CallFailed );" << endl; if(result != "void") str << "\treturn result;" << endl; else str << "\treturn;" << endl; str << " }" << endl; str << " QByteArray data, replyData;" << endl; str << " QCString replyType;" << endl; if(!args.isEmpty()) { str << " QDataStream arg( data, IO_WriteOnly );" << endl; for(QStringList::Iterator args_count = args.begin(); args_count != args.end(); ++args_count) { str << " arg << " << *args_count << ";" << endl; } } str << " if ( dcopClient()->call( app(), obj(), \"" << funcName << "\","; str << " data, replyType, replyData ) ) {" << endl; if(result != "void") { str << "\tif ( replyType == \"" << result << "\" ) {" << endl; str << "\t QDataStream _reply_stream( replyData, IO_ReadOnly );" << endl; str << "\t _reply_stream >> result;" << endl; str << "\t setStatus( CallSucceeded );" << endl; str << "\t} else {" << endl; str << "\t callFailed();" << endl; str << "\t}" << endl; } else { str << "\tsetStatus( CallSucceeded );" << endl; } str << " } else { " << endl; str << "\tcallFailed();" << endl; str << " }" << endl; if(result != "void") str << " return result;" << endl; } str << "}" << endl << endl; } for(; namespace_count > 0; --namespace_count) str << "} // namespace" << endl; str << endl; } impl.close(); }
bool TGlslOutputTraverser::traverseDeclaration(bool preVisit, TIntermDeclaration* decl, TIntermTraverser* it) { TGlslOutputTraverser* goit = static_cast<TGlslOutputTraverser*>(it); GlslFunction *current = goit->current; std::stringstream& out = current->getActiveOutput(); EGlslSymbolType symbol_type = translateType(decl->getTypePointer()); TType& type = *decl->getTypePointer(); bool emit_osx10_6_arrays = goit->m_EmitSnowLeopardCompatibleArrayInitializers && decl->containsArrayInitialization(); if (emit_osx10_6_arrays) { assert(decl->isSingleInitialization() && "Emission of multiple in-line array declarations isn't supported when running in OS X 10.6 compatible mode."); current->indent(out); out << "#if defined(OSX_SNOW_LEOPARD)" << std::endl; current->increaseDepth(); TQualifier q = type.getQualifier(); if (q == EvqConst) q = EvqTemporary; current->beginStatement(); if (q != EvqTemporary && q != EvqGlobal) out << type.getQualifierString() << " "; TIntermBinary* assign = decl->getDeclaration()->getAsBinaryNode(); TIntermSymbol* sym = assign->getLeft()->getAsSymbolNode(); TIntermSequence& init = assign->getRight()->getAsAggregate()->getSequence(); writeType(out, symbol_type, NULL, goit->m_UsePrecision ? decl->getPrecision() : EbpUndefined); out << "[" << type.getArraySize() << "] " << sym->getSymbol(); current->endStatement(); unsigned n_vals = init.size(); for (unsigned i = 0; i != n_vals; ++i) { current->beginStatement(); sym->traverse(goit); out << "[" << i << "]" << " = "; init[i]->traverse(goit); current->endStatement(); } current->decreaseDepth(); current->indent(out); out << "#else" << std::endl; current->increaseDepth(); } current->beginStatement(); if (type.getQualifier() != EvqTemporary && type.getQualifier() != EvqGlobal) out << type.getQualifierString() << " "; if (type.getBasicType() == EbtStruct) out << type.getTypeName(); else writeType(out, symbol_type, NULL, goit->m_UsePrecision ? decl->getPrecision() : EbpUndefined); if (type.isArray()) out << "[" << type.getArraySize() << "]"; out << " "; decl->getDeclaration()->traverse(goit); current->endStatement(); if (emit_osx10_6_arrays) { current->decreaseDepth(); current->indent(out); out << "#endif" << std::endl; } return false; }
bool HlslLinker::link(HlslCrossCompiler* compiler, const char* entryFunc, ETargetVersion targetVersion, unsigned options) { m_Target = targetVersion; m_Options = options; m_Extensions.clear(); if (!linkerSanityCheck(compiler, entryFunc)) return false; const bool usePrecision = Hlsl2Glsl_VersionUsesPrecision(targetVersion); EShLanguage lang = compiler->getLanguage(); std::string entryPoint = GetEntryName (entryFunc); // figure out all relevant functions GlslFunction* globalFunction = NULL; std::vector<GlslFunction*> functionList; FunctionSet calledFunctions; GlslFunction* funcMain = NULL; if (!buildFunctionLists(compiler, lang, entryPoint, globalFunction, functionList, calledFunctions, funcMain)) return false; assert(globalFunction); assert(funcMain); // uniforms and used built-in functions std::vector<GlslSymbol*> constants; std::set<TOperator> libFunctions; buildUniformsAndLibFunctions(calledFunctions, constants, libFunctions); // add built-in functions possibly used by uniform initializers const std::set<TOperator>& referencedGlobalFunctions = globalFunction->getLibFunctions(); libFunctions.insert (referencedGlobalFunctions.begin(), referencedGlobalFunctions.end()); buildUniformReflection (constants); // print all the components collected above. emitLibraryFunctions (libFunctions, lang, usePrecision); emitStructs(compiler); emitGlobals (globalFunction, constants); EmitCalledFunctions (shader, calledFunctions); // Generate a main function that calls the specified entrypoint. // That main function uses semantics on the arguments and return values to // connect items appropriately. std::stringstream attrib; std::stringstream uniform; std::stringstream preamble; std::stringstream postamble; std::stringstream varying; std::stringstream call; markDuplicatedInSemantics(funcMain); // Declare return value const EGlslSymbolType retType = funcMain->getReturnType(); emitMainStart(compiler, retType, funcMain, m_Options, usePrecision, preamble, constants); // Call the entry point call << " "; if (retType != EgstVoid) call << "xl_retval = "; call << funcMain->getName() << "( "; // Entry point parameters const int pCount = funcMain->getParameterCount(); for (int ii=0; ii<pCount; ii++) { GlslSymbol *sym = funcMain->getParameter(ii); EAttribSemantic attrSem = parseAttributeSemantic( sym->getSemantic()); add_extension_from_semantic(attrSem, m_Target, m_Extensions); switch (sym->getQualifier()) { // -------- IN & OUT parameters case EqtIn: case EqtInOut: case EqtConst: if (sym->getType() != EgstStruct) { emitInputNonStructParam(sym, lang, usePrecision, attrSem, attrib, varying, preamble, call); } else { emitInputStructParam(sym, lang, attrib, varying, preamble, call); } // NOTE: for "inout" parameters need to fallthrough to the next case if (sym->getQualifier() != EqtInOut) { break; } // -------- OUT parameters; also fall-through for INOUT (see the check above) case EqtOut: if ( sym->getType() != EgstStruct) { emitOutputNonStructParam(sym, lang, usePrecision, attrSem, varying, preamble, postamble, call); } else { emitOutputStructParam(sym, lang, usePrecision, attrSem, varying, preamble, postamble, call); } break; case EqtUniform: uniform << "uniform "; writeType (uniform, sym->getType(), NULL, usePrecision?sym->getPrecision():EbpUndefined); uniform << " xlu_" << sym->getName(); if(sym->getArraySize()) uniform << "[" << sym->getArraySize() << "]"; uniform << ";\n"; call << "xlu_" << sym->getName(); break; default: assert(0); }; if (ii != pCount -1) call << ", "; } call << ");\n"; // Entry point return value if (!emitReturnValue(retType, funcMain, lang, varying, postamble)) return false; postamble << "}\n\n"; // Generate final code of the pieces above. { shaderPrefix << kTargetVersionStrings[targetVersion]; ExtensionSet::const_iterator it = m_Extensions.begin(), end = m_Extensions.end(); for (; it != end; ++it) shaderPrefix << "#extension " << *it << " : require" << std::endl; } EmitIfNotEmpty (shader, uniform); EmitIfNotEmpty (shader, attrib); EmitIfNotEmpty (shader, varying); shader << preamble.str() << "\n"; shader << call.str() << "\n"; shader << postamble.str() << "\n"; return true; }
void restore() { writeType(address, original); }
void patch() { writeType(address, replaced); }
bool HlslLinker::link(HlslCrossCompiler* compiler, const char* entryFunc, bool usePrecision) { std::vector<GlslFunction*> globalList; std::vector<GlslFunction*> functionList; std::string entryPoint; GlslFunction* funcMain = NULL; FunctionSet calledFunctions; std::set<TOperator> libFunctions; std::map<std::string,GlslSymbol*> globalSymMap; std::map<std::string,GlslStruct*> structMap; if (!compiler) { infoSink.info << "No shader compiler provided\n"; return false; } EShLanguage lang = compiler->getLanguage(); if (!entryFunc) { infoSink.info << "No shader entry function provided\n"; return false; } entryPoint = GetEntryName (entryFunc); //build the list of functions HlslCrossCompiler *comp = static_cast<HlslCrossCompiler*>(compiler); std::vector<GlslFunction*> &fl = comp->functionList; for ( std::vector<GlslFunction*>::iterator fit = fl.begin(); fit < fl.end(); fit++) { if ( (*fit)->getName() == "__global__") globalList.push_back( *fit); else functionList.push_back( *fit); if ((*fit)->getName() == entryPoint) { if (funcMain) { infoSink.info << kShaderTypeNames[lang] << " entry function cannot be overloaded\n"; return false; } funcMain = *fit; } } // check to ensure that we found the entry function if (!funcMain) { infoSink.info << "Failed to find entry function: '" << entryPoint <<"'\n"; return false; } //add all the called functions to the list calledFunctions.push_back (funcMain); if (!addCalledFunctions (funcMain, calledFunctions, functionList)) { infoSink.info << "Failed to resolve all called functions in the " << kShaderTypeNames[lang] << " shader\n"; } //iterate over the functions, building a global list of structure declaractions and symbols // assume a single compilation unit for expediency (eliminates name clashes, as type checking // withing a single compilation unit has been performed) for (FunctionSet::iterator it=calledFunctions.begin(); it != calledFunctions.end(); it++) { //get each symbol and each structure, and add them to the map // checking that any previous entries are equivalent const std::vector<GlslSymbol*> &symList = (*it)->getSymbols(); for (std::vector<GlslSymbol*>::const_iterator cit = symList.begin(); cit < symList.end(); cit++) { if ( (*cit)->getIsGlobal()) { //should check for already added ones here globalSymMap[(*cit)->getName()] = *cit; } } //take each referenced library function, and add it to the set const std::set<TOperator> &libSet = (*it)->getLibFunctions(); libFunctions.insert( libSet.begin(), libSet.end()); } // The following code is what is used to generate the actual shader and "main" // function. The process is to take all the components collected above, and // write them to the appropriate code stream. Finally, a main function is // generated that calls the specified entrypoint. That main function uses // semantics on the arguments and return values to connect items appropriately. // // Write Library Functions & required extensions std::string shaderExtensions, shaderLibFunctions; if (!libFunctions.empty()) { for (std::set<TOperator>::iterator it = libFunctions.begin(); it != libFunctions.end(); it++) { const std::string &func = getHLSLSupportCode(*it, shaderExtensions, lang==EShLangVertex); if (!func.empty()) { shaderLibFunctions += func; shaderLibFunctions += '\n'; } } } shader << shaderExtensions; shader << shaderLibFunctions; // //Structure addition hack // Presently, structures are not tracked per function, just dump them all // This could be improved by building a complete list of structures for the // shaders based on the variables in each function // { HlslCrossCompiler *comp = static_cast<HlslCrossCompiler*>(compiler); std::vector<GlslStruct*> &sList = comp->structList; if (!sList.empty()) { for (std::vector<GlslStruct*>::iterator it = sList.begin(); it < sList.end(); it++) { shader << (*it)->getDecl() << "\n"; } } } // // Write global variables // if (!globalSymMap.empty()) { for (std::map<std::string,GlslSymbol*>::iterator sit = globalSymMap.begin(); sit != globalSymMap.end(); sit++) { sit->second->writeDecl(shader,false,false); shader << ";\n"; if ( sit->second->getIsMutable() ) { sit->second->writeDecl(shader, true, false); shader << ";\n"; } } } // // Write function declarations and definitions // EmitCalledFunctions (shader, calledFunctions); // // Gather the uniforms into the uniform list // for (std::map<std::string, GlslSymbol*>::iterator it = globalSymMap.begin(); it != globalSymMap.end(); it++) { if (it->second->getQualifier() != EqtUniform) continue; ShUniformInfo infoStruct; infoStruct.name = new char[it->first.size()+1]; strcpy( infoStruct.name, it->first.c_str()); if (it->second->getSemantic() != "") { infoStruct.semantic = new char[it->second->getSemantic().size()+1]; strcpy( infoStruct.semantic, it->second->getSemantic().c_str()); } else infoStruct.semantic = 0; //gigantic hack, the enumerations are kept in alignment infoStruct.type = (EShType)it->second->getType(); infoStruct.arraySize = it->second->getArraySize(); if ( it->second->hasInitializer() ) { int initSize = it->second->initializerSize(); infoStruct.init = new float[initSize]; memcpy( infoStruct.init, it->second->getInitializer(), sizeof(float) * initSize); } else infoStruct.init = 0; //TODO: need to add annotation uniforms.push_back( infoStruct); } // // Generate the main function // std::stringstream attrib; std::stringstream uniform; std::stringstream preamble; std::stringstream postamble; std::stringstream varying; std::stringstream call; const int pCount = funcMain->getParameterCount(); preamble << "void main() {\n"; const EGlslSymbolType retType = funcMain->getReturnType(); GlslStruct *retStruct = funcMain->getStruct(); if ( retType == EgstStruct) { assert(retStruct); preamble << " " << retStruct->getName() << " xl_retval;\n"; } else { if ( retType != EgstVoid) { preamble << " "; writeType (preamble, retType, NULL, usePrecision?funcMain->getPrecision():EbpUndefined); preamble << " xl_retval;\n"; } } // Write all mutable initializations if ( calledFunctions.size() > 0 ) { for (FunctionSet::iterator fit = calledFunctions.begin(); fit != calledFunctions.end(); fit++) { std::string mutableDecls = (*fit)->getMutableDecls(1, calledFunctions.begin(), fit); if ( mutableDecls.size() > 0 ) { preamble << mutableDecls; } } } call << " "; if (retType != EgstVoid) call << "xl_retval = " << funcMain->getName() << "( "; else call << funcMain->getName() << "( "; // pass main function parameters for (int ii=0; ii<pCount; ii++) { GlslSymbol *sym = funcMain->getParameter(ii); EAttribSemantic attrSem = parseAttributeSemantic( sym->getSemantic()); switch (sym->getQualifier()) { // -------- IN & OUT parameters case EqtIn: case EqtInOut: if ( sym->getType() != EgstStruct) { std::string name, ctor; int pad; if ( getArgumentData( sym, lang==EShLangVertex ? EClassAttrib : EClassVarIn, name, ctor, pad) ) { // In fragment shader, pass zero for POSITION inputs bool ignoredPositionInFragment = false; if (lang == EShLangFragment && attrSem == EAttrSemPosition) { call << ctor << "(0.0)"; ignoredPositionInFragment = true; } // For "in" parameters, just call directly to the main else if ( sym->getQualifier() != EqtInOut ) { call << ctor << "(" << name; for (int ii = 0; ii<pad; ii++) call << ", 0.0"; call << ")"; } // For "inout" parameters, declare a temp and initialize the temp else { preamble << " "; writeType (preamble, sym->getType(), NULL, usePrecision?sym->getPrecision():EbpUndefined); preamble << " xlt_" << sym->getName() << " = "; preamble << ctor << "(" << name; for (int ii = 0; ii<pad; ii++) preamble << ", 0.0"; preamble << ");\n"; } if (lang == EShLangVertex) // vertex shader: deal with gl_ attributes { if ( strncmp( name.c_str(), "gl_", 3)) { int typeOffset = 0; // If the type is integer or bool based, we must convert to a float based // type. This is because GLSL does not allow int or bool based vertex attributes. if ( sym->getType() >= EgstInt && sym->getType() <= EgstInt4) { typeOffset += 4; } if ( sym->getType() >= EgstBool && sym->getType() <= EgstBool4) { typeOffset += 8; } // This is an undefined attribute attrib << "attribute " << getTypeString((EGlslSymbolType)(sym->getType() + typeOffset)) << " " << name << ";\n"; } } if (lang == EShLangFragment) // deal with varyings { if (!ignoredPositionInFragment) AddToVaryings (varying, sym->getPrecision(), ctor, name); } } else { //should deal with fall through cases here assert(0); infoSink.info << "Unsupported type for shader entry parameter ("; infoSink.info << getTypeString(sym->getType()) << ")\n"; } } else { //structs must pass the struct, then process per element GlslStruct *Struct = sym->getStruct(); assert(Struct); //first create the temp std::string tempVar = "xlt_" + sym->getName(); preamble << " " << Struct->getName() << " "; preamble << tempVar <<";\n"; call << tempVar; const int elem = Struct->memberCount(); for (int jj=0; jj<elem; jj++) { const GlslStruct::member ¤t = Struct->getMember(jj); EAttribSemantic memberSem = parseAttributeSemantic (current.semantic); std::string name, ctor; int pad; int numArrayElements = 1; bool bIsArray = false; // If it is an array, loop over each member if ( current.arraySize > 0 ) { numArrayElements = current.arraySize; bIsArray = true; } for ( int arrayIndex = 0; arrayIndex < numArrayElements; arrayIndex++ ) { if ( getArgumentData2( current.name, current.semantic, current.type, lang==EShLangVertex ? EClassAttrib : EClassVarIn, name, ctor, pad, arrayIndex ) ) { preamble << " "; preamble << tempVar << "." << current.name; if ( bIsArray ) preamble << "[" << arrayIndex << "]"; // In fragment shader, pass zero for POSITION inputs bool ignoredPositionInFragment = false; if (lang == EShLangFragment && memberSem == EAttrSemPosition) { preamble << " = " << ctor << "(0.0);\n"; ignoredPositionInFragment = true; } else { preamble << " = " << ctor << "( " << name; for (int ii = 0; ii<pad; ii++) preamble << ", 0.0"; preamble << ");\n"; } if (lang == EShLangVertex) // vertex shader: gl_ attributes { if ( strncmp( name.c_str(), "gl_", 3)) { int typeOffset = 0; // If the type is integer or bool based, we must convert to a float based // type. This is because GLSL does not allow int or bool based vertex attributes. if ( current.type >= EgstInt && current.type <= EgstInt4) { typeOffset += 4; } if ( current.type >= EgstBool && current.type <= EgstBool4) { typeOffset += 8; } // This is an undefined attribute attrib << "attribute " << getTypeString((EGlslSymbolType)(current.type + typeOffset)) << " " << name << ";\n"; } } if (lang == EShLangFragment) // deal with varyings { if (!ignoredPositionInFragment) AddToVaryings (varying, current.precision, ctor, name); } } else { //should deal with fall through cases here assert(0); infoSink.info << "Unsupported type for struct element in shader entry parameter ("; infoSink.info << getTypeString(current.type) << ")\n"; } } } } // // NOTE: This check only breaks out of the case if we have an "in" parameter, for // "inout" it will fallthrough to the next case // if ( sym->getQualifier() != EqtInOut ) { break; } // -------- OUT parameters; also fall-through for INOUT (see the check above) case EqtOut: if ( sym->getType() != EgstStruct) { std::string name, ctor; int pad; if ( getArgumentData( sym, lang==EShLangVertex ? EClassVarOut : EClassRes, name, ctor, pad) ) { // For "inout" parameters, the preamble was already written so no need to do it here. if ( sym->getQualifier() != EqtInOut ) { preamble << " "; writeType (preamble, sym->getType(), NULL, usePrecision?sym->getPrecision():EbpUndefined); preamble << " xlt_" << sym->getName() << ";\n"; } if (lang == EShLangVertex) // deal with varyings { AddToVaryings (varying, sym->getPrecision(), ctor, name); } call << "xlt_" << sym->getName(); postamble << " "; postamble << name << " = " << ctor << "( xlt_" <<sym->getName(); for (int ii = 0; ii<pad; ii++) postamble << ", 0.0"; postamble << ");\n"; } else { //should deal with fall through cases here assert(0); infoSink.info << "Unsupported type for shader entry parameter ("; infoSink.info << getTypeString(sym->getType()) << ")\n"; } } else { //structs must pass the struct, then process per element GlslStruct *Struct = sym->getStruct(); assert(Struct); //first create the temp std::string tempVar = "xlt_" + sym->getName(); // For "inout" parmaeters the preamble and call were already written, no need to do it here if ( sym->getQualifier() != EqtInOut ) { preamble << " " << Struct->getName() << " "; preamble << tempVar <<";\n"; call << tempVar; } const int elem = Struct->memberCount(); for (int ii=0; ii<elem; ii++) { const GlslStruct::member ¤t = Struct->getMember(ii); std::string name, ctor; int pad; if ( getArgumentData2( current.name, current.semantic, current.type, lang==EShLangVertex ? EClassVarOut : EClassRes, name, ctor, pad, 0) ) { postamble << " "; postamble << name << " = " << ctor; postamble << "( " << tempVar << "." << current.name; for (int ii = 0; ii<pad; ii++) postamble << ", 0.0"; postamble << ");\n"; if (lang == EShLangVertex) // deal with varyings { AddToVaryings (varying, current.precision, ctor, name); } } else { //should deal with fall through cases here assert(0); infoSink.info << "Unsupported type in struct element for shader entry parameter ("; infoSink.info << getTypeString(current.type) << ")\n"; } } } break; case EqtUniform: uniform << "uniform "; writeType (uniform, sym->getType(), NULL, usePrecision?sym->getPrecision():EbpUndefined); uniform << " xlu_" << sym->getName() << ";\n"; call << "xlu_" << sym->getName(); break; default: assert(0); }; if (ii != pCount -1) call << ", "; } call << ");\n"; // -------- return value of main entry point if (retType != EgstVoid) { if (retType != EgstStruct) { std::string name, ctor; int pad; if ( getArgumentData2( "", funcMain->getSemantic(), retType, lang==EShLangVertex ? EClassVarOut : EClassRes, name, ctor, pad, 0) ) { postamble << " "; postamble << name << " = " << ctor << "( xl_retval"; for (int ii = 0; ii<pad; ii++) postamble << ", 0.0"; postamble << ");\n"; if (lang == EShLangVertex) // deal with varyings { AddToVaryings (varying, funcMain->getPrecision(), ctor, name); } } else { //should deal with fall through cases here assert(0); infoSink.info << (lang==EShLangVertex ? "Unsupported type for shader return value (" : "Unsupported return type for shader entry function ("); infoSink.info << getTypeString(retType) << ")\n"; } } else { const int elem = retStruct->memberCount(); for (int ii=0; ii<elem; ii++) { const GlslStruct::member ¤t = retStruct->getMember(ii); std::string name, ctor; int pad; int numArrayElements = 1; bool bIsArray = false; if (lang == EShLangVertex) // vertex shader { // If it is an array, loop over each member if ( current.arraySize > 0 ) { numArrayElements = current.arraySize; bIsArray = true; } } for ( int arrayIndex = 0; arrayIndex < numArrayElements; arrayIndex++ ) { if ( getArgumentData2( current.name, current.semantic, current.type, lang==EShLangVertex ? EClassVarOut : EClassRes, name, ctor, pad, arrayIndex) ) { postamble << " "; postamble << name; postamble << " = " << ctor; postamble << "( xl_retval." << current.name; if ( bIsArray ) { postamble << "[" << arrayIndex << "]"; } for (int ii = 0; ii<pad; ii++) postamble << ", 0.0"; postamble << ");\n"; if (lang == EShLangVertex) // deal with varyings { AddToVaryings (varying, current.precision, ctor, name); } } else { //should deal with fall through cases here //assert(0); infoSink.info << (lang==EShLangVertex ? "Unsupported element type in struct for shader return value (" : "Unsupported struct element type in return type for shader entry function ("); infoSink.info << getTypeString(current.type) << ")\n"; return false; } } } } } else { if (lang == EShLangFragment) // fragment shader { // If no return type, close off the output postamble << ";\n"; } } postamble << "}\n\n"; EmitIfNotEmpty (shader, uniform); EmitIfNotEmpty (shader, attrib); EmitIfNotEmpty (shader, varying); shader << preamble.str() << "\n"; shader << call.str() << "\n"; shader << postamble.str() << "\n"; return true; }