ash/README.md
2016-12-09 19:25:48 +01:00

4.6 KiB

#ASH

A low level Vulkan wrapper for Rust

Why ASH?

Functions return a type VkResult<T> = Result<T, vk::Result> instead of an error code. No mutable references for the output are required.

    pub fn create_swapchain_khr(&self,
                                create_info: &vk::SwapchainCreateInfoKHR)
                                -> VkResult<vk::SwapchainKHR>;
    let swapchain = device.create_swapchain_khr(&swapchain_create_info).unwrap();

Always returns a Vec<T> for functions that output multiple values.

    pub fn get_swapchain_images_khr(&self,
                                    swapchain: vk::SwapchainKHR)
                                    -> VkResult<Vec<vk::Image>>;
    let present_images = device.get_swapchain_images_khr(swapchain).unwrap();

Ash uses always uses slices in functions.

    // C
    void vkCmdPipelineBarrier(
        VkCommandBuffer                             commandBuffer,
        VkPipelineStageFlags                        srcStageMask,
        VkPipelineStageFlags                        dstStageMask,
        VkDependencyFlags                           dependencyFlags,
        uint32_t                                    memoryBarrierCount,
        const VkMemoryBarrier*                      pMemoryBarriers,
        uint32_t                                    bufferMemoryBarrierCount,
        const VkBufferMemoryBarrier*                pBufferMemoryBarriers,
        uint32_t                                    imageMemoryBarrierCount,
        const VkImageMemoryBarrier*                 pImageMemoryBarriers);

    // Rust
    pub fn cmd_pipeline_barrier(&self,
                                command_buffer: vk::CommandBuffer,
                                src_stage_mask: vk::PipelineStageFlags,
                                dst_stage_mask: vk::PipelineStageFlags,
                                dependency_flags: vk::DependencyFlags,
                                memory_barriers: &[vk::MemoryBarrier],
                                buffer_memory_barriers: &[vk::BufferMemoryBarrier],
                                image_memory_barriers: &[vk::ImageMemoryBarrier]);

    device.cmd_pipeline_barrier(setup_command_buffer,
                                vk::PIPELINE_STAGE_TOP_OF_PIPE_BIT,
                                vk::PIPELINE_STAGE_TOP_OF_PIPE_BIT,
                                vk::DependencyFlags::empty(),
                                &[],
                                &[],
                                &[layout_transition_barrier]);

Ash still uses raw Vulkan structs. The only difference is type safety. Everything that can be an enum is an enum like vk::StructureType, flags are implemented similar to the Bitflags crate. Ash also follows the Rust style guide. The reason that Ash uses raw Vulkan structs is to be extensible, just like the Vulkan spec.

    let pool_create_info = vk::CommandPoolCreateInfo {
        s_type: vk::StructureType::CommandPoolCreateInfo,
        p_next: ptr::null(),
        flags: vk::COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
        queue_family_index: queue_family_index,
    };
    let pool = device.create_command_pool(&pool_create_info).unwrap();

Ash also takes care of loading the function pointers. Function pointers are split into 3 categories. Entry, Instance and Device. The reason for not loading it into a global is that in Vulkan you can have multiple devices and each device must load its own function pointers.

    // Looks for the vulkan lib in your path, alternatively you can supply the path explicitly.
    let entry = Entry::load_vulkan().unwrap();
    let instance: Instance = entry.create_instance(&create_info).expect("Instance creation error");
    let device: Device = instance.create_device(pdevice, &device_create_info)
        .unwrap();

You don't have to pass an Instance or Device handle anymore, this is done implicitly for you.

    // C
    VkResult vkCreateCommandPool(
        VkDevice                                    device,
        const VkCommandPoolCreateInfo*              pCreateInfo,
        const VkAllocationCallbacks*                pAllocator,
        VkCommandPool*                              pCommandPool);

    // Rust
    pub fn create_command_pool(&self,
                               create_info: &vk::CommandPoolCreateInfo)
                               -> VkResult<vk::CommandPool>;

    let pool = device.create_command_pool(&pool_create_info).unwrap();

Complete

In progress

  • Wrapping the complete spec
  • Optional extension loading

Not started

  • Custom allocators