blob: 4c80e39ac69a97a002475c4aa4e802d3ce4e1d3d [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_GRAPHICS_LIB_COMPUTE_HOTSORT_PLATFORMS_VK_HOTSORT_VK_H_
#define SRC_GRAPHICS_LIB_COMPUTE_HOTSORT_PLATFORMS_VK_HOTSORT_VK_H_
//
// NOTE: reevaluate the HotSort/VK API once "Physical Storage Buffer
// Access" is more widely supported.
//
#include <vulkan/vulkan_core.h>
//
//
//
#include <stdbool.h>
#include <stdint.h>
//
//
//
#ifdef __cplusplus
extern "C" {
#endif
//
// HotSort/VK relies on pipeline layout compatibility:
//
// Push constants:
//
// - stages : VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT
// - offset : 0
// - size : 12
//
// Descriptor sets:
//
// - Input:
//
// * storage buffer at layout(set=in.set,binding=in.binding)
// * key-vals beginning at offset 'in'
//
// - Output:
//
// * storage buffer at layout(set=out.set,binding=out.binding)
// * key-vals beginning at offset 'out'
//
// The locations of the input and output buffers are declared at
// HotSort instance creation.
//
// The buffer offsets can vary with each invocation of hotsort_vk_sort().
//
//
// A HotSort target is an opaque structure containing target-specific
// configuration parameters and a bundle of SPIR-V modules.
//
// Targets are generated and specific to a particular device vendor,
// architecture and key-val configuration.
//
struct hotsort_vk_target;
//
// TARGET REQUIREMENTS: VULKAN
//
struct hotsort_vk_target_requirements
{
uint32_t ext_name_count;
char const ** ext_names;
VkPhysicalDeviceFeatures * pdf;
};
//
// Yields the extensions and features required by a HotSort target.
//
// If target is not NULL and requirements.ext_names is NULL then the
// respective count will be initialized.
//
// Returns false if:
//
// * target is NULL
// * requirements is NULL
// * requirements.ext_names is NULL
// * requirements.pdf is NULL
// * requirements.ext_name_count is too small
//
// Otherwise returns true.
//
bool
hotsort_vk_target_get_requirements(struct hotsort_vk_target const * const target,
struct hotsort_vk_target_requirements * const requirements);
//
// HotSort push constants are expected at offset 0
//
struct hotsort_vk_push
{
uint32_t kv_offset_in;
uint32_t kv_offset_out;
uint32_t kv_count;
};
// clang-format off
#define HOTSORT_VK_PUSH_CONSTANT_RANGE_STAGE_FLAGS VK_SHADER_STAGE_COMPUTE_BIT
#define HOTSORT_VK_PUSH_CONSTANT_RANGE_OFFSET 0
#define HOTSORT_VK_PUSH_CONSTANT_RANGE_SIZE sizeof(struct hotsort_vk_push)
// clang-format on
//
// Declare the offsets of the key-value arrays before sorting.
//
struct hotsort_vk_ds_offsets
{
VkDeviceSize in;
VkDeviceSize out;
};
//
// Create a HotSort instance for a target that operates on storage
// buffers at specific descriptor set locations.
//
struct hotsort_vk *
hotsort_vk_create(VkDevice device,
VkAllocationCallbacks const * allocator,
VkPipelineCache pipeline_cache,
VkPipelineLayout pipeline_layout,
struct hotsort_vk_target const * const target);
//
// Resources will be disposed of with the same device and allocator
// used for creation.
//
void
hotsort_vk_release(VkDevice device,
VkAllocationCallbacks const * const allocator,
struct hotsort_vk * const hs);
//
// Explicitly reveal what padding of maximum valued key-vals will be
// applied to the input and output buffers.
//
// Input:
// count : Input number of key-vals
//
// Output:
//
// slabs_in : Number of slabs for input key-vals
// padded_in : Padded number of input key-vals
// padded_out : Padded number of output key-vals
//
// Instead of implicitly padding the buffers, HotSort requires this
// explicit step to support use cases like:
//
// - Dynamically allocating an output buffer
// - Avoiding writing past the end of the input buffer
//
void
hotsort_vk_pad(struct hotsort_vk const * const hs,
uint32_t const count,
uint32_t * const slabs_in,
uint32_t * const padded_in,
uint32_t * const padded_out);
//
// Append commands to the command buffer that, when enqueued, will:
//
// 1. Possibly pad the input buffer with max-valued keys
// 2. Load padded_in key-vals from the input buffer
// 3. Sort the key-vals
// 4. Store padded_out key-vals to the output buffer
//
// Pipeline barriers should be applied as necessary, both before and
// after invoking this function.
//
// Note that the algorithm *may* perform transfer operations before
// executing the first compute shader read.
//
// The algorithm ends with a compute shader write to a storage buffer.
//
void
hotsort_vk_sort(VkCommandBuffer cb,
struct hotsort_vk const * const hs,
struct hotsort_vk_ds_offsets const * const offsets,
uint32_t const count,
uint32_t const padded_in,
uint32_t const padded_out,
bool const linearize);
//
//
//
#ifdef __cplusplus
}
#endif
//
//
//
#endif // SRC_GRAPHICS_LIB_COMPUTE_HOTSORT_PLATFORMS_VK_HOTSORT_VK_H_