diff --git a/src/gfxstream/codegen/scripts/cereal/functable.py b/src/gfxstream/codegen/scripts/cereal/functable.py index a707d274c57..20906fe279d 100644 --- a/src/gfxstream/codegen/scripts/cereal/functable.py +++ b/src/gfxstream/codegen/scripts/cereal/functable.py @@ -18,6 +18,7 @@ RESOURCE_TRACKER_ENTRIES = [ "vkGetImageMemoryRequirements", "vkGetImageMemoryRequirements2", "vkGetImageMemoryRequirements2KHR", + "vkGetImageSubresourceLayout", "vkBindImageMemory", "vkBindImageMemory2", "vkBindImageMemory2KHR", diff --git a/src/gfxstream/guest/vulkan_enc/ResourceTracker.cpp b/src/gfxstream/guest/vulkan_enc/ResourceTracker.cpp index 5ac32ff2345..95e1087f57a 100644 --- a/src/gfxstream/guest/vulkan_enc/ResourceTracker.cpp +++ b/src/gfxstream/guest/vulkan_enc/ResourceTracker.cpp @@ -3782,9 +3782,8 @@ VkResult ResourceTracker::on_vkAllocateMemory(void* context, VkResult input_resu .arrayLayer = 0, }; VkSubresourceLayout subResourceLayout; - enc->vkGetImageSubresourceLayout(device, dedicatedAllocInfoPtr->image, - &imageSubresource, &subResourceLayout, - true /* do lock */); + on_vkGetImageSubresourceLayout(context, device, dedicatedAllocInfoPtr->image, + &imageSubresource, &subResourceLayout); if (!subResourceLayout.rowPitch) { mesa_loge("%s: Failed to query stride for VirtGpu resource creation."); return VK_ERROR_INITIALIZATION_FAILED; @@ -4313,6 +4312,34 @@ VkResult ResourceTracker::on_vkCreateImage(void* context, VkResult, VkDevice dev info.isDmaBufImage = isDmaBufImage; if (info.isDmaBufImage) { updateMemoryTypeBits(&memReqs.memoryTypeBits, mCaps.vulkanCapset.colorBufferMemoryIndex); + if (localCreateInfo.tiling == VK_IMAGE_TILING_OPTIMAL) { + // Linux WSI calls vkGetImageSubresourceLayout() to query the stride for swapchain + // support. Similarly, stride is also queried from vkGetImageSubresourceLayout() to + // determine the stride for colorBuffer resource creation (guest-side dmabuf resource). + // To satisfy valid usage of this API, must call on the linearPeerImage for the VkImage + // in question. As long as these two use cases match, the rowPitch won't actually be + // used by WSI. + VkImageCreateInfo linearPeerImageCreateInfo = { + .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, + .pNext = nullptr, + .flags = {}, + .imageType = VK_IMAGE_TYPE_2D, + .format = localCreateInfo.format, + .extent = localCreateInfo.extent, + .mipLevels = 1, + .arrayLayers = 1, + .samples = VK_SAMPLE_COUNT_1_BIT, + .tiling = VK_IMAGE_TILING_LINEAR, + .usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, + .sharingMode = VK_SHARING_MODE_EXCLUSIVE, + .queueFamilyIndexCount = 0, + .pQueueFamilyIndices = nullptr, + .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, + }; + res = enc->vkCreateImage(device, &linearPeerImageCreateInfo, pAllocator, + &info.linearPeerImage, true /* do lock */); + if (res != VK_SUCCESS) return res; + } } #endif @@ -5095,6 +5122,15 @@ void ResourceTracker::on_vkDestroyImage(void* context, VkDevice device, VkImage } #endif VkEncoder* enc = (VkEncoder*)context; +#if defined(LINUX_GUEST_BUILD) + auto imageInfoIt = info_VkImage.find(image); + if (imageInfoIt != info_VkImage.end()) { + auto& imageInfo = imageInfoIt->second; + if (imageInfo.linearPeerImage) { + enc->vkDestroyImage(device, imageInfo.linearPeerImage, pAllocator, true /* do lock */); + } + } +#endif enc->vkDestroyImage(device, image, pAllocator, true /* do lock */); } @@ -5142,6 +5178,23 @@ void ResourceTracker::on_vkGetImageMemoryRequirements2KHR( transformImageMemoryRequirements2ForGuest(pInfo->image, pMemoryRequirements); } +void ResourceTracker::on_vkGetImageSubresourceLayout(void* context, VkDevice device, VkImage image, + const VkImageSubresource* pSubresource, + VkSubresourceLayout* pLayout) { + VkEncoder* enc = (VkEncoder*)context; + VkImage targetImage = image; +#if defined(LINUX_GUEST_BUILD) + auto it = info_VkImage.find(image); + if (it == info_VkImage.end()) return; + const auto& info = it->second; + if (info.linearPeerImage) { + targetImage = info.linearPeerImage; + } +#endif + enc->vkGetImageSubresourceLayout(device, targetImage, pSubresource, pLayout, + true /* do lock */); +} + VkResult ResourceTracker::on_vkBindImageMemory(void* context, VkResult, VkDevice device, VkImage image, VkDeviceMemory memory, VkDeviceSize memoryOffset) { diff --git a/src/gfxstream/guest/vulkan_enc/ResourceTracker.h b/src/gfxstream/guest/vulkan_enc/ResourceTracker.h index 2040a574792..005887b8157 100644 --- a/src/gfxstream/guest/vulkan_enc/ResourceTracker.h +++ b/src/gfxstream/guest/vulkan_enc/ResourceTracker.h @@ -209,6 +209,9 @@ class ResourceTracker { void on_vkGetImageMemoryRequirements2KHR(void* context, VkDevice device, const VkImageMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements); + void on_vkGetImageSubresourceLayout(void* context, VkDevice device, VkImage image, + const VkImageSubresource* pSubresource, + VkSubresourceLayout* pLayout); VkResult on_vkBindImageMemory(void* context, VkResult input_result, VkDevice device, VkImage image, VkDeviceMemory memory, VkDeviceSize memoryOffset); @@ -783,6 +786,7 @@ class ResourceTracker { #endif #ifdef LINUX_GUEST_BUILD bool isDmaBufImage = false; + VkImage linearPeerImage = VK_NULL_HANDLE; #endif };