Merge branch 'main' of https://libneat.hopto.org/git/kevin/rtengine
This commit is contained in:
		
						commit
						efd1f5f983
					
				
							
								
								
									
										11
									
								
								meson.build
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								meson.build
									
									
									
									
									
								
							@ -16,8 +16,9 @@ buildtype = get_option('buildtype')
 | 
			
		||||
# Build options
 | 
			
		||||
if compiler.get_argument_syntax() == 'gcc'
 | 
			
		||||
  add_project_arguments(
 | 
			
		||||
    ['-Wconversion', '-Wno-sign-conversion',
 | 
			
		||||
      '-Wdouble-promotion', '-Wno-unused-function', '-Wno-unused-parameter'],
 | 
			
		||||
    ['-Wno-sign-conversion',
 | 
			
		||||
      '-Wdouble-promotion', '-Wno-unused-function', '-Wno-unused-parameter',
 | 
			
		||||
      '-fms-extensions'],
 | 
			
		||||
    language : ['c', 'cpp']
 | 
			
		||||
    )
 | 
			
		||||
elif compiler.get_argument_syntax() == 'msvc'
 | 
			
		||||
@ -45,6 +46,11 @@ if buildtype == 'debug' or buildtype == 'debugoptimized'
 | 
			
		||||
  add_project_arguments([ '-DRT_DEBUG'], language : ['c', 'cpp'])
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
# OS Specific flags
 | 
			
		||||
if host_machine.system() == 'linux'
 | 
			
		||||
  add_project_arguments(['-D_GNU_SOURCE'], language : ['c', 'cpp'])
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
fs = import('fs')
 | 
			
		||||
 | 
			
		||||
# Gather dependencies
 | 
			
		||||
@ -64,6 +70,7 @@ copy_util = find_program('scripts/copy_util.py')
 | 
			
		||||
engine_incdir = include_directories('src')
 | 
			
		||||
 | 
			
		||||
contrib_dir = meson.project_source_root() / 'contrib'
 | 
			
		||||
contrib_incdir = include_directories('contrib')
 | 
			
		||||
 | 
			
		||||
# Targets append to this, to enable us to run shared library builds from IDEs
 | 
			
		||||
engine_lib_paths = []
 | 
			
		||||
 | 
			
		||||
@ -1,5 +0,0 @@
 | 
			
		||||
option('static_renderer', type : 'string', value : 'vk', description : 'Name of the renderer used for static builds')
 | 
			
		||||
option('use_xlib', type : 'boolean', value : false, description : 'Use Xlib for window creation under linux')
 | 
			
		||||
option('error_report_debugbreak', type : 'boolean', value : true, description : 'Debugbreak in ReportError')
 | 
			
		||||
option('enable_dxc_shader_compiler', type : 'boolean', value : true, description : 'Enables building the dxc-based shader compiler.')
 | 
			
		||||
option('game_as_subdir', type : 'boolean', value : false, description : 'If true, adds the directory "src/game" to the build.')
 | 
			
		||||
							
								
								
									
										6
									
								
								meson_options.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								meson_options.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
			
		||||
option('static_renderer', type : 'string', value : 'vk', description : 'Name of the renderer used for static builds')
 | 
			
		||||
option('use_xlib', type : 'boolean', value : false, description : 'Use Xlib for window creation under linux')
 | 
			
		||||
option('error_report_debugbreak', type : 'boolean', value : true, description : 'Debugbreak in ReportError')
 | 
			
		||||
option('enable_dxc_shader_compiler', type : 'boolean', value : true, description : 'Enables building the dxc-based shader compiler.')
 | 
			
		||||
option('game_as_subdir', type : 'boolean', value : false, description : 'If true, adds the directory "src/game" to the build.')
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										18
									
								
								scripts/download_dxc.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										18
									
								
								scripts/download_dxc.sh
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,18 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
fOutFile ile="dxc_2023_08_14.zip"
 | 
			
		||||
file="linux_dxc_2023_08_14.x86_64.tar.gz"
 | 
			
		||||
 | 
			
		||||
if [! -d contrib]; then
 | 
			
		||||
    echo "Could not find 'contrib'. Make sure to run this script from the projects root directory."
 | 
			
		||||
    exit 1;
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
mkdir -p contrib/dxc
 | 
			
		||||
wget https://github.com/microsoft/DirectXShaderCompiler/releases/download/v1.7.2308/$file -O contrib/dxc/$file
 | 
			
		||||
tar xzf contrib/dxc/$file -C contrib/dxc
 | 
			
		||||
rm contrib/dxc/$file
 | 
			
		||||
 | 
			
		||||
# Match windows version 
 | 
			
		||||
mv contrib/dxc/include contrib/dxc/inc
 | 
			
		||||
