# Plan: RHI Global Context

## Goal

Replace per-call `WpAllocator *allocator` parameters with a global `PrRhiContext`
managed by the RHI. The RHI owns the lifetime of all objects it creates.

## Changes

### 1. `src/prism/rhi/pr_rhi_types.h` — Add context struct

Add after the existing typedefs:

```c
typedef struct PrRhiContext {
	WpAllocator main;     // objects returned to the user
	WpAllocator scratch;  // internal temporaries within functions
} PrRhiContext;
```

### 2. `src/prism/rhi/pr_rhi.h` — Public API changes

- Add `wp_extern PrRhiContext _G_RHI_CONTEXT;` declaration (near top, after includes)
- Add `wp_extern b8 prRhiInit(void);` and `wp_extern void prRhiDestroy(void);`
- Remove `WpAllocator *allocator` (and `const WpAllocator *allocator`) from **all** function signatures

### 3. `src/prism/rhi/pr_rhi.c` — New file (shared across backends)

```c
#include "pr_rhi.h"

PrRhiContext _G_RHI_CONTEXT;

b8 prRhiInit(void) {
	_G_RHI_CONTEXT.main    = wpMemArenaAllocatorInit(MiB(64));
	_G_RHI_CONTEXT.scratch = wpMemArenaAllocatorInit(MiB(32));
	return true;
}

void prRhiDestroy(void) {
	wpMemAllocatorFree(&_G_RHI_CONTEXT.scratch, ...);
	wpMemAllocatorFree(&_G_RHI_CONTEXT.main, ...);
}
```

### 4. `src/prism/rhi/vulkan/pr_rhi_vk.h` — Remove allocator from Vk declarations

Remove `WpAllocator *allocator` from all function declarations.

### 5. `src/prism/rhi/vulkan/pr_rhi_vk.c` — Implementation changes

For every function that previously took `WpAllocator *allocator`:

- Remove the parameter from the signature
- Replace `allocator` with `_G_RHI_CONTEXT.main` for:
  - `wpMemAllocatorAlloc(allocator, sizeof(...))` for user-facing objects (returned to caller)
  - `wpArrayAllocCapacity(...)` for arrays that are stored in user-facing structs
- Replace `allocator` with `_G_RHI_CONTEXT.scratch` for:
  - `wpArrayAllocCapacity(...)` for internal temporary arrays
  - `wpArrayDealloc(...)` for internal temporaries
- Replace `wpMemAllocatorFree(allocator, ...)` with `wpMemAllocatorFree(&_G_RHI_CONTEXT.main, ...)` for destroy functions
- Update internal calls (e.g. `prRhiCreateBufferVk` called from `prRhiCreateTextureFromKtxVk`)

**Specific internal/helper changes:**
- `_createSwapchainTexture` — remove `allocator` param, use `_G_RHI_CONTEXT.main`
- `prRhiCreateTextureFromKtxVk` — staging buffer uses `_G_RHI_CONTEXT.main` (it's a user-facing object destroyed by the user)
- `prRhiAllocateCommandBuffersVk` — VkCommandBuffer temp array uses scratch, PrRhiCommandBuffer array + structs use main
- `prRhiCreatePipelineLayoutVk` — VkDescriptorSetLayout/VkPushConstantRange overflow arrays use scratch
- `prRhiCreateDeviceVk` — VkQueueFamilyProperties2 array uses scratch

### 6. `src/prism/rhi/vulkan/pr_rhi_vk_aliases.h` — No changes needed

Aliases only map function names, not parameters.

## Allocator usage per function

| Function | Returned object | Allocator |
|----------|----------------|-----------|
| `prRhiCreateInstance` | PrRhiInstance | main |
| `prRhiDestroyInstance` | — | free from main |
| `prRhiGetPhysicalDevices` | PrRhiPhysicalDeviceArray + PrRhiPhysicalDevice structs | main |
| `prRhiCreateSurfaceFromWindow` | PrRhiSurface | main |
| `prRhiDestroySurface` | — | free from main |
| `prRhiCreateDevice` | PrRhiDevice | main (internal VkQueueFamilyProperties2 array → scratch) |
| `prRhiDestroyDevice` | — | free from main |
| `prRhiCreateSwapchain` | PrRhiSwapchain + images + depth | main (internal VkImage array → scratch) |
| `prRhiDestroySwapchain` | — | free from main |
| `prRhiRecreateSwapchain` | updates existing struct | main for new images/depth, scratch for temp arrays |
| `prRhiCreateBuffer` | PrRhiBuffer | main |
| `prRhiDestroyBuffer` | — | free from main |
| `prRhiCreateTexture` | PrRhiTexture | main |
| `prRhiCreateTextureFromKtx` | PrRhiTexture (staging buffer too) | main |
| `prRhiDestroyTexture` | — | free from main |
| `prRhiCreateSampler` | PrRhiSampler | main |
| `prRhiDestroySampler` | — | free from main |
| `prRhiCreateShader` | PrRhiShader | main |
| `prRhiDestroyShader` | — | free from main |
| `prRhiCreatePipelineLayout` | PrRhiPipelineLayout | main (internal overflow arrays → scratch) |
| `prRhiDestroyPipelineLayout` | — | free from main |
| `prRhiCreateGraphicsPipeline` | PrRhiPipeline | main |
| `prRhiCreateComputePipeline` | PrRhiPipeline | main |
| `prRhiDestroyPipeline` | — | free from main |
| `prRhiCreateDescriptorSetLayout` | PrRhiDescriptorSetLayout | main |
| `prRhiDestroyDescriptorSetLayout` | — | free from main |
| `prRhiCreateDescriptorPool` | PrRhiDescriptorPool | main |
| `prRhiDestroyDescriptorPool` | — | free from main |
| `prRhiAllocateDescriptorSet` | PrRhiDescriptorSet | main |
| `prRhiFreeDescriptorSet` | — | free from main |
| `prRhiCreateFence` | PrRhiFence | main |
| `prRhiDestroyFence` | — | free from main |
| `prRhiCreateSemaphore` | PrRhiSemaphore | main |
| `prRhiDestroySemaphore` | — | free from main |
| `prRhiCreateCommandPool` | PrRhiCommandPool | main |
| `prRhiDestroyCommandPool` | — | free from main |
| `prRhiAllocateCommandBuffers` | PrRhiCommandBufferArray + structs | main (internal VkCommandBuffer array → scratch) |
