1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © 2019 Red Hat.
3bf215546Sopenharmony_ci * Copyright © 2022 Collabora, LTD
4bf215546Sopenharmony_ci *
5bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
6bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
7bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
8bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
10bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
11bf215546Sopenharmony_ci *
12bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
13bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
14bf215546Sopenharmony_ci * Software.
15bf215546Sopenharmony_ci *
16bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22bf215546Sopenharmony_ci * IN THE SOFTWARE.
23bf215546Sopenharmony_ci */
24bf215546Sopenharmony_ci
25bf215546Sopenharmony_ci#include "vk_alloc.h"
26bf215546Sopenharmony_ci#include "vk_cmd_enqueue_entrypoints.h"
27bf215546Sopenharmony_ci#include "vk_command_buffer.h"
28bf215546Sopenharmony_ci#include "vk_device.h"
29bf215546Sopenharmony_ci#include "vk_pipeline_layout.h"
30bf215546Sopenharmony_ci#include "vk_util.h"
31bf215546Sopenharmony_ci
32bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
33bf215546Sopenharmony_civk_cmd_enqueue_CmdDrawMultiEXT(VkCommandBuffer commandBuffer,
34bf215546Sopenharmony_ci                               uint32_t drawCount,
35bf215546Sopenharmony_ci                               const VkMultiDrawInfoEXT *pVertexInfo,
36bf215546Sopenharmony_ci                               uint32_t instanceCount,
37bf215546Sopenharmony_ci                               uint32_t firstInstance,
38bf215546Sopenharmony_ci                               uint32_t stride)
39bf215546Sopenharmony_ci{
40bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer);
41bf215546Sopenharmony_ci
42bf215546Sopenharmony_ci   struct vk_cmd_queue_entry *cmd =
43bf215546Sopenharmony_ci      vk_zalloc(cmd_buffer->cmd_queue.alloc, sizeof(*cmd), 8,
44bf215546Sopenharmony_ci                VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
45bf215546Sopenharmony_ci   if (!cmd)
46bf215546Sopenharmony_ci      return;
47bf215546Sopenharmony_ci
48bf215546Sopenharmony_ci   cmd->type = VK_CMD_DRAW_MULTI_EXT;
49bf215546Sopenharmony_ci   list_addtail(&cmd->cmd_link, &cmd_buffer->cmd_queue.cmds);
50bf215546Sopenharmony_ci
51bf215546Sopenharmony_ci   cmd->u.draw_multi_ext.draw_count = drawCount;
52bf215546Sopenharmony_ci   if (pVertexInfo) {
53bf215546Sopenharmony_ci      unsigned i = 0;
54bf215546Sopenharmony_ci      cmd->u.draw_multi_ext.vertex_info =
55bf215546Sopenharmony_ci         vk_zalloc(cmd_buffer->cmd_queue.alloc,
56bf215546Sopenharmony_ci                   sizeof(*cmd->u.draw_multi_ext.vertex_info) * drawCount, 8,
57bf215546Sopenharmony_ci                   VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
58bf215546Sopenharmony_ci
59bf215546Sopenharmony_ci      vk_foreach_multi_draw(draw, i, pVertexInfo, drawCount, stride) {
60bf215546Sopenharmony_ci         memcpy(&cmd->u.draw_multi_ext.vertex_info[i], draw,
61bf215546Sopenharmony_ci                sizeof(*cmd->u.draw_multi_ext.vertex_info));
62bf215546Sopenharmony_ci      }
63bf215546Sopenharmony_ci   }
64bf215546Sopenharmony_ci   cmd->u.draw_multi_ext.instance_count = instanceCount;
65bf215546Sopenharmony_ci   cmd->u.draw_multi_ext.first_instance = firstInstance;
66bf215546Sopenharmony_ci   cmd->u.draw_multi_ext.stride = stride;
67bf215546Sopenharmony_ci}
68bf215546Sopenharmony_ci
69bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
70bf215546Sopenharmony_civk_cmd_enqueue_CmdDrawMultiIndexedEXT(VkCommandBuffer commandBuffer,
71bf215546Sopenharmony_ci                                      uint32_t drawCount,
72bf215546Sopenharmony_ci                                      const VkMultiDrawIndexedInfoEXT *pIndexInfo,
73bf215546Sopenharmony_ci                                      uint32_t instanceCount,
74bf215546Sopenharmony_ci                                      uint32_t firstInstance,
75bf215546Sopenharmony_ci                                      uint32_t stride,
76bf215546Sopenharmony_ci                                      const int32_t *pVertexOffset)
77bf215546Sopenharmony_ci{
78bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer);
79bf215546Sopenharmony_ci
80bf215546Sopenharmony_ci   struct vk_cmd_queue_entry *cmd =
81bf215546Sopenharmony_ci      vk_zalloc(cmd_buffer->cmd_queue.alloc, sizeof(*cmd), 8,
82bf215546Sopenharmony_ci                VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
83bf215546Sopenharmony_ci   if (!cmd)
84bf215546Sopenharmony_ci      return;
85bf215546Sopenharmony_ci
86bf215546Sopenharmony_ci   cmd->type = VK_CMD_DRAW_MULTI_INDEXED_EXT;
87bf215546Sopenharmony_ci   list_addtail(&cmd->cmd_link, &cmd_buffer->cmd_queue.cmds);
88bf215546Sopenharmony_ci
89bf215546Sopenharmony_ci   cmd->u.draw_multi_indexed_ext.draw_count = drawCount;
90bf215546Sopenharmony_ci
91bf215546Sopenharmony_ci   if (pIndexInfo) {
92bf215546Sopenharmony_ci      unsigned i = 0;
93bf215546Sopenharmony_ci      cmd->u.draw_multi_indexed_ext.index_info =
94bf215546Sopenharmony_ci         vk_zalloc(cmd_buffer->cmd_queue.alloc,
95bf215546Sopenharmony_ci                   sizeof(*cmd->u.draw_multi_indexed_ext.index_info) * drawCount, 8,
96bf215546Sopenharmony_ci                   VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
97bf215546Sopenharmony_ci
98bf215546Sopenharmony_ci      vk_foreach_multi_draw_indexed(draw, i, pIndexInfo, drawCount, stride) {
99bf215546Sopenharmony_ci         cmd->u.draw_multi_indexed_ext.index_info[i].firstIndex = draw->firstIndex;
100bf215546Sopenharmony_ci         cmd->u.draw_multi_indexed_ext.index_info[i].indexCount = draw->indexCount;
101bf215546Sopenharmony_ci         if (pVertexOffset == NULL)
102bf215546Sopenharmony_ci            cmd->u.draw_multi_indexed_ext.index_info[i].vertexOffset = draw->vertexOffset;
103bf215546Sopenharmony_ci      }
104bf215546Sopenharmony_ci   }
105bf215546Sopenharmony_ci
106bf215546Sopenharmony_ci   cmd->u.draw_multi_indexed_ext.instance_count = instanceCount;
107bf215546Sopenharmony_ci   cmd->u.draw_multi_indexed_ext.first_instance = firstInstance;
108bf215546Sopenharmony_ci   cmd->u.draw_multi_indexed_ext.stride = stride;
109bf215546Sopenharmony_ci
110bf215546Sopenharmony_ci   if (pVertexOffset) {
111bf215546Sopenharmony_ci      cmd->u.draw_multi_indexed_ext.vertex_offset =
112bf215546Sopenharmony_ci         vk_zalloc(cmd_buffer->cmd_queue.alloc,
113bf215546Sopenharmony_ci                   sizeof(*cmd->u.draw_multi_indexed_ext.vertex_offset), 8,
114bf215546Sopenharmony_ci                   VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
115bf215546Sopenharmony_ci
116bf215546Sopenharmony_ci      memcpy(cmd->u.draw_multi_indexed_ext.vertex_offset, pVertexOffset,
117bf215546Sopenharmony_ci             sizeof(*cmd->u.draw_multi_indexed_ext.vertex_offset));
118bf215546Sopenharmony_ci   }
119bf215546Sopenharmony_ci}
120bf215546Sopenharmony_ci
121bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
122bf215546Sopenharmony_civk_cmd_enqueue_CmdPushDescriptorSetKHR(VkCommandBuffer commandBuffer,
123bf215546Sopenharmony_ci                                       VkPipelineBindPoint pipelineBindPoint,
124bf215546Sopenharmony_ci                                       VkPipelineLayout layout,
125bf215546Sopenharmony_ci                                       uint32_t set,
126bf215546Sopenharmony_ci                                       uint32_t descriptorWriteCount,
127bf215546Sopenharmony_ci                                       const VkWriteDescriptorSet *pDescriptorWrites)
128bf215546Sopenharmony_ci{
129bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer);
130bf215546Sopenharmony_ci   struct vk_cmd_push_descriptor_set_khr *pds;
131bf215546Sopenharmony_ci
132bf215546Sopenharmony_ci   struct vk_cmd_queue_entry *cmd =
133bf215546Sopenharmony_ci      vk_zalloc(cmd_buffer->cmd_queue.alloc, sizeof(*cmd), 8,
134bf215546Sopenharmony_ci                VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
135bf215546Sopenharmony_ci   if (!cmd)
136bf215546Sopenharmony_ci      return;
137bf215546Sopenharmony_ci
138bf215546Sopenharmony_ci   pds = &cmd->u.push_descriptor_set_khr;
139bf215546Sopenharmony_ci
140bf215546Sopenharmony_ci   cmd->type = VK_CMD_PUSH_DESCRIPTOR_SET_KHR;
141bf215546Sopenharmony_ci   list_addtail(&cmd->cmd_link, &cmd_buffer->cmd_queue.cmds);
142bf215546Sopenharmony_ci
143bf215546Sopenharmony_ci   pds->pipeline_bind_point = pipelineBindPoint;
144bf215546Sopenharmony_ci   pds->layout = layout;
145bf215546Sopenharmony_ci   pds->set = set;
146bf215546Sopenharmony_ci   pds->descriptor_write_count = descriptorWriteCount;
147bf215546Sopenharmony_ci
148bf215546Sopenharmony_ci   if (pDescriptorWrites) {
149bf215546Sopenharmony_ci      pds->descriptor_writes =
150bf215546Sopenharmony_ci         vk_zalloc(cmd_buffer->cmd_queue.alloc,
151bf215546Sopenharmony_ci                   sizeof(*pds->descriptor_writes) * descriptorWriteCount, 8,
152bf215546Sopenharmony_ci                   VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
153bf215546Sopenharmony_ci      memcpy(pds->descriptor_writes,
154bf215546Sopenharmony_ci             pDescriptorWrites,
155bf215546Sopenharmony_ci             sizeof(*pds->descriptor_writes) * descriptorWriteCount);
156bf215546Sopenharmony_ci
157bf215546Sopenharmony_ci      for (unsigned i = 0; i < descriptorWriteCount; i++) {
158bf215546Sopenharmony_ci         switch (pds->descriptor_writes[i].descriptorType) {
159bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_SAMPLER:
160bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
161bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
162bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
163bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
164bf215546Sopenharmony_ci            pds->descriptor_writes[i].pImageInfo =
165bf215546Sopenharmony_ci               vk_zalloc(cmd_buffer->cmd_queue.alloc,
166bf215546Sopenharmony_ci                         sizeof(VkDescriptorImageInfo) * pds->descriptor_writes[i].descriptorCount, 8,
167bf215546Sopenharmony_ci                         VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
168bf215546Sopenharmony_ci            memcpy((VkDescriptorImageInfo *)pds->descriptor_writes[i].pImageInfo,
169bf215546Sopenharmony_ci                   pDescriptorWrites[i].pImageInfo,
170bf215546Sopenharmony_ci                   sizeof(VkDescriptorImageInfo) * pds->descriptor_writes[i].descriptorCount);
171bf215546Sopenharmony_ci            break;
172bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
173bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
174bf215546Sopenharmony_ci            pds->descriptor_writes[i].pTexelBufferView =
175bf215546Sopenharmony_ci               vk_zalloc(cmd_buffer->cmd_queue.alloc,
176bf215546Sopenharmony_ci                         sizeof(VkBufferView) * pds->descriptor_writes[i].descriptorCount, 8,
177bf215546Sopenharmony_ci                         VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
178bf215546Sopenharmony_ci            memcpy((VkBufferView *)pds->descriptor_writes[i].pTexelBufferView,
179bf215546Sopenharmony_ci                   pDescriptorWrites[i].pTexelBufferView,
180bf215546Sopenharmony_ci                   sizeof(VkBufferView) * pds->descriptor_writes[i].descriptorCount);
181bf215546Sopenharmony_ci            break;
182bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
183bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
184bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
185bf215546Sopenharmony_ci         case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
186bf215546Sopenharmony_ci         default:
187bf215546Sopenharmony_ci            pds->descriptor_writes[i].pBufferInfo =
188bf215546Sopenharmony_ci               vk_zalloc(cmd_buffer->cmd_queue.alloc,
189bf215546Sopenharmony_ci                         sizeof(VkDescriptorBufferInfo) * pds->descriptor_writes[i].descriptorCount, 8,
190bf215546Sopenharmony_ci                         VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
191bf215546Sopenharmony_ci            memcpy((VkDescriptorBufferInfo *)pds->descriptor_writes[i].pBufferInfo,
192bf215546Sopenharmony_ci                   pDescriptorWrites[i].pBufferInfo,
193bf215546Sopenharmony_ci                   sizeof(VkDescriptorBufferInfo) * pds->descriptor_writes[i].descriptorCount);
194bf215546Sopenharmony_ci            break;
195bf215546Sopenharmony_ci         }
196bf215546Sopenharmony_ci      }
197bf215546Sopenharmony_ci   }
198bf215546Sopenharmony_ci}
199bf215546Sopenharmony_ci
200bf215546Sopenharmony_cistatic void
201bf215546Sopenharmony_ciunref_pipeline_layout(struct vk_cmd_queue *queue,
202bf215546Sopenharmony_ci                      struct vk_cmd_queue_entry *cmd)
203bf215546Sopenharmony_ci{
204bf215546Sopenharmony_ci   struct vk_command_buffer *cmd_buffer =
205bf215546Sopenharmony_ci      container_of(queue, struct vk_command_buffer, cmd_queue);
206bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_pipeline_layout, layout,
207bf215546Sopenharmony_ci                  cmd->u.bind_descriptor_sets.layout);
208bf215546Sopenharmony_ci
209bf215546Sopenharmony_ci   assert(cmd->type == VK_CMD_BIND_DESCRIPTOR_SETS);
210bf215546Sopenharmony_ci
211bf215546Sopenharmony_ci   vk_pipeline_layout_unref(cmd_buffer->base.device, layout);
212bf215546Sopenharmony_ci}
213bf215546Sopenharmony_ci
214bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
215bf215546Sopenharmony_civk_cmd_enqueue_CmdBindDescriptorSets(VkCommandBuffer commandBuffer,
216bf215546Sopenharmony_ci                                     VkPipelineBindPoint pipelineBindPoint,
217bf215546Sopenharmony_ci                                     VkPipelineLayout layout,
218bf215546Sopenharmony_ci                                     uint32_t firstSet,
219bf215546Sopenharmony_ci                                     uint32_t descriptorSetCount,
220bf215546Sopenharmony_ci                                     const VkDescriptorSet* pDescriptorSets,
221bf215546Sopenharmony_ci                                     uint32_t dynamicOffsetCount,
222bf215546Sopenharmony_ci                                     const uint32_t *pDynamicOffsets)
223bf215546Sopenharmony_ci{
224bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer);
225bf215546Sopenharmony_ci
226bf215546Sopenharmony_ci   struct vk_cmd_queue_entry *cmd =
227bf215546Sopenharmony_ci      vk_zalloc(cmd_buffer->cmd_queue.alloc, sizeof(*cmd), 8,
228bf215546Sopenharmony_ci                VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
229bf215546Sopenharmony_ci   if (!cmd)
230bf215546Sopenharmony_ci      return;
231bf215546Sopenharmony_ci
232bf215546Sopenharmony_ci   cmd->type = VK_CMD_BIND_DESCRIPTOR_SETS;
233bf215546Sopenharmony_ci   list_addtail(&cmd->cmd_link, &cmd_buffer->cmd_queue.cmds);
234bf215546Sopenharmony_ci
235bf215546Sopenharmony_ci   /* We need to hold a reference to the descriptor set as long as this
236bf215546Sopenharmony_ci    * command is in the queue.  Otherwise, it may get deleted out from under
237bf215546Sopenharmony_ci    * us before the command is replayed.
238bf215546Sopenharmony_ci    */
239bf215546Sopenharmony_ci   vk_pipeline_layout_ref(vk_pipeline_layout_from_handle(layout));
240bf215546Sopenharmony_ci   cmd->u.bind_descriptor_sets.layout = layout;
241bf215546Sopenharmony_ci   cmd->driver_free_cb = unref_pipeline_layout;
242bf215546Sopenharmony_ci
243bf215546Sopenharmony_ci   cmd->u.bind_descriptor_sets.pipeline_bind_point = pipelineBindPoint;
244bf215546Sopenharmony_ci   cmd->u.bind_descriptor_sets.first_set = firstSet;
245bf215546Sopenharmony_ci   cmd->u.bind_descriptor_sets.descriptor_set_count = descriptorSetCount;
246bf215546Sopenharmony_ci   if (pDescriptorSets) {
247bf215546Sopenharmony_ci      cmd->u.bind_descriptor_sets.descriptor_sets =
248bf215546Sopenharmony_ci         vk_zalloc(cmd_buffer->cmd_queue.alloc,
249bf215546Sopenharmony_ci                   sizeof(*cmd->u.bind_descriptor_sets.descriptor_sets) * descriptorSetCount, 8,
250bf215546Sopenharmony_ci                   VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
251bf215546Sopenharmony_ci
252bf215546Sopenharmony_ci      memcpy(cmd->u.bind_descriptor_sets.descriptor_sets, pDescriptorSets,
253bf215546Sopenharmony_ci             sizeof(*cmd->u.bind_descriptor_sets.descriptor_sets) * descriptorSetCount);
254bf215546Sopenharmony_ci   }
255bf215546Sopenharmony_ci   cmd->u.bind_descriptor_sets.dynamic_offset_count = dynamicOffsetCount;
256bf215546Sopenharmony_ci   if (pDynamicOffsets) {
257bf215546Sopenharmony_ci      cmd->u.bind_descriptor_sets.dynamic_offsets =
258bf215546Sopenharmony_ci         vk_zalloc(cmd_buffer->cmd_queue.alloc,
259bf215546Sopenharmony_ci                   sizeof(*cmd->u.bind_descriptor_sets.dynamic_offsets) * dynamicOffsetCount, 8,
260bf215546Sopenharmony_ci                   VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
261bf215546Sopenharmony_ci
262bf215546Sopenharmony_ci      memcpy(cmd->u.bind_descriptor_sets.dynamic_offsets, pDynamicOffsets,
263bf215546Sopenharmony_ci             sizeof(*cmd->u.bind_descriptor_sets.dynamic_offsets) * dynamicOffsetCount);
264bf215546Sopenharmony_ci   }
265bf215546Sopenharmony_ci}
266