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 <post@arntzen-software.no>
This commit is contained in:
Hans-Kristian Arntzen 2022-02-22 15:35:23 +01:00
parent b309913b6d
commit 84d632f194
6 changed files with 443 additions and 346 deletions

View File

@ -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,

View File

@ -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:

View File

@ -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;

View File

@ -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;

File diff suppressed because it is too large Load Diff

View File

@ -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: