RHI vulkan updates
This commit is contained in:
@@ -16,6 +16,21 @@ Use this when working on any file in `src/prism/rhi/`, or when creating a new ba
|
||||
|
||||
## Conventions
|
||||
|
||||
### Global context
|
||||
|
||||
RHI functions do **not** take allocator parameters. A global `PrRhiContext` provides two allocators:
|
||||
- `allocator` — for user-facing objects (buffers, textures, pipelines, etc.)
|
||||
- `tmp` — for short-lived internal temporaries
|
||||
|
||||
```c
|
||||
extern PrRhiContext _G_RHI_CONTEXT;
|
||||
|
||||
void prRhiInit(void); // sets up both allocators
|
||||
void prRhiDestroy(void); // tears down context
|
||||
```
|
||||
|
||||
All RHI functions access `_G_RHI_CONTEXT` directly. Do not pass allocators to RHI API calls.
|
||||
|
||||
### Backend dispatch
|
||||
|
||||
Backend selection is compile-time via `-D PR_RHI_VULKAN` / `-D PR_RHI_D3D12` / `-D PR_RHI_METAL`. The umbrella header `pr_rhi.h` includes the appropriate alias file:
|
||||
@@ -49,22 +64,95 @@ All descriptor structs are passed **by value**, not `const *`:
|
||||
|
||||
```c
|
||||
// correct
|
||||
PrRhiDevice *prRhiCreateDevice(PrRhiPhysicalDevice *pdev, PrRhiSurface *surface,
|
||||
PrRhiDeviceDesc desc, WpAllocator *alloc);
|
||||
PrRhiDevice *prRhiCreateDevice(PrRhiPhysicalDevice *pdev, PrRhiSurface *surface, PrRhiDeviceDesc desc);
|
||||
|
||||
// wrong
|
||||
PrRhiDevice *prRhiCreateDevice(PrRhiPhysicalDevice *pdev, PrRhiSurface *surface,
|
||||
const PrRhiDeviceDesc *desc, WpAllocator *alloc);
|
||||
PrRhiDevice *prRhiCreateDevice(PrRhiPhysicalDevice *pdev, PrRhiSurface *surface, const PrRhiDeviceDesc *desc);
|
||||
```
|
||||
|
||||
### Frame-by-frame command batching
|
||||
|
||||
Commands that run every frame must avoid arena allocation. Use stack arrays with a while-loop to batch operations:
|
||||
|
||||
```c
|
||||
// correct — stack array, batched submission
|
||||
void prRhiCmdBindDescriptorSetsVk(PrRhiCommandBuffer *cb, PrRhiPipelineBindPoint bind_point,
|
||||
PrRhiPipelineLayout *layout, u32 first_set,
|
||||
PrRhiDescriptorSetArray sets) {
|
||||
u32 set_count = sets ? (u32)wpArrayCount(sets) : 0;
|
||||
while (set_count > 0) {
|
||||
VkDescriptorSetArray vk_sets = wpArrayWithCapacity(VkDescriptorSet, 16, WP_ARRAY_INIT_FILLED);
|
||||
u32 total_capacity = (u32)wpArrayCapacity(vk_sets);
|
||||
u32 real_count = set_count < total_capacity ? set_count : total_capacity;
|
||||
for (u32 i = 0; i < real_count; ++i) {
|
||||
vk_sets[i] = sets[i]->handle;
|
||||
}
|
||||
vkCmdBindDescriptorSets(cb->handle, vk_bp, vk_layout, first_set, real_count, vk_sets, 0, NULL);
|
||||
set_count -= real_count;
|
||||
first_set += real_count;
|
||||
}
|
||||
}
|
||||
|
||||
// wrong — allocates from arena on every call
|
||||
void prRhiCmdBindDescriptorSetsBad(PrRhiCommandBuffer *cb, ...) {
|
||||
VkDescriptorSetArray vk_sets = wpArrayAllocCapacity(VkDescriptorSet, &_G_RHI_CONTEXT.allocator, count, ...);
|
||||
// ... this leaks every frame
|
||||
}
|
||||
```
|
||||
|
||||
Apply this pattern to: `prRhiCmdBindDescriptorSets`, `prRhiCmdBindVertexBuffers`, `prRhiCmdCopyBufferToImage`, and any other command that processes user-provided arrays.
|
||||
|
||||
### Opaque struct handles — no casts
|
||||
|
||||
Handle types in opaque structs are already the correct Vulkan type. Do not cast:
|
||||
|
||||
```c
|
||||
// correct
|
||||
vk_device = device->handle;
|
||||
vk_buffer = buffer->handle;
|
||||
|
||||
// wrong
|
||||
vk_device = (VkDevice)device->handle;
|
||||
vk_buffer = (VkBuffer)buffer->handle;
|
||||
```
|
||||
|
||||
### Vulkan struct initialisation — designated initializers
|
||||
|
||||
Always use C99 designated initializers for Vulkan info structs:
|
||||
|
||||
```c
|
||||
// correct
|
||||
VkBufferCreateInfo buf_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
||||
.size = desc.size,
|
||||
.usage = _toVkBufferUsage(desc.usage),
|
||||
};
|
||||
|
||||
// wrong
|
||||
VkBufferCreateInfo buf_info = {};
|
||||
buf_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||
buf_info.size = desc.size;
|
||||
buf_info.usage = _toVkBufferUsage(desc.usage);
|
||||
```
|
||||
|
||||
### API patterns
|
||||
|
||||
- **`prRhiCreateCommandPool`**: Takes only `PrRhiDevice *device` (uses `device->queue_family_index` internally)
|
||||
- **`prRhiFreeCommandBuffers`**: Takes `PrRhiCommandBufferArray buffers` (count derived from `wpArrayCount`)
|
||||
- **`prRhiAllocateDescriptorSet`**: Takes `WpU32Array variable_descriptor_counts` for variable descriptor support
|
||||
- **`prRhiCmdBindVertexBuffers`**: Takes `WpU64Array offsets` (count matched to buffers internally)
|
||||
- **Shader entry points**: Configurable via `vertex_shader_entry_point` / `fragment_shader_entry_point` in pipeline desc (not hardcoded to "main")
|
||||
|
||||
### File layout
|
||||
|
||||
```
|
||||
src/prism/rhi/
|
||||
├── pr_rhi.h ← umbrella header (API declarations + backend dispatch)
|
||||
├── pr_rhi.c ← global context definition (prRhiInit, prRhiDestroy)
|
||||
├── pr_rhi_types.h ← shared types (enums, element types, array aliases, desc structs, opaque handles)
|
||||
├── vulkan/
|
||||
│ ├── pr_rhi_vk.h ← Vulkan backend header (opaque struct defs + Vk-suffixed decls)
|
||||
│ ├── pr_rhi_vk.c ← Vulkan backend implementation
|
||||
│ ├── pr_rhi_vk_aliases.h ← #define alias mapping
|
||||
│ └── profiles/ ← generated Vulkan Profiles library
|
||||
├── d3d12/
|
||||
|
||||
@@ -36,6 +36,16 @@ All code follows the patterns established in `src/wapp/`. The project prefix is
|
||||
|
||||
- **Tabs for indentation**, 8-column tab width.
|
||||
- **Braces** on the same line as control statements (Attach style).
|
||||
- **Braces on single-line if statements**: Always use braces, even for single-line bodies:
|
||||
```c
|
||||
// correct
|
||||
if (!buffer) { return; }
|
||||
if (!texture) { _abort("alloc failed"); }
|
||||
|
||||
// wrong
|
||||
if (!buffer) return;
|
||||
if (!texture) _abort("alloc failed");
|
||||
```
|
||||
- **Pointers**: `*` against the name, not the type (`PrRhiBuffer *buf`, not `PrRhiBuffer* buf`).
|
||||
- **Line width**: 120 columns.
|
||||
- **Continuation lines** align to the opening parenthesis.
|
||||
@@ -117,6 +127,24 @@ prefer SoA layouts, batch processing, and minimise pointer chasing. Keep
|
||||
the DAG in contiguous arrays (e.g. adjacency lists packed in flat buffers)
|
||||
rather than individually allocated linked structures.
|
||||
|
||||
### Frame-by-frame command batching
|
||||
|
||||
Commands that execute every frame must avoid arena allocation. Use stack
|
||||
arrays with a while-loop to batch operations in fixed-size chunks:
|
||||
|
||||
```c
|
||||
while (count > 0) {
|
||||
VkTypeArray batch = wpArrayWithCapacity(VkType, 16, WP_ARRAY_INIT_FILLED);
|
||||
u32 batch_size = count < wpArrayCapacity(batch) ? count : (u32)wpArrayCapacity(batch);
|
||||
// ... process batch ...
|
||||
vkCmd*(cb->handle, ...);
|
||||
count -= batch_size;
|
||||
first += batch_size;
|
||||
}
|
||||
```
|
||||
|
||||
This avoids per-frame arena churn while handling arbitrarily large inputs.
|
||||
|
||||
### Graph / adjacency lists
|
||||
|
||||
Adjacency list nodes must be **separately allocated from the vertex array**.
|
||||
|
||||
@@ -43,7 +43,7 @@ build: vendor
|
||||
bear -a -- {{CC}} -g -c {{VK_FLAGS}} src/prism/rhi/pr_rhi.c -o {{BUILDDIR}}/pr_rhi.o
|
||||
bear -a -- {{CC}} -g -c {{VK_FLAGS}} src/prism/rhi/vulkan/pr_rhi_vk.c -o {{BUILDDIR}}/pr_rhi_vk.o
|
||||
bear -a -- {{CC}} -g -c src/wapp/wapp.c -o {{BUILDDIR}}/wapp.o
|
||||
bear -a -- {{CXX}} -g -c -Wno-nullability-completeness -DVK_NO_PROTOTYPES \
|
||||
bear -a -- {{CXX}} -g -c {{VK_FLAGS}} -Wno-nullability-completeness -DVK_NO_PROTOTYPES \
|
||||
{{APP_INC}} \
|
||||
src/main.cpp \
|
||||
-o {{BUILDDIR}}/main.o
|
||||
@@ -55,6 +55,9 @@ build: vendor
|
||||
-o {{BUILDDIR}}/prism
|
||||
@echo "--- build done: {{BUILDDIR}}/prism ---"
|
||||
|
||||
run:
|
||||
./{{BUILDDIR}}/prism
|
||||
|
||||
# Clean
|
||||
clean:
|
||||
rm -rf {{BUILDDIR}}
|
||||
|
||||
+109
-114
@@ -3,8 +3,7 @@
|
||||
// Prism port of how-to-vulkan's main.cpp — uses the RHI API instead of
|
||||
// direct Vulkan calls.
|
||||
|
||||
#define PR_RHI_VULKAN
|
||||
|
||||
#include "prism/rhi/pr_rhi_types.h"
|
||||
#include "prism/rhi/pr_rhi.h"
|
||||
#include <SDL3/SDL_timer.h>
|
||||
#include <glm/ext/matrix_clip_space.hpp>
|
||||
@@ -95,6 +94,8 @@ struct AppState {
|
||||
PrRhiSurface *surface;
|
||||
PrRhiSwapchain *swapchain;
|
||||
|
||||
PrRhiFormat swapchain_format;
|
||||
|
||||
PrRhiBuffer *vert_index_buf;
|
||||
u64 vertex_buf_size;
|
||||
u64 index_count;
|
||||
@@ -136,9 +137,10 @@ struct AppState {
|
||||
int main() {
|
||||
AppState app = {};
|
||||
WpAllocator arena = wpMemArenaAllocatorInitZero(MiB(128));
|
||||
prRhiInit();
|
||||
|
||||
// {{{ Initialisation
|
||||
prRhiInit();
|
||||
|
||||
check(SDL_Init(SDL_INIT_VIDEO), EXIT_CODE_SDL_INIT_FAILED);
|
||||
|
||||
f32 display_scale = SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay());
|
||||
@@ -149,8 +151,7 @@ int main() {
|
||||
// }}}
|
||||
|
||||
// {{{ Instance creation
|
||||
PrRhiInstanceDesc inst_desc = {};
|
||||
app.inst = prRhiCreateInstance(inst_desc);
|
||||
app.inst = prRhiCreateInstance(PrRhiInstanceDesc{});
|
||||
// }}}
|
||||
|
||||
// {{{ Physical device selection
|
||||
@@ -159,8 +160,7 @@ int main() {
|
||||
|
||||
i32 selected = -1;
|
||||
for (u32 i = 0; i < wpArrayCount(pdevs); ++i) {
|
||||
PrRhiPhysicalDeviceProperties props;
|
||||
prRhiGetPhysicalDeviceProperties(pdevs[i], &props);
|
||||
PrRhiPhysicalDeviceProperties props = prRhiGetPhysicalDeviceProperties(pdevs[i]);
|
||||
switch (props.device_type) {
|
||||
case PR_RHI_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU:
|
||||
selected = (i32)i;
|
||||
@@ -176,7 +176,8 @@ int main() {
|
||||
app.pdev = pdevs[selected];
|
||||
|
||||
// Print device info
|
||||
WpStr8 dev_name, driver_info;
|
||||
WpStr8 dev_name = wpStr8Buf(512);
|
||||
WpStr8 driver_info = wpStr8Buf(512);
|
||||
prRhiGetPhysicalDeviceName(app.pdev, &dev_name);
|
||||
prRhiGetPhysicalDeviceDriverInfo(app.pdev, &driver_info);
|
||||
std::cout << "Selected GPU: " << std::string_view((const char *)dev_name.buf, dev_name.size) << '\n'
|
||||
@@ -186,14 +187,14 @@ int main() {
|
||||
// {{{ Surface creation
|
||||
check(SDL_GetWindowSize(app.window, &app.window_size.x, &app.window_size.y),
|
||||
EXIT_CODE_GET_WINDOW_SIZE_FAILED);
|
||||
app.surface = prRhiCreateSurfaceFromWindow(app.inst, (void *)app.window);
|
||||
app.surface = prRhiCreateSurfaceFromWindow(app.inst, app.window);
|
||||
// }}}
|
||||
|
||||
// {{{ Device creation
|
||||
PrRhiDeviceDesc dev_desc = {};
|
||||
dev_desc.present_mode = PR_RHI_PRESENT_MODE_FIFO;
|
||||
|
||||
app.device = prRhiCreateDevice(app.pdev, app.surface, dev_desc);
|
||||
u32 qfi = prRhiGetQueueFamilyIndex(app.device);
|
||||
// }}}
|
||||
|
||||
// {{{ Swapchain creation
|
||||
@@ -203,9 +204,9 @@ int main() {
|
||||
swap_desc.height = (u32)app.window_size.y;
|
||||
swap_desc.has_depth = true;
|
||||
swap_desc.depth_format = PR_RHI_FORMAT_D24_UNORM_S8_UINT;
|
||||
app.swapchain = prRhiCreateSwapchain(app.device, swap_desc);
|
||||
|
||||
PrRhiFormat swapchain_format = prRhiGetSwapchainFormat(app.swapchain);
|
||||
app.swapchain = prRhiCreateSwapchain(app.device, swap_desc);
|
||||
app.swapchain_format = prRhiGetSwapchainFormat(app.swapchain);
|
||||
// }}}
|
||||
|
||||
// {{{ Vertex/Index buffers
|
||||
@@ -252,6 +253,7 @@ int main() {
|
||||
vert_desc.size = app.vertex_buf_size + index_buf_size;
|
||||
vert_desc.usage = (PrRhiBufferUsage)(PR_RHI_BUFFER_USAGE_VERTEX | PR_RHI_BUFFER_USAGE_INDEX);
|
||||
vert_desc.memory = PR_RHI_MEMORY_CPU_TO_GPU;
|
||||
|
||||
app.vert_index_buf = prRhiCreateBuffer(app.device, vert_desc);
|
||||
|
||||
void *mapped = prRhiBufferMap(app.device, app.vert_index_buf);
|
||||
@@ -271,6 +273,7 @@ int main() {
|
||||
buf_desc.usage = (PrRhiBufferUsage)(PR_RHI_BUFFER_USAGE_STORAGE |
|
||||
PR_RHI_BUFFER_USAGE_SHADER_DEVICE_ADDRESS);
|
||||
buf_desc.memory = PR_RHI_MEMORY_CPU_TO_GPU;
|
||||
|
||||
app.shader_data_bufs[i] = prRhiCreateBuffer(app.device, buf_desc);
|
||||
}
|
||||
// }}}
|
||||
@@ -294,7 +297,7 @@ int main() {
|
||||
}
|
||||
|
||||
// Render completed semaphores (per swapchain image)
|
||||
u32 swapchain_image_count = app.swapchain->image_count;
|
||||
u32 swapchain_image_count = prRhiGetSwapchainImageCount(app.swapchain);
|
||||
app.render_completed_semaphores = wpArrayAllocCapacity(PrRhiSemaphore *, &arena,
|
||||
swapchain_image_count,
|
||||
WP_ARRAY_INIT_FILLED);
|
||||
@@ -304,10 +307,7 @@ int main() {
|
||||
// }}}
|
||||
|
||||
// {{{ Command pool and buffers
|
||||
PrRhiCommandPoolDesc pool_desc = {};
|
||||
pool_desc.queue_family_index = qfi;
|
||||
app.cmd_pool = prRhiCreateCommandPool(app.device, pool_desc);
|
||||
|
||||
app.cmd_pool = prRhiCreateCommandPool(app.device);
|
||||
app.cmd_buffers = prRhiAllocateCommandBuffers(app.device, app.cmd_pool,
|
||||
AppState::max_frames_in_flight);
|
||||
// }}}
|
||||
@@ -331,27 +331,28 @@ int main() {
|
||||
samp_desc.mipmap_mode = PR_RHI_MIPMAP_MODE_LINEAR;
|
||||
samp_desc.max_anisotropy = 8.0f;
|
||||
samp_desc.max_lod = PR_RHI_LOD_CLAMP_NONE;
|
||||
|
||||
PrRhiSampler *sampler = prRhiCreateSampler(app.device, samp_desc);
|
||||
|
||||
app.textures[i].texture = tex;
|
||||
app.textures[i].sampler = sampler;
|
||||
}
|
||||
|
||||
prRhiFreeCommandBuffers(app.device, app.cmd_pool, 1, upload_cbs);
|
||||
wpArrayDealloc(PrRhiCommandBuffer *, &arena, &upload_cbs);
|
||||
prRhiFreeCommandBuffers(app.device, app.cmd_pool, upload_cbs);
|
||||
// }}}
|
||||
|
||||
// {{{ Descriptor set layout, pool, set
|
||||
PrRhiDescriptorSetLayoutBinding bindings[1] = {};
|
||||
bindings[0].type = PR_RHI_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
bindings[0].descriptor_count = AppState::texture_count;
|
||||
bindings[0].stage_flags = PR_RHI_SHADER_STAGE_FRAGMENT;
|
||||
bindings[0].binding_flags = PR_RHI_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT;
|
||||
PrRhiDescriptorSetLayoutBindingArray ds_layouts = wpArray(
|
||||
PrRhiDescriptorSetLayoutBinding,
|
||||
PrRhiDescriptorSetLayoutBinding{
|
||||
PR_RHI_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||
AppState::texture_count,
|
||||
PR_RHI_SHADER_STAGE_FRAGMENT,
|
||||
PR_RHI_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT,
|
||||
}
|
||||
);
|
||||
|
||||
PrRhiDescriptorSetLayoutBindingArray ds_layouts = wpArray(PrRhiDescriptorSetLayoutBinding, bindings[0]);
|
||||
|
||||
PrRhiDescriptorSetLayoutDesc layout_desc = {};
|
||||
layout_desc.bindings = ds_layouts;
|
||||
PrRhiDescriptorSetLayoutDesc layout_desc = { ds_layouts };
|
||||
app.desc_set_layout = prRhiCreateDescriptorSetLayout(app.device, layout_desc);
|
||||
|
||||
// Pool
|
||||
@@ -359,15 +360,16 @@ int main() {
|
||||
pool_size.type = PR_RHI_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
pool_size.descriptor_count = AppState::texture_count;
|
||||
|
||||
PrRhiDescriptorPoolDesc pool_desc2 = {};
|
||||
pool_desc2.max_sets = 1;
|
||||
pool_desc2.pool_sizes = wpArray(PrRhiDescriptorPoolSize, pool_size);
|
||||
app.desc_pool = prRhiCreateDescriptorPool(app.device, pool_desc2);
|
||||
PrRhiDescriptorPoolDesc ds_pool_desc = {};
|
||||
ds_pool_desc.max_sets = 1;
|
||||
ds_pool_desc.pool_sizes = wpArray(PrRhiDescriptorPoolSize, pool_size);
|
||||
|
||||
app.desc_pool = prRhiCreateDescriptorPool(app.device, ds_pool_desc);
|
||||
|
||||
// Allocate descriptor set (variable count)
|
||||
app.desc_set = prRhiAllocateDescriptorSet(app.device, app.desc_pool,
|
||||
app.desc_set_layout,
|
||||
AppState::texture_count);
|
||||
WpU32Array var_counts = wpArray(u32, AppState::texture_count);
|
||||
app.desc_set = prRhiAllocateDescriptorSet(app.device, app.desc_pool, app.desc_set_layout,
|
||||
var_counts);
|
||||
|
||||
// Write descriptor set
|
||||
PrRhiDescriptorImageInfoArray img_infos = wpArrayAllocCapacity(PrRhiDescriptorImageInfo,
|
||||
@@ -417,6 +419,7 @@ int main() {
|
||||
PrRhiShaderDesc shader_desc = {};
|
||||
shader_desc.spirv_code = spirv->getBufferPointer();
|
||||
shader_desc.spirv_size = spirv->getBufferSize();
|
||||
|
||||
app.shader = prRhiCreateShader(app.device, shader_desc);
|
||||
// }}}
|
||||
|
||||
@@ -425,56 +428,56 @@ int main() {
|
||||
pc_range.stage_flags = PR_RHI_SHADER_STAGE_VERTEX;
|
||||
pc_range.size = sizeof(u64);
|
||||
|
||||
PrRhiDescriptorSetLayout *set_layouts_pl[] = { app.desc_set_layout };
|
||||
PrRhiDescriptorSetLayoutArray pl_layouts = wpArray(PrRhiDescriptorSetLayout *, set_layouts_pl[0]);
|
||||
PrRhiDescriptorSetLayoutArray pl_layouts = wpArray(PrRhiDescriptorSetLayout *, app.desc_set_layout);
|
||||
|
||||
PrRhiPipelineLayoutDesc pl_desc = {};
|
||||
pl_desc.set_layouts = pl_layouts;
|
||||
pl_desc.push_constant_ranges = wpArray(PrRhiPushConstantRange, pc_range);
|
||||
|
||||
app.pipeline_layout = prRhiCreatePipelineLayout(app.device, pl_desc);
|
||||
// }}}
|
||||
|
||||
// {{{ Graphics pipeline
|
||||
PrRhiVertexInputBinding vertex_binding = {};
|
||||
vertex_binding.binding = 0;
|
||||
vertex_binding.stride = sizeof(Vertex);
|
||||
PrRhiVertexInputBindingArray vertex_bindings = wpArray(
|
||||
PrRhiVertexInputBinding,
|
||||
PrRhiVertexInputBinding{ 0, sizeof(Vertex) }
|
||||
);
|
||||
|
||||
PrRhiVertexAttribute vertex_attrs[3] = {};
|
||||
vertex_attrs[0].location = 0;
|
||||
vertex_attrs[0].binding = 0;
|
||||
vertex_attrs[0].format = PR_RHI_FORMAT_R32G32B32_SFLOAT;
|
||||
vertex_attrs[0].offset = 0;
|
||||
vertex_attrs[1].location = 1;
|
||||
vertex_attrs[1].binding = 0;
|
||||
vertex_attrs[1].format = PR_RHI_FORMAT_R32G32B32_SFLOAT;
|
||||
vertex_attrs[1].offset = offsetof(Vertex, normal);
|
||||
vertex_attrs[2].location = 2;
|
||||
vertex_attrs[2].binding = 0;
|
||||
vertex_attrs[2].format = PR_RHI_FORMAT_R32G32_SFLOAT;
|
||||
vertex_attrs[2].offset = offsetof(Vertex, uv);
|
||||
PrRhiVertexAttributeArray vertex_attrs = wpArray(
|
||||
PrRhiVertexAttribute,
|
||||
PrRhiVertexAttribute{ 0, 0, PR_RHI_FORMAT_R32G32B32_SFLOAT, 0 },
|
||||
PrRhiVertexAttribute{ 1, 0, PR_RHI_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, normal) },
|
||||
PrRhiVertexAttribute{ 2, 0, PR_RHI_FORMAT_R32G32_SFLOAT, offsetof(Vertex, uv) }
|
||||
);
|
||||
|
||||
PrRhiColorBlendAttachment blend_attachment = {};
|
||||
blend_attachment.color_write_mask = 0xf;
|
||||
PrRhiColorBlendAttachmentArray blend_attachments = wpArray(
|
||||
PrRhiColorBlendAttachment,
|
||||
PrRhiColorBlendAttachment{ 0xf }
|
||||
);
|
||||
|
||||
PrRhiFormat color_fmts[] = { swapchain_format };
|
||||
PrRhiFormatArray color_fmt_array = wpArray(PrRhiFormat, color_fmts[0]);
|
||||
PrRhiFormatArray color_fmt_array = wpArray(PrRhiFormat, app.swapchain_format);
|
||||
|
||||
PrRhiGraphicsPipelineDesc pipe_desc = {};
|
||||
pipe_desc.vertex_shader = app.shader;
|
||||
pipe_desc.vertex_shader_entry_point = "main";
|
||||
pipe_desc.fragment_shader = app.shader;
|
||||
pipe_desc.vertex_bindings = wpArray(PrRhiVertexInputBinding, vertex_binding);
|
||||
pipe_desc.vertex_attributes = wpArray(PrRhiVertexAttribute, vertex_attrs[0],
|
||||
vertex_attrs[1], vertex_attrs[2]);
|
||||
pipe_desc.fragment_shader_entry_point = "main";
|
||||
pipe_desc.vertex_bindings = vertex_bindings;
|
||||
pipe_desc.vertex_attributes = vertex_attrs;
|
||||
pipe_desc.topology = PR_RHI_TOPOLOGY_TRIANGLE_LIST;
|
||||
pipe_desc.color_attachment_formats = color_fmt_array;
|
||||
pipe_desc.depth_attachment_format = swap_desc.depth_format;
|
||||
pipe_desc.depth_test_enable = true;
|
||||
pipe_desc.depth_write_enable = true;
|
||||
pipe_desc.depth_compare_op = PR_RHI_COMPARE_OP_LESS_OR_EQUAL;
|
||||
pipe_desc.blend_attachments = wpArray(PrRhiColorBlendAttachment, blend_attachment);
|
||||
pipe_desc.blend_attachments = blend_attachments;
|
||||
pipe_desc.dynamic_viewport = true;
|
||||
pipe_desc.dynamic_scissor = true;
|
||||
pipe_desc.cull_mode = PR_RHI_CULL_MODE_BACK;
|
||||
pipe_desc.front_face = PR_RHI_FRONT_FACE_COUNTER_CLOCKWISE;
|
||||
pipe_desc.line_width = 1.0f;
|
||||
pipe_desc.layout = app.pipeline_layout;
|
||||
|
||||
app.pipeline = prRhiCreateGraphicsPipeline(app.device, pipe_desc);
|
||||
// }}}
|
||||
|
||||
@@ -516,8 +519,7 @@ int main() {
|
||||
glm::mat4_cast(glm::quat(app.object_rotations[i]));
|
||||
}
|
||||
|
||||
void *shader_data_ptr = prRhiBufferMap(app.device,
|
||||
app.shader_data_bufs[app.frame_index]);
|
||||
void *shader_data_ptr = prRhiBufferMap(app.device, app.shader_data_bufs[app.frame_index]);
|
||||
memcpy(shader_data_ptr, &app.shader_data, sizeof(ShaderData));
|
||||
prRhiBufferUnmap(app.device, app.shader_data_bufs[app.frame_index]);
|
||||
// }}}
|
||||
@@ -529,43 +531,43 @@ int main() {
|
||||
|
||||
// Transition images to attachment optimal
|
||||
{
|
||||
PrRhiImageMemoryBarrier img_barriers[2] = {};
|
||||
PrRhiImageMemoryBarrierArray barriers_arr =
|
||||
wpArrayWithCapacity(PrRhiImageMemoryBarrier, 2, WP_ARRAY_INIT_FILLED);
|
||||
|
||||
// Color attachment
|
||||
PrRhiTexture *color_tex = prRhiGetSwapchainTexture(app.swapchain, image_index);
|
||||
img_barriers[0].texture = color_tex;
|
||||
img_barriers[0].old_layout = PR_RHI_LAYOUT_UNDEFINED;
|
||||
img_barriers[0].new_layout = PR_RHI_LAYOUT_ATTACHMENT_OPTIMAL;
|
||||
img_barriers[0].src_stage_mask = PR_RHI_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT;
|
||||
img_barriers[0].src_access_mask = PR_RHI_ACCESS_NONE;
|
||||
img_barriers[0].dst_stage_mask = PR_RHI_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT;
|
||||
img_barriers[0].dst_access_mask = (PrRhiAccess)(PR_RHI_ACCESS_COLOR_ATTACHMENT_READ | PR_RHI_ACCESS_COLOR_ATTACHMENT_WRITE);
|
||||
barriers_arr[0].texture = color_tex;
|
||||
barriers_arr[0].old_layout = PR_RHI_LAYOUT_UNDEFINED;
|
||||
barriers_arr[0].new_layout = PR_RHI_LAYOUT_ATTACHMENT_OPTIMAL;
|
||||
barriers_arr[0].src_stage_mask = PR_RHI_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT;
|
||||
barriers_arr[0].src_access_mask = PR_RHI_ACCESS_NONE;
|
||||
barriers_arr[0].dst_stage_mask = PR_RHI_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT;
|
||||
barriers_arr[0].dst_access_mask = (PrRhiAccess)(PR_RHI_ACCESS_COLOR_ATTACHMENT_READ | PR_RHI_ACCESS_COLOR_ATTACHMENT_WRITE);
|
||||
|
||||
// Depth attachment
|
||||
PrRhiTexture *depth_tex = prRhiGetSwapchainDepthTexture(app.swapchain);
|
||||
img_barriers[1].texture = depth_tex;
|
||||
img_barriers[1].old_layout = PR_RHI_LAYOUT_UNDEFINED;
|
||||
img_barriers[1].new_layout = PR_RHI_LAYOUT_ATTACHMENT_OPTIMAL;
|
||||
img_barriers[1].src_stage_mask = PR_RHI_PIPELINE_STAGE_LATE_FRAGMENT_TESTS;
|
||||
img_barriers[1].src_access_mask = PR_RHI_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE;
|
||||
img_barriers[1].dst_stage_mask = PR_RHI_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS;
|
||||
img_barriers[1].dst_access_mask = PR_RHI_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE;
|
||||
barriers_arr[1].texture = depth_tex;
|
||||
barriers_arr[1].old_layout = PR_RHI_LAYOUT_UNDEFINED;
|
||||
barriers_arr[1].new_layout = PR_RHI_LAYOUT_ATTACHMENT_OPTIMAL;
|
||||
barriers_arr[1].src_stage_mask = PR_RHI_PIPELINE_STAGE_LATE_FRAGMENT_TESTS;
|
||||
barriers_arr[1].src_access_mask = PR_RHI_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE;
|
||||
barriers_arr[1].dst_stage_mask = PR_RHI_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS;
|
||||
barriers_arr[1].dst_access_mask = PR_RHI_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE;
|
||||
|
||||
PrRhiImageMemoryBarrierArray barriers_arr = wpArray(PrRhiImageMemoryBarrier,
|
||||
img_barriers[0], img_barriers[1]);
|
||||
prRhiCmdPipelineBarrier(cb, barriers_arr, NULL);
|
||||
}
|
||||
|
||||
// Rendering
|
||||
{
|
||||
PrRhiColorAttachment color_att = {};
|
||||
color_att.texture = prRhiGetSwapchainTexture(app.swapchain, image_index);
|
||||
color_att.layout = PR_RHI_LAYOUT_ATTACHMENT_OPTIMAL;
|
||||
color_att.clear = true;
|
||||
color_att.clear_color[0] = 0.0f;
|
||||
color_att.clear_color[1] = 0.0f;
|
||||
color_att.clear_color[2] = 0.0f;
|
||||
color_att.clear_color[3] = 0.0f;
|
||||
PrRhiColorAttachmentArray color_arr =
|
||||
wpArrayWithCapacity(PrRhiColorAttachment, 1, WP_ARRAY_INIT_FILLED);
|
||||
color_arr[0].texture = prRhiGetSwapchainTexture(app.swapchain, image_index);
|
||||
color_arr[0].layout = PR_RHI_LAYOUT_ATTACHMENT_OPTIMAL;
|
||||
color_arr[0].clear = true;
|
||||
color_arr[0].clear_color[0] = 0.0f;
|
||||
color_arr[0].clear_color[1] = 0.0f;
|
||||
color_arr[0].clear_color[2] = 0.0f;
|
||||
color_arr[0].clear_color[3] = 0.0f;
|
||||
|
||||
PrRhiDepthAttachment depth_att = {};
|
||||
depth_att.texture = prRhiGetSwapchainDepthTexture(app.swapchain);
|
||||
@@ -573,7 +575,6 @@ int main() {
|
||||
depth_att.clear = true;
|
||||
depth_att.clear_depth = 1.0f;
|
||||
|
||||
PrRhiColorAttachmentArray color_arr = wpArray(PrRhiColorAttachment, color_att);
|
||||
prRhiCmdBeginRendering(cb, color_arr, &depth_att);
|
||||
}
|
||||
|
||||
@@ -586,44 +587,39 @@ int main() {
|
||||
prRhiCmdBindDescriptorSets(cb, PR_RHI_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
app.pipeline_layout, 0, sets);
|
||||
|
||||
PrRhiBuffer *vert_bufs[] = { app.vert_index_buf };
|
||||
u64 vert_offsets[] = { 0 };
|
||||
PrRhiBufferArray vert_buf_arr = wpArray(PrRhiBuffer *, vert_bufs[0]);
|
||||
prRhiCmdBindVertexBuffers(cb, 0, vert_buf_arr, vert_offsets, 1);
|
||||
prRhiCmdBindIndexBuffer(cb, app.vert_index_buf, app.vertex_buf_size,
|
||||
PR_RHI_INDEX_TYPE_UINT16);
|
||||
PrRhiBufferArray vert_buf_arr = wpArray(PrRhiBuffer *, app.vert_index_buf);
|
||||
WpU64Array vert_offsets = wpArray(u64, 0);
|
||||
prRhiCmdBindVertexBuffers(cb, 0, vert_buf_arr, vert_offsets);
|
||||
prRhiCmdBindIndexBuffer(cb, app.vert_index_buf, app.vertex_buf_size, PR_RHI_INDEX_TYPE_UINT16);
|
||||
|
||||
// Push shader data buffer device address
|
||||
u64 buf_addr = prRhiGetBufferDeviceAddress(app.device,
|
||||
app.shader_data_bufs[app.frame_index]);
|
||||
prRhiCmdPushConstants(cb, app.pipeline_layout, PR_RHI_SHADER_STAGE_VERTEX,
|
||||
0, sizeof(u64), &buf_addr);
|
||||
u64 buf_addr = prRhiGetBufferDeviceAddress(app.device, app.shader_data_bufs[app.frame_index]);
|
||||
prRhiCmdPushConstants(cb, app.pipeline_layout, PR_RHI_SHADER_STAGE_VERTEX, 0, sizeof(u64), &buf_addr);
|
||||
|
||||
prRhiCmdDrawIndexed(cb, (u32)app.index_count, AppState::instance_count, 0, 0, 0);
|
||||
prRhiCmdEndRendering(cb);
|
||||
|
||||
// Transition to present
|
||||
{
|
||||
PrRhiImageMemoryBarrier present_barrier = {};
|
||||
present_barrier.texture = prRhiGetSwapchainTexture(app.swapchain, image_index);
|
||||
present_barrier.old_layout = PR_RHI_LAYOUT_ATTACHMENT_OPTIMAL;
|
||||
present_barrier.new_layout = PR_RHI_LAYOUT_PRESENT_SRC;
|
||||
present_barrier.src_stage_mask = PR_RHI_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT;
|
||||
present_barrier.src_access_mask = PR_RHI_ACCESS_COLOR_ATTACHMENT_WRITE;
|
||||
present_barrier.dst_stage_mask = PR_RHI_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT;
|
||||
present_barrier.dst_access_mask = PR_RHI_ACCESS_NONE;
|
||||
PrRhiImageMemoryBarrierArray present_barriers =
|
||||
wpArrayWithCapacity(PrRhiImageMemoryBarrier, 1, WP_ARRAY_INIT_FILLED);
|
||||
present_barriers[0].texture = prRhiGetSwapchainTexture(app.swapchain, image_index);
|
||||
present_barriers[0].old_layout = PR_RHI_LAYOUT_ATTACHMENT_OPTIMAL;
|
||||
present_barriers[0].new_layout = PR_RHI_LAYOUT_PRESENT_SRC;
|
||||
present_barriers[0].src_stage_mask = PR_RHI_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT;
|
||||
present_barriers[0].src_access_mask = PR_RHI_ACCESS_COLOR_ATTACHMENT_WRITE;
|
||||
present_barriers[0].dst_stage_mask = PR_RHI_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT;
|
||||
present_barriers[0].dst_access_mask = PR_RHI_ACCESS_NONE;
|
||||
|
||||
prRhiCmdPipelineBarrier(cb, wpArray(PrRhiImageMemoryBarrier, present_barrier), NULL);
|
||||
prRhiCmdPipelineBarrier(cb, present_barriers, NULL);
|
||||
}
|
||||
|
||||
prRhiEndCommandBuffer(cb);
|
||||
// }}}
|
||||
|
||||
// {{{ Submit
|
||||
prRhiQueueSubmit(app.device, cb,
|
||||
app.image_acquired_semaphores[app.frame_index],
|
||||
app.render_completed_semaphores[image_index],
|
||||
app.fences[app.frame_index]);
|
||||
prRhiQueueSubmit(app.device, cb, app.image_acquired_semaphores[app.frame_index],
|
||||
app.render_completed_semaphores[image_index], app.fences[app.frame_index]);
|
||||
// }}}
|
||||
|
||||
// {{{ Present
|
||||
@@ -709,8 +705,7 @@ int main() {
|
||||
prRhiDestroyTexture(app.device, app.textures[i].texture);
|
||||
}
|
||||
|
||||
prRhiFreeCommandBuffers(app.device, app.cmd_pool, AppState::max_frames_in_flight,
|
||||
app.cmd_buffers);
|
||||
prRhiFreeCommandBuffers(app.device, app.cmd_pool, app.cmd_buffers);
|
||||
prRhiDestroyCommandPool(app.device, app.cmd_pool);
|
||||
|
||||
for (u32 i = 0; i < swapchain_image_count; ++i) {
|
||||
|
||||
@@ -7,11 +7,9 @@
|
||||
PrRhiContext _G_RHI_CONTEXT;
|
||||
|
||||
void prRhiInit(void) {
|
||||
_G_RHI_CONTEXT.main = wpMemArenaAllocatorInit(MiB(64));
|
||||
_G_RHI_CONTEXT.scratch = wpMemArenaAllocatorInit(MiB(32));
|
||||
_G_RHI_CONTEXT.allocator = wpMemArenaAllocatorInit(MiB(64));
|
||||
}
|
||||
|
||||
void prRhiDestroy(void) {
|
||||
wpMemArenaAllocatorDestroy(&_G_RHI_CONTEXT.scratch);
|
||||
wpMemArenaAllocatorDestroy(&_G_RHI_CONTEXT.main);
|
||||
wpMemArenaAllocatorDestroy(&_G_RHI_CONTEXT.allocator);
|
||||
}
|
||||
|
||||
+10
-8
@@ -24,6 +24,7 @@
|
||||
#define PR_RHI_H
|
||||
|
||||
#include "pr_rhi_types.h"
|
||||
#include <SDL3/SDL_video.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -48,14 +49,13 @@ void prRhiDestroyInstance(PrRhiInstance *inst);
|
||||
PrRhiPhysicalDeviceArray prRhiGetPhysicalDevices(PrRhiInstance *inst);
|
||||
void prRhiGetPhysicalDeviceName(PrRhiPhysicalDevice *pdev, WpStr8 *out);
|
||||
void prRhiGetPhysicalDeviceDriverInfo(PrRhiPhysicalDevice *pdev, WpStr8 *out);
|
||||
void prRhiGetPhysicalDeviceProperties(PrRhiPhysicalDevice *pdev,
|
||||
PrRhiPhysicalDeviceProperties *out);
|
||||
PrRhiPhysicalDeviceProperties prRhiGetPhysicalDeviceProperties(PrRhiPhysicalDevice *pdev);
|
||||
|
||||
// ======================================================================
|
||||
// Surface (platform-specific)
|
||||
// ======================================================================
|
||||
|
||||
PrRhiSurface *prRhiCreateSurfaceFromWindow(PrRhiInstance *inst, void *window_handle);
|
||||
PrRhiSurface *prRhiCreateSurfaceFromWindow(PrRhiInstance *inst, SDL_Window *window);
|
||||
void prRhiDestroySurface(PrRhiInstance *inst, PrRhiSurface *surface);
|
||||
PrRhiSurfaceCapabilities prRhiGetSurfaceCapabilities(PrRhiPhysicalDevice *pdev,
|
||||
PrRhiSurface *surface);
|
||||
@@ -77,6 +77,7 @@ u32 prRhiGetQueueFamilyIndex(PrRhiDevice *device);
|
||||
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);
|
||||
|
||||
@@ -168,7 +169,7 @@ void prRhiDestroyDescriptorPool(PrRhiDevice *device,
|
||||
|
||||
PrRhiDescriptorSet *prRhiAllocateDescriptorSet(PrRhiDevice *device, PrRhiDescriptorPool *pool,
|
||||
PrRhiDescriptorSetLayout *layout,
|
||||
u32 variable_count);
|
||||
WpU32Array variable_descriptor_counts);
|
||||
void prRhiFreeDescriptorSet(PrRhiDevice *device, PrRhiDescriptorPool *pool,
|
||||
PrRhiDescriptorSet *set);
|
||||
void prRhiUpdateDescriptorSet(PrRhiDevice *device, PrRhiWriteDescriptorSetArray writes);
|
||||
@@ -191,13 +192,14 @@ void prRhiDestroySemaphore(PrRhiDevice *device, PrRhiSemaphore *semap
|
||||
// Command pools and command buffers
|
||||
// ======================================================================
|
||||
|
||||
PrRhiCommandPool *prRhiCreateCommandPool(PrRhiDevice *device, PrRhiCommandPoolDesc desc);
|
||||
PrRhiCommandPool *prRhiCreateCommandPool(PrRhiDevice *device);
|
||||
void prRhiDestroyCommandPool(PrRhiDevice *device, PrRhiCommandPool *pool);
|
||||
|
||||
PrRhiCommandBufferArray prRhiAllocateCommandBuffers(PrRhiDevice *device, PrRhiCommandPool *pool,
|
||||
u32 count);
|
||||
|
||||
void prRhiFreeCommandBuffers(PrRhiDevice *device, PrRhiCommandPool *pool,
|
||||
u32 count, PrRhiCommandBufferArray buffers);
|
||||
PrRhiCommandBufferArray buffers);
|
||||
|
||||
// ======================================================================
|
||||
// Command buffer recording
|
||||
@@ -238,8 +240,8 @@ void prRhiCmdPushConstants(PrRhiCommandBuffer *cb, PrRhiPipelineLayout *layout,
|
||||
|
||||
// --- Vertex / index buffers ---
|
||||
|
||||
void prRhiCmdBindVertexBuffers(PrRhiCommandBuffer *cb, u32 first_binding,
|
||||
PrRhiBufferArray buffers, const u64 *offsets, u32 count);
|
||||
void prRhiCmdBindVertexBuffers(PrRhiCommandBuffer *cb, u32 first_binding, PrRhiBufferArray buffers,
|
||||
WpU64Array offsets);
|
||||
void prRhiCmdBindIndexBuffer(PrRhiCommandBuffer *cb, PrRhiBuffer *buffer, u64 offset,
|
||||
PrRhiIndexType index_type);
|
||||
|
||||
|
||||
@@ -357,9 +357,40 @@ typedef struct PrRhiPipelineLayoutDesc {
|
||||
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;
|
||||
@@ -378,11 +409,22 @@ typedef struct PrRhiGraphicsPipelineDesc {
|
||||
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;
|
||||
|
||||
@@ -408,10 +450,6 @@ typedef struct PrRhiFenceDesc {
|
||||
b8 signaled;
|
||||
} PrRhiFenceDesc;
|
||||
|
||||
typedef struct PrRhiCommandPoolDesc {
|
||||
u32 queue_family_index;
|
||||
} PrRhiCommandPoolDesc;
|
||||
|
||||
typedef struct PrRhiSwapchainDesc {
|
||||
PrRhiSurface *surface;
|
||||
u32 width;
|
||||
@@ -443,8 +481,7 @@ typedef u64 PrRhiDeviceAddress;
|
||||
// ============================================================================
|
||||
|
||||
typedef struct PrRhiContext {
|
||||
WpAllocator main;
|
||||
WpAllocator scratch;
|
||||
WpAllocator allocator;
|
||||
} PrRhiContext;
|
||||
|
||||
// --- Command buffer types ---
|
||||
|
||||
+873
-746
File diff suppressed because it is too large
Load Diff
@@ -8,6 +8,7 @@
|
||||
#define PR_RHI_VK_H
|
||||
|
||||
#include "../pr_rhi_types.h"
|
||||
#include <SDL3/SDL_video.h>
|
||||
#include <volk/volk.h>
|
||||
#include <vk_mem_alloc.h>
|
||||
|
||||
@@ -128,10 +129,9 @@ void prRhiDestroyInstanceVk(PrRhiInstance *inst);
|
||||
PrRhiPhysicalDeviceArray prRhiGetPhysicalDevicesVk(PrRhiInstance *inst);
|
||||
void prRhiGetPhysicalDeviceNameVk(PrRhiPhysicalDevice *pdev, WpStr8 *out);
|
||||
void prRhiGetPhysicalDeviceDriverInfoVk(PrRhiPhysicalDevice *pdev, WpStr8 *out);
|
||||
void prRhiGetPhysicalDevicePropertiesVk(PrRhiPhysicalDevice *pdev,
|
||||
PrRhiPhysicalDeviceProperties *out);
|
||||
PrRhiPhysicalDeviceProperties prRhiGetPhysicalDevicePropertiesVk(PrRhiPhysicalDevice *pdev);
|
||||
|
||||
PrRhiSurface *prRhiCreateSurfaceFromWindowVk(PrRhiInstance *inst, void *window_handle);
|
||||
PrRhiSurface *prRhiCreateSurfaceFromWindowVk(PrRhiInstance *inst, SDL_Window *window);
|
||||
void prRhiDestroySurfaceVk(PrRhiInstance *inst, PrRhiSurface *surface);
|
||||
|
||||
PrRhiSurfaceCapabilities prRhiGetSurfaceCapabilitiesVk(PrRhiPhysicalDevice *pdev,
|
||||
@@ -145,6 +145,7 @@ u32 prRhiGetQueueFamilyIndexVk(PrRhiDevice *device);
|
||||
|
||||
PrRhiSwapchain *prRhiCreateSwapchainVk(PrRhiDevice *device, PrRhiSwapchainDesc desc);
|
||||
void prRhiDestroySwapchainVk(PrRhiDevice *device, PrRhiSwapchain *swapchain);
|
||||
u32 prRhiGetSwapchainImageCountVk(PrRhiSwapchain *swapchain);
|
||||
PrRhiSwapchainResult prRhiAcquireNextImageVk(PrRhiDevice *device, PrRhiSwapchain *swapchain,
|
||||
PrRhiSemaphore *signal_semaphore, u32 *out_image_index);
|
||||
PrRhiSwapchainResult prRhiPresentVk(PrRhiDevice *device, PrRhiSwapchain *swapchain,
|
||||
@@ -196,7 +197,7 @@ void prRhiDestroyDescriptorPoolVk(PrRhiDevice *device,
|
||||
PrRhiDescriptorSet *prRhiAllocateDescriptorSetVk(PrRhiDevice *device,
|
||||
PrRhiDescriptorPool *pool,
|
||||
PrRhiDescriptorSetLayout *layout,
|
||||
u32 variable_count);
|
||||
WpU32Array variable_descriptor_counts);
|
||||
void prRhiFreeDescriptorSetVk(PrRhiDevice *device, PrRhiDescriptorPool *pool,
|
||||
PrRhiDescriptorSet *set);
|
||||
void prRhiUpdateDescriptorSetVk(PrRhiDevice *device, PrRhiWriteDescriptorSetArray writes);
|
||||
@@ -211,13 +212,12 @@ void prRhiResetFencesVk(PrRhiDevice *device, PrRhiFenceArray fences, u32 count);
|
||||
PrRhiSemaphore *prRhiCreateSemaphoreVk(PrRhiDevice *device);
|
||||
void prRhiDestroySemaphoreVk(PrRhiDevice *device, PrRhiSemaphore *semaphore);
|
||||
|
||||
PrRhiCommandPool *prRhiCreateCommandPoolVk(PrRhiDevice *device,
|
||||
PrRhiCommandPoolDesc desc);
|
||||
PrRhiCommandPool *prRhiCreateCommandPoolVk(PrRhiDevice *device);
|
||||
void prRhiDestroyCommandPoolVk(PrRhiDevice *device, PrRhiCommandPool *pool);
|
||||
PrRhiCommandBufferArray prRhiAllocateCommandBuffersVk(PrRhiDevice *device, PrRhiCommandPool *pool,
|
||||
u32 count);
|
||||
void prRhiFreeCommandBuffersVk(PrRhiDevice *device, PrRhiCommandPool *pool,
|
||||
u32 count, PrRhiCommandBufferArray buffers);
|
||||
|
||||
void prRhiFreeCommandBuffersVk(PrRhiDevice *device, PrRhiCommandPool *pool, PrRhiCommandBufferArray buffers);
|
||||
|
||||
void prRhiBeginCommandBufferVk(PrRhiCommandBuffer *cb);
|
||||
void prRhiEndCommandBufferVk(PrRhiCommandBuffer *cb);
|
||||
@@ -243,8 +243,8 @@ void prRhiCmdBindDescriptorSetsVk(PrRhiCommandBuffer *cb, PrRhiPipelineBindPoint
|
||||
void prRhiCmdPushConstantsVk(PrRhiCommandBuffer *cb, PrRhiPipelineLayout *layout,
|
||||
PrRhiShaderStage stage_flags, u32 offset, u32 size,
|
||||
const void *data);
|
||||
void prRhiCmdBindVertexBuffersVk(PrRhiCommandBuffer *cb, u32 first_binding,
|
||||
PrRhiBufferArray buffers, const u64 *offsets, u32 count);
|
||||
void prRhiCmdBindVertexBuffersVk(PrRhiCommandBuffer *cb, u32 first_binding, PrRhiBufferArray buffers,
|
||||
WpU64Array offsets);
|
||||
void prRhiCmdBindIndexBufferVk(PrRhiCommandBuffer *cb, PrRhiBuffer *buffer, u64 offset,
|
||||
PrRhiIndexType index_type);
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#define prRhiGetQueueFamilyIndex prRhiGetQueueFamilyIndexVk
|
||||
#define prRhiCreateSwapchain prRhiCreateSwapchainVk
|
||||
#define prRhiDestroySwapchain prRhiDestroySwapchainVk
|
||||
#define prRhiGetSwapchainImageCount prRhiGetSwapchainImageCountVk
|
||||
#define prRhiAcquireNextImage prRhiAcquireNextImageVk
|
||||
#define prRhiPresent prRhiPresentVk
|
||||
#define prRhiRecreateSwapchain prRhiRecreateSwapchainVk
|
||||
|
||||
Reference in New Issue
Block a user