mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-08 06:58:05 +02:00
gfxstream: Switch to using scanout path with native DRM images for Linux WSI
Reviewed-by: Aaron Ruby <aruby@blackberry.com> Acked-by: Yonggang Luo <luoyonggang@gmail.com> Acked-by: Adam Jackson <ajax@redhat.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27246>
This commit is contained in:
parent
6b92e632da
commit
cf8e324fe5
4 changed files with 99 additions and 112 deletions
|
|
@ -33,8 +33,8 @@ VkResult gfxstream_vk_wsi_init(struct gfxstream_vk_physical_device* physical_dev
|
|||
|
||||
// Allow guest-side modifier code paths
|
||||
physical_device->wsi_device.supports_modifiers = true;
|
||||
// For DRM, uses the buffer-blit path for WSI images
|
||||
physical_device->wsi_device.supports_scanout = false;
|
||||
// Support wsi_image_create_info::scanout
|
||||
physical_device->wsi_device.supports_scanout = true;
|
||||
|
||||
physical_device->vk.wsi_device = &physical_device->wsi_device;
|
||||
|
||||
|
|
|
|||
|
|
@ -728,14 +728,6 @@ void ResourceTracker::transformImageMemoryRequirementsForGuestLocked(VkImage ima
|
|||
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;
|
||||
|
|
@ -2907,24 +2899,6 @@ static uint32_t getVirglFormat(VkFormat vkFormat) {
|
|||
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) {
|
||||
|
|
@ -3777,25 +3751,17 @@ VkResult ResourceTracker::on_vkAllocateMemory(void* context, VkResult input_resu
|
|||
#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);
|
||||
|
||||
|
|
@ -3804,67 +3770,62 @@ VkResult ResourceTracker::on_vkAllocateMemory(void* context, VkResult input_resu
|
|||
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;
|
||||
}
|
||||
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;
|
||||
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");
|
||||
}
|
||||
} 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.");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4136,20 +4097,31 @@ VkResult ResourceTracker::on_vkCreateImage(void* context, VkResult, VkDevice dev
|
|||
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
|
||||
|
||||
|
|
@ -4324,19 +4296,25 @@ VkResult ResourceTracker::on_vkCreateImage(void* context, VkResult, VkDevice dev
|
|||
}
|
||||
#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);
|
||||
|
|
|
|||
|
|
@ -781,7 +781,9 @@ class ResourceTracker {
|
|||
#ifdef VK_USE_PLATFORM_FUCHSIA
|
||||
bool isSysmemBackedMemory = false;
|
||||
#endif
|
||||
bool isWsiImage = false;
|
||||
#ifdef LINUX_GUEST_BUILD
|
||||
bool isDmaBufImage = false;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct VkBuffer_Info {
|
||||
|
|
|
|||
|
|
@ -20,6 +20,10 @@
|
|||
#include "vk_android_native_buffer_gfxstream.h"
|
||||
#include "vulkan_gfxstream.h"
|
||||
|
||||
#if defined(LINUX_GUEST_BUILD)
|
||||
#include "vulkan/wsi/wsi_common.h"
|
||||
#endif
|
||||
|
||||
// anonymous
|
||||
namespace {
|
||||
|
||||
|
|
@ -125,6 +129,9 @@ REGISTER_VK_STRUCT_ID(VkDeviceCreateInfo, VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO);
|
|||
REGISTER_VK_STRUCT_ID(VkPhysicalDeviceGroupProperties,
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES);
|
||||
REGISTER_VK_STRUCT_ID(VkPhysicalDeviceSwapchainMaintenance1FeaturesEXT, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SWAPCHAIN_MAINTENANCE_1_FEATURES_EXT);
|
||||
#if defined(LINUX_GUEST_BUILD)
|
||||
REGISTER_VK_STRUCT_ID(wsi_image_create_info, VK_STRUCTURE_TYPE_WSI_IMAGE_CREATE_INFO_MESA);
|
||||
#endif
|
||||
|
||||
#undef REGISTER_VK_STRUCT_ID
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue