rhi_types.h

cross platform rendering playground

src/backend/rhi_types.h

15.4 KB
#pragma once

#include <string>
#include <vector>

#include "core/globals.h"

namespace rhi {

struct Memory;
struct Queue;
struct Buffer;
struct BufferView;
struct Image;
struct ImageView;
struct CmdPool;
struct CmdBuffer;
struct RenderPipeline;
struct ComputePipeline;
struct Sampler;
struct QueryPool;
struct AccelStruct;
struct Swapchain;
struct Device;
struct Sync;
struct SyncPoint;
struct QueueWait;
struct QueueSignal;
struct QueueSubmitDesc;
struct ShaderCompiler;
struct ShaderModule;

enum class PipelineTopology : u8 {
    TRIANGLES,
    LINES,
    POINTS
};

enum class PipelineFillMode : u8 {
    SOLID,
    WIREFRAME
};

enum class PipelineCullMode : u8 {
    NONE,
    FRONT,
    BACK
};

enum class PipelineTriangleWindingOrder : u8 {
    CW,
    CCW,
};

enum class PipelineCompareOp : u8 {
    NEVER,
    LESS,
    EQUAL,
    LESS_EQUAL,
    GREATER,
    NOT_EQUAL,
    GREATER_EQUAL,
    ALWAYS
};

enum class PipelineBlendFactor : u8 {
    ZERO,
    ONE,
    SRC_ALPHA,
    ONE_MINUS_SRC_ALPHA,
    DST_ALPHA,
    ONE_MINUS_DST_ALPHA,
    SRC_COLOR,
    ONE_MINUS_SRC_COLOR,
    DST_COLOR,
    ONE_MINUS_DST_COLOR,
    SRC_ALPHA_SATURATE,
};

enum class PipelineBlendOp : u8 {
    ADD,
    SUBTRACT,
    REVERSE_SUBTRACT,
    MIN,
    MAX,
};

enum class SampleCount : u8 {
    Sample1 = 1,
    Sample2 = 2,
    Sample4 = 4,
    Sample8 = 8,
    Sample16 = 16,
    Sample32 = 32,
    Sample64 = 64
};

enum class ShaderStage : u32 {
    NONE = BIT(0),
    VERTEX = BIT(1),
    FRAGMENT = BIT(2),
    COMPUTE = BIT(3),
    MESH = BIT(4),
    TASK = BIT(5),
    GEOMETRY = BIT(6),
    RAYGEN = BIT(9),
    CLOSEST_HIT = BIT(10),
    ANY_HIT = BIT(11),
    MISS = BIT(12),
    INTERSECTION = BIT(13),
    CALLABLE = BIT(14),
    ALL = BIT(8)
};
ENUM_BIT_OPS(ShaderStage);

enum class ImageType : u8 {
    TYPE_2D,
    TYPE_3D,
    TYPE_CUBE
};

struct Extent2D {
    u32 width = 0;
    u32 height = 0;
};

enum class BufferUsage : u32 {
    None = 0,
    VertexBuffer = BIT(1),
    IndexBuffer = BIT(2),
    UniformBuffer = BIT(3),
    StorageBuffer = BIT(4),
    IndirectBuffer = BIT(5),
    CopySrc = BIT(6),
    CopyDst = BIT(7),
    ShaderAddr = BIT(8),
    AccelStructBuildInput = BIT(9),
    AccelStructStorage = BIT(10),
};
ENUM_BIT_OPS(BufferUsage);

enum class BufferMemType : u8 {
    Device,
    Upload,   // cpu write, mapped for lifetime
    Readback, // gpu write, mapped for lifetime
};

struct BufferDesc {
    u64 size = 0;
    BufferUsage usage = BufferUsage::StorageBuffer;
    BufferMemType memory = BufferMemType::Device;
    bool dedicated = false; // VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT, Metal MTLStorageModePrivate
    std::string name;
};

enum class BufferViewType : u8 {
    Uniform,
    Storage,
    Vertex,
    Index,
    Indirect,
    Texel,
};

enum class ImageViewType : u8 {
    Sampled,
    Storage,
    // Sentinel: "no view declared,
    // ImageResource uses it to mean "not shader-visible".
    // Kind of a sentinal hack for FG, need a better solution
    None,
};

enum class ImageUsage : u32 {
    None = 0,
    ColorAttachment = BIT(1),
    DepthAttachment = BIT(2),
    StencilAttachment = BIT(3),
    Sampled = BIT(4),
    Storage = BIT(5),
    TransferSrc = BIT(6),
    TransferDst = BIT(7),
    InputAttachment = BIT(8),
};
ENUM_BIT_OPS(ImageUsage);

enum class ImageAspect : u32 {
    None = BIT(0),
    Color = BIT(1),
    Depth = BIT(2),
    Stencil = BIT(3),
};
ENUM_BIT_OPS(ImageAspect);

enum class ImageFormat : u8 {
    UNDEFINED,
    R8_UNORM,
    RGBA8_UNORM,
    RGBA8_SRGB,
    BGRA8_UNORM,
    D32_FLOAT,
    RGBA16_FLOAT,
    RGBA32_FLOAT,
    RGB32_FLOAT,
    R10G10B10A2_UNORM,
    RG16_FLOAT,
    RG32_FLOAT,
    R32_FLOAT,
    R32_UINT,
    R16_FLOAT,
    BC7_UNORM,
    BC7_SRGB,
    ASTC6X6_UNORM,
    ASTC6X6_SRGB
};

enum class TextureViewDimension : u8 {
    TEXTURE_2D,
    TEXTURE_2D_ARRAY,
    TEXTURE_3D,
    TEXTURE_CUBE
};

enum class ComponentSwizzle : u8 {
    Identity,
    R,
    G,
    B,
    A,
    Zero,
    One
};

struct ImageDesc {
    u32 width = 0;
    u32 height = 0;
    u32 depth = 1;
    u32 mip_levels = 1;
    u32 layers = 1;
    bool is_cubemap = false;
    SampleCount sample_count = SampleCount::Sample1;
    ImageFormat format = ImageFormat::UNDEFINED;
    ImageUsage usage = ImageUsage::Sampled;
    std::string name;
};

enum class CmdPoolUsage : u32 {
    None = BIT(0),
    Transient = BIT(1),
    ResetCommandBuffer = BIT(2),
    Protected = BIT(3),
};
ENUM_BIT_OPS(CmdPoolUsage);

struct CmdPoolDesc {
    u32 queue_family_index = UINT32_MAX;
    CmdPoolUsage flags;
};

struct Viewport {
    f32 x = 0.0f;
    f32 y = 0.0f;
    f32 width;
    f32 height;
    f32 depth_min = 0.0f;
    f32 depth_max = 1.0f;
    bool flip_y = true;
};

struct Rect {
    i16 x = 0;
    i16 y = 0;
    i16 width;
    i16 height;
};

enum class IndexType : u8 {
    UINT16,
    UINT32,
};

enum class CmdBufferLevel : u8 {
    Primary,
    Secondary,
};

enum class CmdBufferUsage : u32 {
    None = BIT(0),
    OneTimeSubmit = BIT(1),
    RenderPassContinue = BIT(2),
    SimultaneousUse = BIT(3),
};
ENUM_BIT_OPS(CmdBufferUsage);

struct CmdBufferBeginDesc {
    CmdBufferUsage usage;
};

enum class PipelineStages : u64 {
    NONE = 0,
    TOP_OF_PIPE = 0x1,
    DRAW_INDIRECT = 0x2,
    VERTEX_INPUT = 0x4,
    VERTEX_SHADER = 0x8,
    TESS_CONTROL_SHADER = 0x10,
    TESS_EVALUATION_SHADER = 0x20,
    GEOMETRY_SHADER = 0x40,
    FRAGMENT_SHADER = 0x80,
    EARLY_FRAGMENT_TESTS = 0x100,
    LATE_FRAGMENT_TESTS = 0x200,
    COLOR_ATTACHMENT_OUTPUT = 0x400,
    COMPUTE_SHADER = 0x800,
    // ALL_TRANSFER = 0x1000, // vksync2 mismatch?
    BOTTOM_OF_PIPE = 0x2000,
    HOST = 0x4000,
    ALL_GRAPHICS = 0x8000,
    ALL_COMMANDS = 0x10000,
    TASK_SHADER = 0x80000,
    MESH_SHADER = 0x100000,
    RAY_TRACING_SHADER = 0x200000,
    ACCELERATION_STRUCTURE_BUILD = 0x2000000,
    ACCELERATION_STRUCTURE_COPY = 0x10000000,
    MICROMAP_BUILD = 0x4000000,
    COPY = 0x100000000ULL,
    RESOLVE = 0x200000000ULL,
    BLIT = 0x400000000ULL,
    CLEAR = 0x800000000ULL,
    INDEX_INPUT = 0x1000000000ULL,
    VERTEX_ATTRIBUTE_INPUT = 0x2000000000ULL,
    PRE_RASTERIZATION_SHADERS = 0x4000000000ULL,

