xref: /aosp_15_r20/external/mesa3d/src/microsoft/vulkan/dzn_descriptor_set.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © Microsoft 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 "dzn_private.h"
25 
26 #include "vk_alloc.h"
27 #include "vk_descriptors.h"
28 #include "vk_util.h"
29 
30 #include "dxil_spirv_nir.h"
31 
32 #include "util/mesa-sha1.h"
33 
34 static uint32_t
translate_desc_stages(VkShaderStageFlags in)35 translate_desc_stages(VkShaderStageFlags in)
36 {
37    if (in == VK_SHADER_STAGE_ALL)
38       in = VK_SHADER_STAGE_ALL_GRAPHICS | VK_SHADER_STAGE_COMPUTE_BIT;
39 
40    uint32_t out = 0;
41 
42    u_foreach_bit(s, in)
43       out |= BITFIELD_BIT(vk_to_mesa_shader_stage(BITFIELD_BIT(s)));
44 
45    return out;
46 }
47 
48 static D3D12_SHADER_VISIBILITY
translate_desc_visibility(VkShaderStageFlags in)49 translate_desc_visibility(VkShaderStageFlags in)
50 {
51    switch (in) {
52    case VK_SHADER_STAGE_VERTEX_BIT: return D3D12_SHADER_VISIBILITY_VERTEX;
53    case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: return D3D12_SHADER_VISIBILITY_HULL;
54    case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: return D3D12_SHADER_VISIBILITY_DOMAIN;
55    case VK_SHADER_STAGE_GEOMETRY_BIT: return D3D12_SHADER_VISIBILITY_GEOMETRY;
56    case VK_SHADER_STAGE_FRAGMENT_BIT: return D3D12_SHADER_VISIBILITY_PIXEL;
57    default: return D3D12_SHADER_VISIBILITY_ALL;
58    }
59 }
60 
61 static D3D12_DESCRIPTOR_RANGE_TYPE
desc_type_to_range_type(VkDescriptorType in,bool writeable)62 desc_type_to_range_type(VkDescriptorType in, bool writeable)
63 {
64    switch (in) {
65    case VK_DESCRIPTOR_TYPE_SAMPLER:
66       return D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER;
67 
68    case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
69    case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
70    case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
71       return D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
72 
73    case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
74    case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
75       return D3D12_DESCRIPTOR_RANGE_TYPE_CBV;
76 
77    case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
78    case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
79    case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
80    case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
81       return writeable ? D3D12_DESCRIPTOR_RANGE_TYPE_UAV : D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
82    default:
83       unreachable("Unsupported desc type");
84    }
85 }
86 
87 static bool
is_dynamic_desc_type(VkDescriptorType desc_type)88 is_dynamic_desc_type(VkDescriptorType desc_type)
89 {
90    return (desc_type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||
91            desc_type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC);
92 }
93 
94 static bool
is_buffer_desc_type_without_view(VkDescriptorType desc_type)95 is_buffer_desc_type_without_view(VkDescriptorType desc_type)
96 {
97    return (desc_type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ||
98            desc_type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
99 }
100 
101 static bool
dzn_descriptor_type_depends_on_shader_usage(VkDescriptorType type,bool bindless)102 dzn_descriptor_type_depends_on_shader_usage(VkDescriptorType type, bool bindless)
103 {
104    if (bindless)
105       return false;
106    return type == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER ||
107           type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE ||
108           type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER ||
109           type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
110 }
111 
112 static inline bool
dzn_desc_type_has_sampler(VkDescriptorType type)113 dzn_desc_type_has_sampler(VkDescriptorType type)
114 {
115    return type == VK_DESCRIPTOR_TYPE_SAMPLER ||
116           type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
117 }
118 
119 static uint32_t
num_descs_for_type(VkDescriptorType type,bool static_sampler,bool bindless)120 num_descs_for_type(VkDescriptorType type, bool static_sampler, bool bindless)
121 {
122    if (bindless)
123       return 1;
124 
125    unsigned num_descs = 1;
126 
127    /* Some type map to an SRV or UAV depending on how the shaders is using the
128     * resource (NONWRITEABLE flag set or not), in that case we need to reserve
129     * slots for both the UAV and SRV descs.
130     */
131    if (dzn_descriptor_type_depends_on_shader_usage(type, false))
132       num_descs++;
133 
134    /* There's no combined SRV+SAMPLER type in d3d12, we need an descriptor
135     * for the sampler.
136     */
137    if (type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
138       num_descs++;
139 
140    /* Don't count immutable samplers, they have their own descriptor. */
141    if (static_sampler && dzn_desc_type_has_sampler(type))
142       num_descs--;
143 
144    return num_descs;
145 }
146 
147 static VkResult
dzn_descriptor_set_layout_create(struct dzn_device * device,const VkDescriptorSetLayoutCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDescriptorSetLayout * out)148 dzn_descriptor_set_layout_create(struct dzn_device *device,
149                                  const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
150                                  const VkAllocationCallbacks *pAllocator,
151                                  VkDescriptorSetLayout *out)
152 {
153    const VkDescriptorSetLayoutBinding *bindings = pCreateInfo->pBindings;
154    uint32_t binding_count = 0, static_sampler_count = 0, total_ranges = 0;
155    uint32_t dynamic_ranges_offset = 0, immutable_sampler_count = 0;
156    uint32_t dynamic_buffer_count = 0;
157    uint32_t range_count[MAX_SHADER_VISIBILITIES][NUM_POOL_TYPES] = { 0 };
158 
159    const VkDescriptorSetLayoutBindingFlagsCreateInfo *binding_flags =
160       vk_find_struct_const(pCreateInfo->pNext, DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO);
161    bool has_variable_size = false;
162 
163    for (uint32_t i = 0; i < pCreateInfo->bindingCount; i++) {
164       binding_count = MAX2(binding_count, bindings[i].binding + 1);
165 
166       if (!bindings[i].descriptorCount)
167          continue;
168 
169       D3D12_SHADER_VISIBILITY visibility = device->bindless ?
170          D3D12_SHADER_VISIBILITY_ALL :
171          translate_desc_visibility(bindings[i].stageFlags);
172       VkDescriptorType desc_type = bindings[i].descriptorType;
173       bool has_sampler = dzn_desc_type_has_sampler(desc_type);
174 
175       /* From the Vulkan 1.1.97 spec for VkDescriptorSetLayoutBinding:
176        *
177        *    "If descriptorType specifies a VK_DESCRIPTOR_TYPE_SAMPLER or
178        *    VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER type descriptor, then
179        *    pImmutableSamplers can be used to initialize a set of immutable
180        *    samplers. [...]  If descriptorType is not one of these descriptor
181        *    types, then pImmutableSamplers is ignored.
182        *
183        * We need to be careful here and only parse pImmutableSamplers if we
184        * have one of the right descriptor types.
185        */
186       bool immutable_samplers =
187          has_sampler &&
188          bindings[i].pImmutableSamplers != NULL;
189       bool static_sampler = false;
190 
191       if (device->support_static_samplers &&
192           immutable_samplers && bindings[i].descriptorCount == 1) {
193          VK_FROM_HANDLE(dzn_sampler, sampler, bindings[i].pImmutableSamplers[0]);
194 
195          if (sampler->static_border_color != -1)
196             static_sampler = true;
197       }
198 
199       if (static_sampler) {
200          static_sampler_count += bindings[i].descriptorCount;
201       } else if (has_sampler) {
202          unsigned type = device->bindless ? D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV : D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER;
203          range_count[visibility][type]++;
204          total_ranges++;
205 
206          if (immutable_samplers)
207             immutable_sampler_count += bindings[i].descriptorCount;
208       }
209 
210       if (desc_type != VK_DESCRIPTOR_TYPE_SAMPLER) {
211          range_count[visibility][D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV]++;
212          total_ranges++;
213 
214          if (dzn_descriptor_type_depends_on_shader_usage(desc_type, device->bindless)) {
215             range_count[visibility][D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV]++;
216             total_ranges++;
217          }
218 
219          uint32_t factor =
220             dzn_descriptor_type_depends_on_shader_usage(desc_type, device->bindless) ? 2 : 1;
221          if (is_dynamic_desc_type(desc_type))
222             dynamic_buffer_count += bindings[i].descriptorCount * factor;
223          else
224             dynamic_ranges_offset += bindings[i].descriptorCount * factor;
225       }
226 
227       if (binding_flags && binding_flags->bindingCount &&
228           (binding_flags->pBindingFlags[i] & VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT))
229          has_variable_size = true;
230    }
231 
232    assert(!has_variable_size || device->bindless);
233 
234    /* We need to allocate decriptor set layouts off the device allocator
235     * with DEVICE scope because they are reference counted and may not be
236     * destroyed when vkDestroyDescriptorSetLayout is called.
237     */
238    VK_MULTIALLOC(ma);
239    VK_MULTIALLOC_DECL(&ma, struct dzn_descriptor_set_layout, set_layout, 1);
240    VK_MULTIALLOC_DECL(&ma, D3D12_DESCRIPTOR_RANGE1,
241                       ranges, total_ranges);
242    VK_MULTIALLOC_DECL(&ma, D3D12_STATIC_SAMPLER_DESC1, static_samplers,
243                       static_sampler_count);
244    VK_MULTIALLOC_DECL(&ma, const struct dzn_sampler *, immutable_samplers,
245                       immutable_sampler_count);
246    VK_MULTIALLOC_DECL(&ma, struct dzn_descriptor_set_layout_binding, binfos,
247                       binding_count);
248 
249    if (!vk_descriptor_set_layout_multizalloc(&device->vk, &ma))
250       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
251 
252    set_layout->static_samplers = static_samplers;
253    set_layout->static_sampler_count = static_sampler_count;
254    set_layout->immutable_samplers = immutable_samplers;
255    set_layout->immutable_sampler_count = immutable_sampler_count;
256    set_layout->bindings = binfos;
257    set_layout->binding_count = binding_count;
258    set_layout->dynamic_buffers.range_offset = dynamic_ranges_offset;
259    set_layout->buffer_count = dynamic_buffer_count;
260 
261    for (uint32_t i = 0; i < MAX_SHADER_VISIBILITIES; i++) {
262       dzn_foreach_pool_type (type) {
263          if (range_count[i][type]) {
264             set_layout->ranges[i][type] = ranges;
265             set_layout->range_count[i][type] = range_count[i][type];
266             ranges += range_count[i][type];
267          }
268       }
269    }
270 
271    VkDescriptorSetLayoutBinding *ordered_bindings;
272    VkResult ret =
273       vk_create_sorted_bindings(pCreateInfo->pBindings,
274                                 pCreateInfo->bindingCount,
275                                 &ordered_bindings);
276    if (ret != VK_SUCCESS) {
277       vk_descriptor_set_layout_destroy(&device->vk, &set_layout->vk);
278       return ret;
279    }
280 
281    assert(binding_count ==
282           (pCreateInfo->bindingCount ?
283            (ordered_bindings[pCreateInfo->bindingCount - 1].binding + 1) : 0));
284 
285    uint32_t range_idx[MAX_SHADER_VISIBILITIES][NUM_POOL_TYPES] = { 0 };
286    uint32_t static_sampler_idx = 0, immutable_sampler_idx = 0;
287    uint32_t dynamic_buffer_idx = 0;
288    uint32_t base_register = 0;
289 
290    for (uint32_t i = 0; i < binding_count; i++) {
291       binfos[i].immutable_sampler_idx = ~0;
292       binfos[i].buffer_idx = ~0;
293       dzn_foreach_pool_type (type)
294          binfos[i].range_idx[type] = ~0;
295    }
296 
297    for (uint32_t i = 0; i < pCreateInfo->bindingCount; i++) {
298       VkDescriptorType desc_type = ordered_bindings[i].descriptorType;
299       uint32_t binding = ordered_bindings[i].binding;
300       uint32_t desc_count = ordered_bindings[i].descriptorCount;
301       bool has_sampler = dzn_desc_type_has_sampler(desc_type);
302       bool has_immutable_samplers =
303          has_sampler &&
304          ordered_bindings[i].pImmutableSamplers != NULL;
305       bool has_static_sampler = device->support_static_samplers &&
306          has_immutable_samplers && desc_count == 1;
307       bool is_dynamic = is_dynamic_desc_type(desc_type);
308 
309       D3D12_SHADER_VISIBILITY visibility = device->bindless ?
310          D3D12_SHADER_VISIBILITY_ALL :
311          translate_desc_visibility(ordered_bindings[i].stageFlags);
312       binfos[binding].type = desc_type;
313       binfos[binding].stages =
314          translate_desc_stages(ordered_bindings[i].stageFlags);
315       set_layout->stages |= binfos[binding].stages;
316       binfos[binding].visibility = visibility;
317       /* Only the last binding can have variable size */
318       if (binding == binding_count - 1)
319          binfos[binding].variable_size = has_variable_size;
320       if (is_dynamic && device->bindless) {
321          /* Assign these into a separate 0->N space */
322          binfos[binding].base_shader_register = dynamic_buffer_idx;
323       } else {
324          binfos[binding].base_shader_register = base_register;
325          assert(base_register + desc_count >= base_register);
326          base_register += desc_count;
327       }
328 
329       if (has_static_sampler) {
330          VK_FROM_HANDLE(dzn_sampler, sampler, ordered_bindings[i].pImmutableSamplers[0]);
331 
332          /* Not all border colors are supported. */
333          if (sampler->static_border_color != -1) {
334             D3D12_STATIC_SAMPLER_DESC1 *desc = (D3D12_STATIC_SAMPLER_DESC1 *)
335                &static_samplers[static_sampler_idx];
336 
337             desc->Filter = sampler->desc.Filter;
338             desc->AddressU = sampler->desc.AddressU;
339             desc->AddressV = sampler->desc.AddressV;
340             desc->AddressW = sampler->desc.AddressW;
341             desc->MipLODBias = sampler->desc.MipLODBias;
342             desc->MaxAnisotropy = sampler->desc.MaxAnisotropy;
343             desc->ComparisonFunc = sampler->desc.ComparisonFunc;
344             desc->BorderColor = sampler->static_border_color;
345             desc->MinLOD = sampler->desc.MinLOD;
346             desc->MaxLOD = sampler->desc.MaxLOD;
347             desc->ShaderRegister = binfos[binding].base_shader_register;
348             desc->ShaderVisibility = translate_desc_visibility(ordered_bindings[i].stageFlags);
349             desc->Flags = sampler->desc.Flags;
350             if (device->bindless && desc_type == VK_DESCRIPTOR_TYPE_SAMPLER) {
351                /* Avoid using space in the descriptor set buffer for pure static samplers. The meaning
352                 * of base register index is different for them - it's just an ID to map to the root
353                 * signature, as opposed to all other bindings where it's an offset into the buffer. */
354                binfos[binding].base_shader_register = desc->ShaderRegister = static_sampler_idx;
355                base_register--;
356             }
357             static_sampler_idx++;
358          } else {
359             has_static_sampler = false;
360          }
361       }
362 
363       if (has_static_sampler) {
364          binfos[binding].immutable_sampler_idx = STATIC_SAMPLER_TAG;
365       } else if (has_immutable_samplers) {
366          binfos[binding].immutable_sampler_idx = immutable_sampler_idx;
367          for (uint32_t s = 0; s < desc_count; s++) {
368             VK_FROM_HANDLE(dzn_sampler, sampler, ordered_bindings[i].pImmutableSamplers[s]);
369 
370             immutable_samplers[immutable_sampler_idx++] = sampler;
371          }
372       }
373 
374       if (is_dynamic) {
375          binfos[binding].buffer_idx = dynamic_buffer_idx;
376          for (uint32_t d = 0; d < desc_count; d++)
377             set_layout->dynamic_buffers.bindings[dynamic_buffer_idx + d] = binding;
378          dynamic_buffer_idx += desc_count;
379          assert(dynamic_buffer_idx <= MAX_DYNAMIC_BUFFERS);
380       } else if (is_buffer_desc_type_without_view(desc_type)) {
381          binfos[binding].buffer_idx = set_layout->buffer_count;
382          set_layout->buffer_count += desc_count;
383       }
384 
385       if (!ordered_bindings[i].descriptorCount)
386          continue;
387 
388       unsigned num_descs =
389          num_descs_for_type(desc_type, has_static_sampler, device->bindless);
390       if (!num_descs) continue;
391 
392       assert(visibility < ARRAY_SIZE(set_layout->ranges));
393 
394       bool has_range[NUM_POOL_TYPES] = { 0 };
395       has_range[D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER] =
396          has_sampler && !has_static_sampler && !device->bindless;
397       has_range[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV] =
398          desc_type != VK_DESCRIPTOR_TYPE_SAMPLER || (device->bindless && !has_static_sampler);
399 
400       dzn_foreach_pool_type (type) {
401          if (!has_range[type]) continue;
402 
403          uint32_t idx = range_idx[visibility][type]++;
404          assert(idx < range_count[visibility][type]);
405 
406          binfos[binding].range_idx[type] = idx;
407          D3D12_DESCRIPTOR_RANGE1 *range = (D3D12_DESCRIPTOR_RANGE1 *)
408             &set_layout->ranges[visibility][type][idx];
409          VkDescriptorType range_type = desc_type;
410          if (desc_type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) {
411             range_type = type == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER ?
412                          VK_DESCRIPTOR_TYPE_SAMPLER :
413                          VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
414          }
415          range->RangeType = desc_type_to_range_type(range_type, true);
416          range->NumDescriptors = desc_count;
417          range->BaseShaderRegister = binfos[binding].base_shader_register;
418          range->Flags = type == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER ?
419             D3D12_DESCRIPTOR_RANGE_FLAG_NONE :
420             D3D12_DESCRIPTOR_RANGE_FLAG_DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS;
421          if (is_dynamic) {
422             range->OffsetInDescriptorsFromTableStart =
423                set_layout->dynamic_buffers.range_offset +
424                set_layout->dynamic_buffers.desc_count;
425             set_layout->dynamic_buffers.count += range->NumDescriptors;
426             set_layout->dynamic_buffers.desc_count += range->NumDescriptors;
427          } else {
428             range->OffsetInDescriptorsFromTableStart = set_layout->range_desc_count[type];
429             if (!binfos[binding].variable_size)
430                set_layout->range_desc_count[type] += range->NumDescriptors;
431          }
432 
433          if (!dzn_descriptor_type_depends_on_shader_usage(desc_type, device->bindless))
434             continue;
435 
436          assert(idx + 1 < range_count[visibility][type]);
437          range_idx[visibility][type]++;
438          range[1] = range[0];
439          range++;
440          range->RangeType = desc_type_to_range_type(range_type, false);
441          if (is_dynamic) {
442             range->OffsetInDescriptorsFromTableStart =
443                set_layout->dynamic_buffers.range_offset +
444                set_layout->dynamic_buffers.desc_count;
445             set_layout->dynamic_buffers.desc_count += range->NumDescriptors;
446          } else {
447             range->OffsetInDescriptorsFromTableStart = set_layout->range_desc_count[type];
448             set_layout->range_desc_count[type] += range->NumDescriptors;
449          }
450       }
451    }
452 
453    free(ordered_bindings);
454 
455    *out = dzn_descriptor_set_layout_to_handle(set_layout);
456    return VK_SUCCESS;
457 }
458 
459 static uint32_t
dzn_descriptor_set_layout_get_heap_offset(const struct dzn_descriptor_set_layout * layout,uint32_t b,D3D12_DESCRIPTOR_HEAP_TYPE type,bool alt,bool bindless)460 dzn_descriptor_set_layout_get_heap_offset(const struct dzn_descriptor_set_layout *layout,
461                                           uint32_t b,
462                                           D3D12_DESCRIPTOR_HEAP_TYPE type,
463                                           bool alt,
464                                           bool bindless)
465 {
466    assert(b < layout->binding_count);
467    D3D12_SHADER_VISIBILITY visibility = layout->bindings[b].visibility;
468    assert(visibility < ARRAY_SIZE(layout->ranges));
469    assert(type < NUM_POOL_TYPES);
470 
471    if (bindless)
472       type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
473 
474    uint32_t range_idx = layout->bindings[b].range_idx[type];
475 
476    if (range_idx == ~0)
477       return ~0;
478 
479    if (alt &&
480        !dzn_descriptor_type_depends_on_shader_usage(layout->bindings[b].type, bindless))
481       return ~0;
482 
483    if (alt)
484       range_idx++;
485 
486    assert(range_idx < layout->range_count[visibility][type]);
487    return layout->ranges[visibility][type][range_idx].OffsetInDescriptorsFromTableStart;
488 }
489 
490 static uint32_t
dzn_descriptor_set_layout_get_desc_count(const struct dzn_descriptor_set_layout * layout,uint32_t b)491 dzn_descriptor_set_layout_get_desc_count(const struct dzn_descriptor_set_layout *layout,
492                                          uint32_t b)
493 {
494    D3D12_SHADER_VISIBILITY visibility = layout->bindings[b].visibility;
495    assert(visibility < ARRAY_SIZE(layout->ranges));
496 
497    dzn_foreach_pool_type (type) {
498       uint32_t range_idx = layout->bindings[b].range_idx[type];
499       assert(range_idx == ~0 || range_idx < layout->range_count[visibility][type]);
500 
501       if (range_idx != ~0)
502          return layout->ranges[visibility][type][range_idx].NumDescriptors;
503    }
504 
505    return 0;
506 }
507 
508 VKAPI_ATTR VkResult VKAPI_CALL
dzn_CreateDescriptorSetLayout(VkDevice device,const VkDescriptorSetLayoutCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDescriptorSetLayout * pSetLayout)509 dzn_CreateDescriptorSetLayout(VkDevice device,
510                               const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
511                               const VkAllocationCallbacks *pAllocator,
512                               VkDescriptorSetLayout *pSetLayout)
513 {
514    return dzn_descriptor_set_layout_create(dzn_device_from_handle(device),
515                                            pCreateInfo, pAllocator, pSetLayout);
516 }
517 
518 VKAPI_ATTR void VKAPI_CALL
dzn_GetDescriptorSetLayoutSupport(VkDevice _device,const VkDescriptorSetLayoutCreateInfo * pCreateInfo,VkDescriptorSetLayoutSupport * pSupport)519 dzn_GetDescriptorSetLayoutSupport(VkDevice _device,
520                                   const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
521                                   VkDescriptorSetLayoutSupport *pSupport)
522 {
523    VK_FROM_HANDLE(dzn_device, device, _device);
524    const VkDescriptorSetLayoutBinding *bindings = pCreateInfo->pBindings;
525    uint32_t sampler_count = 0, other_desc_count = 0;
526 
527    const VkDescriptorSetLayoutBindingFlagsCreateInfo *binding_flags =
528       vk_find_struct_const(pCreateInfo->pNext, DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO);
529    VkDescriptorSetVariableDescriptorCountLayoutSupport *variable_count =
530       vk_find_struct(pSupport->pNext, DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT);
531    if (variable_count)
532       variable_count->maxVariableDescriptorCount = 0;
533 
534    for (uint32_t i = 0; i < pCreateInfo->bindingCount; i++) {
535       VkDescriptorType desc_type = bindings[i].descriptorType;
536       bool has_sampler = dzn_desc_type_has_sampler(desc_type);
537       bool is_sampler = desc_type == VK_DESCRIPTOR_TYPE_SAMPLER;
538 
539       UINT upper_bound = MAX_DESCS_PER_CBV_SRV_UAV_HEAP - other_desc_count;
540       if (has_sampler) {
541          UINT sampler_upper_bound = MAX_DESCS_PER_SAMPLER_HEAP - sampler_count;
542          upper_bound = is_sampler ? sampler_upper_bound : MIN2(sampler_upper_bound, upper_bound);
543       }
544 
545       if (binding_flags && binding_flags->bindingCount &&
546           (binding_flags->pBindingFlags[i] & VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT))
547          variable_count->maxVariableDescriptorCount = device->bindless ? INT32_MAX : upper_bound;
548 
549       if (has_sampler)
550          sampler_count += bindings[i].descriptorCount;
551       if (!is_sampler)
552          other_desc_count += bindings[i].descriptorCount;
553       if (dzn_descriptor_type_depends_on_shader_usage(desc_type, device->bindless))
554          other_desc_count += bindings[i].descriptorCount;
555    }
556 
557    pSupport->supported = device->bindless ||
558       (sampler_count <= MAX_DESCS_PER_SAMPLER_HEAP &&
559        other_desc_count <= MAX_DESCS_PER_CBV_SRV_UAV_HEAP);
560 }
561 
562 static void
dzn_pipeline_layout_destroy(struct vk_device * vk_device,struct vk_pipeline_layout * vk_layout)563 dzn_pipeline_layout_destroy(struct vk_device *vk_device,
564                             struct vk_pipeline_layout *vk_layout)
565 {
566    struct dzn_pipeline_layout *layout =
567       container_of(vk_layout, struct dzn_pipeline_layout, vk);
568 
569    if (layout->root.sig)
570       ID3D12RootSignature_Release(layout->root.sig);
571 
572    vk_pipeline_layout_destroy(vk_device, &layout->vk);
573 }
574 
575 // Reserve two root parameters for the push constants and sysvals CBVs.
576 #define MAX_INTERNAL_ROOT_PARAMS 2
577 
578 // One root parameter for samplers and the other one for views, multiplied by
579 // the number of visibility combinations, plus the internal root parameters.
580 #define MAX_ROOT_PARAMS ((MAX_SHADER_VISIBILITIES * 2) + MAX_INTERNAL_ROOT_PARAMS)
581 
582 // Maximum number of DWORDS (32-bit words) that can be used for a root signature
583 #define MAX_ROOT_DWORDS 64
584 
585 static void
dzn_pipeline_layout_hash_stages(struct dzn_pipeline_layout * layout,const VkPipelineLayoutCreateInfo * info)586 dzn_pipeline_layout_hash_stages(struct dzn_pipeline_layout *layout,
587                                 const VkPipelineLayoutCreateInfo *info)
588 {
589    uint32_t stages = 0;
590    for (uint32_t stage = 0; stage < ARRAY_SIZE(layout->stages); stage++) {
591       for (uint32_t set = 0; set < info->setLayoutCount; set++) {
592          VK_FROM_HANDLE(dzn_descriptor_set_layout, set_layout, info->pSetLayouts[set]);
593 
594          stages |= set_layout->stages;
595       }
596    }
597 
598    for (uint32_t stage = 0; stage < ARRAY_SIZE(layout->stages); stage++) {
599       if (!(stages & BITFIELD_BIT(stage)))
600          continue;
601 
602       struct mesa_sha1 ctx;
603 
604       _mesa_sha1_init(&ctx);
605       for (uint32_t set = 0; set < info->setLayoutCount; set++) {
606          VK_FROM_HANDLE(dzn_descriptor_set_layout, set_layout, info->pSetLayouts[set]);
607          if (!(BITFIELD_BIT(stage) & set_layout->stages))
608             continue;
609 
610          for (uint32_t b = 0; b < set_layout->binding_count; b++) {
611             if (!(BITFIELD_BIT(stage) & set_layout->bindings[b].stages))
612                continue;
613 
614             _mesa_sha1_update(&ctx, &b, sizeof(b));
615             _mesa_sha1_update(&ctx, &set_layout->bindings[b].base_shader_register,
616                               sizeof(set_layout->bindings[b].base_shader_register));
617          }
618       }
619       _mesa_sha1_final(&ctx, layout->stages[stage].hash);
620    }
621 }
622 
623 static VkResult
dzn_pipeline_layout_create(struct dzn_device * device,const VkPipelineLayoutCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkPipelineLayout * out)624 dzn_pipeline_layout_create(struct dzn_device *device,
625                            const VkPipelineLayoutCreateInfo *pCreateInfo,
626                            const VkAllocationCallbacks *pAllocator,
627                            VkPipelineLayout *out)
628 {
629    struct dzn_physical_device *pdev = container_of(device->vk.physical, struct dzn_physical_device, vk);
630    uint32_t binding_count = 0;
631 
632    for (uint32_t s = 0; s < pCreateInfo->setLayoutCount; s++) {
633       VK_FROM_HANDLE(dzn_descriptor_set_layout, set_layout, pCreateInfo->pSetLayouts[s]);
634 
635       if (!set_layout)
636          continue;
637 
638       binding_count += set_layout->binding_count;
639    }
640 
641    VK_MULTIALLOC(ma);
642    VK_MULTIALLOC_DECL(&ma, struct dzn_pipeline_layout, layout, 1);
643    VK_MULTIALLOC_DECL(&ma, uint32_t, binding_translation, binding_count);
644    VK_MULTIALLOC_DECL(&ma, uint8_t, binding_class, binding_count);
645 
646    if (!vk_pipeline_layout_multizalloc(&device->vk, &ma, pCreateInfo))
647       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
648 
649    layout->vk.destroy = dzn_pipeline_layout_destroy;
650 
651    for (uint32_t s = 0; s < pCreateInfo->setLayoutCount; s++) {
652       VK_FROM_HANDLE(dzn_descriptor_set_layout, set_layout, pCreateInfo->pSetLayouts[s]);
653 
654       if (!set_layout || !set_layout->binding_count)
655          continue;
656 
657       layout->binding_translation[s].base_reg = binding_translation;
658       layout->binding_translation[s].binding_class = binding_class;
659       binding_translation += set_layout->binding_count;
660       binding_class += set_layout->binding_count;
661    }
662 
663    uint32_t range_count = 0, static_sampler_count = 0;
664    uint32_t dynamic_buffer_base = 0;
665 
666    layout->root.param_count = 0;
667    dzn_foreach_pool_type (type)
668       layout->desc_count[type] = 0;
669 
670    layout->set_count = pCreateInfo->setLayoutCount;
671    for (uint32_t j = 0; j < layout->set_count; j++) {
672       VK_FROM_HANDLE(dzn_descriptor_set_layout, set_layout, pCreateInfo->pSetLayouts[j]);
673       uint32_t *binding_trans = layout->binding_translation[j].base_reg;
674 
675       layout->sets[j].dynamic_buffer_count = set_layout->dynamic_buffers.count;
676       memcpy(layout->sets[j].range_desc_count, set_layout->range_desc_count,
677              sizeof(layout->sets[j].range_desc_count));
678       layout->binding_translation[j].binding_count = set_layout->binding_count;
679 
680       for (uint32_t b = 0; b < set_layout->binding_count; b++) {
681          binding_trans[b] = set_layout->bindings[b].base_shader_register;
682          if (is_dynamic_desc_type(set_layout->bindings[b].type)) {
683             layout->binding_translation[j].binding_class[b] = DZN_PIPELINE_BINDING_DYNAMIC_BUFFER;
684             if (device->bindless)
685                binding_trans[b] += dynamic_buffer_base;
686          } else if (dzn_desc_type_has_sampler(set_layout->bindings[b].type) &&
687                   set_layout->bindings[b].immutable_sampler_idx == STATIC_SAMPLER_TAG)
688             layout->binding_translation[j].binding_class[b] = DZN_PIPELINE_BINDING_STATIC_SAMPLER;
689          else
690             layout->binding_translation[j].binding_class[b] = DZN_PIPELINE_BINDING_NORMAL;
691       }
692 
693       static_sampler_count += set_layout->static_sampler_count;
694       dzn_foreach_pool_type (type) {
695          layout->sets[j].heap_offsets[type] = layout->desc_count[type];
696          layout->desc_count[type] += set_layout->range_desc_count[type];
697          for (uint32_t i = 0; i < MAX_SHADER_VISIBILITIES; i++)
698             range_count += set_layout->range_count[i][type];
699       }
700 
701       if (!device->bindless)
702          layout->desc_count[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV] += set_layout->dynamic_buffers.desc_count;
703 
704       dynamic_buffer_base += set_layout->dynamic_buffers.count;
705       for (uint32_t o = 0, elem = 0; o < set_layout->dynamic_buffers.count; o++, elem++) {
706          if (device->bindless) {
707             layout->sets[j].dynamic_buffer_heap_offsets[o].primary = layout->dynamic_buffer_count++;
708             layout->sets[j].dynamic_buffer_heap_offsets[o].alt = ~0;
709          } else {
710             uint32_t b = set_layout->dynamic_buffers.bindings[o];
711 
712             if (o > 0 && set_layout->dynamic_buffers.bindings[o - 1] != b)
713                elem = 0;
714 
715             uint32_t heap_offset =
716                dzn_descriptor_set_layout_get_heap_offset(set_layout, b, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
717                                                          false, false);
718             uint32_t alt_heap_offset =
719                dzn_descriptor_set_layout_get_heap_offset(set_layout, b, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
720                                                          true, false);
721 
722             layout->sets[j].dynamic_buffer_heap_offsets[o].primary = heap_offset != ~0 ? heap_offset + elem : ~0;
723             layout->sets[j].dynamic_buffer_heap_offsets[o].alt = alt_heap_offset != ~0 ? alt_heap_offset + elem : ~0;
724          }
725       }
726    }
727 
728    D3D12_DESCRIPTOR_RANGE1 *ranges =
729       vk_alloc2(&device->vk.alloc, pAllocator, sizeof(*ranges) * range_count, 8,
730                 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
731    if (range_count && !ranges) {
732       vk_pipeline_layout_unref(&device->vk, &layout->vk);
733       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
734    }
735 
736    static_assert(sizeof(D3D12_STATIC_SAMPLER_DESC1) > sizeof(D3D12_STATIC_SAMPLER_DESC),
737                  "Allocating larger array and re-using for smaller struct");
738    D3D12_STATIC_SAMPLER_DESC1 *static_sampler_descs =
739       vk_alloc2(&device->vk.alloc, pAllocator,
740                 sizeof(*static_sampler_descs) * static_sampler_count, 8,
741                 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
742    if (static_sampler_count && !static_sampler_descs) {
743       vk_free2(&device->vk.alloc, pAllocator, ranges);
744       vk_pipeline_layout_unref(&device->vk, &layout->vk);
745       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
746    }
747 
748 
749    D3D12_ROOT_PARAMETER1 root_params[MAX_ROOT_PARAMS] = { 0 };
750    D3D12_DESCRIPTOR_RANGE1 *range_ptr = ranges;
751    D3D12_ROOT_PARAMETER1 *root_param;
752    ASSERTED uint32_t root_dwords = 0;
753 
754    if (device->bindless) {
755       for (uint32_t j = 0; j < pCreateInfo->setLayoutCount; j++) {
756          root_param = &root_params[layout->root.param_count++];
757          root_param->ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV;
758          root_param->Descriptor.RegisterSpace = 0;
759          root_param->Descriptor.ShaderRegister = j;
760          root_param->Descriptor.Flags = D3D12_ROOT_DESCRIPTOR_FLAG_DATA_VOLATILE;
761          root_param->ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
762          root_dwords += 2;
763       }
764    } else {
765       for (uint32_t i = 0; i < MAX_SHADER_VISIBILITIES; i++) {
766          dzn_foreach_pool_type(type) {
767             root_param = &root_params[layout->root.param_count];
768             root_param->ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
769             root_param->DescriptorTable.pDescriptorRanges = range_ptr;
770             root_param->DescriptorTable.NumDescriptorRanges = 0;
771             root_param->ShaderVisibility = (D3D12_SHADER_VISIBILITY)i;
772 
773             for (uint32_t j = 0; j < pCreateInfo->setLayoutCount; j++) {
774                VK_FROM_HANDLE(dzn_descriptor_set_layout, set_layout, pCreateInfo->pSetLayouts[j]);
775                uint32_t range_count = set_layout->range_count[i][type];
776 
777                memcpy(range_ptr, set_layout->ranges[i][type],
778                       range_count * sizeof(D3D12_DESCRIPTOR_RANGE1));
779                for (uint32_t k = 0; k < range_count; k++) {
780                   range_ptr[k].RegisterSpace = j;
781                   range_ptr[k].OffsetInDescriptorsFromTableStart +=
782                      layout->sets[j].heap_offsets[type];
783                }
784                root_param->DescriptorTable.NumDescriptorRanges += range_count;
785                range_ptr += range_count;
786             }
787 
788             if (root_param->DescriptorTable.NumDescriptorRanges) {
789                layout->root.type[layout->root.param_count++] = (D3D12_DESCRIPTOR_HEAP_TYPE)type;
790                root_dwords++;
791             }
792          }
793       }
794    }
795 
796    layout->root.sets_param_count = layout->root.param_count;
797 
798    if (layout->dynamic_buffer_count > 0 && device->bindless) {
799       layout->root.dynamic_buffer_bindless_param_idx = layout->root.param_count;
800       D3D12_ROOT_PARAMETER1 *root_param = &root_params[layout->root.param_count++];
801 
802       root_param->ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV;
803       root_param->Descriptor.RegisterSpace = 0;
804       root_param->Descriptor.ShaderRegister = layout->root.sets_param_count;
805       root_param->Descriptor.Flags = D3D12_ROOT_DESCRIPTOR_FLAG_DATA_STATIC;
806       root_param->ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
807       root_dwords += 2;
808    }
809 
810    /* Add our sysval CBV, and make it visible to all shaders */
811    layout->root.sysval_cbv_param_idx = layout->root.param_count;
812    root_param = &root_params[layout->root.param_count++];
813    root_param->ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS;
814    root_param->Descriptor.RegisterSpace = DZN_REGISTER_SPACE_SYSVALS;
815    root_param->Constants.ShaderRegister = 0;
816    root_param->Constants.Num32BitValues =
817        DIV_ROUND_UP(MAX2(sizeof(struct dxil_spirv_vertex_runtime_data),
818                          sizeof(struct dxil_spirv_compute_runtime_data)),
819                     4);
820    root_param->ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
821    root_dwords += root_param->Constants.Num32BitValues;
822 
823    if (pdev->root_sig_version >= D3D_ROOT_SIGNATURE_VERSION_1_2) {
824       D3D12_STATIC_SAMPLER_DESC1 *static_sampler_ptr = static_sampler_descs;
825       for (uint32_t j = 0; j < pCreateInfo->setLayoutCount; j++) {
826          VK_FROM_HANDLE(dzn_descriptor_set_layout, set_layout, pCreateInfo->pSetLayouts[j]);
827 
828          memcpy(static_sampler_ptr, set_layout->static_samplers,
829                 set_layout->static_sampler_count * sizeof(*set_layout->static_samplers));
830          if (j > 0) {
831             for (uint32_t k = 0; k < set_layout->static_sampler_count; k++)
832                static_sampler_ptr[k].RegisterSpace = j;
833          }
834          static_sampler_ptr += set_layout->static_sampler_count;
835       }
836    } else {
837       D3D12_STATIC_SAMPLER_DESC *static_sampler_ptr = (void *)static_sampler_descs;
838       for (uint32_t j = 0; j < pCreateInfo->setLayoutCount; j++) {
839          VK_FROM_HANDLE(dzn_descriptor_set_layout, set_layout, pCreateInfo->pSetLayouts[j]);
840 
841          for (uint32_t k = 0; k < set_layout->static_sampler_count; k++) {
842             memcpy(static_sampler_ptr, &set_layout->static_samplers[k],
843                      sizeof(*static_sampler_ptr));
844             static_sampler_ptr->RegisterSpace = j;
845             static_sampler_ptr++;
846          }
847       }
848    }
849 
850    uint32_t push_constant_size = 0;
851    uint32_t push_constant_flags = 0;
852    for (uint32_t j = 0; j < pCreateInfo->pushConstantRangeCount; j++) {
853       const VkPushConstantRange *range = pCreateInfo->pPushConstantRanges + j;
854       push_constant_size = MAX2(push_constant_size, range->offset + range->size);
855       push_constant_flags |= range->stageFlags;
856    }
857 
858    if (push_constant_size > 0) {
859       layout->root.push_constant_cbv_param_idx = layout->root.param_count;
860       D3D12_ROOT_PARAMETER1 *root_param = &root_params[layout->root.param_count++];
861 
862       root_param->ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS;
863       root_param->Constants.ShaderRegister = 0;
864       root_param->Constants.Num32BitValues = ALIGN(push_constant_size, 4) / 4;
865       root_param->Constants.RegisterSpace = DZN_REGISTER_SPACE_PUSH_CONSTANT;
866       root_param->ShaderVisibility = translate_desc_visibility(push_constant_flags);
867       root_dwords += root_param->Constants.Num32BitValues;
868    }
869 
870    assert(layout->root.param_count <= ARRAY_SIZE(root_params));
871    assert(root_dwords <= MAX_ROOT_DWORDS);
872 
873    D3D12_VERSIONED_ROOT_SIGNATURE_DESC root_sig_desc = {
874       .Version = pdev->root_sig_version,
875    };
876    /* TODO Only enable this flag when needed (optimization) */
877    D3D12_ROOT_SIGNATURE_FLAGS root_flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;
878    if (device->bindless)
879       root_flags |= D3D12_ROOT_SIGNATURE_FLAG_SAMPLER_HEAP_DIRECTLY_INDEXED |
880                     D3D12_ROOT_SIGNATURE_FLAG_CBV_SRV_UAV_HEAP_DIRECTLY_INDEXED;
881    if (pdev->root_sig_version >= D3D_ROOT_SIGNATURE_VERSION_1_2) {
882       root_sig_desc.Desc_1_2 = (D3D12_ROOT_SIGNATURE_DESC2){
883          .NumParameters = layout->root.param_count,
884          .pParameters = layout->root.param_count ? root_params : NULL,
885          .NumStaticSamplers = static_sampler_count,
886          .pStaticSamplers = static_sampler_descs,
887          .Flags = root_flags,
888       };
889    } else {
890       root_sig_desc.Desc_1_1 = (D3D12_ROOT_SIGNATURE_DESC1){
891             .NumParameters = layout->root.param_count,
892             .pParameters = layout->root.param_count ? root_params : NULL,
893             .NumStaticSamplers = static_sampler_count,
894             .pStaticSamplers = (void *)static_sampler_descs,
895             .Flags = root_flags,
896       };
897    }
898 
899    layout->root.sig = dzn_device_create_root_sig(device, &root_sig_desc);
900    vk_free2(&device->vk.alloc, pAllocator, ranges);
901    vk_free2(&device->vk.alloc, pAllocator, static_sampler_descs);
902 
903    if (!layout->root.sig) {
904       vk_pipeline_layout_unref(&device->vk, &layout->vk);
905       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
906    }
907 
908    dzn_pipeline_layout_hash_stages(layout, pCreateInfo);
909    *out = dzn_pipeline_layout_to_handle(layout);
910    return VK_SUCCESS;
911 }
912 
913 VKAPI_ATTR VkResult VKAPI_CALL
dzn_CreatePipelineLayout(VkDevice device,const VkPipelineLayoutCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkPipelineLayout * pPipelineLayout)914 dzn_CreatePipelineLayout(VkDevice device,
915                          const VkPipelineLayoutCreateInfo *pCreateInfo,
916                          const VkAllocationCallbacks *pAllocator,
917                          VkPipelineLayout *pPipelineLayout)
918 {
919    return dzn_pipeline_layout_create(dzn_device_from_handle(device),
920                                      pCreateInfo, pAllocator, pPipelineLayout);
921 }
922 
923 void
dzn_descriptor_heap_finish(struct dzn_descriptor_heap * heap)924 dzn_descriptor_heap_finish(struct dzn_descriptor_heap *heap)
925 {
926    if (heap->heap)
927       ID3D12DescriptorHeap_Release(heap->heap);
928 }
929 
930 VkResult
dzn_descriptor_heap_init(struct dzn_descriptor_heap * heap,struct dzn_device * device,D3D12_DESCRIPTOR_HEAP_TYPE type,uint32_t desc_count,bool shader_visible)931 dzn_descriptor_heap_init(struct dzn_descriptor_heap *heap,
932                          struct dzn_device *device,
933                          D3D12_DESCRIPTOR_HEAP_TYPE type,
934                          uint32_t desc_count,
935                          bool shader_visible)
936 {
937    heap->desc_count = desc_count;
938    heap->desc_sz = ID3D12Device1_GetDescriptorHandleIncrementSize(device->dev, type);
939 
940    D3D12_DESCRIPTOR_HEAP_DESC desc = {
941       .Type = type,
942       .NumDescriptors = desc_count,
943       .Flags = shader_visible ?
944                D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE :
945                D3D12_DESCRIPTOR_HEAP_FLAG_NONE,
946    };
947 
948    if (FAILED(ID3D12Device1_CreateDescriptorHeap(device->dev, &desc,
949                                                  &IID_ID3D12DescriptorHeap,
950                                                  (void **)&heap->heap))) {
951       return vk_error(device,
952                       shader_visible ?
953                       VK_ERROR_OUT_OF_DEVICE_MEMORY : VK_ERROR_OUT_OF_HOST_MEMORY);
954    }
955 
956    D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle = dzn_ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart(heap->heap);
957    heap->cpu_base = cpu_handle.ptr;
958    if (shader_visible) {
959       D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle = dzn_ID3D12DescriptorHeap_GetGPUDescriptorHandleForHeapStart(heap->heap);
960       heap->gpu_base = gpu_handle.ptr;
961    }
962 
963    return VK_SUCCESS;
964 }
965 
966 D3D12_CPU_DESCRIPTOR_HANDLE
dzn_descriptor_heap_get_cpu_handle(const struct dzn_descriptor_heap * heap,uint32_t desc_offset)967 dzn_descriptor_heap_get_cpu_handle(const struct dzn_descriptor_heap *heap, uint32_t desc_offset)
968 {
969    return (D3D12_CPU_DESCRIPTOR_HANDLE) {
970       .ptr = heap->cpu_base + (desc_offset * heap->desc_sz),
971    };
972 }
973 
974 D3D12_GPU_DESCRIPTOR_HANDLE
dzn_descriptor_heap_get_gpu_handle(const struct dzn_descriptor_heap * heap,uint32_t desc_offset)975 dzn_descriptor_heap_get_gpu_handle(const struct dzn_descriptor_heap *heap, uint32_t desc_offset)
976 {
977    return (D3D12_GPU_DESCRIPTOR_HANDLE) {
978       .ptr = heap->gpu_base ? heap->gpu_base + (desc_offset * heap->desc_sz) : 0,
979    };
980 }
981 
982 void
dzn_descriptor_heap_write_sampler_desc(struct dzn_device * device,struct dzn_descriptor_heap * heap,uint32_t desc_offset,const struct dzn_sampler * sampler)983 dzn_descriptor_heap_write_sampler_desc(struct dzn_device *device,
984                                        struct dzn_descriptor_heap *heap,
985                                        uint32_t desc_offset,
986                                        const struct dzn_sampler *sampler)
987 {
988    struct dzn_physical_device *pdev = container_of(device->vk.physical, struct dzn_physical_device, vk);
989    if (device->dev11 && pdev->options14.AdvancedTextureOpsSupported)
990       ID3D12Device11_CreateSampler2(device->dev11, &sampler->desc,
991                                     dzn_descriptor_heap_get_cpu_handle(heap, desc_offset));
992    else
993       ID3D12Device1_CreateSampler(device->dev, (D3D12_SAMPLER_DESC *)&sampler->desc,
994                                   dzn_descriptor_heap_get_cpu_handle(heap, desc_offset));
995 }
996 
997 void
dzn_descriptor_heap_write_image_view_desc(struct dzn_device * device,struct dzn_descriptor_heap * heap,uint32_t desc_offset,bool writeable,bool cube_as_2darray,const struct dzn_image_view * iview)998 dzn_descriptor_heap_write_image_view_desc(struct dzn_device *device,
999                                           struct dzn_descriptor_heap *heap,
1000                                           uint32_t desc_offset,
1001                                           bool writeable, bool cube_as_2darray,
1002                                           const struct dzn_image_view *iview)
1003 {
1004    D3D12_CPU_DESCRIPTOR_HANDLE view_handle =
1005       dzn_descriptor_heap_get_cpu_handle(heap, desc_offset);
1006    struct dzn_image *image = container_of(iview->vk.image, struct dzn_image, vk);
1007 
1008    if (writeable) {
1009       ID3D12Device1_CreateUnorderedAccessView(device->dev, image->res, NULL, &iview->uav_desc, view_handle);
1010    } else if (cube_as_2darray &&
1011               (iview->srv_desc.ViewDimension == D3D12_SRV_DIMENSION_TEXTURECUBEARRAY ||
1012                iview->srv_desc.ViewDimension == D3D12_SRV_DIMENSION_TEXTURECUBE)) {
1013       D3D12_SHADER_RESOURCE_VIEW_DESC srv_desc = iview->srv_desc;
1014       srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY;
1015       srv_desc.Texture2DArray.PlaneSlice = 0;
1016       srv_desc.Texture2DArray.ResourceMinLODClamp = 0.0f;
1017       if (iview->srv_desc.ViewDimension == D3D12_SRV_DIMENSION_TEXTURECUBEARRAY) {
1018          srv_desc.Texture2DArray.MostDetailedMip =
1019             iview->srv_desc.TextureCubeArray.MostDetailedMip;
1020          srv_desc.Texture2DArray.MipLevels =
1021             iview->srv_desc.TextureCubeArray.MipLevels;
1022          srv_desc.Texture2DArray.FirstArraySlice =
1023             iview->srv_desc.TextureCubeArray.First2DArrayFace;
1024          srv_desc.Texture2DArray.ArraySize =
1025             iview->srv_desc.TextureCubeArray.NumCubes * 6;
1026       } else {
1027          srv_desc.Texture2DArray.MostDetailedMip =
1028             iview->srv_desc.TextureCube.MostDetailedMip;
1029          srv_desc.Texture2DArray.MipLevels =
1030             iview->srv_desc.TextureCube.MipLevels;
1031          srv_desc.Texture2DArray.FirstArraySlice = 0;
1032          srv_desc.Texture2DArray.ArraySize = 6;
1033       }
1034 
1035       ID3D12Device1_CreateShaderResourceView(device->dev, image->res, &srv_desc, view_handle);
1036    } else {
1037       ID3D12Device1_CreateShaderResourceView(device->dev, image->res, &iview->srv_desc, view_handle);
1038    }
1039 }
1040 
1041 void
dzn_descriptor_heap_write_buffer_view_desc(struct dzn_device * device,struct dzn_descriptor_heap * heap,uint32_t desc_offset,bool writeable,const struct dzn_buffer_view * bview)1042 dzn_descriptor_heap_write_buffer_view_desc(struct dzn_device *device,
1043                                            struct dzn_descriptor_heap *heap,
1044                                            uint32_t desc_offset,
1045                                            bool writeable,
1046                                            const struct dzn_buffer_view *bview)
1047 {
1048    D3D12_CPU_DESCRIPTOR_HANDLE view_handle =
1049       dzn_descriptor_heap_get_cpu_handle(heap, desc_offset);
1050 
1051    if (writeable)
1052       ID3D12Device1_CreateUnorderedAccessView(device->dev, bview->buffer->res, NULL, &bview->uav_desc, view_handle);
1053    else
1054       ID3D12Device1_CreateShaderResourceView(device->dev, bview->buffer->res, &bview->srv_desc, view_handle);
1055 }
1056 
1057 void
dzn_descriptor_heap_write_buffer_desc(struct dzn_device * device,struct dzn_descriptor_heap * heap,uint32_t desc_offset,bool writeable,const struct dzn_buffer_desc * info)1058 dzn_descriptor_heap_write_buffer_desc(struct dzn_device *device,
1059                                       struct dzn_descriptor_heap *heap,
1060                                       uint32_t desc_offset,
1061                                       bool writeable,
1062                                       const struct dzn_buffer_desc *info)
1063 {
1064    D3D12_CPU_DESCRIPTOR_HANDLE view_handle =
1065       dzn_descriptor_heap_get_cpu_handle(heap, desc_offset);
1066 
1067    VkDeviceSize size =
1068       info->range == VK_WHOLE_SIZE ?
1069       info->buffer->size - info->offset :
1070       info->range;
1071 
1072    if (info->type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ||
1073        info->type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) {
1074       assert(!writeable);
1075       D3D12_CONSTANT_BUFFER_VIEW_DESC cbv_desc = {
1076          .BufferLocation = info->buffer->gpuva + info->offset,
1077          .SizeInBytes = MIN2(ALIGN_POT(size, 256), D3D12_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * 4 * sizeof(float)),
1078       };
1079       ID3D12Device1_CreateConstantBufferView(device->dev, &cbv_desc, view_handle);
1080    } else if (writeable) {
1081       D3D12_UNORDERED_ACCESS_VIEW_DESC uav_desc = {
1082          .Format = DXGI_FORMAT_R32_TYPELESS,
1083          .ViewDimension = D3D12_UAV_DIMENSION_BUFFER,
1084          .Buffer = {
1085             .FirstElement = info->offset / sizeof(uint32_t),
1086             .NumElements = (UINT)DIV_ROUND_UP(size, sizeof(uint32_t)),
1087             .Flags = D3D12_BUFFER_UAV_FLAG_RAW,
1088          },
1089       };
1090       ID3D12Device1_CreateUnorderedAccessView(device->dev, info->buffer->res, NULL, &uav_desc, view_handle);
1091    } else {
1092       D3D12_SHADER_RESOURCE_VIEW_DESC srv_desc = {
1093          .Format = DXGI_FORMAT_R32_TYPELESS,
1094          .ViewDimension = D3D12_SRV_DIMENSION_BUFFER,
1095          .Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING,
1096          .Buffer = {
1097             .FirstElement = info->offset / sizeof(uint32_t),
1098             .NumElements = (UINT)DIV_ROUND_UP(size, sizeof(uint32_t)),
1099             .Flags = D3D12_BUFFER_SRV_FLAG_RAW,
1100          },
1101       };
1102       ID3D12Device1_CreateShaderResourceView(device->dev, info->buffer->res, &srv_desc, view_handle);
1103    }
1104 }
1105 
1106 static void
dzn_bindless_descriptor_set_write_sampler_desc(volatile struct dxil_spirv_bindless_entry * map,uint32_t desc_offset,const struct dzn_sampler * sampler)1107 dzn_bindless_descriptor_set_write_sampler_desc(volatile struct dxil_spirv_bindless_entry *map,
1108                                                uint32_t desc_offset,
1109                                                const struct dzn_sampler *sampler)
1110 {
1111    map[desc_offset].sampler_idx = sampler->bindless_slot;
1112 }
1113 
1114 static void
dzn_bindless_descriptor_set_write_image_view_desc(volatile struct dxil_spirv_bindless_entry * map,VkDescriptorType type,uint32_t desc_offset,const struct dzn_image_view * iview)1115 dzn_bindless_descriptor_set_write_image_view_desc(volatile struct dxil_spirv_bindless_entry *map,
1116                                                   VkDescriptorType type,
1117                                                   uint32_t desc_offset,
1118                                                   const struct dzn_image_view *iview)
1119 {
1120    switch (type) {
1121    case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
1122       map[desc_offset].texture_idx = iview->uav_bindless_slot;
1123       break;
1124    case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
1125    case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
1126    case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
1127       map[desc_offset].texture_idx = iview->srv_bindless_slot;
1128       break;
1129    default:
1130       unreachable("Unexpected descriptor type");
1131    }
1132 }
1133 
1134 static void
dzn_bindless_descriptor_set_write_buffer_view_desc(volatile struct dxil_spirv_bindless_entry * map,VkDescriptorType type,uint32_t desc_offset,const struct dzn_buffer_view * bview)1135 dzn_bindless_descriptor_set_write_buffer_view_desc(volatile struct dxil_spirv_bindless_entry *map,
1136                                                    VkDescriptorType type,
1137                                                    uint32_t desc_offset,
1138                                                    const struct dzn_buffer_view *bview)
1139 {
1140    switch (type) {
1141    case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
1142       map[desc_offset].texture_idx = bview->srv_bindless_slot;
1143       break;
1144    case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
1145       map[desc_offset].texture_idx = bview->uav_bindless_slot;
1146       break;
1147    default:
1148       unreachable("Unexpected descriptor type");
1149    }
1150 }
1151 
1152 static void
dzn_bindless_descriptor_set_write_buffer_desc(struct dzn_device * device,volatile struct dxil_spirv_bindless_entry * map,uint32_t desc_offset,const struct dzn_buffer_desc * info)1153 dzn_bindless_descriptor_set_write_buffer_desc(struct dzn_device *device,
1154                                               volatile struct dxil_spirv_bindless_entry *map,
1155                                               uint32_t desc_offset,
1156                                               const struct dzn_buffer_desc *info)
1157 {
1158    dzn_buffer_get_bindless_buffer_descriptor(device, info, &map[desc_offset]);
1159 }
1160 
1161 static bool
need_custom_buffer_descriptor(struct dzn_device * device,const struct dzn_buffer_desc * info,struct dzn_buffer_desc * out_desc)1162 need_custom_buffer_descriptor(struct dzn_device *device, const struct dzn_buffer_desc *info,
1163                               struct dzn_buffer_desc *out_desc)
1164 {
1165    *out_desc = *info;
1166    uint32_t upper_bound_default_descriptor;
1167    uint32_t size_align, offset_align;
1168    /* Canonicalize descriptor types for hash/compare, and get size/align info */
1169    switch (info->type) {
1170    case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
1171       out_desc->type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
1172       FALLTHROUGH;
1173    case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
1174       upper_bound_default_descriptor =
1175          MIN2(D3D12_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * sizeof(float) * 4, info->buffer->size);
1176       size_align = offset_align = D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT;
1177       break;
1178    case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
1179       out_desc->type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1180       FALLTHROUGH;
1181    default:
1182       upper_bound_default_descriptor = MIN2(UINT32_MAX, info->buffer->size);
1183       offset_align = D3D12_RAW_UAV_SRV_BYTE_ALIGNMENT;
1184       size_align = 4;
1185       break;
1186    }
1187 
1188    uint64_t upper_bound = info->range == VK_WHOLE_SIZE ?
1189       info->buffer->size :
1190       info->offset + info->range;
1191    /* Addressing the whole buffer, no custom descriptor needed. */
1192    if (upper_bound == upper_bound_default_descriptor)
1193       return false;
1194 
1195    out_desc->range = ALIGN_POT(upper_bound, size_align);
1196    if (out_desc->range <= upper_bound_default_descriptor) {
1197       /* Use a larger descriptor with the hope that we'll be more likely
1198        * to be able to re-use it. The shader is already doing the offset
1199        * add, so there's not really a cost to putting a nonzero value there. */
1200       out_desc->offset = 0;
1201    } else {
1202       /* At least align-down the base offset to ensure that's a valid view to create */
1203       out_desc->offset = (out_desc->offset / offset_align) * offset_align;
1204       out_desc->range -= out_desc->offset;
1205    }
1206    return true;
1207 }
1208 
1209 static uint32_t
hash_buffer_desc(const void * data)1210 hash_buffer_desc(const void *data)
1211 {
1212    const struct dzn_buffer_desc *bdesc = data;
1213    /* Avoid any potential padding in the struct */
1214    uint32_t type_hash = _mesa_hash_data(&bdesc->type, sizeof(bdesc->type));
1215    return _mesa_hash_data_with_seed(&bdesc->range, sizeof(bdesc->range) * 2, type_hash);
1216 }
1217 
1218 static bool
compare_buffer_desc(const void * _a,const void * _b)1219 compare_buffer_desc(const void *_a, const void *_b)
1220 {
1221    const struct dzn_buffer_desc *a = _a, *b = _b;
1222    assert(a->buffer == b->buffer);
1223    /* Avoid any potential padding in the struct */
1224    return a->type == b->type &&
1225           a->range == b->range &&
1226           a->offset == b->offset;
1227 }
1228 
1229 static int
handle_custom_descriptor_cache(struct dzn_device * device,const struct dzn_buffer_desc * stack_desc)1230 handle_custom_descriptor_cache(struct dzn_device *device,
1231                                const struct dzn_buffer_desc *stack_desc)
1232 {
1233    /* Buffer lock is held */
1234 
1235    /* Initialize hash map */
1236    if (!stack_desc->buffer->custom_views)
1237       stack_desc->buffer->custom_views = _mesa_hash_table_create(NULL, hash_buffer_desc, compare_buffer_desc);
1238 
1239    if (!stack_desc->buffer->custom_views)
1240       return -1;
1241 
1242    uint32_t hash = hash_buffer_desc(stack_desc);
1243    struct hash_entry *entry = _mesa_hash_table_search_pre_hashed(stack_desc->buffer->custom_views, hash, stack_desc);
1244    if (entry)
1245       return (int)(intptr_t)entry->data;
1246 
1247    int slot = dzn_device_descriptor_heap_alloc_slot(device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
1248    if (slot < 0)
1249       return slot;
1250 
1251    struct dzn_buffer_desc *key = malloc(sizeof(*stack_desc));
1252    if (!key) {
1253       dzn_device_descriptor_heap_free_slot(device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, slot);
1254       return -1;
1255    }
1256 
1257    *key = *stack_desc;
1258    entry = _mesa_hash_table_insert_pre_hashed(stack_desc->buffer->custom_views, hash, key, (void *)(intptr_t)slot);
1259    if (!entry) {
1260       free(key);
1261       dzn_device_descriptor_heap_free_slot(device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, slot);
1262       return -1;
1263    }
1264 
1265    dzn_descriptor_heap_write_buffer_desc(device, &device->device_heaps[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV].heap,
1266                                          slot, key->type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, key);
1267    return slot;
1268 }
1269 
1270 void
dzn_buffer_get_bindless_buffer_descriptor(struct dzn_device * device,const struct dzn_buffer_desc * bdesc,volatile struct dxil_spirv_bindless_entry * out)1271 dzn_buffer_get_bindless_buffer_descriptor(struct dzn_device *device,
1272                                           const struct dzn_buffer_desc *bdesc,
1273                                           volatile struct dxil_spirv_bindless_entry *out)
1274 {
1275    int slot;
1276    uint32_t offset = bdesc->offset;
1277    switch (bdesc->type) {
1278    case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
1279    case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
1280       slot = bdesc->buffer->cbv_bindless_slot;
1281       break;
1282    case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
1283    case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
1284       slot = bdesc->buffer->uav_bindless_slot;
1285       break;
1286    default:
1287       unreachable("Unexpected descriptor type");
1288    }
1289 
1290    struct dzn_buffer_desc local_desc;
1291    if (need_custom_buffer_descriptor(device, bdesc, &local_desc)) {
1292       mtx_lock(&bdesc->buffer->bindless_view_lock);
1293 
1294       int new_slot = handle_custom_descriptor_cache(device, &local_desc);
1295       if (new_slot >= 0) {
1296          slot = new_slot;
1297          offset = bdesc->offset - local_desc.offset;
1298       }
1299       /* In the case of cache failure, just use the base view and try
1300        * shader-based offsetting, it'll probably still work in most cases. */
1301 
1302       mtx_unlock(&bdesc->buffer->bindless_view_lock);
1303    }
1304 
1305    out->buffer_idx = slot;
1306    out->buffer_offset = offset;
1307 }
1308 
1309 void
dzn_descriptor_heap_copy(struct dzn_device * device,struct dzn_descriptor_heap * dst_heap,uint32_t dst_offset,const struct dzn_descriptor_heap * src_heap,uint32_t src_offset,uint32_t desc_count,D3D12_DESCRIPTOR_HEAP_TYPE type)1310 dzn_descriptor_heap_copy(struct dzn_device *device,
1311                          struct dzn_descriptor_heap *dst_heap,
1312                          uint32_t dst_offset,
1313                          const struct dzn_descriptor_heap *src_heap,
1314                          uint32_t src_offset,
1315                          uint32_t desc_count,
1316                          D3D12_DESCRIPTOR_HEAP_TYPE type)
1317 {
1318    D3D12_CPU_DESCRIPTOR_HANDLE dst_handle =
1319       dzn_descriptor_heap_get_cpu_handle(dst_heap, dst_offset);
1320    D3D12_CPU_DESCRIPTOR_HANDLE src_handle =
1321       dzn_descriptor_heap_get_cpu_handle(src_heap, src_offset);
1322 
1323    ID3D12Device1_CopyDescriptorsSimple(device->dev, desc_count,
1324                                        dst_handle,
1325                                        src_handle,
1326                                        type);
1327 }
1328 
1329 struct dzn_descriptor_set_ptr {
1330    uint32_t binding, elem;
1331 };
1332 
1333 static void
dzn_descriptor_set_ptr_validate(const struct dzn_descriptor_set_layout * layout,struct dzn_descriptor_set_ptr * ptr)1334 dzn_descriptor_set_ptr_validate(const struct dzn_descriptor_set_layout *layout,
1335                                 struct dzn_descriptor_set_ptr *ptr)
1336 {
1337 
1338    if (ptr->binding >= layout->binding_count) {
1339       ptr->binding = ~0;
1340       ptr->elem = ~0;
1341       return;
1342    }
1343 
1344    uint32_t desc_count =
1345       dzn_descriptor_set_layout_get_desc_count(layout, ptr->binding);
1346    if (ptr->elem >= desc_count) {
1347       ptr->binding = ~0;
1348       ptr->elem = ~0;
1349    }
1350 }
1351 
1352 static void
dzn_descriptor_set_ptr_init(const struct dzn_descriptor_set_layout * layout,struct dzn_descriptor_set_ptr * ptr,uint32_t binding,uint32_t elem)1353 dzn_descriptor_set_ptr_init(const struct dzn_descriptor_set_layout *layout,
1354                             struct dzn_descriptor_set_ptr *ptr,
1355                             uint32_t binding, uint32_t elem)
1356 {
1357    ptr->binding = binding;
1358    ptr->elem = elem;
1359    dzn_descriptor_set_ptr_validate(layout, ptr);
1360 }
1361 
1362 static void
dzn_descriptor_set_ptr_move(const struct dzn_descriptor_set_layout * layout,struct dzn_descriptor_set_ptr * ptr,uint32_t count)1363 dzn_descriptor_set_ptr_move(const struct dzn_descriptor_set_layout *layout,
1364                             struct dzn_descriptor_set_ptr *ptr,
1365                             uint32_t count)
1366 {
1367    if (ptr->binding == ~0)
1368       return;
1369 
1370    while (count) {
1371       uint32_t desc_count =
1372          dzn_descriptor_set_layout_get_desc_count(layout, ptr->binding);
1373 
1374       if (count >= desc_count - ptr->elem) {
1375          count -= desc_count - ptr->elem;
1376          ptr->binding++;
1377          ptr->elem = 0;
1378       } else {
1379          ptr->elem += count;
1380          count = 0;
1381       }
1382    }
1383 
1384    dzn_descriptor_set_ptr_validate(layout, ptr);
1385 }
1386 
1387 static bool
dzn_descriptor_set_ptr_is_valid(const struct dzn_descriptor_set_ptr * ptr)1388 dzn_descriptor_set_ptr_is_valid(const struct dzn_descriptor_set_ptr *ptr)
1389 {
1390    return ptr->binding != ~0 && ptr->elem != ~0;
1391 }
1392 
1393 static uint32_t
dzn_descriptor_set_remaining_descs_in_binding(const struct dzn_descriptor_set_layout * layout,const struct dzn_descriptor_set_ptr * ptr)1394 dzn_descriptor_set_remaining_descs_in_binding(const struct dzn_descriptor_set_layout *layout,
1395                                               const struct dzn_descriptor_set_ptr *ptr)
1396 {
1397    if (ptr->binding >= layout->binding_count)
1398       return 0;
1399 
1400    uint32_t desc_count =
1401       dzn_descriptor_set_layout_get_desc_count(layout, ptr->binding);
1402 
1403    return desc_count >= ptr->elem ? desc_count - ptr->elem : 0;
1404 }
1405 
1406 
1407 static uint32_t
dzn_descriptor_set_ptr_get_heap_offset(const struct dzn_descriptor_set_layout * layout,D3D12_DESCRIPTOR_HEAP_TYPE type,const struct dzn_descriptor_set_ptr * ptr,bool alt,bool bindless)1408 dzn_descriptor_set_ptr_get_heap_offset(const struct dzn_descriptor_set_layout *layout,
1409                                        D3D12_DESCRIPTOR_HEAP_TYPE type,
1410                                        const struct dzn_descriptor_set_ptr *ptr,
1411                                        bool alt,
1412                                        bool bindless)
1413 {
1414    if (ptr->binding == ~0)
1415       return ~0;
1416 
1417    uint32_t base =
1418       dzn_descriptor_set_layout_get_heap_offset(layout, ptr->binding, type, alt, bindless);
1419    if (base == ~0)
1420       return ~0;
1421 
1422    return base + ptr->elem;
1423 }
1424 
1425 static void
dzn_descriptor_set_write_sampler_desc(struct dzn_device * device,struct dzn_descriptor_set * set,uint32_t heap_offset,const struct dzn_sampler * sampler)1426 dzn_descriptor_set_write_sampler_desc(struct dzn_device *device,
1427                                       struct dzn_descriptor_set *set,
1428                                       uint32_t heap_offset,
1429                                       const struct dzn_sampler *sampler)
1430 {
1431    if (heap_offset == ~0)
1432       return;
1433 
1434    D3D12_DESCRIPTOR_HEAP_TYPE type = D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER;
1435    if (device->bindless) {
1436       dzn_bindless_descriptor_set_write_sampler_desc(set->pool->bindless.map,
1437                                                      set->heap_offsets[0] + heap_offset,
1438                                                      sampler);
1439    } else {
1440       dzn_descriptor_heap_write_sampler_desc(device,
1441                                              &set->pool->heaps[type],
1442                                              set->heap_offsets[type] + heap_offset,
1443                                              sampler);
1444    }
1445 }
1446 
1447 static void
dzn_descriptor_set_ptr_write_sampler_desc(struct dzn_device * device,struct dzn_descriptor_set * set,const struct dzn_descriptor_set_ptr * ptr,const struct dzn_sampler * sampler)1448 dzn_descriptor_set_ptr_write_sampler_desc(struct dzn_device *device,
1449                                           struct dzn_descriptor_set *set,
1450                                           const struct dzn_descriptor_set_ptr *ptr,
1451                                           const struct dzn_sampler *sampler)
1452 {
1453    D3D12_DESCRIPTOR_HEAP_TYPE type = D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER;
1454    uint32_t heap_offset =
1455       dzn_descriptor_set_ptr_get_heap_offset(set->layout, type, ptr, false, device->bindless);
1456 
1457    dzn_descriptor_set_write_sampler_desc(device, set, heap_offset, sampler);
1458 }
1459 
1460 static uint32_t
dzn_descriptor_set_ptr_get_buffer_idx(const struct dzn_descriptor_set_layout * layout,const struct dzn_descriptor_set_ptr * ptr)1461 dzn_descriptor_set_ptr_get_buffer_idx(const struct dzn_descriptor_set_layout *layout,
1462                                       const struct dzn_descriptor_set_ptr *ptr)
1463 {
1464    if (ptr->binding == ~0)
1465       return ~0;
1466 
1467    uint32_t base = layout->bindings[ptr->binding].buffer_idx;
1468 
1469    if (base == ~0)
1470       return ~0;
1471 
1472    return base + ptr->elem;
1473 }
1474 
1475 static void
dzn_descriptor_set_write_dynamic_buffer_desc(struct dzn_device * device,struct dzn_descriptor_set * set,uint32_t dynamic_buffer_idx,const struct dzn_buffer_desc * info)1476 dzn_descriptor_set_write_dynamic_buffer_desc(struct dzn_device *device,
1477                                              struct dzn_descriptor_set *set,
1478                                              uint32_t dynamic_buffer_idx,
1479                                              const struct dzn_buffer_desc *info)
1480 {
1481    if (dynamic_buffer_idx == ~0)
1482       return;
1483 
1484    assert(dynamic_buffer_idx < set->layout->dynamic_buffers.count);
1485    set->dynamic_buffers[dynamic_buffer_idx] = *info;
1486 }
1487 
1488 static void
dzn_descriptor_set_ptr_write_dynamic_buffer_desc(struct dzn_device * device,struct dzn_descriptor_set * set,const struct dzn_descriptor_set_ptr * ptr,const struct dzn_buffer_desc * info)1489 dzn_descriptor_set_ptr_write_dynamic_buffer_desc(struct dzn_device *device,
1490                                                  struct dzn_descriptor_set *set,
1491                                                  const struct dzn_descriptor_set_ptr *ptr,
1492                                                  const struct dzn_buffer_desc *info)
1493 {
1494    uint32_t dynamic_buffer_idx =
1495       dzn_descriptor_set_ptr_get_buffer_idx(set->layout, ptr);
1496 
1497    dzn_descriptor_set_write_dynamic_buffer_desc(device, set, dynamic_buffer_idx, info);
1498 }
1499 
1500 static VkDescriptorType
dzn_descriptor_set_ptr_get_vk_type(const struct dzn_descriptor_set_layout * layout,const struct dzn_descriptor_set_ptr * ptr)1501 dzn_descriptor_set_ptr_get_vk_type(const struct dzn_descriptor_set_layout *layout,
1502                                    const struct dzn_descriptor_set_ptr *ptr)
1503 {
1504    if (ptr->binding >= layout->binding_count)
1505       return (VkDescriptorType)~0;
1506 
1507    return layout->bindings[ptr->binding].type;
1508 }
1509 
1510 static void
dzn_descriptor_set_write_image_view_desc(struct dzn_device * device,VkDescriptorType desc_type,struct dzn_descriptor_set * set,uint32_t heap_offset,uint32_t alt_heap_offset,bool cube_as_2darray,const struct dzn_image_view * iview)1511 dzn_descriptor_set_write_image_view_desc(struct dzn_device *device,
1512                                          VkDescriptorType desc_type,
1513                                          struct dzn_descriptor_set *set,
1514                                          uint32_t heap_offset,
1515                                          uint32_t alt_heap_offset,
1516                                          bool cube_as_2darray,
1517                                          const struct dzn_image_view *iview)
1518 {
1519    D3D12_DESCRIPTOR_HEAP_TYPE type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
1520 
1521    if (heap_offset == ~0)
1522       return;
1523 
1524    if (device->bindless) {
1525       dzn_bindless_descriptor_set_write_image_view_desc(set->pool->bindless.map,
1526                                                         desc_type,
1527                                                         set->heap_offsets[0] + heap_offset,
1528                                                         iview);
1529       return;
1530    }
1531 
1532    bool primary_writable = desc_type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
1533 
1534    dzn_descriptor_heap_write_image_view_desc(device,
1535                                              &set->pool->heaps[type],
1536                                              set->heap_offsets[type] + heap_offset,
1537                                              primary_writable, cube_as_2darray,
1538                                              iview);
1539 
1540    if (alt_heap_offset != ~0) {
1541       assert(primary_writable);
1542       dzn_descriptor_heap_write_image_view_desc(device,
1543                                                 &set->pool->heaps[type],
1544                                                 set->heap_offsets[type] + alt_heap_offset,
1545                                                 false, cube_as_2darray,
1546                                                 iview);
1547    }
1548 }
1549 
1550 static void
dzn_descriptor_set_ptr_write_image_view_desc(struct dzn_device * device,VkDescriptorType desc_type,struct dzn_descriptor_set * set,const struct dzn_descriptor_set_ptr * ptr,bool cube_as_2darray,const struct dzn_image_view * iview)1551 dzn_descriptor_set_ptr_write_image_view_desc(struct dzn_device *device,
1552                                              VkDescriptorType desc_type,
1553                                              struct dzn_descriptor_set *set,
1554                                              const struct dzn_descriptor_set_ptr *ptr,
1555                                              bool cube_as_2darray,
1556                                              const struct dzn_image_view *iview)
1557 {
1558    D3D12_DESCRIPTOR_HEAP_TYPE type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
1559    uint32_t heap_offset =
1560       dzn_descriptor_set_ptr_get_heap_offset(set->layout, type, ptr, false, device->bindless);
1561    uint32_t alt_heap_offset =
1562       dzn_descriptor_set_ptr_get_heap_offset(set->layout, type, ptr, true, device->bindless);
1563 
1564    dzn_descriptor_set_write_image_view_desc(device, desc_type, set, heap_offset, alt_heap_offset,
1565                                             cube_as_2darray, iview);
1566 }
1567 
1568 static void
dzn_descriptor_set_write_buffer_view_desc(struct dzn_device * device,VkDescriptorType desc_type,struct dzn_descriptor_set * set,uint32_t heap_offset,uint32_t alt_heap_offset,const struct dzn_buffer_view * bview)1569 dzn_descriptor_set_write_buffer_view_desc(struct dzn_device *device,
1570                                           VkDescriptorType desc_type,
1571                                           struct dzn_descriptor_set *set,
1572                                           uint32_t heap_offset,
1573                                           uint32_t alt_heap_offset,
1574                                           const struct dzn_buffer_view *bview)
1575 {
1576    if (heap_offset == ~0)
1577       return;
1578 
1579    if (device->bindless) {
1580       dzn_bindless_descriptor_set_write_buffer_view_desc(set->pool->bindless.map,
1581                                                          desc_type,
1582                                                          set->heap_offsets[0] + heap_offset,
1583                                                          bview);
1584       return;
1585    }
1586 
1587    D3D12_DESCRIPTOR_HEAP_TYPE type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
1588    bool primary_writable = desc_type == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
1589 
1590    dzn_descriptor_heap_write_buffer_view_desc(device,
1591                                               &set->pool->heaps[type],
1592                                               set->heap_offsets[type] +
1593                                               heap_offset,
1594                                               primary_writable, bview);
1595 
1596    if (alt_heap_offset != ~0) {
1597       assert(primary_writable);
1598       dzn_descriptor_heap_write_buffer_view_desc(device,
1599                                                  &set->pool->heaps[type],
1600                                                  set->heap_offsets[type] +
1601                                                  alt_heap_offset,
1602                                                  false, bview);
1603    }
1604 }
1605 
1606 static void
dzn_descriptor_set_ptr_write_buffer_view_desc(struct dzn_device * device,VkDescriptorType desc_type,struct dzn_descriptor_set * set,const struct dzn_descriptor_set_ptr * ptr,const struct dzn_buffer_view * bview)1607 dzn_descriptor_set_ptr_write_buffer_view_desc(struct dzn_device *device,
1608                                               VkDescriptorType desc_type,
1609                                               struct dzn_descriptor_set *set,
1610                                               const struct dzn_descriptor_set_ptr *ptr,
1611                                               const struct dzn_buffer_view *bview)
1612 {
1613    D3D12_DESCRIPTOR_HEAP_TYPE type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
1614    uint32_t heap_offset =
1615       dzn_descriptor_set_ptr_get_heap_offset(set->layout, type, ptr, false, device->bindless);
1616    uint32_t alt_heap_offset =
1617       dzn_descriptor_set_ptr_get_heap_offset(set->layout, type, ptr, true, device->bindless);
1618 
1619    dzn_descriptor_set_write_buffer_view_desc(device, desc_type, set, heap_offset, alt_heap_offset, bview);
1620 }
1621 
1622 static void
dzn_descriptor_set_write_buffer_desc(struct dzn_device * device,VkDescriptorType desc_type,struct dzn_descriptor_set * set,uint32_t heap_offset,uint32_t alt_heap_offset,const struct dzn_buffer_desc * bdesc)1623 dzn_descriptor_set_write_buffer_desc(struct dzn_device *device,
1624                                      VkDescriptorType desc_type,
1625                                      struct dzn_descriptor_set *set,
1626                                      uint32_t heap_offset,
1627                                      uint32_t alt_heap_offset,
1628                                      const struct dzn_buffer_desc *bdesc)
1629 {
1630    D3D12_DESCRIPTOR_HEAP_TYPE type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
1631    if (heap_offset == ~0)
1632       return;
1633 
1634    if (device->bindless) {
1635       dzn_bindless_descriptor_set_write_buffer_desc(device,
1636                                                     set->pool->bindless.map,
1637                                                     set->heap_offsets[0] + heap_offset,
1638                                                     bdesc);
1639       return;
1640    }
1641 
1642    bool primary_writable = desc_type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1643 
1644    dzn_descriptor_heap_write_buffer_desc(device, &set->pool->heaps[type],
1645                                          set->heap_offsets[type] + heap_offset,
1646                                          primary_writable, bdesc);
1647 
1648    if (alt_heap_offset != ~0) {
1649       assert(primary_writable);
1650       dzn_descriptor_heap_write_buffer_desc(device, &set->pool->heaps[type],
1651                                             set->heap_offsets[type] +
1652                                             alt_heap_offset,
1653                                             false, bdesc);
1654    }
1655 }
1656 
1657 static void
dzn_descriptor_set_ptr_write_buffer_desc(struct dzn_device * device,VkDescriptorType desc_type,struct dzn_descriptor_set * set,const struct dzn_descriptor_set_ptr * ptr,const struct dzn_buffer_desc * bdesc)1658 dzn_descriptor_set_ptr_write_buffer_desc(struct dzn_device *device,
1659                                          VkDescriptorType desc_type,
1660                                          struct dzn_descriptor_set *set,
1661                                          const struct dzn_descriptor_set_ptr *ptr,
1662                                          const struct dzn_buffer_desc *bdesc)
1663 {
1664    D3D12_DESCRIPTOR_HEAP_TYPE type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
1665    uint32_t heap_offset =
1666       dzn_descriptor_set_ptr_get_heap_offset(set->layout, type, ptr, false, device->bindless);
1667    uint32_t alt_heap_offset =
1668       dzn_descriptor_set_ptr_get_heap_offset(set->layout, type, ptr, true, device->bindless);
1669 
1670    dzn_descriptor_set_write_buffer_desc(device, desc_type, set, heap_offset, alt_heap_offset, bdesc);
1671 }
1672 
1673 static VkResult
dzn_descriptor_set_init(struct dzn_descriptor_set * set,struct dzn_device * device,struct dzn_descriptor_pool * pool,struct dzn_descriptor_set_layout * layout,bool reuse,uint32_t * variable_descriptor_count)1674 dzn_descriptor_set_init(struct dzn_descriptor_set *set,
1675                         struct dzn_device *device,
1676                         struct dzn_descriptor_pool *pool,
1677                         struct dzn_descriptor_set_layout *layout,
1678                         bool reuse,
1679                         uint32_t *variable_descriptor_count)
1680 {
1681    vk_object_base_init(&device->vk, &set->base, VK_OBJECT_TYPE_DESCRIPTOR_SET);
1682 
1683    set->pool = pool;
1684    set->layout = layout;
1685 
1686    if (!reuse) {
1687       dzn_foreach_pool_type(type) {
1688          set->heap_offsets[type] = pool->free_offset[type];
1689          if (device->bindless)
1690             set->heap_offsets[type] = ALIGN(set->heap_offsets[type], 2);
1691          set->heap_sizes[type] = layout->range_desc_count[type] + variable_descriptor_count[type];
1692          set->pool->free_offset[type] = set->heap_offsets[type] + set->heap_sizes[type];
1693       }
1694    }
1695 
1696    /* Pre-fill the immutable samplers */
1697    if (layout->immutable_sampler_count) {
1698       for (uint32_t b = 0; b < layout->binding_count; b++) {
1699          bool has_samplers =
1700             dzn_desc_type_has_sampler(layout->bindings[b].type);
1701 
1702          if (!has_samplers ||
1703              layout->bindings[b].immutable_sampler_idx == ~0 ||
1704              layout->bindings[b].immutable_sampler_idx == STATIC_SAMPLER_TAG)
1705             continue;
1706 
1707          struct dzn_descriptor_set_ptr ptr;
1708          const struct dzn_sampler **sampler =
1709             &layout->immutable_samplers[layout->bindings[b].immutable_sampler_idx];
1710          for (dzn_descriptor_set_ptr_init(set->layout, &ptr, b, 0);
1711               dzn_descriptor_set_ptr_is_valid(&ptr) && ptr.binding == b;
1712               dzn_descriptor_set_ptr_move(set->layout, &ptr, 1)) {
1713             dzn_descriptor_set_ptr_write_sampler_desc(device, set, &ptr, *sampler);
1714             sampler++;
1715          }
1716       }
1717    }
1718    return VK_SUCCESS;
1719 }
1720 
1721 static void
dzn_descriptor_set_finish(struct dzn_descriptor_set * set)1722 dzn_descriptor_set_finish(struct dzn_descriptor_set *set)
1723 {
1724    vk_object_base_finish(&set->base);
1725    set->pool = NULL;
1726    set->layout = NULL;
1727 }
1728 
1729 static void
dzn_descriptor_pool_destroy(struct dzn_descriptor_pool * pool,const VkAllocationCallbacks * pAllocator)1730 dzn_descriptor_pool_destroy(struct dzn_descriptor_pool *pool,
1731                             const VkAllocationCallbacks *pAllocator)
1732 {
1733    if (!pool)
1734       return;
1735 
1736    struct dzn_device *device = container_of(pool->base.device, struct dzn_device, vk);
1737 
1738    if (device->bindless) {
1739       if (pool->bindless.buf)
1740          ID3D12Resource_Release(pool->bindless.buf);
1741    } else {
1742       dzn_foreach_pool_type(type) {
1743          if (pool->desc_count[type])
1744             dzn_descriptor_heap_finish(&pool->heaps[type]);
1745       }
1746    }
1747 
1748    vk_object_base_finish(&pool->base);
1749    vk_free2(&device->vk.alloc, pAllocator, pool);
1750 }
1751 
1752 static VkResult
dzn_descriptor_pool_create(struct dzn_device * device,const VkDescriptorPoolCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDescriptorPool * out)1753 dzn_descriptor_pool_create(struct dzn_device *device,
1754                            const VkDescriptorPoolCreateInfo *pCreateInfo,
1755                            const VkAllocationCallbacks *pAllocator,
1756                            VkDescriptorPool *out)
1757 {
1758    VK_MULTIALLOC(ma);
1759    VK_MULTIALLOC_DECL(&ma, struct dzn_descriptor_pool, pool, 1);
1760    VK_MULTIALLOC_DECL(&ma, struct dzn_descriptor_set, sets, pCreateInfo->maxSets);
1761 
1762    if (!vk_multialloc_zalloc2(&ma, &device->vk.alloc, pAllocator,
1763                               VK_SYSTEM_ALLOCATION_SCOPE_OBJECT))
1764       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
1765 
1766    pool->alloc = pAllocator ? *pAllocator : device->vk.alloc;
1767    pool->sets = sets;
1768    pool->set_count = pCreateInfo->maxSets;
1769 
1770    vk_object_base_init(&device->vk, &pool->base, VK_OBJECT_TYPE_DESCRIPTOR_POOL);
1771 
1772    for (uint32_t p = 0; p < pCreateInfo->poolSizeCount; p++) {
1773       VkDescriptorType type = pCreateInfo->pPoolSizes[p].type;
1774       uint32_t num_desc = pCreateInfo->pPoolSizes[p].descriptorCount;
1775 
1776       if (device->bindless) {
1777          switch (type) {
1778          case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
1779          case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
1780             break;
1781          default:
1782             pool->desc_count[0] += num_desc;
1783             break;
1784          }
1785       } else {
1786          switch (type) {
1787          case VK_DESCRIPTOR_TYPE_SAMPLER:
1788             pool->desc_count[D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER] += num_desc;
1789             break;
1790          case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
1791             pool->desc_count[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV] += num_desc;
1792             pool->desc_count[D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER] += num_desc;
1793             break;
1794          case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
1795          case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
1796          case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
1797          case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
1798             pool->desc_count[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV] += num_desc;
1799             break;
1800          case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
1801          case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
1802          case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
1803             /* Reserve one UAV and one SRV slot for those. */
1804             pool->desc_count[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV] += num_desc * 2;
1805             break;
1806          case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
1807          case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
1808             break;
1809          default:
1810             unreachable("Unsupported desc type");
1811          }
1812       }
1813    }
1814 
1815    if (device->bindless) {
1816       if (pool->desc_count[0]) {
1817          /* Include extra descriptors so that we can align each allocated descriptor set to a 16-byte boundary */
1818          static_assert(D3D12_RAW_UAV_SRV_BYTE_ALIGNMENT / sizeof(struct dxil_spirv_bindless_entry) == 2,
1819                        "Ensure only one extra descriptor is needed to produce correct alignments");
1820          uint32_t extra_descriptors = pool->set_count - 1;
1821          pool->desc_count[0] += extra_descriptors;
1822 
1823          /* Going to raw APIs to avoid allocating descriptors for this */
1824          D3D12_RESOURCE_DESC buf_desc = {
1825             .Dimension = D3D12_RESOURCE_DIMENSION_BUFFER,
1826             .Width = pool->desc_count[0] * sizeof(struct dxil_spirv_bindless_entry),
1827             .Height = 1, .DepthOrArraySize = 1,
1828             .MipLevels = 1, .SampleDesc = {.Count = 1},
1829             .Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR
1830          };
1831          D3D12_HEAP_PROPERTIES heap_props = { .Type = D3D12_HEAP_TYPE_UPLOAD };
1832          if (FAILED(ID3D12Device_CreateCommittedResource(device->dev, &heap_props, 0, &buf_desc, D3D12_RESOURCE_STATE_GENERIC_READ,
1833                                                          NULL, &IID_ID3D12Resource, (void **)&pool->bindless.buf))) {
1834             dzn_descriptor_pool_destroy(pool, pAllocator);
1835             return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
1836          }
1837          pool->bindless.gpuva = ID3D12Resource_GetGPUVirtualAddress(pool->bindless.buf);
1838          ID3D12Resource_Map(pool->bindless.buf, 0, NULL, (void **)&pool->bindless.map);
1839       }
1840    } else {
1841       dzn_foreach_pool_type(type) {
1842          if (!pool->desc_count[type])
1843             continue;
1844 
1845          VkResult result =
1846             dzn_descriptor_heap_init(&pool->heaps[type], device, type, pool->desc_count[type], false);
1847          if (result != VK_SUCCESS) {
1848             dzn_descriptor_pool_destroy(pool, pAllocator);
1849             return result;
1850          }
1851       }
1852    }
1853 
1854    *out = dzn_descriptor_pool_to_handle(pool);
1855    return VK_SUCCESS;
1856 }
1857 
1858 VKAPI_ATTR VkResult VKAPI_CALL
dzn_CreateDescriptorPool(VkDevice device,const VkDescriptorPoolCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDescriptorPool * pDescriptorPool)1859 dzn_CreateDescriptorPool(VkDevice device,
1860                          const VkDescriptorPoolCreateInfo *pCreateInfo,
1861                          const VkAllocationCallbacks *pAllocator,
1862                          VkDescriptorPool *pDescriptorPool)
1863 {
1864    return dzn_descriptor_pool_create(dzn_device_from_handle(device),
1865                                      pCreateInfo, pAllocator, pDescriptorPool);
1866 }
1867 
1868 VKAPI_ATTR void VKAPI_CALL
dzn_DestroyDescriptorPool(VkDevice device,VkDescriptorPool descriptorPool,const VkAllocationCallbacks * pAllocator)1869 dzn_DestroyDescriptorPool(VkDevice device,
1870                           VkDescriptorPool descriptorPool,
1871                           const VkAllocationCallbacks *pAllocator)
1872 {
1873    dzn_descriptor_pool_destroy(dzn_descriptor_pool_from_handle(descriptorPool),
1874                                pAllocator);
1875 }
1876 
1877 VKAPI_ATTR VkResult VKAPI_CALL
dzn_ResetDescriptorPool(VkDevice device,VkDescriptorPool descriptorPool,VkDescriptorPoolResetFlags flags)1878 dzn_ResetDescriptorPool(VkDevice device,
1879                         VkDescriptorPool descriptorPool,
1880                         VkDescriptorPoolResetFlags flags)
1881 {
1882    VK_FROM_HANDLE(dzn_descriptor_pool, pool, descriptorPool);
1883 
1884    for (uint32_t s = 0; s < pool->set_count; s++)
1885       dzn_descriptor_set_finish(&pool->sets[s]);
1886 
1887    dzn_foreach_pool_type(type) {
1888       pool->free_offset[type] = 0;
1889       pool->used_desc_count[type] = 0;
1890    }
1891    pool->used_set_count = 0;
1892 
1893    return VK_SUCCESS;
1894 }
1895 
1896 void
dzn_descriptor_heap_pool_finish(struct dzn_descriptor_heap_pool * pool)1897 dzn_descriptor_heap_pool_finish(struct dzn_descriptor_heap_pool *pool)
1898 {
1899    list_splicetail(&pool->active_heaps, &pool->free_heaps);
1900    list_for_each_entry_safe(struct dzn_descriptor_heap_pool_entry, entry, &pool->free_heaps, link) {
1901       list_del(&entry->link);
1902       dzn_descriptor_heap_finish(&entry->heap);
1903       vk_free(pool->alloc, entry);
1904    }
1905 }
1906 
1907 void
dzn_descriptor_heap_pool_init(struct dzn_descriptor_heap_pool * pool,struct dzn_device * device,D3D12_DESCRIPTOR_HEAP_TYPE type,bool shader_visible,const VkAllocationCallbacks * alloc)1908 dzn_descriptor_heap_pool_init(struct dzn_descriptor_heap_pool *pool,
1909                               struct dzn_device *device,
1910                               D3D12_DESCRIPTOR_HEAP_TYPE type,
1911                               bool shader_visible,
1912                               const VkAllocationCallbacks *alloc)
1913 {
1914    assert(!shader_visible ||
1915           type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV ||
1916           type == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
1917 
1918    pool->alloc = alloc;
1919    pool->type = type;
1920    pool->shader_visible = shader_visible;
1921    list_inithead(&pool->active_heaps);
1922    list_inithead(&pool->free_heaps);
1923    pool->offset = 0;
1924    pool->desc_sz = ID3D12Device1_GetDescriptorHandleIncrementSize(device->dev, type);
1925 }
1926 
1927 VkResult
dzn_descriptor_heap_pool_alloc_slots(struct dzn_descriptor_heap_pool * pool,struct dzn_device * device,uint32_t desc_count,struct dzn_descriptor_heap ** heap,uint32_t * first_slot)1928 dzn_descriptor_heap_pool_alloc_slots(struct dzn_descriptor_heap_pool *pool,
1929                                      struct dzn_device *device, uint32_t desc_count,
1930                                      struct dzn_descriptor_heap **heap,
1931                                      uint32_t *first_slot)
1932 {
1933    struct dzn_descriptor_heap *last_heap =
1934       list_is_empty(&pool->active_heaps) ?
1935       NULL :
1936       &(list_last_entry(&pool->active_heaps, struct dzn_descriptor_heap_pool_entry, link)->heap);
1937    uint32_t last_heap_desc_count =
1938       last_heap ? last_heap->desc_count : 0;
1939 
1940    if (pool->offset + desc_count > last_heap_desc_count) {
1941       uint32_t granularity =
1942          (pool->type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV ||
1943           pool->type == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER) ?
1944          64 * 1024 : 4 * 1024;
1945       uint32_t alloc_step = ALIGN_POT(desc_count * pool->desc_sz, granularity);
1946       uint32_t heap_desc_count = MAX2(alloc_step / pool->desc_sz, 16);
1947 
1948       /* Maximum of 2048 samplers per heap when shader_visible is true. */
1949       if (pool->shader_visible &&
1950           pool->type == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER) {
1951          assert(desc_count <= MAX_DESCS_PER_SAMPLER_HEAP);
1952          heap_desc_count = MIN2(heap_desc_count, MAX_DESCS_PER_SAMPLER_HEAP);
1953       }
1954 
1955       struct dzn_descriptor_heap_pool_entry *new_heap = NULL;
1956 
1957       list_for_each_entry_safe(struct dzn_descriptor_heap_pool_entry, entry, &pool->free_heaps, link) {
1958          if (entry->heap.desc_count >= heap_desc_count) {
1959             new_heap = entry;
1960             list_del(&entry->link);
1961             break;
1962          }
1963       }
1964 
1965       if (!new_heap) {
1966          new_heap =
1967             vk_zalloc(pool->alloc, sizeof(*new_heap), 8,
1968                       VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
1969          if (!new_heap)
1970             return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
1971 
1972          VkResult result =
1973             dzn_descriptor_heap_init(&new_heap->heap, device, pool->type,
1974                                      heap_desc_count, pool->shader_visible);
1975          if (result != VK_SUCCESS) {
1976             vk_free(&device->vk.alloc, new_heap);
1977             return result;
1978          }
1979       }
1980 
1981       list_addtail(&new_heap->link, &pool->active_heaps);
1982       pool->offset = 0;
1983       last_heap = &new_heap->heap;
1984    }
1985 
1986    *heap = last_heap;
1987    *first_slot = pool->offset;
1988    pool->offset += desc_count;
1989    return VK_SUCCESS;
1990 }
1991 
1992 void
dzn_descriptor_heap_pool_reset(struct dzn_descriptor_heap_pool * pool)1993 dzn_descriptor_heap_pool_reset(struct dzn_descriptor_heap_pool *pool)
1994 {
1995    pool->offset = 0;
1996    list_splicetail(&pool->active_heaps, &pool->free_heaps);
1997    list_inithead(&pool->active_heaps);
1998 }
1999 
2000 VKAPI_ATTR VkResult VKAPI_CALL
dzn_AllocateDescriptorSets(VkDevice dev,const VkDescriptorSetAllocateInfo * pAllocateInfo,VkDescriptorSet * pDescriptorSets)2001 dzn_AllocateDescriptorSets(VkDevice dev,
2002                            const VkDescriptorSetAllocateInfo *pAllocateInfo,
2003                            VkDescriptorSet *pDescriptorSets)
2004 {
2005    VK_FROM_HANDLE(dzn_descriptor_pool, pool, pAllocateInfo->descriptorPool);
2006    VK_FROM_HANDLE(dzn_device, device, dev);
2007 
2008    const struct VkDescriptorSetVariableDescriptorCountAllocateInfo *variable_counts =
2009       vk_find_struct_const(pAllocateInfo->pNext, DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO);
2010 
2011    uint32_t set_idx = 0;
2012    for (unsigned i = 0; i < pAllocateInfo->descriptorSetCount; i++) {
2013       VK_FROM_HANDLE(dzn_descriptor_set_layout, layout, pAllocateInfo->pSetLayouts[i]);
2014       uint32_t additional_desc_counts[NUM_POOL_TYPES];
2015       additional_desc_counts[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV] =
2016          variable_counts && variable_counts->descriptorSetCount ?
2017          variable_counts->pDescriptorCounts[i] : 0;
2018       additional_desc_counts[D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER] = 0;
2019       uint32_t total_desc_count[NUM_POOL_TYPES];
2020 
2021       dzn_foreach_pool_type(type) {
2022          total_desc_count[type] = layout->range_desc_count[type] + additional_desc_counts[type];
2023          if (pool->used_desc_count[type] + total_desc_count[type] > pool->desc_count[type]) {
2024             dzn_FreeDescriptorSets(dev, pAllocateInfo->descriptorPool, i, pDescriptorSets);
2025             return vk_error(device, VK_ERROR_OUT_OF_POOL_MEMORY);
2026          }
2027       }
2028 
2029       struct dzn_descriptor_set *set = NULL;
2030       bool is_reuse = false;
2031       bool found_any_unused = false;
2032       for (; set_idx < pool->set_count; set_idx++) {
2033          /* Find a free set */
2034          if (!pool->sets[set_idx].layout) {
2035             /* Found one. If it's re-use, check if it has enough space */
2036             if (set_idx < pool->used_set_count) {
2037                is_reuse = true;
2038                found_any_unused = true;
2039                dzn_foreach_pool_type(type) {
2040                   if (pool->sets[set_idx].heap_sizes[type] < total_desc_count[type]) {
2041                      /* No, not enough space */
2042                      is_reuse = false;
2043                      break;
2044                   }
2045                }
2046                if (!is_reuse)
2047                   continue;
2048             }
2049             set = &pool->sets[set_idx];
2050             break;
2051          }
2052       }
2053 
2054       /* Either all occupied, or no free space large enough */
2055       if (!set) {
2056          dzn_FreeDescriptorSets(dev, pAllocateInfo->descriptorPool, i, pDescriptorSets);
2057          return vk_error(device, found_any_unused ? VK_ERROR_FRAGMENTED_POOL : VK_ERROR_OUT_OF_POOL_MEMORY);
2058       }
2059 
2060       /* Couldn't find one for re-use, check if there's enough space at the end */
2061       if (!is_reuse) {
2062          dzn_foreach_pool_type(type) {
2063             if (pool->free_offset[type] + total_desc_count[type] > pool->desc_count[type]) {
2064                dzn_FreeDescriptorSets(dev, pAllocateInfo->descriptorPool, i, pDescriptorSets);
2065                return vk_error(device, VK_ERROR_FRAGMENTED_POOL);
2066             }
2067          }
2068       }
2069 
2070       VkResult result = dzn_descriptor_set_init(set, device, pool, layout, is_reuse, additional_desc_counts);
2071       if (result != VK_SUCCESS) {
2072          dzn_FreeDescriptorSets(dev, pAllocateInfo->descriptorPool, i, pDescriptorSets);
2073          return result;
2074       }
2075 
2076       pool->used_set_count = MAX2(pool->used_set_count, set_idx + 1);
2077       dzn_foreach_pool_type(type)
2078          pool->used_desc_count[type] += total_desc_count[type];
2079       pDescriptorSets[i] = dzn_descriptor_set_to_handle(set);
2080    }
2081 
2082    return VK_SUCCESS;
2083 }
2084 
2085 VKAPI_ATTR VkResult VKAPI_CALL
dzn_FreeDescriptorSets(VkDevice dev,VkDescriptorPool descriptorPool,uint32_t count,const VkDescriptorSet * pDescriptorSets)2086 dzn_FreeDescriptorSets(VkDevice dev,
2087                        VkDescriptorPool descriptorPool,
2088                        uint32_t count,
2089                        const VkDescriptorSet *pDescriptorSets)
2090 {
2091    VK_FROM_HANDLE(dzn_descriptor_pool, pool, descriptorPool);
2092 
2093    for (uint32_t s = 0; s < count; s++) {
2094       VK_FROM_HANDLE(dzn_descriptor_set, set, pDescriptorSets[s]);
2095 
2096       if (!set)
2097          continue;
2098 
2099       assert(set->pool == pool);
2100       dzn_foreach_pool_type(type)
2101          pool->used_desc_count[type] -= set->heap_sizes[type];
2102 
2103       dzn_descriptor_set_finish(set);
2104    }
2105 
2106    pool->used_set_count = 0;
2107    dzn_foreach_pool_type(type)
2108       pool->free_offset[type] = 0;
2109 
2110    for (uint32_t s = 0; s < pool->set_count; s++) {
2111       const struct dzn_descriptor_set *set = &pool->sets[s];
2112 
2113       if (set->layout) {
2114          pool->used_set_count = MAX2(pool->used_set_count, s + 1);
2115          dzn_foreach_pool_type (type) {
2116             pool->free_offset[type] =
2117                MAX2(pool->free_offset[type],
2118                     set->heap_offsets[type] +
2119                     set->heap_sizes[type]);
2120          }
2121       }
2122    }
2123 
2124    return VK_SUCCESS;
2125 }
2126 
2127 static void
dzn_descriptor_set_write(struct dzn_device * device,const VkWriteDescriptorSet * pDescriptorWrite)2128 dzn_descriptor_set_write(struct dzn_device *device,
2129                          const VkWriteDescriptorSet *pDescriptorWrite)
2130 {
2131    VK_FROM_HANDLE(dzn_descriptor_set, set, pDescriptorWrite->dstSet);
2132 
2133    struct dzn_descriptor_set_ptr ptr;
2134 
2135    dzn_descriptor_set_ptr_init(set->layout, &ptr,
2136                                pDescriptorWrite->dstBinding,
2137                                pDescriptorWrite->dstArrayElement);
2138    uint32_t desc_count = pDescriptorWrite->descriptorCount;
2139 
2140    uint32_t d = 0;
2141    bool cube_as_2darray =
2142       pDescriptorWrite->descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
2143 
2144    switch (pDescriptorWrite->descriptorType) {
2145    case VK_DESCRIPTOR_TYPE_SAMPLER:
2146       for (; dzn_descriptor_set_ptr_is_valid(&ptr) && d < desc_count;
2147            dzn_descriptor_set_ptr_move(set->layout, &ptr, 1)) {
2148          assert(dzn_descriptor_set_ptr_get_vk_type(set->layout, &ptr) == pDescriptorWrite->descriptorType);
2149          const VkDescriptorImageInfo *pImageInfo = pDescriptorWrite->pImageInfo + d;
2150          VK_FROM_HANDLE(dzn_sampler, sampler, pImageInfo->sampler);
2151 
2152          if (sampler)
2153             dzn_descriptor_set_ptr_write_sampler_desc(device, set, &ptr, sampler);
2154 
2155          d++;
2156       }
2157       break;
2158    case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
2159       for (; dzn_descriptor_set_ptr_is_valid(&ptr) && d < desc_count;
2160            dzn_descriptor_set_ptr_move(set->layout, &ptr, 1)) {
2161          assert(dzn_descriptor_set_ptr_get_vk_type(set->layout, &ptr) == pDescriptorWrite->descriptorType);
2162          const VkDescriptorImageInfo *pImageInfo = pDescriptorWrite->pImageInfo + d;
2163          VK_FROM_HANDLE(dzn_sampler, sampler, pImageInfo->sampler);
2164          VK_FROM_HANDLE(dzn_image_view, iview, pImageInfo->imageView);
2165 
2166          if (sampler)
2167             dzn_descriptor_set_ptr_write_sampler_desc(device, set, &ptr, sampler);
2168 
2169          if (iview)
2170             dzn_descriptor_set_ptr_write_image_view_desc(device, pDescriptorWrite->descriptorType,
2171                                                          set, &ptr, cube_as_2darray, iview);
2172 
2173          d++;
2174       }
2175       break;
2176 
2177    case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
2178    case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
2179    case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
2180       for (; dzn_descriptor_set_ptr_is_valid(&ptr) && d < desc_count;
2181            dzn_descriptor_set_ptr_move(set->layout, &ptr, 1)) {
2182          assert(dzn_descriptor_set_ptr_get_vk_type(set->layout, &ptr) == pDescriptorWrite->descriptorType);
2183          const VkDescriptorImageInfo *pImageInfo = pDescriptorWrite->pImageInfo + d;
2184          VK_FROM_HANDLE(dzn_image_view, iview, pImageInfo->imageView);
2185 
2186          if (iview)
2187             dzn_descriptor_set_ptr_write_image_view_desc(device, pDescriptorWrite->descriptorType,
2188                                                          set, &ptr, cube_as_2darray, iview);
2189 
2190          d++;
2191       }
2192       break;
2193    case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
2194    case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
2195       for (; dzn_descriptor_set_ptr_is_valid(&ptr) && d < desc_count;
2196            dzn_descriptor_set_ptr_move(set->layout, &ptr, 1)) {
2197          assert(dzn_descriptor_set_ptr_get_vk_type(set->layout, &ptr) == pDescriptorWrite->descriptorType);
2198          const VkDescriptorBufferInfo *binfo = &pDescriptorWrite->pBufferInfo[d];
2199          struct dzn_buffer_desc desc = {
2200             pDescriptorWrite->descriptorType,
2201             dzn_buffer_from_handle(binfo->buffer),
2202             binfo->range, binfo->offset
2203          };
2204 
2205          if (desc.buffer)
2206             dzn_descriptor_set_ptr_write_buffer_desc(device, pDescriptorWrite->descriptorType, set, &ptr, &desc);
2207 
2208          d++;
2209       }
2210       break;
2211 
2212    case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
2213    case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
2214       for (; dzn_descriptor_set_ptr_is_valid(&ptr) && d < desc_count;
2215            dzn_descriptor_set_ptr_move(set->layout, &ptr, 1)) {
2216          assert(dzn_descriptor_set_ptr_get_vk_type(set->layout, &ptr) == pDescriptorWrite->descriptorType);
2217          const VkDescriptorBufferInfo *binfo = &pDescriptorWrite->pBufferInfo[d];
2218          struct dzn_buffer_desc desc = {
2219             pDescriptorWrite->descriptorType,
2220             dzn_buffer_from_handle(binfo->buffer),
2221             binfo->range, binfo->offset
2222          };
2223 
2224          if (desc.buffer)
2225             dzn_descriptor_set_ptr_write_dynamic_buffer_desc(device, set, &ptr, &desc);
2226 
2227          d++;
2228       }
2229       break;
2230 
2231    case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
2232    case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
2233       for (; dzn_descriptor_set_ptr_is_valid(&ptr) && d < desc_count;
2234            dzn_descriptor_set_ptr_move(set->layout, &ptr, 1)) {
2235          assert(dzn_descriptor_set_ptr_get_vk_type(set->layout, &ptr) == pDescriptorWrite->descriptorType);
2236          VK_FROM_HANDLE(dzn_buffer_view, bview, pDescriptorWrite->pTexelBufferView[d]);
2237 
2238          if (bview)
2239             dzn_descriptor_set_ptr_write_buffer_view_desc(device, pDescriptorWrite->descriptorType,
2240                                                           set, &ptr, bview);
2241 
2242          d++;
2243       }
2244       break;
2245 
2246    default:
2247       unreachable("invalid descriptor type");
2248       break;
2249    }
2250 
2251    assert(d == pDescriptorWrite->descriptorCount);
2252 }
2253 
2254 static void
dzn_descriptor_set_copy(struct dzn_device * device,const VkCopyDescriptorSet * pDescriptorCopy)2255 dzn_descriptor_set_copy(struct dzn_device *device,
2256                         const VkCopyDescriptorSet *pDescriptorCopy)
2257 {
2258    VK_FROM_HANDLE(dzn_descriptor_set, src_set, pDescriptorCopy->srcSet);
2259    VK_FROM_HANDLE(dzn_descriptor_set, dst_set, pDescriptorCopy->dstSet);
2260    struct dzn_descriptor_set_ptr src_ptr, dst_ptr;
2261 
2262    dzn_descriptor_set_ptr_init(src_set->layout, &src_ptr,
2263                                pDescriptorCopy->srcBinding,
2264                                pDescriptorCopy->srcArrayElement);
2265    dzn_descriptor_set_ptr_init(dst_set->layout, &dst_ptr,
2266                                pDescriptorCopy->dstBinding,
2267                                pDescriptorCopy->dstArrayElement);
2268 
2269    uint32_t copied_count = 0;
2270 
2271    while (dzn_descriptor_set_ptr_is_valid(&src_ptr) &&
2272           dzn_descriptor_set_ptr_is_valid(&dst_ptr) &&
2273           copied_count < pDescriptorCopy->descriptorCount) {
2274       VkDescriptorType src_type =
2275          dzn_descriptor_set_ptr_get_vk_type(src_set->layout, &src_ptr);
2276       ASSERTED VkDescriptorType dst_type =
2277          dzn_descriptor_set_ptr_get_vk_type(dst_set->layout, &dst_ptr);
2278 
2279       assert(src_type == dst_type);
2280       uint32_t count =
2281          MIN2(dzn_descriptor_set_remaining_descs_in_binding(src_set->layout, &src_ptr),
2282               dzn_descriptor_set_remaining_descs_in_binding(dst_set->layout, &dst_ptr));
2283 
2284       if (src_type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||
2285           src_type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) {
2286          uint32_t src_idx =
2287             dzn_descriptor_set_ptr_get_buffer_idx(src_set->layout, &src_ptr);
2288          uint32_t dst_idx =
2289             dzn_descriptor_set_ptr_get_buffer_idx(dst_set->layout, &dst_ptr);
2290 
2291          memcpy(&dst_set->dynamic_buffers[dst_idx],
2292                 &src_set->dynamic_buffers[src_idx],
2293                 sizeof(*dst_set->dynamic_buffers) * count);
2294       } else {
2295          dzn_foreach_pool_type(type) {
2296             uint32_t src_heap_offset =
2297                dzn_descriptor_set_ptr_get_heap_offset(src_set->layout, type, &src_ptr, false, device->bindless);
2298             uint32_t dst_heap_offset =
2299                dzn_descriptor_set_ptr_get_heap_offset(dst_set->layout, type, &dst_ptr, false, device->bindless);
2300 
2301             if (src_heap_offset == ~0) {
2302                assert(dst_heap_offset == ~0);
2303                continue;
2304             }
2305 
2306             src_heap_offset += src_set->heap_offsets[type];
2307             dst_heap_offset += dst_set->heap_offsets[type];
2308 
2309             if (device->bindless) {
2310                memcpy((void *)&dst_set->pool->bindless.map[dst_heap_offset],
2311                       (const void *)&src_set->pool->bindless.map[src_heap_offset],
2312                       sizeof(src_set->pool->bindless.map[0]) * count);
2313                /* There's never a reason to loop and memcpy again for bindless */
2314                break;
2315             } else {
2316                dzn_descriptor_heap_copy(device,
2317                                         &dst_set->pool->heaps[type],
2318                                         dst_heap_offset,
2319                                         &src_set->pool->heaps[type],
2320                                         src_heap_offset,
2321                                         count, type);
2322             }
2323 
2324             if (dzn_descriptor_type_depends_on_shader_usage(src_type, device->bindless)) {
2325                src_heap_offset = src_set->heap_offsets[type] +
2326                   dzn_descriptor_set_ptr_get_heap_offset(src_set->layout, type, &src_ptr, true, device->bindless);
2327                dst_heap_offset = dst_set->heap_offsets[type] +
2328                   dzn_descriptor_set_ptr_get_heap_offset(dst_set->layout, type, &dst_ptr, true, device->bindless);
2329                assert(src_heap_offset != ~0);
2330                assert(dst_heap_offset != ~0);
2331                dzn_descriptor_heap_copy(device,
2332                                         &dst_set->pool->heaps[type],
2333                                         dst_heap_offset,
2334                                         &src_set->pool->heaps[type],
2335                                         src_heap_offset,
2336                                         count, type);
2337             }
2338          }
2339       }
2340 
2341       dzn_descriptor_set_ptr_move(src_set->layout, &src_ptr, count);
2342       dzn_descriptor_set_ptr_move(dst_set->layout, &dst_ptr, count);
2343       copied_count += count;
2344    }
2345 
2346    assert(copied_count == pDescriptorCopy->descriptorCount);
2347 }
2348 
2349 VKAPI_ATTR void VKAPI_CALL
dzn_UpdateDescriptorSets(VkDevice _device,uint32_t descriptorWriteCount,const VkWriteDescriptorSet * pDescriptorWrites,uint32_t descriptorCopyCount,const VkCopyDescriptorSet * pDescriptorCopies)2350 dzn_UpdateDescriptorSets(VkDevice _device,
2351                          uint32_t descriptorWriteCount,
2352                          const VkWriteDescriptorSet *pDescriptorWrites,
2353                          uint32_t descriptorCopyCount,
2354                          const VkCopyDescriptorSet *pDescriptorCopies)
2355 {
2356    VK_FROM_HANDLE(dzn_device, device, _device);
2357    for (unsigned i = 0; i < descriptorWriteCount; i++)
2358       dzn_descriptor_set_write(device, &pDescriptorWrites[i]);
2359 
2360    for (unsigned i = 0; i < descriptorCopyCount; i++)
2361       dzn_descriptor_set_copy(device, &pDescriptorCopies[i]);
2362 }
2363 
2364 static void
dzn_descriptor_update_template_destroy(struct dzn_descriptor_update_template * templ,const VkAllocationCallbacks * alloc)2365 dzn_descriptor_update_template_destroy(struct dzn_descriptor_update_template *templ,
2366                                        const VkAllocationCallbacks *alloc)
2367 {
2368    if (!templ)
2369       return;
2370 
2371    struct dzn_device *device =
2372       container_of(templ->base.device, struct dzn_device, vk);
2373 
2374    vk_object_base_finish(&templ->base);
2375    vk_free2(&device->vk.alloc, alloc, templ);
2376 }
2377 
2378 static VkResult
dzn_descriptor_update_template_create(struct dzn_device * device,const VkDescriptorUpdateTemplateCreateInfo * info,const VkAllocationCallbacks * alloc,VkDescriptorUpdateTemplate * out)2379 dzn_descriptor_update_template_create(struct dzn_device *device,
2380                                       const VkDescriptorUpdateTemplateCreateInfo *info,
2381                                       const VkAllocationCallbacks *alloc,
2382                                       VkDescriptorUpdateTemplate *out)
2383 {
2384    assert(info->templateType == VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET);
2385 
2386    VK_FROM_HANDLE(dzn_descriptor_set_layout, set_layout, info->descriptorSetLayout);
2387 
2388    uint32_t entry_count = 0;
2389    for (uint32_t e = 0; e < info->descriptorUpdateEntryCount; e++) {
2390       struct dzn_descriptor_set_ptr ptr;
2391       dzn_descriptor_set_ptr_init(set_layout, &ptr,
2392                                   info->pDescriptorUpdateEntries[e].dstBinding,
2393                                   info->pDescriptorUpdateEntries[e].dstArrayElement);
2394       uint32_t desc_count = info->pDescriptorUpdateEntries[e].descriptorCount;
2395       ASSERTED VkDescriptorType type = info->pDescriptorUpdateEntries[e].descriptorType;
2396       uint32_t d = 0;
2397 
2398       while (dzn_descriptor_set_ptr_is_valid(&ptr) && d < desc_count) {
2399          uint32_t ndescs = dzn_descriptor_set_remaining_descs_in_binding(set_layout, &ptr);
2400 
2401          assert(dzn_descriptor_set_ptr_get_vk_type(set_layout, &ptr) == type);
2402          d += ndescs;
2403          dzn_descriptor_set_ptr_move(set_layout, &ptr, ndescs);
2404          entry_count++;
2405       }
2406 
2407       assert(d >= desc_count);
2408    }
2409 
2410    VK_MULTIALLOC(ma);
2411    VK_MULTIALLOC_DECL(&ma, struct dzn_descriptor_update_template, templ, 1);
2412    VK_MULTIALLOC_DECL(&ma, struct dzn_descriptor_update_template_entry, entries, entry_count);
2413 
2414    if (!vk_multialloc_zalloc2(&ma, &device->vk.alloc, alloc,
2415                               VK_SYSTEM_ALLOCATION_SCOPE_OBJECT))
2416       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
2417 
2418    vk_object_base_init(&device->vk, &templ->base, VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE);
2419    templ->entry_count = entry_count;
2420    templ->entries = entries;
2421 
2422    struct dzn_descriptor_update_template_entry *entry = entries;
2423 
2424    for (uint32_t e = 0; e < info->descriptorUpdateEntryCount; e++) {
2425       struct dzn_descriptor_set_ptr ptr;
2426       dzn_descriptor_set_ptr_init(set_layout, &ptr,
2427                                   info->pDescriptorUpdateEntries[e].dstBinding,
2428                                   info->pDescriptorUpdateEntries[e].dstArrayElement);
2429       uint32_t desc_count = info->pDescriptorUpdateEntries[e].descriptorCount;
2430       VkDescriptorType type = info->pDescriptorUpdateEntries[e].descriptorType;
2431       size_t user_data_offset = info->pDescriptorUpdateEntries[e].offset;
2432       size_t user_data_stride = info->pDescriptorUpdateEntries[e].stride;
2433       uint32_t d = 0;
2434 
2435       while (dzn_descriptor_set_ptr_is_valid(&ptr) && d < desc_count) {
2436          uint32_t ndescs = dzn_descriptor_set_remaining_descs_in_binding(set_layout, &ptr);
2437 
2438          entry->type = type;
2439          entry->desc_count = MIN2(desc_count - d, ndescs);
2440          entry->user_data.stride = user_data_stride;
2441          entry->user_data.offset = user_data_offset;
2442          memset(&entry->heap_offsets, ~0, sizeof(entry->heap_offsets));
2443 
2444          assert(dzn_descriptor_set_ptr_get_vk_type(set_layout, &ptr) == type);
2445          if (dzn_desc_type_has_sampler(type)) {
2446             entry->heap_offsets.sampler =
2447                dzn_descriptor_set_ptr_get_heap_offset(set_layout,
2448                                                       D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER,
2449                                                       &ptr, false, device->bindless);
2450          }
2451 
2452          if (is_dynamic_desc_type(type)) {
2453             entry->buffer_idx = dzn_descriptor_set_ptr_get_buffer_idx(set_layout, &ptr);
2454          } else if (type != VK_DESCRIPTOR_TYPE_SAMPLER) {
2455             if (is_buffer_desc_type_without_view(type))
2456                entry->buffer_idx = dzn_descriptor_set_ptr_get_buffer_idx(set_layout, &ptr);
2457 
2458             entry->heap_offsets.cbv_srv_uav =
2459                dzn_descriptor_set_ptr_get_heap_offset(set_layout,
2460                                                       D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
2461                                                       &ptr, false, device->bindless);
2462             if (dzn_descriptor_type_depends_on_shader_usage(type, device->bindless)) {
2463                entry->heap_offsets.extra_srv =
2464                   dzn_descriptor_set_ptr_get_heap_offset(set_layout,
2465                                                          D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
2466                                                          &ptr, true, device->bindless);
2467             }
2468          }
2469 
2470          d += ndescs;
2471          dzn_descriptor_set_ptr_move(set_layout, &ptr, ndescs);
2472          user_data_offset += user_data_stride * ndescs;
2473          ++entry;
2474       }
2475    }
2476 
2477    *out = dzn_descriptor_update_template_to_handle(templ);
2478    return VK_SUCCESS;
2479 }
2480 
2481 VKAPI_ATTR VkResult VKAPI_CALL
dzn_CreateDescriptorUpdateTemplate(VkDevice device,const VkDescriptorUpdateTemplateCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDescriptorUpdateTemplate * pDescriptorUpdateTemplate)2482 dzn_CreateDescriptorUpdateTemplate(VkDevice device,
2483                                    const VkDescriptorUpdateTemplateCreateInfo *pCreateInfo,
2484                                    const VkAllocationCallbacks *pAllocator,
2485                                    VkDescriptorUpdateTemplate *pDescriptorUpdateTemplate)
2486 {
2487    return dzn_descriptor_update_template_create(dzn_device_from_handle(device),
2488                                                 pCreateInfo, pAllocator,
2489                                                 pDescriptorUpdateTemplate);
2490 }
2491 
2492 VKAPI_ATTR void VKAPI_CALL
dzn_DestroyDescriptorUpdateTemplate(VkDevice device,VkDescriptorUpdateTemplate descriptorUpdateTemplate,const VkAllocationCallbacks * pAllocator)2493 dzn_DestroyDescriptorUpdateTemplate(VkDevice device,
2494                                     VkDescriptorUpdateTemplate descriptorUpdateTemplate,
2495                                     const VkAllocationCallbacks *pAllocator)
2496 {
2497    dzn_descriptor_update_template_destroy(dzn_descriptor_update_template_from_handle(descriptorUpdateTemplate),
2498                                           pAllocator);
2499 }
2500 
2501 static const void *
dzn_descriptor_update_template_get_desc_data(const struct dzn_descriptor_update_template * templ,uint32_t e,uint32_t d,const void * user_data)2502 dzn_descriptor_update_template_get_desc_data(const struct dzn_descriptor_update_template *templ,
2503                                              uint32_t e, uint32_t d,
2504                                              const void *user_data)
2505 {
2506    return (const void *)((const uint8_t *)user_data +
2507                          templ->entries[e].user_data.offset +
2508                          (d * templ->entries[e].user_data.stride));
2509 }
2510 
2511 VKAPI_ATTR void VKAPI_CALL
dzn_UpdateDescriptorSetWithTemplate(VkDevice _device,VkDescriptorSet descriptorSet,VkDescriptorUpdateTemplate descriptorUpdateTemplate,const void * pData)2512 dzn_UpdateDescriptorSetWithTemplate(VkDevice _device,
2513                                     VkDescriptorSet descriptorSet,
2514                                     VkDescriptorUpdateTemplate descriptorUpdateTemplate,
2515                                     const void *pData)
2516 {
2517    VK_FROM_HANDLE(dzn_device, device, _device);
2518    VK_FROM_HANDLE(dzn_descriptor_set, set, descriptorSet);
2519    VK_FROM_HANDLE(dzn_descriptor_update_template, templ, descriptorUpdateTemplate);
2520 
2521    for (uint32_t e = 0; e < templ->entry_count; e++) {
2522       const struct dzn_descriptor_update_template_entry *entry = &templ->entries[e];
2523       bool cube_as_2darray =
2524          entry->type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
2525 
2526       switch (entry->type) {
2527       case VK_DESCRIPTOR_TYPE_SAMPLER:
2528          for (uint32_t d = 0; d < entry->desc_count; d++) {
2529             const VkDescriptorImageInfo *info = (const VkDescriptorImageInfo *)
2530                dzn_descriptor_update_template_get_desc_data(templ, e, d, pData);
2531             VK_FROM_HANDLE(dzn_sampler, sampler, info->sampler);
2532 
2533             if (sampler)
2534                dzn_descriptor_set_write_sampler_desc(device, set, entry->heap_offsets.sampler + d, sampler);
2535          }
2536          break;
2537 
2538       case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
2539          for (uint32_t d = 0; d < entry->desc_count; d++) {
2540             const VkDescriptorImageInfo *info = (const VkDescriptorImageInfo *)
2541                dzn_descriptor_update_template_get_desc_data(templ, e, d, pData);
2542             VK_FROM_HANDLE(dzn_sampler, sampler, info->sampler);
2543             VK_FROM_HANDLE(dzn_image_view, iview, info->imageView);
2544 
2545             if (sampler)
2546                dzn_descriptor_set_write_sampler_desc(device, set, entry->heap_offsets.sampler + d, sampler);
2547 
2548             if (iview)
2549                dzn_descriptor_set_write_image_view_desc(device, entry->type, set,
2550                                                         entry->heap_offsets.cbv_srv_uav + d, ~0,
2551                                                         cube_as_2darray, iview);
2552          }
2553          break;
2554 
2555       case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
2556       case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
2557       case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
2558          for (uint32_t d = 0; d < entry->desc_count; d++) {
2559             const VkDescriptorImageInfo *info = (const VkDescriptorImageInfo *)
2560                dzn_descriptor_update_template_get_desc_data(templ, e, d, pData);
2561             uint32_t heap_offset = entry->heap_offsets.cbv_srv_uav + d;
2562             uint32_t alt_heap_offset =
2563                dzn_descriptor_type_depends_on_shader_usage(entry->type, device->bindless) ?
2564                entry->heap_offsets.extra_srv + d : ~0;
2565             VK_FROM_HANDLE(dzn_image_view, iview, info->imageView);
2566 
2567             if (iview)
2568                dzn_descriptor_set_write_image_view_desc(device, entry->type, set,
2569                                                         heap_offset, alt_heap_offset,
2570                                                         cube_as_2darray, iview);
2571          }
2572          break;
2573       case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
2574       case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
2575          for (uint32_t d = 0; d < entry->desc_count; d++) {
2576             const VkDescriptorBufferInfo *info = (const VkDescriptorBufferInfo *)
2577                dzn_descriptor_update_template_get_desc_data(templ, e, d, pData);
2578             uint32_t heap_offset = entry->heap_offsets.cbv_srv_uav + d;
2579             uint32_t alt_heap_offset =
2580                dzn_descriptor_type_depends_on_shader_usage(entry->type, device->bindless) ?
2581                entry->heap_offsets.extra_srv + d : ~0;
2582 
2583             struct dzn_buffer_desc desc = {
2584                entry->type,
2585                dzn_buffer_from_handle(info->buffer),
2586                info->range, info->offset
2587             };
2588 
2589             if (desc.buffer)
2590                dzn_descriptor_set_write_buffer_desc(device, entry->type, set, heap_offset,
2591                                                     alt_heap_offset, &desc);
2592          }
2593          break;
2594 
2595       case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
2596       case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
2597          for (uint32_t d = 0; d < entry->desc_count; d++) {
2598             const VkDescriptorBufferInfo *info = (const VkDescriptorBufferInfo *)
2599                dzn_descriptor_update_template_get_desc_data(templ, e, d, pData);
2600             uint32_t dyn_buf_idx = entry->buffer_idx + d;
2601 
2602             struct dzn_buffer_desc desc = {
2603                entry->type,
2604                dzn_buffer_from_handle(info->buffer),
2605                info->range, info->offset
2606             };
2607 
2608             if (desc.buffer)
2609                dzn_descriptor_set_write_dynamic_buffer_desc(device, set, dyn_buf_idx, &desc);
2610          }
2611          break;
2612 
2613       case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
2614       case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
2615          for (uint32_t d = 0; d < entry->desc_count; d++) {
2616             VkBufferView *info = (VkBufferView *)
2617                dzn_descriptor_update_template_get_desc_data(templ, e, d, pData);
2618             VK_FROM_HANDLE(dzn_buffer_view, bview, *info);
2619             uint32_t heap_offset = entry->heap_offsets.cbv_srv_uav + d;
2620             uint32_t alt_heap_offset =
2621                dzn_descriptor_type_depends_on_shader_usage(entry->type, device->bindless) ?
2622                entry->heap_offsets.extra_srv + d : ~0;
2623 
2624             if (bview)
2625                dzn_descriptor_set_write_buffer_view_desc(device, entry->type, set, heap_offset, alt_heap_offset, bview);
2626          }
2627          break;
2628 
2629       default:
2630          unreachable("invalid descriptor type");
2631       }
2632    }
2633 }
2634