Revert "Refactoring Shader objects"
This reverts commit 537dfde52a33d621ab1198c949a81b09a1269b2e.
Change-Id: I5eb8923ac8f78877e6e77a8cd897021e56ee004a
Reviewed-on: https://chromium-review.googlesource.com/214466
Reviewed-by: Brandon Jones <bajones@chromium.org>
Tested-by: Brandon Jones <bajones@chromium.org>
diff --git a/src/libGLESv2/Shader.cpp b/src/libGLESv2/Shader.cpp
index 05e11ad..0d7f601 100644
--- a/src/libGLESv2/Shader.cpp
+++ b/src/libGLESv2/Shader.cpp
@@ -14,22 +14,31 @@
#include "GLSLANG/ShaderLang.h"
#include "common/utilities.h"
#include "libGLESv2/renderer/Renderer.h"
-#include "libGLESv2/renderer/ShaderImpl.h"
#include "libGLESv2/Constants.h"
#include "libGLESv2/ResourceManager.h"
namespace gl
{
+void *Shader::mFragmentCompiler = NULL;
+void *Shader::mVertexCompiler = NULL;
-Shader::Shader(ResourceManager *manager, rx::ShaderImpl *impl, GLenum type, GLuint handle)
- : mShader(impl),
- mType(type),
- mHandle(handle),
- mResourceManager(manager),
- mRefCount(0),
- mDeleteStatus(false),
- mCompiled(false)
+template <typename VarT>
+const std::vector<VarT> *GetShaderVariables(const std::vector<VarT> *variableList)
{
+ // TODO: handle staticUse. for now, assume all returned variables are active.
+ ASSERT(variableList);
+ return variableList;
+}
+
+Shader::Shader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle)
+ : mHandle(handle), mRenderer(renderer), mResourceManager(manager)
+{
+ uncompile();
+ initializeCompiler();
+
+ mRefCount = 0;
+ mDeleteStatus = false;
+ mShaderVersion = 100;
}
Shader::~Shader()
@@ -55,7 +64,7 @@
int Shader::getInfoLogLength() const
{
- return mShader->getInfoLog().empty() ? 0 : (mShader->getInfoLog().length() + 1);
+ return mInfoLog.empty() ? 0 : (mInfoLog.length() + 1);
}
void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const
@@ -64,8 +73,8 @@
if (bufSize > 0)
{
- index = std::min(bufSize - 1, static_cast<GLsizei>(mShader->getInfoLog().length()));
- memcpy(infoLog, mShader->getInfoLog().c_str(), index);
+ index = std::min(bufSize - 1, static_cast<GLsizei>(mInfoLog.length()));
+ memcpy(infoLog, mInfoLog.c_str(), index);
infoLog[index] = '\0';
}
@@ -83,10 +92,10 @@
int Shader::getTranslatedSourceLength() const
{
- return mShader->getTranslatedSource().empty() ? 0 : (mShader->getTranslatedSource().length() + 1);
+ return mHlsl.empty() ? 0 : (mHlsl.length() + 1);
}
-void Shader::getSourceImpl(const std::string &source, GLsizei bufSize, GLsizei *length, char *buffer)
+void Shader::getSourceImpl(const std::string &source, GLsizei bufSize, GLsizei *length, char *buffer) const
{
int index = 0;
@@ -111,12 +120,44 @@
void Shader::getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer) const
{
- getSourceImpl(mShader->getTranslatedSource(), bufSize, length, buffer);
+ getSourceImpl(mHlsl, bufSize, length, buffer);
}
-void Shader::compile()
+unsigned int Shader::getUniformRegister(const std::string &uniformName) const
{
- mCompiled = mShader->compile(mSource);
+ ASSERT(mUniformRegisterMap.count(uniformName) > 0);
+ return mUniformRegisterMap.find(uniformName)->second;
+}
+
+unsigned int Shader::getInterfaceBlockRegister(const std::string &blockName) const
+{
+ ASSERT(mInterfaceBlockRegisterMap.count(blockName) > 0);
+ return mInterfaceBlockRegisterMap.find(blockName)->second;
+}
+
+const std::vector<sh::Uniform> &Shader::getUniforms() const
+{
+ return mActiveUniforms;
+}
+
+const std::vector<sh::InterfaceBlock> &Shader::getInterfaceBlocks() const
+{
+ return mActiveInterfaceBlocks;
+}
+
+std::vector<PackedVarying> &Shader::getVaryings()
+{
+ return mVaryings;
+}
+
+bool Shader::isCompiled() const
+{
+ return !mHlsl.empty();
+}
+
+const std::string &Shader::getHLSL() const
+{
+ return mHlsl;
}
void Shader::addRef()
@@ -149,8 +190,289 @@
mDeleteStatus = true;
}
-VertexShader::VertexShader(ResourceManager *manager, rx::ShaderImpl *impl, GLuint handle)
- : Shader(manager, impl, GL_VERTEX_SHADER, handle)
+// Perform a one-time initialization of the shader compiler (or after being destructed by releaseCompiler)
+void Shader::initializeCompiler()
+{
+ if (!mFragmentCompiler)
+ {
+ int result = ShInitialize();
+
+ if (result)
+ {
+ ShShaderOutput hlslVersion = (mRenderer->getMajorShaderModel() >= 4) ? SH_HLSL11_OUTPUT : SH_HLSL9_OUTPUT;
+
+ ShBuiltInResources resources;
+ ShInitBuiltInResources(&resources);
+
+ // TODO(geofflang): use context's caps
+ const gl::Caps &caps = mRenderer->getRendererCaps();
+ const gl::Extensions &extensions = mRenderer->getRendererExtensions();
+
+ resources.MaxVertexAttribs = caps.maxVertexAttributes;
+ resources.MaxVertexUniformVectors = caps.maxVertexUniformVectors;
+ resources.MaxVaryingVectors = mRenderer->getMaxVaryingVectors();
+ resources.MaxVertexTextureImageUnits = caps.maxVertexTextureImageUnits;
+ resources.MaxCombinedTextureImageUnits = mRenderer->getMaxCombinedTextureImageUnits();
+ resources.MaxTextureImageUnits = caps.maxTextureImageUnits;
+ resources.MaxFragmentUniformVectors = caps.maxFragmentUniformVectors;
+ resources.MaxDrawBuffers = caps.maxDrawBuffers;
+ resources.OES_standard_derivatives = extensions.standardDerivatives;
+ resources.EXT_draw_buffers = extensions.drawBuffers;
+ resources.EXT_shader_texture_lod = 1;
+ // resources.OES_EGL_image_external = mRenderer->getShareHandleSupport() ? 1 : 0; // TODO: commented out until the extension is actually supported.
+ resources.FragmentPrecisionHigh = 1; // Shader Model 2+ always supports FP24 (s16e7) which corresponds to highp
+ resources.EXT_frag_depth = 1; // Shader Model 2+ always supports explicit depth output
+ // GLSL ES 3.0 constants
+ resources.MaxVertexOutputVectors = caps.maxVertexOutputComponents / 4;
+ resources.MaxFragmentInputVectors = caps.maxFragmentInputComponents / 4;
+ resources.MinProgramTexelOffset = caps.minProgramTexelOffset;
+ resources.MaxProgramTexelOffset = caps.maxProgramTexelOffset;
+
+ mFragmentCompiler = ShConstructCompiler(GL_FRAGMENT_SHADER, SH_GLES2_SPEC, hlslVersion, &resources);
+ mVertexCompiler = ShConstructCompiler(GL_VERTEX_SHADER, SH_GLES2_SPEC, hlslVersion, &resources);
+ }
+ }
+}
+
+void Shader::releaseCompiler()
+{
+ ShDestruct(mFragmentCompiler);
+ ShDestruct(mVertexCompiler);
+
+ mFragmentCompiler = NULL;
+ mVertexCompiler = NULL;
+
+ ShFinalize();
+}
+
+void Shader::parseVaryings(void *compiler)
+{
+ if (!mHlsl.empty())
+ {
+ const std::vector<sh::Varying> *activeVaryings = ShGetVaryings(compiler);
+ ASSERT(activeVaryings);
+
+ for (size_t varyingIndex = 0; varyingIndex < activeVaryings->size(); varyingIndex++)
+ {
+ mVaryings.push_back(PackedVarying((*activeVaryings)[varyingIndex]));
+ }
+
+ mUsesMultipleRenderTargets = mHlsl.find("GL_USES_MRT") != std::string::npos;
+ mUsesFragColor = mHlsl.find("GL_USES_FRAG_COLOR") != std::string::npos;
+ mUsesFragData = mHlsl.find("GL_USES_FRAG_DATA") != std::string::npos;
+ mUsesFragCoord = mHlsl.find("GL_USES_FRAG_COORD") != std::string::npos;
+ mUsesFrontFacing = mHlsl.find("GL_USES_FRONT_FACING") != std::string::npos;
+ mUsesPointSize = mHlsl.find("GL_USES_POINT_SIZE") != std::string::npos;
+ mUsesPointCoord = mHlsl.find("GL_USES_POINT_COORD") != std::string::npos;
+ mUsesDepthRange = mHlsl.find("GL_USES_DEPTH_RANGE") != std::string::npos;
+ mUsesFragDepth = mHlsl.find("GL_USES_FRAG_DEPTH") != std::string::npos;
+ mUsesDiscardRewriting = mHlsl.find("ANGLE_USES_DISCARD_REWRITING") != std::string::npos;
+ mUsesNestedBreak = mHlsl.find("ANGLE_USES_NESTED_BREAK") != std::string::npos;
+ }
+}
+
+void Shader::resetVaryingsRegisterAssignment()
+{
+ for (unsigned int varyingIndex = 0; varyingIndex < mVaryings.size(); varyingIndex++)
+ {
+ mVaryings[varyingIndex].resetRegisterAssignment();
+ }
+}
+
+// initialize/clean up previous state
+void Shader::uncompile()
+{
+ // set by compileToHLSL
+ mHlsl.clear();
+ mInfoLog.clear();
+
+ // set by parseVaryings
+ mVaryings.clear();
+
+ mUsesMultipleRenderTargets = false;
+ mUsesFragColor = false;
+ mUsesFragData = false;
+ mUsesFragCoord = false;
+ mUsesFrontFacing = false;
+ mUsesPointSize = false;
+ mUsesPointCoord = false;
+ mUsesDepthRange = false;
+ mUsesFragDepth = false;
+ mShaderVersion = 100;
+ mUsesDiscardRewriting = false;
+ mUsesNestedBreak = false;
+
+ mActiveUniforms.clear();
+ mActiveInterfaceBlocks.clear();
+}
+
+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
+
+ SafeDeleteArray(outputHLSL);
+
+ mActiveUniforms = *GetShaderVariables(ShGetUniforms(compiler));
+
+ for (size_t uniformIndex = 0; uniformIndex < mActiveUniforms.size(); uniformIndex++)
+ {
+ const sh::Uniform &uniform = mActiveUniforms[uniformIndex];
+
+ unsigned int index = -1;
+ bool result = ShGetUniformRegister(compiler, uniform.name.c_str(), &index);
+ UNUSED_ASSERTION_VARIABLE(result);
+ ASSERT(result);
+
+ mUniformRegisterMap[uniform.name] = index;
+ }
+
+ mActiveInterfaceBlocks = *GetShaderVariables(ShGetInterfaceBlocks(compiler));
+
+ for (size_t blockIndex = 0; blockIndex < mActiveInterfaceBlocks.size(); blockIndex++)
+ {
+ const sh::InterfaceBlock &interfaceBlock = mActiveInterfaceBlocks[blockIndex];
+
+ unsigned int index = -1;
+ bool result = ShGetInterfaceBlockRegister(compiler, interfaceBlock.name.c_str(), &index);
+ UNUSED_ASSERTION_VARIABLE(result);
+ ASSERT(result);
+
+ mInterfaceBlockRegisterMap[interfaceBlock.name] = index;
+ }
+ }
+ 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());
+ }
+}
+
+rx::D3DWorkaroundType Shader::getD3DWorkarounds() const
+{
+ if (mUsesDiscardRewriting)
+ {
+ // ANGLE issue 486:
+ // Work-around a D3D9 compiler bug that presents itself when using conditional discard, by disabling optimization
+ return rx::ANGLE_D3D_WORKAROUND_SKIP_OPTIMIZATION;
+ }
+
+ if (mUsesNestedBreak)
+ {
+ // ANGLE issue 603:
+ // Work-around a D3D9 compiler bug that presents itself when using break in a nested loop, by maximizing optimization
+ // We want to keep the use of ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION minimal to prevent hangs, so usesDiscard takes precedence
+ return rx::ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION;
+ }
+
+ return rx::ANGLE_D3D_WORKAROUND_NONE;
+}
+
+// true if varying x has a higher priority in packing than y
+bool Shader::compareVarying(const PackedVarying &x, const PackedVarying &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);
+}
+
+int Shader::getShaderVersion() const
+{
+ return mShaderVersion;
+}
+
+VertexShader::VertexShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle)
+ : Shader(manager, renderer, handle)
{
}
@@ -158,8 +480,60 @@
{
}
-FragmentShader::FragmentShader(ResourceManager *manager, rx::ShaderImpl *impl, GLuint handle)
- : Shader(manager, impl, GL_FRAGMENT_SHADER, handle)
+GLenum VertexShader::getType() const
+{
+ return GL_VERTEX_SHADER;
+}
+
+void VertexShader::uncompile()
+{
+ Shader::uncompile();
+
+ // set by ParseAttributes
+ mActiveAttributes.clear();
+}
+
+void VertexShader::compile()
+{
+ uncompile();
+
+ compileToHLSL(mVertexCompiler);
+ parseAttributes();
+ parseVaryings(mVertexCompiler);
+}
+
+int VertexShader::getSemanticIndex(const std::string &attributeName)
+{
+ if (!attributeName.empty())
+ {
+ int semanticIndex = 0;
+ for (unsigned int attributeIndex = 0; attributeIndex < mActiveAttributes.size(); attributeIndex++)
+ {
+ const sh::ShaderVariable &attribute = mActiveAttributes[attributeIndex];
+
+ if (attribute.name == attributeName)
+ {
+ return semanticIndex;
+ }
+
+ semanticIndex += VariableRegisterCount(attribute.type);
+ }
+ }
+
+ return -1;
+}
+
+void VertexShader::parseAttributes()
+{
+ const std::string &hlsl = getHLSL();
+ if (!hlsl.empty())
+ {
+ mActiveAttributes = *GetShaderVariables(ShGetAttributes(mVertexCompiler));
+ }
+}
+
+FragmentShader::FragmentShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle)
+ : Shader(manager, renderer, handle)
{
}
@@ -167,4 +541,53 @@
{
}
+GLenum FragmentShader::getType() const
+{
+ return GL_FRAGMENT_SHADER;
+}
+
+void FragmentShader::compile()
+{
+ uncompile();
+
+ compileToHLSL(mFragmentCompiler);
+ parseVaryings(mFragmentCompiler);
+ std::sort(mVaryings.begin(), mVaryings.end(), compareVarying);
+
+ const std::string &hlsl = getHLSL();
+ if (!hlsl.empty())
+ {
+ mActiveOutputVariables = *GetShaderVariables(ShGetOutputVariables(mFragmentCompiler));
+ }
+}
+
+void FragmentShader::uncompile()
+{
+ Shader::uncompile();
+
+ mActiveOutputVariables.clear();
+}
+
+const std::vector<sh::Attribute> &FragmentShader::getOutputVariables() const
+{
+ return mActiveOutputVariables;
+}
+
+ShShaderOutput Shader::getCompilerOutputType(GLenum shader)
+{
+ void *compiler = NULL;
+
+ switch (shader)
+ {
+ case GL_VERTEX_SHADER: compiler = mVertexCompiler; break;
+ case GL_FRAGMENT_SHADER: compiler = mFragmentCompiler; break;
+ default: UNREACHABLE(); return SH_HLSL9_OUTPUT;
+ }
+
+ size_t outputType = 0;
+ ShGetInfo(compiler, SH_OUTPUT_TYPE, &outputType);
+
+ return static_cast<ShShaderOutput>(outputType);
+}
+
}