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