Try to improve resource layout transition
This commit is contained in:
		
							parent
							
								
									2a2a743c78
								
							
						
					
					
						commit
						6f89dd4c46
					
				
							
								
								
									
										27
									
								
								assets/forward.framegraph
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								assets/forward.framegraph
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,27 @@
 | 
			
		||||
render_targets {
 | 
			
		||||
    swapchain_out {
 | 
			
		||||
        format SWAPCHAIN;
 | 
			
		||||
        width SWAPCHAIN;
 | 
			
		||||
        height SWAPCHAIN;
 | 
			
		||||
        sample_count 1;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
passes {
 | 
			
		||||
    forward {
 | 
			
		||||
        type GRAPHICS;
 | 
			
		||||
        writes {
 | 
			
		||||
            swapchain_out {
 | 
			
		||||
                clear_value {
 | 
			
		||||
                    r 1.0;
 | 
			
		||||
                    g 1.0;
 | 
			
		||||
                    b 1.0;
 | 
			
		||||
                    a 1.0;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                clear YES;
 | 
			
		||||
                discard NO;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -18,7 +18,7 @@ static void PassPrepare(rt_render_pass_id pass,
 | 
			
		||||
                        uint32_t write_count,
 | 
			
		||||
                        const rt_render_target_read *reads,
 | 
			
		||||
                        uint32_t read_count) {
 | 
			
		||||
    //rtLog("GAME", "Prepare pass %x", pass);
 | 
			
		||||
    // rtLog("GAME", "Prepare pass %x", pass);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void PassExecute(rt_render_pass_id pass,
 | 
			
		||||
@ -26,7 +26,7 @@ static void PassExecute(rt_render_pass_id pass,
 | 
			
		||||
                        uint32_t write_count,
 | 
			
		||||
                        const rt_render_target_read *reads,
 | 
			
		||||
                        uint32_t read_count) {
 | 
			
		||||
    //rtLog("GAME", "Execute pass %x", pass);
 | 
			
		||||
    // rtLog("GAME", "Execute pass %x", pass);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void PassFinalize(rt_render_pass_id pass,
 | 
			
		||||
@ -34,7 +34,7 @@ static void PassFinalize(rt_render_pass_id pass,
 | 
			
		||||
                         uint32_t write_count,
 | 
			
		||||
                         const rt_render_target_read *reads,
 | 
			
		||||
                         uint32_t read_count) {
 | 
			
		||||
    //rtLog("GAME", "Finalize pass %x", pass);
 | 
			
		||||
    // rtLog("GAME", "Finalize pass %x", pass);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Called after the runtime has finished its initialization and before entering the main-loop*/
 | 
			
		||||
@ -46,6 +46,19 @@ void Init(void) {
 | 
			
		||||
 | 
			
		||||
    rt_temp_arena temp = rtGetTemporaryArena(NULL, 0);
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
    rt_resource_id resid = rtGetResourceID("assets/forward.framegraph");
 | 
			
		||||
    size_t size          = rtGetResourceSize(resid);
 | 
			
		||||
    rt_resource *res     = rtArenaPush(temp.arena, size);
 | 
			
		||||
    rtGetResource(resid, res);
 | 
			
		||||
 | 
			
		||||
    _framegraph = rtCreateFramegraph(res->data);
 | 
			
		||||
 | 
			
		||||
    rt_render_pass_bind_fns bind = {.Execute  = PassExecute,
 | 
			
		||||
                                    .Prepare  = PassPrepare,
 | 
			
		||||
                                    .Finalize = PassFinalize};
 | 
			
		||||
    rtBindRenderPass(_framegraph, rtCalculateRenderPassID("forward", sizeof("forward") - 1), &bind);
 | 
			
		||||
#else
 | 
			
		||||
    rt_resource_id resid = rtGetResourceID("assets/test.framegraph");
 | 
			
		||||
    size_t size          = rtGetResourceSize(resid);
 | 
			
		||||
    rt_resource *res     = rtArenaPush(temp.arena, size);
 | 
			
		||||
@ -58,6 +71,7 @@ void Init(void) {
 | 
			
		||||
                                    .Finalize = PassFinalize};
 | 
			
		||||
    rtBindRenderPass(_framegraph, rtCalculateRenderPassID("pass0", sizeof("pass0") - 1), &bind);
 | 
			
		||||
    rtBindRenderPass(_framegraph, rtCalculateRenderPassID("pass1", sizeof("pass1") - 1), &bind);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Called after exiting the main-loop and before the runtime starts its shutdown */
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										10
									
								
								src/gfx/builtin_objects.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/gfx/builtin_objects.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
			
		||||
#define RT_DONT_DEFINE_BULTIN_OBJECTS_GLOBAL
 | 
			
		||||
#include "builtin_objects.h"
 | 
			
		||||
 | 
			
		||||
rt_builtin_render_object_types g_builtin_render_object_types;
 | 
			
		||||
 | 
			
		||||
RT_DLLEXPORT rt_result rtRegisterBuiltinRenderObjectTypes(void) {
 | 
			
		||||
    g_builtin_render_object_types.render_mesh =
 | 
			
		||||
        rtRegisterRenderObjectType(sizeof(rt_render_mesh), "render_mesh");
 | 
			
		||||
    return RT_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										39
									
								
								src/gfx/builtin_objects.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								src/gfx/builtin_objects.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,39 @@
 | 
			
		||||
#ifndef RT_GFX_BUILTIN_OBJECTS_H
 | 
			
		||||
#define RT_GFX_BUILTIN_OBJECTS_H
 | 
			
		||||
 | 
			
		||||
/* Render Object types used by the builtin graphics passes.
 | 
			
		||||
 *
 | 
			
		||||
 * As an user you are free to not use these, but then you
 | 
			
		||||
 * also cannot use the builtin render passes. */
 | 
			
		||||
 | 
			
		||||
#include "renderer_api.h"
 | 
			
		||||
#include "render_list.h"
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    rt_buffer_handle vbo;
 | 
			
		||||
    rt_buffer_handle ibo;
 | 
			
		||||
    uint32_t vertex_count;
 | 
			
		||||
    uint32_t index_count;
 | 
			
		||||
} rt_render_mesh;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    rt_render_object_type render_mesh;
 | 
			
		||||
} rt_builtin_render_object_types;
 | 
			
		||||
 | 
			
		||||
#ifndef RT_DONT_DEFINE_BULTIN_OBJECTS_GLOBAL
 | 
			
		||||
extern RT_DLLIMPORT rt_builtin_render_object_types g_builtin_render_object_types;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
RT_DLLEXPORT rt_result rtRegisterBuiltinRenderObjectTypes(void);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@ -647,14 +647,14 @@ RT_DLLEXPORT void rtExecuteFramegraph(rt_framegraph *framegraph, unsigned int fr
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Find the last pass that writes to the swapchain */
 | 
			
		||||
    uint32_t last_swapchain_write = 0;
 | 
			
		||||
    uint32_t last_swapchain_write = framegraph->pass_count - 1;
 | 
			
		||||
    for (uint32_t i = framegraph->pass_count - 1; i > 0; --i) {
 | 
			
		||||
        if (framegraph->passes[i].writes_swapchain) {
 | 
			
		||||
            last_swapchain_write = i;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    /* Find the first pass that reads the swapchain 0*/
 | 
			
		||||
    /* Find the first pass that reads the swapchain */
 | 
			
		||||
    uint32_t first_swapchain_read = 0;
 | 
			
		||||
    for (uint32_t i = 0; framegraph->pass_count; ++i) {
 | 
			
		||||
        if (framegraph->passes[i].reads_swapchain || framegraph->passes[i].writes_swapchain) {
 | 
			
		||||
@ -705,19 +705,25 @@ RT_DLLEXPORT void rtExecuteFramegraph(rt_framegraph *framegraph, unsigned int fr
 | 
			
		||||
                bool is_graphics_pass =
 | 
			
		||||
                    framegraph->passes[pass_idx].type == RT_RENDER_PASS_TYPE_GRAPHICS;
 | 
			
		||||
                if (is_graphics_pass) {
 | 
			
		||||
                    graphics_wait_semaphore_count += framegraph->passes[pass_idx].read_count;
 | 
			
		||||
                    graphics_wait_semaphore_count += framegraph->passes[pass_idx].read_count +
 | 
			
		||||
                                                     framegraph->passes[pass_idx].write_count;
 | 
			
		||||
                    graphics_signal_semaphore_count += framegraph->passes[pass_idx].write_count;
 | 
			
		||||
                    if (framegraph->passes[pass_idx].reads_swapchain)
 | 
			
		||||
                    if (framegraph->passes[pass_idx].reads_swapchain ||
 | 
			
		||||
                        pass_idx == first_swapchain_read)
 | 
			
		||||
                        graphics_wait_semaphore_count += 1;
 | 
			
		||||
                    if (framegraph->passes[pass_idx].writes_swapchain)
 | 
			
		||||
                    if (framegraph->passes[pass_idx].writes_swapchain ||
 | 
			
		||||
                        pass_idx == last_swapchain_write)
 | 
			
		||||
                        graphics_signal_semaphore_count += 1;
 | 
			
		||||
                    ++graphics_command_buffer_count;
 | 
			
		||||
                } else {
 | 
			
		||||
                    compute_wait_semaphore_count += framegraph->passes[pass_idx].read_count;
 | 
			
		||||
                    compute_wait_semaphore_count += framegraph->passes[pass_idx].read_count +
 | 
			
		||||
                                                    framegraph->passes[pass_idx].write_count;
 | 
			
		||||
                    compute_signal_semaphore_count += framegraph->passes[pass_idx].write_count;
 | 
			
		||||
                    if (framegraph->passes[pass_idx].reads_swapchain)
 | 
			
		||||
                    if (framegraph->passes[pass_idx].reads_swapchain ||
 | 
			
		||||
                        pass_idx == first_swapchain_read)
 | 
			
		||||
                        compute_wait_semaphore_count += 1;
 | 
			
		||||
                    if (framegraph->passes[pass_idx].writes_swapchain)
 | 
			
		||||
                    if (framegraph->passes[pass_idx].writes_swapchain ||
 | 
			
		||||
                        pass_idx == last_swapchain_write)
 | 
			
		||||
                        compute_signal_semaphore_count += 1;
 | 
			
		||||
                    ++compute_command_buffer_count;
 | 
			
		||||
                }
 | 
			
		||||
@ -850,6 +856,12 @@ RT_DLLEXPORT void rtExecuteFramegraph(rt_framegraph *framegraph, unsigned int fr
 | 
			
		||||
                    signal_semaphores[*signal_count] = rt->semaphore;
 | 
			
		||||
                    signal_values[*signal_count]     = signal_value_base + execution_level + 1;
 | 
			
		||||
                    *signal_count += 1;
 | 
			
		||||
 | 
			
		||||
                    if (signal_value_base >= 200) {
 | 
			
		||||
                        wait_semaphores[*wait_count] = rt->semaphore;
 | 
			
		||||
                        wait_values[*wait_count] = signal_value_base - 200 + execution_level + 1;
 | 
			
		||||
                        *wait_count += 1;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                if (pass_idx == first_swapchain_read) {
 | 
			
		||||
                    wait_semaphores[*wait_count] = swapchain_available;
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,13 @@
 | 
			
		||||
gfx_deps = [thread_dep, m_dep]
 | 
			
		||||
gfx_lib = library('rtgfx',
 | 
			
		||||
  # Project Sources
 | 
			
		||||
  'builtin_objects.h',
 | 
			
		||||
  'effect.h',
 | 
			
		||||
  'gfx.h',
 | 
			
		||||
  'renderer_api.h',
 | 
			
		||||
  'render_list.h',
 | 
			
		||||
  
 | 
			
		||||
  'builtin_objects.c',
 | 
			
		||||
  'gfx_framegraph.c',
 | 
			
		||||
  'gfx_main.c',
 | 
			
		||||
  'render_list.c',
 | 
			
		||||
 | 
			
		||||
@ -30,6 +30,7 @@ RT_RENDER_BACKEND_HANDLE(rt_pipeline_handle);
 | 
			
		||||
RT_RENDER_BACKEND_HANDLE(rt_render_target_handle);
 | 
			
		||||
RT_RENDER_BACKEND_HANDLE(rt_command_buffer_handle);
 | 
			
		||||
RT_RENDER_BACKEND_HANDLE(rt_gpu_semaphore_handle);
 | 
			
		||||
RT_RENDER_BACKEND_HANDLE(rt_buffer_handle);
 | 
			
		||||
 | 
			
		||||
#undef RT_RENDER_BACKEND_HANDLE
 | 
			
		||||
 | 
			
		||||
@ -126,6 +127,34 @@ typedef struct {
 | 
			
		||||
    uint64_t initial_value;
 | 
			
		||||
} rt_gpu_semaphore_info;
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
    RT_BUFFER_TYPE_VERTEX,
 | 
			
		||||
    RT_BUFFER_TYPE_INDEX,
 | 
			
		||||
    RT_BUFFER_TYPE_UNIFORM,
 | 
			
		||||
    RT_BUFFER_TYPE_STORAGE,
 | 
			
		||||
    RT_BUFFER_TYPE_count
 | 
			
		||||
} rt_buffer_type;
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
    /* Create once, never change the data. */
 | 
			
		||||
    RT_BUFFER_USAGE_STATIC,
 | 
			
		||||
 | 
			
		||||
    /* Update occasionally (after a number of frames) */
 | 
			
		||||
    RT_BUFFER_USAGE_DYNAMIC,
 | 
			
		||||
 | 
			
		||||
    /* Create, use once and then discard */
 | 
			
		||||
    RT_BUFFER_USAGE_TRANSIENT,
 | 
			
		||||
 | 
			
		||||
    RT_BUFFER_USAGE_count,
 | 
			
		||||
} rt_buffer_usage;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    size_t size;
 | 
			
		||||
    rt_buffer_type type;
 | 
			
		||||
    rt_buffer_usage usage;
 | 
			
		||||
    const void *data;
 | 
			
		||||
} rt_buffer_info;
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
    RT_PASS_LOAD_MODE_LOAD,
 | 
			
		||||
    RT_PASS_LOAD_MODE_CLEAR,
 | 
			
		||||
@ -200,6 +229,9 @@ typedef void rt_destroy_gpu_semaphores_fn(uint32_t count, rt_gpu_semaphore_handl
 | 
			
		||||
typedef uint64_t rt_get_gpu_semaphore_value_fn(rt_gpu_semaphore_handle semaphore);
 | 
			
		||||
typedef rt_gpu_semaphore_handle rt_get_swapchain_available_semaphore_fn(void);
 | 
			
		||||
typedef rt_gpu_semaphore_handle rt_get_render_finished_semaphore_fn(void);
 | 
			
		||||
typedef rt_result
 | 
			
		||||
rt_create_buffers_fn(uint32_t count, const rt_buffer_info *info, rt_buffer_handle *p_buffers);
 | 
			
		||||
typedef void rt_destroy_buffers_fn(uint32_t count, rt_buffer_handle *buffers);
 | 
			
		||||
 | 
			
		||||
typedef void rt_cmd_begin_pass_fn(rt_command_buffer_handle cmdbuf,
 | 
			
		||||
                                  const rt_cmd_begin_pass_info *info);
 | 
			
		||||
@ -226,6 +258,8 @@ typedef struct {
 | 
			
		||||
    rt_get_gpu_semaphore_value_fn *GetSemaphoreValue;
 | 
			
		||||
    rt_get_swapchain_available_semaphore_fn *GetSwapchainAvailableSemaphore;
 | 
			
		||||
    rt_get_render_finished_semaphore_fn *GetRenderFinishedSemaphore;
 | 
			
		||||
    rt_create_buffers_fn *CreateBuffers;
 | 
			
		||||
    rt_destroy_buffers_fn *DestroyBuffers;
 | 
			
		||||
 | 
			
		||||
    /* Command Buffer Functions */
 | 
			
		||||
    rt_cmd_begin_pass_fn *CmdBeginPass;
 | 
			
		||||
 | 
			
		||||
@ -103,6 +103,19 @@ rt_gpu_semaphore_handle RT_RENDERER_API_FN(GetRenderFinishedSemaphore)(void) {
 | 
			
		||||
    return (rt_gpu_semaphore_handle){.index = 2, .version = 1};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
rt_result RT_RENDERER_API_FN(CreateBuffers)(uint32_t count,
 | 
			
		||||
                                            const rt_buffer_info *info,
 | 
			
		||||
                                            rt_buffer_handle *p_buffers) {
 | 
			
		||||
    RT_UNUSED(info);
 | 
			
		||||
    RETURN_HANDLE_ARRAY_STUB(p_buffers, count);
 | 
			
		||||
    return RT_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RT_RENDERER_API_FN(DestroyBuffers)(uint32_t count, rt_buffer_handle *buffers) {
 | 
			
		||||
    RT_UNUSED(count);
 | 
			
		||||
    RT_UNUSED(buffers);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RT_RENDERER_API_FN(CmdBeginPass)(rt_command_buffer_handle cmd,
 | 
			
		||||
                                      const rt_cmd_begin_pass_info *info) {
 | 
			
		||||
    RT_UNUSED(cmd);
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										69
									
								
								src/renderer/vk/buffers.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								src/renderer/vk/buffers.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,69 @@
 | 
			
		||||
#include "gpu.h"
 | 
			
		||||
#include "gfx/renderer_api.h"
 | 
			
		||||
#include "runtime/config.h"
 | 
			
		||||
#include "runtime/threading.h"
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
RT_CVAR_I(rt_VkMaxBufferCount, "Number of slots for gpu buffers. Default: 1024.", 1024);
 | 
			
		||||
 | 
			
		||||
typedef struct rt_buffer_data_s {
 | 
			
		||||
    VkBuffer buffer;
 | 
			
		||||
    VmaAllocation allocation;
 | 
			
		||||
    size_t size;
 | 
			
		||||
    rt_buffer_usage usage;
 | 
			
		||||
    rt_buffer_type type;
 | 
			
		||||
 | 
			
		||||
    rt_rwlock lock;
 | 
			
		||||
 | 
			
		||||
    struct rt_buffer_data_s *next_free;
 | 
			
		||||
} rt_buffer_data;
 | 
			
		||||
 | 
			
		||||
static rt_buffer_data *_buffers;
 | 
			
		||||
static rt_buffer_data *_first_free;
 | 
			
		||||
static rt_mutex *_list_lock;
 | 
			
		||||
 | 
			
		||||
rt_result InitBufferManagement(void) {
 | 
			
		||||
    size_t n = (size_t)rt_VkMaxBufferCount.i;
 | 
			
		||||
    _buffers = malloc(sizeof(rt_buffer_data) * n);
 | 
			
		||||
    if (!_buffers)
 | 
			
		||||
        return RT_OUT_OF_MEMORY;
 | 
			
		||||
    return RT_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ShutdownBufferManagement(void) {
 | 
			
		||||
    for (int i = 0; i < rt_VkMaxBufferCount.i; ++i) {
 | 
			
		||||
        if (_buffers[i].buffer == VK_NULL_HANDLE)
 | 
			
		||||
            continue;
 | 
			
		||||
        vmaDestroyBuffer(g_gpu.allocator, _buffers[i].buffer, _buffers[i].allocation);
 | 
			
		||||
        rtDestroyRWLock(&_buffers[i].lock);
 | 
			
		||||
        memset(&_buffers[i], 0, sizeof(_buffers[i]));
 | 
			
		||||
    }
 | 
			
		||||
    free(_buffers);
 | 
			
		||||
    _first_free = NULL;
 | 
			
		||||
    rtDestroyMutex(_list_lock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RT_RENDERER_API_FN(DestroyBuffers)(uint32_t count, rt_buffer_handle *buffers);
 | 
			
		||||
 | 
			
		||||
rt_result RT_RENDERER_API_FN(CreateBuffers)(uint32_t count,
 | 
			
		||||
                                            const rt_buffer_info *info,
 | 
			
		||||
                                            rt_buffer_handle *p_buffers) {
 | 
			
		||||
    for (uint32_t i = 0; i < count; ++i) {
 | 
			
		||||
        rtLockMutex(_list_lock);
 | 
			
		||||
        rt_buffer_data *slot = _first_free;
 | 
			
		||||
        if (!slot) {
 | 
			
		||||
            rtUnlockMutex(_list_lock);
 | 
			
		||||
            if (i > 0)
 | 
			
		||||
                rtRenDestroyBuffers(i, p_buffers);
 | 
			
		||||
            return RT_OUT_OF_MEMORY;
 | 
			
		||||
        }
 | 
			
		||||
        rtUnlockMutex(_list_lock);
 | 
			
		||||
    }
 | 
			
		||||
    return RT_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RT_RENDERER_API_FN(DestroyBuffers)(uint32_t count, rt_buffer_handle *buffers) {
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -233,6 +233,8 @@ rt_result RT_RENDERER_API_FN(AllocCommandBuffers)(uint32_t count,
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define RT_VK_LOG_SUBMIT_INFO 1
 | 
			
		||||
 | 
			
		||||
rt_result RT_RENDERER_API_FN(SubmitCommandBuffers)(rt_gpu_queue queue,
 | 
			
		||||
                                                   const rt_submit_command_buffers_info *info) {
 | 
			
		||||
 | 
			
		||||
@ -313,6 +315,35 @@ rt_result RT_RENDERER_API_FN(SubmitCommandBuffers)(rt_gpu_queue queue,
 | 
			
		||||
        vkEndCommandBuffer(command_buffers[i].commandBuffer);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#if RT_VK_LOG_SUBMIT_INFO
 | 
			
		||||
    {
 | 
			
		||||
        const char *queue_str = "<invalid>";
 | 
			
		||||
        if (queue == RT_GRAPHICS_QUEUE)
 | 
			
		||||
            queue_str = "GRAPHICS";
 | 
			
		||||
        else if (queue == RT_COMPUTE_QUEUE)
 | 
			
		||||
            queue_str = "COMPUTE";
 | 
			
		||||
        else if (queue == RT_TRANSFER_QUEUE)
 | 
			
		||||
            queue_str = "TRANSFER";
 | 
			
		||||
        rtLog("vk", "Submit Info");
 | 
			
		||||
        rtLog("vk", "Queue: %s", queue_str);
 | 
			
		||||
        rtLog("vk", "Command Buffers: %u", count);
 | 
			
		||||
        rtLog("vk", "  - TODO: More Info");
 | 
			
		||||
        rtLog("vk", "Wait Semaphores:");
 | 
			
		||||
        for (uint32_t i = 0; i < wait_count; ++i) {
 | 
			
		||||
            rtLog("vk", " - %u:%u Value %u", info->wait_semaphores[i].version,
 | 
			
		||||
                info->wait_semaphores[i].index, info->wait_values[i]);
 | 
			
		||||
        }
 | 
			
		||||
        rtLog("vk", "Signal Semaphores:");
 | 
			
		||||
        for (uint32_t i = 0; i < signal_count; ++i) {
 | 
			
		||||
            rtLog("vk",
 | 
			
		||||
                  " - %u:%u Value %u",
 | 
			
		||||
                  info->signal_semaphores[i].version,
 | 
			
		||||
                  info->signal_semaphores[i].index,
 | 
			
		||||
                  info->signal_values[i]);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    VkSubmitInfo2 submit_info = {
 | 
			
		||||
        .sType                    = VK_STRUCTURE_TYPE_SUBMIT_INFO_2,
 | 
			
		||||
        .waitSemaphoreInfoCount   = wait_count,
 | 
			
		||||
 | 
			
		||||
@ -161,37 +161,120 @@ void RT_RENDERER_API_FN(CmdEndPass)(rt_command_buffer_handle cmdbuf_handle) {
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RT_RENDERER_API_FN(CmdTransitionRenderTarget)(rt_command_buffer_handle cmdbuf_handle,
 | 
			
		||||
                                                   rt_render_target_handle render_target,
 | 
			
		||||
                                                   rt_render_target_state new_state) {
 | 
			
		||||
    GET_CMDBUF(cmdbuf, cmdbuf_handle)
 | 
			
		||||
    uint32_t image_index = g_gpu.current_frame_id % g_gpu.max_frames_in_flight;
 | 
			
		||||
    if (render_target.index == g_renderer.GetSwapchainRenderTarget().index) {
 | 
			
		||||
        image_index = rtGetFrameData(g_gpu.current_frame_id)->swapchain_image_index;
 | 
			
		||||
/* Non-layout transition barrier */
 | 
			
		||||
static void ExecuteRenderTargetBarrier(rt_render_target *rt,
 | 
			
		||||
                                       uint32_t image_index,
 | 
			
		||||
                                       VkCommandBuffer cmdbuf) { /* Determine old and new layout */
 | 
			
		||||
    VkImageLayout layout;
 | 
			
		||||
    switch (rt->states[image_index]) {
 | 
			
		||||
    case RT_RENDER_TARGET_STATE_ATTACHMENT:
 | 
			
		||||
        layout = VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL;
 | 
			
		||||
        break;
 | 
			
		||||
    case RT_RENDER_TARGET_STATE_STORAGE_IMAGE:
 | 
			
		||||
    case RT_RENDER_TARGET_STATE_SAMPLED_IMAGE:
 | 
			
		||||
        layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        layout = VK_IMAGE_LAYOUT_UNDEFINED;
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    rt_render_target *rt = rtGetRenderTarget(render_target);
 | 
			
		||||
    if (!rt) {
 | 
			
		||||
        rtLog("vk", "Tried to transition invalid render target");
 | 
			
		||||
        return;
 | 
			
		||||
#ifdef RT_DEBUG
 | 
			
		||||
    VkDebugUtilsLabelEXT debug_label = {
 | 
			
		||||
        .sType      = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT,
 | 
			
		||||
        .pLabelName = "Render Target Barrier",
 | 
			
		||||
        .color      = {.13f, .54f, .13f, .75f},
 | 
			
		||||
    };
 | 
			
		||||
    vkCmdBeginDebugUtilsLabelEXT(cmdbuf, &debug_label);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    VkImageAspectFlags aspect_mask =
 | 
			
		||||
        (rt->format == VK_FORMAT_D24_UNORM_S8_UINT || rt->format == VK_FORMAT_D32_SFLOAT)
 | 
			
		||||
            ? VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT
 | 
			
		||||
            : VK_IMAGE_ASPECT_COLOR_BIT;
 | 
			
		||||
 | 
			
		||||
    /* Determine access flags */
 | 
			
		||||
    VkPipelineStageFlags2 src_stage = 0;
 | 
			
		||||
    VkPipelineStageFlags2 dst_stage = 0;
 | 
			
		||||
    VkAccessFlags2 src_access = 0;
 | 
			
		||||
    VkAccessFlags2 dst_access = 0;
 | 
			
		||||
    if (rt->states[image_index] == RT_RENDER_TARGET_STATE_ATTACHMENT) {
 | 
			
		||||
        src_access =
 | 
			
		||||
            (rt->format == VK_FORMAT_D24_UNORM_S8_UINT || rt->format == VK_FORMAT_D32_SFLOAT)
 | 
			
		||||
                ? VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT
 | 
			
		||||
                : VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT;
 | 
			
		||||
        dst_access =
 | 
			
		||||
            (rt->format == VK_FORMAT_D24_UNORM_S8_UINT || rt->format == VK_FORMAT_D32_SFLOAT)
 | 
			
		||||
                ? VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
 | 
			
		||||
                      VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT
 | 
			
		||||
                : VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT |
 | 
			
		||||
                      VK_ACCESS_2_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT;
 | 
			
		||||
        src_stage =
 | 
			
		||||
            (rt->format == VK_FORMAT_D24_UNORM_S8_UINT || rt->format == VK_FORMAT_D32_SFLOAT)
 | 
			
		||||
                ? VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT_KHR |
 | 
			
		||||
                      VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT_KHR
 | 
			
		||||
                : VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT;
 | 
			
		||||
        dst_stage =
 | 
			
		||||
            (rt->format == VK_FORMAT_D24_UNORM_S8_UINT || rt->format == VK_FORMAT_D32_SFLOAT)
 | 
			
		||||
                ? VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT_KHR |
 | 
			
		||||
                      VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT_KHR
 | 
			
		||||
                : VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT;
 | 
			
		||||
    } else { /* SAMPLED_IMAGE or STORAGE_IMAGE */
 | 
			
		||||
        src_access =
 | 
			
		||||
            (rt->format == VK_FORMAT_D24_UNORM_S8_UINT || rt->format == VK_FORMAT_D32_SFLOAT)
 | 
			
		||||
                ? VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_2_SHADER_WRITE_BIT
 | 
			
		||||
                : VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_2_SHADER_WRITE_BIT;
 | 
			
		||||
        dst_access = VK_ACCESS_2_SHADER_READ_BIT;
 | 
			
		||||
        src_stage  = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT;
 | 
			
		||||
        dst_stage  = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (rt->states[image_index] == new_state)
 | 
			
		||||
        return;
 | 
			
		||||
    VkImageMemoryBarrier2 image_barrier = {
 | 
			
		||||
        .sType         = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
 | 
			
		||||
        .srcStageMask  = src_stage,
 | 
			
		||||
        .srcAccessMask = src_access,
 | 
			
		||||
        .dstStageMask  = dst_stage,
 | 
			
		||||
        .dstAccessMask = dst_access,
 | 
			
		||||
        .oldLayout     = layout,
 | 
			
		||||
        .newLayout     = layout,
 | 
			
		||||
        .image         = rt->image[image_index],
 | 
			
		||||
 /* clang-format off */
 | 
			
		||||
                .subresourceRange = {
 | 
			
		||||
                    .aspectMask = aspect_mask,
 | 
			
		||||
                    .baseArrayLayer = 0,
 | 
			
		||||
                    .baseMipLevel = 0,
 | 
			
		||||
                    .layerCount = 1,
 | 
			
		||||
                    .levelCount = 1,
 | 
			
		||||
                },
 | 
			
		||||
  /* clang-format on */
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    VkDependencyInfo dep_info = {
 | 
			
		||||
        .sType                   = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
 | 
			
		||||
        .pImageMemoryBarriers    = &image_barrier,
 | 
			
		||||
        .imageMemoryBarrierCount = 1,
 | 
			
		||||
    };
 | 
			
		||||
    vkCmdPipelineBarrier2(cmdbuf, &dep_info);
 | 
			
		||||
 | 
			
		||||
#ifdef RT_DEBUG
 | 
			
		||||
    vkCmdEndDebugUtilsLabelEXT(cmdbuf);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void DoLayoutTransition(rt_render_target *rt,
 | 
			
		||||
                               uint32_t image_index,
 | 
			
		||||
                               rt_render_target_state new_state,
 | 
			
		||||
                               VkCommandBuffer cmdbuf) {
 | 
			
		||||
 | 
			
		||||
    /* Determine old and new layout */
 | 
			
		||||
    VkImageLayout old_layout;
 | 
			
		||||
    switch (rt->states[image_index]) {
 | 
			
		||||
    case RT_RENDER_TARGET_STATE_ATTACHMENT:
 | 
			
		||||
        if (rt->format == VK_FORMAT_D24_UNORM_S8_UINT || rt->format == VK_FORMAT_D32_SFLOAT) {
 | 
			
		||||
            old_layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
 | 
			
		||||
        } else {
 | 
			
		||||
            old_layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
 | 
			
		||||
        }
 | 
			
		||||
        old_layout = VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL;
 | 
			
		||||
        break;
 | 
			
		||||
    case RT_RENDER_TARGET_STATE_STORAGE_IMAGE:
 | 
			
		||||
    case RT_RENDER_TARGET_STATE_SAMPLED_IMAGE:
 | 
			
		||||
        old_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
 | 
			
		||||
        old_layout = VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL;
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        old_layout = VK_IMAGE_LAYOUT_UNDEFINED;
 | 
			
		||||
@ -200,15 +283,11 @@ void RT_RENDERER_API_FN(CmdTransitionRenderTarget)(rt_command_buffer_handle cmdb
 | 
			
		||||
    VkImageLayout new_layout;
 | 
			
		||||
    switch (new_state) {
 | 
			
		||||
    case RT_RENDER_TARGET_STATE_ATTACHMENT:
 | 
			
		||||
        if (rt->format == VK_FORMAT_D24_UNORM_S8_UINT || rt->format == VK_FORMAT_D32_SFLOAT) {
 | 
			
		||||
            new_layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
 | 
			
		||||
        } else {
 | 
			
		||||
            new_layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
 | 
			
		||||
        }
 | 
			
		||||
        new_layout = VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL;
 | 
			
		||||
        break;
 | 
			
		||||
    case RT_RENDER_TARGET_STATE_STORAGE_IMAGE:
 | 
			
		||||
    case RT_RENDER_TARGET_STATE_SAMPLED_IMAGE:
 | 
			
		||||
        new_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
 | 
			
		||||
        new_layout = VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL;
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        new_layout = VK_IMAGE_LAYOUT_UNDEFINED;
 | 
			
		||||
@ -227,23 +306,59 @@ void RT_RENDERER_API_FN(CmdTransitionRenderTarget)(rt_command_buffer_handle cmdb
 | 
			
		||||
        (rt->format == VK_FORMAT_D24_UNORM_S8_UINT || rt->format == VK_FORMAT_D32_SFLOAT)
 | 
			
		||||
            ? VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT
 | 
			
		||||
            : VK_IMAGE_ASPECT_COLOR_BIT;
 | 
			
		||||
    
 | 
			
		||||
    VkPipelineStageFlags2 src_stage = 0;
 | 
			
		||||
    VkPipelineStageFlags2 dst_stage = 0;
 | 
			
		||||
    /* Determine access flags */
 | 
			
		||||
    VkAccessFlags2 src_access = 0;
 | 
			
		||||
    VkAccessFlags2 dst_access = 0;
 | 
			
		||||
    if (rt->states[image_index] == RT_RENDER_TARGET_STATE_ATTACHMENT) {
 | 
			
		||||
        src_access =
 | 
			
		||||
            (rt->format == VK_FORMAT_D24_UNORM_S8_UINT || rt->format == VK_FORMAT_D32_SFLOAT)
 | 
			
		||||
                ? VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT
 | 
			
		||||
                : VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT;
 | 
			
		||||
        src_stage =
 | 
			
		||||
            (rt->format == VK_FORMAT_D24_UNORM_S8_UINT || rt->format == VK_FORMAT_D32_SFLOAT)
 | 
			
		||||
                ? VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT_KHR |
 | 
			
		||||
                      VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT_KHR
 | 
			
		||||
                : VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT;
 | 
			
		||||
    } else { /* SAMPLED_IMAGE or STORAGE_IMAGE */
 | 
			
		||||
        src_access = VK_ACCESS_2_SHADER_WRITE_BIT;
 | 
			
		||||
        src_stage  = VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (new_state == RT_RENDER_TARGET_STATE_ATTACHMENT) {
 | 
			
		||||
        dst_access =
 | 
			
		||||
            (rt->format == VK_FORMAT_D24_UNORM_S8_UINT || rt->format == VK_FORMAT_D32_SFLOAT)
 | 
			
		||||
            ? VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT
 | 
			
		||||
                : VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT;
 | 
			
		||||
        dst_stage =
 | 
			
		||||
            (rt->format == VK_FORMAT_D24_UNORM_S8_UINT || rt->format == VK_FORMAT_D32_SFLOAT)
 | 
			
		||||
                ? VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT_KHR |
 | 
			
		||||
                      VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT_KHR
 | 
			
		||||
                : VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT;
 | 
			
		||||
    } else { /* SAMPLED_IMAGE or STORAGE_IMAGE */
 | 
			
		||||
        dst_access = VK_ACCESS_2_SHADER_READ_BIT;
 | 
			
		||||
        dst_stage  = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    VkImageMemoryBarrier2 image_barrier = {
 | 
			
		||||
        .sType         = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
 | 
			
		||||
        .srcStageMask  = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
 | 
			
		||||
        .srcAccessMask = VK_ACCESS_2_MEMORY_WRITE_BIT,
 | 
			
		||||
        .dstStageMask  = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
 | 
			
		||||
        .dstAccessMask = VK_ACCESS_2_MEMORY_WRITE_BIT | VK_ACCESS_2_MEMORY_READ_BIT,
 | 
			
		||||
        .srcStageMask  = src_stage,
 | 
			
		||||
        .srcAccessMask = src_access,
 | 
			
		||||
        .dstStageMask  = dst_stage,
 | 
			
		||||
        .dstAccessMask = dst_access,
 | 
			
		||||
        .oldLayout     = old_layout,
 | 
			
		||||
        .newLayout     = new_layout,
 | 
			
		||||
        .image         = rt->image[image_index],
 | 
			
		||||
 /* clang-format off */
 | 
			
		||||
        .subresourceRange = {
 | 
			
		||||
            .aspectMask = aspect_mask,
 | 
			
		||||
            .baseArrayLayer = 0,
 | 
			
		||||
            .baseMipLevel = 0,
 | 
			
		||||
            .layerCount = 1,
 | 
			
		||||
            .levelCount = 1,
 | 
			
		||||
        },
 | 
			
		||||
                .subresourceRange = {
 | 
			
		||||
                    .aspectMask = aspect_mask,
 | 
			
		||||
                    .baseArrayLayer = 0,
 | 
			
		||||
                    .baseMipLevel = 0,
 | 
			
		||||
                    .layerCount = 1,
 | 
			
		||||
                    .levelCount = 1,
 | 
			
		||||
                },
 | 
			
		||||
  /* clang-format on */
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
@ -260,3 +375,24 @@ void RT_RENDERER_API_FN(CmdTransitionRenderTarget)(rt_command_buffer_handle cmdb
 | 
			
		||||
 | 
			
		||||
    rt->states[image_index] = new_state;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RT_RENDERER_API_FN(CmdTransitionRenderTarget)(rt_command_buffer_handle cmdbuf_handle,
 | 
			
		||||
                                                   rt_render_target_handle render_target,
 | 
			
		||||
                                                   rt_render_target_state new_state) {
 | 
			
		||||
    GET_CMDBUF(cmdbuf, cmdbuf_handle)
 | 
			
		||||
    uint32_t image_index = g_gpu.current_frame_id % g_gpu.max_frames_in_flight;
 | 
			
		||||
    if (render_target.index == g_renderer.GetSwapchainRenderTarget().index) {
 | 
			
		||||
        image_index = rtGetFrameData(g_gpu.current_frame_id)->swapchain_image_index;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    rt_render_target *rt = rtGetRenderTarget(render_target);
 | 
			
		||||
    if (!rt) {
 | 
			
		||||
        rtLog("vk", "Tried to transition invalid render target");
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (rt->states[image_index] != new_state)
 | 
			
		||||
        DoLayoutTransition(rt, image_index, new_state, cmdbuf);
 | 
			
		||||
    else
 | 
			
		||||
        ExecuteRenderTargetBarrier(rt, image_index, cmdbuf);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -89,7 +89,8 @@ DebugUtilsMessengerCb(VkDebugUtilsMessageSeverityFlagBitsEXT severity,
 | 
			
		||||
    else if (severity == VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT)
 | 
			
		||||
        severity_str = "ERROR";
 | 
			
		||||
    rtLog("vk", "[%s] %s", severity_str, callbackData->pMessage);
 | 
			
		||||
    RT_DEBUGBREAK;
 | 
			
		||||
    if (severity == VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT)
 | 
			
		||||
        RT_DEBUGBREAK;
 | 
			
		||||
    return VK_FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -645,6 +646,8 @@ extern rt_result InitCommandBufferManagement(void);
 | 
			
		||||
extern void ShutdownCommandBufferManagement(void);
 | 
			
		||||
extern rt_result InitializeSempahoreManagement(void);
 | 
			
		||||
extern void ShutdownSemaphoreManagement(void);
 | 
			
		||||
extern rt_result InitBufferManagement(void);
 | 
			
		||||
extern void ShutdownBufferManagement(void);
 | 
			
		||||
 | 
			
		||||
rt_result RT_RENDERER_API_FN(Init)(const rt_renderer_init_info *info) {
 | 
			
		||||
    rtLog("vk", "Init");
 | 
			
		||||
@ -691,6 +694,9 @@ rt_result RT_RENDERER_API_FN(Init)(const rt_renderer_init_info *info) {
 | 
			
		||||
    if (res != RT_SUCCESS)
 | 
			
		||||
        return res;
 | 
			
		||||
    res = InitCommandBufferManagement();
 | 
			
		||||
    if (res != RT_SUCCESS)
 | 
			
		||||
        return res;
 | 
			
		||||
    res = InitBufferManagement();
 | 
			
		||||
    if (res != RT_SUCCESS)
 | 
			
		||||
        return res;
 | 
			
		||||
    res = rtCreateSwapchain();
 | 
			
		||||
@ -705,6 +711,7 @@ void RT_RENDERER_API_FN(Shutdown)(void) {
 | 
			
		||||
    rtLog("vk", "Shutdown");
 | 
			
		||||
    vkDeviceWaitIdle(g_gpu.device);
 | 
			
		||||
    rtDestroySwapchain();
 | 
			
		||||
    ShutdownBufferManagement();
 | 
			
		||||
    ShutdownCommandBufferManagement();
 | 
			
		||||
    ShutdownSemaphoreManagement();
 | 
			
		||||
    ShutdownRenderTargetManagement();
 | 
			
		||||
 | 
			
		||||
@ -16,6 +16,7 @@ if vk_dep.found()
 | 
			
		||||
    'render_targets.h',
 | 
			
		||||
    'swapchain.h',
 | 
			
		||||
 | 
			
		||||
    'buffers.c',
 | 
			
		||||
    'command_buffers.c',
 | 
			
		||||
    'commands.c',
 | 
			
		||||
    'frame.c',
 | 
			
		||||
 | 
			
		||||
@ -9,6 +9,9 @@
 | 
			
		||||
#include <X11/Xlib.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
/* GFX */
 | 
			
		||||
#include "gfx/gfx.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -42,7 +42,9 @@ static bool CreateImageAndView(VkExtent2D extent,
 | 
			
		||||
                               VkImageAspectFlagBits aspect,
 | 
			
		||||
                               VkImage *p_image,
 | 
			
		||||
                               VmaAllocation *p_allocation,
 | 
			
		||||
                               VkImageView *p_view) {
 | 
			
		||||
                               VkImageView *p_view,
 | 
			
		||||
                               const char *rt_name,
 | 
			
		||||
                               uint32_t image_index) {
 | 
			
		||||
 | 
			
		||||
    uint32_t queue_families[3];
 | 
			
		||||
    uint32_t distinct_queue_families = 1;
 | 
			
		||||
@ -140,6 +142,25 @@ static bool CreateImageAndView(VkExtent2D extent,
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#ifdef RT_DEBUG
 | 
			
		||||
    char name[260];
 | 
			
		||||
    rtSPrint(name, 260, "%s (%u)", rt_name ? rt_name : "unnamed rendertarget", image_index);
 | 
			
		||||
    VkDebugUtilsObjectNameInfoEXT name_info = {
 | 
			
		||||
        .sType        = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT,
 | 
			
		||||
        .objectHandle = (uint64_t)image,
 | 
			
		||||
        .pObjectName  = name,
 | 
			
		||||
        .objectType   = VK_OBJECT_TYPE_IMAGE};
 | 
			
		||||
    vkSetDebugUtilsObjectNameEXT(g_gpu.device, &name_info);
 | 
			
		||||
 | 
			
		||||
    rtSPrint(name, 260, "%s [view] (%u)", rt_name ? rt_name : "unnamed rendertarget", image_index);
 | 
			
		||||
    name_info =
 | 
			
		||||
        (VkDebugUtilsObjectNameInfoEXT){.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT,
 | 
			
		||||
                                        .objectHandle = (uint64_t)view,
 | 
			
		||||
                                        .pObjectName  = name,
 | 
			
		||||
                                        .objectType   = VK_OBJECT_TYPE_IMAGE_VIEW};
 | 
			
		||||
    vkSetDebugUtilsObjectNameEXT(g_gpu.device, &name_info);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    *p_image      = image;
 | 
			
		||||
    *p_allocation = allocation;
 | 
			
		||||
    *p_view       = view;
 | 
			
		||||
@ -201,6 +222,8 @@ rt_render_target_handle RT_RENDERER_API_FN(CreateRenderTarget)(const rt_render_t
 | 
			
		||||
     */
 | 
			
		||||
    rtUnlockWrite(&_lock);
 | 
			
		||||
 | 
			
		||||
    const char *name = rtResolveConstRelptr(&info->name);
 | 
			
		||||
 | 
			
		||||
    slot->render_target.match_swapchain = 0;
 | 
			
		||||
    slot->render_target.image_count     = g_swapchain.image_count;
 | 
			
		||||
    for (unsigned int i = 0; i < g_swapchain.image_count; ++i) {
 | 
			
		||||
@ -243,7 +266,9 @@ rt_render_target_handle RT_RENDERER_API_FN(CreateRenderTarget)(const rt_render_t
 | 
			
		||||
                                slot->render_target.aspect,
 | 
			
		||||
                                &slot->render_target.image[i],
 | 
			
		||||
                                &slot->render_target.allocation[i],
 | 
			
		||||
                                &slot->render_target.view[i])) {
 | 
			
		||||
                                &slot->render_target.view[i],
 | 
			
		||||
                                name,
 | 
			
		||||
                                i)) {
 | 
			
		||||
            slot->render_target.image_count = i;
 | 
			
		||||
            DestroyRenderTarget(slot);
 | 
			
		||||
            goto out;
 | 
			
		||||
@ -332,7 +357,9 @@ void rtUpdateRenderTargetsFromSwapchain(uint32_t image_count, VkFormat format, V
 | 
			
		||||
                                        render_target->aspect,
 | 
			
		||||
                                        &render_target->image[j],
 | 
			
		||||
                                        &render_target->allocation[j],
 | 
			
		||||
                                        &render_target->view[j])) {
 | 
			
		||||
                                        &render_target->view[j],
 | 
			
		||||
                                        NULL,
 | 
			
		||||
                                        j)) {
 | 
			
		||||
                    render_target->image_count = j;
 | 
			
		||||
                    DestroyRenderTarget(&_render_targets[i]);
 | 
			
		||||
                    rtReportError("VK", "Failed to recreate swapchain-matching render target");
 | 
			
		||||
@ -349,7 +376,9 @@ void rtUpdateRenderTargetsFromSwapchain(uint32_t image_count, VkFormat format, V
 | 
			
		||||
                                        render_target->aspect,
 | 
			
		||||
                                        &render_target->image[j],
 | 
			
		||||
                                        &render_target->allocation[j],
 | 
			
		||||
                                        &render_target->view[j])) {
 | 
			
		||||
                                        &render_target->view[j],
 | 
			
		||||
                                        NULL,
 | 
			
		||||
                                        j)) {
 | 
			
		||||
                    render_target->image_count = j;
 | 
			
		||||
                    DestroyRenderTarget(&_render_targets[i]);
 | 
			
		||||
                    rtReportError("VK", "Failed to create additional render target images");
 | 
			
		||||
 | 
			
		||||
@ -28,7 +28,9 @@ typedef struct {
 | 
			
		||||
static rt_device_swapchain_parameters DetermineSwapchainParameters(void) {
 | 
			
		||||
    rt_device_swapchain_parameters params;
 | 
			
		||||
 | 
			
		||||
    /* determine presentation mode. FIFO should always be available */
 | 
			
		||||
    /* determine presentation mode. FIFO should always be available.
 | 
			
		||||
     * TODO: If vsync is enabled, we should always choose FIFO.
 | 
			
		||||
     */
 | 
			
		||||
    params.present_mode = VK_PRESENT_MODE_FIFO_KHR;
 | 
			
		||||
    if (r_VkPreferMailboxMode.i) {
 | 
			
		||||
        VkPresentModeKHR modes[6];
 | 
			
		||||
@ -43,6 +45,7 @@ static rt_device_swapchain_parameters DetermineSwapchainParameters(void) {
 | 
			
		||||
    /* Determine surface format */
 | 
			
		||||
    VkSurfaceFormatKHR formats[64];
 | 
			
		||||
    uint32_t format_count = 64;
 | 
			
		||||
    vkGetPhysicalDeviceSurfaceFormatsKHR(g_gpu.phys_device, g_gpu.surface, &format_count, NULL);
 | 
			
		||||
    vkGetPhysicalDeviceSurfaceFormatsKHR(g_gpu.phys_device, g_gpu.surface, &format_count, formats);
 | 
			
		||||
    params.surface_format = formats[0];
 | 
			
		||||
    for (uint32_t i = 0; i < format_count; ++i) {
 | 
			
		||||
 | 
			
		||||
@ -49,7 +49,7 @@ static bool DisplayErrorBox(const char *text) {
 | 
			
		||||
 | 
			
		||||
static void LogOut(const char *text) {
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
    WCHAR msg[256];
 | 
			
		||||
    WCHAR msg[512];
 | 
			
		||||
    rtUTF8ToWStr(text, msg, RT_ARRAY_COUNT(msg));
 | 
			
		||||
    OutputDebugStringW(msg);
 | 
			
		||||
#endif
 | 
			
		||||
@ -57,7 +57,7 @@ static void LogOut(const char *text) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RT_DLLEXPORT void rtReportError(const char *subsystem, const char *fmt, ...) {
 | 
			
		||||
    char buf[256];
 | 
			
		||||
    char buf[512];
 | 
			
		||||
 | 
			
		||||
    int at = rtSPrint(buf, RT_ARRAY_COUNT(buf) - 1, "[%s] ", subsystem);
 | 
			
		||||
    va_list ap;
 | 
			
		||||
@ -73,7 +73,7 @@ RT_DLLEXPORT void rtReportError(const char *subsystem, const char *fmt, ...) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RT_DLLEXPORT void rtLog(const char *subsystem, const char *fmt, ...) {
 | 
			
		||||
    char buf[256];
 | 
			
		||||
    char buf[512];
 | 
			
		||||
 | 
			
		||||
    int at = rtSPrint(buf, RT_ARRAY_COUNT(buf), "[%s] ", subsystem);
 | 
			
		||||
    va_list ap;
 | 
			
		||||
 | 
			
		||||
@ -10,7 +10,7 @@ struct rt_condition_var_s {
 | 
			
		||||
    ptrdiff_t next_reusable;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define MAX_CONDS 1024
 | 
			
		||||
#define MAX_CONDS 4096
 | 
			
		||||
rt_condition_var _conds[MAX_CONDS];
 | 
			
		||||
static ptrdiff_t _first_reusable = MAX_CONDS;
 | 
			
		||||
static ptrdiff_t _next           = 0;
 | 
			
		||||
@ -75,7 +75,7 @@ struct rt_condition_var_s {
 | 
			
		||||
    ptrdiff_t next_reusable;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define MAX_CONDS 1024
 | 
			
		||||
#define MAX_CONDS 4096
 | 
			
		||||
rt_condition_var _conds[MAX_CONDS];
 | 
			
		||||
static ptrdiff_t _first_reusable = MAX_CONDS;
 | 
			
		||||
static ptrdiff_t _next           = 0;
 | 
			
		||||
 | 
			
		||||
@ -11,7 +11,7 @@ struct rt_mutex_s {
 | 
			
		||||
    DWORD owner;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define MAX_MUTEX 1024
 | 
			
		||||
#define MAX_MUTEX 4096
 | 
			
		||||
static rt_mutex _mutex[MAX_MUTEX];
 | 
			
		||||
static ptrdiff_t _first_reusable = MAX_MUTEX;
 | 
			
		||||
static ptrdiff_t _next           = 0;
 | 
			
		||||
@ -106,7 +106,7 @@ struct rt_mutex_s {
 | 
			
		||||
    ptrdiff_t next_reusable;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define MAX_MUTEX 1024
 | 
			
		||||
#define MAX_MUTEX 4096
 | 
			
		||||
static rt_mutex _mutex[MAX_MUTEX];
 | 
			
		||||
static ptrdiff_t _first_reusable = MAX_MUTEX;
 | 
			
		||||
static ptrdiff_t _next           = 0;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										31
									
								
								vk_layer_settings.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								vk_layer_settings.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,31 @@
 | 
			
		||||
# The main, heavy-duty validation checks. This may be valuable early in the
 | 
			
		||||
# development cycle to reduce validation output while correcting
 | 
			
		||||
# parameter/object usage errors.
 | 
			
		||||
khronos_validation.validate_core = true
 | 
			
		||||
 | 
			
		||||
# Enable synchronization validation during command buffers recording. This
 | 
			
		||||
# feature reports resource access conflicts due to missing or incorrect
 | 
			
		||||
# synchronization operations between actions (Draw, Copy, Dispatch, Blit)
 | 
			
		||||
# reading or writing the same regions of memory.
 | 
			
		||||
khronos_validation.validate_sync = true
 | 
			
		||||
 | 
			
		||||
# Thread checks. In order to not degrade performance, it might be best to run
 | 
			
		||||
# your program with thread-checking disabled most of the time, enabling it
 | 
			
		||||
# occasionally for a quick sanity check or when debugging difficult application
 | 
			
		||||
# behaviors.
 | 
			
		||||
khronos_validation.thread_safety = true
 | 
			
		||||
 | 
			
		||||
# Specifies what action is to be taken when a layer reports information
 | 
			
		||||
khronos_validation.debug_action = VK_DBG_LAYER_ACTION_LOG_MSG
 | 
			
		||||
 | 
			
		||||
# Comma-delineated list of options specifying the types of messages to be reported
 | 
			
		||||
khronos_validation.report_flags = debug,error,perf,info,warn
 | 
			
		||||
 | 
			
		||||
# Enable limiting of duplicate messages.
 | 
			
		||||
khronos_validation.enable_message_limit = true
 | 
			
		||||
 | 
			
		||||
# Maximum number of times any single validation message should be reported.
 | 
			
		||||
khronos_validation.duplicate_message_limit = 3
 | 
			
		||||
 | 
			
		||||
# Enable once the implementation is more mature
 | 
			
		||||
khronos_validation.validate_best_practices = false
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user