vkd3d: Implement RTAS object creation.
When building acceleration structures, we need to have an VkAccelerationStructureKHR object, but the D3D12 API just uses a plain VA = ID3D12Resource::GetGPUVA() + offset. For this to work, we need to resolve the VA back to VkBuffer + offset. The only VkBuffer we can lookup is the original backing memory allocation in the VA map, and that allocation itself must own a view map, since we cannot tie the VA to any specific ID3D12Resource. Since creating an RTAS is not the common path, we allocate the view map on-demand with CAS. Signed-off-by: Hans-Kristian Arntzen <post@arntzen-software.no>
This commit is contained in:
parent
0fc80d9067
commit
3353ed14de
|
@ -279,6 +279,12 @@ static void vkd3d_memory_allocation_free(const struct vkd3d_memory_allocation *a
|
|||
vkd3d_va_map_free_fake_va(&allocator->va_map, allocation->resource.va, allocation->resource.size);
|
||||
}
|
||||
|
||||
if (allocation->resource.view_map)
|
||||
{
|
||||
vkd3d_view_map_destroy(allocation->resource.view_map, device);
|
||||
vkd3d_free(allocation->resource.view_map);
|
||||
}
|
||||
|
||||
if (allocation->flags & VKD3D_ALLOCATION_FLAG_GLOBAL_BUFFER)
|
||||
VK_CALL(vkDestroyBuffer(device->vk_device, allocation->resource.vk_buffer, NULL));
|
||||
|
||||
|
|
|
@ -585,6 +585,7 @@ static uint32_t vkd3d_view_entry_hash(const void *key)
|
|||
switch (k->view_type)
|
||||
{
|
||||
case VKD3D_VIEW_TYPE_BUFFER:
|
||||
case VKD3D_VIEW_TYPE_ACCELERATION_STRUCTURE:
|
||||
hash = hash_uint64((uint64_t)k->u.buffer.buffer);
|
||||
hash = hash_combine(hash, hash_uint64(k->u.buffer.offset));
|
||||
hash = hash_combine(hash, hash_uint64(k->u.buffer.size));
|
||||
|
@ -645,6 +646,7 @@ static bool vkd3d_view_entry_compare(const void *key, const struct hash_map_entr
|
|||
switch (k->view_type)
|
||||
{
|
||||
case VKD3D_VIEW_TYPE_BUFFER:
|
||||
case VKD3D_VIEW_TYPE_ACCELERATION_STRUCTURE:
|
||||
return k->u.buffer.buffer == e->key.u.buffer.buffer &&
|
||||
k->u.buffer.format == e->key.u.buffer.format &&
|
||||
k->u.buffer.offset == e->key.u.buffer.offset &&
|
||||
|
@ -753,6 +755,10 @@ struct vkd3d_view *vkd3d_view_map_create_view(struct vkd3d_view_map *view_map,
|
|||
SUCCEEDED(d3d12_create_sampler(device, &key->u.sampler, &view->vk_sampler));
|
||||
break;
|
||||
|
||||
case VKD3D_VIEW_TYPE_ACCELERATION_STRUCTURE:
|
||||
success = vkd3d_create_acceleration_structure_view(device, &key->u.buffer, &view);
|
||||
break;
|
||||
|
||||
default:
|
||||
ERR("Unsupported view type %u.\n", key->view_type);
|
||||
success = false;
|
||||
|
@ -2660,6 +2666,9 @@ static void vkd3d_view_destroy(struct vkd3d_view *view, struct d3d12_device *dev
|
|||
case VKD3D_VIEW_TYPE_SAMPLER:
|
||||
VK_CALL(vkDestroySampler(device->vk_device, view->vk_sampler, NULL));
|
||||
break;
|
||||
case VKD3D_VIEW_TYPE_ACCELERATION_STRUCTURE:
|
||||
VK_CALL(vkDestroyAccelerationStructureKHR(device->vk_device, view->vk_acceleration_structure, NULL));
|
||||
break;
|
||||
default:
|
||||
WARN("Unhandled view type %d.\n", view->type);
|
||||
}
|
||||
|
@ -2947,6 +2956,57 @@ bool vkd3d_create_buffer_view(struct d3d12_device *device, const struct vkd3d_bu
|
|||
return true;
|
||||
}
|
||||
|
||||
bool vkd3d_create_acceleration_structure_view(struct d3d12_device *device, const struct vkd3d_buffer_view_desc *desc,
|
||||
struct vkd3d_view **view)
|
||||
{
|
||||
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
|
||||
VkAccelerationStructureKHR vk_acceleration_structure;
|
||||
VkAccelerationStructureCreateInfoKHR create_info;
|
||||
VkDeviceAddress buffer_address;
|
||||
VkDeviceAddress rtas_address;
|
||||
struct vkd3d_view *object;
|
||||
VkResult vr;
|
||||
|
||||
create_info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR;
|
||||
create_info.pNext = NULL;
|
||||
create_info.type = VK_ACCELERATION_STRUCTURE_TYPE_GENERIC_KHR;
|
||||
create_info.createFlags = 0;
|
||||
create_info.deviceAddress = 0;
|
||||
create_info.buffer = desc->buffer;
|
||||
create_info.offset = desc->offset;
|
||||
create_info.size = desc->size;
|
||||
|
||||
vr = VK_CALL(vkCreateAccelerationStructureKHR(device->vk_device, &create_info, NULL, &vk_acceleration_structure));
|
||||
if (vr != VK_SUCCESS)
|
||||
return false;
|
||||
|
||||
if (!(object = vkd3d_view_create(VKD3D_VIEW_TYPE_ACCELERATION_STRUCTURE)))
|
||||
{
|
||||
VK_CALL(vkDestroyAccelerationStructureKHR(device->vk_device, vk_acceleration_structure, NULL));
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Sanity check. Spec should guarantee this.
|
||||
* There is a note in the spec for vkGetAccelerationStructureDeviceAddressKHR:
|
||||
* The acceleration structure device address may be different from the
|
||||
* buffer device address corresponding to the acceleration structure's
|
||||
* start offset in its storage buffer for acceleration structure types
|
||||
* other than VK_ACCELERATION_STRUCTURE_TYPE_GENERIC_KHR. */
|
||||
buffer_address = vkd3d_get_buffer_device_address(device, desc->buffer) + desc->offset;
|
||||
rtas_address = vkd3d_get_acceleration_structure_device_address(device, vk_acceleration_structure);
|
||||
if (buffer_address != rtas_address)
|
||||
{
|
||||
FIXME("buffer_address = 0x%"PRIx64", rtas_address = 0x%"PRIx64".\n", buffer_address, rtas_address);
|
||||
}
|
||||
|
||||
object->vk_acceleration_structure = vk_acceleration_structure;
|
||||
object->format = desc->format;
|
||||
object->info.buffer.offset = desc->offset;
|
||||
object->info.buffer.size = desc->size;
|
||||
*view = object;
|
||||
return true;
|
||||
}
|
||||
|
||||
#define VKD3D_VIEW_RAW_BUFFER 0x1
|
||||
|
||||
static bool vkd3d_create_buffer_view_for_resource(struct d3d12_device *device,
|
||||
|
@ -3755,6 +3815,19 @@ VkDeviceAddress vkd3d_get_buffer_device_address(struct d3d12_device *device, VkB
|
|||
return VK_CALL(vkGetBufferDeviceAddressKHR(device->vk_device, &address_info));
|
||||
}
|
||||
|
||||
VkDeviceAddress vkd3d_get_acceleration_structure_device_address(struct d3d12_device *device,
|
||||
VkAccelerationStructureKHR vk_acceleration_structure)
|
||||
{
|
||||
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
|
||||
|
||||
VkAccelerationStructureDeviceAddressInfoKHR address_info;
|
||||
address_info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR;
|
||||
address_info.pNext = NULL;
|
||||
address_info.accelerationStructure = vk_acceleration_structure;
|
||||
|
||||
return VK_CALL(vkGetAccelerationStructureDeviceAddressKHR(device->vk_device, &address_info));
|
||||
}
|
||||
|
||||
static void vkd3d_create_buffer_uav(struct d3d12_desc *descriptor, struct d3d12_device *device,
|
||||
struct d3d12_resource *resource, struct d3d12_resource *counter_resource,
|
||||
const D3D12_UNORDERED_ACCESS_VIEW_DESC *desc)
|
||||
|
|
|
@ -92,16 +92,16 @@ static void vkd3d_va_map_cleanup_tree(struct vkd3d_va_tree *tree)
|
|||
}
|
||||
}
|
||||
|
||||
static const struct vkd3d_unique_resource *vkd3d_va_map_find_small_entry(struct vkd3d_va_map *va_map,
|
||||
static struct vkd3d_unique_resource *vkd3d_va_map_find_small_entry(struct vkd3d_va_map *va_map,
|
||||
VkDeviceAddress va, size_t *index)
|
||||
{
|
||||
const struct vkd3d_unique_resource *resource = NULL;
|
||||
struct vkd3d_unique_resource *resource = NULL;
|
||||
size_t hi = va_map->small_entries_count;
|
||||
size_t lo = 0;
|
||||
|
||||
while (lo < hi)
|
||||
{
|
||||
const struct vkd3d_unique_resource *r;
|
||||
struct vkd3d_unique_resource *r;
|
||||
size_t i = lo + (hi - lo) / 2;
|
||||
|
||||
r = va_map->small_entries[i];
|
||||
|
@ -123,7 +123,7 @@ static const struct vkd3d_unique_resource *vkd3d_va_map_find_small_entry(struct
|
|||
return resource;
|
||||
}
|
||||
|
||||
void vkd3d_va_map_insert(struct vkd3d_va_map *va_map, const struct vkd3d_unique_resource *resource)
|
||||
void vkd3d_va_map_insert(struct vkd3d_va_map *va_map, struct vkd3d_unique_resource *resource)
|
||||
{
|
||||
VkDeviceAddress block_va, min_va, max_va;
|
||||
struct vkd3d_va_block *block;
|
||||
|
@ -219,10 +219,10 @@ void vkd3d_va_map_remove(struct vkd3d_va_map *va_map, const struct vkd3d_unique_
|
|||
}
|
||||
}
|
||||
|
||||
const struct vkd3d_unique_resource *vkd3d_va_map_deref(struct vkd3d_va_map *va_map, VkDeviceAddress va)
|
||||
static struct vkd3d_unique_resource *vkd3d_va_map_deref_mutable(struct vkd3d_va_map *va_map, VkDeviceAddress va)
|
||||
{
|
||||
const struct vkd3d_va_block *block = vkd3d_va_map_find_block(va_map, va);
|
||||
const struct vkd3d_unique_resource *resource = NULL;
|
||||
struct vkd3d_unique_resource *resource = NULL;
|
||||
|
||||
if (block)
|
||||
{
|
||||
|
@ -242,6 +242,64 @@ const struct vkd3d_unique_resource *vkd3d_va_map_deref(struct vkd3d_va_map *va_m
|
|||
return resource;
|
||||
}
|
||||
|
||||
const struct vkd3d_unique_resource *vkd3d_va_map_deref(struct vkd3d_va_map *va_map, VkDeviceAddress va)
|
||||
{
|
||||
return vkd3d_va_map_deref_mutable(va_map, va);
|
||||
}
|
||||
|
||||
VkAccelerationStructureKHR vkd3d_va_map_place_acceleration_structure(struct vkd3d_va_map *va_map,
|
||||
struct d3d12_device *device,
|
||||
VkDeviceAddress va)
|
||||
{
|
||||
struct vkd3d_unique_resource *resource;
|
||||
struct vkd3d_view_map *old_view_map;
|
||||
struct vkd3d_view_map *view_map;
|
||||
const struct vkd3d_view *view;
|
||||
struct vkd3d_view_key key;
|
||||
|
||||
resource = vkd3d_va_map_deref_mutable(va_map, va);
|
||||
if (!resource || !resource->va)
|
||||
return VK_NULL_HANDLE;
|
||||
|
||||
view_map = vkd3d_atomic_ptr_load_explicit(&resource->view_map, vkd3d_memory_order_acquire);
|
||||
if (!view_map)
|
||||
{
|
||||
/* This is the first time we attempt to place an AS on top of this allocation, so
|
||||
* CAS in a pointer. */
|
||||
view_map = vkd3d_malloc(sizeof(*view_map));
|
||||
if (!view_map)
|
||||
return VK_NULL_HANDLE;
|
||||
|
||||
if (FAILED(vkd3d_view_map_init(view_map)))
|
||||
{
|
||||
vkd3d_free(view_map);
|
||||
return VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
/* Need to release in case other RTASes are placed at the same time, so they observe
|
||||
* the initialized view map, and need to acquire if some other thread placed it. */
|
||||
old_view_map = vkd3d_atomic_ptr_compare_exchange(&resource->view_map, NULL, view_map,
|
||||
vkd3d_memory_order_release, vkd3d_memory_order_acquire);
|
||||
if (old_view_map)
|
||||
{
|
||||
vkd3d_view_map_destroy(view_map, device);
|
||||
vkd3d_free(view_map);
|
||||
view_map = old_view_map;
|
||||
}
|
||||
}
|
||||
|
||||
key.view_type = VKD3D_VIEW_TYPE_ACCELERATION_STRUCTURE;
|
||||
key.u.buffer.buffer = resource->vk_buffer;
|
||||
key.u.buffer.offset = va - resource->va;
|
||||
key.u.buffer.size = resource->size - key.u.buffer.offset;
|
||||
key.u.buffer.format = NULL;
|
||||
|
||||
view = vkd3d_view_map_create_view(view_map, device, &key);
|
||||
if (!view)
|
||||
return VK_NULL_HANDLE;
|
||||
return view->vk_acceleration_structure;
|
||||
}
|
||||
|
||||
#define VKD3D_FAKE_VA_ALIGNMENT (65536)
|
||||
|
||||
VkDeviceAddress vkd3d_va_map_alloc_fake_va(struct vkd3d_va_map *va_map, VkDeviceSize size)
|
||||
|
|
|
@ -297,14 +297,17 @@ struct vkd3d_va_map
|
|||
|
||||
pthread_mutex_t mutex;
|
||||
|
||||
const struct vkd3d_unique_resource **small_entries;
|
||||
struct vkd3d_unique_resource **small_entries;
|
||||
size_t small_entries_size;
|
||||
size_t small_entries_count;
|
||||
};
|
||||
|
||||
void vkd3d_va_map_insert(struct vkd3d_va_map *va_map, const struct vkd3d_unique_resource *resource);
|
||||
void vkd3d_va_map_insert(struct vkd3d_va_map *va_map, struct vkd3d_unique_resource *resource);
|
||||
void vkd3d_va_map_remove(struct vkd3d_va_map *va_map, const struct vkd3d_unique_resource *resource);
|
||||
const struct vkd3d_unique_resource *vkd3d_va_map_deref(struct vkd3d_va_map *va_map, VkDeviceAddress va);
|
||||
VkAccelerationStructureKHR vkd3d_va_map_place_acceleration_structure(struct vkd3d_va_map *va_map,
|
||||
struct d3d12_device *device,
|
||||
VkDeviceAddress va);
|
||||
VkDeviceAddress vkd3d_va_map_alloc_fake_va(struct vkd3d_va_map *va_map, VkDeviceSize size);
|
||||
void vkd3d_va_map_free_fake_va(struct vkd3d_va_map *va_map, VkDeviceAddress va, VkDeviceSize size);
|
||||
void vkd3d_va_map_init(struct vkd3d_va_map *va_map);
|
||||
|
@ -494,6 +497,8 @@ struct vkd3d_allocate_resource_memory_info
|
|||
void *host_ptr;
|
||||
};
|
||||
|
||||
struct vkd3d_view_map;
|
||||
|
||||
struct vkd3d_unique_resource
|
||||
{
|
||||
union
|
||||
|
@ -504,6 +509,10 @@ struct vkd3d_unique_resource
|
|||
uint64_t cookie;
|
||||
VkDeviceAddress va;
|
||||
VkDeviceSize size;
|
||||
|
||||
/* This is used to handle views when we cannot bind it to a
|
||||
* specific ID3D12Resource, i.e. RTAS. Only allocated as needed. */
|
||||
struct vkd3d_view_map *view_map;
|
||||
};
|
||||
|
||||
struct vkd3d_memory_allocation
|
||||
|
@ -759,6 +768,7 @@ enum vkd3d_view_type
|
|||
VKD3D_VIEW_TYPE_BUFFER,
|
||||
VKD3D_VIEW_TYPE_IMAGE,
|
||||
VKD3D_VIEW_TYPE_SAMPLER,
|
||||
VKD3D_VIEW_TYPE_ACCELERATION_STRUCTURE
|
||||
};
|
||||
|
||||
struct vkd3d_view
|
||||
|
@ -772,6 +782,7 @@ struct vkd3d_view
|
|||
VkBufferView vk_buffer_view;
|
||||
VkImageView vk_image_view;
|
||||
VkSampler vk_sampler;
|
||||
VkAccelerationStructureKHR vk_acceleration_structure;
|
||||
};
|
||||
const struct vkd3d_format *format;
|
||||
union
|
||||
|
@ -819,6 +830,8 @@ struct vkd3d_texture_view_desc
|
|||
|
||||
bool vkd3d_create_buffer_view(struct d3d12_device *device,
|
||||
const struct vkd3d_buffer_view_desc *desc, struct vkd3d_view **view);
|
||||
bool vkd3d_create_acceleration_structure_view(struct d3d12_device *device,
|
||||
const struct vkd3d_buffer_view_desc *desc, struct vkd3d_view **view);
|
||||
bool vkd3d_create_texture_view(struct d3d12_device *device,
|
||||
const struct vkd3d_texture_view_desc *desc, struct vkd3d_view **view);
|
||||
|
||||
|
@ -2603,6 +2616,8 @@ static inline unsigned int d3d12_resource_desc_get_sub_resource_count(const D3D1
|
|||
}
|
||||
|
||||
VkDeviceAddress vkd3d_get_buffer_device_address(struct d3d12_device *device, VkBuffer vk_buffer);
|
||||
VkDeviceAddress vkd3d_get_acceleration_structure_device_address(struct d3d12_device *device,
|
||||
VkAccelerationStructureKHR vk_acceleration_structure);
|
||||
|
||||
static inline VkDeviceAddress d3d12_resource_get_va(const struct d3d12_resource *resource, VkDeviceSize offset)
|
||||
{
|
||||
|
|
|
@ -207,6 +207,9 @@ VK_DEVICE_EXT_PFN(vkCmdTraceRaysIndirectKHR)
|
|||
|
||||
/* VK_KHR_acceleration_structure */
|
||||
VK_DEVICE_EXT_PFN(vkGetAccelerationStructureBuildSizesKHR)
|
||||
VK_DEVICE_EXT_PFN(vkCreateAccelerationStructureKHR)
|
||||
VK_DEVICE_EXT_PFN(vkDestroyAccelerationStructureKHR)
|
||||
VK_DEVICE_EXT_PFN(vkGetAccelerationStructureDeviceAddressKHR)
|
||||
|
||||
/* VK_KHR_fragment_shading_rate */
|
||||
VK_INSTANCE_PFN(vkGetPhysicalDeviceFragmentShadingRatesKHR)
|
||||
|
|
Loading…
Reference in New Issue