mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-06 05:08:08 +02:00
gfxstream: Full emulation support for VK_EXT_image_drm_format_modifier
- Fix the checks for emulation (based on presence of the extension on the host) - Add flag in gfxstream_vk_physical_device, otherwise the real device extensions are not properly filtered when communicating with the host. - The "function" version of the check in ResourceTracker can eventually just check the flag once mesa and gfxstream objects are combined - Remove the duplicate getPhysicalDeviceFormatProperties2 impl, this is covered by the ResourceTracker impl - Add ResourceTracker impl for getImageDrmFormatModifierPropertiesEXT - Remove isDmaBufImage flag from VkImage_info, and clean up all the code associated with this flag. In on_vkCreateImage, all required info is avaialble from the extMemImageCi::handleType. In on_vkAllocateMemory, this is all associated with the tiling of the dedicatedImage for the allocation Reviewed-By: Gurchetan Singh <gurchetansingh@google.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33944>
This commit is contained in:
parent
4197081329
commit
2e15763686
5 changed files with 272 additions and 208 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -137,12 +137,20 @@ static std::vector<const char*> filteredInstanceExtensionNames(uint32_t count,
|
|||
return retList;
|
||||
}
|
||||
|
||||
static std::vector<const char*> filteredDeviceExtensionNames(uint32_t count,
|
||||
const char* const* extNames) {
|
||||
static std::vector<const char*> filteredDeviceExtensionNames(
|
||||
gfxstream_vk_physical_device* physical_device, uint32_t count, const char* const* extNames) {
|
||||
std::vector<const char*> 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<const char*> filteredExts = filteredDeviceExtensionNames(
|
||||
localCreateInfo.enabledExtensionCount, localCreateInfo.ppEnabledExtensionNames);
|
||||
gfxstream_physicalDevice, localCreateInfo.enabledExtensionCount,
|
||||
localCreateInfo.ppEnabledExtensionNames);
|
||||
localCreateInfo.enabledExtensionCount = static_cast<uint32_t>(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};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1301,12 +1301,6 @@ void ResourceTracker::setInstanceInfo(VkInstance instance, uint32_t enabledExten
|
|||
std::lock_guard<std::recursive_mutex> 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<std::recursive_mutex> 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<uint8_t*>(&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<void*>(&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<uint8_t*>(&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<void*>(&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<std::recursive_mutex> 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<std::recursive_mutex> 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<std::recursive_mutex> 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);
|
||||
|
|
|
|||
|
|
@ -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<std::string> enabledExtensions;
|
||||
// Fodder for vkEnumeratePhysicalDevices.
|
||||
std::vector<VkPhysicalDevice> physicalDevices;
|
||||
};
|
||||
|
|
@ -743,7 +758,6 @@ class ResourceTracker {
|
|||
VkPhysicalDeviceProperties props;
|
||||
VkPhysicalDeviceMemoryProperties memProps;
|
||||
uint32_t apiVersion;
|
||||
std::set<std::string> enabledExtensions;
|
||||
std::vector<std::pair<PFN_vkDeviceMemoryReportCallbackEXT, void*>>
|
||||
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
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue