// vim:fileencoding=utf-8:foldmethod=marker // // Prism RHI — Render Hardware Interface // // Design based on the How To Vulkan tutorial (https://www.howtovulkan.com/) // which uses these modern Vulkan features: // - Vulkan 1.3 core (dynamic rendering, synchronization2, buffer device // address) // - Descriptor indexing (bindless with variable descriptor count) // - Dynamic state (viewport, scissor) // - VMA for memory management // - Vulkan profiles for device selection // - Slang for shader compilation (SPIR-V output) // // This RHI abstracts those features behind platform-agnostic types. // Backend selection is compile-time — define PR_RHI_VULKAN, PR_RHI_D3D12, // or PR_RHI_METAL at build time. // // Creation functions return the object directly or abort on failure. // Only swapchain acquire/present return a b8 — the caller can detect // out-of-date and recreate. #ifndef PR_RHI_H #define PR_RHI_H #include "pr_rhi_types.h" #include #ifdef __cplusplus extern "C" { #endif wp_extern PrRhiContext _G_RHI_CONTEXT; wp_extern void prRhiInit(void); wp_extern void prRhiDestroy(void); // ====================================================================== // Instance // ====================================================================== PrRhiInstance *prRhiCreateInstance(PrRhiInstanceDesc desc); void prRhiDestroyInstance(PrRhiInstance *inst); // ====================================================================== // Physical device enumeration // ====================================================================== PrRhiPhysicalDeviceArray prRhiGetPhysicalDevices(PrRhiInstance *inst); void prRhiGetPhysicalDeviceName(PrRhiPhysicalDevice *pdev, WpStr8 *out); void prRhiGetPhysicalDeviceDriverInfo(PrRhiPhysicalDevice *pdev, WpStr8 *out); PrRhiPhysicalDeviceProperties prRhiGetPhysicalDeviceProperties(PrRhiPhysicalDevice *pdev); // ====================================================================== // Surface (platform-specific) // ====================================================================== PrRhiSurface *prRhiCreateSurfaceFromWindow(PrRhiInstance *inst, SDL_Window *window); void prRhiDestroySurface(PrRhiInstance *inst, PrRhiSurface *surface); PrRhiSurfaceCapabilities prRhiGetSurfaceCapabilities(PrRhiPhysicalDevice *pdev, PrRhiSurface *surface); // ====================================================================== // Device // ====================================================================== PrRhiDevice *prRhiCreateDevice(PrRhiPhysicalDevice *pdev, PrRhiSurface *surface, PrRhiDeviceDesc desc); void prRhiDestroyDevice(PrRhiDevice *device); void prRhiDeviceWaitIdle(PrRhiDevice *device); u32 prRhiGetQueueFamilyIndex(PrRhiDevice *device); // ====================================================================== // Swapchain // ====================================================================== PrRhiSwapchain *prRhiCreateSwapchain(PrRhiDevice *device, PrRhiSwapchainDesc desc); void prRhiDestroySwapchain(PrRhiDevice *device, PrRhiSwapchain *swapchain); u32 prRhiGetSwapchainImageCount(PrRhiSwapchain *swapchain); PrRhiSwapchainResult prRhiAcquireNextImage(PrRhiDevice *device, PrRhiSwapchain *swapchain, PrRhiSemaphore *signal_semaphore, u32 *out_image_index); PrRhiSwapchainResult prRhiPresent(PrRhiDevice *device, PrRhiSwapchain *swapchain, PrRhiSemaphore *wait_semaphore); void prRhiRecreateSwapchain(PrRhiDevice *device, PrRhiSwapchain **swapchain, u32 width, u32 height); PrRhiTexture *prRhiGetSwapchainTexture(PrRhiSwapchain *swapchain, u32 image_index); PrRhiTexture *prRhiGetSwapchainDepthTexture(PrRhiSwapchain *swapchain); PrRhiFormat prRhiGetSwapchainFormat(PrRhiSwapchain *swapchain); // ====================================================================== // Buffers // ====================================================================== PrRhiBuffer *prRhiCreateBuffer(PrRhiDevice *device, PrRhiBufferDesc desc); void prRhiDestroyBuffer(PrRhiDevice *device, PrRhiBuffer *buffer); void *prRhiBufferMap(PrRhiDevice *device, PrRhiBuffer *buffer); void prRhiBufferUnmap(PrRhiDevice *device, PrRhiBuffer *buffer); PrRhiDeviceAddress prRhiGetBufferDeviceAddress(PrRhiDevice *device, PrRhiBuffer *buffer); // ====================================================================== // Textures // ====================================================================== PrRhiTexture *prRhiCreateTexture(PrRhiDevice *device, PrRhiTextureDesc desc); PrRhiTexture *prRhiCreateTextureFromKtx(PrRhiDevice *device, const char *path, PrRhiCommandPool *pool, PrRhiCommandBuffer *cb); void prRhiDestroyTexture(PrRhiDevice *device, PrRhiTexture *texture); // ====================================================================== // Samplers // ====================================================================== PrRhiSampler *prRhiCreateSampler(PrRhiDevice *device, PrRhiSamplerDesc desc); void prRhiDestroySampler(PrRhiDevice *device, PrRhiSampler *sampler); // ====================================================================== // Shaders (from SPIR-V) // ====================================================================== PrRhiShader *prRhiCreateShader(PrRhiDevice *device, PrRhiShaderDesc desc); void prRhiDestroyShader(PrRhiDevice *device, PrRhiShader *shader); // ====================================================================== // Pipeline layouts // ====================================================================== PrRhiPipelineLayout *prRhiCreatePipelineLayout(PrRhiDevice *device, PrRhiPipelineLayoutDesc desc); void prRhiDestroyPipelineLayout(PrRhiDevice *device, PrRhiPipelineLayout *layout); // ====================================================================== // Pipelines // ====================================================================== PrRhiPipeline *prRhiCreateGraphicsPipeline(PrRhiDevice *device, PrRhiGraphicsPipelineDesc desc); PrRhiPipeline *prRhiCreateComputePipeline(PrRhiDevice *device, PrRhiComputePipelineDesc desc); void prRhiDestroyPipeline(PrRhiDevice *device, PrRhiPipeline *pipeline); // ====================================================================== // Descriptor set layouts // ====================================================================== PrRhiDescriptorSetLayout *prRhiCreateDescriptorSetLayout(PrRhiDevice *device, PrRhiDescriptorSetLayoutDesc desc); void prRhiDestroyDescriptorSetLayout(PrRhiDevice *device, PrRhiDescriptorSetLayout *layout); // ====================================================================== // Descriptor pools // ====================================================================== PrRhiDescriptorPool *prRhiCreateDescriptorPool(PrRhiDevice *device, PrRhiDescriptorPoolDesc desc); void prRhiDestroyDescriptorPool(PrRhiDevice *device, PrRhiDescriptorPool *pool); // ====================================================================== // Descriptor sets // ====================================================================== PrRhiDescriptorSet *prRhiAllocateDescriptorSet(PrRhiDevice *device, PrRhiDescriptorPool *pool, PrRhiDescriptorSetLayout *layout, WpU32Array variable_descriptor_counts); void prRhiFreeDescriptorSet(PrRhiDevice *device, PrRhiDescriptorPool *pool, PrRhiDescriptorSet *set); void prRhiUpdateDescriptorSet(PrRhiDevice *device, PrRhiWriteDescriptorSetArray writes); // ====================================================================== // Fences and semaphores // ====================================================================== PrRhiFence *prRhiCreateFence(PrRhiDevice *device, PrRhiFenceDesc desc); void prRhiDestroyFence(PrRhiDevice *device, PrRhiFence *fence); void prRhiWaitForFences(PrRhiDevice *device, PrRhiFenceArray fences, u32 count, b8 wait_all, u64 timeout_ns); void prRhiResetFences(PrRhiDevice *device, PrRhiFenceArray fences, u32 count); PrRhiSemaphore *prRhiCreateSemaphore(PrRhiDevice *device); void prRhiDestroySemaphore(PrRhiDevice *device, PrRhiSemaphore *semaphore); // ====================================================================== // Command pools and command buffers // ====================================================================== PrRhiCommandPool *prRhiCreateCommandPool(PrRhiDevice *device); void prRhiDestroyCommandPool(PrRhiDevice *device, PrRhiCommandPool *pool); PrRhiCommandBufferArray prRhiAllocateCommandBuffers(PrRhiDevice *device, PrRhiCommandPool *pool, u32 count); void prRhiFreeCommandBuffers(PrRhiDevice *device, PrRhiCommandPool *pool, PrRhiCommandBufferArray buffers); // ====================================================================== // Command buffer recording // ====================================================================== void prRhiBeginCommandBuffer(PrRhiCommandBuffer *cb); void prRhiEndCommandBuffer(PrRhiCommandBuffer *cb); void prRhiResetCommandBuffer(PrRhiCommandBuffer *cb); // --- Pipeline barriers (synchronization2 style) --- void prRhiCmdPipelineBarrier(PrRhiCommandBuffer *cb, PrRhiImageMemoryBarrierArray image_barriers, PrRhiBufferMemoryBarrierArray buffer_barriers); // --- Dynamic rendering --- void prRhiCmdBeginRendering(PrRhiCommandBuffer *cb, PrRhiColorAttachmentArray color_attachments, const PrRhiDepthAttachment *depth_attachment); void prRhiCmdEndRendering(PrRhiCommandBuffer *cb); // --- Dynamic state --- void prRhiCmdSetViewport(PrRhiCommandBuffer *cb, f32 x, f32 y, f32 width, f32 height); void prRhiCmdSetScissor(PrRhiCommandBuffer *cb, i32 x, i32 y, u32 width, u32 height); // --- Binding --- void prRhiCmdBindPipeline(PrRhiCommandBuffer *cb, PrRhiPipelineBindPoint bind_point, PrRhiPipeline *pipeline); void prRhiCmdBindDescriptorSets(PrRhiCommandBuffer *cb, PrRhiPipelineBindPoint bind_point, PrRhiPipelineLayout *layout, u32 first_set, PrRhiDescriptorSetArray sets); void prRhiCmdPushConstants(PrRhiCommandBuffer *cb, PrRhiPipelineLayout *layout, PrRhiShaderStage stage_flags, u32 offset, u32 size, const void *data); // --- Vertex / index buffers --- void prRhiCmdBindVertexBuffers(PrRhiCommandBuffer *cb, u32 first_binding, PrRhiBufferArray buffers, WpU64Array offsets); void prRhiCmdBindIndexBuffer(PrRhiCommandBuffer *cb, PrRhiBuffer *buffer, u64 offset, PrRhiIndexType index_type); // --- Draw calls --- void prRhiCmdDraw(PrRhiCommandBuffer *cb, u32 vertex_count, u32 instance_count, u32 first_vertex, u32 first_instance); void prRhiCmdDrawIndexed(PrRhiCommandBuffer *cb, u32 index_count, u32 instance_count, u32 first_index, i32 vertex_offset, u32 first_instance); // --- Copy --- void prRhiCmdCopyBufferToImage(PrRhiCommandBuffer *cb, PrRhiBuffer *src, PrRhiTexture *dst, PrRhiBufferImageCopyArray copies); // ====================================================================== // Queue submission // ====================================================================== void prRhiQueueSubmit(PrRhiDevice *device, PrRhiCommandBuffer *cb, PrRhiSemaphore *wait_semaphore, PrRhiSemaphore *signal_semaphore, PrRhiFence *fence); // ====================================================================== // Backend dispatch // ====================================================================== #if defined(PR_RHI_VULKAN) # include "vulkan/pr_rhi_vk_aliases.h" #elif defined(PR_RHI_D3D12) # error "D3D12 backend not yet implemented" #elif defined(PR_RHI_METAL) # error "Metal backend not yet implemented" #else # error "Define one of: PR_RHI_VULKAN, PR_RHI_D3D12, PR_RHI_METAL" #endif #ifdef __cplusplus } #endif #endif