diff --git a/include/renderer_gl/gl_driver.hpp b/include/renderer_gl/gl_driver.hpp index 4a0b3727..dfb78ffe 100644 --- a/include/renderer_gl/gl_driver.hpp +++ b/include/renderer_gl/gl_driver.hpp @@ -1,4 +1,5 @@ #pragma once +#include "opengl.hpp" // Information about our OpenGL/OpenGL ES driver that we should keep track of // Stuff like whether specific extensions are supported, and potentially things like OpenGL context information @@ -8,6 +9,9 @@ namespace OpenGL { bool supportsExtFbFetch = false; bool supportsArmFbFetch = false; + // Minimum alignment for UBO offsets. Fetched by the OpenGL renderer using glGetIntegerV. + GLuint uboAlignment = 16; + bool supportFbFetch() const { return supportsExtFbFetch || supportsArmFbFetch; } }; } // namespace OpenGL \ No newline at end of file diff --git a/src/core/renderer_gl/renderer_gl.cpp b/src/core/renderer_gl/renderer_gl.cpp index 35a99bc4..e8739535 100644 --- a/src/core/renderer_gl/renderer_gl.cpp +++ b/src/core/renderer_gl/renderer_gl.cpp @@ -2,6 +2,7 @@ #include +#include #include #include @@ -179,6 +180,10 @@ void RendererGL::initGraphicsContextInternal() { driverInfo.supportsExtFbFetch = (GLAD_GL_EXT_shader_framebuffer_fetch != 0); driverInfo.supportsArmFbFetch = (GLAD_GL_ARM_shader_framebuffer_fetch != 0); + // UBOs have an alignment requirement we have to respect + glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, reinterpret_cast(&driverInfo.uboAlignment)); + driverInfo.uboAlignment = std::max(driverInfo.uboAlignment, 16); + // Initialize the default vertex shader used with shadergen std::string defaultShadergenVSSource = fragShaderGen.getDefaultVertexShader(); defaultShadergenVs.create({defaultShadergenVSSource.c_str(), defaultShadergenVSSource.size()}, OpenGL::Vertex); @@ -1020,7 +1025,7 @@ OpenGL::Program& RendererGL::getSpecializedShader() { // Upload fragment uniforms to UBO shadergenFragmentUBO->Bind(); - auto mapRes = shadergenFragmentUBO->Map(4, sizeof(PICA::FragmentUniforms)); + auto mapRes = shadergenFragmentUBO->Map(driverInfo.uboAlignment, sizeof(PICA::FragmentUniforms)); std::memcpy(mapRes.pointer, &uniforms, sizeof(PICA::FragmentUniforms)); shadergenFragmentUBO->Unmap(sizeof(PICA::FragmentUniforms)); @@ -1074,9 +1079,10 @@ bool RendererGL::prepareForDraw(ShaderUnit& shaderUnit, PICA::DrawAcceleration* generatedVertexShader = &(*shader); hwShaderUniformUBO->Bind(); + // Upload shader uniforms to our UBO if (shaderUnit.vs.uniformsDirty) { shaderUnit.vs.uniformsDirty = false; - auto mapRes = hwShaderUniformUBO->Map(4, PICAShader::totalUniformSize()); + auto mapRes = hwShaderUniformUBO->Map(driverInfo.uboAlignment, PICAShader::totalUniformSize()); std::memcpy(mapRes.pointer, shaderUnit.vs.getUniformPointer(), PICAShader::totalUniformSize()); hwShaderUniformUBO->Unmap(PICAShader::totalUniformSize()); }