Commit b22b1502 by Shahbaz Youssefi Committed by Commit Bot

Vulkan: Fix transform feedback spanning multiple render passes

When the render pass breaks while transform feedback is active, the subsequent render passes didn't restart transform feedback because of a missing dirty bit. Bug: angleproject:5426 Change-Id: Icee79cbdabbceab96973cea124240ac7ced82d55 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2572878 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCharlie Lao <cclao@google.com>
parent b35a468a
...@@ -1121,7 +1121,7 @@ angle::Result ContextVk::handleDirtyGraphicsPipeline(const gl::Context *context, ...@@ -1121,7 +1121,7 @@ angle::Result ContextVk::handleDirtyGraphicsPipeline(const gl::Context *context,
mGraphicsPipelineTransition.reset(); mGraphicsPipelineTransition.reset();
} }
resumeTransformFeedbackIfStarted(); pauseTransformFeedbackIfStarted({});
commandBuffer->bindGraphicsPipeline(mCurrentGraphicsPipeline->getPipeline()); commandBuffer->bindGraphicsPipeline(mCurrentGraphicsPipeline->getPipeline());
// Update the queue serial for the pipeline object. // Update the queue serial for the pipeline object.
...@@ -3657,12 +3657,13 @@ void ContextVk::writeAtomicCounterBufferDriverUniformOffsets(uint32_t *offsetsOu ...@@ -3657,12 +3657,13 @@ void ContextVk::writeAtomicCounterBufferDriverUniformOffsets(uint32_t *offsetsOu
} }
} }
ANGLE_INLINE void ContextVk::resumeTransformFeedbackIfStarted() ANGLE_INLINE void ContextVk::pauseTransformFeedbackIfStarted(DirtyBits onResumeOps)
{ {
if (mRenderPassCommands->isTransformFeedbackStarted()) if (mRenderPassCommands->isTransformFeedbackStarted())
{ {
ASSERT(getFeatures().supportsTransformFeedbackExtension.enabled); ASSERT(getFeatures().supportsTransformFeedbackExtension.enabled);
mGraphicsDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_RESUME); mGraphicsDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_RESUME);
mGraphicsDirtyBits |= onResumeOps;
mRenderPassCommands->pauseTransformFeedback(); mRenderPassCommands->pauseTransformFeedback();
} }
} }
...@@ -4596,7 +4597,9 @@ angle::Result ContextVk::flushCommandsAndEndRenderPass() ...@@ -4596,7 +4597,9 @@ angle::Result ContextVk::flushCommandsAndEndRenderPass()
addOverlayUsedBuffersCount(mRenderPassCommands); addOverlayUsedBuffersCount(mRenderPassCommands);
resumeTransformFeedbackIfStarted(); DirtyBits rebindTransformFeedbackOnResume;
rebindTransformFeedbackOnResume.set(DIRTY_BIT_TRANSFORM_FEEDBACK_STATE);
pauseTransformFeedbackIfStarted(rebindTransformFeedbackOnResume);
mRenderPassCommands->endRenderPass(this); mRenderPassCommands->endRenderPass(this);
......
...@@ -845,7 +845,7 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText ...@@ -845,7 +845,7 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText
void populateTransformFeedbackBufferSet( void populateTransformFeedbackBufferSet(
size_t bufferCount, size_t bufferCount,
const gl::TransformFeedbackBuffersArray<vk::BufferHelper *> &buffers); const gl::TransformFeedbackBuffersArray<vk::BufferHelper *> &buffers);
void resumeTransformFeedbackIfStarted(); void pauseTransformFeedbackIfStarted(DirtyBits onResumeOps);
// DescriptorSet writes // DescriptorSet writes
template <typename T, const T *VkWriteDescriptorSet::*pInfo> template <typename T, const T *VkWriteDescriptorSet::*pInfo>
......
...@@ -280,6 +280,103 @@ TEST_P(TransformFeedbackTest, RecordAndDraw) ...@@ -280,6 +280,103 @@ TEST_P(TransformFeedbackTest, RecordAndDraw)
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
} }
// Test that transform feedback can cover multiple render passes.
TEST_P(TransformFeedbackTest, SpanMultipleRenderPasses)
{
// TODO(anglebug.com/4533) This fails after the upgrade to the 26.20.100.7870 driver.
ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsVulkan());
// Fails on Mac GL drivers. http://anglebug.com/4992
ANGLE_SKIP_TEST_IF(IsOpenGL() && IsOSX());
// anglebug.com/5428
ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsVulkan());
// anglebug.com/5429
ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// Set the program's transform feedback varyings (just gl_Position)
std::vector<std::string> tfVaryings;
tfVaryings.push_back("gl_Position");
compileDefaultProgram(tfVaryings, GL_INTERLEAVED_ATTRIBS);
glUseProgram(mProgram);
GLint positionLocation = glGetAttribLocation(mProgram, essl1_shaders::PositionAttrib());
const GLfloat vertices[] = {
-0.5f, 0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f,
-0.5f, 0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f,
};
glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, vertices);
glEnableVertexAttribArray(positionLocation);
// Bind the buffer for transform feedback output and start transform feedback
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, mTransformFeedbackBuffer);
glBeginTransformFeedback(GL_POINTS);
// Create a query to check how many primitives were written
GLuint primitivesWrittenQuery = 0;
glGenQueries(1, &primitivesWrittenQuery);
glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, primitivesWrittenQuery);
// Draw the first set of three points
glDrawArrays(GL_POINTS, 0, 3);
// Break the render pass
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
// Draw the second set of three points
glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, vertices + 9);
glDrawArrays(GL_POINTS, 0, 3);
glDisableVertexAttribArray(positionLocation);
glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
// End the query and transform feedback
glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
glEndTransformFeedback();
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0);
// Verify the number of primitives written
GLuint primitivesWritten = 0;
glGetQueryObjectuiv(primitivesWrittenQuery, GL_QUERY_RESULT_EXT, &primitivesWritten);
EXPECT_GL_NO_ERROR();
EXPECT_EQ(6u, primitivesWritten);
// Verify the captured buffer.
glBindBuffer(GL_ARRAY_BUFFER, mTransformFeedbackBuffer);
glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(positionLocation);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, 6);
const int w = getWindowWidth();
const int h = getWindowHeight();
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
EXPECT_PIXEL_COLOR_EQ(w - 1, 0, GLColor::black);
EXPECT_PIXEL_COLOR_EQ(0, h - 1, GLColor::black);
EXPECT_PIXEL_COLOR_EQ(w - 1, h - 1, GLColor::black);
EXPECT_PIXEL_COLOR_EQ(w / 4 + 1, h / 4 + 1, GLColor::red);
EXPECT_PIXEL_COLOR_EQ(3 * w / 4 - 1, h / 4 + 1, GLColor::red);
EXPECT_PIXEL_COLOR_EQ(w / 4 + 1, 3 * h / 4 - 1, GLColor::red);
EXPECT_PIXEL_COLOR_EQ(3 * w / 4 - 1, 3 * h / 4 - 1, GLColor::red);
EXPECT_PIXEL_COLOR_EQ(w / 2, h / 2, GLColor::red);
EXPECT_GL_NO_ERROR();
}
// Test that XFB does not allow writing more vertices than fit in the bound buffers. // Test that XFB does not allow writing more vertices than fit in the bound buffers.
// TODO(jmadill): Enable this test after fixing the last case where the buffer size changes after // TODO(jmadill): Enable this test after fixing the last case where the buffer size changes after
// calling glBeginTransformFeedback. // calling glBeginTransformFeedback.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment