Skip to content

Commit

Permalink
GL3+: validate VertexDeclaration against shader inputs
Browse files Browse the repository at this point in the history
like D3D11 does. Catches bugs like missing tangents
  • Loading branch information
paroj committed Oct 30, 2022
1 parent fd13ef3 commit 1b49396
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 0 deletions.
2 changes: 2 additions & 0 deletions RenderSystems/GL3Plus/src/GLSL/include/OgreGLSLShader.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ namespace Ogre {
void extractUniforms(int block = -1) const;
void extractBufferBlocks(GLenum type) const;

void extractAttributes();

mutable HardwareBufferPtr mDefaultBuffer;
bool mHasSamplerBinding;
};
Expand Down
16 changes: 16 additions & 0 deletions RenderSystems/GL3Plus/src/GLSL/src/OgreGLSLShader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,20 @@ namespace Ogre {
mLinked = 0;
}

void GLSLShader::extractAttributes()
{
GLint numAttributes = 0;
OGRE_CHECK_GL_ERROR(glGetProgramInterfaceiv(mGLProgramHandle, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, &numAttributes));
GLenum prop = GL_LOCATION;
for (int attr = 0; attr < numAttributes; ++attr)
{
GLint val;
OGRE_CHECK_GL_ERROR(
glGetProgramResourceiv(mGLProgramHandle, GL_PROGRAM_INPUT, attr, 1, &prop, 1, NULL, &val));
mActiveInputs.push_back(val);
}
}

void GLSLShader::extractUniforms(int block) const
{
GLint numUniforms = 0;
Expand Down Expand Up @@ -642,6 +656,8 @@ namespace Ogre {
extractUniforms();
extractBufferBlocks(GL_UNIFORM_BLOCK);
extractBufferBlocks(GL_SHADER_STORAGE_BLOCK);
if(mType == GPT_VERTEX_PROGRAM)
extractAttributes();
return;
}

Expand Down
2 changes: 2 additions & 0 deletions RenderSystems/GL3Plus/src/OgreGL3PlusRenderSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1098,6 +1098,8 @@ namespace Ogre {
if (updateVAO)
vao->bindToGpu(this, op.vertexData->vertexBufferBinding, 0);

mCurrentShader[GPT_VERTEX_PROGRAM]->validateDeclaration(op.vertexData->vertexDeclaration);

// We treat index buffer binding inside VAO as volatile, always updating and never relying onto it,
// as one shared vertex buffer could be rendered with several index buffers, from submeshes and/or LODs
if (op.useIndexes)
Expand Down
4 changes: 4 additions & 0 deletions RenderSystems/GLSupport/include/GLSL/OgreGLSLShaderCommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ namespace Ogre {

/// GLSL does not provide access to the low level code of the shader, so use this shader for binding as well
GpuProgram* _getBindingDelegate(void) override { return this; }

void validateDeclaration(const VertexDeclaration* decl);
protected:
/// GLSL does not provide access to the low level implementation of the shader, so this method s a no-op
void createLowLevelImpl() override {}
Expand Down Expand Up @@ -144,6 +146,8 @@ namespace Ogre {
/// Pointer to the uniform cache for this shader
GLUniformCache mUniformCache;

std::vector<int> mActiveInputs; // only for vertex shaders

/// Keep track of the number of shaders created.
static uint mShaderCount;
};
Expand Down
23 changes: 23 additions & 0 deletions RenderSystems/GLSupport/src/GLSL/OgreGLSLShaderCommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ THE SOFTWARE.

#include "OgreGLSLShaderCommon.h"
#include "OgreGLSLPreprocessor.h"
#include "OgreGLSLProgramCommon.h"

namespace Ogre {
//-----------------------------------------------------------------------
Expand All @@ -44,6 +45,28 @@ namespace Ogre {
GLSLShaderCommon::CmdAttach GLSLShaderCommon::msCmdAttach;
GLSLShaderCommon::CmdColumnMajorMatrices GLSLShaderCommon::msCmdColumnMajorMatrices;

void GLSLShaderCommon::validateDeclaration(const VertexDeclaration* decl)
{
for(auto sloc : mActiveInputs)
{
bool found = false;
for (const VertexElement & elem : decl->getElements())
{
auto eidx = GLSLProgramCommon::getFixedAttributeIndex(elem.getSemantic(), elem.getIndex());
if(eidx == sloc)
{
found = true;
break;
}
}
if (!found)
{
LogManager::getSingleton().logError("Shader " + mName + " requires a VertexElement at location " +
std::to_string(sloc));
}
}
}

String GLSLShaderCommon::getResourceLogName() const
{
if(mLoadFromFile)
Expand Down

0 comments on commit 1b49396

Please sign in to comment.