diff --git a/src/gfxstream/codegen/scripts/cereal/functable.py b/src/gfxstream/codegen/scripts/cereal/functable.py index 1af69d61a65..225193ad79c 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", + "vkGetImageDrmFormatModifierPropertiesEXT", "vkBindImageMemory", "vkBindImageMemory2", "vkBindImageMemory2KHR", @@ -52,6 +53,8 @@ RESOURCE_TRACKER_ENTRIES = [ "vkDestroySamplerYcbcrConversionKHR", "vkUpdateDescriptorSetWithTemplate", "vkUpdateDescriptorSetWithTemplateKHR", + "vkGetPhysicalDeviceFormatProperties2", + "vkGetPhysicalDeviceFormatProperties2KHR", "vkGetPhysicalDeviceImageFormatProperties2", "vkGetPhysicalDeviceImageFormatProperties2KHR", "vkBeginCommandBuffer", @@ -128,7 +131,6 @@ HANDWRITTEN_ENTRY_POINTS = [ # TODO: Make a codegen module (use deepcopy as reference) to make this more robust "vkAllocateMemory", "vkUpdateDescriptorSets", - "vkGetPhysicalDeviceFormatProperties2", ] # Handles that need to be translated to/from their corresponding gfxstream object types diff --git a/src/gfxstream/guest/vulkan/gfxstream_vk_device.cpp b/src/gfxstream/guest/vulkan/gfxstream_vk_device.cpp index 3e2f81dc90b..15116932701 100644 --- a/src/gfxstream/guest/vulkan/gfxstream_vk_device.cpp +++ b/src/gfxstream/guest/vulkan/gfxstream_vk_device.cpp @@ -137,12 +137,20 @@ static std::vector filteredInstanceExtensionNames(uint32_t count, return retList; } -static std::vector filteredDeviceExtensionNames(uint32_t count, - const char* const* extNames) { +static std::vector filteredDeviceExtensionNames( + gfxstream_vk_physical_device* physical_device, uint32_t count, const char* const* extNames) { std::vector retList; for (uint32_t i = 0; i < count; ++i) { auto extName = extNames[i]; - if (!isGuestOnlyDeviceExtension(extName)) { + // VK_EXT_image_drm_format_modifier + if (!strncmp(extName, VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME, + VK_MAX_EXTENSION_NAME_SIZE)) { + if (physical_device->doImageDrmFormatModifierEmulation) { + // If emulated, drop this exension from the filtered list + } else { + retList.push_back(extName); + } + } else if (!isGuestOnlyDeviceExtension(extName)) { retList.push_back(extName); } } @@ -162,7 +170,7 @@ static void get_device_extensions(VkPhysicalDevice physDevInternal, result = resources->on_vkEnumerateDeviceExtensionProperties( vkEnc, VK_SUCCESS, physDevInternal, NULL, &numDeviceExts, extProps.data()); if (VK_SUCCESS == result) { - // device extensions from gfxstream + // device extensions from the host's physical device for (uint32_t i = 0; i < numDeviceExts; i++) { for (uint32_t j = 0; j < VK_DEVICE_EXTENSION_COUNT; j++) { if (0 == strncmp(extProps[i].extensionName, @@ -190,6 +198,15 @@ static VkResult gfxstream_vk_physical_device_init( struct vk_device_extension_table supported_extensions = {}; get_device_extensions(internal_object, &supported_extensions); + // VK_EXT_image_drm_format_modifier support is either emulated, or passthrough using + // host functionality + if (!supported_extensions.EXT_image_drm_format_modifier) { + physical_device->doImageDrmFormatModifierEmulation = true; + supported_extensions.EXT_image_drm_format_modifier = true; + } else { + physical_device->doImageDrmFormatModifierEmulation = false; + } + struct vk_physical_device_dispatch_table dispatch_table; memset(&dispatch_table, 0, sizeof(struct vk_physical_device_dispatch_table)); vk_physical_device_dispatch_table_from_entrypoints( @@ -461,7 +478,8 @@ VkResult gfxstream_vk_CreateDevice(VkPhysicalDevice physicalDevice, VkDeviceCreateInfo localCreateInfo = *pCreateInfo; std::vector filteredExts = filteredDeviceExtensionNames( - localCreateInfo.enabledExtensionCount, localCreateInfo.ppEnabledExtensionNames); + gfxstream_physicalDevice, localCreateInfo.enabledExtensionCount, + localCreateInfo.ppEnabledExtensionNames); localCreateInfo.enabledExtensionCount = static_cast(filteredExts.size()); localCreateInfo.ppEnabledExtensionNames = filteredExts.data(); @@ -745,29 +763,3 @@ void gfxstream_vk_UpdateDescriptorSets(VkDevice device, uint32_t descriptorWrite internal_pDescriptorWrites.data(), descriptorCopyCount, pDescriptorCopies); } } - -void gfxstream_vk_GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice, - VkFormat format, - VkFormatProperties2* pFormatProperties) { - MESA_TRACE_SCOPE("vkGetPhysicalDeviceFormatProperties2"); - VK_FROM_HANDLE(gfxstream_vk_physical_device, gfxstream_physicalDevice, physicalDevice); - { - auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder(); - vkEnc->vkGetPhysicalDeviceFormatProperties2(gfxstream_physicalDevice->internal_object, - format, pFormatProperties, true /* do lock */); - } - VkDrmFormatModifierPropertiesListEXT* drmFmtMod = - vk_find_struct(pFormatProperties, DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT); - if (drmFmtMod) { - drmFmtMod->drmFormatModifierCount = 1; - if (drmFmtMod->pDrmFormatModifierProperties) { - drmFmtMod->pDrmFormatModifierProperties[0] = { - .drmFormatModifier = 0, - .drmFormatModifierPlaneCount = 1, - .drmFormatModifierTilingFeatures = - VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | - VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | - VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT}; - } - } -} \ No newline at end of file diff --git a/src/gfxstream/guest/vulkan_enc/ResourceTracker.cpp b/src/gfxstream/guest/vulkan_enc/ResourceTracker.cpp index b8d6398546e..6c1b2e7a493 100644 --- a/src/gfxstream/guest/vulkan_enc/ResourceTracker.cpp +++ b/src/gfxstream/guest/vulkan_enc/ResourceTracker.cpp @@ -1301,12 +1301,6 @@ void ResourceTracker::setInstanceInfo(VkInstance instance, uint32_t enabledExten std::lock_guard lock(mLock); auto& info = info_VkInstance[instance]; info.highestApiVersion = apiVersion; - - if (!ppEnabledExtensionNames) return; - - for (uint32_t i = 0; i < enabledExtensionCount; ++i) { - info.enabledExtensions.insert(ppEnabledExtensionNames[i]); - } } void ResourceTracker::setDeviceInfo(VkDevice device, VkPhysicalDevice physdev, @@ -1337,12 +1331,6 @@ void ResourceTracker::setDeviceInfo(VkDevice device, VkPhysicalDevice physdev, } extensionCreateInfo = extensionCreateInfo->pNext; } - - if (!ppEnabledExtensionNames) return; - - for (uint32_t i = 0; i < enabledExtensionCount; ++i) { - info.enabledExtensions.insert(ppEnabledExtensionNames[i]); - } } void ResourceTracker::setDeviceMemoryInfo(VkDevice device, VkDeviceMemory memory, @@ -1794,7 +1782,10 @@ VkResult ResourceTracker::on_vkEnumerateDeviceExtensionProperties( "VK_EXT_device_memory_report", #endif #ifdef LINUX_GUEST_BUILD + // Required by Zink "VK_KHR_imageless_framebuffer", + // Will be emulated on guest if not available on host + "VK_EXT_image_drm_format_modifier", #endif // Vulkan 1.3 "VK_KHR_synchronization2", @@ -1899,9 +1890,6 @@ VkResult ResourceTracker::on_vkEnumerateDeviceExtensionProperties( #ifdef LINUX_GUEST_BUILD filteredExts.push_back(VkExtensionProperties{"VK_KHR_external_memory_fd", 1}); filteredExts.push_back(VkExtensionProperties{"VK_EXT_external_memory_dma_buf", 1}); - // In case the host doesn't support format modifiers, they are emulated - // on guest side. - filteredExts.push_back(VkExtensionProperties{"VK_EXT_image_drm_format_modifier", 1}); #endif } @@ -3398,8 +3386,7 @@ VkResult ResourceTracker::on_vkAllocateMemory(void* context, VkResult input_resu VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA; #endif // VK_USE_PLATFORM_FUCHSIA exportDmabuf = - exportAllocateInfoPtr->handleTypes & (VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT | - VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT); + (exportAllocateInfoPtr->handleTypes & VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT); } else if (importAhbInfoPtr) { importAhb = true; } else if (importBufferCollectionInfoPtr) { @@ -3412,8 +3399,7 @@ VkResult ResourceTracker::on_vkAllocateMemory(void* context, VkResult input_resu vk_find_struct_const(pAllocateInfo, IMPORT_MEMORY_FD_INFO_KHR); if (importFdInfoPtr) { importDmabuf = - (importFdInfoPtr->handleType & (VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT | - VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT)); + (importFdInfoPtr->handleType & VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT); } bool isImport = importAhb || importBufferCollection || importVmo || importDmabuf; @@ -3814,7 +3800,6 @@ VkResult ResourceTracker::on_vkAllocateMemory(void* context, VkResult input_resu if (hasDedicatedImage) { VkImageCreateInfo imageCreateInfo; - bool isDmaBufImage = false; { std::lock_guard lock(mLock); @@ -3823,98 +3808,94 @@ VkResult ResourceTracker::on_vkAllocateMemory(void* context, VkResult input_resu const auto& imageInfo = it->second; imageCreateInfo = imageInfo.createInfo; - isDmaBufImage = imageInfo.isDmaBufImage; } - if (isDmaBufImage) { - const VkImageSubresource imageSubresource = { - .aspectMask = exportAllocateInfoPtr->handleTypes & - VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT - ? VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT - : VK_IMAGE_ASPECT_COLOR_BIT, - .mipLevel = 0, - .arrayLayer = 0, - }; - VkSubresourceLayout subResourceLayout; - enc->vkGetImageSubresourceLayout(device, dedicatedAllocInfoPtr->image, - &imageSubresource, &subResourceLayout, - true /* do lock */); + // Need to query the stride of the underyling image resource + // (VkSubresourceLayout::rowPitch) In most cases, the application will have created the + // VkImage w/ VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT, in which case the aspectMask to + // query is the PLANE_0_BIT resource. Otherwise, query the more generic COLOR_BIT. + // Note: For VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT, the image may actually be emulated + // with VK_IMAGE_TILING_LINEAR. + const VkImageSubresource imageSubresource = { + .aspectMask = (imageCreateInfo.tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) + ? VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT + : 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("Failed to query stride for VirtGpu resource creation."); + return VK_ERROR_INITIALIZATION_FAILED; + } - if (!subResourceLayout.rowPitch) { - mesa_loge("Failed to query stride for VirtGpu resource creation."); - return VK_ERROR_INITIALIZATION_FAILED; + 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; + } + + if (mCaps.vulkanCapset.alwaysBlob) { + struct gfxstreamResourceCreate3d create3d = {}; + struct VirtGpuExecBuffer exec = {}; + struct gfxstreamPlaceholderCommandVk placeholderCmd = {}; + struct VirtGpuCreateBlob createBlob = {}; + + create3d.hdr.opCode = GFXSTREAM_RESOURCE_CREATE_3D; + create3d.bind = bind; + create3d.target = target; + create3d.format = virglFormat; + create3d.width = imageCreateInfo.extent.width; + create3d.height = imageCreateInfo.extent.height; + create3d.blobId = ++mAtomicId; + + createBlob.blobCmd = reinterpret_cast(&create3d); + createBlob.blobCmdSize = sizeof(create3d); + createBlob.blobMem = kBlobMemHost3d; + createBlob.flags = kBlobFlagShareable | kBlobFlagCrossDevice; + createBlob.blobId = create3d.blobId; + createBlob.size = finalAllocInfo.allocationSize; + + bufferBlob = instance->createBlob(createBlob); + if (!bufferBlob) return VK_ERROR_OUT_OF_DEVICE_MEMORY; + + placeholderCmd.hdr.opCode = GFXSTREAM_PLACEHOLDER_COMMAND_VK; + exec.command = static_cast(&placeholderCmd); + exec.command_size = sizeof(placeholderCmd); + exec.flags = kRingIdx; + exec.ring_idx = 1; + if (instance->execBuffer(exec, bufferBlob.get())) { + mesa_loge("Failed to execbuffer placeholder command."); + return VK_ERROR_OUT_OF_HOST_MEMORY; } - 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; - } - - if (mCaps.vulkanCapset.alwaysBlob) { - struct gfxstreamResourceCreate3d create3d = {}; - struct VirtGpuExecBuffer exec = {}; - struct gfxstreamPlaceholderCommandVk placeholderCmd = {}; - struct VirtGpuCreateBlob createBlob = {}; - - create3d.hdr.opCode = GFXSTREAM_RESOURCE_CREATE_3D; - create3d.bind = bind; - create3d.target = target; - create3d.format = virglFormat; - create3d.width = imageCreateInfo.extent.width; - create3d.height = imageCreateInfo.extent.height; - create3d.blobId = ++mAtomicId; - - createBlob.blobCmd = reinterpret_cast(&create3d); - createBlob.blobCmdSize = sizeof(create3d); - createBlob.blobMem = kBlobMemHost3d; - createBlob.flags = kBlobFlagShareable | kBlobFlagCrossDevice; - createBlob.blobId = create3d.blobId; - createBlob.size = finalAllocInfo.allocationSize; - - bufferBlob = instance->createBlob(createBlob); - if (!bufferBlob) return VK_ERROR_OUT_OF_DEVICE_MEMORY; - - placeholderCmd.hdr.opCode = GFXSTREAM_PLACEHOLDER_COMMAND_VK; - exec.command = static_cast(&placeholderCmd); - exec.command_size = sizeof(placeholderCmd); - exec.flags = kRingIdx; - exec.ring_idx = 1; - if (instance->execBuffer(exec, bufferBlob.get())) { - mesa_loge("Failed to execbuffer placeholder command."); - return VK_ERROR_OUT_OF_HOST_MEMORY; - } - - if (bufferBlob->wait()) { - mesa_loge("Failed to wait for blob."); - return VK_ERROR_OUT_OF_HOST_MEMORY; - } - } else { - bufferBlob = instance->createResource( - imageCreateInfo.extent.width, imageCreateInfo.extent.height, - subResourceLayout.rowPitch, - subResourceLayout.rowPitch * imageCreateInfo.extent.height, virglFormat, - target, bind); - if (!bufferBlob) { - mesa_loge("Failed to create colorBuffer resource for Image memory"); - return VK_ERROR_OUT_OF_DEVICE_MEMORY; - } - if (bufferBlob->wait()) { - mesa_loge("Failed to wait for colorBuffer resource for Image memory"); - return VK_ERROR_OUT_OF_DEVICE_MEMORY; - } + if (bufferBlob->wait()) { + mesa_loge("Failed to wait for blob."); + return VK_ERROR_OUT_OF_HOST_MEMORY; } } else { - mesa_logw( - "The VkMemoryDedicatedAllocateInfo::image associated with VkDeviceMemory " - "allocation cannot be used to create exportable resource " - "(VkExportMemoryAllocateInfo).\n"); + bufferBlob = instance->createResource( + imageCreateInfo.extent.width, imageCreateInfo.extent.height, + subResourceLayout.rowPitch, + subResourceLayout.rowPitch * imageCreateInfo.extent.height, virglFormat, target, + bind); + if (!bufferBlob) { + mesa_loge("Failed to create colorBuffer resource for Image memory"); + return VK_ERROR_OUT_OF_DEVICE_MEMORY; + } + if (bufferBlob->wait()) { + mesa_loge("Failed to wait for colorBuffer resource for Image memory"); + return VK_ERROR_OUT_OF_DEVICE_MEMORY; + } } } else if (hasDedicatedBuffer) { uint32_t virglFormat = VIRGL_FORMAT_R8_UNORM; @@ -4268,10 +4249,10 @@ VkResult ResourceTracker::on_vkCreateImage(void* context, VkResult, VkDevice dev } #if defined(LINUX_GUEST_BUILD) - bool isDmaBufImage = false; VkImageDrmFormatModifierExplicitCreateInfoEXT localDrmFormatModifierInfo; VkImageDrmFormatModifierListCreateInfoEXT localDrmFormatModifierList; + // If the VkImage will be bound to guest-dmabuf memory if (extImgCiPtr && (extImgCiPtr->handleTypes & VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT)) { const wsi_image_create_info* wsiImageCi = @@ -4289,9 +4270,35 @@ VkResult ResourceTracker::on_vkCreateImage(void* context, VkResult, VkDevice dev vk_find_struct_const(pCreateInfo, IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT); const VkImageDrmFormatModifierListCreateInfoEXT* drmFmtModList = vk_find_struct_const(pCreateInfo, IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT); - if (drmFmtMod || drmFmtModList) { - if (getHostDeviceExtensionIndex(VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME) != - -1) { + if ((pCreateInfo->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) && + (drmFmtMod || drmFmtModList)) { + VkPhysicalDevice physicalDevice; + { + std::lock_guard lock(mLock); + auto it = info_VkDevice.find(device); + if (it == info_VkDevice.end()) return VK_ERROR_UNKNOWN; + physicalDevice = it->second.physdev; + } + if (doImageDrmFormatModifierEmulation(physicalDevice)) { + bool canUseLinearModifier = + (drmFmtMod && drmFmtMod->drmFormatModifier == DRM_FORMAT_MOD_LINEAR) || + std::any_of( + drmFmtModList->pDrmFormatModifiers, + drmFmtModList->pDrmFormatModifiers + drmFmtModList->drmFormatModifierCount, + [](const uint64_t mod) { return mod == DRM_FORMAT_MOD_LINEAR; }); + // host doesn't support DRM format modifiers, try emulating + if (canUseLinearModifier) { + mesa_logd( + "vkCreateImage: emulating DRM_FORMAT_MOD_LINEAR with " + "VK_IMAGE_TILING_LINEAR"); + localCreateInfo.tiling = VK_IMAGE_TILING_LINEAR; + } else { + mesa_loge( + "Host does not support DRM format modifiers; DRM_FORMAT_MOD_LINEAR must be " + "provided, as it is the only format modifier that can be emulated"); + return VK_ERROR_FORMAT_NOT_SUPPORTED; + } + } else { // host supports DRM format modifiers => forward the struct if (drmFmtMod) { localDrmFormatModifierInfo = vk_make_orphan_copy(*drmFmtMod); @@ -4301,24 +4308,8 @@ VkResult ResourceTracker::on_vkCreateImage(void* context, VkResult, VkDevice dev localDrmFormatModifierList = vk_make_orphan_copy(*drmFmtModList); vk_append_struct(&structChainIter, &localDrmFormatModifierList); } - } else { - bool canUseLinearModifier = - (drmFmtMod && drmFmtMod->drmFormatModifier == DRM_FORMAT_MOD_LINEAR) || - std::any_of( - drmFmtModList->pDrmFormatModifiers, - drmFmtModList->pDrmFormatModifiers + drmFmtModList->drmFormatModifierCount, - [](const uint64_t mod) { return mod == DRM_FORMAT_MOD_LINEAR; }); - // host doesn't support DRM format modifiers, try emulating - if (canUseLinearModifier) { - mesa_logd("emulating DRM_FORMAT_MOD_LINEAR with VK_IMAGE_TILING_LINEAR"); - localCreateInfo.tiling = VK_IMAGE_TILING_LINEAR; - } else { - return VK_ERROR_VALIDATION_FAILED_EXT; - } } } - - isDmaBufImage = true; } #endif @@ -4507,8 +4498,8 @@ VkResult ResourceTracker::on_vkCreateImage(void* context, VkResult, VkDevice dev if (mCaps.vulkanCapset.colorBufferMemoryIndex == 0xFFFFFFFF) { mCaps.vulkanCapset.colorBufferMemoryIndex = getColorBufferMemoryIndex(context, device); } - info.isDmaBufImage = isDmaBufImage; - if (info.isDmaBufImage) { + if (extImgCiPtr && + (extImgCiPtr->handleTypes & VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT)) { updateMemoryTypeBits(&memReqs.memoryTypeBits, mCaps.vulkanCapset.colorBufferMemoryIndex); } #endif @@ -5357,6 +5348,31 @@ void ResourceTracker::on_vkGetImageMemoryRequirements2KHR( transformImageMemoryRequirements2ForGuest(pInfo->image, pMemoryRequirements); } +VkResult ResourceTracker::on_vkGetImageDrmFormatModifierPropertiesEXT( + void* context, VkResult, VkDevice device, VkImage image, + VkImageDrmFormatModifierPropertiesEXT* pProperties) { +#ifdef LINUX_GUEST_BUILD + auto it = info_VkDevice.find(device); + if (it == info_VkDevice.end()) return VK_ERROR_UNKNOWN; + if (doImageDrmFormatModifierEmulation(it->second.physdev)) { + // This is the only format modifier that will be used in emulation + pProperties->drmFormatModifier = DRM_FORMAT_MOD_LINEAR; + return VK_SUCCESS; + } else { + // Passthrough to host + VkEncoder* enc = (VkEncoder*)context; + return enc->vkGetImageDrmFormatModifierPropertiesEXT(device, image, pProperties, + true /* do lock */); + } +#else + (void)context; + (void)device; + (void)image; + (void)pProperties; + return VK_ERROR_INCOMPATIBLE_DRIVER; +#endif +} + VkResult ResourceTracker::on_vkBindImageMemory(void* context, VkResult, VkDevice device, VkImage image, VkDeviceMemory memory, VkDeviceSize memoryOffset) { @@ -6673,6 +6689,49 @@ void ResourceTracker::on_vkUpdateDescriptorSetWithTemplateKHR( pData); } +#ifdef LINUX_GUEST_BUILD +static void fillEmulatedDrmFormatModPropsList( + const VkFormatProperties* pFormatProperties, + VkDrmFormatModifierPropertiesListEXT* emulatedDrmFmtModPropsList) { + mesa_logd( + "VkDrmFormatModifierPropertiesListEXT: emulating DRM_FORMAT_MOD_LINEAR with linear tiling " + "features"); + emulatedDrmFmtModPropsList->drmFormatModifierCount = 1; + if (emulatedDrmFmtModPropsList->pDrmFormatModifierProperties) { + emulatedDrmFmtModPropsList->pDrmFormatModifierProperties[0] = { + .drmFormatModifier = DRM_FORMAT_MOD_LINEAR, + .drmFormatModifierPlaneCount = 1, + .drmFormatModifierTilingFeatures = VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | + VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | + VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT, + }; + }; +} +#endif + +void ResourceTracker::on_vkGetPhysicalDeviceFormatProperties2( + void* context, VkPhysicalDevice physicalDevice, VkFormat format, + VkFormatProperties2* pFormatProperties) { + VkEncoder* enc = (VkEncoder*)context; + enc->vkGetPhysicalDeviceFormatProperties2(physicalDevice, format, pFormatProperties, + true /* do lock */); + +#ifdef LINUX_GUEST_BUILD + VkDrmFormatModifierPropertiesListEXT* emulatedDrmFmtModPropsList = + vk_find_struct(pFormatProperties, DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT); + if (emulatedDrmFmtModPropsList && doImageDrmFormatModifierEmulation(physicalDevice)) { + fillEmulatedDrmFormatModPropsList(&pFormatProperties->formatProperties, + emulatedDrmFmtModPropsList); + } +#endif +} + +void ResourceTracker::on_vkGetPhysicalDeviceFormatProperties2KHR( + void* context, VkPhysicalDevice physicalDevice, VkFormat format, + VkFormatProperties2* pFormatProperties) { + on_vkGetPhysicalDeviceFormatProperties2(context, physicalDevice, format, pFormatProperties); +} + VkResult ResourceTracker::on_vkGetPhysicalDeviceImageFormatProperties2_common( bool isKhr, void* context, VkResult input_result, VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, @@ -6728,20 +6787,27 @@ VkResult ResourceTracker::on_vkGetPhysicalDeviceImageFormatProperties2_common( const VkPhysicalDeviceImageDrmFormatModifierInfoEXT* drmFmtMod = vk_find_struct_const(pImageFormatInfo, PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT); VkDrmFormatModifierPropertiesListEXT* emulatedDrmFmtModPropsList = nullptr; - if (drmFmtMod && - getHostDeviceExtensionIndex(VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME) == -1) { - if (drmFmtMod->drmFormatModifier != DRM_FORMAT_MOD_LINEAR) { - return VK_ERROR_FORMAT_NOT_SUPPORTED; + if (drmFmtMod) { + if (doImageDrmFormatModifierEmulation(physicalDevice)) { + emulatedDrmFmtModPropsList = + vk_find_struct(pImageFormatProperties, DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT); + + if (drmFmtMod->drmFormatModifier == DRM_FORMAT_MOD_LINEAR) { + // Remove the drmFmtMod from the localImageFormatInfo + vk_filter_struct(&localImageFormatInfo, + PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT); + mesa_logd( + "getPhysicalDeviceImageFormatProperties2: emulating DRM_FORMAT_MOD_LINEAR with " + "VK_IMAGE_TILING_LINEAR"); + localImageFormatInfo.tiling = VK_IMAGE_TILING_LINEAR; + localImageFormatInfo.usage &= + ~(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT); + } else { + return VK_ERROR_FORMAT_NOT_SUPPORTED; + } + } else { + // Host supports DRM format modifiers => leave the input unchanged. } - mesa_logd("emulating DRM_FORMAT_MOD_LINEAR with VK_IMAGE_TILING_OPTIMAL"); - emulatedDrmFmtModPropsList = - vk_find_struct(pImageFormatProperties, DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT); - localImageFormatInfo.tiling = VK_IMAGE_TILING_LINEAR; - localImageFormatInfo.usage &= - ~(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT); - pImageFormatInfo = &localImageFormatInfo; - // Leave drmFormatMod in the input; it should be ignored when - // tiling is not VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT } #endif // LINUX_GUEST_BUILD @@ -6762,23 +6828,19 @@ VkResult ResourceTracker::on_vkGetPhysicalDeviceImageFormatProperties2_common( VkFormatProperties formatProperties; enc->vkGetPhysicalDeviceFormatProperties(physicalDevice, localImageFormatInfo.format, &formatProperties, true /* do lock */); - - emulatedDrmFmtModPropsList->drmFormatModifierCount = 1; - if (emulatedDrmFmtModPropsList->pDrmFormatModifierProperties) { - emulatedDrmFmtModPropsList->pDrmFormatModifierProperties[0] = { - .drmFormatModifier = DRM_FORMAT_MOD_LINEAR, - .drmFormatModifierPlaneCount = 1, - .drmFormatModifierTilingFeatures = formatProperties.linearTilingFeatures, - }; - } + fillEmulatedDrmFormatModPropsList(&formatProperties, emulatedDrmFmtModPropsList); } - if (ext_img_info && - ext_img_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT) { - ext_img_properties->externalMemoryProperties.externalMemoryFeatures |= - VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT; - ext_img_properties->externalMemoryProperties.exportFromImportedHandleTypes = - ext_img_properties->externalMemoryProperties.compatibleHandleTypes = - VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT; + if (ext_img_properties) { + if (ext_img_info) { + if (ext_img_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT) { + ext_img_properties->externalMemoryProperties = { + .externalMemoryFeatures = VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT | + VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT, + .exportFromImportedHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, + .compatibleHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, + }; + } + } } #endif // LINUX_GUEST_BUILD @@ -7442,23 +7504,19 @@ uint32_t ResourceTracker::getApiVersionFromDevice(VkDevice device) { return api; } -bool ResourceTracker::hasInstanceExtension(VkInstance instance, const std::string& name) { +#ifdef LINUX_GUEST_BUILD +bool ResourceTracker::doImageDrmFormatModifierEmulation(VkPhysicalDevice physicalDevice) { std::lock_guard lock(mLock); - auto it = info_VkInstance.find(instance); - if (it == info_VkInstance.end()) return false; + bool hostSupportsImageDrmFormatModifiers = + getHostDeviceExtensionIndex(VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME) != -1; - return it->second.enabledExtensions.find(name) != it->second.enabledExtensions.end(); -} - -bool ResourceTracker::hasDeviceExtension(VkDevice device, const std::string& name) { - std::lock_guard lock(mLock); - - auto it = info_VkDevice.find(device); - if (it == info_VkDevice.end()) return false; - - return it->second.enabledExtensions.find(name) != it->second.enabledExtensions.end(); + // If the host device supports the extension, then this gets passed through for + // all functionality relating to the extension. If it doesn't, then this is emulated + // in the guest-side driver + return !hostSupportsImageDrmFormatModifiers; } +#endif VkDevice ResourceTracker::getDevice(VkCommandBuffer commandBuffer) const { struct goldfish_VkCommandBuffer* cb = as_goldfish_VkCommandBuffer(commandBuffer); diff --git a/src/gfxstream/guest/vulkan_enc/ResourceTracker.h b/src/gfxstream/guest/vulkan_enc/ResourceTracker.h index e0cc1f462ce..edec3f13b43 100644 --- a/src/gfxstream/guest/vulkan_enc/ResourceTracker.h +++ b/src/gfxstream/guest/vulkan_enc/ResourceTracker.h @@ -220,6 +220,9 @@ class ResourceTracker { void on_vkGetImageMemoryRequirements2KHR(void* context, VkDevice device, const VkImageMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements); + VkResult on_vkGetImageDrmFormatModifierPropertiesEXT( + void* context, VkResult input_result, VkDevice device, VkImage image, + VkImageDrmFormatModifierPropertiesEXT* pProperties); VkResult on_vkBindImageMemory(void* context, VkResult input_result, VkDevice device, VkImage image, VkDeviceMemory memory, VkDeviceSize memoryOffset); @@ -451,6 +454,14 @@ class ResourceTracker { VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData); + void on_vkGetPhysicalDeviceFormatProperties2(void* context, VkPhysicalDevice physicalDevice, + VkFormat format, + VkFormatProperties2* pFormatProperties); + + void on_vkGetPhysicalDeviceFormatProperties2KHR(void* context, VkPhysicalDevice physicalDevice, + VkFormat format, + VkFormatProperties2* pFormatProperties); + VkResult on_vkGetPhysicalDeviceImageFormatProperties2( void* context, VkResult input_result, VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, @@ -556,13 +567,18 @@ class ResourceTracker { uint32_t getStreamFeatures() const; uint32_t getApiVersionFromInstance(VkInstance instance); uint32_t getApiVersionFromDevice(VkDevice device); - bool hasInstanceExtension(VkInstance instance, const std::string& name); - bool hasDeviceExtension(VkDevice instance, const std::string& name); VkDevice getDevice(VkCommandBuffer commandBuffer) const; void addToCommandPool(VkCommandPool commandPool, uint32_t commandBufferCount, VkCommandBuffer* pCommandBuffers); void resetCommandPoolStagingInfo(VkCommandPool commandPool); +#ifdef LINUX_GUEST_BUILD + // TODO: This information is tracked in + // gfxstream_vk_physical_device::doImageDrmFormatModifierEmulation, but mesa objects need to be + // combined with gfxstream objects + bool doImageDrmFormatModifierEmulation(VkPhysicalDevice physicalDevice); +#endif + #ifdef __GNUC__ #define ALWAYS_INLINE_GFXSTREAM #elif @@ -733,7 +749,6 @@ class ResourceTracker { struct VkInstance_Info { uint32_t highestApiVersion; - std::set enabledExtensions; // Fodder for vkEnumeratePhysicalDevices. std::vector physicalDevices; }; @@ -743,7 +758,6 @@ class ResourceTracker { VkPhysicalDeviceProperties props; VkPhysicalDeviceMemoryProperties memProps; uint32_t apiVersion; - std::set enabledExtensions; std::vector> deviceMemoryReportCallbacks; }; @@ -800,9 +814,6 @@ class ResourceTracker { #endif #ifdef VK_USE_PLATFORM_FUCHSIA bool isSysmemBackedMemory = false; -#endif -#ifdef LINUX_GUEST_BUILD - bool isDmaBufImage = false; #endif }; diff --git a/src/gfxstream/guest/vulkan_enc/gfxstream_vk_private.h b/src/gfxstream/guest/vulkan_enc/gfxstream_vk_private.h index 164c227d6fb..dcec895bf45 100644 --- a/src/gfxstream/guest/vulkan_enc/gfxstream_vk_private.h +++ b/src/gfxstream/guest/vulkan_enc/gfxstream_vk_private.h @@ -71,6 +71,7 @@ struct gfxstream_vk_physical_device { struct wsi_device wsi_device; const struct vk_sync_type* sync_types[2]; struct gfxstream_vk_instance* instance; + bool doImageDrmFormatModifierEmulation; VkPhysicalDevice internal_object; };