diff options
author | Eric R. Smith <eric.smith@collabora.com> | 2024-04-06 18:29:20 -0300 |
---|---|---|
committer | Eric R. Smith <eric.smith@collabora.com> | 2024-04-10 08:21:00 -0300 |
commit | dd6f7eaf82e8dd442da28b346c236141cbcce0b1 (patch) | |
tree | 605b3e3ddfab7bfa2859d34723e74a37ff2dcf3a | |
parent | 025e462ae2dffde2890c30121a447f2d32b93e49 (diff) |
texturing: add a test for GPU/CPU sync when creating textures
On Panfrost, at least, a race condition could occur if a texture
is cleared and then initialized with texSubImage; the clear on
the GPU could happen after the memcpy in texSubImage. This test
checks for that and triggers the original Panfrost bug.
Signed-off-by: Eric R. Smith <eric.smith@collabora.com>
Reviewed-by: Erik Faye-Lund <erik.faye-lund@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/piglit/-/merge_requests/901>
-rw-r--r-- | tests/opengl.py | 1 | ||||
-rw-r--r-- | tests/texturing/CMakeLists.gl.txt | 1 | ||||
-rw-r--r-- | tests/texturing/texsubimage-sync.c | 102 |
3 files changed, 104 insertions, 0 deletions
diff --git a/tests/opengl.py b/tests/opengl.py index 2ce58bb90..b9bd17a9d 100644 --- a/tests/opengl.py +++ b/tests/opengl.py @@ -947,6 +947,7 @@ with profile.test_list.group_manager( g(['generatemipmap-base-change', 'format']) g(['generatemipmap-cubemap']) g(['viewport-clamp']) + g(['texsubimage-sync']) with profile.test_list.group_manager( PiglitGLTest, diff --git a/tests/texturing/CMakeLists.gl.txt b/tests/texturing/CMakeLists.gl.txt index 02b572c79..c56eeaf46 100644 --- a/tests/texturing/CMakeLists.gl.txt +++ b/tests/texturing/CMakeLists.gl.txt @@ -77,6 +77,7 @@ piglit_add_executable (texdepth texdepth.c) piglit_add_executable (teximage-errors teximage-errors.c) piglit_add_executable (texrect-many texrect-many.c) piglit_add_executable (texredefine texredefine.c) +piglit_add_executable (texsubimage-sync texsubimage-sync.c) piglit_add_executable (texture-packed-formats texture-packed-formats.c) piglit_add_executable (texwrap texwrap.c) piglit_add_executable (depth-tex-modes depth-tex-modes.c depth-tex-modes-common.c) diff --git a/tests/texturing/texsubimage-sync.c b/tests/texturing/texsubimage-sync.c new file mode 100644 index 000000000..3bff88503 --- /dev/null +++ b/tests/texturing/texsubimage-sync.c @@ -0,0 +1,102 @@ +/* + * Copyright © 2024 Collabora Ltd + * SPDX-License-Identifier: MIT + * + * Test for clear before render in texture preparation + * If the texture is small and we use memcpy in + * TexSubImage2D then that can complete before the clear, + * which means that if the driver doesn't synchronize the + * GPU and CPU properly the clear can overwrite the texture data. + */ + +#include "piglit-util-gl.h" + +PIGLIT_GL_TEST_CONFIG_BEGIN + + config.supports_gl_compat_version = 30; + + config.window_visual = PIGLIT_GL_VISUAL_DOUBLE | PIGLIT_GL_VISUAL_RGBA; + config.khr_no_error_support = PIGLIT_NO_ERRORS; + +PIGLIT_GL_TEST_CONFIG_END + +static GLuint +create_texture(GLsizei w, GLsizei h) +{ + GLuint tex, fbo; + GLint i; + static GLfloat red[] = { 1.0, 0, 0, 1.0 }; + + /* prepare a blob filled with green and max alpha */ + GLubyte *colorblob = calloc(4, w * h); + for (i = 1; i < w*h*4; i += 2) { + colorblob[i] = 0xff; + } + + /* get a framebuffer for the texture */ + glGenFramebuffers(1, &fbo); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + + /* create texture */ + glGenTextures(1, &tex); + glBindTexture(GL_TEXTURE_2D, tex); + glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, w, h); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + /* use ClearBuffer to fill with red (likely on the GPU) */ + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0); + glClearBufferfv(GL_COLOR, 0, red); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glDeleteFramebuffers(1, &fbo); + + /* now fill with green via TexSubImage2D (possibly on the CPU) */ + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, colorblob); + glBindTexture(GL_TEXTURE_2D, 0); + + free(colorblob); + + return tex; +} + +enum piglit_result +piglit_display(void) +{ + static const GLfloat green[3] = {0.0, 1.0, 0.0}; + GLboolean pass = GL_TRUE; + GLuint tex; + + /* clear frame buffer */ + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + + /* create a small texture */ + tex = create_texture(4, 4); + + /* draw with it */ + glBindTexture(GL_TEXTURE_2D, tex); + glEnable(GL_TEXTURE_2D); + piglit_draw_rect_tex(0, 0, piglit_width, piglit_height, 0, 0, 1, 1); + + /* check for expected values */ + pass = pass && piglit_probe_rect_rgb(0, 0, piglit_width, piglit_height, green); + + /* show on screen */ + piglit_present_results(); + return pass ? PIGLIT_PASS : PIGLIT_FAIL; +} + +void +piglit_init(int argc, char **argv) +{ + glDisable(GL_DITHER); + + glMatrixMode( GL_PROJECTION ); + glPushMatrix(); + glLoadIdentity(); + glOrtho( 0, piglit_width, 0, piglit_height, -1, 1 ); + + glMatrixMode( GL_MODELVIEW ); + glPushMatrix(); + glLoadIdentity(); +} |