// // Driver calls these to create and destroy compiler objects. // ShHandle ConstructCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output, const ShBuiltInResources *resources) { TShHandleBase *base = static_cast<TShHandleBase *>(ConstructCompiler(type, spec, output)); if (base == nullptr) { return 0; } TCompiler *compiler = base->getAsCompiler(); if (compiler == nullptr) { return 0; } // Generate built-in symbol table. if (!compiler->Init(*resources)) { Destruct(base); return 0; } return base; }
const std::map<std::string, std::string> *ShGetNameHashingMap( const ShHandle handle) { TCompiler *compiler = GetCompilerFromHandle(handle); ASSERT(compiler); return &(compiler->getNameMap()); }
// // Return any compiler log of messages for the application. // const std::string &GetInfoLog(const ShHandle handle) { TCompiler *compiler = GetCompilerFromHandle(handle); ASSERT(compiler); TInfoSink &infoSink = compiler->getInfoSink(); return infoSink.info.str(); }
// // Return any object code. // const std::string &ShGetObjectCode(const ShHandle handle) { TCompiler *compiler = GetCompilerFromHandle(handle); ASSERT(compiler); TInfoSink &infoSink = compiler->getInfoSink(); return infoSink.obj.str(); }
int GetVertexShaderNumViews(const ShHandle handle) { ASSERT(handle); TShHandleBase *base = static_cast<TShHandleBase *>(handle); TCompiler *compiler = base->getAsCompiler(); ASSERT(compiler); return compiler->getNumViews(); }
const std::vector<InterfaceBlock> *GetShaderStorageBlocks(const ShHandle handle) { ASSERT(handle); TShHandleBase *base = static_cast<TShHandleBase *>(handle); TCompiler *compiler = base->getAsCompiler(); ASSERT(compiler); return &compiler->getShaderStorageBlocks(); }
const std::vector<Varying> *GetOutputVaryings(const ShHandle handle) { TCompiler *compiler = GetCompilerFromHandle(handle); if (compiler == nullptr) { return nullptr; } return &compiler->getOutputVaryings(); }
// // Do an actual compile on the given strings. The result is left // in the given compile object. // // Return: The return value of ShCompile is really boolean, indicating // success or failure. // bool Compile(const ShHandle handle, const char *const shaderStrings[], size_t numStrings, ShCompileOptions compileOptions) { TCompiler *compiler = GetCompilerFromHandle(handle); ASSERT(compiler); return compiler->compile(shaderStrings, numStrings, compileOptions); }
int GetGeometryShaderInvocations(const ShHandle handle) { ASSERT(handle); TShHandleBase *base = static_cast<TShHandleBase *>(handle); TCompiler *compiler = base->getAsCompiler(); ASSERT(compiler); return compiler->getGeometryShaderInvocations(); }
GLenum GetGeometryShaderOutputPrimitiveType(const ShHandle handle) { ASSERT(handle); TShHandleBase *base = static_cast<TShHandleBase *>(handle); TCompiler *compiler = base->getAsCompiler(); ASSERT(compiler); return GetGeometryShaderPrimitiveTypeEnum(compiler->getGeometryShaderOutputPrimitiveType()); }
bool HasValidGeometryShaderMaxVertices(const ShHandle handle) { ASSERT(handle); TShHandleBase *base = static_cast<TShHandleBase *>(handle); TCompiler *compiler = base->getAsCompiler(); ASSERT(compiler); return compiler->getGeometryShaderMaxVertices() >= 0; }
bool HasValidGeometryShaderOutputPrimitiveType(const ShHandle handle) { ASSERT(handle); TShHandleBase *base = static_cast<TShHandleBase *>(handle); TCompiler *compiler = base->getAsCompiler(); ASSERT(compiler); return compiler->getGeometryShaderOutputPrimitiveType() != EptUndefined; }
WorkGroupSize GetComputeShaderLocalGroupSize(const ShHandle handle) { ASSERT(handle); TShHandleBase *base = static_cast<TShHandleBase *>(handle); TCompiler *compiler = base->getAsCompiler(); ASSERT(compiler); return compiler->getComputeShaderLocalSize(); }
// // Return any compiler log of messages for the application. // void ShGetInfoLog(const ShHandle handle, char* infoLog) { if (!handle || !infoLog) return; TShHandleBase* base = static_cast<TShHandleBase*>(handle); TCompiler* compiler = base->getAsCompiler(); if (!compiler) return; TInfoSink& infoSink = compiler->getInfoSink(); strcpy(infoLog, infoSink.info.c_str()); }
// // Return any object code. // void ShGetObjectCode(const ShHandle handle, char* objCode) { if (!handle || !objCode) return; TShHandleBase* base = static_cast<TShHandleBase*>(handle); TCompiler* compiler = base->getAsCompiler(); if (!compiler) return; TInfoSink& infoSink = compiler->getInfoSink(); strcpy(objCode, infoSink.obj.c_str()); }
int GetGeometryShaderMaxVertices(const ShHandle handle) { ASSERT(handle); TShHandleBase *base = static_cast<TShHandleBase *>(handle); TCompiler *compiler = base->getAsCompiler(); ASSERT(compiler); int maxVertices = compiler->getGeometryShaderMaxVertices(); ASSERT(maxVertices >= 0); return maxVertices; }
void ShGetInfo(const ShHandle handle, ShShaderInfo pname, size_t* params) { if (!handle || !params) return; TShHandleBase* base = static_cast<TShHandleBase*>(handle); TCompiler* compiler = base->getAsCompiler(); if (!compiler) return; switch(pname) { case SH_INFO_LOG_LENGTH: *params = compiler->getInfoSink().info.size() + 1; break; case SH_OBJECT_CODE_LENGTH: *params = compiler->getInfoSink().obj.size() + 1; break; case SH_ACTIVE_UNIFORMS: *params = compiler->getUniforms().size(); break; case SH_ACTIVE_UNIFORM_MAX_LENGTH: *params = 1 + MAX_SYMBOL_NAME_LEN; break; case SH_ACTIVE_ATTRIBUTES: *params = compiler->getAttribs().size(); break; case SH_ACTIVE_ATTRIBUTE_MAX_LENGTH: *params = 1 + MAX_SYMBOL_NAME_LEN; break; case SH_VARYINGS: *params = compiler->getVaryings().size(); break; case SH_VARYING_MAX_LENGTH: *params = 1 + MAX_SYMBOL_NAME_LEN; break; case SH_MAPPED_NAME_MAX_LENGTH: // Use longer length than MAX_SHORTENED_IDENTIFIER_SIZE to // handle array and struct dereferences. *params = 1 + MAX_SYMBOL_NAME_LEN; break; case SH_NAME_MAX_LENGTH: *params = 1 + MAX_SYMBOL_NAME_LEN; break; case SH_HASHED_NAME_MAX_LENGTH: if (compiler->getHashFunction() == NULL) { *params = 0; } else { // 64 bits hashing output requires 16 bytes for hex // representation. const char HashedNamePrefix[] = HASHED_NAME_PREFIX; *params = 16 + sizeof(HashedNamePrefix); } break; case SH_HASHED_NAMES_COUNT: *params = compiler->getNameMap().size(); break; default: UNREACHABLE(); } }
// // Driver calls these to create and destroy compiler objects. // ShHandle ShConstructCompiler(ShShaderType type, ShShaderSpec spec, ShShaderOutput output, const ShBuiltInResources* resources) { TShHandleBase* base = static_cast<TShHandleBase*>(ConstructCompiler(type, spec, output)); TCompiler* compiler = base->getAsCompiler(); if (compiler == 0) return 0; // Generate built-in symbol table. if (!compiler->Init(*resources)) { ShDestruct(base); return 0; } return reinterpret_cast<void*>(base); }
// // Do an actual compile on the given strings. The result is left // in the given compile object. // // Return: The return value of ShCompile is really boolean, indicating // success or failure. // int ShCompile( const ShHandle handle, const char* const shaderStrings[], size_t numStrings, int compileOptions) { if (handle == 0) return 0; TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle); TCompiler* compiler = base->getAsCompiler(); if (compiler == 0) return 0; bool success = compiler->compile(shaderStrings, numStrings, compileOptions); return success ? 1 : 0; }
static void getVariableInfo(ShShaderInfo varType, const ShHandle handle, int index, size_t* length, int* size, ShDataType* type, char* name, char* mappedName) { if (!handle || !size || !type || !name) return; ASSERT((varType == SH_ACTIVE_ATTRIBUTES) || (varType == SH_ACTIVE_UNIFORMS)); TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle); TCompiler* compiler = base->getAsCompiler(); if (compiler == 0) return; const TVariableInfoList& varList = varType == SH_ACTIVE_ATTRIBUTES ? compiler->getAttribs() : compiler->getUniforms(); if (index < 0 || index >= static_cast<int>(varList.size())) return; const TVariableInfo& varInfo = varList[index]; if (length) *length = varInfo.name.size(); *size = varInfo.size; *type = varInfo.type; // This size must match that queried by // SH_ACTIVE_UNIFORM_MAX_LENGTH and SH_ACTIVE_ATTRIBUTE_MAX_LENGTH // in ShGetInfo, below. size_t activeUniformAndAttribLength = 1 + MAX_SYMBOL_NAME_LEN; ASSERT(checkActiveUniformAndAttribMaxLengths(handle, activeUniformAndAttribLength)); strncpy(name, varInfo.name.c_str(), activeUniformAndAttribLength); name[activeUniformAndAttribLength - 1] = 0; if (mappedName) { // This size must match that queried by // SH_MAPPED_NAME_MAX_LENGTH in ShGetInfo, below. size_t maxMappedNameLength = 1 + MAX_SYMBOL_NAME_LEN; ASSERT(checkMappedNameMaxLength(handle, maxMappedNameLength)); strncpy(mappedName, varInfo.mappedName.c_str(), maxMappedNameLength); mappedName[maxMappedNameLength - 1] = 0; } }
// // Driver calls these to create and destroy compiler objects. // ShHandle ShConstructCompiler(EShLanguage language, EShSpec spec, const TBuiltInResource* resources) { if (!InitThread()) return 0; TShHandleBase* base = static_cast<TShHandleBase*>(ConstructCompiler(language, spec)); TCompiler* compiler = base->getAsCompiler(); if (compiler == 0) return 0; // Generate built-in symbol table. if (!GenerateBuiltInSymbolTable(language, spec, *resources, compiler->getInfoSink(), compiler->getSymbolTable())) { ShDestruct(base); return 0; } return reinterpret_cast<void*>(base); }
void ShGetNameHashingEntry(const ShHandle handle, int index, char* name, char* hashedName) { if (!handle || !name || !hashedName || index < 0) return; TShHandleBase* base = static_cast<TShHandleBase*>(handle); TCompiler* compiler = base->getAsCompiler(); if (!compiler) return; const NameMap& nameMap = compiler->getNameMap(); if (index >= static_cast<int>(nameMap.size())) return; NameMap::const_iterator it = nameMap.begin(); for (int i = 0; i < index; ++i) ++it; size_t len = it->first.length() + 1; size_t max_len = 0; ShGetInfo(handle, SH_NAME_MAX_LENGTH, &max_len); if (len > max_len) { ASSERT(false); len = max_len; } strncpy(name, it->first.c_str(), len); // To be on the safe side in case the source is longer than expected. name[len - 1] = '\0'; len = it->second.length() + 1; max_len = 0; ShGetInfo(handle, SH_HASHED_NAME_MAX_LENGTH, &max_len); if (len > max_len) { ASSERT(false); len = max_len; } strncpy(hashedName, it->second.c_str(), len); // To be on the safe side in case the source is longer than expected. hashedName[len - 1] = '\0'; }
// // Do a full compile on the given strings for a single compilation unit // forming a complete stage. The result of the machine dependent compilation // is left in the provided compile object. // // Return: The return value is really boolean, indicating // success (1) or failure (0). // int ShCompile( const ShHandle handle, const char* const shaderStrings[], const int numStrings, const int* inputLengths, const EShOptimizationLevel optLevel, const TBuiltInResource* resources, int /*debugOptions*/, int defaultVersion, // use 100 for ES environment, 110 for desktop bool forwardCompatible, // give errors for use of deprecated features EShMessages messages // warnings/errors/AST; things to print out ) { // Map the generic handle to the C++ object if (handle == 0) return 0; TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle); TCompiler* compiler = base->getAsCompiler(); if (compiler == 0) return 0; compiler->infoSink.info.erase(); compiler->infoSink.debug.erase(); TIntermediate intermediate(compiler->getLanguage()); bool success = CompileDeferred(compiler, shaderStrings, numStrings, inputLengths, "", optLevel, resources, defaultVersion, ENoProfile, false, forwardCompatible, messages, intermediate); // // Call the machine dependent compiler // if (success && intermediate.getTreeRoot() && optLevel != EShOptNoGeneration) success = compiler->compile(intermediate.getTreeRoot(), intermediate.getVersion(), intermediate.getProfile()); intermediate.removeTree(); // Throw away all the temporary memory used by the compilation process. // The push was done in the CompileDeferred() call above. GetThreadPoolAllocator().pop(); return success ? 1 : 0; }
void ShGetInfo(const ShHandle handle, ShShaderInfo pname, int* params) { if (!handle || !params) return; TShHandleBase* base = static_cast<TShHandleBase*>(handle); TCompiler* compiler = base->getAsCompiler(); if (!compiler) return; switch(pname) { case SH_INFO_LOG_LENGTH: *params = compiler->getInfoSink().info.size() + 1; break; case SH_OBJECT_CODE_LENGTH: *params = compiler->getInfoSink().obj.size() + 1; break; case SH_ACTIVE_UNIFORMS: *params = compiler->getUniforms().size(); break; case SH_ACTIVE_UNIFORM_MAX_LENGTH: *params = 1 + MAX_SYMBOL_NAME_LEN; break; case SH_ACTIVE_ATTRIBUTES: *params = compiler->getAttribs().size(); break; case SH_ACTIVE_ATTRIBUTE_MAX_LENGTH: *params = 1 + MAX_SYMBOL_NAME_LEN; break; case SH_MAPPED_NAME_MAX_LENGTH: // Use longer length than MAX_SHORTENED_IDENTIFIER_SIZE to // handle array and struct dereferences. *params = 1 + MAX_SYMBOL_NAME_LEN; break; default: UNREACHABLE(); } }
void ShGetVariableInfo(const ShHandle handle, ShShaderInfo varType, int index, size_t* length, int* size, ShDataType* type, ShPrecisionType* precision, int* staticUse, char* name, char* mappedName) { if (!handle || !size || !type || !precision || !staticUse || !name) return; ASSERT((varType == SH_ACTIVE_ATTRIBUTES) || (varType == SH_ACTIVE_UNIFORMS) || (varType == SH_VARYINGS)); TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle); TCompiler* compiler = base->getAsCompiler(); if (compiler == 0) return; const TVariableInfoList& varList = varType == SH_ACTIVE_ATTRIBUTES ? compiler->getAttribs() : (varType == SH_ACTIVE_UNIFORMS ? compiler->getUniforms() : compiler->getVaryings()); if (index < 0 || index >= static_cast<int>(varList.size())) return; const TVariableInfo& varInfo = varList[index]; if (length) *length = varInfo.name.size(); *size = varInfo.size; *type = varInfo.type; switch (varInfo.precision) { case EbpLow: *precision = SH_PRECISION_LOWP; break; case EbpMedium: *precision = SH_PRECISION_MEDIUMP; break; case EbpHigh: *precision = SH_PRECISION_HIGHP; break; default: // Some types does not support precision, for example, boolean. *precision = SH_PRECISION_UNDEFINED; break; } *staticUse = varInfo.staticUse ? 1 : 0; // This size must match that queried by // SH_ACTIVE_UNIFORM_MAX_LENGTH, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, SH_VARYING_MAX_LENGTH // in ShGetInfo, below. size_t variableLength = 1 + MAX_SYMBOL_NAME_LEN; ASSERT(checkVariableMaxLengths(handle, variableLength)); strncpy(name, varInfo.name.c_str(), variableLength); name[variableLength - 1] = 0; if (mappedName) { // This size must match that queried by // SH_MAPPED_NAME_MAX_LENGTH in ShGetInfo, below. size_t maxMappedNameLength = 1 + MAX_SYMBOL_NAME_LEN; ASSERT(checkMappedNameMaxLength(handle, maxMappedNameLength)); strncpy(mappedName, varInfo.mappedName.c_str(), maxMappedNameLength); mappedName[maxMappedNameLength - 1] = 0; } }
ShShaderOutput ShGetShaderOutputType(const ShHandle handle) { TCompiler* compiler = GetCompilerFromHandle(handle); ASSERT(compiler); return compiler->getOutputType(); }
int ShGetShaderVersion(const ShHandle handle) { TCompiler* compiler = GetCompilerFromHandle(handle); ASSERT(compiler); return compiler->getShaderVersion(); }
void ShClearResults(const ShHandle handle) { TCompiler *compiler = GetCompilerFromHandle(handle); ASSERT(compiler); compiler->clearResults(); }
const std::string &ShGetBuiltInResourcesString(const ShHandle handle) { TCompiler *compiler = GetCompilerFromHandle(handle); ASSERT(compiler); return compiler->getBuiltInResourcesString(); }
// // Do an actual compile on the given strings. The result is left // in the given compile object. // // Return: The return value of ShCompile is really boolean, indicating // success or failure. // int ShCompile( const ShHandle handle, const char* const shaderStrings[], const int numStrings, const EShOptimizationLevel optLevel, const TBuiltInResource* resources, int debugOptions ) { if (!InitThread()) return 0; if (handle == 0) return 0; TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle); TCompiler* compiler = base->getAsCompiler(); if (compiler == 0) return 0; GlobalPoolAllocator.push(); compiler->infoSink.info.erase(); compiler->infoSink.debug.erase(); if (numStrings == 0) return 1; TIntermediate intermediate(compiler->infoSink); TSymbolTable symbolTable(SymbolTables[compiler->getLanguage()]); GenerateBuiltInSymbolTable(resources, compiler->infoSink, &symbolTable, compiler->getLanguage()); TParseContext parseContext(symbolTable, intermediate, compiler->getLanguage(), compiler->infoSink); parseContext.initializeExtensionBehavior(); GlobalParseContext = &parseContext; setInitialState(); InitPreprocessor(); // // Parse the application's shaders. All the following symbol table // work will be throw-away, so push a new allocation scope that can // be thrown away, then push a scope for the current shader's globals. // bool success = true; symbolTable.push(); if (!symbolTable.atGlobalLevel()) parseContext.infoSink.info.message(EPrefixInternalError, "Wrong symbol table level"); if (parseContext.insertBuiltInArrayAtGlobalLevel()) success = false; int ret = PaParseStrings(const_cast<char**>(shaderStrings), 0, numStrings, parseContext); if (ret) success = false; if (success && parseContext.treeRoot) { if (optLevel == EShOptNoGeneration) parseContext.infoSink.info.message(EPrefixNone, "No errors. No code generation or linking was requested."); else { success = intermediate.postProcess(parseContext.treeRoot, parseContext.language); if (success) { if (debugOptions & EDebugOpIntermediate) intermediate.outputTree(parseContext.treeRoot); // // Call the machine dependent compiler // if (! compiler->compile(parseContext.treeRoot)) success = false; } } } else if (!success) { parseContext.infoSink.info.prefix(EPrefixError); parseContext.infoSink.info << parseContext.numErrors << " compilation errors. No code generated.\n\n"; success = false; if (debugOptions & EDebugOpIntermediate) intermediate.outputTree(parseContext.treeRoot); } intermediate.remove(parseContext.treeRoot); // // Ensure symbol table is returned to the built-in level, // throwing away all but the built-ins. // while (! symbolTable.atSharedBuiltInLevel()) symbolTable.pop(); FinalizePreprocessor(); // // Throw away all the temporary memory used by the compilation process. // GlobalPoolAllocator.pop(); return success ? 1 : 0; }