mv contrib/dxc/inc/dxc/*.h contrib/dxc/inc
 | 
			
		||||
rm -r contrib/dxc/inc/dxc
 | 
			
		||||
@ -28,8 +28,11 @@ static LRESULT CALLBACK win32WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RT_DLLEXPORT int
 | 
			
		||||
rtWin32Entry(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow, rt_app_callbacks app_callbacks) {
 | 
			
		||||
RT_DLLEXPORT int rtWin32Entry(HINSTANCE hInstance,
 | 
			
		||||
                              HINSTANCE hPrevInstance,
 | 
			
		||||
                              PWSTR pCmdLine,
 | 
			
		||||
                              int nCmdShow,
 | 
			
		||||
                              rt_app_callbacks app_callbacks) {
 | 
			
		||||
    if (rtInitRuntime() != RT_SUCCESS)
 | 
			
		||||
        return 1;
 | 
			
		||||
 | 
			
		||||
@ -178,7 +181,7 @@ RT_DLLEXPORT int rtXlibEntry(int argc, char **argv, rt_app_callbacks app_callbac
 | 
			
		||||
 | 
			
		||||
    rtRegisterRendererCVars();
 | 
			
		||||
 | 
			
		||||
    if (app_callbacks.RegisterCVars())
 | 
			
		||||
    if (app_callbacks.RegisterCVars)
 | 
			
		||||
        app_callbacks.RegisterCVars();
 | 
			
		||||
 | 
			
		||||
    Display *dpy = XOpenDisplay(NULL);
 | 
			
		||||
 | 
			
		||||
@ -67,14 +67,13 @@ extern RT_ASSET_PROCESSOR_FN(PipelineProcessor);
 | 
			
		||||
extern RT_ASSET_PROCESSOR_FN(FramegraphProcessor);
 | 
			
		||||
 | 
			
		||||
static rt_asset_processor _processors[] = {
 | 
			
		||||
    {.file_ext = ".pipeline", .proc = PipelineProcessor},
 | 
			
		||||
    {  .file_ext = ".pipeline",   .proc = PipelineProcessor},
 | 
			
		||||
    {.file_ext = ".framegraph", .proc = FramegraphProcessor},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void ProcessorThreadEntry(void *);
 | 
			
		||||
static void CompilerThreadEntry(void *);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
RT_DLLEXPORT void rtRegisterAssetCompilerCVars(void) {
 | 
			
		||||
    rtRegisterCVAR(&rt_AssetDirectory);
 | 
			
		||||
    rtRegisterCVAR(&rt_AssetDBSize);
 | 
			
		||||
@ -151,7 +150,6 @@ static int DiscoverAssets(void) {
 | 
			
		||||
#define MAX_DISCOVERY_DEPTH 64
 | 
			
		||||
#define MAX_FILENAME_LEN    260
 | 
			
		||||
    static char directory_stack[MAX_DISCOVERY_DEPTH][MAX_FILENAME_LEN];
 | 
			
		||||
    static unsigned int path_lens[MAX_DISCOVERY_DEPTH];
 | 
			
		||||
    unsigned int top = 0;
 | 
			
		||||
 | 
			
		||||
    memcpy(directory_stack[0],
 | 
			
		||||
@ -213,7 +211,7 @@ static int DiscoverAssets(void) {
 | 
			
		||||
                unsigned int i = 0;
 | 
			
		||||
                rtLockWrite(&_asset_db.lock);
 | 
			
		||||
                while (i < (unsigned int)rt_AssetDBSize.i) {
 | 
			
		||||
                    unsigned int slot = (fid + i) % (unsigned int)rt_AssetDBSize.i;
 | 
			
		||||
                    unsigned int slot = ((unsigned int)fid + i) % (unsigned int)rt_AssetDBSize.i;
 | 
			
		||||
                    if (_asset_db.files[slot] == fid) {
 | 
			
		||||
                        break;
 | 
			
		||||
                    } else if (_asset_db.files[slot] == 0) {
 | 
			
		||||
 | 
			
		||||
@ -2,17 +2,30 @@
 | 
			
		||||
// Required by dxcapi.h, does not work with WIN32_LEAN_AND_MEAN
 | 
			
		||||
#include <Windows.h>
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(__GNUC__) || defined(__clang__)
 | 
			
		||||
#pragma GCC diagnostic push
 | 
			
		||||
#pragma GCC diagnostic ignored "-Wconversion"
 | 
			
		||||
#endif
 | 
			
		||||
#include <dxcapi.h>
 | 
			
		||||
#if defined(__GNUC__) || defined(__clang__)
 | 
			
		||||
#pragma GCC diagnostic pop
 | 
			
		||||
#endif
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
#include "processor.h"
 | 
			
		||||
#include "shader_compiler.h"
 | 
			
		||||
 | 
			
		||||
#ifdef __linux__
 | 
			
		||||
#define WCHAR wchar_t
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
extern "C" rt_shader_bytecode CompileVulkanShader(rt_shader_stage stage,
 | 
			
		||||
                                                  rt_shader_optimization_level optimization,
 | 
			
		||||
                                                  rt_text_span code,
 | 
			
		||||
                                                  const char *file_path,
 | 
			
		||||
                                                  rt_arena *arena) {
 | 
			
		||||
    rt_shader_bytecode bc = {0};
 | 
			
		||||
    rt_shader_bytecode bc;
 | 
			
		||||
    memset(&bc, 0, sizeof(bc));
 | 
			
		||||
 | 
			
		||||
    // NOTE(Kevin): This looks like some sort of autodetect?
 | 
			
		||||
    // Maybe fix this to UTF8?
 | 
			
		||||
@ -22,7 +35,7 @@ extern "C" rt_shader_bytecode CompileVulkanShader(rt_shader_stage stage,
 | 
			
		||||
    // Check if this is what we want.
 | 
			
		||||
    // For example: 6_2 is what allows the usage of 16 bit types
 | 
			
		||||
    LPCWSTR target_profile = nullptr;
 | 
			
		||||
    LPCWSTR entry           = nullptr;
 | 
			
		||||
    LPCWSTR entry          = nullptr;
 | 
			
		||||
    switch (stage) {
 | 
			
		||||
    case RT_SHADER_STAGE_VERTEX:
 | 
			
		||||
        target_profile = L"vs_6_1";
 | 
			
		||||
@ -87,8 +100,8 @@ extern "C" rt_shader_bytecode CompileVulkanShader(rt_shader_stage stage,
 | 
			
		||||
 | 
			
		||||
    // Gather arguments.
 | 
			
		||||
    // TODO(kevin): Maybe add -Qstrip_debug & -Qstrip_reflect?
 | 
			
		||||
    WCHAR wname[MAX_PATH];
 | 
			
		||||
    rtUTF8ToWStr(file_path, wname, MAX_PATH);
 | 
			
		||||
    WCHAR wname[RT_PATH_MAX];
 | 
			
		||||
    rtUTF8ToWStr(file_path, wname, RT_PATH_MAX);
 | 
			
		||||
    // clang-format off
 | 
			
		||||
    LPCWSTR args[] = {
 | 
			
		||||
        wname, 
 | 
			
		||||
 | 
			
		||||
@ -374,9 +374,10 @@ RT_ASSET_PROCESSOR_FN(PipelineProcessor) {
 | 
			
		||||
    for (unsigned int i = 0; i < effect.pass_count; ++i) {
 | 
			
		||||
        rt_parsed_pipeline_data pipeline;
 | 
			
		||||
        memcpy(&pipeline, &effect.pipelines[i], sizeof(pipeline));
 | 
			
		||||
 | 
			
		||||
        rt_resource_id shader_resources[3] = {0};
 | 
			
		||||
        result                             = rtCreateResources(pipeline.shader_count,
 | 
			
		||||
                                   pipeline.shader_names,
 | 
			
		||||
                                   (const char **)pipeline.shader_names,
 | 
			
		||||
                                   pipeline.shaders,
 | 
			
		||||
                                   shader_resources);
 | 
			
		||||
        if (result != RT_SUCCESS)
 | 
			
		||||
 | 
			
		||||
@ -32,7 +32,7 @@ static rt_result ParseFramegraph(const char *text,
 | 
			
		||||
    if (!framegraph)
 | 
			
		||||
        return RT_OUT_OF_MEMORY;
 | 
			
		||||
 | 
			
		||||
#pragma region Render Targets
 | 
			
		||||
    /* ~~~~ Render Targets ~~~~ */
 | 
			
		||||
    const rt_parsed_stmt *rt_list_stmt = rtFindStatement(&state, root_list, "render_targets");
 | 
			
		||||
    if (!rt_list_stmt) {
 | 
			
		||||
        rtLog("AC",
 | 
			
		||||
@ -189,9 +189,8 @@ static rt_result ParseFramegraph(const char *text,
 | 
			
		||||
 | 
			
		||||
        render_targets[i] = rt;
 | 
			
		||||
    }
 | 
			
		||||
#pragma endregion Render Targets
 | 
			
		||||
 | 
			
		||||
#pragma region Render Passes
 | 
			
		||||
    /* ~~~~ Render Passes ~~~~ */
 | 
			
		||||
    /* First count the total number of reads and writes */
 | 
			
		||||
    uint32_t total_reads = 0, total_writes = 0;
 | 
			
		||||
    const rt_parsed_stmt *pass_list_stmt = rtFindStatement(&state, root_list, "passes");
 | 
			
		||||
@ -590,11 +589,9 @@ static rt_result ParseFramegraph(const char *text,
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
#pragma region
 | 
			
		||||
 | 
			
		||||
#pragma region Names
 | 
			
		||||
    /* Fill the render pass names */
 | 
			
		||||
    char *names    = rtArenaPush(arena, framegraph->names_size);
 | 
			
		||||
    /* ~~~~ Names ~~~~ */
 | 
			
		||||
    char *names = rtArenaPush(arena, framegraph->names_size);
 | 
			
		||||
    rtSetRelptr(&framegraph->names, names);
 | 
			
		||||
    char *names_at = names;
 | 
			
		||||
    pass_stmt      = &state.statements[pass_list->first];
 | 
			
		||||
@ -628,7 +625,6 @@ static rt_result ParseFramegraph(const char *text,
 | 
			
		||||
            render_targets[i].name_len = 0;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
#pragma region
 | 
			
		||||
 | 
			
		||||
    *p_framegraph = framegraph;
 | 
			
		||||
    return result;
 | 
			
		||||
 | 
			
		||||
@ -6,7 +6,7 @@ ac_cargs = []
 | 
			
		||||
# DXC for vulkan & directx shaders
 | 
			
		||||
if get_option('enable_dxc_shader_compiler')
 | 
			
		||||
  # We package dxc binaries under contrib/dxc
 | 
			
		||||
  dxc_include = include_directories(meson.project_source_root() / 'contrib' / 'dxc' / 'inc')
 | 
			
		||||
  dxc_include = include_directories('../../contrib/dxc/inc')
 | 
			
		||||
  dxc_libdir = 'NONE'
 | 
			
		||||
  if host_machine.system() == 'windows'
 | 
			
		||||
    dxc_libdir = meson.project_source_root() / 'contrib' / 'dxc' / 'lib' / 'x64'
 | 
			
		||||
@ -16,6 +16,20 @@ if get_option('enable_dxc_shader_compiler')
 | 
			
		||||
      command : [copy_util, '@INPUT@', '@OUTPUT@'],
 | 
			
		||||
      install : false,
 | 
			
		||||
      build_by_default : true)
 | 
			
		||||
  elif host_machine.system() == 'linux'
 | 
			
		||||
    dxc_libdir = meson.project_source_root() / 'contrib' / 'dxc' / 'lib'
 | 
			
		||||
    custom_target('copy libdxcompiler.so',
 | 
			
		||||
      input : meson.project_source_root() / 'contrib' / 'dxc' / 'lib' / 'libdxcompiler.so', 
 | 
			
		||||
      output : 'libdxcompiler.so',
 | 
			
		||||
      command : [copy_util, '@INPUT@', '@OUTPUT@'],
 | 
			
		||||
      install : false,
 | 
			
		||||
      build_by_default : true)
 | 
			
		||||
    custom_target('copy libdxil.so',
 | 
			
		||||
      input : meson.project_source_root() / 'contrib' / 'dxc' / 'lib' / 'libdxil.so', 
 | 
			
		||||
      output : 'libdxil.so',
 | 
			
		||||
      command : [copy_util, '@INPUT@', '@OUTPUT@'],
 | 
			
		||||
      install : false,
 | 
			
		||||
      build_by_default : true)
 | 
			
		||||
  endif
 | 
			
		||||
  dxc_dep = declare_dependency(link_args : ['-L'+dxc_libdir, '-ldxcompiler'], include_directories : dxc_include)
 | 
			
		||||
  ac_deps += dxc_dep
 | 
			
		||||
 | 
			
		||||
@ -17,6 +17,10 @@
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(__GNUC__) || defined(__clang__)
 | 
			
		||||
#pragma GCC diagnostic push
 | 
			
		||||
#pragma GCC diagnostic ignored "-Wpedantic"
 | 
			
		||||
#endif
 | 
			
		||||
typedef union {
 | 
			
		||||
    float v[4];
 | 
			
		||||
    struct {
 | 
			
		||||
@ -26,6 +30,9 @@ typedef union {
 | 
			
		||||
        float a;
 | 
			
		||||
    };
 | 
			
		||||
} rt_color;
 | 
			
		||||
#if defined(__GNUC__) || defined(__clang__)
 | 
			
		||||
#pragma GCC diagnostic pop
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* NOTE(kevin): When you add a value here, you need to handle them in
 | 
			
		||||
 * framegraph_processor.c : ParseFramegraph
 | 
			
		||||
 | 
			
		||||
@ -520,8 +520,8 @@ BeginGraphicsPass(rt_framegraph *framegraph, uint32_t pass_idx, rt_command_buffe
 | 
			
		||||
        rt_render_target *rt = GetRenderTarget(framegraph, writes[0].render_target);
 | 
			
		||||
        RT_ASSERT(rt != NULL, "Invalid render target in pass write.");
 | 
			
		||||
        begin_info.render_area = (rt_rect2i){
 | 
			
		||||
            .offset = {             0,               0},
 | 
			
		||||
            .size   = {.x = rt->width, .y = rt->height}
 | 
			
		||||
            .offset = {{0, 0}},
 | 
			
		||||
            .size   = {{.x = rt->width, .y = rt->height}},
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -15,7 +15,10 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
rt_renderer_api g_renderer;
 | 
			
		||||
 | 
			
		||||
#ifndef RT_STATIC_LIB
 | 
			
		||||
static rt_dynlib _renderer_lib;
 | 
			
		||||
#endif
 | 
			
		||||
static bool _renderer_loaded = false;
 | 
			
		||||
 | 
			
		||||
RT_DLLEXPORT
 | 
			
		||||
 | 
			
		||||
@ -3,9 +3,11 @@
 | 
			
		||||
#include "render_targets.h"
 | 
			
		||||
#include "swapchain.h"
 | 
			
		||||
 | 
			
		||||
#include "gfx/renderer_api.h"
 | 
			
		||||
#include "runtime/handles.h"
 | 
			
		||||
#include "runtime/mem_arena.h"
 | 
			
		||||
#include "gfx/renderer_api.h"
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
/* Retrieve the VkCommandBuffer as varname, or return */
 | 
			
		||||
#define GET_CMDBUF(varname, handle)                                                                \
 | 
			
		||||
 | 
			
		||||
@ -122,7 +122,7 @@ rt_result RT_RENDERER_API_FN(CreateSemaphores)(uint32_t count,
 | 
			
		||||
            sem->current_value[j] = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        p_semaphores[i].version = sem->version;
 | 
			
		||||
        p_semaphores[i].version = (unsigned char)sem->version;
 | 
			
		||||
        p_semaphores[i].index   = (uint32_t)(sem - _semaphores);
 | 
			
		||||
    }
 | 
			
		||||
    return RT_SUCCESS;
 | 
			
		||||
 | 
			
		||||
@ -207,7 +207,7 @@ static rt_result CreateSurface(const rt_renderer_init_info *info) {
 | 
			
		||||
        return RT_SUCCESS;
 | 
			
		||||
    else
 | 
			
		||||
        return 100;
 | 
			
		||||
#elif defined(RT_USE_XLIB_KHR)
 | 
			
		||||
#elif defined(RT_USE_XLIB)
 | 
			
		||||
    g_gpu.native_window.display             = info->display;
 | 
			
		||||
    g_gpu.native_window.window              = info->window;
 | 
			
		||||
    VkXlibSurfaceCreateInfoKHR surface_info = {
 | 
			
		||||
@ -215,7 +215,7 @@ static rt_result CreateSurface(const rt_renderer_init_info *info) {
 | 
			
		||||
        .dpy    = info->display,
 | 
			
		||||
        .window = info->window,
 | 
			
		||||
    };
 | 
			
		||||
    if (vkCreateXlibSurfaceKHR(g_gpu.instance, &surface_info, &g_gpu.alloc_cb, &g_gpu.surface) ==
 | 
			
		||||
    if (vkCreateXlibSurfaceKHR(g_gpu.instance, &surface_info, g_gpu.alloc_cb, &g_gpu.surface) ==
 | 
			
		||||
        VK_SUCCESS)
 | 
			
		||||
        return RT_SUCCESS;
 | 
			
		||||
    else
 | 
			
		||||
 | 
			
		||||
@ -27,16 +27,16 @@ if vk_dep.found()
 | 
			
		||||
    'swapchain.c',
 | 
			
		||||
 | 
			
		||||
    # Contrib Sources
 | 
			
		||||
    contrib_dir / 'volk/volk.h',
 | 
			
		||||
    contrib_dir / 'volk/volk.c',
 | 
			
		||||
    contrib_dir / 'vma/vk_mem_alloc.h',
 | 
			
		||||
    '../../../contrib/volk/volk.h',
 | 
			
		||||
    '../../../contrib/volk/volk.c',
 | 
			
		||||
    '../../../contrib/vma/vk_mem_alloc.h',
 | 
			
		||||
   'vma_impl.cpp',
 | 
			
		||||
    dependencies : [m_dep, vk_inc_dep, windowing_dep],
 | 
			
		||||
    include_directories : [engine_incdir, include_directories(contrib_dir)],
 | 
			
		||||
    include_directories : [engine_incdir, contrib_incdir],
 | 
			
		||||
    link_with : [runtime_lib],
 | 
			
		||||
    c_pch : 'pch/vk_pch.h',
 | 
			
		||||
    c_args : platform_defs,
 | 
			
		||||
    cpp_pch : 'pch/vk_pch.h',
 | 
			
		||||
    cpp_pch : 'pch/vk_pch.hpp',
 | 
			
		||||
    cpp_args : platform_defs,
 | 
			
		||||
    install : true)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										3
									
								
								src/renderer/vk/pch/vk_pch.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/renderer/vk/pch/vk_pch.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
			
		||||
extern "C" {
 | 
			
		||||
#include "vk_pch.h"
 | 
			
		||||
}
 | 
			
		||||
@ -1,7 +1,21 @@
 | 
			
		||||
#ifdef _MSC_VER
 | 
			
		||||
#pragma warning(push, 0)
 | 
			
		||||
#elif defined(__GNUC__) || defined(__clang__)
 | 
			
		||||
#pragma GCC diagnostic push
 | 
			
		||||
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
 | 
			
		||||
#pragma GCC diagnostic ignored "-Wmissing-braces"
 | 
			
		||||
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
 | 
			
		||||
#pragma GCC diagnostic ignored "-Wconversion"
 | 
			
		||||
#pragma GCC diagnostic ignored "-Wunused-variable"
 | 
			
		||||
#pragma GCC diagnostic ignored "-Wparentheses"
 | 
			
		||||
#endif
 | 
			
		||||
#include <volk/volk.h>
 | 
			
		||||
#define VMA_STATIC_VULKAN_FUNCTIONS 0
 | 
			
		||||
#define VMA_STATIC_VULKAN_FUNCTIONS  0
 | 
			
		||||
#define VMA_DYNAMIC_VULKAN_FUNCTIONS 0
 | 
			
		||||
#define VMA_IMPLEMENTATION
 | 
			
		||||
#include <vma/vk_mem_alloc.h>
 | 
			
		||||
#ifdef _MSC_VER
 | 
			
		||||
#pragma warning(pop)
 | 
			
		||||
#elif defined(__GNUC__) || defined(__clang__)
 | 
			
		||||
#pragma GCC diagnostic pop
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@ -313,7 +313,7 @@ RT_DLLEXPORT rt_result rtSubmitWriteBatch(const rt_write_batch *batch, rt_aio_ha
 | 
			
		||||
    return RT_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RT_DLLEXPORT volatile rt_aio_state rtGetAIOState(rt_aio_handle handle) {
 | 
			
		||||
RT_DLLEXPORT rt_aio_state rtGetAIOState(rt_aio_handle handle) {
 | 
			
		||||
    if (handle == RT_AIO_INVALID_HANDLE || handle > _ringbuffer.capacity)
 | 
			
		||||
        return RT_AIO_STATE_INVALID;
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
 | 
			
		||||
@ -73,14 +73,13 @@ typedef enum {
 | 
			
		||||
    RT_AIO_STATE_FAILED,
 | 
			
		||||
} rt_aio_state;
 | 
			
		||||
 | 
			
		||||
RT_DLLEXPORT volatile rt_aio_state rtGetAIOState(rt_aio_handle handle);
 | 
			
		||||
RT_DLLEXPORT rt_aio_state rtGetAIOState(rt_aio_handle handle);
 | 
			
		||||
 | 
			
		||||
/* Blocks until the given operation is no longer pending.
 | 
			
		||||
 * Returns the state that caused the wait to end. The handle is still valid after this function
 | 
			
		||||
 * returned. */
 | 
			
		||||
RT_DLLEXPORT rt_aio_state rtWaitForAIOCompletion(rt_aio_handle handle);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
RT_DLLEXPORT rt_result rtSubmitLoadBatch(const rt_load_batch *batch, rt_aio_handle *handles);
 | 
			
		||||
 | 
			
		||||
/* Releases the internal storage for the operation.
 | 
			
		||||
 | 
			
		||||
@ -78,7 +78,7 @@ extern rt_result InitBufferManager(void) {
 | 
			
		||||
    if (!_memory) {
 | 
			
		||||
        return RT_OUT_OF_MEMORY;
 | 
			
		||||
    }
 | 
			
		||||
    _bitmap = (uint32_t*)(_memory + budget);
 | 
			
		||||
    _bitmap = (uint32_t *)(_memory + budget);
 | 
			
		||||
    memset(_bitmap, 0, sizeof(uint32_t) * dword_count);
 | 
			
		||||
 | 
			
		||||
    return RT_SUCCESS;
 | 
			
		||||
@ -94,23 +94,19 @@ RT_DLLEXPORT void *rtAllocBuffer(size_t size) {
 | 
			
		||||
    size_t alloc_blocks = (size + BLOCK_SIZE - 1) / BLOCK_SIZE;
 | 
			
		||||
    size_t dword_count  = (_block_count + 31) / 32;
 | 
			
		||||
    void *result        = NULL;
 | 
			
		||||
    size_t first_block  = 0;
 | 
			
		||||
    rtLockMutex(_guard);
 | 
			
		||||
    for (size_t i = 0; i < _block_count; ++i) {
 | 
			
		||||
        size_t dword = i / 32;
 | 
			
		||||
        if (_bitmap[dword] == 0 || tzcnt32(_bitmap[dword]) >= alloc_blocks) {
 | 
			
		||||
        if (_bitmap[dword] == 0 || (size_t)tzcnt32(_bitmap[dword]) >= alloc_blocks) {
 | 
			
		||||
            size_t mask = (1ull << alloc_blocks) - 1;
 | 
			
		||||
            _bitmap[dword] |= mask;
 | 
			
		||||
            result      = _memory + i * BLOCK_SIZE;
 | 
			
		||||
            first_block = i;
 | 
			
		||||
            _bitmap[dword] |= (uint32_t)mask;
 | 
			
		||||
            result = _memory + i * BLOCK_SIZE;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        else if (lzcnt32(_bitmap[dword]) >= alloc_blocks) {
 | 
			
		||||
        } else if ((size_t)lzcnt32(_bitmap[dword]) >= alloc_blocks) {
 | 
			
		||||
            size_t first = (_bitmap[dword] != 0) ? 32 - lzcnt32(_bitmap[dword]) : 0;
 | 
			
		||||
            size_t mask  = ((1ull << alloc_blocks) - 1) << first;
 | 
			
		||||
            _bitmap[dword] |= mask;
 | 
			
		||||
            result      = _memory + (i + first) * BLOCK_SIZE;
 | 
			
		||||
            first_block = i + first;
 | 
			
		||||
            _bitmap[dword] |= (uint32_t)mask;
 | 
			
		||||
            result = _memory + (i + first) * BLOCK_SIZE;
 | 
			
		||||
            break;
 | 
			
		||||
        } else if (_bitmap[dword] != UINT32_MAX) {
 | 
			
		||||
            size_t first    = 32 - lzcnt32(_bitmap[dword]);
 | 
			
		||||
@ -124,9 +120,8 @@ RT_DLLEXPORT void *rtAllocBuffer(size_t size) {
 | 
			
		||||
                    continue;
 | 
			
		||||
                _bitmap[dword] = UINT32_MAX;
 | 
			
		||||
                size_t mask    = (1ull << leftover) - 1;
 | 
			
		||||
                _bitmap[dword + 1] |= mask;
 | 
			
		||||
                result      = _memory + (i + first) * BLOCK_SIZE;
 | 
			
		||||
                first_block = i + first;
 | 
			
		||||
                _bitmap[dword + 1] |= (uint32_t)mask;
 | 
			
		||||
                result = _memory + (i + first) * BLOCK_SIZE;
 | 
			
		||||
                break;
 | 
			
		||||
            } else {
 | 
			
		||||
                // Check each bit separately
 | 
			
		||||
@ -145,8 +140,7 @@ RT_DLLEXPORT void *rtAllocBuffer(size_t size) {
 | 
			
		||||
                        size_t bitj   = j % 32;
 | 
			
		||||
                        _bitmap[dwordj] |= (1u << bitj);
 | 
			
		||||
                    }
 | 
			
		||||
                    result      = _memory + (i + first) * BLOCK_SIZE;
 | 
			
		||||
                    first_block = i + first;
 | 
			
		||||
                    result = _memory + (i + first) * BLOCK_SIZE;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
@ -161,8 +155,8 @@ RT_DLLEXPORT void *rtAllocBuffer(size_t size) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RT_DLLEXPORT void rtReleaseBuffer(const void *begin, size_t size) {
 | 
			
		||||
    size_t alloc_blocks = (size + BLOCK_SIZE - 1) / BLOCK_SIZE;
 | 
			
		||||
    uintptr_t off       = (uintptr_t)begin - (uintptr_t)_memory;
 | 
			
		||||
    size_t alloc_blocks   = (size + BLOCK_SIZE - 1) / BLOCK_SIZE;
 | 
			
		||||
    uintptr_t off         = (uintptr_t)begin - (uintptr_t)_memory;
 | 
			
		||||
    uintptr_t first_block = off / BLOCK_SIZE;
 | 
			
		||||
    rtLockMutex(_guard);
 | 
			
		||||
    for (size_t i = first_block; i < first_block + alloc_blocks; ++i) {
 | 
			
		||||
 | 
			
		||||
@ -18,6 +18,7 @@
 | 
			
		||||
 | 
			
		||||
/* TODO(Kevin): Log to file, show error message box, ... */
 | 
			
		||||
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
void Win32ErrorToString(DWORD last_error, char *out, int bufsize) {
 | 
			
		||||
    FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
 | 
			
		||||
                       FORMAT_MESSAGE_ARGUMENT_ARRAY | FORMAT_MESSAGE_ALLOCATE_BUFFER,
 | 
			
		||||
@ -28,6 +29,7 @@ void Win32ErrorToString(DWORD last_error, char *out, int bufsize) {
 | 
			
		||||
                   bufsize,
 | 
			
		||||
                   NULL);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static bool DisplayErrorBox(const char *text) {
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
 | 
			
		||||
@ -14,7 +14,7 @@ struct rt_scandir_handle_s {
 | 
			
		||||
 | 
			
		||||
static rt_scandir_handle _dirs[256];
 | 
			
		||||
static unsigned int _next = 0;
 | 
			
		||||
static rt_mutex *_guard = NULL;
 | 
			
		||||
static rt_mutex *_guard   = NULL;
 | 
			
		||||
 | 
			
		||||
RT_DLLEXPORT rt_scandir_handle *rtScanDirectory(const char *path) {
 | 
			
		||||
    char wildcard_path[MAX_PATH];
 | 
			
		||||
@ -38,7 +38,7 @@ RT_DLLEXPORT rt_scandir_handle *rtScanDirectory(const char *path) {
 | 
			
		||||
 | 
			
		||||
    rtLockMutex(_guard);
 | 
			
		||||
    rt_scandir_handle *dir = &_dirs[_next];
 | 
			
		||||
    _next                   = (_next + 1) % RT_ARRAY_COUNT(_dirs);
 | 
			
		||||
    _next                  = (_next + 1) % RT_ARRAY_COUNT(_dirs);
 | 
			
		||||
    rtUnlockMutex(_guard);
 | 
			
		||||
 | 
			
		||||
    if (dir->handle != NULL) {
 | 
			
		||||
@ -47,7 +47,7 @@ RT_DLLEXPORT rt_scandir_handle *rtScanDirectory(const char *path) {
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    dir->handle = h;
 | 
			
		||||
    dir->handle       = h;
 | 
			
		||||
    dir->next.is_last = false;
 | 
			
		||||
    rtWStrToUTF8(data.cFileName, dir->next.name, 260);
 | 
			
		||||
    if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
 | 
			
		||||
@ -73,7 +73,6 @@ RT_DLLEXPORT rt_dirent rtNextDirectoryEntry(rt_scandir_handle *dir) {
 | 
			
		||||
    else
 | 
			
		||||
        dir->next.type = RT_DIRENT_TYPE_FILE;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    return current;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -118,4 +117,108 @@ uint64_t rtGetFileModificationTimestamp(const char *path) {
 | 
			
		||||
    return ts;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#elif defined(__linux__)
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <sys/dir.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <time.h>
 | 
			
		||||
 | 
			
		||||
struct rt_scandir_handle_s {
 | 
			
		||||
    DIR *handle;
 | 
			
		||||
    rt_dirent next;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static rt_scandir_handle _dirs[256];
 | 
			
		||||
static unsigned int _next = 0;
 | 
			
		||||
static rt_mutex *_guard   = NULL;
 | 
			
		||||
 | 
			
		||||
RT_DLLEXPORT rt_scandir_handle *rtScanDirectory(const char *path) {
 | 
			
		||||
    DIR *h = opendir(path);
 | 
			
		||||
    if (!h)
 | 
			
		||||
        return NULL;
 | 
			
		||||
 | 
			
		||||
    if (!_guard) {
 | 
			
		||||
        _guard = rtCreateMutex();
 | 
			
		||||
        if (!_guard) {
 | 
			
		||||
            closedir(h);
 | 
			
		||||
            return NULL;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    rtLockMutex(_guard);
 | 
			
		||||
    rt_scandir_handle *dir = &_dirs[_next];
 | 
			
		||||
    _next                  = (_next + 1) % RT_ARRAY_COUNT(_dirs);
 | 
			
		||||
    rtUnlockMutex(_guard);
 | 
			
		||||
 | 
			
		||||
    if (dir->handle != NULL) {
 | 
			
		||||
        rtLog("core", "Failed to acquire a scandir handle.");
 | 
			
		||||
        closedir(h);
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    struct dirent *ent = readdir(h);
 | 
			
		||||
    if (!ent) {
 | 
			
		||||
        closedir(h);
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
    dir->handle       = h;
 | 
			
		||||
    dir->next.is_last = false;
 | 
			
		||||
    memcpy(dir->next.name, ent->d_name, 255);
 | 
			
		||||
    if (ent->d_type == DT_DIR)
 | 
			
		||||
        dir->next.type = RT_DIRENT_TYPE_DIRECTORY;
 | 
			
		||||
    else
 | 
			
		||||
        dir->next.type = RT_DIRENT_TYPE_FILE;
 | 
			
		||||
 | 
			
		||||
    return dir;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RT_DLLEXPORT rt_dirent rtNextDirectoryEntry(rt_scandir_handle *dir) {
 | 
			
		||||
    rt_dirent current;
 | 
			
		||||
    memcpy(¤t, &dir->next, sizeof(rt_dirent));
 | 
			
		||||
 | 
			
		||||
    struct dirent *ent = readdir(dir->handle);
 | 
			
		||||
    if (!ent) {
 | 
			
		||||
        current.is_last = true;
 | 
			
		||||
        return current;
 | 
			
		||||
    }
 | 
			
		||||
    memcpy(dir->next.name, ent->d_name, 255);
 | 
			
		||||
    if (ent->d_type == DT_DIR)
 | 
			
		||||
        dir->next.type = RT_DIRENT_TYPE_DIRECTORY;
 | 
			
		||||
    else
 | 
			
		||||
        dir->next.type = RT_DIRENT_TYPE_FILE;
 | 
			
		||||
    return current;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RT_DLLEXPORT void rtCloseDirectory(rt_scandir_handle *dir) {
 | 
			
		||||
    if (!dir)
 | 
			
		||||
        return;
 | 
			
		||||
    closedir(dir->handle);
 | 
			
		||||
    dir->handle = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RT_DLLEXPORT bool rtCreateDirectory(const char *path) {
 | 
			
		||||
    return mkdir(path, S_IRWXU | S_IRGRP) == 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RT_DLLEXPORT size_t rtGetFileSize(const char *path) {
 | 
			
		||||
    struct stat st;
 | 
			
		||||
    if (stat(path, &st) != 0)
 | 
			
		||||
        return 0;
 | 
			
		||||
    return (size_t)st.st_size;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint64_t rtGetCurrentTimestamp(void) {
 | 
			
		||||
    struct timespec ts;
 | 
			
		||||
    clock_gettime(CLOCK_REALTIME, &ts);
 | 
			
		||||
    return (uint64_t)ts.tv_sec;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint64_t rtGetFileModificationTimestamp(const char *path) {
 | 
			
		||||
    struct stat st;
 | 
			
		||||
    if (stat(path, &st) != 0)
 | 
			
		||||
        return 0;
 | 
			
		||||
    return (uint64_t)st.st_mtim.tv_sec;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
# Runtime 
 | 
			
		||||
runtime_deps = [thread_dep, m_dep, windowing_dep]
 | 
			
		||||
runtime_incdirs = include_directories(meson.project_source_root() / 'contrib')
 | 
			
		||||
runtime_incdirs = contrib_incdir
 | 
			
		||||
runtime_lib = library('rt',
 | 
			
		||||
  # Project Sources
 | 
			
		||||
  'aio.h',
 | 
			
		||||
 | 
			
		||||
@ -179,14 +179,14 @@ static void CopyResourceData(const rt_resource *resource, void *dest) {
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        char *names_begin = (char *)read_write_dest;
 | 
			
		||||
        char *names_begin     = (char *)read_write_dest;
 | 
			
		||||
        const char *src_names = rtResolveConstRelptr(&info->names);
 | 
			
		||||
        memcpy(names_begin, src_names, info->names_size);
 | 
			
		||||
        rtSetRelptr(&dest_info->names, names_begin);
 | 
			
		||||
        dest_info->names_size = info->names_size;
 | 
			
		||||
 | 
			
		||||
        const rt_render_target_info *src_rts = rtResolveConstRelptr(&info->render_targets);
 | 
			
		||||
        rt_render_target_info *rts = (rt_render_target_info *)(dest_info + 1);
 | 
			
		||||
        rt_render_target_info *rts           = (rt_render_target_info *)(dest_info + 1);
 | 
			
		||||
        for (uint32_t i = 0; i < info->render_target_count; ++i) {
 | 
			
		||||
            const char *src_name = rtResolveConstRelptr(&src_rts[i].name);
 | 
			
		||||
            if (src_name)
 | 
			
		||||
@ -277,7 +277,7 @@ static rt_result InitResourceCache(void) {
 | 
			
		||||
    _cache.resource_lock = resource_lock_create.lock;
 | 
			
		||||
 | 
			
		||||
    for (int i = 0; i < count; ++i) {
 | 
			
		||||
        _cache.resources[i].next_free = (i < count - 1) ? i + 1 : UINT_MAX;
 | 
			
		||||
        _cache.resources[i].next_free = (i < count - 1) ? (unsigned int)i + 1 : UINT_MAX;
 | 
			
		||||
    }
 | 
			
		||||
    _cache.first_free = 0;
 | 
			
		||||
 | 
			
		||||
@ -1046,11 +1046,11 @@ RT_DLLEXPORT void rDebugLogResource(rt_resource_id id, const rt_resource *resour
 | 
			
		||||
                      (writes[j].flags & RT_RENDER_TARGET_WRITE_DISCARD) ? "YES" : "NO");
 | 
			
		||||
                rtLog("RESMGR",
 | 
			
		||||
                      "          clear_value: {rgba: {%f %f %f %f}, ds: {%f %u}}",
 | 
			
		||||
                      writes[j].clear.color.r,
 | 
			
		||||
                      writes[j].clear.color.g,
 | 
			
		||||
                      writes[j].clear.color.b,
 | 
			
		||||
                      writes[j].clear.color.a,
 | 
			
		||||
                      writes[j].clear.depth_stencil.depth,
 | 
			
		||||
                      (double)writes[j].clear.color.r,
 | 
			
		||||
                      (double)writes[j].clear.color.g,
 | 
			
		||||
                      (double)writes[j].clear.color.b,
 | 
			
		||||
                      (double)writes[j].clear.color.a,
 | 
			
		||||
                      (double)writes[j].clear.depth_stencil.depth,
 | 
			
		||||
                      writes[j].clear.depth_stencil.stencil);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -2,6 +2,17 @@
 | 
			
		||||
#define RT_MATH_H
 | 
			
		||||
 | 
			
		||||
/* Math types and functions */
 | 
			
		||||
#if defined(__GNUC__) || defined(__clang__)
 | 
			
		||||
#pragma GCC diagnostic push
 | 
			
		||||
#pragma GCC diagnostic ignored "-Wpedantic"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
struct vec2 {
 | 
			
		||||
    struct xy {
 | 
			
		||||
        float x;
 | 
			
		||||
        float y;
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* 2d vector */
 | 
			
		||||
typedef union {
 | 
			
		||||
@ -30,4 +41,9 @@ typedef struct {
 | 
			
		||||
    rt_v2i offset;
 | 
			
		||||
    rt_v2i size;
 | 
			
		||||
} rt_rect2i;
 | 
			
		||||
 | 
			
		||||
#if defined(__GNUC__) || defined(__clang__)
 | 
			
		||||
#pragma GCC diagnostic pop
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@ -3,6 +3,7 @@
 | 
			
		||||
 | 
			
		||||
/* basic types and macros */
 | 
			
		||||
 | 
			
		||||
#include <limits.h>
 | 
			
		||||
#include <stdarg.h>
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
@ -28,12 +29,14 @@ extern "C" {
 | 
			
		||||
#define RT_UNUSED(x)      ((void)sizeof((x)))
 | 
			
		||||
#define RT_ARRAY_COUNT(x) (sizeof((x)) / sizeof((x)[0]))
 | 
			
		||||
 | 
			
		||||
#define RT_RESTRICT_VALUE_TO_BOUNDS(v, lower, upper) (((v) < (lower)) ? (lower) : (((v) > (upper)) ? (upper) : (v)))
 | 
			
		||||
#define RT_RESTRICT_VALUE_TO_BOUNDS(v, lower, upper)                                               \
 | 
			
		||||
    (((v) < (lower)) ? (lower) : (((v) > (upper)) ? (upper) : (v)))
 | 
			
		||||
 | 
			
		||||
#define RT_KB(n) ((n)*1024U)
 | 
			
		||||
#define RT_MB(n) ((n)*1024U * 1024U)
 | 
			
		||||
#define RT_GB(n) ((n)*1024U * 1024U * 1024U)
 | 
			
		||||
 | 
			
		||||
#ifndef __cplusplus
 | 
			
		||||
#if defined(_MSC_VER)
 | 
			
		||||
/* For some reason _Thread_local does not work with vs2022,
 | 
			
		||||
 * despite MS documentation claiming it should. */
 | 
			
		||||
@ -45,9 +48,22 @@ extern "C" {
 | 
			
		||||
#elif __STDC_VERSION__ >= 201112L
 | 
			
		||||
#define RT_THREAD_LOCAL _Thread_local
 | 
			
		||||
#else
 | 
			
		||||
#pragma error Pre-C11 not supported.
 | 
			
		||||
#error Versions older than C11 not supported.
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
#else
 | 
			
		||||
// C++ 11 supports thread_local
 | 
			
		||||
#if __cplusplus >= 201103L
 | 
			
		||||
#define RT_THREAD_LOCAL thread_local
 | 
			
		||||
#elif defined(_MSC_VER)
 | 
			
		||||
#define RT_THREAD_LOCAL __declspec(thread)
 | 
			
		||||
#else
 | 
			
		||||
#error Versions older than C++11 not supported.
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Matches windows MAX_PATH */
 | 
			
		||||
#define RT_PATH_MAX 260
 | 
			
		||||
 | 
			
		||||
typedef unsigned int rt_result;
 | 
			
		||||
 | 
			
		||||
@ -59,7 +75,7 @@ enum {
 | 
			
		||||
 | 
			
		||||
    RT_CUSTOM_ERROR_START,
 | 
			
		||||
 | 
			
		||||
    RT_UNKNOWN_ERROR = (rt_result)-1,
 | 
			
		||||
    RT_UNKNOWN_ERROR = (rt_result)INT_MAX,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
 | 
			
		||||
@ -5,6 +5,9 @@
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
#define WIN32_LEAN_AND_MEAN
 | 
			
		||||
#include <Windows.h>
 | 
			
		||||
#elif defined(__linux__)
 | 
			
		||||
 | 
			
		||||
#include <uchar.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
RT_DLLEXPORT int rtCompareSpanToString(rt_text_span span, const char *cmp) {
 | 
			
		||||
@ -18,6 +21,9 @@ RT_DLLEXPORT int rtCompareSpanToString(rt_text_span span, const char *cmp) {
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* These should not be necessary on linux. If we ever run into this problem,
 | 
			
		||||
 * they could be implemented pretty easily. */
 | 
			
		||||
 | 
			
		||||
RT_DLLEXPORT rt_result rtUTF8ToWStr(const char *utf8, wchar_t *wstr, size_t len) {
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
    int res = MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, utf8, -1, wstr, (int)len);
 | 
			
		||||
@ -34,10 +40,11 @@ RT_DLLEXPORT rt_result rtUTF8ToWStr(const char *utf8, wchar_t *wstr, size_t len)
 | 
			
		||||
            return RT_UNKNOWN_ERROR;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
#elif defined(__linux__)
 | 
			
		||||
    return RT_UNKNOWN_ERROR;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
RT_DLLEXPORT rt_result rtWStrToUTF8(const wchar_t *wstr, char *utf8, size_t len) {
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
    int res = WideCharToMultiByte(CP_UTF8, WC_COMPOSITECHECK, wstr, -1, utf8, (int)len, NULL, NULL);
 | 
			
		||||
@ -54,5 +61,7 @@ RT_DLLEXPORT rt_result rtWStrToUTF8(const wchar_t *wstr, char *utf8, size_t len)
 | 
			
		||||
            return RT_UNKNOWN_ERROR;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
#elif defined(__linux__)
 | 
			
		||||
    return RT_UNKNOWN_ERROR;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
@ -129,8 +129,8 @@ RT_DLLEXPORT void rtSleep(unsigned int milliseconds) {
 | 
			
		||||
 | 
			
		||||
#elif defined(__linux__)
 | 
			
		||||
 | 
			
		||||
#define _GNU_SOURCE
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#if _POSIX_C_SOURCE >= 199309L
 | 
			
		||||
#include <time.h>
 | 
			
		||||
@ -151,8 +151,14 @@ static rt_thread _threads[MAX_THREADS];
 | 
			
		||||
static ptrdiff_t _first_reusable = MAX_THREADS;
 | 
			
		||||
static ptrdiff_t _next           = 0;
 | 
			
		||||
 | 
			
		||||
static rt_thread_id _main_thread_id;
 | 
			
		||||
 | 
			
		||||
static pthread_mutex_t _guard = PTHREAD_MUTEX_INITIALIZER;
 | 
			
		||||
 | 
			
		||||
extern void SetMainThreadId(void) {
 | 
			
		||||
    _main_thread_id = (rt_thread_id)gettid();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void *linuxThreadWrapper(void *arg) {
 | 
			
		||||
    rt_thread *user_thread  = arg;
 | 
			
		||||
    user_thread->needs_join = false;
 | 
			
		||||
@ -208,7 +214,7 @@ RT_DLLEXPORT unsigned int rtGetCPUCoreCount(void) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RT_DLLEXPORT rt_thread_id rtGetCurrentThreadId(void) {
 | 
			
		||||
    return (rt_thread_id)GetCurrentThreadId();
 | 
			
		||||
    return (rt_thread_id)gettid();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RT_DLLEXPORT bool rtIsMainThread(void) {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user