3 * Copyright © 2016 Red Hat.
4 * Copyright © 2016 Bas Nieuwenhuizen
6 * based in part on anv driver which is:
7 * Copyright © 2015 Intel Corporation
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
16 * The above copyright notice and this permission notice (including the next
17 * paragraph) shall be included in all copies or substantial portions of the
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
29 #include "libresoc_private.h"
31 void libresoc_CmdEndRenderPass(
32 VkCommandBuffer commandBuffer
)
34 LIBRESOC_FROM_HANDLE(libresoc_cmd_buffer
, cmd_buffer
, commandBuffer
);
35 struct libresoc_cmd
*cmd
;
36 cmd
= vk_alloc(&cmd_buffer
->device
->vk
.alloc
, sizeof(struct libresoc_cmd
), 8,
37 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
38 cmd
->command
.endRenderPass
.commandId
= EndRenderPassID
;
39 list_addtail(&cmd
->link
, &cmd_buffer
->cmd
.link
);
42 void libresoc_CmdSetScissor(
43 VkCommandBuffer commandBuffer
,
44 uint32_t firstScissor
,
45 uint32_t scissorCount
,
46 const VkRect2D
* pScissors
)
48 LIBRESOC_FROM_HANDLE(libresoc_cmd_buffer
, cmd_buffer
, commandBuffer
);
49 struct libresoc_cmd
*cmd
;
50 cmd
= vk_alloc(&cmd_buffer
->device
->vk
.alloc
, sizeof(struct libresoc_cmd
), 8,
51 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
52 cmd
->command
.setScissors
.commandId
= SetScissorsID
;
53 list_addtail(&cmd
->link
, &cmd_buffer
->cmd
.link
);
56 void libresoc_CmdPushConstants(VkCommandBuffer commandBuffer
,
57 VkPipelineLayout layout
,
58 VkShaderStageFlags stageFlags
,
63 LIBRESOC_FROM_HANDLE(libresoc_cmd_buffer
, cmd_buffer
, commandBuffer
);
64 struct libresoc_cmd
*cmd
;
65 cmd
= vk_alloc(&cmd_buffer
->device
->vk
.alloc
, sizeof(struct libresoc_cmd
), 8,
66 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
67 cmd
->command
.pushConstants
.commandId
= PushConstantsID
;
68 cmd
->command
.pushConstants
.offset
= offset
;
69 cmd
->command
.pushConstants
.size
= size
;
70 memcpy(cmd
->command
.pushConstants
.values
, pValues
, size
);
71 list_addtail(&cmd
->link
, &cmd_buffer
->cmd
.link
);
74 void libresoc_CmdDraw(
75 VkCommandBuffer commandBuffer
,
77 uint32_t instanceCount
,
79 uint32_t firstInstance
)
81 LIBRESOC_FROM_HANDLE(libresoc_cmd_buffer
, cmd_buffer
, commandBuffer
);
82 struct libresoc_cmd
*cmd
;
83 cmd
= vk_alloc(&cmd_buffer
->device
->vk
.alloc
, sizeof(struct libresoc_cmd
), 8,
84 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
85 cmd
->command
.draw
.commandId
= DrawID
;
86 cmd
->command
.draw
.vertexCount
= vertexCount
;
87 cmd
->command
.draw
.instanceCount
= instanceCount
;
88 cmd
->command
.draw
.firstVertex
= firstVertex
;
89 cmd
->command
.draw
.firstInstance
= firstInstance
;
90 list_addtail(&cmd
->link
, &cmd_buffer
->cmd
.link
);
93 void libresoc_CmdDrawIndexed(
94 VkCommandBuffer commandBuffer
,
96 uint32_t instanceCount
,
99 uint32_t firstInstance
)
101 LIBRESOC_FROM_HANDLE(libresoc_cmd_buffer
, cmd_buffer
, commandBuffer
);
102 struct libresoc_cmd
*cmd
;
103 cmd
= vk_alloc(&cmd_buffer
->device
->vk
.alloc
, sizeof(struct libresoc_cmd
), 8,
104 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
105 cmd
->command
.drawIndexed
.commandId
= DrawIndexedID
;
106 cmd
->command
.drawIndexed
.indexCount
= indexCount
;
107 cmd
->command
.drawIndexed
.instanceCount
= instanceCount
;
108 cmd
->command
.drawIndexed
.firstIndex
= firstIndex
;
109 cmd
->command
.drawIndexed
.vertexOffset
= vertexOffset
;
110 cmd
->command
.drawIndexed
.firstInstance
= firstInstance
;
111 list_addtail(&cmd
->link
, &cmd_buffer
->cmd
.link
);
114 void libresoc_CmdCopyBufferToImage(
115 VkCommandBuffer commandBuffer
,
118 VkImageLayout destImageLayout
,
119 uint32_t regionCount
,
120 const VkBufferImageCopy
* pRegions
)
122 LIBRESOC_FROM_HANDLE(libresoc_cmd_buffer
, cmd_buffer
, commandBuffer
);
123 for(uint32_t r
= 0; r
< regionCount
; r
++)
125 struct libresoc_cmd
*cmd
;
126 cmd
= vk_alloc(&cmd_buffer
->device
->vk
.alloc
, sizeof(struct libresoc_cmd
), 8,
127 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
128 cmd
->command
.copyBuf2Img
.commandId
= CopyBuf2ImgID
;
129 cmd
->command
.copyBuf2Img
.srcBuffer
= srcBuffer
;
130 cmd
->command
.copyBuf2Img
.dstImage
= destImage
;
131 cmd
->command
.copyBuf2Img
.region
= pRegions
[r
];
132 list_addtail(&cmd
->link
, &cmd_buffer
->cmd
.link
);
136 void libresoc_CmdCopyBuffer(
137 VkCommandBuffer commandBuffer
,
140 uint32_t regionCount
,
141 const VkBufferCopy
* pRegions
)
143 LIBRESOC_FROM_HANDLE(libresoc_cmd_buffer
, cmd_buffer
, commandBuffer
);
144 for(uint32_t r
= 0; r
< regionCount
; r
++)
146 struct libresoc_cmd
*cmd
;
147 cmd
= vk_alloc(&cmd_buffer
->device
->vk
.alloc
, sizeof(struct libresoc_cmd
), 8,
148 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
149 cmd
->command
.copyBuf
.commandId
= CopyBufID
;
150 cmd
->command
.copyBuf
.srcBuffer
= srcBuffer
;
151 cmd
->command
.copyBuf
.dstBuffer
= destBuffer
;
152 cmd
->command
.copyBuf
.region
= pRegions
[r
];
153 list_addtail(&cmd
->link
, &cmd_buffer
->cmd
.link
);
157 void libresoc_CmdBindPipeline(
158 VkCommandBuffer commandBuffer
,
159 VkPipelineBindPoint pipelineBindPoint
,
160 VkPipeline _pipeline
)
162 LIBRESOC_FROM_HANDLE(libresoc_cmd_buffer
, cmd_buffer
, commandBuffer
);
163 struct libresoc_cmd
*cmd
;
164 cmd
= vk_alloc(&cmd_buffer
->device
->vk
.alloc
, sizeof(struct libresoc_cmd
), 8,
165 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
166 cmd
->command
.bindPipeline
.commandId
= BindPipelineID
;
167 cmd
->command
.bindPipeline
.pipeline
= _pipeline
;
168 list_addtail(&cmd
->link
, &cmd_buffer
->cmd
.link
);
171 void libresoc_CmdBindDescriptorSets(
172 VkCommandBuffer commandBuffer
,
173 VkPipelineBindPoint pipelineBindPoint
,
174 VkPipelineLayout _layout
,
176 uint32_t descriptorSetCount
,
177 const VkDescriptorSet
* pDescriptorSets
,
178 uint32_t dynamicOffsetCount
,
179 const uint32_t* pDynamicOffsets
)
181 LIBRESOC_FROM_HANDLE(libresoc_cmd_buffer
, cmd_buffer
, commandBuffer
);
182 for(int i
=0; i
< descriptorSetCount
; ++i
)
184 struct libresoc_cmd
*cmd
;
185 cmd
= vk_alloc(&cmd_buffer
->device
->vk
.alloc
, sizeof(struct libresoc_cmd
), 8,
186 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
187 cmd
->command
.bindDescriptorSets
.commandId
= BindDescriptorSetsID
;
188 cmd
->command
.bindDescriptorSets
.idx
= firstSet
+ i
;
189 cmd
->command
.bindDescriptorSets
.set
= pDescriptorSets
[i
];
190 list_addtail(&cmd
->link
, &cmd_buffer
->cmd
.link
);
194 void libresoc_CmdBindVertexBuffers(
195 VkCommandBuffer commandBuffer
,
196 uint32_t firstBinding
,
197 uint32_t bindingCount
,
198 const VkBuffer
* pBuffers
,
199 const VkDeviceSize
* pOffsets
)
201 LIBRESOC_FROM_HANDLE(libresoc_cmd_buffer
, cmd_buffer
, commandBuffer
);
202 for(int i
=0; i
< bindingCount
; ++i
)
204 struct libresoc_cmd
*cmd
;
205 cmd
= vk_alloc(&cmd_buffer
->device
->vk
.alloc
, sizeof(struct libresoc_cmd
), 8,
206 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
207 cmd
->command
.bindVB
.commandId
= BindVBID
;
208 cmd
->command
.bindVB
.slot
= firstBinding
+ i
;
209 cmd
->command
.bindVB
.buffer
= pBuffers
[i
];
210 cmd
->command
.bindVB
.offset
= pOffsets
[i
];
211 list_addtail(&cmd
->link
, &cmd_buffer
->cmd
.link
);
215 void libresoc_CmdBindIndexBuffer(
216 VkCommandBuffer commandBuffer
,
219 VkIndexType indexType
)
221 LIBRESOC_FROM_HANDLE(libresoc_cmd_buffer
, cmd_buffer
, commandBuffer
);
222 struct libresoc_cmd
*cmd
;
223 cmd
= vk_alloc(&cmd_buffer
->device
->vk
.alloc
, sizeof(struct libresoc_cmd
), 8,
224 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
225 cmd
->command
.bindIB
.commandId
= BindIBID
;
226 cmd
->command
.bindIB
.buffer
= buffer
;
227 cmd
->command
.bindIB
.offset
= offset
;
228 cmd
->command
.bindIB
.indexType
= indexType
;
229 list_addtail(&cmd
->link
, &cmd_buffer
->cmd
.link
);
232 void libresoc_CmdBeginRenderPass(
233 VkCommandBuffer commandBuffer
,
234 const VkRenderPassBeginInfo
* pRenderPassBegin
,
235 VkSubpassContents contents
)
238 LIBRESOC_FROM_HANDLE(libresoc_cmd_buffer
, cmd_buffer
, commandBuffer
);
239 struct libresoc_cmd
*cmd
;
240 cmd
= vk_alloc(&cmd_buffer
->device
->vk
.alloc
, sizeof(struct libresoc_cmd
), 8,
241 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
242 cmd
->command
.beginRenderPass
.commandId
= BeginRenderPassID
;
243 cmd
->command
.beginRenderPass
.renderPass
= pRenderPassBegin
->renderPass
;
244 cmd
->command
.beginRenderPass
.framebuffer
= pRenderPassBegin
->framebuffer
;
245 size_t count
= (pRenderPassBegin
->clearValueCount
< 8U) ? pRenderPassBegin
->clearValueCount
: 8U;
246 memcpy(&cmd
->command
.beginRenderPass
.clearval
, pRenderPassBegin
->pClearValues
,
247 sizeof(VkClearValue
) * count
);
248 list_addtail(&cmd
->link
, &cmd_buffer
->cmd
.link
);
251 void libresoc_FreeCommandBuffers(
253 VkCommandPool commandPool
,
254 uint32_t commandBufferCount
,
255 const VkCommandBuffer
*pCommandBuffers
)
260 VkResult
libresoc_CreateCommandPool(
262 const VkCommandPoolCreateInfo
* pCreateInfo
,
263 const VkAllocationCallbacks
* pAllocator
,
264 VkCommandPool
* pCmdPool
)
266 LIBRESOC_FROM_HANDLE(libresoc_device
, device
, _device
);
267 struct libresoc_cmd_pool
*pool
;
269 pool
= vk_alloc2(&device
->vk
.alloc
, pAllocator
, sizeof(*pool
), 8,
270 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
272 return vk_error(device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
274 vk_object_base_init(&device
->vk
, &pool
->base
,
275 VK_OBJECT_TYPE_COMMAND_POOL
);
278 pool
->alloc
= *pAllocator
;
280 pool
->alloc
= device
->vk
.alloc
;
282 list_inithead(&pool
->cmd_buffers
);
283 list_inithead(&pool
->free_cmd_buffers
);
285 pool
->queue_family_index
= pCreateInfo
->queueFamilyIndex
;
287 *pCmdPool
= libresoc_cmd_pool_to_handle(pool
);
293 void libresoc_DestroyCommandPool(
295 VkCommandPool commandPool
,
296 const VkAllocationCallbacks
* pAllocator
)
298 LIBRESOC_FROM_HANDLE(libresoc_device
, device
, _device
);
299 LIBRESOC_FROM_HANDLE(libresoc_cmd_pool
, pool
, commandPool
);
304 // list_for_each_entry_safe(struct libresoc_cmd_buffer, cmd_buffer,
305 // &pool->cmd_buffers, pool_link) {
306 // libresoc_destroy_cmd_buffer(cmd_buffer);
309 // list_for_each_entry_safe(struct libresoc_cmd_buffer, cmd_buffer,
310 // &pool->free_cmd_buffers, pool_link) {
311 // libresoc_destroy_cmd_buffer(cmd_buffer);
314 vk_object_base_finish(&pool
->base
);
315 vk_free2(&device
->vk
.alloc
, pAllocator
, pool
);
318 static VkResult
libresoc_create_cmd_buffer(
319 struct libresoc_device
* device
,
320 struct libresoc_cmd_pool
* pool
,
321 VkCommandBufferLevel level
,
322 VkCommandBuffer
* pCommandBuffer
)
324 struct libresoc_cmd_buffer
*cmd_buffer
;
326 cmd_buffer
= vk_zalloc(&pool
->alloc
, sizeof(*cmd_buffer
), 8,
327 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
328 if (cmd_buffer
== NULL
)
329 return vk_error(device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
331 vk_object_base_init(&device
->vk
, &cmd_buffer
->base
,
332 VK_OBJECT_TYPE_COMMAND_BUFFER
);
333 cmd_buffer
->device
= device
;
334 cmd_buffer
->size
= 0;
335 list_inithead(&cmd_buffer
->cmd
.link
);
336 *pCommandBuffer
= libresoc_cmd_buffer_to_handle(cmd_buffer
);
341 VkResult
libresoc_AllocateCommandBuffers(
343 const VkCommandBufferAllocateInfo
*pAllocateInfo
,
344 VkCommandBuffer
*pCommandBuffers
)
346 LIBRESOC_FROM_HANDLE(libresoc_device
, device
, _device
);
347 LIBRESOC_FROM_HANDLE(libresoc_cmd_pool
, pool
, pAllocateInfo
->commandPool
);
349 VkResult result
= VK_SUCCESS
;
352 for (i
= 0; i
< pAllocateInfo
->commandBufferCount
; i
++) {
353 result
= libresoc_create_cmd_buffer(device
, pool
, pAllocateInfo
->level
,
354 &pCommandBuffers
[i
]);
355 if (result
!= VK_SUCCESS
)
359 // if (result != VK_SUCCESS) {
360 // libresoc_FreeCommandBuffers(_device, pAllocateInfo->commandPool,
361 // i, pCommandBuffers);
363 // /* From the Vulkan 1.0.66 spec:
365 // * "vkAllocateCommandBuffers can be used to create multiple
366 // * command buffers. If the creation of any of those command
367 // * buffers fails, the implementation must destroy all
368 // * successfully created command buffer objects from this
369 // * command, set all entries of the pCommandBuffers array to
370 // * NULL and return the error."
372 // memset(pCommandBuffers, 0,
373 // sizeof(*pCommandBuffers) * pAllocateInfo->commandBufferCount);
379 VkResult
libresoc_BeginCommandBuffer(
380 VkCommandBuffer commandBuffer
,
381 const VkCommandBufferBeginInfo
*pBeginInfo
)
383 LIBRESOC_FROM_HANDLE(libresoc_cmd_buffer
, cmd_buffer
, commandBuffer
);
384 VkResult result
= VK_SUCCESS
;
390 void libresoc_CmdPipelineBarrier(
391 VkCommandBuffer commandBuffer
,
392 VkPipelineStageFlags srcStageMask
,
393 VkPipelineStageFlags destStageMask
,
395 uint32_t memoryBarrierCount
,
396 const VkMemoryBarrier
* pMemoryBarriers
,
397 uint32_t bufferMemoryBarrierCount
,
398 const VkBufferMemoryBarrier
* pBufferMemoryBarriers
,
399 uint32_t imageMemoryBarrierCount
,
400 const VkImageMemoryBarrier
* pImageMemoryBarriers
)
402 // LIBRESOC_FROM_HANDLE(libresoc_cmd_buffer, cmd_buffer, commandBuffer);
403 // struct PipelineBarrier *cmd;
404 // cmd = vk_alloc(&cmd_buffer->device->vk.alloc, sizeof(struct PipelineBarrier), 8,
405 // VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
406 // cmd->commandId = PipelineBarrierID;
407 // if (list_is_empty(&cmd_buffer->list)) {
408 // list_inithead(&cmd);
410 // list_addtail(&cmd, &cmd_buffer->list);
412 // cmd_buffer->size += sizeof(struct PipelineBarrier);
415 VkResult
libresoc_EndCommandBuffer(
416 VkCommandBuffer commandBuffer
)
419 LIBRESOC_FROM_HANDLE(libresoc_cmd_buffer
, cmd_buffer
, commandBuffer
);
421 // if (cmd_buffer->queue_family_index != LIBRESOC_QUEUE_TRANSFER) {
422 // if (cmd_buffer->device->physical_device->rad_info.chip_class == GFX6)
423 // cmd_buffer->state.flush_bits |= LIBRESOC_CMD_FLAG_CS_PARTIAL_FLUSH | LIBRESOC_CMD_FLAG_PS_PARTIAL_FLUSH | LIBRESOC_CMD_FLAG_WB_L2;
425 // /* Make sure to sync all pending active queries at the end of
428 // cmd_buffer->state.flush_bits |= cmd_buffer->active_query_flush_bits;
430 // /* Since NGG streamout uses GDS, we need to make GDS idle when
431 // * we leave the IB, otherwise another process might overwrite
432 // * it while our shaders are busy.
434 // if (cmd_buffer->gds_needed)
435 // cmd_buffer->state.flush_bits |= LIBRESOC_CMD_FLAG_PS_PARTIAL_FLUSH;
437 // si_emit_cache_flush(cmd_buffer);
440 // /* Make sure CP DMA is idle at the end of IBs because the kernel
441 // * doesn't wait for it.
443 // si_cp_dma_wait_for_idle(cmd_buffer);
445 // libresoc_describe_end_cmd_buffer(cmd_buffer);
447 // vk_free(&cmd_buffer->pool->alloc, cmd_buffer->state.attachments);
448 // vk_free(&cmd_buffer->pool->alloc, cmd_buffer->state.subpass_sample_locs);
450 // VkResult result = cmd_buffer->device->ws->cs_finalize(cmd_buffer->cs);
451 // if (result != VK_SUCCESS)
452 // return vk_error(cmd_buffer->device->instance, result);
454 // cmd_buffer->status = LIBRESOC_CMD_BUFFER_STATUS_EXECUTABLE;