vulkan: Validate that exporting a texture uses VK_IMAGE_LAYOUT_UNDEFINED

Using any other desiredLayout is deprecated. This simplifies future
changes which as much as possible eliminate any transitions during
texture export.

Bug: chromium:1359106
Change-Id: Ifb5818775e8f15ec77a229d3cbf593348740da46
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/104543
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Austin Eng <enga@chromium.org>
This commit is contained in:
Austin Eng 2022-10-04 17:27:21 +00:00 committed by Dawn LUCI CQ
parent 9ecc310210
commit 663932d741
8 changed files with 31 additions and 41 deletions

View File

@ -174,6 +174,8 @@ DAWN_NATIVE_EXPORT WGPUTexture WrapVulkanImage(WGPUDevice device,
DAWN_NATIVE_EXPORT bool ExportVulkanImage(WGPUTexture texture, DAWN_NATIVE_EXPORT bool ExportVulkanImage(WGPUTexture texture,
VkImageLayout desiredLayout, VkImageLayout desiredLayout,
ExternalImageExportInfoVk* info); ExternalImageExportInfoVk* info);
// |ExportVulkanImage| with default desiredLayout of VK_IMAGE_LAYOUT_UNDEFINED.
DAWN_NATIVE_EXPORT bool ExportVulkanImage(WGPUTexture texture, ExternalImageExportInfoVk* info);
} // namespace dawn::native::vulkan } // namespace dawn::native::vulkan

View File

