• 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    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