summaryrefslogtreecommitdiff
path: root/Rend
diff options
context:
space:
mode:
authorVasco <[email protected]>2026-08-24 17:47:30 +0100
committerVasco <[email protected]>2026-08-24 17:50:52 +0100
commitcc3429220b19df8c5ca6abf28a02cd38d08de32d (patch)
treedd6fe3911535cc75570e5fe34ff84c758028aa81 /Rend
parentad5248a3e1bafc1b7dec4c8af82d56ed324ef314 (diff)
Cool 0.0.0. Rend 1.0.4.
Diffstat (limited to 'Rend')
-rw-r--r--Rend/rend.c125
-rw-r--r--Rend/rend.h3
-rw-r--r--Rend/rend_internal.h29
-rw-r--r--Rend/rend_vk.c3187
-rw-r--r--Rend/rend_vk_allocator.c118
-rw-r--r--Rend/rend_vk_arena.c264
-rw-r--r--Rend/rend_vk_device.c377
-rw-r--r--Rend/rend_vk_image.c125
-rw-r--r--Rend/rend_vk_internal.c1014
-rw-r--r--Rend/rend_vk_internal.h177
10 files changed, 2568 insertions, 2851 deletions
diff --git a/Rend/rend.c b/Rend/rend.c
index 4d85745..f390de2 100644
--- a/Rend/rend.c
+++ b/Rend/rend.c
@@ -8,12 +8,10 @@
#include "rend.h"
#include "rend_internal.h"
#include "rend_vk.c"
-#include "rend_vk_internal.h"
/* clean up functions */
-static void rend__renderer_destroy_recursive(RendRenderer renderer);
-static void rend__pipeline_destroy_recursive(RendPipeline pipeline);
+static void rend__pipeline_free_list(RendPipeline pipeline);
static bool rend__renderer_init_recursive(RendRenderer renderer, RendBackendType backend, bool auto_pick);
static RendRenderer rend_renderers_head = NULL;
@@ -65,40 +63,44 @@ RendVTable rend_vtables[] = {
extern void
rend_quit()
{
- rend__renderer_destroy_recursive(rend_renderers_head);
+ while (rend_renderers_head)
+ rend_renderer_destroy(rend_renderers_head);
if (rend_backend_vk_initialized) {
rend_vk_quit();
rend_backend_vk_initialized = false;
}
-
}
extern RendRenderer
rend_renderer_create(PeakWindow *target, RendBackendType backend, void* device, bool vsync, RendBindingInfo *bind_info)
{
-
RendRenderer rend = rmalloc(sizeof *rend);
- rend->next = rend_renderers_head;
- rend->prev = NULL;
- rend_renderers_head = rend;
- if(rend->next) {
- rend->next->prev = rend;
- }
+ if (!rend) return NULL;
+ memset(rend, 0, sizeof *rend);
- rend__renderer_init_recursive(rend, backend, false);
+ if (!rend__renderer_init_recursive(rend, backend, false)) {
+ rfree(rend);
+ return NULL;
+ }
rend->vsync = vsync;
rend->bind_info = *bind_info;
rend->window = target;
- rend->pipeline_head = 0;
rend->context = rend_vtables[rend->backend].renderer_create(target, bind_info);
- if (rend->context) {
- return rend;
+ if (!rend->context) {
+ rfree(rend);
+ return NULL;
}
- return NULL;
+ rend->next = rend_renderers_head;
+ rend->prev = NULL;
+ rend_renderers_head = rend;
+ if (rend->next)
+ rend->next->prev = rend;
+
+ return rend;
}
extern void
@@ -107,10 +109,12 @@ rend_renderer_destroy(RendRenderer renderer)
RASSERT(renderer && renderer->context, "Invalid renderer.");
if (!renderer) return;
- rend__pipeline_destroy_recursive(renderer->pipeline_head);
+ rend__pipeline_free_list(renderer->pipeline_head);
+ renderer->pipeline_head = NULL;
- if (renderer->backend != 0) {
+ if (renderer->backend != 0 && renderer->context) {
rend_vtables[renderer->backend].renderer_destroy(renderer->context);
+ renderer->context = NULL;
}
if (renderer->prev) renderer->prev->next = renderer->next;
@@ -118,6 +122,8 @@ rend_renderer_destroy(RendRenderer renderer)
if (renderer->next) renderer->next->prev = renderer->prev;
+ renderer->next = NULL;
+ renderer->prev = NULL;
rfree(renderer);
}
@@ -153,21 +159,21 @@ extern void
rend_renderer_render_pass_begin(RendRenderer renderer, float r, float g ,float b, float a)
{
renderer->in_pass = 1;
- rend_vtables[renderer->backend].renderer_render_pass_begin(renderer, r, g, b, a);
+ rend_vtables[renderer->backend].renderer_render_pass_begin(renderer->context, r, g, b, a);
}
extern void
rend_renderer_render_pass_begin_texture(RendRenderer renderer, RendTexture *texture)
{
renderer->in_pass = 1;
- rend_vtables[renderer->backend].renderer_render_pass_begin_texture(renderer, texture);
+ rend_vtables[renderer->backend].renderer_render_pass_begin_texture(renderer->context, texture);
}
extern void
rend_renderer_render_pass_end_texture(RendRenderer renderer, RendTexture *texture)
{
renderer->in_pass = 0;
- rend_vtables[renderer->backend].renderer_render_pass_end_texture(renderer, texture);
+ rend_vtables[renderer->backend].renderer_render_pass_end_texture(renderer->context, texture);
}
@@ -175,25 +181,25 @@ extern void
rend_renderer_render_pass_end(RendRenderer renderer)
{
renderer->in_pass = 0;
- rend_vtables[renderer->backend].renderer_render_pass_end(renderer);
+ rend_vtables[renderer->backend].renderer_render_pass_end(renderer->context);
}
extern void
rend_descriptor_write_ubo(RendRenderer renderer, RendBuffer ubo, uint32_t binding, uint32_t slot)
{
- rend_vtables[renderer->backend].descriptor_write_buffer(renderer, ubo, binding, slot, 0, ubo.size, true);
+ rend_vtables[renderer->backend].descriptor_write_buffer(renderer->context, ubo, binding, slot, 0, ubo.size, true);
}
extern void
rend_descriptor_write_ssbo(RendRenderer renderer, RendBuffer ssbo, uint32_t binding, uint32_t slot)
{
- rend_vtables[renderer->backend].descriptor_write_buffer(renderer, ssbo, binding, slot, 0, ssbo.size, false);
+ rend_vtables[renderer->backend].descriptor_write_buffer(renderer->context, ssbo, binding, slot, 0, ssbo.size, false);
}
extern RendBuffer
rend_buffer_create(RendRenderer renderer, size_t size, RendBufferType type, bool gpu) {
- RendBuffer buffer = rend_vtables[renderer->backend].buffer_create_lifetime(renderer, size, type, gpu, REND_LIFETIME_PERMANENT);
+ RendBuffer buffer = rend_vtables[renderer->backend].buffer_create_lifetime(renderer->context, size, type, gpu, REND_LIFETIME_PERMANENT);
buffer.backend = renderer->backend;
return buffer;
}
@@ -211,9 +217,9 @@ rend_buffer_write(RendRenderer renderer, RendBuffer *buffer, const void *data, s
memcpy(ptr + offset, data, size);
} else {
/* if the memory is bound to the device we must create and deallocate a transfer buffer */
- RendBuffer transfer_buffer = rend_vtables[buffer->backend].buffer_create_lifetime(renderer, size, REND_BUFFER_TRANSFER, false, REND_LIFETIME_FRAME);
+ RendBuffer transfer_buffer = rend_vtables[buffer->backend].buffer_create_lifetime(renderer->context, size, REND_BUFFER_TRANSFER, false, REND_LIFETIME_FRAME);
memcpy(transfer_buffer.mapped_memory, data, size);
- rend_vtables[buffer->backend].buffer_copy(renderer, buffer, offset, &transfer_buffer, 0, size);
+ rend_vtables[buffer->backend].buffer_copy(renderer->context, buffer, offset, &transfer_buffer, 0, size);
rend_vtables[buffer->backend].buffer_destroy(&transfer_buffer);
}
}
@@ -221,7 +227,7 @@ rend_buffer_write(RendRenderer renderer, RendBuffer *buffer, const void *data, s
extern void
rend_buffer_copy(RendRenderer renderer, RendBuffer *dest, size_t dest_offset, RendBuffer *src, size_t src_offset, size_t bytes)
{
- rend_vtables[renderer->backend].buffer_copy(renderer, dest, dest_offset, src, src_offset, bytes);
+ rend_vtables[renderer->backend].buffer_copy(renderer->context, dest, dest_offset, src, src_offset, bytes);
}
extern uint64_t
@@ -234,7 +240,7 @@ rend_buffer_address(RendBuffer *buffer)
extern RendTexture
rend_texture_create(RendRenderer renderer, uint32_t width, uint32_t height, uint32_t depth, uint32_t mip_levels, uint32_t layers, RendFormat format)
{
- RendTexture tex = rend_vtables[renderer->backend].texture_create(renderer, width, height, depth, mip_levels, layers, format);
+ RendTexture tex = rend_vtables[renderer->backend].texture_create(renderer->context, width, height, depth, mip_levels, layers, format);
tex.backend = renderer->backend;
return tex;
}
@@ -242,14 +248,14 @@ rend_texture_create(RendRenderer renderer, uint32_t width, uint32_t height, uint
extern RendTexture
rend_texture_create_from_data(RendRenderer renderer, const void *data, uint32_t width, uint32_t height, RendFormat format)
{
- RendTexture tex = rend_vtables[renderer->backend].texture_create(renderer, width, height, 1, 1, 1, format);
+ RendTexture tex = rend_vtables[renderer->backend].texture_create(renderer->context, width, height, 1, 1, 1, format);
tex.backend = renderer->backend;
uint32_t size = width * height * rend_format_size[format];
- RendBuffer staging_buffer = rend_vtables[renderer->backend].buffer_create_lifetime(renderer, size, REND_BUFFER_TRANSFER, false, REND_LIFETIME_FRAME);
+ RendBuffer staging_buffer = rend_vtables[renderer->backend].buffer_create_lifetime(renderer->context, size, REND_BUFFER_TRANSFER, false, REND_LIFETIME_FRAME);
memcpy(staging_buffer.mapped_memory, data, size);
- rend_vtables[renderer->backend].texture_copy_buffer(renderer, &tex, &staging_buffer);
+ rend_vtables[renderer->backend].texture_copy_buffer(renderer->context, &tex, &staging_buffer);
rend_vtables[renderer->backend].buffer_destroy(&staging_buffer);
return tex;
}
@@ -257,9 +263,9 @@ rend_texture_create_from_data(RendRenderer renderer, const void *data, uint32_t
extern void
rend_texture_copy_data(RendRenderer renderer, RendTexture *texture, const void *data, size_t size)
{
- RendBuffer staging_buffer = rend_vtables[renderer->backend].buffer_create_lifetime(renderer, size, REND_BUFFER_TRANSFER, false, REND_LIFETIME_FRAME);
+ RendBuffer staging_buffer = rend_vtables[renderer->backend].buffer_create_lifetime(renderer->context, size, REND_BUFFER_TRANSFER, false, REND_LIFETIME_FRAME);
memcpy(staging_buffer.mapped_memory, data, size);
- rend_vtables[renderer->backend].texture_copy_buffer(renderer, texture, &staging_buffer);
+ rend_vtables[renderer->backend].texture_copy_buffer(renderer->context, texture, &staging_buffer);
rend_vtables[renderer->backend].buffer_destroy(&staging_buffer);
}
@@ -267,13 +273,13 @@ rend_texture_copy_data(RendRenderer renderer, RendTexture *texture, const void *
extern void
rend_texture_copy_buffer(RendRenderer renderer, RendTexture *texture, RendBuffer *buffer)
{
- rend_vtables[renderer->backend].texture_copy_buffer(renderer, texture, buffer);
+ rend_vtables[renderer->backend].texture_copy_buffer(renderer->context, texture, buffer);
}
extern void
rend_texture_blit(RendRenderer renderer, RendTexture *src, RendTexture *dst, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h, uint32_t dst_x, uint32_t dst_y, uint32_t dst_w, uint32_t dst_h)
{
- rend_vtables[renderer->backend].texture_blit(renderer, src, dst, src_x, src_y, src_w, src_h, dst_x, dst_y, dst_w, dst_h);
+ rend_vtables[renderer->backend].texture_blit(renderer->context, src, dst, src_x, src_y, src_w, src_h, dst_x, dst_y, dst_w, dst_h);
}
extern uint64_t
@@ -285,7 +291,7 @@ rend_texture_id(RendTexture *texture)
extern void
rend_texture_destroy(RendRenderer renderer, RendTexture *tex)
{
- rend_vtables[renderer->backend].texture_destroy(renderer, tex);
+ rend_vtables[renderer->backend].texture_destroy(renderer->context, tex);
}
extern void
@@ -341,7 +347,7 @@ rend_pipeline_create_graphics_spirv(RendRenderer renderer, uint8_t *vertex_bytes
.color_format = color_format,
};
- if (rend_vtables[renderer->backend].pipeline_create(renderer, pipeline, config, REND__PIPELINE_GRAPHICS, vertex_bytes, vertex_size, frag_bytes, frag_size, NULL, 0)) {
+ if (rend_vtables[renderer->backend].pipeline_create(renderer->context, pipeline, config, REND__PIPELINE_GRAPHICS, vertex_bytes, vertex_size, frag_bytes, frag_size, NULL, 0)) {
pipeline->backend = renderer->backend;
pipeline->next = renderer->pipeline_head;
@@ -378,7 +384,7 @@ rend_pipeline_create_graphics_bindless_spirv(RendRenderer renderer, uint8_t *ver
.color_format = color_format,
};
- if (rend_vtables[renderer->backend].pipeline_create(renderer, pipeline, config, REND__PIPELINE_GRAPHICS, vertex_bytes, vertex_size, frag_bytes, frag_size, NULL, 0)) {
+ if (rend_vtables[renderer->backend].pipeline_create(renderer->context, pipeline, config, REND__PIPELINE_GRAPHICS, vertex_bytes, vertex_size, frag_bytes, frag_size, NULL, 0)) {
pipeline->backend = renderer->backend;
pipeline->next = renderer->pipeline_head;
@@ -404,7 +410,7 @@ rend_pipeline_create_compute_spirv(RendRenderer renderer, const uint8_t *compute
.push_constant_count = push_constant_count,
};
- if (rend_vtables[renderer->backend].pipeline_create(renderer, pipeline, config, REND__PIPELINE_COMPUTE, compute_bytes, compute_size, NULL, 0, NULL, 0)) {
+ if (rend_vtables[renderer->backend].pipeline_create(renderer->context, pipeline, config, REND__PIPELINE_COMPUTE, compute_bytes, compute_size, NULL, 0, NULL, 0)) {
pipeline->backend = renderer->backend;
pipeline->type = REND__PIPELINE_COMPUTE;
@@ -432,7 +438,7 @@ rend_pipeline_create_meshlet_spirv(RendRenderer renderer, uint8_t *meshlet_bytes
.cull_mode = cull_mode,
.depth_test_enable = depth_test_enable
};
- if (rend_vtables[renderer->backend].pipeline_create(renderer, pipeline, config, REND__PIPELINE_MESH, meshlet_bytes, meshlet_size, frag_bytes, frag_size, NULL, 0)) {
+ if (rend_vtables[renderer->backend].pipeline_create(renderer->context, pipeline, config, REND__PIPELINE_MESH, meshlet_bytes, meshlet_size, frag_bytes, frag_size, NULL, 0)) {
pipeline->backend = renderer->backend;
pipeline->type = REND__PIPELINE_MESH;
@@ -483,28 +489,28 @@ extern void
rend_cmd_render_begin(RendRenderer renderer, float r, float g, float b, float a)
{
renderer->in_pass = 1;
- rend_vtables[renderer->backend].renderer_render_pass_begin(renderer, r, g, b, a);
+ rend_vtables[renderer->backend].renderer_render_pass_begin(renderer->context, r, g, b, a);
}
extern void
rend_cmd_render_begin_texture(RendRenderer renderer, RendTexture *texture)
{
renderer->in_pass = 1;
- rend_vtables[renderer->backend].renderer_render_pass_begin_texture(renderer, texture);
+ rend_vtables[renderer->backend].renderer_render_pass_begin_texture(renderer->context, texture);
}
extern void
rend_cmd_render_end(RendRenderer renderer)
{
renderer->in_pass = 0;
- rend_vtables[renderer->backend].renderer_render_pass_end(renderer);
+ rend_vtables[renderer->backend].renderer_render_pass_end(renderer->context);
}
extern void
rend_cmd_render_end_texture(RendRenderer renderer, RendTexture *texture)
{
renderer->in_pass = 0;
- rend_vtables[renderer->backend].renderer_render_pass_end_texture(renderer, texture);
+ rend_vtables[renderer->backend].renderer_render_pass_end_texture(renderer->context, texture);
}
extern void
@@ -557,7 +563,7 @@ rend_cmd_blit(RendRenderer renderer, RendTexture *src, RendTexture *dst, uint32_
RASSERT(renderer->in_frame && "Must be called while rendering a frame!");
RASSERT(!renderer->in_pass && "Must be called outside a render pass!");
renderer->in_pass = true;
- rend_vtables[renderer->backend].texture_blit(renderer, src, dst, src_x, src_y, src_w, src_h, dst_x, dst_y, dst_w, dst_h);
+ rend_vtables[renderer->backend].texture_blit(renderer->context, src, dst, src_x, src_y, src_w, src_h, dst_x, dst_y, dst_w, dst_h);
}
static bool
@@ -597,24 +603,13 @@ rend__renderer_init_recursive(RendRenderer renderer, RendBackendType backend, bo
}
static void
-rend__renderer_destroy_recursive(RendRenderer renderer)
+rend__pipeline_free_list(RendPipeline pipeline)
{
- if (renderer == NULL) return;
-
- rend__renderer_destroy_recursive(renderer->next);
-
- if (renderer->backend != 0) {
- rend_vtables[renderer->backend].renderer_destroy(renderer);
+ while (pipeline) {
+ RendPipeline next = pipeline->next;
+ pipeline->next = NULL;
+ pipeline->prev = NULL;
+ rfree(pipeline);
+ pipeline = next;
}
-
- rend__pipeline_destroy_recursive(renderer->pipeline_head);
- rfree(renderer);
-}
-
-static void
-rend__pipeline_destroy_recursive(RendPipeline pipeline)
-{
- if (pipeline == NULL) return;
- rend__pipeline_destroy_recursive(pipeline->next);
- rfree(pipeline);
}
diff --git a/Rend/rend.h b/Rend/rend.h
index c4ba1d4..489686a 100644
--- a/Rend/rend.h
+++ b/Rend/rend.h
@@ -15,7 +15,7 @@
#define REND_MAJOR 1 // breaking API changes
#define REND_MINOR 0 // non-breaking features
-#define REND_PATCH 3 // non-breaking patches and bug fixes
+#define REND_PATCH 4 // non-breaking patches and bug fixes
#ifndef PEAK_VULKAN
#define PEAK_VULKAN
@@ -284,6 +284,7 @@ enum RendBufferType_t {
* 1.0.1 - @vasco - render pass that targets textures
* 1.0.2 - @vasco - Peak instead of Podium
* 1.0.3 - @vasco - frame_begin no longer sticks in_frame or burns timeline on OUT_OF_DATE
+ * 1.0.4 - @vasco - vulkan backend collapsed; renderer create fails cleanly
*
* 1.0.0 finished API release
*
diff --git a/Rend/rend_internal.h b/Rend/rend_internal.h
index 4993d92..78275cc 100644
--- a/Rend/rend_internal.h
+++ b/Rend/rend_internal.h
@@ -1,9 +1,6 @@
#ifndef REND_INTERNAL_H
#define REND_INTERNAL_H
-#include "rend_vk_internal.h"
-
-
#if defined(REND_DEBUG)
#ifndef P_LOG_DEBUG_ENABLED
#define P_LOG_DEBUG_ENABLED 1
@@ -78,19 +75,19 @@ typedef struct {
bool (*renderer_frame_begin)(RendContextHandle);
void (*renderer_frame_end)(RendContextHandle, float *delta);
- void (*descriptor_write_buffer)(RendRenderer renderer, RendBuffer ubo, uint32_t binding, uint32_t slot, uint32_t offset, uint32_t size, bool is_ubo);
- void (*descriptor_write_texture)(void *ctx, RendTexture *texture, uint32_t binding, uint32_t slot);
+ void (*descriptor_write_buffer)(RendContextHandle handle, RendBuffer ubo, uint32_t binding, uint32_t slot, uint32_t offset, uint32_t size, bool is_ubo);
+ void (*descriptor_write_texture)(RendContextHandle handle, RendTexture *texture, uint32_t binding, uint32_t slot);
- RendBuffer (*buffer_create_lifetime)(RendRenderer renderer, size_t size, RendBufferType type, bool gpu, int lifetime);
+ RendBuffer (*buffer_create_lifetime)(RendContextHandle handle, size_t size, RendBufferType type, bool gpu, int lifetime);
void (*buffer_destroy)(RendBuffer *buffer);
- void (*buffer_copy)(RendRenderer renderer, RendBuffer *dest, size_t dest_offset, RendBuffer *src, size_t src_offset, size_t bytes);
+ void (*buffer_copy)(RendContextHandle handle, RendBuffer *dest, size_t dest_offset, RendBuffer *src, size_t src_offset, size_t bytes);
- RendTexture (*texture_create)(RendRenderer renderer, uint32_t width, uint32_t height, uint32_t depth, uint32_t mip_levels, uint32_t layers, RendFormat format);
- void (*texture_destroy)(RendRenderer renderer, RendTexture *tex);
- void (*texture_copy_buffer)(RendRenderer renderer, RendTexture *texture, RendBuffer *buffer);
- void (*texture_blit)(RendRenderer renderer, RendTexture *src, RendTexture *dst, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h, uint32_t dst_x, uint32_t dst_y, uint32_t dst_w, uint32_t dst_h);
+ RendTexture (*texture_create)(RendContextHandle handle, uint32_t width, uint32_t height, uint32_t depth, uint32_t mip_levels, uint32_t layers, RendFormat format);
+ void (*texture_destroy)(RendContextHandle handle, RendTexture *tex);
+ void (*texture_copy_buffer)(RendContextHandle handle, RendTexture *texture, RendBuffer *buffer);
+ void (*texture_blit)(RendContextHandle handle, RendTexture *src, RendTexture *dst, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h, uint32_t dst_x, uint32_t dst_y, uint32_t dst_w, uint32_t dst_h);
- bool (*pipeline_create)(RendRenderer, RendPipeline, Rend__PipelineConfig, uint8_t type, const uint8_t *shader1, size_t bytes1, const uint8_t *shader2, size_t bytes2, const uint8_t *shader3, size_t bytes3);
+ bool (*pipeline_create)(RendContextHandle, RendPipeline, Rend__PipelineConfig, uint8_t type, const uint8_t *shader1, size_t bytes1, const uint8_t *shader2, size_t bytes2, const uint8_t *shader3, size_t bytes3);
void (*pipeline_bind)(RendPipeline);
void (*pipeline_push_constants)(RendPipeline pipeline, void *push_data, size_t size);
@@ -102,10 +99,10 @@ typedef struct {
void (*pipeline_draw_indexed)(RendPipeline pipeline, uint32_t index_count, uint32_t first_index, int32_t vertex_offset, uint32_t instance_count);
void (*pipeline_set_blend)(RendPipeline, bool);
- void (*renderer_render_pass_begin)(RendRenderer renderer, float r, float g, float b, float a);
- void (*renderer_render_pass_begin_texture)(RendRenderer, RendTexture*);
- void (*renderer_render_pass_end)(RendRenderer renderer);
- void (*renderer_render_pass_end_texture)(RendRenderer renderer, RendTexture*);
+ void (*renderer_render_pass_begin)(RendContextHandle handle, float r, float g, float b, float a);
+ void (*renderer_render_pass_begin_texture)(RendContextHandle, RendTexture*);
+ void (*renderer_render_pass_end)(RendContextHandle handle);
+ void (*renderer_render_pass_end_texture)(RendContextHandle handle, RendTexture*);
} RendVTable;
diff --git a/Rend/rend_vk.c b/Rend/rend_vk.c
index 8fac97b..cfce9d4 100644
--- a/Rend/rend_vk.c
+++ b/Rend/rend_vk.c
@@ -1,53 +1,46 @@
-#pragma once
-#include "rend.h"
-#include "rend_internal.h"
+/*
+ * Vulkan 1.4 backend. Per-renderer context is RendVk14Context.
+ * Instance, allocator, and device are process-global (see rend_vk_internal.c).
+ *
+ * * 1.0.3 - @vasco - backend functions take RendContextHandle
+ */
+
#include <stdint.h>
#include <vulkan/vulkan.h>
#include <vulkan/vulkan_core.h>
-#include "rend_vk_internal.h"
-#include "rend_vk_allocator.c"
-#include "rend_vk_device.c"
-#include "rend_vk_arena.c"
-#include "rend_vk_image.c"
+#include "rend.h"
+#include "rend_internal.h"
+#include "rend_vk_internal.c"
-#define REND_MIN_FRAMES_IN_FLIGHT 2 // double buffering!
-#define REND_MAX_FRAMES_IN_FLIGHT 4 // quadruple buffering!
+#define REND_MIN_FRAMES_IN_FLIGHT 2 /* double buffering! */
+#define REND_MAX_FRAMES_IN_FLIGHT 4 /* quadruple buffering! */
#define REND_VK_MAX_PIPELINES 100
typedef struct {
- VkSwapchainKHR handle;
- VkSurfaceFormatKHR format;
- VkExtent2D extent;
+ VkSwapchainKHR handle;
+ VkSurfaceFormatKHR format;
+ VkExtent2D extent;
- uint32_t image_count;
- VkImage *images;
- VkImageView *views;
+ uint32_t image_count;
+ VkImage *images;
+ VkImageView *views;
- RendVkImage depth_attachment;
+ RendVkImage depth_attachment;
} RendVkSwapchain;
typedef struct {
- VkCommandPool command_pool;
- VkCommandBuffer command_buffer;
- VkSemaphore image_acquired_semaphore;
+ VkCommandPool command_pool;
+ VkCommandBuffer command_buffer;
+ VkSemaphore image_acquired_semaphore;
} RendVkFrameResources;
-typedef struct {
- uint8_t push_data[128];
- uint32_t size;
-} RendVkResourceSet;
-
typedef struct RendVkPipeline {
- void *ctx;
- VkPipeline handle;
- VkPipelineLayout layout;
- uint32_t vertex_count;
- uint32_t vertex_stride;
- uint32_t push_constants_range;
-
- bool blend_enable;
+ VkPipeline handle;
+ VkPipelineLayout layout;
+ uint32_t push_constants_range;
+ bool blend_enable;
} RendVkPipeline;
@@ -56,1851 +49,1627 @@ typedef struct RendVkPipeline {
* such as the instance, the allocator, the devices etc...
*/
typedef struct RendVk14Context {
+ PeakWindow *window;
+ VkSurfaceKHR surface;
+ RendVkPipeline pipelines[REND_VK_MAX_PIPELINES];
+ RendVkFrameResources frame_resources[REND_MAX_FRAMES_IN_FLIGHT];
+ RendVkSwapchain swapchain;
+ VkSemaphore timeline_semaphore;
+ VkSemaphore render_complete_semaphores[REND_MAX_FRAMES_IN_FLIGHT];
- RendVkDevice device; // SPEC: All objects created or allocated from a VkDevice are private to that device, and must not be used on other devices.
-
- PeakWindow *window;
- VkSurfaceKHR surface;
- RendVkPipeline pipelines[REND_VK_MAX_PIPELINES];
- RendVkFrameResources frame_resources[REND_MAX_FRAMES_IN_FLIGHT];
- RendVkSwapchain swapchain;
- VkSemaphore timeline_semaphore;
- VkSemaphore render_complete_semaphores[REND_MAX_FRAMES_IN_FLIGHT];
-
- VkCommandPool upload_command_pool;
- VkCommandPool graphics_command_pool;
+ VkCommandPool upload_command_pool;
+ VkCommandPool graphics_command_pool;
- RendVkArenaAllocator arena_persistent; // magical arena allocator for every type of memory
- RendVkArenaAllocator arena_frame;
+ RendVkArenaAllocator arena_persistent; /* magical arena allocator for every type of memory */
+ RendVkArenaAllocator arena_frame;
- uint64_t frame;
- uint64_t frame_index;
- uint64_t signal_value;
- uint64_t next_signal_value;
- uint64_t max_frames_in_flight;
- uint32_t pipeline_count;
- uint32_t image_index;
+ uint64_t frame;
+ uint64_t frame_index;
+ uint64_t signal_value;
+ uint64_t next_signal_value;
+ uint64_t max_frames_in_flight;
+ uint32_t pipeline_count;
+ uint32_t image_index;
- bool require_swapchain_recreation;
+ bool require_swapchain_recreation;
- bool vsync;
- bool in_frame;
+ bool vsync;
+ bool in_frame;
- VkDescriptorPool descriptor_pool;
- VkDescriptorSet desc_set;
- VkDescriptorSetLayout desc_layout;
+ VkDescriptorPool descriptor_pool;
+ VkDescriptorSet desc_set;
+ VkDescriptorSetLayout desc_layout;
} RendVk14Context;
-/* function declarations */
-extern bool rend_vk_init();
-extern void rend_vk_quit();
-
-extern RendContextHandle rend_vk_renderer_create(PeakWindow *window, RendBindingInfo *bind_info);
-extern void rend_vk_renderer_destroy(RendContextHandle handle);
-extern bool rend_vk_renderer_frame_begin(RendContextHandle handle);
-extern void rend_vk_renderer_frame_end(RendContextHandle handle, float *delta);
-
-static inline void rend_vk__renderer_render_pass_begin_internal(RendRenderer renderer, float r, float g, float b, float a, uint64_t view_handle, uint64_t depth_attachment_view_handle, uint32_t offset_x, uint32_t offset_y, uint32_t width, uint32_t height);
-
-extern void rend_vk_renderer_render_pass_begin(RendRenderer renderer, float r, float g, float b, float a);
-extern void rend_vk_renderer_render_pass_begin_texture(RendRenderer renderer, RendTexture *texture);
-extern void rend_vk_renderer_render_pass_end(RendRenderer renderer);
-extern void rend_vk_renderer_render_pass_end_texture(RendRenderer renderer, RendTexture *texture);
-
-extern void rend_vk_descriptor_write_buffer(RendRenderer renderer, RendBuffer ubo, uint32_t binding, uint32_t slot, uint32_t offset, uint32_t size, bool is_ubo);
-extern void rend_vk_descriptor_write_texture(void *ctx, RendTexture *texture, uint32_t binding, uint32_t slot);
-
-extern RendBuffer rend_vk_buffer_create_lifetime(RendRenderer renderer, size_t size, RendBufferType type, bool gpu, int lifetime);
-extern void rend_vk_buffer_destroy(RendBuffer *buffer);
-extern void rend_vk_buffer_copy(RendRenderer renderer, RendBuffer *dest, size_t dest_offset, RendBuffer *src, size_t src_offset, size_t bytes);
-
-extern RendTexture rend_vk_texture_create(RendRenderer renderer, uint32_t width, uint32_t height, uint32_t depth, uint32_t mip_levels, uint32_t layers, RendFormat format);
-extern void rend_vk_texture_destroy(RendRenderer renderer, RendTexture *tex);
-extern void rend_vk_texture_transition_layout(RendRenderer renderer, VkCommandBuffer cmd, RendTexture *texture, VkImageLayout new_layout);
-extern void rend_vk_texture_transfer_ownership_release(RendRenderer renderer, VkCommandBuffer cmd, RendTexture *texture, uint32_t src_family, uint32_t dst_family, VkImageLayout new_layout);
-extern void rend_vk_texture_transfer_ownership_acquire(RendRenderer renderer, VkCommandBuffer cmd, RendTexture *texture, uint32_t src_family, uint32_t dst_family, VkImageLayout new_layout);
-extern void rend_vk_texture_copy_buffer(RendRenderer renderer, RendTexture *texture, RendBuffer *buffer);
-extern void rend_vk_texture_blit(RendRenderer renderer, RendTexture *src, RendTexture *dst, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h, uint32_t dst_x, uint32_t dst_y, uint32_t dst_w, uint32_t dst_h);
-
+static void rend_vk_texture_transition_layout(RendContextHandle handle, VkCommandBuffer cmd, RendTexture *texture, VkImageLayout new_layout);
static VkCommandBuffer rend_vk_cmdbuffer_single_use_begin(VkCommandPool pool);
static void rend_vk_cmdbuffer_single_use_end(VkCommandPool pool, VkCommandBuffer cmd, VkQueue q);
-
-extern bool rend_vk_pipeline_create(RendRenderer renderer, RendPipeline pipeline, Rend__PipelineConfig config, uint8_t type, const uint8_t *shader1, size_t bytes1, const uint8_t *shader2, size_t bytes2, const uint8_t *shader3, size_t bytes3);
-extern void rend_vk_pipeline_bind(RendPipeline);
-extern void rend_vk_pipeline_push_constants(RendPipeline pipeline, void *push_data, size_t size);
-
-extern void rend_vk_pipeline_bind_vertex_buffer(RendPipeline pipeline, uint32_t binding, RendBuffer buffer, size_t offset);
-extern void rend_vk_pipeline_bind_index_buffer(RendPipeline pipeline, RendBuffer buffer, size_t offset, RendIndexType index_type);
-
-extern void rend_vk_pipeline_dispatch(RendPipeline pipeline, uint32_t x, uint32_t y, uint32_t z);
-extern void rend_vk_pipeline_draw(RendPipeline, size_t count, uint32_t instance_count);
-extern void rend_vk_pipeline_draw_indexed(RendPipeline pipeline, uint32_t index_count, uint32_t first_index, int32_t vertex_offset, uint32_t instance_count);
-extern void rend_vk_pipeline_set_blend(RendPipeline, bool);
-
-VKAPI_ATTR VkBool32 VKAPI_CALL rend_vk_debug_func( VkDebugUtilsMessageSeverityFlagBitsEXT message_severity, VkDebugUtilsMessageTypeFlagsEXT message_types, const VkDebugUtilsMessengerCallbackDataEXT *callback_data, void *user_data);
static void rend_vk_pipeline_destroy(RendVkPipeline *pipeline);
static void rend_vk_swapchain_create(RendVk14Context *ctx, RendVkSwapchain *swapchain);
static void rend_vk_swapchain_destroy(RendVk14Context *ctx, RendVkSwapchain *swapchain);
-
static VkShaderModule rend_vk_shader_module_create(const void *data, size_t size);
static uint32_t rend_vk_get_heap_index(uint32_t memory_type_bits, uint32_t preferred_index);
+VKAPI_ATTR VkBool32 VKAPI_CALL rend_vk_debug_func(VkDebugUtilsMessageSeverityFlagBitsEXT message_severity, VkDebugUtilsMessageTypeFlagsEXT message_types, const VkDebugUtilsMessengerCallbackDataEXT *callback_data, void *user_data);
-extern bool
-rend_vk_init()
+bool
+rend_vk_init(void)
{
- RASSERT(sizeof(void*) == 8 && sizeof(int64_t) == 8 && sizeof(double) == 8, "SPEC: Host device 64-bit integer and floating-point types.");
+ RASSERT(sizeof(void*) == 8 && sizeof(int64_t) == 8 && sizeof(double) == 8, "SPEC: Host device 64-bit integer and floating-point types.");
- /* trying to init another renderer with the same backend */
- if (vk_instance) {
- return true;
- }
+ /* trying to init another renderer with the same backend */
+ if (vk_instance) {
+ return true;
+ }
- /* create instance if does not exist */
- VkApplicationInfo vk_app_info = {VK_STRUCTURE_TYPE_APPLICATION_INFO};
- vk_app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
- vk_app_info.pApplicationName = "REND";
- vk_app_info.applicationVersion = VK_MAKE_VERSION(REND_MAJOR, REND_MINOR, REND_PATCH);
- vk_app_info.apiVersion = VK_API_VERSION_1_4;
- vk_app_info.pEngineName = "REND Renderer";
- vk_app_info.engineVersion = VK_MAKE_VERSION(REND_MAJOR, REND_MINOR, REND_PATCH);
+ /* create instance if does not exist */
+ VkApplicationInfo vk_app_info = {VK_STRUCTURE_TYPE_APPLICATION_INFO};
+ vk_app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
+ vk_app_info.pApplicationName = "REND";
+ vk_app_info.applicationVersion = VK_MAKE_VERSION(REND_MAJOR, REND_MINOR, REND_PATCH);
+ vk_app_info.apiVersion = VK_API_VERSION_1_4;
+ vk_app_info.pEngineName = "REND Renderer";
+ vk_app_info.engineVersion = VK_MAKE_VERSION(REND_MAJOR, REND_MINOR, REND_PATCH);
- uint32_t peak_ext_count = 0;
- const char **peak_exts = peak_vulkan_get_extensions(&peak_ext_count);
- const char *extensions[8];
- uint32_t ext_count = 0;
- uint32_t ei;
- for (ei = 0; ei < peak_ext_count && ext_count < 8; ei++)
- extensions[ext_count++] = peak_exts[ei];
+ uint32_t peak_ext_count = 0;
+ const char **peak_exts = peak_vulkan_get_extensions(&peak_ext_count);
+ const char *extensions[8];
+ uint32_t ext_count = 0;
+ uint32_t ei;
+ for (ei = 0; ei < peak_ext_count && ext_count < 8; ei++)
+ extensions[ext_count++] = peak_exts[ei];
#ifdef REND_DEBUG
- if (ext_count < 8)
- extensions[ext_count++] = VK_EXT_DEBUG_UTILS_EXTENSION_NAME;
- PDEBUG("Vulkan Extensions: ");
- for (ei = 0; ei < ext_count; ei++)
- PDEBUG("%s", extensions[ei]);
+ if (ext_count < 8)
+ extensions[ext_count++] = VK_EXT_DEBUG_UTILS_EXTENSION_NAME;
+ PDEBUG("Vulkan Extensions: ");
+ for (ei = 0; ei < ext_count; ei++)
+ PDEBUG("%s", extensions[ei]);
#endif
#ifdef REND_DEBUG
- const char *required_validation_layers[] = { "VK_LAYER_KHRONOS_validation" };
- uint32_t layer_count = 1;
-
- PDEBUG("Required Validation Layers: ");
- for (ei = 0; ei < layer_count; ei++) {
- PDEBUG(" - %s", required_validation_layers[ei]);
- }
+ const char *required_validation_layers[] = { "VK_LAYER_KHRONOS_validation" };
+ uint32_t layer_count = 1;
- VkValidationFeatureEnableEXT enabled_validation_features[] = {
- // VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT,
- // VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT,
- };
+ PDEBUG("Required Validation Layers: ");
+ for (ei = 0; ei < layer_count; ei++) {
+ PDEBUG(" - %s", required_validation_layers[ei]);
+ }
- VkValidationFeaturesEXT validation_features = {
- .sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT,
- .pNext = NULL,
- // .enabledValidationFeatureCount = sizeof(enabled_validation_features) / sizeof(enabled_validation_features[0]),
- // .pEnabledValidationFeatures = enabled_validation_features,
- };
+ VkValidationFeaturesEXT validation_features = {
+ .sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT,
+ .pNext = NULL,
+ /* GPU-assisted validation: VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT */
+ };
#endif
- VkInstanceCreateInfo vk_create_info = { VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO};
- vk_create_info.pApplicationInfo = &vk_app_info;
- vk_create_info.ppEnabledExtensionNames = extensions;
- vk_create_info.enabledExtensionCount = ext_count;
- vk_create_info.pApplicationInfo = &vk_app_info;
+ VkInstanceCreateInfo vk_create_info = { VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO};
+ vk_create_info.pApplicationInfo = &vk_app_info;
+ vk_create_info.ppEnabledExtensionNames = extensions;
+ vk_create_info.enabledExtensionCount = ext_count;
+ vk_create_info.pApplicationInfo = &vk_app_info;
#ifdef REND_DEBUG
- vk_create_info.enabledLayerCount = layer_count;
- vk_create_info.ppEnabledLayerNames = required_validation_layers;
- vk_create_info.pNext = &validation_features;
+ vk_create_info.enabledLayerCount = layer_count;
+ vk_create_info.ppEnabledLayerNames = required_validation_layers;
+ vk_create_info.pNext = &validation_features;
#else
- vk_create_info.enabledLayerCount = 0;
- vk_create_info.ppEnabledLayerNames = NULL;
+ vk_create_info.enabledLayerCount = 0;
+ vk_create_info.ppEnabledLayerNames = NULL;
#endif
- VkResult res = vkCreateInstance(&vk_create_info, vk_allocator, &vk_instance);
- CHECK_VK_RESULT(res);
+ VkResult res = vkCreateInstance(&vk_create_info, vk_allocator, &vk_instance);
+ CHECK_VK_RESULT(res);
- PDEBUG("Vulkan instance created!");
+ PDEBUG("Vulkan instance created!");
#ifdef REND_DEBUG
- uint32_t log_severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
- VkDebugUtilsMessengerCreateInfoEXT debug_create_info = { VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT};
- debug_create_info.messageSeverity = log_severity;
- debug_create_info.messageType =
- VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
- VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT |
- VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;
- debug_create_info.pfnUserCallback = rend_vk_debug_func;
+ uint32_t log_severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
+ VkDebugUtilsMessengerCreateInfoEXT debug_create_info = { VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT};
+ debug_create_info.messageSeverity = log_severity;
+ debug_create_info.messageType =
+ VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
+ VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT |
+ VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;
+ debug_create_info.pfnUserCallback = rend_vk_debug_func;
- PFN_vkCreateDebugUtilsMessengerEXT func = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr( vk_instance, "vkCreateDebugUtilsMessengerEXT");
- if (!func) {
- PDEBUG("Failed to create vulkan debug messenger!");
- return false;
- }
- func(vk_instance, &debug_create_info, vk_allocator, &vk_debug_messenger);
+ PFN_vkCreateDebugUtilsMessengerEXT func = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(vk_instance, "vkCreateDebugUtilsMessengerEXT");
+ if (!func) {
+ PDEBUG("Failed to create vulkan debug messenger!");
+ return false;
+ }
+ func(vk_instance, &debug_create_info, vk_allocator, &vk_debug_messenger);
#endif
- return true;
+ return true;
}
-extern void
-rend_vk_quit()
+void
+rend_vk_quit(void)
{
- PDEBUG("[REND_VK14] Destroying device.");
+ PDEBUG("[REND_VK14] Destroying device.");
- /* we destroy the device on quit */
- if (vk_device.logical_device != 0) {
- rend_vk_device_destroy(&vk_device);
- }
+ /* we destroy the device on quit */
+ if (vk_device.logical_device != 0) {
+ rend_vk_device_destroy(&vk_device);
+ }
- if (vk_debug_messenger) {
- PFN_vkDestroyDebugUtilsMessengerEXT func = (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr( vk_instance, "vkDestroyDebugUtilsMessengerEXT");
- func(vk_instance, vk_debug_messenger, vk_allocator);
- vk_debug_messenger = 0;
- }
+ if (vk_debug_messenger) {
+ PFN_vkDestroyDebugUtilsMessengerEXT func = (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(vk_instance, "vkDestroyDebugUtilsMessengerEXT");
+ func(vk_instance, vk_debug_messenger, vk_allocator);
+ vk_debug_messenger = 0;
+ }
- vkDestroyInstance(vk_instance, vk_allocator);
- vk_instance = 0;
+ vkDestroyInstance(vk_instance, vk_allocator);
+ vk_instance = 0;
}
-extern RendContextHandle
+RendContextHandle
rend_vk_renderer_create(PeakWindow *window, RendBindingInfo *bind_info)
{
- RendVk14Context *ctx = rmalloc(sizeof(*ctx));
- if (!ctx) {
- PERROR("Failed to allocate internal vulkan context.");
- return NULL;
- }
+ uint32_t u;
+ uint32_t i;
+ RendVk14Context *ctx = rmalloc(sizeof(*ctx));
+ if (!ctx) {
+ PERROR("Failed to allocate internal vulkan context.");
+ return NULL;
+ }
- memset(ctx, 0, sizeof *ctx);
- ctx->window = window;
+ memset(ctx, 0, sizeof(*ctx));
+ ctx->window = window;
- /* get surface from window */
- if (!peak_vulkan_create_surface(window, vk_instance, vk_allocator, &ctx->surface)) {
- PERROR("Failed to create vulkan surface!");
- rfree(ctx);
- return NULL;
- }
+ /* get surface from window */
+ if (!peak_vulkan_create_surface(window, vk_instance, vk_allocator, &ctx->surface)) {
+ PERROR("Failed to create vulkan surface!");
+ rfree(ctx);
+ return NULL;
+ }
- RendSpecs specs = {
- .sampler_anisotropy = true,
- .graphics = true,
- .transfer = true,
- .discrete_gpu = false, // even though its not a requirement, I expect discrete gpu to be picked
- };
+ RendSpecs specs = {
+ .sampler_anisotropy = true,
+ .graphics = true,
+ .transfer = true,
+ .discrete_gpu = false, /* even though its not a requirement, I expect discrete gpu to be picked */
+ };
- /* we lazily create the logical device only after creating the first renderer
- * because we need the surface first */
- if (vk_device.logical_device == 0) {
- rend_vk_device_create(ctx->surface, specs, &vk_device, rend_vk_device_score_default);
- }
+ /* we lazily create the logical device only after creating the first renderer
+ * because we need the surface first */
+ if (vk_device.logical_device == 0) {
+ rend_vk_device_create(ctx->surface, specs, &vk_device);
+ }
- /* we must create arena before swapchain */
- ctx->arena_persistent = rend_vk_arena_create(
- vk_device.logical_device,
- vk_device.physical_device,
- vk_device.properties.limits,
- vk_allocator);
+ /* we must create arena before swapchain */
+ ctx->arena_persistent = rend_vk_arena_create(
+ vk_device.logical_device,
+ vk_device.physical_device,
+ vk_device.properties.limits,
+ vk_allocator);
- ctx->arena_frame = rend_vk_arena_create(
- vk_device.logical_device,
- vk_device.physical_device,
- vk_device.properties.limits,
- vk_allocator);
+ ctx->arena_frame = rend_vk_arena_create(
+ vk_device.logical_device,
+ vk_device.physical_device,
+ vk_device.properties.limits,
+ vk_allocator);
- /* create swapchain */
- rend_vk_swapchain_create(ctx, &ctx->swapchain);
+ /* create swapchain */
+ rend_vk_swapchain_create(ctx, &ctx->swapchain);
- /* timeline semaphore */
- VkSemaphoreTypeCreateInfo timeline_type_info = {VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO};
- timeline_type_info.semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE;
- timeline_type_info.initialValue = ctx->max_frames_in_flight;
+ /* timeline semaphore */
+ VkSemaphoreTypeCreateInfo timeline_type_info = {VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO};
+ timeline_type_info.semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE;
+ timeline_type_info.initialValue = ctx->max_frames_in_flight;
- VkSemaphoreCreateInfo timeline_semaphore_info = {VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO};
- timeline_semaphore_info.pNext = &timeline_type_info;
+ VkSemaphoreCreateInfo timeline_semaphore_info = {VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO};
+ timeline_semaphore_info.pNext = &timeline_type_info;
- if (vkCreateSemaphore(vk_device.logical_device, &timeline_semaphore_info, vk_allocator, &ctx->timeline_semaphore) != VK_SUCCESS) {
- PERROR("Unable to create the timeline semaphore for the renderer!");
- rfree(ctx);
- return NULL;
- }
+ if (vkCreateSemaphore(vk_device.logical_device, &timeline_semaphore_info, vk_allocator, &ctx->timeline_semaphore) != VK_SUCCESS) {
+ PERROR("Unable to create the timeline semaphore for the renderer!");
+ rfree(ctx);
+ return NULL;
+ }
- /* create per frame semaphores */
- VkSemaphoreCreateInfo frame_semaphore_info = {VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO};
- for (uint32_t u = 0; u < REND_MAX_FRAMES_IN_FLIGHT; ++u) {
- if (vkCreateSemaphore(
- vk_device.logical_device,
- &frame_semaphore_info,
- vk_allocator,
- &ctx->frame_resources[u].image_acquired_semaphore) != VK_SUCCESS) {
- PERROR("Unable to create semaphore for frame #%u!", u);
- rfree(ctx);
- return NULL;
- }
+ /* create per frame semaphores */
+ VkSemaphoreCreateInfo frame_semaphore_info = {VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO};
+ for (u = 0; u < REND_MAX_FRAMES_IN_FLIGHT; ++u) {
+ if (vkCreateSemaphore(
+ vk_device.logical_device,
+ &frame_semaphore_info,
+ vk_allocator,
+ &ctx->frame_resources[u].image_acquired_semaphore) != VK_SUCCESS) {
+ PERROR("Unable to create semaphore for frame #%u!", u);
+ rfree(ctx);
+ return NULL;
+ }
- if (vkCreateSemaphore(
- vk_device.logical_device,
- &frame_semaphore_info,
- vk_allocator,
- &ctx->render_complete_semaphores[u]) != VK_SUCCESS) {
- PERROR("Unable to create render complete semaphore #%u!", u);
- rfree(ctx);
- return NULL;
- }
+ if (vkCreateSemaphore(
+ vk_device.logical_device,
+ &frame_semaphore_info,
+ vk_allocator,
+ &ctx->render_complete_semaphores[u]) != VK_SUCCESS) {
+ PERROR("Unable to create render complete semaphore #%u!", u);
+ rfree(ctx);
+ return NULL;
+ }
- VkCommandPoolCreateInfo pool_info = {VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO};
- pool_info.queueFamilyIndex = vk_device.graphics_family_index;
- if (vkCreateCommandPool(vk_device.logical_device, &pool_info, vk_allocator, &ctx->frame_resources[u].command_pool) != VK_SUCCESS) {
- PERROR("Unable to create command pool for frame #%u!", u);
- rfree(ctx);
- return NULL;
- }
+ VkCommandPoolCreateInfo pool_info = {VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO};
+ pool_info.queueFamilyIndex = vk_device.graphics_family_index;
+ if (vkCreateCommandPool(vk_device.logical_device, &pool_info, vk_allocator, &ctx->frame_resources[u].command_pool) != VK_SUCCESS) {
+ PERROR("Unable to create command pool for frame #%u!", u);
+ rfree(ctx);
+ return NULL;
+ }
- VkCommandBufferAllocateInfo cmdbuf_info = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO};
- cmdbuf_info.commandPool = ctx->frame_resources[u].command_pool;
- cmdbuf_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
- cmdbuf_info.commandBufferCount = 1;
- if (vkAllocateCommandBuffers(vk_device.logical_device, &cmdbuf_info, &ctx->frame_resources[u].command_buffer) != VK_SUCCESS) {
- PERROR("Unable to create command buffer for frame #%u!", u);
- rfree(ctx);
- return NULL;
- }
+ VkCommandBufferAllocateInfo cmdbuf_info = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO};
+ cmdbuf_info.commandPool = ctx->frame_resources[u].command_pool;
+ cmdbuf_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
+ cmdbuf_info.commandBufferCount = 1;
+ if (vkAllocateCommandBuffers(vk_device.logical_device, &cmdbuf_info, &ctx->frame_resources[u].command_buffer) != VK_SUCCESS) {
+ PERROR("Unable to create command buffer for frame #%u!", u);
+ rfree(ctx);
+ return NULL;
+ }
- }
+ }
- VkCommandPoolCreateInfo pool_info = {
- .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
- .queueFamilyIndex = vk_device.transfer_family_index,
- .flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT
- };
+ VkCommandPoolCreateInfo pool_info = {
+ .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
+ .queueFamilyIndex = vk_device.transfer_family_index,
+ .flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT
+ };
- if (vkCreateCommandPool(vk_device.logical_device, &pool_info, vk_allocator, &ctx->upload_command_pool) != VK_SUCCESS) {
- PERROR("Unable to create upload command pool!");
- rfree(ctx);
- return NULL;
- }
+ if (vkCreateCommandPool(vk_device.logical_device, &pool_info, vk_allocator, &ctx->upload_command_pool) != VK_SUCCESS) {
+ PERROR("Unable to create upload command pool!");
+ rfree(ctx);
+ return NULL;
+ }
- pool_info.queueFamilyIndex = vk_device.graphics_family_index;
- if (vkCreateCommandPool(vk_device.logical_device, &pool_info, vk_allocator, &ctx->graphics_command_pool) != VK_SUCCESS) {
- PERROR("Unable to create graphics command pool!");
- rfree(ctx);
- return NULL;
- }
+ pool_info.queueFamilyIndex = vk_device.graphics_family_index;
+ if (vkCreateCommandPool(vk_device.logical_device, &pool_info, vk_allocator, &ctx->graphics_command_pool) != VK_SUCCESS) {
+ PERROR("Unable to create graphics command pool!");
+ rfree(ctx);
+ return NULL;
+ }
- ctx->frame = 0;
- ctx->frame_index = 0;
- ctx->next_signal_value = ctx->max_frames_in_flight + 1; /* start at frame zero */
+ ctx->frame = 0;
+ ctx->frame_index = 0;
+ ctx->next_signal_value = ctx->max_frames_in_flight + 1; /* start at frame zero */
- /*
- * Descriptor Pool
- */
- {
- RendBindingInfo bind_info_local = {0};
- if (bind_info) bind_info_local = *bind_info;
- RendBindingInfo bind_info = bind_info_local;
+ /*
+ * Descriptor Pool
+ */
+ {
+ RendBindingInfo bind_info_local = {0};
+ if (bind_info) bind_info_local = *bind_info;
+ RendBindingInfo bind_info = bind_info_local;
- uint32_t total_ubos = 0;
- for (uint32_t i = 0; i < bind_info.ubo_binding_count; ++i) {
- total_ubos += bind_info.ubo_array_sizes[i];
- }
+ uint32_t total_ubos = 0;
+ for (i = 0; i < bind_info.ubo_binding_count; ++i) {
+ total_ubos += bind_info.ubo_array_sizes[i];
+ }
- uint32_t total_ssbos = 0;
- for (uint32_t i = 0; i < bind_info.ssbo_binding_count; ++i) {
- total_ssbos += bind_info.ssbo_array_sizes[i];
- }
+ uint32_t total_ssbos = 0;
+ for (i = 0; i < bind_info.ssbo_binding_count; ++i) {
+ total_ssbos += bind_info.ssbo_array_sizes[i];
+ }
- uint32_t total_textures = 0;
- for (uint32_t i = 0; i < bind_info.texture_binding_count; ++i) {
- total_textures += bind_info.texture_array_sizes[i];
- }
+ uint32_t total_textures = 0;
+ for (i = 0; i < bind_info.texture_binding_count; ++i) {
+ total_textures += bind_info.texture_array_sizes[i];
+ }
- const uint32_t pool_count = 3;
- VkDescriptorPoolSize pool_sizes[3] = {
- { .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, .descriptorCount = (total_ubos > 0) ? total_ubos : 1 },
- { .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, .descriptorCount = (total_ssbos > 0) ? total_ssbos : 1 },
- { .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, .descriptorCount = (total_textures > 0) ? total_textures : 1 }
- };
+ const uint32_t pool_count = 3;
+ VkDescriptorPoolSize pool_sizes[3] = {
+ { .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, .descriptorCount = (total_ubos > 0) ? total_ubos : 1 },
+ { .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, .descriptorCount = (total_ssbos > 0) ? total_ssbos : 1 },
+ { .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, .descriptorCount = (total_textures > 0) ? total_textures : 1 }
+ };
- VkDescriptorPoolCreateInfo pool_info = {
- .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
- .flags = 0,
- .maxSets = 1,
- .poolSizeCount = pool_count,
- .pPoolSizes = pool_sizes,
- .pNext = NULL,
- };
+ VkDescriptorPoolCreateInfo pool_info = {
+ .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
+ .flags = 0,
+ .maxSets = 1,
+ .poolSizeCount = pool_count,
+ .pPoolSizes = pool_sizes,
+ .pNext = NULL,
+ };
- VkResult result = vkCreateDescriptorPool(vk_device.logical_device, &pool_info, vk_allocator, &ctx->descriptor_pool);
- if (result != VK_SUCCESS) {
- rfree(ctx);
- return NULL;
- }
+ VkResult result = vkCreateDescriptorPool(vk_device.logical_device, &pool_info, vk_allocator, &ctx->descriptor_pool);
+ if (result != VK_SUCCESS) {
+ rfree(ctx);
+ return NULL;
+ }
- /*
- * Descriptor Sets!!!!!!
- */
+ /*
+ * Descriptor Sets!!!!!!
+ */
- const uint32_t binding_count = bind_info.ubo_binding_count + bind_info.ssbo_binding_count + bind_info.texture_binding_count;
- VkDescriptorSetLayoutBinding binding_array[binding_count];
+ const uint32_t binding_count = bind_info.ubo_binding_count + bind_info.ssbo_binding_count + bind_info.texture_binding_count;
+ VkDescriptorSetLayoutBinding binding_array[binding_count];
- for (uint32_t i = 0; i < bind_info.ubo_binding_count; ++i) {
- binding_array[i] = (VkDescriptorSetLayoutBinding) {
- .binding = bind_info.ubo_bindings[i],
- .descriptorCount = bind_info.ubo_array_sizes[i],
- .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
- .stageFlags = VK_SHADER_STAGE_ALL,
- .pImmutableSamplers = 0,
- };
- };
+ for (i = 0; i < bind_info.ubo_binding_count; ++i) {
+ binding_array[i] = (VkDescriptorSetLayoutBinding) {
+ .binding = bind_info.ubo_bindings[i],
+ .descriptorCount = bind_info.ubo_array_sizes[i],
+ .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+ .stageFlags = VK_SHADER_STAGE_ALL,
+ .pImmutableSamplers = 0,
+ };
+ };
- uint32_t offset = bind_info.ubo_binding_count;
- for (uint32_t i = 0; i < bind_info.ssbo_binding_count; ++i) {
- binding_array[i + offset] = (VkDescriptorSetLayoutBinding) {
- .binding = bind_info.ssbo_bindings[i],
- .descriptorCount = bind_info.ssbo_array_sizes[i],
- .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
- .stageFlags = VK_SHADER_STAGE_ALL,
- .pImmutableSamplers = 0,
- };
- };
+ uint32_t offset = bind_info.ubo_binding_count;
+ for (i = 0; i < bind_info.ssbo_binding_count; ++i) {
+ binding_array[i + offset] = (VkDescriptorSetLayoutBinding) {
+ .binding = bind_info.ssbo_bindings[i],
+ .descriptorCount = bind_info.ssbo_array_sizes[i],
+ .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+ .stageFlags = VK_SHADER_STAGE_ALL,
+ .pImmutableSamplers = 0,
+ };
+ };
- offset += bind_info.ssbo_binding_count;
- for (uint32_t i = 0; i < bind_info.texture_binding_count; ++i) {
- binding_array[i + offset] = (VkDescriptorSetLayoutBinding) {
- .binding = bind_info.texture_bindings[i],
- .descriptorCount = bind_info.texture_array_sizes[i],
- .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
- .stageFlags = VK_SHADER_STAGE_ALL,
- .pImmutableSamplers = 0,
- };
- };
+ offset += bind_info.ssbo_binding_count;
+ for (i = 0; i < bind_info.texture_binding_count; ++i) {
+ binding_array[i + offset] = (VkDescriptorSetLayoutBinding) {
+ .binding = bind_info.texture_bindings[i],
+ .descriptorCount = bind_info.texture_array_sizes[i],
+ .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
+ .stageFlags = VK_SHADER_STAGE_ALL,
+ .pImmutableSamplers = 0,
+ };
+ };
- VkDescriptorBindingFlags binding_flags[binding_count];
- for (uint32_t u = 0; u < binding_count; ++u) {
- binding_flags[u] = VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT;
- }
+ VkDescriptorBindingFlags binding_flags[binding_count];
+ for (u = 0; u < binding_count; ++u) {
+ binding_flags[u] = VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT;
+ }
- VkDescriptorSetLayoutBindingFlagsCreateInfo desc_flags_info = {
- .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO,
- .bindingCount = binding_count,
- .pBindingFlags = binding_flags
- };
+ VkDescriptorSetLayoutBindingFlagsCreateInfo desc_flags_info = {
+ .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO,
+ .bindingCount = binding_count,
+ .pBindingFlags = binding_flags
+ };
- VkDescriptorSetLayoutCreateInfo desc_layout_info = {
- .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
- .flags = 0,
- .bindingCount = binding_count,
- .pBindings = binding_array,
- .pNext = &desc_flags_info,
- };
+ VkDescriptorSetLayoutCreateInfo desc_layout_info = {
+ .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
+ .flags = 0,
+ .bindingCount = binding_count,
+ .pBindings = binding_array,
+ .pNext = &desc_flags_info,
+ };
- result = vkCreateDescriptorSetLayout(vk_device.logical_device, &desc_layout_info, vk_allocator, &ctx->desc_layout);
- if (result != VK_SUCCESS) {
- PERROR("Failed to create descriptor set layout!");
- rfree(ctx);
- return NULL;
- }
+ result = vkCreateDescriptorSetLayout(vk_device.logical_device, &desc_layout_info, vk_allocator, &ctx->desc_layout);
+ if (result != VK_SUCCESS) {
+ PERROR("Failed to create descriptor set layout!");
+ rfree(ctx);
+ return NULL;
+ }
- VkDescriptorSetAllocateInfo alloc_info = {
- .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
- .descriptorPool = ctx->descriptor_pool,
- .descriptorSetCount = 1, // ONLY ONE DESCRIPTOR SET
- .pSetLayouts = &ctx->desc_layout,
- .pNext = NULL,
- };
+ VkDescriptorSetAllocateInfo alloc_info = {
+ .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
+ .descriptorPool = ctx->descriptor_pool,
+ .descriptorSetCount = 1, /* ONLY ONE DESCRIPTOR SET */
+ .pSetLayouts = &ctx->desc_layout,
+ .pNext = NULL,
+ };
- result = vkAllocateDescriptorSets(vk_device.logical_device, &alloc_info, &ctx->desc_set);
- if (result != VK_SUCCESS) {
- PERROR("Failed to allocate descriptors!!!");
- rfree(ctx);
- return NULL;
- }
- }
+ result = vkAllocateDescriptorSets(vk_device.logical_device, &alloc_info, &ctx->desc_set);
+ if (result != VK_SUCCESS) {
+ PERROR("Failed to allocate descriptors!!!");
+ rfree(ctx);
+ return NULL;
+ }
+ }
- return ctx;
+ return ctx;
}
-extern void
+void
rend_vk_renderer_destroy(RendContextHandle handle)
{
- RASSERT(handle, "Invalid context handle.");
+ uint32_t u;
+ RASSERT(handle, "Invalid context handle.");
- RendVk14Context *ctx = (RendVk14Context *)handle;
+ RendVk14Context *ctx = (RendVk14Context *)handle;
- VkDevice dev = vk_device.logical_device;
+ VkDevice dev = vk_device.logical_device;
- PDEBUG("[REND] Waiting for device...");
- vkDeviceWaitIdle(dev);
+ PDEBUG("[REND] Waiting for device...");
+ vkDeviceWaitIdle(dev);
- PDEBUG("[REND] Destroying renderer...");
- vkDestroySemaphore(dev, ctx->timeline_semaphore, vk_allocator);
+ PDEBUG("[REND] Destroying renderer...");
+ vkDestroySemaphore(dev, ctx->timeline_semaphore, vk_allocator);
- /* destroy per frame semaphores */
- for (uint32_t u = 0; u < REND_MAX_FRAMES_IN_FLIGHT; ++u) {
- vkDestroySemaphore(dev, ctx->frame_resources[u].image_acquired_semaphore, vk_allocator);
- vkDestroySemaphore(dev, ctx->render_complete_semaphores[u], vk_allocator);
- vkDestroyCommandPool(dev, ctx->frame_resources[u].command_pool, vk_allocator);
- ctx->frame_resources[u].image_acquired_semaphore = 0;
- ctx->frame_resources[u].command_pool = 0;
- ctx->frame_resources[u].command_buffer = 0;
- }
+ /* destroy per frame semaphores */
+ for (u = 0; u < REND_MAX_FRAMES_IN_FLIGHT; ++u) {
+ vkDestroySemaphore(dev, ctx->frame_resources[u].image_acquired_semaphore, vk_allocator);
+ vkDestroySemaphore(dev, ctx->render_complete_semaphores[u], vk_allocator);
+ vkDestroyCommandPool(dev, ctx->frame_resources[u].command_pool, vk_allocator);
+ ctx->frame_resources[u].image_acquired_semaphore = 0;
+ ctx->frame_resources[u].command_pool = 0;
+ ctx->frame_resources[u].command_buffer = 0;
+ }
- vkDestroyCommandPool(vk_device.logical_device, ctx->upload_command_pool, vk_allocator);
- vkDestroyCommandPool(vk_device.logical_device, ctx->graphics_command_pool, vk_allocator);
+ vkDestroyCommandPool(vk_device.logical_device, ctx->upload_command_pool, vk_allocator);
+ vkDestroyCommandPool(vk_device.logical_device, ctx->graphics_command_pool, vk_allocator);
- rend_vk_arena_destroy(&ctx->arena_persistent);
- rend_vk_arena_destroy(&ctx->arena_frame);
+ rend_vk_arena_destroy(&ctx->arena_persistent);
+ rend_vk_arena_destroy(&ctx->arena_frame);
- vkDestroyDescriptorSetLayout(dev, ctx->desc_layout, vk_allocator);
- vkDestroyDescriptorPool(dev, ctx->descriptor_pool, vk_allocator);
+ vkDestroyDescriptorSetLayout(dev, ctx->desc_layout, vk_allocator);
+ vkDestroyDescriptorPool(dev, ctx->descriptor_pool, vk_allocator);
- PDEBUG("[REND] Destroying pipelines...");
- for (uint32_t u = 0; u < ctx->pipeline_count; ++u) {
- rend_vk_pipeline_destroy(&ctx->pipelines[u]);
- }
+ PDEBUG("[REND] Destroying pipelines...");
+ for (u = 0; u < ctx->pipeline_count; ++u) {
+ rend_vk_pipeline_destroy(&ctx->pipelines[u]);
+ }
- PDEBUG("[REND] Destroying swapchain...");
- rend_vk_swapchain_destroy(ctx, &ctx->swapchain);
- ctx->swapchain.handle = 0;
+ PDEBUG("[REND] Destroying swapchain...");
+ rend_vk_swapchain_destroy(ctx, &ctx->swapchain);
+ ctx->swapchain.handle = 0;
- PDEBUG("[REND] Destroying surface...");
- RASSERT(vk_instance);
- vkDestroySurfaceKHR(vk_instance, ctx->surface, vk_allocator);
- ctx->surface = 0;
+ PDEBUG("[REND] Destroying surface...");
+ RASSERT(vk_instance);
+ vkDestroySurfaceKHR(vk_instance, ctx->surface, vk_allocator);
+ ctx->surface = 0;
- /* handle is guarranteed to be allocated */
- rfree(handle);
+ /* handle is guarranteed to be allocated */
+ rfree(handle);
}
-extern bool
+bool
rend_vk_renderer_frame_begin(RendContextHandle handle)
{
- RendVk14Context *ctx;
- VkDevice dev;
- uint32_t retries;
+ RendVk14Context *ctx;
+ VkDevice dev;
+ uint32_t retries;
- RASSERT(handle, "Invalid handle.");
+ RASSERT(handle, "Invalid handle.");
- ctx = (RendVk14Context *) handle;
- dev = vk_device.logical_device;
+ ctx = (RendVk14Context *)handle;
+ dev = vk_device.logical_device;
- for (retries = 0; retries < 4; retries++) {
- uint64_t frame_res_index;
- uint64_t wait_value;
- VkResult acquire_image;
- RendVkFrameResources frame_resource;
- VkSemaphoreWaitInfo timeline_wait_info;
+ for (retries = 0; retries < 4; retries++) {
+ uint64_t frame_res_index;
+ uint64_t wait_value;
+ VkResult acquire_image;
+ RendVkFrameResources frame_resource;
+ VkSemaphoreWaitInfo timeline_wait_info;
- if (ctx->require_swapchain_recreation) {
- if (ctx->window && (ctx->window->width == 0 || ctx->window->height == 0))
- return false;
- PDEBUG("[REND] Awaiting device...");
- vkDeviceWaitIdle(vk_device.logical_device);
- PDEBUG("[REND] Recreating swapchain...");
- rend_vk_swapchain_destroy(ctx, &ctx->swapchain);
- rend_vk_swapchain_create(ctx, &ctx->swapchain);
- ctx->require_swapchain_recreation = false;
- }
+ if (ctx->require_swapchain_recreation) {
+ if (ctx->window && (ctx->window->width == 0 || ctx->window->height == 0))
+ return false;
+ PDEBUG("[REND] Awaiting device...");
+ vkDeviceWaitIdle(vk_device.logical_device);
+ PDEBUG("[REND] Recreating swapchain...");
+ rend_vk_swapchain_destroy(ctx, &ctx->swapchain);
+ rend_vk_swapchain_create(ctx, &ctx->swapchain);
+ ctx->require_swapchain_recreation = false;
+ }
- if (ctx->max_frames_in_flight == 0)
- return false;
+ if (ctx->max_frames_in_flight == 0)
+ return false;
- /* wait on timeline semaphore */
- frame_res_index = ctx->frame % ctx->max_frames_in_flight;
- ctx->frame_index = frame_res_index;
+ /* wait on timeline semaphore */
+ frame_res_index = ctx->frame % ctx->max_frames_in_flight;
+ ctx->frame_index = frame_res_index;
- wait_value = ctx->next_signal_value - ctx->max_frames_in_flight;
+ wait_value = ctx->next_signal_value - ctx->max_frames_in_flight;
- timeline_wait_info = (VkSemaphoreWaitInfo) {
- .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
- .semaphoreCount = 1,
- .pSemaphores = &ctx->timeline_semaphore,
- .pValues = &wait_value
- };
+ timeline_wait_info = (VkSemaphoreWaitInfo) {
+ .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
+ .semaphoreCount = 1,
+ .pSemaphores = &ctx->timeline_semaphore,
+ .pValues = &wait_value
+ };
- vkWaitSemaphores(vk_device.logical_device, &timeline_wait_info, UINT64_MAX);
+ vkWaitSemaphores(vk_device.logical_device, &timeline_wait_info, UINT64_MAX);
- frame_resource = ctx->frame_resources[frame_res_index];
- vkResetCommandPool(dev, frame_resource.command_pool, 0);
+ frame_resource = ctx->frame_resources[frame_res_index];
+ vkResetCommandPool(dev, frame_resource.command_pool, 0);
- /* acquire next image */
- acquire_image = vkAcquireNextImageKHR(
- vk_device.logical_device,
- ctx->swapchain.handle,
- UINT64_MAX,
- frame_resource.image_acquired_semaphore,
- VK_NULL_HANDLE,
- &ctx->image_index);
+ /* acquire next image */
+ acquire_image = vkAcquireNextImageKHR(
+ vk_device.logical_device,
+ ctx->swapchain.handle,
+ UINT64_MAX,
+ frame_resource.image_acquired_semaphore,
+ VK_NULL_HANDLE,
+ &ctx->image_index);
- if (acquire_image == VK_ERROR_OUT_OF_DATE_KHR) {
- ctx->require_swapchain_recreation = true;
- continue;
- }
- if (acquire_image == VK_SUBOPTIMAL_KHR) {
- ctx->require_swapchain_recreation = true;
- } else if (acquire_image != VK_SUCCESS) {
- return false;
- }
+ if (acquire_image == VK_ERROR_OUT_OF_DATE_KHR) {
+ ctx->require_swapchain_recreation = true;
+ continue;
+ }
+ if (acquire_image == VK_SUBOPTIMAL_KHR) {
+ ctx->require_swapchain_recreation = true;
+ } else if (acquire_image != VK_SUCCESS) {
+ return false;
+ }
- ctx->signal_value = ctx->next_signal_value++;
+ ctx->signal_value = ctx->next_signal_value++;
- {
- VkCommandBufferBeginInfo cmd_begin_info = {
- .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
- .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT
- };
+ {
+ VkCommandBufferBeginInfo cmd_begin_info = {
+ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
+ .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT
+ };
- vkBeginCommandBuffer(frame_resource.command_buffer, &cmd_begin_info);
+ vkBeginCommandBuffer(frame_resource.command_buffer, &cmd_begin_info);
- static const size_t NUM_LAYOUT_BARRIERS = 2;
- VkImageMemoryBarrier2 layout_barriers[NUM_LAYOUT_BARRIERS];
- layout_barriers[0] = (VkImageMemoryBarrier2) {
- .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
+ static const size_t NUM_LAYOUT_BARRIERS = 2;
+ VkImageMemoryBarrier2 layout_barriers[NUM_LAYOUT_BARRIERS];
+ layout_barriers[0] = (VkImageMemoryBarrier2) {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
- .srcStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT,
- .srcAccessMask = 0,
+ .srcStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT,
+ .srcAccessMask = 0,
- .dstStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT,
- .dstAccessMask = VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT_KHR,
+ .dstStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT,
+ .dstAccessMask = VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT_KHR,
- .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
- .newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+ .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
+ .newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
- .image = ctx->swapchain.images[ctx->image_index],
+ .image = ctx->swapchain.images[ctx->image_index],
- .subresourceRange = (VkImageSubresourceRange) {
- .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
- .baseMipLevel = 0,
- .levelCount = 1,
- .baseArrayLayer = 0,
- .layerCount = 1
- },
+ .subresourceRange = (VkImageSubresourceRange) {
+ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+ .baseMipLevel = 0,
+ .levelCount = 1,
+ .baseArrayLayer = 0,
+ .layerCount = 1
+ },
- // .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
- // .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
- };
- layout_barriers[1] = (VkImageMemoryBarrier2) {
- .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
+ /* .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, */
+ /* .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, */
+ };
+ layout_barriers[1] = (VkImageMemoryBarrier2) {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
- .srcStageMask = VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT,
- .srcAccessMask = 0,
+ .srcStageMask = VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT,
+ .srcAccessMask = 0,
- .dstStageMask = VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT,
- .dstAccessMask = VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
+ .dstStageMask = VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT,
+ .dstAccessMask = VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
- .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
- .newLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL,
+ .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
+ .newLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL,
- .image = ctx->swapchain.depth_attachment.handle,
+ .image = ctx->swapchain.depth_attachment.handle,
- .subresourceRange = (VkImageSubresourceRange) {
- .aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT,
- .baseMipLevel = 0,
- .levelCount = 1,
- .baseArrayLayer = 0,
- .layerCount = 1
- },
- };
+ .subresourceRange = (VkImageSubresourceRange) {
+ .aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT,
+ .baseMipLevel = 0,
+ .levelCount = 1,
+ .baseArrayLayer = 0,
+ .layerCount = 1
+ },
+ };
- VkMemoryBarrier2 memory_barrier = {
- .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
- .srcStageMask = VK_PIPELINE_STAGE_2_HOST_BIT,
- .srcAccessMask = VK_ACCESS_2_HOST_WRITE_BIT,
- .dstStageMask = VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT,
- .dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT,
- };
+ VkMemoryBarrier2 memory_barrier = {
+ .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
+ .srcStageMask = VK_PIPELINE_STAGE_2_HOST_BIT,
+ .srcAccessMask = VK_ACCESS_2_HOST_WRITE_BIT,
+ .dstStageMask = VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT,
+ .dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT,
+ };
- VkDependencyInfo dep_info = {VK_STRUCTURE_TYPE_DEPENDENCY_INFO};
- dep_info.memoryBarrierCount = 1;
- dep_info.pMemoryBarriers = &memory_barrier;
- dep_info.imageMemoryBarrierCount = (uint32_t) NUM_LAYOUT_BARRIERS;
- dep_info.pImageMemoryBarriers = layout_barriers;
+ VkDependencyInfo dep_info = {VK_STRUCTURE_TYPE_DEPENDENCY_INFO};
+ dep_info.memoryBarrierCount = 1;
+ dep_info.pMemoryBarriers = &memory_barrier;
+ dep_info.imageMemoryBarrierCount = (uint32_t) NUM_LAYOUT_BARRIERS;
+ dep_info.pImageMemoryBarriers = layout_barriers;
- vkCmdPipelineBarrier2(frame_resource.command_buffer, &dep_info);
- }
+ vkCmdPipelineBarrier2(frame_resource.command_buffer, &dep_info);
+ }
- ctx->in_frame = true;
- return true;
- }
+ ctx->in_frame = true;
+ return true;
+ }
- return false;
+ return false;
}
-extern void
+void
rend_vk_renderer_frame_end(RendContextHandle handle, float *delta)
{
- RendVk14Context *ctx = (RendVk14Context *)handle;
- RASSERT(ctx, "Uninitialized renderer.");
+ RendVk14Context *ctx = (RendVk14Context *)handle;
+ RASSERT(ctx, "Uninitialized renderer.");
- RendVkFrameResources res = ctx->frame_resources[ctx->frame_index];
+ RendVkFrameResources res = ctx->frame_resources[ctx->frame_index];
- VkImageMemoryBarrier2 present_barrier;
- present_barrier = (VkImageMemoryBarrier2) {
- .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
+ VkImageMemoryBarrier2 present_barrier;
+ present_barrier = (VkImageMemoryBarrier2) {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
- .srcStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT,
- .srcAccessMask = VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT,
+ .srcStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT,
+ .srcAccessMask = VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT,
- .dstStageMask = VK_PIPELINE_STAGE_2_NONE,
- .dstAccessMask = 0,
+ .dstStageMask = VK_PIPELINE_STAGE_2_NONE,
+ .dstAccessMask = 0,
- .oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
- .newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
+ .oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+ .newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
- .image = ctx->swapchain.images[ctx->image_index],
+ .image = ctx->swapchain.images[ctx->image_index],
- .subresourceRange = (VkImageSubresourceRange) {
- .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
- .baseMipLevel = 0,
- .levelCount = 1,
- .baseArrayLayer = 0,
- .layerCount = 1
- }
+ .subresourceRange = (VkImageSubresourceRange) {
+ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+ .baseMipLevel = 0,
+ .levelCount = 1,
+ .baseArrayLayer = 0,
+ .layerCount = 1
+ }
- };
+ };
- VkDependencyInfo dep_info = {VK_STRUCTURE_TYPE_DEPENDENCY_INFO};
- dep_info.imageMemoryBarrierCount = 1;
- dep_info.pImageMemoryBarriers = &present_barrier;
+ VkDependencyInfo dep_info = {VK_STRUCTURE_TYPE_DEPENDENCY_INFO};
+ dep_info.imageMemoryBarrierCount = 1;
+ dep_info.pImageMemoryBarriers = &present_barrier;
- vkCmdPipelineBarrier2(res.command_buffer, &dep_info);
- vkEndCommandBuffer(res.command_buffer);
+ vkCmdPipelineBarrier2(res.command_buffer, &dep_info);
+ vkEndCommandBuffer(res.command_buffer);
- /* ensure swapchain image is available */
- VkSemaphoreSubmitInfo image_acquire_await_info = {
- .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
- .semaphore = res.image_acquired_semaphore,
- .stageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT
- };
+ /* ensure swapchain image is available */
+ VkSemaphoreSubmitInfo image_acquire_await_info = {
+ .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
+ .semaphore = res.image_acquired_semaphore,
+ .stageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT
+ };
- /* signal that the image is presented */
- VkSemaphoreSubmitInfo semaphore_signals[2] = {
- [0] = {
- .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
- .semaphore = ctx->render_complete_semaphores[ctx->image_index],
- .stageMask = VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT
- },
- [1] = {
- .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
- .semaphore = ctx->timeline_semaphore,
- .value = ctx->signal_value,
- .stageMask = VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT
- },
- };
+ /* signal that the image is presented */
+ VkSemaphoreSubmitInfo semaphore_signals[2] = {
+ [0] = {
+ .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
+ .semaphore = ctx->render_complete_semaphores[ctx->image_index],
+ .stageMask = VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT
+ },
+ [1] = {
+ .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
+ .semaphore = ctx->timeline_semaphore,
+ .value = ctx->signal_value,
+ .stageMask = VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT
+ },
+ };
- VkCommandBufferSubmitInfo cmd_submit_info = {
- .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO,
- .commandBuffer = res.command_buffer,
- };
+ VkCommandBufferSubmitInfo cmd_submit_info = {
+ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO,
+ .commandBuffer = res.command_buffer,
+ };
- VkSubmitInfo2 submit_info = {
- .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO_2,
- .waitSemaphoreInfoCount = 1,
- .pWaitSemaphoreInfos = &image_acquire_await_info,
- .commandBufferInfoCount = 1,
- .pCommandBufferInfos = &cmd_submit_info,
- .signalSemaphoreInfoCount = 2,
- .pSignalSemaphoreInfos = semaphore_signals
- };
+ VkSubmitInfo2 submit_info = {
+ .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO_2,
+ .waitSemaphoreInfoCount = 1,
+ .pWaitSemaphoreInfos = &image_acquire_await_info,
+ .commandBufferInfoCount = 1,
+ .pCommandBufferInfos = &cmd_submit_info,
+ .signalSemaphoreInfoCount = 2,
+ .pSignalSemaphoreInfos = semaphore_signals
+ };
- vkQueueSubmit2(vk_device.graphics_queue, 1, &submit_info, VK_NULL_HANDLE);
+ vkQueueSubmit2(vk_device.graphics_queue, 1, &submit_info, VK_NULL_HANDLE);
- VkPresentInfoKHR present_info = {
- .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
- .waitSemaphoreCount = 1,
- .pWaitSemaphores = &ctx->render_complete_semaphores[ctx->image_index],
- .swapchainCount = 1,
- .pSwapchains = &ctx->swapchain.handle,
- .pImageIndices = &ctx->image_index,
- .pResults = NULL,
- };
+ VkPresentInfoKHR present_info = {
+ .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
+ .waitSemaphoreCount = 1,
+ .pWaitSemaphores = &ctx->render_complete_semaphores[ctx->image_index],
+ .swapchainCount = 1,
+ .pSwapchains = &ctx->swapchain.handle,
+ .pImageIndices = &ctx->image_index,
+ .pResults = NULL,
+ };
- vkQueuePresentKHR(vk_device.graphics_queue, &present_info);
+ vkQueuePresentKHR(vk_device.graphics_queue, &present_info);
- ctx->frame++;
- ctx->in_frame = false;
- uint64_t f = ctx->frame_index;
+ ctx->frame++;
+ ctx->in_frame = false;
- /* clear host mapped memory */
- rend_vk_arena_clear_all(&ctx->arena_frame);
- rend_vk_arena_clear(&ctx->arena_persistent, vk_device.host_index);
+ /* clear host mapped memory */
+ rend_vk_arena_clear_all(&ctx->arena_frame);
+ rend_vk_arena_clear(&ctx->arena_persistent, vk_device.host_index);
}
static inline void
-rend_vk__renderer_render_pass_begin_internal(RendRenderer renderer, float r, float g, float b, float a, uint64_t view_handle, uint64_t depth_attachment_view_handle, uint32_t offset_x, uint32_t offset_y, uint32_t width, uint32_t height)
+rend_vk__renderer_render_pass_begin_internal(RendContextHandle handle, float r, float g, float b, float a, uint64_t view_handle, uint64_t depth_attachment_view_handle, uint32_t offset_x, uint32_t offset_y, uint32_t width, uint32_t height, VkAttachmentLoadOp color_load)
{
- RendVk14Context *ctx = (RendVk14Context*) renderer->context;
- RASSERT(ctx->in_frame && "must begin render pass inside a frame");
+ RendVk14Context *ctx = (RendVk14Context *)handle;
+ RASSERT(ctx->in_frame && "must begin render pass inside a frame");
- RendVkFrameResources frame_resource = ctx->frame_resources[ctx->frame_index];
+ RendVkFrameResources frame_resource = ctx->frame_resources[ctx->frame_index];
- VkRenderingAttachmentInfo color_attachment = {
- .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
- .imageView = (VkImageView) view_handle,
- .imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
- .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, // clear image
- .storeOp = VK_ATTACHMENT_STORE_OP_STORE, // store for presentation
- .clearValue = (VkClearValue) {
- .color = {r, g, b, a},
- }
- };
-
- VkRenderingAttachmentInfo depth_attachment = {
- .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
- .imageView = (VkImageView) depth_attachment_view_handle,
- .imageLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL,
- .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, // clear depth data
- .storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE, // don't care after rendering
- .clearValue = (VkClearValue) {
- .depthStencil = (VkClearDepthStencilValue) {1.0f, 0},
- },
- };
+ VkRenderingAttachmentInfo color_attachment = {
+ .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
+ .imageView = (VkImageView)view_handle,
+ .imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+ .loadOp = color_load,
+ .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
+ .clearValue = {
+ .color = {{r, g, b, a}},
+ }
+ };
- VkRenderingInfo rendering_info = {
- .sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
- .renderArea.offset = (VkOffset2D) {offset_x, offset_y},
- .renderArea.extent = (VkExtent2D) {width, height},
- .layerCount = 1,
- .colorAttachmentCount = 1,
- .pColorAttachments = &color_attachment,
- .pDepthAttachment = &depth_attachment,
- };
+ VkRenderingAttachmentInfo depth_attachment = {
+ .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
+ .imageView = (VkImageView)depth_attachment_view_handle,
+ .imageLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL,
+ .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, /* clear depth data */
+ .storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE, /* don't care after rendering */
+ .clearValue = (VkClearValue) {
+ .depthStencil = (VkClearDepthStencilValue) {1.0f, 0},
+ },
+ };
- vkCmdBeginRendering(frame_resource.command_buffer, &rendering_info);
+ VkRenderingInfo rendering_info = {
+ .sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
+ .renderArea.offset = (VkOffset2D) {offset_x, offset_y},
+ .renderArea.extent = (VkExtent2D) {width, height},
+ .layerCount = 1,
+ .colorAttachmentCount = 1,
+ .pColorAttachments = &color_attachment,
+ .pDepthAttachment = &depth_attachment,
+ };
- VkViewport viewport = {
- .x = offset_x,
- .y = offset_y,
- .width = width,
- .height = height,
- .minDepth = 0.0f,
- .maxDepth = 1.0f
- };
+ vkCmdBeginRendering(frame_resource.command_buffer, &rendering_info);
- vkCmdSetViewport(frame_resource.command_buffer, 0, 1, &viewport);
+ VkViewport viewport = {
+ .x = offset_x,
+ .y = offset_y,
+ .width = width,
+ .height = height,
+ .minDepth = 0.0f,
+ .maxDepth = 1.0f
+ };
- VkRect2D scissor = {{offset_x, offset_y}, {width, height}};
- vkCmdSetScissor(frame_resource.command_buffer, 0, 1, &scissor);
+ vkCmdSetViewport(frame_resource.command_buffer, 0, 1, &viewport);
+
+ VkRect2D scissor = {{offset_x, offset_y}, {width, height}};
+ vkCmdSetScissor(frame_resource.command_buffer, 0, 1, &scissor);
}
-extern void
-rend_vk_renderer_render_pass_begin(RendRenderer renderer, float r, float g, float b, float a)
+void
+rend_vk_renderer_render_pass_begin(RendContextHandle handle, float r, float g, float b, float a)
{
-
- RendVk14Context *ctx = (RendVk14Context*) renderer->context;
+ RendVk14Context *ctx = (RendVk14Context *)handle;
- rend_vk__renderer_render_pass_begin_internal(
- renderer,
- r, g, b, a,
- (uint64_t) ctx->swapchain.views[ctx->image_index],
- (uint64_t) ctx->swapchain.depth_attachment.view,
- 0, 0,
- ctx->swapchain.extent.width, ctx->swapchain.extent.height
- );
+ rend_vk__renderer_render_pass_begin_internal(
+ handle,
+ r, g, b, a,
+ (uint64_t) ctx->swapchain.views[ctx->image_index],
+ (uint64_t) ctx->swapchain.depth_attachment.view,
+ 0, 0,
+ ctx->swapchain.extent.width, ctx->swapchain.extent.height,
+ VK_ATTACHMENT_LOAD_OP_CLEAR
+ );
}
-extern void
-rend_vk_renderer_render_pass_begin_texture(RendRenderer renderer, RendTexture *texture)
+void
+rend_vk_renderer_render_pass_begin_texture(RendContextHandle handle, RendTexture *texture)
{
-
- RendVk14Context *ctx = (RendVk14Context*) renderer->context;
-
- RendVkFrameResources frame_resource = ctx->frame_resources[ctx->frame_index];
+ RendVk14Context *ctx = (RendVk14Context *)handle;
- rend_vk_texture_transition_layout(renderer, ctx->frame_resources[ctx->frame_index].command_buffer, texture, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
-
- VkRenderingAttachmentInfo color_attachment = {
- .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
- .imageView = (VkImageView) texture->view,
- .imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
- .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD, // load image instead of clearing
- .storeOp = VK_ATTACHMENT_STORE_OP_STORE, // store for presentation
- };
-
- VkRenderingAttachmentInfo depth_attachment = {
- .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
- .imageView = (VkImageView) ctx->swapchain.depth_attachment.view,
- .imageLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL,
- .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, // clear depth data
- .storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE, // don't care after rendering
- .clearValue = (VkClearValue) {
- .depthStencil = (VkClearDepthStencilValue) {1.0f, 0},
- },
- };
-
- VkRenderingInfo rendering_info = {
- .sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
- .renderArea.offset = (VkOffset2D) {0, 0},
- .renderArea.extent = (VkExtent2D) {texture->width, texture->height},
- .layerCount = 1,
- .colorAttachmentCount = 1,
- .pColorAttachments = &color_attachment,
- .pDepthAttachment = &depth_attachment,
- };
-
- vkCmdBeginRendering(frame_resource.command_buffer, &rendering_info);
-
- VkViewport viewport = {
- .x = 0,
- .y = 0,
- .width = texture->width,
- .height = texture->height,
- .minDepth = 0.0f,
- .maxDepth = 1.0f
- };
-
- vkCmdSetViewport(frame_resource.command_buffer, 0, 1, &viewport);
-
- VkRect2D scissor = {{0, 0}, {texture->width, texture->height}};
- vkCmdSetScissor(frame_resource.command_buffer, 0, 1, &scissor);
+ rend_vk_texture_transition_layout(handle, ctx->frame_resources[ctx->frame_index].command_buffer, texture, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
+ rend_vk__renderer_render_pass_begin_internal(
+ handle,
+ 0, 0, 0, 0,
+ (uint64_t)texture->view,
+ (uint64_t)ctx->swapchain.depth_attachment.view,
+ 0, 0,
+ texture->width, texture->height,
+ VK_ATTACHMENT_LOAD_OP_LOAD
+ );
}
-extern void
-rend_vk_renderer_render_pass_end_texture(RendRenderer renderer, RendTexture *texture)
+void
+rend_vk_renderer_render_pass_end(RendContextHandle handle)
{
-
- RendVk14Context *ctx = (RendVk14Context*) renderer->context;
- rend_vk_texture_transition_layout(renderer, ctx->frame_resources[ctx->frame_index].command_buffer, texture, VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL);
- rend_vk_renderer_render_pass_end(renderer);
+ RendVk14Context *ctx = (RendVk14Context *)handle;
+ RASSERT(ctx->in_frame && "must end render pass inside a frame");
+ RendVkFrameResources res = ctx->frame_resources[ctx->frame_index];
+ vkCmdEndRendering(res.command_buffer);
}
-
-extern void
-rend_vk_renderer_render_pass_end(RendRenderer renderer)
+void
+rend_vk_renderer_render_pass_end_texture(RendContextHandle handle, RendTexture *texture)
{
- RendVk14Context *ctx = (RendVk14Context*) renderer->context;
- RASSERT(ctx->in_frame && "must end render pass inside a frame");
- RendVkFrameResources res = ctx->frame_resources[ctx->frame_index];
- vkCmdEndRendering(res.command_buffer);
+ RendVk14Context *ctx = (RendVk14Context *)handle;
+ rend_vk_texture_transition_layout(handle, ctx->frame_resources[ctx->frame_index].command_buffer, texture, VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL);
+ rend_vk_renderer_render_pass_end(handle);
}
-extern void
-rend_vk_descriptor_write_buffer(RendRenderer renderer, RendBuffer ubo, uint32_t binding, uint32_t slot, uint32_t offset, uint32_t size, bool is_ubo)
+void
+rend_vk_descriptor_write_buffer(RendContextHandle handle, RendBuffer ubo, uint32_t binding, uint32_t slot, uint32_t offset, uint32_t size, bool is_ubo)
{
- RendVk14Context *ctx = renderer->context;
+ RendVk14Context *ctx = (RendVk14Context *)handle;
- VkDescriptorBufferInfo buffer_info = {
- .buffer = (VkBuffer) ubo.handle,
- .offset = offset,
- .range = size,
- };
+ VkDescriptorBufferInfo buffer_info = {
+ .buffer = (VkBuffer)ubo.handle,
+ .offset = offset,
+ .range = size,
+ };
- VkWriteDescriptorSet descriptor_write = {
- .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
- .dstSet = ctx->desc_set,
- .dstBinding = binding,
- .dstArrayElement = slot, // write texture to slot
- .descriptorCount = 1,
- .descriptorType = (is_ubo) ? VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER : VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
- .pBufferInfo = &buffer_info,
- };
+ VkWriteDescriptorSet descriptor_write = {
+ .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
+ .dstSet = ctx->desc_set,
+ .dstBinding = binding,
+ .dstArrayElement = slot, /* write texture to slot */
+ .descriptorCount = 1,
+ .descriptorType = (is_ubo) ? VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER : VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+ .pBufferInfo = &buffer_info,
+ };
- vkUpdateDescriptorSets(vk_device.logical_device, 1, &descriptor_write, 0, NULL);
+ vkUpdateDescriptorSets(vk_device.logical_device, 1, &descriptor_write, 0, NULL);
}
-extern RendBuffer
-rend_vk_buffer_create_lifetime(RendRenderer renderer, size_t size, RendBufferType type, bool gpu, int lifetime)
+RendBuffer
+rend_vk_buffer_create_lifetime(RendContextHandle handle, size_t size, RendBufferType type, bool gpu, int lifetime)
{
- RendVk14Context *ctx = (RendVk14Context *)renderer->context;
- int32_t index = (gpu) ? vk_device.device_index : vk_device.host_index;
+ RendVk14Context *ctx = (RendVk14Context *)handle;
+ int32_t index = (gpu) ? vk_device.device_index : vk_device.host_index;
- VkBufferUsageFlags vk_usage = 0;
- switch (type) {
- case REND_BUFFER_VERTEX:
- vk_usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
- break;
- case REND_BUFFER_INDEX:
- vk_usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
- break;
- case REND_BUFFER_UNIFORM:
- vk_usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
- break;
- case REND_BUFFER_STORAGE:
- vk_usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
- break;
- case REND_BUFFER_TRANSFER:
- vk_usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
- break;
- default:
- REND__CRASH("Invalid buffer type!");
- break;
- }
+ if (type >= REND_BUFFER_COUNT || !vk_buffer_usage[type]) {
+ REND__CRASH("Invalid buffer type!");
+ }
+ VkBufferUsageFlags vk_usage = vk_buffer_usage[type];
- RendBuffer buffer = {0};
- buffer.usage = vk_usage | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
+ RendBuffer buffer = {0};
+ buffer.usage = vk_usage | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
- bool is_concurrent = (gpu && (vk_device.graphics_family_index != vk_device.transfer_family_index));
- int32_t family[] = { vk_device.graphics_family_index, vk_device.transfer_family_index };
+ bool is_concurrent = (gpu && (vk_device.graphics_family_index != vk_device.transfer_family_index));
+ uint32_t family[] = { vk_device.graphics_family_index, vk_device.transfer_family_index };
- VkBufferCreateInfo buffer_info = {
- .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
- .size = size,
- .usage = buffer.usage,
- .sharingMode = is_concurrent ? VK_SHARING_MODE_CONCURRENT : VK_SHARING_MODE_EXCLUSIVE,
- .queueFamilyIndexCount = is_concurrent ? 2 : 1,
- .pQueueFamilyIndices = is_concurrent ? family : NULL,
- };
+ VkBufferCreateInfo buffer_info = {
+ .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
+ .size = size,
+ .usage = buffer.usage,
+ .sharingMode = is_concurrent ? VK_SHARING_MODE_CONCURRENT : VK_SHARING_MODE_EXCLUSIVE,
+ .queueFamilyIndexCount = is_concurrent ? 2 : 1,
+ .pQueueFamilyIndices = is_concurrent ? family : NULL,
+ };
- if (vkCreateBuffer(vk_device.logical_device, &buffer_info, vk_allocator, (VkBuffer*) &buffer.handle) != VK_SUCCESS) {
- REND__CRASH("Failed to create VkBuffer!");
- }
+ if (vkCreateBuffer(vk_device.logical_device, &buffer_info, vk_allocator, (VkBuffer *) &buffer.handle) != VK_SUCCESS) {
+ REND__CRASH("Failed to create VkBuffer!");
+ }
- VkMemoryRequirements mem_reqs;
- vkGetBufferMemoryRequirements(vk_device.logical_device, (VkBuffer) buffer.handle, &mem_reqs);
+ VkMemoryRequirements mem_reqs;
+ vkGetBufferMemoryRequirements(vk_device.logical_device, (VkBuffer)buffer.handle, &mem_reqs);
- RASSERT((mem_reqs.memoryTypeBits & (1u << index)) && "Buffer incompatible with chosen memory type!");
+ RASSERT((mem_reqs.memoryTypeBits & (1u << index)) && "Buffer incompatible with chosen memory type!");
- RendVkArenaAllocator *arena = (lifetime == REND_LIFETIME_FRAME) ? &ctx->arena_frame : &ctx->arena_persistent;
- RendMemory vk_memory = rend_vk_arena_alloc(arena, mem_reqs.size, index);
+ RendVkArenaAllocator *arena = (lifetime == REND_LIFETIME_FRAME) ? &ctx->arena_frame : &ctx->arena_persistent;
+ RendMemory vk_memory = rend_vk_arena_alloc(arena, mem_reqs.size, index);
- if (vkBindBufferMemory(vk_device.logical_device, (VkBuffer) buffer.handle, (VkDeviceMemory) vk_memory.device_memory, vk_memory.offset) != VK_SUCCESS) {
- REND__CRASH("Failed to bind VkBuffer memory!");
- }
+ if (vkBindBufferMemory(vk_device.logical_device, (VkBuffer)buffer.handle, (VkDeviceMemory)vk_memory.device_memory, vk_memory.offset) != VK_SUCCESS) {
+ REND__CRASH("Failed to bind VkBuffer memory!");
+ }
- buffer.memory = vk_memory;
+ buffer.memory = vk_memory;
- VkBufferDeviceAddressInfo address_info = {
- .sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO,
- .buffer = (VkBuffer) buffer.handle,
- };
+ VkBufferDeviceAddressInfo address_info = {
+ .sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO,
+ .buffer = (VkBuffer)buffer.handle,
+ };
- if (!gpu && vk_memory.host_mapped_memory) {
- buffer.mapped_memory = vk_memory.host_mapped_memory;
- } else {
- buffer.mapped_memory = NULL;
- }
+ if (!gpu && vk_memory.host_mapped_memory) {
+ buffer.mapped_memory = vk_memory.host_mapped_memory;
+ } else {
+ buffer.mapped_memory = NULL;
+ }
- buffer.gpu_address = vkGetBufferDeviceAddress(vk_device.logical_device, &address_info);
- buffer.size = size;
- return buffer;
+ buffer.gpu_address = vkGetBufferDeviceAddress(vk_device.logical_device, &address_info);
+ buffer.size = size;
+ return buffer;
}
-extern void
+void
rend_vk_buffer_destroy(RendBuffer *buffer)
{
- // NOTE: this function is meant to be called by the user
- // when freeing his buffers mid frame, there may be a better
- // way using fences perhaps? or by checking the timeline semaphore?
- vkDeviceWaitIdle(vk_device.logical_device);
- vkDestroyBuffer(vk_device.logical_device, (VkBuffer) buffer->handle, vk_allocator);
- memset(buffer, 0xC0FFEE, sizeof *buffer); // fill buffer with coffee
+ /* NOTE: this function is meant to be called by the user */
+ /* when freeing his buffers mid frame, there may be a better */
+ /* way using fences perhaps? or by checking the timeline semaphore? */
+ vkDeviceWaitIdle(vk_device.logical_device);
+ vkDestroyBuffer(vk_device.logical_device, (VkBuffer)buffer->handle, vk_allocator);
+ memset(buffer, 0xC0FFEE, sizeof(*buffer)); /* fill buffer with coffee */
}
-extern void
-rend_vk_buffer_copy(RendRenderer renderer, RendBuffer *dest, size_t dest_offset, RendBuffer *src, size_t src_offset, size_t bytes)
+void
+rend_vk_buffer_copy(RendContextHandle handle, RendBuffer *dest, size_t dest_offset, RendBuffer *src, size_t src_offset, size_t bytes)
{
- RASSERT(src && dest); // check that im not sending null pointers
- RASSERT(src->usage & VK_BUFFER_USAGE_TRANSFER_SRC_BIT); // source buffer must be marked as transfer src
- RASSERT(dest->usage & VK_BUFFER_USAGE_TRANSFER_DST_BIT); // dest buffer must be marked as transfer dest
+ RASSERT(src && dest); /* check that im not sending null pointers */
+ RASSERT(src->usage & VK_BUFFER_USAGE_TRANSFER_SRC_BIT); /* source buffer must be marked as transfer src */
+ RASSERT(dest->usage & VK_BUFFER_USAGE_TRANSFER_DST_BIT); /* dest buffer must be marked as transfer dest */
+
+ RendVk14Context *ctx = (RendVk14Context *)handle;
+ VkBuffer src_vk = (VkBuffer)(uintptr_t)src->handle;
+ VkBuffer dest_vk = (VkBuffer)(uintptr_t)dest->handle;
- RendVk14Context *ctx = (RendVk14Context *)renderer->context;
- VkBuffer src_vk = (VkBuffer)(uintptr_t)src->handle;
- VkBuffer dest_vk = (VkBuffer)(uintptr_t)dest->handle;
+ VkCommandBuffer transfer_cmd = VK_NULL_HANDLE;
- VkCommandBuffer transfer_cmd = VK_NULL_HANDLE;
+ VkCommandBufferAllocateInfo alloc_info = {
+ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
+ .commandBufferCount = 1,
+ .commandPool = ctx->upload_command_pool,
+ .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
+ .pNext = NULL,
+ };
- VkCommandBufferAllocateInfo alloc_info = {
- .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
- .commandBufferCount = 1,
- .commandPool = ctx->upload_command_pool,
- .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
- .pNext = NULL,
- };
+ if (vkAllocateCommandBuffers(vk_device.logical_device, &alloc_info, &transfer_cmd) != VK_SUCCESS) {
+ REND__CRASH("Failed to allocate transfer command buffer!");
+ }
- if (vkAllocateCommandBuffers(vk_device.logical_device, &alloc_info, &transfer_cmd) != VK_SUCCESS) {
- REND__CRASH("Failed to allocate transfer command buffer!");
- }
+ VkCommandBufferBeginInfo begin_info = {
+ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
+ .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
+ };
+ vkBeginCommandBuffer(transfer_cmd, &begin_info);
- VkCommandBufferBeginInfo begin_info = {
- .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
- .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
- };
- vkBeginCommandBuffer(transfer_cmd, &begin_info);
+ VkBufferCopy buffer_copy = {
+ .srcOffset = (VkDeviceSize)src_offset,
+ .dstOffset = (VkDeviceSize)dest_offset,
+ .size = (VkDeviceSize)bytes,
+ };
- VkBufferCopy buffer_copy = {
- .srcOffset = (VkDeviceSize)src_offset,
- .dstOffset = (VkDeviceSize)dest_offset,
- .size = (VkDeviceSize)bytes,
- };
+ vkCmdCopyBuffer(transfer_cmd, src_vk, dest_vk, 1, &buffer_copy);
+ vkEndCommandBuffer(transfer_cmd);
- vkCmdCopyBuffer(transfer_cmd, src_vk, dest_vk, 1, &buffer_copy);
- vkEndCommandBuffer(transfer_cmd);
+ VkCommandBufferSubmitInfo cmd_info = {
+ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO,
+ .commandBuffer = transfer_cmd,
+ .deviceMask = 0,
+ };
- VkCommandBufferSubmitInfo cmd_info = {
- .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO,
- .commandBuffer = transfer_cmd,
- .deviceMask = 0,
- };
+ VkSubmitInfo2 submit_info = {
+ .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO_2,
+ .commandBufferInfoCount = 1,
+ .pCommandBufferInfos = &cmd_info,
+ };
- VkSubmitInfo2 submit_info = {
- .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO_2,
- .commandBufferInfoCount = 1,
- .pCommandBufferInfos = &cmd_info,
- };
+ vkQueueSubmit2(vk_device.transfer_queue, 1, &submit_info, VK_NULL_HANDLE);
- vkQueueSubmit2(vk_device.transfer_queue, 1, &submit_info, VK_NULL_HANDLE);
-
- vkQueueWaitIdle(vk_device.transfer_queue);
- vkFreeCommandBuffers(vk_device.logical_device, ctx->upload_command_pool, 1, &transfer_cmd);
+ vkQueueWaitIdle(vk_device.transfer_queue);
+ vkFreeCommandBuffers(vk_device.logical_device, ctx->upload_command_pool, 1, &transfer_cmd);
}
-extern RendTexture
-rend_vk_texture_create(RendRenderer renderer, uint32_t width, uint32_t height, uint32_t depth, uint32_t mip_levels, uint32_t layers, RendFormat format)
+RendTexture
+rend_vk_texture_create(RendContextHandle handle, uint32_t width, uint32_t height, uint32_t depth, uint32_t mip_levels, uint32_t layers, RendFormat format)
{
- RASSERT(format < REND_FORMAT_COUNT && "Invalid format!");
+ RASSERT(format < REND_FORMAT_COUNT && "Invalid format!");
- RendVk14Context *ctx = (RendVk14Context*) renderer->context;
- VkFormat vk_format = vk_format_from_rend_format[format];
+ RendVk14Context *ctx = (RendVk14Context *)handle;
+ VkFormat vk_format = vk_format_from_rend_format[format];
- uint32_t safe_depth = (depth > 0) ? depth : 1;
- uint32_t safe_mips = (mip_levels > 0) ? mip_levels : 1;
- uint32_t safe_layers = (layers > 0) ? layers : 1;
+ uint32_t safe_depth = (depth > 0) ? depth : 1;
+ uint32_t safe_mips = (mip_levels > 0) ? mip_levels : 1;
+ uint32_t safe_layers = (layers > 0) ? layers : 1;
- RendTexture tex = {
- .handle = 0,
- .width = width,
- .height = height,
- .depth = safe_depth,
- .mip_levels = safe_mips,
- .layers = safe_layers,
- .format = vk_format,
- .layout = VK_IMAGE_LAYOUT_UNDEFINED,
- };
+ RendTexture tex = {
+ .handle = 0,
+ .width = width,
+ .height = height,
+ .depth = safe_depth,
+ .mip_levels = safe_mips,
+ .layers = safe_layers,
+ .format = vk_format,
+ .layout = VK_IMAGE_LAYOUT_UNDEFINED,
+ };
- VkImageCreateInfo image_info = {
- .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
- .imageType = (safe_depth > 1) ? VK_IMAGE_TYPE_3D : VK_IMAGE_TYPE_2D,
- .extent = { .width = width, .height = height, .depth = safe_depth },
- .mipLevels = tex.mip_levels,
- .arrayLayers = tex.layers,
- .format = vk_format,
- .tiling = VK_IMAGE_TILING_OPTIMAL,
- .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
- .usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
- .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
- .samples = VK_SAMPLE_COUNT_1_BIT,
- .flags = 0,
- };
+ VkImageCreateInfo image_info = {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
+ .imageType = (safe_depth > 1) ? VK_IMAGE_TYPE_3D : VK_IMAGE_TYPE_2D,
+ .extent = { .width = width, .height = height, .depth = safe_depth },
+ .mipLevels = tex.mip_levels,
+ .arrayLayers = tex.layers,
+ .format = vk_format,
+ .tiling = VK_IMAGE_TILING_OPTIMAL,
+ .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
+ .usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
+ .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
+ .samples = VK_SAMPLE_COUNT_1_BIT,
+ .flags = 0,
+ };
- if (vkCreateImage(vk_device.logical_device, &image_info, vk_allocator, (VkImage*)&tex.handle) != VK_SUCCESS) {
- REND__CRASH("failed to create image!");
- return tex;
- }
+ if (vkCreateImage(vk_device.logical_device, &image_info, vk_allocator, (VkImage *)&tex.handle) != VK_SUCCESS) {
+ REND__CRASH("failed to create image!");
+ return tex;
+ }
- VkMemoryRequirements mem_requirements;
- vkGetImageMemoryRequirements(vk_device.logical_device, (VkImage)tex.handle, &mem_requirements);
+ VkMemoryRequirements mem_requirements;
+ vkGetImageMemoryRequirements(vk_device.logical_device, (VkImage)tex.handle, &mem_requirements);
- uint32_t index = rend_vk_get_heap_index(mem_requirements.memoryTypeBits, vk_device.device_index);
- tex.memory = rend_vk_arena_alloc(&ctx->arena_persistent, mem_requirements.size, index);
+ uint32_t index = rend_vk_get_heap_index(mem_requirements.memoryTypeBits, vk_device.device_index);
+ tex.memory = rend_vk_arena_alloc(&ctx->arena_persistent, mem_requirements.size, index);
- vkBindImageMemory(vk_device.logical_device, (VkImage)tex.handle, (VkDeviceMemory)tex.memory.device_memory, (VkDeviceSize)tex.memory.offset);
+ vkBindImageMemory(vk_device.logical_device, (VkImage)tex.handle, (VkDeviceMemory)tex.memory.device_memory, (VkDeviceSize)tex.memory.offset);
- // Correct ImageView creation using strict VkImageViewType and derived format
- VkImageViewCreateInfo view_info = {
- .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
- .image = (VkImage)tex.handle,
- .viewType = (safe_depth > 1) ? VK_IMAGE_VIEW_TYPE_3D : VK_IMAGE_VIEW_TYPE_2D,
- .format = vk_format,
- .subresourceRange = {
- .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
- .baseMipLevel = 0,
- .levelCount = tex.mip_levels,
- .baseArrayLayer = 0,
- .layerCount = tex.layers,
- },
- };
+ /* Correct ImageView creation using strict VkImageViewType and derived format */
+ VkImageViewCreateInfo view_info = {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
+ .image = (VkImage)tex.handle,
+ .viewType = (safe_depth > 1) ? VK_IMAGE_VIEW_TYPE_3D : VK_IMAGE_VIEW_TYPE_2D,
+ .format = vk_format,
+ .subresourceRange = {
+ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+ .baseMipLevel = 0,
+ .levelCount = tex.mip_levels,
+ .baseArrayLayer = 0,
+ .layerCount = tex.layers,
+ },
+ };
- if (vkCreateImageView(vk_device.logical_device, &view_info, vk_allocator, (VkImageView*)&tex.view) != VK_SUCCESS) {
- REND__CRASH("failed to create image view!");
- return tex;
- }
+ if (vkCreateImageView(vk_device.logical_device, &view_info, vk_allocator, (VkImageView *)&tex.view) != VK_SUCCESS) {
+ REND__CRASH("failed to create image view!");
+ return tex;
+ }
- /* per-texture sampler */
- VkSamplerCreateInfo sampler_info = {
- .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
- .magFilter = VK_FILTER_LINEAR, // force sharp upscaling
- .minFilter = VK_FILTER_LINEAR, // TODO: add filter setting to texture
- .addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT,
- .addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT,
- .addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT,
+ /* per-texture sampler */
+ VkSamplerCreateInfo sampler_info = {
+ .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
+ .magFilter = VK_FILTER_LINEAR, /* force sharp upscaling */
+ .minFilter = VK_FILTER_LINEAR, /* TODO: add filter setting to texture */
+ .addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT,
+ .addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT,
+ .addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT,
- .mipmapMode = (tex.mip_levels > 1) ? VK_SAMPLER_MIPMAP_MODE_LINEAR : VK_SAMPLER_MIPMAP_MODE_NEAREST,
- .minLod = 0.0f,
- .maxLod = (tex.mip_levels > 1) ? (float)tex.mip_levels : 0.0f,
+ .mipmapMode = (tex.mip_levels > 1) ? VK_SAMPLER_MIPMAP_MODE_LINEAR : VK_SAMPLER_MIPMAP_MODE_NEAREST,
+ .minLod = 0.0f,
+ .maxLod = (tex.mip_levels > 1) ? (float)tex.mip_levels : 0.0f,
- .anisotropyEnable = (tex.mip_levels > 1 && vk_device.features.samplerAnisotropy) ? VK_TRUE : VK_FALSE,
- .maxAnisotropy = 8.0f,
- };
+ .anisotropyEnable = (tex.mip_levels > 1 && vk_device.features.samplerAnisotropy) ? VK_TRUE : VK_FALSE,
+ .maxAnisotropy = 8.0f,
+ };
- if (vkCreateSampler(vk_device.logical_device, &sampler_info, vk_allocator, (VkSampler*)&tex.sampler) != VK_SUCCESS) {
- REND__CRASH("failed to create sampler!");
- }
+ if (vkCreateSampler(vk_device.logical_device, &sampler_info, vk_allocator, (VkSampler *)&tex.sampler) != VK_SUCCESS) {
+ REND__CRASH("failed to create sampler!");
+ }
- return tex;
+ return tex;
}
-extern void
-rend_vk_texture_destroy(RendRenderer renderer, RendTexture *tex)
+void
+rend_vk_texture_destroy(RendContextHandle handle, RendTexture *tex)
{
- RASSERT(renderer && tex);
- RendVk14Context *ctx = (RendVk14Context*)renderer->context;
+ RASSERT(handle && tex);
- if (tex->handle) {
- vkDestroyImage(vk_device.logical_device, (VkImage) tex->handle, vk_allocator);
- tex->handle = 0;
- }
+ if (tex->handle) {
+ vkDestroyImage(vk_device.logical_device, (VkImage)tex->handle, vk_allocator);
+ tex->handle = 0;
+ }
- if (tex->view) {
- vkDestroyImageView(vk_device.logical_device, (VkImageView) tex->view, vk_allocator);
- tex->view = 0;
- }
+ if (tex->view) {
+ vkDestroyImageView(vk_device.logical_device, (VkImageView)tex->view, vk_allocator);
+ tex->view = 0;
+ }
- if (tex->sampler) {
- vkDestroySampler(vk_device.logical_device, (VkSampler)tex->sampler, vk_allocator);
- tex->sampler = 0;
- }
+ if (tex->sampler) {
+ vkDestroySampler(vk_device.logical_device, (VkSampler)tex->sampler, vk_allocator);
+ tex->sampler = 0;
+ }
- // memset(tex, 0xBABE, sizeof *tex);
+ /* memset(tex, 0xBABE, sizeof(*tex)); */
}
-extern void
-rend_vk_texture_transition_layout(RendRenderer renderer, VkCommandBuffer cmd, RendTexture *texture, VkImageLayout new_layout)
+static void
+rend_vk_texture_barrier(VkCommandBuffer cmd, RendTexture *texture, VkImageLayout new_layout, uint32_t src_family, uint32_t dst_family, VkAccessFlags2 src_access, VkAccessFlags2 dst_access, VkPipelineStageFlags2 src_stage, VkPipelineStageFlags2 dst_stage)
{
- RendVk14Context *ctx = renderer->context;
- VkCommandPool pool = ctx->upload_command_pool;
-
- VkImageMemoryBarrier2 barrier = {
- .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
- .oldLayout = texture->layout,
- .newLayout = new_layout,
-
- .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
- .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
-
- .image = (VkImage) texture->handle,
-
- .subresourceRange = (VkImageSubresourceRange) {
- .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
- .baseMipLevel = 0,
- .levelCount = texture->mip_levels,
- .baseArrayLayer = 0,
- .layerCount = texture->layers,
- },
-
- .srcAccessMask = 0, // TODO
- .dstAccessMask = 0, // TODO
-
- };
-
- if (texture->layout == VK_IMAGE_LAYOUT_UNDEFINED && new_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
- barrier.srcAccessMask = 0;
- barrier.dstAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT;
- barrier.srcStageMask = VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT;
- barrier.dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT;
- } else if (texture->layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && new_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
- barrier.srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT;
- barrier.dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT;
- barrier.srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT;
- barrier.dstStageMask = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT;
- } else {
- barrier.srcAccessMask = VK_ACCESS_2_MEMORY_WRITE_BIT;
- barrier.dstAccessMask = VK_ACCESS_2_MEMORY_READ_BIT | VK_ACCESS_2_MEMORY_WRITE_BIT;
- barrier.srcStageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT;
- barrier.dstStageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT;
- }
-
- VkDependencyInfo dep = {
- .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
- .pImageMemoryBarriers = &barrier,
- .imageMemoryBarrierCount = 1,
- };
-
- texture->layout = new_layout;
- vkCmdPipelineBarrier2(cmd, &dep);
+ VkImageMemoryBarrier2 barrier = {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
+ .oldLayout = texture->layout,
+ .newLayout = new_layout,
+ .srcQueueFamilyIndex = src_family,
+ .dstQueueFamilyIndex = dst_family,
+ .image = (VkImage)texture->handle,
+ .srcAccessMask = src_access,
+ .dstAccessMask = dst_access,
+ .srcStageMask = src_stage,
+ .dstStageMask = dst_stage,
+ .subresourceRange = {
+ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+ .baseMipLevel = 0,
+ .levelCount = texture->mip_levels,
+ .baseArrayLayer = 0,
+ .layerCount = texture->layers,
+ },
+ };
+ VkDependencyInfo dep = {
+ .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
+ .pImageMemoryBarriers = &barrier,
+ .imageMemoryBarrierCount = 1,
+ };
+ texture->layout = new_layout;
+ vkCmdPipelineBarrier2(cmd, &dep);
}
-extern void
-rend_vk_texture_transfer_ownership_release(RendRenderer renderer, VkCommandBuffer cmd, RendTexture *texture, uint32_t src_family, uint32_t dst_family, VkImageLayout new_layout)
+void
+rend_vk_texture_transition_layout(RendContextHandle handle, VkCommandBuffer cmd, RendTexture *texture, VkImageLayout new_layout)
{
- RendVk14Context *ctx = renderer->context;
- (void) ctx; // reserved in case you need it for stage/access lookups later
-
- VkImageMemoryBarrier2 barrier = {
- .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
- .oldLayout = texture->layout,
- .newLayout = new_layout,
- .srcQueueFamilyIndex = src_family,
- .dstQueueFamilyIndex = dst_family,
- .image = (VkImage) texture->handle,
- .subresourceRange = (VkImageSubresourceRange) {
- .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
- .baseMipLevel = 0,
- .levelCount = texture->mip_levels,
- .baseArrayLayer = 0,
- .layerCount = texture->layers,
- },
- };
-
- if (texture->layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && new_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
- barrier.srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT;
- barrier.dstAccessMask = 0;
- barrier.srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT;
- barrier.dstStageMask = VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT;
- } else {
- barrier.srcAccessMask = VK_ACCESS_2_MEMORY_WRITE_BIT;
- barrier.dstAccessMask = 0;
- barrier.srcStageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT;
- barrier.dstStageMask = VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT;
- }
-
- VkDependencyInfo dep = {
- .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
- .pImageMemoryBarriers = &barrier,
- .imageMemoryBarrierCount = 1,
- };
-
- texture->layout = new_layout;
- vkCmdPipelineBarrier2(cmd, &dep);
+ (void)handle;
+ if (texture->layout == VK_IMAGE_LAYOUT_UNDEFINED && new_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
+ rend_vk_texture_barrier(cmd, texture, new_layout, VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED,
+ 0, VK_ACCESS_2_TRANSFER_WRITE_BIT,
+ VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_2_TRANSFER_BIT);
+ } else if (texture->layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && new_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
+ rend_vk_texture_barrier(cmd, texture, new_layout, VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED,
+ VK_ACCESS_2_TRANSFER_WRITE_BIT, VK_ACCESS_2_SHADER_READ_BIT,
+ VK_PIPELINE_STAGE_2_TRANSFER_BIT, VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT);
+ } else {
+ rend_vk_texture_barrier(cmd, texture, new_layout, VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED,
+ VK_ACCESS_2_MEMORY_WRITE_BIT, VK_ACCESS_2_MEMORY_READ_BIT | VK_ACCESS_2_MEMORY_WRITE_BIT,
+ VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT);
+ }
}
-extern void
-rend_vk_texture_transfer_ownership_acquire(RendRenderer renderer, VkCommandBuffer cmd, RendTexture *texture, uint32_t src_family, uint32_t dst_family, VkImageLayout new_layout)
+void
+rend_vk_texture_transfer_ownership_release(RendContextHandle handle, VkCommandBuffer cmd, RendTexture *texture, uint32_t src_family, uint32_t dst_family, VkImageLayout new_layout)
{
- RendVk14Context *ctx = renderer->context;
- (void) ctx;
-
- VkImageMemoryBarrier2 barrier = {
- .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
- .oldLayout = texture->layout,
- .newLayout = new_layout,
- .srcQueueFamilyIndex = src_family,
- .dstQueueFamilyIndex = dst_family,
- .image = (VkImage) texture->handle,
-
- .subresourceRange = (VkImageSubresourceRange) {
- .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
- .baseMipLevel = 0,
- .levelCount = texture->mip_levels,
- .baseArrayLayer = 0,
- .layerCount = texture->layers,
- },
- };
-
- if (texture->layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && new_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
- barrier.srcAccessMask = 0;
- barrier.dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT;
- barrier.srcStageMask = VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT;
- barrier.dstStageMask = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT;
- } else {
- barrier.srcAccessMask = 0;
- barrier.dstAccessMask = VK_ACCESS_2_MEMORY_READ_BIT | VK_ACCESS_2_MEMORY_WRITE_BIT;
- barrier.srcStageMask = VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT;
- barrier.dstStageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT;
- }
-
- VkDependencyInfo dep = {
- .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
- .pImageMemoryBarriers = &barrier,
- .imageMemoryBarrierCount = 1,
- };
+ (void)handle;
+ if (texture->layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && new_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
+ rend_vk_texture_barrier(cmd, texture, new_layout, src_family, dst_family,
+ VK_ACCESS_2_TRANSFER_WRITE_BIT, 0,
+ VK_PIPELINE_STAGE_2_TRANSFER_BIT, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT);
+ } else {
+ rend_vk_texture_barrier(cmd, texture, new_layout, src_family, dst_family,
+ VK_ACCESS_2_MEMORY_WRITE_BIT, 0,
+ VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT);
+ }
+}
- texture->layout = new_layout;
- vkCmdPipelineBarrier2(cmd, &dep);
+void
+rend_vk_texture_transfer_ownership_acquire(RendContextHandle handle, VkCommandBuffer cmd, RendTexture *texture, uint32_t src_family, uint32_t dst_family, VkImageLayout new_layout)
+{
+ (void)handle;
+ if (texture->layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && new_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
+ rend_vk_texture_barrier(cmd, texture, new_layout, src_family, dst_family,
+ 0, VK_ACCESS_2_SHADER_READ_BIT,
+ VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT);
+ } else {
+ rend_vk_texture_barrier(cmd, texture, new_layout, src_family, dst_family,
+ 0, VK_ACCESS_2_MEMORY_READ_BIT | VK_ACCESS_2_MEMORY_WRITE_BIT,
+ VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT);
+ }
}
-extern void
-rend_vk_texture_copy_buffer(RendRenderer renderer, RendTexture *texture, RendBuffer *buffer)
+void
+rend_vk_texture_copy_buffer(RendContextHandle handle, RendTexture *texture, RendBuffer *buffer)
{
- RendVk14Context *ctx = renderer->context;
+ RendVk14Context *ctx = (RendVk14Context *)handle;
- VkCommandBuffer cmd_transfer = rend_vk_cmdbuffer_single_use_begin(ctx->upload_command_pool); {
- rend_vk_texture_transition_layout(renderer, cmd_transfer, texture, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
- VkBufferImageCopy region = {
- .imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
- .imageSubresource.layerCount = texture->layers,
- .imageExtent = (VkExtent3D) { texture->width, texture->height, texture->depth },
- };
+ VkCommandBuffer cmd_transfer = rend_vk_cmdbuffer_single_use_begin(ctx->upload_command_pool); {
+ rend_vk_texture_transition_layout(handle, cmd_transfer, texture, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
+ VkBufferImageCopy region = {
+ .imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+ .imageSubresource.layerCount = texture->layers,
+ .imageExtent = (VkExtent3D) { texture->width, texture->height, texture->depth },
+ };
- vkCmdCopyBufferToImage(cmd_transfer, (VkBuffer) buffer->handle, (VkImage) texture->handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
- rend_vk_texture_transfer_ownership_release(renderer, cmd_transfer, texture, vk_device.transfer_family_index, vk_device.graphics_family_index, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
- } rend_vk_cmdbuffer_single_use_end(ctx->upload_command_pool, cmd_transfer, vk_device.transfer_queue);
+ vkCmdCopyBufferToImage(cmd_transfer, (VkBuffer)buffer->handle, (VkImage)texture->handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
+ rend_vk_texture_transfer_ownership_release(handle, cmd_transfer, texture, vk_device.transfer_family_index, vk_device.graphics_family_index, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
+ } rend_vk_cmdbuffer_single_use_end(ctx->upload_command_pool, cmd_transfer, vk_device.transfer_queue);
- VkCommandBuffer cmd_graphics = rend_vk_cmdbuffer_single_use_begin(ctx->graphics_command_pool); {
- rend_vk_texture_transfer_ownership_acquire(renderer, cmd_graphics, texture, vk_device.transfer_family_index, vk_device.graphics_family_index, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
- } rend_vk_cmdbuffer_single_use_end(ctx->graphics_command_pool, cmd_graphics, vk_device.graphics_queue);
+ VkCommandBuffer cmd_graphics = rend_vk_cmdbuffer_single_use_begin(ctx->graphics_command_pool); {
+ rend_vk_texture_transfer_ownership_acquire(handle, cmd_graphics, texture, vk_device.transfer_family_index, vk_device.graphics_family_index, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
+ } rend_vk_cmdbuffer_single_use_end(ctx->graphics_command_pool, cmd_graphics, vk_device.graphics_queue);
}
-extern void
-rend_vk_texture_blit(RendRenderer renderer, RendTexture *src, RendTexture *dst, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h, uint32_t dst_x, uint32_t dst_y, uint32_t dst_w, uint32_t dst_h)
+void
+rend_vk_texture_blit(RendContextHandle handle, RendTexture *src, RendTexture *dst, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h, uint32_t dst_x, uint32_t dst_y, uint32_t dst_w, uint32_t dst_h)
{
+ RendVk14Context *ctx = (RendVk14Context *)handle;
+ VkCommandBuffer cmd = ctx->frame_resources[ctx->frame_index].command_buffer;
- RendVk14Context *ctx = (RendVk14Context*) renderer->context;
- VkCommandBuffer cmd = ctx->frame_resources[ctx->frame_index].command_buffer;
-
- rend_vk_texture_transition_layout(renderer, cmd, src, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
- rend_vk_texture_transition_layout(renderer, cmd, dst, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
+ rend_vk_texture_transition_layout(handle, cmd, src, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
+ rend_vk_texture_transition_layout(handle, cmd, dst, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
- VkImageBlit2 blit_region = {
- .sType = VK_STRUCTURE_TYPE_IMAGE_BLIT_2,
- .srcSubresource = {
- .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
- .mipLevel = 0,
- .baseArrayLayer = 0,
- .layerCount = 1,
- },
- .srcOffsets = {
- { src_x, src_y, 0 },
- { src_x + src_w, src_y + src_h, 1 }
- },
- .dstSubresource = {
- .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
- .mipLevel = 0,
- .baseArrayLayer = 0,
- .layerCount = 1,
- },
- .dstOffsets = {
- { dst_x, dst_y, 0 },
- { dst_x + dst_w, dst_y + dst_h, 1 }
- }
- };
+ VkImageBlit2 blit_region = {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_BLIT_2,
+ .srcSubresource = {
+ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+ .mipLevel = 0,
+ .baseArrayLayer = 0,
+ .layerCount = 1,
+ },
+ .srcOffsets = {
+ { src_x, src_y, 0 },
+ { src_x + src_w, src_y + src_h, 1 }
+ },
+ .dstSubresource = {
+ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+ .mipLevel = 0,
+ .baseArrayLayer = 0,
+ .layerCount = 1,
+ },
+ .dstOffsets = {
+ { dst_x, dst_y, 0 },
+ { dst_x + dst_w, dst_y + dst_h, 1 }
+ }
+ };
- VkBlitImageInfo2 blit_info = {
- .sType = VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2,
- .srcImage = (VkImage) src->handle,
- .srcImageLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
- .dstImage = (VkImage) dst->handle,
- .dstImageLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- .regionCount = 1,
- .pRegions = &blit_region,
+ VkBlitImageInfo2 blit_info = {
+ .sType = VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2,
+ .srcImage = (VkImage)src->handle,
+ .srcImageLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ .dstImage = (VkImage)dst->handle,
+ .dstImageLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ .regionCount = 1,
+ .pRegions = &blit_region,
- .filter = VK_FILTER_NEAREST // crispy
- };
+ .filter = VK_FILTER_NEAREST /* crispy */
+ };
- vkCmdBlitImage2(cmd, &blit_info);
+ vkCmdBlitImage2(cmd, &blit_info);
}
static VkCommandBuffer
rend_vk_cmdbuffer_single_use_begin(VkCommandPool pool)
{
- VkCommandBufferAllocateInfo alloc_info = {
- .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
- .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
- .commandPool = pool,
- .commandBufferCount = 1,
- };
+ VkCommandBufferAllocateInfo alloc_info = {
+ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
+ .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
+ .commandPool = pool,
+ .commandBufferCount = 1,
+ };
- VkCommandBuffer cmd;
- vkAllocateCommandBuffers(vk_device.logical_device, &alloc_info, &cmd);
+ VkCommandBuffer cmd;
+ vkAllocateCommandBuffers(vk_device.logical_device, &alloc_info, &cmd);
- VkCommandBufferBeginInfo begin = {
- .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
- .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
- };
+ VkCommandBufferBeginInfo begin = {
+ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
+ .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
+ };
- vkBeginCommandBuffer(cmd, &begin);
+ vkBeginCommandBuffer(cmd, &begin);
- return cmd;
+ return cmd;
}
static void
rend_vk_cmdbuffer_single_use_end(VkCommandPool pool, VkCommandBuffer cmd, VkQueue q)
{
- vkEndCommandBuffer(cmd);
+ vkEndCommandBuffer(cmd);
- VkSubmitInfo submit_info = {
- .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
- .commandBufferCount = 1,
- .pCommandBuffers = &cmd,
- };
+ VkSubmitInfo submit_info = {
+ .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
+ .commandBufferCount = 1,
+ .pCommandBuffers = &cmd,
+ };
- vkQueueSubmit(q, 1, &submit_info, VK_NULL_HANDLE);
- vkQueueWaitIdle(q);
+ vkQueueSubmit(q, 1, &submit_info, VK_NULL_HANDLE);
+ vkQueueWaitIdle(q);
- vkFreeCommandBuffers(vk_device.logical_device, pool, 1, &cmd);
+ vkFreeCommandBuffers(vk_device.logical_device, pool, 1, &cmd);
}
-extern bool
-rend_vk_pipeline_create(RendRenderer renderer, RendPipeline pipeline, Rend__PipelineConfig config, uint8_t type, const uint8_t *shader1, size_t bytes1, const uint8_t *shader2, size_t bytes2, const uint8_t *shader3, size_t bytes3)
+bool
+rend_vk_pipeline_create(RendContextHandle handle, RendPipeline pipeline, Rend__PipelineConfig config, uint8_t type, const uint8_t *shader1, size_t bytes1, const uint8_t *shader2, size_t bytes2, const uint8_t *shader3, size_t bytes3)
{
+ uint32_t u;
+ uint32_t i;
+ RendVk14Context *ctx = (RendVk14Context *)handle;
+ pipeline->idx = ctx->pipeline_count++;
+ pipeline->backend_ctx = ctx; /* useful for when we only have RendPipeline as an argument */
- RendVk14Context *ctx = (RendVk14Context *)renderer->context;
- pipeline->idx = ctx->pipeline_count++;
- pipeline->backend_ctx = ctx; // useful for when we only have RendPipeline as an argument
-
- RendVkPipeline *vk_pipeline = &ctx->pipelines[pipeline->idx];
- vk_pipeline->blend_enable = false;
-
- /*
- * set color and depth format
- */
- VkFormat color_format = (config.color_format != REND_FORMAT_UNDEFINED)
- ? vk_format_from_rend_format[config.color_format]
- : ctx->swapchain.format.format;
-
- VkFormat depth_format = (config.depth_format != REND_FORMAT_UNDEFINED)
- ? vk_format_from_rend_format[config.depth_format]
- : vk_device.depth_format;
-
- /*
- * Pipeline Layout
- */
-
- vk_pipeline->push_constants_range = 0;
- uint32_t total_size = 0;
- for (uint32_t u = 0; u < config.push_constant_count; ++u) {
- total_size += config.push_constants[u].size;
- }
-
- vk_pipeline->push_constants_range = total_size;
-
- VkPushConstantRange pc_range = {
- .offset = 0,
- .size = total_size,
- .stageFlags = VK_SHADER_STAGE_ALL,
- };
+ RendVkPipeline *vk_pipeline = &ctx->pipelines[pipeline->idx];
+ vk_pipeline->blend_enable = false;
- VkPipelineLayoutCreateInfo layout_info = {
- .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
- .pSetLayouts = &ctx->desc_layout,
- .setLayoutCount = 1,
- .pPushConstantRanges = (total_size > 0) ? &pc_range : NULL,
- .pushConstantRangeCount = (total_size > 0) ? 1 : 0,
- };
+ /*
+ * set color and depth format
+ */
+ VkFormat color_format = (config.color_format != REND_FORMAT_UNDEFINED)
+ ? vk_format_from_rend_format[config.color_format]
+ : ctx->swapchain.format.format;
- CHECK_VK_RESULT(vkCreatePipelineLayout(vk_device.logical_device, &layout_info, vk_allocator, &vk_pipeline->layout));
+ VkFormat depth_format = (config.depth_format != REND_FORMAT_UNDEFINED)
+ ? vk_format_from_rend_format[config.depth_format]
+ : vk_device.depth_format;
- /*
- * Setup shaders based on pipeline type
- */
- VkPipelineShaderStageCreateInfo shader_stages[3] = {0};
- VkShaderModule shader_modules[3] = {0};
- uint32_t shader_count = 0;
+ /*
+ * Pipeline Layout
+ */
- if (type == REND__PIPELINE_GRAPHICS) {
- shader_count = 2;
- shader_modules[0] = rend_vk_shader_module_create(shader1, bytes1);
- shader_modules[1] = rend_vk_shader_module_create(shader2, bytes2);
+ uint32_t total_size = 0;
+ for (u = 0; u < config.push_constant_count; ++u) {
+ total_size += config.push_constants[u].size;
+ }
+ vk_pipeline->push_constants_range = total_size;
- shader_stages[0] = (VkPipelineShaderStageCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
- .stage = VK_SHADER_STAGE_VERTEX_BIT,
- .module = shader_modules[0],
- .pName = "main"
- };
+ VkPushConstantRange pc_range = {
+ .offset = 0,
+ .size = total_size,
+ .stageFlags = VK_SHADER_STAGE_ALL,
+ };
- shader_stages[1] = (VkPipelineShaderStageCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
- .stage = VK_SHADER_STAGE_FRAGMENT_BIT,
- .module = shader_modules[1],
- .pName = "main",
- };
+ VkPipelineLayoutCreateInfo layout_info = {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
+ .pSetLayouts = &ctx->desc_layout,
+ .setLayoutCount = 1,
+ .pPushConstantRanges = (total_size > 0) ? &pc_range : NULL,
+ .pushConstantRangeCount = (total_size > 0) ? 1 : 0,
+ };
- } else if (type == REND__PIPELINE_MESH) {
- shader_count = 2;
- shader_modules[0] = rend_vk_shader_module_create(shader1, bytes1);
- shader_modules[1] = rend_vk_shader_module_create(shader2, bytes2);
+ CHECK_VK_RESULT(vkCreatePipelineLayout(vk_device.logical_device, &layout_info, vk_allocator, &vk_pipeline->layout));
- shader_stages[0] = (VkPipelineShaderStageCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
- .stage = VK_SHADER_STAGE_MESH_BIT_EXT,
- .module = shader_modules[0],
- .pName = "main"
- };
+ VkPipelineShaderStageCreateInfo shader_stages[3] = {0};
+ VkShaderModule shader_modules[3] = {0};
+ const uint8_t *shader_bytes[3] = { shader1, shader2, shader3 };
+ size_t shader_sizes[3] = { bytes1, bytes2, bytes3 };
+ uint32_t shader_count = 0;
- shader_stages[1] = (VkPipelineShaderStageCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
- .stage = VK_SHADER_STAGE_FRAGMENT_BIT,
- .module = shader_modules[1],
- .pName = "main",
- };
+ if (type != REND__PIPELINE_GRAPHICS && type != REND__PIPELINE_MESH && type != REND__PIPELINE_COMPUTE) {
+ REND__CRASH("Invalid pipeline type");
+ }
+ for (i = 0; i < 3 && vk_pipeline_stages[type][i]; ++i) {
+ shader_modules[i] = rend_vk_shader_module_create(shader_bytes[i], shader_sizes[i]);
+ shader_stages[i] = (VkPipelineShaderStageCreateInfo) {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ .stage = vk_pipeline_stages[type][i],
+ .module = shader_modules[i],
+ .pName = "main"
+ };
+ shader_count++;
+ }
- } else if (type == REND__PIPELINE_COMPUTE) {
- shader_count = 1;
- shader_modules[0] = rend_vk_shader_module_create(shader1, bytes1);
+ /*
+ * Compute Pipeline Branch
+ */
+ if (type == REND__PIPELINE_COMPUTE) {
+ VkComputePipelineCreateInfo compute_pipeline_info = {
+ .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
+ .stage = shader_stages[0],
+ .layout = vk_pipeline->layout,
+ .basePipelineHandle = VK_NULL_HANDLE,
+ .basePipelineIndex = -1,
+ };
- shader_stages[0] = (VkPipelineShaderStageCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
- .stage = VK_SHADER_STAGE_COMPUTE_BIT,
- .module = shader_modules[0],
- .pName = "main"
- };
- } else {
- REND__CRASH("Invalid pipeline type");
- }
+ CHECK_VK_RESULT(vkCreateComputePipelines(vk_device.logical_device, VK_NULL_HANDLE, 1, &compute_pipeline_info, vk_allocator, &vk_pipeline->handle));
- /*
- * Compute Pipeline Branch
- */
- if (type == REND__PIPELINE_COMPUTE) {
- VkComputePipelineCreateInfo compute_pipeline_info = {
- .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
- .stage = shader_stages[0],
- .layout = vk_pipeline->layout,
- .basePipelineHandle = VK_NULL_HANDLE,
- .basePipelineIndex = -1,
- };
+ PINFO("Successfully created compute pipeline!");
+ }
+ /*
+ * Graphics / Mesh Pipeline Branch
+ */
+ else {
+ VkPipelineRenderingCreateInfo rendering_info = {VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO};
+ rendering_info.colorAttachmentCount = 1;
+ rendering_info.pColorAttachmentFormats = &color_format;
+ rendering_info.depthAttachmentFormat = depth_format;
- CHECK_VK_RESULT(vkCreateComputePipelines(vk_device.logical_device, VK_NULL_HANDLE, 1, &compute_pipeline_info, vk_allocator, &vk_pipeline->handle));
+ VkPipelineViewportStateCreateInfo viewport_state = {VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO};
+ viewport_state.viewportCount = 1;
+ viewport_state.scissorCount = 1;
- PINFO("Successfully created compute pipeline!");
- }
- /*
- * Graphics / Mesh Pipeline Branch
- */
- else {
- VkPipelineRenderingCreateInfo rendering_info = {VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO};
- rendering_info.colorAttachmentCount = 1;
- rendering_info.pColorAttachmentFormats = &color_format;
- rendering_info.depthAttachmentFormat = depth_format;
+ VkPipelineRasterizationStateCreateInfo rasterizer = {VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO};
+ rasterizer.depthClampEnable = VK_FALSE;
+ rasterizer.rasterizerDiscardEnable = VK_FALSE;
+ rasterizer.polygonMode = vk_polymode[config.polygon_mode];
+ rasterizer.lineWidth = 1.0f;
+ rasterizer.cullMode = vk_cullflags[config.cull_mode];
+ rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE;
+ rasterizer.depthBiasEnable = VK_FALSE;
- VkPipelineViewportStateCreateInfo viewport_state = {VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO};
- viewport_state.viewportCount = 1;
- viewport_state.scissorCount = 1;
+ VkPipelineMultisampleStateCreateInfo multisampling = {VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO};
+ multisampling.sampleShadingEnable = VK_FALSE;
+ multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
- VkPipelineRasterizationStateCreateInfo rasterizer = {VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO};
- rasterizer.depthClampEnable = VK_FALSE;
- rasterizer.rasterizerDiscardEnable = VK_FALSE;
- rasterizer.polygonMode = vk_polymode[config.polygon_mode];
- rasterizer.lineWidth = 1.0f;
- rasterizer.cullMode = vk_cullflags[config.cull_mode];
- rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE;
- rasterizer.depthBiasEnable = VK_FALSE;
+ VkPipelineColorBlendAttachmentState color_blend_attachment = {0};
+ color_blend_attachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
+ color_blend_attachment.blendEnable = VK_FALSE;
- VkPipelineMultisampleStateCreateInfo multisampling = {VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO};
- multisampling.sampleShadingEnable = VK_FALSE;
- multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
+ VkPipelineColorBlendStateCreateInfo color_blending = { VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO};
+ color_blending.logicOpEnable = VK_FALSE;
+ color_blending.logicOp = VK_LOGIC_OP_COPY;
+ color_blending.attachmentCount = 1;
+ color_blending.pAttachments = &color_blend_attachment;
- VkPipelineColorBlendAttachmentState color_blend_attachment = {0};
- color_blend_attachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
- color_blend_attachment.blendEnable = VK_FALSE;
+ VkPipelineDepthStencilStateCreateInfo depth_stencil = { VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO};
+ depth_stencil.depthTestEnable = config.depth_test_enable;
+ depth_stencil.depthWriteEnable = VK_TRUE;
+ depth_stencil.depthCompareOp = VK_COMPARE_OP_LESS;
+ depth_stencil.depthBoundsTestEnable = VK_FALSE;
+ depth_stencil.stencilTestEnable = VK_FALSE;
- VkPipelineColorBlendStateCreateInfo color_blending = { VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO};
- color_blending.logicOpEnable = VK_FALSE;
- color_blending.logicOp = VK_LOGIC_OP_COPY;
- color_blending.attachmentCount = 1;
- color_blending.pAttachments = &color_blend_attachment;
+ VkDynamicState dynamic_states[] = {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR};
+ VkPipelineDynamicStateCreateInfo dynamic_state = { VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO};
+ dynamic_state.dynamicStateCount = 2;
+ dynamic_state.pDynamicStates = dynamic_states;
- VkPipelineDepthStencilStateCreateInfo depth_stencil = { VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO};
- depth_stencil.depthTestEnable = config.depth_test_enable;
- depth_stencil.depthWriteEnable = VK_TRUE;
- depth_stencil.depthCompareOp = VK_COMPARE_OP_LESS;
- depth_stencil.depthBoundsTestEnable = VK_FALSE;
- depth_stencil.stencilTestEnable = VK_FALSE;
+ VkPipelineVertexInputStateCreateInfo vertex_input_info = { VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO};
+ VkPipelineInputAssemblyStateCreateInfo input_assembly = {VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO};
+ VkVertexInputBindingDescription* vk_bindings = NULL;
+ VkVertexInputAttributeDescription* vk_attributes = NULL;
- VkDynamicState dynamic_states[] = {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR};
- VkPipelineDynamicStateCreateInfo dynamic_state = { VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO};
- dynamic_state.dynamicStateCount = 2;
- dynamic_state.pDynamicStates = dynamic_states;
+ if (type == REND__PIPELINE_GRAPHICS) {
+ uint32_t binding_count = config.vertex_binding_count;
+ uint32_t attribute_count = config.vertex_attribute_count;
- VkPipelineVertexInputStateCreateInfo vertex_input_info = { VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO};
- VkPipelineInputAssemblyStateCreateInfo input_assembly = {VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO};
- VkVertexInputBindingDescription* vk_bindings = NULL;
- VkVertexInputAttributeDescription* vk_attributes = NULL;
+ /*
+ * Bind Vertex Attributes
+ */
+ if (binding_count > 0) {
+ vk_bindings = rmalloc(sizeof(VkVertexInputBindingDescription) * binding_count);
+ for (i = 0; i < binding_count; i++) {
+ RendVertexBinding rb = config.vertex_bindings[i];
+ vk_bindings[i].binding = rb.binding;
+ vk_bindings[i].stride = rb.stride;
+ vk_bindings[i].inputRate = (rb.input_rate == REND_INPUT_RATE_INSTANCE) ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX;
+ }
+ }
- if (type == REND__PIPELINE_GRAPHICS) {
- uint32_t binding_count = config.vertex_binding_count;
- uint32_t attribute_count = config.vertex_attribute_count;
+ if (attribute_count > 0) {
+ vk_attributes = rmalloc(sizeof(VkVertexInputAttributeDescription) * attribute_count);
+ for (i = 0; i < attribute_count; i++) {
+ RendVertexAttributes ra = config.vertex_attributes[i];
+ vk_attributes[i].binding = ra.binding;
+ vk_attributes[i].location = ra.location;
+ vk_attributes[i].offset = ra.offset;
+ vk_attributes[i].format = vk_format_from_rend_format[ra.format];
+ }
+ }
- /*
- * Bind Vertex Attributes
- */
- if (binding_count > 0) {
- vk_bindings = rmalloc(sizeof(VkVertexInputBindingDescription) * binding_count);
- for (uint32_t i = 0; i < binding_count; i++) {
- RendVertexBinding rb = config.vertex_bindings[i];
- vk_bindings[i].binding = rb.binding;
- vk_bindings[i].stride = rb.stride;
- vk_bindings[i].inputRate = (rb.input_rate == REND_INPUT_RATE_INSTANCE) ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX;
- }
- }
+ vertex_input_info.vertexBindingDescriptionCount = binding_count;
+ vertex_input_info.pVertexBindingDescriptions = vk_bindings;
+ vertex_input_info.vertexAttributeDescriptionCount = attribute_count;
+ vertex_input_info.pVertexAttributeDescriptions = vk_attributes;
- if (attribute_count > 0) {
- vk_attributes = rmalloc(sizeof(VkVertexInputAttributeDescription) * attribute_count);
- for (uint32_t i = 0; i < attribute_count; i++) {
- RendVertexAttributes ra = config.vertex_attributes[i];
- vk_attributes[i].binding = ra.binding;
- vk_attributes[i].location = ra.location;
- vk_attributes[i].offset = ra.offset;
- vk_attributes[i].format = vk_format_from_rend_format[ra.format];
- }
- }
+ input_assembly.topology = vk_topology[config.topology];
+ input_assembly.primitiveRestartEnable = VK_FALSE;
+ }
- vertex_input_info.vertexBindingDescriptionCount = binding_count;
- vertex_input_info.pVertexBindingDescriptions = vk_bindings;
- vertex_input_info.vertexAttributeDescriptionCount = attribute_count;
- vertex_input_info.pVertexAttributeDescriptions = vk_attributes;
+ VkGraphicsPipelineCreateInfo pipeline_info = { VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO};
+ pipeline_info.pNext = &rendering_info;
+ pipeline_info.stageCount = shader_count;
+ pipeline_info.pStages = shader_stages;
+ pipeline_info.pVertexInputState = &vertex_input_info;
+ pipeline_info.pInputAssemblyState = &input_assembly;
+ pipeline_info.pViewportState = &viewport_state;
+ pipeline_info.pRasterizationState = &rasterizer;
+ pipeline_info.pMultisampleState = &multisampling;
+ pipeline_info.pColorBlendState = &color_blending;
+ pipeline_info.pDepthStencilState = &depth_stencil;
+ pipeline_info.pDynamicState = &dynamic_state;
+ pipeline_info.layout = vk_pipeline->layout;
+ pipeline_info.renderPass = VK_NULL_HANDLE;
- input_assembly.topology = vk_topology[config.topology];
- input_assembly.primitiveRestartEnable = VK_FALSE;
- }
+ CHECK_VK_RESULT(vkCreateGraphicsPipelines(vk_device.logical_device, VK_NULL_HANDLE, 1, &pipeline_info, vk_allocator, &vk_pipeline->handle));
- VkGraphicsPipelineCreateInfo pipeline_info = { VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO};
- pipeline_info.pNext = &rendering_info;
- pipeline_info.stageCount = shader_count;
- pipeline_info.pStages = shader_stages;
- pipeline_info.pVertexInputState = &vertex_input_info;
- pipeline_info.pInputAssemblyState = &input_assembly;
- pipeline_info.pViewportState = &viewport_state;
- pipeline_info.pRasterizationState = &rasterizer;
- pipeline_info.pMultisampleState = &multisampling;
- pipeline_info.pColorBlendState = &color_blending;
- pipeline_info.pDepthStencilState = &depth_stencil;
- pipeline_info.pDynamicState = &dynamic_state;
- pipeline_info.layout = vk_pipeline->layout;
- pipeline_info.renderPass = VK_NULL_HANDLE;
+ if (vk_bindings) rfree(vk_bindings);
+ if (vk_attributes) rfree(vk_attributes);
- CHECK_VK_RESULT(vkCreateGraphicsPipelines(vk_device.logical_device, VK_NULL_HANDLE, 1, &pipeline_info, vk_allocator, &vk_pipeline->handle));
+ }
- if (vk_bindings) rfree(vk_bindings);
- if (vk_attributes) rfree(vk_attributes);
+ /* destroy shader modules */
+ for (i = 0; i < shader_count; ++i) {
+ if (shader_modules[i] != VK_NULL_HANDLE) {
+ vkDestroyShaderModule(vk_device.logical_device, shader_modules[i], vk_allocator);
+ }
+ }
- }
-
- /* destroy shader modules */
- for (uint32_t i = 0; i < shader_count; ++i) {
- if (shader_modules[i] != VK_NULL_HANDLE) {
- vkDestroyShaderModule(vk_device.logical_device, shader_modules[i], vk_allocator);
- }
- }
-
- return true;
+ return true;
}
-extern void
+void
rend_vk_pipeline_bind(RendPipeline pipeline)
{
- RendVk14Context *ctx = pipeline->backend_ctx;
- RendVkPipeline vk_pipeline = ctx->pipelines[pipeline->idx];
- VkCommandBuffer cmd = ctx->frame_resources[ctx->frame_index].command_buffer;
- VkPipelineBindPoint bind_point = (pipeline->type == REND__PIPELINE_COMPUTE) ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS;
- vkCmdBindPipeline(cmd, bind_point, vk_pipeline.handle);
- vkCmdBindDescriptorSets(cmd, bind_point, vk_pipeline.layout, 0, 1, &ctx->desc_set, 0, NULL);
+ RendVk14Context *ctx = pipeline->backend_ctx;
+ RendVkPipeline vk_pipeline = ctx->pipelines[pipeline->idx];
+ VkCommandBuffer cmd = ctx->frame_resources[ctx->frame_index].command_buffer;
+ VkPipelineBindPoint bind_point = (pipeline->type == REND__PIPELINE_COMPUTE) ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS;
+ vkCmdBindPipeline(cmd, bind_point, vk_pipeline.handle);
+ vkCmdBindDescriptorSets(cmd, bind_point, vk_pipeline.layout, 0, 1, &ctx->desc_set, 0, NULL);
}
-extern void
+void
rend_vk_pipeline_push_constants(RendPipeline pipeline, void *push_data, size_t size)
{
- RASSERT(pipeline && push_data);
+ RASSERT(pipeline && push_data);
- RendVk14Context *ctx = pipeline->backend_ctx;
- RendVkPipeline p = ctx->pipelines[pipeline->idx];
- RASSERT(size <= p.push_constants_range && "Size exceeds bound push constant range!");
- vkCmdPushConstants(ctx->frame_resources[ctx->frame_index].command_buffer, p.layout, VK_SHADER_STAGE_ALL, 0, size, push_data);
+ RendVk14Context *ctx = pipeline->backend_ctx;
+ RendVkPipeline p = ctx->pipelines[pipeline->idx];
+ RASSERT(size <= p.push_constants_range && "Size exceeds bound push constant range!");
+ vkCmdPushConstants(ctx->frame_resources[ctx->frame_index].command_buffer, p.layout, VK_SHADER_STAGE_ALL, 0, size, push_data);
}
-extern void
+void
rend_vk_pipeline_bind_vertex_buffer(RendPipeline pipeline, uint32_t binding, RendBuffer buffer, size_t offset)
{
- RendVk14Context *ctx = pipeline->backend_ctx;
- VkBuffer buf = (VkBuffer)(uintptr_t)buffer.handle;
- VkCommandBuffer cmd = ctx->frame_resources[ctx->frame_index].command_buffer;
-
- VkDeviceSize vk_offset = (VkDeviceSize)offset;
- vkCmdBindVertexBuffers(cmd, binding, 1, &buf, &vk_offset);
+ RendVk14Context *ctx = pipeline->backend_ctx;
+ VkBuffer buf = (VkBuffer)(uintptr_t)buffer.handle;
+ VkCommandBuffer cmd = ctx->frame_resources[ctx->frame_index].command_buffer;
+
+ VkDeviceSize vk_offset = (VkDeviceSize)offset;
+ vkCmdBindVertexBuffers(cmd, binding, 1, &buf, &vk_offset);
}
-extern void
+void
rend_vk_pipeline_bind_index_buffer(RendPipeline pipeline, RendBuffer buffer, size_t offset, RendIndexType index_type)
{
- RendVk14Context *ctx = pipeline->backend_ctx;
- VkBuffer buf = (VkBuffer)(uintptr_t)buffer.handle;
- VkCommandBuffer cmd = ctx->frame_resources[ctx->frame_index].command_buffer;
-
- VkIndexType vk_index_type = (index_type == REND_INDEX_UINT16) ? VK_INDEX_TYPE_UINT16 : VK_INDEX_TYPE_UINT32;
-
- vkCmdBindIndexBuffer(cmd, buf, (VkDeviceSize)offset, vk_index_type);
+ RendVk14Context *ctx = pipeline->backend_ctx;
+ VkBuffer buf = (VkBuffer)(uintptr_t)buffer.handle;
+ VkCommandBuffer cmd = ctx->frame_resources[ctx->frame_index].command_buffer;
+
+ VkIndexType vk_index_type = (index_type == REND_INDEX_UINT16) ? VK_INDEX_TYPE_UINT16 : VK_INDEX_TYPE_UINT32;
+
+ vkCmdBindIndexBuffer(cmd, buf, (VkDeviceSize)offset, vk_index_type);
}
-extern void
-rend_vk_descriptor_write_texture(void *ctx, RendTexture *texture, uint32_t binding, uint32_t slot)
+void
+rend_vk_descriptor_write_texture(RendContextHandle handle, RendTexture *texture, uint32_t binding, uint32_t slot)
{
- RendVk14Context *vk_ctx = (RendVk14Context*) ctx;
+ RendVk14Context *vk_ctx = (RendVk14Context *)handle;
- VkDescriptorImageInfo image_info = {
- .sampler = (VkSampler) texture->sampler,
- .imageView = (VkImageView) texture->view,
- .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
- };
+ VkDescriptorImageInfo image_info = {
+ .sampler = (VkSampler)texture->sampler,
+ .imageView = (VkImageView)texture->view,
+ .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
+ };
- VkWriteDescriptorSet descriptor_write = {
- .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
- .dstSet = vk_ctx->desc_set,
- .dstBinding = binding,
- .dstArrayElement = slot, // write texture to slot
- .descriptorCount = 1,
- .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
- .pImageInfo = &image_info,
- };
+ VkWriteDescriptorSet descriptor_write = {
+ .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
+ .dstSet = vk_ctx->desc_set,
+ .dstBinding = binding,
+ .dstArrayElement = slot, /* write texture to slot */
+ .descriptorCount = 1,
+ .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
+ .pImageInfo = &image_info,
+ };
- vkUpdateDescriptorSets(vk_device.logical_device, 1, &descriptor_write, 0, NULL);
+ vkUpdateDescriptorSets(vk_device.logical_device, 1, &descriptor_write, 0, NULL);
}
-extern void
+void
rend_vk_pipeline_dispatch(RendPipeline pipeline, uint32_t x, uint32_t y, uint32_t z)
{
- RendVk14Context *ctx = pipeline->backend_ctx;
- VkCommandBuffer cmd = ctx->frame_resources[ctx->frame_index].command_buffer;
- vkCmdDispatch(cmd, x, y, z);
+ RendVk14Context *ctx = pipeline->backend_ctx;
+ VkCommandBuffer cmd = ctx->frame_resources[ctx->frame_index].command_buffer;
+ vkCmdDispatch(cmd, x, y, z);
}
-extern void
+void
rend_vk_pipeline_draw(RendPipeline pipeline, size_t count, uint32_t instance_count)
{
- RendVk14Context *ctx = pipeline->backend_ctx;
- VkCommandBuffer cmd = ctx->frame_resources[ctx->frame_index].command_buffer;
- vkCmdDraw(cmd, count, instance_count, 0, 0);
+ RendVk14Context *ctx = pipeline->backend_ctx;
+ VkCommandBuffer cmd = ctx->frame_resources[ctx->frame_index].command_buffer;
+ vkCmdDraw(cmd, count, instance_count, 0, 0);
}
-extern void
+void
rend_vk_pipeline_draw_indexed(RendPipeline pipeline, uint32_t index_count, uint32_t first_index, int32_t vertex_offset, uint32_t instance_count)
{
- RendVk14Context *ctx = pipeline->backend_ctx;
- VkCommandBuffer cmd = ctx->frame_resources[ctx->frame_index].command_buffer;
- vkCmdDrawIndexed(cmd, index_count, instance_count, first_index, vertex_offset, 0);
+ RendVk14Context *ctx = pipeline->backend_ctx;
+ VkCommandBuffer cmd = ctx->frame_resources[ctx->frame_index].command_buffer;
+ vkCmdDrawIndexed(cmd, index_count, instance_count, first_index, vertex_offset, 0);
}
-extern void
+void
rend_vk_pipeline_set_blend(RendPipeline pipeline, bool blend)
{
- RendVk14Context *ctx = pipeline->backend_ctx;
- RendVkPipeline *vk_pipeline = &ctx->pipelines[pipeline->idx];
- vk_pipeline->blend_enable = blend;
+ RendVk14Context *ctx = pipeline->backend_ctx;
+ RendVkPipeline *vk_pipeline = &ctx->pipelines[pipeline->idx];
+ vk_pipeline->blend_enable = blend;
}
-extern void
-rend_vk_pipeline_draw_instanced(RendPipeline pipeline, uint32_t index_count, uint32_t instance_count)
-{
- RendVk14Context *ctx = pipeline->backend_ctx;
- VkCommandBuffer cmd = ctx->frame_resources[ctx->frame_index].command_buffer;
- vkCmdDraw(cmd, index_count, instance_count, 0, 0);
-}
-
-extern VKAPI_ATTR VkBool32 VKAPI_CALL
+VKAPI_ATTR VkBool32 VKAPI_CALL
rend_vk_debug_func(VkDebugUtilsMessageSeverityFlagBitsEXT message_severity, VkDebugUtilsMessageTypeFlagsEXT message_types, const VkDebugUtilsMessengerCallbackDataEXT *callback_data, void *user_data)
{
- switch (message_severity) {
- default:
- case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT:
- PERROR(callback_data->pMessage);
- break;
- case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT:
- PWARN(callback_data->pMessage);
- break;
- case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT:
- PINFO(callback_data->pMessage);
- break;
- case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT:
- PTRACE(callback_data->pMessage);
- break;
- }
- return VK_FALSE;
+ switch (message_severity) {
+ default:
+ case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT:
+ PERROR(callback_data->pMessage);
+ break;
+ case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT:
+ PWARN(callback_data->pMessage);
+ break;
+ case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT:
+ PINFO(callback_data->pMessage);
+ break;
+ case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT:
+ PTRACE(callback_data->pMessage);
+ break;
+ }
+ return VK_FALSE;
}
@@ -1908,278 +1677,280 @@ rend_vk_debug_func(VkDebugUtilsMessageSeverityFlagBitsEXT message_severity, VkDe
static void
rend_vk_pipeline_destroy(RendVkPipeline *pipeline)
{
- VkDevice dev = vk_device.logical_device;
+ VkDevice dev = vk_device.logical_device;
- if (pipeline->handle != VK_NULL_HANDLE) {
- vkDestroyPipeline(dev, pipeline->handle, vk_allocator);
- }
+ if (pipeline->handle != VK_NULL_HANDLE) {
+ vkDestroyPipeline(dev, pipeline->handle, vk_allocator);
+ }
- if (pipeline->layout != VK_NULL_HANDLE) {
- vkDestroyPipelineLayout(dev, pipeline->layout, vk_allocator);
- }
+ if (pipeline->layout != VK_NULL_HANDLE) {
+ vkDestroyPipelineLayout(dev, pipeline->layout, vk_allocator);
+ }
}
static void
rend_vk_swapchain_create(RendVk14Context *ctx, RendVkSwapchain *swapchain)
{
- RASSERT(ctx && "No context provided.");
- RASSERT(swapchain && "No swapchain provided.");
+ uint32_t i;
+ RASSERT(ctx && "No context provided.");
+ RASSERT(swapchain && "No swapchain provided.");
- VkSurfaceCapabilitiesKHR surface_caps;
- uint32_t width;
- uint32_t height;
- VkExtent2D swapchain_extent;
+ VkSurfaceCapabilitiesKHR surface_caps;
+ uint32_t width;
+ uint32_t height;
+ VkExtent2D swapchain_extent;
- vkGetPhysicalDeviceSurfaceCapabilitiesKHR(vk_device.physical_device, ctx->surface, &surface_caps);
- width = surface_caps.currentExtent.width;
- height = surface_caps.currentExtent.height;
+ vkGetPhysicalDeviceSurfaceCapabilitiesKHR(vk_device.physical_device, ctx->surface, &surface_caps);
+ width = surface_caps.currentExtent.width;
+ height = surface_caps.currentExtent.height;
- /* 0xffffffff means the surface size is defined by the swapchain extent */
- if (width == 0xffffffffu || height == 0xffffffffu) {
- width = ctx->window ? ctx->window->width : 0;
- height = ctx->window ? ctx->window->height : 0;
- }
- if (width == 0) width = 1;
- if (height == 0) height = 1;
+ /* 0xffffffff means the surface size is defined by the swapchain extent */
+ if (width == 0xffffffffu || height == 0xffffffffu) {
+ width = ctx->window ? ctx->window->width : 0;
+ height = ctx->window ? ctx->window->height : 0;
+ }
+ if (width == 0) width = 1;
+ if (height == 0) height = 1;
- swapchain_extent = (VkExtent2D){width, height};
+ swapchain_extent = (VkExtent2D){width, height};
- ctx->max_frames_in_flight = REND_MIN_FRAMES_IN_FLIGHT;
+ ctx->max_frames_in_flight = REND_MIN_FRAMES_IN_FLIGHT;
- if (surface_caps.minImageCount > ctx->max_frames_in_flight) {
- ctx->max_frames_in_flight = surface_caps.minImageCount;
- }
+ if (surface_caps.minImageCount > ctx->max_frames_in_flight) {
+ ctx->max_frames_in_flight = surface_caps.minImageCount;
+ }
- /* maxImageCount == 0 means there is no maximum */
- if (surface_caps.maxImageCount > 0 && surface_caps.maxImageCount < ctx->max_frames_in_flight) {
- ctx->max_frames_in_flight = surface_caps.maxImageCount;
- }
- if (ctx->max_frames_in_flight > REND_MAX_FRAMES_IN_FLIGHT) {
- ctx->max_frames_in_flight = REND_MAX_FRAMES_IN_FLIGHT;
- }
- if (ctx->max_frames_in_flight == 0) {
- ctx->max_frames_in_flight = 1;
- }
+ /* maxImageCount == 0 means there is no maximum */
+ if (surface_caps.maxImageCount > 0 && surface_caps.maxImageCount < ctx->max_frames_in_flight) {
+ ctx->max_frames_in_flight = surface_caps.maxImageCount;
+ }
+ if (ctx->max_frames_in_flight > REND_MAX_FRAMES_IN_FLIGHT) {
+ ctx->max_frames_in_flight = REND_MAX_FRAMES_IN_FLIGHT;
+ }
+ if (ctx->max_frames_in_flight == 0) {
+ ctx->max_frames_in_flight = 1;
+ }
- bool found = false;
- for (uint32_t i = 0; i < vk_device.swapchain_support.format_count; i++) {
- VkSurfaceFormatKHR format = vk_device.swapchain_support.format[i];
+ bool found = false;
+ for (i = 0; i < vk_device.swapchain_support.format_count; i++) {
+ VkSurfaceFormatKHR format = vk_device.swapchain_support.format[i];
- /* preferred format */
- if (format.format == VK_FORMAT_B8G8R8A8_UNORM &&
- format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
- swapchain->format = format;
- found = true;
- break;
- }
- }
+ /* preferred format */
+ if (format.format == VK_FORMAT_B8G8R8A8_UNORM &&
+ format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
+ swapchain->format = format;
+ found = true;
+ break;
+ }
+ }
- /* default format */
- if (!found) {
- swapchain->format = vk_device.swapchain_support.format[0];
- }
+ /* default format */
+ if (!found) {
+ swapchain->format = vk_device.swapchain_support.format[0];
+ }
- /* NOTE: mailbox is probably the best for most applications
- * but I may want the ability to pick a different mode in
- * very niche circumstances.
- *
- * We also may want immediate mode if we want to disable VSYNC.
- */
+ /* NOTE: mailbox is probably the best for most applications
+ * but I may want the ability to pick a different mode in
+ * very niche circumstances.
+ *
+ * We also may want immediate mode if we want to disable VSYNC.
+ */
- /* default present mode */
- VkPresentModeKHR present_mode = VK_PRESENT_MODE_FIFO_KHR;
- for (uint32_t i = 0; i < vk_device.swapchain_support.present_mode_count; i++) {
- VkPresentModeKHR pres = vk_device.swapchain_support.present_modes[i];
- /* preferred format is mailbox */
- if (ctx->vsync) {
- if (pres == VK_PRESENT_MODE_MAILBOX_KHR) {
- present_mode = pres;
- break;
- }
- } else {
- if (pres == VK_PRESENT_MODE_IMMEDIATE_KHR) {
- present_mode = pres;
- break;
- }
- }
- }
+ /* default present mode */
+ VkPresentModeKHR present_mode = VK_PRESENT_MODE_FIFO_KHR;
+ for (i = 0; i < vk_device.swapchain_support.present_mode_count; i++) {
+ VkPresentModeKHR pres = vk_device.swapchain_support.present_modes[i];
+ /* preferred format is mailbox */
+ if (ctx->vsync) {
+ if (pres == VK_PRESENT_MODE_MAILBOX_KHR) {
+ present_mode = pres;
+ break;
+ }
+ } else {
+ if (pres == VK_PRESENT_MODE_IMMEDIATE_KHR) {
+ present_mode = pres;
+ break;
+ }
+ }
+ }
#ifdef REND_DEBUG
- static const char* present_mode_names[] = {
- [VK_PRESENT_MODE_IMMEDIATE_KHR] = "IMMEDIATE",
- [VK_PRESENT_MODE_MAILBOX_KHR] = "MAILBOX",
- [VK_PRESENT_MODE_FIFO_KHR] = "FIFO",
- [VK_PRESENT_MODE_FIFO_RELAXED_KHR] = "FIFO_RELAXED"
- };
- PDEBUG("Present mode %s was chosen!", present_mode_names[present_mode]);
+ static const char* present_mode_names[] = {
+ [VK_PRESENT_MODE_IMMEDIATE_KHR] = "IMMEDIATE",
+ [VK_PRESENT_MODE_MAILBOX_KHR] = "MAILBOX",
+ [VK_PRESENT_MODE_FIFO_KHR] = "FIFO",
+ [VK_PRESENT_MODE_FIFO_RELAXED_KHR] = "FIFO_RELAXED"
+ };
+ PDEBUG("Present mode %s was chosen!", present_mode_names[present_mode]);
#endif
- VkExtent2D min = surface_caps.minImageExtent;
- VkExtent2D max = surface_caps.maxImageExtent;
- swapchain_extent.width = (swapchain_extent.width < min.width) ? min.width : swapchain_extent.width;
- swapchain_extent.width = (swapchain_extent.width > max.width) ? max.width : swapchain_extent.width;
- swapchain_extent.height = (swapchain_extent.height < min.height) ? min.height : swapchain_extent.height;
- swapchain_extent.height = (swapchain_extent.height > max.height) ? max.height : swapchain_extent.height;
+ VkExtent2D min = surface_caps.minImageExtent;
+ VkExtent2D max = surface_caps.maxImageExtent;
+ swapchain_extent.width = (swapchain_extent.width < min.width) ? min.width : swapchain_extent.width;
+ swapchain_extent.width = (swapchain_extent.width > max.width) ? max.width : swapchain_extent.width;
+ swapchain_extent.height = (swapchain_extent.height < min.height) ? min.height : swapchain_extent.height;
+ swapchain_extent.height = (swapchain_extent.height > max.height) ? max.height : swapchain_extent.height;
- uint32_t img_count = surface_caps.minImageCount + 1;
- if (surface_caps.maxImageCount > 0 && img_count > surface_caps.maxImageCount) {
- img_count = surface_caps.maxImageCount;
- }
+ uint32_t img_count = surface_caps.minImageCount + 1;
+ if (surface_caps.maxImageCount > 0 && img_count > surface_caps.maxImageCount) {
+ img_count = surface_caps.maxImageCount;
+ }
- VkSwapchainCreateInfoKHR swapchain_create_info = { VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR};
- swapchain_create_info.surface = ctx->surface;
- swapchain_create_info.minImageCount = img_count;
- swapchain_create_info.imageFormat = swapchain->format.format;
- swapchain_create_info.imageColorSpace = swapchain->format.colorSpace;
- swapchain_create_info.imageExtent = swapchain_extent;
- swapchain_create_info.imageArrayLayers = 1;
- swapchain_create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+ VkSwapchainCreateInfoKHR swapchain_create_info = { VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR};
+ swapchain_create_info.surface = ctx->surface;
+ swapchain_create_info.minImageCount = img_count;
+ swapchain_create_info.imageFormat = swapchain->format.format;
+ swapchain_create_info.imageColorSpace = swapchain->format.colorSpace;
+ swapchain_create_info.imageExtent = swapchain_extent;
+ swapchain_create_info.imageArrayLayers = 1;
+ swapchain_create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
- /* index sharing */
- if (vk_device.graphics_family_index != vk_device.present_family_index) {
- uint32_t queueFamilyIndices[] = {vk_device.graphics_family_index, vk_device.present_family_index};
- swapchain_create_info.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
- swapchain_create_info.queueFamilyIndexCount = 2;
- swapchain_create_info.pQueueFamilyIndices = queueFamilyIndices;
- } else {
- swapchain_create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
- swapchain_create_info.queueFamilyIndexCount = 0;
- swapchain_create_info.pQueueFamilyIndices = 0;
- }
+ /* index sharing */
+ if (vk_device.graphics_family_index != vk_device.present_family_index) {
+ uint32_t queueFamilyIndices[] = {vk_device.graphics_family_index, vk_device.present_family_index};
+ swapchain_create_info.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
+ swapchain_create_info.queueFamilyIndexCount = 2;
+ swapchain_create_info.pQueueFamilyIndices = queueFamilyIndices;
+ } else {
+ swapchain_create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ swapchain_create_info.queueFamilyIndexCount = 0;
+ swapchain_create_info.pQueueFamilyIndices = 0;
+ }
- swapchain_create_info.preTransform = surface_caps.currentTransform;
- swapchain_create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
- swapchain_create_info.presentMode = present_mode;
- swapchain_create_info.clipped = VK_TRUE;
- swapchain_create_info.oldSwapchain = 0;
+ swapchain_create_info.preTransform = surface_caps.currentTransform;
+ swapchain_create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
+ swapchain_create_info.presentMode = present_mode;
+ swapchain_create_info.clipped = VK_TRUE;
+ swapchain_create_info.oldSwapchain = 0;
- if (vkCreateSwapchainKHR(vk_device.logical_device, &swapchain_create_info, vk_allocator, &swapchain->handle) != VK_SUCCESS) {
- REND__CRASH("Swapchain creation failed, you are probably trying to create two renderers for the same surface!");
- }
+ if (vkCreateSwapchainKHR(vk_device.logical_device, &swapchain_create_info, vk_allocator, &swapchain->handle) != VK_SUCCESS) {
+ REND__CRASH("Swapchain creation failed, you are probably trying to create two renderers for the same surface!");
+ }
- swapchain->image_count = 0;
- CHECK_VK_RESULT(vkGetSwapchainImagesKHR(vk_device.logical_device, swapchain->handle, &swapchain->image_count, 0));
+ swapchain->image_count = 0;
+ CHECK_VK_RESULT(vkGetSwapchainImagesKHR(vk_device.logical_device, swapchain->handle, &swapchain->image_count, 0));
- if (!swapchain->images) {
- swapchain->images = rmalloc(swapchain->image_count * sizeof *swapchain->images);
- }
- if (!swapchain->views) {
- swapchain->views = rmalloc(swapchain->image_count * sizeof *swapchain->views);
- }
+ if (!swapchain->images) {
+ swapchain->images = rmalloc(swapchain->image_count * sizeof(*swapchain->images));
+ }
+ if (!swapchain->views) {
+ swapchain->views = rmalloc(swapchain->image_count * sizeof(*swapchain->views));
+ }
- CHECK_VK_RESULT( vkGetSwapchainImagesKHR(vk_device.logical_device, swapchain->handle, &swapchain->image_count, swapchain->images));
+ CHECK_VK_RESULT( vkGetSwapchainImagesKHR(vk_device.logical_device, swapchain->handle, &swapchain->image_count, swapchain->images));
- for (uint32_t i = 0; i < swapchain->image_count; i++) {
+ for (i = 0; i < swapchain->image_count; i++) {
- VkImageViewCreateInfo view_info = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO};
- view_info.image = swapchain->images[i];
- view_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
- view_info.format = swapchain->format.format;
- view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- view_info.subresourceRange.baseMipLevel = 0;
- view_info.subresourceRange.levelCount = 1;
- view_info.subresourceRange.baseArrayLayer = 0;
- view_info.subresourceRange.layerCount = 1;
+ VkImageViewCreateInfo view_info = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO};
+ view_info.image = swapchain->images[i];
+ view_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
+ view_info.format = swapchain->format.format;
+ view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ view_info.subresourceRange.baseMipLevel = 0;
+ view_info.subresourceRange.levelCount = 1;
+ view_info.subresourceRange.baseArrayLayer = 0;
+ view_info.subresourceRange.layerCount = 1;
- CHECK_VK_RESULT(vkCreateImageView(vk_device.logical_device, &view_info, vk_allocator, &swapchain->views[i]));
- }
+ CHECK_VK_RESULT(vkCreateImageView(vk_device.logical_device, &view_info, vk_allocator, &swapchain->views[i]));
+ }
- /* depth resources */
- if (!rend_vk_device_detect_depth_format(&vk_device)) {
- vk_device.depth_format = VK_FORMAT_UNDEFINED;
- PFATAL("Failed to find a supported depth buffer format!");
- }
+ /* depth resources */
+ if (!rend_vk_device_detect_depth_format(&vk_device)) {
+ vk_device.depth_format = VK_FORMAT_UNDEFINED;
+ PFATAL("Failed to find a supported depth buffer format!");
+ }
- swapchain->depth_attachment = rend_vk_image_create(
- vk_device.logical_device,
- VK_IMAGE_TYPE_2D,
- swapchain_extent.width, swapchain_extent.height,
- vk_device.depth_format,
- VK_IMAGE_TILING_OPTIMAL,
- VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
- VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
- 1, // depth
- 1, // mip level
- 1, // layers
- VK_SAMPLE_COUNT_1_BIT,
- VK_SHARING_MODE_EXCLUSIVE
- );
+ swapchain->depth_attachment = rend_vk_image_create(
+ vk_device.logical_device,
+ VK_IMAGE_TYPE_2D,
+ swapchain_extent.width, swapchain_extent.height,
+ vk_device.depth_format,
+ VK_IMAGE_TILING_OPTIMAL,
+ VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
+ 1, /* depth */
+ 1, /* mip level */
+ 1, /* layers */
+ VK_SAMPLE_COUNT_1_BIT,
+ VK_SHARING_MODE_EXCLUSIVE
+ );
- uint32_t mem_type = rend_vk_image_required_memory_type(&swapchain->depth_attachment);
- uint32_t depth_index = rend_vk_get_heap_index(mem_type, vk_device.device_index);
+ uint32_t mem_type = rend_vk_image_required_memory_type(&swapchain->depth_attachment);
+ uint32_t depth_index = rend_vk_get_heap_index(mem_type, vk_device.device_index);
- RASSERT(ctx);
- RendMemory depth_mem = rend_vk_arena_alloc(&ctx->arena_persistent, swapchain->depth_attachment.requirements.size, depth_index);
+ RASSERT(ctx);
+ RendMemory depth_mem = rend_vk_arena_alloc(&ctx->arena_persistent, swapchain->depth_attachment.requirements.size, depth_index);
- rend_vk_image_bind_memory(&swapchain->depth_attachment, &depth_mem);
+ rend_vk_image_bind_memory(&swapchain->depth_attachment, &depth_mem);
- rend_vk_image_view_create(
- &swapchain->depth_attachment,
- VK_IMAGE_VIEW_TYPE_2D,
- VK_IMAGE_ASPECT_DEPTH_BIT
- );
+ rend_vk_image_view_create(
+ &swapchain->depth_attachment,
+ VK_IMAGE_VIEW_TYPE_2D,
+ VK_IMAGE_ASPECT_DEPTH_BIT
+ );
- swapchain->extent = swapchain_extent;
+ swapchain->extent = swapchain_extent;
}
static void
rend_vk_swapchain_destroy(RendVk14Context *ctx, RendVkSwapchain *swapchain)
{
- if (!swapchain || swapchain->handle == VK_NULL_HANDLE) return;
- RASSERT(vk_device.logical_device);
+ uint32_t i;
+ if (!swapchain || swapchain->handle == VK_NULL_HANDLE) return;
+ RASSERT(vk_device.logical_device);
- rend_vk_image_destroy(&swapchain->depth_attachment);
+ rend_vk_image_destroy(&swapchain->depth_attachment);
- if (swapchain->views) {
- for (uint32_t i = 0; i < swapchain->image_count; i++) {
- vkDestroyImageView(vk_device.logical_device, swapchain->views[i], vk_allocator);
- }
- rfree(swapchain->views);
- swapchain->views = 0;
- }
+ if (swapchain->views) {
+ for (i = 0; i < swapchain->image_count; i++) {
+ vkDestroyImageView(vk_device.logical_device, swapchain->views[i], vk_allocator);
+ }
+ rfree(swapchain->views);
+ swapchain->views = 0;
+ }
- if (swapchain->images) {
- rfree(swapchain->images);
- swapchain->images = 0;
- }
+ if (swapchain->images) {
+ rfree(swapchain->images);
+ swapchain->images = 0;
+ }
- swapchain->image_count = 0;
- vkDestroySwapchainKHR(vk_device.logical_device, swapchain->handle, vk_allocator);
- swapchain->handle = VK_NULL_HANDLE;
+ swapchain->image_count = 0;
+ vkDestroySwapchainKHR(vk_device.logical_device, swapchain->handle, vk_allocator);
+ swapchain->handle = VK_NULL_HANDLE;
}
static VkShaderModule
rend_vk_shader_module_create(const void *data, size_t size)
{
- VkShaderModuleCreateInfo create_info = { VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO};
- create_info.codeSize = size;
- create_info.pCode = (const uint32_t *)data;
+ VkShaderModuleCreateInfo create_info = { VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO};
+ create_info.codeSize = size;
+ create_info.pCode = (const uint32_t *)data;
+
+ VkShaderModule module;
+ VkResult res = vkCreateShaderModule(vk_device.logical_device, &create_info, vk_allocator, &module);
- VkShaderModule module;
- VkResult res = vkCreateShaderModule(vk_device.logical_device, &create_info, vk_allocator, &module);
+ if (res != VK_SUCCESS) {
+ PWARN("Failed to create shader module for %p", data);
+ return VK_NULL_HANDLE;
+ }
- if (res != VK_SUCCESS) {
- PWARN("Failed to create shader module for %p", data);
- return VK_NULL_HANDLE;
- }
-
- return module;
+ return module;
}
static uint32_t
rend_vk_get_heap_index(uint32_t memory_type_bits, uint32_t preferred_index)
{
- if (memory_type_bits & (1u << preferred_index)) {
- return preferred_index;
- }
+ uint32_t i;
+ if (memory_type_bits & (1u << preferred_index)) {
+ return preferred_index;
+ }
- for (uint32_t i = 0; i < 32; i++) {
- if (memory_type_bits & (1u << i)) {
- return i;
- }
- }
+ for (i = 0; i < 32; i++) {
+ if (memory_type_bits & (1u << i)) {
+ return i;
+ }
+ }
- return UINT32_MAX;
+ return UINT32_MAX;
}
diff --git a/Rend/rend_vk_allocator.c b/Rend/rend_vk_allocator.c
deleted file mode 100644
index 737e566..0000000
--- a/Rend/rend_vk_allocator.c
+++ /dev/null
@@ -1,118 +0,0 @@
-#pragma once
-#include "rend_internal.h"
-#include <stdint.h>
-#include <vulkan/vulkan.h>
-#include <vulkan/vulkan_core.h>
-
-typedef struct RendVkAllocatorState {
- const char *name;
-} RendVkAllocatorState;
-
-typedef struct RendVkAllocatorHeader {
- uint32_t offset;
-} RendVkAllocatorHeader;
-
-static bool rend_vk_allocator_is_power_of_two(uintptr_t x);
-static void *rend_vk_allocator_alloc(void *pUserData, size_t size, size_t alignment, VkSystemAllocationScope allocationScope);
-static void *rend_vk_allocator_realloc(void *pUserData, void *pOriginal, size_t size, size_t alignment, VkSystemAllocationScope allocationScope);
-static void rend_vk_allocator_free(void *pUserData, void *pMemory);
-static void rend_vk_allocator_internal_notification(void *pUserData, size_t size, VkInternalAllocationType allocationType, VkSystemAllocationScope allocationScope);
-static void rend_vk_allocator_free_notification(void *pUserData, size_t size, VkInternalAllocationType allocationType, VkSystemAllocationScope allocationScope);
-
-static VkAllocationCallbacks rend_vk_allocator = {
- .pfnAllocation = rend_vk_allocator_alloc,
- .pfnReallocation = rend_vk_allocator_realloc,
- .pfnFree = rend_vk_allocator_free,
- .pfnInternalAllocation = rend_vk_allocator_internal_notification,
- .pfnInternalFree = rend_vk_allocator_free_notification,
-};
-
-static const char* rend_vk_allocator_scope_name[] = {
- [VK_SYSTEM_ALLOCATION_SCOPE_CACHE] = "Cache",
- [VK_SYSTEM_ALLOCATION_SCOPE_COMMAND] = "Command",
- [VK_SYSTEM_ALLOCATION_SCOPE_DEVICE] = "Device",
- [VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE] = "Instance",
- [VK_SYSTEM_ALLOCATION_SCOPE_OBJECT] = "Object",
-};
-
-
-static bool
-rend_vk_allocator_is_power_of_two(uintptr_t x)
-{
- return (x & (x-1)) == 0;
-}
-
-static uintptr_t
-rend_vk_allocator_align_forward(uintptr_t ptr, size_t align)
-{
- uintptr_t p, a, modulo;
-
- assert(rend_vk_allocator_is_power_of_two(align));
-
- p = ptr;
- a = (uintptr_t)align;
- modulo = p & (a-1);
-
- if (modulo != 0) {
- p += a - modulo;
- }
- return p;
-}
-
-static void*
-rend_vk_allocator_alloc(void *pUserData, size_t size, size_t alignment, VkSystemAllocationScope allocationScope)
-{
- size_t total_size = size + alignment + sizeof (RendVkAllocatorHeader);
- uint8_t *raw_ptr = malloc(total_size);
- uintptr_t unaligned_addr = (uintptr_t)(raw_ptr + sizeof (RendVkAllocatorHeader));
-
- uint8_t *aligned_ptr = (uint8_t*)rend_vk_allocator_align_forward(unaligned_addr, alignment);
- RendVkAllocatorHeader *header = (RendVkAllocatorHeader*) aligned_ptr - 1;
- header->offset = aligned_ptr - raw_ptr;
-
- PDEBUG("[VK_ALLOC] %p - bytes %lu with alignment %lu - scope %s",
- aligned_ptr, size, alignment, rend_vk_allocator_scope_name[allocationScope]);
-
- return (void*) aligned_ptr;
-}
-
-static void*
-rend_vk_allocator_realloc(void *pUserData, void *pOriginal, size_t size, size_t alignment, VkSystemAllocationScope allocationScope)
-{
- if (!pOriginal) return rend_vk_allocator_alloc(pUserData, size, alignment, allocationScope);
- if (size == 0) {
- rend_vk_allocator_free(pUserData, pOriginal);
- return NULL;
- }
- void *new_ptr = rend_vk_allocator_alloc(pUserData, size, alignment, allocationScope);
- if (!new_ptr) return NULL;
- memcpy(new_ptr, pOriginal, size);
- rend_vk_allocator_free(pUserData, pOriginal);
- return new_ptr;
-}
-
-static void
-rend_vk_allocator_free(void *pUserData, void *pMemory)
-{
- RendVkAllocatorHeader *ptr = pMemory;
- uint8_t *raw_ptr = pMemory;
- raw_ptr -= (ptr-1)->offset;
-
- PDEBUG("[VK_FREE] %p", ptr);
- free(raw_ptr);
-}
-
-static void
-rend_vk_allocator_internal_notification(void *pUserData, size_t size, VkInternalAllocationType allocationType, VkSystemAllocationScope allocationScope)
-{
- PDEBUG("[VK_ALLOC_INTERNAL] bytes %lu - scope %s",
- size, rend_vk_allocator_scope_name[allocationScope]);
-
-}
-
-static void
-rend_vk_allocator_free_notification(void *pUserData, size_t size, VkInternalAllocationType allocationType, VkSystemAllocationScope allocationScope)
-{
- PDEBUG("[VK_FREE_INTERNAL] bytes %lu - scope %s",
- size, rend_vk_allocator_scope_name[allocationScope]);
-}
diff --git a/Rend/rend_vk_arena.c b/Rend/rend_vk_arena.c
deleted file mode 100644
index b936be4..0000000
--- a/Rend/rend_vk_arena.c
+++ /dev/null
@@ -1,264 +0,0 @@
-#pragma once
-#include "rend_internal.h"
-#include "rend_vk_internal.h"
-#include <vulkan/vulkan_core.h>
-
-/* arenas need to be subdivided into blocks
- * just like pools because we must respect page size */
-typedef struct RendVkPage {
- RendMemory memory;
- size_t head;
- int reserved;
-} RendVkPage;
-
-typedef struct RendVkPagedArena {
- RendVkPage *page_darr;
- uint32_t capacity;
- uint32_t elements;
-} RendVkPagedArena;
-
-struct RendVkArenaAllocator {
- VkAllocationCallbacks *allocator;
- size_t *heap_idx_alloc_sizes; // allocation size per type of memory available on the gpu
- RendVkPagedArena *mem_arenas; // memory arena per type of memory available on the gpu
- VkDevice logical_device; // virtual device
- VkPhysicalDevice physical_device; // physical device we are allocating memory from
- VkDeviceSize gpu_alignment; // allocations must respect the physical limitations of the gpu
- VkDeviceSize block_min_size; // minimum size per block of memory
- uint64_t total_allocations;
- uint32_t heap_index_count;
- VkPhysicalDeviceMemoryProperties properties; // useful for getting properties per heap index
-};
-
-static RendVkArenaAllocator
-rend_vk_arena_create(VkDevice logical_device, VkPhysicalDevice physical_device, VkPhysicalDeviceLimits device_limits, VkAllocationCallbacks *allocator)
-{
- RendVkArenaAllocator arena = {
- .allocator = allocator,
- .heap_idx_alloc_sizes = NULL,
- .logical_device = logical_device,
- .physical_device = physical_device,
- .gpu_alignment = 0,
- .block_min_size = 0,
- .total_allocations = 0,
- .heap_index_count = 0,
- .mem_arenas = 0,
- };
-
- VkPhysicalDeviceMemoryProperties mem_properties;
- vkGetPhysicalDeviceMemoryProperties(physical_device, &mem_properties);
- arena.properties = mem_properties;
-
- uint32_t count = mem_properties.memoryTypeCount;
- arena.heap_index_count = count;
-
- arena.heap_idx_alloc_sizes = rmalloc(count * sizeof *arena.heap_idx_alloc_sizes);
- memset(arena.heap_idx_alloc_sizes, 0, count * sizeof *arena.heap_idx_alloc_sizes);
-
- arena.mem_arenas = rmalloc(count * sizeof *arena.mem_arenas);
- for (uint32_t u = 0; u < count; ++u) {
- arena.mem_arenas[u].capacity = 2;
- arena.mem_arenas[u].elements = 0;
- arena.mem_arenas[u].page_darr = rmalloc(2 * sizeof *arena.mem_arenas[u].page_darr);
- memset(arena.mem_arenas[u].page_darr, 0, 2 * sizeof *arena.mem_arenas[u].page_darr);
- }
-
- VkDeviceSize alignment = device_limits.bufferImageGranularity;
- if (device_limits.nonCoherentAtomSize > alignment) {
- alignment = device_limits.nonCoherentAtomSize;
- }
-
- arena.gpu_alignment = alignment;
- arena.block_min_size = arena.gpu_alignment * 10;
-
- return arena;
-}
-
-static uint32_t
-rend_vk_arena_add_page(RendVkArenaAllocator *arena, VkDeviceSize size, uint32_t heap_index, bool fit_to_alloc)
-{
- VkDeviceSize new_arena_size = fit_to_alloc ? size : (size * 2);
- new_arena_size = (new_arena_size < arena->block_min_size) ? arena->block_min_size : new_arena_size;
-
- VkMemoryPropertyFlags properties = arena->properties.memoryTypes[heap_index].propertyFlags;
-
- RendVkPage page = (RendVkPage) {0};
- page.head = 0;
-
- VkMemoryAllocateFlagsInfo flags_info = {
- .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO,
- .pNext = NULL,
- .flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT,
- .deviceMask = 0
- };
-
- VkMemoryAllocateInfo alloc_info = {
- .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
- .allocationSize = new_arena_size,
- .pNext = &flags_info,
- .memoryTypeIndex = heap_index
- };
-
- page.memory = (RendMemory) {0};
- page.memory.offset = 0;
- page.memory.size = new_arena_size;
-
- VkResult res = vkAllocateMemory(arena->logical_device, &alloc_info, arena->allocator, (VkDeviceMemory*) &page.memory.device_memory);
- if (res != VK_SUCCESS) {
- return UINT32_MAX;
- }
-
- if (properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
- vkMapMemory(
- arena->logical_device,
- (VkDeviceMemory) page.memory.device_memory,
- 0, // Offset inside VkDeviceMemory!!!1
- new_arena_size, // MUST match alloc_info.allocationSize and NOT raw size!!!
- 0,
- &page.memory.host_mapped_memory
- );
- }
-
- RendVkPagedArena *mem_arena = &arena->mem_arenas[heap_index];
-
- if (mem_arena->elements + 1 >= mem_arena->capacity) {
- uint32_t new_capacity = mem_arena->capacity * 2;
- void *new_darr = rrealloc(mem_arena->page_darr, new_capacity * sizeof *mem_arena->page_darr);
- if (!new_darr) {
- vkFreeMemory(arena->logical_device, (VkDeviceMemory) page.memory.device_memory, arena->allocator);
- return UINT32_MAX;
- }
- mem_arena->page_darr = new_darr;
- mem_arena->capacity = new_capacity;
- }
-
- uint32_t page_index = mem_arena->elements;
- mem_arena->page_darr[mem_arena->elements++] = page;
-
- arena->total_allocations++;
-
- return page_index;
-}
-
-static RendMemory
-rend_vk_arena_alloc(RendVkArenaAllocator *arena, VkDeviceSize size, uint32_t heap_index)
-{
- assert(heap_index < 32 && "Unusual heap index. Did you pass the memory type instead?");
- RendVkPagedArena *mem_arena = &arena->mem_arenas[heap_index];
-
- VkMemoryPropertyFlags properties = arena->properties.memoryTypes[heap_index].propertyFlags;
-
- /* align to allocation to fit page size */
- VkDeviceSize align = arena->gpu_alignment;
- VkDeviceSize aligned_size = (size + align - 1) & ~(align - 1);
-
- /* check if fits in previous blocks */
- int whole_page = !(properties & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
- uint32_t page_idx = UINT32_MAX;
- for (uint32_t u = 0; u < mem_arena->elements; ++u) {
- RendVkPage page = mem_arena->page_darr[u];
- int valid = (whole_page) ? (page.head == 0) : 1;
- if ((page.head + aligned_size <= page.memory.size) && valid) {
- page_idx = u;
- break;
- }
- }
-
- /* page not found, add new page */
- if (page_idx == UINT32_MAX) {
- page_idx = rend_vk_arena_add_page(arena, aligned_size, heap_index, whole_page);
- if (page_idx == UINT32_MAX) {
- REND__CRASH("[REND_VK] Arena page allocation failed!");
- }
- }
-
- mem_arena->page_darr[page_idx].reserved = whole_page;
-
- RendMemory memory = {
- .device_memory = mem_arena->page_darr[page_idx].memory.device_memory,
- .size = aligned_size,
- .offset = mem_arena->page_darr[page_idx].head,
- .host_mapped_memory = 0,
- .heap_index = heap_index,
- .id = page_idx,
- };
-
- if (properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
- memory.host_mapped_memory = mem_arena->page_darr[page_idx].memory.host_mapped_memory + memory.offset;
- }
-
- /* move head */
- arena->heap_idx_alloc_sizes[heap_index] += aligned_size;
- mem_arena->page_darr[page_idx].head += aligned_size;
- return memory;
-}
-
-
-static void
-rend_vk_arena_clear(RendVkArenaAllocator *arena, uint32_t heap_index)
-{
- assert(heap_index < 32 && "Unusual heap index. Did you pass the memory type instead?");
- RendVkPagedArena mem_arena = arena->mem_arenas[heap_index];
- if (mem_arena.page_darr) {
- for (uint32_t u = 0; u < mem_arena.elements; ++u) {
- mem_arena.page_darr[u].head = 0;
- mem_arena.page_darr[u].reserved = 0;
- }
- }
-}
-
-static void
-rend_vk_arena_clear_all(RendVkArenaAllocator *arena)
-{
- for (uint32_t u = 0; u < arena->properties.memoryTypeCount; ++u) {
- rend_vk_arena_clear(arena, u);
- }
-}
-
-static void
-rend_vk_arena_shrink(RendVkArenaAllocator *arena, uint32_t heap_index)
-{
- assert(heap_index < 32 && "Unusual heap index. Did you pass the memory type instead?");
- RendVkPagedArena *mem_arena = &arena->mem_arenas[heap_index];
- if (mem_arena->capacity > 4) {
- uint32_t new_capacity = mem_arena->capacity / 2;
- void *new_darr = rrealloc(mem_arena->page_darr, new_capacity * sizeof *mem_arena->page_darr);
- if (!new_darr) return;
- mem_arena->page_darr = new_darr;
- mem_arena->capacity = new_capacity;
- }
-}
-
-static void
-rend_vk_arena_destroy(RendVkArenaAllocator *arena)
-{
- if (arena->mem_arenas) {
- for (size_t u = 0; u < arena->heap_index_count; ++u) {
- RendVkPagedArena *mem_arena = &arena->mem_arenas[u];
- for (uint32_t p = 0; p < mem_arena->elements; ++p) {
-
- RendMemory memory = mem_arena->page_darr[p].memory ;
- if (memory.offset == 0) {
- if (memory.host_mapped_memory) {
- vkUnmapMemory(arena->logical_device, (VkDeviceMemory) memory.device_memory);
- }
- vkFreeMemory(arena->logical_device, (VkDeviceMemory) memory.device_memory, arena->allocator);
- } else {
- PWARN("[REND_VK] Attempted to free memory with an offset!");
- }
-
- }
- if (mem_arena->page_darr) {
- rfree(mem_arena->page_darr);
- mem_arena->page_darr = 0;
- }
- }
- rfree(arena->mem_arenas);
- arena->mem_arenas = 0;
- }
- if (arena->heap_idx_alloc_sizes) {
- rfree(arena->heap_idx_alloc_sizes);
- arena->heap_idx_alloc_sizes = 0;
- }
- memset(arena, 0, sizeof *arena);
-}
diff --git a/Rend/rend_vk_device.c b/Rend/rend_vk_device.c
deleted file mode 100644
index 6f25557..0000000
--- a/Rend/rend_vk_device.c
+++ /dev/null
@@ -1,377 +0,0 @@
-#pragma once
-#include "rend_internal.h"
-#include "rend_vk_internal.h"
-#include <vulkan/vulkan_core.h>
-
-// struct RendDevice {
-// bool anisotropy_support;
-// bool bindless_support;
-// };
-
-
-static bool
-rend_vk_device_create(VkSurfaceKHR surface, RendSpecs specs, RendVkDevice *out_device, uint32_t (*score_devices)(RendVkDevice *, RendSpecs, const char **, uint32_t))
-{
- assert(out_device);
-
- uint32_t device_count = 0;
- CHECK_VK_RESULT(vkEnumeratePhysicalDevices(vk_instance, &device_count, VK_NULL_HANDLE));
- if (device_count == 0) {
- PFATAL("No GPU with Vulkan support found!");
- return false;
- }
-
- VkPhysicalDevice physical_devices[device_count];
- CHECK_VK_RESULT(vkEnumeratePhysicalDevices(vk_instance, &device_count, physical_devices));
-
- const char *extension_names[] = { VK_KHR_SWAPCHAIN_EXTENSION_NAME };
-
- uint32_t best_score = 1; // 1 so that devices that do not meet specs get ignored
- RendVkDevice best_device = {0};
-
- PDEBUG("DEVICE SCORE");
- for (uint32_t i = 0; i < device_count; i++) {
-
- /* populate device struct */
- RendVkDevice scoring = {0};
- scoring.surface = surface;
- scoring.physical_device = physical_devices[i];
- vkGetPhysicalDeviceProperties(physical_devices[i], &scoring.properties);
- vkGetPhysicalDeviceFeatures(physical_devices[i], &scoring.features);
- vkGetPhysicalDeviceMemoryProperties(physical_devices[i], &scoring.memory);
-
- /* score device */
- uint32_t dev_score = score_devices(&scoring, specs, extension_names, 1);
- PDEBUG("%-20.20s %5d", scoring.properties.deviceName, dev_score);
- if (dev_score >= best_score) {
- if (best_device.swapchain_support.format) {
- rfree(best_device.swapchain_support.format);
- }
- if (best_device.swapchain_support.present_modes) {
- rfree(best_device.swapchain_support.present_modes);
- }
- best_score = dev_score;
- best_device = scoring;
- } else {
- if (scoring.swapchain_support.format) {
- rfree(scoring.swapchain_support.format);
- }
- if (scoring.swapchain_support.present_modes) {
- rfree(scoring.swapchain_support.present_modes);
- }
- }
-
- }
-
- if (best_score > 1) {
- PDEBUG("Driver version %d.%d.%d", VK_VERSION_MAJOR(best_device.properties.driverVersion), VK_VERSION_MINOR(best_device.properties.driverVersion), VK_VERSION_PATCH(best_device.properties.driverVersion));
- PDEBUG("Vulkan API version %d.%d.%d", VK_VERSION_MAJOR(best_device.properties.apiVersion), VK_VERSION_MINOR(best_device.properties.apiVersion), VK_VERSION_PATCH(best_device.properties.apiVersion));
- }
-
- if (!best_device.physical_device) {
- PERROR("No physical devices were found that meet specs!");
- return false;
- }
-
- /* update out device to use best selected device */
- *out_device = best_device;
-
- PDEBUG("Graphics Family Index: %u", out_device->graphics_family_index);
- PDEBUG("Present Family Index: %u", out_device->present_family_index);
- PDEBUG("Compute Family Index: %u", out_device->compute_family_index);
- PDEBUG("Transfer Family Index: %u", out_device->transfer_family_index);
-
- bool present_shares_graphics_q = out_device->present_family_index == out_device->graphics_family_index;
- bool transfer_shares_graphics_q = out_device->transfer_family_index == out_device->graphics_family_index;
-
- uint32_t index_count = 1;
- if (!present_shares_graphics_q) index_count++;
- if (!transfer_shares_graphics_q) index_count++;
-
- uint32_t indices[index_count];
- uint8_t index = 0;
-
- indices[index++] = out_device->graphics_family_index;
- if (!present_shares_graphics_q) {
- indices[index++] = out_device->present_family_index;
- }
- if (!transfer_shares_graphics_q) {
- indices[index++] = out_device->transfer_family_index;
- }
-
- VkDeviceQueueCreateInfo q_create_info[index_count];
-
- float queue_priority[2] = {1.0f, 1.0f};
- for (uint32_t i = 0; i < index_count; i++) {
- q_create_info[i].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
- q_create_info[i].queueFamilyIndex = indices[i];
- // TODO: request 2 queues when possible
- // q_create_info[i].queueCount = (indices[i] == out_device->graphics_family_index) ? 2 : 1;
- q_create_info[i].queueCount = 1;
- q_create_info[i].flags = 0;
- q_create_info[i].pNext = 0;
- q_create_info[i].pQueuePriorities = queue_priority;
- }
-
- // TODO: driven by the same config as the check_specs function
- // used earlier
-
- VkPhysicalDeviceFeatures device_features = {0};
- device_features.samplerAnisotropy = specs.sampler_anisotropy;
- device_features.fillModeNonSolid = VK_TRUE;
- device_features.shaderInt64 = VK_TRUE;
-
- // vulkan 1.3 features (dynamic rendering + sync2)
- VkPhysicalDeviceVulkan13Features vk13_features = {0};
- vk13_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES;
- vk13_features.dynamicRendering = VK_TRUE;
- vk13_features.synchronization2 = VK_TRUE;
-
- // vulkan 1.2 features (timeline semaphores)
- VkPhysicalDeviceVulkan12Features vk12_features = {0};
- vk12_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES;
- vk12_features.timelineSemaphore = VK_TRUE;
-
- // vk12_features.descriptorIndexing = VK_TRUE;
- // vk12_features.descriptorBindingSampledImageUpdateAfterBind = VK_TRUE;
- vk12_features.descriptorBindingPartiallyBound = VK_TRUE;
- // vk12_features.descriptorBindingUniformBufferUpdateAfterBind = VK_TRUE;
- // vk12_features.descriptorBindingVariableDescriptorCount = VK_TRUE;
- // vk12_features.runtimeDescriptorArray = VK_TRUE;
-
- vk12_features.bufferDeviceAddress = VK_TRUE;
- vk12_features.scalarBlockLayout = VK_TRUE;
- vk12_features.pNext = &vk13_features;
-
- // vulkan 1.1 features (draw parameters)
- VkPhysicalDeviceVulkan11Features vk11_features = {0};
- vk11_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES;
- vk11_features.shaderDrawParameters = VK_TRUE;
- vk11_features.pNext = &vk12_features;
-
- VkDeviceCreateInfo device_create_info = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO };
- device_create_info.pNext = &vk11_features;
- device_create_info.queueCreateInfoCount = index_count;
- device_create_info.pQueueCreateInfos = q_create_info;
- device_create_info.pEnabledFeatures = &device_features;
- device_create_info.enabledExtensionCount = 1;
-
- const char *extention_names = VK_KHR_SWAPCHAIN_EXTENSION_NAME;
- device_create_info.ppEnabledExtensionNames = &extention_names;
-
- /* deprecated and ignored */
- device_create_info.enabledLayerCount = 0;
- device_create_info.ppEnabledLayerNames = 0;
-
- CHECK_VK_RESULT(vkCreateDevice(out_device->physical_device, &device_create_info, vk_allocator, &out_device->logical_device));
-
- vkGetDeviceQueue(out_device->logical_device, out_device->graphics_family_index, 0, &out_device->graphics_queue);
- vkGetDeviceQueue(out_device->logical_device, out_device->present_family_index, 0, &out_device->present_queue);
- vkGetDeviceQueue(out_device->logical_device, out_device->transfer_family_index, 0, &out_device->transfer_queue);
-
- PDEBUG("GRAPHICS | PRESENT | COMPUTE | TRANSFER | DEVICE");
- PDEBUG(" %02d | %02d | %02d | %02d | %s",
- out_device->graphics_family_index != UINT32_MAX,
- out_device->present_family_index != UINT32_MAX,
- out_device->compute_family_index != UINT32_MAX,
- out_device->transfer_family_index != UINT32_MAX,
- out_device->properties.deviceName);
-
- VkPhysicalDeviceMemoryProperties mem_props = out_device->memory;
- out_device->device_index = UINT32_MAX;
- for (uint32_t i = 0; i < mem_props.memoryTypeCount; i++) {
- if ((mem_props.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) == VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {
- out_device->device_index = i;
- break;
- }
- }
-
- VkMemoryPropertyFlags host_flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
- out_device->host_index = UINT32_MAX;
- for (uint32_t i = 0; i < mem_props.memoryTypeCount; i++) {
- if ((mem_props.memoryTypes[i].propertyFlags & host_flags) == host_flags) {
- out_device->host_index = i;
- break;
- }
- }
-
- PDEBUG("Device local heap: %2u", out_device->device_index);
- PDEBUG("Host mapped heap: %2u", out_device->host_index);
- return true;
-}
-
-static void
-rend_vk_device_destroy(RendVkDevice *device)
-{
- RASSERT(device && device->logical_device, "Invalid or uninitialized device.");
-
- vkDeviceWaitIdle(device->logical_device); // safe when destroying device
- vkDestroyDevice(device->logical_device, vk_allocator);
- if (device->swapchain_support.format) rfree(vk_device.swapchain_support.format);
- if (device->swapchain_support.present_modes) rfree(vk_device.swapchain_support.present_modes);
-
- *device = (RendVkDevice){0};
-}
-
-static void
-rend_vk_device_query_swapchain_support(RendVkDevice *device)
-{
- RASSERT(device->physical_device, "Invalid device pointer.");
-
- /* surface capabilities */
- CHECK_VK_RESULT(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device->physical_device, device->surface, &device->swapchain_support.capabilities));
-
- /* surface formats */
- CHECK_VK_RESULT(vkGetPhysicalDeviceSurfaceFormatsKHR(device->physical_device, device->surface, &device->swapchain_support.format_count, VK_NULL_HANDLE));
- if (device->swapchain_support.format_count != 0) {
- if (!device->swapchain_support.format) {
- device->swapchain_support.format = rmalloc(device->swapchain_support.format_count * sizeof(*device->swapchain_support.format));
- }
- CHECK_VK_RESULT(vkGetPhysicalDeviceSurfaceFormatsKHR(device->physical_device, device->surface, &device->swapchain_support.format_count, device->swapchain_support.format));
- }
-
- /* present modes */
- CHECK_VK_RESULT(vkGetPhysicalDeviceSurfacePresentModesKHR(device->physical_device, device->surface, &device->swapchain_support.present_mode_count, VK_NULL_HANDLE));
- if (device->swapchain_support.present_mode_count != 0) {
- if (!device->swapchain_support.present_modes) {
- device->swapchain_support.present_modes = rmalloc(device->swapchain_support.present_mode_count * sizeof(*device->swapchain_support.present_modes));
- }
- CHECK_VK_RESULT(vkGetPhysicalDeviceSurfacePresentModesKHR(device->physical_device, device->surface, &device->swapchain_support.present_mode_count, device->swapchain_support.present_modes));
- }
-}
-
-static bool
-rend_vk_device_detect_depth_format(RendVkDevice *device)
-{
- const uint64_t candidate_count = 3;
- VkFormat candidates[] = {VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT};
-
- uint32_t flags = VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
- for (uint32_t i = 0; i < candidate_count; i++) {
- VkFormatProperties properties;
- vkGetPhysicalDeviceFormatProperties(device->physical_device, candidates[i], &properties);
- if ((properties.linearTilingFeatures & flags) == flags) {
- device->depth_format = candidates[i];
- return true;
- } else if ((properties.optimalTilingFeatures & flags) == flags) {
- device->depth_format = candidates[i];
- return true;
- }
- }
-
- return false;
-}
-
-static uint32_t
-rend_vk_device_score_default(RendVkDevice *device, RendSpecs minimum_specs, const char **required_extensions, uint32_t required_extension_count)
-{
- /* NOTE: When we score the device we will also check for specs. Not meeting a spec
- * leads to 0 score and continue. We will assume device already contains some information
- * about properties when this function is called. */
-
- uint32_t score = 0;
-
- device->graphics_family_index = UINT32_MAX;
- device->present_family_index = UINT32_MAX;
- device->compute_family_index = UINT32_MAX;
- device->transfer_family_index = UINT32_MAX;
-
- if (minimum_specs.discrete_gpu) {
- if (device->properties.deviceType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) {
- return 0;
- }
- }
-
- uint32_t q_family_count = 0;
- vkGetPhysicalDeviceQueueFamilyProperties(device->physical_device, &q_family_count, VK_NULL_HANDLE);
-
- VkQueueFamilyProperties q_family[q_family_count];
- vkGetPhysicalDeviceQueueFamilyProperties(device->physical_device, &q_family_count, q_family);
-
- uint8_t min_transfer_score = 255;
- for (uint32_t i = 0; i < q_family_count; i++) {
-
- uint8_t transfer_score = 0;
- if (q_family[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
- device->graphics_family_index = i;
- transfer_score++;
- }
-
- if (q_family[i].queueFlags & VK_QUEUE_COMPUTE_BIT) {
- device->compute_family_index = i;
- transfer_score++;
- }
-
- if (q_family[i].queueFlags & VK_QUEUE_TRANSFER_BIT) {
- // take the index if the transfer score is minimal
- if (transfer_score <= min_transfer_score) {
- min_transfer_score = transfer_score;
- device->transfer_family_index = i;
- }
- }
-
- VkBool32 supports_present = VK_FALSE;
- CHECK_VK_RESULT(vkGetPhysicalDeviceSurfaceSupportKHR(device->physical_device, i, device->surface, &supports_present));
- if (supports_present) {
- device->present_family_index = i;
- }
- }
-
- if ( (minimum_specs.graphics && device->graphics_family_index == UINT32_MAX) ||
- (minimum_specs.present && device->present_family_index == UINT32_MAX) ||
- (minimum_specs.compute && device->compute_family_index == UINT32_MAX) ||
- (minimum_specs.transfer && device->transfer_family_index == UINT32_MAX)) {
- return 0;
- }
-
- // swapchain support
- rend_vk_device_query_swapchain_support(device);
-
- if (device->swapchain_support.format_count < 1 || device->swapchain_support.present_mode_count < 1) {
- return 0;
- }
-
- // check for extension specs
- if (required_extensions) {
- uint32_t available_extentions_count = 0;
- VkExtensionProperties *available_extentions = NULL;
- CHECK_VK_RESULT(vkEnumerateDeviceExtensionProperties(device->physical_device, VK_NULL_HANDLE, &available_extentions_count, VK_NULL_HANDLE));
-
- if (available_extentions_count != 0) {
-
- available_extentions = rmalloc(available_extentions_count * sizeof(*available_extentions));
- CHECK_VK_RESULT(vkEnumerateDeviceExtensionProperties(device->physical_device, VK_NULL_HANDLE, &available_extentions_count, available_extentions));
-
- bool overall_found = true;
- for (uint32_t i = 0; i < required_extension_count; ++i) {
- bool found = false;
- for (uint32_t j = 0; j < available_extentions_count; ++j) {
- if (strcmp(required_extensions[i], available_extentions[j].extensionName) == 0) {
- found = true;
- break;
- }
- }
- if (!found) {
- overall_found = false;
- break;
- }
- }
-
- rfree(available_extentions);
- if (!overall_found) {
- return 0;
- }
- }
- }
-
- if (minimum_specs.sampler_anisotropy && !device->features.samplerAnisotropy) {
- return 0;
- }
-
- score = 10;
- if (device->properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) {
- score += 1000;
- }
-
- return score;
-}
diff --git a/Rend/rend_vk_image.c b/Rend/rend_vk_image.c
deleted file mode 100644
index e842bf0..0000000
--- a/Rend/rend_vk_image.c
+++ /dev/null
@@ -1,125 +0,0 @@
-#pragma once
-#include "rend_internal.h"
-#include "rend_vk_internal.h"
-#include <vulkan/vulkan_core.h>
-
-struct RendVkImage {
- VkDevice logical_device;
- VkImage handle;
- VkImageView view;
-
- VkMemoryRequirements requirements;
-
- VkImageType img_type;
- uint32_t width, height;
- VkFormat format;
- VkImageTiling tiling;
- VkImageUsageFlags usage;
- uint32_t depth;
- uint32_t mip_levels;
- uint32_t layers;
- VkSampleCountFlags sample_count_flags;
- VkSharingMode sharing_mode;
-
- RendMemory *memory;
-};
-
-static RendVkImage
-rend_vk_image_create(VkDevice logical_device, VkImageType img_type, uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling,
- VkImageUsageFlags usage, VkMemoryPropertyFlags memory_flags, uint32_t depth, uint32_t mip_levels, uint32_t layers,
- VkSampleCountFlags sample_count_flags, VkSharingMode sharing_mode)
-{
- RendVkImage image = {
- .handle = VK_NULL_HANDLE,
- .memory = VK_NULL_HANDLE,
- .logical_device = logical_device,
- .img_type = img_type,
- .width = width,
- .height = height,
- .format = format,
- .tiling = tiling,
- .usage = usage,
- .depth = depth,
- .mip_levels = mip_levels,
- .layers = layers,
- .sample_count_flags = sample_count_flags,
- .sharing_mode = sharing_mode
- };
-
- VkImageCreateInfo img_create_info = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO};
- img_create_info.imageType = img_type;
- img_create_info.extent.width = width;
- img_create_info.extent.height = height;
- img_create_info.extent.depth = depth;
- img_create_info.mipLevels = mip_levels;
- img_create_info.arrayLayers = layers;
- img_create_info.format = format;
- img_create_info.tiling = tiling;
- img_create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
- img_create_info.usage = usage;
- img_create_info.samples = sample_count_flags;
- img_create_info.sharingMode = sharing_mode;
-
-
- if (vkCreateImage(logical_device, &img_create_info, vk_allocator, &image.handle) != VK_SUCCESS) {
- return image;
- }
-
- return image;
-}
-
-static uint32_t
-rend_vk_image_required_memory_type(RendVkImage *img)
-{
- assert(img->memory == NULL && "Image already bound to memory");
- VkMemoryRequirements memory_requirements = {0};
- vkGetImageMemoryRequirements(img->logical_device, img->handle, &memory_requirements);
- img->requirements = memory_requirements;
- return memory_requirements.memoryTypeBits;
-}
-
-static void
-rend_vk_image_bind_memory(RendVkImage *img, RendMemory *memory)
-{
- assert(img->memory == NULL && "Image already bound to memory");
- vkBindImageMemory(img->logical_device, img->handle, (VkDeviceMemory) memory->device_memory, memory->offset);
-}
-
-static void
-rend_vk_image_destroy(RendVkImage *img)
-{
- if (img->view) {
- vkDestroyImageView(img->logical_device, img->view, vk_allocator);
- img->view = 0;
- }
-
- if (img->handle) {
- vkDestroyImage(img->logical_device, img->handle, vk_allocator);
- img->handle = 0;
- }
-}
-
-static void
-rend_vk_image_view_create(RendVkImage *image, VkImageViewType view_type, VkImageAspectFlags view_aspect_flags)
-{
- VkImageViewCreateInfo view_create_info = {
- .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
- .image = image->handle,
- .format = image->format,
- .viewType = view_type,
- .subresourceRange.aspectMask = view_aspect_flags,
- .subresourceRange.baseMipLevel = 0, // offset starts at 0
- .subresourceRange.levelCount = image->mip_levels, // number of mips
- .subresourceRange.baseArrayLayer = 0, // offset starts at 0
- .subresourceRange.layerCount = image->layers, // number of layers
- };
-
- vkCreateImageView(image->logical_device, &view_create_info, vk_allocator, &image->view);
-}
-
-static uint64_t
-rend_vk_image_address(RendVkImage *image)
-{
- assert(image->memory == NULL && "Image already bound to memory");
- return (uint64_t) image->memory->device_memory + image->memory->offset;
-}
diff --git a/Rend/rend_vk_internal.c b/Rend/rend_vk_internal.c
new file mode 100644
index 0000000..4f1679f
--- /dev/null
+++ b/Rend/rend_vk_internal.c
@@ -0,0 +1,1014 @@
+#include <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <vulkan/vulkan.h>
+#include <vulkan/vulkan_core.h>
+
+#include "rend.h"
+#include "rend_internal.h"
+
+#define CHECK_VK_RESULT(r) \
+{ \
+ assert(r == VK_SUCCESS && __LINE__); \
+}
+
+typedef struct RendVkImage RendVkImage;
+typedef struct RendVkArenaAllocator RendVkArenaAllocator;
+
+typedef struct {
+ VkSurfaceCapabilitiesKHR capabilities;
+ VkSurfaceFormatKHR *format;
+ VkPresentModeKHR *present_modes;
+ uint32_t format_count;
+ uint32_t present_mode_count;
+} RendVkSwapchainSupport;
+
+typedef struct {
+ VkDevice logical_device;
+
+ VkPhysicalDeviceProperties properties;
+ VkPhysicalDeviceMemoryProperties memory;
+ VkPhysicalDevice physical_device;
+ VkPhysicalDeviceFeatures features;
+
+ VkSurfaceKHR surface;
+ RendVkSwapchainSupport swapchain_support;
+ VkFormat depth_format;
+
+ VkQueue graphics_queue;
+ VkQueue present_queue;
+ VkQueue compute_queue;
+ VkQueue transfer_queue;
+ uint32_t graphics_family_index;
+ uint32_t present_family_index;
+ uint32_t compute_family_index;
+ uint32_t transfer_family_index;
+
+ uint32_t host_index;
+ uint32_t device_index;
+} RendVkDevice;
+
+typedef struct RendVkPage {
+ RendMemory memory;
+ size_t head;
+ int reserved;
+} RendVkPage;
+
+typedef struct RendVkPagedArena {
+ RendVkPage *page_darr;
+ uint32_t capacity;
+ uint32_t elements;
+} RendVkPagedArena;
+
+struct RendVkArenaAllocator {
+ VkAllocationCallbacks *allocator;
+ RendVkPagedArena *mem_arenas;
+ VkDevice logical_device;
+ VkPhysicalDevice physical_device;
+ VkDeviceSize gpu_alignment;
+ VkDeviceSize block_min_size;
+ uint32_t heap_index_count;
+ VkPhysicalDeviceMemoryProperties properties;
+};
+
+struct RendVkImage {
+ VkDevice logical_device;
+ VkImage handle;
+ VkImageView view;
+
+ VkMemoryRequirements requirements;
+
+ VkImageType img_type;
+ uint32_t width, height;
+ VkFormat format;
+ VkImageTiling tiling;
+ VkImageUsageFlags usage;
+ uint32_t depth;
+ uint32_t mip_levels;
+ uint32_t layers;
+ VkSampleCountFlags sample_count_flags;
+ VkSharingMode sharing_mode;
+
+ RendMemory *memory;
+};
+
+typedef struct RendVkAllocatorState {
+ const char *name;
+} RendVkAllocatorState;
+
+typedef struct RendVkAllocatorHeader {
+ uint32_t offset;
+} RendVkAllocatorHeader;
+
+static bool rend_vk_allocator_is_power_of_two(uintptr_t x);
+static uintptr_t rend_vk_allocator_align_forward(uintptr_t ptr, size_t align);
+static void *rend_vk_allocator_alloc(void *pUserData, size_t size, size_t alignment, VkSystemAllocationScope allocationScope);
+static void *rend_vk_allocator_realloc(void *pUserData, void *pOriginal, size_t size, size_t alignment, VkSystemAllocationScope allocationScope);
+static void rend_vk_allocator_free(void *pUserData, void *pMemory);
+static void rend_vk_allocator_internal_notification(void *pUserData, size_t size, VkInternalAllocationType allocationType, VkSystemAllocationScope allocationScope);
+static void rend_vk_allocator_free_notification(void *pUserData, size_t size, VkInternalAllocationType allocationType, VkSystemAllocationScope allocationScope);
+
+static VkAllocationCallbacks rend_vk_allocator = {
+ .pfnAllocation = rend_vk_allocator_alloc,
+ .pfnReallocation = rend_vk_allocator_realloc,
+ .pfnFree = rend_vk_allocator_free,
+ .pfnInternalAllocation = rend_vk_allocator_internal_notification,
+ .pfnInternalFree = rend_vk_allocator_free_notification,
+};
+
+static const char *rend_vk_allocator_scope_name[] = {
+ [VK_SYSTEM_ALLOCATION_SCOPE_CACHE] = "Cache",
+ [VK_SYSTEM_ALLOCATION_SCOPE_COMMAND] = "Command",
+ [VK_SYSTEM_ALLOCATION_SCOPE_DEVICE] = "Device",
+ [VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE] = "Instance",
+ [VK_SYSTEM_ALLOCATION_SCOPE_OBJECT] = "Object",
+};
+
+static VkInstance vk_instance = 0;
+static VkDebugUtilsMessengerEXT vk_debug_messenger = 0;
+static RendVkDevice vk_device = {0};
+static VkAllocationCallbacks *vk_allocator = &rend_vk_allocator;
+
+static VkFormat vk_format_from_rend_format[] = {
+ [REND_FORMAT_R8_UNORM] = VK_FORMAT_R8_UNORM,
+ [REND_FORMAT_R8G8_UNORM] = VK_FORMAT_R8G8_UNORM,
+ [REND_FORMAT_R8G8B8A8_UNORM] = VK_FORMAT_R8G8B8A8_UNORM,
+ [REND_FORMAT_B8G8R8A8_UNORM] = VK_FORMAT_B8G8R8A8_UNORM,
+ [REND_FORMAT_R8G8B8A8_SRGB] = VK_FORMAT_R8G8B8A8_SRGB,
+ [REND_FORMAT_B8G8R8A8_SRGB] = VK_FORMAT_B8G8R8A8_SRGB,
+ [REND_FORMAT_R32_SFLOAT] = VK_FORMAT_R32_SFLOAT,
+ [REND_FORMAT_R32G32_SFLOAT] = VK_FORMAT_R32G32_SFLOAT,
+ [REND_FORMAT_R32G32B32_SFLOAT] = VK_FORMAT_R32G32B32_SFLOAT,
+ [REND_FORMAT_R32G32B32A32_SFLOAT]= VK_FORMAT_R32G32B32A32_SFLOAT,
+ [REND_FORMAT_R16_SFLOAT] = VK_FORMAT_R16_SFLOAT,
+ [REND_FORMAT_R16G16_SFLOAT] = VK_FORMAT_R16G16_SFLOAT,
+ [REND_FORMAT_R16G16B16A16_SFLOAT]= VK_FORMAT_R16G16B16A16_SFLOAT,
+ [REND_FORMAT_R32_UINT] = VK_FORMAT_R32_UINT,
+ [REND_FORMAT_R32_SINT] = VK_FORMAT_R32_SINT,
+ [REND_FORMAT_R32G32B32A32_UINT] = VK_FORMAT_R32G32B32A32_UINT,
+ [REND_FORMAT_R16G16B16A16_UINT] = VK_FORMAT_R16G16B16A16_UINT,
+ [REND_FORMAT_R8G8B8A8_UINT] = VK_FORMAT_R8G8B8A8_UINT,
+ [REND_FORMAT_D32_SFLOAT] = VK_FORMAT_D32_SFLOAT,
+ [REND_FORMAT_D24_UNORM_S8_UINT] = VK_FORMAT_D24_UNORM_S8_UINT,
+ [REND_FORMAT_D32_SFLOAT_S8_UINT] = VK_FORMAT_D32_SFLOAT_S8_UINT,
+};
+
+static VkPrimitiveTopology vk_topology[] = {
+ [REND_TOPOLOGY_TRIANGLE_LIST] = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
+ [REND_TOPOLOGY_TRIANGLE_STRIP] = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
+ [REND_TOPOLOGY_LINE_LIST] = VK_PRIMITIVE_TOPOLOGY_LINE_LIST,
+ [REND_TOPOLOGY_LINE_STRIP] = VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,
+ [REND_TOPOLOGY_POINT_LIST] = VK_PRIMITIVE_TOPOLOGY_POINT_LIST
+};
+
+static VkPolygonMode vk_polymode[] = {
+ [REND_POLYGON_MODE_FILL] = VK_POLYGON_MODE_FILL,
+ [REND_POLYGON_MODE_LINE] = VK_POLYGON_MODE_LINE,
+ [REND_POLYGON_MODE_POINT] = VK_POLYGON_MODE_POINT,
+};
+
+static VkCullModeFlags vk_cullflags[] = {
+ [REND_CULL_MODE_NONE] = VK_CULL_MODE_NONE,
+ [REND_CULL_MODE_FRONT] = VK_CULL_MODE_FRONT_BIT,
+ [REND_CULL_MODE_BACK] = VK_CULL_MODE_BACK_BIT,
+ [REND_CULL_MODE_FRONT_AND_BACK] = VK_CULL_MODE_FRONT_AND_BACK,
+};
+
+static const VkBufferUsageFlags vk_buffer_usage[] = {
+ [REND_BUFFER_VERTEX] = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
+ [REND_BUFFER_INDEX] = VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
+ [REND_BUFFER_UNIFORM] = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
+ [REND_BUFFER_STORAGE] = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
+ [REND_BUFFER_TRANSFER] = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
+};
+
+static const VkShaderStageFlagBits vk_pipeline_stages[][3] = {
+ [REND__PIPELINE_GRAPHICS] = { VK_SHADER_STAGE_VERTEX_BIT, VK_SHADER_STAGE_FRAGMENT_BIT },
+ [REND__PIPELINE_COMPUTE] = { VK_SHADER_STAGE_COMPUTE_BIT },
+ [REND__PIPELINE_MESH] = { VK_SHADER_STAGE_MESH_BIT_EXT, VK_SHADER_STAGE_FRAGMENT_BIT },
+};
+
+/* --- host allocator --- */
+
+static bool
+rend_vk_allocator_is_power_of_two(uintptr_t x)
+{
+ return (x & (x - 1)) == 0;
+}
+
+static uintptr_t
+rend_vk_allocator_align_forward(uintptr_t ptr, size_t align)
+{
+ uintptr_t p, a, modulo;
+
+ assert(rend_vk_allocator_is_power_of_two(align));
+
+ p = ptr;
+ a = (uintptr_t)align;
+ modulo = p & (a - 1);
+
+ if (modulo != 0) {
+ p += a - modulo;
+ }
+ return p;
+}
+
+static void *
+rend_vk_allocator_alloc(void *pUserData, size_t size, size_t alignment, VkSystemAllocationScope allocationScope)
+{
+ size_t total_size;
+ uint8_t *raw_ptr;
+ uintptr_t unaligned_addr;
+ uint8_t *aligned_ptr;
+ RendVkAllocatorHeader *header;
+
+ (void)pUserData;
+ total_size = size + alignment + sizeof(RendVkAllocatorHeader);
+ raw_ptr = malloc(total_size);
+ unaligned_addr = (uintptr_t)(raw_ptr + sizeof(RendVkAllocatorHeader));
+
+ aligned_ptr = (uint8_t *)rend_vk_allocator_align_forward(unaligned_addr, alignment);
+ header = (RendVkAllocatorHeader *)aligned_ptr - 1;
+ header->offset = aligned_ptr - raw_ptr;
+
+ PDEBUG("[VK_ALLOC] %p - bytes %lu with alignment %lu - scope %s",
+ aligned_ptr, size, alignment, rend_vk_allocator_scope_name[allocationScope]);
+
+ return (void *)aligned_ptr;
+}
+
+static void *
+rend_vk_allocator_realloc(void *pUserData, void *pOriginal, size_t size, size_t alignment, VkSystemAllocationScope allocationScope)
+{
+ void *new_ptr;
+
+ if (!pOriginal)
+ return rend_vk_allocator_alloc(pUserData, size, alignment, allocationScope);
+ if (size == 0) {
+ rend_vk_allocator_free(pUserData, pOriginal);
+ return NULL;
+ }
+ new_ptr = rend_vk_allocator_alloc(pUserData, size, alignment, allocationScope);
+ if (!new_ptr)
+ return NULL;
+ memcpy(new_ptr, pOriginal, size);
+ rend_vk_allocator_free(pUserData, pOriginal);
+ return new_ptr;
+}
+
+static void
+rend_vk_allocator_free(void *pUserData, void *pMemory)
+{
+ RendVkAllocatorHeader *ptr;
+ uint8_t *raw_ptr;
+
+ (void)pUserData;
+ if (!pMemory)
+ return;
+ ptr = pMemory;
+ raw_ptr = pMemory;
+ raw_ptr -= (ptr - 1)->offset;
+
+ PDEBUG("[VK_FREE] %p", ptr);
+ free(raw_ptr);
+}
+
+static void
+rend_vk_allocator_internal_notification(void *pUserData, size_t size, VkInternalAllocationType allocationType, VkSystemAllocationScope allocationScope)
+{
+ (void)pUserData;
+ (void)allocationType;
+ PDEBUG("[VK_ALLOC_INTERNAL] bytes %lu - scope %s",
+ size, rend_vk_allocator_scope_name[allocationScope]);
+}
+
+static void
+rend_vk_allocator_free_notification(void *pUserData, size_t size, VkInternalAllocationType allocationType, VkSystemAllocationScope allocationScope)
+{
+ (void)pUserData;
+ (void)allocationType;
+ PDEBUG("[VK_FREE_INTERNAL] bytes %lu - scope %s",
+ size, rend_vk_allocator_scope_name[allocationScope]);
+}
+
+/* --- device --- */
+
+static void
+rend_vk_device_query_swapchain_support(RendVkDevice *device)
+{
+ RASSERT(device->physical_device, "Invalid device pointer.");
+
+ CHECK_VK_RESULT(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device->physical_device, device->surface, &device->swapchain_support.capabilities));
+
+ CHECK_VK_RESULT(vkGetPhysicalDeviceSurfaceFormatsKHR(device->physical_device, device->surface, &device->swapchain_support.format_count, VK_NULL_HANDLE));
+ if (device->swapchain_support.format_count != 0) {
+ if (!device->swapchain_support.format) {
+ device->swapchain_support.format = rmalloc(device->swapchain_support.format_count * sizeof(*device->swapchain_support.format));
+ }
+ CHECK_VK_RESULT(vkGetPhysicalDeviceSurfaceFormatsKHR(device->physical_device, device->surface, &device->swapchain_support.format_count, device->swapchain_support.format));
+ }
+
+ CHECK_VK_RESULT(vkGetPhysicalDeviceSurfacePresentModesKHR(device->physical_device, device->surface, &device->swapchain_support.present_mode_count, VK_NULL_HANDLE));
+ if (device->swapchain_support.present_mode_count != 0) {
+ if (!device->swapchain_support.present_modes) {
+ device->swapchain_support.present_modes = rmalloc(device->swapchain_support.present_mode_count * sizeof(*device->swapchain_support.present_modes));
+ }
+ CHECK_VK_RESULT(vkGetPhysicalDeviceSurfacePresentModesKHR(device->physical_device, device->surface, &device->swapchain_support.present_mode_count, device->swapchain_support.present_modes));
+ }
+}
+
+static uint32_t
+rend_vk_device_score_default(RendVkDevice *device, RendSpecs minimum_specs, const char **required_extensions, uint32_t required_extension_count)
+{
+ uint32_t score;
+ uint32_t q_family_count;
+ uint8_t min_transfer_score;
+ uint32_t i;
+
+ score = 0;
+
+ device->graphics_family_index = UINT32_MAX;
+ device->present_family_index = UINT32_MAX;
+ device->compute_family_index = UINT32_MAX;
+ device->transfer_family_index = UINT32_MAX;
+
+ if (minimum_specs.discrete_gpu) {
+ if (device->properties.deviceType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) {
+ return 0;
+ }
+ }
+
+ q_family_count = 0;
+ vkGetPhysicalDeviceQueueFamilyProperties(device->physical_device, &q_family_count, VK_NULL_HANDLE);
+
+ {
+ VkQueueFamilyProperties q_family[q_family_count];
+
+ vkGetPhysicalDeviceQueueFamilyProperties(device->physical_device, &q_family_count, q_family);
+
+ min_transfer_score = 255;
+ for (i = 0; i < q_family_count; i++) {
+ uint8_t transfer_score;
+ VkBool32 supports_present;
+
+ transfer_score = 0;
+ if (q_family[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
+ device->graphics_family_index = i;
+ transfer_score++;
+ }
+
+ if (q_family[i].queueFlags & VK_QUEUE_COMPUTE_BIT) {
+ device->compute_family_index = i;
+ transfer_score++;
+ }
+
+ if (q_family[i].queueFlags & VK_QUEUE_TRANSFER_BIT) {
+ if (transfer_score <= min_transfer_score) {
+ min_transfer_score = transfer_score;
+ device->transfer_family_index = i;
+ }
+ }
+
+ supports_present = VK_FALSE;
+ CHECK_VK_RESULT(vkGetPhysicalDeviceSurfaceSupportKHR(device->physical_device, i, device->surface, &supports_present));
+ if (supports_present) {
+ device->present_family_index = i;
+ }
+ }
+ }
+
+ if ((minimum_specs.graphics && device->graphics_family_index == UINT32_MAX) ||
+ (minimum_specs.present && device->present_family_index == UINT32_MAX) ||
+ (minimum_specs.compute && device->compute_family_index == UINT32_MAX) ||
+ (minimum_specs.transfer && device->transfer_family_index == UINT32_MAX)) {
+ return 0;
+ }
+
+ rend_vk_device_query_swapchain_support(device);
+
+ if (device->swapchain_support.format_count < 1 || device->swapchain_support.present_mode_count < 1) {
+ return 0;
+ }
+
+ if (required_extensions) {
+ uint32_t available_extentions_count;
+ VkExtensionProperties *available_extentions;
+
+ available_extentions_count = 0;
+ available_extentions = NULL;
+ CHECK_VK_RESULT(vkEnumerateDeviceExtensionProperties(device->physical_device, VK_NULL_HANDLE, &available_extentions_count, VK_NULL_HANDLE));
+
+ if (available_extentions_count != 0) {
+ bool overall_found;
+ uint32_t j;
+
+ available_extentions = rmalloc(available_extentions_count * sizeof(*available_extentions));
+ CHECK_VK_RESULT(vkEnumerateDeviceExtensionProperties(device->physical_device, VK_NULL_HANDLE, &available_extentions_count, available_extentions));
+
+ overall_found = true;
+ for (i = 0; i < required_extension_count; ++i) {
+ bool found;
+
+ found = false;
+ for (j = 0; j < available_extentions_count; ++j) {
+ if (strcmp(required_extensions[i], available_extentions[j].extensionName) == 0) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ overall_found = false;
+ break;
+ }
+ }
+
+ rfree(available_extentions);
+ if (!overall_found) {
+ return 0;
+ }
+ }
+ }
+
+ if (minimum_specs.sampler_anisotropy && !device->features.samplerAnisotropy) {
+ return 0;
+ }
+
+ score = 10;
+ if (device->properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) {
+ score += 1000;
+ }
+
+ return score;
+}
+
+static bool
+rend_vk_device_create(VkSurfaceKHR surface, RendSpecs specs, RendVkDevice *out_device)
+{
+ uint32_t device_count;
+ const char *extension_names[] = { VK_KHR_SWAPCHAIN_EXTENSION_NAME };
+ uint32_t best_score;
+ RendVkDevice best_device;
+ uint32_t i;
+ bool present_shares_graphics_q;
+ bool transfer_shares_graphics_q;
+ uint32_t index_count;
+ uint8_t index;
+ float queue_priority[2];
+ VkPhysicalDeviceFeatures device_features;
+ VkPhysicalDeviceVulkan13Features vk13_features;
+ VkPhysicalDeviceVulkan12Features vk12_features;
+ VkPhysicalDeviceVulkan11Features vk11_features;
+ VkDeviceCreateInfo device_create_info;
+ const char *extention_names;
+ VkPhysicalDeviceMemoryProperties mem_props;
+ VkMemoryPropertyFlags host_flags;
+
+ assert(out_device);
+
+ device_count = 0;
+ CHECK_VK_RESULT(vkEnumeratePhysicalDevices(vk_instance, &device_count, VK_NULL_HANDLE));
+ if (device_count == 0) {
+ PFATAL("No GPU with Vulkan support found!");
+ return false;
+ }
+
+ {
+ VkPhysicalDevice physical_devices[device_count];
+
+ CHECK_VK_RESULT(vkEnumeratePhysicalDevices(vk_instance, &device_count, physical_devices));
+
+ best_score = 1;
+ best_device = (RendVkDevice){0};
+
+ PDEBUG("DEVICE SCORE");
+ for (i = 0; i < device_count; i++) {
+ RendVkDevice scoring;
+ uint32_t dev_score;
+
+ scoring = (RendVkDevice){0};
+ scoring.surface = surface;
+ scoring.physical_device = physical_devices[i];
+ vkGetPhysicalDeviceProperties(physical_devices[i], &scoring.properties);
+ vkGetPhysicalDeviceFeatures(physical_devices[i], &scoring.features);
+ vkGetPhysicalDeviceMemoryProperties(physical_devices[i], &scoring.memory);
+
+ dev_score = rend_vk_device_score_default(&scoring, specs, extension_names, 1);
+ PDEBUG("%-20.20s %5d", scoring.properties.deviceName, dev_score);
+ if (dev_score >= best_score) {
+ if (best_device.swapchain_support.format) {
+ rfree(best_device.swapchain_support.format);
+ }
+ if (best_device.swapchain_support.present_modes) {
+ rfree(best_device.swapchain_support.present_modes);
+ }
+ best_score = dev_score;
+ best_device = scoring;
+ } else {
+ if (scoring.swapchain_support.format) {
+ rfree(scoring.swapchain_support.format);
+ }
+ if (scoring.swapchain_support.present_modes) {
+ rfree(scoring.swapchain_support.present_modes);
+ }
+ }
+ }
+ }
+
+ if (best_score > 1) {
+ PDEBUG("Driver version %d.%d.%d", VK_VERSION_MAJOR(best_device.properties.driverVersion), VK_VERSION_MINOR(best_device.properties.driverVersion), VK_VERSION_PATCH(best_device.properties.driverVersion));
+ PDEBUG("Vulkan API version %d.%d.%d", VK_VERSION_MAJOR(best_device.properties.apiVersion), VK_VERSION_MINOR(best_device.properties.apiVersion), VK_VERSION_PATCH(best_device.properties.apiVersion));
+ }
+
+ if (!best_device.physical_device) {
+ PERROR("No physical devices were found that meet specs!");
+ return false;
+ }
+
+ *out_device = best_device;
+
+ PDEBUG("Graphics Family Index: %u", out_device->graphics_family_index);
+ PDEBUG("Present Family Index: %u", out_device->present_family_index);
+ PDEBUG("Compute Family Index: %u", out_device->compute_family_index);
+ PDEBUG("Transfer Family Index: %u", out_device->transfer_family_index);
+
+ present_shares_graphics_q = out_device->present_family_index == out_device->graphics_family_index;
+ transfer_shares_graphics_q = out_device->transfer_family_index == out_device->graphics_family_index;
+
+ index_count = 1;
+ if (!present_shares_graphics_q)
+ index_count++;
+ if (!transfer_shares_graphics_q)
+ index_count++;
+
+ {
+ uint32_t indices[index_count];
+ VkDeviceQueueCreateInfo q_create_info[index_count];
+
+ index = 0;
+ indices[index++] = out_device->graphics_family_index;
+ if (!present_shares_graphics_q) {
+ indices[index++] = out_device->present_family_index;
+ }
+ if (!transfer_shares_graphics_q) {
+ indices[index++] = out_device->transfer_family_index;
+ }
+
+ queue_priority[0] = 1.0f;
+ queue_priority[1] = 1.0f;
+ for (i = 0; i < index_count; i++) {
+ q_create_info[i].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
+ q_create_info[i].queueFamilyIndex = indices[i];
+ q_create_info[i].queueCount = 1;
+ q_create_info[i].flags = 0;
+ q_create_info[i].pNext = 0;
+ q_create_info[i].pQueuePriorities = queue_priority;
+ }
+
+ device_features = (VkPhysicalDeviceFeatures){0};
+ device_features.samplerAnisotropy = specs.sampler_anisotropy;
+ device_features.fillModeNonSolid = VK_TRUE;
+ device_features.shaderInt64 = VK_TRUE;
+
+ vk13_features = (VkPhysicalDeviceVulkan13Features){0};
+ vk13_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES;
+ vk13_features.dynamicRendering = VK_TRUE;
+ vk13_features.synchronization2 = VK_TRUE;
+
+ vk12_features = (VkPhysicalDeviceVulkan12Features){0};
+ vk12_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES;
+ vk12_features.timelineSemaphore = VK_TRUE;
+ vk12_features.descriptorBindingPartiallyBound = VK_TRUE;
+ vk12_features.bufferDeviceAddress = VK_TRUE;
+ vk12_features.scalarBlockLayout = VK_TRUE;
+ vk12_features.pNext = &vk13_features;
+
+ vk11_features = (VkPhysicalDeviceVulkan11Features){0};
+ vk11_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES;
+ vk11_features.shaderDrawParameters = VK_TRUE;
+ vk11_features.pNext = &vk12_features;
+
+ device_create_info = (VkDeviceCreateInfo){ VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO };
+ device_create_info.pNext = &vk11_features;
+ device_create_info.queueCreateInfoCount = index_count;
+ device_create_info.pQueueCreateInfos = q_create_info;
+ device_create_info.pEnabledFeatures = &device_features;
+ device_create_info.enabledExtensionCount = 1;
+
+ extention_names = VK_KHR_SWAPCHAIN_EXTENSION_NAME;
+ device_create_info.ppEnabledExtensionNames = &extention_names;
+
+ device_create_info.enabledLayerCount = 0;
+ device_create_info.ppEnabledLayerNames = 0;
+
+ CHECK_VK_RESULT(vkCreateDevice(out_device->physical_device, &device_create_info, vk_allocator, &out_device->logical_device));
+ }
+
+ vkGetDeviceQueue(out_device->logical_device, out_device->graphics_family_index, 0, &out_device->graphics_queue);
+ vkGetDeviceQueue(out_device->logical_device, out_device->present_family_index, 0, &out_device->present_queue);
+ vkGetDeviceQueue(out_device->logical_device, out_device->transfer_family_index, 0, &out_device->transfer_queue);
+
+ PDEBUG("GRAPHICS | PRESENT | COMPUTE | TRANSFER | DEVICE");
+ PDEBUG(" %02d | %02d | %02d | %02d | %s",
+ out_device->graphics_family_index != UINT32_MAX,
+ out_device->present_family_index != UINT32_MAX,
+ out_device->compute_family_index != UINT32_MAX,
+ out_device->transfer_family_index != UINT32_MAX,
+ out_device->properties.deviceName);
+
+ mem_props = out_device->memory;
+ out_device->device_index = UINT32_MAX;
+ for (i = 0; i < mem_props.memoryTypeCount; i++) {
+ if ((mem_props.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) == VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {
+ out_device->device_index = i;
+ break;
+ }
+ }
+
+ host_flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
+ out_device->host_index = UINT32_MAX;
+ for (i = 0; i < mem_props.memoryTypeCount; i++) {
+ if ((mem_props.memoryTypes[i].propertyFlags & host_flags) == host_flags) {
+ out_device->host_index = i;
+ break;
+ }
+ }
+
+ PDEBUG("Device local heap: %2u", out_device->device_index);
+ PDEBUG("Host mapped heap: %2u", out_device->host_index);
+ return true;
+}
+
+static void
+rend_vk_device_destroy(RendVkDevice *device)
+{
+ RASSERT(device && device->logical_device, "Invalid or uninitialized device.");
+
+ vkDeviceWaitIdle(device->logical_device);
+ vkDestroyDevice(device->logical_device, vk_allocator);
+ if (device->swapchain_support.format)
+ rfree(vk_device.swapchain_support.format);
+ if (device->swapchain_support.present_modes)
+ rfree(vk_device.swapchain_support.present_modes);
+
+ *device = (RendVkDevice){0};
+}
+
+static bool
+rend_vk_device_detect_depth_format(RendVkDevice *device)
+{
+ const uint64_t candidate_count = 3;
+ VkFormat candidates[] = {VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT};
+ uint32_t flags;
+ uint32_t i;
+ VkFormatProperties properties;
+
+ flags = VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
+ for (i = 0; i < candidate_count; i++) {
+ vkGetPhysicalDeviceFormatProperties(device->physical_device, candidates[i], &properties);
+ if ((properties.linearTilingFeatures & flags) == flags) {
+ device->depth_format = candidates[i];
+ return true;
+ } else if ((properties.optimalTilingFeatures & flags) == flags) {
+ device->depth_format = candidates[i];
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/* --- arena --- */
+
+static RendVkArenaAllocator
+rend_vk_arena_create(VkDevice logical_device, VkPhysicalDevice physical_device, VkPhysicalDeviceLimits device_limits, VkAllocationCallbacks *allocator)
+{
+ RendVkArenaAllocator arena;
+ VkPhysicalDeviceMemoryProperties mem_properties;
+ VkDeviceSize alignment;
+ uint32_t count;
+ uint32_t u;
+
+ arena = (RendVkArenaAllocator){
+ .allocator = allocator,
+ .logical_device = logical_device,
+ .physical_device = physical_device,
+ .gpu_alignment = 0,
+ .block_min_size = 0,
+ .heap_index_count = 0,
+ .mem_arenas = 0,
+ };
+
+ vkGetPhysicalDeviceMemoryProperties(physical_device, &mem_properties);
+ arena.properties = mem_properties;
+
+ count = mem_properties.memoryTypeCount;
+ arena.heap_index_count = count;
+
+ arena.mem_arenas = rmalloc(count * sizeof(*arena.mem_arenas));
+ for (u = 0; u < count; ++u) {
+ arena.mem_arenas[u].capacity = 2;
+ arena.mem_arenas[u].elements = 0;
+ arena.mem_arenas[u].page_darr = rmalloc(2 * sizeof(*arena.mem_arenas[u].page_darr));
+ memset(arena.mem_arenas[u].page_darr, 0, 2 * sizeof(*arena.mem_arenas[u].page_darr));
+ }
+
+ alignment = device_limits.bufferImageGranularity;
+ if (device_limits.nonCoherentAtomSize > alignment) {
+ alignment = device_limits.nonCoherentAtomSize;
+ }
+
+ arena.gpu_alignment = alignment;
+ arena.block_min_size = arena.gpu_alignment * 10;
+
+ return arena;
+}
+
+static uint32_t
+rend_vk_arena_add_page(RendVkArenaAllocator *arena, VkDeviceSize size, uint32_t heap_index, bool fit_to_alloc)
+{
+ VkDeviceSize new_arena_size;
+ VkMemoryPropertyFlags properties;
+ RendVkPage page;
+ VkMemoryAllocateFlagsInfo flags_info;
+ VkMemoryAllocateInfo alloc_info;
+ VkResult res;
+ RendVkPagedArena *mem_arena;
+ uint32_t page_index;
+ uint32_t new_capacity;
+ void *new_darr;
+
+ new_arena_size = fit_to_alloc ? size : (size * 2);
+ new_arena_size = (new_arena_size < arena->block_min_size) ? arena->block_min_size : new_arena_size;
+
+ properties = arena->properties.memoryTypes[heap_index].propertyFlags;
+
+ page = (RendVkPage){0};
+ page.head = 0;
+
+ flags_info = (VkMemoryAllocateFlagsInfo){
+ .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO,
+ .pNext = NULL,
+ .flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT,
+ .deviceMask = 0
+ };
+
+ alloc_info = (VkMemoryAllocateInfo){
+ .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+ .allocationSize = new_arena_size,
+ .pNext = &flags_info,
+ .memoryTypeIndex = heap_index
+ };
+
+ page.memory = (RendMemory){0};
+ page.memory.offset = 0;
+ page.memory.size = new_arena_size;
+
+ res = vkAllocateMemory(arena->logical_device, &alloc_info, arena->allocator, (VkDeviceMemory *)&page.memory.device_memory);
+ if (res != VK_SUCCESS) {
+ return UINT32_MAX;
+ }
+
+ if (properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
+ vkMapMemory(
+ arena->logical_device,
+ (VkDeviceMemory)page.memory.device_memory,
+ 0,
+ new_arena_size,
+ 0,
+ &page.memory.host_mapped_memory
+ );
+ }
+
+ mem_arena = &arena->mem_arenas[heap_index];
+
+ if (mem_arena->elements + 1 >= mem_arena->capacity) {
+ new_capacity = mem_arena->capacity * 2;
+ new_darr = rrealloc(mem_arena->page_darr, new_capacity * sizeof(*mem_arena->page_darr));
+ if (!new_darr) {
+ vkFreeMemory(arena->logical_device, (VkDeviceMemory)page.memory.device_memory, arena->allocator);
+ return UINT32_MAX;
+ }
+ mem_arena->page_darr = new_darr;
+ mem_arena->capacity = new_capacity;
+ }
+
+ page_index = mem_arena->elements;
+ mem_arena->page_darr[mem_arena->elements++] = page;
+
+ return page_index;
+}
+
+static RendMemory
+rend_vk_arena_alloc(RendVkArenaAllocator *arena, VkDeviceSize size, uint32_t heap_index)
+{
+ RendVkPagedArena *mem_arena;
+ VkMemoryPropertyFlags properties;
+ VkDeviceSize align;
+ VkDeviceSize aligned_size;
+ int whole_page;
+ uint32_t page_idx;
+ uint32_t u;
+ RendVkPage page;
+ int valid;
+ RendMemory memory;
+
+ assert(heap_index < 32 && "Unusual heap index. Did you pass the memory type instead?");
+ mem_arena = &arena->mem_arenas[heap_index];
+
+ properties = arena->properties.memoryTypes[heap_index].propertyFlags;
+
+ align = arena->gpu_alignment;
+ aligned_size = (size + align - 1) & ~(align - 1);
+
+ whole_page = !(properties & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
+ page_idx = UINT32_MAX;
+ for (u = 0; u < mem_arena->elements; ++u) {
+ page = mem_arena->page_darr[u];
+ valid = (whole_page) ? (page.head == 0) : 1;
+ if ((page.head + aligned_size <= page.memory.size) && valid) {
+ page_idx = u;
+ break;
+ }
+ }
+
+ if (page_idx == UINT32_MAX) {
+ page_idx = rend_vk_arena_add_page(arena, aligned_size, heap_index, whole_page);
+ if (page_idx == UINT32_MAX) {
+ REND__CRASH("[REND_VK] Arena page allocation failed!");
+ }
+ }
+
+ mem_arena->page_darr[page_idx].reserved = whole_page;
+
+ memory = (RendMemory){
+ .device_memory = mem_arena->page_darr[page_idx].memory.device_memory,
+ .size = aligned_size,
+ .offset = mem_arena->page_darr[page_idx].head,
+ .host_mapped_memory = 0,
+ .heap_index = heap_index,
+ .id = page_idx,
+ };
+
+ if (properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
+ memory.host_mapped_memory = mem_arena->page_darr[page_idx].memory.host_mapped_memory + memory.offset;
+ }
+
+ mem_arena->page_darr[page_idx].head += aligned_size;
+ return memory;
+}
+
+static void
+rend_vk_arena_clear(RendVkArenaAllocator *arena, uint32_t heap_index)
+{
+ RendVkPagedArena mem_arena;
+ uint32_t u;
+
+ assert(heap_index < 32 && "Unusual heap index. Did you pass the memory type instead?");
+ mem_arena = arena->mem_arenas[heap_index];
+ if (mem_arena.page_darr) {
+ for (u = 0; u < mem_arena.elements; ++u) {
+ mem_arena.page_darr[u].head = 0;
+ mem_arena.page_darr[u].reserved = 0;
+ }
+ }
+}
+
+static void
+rend_vk_arena_clear_all(RendVkArenaAllocator *arena)
+{
+ uint32_t u;
+
+ for (u = 0; u < arena->properties.memoryTypeCount; ++u) {
+ rend_vk_arena_clear(arena, u);
+ }
+}
+
+static void
+rend_vk_arena_destroy(RendVkArenaAllocator *arena)
+{
+ size_t u;
+ uint32_t p;
+ RendVkPagedArena *mem_arena;
+ RendMemory memory;
+
+ if (arena->mem_arenas) {
+ for (u = 0; u < arena->heap_index_count; ++u) {
+ mem_arena = &arena->mem_arenas[u];
+ for (p = 0; p < mem_arena->elements; ++p) {
+ memory = mem_arena->page_darr[p].memory;
+ if (memory.offset == 0) {
+ if (memory.host_mapped_memory) {
+ vkUnmapMemory(arena->logical_device, (VkDeviceMemory)memory.device_memory);
+ }
+ vkFreeMemory(arena->logical_device, (VkDeviceMemory)memory.device_memory, arena->allocator);
+ } else {
+ PWARN("[REND_VK] Attempted to free memory with an offset!");
+ }
+ }
+ if (mem_arena->page_darr) {
+ rfree(mem_arena->page_darr);
+ mem_arena->page_darr = 0;
+ }
+ }
+ rfree(arena->mem_arenas);
+ arena->mem_arenas = 0;
+ }
+ memset(arena, 0, sizeof(*arena));
+}
+
+/* --- image --- */
+
+static RendVkImage
+rend_vk_image_create(VkDevice logical_device, VkImageType img_type, uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling,
+ VkImageUsageFlags usage, uint32_t depth, uint32_t mip_levels, uint32_t layers,
+ VkSampleCountFlags sample_count_flags, VkSharingMode sharing_mode)
+{
+ RendVkImage image = {
+ .handle = VK_NULL_HANDLE,
+ .memory = VK_NULL_HANDLE,
+ .logical_device = logical_device,
+ .img_type = img_type,
+ .width = width,
+ .height = height,
+ .format = format,
+ .tiling = tiling,
+ .usage = usage,
+ .depth = depth,
+ .mip_levels = mip_levels,
+ .layers = layers,
+ .sample_count_flags = sample_count_flags,
+ .sharing_mode = sharing_mode
+ };
+
+ VkImageCreateInfo img_create_info = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO};
+ img_create_info.imageType = img_type;
+ img_create_info.extent.width = width;
+ img_create_info.extent.height = height;
+ img_create_info.extent.depth = depth;
+ img_create_info.mipLevels = mip_levels;
+ img_create_info.arrayLayers = layers;
+ img_create_info.format = format;
+ img_create_info.tiling = tiling;
+ img_create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ img_create_info.usage = usage;
+ img_create_info.samples = sample_count_flags;
+ img_create_info.sharingMode = sharing_mode;
+
+ if (vkCreateImage(logical_device, &img_create_info, vk_allocator, &image.handle) != VK_SUCCESS) {
+ return image;
+ }
+
+ return image;
+}
+
+static uint32_t
+rend_vk_image_required_memory_type(RendVkImage *img)
+{
+ VkMemoryRequirements memory_requirements;
+
+ assert(img->memory == NULL && "Image already bound to memory");
+ memory_requirements = (VkMemoryRequirements){0};
+ vkGetImageMemoryRequirements(img->logical_device, img->handle, &memory_requirements);
+ img->requirements = memory_requirements;
+ return memory_requirements.memoryTypeBits;
+}
+
+static void
+rend_vk_image_bind_memory(RendVkImage *img, RendMemory *memory)
+{
+ assert(img->memory == NULL && "Image already bound to memory");
+ vkBindImageMemory(img->logical_device, img->handle, (VkDeviceMemory) memory->device_memory, memory->offset);
+}
+
+static void
+rend_vk_image_destroy(RendVkImage *img)
+{
+ if (img->view) {
+ vkDestroyImageView(img->logical_device, img->view, vk_allocator);
+ img->view = 0;
+ }
+
+ if (img->handle) {
+ vkDestroyImage(img->logical_device, img->handle, vk_allocator);
+ img->handle = 0;
+ }
+}
+
+static void
+rend_vk_image_view_create(RendVkImage *image, VkImageViewType view_type, VkImageAspectFlags view_aspect_flags)
+{
+ VkImageViewCreateInfo view_create_info = {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
+ .image = image->handle,
+ .format = image->format,
+ .viewType = view_type,
+ .subresourceRange.aspectMask = view_aspect_flags,
+ .subresourceRange.baseMipLevel = 0,
+ .subresourceRange.levelCount = image->mip_levels,
+ .subresourceRange.baseArrayLayer = 0,
+ .subresourceRange.layerCount = image->layers,
+ };
+
+ vkCreateImageView(image->logical_device, &view_create_info, vk_allocator, &image->view);
+}
diff --git a/Rend/rend_vk_internal.h b/Rend/rend_vk_internal.h
deleted file mode 100644
index 5a03aea..0000000
--- a/Rend/rend_vk_internal.h
+++ /dev/null
@@ -1,177 +0,0 @@
-#ifndef REND_VK_INTERNAL_H
-#define REND_VK_INTERNAL_H
-
-#include <vulkan/vulkan.h>
-#include <vulkan/vulkan_core.h>
-#include <assert.h>
-
-#define CHECK_VK_RESULT(r) \
-{ \
- assert(r == VK_SUCCESS && __LINE__); \
-}
-
-
-typedef struct RendVkImage RendVkImage;
-typedef struct RendVkArenaAllocator RendVkArenaAllocator;
-typedef struct RendVkSbta RendVkSbta;
-
-typedef struct RendVkPendingCmd RendVkPendingCmd;
-typedef struct RendVkDeferredCmds RendVkDeferredCmds;
-
-typedef struct {
- const char **extention_names_darray;
- bool sampler_anisotropy;
- bool discrete_gpu;
- bool graphics;
- bool present;
- bool compute;
- bool transfer;
-} RendVkDevicespecs;
-
-typedef struct {
- uint32_t graphics_family_index;
- uint32_t present_family_index;
- uint32_t compute_family_index;
- uint32_t transfer_family_index;
-} RendVkQueueFamily;
-
-typedef struct {
- VkSurfaceCapabilitiesKHR capabilities;
- VkSurfaceFormatKHR *format;
- VkPresentModeKHR *present_modes;
- uint32_t format_count;
- uint32_t present_mode_count;
-} RendVkSwapchainSupport;
-
-typedef struct {
- /* logical device handle */
- VkDevice logical_device;
-
- /* physical device limitation */
- VkPhysicalDeviceProperties properties;
- VkPhysicalDeviceMemoryProperties memory;
- VkPhysicalDevice physical_device;
- VkPhysicalDeviceFeatures features;
- VkPhysicalDeviceDescriptorBufferPropertiesEXT desc_props;
-
- /* swapchain support */
- VkSurfaceKHR surface;
- RendVkSwapchainSupport swapchain_support;
- VkFormat depth_format;
-
- /* queues */
- VkQueue graphics_queue;
- VkQueue present_queue;
- VkQueue compute_queue;
- VkQueue transfer_queue;
- uint32_t graphics_family_index;
- uint32_t present_family_index;
- uint32_t compute_family_index;
- uint32_t transfer_family_index;
-
- /* memory heap indices */
- uint32_t host_index;
- uint32_t device_index;
-} RendVkDevice;
-
-static VkInstance vk_instance = 0;
-static VkDebugUtilsMessengerEXT vk_debug_messenger = 0;
-static RendVkDevice vk_device = {0};
-
-/* helper functions */
-static int32_t rend_vk_memory_find_index(VkPhysicalDevice device, uint32_t type_filter, VkMemoryPropertyFlags property_flags);
-
-/* rend_vk_device.c */
-static bool rend_vk_device_create(VkSurfaceKHR surface, RendSpecs specs, RendVkDevice *out_device, uint32_t (*score_devices)(RendVkDevice *, RendSpecs, const char **, uint32_t));
-static uint32_t rend_vk_device_score_default(RendVkDevice *device, RendSpecs minimum_specs, const char **required_extensions, uint32_t required_extension_count);
-static void rend_vk_physical_device_query_swapchain_support(RendVkDevice *device);
-static bool rend_vk_device_detect_depth_format(RendVkDevice *device);
-static void rend_vk_device_destroy(RendVkDevice *device);
-
-/* rend_vk_arena.c */
-static RendVkArenaAllocator rend_vk_arena_create(VkDevice logical_device, VkPhysicalDevice physical_device, VkPhysicalDeviceLimits device_limits, VkAllocationCallbacks *allocator);
-static uint32_t rend_vk_arena_add_page(RendVkArenaAllocator *arena, VkDeviceSize size, uint32_t heap_index, bool fit_to_alloc);
-static RendMemory rend_vk_arena_alloc(RendVkArenaAllocator *arena, VkDeviceSize size, uint32_t heap_index);
-static void rend_vk_arena_clear(RendVkArenaAllocator *arena, uint32_t memory_type);
-static void rend_vk_arena_clear_all(RendVkArenaAllocator *arena);
-static void rend_vk_arena_shrink(RendVkArenaAllocator *arena, uint32_t memory_type);
-static void rend_vk_arena_destroy(RendVkArenaAllocator *arena);
-
-/* rend_vk_command_queue.c */
-static inline RendVkDeferredCmds rend_vk_cmdbuf_deferred_create(void);
-static inline void rend_vk_cmdbuf_deferred_destroy(RendVkDeferredCmds *tracker);
-static inline uint64_t rend_vk_cmdbuf_deferred_submit(RendVkDeferredCmds *tracker, VkCommandPool pool, VkCommandBuffer cmd, VkQueue queue, uint64_t wait_value, VkPipelineStageFlags2 wait_stage, VkPipelineStageFlags2 signal_stage);
-static inline void rend_vk_cmdbuf_deferred_push(RendVkDeferredCmds *tracker, VkCommandPool pool, VkCommandBuffer cmd, uint64_t wait_value);
-static inline void rend_vk_cmdbuf_deferred_flush(RendVkDeferredCmds *tracker);
-
-/* rend_vk_image.c */
-static RendVkImage rend_vk_image_create(VkDevice logical_device, VkImageType img_type, uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags memory_flags, uint32_t depth, uint32_t mip_levels, uint32_t layers, VkSampleCountFlags sample_count_flags, VkSharingMode sharing_mode);
-static uint32_t rend_vk_image_required_memory_type(RendVkImage *img);
-static void rend_vk_image_bind_memory(RendVkImage *image, RendMemory *memory);
-static void rend_vk_image_destroy(RendVkImage *img);
-static void rend_vk_image_view_create(RendVkImage *image, VkImageViewType view_type, VkImageAspectFlags view_aspect_flags);
-static uint64_t rend_vk_image_address(RendVkImage *image);
-
-
-static VkAllocationCallbacks *vk_allocator = 0; // we are only ever going to use one, either the default one or the custom one
-
-static VkFormat vk_format_from_rend_format[] = {
- [REND_FORMAT_R8_UNORM] = VK_FORMAT_R8_UNORM,
- [REND_FORMAT_R8G8_UNORM] = VK_FORMAT_R8G8_UNORM,
- [REND_FORMAT_R8G8B8A8_UNORM] = VK_FORMAT_R8G8B8A8_UNORM,
- [REND_FORMAT_B8G8R8A8_UNORM] = VK_FORMAT_B8G8R8A8_UNORM,
- [REND_FORMAT_R8G8B8A8_SRGB] = VK_FORMAT_R8G8B8A8_SRGB,
- [REND_FORMAT_B8G8R8A8_SRGB] = VK_FORMAT_B8G8R8A8_SRGB,
- [REND_FORMAT_R32_SFLOAT] = VK_FORMAT_R32_SFLOAT,
- [REND_FORMAT_R32G32_SFLOAT] = VK_FORMAT_R32G32_SFLOAT,
- [REND_FORMAT_R32G32B32_SFLOAT] = VK_FORMAT_R32G32B32_SFLOAT,
- [REND_FORMAT_R32G32B32A32_SFLOAT]= VK_FORMAT_R32G32B32A32_SFLOAT,
- [REND_FORMAT_R16_SFLOAT] = VK_FORMAT_R16_SFLOAT,
- [REND_FORMAT_R16G16_SFLOAT] = VK_FORMAT_R16G16_SFLOAT,
- [REND_FORMAT_R16G16B16A16_SFLOAT]= VK_FORMAT_R16G16B16A16_SFLOAT,
- [REND_FORMAT_R32_UINT] = VK_FORMAT_R32_UINT,
- [REND_FORMAT_R32_SINT] = VK_FORMAT_R32_SINT,
- [REND_FORMAT_R32G32B32A32_UINT] = VK_FORMAT_R32G32B32A32_UINT,
- [REND_FORMAT_R16G16B16A16_UINT] = VK_FORMAT_R16G16B16A16_UINT,
- [REND_FORMAT_R8G8B8A8_UINT] = VK_FORMAT_R8G8B8A8_UINT,
- [REND_FORMAT_D32_SFLOAT] = VK_FORMAT_D32_SFLOAT,
- [REND_FORMAT_D24_UNORM_S8_UINT] = VK_FORMAT_D24_UNORM_S8_UINT,
- [REND_FORMAT_D32_SFLOAT_S8_UINT] = VK_FORMAT_D32_SFLOAT_S8_UINT,
-};
-
-static VkPrimitiveTopology vk_topology[] = {
- [REND_TOPOLOGY_TRIANGLE_LIST] = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
- [REND_TOPOLOGY_TRIANGLE_STRIP] = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
- [REND_TOPOLOGY_LINE_LIST] = VK_PRIMITIVE_TOPOLOGY_LINE_LIST,
- [REND_TOPOLOGY_LINE_STRIP] = VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,
- [REND_TOPOLOGY_POINT_LIST] = VK_PRIMITIVE_TOPOLOGY_POINT_LIST
-};
-
-static VkPolygonMode vk_polymode[] = {
- [REND_POLYGON_MODE_FILL] = VK_POLYGON_MODE_FILL,
- [REND_POLYGON_MODE_LINE] = VK_POLYGON_MODE_LINE,
- [REND_POLYGON_MODE_POINT] = VK_POLYGON_MODE_POINT,
-};
-
-static VkCullModeFlags vk_cullflags[] = {
- [REND_CULL_MODE_NONE] = VK_CULL_MODE_NONE,
- [REND_CULL_MODE_FRONT] = VK_CULL_MODE_FRONT_BIT,
- [REND_CULL_MODE_BACK] = VK_CULL_MODE_BACK_BIT,
- [REND_CULL_MODE_FRONT_AND_BACK] = VK_CULL_MODE_FRONT_AND_BACK,
-};
-
-static int32_t
-rend_vk_memory_find_index(VkPhysicalDevice device, uint32_t type_filter, VkMemoryPropertyFlags property_flags)
-{
- VkPhysicalDeviceMemoryProperties memory_properties;
- vkGetPhysicalDeviceMemoryProperties(device, &memory_properties);
- for (uint32_t i = 0; i < memory_properties.memoryTypeCount; i++) {
- if (type_filter & (1 << i) && (memory_properties.memoryTypes[i].propertyFlags & property_flags) == property_flags) {
- return i;
- }
- }
-
- return -1;
-}
-
-#endif