Support direct image import from buffer collections
Test: nuc:go/magma-tps#L0
Change-Id: I5a94507d9290d0af3048d32849b6a6c503d749b9
diff --git a/include/vulkan/vulkan_core.h b/include/vulkan/vulkan_core.h
index 283712d..9296d10 100644
--- a/include/vulkan/vulkan_core.h
+++ b/include/vulkan/vulkan_core.h
@@ -458,6 +458,9 @@
VK_STRUCTURE_TYPE_IMAGEPIPE_SURFACE_CREATE_INFO_FUCHSIA = 1000214000,
VK_STRUCTURE_TYPE_BUFFER_COLLECTION_CREATE_INFO_FUCHSIA = 1001004000,
VK_STRUCTURE_TYPE_FUCHSIA_IMAGE_FORMAT_FUCHSIA = 1001004001,
+ VK_STRUCTURE_TYPE_IMPORT_MEMORY_BUFFER_COLLECTION_FUCHSIA = 1001004004,
+ VK_STRUCTURE_TYPE_BUFFER_COLLECTION_IMAGE_CREATE_INFO_FUCHSIA = 1001004005,
+ VK_STRUCTURE_TYPE_BUFFER_COLLECTION_PROPERTIES_FUCHSIA = 1001004006,
VK_STRUCTURE_TYPE_IMPORT_MEMORY_FUCHSIA_HANDLE_INFO_KHR = 1001000000,
VK_STRUCTURE_TYPE_MEMORY_FUCHSIA_HANDLE_PROPERTIES_KHR = 1001000001,
VK_STRUCTURE_TYPE_MEMORY_GET_FUCHSIA_HANDLE_INFO_KHR = 1001000002,
diff --git a/include/vulkan/vulkan_fuchsia.h b/include/vulkan/vulkan_fuchsia.h
index 1977f5c..ab7d636 100644
--- a/include/vulkan/vulkan_fuchsia.h
+++ b/include/vulkan/vulkan_fuchsia.h
@@ -150,10 +150,33 @@
uint32_t imageFormatSize;
} VkFuchsiaImageFormatFUCHSIA;
+typedef struct VkImportMemoryBufferCollectionFUCHSIA {
+ VkStructureType sType;
+ const void* pNext;
+ VkBufferCollectionFUCHSIA collection;
+ uint32_t index;
+} VkImportMemoryBufferCollectionFUCHSIA;
+
+typedef struct VkBufferCollectionImageCreateInfoFUCHSIA {
+ VkStructureType sType;
+ const void* pNext;
+ VkBufferCollectionFUCHSIA collection;
+ uint32_t index;
+} VkBufferCollectionImageCreateInfoFUCHSIA;
+
+typedef struct VkBufferCollectionPropertiesFUCHSIA {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t memoryTypeBits;
+ uint32_t count;
+} VkBufferCollectionPropertiesFUCHSIA;
+
typedef VkResult (VKAPI_PTR *PFN_vkCreateBufferCollectionFUCHSIA)(VkDevice device, const VkBufferCollectionCreateInfoFUCHSIA* pImportInfo, const VkAllocationCallbacks* pAllocator, VkBufferCollectionFUCHSIA* pCollection);
typedef VkResult (VKAPI_PTR *PFN_vkSetBufferCollectionConstraintsFUCHSIA)(VkDevice device, VkBufferCollectionFUCHSIA collection, const VkImageCreateInfo* pImageInfo);
typedef void (VKAPI_PTR *PFN_vkDestroyBufferCollectionFUCHSIA)(VkDevice device, VkBufferCollectionFUCHSIA collection, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkGetBufferCollectionPropertiesFUCHSIA)(VkDevice device, VkBufferCollectionFUCHSIA collection, VkBufferCollectionPropertiesFUCHSIA* pProperties);
+
#ifndef VK_NO_PROTOTYPES
VKAPI_ATTR VkResult VKAPI_CALL vkCreateBufferCollectionFUCHSIA(
@@ -171,6 +194,11 @@
VkDevice device,
VkBufferCollectionFUCHSIA collection,
const VkAllocationCallbacks* pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetBufferCollectionPropertiesFUCHSIA(
+ VkDevice device,
+ VkBufferCollectionFUCHSIA collection,
+ VkBufferCollectionPropertiesFUCHSIA* pProperties);
#endif
@@ -254,4 +282,4 @@
}
#endif
-#endif
\ No newline at end of file
+#endif
diff --git a/src/intel/vulkan/anv_device.c b/src/intel/vulkan/anv_device.c
index 86bd022..83e82c4 100644
--- a/src/intel/vulkan/anv_device.c
+++ b/src/intel/vulkan/anv_device.c
@@ -2220,6 +2220,8 @@
vk_find_struct_const(pAllocateInfo->pNext, IMPORT_MEMORY_FUCHSIA_HANDLE_INFO_KHR);
const VkImportMemoryZirconHandleInfoFUCHSIA *fuchsia_info =
vk_find_struct_const(pAllocateInfo->pNext, TEMP_IMPORT_MEMORY_ZIRCON_HANDLE_INFO_FUCHSIA);
+ const VkImportMemoryBufferCollectionFUCHSIA* fuchsia_buffer_collection =
+ vk_find_struct_const(pAllocateInfo->pNext, IMPORT_MEMORY_BUFFER_COLLECTION_FUCHSIA);
#endif // VK_USE_PLATFORM_FUCHSIA
/* The Vulkan spec permits handleType to be 0, in which case the struct is
@@ -2338,6 +2340,42 @@
if (result != VK_SUCCESS)
goto fail;
+ } else if (fuchsia_buffer_collection) {
+ VkDeviceSize aligned_alloc_size = align_u64(pAllocateInfo->allocationSize, 4096);
+
+ uint32_t handle;
+ uint32_t offset;
+ VkResult result =
+ anv_get_buffer_collection_handle(device, fuchsia_buffer_collection->collection,
+ fuchsia_buffer_collection->index, &handle, &offset);
+ if (result != VK_SUCCESS)
+ goto fail;
+
+ // The anv_buffer_handle_t isn't a unique handle per object, so the cache
+ // lookup in the import will always fail.
+ // TODO(MA-320) - get a unique id for this object and use that as the cache key;
+ // then clients will be able to import a buffer more than once.
+ anv_buffer_handle_t buffer;
+ uint64_t import_size;
+ int status = anv_gem_import_fuchsia_buffer(device, handle, &buffer, &import_size);
+ if (status != 0)
+ return vk_error(VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR);
+ if (import_size < aligned_alloc_size) {
+ result = vk_errorf(device->instance, device, VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR,
+ "aligned allocationSize too large for "
+ "VK_EXTERNAL_MEMORY_HANDLE_TYPE_FUCHSIA_BIT_KHR: "
+ "%" PRIu64 "B > %" PRIu64 "B",
+ aligned_alloc_size, import_size);
+ anv_gem_close(device, buffer);
+ goto fail;
+ }
+
+ result = anv_bo_cache_import_buffer_handle(device, &device->bo_cache, buffer,
+ bo_flags | ANV_BO_EXTERNAL, aligned_alloc_size,
+ &mem->bo);
+ if (result != VK_SUCCESS)
+ goto fail;
+
#endif // VK_USE_PLATFORM_FUCHSIA
} else {
diff --git a/src/intel/vulkan/anv_image.c b/src/intel/vulkan/anv_image.c
index dfb976c..9554495 100644
--- a/src/intel/vulkan/anv_image.c
+++ b/src/intel/vulkan/anv_image.c
@@ -645,15 +645,24 @@
#if VK_USE_PLATFORM_FUCHSIA
const struct VkFuchsiaImageFormatFUCHSIA *image_format_fuchsia =
vk_find_struct_const(pCreateInfo->pNext, FUCHSIA_IMAGE_FORMAT_FUCHSIA);
- if (image_format_fuchsia) {
+ const struct VkBufferCollectionImageCreateInfoFUCHSIA* buffer_collection_fuchsia =
+ vk_find_struct_const(pCreateInfo->pNext, BUFFER_COLLECTION_IMAGE_CREATE_INFO_FUCHSIA);
+ if (image_format_fuchsia || buffer_collection_fuchsia) {
const int kParamCount = 4;
struct anv_fuchsia_image_plane_params params[kParamCount];
isl_tiling_flags_t tiling_flags;
bool non_cache_coherent;
- VkResult result = anv_image_params_from_fuchsia_image(device, pCreateInfo, params,
- &tiling_flags, &non_cache_coherent);
+ VkResult result;
+ if (image_format_fuchsia) {
+ result = anv_image_params_from_fuchsia_image(device, pCreateInfo, params, &tiling_flags,
+ &non_cache_coherent);
+ } else {
+ result =
+ anv_image_params_from_buffer_collection(device, buffer_collection_fuchsia->collection,
+ params, &tiling_flags, &non_cache_coherent);
+ }
if (result != VK_SUCCESS)
- return result;
+ return result;
// We support only one bytes_per_row for all planes.
uint32_t bytes_per_row = params[0].bytes_per_row;
diff --git a/src/intel/vulkan/anv_magma_buffer_collection.c b/src/intel/vulkan/anv_magma_buffer_collection.c
index b1c7ea1..1c1bf75 100644
--- a/src/intel/vulkan/anv_magma_buffer_collection.c
+++ b/src/intel/vulkan/anv_magma_buffer_collection.c
@@ -255,30 +255,46 @@
return VK_SUCCESS;
}
-VkResult anv_image_params_from_fuchsia_image(
- VkDevice vk_device, const VkImageCreateInfo* pCreateInfo,
+VkResult anv_GetBufferCollectionPropertiesFUCHSIA(VkDevice vk_device,
+ VkBufferCollectionFUCHSIA vk_collection,
+ VkBufferCollectionPropertiesFUCHSIA* pProperties)
+{
+ ANV_FROM_HANDLE(anv_device, device, vk_device);
+ ANV_FROM_HANDLE(anv_buffer_collection, buffer_collection, vk_collection);
+
+ magma_sysmem_connection_t sysmem_connection;
+ magma_status_t status = AnvMagmaGetSysmemConnection(device->connection, &sysmem_connection);
+ if (status != MAGMA_STATUS_OK)
+ return ANV_MAGMA_DRET(VK_ERROR_DEVICE_LOST);
+ magma_buffer_format_description_t description;
+ status = magma_sysmem_get_description_from_collection(
+ sysmem_connection, buffer_collection->buffer_collection, &description);
+ if (status != MAGMA_STATUS_OK)
+ return ANV_MAGMA_DRET(VK_ERROR_DEVICE_LOST);
+
+ status = magma_get_buffer_count(description, &pProperties->count);
+ magma_buffer_format_description_release(description);
+
+ if (status != MAGMA_STATUS_OK)
+ return ANV_MAGMA_DRET(VK_ERROR_DEVICE_LOST);
+
+ struct anv_physical_device* pdevice = &device->instance->physicalDevice;
+ // All memory types supported.
+ pProperties->memoryTypeBits = (1ull << pdevice->memory.type_count) - 1;
+ return VK_SUCCESS;
+}
+
+// Takes ownership of the buffer format description.
+static VkResult anv_image_params_from_description(
+ magma_buffer_format_description_t description,
struct anv_fuchsia_image_plane_params params_out[MAGMA_MAX_IMAGE_PLANES],
isl_tiling_flags_t* tiling_flags_out, bool* not_cache_coherent_out)
{
- assert(pCreateInfo->arrayLayers == 1);
- assert(pCreateInfo->extent.depth == 1);
-
- const struct VkFuchsiaImageFormatFUCHSIA* image_format_fuchsia =
- vk_find_struct_const(pCreateInfo->pNext, FUCHSIA_IMAGE_FORMAT_FUCHSIA);
- assert(image_format_fuchsia);
-
- magma_buffer_format_description_t description;
- magma_status_t status;
- status = magma_get_buffer_format_description(
- image_format_fuchsia->imageFormat, image_format_fuchsia->imageFormatSize, &description);
- if (status != MAGMA_STATUS_OK)
- return ANV_MAGMA_DRET(VK_ERROR_FORMAT_NOT_SUPPORTED);
-
magma_bool_t has_format_modifier;
uint64_t format_modifier;
magma_image_plane_t planes[MAGMA_MAX_IMAGE_PLANES];
- status = magma_get_buffer_format_plane_info(description, planes);
+ magma_status_t status = magma_get_buffer_format_plane_info(description, planes);
if (status == MAGMA_STATUS_OK) {
status =
magma_get_buffer_format_modifier(description, &has_format_modifier, &format_modifier);
@@ -321,4 +337,67 @@
return VK_SUCCESS;
}
+VkResult anv_image_params_from_fuchsia_image(
+ VkDevice vk_device, const VkImageCreateInfo* pCreateInfo,
+ struct anv_fuchsia_image_plane_params params_out[MAGMA_MAX_IMAGE_PLANES],
+ isl_tiling_flags_t* tiling_flags_out, bool* not_cache_coherent_out)
+{
+ assert(pCreateInfo->arrayLayers == 1);
+ assert(pCreateInfo->extent.depth == 1);
+
+ const struct VkFuchsiaImageFormatFUCHSIA* image_format_fuchsia =
+ vk_find_struct_const(pCreateInfo->pNext, FUCHSIA_IMAGE_FORMAT_FUCHSIA);
+ assert(image_format_fuchsia);
+
+ magma_buffer_format_description_t description;
+ magma_status_t status;
+ status = magma_get_buffer_format_description(
+ image_format_fuchsia->imageFormat, image_format_fuchsia->imageFormatSize, &description);
+ if (status != MAGMA_STATUS_OK)
+ return ANV_MAGMA_DRET(VK_ERROR_FORMAT_NOT_SUPPORTED);
+
+ return anv_image_params_from_description(description, params_out, tiling_flags_out,
+ not_cache_coherent_out);
+}
+
+VkResult anv_image_params_from_buffer_collection(
+ VkDevice vk_device, VkBufferCollectionFUCHSIA vk_collection,
+ struct anv_fuchsia_image_plane_params params_out[MAGMA_MAX_IMAGE_PLANES],
+ isl_tiling_flags_t* tiling_flags_out, bool* not_cache_coherent_out)
+{
+ ANV_FROM_HANDLE(anv_device, device, vk_device);
+ ANV_FROM_HANDLE(anv_buffer_collection, buffer_collection, vk_collection);
+
+ magma_sysmem_connection_t sysmem_connection;
+ magma_status_t status = AnvMagmaGetSysmemConnection(device->connection, &sysmem_connection);
+ if (status != MAGMA_STATUS_OK)
+ return ANV_MAGMA_DRET(VK_ERROR_DEVICE_LOST);
+ magma_buffer_format_description_t description;
+ status = magma_sysmem_get_description_from_collection(
+ sysmem_connection, buffer_collection->buffer_collection, &description);
+ if (status != MAGMA_STATUS_OK)
+ return ANV_MAGMA_DRET(VK_ERROR_DEVICE_LOST);
+
+ return anv_image_params_from_description(description, params_out, tiling_flags_out,
+ not_cache_coherent_out);
+}
+
+VkResult anv_get_buffer_collection_handle(struct anv_device* device,
+ VkBufferCollectionFUCHSIA vk_collection, uint32_t index,
+ uint32_t* handle_out, uint32_t* offset_out)
+{
+ ANV_FROM_HANDLE(anv_buffer_collection, buffer_collection, vk_collection);
+
+ magma_sysmem_connection_t sysmem_connection;
+ magma_status_t status = AnvMagmaGetSysmemConnection(device->connection, &sysmem_connection);
+ if (status != MAGMA_STATUS_OK)
+ return ANV_MAGMA_DRET(VK_ERROR_DEVICE_LOST);
+ if (magma_sysmem_get_buffer_handle_from_collection(sysmem_connection,
+ buffer_collection->buffer_collection, index,
+ handle_out, offset_out) != MAGMA_STATUS_OK) {
+ return ANV_MAGMA_DRET(VK_ERROR_DEVICE_LOST);
+ }
+ return VK_SUCCESS;
+}
+
#endif // VK_USE_PLATFORM_FUCHSIA
diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h
index 3fe8ae5..fce08c4 100644
--- a/src/intel/vulkan/anv_private.h
+++ b/src/intel/vulkan/anv_private.h
@@ -3331,6 +3331,16 @@
isl_tiling_flags_t* tiling_flags_out,
bool* not_cache_coherent_out);
+VkResult
+anv_image_params_from_buffer_collection(VkDevice device, VkBufferCollectionFUCHSIA vk_collection,
+ struct anv_fuchsia_image_plane_params params_out[4],
+ isl_tiling_flags_t* tiling_flags_out,
+ bool* not_cache_coherent_out);
+
+VkResult anv_get_buffer_collection_handle(struct anv_device* device,
+ VkBufferCollectionFUCHSIA collection, uint32_t index,
+ uint32_t* handle_out, uint32_t* offset_out);
+
#endif
#define ANV_DEFINE_HANDLE_CASTS(__anv_type, __VkType) \
diff --git a/src/vulkan/registry/vk.xml b/src/vulkan/registry/vk.xml
index 887f696..35e793b 100644
--- a/src/vulkan/registry/vk.xml
+++ b/src/vulkan/registry/vk.xml
@@ -2166,11 +2166,29 @@
<member>const <type>void</type>* <name>imageFormat</name></member>
<member><type>uint32_t</type> <name>imageFormatSize</name></member>
</type>
+ <type category="struct" name="VkImportMemoryBufferCollectionFUCHSIA" structextends="VkMemoryAllocateInfo">
+ <member values="VK_STRUCTURE_TYPE_IMPORT_MEMORY_BUFFER_COLLECTION_FUCHSIA"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkBufferCollectionFUCHSIA</type> <name>collection</name></member>
+ <member><type>uint32_t</type> <name>index</name></member>
+ </type>
+ <type category="struct" name="VkBufferCollectionImageCreateInfoFUCHSIA" structextends="VkImageCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_BUFFER_COLLECTION_IMAGE_CREATE_INFO_FUCHSIA"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkBufferCollectionFUCHSIA</type> <name>collection</name></member>
+ <member><type>uint32_t</type> <name>index</name></member>
+ </type>
<type category="struct" name="VkBufferCollectionCreateInfoFUCHSIA">
<member values="VK_STRUCTURE_TYPE_BUFFER_COLLECTION_CREATE_INFO_FUCHSIA"><type>VkStructureType</type> <name>sType</name></member>
<member>const <type>void</type>* <name>pNext</name></member>
<member><type>zx_handle_t</type> <name>collectionToken</name></member>
</type>
+ <type category="struct" name="VkBufferCollectionPropertiesFUCHSIA">
+ <member values="VK_STRUCTURE_TYPE_BUFFER_COLLECTION_PROPERTIES_FUCHSIA"><type>VkStructureType</type> <name>sType</name></member>
+ <member><type>void</type>* <name>pNext</name></member>
+ <member><type>uint32_t</type> <name>memoryTypeBits</name></member>
+ <member><type>uint32_t</type> <name>count</name></member>
+ </type>
<type category="struct" name="VkWin32KeyedMutexAcquireReleaseInfoKHR" structextends="VkSubmitInfo">
<member values="VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
<member>const <type>void</type>* <name>pNext</name></member>
@@ -5999,6 +6017,12 @@
<param><type>VkBufferCollectionFUCHSIA</type> <name>collection</name></param>
<param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
</command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkGetBufferCollectionPropertiesFUCHSIA</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param><type>VkBufferCollectionFUCHSIA</type> <name>collection</name></param>
+ <param><type>VkBufferCollectionPropertiesFUCHSIA</type>* <name>pProperties</name></param>
+ </command>
<command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY">
<proto><type>VkResult</type> <name>vkCreateDebugReportCallbackEXT</name></proto>
<param><type>VkInstance</type> <name>instance</name></param>
@@ -10290,12 +10314,19 @@
<enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_FUCHSIA_IMAGE_FORMAT_FUCHSIA"/>
<enum offset="2" extends="VkObjectType" name="VK_OBJECT_TYPE_BUFFER_COLLECTION_FUCHSIA" comment="VkBufferCollectionFUCHSIA"/>
<enum offset="3" extends="VkDebugReportObjectTypeEXT" name="VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_COLLECTION_FUCHSIA_EXT"/>
+ <enum offset="4" extends="VkStructureType" name="VK_STRUCTURE_TYPE_IMPORT_MEMORY_BUFFER_COLLECTION_FUCHSIA"/>
+ <enum offset="5" extends="VkStructureType" name="VK_STRUCTURE_TYPE_BUFFER_COLLECTION_IMAGE_CREATE_INFO_FUCHSIA"/>
+ <enum offset="6" extends="VkStructureType" name="VK_STRUCTURE_TYPE_BUFFER_COLLECTION_PROPERTIES_FUCHSIA"/>
<type name="VkBufferCollectionFUCHSIA"/>
<type name="VkBufferCollectionCreateInfoFUCHSIA"/>
<type name="VkFuchsiaImageFormatFUCHSIA"/>
+ <type name="VkImportMemoryBufferCollectionFUCHSIA"/>
+ <type name="VkBufferCollectionImageCreateInfoFUCHSIA"/>
+ <type name="VkBufferCollectionPropertiesFUCHSIA"/>
<command name="vkCreateBufferCollectionFUCHSIA"/>
<command name="vkSetBufferCollectionConstraintsFUCHSIA"/>
<command name="vkDestroyBufferCollectionFUCHSIA"/>
+ <command name="vkGetBufferCollectionPropertiesFUCHSIA"/>
</require>
</extension>
<extension name="VK_FUCHSIA_external_memory" number="1006" type="device" requires="VK_KHR_external_memory_capabilities,VK_KHR_external_memory" author="FUCHSIA" contact="Craig Stout @cdotstout" supported="vulkan" platform="fuchsia">