@ -882,6 +882,9 @@ MaybeError Texture::ExportExternalTexture(VkImageLayout desiredLayout,
"Can't export a signal semaphore from destroyed or non-external texture %s.", "Can't export a signal semaphore from destroyed or non-external texture %s.",
this); this);
DAWN_INVALID_IF(desiredLayout != VK_IMAGE_LAYOUT_UNDEFINED,
"desiredLayout (%d) was not VK_IMAGE_LAYOUT_UNDEFINED", desiredLayout);
// Release the texture // Release the texture
mExternalState = ExternalState::Released; mExternalState = ExternalState::Released;
@ -894,9 +897,7 @@ MaybeError Texture::ExportExternalTexture(VkImageLayout desiredLayout,
// promoting to GENERAL. // promoting to GENERAL.
VkImageLayout currentLayout = VulkanImageLayout(this, usage); VkImageLayout currentLayout = VulkanImageLayout(this, usage);
VkImageLayout targetLayout; VkImageLayout targetLayout;
if (desiredLayout != VK_IMAGE_LAYOUT_UNDEFINED) { if (currentLayout != VK_IMAGE_LAYOUT_UNDEFINED) {
targetLayout = desiredLayout;
} else if (currentLayout != VK_IMAGE_LAYOUT_UNDEFINED) {
targetLayout = currentLayout; targetLayout = currentLayout;
} else { } else {
targetLayout = VK_IMAGE_LAYOUT_GENERAL; targetLayout = VK_IMAGE_LAYOUT_GENERAL;

View File

@ -136,4 +136,8 @@ bool ExportVulkanImage(WGPUTexture texture,
#endif // DAWN_PLATFORM_IS(LINUX) #endif // DAWN_PLATFORM_IS(LINUX)
} }
bool ExportVulkanImage(WGPUTexture texture, ExternalImageExportInfoVk* info) {
return ExportVulkanImage(texture, VK_IMAGE_LAYOUT_UNDEFINED, info);
}
} // namespace dawn::native::vulkan } // namespace dawn::native::vulkan

View File

@ -204,7 +204,7 @@ class VideoViewsTestBackendGbm : public VideoViewsTestBackend {
// Exports the signal and ignores it. // Exports the signal and ignores it.
dawn::native::vulkan::ExternalImageExportInfoDmaBuf exportInfo; dawn::native::vulkan::ExternalImageExportInfoDmaBuf exportInfo;
dawn::native::vulkan::ExportVulkanImage(platformTexture->wgpuTexture.Get(), dawn::native::vulkan::ExportVulkanImage(platformTexture->wgpuTexture.Get(),
VK_IMAGE_LAYOUT_GENERAL, &exportInfo); VK_IMAGE_LAYOUT_UNDEFINED, &exportInfo);
for (int fd : exportInfo.semaphoreHandles) { for (int fd : exportInfo.semaphoreHandles) {
ASSERT_NE(fd, -1); ASSERT_NE(fd, -1);
close(fd); close(fd);

View File

@ -134,7 +134,7 @@ class VulkanImageWrappingTestBase : public DawnTestWithParams<ImageWrappingParam
// assertion failure // assertion failure
void IgnoreSignalSemaphore(wgpu::Texture wrappedTexture) { void IgnoreSignalSemaphore(wgpu::Texture wrappedTexture) {
ExternalImageExportInfoVkForTesting exportInfo; ExternalImageExportInfoVkForTesting exportInfo;
bool result = mBackend->ExportImage(wrappedTexture, VK_IMAGE_LAYOUT_UNDEFINED, &exportInfo); bool result = mBackend->ExportImage(wrappedTexture, &exportInfo);
ASSERT(result); ASSERT(result);
} }
@ -225,8 +225,7 @@ TEST_P(VulkanImageWrappingValidationTests, DoubleSignalSemaphoreExport) {
IgnoreSignalSemaphore(texture); IgnoreSignalSemaphore(texture);
ExternalImageExportInfoVkForTesting exportInfo; ExternalImageExportInfoVkForTesting exportInfo;
ASSERT_DEVICE_ERROR(bool success = ASSERT_DEVICE_ERROR(bool success = mBackend->ExportImage(texture, &exportInfo));
mBackend->ExportImage(texture, VK_IMAGE_LAYOUT_UNDEFINED, &exportInfo));
ASSERT_FALSE(success); ASSERT_FALSE(success);
ASSERT_EQ(exportInfo.semaphores.size(), 0u); ASSERT_EQ(exportInfo.semaphores.size(), 0u);
} }
@ -237,21 +236,20 @@ TEST_P(VulkanImageWrappingValidationTests, NormalTextureSignalSemaphoreExport) {
ASSERT_NE(texture.Get(), nullptr); ASSERT_NE(texture.Get(), nullptr);
ExternalImageExportInfoVkForTesting exportInfo; ExternalImageExportInfoVkForTesting exportInfo;
ASSERT_DEVICE_ERROR(bool success = ASSERT_DEVICE_ERROR(bool success = mBackend->ExportImage(texture, &exportInfo));
mBackend->ExportImage(texture, VK_IMAGE_LAYOUT_UNDEFINED, &exportInfo));
ASSERT_FALSE(success); ASSERT_FALSE(success);
ASSERT_EQ(exportInfo.semaphores.size(), 0u); ASSERT_EQ(exportInfo.semaphores.size(), 0u);
} }
// Test an error occurs if we try to export the signal semaphore from a destroyed texture // Test an error occurs if we try to export the signal semaphore from a destroyed texture
TEST_P(VulkanImageWrappingValidationTests, DestroyedTextureSignalSemaphoreExport) { TEST_P(VulkanImageWrappingValidationTests, DestroyedTextureSignalSemaphoreExport) {
wgpu::Texture texture = device.CreateTexture(&defaultDescriptor); wgpu::Texture texture =
WrapVulkanImage(device, &defaultDescriptor, defaultTexture.get(), {}, true, true);
ASSERT_NE(texture.Get(), nullptr); ASSERT_NE(texture.Get(), nullptr);
texture.Destroy(); texture.Destroy();
ExternalImageExportInfoVkForTesting exportInfo; ExternalImageExportInfoVkForTesting exportInfo;
ASSERT_DEVICE_ERROR(bool success = ASSERT_DEVICE_ERROR(bool success = mBackend->ExportImage(texture, &exportInfo));
mBackend->ExportImage(texture, VK_IMAGE_LAYOUT_UNDEFINED, &exportInfo));
ASSERT_FALSE(success); ASSERT_FALSE(success);
ASSERT_EQ(exportInfo.semaphores.size(), 0u); ASSERT_EQ(exportInfo.semaphores.size(), 0u);
} }
@ -337,8 +335,7 @@ TEST_P(VulkanImageWrappingUsageTests, ClearImageAcrossDevices) {
ClearImage(secondDevice, wrappedTexture, {1 / 255.0f, 2 / 255.0f, 3 / 255.0f, 4 / 255.0f}); ClearImage(secondDevice, wrappedTexture, {1 / 255.0f, 2 / 255.0f, 3 / 255.0f, 4 / 255.0f});
ExternalImageExportInfoVkForTesting exportInfo; ExternalImageExportInfoVkForTesting exportInfo;
ASSERT_TRUE( ASSERT_TRUE(mBackend->ExportImage(wrappedTexture, &exportInfo));
mBackend->ExportImage(wrappedTexture, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, &exportInfo));
// Import the image to |device|, making sure we wait on signalFd // Import the image to |device|, making sure we wait on signalFd
wgpu::Texture nextWrappedTexture = WrapVulkanImage( wgpu::Texture nextWrappedTexture = WrapVulkanImage(
@ -363,8 +360,7 @@ TEST_P(VulkanImageWrappingUsageTests, UninitializedTextureIsCleared) {
ClearImage(secondDevice, wrappedTexture, {1 / 255.0f, 2 / 255.0f, 3 / 255.0f, 4 / 255.0f}); ClearImage(secondDevice, wrappedTexture, {1 / 255.0f, 2 / 255.0f, 3 / 255.0f, 4 / 255.0f});
ExternalImageExportInfoVkForTesting exportInfo; ExternalImageExportInfoVkForTesting exportInfo;
ASSERT_TRUE( ASSERT_TRUE(mBackend->ExportImage(wrappedTexture, &exportInfo));
mBackend->ExportImage(wrappedTexture, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, &exportInfo));
// Import the image to |device|, making sure we wait on signalFd // Import the image to |device|, making sure we wait on signalFd
wgpu::Texture nextWrappedTexture = WrapVulkanImage( wgpu::Texture nextWrappedTexture = WrapVulkanImage(
@ -391,8 +387,7 @@ TEST_P(VulkanImageWrappingUsageTests, CopyTextureToTextureSrcSync) {
ClearImage(secondDevice, wrappedTexture, {1 / 255.0f, 2 / 255.0f, 3 / 255.0f, 4 / 255.0f}); ClearImage(secondDevice, wrappedTexture, {1 / 255.0f, 2 / 255.0f, 3 / 255.0f, 4 / 255.0f});
ExternalImageExportInfoVkForTesting exportInfo; ExternalImageExportInfoVkForTesting exportInfo;
ASSERT_TRUE( ASSERT_TRUE(mBackend->ExportImage(wrappedTexture, &exportInfo));
mBackend->ExportImage(wrappedTexture, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, &exportInfo));
// Import the image to |device|, making sure we wait on |signalFd| // Import the image to |device|, making sure we wait on |signalFd|
wgpu::Texture deviceWrappedTexture = WrapVulkanImage( wgpu::Texture deviceWrappedTexture = WrapVulkanImage(
@ -430,8 +425,7 @@ TEST_P(VulkanImageWrappingUsageTests, CopyTextureToTextureDstSync) {
ClearImage(device, wrappedTexture, {5 / 255.0f, 6 / 255.0f, 7 / 255.0f, 8 / 255.0f}); ClearImage(device, wrappedTexture, {5 / 255.0f, 6 / 255.0f, 7 / 255.0f, 8 / 255.0f});
ExternalImageExportInfoVkForTesting exportInfo; ExternalImageExportInfoVkForTesting exportInfo;
ASSERT_TRUE( ASSERT_TRUE(mBackend->ExportImage(wrappedTexture, &exportInfo));
mBackend->ExportImage(wrappedTexture, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &exportInfo));
// Import the image to |secondDevice|, making sure we wait on |signalFd| // Import the image to |secondDevice|, making sure we wait on |signalFd|
wgpu::Texture secondDeviceWrappedTexture = WrapVulkanImage( wgpu::Texture secondDeviceWrappedTexture = WrapVulkanImage(
@ -449,8 +443,7 @@ TEST_P(VulkanImageWrappingUsageTests, CopyTextureToTextureDstSync) {
// Re-import back into |device|, waiting on |secondDevice|'s signal // Re-import back into |device|, waiting on |secondDevice|'s signal
ExternalImageExportInfoVkForTesting secondExportInfo; ExternalImageExportInfoVkForTesting secondExportInfo;
ASSERT_TRUE(mBackend->ExportImage(secondDeviceWrappedTexture, ASSERT_TRUE(mBackend->ExportImage(secondDeviceWrappedTexture, &secondExportInfo));
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, &secondExportInfo));
wgpu::Texture nextWrappedTexture = WrapVulkanImage( wgpu::Texture nextWrappedTexture = WrapVulkanImage(
device, &defaultDescriptor, defaultTexture.get(), std::move(secondExportInfo.semaphores), device, &defaultDescriptor, defaultTexture.get(), std::move(secondExportInfo.semaphores),
@ -476,8 +469,7 @@ TEST_P(VulkanImageWrappingUsageTests, CopyTextureToBufferSrcSync) {
ClearImage(secondDevice, wrappedTexture, {1 / 255.0f, 2 / 255.0f, 3 / 255.0f, 4 / 255.0f}); ClearImage(secondDevice, wrappedTexture, {1 / 255.0f, 2 / 255.0f, 3 / 255.0f, 4 / 255.0f});
ExternalImageExportInfoVkForTesting exportInfo; ExternalImageExportInfoVkForTesting exportInfo;
ASSERT_TRUE( ASSERT_TRUE(mBackend->ExportImage(wrappedTexture, &exportInfo));
mBackend->ExportImage(wrappedTexture, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, &exportInfo));
// Import the image to |device|, making sure we wait on |signalFd| // Import the image to |device|, making sure we wait on |signalFd|
wgpu::Texture deviceWrappedTexture = WrapVulkanImage( wgpu::Texture deviceWrappedTexture = WrapVulkanImage(
@ -527,8 +519,7 @@ TEST_P(VulkanImageWrappingUsageTests, CopyBufferToTextureDstSync) {
ClearImage(device, wrappedTexture, {5 / 255.0f, 6 / 255.0f, 7 / 255.0f, 8 / 255.0f}); ClearImage(device, wrappedTexture, {5 / 255.0f, 6 / 255.0f, 7 / 255.0f, 8 / 255.0f});
ExternalImageExportInfoVkForTesting exportInfo; ExternalImageExportInfoVkForTesting exportInfo;
ASSERT_TRUE( ASSERT_TRUE(mBackend->ExportImage(wrappedTexture, &exportInfo));
mBackend->ExportImage(wrappedTexture, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, &exportInfo));
// Import the image to |secondDevice|, making sure we wait on |signalFd| // Import the image to |secondDevice|, making sure we wait on |signalFd|
wgpu::Texture secondDeviceWrappedTexture = WrapVulkanImage( wgpu::Texture secondDeviceWrappedTexture = WrapVulkanImage(
@ -556,8 +547,7 @@ TEST_P(VulkanImageWrappingUsageTests, CopyBufferToTextureDstSync) {
// Re-import back into |device|, waiting on |secondDevice|'s signal // Re-import back into |device|, waiting on |secondDevice|'s signal
ExternalImageExportInfoVkForTesting secondExportInfo; ExternalImageExportInfoVkForTesting secondExportInfo;
ASSERT_TRUE(mBackend->ExportImage(secondDeviceWrappedTexture, ASSERT_TRUE(mBackend->ExportImage(secondDeviceWrappedTexture, &secondExportInfo));
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, &secondExportInfo));
wgpu::Texture nextWrappedTexture = WrapVulkanImage( wgpu::Texture nextWrappedTexture = WrapVulkanImage(
device, &defaultDescriptor, defaultTexture.get(), std::move(secondExportInfo.semaphores), device, &defaultDescriptor, defaultTexture.get(), std::move(secondExportInfo.semaphores),
@ -584,8 +574,7 @@ TEST_P(VulkanImageWrappingUsageTests, DoubleTextureUsage) {
ClearImage(secondDevice, wrappedTexture, {1 / 255.0f, 2 / 255.0f, 3 / 255.0f, 4 / 255.0f}); ClearImage(secondDevice, wrappedTexture, {1 / 255.0f, 2 / 255.0f, 3 / 255.0f, 4 / 255.0f});
ExternalImageExportInfoVkForTesting exportInfo; ExternalImageExportInfoVkForTesting exportInfo;
ASSERT_TRUE( ASSERT_TRUE(mBackend->ExportImage(wrappedTexture, &exportInfo));
mBackend->ExportImage(wrappedTexture, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, &exportInfo));
// Import the image to |device|, making sure we wait on |signalFd| // Import the image to |device|, making sure we wait on |signalFd|
wgpu::Texture deviceWrappedTexture = WrapVulkanImage( wgpu::Texture deviceWrappedTexture = WrapVulkanImage(
@ -658,8 +647,7 @@ TEST_P(VulkanImageWrappingUsageTests, ChainTextureCopy) {
wrappedTexBDevice3); wrappedTexBDevice3);
ExternalImageExportInfoVkForTesting exportInfoTexBDevice3; ExternalImageExportInfoVkForTesting exportInfoTexBDevice3;
ASSERT_TRUE(mBackend->ExportImage(wrappedTexBDevice3, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, ASSERT_TRUE(mBackend->ExportImage(wrappedTexBDevice3, &exportInfoTexBDevice3));
&exportInfoTexBDevice3));
IgnoreSignalSemaphore(wrappedTexADevice3); IgnoreSignalSemaphore(wrappedTexADevice3);
// Import TexB, TexC on device 2 // Import TexB, TexC on device 2
@ -677,8 +665,7 @@ TEST_P(VulkanImageWrappingUsageTests, ChainTextureCopy) {
wrappedTexCDevice2); wrappedTexCDevice2);
ExternalImageExportInfoVkForTesting exportInfoTexCDevice2; ExternalImageExportInfoVkForTesting exportInfoTexCDevice2;
ASSERT_TRUE(mBackend->ExportImage(wrappedTexCDevice2, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, ASSERT_TRUE(mBackend->ExportImage(wrappedTexCDevice2, &exportInfoTexCDevice2));
&exportInfoTexCDevice2));
IgnoreSignalSemaphore(wrappedTexBDevice2); IgnoreSignalSemaphore(wrappedTexBDevice2);
// Import TexC on device 1 // Import TexC on device 1
@ -760,8 +747,7 @@ TEST_P(VulkanImageWrappingUsageTests, LargerImage) {
secondDeviceQueue.Submit(1, &commands); secondDeviceQueue.Submit(1, &commands);
} }
ExternalImageExportInfoVkForTesting exportInfo; ExternalImageExportInfoVkForTesting exportInfo;
ASSERT_TRUE( ASSERT_TRUE(mBackend->ExportImage(wrappedTexture, &exportInfo));
mBackend->ExportImage(wrappedTexture, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, &exportInfo));
// Import the image on |device| // Import the image on |device|
wgpu::Texture nextWrappedTexture = wgpu::Texture nextWrappedTexture =

View File

@ -66,7 +66,6 @@ class VulkanImageWrappingTestBackend {
std::vector<std::unique_ptr<ExternalSemaphore>> semaphores) = 0; std::vector<std::unique_ptr<ExternalSemaphore>> semaphores) = 0;
virtual bool ExportImage(const wgpu::Texture& texture, virtual bool ExportImage(const wgpu::Texture& texture,
VkImageLayout layout,
ExternalImageExportInfoVkForTesting* exportInfo) = 0; ExternalImageExportInfoVkForTesting* exportInfo) = 0;
private: private:

View File

@ -143,10 +143,9 @@ class VulkanImageWrappingTestBackendDmaBuf : public VulkanImageWrappingTestBacke
} }
bool ExportImage(const wgpu::Texture& texture, bool ExportImage(const wgpu::Texture& texture,
VkImageLayout layout,
ExternalImageExportInfoVkForTesting* exportInfo) override { ExternalImageExportInfoVkForTesting* exportInfo) override {
ExternalImageExportInfoDmaBuf infoDmaBuf; ExternalImageExportInfoDmaBuf infoDmaBuf;
bool success = ExportVulkanImage(texture.Get(), layout, &infoDmaBuf); bool success = ExportVulkanImage(texture.Get(), VK_IMAGE_LAYOUT_UNDEFINED, &infoDmaBuf);
*static_cast<ExternalImageExportInfoVk*>(exportInfo) = infoDmaBuf; *static_cast<ExternalImageExportInfoVk*>(exportInfo) = infoDmaBuf;
for (int fd : infoDmaBuf.semaphoreHandles) { for (int fd : infoDmaBuf.semaphoreHandles) {

View File

@ -160,10 +160,9 @@ class VulkanImageWrappingTestBackendOpaqueFD : public VulkanImageWrappingTestBac
} }
bool ExportImage(const wgpu::Texture& texture, bool ExportImage(const wgpu::Texture& texture,
VkImageLayout layout,
ExternalImageExportInfoVkForTesting* exportInfo) override { ExternalImageExportInfoVkForTesting* exportInfo) override {
ExternalImageExportInfoOpaqueFD infoOpaqueFD; ExternalImageExportInfoOpaqueFD infoOpaqueFD;
bool success = ExportVulkanImage(texture.Get(), layout, &infoOpaqueFD); bool success = ExportVulkanImage(texture.Get(), VK_IMAGE_LAYOUT_UNDEFINED, &infoOpaqueFD);
*static_cast<ExternalImageExportInfoVk*>(exportInfo) = infoOpaqueFD; *static_cast<ExternalImageExportInfoVk*>(exportInfo) = infoOpaqueFD;
for (int fd : infoOpaqueFD.semaphoreHandles) { for (int fd : infoOpaqueFD.semaphoreHandles) {