    // backwards compat names, remove
    COLOR_ATTACHMENT = COLOR_ATTACHMENT_OUTPUT,
    INDIRECT = DRAW_INDIRECT,
    CLEAR_STORAGE = CLEAR,
    ACCELERATION_STRUCTURE = ACCELERATION_STRUCTURE_BUILD,
    MICROMAP = MICROMAP_BUILD,

    // wrapper aliases
    DEPTH_STENCIL_ATTACHMENT = EARLY_FRAGMENT_TESTS | LATE_FRAGMENT_TESTS,
    TESSELLATION_SHADERS = TESS_CONTROL_SHADER | TESS_EVALUATION_SHADER,
    MESH_SHADERS = TASK_SHADER | MESH_SHADER,
    RASTER_SHADERS = INDEX_INPUT | VERTEX_SHADER | FRAGMENT_SHADER | DEPTH_STENCIL_ATTACHMENT | COLOR_ATTACHMENT_OUTPUT,

    // Legacy alias
    ALL = ALL_COMMANDS,
};
ENUM_BIT_OPS_64(PipelineStages);

enum class ResourceState : u8 {
    Idle = 0,                 // no access, no stage (fresh / aliased transient)
    ColorDraw,                // write in color-output stage
    ColorFetch,               // read in color-output stage (blend / input / resolve-src)
    DepthDraw,                // write in depth-stencil-test stage
    DepthFetch,               // read in depth-stencil-test stage
    TextureSample,            // read in fragment/vertex stage (sampled texture)
    TextureSampleNonFragment, // read in vertex/compute stage (sampled texture)
    StorageRead,              // read in compute stage (storage image/buffer)
    StorageReadWrite,         // read+write in compute stage (storage image/buffer)
    VertexFetch,              // read in vertex-fetch stage (vertex buffer)
    IndexFetch,               // read in index-fetch stage (index buffer)
    IndirectFetch,            // read in indirect-draw stage (indirect args)
    UniformRead,              // read in any shader stage (uniform buffer)
    TransferFrom,             // read in transfer stage (copy/blit/resolve src)
    TransferTo,               // write in transfer stage (copy/blit/resolve dst, clear dst)
    HostRead,                 // read by host stage (destination-only barrier)
    AccelBuild,               // read+write in accel-build stage (TLAS/BLAS build)
    AccelTrace,               // read in accel-trace stage (ray trace / AS read)
    Display,                  // no access, handed to swapchain (was Present)
};

struct ImageRange {
    u32 mip = 0;
    u32 mip_count = REMAINING_MIPS;
    u32 layer = 0;
    u32 layer_count = REMAINING_LAYERS;
    ImageAspect aspect = ImageAspect::Color;
};

struct MemoryStats {
    u32 block_count = 0;
    u32 allocation_count = 0;
    u64 allocation_bytes = 0;
    u64 used_bytes = 0;
};

enum class LoadOp : u8 {
    LOAD,
    CLEAR
};

enum class StoreOp : u8 {
    STORE,
    DISCARD
};

enum class ResolveOp : u8 {
    NONE,
    AVERAGE,
    MIN,
    MAX,
    SAMPLE_ZERO,
};

struct ClearDepthStencil {
    f32 depth;
    u32 stencil;
};

union ClearColorValue {
    f32 float32[4];
    i32 int32[4];
    u32 uint32[4];
};

union ClearValue {
    ClearColorValue color;
    ClearDepthStencil depthStencil;
};

struct TextureCopyRegion {
    u32 SrcMipLevel;
    u32 SrcBaseArrayLayer;
    u32 SrcOffsetX;
    u32 SrcOffsetY;
    u32 SrcOffsetZ;
    u32 DstMipLevel;
    u32 DstBaseArrayLayer;
    u32 DstOffsetX;
    u32 DstOffsetY;
    u32 DstOffsetZ;
    u32 ExtentWidth;
    u32 ExtentHeight;
    u32 ExtentDepth;
};

struct BufferTextureCopyRegion {
    u64 buffer_offset;
    u32 buffer_row_length;
    u32 buffer_image_height;
    u32 mip_level;
    u32 base_array_layer;
    u32 layer_count;
    u32 texture_offset_x;
    u32 texture_offset_y;
    u32 texture_offset_z;
    u32 texture_extent_width;
    u32 texture_extent_height;
    u32 texture_extent_depth;
};

#define SWAPCHAIN_IMAGE_COUNT 3

#define MAX_FRAMES_IN_FLIGHT 2

struct Config {
    bool enable_validation = false;
    void *app_info = nullptr;
    std::vector<const char *> device_extensions;
    std::vector<const char *> instance_extensions;
    std::vector<const char *> instance_layers;

