summaryrefslogtreecommitdiffstats
path: root/gfx/angle/src/libANGLE/Shader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/angle/src/libANGLE/Shader.cpp')
-rwxr-xr-xgfx/angle/src/libANGLE/Shader.cpp432
1 files changed, 432 insertions, 0 deletions
diff --git a/gfx/angle/src/libANGLE/Shader.cpp b/gfx/angle/src/libANGLE/Shader.cpp
new file mode 100755
index 000000000..a4c68950b
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Shader.cpp
@@ -0,0 +1,432 @@
+//
+// Copyright (c) 2002-2014 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.
+//
+
+// Shader.cpp: Implements the gl::Shader class and its derived classes
+// VertexShader and FragmentShader. Implements GL shader objects and related
+// functionality. [OpenGL ES 2.0.24] section 2.10 page 24 and section 3.8 page 84.
+
+#include "libANGLE/Shader.h"
+
+#include <sstream>
+
+#include "common/utilities.h"
+#include "GLSLANG/ShaderLang.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/Compiler.h"
+#include "libANGLE/Constants.h"
+#include "libANGLE/renderer/GLImplFactory.h"
+#include "libANGLE/renderer/ShaderImpl.h"
+#include "libANGLE/ResourceManager.h"
+#include "libANGLE/Context.h"
+
+namespace gl
+{
+
+namespace
+{
+template <typename VarT>
+std::vector<VarT> GetActiveShaderVariables(const std::vector<VarT> *variableList)
+{
+ ASSERT(variableList);
+ std::vector<VarT> result;
+ for (size_t varIndex = 0; varIndex < variableList->size(); varIndex++)
+ {
+ const VarT &var = variableList->at(varIndex);
+ if (var.staticUse)
+ {
+ result.push_back(var);
+ }
+ }
+ return result;
+}
+
+template <typename VarT>
+const std::vector<VarT> &GetShaderVariables(const std::vector<VarT> *variableList)
+{
+ ASSERT(variableList);
+ return *variableList;
+}
+
+} // anonymous namespace
+
+// true if varying x has a higher priority in packing than y
+bool CompareShaderVar(const sh::ShaderVariable &x, const sh::ShaderVariable &y)
+{
+ if (x.type == y.type)
+ {
+ return x.arraySize > y.arraySize;
+ }
+
+ // Special case for handling structs: we sort these to the end of the list
+ if (x.type == GL_STRUCT_ANGLEX)
+ {
+ return false;
+ }
+
+ if (y.type == GL_STRUCT_ANGLEX)
+ {
+ return true;
+ }
+
+ return gl::VariableSortOrder(x.type) < gl::VariableSortOrder(y.type);
+}
+
+ShaderState::ShaderState(GLenum shaderType) : mLabel(), mShaderType(shaderType), mShaderVersion(100)
+{
+ mLocalSize.fill(-1);
+}
+
+ShaderState::~ShaderState()
+{
+}
+
+Shader::Shader(ResourceManager *manager,
+ rx::GLImplFactory *implFactory,
+ const gl::Limitations &rendererLimitations,
+ GLenum type,
+ GLuint handle)
+ : mState(type),
+ mImplementation(implFactory->createShader(mState)),
+ mRendererLimitations(rendererLimitations),
+ mHandle(handle),
+ mType(type),
+ mRefCount(0),
+ mDeleteStatus(false),
+ mCompiled(false),
+ mResourceManager(manager)
+{
+ ASSERT(mImplementation);
+}
+
+Shader::~Shader()
+{
+ SafeDelete(mImplementation);
+}
+
+void Shader::setLabel(const std::string &label)
+{
+ mState.mLabel = label;
+}
+
+const std::string &Shader::getLabel() const
+{
+ return mState.mLabel;
+}
+
+GLuint Shader::getHandle() const
+{
+ return mHandle;
+}
+
+void Shader::setSource(GLsizei count, const char *const *string, const GLint *length)
+{
+ std::ostringstream stream;
+
+ for (int i = 0; i < count; i++)
+ {
+ if (length == nullptr || length[i] < 0)
+ {
+ stream.write(string[i], strlen(string[i]));
+ }
+ else
+ {
+ stream.write(string[i], length[i]);
+ }
+ }
+
+ mState.mSource = stream.str();
+}
+
+int Shader::getInfoLogLength() const
+{
+ if (mInfoLog.empty())
+ {
+ return 0;
+ }
+
+ return (static_cast<int>(mInfoLog.length()) + 1);
+}
+
+void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const
+{
+ int index = 0;
+
+ if (bufSize > 0)
+ {
+ index = std::min(bufSize - 1, static_cast<GLsizei>(mInfoLog.length()));
+ memcpy(infoLog, mInfoLog.c_str(), index);
+
+ infoLog[index] = '\0';
+ }
+
+ if (length)
+ {
+ *length = index;
+ }
+}
+
+int Shader::getSourceLength() const
+{
+ return mState.mSource.empty() ? 0 : (static_cast<int>(mState.mSource.length()) + 1);
+}
+
+int Shader::getTranslatedSourceLength() const
+{
+ if (mState.mTranslatedSource.empty())
+ {
+ return 0;
+ }
+
+ return (static_cast<int>(mState.mTranslatedSource.length()) + 1);
+}
+
+int Shader::getTranslatedSourceWithDebugInfoLength() const
+{
+ const std::string &debugInfo = mImplementation->getDebugInfo();
+ if (debugInfo.empty())
+ {
+ return 0;
+ }
+
+ return (static_cast<int>(debugInfo.length()) + 1);
+}
+
+void Shader::getSourceImpl(const std::string &source, GLsizei bufSize, GLsizei *length, char *buffer)
+{
+ int index = 0;
+
+ if (bufSize > 0)
+ {
+ index = std::min(bufSize - 1, static_cast<GLsizei>(source.length()));
+ memcpy(buffer, source.c_str(), index);
+
+ buffer[index] = '\0';
+ }
+
+ if (length)
+ {
+ *length = index;
+ }
+}
+
+void Shader::getSource(GLsizei bufSize, GLsizei *length, char *buffer) const
+{
+ getSourceImpl(mState.mSource, bufSize, length, buffer);
+}
+
+void Shader::getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer) const
+{
+ getSourceImpl(mState.mTranslatedSource, bufSize, length, buffer);
+}
+
+void Shader::getTranslatedSourceWithDebugInfo(GLsizei bufSize, GLsizei *length, char *buffer) const
+{
+ const std::string &debugInfo = mImplementation->getDebugInfo();
+ getSourceImpl(debugInfo, bufSize, length, buffer);
+}
+
+void Shader::compile(const Context *context)
+{
+ mState.mTranslatedSource.clear();
+ mInfoLog.clear();
+ mState.mShaderVersion = 100;
+ mState.mVaryings.clear();
+ mState.mUniforms.clear();
+ mState.mInterfaceBlocks.clear();
+ mState.mActiveAttributes.clear();
+ mState.mActiveOutputVariables.clear();
+
+ Compiler *compiler = context->getCompiler();
+ ShHandle compilerHandle = compiler->getCompilerHandle(mState.mShaderType);
+
+ std::stringstream sourceStream;
+
+ std::string sourcePath;
+ ShCompileOptions additionalOptions =
+ mImplementation->prepareSourceAndReturnOptions(&sourceStream, &sourcePath);
+ ShCompileOptions compileOptions = (SH_OBJECT_CODE | SH_VARIABLES | additionalOptions);
+
+ // Add default options to WebGL shaders to prevent unexpected behavior during compilation.
+ if (context->getExtensions().webglCompatibility)
+ {
+ compileOptions |= SH_LIMIT_CALL_STACK_DEPTH;
+ compileOptions |= SH_LIMIT_EXPRESSION_COMPLEXITY;
+ compileOptions |= SH_ENFORCE_PACKING_RESTRICTIONS;
+ }
+
+ // 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 =
+ sh::Compile(compilerHandle, &sourceCStrings[0], sourceCStrings.size(), compileOptions);
+
+ if (!result)
+ {
+ mInfoLog = sh::GetInfoLog(compilerHandle);
+ TRACE("\n%s", mInfoLog.c_str());
+ mCompiled = false;
+ return;
+ }
+
+ mState.mTranslatedSource = sh::GetObjectCode(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 = mState.mSource.find("\n", curPos);
+ size_t len = (nextLine == std::string::npos) ? std::string::npos : (nextLine - curPos + 1);
+
+ shaderStream << "// " << mState.mSource.substr(curPos, len);
+
+ curPos = (nextLine == std::string::npos) ? std::string::npos : (nextLine + 1);
+ }
+ shaderStream << "\n\n";
+ shaderStream << mState.mTranslatedSource;
+ mState.mTranslatedSource = shaderStream.str();
+#endif
+
+ // Gather the shader information
+ mState.mShaderVersion = sh::GetShaderVersion(compilerHandle);
+
+ mState.mVaryings = GetShaderVariables(sh::GetVaryings(compilerHandle));
+ mState.mUniforms = GetShaderVariables(sh::GetUniforms(compilerHandle));
+ mState.mInterfaceBlocks = GetShaderVariables(sh::GetInterfaceBlocks(compilerHandle));
+
+ switch (mState.mShaderType)
+ {
+ case GL_COMPUTE_SHADER:
+ {
+ mState.mLocalSize = sh::GetComputeShaderLocalGroupSize(compilerHandle);
+ break;
+ }
+ case GL_VERTEX_SHADER:
+ {
+ mState.mActiveAttributes = GetActiveShaderVariables(sh::GetAttributes(compilerHandle));
+ break;
+ }
+ case GL_FRAGMENT_SHADER:
+ {
+ // TODO(jmadill): Figure out why we only sort in the FS, and if we need to.
+ std::sort(mState.mVaryings.begin(), mState.mVaryings.end(), CompareShaderVar);
+ mState.mActiveOutputVariables =
+ GetActiveShaderVariables(sh::GetOutputVariables(compilerHandle));
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
+
+ ASSERT(!mState.mTranslatedSource.empty());
+
+ mCompiled = mImplementation->postTranslateCompile(compiler, &mInfoLog);
+}
+
+void Shader::addRef()
+{
+ mRefCount++;
+}
+
+void Shader::release()
+{
+ mRefCount--;
+
+ if (mRefCount == 0 && mDeleteStatus)
+ {
+ mResourceManager->deleteShader(mHandle);
+ }
+}
+
+unsigned int Shader::getRefCount() const
+{
+ return mRefCount;
+}
+
+bool Shader::isFlaggedForDeletion() const
+{
+ return mDeleteStatus;
+}
+
+void Shader::flagForDeletion()
+{
+ mDeleteStatus = true;
+}
+
+int Shader::getShaderVersion() const
+{
+ return mState.mShaderVersion;
+}
+
+const std::vector<sh::Varying> &Shader::getVaryings() const
+{
+ return mState.getVaryings();
+}
+
+const std::vector<sh::Uniform> &Shader::getUniforms() const
+{
+ return mState.getUniforms();
+}
+
+const std::vector<sh::InterfaceBlock> &Shader::getInterfaceBlocks() const
+{
+ return mState.getInterfaceBlocks();
+}
+
+const std::vector<sh::Attribute> &Shader::getActiveAttributes() const
+{
+ return mState.getActiveAttributes();
+}
+
+const std::vector<sh::OutputVariable> &Shader::getActiveOutputVariables() const
+{
+ return mState.getActiveOutputVariables();
+}
+
+int Shader::getSemanticIndex(const std::string &attributeName) const
+{
+ if (!attributeName.empty())
+ {
+ const auto &activeAttributes = mState.getActiveAttributes();
+
+ int semanticIndex = 0;
+ for (size_t attributeIndex = 0; attributeIndex < activeAttributes.size(); attributeIndex++)
+ {
+ const sh::ShaderVariable &attribute = activeAttributes[attributeIndex];
+
+ if (attribute.name == attributeName)
+ {
+ return semanticIndex;
+ }
+
+ semanticIndex += gl::VariableRegisterCount(attribute.type);
+ }
+ }
+
+ return -1;
+}
+
+}