| // |
| // Copyright 2015 The ANGLE Project Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| // |
| |
| // ShaderGL.cpp: Implements the class methods for ShaderGL. |
| |
| #include "libANGLE/renderer/gl/ShaderGL.h" |
| |
| #include "common/debug.h" |
| #include "libANGLE/Compiler.h" |
| #include "libANGLE/renderer/gl/FunctionsGL.h" |
| #include "libANGLE/renderer/gl/RendererGL.h" |
| #include "libANGLE/renderer/gl/WorkaroundsGL.h" |
| |
| #include <iostream> |
| |
| namespace rx |
| { |
| |
| ShaderGL::ShaderGL(const gl::ShaderState &data, |
| const FunctionsGL *functions, |
| const WorkaroundsGL &workarounds) |
| : ShaderImpl(data), mFunctions(functions), mWorkarounds(workarounds), mShaderID(0) |
| { |
| ASSERT(mFunctions); |
| } |
| |
| ShaderGL::~ShaderGL() |
| { |
| if (mShaderID != 0) |
| { |
| mFunctions->deleteShader(mShaderID); |
| mShaderID = 0; |
| } |
| } |
| |
| ShCompileOptions ShaderGL::prepareSourceAndReturnOptions(std::stringstream *sourceStream, |
| std::string * /*sourcePath*/) |
| { |
| // Reset the previous state |
| if (mShaderID != 0) |
| { |
| mFunctions->deleteShader(mShaderID); |
| mShaderID = 0; |
| } |
| |
| *sourceStream << mData.getSource(); |
| |
| ShCompileOptions options = SH_INIT_GL_POSITION; |
| |
| if (mWorkarounds.doWhileGLSLCausesGPUHang) |
| { |
| options |= SH_REWRITE_DO_WHILE_LOOPS; |
| } |
| |
| if (mWorkarounds.emulateAbsIntFunction) |
| { |
| options |= SH_EMULATE_ABS_INT_FUNCTION; |
| } |
| |
| if (mWorkarounds.addAndTrueToLoopCondition) |
| { |
| options |= SH_ADD_AND_TRUE_TO_LOOP_CONDITION; |
| } |
| |
| if (mWorkarounds.emulateIsnanFloat) |
| { |
| options |= SH_EMULATE_ISNAN_FLOAT_FUNCTION; |
| } |
| |
| if (mWorkarounds.emulateAtan2Float) |
| { |
| options |= SH_EMULATE_ATAN2_FLOAT_FUNCTION; |
| } |
| |
| if (mWorkarounds.useUnusedBlocksWithStandardOrSharedLayout) |
| { |
| options |= SH_USE_UNUSED_STANDARD_SHARED_BLOCKS; |
| } |
| |
| if (mWorkarounds.dontRemoveInvariantForFragmentInput) |
| { |
| options |= SH_DONT_REMOVE_INVARIANT_FOR_FRAGMENT_INPUT; |
| } |
| |
| if (mWorkarounds.removeInvariantAndCentroidForESSL3) |
| { |
| options |= SH_REMOVE_INVARIANT_AND_CENTROID_FOR_ESSL3; |
| } |
| |
| if (mWorkarounds.rewriteFloatUnaryMinusOperator) |
| { |
| options |= SH_REWRITE_FLOAT_UNARY_MINUS_OPERATOR; |
| } |
| |
| return options; |
| } |
| |
| bool ShaderGL::postTranslateCompile(gl::Compiler *compiler, std::string *infoLog) |
| { |
| // Translate the ESSL into GLSL |
| const char *translatedSourceCString = mData.getTranslatedSource().c_str(); |
| |
| // Generate a shader object and set the source |
| mShaderID = mFunctions->createShader(mData.getShaderType()); |
| mFunctions->shaderSource(mShaderID, 1, &translatedSourceCString, nullptr); |
| mFunctions->compileShader(mShaderID); |
| |
| // Check for compile errors from the native driver |
| GLint compileStatus = GL_FALSE; |
| mFunctions->getShaderiv(mShaderID, GL_COMPILE_STATUS, &compileStatus); |
| if (compileStatus == GL_FALSE) |
| { |
| // Compilation failed, put the error into the info log |
| GLint infoLogLength = 0; |
| mFunctions->getShaderiv(mShaderID, GL_INFO_LOG_LENGTH, &infoLogLength); |
| |
| // Info log length includes the null terminator, so 1 means that the info log is an empty |
| // string. |
| if (infoLogLength > 1) |
| { |
| std::vector<char> buf(infoLogLength); |
| mFunctions->getShaderInfoLog(mShaderID, infoLogLength, nullptr, &buf[0]); |
| |
| mFunctions->deleteShader(mShaderID); |
| mShaderID = 0; |
| |
| *infoLog = &buf[0]; |
| WARN() << std::endl << *infoLog; |
| } |
| else |
| { |
| WARN() << std::endl << "Shader compilation failed with no info log."; |
| } |
| return false; |
| } |
| |
| return true; |
| } |
| |
| std::string ShaderGL::getDebugInfo() const |
| { |
| return mData.getTranslatedSource(); |
| } |
| |
| GLuint ShaderGL::getShaderID() const |
| { |
| return mShaderID; |
| } |
| |
| } |