started work on async code
This commit is contained in:
parent
0f14ffd37f
commit
4ab1abbc27
13
build.sh
13
build.sh
@ -76,9 +76,10 @@ mkdir -p build
|
|||||||
|
|
||||||
cd build
|
cd build
|
||||||
|
|
||||||
|
mkdir -p ../src/file_data
|
||||||
|
|
||||||
if [ -v vulkan ]; then
|
if [ -v vulkan ]; then
|
||||||
mkdir -p ./shaders/glsl
|
mkdir -p ./shaders/glsl
|
||||||
mkdir -p ../src/file_data
|
|
||||||
|
|
||||||
for file in ../src/shaders/glsl/*.glsl; do
|
for file in ../src/shaders/glsl/*.glsl; do
|
||||||
base_name=$(basename -- "$file" .glsl)
|
base_name=$(basename -- "$file" .glsl)
|
||||||
@ -107,6 +108,16 @@ if [ -v vulkan ]; then
|
|||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
rm -f ../src/file_data/images.c
|
||||||
|
touch ../src/file_data/images.c
|
||||||
|
|
||||||
|
for file in ../assets/*.png; do
|
||||||
|
base_name=$(basename -- "$file" .png)
|
||||||
|
|
||||||
|
xxd -n "image_${base_name}" -i $file >> ../src/file_data/images.c
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
$cpp_compiler $vma_compile_flags $vma_source_files $vma_out $vma_obj
|
$cpp_compiler $vma_compile_flags $vma_source_files $vma_out $vma_obj
|
||||||
|
|
||||||
ar rcs libvma.a vma.o
|
ar rcs libvma.a vma.o
|
||||||
|
|||||||
@ -8,6 +8,45 @@
|
|||||||
#include "renderer.c"
|
#include "renderer.c"
|
||||||
#include "game.c"
|
#include "game.c"
|
||||||
|
|
||||||
|
const char *strs[10] = {
|
||||||
|
"String 1",
|
||||||
|
"String 2",
|
||||||
|
"String 3",
|
||||||
|
"String 4",
|
||||||
|
"String 5",
|
||||||
|
"String 6",
|
||||||
|
"String 7",
|
||||||
|
"String 8",
|
||||||
|
"String 9",
|
||||||
|
"String 10",
|
||||||
|
};
|
||||||
|
u32 volatile str_index = 0;
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
void *ThreadFunc(void *i)
|
||||||
|
{
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
u32 val = __atomic_fetch_add(&str_index, 1, __ATOMIC_RELEASE);
|
||||||
|
if (val < 10)
|
||||||
|
{
|
||||||
|
Printfln("Thread %d: %s", *(u32 *)i, strs[val]);
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_exit(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunThreadFunc(pthread_t *th, u32 *u, void *func)
|
||||||
|
{
|
||||||
|
pthread_create(th, NULL, func, u);
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
u8 *mem = (u8 *)MemAllocZeroed(MB(64));
|
u8 *mem = (u8 *)MemAllocZeroed(MB(64));
|
||||||
|
|||||||
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
|
||||||
#define STB_SPRINTF_IMPLEMENTATION
|
#define STB_SPRINTF_IMPLEMENTATION
|
||||||
|
|
||||||
#define WINDOW_NAME "Video Game"
|
#define WINDOW_NAME "Video Game"
|
||||||
|
|||||||
@ -558,3 +558,10 @@ b32 _ShouldQuit()
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 AvailableCPUCount()
|
||||||
|
{
|
||||||
|
cpu_set_t cpu_set;
|
||||||
|
sched_getaffinity(0, sizeof(cpu_set), &cpu_set);
|
||||||
|
return CPU_COUNT(&cpu_set);
|
||||||
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
@ -17,6 +18,9 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <nmmintrin.h>
|
#include <nmmintrin.h>
|
||||||
|
#include <immintrin.h>
|
||||||
|
|
||||||
|
#include <sched.h>
|
||||||
|
|
||||||
// syscall defines
|
// syscall defines
|
||||||
#define SYS_ERR -1
|
#define SYS_ERR -1
|
||||||
@ -89,6 +93,7 @@ void RepaintWindow();
|
|||||||
|
|
||||||
// General Utils
|
// General Utils
|
||||||
b32 CheckSyscallErr(void *ptr);
|
b32 CheckSyscallErr(void *ptr);
|
||||||
|
u32 AvailableCPUCount();
|
||||||
|
|
||||||
// Write Utils
|
// Write Utils
|
||||||
i32 Write(int fd, void const *str, isize count);
|
i32 Write(int fd, void const *str, isize count);
|
||||||
|
|||||||
@ -34,6 +34,8 @@ typedef enum VertexAttrType_e
|
|||||||
|
|
||||||
// Declarations
|
// Declarations
|
||||||
|
|
||||||
|
typedef u16 DescHandle;
|
||||||
|
|
||||||
// @requirement RenderBuffer type;
|
// @requirement RenderBuffer type;
|
||||||
// @requirement u32 size;
|
// @requirement u32 size;
|
||||||
typedef struct RenderBuffer_t RenderBuffer;
|
typedef struct RenderBuffer_t RenderBuffer;
|
||||||
@ -51,27 +53,29 @@ typedef struct RenderBuffers_t
|
|||||||
|
|
||||||
// Back End API
|
// Back End API
|
||||||
|
|
||||||
// Initialization
|
// ::Initialization::Header::
|
||||||
b32 InitRenderer(Arena *arena);
|
b32 InitRenderer(Arena *arena);
|
||||||
void DestroyRenderer();
|
void DestroyRenderer();
|
||||||
|
|
||||||
// Buffers
|
// ::Buffers::Header::
|
||||||
static b32 CreateBuffer(RenderBuffer *buffer);
|
static b32 CreateBuffer(RenderBuffer *buffer);
|
||||||
static void FreeBuffers(RenderBuffer *buffers, u32 buffer_count);
|
static void FreeBuffers(RenderBuffer *buffers, u32 buffer_count);
|
||||||
static b32 UploadToBuffer(RenderBuffer *buffer, rawptr ptr);
|
static b32 UploadToBuffer(RenderBuffer *buffer, rawptr ptr, u8 thr_ix);
|
||||||
static b32 CreateAndUploadToBuffer(RenderBuffer *buffer, rawptr ptr);
|
static b32 CreateAndUploadToBuffer(RenderBuffer *buffer, rawptr ptr);
|
||||||
static void BindVertexBuffer(RenderBuffer *buffer);
|
static void BindVertexBuffer(RenderBuffer *buffer);
|
||||||
static void BindIndexBuffer(RenderBuffer *buffer);
|
static void BindIndexBuffer(RenderBuffer *buffer);
|
||||||
|
|
||||||
// Uniforms/PushConstants
|
// ::Uniforms::Header:: ::PushConstants::Header::
|
||||||
static void GetViewportSize(Vec2 *size);
|
static void GetViewportSize(Vec2 *size);
|
||||||
static void SetGlobalUniform(ShaderGlobals *globals);
|
static void SetGlobalUniform(ShaderGlobals *globals);
|
||||||
static void SetPushConstants(PushConst *pc);
|
static void SetPushConstants(PushConst *pc);
|
||||||
|
static DescHandle UploadImageUniform();
|
||||||
|
|
||||||
// Config
|
// ::Config::Header::
|
||||||
static void SetRenderResolution(u32 x, u32 y);
|
static void SetRenderResolution(u32 x, u32 y);
|
||||||
|
static void SetRendererAvailableThreads(u32 n);
|
||||||
|
|
||||||
// Rendering
|
// ::Rendering::Header::
|
||||||
static b32 BeginFrame();
|
static b32 BeginFrame();
|
||||||
static b32 FinishFrame();
|
static b32 FinishFrame();
|
||||||
static void DrawIndexed(u32 index_count, u32 instance_count);
|
static void DrawIndexed(u32 index_count, u32 instance_count);
|
||||||
|
|||||||
@ -702,19 +702,19 @@ static b32 VLayersSupported()
|
|||||||
|
|
||||||
static b32 CreateFrameStructures()
|
static b32 CreateFrameStructures()
|
||||||
{
|
{
|
||||||
b32 success = true;
|
b32 success = true;
|
||||||
FrameStructures *data = &renderer.vk.frame;
|
FrameStructures *data = &renderer.vk.frame;
|
||||||
u32 img_count = renderer.vk.sc.img_count;
|
u32 img_count = renderer.vk.sc.img_count;
|
||||||
|
|
||||||
pool_create_info.queueFamilyIndex = renderer.vk.queues.graphics;
|
pool_create_info.queueFamilyIndex = renderer.vk.queues.graphics;
|
||||||
|
|
||||||
renderer.vk.frame.pools = ArenaAlloc(renderer.perm_arena, sizeof(VkCommandPool) * img_count);
|
renderer.vk.frame.pools = ArenaAlloc(renderer.perm_arena, sizeof(VkCommandPool) * img_count);
|
||||||
renderer.vk.frame.buffers = ArenaAlloc(renderer.perm_arena, sizeof(VkCommandBuffer) * img_count);
|
renderer.vk.frame.buffers = ArenaAlloc(renderer.perm_arena, sizeof(VkCommandBuffer) * img_count);
|
||||||
renderer.vk.frame.swapchain_sems = ArenaAlloc(renderer.perm_arena, sizeof(VkSemaphore) * img_count);
|
renderer.vk.frame.swapchain_sems = ArenaAlloc(renderer.perm_arena, sizeof(VkSemaphore) * img_count);
|
||||||
renderer.vk.frame.render_sems = ArenaAlloc(renderer.perm_arena, sizeof(VkSemaphore) * img_count);
|
renderer.vk.frame.render_sems = ArenaAlloc(renderer.perm_arena, sizeof(VkSemaphore) * img_count);
|
||||||
renderer.vk.frame.render_fences = ArenaAlloc(renderer.perm_arena, sizeof(VkFence) * img_count);
|
renderer.vk.frame.render_fences = ArenaAlloc(renderer.perm_arena, sizeof(VkFence) * img_count);
|
||||||
renderer.vk.frame.buffer_destroy_queues = ArenaAlloc(renderer.perm_arena, sizeof(RenderBuffer *) * FRAME_OVERLAP);
|
renderer.vk.frame.buffer_destroy_queues = ArenaAlloc(renderer.perm_arena, sizeof(RenderBuffer *) * FRAME_OVERLAP);
|
||||||
renderer.vk.frame.buffer_counts = ArenaAlloc(renderer.perm_arena, sizeof(u32) * FRAME_OVERLAP);
|
renderer.vk.frame.buffer_counts = ArenaAlloc(renderer.perm_arena, sizeof(u32) * FRAME_OVERLAP);
|
||||||
|
|
||||||
for (u32 i = 0; i < FRAME_OVERLAP; i++)
|
for (u32 i = 0; i < FRAME_OVERLAP; i++)
|
||||||
{
|
{
|
||||||
@ -751,25 +751,40 @@ static b32 CreateFrameStructures()
|
|||||||
|
|
||||||
static b32 CreateImmediateStructures()
|
static b32 CreateImmediateStructures()
|
||||||
{
|
{
|
||||||
b32 success = true;
|
b32 success = true;
|
||||||
VkResult result;
|
VkResult result;
|
||||||
VkDevice device = renderer.vk.device;
|
VkDevice device = renderer.vk.device;
|
||||||
ImmediateStructures *imm = &renderer.vk.imm;
|
ImmediateStructures *imm = &renderer.vk.imm;
|
||||||
|
u8 thread_count = 1;
|
||||||
pool_create_info.queueFamilyIndex = renderer.vk.queues.transfer;
|
pool_create_info.queueFamilyIndex = renderer.vk.queues.transfer;
|
||||||
|
|
||||||
result = vkCreateCommandPool(device, &pool_create_info, NULL, &imm->pool);
|
if (renderer.vk_conf.avail_threads >= 10)
|
||||||
if (result != VK_SUCCESS)
|
thread_count = 3;
|
||||||
success = false;
|
else if (renderer.vk_conf.avail_threads >= 8)
|
||||||
|
thread_count = 2;
|
||||||
|
|
||||||
cmd_buf_info.commandPool = imm->pool;
|
imm->pools = ArenaAlloc(renderer.perm_arena, sizeof(VkCommandPool) * thread_count);
|
||||||
|
imm->cmds = ArenaAlloc(renderer.perm_arena, sizeof(VkCommandBuffer) * thread_count);
|
||||||
|
imm->fences = ArenaAlloc(renderer.perm_arena, sizeof(VkFence) * thread_count);
|
||||||
|
imm->queued_buffers = ArenaAlloc(renderer.perm_arena, sizeof(RenderBuffer) * BUFFER_QUEUE_LEN);
|
||||||
|
imm->data = ArenaAlloc(renderer.perm_arena, sizeof(void *) * BUFFER_QUEUE_LEN);
|
||||||
|
|
||||||
|
for (u32 i = 0; i < thread_count && success; i++)
|
||||||
|
{
|
||||||
|
result = vkCreateCommandPool(device, &pool_create_info, NULL, &imm->pools[i]);
|
||||||
|
if (result != VK_SUCCESS)
|
||||||
|
success = false;
|
||||||
|
|
||||||
result = vkAllocateCommandBuffers(device, &cmd_buf_info, &imm->cmd);
|
cmd_buf_info.commandPool = imm->pools[i];
|
||||||
if (result != VK_SUCCESS)
|
|
||||||
success = false;
|
|
||||||
|
|
||||||
result = vkCreateFence(device, &fence_create_info, NULL, &imm->fence);
|
result = vkAllocateCommandBuffers(device, &cmd_buf_info, &imm->cmds[i]);
|
||||||
if (result != VK_SUCCESS)
|
if (result != VK_SUCCESS)
|
||||||
success = false;
|
success = false;
|
||||||
|
|
||||||
|
result = vkCreateFence(device, &fence_create_info, NULL, &imm->fences[i]);
|
||||||
|
if (result != VK_SUCCESS)
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
@ -997,6 +1012,7 @@ static b32 CreateDescriptors()
|
|||||||
{
|
{
|
||||||
bindings[i].free = ArenaAlloc(renderer.perm_arena, sizeof(u16) * DESC_MAX_BINDINGS);
|
bindings[i].free = ArenaAlloc(renderer.perm_arena, sizeof(u16) * DESC_MAX_BINDINGS);
|
||||||
bindings[i].used = ArenaAlloc(renderer.perm_arena, sizeof(u16) * DESC_MAX_BINDINGS);
|
bindings[i].used = ArenaAlloc(renderer.perm_arena, sizeof(u16) * DESC_MAX_BINDINGS);
|
||||||
|
bindings[i].handle_indices = ArenaAlloc(renderer.perm_arena, sizeof(DescHandle) * DESC_MAX_BINDINGS);
|
||||||
|
|
||||||
u16 free_count = 0;
|
u16 free_count = 0;
|
||||||
for (i32 j = DESC_MAX_BINDINGS-1; j >= 0; j--)
|
for (i32 j = DESC_MAX_BINDINGS-1; j >= 0; j--)
|
||||||
@ -1115,6 +1131,54 @@ static b32 CreateShaderModule(u8 *bytes, u32 len, VkShaderModule *module)
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
|
||||||
|
void *VkLoaderStart(void *i)
|
||||||
|
{
|
||||||
|
u32 index = *(u32 *)i;
|
||||||
|
pthread_t self = pthread_self();
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
u32 job_count = __atomic_load_n(&renderer.vk_conf.job_count, __ATOMIC_RELEASE);
|
||||||
|
if (job_count < 0)
|
||||||
|
{
|
||||||
|
pthread_exit(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (job_count == 0)
|
||||||
|
{
|
||||||
|
__atomic_add_fetch(&renderer.vk_conf.sleeping_count, __ATOMIC_RELEASE);
|
||||||
|
pthread_suspend(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (__atomic_compare_exchange_n(&renderer.vk_conf.job_count, &job_count, job_count-1, false, __ATOMIC_RELEASE, __ATOMIC_RELAXED))
|
||||||
|
{
|
||||||
|
job_count -= 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static b32 StartVkLoaderThreads()
|
||||||
|
{
|
||||||
|
u32 count = renderer.vk_conf.avail_threads;
|
||||||
|
pthread_t *threads = ArenaAlloc(renderer.perm_arena, sizeof(pthread_t) * count);
|
||||||
|
|
||||||
|
for (u32 i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
vk_thread_indices[i] = i;
|
||||||
|
pthread_create(&threads[i], NULL, VkLoaderStart, &vk_thread_indices[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif _WIN32
|
||||||
|
|
||||||
|
#error not yet implemented
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
static void DestroySwapchain()
|
static void DestroySwapchain()
|
||||||
{
|
{
|
||||||
for (u32 i = 0; i < renderer.vk.sc.img_count; i++)
|
for (u32 i = 0; i < renderer.vk.sc.img_count; i++)
|
||||||
|
|||||||
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
#include "file_data/spv.c"
|
#include "file_data/spv.c"
|
||||||
|
|
||||||
// Macros
|
// ::Vulkan::Macros::Header::
|
||||||
|
|
||||||
#define VK_DECLARE(fn) static PFN_##fn fn = NULL
|
#define VK_DECLARE(fn) static PFN_##fn fn = NULL
|
||||||
#define STYPE(type) VK_STRUCTURE_TYPE_ ## type
|
#define STYPE(type) VK_STRUCTURE_TYPE_ ## type
|
||||||
@ -36,19 +36,14 @@
|
|||||||
if (!name) return false; \
|
if (!name) return false; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define FRAME_OVERLAP 2
|
// ::Vulkan::GlobalFunctions::Header::
|
||||||
#define DESC_MAX_BINDINGS 256
|
|
||||||
|
|
||||||
// Macros END
|
|
||||||
|
|
||||||
// Vulkan Functions
|
|
||||||
|
|
||||||
// Global
|
|
||||||
VK_DECLARE(vkGetInstanceProcAddr);
|
VK_DECLARE(vkGetInstanceProcAddr);
|
||||||
VK_DECLARE(vkCreateInstance);
|
VK_DECLARE(vkCreateInstance);
|
||||||
VK_DECLARE(vkEnumerateInstanceLayerProperties);
|
VK_DECLARE(vkEnumerateInstanceLayerProperties);
|
||||||
|
|
||||||
// Instance
|
// ::Vulkan::InstanceFunctions::Header::
|
||||||
|
|
||||||
VK_DECLARE(vkEnumeratePhysicalDevices);
|
VK_DECLARE(vkEnumeratePhysicalDevices);
|
||||||
VK_DECLARE(vkCreateDevice);
|
VK_DECLARE(vkCreateDevice);
|
||||||
VK_DECLARE(vkGetPhysicalDeviceQueueFamilyProperties);
|
VK_DECLARE(vkGetPhysicalDeviceQueueFamilyProperties);
|
||||||
@ -61,6 +56,8 @@ VK_DECLARE(vkGetPhysicalDeviceSurfaceFormatsKHR);
|
|||||||
VK_DECLARE(vkGetPhysicalDeviceSurfaceCapabilitiesKHR);
|
VK_DECLARE(vkGetPhysicalDeviceSurfaceCapabilitiesKHR);
|
||||||
VK_DECLARE(vkGetPhysicalDeviceImageFormatProperties);
|
VK_DECLARE(vkGetPhysicalDeviceImageFormatProperties);
|
||||||
|
|
||||||
|
// ::Vulkan::PlatformFunctions::Header::
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
VK_DECLARE(vkCreateXcbSurfaceKHR);
|
VK_DECLARE(vkCreateXcbSurfaceKHR);
|
||||||
#elif _WIN32
|
#elif _WIN32
|
||||||
@ -77,7 +74,8 @@ VK_DECLARE(vkCreateDebugUtilsMessengerEXT);
|
|||||||
VK_DECLARE(vkDestroyDebugUtilsMessengerEXT);
|
VK_DECLARE(vkDestroyDebugUtilsMessengerEXT);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Device
|
// ::Vulkan::DeviceFunctions::Header::
|
||||||
|
|
||||||
VK_DECLARE(vkGetDeviceProcAddr);
|
VK_DECLARE(vkGetDeviceProcAddr);
|
||||||
VK_DECLARE(vkCreateSwapchainKHR);
|
VK_DECLARE(vkCreateSwapchainKHR);
|
||||||
VK_DECLARE(vkCreateImage);
|
VK_DECLARE(vkCreateImage);
|
||||||
@ -139,14 +137,16 @@ VK_DECLARE(vkCmdDraw);
|
|||||||
VK_DECLARE(vkDeviceWaitIdle);
|
VK_DECLARE(vkDeviceWaitIdle);
|
||||||
VK_DECLARE(vkCmdClearColorImage);
|
VK_DECLARE(vkCmdClearColorImage);
|
||||||
|
|
||||||
// Vulkan Functions END
|
|
||||||
|
|
||||||
#include "vma/vk_mem_alloc.h"
|
#include "vma/vk_mem_alloc.h"
|
||||||
|
|
||||||
// Defines
|
// ::Vulkan::Defines::Header::
|
||||||
|
|
||||||
|
#define FRAME_OVERLAP 2
|
||||||
|
#define DESC_MAX_BINDINGS 256
|
||||||
|
#define BUFFER_QUEUE_LEN 32
|
||||||
#define HOST_VISIBLE_BUFFERS (RENDER_BUFFER_TYPE_UNIFORM | RENDER_BUFFER_TYPE_STAGING)
|
#define HOST_VISIBLE_BUFFERS (RENDER_BUFFER_TYPE_UNIFORM | RENDER_BUFFER_TYPE_STAGING)
|
||||||
|
|
||||||
// Types
|
// ::Vulkan::Types::Header::
|
||||||
|
|
||||||
typedef enum DescType_e
|
typedef enum DescType_e
|
||||||
{
|
{
|
||||||
@ -165,18 +165,18 @@ typedef struct ShaderGlobals_t
|
|||||||
|
|
||||||
typedef struct RenderBuffer_t
|
typedef struct RenderBuffer_t
|
||||||
{
|
{
|
||||||
RenderBufferType type;
|
RenderBufferType type;
|
||||||
VkBuffer buffer;
|
VkBuffer buffer;
|
||||||
VmaAllocation alloc;
|
VmaAllocation alloc;
|
||||||
VmaAllocationInfo info;
|
VmaAllocationInfo info;
|
||||||
u32 size;
|
u32 size;
|
||||||
i32 mem_index; // TODO(MA): use this
|
i32 mem_index; // TODO(MA): use this
|
||||||
} RenderBuffer;
|
} RenderBuffer;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
RenderBuffer index_buf, vertex_buf;
|
RenderBuffer index_buf, vertex_buf;
|
||||||
u32 index_count;
|
u32 index_count;
|
||||||
} MeshBuffer;
|
} MeshBuffer;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
@ -186,21 +186,22 @@ typedef struct
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
u16 *free;
|
u16 *free;
|
||||||
u16 free_count;
|
u16 free_count;
|
||||||
u16 *used;
|
u16 *used;
|
||||||
u16 used_count;
|
u16 used_count;
|
||||||
|
DescHandle *handle_indices;
|
||||||
} DescBindings;
|
} DescBindings;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
VkPipelineLayout pipeline_layout;
|
VkPipelineLayout pipeline_layout;
|
||||||
VkDescriptorPool pool;
|
VkDescriptorPool pool;
|
||||||
VkDescriptorSetLayout layouts[DESC_TYPE_MAX];
|
VkDescriptorSetLayout layouts[DESC_TYPE_MAX];
|
||||||
VkDescriptorSet sets[DESC_TYPE_MAX];
|
VkDescriptorSet sets[DESC_TYPE_MAX];
|
||||||
DescBindings *bindings;
|
DescBindings *bindings;
|
||||||
u16 bindings_count;
|
u16 bindings_count;
|
||||||
VkPipeline pipelines[PIPELINE_MAX];
|
VkPipeline pipelines[PIPELINE_MAX];
|
||||||
} PipelineStructures;
|
} PipelineStructures;
|
||||||
|
|
||||||
typedef struct PushConst_t
|
typedef struct PushConst_t
|
||||||
@ -210,70 +211,75 @@ typedef struct PushConst_t
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
VkCommandPool *pools;
|
VkCommandPool *pools;
|
||||||
VkCommandBuffer *buffers;
|
VkCommandBuffer *buffers;
|
||||||
VkSemaphore *swapchain_sems;
|
VkSemaphore *swapchain_sems;
|
||||||
VkSemaphore *render_sems;
|
VkSemaphore *render_sems;
|
||||||
VkFence *render_fences;
|
VkFence *render_fences;
|
||||||
RenderBuffer **buffer_destroy_queues;
|
RenderBuffer **buffer_destroy_queues;
|
||||||
u32 *buffer_counts;
|
u32 *buffer_counts;
|
||||||
} FrameStructures;
|
} FrameStructures;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
VkCommandPool pool;
|
VkCommandPool *pools;
|
||||||
VkCommandBuffer cmd;
|
VkCommandBuffer *cmds;
|
||||||
VkFence fence;
|
VkFence *fences;
|
||||||
|
RenderBuffer **queued_buffers;
|
||||||
|
void *data;
|
||||||
|
i32 volatile job_count;
|
||||||
|
i32 volatile completed_count;
|
||||||
|
i32 volatile sleeping_count;
|
||||||
} ImmediateStructures;
|
} ImmediateStructures;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
i32 graphics, transfer;
|
i32 graphics, transfer;
|
||||||
VkQueue graphics_queue, transfer_queue;
|
VkQueue graphics_queue, transfer_queue;
|
||||||
} DeviceQueues;
|
} DeviceQueues;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
VkImage img;
|
VkImage img;
|
||||||
VkImageView view;
|
VkImageView view;
|
||||||
VmaAllocation alloc;
|
VmaAllocation alloc;
|
||||||
VkFormat fmt;
|
VkFormat fmt;
|
||||||
VkImageLayout curr_layout;
|
VkImageLayout curr_layout;
|
||||||
} Image;
|
} Image;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
VkFormat format;
|
VkFormat format;
|
||||||
VkColorSpaceKHR color_space;
|
VkColorSpaceKHR color_space;
|
||||||
VkPresentModeKHR present_mode;
|
VkPresentModeKHR present_mode;
|
||||||
VkExtent3D extent;
|
VkExtent3D extent;
|
||||||
VkImage *imgs;
|
VkImage *imgs;
|
||||||
VkImageView *views;
|
VkImageView *views;
|
||||||
u32 img_count;
|
u32 img_count;
|
||||||
Image draw_img;
|
Image draw_img;
|
||||||
Image depth_img;
|
Image depth_img;
|
||||||
} SwapchainStructures;
|
} SwapchainStructures;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 img_ix;
|
u32 img_ix;
|
||||||
u64 frame_cnt;
|
u64 frame_cnt;
|
||||||
u64 prev_frame;
|
u64 prev_frame;
|
||||||
b8 begin_rendering;
|
b8 begin_rendering;
|
||||||
PipelineHandle last_pipeline;
|
PipelineHandle last_pipeline;
|
||||||
RenderBuffer *prev_buffers;
|
RenderBuffer *prev_buffers;
|
||||||
u32 prev_buffer_count;
|
u32 prev_buffer_count;
|
||||||
} FrameState;
|
} FrameState;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Library lib;
|
Library lib;
|
||||||
VkInstance inst;
|
VkInstance inst;
|
||||||
VkSurfaceKHR surface;
|
VkSurfaceKHR surface;
|
||||||
VkDevice device;
|
VkDevice device;
|
||||||
VkSwapchainKHR swapchain;
|
VkSwapchainKHR swapchain;
|
||||||
VkPhysicalDevice phys_device;
|
VkPhysicalDevice phys_device;
|
||||||
DeviceQueues queues;
|
DeviceQueues queues;
|
||||||
VmaAllocator alloc;
|
VmaAllocator alloc;
|
||||||
FrameStructures frame;
|
FrameStructures frame;
|
||||||
ImmediateStructures imm;
|
ImmediateStructures imm;
|
||||||
SwapchainStructures sc;
|
SwapchainStructures sc;
|
||||||
PipelineStructures pipe;
|
PipelineStructures pipe;
|
||||||
#ifdef BUILD_DEBUG
|
#ifdef BUILD_DEBUG
|
||||||
VkDebugUtilsMessengerEXT debug;
|
VkDebugUtilsMessengerEXT debug;
|
||||||
#endif
|
#endif
|
||||||
@ -282,21 +288,33 @@ typedef struct {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
u16 render_width;
|
u16 render_width;
|
||||||
u16 render_height;
|
u16 render_height;
|
||||||
b8 resized;
|
b8 resized;
|
||||||
} PendingUpdates;
|
} PendingUpdates;
|
||||||
|
|
||||||
|
typedef struct VulkanConfig_t
|
||||||
|
{
|
||||||
|
u8 avail_threads;
|
||||||
|
#ifdef __linux__
|
||||||
|
pthread_t *threads;
|
||||||
|
#elif _WIN32
|
||||||
|
#error not yet implemented
|
||||||
|
#endif
|
||||||
|
} VulkanConfig;
|
||||||
|
|
||||||
typedef struct Renderer_t
|
typedef struct Renderer_t
|
||||||
{
|
{
|
||||||
Vulkan_t vk;
|
Vulkan_t vk;
|
||||||
FrameState frame_state;
|
VulkanConfig vk_conf;
|
||||||
|
FrameState frame_state;
|
||||||
PendingUpdates pending;
|
PendingUpdates pending;
|
||||||
Arena *arena;
|
Arena *arena;
|
||||||
Arena *perm_arena;
|
Arena *perm_arena;
|
||||||
} Renderer;
|
} Renderer;
|
||||||
|
|
||||||
// Renderer Function Declarations
|
// ::Vulkan::Functions::Header::
|
||||||
|
|
||||||
|
// ::Vulkan::Debug::Header::
|
||||||
|
|
||||||
// Debug
|
|
||||||
static b32 VLayersSupported();
|
static b32 VLayersSupported();
|
||||||
static VKAPI_ATTR VkBool32 DebugCallback(
|
static VKAPI_ATTR VkBool32 DebugCallback(
|
||||||
VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
|
VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
|
||||||
@ -306,7 +324,8 @@ static VKAPI_ATTR VkBool32 DebugCallback(
|
|||||||
);
|
);
|
||||||
const char *VkResultStr(VkResult result);
|
const char *VkResultStr(VkResult result);
|
||||||
|
|
||||||
// Init
|
// ::Vulkan::Init::Header::
|
||||||
|
|
||||||
static b32 LoadVulkanLib();
|
static b32 LoadVulkanLib();
|
||||||
static b32 InitVkInstanceFunctions();
|
static b32 InitVkInstanceFunctions();
|
||||||
static b32 InitVkGlobalFunctions();
|
static b32 InitVkGlobalFunctions();
|
||||||
@ -326,8 +345,10 @@ static VkFormat GetImageFormat();
|
|||||||
static b32 CreateDescriptors();
|
static b32 CreateDescriptors();
|
||||||
static b32 CreatePipelines();
|
static b32 CreatePipelines();
|
||||||
static b32 CreateShaderModule(u8 *bytes, u32 len, VkShaderModule *module);
|
static b32 CreateShaderModule(u8 *bytes, u32 len, VkShaderModule *module);
|
||||||
|
static b32 StartVkLoaderThreads();
|
||||||
|
|
||||||
|
// ::Vulkan::Util::Header::
|
||||||
|
|
||||||
// Util
|
|
||||||
static inline VkCommandBuffer GetFrameCmdBuf();
|
static inline VkCommandBuffer GetFrameCmdBuf();
|
||||||
static inline VkFence *GetFrameRenderFence();
|
static inline VkFence *GetFrameRenderFence();
|
||||||
static inline VkSemaphore GetFrameRenderSem();
|
static inline VkSemaphore GetFrameRenderSem();
|
||||||
@ -338,36 +359,49 @@ static inline u32 *GetFrameBufferCount();
|
|||||||
static inline RenderBuffer *GetFrameRenderBuffers();
|
static inline RenderBuffer *GetFrameRenderBuffers();
|
||||||
static void BeginRendering();
|
static void BeginRendering();
|
||||||
|
|
||||||
// Immediate Submit
|
// ::Vulkan::Async::Header::
|
||||||
|
#ifdef __linux__
|
||||||
|
void *VkLoaderStart(void *thread_data);
|
||||||
|
#elif _WIN32
|
||||||
|
#error not yet implemented
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ::Vulkan::ImmediateSubmit::Header::
|
||||||
|
|
||||||
static b32 BeginImmSubmit(VkDevice device, VkFence *fence, VkCommandBuffer cmd);
|
static b32 BeginImmSubmit(VkDevice device, VkFence *fence, VkCommandBuffer cmd);
|
||||||
static b32 FinishImmSubmit(VkDevice device, VkFence *fence, VkCommandBuffer cmd, VkQueue queue);
|
static b32 FinishImmSubmit(VkDevice device, VkFence *fence, VkCommandBuffer cmd, VkQueue queue);
|
||||||
|
|
||||||
// Buffers
|
// ::Vulkan::Buffers::Header::
|
||||||
|
|
||||||
static b32 UploadGUIBuffer(MeshBuffer *buf, GUIContext *ctx);
|
static b32 UploadGUIBuffer(MeshBuffer *buf, GUIContext *ctx);
|
||||||
|
|
||||||
// Destroy
|
// ::Vulkan::Destroy::Header::
|
||||||
|
|
||||||
static void DestroySwapchain();
|
static void DestroySwapchain();
|
||||||
static void DestroyDrawImages();
|
static void DestroyDrawImages();
|
||||||
|
|
||||||
// Util
|
// ::Vulkan::Util::Header::
|
||||||
|
|
||||||
static void TransitionImage(VkCommandBuffer cmd, Image *img, VkImageLayout new);
|
static void TransitionImage(VkCommandBuffer cmd, Image *img, VkImageLayout new);
|
||||||
static void TransitionImageLayout(VkCommandBuffer cmd, VkImage img, VkImageLayout curr, VkImageLayout new);
|
static void TransitionImageLayout(VkCommandBuffer cmd, VkImage img, VkImageLayout curr, VkImageLayout new);
|
||||||
static void CopyImageToImage(VkCommandBuffer cmd, VkImage src, VkImage dst, VkExtent2D src_ext, VkExtent2D dst_ext);
|
static void CopyImageToImage(VkCommandBuffer cmd, VkImage src, VkImage dst, VkExtent2D src_ext, VkExtent2D dst_ext);
|
||||||
|
|
||||||
// Swapchain
|
// ::Vulkan::Swapchain::Header::
|
||||||
|
|
||||||
static VkExtent2D SelectSwapchainExtent(VkSurfaceCapabilitiesKHR *capabilities);
|
static VkExtent2D SelectSwapchainExtent(VkSurfaceCapabilitiesKHR *capabilities);
|
||||||
static VkSurfaceFormatKHR SelectSwapchainFormat(VkSurfaceFormatKHR *formats);
|
static VkSurfaceFormatKHR SelectSwapchainFormat(VkSurfaceFormatKHR *formats);
|
||||||
static void ResizeSwapchain();
|
static void ResizeSwapchain();
|
||||||
|
|
||||||
// Logging
|
// ::Vulkan::Logging::Header::
|
||||||
|
|
||||||
static void VkInfo(const char *str);
|
static void VkInfo(const char *str);
|
||||||
static void VkWarn(const char *str);
|
static void VkWarn(const char *str);
|
||||||
static void VkError(const char *str);
|
static void VkError(const char *str);
|
||||||
|
|
||||||
// Renderer Functions Declarations END
|
|
||||||
|
|
||||||
#include "vulkan_config.c"
|
#include "vulkan_config.c"
|
||||||
|
|
||||||
|
// ::Vulkan::Globals::Header::
|
||||||
|
|
||||||
static Renderer renderer = {
|
static Renderer renderer = {
|
||||||
.vk = {
|
.vk = {
|
||||||
.queues = {
|
.queues = {
|
||||||
@ -382,6 +416,10 @@ static Renderer renderer = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static u32 vk_thread_indices[10] = {};
|
||||||
|
|
||||||
|
// ::Vulkan::Constants::Header::
|
||||||
|
|
||||||
static const char *_VK_VALIDATION = "VK_LAYER_KHRONOS_validation";
|
static const char *_VK_VALIDATION = "VK_LAYER_KHRONOS_validation";
|
||||||
|
|
||||||
#if __linux__
|
#if __linux__
|
||||||
|
|||||||
@ -3,6 +3,8 @@
|
|||||||
*/
|
*/
|
||||||
b32 InitRenderer(Arena *arena)
|
b32 InitRenderer(Arena *arena)
|
||||||
{
|
{
|
||||||
|
SetRendererAvailableThreads(AvailableCPUCount());
|
||||||
|
|
||||||
CustomizePipelines();
|
CustomizePipelines();
|
||||||
|
|
||||||
Assert(arena != NULL, "Vulkan memory is null");
|
Assert(arena != NULL, "Vulkan memory is null");
|
||||||
@ -39,6 +41,7 @@ b32 InitRenderer(Arena *arena)
|
|||||||
Assert(CreateImmediateStructures(), "Unable to create immediate structures");
|
Assert(CreateImmediateStructures(), "Unable to create immediate structures");
|
||||||
Assert(CreateDescriptors(), "Unable to initialize descriptors.");
|
Assert(CreateDescriptors(), "Unable to initialize descriptors.");
|
||||||
Assert(CreatePipelines(), "Unable to initialize pipelines.");
|
Assert(CreatePipelines(), "Unable to initialize pipelines.");
|
||||||
|
Assert(StartVkLoaderThreads(), "Unable to initialize vulkan loader threads");
|
||||||
|
|
||||||
ArenaFree(renderer.arena);
|
ArenaFree(renderer.arena);
|
||||||
|
|
||||||
@ -74,9 +77,12 @@ void DestroyRenderer()
|
|||||||
|
|
||||||
DestroySwapchain();
|
DestroySwapchain();
|
||||||
|
|
||||||
vkDestroyFence(device, imm.fence, NULL);
|
for (u32 i = 0; i < renderer.vk_conf.avail_threads; i++)
|
||||||
vkFreeCommandBuffers(device, imm.pool, 1, &imm.cmd);
|
{
|
||||||
vkDestroyCommandPool(device, imm.pool, NULL);
|
vkDestroyFence(device, imm.fences[i], NULL);
|
||||||
|
vkFreeCommandBuffers(device, imm.pools[i], 1, &imm.cmds[i]);
|
||||||
|
vkDestroyCommandPool(device, imm.pools[i], NULL);
|
||||||
|
}
|
||||||
|
|
||||||
for (u32 i = 0; i < FRAME_OVERLAP; i++)
|
for (u32 i = 0; i < FRAME_OVERLAP; i++)
|
||||||
{
|
{
|
||||||
@ -196,14 +202,15 @@ static b32 CreateBuffer(RenderBuffer *buffer)
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
static b32 UploadToBuffer(RenderBuffer *buffer, rawptr ptr)
|
static b32 UploadToBuffer(RenderBuffer *buffer, rawptr ptr, u8 thr_ix)
|
||||||
{
|
{
|
||||||
Assert(buffer, "UploadToBuffer: buffer must not be null");
|
Assert(buffer, "UploadToBuffer: buffer must not be null");
|
||||||
Assert(ptr, "UploadToBuffer: ptr must not be null");
|
Assert(ptr, "UploadToBuffer: ptr must not be null");
|
||||||
|
|
||||||
b32 success = true;
|
b32 success = true;
|
||||||
|
|
||||||
ImmediateStructures *imm = &renderer.vk.imm;
|
VkCommandBuffer cmd = renderer.vk.imm.cmds[thr_ix];
|
||||||
|
VkFence fence = renderer.vk.imm.fences[thr_ix];
|
||||||
VkDevice device = renderer.vk.device;
|
VkDevice device = renderer.vk.device;
|
||||||
VkQueue queue = renderer.vk.queues.transfer_queue;
|
VkQueue queue = renderer.vk.queues.transfer_queue;
|
||||||
VmaAllocator alloc = renderer.vk.alloc;
|
VmaAllocator alloc = renderer.vk.alloc;
|
||||||
@ -231,18 +238,18 @@ static b32 UploadToBuffer(RenderBuffer *buffer, rawptr ptr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
success = BeginImmSubmit(device, &imm->fence, imm->cmd);
|
success = BeginImmSubmit(device, &fence, cmd);
|
||||||
|
|
||||||
b32 imm_started = success;
|
b32 imm_started = success;
|
||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
VkBufferCopy buffer_copy = { .size = (VkDeviceSize)buffer->size };
|
VkBufferCopy buffer_copy = { .size = (VkDeviceSize)buffer->size };
|
||||||
vkCmdCopyBuffer(imm->cmd, staging_buffer.buffer, buffer->buffer, 1, &buffer_copy);
|
vkCmdCopyBuffer(cmd, staging_buffer.buffer, buffer->buffer, 1, &buffer_copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (imm_started)
|
if (imm_started)
|
||||||
FinishImmSubmit(device, &imm->fence, imm->cmd, queue);
|
FinishImmSubmit(device, &fence, cmd, queue);
|
||||||
|
|
||||||
if (buffer_created)
|
if (buffer_created)
|
||||||
{
|
{
|
||||||
@ -254,6 +261,17 @@ static b32 UploadToBuffer(RenderBuffer *buffer, rawptr ptr)
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void CreateAndUploadToBuffer(RenderBuffer *buffer, rawptr ptr)
|
||||||
|
{
|
||||||
|
// TODO: revisit this to see if it could be done better
|
||||||
|
|
||||||
|
u32 i = __atomic_fetch_add(&renderer.vk.imm.job_count, 1, __ATOMIC_RELEASE);
|
||||||
|
|
||||||
|
renderer.vk.imm.queued_buffers[i] = buffer;
|
||||||
|
renderer.vk.imm.data[i] = ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: DELETE
|
||||||
static b32 CreateAndUploadToBuffer(RenderBuffer *buffer, rawptr ptr)
|
static b32 CreateAndUploadToBuffer(RenderBuffer *buffer, rawptr ptr)
|
||||||
{
|
{
|
||||||
b32 success = true;
|
b32 success = true;
|
||||||
@ -261,10 +279,11 @@ static b32 CreateAndUploadToBuffer(RenderBuffer *buffer, rawptr ptr)
|
|||||||
success = CreateBuffer(buffer);
|
success = CreateBuffer(buffer);
|
||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
success = UploadToBuffer(buffer, ptr);
|
success = UploadToBuffer(buffer, ptr, 0); // TODO: DELETE this
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
static void FreeBuffers(RenderBuffer *buffers, u32 buffer_count)
|
static void FreeBuffers(RenderBuffer *buffers, u32 buffer_count)
|
||||||
{
|
{
|
||||||
@ -348,6 +367,11 @@ static void SetRenderResolution(u32 x, u32 y)
|
|||||||
renderer.pending.resized = true;
|
renderer.pending.resized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void SetRendererAvailableThreads(u32 n)
|
||||||
|
{
|
||||||
|
renderer.vk_conf.avail_threads = n;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ::Config::End::
|
* ::Config::End::
|
||||||
*/
|
*/
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user