From 71ca6afaefdd5f2e38e235a75cef1e86295ca0da Mon Sep 17 00:00:00 2001 From: Jean-Francois Thibert Date: Thu, 18 Jul 2024 13:25:06 -0400 Subject: [PATCH] Add format filtering for virgl gfxstream MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug=b:352091996 Test=Ran CTS deqp test cases with cuttlefish Change-Id: Ie6af00d39abfd19b8070b8df9349d05c80b324c2 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/minigbm/+/5722608 Reviewed-by: Dominik Behr Commit-Queue: Jean-François Thibert Reviewed-by: Jason Macnak Tested-by: Jean-François Thibert --- external/virtgpu_gfxstream_protocol.h | 147 ++++++++++++++++++++++++++ virtgpu.h | 2 +- virtgpu_virgl.c | 46 ++++++-- 3 files changed, 183 insertions(+), 12 deletions(-) create mode 100644 external/virtgpu_gfxstream_protocol.h diff --git a/external/virtgpu_gfxstream_protocol.h b/external/virtgpu_gfxstream_protocol.h new file mode 100644 index 0000000..8253e64 --- /dev/null +++ b/external/virtgpu_gfxstream_protocol.h @@ -0,0 +1,147 @@ +// Copyright 2022 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef VIRTGPU_GFXSTREAM_PROTOCOL_H +#define VIRTGPU_GFXSTREAM_PROTOCOL_H + +#include + +// See definitions in rutabaga_gfx_ffi.h +#define VIRTGPU_CAPSET_VIRGL 1 +#define VIRTGPU_CAPSET_VIRGL2 2 +#define VIRTGPU_CAPSET_GFXSTREAM_VULKAN 3 +#define VIRTGPU_CAPSET_VENUS 4 +#define VIRTGPU_CAPSET_CROSS_DOMAIN 5 +#define VIRTGPU_CAPSET_DRM 6 +#define VIRTGPU_CAPSET_GFXSTREAM_MAGMA 7 +#define VIRTGPU_CAPSET_GFXSTREAM_GLES 8 +#define VIRTGPU_CAPSET_GFXSTREAM_COMPOSER 9 + +// Address Space Graphics contexts +#define GFXSTREAM_CONTEXT_CREATE 0x1001 +#define GFXSTREAM_CONTEXT_PING 0x1002 +#define GFXSTREAM_CONTEXT_PING_WITH_RESPONSE 0x1003 + +// Native Sync FD +#define GFXSTREAM_CREATE_EXPORT_SYNC 0x9000 +#define GFXSTREAM_CREATE_IMPORT_SYNC 0x9001 + +// Vulkan Sync +#define GFXSTREAM_CREATE_EXPORT_SYNC_VK 0xa000 +#define GFXSTREAM_CREATE_IMPORT_SYNC_VK 0xa001 +#define GFXSTREAM_CREATE_QSRI_EXPORT_VK 0xa002 +#define GFXSTREAM_RESOURCE_CREATE_3D 0xa003 + +// clang-format off +// A placeholder command to ensure virtio-gpu completes +#define GFXSTREAM_PLACEHOLDER_COMMAND_VK 0xf002 +// clang-format on + +struct gfxstreamHeader { + uint32_t opCode; +}; + +struct gfxstreamContextCreate { + struct gfxstreamHeader hdr; + uint32_t resourceId; +}; + +struct gfxstreamContextPing { + struct gfxstreamHeader hdr; + uint32_t resourceId; +}; + +struct gfxstreamCreateExportSync { + struct gfxstreamHeader hdr; + uint32_t syncHandleLo; + uint32_t syncHandleHi; +}; + +struct gfxstreamCreateExportSyncVK { + struct gfxstreamHeader hdr; + uint32_t deviceHandleLo; + uint32_t deviceHandleHi; + uint32_t fenceHandleLo; + uint32_t fenceHandleHi; +}; + +struct gfxstreamCreateQSRIExportVK { + struct gfxstreamHeader hdr; + uint32_t imageHandleLo; + uint32_t imageHandleHi; +}; + +struct gfxstreamPlaceholderCommandVk { + struct gfxstreamHeader hdr; + uint32_t pad; + uint32_t padding; +}; + +struct gfxstreamResourceCreate3d { + struct gfxstreamHeader hdr; + uint32_t target; + uint32_t format; + uint32_t bind; + uint32_t width; + uint32_t height; + uint32_t depth; + uint32_t arraySize; + uint32_t lastLevel; + uint32_t nrSamples; + uint32_t flags; + uint32_t pad; + uint64_t blobId; +}; + +struct vulkanCapset { + uint32_t protocolVersion; + + // ASG Ring Parameters + uint32_t ringSize; + uint32_t bufferSize; + + uint32_t colorBufferMemoryIndex; + uint32_t deferredMapping; + uint32_t blobAlignment; + uint32_t noRenderControlEnc; + uint32_t alwaysBlob; + uint32_t externalSync; + uint32_t virglSupportedFormats[16]; +}; + +struct magmaCapset { + uint32_t protocolVersion; + // ASG Ring Parameters + uint32_t ringSize; + uint32_t bufferSize; + uint32_t blobAlignment; +}; + +struct glesCapset { + uint32_t protocolVersion; + // ASG Ring Parameters + uint32_t ringSize; + uint32_t bufferSize; + uint32_t blobAlignment; +}; + +struct composerCapset { + uint32_t protocolVersion; + // ASG Ring Parameters + uint32_t ringSize; + uint32_t bufferSize; + uint32_t blobAlignment; +}; + +#endif diff --git a/virtgpu.h b/virtgpu.h index b2f82ba..e74afd2 100644 --- a/virtgpu.h +++ b/virtgpu.h @@ -26,6 +26,6 @@ enum virtgpu_param_id { #define VIRTIO_GPU_CAPSET_VIRGL 1 #define VIRTIO_GPU_CAPSET_VIRGL2 2 -#define VIRTIO_GPU_CAPSET_GFXSTREAM 3 +#define VIRTIO_GPU_CAPSET_GFXSTREAM_VULKAN 3 #define VIRTIO_GPU_CAPSET_VENUS 4 #define VIRTIO_GPU_CAPSET_CROSS_DOMAIN 5 diff --git a/virtgpu_virgl.c b/virtgpu_virgl.c index 4850971..04fa1d2 100644 --- a/virtgpu_virgl.c +++ b/virtgpu_virgl.c @@ -21,6 +21,7 @@ #include "external/virgl_hw.h" #include "external/virgl_protocol.h" #include "external/virtgpu_drm.h" +#include "external/virtgpu_gfxstream_protocol.h" #include "util.h" #include "virtgpu.h" @@ -70,6 +71,8 @@ struct virgl_blob_metadata_cache { struct virgl_priv { int caps_is_v2; union virgl_caps caps; + int caps_is_gfxstream; + struct vulkanCapset gfxstream_vulkan_caps; int host_gbm_enabled; atomic_int next_blob_id; @@ -329,6 +332,17 @@ static bool virgl_supports_combination_natively(struct driver *drv, uint32_t drm { struct virgl_priv *priv = (struct virgl_priv *)drv->priv; + if (priv->caps_is_gfxstream) { + // If the data is invalid or an older version just accept all formats as previously + if (priv->gfxstream_vulkan_caps.protocolVersion == 0 || + priv->gfxstream_vulkan_caps.virglSupportedFormats[0] == 0) + return true; + bool supported_format = virgl_bitmask_supports_format( + (struct virgl_supported_format_mask *)&priv->gfxstream_vulkan_caps + .virglSupportedFormats[0], + drm_format); + return supported_format; + } if (priv->caps.max_version == 0) return true; @@ -558,34 +572,42 @@ static uint32_t virgl_3d_get_max_texture_2d_size(struct driver *drv) return UINT32_MAX; } -static int virgl_get_caps(struct driver *drv, union virgl_caps *caps, int *caps_is_v2) +static int virgl_get_caps(struct driver *drv, struct virgl_priv *priv) { int ret; struct drm_virtgpu_get_caps cap_args = { 0 }; - memset(caps, 0, sizeof(union virgl_caps)); - *caps_is_v2 = 0; + memset(&priv->caps, 0, sizeof(union virgl_caps)); + priv->caps_is_v2 = 0; + memset(&priv->gfxstream_vulkan_caps, 0, sizeof(struct vulkanCapset)); if (params[param_supported_capset_ids].value) { drv_logi("Supported CAPSET IDs: %u.", params[param_supported_capset_ids].value); if (params[param_supported_capset_ids].value & (1 << VIRTIO_GPU_CAPSET_VIRGL2)) { - *caps_is_v2 = 1; + priv->caps_is_v2 = 1; } else if (params[param_supported_capset_ids].value & (1 << VIRTIO_GPU_CAPSET_VIRGL)) { - *caps_is_v2 = 0; + priv->caps_is_v2 = 0; + } else if (params[param_supported_capset_ids].value & + (1 << VIRTIO_GPU_CAPSET_GFXSTREAM_VULKAN)) { + priv->caps_is_gfxstream = 1; } else { drv_logi("Unrecognized CAPSET IDs: %u. Assuming all zero caps.", params[param_supported_capset_ids].value); return 0; } } else if (params[param_capset_fix].value) { - *caps_is_v2 = 1; + priv->caps_is_v2 = 1; } - cap_args.addr = (unsigned long long)caps; - if (*caps_is_v2) { + cap_args.addr = (unsigned long long)&priv->caps; + if (priv->caps_is_v2) { cap_args.cap_set_id = VIRTIO_GPU_CAPSET_VIRGL2; cap_args.size = sizeof(union virgl_caps); + } else if (priv->caps_is_gfxstream) { + cap_args.addr = (unsigned long long)&priv->gfxstream_vulkan_caps; + cap_args.cap_set_id = VIRTIO_GPU_CAPSET_GFXSTREAM_VULKAN; + cap_args.size = sizeof(struct vulkanCapset); } else { cap_args.cap_set_id = VIRTIO_GPU_CAPSET_VIRGL; cap_args.size = sizeof(struct virgl_caps_v1); @@ -594,7 +616,9 @@ static int virgl_get_caps(struct driver *drv, union virgl_caps *caps, int *caps_ ret = drmIoctl(drv->fd, DRM_IOCTL_VIRTGPU_GET_CAPS, &cap_args); if (ret) { drv_loge("DRM_IOCTL_VIRTGPU_GET_CAPS failed with %s\n", strerror(errno)); - *caps_is_v2 = 0; + priv->caps_is_v2 = 0; + priv->caps_is_gfxstream = 0; + cap_args.addr = (unsigned long long)&priv->caps; // Fallback to v1 cap_args.cap_set_id = VIRTIO_GPU_CAPSET_VIRGL; @@ -612,7 +636,7 @@ static void virgl_init_params_and_caps(struct driver *drv) { struct virgl_priv *priv = (struct virgl_priv *)drv->priv; if (params[param_3d].value) { - virgl_get_caps(drv, &priv->caps, &priv->caps_is_v2); + virgl_get_caps(drv, priv); // We use two criteria to determine whether host minigbm is used on the host for // swapchain allocations. @@ -655,7 +679,7 @@ static int virgl_init(struct driver *drv) BO_USE_TEXTURE_MASK); virgl_add_combinations(drv, depth_stencil_formats, ARRAY_SIZE(depth_stencil_formats), &LINEAR_METADATA, - BO_USE_RENDER_MASK | BO_USE_TEXTURE_MASK); + BO_USE_GPU_HW); /* NV12 with scanout must flow through virgl_add_combination, so that the native * support is checked and scanout use_flag can be conditionally stripped. */ virgl_add_combination(drv, DRM_FORMAT_NV12, &LINEAR_METADATA,