Weird opengl result because of wrong deallocation of resources


image

최근에 modern opengl 기반 gltf viewer를 구현하고 있는데, multi gltf input을 지원하는 과정에서 문제가 발생했다.

gltf scene file로부터 parsing한 data를 GLTFScene class로 abstraction 했기 때문에, gltf scene file을 하나를 넣으나 두개 이상을 넣으나 이상이 없어야하는 것이 당연했다.

하지만, 기존의 initialization method에서 scene, environment map, scene data uniform buffer를 순서대로 초기화하는 코드에서, initialization method에서는 scene data uniform buffer만 초기화하고 gltf scene과 environment map은 별도의 method로 마음껏 추가할 수 있도록 코드를 변경했는데 렌더링 결과 검은화면만 나타나고 아래의 debug message가 콘솔창에 도배되었다.

[Type] : Error[Source] : API[ID] : 1282[Serverity] : High
[Message] : GL_INVALID_OPERATION error generated. Buffer name does not refer to an buffer object generated by OpenGL.

debug message가 발생한 코드를 stack-trace를 통해 찾아가보니 아래의 scene data uniform buffer를 binding 하는 코드에서 발생했다.

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.0f, 0.0f, 0.8f, 1.0f);

//! Bind uniform buffer & shader storage buffers
_cameras[0]->BindCamera(0);
glBindBufferBase(GL_UNIFORM_BUFFER, 1, _uniformBuffer);

//! Bind skybox shader and render attached skydome
auto& skyboxShader = _shaders["skybox"];
skyboxShader->BindShaderProgram();
_skyDome.Render(skyboxShader, GL_BLEND_SRC_ALPHA);

uniform buffer resource의 생성과정에서 뭔가 잘못되었나 코드를 보았지만 특별한 이상이 없었다.

//! Initialize scene data uniform buffer
glGenBuffers(1, &_uniformBuffer);
glBindBuffer(GL_UNIFORM_BUFFER, _uniformBuffer);
glBufferData(GL_UNIFORM_BUFFER, sizeof(SceneData), &_sceneData, GL_STATIC_COPY);
glBindBuffer(GL_UNIFORM_BUFFER, 0);

원인을 알 수 없어서 Renderdoc 툴을 통해 frame debugging을 해보려고 했더니, Renderdoc에서는 화면이 정상적으로 출력되었다. 이제 남은 방법은, 해당 uniform buffer를 이용하는 다른 코드들을 하나하나 뜯어봐야 했는데, 가장 가능성있는 Skydome class의 코드를 먼저 살펴봤다. Skydome class는 environment map image에서 BRDR lookup table, irradiance map, prefiltered diffuse texture들을 precalculation하여 제공하는 역할을 하는데 코드를 하나하나 보니 opengl resource 할당/해제에서 실수가 있었다.

//! Create framebuffer for capturing
GLuint fbo, rbo;
glCreateFramebuffers(1, &fbo);
//! ...
glDeleteRenderbuffers(1, &rbo);
glDeleteBuffers(1, &fbo);

코드를 살펴보면 할당하지도 않은 render buffer object를 delete하고 있고, glCreateFramebuffers로 생성한 frame buffer object를 glDeleteFramebuffers가 아닌 glDeleteBuffers로 지우고 있다. 이런 말도 안되는 코드에서 위와 같은 버그가 발생했던 것이다.

그런데 왜 glDebugMessenger에서 위와 같은 잘못된 자원 해제를 알려주지 않았을까?




© 2020.11. by snowapril

Powered by snowapril