baldurk/renderdoc

VAO DSA format and divisor state after glVertexArrayVertexBuffer

Closed this issue · 4 comments

Description

  • I have DSA VAO usage code that renders fine outside RenderDoc, but RenderDoc has trouble displaying it correctly.
  • I believe that a call to glVertexArrayVertexBuffer incorrectly clears the state set by glVertexArrayAttribFormat and glVertexArrayBindingDivisor.
  • Neither the driver nor RenderDoc report incorrect API/buffer usage.

This is captured in bug_1.rdc (frame 1), which shows that format and divisor state is reset compared to bug_0.rdc (frame 0). Captures: vaodsabug.zip

I can workaround this by setting the state again after calling glVertexArrayVertexBuffer. This is shown in workaround_[0,1].rdc. From examples I've seen this should be unnecessary though.

Steps to reproduce

jbarthelmes@cb3a985

Command lists from the captures: vaodsabug.zip

Code for reference
// init
gl.createVertexArrays(1, &vao);
gl.enableVertexArrayAttrib(vao, 0);
gl.vertexArrayAttribFormat(vao, 0, 2, gl.FLOAT, gl.FALSE, 0);
gl.vertexArrayAttribBinding(vao, 0, 0);
gl.vertexArrayBindingDivisor(vao, 0, 1);
gl.enableVertexArrayAttrib(vao, 1);
gl.vertexArrayAttribFormat(vao, 1, 4, gl.FLOAT, gl.FALSE, 0);
gl.vertexArrayAttribBinding(vao, 1, 1);
gl.vertexArrayBindingDivisor(vao, 1, 1);
gl.enableVertexArrayAttrib(vao, 2);
gl.vertexArrayAttribFormat(vao, 2, 4, gl.UNSIGNED_BYTE, gl.TRUE, 0);
gl.vertexArrayAttribBinding(vao, 2, 2);
gl.vertexArrayBindingDivisor(vao, 2, 1);

gl.createBuffers(3, &vbo);
gl.vertexArrayVertexBuffer(vao, 0, vbo[0], 0, @sizeOf(Position));
gl.vertexArrayVertexBuffer(vao, 1, vbo[1], 0, @sizeOf([4]f32));
gl.vertexArrayVertexBuffer(vao, 2, vbo[2], 0, @sizeOf(Color));

// draw
gl.namedBufferData(vbo[0], count * @sizeOf(Position), positions.ptr, gl.STATIC_DRAW);
gl.namedBufferData(vbo[1], count * @sizeOf([4]f32), src_rect_buffer.ptr, gl.STATIC_DRAW);
gl.namedBufferData(vbo[2], count * @sizeOf(Color), tints.ptr, gl.STATIC_DRAW);
gl.bindVertexArray(vao);
gl.vertexArrayVertexBuffer(vao, 0, vbo[0], 0, @sizeOf(Position));
gl.vertexArrayVertexBuffer(vao, 1, vbo[1], 0, @sizeOf([4]f32));
gl.vertexArrayVertexBuffer(vao, 2, vbo[2], 0, @sizeOf(Color));
{
  // RenderDoc workaround
  gl.vertexArrayAttribFormat(vao, 0, 2, gl.FLOAT, gl.FALSE, 0);
  gl.vertexArrayAttribFormat(vao, 1, 4, gl.FLOAT, gl.FALSE, 0);
  gl.vertexArrayAttribFormat(vao, 2, 4, gl.UNSIGNED_BYTE, gl.TRUE, 0);
  gl.vertexArrayBindingDivisor(vao, 0, 1);
  gl.vertexArrayBindingDivisor(vao, 1, 1);
  gl.vertexArrayBindingDivisor(vao, 2, 1);
}
gl.drawArraysInstanced(gl.TRIANGLE_STRIP, 0, 4, count);

Environment

  • RenderDoc version: 1.3.0
  • Operating System: Windows 10
  • Graphics API: OpenGL 4.5 core
  • GPU: AMD Radeon RX 570
  • Driver version: 31.0.12027.9001

This looks to be a problem at capture time as the format and divisor data is not correct in the capture.
I have recreated the scenario in a test project, however that test project is working for me.
There must be something else or something different in your test project that is required to recreate the problem.
If possible can you supply a reproduction project (an executable or source code would be perfect)

I have it reproduced in your demos framework:
jbarthelmes@cb3a985 [edit: fixed a translation error]

The driver accepts this and renders frames 1+, but renderdoc replay doesn't without the workaround.

Thank you for the reproduction case using the RenderDoc test framework.
The test is working locally : tested on AMD, nVidia on Windows and nVidia on Linux.
Perhaps it is an AMD driver bug, your AMD driver looks to be about one year old.
I have included example local captures for comparison
GL_VAO_DSA_NVIDIA_FRAME_0.zip
GL_VAO_DSA_NVIDIA_FRAME_1.zip

As you said it seems to occur at capture time and with an old driver.