diff --git a/meson.build b/meson.build index e433d07..67da532 100644 --- a/meson.build +++ b/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 = [] diff --git a/scripts/download_dxc.sh b/scripts/download_dxc.sh new file mode 100755 index 0000000..f194bcf --- /dev/null +++ b/scripts/download_dxc.sh @@ -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 diff --git a/src/app_framework/app.c b/src/app_framework/app.c index fb15c37..96df7ef 100644 --- a/src/app_framework/app.c +++ b/src/app_framework/app.c @@ -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; @@ -117,7 +120,7 @@ rtWin32Entry(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int n } } } - + app_callbacks.Shutdown(); rtShutdownMainLoop(); @@ -177,8 +180,8 @@ RT_DLLEXPORT int rtXlibEntry(int argc, char **argv, rt_app_callbacks app_callbac return 1; rtRegisterRendererCVars(); - - if (app_callbacks.RegisterCVars()) + + if (app_callbacks.RegisterCVars) app_callbacks.RegisterCVars(); Display *dpy = XOpenDisplay(NULL); diff --git a/src/asset_compiler/asset_compiler.c b/src/asset_compiler/asset_compiler.c index 0c11bfc..7d41eee 100644 --- a/src/asset_compiler/asset_compiler.c +++ b/src/asset_compiler/asset_compiler.c @@ -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) { diff --git a/src/asset_compiler/dxc_shader_compiler.cpp b/src/asset_compiler/dxc_shader_compiler.cpp index ddbc03d..b93db6f 100644 --- a/src/asset_compiler/dxc_shader_compiler.cpp +++ b/src/asset_compiler/dxc_shader_compiler.cpp @@ -2,17 +2,30 @@ // Required by dxcapi.h, does not work with WIN32_LEAN_AND_MEAN #include #endif +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif #include +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic pop +#endif +#include #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, @@ -147,4 +160,4 @@ extern "C" rt_shader_bytecode CompileVulkanShader(rt_shader_stage stage, compiler->Release(); library->Release(); return bc; -} \ No newline at end of file +} diff --git a/src/asset_compiler/framegraph_processor.c b/src/asset_compiler/framegraph_processor.c index 2d0d044..7b463a1 100644 --- a/src/asset_compiler/framegraph_processor.c +++ b/src/asset_compiler/framegraph_processor.c @@ -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; @@ -661,4 +657,4 @@ RT_ASSET_PROCESSOR_FN(FramegraphProcessor) { out: rtReleaseBuffer(asset.buffer, asset.size); return result; -} \ No newline at end of file +} diff --git a/src/asset_compiler/meson.build b/src/asset_compiler/meson.build index e98b44c..cad27b2 100644 --- a/src/asset_compiler/meson.build +++ b/src/asset_compiler/meson.build @@ -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 diff --git a/src/asset_compiler/pipeline_processor.c b/src/asset_compiler/pipeline_processor.c index d1f134c..2a64222 100644 --- a/src/asset_compiler/pipeline_processor.c +++ b/src/asset_compiler/pipeline_processor.c @@ -448,7 +448,7 @@ RT_ASSET_PROCESSOR_FN(PipelineProcessor) { 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) diff --git a/src/gfx/gfx.h b/src/gfx/gfx.h index ebbe2bc..612c956 100644 --- a/src/gfx/gfx.h +++ b/src/gfx/gfx.h @@ -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 diff --git a/src/gfx/gfx_framegraph.c b/src/gfx/gfx_framegraph.c index 2cb1195..3b55dec 100644 --- a/src/gfx/gfx_framegraph.c +++ b/src/gfx/gfx_framegraph.c @@ -318,7 +318,7 @@ CreateRenderTargets(rt_framegraph *graph, const rt_framegraph_info *info, rt_are graph->render_targets[i].height = render_targets[i].height; graph->render_targets[i].sample_count = render_targets[i].sample_count; graph->render_targets[i].name = NULL; - + const char *name = rtResolveConstRelptr(&render_targets[i].name); if (name) { size_t name_strlen = strlen(name); @@ -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}}, }; } @@ -913,4 +913,4 @@ RT_DLLEXPORT rt_render_pass_id rtCalculateRenderPassID(const char *name, size_t if (id == 0) id = ~id; return id; -} \ No newline at end of file +} diff --git a/src/gfx/gfx_main.c b/src/gfx/gfx_main.c index f49fac1..721fd7d 100644 --- a/src/gfx/gfx_main.c +++ b/src/gfx/gfx_main.c @@ -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 @@ -165,4 +168,4 @@ RT_DLLEXPORT void rtBeginGFXFrame(unsigned int frame_id) { RT_DLLEXPORT void rtEndGFXFrame(unsigned int frame_id) { g_renderer.EndFrame(frame_id); -} \ No newline at end of file +} diff --git a/src/renderer/vk/commands.c b/src/renderer/vk/commands.c index 4d0592f..5873876 100644 --- a/src/renderer/vk/commands.c +++ b/src/renderer/vk/commands.c @@ -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 /* Retrieve the VkCommandBuffer as varname, or return */ #define GET_CMDBUF(varname, handle) \ diff --git a/src/renderer/vk/gpu_sync.c b/src/renderer/vk/gpu_sync.c index c1474dd..b98368d 100644 --- a/src/renderer/vk/gpu_sync.c +++ b/src/renderer/vk/gpu_sync.c @@ -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; @@ -189,4 +189,4 @@ rt_gpu_semaphore_handle RT_RENDERER_API_FN(GetRenderFinishedSemaphore)(void) { .version = 1, .index = RENDER_FINISHED_SEMAPHORE_INDEX, }; -} \ No newline at end of file +} diff --git a/src/renderer/vk/init.c b/src/renderer/vk/init.c index f75c9ba..b5d0cd9 100644 --- a/src/renderer/vk/init.c +++ b/src/renderer/vk/init.c @@ -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 diff --git a/src/renderer/vk/meson.build b/src/renderer/vk/meson.build index 6c8ccc2..e60a368 100644 --- a/src/renderer/vk/meson.build +++ b/src/renderer/vk/meson.build @@ -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) diff --git a/src/renderer/vk/pch/vk_pch.hpp b/src/renderer/vk/pch/vk_pch.hpp new file mode 100644 index 0000000..1f0fb0e --- /dev/null +++ b/src/renderer/vk/pch/vk_pch.hpp @@ -0,0 +1,3 @@ +extern "C" { +#include "vk_pch.h" +} diff --git a/src/renderer/vk/vma_impl.cpp b/src/renderer/vk/vma_impl.cpp index f56068b..40a26d5 100644 --- a/src/renderer/vk/vma_impl.cpp +++ b/src/renderer/vk/vma_impl.cpp @@ -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 -#define VMA_STATIC_VULKAN_FUNCTIONS 0 +#define VMA_STATIC_VULKAN_FUNCTIONS 0 #define VMA_DYNAMIC_VULKAN_FUNCTIONS 0 #define VMA_IMPLEMENTATION #include -#pragma warning(pop) \ No newline at end of file +#ifdef _MSC_VER +#pragma warning(pop) +#elif defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic pop +#endif diff --git a/src/runtime/aio.c b/src/runtime/aio.c index 3b6beb5..d7e86b1 100644 --- a/src/runtime/aio.c +++ b/src/runtime/aio.c @@ -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 @@ -374,4 +374,4 @@ RT_DLLEXPORT rt_aio_state rtSubmitSingleLoadSync(rt_file_load load) { rt_aio_state state = rtWaitForAIOCompletion(handle); rtReleaseAIO(handle); return state; -} \ No newline at end of file +} diff --git a/src/runtime/aio.h b/src/runtime/aio.h index 7b95e53..8fc79fe 100644 --- a/src/runtime/aio.h +++ b/src/runtime/aio.h @@ -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. diff --git a/src/runtime/buffer_manager.c b/src/runtime/buffer_manager.c index 1973841..a31df13 100644 --- a/src/runtime/buffer_manager.c +++ b/src/runtime/buffer_manager.c @@ -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) { diff --git a/src/runtime/error_report.c b/src/runtime/error_report.c index 4e254ff..19d00b9 100644 --- a/src/runtime/error_report.c +++ b/src/runtime/error_report.c @@ -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 @@ -81,4 +83,4 @@ RT_DLLEXPORT void rtLog(const char *subsystem, const char *fmt, ...) { at += rtSPrint(&buf[at], RT_ARRAY_COUNT(buf) - at, "\n"); LogOut(buf); -} \ No newline at end of file +} diff --git a/src/runtime/fsutils.c b/src/runtime/fsutils.c index 9007893..8aeab88 100644 --- a/src/runtime/fsutils.c +++ b/src/runtime/fsutils.c @@ -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) @@ -61,7 +61,7 @@ RT_DLLEXPORT rt_scandir_handle *rtScanDirectory(const char *path) { RT_DLLEXPORT rt_dirent rtNextDirectoryEntry(rt_scandir_handle *dir) { rt_dirent current; memcpy(¤t, &dir->next, sizeof(rt_dirent)); - + WIN32_FIND_DATAW data; if (!FindNextFileW(dir->handle, &data)) { current.is_last = true; @@ -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; } -#endif \ No newline at end of file +#elif defined(__linux__) + +#include +#include +#include +#include + +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 diff --git a/src/runtime/meson.build b/src/runtime/meson.build index 026c2b1..4555b13 100644 --- a/src/runtime/meson.build +++ b/src/runtime/meson.build @@ -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', diff --git a/src/runtime/resource_manager.c b/src/runtime/resource_manager.c index 7cd9f0a..96a1673 100644 --- a/src/runtime/resource_manager.c +++ b/src/runtime/resource_manager.c @@ -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; @@ -1082,11 +1082,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); } } @@ -1152,4 +1152,4 @@ RT_DLLEXPORT void rtSaveResourceNamespace(void) { out: rtUnlockRead(&_namespace.lock); rtReturnTemporaryArena(temp); -} \ No newline at end of file +} diff --git a/src/runtime/rt_math.h b/src/runtime/rt_math.h index 1d0163a..b2668f1 100644 --- a/src/runtime/rt_math.h +++ b/src/runtime/rt_math.h @@ -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 diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h index 23a4c58..933c1dd 100644 --- a/src/runtime/runtime.h +++ b/src/runtime/runtime.h @@ -3,6 +3,7 @@ /* basic types and macros */ +#include #include #include #include @@ -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,20 @@ 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 +#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 +73,7 @@ enum { RT_CUSTOM_ERROR_START, - RT_UNKNOWN_ERROR = (rt_result)-1, + RT_UNKNOWN_ERROR = (rt_result)INT_MAX, }; typedef struct { diff --git a/src/runtime/text.c b/src/runtime/text.c index 372f9a0..966589f 100644 --- a/src/runtime/text.c +++ b/src/runtime/text.c @@ -5,6 +5,9 @@ #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include +#elif defined(__linux__) + +#include #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 -} \ No newline at end of file +} diff --git a/src/runtime/threading_thread.c b/src/runtime/threading_thread.c index d6d5658..cb9cc48 100644 --- a/src/runtime/threading_thread.c +++ b/src/runtime/threading_thread.c @@ -129,8 +129,8 @@ RT_DLLEXPORT void rtSleep(unsigned int milliseconds) { #elif defined(__linux__) -#define _GNU_SOURCE #include +#include #include #if _POSIX_C_SOURCE >= 199309L #include @@ -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) {