// vim:fileencoding=utf-8:foldmethod=marker
//
// Shared RHI types — enums, description structs, and opaque handle
// forward declarations. Included by both the umbrella pr_rhi.h and
// backend headers.

#ifndef PR_RHI_TYPES_H
#define PR_RHI_TYPES_H

#include "../../vendor/wapp/wapp.h"

#define PR_RHI_LOD_CLAMP_NONE 1000.0f

// ============================================================================
// Opaque handle types
// ============================================================================

typedef struct PrRhiInstance            PrRhiInstance;
typedef struct PrRhiPhysicalDevice      PrRhiPhysicalDevice;
typedef struct PrRhiDevice              PrRhiDevice;
typedef struct PrRhiSurface             PrRhiSurface;
typedef struct PrRhiSwapchain           PrRhiSwapchain;
typedef struct PrRhiBuffer              PrRhiBuffer;
typedef struct PrRhiTexture             PrRhiTexture;
typedef struct PrRhiSampler             PrRhiSampler;
typedef struct PrRhiShader              PrRhiShader;
typedef struct PrRhiPipelineLayout      PrRhiPipelineLayout;
typedef struct PrRhiPipeline            PrRhiPipeline;
typedef struct PrRhiDescriptorSetLayout PrRhiDescriptorSetLayout;
typedef struct PrRhiDescriptorPool      PrRhiDescriptorPool;
typedef struct PrRhiDescriptorSet       PrRhiDescriptorSet;
typedef struct PrRhiCommandPool         PrRhiCommandPool;
typedef struct PrRhiCommandBuffer       PrRhiCommandBuffer;
typedef struct PrRhiFence               PrRhiFence;
typedef struct PrRhiSemaphore           PrRhiSemaphore;

// ============================================================================
// Enums and flags
// ============================================================================

typedef enum PrRhiPhysicalDeviceType {
	PR_RHI_PHYSICAL_DEVICE_TYPE_OTHER          = 0,
	PR_RHI_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU = 1,
	PR_RHI_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU   = 2,
	PR_RHI_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU    = 3,
	PR_RHI_PHYSICAL_DEVICE_TYPE_CPU            = 4,
} PrRhiPhysicalDeviceType;

typedef enum PrRhiSwapchainResult {
	PR_RHI_SWAPCHAIN_SUCCESS        = 0,
	PR_RHI_SWAPCHAIN_OUT_OF_DATE,
} PrRhiSwapchainResult;

typedef enum PrRhiBufferUsage {
	PR_RHI_BUFFER_USAGE_VERTEX                 = 1 << 0,
	PR_RHI_BUFFER_USAGE_INDEX                  = 1 << 1,
	PR_RHI_BUFFER_USAGE_UNIFORM                = 1 << 2,
	PR_RHI_BUFFER_USAGE_STORAGE                = 1 << 3,
	PR_RHI_BUFFER_USAGE_TRANSFER_SRC           = 1 << 4,
	PR_RHI_BUFFER_USAGE_TRANSFER_DST           = 1 << 5,
	PR_RHI_BUFFER_USAGE_SHADER_DEVICE_ADDRESS  = 1 << 6,
} PrRhiBufferUsage;

typedef enum PrRhiTextureUsage {
	PR_RHI_TEXTURE_USAGE_SAMPLED            = 1 << 0,
	PR_RHI_TEXTURE_USAGE_COLOR_ATTACHMENT   = 1 << 1,
	PR_RHI_TEXTURE_USAGE_DEPTH_ATTACHMENT   = 1 << 2,
	PR_RHI_TEXTURE_USAGE_STORAGE            = 1 << 3,
	PR_RHI_TEXTURE_USAGE_TRANSFER_SRC       = 1 << 4,
	PR_RHI_TEXTURE_USAGE_TRANSFER_DST       = 1 << 5,
} PrRhiTextureUsage;

typedef enum PrRhiMemoryUsage {
	PR_RHI_MEMORY_GPU_ONLY,
	PR_RHI_MEMORY_CPU_TO_GPU,
	PR_RHI_MEMORY_CPU_ONLY,
} PrRhiMemoryUsage;

