1 /*
2 * Copyright © 2021 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 #include "vk_command_buffer.h"
25
26 #include "vk_command_pool.h"
27 #include "vk_common_entrypoints.h"
28 #include "vk_device.h"
29
30 VkResult
vk_command_buffer_init(struct vk_command_pool * pool,struct vk_command_buffer * command_buffer,const struct vk_command_buffer_ops * ops,VkCommandBufferLevel level)31 vk_command_buffer_init(struct vk_command_pool *pool,
32 struct vk_command_buffer *command_buffer,
33 const struct vk_command_buffer_ops *ops,
34 VkCommandBufferLevel level)
35 {
36 memset(command_buffer, 0, sizeof(*command_buffer));
37 vk_object_base_init(pool->base.device, &command_buffer->base,
38 VK_OBJECT_TYPE_COMMAND_BUFFER);
39
40 command_buffer->pool = pool;
41 command_buffer->level = level;
42 command_buffer->ops = ops;
43 vk_dynamic_graphics_state_init(&command_buffer->dynamic_graphics_state);
44 command_buffer->state = MESA_VK_COMMAND_BUFFER_STATE_INITIAL;
45 command_buffer->record_result = VK_SUCCESS;
46 vk_cmd_queue_init(&command_buffer->cmd_queue, &pool->alloc);
47 vk_meta_object_list_init(&command_buffer->meta_objects);
48 util_dynarray_init(&command_buffer->labels, NULL);
49 command_buffer->region_begin = true;
50
51 list_add(&command_buffer->pool_link, &pool->command_buffers);
52
53 return VK_SUCCESS;
54 }
55
56 void
vk_command_buffer_reset(struct vk_command_buffer * command_buffer)57 vk_command_buffer_reset(struct vk_command_buffer *command_buffer)
58 {
59 vk_dynamic_graphics_state_clear(&command_buffer->dynamic_graphics_state);
60 command_buffer->state = MESA_VK_COMMAND_BUFFER_STATE_INITIAL;
61 command_buffer->record_result = VK_SUCCESS;
62 vk_command_buffer_reset_render_pass(command_buffer);
63 vk_cmd_queue_reset(&command_buffer->cmd_queue);
64 vk_meta_object_list_reset(command_buffer->base.device,
65 &command_buffer->meta_objects);
66 util_dynarray_clear(&command_buffer->labels);
67 command_buffer->region_begin = true;
68 }
69
70 void
vk_command_buffer_begin(struct vk_command_buffer * command_buffer,const VkCommandBufferBeginInfo * pBeginInfo)71 vk_command_buffer_begin(struct vk_command_buffer *command_buffer,
72 const VkCommandBufferBeginInfo *pBeginInfo)
73 {
74 if (command_buffer->state != MESA_VK_COMMAND_BUFFER_STATE_INITIAL &&
75 command_buffer->ops->reset != NULL)
76 command_buffer->ops->reset(command_buffer, 0);
77
78 command_buffer->state = MESA_VK_COMMAND_BUFFER_STATE_RECORDING;
79 }
80
81 VkResult
vk_command_buffer_end(struct vk_command_buffer * command_buffer)82 vk_command_buffer_end(struct vk_command_buffer *command_buffer)
83 {
84 assert(command_buffer->state == MESA_VK_COMMAND_BUFFER_STATE_RECORDING);
85
86 if (vk_command_buffer_has_error(command_buffer))
87 command_buffer->state = MESA_VK_COMMAND_BUFFER_STATE_INVALID;
88 else
89 command_buffer->state = MESA_VK_COMMAND_BUFFER_STATE_EXECUTABLE;
90
91 return vk_command_buffer_get_record_result(command_buffer);
92 }
93
94 void
vk_command_buffer_finish(struct vk_command_buffer * command_buffer)95 vk_command_buffer_finish(struct vk_command_buffer *command_buffer)
96 {
97 list_del(&command_buffer->pool_link);
98 vk_command_buffer_reset_render_pass(command_buffer);
99 vk_cmd_queue_finish(&command_buffer->cmd_queue);
100 util_dynarray_fini(&command_buffer->labels);
101 vk_meta_object_list_finish(command_buffer->base.device,
102 &command_buffer->meta_objects);
103 vk_object_base_finish(&command_buffer->base);
104 }
105
106 void
vk_command_buffer_recycle(struct vk_command_buffer * cmd_buffer)107 vk_command_buffer_recycle(struct vk_command_buffer *cmd_buffer)
108 {
109 /* Reset, returning resources to the pool. The command buffer object
110 * itself will be recycled but, if the driver supports returning other
111 * resources such as batch buffers to the pool, it should do so so they're
112 * not tied up in recycled command buffer objects.
113 */
114 cmd_buffer->ops->reset(cmd_buffer,
115 VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT);
116
117 vk_object_base_recycle(&cmd_buffer->base);
118 }
119
120 VKAPI_ATTR VkResult VKAPI_CALL
vk_common_ResetCommandBuffer(VkCommandBuffer commandBuffer,VkCommandBufferResetFlags flags)121 vk_common_ResetCommandBuffer(VkCommandBuffer commandBuffer,
122 VkCommandBufferResetFlags flags)
123 {
124 VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer);
125
126 if (cmd_buffer->state != MESA_VK_COMMAND_BUFFER_STATE_INITIAL)
127 cmd_buffer->ops->reset(cmd_buffer, flags);
128
129 return VK_SUCCESS;
130 }
131
132 VKAPI_ATTR void VKAPI_CALL
vk_common_CmdExecuteCommands(VkCommandBuffer commandBuffer,uint32_t commandBufferCount,const VkCommandBuffer * pCommandBuffers)133 vk_common_CmdExecuteCommands(VkCommandBuffer commandBuffer,
134 uint32_t commandBufferCount,
135 const VkCommandBuffer *pCommandBuffers)
136 {
137 VK_FROM_HANDLE(vk_command_buffer, primary, commandBuffer);
138 const struct vk_device_dispatch_table *disp =
139 primary->base.device->command_dispatch_table;
140
141 for (uint32_t i = 0; i < commandBufferCount; i++) {
142 VK_FROM_HANDLE(vk_command_buffer, secondary, pCommandBuffers[i]);
143
144 vk_cmd_queue_execute(&secondary->cmd_queue, commandBuffer, disp);
145 }
146 }
147
148 VKAPI_ATTR void VKAPI_CALL
vk_common_CmdBindVertexBuffers(VkCommandBuffer commandBuffer,uint32_t firstBinding,uint32_t bindingCount,const VkBuffer * pBuffers,const VkDeviceSize * pOffsets)149 vk_common_CmdBindVertexBuffers(VkCommandBuffer commandBuffer,
150 uint32_t firstBinding,
151 uint32_t bindingCount,
152 const VkBuffer *pBuffers,
153 const VkDeviceSize *pOffsets)
154 {
155 VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer);
156 const struct vk_device_dispatch_table *disp =
157 &cmd_buffer->base.device->dispatch_table;
158
159 disp->CmdBindVertexBuffers2(commandBuffer, firstBinding, bindingCount,
160 pBuffers, pOffsets, NULL, NULL);
161 }
162
163 VKAPI_ATTR void VKAPI_CALL
vk_common_CmdBindIndexBuffer(VkCommandBuffer commandBuffer,VkBuffer buffer,VkDeviceSize offset,VkIndexType indexType)164 vk_common_CmdBindIndexBuffer(
165 VkCommandBuffer commandBuffer,
166 VkBuffer buffer,
167 VkDeviceSize offset,
168 VkIndexType indexType)
169 {
170 VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer);
171 const struct vk_device_dispatch_table *disp =
172 &cmd_buffer->base.device->dispatch_table;
173
174 disp->CmdBindIndexBuffer2KHR(commandBuffer, buffer, offset,
175 VK_WHOLE_SIZE, indexType);
176 }
177
178 VKAPI_ATTR void VKAPI_CALL
vk_common_CmdDispatch(VkCommandBuffer commandBuffer,uint32_t groupCountX,uint32_t groupCountY,uint32_t groupCountZ)179 vk_common_CmdDispatch(VkCommandBuffer commandBuffer,
180 uint32_t groupCountX,
181 uint32_t groupCountY,
182 uint32_t groupCountZ)
183 {
184 VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer);
185 const struct vk_device_dispatch_table *disp =
186 &cmd_buffer->base.device->dispatch_table;
187
188 disp->CmdDispatchBase(commandBuffer, 0, 0, 0,
189 groupCountX, groupCountY, groupCountZ);
190 }
191
192 VKAPI_ATTR void VKAPI_CALL
vk_common_CmdSetDeviceMask(VkCommandBuffer commandBuffer,uint32_t deviceMask)193 vk_common_CmdSetDeviceMask(VkCommandBuffer commandBuffer, uint32_t deviceMask)
194 {
195 /* Nothing to do here since we only support a single device */
196 assert(deviceMask == 0x1);
197 }
198
199 VkShaderStageFlags
vk_shader_stages_from_bind_point(VkPipelineBindPoint pipelineBindPoint)200 vk_shader_stages_from_bind_point(VkPipelineBindPoint pipelineBindPoint)
201 {
202 switch (pipelineBindPoint) {
203 #ifdef VK_ENABLE_BETA_EXTENSIONS
204 case VK_PIPELINE_BIND_POINT_EXECUTION_GRAPH_AMDX:
205 return VK_SHADER_STAGE_COMPUTE_BIT | MESA_VK_SHADER_STAGE_WORKGRAPH_HACK_BIT_FIXME;
206 #endif
207 case VK_PIPELINE_BIND_POINT_COMPUTE:
208 return VK_SHADER_STAGE_COMPUTE_BIT;
209 case VK_PIPELINE_BIND_POINT_GRAPHICS:
210 return VK_SHADER_STAGE_ALL_GRAPHICS | VK_SHADER_STAGE_TASK_BIT_EXT | VK_SHADER_STAGE_MESH_BIT_EXT;
211 case VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR:
212 return VK_SHADER_STAGE_RAYGEN_BIT_KHR |
213 VK_SHADER_STAGE_ANY_HIT_BIT_KHR |
214 VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR |
215 VK_SHADER_STAGE_MISS_BIT_KHR |
216 VK_SHADER_STAGE_INTERSECTION_BIT_KHR |
217 VK_SHADER_STAGE_CALLABLE_BIT_KHR;
218 default:
219 unreachable("unknown bind point!");
220 }
221 return 0;
222 }
223
224 VKAPI_ATTR void VKAPI_CALL
vk_common_CmdBindDescriptorSets(VkCommandBuffer commandBuffer,VkPipelineBindPoint pipelineBindPoint,VkPipelineLayout layout,uint32_t firstSet,uint32_t descriptorSetCount,const VkDescriptorSet * pDescriptorSets,uint32_t dynamicOffsetCount,const uint32_t * pDynamicOffsets)225 vk_common_CmdBindDescriptorSets(
226 VkCommandBuffer commandBuffer,
227 VkPipelineBindPoint pipelineBindPoint,
228 VkPipelineLayout layout,
229 uint32_t firstSet,
230 uint32_t descriptorSetCount,
231 const VkDescriptorSet* pDescriptorSets,
232 uint32_t dynamicOffsetCount,
233 const uint32_t* pDynamicOffsets)
234 {
235 const VkBindDescriptorSetsInfoKHR two = {
236 .sType = VK_STRUCTURE_TYPE_BIND_DESCRIPTOR_SETS_INFO_KHR,
237 .stageFlags = vk_shader_stages_from_bind_point(pipelineBindPoint),
238 .layout = layout,
239 .firstSet = firstSet,
240 .descriptorSetCount = descriptorSetCount,
241 .pDescriptorSets = pDescriptorSets,
242 .dynamicOffsetCount = dynamicOffsetCount,
243 .pDynamicOffsets = pDynamicOffsets
244 };
245
246 VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer);
247 const struct vk_device_dispatch_table *disp =
248 &cmd_buffer->base.device->dispatch_table;
249
250 disp->CmdBindDescriptorSets2KHR(commandBuffer, &two);
251 }
252
253 VKAPI_ATTR void VKAPI_CALL
vk_common_CmdPushConstants(VkCommandBuffer commandBuffer,VkPipelineLayout layout,VkShaderStageFlags stageFlags,uint32_t offset,uint32_t size,const void * pValues)254 vk_common_CmdPushConstants(
255 VkCommandBuffer commandBuffer,
256 VkPipelineLayout layout,
257 VkShaderStageFlags stageFlags,
258 uint32_t offset,
259 uint32_t size,
260 const void* pValues)
261 {
262 const VkPushConstantsInfoKHR two = {
263 .sType = VK_STRUCTURE_TYPE_PUSH_CONSTANTS_INFO_KHR,
264 .layout = layout,
265 .stageFlags = stageFlags,
266 .offset = offset,
267 .size = size,
268 .pValues = pValues,
269 };
270
271 VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer);
272 const struct vk_device_dispatch_table *disp =
273 &cmd_buffer->base.device->dispatch_table;
274
275 disp->CmdPushConstants2KHR(commandBuffer, &two);
276 }
277
278 VKAPI_ATTR void VKAPI_CALL
vk_common_CmdPushDescriptorSetKHR(VkCommandBuffer commandBuffer,VkPipelineBindPoint pipelineBindPoint,VkPipelineLayout layout,uint32_t set,uint32_t descriptorWriteCount,const VkWriteDescriptorSet * pDescriptorWrites)279 vk_common_CmdPushDescriptorSetKHR(
280 VkCommandBuffer commandBuffer,
281 VkPipelineBindPoint pipelineBindPoint,
282 VkPipelineLayout layout,
283 uint32_t set,
284 uint32_t descriptorWriteCount,
285 const VkWriteDescriptorSet* pDescriptorWrites)
286 {
287 const VkPushDescriptorSetInfoKHR two = {
288 .sType = VK_STRUCTURE_TYPE_PUSH_CONSTANTS_INFO_KHR,
289 .stageFlags = vk_shader_stages_from_bind_point(pipelineBindPoint),
290 .layout = layout,
291 .set = set,
292 .descriptorWriteCount = descriptorWriteCount,
293 .pDescriptorWrites = pDescriptorWrites,
294 };
295
296 VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer);
297 const struct vk_device_dispatch_table *disp =
298 &cmd_buffer->base.device->dispatch_table;
299
300 disp->CmdPushDescriptorSet2KHR(commandBuffer, &two);
301 }
302
303 VKAPI_ATTR void VKAPI_CALL
vk_common_CmdPushDescriptorSetWithTemplateKHR(VkCommandBuffer commandBuffer,VkDescriptorUpdateTemplate descriptorUpdateTemplate,VkPipelineLayout layout,uint32_t set,const void * pData)304 vk_common_CmdPushDescriptorSetWithTemplateKHR(
305 VkCommandBuffer commandBuffer,
306 VkDescriptorUpdateTemplate descriptorUpdateTemplate,
307 VkPipelineLayout layout,
308 uint32_t set,
309 const void* pData)
310 {
311 const VkPushDescriptorSetWithTemplateInfoKHR two = {
312 .sType = VK_STRUCTURE_TYPE_PUSH_DESCRIPTOR_SET_WITH_TEMPLATE_INFO_KHR,
313 .descriptorUpdateTemplate = descriptorUpdateTemplate,
314 .layout = layout,
315 .set = set,
316 .pData = pData,
317 };
318
319 VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer);
320 const struct vk_device_dispatch_table *disp =
321 &cmd_buffer->base.device->dispatch_table;
322
323 disp->CmdPushDescriptorSetWithTemplate2KHR(commandBuffer, &two);
324 }
325
326 VKAPI_ATTR void VKAPI_CALL
vk_common_CmdSetDescriptorBufferOffsetsEXT(VkCommandBuffer commandBuffer,VkPipelineBindPoint pipelineBindPoint,VkPipelineLayout layout,uint32_t firstSet,uint32_t setCount,const uint32_t * pBufferIndices,const VkDeviceSize * pOffsets)327 vk_common_CmdSetDescriptorBufferOffsetsEXT(
328 VkCommandBuffer commandBuffer,
329 VkPipelineBindPoint pipelineBindPoint,
330 VkPipelineLayout layout,
331 uint32_t firstSet,
332 uint32_t setCount,
333 const uint32_t* pBufferIndices,
334 const VkDeviceSize* pOffsets)
335 {
336 const VkSetDescriptorBufferOffsetsInfoEXT two = {
337 .sType = VK_STRUCTURE_TYPE_SET_DESCRIPTOR_BUFFER_OFFSETS_INFO_EXT,
338 .stageFlags = vk_shader_stages_from_bind_point(pipelineBindPoint),
339 .layout = layout,
340 .firstSet = firstSet,
341 .setCount = setCount,
342 .pBufferIndices = pBufferIndices,
343 .pOffsets = pOffsets
344 };
345
346 VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer);
347 const struct vk_device_dispatch_table *disp =
348 &cmd_buffer->base.device->dispatch_table;
349
350 disp->CmdSetDescriptorBufferOffsets2EXT(commandBuffer, &two);
351 }
352
353 VKAPI_ATTR void VKAPI_CALL
vk_common_CmdBindDescriptorBufferEmbeddedSamplersEXT(VkCommandBuffer commandBuffer,VkPipelineBindPoint pipelineBindPoint,VkPipelineLayout layout,uint32_t set)354 vk_common_CmdBindDescriptorBufferEmbeddedSamplersEXT(
355 VkCommandBuffer commandBuffer,
356 VkPipelineBindPoint pipelineBindPoint,
357 VkPipelineLayout layout,
358 uint32_t set)
359 {
360 const VkBindDescriptorBufferEmbeddedSamplersInfoEXT two = {
361 .sType = VK_STRUCTURE_TYPE_BIND_DESCRIPTOR_BUFFER_EMBEDDED_SAMPLERS_INFO_EXT,
362 .stageFlags = vk_shader_stages_from_bind_point(pipelineBindPoint),
363 .layout = layout,
364 .set = set
365 };
366
367 VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer);
368 const struct vk_device_dispatch_table *disp =
369 &cmd_buffer->base.device->dispatch_table;
370
371 disp->CmdBindDescriptorBufferEmbeddedSamplers2EXT(commandBuffer, &two);
372 }
373