// 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" // ====================================================================== // Instance // ====================================================================== PrRhiInstance *prRhiCreateInstance(PrRhiInstanceDesc desc, WpAllocator *alloc); void prRhiDestroyInstance(PrRhiInstance *inst, WpAllocator *alloc); // ====================================================================== // Physical device enumeration // ====================================================================== PrRhiPhysicalDeviceArray prRhiGetPhysicalDevices(PrRhiInstance *inst, const WpAllocator *scratch); void prRhiGetPhysicalDeviceName(PrRhiPhysicalDevice *pdev, WpStr8 *out); void prRhiGetPhysicalDeviceDriverInfo(PrRhiPhysicalDevice *pdev, WpStr8 *out); // ====================================================================== // Surface (platform-specific) // ====================================================================== PrRhiSurface *prRhiCreateSurface(PrRhiInstance *inst, void *window_handle, WpAllocator *alloc); void prRhiDestroySurface(PrRhiInstance *inst, PrRhiSurface *surface, WpAllocator *alloc); PrRhiSurfaceCapabilities prRhiGetSurfaceCapabilities(PrRhiPhysicalDevice *pdev, PrRhiSurface *surface); // ====================================================================== // Device // ====================================================================== PrRhiDevice *prRhiCreateDevice(PrRhiPhysicalDevice *pdev, PrRhiSurface *surface, PrRhiDeviceDesc desc, WpAllocator *alloc); void prRhiDestroyDevice(PrRhiDevice *device, WpAllocator *alloc); void prRhiDeviceWaitIdle(PrRhiDevice *device); // ====================================================================== // Swapchain // ====================================================================== PrRhiSwapchain *prRhiCreateSwapchain(PrRhiDevice *device, PrRhiSwapchainDesc desc, WpAllocator *alloc); void prRhiDestroySwapchain(PrRhiDevice *device, PrRhiSwapchain *swapchain, WpAllocator *alloc); 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, WpAllocator *alloc); PrRhiTexture *prRhiGetSwapchainTexture(PrRhiSwapchain *swapchain, u32 image_index); PrRhiTexture *prRhiGetSwapchainDepthTexture(PrRhiSwapchain *swapchain); // ====================================================================== // Buffers // ====================================================================== PrRhiBuffer *prRhiCreateBuffer(PrRhiDevice *device, PrRhiBufferDesc desc, WpAllocator *alloc); void prRhiDestroyBuffer(PrRhiDevice *device, PrRhiBuffer *buffer, WpAllocator *alloc); 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, WpAllocator *alloc); void prRhiDestroyTexture(PrRhiDevice *device, PrRhiTexture *texture, WpAllocator *alloc); // ====================================================================== // Samplers // ====================================================================== PrRhiSampler *prRhiCreateSampler(PrRhiDevice *device, PrRhiSamplerDesc desc, WpAllocator *alloc); void prRhiDestroySampler(PrRhiDevice *device, PrRhiSampler *sampler, WpAllocator *alloc); // ====================================================================== // Shaders (from SPIR-V) // ====================================================================== PrRhiShader *prRhiCreateShader(PrRhiDevice *device, PrRhiShaderDesc desc, WpAllocator *alloc); void prRhiDestroyShader(PrRhiDevice *device, PrRhiShader *shader, WpAllocator *alloc); // ====================================================================== // Pipeline layouts // ====================================================================== PrRhiPipelineLayout *prRhiCreatePipelineLayout(PrRhiDevice *device, PrRhiPipelineLayoutDesc desc, WpAllocator *alloc); void prRhiDestroyPipelineLayout(PrRhiDevice *device, PrRhiPipelineLayout *layout, WpAllocator *alloc); // ====================================================================== // Pipelines // ====================================================================== PrRhiPipeline *prRhiCreateGraphicsPipeline(PrRhiDevice *device, PrRhiGraphicsPipelineDesc desc, WpAllocator *alloc); PrRhiPipeline *prRhiCreateComputePipeline(PrRhiDevice *device, PrRhiComputePipelineDesc desc, WpAllocator *alloc); void prRhiDestroyPipeline(PrRhiDevice *device, PrRhiPipeline *pipeline, WpAllocator *alloc); // ====================================================================== // Descriptor set layouts // ====================================================================== PrRhiDescriptorSetLayout *prRhiCreateDescriptorSetLayout(PrRhiDevice *device, PrRhiDescriptorSetLayoutDesc desc, WpAllocator *alloc); void prRhiDestroyDescriptorSetLayout(PrRhiDevice *device, PrRhiDescriptorSetLayout *layout, WpAllocator *alloc); // ====================================================================== // Descriptor pools // ====================================================================== PrRhiDescriptorPool *prRhiCreateDescriptorPool(PrRhiDevice *device, PrRhiDescriptorPoolDesc desc, WpAllocator *alloc); void prRhiDestroyDescriptorPool(PrRhiDevice *device, PrRhiDescriptorPool *pool, WpAllocator *alloc); // ====================================================================== // Descriptor sets // ====================================================================== PrRhiDescriptorSet *prRhiAllocateDescriptorSet(PrRhiDevice *device, PrRhiDescriptorPool *pool, PrRhiDescriptorSetLayout *layout, u32 variable_count, WpAllocator *alloc); void prRhiFreeDescriptorSet(PrRhiDevice *device, PrRhiDescriptorPool *pool, PrRhiDescriptorSet *set, WpAllocator *alloc); void prRhiUpdateDescriptorSet(PrRhiDevice *device, PrRhiWriteDescriptorSetArray writes); // ====================================================================== // Fences and semaphores // ====================================================================== PrRhiFence *prRhiCreateFence(PrRhiDevice *device, PrRhiFenceDesc desc, WpAllocator *alloc); void prRhiDestroyFence(PrRhiDevice *device, PrRhiFence *fence, WpAllocator *alloc); 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, WpAllocator *alloc); void prRhiDestroySemaphore(PrRhiDevice *device, PrRhiSemaphore *semaphore, WpAllocator *alloc); // ====================================================================== // Command pools and command buffers // ====================================================================== PrRhiCommandPool *prRhiCreateCommandPool(PrRhiDevice *device, PrRhiCommandPoolDesc desc, WpAllocator *alloc); void prRhiDestroyCommandPool(PrRhiDevice *device, PrRhiCommandPool *pool, WpAllocator *alloc); PrRhiCommandBufferArray prRhiAllocateCommandBuffers(PrRhiDevice *device, PrRhiCommandPool *pool, u32 count, WpAllocator *alloc); void prRhiFreeCommandBuffers(PrRhiDevice *device, PrRhiCommandPool *pool, u32 count, 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, const u64 *offsets, u32 count); 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); // ====================================================================== // 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 #endif