mesa/src/gfxstream/guest/vulkan/gfxstream_vk_device.cpp
Igor Chernyshev 10ba22db00 Do not copy invalid descriptor set image view handles
Also do the same filtering for descriptor and texel buffers

Spec defines what types must have valid handles,
e.g. VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, etc

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>
2024-09-19 20:05:59 +00:00

966 lines
47 KiB
C++

// Copyright (C) 2023 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.
#include <errno.h>
#include <string.h>
#include "../vulkan_enc/vk_util.h"
#include "HostConnection.h"
#include "ProcessPipe.h"
#include "ResourceTracker.h"
#include "VkEncoder.h"
#include "gfxstream_vk_entrypoints.h"
#include "gfxstream_vk_private.h"
#include "vk_alloc.h"
#include "vk_device.h"
#include "vk_instance.h"
#include "vk_sync_dummy.h"
static HostConnection* getConnection(void) {
auto hostCon = HostConnection::get();
return hostCon;
}
static gfxstream::vk::VkEncoder* getVkEncoder(HostConnection* con) { return con->vkEncoder(); }
gfxstream::vk::ResourceTracker::ThreadingCallbacks threadingCallbacks = {
.hostConnectionGetFunc = getConnection,
.vkEncoderGetFunc = getVkEncoder,
};
VkResult SetupInstance(void) {
uint32_t noRenderControlEnc = 0;
HostConnection* hostCon = HostConnection::getOrCreate(kCapsetGfxStreamVulkan);
if (!hostCon) {
ALOGE("vulkan: Failed to get host connection\n");
return VK_ERROR_DEVICE_LOST;
}
gfxstream::vk::ResourceTracker::get()->setupCaps(noRenderControlEnc);
// Legacy goldfish path: could be deleted once goldfish not used guest-side.
if (!noRenderControlEnc) {
// Implicitly sets up sequence number
ExtendedRCEncoderContext* rcEnc = hostCon->rcEncoder();
if (!rcEnc) {
ALOGE("vulkan: Failed to get renderControl encoder context\n");
return VK_ERROR_DEVICE_LOST;
}
gfxstream::vk::ResourceTracker::get()->setupFeatures(rcEnc->featureInfo_const());
}
gfxstream::vk::ResourceTracker::get()->setThreadingCallbacks(threadingCallbacks);
gfxstream::vk::ResourceTracker::get()->setSeqnoPtr(getSeqnoPtrForProcess());
gfxstream::vk::VkEncoder* vkEnc = hostCon->vkEncoder();
if (!vkEnc) {
ALOGE("vulkan: Failed to get Vulkan encoder\n");
return VK_ERROR_DEVICE_LOST;
}
return VK_SUCCESS;
}
#define VK_HOST_CONNECTION(ret) \
HostConnection* hostCon = HostConnection::getOrCreate(kCapsetGfxStreamVulkan); \
gfxstream::vk::VkEncoder* vkEnc = hostCon->vkEncoder(); \
if (!vkEnc) { \
ALOGE("vulkan: Failed to get Vulkan encoder\n"); \
return ret; \
}
static bool instance_extension_table_initialized = false;
static struct vk_instance_extension_table gfxstream_vk_instance_extensions_supported = {0};
// Provided by Mesa components only; never encoded/decoded through gfxstream
static const char* const kMesaOnlyInstanceExtension[] = {
VK_KHR_SURFACE_EXTENSION_NAME,
#if defined(LINUX_GUEST_BUILD)
VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME,
#endif
VK_EXT_DEBUG_UTILS_EXTENSION_NAME,
};
static const char* const kMesaOnlyDeviceExtensions[] = {
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
};
static bool isMesaOnlyInstanceExtension(const char* name) {
for (auto mesaExt : kMesaOnlyInstanceExtension) {
if (!strncmp(mesaExt, name, VK_MAX_EXTENSION_NAME_SIZE)) return true;
}
return false;
}
static bool isMesaOnlyDeviceExtension(const char* name) {
for (auto mesaExt : kMesaOnlyDeviceExtensions) {
if (!strncmp(mesaExt, name, VK_MAX_EXTENSION_NAME_SIZE)) return true;
}
return false;
}
// Filtered extension names for encoding
static std::vector<const char*> filteredInstanceExtensionNames(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 (!isMesaOnlyInstanceExtension(extName)) {
retList.push_back(extName);
}
}
return retList;
}
static std::vector<const char*> filteredDeviceExtensionNames(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 (!isMesaOnlyDeviceExtension(extName)) {
retList.push_back(extName);
}
}
return retList;
}
static void get_device_extensions(VkPhysicalDevice physDevInternal,
struct vk_device_extension_table* deviceExts) {
VkResult result = (VkResult)0;
auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
auto resources = gfxstream::vk::ResourceTracker::get();
uint32_t numDeviceExts = 0;
result = resources->on_vkEnumerateDeviceExtensionProperties(vkEnc, VK_SUCCESS, physDevInternal,
NULL, &numDeviceExts, NULL);
if (VK_SUCCESS == result) {
std::vector<VkExtensionProperties> extProps(numDeviceExts);
result = resources->on_vkEnumerateDeviceExtensionProperties(
vkEnc, VK_SUCCESS, physDevInternal, NULL, &numDeviceExts, extProps.data());
if (VK_SUCCESS == result) {
// device extensions from gfxstream
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,
vk_device_extensions[j].extensionName,
VK_MAX_EXTENSION_NAME_SIZE)) {
deviceExts->extensions[j] = true;
break;
}
}
}
// device extensions from Mesa
for (uint32_t j = 0; j < VK_DEVICE_EXTENSION_COUNT; j++) {
if (isMesaOnlyDeviceExtension(vk_device_extensions[j].extensionName)) {
deviceExts->extensions[j] = true;
break;
}
}
}
}
}
static VkResult gfxstream_vk_physical_device_init(
struct gfxstream_vk_physical_device* physical_device, struct gfxstream_vk_instance* instance,
VkPhysicalDevice internal_object) {
struct vk_device_extension_table supported_extensions = {0};
get_device_extensions(internal_object, &supported_extensions);
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(
&dispatch_table, &gfxstream_vk_physical_device_entrypoints, false);
vk_physical_device_dispatch_table_from_entrypoints(&dispatch_table,
&wsi_physical_device_entrypoints, false);
// Initialize the mesa object
VkResult result = vk_physical_device_init(&physical_device->vk, &instance->vk,
&supported_extensions, NULL, NULL, &dispatch_table);
if (VK_SUCCESS == result) {
// Set the gfxstream-internal object
physical_device->internal_object = internal_object;
physical_device->instance = instance;
// Note: Must use dummy_sync for correct sync object path in WSI operations
physical_device->sync_types[0] = &vk_sync_dummy_type;
physical_device->sync_types[1] = NULL;
physical_device->vk.supported_sync_types = physical_device->sync_types;
result = gfxstream_vk_wsi_init(physical_device);
}
return result;
}
static void gfxstream_vk_physical_device_finish(
struct gfxstream_vk_physical_device* physical_device) {
gfxstream_vk_wsi_finish(physical_device);
vk_physical_device_finish(&physical_device->vk);
}
static void gfxstream_vk_destroy_physical_device(struct vk_physical_device* physical_device) {
gfxstream_vk_physical_device_finish((struct gfxstream_vk_physical_device*)physical_device);
vk_free(&physical_device->instance->alloc, physical_device);
}
static VkResult gfxstream_vk_enumerate_devices(struct vk_instance* vk_instance) {
VkResult result = VK_SUCCESS;
gfxstream_vk_instance* gfxstream_instance = (gfxstream_vk_instance*)vk_instance;
uint32_t deviceCount = 0;
auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
auto resources = gfxstream::vk::ResourceTracker::get();
result = resources->on_vkEnumeratePhysicalDevices(
vkEnc, VK_SUCCESS, gfxstream_instance->internal_object, &deviceCount, NULL);
if (VK_SUCCESS != result) return result;
std::vector<VkPhysicalDevice> internal_list(deviceCount);
result = resources->on_vkEnumeratePhysicalDevices(
vkEnc, VK_SUCCESS, gfxstream_instance->internal_object, &deviceCount, internal_list.data());
if (VK_SUCCESS == result) {
for (uint32_t i = 0; i < deviceCount; i++) {
struct gfxstream_vk_physical_device* gfxstream_physicalDevice =
(struct gfxstream_vk_physical_device*)vk_zalloc(
&gfxstream_instance->vk.alloc, sizeof(struct gfxstream_vk_physical_device), 8,
VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
if (!gfxstream_physicalDevice) {
result = VK_ERROR_OUT_OF_HOST_MEMORY;
break;
}
result = gfxstream_vk_physical_device_init(gfxstream_physicalDevice, gfxstream_instance,
internal_list[i]);
if (VK_SUCCESS == result) {
list_addtail(&gfxstream_physicalDevice->vk.link,
&gfxstream_instance->vk.physical_devices.list);
} else {
vk_free(&gfxstream_instance->vk.alloc, gfxstream_physicalDevice);
break;
}
}
}
return result;
}
static struct vk_instance_extension_table* get_instance_extensions() {
struct vk_instance_extension_table* const retTablePtr =
&gfxstream_vk_instance_extensions_supported;
if (!instance_extension_table_initialized) {
VkResult result = SetupInstance();
if (VK_SUCCESS == result) {
VK_HOST_CONNECTION(retTablePtr)
auto resources = gfxstream::vk::ResourceTracker::get();
uint32_t numInstanceExts = 0;
result = resources->on_vkEnumerateInstanceExtensionProperties(vkEnc, VK_SUCCESS, NULL,
&numInstanceExts, NULL);
if (VK_SUCCESS == result) {
std::vector<VkExtensionProperties> extProps(numInstanceExts);
result = resources->on_vkEnumerateInstanceExtensionProperties(
vkEnc, VK_SUCCESS, NULL, &numInstanceExts, extProps.data());
if (VK_SUCCESS == result) {
// instance extensions from gfxstream
for (uint32_t i = 0; i < numInstanceExts; i++) {
for (uint32_t j = 0; j < VK_INSTANCE_EXTENSION_COUNT; j++) {
if (0 == strncmp(extProps[i].extensionName,
vk_instance_extensions[j].extensionName,
VK_MAX_EXTENSION_NAME_SIZE)) {
gfxstream_vk_instance_extensions_supported.extensions[j] = true;
break;
}
}
}
// instance extensions from Mesa
for (uint32_t j = 0; j < VK_INSTANCE_EXTENSION_COUNT; j++) {
if (isMesaOnlyInstanceExtension(vk_instance_extensions[j].extensionName)) {
gfxstream_vk_instance_extensions_supported.extensions[j] = true;
}
}
instance_extension_table_initialized = true;
}
}
}
}
return retTablePtr;
}
VkResult gfxstream_vk_CreateInstance(const VkInstanceCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkInstance* pInstance) {
AEMU_SCOPED_TRACE("vkCreateInstance");
struct gfxstream_vk_instance* instance;
pAllocator = pAllocator ?: vk_default_allocator();
instance = (struct gfxstream_vk_instance*)vk_zalloc(pAllocator, sizeof(*instance), 8,
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
if (NULL == instance) {
return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
}
VkResult result = VK_SUCCESS;
/* Encoder call */
{
ALOGE("calling setup instance internally");
result = SetupInstance();
if (VK_SUCCESS != result) {
return vk_error(NULL, result);
}
uint32_t initialEnabledExtensionCount = pCreateInfo->enabledExtensionCount;
const char* const* initialPpEnabledExtensionNames = pCreateInfo->ppEnabledExtensionNames;
std::vector<const char*> filteredExts = filteredInstanceExtensionNames(
pCreateInfo->enabledExtensionCount, pCreateInfo->ppEnabledExtensionNames);
// Temporarily modify createInfo for the encoder call
VkInstanceCreateInfo* mutableCreateInfo = (VkInstanceCreateInfo*)pCreateInfo;
mutableCreateInfo->enabledExtensionCount = static_cast<uint32_t>(filteredExts.size());
mutableCreateInfo->ppEnabledExtensionNames = filteredExts.data();
VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST);
result = vkEnc->vkCreateInstance(pCreateInfo, nullptr, &instance->internal_object,
true /* do lock */);
if (VK_SUCCESS != result) {
return vk_error(NULL, result);
}
// Revert the createInfo the user-set data
mutableCreateInfo->enabledExtensionCount = initialEnabledExtensionCount;
mutableCreateInfo->ppEnabledExtensionNames = initialPpEnabledExtensionNames;
}
struct vk_instance_dispatch_table dispatch_table;
memset(&dispatch_table, 0, sizeof(struct vk_instance_dispatch_table));
vk_instance_dispatch_table_from_entrypoints(&dispatch_table, &gfxstream_vk_instance_entrypoints,
false);
vk_instance_dispatch_table_from_entrypoints(&dispatch_table, &wsi_instance_entrypoints, false);
result = vk_instance_init(&instance->vk, get_instance_extensions(), &dispatch_table,
pCreateInfo, pAllocator);
if (result != VK_SUCCESS) {
vk_free(pAllocator, instance);
return vk_error(NULL, result);
}
instance->vk.physical_devices.enumerate = gfxstream_vk_enumerate_devices;
instance->vk.physical_devices.destroy = gfxstream_vk_destroy_physical_device;
// TODO: instance->vk.physical_devices.try_create_for_drm (?)
*pInstance = gfxstream_vk_instance_to_handle(instance);
return VK_SUCCESS;
}
void gfxstream_vk_DestroyInstance(VkInstance _instance, const VkAllocationCallbacks* pAllocator) {
AEMU_SCOPED_TRACE("vkDestroyInstance");
if (VK_NULL_HANDLE == _instance) return;
VK_FROM_HANDLE(gfxstream_vk_instance, instance, _instance);
VK_HOST_CONNECTION()
vkEnc->vkDestroyInstance(instance->internal_object, pAllocator, true /* do lock */);
vk_instance_finish(&instance->vk);
vk_free(&instance->vk.alloc, instance);
// To make End2EndTests happy, since now the host connection is statically linked to
// libvulkan_ranchu.so [separate HostConnections now].
#if defined(END2END_TESTS)
hostCon->exit();
processPipeRestart();
#endif
}
VkResult gfxstream_vk_EnumerateInstanceExtensionProperties(const char* pLayerName,
uint32_t* pPropertyCount,
VkExtensionProperties* pProperties) {
AEMU_SCOPED_TRACE("vkvkEnumerateInstanceExtensionProperties");
(void)pLayerName;
return vk_enumerate_instance_extension_properties(get_instance_extensions(), pPropertyCount,
pProperties);
}
VkResult gfxstream_vk_EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
const char* pLayerName,
uint32_t* pPropertyCount,
VkExtensionProperties* pProperties) {
AEMU_SCOPED_TRACE("vkEnumerateDeviceExtensionProperties");
(void)pLayerName;
VK_FROM_HANDLE(vk_physical_device, pdevice, physicalDevice);
VK_OUTARRAY_MAKE_TYPED(VkExtensionProperties, out, pProperties, pPropertyCount);
for (int i = 0; i < VK_DEVICE_EXTENSION_COUNT; i++) {
if (!pdevice->supported_extensions.extensions[i]) continue;
vk_outarray_append_typed(VkExtensionProperties, &out, prop) {
*prop = vk_device_extensions[i];
}
}
return vk_outarray_status(&out);
}
VkResult gfxstream_vk_CreateDevice(VkPhysicalDevice physicalDevice,
const VkDeviceCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator, VkDevice* pDevice) {
AEMU_SCOPED_TRACE("vkCreateDevice");
VK_FROM_HANDLE(gfxstream_vk_physical_device, gfxstream_physicalDevice, physicalDevice);
VkResult result = (VkResult)0;
/*
* Android's libvulkan implements VkPhysicalDeviceSwapchainMaintenance1FeaturesEXT, but
* passes it to the underlying driver anyways. See:
*
* https://android-review.googlesource.com/c/platform/hardware/google/gfxstream/+/2839438
*
* and associated bugs. Mesa VK runtime also checks this, so we have to filter out before
* reaches it. vk_find_struct<VkPhysicalDeviceSwapchainMaintenance1FeaturesEXT>(..) doesn't
* work for some reason.
*/
VkBaseInStructure* extensionCreateInfo = (VkBaseInStructure*)(pCreateInfo->pNext);
while (extensionCreateInfo) {
if (extensionCreateInfo->sType ==
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SWAPCHAIN_MAINTENANCE_1_FEATURES_EXT) {
auto swapchainMaintenance1Features =
reinterpret_cast<VkPhysicalDeviceSwapchainMaintenance1FeaturesEXT*>(
extensionCreateInfo);
swapchainMaintenance1Features->swapchainMaintenance1 = VK_FALSE;
}
extensionCreateInfo = (VkBaseInStructure*)(extensionCreateInfo->pNext);
}
const VkAllocationCallbacks* pMesaAllocator =
pAllocator ?: &gfxstream_physicalDevice->instance->vk.alloc;
struct gfxstream_vk_device* gfxstream_device = (struct gfxstream_vk_device*)vk_zalloc(
pMesaAllocator, sizeof(struct gfxstream_vk_device), 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
result = gfxstream_device ? VK_SUCCESS : VK_ERROR_OUT_OF_HOST_MEMORY;
if (VK_SUCCESS == result) {
uint32_t initialEnabledExtensionCount = pCreateInfo->enabledExtensionCount;
const char* const* initialPpEnabledExtensionNames = pCreateInfo->ppEnabledExtensionNames;
std::vector<const char*> filteredExts = filteredDeviceExtensionNames(
pCreateInfo->enabledExtensionCount, pCreateInfo->ppEnabledExtensionNames);
// Temporarily modify createInfo for the encoder call
VkDeviceCreateInfo* mutableCreateInfo = (VkDeviceCreateInfo*)pCreateInfo;
mutableCreateInfo->enabledExtensionCount = static_cast<uint32_t>(filteredExts.size());
mutableCreateInfo->ppEnabledExtensionNames = filteredExts.data();
auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
result = vkEnc->vkCreateDevice(gfxstream_physicalDevice->internal_object, pCreateInfo,
pAllocator, &gfxstream_device->internal_object,
true /* do lock */);
// Revert the createInfo the user-set data
mutableCreateInfo->enabledExtensionCount = initialEnabledExtensionCount;
mutableCreateInfo->ppEnabledExtensionNames = initialPpEnabledExtensionNames;
}
if (VK_SUCCESS == result) {
struct vk_device_dispatch_table dispatch_table;
memset(&dispatch_table, 0, sizeof(struct vk_device_dispatch_table));
vk_device_dispatch_table_from_entrypoints(&dispatch_table, &gfxstream_vk_device_entrypoints,
false);
vk_device_dispatch_table_from_entrypoints(&dispatch_table, &wsi_device_entrypoints, false);
result = vk_device_init(&gfxstream_device->vk, &gfxstream_physicalDevice->vk,
&dispatch_table, pCreateInfo, pMesaAllocator);
}
if (VK_SUCCESS == result) {
gfxstream_device->physical_device = gfxstream_physicalDevice;
// TODO: Initialize cmd_dispatch for emulated secondary command buffer support?
gfxstream_device->vk.command_dispatch_table = &gfxstream_device->cmd_dispatch;
*pDevice = gfxstream_vk_device_to_handle(gfxstream_device);
} else {
vk_free(pMesaAllocator, gfxstream_device);
}
return result;
}
void gfxstream_vk_DestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator) {
AEMU_SCOPED_TRACE("vkDestroyDevice");
VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
if (VK_NULL_HANDLE == device) return;
auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
vkEnc->vkDestroyDevice(gfxstream_device->internal_object, pAllocator, true /* do lock */);
/* Must destroy device queues manually */
vk_foreach_queue_safe(queue, &gfxstream_device->vk) {
vk_queue_finish(queue);
vk_free(&gfxstream_device->vk.alloc, queue);
}
vk_device_finish(&gfxstream_device->vk);
vk_free(&gfxstream_device->vk.alloc, gfxstream_device);
}
void gfxstream_vk_GetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex,
VkQueue* pQueue) {
AEMU_SCOPED_TRACE("vkGetDeviceQueue");
VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
struct gfxstream_vk_queue* gfxstream_queue = (struct gfxstream_vk_queue*)vk_zalloc(
&gfxstream_device->vk.alloc, sizeof(struct gfxstream_vk_queue), 8,
VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
VkResult result = gfxstream_queue ? VK_SUCCESS : VK_ERROR_OUT_OF_HOST_MEMORY;
if (VK_SUCCESS == result) {
VkDeviceQueueCreateInfo createInfo = {
.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
.pNext = NULL,
.flags = 0,
.queueFamilyIndex = queueFamilyIndex,
.queueCount = 1,
.pQueuePriorities = NULL,
};
result =
vk_queue_init(&gfxstream_queue->vk, &gfxstream_device->vk, &createInfo, queueIndex);
}
if (VK_SUCCESS == result) {
auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
vkEnc->vkGetDeviceQueue(gfxstream_device->internal_object, queueFamilyIndex, queueIndex,
&gfxstream_queue->internal_object, true /* do lock */);
gfxstream_queue->device = gfxstream_device;
*pQueue = gfxstream_vk_queue_to_handle(gfxstream_queue);
} else {
*pQueue = VK_NULL_HANDLE;
}
}
void gfxstream_vk_GetDeviceQueue2(VkDevice device, const VkDeviceQueueInfo2* pQueueInfo,
VkQueue* pQueue) {
AEMU_SCOPED_TRACE("vkGetDeviceQueue2");
VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
struct gfxstream_vk_queue* gfxstream_queue = (struct gfxstream_vk_queue*)vk_zalloc(
&gfxstream_device->vk.alloc, sizeof(struct gfxstream_vk_queue), 8,
VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
VkResult result = gfxstream_queue ? VK_SUCCESS : VK_ERROR_OUT_OF_HOST_MEMORY;
if (VK_SUCCESS == result) {
VkDeviceQueueCreateInfo createInfo = {
.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
.pNext = NULL,
.flags = pQueueInfo->flags,
.queueFamilyIndex = pQueueInfo->queueFamilyIndex,
.queueCount = 1,
.pQueuePriorities = NULL,
};
result = vk_queue_init(&gfxstream_queue->vk, &gfxstream_device->vk, &createInfo,
pQueueInfo->queueIndex);
}
if (VK_SUCCESS == result) {
auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
vkEnc->vkGetDeviceQueue2(gfxstream_device->internal_object, pQueueInfo,
&gfxstream_queue->internal_object, true /* do lock */);
gfxstream_queue->device = gfxstream_device;
*pQueue = gfxstream_vk_queue_to_handle(gfxstream_queue);
} else {
*pQueue = VK_NULL_HANDLE;
}
}
/* The loader wants us to expose a second GetInstanceProcAddr function
* to work around certain LD_PRELOAD issues seen in apps.
*/
extern "C" PUBLIC VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
vk_icdGetInstanceProcAddr(VkInstance instance, const char* pName);
extern "C" PUBLIC VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
vk_icdGetInstanceProcAddr(VkInstance instance, const char* pName) {
return gfxstream_vk_GetInstanceProcAddr(instance, pName);
}
/* vk_icd.h does not declare this function, so we declare it here to
* suppress Wmissing-prototypes.
*/
extern "C" PUBLIC VKAPI_ATTR VkResult VKAPI_CALL
vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t* pSupportedVersion);
extern "C" PUBLIC VKAPI_ATTR VkResult VKAPI_CALL
vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t* pSupportedVersion) {
*pSupportedVersion = std::min(*pSupportedVersion, 3u);
return VK_SUCCESS;
}
/* With version 4+ of the loader interface the ICD should expose
* vk_icdGetPhysicalDeviceProcAddr()
*/
extern "C" PUBLIC VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
vk_icdGetPhysicalDeviceProcAddr(VkInstance _instance, const char* pName);
PFN_vkVoidFunction vk_icdGetPhysicalDeviceProcAddr(VkInstance _instance, const char* pName) {
VK_FROM_HANDLE(gfxstream_vk_instance, instance, _instance);
return vk_instance_get_physical_device_proc_addr(&instance->vk, pName);
}
PFN_vkVoidFunction gfxstream_vk_GetInstanceProcAddr(VkInstance _instance, const char* pName) {
VK_FROM_HANDLE(gfxstream_vk_instance, instance, _instance);
return vk_instance_get_proc_addr(&instance->vk, &gfxstream_vk_instance_entrypoints, pName);
}
PFN_vkVoidFunction gfxstream_vk_GetDeviceProcAddr(VkDevice _device, const char* pName) {
AEMU_SCOPED_TRACE("vkGetDeviceProcAddr");
VK_FROM_HANDLE(gfxstream_vk_device, device, _device);
return vk_device_get_proc_addr(&device->vk, pName);
}
VkResult gfxstream_vk_AllocateMemory(VkDevice device, const VkMemoryAllocateInfo* pAllocateInfo,
const VkAllocationCallbacks* pAllocator,
VkDeviceMemory* pMemory) {
AEMU_SCOPED_TRACE("vkAllocateMemory");
VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
VkResult vkAllocateMemory_VkResult_return = (VkResult)0;
struct gfxstream_vk_device_memory* gfxstream_pMemory =
(struct gfxstream_vk_device_memory*)vk_device_memory_create(
(vk_device*)gfxstream_device, pAllocateInfo, pAllocator,
sizeof(struct gfxstream_vk_device_memory));
/* VkMemoryDedicatedAllocateInfo */
VkMemoryDedicatedAllocateInfo* dedicatedAllocInfoPtr =
(VkMemoryDedicatedAllocateInfo*)vk_find_struct<VkMemoryDedicatedAllocateInfo>(
pAllocateInfo);
if (dedicatedAllocInfoPtr) {
if (dedicatedAllocInfoPtr->buffer) {
VK_FROM_HANDLE(gfxstream_vk_buffer, gfxstream_buffer, dedicatedAllocInfoPtr->buffer);
dedicatedAllocInfoPtr->buffer = gfxstream_buffer->internal_object;
}
if (dedicatedAllocInfoPtr->image) {
VK_FROM_HANDLE(gfxstream_vk_image, gfxstream_image, dedicatedAllocInfoPtr->image);
dedicatedAllocInfoPtr->image = gfxstream_image->internal_object;
}
}
vkAllocateMemory_VkResult_return = gfxstream_pMemory ? VK_SUCCESS : VK_ERROR_OUT_OF_HOST_MEMORY;
if (VK_SUCCESS == vkAllocateMemory_VkResult_return) {
auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
auto resources = gfxstream::vk::ResourceTracker::get();
vkAllocateMemory_VkResult_return = resources->on_vkAllocateMemory(
vkEnc, VK_SUCCESS, gfxstream_device->internal_object, pAllocateInfo, pAllocator,
&gfxstream_pMemory->internal_object);
}
*pMemory = gfxstream_vk_device_memory_to_handle(gfxstream_pMemory);
return vkAllocateMemory_VkResult_return;
}
void gfxstream_vk_CmdBeginRenderPass(VkCommandBuffer commandBuffer,
const VkRenderPassBeginInfo* pRenderPassBegin,
VkSubpassContents contents) {
AEMU_SCOPED_TRACE("vkCmdBeginRenderPass");
VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
{
auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
gfxstream_commandBuffer->internal_object);
VkRenderPassBeginInfo internal_pRenderPassBegin = vk_make_orphan_copy(*pRenderPassBegin);
vk_struct_chain_iterator structChainIter =
vk_make_chain_iterator(&internal_pRenderPassBegin);
/* VkRenderPassBeginInfo::renderPass */
VK_FROM_HANDLE(gfxstream_vk_render_pass, gfxstream_renderPass,
internal_pRenderPassBegin.renderPass);
internal_pRenderPassBegin.renderPass = gfxstream_renderPass->internal_object;
/* VkRenderPassBeginInfo::framebuffer */
VK_FROM_HANDLE(gfxstream_vk_framebuffer, gfxstream_framebuffer,
internal_pRenderPassBegin.framebuffer);
internal_pRenderPassBegin.framebuffer = gfxstream_framebuffer->internal_object;
/* pNext = VkRenderPassAttachmentBeginInfo */
std::vector<VkImageView> internal_pAttachments;
VkRenderPassAttachmentBeginInfo internal_renderPassAttachmentBeginInfo;
VkRenderPassAttachmentBeginInfo* pRenderPassAttachmentBeginInfo =
(VkRenderPassAttachmentBeginInfo*)vk_find_struct<VkRenderPassAttachmentBeginInfo>(
pRenderPassBegin);
if (pRenderPassAttachmentBeginInfo) {
internal_renderPassAttachmentBeginInfo = *pRenderPassAttachmentBeginInfo;
/* VkRenderPassAttachmentBeginInfo::pAttachments */
internal_pAttachments.reserve(internal_renderPassAttachmentBeginInfo.attachmentCount);
for (uint32_t i = 0; i < internal_renderPassAttachmentBeginInfo.attachmentCount; i++) {
VK_FROM_HANDLE(gfxstream_vk_image_view, gfxstream_image_view,
internal_renderPassAttachmentBeginInfo.pAttachments[i]);
internal_pAttachments[i] = gfxstream_image_view->internal_object;
}
internal_renderPassAttachmentBeginInfo.pAttachments = internal_pAttachments.data();
vk_append_struct(&structChainIter, &internal_renderPassAttachmentBeginInfo);
}
vkEnc->vkCmdBeginRenderPass(gfxstream_commandBuffer->internal_object,
&internal_pRenderPassBegin, contents, true /* do lock */);
}
}
void gfxstream_vk_CmdBeginRenderPass2KHR(VkCommandBuffer commandBuffer,
const VkRenderPassBeginInfo* pRenderPassBegin,
const VkSubpassBeginInfo* pSubpassBeginInfo) {
AEMU_SCOPED_TRACE("vkCmdBeginRenderPass2KHR");
VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
{
auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
gfxstream_commandBuffer->internal_object);
VkRenderPassBeginInfo internal_pRenderPassBegin = vk_make_orphan_copy(*pRenderPassBegin);
vk_struct_chain_iterator structChainIter =
vk_make_chain_iterator(&internal_pRenderPassBegin);
/* VkRenderPassBeginInfo::renderPass */
VK_FROM_HANDLE(gfxstream_vk_render_pass, gfxstream_renderPass,
internal_pRenderPassBegin.renderPass);
internal_pRenderPassBegin.renderPass = gfxstream_renderPass->internal_object;
/* VkRenderPassBeginInfo::framebuffer */
VK_FROM_HANDLE(gfxstream_vk_framebuffer, gfxstream_framebuffer,
internal_pRenderPassBegin.framebuffer);
internal_pRenderPassBegin.framebuffer = gfxstream_framebuffer->internal_object;
/* pNext = VkRenderPassAttachmentBeginInfo */
std::vector<VkImageView> internal_pAttachments;
VkRenderPassAttachmentBeginInfo internal_renderPassAttachmentBeginInfo;
VkRenderPassAttachmentBeginInfo* pRenderPassAttachmentBeginInfo =
(VkRenderPassAttachmentBeginInfo*)vk_find_struct<VkRenderPassAttachmentBeginInfo>(
pRenderPassBegin);
if (pRenderPassAttachmentBeginInfo) {
internal_renderPassAttachmentBeginInfo = *pRenderPassAttachmentBeginInfo;
/* VkRenderPassAttachmentBeginInfo::pAttachments */
internal_pAttachments.reserve(internal_renderPassAttachmentBeginInfo.attachmentCount);
for (uint32_t i = 0; i < internal_renderPassAttachmentBeginInfo.attachmentCount; i++) {
VK_FROM_HANDLE(gfxstream_vk_image_view, gfxstream_image_view,
internal_renderPassAttachmentBeginInfo.pAttachments[i]);
internal_pAttachments[i] = gfxstream_image_view->internal_object;
}
internal_renderPassAttachmentBeginInfo.pAttachments = internal_pAttachments.data();
vk_append_struct(&structChainIter, &internal_renderPassAttachmentBeginInfo);
}
vkEnc->vkCmdBeginRenderPass2KHR(gfxstream_commandBuffer->internal_object,
&internal_pRenderPassBegin, pSubpassBeginInfo,
true /* do lock */);
}
}
VkResult gfxstream_vk_GetMemoryFdKHR(VkDevice device, const VkMemoryGetFdInfoKHR* pGetFdInfo,
int* pFd) {
AEMU_SCOPED_TRACE("vkGetMemoryFdKHR");
VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
VkResult vkGetMemoryFdKHR_VkResult_return = (VkResult)0;
{
auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
std::vector<VkMemoryGetFdInfoKHR> internal_pGetFdInfo(1);
for (uint32_t i = 0; i < 1; ++i) {
internal_pGetFdInfo[i] = pGetFdInfo[i];
/* VkMemoryGetFdInfoKHR::memory */
VK_FROM_HANDLE(gfxstream_vk_device_memory, gfxstream_memory,
internal_pGetFdInfo[i].memory);
internal_pGetFdInfo[i].memory = gfxstream_memory->internal_object;
}
auto resources = gfxstream::vk::ResourceTracker::get();
vkGetMemoryFdKHR_VkResult_return = resources->on_vkGetMemoryFdKHR(
vkEnc, VK_SUCCESS, gfxstream_device->internal_object, internal_pGetFdInfo.data(), pFd);
}
return vkGetMemoryFdKHR_VkResult_return;
}
VkResult gfxstream_vk_EnumerateInstanceLayerProperties(uint32_t* pPropertyCount,
VkLayerProperties* pProperties) {
AEMU_SCOPED_TRACE("vkEnumerateInstanceLayerProperties");
auto result = SetupInstance();
if (VK_SUCCESS != result) {
return vk_error(NULL, result);
}
VkResult vkEnumerateInstanceLayerProperties_VkResult_return = (VkResult)0;
{
auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
vkEnumerateInstanceLayerProperties_VkResult_return =
vkEnc->vkEnumerateInstanceLayerProperties(pPropertyCount, pProperties,
true /* do lock */);
}
return vkEnumerateInstanceLayerProperties_VkResult_return;
}
VkResult gfxstream_vk_EnumerateInstanceVersion(uint32_t* pApiVersion) {
AEMU_SCOPED_TRACE("vkEnumerateInstanceVersion");
auto result = SetupInstance();
if (VK_SUCCESS != result) {
return vk_error(NULL, result);
}
VkResult vkEnumerateInstanceVersion_VkResult_return = (VkResult)0;
{
auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
vkEnumerateInstanceVersion_VkResult_return =
vkEnc->vkEnumerateInstanceVersion(pApiVersion, true /* do lock */);
}
return vkEnumerateInstanceVersion_VkResult_return;
}
VkResult gfxstream_vk_CreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache,
uint32_t createInfoCount,
const VkComputePipelineCreateInfo* pCreateInfos,
const VkAllocationCallbacks* pAllocator,
VkPipeline* pPipelines) {
AEMU_SCOPED_TRACE("vkCreateComputePipelines");
VkResult vkCreateComputePipelines_VkResult_return = (VkResult)0;
VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
VK_FROM_HANDLE(gfxstream_vk_pipeline_cache, gfxstream_pipelineCache, pipelineCache);
struct gfxstream_vk_pipeline* gfxstream_pPipelines = (gfxstream_vk_pipeline*)vk_object_zalloc(
&gfxstream_device->vk, pAllocator, sizeof(gfxstream_vk_pipeline), VK_OBJECT_TYPE_PIPELINE);
vkCreateComputePipelines_VkResult_return =
gfxstream_pPipelines ? VK_SUCCESS : VK_ERROR_OUT_OF_HOST_MEMORY;
if (VK_SUCCESS == vkCreateComputePipelines_VkResult_return) {
auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
std::vector<VkComputePipelineCreateInfo> internal_pCreateInfos(createInfoCount);
std::vector<VkPipelineShaderStageCreateInfo> internal_VkComputePipelineCreateInfo_stage(createInfoCount);
for (uint32_t i = 0; i < createInfoCount; ++i) {
internal_pCreateInfos[i] = pCreateInfos[i];
/* VkComputePipelineCreateInfo::stage */
{
internal_VkComputePipelineCreateInfo_stage[i] = internal_pCreateInfos[i].stage;
/* VkPipelineShaderStageCreateInfo::module */
if (internal_VkComputePipelineCreateInfo_stage[i].module) {
VK_FROM_HANDLE(gfxstream_vk_shader_module, gfxstream_module,
internal_VkComputePipelineCreateInfo_stage[i].module);
internal_VkComputePipelineCreateInfo_stage[i].module =
gfxstream_module->internal_object;
}
internal_pCreateInfos[i].stage = internal_VkComputePipelineCreateInfo_stage[i];
}
/* VkComputePipelineCreateInfo::layout */
VK_FROM_HANDLE(gfxstream_vk_pipeline_layout, gfxstream_layout,
internal_pCreateInfos[i].layout);
internal_pCreateInfos[i].layout = gfxstream_layout->internal_object;
/* VkComputePipelineCreateInfo::basePipelineHandle */
if (internal_pCreateInfos[i].basePipelineHandle) {
VK_FROM_HANDLE(gfxstream_vk_pipeline, gfxstream_basePipelineHandle,
internal_pCreateInfos[i].basePipelineHandle);
internal_pCreateInfos[i].basePipelineHandle =
gfxstream_basePipelineHandle->internal_object;
}
}
vkCreateComputePipelines_VkResult_return = vkEnc->vkCreateComputePipelines(
gfxstream_device->internal_object,
gfxstream_pipelineCache ? gfxstream_pipelineCache->internal_object : VK_NULL_HANDLE,
createInfoCount, internal_pCreateInfos.data(), pAllocator,
&gfxstream_pPipelines->internal_object, true /* do lock */);
}
*pPipelines = gfxstream_vk_pipeline_to_handle(gfxstream_pPipelines);
return vkCreateComputePipelines_VkResult_return;
}
struct DescriptorSetTransformStorage {
std::vector<std::vector<VkDescriptorImageInfo>> imageInfos;
std::vector<std::vector<VkDescriptorBufferInfo>> bufferInfos;
std::vector<std::vector<VkBufferView>> texelBuffers;
};
static std::vector<VkWriteDescriptorSet> transformDescriptorSetList(
const VkWriteDescriptorSet* pDescriptorSets,
uint32_t descriptorSetCount,
DescriptorSetTransformStorage& storage) {
std::vector<VkWriteDescriptorSet> outDescriptorSets(descriptorSetCount);
for (uint32_t i = 0; i < descriptorSetCount; ++i) {
const auto& srcDescriptorSet = pDescriptorSets[i];
const uint32_t descriptorCount = srcDescriptorSet.descriptorCount;
VkWriteDescriptorSet& outDescriptorSet = outDescriptorSets[i];
outDescriptorSet = srcDescriptorSet;
storage.imageInfos.push_back(std::vector<VkDescriptorImageInfo>());
storage.imageInfos[i].reserve(descriptorCount);
memset(&storage.imageInfos[i][0], 0, sizeof(VkDescriptorImageInfo) * descriptorCount);
for (uint32_t j = 0; j < descriptorCount; ++j) {
const auto* srcImageInfo = srcDescriptorSet.pImageInfo;
if (srcImageInfo) {
storage.imageInfos[i][j] = srcImageInfo[j];
storage.imageInfos[i][j].imageView = VK_NULL_HANDLE;
if (vk_descriptor_type_has_image_view(srcDescriptorSet.descriptorType) &&
srcImageInfo[j].imageView) {
VK_FROM_HANDLE(gfxstream_vk_image_view, gfxstreamImageView,
srcImageInfo[j].imageView);
storage.imageInfos[i][j].imageView = gfxstreamImageView->internal_object;
}
}
}
outDescriptorSet.pImageInfo = storage.imageInfos[i].data();
storage.bufferInfos.push_back(std::vector<VkDescriptorBufferInfo>());
storage.bufferInfos[i].reserve(descriptorCount);
memset(&storage.bufferInfos[i][0], 0, sizeof(VkDescriptorBufferInfo) * descriptorCount);
for (uint32_t j = 0; j < descriptorCount; ++j) {
const auto* srcBufferInfo = srcDescriptorSet.pBufferInfo;
if (srcBufferInfo) {
storage.bufferInfos[i][j] = srcBufferInfo[j];
storage.bufferInfos[i][j].buffer = VK_NULL_HANDLE;
if (vk_descriptor_type_has_descriptor_buffer(srcDescriptorSet.descriptorType) &&
srcBufferInfo[j].buffer) {
VK_FROM_HANDLE(gfxstream_vk_buffer, gfxstreamBuffer, srcBufferInfo[j].buffer);
storage.bufferInfos[i][j].buffer = gfxstreamBuffer->internal_object;
}
}
}
outDescriptorSet.pBufferInfo = storage.bufferInfos[i].data();
storage.texelBuffers.push_back(std::vector<VkBufferView>());
storage.texelBuffers[i].reserve(descriptorCount);
memset(&storage.texelBuffers[i][0], 0, sizeof(VkBufferView) * descriptorCount);
for (uint32_t j = 0; j < descriptorCount; ++j) {
const auto* srcBufferView = srcDescriptorSet.pTexelBufferView;
if (vk_descriptor_type_has_texel_buffer(srcDescriptorSet.descriptorType) &&
srcBufferView) {
VK_FROM_HANDLE(gfxstream_vk_buffer_view, gfxstreamBufferView, srcBufferView[j]);
storage.texelBuffers[i][j] =
gfxstreamBufferView->internal_object;
}
}
outDescriptorSet.pTexelBufferView = storage.texelBuffers[i].data();
}
return outDescriptorSets;
}
void gfxstream_vk_UpdateDescriptorSets(VkDevice device, uint32_t descriptorWriteCount,
const VkWriteDescriptorSet* pDescriptorWrites,
uint32_t descriptorCopyCount,
const VkCopyDescriptorSet* pDescriptorCopies) {
AEMU_SCOPED_TRACE("vkUpdateDescriptorSets");
VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
{
auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
DescriptorSetTransformStorage descriptorSetTransformStorage;
std::vector<VkWriteDescriptorSet> internal_pDescriptorWrites =
transformDescriptorSetList(pDescriptorWrites, descriptorWriteCount,
descriptorSetTransformStorage);
auto resources = gfxstream::vk::ResourceTracker::get();
resources->on_vkUpdateDescriptorSets(
vkEnc, gfxstream_device->internal_object, descriptorWriteCount,
internal_pDescriptorWrites.data(), descriptorCopyCount, pDescriptorCopies);
}
}
void gfxstream_vk_QueueCommitDescriptorSetUpdatesGOOGLE(
VkQueue queue, uint32_t descriptorPoolCount, const VkDescriptorPool* pDescriptorPools,
uint32_t descriptorSetCount, const VkDescriptorSetLayout* pSetLayouts,
const uint64_t* pDescriptorSetPoolIds, const uint32_t* pDescriptorSetWhichPool,
const uint32_t* pDescriptorSetPendingAllocation,
const uint32_t* pDescriptorWriteStartingIndices, uint32_t pendingDescriptorWriteCount,
const VkWriteDescriptorSet* pPendingDescriptorWrites) {
AEMU_SCOPED_TRACE("vkQueueCommitDescriptorSetUpdatesGOOGLE");
VK_FROM_HANDLE(gfxstream_vk_queue, gfxstream_queue, queue);
{
auto vkEnc =
gfxstream::vk::ResourceTracker::getQueueEncoder(gfxstream_queue->internal_object);
std::vector<VkDescriptorPool> internal_pDescriptorPools(descriptorPoolCount);
for (uint32_t i = 0; i < descriptorPoolCount; ++i) {
VK_FROM_HANDLE(gfxstream_vk_descriptor_pool, gfxstream_pDescriptorPools,
pDescriptorPools[i]);
internal_pDescriptorPools[i] = gfxstream_pDescriptorPools->internal_object;
}
std::vector<VkDescriptorSetLayout> internal_pSetLayouts(descriptorSetCount);
for (uint32_t i = 0; i < descriptorSetCount; ++i) {
VK_FROM_HANDLE(gfxstream_vk_descriptor_set_layout, gfxstream_pSetLayouts,
pSetLayouts[i]);
internal_pSetLayouts[i] = gfxstream_pSetLayouts->internal_object;
}
DescriptorSetTransformStorage descriptorSetTransformStorage;
std::vector<VkWriteDescriptorSet> internal_pPendingDescriptorWrites =
transformDescriptorSetList(pPendingDescriptorWrites, pendingDescriptorWriteCount,
descriptorSetTransformStorage);
vkEnc->vkQueueCommitDescriptorSetUpdatesGOOGLE(
gfxstream_queue->internal_object, descriptorPoolCount, internal_pDescriptorPools.data(),
descriptorSetCount, internal_pSetLayouts.data(), pDescriptorSetPoolIds,
pDescriptorSetWhichPool, pDescriptorSetPendingAllocation,
pDescriptorWriteStartingIndices, pendingDescriptorWriteCount,
internal_pPendingDescriptorWrites.data(), true /* do lock */);
}
}