Commit 426fa735 by Shahbaz Youssefi Committed by Commit Bot

Vulkan: Fix command reordering on release to external

When releasing buffer/image to external, the necessary barrier was recorded on the "outside render pass command buffer". However, if the resource was used in the current render pass, that render pass should have closed before this, otherwise the barrier was reordered before it which is incorrect. Bug: chromium:1136367 Bug: chromium:1135792 Bug: angleproject:5002 Change-Id: I237d5e6bb46189a4ce61c2f4602e356955cc87a9 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2468456 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCharlie Lao <cclao@google.com>
parent 298c2768
......@@ -4667,6 +4667,20 @@ angle::Result ContextVk::onImageWrite(gl::LevelIndex levelStart,
return angle::Result::Continue;
}
angle::Result ContextVk::onBufferReleaseToExternal(const vk::BufferHelper &buffer)
{
if (mRenderPassCommands->usesBuffer(buffer))
{
ANGLE_TRY(flushCommandsAndEndRenderPass());
}
return angle::Result::Continue;
}
angle::Result ContextVk::onImageReleaseToExternal(const vk::ImageHelper &image)
{
return endRenderPassIfImageUsed(image);
}
angle::Result ContextVk::beginNewRenderPass(
const vk::Framebuffer &framebuffer,
const gl::Rectangle &renderArea,
......
......@@ -506,6 +506,7 @@ class ContextVk : public ContextImpl, public vk::Context
{
return onBufferWrite(VK_ACCESS_SHADER_WRITE_BIT, vk::PipelineStage::ComputeShader, buffer);
}
angle::Result onBufferReleaseToExternal(const vk::BufferHelper &buffer);
angle::Result onImageTransferRead(VkImageAspectFlags aspectFlags, vk::ImageHelper *image)
{
......@@ -535,6 +536,7 @@ class ContextVk : public ContextImpl, public vk::Context
return onImageWrite(levelStart, levelCount, layerStart, layerCount, aspectFlags,
vk::ImageLayout::ComputeShaderWrite, image);
}
angle::Result onImageReleaseToExternal(const vk::ImageHelper &image);
void onImageRenderPassRead(VkImageAspectFlags aspectFlags,
vk::ImageLayout imageLayout,
......
......@@ -168,6 +168,7 @@ angle::Result SemaphoreVk::signal(gl::Context *context,
BufferVk *bufferVk = vk::GetImpl(buffer);
vk::BufferHelper &bufferHelper = bufferVk->getBuffer();
ANGLE_TRY(contextVk->onBufferReleaseToExternal(bufferHelper));
vk::CommandBuffer &commandBuffer = contextVk->getOutsideRenderPassCommandBuffer();
// Queue ownership transfer.
......@@ -196,6 +197,7 @@ angle::Result SemaphoreVk::signal(gl::Context *context,
ANGLE_TRY(textureVk->ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));
ANGLE_TRY(contextVk->onImageReleaseToExternal(image));
vk::CommandBuffer &commandBuffer = contextVk->getOutsideRenderPassCommandBuffer();
// Queue ownership transfer and layout transition.
......
......@@ -206,6 +206,9 @@ class VulkanExternalImageTest : public ANGLETest
setConfigBlueBits(8);
setConfigAlphaBits(8);
}
template <typename Traits>
void runShouldDrawTest(bool isSwiftshader, bool enableDebugLayers);
};
template <typename Traits>
......@@ -442,7 +445,7 @@ TEST_P(VulkanExternalImageTest, ShouldClearZirconWithFlagsVmoRGBA8)
// Test creating and clearing a simple RGBA8 texture without STORAGE usage in a zircon vmo.
TEST_P(VulkanExternalImageTest, ShouldClearNoStorageUsageZirconVmoRGBA8)
{
ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fuchsia"));
ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_fuchsia"));
ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
RunShouldClearTest<FuchsiaTraits>(true, kDefaultImageCreateFlags, kNoStorageImageUsageFlags,
isSwiftshader(), enableDebugLayers());
......@@ -452,7 +455,7 @@ TEST_P(VulkanExternalImageTest, ShouldClearNoStorageUsageZirconVmoRGBA8)
// zircon vmo.
TEST_P(VulkanExternalImageTest, ShouldClearMutableNoStorageUsageZirconVmoRGBA8)
{
ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fuchsia"));
ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_fuchsia"));
ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
RunShouldClearTest<FuchsiaTraits>(true, kMutableImageCreateFlags, kNoStorageImageUsageFlags,
isSwiftshader(), enableDebugLayers());
......@@ -820,6 +823,7 @@ TEST_P(VulkanExternalImageTest, ShouldClearZirconVmoWithSemaphoresNoStorage)
{
ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_fuchsia"));
ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_semaphore_fuchsia"));
ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
RunShouldClearWithSemaphoresTest<FuchsiaTraits>(true, kDefaultImageCreateFlags,
kNoStorageImageUsageFlags, isSwiftshader(),
enableDebugLayers());
......@@ -831,11 +835,157 @@ TEST_P(VulkanExternalImageTest, ShouldClearZirconVmoWithSemaphoresMutableNoStora
{
ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_fuchsia"));
ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_semaphore_fuchsia"));
ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
RunShouldClearWithSemaphoresTest<FuchsiaTraits>(true, kMutableImageCreateFlags,
kNoStorageImageUsageFlags, isSwiftshader(),
enableDebugLayers());
}
template <typename Traits>
void VulkanExternalImageTest::runShouldDrawTest(bool isSwiftshader, bool enableDebugLayers)
{
ASSERT(EnsureGLExtensionEnabled(Traits::MemoryObjectExtension()));
ASSERT(EnsureGLExtensionEnabled(Traits::SemaphoreExtension()));
VulkanExternalHelper helper;
helper.initialize(isSwiftshader, enableDebugLayers);
VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
ANGLE_SKIP_TEST_IF(!Traits::CanCreateImage(helper, format, VK_IMAGE_TYPE_2D,
VK_IMAGE_TILING_OPTIMAL, kDefaultImageCreateFlags,
kDefaultImageUsageFlags));
ANGLE_SKIP_TEST_IF(!Traits::CanCreateSemaphore(helper));
VkSemaphore vkAcquireSemaphore = VK_NULL_HANDLE;
VkResult result = Traits::CreateSemaphore(&helper, &vkAcquireSemaphore);
EXPECT_EQ(result, VK_SUCCESS);
EXPECT_TRUE(vkAcquireSemaphore != VK_NULL_HANDLE);
VkSemaphore vkReleaseSemaphore = VK_NULL_HANDLE;
result = Traits::CreateSemaphore(&helper, &vkReleaseSemaphore);
EXPECT_EQ(result, VK_SUCCESS);
EXPECT_TRUE(vkReleaseSemaphore != VK_NULL_HANDLE);
typename Traits::Handle acquireSemaphoreHandle = Traits::InvalidHandle();
result = Traits::ExportSemaphore(&helper, vkAcquireSemaphore, &acquireSemaphoreHandle);
EXPECT_EQ(result, VK_SUCCESS);
EXPECT_NE(acquireSemaphoreHandle, Traits::InvalidHandle());
typename Traits::Handle releaseSemaphoreHandle = Traits::InvalidHandle();
result = Traits::ExportSemaphore(&helper, vkReleaseSemaphore, &releaseSemaphoreHandle);
EXPECT_EQ(result, VK_SUCCESS);
EXPECT_NE(releaseSemaphoreHandle, Traits::InvalidHandle());
VkImage image = VK_NULL_HANDLE;
VkDeviceMemory deviceMemory = VK_NULL_HANDLE;
VkDeviceSize deviceMemorySize = 0;
VkExtent3D extent = {1, 1, 1};
result =
Traits::CreateImage2D(&helper, format, kDefaultImageCreateFlags, kDefaultImageUsageFlags,
extent, &image, &deviceMemory, &deviceMemorySize);
EXPECT_EQ(result, VK_SUCCESS);
typename Traits::Handle memoryHandle = Traits::InvalidHandle();
result = Traits::ExportMemory(&helper, deviceMemory, &memoryHandle);
EXPECT_EQ(result, VK_SUCCESS);
EXPECT_NE(memoryHandle, Traits::InvalidHandle());
{
GLMemoryObject memoryObject;
GLint dedicatedMemory = GL_TRUE;
glMemoryObjectParameterivEXT(memoryObject, GL_DEDICATED_MEMORY_OBJECT_EXT,
&dedicatedMemory);
Traits::ImportMemory(memoryObject, deviceMemorySize, memoryHandle);
GLTexture texture;
glBindTexture(GL_TEXTURE_2D, texture);
glTexStorageMem2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1, memoryObject, 0);
GLSemaphore glAcquireSemaphore;
Traits::ImportSemaphore(glAcquireSemaphore, acquireSemaphoreHandle);
// Transfer ownership to GL.
helper.releaseImageAndSignalSemaphore(image, VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_GENERAL, vkAcquireSemaphore);
const GLuint barrierTextures[] = {
texture,
};
constexpr uint32_t textureBarriersCount = std::extent<decltype(barrierTextures)>();
const GLenum textureSrcLayouts[] = {
GL_LAYOUT_GENERAL_EXT,
};
constexpr uint32_t textureSrcLayoutsCount = std::extent<decltype(textureSrcLayouts)>();
static_assert(textureBarriersCount == textureSrcLayoutsCount,
"barrierTextures and textureSrcLayouts must be the same length");
glWaitSemaphoreEXT(glAcquireSemaphore, 0, nullptr, textureBarriersCount, barrierTextures,
textureSrcLayouts);
GLFramebuffer framebuffer;
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
// Make the texture red.
ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.0f);
EXPECT_GL_NO_ERROR();
// Transfer ownership back to test.
GLSemaphore glReleaseSemaphore;
Traits::ImportSemaphore(glReleaseSemaphore, releaseSemaphoreHandle);
const GLenum textureDstLayouts[] = {
GL_LAYOUT_TRANSFER_SRC_EXT,
};
constexpr uint32_t textureDstLayoutsCount = std::extent<decltype(textureSrcLayouts)>();
static_assert(textureBarriersCount == textureDstLayoutsCount,
"barrierTextures and textureDstLayouts must be the same length");
glSignalSemaphoreEXT(glReleaseSemaphore, 0, nullptr, textureBarriersCount, barrierTextures,
textureDstLayouts);
helper.waitSemaphoreAndAcquireImage(image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
vkReleaseSemaphore);
uint8_t pixels[4];
VkOffset3D offset = {};
VkExtent3D extent = {1, 1, 1};
helper.readPixels(image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, format, offset, extent,
pixels, sizeof(pixels));
EXPECT_EQ(0xFF, pixels[0]);
EXPECT_EQ(0x00, pixels[1]);
EXPECT_EQ(0x00, pixels[2]);
EXPECT_EQ(0xFF, pixels[3]);
}
EXPECT_GL_NO_ERROR();
vkDeviceWaitIdle(helper.getDevice());
vkDestroyImage(helper.getDevice(), image, nullptr);
vkDestroySemaphore(helper.getDevice(), vkAcquireSemaphore, nullptr);
vkDestroySemaphore(helper.getDevice(), vkReleaseSemaphore, nullptr);
vkFreeMemory(helper.getDevice(), deviceMemory, nullptr);
}
// Test drawing to RGBA8 texture in opaque fd with acquire/release.
TEST_P(VulkanExternalImageTest, ShouldDrawOpaqueFdWithSemaphores)
{
ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_semaphore_fd"));
runShouldDrawTest<OpaqueFdTraits>(isSwiftshader(), enableDebugLayers());
}
// Test drawing to RGBA8 texture in zircon vmo with acquire/release multiple times.
TEST_P(VulkanExternalImageTest, ShouldDrawZirconVmoWithSemaphores)
{
ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_fuchsia"));
ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_semaphore_fuchsia"));
runShouldDrawTest<FuchsiaTraits>(isSwiftshader(), enableDebugLayers());
}
// Support for Zircon handle types is mandatory on Fuchsia.
TEST_P(VulkanExternalImageTest, ShouldSupportExternalHandlesFuchsia)
{
......
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