typedef enum PrRhiFormat {
	PR_RHI_FORMAT_UNDEFINED,
	PR_RHI_FORMAT_R8G8B8A8_SRGB,
	PR_RHI_FORMAT_R8G8B8A8_UNORM,
	PR_RHI_FORMAT_R16G16B16A16_SFLOAT,
	PR_RHI_FORMAT_R32G32B32A32_SFLOAT,
	PR_RHI_FORMAT_R32G32B32_SFLOAT,
	PR_RHI_FORMAT_R32G32_SFLOAT,
	PR_RHI_FORMAT_R32_SFLOAT,
	PR_RHI_FORMAT_D24_UNORM_S8_UINT,
	PR_RHI_FORMAT_D32_SFLOAT_S8_UINT,
	PR_RHI_FORMAT_B8G8R8A8_SRGB,
} PrRhiFormat;

typedef enum PrRhiImageLayout {
	PR_RHI_LAYOUT_UNDEFINED,
	PR_RHI_LAYOUT_ATTACHMENT_OPTIMAL,
	PR_RHI_LAYOUT_READ_ONLY_OPTIMAL,
	PR_RHI_LAYOUT_TRANSFER_SRC_OPTIMAL,
	PR_RHI_LAYOUT_TRANSFER_DST_OPTIMAL,
	PR_RHI_LAYOUT_PRESENT_SRC,
	PR_RHI_LAYOUT_GENERAL,
} PrRhiImageLayout;

typedef enum PrRhiShaderStage {
	PR_RHI_SHADER_STAGE_VERTEX   = 1 << 0,
	PR_RHI_SHADER_STAGE_FRAGMENT = 1 << 1,
	PR_RHI_SHADER_STAGE_COMPUTE  = 1 << 2,
} PrRhiShaderStage;

typedef enum PrRhiPipelineStage {
	PR_RHI_PIPELINE_STAGE_NONE                    = 0,
	PR_RHI_PIPELINE_STAGE_TOP_OF_PIPE             = 1 << 0,
	PR_RHI_PIPELINE_STAGE_TRANSFER                = 1 << 1,
	PR_RHI_PIPELINE_STAGE_VERTEX_SHADER           = 1 << 2,
	PR_RHI_PIPELINE_STAGE_FRAGMENT_SHADER         = 1 << 3,
	PR_RHI_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS    = 1 << 4,
	PR_RHI_PIPELINE_STAGE_LATE_FRAGMENT_TESTS     = 1 << 5,
	PR_RHI_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT = 1 << 6,
	PR_RHI_PIPELINE_STAGE_COMPUTE_SHADER          = 1 << 7,
	PR_RHI_PIPELINE_STAGE_BOTTOM_OF_PIPE          = 1 << 8,
} PrRhiPipelineStage;

typedef enum PrRhiAccess {
	PR_RHI_ACCESS_NONE                             = 0,
	PR_RHI_ACCESS_TRANSFER_READ                    = 1 << 0,
	PR_RHI_ACCESS_TRANSFER_WRITE                   = 1 << 1,
	PR_RHI_ACCESS_SHADER_READ                      = 1 << 2,
	PR_RHI_ACCESS_SHADER_WRITE                     = 1 << 3,
	PR_RHI_ACCESS_COLOR_ATTACHMENT_READ            = 1 << 4,
	PR_RHI_ACCESS_COLOR_ATTACHMENT_WRITE           = 1 << 5,
	PR_RHI_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ    = 1 << 6,
	PR_RHI_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE   = 1 << 7,
	PR_RHI_ACCESS_MEMORY_READ                      = 1 << 8,
	PR_RHI_ACCESS_MEMORY_WRITE                     = 1 << 9,
} PrRhiAccess;

typedef enum PrRhiDescriptorType {
	PR_RHI_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
	PR_RHI_DESCRIPTOR_TYPE_STORAGE_IMAGE,
	PR_RHI_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
	PR_RHI_DESCRIPTOR_TYPE_STORAGE_BUFFER,
} PrRhiDescriptorType;

typedef enum PrRhiDescriptorBindingFlag {
	PR_RHI_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND         = 1 << 0,
	PR_RHI_DESCRIPTOR_BINDING_PARTIALLY_BOUND           = 1 << 1,
	PR_RHI_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT = 1 << 2,
} PrRhiDescriptorBindingFlag;

typedef enum PrRhiPipelineBindPoint {
	PR_RHI_PIPELINE_BIND_POINT_GRAPHICS,
	PR_RHI_PIPELINE_BIND_POINT_COMPUTE,
} PrRhiPipelineBindPoint;

typedef enum PrRhiCompareOp {
	PR_RHI_COMPARE_OP_NEVER,
	PR_RHI_COMPARE_OP_LESS,
	PR_RHI_COMPARE_OP_EQUAL,
	PR_RHI_COMPARE_OP_LESS_OR_EQUAL,
	PR_RHI_COMPARE_OP_GREATER,
	PR_RHI_COMPARE_OP_NOT_EQUAL,
	PR_RHI_COMPARE_OP_GREATER_OR_EQUAL,
	PR_RHI_COMPARE_OP_ALWAYS,
} PrRhiCompareOp;

