gfxstream: Switch to using scanout path with native DRM images for Linux WSI BUG=343234676 TEST=compile Change-Id: Ibbdb41b078eda8aa27c70caee0d6d3a8e5fa0758
diff --git a/guest/vulkan_enc/ResourceTracker.cpp b/guest/vulkan_enc/ResourceTracker.cpp index f6efb7a..948c316 100644 --- a/guest/vulkan_enc/ResourceTracker.cpp +++ b/guest/vulkan_enc/ResourceTracker.cpp
@@ -727,14 +727,6 @@ auto height = info.createInfo.extent.height; reqs->size = width * height * 4; } -#elif defined(__linux__) && !defined(VK_USE_PLATFORM_ANDROID_KHR) - auto it = info_VkImage.find(image); - if (it == info_VkImage.end()) return; - auto& info = it->second; - if (info.isWsiImage) { - static const uint32_t kColorBufferBpp = 4; - reqs->size = kColorBufferBpp * info.createInfo.extent.width * info.createInfo.extent.height; - } #else // Bypass "unused parameter" checks. (void)image; @@ -2905,24 +2897,6 @@ return virglFormat; } -static bool getVirtGpuFormatParams(const VkFormat vkFormat, uint32_t* virglFormat, uint32_t* target, - uint32_t* bind, uint32_t* bpp) { - *virglFormat = getVirglFormat(vkFormat); - switch (*virglFormat) { - case VIRGL_FORMAT_R8G8B8A8_UNORM: - case VIRGL_FORMAT_B8G8R8A8_UNORM: - *target = PIPE_TEXTURE_2D; - *bind = VIRGL_BIND_RENDER_TARGET; - *bpp = 4; - break; - default: - /* Format not recognized */ - return false; - } - - return true; -} - CoherentMemoryPtr ResourceTracker::createCoherentMemory( VkDevice device, VkDeviceMemory mem, const VkMemoryAllocateInfo& hostAllocationInfo, VkEncoder* enc, VkResult& res) { @@ -3775,25 +3749,17 @@ #endif VirtGpuResourcePtr colorBufferBlob = nullptr; -#if defined(__linux__) && !defined(VK_USE_PLATFORM_ANDROID_KHR) +#if defined(LINUX_GUEST_BUILD) if (exportDmabuf) { VirtGpuDevice* instance = VirtGpuDevice::getInstance(); - // // TODO: any special action for VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA? Can mark - // special state if needed. - // // const wsi_memory_allocate_info* wsiAllocateInfoPtr = - // vk_find_struct<wsi_memory_allocate_info>(pAllocateInfo); bool hasDedicatedImage = dedicatedAllocInfoPtr && (dedicatedAllocInfoPtr->image != VK_NULL_HANDLE); bool hasDedicatedBuffer = dedicatedAllocInfoPtr && (dedicatedAllocInfoPtr->buffer != VK_NULL_HANDLE); - if (!hasDedicatedImage && !hasDedicatedBuffer) { - mesa_loge( - "dma-buf exportable memory requires dedicated Image or Buffer information.\n"); - return VK_ERROR_OUT_OF_DEVICE_MEMORY; - } if (hasDedicatedImage) { VkImageCreateInfo imageCreateInfo; + bool isDmaBufImage = false; { AutoLock<RecursiveLock> lock(mLock); @@ -3802,67 +3768,62 @@ const auto& imageInfo = it->second; imageCreateInfo = imageInfo.createInfo; + isDmaBufImage = imageInfo.isDmaBufImage; } - uint32_t virglFormat = 0; - uint32_t target = 0; - uint32_t bind = 0; - uint32_t bpp = 0; - if (!gfxstream::vk::getVirtGpuFormatParams(imageCreateInfo.format, &virglFormat, - &target, &bind, &bpp)) { - mesa_loge("%s: Unsupported VK format for VirtGpu resource, vkFormat: 0x%x", - __func__, imageCreateInfo.format); - return VK_ERROR_FORMAT_NOT_SUPPORTED; - } - const uint32_t stride = imageCreateInfo.extent.width * bpp; - colorBufferBlob = instance->createResource(imageCreateInfo.extent.width, - imageCreateInfo.extent.height, stride, - virglFormat, target, bind); - if (!colorBufferBlob) { - mesa_loge("%s: Failed to create colorBuffer resource for Image memory\n", __func__); - return VK_ERROR_OUT_OF_DEVICE_MEMORY; - } - if (0 != colorBufferBlob->wait()) { - mesa_loge("%s: Failed to wait for colorBuffer resource for Image memory\n", - __func__); - return VK_ERROR_OUT_OF_DEVICE_MEMORY; - } - } + // TODO (b/326956485): Support DRM format modifiers for dmabuf memory + // For now, can only externalize memory for linear images + if (isDmaBufImage) { + const VkImageSubresource imageSubresource = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .mipLevel = 0, + .arrayLayer = 0, + }; + VkSubresourceLayout subResourceLayout; + enc->vkGetImageSubresourceLayout(device, dedicatedAllocInfoPtr->image, + &imageSubresource, &subResourceLayout, + true /* do lock */); + if (!subResourceLayout.rowPitch) { + mesa_loge("%s: Failed to query stride for VirtGpu resource creation."); + return VK_ERROR_INITIALIZATION_FAILED; + } - if (hasDedicatedBuffer) { - VkBufferCreateInfo bufferCreateInfo; - { - AutoLock<RecursiveLock> lock(mLock); - - auto it = info_VkBuffer.find(dedicatedAllocInfoPtr->buffer); - if (it == info_VkBuffer.end()) return VK_ERROR_INITIALIZATION_FAILED; - const auto& bufferInfo = it->second; - bufferCreateInfo = bufferInfo.createInfo; + uint32_t virglFormat = gfxstream::vk::getVirglFormat(imageCreateInfo.format); + if (!virglFormat) { + mesa_loge("Unsupported VK format for VirtGpu resource, vkFormat: 0x%x", + imageCreateInfo.format); + return VK_ERROR_FORMAT_NOT_SUPPORTED; + } + const uint32_t target = PIPE_TEXTURE_2D; + uint32_t bind = VIRGL_BIND_RENDER_TARGET; + if (VK_IMAGE_TILING_LINEAR == imageCreateInfo.tiling) { + bind |= VIRGL_BIND_LINEAR; + } + colorBufferBlob = instance->createResource( + imageCreateInfo.extent.width, imageCreateInfo.extent.height, + subResourceLayout.rowPitch, virglFormat, target, bind); + if (!colorBufferBlob) { + mesa_loge("Failed to create colorBuffer resource for Image memory"); + return VK_ERROR_OUT_OF_DEVICE_MEMORY; + } + if (!colorBufferBlob->wait()) { + mesa_loge("Failed to wait for colorBuffer resource for Image memory"); + return VK_ERROR_OUT_OF_DEVICE_MEMORY; + } + } else { + mesa_logw( + "The VkMemoryDedicatedAllocateInfo::image associated with VkDeviceMemory " + "allocation cannot be used to create exportable resource " + "(VkExportMemoryAllocateInfo).\n"); } - const VkFormat vkFormat = VK_FORMAT_R8G8B8A8_UNORM; - uint32_t virglFormat = 0; - uint32_t target = 0; - uint32_t bind = 0; - uint32_t bpp = 0; - if (!gfxstream::vk::getVirtGpuFormatParams(vkFormat, &virglFormat, &target, &bind, - &bpp)) { - mesa_loge("%s: Unexpected error getting VirtGpu format params for vkFormat: 0x%x", - __func__, vkFormat); - return VK_ERROR_FORMAT_NOT_SUPPORTED; - } - - colorBufferBlob = instance->createResource(bufferCreateInfo.size / bpp, 1, virglFormat, - target, bind, bpp); - if (!colorBufferBlob) { - mesa_loge("%s: Failed to create colorBuffer resource for Buffer memory\n", - __func__); - return VK_ERROR_OUT_OF_DEVICE_MEMORY; - } - if (0 != colorBufferBlob->wait()) { - mesa_loge("%s: Failed to wait for colorBuffer resource for Buffer memory\n", - __func__); - return VK_ERROR_OUT_OF_DEVICE_MEMORY; - } + } else if (hasDedicatedBuffer) { + mesa_logw( + "VkDeviceMemory allocated with VkMemoryDedicatedAllocateInfo::buffer cannot be " + "exported (VkExportMemoryAllocateInfo)"); + } else { + mesa_logw( + "VkDeviceMemory is not exportable (VkExportMemoryAllocateInfo). Requires " + "VkMemoryDedicatedAllocateInfo::image to create external resource."); } } @@ -4134,20 +4095,31 @@ vk_append_struct(&structChainIter, &localExtImgCi); } - bool isWsiImage = false; - -#if defined(__linux__) && !defined(VK_USE_PLATFORM_ANDROID_KHR) +#if defined(LINUX_GUEST_BUILD) + bool isDmaBufImage = false; if (extImgCiPtr && (extImgCiPtr->handleTypes & VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT)) { - // Assumes that handleType with DMA_BUF_BIT indicates creation of a - // image for WSI use; no other external dma_buf usage is supported - isWsiImage = true; - // Must be linear. Otherwise querying stride and other properties - // can be implementation-dependent. - localCreateInfo.tiling = VK_IMAGE_TILING_LINEAR; - if (gfxstream::vk::getVirglFormat(localCreateInfo.format) < 0) { - localCreateInfo.format = VK_FORMAT_R8G8B8A8_UNORM; + const wsi_image_create_info* wsiImageCi = + vk_find_struct<wsi_image_create_info>(pCreateInfo); + if (wsiImageCi) { + if (!wsiImageCi->scanout) { + mesa_logd( + "gfxstream only supports native DRM image scanout path for Linux WSI " + "(wsi_image_create_info::scanout)"); + return VK_ERROR_INITIALIZATION_FAILED; + } + // Linux WSI creates swapchain images with VK_IMAGE_CREATE_ALIAS_BIT. Vulkan spec + // states: "If the pNext chain includes a VkExternalMemoryImageCreateInfo or + // VkExternalMemoryImageCreateInfoNV structure whose handleTypes member is not 0, it is + // as if VK_IMAGE_CREATE_ALIAS_BIT is set." To avoid flag mismatches on host driver, + // remove the VK_IMAGE_CREATE_ALIAS_BIT here. + localCreateInfo.flags &= ~VK_IMAGE_CREATE_ALIAS_BIT; + // TODO (b/326956485): DRM format modifiers to support client/compositor awareness + // For now, override WSI images to use linear tiling, as compositor will default to + // DRM_FORMAT_MOD_LINEAR. + localCreateInfo.tiling = VK_IMAGE_TILING_LINEAR; } + isDmaBufImage = true; } #endif @@ -4322,19 +4294,25 @@ } #endif - info.isWsiImage = isWsiImage; - // Delete `protocolVersion` check goldfish drivers are gone. -#if defined(VK_USE_PLATFORM_ANDROID_KHR) || defined(__linux__) +#if defined(VK_USE_PLATFORM_ANDROID_KHR) if (mCaps.vulkanCapset.colorBufferMemoryIndex == 0xFFFFFFFF) { mCaps.vulkanCapset.colorBufferMemoryIndex = getColorBufferMemoryIndex(context, device); } - if (isWsiImage || - (extImgCiPtr && (extImgCiPtr->handleTypes & + if ((extImgCiPtr && (extImgCiPtr->handleTypes & VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID))) { updateMemoryTypeBits(&memReqs.memoryTypeBits, mCaps.vulkanCapset.colorBufferMemoryIndex); } #endif +#if defined(LINUX_GUEST_BUILD) + if (mCaps.vulkanCapset.colorBufferMemoryIndex == 0xFFFFFFFF) { + mCaps.vulkanCapset.colorBufferMemoryIndex = getColorBufferMemoryIndex(context, device); + } + info.isDmaBufImage = isDmaBufImage; + if (info.isDmaBufImage) { + updateMemoryTypeBits(&memReqs.memoryTypeBits, mCaps.vulkanCapset.colorBufferMemoryIndex); + } +#endif if (info.baseRequirementsKnown) { transformImageMemoryRequirementsForGuestLocked(*pImage, &memReqs);