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);