Create VkImage before importing external memory
This CL is part of a chain of CLs that imports dma-bufs as VkImages to support WebGPU on Chrome OS. There are currently two steps for importing external memory into Vulkan: 1. DeviceVk::ImportExternalImage: calls into MemoryServiceOpaqueFD::ImportMemory which in turn calls into vkAllocateMemory and outputs a VkDeviceMemory handle to the imported memory. 2. TextureVk::CreateFromExternal: creates the actual TextureVk object, creates the VkImage, and binds the VkDeviceMemory from ImportExternalImage to the VkImage. For dma-buf support, however, we need to re-order these two steps because importing dma-buf memory requires a handle to the VkImage that will alias it [1]. This CL splits these two steps into three steps to ensure we create the VkImage first so we can use it in vkAllocateMemory: 1. TextureVk::CreateFromExternal: creates the TextureVk and VkImage (no longer concerns itself with vkBindImageMemory). 2. DeviceVk::ImportExternalImage: now takes the VkImage as input but is otherwise unchanged. 3. TextureVk::BindExternalMemory: calls vkBindImageMemory with handles to VkDeviceMemory and VkImage. [1] https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/VkMemoryDedicatedAllocateInfo.html BUG=chromium:996470 Change-Id: Id2d5951e9b573af79c44ce8c63be5210a279f946 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/13780 Commit-Queue: Brian Ho <hob@chromium.org> Reviewed-by: Austin Eng <enga@chromium.org>
This commit is contained in:
parent
02dd733454
commit
756a9d7e49
|
@ -595,6 +595,7 @@ namespace dawn_native { namespace vulkan {
|
|||
|
||||
MaybeError Device::ImportExternalImage(const ExternalImageDescriptor* descriptor,
|
||||
ExternalMemoryHandle memoryHandle,
|
||||
VkImage image,
|
||||
const std::vector<ExternalSemaphoreHandle>& waitHandles,
|
||||
VkSemaphore* outSignalSemaphore,
|
||||
VkDeviceMemory* outAllocation,
|
||||
|
@ -620,9 +621,11 @@ namespace dawn_native { namespace vulkan {
|
|||
mExternalSemaphoreService->CreateExportableSemaphore());
|
||||
|
||||
// Import the external image's memory
|
||||
external_memory::MemoryImportParams importParams;
|
||||
DAWN_TRY_ASSIGN(importParams,
|
||||
mExternalMemoryService->GetMemoryImportParams(descriptor, image));
|
||||
DAWN_TRY_ASSIGN(*outAllocation,
|
||||
mExternalMemoryService->ImportMemory(
|
||||
memoryHandle, descriptor->allocationSize, descriptor->memoryTypeIndex));
|
||||
mExternalMemoryService->ImportMemory(memoryHandle, importParams, image));
|
||||
|
||||
// Import semaphores we have to wait on before using the texture
|
||||
for (const ExternalSemaphoreHandle& handle : waitHandles) {
|
||||
|
@ -671,11 +674,19 @@ namespace dawn_native { namespace vulkan {
|
|||
// Cleanup in case of a failure, the image creation doesn't acquire the external objects
|
||||
// if a failure happems.
|
||||
Texture* result = nullptr;
|
||||
if (ConsumedError(ImportExternalImage(descriptor, memoryHandle, waitHandles,
|
||||
&signalSemaphore, &allocation, &waitSemaphores)) ||
|
||||
ConsumedError(Texture::CreateFromExternal(this, descriptor, textureDescriptor,
|
||||
signalSemaphore, allocation, waitSemaphores),
|
||||
&result)) {
|
||||
// TODO(crbug.com/1026480): Consolidate this into a single CreateFromExternal call.
|
||||
if (ConsumedError(Texture::CreateFromExternal(this, descriptor, textureDescriptor),
|
||||
&result) ||
|
||||
ConsumedError(ImportExternalImage(descriptor, memoryHandle, result->GetHandle(),
|
||||
waitHandles, &signalSemaphore, &allocation,
|
||||
&waitSemaphores)) ||
|
||||
ConsumedError(result->BindExternalMemory(descriptor, signalSemaphore, allocation,
|
||||
waitSemaphores))) {
|
||||
// Delete the Texture if it was created
|
||||
if (result != nullptr) {
|
||||
delete result;
|
||||
}
|
||||
|
||||
// Clear the signal semaphore
|
||||
fn.DestroySemaphore(GetVkDevice(), signalSemaphore, nullptr);
|
||||
|
||||
|
|
|
@ -171,6 +171,7 @@ namespace dawn_native { namespace vulkan {
|
|||
|
||||
MaybeError ImportExternalImage(const ExternalImageDescriptor* descriptor,
|
||||
ExternalMemoryHandle memoryHandle,
|
||||
VkImage image,
|
||||
const std::vector<ExternalSemaphoreHandle>& waitHandles,
|
||||
VkSemaphore* outSignalSemaphore,
|
||||
VkDeviceMemory* outAllocation,
|
||||
|
|
|
@ -406,16 +406,13 @@ namespace dawn_native { namespace vulkan {
|
|||
}
|
||||
|
||||
// static
|
||||
ResultOrError<Texture*> Texture::CreateFromExternal(Device* device,
|
||||
ResultOrError<Texture*> Texture::CreateFromExternal(
|
||||
Device* device,
|
||||
const ExternalImageDescriptor* descriptor,
|
||||
const TextureDescriptor* textureDescriptor,
|
||||
VkSemaphore signalSemaphore,
|
||||
VkDeviceMemory externalMemoryAllocation,
|
||||
std::vector<VkSemaphore> waitSemaphores) {
|
||||
const TextureDescriptor* textureDescriptor) {
|
||||
std::unique_ptr<Texture> texture =
|
||||
std::make_unique<Texture>(device, textureDescriptor, TextureState::OwnedInternal);
|
||||
DAWN_TRY(texture->InitializeFromExternal(
|
||||
descriptor, signalSemaphore, externalMemoryAllocation, std::move((waitSemaphores))));
|
||||
DAWN_TRY(texture->InitializeFromExternal(descriptor));
|
||||
return texture.release();
|
||||
}
|
||||
|
||||
|
@ -484,10 +481,7 @@ namespace dawn_native { namespace vulkan {
|
|||
}
|
||||
|
||||
// Internally managed, but imported from external handle
|
||||
MaybeError Texture::InitializeFromExternal(const ExternalImageDescriptor* descriptor,
|
||||
VkSemaphore signalSemaphore,
|
||||
VkDeviceMemory externalMemoryAllocation,
|
||||
std::vector<VkSemaphore> waitSemaphores) {
|
||||
MaybeError Texture::InitializeFromExternal(const ExternalImageDescriptor* descriptor) {
|
||||
mExternalState = ExternalState::PendingAcquire;
|
||||
Device* device = ToBackend(GetDevice());
|
||||
|
||||
|
@ -519,7 +513,14 @@ namespace dawn_native { namespace vulkan {
|
|||
device->fn.CreateImage(device->GetVkDevice(), &createInfo, nullptr, &mHandle),
|
||||
"CreateImage"));
|
||||
|
||||
// Create the image memory and associate it with the container
|
||||
return {};
|
||||
}
|
||||
|
||||
MaybeError Texture::BindExternalMemory(const ExternalImageDescriptor* descriptor,
|
||||
VkSemaphore signalSemaphore,
|
||||
VkDeviceMemory externalMemoryAllocation,
|
||||
std::vector<VkSemaphore> waitSemaphores) {
|
||||
Device* device = ToBackend(GetDevice());
|
||||
VkMemoryRequirements requirements;
|
||||
device->fn.GetImageMemoryRequirements(device->GetVkDevice(), mHandle, &requirements);
|
||||
|
||||
|
@ -538,7 +539,6 @@ namespace dawn_native { namespace vulkan {
|
|||
mExternalAllocation = externalMemoryAllocation;
|
||||
mSignalSemaphore = signalSemaphore;
|
||||
mWaitRequirements = std::move(waitSemaphores);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
|
|
|
@ -39,16 +39,13 @@ namespace dawn_native { namespace vulkan {
|
|||
// Used to create a regular texture from a descriptor.
|
||||
static ResultOrError<Texture*> Create(Device* device, const TextureDescriptor* descriptor);
|
||||
|
||||
// Used to create a texture from Vulkan external memory objects.
|
||||
// Ownership of semaphores and the memory allocation is taken only if the creation is
|
||||
// a success.
|
||||
// Creates a texture and initializes it with a VkImage that references an external memory
|
||||
// object. Before the texture can be used, the VkDeviceMemory associated with the external
|
||||
// image must be bound via Texture::BindExternalMemory.
|
||||
static ResultOrError<Texture*> CreateFromExternal(
|
||||
Device* device,
|
||||
const ExternalImageDescriptor* descriptor,
|
||||
const TextureDescriptor* textureDescriptor,
|
||||
VkSemaphore signalSemaphore,
|
||||
VkDeviceMemory externalMemoryAllocation,
|
||||
std::vector<VkSemaphore> waitSemaphores);
|
||||
const TextureDescriptor* textureDescriptor);
|
||||
|
||||
Texture(Device* device, const TextureDescriptor* descriptor, VkImage nativeImage);
|
||||
~Texture();
|
||||
|
@ -68,14 +65,18 @@ namespace dawn_native { namespace vulkan {
|
|||
uint32_t layerCount);
|
||||
|
||||
MaybeError SignalAndDestroy(VkSemaphore* outSignalSemaphore);
|
||||
// Binds externally allocated memory to the VkImage and on success, takes ownership of
|
||||
// semaphores.
|
||||
MaybeError BindExternalMemory(const ExternalImageDescriptor* descriptor,
|
||||
VkSemaphore signalSemaphore,
|
||||
VkDeviceMemory externalMemoryAllocation,
|
||||
std::vector<VkSemaphore> waitSemaphores);
|
||||
|
||||
private:
|
||||
using TextureBase::TextureBase;
|
||||
MaybeError InitializeAsInternalTexture();
|
||||
MaybeError InitializeFromExternal(const ExternalImageDescriptor* descriptor,
|
||||
VkSemaphore signalSemaphore,
|
||||
VkDeviceMemory externalMemoryAllocation,
|
||||
std::vector<VkSemaphore> waitSemaphores);
|
||||
|
||||
MaybeError InitializeFromExternal(const ExternalImageDescriptor* descriptor);
|
||||
|
||||
void DestroyImpl() override;
|
||||
MaybeError ClearTexture(CommandRecordingContext* recordingContext,
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include "common/vulkan_platform.h"
|
||||
#include "dawn_native/Error.h"
|
||||
#include "dawn_native/VulkanBackend.h"
|
||||
#include "dawn_native/vulkan/ExternalHandle.h"
|
||||
|
||||
namespace dawn_native { namespace vulkan {
|
||||
|
@ -25,6 +26,11 @@ namespace dawn_native { namespace vulkan {
|
|||
|
||||
namespace dawn_native { namespace vulkan { namespace external_memory {
|
||||
|
||||
struct MemoryImportParams {
|
||||
VkDeviceSize allocationSize;
|
||||
uint32_t memoryTypeIndex;
|
||||
};
|
||||
|
||||
class Service {
|
||||
public:
|
||||
explicit Service(Device* device);
|
||||
|
@ -37,10 +43,15 @@ namespace dawn_native { namespace vulkan { namespace external_memory {
|
|||
VkImageUsageFlags usage,
|
||||
VkImageCreateFlags flags);
|
||||
|
||||
// Returns the parameters required for importing memory
|
||||
ResultOrError<MemoryImportParams> GetMemoryImportParams(
|
||||
const ExternalImageDescriptor* descriptor,
|
||||
VkImage image);
|
||||
|
||||
// Given an external handle pointing to memory, import it into a VkDeviceMemory
|
||||
ResultOrError<VkDeviceMemory> ImportMemory(ExternalMemoryHandle handle,
|
||||
VkDeviceSize allocationSize,
|
||||
uint32_t memoryTypeIndex);
|
||||
const MemoryImportParams& importParams,
|
||||
VkImage image);
|
||||
|
||||
private:
|
||||
Device* mDevice = nullptr;
|
||||
|
|
|
@ -32,10 +32,16 @@ namespace dawn_native { namespace vulkan { namespace external_memory {
|
|||
return false;
|
||||
}
|
||||
|
||||
ResultOrError<MemoryImportParams> Service::GetMemoryImportParams(
|
||||
const ExternalImageDescriptor* descriptor,
|
||||
VkImage image) {
|
||||
return DAWN_UNIMPLEMENTED_ERROR("Using null memory service to interop inside Vulkan");
|
||||
}
|
||||
|
||||
ResultOrError<VkDeviceMemory> Service::ImportMemory(ExternalMemoryHandle handle,
|
||||
VkDeviceSize allocationSize,
|
||||
uint32_t memoryTypeIndex) {
|
||||
return DAWN_UNIMPLEMENTED_ERROR("Using null semaphore service to interop inside Vulkan");
|
||||
const MemoryImportParams& importParams,
|
||||
VkImage image) {
|
||||
return DAWN_UNIMPLEMENTED_ERROR("Using null memory service to interop inside Vulkan");
|
||||
}
|
||||
|
||||
}}} // namespace dawn_native::vulkan::external_memory
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "common/Assert.h"
|
||||
#include "dawn_native/vulkan/AdapterVk.h"
|
||||
#include "dawn_native/vulkan/BackendVk.h"
|
||||
#include "dawn_native/vulkan/DeviceVk.h"
|
||||
|
@ -79,9 +80,16 @@ namespace dawn_native { namespace vulkan { namespace external_memory {
|
|||
!(memoryFlags & VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR);
|
||||
}
|
||||
|
||||
ResultOrError<MemoryImportParams> Service::GetMemoryImportParams(
|
||||
const ExternalImageDescriptor* descriptor,
|
||||
VkImage image) {
|
||||
MemoryImportParams params = {descriptor->allocationSize, descriptor->memoryTypeIndex};
|
||||
return params;
|
||||
}
|
||||
|
||||
ResultOrError<VkDeviceMemory> Service::ImportMemory(ExternalMemoryHandle handle,
|
||||
VkDeviceSize allocationSize,
|
||||
uint32_t memoryTypeIndex) {
|
||||
const MemoryImportParams& importParams,
|
||||
VkImage image) {
|
||||
if (handle < 0) {
|
||||
return DAWN_VALIDATION_ERROR("Trying to import memory with invalid handle");
|
||||
}
|
||||
|
@ -95,8 +103,8 @@ namespace dawn_native { namespace vulkan { namespace external_memory {
|
|||
VkMemoryAllocateInfo allocateInfo;
|
||||
allocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||
allocateInfo.pNext = &importMemoryFdInfo;
|
||||
allocateInfo.allocationSize = allocationSize;
|
||||
allocateInfo.memoryTypeIndex = memoryTypeIndex;
|
||||
allocateInfo.allocationSize = importParams.allocationSize;
|
||||
allocateInfo.memoryTypeIndex = importParams.memoryTypeIndex;
|
||||
|
||||
VkDeviceMemory allocatedMemory = VK_NULL_HANDLE;
|
||||
DAWN_TRY(CheckVkSuccess(mDevice->fn.AllocateMemory(mDevice->GetVkDevice(), &allocateInfo,
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "common/Assert.h"
|
||||
#include "dawn_native/vulkan/AdapterVk.h"
|
||||
#include "dawn_native/vulkan/BackendVk.h"
|
||||
#include "dawn_native/vulkan/DeviceVk.h"
|
||||
|
@ -79,9 +80,16 @@ namespace dawn_native { namespace vulkan { namespace external_memory {
|
|||
!(memoryFlags & VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR);
|
||||
}
|
||||
|
||||
ResultOrError<MemoryImportParams> Service::GetMemoryImportParams(
|
||||
const ExternalImageDescriptor* descriptor,
|
||||
VkImage image) {
|
||||
MemoryImportParams params = {descriptor->allocationSize, descriptor->memoryTypeIndex};
|
||||
return params;
|
||||
}
|
||||
|
||||
ResultOrError<VkDeviceMemory> Service::ImportMemory(ExternalMemoryHandle handle,
|
||||
VkDeviceSize allocationSize,
|
||||
uint32_t memoryTypeIndex) {
|
||||
const MemoryImportParams& importParams,
|
||||
VkImage image) {
|
||||
if (handle == ZX_HANDLE_INVALID) {
|
||||
return DAWN_VALIDATION_ERROR("Trying to import memory with invalid handle");
|
||||
}
|
||||
|
@ -97,8 +105,8 @@ namespace dawn_native { namespace vulkan { namespace external_memory {
|
|||
VkMemoryAllocateInfo allocateInfo;
|
||||
allocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||
allocateInfo.pNext = &importMemoryHandleInfo;
|
||||
allocateInfo.allocationSize = allocationSize;
|
||||
allocateInfo.memoryTypeIndex = memoryTypeIndex;
|
||||
allocateInfo.allocationSize = importParams.allocationSize;
|
||||
allocateInfo.memoryTypeIndex = importParams.memoryTypeIndex;
|
||||
|
||||
VkDeviceMemory allocatedMemory = VK_NULL_HANDLE;
|
||||
DAWN_TRY(CheckVkSuccess(mDevice->fn.AllocateMemory(mDevice->GetVkDevice(), &allocateInfo,
|
||||
|
|
Loading…
Reference in New Issue