typedef enum PrRhiPrimitiveTopology {
	PR_RHI_TOPOLOGY_POINT_LIST,
	PR_RHI_TOPOLOGY_LINE_LIST,
	PR_RHI_TOPOLOGY_LINE_STRIP,
	PR_RHI_TOPOLOGY_TRIANGLE_LIST,
	PR_RHI_TOPOLOGY_TRIANGLE_STRIP,
	PR_RHI_TOPOLOGY_TRIANGLE_FAN,
	PR_RHI_TOPOLOGY_LINE_LIST_WITH_ADJACENCY,
	PR_RHI_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY,
	PR_RHI_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY,
	PR_RHI_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY,
	PR_RHI_TOPOLOGY_PATCH_LIST,
} PrRhiPrimitiveTopology;

typedef enum PrRhiIndexType {
	PR_RHI_INDEX_TYPE_UINT16,
	PR_RHI_INDEX_TYPE_UINT32,
} PrRhiIndexType;

typedef enum PrRhiPresentMode {
	PR_RHI_PRESENT_MODE_IMMEDIATE,
	PR_RHI_PRESENT_MODE_FIFO,
	PR_RHI_PRESENT_MODE_MAILBOX,
} PrRhiPresentMode;

typedef enum PrRhiFilter  { PR_RHI_FILTER_NEAREST, PR_RHI_FILTER_LINEAR } PrRhiFilter;
typedef enum PrRhiMipmapMode { PR_RHI_MIPMAP_MODE_NEAREST, PR_RHI_MIPMAP_MODE_LINEAR } PrRhiMipmapMode;
typedef enum PrRhiAddressMode {
	PR_RHI_ADDRESS_MODE_REPEAT,
	PR_RHI_ADDRESS_MODE_CLAMP_TO_EDGE,
	PR_RHI_ADDRESS_MODE_CLAMP_TO_BORDER,
} PrRhiAddressMode;

// ============================================================================
// Element types (referenced by array aliases)
// ============================================================================

typedef struct PrRhiPushConstantRange {
	PrRhiShaderStage stage_flags;
	u32              offset;
	u32              size;
} PrRhiPushConstantRange;

typedef struct PrRhiVertexInputBinding {
	u32 binding;
	u32 stride;
} PrRhiVertexInputBinding;

typedef struct PrRhiVertexAttribute {
	u32         location;
	u32         binding;
	PrRhiFormat format;
	u32         offset;
} PrRhiVertexAttribute;

typedef struct PrRhiColorBlendAttachment {
	u8 color_write_mask;
} PrRhiColorBlendAttachment;

typedef struct PrRhiDescriptorSetLayoutBinding {
	PrRhiDescriptorType        type;
	u32                        descriptor_count;
	PrRhiShaderStage           stage_flags;
	PrRhiDescriptorBindingFlag binding_flags;
} PrRhiDescriptorSetLayoutBinding;

typedef struct PrRhiDescriptorPoolSize {
	PrRhiDescriptorType type;
	u32                 descriptor_count;
} PrRhiDescriptorPoolSize;

typedef struct PrRhiDescriptorImageInfo {
	PrRhiTexture    *texture;
	PrRhiSampler    *sampler;
	PrRhiImageLayout layout;
} PrRhiDescriptorImageInfo;

typedef struct PrRhiDescriptorBufferInfo {
	PrRhiBuffer *buffer;
	u64          offset;
	u64          range;
} PrRhiDescriptorBufferInfo;

typedef struct PrRhiImageMemoryBarrier {
	PrRhiTexture     *texture;
	PrRhiImageLayout  old_layout;
	PrRhiImageLayout  new_layout;
	PrRhiPipelineStage src_stage_mask;
	PrRhiAccess        src_access_mask;
	PrRhiPipelineStage dst_stage_mask;
	PrRhiAccess        dst_access_mask;
} PrRhiImageMemoryBarrier;

typedef struct PrRhiBufferMemoryBarrier {
	PrRhiBuffer      *buffer;
	u64               offset;
	u64               size;
	PrRhiPipelineStage src_stage_mask;
	PrRhiAccess        src_access_mask;
	PrRhiPipelineStage dst_stage_mask;
	PrRhiAccess        dst_access_mask;
} PrRhiBufferMemoryBarrier;

