gfxstream: host: create blobs backed by ColorBuffers
stream_renderer_resource_create_blob uses less guest memory
than stream_renderer_resource_create_3d.
BUG=349122558
TEST=see dmabufs being exported
Change-Id: Ib2eb4c9292305f1f40164c3753ba01f7c1509906
diff --git a/host/virtgpu_gfxstream_protocol.h b/host/virtgpu_gfxstream_protocol.h
index 823f300..1e77661 100644
--- a/host/virtgpu_gfxstream_protocol.h
+++ b/host/virtgpu_gfxstream_protocol.h
@@ -39,10 +39,11 @@
#define GFXSTREAM_CREATE_EXPORT_SYNC 0x9000
#define GFXSTREAM_CREATE_IMPORT_SYNC 0x9001
-// Vulkan Sync
+// Vulkan related
#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
@@ -89,6 +90,22 @@
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;
diff --git a/host/virtio-gpu-gfxstream-renderer.cpp b/host/virtio-gpu-gfxstream-renderer.cpp
index e572a90..b03e582 100644
--- a/host/virtio-gpu-gfxstream-renderer.cpp
+++ b/host/virtio-gpu-gfxstream-renderer.cpp
@@ -242,6 +242,7 @@
uint32_t addressSpaceHandle;
bool hasAddressSpaceHandle;
std::unordered_map<VirtioGpuResId, uint32_t> addressSpaceHandles;
+ std::unordered_map<uint32_t, struct stream_renderer_resource_create_args> blobMap;
};
enum class ResType {
@@ -252,6 +253,8 @@
BUFFER,
// Used as a GPU texture.
COLOR_BUFFER,
+ // Used as a blob and not known to FrameBuffer.
+ BLOB,
};
struct AlignedMemory {
@@ -782,6 +785,7 @@
return -EINVAL;
}
std::unordered_map<uint32_t, uint32_t> map;
+ std::unordered_map<uint32_t, struct stream_renderer_resource_create_args> blobMap;
PipeCtxEntry res = {
std::move(contextName), // contextName
@@ -792,6 +796,7 @@
0, // AS handle
false, // does not have an AS handle
map, // resourceId --> ASG handle map
+ blobMap, // blobId -> resource create args
};
stream_renderer_debug("initial host pipe for ctxid %u: %p", ctx_id, hostPipe);
@@ -1023,6 +1028,36 @@
[this, taskId] { mVirtioGpuTimelines->notifyTaskCompletion(taskId); });
break;
}
+ case GFXSTREAM_RESOURCE_CREATE_3D: {
+ DECODE(create3d, gfxstream::gfxstreamResourceCreate3d, buffer)
+ struct stream_renderer_resource_create_args rc3d = {0};
+
+ rc3d.target = create3d.target;
+ rc3d.format = create3d.format;
+ rc3d.bind = create3d.bind;
+ rc3d.width = create3d.width;
+ rc3d.height = create3d.height;
+ rc3d.depth = create3d.depth;
+ rc3d.array_size = create3d.arraySize;
+ rc3d.last_level = create3d.lastLevel;
+ rc3d.nr_samples = create3d.nrSamples;
+ rc3d.flags = create3d.flags;
+
+ auto ctxIt = mContexts.find(cmd->ctx_id);
+ if (ctxIt == mContexts.end()) {
+ stream_renderer_error("ctx id %u is not found", cmd->ctx_id);
+ return -EINVAL;
+ }
+
+ auto& ctxEntry = ctxIt->second;
+ if (ctxEntry.blobMap.count(create3d.blobId)) {
+ stream_renderer_error("blob ID already in use");
+ return -EINVAL;
+ }
+
+ ctxEntry.blobMap[create3d.blobId] = rc3d;
+ break;
+ }
case GFXSTREAM_PLACEHOLDER_COMMAND_VK: {
// Do nothing, this is a placeholder command
break;
@@ -1165,6 +1200,8 @@
const auto resType = getResourceType(*args);
switch (resType) {
+ case ResType::BLOB:
+ return -EINVAL;
case ResType::PIPE:
break;
case ResType::BUFFER:
@@ -1207,6 +1244,7 @@
auto& entry = it->second;
switch (entry.type) {
+ case ResType::BLOB:
case ResType::PIPE:
break;
case ResType::BUFFER:
@@ -1434,6 +1472,8 @@
auto& entry = it->second;
switch (entry.type) {
+ case ResType::BLOB:
+ return -EINVAL;
case ResType::PIPE:
ret = handleTransferReadPipe(&entry, offset, box);
break;
@@ -1483,6 +1523,8 @@
}
switch (entry.type) {
+ case ResType::BLOB:
+ return -EINVAL;
case ResType::PIPE:
ret = handleTransferWritePipe(&entry, offset, box);
break;
@@ -1717,9 +1759,48 @@
PipeResEntry e;
struct stream_renderer_resource_create_args args = {0};
+ std::optional<ManagedDescriptorInfo> descriptorInfoOpt = std::nullopt;
e.args = args;
e.hostPipe = 0;
+ auto ctxIt = mContexts.find(ctx_id);
+ if (ctxIt == mContexts.end()) {
+ stream_renderer_error("ctx id %u is not found", ctx_id);
+ return -EINVAL;
+ }
+
+ auto& ctxEntry = ctxIt->second;
+
+ ResType blobType = ResType::BLOB;
+
+ auto blobIt = ctxEntry.blobMap.find(create_blob->blob_id);
+ if (blobIt != ctxEntry.blobMap.end()) {
+ auto& create3d = blobIt->second;
+ create3d.handle = res_handle;
+
+ const auto resType = getResourceType(create3d);
+ switch (resType) {
+ case ResType::BLOB:
+ return -EINVAL;
+ case ResType::PIPE:
+ // Fallthrough for pipe is intended for blob buffers.
+ case ResType::BUFFER:
+ blobType = ResType::BUFFER;
+ handleCreateResourceBuffer(&create3d);
+ descriptorInfoOpt = gfxstream::FrameBuffer::getFB()->exportBuffer(res_handle);
+ break;
+ case ResType::COLOR_BUFFER:
+ blobType = ResType::COLOR_BUFFER;
+ handleCreateResourceColorBuffer(&create3d);
+ descriptorInfoOpt =
+ gfxstream::FrameBuffer::getFB()->exportColorBuffer(res_handle);
+ break;
+ }
+
+ e.args = create3d;
+ ctxEntry.blobMap.erase(create_blob->blob_id);
+ }
+
if (create_blob->blob_id == 0) {
int ret = createRingBlob(e, res_handle, create_blob, handle);
if (ret) {
@@ -1739,8 +1820,11 @@
return -EINVAL;
#endif
} else {
- auto descriptorInfoOpt =
- BlobManager::get()->removeDescriptorInfo(ctx_id, create_blob->blob_id);
+ if (!descriptorInfoOpt) {
+ descriptorInfoOpt =
+ BlobManager::get()->removeDescriptorInfo(ctx_id, create_blob->blob_id);
+ }
+
if (descriptorInfoOpt) {
e.descriptorInfo =
std::make_shared<ManagedDescriptorInfo>(std::move(*descriptorInfoOpt));
@@ -1764,6 +1848,7 @@
e.blobId = create_blob->blob_id;
e.blobMem = create_blob->blob_mem;
e.blobFlags = create_blob->blob_flags;
+ e.type = blobType;
e.iov = nullptr;
e.numIovs = 0;
e.linear = 0;