• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2024 Valve 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_alloc.h"
25 #include "vk_device.h"
26 #include "vk_device_generated_commands.h"
27 #include "vk_log.h"
28 #include "vk_util.h"
29 
30 #include "util/compiler.h"
31 
32 void *
vk_indirect_command_layout_create(struct vk_device * device,const VkIndirectCommandsLayoutCreateInfoEXT * pCreateInfo,const VkAllocationCallbacks * pAllocator,size_t struct_size)33 vk_indirect_command_layout_create(struct vk_device *device,
34                                   const VkIndirectCommandsLayoutCreateInfoEXT* pCreateInfo,
35                                   const VkAllocationCallbacks*                 pAllocator,
36                                   size_t struct_size)
37 {
38    struct vk_indirect_command_layout *elayout;
39    uint32_t n_pc_layouts = 0, n_vb_layouts = 0;
40 
41    for (unsigned i = 0; i < pCreateInfo->tokenCount; i++) {
42       const VkIndirectCommandsLayoutTokenEXT *token = &pCreateInfo->pTokens[i];
43       switch (token->type) {
44       case VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_EXT:
45          n_pc_layouts++;
46          break;
47       case VK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_EXT:
48          n_vb_layouts++;
49          break;
50       default:
51          break;
52       }
53    }
54 
55    VK_MULTIALLOC(ma);
56    vk_multialloc_add_size_align(&ma, (void **)&elayout, struct_size, 8);
57    VK_MULTIALLOC_DECL(&ma, struct vk_indirect_command_push_constant_layout, pc_layouts, n_pc_layouts);
58    VK_MULTIALLOC_DECL(&ma, struct vk_indirect_command_vertex_layout, vb_layouts, n_vb_layouts);
59    elayout = vk_multialloc_zalloc2(&ma, &device->alloc, pAllocator,
60                                    VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
61    if (!elayout)
62       return NULL;
63 
64    vk_object_base_init(device, &elayout->base, VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_EXT);
65 
66    elayout->pc_layouts = pc_layouts;
67    elayout->vb_layouts = vb_layouts;
68 
69    for (unsigned i = 0; i < pCreateInfo->tokenCount; i++) {
70       const VkIndirectCommandsLayoutTokenEXT *token = &pCreateInfo->pTokens[i];
71       switch (token->type) {
72       case VK_INDIRECT_COMMANDS_TOKEN_TYPE_EXECUTION_SET_EXT:
73          elayout->is_shaders = token->data.pExecutionSet->type == VK_INDIRECT_EXECUTION_SET_INFO_TYPE_SHADER_OBJECTS_EXT;
74          elayout->ies_src_offset_B = token->offset;
75          elayout->dgc_info |= BITFIELD_BIT(MESA_VK_DGC_IES);
76          break;
77       case VK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_EXT:
78          assert(token->data.pVertexBuffer->vertexBindingUnit < 32);
79          elayout->vertex_bindings |= BITFIELD_BIT(token->data.pVertexBuffer->vertexBindingUnit);
80          elayout->dgc_info |= BITFIELD_BIT(MESA_VK_DGC_VB);
81          vb_layouts[elayout->n_vb_layouts++] = (struct vk_indirect_command_vertex_layout) {
82             .binding      = token->data.pVertexBuffer->vertexBindingUnit,
83             .src_offset_B = token->offset,
84          };
85          break;
86       case VK_INDIRECT_COMMANDS_TOKEN_TYPE_INDEX_BUFFER_EXT:
87          elayout->index_mode_is_dx = token->data.pIndexBuffer->mode == VK_INDIRECT_COMMANDS_INPUT_MODE_DXGI_INDEX_BUFFER_EXT;
88          elayout->index_src_offset_B = token->offset;
89          elayout->dgc_info |= BITFIELD_BIT(MESA_VK_DGC_IB);
90          break;
91       case VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_EXT:
92          elayout->dgc_info |= BITFIELD_BIT(MESA_VK_DGC_PC);
93          pc_layouts[elayout->n_pc_layouts++] = (struct vk_indirect_command_push_constant_layout) {
94             .stages       = token->data.pPushConstant->updateRange.stageFlags,
95             .dst_offset_B = token->data.pPushConstant->updateRange.offset,
96             .src_offset_B = token->offset,
97             .size_B       = token->data.pPushConstant->updateRange.size,
98          };
99          break;
100       case VK_INDIRECT_COMMANDS_TOKEN_TYPE_SEQUENCE_INDEX_EXT:
101          assert(token->data.pPushConstant->updateRange.size == 4);
102          elayout->dgc_info |= BITFIELD_BIT(MESA_VK_DGC_SI);
103          elayout->si_layout = (struct vk_indirect_command_push_constant_layout) {
104             .stages       = token->data.pPushConstant->updateRange.stageFlags,
105             .dst_offset_B = token->data.pPushConstant->updateRange.offset,
106             .src_offset_B = token->offset,
107             .size_B       = token->data.pPushConstant->updateRange.size,
108          };
109          break;
110       case VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_COUNT_EXT:
111          elayout->draw_count = true;
112          FALLTHROUGH;
113       case VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_EXT:
114          elayout->dgc_info |= BITFIELD_BIT(MESA_VK_DGC_DRAW);
115          elayout->draw_src_offset_B = token->offset;
116          break;
117       case VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_COUNT_EXT:
118          elayout->draw_count = true;
119          FALLTHROUGH;
120       case VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_EXT:
121          elayout->dgc_info |= BITFIELD_BIT(MESA_VK_DGC_DRAW_INDEXED);
122          elayout->draw_src_offset_B = token->offset;
123          break;
124       case VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_MESH_TASKS_COUNT_NV_EXT:
125       case VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_MESH_TASKS_COUNT_EXT:
126          elayout->draw_count = true;
127          FALLTHROUGH;
128       case VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_MESH_TASKS_NV_EXT:
129       case VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_MESH_TASKS_EXT:
130          elayout->dgc_info |= BITFIELD_BIT(MESA_VK_DGC_DRAW_MESH);
131          elayout->draw_src_offset_B = token->offset;
132          break;
133       case VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_EXT:
134          elayout->dgc_info |= BITFIELD_BIT(MESA_VK_DGC_DISPATCH);
135          elayout->dispatch_src_offset_B = token->offset;
136          break;
137       case VK_INDIRECT_COMMANDS_TOKEN_TYPE_TRACE_RAYS2_EXT:
138          elayout->dgc_info |= BITFIELD_BIT(MESA_VK_DGC_RT);
139          elayout->dispatch_src_offset_B = token->offset;
140          break;
141       default: break;
142       }
143    }
144 
145    if (elayout->dgc_info & (BITFIELD_BIT(MESA_VK_DGC_PC) | BITFIELD_BIT(MESA_VK_DGC_SI))) {
146       if (pCreateInfo->pipelineLayout) {
147          elayout->layout = pCreateInfo->pipelineLayout;
148       } else {
149          const struct vk_device_dispatch_table *disp = &device->dispatch_table;
150          assert(device->enabled_features.dynamicGeneratedPipelineLayout);
151          const VkPipelineLayoutCreateInfo *plci = vk_find_struct_const(pCreateInfo->pNext, PIPELINE_LAYOUT_CREATE_INFO);
152          assert(plci);
153          disp->CreatePipelineLayout(vk_device_to_handle(device), plci, NULL, &elayout->layout);
154          elayout->delete_layout = true;
155       }
156    }
157    elayout->stages = pCreateInfo->shaderStages;
158    elayout->usage = pCreateInfo->flags;
159    elayout->stride = pCreateInfo->indirectStride;
160    elayout->token_count = pCreateInfo->tokenCount;
161 
162    return elayout;
163 }
164 
165 void
vk_indirect_command_layout_destroy(struct vk_device * device,const VkAllocationCallbacks * pAllocator,struct vk_indirect_command_layout * elayout)166 vk_indirect_command_layout_destroy(struct vk_device *device,
167                                    const VkAllocationCallbacks *pAllocator,
168                                    struct vk_indirect_command_layout *elayout)
169 {
170    if (elayout->delete_layout) {
171       const struct vk_device_dispatch_table *disp = &device->dispatch_table;
172       assert(device->enabled_features.dynamicGeneratedPipelineLayout);
173       disp->DestroyPipelineLayout(vk_device_to_handle(device), elayout->layout, NULL);
174    }
175    vk_object_base_finish(&elayout->base);
176    vk_free2(&device->alloc, pAllocator, elayout);
177 }
178