summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric R. Smith <eric.smith@collabora.com>2024-04-06 18:29:20 -0300
committerEric R. Smith <eric.smith@collabora.com>2024-04-10 08:21:00 -0300
commitdd6f7eaf82e8dd442da28b346c236141cbcce0b1 (patch)
tree605b3e3ddfab7bfa2859d34723e74a37ff2dcf3a
parent025e462ae2dffde2890c30121a447f2d32b93e49 (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.py1
-rw-r--r--tests/texturing/CMakeLists.gl.txt1
-rw-r--r--tests/texturing/texsubimage-sync.c102
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();
+}