single-header C library for compressing/interleaving arrays into GPU buffers, and vice versa.
  • C 96.5%
  • CMake 3.5%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2017-12-22 10:54:52 -08:00
tests Add support for 4-bit formats. Untested; buffer support for 4-bit formats seems pretty unheard of. 2017-12-22 10:54:52 -08:00
.clang-format Initial commit. Mostly functional, not necessarily fully-tested. 2017-11-26 20:45:35 -08:00
.gitignore Initial commit. Mostly functional, not necessarily fully-tested. 2017-11-26 20:45:35 -08:00
cds_gpubuf.h Add support for 4-bit formats. Untested; buffer support for 4-bit formats seems pretty unheard of. 2017-12-22 10:54:52 -08:00
CMakeLists.txt Initial commit. Mostly functional, not necessarily fully-tested. 2017-11-26 20:45:35 -08:00
README.md Attribute metadata table is now local to a function. Fixes #9 2017-11-26 20:46:22 -08:00

cds_gpubuf

A single-header C library to convert streams of data between common GPU-native data formats. It focuses on portability and ease of integration, rather than performance; if speed is critical, you probably want to use a compute shader instead.

Potential use cases:

  • Compressing vertex buffer data from raw floats to smaller, more cache-friendly formats.
  • Interleaving/deinterleaving data streams between SoA and AoS.
  • Decompressing GPU output buffers back to formats easily readable by the CPU.

Basic Usage

Include the header:

#define CDS_GPUBUF_IMPLEMENTATION
#include <cds_gpubuf.h>

Construct cdsgb_layout structs for the source and destination streams. Each cdsgb_layout is made up of one or more cdsgb_attribute structs, which define the format and location of each attribute within a stream element. Each attribute is assigned a layout-unique ID, which is used to match it with corresponding attributes in other layouts.

cdsgb_attribute src_attributes[3] = {
  {0, CDSGB_ATTR_FORMAT_R32G32B32_SFLOAT, 0},     // position
  {1, CDSGB_ATTR_FORMAT_R32G32_SFLOAT, 12},       // texcoord
  {2, CDSGB_ATTR_FORMAT_R32G32B32_SFLOAT, 20},    // normal
  {3, CDSGB_ATTR_FORMAT_R32G32B32A32_SFLOAT, 32}, // color
};
cdsgb_layout src_layout = { src_attributes, 4, 48 };

cdsgb_attribute dst_attributes[4] = {
  {0, CDSGB_ATTR_FORMAT_R32G32B32_SFLOAT, 0}, // position
  {1, CDSGB_ATTR_FORMAT_R16G16_UNORM, 12},    // texcoord
  {3, CDSGB_ATTR_FORMAT_R8G8B8A8_UNORM, 16},  // color
  {2, CDSGB_ATTR_FORMAT_R16G16B16_SNORM, 20}, // normal
};
cdsgb_layout dst_layout = { dst_attributes, 4, 26 };

Finally, call cdsgb_convert() to convert a data stream from one layout to another:

void *src_data = ...;
void *dst_data = ...;
int element_count = 100;
int convert_error = cdsgb_convert(src_data, &src_layout, dst_data, &dst_layout, element_count);
assert(convert_error == 0);

Advanced Usage

API-specific Format Enum Conversion

The cdsgb_attr_format enum describes all the attribute formats that can be processed by this library. Each rendering API defines its own list of supported formats, each with its own ordering. Use the provided cdsgb_get_format_as_*() and cdsgb_get_format_from_*() functions to convert between cdsgb_attr_format and the corresponding API-specific format enums.

cdsgb_attr_format fmt = CDSGB_ATTR_FORMAT_R32G32_SFLOAT;
VkFormat vk_attr_format =
    (VkFormat)cdsgb_get_format_as_vk(fmt);  // returns VK_FORMAT_R32G32_SFLOAT
fmt = cdsgb_get_format_from_vk(vk_attr_format);  // returns CDSGB_ATTR_FORMAT_R32G32_SFLOAT

Attribute ID matching

The id field in cdsgb_attribute is used to uniquely identify each attribute within a cdsgb_layout, and to match it with corresponding attributes in other layouts during conversion. Some consequences of this design:

  1. Attribute order does not need to match between layouts, so long as the IDs line up.
  2. The source and destination layouts do not need to contain the same sets of attributes for conversion to succeed.
    • If an attribute ID is present in src_layout but not in dst_layout, it is ignored during conversion.
    • If an attribute ID is present in dst_layout but not in src_layout, the contents of that attribute in the dst_buffer will not be modified during conversion.
    • If an attribute ID is present in both src_layout and dst_layout, it is converted normally.

Interleaving and De-interleaving data

The attribute ID matching rules allow data to be interleaved and de-interleaved. To interleave data from multiple streams, call cdsgb_convert() for each input stream with a single-attribute layout, using the same dst_layout and dst_buffer for each call. To de-interleave, reverse the process.