diff options
author | Andrew Knight <andrew.knight@digia.com> | 2014-09-25 13:22:55 +0300 |
---|---|---|
committer | Andrew Knight <andrew.knight@digia.com> | 2014-09-29 16:09:29 +0200 |
commit | 311157c3c6849e8efccd88f7594bb34c570a6780 (patch) | |
tree | a50c252b638488326529c0e69aa05e42abce7462 /src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp | |
parent | 04d3a89e20d49a3b5015b071bfdedc81973b090c (diff) |
ANGLE: Upgrade to 2.1~abce76206141
Upgrade to address issues discovered since the last upgrade.
Patch notes:
0000-General-fixes-for-ANGLE-2.1.patch
added removal of the unused third-party tracing functions
0003-Fix-compilation-with-MinGW-gcc-64-bit.patch
removed as it is no longer needed
0011-ANGLE-Fix-compilation-error-on-MinGW-caused-by-trace.patch
removed as it is no longer needed
0016-ANGLE-Fix-compilation-with-MinGW-D3D11.patch
now supports MinGW 64-bit
[ChangeLog][Third-party libraries] ANGLE updated to 2.1~f8602ad91e4f
Task-number: QTBUG-40649
Task-number: QTBUG-40658
Task-number: QTBUG-41031
Task-number: QTBUG-41081
Task-number: QTBUG-41308
Task-number: QTBUG-41563
Change-Id: I9f776c8d5cb94ddb12d608a8d5630bfc54437bea
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
Reviewed-by: Oliver Wolff <oliver.wolff@digia.com>
Reviewed-by: Kai Koehne <kai.koehne@digia.com>
Diffstat (limited to 'src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp')
-rw-r--r-- | src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp | 822 |
1 files changed, 379 insertions, 443 deletions
diff --git a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp index 9fad5fbfc5..3f6d9e0ef9 100644 --- a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp +++ b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // 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 @@ -11,33 +10,34 @@ #include "libGLESv2/BinaryStream.h" #include "libGLESv2/ProgramBinary.h" #include "libGLESv2/Framebuffer.h" +#include "libGLESv2/FramebufferAttachment.h" #include "libGLESv2/Renderbuffer.h" #include "libGLESv2/renderer/ShaderExecutable.h" #include "common/debug.h" #include "common/version.h" #include "common/utilities.h" +#include "common/platform.h" #include "libGLESv2/main.h" #include "libGLESv2/Shader.h" #include "libGLESv2/Program.h" +#include "libGLESv2/renderer/ProgramImpl.h" #include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/renderer/d3d/DynamicHLSL.h" +#include "libGLESv2/renderer/d3d/ShaderD3D.h" #include "libGLESv2/renderer/d3d/VertexDataManager.h" #include "libGLESv2/Context.h" #include "libGLESv2/Buffer.h" -#include "libGLESv2/DynamicHLSL.h" #include "common/blocklayout.h" -#undef near -#undef far - namespace gl { namespace { -TextureType GetTextureType(GLenum samplerType) +GLenum GetTextureType(GLenum samplerType) { switch (samplerType) { @@ -45,26 +45,26 @@ TextureType GetTextureType(GLenum samplerType) case GL_INT_SAMPLER_2D: case GL_UNSIGNED_INT_SAMPLER_2D: case GL_SAMPLER_2D_SHADOW: - return TEXTURE_2D; + return GL_TEXTURE_2D; case GL_SAMPLER_3D: case GL_INT_SAMPLER_3D: case GL_UNSIGNED_INT_SAMPLER_3D: - return TEXTURE_3D; + return GL_TEXTURE_3D; case GL_SAMPLER_CUBE: case GL_SAMPLER_CUBE_SHADOW: - return TEXTURE_CUBE; + return GL_TEXTURE_CUBE_MAP; case GL_INT_SAMPLER_CUBE: case GL_UNSIGNED_INT_SAMPLER_CUBE: - return TEXTURE_CUBE; + return GL_TEXTURE_CUBE_MAP; case GL_SAMPLER_2D_ARRAY: case GL_INT_SAMPLER_2D_ARRAY: case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: case GL_SAMPLER_2D_ARRAY_SHADOW: - return TEXTURE_2D_ARRAY; + return GL_TEXTURE_2D_ARRAY; default: UNREACHABLE(); } - return TEXTURE_2D; + return GL_TEXTURE_2D; } unsigned int ParseAndStripArrayIndex(std::string* name) @@ -83,7 +83,7 @@ unsigned int ParseAndStripArrayIndex(std::string* name) return subscript; } -void GetInputLayoutFromShader(const std::vector<sh::Attribute> &shaderAttributes, VertexFormat inputLayout[MAX_VERTEX_ATTRIBS]) +void GetDefaultInputLayoutFromShader(const std::vector<sh::Attribute> &shaderAttributes, VertexFormat inputLayout[MAX_VERTEX_ATTRIBS]) { size_t layoutIndex = 0; for (size_t attributeIndex = 0; attributeIndex < shaderAttributes.size(); attributeIndex++) @@ -109,6 +109,26 @@ void GetInputLayoutFromShader(const std::vector<sh::Attribute> &shaderAttributes } } +std::vector<GLenum> GetDefaultOutputLayoutFromShader(const std::vector<rx::PixelShaderOutputVariable> &shaderOutputVars) +{ + std::vector<GLenum> defaultPixelOutput(1); + + ASSERT(!shaderOutputVars.empty()); + defaultPixelOutput[0] = GL_COLOR_ATTACHMENT0 + shaderOutputVars[0].outputIndex; + + return defaultPixelOutput; +} + +bool IsRowMajorLayout(const sh::InterfaceBlockField &var) +{ + return var.isRowMajorLayout; +} + +bool IsRowMajorLayout(const sh::ShaderVariable &var) +{ + return false; +} + } VariableLocation::VariableLocation(const std::string &name, unsigned int element, unsigned int index) @@ -169,45 +189,30 @@ LinkedVarying::LinkedVarying(const std::string &name, GLenum type, GLsizei size, unsigned int ProgramBinary::mCurrentSerial = 1; -ProgramBinary::ProgramBinary(rx::Renderer *renderer) +ProgramBinary::ProgramBinary(rx::ProgramImpl *impl) : RefCountObject(0), - mRenderer(renderer), - mDynamicHLSL(NULL), - mVertexWorkarounds(rx::ANGLE_D3D_WORKAROUND_NONE), - mPixelWorkarounds(rx::ANGLE_D3D_WORKAROUND_NONE), + mProgram(impl), mGeometryExecutable(NULL), mUsedVertexSamplerRange(0), mUsedPixelSamplerRange(0), mUsesPointSize(false), mShaderVersion(100), mDirtySamplerMapping(true), - mVertexUniformStorage(NULL), - mFragmentUniformStorage(NULL), mValidated(false), mSerial(issueSerial()) { + ASSERT(impl); + for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++) { mSemanticIndex[index] = -1; } - - for (int index = 0; index < MAX_TEXTURE_IMAGE_UNITS; index++) - { - mSamplersPS[index].active = false; - } - - for (int index = 0; index < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; index++) - { - mSamplersVS[index].active = false; - } - - mDynamicHLSL = new DynamicHLSL(renderer); } ProgramBinary::~ProgramBinary() { reset(); - SafeDelete(mDynamicHLSL); + SafeDelete(mProgram); } unsigned int ProgramBinary::getSerial() const @@ -227,17 +232,21 @@ unsigned int ProgramBinary::issueSerial() rx::ShaderExecutable *ProgramBinary::getPixelExecutableForFramebuffer(const Framebuffer *fbo) { - std::vector<GLenum> outputs(IMPLEMENTATION_MAX_DRAW_BUFFERS); - for (size_t outputIndex = 0; outputIndex < IMPLEMENTATION_MAX_DRAW_BUFFERS; outputIndex++) + std::vector<GLenum> outputs; + + const gl::ColorbufferInfo &colorbuffers = fbo->getColorbuffersForRender(); + + for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment) { - if (fbo->getColorbuffer(outputIndex) != NULL) + const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment]; + + if (colorbuffer) { - // Always output floats for now - outputs[outputIndex] = GL_FLOAT; + outputs.push_back(colorbuffer->getBinding() == GL_BACK ? GL_COLOR_ATTACHMENT0 : colorbuffer->getBinding()); } else { - outputs[outputIndex] = GL_NONE; + outputs.push_back(GL_NONE); } } @@ -254,15 +263,9 @@ rx::ShaderExecutable *ProgramBinary::getPixelExecutableForOutputLayout(const std } } - std::string finalPixelHLSL = mDynamicHLSL->generatePixelShaderForOutputSignature(mPixelHLSL, mPixelShaderKey, mUsesFragDepth, - outputSignature); - - // Generate new pixel executable InfoLog tempInfoLog; - rx::ShaderExecutable *pixelExecutable = mRenderer->compileToExecutable(tempInfoLog, finalPixelHLSL.c_str(), rx::SHADER_PIXEL, - mTransformFeedbackLinkedVaryings, - (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS), - mPixelWorkarounds); + rx::ShaderExecutable *pixelExecutable = mProgram->getPixelExecutableForOutputLayout(tempInfoLog, outputSignature, + mTransformFeedbackLinkedVaryings, (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS)); if (!pixelExecutable) { @@ -281,7 +284,7 @@ rx::ShaderExecutable *ProgramBinary::getPixelExecutableForOutputLayout(const std rx::ShaderExecutable *ProgramBinary::getVertexExecutableForInputLayout(const VertexFormat inputLayout[MAX_VERTEX_ATTRIBS]) { GLenum signature[MAX_VERTEX_ATTRIBS]; - mDynamicHLSL->getInputLayoutSignature(inputLayout, signature); + mProgram->getDynamicHLSL()->getInputLayoutSignature(inputLayout, signature); for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++) { @@ -291,16 +294,9 @@ rx::ShaderExecutable *ProgramBinary::getVertexExecutableForInputLayout(const Ver } } - // Generate new dynamic layout with attribute conversions - std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(mVertexHLSL, inputLayout, mShaderAttributes); - - // Generate new vertex executable InfoLog tempInfoLog; - rx::ShaderExecutable *vertexExecutable = mRenderer->compileToExecutable(tempInfoLog, finalVertexHLSL.c_str(), - rx::SHADER_VERTEX, - mTransformFeedbackLinkedVaryings, - (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS), - mVertexWorkarounds); + rx::ShaderExecutable *vertexExecutable = mProgram->getVertexExecutableForInputLayout(tempInfoLog, inputLayout, mShaderAttributes, + mTransformFeedbackLinkedVaryings, (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS)); if (!vertexExecutable) { @@ -366,7 +362,7 @@ bool ProgramBinary::usesPointSize() const bool ProgramBinary::usesPointSpriteEmulation() const { - return mUsesPointSize && mRenderer->getMajorShaderModel() >= 4; + return mUsesPointSize && mProgram->getRenderer()->getMajorShaderModel() >= 4; } bool ProgramBinary::usesGeometryShader() const @@ -374,26 +370,22 @@ bool ProgramBinary::usesGeometryShader() const return usesPointSpriteEmulation(); } -// Returns the index of the texture image unit (0-19) corresponding to a Direct3D 9 sampler -// index (0-15 for the pixel shader and 0-3 for the vertex shader). -GLint ProgramBinary::getSamplerMapping(SamplerType type, unsigned int samplerIndex) +GLint ProgramBinary::getSamplerMapping(SamplerType type, unsigned int samplerIndex, const Caps &caps) { GLint logicalTextureUnit = -1; switch (type) { case SAMPLER_PIXEL: - ASSERT(samplerIndex < ArraySize(mSamplersPS)); - - if (mSamplersPS[samplerIndex].active) + ASSERT(samplerIndex < caps.maxTextureImageUnits); + if (samplerIndex < mSamplersPS.size() && mSamplersPS[samplerIndex].active) { logicalTextureUnit = mSamplersPS[samplerIndex].logicalTextureUnit; } break; case SAMPLER_VERTEX: - ASSERT(samplerIndex < ArraySize(mSamplersVS)); - - if (mSamplersVS[samplerIndex].active) + ASSERT(samplerIndex < caps.maxVertexTextureImageUnits); + if (samplerIndex < mSamplersVS.size() && mSamplersVS[samplerIndex].active) { logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit; } @@ -401,7 +393,7 @@ GLint ProgramBinary::getSamplerMapping(SamplerType type, unsigned int samplerInd default: UNREACHABLE(); } - if (logicalTextureUnit >= 0 && logicalTextureUnit < (GLint)mRenderer->getMaxCombinedTextureImageUnits()) + if (logicalTextureUnit >= 0 && logicalTextureUnit < static_cast<GLint>(caps.maxCombinedTextureImageUnits)) { return logicalTextureUnit; } @@ -411,22 +403,22 @@ GLint ProgramBinary::getSamplerMapping(SamplerType type, unsigned int samplerInd // Returns the texture type for a given Direct3D 9 sampler type and // index (0-15 for the pixel shader and 0-3 for the vertex shader). -TextureType ProgramBinary::getSamplerTextureType(SamplerType type, unsigned int samplerIndex) +GLenum ProgramBinary::getSamplerTextureType(SamplerType type, unsigned int samplerIndex) { switch (type) { case SAMPLER_PIXEL: - ASSERT(samplerIndex < ArraySize(mSamplersPS)); + ASSERT(samplerIndex < mSamplersPS.size()); ASSERT(mSamplersPS[samplerIndex].active); return mSamplersPS[samplerIndex].textureType; case SAMPLER_VERTEX: - ASSERT(samplerIndex < ArraySize(mSamplersVS)); + ASSERT(samplerIndex < mSamplersVS.size()); ASSERT(mSamplersVS[samplerIndex].active); return mSamplersVS[samplerIndex].textureType; default: UNREACHABLE(); } - return TEXTURE_2D; + return GL_TEXTURE_2D; } GLint ProgramBinary::getUniformLocation(std::string name) @@ -562,38 +554,64 @@ void ProgramBinary::setUniform(GLint location, GLsizei count, const T* v, GLenum if (targetUniform->type == targetUniformType) { - T *target = (T*)targetUniform->data + mUniformIndex[location].element * 4; + T *target = reinterpret_cast<T*>(targetUniform->data) + mUniformIndex[location].element * 4; for (int i = 0; i < count; i++) { + T *dest = target + (i * 4); + const T *source = v + (i * components); + for (int c = 0; c < components; c++) { - SetIfDirty(target + c, v[c], &targetUniform->dirty); + SetIfDirty(dest + c, source[c], &targetUniform->dirty); } for (int c = components; c < 4; c++) { - SetIfDirty(target + c, T(0), &targetUniform->dirty); + SetIfDirty(dest + c, T(0), &targetUniform->dirty); } - target += 4; - v += components; } } else if (targetUniform->type == targetBoolType) { - GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; + GLint *boolParams = reinterpret_cast<GLint*>(targetUniform->data) + mUniformIndex[location].element * 4; for (int i = 0; i < count; i++) { + GLint *dest = boolParams + (i * 4); + const T *source = v + (i * components); + for (int c = 0; c < components; c++) { - SetIfDirty(boolParams + c, (v[c] == static_cast<T>(0)) ? GL_FALSE : GL_TRUE, &targetUniform->dirty); + SetIfDirty(dest + c, (source[c] == static_cast<T>(0)) ? GL_FALSE : GL_TRUE, &targetUniform->dirty); } for (int c = components; c < 4; c++) { - SetIfDirty(boolParams + c, GL_FALSE, &targetUniform->dirty); + SetIfDirty(dest + c, GL_FALSE, &targetUniform->dirty); } - boolParams += 4; - v += components; + } + } + else if (IsSampler(targetUniform->type)) + { + ASSERT(targetUniformType == GL_INT); + + GLint *target = reinterpret_cast<GLint*>(targetUniform->data) + mUniformIndex[location].element * 4; + + bool wasDirty = targetUniform->dirty; + + for (int i = 0; i < count; i++) + { + GLint *dest = target + (i * 4); + const GLint *source = reinterpret_cast<const GLint*>(v) + (i * components); + + SetIfDirty(dest + 0, source[0], &targetUniform->dirty); + SetIfDirty(dest + 1, 0, &targetUniform->dirty); + SetIfDirty(dest + 2, 0, &targetUniform->dirty); + SetIfDirty(dest + 3, 0, &targetUniform->dirty); + } + + if (!wasDirty && targetUniform->dirty) + { + mDirtySamplerMapping = true; } } else UNREACHABLE(); @@ -761,48 +779,7 @@ void ProgramBinary::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboole void ProgramBinary::setUniform1iv(GLint location, GLsizei count, const GLint *v) { - LinkedUniform *targetUniform = mUniforms[mUniformIndex[location].index]; - - int elementCount = targetUniform->elementCount(); - - count = std::min(elementCount - (int)mUniformIndex[location].element, count); - - if (targetUniform->type == GL_INT || IsSampler(targetUniform->type)) - { - GLint *target = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - - for (int i = 0; i < count; i++) - { - SetIfDirty(target + 0, v[0], &targetUniform->dirty); - SetIfDirty(target + 1, 0, &targetUniform->dirty); - SetIfDirty(target + 2, 0, &targetUniform->dirty); - SetIfDirty(target + 3, 0, &targetUniform->dirty); - target += 4; - v += 1; - } - } - else if (targetUniform->type == GL_BOOL) - { - GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - - for (int i = 0; i < count; i++) - { - SetIfDirty(boolParams + 0, (v[0] == 0) ? GL_FALSE : GL_TRUE, &targetUniform->dirty); - SetIfDirty(boolParams + 1, GL_FALSE, &targetUniform->dirty); - SetIfDirty(boolParams + 2, GL_FALSE, &targetUniform->dirty); - SetIfDirty(boolParams + 3, GL_FALSE, &targetUniform->dirty); - boolParams += 4; - v += 1; - } - } - else UNREACHABLE(); - - // Set a special flag if we change a sampler uniform - if (IsSampler(targetUniform->type) && - (memcmp(targetUniform->data, v, sizeof(GLint)) != 0)) - { - mDirtySamplerMapping = true; - } + setUniform(location, count, v, GL_INT); } void ProgramBinary::setUniform2iv(GLint location, GLsizei count, const GLint *v) @@ -841,20 +818,10 @@ void ProgramBinary::setUniform4uiv(GLint location, GLsizei count, const GLuint * } template <typename T> -bool ProgramBinary::getUniformv(GLint location, GLsizei *bufSize, T *params, GLenum uniformType) +void ProgramBinary::getUniformv(GLint location, T *params, GLenum uniformType) { LinkedUniform *targetUniform = mUniforms[mUniformIndex[location].index]; - // sized queries -- ensure the provided buffer is large enough - if (bufSize) - { - int requiredBytes = VariableExternalSize(targetUniform->type); - if (*bufSize < requiredBytes) - { - return false; - } - } - if (IsMatrixType(targetUniform->type)) { const int rows = VariableRowCount(targetUniform->type); @@ -919,23 +886,21 @@ bool ProgramBinary::getUniformv(GLint location, GLsizei *bufSize, T *params, GLe default: UNREACHABLE(); } } - - return true; } -bool ProgramBinary::getUniformfv(GLint location, GLsizei *bufSize, GLfloat *params) +void ProgramBinary::getUniformfv(GLint location, GLfloat *params) { - return getUniformv(location, bufSize, params, GL_FLOAT); + getUniformv(location, params, GL_FLOAT); } -bool ProgramBinary::getUniformiv(GLint location, GLsizei *bufSize, GLint *params) +void ProgramBinary::getUniformiv(GLint location, GLint *params) { - return getUniformv(location, bufSize, params, GL_INT); + getUniformv(location, params, GL_INT); } -bool ProgramBinary::getUniformuiv(GLint location, GLsizei *bufSize, GLuint *params) +void ProgramBinary::getUniformuiv(GLint location, GLuint *params) { - return getUniformv(location, bufSize, params, GL_UNSIGNED_INT); + getUniformv(location, params, GL_UNSIGNED_INT); } void ProgramBinary::dirtyAllUniforms() @@ -976,7 +941,7 @@ void ProgramBinary::updateSamplerMapping() { unsigned int samplerIndex = firstIndex + i; - if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS) + if (samplerIndex < mSamplersPS.size()) { ASSERT(mSamplersPS[samplerIndex].active); mSamplersPS[samplerIndex].logicalTextureUnit = v[i][0]; @@ -992,7 +957,7 @@ void ProgramBinary::updateSamplerMapping() { unsigned int samplerIndex = firstIndex + i; - if (samplerIndex < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS) + if (samplerIndex < mSamplersVS.size()) { ASSERT(mSamplersVS[samplerIndex].active); mSamplersVS[samplerIndex].logicalTextureUnit = v[i][0]; @@ -1005,25 +970,31 @@ void ProgramBinary::updateSamplerMapping() } // Applies all the uniforms set for this program object to the renderer -void ProgramBinary::applyUniforms() +Error ProgramBinary::applyUniforms() { updateSamplerMapping(); - mRenderer->applyUniforms(*this); + Error error = mProgram->getRenderer()->applyUniforms(*this); + if (error.isError()) + { + return error; + } for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) { mUniforms[uniformIndex]->dirty = false; } + + return gl::Error(GL_NO_ERROR); } -bool ProgramBinary::applyUniformBuffers(const std::vector<gl::Buffer*> boundBuffers) +Error ProgramBinary::applyUniformBuffers(const std::vector<gl::Buffer*> boundBuffers, const Caps &caps) { const gl::Buffer *vertexUniformBuffers[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS] = {NULL}; const gl::Buffer *fragmentUniformBuffers[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS] = {NULL}; - const unsigned int reservedBuffersInVS = mRenderer->getReservedVertexUniformBuffers(); - const unsigned int reservedBuffersInFS = mRenderer->getReservedFragmentUniformBuffers(); + const unsigned int reservedBuffersInVS = mProgram->getRenderer()->getReservedVertexUniformBuffers(); + const unsigned int reservedBuffersInFS = mProgram->getRenderer()->getReservedFragmentUniformBuffers(); ASSERT(boundBuffers.size() == mUniformBlocks.size()); @@ -1037,16 +1008,20 @@ bool ProgramBinary::applyUniformBuffers(const std::vector<gl::Buffer*> boundBuff if (uniformBuffer->getSize() < uniformBlock->dataSize) { // undefined behaviour - return false; + return gl::Error(GL_INVALID_OPERATION, "It is undefined behaviour to use a uniform buffer that is too small."); } - ASSERT(uniformBlock->isReferencedByVertexShader() || uniformBlock->isReferencedByFragmentShader()); + // Unnecessary to apply an unreferenced standard or shared UBO + if (!uniformBlock->isReferencedByVertexShader() && !uniformBlock->isReferencedByFragmentShader()) + { + continue; + } if (uniformBlock->isReferencedByVertexShader()) { unsigned int registerIndex = uniformBlock->vsRegisterIndex - reservedBuffersInVS; ASSERT(vertexUniformBuffers[registerIndex] == NULL); - ASSERT(registerIndex < mRenderer->getMaxVertexShaderUniformBuffers()); + ASSERT(registerIndex < caps.maxVertexUniformBlocks); vertexUniformBuffers[registerIndex] = uniformBuffer; } @@ -1054,15 +1029,15 @@ bool ProgramBinary::applyUniformBuffers(const std::vector<gl::Buffer*> boundBuff { unsigned int registerIndex = uniformBlock->psRegisterIndex - reservedBuffersInFS; ASSERT(fragmentUniformBuffers[registerIndex] == NULL); - ASSERT(registerIndex < mRenderer->getMaxFragmentShaderUniformBuffers()); + ASSERT(registerIndex < caps.maxFragmentUniformBlocks); fragmentUniformBuffers[registerIndex] = uniformBuffer; } } - return mRenderer->setUniformBuffers(vertexUniformBuffers, fragmentUniformBuffers); + return mProgram->getRenderer()->setUniformBuffers(vertexUniformBuffers, fragmentUniformBuffers); } -bool ProgramBinary::linkVaryings(InfoLog &infoLog, FragmentShader *fragmentShader, VertexShader *vertexShader) +bool ProgramBinary::linkVaryings(InfoLog &infoLog, Shader *fragmentShader, Shader *vertexShader) { std::vector<PackedVarying> &fragmentVaryings = fragmentShader->getVaryings(); std::vector<PackedVarying> &vertexVaryings = vertexShader->getVaryings(); @@ -1072,24 +1047,32 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, FragmentShader *fragmentShade PackedVarying *input = &fragmentVaryings[fragVaryingIndex]; bool matched = false; + // Built-in varyings obey special rules + if (input->isBuiltIn()) + { + continue; + } + for (size_t vertVaryingIndex = 0; vertVaryingIndex < vertexVaryings.size(); vertVaryingIndex++) { PackedVarying *output = &vertexVaryings[vertVaryingIndex]; if (output->name == input->name) { - if (!linkValidateVariables(infoLog, output->name, *input, *output)) + if (!linkValidateVaryings(infoLog, output->name, *input, *output)) { return false; } output->registerIndex = input->registerIndex; + output->columnIndex = input->columnIndex; matched = true; break; } } - if (!matched) + // We permit unmatched, unreferenced varyings + if (!matched && input->staticUse) { infoLog.append("Fragment varying %s does not match any vertex varying", input->name.c_str()); return false; @@ -1099,17 +1082,19 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, FragmentShader *fragmentShade return true; } -bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) +bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *binary, GLsizei length) { #ifdef ANGLE_DISABLE_PROGRAM_BINARY_LOAD return false; #else + ASSERT(binaryFormat == mProgram->getBinaryFormat()); + reset(); BinaryInputStream stream(binary, length); - int format = stream.readInt<int>(); - if (format != GL_PROGRAM_BINARY_ANGLE) + GLenum format = stream.readInt<GLenum>(); + if (format != mProgram->getBinaryFormat()) { infoLog.append("Invalid program binary format."); return false; @@ -1149,18 +1134,23 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) initAttributesByLayout(); - for (unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i) + const unsigned int psSamplerCount = stream.readInt<unsigned int>(); + for (unsigned int i = 0; i < psSamplerCount; ++i) { - stream.readBool(&mSamplersPS[i].active); - stream.readInt(&mSamplersPS[i].logicalTextureUnit); - stream.readInt(&mSamplersPS[i].textureType); + Sampler sampler; + stream.readBool(&sampler.active); + stream.readInt(&sampler.logicalTextureUnit); + stream.readInt(&sampler.textureType); + mSamplersPS.push_back(sampler); } - - for (unsigned int i = 0; i < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; ++i) + const unsigned int vsSamplerCount = stream.readInt<unsigned int>(); + for (unsigned int i = 0; i < vsSamplerCount; ++i) { - stream.readBool(&mSamplersVS[i].active); - stream.readInt(&mSamplersVS[i].logicalTextureUnit); - stream.readInt(&mSamplersVS[i].textureType); + Sampler sampler; + stream.readBool(&sampler.active); + stream.readInt(&sampler.logicalTextureUnit); + stream.readInt(&sampler.textureType); + mSamplersVS.push_back(sampler); } stream.readInt(&mUsedVertexSamplerRange); @@ -1260,10 +1250,6 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) stream.readInt(&varying.semanticIndexCount); } - stream.readString(&mVertexHLSL); - - stream.readInt(&mVertexWorkarounds); - const unsigned int vertexShaderCount = stream.readInt<unsigned int>(); for (unsigned int vertexShaderIndex = 0; vertexShaderIndex < vertexShaderCount; vertexShaderIndex++) { @@ -1280,7 +1266,7 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) unsigned int vertexShaderSize = stream.readInt<unsigned int>(); const unsigned char *vertexShaderFunction = reinterpret_cast<const unsigned char*>(binary) + stream.offset(); - rx::ShaderExecutable *shaderExecutable = mRenderer->loadExecutable(reinterpret_cast<const DWORD*>(vertexShaderFunction), + rx::ShaderExecutable *shaderExecutable = mProgram->getRenderer()->loadExecutable(reinterpret_cast<const DWORD*>(vertexShaderFunction), vertexShaderSize, rx::SHADER_VERTEX, mTransformFeedbackLinkedVaryings, (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS)); @@ -1292,7 +1278,7 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) // generated converted input layout GLenum signature[MAX_VERTEX_ATTRIBS]; - mDynamicHLSL->getInputLayoutSignature(inputLayout, signature); + mProgram->getDynamicHLSL()->getInputLayoutSignature(inputLayout, signature); // add new binary mVertexExecutables.push_back(new VertexExecutable(inputLayout, signature, shaderExecutable)); @@ -1300,20 +1286,6 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) stream.skip(vertexShaderSize); } - stream.readString(&mPixelHLSL); - stream.readInt(&mPixelWorkarounds); - stream.readBool(&mUsesFragDepth); - - const size_t pixelShaderKeySize = stream.readInt<unsigned int>(); - mPixelShaderKey.resize(pixelShaderKeySize); - for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKeySize; pixelShaderKeyIndex++) - { - stream.readInt(&mPixelShaderKey[pixelShaderKeyIndex].type); - stream.readString(&mPixelShaderKey[pixelShaderKeyIndex].name); - stream.readString(&mPixelShaderKey[pixelShaderKeyIndex].source); - stream.readInt(&mPixelShaderKey[pixelShaderKeyIndex].outputIndex); - } - const size_t pixelShaderCount = stream.readInt<unsigned int>(); for (size_t pixelShaderIndex = 0; pixelShaderIndex < pixelShaderCount; pixelShaderIndex++) { @@ -1326,10 +1298,11 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) const size_t pixelShaderSize = stream.readInt<unsigned int>(); const unsigned char *pixelShaderFunction = reinterpret_cast<const unsigned char*>(binary) + stream.offset(); - rx::ShaderExecutable *shaderExecutable = mRenderer->loadExecutable(pixelShaderFunction, pixelShaderSize, - rx::SHADER_PIXEL, - mTransformFeedbackLinkedVaryings, - (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS)); + rx::Renderer *renderer = mProgram->getRenderer(); + rx::ShaderExecutable *shaderExecutable = renderer->loadExecutable(pixelShaderFunction, pixelShaderSize, + rx::SHADER_PIXEL, mTransformFeedbackLinkedVaryings, + (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS)); + if (!shaderExecutable) { infoLog.append("Could not create pixel shader."); @@ -1347,9 +1320,11 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) if (geometryShaderSize > 0) { const char *geometryShaderFunction = (const char*) binary + stream.offset(); - mGeometryExecutable = mRenderer->loadExecutable(reinterpret_cast<const DWORD*>(geometryShaderFunction), - geometryShaderSize, rx::SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings, - (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS)); + rx::Renderer *renderer = mProgram->getRenderer(); + mGeometryExecutable = renderer->loadExecutable(reinterpret_cast<const DWORD*>(geometryShaderFunction), + geometryShaderSize, rx::SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings, + (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS)); + if (!mGeometryExecutable) { infoLog.append("Could not create geometry shader."); @@ -1358,29 +1333,39 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) stream.skip(geometryShaderSize); } + if (!mProgram->load(infoLog, &stream)) + { + return false; + } + const char *ptr = (const char*) binary + stream.offset(); const GUID *binaryIdentifier = (const GUID *) ptr; ptr += sizeof(GUID); - GUID identifier = mRenderer->getAdapterIdentifier(); + GUID identifier = mProgram->getRenderer()->getAdapterIdentifier(); if (memcmp(&identifier, binaryIdentifier, sizeof(GUID)) != 0) { infoLog.append("Invalid program binary."); return false; } - initializeUniformStorage(); + mProgram->initializeUniformStorage(mUniforms); return true; #endif // #ifdef ANGLE_DISABLE_PROGRAM_BINARY_LOAD } -bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length) +bool ProgramBinary::save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length) { + if (binaryFormat) + { + *binaryFormat = mProgram->getBinaryFormat(); + } + BinaryOutputStream stream; - stream.writeInt(GL_PROGRAM_BINARY_ANGLE); + stream.writeInt(mProgram->getBinaryFormat()); stream.writeInt(ANGLE_MAJOR_VERSION); stream.writeInt(ANGLE_MINOR_VERSION); stream.writeBytes(reinterpret_cast<const unsigned char*>(ANGLE_COMMIT_HASH), ANGLE_COMMIT_HASH_SIZE); @@ -1395,14 +1380,16 @@ bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length) stream.writeInt(mSemanticIndex[i]); } - for (unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i) + stream.writeInt(mSamplersPS.size()); + for (unsigned int i = 0; i < mSamplersPS.size(); ++i) { stream.writeInt(mSamplersPS[i].active); stream.writeInt(mSamplersPS[i].logicalTextureUnit); stream.writeInt(mSamplersPS[i].textureType); } - for (unsigned int i = 0; i < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; ++i) + stream.writeInt(mSamplersVS.size()); + for (unsigned int i = 0; i < mSamplersVS.size(); ++i) { stream.writeInt(mSamplersVS[i].active); stream.writeInt(mSamplersVS[i].logicalTextureUnit); @@ -1477,9 +1464,6 @@ bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length) stream.writeInt(varying.semanticIndexCount); } - stream.writeString(mVertexHLSL); - stream.writeInt(mVertexWorkarounds); - stream.writeInt(mVertexExecutables.size()); for (size_t vertexExecutableIndex = 0; vertexExecutableIndex < mVertexExecutables.size(); vertexExecutableIndex++) { @@ -1501,20 +1485,6 @@ bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length) stream.writeBytes(vertexBlob, vertexShaderSize); } - stream.writeString(mPixelHLSL); - stream.writeInt(mPixelWorkarounds); - stream.writeInt(mUsesFragDepth); - - stream.writeInt(mPixelShaderKey.size()); - for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < mPixelShaderKey.size(); pixelShaderKeyIndex++) - { - const PixelShaderOuputVariable &variable = mPixelShaderKey[pixelShaderKeyIndex]; - stream.writeInt(variable.type); - stream.writeString(variable.name); - stream.writeString(variable.source); - stream.writeInt(variable.outputIndex); - } - stream.writeInt(mPixelExecutables.size()); for (size_t pixelExecutableIndex = 0; pixelExecutableIndex < mPixelExecutables.size(); pixelExecutableIndex++) { @@ -1543,7 +1513,17 @@ bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length) stream.writeBytes(geometryBlob, geometryShaderSize); } - GUID identifier = mRenderer->getAdapterIdentifier(); + if (!mProgram->save(&stream)) + { + if (length) + { + *length = 0; + } + + return false; + } + + GUID identifier = mProgram->getRenderer()->getAdapterIdentifier(); GLsizei streamLength = stream.length(); const void *streamData = stream.data(); @@ -1583,7 +1563,7 @@ bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length) GLint ProgramBinary::getLength() { GLint length; - if (save(NULL, INT_MAX, &length)) + if (save(NULL, NULL, INT_MAX, &length)) { return length; } @@ -1593,68 +1573,56 @@ GLint ProgramBinary::getLength() } } -bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader, - const std::vector<std::string>& transformFeedbackVaryings, GLenum transformFeedbackBufferMode) +bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBindings, Shader *fragmentShader, Shader *vertexShader, + const std::vector<std::string>& transformFeedbackVaryings, GLenum transformFeedbackBufferMode, const Caps &caps) { if (!fragmentShader || !fragmentShader->isCompiled()) { return false; } + ASSERT(fragmentShader->getType() == GL_FRAGMENT_SHADER); if (!vertexShader || !vertexShader->isCompiled()) { return false; } + ASSERT(vertexShader->getType() == GL_VERTEX_SHADER); reset(); - mTransformFeedbackBufferMode = transformFeedbackBufferMode; - - mShaderVersion = vertexShader->getShaderVersion(); + mSamplersPS.resize(caps.maxTextureImageUnits); + mSamplersVS.resize(caps.maxVertexTextureImageUnits); - mPixelHLSL = fragmentShader->getHLSL(); - mPixelWorkarounds = fragmentShader->getD3DWorkarounds(); - - mVertexHLSL = vertexShader->getHLSL(); - mVertexWorkarounds = vertexShader->getD3DWorkarounds(); + mTransformFeedbackBufferMode = transformFeedbackBufferMode; - // Map the varyings to the register file - VaryingPacking packing = { NULL }; - int registers = mDynamicHLSL->packVaryings(infoLog, packing, fragmentShader, vertexShader, transformFeedbackVaryings); + rx::ShaderD3D *vertexShaderD3D = rx::ShaderD3D::makeShaderD3D(vertexShader->getImplementation()); + rx::ShaderD3D *fragmentShaderD3D = rx::ShaderD3D::makeShaderD3D(fragmentShader->getImplementation()); - if (registers < 0) - { - return false; - } + mShaderVersion = vertexShaderD3D->getShaderVersion(); - if (!linkVaryings(infoLog, fragmentShader, vertexShader)) - { - return false; - } - - mUsesPointSize = vertexShader->usesPointSize(); + int registers; std::vector<LinkedVarying> linkedVaryings; - if (!mDynamicHLSL->generateShaderLinkHLSL(infoLog, registers, packing, mPixelHLSL, mVertexHLSL, - fragmentShader, vertexShader, transformFeedbackVaryings, - &linkedVaryings, &mOutputVariables, &mPixelShaderKey, &mUsesFragDepth)) + if (!mProgram->link(infoLog, fragmentShader, vertexShader, transformFeedbackVaryings, ®isters, &linkedVaryings, &mOutputVariables)) { return false; } + mUsesPointSize = vertexShaderD3D->usesPointSize(); + bool success = true; - if (!linkAttributes(infoLog, attributeBindings, fragmentShader, vertexShader)) + if (!linkAttributes(infoLog, attributeBindings, vertexShader)) { success = false; } - if (!linkUniforms(infoLog, *vertexShader, *fragmentShader)) + if (!linkUniforms(infoLog, *vertexShader, *fragmentShader, caps)) { success = false; } // special case for gl_DepthRange, the only built-in uniform (also a struct) - if (vertexShader->usesDepthRange() || fragmentShader->usesDepthRange()) + if (vertexShaderD3D->usesDepthRange() || fragmentShaderD3D->usesDepthRange()) { const sh::BlockMemberInfo &defaultInfo = sh::BlockMemberInfo::getDefaultBlockInfo(); @@ -1663,13 +1631,13 @@ bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBin mUniforms.push_back(new LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.diff", 0, -1, defaultInfo)); } - if (!linkUniformBlocks(infoLog, *vertexShader, *fragmentShader)) + if (!linkUniformBlocks(infoLog, *vertexShader, *fragmentShader, caps)) { success = false; } if (!gatherTransformFeedbackLinkedVaryings(infoLog, linkedVaryings, transformFeedbackVaryings, - transformFeedbackBufferMode, &mTransformFeedbackLinkedVaryings)) + transformFeedbackBufferMode, &mTransformFeedbackLinkedVaryings, caps)) { success = false; } @@ -1677,23 +1645,19 @@ bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBin if (success) { VertexFormat defaultInputLayout[MAX_VERTEX_ATTRIBS]; - GetInputLayoutFromShader(vertexShader->activeAttributes(), defaultInputLayout); + GetDefaultInputLayoutFromShader(vertexShader->getActiveAttributes(), defaultInputLayout); rx::ShaderExecutable *defaultVertexExecutable = getVertexExecutableForInputLayout(defaultInputLayout); - std::vector<GLenum> defaultPixelOutput(IMPLEMENTATION_MAX_DRAW_BUFFERS); - for (size_t i = 0; i < defaultPixelOutput.size(); i++) - { - defaultPixelOutput[i] = (i == 0) ? GL_FLOAT : GL_NONE; - } + std::vector<GLenum> defaultPixelOutput = GetDefaultOutputLayoutFromShader(mProgram->getPixelShaderKey()); rx::ShaderExecutable *defaultPixelExecutable = getPixelExecutableForOutputLayout(defaultPixelOutput); if (usesGeometryShader()) { - std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL(registers, fragmentShader, vertexShader); - mGeometryExecutable = mRenderer->compileToExecutable(infoLog, geometryHLSL.c_str(), rx::SHADER_GEOMETRY, - mTransformFeedbackLinkedVaryings, - (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS), - rx::ANGLE_D3D_WORKAROUND_NONE); + std::string geometryHLSL = mProgram->getDynamicHLSL()->generateGeometryShaderHLSL(registers, fragmentShaderD3D, vertexShaderD3D); + mGeometryExecutable = mProgram->getRenderer()->compileToExecutable(infoLog, geometryHLSL.c_str(), + rx::SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings, + (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS), + rx::ANGLE_D3D_WORKAROUND_NONE); } if (!defaultVertexExecutable || !defaultPixelExecutable || (usesGeometryShader() && !mGeometryExecutable)) @@ -1708,15 +1672,20 @@ bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBin } // Determines the mapping between GL attributes and Direct3D 9 vertex stream usage indices -bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader) +bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, const Shader *vertexShader) { + const rx::ShaderD3D *vertexShaderD3D = rx::ShaderD3D::makeShaderD3D(vertexShader->getImplementation()); + unsigned int usedLocations = 0; - const std::vector<sh::Attribute> &activeAttributes = vertexShader->activeAttributes(); + const std::vector<sh::Attribute> &shaderAttributes = vertexShader->getActiveAttributes(); // Link attributes that have a binding location - for (unsigned int attributeIndex = 0; attributeIndex < activeAttributes.size(); attributeIndex++) + for (unsigned int attributeIndex = 0; attributeIndex < shaderAttributes.size(); attributeIndex++) { - const sh::Attribute &attribute = activeAttributes[attributeIndex]; + const sh::Attribute &attribute = shaderAttributes[attributeIndex]; + + ASSERT(attribute.staticUse); + const int location = attribute.location == -1 ? attributeBindings.getAttributeBinding(attribute.name) : attribute.location; mShaderAttributes[attributeIndex] = attribute; @@ -1755,9 +1724,12 @@ bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &at } // Link attributes that don't have a binding location - for (unsigned int attributeIndex = 0; attributeIndex < activeAttributes.size(); attributeIndex++) + for (unsigned int attributeIndex = 0; attributeIndex < shaderAttributes.size(); attributeIndex++) { - const sh::Attribute &attribute = activeAttributes[attributeIndex]; + const sh::Attribute &attribute = shaderAttributes[attributeIndex]; + + ASSERT(attribute.staticUse); + const int location = attribute.location == -1 ? attributeBindings.getAttributeBinding(attribute.name) : attribute.location; if (location == -1) // Not set by glBindAttribLocation or by location layout qualifier @@ -1778,7 +1750,7 @@ bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &at for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; ) { - int index = vertexShader->getSemanticIndex(mLinkedAttribute[attributeIndex].name); + int index = vertexShaderD3D->getSemanticIndex(mLinkedAttribute[attributeIndex].name); int rows = VariableRegisterCount(mLinkedAttribute[attributeIndex].type); for (int r = 0; r < rows; r++) @@ -1811,32 +1783,29 @@ bool ProgramBinary::linkValidateVariablesBase(InfoLog &infoLog, const std::strin return false; } - return true; -} - -template <class ShaderVarType> -bool ProgramBinary::linkValidateFields(InfoLog &infoLog, const std::string &varName, const ShaderVarType &vertexVar, const ShaderVarType &fragmentVar) -{ - if (vertexVar.fields.size() != fragmentVar.fields.size()) + if (vertexVariable.fields.size() != fragmentVariable.fields.size()) { - infoLog.append("Structure lengths for %s differ between vertex and fragment shaders", varName.c_str()); + infoLog.append("Structure lengths for %s differ between vertex and fragment shaders", variableName.c_str()); return false; } - const unsigned int numMembers = vertexVar.fields.size(); + const unsigned int numMembers = vertexVariable.fields.size(); for (unsigned int memberIndex = 0; memberIndex < numMembers; memberIndex++) { - const ShaderVarType &vertexMember = vertexVar.fields[memberIndex]; - const ShaderVarType &fragmentMember = fragmentVar.fields[memberIndex]; + const sh::ShaderVariable &vertexMember = vertexVariable.fields[memberIndex]; + const sh::ShaderVariable &fragmentMember = fragmentVariable.fields[memberIndex]; if (vertexMember.name != fragmentMember.name) { infoLog.append("Name mismatch for field '%d' of %s: (in vertex: '%s', in fragment: '%s')", - memberIndex, varName.c_str(), vertexMember.name.c_str(), fragmentMember.name.c_str()); + memberIndex, variableName.c_str(), + vertexMember.name.c_str(), fragmentMember.name.c_str()); return false; } - const std::string memberName = varName.substr(0, varName.length()-1) + "." + vertexVar.name + "'"; - if (!linkValidateVariables(infoLog, memberName, vertexMember, fragmentMember)) + const std::string memberName = variableName.substr(0, variableName.length() - 1) + "." + + vertexMember.name + "'"; + + if (!linkValidateVariablesBase(infoLog, vertexMember.name, vertexMember, fragmentMember, validatePrecision)) { return false; } @@ -1845,22 +1814,17 @@ bool ProgramBinary::linkValidateFields(InfoLog &infoLog, const std::string &varN return true; } -bool ProgramBinary::linkValidateVariables(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform) +bool ProgramBinary::linkValidateUniforms(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform) { if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform, true)) { return false; } - if (!linkValidateFields<sh::Uniform>(infoLog, uniformName, vertexUniform, fragmentUniform)) - { - return false; - } - return true; } -bool ProgramBinary::linkValidateVariables(InfoLog &infoLog, const std::string &varyingName, const sh::Varying &vertexVarying, const sh::Varying &fragmentVarying) +bool ProgramBinary::linkValidateVaryings(InfoLog &infoLog, const std::string &varyingName, const sh::Varying &vertexVarying, const sh::Varying &fragmentVarying) { if (!linkValidateVariablesBase(infoLog, varyingName, vertexVarying, fragmentVarying, false)) { @@ -1873,37 +1837,30 @@ bool ProgramBinary::linkValidateVariables(InfoLog &infoLog, const std::string &v return false; } - if (!linkValidateFields<sh::Varying>(infoLog, varyingName, vertexVarying, fragmentVarying)) - { - return false; - } - return true; } -bool ProgramBinary::linkValidateVariables(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform) +bool ProgramBinary::linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform) { if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform, true)) { return false; } - if (vertexUniform.isRowMajorMatrix != fragmentUniform.isRowMajorMatrix) + if (vertexUniform.isRowMajorLayout != fragmentUniform.isRowMajorLayout) { infoLog.append("Matrix packings for %s differ between vertex and fragment shaders", uniformName.c_str()); return false; } - if (!linkValidateFields<sh::InterfaceBlockField>(infoLog, uniformName, vertexUniform, fragmentUniform)) - { - return false; - } - return true; } -bool ProgramBinary::linkUniforms(InfoLog &infoLog, const VertexShader &vertexShader, const FragmentShader &fragmentShader) +bool ProgramBinary::linkUniforms(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps) { + const rx::ShaderD3D *vertexShaderD3D = rx::ShaderD3D::makeShaderD3D(vertexShader.getImplementation()); + const rx::ShaderD3D *fragmentShaderD3D = rx::ShaderD3D::makeShaderD3D(fragmentShader.getImplementation()); + const std::vector<sh::Uniform> &vertexUniforms = vertexShader.getUniforms(); const std::vector<sh::Uniform> &fragmentUniforms = fragmentShader.getUniforms(); @@ -1925,7 +1882,7 @@ bool ProgramBinary::linkUniforms(InfoLog &infoLog, const VertexShader &vertexSha { const sh::Uniform &vertexUniform = *entry->second; const std::string &uniformName = "uniform '" + vertexUniform.name + "'"; - if (!linkValidateVariables(infoLog, uniformName, vertexUniform, fragmentUniform)) + if (!linkValidateUniforms(infoLog, uniformName, vertexUniform, fragmentUniform)) { return false; } @@ -1935,35 +1892,43 @@ bool ProgramBinary::linkUniforms(InfoLog &infoLog, const VertexShader &vertexSha for (unsigned int uniformIndex = 0; uniformIndex < vertexUniforms.size(); uniformIndex++) { const sh::Uniform &uniform = vertexUniforms[uniformIndex]; - defineUniformBase(GL_VERTEX_SHADER, uniform, vertexShader.getUniformRegister(uniform.name)); + + if (uniform.staticUse) + { + defineUniformBase(GL_VERTEX_SHADER, uniform, vertexShaderD3D->getUniformRegister(uniform.name)); + } } for (unsigned int uniformIndex = 0; uniformIndex < fragmentUniforms.size(); uniformIndex++) { const sh::Uniform &uniform = fragmentUniforms[uniformIndex]; - defineUniformBase(GL_FRAGMENT_SHADER, uniform, fragmentShader.getUniformRegister(uniform.name)); + + if (uniform.staticUse) + { + defineUniformBase(GL_FRAGMENT_SHADER, uniform, fragmentShaderD3D->getUniformRegister(uniform.name)); + } } - if (!indexUniforms(infoLog)) + if (!indexUniforms(infoLog, caps)) { return false; } - initializeUniformStorage(); + mProgram->initializeUniformStorage(mUniforms); return true; } void ProgramBinary::defineUniformBase(GLenum shader, const sh::Uniform &uniform, unsigned int uniformRegister) { - ShShaderOutput outputType = Shader::getCompilerOutputType(shader); + ShShaderOutput outputType = rx::ShaderD3D::getCompilerOutputType(shader); sh::HLSLBlockEncoder encoder(sh::HLSLBlockEncoder::GetStrategyFor(outputType)); encoder.skipRegisters(uniformRegister); defineUniform(shader, uniform, uniform.name, &encoder); } -void ProgramBinary::defineUniform(GLenum shader, const sh::Uniform &uniform, +void ProgramBinary::defineUniform(GLenum shader, const sh::ShaderVariable &uniform, const std::string &fullName, sh::HLSLBlockEncoder *encoder) { if (uniform.isStruct()) @@ -1976,7 +1941,7 @@ void ProgramBinary::defineUniform(GLenum shader, const sh::Uniform &uniform, for (size_t fieldIndex = 0; fieldIndex < uniform.fields.size(); fieldIndex++) { - const sh::Uniform &field = uniform.fields[fieldIndex]; + const sh::ShaderVariable &field = uniform.fields[fieldIndex]; const std::string &fieldFullName = (fullName + elementString + "." + field.name); defineUniform(shader, field, fieldFullName, encoder); @@ -2027,7 +1992,7 @@ void ProgramBinary::defineUniform(GLenum shader, const sh::Uniform &uniform, } } -bool ProgramBinary::indexSamplerUniform(const LinkedUniform &uniform, InfoLog &infoLog) +bool ProgramBinary::indexSamplerUniform(const LinkedUniform &uniform, InfoLog &infoLog, const Caps &caps) { ASSERT(IsSampler(uniform.type)); ASSERT(uniform.vsRegisterIndex != GL_INVALID_INDEX || uniform.psRegisterIndex != GL_INVALID_INDEX); @@ -2035,19 +2000,18 @@ bool ProgramBinary::indexSamplerUniform(const LinkedUniform &uniform, InfoLog &i if (uniform.vsRegisterIndex != GL_INVALID_INDEX) { if (!assignSamplers(uniform.vsRegisterIndex, uniform.type, uniform.arraySize, mSamplersVS, - &mUsedVertexSamplerRange, mRenderer->getMaxVertexTextureImageUnits())) + &mUsedVertexSamplerRange)) { infoLog.append("Vertex shader sampler count exceeds the maximum vertex texture units (%d).", - mRenderer->getMaxVertexTextureImageUnits()); + mSamplersVS.size()); return false; } - unsigned int maxVertexVectors = mRenderer->getReservedVertexUniformVectors() + - mRenderer->getMaxVertexUniformVectors(); + unsigned int maxVertexVectors = mProgram->getRenderer()->getReservedVertexUniformVectors() + caps.maxVertexUniformVectors; if (uniform.vsRegisterIndex + uniform.registerCount > maxVertexVectors) { infoLog.append("Vertex shader active uniforms exceed GL_MAX_VERTEX_UNIFORM_VECTORS (%u)", - mRenderer->getMaxVertexUniformVectors()); + caps.maxVertexUniformVectors); return false; } } @@ -2055,19 +2019,18 @@ bool ProgramBinary::indexSamplerUniform(const LinkedUniform &uniform, InfoLog &i if (uniform.psRegisterIndex != GL_INVALID_INDEX) { if (!assignSamplers(uniform.psRegisterIndex, uniform.type, uniform.arraySize, mSamplersPS, - &mUsedPixelSamplerRange, MAX_TEXTURE_IMAGE_UNITS)) + &mUsedPixelSamplerRange)) { infoLog.append("Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (%d).", - MAX_TEXTURE_IMAGE_UNITS); + mSamplersPS.size()); return false; } - unsigned int maxFragmentVectors = mRenderer->getReservedFragmentUniformVectors() + - mRenderer->getMaxFragmentUniformVectors(); + unsigned int maxFragmentVectors = mProgram->getRenderer()->getReservedFragmentUniformVectors() + caps.maxFragmentUniformVectors; if (uniform.psRegisterIndex + uniform.registerCount > maxFragmentVectors) { infoLog.append("Fragment shader active uniforms exceed GL_MAX_FRAGMENT_UNIFORM_VECTORS (%u)", - mRenderer->getMaxFragmentUniformVectors()); + caps.maxFragmentUniformVectors); return false; } } @@ -2075,7 +2038,7 @@ bool ProgramBinary::indexSamplerUniform(const LinkedUniform &uniform, InfoLog &i return true; } -bool ProgramBinary::indexUniforms(InfoLog &infoLog) +bool ProgramBinary::indexUniforms(InfoLog &infoLog, const Caps &caps) { for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) { @@ -2083,7 +2046,7 @@ bool ProgramBinary::indexUniforms(InfoLog &infoLog) if (IsSampler(uniform.type)) { - if (!indexSamplerUniform(uniform, infoLog)) + if (!indexSamplerUniform(uniform, infoLog, caps)) { return false; } @@ -2101,20 +2064,20 @@ bool ProgramBinary::indexUniforms(InfoLog &infoLog) bool ProgramBinary::assignSamplers(unsigned int startSamplerIndex, GLenum samplerType, unsigned int samplerCount, - Sampler *outArray, - GLuint *usedRange, - unsigned int limit) + std::vector<Sampler> &outSamplers, + GLuint *outUsedRange) { unsigned int samplerIndex = startSamplerIndex; do { - if (samplerIndex < limit) + if (samplerIndex < outSamplers.size()) { - outArray[samplerIndex].active = true; - outArray[samplerIndex].textureType = GetTextureType(samplerType); - outArray[samplerIndex].logicalTextureUnit = 0; - *usedRange = std::max(samplerIndex + 1, *usedRange); + Sampler& sampler = outSamplers[samplerIndex]; + sampler.active = true; + sampler.textureType = GetTextureType(samplerType); + sampler.logicalTextureUnit = 0; + *outUsedRange = std::max(samplerIndex + 1, *outUsedRange); } else { @@ -2163,8 +2126,8 @@ bool ProgramBinary::areMatchingInterfaceBlocks(InfoLog &infoLog, const sh::Inter return false; } - std::string uniformName = "interface block '" + vertexInterfaceBlock.name + "' member '" + vertexMember.name + "'"; - if (!linkValidateVariables(infoLog, uniformName, vertexMember, fragmentMember)) + std::string memberName = "interface block '" + vertexInterfaceBlock.name + "' member '" + vertexMember.name + "'"; + if (!linkValidateInterfaceBlockFields(infoLog, memberName, vertexMember, fragmentMember)) { return false; } @@ -2173,8 +2136,7 @@ bool ProgramBinary::areMatchingInterfaceBlocks(InfoLog &infoLog, const sh::Inter return true; } -bool ProgramBinary::linkUniformBlocks(InfoLog &infoLog, const VertexShader &vertexShader, - const FragmentShader &fragmentShader) +bool ProgramBinary::linkUniformBlocks(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps) { const std::vector<sh::InterfaceBlock> &vertexInterfaceBlocks = vertexShader.getInterfaceBlocks(); const std::vector<sh::InterfaceBlock> &fragmentInterfaceBlocks = fragmentShader.getInterfaceBlocks(); @@ -2205,17 +2167,29 @@ bool ProgramBinary::linkUniformBlocks(InfoLog &infoLog, const VertexShader &vert for (unsigned int blockIndex = 0; blockIndex < vertexInterfaceBlocks.size(); blockIndex++) { - if (!defineUniformBlock(infoLog, vertexShader, vertexInterfaceBlocks[blockIndex])) + const sh::InterfaceBlock &interfaceBlock = vertexInterfaceBlocks[blockIndex]; + + // Note: shared and std140 layouts are always considered active + if (interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED) { - return false; + if (!defineUniformBlock(infoLog, vertexShader, interfaceBlock, caps)) + { + return false; + } } } for (unsigned int blockIndex = 0; blockIndex < fragmentInterfaceBlocks.size(); blockIndex++) { - if (!defineUniformBlock(infoLog, fragmentShader, fragmentInterfaceBlocks[blockIndex])) + const sh::InterfaceBlock &interfaceBlock = fragmentInterfaceBlocks[blockIndex]; + + // Note: shared and std140 layouts are always considered active + if (interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED) { - return false; + if (!defineUniformBlock(infoLog, fragmentShader, interfaceBlock, caps)) + { + return false; + } } } @@ -2225,11 +2199,10 @@ bool ProgramBinary::linkUniformBlocks(InfoLog &infoLog, const VertexShader &vert bool ProgramBinary::gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, const std::vector<LinkedVarying> &linkedVaryings, const std::vector<std::string> &transformFeedbackVaryingNames, GLenum transformFeedbackBufferMode, - std::vector<LinkedVarying> *outTransformFeedbackLinkedVaryings) const + std::vector<LinkedVarying> *outTransformFeedbackLinkedVaryings, + const Caps &caps) const { size_t totalComponents = 0; - const size_t maxSeparateComponents = mRenderer->getMaxTransformFeedbackSeparateComponents(); - const size_t maxInterleavedComponents = mRenderer->getMaxTransformFeedbackInterleavedComponents(); // Gather the linked varyings that are used for transform feedback, they should all exist. outTransformFeedbackLinkedVaryings->clear(); @@ -2251,10 +2224,10 @@ bool ProgramBinary::gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, cons size_t componentCount = linkedVaryings[j].semanticIndexCount * 4; if (transformFeedbackBufferMode == GL_SEPARATE_ATTRIBS && - componentCount > maxSeparateComponents) + componentCount > caps.maxTransformFeedbackSeparateComponents) { infoLog.append("Transform feedback varying's %s components (%u) exceed the maximum separate components (%u).", - linkedVaryings[j].name.c_str(), componentCount, maxSeparateComponents); + linkedVaryings[j].name.c_str(), componentCount, caps.maxTransformFeedbackSeparateComponents); return false; } @@ -2270,39 +2243,45 @@ bool ProgramBinary::gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, cons ASSERT(found); } - if (transformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS && totalComponents > maxInterleavedComponents) + if (transformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS && totalComponents > caps.maxTransformFeedbackInterleavedComponents) { infoLog.append("Transform feedback varying total components (%u) exceed the maximum interleaved components (%u).", - totalComponents, maxInterleavedComponents); + totalComponents, caps.maxTransformFeedbackInterleavedComponents); return false; } return true; } -void ProgramBinary::defineUniformBlockMembers(const std::vector<sh::InterfaceBlockField> &fields, const std::string &prefix, int blockIndex, - sh::BlockLayoutEncoder *encoder, std::vector<unsigned int> *blockUniformIndexes) +template <typename VarT> +void ProgramBinary::defineUniformBlockMembers(const std::vector<VarT> &fields, const std::string &prefix, int blockIndex, + sh::BlockLayoutEncoder *encoder, std::vector<unsigned int> *blockUniformIndexes, + bool inRowMajorLayout) { for (unsigned int uniformIndex = 0; uniformIndex < fields.size(); uniformIndex++) { - const sh::InterfaceBlockField &field = fields[uniformIndex]; + const VarT &field = fields[uniformIndex]; const std::string &fieldName = (prefix.empty() ? field.name : prefix + "." + field.name); if (field.isStruct()) { + bool rowMajorLayout = (inRowMajorLayout || IsRowMajorLayout(field)); + for (unsigned int arrayElement = 0; arrayElement < field.elementCount(); arrayElement++) { encoder->enterAggregateType(); const std::string uniformElementName = fieldName + (field.isArray() ? ArrayString(arrayElement) : ""); - defineUniformBlockMembers(field.fields, uniformElementName, blockIndex, encoder, blockUniformIndexes); + defineUniformBlockMembers(field.fields, uniformElementName, blockIndex, encoder, blockUniformIndexes, rowMajorLayout); encoder->exitAggregateType(); } } else { - sh::BlockMemberInfo memberInfo = encoder->encodeInterfaceBlockField(field); + bool isRowMajorMatrix = (IsMatrixType(field.type) && inRowMajorLayout); + + sh::BlockMemberInfo memberInfo = encoder->encodeType(field.type, field.arraySize, isRowMajorMatrix); LinkedUniform *newUniform = new LinkedUniform(field.type, field.precision, fieldName, field.arraySize, blockIndex, memberInfo); @@ -2314,8 +2293,10 @@ void ProgramBinary::defineUniformBlockMembers(const std::vector<sh::InterfaceBlo } } -bool ProgramBinary::defineUniformBlock(InfoLog &infoLog, const Shader &shader, const sh::InterfaceBlock &interfaceBlock) +bool ProgramBinary::defineUniformBlock(InfoLog &infoLog, const Shader &shader, const sh::InterfaceBlock &interfaceBlock, const Caps &caps) { + const rx::ShaderD3D* shaderD3D = rx::ShaderD3D::makeShaderD3D(shader.getImplementation()); + // create uniform block entries if they do not exist if (getUniformBlockIndex(interfaceBlock.name) == GL_INVALID_INDEX) { @@ -2335,7 +2316,7 @@ bool ProgramBinary::defineUniformBlock(InfoLog &infoLog, const Shader &shader, c } ASSERT(encoder); - defineUniformBlockMembers(interfaceBlock.fields, "", blockIndex, encoder, &blockUniformIndexes); + defineUniformBlockMembers(interfaceBlock.fields, "", blockIndex, encoder, &blockUniformIndexes, interfaceBlock.isRowMajorLayout); size_t dataSize = encoder->getBlockSize(); @@ -2357,50 +2338,49 @@ bool ProgramBinary::defineUniformBlock(InfoLog &infoLog, const Shader &shader, c } } - // Assign registers to the uniform blocks - const GLuint blockIndex = getUniformBlockIndex(interfaceBlock.name); - const unsigned int elementCount = std::max(1u, interfaceBlock.arraySize); - ASSERT(blockIndex != GL_INVALID_INDEX); - ASSERT(blockIndex + elementCount <= mUniformBlocks.size()); - - unsigned int interfaceBlockRegister = shader.getInterfaceBlockRegister(interfaceBlock.name); - - for (unsigned int uniformBlockElement = 0; uniformBlockElement < elementCount; uniformBlockElement++) + if (interfaceBlock.staticUse) { - UniformBlock *uniformBlock = mUniformBlocks[blockIndex + uniformBlockElement]; - ASSERT(uniformBlock->name == interfaceBlock.name); + // Assign registers to the uniform blocks + const GLuint blockIndex = getUniformBlockIndex(interfaceBlock.name); + const unsigned int elementCount = std::max(1u, interfaceBlock.arraySize); + ASSERT(blockIndex != GL_INVALID_INDEX); + ASSERT(blockIndex + elementCount <= mUniformBlocks.size()); + + unsigned int interfaceBlockRegister = shaderD3D->getInterfaceBlockRegister(interfaceBlock.name); - if (!assignUniformBlockRegister(infoLog, uniformBlock, shader.getType(), - interfaceBlockRegister + uniformBlockElement)) + for (unsigned int uniformBlockElement = 0; uniformBlockElement < elementCount; uniformBlockElement++) { - return false; + UniformBlock *uniformBlock = mUniformBlocks[blockIndex + uniformBlockElement]; + ASSERT(uniformBlock->name == interfaceBlock.name); + + if (!assignUniformBlockRegister(infoLog, uniformBlock, shader.getType(), + interfaceBlockRegister + uniformBlockElement, caps)) + { + return false; + } } } return true; } -bool ProgramBinary::assignUniformBlockRegister(InfoLog &infoLog, UniformBlock *uniformBlock, GLenum shader, unsigned int registerIndex) +bool ProgramBinary::assignUniformBlockRegister(InfoLog &infoLog, UniformBlock *uniformBlock, GLenum shader, unsigned int registerIndex, const Caps &caps) { if (shader == GL_VERTEX_SHADER) { uniformBlock->vsRegisterIndex = registerIndex; - unsigned int maximumBlocks = mRenderer->getMaxVertexShaderUniformBuffers(); - - if (registerIndex - mRenderer->getReservedVertexUniformBuffers() >= maximumBlocks) + if (registerIndex - mProgram->getRenderer()->getReservedVertexUniformBuffers() >= caps.maxVertexUniformBlocks) { - infoLog.append("Vertex shader uniform block count exceed GL_MAX_VERTEX_UNIFORM_BLOCKS (%u)", maximumBlocks); + infoLog.append("Vertex shader uniform block count exceed GL_MAX_VERTEX_UNIFORM_BLOCKS (%u)", caps.maxVertexUniformBlocks); return false; } } else if (shader == GL_FRAGMENT_SHADER) { uniformBlock->psRegisterIndex = registerIndex; - unsigned int maximumBlocks = mRenderer->getMaxFragmentShaderUniformBuffers(); - - if (registerIndex - mRenderer->getReservedFragmentUniformBuffers() >= maximumBlocks) + if (registerIndex - mProgram->getRenderer()->getReservedFragmentUniformBuffers() >= caps.maxFragmentUniformBlocks) { - infoLog.append("Fragment shader uniform block count exceed GL_MAX_FRAGMENT_UNIFORM_BLOCKS (%u)", maximumBlocks); + infoLog.append("Fragment shader uniform block count exceed GL_MAX_FRAGMENT_UNIFORM_BLOCKS (%u)", caps.maxFragmentUniformBlocks); return false; } } @@ -2670,10 +2650,10 @@ GLuint ProgramBinary::getActiveUniformBlockMaxLength() const return maxLength; } -void ProgramBinary::validate(InfoLog &infoLog) +void ProgramBinary::validate(InfoLog &infoLog, const Caps &caps) { applyUniforms(); - if (!validateSamplers(&infoLog)) + if (!validateSamplers(&infoLog, caps)) { mValidated = false; } @@ -2683,20 +2663,14 @@ void ProgramBinary::validate(InfoLog &infoLog) } } -bool ProgramBinary::validateSamplers(InfoLog *infoLog) +bool ProgramBinary::validateSamplers(InfoLog *infoLog, const Caps &caps) { // if any two active samplers in a program are of different types, but refer to the same // texture image unit, and this is the current program, then ValidateProgram will fail, and // DrawArrays and DrawElements will issue the INVALID_OPERATION error. updateSamplerMapping(); - const unsigned int maxCombinedTextureImageUnits = mRenderer->getMaxCombinedTextureImageUnits(); - TextureType textureUnitType[IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS]; - - for (unsigned int i = 0; i < IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS; ++i) - { - textureUnitType[i] = TEXTURE_UNKNOWN; - } + std::vector<GLenum> textureUnitTypes(caps.maxCombinedTextureImageUnits, GL_NONE); for (unsigned int i = 0; i < mUsedPixelSamplerRange; ++i) { @@ -2704,19 +2678,19 @@ bool ProgramBinary::validateSamplers(InfoLog *infoLog) { unsigned int unit = mSamplersPS[i].logicalTextureUnit; - if (unit >= maxCombinedTextureImageUnits) + if (unit >= textureUnitTypes.size()) { if (infoLog) { - infoLog->append("Sampler uniform (%d) exceeds IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits); + infoLog->append("Sampler uniform (%d) exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, textureUnitTypes.size()); } return false; } - if (textureUnitType[unit] != TEXTURE_UNKNOWN) + if (textureUnitTypes[unit] != GL_NONE) { - if (mSamplersPS[i].textureType != textureUnitType[unit]) + if (mSamplersPS[i].textureType != textureUnitTypes[unit]) { if (infoLog) { @@ -2728,7 +2702,7 @@ bool ProgramBinary::validateSamplers(InfoLog *infoLog) } else { - textureUnitType[unit] = mSamplersPS[i].textureType; + textureUnitTypes[unit] = mSamplersPS[i].textureType; } } } @@ -2739,19 +2713,19 @@ bool ProgramBinary::validateSamplers(InfoLog *infoLog) { unsigned int unit = mSamplersVS[i].logicalTextureUnit; - if (unit >= maxCombinedTextureImageUnits) + if (unit >= textureUnitTypes.size()) { if (infoLog) { - infoLog->append("Sampler uniform (%d) exceeds IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits); + infoLog->append("Sampler uniform (%d) exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, textureUnitTypes.size()); } return false; } - if (textureUnitType[unit] != TEXTURE_UNKNOWN) + if (textureUnitTypes[unit] != GL_NONE) { - if (mSamplersVS[i].textureType != textureUnitType[unit]) + if (mSamplersVS[i].textureType != textureUnitTypes[unit]) { if (infoLog) { @@ -2763,7 +2737,7 @@ bool ProgramBinary::validateSamplers(InfoLog *infoLog) } else { - textureUnitType[unit] = mSamplersVS[i].textureType; + textureUnitTypes[unit] = mSamplersVS[i].textureType; } } } @@ -2771,7 +2745,7 @@ bool ProgramBinary::validateSamplers(InfoLog *infoLog) return true; } -ProgramBinary::Sampler::Sampler() : active(false), logicalTextureUnit(0), textureType(TEXTURE_2D) +ProgramBinary::Sampler::Sampler() : active(false), logicalTextureUnit(0), textureType(GL_TEXTURE_2D) { } @@ -2819,42 +2793,9 @@ void ProgramBinary::sortAttributesByLayout(rx::TranslatedAttribute attributes[MA } } -void ProgramBinary::initializeUniformStorage() -{ - // Compute total default block size - unsigned int vertexRegisters = 0; - unsigned int fragmentRegisters = 0; - for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) - { - const LinkedUniform &uniform = *mUniforms[uniformIndex]; - - if (!IsSampler(uniform.type)) - { - if (uniform.isReferencedByVertexShader()) - { - vertexRegisters = std::max(vertexRegisters, uniform.vsRegisterIndex + uniform.registerCount); - } - if (uniform.isReferencedByFragmentShader()) - { - fragmentRegisters = std::max(fragmentRegisters, uniform.psRegisterIndex + uniform.registerCount); - } - } - } - - mVertexUniformStorage = mRenderer->createUniformStorage(vertexRegisters * 16u); - mFragmentUniformStorage = mRenderer->createUniformStorage(fragmentRegisters * 16u); -} - void ProgramBinary::reset() { - mVertexHLSL.clear(); - mVertexWorkarounds = rx::ANGLE_D3D_WORKAROUND_NONE; SafeDeleteContainer(mVertexExecutables); - - mPixelHLSL.clear(); - mPixelWorkarounds = rx::ANGLE_D3D_WORKAROUND_NONE; - mUsesFragDepth = false; - mPixelShaderKey.clear(); SafeDeleteContainer(mPixelExecutables); SafeDelete(mGeometryExecutable); @@ -2862,14 +2803,9 @@ void ProgramBinary::reset() mTransformFeedbackBufferMode = GL_NONE; mTransformFeedbackLinkedVaryings.clear(); - for (size_t i = 0; i < ArraySize(mSamplersPS); i++) - { - mSamplersPS[i] = Sampler(); - } - for (size_t i = 0; i < ArraySize(mSamplersVS); i++) - { - mSamplersVS[i] = Sampler(); - } + mSamplersPS.clear(); + mSamplersVS.clear(); + mUsedVertexSamplerRange = 0; mUsedPixelSamplerRange = 0; mUsesPointSize = false; @@ -2880,8 +2816,8 @@ void ProgramBinary::reset() SafeDeleteContainer(mUniformBlocks); mUniformIndex.clear(); mOutputVariables.clear(); - SafeDelete(mVertexUniformStorage); - SafeDelete(mFragmentUniformStorage); + + mProgram->reset(); mValidated = false; } |