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