Pass the old/new VkImageLayouts to Vulkan image import/export
Returning the layouts from an export operation and then using
them in a subsequent import operation allows the import to preserve
the texture contents.
This fixes Vukan image wrapping on some AMD/NVIDIA devices.
Bug: dawn:200
Change-Id: Icbb6e759856d410bb69724b9f439bc3088756d19
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/28380
Commit-Queue: Austin Eng <enga@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
diff --git a/src/dawn_native/DawnNative.cpp b/src/dawn_native/DawnNative.cpp
index b7bb94b..22b3dde 100644
--- a/src/dawn_native/DawnNative.cpp
+++ b/src/dawn_native/DawnNative.cpp
@@ -195,8 +195,14 @@
return GetProcMapNamesForTestingInternal();
}
- ExternalImageDescriptor::ExternalImageDescriptor(ExternalImageDescriptorType type)
- : type(type) {
+ // ExternalImageDescriptor
+
+ ExternalImageDescriptor::ExternalImageDescriptor(ExternalImageType type) : type(type) {
+ }
+
+ // ExternalImageExportInfo
+
+ ExternalImageExportInfo::ExternalImageExportInfo(ExternalImageType type) : type(type) {
}
} // namespace dawn_native
diff --git a/src/dawn_native/d3d12/D3D12Backend.cpp b/src/dawn_native/d3d12/D3D12Backend.cpp
index 7196599..73175fa 100644
--- a/src/dawn_native/d3d12/D3D12Backend.cpp
+++ b/src/dawn_native/d3d12/D3D12Backend.cpp
@@ -48,7 +48,7 @@
}
ExternalImageDescriptorDXGISharedHandle::ExternalImageDescriptorDXGISharedHandle()
- : ExternalImageDescriptor(ExternalImageDescriptorType::DXGISharedHandle) {
+ : ExternalImageDescriptor(ExternalImageType::DXGISharedHandle) {
}
uint64_t SetExternalMemoryReservation(WGPUDevice device,
diff --git a/src/dawn_native/d3d12/TextureD3D12.cpp b/src/dawn_native/d3d12/TextureD3D12.cpp
index e30534a..d9ef627 100644
--- a/src/dawn_native/d3d12/TextureD3D12.cpp
+++ b/src/dawn_native/d3d12/TextureD3D12.cpp
@@ -396,7 +396,7 @@
AcquireRef(new Texture(device, textureDescriptor, TextureState::OwnedExternal));
DAWN_TRY(dawnTexture->InitializeAsExternalTexture(textureDescriptor, sharedHandle,
acquireMutexKey, isSwapChainTexture));
- dawnTexture->SetIsSubresourceContentInitialized(descriptor->isCleared,
+ dawnTexture->SetIsSubresourceContentInitialized(descriptor->isInitialized,
dawnTexture->GetAllSubresources());
return std::move(dawnTexture);
}
diff --git a/src/dawn_native/metal/MetalBackend.mm b/src/dawn_native/metal/MetalBackend.mm
index 24c4481..74265a23 100644
--- a/src/dawn_native/metal/MetalBackend.mm
+++ b/src/dawn_native/metal/MetalBackend.mm
@@ -28,7 +28,7 @@
}
ExternalImageDescriptorIOSurface::ExternalImageDescriptorIOSurface()
- : ExternalImageDescriptor(ExternalImageDescriptorType::IOSurface) {
+ : ExternalImageDescriptor(ExternalImageType::IOSurface) {
}
WGPUTexture WrapIOSurface(WGPUDevice cDevice,
diff --git a/src/dawn_native/metal/TextureMTL.mm b/src/dawn_native/metal/TextureMTL.mm
index 22931fd..c1a6abf 100644
--- a/src/dawn_native/metal/TextureMTL.mm
+++ b/src/dawn_native/metal/TextureMTL.mm
@@ -355,7 +355,7 @@
plane:plane];
[mtlDesc release];
- SetIsSubresourceContentInitialized(descriptor->isCleared, GetAllSubresources());
+ SetIsSubresourceContentInitialized(descriptor->isInitialized, GetAllSubresources());
}
Texture::~Texture() {
diff --git a/src/dawn_native/vulkan/DeviceVk.cpp b/src/dawn_native/vulkan/DeviceVk.cpp
index b838858..c96cede 100644
--- a/src/dawn_native/vulkan/DeviceVk.cpp
+++ b/src/dawn_native/vulkan/DeviceVk.cpp
@@ -658,7 +658,7 @@
return {};
}
- MaybeError Device::ImportExternalImage(const ExternalImageDescriptor* descriptor,
+ MaybeError Device::ImportExternalImage(const ExternalImageDescriptorVk* descriptor,
ExternalMemoryHandle memoryHandle,
VkImage image,
const std::vector<ExternalSemaphoreHandle>& waitHandles,
@@ -702,22 +702,35 @@
return {};
}
- MaybeError Device::SignalAndExportExternalTexture(Texture* texture,
- ExternalSemaphoreHandle* outHandle) {
- DAWN_TRY(ValidateObject(texture));
+ bool Device::SignalAndExportExternalTexture(
+ Texture* texture,
+ VkImageLayout desiredLayout,
+ ExternalImageExportInfoVk* info,
+ std::vector<ExternalSemaphoreHandle>* semaphoreHandles) {
+ return !ConsumedError([&]() -> MaybeError {
+ DAWN_TRY(ValidateObject(texture));
- VkSemaphore outSignalSemaphore;
- DAWN_TRY(texture->SignalAndDestroy(&outSignalSemaphore));
+ VkSemaphore signalSemaphore;
+ VkImageLayout releasedOldLayout;
+ VkImageLayout releasedNewLayout;
+ DAWN_TRY(texture->ExportExternalTexture(desiredLayout, &signalSemaphore,
+ &releasedOldLayout, &releasedNewLayout));
- // This has to happen right after SignalAndDestroy, since the semaphore will be
- // deleted when the fenced deleter runs after the queue submission
- DAWN_TRY_ASSIGN(*outHandle, mExternalSemaphoreService->ExportSemaphore(outSignalSemaphore));
+ ExternalSemaphoreHandle semaphoreHandle;
+ DAWN_TRY_ASSIGN(semaphoreHandle,
+ mExternalSemaphoreService->ExportSemaphore(signalSemaphore));
+ semaphoreHandles->push_back(semaphoreHandle);
+ info->releasedOldLayout = releasedOldLayout;
+ info->releasedNewLayout = releasedNewLayout;
+ info->isInitialized =
+ texture->IsSubresourceContentInitialized(texture->GetAllSubresources());
- return {};
+ return {};
+ }());
}
TextureBase* Device::CreateTextureWrappingVulkanImage(
- const ExternalImageDescriptor* descriptor,
+ const ExternalImageDescriptorVk* descriptor,
ExternalMemoryHandle memoryHandle,
const std::vector<ExternalSemaphoreHandle>& waitHandles) {
const TextureDescriptor* textureDescriptor =
diff --git a/src/dawn_native/vulkan/DeviceVk.h b/src/dawn_native/vulkan/DeviceVk.h
index 9adf3ee..1b44bb7 100644
--- a/src/dawn_native/vulkan/DeviceVk.h
+++ b/src/dawn_native/vulkan/DeviceVk.h
@@ -69,12 +69,13 @@
// Dawn Native API
TextureBase* CreateTextureWrappingVulkanImage(
- const ExternalImageDescriptor* descriptor,
+ const ExternalImageDescriptorVk* descriptor,
ExternalMemoryHandle memoryHandle,
const std::vector<ExternalSemaphoreHandle>& waitHandles);
-
- MaybeError SignalAndExportExternalTexture(Texture* texture,
- ExternalSemaphoreHandle* outHandle);
+ bool SignalAndExportExternalTexture(Texture* texture,
+ VkImageLayout desiredLayout,
+ ExternalImageExportInfoVk* info,
+ std::vector<ExternalSemaphoreHandle>* semaphoreHandle);
// Dawn API
CommandBufferBase* CreateCommandBuffer(CommandEncoder* encoder,
@@ -192,7 +193,7 @@
// There is always a valid recording context stored in mRecordingContext
CommandRecordingContext mRecordingContext;
- MaybeError ImportExternalImage(const ExternalImageDescriptor* descriptor,
+ MaybeError ImportExternalImage(const ExternalImageDescriptorVk* descriptor,
ExternalMemoryHandle memoryHandle,
VkImage image,
const std::vector<ExternalSemaphoreHandle>& waitHandles,
@@ -203,4 +204,4 @@
}} // namespace dawn_native::vulkan
-#endif // DAWNNATIVE_VULKAN_DEVICEVK_H_
\ No newline at end of file
+#endif // DAWNNATIVE_VULKAN_DEVICEVK_H_
diff --git a/src/dawn_native/vulkan/TextureVk.cpp b/src/dawn_native/vulkan/TextureVk.cpp
index 5112a4c..7627282 100644
--- a/src/dawn_native/vulkan/TextureVk.cpp
+++ b/src/dawn_native/vulkan/TextureVk.cpp
@@ -462,7 +462,7 @@
// static
ResultOrError<Texture*> Texture::CreateFromExternal(
Device* device,
- const ExternalImageDescriptor* descriptor,
+ const ExternalImageDescriptorVk* descriptor,
const TextureDescriptor* textureDescriptor,
external_memory::Service* externalMemoryService) {
Ref<Texture> texture =
@@ -537,7 +537,7 @@
}
// Internally managed, but imported from external handle
- MaybeError Texture::InitializeFromExternal(const ExternalImageDescriptor* descriptor,
+ MaybeError Texture::InitializeFromExternal(const ExternalImageDescriptorVk* descriptor,
external_memory::Service* externalMemoryService) {
VkFormat format = VulkanImageFormat(ToBackend(GetDevice()), GetFormat().format);
VkImageUsageFlags usage = VulkanImageUsage(GetUsage(), GetFormat());
@@ -547,6 +547,9 @@
mExternalState = ExternalState::PendingAcquire;
+ mPendingAcquireOldLayout = descriptor->releasedOldLayout;
+ mPendingAcquireNewLayout = descriptor->releasedNewLayout;
+
VkImageCreateInfo baseCreateInfo = {};
FillVulkanCreateInfoSizesAndType(*this, &baseCreateInfo);
@@ -571,7 +574,7 @@
mHandle = nativeImage;
}
- MaybeError Texture::BindExternalMemory(const ExternalImageDescriptor* descriptor,
+ MaybeError Texture::BindExternalMemory(const ExternalImageDescriptorVk* descriptor,
VkSemaphore signalSemaphore,
VkDeviceMemory externalMemoryAllocation,
std::vector<VkSemaphore> waitSemaphores) {
@@ -580,8 +583,8 @@
device->fn.BindImageMemory(device->GetVkDevice(), mHandle, externalMemoryAllocation, 0),
"BindImageMemory (external)"));
- // Don't clear imported texture if already cleared
- if (descriptor->isCleared) {
+ // Don't clear imported texture if already initialized
+ if (descriptor->isInitialized) {
SetIsSubresourceContentInitialized(true, GetAllSubresources());
}
@@ -592,7 +595,10 @@
return {};
}
- MaybeError Texture::SignalAndDestroy(VkSemaphore* outSignalSemaphore) {
+ MaybeError Texture::ExportExternalTexture(VkImageLayout desiredLayout,
+ VkSemaphore* signalSemaphore,
+ VkImageLayout* releasedOldLayout,
+ VkImageLayout* releasedNewLayout) {
Device* device = ToBackend(GetDevice());
if (mExternalState == ExternalState::Released) {
@@ -605,17 +611,60 @@
}
ASSERT(mSignalSemaphore != VK_NULL_HANDLE);
+ ASSERT(GetNumMipLevels() == 1 && GetArrayLayers() == 1);
// Release the texture
- mExternalState = ExternalState::PendingRelease;
- TransitionFullUsage(device->GetPendingRecordingContext(), wgpu::TextureUsage::None);
+ mExternalState = ExternalState::Released;
+
+ wgpu::TextureUsage usage = mSubresourceLastUsages[0];
+
+ VkImageMemoryBarrier barrier;
+ barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+ barrier.pNext = nullptr;
+ barrier.image = GetHandle();
+ barrier.subresourceRange.aspectMask = VulkanAspectMask(GetFormat().aspects);
+ barrier.subresourceRange.baseMipLevel = 0;
+ barrier.subresourceRange.levelCount = 1;
+ barrier.subresourceRange.baseArrayLayer = 0;
+ barrier.subresourceRange.layerCount = 1;
+
+ barrier.srcAccessMask = VulkanAccessFlags(usage, GetFormat());
+ barrier.dstAccessMask = 0; // The barrier must be paired with another barrier that will
+ // specify the dst access mask on the importing queue.
+
+ barrier.oldLayout = VulkanImageLayout(usage, GetFormat());
+ if (desiredLayout == VK_IMAGE_LAYOUT_UNDEFINED) {
+ // VK_IMAGE_LAYOUT_UNDEFINED is invalid here. We use it as a
+ // special value to indicate no layout transition should be done.
+ barrier.newLayout = barrier.oldLayout;
+ } else {
+ barrier.newLayout = desiredLayout;
+ }
+
+ barrier.srcQueueFamilyIndex = device->GetGraphicsQueueFamily();
+ barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL_KHR;
+
+ VkPipelineStageFlags srcStages = VulkanPipelineStage(usage, GetFormat());
+ VkPipelineStageFlags dstStages =
+ VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; // We don't know when the importing queue will need
+ // the texture, so pass
+ // VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT to ensure
+ // the barrier happens-before any usage in the
+ // importing queue.
+
+ CommandRecordingContext* recordingContext = device->GetPendingRecordingContext();
+ device->fn.CmdPipelineBarrier(recordingContext->commandBuffer, srcStages, dstStages, 0, 0,
+ nullptr, 0, nullptr, 1, &barrier);
// Queue submit to signal we are done with the texture
- device->GetPendingRecordingContext()->signalSemaphores.push_back(mSignalSemaphore);
+ recordingContext->signalSemaphores.push_back(mSignalSemaphore);
DAWN_TRY(device->SubmitPendingCommands());
- // Write out the signal semaphore
- *outSignalSemaphore = mSignalSemaphore;
+ // Write out the layouts and signal semaphore
+ *releasedOldLayout = barrier.oldLayout;
+ *releasedNewLayout = barrier.newLayout;
+ *signalSemaphore = mSignalSemaphore;
+
mSignalSemaphore = VK_NULL_HANDLE;
// Destroy the texture so it can't be used again
@@ -688,26 +737,58 @@
SubresourceRange::SingleMipAndLayer(0, 0, GetFormat().aspects)));
}
+ VkImageMemoryBarrier* barrier = &(*barriers)[transitionBarrierStart];
// Transfer texture from external queue to graphics queue
- (*barriers)[transitionBarrierStart].srcQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL_KHR;
- (*barriers)[transitionBarrierStart].dstQueueFamilyIndex =
- ToBackend(GetDevice())->GetGraphicsQueueFamily();
- // Don't override oldLayout to leave it as VK_IMAGE_LAYOUT_UNDEFINED
- // TODO(http://crbug.com/dawn/200)
- mExternalState = ExternalState::Acquired;
- } else if (mExternalState == ExternalState::PendingRelease) {
- if (barriers->size() == transitionBarrierStart) {
- barriers->push_back(BuildMemoryBarrier(
- GetFormat(), mHandle, wgpu::TextureUsage::None, wgpu::TextureUsage::None,
- SubresourceRange::SingleMipAndLayer(0, 0, GetFormat().aspects)));
+ barrier->srcQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL_KHR;
+ barrier->dstQueueFamilyIndex = ToBackend(GetDevice())->GetGraphicsQueueFamily();
+
+ // srcAccessMask means nothing when importing. Queue transfers require a barrier on
+ // both the importing and exporting queues. The exporting queue should have specified
+ // this.
+ barrier->srcAccessMask = 0;
+
+ // This should be the first barrier after import.
+ ASSERT(barrier->oldLayout == VK_IMAGE_LAYOUT_UNDEFINED);
+
+ // Save the desired layout. We may need to transition through an intermediate
+ // |mPendingAcquireLayout| first.
+ VkImageLayout desiredLayout = barrier->newLayout;
+
+ bool isInitialized = IsSubresourceContentInitialized(GetAllSubresources());
+
+ // We don't care about the pending old layout if the texture is uninitialized. The
+ // driver is free to discard it. Likewise, we don't care about the pending new layout if
+ // the texture is uninitialized. We can skip the layout transition.
+ if (!isInitialized) {
+ barrier->oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ barrier->newLayout = desiredLayout;
+ } else {
+ barrier->oldLayout = mPendingAcquireOldLayout;
+ barrier->newLayout = mPendingAcquireNewLayout;
}
- // Transfer texture from graphics queue to external queue
- (*barriers)[transitionBarrierStart].srcQueueFamilyIndex =
- ToBackend(GetDevice())->GetGraphicsQueueFamily();
- (*barriers)[transitionBarrierStart].dstQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL_KHR;
- (*barriers)[transitionBarrierStart].newLayout = VK_IMAGE_LAYOUT_GENERAL;
- mExternalState = ExternalState::Released;
+ // If these are unequal, we need an another barrier to transition the layout.
+ if (barrier->newLayout != desiredLayout) {
+ VkImageMemoryBarrier layoutBarrier;
+ layoutBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+ layoutBarrier.pNext = nullptr;
+ layoutBarrier.image = GetHandle();
+ layoutBarrier.subresourceRange = barrier->subresourceRange;
+
+ // Transition from the acquired new layout to the desired layout.
+ layoutBarrier.oldLayout = barrier->newLayout;
+ layoutBarrier.newLayout = desiredLayout;
+
+ // We already transitioned these.
+ layoutBarrier.srcAccessMask = 0;
+ layoutBarrier.dstAccessMask = 0;
+ layoutBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ layoutBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+
+ barriers->push_back(layoutBarrier);
+ }
+
+ mExternalState = ExternalState::Acquired;
}
mLastExternalState = mExternalState;
diff --git a/src/dawn_native/vulkan/TextureVk.h b/src/dawn_native/vulkan/TextureVk.h
index 6cf52f5..1eafb0e 100644
--- a/src/dawn_native/vulkan/TextureVk.h
+++ b/src/dawn_native/vulkan/TextureVk.h
@@ -49,7 +49,7 @@
// image must be bound via Texture::BindExternalMemory.
static ResultOrError<Texture*> CreateFromExternal(
Device* device,
- const ExternalImageDescriptor* descriptor,
+ const ExternalImageDescriptorVk* descriptor,
const TextureDescriptor* textureDescriptor,
external_memory::Service* externalMemoryService);
@@ -84,20 +84,24 @@
void EnsureSubresourceContentInitialized(CommandRecordingContext* recordingContext,
const SubresourceRange& range);
- MaybeError SignalAndDestroy(VkSemaphore* outSignalSemaphore);
// Binds externally allocated memory to the VkImage and on success, takes ownership of
// semaphores.
- MaybeError BindExternalMemory(const ExternalImageDescriptor* descriptor,
+ MaybeError BindExternalMemory(const ExternalImageDescriptorVk* descriptor,
VkSemaphore signalSemaphore,
VkDeviceMemory externalMemoryAllocation,
std::vector<VkSemaphore> waitSemaphores);
+ MaybeError ExportExternalTexture(VkImageLayout desiredLayout,
+ VkSemaphore* signalSemaphore,
+ VkImageLayout* releasedOldLayout,
+ VkImageLayout* releasedNewLayout);
+
private:
~Texture() override;
using TextureBase::TextureBase;
MaybeError InitializeAsInternalTexture();
- MaybeError InitializeFromExternal(const ExternalImageDescriptor* descriptor,
+ MaybeError InitializeFromExternal(const ExternalImageDescriptorVk* descriptor,
external_memory::Service* externalMemoryService);
void InitializeForSwapChain(VkImage nativeImage);
@@ -119,12 +123,14 @@
InternalOnly,
PendingAcquire,
Acquired,
- PendingRelease,
Released
};
ExternalState mExternalState = ExternalState::InternalOnly;
ExternalState mLastExternalState = ExternalState::InternalOnly;
+ VkImageLayout mPendingAcquireOldLayout;
+ VkImageLayout mPendingAcquireNewLayout;
+
VkSemaphore mSignalSemaphore = VK_NULL_HANDLE;
std::vector<VkSemaphore> mWaitRequirements;
diff --git a/src/dawn_native/vulkan/VulkanBackend.cpp b/src/dawn_native/vulkan/VulkanBackend.cpp
index c1458a0..faf17f8 100644
--- a/src/dawn_native/vulkan/VulkanBackend.cpp
+++ b/src/dawn_native/vulkan/VulkanBackend.cpp
@@ -59,51 +59,75 @@
return static_cast<WGPUTextureFormat>(impl->GetPreferredFormat());
}
-#ifdef DAWN_PLATFORM_LINUX
- ExternalImageDescriptorFD::ExternalImageDescriptorFD(ExternalImageDescriptorType descType)
- : ExternalImageDescriptor(descType) {
- }
-
+#if defined(DAWN_PLATFORM_LINUX)
ExternalImageDescriptorOpaqueFD::ExternalImageDescriptorOpaqueFD()
- : ExternalImageDescriptorFD(ExternalImageDescriptorType::OpaqueFD) {
+ : ExternalImageDescriptorFD(ExternalImageType::OpaqueFD) {
}
ExternalImageDescriptorDmaBuf::ExternalImageDescriptorDmaBuf()
- : ExternalImageDescriptorFD(ExternalImageDescriptorType::DmaBuf) {
+ : ExternalImageDescriptorFD(ExternalImageType::DmaBuf) {
+ }
+
+ ExternalImageExportInfoOpaqueFD::ExternalImageExportInfoOpaqueFD()
+ : ExternalImageExportInfoFD(ExternalImageType::OpaqueFD) {
+ }
+
+ ExternalImageExportInfoDmaBuf::ExternalImageExportInfoDmaBuf()
+ : ExternalImageExportInfoFD(ExternalImageType::DmaBuf) {
}
int ExportSignalSemaphoreOpaqueFD(WGPUDevice cDevice, WGPUTexture cTexture) {
+ // Doesn't actually matter if we use OpaqueFD or DmaBuf since these paths are the same right
+ // now. This function will be removed.
Device* device = reinterpret_cast<Device*>(cDevice);
- Texture* texture = reinterpret_cast<Texture*>(cTexture);
-
- if (!texture) {
+ device->EmitDeprecationWarning(
+ "ExportSignalSemaphoreOpaqueFD is deprecated. Please use ExportVulkanImage instead.");
+ ExternalImageExportInfoOpaqueFD info;
+ if (!ExportVulkanImage(cTexture, VK_IMAGE_LAYOUT_GENERAL, &info)) {
return -1;
}
-
- ExternalSemaphoreHandle outHandle;
- if (device->ConsumedError(device->SignalAndExportExternalTexture(texture, &outHandle))) {
- return -1;
- }
-
- return outHandle;
+ return info.semaphoreHandles[0];
}
+#endif // DAWN_PLATFORM_LINUX
- WGPUTexture WrapVulkanImage(WGPUDevice cDevice, const ExternalImageDescriptor* descriptor) {
- Device* device = reinterpret_cast<Device*>(cDevice);
-
+ WGPUTexture WrapVulkanImage(WGPUDevice cDevice, const ExternalImageDescriptorVk* descriptor) {
switch (descriptor->type) {
- case ExternalImageDescriptorType::OpaqueFD:
- case ExternalImageDescriptorType::DmaBuf: {
+#if defined(DAWN_PLATFORM_LINUX)
+ case ExternalImageType::OpaqueFD:
+ case ExternalImageType::DmaBuf: {
const ExternalImageDescriptorFD* fdDescriptor =
static_cast<const ExternalImageDescriptorFD*>(descriptor);
+ Device* device = reinterpret_cast<Device*>(cDevice);
TextureBase* texture = device->CreateTextureWrappingVulkanImage(
- descriptor, fdDescriptor->memoryFD, fdDescriptor->waitFDs);
+ fdDescriptor, fdDescriptor->memoryFD, fdDescriptor->waitFDs);
return reinterpret_cast<WGPUTexture>(texture);
}
+#endif // DAWN_PLATFORM_LINUX
default:
return nullptr;
}
}
-#endif
+
+ bool ExportVulkanImage(WGPUTexture cTexture,
+ VkImageLayout desiredLayout,
+ ExternalImageExportInfoVk* info) {
+ if (cTexture == nullptr) {
+ return false;
+ }
+ switch (info->type) {
+#if defined(DAWN_PLATFORM_LINUX)
+ case ExternalImageType::OpaqueFD:
+ case ExternalImageType::DmaBuf: {
+ Texture* texture = reinterpret_cast<Texture*>(cTexture);
+ Device* device = ToBackend(texture->GetDevice());
+ ExternalImageExportInfoFD* fdInfo = static_cast<ExternalImageExportInfoFD*>(info);
+ return device->SignalAndExportExternalTexture(texture, desiredLayout, fdInfo,
+ &fdInfo->semaphoreHandles);
+ }
+#endif // DAWN_PLATFORM_LINUX
+ default:
+ return false;
+ }
+ }
}} // namespace dawn_native::vulkan
diff --git a/src/dawn_native/vulkan/external_memory/MemoryServiceDmaBuf.cpp b/src/dawn_native/vulkan/external_memory/MemoryServiceDmaBuf.cpp
index 4129745..f173bab 100644
--- a/src/dawn_native/vulkan/external_memory/MemoryServiceDmaBuf.cpp
+++ b/src/dawn_native/vulkan/external_memory/MemoryServiceDmaBuf.cpp
@@ -83,7 +83,7 @@
if (!mSupported) {
return false;
}
- if (descriptor->type != ExternalImageDescriptorType::DmaBuf) {
+ if (descriptor->type != ExternalImageType::DmaBuf) {
return false;
}
const ExternalImageDescriptorDmaBuf* dmaBufDescriptor =
@@ -150,7 +150,7 @@
ResultOrError<MemoryImportParams> Service::GetMemoryImportParams(
const ExternalImageDescriptor* descriptor,
VkImage image) {
- if (descriptor->type != ExternalImageDescriptorType::DmaBuf) {
+ if (descriptor->type != ExternalImageType::DmaBuf) {
return DAWN_VALIDATION_ERROR("ExternalImageDescriptor is not a dma-buf descriptor");
}
const ExternalImageDescriptorDmaBuf* dmaBufDescriptor =
@@ -216,7 +216,7 @@
ResultOrError<VkImage> Service::CreateImage(const ExternalImageDescriptor* descriptor,
const VkImageCreateInfo& baseCreateInfo) {
- if (descriptor->type != ExternalImageDescriptorType::DmaBuf) {
+ if (descriptor->type != ExternalImageType::DmaBuf) {
return DAWN_VALIDATION_ERROR("ExternalImageDescriptor is not a dma-buf descriptor");
}
const ExternalImageDescriptorDmaBuf* dmaBufDescriptor =
diff --git a/src/dawn_native/vulkan/external_memory/MemoryServiceOpaqueFD.cpp b/src/dawn_native/vulkan/external_memory/MemoryServiceOpaqueFD.cpp
index d43a10f..ebdab5b 100644
--- a/src/dawn_native/vulkan/external_memory/MemoryServiceOpaqueFD.cpp
+++ b/src/dawn_native/vulkan/external_memory/MemoryServiceOpaqueFD.cpp
@@ -71,8 +71,7 @@
// TODO(http://crbug.com/dawn/206): Investigate dedicated only images
VkFlags memoryFlags =
externalFormatProperties.externalMemoryProperties.externalMemoryFeatures;
- return (memoryFlags & VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR) &&
- !(memoryFlags & VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR);
+ return (memoryFlags & VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR) != 0;
}
bool Service::SupportsCreateImage(const ExternalImageDescriptor* descriptor,
@@ -84,7 +83,7 @@
ResultOrError<MemoryImportParams> Service::GetMemoryImportParams(
const ExternalImageDescriptor* descriptor,
VkImage image) {
- if (descriptor->type != ExternalImageDescriptorType::OpaqueFD) {
+ if (descriptor->type != ExternalImageType::OpaqueFD) {
return DAWN_VALIDATION_ERROR("ExternalImageDescriptor is not an OpaqueFD descriptor");
}
const ExternalImageDescriptorOpaqueFD* opaqueFDDescriptor =
diff --git a/src/dawn_native/vulkan/external_memory/MemoryServiceZirconHandle.cpp b/src/dawn_native/vulkan/external_memory/MemoryServiceZirconHandle.cpp
index 85c4e4a..ae8744f 100644
--- a/src/dawn_native/vulkan/external_memory/MemoryServiceZirconHandle.cpp
+++ b/src/dawn_native/vulkan/external_memory/MemoryServiceZirconHandle.cpp
@@ -71,8 +71,7 @@
// TODO(http://crbug.com/dawn/206): Investigate dedicated only images
VkFlags memoryFlags =
externalFormatProperties.externalMemoryProperties.externalMemoryFeatures;
- return (memoryFlags & VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR) &&
- !(memoryFlags & VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR);
+ return (memoryFlags & VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR) != 0;
}
bool Service::SupportsCreateImage(const ExternalImageDescriptor* descriptor,
@@ -84,7 +83,7 @@
ResultOrError<MemoryImportParams> Service::GetMemoryImportParams(
const ExternalImageDescriptor* descriptor,
VkImage image) {
- if (descriptor->type != ExternalImageDescriptorType::OpaqueFD) {
+ if (descriptor->type != ExternalImageType::OpaqueFD) {
return DAWN_VALIDATION_ERROR("ExternalImageDescriptor is not an OpaqueFD descriptor");
}
const ExternalImageDescriptorOpaqueFD* opaqueFDDescriptor =
diff --git a/src/include/dawn_native/DawnNative.h b/src/include/dawn_native/DawnNative.h
index a57baeb..2199efa 100644
--- a/src/include/dawn_native/DawnNative.h
+++ b/src/include/dawn_native/DawnNative.h
@@ -200,8 +200,8 @@
DAWN_NATIVE_EXPORT uint64_t AcquireErrorInjectorCallCount();
DAWN_NATIVE_EXPORT void InjectErrorAt(uint64_t index);
- // The different types of ExternalImageDescriptors
- enum ExternalImageDescriptorType {
+ // The different types of external images
+ enum ExternalImageType {
OpaqueFD,
DmaBuf,
IOSurface,
@@ -211,13 +211,26 @@
// Common properties of external images
struct DAWN_NATIVE_EXPORT ExternalImageDescriptor {
public:
- const ExternalImageDescriptorType type;
+ const ExternalImageType type;
const WGPUTextureDescriptor* cTextureDescriptor; // Must match image creation params
- bool isCleared; // Sets whether the texture will be cleared before use
+ union {
+ bool isInitialized; // Whether the texture is initialized on import
+ bool isCleared; // DEPRECATED: Sets whether the texture will be cleared before use
+ };
protected:
- ExternalImageDescriptor(ExternalImageDescriptorType type);
+ ExternalImageDescriptor(ExternalImageType type);
};
+
+ struct DAWN_NATIVE_EXPORT ExternalImageExportInfo {
+ public:
+ const ExternalImageType type;
+ bool isInitialized; // Whether the texture is initialized after export
+
+ protected:
+ ExternalImageExportInfo(ExternalImageType type);
+ };
+
} // namespace dawn_native
#endif // DAWNNATIVE_DAWNNATIVE_H_
diff --git a/src/include/dawn_native/VulkanBackend.h b/src/include/dawn_native/VulkanBackend.h
index 4e5aee9..88cf03d 100644
--- a/src/include/dawn_native/VulkanBackend.h
+++ b/src/include/dawn_native/VulkanBackend.h
@@ -33,19 +33,49 @@
DAWN_NATIVE_EXPORT WGPUTextureFormat
GetNativeSwapChainPreferredFormat(const DawnSwapChainImplementation* swapChain);
-// Can't use DAWN_PLATFORM_LINUX since header included in both dawn and chrome
+ struct DAWN_NATIVE_EXPORT ExternalImageDescriptorVk : ExternalImageDescriptor {
+ public:
+ // The following members may be ignored if |ExternalImageDescriptor::isInitialized| is false
+ // since the import does not need to preserve texture contents.
+
+ // See https://www.khronos.org/registry/vulkan/specs/1.1/html/chap7.html. The acquire
+ // operation old/new layouts must match exactly the layouts in the release operation. So
+ // we may need to issue two barriers releasedOldLayout -> releasedNewLayout ->
+ // cTextureDescriptor.usage if the new layout is not compatible with the desired usage.
+ // The first barrier is the queue transfer, the second is the layout transition to our
+ // desired usage.
+ VkImageLayout releasedOldLayout = VK_IMAGE_LAYOUT_GENERAL;
+ VkImageLayout releasedNewLayout = VK_IMAGE_LAYOUT_GENERAL;
+
+ protected:
+ using ExternalImageDescriptor::ExternalImageDescriptor;
+ };
+
+ struct ExternalImageExportInfoVk : ExternalImageExportInfo {
+ public:
+ // See comments in |ExternalImageDescriptorVk|
+ // Contains the old/new layouts used in the queue release operation.
+ VkImageLayout releasedOldLayout;
+ VkImageLayout releasedNewLayout;
+
+ protected:
+ using ExternalImageExportInfo::ExternalImageExportInfo;
+ };
+
+// Can't use DAWN_PLATFORM_LINUX since header included in both Dawn and Chrome
#ifdef __linux__
+
// Common properties of external images represented by FDs. On successful import the file
// descriptor's ownership is transferred to the Dawn implementation and they shouldn't be
// used outside of Dawn again. TODO(enga): Also transfer ownership in the error case so the
// caller can assume the FD is always consumed.
- struct DAWN_NATIVE_EXPORT ExternalImageDescriptorFD : ExternalImageDescriptor {
+ struct DAWN_NATIVE_EXPORT ExternalImageDescriptorFD : ExternalImageDescriptorVk {
public:
int memoryFD; // A file descriptor from an export of the memory of the image
std::vector<int> waitFDs; // File descriptors of semaphores which will be waited on
protected:
- ExternalImageDescriptorFD(ExternalImageDescriptorType type);
+ using ExternalImageDescriptorVk::ExternalImageDescriptorVk;
};
// Descriptor for opaque file descriptor image import
@@ -64,8 +94,29 @@
uint64_t drmModifier; // DRM modifier of the buffer
};
+ // Info struct that is written to in |ExportVulkanImage|.
+ struct DAWN_NATIVE_EXPORT ExternalImageExportInfoFD : ExternalImageExportInfoVk {
+ public:
+ // Contains the exported semaphore handles.
+ std::vector<int> semaphoreHandles;
+
+ protected:
+ using ExternalImageExportInfoVk::ExternalImageExportInfoVk;
+ };
+
+ struct DAWN_NATIVE_EXPORT ExternalImageExportInfoOpaqueFD : ExternalImageExportInfoFD {
+ ExternalImageExportInfoOpaqueFD();
+ };
+
+ struct DAWN_NATIVE_EXPORT ExternalImageExportInfoDmaBuf : ExternalImageExportInfoFD {
+ ExternalImageExportInfoDmaBuf();
+ };
+
+#endif // __linux__
+
// Exports a signal semaphore from a wrapped texture. This must be called on wrapped
// textures before they are destroyed. On failure, returns -1
+ // TODO(enga): Remove after updating Chromium to use ExportVulkanImage.
DAWN_NATIVE_EXPORT int ExportSignalSemaphoreOpaqueFD(WGPUDevice cDevice,
WGPUTexture cTexture);
@@ -74,8 +125,15 @@
// primitives before the texture can be used.
// On failure, returns a nullptr.
DAWN_NATIVE_EXPORT WGPUTexture WrapVulkanImage(WGPUDevice cDevice,
- const ExternalImageDescriptor* descriptor);
-#endif // __linux__
+ const ExternalImageDescriptorVk* descriptor);
+
+ // Exports external memory from a Vulkan image. This must be called on wrapped textures
+ // before they are destroyed. It writes the semaphore to wait on and the old/new image
+ // layouts to |info|. Pass VK_IMAGE_LAYOUT_UNDEFINED as |desiredLayout| if you don't want to
+ // perform a layout transition.
+ DAWN_NATIVE_EXPORT bool ExportVulkanImage(WGPUTexture cTexture,
+ VkImageLayout desiredLayout,
+ ExternalImageExportInfoVk* info);
}} // namespace dawn_native::vulkan
diff --git a/src/tests/end2end/D3D12ResourceWrappingTests.cpp b/src/tests/end2end/D3D12ResourceWrappingTests.cpp
index b1187bc..a028319 100644
--- a/src/tests/end2end/D3D12ResourceWrappingTests.cpp
+++ b/src/tests/end2end/D3D12ResourceWrappingTests.cpp
@@ -300,7 +300,7 @@
const wgpu::Color& clearColor,
ID3D11Texture2D** d3d11TextureOut,
IDXGIKeyedMutex** dxgiKeyedMutexOut,
- bool isCleared = true) const {
+ bool isInitialized = true) const {
ComPtr<ID3D11Texture2D> d3d11Texture;
HRESULT hr = mD3d11Device->CreateTexture2D(d3dDescriptor, nullptr, &d3d11Texture);
ASSERT_EQ(hr, S_OK);
@@ -339,7 +339,7 @@
reinterpret_cast<const WGPUTextureDescriptor*>(dawnDescriptor);
externDesc.sharedHandle = sharedHandle;
externDesc.acquireMutexKey = 1;
- externDesc.isCleared = isCleared;
+ externDesc.isInitialized = isInitialized;
WGPUTexture dawnTexture = dawn_native::d3d12::WrapSharedHandle(device.Get(), &externDesc);
*dawnTextureOut = wgpu::Texture::Acquire(dawnTexture);
@@ -502,9 +502,9 @@
}
// 1. Create and clear a D3D11 texture with clearColor
-// 2. Import the texture with isCleared = false
+// 2. Import the texture with isInitialized = false
// 3. Verify clearColor is not visible in wrapped texture
-TEST_P(D3D12SharedHandleUsageTests, UnclearedTextureIsCleared) {
+TEST_P(D3D12SharedHandleUsageTests, UninitializedTextureIsCleared) {
DAWN_SKIP_TEST_IF(UsesWire());
const wgpu::Color clearColor{1.0f, 0.0f, 0.0f, 1.0f};
diff --git a/src/tests/end2end/IOSurfaceWrappingTests.cpp b/src/tests/end2end/IOSurfaceWrappingTests.cpp
index 9e44cb7..ad025f3 100644
--- a/src/tests/end2end/IOSurfaceWrappingTests.cpp
+++ b/src/tests/end2end/IOSurfaceWrappingTests.cpp
@@ -97,13 +97,13 @@
wgpu::Texture WrapIOSurface(const wgpu::TextureDescriptor* descriptor,
IOSurfaceRef ioSurface,
uint32_t plane,
- bool isCleared = true) {
+ bool isInitialized = true) {
dawn_native::metal::ExternalImageDescriptorIOSurface externDesc;
externDesc.cTextureDescriptor =
reinterpret_cast<const WGPUTextureDescriptor*>(descriptor);
externDesc.ioSurface = ioSurface;
externDesc.plane = plane;
- externDesc.isCleared = isCleared;
+ externDesc.isInitialized = isInitialized;
WGPUTexture texture = dawn_native::metal::WrapIOSurface(device.Get(), &externDesc);
return wgpu::Texture::Acquire(texture);
}
@@ -446,8 +446,8 @@
DoClearTest(ioSurface.get(), wgpu::TextureFormat::RGBA8Unorm, &data, sizeof(data));
}
-// Test that texture with color is cleared when isCleared = false
-TEST_P(IOSurfaceUsageTests, UnclearedTextureIsCleared) {
+// Test that texture with color is cleared when isInitialized = false
+TEST_P(IOSurfaceUsageTests, UninitializedTextureIsCleared) {
DAWN_SKIP_TEST_IF(UsesWire());
ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(1, 1, kCVPixelFormatType_32RGBA, 4);
@@ -465,7 +465,7 @@
textureDescriptor.mipLevelCount = 1;
textureDescriptor.usage = wgpu::TextureUsage::OutputAttachment | wgpu::TextureUsage::CopySrc;
- // wrap ioSurface and ensure color is not visible when isCleared set to false
+ // wrap ioSurface and ensure color is not visible when isInitialized set to false
wgpu::Texture ioSurfaceTexture = WrapIOSurface(&textureDescriptor, ioSurface.get(), 0, false);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), ioSurfaceTexture, 0, 0);
}
diff --git a/src/tests/white_box/VulkanImageWrappingTestsDmaBuf.cpp b/src/tests/white_box/VulkanImageWrappingTestsDmaBuf.cpp
index f52b365..8f6dae6 100644
--- a/src/tests/white_box/VulkanImageWrappingTestsDmaBuf.cpp
+++ b/src/tests/white_box/VulkanImageWrappingTestsDmaBuf.cpp
@@ -104,16 +104,34 @@
uint32_t stride,
uint64_t drmModifier,
std::vector<int> waitFDs,
- bool isCleared = true,
+ bool isInitialized = true,
+ bool expectValid = true) {
+ dawn_native::vulkan::ExternalImageDescriptorDmaBuf descriptor;
+ return WrapVulkanImage(dawnDevice, textureDescriptor, memoryFd, stride, drmModifier,
+ waitFDs, descriptor.releasedOldLayout,
+ descriptor.releasedNewLayout, isInitialized, expectValid);
+ }
+
+ wgpu::Texture WrapVulkanImage(wgpu::Device dawnDevice,
+ const wgpu::TextureDescriptor* textureDescriptor,
+ int memoryFd,
+ uint32_t stride,
+ uint64_t drmModifier,
+ std::vector<int> waitFDs,
+ VkImageLayout releasedOldLayout,
+ VkImageLayout releasedNewLayout,
+ bool isInitialized = true,
bool expectValid = true) {
dawn_native::vulkan::ExternalImageDescriptorDmaBuf descriptor;
descriptor.cTextureDescriptor =
reinterpret_cast<const WGPUTextureDescriptor*>(textureDescriptor);
- descriptor.isCleared = isCleared;
+ descriptor.isInitialized = isInitialized;
descriptor.stride = stride;
descriptor.drmModifier = drmModifier;
descriptor.memoryFD = memoryFd;
descriptor.waitFDs = waitFDs;
+ descriptor.releasedOldLayout = releasedOldLayout;
+ descriptor.releasedNewLayout = releasedNewLayout;
WGPUTexture texture =
dawn_native::vulkan::WrapVulkanImage(dawnDevice.Get(), &descriptor);
@@ -131,11 +149,13 @@
// Exports the signal from a wrapped texture and ignores it
// We have to export the signal before destroying the wrapped texture else it's an
// assertion failure
- void IgnoreSignalSemaphore(wgpu::Device dawnDevice, wgpu::Texture wrappedTexture) {
- int fd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(dawnDevice.Get(),
- wrappedTexture.Get());
- ASSERT_NE(fd, -1);
- close(fd);
+ void IgnoreSignalSemaphore(wgpu::Texture wrappedTexture) {
+ dawn_native::vulkan::ExternalImageExportInfoDmaBuf exportInfo;
+ dawn_native::vulkan::ExportVulkanImage(wrappedTexture.Get(), VK_IMAGE_LAYOUT_GENERAL, &exportInfo));
+ for (int handle : info.semaphoreHandles) {
+ ASSERT_NE(handle, -1);
+ close(handle);
+ }
}
protected:
@@ -157,7 +177,7 @@
wgpu::Texture texture = WrapVulkanImage(device, &defaultDescriptor, defaultFd,
defaultStride, defaultModifier, {}, true, true);
EXPECT_NE(texture.Get(), nullptr);
- IgnoreSignalSemaphore(device, texture);
+ IgnoreSignalSemaphore(texture);
}
// Test an error occurs if the texture descriptor is missing
@@ -230,10 +250,12 @@
wgpu::Texture texture = WrapVulkanImage(device, &defaultDescriptor, defaultFd,
defaultStride, defaultModifier, {}, true, true);
ASSERT_NE(texture.Get(), nullptr);
- IgnoreSignalSemaphore(device, texture);
- ASSERT_DEVICE_ERROR(int fd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(
- device.Get(), texture.Get()));
- ASSERT_EQ(fd, -1);
+ IgnoreSignalSemaphore(texture);
+
+ dawn_native::vulkan::ExternalImageExportInfoDmaBuf exportInfo;
+ ASSERT_DEVICE_ERROR(bool success = dawn_native::vulkan::ExportVulkanImage(
+ texture.Get(), VK_IMAGE_LAYOUT_GENERAL, &exportInfo));
+ ASSERT_FALSE(success);
}
// Test an error occurs if we try to export the signal semaphore from a normal texture
@@ -242,9 +264,11 @@
wgpu::Texture texture = device.CreateTexture(&defaultDescriptor);
ASSERT_NE(texture.Get(), nullptr);
- ASSERT_DEVICE_ERROR(int fd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(
- device.Get(), texture.Get()));
- ASSERT_EQ(fd, -1);
+
+ dawn_native::vulkan::ExternalImageExportInfoDmaBuf exportInfo;
+ ASSERT_DEVICE_ERROR(bool success = dawn_native::vulkan::ExportVulkanImage(
+ texture.Get(), VK_IMAGE_LAYOUT_GENERAL, &exportInfo));
+ ASSERT_FALSE(success);
}
// Test an error occurs if we try to export the signal semaphore from a destroyed texture
@@ -254,9 +278,11 @@
wgpu::Texture texture = device.CreateTexture(&defaultDescriptor);
ASSERT_NE(texture.Get(), nullptr);
texture.Destroy();
- ASSERT_DEVICE_ERROR(int fd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(
- device.Get(), texture.Get()));
- ASSERT_EQ(fd, -1);
+
+ dawn_native::vulkan::ExternalImageExportInfoDmaBuf exportInfo;
+ ASSERT_DEVICE_ERROR(bool success = dawn_native::vulkan::ExportVulkanImage(
+ texture.Get(), VK_IMAGE_LAYOUT_GENERAL, &exportInfo));
+ ASSERT_FALSE(success);
}
// Fixture to test using external memory textures through different usages.
@@ -330,84 +356,56 @@
// Verify clear color is visible in |device|
TEST_P(VulkanImageWrappingUsageTests, ClearImageAcrossDevices) {
// Import the image on |secondDevice|
- wgpu::Texture wrappedTexture = WrapVulkanImage(secondDevice, &defaultDescriptor, defaultFd,
- defaultStride, defaultModifier, {});
+ wgpu::Texture wrappedTexture = WrapVulkanImage(
+ secondDevice, &defaultDescriptor, defaultFd, defaultStride, defaultModifier, {},
+ VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
// Clear |wrappedTexture| on |secondDevice|
ClearImage(secondDevice, wrappedTexture, {1 / 255.0f, 2 / 255.0f, 3 / 255.0f, 4 / 255.0f});
- int signalFd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(secondDevice.Get(),
- wrappedTexture.Get());
+ dawn_native::vulkan::ExternalImageExportInfoDmaBuf exportInfo;
+ dawn_native::vulkan::ExportVulkanImage(wrappedTexture.Get(),
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, &exportInfo);
// Import the image to |device|, making sure we wait on signalFd
int nextFd = gbm_bo_get_fd(defaultGbmBo);
- wgpu::Texture nextWrappedTexture = WrapVulkanImage(
- device, &defaultDescriptor, nextFd, defaultStride, defaultModifier, {signalFd});
+ wgpu::Texture nextWrappedTexture =
+ WrapVulkanImage(device, &defaultDescriptor, nextFd, defaultStride, defaultModifier,
+ exportInfo.semaphoreHandles, exportInfo.releasedOldLayout,
+ exportInfo.releasedNewLayout);
// Verify |device| sees the changes from |secondDevice|
EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 2, 3, 4), nextWrappedTexture, 0, 0);
- IgnoreSignalSemaphore(device, nextWrappedTexture);
- }
-
- // Import texture to |device| and |secondDevice|
- // Clear image in |secondDevice|
- // Verify clear color is visible in |device|
- // Verify the very first import into |device| also sees the change, since it should
- // alias the same memory
- TEST_P(VulkanImageWrappingUsageTests, ClearImageAcrossDevicesAliased) {
- // Import the image on |device|
- wgpu::Texture wrappedTextureAlias = WrapVulkanImage(device, &defaultDescriptor, defaultFd,
- defaultStride, defaultModifier, {});
-
- // Import the image on |secondDevice|
- int nextFd = gbm_bo_get_fd(defaultGbmBo);
- wgpu::Texture wrappedTexture = WrapVulkanImage(secondDevice, &defaultDescriptor, nextFd,
- defaultStride, defaultModifier, {});
-
- // Clear |wrappedTexture| on |secondDevice|
- ClearImage(secondDevice, wrappedTexture, {1 / 255.0f, 2 / 255.0f, 3 / 255.0f, 4 / 255.0f});
-
- int signalFd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(secondDevice.Get(),
- wrappedTexture.Get());
-
- // Import the image to |device|, making sure we wait on signalFd
- nextFd = gbm_bo_get_fd(defaultGbmBo);
- wgpu::Texture nextWrappedTexture = WrapVulkanImage(
- device, &defaultDescriptor, nextFd, defaultStride, defaultModifier, {signalFd});
-
- // Verify |device| sees the changes from |secondDevice| (waits)
- EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 2, 3, 4), nextWrappedTexture, 0, 0);
-
- // Verify aliased texture sees changes from |secondDevice| (without waiting!)
- EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 2, 3, 4), wrappedTextureAlias, 0, 0);
-
- IgnoreSignalSemaphore(device, nextWrappedTexture);
- IgnoreSignalSemaphore(device, wrappedTextureAlias);
+ IgnoreSignalSemaphore(nextWrappedTexture);
}
// Clear an image in |secondDevice|
// Verify clear color is not visible in |device| if we import the texture as not cleared
- TEST_P(VulkanImageWrappingUsageTests, UnclearedTextureIsCleared) {
+ TEST_P(VulkanImageWrappingUsageTests, UninitializedTextureIsCleared) {
// Import the image on |secondDevice|
- wgpu::Texture wrappedTexture = WrapVulkanImage(secondDevice, &defaultDescriptor, defaultFd,
- defaultStride, defaultModifier, {});
+ wgpu::Texture wrappedTexture = WrapVulkanImage(
+ secondDevice, &defaultDescriptor, defaultFd, defaultStride, defaultModifier, {},
+ VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
// Clear |wrappedTexture| on |secondDevice|
ClearImage(secondDevice, wrappedTexture, {1 / 255.0f, 2 / 255.0f, 3 / 255.0f, 4 / 255.0f});
- int signalFd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(secondDevice.Get(),
- wrappedTexture.Get());
+ dawn_native::vulkan::ExternalImageExportInfoDmaBuf exportInfo;
+ dawn_native::vulkan::ExportVulkanImage(wrappedTexture.Get(),
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, &exportInfo);
// Import the image to |device|, making sure we wait on signalFd
int nextFd = gbm_bo_get_fd(defaultGbmBo);
- wgpu::Texture nextWrappedTexture = WrapVulkanImage(
- device, &defaultDescriptor, nextFd, defaultStride, defaultModifier, {signalFd}, false);
+ wgpu::Texture nextWrappedTexture =
+ WrapVulkanImage(device, &defaultDescriptor, nextFd, defaultStride, defaultModifier,
+ exportInfo.semaphoreHandles, exportInfo.releasedOldLayout,
+ exportInfo.releasedNewLayout, false);
// Verify |device| doesn't see the changes from |secondDevice|
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), nextWrappedTexture, 0, 0);
- IgnoreSignalSemaphore(device, nextWrappedTexture);
+ IgnoreSignalSemaphore(nextWrappedTexture);
}
// Import a texture into |secondDevice|
@@ -416,19 +414,23 @@
// Verify the clear color from |secondDevice| is visible in |copyDstTexture|
TEST_P(VulkanImageWrappingUsageTests, CopyTextureToTextureSrcSync) {
// Import the image on |secondDevice|
- wgpu::Texture wrappedTexture = WrapVulkanImage(secondDevice, &defaultDescriptor, defaultFd,
- defaultStride, defaultModifier, {});
+ wgpu::Texture wrappedTexture = WrapVulkanImage(
+ secondDevice, &defaultDescriptor, defaultFd, defaultStride, defaultModifier, {},
+ VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
// Clear |wrappedTexture| on |secondDevice|
ClearImage(secondDevice, wrappedTexture, {1 / 255.0f, 2 / 255.0f, 3 / 255.0f, 4 / 255.0f});
- int signalFd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(secondDevice.Get(),
- wrappedTexture.Get());
+ dawn_native::vulkan::ExternalImageExportInfoDmaBuf exportInfo;
+ dawn_native::vulkan::ExportVulkanImage(wrappedTexture.Get(),
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, &exportInfo);
// Import the image to |device|, making sure we wait on |signalFd|
int nextFd = gbm_bo_get_fd(defaultGbmBo);
- wgpu::Texture deviceWrappedTexture = WrapVulkanImage(
- device, &defaultDescriptor, nextFd, defaultStride, defaultModifier, {signalFd});
+ wgpu::Texture deviceWrappedTexture =
+ WrapVulkanImage(device, &defaultDescriptor, nextFd, defaultStride, defaultModifier,
+ exportInfo.semaphoreHandles, exportInfo.releasedOldLayout,
+ exportInfo.releasedNewLayout);
// Create a second texture on |device|
wgpu::Texture copyDstTexture = device.CreateTexture(&defaultDescriptor);
@@ -439,7 +441,7 @@
// Verify |copyDstTexture| sees changes from |secondDevice|
EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 2, 3, 4), copyDstTexture, 0, 0);
- IgnoreSignalSemaphore(device, deviceWrappedTexture);
+ IgnoreSignalSemaphore(deviceWrappedTexture);
}
// Import a texture into |device|
@@ -453,19 +455,23 @@
// into the texture first, then |device| writes color A
TEST_P(VulkanImageWrappingUsageTests, CopyTextureToTextureDstSync) {
// Import the image on |device|
- wgpu::Texture wrappedTexture = WrapVulkanImage(device, &defaultDescriptor, defaultFd,
- defaultStride, defaultModifier, {});
+ wgpu::Texture wrappedTexture = WrapVulkanImage(
+ device, &defaultDescriptor, defaultFd, defaultStride, defaultModifier, {},
+ VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
// Clear |wrappedTexture| on |device|
ClearImage(device, wrappedTexture, {5 / 255.0f, 6 / 255.0f, 7 / 255.0f, 8 / 255.0f});
- int signalFd =
- dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(device.Get(), wrappedTexture.Get());
+ dawn_native::vulkan::ExternalImageExportInfoDmaBuf exportInfo;
+ dawn_native::vulkan::ExportVulkanImage(wrappedTexture.Get(),
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &exportInfo);
// Import the image to |secondDevice|, making sure we wait on |signalFd|
int nextFd = gbm_bo_get_fd(defaultGbmBo);
- wgpu::Texture secondDeviceWrappedTexture = WrapVulkanImage(
- secondDevice, &defaultDescriptor, nextFd, defaultStride, defaultModifier, {signalFd});
+ wgpu::Texture secondDeviceWrappedTexture =
+ WrapVulkanImage(secondDevice, &defaultDescriptor, nextFd, defaultStride,
+ defaultModifier, exportInfo.semaphoreHandles,
+ exportInfo.releasedOldLayout, exportInfo.releasedNewLayout);
// Create a texture with color B on |secondDevice|
wgpu::Texture copySrcTexture = secondDevice.CreateTexture(&defaultDescriptor);
@@ -477,17 +483,21 @@
secondDeviceWrappedTexture);
// Re-import back into |device|, waiting on |secondDevice|'s signal
- signalFd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(
- secondDevice.Get(), secondDeviceWrappedTexture.Get());
+ dawn_native::vulkan::ExternalImageExportInfoDmaBuf secondExportInfo;
+ dawn_native::vulkan::ExportVulkanImage(secondDeviceWrappedTexture.Get(),
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ &secondExportInfo);
nextFd = gbm_bo_get_fd(defaultGbmBo);
- wgpu::Texture nextWrappedTexture = WrapVulkanImage(
- device, &defaultDescriptor, nextFd, defaultStride, defaultModifier, {signalFd});
+ wgpu::Texture nextWrappedTexture =
+ WrapVulkanImage(device, &defaultDescriptor, nextFd, defaultStride, defaultModifier,
+ secondExportInfo.semaphoreHandles, secondExportInfo.releasedOldLayout,
+ secondExportInfo.releasedNewLayout);
// Verify |nextWrappedTexture| contains the color from our copy
EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 2, 3, 4), nextWrappedTexture, 0, 0);
- IgnoreSignalSemaphore(device, nextWrappedTexture);
+ IgnoreSignalSemaphore(nextWrappedTexture);
}
// Import a texture from |secondDevice|
@@ -496,19 +506,23 @@
// Verify the clear color from |secondDevice| is visible in |copyDstBuffer|
TEST_P(VulkanImageWrappingUsageTests, CopyTextureToBufferSrcSync) {
// Import the image on |secondDevice|
- wgpu::Texture wrappedTexture = WrapVulkanImage(secondDevice, &defaultDescriptor, defaultFd,
- defaultStride, defaultModifier, {});
+ wgpu::Texture wrappedTexture = WrapVulkanImage(
+ secondDevice, &defaultDescriptor, defaultFd, defaultStride, defaultModifier, {},
+ VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
// Clear |wrappedTexture| on |secondDevice|
ClearImage(secondDevice, wrappedTexture, {1 / 255.0f, 2 / 255.0f, 3 / 255.0f, 4 / 255.0f});
- int signalFd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(secondDevice.Get(),
- wrappedTexture.Get());
+ dawn_native::vulkan::ExternalImageExportInfoDmaBuf exportInfo;
+ dawn_native::vulkan::ExportVulkanImage(wrappedTexture.Get(),
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, &exportInfo);
// Import the image to |device|, making sure we wait on |signalFd|
int nextFd = gbm_bo_get_fd(defaultGbmBo);
- wgpu::Texture deviceWrappedTexture = WrapVulkanImage(
- device, &defaultDescriptor, nextFd, defaultStride, defaultModifier, {signalFd});
+ wgpu::Texture deviceWrappedTexture =
+ WrapVulkanImage(device, &defaultDescriptor, nextFd, defaultStride, defaultModifier,
+ exportInfo.semaphoreHandles, exportInfo.releasedOldLayout,
+ exportInfo.releasedNewLayout);
// Create a destination buffer on |device|
wgpu::BufferDescriptor bufferDesc;
@@ -532,7 +546,7 @@
uint32_t expected = 1;
EXPECT_BUFFER_U32_EQ(expected, copyDstBuffer, 0);
- IgnoreSignalSemaphore(device, deviceWrappedTexture);
+ IgnoreSignalSemaphore(deviceWrappedTexture);
}
// Import a texture into |device|
@@ -545,19 +559,23 @@
// into the texture first, then |device| writes color A
TEST_P(VulkanImageWrappingUsageTests, CopyBufferToTextureDstSync) {
// Import the image on |device|
- wgpu::Texture wrappedTexture = WrapVulkanImage(device, &defaultDescriptor, defaultFd,
- defaultStride, defaultModifier, {});
+ wgpu::Texture wrappedTexture = WrapVulkanImage(
+ device, &defaultDescriptor, defaultFd, defaultStride, defaultModifier, {},
+ VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
// Clear |wrappedTexture| on |device|
ClearImage(device, wrappedTexture, {5 / 255.0f, 6 / 255.0f, 7 / 255.0f, 8 / 255.0f});
- int signalFd =
- dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(device.Get(), wrappedTexture.Get());
+ dawn_native::vulkan::ExternalImageExportInfoDmaBuf exportInfo;
+ dawn_native::vulkan::ExportVulkanImage(wrappedTexture.Get(),
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, &exportInfo);
// Import the image to |secondDevice|, making sure we wait on |signalFd|
int nextFd = gbm_bo_get_fd(defaultGbmBo);
- wgpu::Texture secondDeviceWrappedTexture = WrapVulkanImage(
- secondDevice, &defaultDescriptor, nextFd, defaultStride, defaultModifier, {signalFd});
+ wgpu::Texture secondDeviceWrappedTexture =
+ WrapVulkanImage(secondDevice, &defaultDescriptor, nextFd, defaultStride,
+ defaultModifier, exportInfo.semaphoreHandles,
+ exportInfo.releasedOldLayout, exportInfo.releasedNewLayout);
// Copy color B on |secondDevice|
wgpu::Queue secondDeviceQueue = secondDevice.GetDefaultQueue();
@@ -579,17 +597,21 @@
secondDeviceQueue.Submit(1, &commands);
// Re-import back into |device|, waiting on |secondDevice|'s signal
- signalFd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(
- secondDevice.Get(), secondDeviceWrappedTexture.Get());
+ dawn_native::vulkan::ExternalImageExportInfoDmaBuf secondExportInfo;
+ dawn_native::vulkan::ExportVulkanImage(secondDeviceWrappedTexture.Get(),
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ &secondExportInfo);
nextFd = gbm_bo_get_fd(defaultGbmBo);
- wgpu::Texture nextWrappedTexture = WrapVulkanImage(
- device, &defaultDescriptor, nextFd, defaultStride, defaultModifier, {signalFd});
+ wgpu::Texture nextWrappedTexture =
+ WrapVulkanImage(device, &defaultDescriptor, nextFd, defaultStride, defaultModifier,
+ secondExportInfo.semaphoreHandles, secondExportInfo.releasedOldLayout,
+ secondExportInfo.releasedNewLayout);
// Verify |nextWrappedTexture| contains the color from our copy
EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 2, 3, 4), nextWrappedTexture, 0, 0);
- IgnoreSignalSemaphore(device, nextWrappedTexture);
+ IgnoreSignalSemaphore(nextWrappedTexture);
}
// Import a texture from |secondDevice|
@@ -599,19 +621,23 @@
// Verify the clear color from |secondDevice| is visible in both copies
TEST_P(VulkanImageWrappingUsageTests, DoubleTextureUsage) {
// Import the image on |secondDevice|
- wgpu::Texture wrappedTexture = WrapVulkanImage(secondDevice, &defaultDescriptor, defaultFd,
- defaultStride, defaultModifier, {});
+ wgpu::Texture wrappedTexture = WrapVulkanImage(
+ secondDevice, &defaultDescriptor, defaultFd, defaultStride, defaultModifier, {},
+ VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
// Clear |wrappedTexture| on |secondDevice|
ClearImage(secondDevice, wrappedTexture, {1 / 255.0f, 2 / 255.0f, 3 / 255.0f, 4 / 255.0f});
- int signalFd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(secondDevice.Get(),
- wrappedTexture.Get());
+ dawn_native::vulkan::ExternalImageExportInfoDmaBuf exportInfo;
+ dawn_native::vulkan::ExportVulkanImage(wrappedTexture.Get(),
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, &exportInfo);
// Import the image to |device|, making sure we wait on |signalFd|
int nextFd = gbm_bo_get_fd(defaultGbmBo);
- wgpu::Texture deviceWrappedTexture = WrapVulkanImage(
- device, &defaultDescriptor, nextFd, defaultStride, defaultModifier, {signalFd});
+ wgpu::Texture deviceWrappedTexture =
+ WrapVulkanImage(device, &defaultDescriptor, nextFd, defaultStride, defaultModifier,
+ exportInfo.semaphoreHandles, exportInfo.releasedOldLayout,
+ exportInfo.releasedNewLayout);
// Create a second texture on |device|
wgpu::Texture copyDstTexture = device.CreateTexture(&defaultDescriptor);
@@ -631,7 +657,7 @@
// Verify |secondCopyDstTexture| sees changes from |secondDevice|
EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 2, 3, 4), secondCopyDstTexture, 0, 0);
- IgnoreSignalSemaphore(device, deviceWrappedTexture);
+ IgnoreSignalSemaphore(deviceWrappedTexture);
}
// Tex A on device 3 (external export)
@@ -676,10 +702,12 @@
// Import TexA, TexB on device 3
wgpu::Texture wrappedTexADevice3 =
- WrapVulkanImage(thirdDevice, &defaultDescriptor, fdA, strideA, modifierA, {});
+ WrapVulkanImage(thirdDevice, &defaultDescriptor, fdA, strideA, modifierA, {},
+ VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
wgpu::Texture wrappedTexBDevice3 =
- WrapVulkanImage(thirdDevice, &defaultDescriptor, fdB, strideB, modifierB, {});
+ WrapVulkanImage(thirdDevice, &defaultDescriptor, fdB, strideB, modifierB, {},
+ VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
// Clear TexA
ClearImage(thirdDevice, wrappedTexADevice3,
@@ -689,30 +717,37 @@
SimpleCopyTextureToTexture(thirdDevice, thirdDeviceQueue, wrappedTexADevice3,
wrappedTexBDevice3);
- int signalFdTexBDevice3 = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(
- thirdDevice.Get(), wrappedTexBDevice3.Get());
- IgnoreSignalSemaphore(thirdDevice, wrappedTexADevice3);
+ dawn_native::vulkan::ExternalImageExportInfoDmaBuf exportInfoTexBDevice3;
+ dawn_native::vulkan::ExportVulkanImage(
+ wrappedTexBDevice3.Get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, &exportInfoTexBDevice3);
+ IgnoreSignalSemaphore(wrappedTexADevice3);
// Import TexB, TexC on device 2
fdB = gbm_bo_get_fd(gbmBoB);
wgpu::Texture wrappedTexBDevice2 = WrapVulkanImage(
- secondDevice, &defaultDescriptor, fdB, strideB, modifierB, {signalFdTexBDevice3});
+ secondDevice, &defaultDescriptor, fdB, strideB, modifierB,
+ exportInfoTexBDevice3.semaphoreHandles, exportInfoTexBDevice3.releasedOldLayout,
+ exportInfoTexBDevice3.releasedNewLayout);
wgpu::Texture wrappedTexCDevice2 =
- WrapVulkanImage(secondDevice, &defaultDescriptor, fdC, strideC, modifierC, {});
+ WrapVulkanImage(secondDevice, &defaultDescriptor, fdC, strideC, modifierC, {},
+ VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
// Copy B->C on device 2
SimpleCopyTextureToTexture(secondDevice, secondDeviceQueue, wrappedTexBDevice2,
wrappedTexCDevice2);
- int signalFdTexCDevice2 = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(
- secondDevice.Get(), wrappedTexCDevice2.Get());
- IgnoreSignalSemaphore(secondDevice, wrappedTexBDevice2);
+ dawn_native::vulkan::ExternalImageExportInfoDmaBuf exportInfoTexCDevice2;
+ dawn_native::vulkan::ExportVulkanImage(
+ wrappedTexCDevice2.Get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, &exportInfoTexCDevice2);
+ IgnoreSignalSemaphore(wrappedTexBDevice2);
// Import TexC on device 1
fdC = gbm_bo_get_fd(gbmBoC);
- wgpu::Texture wrappedTexCDevice1 = WrapVulkanImage(device, &defaultDescriptor, fdC, strideC,
- modifierC, {signalFdTexCDevice2});
+ wgpu::Texture wrappedTexCDevice1 = WrapVulkanImage(
+ device, &defaultDescriptor, fdC, strideC, modifierC,
+ exportInfoTexCDevice2.semaphoreHandles, exportInfoTexCDevice2.releasedOldLayout,
+ exportInfoTexCDevice2.releasedNewLayout);
// Create TexD on device 1
wgpu::Texture texD = device.CreateTexture(&defaultDescriptor);
@@ -723,7 +758,7 @@
// Verify D matches clear color
EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 2, 3, 4), texD, 0, 0);
- IgnoreSignalSemaphore(device, wrappedTexCDevice1);
+ IgnoreSignalSemaphore(wrappedTexCDevice1);
}
// Tests a larger image is preserved when importing
@@ -756,7 +791,8 @@
// Import the image on |secondDevice|
wgpu::Texture wrappedTexture =
- WrapVulkanImage(secondDevice, &descriptor, fd, stride, modifier, {});
+ WrapVulkanImage(secondDevice, &descriptor, fd, stride, modifier, {},
+ VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
// Draw a non-trivial picture
uint32_t width = 640, height = 480, pixelSize = 4;
@@ -791,14 +827,15 @@
wgpu::CommandBuffer commands = encoder.Finish();
secondDeviceQueue.Submit(1, &commands);
}
-
- int signalFd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(secondDevice.Get(),
- wrappedTexture.Get());
+ dawn_native::vulkan::ExternalImageExportInfoDmaBuf exportInfo;
+ dawn_native::vulkan::ExportVulkanImage(wrappedTexture.Get(),
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, &exportInfo);
int nextFd = gbm_bo_get_fd(gbmBo);
// Import the image on |device|
- wgpu::Texture nextWrappedTexture =
- WrapVulkanImage(device, &descriptor, nextFd, stride, modifier, {signalFd});
+ wgpu::Texture nextWrappedTexture = WrapVulkanImage(
+ device, &descriptor, nextFd, stride, modifier, exportInfo.semaphoreHandles,
+ exportInfo.releasedOldLayout, exportInfo.releasedNewLayout);
// Copy the image into a buffer for comparison
wgpu::BufferDescriptor copyDesc;
@@ -823,7 +860,7 @@
EXPECT_BUFFER_U32_RANGE_EQ(reinterpret_cast<uint32_t*>(data.data()), copyDstBuffer, 0,
data.size() / 4);
- IgnoreSignalSemaphore(device, nextWrappedTexture);
+ IgnoreSignalSemaphore(nextWrappedTexture);
}
DAWN_INSTANTIATE_TEST(VulkanImageWrappingValidationTests, VulkanBackend());
diff --git a/src/tests/white_box/VulkanImageWrappingTestsOpaqueFD.cpp b/src/tests/white_box/VulkanImageWrappingTestsOpaqueFD.cpp
index cfd3c60..3259429 100644
--- a/src/tests/white_box/VulkanImageWrappingTestsOpaqueFD.cpp
+++ b/src/tests/white_box/VulkanImageWrappingTestsOpaqueFD.cpp
@@ -157,16 +157,34 @@
VkDeviceSize allocationSize,
uint32_t memoryTypeIndex,
std::vector<int> waitFDs,
- bool isCleared = true,
+ bool isInitialized = true,
+ bool expectValid = true) {
+ dawn_native::vulkan::ExternalImageDescriptorOpaqueFD descriptor;
+ return WrapVulkanImage(dawnDevice, textureDescriptor, memoryFd, allocationSize,
+ memoryTypeIndex, waitFDs, descriptor.releasedOldLayout,
+ descriptor.releasedNewLayout, isInitialized, expectValid);
+ }
+
+ wgpu::Texture WrapVulkanImage(wgpu::Device dawnDevice,
+ const wgpu::TextureDescriptor* textureDescriptor,
+ int memoryFd,
+ VkDeviceSize allocationSize,
+ uint32_t memoryTypeIndex,
+ std::vector<int> waitFDs,
+ VkImageLayout releasedOldLayout,
+ VkImageLayout releasedNewLayout,
+ bool isInitialized = true,
bool expectValid = true) {
dawn_native::vulkan::ExternalImageDescriptorOpaqueFD descriptor;
descriptor.cTextureDescriptor =
reinterpret_cast<const WGPUTextureDescriptor*>(textureDescriptor);
- descriptor.isCleared = isCleared;
+ descriptor.isInitialized = isInitialized;
descriptor.allocationSize = allocationSize;
descriptor.memoryTypeIndex = memoryTypeIndex;
descriptor.memoryFD = memoryFd;
descriptor.waitFDs = waitFDs;
+ descriptor.releasedOldLayout = releasedOldLayout;
+ descriptor.releasedNewLayout = releasedNewLayout;
WGPUTexture texture =
dawn_native::vulkan::WrapVulkanImage(dawnDevice.Get(), &descriptor);
@@ -184,11 +202,14 @@
// Exports the signal from a wrapped texture and ignores it
// We have to export the signal before destroying the wrapped texture else it's an
// assertion failure
- void IgnoreSignalSemaphore(wgpu::Device dawnDevice, wgpu::Texture wrappedTexture) {
- int fd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(dawnDevice.Get(),
- wrappedTexture.Get());
- ASSERT_NE(fd, -1);
- close(fd);
+ void IgnoreSignalSemaphore(wgpu::Texture wrappedTexture) {
+ dawn_native::vulkan::ExternalImageExportInfoOpaqueFD info;
+ dawn_native::vulkan::ExportVulkanImage(wrappedTexture.Get(),
+ VK_IMAGE_LAYOUT_GENERAL, &info);
+ for (int handle : info.semaphoreHandles) {
+ ASSERT_NE(handle, -1);
+ close(handle);
+ }
}
protected:
@@ -244,7 +265,7 @@
WrapVulkanImage(device, &defaultDescriptor, defaultFd, defaultAllocationSize,
defaultMemoryTypeIndex, {}, true, true);
EXPECT_NE(texture.Get(), nullptr);
- IgnoreSignalSemaphore(device, texture);
+ IgnoreSignalSemaphore(texture);
}
// Test an error occurs if the texture descriptor is missing
@@ -319,10 +340,12 @@
WrapVulkanImage(device, &defaultDescriptor, defaultFd, defaultAllocationSize,
defaultMemoryTypeIndex, {}, true, true);
ASSERT_NE(texture.Get(), nullptr);
- IgnoreSignalSemaphore(device, texture);
- ASSERT_DEVICE_ERROR(int fd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(
- device.Get(), texture.Get()));
- ASSERT_EQ(fd, -1);
+ IgnoreSignalSemaphore(texture);
+
+ dawn_native::vulkan::ExternalImageExportInfoOpaqueFD exportInfo;
+ ASSERT_DEVICE_ERROR(bool success = dawn_native::vulkan::ExportVulkanImage(
+ texture.Get(), VK_IMAGE_LAYOUT_GENERAL, &exportInfo));
+ ASSERT_FALSE(success);
}
// Test an error occurs if we try to export the signal semaphore from a normal texture
@@ -330,9 +353,11 @@
DAWN_SKIP_TEST_IF(UsesWire());
wgpu::Texture texture = device.CreateTexture(&defaultDescriptor);
ASSERT_NE(texture.Get(), nullptr);
- ASSERT_DEVICE_ERROR(int fd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(
- device.Get(), texture.Get()));
- ASSERT_EQ(fd, -1);
+
+ dawn_native::vulkan::ExternalImageExportInfoOpaqueFD exportInfo;
+ ASSERT_DEVICE_ERROR(bool success = dawn_native::vulkan::ExportVulkanImage(
+ texture.Get(), VK_IMAGE_LAYOUT_GENERAL, &exportInfo));
+ ASSERT_FALSE(success);
}
// Test an error occurs if we try to export the signal semaphore from a destroyed texture
@@ -341,9 +366,11 @@
wgpu::Texture texture = device.CreateTexture(&defaultDescriptor);
ASSERT_NE(texture.Get(), nullptr);
texture.Destroy();
- ASSERT_DEVICE_ERROR(int fd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(
- device.Get(), texture.Get()));
- ASSERT_EQ(fd, -1);
+
+ dawn_native::vulkan::ExternalImageExportInfoOpaqueFD exportInfo;
+ ASSERT_DEVICE_ERROR(bool success = dawn_native::vulkan::ExportVulkanImage(
+ texture.Get(), VK_IMAGE_LAYOUT_GENERAL, &exportInfo));
+ ASSERT_FALSE(success);
}
// Fixture to test using external memory textures through different usages.
@@ -456,97 +483,58 @@
// Import the image on |secondDevice|
wgpu::Texture wrappedTexture =
WrapVulkanImage(secondDevice, &defaultDescriptor, defaultFd, defaultAllocationSize,
- defaultMemoryTypeIndex, {});
+ defaultMemoryTypeIndex, {}, VK_IMAGE_LAYOUT_UNDEFINED,
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
// Clear |wrappedTexture| on |secondDevice|
ClearImage(secondDevice, wrappedTexture, {1 / 255.0f, 2 / 255.0f, 3 / 255.0f, 4 / 255.0f});
- int signalFd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(secondDevice.Get(),
- wrappedTexture.Get());
+ dawn_native::vulkan::ExternalImageExportInfoOpaqueFD exportInfo;
+ dawn_native::vulkan::ExportVulkanImage(wrappedTexture.Get(),
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, &exportInfo);
// Import the image to |device|, making sure we wait on signalFd
int memoryFd = GetMemoryFd(deviceVk, defaultAllocation);
wgpu::Texture nextWrappedTexture =
WrapVulkanImage(device, &defaultDescriptor, memoryFd, defaultAllocationSize,
- defaultMemoryTypeIndex, {signalFd});
+ defaultMemoryTypeIndex, exportInfo.semaphoreHandles,
+ exportInfo.releasedOldLayout, exportInfo.releasedNewLayout);
// Verify |device| sees the changes from |secondDevice|
EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 2, 3, 4), nextWrappedTexture, 0, 0);
- IgnoreSignalSemaphore(device, nextWrappedTexture);
- }
-
- // Import texture to |device| and |secondDevice|
- // Clear image in |secondDevice|
- // Verify clear color is visible in |device|
- // Verify the very first import into |device| also sees the change, since it should
- // alias the same memory
- TEST_P(VulkanImageWrappingUsageTests, ClearImageAcrossDevicesAliased) {
- DAWN_SKIP_TEST_IF(UsesWire());
-
- // WrapVulkanImage consumes the file descriptor so we can't import defaultFd twice.
- // Duplicate the file descriptor so we can import it twice.
- int defaultFdCopy = dup(defaultFd);
- ASSERT(defaultFdCopy != -1);
-
- // Import the image on |device
- wgpu::Texture wrappedTextureAlias =
- WrapVulkanImage(device, &defaultDescriptor, defaultFdCopy, defaultAllocationSize,
- defaultMemoryTypeIndex, {});
-
- // Import the image on |secondDevice|
- wgpu::Texture wrappedTexture =
- WrapVulkanImage(secondDevice, &defaultDescriptor, defaultFd, defaultAllocationSize,
- defaultMemoryTypeIndex, {});
-
- // Clear |wrappedTexture| on |secondDevice|
- ClearImage(secondDevice, wrappedTexture, {1 / 255.0f, 2 / 255.0f, 3 / 255.0f, 4 / 255.0f});
-
- int signalFd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(secondDevice.Get(),
- wrappedTexture.Get());
-
- // Import the image to |device|, making sure we wait on signalFd
- int memoryFd = GetMemoryFd(deviceVk, defaultAllocation);
- wgpu::Texture nextWrappedTexture =
- WrapVulkanImage(device, &defaultDescriptor, memoryFd, defaultAllocationSize,
- defaultMemoryTypeIndex, {signalFd});
-
- // Verify |device| sees the changes from |secondDevice| (waits)
- EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 2, 3, 4), nextWrappedTexture, 0, 0);
-
- // Verify aliased texture sees changes from |secondDevice| (without waiting!)
- EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 2, 3, 4), wrappedTextureAlias, 0, 0);
-
- IgnoreSignalSemaphore(device, nextWrappedTexture);
- IgnoreSignalSemaphore(device, wrappedTextureAlias);
+ IgnoreSignalSemaphore(nextWrappedTexture);
}
// Clear an image in |secondDevice|
// Verify clear color is not visible in |device| if we import the texture as not cleared
- TEST_P(VulkanImageWrappingUsageTests, UnclearedTextureIsCleared) {
+ TEST_P(VulkanImageWrappingUsageTests, UninitializedTextureIsCleared) {
DAWN_SKIP_TEST_IF(UsesWire());
// Import the image on |secondDevice|
wgpu::Texture wrappedTexture =
WrapVulkanImage(secondDevice, &defaultDescriptor, defaultFd, defaultAllocationSize,
- defaultMemoryTypeIndex, {});
+ defaultMemoryTypeIndex, {}, VK_IMAGE_LAYOUT_UNDEFINED,
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
// Clear |wrappedTexture| on |secondDevice|
ClearImage(secondDevice, wrappedTexture, {1 / 255.0f, 2 / 255.0f, 3 / 255.0f, 4 / 255.0f});
- int signalFd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(secondDevice.Get(),
- wrappedTexture.Get());
+ dawn_native::vulkan::ExternalImageExportInfoOpaqueFD exportInfo;
+ dawn_native::vulkan::ExportVulkanImage(wrappedTexture.Get(),
+ 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 the semaphore
int memoryFd = GetMemoryFd(deviceVk, defaultAllocation);
wgpu::Texture nextWrappedTexture =
WrapVulkanImage(device, &defaultDescriptor, memoryFd, defaultAllocationSize,
- defaultMemoryTypeIndex, {signalFd}, false);
+ defaultMemoryTypeIndex, exportInfo.semaphoreHandles,
+ exportInfo.releasedOldLayout, exportInfo.releasedNewLayout, false);
// Verify |device| doesn't see the changes from |secondDevice|
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), nextWrappedTexture, 0, 0);
- IgnoreSignalSemaphore(device, nextWrappedTexture);
+ IgnoreSignalSemaphore(nextWrappedTexture);
}
// Import a texture into |secondDevice|
@@ -558,19 +546,22 @@
// Import the image on |secondDevice|
wgpu::Texture wrappedTexture =
WrapVulkanImage(secondDevice, &defaultDescriptor, defaultFd, defaultAllocationSize,
- defaultMemoryTypeIndex, {});
+ defaultMemoryTypeIndex, {}, VK_IMAGE_LAYOUT_UNDEFINED,
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
// Clear |wrappedTexture| on |secondDevice|
ClearImage(secondDevice, wrappedTexture, {1 / 255.0f, 2 / 255.0f, 3 / 255.0f, 4 / 255.0f});
- int signalFd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(secondDevice.Get(),
- wrappedTexture.Get());
+ dawn_native::vulkan::ExternalImageExportInfoOpaqueFD exportInfo;
+ dawn_native::vulkan::ExportVulkanImage(wrappedTexture.Get(),
+ 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 the semaphore
int memoryFd = GetMemoryFd(deviceVk, defaultAllocation);
wgpu::Texture deviceWrappedTexture =
WrapVulkanImage(device, &defaultDescriptor, memoryFd, defaultAllocationSize,
- defaultMemoryTypeIndex, {signalFd});
+ defaultMemoryTypeIndex, exportInfo.semaphoreHandles,
+ exportInfo.releasedOldLayout, exportInfo.releasedNewLayout);
// Create a second texture on |device|
wgpu::Texture copyDstTexture = device.CreateTexture(&defaultDescriptor);
@@ -581,7 +572,7 @@
// Verify |copyDstTexture| sees changes from |secondDevice|
EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 2, 3, 4), copyDstTexture, 0, 0);
- IgnoreSignalSemaphore(device, deviceWrappedTexture);
+ IgnoreSignalSemaphore(deviceWrappedTexture);
}
// Import a texture into |device|
@@ -596,21 +587,23 @@
DAWN_SKIP_TEST_IF(UsesWire());
// Import the image on |device|
- wgpu::Texture wrappedTexture =
- WrapVulkanImage(device, &defaultDescriptor, defaultFd, defaultAllocationSize,
- defaultMemoryTypeIndex, {});
+ wgpu::Texture wrappedTexture = WrapVulkanImage(
+ device, &defaultDescriptor, defaultFd, defaultAllocationSize, defaultMemoryTypeIndex,
+ {}, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
// Clear |wrappedTexture| on |device|
ClearImage(device, wrappedTexture, {5 / 255.0f, 6 / 255.0f, 7 / 255.0f, 8 / 255.0f});
- int signalFd =
- dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(device.Get(), wrappedTexture.Get());
+ dawn_native::vulkan::ExternalImageExportInfoOpaqueFD exportInfo;
+ dawn_native::vulkan::ExportVulkanImage(wrappedTexture.Get(),
+ 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 the semaphore
int memoryFd = GetMemoryFd(deviceVk, defaultAllocation);
wgpu::Texture secondDeviceWrappedTexture =
WrapVulkanImage(secondDevice, &defaultDescriptor, memoryFd, defaultAllocationSize,
- defaultMemoryTypeIndex, {signalFd});
+ defaultMemoryTypeIndex, exportInfo.semaphoreHandles,
+ exportInfo.releasedOldLayout, exportInfo.releasedNewLayout);
// Create a texture with color B on |secondDevice|
wgpu::Texture copySrcTexture = secondDevice.CreateTexture(&defaultDescriptor);
@@ -622,18 +615,21 @@
secondDeviceWrappedTexture);
// Re-import back into |device|, waiting on |secondDevice|'s signal
- signalFd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(
- secondDevice.Get(), secondDeviceWrappedTexture.Get());
+ dawn_native::vulkan::ExternalImageExportInfoOpaqueFD secondExportInfo;
+ dawn_native::vulkan::ExportVulkanImage(secondDeviceWrappedTexture.Get(),
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ &secondExportInfo);
memoryFd = GetMemoryFd(deviceVk, defaultAllocation);
wgpu::Texture nextWrappedTexture =
WrapVulkanImage(device, &defaultDescriptor, memoryFd, defaultAllocationSize,
- defaultMemoryTypeIndex, {signalFd});
+ defaultMemoryTypeIndex, secondExportInfo.semaphoreHandles,
+ secondExportInfo.releasedOldLayout, secondExportInfo.releasedNewLayout);
// Verify |nextWrappedTexture| contains the color from our copy
EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 2, 3, 4), nextWrappedTexture, 0, 0);
- IgnoreSignalSemaphore(device, nextWrappedTexture);
+ IgnoreSignalSemaphore(nextWrappedTexture);
}
// Import a texture from |secondDevice|
@@ -645,19 +641,22 @@
// Import the image on |secondDevice|
wgpu::Texture wrappedTexture =
WrapVulkanImage(secondDevice, &defaultDescriptor, defaultFd, defaultAllocationSize,
- defaultMemoryTypeIndex, {});
+ defaultMemoryTypeIndex, {}, VK_IMAGE_LAYOUT_UNDEFINED,
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
// Clear |wrappedTexture| on |secondDevice|
ClearImage(secondDevice, wrappedTexture, {1 / 255.0f, 2 / 255.0f, 3 / 255.0f, 4 / 255.0f});
- int signalFd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(secondDevice.Get(),
- wrappedTexture.Get());
+ dawn_native::vulkan::ExternalImageExportInfoOpaqueFD exportInfo;
+ dawn_native::vulkan::ExportVulkanImage(wrappedTexture.Get(),
+ 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 the semaphore
int memoryFd = GetMemoryFd(deviceVk, defaultAllocation);
wgpu::Texture deviceWrappedTexture =
WrapVulkanImage(device, &defaultDescriptor, memoryFd, defaultAllocationSize,
- defaultMemoryTypeIndex, {signalFd});
+ defaultMemoryTypeIndex, exportInfo.semaphoreHandles,
+ exportInfo.releasedOldLayout, exportInfo.releasedNewLayout);
// Create a destination buffer on |device|
wgpu::BufferDescriptor bufferDesc;
@@ -681,7 +680,7 @@
uint32_t expected = 0x04030201;
EXPECT_BUFFER_U32_EQ(expected, copyDstBuffer, 0);
- IgnoreSignalSemaphore(device, deviceWrappedTexture);
+ IgnoreSignalSemaphore(deviceWrappedTexture);
}
// Import a texture into |device|
@@ -696,21 +695,23 @@
DAWN_SKIP_TEST_IF(UsesWire());
// Import the image on |device|
- wgpu::Texture wrappedTexture =
- WrapVulkanImage(device, &defaultDescriptor, defaultFd, defaultAllocationSize,
- defaultMemoryTypeIndex, {});
+ wgpu::Texture wrappedTexture = WrapVulkanImage(
+ device, &defaultDescriptor, defaultFd, defaultAllocationSize, defaultMemoryTypeIndex,
+ {}, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
// Clear |wrappedTexture| on |device|
ClearImage(device, wrappedTexture, {5 / 255.0f, 6 / 255.0f, 7 / 255.0f, 8 / 255.0f});
- int signalFd =
- dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(device.Get(), wrappedTexture.Get());
+ dawn_native::vulkan::ExternalImageExportInfoOpaqueFD exportInfo;
+ dawn_native::vulkan::ExportVulkanImage(wrappedTexture.Get(),
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, &exportInfo);
// Import the image to |secondDevice|, making sure we wait on |signalFd|
int memoryFd = GetMemoryFd(deviceVk, defaultAllocation);
wgpu::Texture secondDeviceWrappedTexture =
WrapVulkanImage(secondDevice, &defaultDescriptor, memoryFd, defaultAllocationSize,
- defaultMemoryTypeIndex, {signalFd});
+ defaultMemoryTypeIndex, exportInfo.semaphoreHandles,
+ exportInfo.releasedOldLayout, exportInfo.releasedNewLayout);
// Copy color B on |secondDevice|
wgpu::Queue secondDeviceQueue = secondDevice.GetDefaultQueue();
@@ -732,18 +733,21 @@
secondDeviceQueue.Submit(1, &commands);
// Re-import back into |device|, waiting on |secondDevice|'s signal
- signalFd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(
- secondDevice.Get(), secondDeviceWrappedTexture.Get());
+ dawn_native::vulkan::ExternalImageExportInfoOpaqueFD secondExportInfo;
+ dawn_native::vulkan::ExportVulkanImage(secondDeviceWrappedTexture.Get(),
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ &secondExportInfo);
memoryFd = GetMemoryFd(deviceVk, defaultAllocation);
wgpu::Texture nextWrappedTexture =
WrapVulkanImage(device, &defaultDescriptor, memoryFd, defaultAllocationSize,
- defaultMemoryTypeIndex, {signalFd});
+ defaultMemoryTypeIndex, secondExportInfo.semaphoreHandles,
+ secondExportInfo.releasedOldLayout, secondExportInfo.releasedNewLayout);
// Verify |nextWrappedTexture| contains the color from our copy
EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 2, 3, 4), nextWrappedTexture, 0, 0);
- IgnoreSignalSemaphore(device, nextWrappedTexture);
+ IgnoreSignalSemaphore(nextWrappedTexture);
}
// Import a texture from |secondDevice|
@@ -756,19 +760,22 @@
// Import the image on |secondDevice|
wgpu::Texture wrappedTexture =
WrapVulkanImage(secondDevice, &defaultDescriptor, defaultFd, defaultAllocationSize,
- defaultMemoryTypeIndex, {});
+ defaultMemoryTypeIndex, {}, VK_IMAGE_LAYOUT_UNDEFINED,
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
// Clear |wrappedTexture| on |secondDevice|
ClearImage(secondDevice, wrappedTexture, {1 / 255.0f, 2 / 255.0f, 3 / 255.0f, 4 / 255.0f});
- int signalFd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(secondDevice.Get(),
- wrappedTexture.Get());
+ dawn_native::vulkan::ExternalImageExportInfoOpaqueFD exportInfo;
+ dawn_native::vulkan::ExportVulkanImage(wrappedTexture.Get(),
+ 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 the semaphore
int memoryFd = GetMemoryFd(deviceVk, defaultAllocation);
wgpu::Texture deviceWrappedTexture =
WrapVulkanImage(device, &defaultDescriptor, memoryFd, defaultAllocationSize,
- defaultMemoryTypeIndex, {signalFd});
+ defaultMemoryTypeIndex, exportInfo.semaphoreHandles,
+ exportInfo.releasedOldLayout, exportInfo.releasedNewLayout);
// Create a second texture on |device|
wgpu::Texture copyDstTexture = device.CreateTexture(&defaultDescriptor);
@@ -788,7 +795,7 @@
// Verify |secondCopyDstTexture| sees changes from |secondDevice|
EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 2, 3, 4), secondCopyDstTexture, 0, 0);
- IgnoreSignalSemaphore(device, deviceWrappedTexture);
+ IgnoreSignalSemaphore(deviceWrappedTexture);
}
// Tex A on device 3 (external export)
@@ -844,10 +851,12 @@
// Import TexA, TexB on device 3
wgpu::Texture wrappedTexADevice3 = WrapVulkanImage(
- thirdDevice, &defaultDescriptor, memoryFdA, allocationSizeA, memoryTypeIndexA, {});
+ thirdDevice, &defaultDescriptor, memoryFdA, allocationSizeA, memoryTypeIndexA, {},
+ VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
wgpu::Texture wrappedTexBDevice3 = WrapVulkanImage(
- thirdDevice, &defaultDescriptor, memoryFdB, allocationSizeB, memoryTypeIndexB, {});
+ thirdDevice, &defaultDescriptor, memoryFdB, allocationSizeB, memoryTypeIndexB, {},
+ VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
// Clear TexA
ClearImage(thirdDevice, wrappedTexADevice3,
@@ -857,32 +866,39 @@
SimpleCopyTextureToTexture(thirdDevice, thirdDeviceQueue, wrappedTexADevice3,
wrappedTexBDevice3);
- int signalFdTexBDevice3 = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(
- thirdDevice.Get(), wrappedTexBDevice3.Get());
- IgnoreSignalSemaphore(thirdDevice, wrappedTexADevice3);
+ dawn_native::vulkan::ExternalImageExportInfoOpaqueFD exportInfoTexBDevice3;
+ dawn_native::vulkan::ExportVulkanImage(
+ wrappedTexBDevice3.Get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, &exportInfoTexBDevice3);
+
+ IgnoreSignalSemaphore(wrappedTexADevice3);
// Import TexB, TexC on device 2
memoryFdB = GetMemoryFd(secondDeviceVk, allocationB);
- wgpu::Texture wrappedTexBDevice2 =
- WrapVulkanImage(secondDevice, &defaultDescriptor, memoryFdB, allocationSizeB,
- memoryTypeIndexB, {signalFdTexBDevice3});
+ wgpu::Texture wrappedTexBDevice2 = WrapVulkanImage(
+ secondDevice, &defaultDescriptor, memoryFdB, allocationSizeB, memoryTypeIndexB,
+ exportInfoTexBDevice3.semaphoreHandles, exportInfoTexBDevice3.releasedOldLayout,
+ exportInfoTexBDevice3.releasedNewLayout);
wgpu::Texture wrappedTexCDevice2 = WrapVulkanImage(
- secondDevice, &defaultDescriptor, memoryFdC, allocationSizeC, memoryTypeIndexC, {});
+ secondDevice, &defaultDescriptor, memoryFdC, allocationSizeC, memoryTypeIndexC, {},
+ VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
// Copy B->C on device 2
SimpleCopyTextureToTexture(secondDevice, secondDeviceQueue, wrappedTexBDevice2,
wrappedTexCDevice2);
- int signalFdTexCDevice2 = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(
- secondDevice.Get(), wrappedTexCDevice2.Get());
- IgnoreSignalSemaphore(secondDevice, wrappedTexBDevice2);
+ dawn_native::vulkan::ExternalImageExportInfoOpaqueFD exportInfoTexCDevice2;
+ dawn_native::vulkan::ExportVulkanImage(
+ wrappedTexCDevice2.Get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, &exportInfoTexCDevice2);
+
+ IgnoreSignalSemaphore(wrappedTexBDevice2);
// Import TexC on device 1
memoryFdC = GetMemoryFd(deviceVk, allocationC);
- wgpu::Texture wrappedTexCDevice1 =
- WrapVulkanImage(device, &defaultDescriptor, memoryFdC, allocationSizeC,
- memoryTypeIndexC, {signalFdTexCDevice2});
+ wgpu::Texture wrappedTexCDevice1 = WrapVulkanImage(
+ device, &defaultDescriptor, memoryFdC, allocationSizeC, memoryTypeIndexC,
+ exportInfoTexCDevice2.semaphoreHandles, exportInfoTexCDevice2.releasedOldLayout,
+ exportInfoTexCDevice2.releasedNewLayout);
// Create TexD on device 1
wgpu::Texture texD = device.CreateTexture(&defaultDescriptor);
@@ -900,7 +916,7 @@
deviceVk->GetFencedDeleter()->DeleteWhenUnused(imageC);
deviceVk->GetFencedDeleter()->DeleteWhenUnused(allocationC);
- IgnoreSignalSemaphore(device, wrappedTexCDevice1);
+ IgnoreSignalSemaphore(wrappedTexCDevice1);
}
// Tests a larger image is preserved when importing
@@ -938,8 +954,9 @@
&allocationA, &allocationSizeA, &memoryTypeIndexA, &memoryFdA);
// Import the image on |secondDevice|
- wgpu::Texture wrappedTexture = WrapVulkanImage(secondDevice, &descriptor, memoryFdA,
- allocationSizeA, memoryTypeIndexA, {});
+ wgpu::Texture wrappedTexture =
+ WrapVulkanImage(secondDevice, &descriptor, memoryFdA, allocationSizeA, memoryTypeIndexA,
+ {}, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
// Draw a non-trivial picture
uint32_t width = 640, height = 480, pixelSize = 4;
@@ -975,13 +992,17 @@
secondDeviceQueue.Submit(1, &commands);
}
- int signalFd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(secondDevice.Get(),
- wrappedTexture.Get());
+ dawn_native::vulkan::ExternalImageExportInfoOpaqueFD exportInfo;
+ dawn_native::vulkan::ExportVulkanImage(wrappedTexture.Get(),
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, &exportInfo);
+
int memoryFd = GetMemoryFd(secondDeviceVk, allocationA);
// Import the image on |device|
- wgpu::Texture nextWrappedTexture = WrapVulkanImage(
- device, &descriptor, memoryFd, allocationSizeA, memoryTypeIndexA, {signalFd});
+ wgpu::Texture nextWrappedTexture =
+ WrapVulkanImage(device, &descriptor, memoryFd, allocationSizeA, memoryTypeIndexA,
+ exportInfo.semaphoreHandles, exportInfo.releasedOldLayout,
+ exportInfo.releasedNewLayout);
// Copy the image into a buffer for comparison
wgpu::BufferDescriptor copyDesc;
@@ -1006,7 +1027,7 @@
EXPECT_BUFFER_U32_RANGE_EQ(reinterpret_cast<uint32_t*>(data.data()), copyDstBuffer, 0,
data.size() / 4);
- IgnoreSignalSemaphore(device, nextWrappedTexture);
+ IgnoreSignalSemaphore(nextWrappedTexture);
secondDeviceVk->GetFencedDeleter()->DeleteWhenUnused(imageA);
secondDeviceVk->GetFencedDeleter()->DeleteWhenUnused(allocationA);
}