Various improvements
- Support static linking - Buffer manager
This commit is contained in:
		
							parent
							
								
									b2037519cc
								
							
						
					
					
						commit
						11ec5a0cd2
					
				
							
								
								
									
										24
									
								
								meson.build
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								meson.build
									
									
									
									
									
								
							@ -1,5 +1,5 @@
 | 
				
			|||||||
project('voyage', 'c',
 | 
					project('voyage', 'c',
 | 
				
			||||||
  default_options: ['buildtype=debugoptimized', 'b_sanitize=address', 'c_std=c17', 'warning_level=3'])
 | 
					  default_options: ['buildtype=debug', 'b_sanitize=address', 'c_std=c17', 'warning_level=3'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
compiler = meson.get_compiler('c')
 | 
					compiler = meson.get_compiler('c')
 | 
				
			||||||
buildtype = get_option('buildtype')
 | 
					buildtype = get_option('buildtype')
 | 
				
			||||||
@ -21,6 +21,10 @@ elif compiler.get_argument_syntax() == 'msvc'
 | 
				
			|||||||
  endif
 | 
					  endif
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if get_option('default_library') == 'static'
 | 
				
			||||||
 | 
					    add_project_arguments(['-DVY_STATIC_LIB'], language : 'c')
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Debug specific flags
 | 
					# Debug specific flags
 | 
				
			||||||
if buildtype == 'debug' or buildtype == 'debugoptimized'
 | 
					if buildtype == 'debug' or buildtype == 'debugoptimized'
 | 
				
			||||||
  add_project_arguments([ '-DVY_DEBUG'], language : 'c')
 | 
					  add_project_arguments([ '-DVY_DEBUG'], language : 'c')
 | 
				
			||||||
@ -51,6 +55,7 @@ runtime_lib = library('vyrt',
 | 
				
			|||||||
  'src/runtime/jobs.h',
 | 
					  'src/runtime/jobs.h',
 | 
				
			||||||
  'src/runtime/aio.h',
 | 
					  'src/runtime/aio.h',
 | 
				
			||||||
  'src/runtime/file_tab.h',
 | 
					  'src/runtime/file_tab.h',
 | 
				
			||||||
 | 
					  'src/runtime/buffer_manager.h',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  'src/runtime/error_report.c',
 | 
					  'src/runtime/error_report.c',
 | 
				
			||||||
  'src/runtime/gfx_main.c',
 | 
					  'src/runtime/gfx_main.c',
 | 
				
			||||||
@ -65,6 +70,7 @@ runtime_lib = library('vyrt',
 | 
				
			|||||||
  'src/runtime/jobs.c',
 | 
					  'src/runtime/jobs.c',
 | 
				
			||||||
  'src/runtime/aio.c',
 | 
					  'src/runtime/aio.c',
 | 
				
			||||||
  'src/runtime/file_tab.c',
 | 
					  'src/runtime/file_tab.c',
 | 
				
			||||||
 | 
					  'src/runtime/buffer_manager.c',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # Contrib Sources
 | 
					  # Contrib Sources
 | 
				
			||||||
  'contrib/xxhash/xxhash.c',
 | 
					  'contrib/xxhash/xxhash.c',
 | 
				
			||||||
@ -72,6 +78,10 @@ runtime_lib = library('vyrt',
 | 
				
			|||||||
  include_directories : incdir,
 | 
					  include_directories : incdir,
 | 
				
			||||||
  c_pch : 'pch/rt_pch.h')
 | 
					  c_pch : 'pch/rt_pch.h')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Renderer libraries
 | 
				
			||||||
 | 
					static_renderer_lib = 'NONE'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if vk_dep.found()
 | 
					if vk_dep.found()
 | 
				
			||||||
  platform_defs = []
 | 
					  platform_defs = []
 | 
				
			||||||
  if get_option('use_xlib')
 | 
					  if get_option('use_xlib')
 | 
				
			||||||
@ -98,12 +108,22 @@ if vk_dep.found()
 | 
				
			|||||||
    link_with : [runtime_lib],
 | 
					    link_with : [runtime_lib],
 | 
				
			||||||
    c_pch : 'pch/vk_pch.h',
 | 
					    c_pch : 'pch/vk_pch.h',
 | 
				
			||||||
    c_args : platform_defs)
 | 
					    c_args : platform_defs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static_renderer_lib = vk_renderer_lib
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					game_link_libs = []
 | 
				
			||||||
 | 
					if get_option('default_library') == 'static'
 | 
				
			||||||
 | 
					  game_link_libs = [runtime_lib, static_renderer_lib]
 | 
				
			||||||
 | 
					else
 | 
				
			||||||
 | 
					  game_link_libs = [runtime_lib]
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
executable('voyage',
 | 
					executable('voyage',
 | 
				
			||||||
  'src/game/voyage.c',
 | 
					  'src/game/voyage.c',
 | 
				
			||||||
  include_directories : incdir,
 | 
					  include_directories : incdir,
 | 
				
			||||||
  link_with : [runtime_lib],
 | 
					  link_with : game_link_libs,
 | 
				
			||||||
  win_subsystem : 'windows')
 | 
					  win_subsystem : 'windows')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -52,8 +52,7 @@ static void ReleasePipelineSlot(vy_gfx_pipeline_handle id) {
 | 
				
			|||||||
        _storage.generation_in_use[slot] &= ~0x1;
 | 
					        _storage.generation_in_use[slot] &= ~0x1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
VY_DLLEXPORT vy_gfx_pipeline_handle
 | 
					vy_gfx_pipeline_handle VY_RENDERER_API_FN(CompileComputePipeline)(const vy_compute_pipeline_info *info) {
 | 
				
			||||||
vyCompileComputePipeline(const vy_compute_pipeline_info *info) {
 | 
					 | 
				
			||||||
#if 0
 | 
					#if 0
 | 
				
			||||||
    char info_log[512];
 | 
					    char info_log[512];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -94,8 +93,7 @@ vyCompileComputePipeline(const vy_compute_pipeline_info *info) {
 | 
				
			|||||||
    return StorePipeline(pipeline);
 | 
					    return StorePipeline(pipeline);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
VY_DLLEXPORT vy_gfx_pipeline_handle
 | 
					vy_gfx_pipeline_handle VY_RENDERER_API_FN(CompileGraphicsPipeline)(const vy_graphics_pipeline_info *info) {
 | 
				
			||||||
vyCompileGraphicsPipeline(const vy_graphics_pipeline_info *info) {
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if 0
 | 
					#if 0
 | 
				
			||||||
    char info_log[512];
 | 
					    char info_log[512];
 | 
				
			||||||
 | 
				
			|||||||
@ -85,7 +85,7 @@ DebugUtilsMessengerCb(VkDebugUtilsMessageSeverityFlagBitsEXT severity,
 | 
				
			|||||||
extern vy_cvar r_VkPreferredSwapchainImages;
 | 
					extern vy_cvar r_VkPreferredSwapchainImages;
 | 
				
			||||||
extern vy_cvar r_VkPreferMailboxMode;
 | 
					extern vy_cvar r_VkPreferMailboxMode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
VY_DLLEXPORT void vyRegisterCVars(void) {
 | 
					void VY_RENDERER_API_FN(RegisterCVars)(void) {
 | 
				
			||||||
    vyRegisterCVAR(&r_VkEnableAPIAllocTracking);
 | 
					    vyRegisterCVAR(&r_VkEnableAPIAllocTracking);
 | 
				
			||||||
    vyRegisterCVAR(&r_VkPhysDeviceName);
 | 
					    vyRegisterCVAR(&r_VkPhysDeviceName);
 | 
				
			||||||
    vyRegisterCVAR(&r_VkPreferredSwapchainImages);
 | 
					    vyRegisterCVAR(&r_VkPreferredSwapchainImages);
 | 
				
			||||||
@ -470,7 +470,7 @@ static vy_result CreateDevice(void) {
 | 
				
			|||||||
    return VY_SUCCESS;
 | 
					    return VY_SUCCESS;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
VY_DLLEXPORT vy_result vyInit(const vy_renderer_init_info *info) {
 | 
					vy_result VY_RENDERER_API_FN(Init)(const vy_renderer_init_info *info) {
 | 
				
			||||||
    vyLog("vk", "Init");
 | 
					    vyLog("vk", "Init");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    _tracking_alloc_cbs.pUserData       = NULL;
 | 
					    _tracking_alloc_cbs.pUserData       = NULL;
 | 
				
			||||||
@ -503,7 +503,7 @@ VY_DLLEXPORT vy_result vyInit(const vy_renderer_init_info *info) {
 | 
				
			|||||||
    return VY_SUCCESS;
 | 
					    return VY_SUCCESS;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
VY_DLLEXPORT void vyShutdown(void) {
 | 
					void VY_RENDERER_API_FN(Shutdown)(void) {
 | 
				
			||||||
    vyLog("vk", "Shutdown");
 | 
					    vyLog("vk", "Shutdown");
 | 
				
			||||||
    vkDeviceWaitIdle(g_gpu.device);
 | 
					    vkDeviceWaitIdle(g_gpu.device);
 | 
				
			||||||
    vyDestroySwapchain();
 | 
					    vyDestroySwapchain();
 | 
				
			||||||
 | 
				
			|||||||
@ -3,6 +3,7 @@
 | 
				
			|||||||
#include "gfx.h"
 | 
					#include "gfx.h"
 | 
				
			||||||
#include "aio.h"
 | 
					#include "aio.h"
 | 
				
			||||||
#include "renderer_api.h"
 | 
					#include "renderer_api.h"
 | 
				
			||||||
 | 
					#include "buffer_manager.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern void __RegisterRuntimeCVars(void);
 | 
					extern void __RegisterRuntimeCVars(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -37,6 +38,11 @@ VY_DLLEXPORT int vyWin32Entry(HINSTANCE hInstance,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    /* TODO: Parse the cvar config file */
 | 
					    /* TODO: Parse the cvar config file */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (vyInitBufferManager() != VY_SUCCESS) {
 | 
				
			||||||
 | 
					        vyReportError("BUFFERMGR", "Init failed.");
 | 
				
			||||||
 | 
					        return 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (vyInitFileTab(1024) != VY_SUCCESS) {
 | 
					    if (vyInitFileTab(1024) != VY_SUCCESS) {
 | 
				
			||||||
        vyReportError("FTAB", "Init failed.");
 | 
					        vyReportError("FTAB", "Init failed.");
 | 
				
			||||||
        return 1;
 | 
					        return 1;
 | 
				
			||||||
@ -131,6 +137,7 @@ VY_DLLEXPORT int vyWin32Entry(HINSTANCE hInstance,
 | 
				
			|||||||
    vyShutdownAIO();
 | 
					    vyShutdownAIO();
 | 
				
			||||||
    vyShutdownAIO();
 | 
					    vyShutdownAIO();
 | 
				
			||||||
    vyShutdownFileTab();
 | 
					    vyShutdownFileTab();
 | 
				
			||||||
 | 
					    vyShutdownBufferManager();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -180,6 +187,11 @@ VY_DLLEXPORT int vyXlibEntry(int argc, char **argv) {
 | 
				
			|||||||
    __RegisterRuntimeCVars();
 | 
					    __RegisterRuntimeCVars();
 | 
				
			||||||
    vyRegisterRendererCVars();
 | 
					    vyRegisterRendererCVars();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (vyInitBufferManager() != VY_SUCCESS) {
 | 
				
			||||||
 | 
					        vyReportError("BUFFERMGR", "Init failed.");
 | 
				
			||||||
 | 
					        return 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (vyInitFileTab(1024) != VY_SUCCESS) {
 | 
					    if (vyInitFileTab(1024) != VY_SUCCESS) {
 | 
				
			||||||
        vyReportError("FTAB", "Init failed.");
 | 
					        vyReportError("FTAB", "Init failed.");
 | 
				
			||||||
        return 1;
 | 
					        return 1;
 | 
				
			||||||
@ -260,6 +272,7 @@ VY_DLLEXPORT int vyXlibEntry(int argc, char **argv) {
 | 
				
			|||||||
    XCloseDisplay(dpy);
 | 
					    XCloseDisplay(dpy);
 | 
				
			||||||
    vyShutdownAIO();
 | 
					    vyShutdownAIO();
 | 
				
			||||||
    vyShutdownFileTab();
 | 
					    vyShutdownFileTab();
 | 
				
			||||||
 | 
					    vyShutdownBufferManager();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										250
									
								
								src/runtime/buffer_manager.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										250
									
								
								src/runtime/buffer_manager.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,250 @@
 | 
				
			|||||||
 | 
					#include "runtime.h"
 | 
				
			||||||
 | 
					#include "threading.h"
 | 
				
			||||||
 | 
					#include "config.h"
 | 
				
			||||||
 | 
					#include "buffer_manager.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
					#include <assert.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct vy_buffer_region_s {
 | 
				
			||||||
 | 
					    void *memory;
 | 
				
			||||||
 | 
					    int16_t *refcounts; // One per block
 | 
				
			||||||
 | 
					    uint32_t *bitmap;
 | 
				
			||||||
 | 
					    size_t block_count;
 | 
				
			||||||
 | 
					    vy_mutex *guard;
 | 
				
			||||||
 | 
					} vy_buffer_region;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Count leading zeroes.
 | 
				
			||||||
 | 
					 * Note that the return value of __builtin_clz(0) is undefined. */
 | 
				
			||||||
 | 
					#ifdef _MSC_VER
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <intrin.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define lzcnt32(x) __lzcnt((x))
 | 
				
			||||||
 | 
					#define popcnt32(x) __popcnt((x))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static __forceinline uint32_t tzcnt32(uint32_t x) {
 | 
				
			||||||
 | 
					    unsigned long i;
 | 
				
			||||||
 | 
					    _BitScanForward(&i, x);
 | 
				
			||||||
 | 
					    return (uint32_t)i;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline bool IsLZCNTSupported(void) {
 | 
				
			||||||
 | 
					#define Type 0x80000001
 | 
				
			||||||
 | 
					    int info[4];
 | 
				
			||||||
 | 
					    __cpuid(info, Type);
 | 
				
			||||||
 | 
					    return (info[2] & (1 << 5)) != 0;
 | 
				
			||||||
 | 
					#undef Type
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#elif defined(__GNUC__)
 | 
				
			||||||
 | 
					#define lzcnt32(x) __builtin_clz((x))
 | 
				
			||||||
 | 
					#define tzcnt32(x)  __builtin_ctz((x))
 | 
				
			||||||
 | 
					#define popcnt32(x) __builtin_popcount((x))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define IsLZCNTSupported() true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* NOTE(Kevin): Keep these sorted! */
 | 
				
			||||||
 | 
					static size_t _block_sizes[] = {VY_KB(512), VY_MB(1), VY_MB(4), VY_MB(8) };
 | 
				
			||||||
 | 
					#define NUM_BLOCK_SIZES (sizeof(_block_sizes) / sizeof(_block_sizes[0]))
 | 
				
			||||||
 | 
					static vy_buffer_region _regions[NUM_BLOCK_SIZES];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VY_CVAR_SZ(
 | 
				
			||||||
 | 
					    rt_BufferManagerMemory,
 | 
				
			||||||
 | 
					    "Total number of bytes allocated for the buffer manager. Default: 1GB", VY_GB(1));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VY_DLLEXPORT vy_result vyInitBufferManager(void) {
 | 
				
			||||||
 | 
					    if ((rt_BufferManagerMemory.sz % NUM_BLOCK_SIZES) != 0)
 | 
				
			||||||
 | 
					        vyLog("BUFFERMGR",
 | 
				
			||||||
 | 
					              "Configured memory amount is not dividable by number of block "
 | 
				
			||||||
 | 
					              "sizes: %u MB/%u",
 | 
				
			||||||
 | 
					              rt_BufferManagerMemory.sz / (1024 * 1024),
 | 
				
			||||||
 | 
					              NUM_BLOCK_SIZES);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    size_t mem_per_size = rt_BufferManagerMemory.sz / NUM_BLOCK_SIZES;
 | 
				
			||||||
 | 
					    for (unsigned int i = 0; i < NUM_BLOCK_SIZES; ++i) {
 | 
				
			||||||
 | 
					        if ((mem_per_size % _block_sizes[i]) != 0)
 | 
				
			||||||
 | 
					            vyLog("BUFFERMGR",
 | 
				
			||||||
 | 
					                  "Memory per block size is not dividable by block size: %u "
 | 
				
			||||||
 | 
					                  "MB/%u KB",
 | 
				
			||||||
 | 
					                  mem_per_size / (1024 * 1024),
 | 
				
			||||||
 | 
					                  _block_sizes[i] / 1024);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        size_t block_count = mem_per_size / _block_sizes[i];
 | 
				
			||||||
 | 
					        _regions[i].block_count = block_count;
 | 
				
			||||||
 | 
					        _regions[i].guard       = vyCreateMutex();
 | 
				
			||||||
 | 
					        if (!_regions[i].guard) {
 | 
				
			||||||
 | 
					            vyReportError("BUFFERMGR", "Failed to create guard mutex %u", i);
 | 
				
			||||||
 | 
					            return VY_BUFFER_MGR_MUTEX_CREATION_FAILED;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        _regions[i].memory      = malloc(mem_per_size);
 | 
				
			||||||
 | 
					        if (!_regions[i].memory) {
 | 
				
			||||||
 | 
					            vyDestroyMutex(_regions[i].guard);
 | 
				
			||||||
 | 
					            vyReportError("BUFFERMGR", "Failed to allocate memory.", i);
 | 
				
			||||||
 | 
					            return VY_BUFFER_MGR_OUT_OF_MEMORY;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        _regions[i].bitmap = calloc((block_count + 31) / 32, sizeof(uint32_t));
 | 
				
			||||||
 | 
					        if (!_regions[i].bitmap) {
 | 
				
			||||||
 | 
					            vyDestroyMutex(_regions[i].guard);
 | 
				
			||||||
 | 
					            free(_regions[i].memory);
 | 
				
			||||||
 | 
					            vyReportError("BUFFERMGR", "Failed to allocate memory.", i);
 | 
				
			||||||
 | 
					            return VY_BUFFER_MGR_OUT_OF_MEMORY;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        _regions[i].refcounts = calloc(block_count, sizeof(uint16_t));
 | 
				
			||||||
 | 
					        if (!_regions[i].refcounts) {
 | 
				
			||||||
 | 
					            vyDestroyMutex(_regions[i].guard);
 | 
				
			||||||
 | 
					            free(_regions[i].memory);
 | 
				
			||||||
 | 
					            free(_regions[i].bitmap);
 | 
				
			||||||
 | 
					            vyReportError("BUFFERMGR", "Failed to allocate memory.", i);
 | 
				
			||||||
 | 
					            return VY_BUFFER_MGR_OUT_OF_MEMORY;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return VY_SUCCESS;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VY_DLLEXPORT void vyShutdownBufferManager(void) {
 | 
				
			||||||
 | 
					    for (unsigned int i = 0; i < NUM_BLOCK_SIZES; ++i) {
 | 
				
			||||||
 | 
					        vyDestroyMutex(_regions[i].guard);
 | 
				
			||||||
 | 
					        free(_regions[i].memory);
 | 
				
			||||||
 | 
					        free(_regions[i].bitmap);
 | 
				
			||||||
 | 
					        free(_regions[i].refcounts);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VY_DLLEXPORT void *vyAllocBuffer(size_t size) {
 | 
				
			||||||
 | 
					    assert(IsLZCNTSupported());
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // Determine the best block size to use
 | 
				
			||||||
 | 
					    size_t required_blocks = (size + _block_sizes[0] - 1) / _block_sizes[0];
 | 
				
			||||||
 | 
					    size_t best_fit        = 0;
 | 
				
			||||||
 | 
					    for (size_t i = 1; i < NUM_BLOCK_SIZES; ++i) {
 | 
				
			||||||
 | 
					        size_t block_count = (size + _block_sizes[i] - 1) / _block_sizes[i];
 | 
				
			||||||
 | 
					        if (block_count < required_blocks && size >= _block_sizes[i]) {
 | 
				
			||||||
 | 
					            required_blocks = block_count;
 | 
				
			||||||
 | 
					            best_fit        = i;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void *result = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    vy_buffer_region *region = &_regions[best_fit];
 | 
				
			||||||
 | 
					    vyLockMutex(region->guard);
 | 
				
			||||||
 | 
					    size_t dword_count = (region->block_count + 31) / 32;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (required_blocks < 32) {
 | 
				
			||||||
 | 
					        /* Fast path for allocations that potentially fit into one dword */
 | 
				
			||||||
 | 
					        uint32_t in_use_mask = (1ull << required_blocks) - 1;
 | 
				
			||||||
 | 
					        size_t max_occupancy = 32 - required_blocks;
 | 
				
			||||||
 | 
					        for (size_t i = 0; i < dword_count; ++i) {
 | 
				
			||||||
 | 
					            size_t block_index = 0;
 | 
				
			||||||
 | 
					            if (region->bitmap[i] != 0 && popcnt32(region->bitmap[i]) < max_occupancy) {
 | 
				
			||||||
 | 
					                size_t free_high_blocks = lzcnt32(region->bitmap[i]);
 | 
				
			||||||
 | 
					                if (free_high_blocks >= required_blocks) {
 | 
				
			||||||
 | 
					                    /* High blocks are free */
 | 
				
			||||||
 | 
					                    size_t first_free = 32 - free_high_blocks;
 | 
				
			||||||
 | 
					                    region->bitmap[i] |= (in_use_mask << first_free);
 | 
				
			||||||
 | 
					                    block_index = i * 32 + first_free;
 | 
				
			||||||
 | 
					                    result      = (char *)region->memory +
 | 
				
			||||||
 | 
					                        block_index * _block_sizes[best_fit];
 | 
				
			||||||
 | 
					                } else if (tzcnt32(region->bitmap[i]) >= required_blocks) {
 | 
				
			||||||
 | 
					                    /* Low blocks are free */
 | 
				
			||||||
 | 
					                    region->bitmap[i] |= in_use_mask;
 | 
				
			||||||
 | 
					                    block_index = i * 32;
 | 
				
			||||||
 | 
					                    result      = (char *)region->memory +  block_index * _block_sizes[best_fit];
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    /* Check if we can find a large enough range of free blocks.
 | 
				
			||||||
 | 
					                     * Start after the first set bit.
 | 
				
			||||||
 | 
					                     */
 | 
				
			||||||
 | 
					                    for (uint32_t j = tzcnt32(region->bitmap[i]) + 1; j < 32 - required_blocks; ++j) {
 | 
				
			||||||
 | 
					                        if ((region->bitmap[i] & in_use_mask << j) == 0) {
 | 
				
			||||||
 | 
					                            region->bitmap[i] |= (in_use_mask << j);
 | 
				
			||||||
 | 
					                            block_index = i * 32 + j;
 | 
				
			||||||
 | 
					                            result = (char *)region->memory + block_index * _block_sizes[best_fit];
 | 
				
			||||||
 | 
					                            break;
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            } else if (region->bitmap[i] == 0) {
 | 
				
			||||||
 | 
					                /* All free */
 | 
				
			||||||
 | 
					                region->bitmap[i]  = in_use_mask;
 | 
				
			||||||
 | 
					                block_index = i * 32;
 | 
				
			||||||
 | 
					                result             = (char *)region->memory + block_index * _block_sizes[best_fit];
 | 
				
			||||||
 | 
					            } else if (i < dword_count - 1) {
 | 
				
			||||||
 | 
					                /* Check if we can use high blocks from this dword and low blocks from the next one */
 | 
				
			||||||
 | 
					                size_t high_blocks = lzcnt32(region->bitmap[i]);
 | 
				
			||||||
 | 
					                size_t low_blocks  = (region->bitmap[i + 1] != 0) ? tzcnt32(region->bitmap[i + 1]) : 32;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (high_blocks + low_blocks >= required_blocks) {
 | 
				
			||||||
 | 
					                    size_t high_mask = (1u << high_blocks) - 1;
 | 
				
			||||||
 | 
					                    size_t first_free = 32 - high_blocks;
 | 
				
			||||||
 | 
					                    size_t low_mask = (1u << (required_blocks - high_blocks)) - 1;
 | 
				
			||||||
 | 
					                    
 | 
				
			||||||
 | 
					                    region->bitmap[i] |= (high_mask << first_free);
 | 
				
			||||||
 | 
					                    region->bitmap[i + 1] |= low_mask;
 | 
				
			||||||
 | 
					                    block_index = i * 32 + first_free;
 | 
				
			||||||
 | 
					                    result             = (char *)region->memory + block_index * _block_sizes[best_fit];
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (result) {
 | 
				
			||||||
 | 
					                for (size_t j = 0; j < required_blocks; ++j)
 | 
				
			||||||
 | 
					                    region->refcounts[block_index + j] = 1;
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    vyUnlockMutex(region->guard);
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VY_DLLEXPORT void vyReleaseBuffer(const void *begin, size_t size) {
 | 
				
			||||||
 | 
					    uintptr_t begin_addr = (uintptr_t)begin;
 | 
				
			||||||
 | 
					    for (unsigned int i = 0; i < NUM_BLOCK_SIZES; ++i) {
 | 
				
			||||||
 | 
					        uintptr_t region_addr = (uintptr_t)_regions[i].memory;
 | 
				
			||||||
 | 
					        size_t region_size    = _block_sizes[i] * _regions[i].block_count;
 | 
				
			||||||
 | 
					        if (begin_addr >= region_addr &&
 | 
				
			||||||
 | 
					                begin_addr + size <= region_addr + region_size) {
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					            size_t block_count = (size + _block_sizes[i] - 1) / _block_sizes[i];
 | 
				
			||||||
 | 
					            size_t first_block = (begin_addr - region_addr) / _block_sizes[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            vyLockMutex(_regions[i].guard);
 | 
				
			||||||
 | 
					            for (size_t j = 0; j < block_count; ++j) {
 | 
				
			||||||
 | 
					                size_t dword = (first_block + j) / 32;
 | 
				
			||||||
 | 
					                size_t bit   = (first_block + j) % 32;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (--_regions[i].refcounts[first_block + j] == 0)
 | 
				
			||||||
 | 
					                    _regions[i].bitmap[dword] &= ~(1u << bit);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            vyUnlockMutex(_regions[i].guard);
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    vyLog("BUFFERMGR", "Tried to release an invalid buffer");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VY_DLLEXPORT void vyIncreaseBufferRefCount(const void *begin, size_t size) {
 | 
				
			||||||
 | 
					    uintptr_t begin_addr = (uintptr_t)begin;
 | 
				
			||||||
 | 
					    for (unsigned int i = 0; i < NUM_BLOCK_SIZES; ++i) {
 | 
				
			||||||
 | 
					        uintptr_t region_addr = (uintptr_t)_regions[i].memory;
 | 
				
			||||||
 | 
					        size_t region_size    = _block_sizes[i] * _regions[i].block_count;
 | 
				
			||||||
 | 
					        if (begin_addr >= region_addr &&
 | 
				
			||||||
 | 
					            begin_addr + size <= region_addr + region_size) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            size_t block_count = (size + _block_sizes[i] - 1) / _block_sizes[i];
 | 
				
			||||||
 | 
					            size_t first_block = (begin_addr - region_addr) / _block_sizes[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            vyLockMutex(_regions[i].guard);
 | 
				
			||||||
 | 
					            for (size_t j = 0; j < block_count; ++j) {
 | 
				
			||||||
 | 
					                ++_regions[i].refcounts[first_block + j];
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            vyUnlockMutex(_regions[i].guard);
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    vyLog("BUFFERMGR", "Tried to increase the refcount of an invalid buffer");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										21
									
								
								src/runtime/buffer_manager.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/runtime/buffer_manager.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					#ifndef VY_BUFFER_MANAGER_H
 | 
				
			||||||
 | 
					#define VY_BUFFER_MANAGER_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "runtime.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum {
 | 
				
			||||||
 | 
					    VY_BUFFER_MGR_OUT_OF_MEMORY = VY_SUCCESS + 1,
 | 
				
			||||||
 | 
					    VY_BUFFER_MGR_MUTEX_CREATION_FAILED,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VY_DLLEXPORT vy_result vyInitBufferManager(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VY_DLLEXPORT void vyShutdownBufferManager(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VY_DLLEXPORT void *vyAllocBuffer(size_t size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VY_DLLEXPORT void vyReleaseBuffer(const void *begin, size_t size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VY_DLLEXPORT void vyIncreaseBufferRefCount(const void *begin, size_t size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
@ -8,6 +8,7 @@ typedef enum
 | 
				
			|||||||
    VY_CVAR_TYPE_INT,
 | 
					    VY_CVAR_TYPE_INT,
 | 
				
			||||||
    VY_CVAR_TYPE_FLOAT,
 | 
					    VY_CVAR_TYPE_FLOAT,
 | 
				
			||||||
    VY_CVAR_TYPE_STRING,
 | 
					    VY_CVAR_TYPE_STRING,
 | 
				
			||||||
 | 
					    VY_CVAR_TYPE_SIZE,
 | 
				
			||||||
} vy_cvar_type;
 | 
					} vy_cvar_type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct
 | 
					typedef struct
 | 
				
			||||||
@ -18,6 +19,7 @@ typedef struct
 | 
				
			|||||||
        int i;
 | 
					        int i;
 | 
				
			||||||
        float f;
 | 
					        float f;
 | 
				
			||||||
        const char *s;
 | 
					        const char *s;
 | 
				
			||||||
 | 
					        size_t sz;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    vy_cvar_type type;
 | 
					    vy_cvar_type type;
 | 
				
			||||||
} vy_cvar;
 | 
					} vy_cvar;
 | 
				
			||||||
@ -37,6 +39,11 @@ typedef struct
 | 
				
			|||||||
                 .description = d,                                             \
 | 
					                 .description = d,                                             \
 | 
				
			||||||
                 .s           = (v),                                           \
 | 
					                 .s           = (v),                                           \
 | 
				
			||||||
                 .type        = VY_CVAR_TYPE_STRING}
 | 
					                 .type        = VY_CVAR_TYPE_STRING}
 | 
				
			||||||
 | 
					#define VY_CVAR_SZ(n, d, v)                                                     \
 | 
				
			||||||
 | 
					    vy_cvar n = {.name        = #n,                                            \
 | 
				
			||||||
 | 
					                 .description = d,                                             \
 | 
				
			||||||
 | 
					                 .sz          = (v),                                           \
 | 
				
			||||||
 | 
					                 .type        = VY_CVAR_TYPE_SIZE}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
VY_DLLEXPORT void vyRegisterCVAR(vy_cvar *cvar);
 | 
					VY_DLLEXPORT void vyRegisterCVAR(vy_cvar *cvar);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -4,6 +4,10 @@
 | 
				
			|||||||
#define WIN32_LEAN_AND_MEAN
 | 
					#define WIN32_LEAN_AND_MEAN
 | 
				
			||||||
#include <Windows.h>
 | 
					#include <Windows.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VY_DLLEXPORT vy_dynlib vyOpenCallerLib(void) {
 | 
				
			||||||
 | 
					    return (vy_dynlib)GetModuleHandleW(NULL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
VY_DLLEXPORT vy_dynlib vyOpenLib(const char *libname) {
 | 
					VY_DLLEXPORT vy_dynlib vyOpenLib(const char *libname) {
 | 
				
			||||||
    wchar_t libname_w[MAX_PATH];
 | 
					    wchar_t libname_w[MAX_PATH];
 | 
				
			||||||
    MultiByteToWideChar(CP_UTF8,
 | 
					    MultiByteToWideChar(CP_UTF8,
 | 
				
			||||||
@ -27,6 +31,10 @@ VY_DLLEXPORT void vyCloseLib(vy_dynlib lib) {
 | 
				
			|||||||
#elif defined(__linux__)
 | 
					#elif defined(__linux__)
 | 
				
			||||||
#include <dlfcn.h>
 | 
					#include <dlfcn.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VY_DLLEXPORT vy_dynlib vyOpenCallerLib(void) {
 | 
				
			||||||
 | 
					    return dlopen(NULL, RTLD_NOW | RTLD_LOCAL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
VY_DLLEXPORT vy_dynlib vyOpenLib(const char *libname) {
 | 
					VY_DLLEXPORT vy_dynlib vyOpenLib(const char *libname) {
 | 
				
			||||||
    return dlopen(libname, RTLD_NOW | RTLD_LOCAL);
 | 
					    return dlopen(libname, RTLD_NOW | RTLD_LOCAL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -17,6 +17,8 @@ typedef void *vy_dynlib;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
VY_DLLEXPORT vy_dynlib vyOpenLib(const char *libname);
 | 
					VY_DLLEXPORT vy_dynlib vyOpenLib(const char *libname);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VY_DLLEXPORT vy_dynlib vyOpenCallerLib(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
VY_DLLEXPORT void *vyGetSymbol(vy_dynlib lib, const char *symbol);
 | 
					VY_DLLEXPORT void *vyGetSymbol(vy_dynlib lib, const char *symbol);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
VY_DLLEXPORT void vyCloseLib(vy_dynlib lib);
 | 
					VY_DLLEXPORT void vyCloseLib(vy_dynlib lib);
 | 
				
			||||||
 | 
				
			|||||||
@ -24,16 +24,28 @@ VY_CVAR_S(rt_Renderer,
 | 
				
			|||||||
extern bool
 | 
					extern bool
 | 
				
			||||||
vyLoadShaders(const char **paths, vy_shader *shaders, unsigned int count);
 | 
					vyLoadShaders(const char **paths, vy_shader *shaders, unsigned int count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef VY_STATIC_LIB
 | 
				
			||||||
 | 
					extern void VY_RENDERER_API_FN(RegisterCVars)(void);
 | 
				
			||||||
 | 
					extern vy_result VY_RENDERER_API_FN(Init)(const vy_renderer_init_info *);
 | 
				
			||||||
 | 
					extern void VY_RENDERER_API_FN(Shutdown)(void);
 | 
				
			||||||
 | 
					extern vy_gfx_pipeline_handle VY_RENDERER_API_FN(CompileComputePipeline)(
 | 
				
			||||||
 | 
					    const vy_compute_pipeline_info *);
 | 
				
			||||||
 | 
					extern vy_gfx_pipeline_handle VY_RENDERER_API_FN(CompileGraphicsPipeline)(
 | 
				
			||||||
 | 
					    const vy_graphics_pipeline_info *);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool LoadRenderer(void) {
 | 
					static bool LoadRenderer(void) {
 | 
				
			||||||
#define RETRIEVE_SYMBOL(name, type)                                            \
 | 
					
 | 
				
			||||||
    g_renderer.name = (type *)vyGetSymbol(_renderer_lib, "vy" #name);          \
 | 
					#if !defined(VY_STATIC_LIB)
 | 
				
			||||||
    if (!g_renderer.name) {                                                    \
 | 
					    #define RETRIEVE_SYMBOL(name, type)                                        \
 | 
				
			||||||
        vyReportError(                                                         \
 | 
					        g_renderer.name = (type *)vyGetSymbol(_renderer_lib, "vyRen" #name);   \
 | 
				
			||||||
            "GFX",                                                             \
 | 
					        if (!g_renderer.name) {                                                \
 | 
				
			||||||
            "Unable to retrieve renderer function %s from backend %s",         \
 | 
					            vyReportError(                                                     \
 | 
				
			||||||
            #name,                                                             \
 | 
					                "GFX",                                                         \
 | 
				
			||||||
            rt_Renderer.s);                                                    \
 | 
					                "Unable to retrieve renderer function %s from backend %s",     \
 | 
				
			||||||
    }
 | 
					                #name,                                                         \
 | 
				
			||||||
 | 
					                rt_Renderer.s);                                                \
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (strcmp(rt_Renderer.s, "vk") == 0) {
 | 
					    if (strcmp(rt_Renderer.s, "vk") == 0) {
 | 
				
			||||||
        _renderer_lib = vyOpenLib(VY_DLLNAME("vyvk"));
 | 
					        _renderer_lib = vyOpenLib(VY_DLLNAME("vyvk"));
 | 
				
			||||||
@ -49,7 +61,6 @@ static bool LoadRenderer(void) {
 | 
				
			|||||||
        RETRIEVE_SYMBOL(CompileComputePipeline, vy_compile_compute_pipeline_fn);
 | 
					        RETRIEVE_SYMBOL(CompileComputePipeline, vy_compile_compute_pipeline_fn);
 | 
				
			||||||
        RETRIEVE_SYMBOL(CompileGraphicsPipeline,
 | 
					        RETRIEVE_SYMBOL(CompileGraphicsPipeline,
 | 
				
			||||||
                        vy_compile_graphics_pipeline_fn);
 | 
					                        vy_compile_graphics_pipeline_fn);
 | 
				
			||||||
        return true;
 | 
					 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        vyReportError("GFX",
 | 
					        vyReportError("GFX",
 | 
				
			||||||
                      "Unsupported renderer backend: (%s) %s",
 | 
					                      "Unsupported renderer backend: (%s) %s",
 | 
				
			||||||
@ -57,7 +68,15 @@ static bool LoadRenderer(void) {
 | 
				
			|||||||
                      rt_Renderer.s);
 | 
					                      rt_Renderer.s);
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
#undef RETRIEVE_SYMBOL
 | 
					    #undef RETRIEVE_SYMBOL
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					    g_renderer.RegisterCVars = &vyRenRegisterCVars;
 | 
				
			||||||
 | 
					    g_renderer.Init          = &vyRenInit;
 | 
				
			||||||
 | 
					    g_renderer.Shutdown      = &vyRenShutdown;
 | 
				
			||||||
 | 
					    g_renderer.CompileComputePipeline = &vyRenCompileComputePipeline;
 | 
				
			||||||
 | 
					    g_renderer.CompileGraphicsPipeline = &vyRenCompileGraphicsPipeline;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
VY_DLLEXPORT void vyRegisterRendererCVars(void) {
 | 
					VY_DLLEXPORT void vyRegisterRendererCVars(void) {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,3 +1,8 @@
 | 
				
			|||||||
 | 
					/* TODO(Kevin):
 | 
				
			||||||
 | 
					 * This should move into a standalone tool.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <assert.h>
 | 
					#include <assert.h>
 | 
				
			||||||
#include <limits.h>
 | 
					#include <limits.h>
 | 
				
			||||||
#include <stdbool.h>
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
				
			|||||||
@ -54,6 +54,8 @@ typedef struct {
 | 
				
			|||||||
    vy_compile_graphics_pipeline_fn *CompileGraphicsPipeline;
 | 
					    vy_compile_graphics_pipeline_fn *CompileGraphicsPipeline;
 | 
				
			||||||
} vy_renderer_api;
 | 
					} vy_renderer_api;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define VY_RENDERER_API_FN(name) VY_DLLEXPORT vyRen##name
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef VY_DONT_DEFINE_RENDERER_GLOBAL
 | 
					#ifndef VY_DONT_DEFINE_RENDERER_GLOBAL
 | 
				
			||||||
extern vy_renderer_api g_renderer;
 | 
					extern vy_renderer_api g_renderer;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -5,7 +5,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <stddef.h>
 | 
					#include <stddef.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef _WIN32
 | 
					#if defined(_WIN32)
 | 
				
			||||||
    #define VY_DLLEXPORT __declspec(dllexport)
 | 
					    #define VY_DLLEXPORT __declspec(dllexport)
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
    #define VY_DLLEXPORT
 | 
					    #define VY_DLLEXPORT
 | 
				
			||||||
@ -14,6 +14,10 @@
 | 
				
			|||||||
#define VY_UNUSED(x)      ((void)sizeof((x)))
 | 
					#define VY_UNUSED(x)      ((void)sizeof((x)))
 | 
				
			||||||
#define VY_ARRAY_COUNT(x) (sizeof((x)) / sizeof((x)[0]))
 | 
					#define VY_ARRAY_COUNT(x) (sizeof((x)) / sizeof((x)[0]))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define VY_KB(n) ((n) * 1024U)
 | 
				
			||||||
 | 
					#define VY_MB(n) ((n) * 1024U * 1024U)
 | 
				
			||||||
 | 
					#define VY_GB(n) ((n) * 1024U * 1024U * 1024U)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef unsigned int vy_result;
 | 
					typedef unsigned int vy_result;
 | 
				
			||||||
#define VY_SUCCESS 0
 | 
					#define VY_SUCCESS 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -4,6 +4,7 @@ extern vy_cvar rt_Renderer;
 | 
				
			|||||||
extern vy_cvar rt_Fullscreen;
 | 
					extern vy_cvar rt_Fullscreen;
 | 
				
			||||||
extern vy_cvar rt_WindowWidth;
 | 
					extern vy_cvar rt_WindowWidth;
 | 
				
			||||||
extern vy_cvar rt_WindowHeight;
 | 
					extern vy_cvar rt_WindowHeight;
 | 
				
			||||||
 | 
					extern vy_cvar rt_BufferManagerMemory;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void __RegisterRuntimeCVars(void)
 | 
					void __RegisterRuntimeCVars(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -11,4 +12,5 @@ void __RegisterRuntimeCVars(void)
 | 
				
			|||||||
    vyRegisterCVAR(&rt_Fullscreen);
 | 
					    vyRegisterCVAR(&rt_Fullscreen);
 | 
				
			||||||
    vyRegisterCVAR(&rt_WindowWidth);
 | 
					    vyRegisterCVAR(&rt_WindowWidth);
 | 
				
			||||||
    vyRegisterCVAR(&rt_WindowHeight);
 | 
					    vyRegisterCVAR(&rt_WindowHeight);
 | 
				
			||||||
 | 
					    vyRegisterCVAR(&rt_BufferManagerMemory);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user