typedef struct PrRhiBufferImageCopy {
	u64 buffer_offset;
	u32 mip_level;
	u32 width;
	u32 height;
} PrRhiBufferImageCopy;

typedef struct PrRhiColorAttachment {
	PrRhiTexture    *texture;
	PrRhiImageLayout layout;
	b8               clear;
	f32              clear_color[4];
} PrRhiColorAttachment;

// ============================================================================
// Typed array aliases
// ============================================================================

// Opaque handle arrays (pointer-to-pointer)
typedef PrRhiPhysicalDevice      **PrRhiPhysicalDeviceArray;
typedef PrRhiBuffer              **PrRhiBufferArray;
typedef PrRhiTexture             **PrRhiTextureArray;
typedef PrRhiFence               **PrRhiFenceArray;
typedef PrRhiSemaphore           **PrRhiSemaphoreArray;
typedef PrRhiCommandBuffer       **PrRhiCommandBufferArray;
typedef PrRhiDescriptorSetLayout **PrRhiDescriptorSetLayoutArray;
typedef PrRhiDescriptorSet       **PrRhiDescriptorSetArray;
// Value type arrays (contiguous structs/enums)
typedef PrRhiPushConstantRange          *PrRhiPushConstantRangeArray;
typedef PrRhiVertexInputBinding         *PrRhiVertexInputBindingArray;
typedef PrRhiVertexAttribute            *PrRhiVertexAttributeArray;
typedef PrRhiFormat                     *PrRhiFormatArray;
typedef PrRhiColorBlendAttachment       *PrRhiColorBlendAttachmentArray;
typedef PrRhiDescriptorSetLayoutBinding *PrRhiDescriptorSetLayoutBindingArray;
typedef PrRhiDescriptorPoolSize         *PrRhiDescriptorPoolSizeArray;
typedef PrRhiDescriptorImageInfo        *PrRhiDescriptorImageInfoArray;
typedef PrRhiDescriptorBufferInfo       *PrRhiDescriptorBufferInfoArray;
typedef PrRhiImageMemoryBarrier         *PrRhiImageMemoryBarrierArray;
typedef PrRhiBufferMemoryBarrier        *PrRhiBufferMemoryBarrierArray;
typedef PrRhiColorAttachment            *PrRhiColorAttachmentArray;
typedef PrRhiBufferImageCopy            *PrRhiBufferImageCopyArray;
typedef struct PrRhiWriteDescriptorSet  *PrRhiWriteDescriptorSetArray;

// ============================================================================
// Description structs
// ============================================================================

typedef struct PrRhiInstanceDesc {
	const char *app_name;
	u32         app_version;
} PrRhiInstanceDesc;

typedef struct PrRhiDeviceDesc {
	PrRhiPresentMode present_mode;
} PrRhiDeviceDesc;

typedef struct PrRhiBufferDesc {
	u64              size;
	PrRhiBufferUsage usage;
	PrRhiMemoryUsage memory;
} PrRhiBufferDesc;

typedef struct PrRhiTextureDesc {
	PrRhiFormat       format;
	u32               width;
	u32               height;
	u32               mip_levels;
	PrRhiTextureUsage usage;
} PrRhiTextureDesc;

typedef struct PrRhiSamplerDesc {
	PrRhiFilter      mag_filter;
	PrRhiFilter      min_filter;
	PrRhiMipmapMode  mipmap_mode;
	PrRhiAddressMode address_mode_u;
	PrRhiAddressMode address_mode_v;
	PrRhiAddressMode address_mode_w;
	f32              max_anisotropy;
	f32              min_lod;
	f32              max_lod;
} PrRhiSamplerDesc;

typedef struct PrRhiShaderDesc {
	const void *spirv_code;
	u64         spirv_size;
} PrRhiShaderDesc;

typedef struct PrRhiTextureSize {
	u32 width;
	u32 height;
} PrRhiTextureSize;

typedef struct PrRhiPipelineLayoutDesc {
	PrRhiDescriptorSetLayoutArray set_layouts;
	PrRhiPushConstantRangeArray   push_constant_ranges;
} PrRhiPipelineLayoutDesc;

typedef enum PrRhiPolygonMode {
	PR_RHI_POLYGON_MODE_FILL  = 0,
	PR_RHI_POLYGON_MODE_LINE  = 1,
	PR_RHI_POLYGON_MODE_POINT = 2,
} PrRhiPolygonMode;

