mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-06-24 07:23:35 +00:00
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>
This commit is contained in:
parent
670858da9b
commit
0b29732cd8
@ -195,8 +195,14 @@ namespace dawn_native {
|
|||||||
return GetProcMapNamesForTestingInternal();
|
return GetProcMapNamesForTestingInternal();
|
||||||
}
|
}
|
||||||
|
|
||||||
ExternalImageDescriptor::ExternalImageDescriptor(ExternalImageDescriptorType type)
|
// ExternalImageDescriptor
|
||||||
: type(type) {
|
|
||||||
|
ExternalImageDescriptor::ExternalImageDescriptor(ExternalImageType type) : type(type) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExternalImageExportInfo
|
||||||
|
|
||||||
|
ExternalImageExportInfo::ExternalImageExportInfo(ExternalImageType type) : type(type) {
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace dawn_native
|
} // namespace dawn_native
|
||||||
|
@ -48,7 +48,7 @@ namespace dawn_native { namespace d3d12 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ExternalImageDescriptorDXGISharedHandle::ExternalImageDescriptorDXGISharedHandle()
|
ExternalImageDescriptorDXGISharedHandle::ExternalImageDescriptorDXGISharedHandle()
|
||||||
: ExternalImageDescriptor(ExternalImageDescriptorType::DXGISharedHandle) {
|
: ExternalImageDescriptor(ExternalImageType::DXGISharedHandle) {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t SetExternalMemoryReservation(WGPUDevice device,
|
uint64_t SetExternalMemoryReservation(WGPUDevice device,
|
||||||
|
@ -396,7 +396,7 @@ namespace dawn_native { namespace d3d12 {
|
|||||||
AcquireRef(new Texture(device, textureDescriptor, TextureState::OwnedExternal));
|
AcquireRef(new Texture(device, textureDescriptor, TextureState::OwnedExternal));
|
||||||
DAWN_TRY(dawnTexture->InitializeAsExternalTexture(textureDescriptor, sharedHandle,
|
DAWN_TRY(dawnTexture->InitializeAsExternalTexture(textureDescriptor, sharedHandle,
|
||||||
acquireMutexKey, isSwapChainTexture));
|
acquireMutexKey, isSwapChainTexture));
|
||||||
dawnTexture->SetIsSubresourceContentInitialized(descriptor->isCleared,
|
dawnTexture->SetIsSubresourceContentInitialized(descriptor->isInitialized,
|
||||||
dawnTexture->GetAllSubresources());
|
dawnTexture->GetAllSubresources());
|
||||||
return std::move(dawnTexture);
|
return std::move(dawnTexture);
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ namespace dawn_native { namespace metal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ExternalImageDescriptorIOSurface::ExternalImageDescriptorIOSurface()
|
ExternalImageDescriptorIOSurface::ExternalImageDescriptorIOSurface()
|
||||||
: ExternalImageDescriptor(ExternalImageDescriptorType::IOSurface) {
|
: ExternalImageDescriptor(ExternalImageType::IOSurface) {
|
||||||
}
|
}
|
||||||
|
|
||||||
WGPUTexture WrapIOSurface(WGPUDevice cDevice,
|
WGPUTexture WrapIOSurface(WGPUDevice cDevice,
|
||||||
|
@ -355,7 +355,7 @@ namespace dawn_native { namespace metal {
|
|||||||
plane:plane];
|
plane:plane];
|
||||||
[mtlDesc release];
|
[mtlDesc release];
|
||||||
|
|
||||||
SetIsSubresourceContentInitialized(descriptor->isCleared, GetAllSubresources());
|
SetIsSubresourceContentInitialized(descriptor->isInitialized, GetAllSubresources());
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture::~Texture() {
|
Texture::~Texture() {
|
||||||
|
@ -658,7 +658,7 @@ namespace dawn_native { namespace vulkan {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeError Device::ImportExternalImage(const ExternalImageDescriptor* descriptor,
|
MaybeError Device::ImportExternalImage(const ExternalImageDescriptorVk* descriptor,
|
||||||
ExternalMemoryHandle memoryHandle,
|
ExternalMemoryHandle memoryHandle,
|
||||||
VkImage image,
|
VkImage image,
|
||||||
const std::vector<ExternalSemaphoreHandle>& waitHandles,
|
const std::vector<ExternalSemaphoreHandle>& waitHandles,
|
||||||
@ -702,22 +702,35 @@ namespace dawn_native { namespace vulkan {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeError Device::SignalAndExportExternalTexture(Texture* texture,
|
bool Device::SignalAndExportExternalTexture(
|
||||||
ExternalSemaphoreHandle* outHandle) {
|
Texture* texture,
|
||||||
DAWN_TRY(ValidateObject(texture));
|
VkImageLayout desiredLayout,
|
||||||
|
ExternalImageExportInfoVk* info,
|
||||||
|
std::vector<ExternalSemaphoreHandle>* semaphoreHandles) {
|
||||||
|
return !ConsumedError([&]() -> MaybeError {
|
||||||
|
DAWN_TRY(ValidateObject(texture));
|
||||||
|
|
||||||
VkSemaphore outSignalSemaphore;
|
VkSemaphore signalSemaphore;
|
||||||
DAWN_TRY(texture->SignalAndDestroy(&outSignalSemaphore));
|
VkImageLayout releasedOldLayout;
|
||||||
|
VkImageLayout releasedNewLayout;
|
||||||
|
DAWN_TRY(texture->ExportExternalTexture(desiredLayout, &signalSemaphore,
|
||||||
|
&releasedOldLayout, &releasedNewLayout));
|
||||||
|
|
||||||
// This has to happen right after SignalAndDestroy, since the semaphore will be
|
ExternalSemaphoreHandle semaphoreHandle;
|
||||||
// deleted when the fenced deleter runs after the queue submission
|
DAWN_TRY_ASSIGN(semaphoreHandle,
|
||||||
DAWN_TRY_ASSIGN(*outHandle, mExternalSemaphoreService->ExportSemaphore(outSignalSemaphore));
|
mExternalSemaphoreService->ExportSemaphore(signalSemaphore));
|
||||||
|
semaphoreHandles->push_back(semaphoreHandle);
|
||||||
|
info->releasedOldLayout = releasedOldLayout;
|
||||||
|
info->releasedNewLayout = releasedNewLayout;
|
||||||
|
info->isInitialized =
|
||||||
|
texture->IsSubresourceContentInitialized(texture->GetAllSubresources());
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
|
}());
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureBase* Device::CreateTextureWrappingVulkanImage(
|
TextureBase* Device::CreateTextureWrappingVulkanImage(
|
||||||
const ExternalImageDescriptor* descriptor,
|
const ExternalImageDescriptorVk* descriptor,
|
||||||
ExternalMemoryHandle memoryHandle,
|
ExternalMemoryHandle memoryHandle,
|
||||||
const std::vector<ExternalSemaphoreHandle>& waitHandles) {
|
const std::vector<ExternalSemaphoreHandle>& waitHandles) {
|
||||||
const TextureDescriptor* textureDescriptor =
|
const TextureDescriptor* textureDescriptor =
|
||||||
|
@ -69,12 +69,13 @@ namespace dawn_native { namespace vulkan {
|
|||||||
// Dawn Native API
|
// Dawn Native API
|
||||||
|
|
||||||
TextureBase* CreateTextureWrappingVulkanImage(
|
TextureBase* CreateTextureWrappingVulkanImage(
|
||||||
const ExternalImageDescriptor* descriptor,
|
const ExternalImageDescriptorVk* descriptor,
|
||||||
ExternalMemoryHandle memoryHandle,
|
ExternalMemoryHandle memoryHandle,
|
||||||
const std::vector<ExternalSemaphoreHandle>& waitHandles);
|
const std::vector<ExternalSemaphoreHandle>& waitHandles);
|
||||||
|
bool SignalAndExportExternalTexture(Texture* texture,
|
||||||
MaybeError SignalAndExportExternalTexture(Texture* texture,
|
VkImageLayout desiredLayout,
|
||||||
ExternalSemaphoreHandle* outHandle);
|
ExternalImageExportInfoVk* info,
|
||||||
|
std::vector<ExternalSemaphoreHandle>* semaphoreHandle);
|
||||||
|
|
||||||
// Dawn API
|
// Dawn API
|
||||||
CommandBufferBase* CreateCommandBuffer(CommandEncoder* encoder,
|
CommandBufferBase* CreateCommandBuffer(CommandEncoder* encoder,
|
||||||
@ -192,7 +193,7 @@ namespace dawn_native { namespace vulkan {
|
|||||||
// There is always a valid recording context stored in mRecordingContext
|
// There is always a valid recording context stored in mRecordingContext
|
||||||
CommandRecordingContext mRecordingContext;
|
CommandRecordingContext mRecordingContext;
|
||||||
|
|
||||||
MaybeError ImportExternalImage(const ExternalImageDescriptor* descriptor,
|
MaybeError ImportExternalImage(const ExternalImageDescriptorVk* descriptor,
|
||||||
ExternalMemoryHandle memoryHandle,
|
ExternalMemoryHandle memoryHandle,
|
||||||
VkImage image,
|
VkImage image,
|
||||||
const std::vector<ExternalSemaphoreHandle>& waitHandles,
|
const std::vector<ExternalSemaphoreHandle>& waitHandles,
|
||||||
@ -203,4 +204,4 @@ namespace dawn_native { namespace vulkan {
|
|||||||
|
|
||||||
}} // namespace dawn_native::vulkan
|
}} // namespace dawn_native::vulkan
|
||||||
|
|
||||||
#endif // DAWNNATIVE_VULKAN_DEVICEVK_H_
|
#endif // DAWNNATIVE_VULKAN_DEVICEVK_H_
|
||||||
|
@ -462,7 +462,7 @@ namespace dawn_native { namespace vulkan {
|
|||||||
// static
|
// static
|
||||||
ResultOrError<Texture*> Texture::CreateFromExternal(
|
ResultOrError<Texture*> Texture::CreateFromExternal(
|
||||||
Device* device,
|
Device* device,
|
||||||
const ExternalImageDescriptor* descriptor,
|
const ExternalImageDescriptorVk* descriptor,
|
||||||
const TextureDescriptor* textureDescriptor,
|
const TextureDescriptor* textureDescriptor,
|
||||||
external_memory::Service* externalMemoryService) {
|
external_memory::Service* externalMemoryService) {
|
||||||
Ref<Texture> texture =
|
Ref<Texture> texture =
|
||||||
@ -537,7 +537,7 @@ namespace dawn_native { namespace vulkan {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Internally managed, but imported from external handle
|
// Internally managed, but imported from external handle
|
||||||
MaybeError Texture::InitializeFromExternal(const ExternalImageDescriptor* descriptor,
|
MaybeError Texture::InitializeFromExternal(const ExternalImageDescriptorVk* descriptor,
|
||||||
external_memory::Service* externalMemoryService) {
|
external_memory::Service* externalMemoryService) {
|
||||||
VkFormat format = VulkanImageFormat(ToBackend(GetDevice()), GetFormat().format);
|
VkFormat format = VulkanImageFormat(ToBackend(GetDevice()), GetFormat().format);
|
||||||
VkImageUsageFlags usage = VulkanImageUsage(GetUsage(), GetFormat());
|
VkImageUsageFlags usage = VulkanImageUsage(GetUsage(), GetFormat());
|
||||||
@ -547,6 +547,9 @@ namespace dawn_native { namespace vulkan {
|
|||||||
|
|
||||||
mExternalState = ExternalState::PendingAcquire;
|
mExternalState = ExternalState::PendingAcquire;
|
||||||
|
|
||||||
|
mPendingAcquireOldLayout = descriptor->releasedOldLayout;
|
||||||
|
mPendingAcquireNewLayout = descriptor->releasedNewLayout;
|
||||||
|
|
||||||
VkImageCreateInfo baseCreateInfo = {};
|
VkImageCreateInfo baseCreateInfo = {};
|
||||||
FillVulkanCreateInfoSizesAndType(*this, &baseCreateInfo);
|
FillVulkanCreateInfoSizesAndType(*this, &baseCreateInfo);
|
||||||
|
|
||||||
@ -571,7 +574,7 @@ namespace dawn_native { namespace vulkan {
|
|||||||
mHandle = nativeImage;
|
mHandle = nativeImage;
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeError Texture::BindExternalMemory(const ExternalImageDescriptor* descriptor,
|
MaybeError Texture::BindExternalMemory(const ExternalImageDescriptorVk* descriptor,
|
||||||
VkSemaphore signalSemaphore,
|
VkSemaphore signalSemaphore,
|
||||||
VkDeviceMemory externalMemoryAllocation,
|
VkDeviceMemory externalMemoryAllocation,
|
||||||
std::vector<VkSemaphore> waitSemaphores) {
|
std::vector<VkSemaphore> waitSemaphores) {
|
||||||
@ -580,8 +583,8 @@ namespace dawn_native { namespace vulkan {
|
|||||||
device->fn.BindImageMemory(device->GetVkDevice(), mHandle, externalMemoryAllocation, 0),
|
device->fn.BindImageMemory(device->GetVkDevice(), mHandle, externalMemoryAllocation, 0),
|
||||||
"BindImageMemory (external)"));
|
"BindImageMemory (external)"));
|
||||||
|
|
||||||
// Don't clear imported texture if already cleared
|
// Don't clear imported texture if already initialized
|
||||||
if (descriptor->isCleared) {
|
if (descriptor->isInitialized) {
|
||||||
SetIsSubresourceContentInitialized(true, GetAllSubresources());
|
SetIsSubresourceContentInitialized(true, GetAllSubresources());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -592,7 +595,10 @@ namespace dawn_native { namespace vulkan {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeError Texture::SignalAndDestroy(VkSemaphore* outSignalSemaphore) {
|
MaybeError Texture::ExportExternalTexture(VkImageLayout desiredLayout,
|
||||||
|
VkSemaphore* signalSemaphore,
|
||||||
|
VkImageLayout* releasedOldLayout,
|
||||||
|
VkImageLayout* releasedNewLayout) {
|
||||||
Device* device = ToBackend(GetDevice());
|
Device* device = ToBackend(GetDevice());
|
||||||
|
|
||||||
if (mExternalState == ExternalState::Released) {
|
if (mExternalState == ExternalState::Released) {
|
||||||
@ -605,17 +611,60 @@ namespace dawn_native { namespace vulkan {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ASSERT(mSignalSemaphore != VK_NULL_HANDLE);
|
ASSERT(mSignalSemaphore != VK_NULL_HANDLE);
|
||||||
|
ASSERT(GetNumMipLevels() == 1 && GetArrayLayers() == 1);
|
||||||
|
|
||||||
// Release the texture
|
// Release the texture
|
||||||
mExternalState = ExternalState::PendingRelease;
|
mExternalState = ExternalState::Released;
|
||||||
TransitionFullUsage(device->GetPendingRecordingContext(), wgpu::TextureUsage::None);
|
|
||||||
|
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
|
// 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());
|
DAWN_TRY(device->SubmitPendingCommands());
|
||||||
|
|
||||||
// Write out the signal semaphore
|
// Write out the layouts and signal semaphore
|
||||||
*outSignalSemaphore = mSignalSemaphore;
|
*releasedOldLayout = barrier.oldLayout;
|
||||||
|
*releasedNewLayout = barrier.newLayout;
|
||||||
|
*signalSemaphore = mSignalSemaphore;
|
||||||
|
|
||||||
mSignalSemaphore = VK_NULL_HANDLE;
|
mSignalSemaphore = VK_NULL_HANDLE;
|
||||||
|
|
||||||
// Destroy the texture so it can't be used again
|
// Destroy the texture so it can't be used again
|
||||||
@ -688,26 +737,58 @@ namespace dawn_native { namespace vulkan {
|
|||||||
SubresourceRange::SingleMipAndLayer(0, 0, GetFormat().aspects)));
|
SubresourceRange::SingleMipAndLayer(0, 0, GetFormat().aspects)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VkImageMemoryBarrier* barrier = &(*barriers)[transitionBarrierStart];
|
||||||
// Transfer texture from external queue to graphics queue
|
// Transfer texture from external queue to graphics queue
|
||||||
(*barriers)[transitionBarrierStart].srcQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL_KHR;
|
barrier->srcQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL_KHR;
|
||||||
(*barriers)[transitionBarrierStart].dstQueueFamilyIndex =
|
barrier->dstQueueFamilyIndex = ToBackend(GetDevice())->GetGraphicsQueueFamily();
|
||||||
ToBackend(GetDevice())->GetGraphicsQueueFamily();
|
|
||||||
// Don't override oldLayout to leave it as VK_IMAGE_LAYOUT_UNDEFINED
|
// srcAccessMask means nothing when importing. Queue transfers require a barrier on
|
||||||
// TODO(http://crbug.com/dawn/200)
|
// both the importing and exporting queues. The exporting queue should have specified
|
||||||
mExternalState = ExternalState::Acquired;
|
// this.
|
||||||
} else if (mExternalState == ExternalState::PendingRelease) {
|
barrier->srcAccessMask = 0;
|
||||||
if (barriers->size() == transitionBarrierStart) {
|
|
||||||
barriers->push_back(BuildMemoryBarrier(
|
// This should be the first barrier after import.
|
||||||
GetFormat(), mHandle, wgpu::TextureUsage::None, wgpu::TextureUsage::None,
|
ASSERT(barrier->oldLayout == VK_IMAGE_LAYOUT_UNDEFINED);
|
||||||
SubresourceRange::SingleMipAndLayer(0, 0, GetFormat().aspects)));
|
|
||||||
|
// 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
|
// If these are unequal, we need an another barrier to transition the layout.
|
||||||
(*barriers)[transitionBarrierStart].srcQueueFamilyIndex =
|
if (barrier->newLayout != desiredLayout) {
|
||||||
ToBackend(GetDevice())->GetGraphicsQueueFamily();
|
VkImageMemoryBarrier layoutBarrier;
|
||||||
(*barriers)[transitionBarrierStart].dstQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL_KHR;
|
layoutBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||||
(*barriers)[transitionBarrierStart].newLayout = VK_IMAGE_LAYOUT_GENERAL;
|
layoutBarrier.pNext = nullptr;
|
||||||
mExternalState = ExternalState::Released;
|
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;
|
mLastExternalState = mExternalState;
|
||||||
|
@ -49,7 +49,7 @@ namespace dawn_native { namespace vulkan {
|
|||||||
// image must be bound via Texture::BindExternalMemory.
|
// image must be bound via Texture::BindExternalMemory.
|
||||||
static ResultOrError<Texture*> CreateFromExternal(
|
static ResultOrError<Texture*> CreateFromExternal(
|
||||||
Device* device,
|
Device* device,
|
||||||
const ExternalImageDescriptor* descriptor,
|
const ExternalImageDescriptorVk* descriptor,
|
||||||
const TextureDescriptor* textureDescriptor,
|
const TextureDescriptor* textureDescriptor,
|
||||||
external_memory::Service* externalMemoryService);
|
external_memory::Service* externalMemoryService);
|
||||||
|
|
||||||
@ -84,20 +84,24 @@ namespace dawn_native { namespace vulkan {
|
|||||||
void EnsureSubresourceContentInitialized(CommandRecordingContext* recordingContext,
|
void EnsureSubresourceContentInitialized(CommandRecordingContext* recordingContext,
|
||||||
const SubresourceRange& range);
|
const SubresourceRange& range);
|
||||||
|
|
||||||
MaybeError SignalAndDestroy(VkSemaphore* outSignalSemaphore);
|
|
||||||
// Binds externally allocated memory to the VkImage and on success, takes ownership of
|
// Binds externally allocated memory to the VkImage and on success, takes ownership of
|
||||||
// semaphores.
|
// semaphores.
|
||||||
MaybeError BindExternalMemory(const ExternalImageDescriptor* descriptor,
|
MaybeError BindExternalMemory(const ExternalImageDescriptorVk* descriptor,
|
||||||
VkSemaphore signalSemaphore,
|
VkSemaphore signalSemaphore,
|
||||||
VkDeviceMemory externalMemoryAllocation,
|
VkDeviceMemory externalMemoryAllocation,
|
||||||
std::vector<VkSemaphore> waitSemaphores);
|
std::vector<VkSemaphore> waitSemaphores);
|
||||||
|
|
||||||
|
MaybeError ExportExternalTexture(VkImageLayout desiredLayout,
|
||||||
|
VkSemaphore* signalSemaphore,
|
||||||
|
VkImageLayout* releasedOldLayout,
|
||||||
|
VkImageLayout* releasedNewLayout);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
~Texture() override;
|
~Texture() override;
|
||||||
using TextureBase::TextureBase;
|
using TextureBase::TextureBase;
|
||||||
|
|
||||||
MaybeError InitializeAsInternalTexture();
|
MaybeError InitializeAsInternalTexture();
|
||||||
MaybeError InitializeFromExternal(const ExternalImageDescriptor* descriptor,
|
MaybeError InitializeFromExternal(const ExternalImageDescriptorVk* descriptor,
|
||||||
external_memory::Service* externalMemoryService);
|
external_memory::Service* externalMemoryService);
|
||||||
void InitializeForSwapChain(VkImage nativeImage);
|
void InitializeForSwapChain(VkImage nativeImage);
|
||||||
|
|
||||||
@ -119,12 +123,14 @@ namespace dawn_native { namespace vulkan {
|
|||||||
InternalOnly,
|
InternalOnly,
|
||||||
PendingAcquire,
|
PendingAcquire,
|
||||||
Acquired,
|
Acquired,
|
||||||
PendingRelease,
|
|
||||||
Released
|
Released
|
||||||
};
|
};
|
||||||
ExternalState mExternalState = ExternalState::InternalOnly;
|
ExternalState mExternalState = ExternalState::InternalOnly;
|
||||||
ExternalState mLastExternalState = ExternalState::InternalOnly;
|
ExternalState mLastExternalState = ExternalState::InternalOnly;
|
||||||
|
|
||||||
|
VkImageLayout mPendingAcquireOldLayout;
|
||||||
|
VkImageLayout mPendingAcquireNewLayout;
|
||||||
|
|
||||||
VkSemaphore mSignalSemaphore = VK_NULL_HANDLE;
|
VkSemaphore mSignalSemaphore = VK_NULL_HANDLE;
|
||||||
std::vector<VkSemaphore> mWaitRequirements;
|
std::vector<VkSemaphore> mWaitRequirements;
|
||||||
|
|
||||||
|
@ -59,51 +59,75 @@ namespace dawn_native { namespace vulkan {
|
|||||||
return static_cast<WGPUTextureFormat>(impl->GetPreferredFormat());
|
return static_cast<WGPUTextureFormat>(impl->GetPreferredFormat());
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DAWN_PLATFORM_LINUX
|
#if defined(DAWN_PLATFORM_LINUX)
|
||||||
ExternalImageDescriptorFD::ExternalImageDescriptorFD(ExternalImageDescriptorType descType)
|
|
||||||
: ExternalImageDescriptor(descType) {
|
|
||||||
}
|
|
||||||
|
|
||||||
ExternalImageDescriptorOpaqueFD::ExternalImageDescriptorOpaqueFD()
|
ExternalImageDescriptorOpaqueFD::ExternalImageDescriptorOpaqueFD()
|
||||||
: ExternalImageDescriptorFD(ExternalImageDescriptorType::OpaqueFD) {
|
: ExternalImageDescriptorFD(ExternalImageType::OpaqueFD) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ExternalImageDescriptorDmaBuf::ExternalImageDescriptorDmaBuf()
|
ExternalImageDescriptorDmaBuf::ExternalImageDescriptorDmaBuf()
|
||||||
: ExternalImageDescriptorFD(ExternalImageDescriptorType::DmaBuf) {
|
: ExternalImageDescriptorFD(ExternalImageType::DmaBuf) {
|
||||||
|
}
|
||||||
|
|
||||||
|
ExternalImageExportInfoOpaqueFD::ExternalImageExportInfoOpaqueFD()
|
||||||
|
: ExternalImageExportInfoFD(ExternalImageType::OpaqueFD) {
|
||||||
|
}
|
||||||
|
|
||||||
|
ExternalImageExportInfoDmaBuf::ExternalImageExportInfoDmaBuf()
|
||||||
|
: ExternalImageExportInfoFD(ExternalImageType::DmaBuf) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int ExportSignalSemaphoreOpaqueFD(WGPUDevice cDevice, WGPUTexture cTexture) {
|
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);
|
Device* device = reinterpret_cast<Device*>(cDevice);
|
||||||
Texture* texture = reinterpret_cast<Texture*>(cTexture);
|
device->EmitDeprecationWarning(
|
||||||
|
"ExportSignalSemaphoreOpaqueFD is deprecated. Please use ExportVulkanImage instead.");
|
||||||
if (!texture) {
|
ExternalImageExportInfoOpaqueFD info;
|
||||||
|
if (!ExportVulkanImage(cTexture, VK_IMAGE_LAYOUT_GENERAL, &info)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
return info.semaphoreHandles[0];
|
||||||
ExternalSemaphoreHandle outHandle;
|
|
||||||
if (device->ConsumedError(device->SignalAndExportExternalTexture(texture, &outHandle))) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return outHandle;
|
|
||||||
}
|
}
|
||||||
|
#endif // DAWN_PLATFORM_LINUX
|
||||||
|
|
||||||
WGPUTexture WrapVulkanImage(WGPUDevice cDevice, const ExternalImageDescriptor* descriptor) {
|
WGPUTexture WrapVulkanImage(WGPUDevice cDevice, const ExternalImageDescriptorVk* descriptor) {
|
||||||
Device* device = reinterpret_cast<Device*>(cDevice);
|
|
||||||
|
|
||||||
switch (descriptor->type) {
|
switch (descriptor->type) {
|
||||||
case ExternalImageDescriptorType::OpaqueFD:
|
#if defined(DAWN_PLATFORM_LINUX)
|
||||||
case ExternalImageDescriptorType::DmaBuf: {
|
case ExternalImageType::OpaqueFD:
|
||||||
|
case ExternalImageType::DmaBuf: {
|
||||||
const ExternalImageDescriptorFD* fdDescriptor =
|
const ExternalImageDescriptorFD* fdDescriptor =
|
||||||
static_cast<const ExternalImageDescriptorFD*>(descriptor);
|
static_cast<const ExternalImageDescriptorFD*>(descriptor);
|
||||||
|
Device* device = reinterpret_cast<Device*>(cDevice);
|
||||||
TextureBase* texture = device->CreateTextureWrappingVulkanImage(
|
TextureBase* texture = device->CreateTextureWrappingVulkanImage(
|
||||||
descriptor, fdDescriptor->memoryFD, fdDescriptor->waitFDs);
|
fdDescriptor, fdDescriptor->memoryFD, fdDescriptor->waitFDs);
|
||||||
return reinterpret_cast<WGPUTexture>(texture);
|
return reinterpret_cast<WGPUTexture>(texture);
|
||||||
}
|
}
|
||||||
|
#endif // DAWN_PLATFORM_LINUX
|
||||||
default:
|
default:
|
||||||
return nullptr;
|
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
|
}} // namespace dawn_native::vulkan
|
||||||
|
@ -83,7 +83,7 @@ namespace dawn_native { namespace vulkan { namespace external_memory {
|
|||||||
if (!mSupported) {
|
if (!mSupported) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (descriptor->type != ExternalImageDescriptorType::DmaBuf) {
|
if (descriptor->type != ExternalImageType::DmaBuf) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const ExternalImageDescriptorDmaBuf* dmaBufDescriptor =
|
const ExternalImageDescriptorDmaBuf* dmaBufDescriptor =
|
||||||
@ -150,7 +150,7 @@ namespace dawn_native { namespace vulkan { namespace external_memory {
|
|||||||
ResultOrError<MemoryImportParams> Service::GetMemoryImportParams(
|
ResultOrError<MemoryImportParams> Service::GetMemoryImportParams(
|
||||||
const ExternalImageDescriptor* descriptor,
|
const ExternalImageDescriptor* descriptor,
|
||||||
VkImage image) {
|
VkImage image) {
|
||||||
if (descriptor->type != ExternalImageDescriptorType::DmaBuf) {
|
if (descriptor->type != ExternalImageType::DmaBuf) {
|
||||||
return DAWN_VALIDATION_ERROR("ExternalImageDescriptor is not a dma-buf descriptor");
|
return DAWN_VALIDATION_ERROR("ExternalImageDescriptor is not a dma-buf descriptor");
|
||||||
}
|
}
|
||||||
const ExternalImageDescriptorDmaBuf* dmaBufDescriptor =
|
const ExternalImageDescriptorDmaBuf* dmaBufDescriptor =
|
||||||
@ -216,7 +216,7 @@ namespace dawn_native { namespace vulkan { namespace external_memory {
|
|||||||
|
|
||||||
ResultOrError<VkImage> Service::CreateImage(const ExternalImageDescriptor* descriptor,
|
ResultOrError<VkImage> Service::CreateImage(const ExternalImageDescriptor* descriptor,
|
||||||
const VkImageCreateInfo& baseCreateInfo) {
|
const VkImageCreateInfo& baseCreateInfo) {
|
||||||
if (descriptor->type != ExternalImageDescriptorType::DmaBuf) {
|
if (descriptor->type != ExternalImageType::DmaBuf) {
|
||||||
return DAWN_VALIDATION_ERROR("ExternalImageDescriptor is not a dma-buf descriptor");
|
return DAWN_VALIDATION_ERROR("ExternalImageDescriptor is not a dma-buf descriptor");
|
||||||
}
|
}
|
||||||
const ExternalImageDescriptorDmaBuf* dmaBufDescriptor =
|
const ExternalImageDescriptorDmaBuf* dmaBufDescriptor =
|
||||||
|
@ -71,8 +71,7 @@ namespace dawn_native { namespace vulkan { namespace external_memory {
|
|||||||
// TODO(http://crbug.com/dawn/206): Investigate dedicated only images
|
// TODO(http://crbug.com/dawn/206): Investigate dedicated only images
|
||||||
VkFlags memoryFlags =
|
VkFlags memoryFlags =
|
||||||
externalFormatProperties.externalMemoryProperties.externalMemoryFeatures;
|
externalFormatProperties.externalMemoryProperties.externalMemoryFeatures;
|
||||||
return (memoryFlags & VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR) &&
|
return (memoryFlags & VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR) != 0;
|
||||||
!(memoryFlags & VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Service::SupportsCreateImage(const ExternalImageDescriptor* descriptor,
|
bool Service::SupportsCreateImage(const ExternalImageDescriptor* descriptor,
|
||||||
@ -84,7 +83,7 @@ namespace dawn_native { namespace vulkan { namespace external_memory {
|
|||||||
ResultOrError<MemoryImportParams> Service::GetMemoryImportParams(
|
ResultOrError<MemoryImportParams> Service::GetMemoryImportParams(
|
||||||
const ExternalImageDescriptor* descriptor,
|
const ExternalImageDescriptor* descriptor,
|
||||||
VkImage image) {
|
VkImage image) {
|
||||||
if (descriptor->type != ExternalImageDescriptorType::OpaqueFD) {
|
if (descriptor->type != ExternalImageType::OpaqueFD) {
|
||||||
return DAWN_VALIDATION_ERROR("ExternalImageDescriptor is not an OpaqueFD descriptor");
|
return DAWN_VALIDATION_ERROR("ExternalImageDescriptor is not an OpaqueFD descriptor");
|
||||||
}
|
}
|
||||||
const ExternalImageDescriptorOpaqueFD* opaqueFDDescriptor =
|
const ExternalImageDescriptorOpaqueFD* opaqueFDDescriptor =
|
||||||
|
@ -71,8 +71,7 @@ namespace dawn_native { namespace vulkan { namespace external_memory {
|
|||||||
// TODO(http://crbug.com/dawn/206): Investigate dedicated only images
|
// TODO(http://crbug.com/dawn/206): Investigate dedicated only images
|
||||||
VkFlags memoryFlags =
|
VkFlags memoryFlags =
|
||||||
externalFormatProperties.externalMemoryProperties.externalMemoryFeatures;
|
externalFormatProperties.externalMemoryProperties.externalMemoryFeatures;
|
||||||
return (memoryFlags & VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR) &&
|
return (memoryFlags & VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR) != 0;
|
||||||
!(memoryFlags & VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Service::SupportsCreateImage(const ExternalImageDescriptor* descriptor,
|
bool Service::SupportsCreateImage(const ExternalImageDescriptor* descriptor,
|
||||||
@ -84,7 +83,7 @@ namespace dawn_native { namespace vulkan { namespace external_memory {
|
|||||||
ResultOrError<MemoryImportParams> Service::GetMemoryImportParams(
|
ResultOrError<MemoryImportParams> Service::GetMemoryImportParams(
|
||||||
const ExternalImageDescriptor* descriptor,
|
const ExternalImageDescriptor* descriptor,
|
||||||
VkImage image) {
|
VkImage image) {
|
||||||
if (descriptor->type != ExternalImageDescriptorType::OpaqueFD) {
|
if (descriptor->type != ExternalImageType::OpaqueFD) {
|
||||||
return DAWN_VALIDATION_ERROR("ExternalImageDescriptor is not an OpaqueFD descriptor");
|
return DAWN_VALIDATION_ERROR("ExternalImageDescriptor is not an OpaqueFD descriptor");
|
||||||
}
|
}
|
||||||
const ExternalImageDescriptorOpaqueFD* opaqueFDDescriptor =
|
const ExternalImageDescriptorOpaqueFD* opaqueFDDescriptor =
|
||||||
|
@ -200,8 +200,8 @@ namespace dawn_native {
|
|||||||
DAWN_NATIVE_EXPORT uint64_t AcquireErrorInjectorCallCount();
|
DAWN_NATIVE_EXPORT uint64_t AcquireErrorInjectorCallCount();
|
||||||
DAWN_NATIVE_EXPORT void InjectErrorAt(uint64_t index);
|
DAWN_NATIVE_EXPORT void InjectErrorAt(uint64_t index);
|
||||||
|
|
||||||
// The different types of ExternalImageDescriptors
|
// The different types of external images
|
||||||
enum ExternalImageDescriptorType {
|
enum ExternalImageType {
|
||||||
OpaqueFD,
|
OpaqueFD,
|
||||||
DmaBuf,
|
DmaBuf,
|
||||||
IOSurface,
|
IOSurface,
|
||||||
@ -211,13 +211,26 @@ namespace dawn_native {
|
|||||||
// Common properties of external images
|
// Common properties of external images
|
||||||
struct DAWN_NATIVE_EXPORT ExternalImageDescriptor {
|
struct DAWN_NATIVE_EXPORT ExternalImageDescriptor {
|
||||||
public:
|
public:
|
||||||
const ExternalImageDescriptorType type;
|
const ExternalImageType type;
|
||||||
const WGPUTextureDescriptor* cTextureDescriptor; // Must match image creation params
|
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:
|
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
|
} // namespace dawn_native
|
||||||
|
|
||||||
#endif // DAWNNATIVE_DAWNNATIVE_H_
|
#endif // DAWNNATIVE_DAWNNATIVE_H_
|
||||||
|
@ -33,19 +33,49 @@ namespace dawn_native { namespace vulkan {
|
|||||||
DAWN_NATIVE_EXPORT WGPUTextureFormat
|
DAWN_NATIVE_EXPORT WGPUTextureFormat
|
||||||
GetNativeSwapChainPreferredFormat(const DawnSwapChainImplementation* swapChain);
|
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__
|
#ifdef __linux__
|
||||||
|
|
||||||
// Common properties of external images represented by FDs. On successful import the file
|
// 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
|
// 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
|
// used outside of Dawn again. TODO(enga): Also transfer ownership in the error case so the
|
||||||
// caller can assume the FD is always consumed.
|
// caller can assume the FD is always consumed.
|
||||||
struct DAWN_NATIVE_EXPORT ExternalImageDescriptorFD : ExternalImageDescriptor {
|
struct DAWN_NATIVE_EXPORT ExternalImageDescriptorFD : ExternalImageDescriptorVk {
|
||||||
public:
|
public:
|
||||||
int memoryFD; // A file descriptor from an export of the memory of the image
|
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
|
std::vector<int> waitFDs; // File descriptors of semaphores which will be waited on
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ExternalImageDescriptorFD(ExternalImageDescriptorType type);
|
using ExternalImageDescriptorVk::ExternalImageDescriptorVk;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Descriptor for opaque file descriptor image import
|
// Descriptor for opaque file descriptor image import
|
||||||
@ -64,8 +94,29 @@ namespace dawn_native { namespace vulkan {
|
|||||||
uint64_t drmModifier; // DRM modifier of the buffer
|
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
|
// Exports a signal semaphore from a wrapped texture. This must be called on wrapped
|
||||||
// textures before they are destroyed. On failure, returns -1
|
// 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,
|
DAWN_NATIVE_EXPORT int ExportSignalSemaphoreOpaqueFD(WGPUDevice cDevice,
|
||||||
WGPUTexture cTexture);
|
WGPUTexture cTexture);
|
||||||
|
|
||||||
@ -74,8 +125,15 @@ namespace dawn_native { namespace vulkan {
|
|||||||
// primitives before the texture can be used.
|
// primitives before the texture can be used.
|
||||||
// On failure, returns a nullptr.
|
// On failure, returns a nullptr.
|
||||||
DAWN_NATIVE_EXPORT WGPUTexture WrapVulkanImage(WGPUDevice cDevice,
|
DAWN_NATIVE_EXPORT WGPUTexture WrapVulkanImage(WGPUDevice cDevice,
|
||||||
const ExternalImageDescriptor* descriptor);
|
const ExternalImageDescriptorVk* descriptor);
|
||||||
#endif // __linux__
|
|
||||||
|
// 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
|
}} // namespace dawn_native::vulkan
|
||||||
|
|
||||||
|
@ -300,7 +300,7 @@ class D3D12SharedHandleUsageTests : public D3D12ResourceTestBase {
|
|||||||
const wgpu::Color& clearColor,
|
const wgpu::Color& clearColor,
|
||||||
ID3D11Texture2D** d3d11TextureOut,
|
ID3D11Texture2D** d3d11TextureOut,
|
||||||
IDXGIKeyedMutex** dxgiKeyedMutexOut,
|
IDXGIKeyedMutex** dxgiKeyedMutexOut,
|
||||||
bool isCleared = true) const {
|
bool isInitialized = true) const {
|
||||||
ComPtr<ID3D11Texture2D> d3d11Texture;
|
ComPtr<ID3D11Texture2D> d3d11Texture;
|
||||||
HRESULT hr = mD3d11Device->CreateTexture2D(d3dDescriptor, nullptr, &d3d11Texture);
|
HRESULT hr = mD3d11Device->CreateTexture2D(d3dDescriptor, nullptr, &d3d11Texture);
|
||||||
ASSERT_EQ(hr, S_OK);
|
ASSERT_EQ(hr, S_OK);
|
||||||
@ -339,7 +339,7 @@ class D3D12SharedHandleUsageTests : public D3D12ResourceTestBase {
|
|||||||
reinterpret_cast<const WGPUTextureDescriptor*>(dawnDescriptor);
|
reinterpret_cast<const WGPUTextureDescriptor*>(dawnDescriptor);
|
||||||
externDesc.sharedHandle = sharedHandle;
|
externDesc.sharedHandle = sharedHandle;
|
||||||
externDesc.acquireMutexKey = 1;
|
externDesc.acquireMutexKey = 1;
|
||||||
externDesc.isCleared = isCleared;
|
externDesc.isInitialized = isInitialized;
|
||||||
WGPUTexture dawnTexture = dawn_native::d3d12::WrapSharedHandle(device.Get(), &externDesc);
|
WGPUTexture dawnTexture = dawn_native::d3d12::WrapSharedHandle(device.Get(), &externDesc);
|
||||||
|
|
||||||
*dawnTextureOut = wgpu::Texture::Acquire(dawnTexture);
|
*dawnTextureOut = wgpu::Texture::Acquire(dawnTexture);
|
||||||
@ -502,9 +502,9 @@ TEST_P(D3D12SharedHandleUsageTests, ClearTwiceInD3D12ReadbackInD3D11) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 1. Create and clear a D3D11 texture with clearColor
|
// 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
|
// 3. Verify clearColor is not visible in wrapped texture
|
||||||
TEST_P(D3D12SharedHandleUsageTests, UnclearedTextureIsCleared) {
|
TEST_P(D3D12SharedHandleUsageTests, UninitializedTextureIsCleared) {
|
||||||
DAWN_SKIP_TEST_IF(UsesWire());
|
DAWN_SKIP_TEST_IF(UsesWire());
|
||||||
|
|
||||||
const wgpu::Color clearColor{1.0f, 0.0f, 0.0f, 1.0f};
|
const wgpu::Color clearColor{1.0f, 0.0f, 0.0f, 1.0f};
|
||||||
|
@ -97,13 +97,13 @@ namespace {
|
|||||||
wgpu::Texture WrapIOSurface(const wgpu::TextureDescriptor* descriptor,
|
wgpu::Texture WrapIOSurface(const wgpu::TextureDescriptor* descriptor,
|
||||||
IOSurfaceRef ioSurface,
|
IOSurfaceRef ioSurface,
|
||||||
uint32_t plane,
|
uint32_t plane,
|
||||||
bool isCleared = true) {
|
bool isInitialized = true) {
|
||||||
dawn_native::metal::ExternalImageDescriptorIOSurface externDesc;
|
dawn_native::metal::ExternalImageDescriptorIOSurface externDesc;
|
||||||
externDesc.cTextureDescriptor =
|
externDesc.cTextureDescriptor =
|
||||||
reinterpret_cast<const WGPUTextureDescriptor*>(descriptor);
|
reinterpret_cast<const WGPUTextureDescriptor*>(descriptor);
|
||||||
externDesc.ioSurface = ioSurface;
|
externDesc.ioSurface = ioSurface;
|
||||||
externDesc.plane = plane;
|
externDesc.plane = plane;
|
||||||
externDesc.isCleared = isCleared;
|
externDesc.isInitialized = isInitialized;
|
||||||
WGPUTexture texture = dawn_native::metal::WrapIOSurface(device.Get(), &externDesc);
|
WGPUTexture texture = dawn_native::metal::WrapIOSurface(device.Get(), &externDesc);
|
||||||
return wgpu::Texture::Acquire(texture);
|
return wgpu::Texture::Acquire(texture);
|
||||||
}
|
}
|
||||||
@ -446,8 +446,8 @@ TEST_P(IOSurfaceUsageTests, ClearRGBA8IOSurface) {
|
|||||||
DoClearTest(ioSurface.get(), wgpu::TextureFormat::RGBA8Unorm, &data, sizeof(data));
|
DoClearTest(ioSurface.get(), wgpu::TextureFormat::RGBA8Unorm, &data, sizeof(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that texture with color is cleared when isCleared = false
|
// Test that texture with color is cleared when isInitialized = false
|
||||||
TEST_P(IOSurfaceUsageTests, UnclearedTextureIsCleared) {
|
TEST_P(IOSurfaceUsageTests, UninitializedTextureIsCleared) {
|
||||||
DAWN_SKIP_TEST_IF(UsesWire());
|
DAWN_SKIP_TEST_IF(UsesWire());
|
||||||
|
|
||||||
ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(1, 1, kCVPixelFormatType_32RGBA, 4);
|
ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(1, 1, kCVPixelFormatType_32RGBA, 4);
|
||||||
@ -465,7 +465,7 @@ TEST_P(IOSurfaceUsageTests, UnclearedTextureIsCleared) {
|
|||||||
textureDescriptor.mipLevelCount = 1;
|
textureDescriptor.mipLevelCount = 1;
|
||||||
textureDescriptor.usage = wgpu::TextureUsage::OutputAttachment | wgpu::TextureUsage::CopySrc;
|
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);
|
wgpu::Texture ioSurfaceTexture = WrapIOSurface(&textureDescriptor, ioSurface.get(), 0, false);
|
||||||
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), ioSurfaceTexture, 0, 0);
|
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), ioSurfaceTexture, 0, 0);
|
||||||
}
|
}
|
||||||
|
@ -104,16 +104,34 @@ namespace dawn_native { namespace vulkan {
|
|||||||
uint32_t stride,
|
uint32_t stride,
|
||||||
uint64_t drmModifier,
|
uint64_t drmModifier,
|
||||||
std::vector<int> waitFDs,
|
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) {
|
bool expectValid = true) {
|
||||||
dawn_native::vulkan::ExternalImageDescriptorDmaBuf descriptor;
|
dawn_native::vulkan::ExternalImageDescriptorDmaBuf descriptor;
|
||||||
descriptor.cTextureDescriptor =
|
descriptor.cTextureDescriptor =
|
||||||
reinterpret_cast<const WGPUTextureDescriptor*>(textureDescriptor);
|
reinterpret_cast<const WGPUTextureDescriptor*>(textureDescriptor);
|
||||||
descriptor.isCleared = isCleared;
|
descriptor.isInitialized = isInitialized;
|
||||||
descriptor.stride = stride;
|
descriptor.stride = stride;
|
||||||
descriptor.drmModifier = drmModifier;
|
descriptor.drmModifier = drmModifier;
|
||||||
descriptor.memoryFD = memoryFd;
|
descriptor.memoryFD = memoryFd;
|
||||||
descriptor.waitFDs = waitFDs;
|
descriptor.waitFDs = waitFDs;
|
||||||
|
descriptor.releasedOldLayout = releasedOldLayout;
|
||||||
|
descriptor.releasedNewLayout = releasedNewLayout;
|
||||||
|
|
||||||
WGPUTexture texture =
|
WGPUTexture texture =
|
||||||
dawn_native::vulkan::WrapVulkanImage(dawnDevice.Get(), &descriptor);
|
dawn_native::vulkan::WrapVulkanImage(dawnDevice.Get(), &descriptor);
|
||||||
@ -131,11 +149,13 @@ namespace dawn_native { namespace vulkan {
|
|||||||
// Exports the signal from a wrapped texture and ignores it
|
// 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
|
// We have to export the signal before destroying the wrapped texture else it's an
|
||||||
// assertion failure
|
// assertion failure
|
||||||
void IgnoreSignalSemaphore(wgpu::Device dawnDevice, wgpu::Texture wrappedTexture) {
|
void IgnoreSignalSemaphore(wgpu::Texture wrappedTexture) {
|
||||||
int fd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(dawnDevice.Get(),
|
dawn_native::vulkan::ExternalImageExportInfoDmaBuf exportInfo;
|
||||||
wrappedTexture.Get());
|
dawn_native::vulkan::ExportVulkanImage(wrappedTexture.Get(), VK_IMAGE_LAYOUT_GENERAL, &exportInfo));
|
||||||
ASSERT_NE(fd, -1);
|
for (int handle : info.semaphoreHandles) {
|
||||||
close(fd);
|
ASSERT_NE(handle, -1);
|
||||||
|
close(handle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -157,7 +177,7 @@ namespace dawn_native { namespace vulkan {
|
|||||||
wgpu::Texture texture = WrapVulkanImage(device, &defaultDescriptor, defaultFd,
|
wgpu::Texture texture = WrapVulkanImage(device, &defaultDescriptor, defaultFd,
|
||||||
defaultStride, defaultModifier, {}, true, true);
|
defaultStride, defaultModifier, {}, true, true);
|
||||||
EXPECT_NE(texture.Get(), nullptr);
|
EXPECT_NE(texture.Get(), nullptr);
|
||||||
IgnoreSignalSemaphore(device, texture);
|
IgnoreSignalSemaphore(texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test an error occurs if the texture descriptor is missing
|
// Test an error occurs if the texture descriptor is missing
|
||||||
@ -230,10 +250,12 @@ namespace dawn_native { namespace vulkan {
|
|||||||
wgpu::Texture texture = WrapVulkanImage(device, &defaultDescriptor, defaultFd,
|
wgpu::Texture texture = WrapVulkanImage(device, &defaultDescriptor, defaultFd,
|
||||||
defaultStride, defaultModifier, {}, true, true);
|
defaultStride, defaultModifier, {}, true, true);
|
||||||
ASSERT_NE(texture.Get(), nullptr);
|
ASSERT_NE(texture.Get(), nullptr);
|
||||||
IgnoreSignalSemaphore(device, texture);
|
IgnoreSignalSemaphore(texture);
|
||||||
ASSERT_DEVICE_ERROR(int fd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(
|
|
||||||
device.Get(), texture.Get()));
|
dawn_native::vulkan::ExternalImageExportInfoDmaBuf exportInfo;
|
||||||
ASSERT_EQ(fd, -1);
|
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
|
// Test an error occurs if we try to export the signal semaphore from a normal texture
|
||||||
@ -242,9 +264,11 @@ namespace dawn_native { namespace vulkan {
|
|||||||
|
|
||||||
wgpu::Texture texture = device.CreateTexture(&defaultDescriptor);
|
wgpu::Texture texture = device.CreateTexture(&defaultDescriptor);
|
||||||
ASSERT_NE(texture.Get(), nullptr);
|
ASSERT_NE(texture.Get(), nullptr);
|
||||||
ASSERT_DEVICE_ERROR(int fd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(
|
|
||||||
device.Get(), texture.Get()));
|
dawn_native::vulkan::ExternalImageExportInfoDmaBuf exportInfo;
|
||||||
ASSERT_EQ(fd, -1);
|
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
|
// Test an error occurs if we try to export the signal semaphore from a destroyed texture
|
||||||
@ -254,9 +278,11 @@ namespace dawn_native { namespace vulkan {
|
|||||||
wgpu::Texture texture = device.CreateTexture(&defaultDescriptor);
|
wgpu::Texture texture = device.CreateTexture(&defaultDescriptor);
|
||||||
ASSERT_NE(texture.Get(), nullptr);
|
ASSERT_NE(texture.Get(), nullptr);
|
||||||
texture.Destroy();
|
texture.Destroy();
|
||||||
ASSERT_DEVICE_ERROR(int fd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(
|
|
||||||
device.Get(), texture.Get()));
|
dawn_native::vulkan::ExternalImageExportInfoDmaBuf exportInfo;
|
||||||
ASSERT_EQ(fd, -1);
|
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.
|
// Fixture to test using external memory textures through different usages.
|
||||||
@ -330,84 +356,56 @@ namespace dawn_native { namespace vulkan {
|
|||||||
// Verify clear color is visible in |device|
|
// Verify clear color is visible in |device|
|
||||||
TEST_P(VulkanImageWrappingUsageTests, ClearImageAcrossDevices) {
|
TEST_P(VulkanImageWrappingUsageTests, ClearImageAcrossDevices) {
|
||||||
// Import the image on |secondDevice|
|
// Import the image on |secondDevice|
|
||||||
wgpu::Texture wrappedTexture = WrapVulkanImage(secondDevice, &defaultDescriptor, defaultFd,
|
wgpu::Texture wrappedTexture = WrapVulkanImage(
|
||||||
defaultStride, defaultModifier, {});
|
secondDevice, &defaultDescriptor, defaultFd, defaultStride, defaultModifier, {},
|
||||||
|
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||||
|
|
||||||
// Clear |wrappedTexture| on |secondDevice|
|
// Clear |wrappedTexture| on |secondDevice|
|
||||||
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});
|
||||||
|
|
||||||
int signalFd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(secondDevice.Get(),
|
dawn_native::vulkan::ExternalImageExportInfoDmaBuf exportInfo;
|
||||||
wrappedTexture.Get());
|
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 signalFd
|
||||||
int nextFd = gbm_bo_get_fd(defaultGbmBo);
|
int nextFd = gbm_bo_get_fd(defaultGbmBo);
|
||||||
wgpu::Texture nextWrappedTexture = WrapVulkanImage(
|
wgpu::Texture nextWrappedTexture =
|
||||||
device, &defaultDescriptor, nextFd, defaultStride, defaultModifier, {signalFd});
|
WrapVulkanImage(device, &defaultDescriptor, nextFd, defaultStride, defaultModifier,
|
||||||
|
exportInfo.semaphoreHandles, exportInfo.releasedOldLayout,
|
||||||
|
exportInfo.releasedNewLayout);
|
||||||
|
|
||||||
// Verify |device| sees the changes from |secondDevice|
|
// Verify |device| sees the changes from |secondDevice|
|
||||||
EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 2, 3, 4), nextWrappedTexture, 0, 0);
|
EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 2, 3, 4), nextWrappedTexture, 0, 0);
|
||||||
|
|
||||||
IgnoreSignalSemaphore(device, nextWrappedTexture);
|
IgnoreSignalSemaphore(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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear an image in |secondDevice|
|
// Clear an image in |secondDevice|
|
||||||
// Verify clear color is not visible in |device| if we import the texture as not cleared
|
// 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|
|
// Import the image on |secondDevice|
|
||||||
wgpu::Texture wrappedTexture = WrapVulkanImage(secondDevice, &defaultDescriptor, defaultFd,
|
wgpu::Texture wrappedTexture = WrapVulkanImage(
|
||||||
defaultStride, defaultModifier, {});
|
secondDevice, &defaultDescriptor, defaultFd, defaultStride, defaultModifier, {},
|
||||||
|
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||||
|
|
||||||
// Clear |wrappedTexture| on |secondDevice|
|
// Clear |wrappedTexture| on |secondDevice|
|
||||||
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});
|
||||||
|
|
||||||
int signalFd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(secondDevice.Get(),
|
dawn_native::vulkan::ExternalImageExportInfoDmaBuf exportInfo;
|
||||||
wrappedTexture.Get());
|
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 signalFd
|
||||||
int nextFd = gbm_bo_get_fd(defaultGbmBo);
|
int nextFd = gbm_bo_get_fd(defaultGbmBo);
|
||||||
wgpu::Texture nextWrappedTexture = WrapVulkanImage(
|
wgpu::Texture nextWrappedTexture =
|
||||||
device, &defaultDescriptor, nextFd, defaultStride, defaultModifier, {signalFd}, false);
|
WrapVulkanImage(device, &defaultDescriptor, nextFd, defaultStride, defaultModifier,
|
||||||
|
exportInfo.semaphoreHandles, exportInfo.releasedOldLayout,
|
||||||
|
exportInfo.releasedNewLayout, false);
|
||||||
|
|
||||||
// Verify |device| doesn't see the changes from |secondDevice|
|
// Verify |device| doesn't see the changes from |secondDevice|
|
||||||
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), nextWrappedTexture, 0, 0);
|
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), nextWrappedTexture, 0, 0);
|
||||||
|
|
||||||
IgnoreSignalSemaphore(device, nextWrappedTexture);
|
IgnoreSignalSemaphore(nextWrappedTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Import a texture into |secondDevice|
|
// Import a texture into |secondDevice|
|
||||||
@ -416,19 +414,23 @@ namespace dawn_native { namespace vulkan {
|
|||||||
// Verify the clear color from |secondDevice| is visible in |copyDstTexture|
|
// Verify the clear color from |secondDevice| is visible in |copyDstTexture|
|
||||||
TEST_P(VulkanImageWrappingUsageTests, CopyTextureToTextureSrcSync) {
|
TEST_P(VulkanImageWrappingUsageTests, CopyTextureToTextureSrcSync) {
|
||||||
// Import the image on |secondDevice|
|
// Import the image on |secondDevice|
|
||||||
wgpu::Texture wrappedTexture = WrapVulkanImage(secondDevice, &defaultDescriptor, defaultFd,
|
wgpu::Texture wrappedTexture = WrapVulkanImage(
|
||||||
defaultStride, defaultModifier, {});
|
secondDevice, &defaultDescriptor, defaultFd, defaultStride, defaultModifier, {},
|
||||||
|
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||||
|
|
||||||
// Clear |wrappedTexture| on |secondDevice|
|
// Clear |wrappedTexture| on |secondDevice|
|
||||||
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});
|
||||||
|
|
||||||
int signalFd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(secondDevice.Get(),
|
dawn_native::vulkan::ExternalImageExportInfoDmaBuf exportInfo;
|
||||||
wrappedTexture.Get());
|
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 |signalFd|
|
||||||
int nextFd = gbm_bo_get_fd(defaultGbmBo);
|
int nextFd = gbm_bo_get_fd(defaultGbmBo);
|
||||||
wgpu::Texture deviceWrappedTexture = WrapVulkanImage(
|
wgpu::Texture deviceWrappedTexture =
|
||||||
device, &defaultDescriptor, nextFd, defaultStride, defaultModifier, {signalFd});
|
WrapVulkanImage(device, &defaultDescriptor, nextFd, defaultStride, defaultModifier,
|
||||||
|
exportInfo.semaphoreHandles, exportInfo.releasedOldLayout,
|
||||||
|
exportInfo.releasedNewLayout);
|
||||||
|
|
||||||
// Create a second texture on |device|
|
// Create a second texture on |device|
|
||||||
wgpu::Texture copyDstTexture = device.CreateTexture(&defaultDescriptor);
|
wgpu::Texture copyDstTexture = device.CreateTexture(&defaultDescriptor);
|
||||||
@ -439,7 +441,7 @@ namespace dawn_native { namespace vulkan {
|
|||||||
// Verify |copyDstTexture| sees changes from |secondDevice|
|
// Verify |copyDstTexture| sees changes from |secondDevice|
|
||||||
EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 2, 3, 4), copyDstTexture, 0, 0);
|
EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 2, 3, 4), copyDstTexture, 0, 0);
|
||||||
|
|
||||||
IgnoreSignalSemaphore(device, deviceWrappedTexture);
|
IgnoreSignalSemaphore(deviceWrappedTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Import a texture into |device|
|
// Import a texture into |device|
|
||||||
@ -453,19 +455,23 @@ namespace dawn_native { namespace vulkan {
|
|||||||
// into the texture first, then |device| writes color A
|
// into the texture first, then |device| writes color A
|
||||||
TEST_P(VulkanImageWrappingUsageTests, CopyTextureToTextureDstSync) {
|
TEST_P(VulkanImageWrappingUsageTests, CopyTextureToTextureDstSync) {
|
||||||
// Import the image on |device|
|
// Import the image on |device|
|
||||||
wgpu::Texture wrappedTexture = WrapVulkanImage(device, &defaultDescriptor, defaultFd,
|
wgpu::Texture wrappedTexture = WrapVulkanImage(
|
||||||
defaultStride, defaultModifier, {});
|
device, &defaultDescriptor, defaultFd, defaultStride, defaultModifier, {},
|
||||||
|
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||||
|
|
||||||
// Clear |wrappedTexture| on |device|
|
// Clear |wrappedTexture| on |device|
|
||||||
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});
|
||||||
|
|
||||||
int signalFd =
|
dawn_native::vulkan::ExternalImageExportInfoDmaBuf exportInfo;
|
||||||
dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(device.Get(), wrappedTexture.Get());
|
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 |signalFd|
|
||||||
int nextFd = gbm_bo_get_fd(defaultGbmBo);
|
int nextFd = gbm_bo_get_fd(defaultGbmBo);
|
||||||
wgpu::Texture secondDeviceWrappedTexture = WrapVulkanImage(
|
wgpu::Texture secondDeviceWrappedTexture =
|
||||||
secondDevice, &defaultDescriptor, nextFd, defaultStride, defaultModifier, {signalFd});
|
WrapVulkanImage(secondDevice, &defaultDescriptor, nextFd, defaultStride,
|
||||||
|
defaultModifier, exportInfo.semaphoreHandles,
|
||||||
|
exportInfo.releasedOldLayout, exportInfo.releasedNewLayout);
|
||||||
|
|
||||||
// Create a texture with color B on |secondDevice|
|
// Create a texture with color B on |secondDevice|
|
||||||
wgpu::Texture copySrcTexture = secondDevice.CreateTexture(&defaultDescriptor);
|
wgpu::Texture copySrcTexture = secondDevice.CreateTexture(&defaultDescriptor);
|
||||||
@ -477,17 +483,21 @@ namespace dawn_native { namespace vulkan {
|
|||||||
secondDeviceWrappedTexture);
|
secondDeviceWrappedTexture);
|
||||||
|
|
||||||
// Re-import back into |device|, waiting on |secondDevice|'s signal
|
// Re-import back into |device|, waiting on |secondDevice|'s signal
|
||||||
signalFd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(
|
dawn_native::vulkan::ExternalImageExportInfoDmaBuf secondExportInfo;
|
||||||
secondDevice.Get(), secondDeviceWrappedTexture.Get());
|
dawn_native::vulkan::ExportVulkanImage(secondDeviceWrappedTexture.Get(),
|
||||||
|
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||||
|
&secondExportInfo);
|
||||||
nextFd = gbm_bo_get_fd(defaultGbmBo);
|
nextFd = gbm_bo_get_fd(defaultGbmBo);
|
||||||
|
|
||||||
wgpu::Texture nextWrappedTexture = WrapVulkanImage(
|
wgpu::Texture nextWrappedTexture =
|
||||||
device, &defaultDescriptor, nextFd, defaultStride, defaultModifier, {signalFd});
|
WrapVulkanImage(device, &defaultDescriptor, nextFd, defaultStride, defaultModifier,
|
||||||
|
secondExportInfo.semaphoreHandles, secondExportInfo.releasedOldLayout,
|
||||||
|
secondExportInfo.releasedNewLayout);
|
||||||
|
|
||||||
// Verify |nextWrappedTexture| contains the color from our copy
|
// Verify |nextWrappedTexture| contains the color from our copy
|
||||||
EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 2, 3, 4), nextWrappedTexture, 0, 0);
|
EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 2, 3, 4), nextWrappedTexture, 0, 0);
|
||||||
|
|
||||||
IgnoreSignalSemaphore(device, nextWrappedTexture);
|
IgnoreSignalSemaphore(nextWrappedTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Import a texture from |secondDevice|
|
// Import a texture from |secondDevice|
|
||||||
@ -496,19 +506,23 @@ namespace dawn_native { namespace vulkan {
|
|||||||
// Verify the clear color from |secondDevice| is visible in |copyDstBuffer|
|
// Verify the clear color from |secondDevice| is visible in |copyDstBuffer|
|
||||||
TEST_P(VulkanImageWrappingUsageTests, CopyTextureToBufferSrcSync) {
|
TEST_P(VulkanImageWrappingUsageTests, CopyTextureToBufferSrcSync) {
|
||||||
// Import the image on |secondDevice|
|
// Import the image on |secondDevice|
|
||||||
wgpu::Texture wrappedTexture = WrapVulkanImage(secondDevice, &defaultDescriptor, defaultFd,
|
wgpu::Texture wrappedTexture = WrapVulkanImage(
|
||||||
defaultStride, defaultModifier, {});
|
secondDevice, &defaultDescriptor, defaultFd, defaultStride, defaultModifier, {},
|
||||||
|
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||||
|
|
||||||
// Clear |wrappedTexture| on |secondDevice|
|
// Clear |wrappedTexture| on |secondDevice|
|
||||||
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});
|
||||||
|
|
||||||
int signalFd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(secondDevice.Get(),
|
dawn_native::vulkan::ExternalImageExportInfoDmaBuf exportInfo;
|
||||||
wrappedTexture.Get());
|
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 |signalFd|
|
||||||
int nextFd = gbm_bo_get_fd(defaultGbmBo);
|
int nextFd = gbm_bo_get_fd(defaultGbmBo);
|
||||||
wgpu::Texture deviceWrappedTexture = WrapVulkanImage(
|
wgpu::Texture deviceWrappedTexture =
|
||||||
device, &defaultDescriptor, nextFd, defaultStride, defaultModifier, {signalFd});
|
WrapVulkanImage(device, &defaultDescriptor, nextFd, defaultStride, defaultModifier,
|
||||||
|
exportInfo.semaphoreHandles, exportInfo.releasedOldLayout,
|
||||||
|
exportInfo.releasedNewLayout);
|
||||||
|
|
||||||
// Create a destination buffer on |device|
|
// Create a destination buffer on |device|
|
||||||
wgpu::BufferDescriptor bufferDesc;
|
wgpu::BufferDescriptor bufferDesc;
|
||||||
@ -532,7 +546,7 @@ namespace dawn_native { namespace vulkan {
|
|||||||
uint32_t expected = 1;
|
uint32_t expected = 1;
|
||||||
EXPECT_BUFFER_U32_EQ(expected, copyDstBuffer, 0);
|
EXPECT_BUFFER_U32_EQ(expected, copyDstBuffer, 0);
|
||||||
|
|
||||||
IgnoreSignalSemaphore(device, deviceWrappedTexture);
|
IgnoreSignalSemaphore(deviceWrappedTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Import a texture into |device|
|
// Import a texture into |device|
|
||||||
@ -545,19 +559,23 @@ namespace dawn_native { namespace vulkan {
|
|||||||
// into the texture first, then |device| writes color A
|
// into the texture first, then |device| writes color A
|
||||||
TEST_P(VulkanImageWrappingUsageTests, CopyBufferToTextureDstSync) {
|
TEST_P(VulkanImageWrappingUsageTests, CopyBufferToTextureDstSync) {
|
||||||
// Import the image on |device|
|
// Import the image on |device|
|
||||||
wgpu::Texture wrappedTexture = WrapVulkanImage(device, &defaultDescriptor, defaultFd,
|
wgpu::Texture wrappedTexture = WrapVulkanImage(
|
||||||
defaultStride, defaultModifier, {});
|
device, &defaultDescriptor, defaultFd, defaultStride, defaultModifier, {},
|
||||||
|
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||||
|
|
||||||
// Clear |wrappedTexture| on |device|
|
// Clear |wrappedTexture| on |device|
|
||||||
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});
|
||||||
|
|
||||||
int signalFd =
|
dawn_native::vulkan::ExternalImageExportInfoDmaBuf exportInfo;
|
||||||
dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(device.Get(), wrappedTexture.Get());
|
dawn_native::vulkan::ExportVulkanImage(wrappedTexture.Get(),
|
||||||
|
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|
|
||||||
int nextFd = gbm_bo_get_fd(defaultGbmBo);
|
int nextFd = gbm_bo_get_fd(defaultGbmBo);
|
||||||
wgpu::Texture secondDeviceWrappedTexture = WrapVulkanImage(
|
wgpu::Texture secondDeviceWrappedTexture =
|
||||||
secondDevice, &defaultDescriptor, nextFd, defaultStride, defaultModifier, {signalFd});
|
WrapVulkanImage(secondDevice, &defaultDescriptor, nextFd, defaultStride,
|
||||||
|
defaultModifier, exportInfo.semaphoreHandles,
|
||||||
|
exportInfo.releasedOldLayout, exportInfo.releasedNewLayout);
|
||||||
|
|
||||||
// Copy color B on |secondDevice|
|
// Copy color B on |secondDevice|
|
||||||
wgpu::Queue secondDeviceQueue = secondDevice.GetDefaultQueue();
|
wgpu::Queue secondDeviceQueue = secondDevice.GetDefaultQueue();
|
||||||
@ -579,17 +597,21 @@ namespace dawn_native { namespace vulkan {
|
|||||||
secondDeviceQueue.Submit(1, &commands);
|
secondDeviceQueue.Submit(1, &commands);
|
||||||
|
|
||||||
// Re-import back into |device|, waiting on |secondDevice|'s signal
|
// Re-import back into |device|, waiting on |secondDevice|'s signal
|
||||||
signalFd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(
|
dawn_native::vulkan::ExternalImageExportInfoDmaBuf secondExportInfo;
|
||||||
secondDevice.Get(), secondDeviceWrappedTexture.Get());
|
dawn_native::vulkan::ExportVulkanImage(secondDeviceWrappedTexture.Get(),
|
||||||
|
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||||
|
&secondExportInfo);
|
||||||
nextFd = gbm_bo_get_fd(defaultGbmBo);
|
nextFd = gbm_bo_get_fd(defaultGbmBo);
|
||||||
|
|
||||||
wgpu::Texture nextWrappedTexture = WrapVulkanImage(
|
wgpu::Texture nextWrappedTexture =
|
||||||
device, &defaultDescriptor, nextFd, defaultStride, defaultModifier, {signalFd});
|
WrapVulkanImage(device, &defaultDescriptor, nextFd, defaultStride, defaultModifier,
|
||||||
|
secondExportInfo.semaphoreHandles, secondExportInfo.releasedOldLayout,
|
||||||
|
secondExportInfo.releasedNewLayout);
|
||||||
|
|
||||||
// Verify |nextWrappedTexture| contains the color from our copy
|
// Verify |nextWrappedTexture| contains the color from our copy
|
||||||
EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 2, 3, 4), nextWrappedTexture, 0, 0);
|
EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 2, 3, 4), nextWrappedTexture, 0, 0);
|
||||||
|
|
||||||
IgnoreSignalSemaphore(device, nextWrappedTexture);
|
IgnoreSignalSemaphore(nextWrappedTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Import a texture from |secondDevice|
|
// Import a texture from |secondDevice|
|
||||||
@ -599,19 +621,23 @@ namespace dawn_native { namespace vulkan {
|
|||||||
// Verify the clear color from |secondDevice| is visible in both copies
|
// Verify the clear color from |secondDevice| is visible in both copies
|
||||||
TEST_P(VulkanImageWrappingUsageTests, DoubleTextureUsage) {
|
TEST_P(VulkanImageWrappingUsageTests, DoubleTextureUsage) {
|
||||||
// Import the image on |secondDevice|
|
// Import the image on |secondDevice|
|
||||||
wgpu::Texture wrappedTexture = WrapVulkanImage(secondDevice, &defaultDescriptor, defaultFd,
|
wgpu::Texture wrappedTexture = WrapVulkanImage(
|
||||||
defaultStride, defaultModifier, {});
|
secondDevice, &defaultDescriptor, defaultFd, defaultStride, defaultModifier, {},
|
||||||
|
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||||
|
|
||||||
// Clear |wrappedTexture| on |secondDevice|
|
// Clear |wrappedTexture| on |secondDevice|
|
||||||
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});
|
||||||
|
|
||||||
int signalFd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(secondDevice.Get(),
|
dawn_native::vulkan::ExternalImageExportInfoDmaBuf exportInfo;
|
||||||
wrappedTexture.Get());
|
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 |signalFd|
|
||||||
int nextFd = gbm_bo_get_fd(defaultGbmBo);
|
int nextFd = gbm_bo_get_fd(defaultGbmBo);
|
||||||
wgpu::Texture deviceWrappedTexture = WrapVulkanImage(
|
wgpu::Texture deviceWrappedTexture =
|
||||||
device, &defaultDescriptor, nextFd, defaultStride, defaultModifier, {signalFd});
|
WrapVulkanImage(device, &defaultDescriptor, nextFd, defaultStride, defaultModifier,
|
||||||
|
exportInfo.semaphoreHandles, exportInfo.releasedOldLayout,
|
||||||
|
exportInfo.releasedNewLayout);
|
||||||
|
|
||||||
// Create a second texture on |device|
|
// Create a second texture on |device|
|
||||||
wgpu::Texture copyDstTexture = device.CreateTexture(&defaultDescriptor);
|
wgpu::Texture copyDstTexture = device.CreateTexture(&defaultDescriptor);
|
||||||
@ -631,7 +657,7 @@ namespace dawn_native { namespace vulkan {
|
|||||||
// Verify |secondCopyDstTexture| sees changes from |secondDevice|
|
// Verify |secondCopyDstTexture| sees changes from |secondDevice|
|
||||||
EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 2, 3, 4), secondCopyDstTexture, 0, 0);
|
EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 2, 3, 4), secondCopyDstTexture, 0, 0);
|
||||||
|
|
||||||
IgnoreSignalSemaphore(device, deviceWrappedTexture);
|
IgnoreSignalSemaphore(deviceWrappedTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tex A on device 3 (external export)
|
// Tex A on device 3 (external export)
|
||||||
@ -676,10 +702,12 @@ namespace dawn_native { namespace vulkan {
|
|||||||
|
|
||||||
// Import TexA, TexB on device 3
|
// Import TexA, TexB on device 3
|
||||||
wgpu::Texture wrappedTexADevice3 =
|
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 =
|
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
|
// Clear TexA
|
||||||
ClearImage(thirdDevice, wrappedTexADevice3,
|
ClearImage(thirdDevice, wrappedTexADevice3,
|
||||||
@ -689,30 +717,37 @@ namespace dawn_native { namespace vulkan {
|
|||||||
SimpleCopyTextureToTexture(thirdDevice, thirdDeviceQueue, wrappedTexADevice3,
|
SimpleCopyTextureToTexture(thirdDevice, thirdDeviceQueue, wrappedTexADevice3,
|
||||||
wrappedTexBDevice3);
|
wrappedTexBDevice3);
|
||||||
|
|
||||||
int signalFdTexBDevice3 = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(
|
dawn_native::vulkan::ExternalImageExportInfoDmaBuf exportInfoTexBDevice3;
|
||||||
thirdDevice.Get(), wrappedTexBDevice3.Get());
|
dawn_native::vulkan::ExportVulkanImage(
|
||||||
IgnoreSignalSemaphore(thirdDevice, wrappedTexADevice3);
|
wrappedTexBDevice3.Get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, &exportInfoTexBDevice3);
|
||||||
|
IgnoreSignalSemaphore(wrappedTexADevice3);
|
||||||
|
|
||||||
// Import TexB, TexC on device 2
|
// Import TexB, TexC on device 2
|
||||||
fdB = gbm_bo_get_fd(gbmBoB);
|
fdB = gbm_bo_get_fd(gbmBoB);
|
||||||
wgpu::Texture wrappedTexBDevice2 = WrapVulkanImage(
|
wgpu::Texture wrappedTexBDevice2 = WrapVulkanImage(
|
||||||
secondDevice, &defaultDescriptor, fdB, strideB, modifierB, {signalFdTexBDevice3});
|
secondDevice, &defaultDescriptor, fdB, strideB, modifierB,
|
||||||
|
exportInfoTexBDevice3.semaphoreHandles, exportInfoTexBDevice3.releasedOldLayout,
|
||||||
|
exportInfoTexBDevice3.releasedNewLayout);
|
||||||
|
|
||||||
wgpu::Texture wrappedTexCDevice2 =
|
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
|
// Copy B->C on device 2
|
||||||
SimpleCopyTextureToTexture(secondDevice, secondDeviceQueue, wrappedTexBDevice2,
|
SimpleCopyTextureToTexture(secondDevice, secondDeviceQueue, wrappedTexBDevice2,
|
||||||
wrappedTexCDevice2);
|
wrappedTexCDevice2);
|
||||||
|
|
||||||
int signalFdTexCDevice2 = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(
|
dawn_native::vulkan::ExternalImageExportInfoDmaBuf exportInfoTexCDevice2;
|
||||||
secondDevice.Get(), wrappedTexCDevice2.Get());
|
dawn_native::vulkan::ExportVulkanImage(
|
||||||
IgnoreSignalSemaphore(secondDevice, wrappedTexBDevice2);
|
wrappedTexCDevice2.Get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, &exportInfoTexCDevice2);
|
||||||
|
IgnoreSignalSemaphore(wrappedTexBDevice2);
|
||||||
|
|
||||||
// Import TexC on device 1
|
// Import TexC on device 1
|
||||||
fdC = gbm_bo_get_fd(gbmBoC);
|
fdC = gbm_bo_get_fd(gbmBoC);
|
||||||
wgpu::Texture wrappedTexCDevice1 = WrapVulkanImage(device, &defaultDescriptor, fdC, strideC,
|
wgpu::Texture wrappedTexCDevice1 = WrapVulkanImage(
|
||||||
modifierC, {signalFdTexCDevice2});
|
device, &defaultDescriptor, fdC, strideC, modifierC,
|
||||||
|
exportInfoTexCDevice2.semaphoreHandles, exportInfoTexCDevice2.releasedOldLayout,
|
||||||
|
exportInfoTexCDevice2.releasedNewLayout);
|
||||||
|
|
||||||
// Create TexD on device 1
|
// Create TexD on device 1
|
||||||
wgpu::Texture texD = device.CreateTexture(&defaultDescriptor);
|
wgpu::Texture texD = device.CreateTexture(&defaultDescriptor);
|
||||||
@ -723,7 +758,7 @@ namespace dawn_native { namespace vulkan {
|
|||||||
// Verify D matches clear color
|
// Verify D matches clear color
|
||||||
EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 2, 3, 4), texD, 0, 0);
|
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
|
// Tests a larger image is preserved when importing
|
||||||
@ -756,7 +791,8 @@ namespace dawn_native { namespace vulkan {
|
|||||||
|
|
||||||
// Import the image on |secondDevice|
|
// Import the image on |secondDevice|
|
||||||
wgpu::Texture wrappedTexture =
|
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
|
// Draw a non-trivial picture
|
||||||
uint32_t width = 640, height = 480, pixelSize = 4;
|
uint32_t width = 640, height = 480, pixelSize = 4;
|
||||||
@ -791,14 +827,15 @@ namespace dawn_native { namespace vulkan {
|
|||||||
wgpu::CommandBuffer commands = encoder.Finish();
|
wgpu::CommandBuffer commands = encoder.Finish();
|
||||||
secondDeviceQueue.Submit(1, &commands);
|
secondDeviceQueue.Submit(1, &commands);
|
||||||
}
|
}
|
||||||
|
dawn_native::vulkan::ExternalImageExportInfoDmaBuf exportInfo;
|
||||||
int signalFd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(secondDevice.Get(),
|
dawn_native::vulkan::ExportVulkanImage(wrappedTexture.Get(),
|
||||||
wrappedTexture.Get());
|
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, &exportInfo);
|
||||||
int nextFd = gbm_bo_get_fd(gbmBo);
|
int nextFd = gbm_bo_get_fd(gbmBo);
|
||||||
|
|
||||||
// Import the image on |device|
|
// Import the image on |device|
|
||||||
wgpu::Texture nextWrappedTexture =
|
wgpu::Texture nextWrappedTexture = WrapVulkanImage(
|
||||||
WrapVulkanImage(device, &descriptor, nextFd, stride, modifier, {signalFd});
|
device, &descriptor, nextFd, stride, modifier, exportInfo.semaphoreHandles,
|
||||||
|
exportInfo.releasedOldLayout, exportInfo.releasedNewLayout);
|
||||||
|
|
||||||
// Copy the image into a buffer for comparison
|
// Copy the image into a buffer for comparison
|
||||||
wgpu::BufferDescriptor copyDesc;
|
wgpu::BufferDescriptor copyDesc;
|
||||||
@ -823,7 +860,7 @@ namespace dawn_native { namespace vulkan {
|
|||||||
EXPECT_BUFFER_U32_RANGE_EQ(reinterpret_cast<uint32_t*>(data.data()), copyDstBuffer, 0,
|
EXPECT_BUFFER_U32_RANGE_EQ(reinterpret_cast<uint32_t*>(data.data()), copyDstBuffer, 0,
|
||||||
data.size() / 4);
|
data.size() / 4);
|
||||||
|
|
||||||
IgnoreSignalSemaphore(device, nextWrappedTexture);
|
IgnoreSignalSemaphore(nextWrappedTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
DAWN_INSTANTIATE_TEST(VulkanImageWrappingValidationTests, VulkanBackend());
|
DAWN_INSTANTIATE_TEST(VulkanImageWrappingValidationTests, VulkanBackend());
|
||||||
|
@ -157,16 +157,34 @@ namespace dawn_native { namespace vulkan {
|
|||||||
VkDeviceSize allocationSize,
|
VkDeviceSize allocationSize,
|
||||||
uint32_t memoryTypeIndex,
|
uint32_t memoryTypeIndex,
|
||||||
std::vector<int> waitFDs,
|
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) {
|
bool expectValid = true) {
|
||||||
dawn_native::vulkan::ExternalImageDescriptorOpaqueFD descriptor;
|
dawn_native::vulkan::ExternalImageDescriptorOpaqueFD descriptor;
|
||||||
descriptor.cTextureDescriptor =
|
descriptor.cTextureDescriptor =
|
||||||
reinterpret_cast<const WGPUTextureDescriptor*>(textureDescriptor);
|
reinterpret_cast<const WGPUTextureDescriptor*>(textureDescriptor);
|
||||||
descriptor.isCleared = isCleared;
|
descriptor.isInitialized = isInitialized;
|
||||||
descriptor.allocationSize = allocationSize;
|
descriptor.allocationSize = allocationSize;
|
||||||
descriptor.memoryTypeIndex = memoryTypeIndex;
|
descriptor.memoryTypeIndex = memoryTypeIndex;
|
||||||
descriptor.memoryFD = memoryFd;
|
descriptor.memoryFD = memoryFd;
|
||||||
descriptor.waitFDs = waitFDs;
|
descriptor.waitFDs = waitFDs;
|
||||||
|
descriptor.releasedOldLayout = releasedOldLayout;
|
||||||
|
descriptor.releasedNewLayout = releasedNewLayout;
|
||||||
|
|
||||||
WGPUTexture texture =
|
WGPUTexture texture =
|
||||||
dawn_native::vulkan::WrapVulkanImage(dawnDevice.Get(), &descriptor);
|
dawn_native::vulkan::WrapVulkanImage(dawnDevice.Get(), &descriptor);
|
||||||
@ -184,11 +202,14 @@ namespace dawn_native { namespace vulkan {
|
|||||||
// Exports the signal from a wrapped texture and ignores it
|
// 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
|
// We have to export the signal before destroying the wrapped texture else it's an
|
||||||
// assertion failure
|
// assertion failure
|
||||||
void IgnoreSignalSemaphore(wgpu::Device dawnDevice, wgpu::Texture wrappedTexture) {
|
void IgnoreSignalSemaphore(wgpu::Texture wrappedTexture) {
|
||||||
int fd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(dawnDevice.Get(),
|
dawn_native::vulkan::ExternalImageExportInfoOpaqueFD info;
|
||||||
wrappedTexture.Get());
|
dawn_native::vulkan::ExportVulkanImage(wrappedTexture.Get(),
|
||||||
ASSERT_NE(fd, -1);
|
VK_IMAGE_LAYOUT_GENERAL, &info);
|
||||||
close(fd);
|
for (int handle : info.semaphoreHandles) {
|
||||||
|
ASSERT_NE(handle, -1);
|
||||||
|
close(handle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -244,7 +265,7 @@ namespace dawn_native { namespace vulkan {
|
|||||||
WrapVulkanImage(device, &defaultDescriptor, defaultFd, defaultAllocationSize,
|
WrapVulkanImage(device, &defaultDescriptor, defaultFd, defaultAllocationSize,
|
||||||
defaultMemoryTypeIndex, {}, true, true);
|
defaultMemoryTypeIndex, {}, true, true);
|
||||||
EXPECT_NE(texture.Get(), nullptr);
|
EXPECT_NE(texture.Get(), nullptr);
|
||||||
IgnoreSignalSemaphore(device, texture);
|
IgnoreSignalSemaphore(texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test an error occurs if the texture descriptor is missing
|
// Test an error occurs if the texture descriptor is missing
|
||||||
@ -319,10 +340,12 @@ namespace dawn_native { namespace vulkan {
|
|||||||
WrapVulkanImage(device, &defaultDescriptor, defaultFd, defaultAllocationSize,
|
WrapVulkanImage(device, &defaultDescriptor, defaultFd, defaultAllocationSize,
|
||||||
defaultMemoryTypeIndex, {}, true, true);
|
defaultMemoryTypeIndex, {}, true, true);
|
||||||
ASSERT_NE(texture.Get(), nullptr);
|
ASSERT_NE(texture.Get(), nullptr);
|
||||||
IgnoreSignalSemaphore(device, texture);
|
IgnoreSignalSemaphore(texture);
|
||||||
ASSERT_DEVICE_ERROR(int fd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(
|
|
||||||
device.Get(), texture.Get()));
|
dawn_native::vulkan::ExternalImageExportInfoOpaqueFD exportInfo;
|
||||||
ASSERT_EQ(fd, -1);
|
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
|
// Test an error occurs if we try to export the signal semaphore from a normal texture
|
||||||
@ -330,9 +353,11 @@ namespace dawn_native { namespace vulkan {
|
|||||||
DAWN_SKIP_TEST_IF(UsesWire());
|
DAWN_SKIP_TEST_IF(UsesWire());
|
||||||
wgpu::Texture texture = device.CreateTexture(&defaultDescriptor);
|
wgpu::Texture texture = device.CreateTexture(&defaultDescriptor);
|
||||||
ASSERT_NE(texture.Get(), nullptr);
|
ASSERT_NE(texture.Get(), nullptr);
|
||||||
ASSERT_DEVICE_ERROR(int fd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(
|
|
||||||
device.Get(), texture.Get()));
|
dawn_native::vulkan::ExternalImageExportInfoOpaqueFD exportInfo;
|
||||||
ASSERT_EQ(fd, -1);
|
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
|
// Test an error occurs if we try to export the signal semaphore from a destroyed texture
|
||||||
@ -341,9 +366,11 @@ namespace dawn_native { namespace vulkan {
|
|||||||
wgpu::Texture texture = device.CreateTexture(&defaultDescriptor);
|
wgpu::Texture texture = device.CreateTexture(&defaultDescriptor);
|
||||||
ASSERT_NE(texture.Get(), nullptr);
|
ASSERT_NE(texture.Get(), nullptr);
|
||||||
texture.Destroy();
|
texture.Destroy();
|
||||||
ASSERT_DEVICE_ERROR(int fd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(
|
|
||||||
device.Get(), texture.Get()));
|
dawn_native::vulkan::ExternalImageExportInfoOpaqueFD exportInfo;
|
||||||
ASSERT_EQ(fd, -1);
|
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.
|
// Fixture to test using external memory textures through different usages.
|
||||||
@ -456,97 +483,58 @@ namespace dawn_native { namespace vulkan {
|
|||||||
// Import the image on |secondDevice|
|
// Import the image on |secondDevice|
|
||||||
wgpu::Texture wrappedTexture =
|
wgpu::Texture wrappedTexture =
|
||||||
WrapVulkanImage(secondDevice, &defaultDescriptor, defaultFd, defaultAllocationSize,
|
WrapVulkanImage(secondDevice, &defaultDescriptor, defaultFd, defaultAllocationSize,
|
||||||
defaultMemoryTypeIndex, {});
|
defaultMemoryTypeIndex, {}, VK_IMAGE_LAYOUT_UNDEFINED,
|
||||||
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||||
|
|
||||||
// Clear |wrappedTexture| on |secondDevice|
|
// Clear |wrappedTexture| on |secondDevice|
|
||||||
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});
|
||||||
|
|
||||||
int signalFd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(secondDevice.Get(),
|
dawn_native::vulkan::ExternalImageExportInfoOpaqueFD exportInfo;
|
||||||
wrappedTexture.Get());
|
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 signalFd
|
||||||
int memoryFd = GetMemoryFd(deviceVk, defaultAllocation);
|
int memoryFd = GetMemoryFd(deviceVk, defaultAllocation);
|
||||||
wgpu::Texture nextWrappedTexture =
|
wgpu::Texture nextWrappedTexture =
|
||||||
WrapVulkanImage(device, &defaultDescriptor, memoryFd, defaultAllocationSize,
|
WrapVulkanImage(device, &defaultDescriptor, memoryFd, defaultAllocationSize,
|
||||||
defaultMemoryTypeIndex, {signalFd});
|
defaultMemoryTypeIndex, exportInfo.semaphoreHandles,
|
||||||
|
exportInfo.releasedOldLayout, exportInfo.releasedNewLayout);
|
||||||
|
|
||||||
// Verify |device| sees the changes from |secondDevice|
|
// Verify |device| sees the changes from |secondDevice|
|
||||||
EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 2, 3, 4), nextWrappedTexture, 0, 0);
|
EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 2, 3, 4), nextWrappedTexture, 0, 0);
|
||||||
|
|
||||||
IgnoreSignalSemaphore(device, nextWrappedTexture);
|
IgnoreSignalSemaphore(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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear an image in |secondDevice|
|
// Clear an image in |secondDevice|
|
||||||
// Verify clear color is not visible in |device| if we import the texture as not cleared
|
// 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());
|
DAWN_SKIP_TEST_IF(UsesWire());
|
||||||
|
|
||||||
// Import the image on |secondDevice|
|
// Import the image on |secondDevice|
|
||||||
wgpu::Texture wrappedTexture =
|
wgpu::Texture wrappedTexture =
|
||||||
WrapVulkanImage(secondDevice, &defaultDescriptor, defaultFd, defaultAllocationSize,
|
WrapVulkanImage(secondDevice, &defaultDescriptor, defaultFd, defaultAllocationSize,
|
||||||
defaultMemoryTypeIndex, {});
|
defaultMemoryTypeIndex, {}, VK_IMAGE_LAYOUT_UNDEFINED,
|
||||||
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||||
|
|
||||||
// Clear |wrappedTexture| on |secondDevice|
|
// Clear |wrappedTexture| on |secondDevice|
|
||||||
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});
|
||||||
|
|
||||||
int signalFd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(secondDevice.Get(),
|
dawn_native::vulkan::ExternalImageExportInfoOpaqueFD exportInfo;
|
||||||
wrappedTexture.Get());
|
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);
|
int memoryFd = GetMemoryFd(deviceVk, defaultAllocation);
|
||||||
wgpu::Texture nextWrappedTexture =
|
wgpu::Texture nextWrappedTexture =
|
||||||
WrapVulkanImage(device, &defaultDescriptor, memoryFd, defaultAllocationSize,
|
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|
|
// Verify |device| doesn't see the changes from |secondDevice|
|
||||||
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), nextWrappedTexture, 0, 0);
|
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), nextWrappedTexture, 0, 0);
|
||||||
|
|
||||||
IgnoreSignalSemaphore(device, nextWrappedTexture);
|
IgnoreSignalSemaphore(nextWrappedTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Import a texture into |secondDevice|
|
// Import a texture into |secondDevice|
|
||||||
@ -558,19 +546,22 @@ namespace dawn_native { namespace vulkan {
|
|||||||
// Import the image on |secondDevice|
|
// Import the image on |secondDevice|
|
||||||
wgpu::Texture wrappedTexture =
|
wgpu::Texture wrappedTexture =
|
||||||
WrapVulkanImage(secondDevice, &defaultDescriptor, defaultFd, defaultAllocationSize,
|
WrapVulkanImage(secondDevice, &defaultDescriptor, defaultFd, defaultAllocationSize,
|
||||||
defaultMemoryTypeIndex, {});
|
defaultMemoryTypeIndex, {}, VK_IMAGE_LAYOUT_UNDEFINED,
|
||||||
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||||
|
|
||||||
// Clear |wrappedTexture| on |secondDevice|
|
// Clear |wrappedTexture| on |secondDevice|
|
||||||
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});
|
||||||
|
|
||||||
int signalFd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(secondDevice.Get(),
|
dawn_native::vulkan::ExternalImageExportInfoOpaqueFD exportInfo;
|
||||||
wrappedTexture.Get());
|
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);
|
int memoryFd = GetMemoryFd(deviceVk, defaultAllocation);
|
||||||
wgpu::Texture deviceWrappedTexture =
|
wgpu::Texture deviceWrappedTexture =
|
||||||
WrapVulkanImage(device, &defaultDescriptor, memoryFd, defaultAllocationSize,
|
WrapVulkanImage(device, &defaultDescriptor, memoryFd, defaultAllocationSize,
|
||||||
defaultMemoryTypeIndex, {signalFd});
|
defaultMemoryTypeIndex, exportInfo.semaphoreHandles,
|
||||||
|
exportInfo.releasedOldLayout, exportInfo.releasedNewLayout);
|
||||||
|
|
||||||
// Create a second texture on |device|
|
// Create a second texture on |device|
|
||||||
wgpu::Texture copyDstTexture = device.CreateTexture(&defaultDescriptor);
|
wgpu::Texture copyDstTexture = device.CreateTexture(&defaultDescriptor);
|
||||||
@ -581,7 +572,7 @@ namespace dawn_native { namespace vulkan {
|
|||||||
// Verify |copyDstTexture| sees changes from |secondDevice|
|
// Verify |copyDstTexture| sees changes from |secondDevice|
|
||||||
EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 2, 3, 4), copyDstTexture, 0, 0);
|
EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 2, 3, 4), copyDstTexture, 0, 0);
|
||||||
|
|
||||||
IgnoreSignalSemaphore(device, deviceWrappedTexture);
|
IgnoreSignalSemaphore(deviceWrappedTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Import a texture into |device|
|
// Import a texture into |device|
|
||||||
@ -596,21 +587,23 @@ namespace dawn_native { namespace vulkan {
|
|||||||
DAWN_SKIP_TEST_IF(UsesWire());
|
DAWN_SKIP_TEST_IF(UsesWire());
|
||||||
|
|
||||||
// Import the image on |device|
|
// Import the image on |device|
|
||||||
wgpu::Texture wrappedTexture =
|
wgpu::Texture wrappedTexture = WrapVulkanImage(
|
||||||
WrapVulkanImage(device, &defaultDescriptor, defaultFd, defaultAllocationSize,
|
device, &defaultDescriptor, defaultFd, defaultAllocationSize, defaultMemoryTypeIndex,
|
||||||
defaultMemoryTypeIndex, {});
|
{}, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||||
|
|
||||||
// Clear |wrappedTexture| on |device|
|
// Clear |wrappedTexture| on |device|
|
||||||
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});
|
||||||
|
|
||||||
int signalFd =
|
dawn_native::vulkan::ExternalImageExportInfoOpaqueFD exportInfo;
|
||||||
dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(device.Get(), wrappedTexture.Get());
|
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);
|
int memoryFd = GetMemoryFd(deviceVk, defaultAllocation);
|
||||||
wgpu::Texture secondDeviceWrappedTexture =
|
wgpu::Texture secondDeviceWrappedTexture =
|
||||||
WrapVulkanImage(secondDevice, &defaultDescriptor, memoryFd, defaultAllocationSize,
|
WrapVulkanImage(secondDevice, &defaultDescriptor, memoryFd, defaultAllocationSize,
|
||||||
defaultMemoryTypeIndex, {signalFd});
|
defaultMemoryTypeIndex, exportInfo.semaphoreHandles,
|
||||||
|
exportInfo.releasedOldLayout, exportInfo.releasedNewLayout);
|
||||||
|
|
||||||
// Create a texture with color B on |secondDevice|
|
// Create a texture with color B on |secondDevice|
|
||||||
wgpu::Texture copySrcTexture = secondDevice.CreateTexture(&defaultDescriptor);
|
wgpu::Texture copySrcTexture = secondDevice.CreateTexture(&defaultDescriptor);
|
||||||
@ -622,18 +615,21 @@ namespace dawn_native { namespace vulkan {
|
|||||||
secondDeviceWrappedTexture);
|
secondDeviceWrappedTexture);
|
||||||
|
|
||||||
// Re-import back into |device|, waiting on |secondDevice|'s signal
|
// Re-import back into |device|, waiting on |secondDevice|'s signal
|
||||||
signalFd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(
|
dawn_native::vulkan::ExternalImageExportInfoOpaqueFD secondExportInfo;
|
||||||
secondDevice.Get(), secondDeviceWrappedTexture.Get());
|
dawn_native::vulkan::ExportVulkanImage(secondDeviceWrappedTexture.Get(),
|
||||||
|
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||||
|
&secondExportInfo);
|
||||||
memoryFd = GetMemoryFd(deviceVk, defaultAllocation);
|
memoryFd = GetMemoryFd(deviceVk, defaultAllocation);
|
||||||
|
|
||||||
wgpu::Texture nextWrappedTexture =
|
wgpu::Texture nextWrappedTexture =
|
||||||
WrapVulkanImage(device, &defaultDescriptor, memoryFd, defaultAllocationSize,
|
WrapVulkanImage(device, &defaultDescriptor, memoryFd, defaultAllocationSize,
|
||||||
defaultMemoryTypeIndex, {signalFd});
|
defaultMemoryTypeIndex, secondExportInfo.semaphoreHandles,
|
||||||
|
secondExportInfo.releasedOldLayout, secondExportInfo.releasedNewLayout);
|
||||||
|
|
||||||
// Verify |nextWrappedTexture| contains the color from our copy
|
// Verify |nextWrappedTexture| contains the color from our copy
|
||||||
EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 2, 3, 4), nextWrappedTexture, 0, 0);
|
EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 2, 3, 4), nextWrappedTexture, 0, 0);
|
||||||
|
|
||||||
IgnoreSignalSemaphore(device, nextWrappedTexture);
|
IgnoreSignalSemaphore(nextWrappedTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Import a texture from |secondDevice|
|
// Import a texture from |secondDevice|
|
||||||
@ -645,19 +641,22 @@ namespace dawn_native { namespace vulkan {
|
|||||||
// Import the image on |secondDevice|
|
// Import the image on |secondDevice|
|
||||||
wgpu::Texture wrappedTexture =
|
wgpu::Texture wrappedTexture =
|
||||||
WrapVulkanImage(secondDevice, &defaultDescriptor, defaultFd, defaultAllocationSize,
|
WrapVulkanImage(secondDevice, &defaultDescriptor, defaultFd, defaultAllocationSize,
|
||||||
defaultMemoryTypeIndex, {});
|
defaultMemoryTypeIndex, {}, VK_IMAGE_LAYOUT_UNDEFINED,
|
||||||
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||||
|
|
||||||
// Clear |wrappedTexture| on |secondDevice|
|
// Clear |wrappedTexture| on |secondDevice|
|
||||||
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});
|
||||||
|
|
||||||
int signalFd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(secondDevice.Get(),
|
dawn_native::vulkan::ExternalImageExportInfoOpaqueFD exportInfo;
|
||||||
wrappedTexture.Get());
|
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);
|
int memoryFd = GetMemoryFd(deviceVk, defaultAllocation);
|
||||||
wgpu::Texture deviceWrappedTexture =
|
wgpu::Texture deviceWrappedTexture =
|
||||||
WrapVulkanImage(device, &defaultDescriptor, memoryFd, defaultAllocationSize,
|
WrapVulkanImage(device, &defaultDescriptor, memoryFd, defaultAllocationSize,
|
||||||
defaultMemoryTypeIndex, {signalFd});
|
defaultMemoryTypeIndex, exportInfo.semaphoreHandles,
|
||||||
|
exportInfo.releasedOldLayout, exportInfo.releasedNewLayout);
|
||||||
|
|
||||||
// Create a destination buffer on |device|
|
// Create a destination buffer on |device|
|
||||||
wgpu::BufferDescriptor bufferDesc;
|
wgpu::BufferDescriptor bufferDesc;
|
||||||
@ -681,7 +680,7 @@ namespace dawn_native { namespace vulkan {
|
|||||||
uint32_t expected = 0x04030201;
|
uint32_t expected = 0x04030201;
|
||||||
EXPECT_BUFFER_U32_EQ(expected, copyDstBuffer, 0);
|
EXPECT_BUFFER_U32_EQ(expected, copyDstBuffer, 0);
|
||||||
|
|
||||||
IgnoreSignalSemaphore(device, deviceWrappedTexture);
|
IgnoreSignalSemaphore(deviceWrappedTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Import a texture into |device|
|
// Import a texture into |device|
|
||||||
@ -696,21 +695,23 @@ namespace dawn_native { namespace vulkan {
|
|||||||
DAWN_SKIP_TEST_IF(UsesWire());
|
DAWN_SKIP_TEST_IF(UsesWire());
|
||||||
|
|
||||||
// Import the image on |device|
|
// Import the image on |device|
|
||||||
wgpu::Texture wrappedTexture =
|
wgpu::Texture wrappedTexture = WrapVulkanImage(
|
||||||
WrapVulkanImage(device, &defaultDescriptor, defaultFd, defaultAllocationSize,
|
device, &defaultDescriptor, defaultFd, defaultAllocationSize, defaultMemoryTypeIndex,
|
||||||
defaultMemoryTypeIndex, {});
|
{}, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||||
|
|
||||||
// Clear |wrappedTexture| on |device|
|
// Clear |wrappedTexture| on |device|
|
||||||
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});
|
||||||
|
|
||||||
int signalFd =
|
dawn_native::vulkan::ExternalImageExportInfoOpaqueFD exportInfo;
|
||||||
dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(device.Get(), wrappedTexture.Get());
|
dawn_native::vulkan::ExportVulkanImage(wrappedTexture.Get(),
|
||||||
|
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|
|
||||||
int memoryFd = GetMemoryFd(deviceVk, defaultAllocation);
|
int memoryFd = GetMemoryFd(deviceVk, defaultAllocation);
|
||||||
wgpu::Texture secondDeviceWrappedTexture =
|
wgpu::Texture secondDeviceWrappedTexture =
|
||||||
WrapVulkanImage(secondDevice, &defaultDescriptor, memoryFd, defaultAllocationSize,
|
WrapVulkanImage(secondDevice, &defaultDescriptor, memoryFd, defaultAllocationSize,
|
||||||
defaultMemoryTypeIndex, {signalFd});
|
defaultMemoryTypeIndex, exportInfo.semaphoreHandles,
|
||||||
|
exportInfo.releasedOldLayout, exportInfo.releasedNewLayout);
|
||||||
|
|
||||||
// Copy color B on |secondDevice|
|
// Copy color B on |secondDevice|
|
||||||
wgpu::Queue secondDeviceQueue = secondDevice.GetDefaultQueue();
|
wgpu::Queue secondDeviceQueue = secondDevice.GetDefaultQueue();
|
||||||
@ -732,18 +733,21 @@ namespace dawn_native { namespace vulkan {
|
|||||||
secondDeviceQueue.Submit(1, &commands);
|
secondDeviceQueue.Submit(1, &commands);
|
||||||
|
|
||||||
// Re-import back into |device|, waiting on |secondDevice|'s signal
|
// Re-import back into |device|, waiting on |secondDevice|'s signal
|
||||||
signalFd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(
|
dawn_native::vulkan::ExternalImageExportInfoOpaqueFD secondExportInfo;
|
||||||
secondDevice.Get(), secondDeviceWrappedTexture.Get());
|
dawn_native::vulkan::ExportVulkanImage(secondDeviceWrappedTexture.Get(),
|
||||||
|
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||||
|
&secondExportInfo);
|
||||||
memoryFd = GetMemoryFd(deviceVk, defaultAllocation);
|
memoryFd = GetMemoryFd(deviceVk, defaultAllocation);
|
||||||
|
|
||||||
wgpu::Texture nextWrappedTexture =
|
wgpu::Texture nextWrappedTexture =
|
||||||
WrapVulkanImage(device, &defaultDescriptor, memoryFd, defaultAllocationSize,
|
WrapVulkanImage(device, &defaultDescriptor, memoryFd, defaultAllocationSize,
|
||||||
defaultMemoryTypeIndex, {signalFd});
|
defaultMemoryTypeIndex, secondExportInfo.semaphoreHandles,
|
||||||
|
secondExportInfo.releasedOldLayout, secondExportInfo.releasedNewLayout);
|
||||||
|
|
||||||
// Verify |nextWrappedTexture| contains the color from our copy
|
// Verify |nextWrappedTexture| contains the color from our copy
|
||||||
EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 2, 3, 4), nextWrappedTexture, 0, 0);
|
EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 2, 3, 4), nextWrappedTexture, 0, 0);
|
||||||
|
|
||||||
IgnoreSignalSemaphore(device, nextWrappedTexture);
|
IgnoreSignalSemaphore(nextWrappedTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Import a texture from |secondDevice|
|
// Import a texture from |secondDevice|
|
||||||
@ -756,19 +760,22 @@ namespace dawn_native { namespace vulkan {
|
|||||||
// Import the image on |secondDevice|
|
// Import the image on |secondDevice|
|
||||||
wgpu::Texture wrappedTexture =
|
wgpu::Texture wrappedTexture =
|
||||||
WrapVulkanImage(secondDevice, &defaultDescriptor, defaultFd, defaultAllocationSize,
|
WrapVulkanImage(secondDevice, &defaultDescriptor, defaultFd, defaultAllocationSize,
|
||||||
defaultMemoryTypeIndex, {});
|
defaultMemoryTypeIndex, {}, VK_IMAGE_LAYOUT_UNDEFINED,
|
||||||
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||||
|
|
||||||
// Clear |wrappedTexture| on |secondDevice|
|
// Clear |wrappedTexture| on |secondDevice|
|
||||||
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});
|
||||||
|
|
||||||
int signalFd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(secondDevice.Get(),
|
dawn_native::vulkan::ExternalImageExportInfoOpaqueFD exportInfo;
|
||||||
wrappedTexture.Get());
|
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);
|
int memoryFd = GetMemoryFd(deviceVk, defaultAllocation);
|
||||||
wgpu::Texture deviceWrappedTexture =
|
wgpu::Texture deviceWrappedTexture =
|
||||||
WrapVulkanImage(device, &defaultDescriptor, memoryFd, defaultAllocationSize,
|
WrapVulkanImage(device, &defaultDescriptor, memoryFd, defaultAllocationSize,
|
||||||
defaultMemoryTypeIndex, {signalFd});
|
defaultMemoryTypeIndex, exportInfo.semaphoreHandles,
|
||||||
|
exportInfo.releasedOldLayout, exportInfo.releasedNewLayout);
|
||||||
|
|
||||||
// Create a second texture on |device|
|
// Create a second texture on |device|
|
||||||
wgpu::Texture copyDstTexture = device.CreateTexture(&defaultDescriptor);
|
wgpu::Texture copyDstTexture = device.CreateTexture(&defaultDescriptor);
|
||||||
@ -788,7 +795,7 @@ namespace dawn_native { namespace vulkan {
|
|||||||
// Verify |secondCopyDstTexture| sees changes from |secondDevice|
|
// Verify |secondCopyDstTexture| sees changes from |secondDevice|
|
||||||
EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 2, 3, 4), secondCopyDstTexture, 0, 0);
|
EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 2, 3, 4), secondCopyDstTexture, 0, 0);
|
||||||
|
|
||||||
IgnoreSignalSemaphore(device, deviceWrappedTexture);
|
IgnoreSignalSemaphore(deviceWrappedTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tex A on device 3 (external export)
|
// Tex A on device 3 (external export)
|
||||||
@ -844,10 +851,12 @@ namespace dawn_native { namespace vulkan {
|
|||||||
|
|
||||||
// Import TexA, TexB on device 3
|
// Import TexA, TexB on device 3
|
||||||
wgpu::Texture wrappedTexADevice3 = WrapVulkanImage(
|
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(
|
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
|
// Clear TexA
|
||||||
ClearImage(thirdDevice, wrappedTexADevice3,
|
ClearImage(thirdDevice, wrappedTexADevice3,
|
||||||
@ -857,32 +866,39 @@ namespace dawn_native { namespace vulkan {
|
|||||||
SimpleCopyTextureToTexture(thirdDevice, thirdDeviceQueue, wrappedTexADevice3,
|
SimpleCopyTextureToTexture(thirdDevice, thirdDeviceQueue, wrappedTexADevice3,
|
||||||
wrappedTexBDevice3);
|
wrappedTexBDevice3);
|
||||||
|
|
||||||
int signalFdTexBDevice3 = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(
|
dawn_native::vulkan::ExternalImageExportInfoOpaqueFD exportInfoTexBDevice3;
|
||||||
thirdDevice.Get(), wrappedTexBDevice3.Get());
|
dawn_native::vulkan::ExportVulkanImage(
|
||||||
IgnoreSignalSemaphore(thirdDevice, wrappedTexADevice3);
|
wrappedTexBDevice3.Get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, &exportInfoTexBDevice3);
|
||||||
|
|
||||||
|
IgnoreSignalSemaphore(wrappedTexADevice3);
|
||||||
|
|
||||||
// Import TexB, TexC on device 2
|
// Import TexB, TexC on device 2
|
||||||
memoryFdB = GetMemoryFd(secondDeviceVk, allocationB);
|
memoryFdB = GetMemoryFd(secondDeviceVk, allocationB);
|
||||||
wgpu::Texture wrappedTexBDevice2 =
|
wgpu::Texture wrappedTexBDevice2 = WrapVulkanImage(
|
||||||
WrapVulkanImage(secondDevice, &defaultDescriptor, memoryFdB, allocationSizeB,
|
secondDevice, &defaultDescriptor, memoryFdB, allocationSizeB, memoryTypeIndexB,
|
||||||
memoryTypeIndexB, {signalFdTexBDevice3});
|
exportInfoTexBDevice3.semaphoreHandles, exportInfoTexBDevice3.releasedOldLayout,
|
||||||
|
exportInfoTexBDevice3.releasedNewLayout);
|
||||||
|
|
||||||
wgpu::Texture wrappedTexCDevice2 = WrapVulkanImage(
|
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
|
// Copy B->C on device 2
|
||||||
SimpleCopyTextureToTexture(secondDevice, secondDeviceQueue, wrappedTexBDevice2,
|
SimpleCopyTextureToTexture(secondDevice, secondDeviceQueue, wrappedTexBDevice2,
|
||||||
wrappedTexCDevice2);
|
wrappedTexCDevice2);
|
||||||
|
|
||||||
int signalFdTexCDevice2 = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(
|
dawn_native::vulkan::ExternalImageExportInfoOpaqueFD exportInfoTexCDevice2;
|
||||||
secondDevice.Get(), wrappedTexCDevice2.Get());
|
dawn_native::vulkan::ExportVulkanImage(
|
||||||
IgnoreSignalSemaphore(secondDevice, wrappedTexBDevice2);
|
wrappedTexCDevice2.Get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, &exportInfoTexCDevice2);
|
||||||
|
|
||||||
|
IgnoreSignalSemaphore(wrappedTexBDevice2);
|
||||||
|
|
||||||
// Import TexC on device 1
|
// Import TexC on device 1
|
||||||
memoryFdC = GetMemoryFd(deviceVk, allocationC);
|
memoryFdC = GetMemoryFd(deviceVk, allocationC);
|
||||||
wgpu::Texture wrappedTexCDevice1 =
|
wgpu::Texture wrappedTexCDevice1 = WrapVulkanImage(
|
||||||
WrapVulkanImage(device, &defaultDescriptor, memoryFdC, allocationSizeC,
|
device, &defaultDescriptor, memoryFdC, allocationSizeC, memoryTypeIndexC,
|
||||||
memoryTypeIndexC, {signalFdTexCDevice2});
|
exportInfoTexCDevice2.semaphoreHandles, exportInfoTexCDevice2.releasedOldLayout,
|
||||||
|
exportInfoTexCDevice2.releasedNewLayout);
|
||||||
|
|
||||||
// Create TexD on device 1
|
// Create TexD on device 1
|
||||||
wgpu::Texture texD = device.CreateTexture(&defaultDescriptor);
|
wgpu::Texture texD = device.CreateTexture(&defaultDescriptor);
|
||||||
@ -900,7 +916,7 @@ namespace dawn_native { namespace vulkan {
|
|||||||
deviceVk->GetFencedDeleter()->DeleteWhenUnused(imageC);
|
deviceVk->GetFencedDeleter()->DeleteWhenUnused(imageC);
|
||||||
deviceVk->GetFencedDeleter()->DeleteWhenUnused(allocationC);
|
deviceVk->GetFencedDeleter()->DeleteWhenUnused(allocationC);
|
||||||
|
|
||||||
IgnoreSignalSemaphore(device, wrappedTexCDevice1);
|
IgnoreSignalSemaphore(wrappedTexCDevice1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests a larger image is preserved when importing
|
// Tests a larger image is preserved when importing
|
||||||
@ -938,8 +954,9 @@ namespace dawn_native { namespace vulkan {
|
|||||||
&allocationA, &allocationSizeA, &memoryTypeIndexA, &memoryFdA);
|
&allocationA, &allocationSizeA, &memoryTypeIndexA, &memoryFdA);
|
||||||
|
|
||||||
// Import the image on |secondDevice|
|
// Import the image on |secondDevice|
|
||||||
wgpu::Texture wrappedTexture = WrapVulkanImage(secondDevice, &descriptor, memoryFdA,
|
wgpu::Texture wrappedTexture =
|
||||||
allocationSizeA, memoryTypeIndexA, {});
|
WrapVulkanImage(secondDevice, &descriptor, memoryFdA, allocationSizeA, memoryTypeIndexA,
|
||||||
|
{}, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||||
|
|
||||||
// Draw a non-trivial picture
|
// Draw a non-trivial picture
|
||||||
uint32_t width = 640, height = 480, pixelSize = 4;
|
uint32_t width = 640, height = 480, pixelSize = 4;
|
||||||
@ -975,13 +992,17 @@ namespace dawn_native { namespace vulkan {
|
|||||||
secondDeviceQueue.Submit(1, &commands);
|
secondDeviceQueue.Submit(1, &commands);
|
||||||
}
|
}
|
||||||
|
|
||||||
int signalFd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(secondDevice.Get(),
|
dawn_native::vulkan::ExternalImageExportInfoOpaqueFD exportInfo;
|
||||||
wrappedTexture.Get());
|
dawn_native::vulkan::ExportVulkanImage(wrappedTexture.Get(),
|
||||||
|
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, &exportInfo);
|
||||||
|
|
||||||
int memoryFd = GetMemoryFd(secondDeviceVk, allocationA);
|
int memoryFd = GetMemoryFd(secondDeviceVk, allocationA);
|
||||||
|
|
||||||
// Import the image on |device|
|
// Import the image on |device|
|
||||||
wgpu::Texture nextWrappedTexture = WrapVulkanImage(
|
wgpu::Texture nextWrappedTexture =
|
||||||
device, &descriptor, memoryFd, allocationSizeA, memoryTypeIndexA, {signalFd});
|
WrapVulkanImage(device, &descriptor, memoryFd, allocationSizeA, memoryTypeIndexA,
|
||||||
|
exportInfo.semaphoreHandles, exportInfo.releasedOldLayout,
|
||||||
|
exportInfo.releasedNewLayout);
|
||||||
|
|
||||||
// Copy the image into a buffer for comparison
|
// Copy the image into a buffer for comparison
|
||||||
wgpu::BufferDescriptor copyDesc;
|
wgpu::BufferDescriptor copyDesc;
|
||||||
@ -1006,7 +1027,7 @@ namespace dawn_native { namespace vulkan {
|
|||||||
EXPECT_BUFFER_U32_RANGE_EQ(reinterpret_cast<uint32_t*>(data.data()), copyDstBuffer, 0,
|
EXPECT_BUFFER_U32_RANGE_EQ(reinterpret_cast<uint32_t*>(data.data()), copyDstBuffer, 0,
|
||||||
data.size() / 4);
|
data.size() / 4);
|
||||||
|
|
||||||
IgnoreSignalSemaphore(device, nextWrappedTexture);
|
IgnoreSignalSemaphore(nextWrappedTexture);
|
||||||
secondDeviceVk->GetFencedDeleter()->DeleteWhenUnused(imageA);
|
secondDeviceVk->GetFencedDeleter()->DeleteWhenUnused(imageA);
|
||||||
secondDeviceVk->GetFencedDeleter()->DeleteWhenUnused(allocationA);
|
secondDeviceVk->GetFencedDeleter()->DeleteWhenUnused(allocationA);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user