1 // Copyright (C) 2023 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "ResourceTracker.h"
16 #include "VkEncoder.h"
17 #include "gfxstream_vk_private.h"
18
gfxstream_vk_CreateCommandPool(VkDevice device,const VkCommandPoolCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkCommandPool * pCommandPool)19 VkResult gfxstream_vk_CreateCommandPool(VkDevice device, const VkCommandPoolCreateInfo* pCreateInfo,
20 const VkAllocationCallbacks* pAllocator,
21 VkCommandPool* pCommandPool) {
22 AEMU_SCOPED_TRACE("vkCreateCommandPool");
23 VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
24 VkResult result = (VkResult)0;
25 struct gfxstream_vk_command_pool* gfxstream_pCommandPool =
26 (gfxstream_vk_command_pool*)vk_zalloc2(&gfxstream_device->vk.alloc, pAllocator,
27 sizeof(gfxstream_vk_command_pool), 8,
28 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
29 result = gfxstream_pCommandPool ? VK_SUCCESS : VK_ERROR_OUT_OF_HOST_MEMORY;
30 if (VK_SUCCESS == result) {
31 result = vk_command_pool_init(&gfxstream_device->vk, &gfxstream_pCommandPool->vk,
32 pCreateInfo, pAllocator);
33 }
34 if (VK_SUCCESS == result) {
35 auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
36 result = vkEnc->vkCreateCommandPool(gfxstream_device->internal_object, pCreateInfo,
37 pAllocator, &gfxstream_pCommandPool->internal_object,
38 true /* do lock */);
39 }
40 *pCommandPool = gfxstream_vk_command_pool_to_handle(gfxstream_pCommandPool);
41 return result;
42 }
43
gfxstream_vk_DestroyCommandPool(VkDevice device,VkCommandPool commandPool,const VkAllocationCallbacks * pAllocator)44 void gfxstream_vk_DestroyCommandPool(VkDevice device, VkCommandPool commandPool,
45 const VkAllocationCallbacks* pAllocator) {
46 AEMU_SCOPED_TRACE("vkDestroyCommandPool");
47 if (VK_NULL_HANDLE == commandPool) {
48 return;
49 }
50 VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
51 VK_FROM_HANDLE(gfxstream_vk_command_pool, gfxstream_commandPool, commandPool);
52 {
53 auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
54 vkEnc->vkDestroyCommandPool(gfxstream_device->internal_object,
55 gfxstream_commandPool->internal_object, pAllocator,
56 true /* do lock */);
57 }
58 vk_command_pool_finish(&gfxstream_commandPool->vk);
59 vk_free(&gfxstream_commandPool->vk.alloc, gfxstream_commandPool);
60 }
61
gfxstream_vk_ResetCommandPool(VkDevice device,VkCommandPool commandPool,VkCommandPoolResetFlags flags)62 VkResult gfxstream_vk_ResetCommandPool(VkDevice device, VkCommandPool commandPool,
63 VkCommandPoolResetFlags flags) {
64 AEMU_SCOPED_TRACE("vkResetCommandPool");
65 VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
66 VK_FROM_HANDLE(gfxstream_vk_command_pool, gfxstream_commandPool, commandPool);
67 VkResult vkResetCommandPool_VkResult_return = (VkResult)0;
68 {
69 auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
70 vkResetCommandPool_VkResult_return = vkEnc->vkResetCommandPool(
71 gfxstream_device->internal_object, gfxstream_commandPool->internal_object, flags,
72 true /* do lock */);
73 if (vkResetCommandPool_VkResult_return == VK_SUCCESS) {
74 gfxstream::vk::ResourceTracker::get()->resetCommandPoolStagingInfo(
75 gfxstream_commandPool->internal_object);
76 }
77 }
78 return vkResetCommandPool_VkResult_return;
79 }
80
81 static VkResult vk_command_buffer_createOp(struct vk_command_pool*, struct vk_command_buffer**);
82 static void vk_command_buffer_resetOp(struct vk_command_buffer*, VkCommandBufferResetFlags);
83 static void vk_command_buffer_destroyOp(struct vk_command_buffer*);
84
85 static vk_command_buffer_ops gfxstream_vk_commandBufferOps = {
86 .create = vk_command_buffer_createOp,
87 .reset = vk_command_buffer_resetOp,
88 .destroy = vk_command_buffer_destroyOp};
89
vk_command_buffer_createOp(struct vk_command_pool * commandPool,struct vk_command_buffer ** pCommandBuffer)90 VkResult vk_command_buffer_createOp(struct vk_command_pool* commandPool,
91 struct vk_command_buffer** pCommandBuffer) {
92 VkResult result = VK_SUCCESS;
93 struct gfxstream_vk_command_buffer* gfxstream_commandBuffer =
94 (struct gfxstream_vk_command_buffer*)vk_zalloc(&commandPool->alloc,
95 sizeof(struct gfxstream_vk_command_buffer),
96 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
97 if (gfxstream_commandBuffer) {
98 result =
99 vk_command_buffer_init(commandPool, &gfxstream_commandBuffer->vk,
100 &gfxstream_vk_commandBufferOps, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
101 if (VK_SUCCESS == result) {
102 *pCommandBuffer = &gfxstream_commandBuffer->vk;
103 }
104 } else {
105 result = VK_ERROR_OUT_OF_HOST_MEMORY;
106 }
107 return result;
108 }
109
vk_command_buffer_resetOp(struct vk_command_buffer * commandBuffer,VkCommandBufferResetFlags flags)110 void vk_command_buffer_resetOp(struct vk_command_buffer* commandBuffer,
111 VkCommandBufferResetFlags flags) {
112 (void)flags;
113 vk_command_buffer_reset(commandBuffer);
114 }
115
vk_command_buffer_destroyOp(struct vk_command_buffer * commandBuffer)116 void vk_command_buffer_destroyOp(struct vk_command_buffer* commandBuffer) {
117 vk_command_buffer_finish(commandBuffer);
118 vk_free(&commandBuffer->pool->alloc, commandBuffer);
119 }
120
gfxstream_vk_AllocateCommandBuffers(VkDevice device,const VkCommandBufferAllocateInfo * pAllocateInfo,VkCommandBuffer * pCommandBuffers)121 VkResult gfxstream_vk_AllocateCommandBuffers(VkDevice device,
122 const VkCommandBufferAllocateInfo* pAllocateInfo,
123 VkCommandBuffer* pCommandBuffers) {
124 AEMU_SCOPED_TRACE("vkAllocateCommandBuffers");
125 VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
126 VK_FROM_HANDLE(gfxstream_vk_command_pool, gfxstream_commandPool, pAllocateInfo->commandPool);
127 VkResult result = (VkResult)0;
128 std::vector<gfxstream_vk_command_buffer*> gfxstream_commandBuffers(
129 pAllocateInfo->commandBufferCount);
130 for (uint32_t i = 0; i < pAllocateInfo->commandBufferCount; i++) {
131 result = vk_command_buffer_createOp(&gfxstream_commandPool->vk,
132 (vk_command_buffer**)&gfxstream_commandBuffers[i]);
133 if (VK_SUCCESS == result) {
134 gfxstream_commandBuffers[i]->vk.level = pAllocateInfo->level;
135 } else {
136 break;
137 }
138 }
139 if (VK_SUCCESS == result) {
140 // Create gfxstream-internal commandBuffer array
141 std::vector<VkCommandBuffer> internal_objects(pAllocateInfo->commandBufferCount);
142 auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
143 auto resources = gfxstream::vk::ResourceTracker::get();
144 VkCommandBufferAllocateInfo internal_allocateInfo;
145 internal_allocateInfo = *pAllocateInfo;
146 internal_allocateInfo.commandPool = gfxstream_commandPool->internal_object;
147 result = resources->on_vkAllocateCommandBuffers(
148 vkEnc, VK_SUCCESS, gfxstream_device->internal_object, &internal_allocateInfo,
149 internal_objects.data());
150 if (result == VK_SUCCESS) {
151 gfxstream::vk::ResourceTracker::get()->addToCommandPool(
152 gfxstream_commandPool->internal_object, pAllocateInfo->commandBufferCount,
153 internal_objects.data());
154 for (uint32_t i = 0; i < (uint32_t)internal_objects.size(); i++) {
155 gfxstream_commandBuffers[i]->internal_object = internal_objects[i];
156 // TODO: Also vk_command_buffer_init() on every mesa command buffer?
157 pCommandBuffers[i] =
158 gfxstream_vk_command_buffer_to_handle(gfxstream_commandBuffers[i]);
159 }
160 }
161 }
162 return result;
163 }
164
gfxstream_vk_FreeCommandBuffers(VkDevice device,VkCommandPool commandPool,uint32_t commandBufferCount,const VkCommandBuffer * pCommandBuffers)165 void gfxstream_vk_FreeCommandBuffers(VkDevice device, VkCommandPool commandPool,
166 uint32_t commandBufferCount,
167 const VkCommandBuffer* pCommandBuffers) {
168 AEMU_SCOPED_TRACE("vkFreeCommandBuffers");
169 VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
170 VK_FROM_HANDLE(gfxstream_vk_command_pool, gfxstream_commandPool, commandPool);
171 {
172 // Set up internal commandBuffer array for gfxstream-internal call
173 std::vector<VkCommandBuffer> internal_objects(commandBufferCount);
174 for (uint32_t i = 0; i < commandBufferCount; i++) {
175 VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer,
176 pCommandBuffers[i]);
177 internal_objects[i] = gfxstream_commandBuffer->internal_object;
178 }
179 auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
180 vkEnc->vkFreeCommandBuffers(gfxstream_device->internal_object,
181 gfxstream_commandPool->internal_object, commandBufferCount,
182 internal_objects.data(), true /* do lock */);
183 }
184 for (uint32_t i = 0; i < commandBufferCount; i++) {
185 VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, pCommandBuffers[i]);
186 vk_command_buffer_destroyOp(&gfxstream_commandBuffer->vk);
187 }
188 }
189