typedef enum PrRhiCullMode {
	PR_RHI_CULL_MODE_NONE           = 0,
	PR_RHI_CULL_MODE_FRONT          = 0x00000001,
	PR_RHI_CULL_MODE_BACK           = 0x00000002,
	PR_RHI_CULL_MODE_FRONT_AND_BACK = 0x00000003,
} PrRhiCullMode;

typedef enum PrRhiFrontFace {
	PR_RHI_FRONT_FACE_COUNTER_CLOCKWISE = 0,
	PR_RHI_FRONT_FACE_CLOCKWISE         = 1,
} PrRhiFrontFace;

typedef enum PrRhiMultisampleCount {
	PR_RHI_SAMPLE_COUNT_1  = 0x00000001,
	PR_RHI_SAMPLE_COUNT_2  = 0x00000002,
	PR_RHI_SAMPLE_COUNT_4  = 0x00000004,
	PR_RHI_SAMPLE_COUNT_8  = 0x00000008,
	PR_RHI_SAMPLE_COUNT_16 = 0x00000010,
	PR_RHI_SAMPLE_COUNT_32 = 0x00000020,
	PR_RHI_SAMPLE_COUNT_64 = 0x00000040,
} PrRhiMultisampleCount;

typedef struct PrRhiGraphicsPipelineDesc {
	PrRhiShader                   *vertex_shader;
	const char                    *vertex_shader_entry_point;

	PrRhiShader                   *fragment_shader;
	const char                    *fragment_shader_entry_point;

	PrRhiVertexInputBindingArray   vertex_bindings;
	PrRhiVertexAttributeArray      vertex_attributes;

	PrRhiPrimitiveTopology         topology;

	PrRhiFormatArray               color_attachment_formats;
	PrRhiFormat                    depth_attachment_format;

	b8                             depth_test_enable;
	b8                             depth_write_enable;
	PrRhiCompareOp                 depth_compare_op;

	PrRhiColorBlendAttachmentArray blend_attachments;

	b8                             dynamic_viewport;
	b8                             dynamic_scissor;

	PrRhiPolygonMode               polygon_mode;

	PrRhiCullMode                  cull_mode;

	PrRhiFrontFace                 front_face;

	f32                            line_width;

	PrRhiMultisampleCount          multisample_count;

	PrRhiPipelineLayout           *layout;
} PrRhiGraphicsPipelineDesc;

typedef struct PrRhiComputePipelineDesc {
	PrRhiShader         *shader;
	const char          *shader_entry_point;
	PrRhiPipelineLayout *layout;
} PrRhiComputePipelineDesc;

typedef struct PrRhiDescriptorSetLayoutDesc {
	PrRhiDescriptorSetLayoutBindingArray bindings;
} PrRhiDescriptorSetLayoutDesc;

typedef struct PrRhiDescriptorPoolDesc {
	u32                          max_sets;
	PrRhiDescriptorPoolSizeArray pool_sizes;
} PrRhiDescriptorPoolDesc;

typedef struct PrRhiWriteDescriptorSet {
	PrRhiDescriptorSet            *dst_set;
	u32                            dst_binding;
	u32                            dst_array_element;
	PrRhiDescriptorType            type;
	PrRhiDescriptorImageInfoArray  image_info;
	PrRhiDescriptorBufferInfoArray buffer_info;
} PrRhiWriteDescriptorSet;

typedef struct PrRhiFenceDesc {
	b8 signaled;
} PrRhiFenceDesc;

typedef struct PrRhiSwapchainDesc {
	PrRhiSurface *surface;
	u32           width;
	u32           height;
	b8            has_depth;
	PrRhiFormat   depth_format;  // PR_RHI_FORMAT_UNDEFINED = auto-pick
} PrRhiSwapchainDesc;

typedef struct PrRhiSurfaceCapabilities {
	u32 min_image_count;
	u32 max_image_count;
	u32 current_width;
	u32 current_height;
	u32 min_width;
	u32 min_height;
	u32 max_width;
	u32 max_height;
} PrRhiSurfaceCapabilities;

typedef struct PrRhiPhysicalDeviceProperties {
	u32                     api_version;
	PrRhiPhysicalDeviceType device_type;
} PrRhiPhysicalDeviceProperties;

typedef u64 PrRhiDeviceAddress;

// ============================================================================
// RHI context (global, owns all RHI object lifetimes)
// ============================================================================

typedef struct PrRhiContext {
	WpAllocator allocator;
} PrRhiContext;

// --- Command buffer types ---

typedef struct PrRhiDepthAttachment {
	PrRhiTexture    *texture;
	PrRhiImageLayout layout;
	b8               clear;
	f32              clear_depth;
} PrRhiDepthAttachment;

#endif
