Commit a4b582e8 by Shahbaz Youssefi Committed by Commit Bot

Vulkan: Notify ContextVk when UtilsVk binds compute pipelines

This issue was fixed for graphics pipelines (in UtilsVk::clearFramebuffer), but remained for compute pipelines. If UtilsVk issues a dispatch call, it now notifies ContextVk to rebind the pipeline and descriptor sets. Bug: angleproject:5529 Change-Id: Ic52f91bdc70d02c065ec2d5e2a3614c11fd62a9f Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2622236 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarTim Van Patten <timvp@google.com>
parent c0ef8ccf
...@@ -3567,6 +3567,16 @@ angle::Result ContextVk::onPauseTransformFeedback() ...@@ -3567,6 +3567,16 @@ angle::Result ContextVk::onPauseTransformFeedback()
return angle::Result::Continue; return angle::Result::Continue;
} }
void ContextVk::invalidateGraphicsPipeline()
{
mGraphicsDirtyBits.set(DIRTY_BIT_PIPELINE);
}
void ContextVk::invalidateComputePipeline()
{
mComputeDirtyBits.set(DIRTY_BIT_PIPELINE);
}
void ContextVk::invalidateGraphicsDescriptorSet(DescriptorSetIndex usedDescriptorSet) void ContextVk::invalidateGraphicsDescriptorSet(DescriptorSetIndex usedDescriptorSet)
{ {
// UtilsVk currently only uses set 0 // UtilsVk currently only uses set 0
...@@ -4979,12 +4989,6 @@ void ContextVk::setDefaultUniformBlocksMinSizeForTesting(size_t minSize) ...@@ -4979,12 +4989,6 @@ void ContextVk::setDefaultUniformBlocksMinSizeForTesting(size_t minSize)
mDefaultUniformStorage.setMinimumSizeForTesting(minSize); mDefaultUniformStorage.setMinimumSizeForTesting(minSize);
} }
void ContextVk::invalidateGraphicsPipelineAndDescriptorSets()
{
mGraphicsDirtyBits.set(DIRTY_BIT_PIPELINE);
mGraphicsDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
}
angle::Result ContextVk::initializeMultisampleTextureToBlack(const gl::Context *context, angle::Result ContextVk::initializeMultisampleTextureToBlack(const gl::Context *context,
gl::Texture *glTexture) gl::Texture *glTexture)
{ {
......
...@@ -322,9 +322,11 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText ...@@ -322,9 +322,11 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText
angle::Result onPauseTransformFeedback(); angle::Result onPauseTransformFeedback();
void pauseTransformFeedbackIfStartedAndRebindBuffersOnResume(); void pauseTransformFeedbackIfStartedAndRebindBuffersOnResume();
// When UtilsVk issues draw or dispatch calls, it binds descriptor sets that the context is not // When UtilsVk issues draw or dispatch calls, it binds a new pipeline and descriptor sets that
// aware of. This function is called to make sure affected descriptor set bindings are dirtied // the context is not aware of. These functions are called to make sure the pipeline and
// for the next application draw/dispatch call. // affected descriptor set bindings are dirtied for the next application draw/dispatch call.
void invalidateGraphicsPipeline();
void invalidateComputePipeline();
void invalidateGraphicsDescriptorSet(DescriptorSetIndex usedDescriptorSet); void invalidateGraphicsDescriptorSet(DescriptorSetIndex usedDescriptorSet);
void invalidateComputeDescriptorSet(DescriptorSetIndex usedDescriptorSet); void invalidateComputeDescriptorSet(DescriptorSetIndex usedDescriptorSet);
...@@ -571,10 +573,6 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText ...@@ -571,10 +573,6 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText
void onSyncHelperInitialize() { mSyncObjectPendingFlush = true; } void onSyncHelperInitialize() { mSyncObjectPendingFlush = true; }
void onEGLSyncHelperInitialize() { mEGLSyncObjectPendingFlush = true; } void onEGLSyncHelperInitialize() { mEGLSyncObjectPendingFlush = true; }
// When UtilsVk issues a draw call on the currently running render pass, the pipelines and
// descriptor sets it binds need to be undone.
void invalidateGraphicsPipelineAndDescriptorSets();
// Implementation of MultisampleTextureInitializer // Implementation of MultisampleTextureInitializer
angle::Result initializeMultisampleTextureToBlack(const gl::Context *context, angle::Result initializeMultisampleTextureToBlack(const gl::Context *context,
gl::Texture *glTexture) override; gl::Texture *glTexture) override;
......
...@@ -995,6 +995,8 @@ angle::Result UtilsVk::setupProgram(ContextVk *contextVk, ...@@ -995,6 +995,8 @@ angle::Result UtilsVk::setupProgram(ContextVk *contextVk,
// TODO: https://issuetracker.google.com/issues/169788986: Update serial handling. // TODO: https://issuetracker.google.com/issues/169788986: Update serial handling.
pipelineAndSerial->updateSerial(serial); pipelineAndSerial->updateSerial(serial);
commandBuffer->bindComputePipeline(pipelineAndSerial->get()); commandBuffer->bindComputePipeline(pipelineAndSerial->get());
contextVk->invalidateComputePipeline();
} }
else else
{ {
...@@ -1014,6 +1016,8 @@ angle::Result UtilsVk::setupProgram(ContextVk *contextVk, ...@@ -1014,6 +1016,8 @@ angle::Result UtilsVk::setupProgram(ContextVk *contextVk,
*pipelineDesc, gl::AttributesMask(), gl::ComponentTypeMask(), &descPtr, &helper)); *pipelineDesc, gl::AttributesMask(), gl::ComponentTypeMask(), &descPtr, &helper));
helper->updateSerial(serial); helper->updateSerial(serial);
commandBuffer->bindGraphicsPipeline(helper->getPipeline()); commandBuffer->bindGraphicsPipeline(helper->getPipeline());
contextVk->invalidateGraphicsPipeline();
} }
if (descriptorSet != VK_NULL_HANDLE) if (descriptorSet != VK_NULL_HANDLE)
...@@ -1606,9 +1610,6 @@ angle::Result UtilsVk::clearFramebuffer(ContextVk *contextVk, ...@@ -1606,9 +1610,6 @@ angle::Result UtilsVk::clearFramebuffer(ContextVk *contextVk,
commandBuffer->draw(3, 0); commandBuffer->draw(3, 0);
ANGLE_TRY(contextVk->resumeRenderPassQueriesIfActive()); ANGLE_TRY(contextVk->resumeRenderPassQueriesIfActive());
// Make sure what's bound here is correctly reverted on the next draw.
contextVk->invalidateGraphicsPipelineAndDescriptorSets();
// If transform feedback was active, we can't pause and resume it in the same render pass // If transform feedback was active, we can't pause and resume it in the same render pass
// because we can't insert a memory barrier for the counter buffers. In that case, break the // because we can't insert a memory barrier for the counter buffers. In that case, break the
// render pass. // render pass.
......
...@@ -4050,6 +4050,199 @@ void main() { ...@@ -4050,6 +4050,199 @@ void main() {
glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER); glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
} }
// Validate that on Vulkan, compute pipeline is correctly bound after an internal dispatch call is
// made. Blit stencil may issue a dispatch call.
TEST_P(ComputeShaderTest, DispatchBlitStencilDispatch)
{
// http://anglebug.com/5533
ANGLE_SKIP_TEST_IF(IsQualcomm() && IsOpenGLES());
constexpr GLsizei kSize = 1;
constexpr char kCS[] = R"(#version 310 es
layout(local_size_x=6, local_size_y=1, local_size_z=1) in;
uniform vec4 data;
layout(rgba8, binding = 0) writeonly uniform highp image2D image;
void main()
{
imageStore(image, ivec2(gl_LocalInvocationID.xy), data);
})";
ANGLE_GL_COMPUTE_PROGRAM(programCS, kCS);
EXPECT_GL_NO_ERROR();
// Create a framebuffer with stencil buffer. Use multisampled textures so the future blit
// cannot use vkCmdBlitImage.
GLTexture color;
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, color);
glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, true);
GLTexture depthStencil;
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, depthStencil);
glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_DEPTH24_STENCIL8, kSize, kSize,
true);
GLFramebuffer fbo;
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, color,
0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE,
depthStencil, 0);
ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
ASSERT_GL_NO_ERROR();
// Clear the stencil and make sure it's done.
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClearStencil(0x55);
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_EQUAL, 0x55, 0xFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glStencilMask(0xFF);
ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.0f);
ASSERT_GL_NO_ERROR();
GLTexture colorCopy;
glBindTexture(GL_TEXTURE_2D, colorCopy);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
GLFramebuffer copyFbo;
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, copyFbo);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorCopy, 0);
ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
ASSERT_GL_NO_ERROR();
glBindFramebuffer(GL_READ_FRAMEBUFFER, copyFbo);
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
// Setup image for compute call
GLTexture computeOut;
glBindTexture(GL_TEXTURE_2D, computeOut);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
glBindImageTexture(0, computeOut, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
ASSERT_GL_NO_ERROR();
// Issue a dispatch call.
glUseProgram(programCS);
GLint uniformLoc = glGetUniformLocation(programCS, "data");
ASSERT_NE(uniformLoc, -1);
glUniform4f(uniformLoc, 0.0f, 0.0f, 1.0f, 1.0f);
glDispatchCompute(1, 1, 1);
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
ASSERT_GL_NO_ERROR();
// Blit the stencil texture. This may use a compute shader internally.
GLTexture depthStencilCopy;
glBindTexture(GL_TEXTURE_2D, depthStencilCopy);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH24_STENCIL8, kSize, kSize);
ASSERT_GL_NO_ERROR();
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, copyFbo);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
depthStencilCopy, 0);
ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
ASSERT_GL_NO_ERROR();
glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_STENCIL_BUFFER_BIT, GL_NEAREST);
ASSERT_GL_NO_ERROR();
// Issue another dispatch call.
glUniform4f(uniformLoc, 0.0f, 1.0f, 0.0f, 1.0f);
glDispatchCompute(1, 1, 1);
ASSERT_GL_NO_ERROR();
// Verify the results.
glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
glBindFramebuffer(GL_FRAMEBUFFER, copyFbo);
glBindTexture(GL_TEXTURE_2D, computeOut);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, computeOut, 0);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
// Verify the blit copy results.
drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.0f);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
}
// Validate that on Vulkan, compute pipeline is correctly bound after an internal dispatch call is
// made. Generate mipmap may issue a dispatch call.
TEST_P(ComputeShaderTest, DispatchGenerateMipmapDispatch)
{
constexpr GLsizei kSize = 8;
constexpr char kCS[] = R"(#version 310 es
layout(local_size_x=6, local_size_y=1, local_size_z=1) in;
uniform vec4 data;
layout(rgba8, binding = 0) writeonly uniform highp image2D image;
void main()
{
imageStore(image, ivec2(gl_LocalInvocationID.xy), data);
})";
ANGLE_GL_COMPUTE_PROGRAM(programCS, kCS);
EXPECT_GL_NO_ERROR();
GLTexture color;
glBindTexture(GL_TEXTURE_2D, color);
glTexStorage2D(GL_TEXTURE_2D, 4, GL_RGBA8, kSize, kSize);
const std::vector<GLColor> kInitialColor(kSize * kSize, GLColor::green);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE,
kInitialColor.data());
// Setup image for compute call
GLTexture computeOut;
glBindTexture(GL_TEXTURE_2D, computeOut);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
glBindImageTexture(0, computeOut, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
ASSERT_GL_NO_ERROR();
// Issue a dispatch call.
glUseProgram(programCS);
GLint uniformLoc = glGetUniformLocation(programCS, "data");
ASSERT_NE(uniformLoc, -1);
glUniform4f(uniformLoc, 0.0f, 0.0f, 1.0f, 1.0f);
glDispatchCompute(1, 1, 1);
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
ASSERT_GL_NO_ERROR();
// Generate mipmap on the texture. This may use a compute shader internally.
glBindTexture(GL_TEXTURE_2D, color);
glGenerateMipmap(GL_TEXTURE_2D);
// Issue another dispatch call.
glUniform4f(uniformLoc, 0.0f, 1.0f, 0.0f, 1.0f);
glDispatchCompute(1, 1, 1);
ASSERT_GL_NO_ERROR();
// Verify the results.
GLFramebuffer fbo;
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glBindTexture(GL_TEXTURE_2D, computeOut);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, computeOut, 0);
ASSERT_GL_NO_ERROR();
glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
}
// Write to image array with an aliasing format. // Write to image array with an aliasing format.
TEST_P(ComputeShaderTest, AliasingFormatForImageArray) TEST_P(ComputeShaderTest, AliasingFormatForImageArray)
{ {
......
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