1
// Copyright 2021 The Fuchsia Authors. All rights reserved.
2
// Use of this source code is governed by a BSD-style license that can be
3
// found in the LICENSE file.
5
#ifndef SRC_GRAPHICS_LIB_COMPUTE_RADIX_SORT_PLATFORMS_VK_INCLUDE_RADIX_SORT_PLATFORMS_VK_RADIX_SORT_VK_H_
6
#define SRC_GRAPHICS_LIB_COMPUTE_RADIX_SORT_PLATFORMS_VK_INCLUDE_RADIX_SORT_PLATFORMS_VK_RADIX_SORT_VK_H_
12
#include <vulkan/vulkan_core.h>
28
// Radix Sort Vk is a high-performance sorting library for Vulkan 1.2.
30
// The sorting function is both directly and indirectly dispatchable.
38
// Get a Radix Sort target's Vulkan requirements.
40
// A Radix Sort target is a binary image containing configuration parameters and
41
// a bundle of SPIR-V modules.
43
// Targets are prebuilt and specific to a particular device vendor, architecture
44
// and key-val configuration.
46
// A Radix Sort instance can only be created with a VkDevice that is initialized
47
// with all of the target's required extensions and features.
49
// The `radix_sort_vk_target_get_requirements()` function yields the extensions
50
// and initialized feature flags required by a Radix Sort target.
52
// These requirements can be merged with other Vulkan library requirements
53
// before VkDevice creation.
55
// If the `.ext_names` member is NULL, the `.ext_name_count` member will be
58
// Returns `false` if:
60
// * The .ext_names field is NULL and the number of required extensions is
62
// * The .ext_name_count is less than the number of required extensions is
64
// * Any of the .pdf, .pdf11 or .pdf12 members are NULL.
66
// Otherwise, returns true.
68
typedef struct radix_sort_vk_target radix_sort_vk_target_t;
71
// NOTE: The library currently supports uint32_t and uint64_t keyvals.
74
#define RS_KV_DWORDS_MAX 2
80
struct rs_pipeline_layout_scatter
82
VkPipelineLayout even;
86
struct rs_pipeline_scatter
96
struct rs_pipeline_layouts_named
98
VkPipelineLayout init;
99
VkPipelineLayout fill;
100
VkPipelineLayout histogram;
101
VkPipelineLayout prefix;
102
struct rs_pipeline_layout_scatter scatter[RS_KV_DWORDS_MAX];
105
struct rs_pipelines_named
109
VkPipeline histogram;
111
struct rs_pipeline_scatter scatter[RS_KV_DWORDS_MAX];
115
#define RS_PIPELINE_LAYOUTS_HANDLES (sizeof(struct rs_pipeline_layouts_named) / sizeof(VkPipelineLayout))
116
#define RS_PIPELINES_HANDLES (sizeof(struct rs_pipelines_named) / sizeof(VkPipeline))
125
struct radix_sort_vk_target_config config;
129
struct rs_pipeline_layouts_named named;
130
VkPipelineLayout handles[RS_PIPELINE_LAYOUTS_HANDLES];
135
struct rs_pipelines_named named;
136
VkPipeline handles[RS_PIPELINES_HANDLES];
156
// Create a Radix Sort instance for a target.(VkCommandBuffer cb,
158
// Keyval size is implicitly determined by the target.
160
// Returns NULL on failure.
162
typedef struct radix_sort_vk radix_sort_vk_t;
168
radix_sort_vk_create(VkDevice device,
169
VkAllocationCallbacks const * ac,
171
const uint32_t* const* spv,
172
const uint32_t* spv_sizes,
173
struct radix_sort_vk_target_config config);
176
// Destroy the Radix Sort instance using the same device and allocator used at
180
radix_sort_vk_destroy(radix_sort_vk_t * rs, //
182
VkAllocationCallbacks const * ac);
185
// Returns the buffer size and alignment requirements for a maximum number of
188
// The radix sort implementation is not an in-place sorting algorithm so two
189
// non-overlapping keyval buffers are required that are at least
192
// The radix sort instance also requires an `internal` buffer during sorting.
194
// If the indirect dispatch sorting function is used, then an `indirect` buffer
197
// The alignment requirements for the keyval, internal, and indirect buffers
198
// must be honored. All alignments are power of 2.
201
// count : Maximum number of keyvals
204
// keyval_size : Size of a single keyval
206
// keyvals_size : Minimum size of the even and odd keyval buffers
207
// keyvals_alignment : Alignment of each keyval buffer
209
// internal_size : Minimum size of internal buffer
210
// internal_aligment : Alignment of the internal buffer
212
// indirect_size : Minimum size of indirect buffer
213
// indirect_aligment : Alignment of the indirect buffer
217
// VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
218
// VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT
222
// VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
223
// VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT
224
// VK_BUFFER_USAGE_TRANSFER_DST_BIT ("direct" mode only)
228
// VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
229
// VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT
230
// VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT
232
typedef struct radix_sort_vk_memory_requirements
234
VkDeviceSize keyval_size;
236
VkDeviceSize keyvals_size;
237
VkDeviceSize keyvals_alignment;
239
VkDeviceSize internal_size;
240
VkDeviceSize internal_alignment;
242
VkDeviceSize indirect_size;
243
VkDeviceSize indirect_alignment;
244
} radix_sort_vk_memory_requirements_t;
247
radix_sort_vk_get_memory_requirements(radix_sort_vk_t const * rs,
249
radix_sort_vk_memory_requirements_t * mr);
252
// Direct dispatch sorting
253
// -----------------------
255
// Using a key size of `key_bits`, sort `count` keyvals found in the
256
// `.devaddr_keyvals_even` buffer.
258
// Each internal sorting pass copies the keyvals from one keyvals buffer to the
261
// The number of internal sorting passes is determined by `.key_bits`.
263
// If an even number of internal sorting passes is required, the sorted keyvals
264
// will be found in the "even" keyvals buffer. Otherwise, the sorted keyvals
265
// will be found in the "odd" keyvals buffer.
267
// Which buffer has the sorted keyvals is returned in `keyvals_sorted`.
269
// A keyval's `key_bits` are the most significant bits of a keyval.
271
// The maximum number of key bits is determined by the keyval size.
273
// The keyval count must be less than (1 << 30) as well as be less than or equal
274
// to the count used to obtain the the memory requirements.
276
// The info struct's `ext` member must be NULL.
278
// This function appends push constants, dispatch commands, and barriers.
280
// Pipeline barriers should be applied as necessary, both before and after
281
// invoking this function.
283
// The sort begins with either a TRANSFER/WRITE or a COMPUTE/READ to the
284
// `internal` and `keyvals_even` buffers.
286
// The sort ends with a COMPUTE/WRITE to the `internal` and `keyvals_sorted`
291
// Direct dispatch sorting using VkDescriptorBufferInfo structures
292
// ---------------------------------------------------------------
294
typedef struct radix_sort_vk_sort_info
299
VkDescriptorBufferInfo keyvals_even;
300
VkDescriptorBufferInfo keyvals_odd;
301
VkDescriptorBufferInfo internal;
302
} radix_sort_vk_sort_info_t;
305
radix_sort_vk_sort(radix_sort_vk_t const * rs,
306
radix_sort_vk_sort_info_t const * info,
309
VkDescriptorBufferInfo * keyvals_sorted);
312
// Indirect dispatch sorting
313
// -------------------------
315
// Using a key size of `key_bits`, at pipeline execution time, load keyvals
316
// count from `devaddr_count` and sorts the keyvals in `.devaddr_keyvals_even`.
318
// Each internal sorting pass copies the keyvals from one keyvals buffer to the
321
// The number of internal sorting passes is determined by `.key_bits`.
323
// If an even number of internal sorting passes is required, the sorted keyvals
324
// will be found in the "even" keyvals buffer. Otherwise, the sorted keyvals
325
// will be found in the "odd" keyvals buffer.
327
// Which buffer has the sorted keyvals is returned in `keyvals_sorted`.
329
// A keyval's `key_bits` are the most significant bits of a keyval.
331
// The keyval count must be less than (1 << 30) as well as be less than or equal
332
// to the count used to obtain the the memory requirements.
334
// The info struct's `ext` member must be NULL.
336
// This function appends push constants, dispatch commands, and barriers.
338
// Pipeline barriers should be applied as necessary, both before and after
339
// invoking this function.
341
// The indirect radix sort begins with a COMPUTE/READ from the `count` buffer
342
// and ends with a COMPUTE/WRITE to the `internal` and the `keyvals_sorted`
345
// The `indirect` buffer must support USAGE_INDIRECT.
347
// The `count` buffer must be at least 4 bytes and 4-byte aligned.
351
// Indirect dispatch sorting using VkDescriptorBufferInfo structures
352
// -----------------------------------------------------------------
354
typedef struct radix_sort_vk_sort_indirect_info
358
VkDescriptorBufferInfo count;
359
VkDescriptorBufferInfo keyvals_even;
360
VkDescriptorBufferInfo keyvals_odd;
361
VkDescriptorBufferInfo internal;
362
VkDescriptorBufferInfo indirect;
363
} radix_sort_vk_sort_indirect_info_t;
366
radix_sort_vk_sort_indirect(radix_sort_vk_t const * rs,
367
radix_sort_vk_sort_indirect_info_t const * info,
370
VkDescriptorBufferInfo * keyvals_sorted);
384
#endif // SRC_GRAPHICS_LIB_COMPUTE_RADIX_SORT_PLATFORMS_VK_INCLUDE_RADIX_SORT_PLATFORMS_VK_RADIX_SORT_VK_H_