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