• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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