xref: /aosp_15_r20/external/mesa3d/src/gfxstream/guest/vulkan/gfxstream_vk_cmd.cpp (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright 2023 Google LLC
3  * SPDX-License-Identifier: MIT
4  */
5 
6 #include "ResourceTracker.h"
7 #include "VkEncoder.h"
8 #include "gfxstream_vk_private.h"
9 #include "util/perf/cpu_trace.h"
10 
gfxstream_vk_CreateCommandPool(VkDevice device,const VkCommandPoolCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkCommandPool * pCommandPool)11 VkResult gfxstream_vk_CreateCommandPool(VkDevice device, const VkCommandPoolCreateInfo* pCreateInfo,
12                                         const VkAllocationCallbacks* pAllocator,
13                                         VkCommandPool* pCommandPool) {
14     MESA_TRACE_SCOPE("vkCreateCommandPool");
15     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
16     VkResult result = (VkResult)0;
17     struct gfxstream_vk_command_pool* gfxstream_pCommandPool =
18         (gfxstream_vk_command_pool*)vk_zalloc2(&gfxstream_device->vk.alloc, pAllocator,
19                                                sizeof(gfxstream_vk_command_pool), 8,
20                                                VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
21     result = gfxstream_pCommandPool ? VK_SUCCESS : VK_ERROR_OUT_OF_HOST_MEMORY;
22     if (VK_SUCCESS == result) {
23         result = vk_command_pool_init(&gfxstream_device->vk, &gfxstream_pCommandPool->vk,
24                                       pCreateInfo, pAllocator);
25     }
26     if (VK_SUCCESS == result) {
27         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
28         result = vkEnc->vkCreateCommandPool(gfxstream_device->internal_object, pCreateInfo,
29                                             pAllocator, &gfxstream_pCommandPool->internal_object,
30                                             true /* do lock */);
31     }
32     *pCommandPool = gfxstream_vk_command_pool_to_handle(gfxstream_pCommandPool);
33     return result;
34 }
35 
gfxstream_vk_DestroyCommandPool(VkDevice device,VkCommandPool commandPool,const VkAllocationCallbacks * pAllocator)36 void gfxstream_vk_DestroyCommandPool(VkDevice device, VkCommandPool commandPool,
37                                      const VkAllocationCallbacks* pAllocator) {
38     MESA_TRACE_SCOPE("vkDestroyCommandPool");
39     if (VK_NULL_HANDLE == commandPool) {
40         return;
41     }
42     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
43     VK_FROM_HANDLE(gfxstream_vk_command_pool, gfxstream_commandPool, commandPool);
44     {
45         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
46         vkEnc->vkDestroyCommandPool(gfxstream_device->internal_object,
47                                     gfxstream_commandPool->internal_object, pAllocator,
48                                     true /* do lock */);
49     }
50     vk_command_pool_finish(&gfxstream_commandPool->vk);
51     vk_free(&gfxstream_commandPool->vk.alloc, gfxstream_commandPool);
52 }
53 
gfxstream_vk_ResetCommandPool(VkDevice device,VkCommandPool commandPool,VkCommandPoolResetFlags flags)54 VkResult gfxstream_vk_ResetCommandPool(VkDevice device, VkCommandPool commandPool,
55                                        VkCommandPoolResetFlags flags) {
56     MESA_TRACE_SCOPE("vkResetCommandPool");
57     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
58     VK_FROM_HANDLE(gfxstream_vk_command_pool, gfxstream_commandPool, commandPool);
59     VkResult vkResetCommandPool_VkResult_return = (VkResult)0;
60     {
61         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
62         vkResetCommandPool_VkResult_return = vkEnc->vkResetCommandPool(
63             gfxstream_device->internal_object, gfxstream_commandPool->internal_object, flags,
64             true /* do lock */);
65         if (vkResetCommandPool_VkResult_return == VK_SUCCESS) {
66             gfxstream::vk::ResourceTracker::get()->resetCommandPoolStagingInfo(
67                 gfxstream_commandPool->internal_object);
68         }
69     }
70     return vkResetCommandPool_VkResult_return;
71 }
72 
73 static VkResult vk_command_buffer_createOp(struct vk_command_pool*, VkCommandBufferLevel,
74                                            struct vk_command_buffer**);
75 static void vk_command_buffer_resetOp(struct vk_command_buffer*, VkCommandBufferResetFlags);
76 static void vk_command_buffer_destroyOp(struct vk_command_buffer*);
77 
78 static vk_command_buffer_ops gfxstream_vk_commandBufferOps = {
79     .create = vk_command_buffer_createOp,
80     .reset = vk_command_buffer_resetOp,
81     .destroy = vk_command_buffer_destroyOp};
82 
vk_command_buffer_createOp(struct vk_command_pool * commandPool,VkCommandBufferLevel level,struct vk_command_buffer ** pCommandBuffer)83 VkResult vk_command_buffer_createOp(struct vk_command_pool* commandPool, VkCommandBufferLevel level,
84                                     struct vk_command_buffer** pCommandBuffer) {
85     VkResult result = VK_SUCCESS;
86     struct gfxstream_vk_command_buffer* gfxstream_commandBuffer =
87         (struct gfxstream_vk_command_buffer*)vk_zalloc(&commandPool->alloc,
88                                                        sizeof(struct gfxstream_vk_command_buffer),
89                                                        8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
90     if (gfxstream_commandBuffer) {
91         result =
92             vk_command_buffer_init(commandPool, &gfxstream_commandBuffer->vk,
93                                    &gfxstream_vk_commandBufferOps, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
94         if (VK_SUCCESS == result) {
95             *pCommandBuffer = &gfxstream_commandBuffer->vk;
96         }
97     } else {
98         result = VK_ERROR_OUT_OF_HOST_MEMORY;
99     }
100     return result;
101 }
102 
vk_command_buffer_resetOp(struct vk_command_buffer * commandBuffer,VkCommandBufferResetFlags flags)103 void vk_command_buffer_resetOp(struct vk_command_buffer* commandBuffer,
104                                VkCommandBufferResetFlags flags) {
105     (void)flags;
106     vk_command_buffer_reset(commandBuffer);
107 }
108 
vk_command_buffer_destroyOp(struct vk_command_buffer * commandBuffer)109 void vk_command_buffer_destroyOp(struct vk_command_buffer* commandBuffer) {
110     vk_command_buffer_finish(commandBuffer);
111     vk_free(&commandBuffer->pool->alloc, commandBuffer);
112 }
113 
gfxstream_vk_AllocateCommandBuffers(VkDevice device,const VkCommandBufferAllocateInfo * pAllocateInfo,VkCommandBuffer * pCommandBuffers)114 VkResult gfxstream_vk_AllocateCommandBuffers(VkDevice device,
115                                              const VkCommandBufferAllocateInfo* pAllocateInfo,
116                                              VkCommandBuffer* pCommandBuffers) {
117     MESA_TRACE_SCOPE("vkAllocateCommandBuffers");
118     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
119     VK_FROM_HANDLE(gfxstream_vk_command_pool, gfxstream_commandPool, pAllocateInfo->commandPool);
120     VkResult result = (VkResult)0;
121     for (uint32_t i = 0; i < pAllocateInfo->commandBufferCount; i++) {
122         pCommandBuffers[i] = VK_NULL_HANDLE;
123     }
124     std::vector<gfxstream_vk_command_buffer*> gfxstream_commandBuffers(
125         pAllocateInfo->commandBufferCount);
126     for (uint32_t i = 0; i < pAllocateInfo->commandBufferCount; i++) {
127         result =
128             vk_command_buffer_createOp(&gfxstream_commandPool->vk, VK_COMMAND_BUFFER_LEVEL_PRIMARY,
129                                        (vk_command_buffer**)&gfxstream_commandBuffers[i]);
130         if (VK_SUCCESS == result) {
131             gfxstream_commandBuffers[i]->vk.level = pAllocateInfo->level;
132         } else {
133             break;
134         }
135     }
136     if (VK_SUCCESS == result) {
137         // Create gfxstream-internal commandBuffer array
138         std::vector<VkCommandBuffer> internal_objects(pAllocateInfo->commandBufferCount);
139         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
140         auto resources = gfxstream::vk::ResourceTracker::get();
141         VkCommandBufferAllocateInfo internal_allocateInfo;
142         internal_allocateInfo = *pAllocateInfo;
143         internal_allocateInfo.commandPool = gfxstream_commandPool->internal_object;
144         result = resources->on_vkAllocateCommandBuffers(
145             vkEnc, VK_SUCCESS, gfxstream_device->internal_object, &internal_allocateInfo,
146             internal_objects.data());
147         if (result == VK_SUCCESS) {
148             gfxstream::vk::ResourceTracker::get()->addToCommandPool(
149                 gfxstream_commandPool->internal_object, pAllocateInfo->commandBufferCount,
150                 internal_objects.data());
151             for (uint32_t i = 0; i < (uint32_t)internal_objects.size(); i++) {
152                 gfxstream_commandBuffers[i]->internal_object = internal_objects[i];
153                 // TODO: Also vk_command_buffer_init() on every mesa command buffer?
154                 pCommandBuffers[i] =
155                     gfxstream_vk_command_buffer_to_handle(gfxstream_commandBuffers[i]);
156             }
157         }
158     }
159     return result;
160 }
161 
gfxstream_vk_FreeCommandBuffers(VkDevice device,VkCommandPool commandPool,uint32_t commandBufferCount,const VkCommandBuffer * pCommandBuffers)162 void gfxstream_vk_FreeCommandBuffers(VkDevice device, VkCommandPool commandPool,
163                                      uint32_t commandBufferCount,
164                                      const VkCommandBuffer* pCommandBuffers) {
165     MESA_TRACE_SCOPE("vkFreeCommandBuffers");
166     VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device);
167     VK_FROM_HANDLE(gfxstream_vk_command_pool, gfxstream_commandPool, commandPool);
168     {
169         // Set up internal commandBuffer array for gfxstream-internal call
170         std::vector<VkCommandBuffer> internal_objects;
171         internal_objects.reserve(commandBufferCount);
172         for (uint32_t i = 0; i < commandBufferCount; i++) {
173             VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer,
174                            pCommandBuffers[i]);
175             if (gfxstream_commandBuffer) {
176                 internal_objects.push_back(gfxstream_commandBuffer->internal_object);
177             }
178         }
179         auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder();
180         vkEnc->vkFreeCommandBuffers(gfxstream_device->internal_object,
181                                     gfxstream_commandPool->internal_object,
182                                     internal_objects.size(),
183                                     internal_objects.data(), true /* do lock */);
184     }
185     for (uint32_t i = 0; i < commandBufferCount; i++) {
186         VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, pCommandBuffers[i]);
187         if (gfxstream_commandBuffer) {
188             vk_command_buffer_destroyOp(&gfxstream_commandBuffer->vk);
189         }
190     }
191 }
192 
gfxstream_vk_CmdBeginTransformFeedbackEXT(VkCommandBuffer commandBuffer,uint32_t firstCounterBuffer,uint32_t counterBufferCount,const VkBuffer * pCounterBuffers,const VkDeviceSize * pCounterBufferOffsets)193 void gfxstream_vk_CmdBeginTransformFeedbackEXT(VkCommandBuffer commandBuffer,
194                                                uint32_t firstCounterBuffer,
195                                                uint32_t counterBufferCount,
196                                                const VkBuffer* pCounterBuffers,
197                                                const VkDeviceSize* pCounterBufferOffsets) {
198     MESA_TRACE_SCOPE("vkCmdBeginTransformFeedbackEXT");
199     VK_FROM_HANDLE(gfxstream_vk_command_buffer, gfxstream_commandBuffer, commandBuffer);
200     auto vkEnc = gfxstream::vk::ResourceTracker::getCommandBufferEncoder(
201         gfxstream_commandBuffer->internal_object);
202     std::vector<VkBuffer> internal_pCounterBuffers(counterBufferCount);
203     for (uint32_t i = 0; i < counterBufferCount; ++i) {
204         if (pCounterBuffers && pCounterBuffers[i]) {
205             VK_FROM_HANDLE(gfxstream_vk_buffer, gfxstream_pCounterBuffers, pCounterBuffers[i]);
206             internal_pCounterBuffers[i] = gfxstream_pCounterBuffers->internal_object;
207         }
208     }
209     vkEnc->vkCmdBeginTransformFeedbackEXT(gfxstream_commandBuffer->internal_object,
210                                           firstCounterBuffer, counterBufferCount,
211                                           pCounterBuffers ? internal_pCounterBuffers.data() : NULL,
212                                           pCounterBufferOffsets, true /* do lock */);
213 }
214