hello triangle completed
This commit is contained in:
parent
e04111aefb
commit
3279fabb1b
71
src/game.c
Normal file
71
src/game.c
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
static void Run()
|
||||||
|
{
|
||||||
|
InitPlatform();
|
||||||
|
|
||||||
|
u8 *mem = (u8 *)MemAllocZeroed(MB(512));
|
||||||
|
Arena *arena = CreateArenaDebug(mem, MB(512), __LINE__);
|
||||||
|
|
||||||
|
isize renderer_mem_size = MB(8);
|
||||||
|
|
||||||
|
rawptr renderer_mem = ArenaAlloc(arena, renderer_mem_size);
|
||||||
|
Arena *renderer_arena = CreateArenaDebug(renderer_mem, MB(8), __LINE__);
|
||||||
|
|
||||||
|
Assert(CreateWindow(), "Failed to initialize the window");
|
||||||
|
Assert(InitRenderer(renderer_arena), "Failed to initialize the renderer");
|
||||||
|
|
||||||
|
b32 quit = false;
|
||||||
|
while (!quit)
|
||||||
|
{
|
||||||
|
if (HandleEvents()) break;
|
||||||
|
|
||||||
|
BeginFrame();
|
||||||
|
DrawTriangle();
|
||||||
|
FinishFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
DestroyRenderer();
|
||||||
|
}
|
||||||
|
|
||||||
|
static b32 HandleEvents()
|
||||||
|
{
|
||||||
|
b32 quit = false;
|
||||||
|
|
||||||
|
WindowEvent e;
|
||||||
|
while (GetWindowEvent(&e))
|
||||||
|
{
|
||||||
|
quit = ProcessEvent(&e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return quit;
|
||||||
|
}
|
||||||
|
|
||||||
|
static b32 WaitForAndHandleEvent()
|
||||||
|
{
|
||||||
|
WindowEvent e;
|
||||||
|
WaitForWindowEvent(&e);
|
||||||
|
return ProcessEvent(&e);
|
||||||
|
}
|
||||||
|
|
||||||
|
static b32 ProcessEvent(WindowEvent *e)
|
||||||
|
{
|
||||||
|
b32 quit = false;
|
||||||
|
|
||||||
|
switch (e->type)
|
||||||
|
{
|
||||||
|
case EVENT_QUIT:
|
||||||
|
quit = true;
|
||||||
|
break;
|
||||||
|
case EVENT_RESIZE:
|
||||||
|
SetRenderResolution(e->resize.w, e->resize.h);
|
||||||
|
break;
|
||||||
|
case EVENT_MINIMIZE:
|
||||||
|
break;
|
||||||
|
case EVENT_SHOW:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return quit;
|
||||||
|
}
|
||||||
|
|
||||||
6
src/game.h
Normal file
6
src/game.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
static void Run();
|
||||||
|
static b32 HandleEvents();
|
||||||
|
static b32 WaitForAndHandleEvent();
|
||||||
|
static b32 ProcessEvent(WindowEvent *e);
|
||||||
39
src/main.c
39
src/main.c
@ -4,44 +4,9 @@
|
|||||||
#include "util.c"
|
#include "util.c"
|
||||||
#include "arena.c"
|
#include "arena.c"
|
||||||
#include "render.c"
|
#include "render.c"
|
||||||
|
#include "game.c"
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
InitPlatform();
|
Run();
|
||||||
|
|
||||||
u8 *mem = (u8 *)MemAllocZeroed(MB(512));
|
|
||||||
Arena *arena = CreateArenaDebug(mem, MB(512), __LINE__);
|
|
||||||
|
|
||||||
isize renderer_mem_size = MB(8);
|
|
||||||
|
|
||||||
rawptr renderer_mem = ArenaAlloc(arena, renderer_mem_size);
|
|
||||||
Arena *renderer_arena = CreateArenaDebug(renderer_mem, MB(8), __LINE__);
|
|
||||||
|
|
||||||
Assert(CreateWindow(), "Failed to initialize the window");
|
|
||||||
Assert(InitRenderer(renderer_arena), "Failed to initialize the renderer");
|
|
||||||
|
|
||||||
b32 quit = false;
|
|
||||||
WindowEvent e;
|
|
||||||
while (!quit)
|
|
||||||
{
|
|
||||||
while (GetWindowEvent(&e))
|
|
||||||
{
|
|
||||||
switch (e.type)
|
|
||||||
{
|
|
||||||
case EVENT_QUIT:
|
|
||||||
quit = true;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BeginFrame();
|
|
||||||
DrawTriangle();
|
|
||||||
FinishFrame();
|
|
||||||
}
|
|
||||||
|
|
||||||
DestroyRenderer();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,5 +12,6 @@
|
|||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "arena.h"
|
#include "arena.h"
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
|
#include "game.h"
|
||||||
|
|
||||||
int main(int argc, char **argv);
|
int main(int argc, char **argv);
|
||||||
|
|||||||
@ -97,6 +97,11 @@ b32 GetWindowEvent(WindowEvent *event)
|
|||||||
return _GetWindowEvent(event);
|
return _GetWindowEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WaitForWindowEvent(WindowEvent *event)
|
||||||
|
{
|
||||||
|
_WaitForWindowEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
WindowSize GetWindowSize()
|
WindowSize GetWindowSize()
|
||||||
{
|
{
|
||||||
return _GetWindowSize();
|
return _GetWindowSize();
|
||||||
|
|||||||
@ -25,6 +25,8 @@ enum Event_e
|
|||||||
EVENT_NONE = 0,
|
EVENT_NONE = 0,
|
||||||
EVENT_QUIT,
|
EVENT_QUIT,
|
||||||
EVENT_RESIZE,
|
EVENT_RESIZE,
|
||||||
|
EVENT_MINIMIZE,
|
||||||
|
EVENT_SHOW,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WindowSize
|
struct WindowSize
|
||||||
@ -62,6 +64,7 @@ i32 EPrintf(const char *fmt, ...);
|
|||||||
b32 CreateWindow();
|
b32 CreateWindow();
|
||||||
Window *GetWindow();
|
Window *GetWindow();
|
||||||
b32 GetWindowEvent(WindowEvent *event);
|
b32 GetWindowEvent(WindowEvent *event);
|
||||||
|
void WaitForWindowEvent(WindowEvent *event);
|
||||||
WindowSize GetWindowSize();
|
WindowSize GetWindowSize();
|
||||||
|
|
||||||
// Directory Functions
|
// Directory Functions
|
||||||
|
|||||||
@ -140,7 +140,8 @@ b32 _CreateWindow()
|
|||||||
{
|
{
|
||||||
Window *window = &linux_window;
|
Window *window = &linux_window;
|
||||||
|
|
||||||
window->connection = xcb_connect(NULL, NULL);
|
int screen_index;
|
||||||
|
window->connection = xcb_connect(NULL, &screen_index);
|
||||||
|
|
||||||
if (!window->connection) {
|
if (!window->connection) {
|
||||||
return false;
|
return false;
|
||||||
@ -159,23 +160,23 @@ b32 _CreateWindow()
|
|||||||
XCB_EVENT_MASK_BUTTON_PRESS |
|
XCB_EVENT_MASK_BUTTON_PRESS |
|
||||||
XCB_EVENT_MASK_BUTTON_RELEASE |
|
XCB_EVENT_MASK_BUTTON_RELEASE |
|
||||||
XCB_EVENT_MASK_POINTER_MOTION |
|
XCB_EVENT_MASK_POINTER_MOTION |
|
||||||
XCB_EVENT_MASK_BUTTON_MOTION |
|
XCB_EVENT_MASK_STRUCTURE_NOTIFY;
|
||||||
XCB_EVENT_MASK_STRUCTURE_NOTIFY|
|
|
||||||
XCB_EVENT_MASK_RESIZE_REDIRECT;
|
|
||||||
|
|
||||||
const int val_win[] = {event_mask, 0};
|
const int val_win[] = {screen->black_pixel, event_mask};
|
||||||
const int val_mask = XCB_CW_EVENT_MASK;
|
const int val_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
|
||||||
|
|
||||||
window->window = xcb_generate_id(window->connection);
|
window->window = xcb_generate_id(window->connection);
|
||||||
|
|
||||||
cookie = xcb_create_window_checked(
|
cookie = xcb_create_window(
|
||||||
window->connection,
|
window->connection,
|
||||||
XCB_COPY_FROM_PARENT,
|
XCB_COPY_FROM_PARENT,
|
||||||
window->window,
|
window->window,
|
||||||
screen->root,
|
screen->root,
|
||||||
0, 0, // x/y pos
|
0, // x pos
|
||||||
window->w, window->h,
|
0, // y pos
|
||||||
10,
|
window->w, // width
|
||||||
|
window->h, // height
|
||||||
|
0,
|
||||||
XCB_WINDOW_CLASS_INPUT_OUTPUT,
|
XCB_WINDOW_CLASS_INPUT_OUTPUT,
|
||||||
screen->root_visual,
|
screen->root_visual,
|
||||||
val_mask,
|
val_mask,
|
||||||
@ -206,6 +207,10 @@ b32 _CreateWindow()
|
|||||||
xcb_intern_atom_reply_t *r_close = xcb_intern_atom_reply(window->connection, c_close, &error);
|
xcb_intern_atom_reply_t *r_close = xcb_intern_atom_reply(window->connection, c_close, &error);
|
||||||
XCB_CHECK_CURRENT_ERROR(window, error, "Failed to get WM_DELETE_WINDOW.");
|
XCB_CHECK_CURRENT_ERROR(window, error, "Failed to get WM_DELETE_WINDOW.");
|
||||||
|
|
||||||
|
xcb_intern_atom_cookie_t c_minimize = xcb_intern_atom(window->connection, 0, 20, "_NET_WM_STATE_HIDDEN");
|
||||||
|
xcb_intern_atom_reply_t *r_minimize = xcb_intern_atom_reply(window->connection, c_minimize, &error);
|
||||||
|
XCB_CHECK_CURRENT_ERROR(window, error, "Failed to get _NET_WM_STATE_HIDDEN");
|
||||||
|
|
||||||
cookie = xcb_change_property_checked(
|
cookie = xcb_change_property_checked(
|
||||||
window->connection,
|
window->connection,
|
||||||
XCB_PROP_MODE_REPLACE,
|
XCB_PROP_MODE_REPLACE,
|
||||||
@ -219,6 +224,20 @@ b32 _CreateWindow()
|
|||||||
XCB_CHECK_ERROR(window, cookie, error, "Failed to set window close event.");
|
XCB_CHECK_ERROR(window, cookie, error, "Failed to set window close event.");
|
||||||
|
|
||||||
window->close_event = r_close->atom;
|
window->close_event = r_close->atom;
|
||||||
|
window->minimize_event = r_minimize->atom;
|
||||||
|
|
||||||
|
free(r_proto);
|
||||||
|
free(r_close);
|
||||||
|
free(r_minimize);
|
||||||
|
|
||||||
|
xcb_map_window(window->connection, window->window);
|
||||||
|
|
||||||
|
i32 stream_result = xcb_flush(window->connection);
|
||||||
|
if (stream_result <= 0)
|
||||||
|
{
|
||||||
|
Printfln("Error flushing the stream: %d", stream_result);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -236,6 +255,16 @@ WindowSize _GetWindowSize()
|
|||||||
}
|
}
|
||||||
|
|
||||||
b32 _GetWindowEvent(WindowEvent *event)
|
b32 _GetWindowEvent(WindowEvent *event)
|
||||||
|
{
|
||||||
|
return HandleWindowEvent(event, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _WaitForWindowEvent(WindowEvent *event)
|
||||||
|
{
|
||||||
|
HandleWindowEvent(event, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
b32 HandleWindowEvent(WindowEvent *event, b32 wait_for_event)
|
||||||
{
|
{
|
||||||
Assert(event != NULL, "GetWindowEvent received a null pointer");
|
Assert(event != NULL, "GetWindowEvent received a null pointer");
|
||||||
|
|
||||||
@ -243,8 +272,13 @@ b32 _GetWindowEvent(WindowEvent *event)
|
|||||||
b32 no_event = false;
|
b32 no_event = false;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
xcb_generic_event_t *e = xcb_poll_for_event(linux_window.connection);
|
xcb_generic_event_t *e;
|
||||||
|
if (wait_for_event)
|
||||||
|
e = xcb_wait_for_event(linux_window.connection);
|
||||||
|
else
|
||||||
|
e = xcb_poll_for_event(linux_window.connection);
|
||||||
|
|
||||||
|
// XCB_UNMAP_NOTIFY
|
||||||
if (e != NULL)
|
if (e != NULL)
|
||||||
{
|
{
|
||||||
switch (e->response_type & ~0x80)
|
switch (e->response_type & ~0x80)
|
||||||
@ -256,34 +290,55 @@ b32 _GetWindowEvent(WindowEvent *event)
|
|||||||
event->type = EVENT_QUIT;
|
event->type = EVENT_QUIT;
|
||||||
valid_event = true;
|
valid_event = true;
|
||||||
}
|
}
|
||||||
|
if (msg->data.data32[0] == linux_window.minimize_event)
|
||||||
|
{
|
||||||
|
event->type = EVENT_MINIMIZE;
|
||||||
|
valid_event = true;
|
||||||
|
linux_window.w = 0;
|
||||||
|
linux_window.h = 0;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case XCB_RESIZE_REQUEST:
|
case XCB_UNMAP_NOTIFY:
|
||||||
|
break;
|
||||||
|
case XCB_EXPOSE:
|
||||||
|
event->type = EVENT_SHOW;
|
||||||
|
|
||||||
|
xcb_expose_event_t *expose_e = (xcb_expose_event_t *)e;
|
||||||
|
linux_window.w = expose_e->width;
|
||||||
|
linux_window.h = expose_e->height;
|
||||||
|
break;
|
||||||
|
case XCB_CONFIGURE_NOTIFY:
|
||||||
|
Printfln("configure notify");
|
||||||
|
xcb_configure_notify_event_t *configure_event = (xcb_configure_notify_event_t *)e;
|
||||||
|
|
||||||
|
if (linux_window.w != configure_event->width || linux_window.h != configure_event->height)
|
||||||
|
{
|
||||||
|
|
||||||
|
Printfln("inner w %d h %d", configure_event->width, configure_event->height);
|
||||||
event->type = EVENT_RESIZE;
|
event->type = EVENT_RESIZE;
|
||||||
valid_event = true;
|
valid_event = true;
|
||||||
|
|
||||||
xcb_resize_request_event_t *resize = (xcb_resize_request_event_t *)e;
|
event->resize.w = configure_event->width;
|
||||||
|
event->resize.h = configure_event->height;
|
||||||
|
|
||||||
if (resize->width > 0)
|
linux_window.w = configure_event->width;
|
||||||
{
|
linux_window.h = configure_event->height;
|
||||||
linux_window.w = resize->width;
|
|
||||||
event->resize.w = resize->width;
|
|
||||||
}
|
|
||||||
if (resize->height > 0)
|
|
||||||
{
|
|
||||||
linux_window.h = resize->height;
|
|
||||||
event->resize.h = resize->height;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(e);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} while(!valid_event);
|
|
||||||
|
|
||||||
|
} while(!valid_event && !wait_for_event);
|
||||||
|
|
||||||
return valid_event;
|
return valid_event;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -62,6 +62,7 @@ typedef size_t usize;
|
|||||||
typedef float f32;
|
typedef float f32;
|
||||||
typedef double f64;
|
typedef double f64;
|
||||||
|
|
||||||
|
typedef uint8_t b8;
|
||||||
typedef uint32_t b32;
|
typedef uint32_t b32;
|
||||||
|
|
||||||
typedef void * rawptr;
|
typedef void * rawptr;
|
||||||
@ -70,6 +71,7 @@ typedef struct {
|
|||||||
xcb_connection_t *connection;
|
xcb_connection_t *connection;
|
||||||
xcb_window_t window;
|
xcb_window_t window;
|
||||||
xcb_atom_t close_event;
|
xcb_atom_t close_event;
|
||||||
|
xcb_atom_t minimize_event;
|
||||||
u16 w, h;
|
u16 w, h;
|
||||||
} Window;
|
} Window;
|
||||||
|
|
||||||
@ -81,6 +83,36 @@ typedef struct {
|
|||||||
void *fn;
|
void *fn;
|
||||||
} Function;
|
} Function;
|
||||||
|
|
||||||
|
// X11
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
|
||||||
|
} XConnectRequest;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u8 opcode;
|
||||||
|
u16 len; // length in units of 4 bytes
|
||||||
|
u8 data;
|
||||||
|
// Extra data
|
||||||
|
} XRequest;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u32 len;
|
||||||
|
} XReply;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
|
||||||
|
} XError;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
|
||||||
|
} XEvent;
|
||||||
|
|
||||||
|
typedef u32 XWindow;
|
||||||
|
typedef u32 XAtom;
|
||||||
|
typedef u32 XVisID;
|
||||||
|
|
||||||
// Platform API
|
// Platform API
|
||||||
|
|
||||||
// Init Functions
|
// Init Functions
|
||||||
@ -103,7 +135,9 @@ i32 _EPrintf(const char *fmt, va_list arg);
|
|||||||
b32 _CreateWindow();
|
b32 _CreateWindow();
|
||||||
Window *_GetWindow();
|
Window *_GetWindow();
|
||||||
b32 _GetWindowEvent(WindowEvent *event);
|
b32 _GetWindowEvent(WindowEvent *event);
|
||||||
|
void _WaitForWindowEvent(WindowEvent *event);
|
||||||
WindowSize _GetWindowSize();
|
WindowSize _GetWindowSize();
|
||||||
|
b32 HandleWindowEvent(WindowEvent *event, b32 wait_for_event);
|
||||||
|
|
||||||
// Platform API END
|
// Platform API END
|
||||||
|
|
||||||
|
|||||||
@ -36,3 +36,8 @@ b32 FinishFrame()
|
|||||||
{
|
{
|
||||||
return _FinishFrame();
|
return _FinishFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetRenderResolution(u32 x, u32 y)
|
||||||
|
{
|
||||||
|
_SetRenderResolution(x, y);
|
||||||
|
}
|
||||||
|
|||||||
@ -23,4 +23,4 @@ void DestroyRenderer();
|
|||||||
static b32 DrawFrame();
|
static b32 DrawFrame();
|
||||||
static void DrawTriangle();
|
static void DrawTriangle();
|
||||||
static b32 FinishFrame();
|
static b32 FinishFrame();
|
||||||
|
static void SetRenderResolution(u32 x, u32 y);
|
||||||
|
|||||||
@ -15,22 +15,45 @@ void _DestroyRenderer()
|
|||||||
DestroyVulkan();
|
DestroyVulkan();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static u32 GetFrameIndex()
|
||||||
|
{
|
||||||
|
return renderer.frame_state.frame_cnt % renderer.vk.sc.img_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VkCommandBuffer GetFrameCmdBuf()
|
||||||
|
{
|
||||||
|
return renderer.vk.frame.buffers[GetFrameIndex()];
|
||||||
|
}
|
||||||
|
|
||||||
|
static VkFence *GetFrameRenderFence()
|
||||||
|
{
|
||||||
|
return &renderer.vk.frame.render_fences[GetFrameIndex()];
|
||||||
|
}
|
||||||
|
|
||||||
|
static VkSemaphore GetFrameRenderSem()
|
||||||
|
{
|
||||||
|
return renderer.vk.frame.render_sems[GetFrameIndex()];
|
||||||
|
}
|
||||||
|
|
||||||
|
static VkSemaphore GetFrameSwapSem()
|
||||||
|
{
|
||||||
|
return renderer.vk.frame.swapchain_sems[GetFrameIndex()];
|
||||||
|
}
|
||||||
|
|
||||||
b32 _BeginFrame()
|
b32 _BeginFrame()
|
||||||
{
|
{
|
||||||
b32 success = true;
|
b32 success = true;
|
||||||
VkResult result;
|
VkResult result;
|
||||||
|
|
||||||
u8 f_ix = renderer.frame_state.frame_cnt % FRAME_OVERLAP;
|
|
||||||
|
|
||||||
VkDevice device = renderer.vk.device;
|
VkDevice device = renderer.vk.device;
|
||||||
VkCommandBuffer cmd = renderer.vk.frame.buffers[f_ix];
|
|
||||||
VkFence fence = renderer.vk.frame.render_fences[f_ix];
|
|
||||||
VkSemaphore sc_sem = renderer.vk.frame.swapchain_sems[f_ix];
|
|
||||||
VkSemaphore rndr_sem = renderer.vk.frame.render_sems[f_ix];
|
|
||||||
VkSwapchainKHR swapchain = renderer.vk.swapchain;
|
VkSwapchainKHR swapchain = renderer.vk.swapchain;
|
||||||
|
VkCommandBuffer cmd = GetFrameCmdBuf();
|
||||||
|
VkFence *fence = GetFrameRenderFence();
|
||||||
|
VkSemaphore sc_sem = GetFrameSwapSem();
|
||||||
|
VkSemaphore rndr_sem = GetFrameRenderSem();
|
||||||
|
|
||||||
// TODO(MA): make this work with VK_PRESENT_MODE_MAILBOX_KHR and remove assignment of present mode to FIFO
|
// TODO(MA): make this work with VK_PRESENT_MODE_MAILBOX_KHR and remove assignment of present mode to FIFO
|
||||||
result = vkWaitForFences(device, 1, &fence, VK_TRUE, 1000000000);
|
result = vkWaitForFences(device, 1, fence, VK_TRUE, 1000000000);
|
||||||
if (result != VK_SUCCESS)
|
if (result != VK_SUCCESS)
|
||||||
{
|
{
|
||||||
Printf("vkWaitForFences failure: %s", VkResultStr(result));
|
Printf("vkWaitForFences failure: %s", VkResultStr(result));
|
||||||
@ -39,20 +62,22 @@ b32 _BeginFrame()
|
|||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
result = vkAcquireNextImageKHR(device, swapchain, 1000000000, sc_sem, 0, &renderer.frame_state.img_ix);
|
result = vkResetFences(device, 1, fence);
|
||||||
if (result != VK_SUCCESS)
|
if (result != VK_SUCCESS)
|
||||||
{
|
{
|
||||||
Printf("vkAcquireNextImageKHR failure: %s", VkResultStr(result));
|
Printf("vkResetFences failure: %s", VkResultStr(result));
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
result = vkResetFences(device, 1, &fence);
|
result = vkAcquireNextImageKHR(device, swapchain, 1000000000, sc_sem, 0, &renderer.frame_state.img_ix);
|
||||||
if (result != VK_SUCCESS)
|
if (result == VK_ERROR_OUT_OF_DATE_KHR)
|
||||||
|
ResizeSwapchain();
|
||||||
|
else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR)
|
||||||
{
|
{
|
||||||
Printf("vkResetFences failure: %s", VkResultStr(result));
|
Printf("vkAcquireNextImageKHR failure: %s", VkResultStr(result));
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -67,6 +92,7 @@ b32 _BeginFrame()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
VkCommandBufferBeginInfo cmd_info = {
|
VkCommandBufferBeginInfo cmd_info = {
|
||||||
@ -85,9 +111,14 @@ b32 _BeginFrame()
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _ClearScreen()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void _DrawTriangle()
|
void _DrawTriangle()
|
||||||
{
|
{
|
||||||
u8 f_ix = renderer.frame_state.frame_cnt % FRAME_OVERLAP;
|
u32 f_ix = renderer.frame_state.frame_cnt % renderer.vk.sc.img_count;
|
||||||
|
|
||||||
VkCommandBuffer cmd = renderer.vk.frame.buffers[f_ix];
|
VkCommandBuffer cmd = renderer.vk.frame.buffers[f_ix];
|
||||||
|
|
||||||
@ -106,7 +137,7 @@ void _DrawTriangle()
|
|||||||
.sType = STYPE(RENDERING_ATTACHMENT_INFO),
|
.sType = STYPE(RENDERING_ATTACHMENT_INFO),
|
||||||
.imageView = renderer.vk.sc.depth_img.view,
|
.imageView = renderer.vk.sc.depth_img.view,
|
||||||
.imageLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL,
|
.imageLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL,
|
||||||
.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
|
.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
|
||||||
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
|
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -146,7 +177,7 @@ void _DrawTriangle()
|
|||||||
|
|
||||||
vkCmdSetScissor(cmd, 0, 1, &scissor);
|
vkCmdSetScissor(cmd, 0, 1, &scissor);
|
||||||
|
|
||||||
vkCmdDrawIndexed(cmd, 3, 1, 0, 0, 0);
|
vkCmdDraw(cmd, 3, 1, 0, 0);
|
||||||
|
|
||||||
// TODO(MA): maybe store current image layout between functions
|
// TODO(MA): maybe store current image layout between functions
|
||||||
}
|
}
|
||||||
@ -156,26 +187,27 @@ b32 _FinishFrame()
|
|||||||
b32 success = true;
|
b32 success = true;
|
||||||
VkResult result;
|
VkResult result;
|
||||||
|
|
||||||
u32 f_ix = renderer.frame_state.frame_cnt % FRAME_OVERLAP;
|
u32 f_ix = renderer.frame_state.frame_cnt % renderer.vk.sc.img_count;
|
||||||
|
|
||||||
VkCommandBuffer cmd = renderer.vk.frame.buffers[f_ix];
|
VkCommandBuffer cmd = renderer.vk.frame.buffers[f_ix];
|
||||||
VkSemaphore sc_sem = renderer.vk.frame.swapchain_sems[f_ix];
|
VkSemaphore sc_sem = renderer.vk.frame.swapchain_sems[f_ix];
|
||||||
VkSemaphore rndr_sem = renderer.vk.frame.render_sems[f_ix];
|
VkSemaphore rndr_sem = renderer.vk.frame.render_sems[f_ix];
|
||||||
VkFence fence = renderer.vk.frame.render_fences[f_ix];
|
VkFence fence = renderer.vk.frame.render_fences[f_ix];
|
||||||
|
VkImage curr_img = renderer.vk.sc.imgs[renderer.frame_state.img_ix];
|
||||||
|
|
||||||
vkCmdEndRendering(cmd);
|
vkCmdEndRendering(cmd);
|
||||||
|
|
||||||
TransitionImage(cmd, renderer.vk.sc.draw_img.img, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
TransitionImage(cmd, renderer.vk.sc.draw_img.img, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
||||||
TransitionImage(cmd, renderer.vk.sc.imgs[f_ix], VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
TransitionImage(cmd, curr_img, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||||
|
|
||||||
VkExtent2D extent = {
|
VkExtent2D extent = {
|
||||||
.width = renderer.vk.sc.extent.width,
|
.width = renderer.vk.sc.extent.width,
|
||||||
.height = renderer.vk.sc.extent.height,
|
.height = renderer.vk.sc.extent.height,
|
||||||
};
|
};
|
||||||
|
|
||||||
CopyImageToImage(cmd, renderer.vk.sc.draw_img.img, renderer.vk.sc.imgs[f_ix], extent, extent);
|
CopyImageToImage(cmd, renderer.vk.sc.draw_img.img, curr_img, extent, extent);
|
||||||
|
|
||||||
TransitionImage(cmd, renderer.vk.sc.imgs[f_ix], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
TransitionImage(cmd, curr_img, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
||||||
|
|
||||||
result = vkEndCommandBuffer(cmd);
|
result = vkEndCommandBuffer(cmd);
|
||||||
if (result != VK_SUCCESS)
|
if (result != VK_SUCCESS)
|
||||||
@ -231,20 +263,34 @@ b32 _FinishFrame()
|
|||||||
.swapchainCount = 1,
|
.swapchainCount = 1,
|
||||||
.pWaitSemaphores = &rndr_sem,
|
.pWaitSemaphores = &rndr_sem,
|
||||||
.waitSemaphoreCount = 1,
|
.waitSemaphoreCount = 1,
|
||||||
.pImageIndices = &f_ix,
|
.pImageIndices = &renderer.frame_state.img_ix,
|
||||||
};
|
};
|
||||||
|
|
||||||
result = vkQueuePresentKHR(renderer.vk.queues.graphics_queue, &present_info);
|
result = vkQueuePresentKHR(renderer.vk.queues.graphics_queue, &present_info);
|
||||||
if (result != VK_SUCCESS)
|
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || renderer.resize_requested)
|
||||||
|
{
|
||||||
|
renderer.resize_requested = false;
|
||||||
|
ResizeSwapchain();
|
||||||
|
}
|
||||||
|
else if (result != VK_SUCCESS)
|
||||||
{
|
{
|
||||||
Printf("vkQueuePresentKHR failure: %s", VkResultStr(result));
|
Printf("vkQueuePresentKHR failure: %s", VkResultStr(result));
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderer.frame_state.frame_cnt++;
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _SetRenderResolution(u32 x, u32 y)
|
||||||
|
{
|
||||||
|
renderer.vk.sc.extent.width = x;
|
||||||
|
renderer.vk.sc.extent.height = y;
|
||||||
|
renderer.resize_requested = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BACK END API END
|
* BACK END API END
|
||||||
@ -254,6 +300,21 @@ b32 _FinishFrame()
|
|||||||
* INTERNAL API
|
* INTERNAL API
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Swapchain
|
||||||
|
static void ResizeSwapchain()
|
||||||
|
{
|
||||||
|
vkDeviceWaitIdle(renderer.vk.device);
|
||||||
|
|
||||||
|
DestroySwapchain();
|
||||||
|
|
||||||
|
DestroyDrawImages();
|
||||||
|
|
||||||
|
Assert(CreateSwapchain(), "Unable to recreate swapchain");
|
||||||
|
Assert(CreateDrawImages(), "Unable to recreate draw images");
|
||||||
|
|
||||||
|
renderer.resize_requested = false;
|
||||||
|
}
|
||||||
|
|
||||||
// UTIL
|
// UTIL
|
||||||
|
|
||||||
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)
|
||||||
@ -285,7 +346,7 @@ static void CopyImageToImage(VkCommandBuffer cmd, VkImage src, VkImage dst, VkEx
|
|||||||
VkBlitImageInfo2 blit_info = {
|
VkBlitImageInfo2 blit_info = {
|
||||||
.sType = STYPE(BLIT_IMAGE_INFO_2),
|
.sType = STYPE(BLIT_IMAGE_INFO_2),
|
||||||
.srcImage = src,
|
.srcImage = src,
|
||||||
.srcImageLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
.srcImageLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||||
.dstImage = dst,
|
.dstImage = dst,
|
||||||
.dstImageLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
.dstImageLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||||
.filter = VK_FILTER_LINEAR,
|
.filter = VK_FILTER_LINEAR,
|
||||||
@ -350,9 +411,10 @@ static b32 InitVulkan(Arena *arena)
|
|||||||
Assert(CreateDevice(), "Unable to create device");
|
Assert(CreateDevice(), "Unable to create device");
|
||||||
|
|
||||||
Assert(CreateVmaAllocator(), "Unable to create VMA allocator");
|
Assert(CreateVmaAllocator(), "Unable to create VMA allocator");
|
||||||
|
Assert(CreateSwapchain(), "Unable to initialize swapchain and draw images");
|
||||||
|
Assert(CreateDrawImages(), "Unable to create draw images");
|
||||||
Assert(CreateFrameStructures(), "Unable to create frame structures");
|
Assert(CreateFrameStructures(), "Unable to create frame structures");
|
||||||
Assert(CreateImmediateStructures(), "Unable to create immediate structures");
|
Assert(CreateImmediateStructures(), "Unable to create immediate structures");
|
||||||
Assert(CreateSwapchain(), "Unable to initialize swapchain and draw images");
|
|
||||||
Assert(CreateDescriptors(), "Unable to initialize descriptors.");
|
Assert(CreateDescriptors(), "Unable to initialize descriptors.");
|
||||||
Assert(CreatePipelines(), "Unable to initialize pipelines.");
|
Assert(CreatePipelines(), "Unable to initialize pipelines.");
|
||||||
|
|
||||||
@ -661,6 +723,8 @@ static b32 InitVkDeviceFunctions() {
|
|||||||
INIT_DEV_FN(vkDestroyDescriptorSetLayout);
|
INIT_DEV_FN(vkDestroyDescriptorSetLayout);
|
||||||
INIT_DEV_FN(vkDestroyShaderModule);
|
INIT_DEV_FN(vkDestroyShaderModule);
|
||||||
INIT_DEV_FN(vkQueuePresentKHR);
|
INIT_DEV_FN(vkQueuePresentKHR);
|
||||||
|
INIT_DEV_FN(vkCmdDraw);
|
||||||
|
INIT_DEV_FN(vkDeviceWaitIdle);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -727,9 +791,17 @@ 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;
|
||||||
|
|
||||||
pool_create_info.queueFamilyIndex = renderer.vk.queues.graphics;
|
pool_create_info.queueFamilyIndex = renderer.vk.queues.graphics;
|
||||||
|
|
||||||
for (u32 i = 0; i < FRAME_OVERLAP; i++)
|
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.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_fences = ArenaAlloc(renderer.perm_arena, sizeof(VkFence) * img_count);
|
||||||
|
|
||||||
|
for (u32 i = 0; i < renderer.vk.sc.img_count; i++)
|
||||||
{
|
{
|
||||||
VkResult result;
|
VkResult result;
|
||||||
VkDevice device = renderer.vk.device;
|
VkDevice device = renderer.vk.device;
|
||||||
@ -795,11 +867,14 @@ static b32 CreateSwapchain()
|
|||||||
VkSurfaceCapabilitiesKHR capabilities;
|
VkSurfaceCapabilitiesKHR capabilities;
|
||||||
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(phys_device, surface, &capabilities);
|
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(phys_device, surface, &capabilities);
|
||||||
|
|
||||||
|
// Maybe reconsider handling window sizing within here and only handle it from events themselves
|
||||||
|
// causes issues when the window size is out of sync with the current swapchain
|
||||||
VkExtent2D extent;
|
VkExtent2D extent;
|
||||||
WindowSize win_size = GetWindowSize();
|
u32 width = renderer.vk.sc.extent.width;
|
||||||
|
u32 height = renderer.vk.sc.extent.height;
|
||||||
|
|
||||||
extent.width = u32Clamp((u32)win_size.w, capabilities.minImageExtent.width, capabilities.maxImageExtent.width);
|
extent.width = u32Clamp((u32)width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width);
|
||||||
extent.height = u32Clamp((u32)win_size.h, capabilities.minImageExtent.height, capabilities.maxImageExtent.height);
|
extent.height = u32Clamp((u32)height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height);
|
||||||
|
|
||||||
u32 format_count;
|
u32 format_count;
|
||||||
vkGetPhysicalDeviceSurfaceFormatsKHR(phys_device, surface, &format_count, NULL);
|
vkGetPhysicalDeviceSurfaceFormatsKHR(phys_device, surface, &format_count, NULL);
|
||||||
@ -827,11 +902,6 @@ static b32 CreateSwapchain()
|
|||||||
if (present_mode != VK_PRESENT_MODE_MAILBOX_KHR)
|
if (present_mode != VK_PRESENT_MODE_MAILBOX_KHR)
|
||||||
present_mode = VK_PRESENT_MODE_FIFO_KHR;
|
present_mode = VK_PRESENT_MODE_FIFO_KHR;
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// TODO(MA): REMOVE THIS LATER
|
|
||||||
present_mode = VK_PRESENT_MODE_FIFO_KHR;
|
|
||||||
|
|
||||||
swapchain_create_info.minImageCount = capabilities.minImageCount + 1;
|
swapchain_create_info.minImageCount = capabilities.minImageCount + 1;
|
||||||
swapchain_create_info.surface = surface;
|
swapchain_create_info.surface = surface;
|
||||||
swapchain_create_info.imageFormat = renderer.vk.sc.format;
|
swapchain_create_info.imageFormat = renderer.vk.sc.format;
|
||||||
@ -848,7 +918,7 @@ static b32 CreateSwapchain()
|
|||||||
u32 image_count;
|
u32 image_count;
|
||||||
vkGetSwapchainImagesKHR(device, renderer.vk.swapchain, &image_count, NULL);
|
vkGetSwapchainImagesKHR(device, renderer.vk.swapchain, &image_count, NULL);
|
||||||
VkImage *sc_images = ArenaAlloc(renderer.perm_arena, sizeof(VkImage) * image_count);
|
VkImage *sc_images = ArenaAlloc(renderer.perm_arena, sizeof(VkImage) * image_count);
|
||||||
VkImageView *sc_views = ArenaAlloc(renderer.perm_arena, sizeof(VkImage) * image_count);
|
VkImageView *sc_views = ArenaAlloc(renderer.perm_arena, sizeof(VkImageView) * image_count);
|
||||||
vkGetSwapchainImagesKHR(device, renderer.vk.swapchain, &image_count, sc_images);
|
vkGetSwapchainImagesKHR(device, renderer.vk.swapchain, &image_count, sc_images);
|
||||||
|
|
||||||
for (u32 i = 0; i < image_count; i++)
|
for (u32 i = 0; i < image_count; i++)
|
||||||
@ -864,13 +934,21 @@ static b32 CreateSwapchain()
|
|||||||
renderer.vk.sc.imgs = sc_images;
|
renderer.vk.sc.imgs = sc_images;
|
||||||
renderer.vk.sc.views = sc_views;
|
renderer.vk.sc.views = sc_views;
|
||||||
renderer.vk.sc.img_count = image_count;
|
renderer.vk.sc.img_count = image_count;
|
||||||
|
renderer.vk.sc.extent.width = extent.width;
|
||||||
|
renderer.vk.sc.extent.height = extent.height;
|
||||||
|
renderer.vk.sc.extent.depth = 1;
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
static b32 CreateDrawImages()
|
||||||
|
{
|
||||||
|
b32 success = true;
|
||||||
|
VkResult result;
|
||||||
|
|
||||||
VkFormat image_format = GetImageFormat();
|
VkFormat image_format = GetImageFormat();
|
||||||
VkExtent3D extent_3d = {
|
VkExtent3D extent = renderer.vk.sc.extent;
|
||||||
.width = extent.width,
|
VkDevice device = renderer.vk.device;
|
||||||
.height = extent.height,
|
|
||||||
.depth = 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
VmaAllocationCreateInfo alloc_create_info = {
|
VmaAllocationCreateInfo alloc_create_info = {
|
||||||
.usage = VMA_MEMORY_USAGE_GPU_ONLY,
|
.usage = VMA_MEMORY_USAGE_GPU_ONLY,
|
||||||
@ -879,7 +957,7 @@ static b32 CreateSwapchain()
|
|||||||
|
|
||||||
// Draw Image
|
// Draw Image
|
||||||
draw_image_create_info.format = image_format;
|
draw_image_create_info.format = image_format;
|
||||||
draw_image_create_info.extent = extent_3d;
|
draw_image_create_info.extent = extent;
|
||||||
|
|
||||||
result = vmaCreateImage(renderer.vk.alloc, &draw_image_create_info,
|
result = vmaCreateImage(renderer.vk.alloc, &draw_image_create_info,
|
||||||
&alloc_create_info, &renderer.vk.sc.draw_img.img, &renderer.vk.sc.draw_img.alloc, NULL);
|
&alloc_create_info, &renderer.vk.sc.draw_img.img, &renderer.vk.sc.draw_img.alloc, NULL);
|
||||||
@ -895,7 +973,7 @@ static b32 CreateSwapchain()
|
|||||||
success = false;
|
success = false;
|
||||||
|
|
||||||
// Depth Image
|
// Depth Image
|
||||||
depth_image_create_info.extent = extent_3d;
|
depth_image_create_info.extent = extent;
|
||||||
|
|
||||||
result = vmaCreateImage(renderer.vk.alloc, &depth_image_create_info,
|
result = vmaCreateImage(renderer.vk.alloc, &depth_image_create_info,
|
||||||
&alloc_create_info, &renderer.vk.sc.depth_img.img, &renderer.vk.sc.depth_img.alloc, NULL);
|
&alloc_create_info, &renderer.vk.sc.depth_img.img, &renderer.vk.sc.depth_img.alloc, NULL);
|
||||||
@ -909,7 +987,7 @@ static b32 CreateSwapchain()
|
|||||||
success = false;
|
success = false;
|
||||||
|
|
||||||
// Setting values
|
// Setting values
|
||||||
renderer.vk.sc.extent = extent_3d;
|
renderer.vk.sc.extent = extent;
|
||||||
renderer.vk.sc.depth_img.fmt = depth_image_create_info.format;
|
renderer.vk.sc.depth_img.fmt = depth_image_create_info.format;
|
||||||
renderer.vk.sc.draw_img.fmt = draw_image_create_info.format;
|
renderer.vk.sc.draw_img.fmt = draw_image_create_info.format;
|
||||||
|
|
||||||
@ -1058,6 +1136,29 @@ static b32 CreateShaderModule(u8 *bytes, u32 len, VkShaderModule *module)
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void DestroySwapchain()
|
||||||
|
{
|
||||||
|
for (u32 i = 0; i < renderer.vk.sc.img_count; i++)
|
||||||
|
{
|
||||||
|
vkDestroyImageView(renderer.vk.device, renderer.vk.sc.views[i], NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
vkDestroySwapchainKHR(renderer.vk.device, renderer.vk.swapchain, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DestroyDrawImages()
|
||||||
|
{
|
||||||
|
SwapchainStructures *sc = &renderer.vk.sc;
|
||||||
|
VkDevice device = renderer.vk.device;
|
||||||
|
VmaAllocator vma_alloc = renderer.vk.alloc;
|
||||||
|
|
||||||
|
vkDestroyImageView(device, sc->draw_img.view, NULL);
|
||||||
|
vmaDestroyImage(vma_alloc, sc->draw_img.img, sc->draw_img.alloc);
|
||||||
|
|
||||||
|
vkDestroyImageView(device, sc->depth_img.view, NULL);
|
||||||
|
vmaDestroyImage(vma_alloc, sc->depth_img.img, sc->depth_img.alloc);
|
||||||
|
}
|
||||||
|
|
||||||
static void DestroyVulkan()
|
static void DestroyVulkan()
|
||||||
{
|
{
|
||||||
VkDevice device = renderer.vk.device;
|
VkDevice device = renderer.vk.device;
|
||||||
@ -1069,6 +1170,8 @@ static void DestroyVulkan()
|
|||||||
VkSwapchainKHR swapchain = renderer.vk.swapchain;
|
VkSwapchainKHR swapchain = renderer.vk.swapchain;
|
||||||
PipelineStructures pipe = renderer.vk.pipe;
|
PipelineStructures pipe = renderer.vk.pipe;
|
||||||
|
|
||||||
|
vkDeviceWaitIdle(device);
|
||||||
|
|
||||||
for (u32 i = PIPELINE_CUBE; i < PIPELINE_MAX; i++)
|
for (u32 i = PIPELINE_CUBE; i < PIPELINE_MAX; i++)
|
||||||
vkDestroyPipeline(device, pipe.pipelines[i], NULL);
|
vkDestroyPipeline(device, pipe.pipelines[i], NULL);
|
||||||
|
|
||||||
@ -1079,24 +1182,15 @@ static void DestroyVulkan()
|
|||||||
|
|
||||||
vkDestroyDescriptorPool(device, pipe.pool, NULL);
|
vkDestroyDescriptorPool(device, pipe.pool, NULL);
|
||||||
|
|
||||||
vkDestroyImageView(device, sc.draw_img.view, NULL);
|
DestroyDrawImages();
|
||||||
vmaDestroyImage(vma_alloc, sc.draw_img.img, sc.draw_img.alloc);
|
|
||||||
|
|
||||||
vkDestroyImageView(device, sc.depth_img.view, NULL);
|
DestroySwapchain();
|
||||||
vmaDestroyImage(vma_alloc, sc.depth_img.img, sc.depth_img.alloc);
|
|
||||||
|
|
||||||
for (u32 i = 0; i < sc.img_count; i++)
|
|
||||||
{
|
|
||||||
vkDestroyImageView(device, sc.views[i], NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
vkDestroySwapchainKHR(device, swapchain, NULL);
|
|
||||||
|
|
||||||
vkDestroyFence(device, imm.fence, NULL);
|
vkDestroyFence(device, imm.fence, NULL);
|
||||||
vkFreeCommandBuffers(device, imm.pool, 1, &imm.buffer);
|
vkFreeCommandBuffers(device, imm.pool, 1, &imm.buffer);
|
||||||
vkDestroyCommandPool(device, imm.pool, NULL);
|
vkDestroyCommandPool(device, imm.pool, NULL);
|
||||||
|
|
||||||
for (u32 i = 0; i < FRAME_OVERLAP; i++)
|
for (u32 i = 0; i < sc.img_count; i++)
|
||||||
{
|
{
|
||||||
vkDestroySemaphore(device, data.render_sems[i], NULL);
|
vkDestroySemaphore(device, data.render_sems[i], NULL);
|
||||||
vkDestroySemaphore(device, data.swapchain_sems[i], NULL);
|
vkDestroySemaphore(device, data.swapchain_sems[i], NULL);
|
||||||
|
|||||||
@ -118,6 +118,8 @@ VK_DECLARE(vkFreeCommandBuffers);
|
|||||||
VK_DECLARE(vkDestroyDescriptorSetLayout);
|
VK_DECLARE(vkDestroyDescriptorSetLayout);
|
||||||
VK_DECLARE(vkDestroyShaderModule);
|
VK_DECLARE(vkDestroyShaderModule);
|
||||||
VK_DECLARE(vkQueuePresentKHR);
|
VK_DECLARE(vkQueuePresentKHR);
|
||||||
|
VK_DECLARE(vkCmdDraw);
|
||||||
|
VK_DECLARE(vkDeviceWaitIdle);
|
||||||
|
|
||||||
// Vulkan Functions END
|
// Vulkan Functions END
|
||||||
|
|
||||||
@ -170,11 +172,11 @@ typedef struct
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
VkCommandPool pools[FRAME_OVERLAP];
|
VkCommandPool *pools;
|
||||||
VkCommandBuffer buffers[FRAME_OVERLAP];
|
VkCommandBuffer *buffers;
|
||||||
VkSemaphore swapchain_sems[FRAME_OVERLAP];
|
VkSemaphore *swapchain_sems;
|
||||||
VkSemaphore render_sems[FRAME_OVERLAP];
|
VkSemaphore *render_sems;
|
||||||
VkFence render_fences[FRAME_OVERLAP];
|
VkFence *render_fences;
|
||||||
} FrameStructures;
|
} FrameStructures;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
@ -210,6 +212,8 @@ typedef struct {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
u32 img_ix;
|
u32 img_ix;
|
||||||
u64 frame_cnt;
|
u64 frame_cnt;
|
||||||
|
b8 comp_started;
|
||||||
|
b8 gfx_started;
|
||||||
} FrameState;
|
} FrameState;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -233,6 +237,7 @@ typedef struct {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
Vulkan_t vk;
|
Vulkan_t vk;
|
||||||
FrameState frame_state;
|
FrameState frame_state;
|
||||||
|
b32 resize_requested;
|
||||||
Arena *arena;
|
Arena *arena;
|
||||||
Arena *perm_arena;
|
Arena *perm_arena;
|
||||||
} Renderer_t;
|
} Renderer_t;
|
||||||
@ -265,18 +270,33 @@ static b32 CreateVmaAllocator();
|
|||||||
static b32 CreateFrameStructures();
|
static b32 CreateFrameStructures();
|
||||||
static b32 CreateImmediateStructures();
|
static b32 CreateImmediateStructures();
|
||||||
static b32 CreateSwapchain();
|
static b32 CreateSwapchain();
|
||||||
|
static b32 CreateDrawImages();
|
||||||
static VkFormat GetImageFormat();
|
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);
|
||||||
|
|
||||||
|
// Util
|
||||||
|
static VkCommandBuffer GetFrameCmdBuf();
|
||||||
|
static VkFence *GetFrameRenderFence();
|
||||||
|
static VkSemaphore GetFrameRenderSem();
|
||||||
|
static VkSemaphore GetFrameSwapSem();
|
||||||
|
static u32 GetFrameIndex();
|
||||||
|
|
||||||
// Destroy
|
// Destroy
|
||||||
static void DestroyVulkan();
|
static void DestroyVulkan();
|
||||||
|
static void DestroySwapchain();
|
||||||
|
static void DestroyDrawImages();
|
||||||
|
|
||||||
// Util
|
// Util
|
||||||
static void TransitionImage(VkCommandBuffer cmd, VkImage img, VkImageLayout curr, VkImageLayout new);
|
static void TransitionImage(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
|
||||||
|
static VkExtent2D SelectSwapchainExtent(VkSurfaceCapabilitiesKHR *capabilities);
|
||||||
|
static VkSurfaceFormatKHR SelectSwapchainFormat(VkSurfaceFormatKHR *formats);
|
||||||
|
static void ResizeSwapchain();
|
||||||
|
|
||||||
// Renderer Functions Declarations END
|
// Renderer Functions Declarations END
|
||||||
|
|
||||||
#include "vulkan_config.c"
|
#include "vulkan_config.c"
|
||||||
@ -322,3 +342,4 @@ void _DestroyRenderer();
|
|||||||
static b32 _BeginFrame();
|
static b32 _BeginFrame();
|
||||||
static void _DrawTriangle();
|
static void _DrawTriangle();
|
||||||
static b32 _FinishFrame();
|
static b32 _FinishFrame();
|
||||||
|
static void _SetRenderSize(u32 x, u32 y);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user