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