From a517d4d95fce3019bc502ba4befb82967b013ebf Mon Sep 17 00:00:00 2001 From: Shahbaz Youssefi Date: Mon, 1 Nov 2021 16:21:06 -0400 Subject: [PATCH] Vulkan: Regression test for xfb query before resume Bug: angleproject:6622 Change-Id: If15195437e656dc20aed10d02cf8429ad15ae3d2 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3254432 Reviewed-by: Tim Van Patten Commit-Queue: Shahbaz Youssefi --- .../angle_end2end_tests_expectations.txt | 1 + src/tests/gl_tests/TransformFeedbackTest.cpp | 109 +++++++++++++++++- 2 files changed, 109 insertions(+), 1 deletion(-) diff --git a/src/tests/angle_end2end_tests_expectations.txt b/src/tests/angle_end2end_tests_expectations.txt index d85ab2a15..e85216c0c 100644 --- a/src/tests/angle_end2end_tests_expectations.txt +++ b/src/tests/angle_end2end_tests_expectations.txt @@ -107,6 +107,7 @@ 6570 MAC INTEL OPENGL : WebGLCompatibilityTest.R32FTextures/* = SKIP 6570 MAC INTEL OPENGL : WebGLCompatibilityTest.RGB32FTextures/* = SKIP 6603 MAC OPENGL : ProgramBinaryES3Test.SaveAndLoadDetachedShaders/* = SKIP +6643 MAC AMD OPENGL : TransformFeedbackTest.TransformFeedbackQueryPausedDrawThenResume/* = SKIP // Failures from Transform Feedback Enablement. Passes on BigSur 6407 MAC NVIDIA METAL : TransformFeedbackTest.OptimizedVaryings/ES3_Metal = SKIP diff --git a/src/tests/gl_tests/TransformFeedbackTest.cpp b/src/tests/gl_tests/TransformFeedbackTest.cpp index 1e69ad616..a12b52db4 100644 --- a/src/tests/gl_tests/TransformFeedbackTest.cpp +++ b/src/tests/gl_tests/TransformFeedbackTest.cpp @@ -377,7 +377,6 @@ TEST_P(TransformFeedbackTest, SpanMultipleRenderPasses) // Test that uploading data to buffer that's in use then using it for transform feedback works. TEST_P(TransformFeedbackTest, UseAsUBOThenUpdateThenCapture) { - // http://anglebug.com/5833 ANGLE_SKIP_TEST_IF(IsVulkan() && IsQualcomm()); @@ -3675,6 +3674,114 @@ void main() { EXPECT_GL_ERROR(GL_INVALID_OPERATION); } +// Test that transform feedback query works when render pass is started while transform feedback is +// paused. +TEST_P(TransformFeedbackTest, TransformFeedbackQueryPausedDrawThenResume) +{ + constexpr char kVS[] = R"( +attribute vec4 pos; +varying vec4 v; + +void main() +{ + v = vec4(0.25, 0.5, 0.75, 1.0); + gl_Position = pos; +})"; + + constexpr char kFS[] = R"( +precision mediump float; +varying vec4 v; +void main() +{ + gl_FragColor = v; +})"; + + const std::vector tfVaryings = {"v"}; + ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(program, kVS, kFS, tfVaryings, GL_INTERLEAVED_ATTRIBS); + ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red()); + + const GLfloat vertices[] = { + -0.5f, 0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, + }; + GLint positionLocation = glGetAttribLocation(program, "pos"); + glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, vertices); + glEnableVertexAttribArray(positionLocation); + + glClearColor(0.0f, 0.0f, 1.0f, 1.0f); + glClearDepthf(0.1f); + glClearStencil(0x5A); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + + glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, mTransformFeedbackBuffer); + + // Test the following: + // + // - Start xfb and query + // - Draw + // - Pause query + // - break the render pass + // + // - Draw without xfb, starts a new render pass + // - Without breaking the render pass, resume xfb + // - Draw with xfb + // - End query and xfb + // + // The test ensures that the query is made active on resume. + + glUseProgram(program); + glBeginTransformFeedback(GL_POINTS); + EXPECT_GL_NO_ERROR(); + + GLQuery xfbQuery; + glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, xfbQuery); + EXPECT_GL_NO_ERROR(); + + // Draw with xfb. + glDrawArrays(GL_POINTS, 0, 3); + + glPauseTransformFeedback(); + + // Issue a copy to make sure the render pass is broken. + GLTexture copyTex; + glBindTexture(GL_TEXTURE_2D, copyTex); + glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 1, 1, 0); + + // Start a render pass without xfb. + glUseProgram(drawRed); + glDrawArrays(GL_POINTS, 0, 3); + + // Resume xfb and issue another draw call. + glUseProgram(program); + glResumeTransformFeedback(); + glDrawArrays(GL_POINTS, 0, 3); + + // End the query and verify results. + glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN); + glEndTransformFeedback(); + + GLuint primitivesWritten = 0; + glGetQueryObjectuiv(xfbQuery, GL_QUERY_RESULT_EXT, &primitivesWritten); + EXPECT_GL_NO_ERROR(); + + EXPECT_EQ(primitivesWritten, 6u); + + void *mappedBuffer = glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, + sizeof(float) * 4 * 3 * 2, GL_MAP_READ_BIT); + ASSERT_NE(nullptr, mappedBuffer); + + float *mappedFloats = static_cast(mappedBuffer); + for (unsigned int cnt = 0; cnt < 6; ++cnt) + { + EXPECT_NEAR(mappedFloats[4 * cnt + 0], 0.25f, 0.01f) << cnt; + EXPECT_NEAR(mappedFloats[4 * cnt + 1], 0.5f, 0.01f) << cnt; + EXPECT_NEAR(mappedFloats[4 * cnt + 2], 0.75f, 0.01f) << cnt; + EXPECT_NEAR(mappedFloats[4 * cnt + 3], 1.0f, 0.01f) << cnt; + } + glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); + + EXPECT_GL_NO_ERROR(); +} + GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TransformFeedbackTest); ANGLE_INSTANTIATE_TEST_ES3(TransformFeedbackTest);