Add format filtering for virgl gfxstream

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 <dbehr@chromium.org>
Commit-Queue: Jean-François Thibert <jfthibert@google.com>
Reviewed-by: Jason Macnak <natsu@google.com>
Tested-by: Jean-François Thibert <jfthibert@google.com>
This commit is contained in:
Jean-Francois Thibert 2024-07-18 13:25:06 -04:00 committed by Chromeos LUCI
parent 661992dfdf
commit 71ca6afaef
3 changed files with 183 additions and 12 deletions

147
external/virtgpu_gfxstream_protocol.h vendored Normal file
View file

@ -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 <stdint.h>
// 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

View file

@ -26,6 +26,6 @@ enum virtgpu_param_id {
#define VIRTIO_GPU_CAPSET_VIRGL 1 #define VIRTIO_GPU_CAPSET_VIRGL 1
#define VIRTIO_GPU_CAPSET_VIRGL2 2 #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_VENUS 4
#define VIRTIO_GPU_CAPSET_CROSS_DOMAIN 5 #define VIRTIO_GPU_CAPSET_CROSS_DOMAIN 5

View file

@ -21,6 +21,7 @@
#include "external/virgl_hw.h" #include "external/virgl_hw.h"
#include "external/virgl_protocol.h" #include "external/virgl_protocol.h"
#include "external/virtgpu_drm.h" #include "external/virtgpu_drm.h"
#include "external/virtgpu_gfxstream_protocol.h"
#include "util.h" #include "util.h"
#include "virtgpu.h" #include "virtgpu.h"
@ -70,6 +71,8 @@ struct virgl_blob_metadata_cache {
struct virgl_priv { struct virgl_priv {
int caps_is_v2; int caps_is_v2;
union virgl_caps caps; union virgl_caps caps;
int caps_is_gfxstream;
struct vulkanCapset gfxstream_vulkan_caps;
int host_gbm_enabled; int host_gbm_enabled;
atomic_int next_blob_id; 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; 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) if (priv->caps.max_version == 0)
return true; return true;
@ -558,34 +572,42 @@ static uint32_t virgl_3d_get_max_texture_2d_size(struct driver *drv)
return UINT32_MAX; 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; int ret;
struct drm_virtgpu_get_caps cap_args = { 0 }; struct drm_virtgpu_get_caps cap_args = { 0 };
memset(caps, 0, sizeof(union virgl_caps)); memset(&priv->caps, 0, sizeof(union virgl_caps));
*caps_is_v2 = 0; priv->caps_is_v2 = 0;
memset(&priv->gfxstream_vulkan_caps, 0, sizeof(struct vulkanCapset));
if (params[param_supported_capset_ids].value) { if (params[param_supported_capset_ids].value) {
drv_logi("Supported CAPSET IDs: %u.", 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)) { 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 & } else if (params[param_supported_capset_ids].value &
(1 << VIRTIO_GPU_CAPSET_VIRGL)) { (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 { } else {
drv_logi("Unrecognized CAPSET IDs: %u. Assuming all zero caps.", drv_logi("Unrecognized CAPSET IDs: %u. Assuming all zero caps.",
params[param_supported_capset_ids].value); params[param_supported_capset_ids].value);
return 0; return 0;
} }
} else if (params[param_capset_fix].value) { } else if (params[param_capset_fix].value) {
*caps_is_v2 = 1; priv->caps_is_v2 = 1;
} }
cap_args.addr = (unsigned long long)caps; cap_args.addr = (unsigned long long)&priv->caps;
if (*caps_is_v2) { if (priv->caps_is_v2) {
cap_args.cap_set_id = VIRTIO_GPU_CAPSET_VIRGL2; cap_args.cap_set_id = VIRTIO_GPU_CAPSET_VIRGL2;
cap_args.size = sizeof(union virgl_caps); 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 { } else {
cap_args.cap_set_id = VIRTIO_GPU_CAPSET_VIRGL; cap_args.cap_set_id = VIRTIO_GPU_CAPSET_VIRGL;
cap_args.size = sizeof(struct virgl_caps_v1); 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); ret = drmIoctl(drv->fd, DRM_IOCTL_VIRTGPU_GET_CAPS, &cap_args);
if (ret) { if (ret) {
drv_loge("DRM_IOCTL_VIRTGPU_GET_CAPS failed with %s\n", strerror(errno)); 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 // Fallback to v1
cap_args.cap_set_id = VIRTIO_GPU_CAPSET_VIRGL; 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; struct virgl_priv *priv = (struct virgl_priv *)drv->priv;
if (params[param_3d].value) { 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 // We use two criteria to determine whether host minigbm is used on the host for
// swapchain allocations. // swapchain allocations.
@ -655,7 +679,7 @@ static int virgl_init(struct driver *drv)
BO_USE_TEXTURE_MASK); BO_USE_TEXTURE_MASK);
virgl_add_combinations(drv, depth_stencil_formats, virgl_add_combinations(drv, depth_stencil_formats,
ARRAY_SIZE(depth_stencil_formats), &LINEAR_METADATA, 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 /* NV12 with scanout must flow through virgl_add_combination, so that the native
* support is checked and scanout use_flag can be conditionally stripped. */ * support is checked and scanout use_flag can be conditionally stripped. */
virgl_add_combination(drv, DRM_FORMAT_NV12, &LINEAR_METADATA, virgl_add_combination(drv, DRM_FORMAT_NV12, &LINEAR_METADATA,