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 #if USE_VK_COMPILER
44 vk_dynamic_graphics_state_init(&command_buffer->dynamic_graphics_state);
45 #endif
46 command_buffer->state = MESA_VK_COMMAND_BUFFER_STATE_INITIAL;
47 command_buffer->record_result = VK_SUCCESS;
48 vk_cmd_queue_init(&command_buffer->cmd_queue, &pool->alloc);
49 vk_meta_object_list_init(&command_buffer->meta_objects);
50 util_dynarray_init(&command_buffer->labels, NULL);
51 command_buffer->region_begin = true;
52
53 list_add(&command_buffer->pool_link, &pool->command_buffers);
54
55 return VK_SUCCESS;
56 }
57
58 void
vk_command_buffer_reset(struct vk_command_buffer * command_buffer)59 vk_command_buffer_reset(struct vk_command_buffer *command_buffer)
60 {
61 #if USE_VK_COMPILER
62 vk_dynamic_graphics_state_clear(&command_buffer->dynamic_graphics_state);
63 #endif
64 command_buffer->state = MESA_VK_COMMAND_BUFFER_STATE_INITIAL;
65 command_buffer->record_result = VK_SUCCESS;
66 vk_command_buffer_reset_render_pass(command_buffer);
67 vk_cmd_queue_reset(&command_buffer->cmd_queue);
68 vk_meta_object_list_reset(command_buffer->base.device,
69 &command_buffer->meta_objects);
70 util_dynarray_clear(&command_buffer->labels);
71 command_buffer->region_begin = true;
72 }
73
74 void
vk_command_buffer_begin(struct vk_command_buffer * command_buffer,const VkCommandBufferBeginInfo * pBeginInfo)75 vk_command_buffer_begin(struct vk_command_buffer *command_buffer,
76 const VkCommandBufferBeginInfo *pBeginInfo)
77 {
78 if (command_buffer->state != MESA_VK_COMMAND_BUFFER_STATE_INITIAL &&
79 command_buffer->ops->reset != NULL)
80 command_buffer->ops->reset(command_buffer, 0);
81
82 command_buffer->state = MESA_VK_COMMAND_BUFFER_STATE_RECORDING;
83 }
84
85 VkResult
vk_command_buffer_end(struct vk_command_buffer * command_buffer)86 vk_command_buffer_end(struct vk_command_buffer *command_buffer)
87 {
88 assert(command_buffer->state == MESA_VK_COMMAND_BUFFER_STATE_RECORDING);
89
90 if (vk_command_buffer_has_error(command_buffer))
91 command_buffer->state = MESA_VK_COMMAND_BUFFER_STATE_INVALID;
92 else
93 command_buffer->state = MESA_VK_COMMAND_BUFFER_STATE_EXECUTABLE;
94
95 return vk_command_buffer_get_record_result(command_buffer);
96 }
97
98 void
vk_command_buffer_finish(struct vk_command_buffer * command_buffer)99 vk_command_buffer_finish(struct vk_command_buffer *command_buffer)
100 {
101 list_del(&command_buffer->pool_link);
102 vk_command_buffer_reset_render_pass(command_buffer);
103 vk_cmd_queue_finish(&command_buffer->cmd_queue);
104 util_dynarray_fini(&command_buffer->labels);
105 vk_meta_object_list_finish(command_buffer->base.device,
106 &command_buffer->meta_objects);
107 vk_object_base_finish(&command_buffer->base);
108 }
109
110 void
vk_command_buffer_recycle(struct vk_command_buffer * cmd_buffer)111 vk_command_buffer_recycle(struct vk_command_buffer *cmd_buffer)
112 {
113 /* Reset, returning resources to the pool. The command buffer object
114 * itself will be recycled but, if the driver supports returning other
115 * resources such as batch buffers to the pool, it should do so so they're
116 * not tied up in recycled command buffer objects.
117 */
118 cmd_buffer->ops->reset(cmd_buffer,
119 VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT);
120
121 vk_object_base_recycle(&cmd_buffer->base);
122 }
123
124 VKAPI_ATTR VkResult VKAPI_CALL
vk_common_ResetCommandBuffer(VkCommandBuffer commandBuffer,VkCommandBufferResetFlags flags)125 vk_common_ResetCommandBuffer(VkCommandBuffer commandBuffer,
126 VkCommandBufferResetFlags flags)
127 {
128 VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer);
129
130 if (cmd_buffer->state != MESA_VK_COMMAND_BUFFER_STATE_INITIAL)
131 cmd_buffer->ops->reset(cmd_buffer, flags);
132
133 return VK_SUCCESS;
134 }
135
136 VKAPI_ATTR void VKAPI_CALL
vk_common_CmdExecuteCommands(VkCommandBuffer commandBuffer,uint32_t commandBufferCount,const VkCommandBuffer * pCommandBuffers)137 vk_common_CmdExecuteCommands(VkCommandBuffer commandBuffer,
138 uint32_t commandBufferCount,
139 const VkCommandBuffer *pCommandBuffers)
140 {
141 VK_FROM_HANDLE(vk_command_buffer, primary, commandBuffer);
142 const struct vk_device_dispatch_table *disp =
143 primary->base.device->command_dispatch_table;
144
145 for (uint32_t i = 0; i < commandBufferCount; i++) {
146 VK_FROM_HANDLE(vk_command_buffer, secondary, pCommandBuffers[i]);
147
148 vk_cmd_queue_execute(&secondary->cmd_queue, commandBuffer, disp);
149 }
150 }
151
152 VKAPI_ATTR void VKAPI_CALL
vk_common_CmdBindVertexBuffers(VkCommandBuffer commandBuffer,uint32_t firstBinding,uint32_t bindingCount,const VkBuffer * pBuffers,const VkDeviceSize * pOffsets)153 vk_common_CmdBindVertexBuffers(VkCommandBuffer commandBuffer,
154 uint32_t firstBinding,
155 uint32_t bindingCount,
156 const VkBuffer *pBuffers,
157 const VkDeviceSize *pOffsets)
158 {
159 VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer);
160 const struct vk_device_dispatch_table *disp =
161 &cmd_buffer->base.device->dispatch_table;
162
163 disp->CmdBindVertexBuffers2(commandBuffer, firstBinding, bindingCount,
164 pBuffers, pOffsets, NULL, NULL);
165 }
166
167 VKAPI_ATTR void VKAPI_CALL
vk_common_CmdBindIndexBuffer(VkCommandBuffer commandBuffer,VkBuffer buffer,VkDeviceSize offset,VkIndexType indexType)168 vk_common_CmdBindIndexBuffer(
169 VkCommandBuffer commandBuffer,
170 VkBuffer buffer,
171 VkDeviceSize offset,
172 VkIndexType indexType)
173 {
174 VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer);
175 const struct vk_device_dispatch_table *disp =
176 &cmd_buffer->base.device->dispatch_table;
177
178 disp->CmdBindIndexBuffer2KHR(commandBuffer, buffer, offset,
179 VK_WHOLE_SIZE, indexType);
180 }
181
182 VKAPI_ATTR void VKAPI_CALL
vk_common_CmdDispatch(VkCommandBuffer commandBuffer,uint32_t groupCountX,uint32_t groupCountY,uint32_t groupCountZ)183 vk_common_CmdDispatch(VkCommandBuffer commandBuffer,
184 uint32_t groupCountX,
185 uint32_t groupCountY,
186 uint32_t groupCountZ)
187 {
188 VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer);
189 const struct vk_device_dispatch_table *disp =
190 &cmd_buffer->base.device->dispatch_table;
191
192 disp->CmdDispatchBase(commandBuffer, 0, 0, 0,
193 groupCountX, groupCountY, groupCountZ);
194 }
195
196 VKAPI_ATTR void VKAPI_CALL
vk_common_CmdSetDeviceMask(VkCommandBuffer commandBuffer,uint32_t deviceMask)197 vk_common_CmdSetDeviceMask(VkCommandBuffer commandBuffer, uint32_t deviceMask)
198 {
199 /* Nothing to do here since we only support a single device */
200 assert(deviceMask == 0x1);
201 }
202
203 VkShaderStageFlags
vk_shader_stages_from_bind_point(VkPipelineBindPoint pipelineBindPoint)204 vk_shader_stages_from_bind_point(VkPipelineBindPoint pipelineBindPoint)
205 {
206 switch (pipelineBindPoint) {
207 #ifdef VK_ENABLE_BETA_EXTENSIONS
208 case VK_PIPELINE_BIND_POINT_EXECUTION_GRAPH_AMDX:
209 return VK_SHADER_STAGE_COMPUTE_BIT | MESA_VK_SHADER_STAGE_WORKGRAPH_HACK_BIT_FIXME;
210 #endif
211 case VK_PIPELINE_BIND_POINT_COMPUTE:
212 return VK_SHADER_STAGE_COMPUTE_BIT;
213 case VK_PIPELINE_BIND_POINT_GRAPHICS:
214 return VK_SHADER_STAGE_ALL_GRAPHICS | VK_SHADER_STAGE_TASK_BIT_EXT | VK_SHADER_STAGE_MESH_BIT_EXT;
215 case VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR:
216 return VK_SHADER_STAGE_RAYGEN_BIT_KHR |
217 VK_SHADER_STAGE_ANY_HIT_BIT_KHR |
218 VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR |
219 VK_SHADER_STAGE_MISS_BIT_KHR |
220 VK_SHADER_STAGE_INTERSECTION_BIT_KHR |
221 VK_SHADER_STAGE_CALLABLE_BIT_KHR;
222 default:
223 unreachable("unknown bind point!");
224 }
225 return 0;
226 }
227
228 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)229 vk_common_CmdBindDescriptorSets(
230 VkCommandBuffer commandBuffer,
231 VkPipelineBindPoint pipelineBindPoint,
232 VkPipelineLayout layout,
233 uint32_t firstSet,
234 uint32_t descriptorSetCount,
235 const VkDescriptorSet* pDescriptorSets,
236 uint32_t dynamicOffsetCount,
237 const uint32_t* pDynamicOffsets)
238 {
239 const VkBindDescriptorSetsInfoKHR two = {
240 .sType = VK_STRUCTURE_TYPE_BIND_DESCRIPTOR_SETS_INFO_KHR,
241 .stageFlags = vk_shader_stages_from_bind_point(pipelineBindPoint),
242 .layout = layout,
243 .firstSet = firstSet,
244 .descriptorSetCount = descriptorSetCount,
245 .pDescriptorSets = pDescriptorSets,
246 .dynamicOffsetCount = dynamicOffsetCount,
247 .pDynamicOffsets = pDynamicOffsets
248 };
249
250 VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer);
251 const struct vk_device_dispatch_table *disp =
252 &cmd_buffer->base.device->dispatch_table;
253
254 disp->CmdBindDescriptorSets2KHR(commandBuffer, &two);
255 }
256
257 VKAPI_ATTR void VKAPI_CALL
vk_common_CmdPushConstants(VkCommandBuffer commandBuffer,VkPipelineLayout layout,VkShaderStageFlags stageFlags,uint32_t offset,uint32_t size,const void * pValues)258 vk_common_CmdPushConstants(
259 VkCommandBuffer commandBuffer,
260 VkPipelineLayout layout,
261 VkShaderStageFlags stageFlags,
262 uint32_t offset,
263 uint32_t size,
264 const void* pValues)
265 {
266 const VkPushConstantsInfoKHR two = {
267 .sType = VK_STRUCTURE_TYPE_PUSH_CONSTANTS_INFO_KHR,
268 .layout = layout,
269 .stageFlags = stageFlags,
270 .offset = offset,
271 .size = size,
272 .pValues = pValues,
273 };
274
275 VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer);
276 const struct vk_device_dispatch_table *disp =
277 &cmd_buffer->base.device->dispatch_table;
278
279 disp->CmdPushConstants2KHR(commandBuffer, &two);
280 }
281
282 VKAPI_ATTR void VKAPI_CALL
vk_common_CmdPushDescriptorSetKHR(VkCommandBuffer commandBuffer,VkPipelineBindPoint pipelineBindPoint,VkPipelineLayout layout,uint32_t set,uint32_t descriptorWriteCount,const VkWriteDescriptorSet * pDescriptorWrites)283 vk_common_CmdPushDescriptorSetKHR(
284 VkCommandBuffer commandBuffer,
285 VkPipelineBindPoint pipelineBindPoint,
286 VkPipelineLayout layout,
287 uint32_t set,
288 uint32_t descriptorWriteCount,
289 const VkWriteDescriptorSet* pDescriptorWrites)
290 {
291 const VkPushDescriptorSetInfoKHR two = {
292 .sType = VK_STRUCTURE_TYPE_PUSH_CONSTANTS_INFO_KHR,
293 .stageFlags = vk_shader_stages_from_bind_point(pipelineBindPoint),
294 .layout = layout,
295 .set = set,
296 .descriptorWriteCount = descriptorWriteCount,
297 .pDescriptorWrites = pDescriptorWrites,
298 };
299
300 VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer);
301 const struct vk_device_dispatch_table *disp =
302 &cmd_buffer->base.device->dispatch_table;
303
304 disp->CmdPushDescriptorSet2KHR(commandBuffer, &two);
305 }
306
307 VKAPI_ATTR void VKAPI_CALL
vk_common_CmdPushDescriptorSetWithTemplateKHR(VkCommandBuffer commandBuffer,VkDescriptorUpdateTemplate descriptorUpdateTemplate,VkPipelineLayout layout,uint32_t set,const void * pData)308 vk_common_CmdPushDescriptorSetWithTemplateKHR(
309 VkCommandBuffer commandBuffer,
310 VkDescriptorUpdateTemplate descriptorUpdateTemplate,
311 VkPipelineLayout layout,
312 uint32_t set,
313 const void* pData)
314 {
315 const VkPushDescriptorSetWithTemplateInfoKHR two = {
316 .sType = VK_STRUCTURE_TYPE_PUSH_DESCRIPTOR_SET_WITH_TEMPLATE_INFO_KHR,
317 .descriptorUpdateTemplate = descriptorUpdateTemplate,
318 .layout = layout,
319 .set = set,
320 .pData = pData,
321 };
322
323 VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer);
324 const struct vk_device_dispatch_table *disp =
325 &cmd_buffer->base.device->dispatch_table;
326
327 disp->CmdPushDescriptorSetWithTemplate2KHR(commandBuffer, &two);
328 }
329
330 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)331 vk_common_CmdSetDescriptorBufferOffsetsEXT(
332 VkCommandBuffer commandBuffer,
333 VkPipelineBindPoint pipelineBindPoint,
334 VkPipelineLayout layout,
335 uint32_t firstSet,
336 uint32_t setCount,
337 const uint32_t* pBufferIndices,
338 const VkDeviceSize* pOffsets)
339 {
340 const VkSetDescriptorBufferOffsetsInfoEXT two = {
341 .sType = VK_STRUCTURE_TYPE_SET_DESCRIPTOR_BUFFER_OFFSETS_INFO_EXT,
342 .stageFlags = vk_shader_stages_from_bind_point(pipelineBindPoint),
343 .layout = layout,
344 .firstSet = firstSet,
345 .setCount = setCount,
346 .pBufferIndices = pBufferIndices,
347 .pOffsets = pOffsets
348 };
349
350 VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer);
351 const struct vk_device_dispatch_table *disp =
352 &cmd_buffer->base.device->dispatch_table;
353
354 disp->CmdSetDescriptorBufferOffsets2EXT(commandBuffer, &two);
355 }
356
357 VKAPI_ATTR void VKAPI_CALL
vk_common_CmdBindDescriptorBufferEmbeddedSamplersEXT(VkCommandBuffer commandBuffer,VkPipelineBindPoint pipelineBindPoint,VkPipelineLayout layout,uint32_t set)358 vk_common_CmdBindDescriptorBufferEmbeddedSamplersEXT(
359 VkCommandBuffer commandBuffer,
360 VkPipelineBindPoint pipelineBindPoint,
361 VkPipelineLayout layout,
362 uint32_t set)
363 {
364 const VkBindDescriptorBufferEmbeddedSamplersInfoEXT two = {
365 .sType = VK_STRUCTURE_TYPE_BIND_DESCRIPTOR_BUFFER_EMBEDDED_SAMPLERS_INFO_EXT,
366 .stageFlags = vk_shader_stages_from_bind_point(pipelineBindPoint),
367 .layout = layout,
368 .set = set
369 };
370
371 VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer);
372 const struct vk_device_dispatch_table *disp =
373 &cmd_buffer->base.device->dispatch_table;
374
375 disp->CmdBindDescriptorBufferEmbeddedSamplers2EXT(commandBuffer, &two);
376 }
377