GL: Respect minimum UBO alignment requirement

This commit is contained in:
wheremyfoodat 2025-07-25 00:16:01 +03:00
commit c92c4c0136
2 changed files with 12 additions and 2 deletions

View file

@ -1,4 +1,5 @@
#pragma once #pragma once
#include "opengl.hpp"
// Information about our OpenGL/OpenGL ES driver that we should keep track of // 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 // Stuff like whether specific extensions are supported, and potentially things like OpenGL context information
@ -8,6 +9,9 @@ namespace OpenGL {
bool supportsExtFbFetch = false; bool supportsExtFbFetch = false;
bool supportsArmFbFetch = 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; } bool supportFbFetch() const { return supportsExtFbFetch || supportsArmFbFetch; }
}; };
} // namespace OpenGL } // namespace OpenGL

View file

@ -2,6 +2,7 @@
#include <stb_image_write.h> #include <stb_image_write.h>
#include <algorithm>
#include <bit> #include <bit>
#include <cmrc/cmrc.hpp> #include <cmrc/cmrc.hpp>
@ -179,6 +180,10 @@ void RendererGL::initGraphicsContextInternal() {
driverInfo.supportsExtFbFetch = (GLAD_GL_EXT_shader_framebuffer_fetch != 0); driverInfo.supportsExtFbFetch = (GLAD_GL_EXT_shader_framebuffer_fetch != 0);
driverInfo.supportsArmFbFetch = (GLAD_GL_ARM_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<GLint*>(&driverInfo.uboAlignment));
driverInfo.uboAlignment = std::max<GLuint>(driverInfo.uboAlignment, 16);
// Initialize the default vertex shader used with shadergen // Initialize the default vertex shader used with shadergen
std::string defaultShadergenVSSource = fragShaderGen.getDefaultVertexShader(); std::string defaultShadergenVSSource = fragShaderGen.getDefaultVertexShader();
defaultShadergenVs.create({defaultShadergenVSSource.c_str(), defaultShadergenVSSource.size()}, OpenGL::Vertex); defaultShadergenVs.create({defaultShadergenVSSource.c_str(), defaultShadergenVSSource.size()}, OpenGL::Vertex);
@ -1020,7 +1025,7 @@ OpenGL::Program& RendererGL::getSpecializedShader() {
// Upload fragment uniforms to UBO // Upload fragment uniforms to UBO
shadergenFragmentUBO->Bind(); 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)); std::memcpy(mapRes.pointer, &uniforms, sizeof(PICA::FragmentUniforms));
shadergenFragmentUBO->Unmap(sizeof(PICA::FragmentUniforms)); shadergenFragmentUBO->Unmap(sizeof(PICA::FragmentUniforms));
@ -1074,9 +1079,10 @@ bool RendererGL::prepareForDraw(ShaderUnit& shaderUnit, PICA::DrawAcceleration*
generatedVertexShader = &(*shader); generatedVertexShader = &(*shader);
hwShaderUniformUBO->Bind(); hwShaderUniformUBO->Bind();
// Upload shader uniforms to our UBO
if (shaderUnit.vs.uniformsDirty) { if (shaderUnit.vs.uniformsDirty) {
shaderUnit.vs.uniformsDirty = false; 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()); std::memcpy(mapRes.pointer, shaderUnit.vs.getUniformPointer(), PICAShader::totalUniformSize());
hwShaderUniformUBO->Unmap(PICAShader::totalUniformSize()); hwShaderUniformUBO->Unmap(PICAShader::totalUniformSize());
} }