bool ANGLEWebKitBridge::validateShaderSource(const char* shaderSource, ANGLEShaderType shaderType, String& translatedShaderSource, String& shaderValidationLog) { if (!builtCompilers) { m_fragmentCompiler = ShConstructCompiler(EShLangFragment, EShSpecWebGL, &m_resources); m_vertexCompiler = ShConstructCompiler(EShLangVertex, EShSpecWebGL, &m_resources); builtCompilers = true; } ShHandle compiler; if (shaderType == SHADER_TYPE_VERTEX) compiler = m_vertexCompiler; else compiler = m_fragmentCompiler; const char* const shaderSourceStrings[] = { shaderSource }; bool validateSuccess = ShCompile(compiler, shaderSourceStrings, 1, EShOptNone, EDebugOpIntermediate); translatedShaderSource = ShGetObjectCode(compiler); shaderValidationLog = ShGetInfoLog(compiler); return validateSuccess; }
void Shader::compileToHLSL(void *compiler) { if (isCompiled() || !mSource) { return; } TRACE("\n%s", mSource); delete[] mInfoLog; mInfoLog = NULL; int result = ShCompile(compiler, &mSource, 1, EShOptNone, EDebugOpNone); const char *obj = ShGetObjectCode(compiler); const char *info = ShGetInfoLog(compiler); if (result) { mHlsl = new char[strlen(obj) + 1]; strcpy(mHlsl, obj); TRACE("\n%s", mHlsl); } else { mInfoLog = new char[strlen(info) + 1]; strcpy(mInfoLog, info); TRACE("\n%s", mInfoLog); } }
void Shader::compileToHLSL(void *compiler) { if (isCompiled() || !mSource) { return; } TRACE("\n%s", mSource); delete[] mInfoLog; mInfoLog = NULL; int result = ShCompile(compiler, &mSource, 1, SH_OBJECT_CODE); if (result) { int objCodeLen = 0; ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &objCodeLen); mHlsl = new char[objCodeLen]; ShGetObjectCode(compiler, mHlsl); TRACE("\n%s", mHlsl); } else { int infoLogLen = 0; ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &infoLogLen); mInfoLog = new char[infoLogLen]; ShGetInfoLog(compiler, mInfoLog); TRACE("\n%s", mInfoLog); } }
osgToy::GlslLint::Status osgToy::GlslLint::link() { // The upstream compiler front-end only has a minimal stub for the // linker, so it isn't very interesting from a "lint" perspective. // FUTURE: implement a linker for lint to verify the consistancy of // shaders/uniforms/attributes. int options = (_options == VERBOSE) ? EDebugOpIntermediate : 0; _infoLog = ""; if( _compilerList.empty() ) return ERR_LINK; if( !_uniformMap ) _uniformMap = ShConstructUniformMap(); if( !_uniformMap ) return ERR_UNIFORM_MAP; if( !_linker ) _linker = ShConstructLinker( EShExVertexFragment, options ); if( !_linker ) return ERR_LINKER_CTOR; ShSetFixedAttributeBindings( _linker, &g_BoundAttribTable ); int success = ShLink( _linker, &_compilerList[0], _compilerList.size(), _uniformMap, 0, 0 ); _infoLog = ShGetInfoLog( _linker ); //if( !success ) return ERR_LINK; return SUCCESS; }
void ShaderValidator::GetInfoLog(nsACString* out) const { MOZ_ASSERT(mHasRun); const std::string &log = ShGetInfoLog(mHandle); out->Assign(log.data(), log.length()); }
void Shader::compileToHLSL(void *compiler) { // ensure we don't pass a NULL source to the compiler const char *source = "\0"; if (mSource) { source = mSource; } // ensure the compiler is loaded initializeCompiler(); int compileOptions = SH_OBJECT_CODE; std::string sourcePath; if (perfActive()) { sourcePath = ""; writeFile(sourcePath.c_str(), source, strlen(source)); compileOptions |= SH_LINE_DIRECTIVES; } int result; if (sourcePath.empty()) { result = ShCompile(compiler, &source, 1, compileOptions); } else { const char* sourceStrings[2] = { sourcePath.c_str(), source }; result = ShCompile(compiler, sourceStrings, 2, compileOptions | SH_SOURCE_PATH); } if (result) { size_t objCodeLen = 0; ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &objCodeLen); mHlsl = new char[objCodeLen]; ShGetObjectCode(compiler, mHlsl); void *activeUniforms; ShGetInfoPointer(compiler, SH_ACTIVE_UNIFORMS_ARRAY, &activeUniforms); mActiveUniforms = *(sh::ActiveUniforms*)activeUniforms; } else { size_t infoLogLen = 0; ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &infoLogLen); mInfoLog = new char[infoLogLen]; ShGetInfoLog(compiler, mInfoLog); TRACE("\n%s", mInfoLog); } }
bool ANGLEPlatformBridge::compileShaderSource(const char* shaderSource, ANGLEShaderType shaderType, String& translatedShaderSource, String& shaderValidationLog, Vector<ANGLEShaderSymbol>& symbols, int extraCompileOptions) { if (!builtCompilers) { m_fragmentCompiler = ShConstructCompiler(SH_FRAGMENT_SHADER, m_shaderSpec, m_shaderOutput, &m_resources); m_vertexCompiler = ShConstructCompiler(SH_VERTEX_SHADER, m_shaderSpec, m_shaderOutput, &m_resources); if (!m_fragmentCompiler || !m_vertexCompiler) { cleanupCompilers(); return false; } builtCompilers = true; } ShHandle compiler; if (shaderType == SHADER_TYPE_VERTEX) compiler = m_vertexCompiler; else compiler = m_fragmentCompiler; const char* const shaderSourceStrings[] = { shaderSource }; #if ANGLE_SH_VERSION >= 111 bool validateSuccess = ShCompile(compiler, shaderSourceStrings, 1, SH_OBJECT_CODE | SH_VARIABLES | extraCompileOptions); #else bool validateSuccess = ShCompile(compiler, shaderSourceStrings, 1, SH_OBJECT_CODE | SH_ATTRIBUTES_UNIFORMS | extraCompileOptions); #endif if (!validateSuccess) { int logSize = getValidationResultValue(compiler, SH_INFO_LOG_LENGTH); if (logSize > 1) { OwnPtr<char[]> logBuffer = adoptArrayPtr(new char[logSize]); if (logBuffer) { ShGetInfoLog(compiler, logBuffer.get()); shaderValidationLog = logBuffer.get(); } } return false; } int translationLength = getValidationResultValue(compiler, SH_OBJECT_CODE_LENGTH); if (translationLength > 1) { OwnPtr<char[]> translationBuffer = adoptArrayPtr(new char[translationLength]); if (!translationBuffer) return false; ShGetObjectCode(compiler, translationBuffer.get()); translatedShaderSource = translationBuffer.get(); } if (!getSymbolInfo(compiler, SH_ACTIVE_ATTRIBUTES, symbols)) return false; if (!getSymbolInfo(compiler, SH_ACTIVE_UNIFORMS, symbols)) return false; return true; }
testing::AssertionResult TestShaderCompile(const char *version, const char *pragma, const char *shader) { const char *shaderStrings[] = {version, pragma, shader}; bool success = ShCompile(mCompiler, shaderStrings, 3, 0); if (success) { return ::testing::AssertionSuccess() << "Compilation success"; } return ::testing::AssertionFailure() << ShGetInfoLog(mCompiler); }
void Shader::compileToHLSL(void *compiler) { if (isCompiled() || !mSource) { return; } delete[] mInfoLog; mInfoLog = NULL; int compileOptions = SH_OBJECT_CODE; std::string sourcePath; if (perfActive()) { sourcePath = getTempPath(); writeFile(sourcePath.c_str(), mSource, strlen(mSource)); compileOptions |= SH_LINE_DIRECTIVES; } int result; if (sourcePath.empty()) { result = ShCompile(compiler, &mSource, 1, compileOptions); } else { const char* sourceStrings[2] = { sourcePath.c_str(), mSource }; result = ShCompile(compiler, sourceStrings, 2, compileOptions | SH_SOURCE_PATH); } if (result) { int objCodeLen = 0; ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &objCodeLen); mHlsl = new char[objCodeLen]; ShGetObjectCode(compiler, mHlsl); } else { int infoLogLen = 0; ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &infoLogLen); mInfoLog = new char[infoLogLen]; ShGetInfoLog(compiler, mInfoLog); TRACE("\n%s", mInfoLog); } }
bool ANGLEWebKitBridge::validateShaderSource(const char* shaderSource, ANGLEShaderType shaderType, String& translatedShaderSource, String& shaderValidationLog) { if (!builtCompilers) { m_fragmentCompiler = ShConstructCompiler(SH_FRAGMENT_SHADER, SH_WEBGL_SPEC, m_shaderOutput, &m_resources); m_vertexCompiler = ShConstructCompiler(SH_VERTEX_SHADER, SH_WEBGL_SPEC, m_shaderOutput, &m_resources); if (!m_fragmentCompiler || !m_vertexCompiler) { cleanupCompilers(); return false; } builtCompilers = true; } ShHandle compiler; if (shaderType == SHADER_TYPE_VERTEX) compiler = m_vertexCompiler; else compiler = m_fragmentCompiler; const char* const shaderSourceStrings[] = { shaderSource }; bool validateSuccess = ShCompile(compiler, shaderSourceStrings, 1, SH_OBJECT_CODE); if (!validateSuccess) { int logSize = 0; ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &logSize); if (logSize > 1) { OwnArrayPtr<char> logBuffer = adoptArrayPtr(new char[logSize]); if (logBuffer) { ShGetInfoLog(compiler, logBuffer.get()); shaderValidationLog = logBuffer.get(); } } return false; } int translationLength = 0; ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &translationLength); if (translationLength > 1) { OwnArrayPtr<char> translationBuffer = adoptArrayPtr(new char[translationLength]); if (!translationBuffer) return false; ShGetObjectCode(compiler, translationBuffer.get()); translatedShaderSource = translationBuffer.get(); } return true; }
osgToy::GlslLint::Status osgToy::GlslLint::compile( osg::Shader::Type type, const std::string& sourceText ) { int options = (_options == VERBOSE) ? EDebugOpIntermediate : 0; EShLanguage lang = (type == osg::Shader::VERTEX) ? EShLangVertex : EShLangFragment; _infoLog = ""; ShHandle compiler = ShConstructCompiler( lang, options ); if( !compiler ) return ERR_COMPILER_CTOR; _compilerList.push_back( compiler ); const char* text = sourceText.c_str(); int success = ShCompile( compiler, &text, 1, EShOptNone, &g_Resources, options ); _infoLog = ShGetInfoLog( compiler ); if( !success ) return ERR_COMPILE; return SUCCESS; }
// // Thread entry point, for non-linking asynchronous mode. // // Return 0 for failure, 1 for success. // unsigned int CompileShaders(void*) { glslang::TWorkItem* workItem; while (Worklist.remove(workItem)) { ShHandle compiler = ShConstructCompiler(FindLanguage(workItem->name), Options); if (compiler == 0) return 0; CompileFile(workItem->name.c_str(), compiler); if (! (Options & EOptionSuppressInfolog)) workItem->results = ShGetInfoLog(compiler); ShDestruct(compiler); } return 0; }
bool ANGLEWebKitBridge::compileShaderSource(const char* shaderSource, ANGLEShaderType shaderType, String& translatedShaderSource, String& shaderValidationLog, Vector<ANGLEShaderSymbol>& symbols, int extraCompileOptions) { if (!builtCompilers) { m_fragmentCompiler = ShConstructCompiler(GL_FRAGMENT_SHADER, m_shaderSpec, m_shaderOutput, &m_resources); m_vertexCompiler = ShConstructCompiler(GL_VERTEX_SHADER, m_shaderSpec, m_shaderOutput, &m_resources); if (!m_fragmentCompiler || !m_vertexCompiler) { cleanupCompilers(); return false; } builtCompilers = true; } ShHandle compiler; if (shaderType == SHADER_TYPE_VERTEX) compiler = m_vertexCompiler; else compiler = m_fragmentCompiler; const char* const shaderSourceStrings[] = { shaderSource }; bool validateSuccess = ShCompile(compiler, shaderSourceStrings, 1, SH_OBJECT_CODE | SH_VARIABLES | extraCompileOptions); if (!validateSuccess) { const std::string& log = ShGetInfoLog(compiler); if (log.length()) shaderValidationLog = log.c_str(); return false; } const std::string& objectCode = ShGetObjectCode(compiler); if (objectCode.length()) translatedShaderSource = objectCode.c_str(); if (!getSymbolInfo(compiler, SHADER_SYMBOL_TYPE_ATTRIBUTE, symbols)) return false; if (!getSymbolInfo(compiler, SHADER_SYMBOL_TYPE_UNIFORM, symbols)) return false; if (!getSymbolInfo(compiler, SHADER_SYMBOL_TYPE_VARYING, symbols)) return false; return true; }
void Shader::compileToHLSL(void *compiler) { if (isCompiled() || !mSource) { return; } TRACE("\n%s", mSource); delete[] mInfoLog; mInfoLog = NULL; TBuiltInResource resources; resources.maxVertexAttribs = MAX_VERTEX_ATTRIBS; resources.maxVertexUniformVectors = MAX_VERTEX_UNIFORM_VECTORS; resources.maxVaryingVectors = MAX_VARYING_VECTORS; resources.maxVertexTextureImageUnits = MAX_VERTEX_TEXTURE_IMAGE_UNITS; resources.maxCombinedTextureImageUnits = MAX_COMBINED_TEXTURE_IMAGE_UNITS; resources.maxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS; resources.maxFragmentUniformVectors = MAX_FRAGMENT_UNIFORM_VECTORS; resources.maxDrawBuffers = MAX_DRAW_BUFFERS; int result = ShCompile(compiler, &mSource, 1, EShOptNone, &resources, EDebugOpObjectCode); const char *obj = ShGetObjectCode(compiler); const char *info = ShGetInfoLog(compiler); if (result) { mHlsl = new char[strlen(obj) + 1]; strcpy(mHlsl, obj); TRACE("\n%s", mHlsl); } else { mInfoLog = new char[strlen(info) + 1]; strcpy(mInfoLog, info); TRACE("\n%s", mInfoLog); } }
// Compiles a shader and if there's an error checks for a specific // substring in the error log. This way we know the error is specific // to the issue we are testing. bool CheckShaderCompilation(ShHandle compiler, const char *source, int compileOptions, const char *expected_error) { bool success = ShCompile(compiler, &source, 1, compileOptions) != 0; if (success) { success = !expected_error; } else { std::string log = ShGetInfoLog(compiler); if (expected_error) success = log.find(expected_error) != std::string::npos; EXPECT_TRUE(success) << log << "\n----shader----\n" << source; } return success; }
int main(int argc, char* argv[]) { TFailCode failCode = ESuccess; int compileOptions = 0; int numCompiles = 0; ShHandle vertexCompiler = 0; ShHandle fragmentCompiler = 0; char* buffer = 0; int bufferLen = 0; int numAttribs = 0, numUniforms = 0; ShShaderSpec spec = SH_GLES2_SPEC; ShShaderOutput output = SH_ESSL_OUTPUT; ShInitialize(); ShBuiltInResources resources; GenerateResources(&resources); argc--; argv++; for (; (argc >= 1) && (failCode == ESuccess); argc--, argv++) { if (argv[0][0] == '-') { switch (argv[0][1]) { case 'i': compileOptions |= SH_INTERMEDIATE_TREE; break; case 'm': compileOptions |= SH_MAP_LONG_VARIABLE_NAMES; break; case 'o': compileOptions |= SH_OBJECT_CODE; break; case 'u': compileOptions |= SH_ATTRIBUTES_UNIFORMS; break; case 'l': compileOptions |= SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX; break; case 'e': compileOptions |= SH_EMULATE_BUILT_IN_FUNCTIONS; break; case 'd': compileOptions |= SH_DEPENDENCY_GRAPH; break; case 't': compileOptions |= SH_TIMING_RESTRICTIONS; break; case 's': if (argv[0][2] == '=') { switch (argv[0][3]) { case 'e': spec = SH_GLES2_SPEC; break; case 'w': spec = SH_WEBGL_SPEC; break; case 'c': spec = SH_CSS_SHADERS_SPEC; break; default: failCode = EFailUsage; } } else { failCode = EFailUsage; } break; case 'b': if (argv[0][2] == '=') { switch (argv[0][3]) { case 'e': output = SH_ESSL_OUTPUT; break; case 'g': output = SH_GLSL_OUTPUT; break; case 'h': output = SH_HLSL_OUTPUT; break; default: failCode = EFailUsage; } } else { failCode = EFailUsage; } break; case 'x': if (argv[0][2] == '=') { switch (argv[0][3]) { case 'i': resources.OES_EGL_image_external = 1; break; case 'd': resources.OES_standard_derivatives = 1; break; case 'r': resources.ARB_texture_rectangle = 1; break; default: failCode = EFailUsage; } } else { failCode = EFailUsage; } break; default: failCode = EFailUsage; } } else { ShHandle compiler = 0; switch (FindShaderType(argv[0])) { case SH_VERTEX_SHADER: if (vertexCompiler == 0) vertexCompiler = ShConstructCompiler( SH_VERTEX_SHADER, spec, output, &resources); compiler = vertexCompiler; break; case SH_FRAGMENT_SHADER: if (fragmentCompiler == 0) fragmentCompiler = ShConstructCompiler( SH_FRAGMENT_SHADER, spec, output, &resources); compiler = fragmentCompiler; break; default: break; } if (compiler) { bool compiled = CompileFile(argv[0], compiler, compileOptions); LogMsg("BEGIN", "COMPILER", numCompiles, "INFO LOG"); ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &bufferLen); buffer = (char*) realloc(buffer, bufferLen * sizeof(char)); ShGetInfoLog(compiler, buffer); puts(buffer); LogMsg("END", "COMPILER", numCompiles, "INFO LOG"); printf("\n\n"); if (compiled && (compileOptions & SH_OBJECT_CODE)) { LogMsg("BEGIN", "COMPILER", numCompiles, "OBJ CODE"); ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &bufferLen); buffer = (char*) realloc(buffer, bufferLen * sizeof(char)); ShGetObjectCode(compiler, buffer); puts(buffer); LogMsg("END", "COMPILER", numCompiles, "OBJ CODE"); printf("\n\n"); } if (compiled && (compileOptions & SH_ATTRIBUTES_UNIFORMS)) { LogMsg("BEGIN", "COMPILER", numCompiles, "ACTIVE ATTRIBS"); PrintActiveVariables(compiler, SH_ACTIVE_ATTRIBUTES, (compileOptions & SH_MAP_LONG_VARIABLE_NAMES) != 0); LogMsg("END", "COMPILER", numCompiles, "ACTIVE ATTRIBS"); printf("\n\n"); LogMsg("BEGIN", "COMPILER", numCompiles, "ACTIVE UNIFORMS"); PrintActiveVariables(compiler, SH_ACTIVE_UNIFORMS, (compileOptions & SH_MAP_LONG_VARIABLE_NAMES) != 0); LogMsg("END", "COMPILER", numCompiles, "ACTIVE UNIFORMS"); printf("\n\n"); } if (!compiled) failCode = EFailCompile; ++numCompiles; } else { failCode = EFailCompilerCreate; } } } if ((vertexCompiler == 0) && (fragmentCompiler == 0)) failCode = EFailUsage; if (failCode == EFailUsage) usage(); if (vertexCompiler) ShDestruct(vertexCompiler); if (fragmentCompiler) ShDestruct(fragmentCompiler); if (buffer) free(buffer); ShFinalize(); return failCode; }
void ShaderD3D::compileToHLSL(ShHandle compiler, const std::string &source) { int compileOptions = (SH_OBJECT_CODE | SH_VARIABLES); // D3D11 Feature Level 9_3 and below do not support non-constant loop indexers in fragment // shaders. // Shader compilation will fail. To provide a better error message we can instruct the // compiler to pre-validate. if (mRenderer->getRendererLimitations().shadersRequireIndexedLoopValidation) { compileOptions |= SH_VALIDATE_LOOP_INDEXING; } std::string sourcePath; #if !defined (ANGLE_ENABLE_WINDOWS_STORE) if (gl::DebugAnnotationsActive()) { sourcePath = getTempPath(); writeFile(sourcePath.c_str(), source.c_str(), source.length()); compileOptions |= SH_LINE_DIRECTIVES; } #endif int result; if (sourcePath.empty()) { const char* sourceStrings[] = { source.c_str(), }; result = ShCompile(compiler, sourceStrings, ArraySize(sourceStrings), compileOptions); } else { const char* sourceStrings[] = { sourcePath.c_str(), source.c_str(), }; result = ShCompile(compiler, sourceStrings, ArraySize(sourceStrings), compileOptions | SH_SOURCE_PATH); } mShaderVersion = ShGetShaderVersion(compiler); if (result) { mTranslatedSource = ShGetObjectCode(compiler); #ifdef _DEBUG // Prefix hlsl shader with commented out glsl shader // Useful in diagnostics tools like pix which capture the hlsl shaders std::ostringstream hlslStream; hlslStream << "// GLSL\n"; hlslStream << "//\n"; size_t curPos = 0; while (curPos != std::string::npos) { size_t nextLine = source.find("\n", curPos); size_t len = (nextLine == std::string::npos) ? std::string::npos : (nextLine - curPos + 1); hlslStream << "// " << source.substr(curPos, len); curPos = (nextLine == std::string::npos) ? std::string::npos : (nextLine + 1); } hlslStream << "\n\n"; hlslStream << mTranslatedSource; mTranslatedSource = hlslStream.str(); #endif mUniforms = *GetShaderVariables(ShGetUniforms(compiler)); for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) { const sh::Uniform &uniform = mUniforms[uniformIndex]; if (uniform.staticUse && !uniform.isBuiltIn()) { unsigned int index = static_cast<unsigned int>(-1); bool getUniformRegisterResult = ShGetUniformRegister(compiler, uniform.name, &index); UNUSED_ASSERTION_VARIABLE(getUniformRegisterResult); ASSERT(getUniformRegisterResult); mUniformRegisterMap[uniform.name] = index; } } mInterfaceBlocks = *GetShaderVariables(ShGetInterfaceBlocks(compiler)); for (size_t blockIndex = 0; blockIndex < mInterfaceBlocks.size(); blockIndex++) { const sh::InterfaceBlock &interfaceBlock = mInterfaceBlocks[blockIndex]; if (interfaceBlock.staticUse) { unsigned int index = static_cast<unsigned int>(-1); bool blockRegisterResult = ShGetInterfaceBlockRegister(compiler, interfaceBlock.name, &index); UNUSED_ASSERTION_VARIABLE(blockRegisterResult); ASSERT(blockRegisterResult); mInterfaceBlockRegisterMap[interfaceBlock.name] = index; } } } else { mInfoLog = ShGetInfoLog(compiler); TRACE("\n%s", mInfoLog.c_str()); } }
void ShaderD3D::compileToHLSL(void *compiler, const std::string &source) { // ensure the compiler is loaded initializeCompiler(); int compileOptions = (SH_OBJECT_CODE | SH_VARIABLES); std::string sourcePath; #if !defined (ANGLE_ENABLE_WINDOWS_STORE) if (gl::perfActive()) { sourcePath = getTempPath(); writeFile(sourcePath.c_str(), source.c_str(), source.length()); compileOptions |= SH_LINE_DIRECTIVES; } #endif int result; if (sourcePath.empty()) { const char* sourceStrings[] = { source.c_str(), }; result = ShCompile(compiler, sourceStrings, ArraySize(sourceStrings), compileOptions); } else { const char* sourceStrings[] = { sourcePath.c_str(), source.c_str(), }; result = ShCompile(compiler, sourceStrings, ArraySize(sourceStrings), compileOptions | SH_SOURCE_PATH); } mShaderVersion = ShGetShaderVersion(compiler); if (mShaderVersion == 300 && mRenderer->getCurrentClientVersion() < 3) { mInfoLog = "GLSL ES 3.00 is not supported by OpenGL ES 2.0 contexts"; TRACE("\n%s", mInfoLog.c_str()); } else if (result) { mHlsl = ShGetObjectCode(compiler); #ifdef _DEBUG // Prefix hlsl shader with commented out glsl shader // Useful in diagnostics tools like pix which capture the hlsl shaders std::ostringstream hlslStream; hlslStream << "// GLSL\n"; hlslStream << "//\n"; size_t curPos = 0; while (curPos != std::string::npos) { size_t nextLine = source.find("\n", curPos); size_t len = (nextLine == std::string::npos) ? std::string::npos : (nextLine - curPos + 1); hlslStream << "// " << source.substr(curPos, len); curPos = (nextLine == std::string::npos) ? std::string::npos : (nextLine + 1); } hlslStream << "\n\n"; hlslStream << mHlsl; mHlsl = hlslStream.str(); #endif mUniforms = *GetShaderVariables(ShGetUniforms(compiler)); for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) { const sh::Uniform &uniform = mUniforms[uniformIndex]; if (uniform.staticUse) { unsigned int index = -1; bool result = ShGetUniformRegister(compiler, uniform.name, &index); UNUSED_ASSERTION_VARIABLE(result); ASSERT(result); mUniformRegisterMap[uniform.name] = index; } } mInterfaceBlocks = *GetShaderVariables(ShGetInterfaceBlocks(compiler)); for (size_t blockIndex = 0; blockIndex < mInterfaceBlocks.size(); blockIndex++) { const sh::InterfaceBlock &interfaceBlock = mInterfaceBlocks[blockIndex]; if (interfaceBlock.staticUse) { unsigned int index = -1; bool result = ShGetInterfaceBlockRegister(compiler, interfaceBlock.name, &index); UNUSED_ASSERTION_VARIABLE(result); ASSERT(result); mInterfaceBlockRegisterMap[interfaceBlock.name] = index; } } } else { mInfoLog = ShGetInfoLog(compiler); TRACE("\n%s", mInfoLog.c_str()); } }
void TestShaderExtension(const char **shaderStrings, int stringCount, bool expectation) { bool success = ShCompile(mCompiler, shaderStrings, stringCount, 0); const std::string& compileLog = ShGetInfoLog(mCompiler); EXPECT_EQ(expectation, success) << compileLog; }
void Shader::compileToHLSL(void *compiler) { // ensure the compiler is loaded initializeCompiler(); int compileOptions = SH_OBJECT_CODE; std::string sourcePath; if (perfActive()) { sourcePath = getTempPath(); writeFile(sourcePath.c_str(), mSource.c_str(), mSource.length()); compileOptions |= SH_LINE_DIRECTIVES; } int result; if (sourcePath.empty()) { const char* sourceStrings[] = { mSource.c_str(), }; result = ShCompile(compiler, sourceStrings, ArraySize(sourceStrings), compileOptions); } else { const char* sourceStrings[] = { sourcePath.c_str(), mSource.c_str(), }; result = ShCompile(compiler, sourceStrings, ArraySize(sourceStrings), compileOptions | SH_SOURCE_PATH); } size_t shaderVersion = 100; ShGetInfo(compiler, SH_SHADER_VERSION, &shaderVersion); mShaderVersion = static_cast<int>(shaderVersion); if (shaderVersion == 300 && mRenderer->getCurrentClientVersion() < 3) { mInfoLog = "GLSL ES 3.00 is not supported by OpenGL ES 2.0 contexts"; TRACE("\n%s", mInfoLog.c_str()); } else if (result) { size_t objCodeLen = 0; ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &objCodeLen); char* outputHLSL = new char[objCodeLen]; ShGetObjectCode(compiler, outputHLSL); #ifdef _DEBUG std::ostringstream hlslStream; hlslStream << "// GLSL\n"; hlslStream << "//\n"; size_t curPos = 0; while (curPos != std::string::npos) { size_t nextLine = mSource.find("\n", curPos); size_t len = (nextLine == std::string::npos) ? std::string::npos : (nextLine - curPos + 1); hlslStream << "// " << mSource.substr(curPos, len); curPos = (nextLine == std::string::npos) ? std::string::npos : (nextLine + 1); } hlslStream << "\n\n"; hlslStream << outputHLSL; mHlsl = hlslStream.str(); #else mHlsl = outputHLSL; #endif delete[] outputHLSL; void *activeUniforms; ShGetInfoPointer(compiler, SH_ACTIVE_UNIFORMS_ARRAY, &activeUniforms); mActiveUniforms = *(std::vector<Uniform>*)activeUniforms; void *activeInterfaceBlocks; ShGetInfoPointer(compiler, SH_ACTIVE_INTERFACE_BLOCKS_ARRAY, &activeInterfaceBlocks); mActiveInterfaceBlocks = *(std::vector<InterfaceBlock>*)activeInterfaceBlocks; } else { size_t infoLogLen = 0; ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &infoLogLen); char* infoLog = new char[infoLogLen]; ShGetInfoLog(compiler, infoLog); mInfoLog = infoLog; TRACE("\n%s", mInfoLog.c_str()); } }
int main(int argc, char *argv[]) { TFailCode failCode = ESuccess; int compileOptions = 0; int numCompiles = 0; ShHandle vertexCompiler = 0; ShHandle fragmentCompiler = 0; ShShaderSpec spec = SH_GLES2_SPEC; ShShaderOutput output = SH_ESSL_OUTPUT; ShInitialize(); ShBuiltInResources resources; GenerateResources(&resources); argc--; argv++; for (; (argc >= 1) && (failCode == ESuccess); argc--, argv++) { if (argv[0][0] == '-') { switch (argv[0][1]) { case 'i': compileOptions |= SH_INTERMEDIATE_TREE; break; case 'o': compileOptions |= SH_OBJECT_CODE; break; case 'u': compileOptions |= SH_VARIABLES; break; case 'l': compileOptions |= SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX; break; case 'e': compileOptions |= SH_EMULATE_BUILT_IN_FUNCTIONS; break; case 'd': compileOptions |= SH_DEPENDENCY_GRAPH; break; case 't': compileOptions |= SH_TIMING_RESTRICTIONS; break; case 'p': resources.WEBGL_debug_shader_precision = 1; break; case 's': if (argv[0][2] == '=') { switch (argv[0][3]) { case 'e': if (argv[0][4] == '3') { spec = SH_GLES3_SPEC; } else { spec = SH_GLES2_SPEC; } break; case 'w': if (argv[0][4] == '2') { spec = SH_WEBGL2_SPEC; } else { spec = SH_WEBGL_SPEC; } break; case 'c': spec = SH_CSS_SHADERS_SPEC; break; default: failCode = EFailUsage; } } else { failCode = EFailUsage; } break; case 'b': if (argv[0][2] == '=') { switch (argv[0][3]) { case 'e': output = SH_ESSL_OUTPUT; break; case 'g': output = SH_GLSL_OUTPUT; break; case 'h': if (argv[0][4] == '1' && argv[0][5] == '1') { output = SH_HLSL11_OUTPUT; } else { output = SH_HLSL9_OUTPUT; } break; default: failCode = EFailUsage; } } else { failCode = EFailUsage; } break; case 'x': if (argv[0][2] == '=') { switch (argv[0][3]) { case 'i': resources.OES_EGL_image_external = 1; break; case 'd': resources.OES_standard_derivatives = 1; break; case 'r': resources.ARB_texture_rectangle = 1; break; case 'l': resources.EXT_shader_texture_lod = 1; break; case 'f': resources.EXT_shader_framebuffer_fetch = 1; break; case 'n': resources.NV_shader_framebuffer_fetch = 1; break; case 'a': resources.ARM_shader_framebuffer_fetch = 1; break; default: failCode = EFailUsage; } } else { failCode = EFailUsage; } break; default: failCode = EFailUsage; } } else { ShHandle compiler = 0; switch (FindShaderType(argv[0])) { case GL_VERTEX_SHADER: if (vertexCompiler == 0) { vertexCompiler = ShConstructCompiler( GL_VERTEX_SHADER, spec, output, &resources); } compiler = vertexCompiler; break; case GL_FRAGMENT_SHADER: if (fragmentCompiler == 0) { fragmentCompiler = ShConstructCompiler( GL_FRAGMENT_SHADER, spec, output, &resources); } compiler = fragmentCompiler; break; default: break; } if (compiler) { bool compiled = CompileFile(argv[0], compiler, compileOptions); LogMsg("BEGIN", "COMPILER", numCompiles, "INFO LOG"); std::string log = ShGetInfoLog(compiler); puts(log.c_str()); LogMsg("END", "COMPILER", numCompiles, "INFO LOG"); printf("\n\n"); if (compiled && (compileOptions & SH_OBJECT_CODE)) { LogMsg("BEGIN", "COMPILER", numCompiles, "OBJ CODE"); std::string code = ShGetObjectCode(compiler); puts(code.c_str()); LogMsg("END", "COMPILER", numCompiles, "OBJ CODE"); printf("\n\n"); } if (compiled && (compileOptions & SH_VARIABLES)) { LogMsg("BEGIN", "COMPILER", numCompiles, "VARIABLES"); PrintActiveVariables(compiler); LogMsg("END", "COMPILER", numCompiles, "VARIABLES"); printf("\n\n"); } if (!compiled) failCode = EFailCompile; ++numCompiles; } else { failCode = EFailCompilerCreate; } } } if ((vertexCompiler == 0) && (fragmentCompiler == 0)) failCode = EFailUsage; if (failCode == EFailUsage) usage(); if (vertexCompiler) ShDestruct(vertexCompiler); if (fragmentCompiler) ShDestruct(fragmentCompiler); ShFinalize(); return failCode; }
void Shader::compile(Compiler *compiler) { mData.mTranslatedSource.clear(); mInfoLog.clear(); mData.mShaderVersion = 100; mData.mVaryings.clear(); mData.mUniforms.clear(); mData.mInterfaceBlocks.clear(); mData.mActiveAttributes.clear(); mData.mActiveOutputVariables.clear(); ShHandle compilerHandle = compiler->getCompilerHandle(mData.mShaderType); std::stringstream sourceStream; std::string sourcePath; int additionalOptions = mImplementation->prepareSourceAndReturnOptions(&sourceStream, &sourcePath); int compileOptions = (SH_OBJECT_CODE | SH_VARIABLES | additionalOptions); // Some targets (eg D3D11 Feature Level 9_3 and below) do not support non-constant loop indexes // in fragment shaders. Shader compilation will fail. To provide a better error message we can // instruct the compiler to pre-validate. if (mRendererLimitations.shadersRequireIndexedLoopValidation) { compileOptions |= SH_VALIDATE_LOOP_INDEXING; } std::string sourceString = sourceStream.str(); std::vector<const char *> sourceCStrings; if (!sourcePath.empty()) { sourceCStrings.push_back(sourcePath.c_str()); } sourceCStrings.push_back(sourceString.c_str()); bool result = ShCompile(compilerHandle, &sourceCStrings[0], sourceCStrings.size(), compileOptions); if (!result) { mInfoLog = ShGetInfoLog(compilerHandle); TRACE("\n%s", mInfoLog.c_str()); mCompiled = false; return; } mData.mTranslatedSource = ShGetObjectCode(compilerHandle); #ifndef NDEBUG // Prefix translated shader with commented out un-translated shader. // Useful in diagnostics tools which capture the shader source. std::ostringstream shaderStream; shaderStream << "// GLSL\n"; shaderStream << "//\n"; size_t curPos = 0; while (curPos != std::string::npos) { size_t nextLine = mData.mSource.find("\n", curPos); size_t len = (nextLine == std::string::npos) ? std::string::npos : (nextLine - curPos + 1); shaderStream << "// " << mData.mSource.substr(curPos, len); curPos = (nextLine == std::string::npos) ? std::string::npos : (nextLine + 1); } shaderStream << "\n\n"; shaderStream << mData.mTranslatedSource; mData.mTranslatedSource = shaderStream.str(); #endif // Gather the shader information mData.mShaderVersion = ShGetShaderVersion(compilerHandle); mData.mVaryings = GetShaderVariables(ShGetVaryings(compilerHandle)); mData.mUniforms = GetShaderVariables(ShGetUniforms(compilerHandle)); mData.mInterfaceBlocks = GetShaderVariables(ShGetInterfaceBlocks(compilerHandle)); if (mData.mShaderType == GL_VERTEX_SHADER) { mData.mActiveAttributes = GetActiveShaderVariables(ShGetAttributes(compilerHandle)); } else { ASSERT(mData.mShaderType == GL_FRAGMENT_SHADER); // TODO(jmadill): Figure out why we only sort in the FS, and if we need to. std::sort(mData.mVaryings.begin(), mData.mVaryings.end(), CompareShaderVar); mData.mActiveOutputVariables = GetActiveShaderVariables(ShGetOutputVariables(compilerHandle)); } ASSERT(!mData.mTranslatedSource.empty()); mCompiled = mImplementation->postTranslateCompile(compiler, &mInfoLog); }