Add vulkan external memory large image test
This test catches when image layout is broken, by copying a non-trivial
image after it's imported across devices.
Bug: dawn:206
Change-Id: Ic980cfe31c0e564176c6c060f4a1fab220737938
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/10162
Reviewed-by: Austin Eng <enga@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
Commit-Queue: Idan Raiter <idanr@google.com>
diff --git a/src/tests/white_box/VulkanImageWrappingTests.cpp b/src/tests/white_box/VulkanImageWrappingTests.cpp
index 4284a00..abd4e4d 100644
--- a/src/tests/white_box/VulkanImageWrappingTests.cpp
+++ b/src/tests/white_box/VulkanImageWrappingTests.cpp
@@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include "common/Math.h"
#include "tests/DawnTest.h"
#include "common/vulkan_platform.h"
@@ -908,5 +909,111 @@
IgnoreSignalSemaphore(device, wrappedTexCDevice1);
}
+// Tests a larger image is preserved when importing
+// TODO(http://crbug.com/dawn/206): This fails on AMD
+TEST_P(VulkanImageWrappingUsageTests, LargerImage) {
+ DAWN_SKIP_TEST_IF(UsesWire() || IsIntel() || IsAMD());
+
+ close(defaultFd);
+
+ dawn::TextureDescriptor descriptor;
+ descriptor.dimension = dawn::TextureDimension::e2D;
+ descriptor.size.width = 640;
+ descriptor.size.height = 480;
+ descriptor.size.depth = 1;
+ descriptor.arrayLayerCount = 1;
+ descriptor.sampleCount = 1;
+ descriptor.format = dawn::TextureFormat::BGRA8Unorm;
+ descriptor.mipLevelCount = 1;
+ descriptor.usage = dawn::TextureUsageBit::CopyDst | dawn::TextureUsageBit::CopySrc;
+
+ // Fill memory with textures to trigger layout issues on AMD
+ std::vector<dawn::Texture> textures;
+ for (int i = 0; i < 20; i++) {
+ textures.push_back(device.CreateTexture(&descriptor));
+ }
+
+ dawn::Queue secondDeviceQueue = secondDevice.CreateQueue();
+
+ // Make an image on |secondDevice|
+ VkImage imageA;
+ VkDeviceMemory allocationA;
+ int memoryFdA;
+ VkDeviceSize allocationSizeA;
+ uint32_t memoryTypeIndexA;
+ CreateBindExportImage(secondDeviceVk, 640, 480, VK_FORMAT_R8G8B8A8_UNORM, &imageA, &allocationA,
+ &allocationSizeA, &memoryTypeIndexA, &memoryFdA);
+
+ // Import the image on |secondDevice|
+ dawn::Texture wrappedTexture = WrapVulkanImage(secondDevice, &descriptor, memoryFdA,
+ allocationSizeA, memoryTypeIndexA, {});
+
+ // Draw a non-trivial picture
+ int width = 640, height = 480, pixelSize = 4;
+ uint32_t rowPitch = Align(width * pixelSize, kTextureRowPitchAlignment);
+ uint32_t size = rowPitch * (height - 1) + width * pixelSize;
+ unsigned char data[size];
+ for (int row = 0; row < height; row++) {
+ for (int col = 0; col < width; col++) {
+ float normRow = static_cast<float>(row) / height;
+ float normCol = static_cast<float>(col) / width;
+ float dist = sqrt(normRow * normRow + normCol * normCol) * 3;
+ dist = dist - static_cast<int>(dist);
+ data[4 * (row * width + col)] = static_cast<unsigned char>(dist * 255);
+ data[4 * (row * width + col) + 1] = static_cast<unsigned char>(dist * 255);
+ data[4 * (row * width + col) + 2] = static_cast<unsigned char>(dist * 255);
+ data[4 * (row * width + col) + 3] = 255;
+ }
+ }
+
+ // Write the picture
+ {
+ dawn::Buffer copySrcBuffer =
+ utils::CreateBufferFromData(secondDevice, data, size, dawn::BufferUsageBit::CopySrc);
+ dawn::BufferCopyView copySrc = utils::CreateBufferCopyView(copySrcBuffer, 0, rowPitch, 0);
+ dawn::TextureCopyView copyDst =
+ utils::CreateTextureCopyView(wrappedTexture, 0, 0, {0, 0, 0});
+ dawn::Extent3D copySize = {width, height, 1};
+
+ dawn::CommandEncoder encoder = secondDevice.CreateCommandEncoder();
+ encoder.CopyBufferToTexture(©Src, ©Dst, ©Size);
+ dawn::CommandBuffer commands = encoder.Finish();
+ secondDeviceQueue.Submit(1, &commands);
+ }
+
+ int signalFd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(secondDevice.Get(),
+ wrappedTexture.Get());
+ int memoryFd = GetMemoryFd(secondDeviceVk, allocationA);
+
+ // Import the image on |device|
+ dawn::Texture nextWrappedTexture = WrapVulkanImage(
+ device, &descriptor, memoryFd, allocationSizeA, memoryTypeIndexA, {signalFd});
+
+ // Copy the image into a buffer for comparison
+ dawn::BufferDescriptor copyDesc;
+ copyDesc.size = size;
+ copyDesc.usage = dawn::BufferUsageBit::CopySrc | dawn::BufferUsageBit::CopyDst;
+ dawn::Buffer copyDstBuffer = device.CreateBuffer(©Desc);
+ {
+ dawn::TextureCopyView copySrc =
+ utils::CreateTextureCopyView(nextWrappedTexture, 0, 0, {0, 0, 0});
+ dawn::BufferCopyView copyDst = utils::CreateBufferCopyView(copyDstBuffer, 0, rowPitch, 0);
+
+ dawn::Extent3D copySize = {width, height, 1};
+
+ dawn::CommandEncoder encoder = device.CreateCommandEncoder();
+ encoder.CopyTextureToBuffer(©Src, ©Dst, ©Size);
+ dawn::CommandBuffer commands = encoder.Finish();
+ queue.Submit(1, &commands);
+ }
+
+ // Check the image is not corrupted on |device|
+ EXPECT_BUFFER_U32_RANGE_EQ(reinterpret_cast<uint32_t*>(data), copyDstBuffer, 0, size / 4);
+
+ IgnoreSignalSemaphore(device, nextWrappedTexture);
+ secondDeviceVk->GetFencedDeleter()->DeleteWhenUnused(imageA);
+ secondDeviceVk->GetFencedDeleter()->DeleteWhenUnused(allocationA);
+}
+
DAWN_INSTANTIATE_TEST(VulkanImageWrappingValidationTests, VulkanBackend);
DAWN_INSTANTIATE_TEST(VulkanImageWrappingUsageTests, VulkanBackend);