This is another blog post on OpenGL and Vulkan Interoperability. It’s not really a description of a new use case as the Piglit test I am going to describe is quite similar to the previous example we’ve seen where we reused a Vulkan pixel buffer from OpenGL. This Piglit test was written because there’s an interesting issue (Issue 7) in the spec according to which overwriting Vulkan buffers with glBufferSubData is not possible! This is interesting because we can overwrite textures but not buffers. When we attempt to overwrite a buffer using glBufferSubData the driver must return an Invalid Operation Error and this is what we tested with the vk-pix-buf-update-errors
test that can be found in tests/spec/ext_external_objects
directory like all other tests we’ve seen so far.
So, there isn’t much to describe here. All steps are similar to the ones we’ve seen in Part 5:
we first create a pixel buffer and fill it with a Vulkan image’s data, and then we import it in OpenGL as PIXEL_UNPACK_BUFFER
. The difference is that in the previous example we used it to fill the texture, but here we first try to overwrite it using glBufferSubData and then we fill the texture. At the end we validate first that the correct error had been returned to the user, and then that the data remained unchanged.
The new gl_init
doesn’t fill the texture anymore:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
static bool gl_init() { gl_prog = piglit_build_simple_program(vs, fs); glClearColor(1.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); /* We use the gl_bo buffer as backing storage for the gl_tex texture */ glGenTextures(1, &gl_tex); glBindTexture(GL_TEXTURE_2D, gl_tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glBindTexture(GL_TEXTURE_2D, 0); return glGetError() == GL_NO_ERROR; } |
and the new display performs the checks described above:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
enum piglit_result piglit_display(void) { int i; float colors[6][4] = { {1.0, 0.0, 0.0, 1.0}, {0.0, 1.0, 0.0, 1.0}, {0.0, 0.0, 1.0, 1.0}, {1.0, 1.0, 0.0, 1.0}, {1.0, 0.0, 1.0, 1.0}, {0.0, 1.0, 1.0, 1.0} }; enum piglit_result res = PIGLIT_PASS; unsigned char *data = (unsigned char*) calloc(w * h, 1); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, gl_bo); glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, vk_bo.mobj.mem_sz, data); if (glGetError() != GL_INVALID_OPERATION) { fprintf(stderr, "glBufferSubData should return GL_INVALID_OPERATION error!\n"); res = PIGLIT_FAIL; } glBindTexture(GL_TEXTURE_2D, gl_tex); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, w, h, 0, GL_RGBA, GL_FLOAT, 0); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); glUseProgram(gl_prog); piglit_draw_rect_tex(-1, -1, 2, 2, 0, 0, 1, 1); /* We make sure that the gl_bo buffer data are the initial ones */ for (i = 0; i < 6; i++) { float x = i * (float)piglit_width / 6.0 + (float)piglit_width / 12.0; float y = (float)piglit_height / 2.0; if (!piglit_probe_pixel_rgba(x, y, colors[i])) res = PIGLIT_FAIL; } piglit_present_results(); return res; } |
The rest of the code has been explained in Part 5.
And that was it! I’ve decided to include this test in the blog posts because it is important to remember that with the EXT_external_objects extensions:
External Vulkan textures can be overwritten from OpenGL but external Vulkan buffers can’t!
Links:
- [1] EXT_external_objects specification
- [2] EXT_external_objects_fd specification
- [3] Previous posts on interoperability:
- [OpenGL and Vulkan Interoperability on Linux] Part 1: Introduction
- [OpenGL and Vulkan Interoperability on Linux] Part 2: Using OpenGL to draw on Vulkan textures.
- [OpenGL and Vulkan Interoperability on Linux] Part 3: Using OpenGL to display Vulkan allocated textures.
- [OpenGL and Vulkan Interoperability on Linux] Part 4: Using OpenGL to overwrite Vulkan allocated textures.
- [OpenGL and Vulkan Interoperability on Linux] Part 5: A Vulkan pixel buffer is reused by OpenGL
- [OpenGL and Vulkan Interoperability on Linux]: The XDC 2020 presentation
What’s coming next:
Next posts will be about reusing vertex buffers and attempting to overwrite them. Stay tuned!
