I have the following opengl code to bind a created buffer and fill it with some data.
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <array>
#include <iostream>
template <size_t max_lights = 100>
class SceneLights
{
private:
struct Light
{
glm::vec4 position;
glm::vec4 color;
};
std::array<Light, max_lights> lights;
public:
SceneLights()
{
lights.fill(Light(glm::vec4(0.0), glm::vec4(0.0)));
}
constexpr size_t size() const noexcept
{
return lights.size();
}
constexpr size_t size_bytes() const noexcept
{
return size() * 2 * sizeof(glm::mat4);
}
constexpr Light const* data() const noexcept
{
return lights.data();
}
};
int main()
{
GLFWwindow* window;
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);
window = glfwCreateWindow(800, 600, "The Window", NULL, NULL);
if (window == nullptr)
{
glfwTerminate();
throw "Failed to create GLFW window";
}
glfwMakeContextCurrent(window);
glfwSwapInterval(0);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
throw "Failed to initialize GLAD";
}
std::cout << "OpenGL Info:" << std::endl;
std::cout << " Vendor: " << glGetString(GL_VENDOR) << std::endl;
std::cout << " Renderer: " << glGetString(GL_RENDERER) << std::endl;
std::cout << " Version: " << glGetString(GL_VERSION) << std::endl;
SceneLights sl = SceneLights();
unsigned int ubo_id;
glGenBuffers(1, &ubo_id);
glBindBuffer(GL_UNIFORM_BUFFER, ubo_id);
glBufferData(GL_UNIFORM_BUFFER, sl.size_bytes(), NULL, GL_DYNAMIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
glBindBufferRange(GL_UNIFORM_BUFFER, 0, ubo_id, 0, sl.size_bytes());
glBindBuffer(GL_UNIFORM_BUFFER, ubo_id);
int buf;
int size;
glGetIntegerv(GL_UNIFORM_BUFFER_BINDING, &buf);
glGetBufferParameteriv(GL_UNIFORM_BUFFER, GL_BUFFER_SIZE, &size);
std::cout << sl.size_bytes() << std::endl;
std::cout << sl.data() << std::endl;
std::cout << buf << std::endl;
std::cout << size << std::endl;
glBufferSubData(GL_UNIFORM_BUFFER, 0, sl.size_bytes(), sl.data());
return 0;
}
the output is:
OpenGL Info:
Vendor: NVIDIA Corporation
Renderer: NVIDIA GeForce GTX 950/PCIe/SSE2
Version: 4.5.0 NVIDIA 466.27
12800
00000080860FE830
1
12800
And I am consistently getting "Exception thrown at 0x0000000000000000 in main.exe: 0xC0000005: Access violation executing location 0x0000000000000000." when calling glBufferSubData(GL_UNIFORM_BUFFER, 0, sl.size_bytes(), sl.data());
I don't quite understand why? The buffer seems to be bound, my input data isn't a nullptr, and the sizes match up? Any help or debugging suggestions appreciated.
Got repro on my machine when compiling for 64-bit. Didn't crash on 32-bit but I suspect I just got lucky with page sizes/layouts.
Noticed this:
constexpr size_t size_bytes() const noexcept
{
return size() * 2 * sizeof(glm::mat4);
^^^^ not a vec4?
}
Changing the mat4
to match the vec4
s in the Light
struct fixed the crash on my end.
sizeof(lights)
or size() * sizeof(Light)
also work, with a preference for the latter if there's any chance the type of lights
is expected to change to a dynamic container sometime in the future.
In general, don't tell OpenGL that memory buffers you ask it to read from are longer than they actually are. Otherwise OpenGL will happily read off the end buffer, either grabbing garbage or a segfault.
User contributions licensed under CC BY-SA 3.0