From 84d632f19490b91004d5c1b4270c306c2d188646 Mon Sep 17 00:00:00 2001 From: Hans-Kristian Arntzen Date: Tue, 22 Feb 2022 15:35:23 +0100 Subject: [PATCH] vkd3d: Rewrite memory layout for resource descriptors. Tune memory layout so that we can deduce various information without making a single pointer dereference: - d3d12_descriptor_heap* - heap offset - Pointer to various side data structures we need to keep around. Instead of having one big 64 byte data structure with tons of padding, tune it down to 32 + 8 bytes per descriptor of extra dummy data. To make all of this work, use a somewhat clever encoding scheme for CPU VA where lower bits store number of active bits used to encode descriptor offset. From there, we can mask away bits to recover d3d12_descriptor_heap. Metadata is stored inline in one big allocation, and we can just offset from there based on extracted log2i_ceil(descriptor count). Signed-off-by: Hans-Kristian Arntzen --- libs/vkd3d/command.c | 76 +++-- libs/vkd3d/device.c | 24 +- libs/vkd3d/device_vkd3d_ext.c | 28 +- libs/vkd3d/raytracing_pipeline.c | 2 +- libs/vkd3d/resource.c | 548 +++++++++++++++++-------------- libs/vkd3d/vkd3d_private.h | 111 ++++--- 6 files changed, 443 insertions(+), 346 deletions(-) diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c index fabde7cc..94e98960 100644 --- a/libs/vkd3d/command.c +++ b/libs/vkd3d/command.c @@ -4364,7 +4364,8 @@ static void d3d12_command_list_reset_api_state(struct d3d12_command_list *list, memset(list->so_counter_buffers, 0, sizeof(list->so_counter_buffers)); memset(list->so_counter_buffer_offsets, 0, sizeof(list->so_counter_buffer_offsets)); - list->cbv_srv_uav_descriptors = NULL; + list->cbv_srv_uav_descriptors_types = NULL; + list->cbv_srv_uav_descriptors_view = NULL; list->vrs_image = NULL; list->workaround_state.has_pending_color_write = false; @@ -5047,9 +5048,10 @@ static void d3d12_command_list_update_hoisted_descriptors(struct d3d12_command_l { const struct d3d12_root_signature *rs = bindings->root_signature; const struct vkd3d_descriptor_hoist_desc *hoist_desc; + const struct vkd3d_descriptor_metadata_types *types; struct vkd3d_root_descriptor_info *root_parameter; + const struct vkd3d_descriptor_metadata_view *view; union vkd3d_descriptor_info *info; - const struct d3d12_desc *desc; unsigned int i; /* We don't track dirty table index, just update every hoisted descriptor. @@ -5058,9 +5060,13 @@ static void d3d12_command_list_update_hoisted_descriptors(struct d3d12_command_l { hoist_desc = &rs->hoist_info.desc[i]; - desc = list->cbv_srv_uav_descriptors; - if (desc) - desc += bindings->descriptor_tables[hoist_desc->table_index] + hoist_desc->table_offset; + view = list->cbv_srv_uav_descriptors_view; + types = list->cbv_srv_uav_descriptors_types; + if (view) + { + view += bindings->descriptor_tables[hoist_desc->table_index] + hoist_desc->table_offset; + types += bindings->descriptor_tables[hoist_desc->table_index] + hoist_desc->table_offset; + } root_parameter = &bindings->root_descriptors[hoist_desc->parameter_index]; @@ -5069,10 +5075,10 @@ static void d3d12_command_list_update_hoisted_descriptors(struct d3d12_command_l root_parameter->vk_descriptor_type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; info = &root_parameter->info; - if (desc && (desc->metadata.flags & VKD3D_DESCRIPTOR_FLAG_OFFSET_RANGE)) + if (types && (types->flags & VKD3D_DESCRIPTOR_FLAG_OFFSET_RANGE)) { /* Buffer descriptors must be valid on recording time. */ - info->buffer = desc->info.buffer; + info->buffer = view->info.buffer; } else { @@ -7421,7 +7427,12 @@ static void STDMETHODCALLTYPE d3d12_command_list_SetDescriptorHeaps(d3d12_comman /* In case we need to hoist buffer descriptors. */ if (heap->desc.Type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV) - list->cbv_srv_uav_descriptors = (const struct d3d12_desc *) heap->descriptors; + { + struct d3d12_desc_split d; + d = d3d12_desc_decode_va(heap->cpu_va.ptr); + list->cbv_srv_uav_descriptors_types = d.types; + list->cbv_srv_uav_descriptors_view = d.view; + } } for (i = 0; i < ARRAY_SIZE(list->pipeline_bindings); i++) @@ -8165,7 +8176,8 @@ struct vkd3d_clear_uav_info } u; }; -static void d3d12_command_list_clear_uav(struct d3d12_command_list *list, const struct d3d12_desc *desc, +static void d3d12_command_list_clear_uav(struct d3d12_command_list *list, + const struct d3d12_desc_split *d, struct d3d12_resource *resource, const struct vkd3d_clear_uav_info *args, const VkClearColorValue *clear_color, UINT rect_count, const D3D12_RECT *rects) { @@ -8261,14 +8273,14 @@ static void d3d12_command_list_clear_uav(struct d3d12_command_list *list, const if (d3d12_resource_is_buffer(resource)) { - const struct vkd3d_bound_buffer_range *ranges = desc->heap->buffer_ranges.host_ptr; + const struct vkd3d_bound_buffer_range *ranges = d->heap->buffer_ranges.host_ptr; if (args->has_view) { if (list->device->bindless_state.flags & VKD3D_TYPED_OFFSET_BUFFER) { - extra_offset = ranges[desc->heap_offset].element_offset; - full_rect.right = ranges[desc->heap_offset].element_count; + extra_offset = ranges[d->offset].element_offset; + full_rect.right = ranges[d->offset].element_count; } else { @@ -8280,8 +8292,8 @@ static void d3d12_command_list_clear_uav(struct d3d12_command_list *list, const } else if (list->device->bindless_state.flags & VKD3D_SSBO_OFFSET_BUFFER) { - extra_offset = ranges[desc->heap_offset].byte_offset / sizeof(uint32_t); - full_rect.right = ranges[desc->heap_offset].byte_count / sizeof(uint32_t); + extra_offset = ranges[d->offset].byte_offset / sizeof(uint32_t); + full_rect.right = ranges[d->offset].byte_count / sizeof(uint32_t); } else full_rect.right = args->u.buffer.range / sizeof(uint32_t); @@ -8379,19 +8391,19 @@ static const struct vkd3d_format *vkd3d_clear_uav_find_uint_format(struct d3d12_ return vkd3d_get_format(device, uint_format, false); } -static bool vkd3d_clear_uav_info_from_desc(struct vkd3d_clear_uav_info *args, const struct d3d12_desc *desc) +static inline bool vkd3d_clear_uav_info_from_desc(struct vkd3d_clear_uav_info *args, const struct d3d12_desc_split *d) { - if (desc->metadata.flags & VKD3D_DESCRIPTOR_FLAG_VIEW) + if (d->types->flags & VKD3D_DESCRIPTOR_FLAG_VIEW) { args->has_view = true; - args->u.view = desc->info.view; + args->u.view = d->view->info.view; return true; } - else if (desc->metadata.flags & VKD3D_DESCRIPTOR_FLAG_OFFSET_RANGE) + else if (d->types->flags & VKD3D_DESCRIPTOR_FLAG_OFFSET_RANGE) { args->has_view = false; - args->u.buffer.offset = desc->info.buffer.offset; - args->u.buffer.range = desc->info.buffer.range; + args->u.buffer.offset = d->view->info.buffer.offset; + args->u.buffer.range = d->view->info.buffer.range; return true; } else @@ -8438,11 +8450,11 @@ static void STDMETHODCALLTYPE d3d12_command_list_ClearUnorderedAccessViewUint(d3 const UINT values[4], UINT rect_count, const D3D12_RECT *rects) { struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList(iface); - const struct d3d12_desc *desc = d3d12_desc_from_cpu_handle(cpu_handle); const struct vkd3d_format *uint_format; struct vkd3d_view *inline_view = NULL; struct d3d12_resource *resource_impl; struct vkd3d_clear_uav_info args; + struct d3d12_desc_split d; VkClearColorValue color; TRACE("iface %p, gpu_handle %#"PRIx64", cpu_handle %lx, resource %p, values %p, rect_count %u, rects %p.\n", @@ -8450,17 +8462,18 @@ static void STDMETHODCALLTYPE d3d12_command_list_ClearUnorderedAccessViewUint(d3 memcpy(color.uint32, values, sizeof(color.uint32)); + d = d3d12_desc_decode_va(cpu_handle.ptr); resource_impl = impl_from_ID3D12Resource(resource); - if (!vkd3d_clear_uav_info_from_desc(&args, desc)) + if (!vkd3d_clear_uav_info_from_desc(&args, &d)) return; if (args.has_view) - color = vkd3d_fixup_clear_uav_swizzle(list->device, desc->info.view->format->dxgi_format, color); + color = vkd3d_fixup_clear_uav_swizzle(list->device, d.view->info.view->format->dxgi_format, color); - if (args.has_view && desc->info.view->format->type != VKD3D_FORMAT_TYPE_UINT) + if (args.has_view && d.view->info.view->format->type != VKD3D_FORMAT_TYPE_UINT) { - const struct vkd3d_view *base_view = desc->info.view; + const struct vkd3d_view *base_view = d.view->info.view; uint_format = vkd3d_clear_uav_find_uint_format(list->device, base_view->format->dxgi_format); if (!uint_format) @@ -8514,10 +8527,10 @@ static void STDMETHODCALLTYPE d3d12_command_list_ClearUnorderedAccessViewUint(d3 } else if (args.has_view) { - vkd3d_mask_uint_clear_color(color.uint32, desc->info.view->format->vk_format); + vkd3d_mask_uint_clear_color(color.uint32, d.view->info.view->format->vk_format); } - d3d12_command_list_clear_uav(list, desc, resource_impl, &args, &color, rect_count, rects); + d3d12_command_list_clear_uav(list, &d, resource_impl, &args, &color, rect_count, rects); if (inline_view) { @@ -8531,24 +8544,25 @@ static void STDMETHODCALLTYPE d3d12_command_list_ClearUnorderedAccessViewFloat(d const float values[4], UINT rect_count, const D3D12_RECT *rects) { struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList(iface); - const struct d3d12_desc *desc = d3d12_desc_from_cpu_handle(cpu_handle); struct d3d12_resource *resource_impl; struct vkd3d_clear_uav_info args; + struct d3d12_desc_split d; VkClearColorValue color; TRACE("iface %p, gpu_handle %#"PRIx64", cpu_handle %lx, resource %p, values %p, rect_count %u, rects %p.\n", iface, gpu_handle.ptr, cpu_handle.ptr, resource, values, rect_count, rects); + d = d3d12_desc_decode_va(cpu_handle.ptr); memcpy(color.float32, values, sizeof(color.float32)); resource_impl = impl_from_ID3D12Resource(resource); - if (!vkd3d_clear_uav_info_from_desc(&args, desc)) + if (!vkd3d_clear_uav_info_from_desc(&args, &d)) return; if (args.has_view) - color = vkd3d_fixup_clear_uav_swizzle(list->device, desc->info.view->format->dxgi_format, color); + color = vkd3d_fixup_clear_uav_swizzle(list->device, d.view->info.view->format->dxgi_format, color); - d3d12_command_list_clear_uav(list, desc, resource_impl, &args, &color, rect_count, rects); + d3d12_command_list_clear_uav(list, &d, resource_impl, &args, &color, rect_count, rects); } static void STDMETHODCALLTYPE d3d12_command_list_DiscardResource(d3d12_command_list_iface *iface, diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c index f281d595..09d08938 100644 --- a/libs/vkd3d/device.c +++ b/libs/vkd3d/device.c @@ -3840,7 +3840,7 @@ static void STDMETHODCALLTYPE d3d12_device_CreateConstantBufferView(d3d12_device TRACE("iface %p, desc %p, descriptor %#lx.\n", iface, desc, descriptor.ptr); - d3d12_desc_create_cbv(d3d12_desc_from_cpu_handle(descriptor), device, desc); + d3d12_desc_create_cbv(descriptor.ptr, device, desc); } static void STDMETHODCALLTYPE d3d12_device_CreateShaderResourceView(d3d12_device_iface *iface, @@ -3852,8 +3852,7 @@ static void STDMETHODCALLTYPE d3d12_device_CreateShaderResourceView(d3d12_device TRACE("iface %p, resource %p, desc %p, descriptor %#lx.\n", iface, resource, desc, descriptor.ptr); - d3d12_desc_create_srv(d3d12_desc_from_cpu_handle(descriptor), - device, impl_from_ID3D12Resource(resource), desc); + d3d12_desc_create_srv(descriptor.ptr, device, impl_from_ID3D12Resource(resource), desc); } VKD3D_THREAD_LOCAL struct D3D12_UAV_INFO *d3d12_uav_info = NULL; @@ -3868,18 +3867,19 @@ static void STDMETHODCALLTYPE d3d12_device_CreateUnorderedAccessView(d3d12_devic VkResult vr; struct d3d12_resource *d3d12_resource_ = impl_from_ID3D12Resource(resource); struct d3d12_device *device = impl_from_ID3D12Device(iface); - struct d3d12_desc *d3d12_desc_cpu = d3d12_desc_from_cpu_handle(descriptor); TRACE("iface %p, resource %p, counter_resource %p, desc %p, descriptor %#lx.\n", iface, resource, counter_resource, desc, descriptor.ptr); - d3d12_desc_create_uav(d3d12_desc_cpu, + d3d12_desc_create_uav(descriptor.ptr, device, d3d12_resource_, impl_from_ID3D12Resource(counter_resource), desc); /* d3d12_uav_info stores the pointer to data from previous call to d3d12_device_vkd3d_ext_CaptureUAVInfo(). Below code will update the data. */ if (d3d12_uav_info) { - imageViewHandleInfo.imageView = d3d12_desc_cpu->info.view->vk_image_view; + struct d3d12_desc_split d = d3d12_desc_decode_va(descriptor.ptr); + + imageViewHandleInfo.imageView = d.view->info.view->vk_image_view; imageViewHandleInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; vk_procs = &device->vk_procs; @@ -3927,7 +3927,7 @@ static void STDMETHODCALLTYPE d3d12_device_CreateSampler(d3d12_device_iface *ifa TRACE("iface %p, desc %p, descriptor %#lx.\n", iface, desc, descriptor.ptr); - d3d12_desc_create_sampler(d3d12_desc_from_cpu_handle(descriptor), device, desc); + d3d12_desc_create_sampler(descriptor.ptr, device, desc); } static inline D3D12_CPU_DESCRIPTOR_HANDLE d3d12_advance_cpu_descriptor_handle(D3D12_CPU_DESCRIPTOR_HANDLE handle, @@ -3946,15 +3946,12 @@ static inline void d3d12_device_copy_descriptors_cbv_srv_uav_sampler(struct d3d1 if (descriptor_count == 1) { /* Most common path. This path is faster for 1 descriptor. */ - d3d12_desc_copy_single(d3d12_desc_from_cpu_handle(dst), - d3d12_desc_from_cpu_handle(src), device); + d3d12_desc_copy_single(dst.ptr, src.ptr, device); } else #endif { - d3d12_desc_copy(d3d12_desc_from_cpu_handle(dst), - d3d12_desc_from_cpu_handle(src), descriptor_count, - heap_type, device); + d3d12_desc_copy(dst.ptr, src.ptr, descriptor_count, heap_type, device); } } @@ -3991,8 +3988,7 @@ static inline void d3d12_device_copy_descriptors(struct d3d12_device *device, { case D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER: case D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV: - d3d12_desc_copy(d3d12_desc_from_cpu_handle(dst), - d3d12_desc_from_cpu_handle(src), copy_count, + d3d12_desc_copy(dst.ptr, src.ptr, copy_count, descriptor_heap_type, device); break; case D3D12_DESCRIPTOR_HEAP_TYPE_RTV: diff --git a/libs/vkd3d/device_vkd3d_ext.c b/libs/vkd3d/device_vkd3d_ext.c index c55116e7..33a970bb 100644 --- a/libs/vkd3d/device_vkd3d_ext.c +++ b/libs/vkd3d/device_vkd3d_ext.c @@ -154,20 +154,22 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_vkd3d_ext_GetCudaTextureObject(ID3 { VkImageViewHandleInfoNVX imageViewHandleInfo = { VK_STRUCTURE_TYPE_IMAGE_VIEW_HANDLE_INFO_NVX }; const struct vkd3d_vk_device_procs *vk_procs; - struct d3d12_desc *sampler_desc; + struct d3d12_desc_split sampler_desc; + struct d3d12_desc_split srv_desc; struct d3d12_device *device; - struct d3d12_desc *srv_desc; - - TRACE("iface %p, srv_handle %#x, sampler_handle %#x, cuda_texture_handle %p.\n", iface, srv_handle, sampler_handle, cuda_texture_handle); + + TRACE("iface %p, srv_handle %zu, sampler_handle %zu, cuda_texture_handle %p.\n", + iface, srv_handle.ptr, sampler_handle.ptr, cuda_texture_handle); + if (!cuda_texture_handle) return E_INVALIDARG; device = d3d12_device_from_ID3D12DeviceExt(iface); - srv_desc = d3d12_desc_from_cpu_handle(srv_handle); - sampler_desc = d3d12_desc_from_cpu_handle(sampler_handle); + srv_desc = d3d12_desc_decode_va(srv_handle.ptr); + sampler_desc = d3d12_desc_decode_va(sampler_handle.ptr); - imageViewHandleInfo.imageView = srv_desc->info.view->vk_image_view; - imageViewHandleInfo.sampler = sampler_desc->info.view->vk_sampler; + imageViewHandleInfo.imageView = srv_desc.view->info.view->vk_image_view; + imageViewHandleInfo.sampler = sampler_desc.view->info.view->vk_sampler; imageViewHandleInfo.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; vk_procs = &device->vk_procs; @@ -180,17 +182,17 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_vkd3d_ext_GetCudaSurfaceObject(ID3 { VkImageViewHandleInfoNVX imageViewHandleInfo = { VK_STRUCTURE_TYPE_IMAGE_VIEW_HANDLE_INFO_NVX }; const struct vkd3d_vk_device_procs *vk_procs; + struct d3d12_desc_split uav_desc; struct d3d12_device *device; - struct d3d12_desc *uav_desc; - - TRACE("iface %p, uav_handle %#x, cuda_surface_handle %p.\n", iface, uav_handle, cuda_surface_handle); + + TRACE("iface %p, uav_handle %zu, cuda_surface_handle %p.\n", iface, uav_handle.ptr, cuda_surface_handle); if (!cuda_surface_handle) return E_INVALIDARG; device = d3d12_device_from_ID3D12DeviceExt(iface); - uav_desc = d3d12_desc_from_cpu_handle(uav_handle); + uav_desc = d3d12_desc_decode_va(uav_handle.ptr); - imageViewHandleInfo.imageView = uav_desc->info.view->vk_image_view; + imageViewHandleInfo.imageView = uav_desc.view->info.view->vk_image_view; imageViewHandleInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; vk_procs = &device->vk_procs; diff --git a/libs/vkd3d/raytracing_pipeline.c b/libs/vkd3d/raytracing_pipeline.c index dc410383..6b3f8126 100644 --- a/libs/vkd3d/raytracing_pipeline.c +++ b/libs/vkd3d/raytracing_pipeline.c @@ -1016,7 +1016,7 @@ static HRESULT d3d12_state_object_compile_pipeline(struct d3d12_state_object *ob #endif } - shader_interface_local_info.descriptor_size = sizeof(struct d3d12_desc); + shader_interface_local_info.descriptor_size = VKD3D_RESOURCE_DESC_INCREMENT; local_static_sampler_bindings = NULL; local_static_sampler_bindings_count = 0; diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c index a6dc78cf..fcad63a7 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -3046,121 +3046,106 @@ void vkd3d_view_decref(struct vkd3d_view *view, struct d3d12_device *device) vkd3d_view_destroy(view, device); } -void d3d12_desc_copy_single(struct d3d12_desc *dst, struct d3d12_desc *src, +void d3d12_desc_copy_single(vkd3d_cpu_descriptor_va_t dst_va, vkd3d_cpu_descriptor_va_t src_va, struct d3d12_device *device) { VkCopyDescriptorSet vk_copies[VKD3D_MAX_BINDLESS_DESCRIPTOR_SETS]; const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; - struct vkd3d_descriptor_data metadata = src->metadata; struct vkd3d_descriptor_binding binding; uint32_t set_mask, set_info_index; + struct d3d12_desc_split src, dst; const VkDescriptorSet *src_sets; const VkDescriptorSet *dst_sets; VkCopyDescriptorSet *vk_copy; uint32_t copy_count = 0; - bool needs_update; + uint32_t flags; - /* Only update the descriptor if something has changed */ - if (!(needs_update = (metadata.cookie != dst->metadata.cookie))) + src = d3d12_desc_decode_va(src_va); + dst = d3d12_desc_decode_va(dst_va); + + flags = src.types->flags; + src_sets = src.heap->vk_descriptor_sets; + dst_sets = dst.heap->vk_descriptor_sets; + set_mask = src.types->set_info_mask; + + while (set_mask) { - /* We don't have a cookie for the UAV counter, so just force update if we have that. - * If flags differ, we also need to update. E.g. happens if UAV counter flag is turned off. - * We have no cookie for the UAV counter itself. - * Lastly, if we have plain VkBuffers, offset/range might differ. */ - if ((metadata.flags & VKD3D_DESCRIPTOR_FLAG_RAW_VA_AUX_BUFFER) != 0 || - (metadata.flags != dst->metadata.flags)) - { - needs_update = true; - } - else if (metadata.flags & VKD3D_DESCRIPTOR_FLAG_OFFSET_RANGE) - { - needs_update = - dst->info.buffer.offset != src->info.buffer.offset || - dst->info.buffer.range != src->info.buffer.range; - } + set_info_index = vkd3d_bitmask_iter32(&set_mask); + binding = vkd3d_bindless_state_binding_from_info_index(&device->bindless_state, set_info_index); + + vk_copy = &vk_copies[copy_count++]; + vk_copy->sType = VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET; + vk_copy->pNext = NULL; + vk_copy->srcSet = src_sets[binding.set]; + vk_copy->srcBinding = binding.binding; + vk_copy->srcArrayElement = src.offset; + vk_copy->dstSet = dst_sets[binding.set]; + vk_copy->dstBinding = binding.binding; + vk_copy->dstArrayElement = dst.offset; + vk_copy->descriptorCount = 1; } - if (needs_update) + if (flags & VKD3D_DESCRIPTOR_FLAG_RAW_VA_AUX_BUFFER) { - src_sets = src->heap->vk_descriptor_sets; - dst_sets = dst->heap->vk_descriptor_sets; - dst->metadata = metadata; - dst->info = src->info; - set_mask = metadata.set_info_mask; - - while (set_mask) + if (dst.heap->raw_va_aux_buffer.host_ptr) { - set_info_index = vkd3d_bitmask_iter32(&set_mask); - binding = vkd3d_bindless_state_binding_from_info_index(&device->bindless_state, set_info_index); + const VkDeviceAddress *src_vas = src.heap->raw_va_aux_buffer.host_ptr; + VkDeviceAddress *dst_vas = dst.heap->raw_va_aux_buffer.host_ptr; + dst_vas[dst.offset] = src_vas[src.offset]; + } + else + { + binding = vkd3d_bindless_state_find_set( + &device->bindless_state, VKD3D_BINDLESS_SET_UAV | VKD3D_BINDLESS_SET_AUX_BUFFER); vk_copy = &vk_copies[copy_count++]; vk_copy->sType = VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET; vk_copy->pNext = NULL; - vk_copy->srcSet = src_sets[binding.set]; + vk_copy->srcSet = src.heap->vk_descriptor_sets[binding.set]; vk_copy->srcBinding = binding.binding; - vk_copy->srcArrayElement = src->heap_offset; - vk_copy->dstSet = dst_sets[binding.set]; + vk_copy->srcArrayElement = src.offset; + vk_copy->dstSet = dst.heap->vk_descriptor_sets[binding.set]; vk_copy->dstBinding = binding.binding; - vk_copy->dstArrayElement = dst->heap_offset; + vk_copy->dstArrayElement = dst.offset; vk_copy->descriptorCount = 1; } - - if (metadata.flags & VKD3D_DESCRIPTOR_FLAG_RAW_VA_AUX_BUFFER) - { - if (dst->heap->raw_va_aux_buffer.host_ptr) - { - const VkDeviceAddress *src_vas = src->heap->raw_va_aux_buffer.host_ptr; - VkDeviceAddress *dst_vas = dst->heap->raw_va_aux_buffer.host_ptr; - dst_vas[dst->heap_offset] = src_vas[src->heap_offset]; - } - else - { - binding = vkd3d_bindless_state_find_set( - &device->bindless_state, VKD3D_BINDLESS_SET_UAV | VKD3D_BINDLESS_SET_AUX_BUFFER); - - vk_copy = &vk_copies[copy_count++]; - vk_copy->sType = VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET; - vk_copy->pNext = NULL; - vk_copy->srcSet = src->heap->vk_descriptor_sets[binding.set]; - vk_copy->srcBinding = binding.binding; - vk_copy->srcArrayElement = src->heap_offset; - vk_copy->dstSet = dst->heap->vk_descriptor_sets[binding.set]; - vk_copy->dstBinding = binding.binding; - vk_copy->dstArrayElement = dst->heap_offset; - vk_copy->descriptorCount = 1; - } - } - - if (copy_count) - VK_CALL(vkUpdateDescriptorSets(device->vk_device, 0, NULL, copy_count, vk_copies)); } - if (metadata.flags & VKD3D_DESCRIPTOR_FLAG_BUFFER_OFFSET) + if (copy_count) + VK_CALL(vkUpdateDescriptorSets(device->vk_device, 0, NULL, copy_count, vk_copies)); + + if (flags & VKD3D_DESCRIPTOR_FLAG_BUFFER_OFFSET) { - const struct vkd3d_bound_buffer_range *src_buffer_ranges = src->heap->buffer_ranges.host_ptr; - struct vkd3d_bound_buffer_range *dst_buffer_ranges = dst->heap->buffer_ranges.host_ptr; - dst_buffer_ranges[dst->heap_offset] = src_buffer_ranges[src->heap_offset]; + const struct vkd3d_bound_buffer_range *src_buffer_ranges = src.heap->buffer_ranges.host_ptr; + struct vkd3d_bound_buffer_range *dst_buffer_ranges = dst.heap->buffer_ranges.host_ptr; + dst_buffer_ranges[dst.offset] = src_buffer_ranges[src.offset]; } + + *dst.types = *src.types; + *dst.view = *src.view; } -void d3d12_desc_copy_range(struct d3d12_desc *dst, struct d3d12_desc *src, +void d3d12_desc_copy_range(vkd3d_cpu_descriptor_va_t dst_va, vkd3d_cpu_descriptor_va_t src_va, unsigned int count, D3D12_DESCRIPTOR_HEAP_TYPE heap_type, struct d3d12_device *device) { VkCopyDescriptorSet vk_copies[VKD3D_MAX_BINDLESS_DESCRIPTOR_SETS]; const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; struct vkd3d_descriptor_binding binding; + struct d3d12_desc_split src, dst; VkCopyDescriptorSet *vk_copy; uint32_t set_info_mask = 0; uint32_t copy_count = 0; uint32_t set_info_index; unsigned int i; + src = d3d12_desc_decode_va(src_va); + dst = d3d12_desc_decode_va(dst_va); + for (i = 0; i < count; i++) - { - set_info_mask |= src[i].metadata.set_info_mask; - dst[i].metadata = src[i].metadata; - dst[i].info = src[i].info; - } + set_info_mask |= src.types[i].set_info_mask; + + memcpy(dst.view, src.view, sizeof(*dst.view) * count); + memcpy(dst.types, src.types, sizeof(*dst.types) * count); while (set_info_mask) { @@ -3170,12 +3155,12 @@ void d3d12_desc_copy_range(struct d3d12_desc *dst, struct d3d12_desc *src, vk_copy = &vk_copies[copy_count++]; vk_copy->sType = VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET; vk_copy->pNext = NULL; - vk_copy->srcSet = src->heap->vk_descriptor_sets[binding.set]; + vk_copy->srcSet = src.heap->vk_descriptor_sets[binding.set]; vk_copy->srcBinding = binding.binding; - vk_copy->srcArrayElement = src->heap_offset; - vk_copy->dstSet = dst->heap->vk_descriptor_sets[binding.set]; + vk_copy->srcArrayElement = src.offset; + vk_copy->dstSet = dst.heap->vk_descriptor_sets[binding.set]; vk_copy->dstBinding = binding.binding; - vk_copy->dstArrayElement = dst->heap_offset; + vk_copy->dstArrayElement = dst.offset; vk_copy->descriptorCount = count; } @@ -3183,9 +3168,9 @@ void d3d12_desc_copy_range(struct d3d12_desc *dst, struct d3d12_desc *src, { if (device->bindless_state.flags & VKD3D_RAW_VA_AUX_BUFFER) { - const VkDeviceAddress *src_vas = src->heap->raw_va_aux_buffer.host_ptr; - VkDeviceAddress *dst_vas = dst->heap->raw_va_aux_buffer.host_ptr; - memcpy(dst_vas + dst->heap_offset, src_vas + src->heap_offset, sizeof(*dst_vas) * count); + const VkDeviceAddress *src_vas = src.heap->raw_va_aux_buffer.host_ptr; + VkDeviceAddress *dst_vas = dst.heap->raw_va_aux_buffer.host_ptr; + memcpy(dst_vas + dst.offset, src_vas + src.offset, sizeof(*dst_vas) * count); } else { @@ -3194,20 +3179,20 @@ void d3d12_desc_copy_range(struct d3d12_desc *dst, struct d3d12_desc *src, vk_copy = &vk_copies[copy_count++]; vk_copy->sType = VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET; vk_copy->pNext = NULL; - vk_copy->srcSet = src->heap->vk_descriptor_sets[binding.set]; + vk_copy->srcSet = src.heap->vk_descriptor_sets[binding.set]; vk_copy->srcBinding = binding.binding; - vk_copy->srcArrayElement = src->heap_offset; - vk_copy->dstSet = dst->heap->vk_descriptor_sets[binding.set]; + vk_copy->srcArrayElement = src.offset; + vk_copy->dstSet = dst.heap->vk_descriptor_sets[binding.set]; vk_copy->dstBinding = binding.binding; - vk_copy->dstArrayElement = dst->heap_offset; + vk_copy->dstArrayElement = dst.offset; vk_copy->descriptorCount = count; } if (device->bindless_state.flags & (VKD3D_TYPED_OFFSET_BUFFER | VKD3D_SSBO_OFFSET_BUFFER)) { - const struct vkd3d_bound_buffer_range *src_ranges = src->heap->buffer_ranges.host_ptr; - struct vkd3d_bound_buffer_range *dst_ranges = dst->heap->buffer_ranges.host_ptr; - memcpy(dst_ranges + dst->heap_offset, src_ranges + src->heap_offset, sizeof(*dst_ranges) * count); + const struct vkd3d_bound_buffer_range *src_ranges = src.heap->buffer_ranges.host_ptr; + struct vkd3d_bound_buffer_range *dst_ranges = dst.heap->buffer_ranges.host_ptr; + memcpy(dst_ranges + dst.offset, src_ranges + src.offset, sizeof(*dst_ranges) * count); } } @@ -3215,27 +3200,38 @@ void d3d12_desc_copy_range(struct d3d12_desc *dst, struct d3d12_desc *src, VK_CALL(vkUpdateDescriptorSets(device->vk_device, 0, NULL, copy_count, vk_copies)); } -void d3d12_desc_copy(struct d3d12_desc *dst, struct d3d12_desc *src, +void d3d12_desc_copy(vkd3d_cpu_descriptor_va_t dst_va, vkd3d_cpu_descriptor_va_t src_va, unsigned int count, D3D12_DESCRIPTOR_HEAP_TYPE heap_type, struct d3d12_device *device) { unsigned int i; #ifdef VKD3D_ENABLE_DESCRIPTOR_QA - for (i = 0; i < count; i++) { - vkd3d_descriptor_debug_copy_descriptor( - dst[i].heap->descriptor_heap_info.host_ptr, dst[i].heap->cookie, dst[i].heap_offset, - src[i].heap->descriptor_heap_info.host_ptr, src[i].heap->cookie, src[i].heap_offset, - src[i].metadata.cookie); + struct d3d12_desc_split dst, src; + dst = d3d12_desc_decode_va(dst_va); + src = d3d12_desc_decode_va(src_va); + + for (i = 0; i < count; i++) + { + vkd3d_descriptor_debug_copy_descriptor( + dst.heap->descriptor_heap_info.host_ptr, dst.heap->cookie, dst.offset, + src.heap->descriptor_heap_info.host_ptr, src.heap->cookie, src.offset, + src.view[i].cookie); + } } #endif if (device->bindless_state.flags & VKD3D_BINDLESS_MUTABLE_TYPE) - d3d12_desc_copy_range(dst, src, count, heap_type, device); + d3d12_desc_copy_range(dst_va, src_va, count, heap_type, device); else { + /* This path is quite rare. Could potentially amortize d3d12_desc_decode_va(). */ for (i = 0; i < count; i++) - d3d12_desc_copy_single(dst + i, src + i, device); + { + d3d12_desc_copy_single(dst_va, src_va, device); + dst_va += VKD3D_RESOURCE_DESC_INCREMENT; + src_va += VKD3D_RESOURCE_DESC_INCREMENT; + } } } @@ -3668,15 +3664,15 @@ bool vkd3d_create_texture_view(struct d3d12_device *device, const struct vkd3d_t return true; } -static inline void vkd3d_init_write_descriptor_set(VkWriteDescriptorSet *vk_write, const struct d3d12_desc *descriptor, +static inline void vkd3d_init_write_descriptor_set(VkWriteDescriptorSet *vk_write, const struct d3d12_desc_split *split, struct vkd3d_descriptor_binding binding, VkDescriptorType vk_descriptor_type, const union vkd3d_descriptor_info *info) { vk_write->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; vk_write->pNext = NULL; - vk_write->dstSet = descriptor->heap->vk_descriptor_sets[binding.set]; + vk_write->dstSet = split->heap->vk_descriptor_sets[binding.set]; vk_write->dstBinding = binding.binding; - vk_write->dstArrayElement = d3d12_desc_heap_offset(descriptor); + vk_write->dstArrayElement = split->offset; vk_write->descriptorCount = 1; vk_write->descriptorType = vk_descriptor_type; vk_write->pImageInfo = &info->image; @@ -3684,60 +3680,60 @@ static inline void vkd3d_init_write_descriptor_set(VkWriteDescriptorSet *vk_writ vk_write->pTexelBufferView = &info->buffer_view; } -static void d3d12_descriptor_heap_write_null_descriptor_template(struct d3d12_desc *desc, +static void d3d12_descriptor_heap_write_null_descriptor_template(vkd3d_cpu_descriptor_va_t desc_va, VkDescriptorType vk_mutable_descriptor_type) { /* For null descriptors, some games don't write the correct type (usually an image SRV), * so we will need to splat null descriptors over all descriptor sets. * For MUTABLE, this would normally just be one descriptor set, but * we need MUTABLE + STORAGE_BUFFER, or 6 sets for non-mutable :\ */ - VkWriteDescriptorSet writes[ARRAY_SIZE(desc->heap->null_descriptor_template.writes)]; + VkWriteDescriptorSet writes[VKD3D_MAX_BINDLESS_DESCRIPTOR_SETS]; const struct vkd3d_vk_device_procs *vk_procs; - struct d3d12_descriptor_heap *heap; + struct d3d12_desc_split desc; unsigned int num_writes, i; unsigned int offset; VkDeviceAddress *va; - heap = desc->heap; + desc = d3d12_desc_decode_va(desc_va); /* When mutable descriptors are not supported, set a dummy type. This will make those drivers not care about the null type being different between null writes. */ - if (!heap->null_descriptor_template.has_mutable_descriptors) + if (!desc.heap->null_descriptor_template.has_mutable_descriptors) vk_mutable_descriptor_type = 0; /* Skip writes with the same null type that are already null. */ - if (!(desc->metadata.flags & VKD3D_DESCRIPTOR_FLAG_NON_NULL) - && desc->metadata.current_null_type == vk_mutable_descriptor_type) + if (!(desc.types->flags & VKD3D_DESCRIPTOR_FLAG_NON_NULL) + && desc.types->current_null_type == vk_mutable_descriptor_type) return; - num_writes = heap->null_descriptor_template.num_writes; - vk_procs = &heap->device->vk_procs; - offset = desc->heap_offset; + num_writes = desc.heap->null_descriptor_template.num_writes; + vk_procs = &desc.heap->device->vk_procs; + offset = desc.offset; for (i = 0; i < num_writes; i++) { - writes[i] = heap->null_descriptor_template.writes[i]; + writes[i] = desc.heap->null_descriptor_template.writes[i]; if (writes[i].descriptorType == VK_DESCRIPTOR_TYPE_MUTABLE_VALVE) writes[i].descriptorType = vk_mutable_descriptor_type; writes[i].dstArrayElement = offset; } - VK_CALL(vkUpdateDescriptorSets(heap->device->vk_device, num_writes, writes, 0, NULL)); + VK_CALL(vkUpdateDescriptorSets(desc.heap->device->vk_device, num_writes, writes, 0, NULL)); - desc->metadata.cookie = 0; - desc->metadata.flags = 0; - desc->metadata.set_info_mask = heap->null_descriptor_template.set_info_mask; - desc->metadata.current_null_type = vk_mutable_descriptor_type; - memset(&desc->info, 0, sizeof(desc->info)); + desc.view->cookie = 0; + desc.types->flags = 0; + desc.types->set_info_mask = desc.heap->null_descriptor_template.set_info_mask; + desc.types->current_null_type = vk_mutable_descriptor_type; + memset(desc.view, 0, sizeof(*desc.view)); - va = heap->raw_va_aux_buffer.host_ptr; + va = desc.heap->raw_va_aux_buffer.host_ptr; if (va) va[offset] = 0; /* Notify descriptor QA that we have a universal null descriptor. */ - vkd3d_descriptor_debug_write_descriptor(heap->descriptor_heap_info.host_ptr, - heap->cookie, offset, + vkd3d_descriptor_debug_write_descriptor(desc.heap->descriptor_heap_info.host_ptr, + desc.heap->cookie, offset, VKD3D_DESCRIPTOR_QA_TYPE_UNIFORM_BUFFER_BIT | VKD3D_DESCRIPTOR_QA_TYPE_STORAGE_BUFFER_BIT | VKD3D_DESCRIPTOR_QA_TYPE_SAMPLED_IMAGE_BIT | @@ -3748,7 +3744,7 @@ static void d3d12_descriptor_heap_write_null_descriptor_template(struct d3d12_de VKD3D_DESCRIPTOR_QA_TYPE_RT_ACCELERATION_STRUCTURE_BIT, 0); } -void d3d12_desc_create_cbv(struct d3d12_desc *descriptor, +void d3d12_desc_create_cbv(vkd3d_cpu_descriptor_va_t desc_va, struct d3d12_device *device, const D3D12_CONSTANT_BUFFER_VIEW_DESC *desc) { const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; @@ -3756,6 +3752,7 @@ void d3d12_desc_create_cbv(struct d3d12_desc *descriptor, union vkd3d_descriptor_info descriptor_info; VkDescriptorType vk_descriptor_type; VkWriteDescriptorSet vk_write; + struct d3d12_desc_split d; uint32_t info_index; if (!desc) @@ -3774,10 +3771,12 @@ void d3d12_desc_create_cbv(struct d3d12_desc *descriptor, if (!desc->BufferLocation) { - d3d12_descriptor_heap_write_null_descriptor_template(descriptor, vk_descriptor_type); + d3d12_descriptor_heap_write_null_descriptor_template(desc_va, vk_descriptor_type); return; } + d = d3d12_desc_decode_va(desc_va); + resource = vkd3d_va_map_deref(&device->memory_allocator.va_map, desc->BufferLocation); descriptor_info.buffer.buffer = resource->vk_buffer; descriptor_info.buffer.offset = desc->BufferLocation - resource->va; @@ -3785,22 +3784,22 @@ void d3d12_desc_create_cbv(struct d3d12_desc *descriptor, info_index = vkd3d_bindless_state_find_set_info_index(&device->bindless_state, VKD3D_BINDLESS_SET_CBV); - descriptor->metadata.cookie = resource ? resource->cookie : 0; - descriptor->metadata.set_info_mask = 1u << info_index; - descriptor->metadata.flags = VKD3D_DESCRIPTOR_FLAG_OFFSET_RANGE | VKD3D_DESCRIPTOR_FLAG_NON_NULL; - descriptor->info.buffer = descriptor_info.buffer; + d.view->cookie = resource ? resource->cookie : 0; + d.types->set_info_mask = 1u << info_index; + d.types->flags = VKD3D_DESCRIPTOR_FLAG_OFFSET_RANGE | VKD3D_DESCRIPTOR_FLAG_NON_NULL; + d.view->info.buffer = descriptor_info.buffer; - vkd3d_init_write_descriptor_set(&vk_write, descriptor, + vkd3d_init_write_descriptor_set(&vk_write, &d, vkd3d_bindless_state_binding_from_info_index(&device->bindless_state, info_index), vk_descriptor_type, &descriptor_info); - vkd3d_descriptor_debug_write_descriptor(descriptor->heap->descriptor_heap_info.host_ptr, - descriptor->heap->cookie, - descriptor->heap_offset, + vkd3d_descriptor_debug_write_descriptor(d.heap->descriptor_heap_info.host_ptr, + d.heap->cookie, + d.offset, vk_descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ? VKD3D_DESCRIPTOR_QA_TYPE_UNIFORM_BUFFER_BIT : VKD3D_DESCRIPTOR_QA_TYPE_STORAGE_BUFFER_BIT, - descriptor->metadata.cookie); + d.view->cookie); VK_CALL(vkUpdateDescriptorSets(device->vk_device, 1, &vk_write, 0, NULL)); } @@ -3814,7 +3813,7 @@ static unsigned int vkd3d_view_flags_from_d3d12_buffer_srv_flags(D3D12_BUFFER_SR return 0; } -static void vkd3d_buffer_view_get_bound_range_ssbo(struct d3d12_desc *descriptor, +static void vkd3d_buffer_view_get_bound_range_ssbo( struct d3d12_device *device, struct d3d12_resource *resource, VkDeviceSize offset, VkDeviceSize range, VkDescriptorBufferInfo *vk_buffer, struct vkd3d_bound_buffer_range *bound_range) @@ -3844,7 +3843,7 @@ static void vkd3d_buffer_view_get_bound_range_ssbo(struct d3d12_desc *descriptor } } -static bool vkd3d_buffer_view_get_aligned_view(struct d3d12_desc *descriptor, +static bool vkd3d_buffer_view_get_aligned_view( struct d3d12_device *device, struct d3d12_resource *resource, DXGI_FORMAT format, unsigned int vk_flags, VkDeviceSize first_element, VkDeviceSize num_elements, @@ -3926,7 +3925,7 @@ static bool vkd3d_buffer_view_get_aligned_view(struct d3d12_desc *descriptor, return true; } -static void vkd3d_create_buffer_srv(struct d3d12_desc *descriptor, +static void vkd3d_create_buffer_srv(vkd3d_cpu_descriptor_va_t desc_va, struct d3d12_device *device, struct d3d12_resource *resource, const D3D12_SHADER_RESOURCE_VIEW_DESC *desc) { @@ -3939,6 +3938,7 @@ static void vkd3d_create_buffer_srv(struct d3d12_desc *descriptor, VkWriteDescriptorSet vk_write[2]; struct vkd3d_view *view = NULL; uint32_t vk_write_count = 0; + struct d3d12_desc_split d; unsigned int vk_flags; uint32_t info_index; bool desc_is_raw; @@ -3951,6 +3951,8 @@ static void vkd3d_create_buffer_srv(struct d3d12_desc *descriptor, return; } + d = d3d12_desc_decode_va(desc_va); + if (desc->ViewDimension == D3D12_SRV_DIMENSION_RAYTRACING_ACCELERATION_STRUCTURE) { if (!desc->RaytracingAccelerationStructure.Location) @@ -3958,29 +3960,29 @@ static void vkd3d_create_buffer_srv(struct d3d12_desc *descriptor, /* There is no concrete descriptor to use here, * so just write a SAMPLED_IMAGE to clear out mutable descriptor. * What we really want to clear here is the raw VA. */ - d3d12_descriptor_heap_write_null_descriptor_template(descriptor, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE); + d3d12_descriptor_heap_write_null_descriptor_template(desc_va, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE); return; } if (d3d12_device_supports_ray_tracing_tier_1_0(device)) { /* We implement this as a raw VA in the aux buffer. */ - VkDeviceAddress *raw_addresses = descriptor->heap->raw_va_aux_buffer.host_ptr; - uint32_t descriptor_index = d3d12_desc_heap_offset(descriptor); + VkDeviceAddress *raw_addresses = d.heap->raw_va_aux_buffer.host_ptr; + uint32_t descriptor_index = d.offset; raw_addresses[descriptor_index] = desc->RaytracingAccelerationStructure.Location; - descriptor->metadata.flags = VKD3D_DESCRIPTOR_FLAG_RAW_VA_AUX_BUFFER | - VKD3D_DESCRIPTOR_FLAG_NON_NULL; - descriptor->metadata.set_info_mask = 0; + d.types->flags = VKD3D_DESCRIPTOR_FLAG_RAW_VA_AUX_BUFFER | + VKD3D_DESCRIPTOR_FLAG_NON_NULL; + d.types->set_info_mask = 0; /* There is no resource tied to this descriptor, just a naked pointer. */ - descriptor->metadata.cookie = 0; + d.view->cookie = 0; } else WARN("Using CreateSRV for RTAS without RT support?\n"); - vkd3d_descriptor_debug_write_descriptor(descriptor->heap->descriptor_heap_info.host_ptr, - descriptor->heap->cookie, descriptor->heap_offset, + vkd3d_descriptor_debug_write_descriptor(d.heap->descriptor_heap_info.host_ptr, + d.heap->cookie, d.offset, VKD3D_DESCRIPTOR_QA_TYPE_RT_ACCELERATION_STRUCTURE_BIT | VKD3D_DESCRIPTOR_QA_TYPE_RAW_VA_BIT, - descriptor->metadata.cookie); + d.view->cookie); return; } @@ -4001,20 +4003,20 @@ static void vkd3d_create_buffer_srv(struct d3d12_desc *descriptor, { if (mutable_uses_single_descriptor) { - d3d12_descriptor_heap_write_null_descriptor_template(descriptor, + d3d12_descriptor_heap_write_null_descriptor_template(desc_va, desc_is_raw ? VK_DESCRIPTOR_TYPE_STORAGE_BUFFER : VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER); } else { /* In the mutable set, always write texel buffer. The STORAGE_BUFFER set is also written to. */ - d3d12_descriptor_heap_write_null_descriptor_template(descriptor, + d3d12_descriptor_heap_write_null_descriptor_template(desc_va, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER); } return; } - descriptor->metadata.set_info_mask = 0; - descriptor->metadata.flags = 0; + d.types->set_info_mask = 0; + d.types->flags = 0; if (d3d12_device_use_ssbo_raw_buffer(device) && emit_ssbo) { @@ -4022,25 +4024,25 @@ static void vkd3d_create_buffer_srv(struct d3d12_desc *descriptor, ? desc->Buffer.StructureByteStride : vkd3d_get_format(device, desc->Format, false)->byte_count; - vkd3d_buffer_view_get_bound_range_ssbo(descriptor, device, resource, + vkd3d_buffer_view_get_bound_range_ssbo(device, resource, desc->Buffer.FirstElement * stride, desc->Buffer.NumElements * stride, &descriptor_info[vk_write_count].buffer, &bound_range); info_index = vkd3d_bindless_state_find_set_info_index(&device->bindless_state, VKD3D_BINDLESS_SET_SRV | VKD3D_BINDLESS_SET_RAW_SSBO); - descriptor->info.buffer = descriptor_info[vk_write_count].buffer; - descriptor->metadata.cookie = resource ? resource->res.cookie : 0; - descriptor->metadata.set_info_mask |= 1u << info_index; + d.view->info.buffer = descriptor_info[vk_write_count].buffer; + d.view->cookie = resource ? resource->res.cookie : 0; + d.types->set_info_mask |= 1u << info_index; - descriptor->metadata.flags |= VKD3D_DESCRIPTOR_FLAG_OFFSET_RANGE | + d.types->flags |= VKD3D_DESCRIPTOR_FLAG_OFFSET_RANGE | VKD3D_DESCRIPTOR_FLAG_NON_NULL; if (device->bindless_state.flags & VKD3D_SSBO_OFFSET_BUFFER) - descriptor->metadata.flags |= VKD3D_DESCRIPTOR_FLAG_BUFFER_OFFSET; + d.types->flags |= VKD3D_DESCRIPTOR_FLAG_BUFFER_OFFSET; vk_descriptor_type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; descriptor_qa_flags |= VKD3D_DESCRIPTOR_QA_TYPE_STORAGE_BUFFER_BIT; - vkd3d_init_write_descriptor_set(&vk_write[vk_write_count], descriptor, + vkd3d_init_write_descriptor_set(&vk_write[vk_write_count], &d, vkd3d_bindless_state_binding_from_info_index(&device->bindless_state, info_index), vk_descriptor_type, &descriptor_info[vk_write_count]); vk_write_count++; @@ -4049,7 +4051,7 @@ static void vkd3d_create_buffer_srv(struct d3d12_desc *descriptor, if (emit_typed) { vk_flags = vkd3d_view_flags_from_d3d12_buffer_srv_flags(desc->Buffer.Flags); - if (!vkd3d_buffer_view_get_aligned_view(descriptor, device, resource, desc->Format, vk_flags, + if (!vkd3d_buffer_view_get_aligned_view(device, resource, desc->Format, vk_flags, desc->Buffer.FirstElement, desc->Buffer.NumElements, desc->Buffer.StructureByteStride, &bound_range, &view)) return; @@ -4059,40 +4061,40 @@ static void vkd3d_create_buffer_srv(struct d3d12_desc *descriptor, info_index = vkd3d_bindless_state_find_set_info_index(&device->bindless_state, VKD3D_BINDLESS_SET_SRV | VKD3D_BINDLESS_SET_BUFFER); - descriptor->info.view = view; + d.view->info.view = view; /* Typed cookie takes precedence over raw cookie. * The typed cookie is more unique than raw cookie, * since raw cookie is just the ID3D12Resource. */ - descriptor->metadata.cookie = view ? view->cookie : 0; - descriptor->metadata.set_info_mask |= 1u << info_index; + d.view->cookie = view ? view->cookie : 0; + d.types->set_info_mask |= 1u << info_index; - descriptor->metadata.flags |= VKD3D_DESCRIPTOR_FLAG_VIEW | VKD3D_DESCRIPTOR_FLAG_NON_NULL; + d.types->flags |= VKD3D_DESCRIPTOR_FLAG_VIEW | VKD3D_DESCRIPTOR_FLAG_NON_NULL; if (device->bindless_state.flags & VKD3D_TYPED_OFFSET_BUFFER) - descriptor->metadata.flags |= VKD3D_DESCRIPTOR_FLAG_BUFFER_OFFSET; + d.types->flags |= VKD3D_DESCRIPTOR_FLAG_BUFFER_OFFSET; vk_descriptor_type = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; descriptor_qa_flags |= VKD3D_DESCRIPTOR_QA_TYPE_UNIFORM_TEXEL_BUFFER_BIT; - vkd3d_init_write_descriptor_set(&vk_write[vk_write_count], descriptor, + vkd3d_init_write_descriptor_set(&vk_write[vk_write_count], &d, vkd3d_bindless_state_binding_from_info_index(&device->bindless_state, info_index), vk_descriptor_type, &descriptor_info[vk_write_count]); vk_write_count++; } - if (descriptor->metadata.flags & VKD3D_DESCRIPTOR_FLAG_BUFFER_OFFSET) + if (d.types->flags & VKD3D_DESCRIPTOR_FLAG_BUFFER_OFFSET) { - struct vkd3d_bound_buffer_range *buffer_ranges = descriptor->heap->buffer_ranges.host_ptr; - buffer_ranges[descriptor->heap_offset] = bound_range; + struct vkd3d_bound_buffer_range *buffer_ranges = d.heap->buffer_ranges.host_ptr; + buffer_ranges[d.offset] = bound_range; } - vkd3d_descriptor_debug_write_descriptor(descriptor->heap->descriptor_heap_info.host_ptr, - descriptor->heap->cookie, descriptor->heap_offset, descriptor_qa_flags, descriptor->metadata.cookie); + vkd3d_descriptor_debug_write_descriptor(d.heap->descriptor_heap_info.host_ptr, + d.heap->cookie, d.offset, descriptor_qa_flags, d.view->cookie); if (vk_write_count) VK_CALL(vkUpdateDescriptorSets(device->vk_device, vk_write_count, vk_write, 0, NULL)); } -static void vkd3d_create_texture_srv(struct d3d12_desc *descriptor, +static void vkd3d_create_texture_srv(vkd3d_cpu_descriptor_va_t desc_va, struct d3d12_device *device, struct d3d12_resource *resource, const D3D12_SHADER_RESOURCE_VIEW_DESC *desc) { @@ -4101,14 +4103,17 @@ static void vkd3d_create_texture_srv(struct d3d12_desc *descriptor, struct vkd3d_view *view = NULL; VkWriteDescriptorSet vk_write; struct vkd3d_view_key key; + struct d3d12_desc_split d; uint32_t info_index; if (!resource) { - d3d12_descriptor_heap_write_null_descriptor_template(descriptor, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE); + d3d12_descriptor_heap_write_null_descriptor_template(desc_va, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE); return; } + d = d3d12_desc_decode_va(desc_va); + if (!init_default_texture_view_desc(&key.u.texture, resource, desc ? desc->Format : 0)) return; @@ -4210,23 +4215,23 @@ static void vkd3d_create_texture_srv(struct d3d12_desc *descriptor, info_index = vkd3d_bindless_state_find_set_info_index(&device->bindless_state, VKD3D_BINDLESS_SET_SRV | VKD3D_BINDLESS_SET_IMAGE); - descriptor->info.view = view; - descriptor->metadata.cookie = view ? view->cookie : 0; - descriptor->metadata.set_info_mask = 1u << info_index; - descriptor->metadata.flags = VKD3D_DESCRIPTOR_FLAG_VIEW | VKD3D_DESCRIPTOR_FLAG_NON_NULL; + d.view->info.view = view; + d.view->cookie = view ? view->cookie : 0; + d.types->set_info_mask = 1u << info_index; + d.types->flags = VKD3D_DESCRIPTOR_FLAG_VIEW | VKD3D_DESCRIPTOR_FLAG_NON_NULL; - vkd3d_init_write_descriptor_set(&vk_write, descriptor, + vkd3d_init_write_descriptor_set(&vk_write, &d, vkd3d_bindless_state_binding_from_info_index(&device->bindless_state, info_index), VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &descriptor_info); - vkd3d_descriptor_debug_write_descriptor(descriptor->heap->descriptor_heap_info.host_ptr, - descriptor->heap->cookie, descriptor->heap_offset, - VKD3D_DESCRIPTOR_QA_TYPE_SAMPLED_IMAGE_BIT, descriptor->metadata.cookie); + vkd3d_descriptor_debug_write_descriptor(d.heap->descriptor_heap_info.host_ptr, + d.heap->cookie, d.offset, + VKD3D_DESCRIPTOR_QA_TYPE_SAMPLED_IMAGE_BIT, d.view->cookie); VK_CALL(vkUpdateDescriptorSets(device->vk_device, 1, &vk_write, 0, NULL)); } -void d3d12_desc_create_srv(struct d3d12_desc *descriptor, +void d3d12_desc_create_srv(vkd3d_cpu_descriptor_va_t desc_va, struct d3d12_device *device, struct d3d12_resource *resource, const D3D12_SHADER_RESOURCE_VIEW_DESC *desc) { @@ -4248,9 +4253,9 @@ void d3d12_desc_create_srv(struct d3d12_desc *descriptor, } if (is_buffer) - vkd3d_create_buffer_srv(descriptor, device, resource, desc); + vkd3d_create_buffer_srv(desc_va, device, resource, desc); else - vkd3d_create_texture_srv(descriptor, device, resource, desc); + vkd3d_create_texture_srv(desc_va, device, resource, desc); } static unsigned int vkd3d_view_flags_from_d3d12_buffer_uav_flags(D3D12_BUFFER_UAV_FLAGS flags) @@ -4287,7 +4292,7 @@ VkDeviceAddress vkd3d_get_acceleration_structure_device_address(struct d3d12_dev return VK_CALL(vkGetAccelerationStructureDeviceAddressKHR(device->vk_device, &address_info)); } -static void vkd3d_create_buffer_uav(struct d3d12_desc *descriptor, struct d3d12_device *device, +static void vkd3d_create_buffer_uav(vkd3d_cpu_descriptor_va_t desc_va, struct d3d12_device *device, struct d3d12_resource *resource, struct d3d12_resource *counter_resource, const D3D12_UNORDERED_ACCESS_VIEW_DESC *desc) { @@ -4302,6 +4307,7 @@ static void vkd3d_create_buffer_uav(struct d3d12_desc *descriptor, struct d3d12_ VkWriteDescriptorSet vk_write[3]; struct vkd3d_view *view = NULL; VkBufferView uav_counter_view; + struct d3d12_desc_split d; uint32_t info_index; bool desc_is_raw; bool emit_typed; @@ -4329,22 +4335,24 @@ static void vkd3d_create_buffer_uav(struct d3d12_desc *descriptor, struct d3d12_ { if (mutable_uses_single_descriptor) { - d3d12_descriptor_heap_write_null_descriptor_template(descriptor, + d3d12_descriptor_heap_write_null_descriptor_template(desc_va, desc_is_raw ? VK_DESCRIPTOR_TYPE_STORAGE_BUFFER : VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER); } else { /* In the mutable set, always write texel buffer. The STORAGE_BUFFER set is also written to. */ - d3d12_descriptor_heap_write_null_descriptor_template(descriptor, + d3d12_descriptor_heap_write_null_descriptor_template(desc_va, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER); } return; } + d = d3d12_desc_decode_va(desc_va); + /* Handle UAV itself */ - descriptor->metadata.set_info_mask = 0; - descriptor->metadata.flags = VKD3D_DESCRIPTOR_FLAG_RAW_VA_AUX_BUFFER | - VKD3D_DESCRIPTOR_FLAG_NON_NULL; + d.types->set_info_mask = 0; + d.types->flags = VKD3D_DESCRIPTOR_FLAG_RAW_VA_AUX_BUFFER | + VKD3D_DESCRIPTOR_FLAG_NON_NULL; if (d3d12_device_use_ssbo_raw_buffer(device) && emit_ssbo) { @@ -4354,25 +4362,25 @@ static void vkd3d_create_buffer_uav(struct d3d12_desc *descriptor, struct d3d12_ ? desc->Buffer.StructureByteStride : vkd3d_get_format(device, desc->Format, false)->byte_count; - vkd3d_buffer_view_get_bound_range_ssbo(descriptor, device, resource, + vkd3d_buffer_view_get_bound_range_ssbo(device, resource, desc->Buffer.FirstElement * stride, desc->Buffer.NumElements * stride, buffer_info, &bound_range); info_index = vkd3d_bindless_state_find_set_info_index(&device->bindless_state, VKD3D_BINDLESS_SET_UAV | VKD3D_BINDLESS_SET_RAW_SSBO); - descriptor->info.buffer = *buffer_info; - descriptor->metadata.cookie = resource ? resource->res.cookie : 0; - descriptor->metadata.set_info_mask |= 1u << info_index; + d.view->info.buffer = *buffer_info; + d.view->cookie = resource ? resource->res.cookie : 0; + d.types->set_info_mask |= 1u << info_index; - descriptor->metadata.flags |= VKD3D_DESCRIPTOR_FLAG_OFFSET_RANGE; + d.types->flags |= VKD3D_DESCRIPTOR_FLAG_OFFSET_RANGE; if (device->bindless_state.flags & VKD3D_SSBO_OFFSET_BUFFER) - descriptor->metadata.flags |= VKD3D_DESCRIPTOR_FLAG_BUFFER_OFFSET; + d.types->flags |= VKD3D_DESCRIPTOR_FLAG_BUFFER_OFFSET; vk_descriptor_type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; descriptor_qa_flags |= VKD3D_DESCRIPTOR_QA_TYPE_STORAGE_BUFFER_BIT; - vkd3d_init_write_descriptor_set(&vk_write[vk_write_count], descriptor, + vkd3d_init_write_descriptor_set(&vk_write[vk_write_count], &d, vkd3d_bindless_state_binding_from_info_index(&device->bindless_state, info_index), vk_descriptor_type, &descriptor_info[vk_write_count]); vk_write_count++; @@ -4382,7 +4390,7 @@ static void vkd3d_create_buffer_uav(struct d3d12_desc *descriptor, struct d3d12_ { flags = vkd3d_view_flags_from_d3d12_buffer_uav_flags(desc->Buffer.Flags); - if (!vkd3d_buffer_view_get_aligned_view(descriptor, device, resource, desc->Format, flags, + if (!vkd3d_buffer_view_get_aligned_view(device, resource, desc->Format, flags, desc->Buffer.FirstElement, desc->Buffer.NumElements, desc->Buffer.StructureByteStride, &bound_range, &view)) return; @@ -4390,32 +4398,32 @@ static void vkd3d_create_buffer_uav(struct d3d12_desc *descriptor, struct d3d12_ info_index = vkd3d_bindless_state_find_set_info_index(&device->bindless_state, VKD3D_BINDLESS_SET_UAV | VKD3D_BINDLESS_SET_BUFFER); - descriptor->info.view = view; + d.view->info.view = view; /* Typed cookie takes precedence over raw cookie. * The typed cookie is more unique than raw cookie, * since raw cookie is just the ID3D12Resource. */ - descriptor->metadata.cookie = view ? view->cookie : 0; - descriptor->metadata.set_info_mask |= 1u << info_index; + d.view->cookie = view ? view->cookie : 0; + d.types->set_info_mask |= 1u << info_index; - descriptor->metadata.flags |= VKD3D_DESCRIPTOR_FLAG_VIEW; + d.types->flags |= VKD3D_DESCRIPTOR_FLAG_VIEW; if (device->bindless_state.flags & VKD3D_TYPED_OFFSET_BUFFER) - descriptor->metadata.flags |= VKD3D_DESCRIPTOR_FLAG_BUFFER_OFFSET; + d.types->flags |= VKD3D_DESCRIPTOR_FLAG_BUFFER_OFFSET; descriptor_info[vk_write_count].buffer_view = view ? view->vk_buffer_view : VK_NULL_HANDLE; vk_descriptor_type = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; descriptor_qa_flags |= VKD3D_DESCRIPTOR_QA_TYPE_STORAGE_TEXEL_BUFFER_BIT; - vkd3d_init_write_descriptor_set(&vk_write[vk_write_count], descriptor, + vkd3d_init_write_descriptor_set(&vk_write[vk_write_count], &d, vkd3d_bindless_state_binding_from_info_index(&device->bindless_state, info_index), vk_descriptor_type, &descriptor_info[vk_write_count]); vk_write_count++; } - if (descriptor->metadata.flags & VKD3D_DESCRIPTOR_FLAG_BUFFER_OFFSET) + if (d.types->flags & VKD3D_DESCRIPTOR_FLAG_BUFFER_OFFSET) { - struct vkd3d_bound_buffer_range *buffer_ranges = descriptor->heap->buffer_ranges.host_ptr; - buffer_ranges[descriptor->heap_offset] = bound_range; + struct vkd3d_bound_buffer_range *buffer_ranges = d.heap->buffer_ranges.host_ptr; + buffer_ranges[d.offset] = bound_range; } /* Handle UAV counter */ @@ -4449,8 +4457,8 @@ static void vkd3d_create_buffer_uav(struct d3d12_desc *descriptor, struct d3d12_ if (device->bindless_state.flags & VKD3D_RAW_VA_AUX_BUFFER) { - VkDeviceAddress *counter_addresses = descriptor->heap->raw_va_aux_buffer.host_ptr; - uint32_t descriptor_index = d3d12_desc_heap_offset(descriptor); + VkDeviceAddress *counter_addresses = d.heap->raw_va_aux_buffer.host_ptr; + uint32_t descriptor_index = d.offset; counter_addresses[descriptor_index] = uav_counter_address; } else @@ -4459,20 +4467,20 @@ static void vkd3d_create_buffer_uav(struct d3d12_desc *descriptor, struct d3d12_ &device->bindless_state, VKD3D_BINDLESS_SET_UAV | VKD3D_BINDLESS_SET_AUX_BUFFER); descriptor_info[vk_write_count].buffer_view = uav_counter_view; - vkd3d_init_write_descriptor_set(&vk_write[vk_write_count], descriptor, + vkd3d_init_write_descriptor_set(&vk_write[vk_write_count], &d, binding, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, &descriptor_info[vk_write_count]); vk_write_count++; } - vkd3d_descriptor_debug_write_descriptor(descriptor->heap->descriptor_heap_info.host_ptr, - descriptor->heap->cookie, descriptor->heap_offset, - descriptor_qa_flags, descriptor->metadata.cookie); + vkd3d_descriptor_debug_write_descriptor(d.heap->descriptor_heap_info.host_ptr, + d.heap->cookie, d.offset, + descriptor_qa_flags, d.view->cookie); VK_CALL(vkUpdateDescriptorSets(device->vk_device, vk_write_count, vk_write, 0, NULL)); } -static void vkd3d_create_texture_uav(struct d3d12_desc *descriptor, +static void vkd3d_create_texture_uav(vkd3d_cpu_descriptor_va_t desc_va, struct d3d12_device *device, struct d3d12_resource *resource, const D3D12_UNORDERED_ACCESS_VIEW_DESC *desc) { @@ -4480,15 +4488,18 @@ static void vkd3d_create_texture_uav(struct d3d12_desc *descriptor, union vkd3d_descriptor_info descriptor_info; struct vkd3d_view *view = NULL; VkWriteDescriptorSet vk_write; + struct d3d12_desc_split d; struct vkd3d_view_key key; uint32_t info_index; if (!resource) { - d3d12_descriptor_heap_write_null_descriptor_template(descriptor, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE); + d3d12_descriptor_heap_write_null_descriptor_template(desc_va, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE); return; } + d = d3d12_desc_decode_va(desc_va); + key.view_type = VKD3D_VIEW_TYPE_IMAGE; if (!init_default_texture_view_desc(&key.u.texture, resource, desc ? desc->Format : 0)) @@ -4554,23 +4565,23 @@ static void vkd3d_create_texture_uav(struct d3d12_desc *descriptor, info_index = vkd3d_bindless_state_find_set_info_index(&device->bindless_state, VKD3D_BINDLESS_SET_UAV | VKD3D_BINDLESS_SET_IMAGE); - descriptor->info.view = view; - descriptor->metadata.cookie = view ? view->cookie : 0; - descriptor->metadata.set_info_mask = 1u << info_index; - descriptor->metadata.flags = VKD3D_DESCRIPTOR_FLAG_VIEW | VKD3D_DESCRIPTOR_FLAG_NON_NULL; + d.view->info.view = view; + d.view->cookie = view ? view->cookie : 0; + d.types->set_info_mask = 1u << info_index; + d.types->flags = VKD3D_DESCRIPTOR_FLAG_VIEW | VKD3D_DESCRIPTOR_FLAG_NON_NULL; - vkd3d_init_write_descriptor_set(&vk_write, descriptor, + vkd3d_init_write_descriptor_set(&vk_write, &d, vkd3d_bindless_state_binding_from_info_index(&device->bindless_state, info_index), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptor_info); - vkd3d_descriptor_debug_write_descriptor(descriptor->heap->descriptor_heap_info.host_ptr, - descriptor->heap->cookie, descriptor->heap_offset, - VKD3D_DESCRIPTOR_QA_TYPE_STORAGE_IMAGE_BIT, descriptor->metadata.cookie); + vkd3d_descriptor_debug_write_descriptor(d.heap->descriptor_heap_info.host_ptr, + d.heap->cookie, d.offset, + VKD3D_DESCRIPTOR_QA_TYPE_STORAGE_IMAGE_BIT, d.view->cookie); VK_CALL(vkUpdateDescriptorSets(device->vk_device, 1, &vk_write, 0, NULL)); } -void d3d12_desc_create_uav(struct d3d12_desc *descriptor, struct d3d12_device *device, +void d3d12_desc_create_uav(vkd3d_cpu_descriptor_va_t desc_va, struct d3d12_device *device, struct d3d12_resource *resource, struct d3d12_resource *counter_resource, const D3D12_UNORDERED_ACCESS_VIEW_DESC *desc) { @@ -4594,9 +4605,9 @@ void d3d12_desc_create_uav(struct d3d12_desc *descriptor, struct d3d12_device *d FIXME("Ignoring counter resource %p.\n", counter_resource); if (is_buffer) - vkd3d_create_buffer_uav(descriptor, device, resource, counter_resource, desc); + vkd3d_create_buffer_uav(desc_va, device, resource, counter_resource, desc); else - vkd3d_create_texture_uav(descriptor, device, resource, desc); + vkd3d_create_texture_uav(desc_va, device, resource, desc); } bool vkd3d_create_raw_buffer_view(struct d3d12_device *device, @@ -4833,12 +4844,13 @@ static HRESULT d3d12_create_sampler(struct d3d12_device *device, return hresult_from_vk_result(vr); } -void d3d12_desc_create_sampler(struct d3d12_desc *sampler, +void d3d12_desc_create_sampler(vkd3d_cpu_descriptor_va_t desc_va, struct d3d12_device *device, const D3D12_SAMPLER_DESC *desc) { const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; union vkd3d_descriptor_info descriptor_info; VkWriteDescriptorSet vk_write; + struct d3d12_desc_split d; struct vkd3d_view_key key; struct vkd3d_view *view; uint32_t info_index; @@ -4849,6 +4861,8 @@ void d3d12_desc_create_sampler(struct d3d12_desc *sampler, return; } + d = d3d12_desc_decode_va(desc_va); + key.view_type = VKD3D_VIEW_TYPE_SAMPLER; key.u.sampler = *desc; @@ -4859,22 +4873,22 @@ void d3d12_desc_create_sampler(struct d3d12_desc *sampler, info_index = vkd3d_bindless_state_find_set_info_index(&device->bindless_state, VKD3D_BINDLESS_SET_SAMPLER); - sampler->info.view = view; - sampler->metadata.cookie = view->cookie; - sampler->metadata.set_info_mask = 1u << info_index; - sampler->metadata.flags = VKD3D_DESCRIPTOR_FLAG_VIEW | VKD3D_DESCRIPTOR_FLAG_NON_NULL; + d.view->info.view = view; + d.view->cookie = view->cookie; + d.types->set_info_mask = 1u << info_index; + d.types->flags = VKD3D_DESCRIPTOR_FLAG_VIEW | VKD3D_DESCRIPTOR_FLAG_NON_NULL; descriptor_info.image.sampler = view->vk_sampler; descriptor_info.image.imageView = VK_NULL_HANDLE; descriptor_info.image.imageLayout = VK_IMAGE_LAYOUT_UNDEFINED; - vkd3d_init_write_descriptor_set(&vk_write, sampler, + vkd3d_init_write_descriptor_set(&vk_write, &d, vkd3d_bindless_state_binding_from_info_index(&device->bindless_state, info_index), VK_DESCRIPTOR_TYPE_SAMPLER, &descriptor_info); - vkd3d_descriptor_debug_write_descriptor(sampler->heap->descriptor_heap_info.host_ptr, - sampler->heap->cookie, sampler->heap_offset, - VKD3D_DESCRIPTOR_QA_TYPE_SAMPLER_BIT, sampler->metadata.cookie); + vkd3d_descriptor_debug_write_descriptor(d.heap->descriptor_heap_info.host_ptr, + d.heap->cookie, d.offset, + VKD3D_DESCRIPTOR_QA_TYPE_SAMPLER_BIT, d.view->cookie); VK_CALL(vkUpdateDescriptorSets(device->vk_device, 1, &vk_write, 0, NULL)); } @@ -5186,7 +5200,7 @@ static D3D12_CPU_DESCRIPTOR_HANDLE * STDMETHODCALLTYPE d3d12_descriptor_heap_Get TRACE("iface %p, descriptor %p.\n", iface, descriptor); - descriptor->ptr = (SIZE_T)heap->descriptors; + *descriptor = heap->cpu_va; return descriptor; } @@ -5684,28 +5698,18 @@ fail: return hr; } -static void d3d12_descriptor_heap_init_descriptors(struct d3d12_descriptor_heap *descriptor_heap, - size_t descriptor_size) +static void d3d12_descriptor_heap_init_descriptors(struct d3d12_descriptor_heap *descriptor_heap) { - struct d3d12_desc *desc; + struct vkd3d_descriptor_metadata_types *meta; unsigned int i; - memset(descriptor_heap->descriptors, 0, descriptor_size * descriptor_heap->desc.NumDescriptors); - switch (descriptor_heap->desc.Type) { case D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV: case D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER: - desc = (struct d3d12_desc *)descriptor_heap->descriptors; - + meta = (struct vkd3d_descriptor_metadata_types *)descriptor_heap->descriptors; for (i = 0; i < descriptor_heap->desc.NumDescriptors; i++) - { - desc[i].heap = descriptor_heap; - desc[i].heap_offset = i; - /* If we begin copying from the descriptors right away, we should copy the null descriptors - * which are already initialized. */ - desc[i].metadata.set_info_mask = descriptor_heap->null_descriptor_template.set_info_mask; - } + meta[i].set_info_mask = descriptor_heap->null_descriptor_template.set_info_mask; break; case D3D12_DESCRIPTOR_HEAP_TYPE_RTV: @@ -5722,6 +5726,10 @@ HRESULT d3d12_descriptor_heap_create(struct d3d12_device *device, { size_t max_descriptor_count, descriptor_size; struct d3d12_descriptor_heap *object; + unsigned int num_descriptor_bits = 0; + unsigned int num_descriptors_pot = 0; + size_t required_size; + size_t alignment; HRESULT hr; if (!(descriptor_size = d3d12_device_get_descriptor_handle_increment_size(desc->Type))) @@ -5744,9 +5752,45 @@ HRESULT d3d12_descriptor_heap_create(struct d3d12_device *device, return E_OUTOFMEMORY; } - if (!(object = vkd3d_malloc_aligned(offsetof(struct d3d12_descriptor_heap, - descriptors[descriptor_size * desc->NumDescriptors]), D3D12_DESC_ALIGNMENT))) + if (desc->Type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV || desc->Type == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER) + { + /* Always allocate a POT number of descriptors. We want the CPU VA layout to be very specific. + * This allows us to synthesize pointers to the heap and metadata without + * performing any de-references, which is great, because it avoids cache misses, + * and reduces our dependency chain of memory accesses required to perform a descriptor copy. + * Missing caches in descriptor copies is a large chunk of our CPU overhead, so we should make sure to avoid it + * when we can. + * We encode descriptors as: + * <--- MSBs ------------------------------------------------------- LSBs ---> + * | descriptor_heap VA | heap_offset | log2i_ceil(num_descriptors) (5 bits) | + * The base VA of the heap therefore becomes descriptor_heap CPU VA + log2i_ceil(num_descriptors). + * The increment is set to 1 << 5. */ + + num_descriptor_bits = vkd3d_log2i_ceil(max(1, desc->NumDescriptors)); + num_descriptors_pot = 1u << num_descriptor_bits; + + required_size = sizeof(struct d3d12_descriptor_heap); + /* From base descriptor heap, we can offset directly to get metadata_bindings. + * Metadata view data is placed at an offset we can deduce from num descriptors. */ + required_size += num_descriptors_pot * sizeof(struct vkd3d_descriptor_metadata_types); + required_size += desc->NumDescriptors * sizeof(struct vkd3d_descriptor_metadata_view); + + /* The alignment should scale roughly with size of the heap, + * so any wasted space shouldn't really be that bad. */ + alignment = max(D3D12_DESC_ALIGNMENT, num_descriptors_pot * VKD3D_RESOURCE_DESC_INCREMENT); + } + else + { + /* For RTV/DSV just store the descriptors inline after the data structure. + * Performance isn't that critical. */ + required_size = sizeof(struct d3d12_descriptor_heap); + required_size += desc->NumDescriptors * sizeof(struct d3d12_rtv_desc); + alignment = D3D12_DESC_ALIGNMENT; + } + + if (!(object = vkd3d_malloc_aligned(required_size, alignment))) return E_OUTOFMEMORY; + memset(object, 0, required_size); if (FAILED(hr = d3d12_descriptor_heap_init(object, device, desc))) { @@ -5754,7 +5798,17 @@ HRESULT d3d12_descriptor_heap_create(struct d3d12_device *device, return hr; } - d3d12_descriptor_heap_init_descriptors(object, descriptor_size); + if (desc->Type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV || desc->Type == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER) + { + /* See comments above on how this is supposed to work */ + object->cpu_va.ptr = (SIZE_T)object + num_descriptor_bits; + } + else + { + object->cpu_va.ptr = (SIZE_T)object->descriptors; + } + + d3d12_descriptor_heap_init_descriptors(object); TRACE("Created descriptor heap %p.\n", object); diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index 7deb1a9c..8c2fd06e 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -1053,56 +1053,47 @@ struct vkd3d_descriptor_binding uint16_t binding; }; -struct vkd3d_descriptor_data +#define VKD3D_RESOURCE_DESC_INCREMENT_LOG2 5 +#define VKD3D_RESOURCE_DESC_INCREMENT (1u << VKD3D_RESOURCE_DESC_INCREMENT_LOG2) + +/* Arrange data so that it can pack as tightly as possible. + * When we copy descriptors, we must copy both structures. + * In copy_desc_range we scan through the entire metadata_binding, so + * this data structure should be small. */ +struct vkd3d_descriptor_metadata_types +{ + VkDescriptorType current_null_type; + uint16_t set_info_mask; + uint16_t flags; +}; +STATIC_ASSERT(sizeof(struct vkd3d_descriptor_metadata_types) == 8); + +struct vkd3d_descriptor_metadata_view { uint64_t cookie; - uint32_t set_info_mask; - uint32_t flags; - VkDescriptorType current_null_type; -}; - -#define D3D12_DESC_ALIGNMENT 64 -struct d3d12_desc -{ - /* Align d3d12_desc to 64 bytes for two reasons. - * - We need a POT size when reporting GPU addresses. - * In DXR, we will need to handle app-placed VAs in a local root signature, - * and the fastest approach we can use is uint(VA) >> 6 to derive an index. - * - Can avoid false sharing on cache lines if multiple threads - * modify adjacent descriptors somehow. */ - DECLSPEC_ALIGN(D3D12_DESC_ALIGNMENT) struct vkd3d_descriptor_data metadata; - struct d3d12_descriptor_heap *heap; - uint32_t heap_offset; union { VkDescriptorBufferInfo buffer; struct vkd3d_view *view; } info; }; -STATIC_ASSERT(sizeof(struct d3d12_desc) == 64); +STATIC_ASSERT(sizeof(struct vkd3d_descriptor_metadata_view) == 32); -static inline struct d3d12_desc *d3d12_desc_from_cpu_handle(D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle) -{ - return (struct d3d12_desc *)cpu_handle.ptr; -} +typedef uintptr_t vkd3d_cpu_descriptor_va_t; -static inline struct d3d12_desc *d3d12_desc_from_gpu_handle(D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle) -{ - return (struct d3d12_desc *)(intptr_t)gpu_handle.ptr; -} - -void d3d12_desc_copy(struct d3d12_desc *dst, struct d3d12_desc *src, +void d3d12_desc_copy(vkd3d_cpu_descriptor_va_t dst, vkd3d_cpu_descriptor_va_t src, unsigned int count, D3D12_DESCRIPTOR_HEAP_TYPE heap_type, struct d3d12_device *device); -void d3d12_desc_copy_single(struct d3d12_desc *dst, struct d3d12_desc *src, struct d3d12_device *device); -void d3d12_desc_create_cbv(struct d3d12_desc *descriptor, +void d3d12_desc_copy_single(vkd3d_cpu_descriptor_va_t dst, + vkd3d_cpu_descriptor_va_t src, struct d3d12_device *device); +void d3d12_desc_create_cbv(vkd3d_cpu_descriptor_va_t descriptor, struct d3d12_device *device, const D3D12_CONSTANT_BUFFER_VIEW_DESC *desc); -void d3d12_desc_create_srv(struct d3d12_desc *descriptor, +void d3d12_desc_create_srv(vkd3d_cpu_descriptor_va_t descriptor, struct d3d12_device *device, struct d3d12_resource *resource, const D3D12_SHADER_RESOURCE_VIEW_DESC *desc); -void d3d12_desc_create_uav(struct d3d12_desc *descriptor, struct d3d12_device *device, +void d3d12_desc_create_uav(vkd3d_cpu_descriptor_va_t descriptor, struct d3d12_device *device, struct d3d12_resource *resource, struct d3d12_resource *counter_resource, const D3D12_UNORDERED_ACCESS_VIEW_DESC *desc); -void d3d12_desc_create_sampler(struct d3d12_desc *sampler, +void d3d12_desc_create_sampler(vkd3d_cpu_descriptor_va_t sampler, struct d3d12_device *device, const D3D12_SAMPLER_DESC *desc); bool vkd3d_create_raw_buffer_view(struct d3d12_device *device, @@ -1110,6 +1101,7 @@ bool vkd3d_create_raw_buffer_view(struct d3d12_device *device, HRESULT d3d12_create_static_sampler(struct d3d12_device *device, const D3D12_STATIC_SAMPLER_DESC *desc, VkSampler *vk_sampler); +#define D3D12_DESC_ALIGNMENT 64 struct d3d12_rtv_desc { DECLSPEC_ALIGN(D3D12_DESC_ALIGNMENT) VkSampleCountFlagBits sample_count; @@ -1120,7 +1112,7 @@ struct d3d12_rtv_desc struct vkd3d_view *view; struct d3d12_resource *resource; }; -STATIC_ASSERT(sizeof(struct d3d12_rtv_desc) == 64); +STATIC_ASSERT(sizeof(struct d3d12_rtv_desc) == D3D12_DESC_ALIGNMENT); void d3d12_rtv_desc_copy(struct d3d12_rtv_desc *dst, struct d3d12_rtv_desc *src, unsigned int count); @@ -1176,6 +1168,7 @@ struct d3d12_descriptor_heap uint64_t gpu_va; D3D12_DESCRIPTOR_HEAP_DESC desc; + D3D12_CPU_DESCRIPTOR_HANDLE cpu_va; VkDescriptorPool vk_descriptor_pool; VkDescriptorSet vk_descriptor_sets[VKD3D_MAX_BINDLESS_DESCRIPTOR_SETS]; @@ -1197,6 +1190,8 @@ struct d3d12_descriptor_heap struct vkd3d_private_store private_store; + /* Here we pack metadata data structures for CBV_SRV_UAV and SAMPLER. + * For RTV/DSV heaps, we just encode rtv_desc structs inline. */ DECLSPEC_ALIGN(D3D12_DESC_ALIGNMENT) BYTE descriptors[]; }; @@ -1213,14 +1208,49 @@ static inline struct d3d12_descriptor_heap *impl_from_ID3D12DescriptorHeap(ID3D1 return CONTAINING_RECORD(iface, struct d3d12_descriptor_heap, ID3D12DescriptorHeap_iface); } -static inline uint32_t d3d12_desc_heap_offset(const struct d3d12_desc *dst) +/* Decodes descriptor heap VA (for resources only) and its offset. + * Somewhat cursed, but avoids any de-referencing to achieve this result. + * See d3d12_descriptor_heap_create for comments on how this works. */ + +struct d3d12_desc_split { - return dst->heap_offset; + struct d3d12_descriptor_heap *heap; + struct vkd3d_descriptor_metadata_types *types; + struct vkd3d_descriptor_metadata_view *view; + uint32_t offset; +}; + +static inline struct d3d12_desc_split d3d12_desc_decode_va(vkd3d_cpu_descriptor_va_t va) +{ + uintptr_t num_bits_descriptors; + struct d3d12_desc_split split; + uintptr_t heap_offset; + uintptr_t heap_va; + + /* 5 LSBs encode number of bits for descriptors. + * Over that, we have the heap offset (increment size is 32). + * Above that, we have the d3d12_descriptor_heap, which is allocated with enough alignment + * to contain these twiddle bits. */ + + num_bits_descriptors = va & (VKD3D_RESOURCE_DESC_INCREMENT - 1); + heap_offset = (va >> VKD3D_RESOURCE_DESC_INCREMENT_LOG2) & (((size_t)1 << num_bits_descriptors) - 1); + split.offset = (uint32_t)heap_offset; + + heap_va = va & ~(((size_t)1 << (num_bits_descriptors + VKD3D_RESOURCE_DESC_INCREMENT_LOG2)) - 1); + split.heap = (struct d3d12_descriptor_heap *)heap_va; + heap_va += offsetof(struct d3d12_descriptor_heap, descriptors); + split.types = (struct vkd3d_descriptor_metadata_types *)heap_va; + split.types += heap_offset; + heap_va += sizeof(struct vkd3d_descriptor_metadata_types) << num_bits_descriptors; + split.view = (struct vkd3d_descriptor_metadata_view *)heap_va; + split.view += heap_offset; + + return split; } static inline uint32_t d3d12_desc_heap_offset_from_gpu_handle(D3D12_GPU_DESCRIPTOR_HANDLE handle) { - return (uint32_t)handle.ptr / sizeof(struct d3d12_desc); + return (uint32_t)handle.ptr / VKD3D_RESOURCE_DESC_INCREMENT; } /* ID3D12QueryHeap */ @@ -2008,7 +2038,8 @@ struct d3d12_command_list LONG *outstanding_submissions_count; - const struct d3d12_desc *cbv_srv_uav_descriptors; + const struct vkd3d_descriptor_metadata_types *cbv_srv_uav_descriptors_types; + const struct vkd3d_descriptor_metadata_view *cbv_srv_uav_descriptors_view; struct d3d12_resource *vrs_image; @@ -3011,7 +3042,7 @@ static inline unsigned int d3d12_device_get_descriptor_handle_increment_size( { case D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV: case D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER: - return sizeof(struct d3d12_desc); + return VKD3D_RESOURCE_DESC_INCREMENT; case D3D12_DESCRIPTOR_HEAP_TYPE_RTV: case D3D12_DESCRIPTOR_HEAP_TYPE_DSV: