diff --git a/src/nouveau/vulkan/nvk_buffer.c b/src/nouveau/vulkan/nvk_buffer.c index cc1b43cc4f6..c8f96a8e34c 100644 --- a/src/nouveau/vulkan/nvk_buffer.c +++ b/src/nouveau/vulkan/nvk_buffer.c @@ -64,6 +64,50 @@ nvk_GetDeviceBufferMemoryRequirements(VkDevice _device, } } +VKAPI_ATTR void VKAPI_CALL +nvk_GetPhysicalDeviceExternalBufferProperties( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceExternalBufferInfo *pExternalBufferInfo, + VkExternalBufferProperties *pExternalBufferProperties) +{ + /* The Vulkan 1.3.256 spec says: + * + * VUID-VkPhysicalDeviceExternalBufferInfo-handleType-parameter + * + * "handleType must be a valid VkExternalMemoryHandleTypeFlagBits value" + * + * This differs from VkPhysicalDeviceExternalImageFormatInfo, which + * surprisingly permits handleType == 0. + */ + assert(pExternalBufferInfo->handleType != 0); + + /* All of the current flags are for sparse which we don't support yet. + * Even when we do support it, doing sparse on external memory sounds + * sketchy. Also, just disallowing flags is the safe option. + */ + if (pExternalBufferInfo->flags) + goto unsupported; + + switch (pExternalBufferInfo->handleType) { + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT: + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT: + pExternalBufferProperties->externalMemoryProperties = nvk_dma_buf_mem_props; + return; + default: + goto unsupported; + } + +unsupported: + /* From the Vulkan 1.3.256 spec: + * + * compatibleHandleTypes must include at least handleType. + */ + pExternalBufferProperties->externalMemoryProperties = + (VkExternalMemoryProperties) { + .compatibleHandleTypes = pExternalBufferInfo->handleType, + }; +} + VKAPI_ATTR VkResult VKAPI_CALL nvk_BindBufferMemory2(VkDevice _device, uint32_t bindInfoCount, diff --git a/src/nouveau/vulkan/nvk_device_memory.c b/src/nouveau/vulkan/nvk_device_memory.c index f3ad379c2ae..d22906815b2 100644 --- a/src/nouveau/vulkan/nvk_device_memory.c +++ b/src/nouveau/vulkan/nvk_device_memory.c @@ -12,6 +12,30 @@ #include "nvtypes.h" #include "nvk_cl902d.h" +/* Supports opaque fd only */ +const VkExternalMemoryProperties nvk_opaque_fd_mem_props = { + .externalMemoryFeatures = + VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT | + VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT, + .exportFromImportedHandleTypes = + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT, + .compatibleHandleTypes = + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT, +}; + +/* Supports opaque fd and dma_buf. */ +const VkExternalMemoryProperties nvk_dma_buf_mem_props = { + .externalMemoryFeatures = + VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT | + VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT, + .exportFromImportedHandleTypes = + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT | + VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, + .compatibleHandleTypes = + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT | + VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, +}; + static VkResult zero_vram(struct nvk_device *dev, struct nouveau_ws_bo *bo) { diff --git a/src/nouveau/vulkan/nvk_device_memory.h b/src/nouveau/vulkan/nvk_device_memory.h index e1e17d45765..cb24b122b3a 100644 --- a/src/nouveau/vulkan/nvk_device_memory.h +++ b/src/nouveau/vulkan/nvk_device_memory.h @@ -36,4 +36,7 @@ void nvk_free_memory(struct nvk_device *device, struct nvk_device_memory *mem, const VkAllocationCallbacks *pAllocator); +extern const VkExternalMemoryProperties nvk_opaque_fd_mem_props; +extern const VkExternalMemoryProperties nvk_dma_buf_mem_props; + #endif diff --git a/src/nouveau/vulkan/nvk_image.c b/src/nouveau/vulkan/nvk_image.c index eed1e5da77b..17c97c88a73 100644 --- a/src/nouveau/vulkan/nvk_image.c +++ b/src/nouveau/vulkan/nvk_image.c @@ -104,6 +104,10 @@ nvk_GetPhysicalDeviceImageFormatProperties2( { VK_FROM_HANDLE(nvk_physical_device, pdev, physicalDevice); + const VkPhysicalDeviceExternalImageFormatInfo *external_info = NULL; + vk_find_struct_const(pImageFormatInfo->pNext, + PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO); + /* Initialize to zero in case we return VK_ERROR_FORMAT_NOT_SUPPORTED */ memset(&pImageFormatProperties->imageFormatProperties, 0, sizeof(pImageFormatProperties->imageFormatProperties)); @@ -171,6 +175,59 @@ nvk_GetPhysicalDeviceImageFormatProperties2( return VK_ERROR_FORMAT_NOT_SUPPORTED; } + const VkExternalMemoryProperties *ext_mem_props = NULL; + if (external_info != NULL && external_info->handleType != 0) { + bool tiling_has_explicit_layout; + switch (pImageFormatInfo->tiling) { + case VK_IMAGE_TILING_LINEAR: + case VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT: + tiling_has_explicit_layout = true; + break; + case VK_IMAGE_TILING_OPTIMAL: + tiling_has_explicit_layout = false; + break; + default: + unreachable("Unsupported VkImageTiling"); + } + + switch (external_info->handleType) { + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT: + /* No special restrictions */ + if (tiling_has_explicit_layout) { + /* With an explicit memory layout, we don't care which type of + * fd the image belongs too. Both OPAQUE_FD and DMA_BUF are + * interchangeable here. + */ + ext_mem_props = &nvk_dma_buf_mem_props; + } else { + ext_mem_props = &nvk_opaque_fd_mem_props; + } + break; + + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT: + if (!tiling_has_explicit_layout) { + return vk_errorf(pdev, VK_ERROR_FORMAT_NOT_SUPPORTED, + "VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT " + "requires VK_IMAGE_TILING_LINEAR or " + "VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT"); + } + ext_mem_props = &nvk_dma_buf_mem_props; + break; + + default: + /* From the Vulkan 1.3.256 spec: + * + * "If handleType is not compatible with the [parameters] in + * VkPhysicalDeviceImageFormatInfo2, then + * vkGetPhysicalDeviceImageFormatProperties2 returns + * VK_ERROR_FORMAT_NOT_SUPPORTED." + */ + return vk_errorf(pdev, VK_ERROR_FORMAT_NOT_SUPPORTED, + "unsupported VkExternalMemoryTypeFlagBits 0x%x", + external_info->handleType); + } + } + pImageFormatProperties->imageFormatProperties = (VkImageFormatProperties) { .maxExtent = maxExtent, .maxMipLevels = maxMipLevels, @@ -181,6 +238,21 @@ nvk_GetPhysicalDeviceImageFormatProperties2( vk_foreach_struct(s, pImageFormatProperties->pNext) { switch (s->sType) { + case VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES: { + VkExternalImageFormatProperties *p = (void *)s; + /* From the Vulkan 1.3.256 spec: + * + * "If handleType is 0, vkGetPhysicalDeviceImageFormatProperties2 + * will behave as if VkPhysicalDeviceExternalImageFormatInfo was + * not present, and VkExternalImageFormatProperties will be + * ignored." + * + * This is true if and only if ext_mem_props == NULL + */ + if (ext_mem_props != NULL) + p->externalMemoryProperties = *ext_mem_props; + break; + } default: nvk_debug_ignored_stype(s->sType); break;