/* * Copyright © 2019 Red Hat. * Copyright © 2022 Collabora, LTD * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. */ #include "vk_alloc.h" #include "vk_cmd_enqueue_entrypoints.h" #include "vk_command_buffer.h" #include "vk_device.h" #include "vk_pipeline_layout.h" #include "vk_util.h" VKAPI_ATTR void VKAPI_CALL vk_cmd_enqueue_CmdDrawMultiEXT(VkCommandBuffer commandBuffer, uint32_t drawCount, const VkMultiDrawInfoEXT *pVertexInfo, uint32_t instanceCount, uint32_t firstInstance, uint32_t stride) { VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer); struct vk_cmd_queue_entry *cmd = vk_zalloc(cmd_buffer->cmd_queue.alloc, sizeof(*cmd), 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); if (!cmd) return; cmd->type = VK_CMD_DRAW_MULTI_EXT; list_addtail(&cmd->cmd_link, &cmd_buffer->cmd_queue.cmds); cmd->u.draw_multi_ext.draw_count = drawCount; if (pVertexInfo) { unsigned i = 0; cmd->u.draw_multi_ext.vertex_info = vk_zalloc(cmd_buffer->cmd_queue.alloc, sizeof(*cmd->u.draw_multi_ext.vertex_info) * drawCount, 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); vk_foreach_multi_draw(draw, i, pVertexInfo, drawCount, stride) { memcpy(&cmd->u.draw_multi_ext.vertex_info[i], draw, sizeof(*cmd->u.draw_multi_ext.vertex_info)); } } cmd->u.draw_multi_ext.instance_count = instanceCount; cmd->u.draw_multi_ext.first_instance = firstInstance; cmd->u.draw_multi_ext.stride = stride; } VKAPI_ATTR void VKAPI_CALL vk_cmd_enqueue_CmdDrawMultiIndexedEXT(VkCommandBuffer commandBuffer, uint32_t drawCount, const VkMultiDrawIndexedInfoEXT *pIndexInfo, uint32_t instanceCount, uint32_t firstInstance, uint32_t stride, const int32_t *pVertexOffset) { VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer); struct vk_cmd_queue_entry *cmd = vk_zalloc(cmd_buffer->cmd_queue.alloc, sizeof(*cmd), 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); if (!cmd) return; cmd->type = VK_CMD_DRAW_MULTI_INDEXED_EXT; list_addtail(&cmd->cmd_link, &cmd_buffer->cmd_queue.cmds); cmd->u.draw_multi_indexed_ext.draw_count = drawCount; if (pIndexInfo) { unsigned i = 0; cmd->u.draw_multi_indexed_ext.index_info = vk_zalloc(cmd_buffer->cmd_queue.alloc, sizeof(*cmd->u.draw_multi_indexed_ext.index_info) * drawCount, 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); vk_foreach_multi_draw_indexed(draw, i, pIndexInfo, drawCount, stride) { cmd->u.draw_multi_indexed_ext.index_info[i].firstIndex = draw->firstIndex; cmd->u.draw_multi_indexed_ext.index_info[i].indexCount = draw->indexCount; if (pVertexOffset == NULL) cmd->u.draw_multi_indexed_ext.index_info[i].vertexOffset = draw->vertexOffset; } } cmd->u.draw_multi_indexed_ext.instance_count = instanceCount; cmd->u.draw_multi_indexed_ext.first_instance = firstInstance; cmd->u.draw_multi_indexed_ext.stride = stride; if (pVertexOffset) { cmd->u.draw_multi_indexed_ext.vertex_offset = vk_zalloc(cmd_buffer->cmd_queue.alloc, sizeof(*cmd->u.draw_multi_indexed_ext.vertex_offset), 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); memcpy(cmd->u.draw_multi_indexed_ext.vertex_offset, pVertexOffset, sizeof(*cmd->u.draw_multi_indexed_ext.vertex_offset)); } } VKAPI_ATTR void VKAPI_CALL vk_cmd_enqueue_CmdPushDescriptorSetKHR(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t set, uint32_t descriptorWriteCount, const VkWriteDescriptorSet *pDescriptorWrites) { VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer); struct vk_cmd_push_descriptor_set_khr *pds; struct vk_cmd_queue_entry *cmd = vk_zalloc(cmd_buffer->cmd_queue.alloc, sizeof(*cmd), 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); if (!cmd) return; pds = &cmd->u.push_descriptor_set_khr; cmd->type = VK_CMD_PUSH_DESCRIPTOR_SET_KHR; list_addtail(&cmd->cmd_link, &cmd_buffer->cmd_queue.cmds); pds->pipeline_bind_point = pipelineBindPoint; pds->layout = layout; pds->set = set; pds->descriptor_write_count = descriptorWriteCount; if (pDescriptorWrites) { pds->descriptor_writes = vk_zalloc(cmd_buffer->cmd_queue.alloc, sizeof(*pds->descriptor_writes) * descriptorWriteCount, 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); memcpy(pds->descriptor_writes, pDescriptorWrites, sizeof(*pds->descriptor_writes) * descriptorWriteCount); for (unsigned i = 0; i < descriptorWriteCount; i++) { switch (pds->descriptor_writes[i].descriptorType) { case VK_DESCRIPTOR_TYPE_SAMPLER: case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: pds->descriptor_writes[i].pImageInfo = vk_zalloc(cmd_buffer->cmd_queue.alloc, sizeof(VkDescriptorImageInfo) * pds->descriptor_writes[i].descriptorCount, 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); memcpy((VkDescriptorImageInfo *)pds->descriptor_writes[i].pImageInfo, pDescriptorWrites[i].pImageInfo, sizeof(VkDescriptorImageInfo) * pds->descriptor_writes[i].descriptorCount); break; case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: pds->descriptor_writes[i].pTexelBufferView = vk_zalloc(cmd_buffer->cmd_queue.alloc, sizeof(VkBufferView) * pds->descriptor_writes[i].descriptorCount, 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); memcpy((VkBufferView *)pds->descriptor_writes[i].pTexelBufferView, pDescriptorWrites[i].pTexelBufferView, sizeof(VkBufferView) * pds->descriptor_writes[i].descriptorCount); break; case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: default: pds->descriptor_writes[i].pBufferInfo = vk_zalloc(cmd_buffer->cmd_queue.alloc, sizeof(VkDescriptorBufferInfo) * pds->descriptor_writes[i].descriptorCount, 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); memcpy((VkDescriptorBufferInfo *)pds->descriptor_writes[i].pBufferInfo, pDescriptorWrites[i].pBufferInfo, sizeof(VkDescriptorBufferInfo) * pds->descriptor_writes[i].descriptorCount); break; } } } } static void unref_pipeline_layout(struct vk_cmd_queue *queue, struct vk_cmd_queue_entry *cmd) { struct vk_command_buffer *cmd_buffer = container_of(queue, struct vk_command_buffer, cmd_queue); VK_FROM_HANDLE(vk_pipeline_layout, layout, cmd->u.bind_descriptor_sets.layout); assert(cmd->type == VK_CMD_BIND_DESCRIPTOR_SETS); vk_pipeline_layout_unref(cmd_buffer->base.device, layout); } VKAPI_ATTR void VKAPI_CALL vk_cmd_enqueue_CmdBindDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t firstSet, uint32_t descriptorSetCount, const VkDescriptorSet* pDescriptorSets, uint32_t dynamicOffsetCount, const uint32_t *pDynamicOffsets) { VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer); struct vk_cmd_queue_entry *cmd = vk_zalloc(cmd_buffer->cmd_queue.alloc, sizeof(*cmd), 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); if (!cmd) return; cmd->type = VK_CMD_BIND_DESCRIPTOR_SETS; list_addtail(&cmd->cmd_link, &cmd_buffer->cmd_queue.cmds); /* We need to hold a reference to the descriptor set as long as this * command is in the queue. Otherwise, it may get deleted out from under * us before the command is replayed. */ vk_pipeline_layout_ref(vk_pipeline_layout_from_handle(layout)); cmd->u.bind_descriptor_sets.layout = layout; cmd->driver_free_cb = unref_pipeline_layout; cmd->u.bind_descriptor_sets.pipeline_bind_point = pipelineBindPoint; cmd->u.bind_descriptor_sets.first_set = firstSet; cmd->u.bind_descriptor_sets.descriptor_set_count = descriptorSetCount; if (pDescriptorSets) { cmd->u.bind_descriptor_sets.descriptor_sets = vk_zalloc(cmd_buffer->cmd_queue.alloc, sizeof(*cmd->u.bind_descriptor_sets.descriptor_sets) * descriptorSetCount, 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); memcpy(cmd->u.bind_descriptor_sets.descriptor_sets, pDescriptorSets, sizeof(*cmd->u.bind_descriptor_sets.descriptor_sets) * descriptorSetCount); } cmd->u.bind_descriptor_sets.dynamic_offset_count = dynamicOffsetCount; if (pDynamicOffsets) { cmd->u.bind_descriptor_sets.dynamic_offsets = vk_zalloc(cmd_buffer->cmd_queue.alloc, sizeof(*cmd->u.bind_descriptor_sets.dynamic_offsets) * dynamicOffsetCount, 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); memcpy(cmd->u.bind_descriptor_sets.dynamic_offsets, pDynamicOffsets, sizeof(*cmd->u.bind_descriptor_sets.dynamic_offsets) * dynamicOffsetCount); } }