ash icon indicating copy to clipboard operation
ash copied to clipboard

AccelerationStructure and use of array of array reference

Open filnet opened this issue 4 years ago • 2 comments

Some functions like cmd_build_acceleration_structures take an array of array references as argument.

Those are a pain to build as you need to first create an array of arrays and then turn it into an array of array references. You also need to make sure the array of array lives as long as the array of array references. I ended up using the array_ref! macro.

let range_infos = {
    let mut range_infos: Vec<&[vk::AccelerationStructureBuildRangeInfoKHR]> =
        Vec::with_capacity(build_range_infos.len());
    for i in 0..build_range_infos.len() {
        range_infos.push(array_ref![build_range_infos, i, 1]);
    }
    range_infos
};

May be I am missing something (I am quite new to Rust). Is there a trick I am missing ?

Anyways, would it make sense to turn those arguments into array of arrays ?

The build_range_infos is such an array of array references.

 pub fn cmd_build_acceleration_structures(
    device: &ash::Device,
    command_pool: vk::CommandPool,
    submit_queue: vk::Queue,
    infos: &[vk::AccelerationStructureBuildGeometryInfoKHR],
    build_range_infos: &[&[vk::AccelerationStructureBuildRangeInfoKHR]],
) {
...
}

filnet avatar Feb 27 '21 15:02 filnet

That is, unfortunately, mapped to how vkCmdBuildAccelerationStructuresKHR works. See for example #365 that improves the safety around this function. Vulkan takes an array of pointers, so some allocation where these pointers are stored is necessary.

Since we are however iterating and transforming array slices (fat pointers, 16-bytes) to raw pointers (8-bytes) anyway we might as well changes this/these function(s) to take an impl Iterator<Item = &[vk::AccelerationStructureBuildRangeInfoKHR]> instead so that you do not need to push into a vector.

In the provided example you should be able to take a sub-slice of the array with &build_range_infos[i..i+1] where you seemingly have one geometry per acceleration structure. If having more than one geometry per accel struct the same can be done by storing them consecutively in a vector and creating a second vector with slice references into it.

MarijnS95 avatar Feb 27 '21 16:02 MarijnS95

https://github.com/Traverse-Research/ash/commit/a94b018b4101b97cd04fd42fa0e5d67f23a72e8d

With that you should be able to do something like:

    let build_range_infos: Vec<vk::AccelerationStructureBuildRangeInfoKHR> = todo!(); // One geometry per AS

    a.cmd_build_acceleration_structures(
        /*device is gone on master,*/
        cmd,
        infos,
        build_range_infos
            .iter()
            // Single geometry per acceleration structure
            .map(|rng| std::slice::from_ref(rng)),
    );

While existing applications using a slice/array/vec simply need to call .iter() there and it should all keep working.

MarijnS95 avatar Feb 27 '21 17:02 MarijnS95