    u32 swapchain_image_count = SWAPCHAIN_IMAGE_COUNT;
    u32 max_frames_in_flight = MAX_FRAMES_IN_FLIGHT;
    bool vsync_enabled = true;
};

struct SwapchainDesc {
    void *native_window = nullptr;
    u32 width = 0;
    u32 height = 0;
    ImageFormat format = ImageFormat::UNDEFINED;
    u32 image_count = SWAPCHAIN_IMAGE_COUNT;
    bool vsync_enabled = true;
};

struct BufferViewDesc {
    Buffer *buffer = nullptr;
    u64 offset = 0;
    u64 size = 0;
    BufferViewType type = BufferViewType::Storage;
};

struct ImageViewDesc {
    Image *image = nullptr;
    ImageAspect aspect = ImageAspect::None;
    TextureViewDimension dimension = TextureViewDimension::TEXTURE_2D;
    ImageViewType type = ImageViewType::Sampled;
    u32 mip_start = 0;
    u32 mip_count = 1;
    u32 layer_start = 0;
    u32 layer_count = 1;
    ComponentSwizzle swizzle_r = ComponentSwizzle::Identity;
    ComponentSwizzle swizzle_g = ComponentSwizzle::Identity;
    ComponentSwizzle swizzle_b = ComponentSwizzle::Identity;
    ComponentSwizzle swizzle_a = ComponentSwizzle::Identity;
};

enum class SamplerAddressMode : u8 {
    WRAP,
    MIRROR,
    CLAMP,
    BORDER
};

enum class SamplerFilter : u8 {
    POINT,
    LINEAR,
    ANISOTROPIC
};

enum class SamplerComparisonFunc : u8 {
    NEVER,
    LESS,
    EQUAL,
    LESS_EQUAL,
    GREATER,
    NOT_EQUAL,
    GREATER_EQUAL,
    ALWAYS
};

struct SamplerDesc {
    SamplerAddressMode address = SamplerAddressMode::WRAP;
    SamplerFilter filter = SamplerFilter::LINEAR;
    SamplerComparisonFunc comparison_func = SamplerComparisonFunc::NEVER;
    bool use_mips = false;
    std::string name;
};

enum class QueryType : u8 {
    TIMESTAMP,
    TIMESTAMP_COPY_QUEUE,
    OCCLUSION,
    PIPELINE_STATISTICS,
    ACCELERATION_STRUCTURE_SIZE,
    ACCELERATION_STRUCTURE_COMPACTED_SIZE,
    MICROMAP_COMPACTED_SIZE
};

struct QueryPoolDesc {
    QueryType queryType;
    u32 capacity;
    std::string name;
};

struct AccelStructTransform {
    f32 matrix[3][4];
};

struct AccelStructInstance {
    AccelStructTransform transform;
    u32 instance_custom_index : 24;
    u32 mask : 8;
    u32 sbt_record_offset : 24;
    u32 flags : 8;
    u64 acceleration_structure_reference;
};

enum class AccelStructInstanceFlags : u8 {
    None = 0,
    TriangleFacingCullDisable = BIT(0),
    TriangleFlipFacing = BIT(1),
    ForceOpaque = BIT(2),
    ForceNoOpaque = BIT(3),
};
ENUM_BIT_OPS(AccelStructInstanceFlags);

enum class AccelStructType : u8 {
    BottomLevel,
    TopLevel,
};

enum class AccelStructGeometryType : u8 {
    Triangles,
    Instances,
};

enum class AccelStructGeometryFlags : u8 {
    None = 0,
    Opaque = BIT(0),
    NoDuplicateAnyHitInvocation = BIT(1),
};
ENUM_BIT_OPS(AccelStructGeometryFlags);

enum class AccelStructBuildFlags : u8 {
    None = 0,
    AllowUpdate = BIT(0),
    AllowCompaction = BIT(1),
    PreferFastTrace = BIT(2),
    PreferFastBuild = BIT(3),
    LowMemory = BIT(4),
};
ENUM_BIT_OPS(AccelStructBuildFlags);

enum class VertexFormat : u8 {
    Undefined,
    R32G32B32_FLOAT,
    R32G32B32A32_FLOAT,
};

struct AccelStructGeometryTrianglesData {
    VertexFormat vertex_format = VertexFormat::R32G32B32_FLOAT;
    u64 vertex_data = 0;
    u64 vertex_stride = 0;
    u32 max_vertex = 0;
    IndexType index_type = IndexType::UINT32;
    u64 index_data = 0;
    u64 transform_data = 0;
};

struct AccelStructGeometryInstancesData {
    u64 data = 0;
    bool array_of_pointers = false;
};

struct AccelStructGeometry {
    AccelStructGeometryType type = AccelStructGeometryType::Triangles;
    AccelStructGeometryFlags flags = AccelStructGeometryFlags::None;
    union {
        AccelStructGeometryTrianglesData triangles;
        AccelStructGeometryInstancesData instances;
    };
};

struct AccelStructBuildRangeInfo {
    u32 primitive_count = 0;
    u32 primitive_offset = 0;
    u32 first_vertex = 0;
    u32 transform_offset = 0;
};

struct AccelStructBuildSizesInfo {
    u64 acceleration_structure_size = 0;
    u64 update_scratch_size = 0;
    u64 build_scratch_size = 0;
};

struct ImageBlit {
    u32 src_mip = 0;
    u32 dst_mip = 0;
    u32 src_layer = 0;
    u32 dst_layer = 0;
    i32 src_x0 = 0, src_y0 = 0, src_x1 = 0, src_y1 = 0;
    i32 dst_x0 = 0, dst_y0 = 0, dst_x1 = 0, dst_y1 = 0;
};

// VkDrawIndexedIndirectCommand
inline constexpr u32 DRAW_INDEXED_INDIRECT_STRIDE = 5 * sizeof(u32);

struct CmdBufferDesc {
    CmdPool *pool = nullptr;
    CmdBufferLevel level = CmdBufferLevel::Primary;
};

struct AttachmentDesc {
    ImageView *img = nullptr;
    ImageView *resolveImg = nullptr;
    LoadOp loadOp = LoadOp::LOAD;
    StoreOp storeOp = StoreOp::STORE;
    ResolveOp resolveOp = ResolveOp::NONE;
    ClearValue clearValue{};
};

struct RenderingInfo {
    AttachmentDesc colorAttachments[8];
    u32 colorAttachmentCount;
    AttachmentDesc depthAttachment;
    u32 width;
    u32 height;
};

// Barrier descs removed; see barrier() overloads in rhi_api.h.

struct VertexAttribute {
    u32 location;
    u32 binding;
    ImageFormat format;
    u32 offset;
};

struct VertexBinding {
    u32 binding;
    u32 stride;
    bool is_instanced{false};
};

struct AccelStructBuildGeometryInfo {
    AccelStructType type = AccelStructType::BottomLevel;
    AccelStructBuildFlags flags = AccelStructBuildFlags::None;
    AccelStruct *dst_acceleration_structure = nullptr;
    AccelStructGeometry *geometries = nullptr;
    u32 geometry_count = 0;
    u64 scratch_data = 0;
};

struct AccelStructCreateInfo {
    Buffer *buffer = nullptr;
    u64 offset = 0;
    u64 size = 0;
    AccelStructType type = AccelStructType::BottomLevel;
    std::string name;
};

} // namespace rhi