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