From 6126144f7c1c6f7ef4b8c8a4ca6f72099231ed05 Mon Sep 17 00:00:00 2001 From: Matthew Date: Fri, 12 Jun 2026 13:57:09 +1000 Subject: [PATCH] add sdl vulkan support, dub broken --- dlib/dlibincludes.c | 5 ++ dlib/platform.d | 4 +- dub.json | 9 ++- vulkan/vulkan.d | 174 +++++++++++++++++++++++++++++++------------- 4 files changed, 137 insertions(+), 55 deletions(-) diff --git a/dlib/dlibincludes.c b/dlib/dlibincludes.c index 2f5ab87..0b3aa3b 100644 --- a/dlib/dlibincludes.c +++ b/dlib/dlibincludes.c @@ -44,6 +44,11 @@ #ifndef BUILD_WASM # include + +# ifdef BUILD_VULKAN +# include +# endif + #endif #ifdef BUILD_GL diff --git a/dlib/platform.d b/dlib/platform.d index 7541d6a..170a35b 100644 --- a/dlib/platform.d +++ b/dlib/platform.d @@ -1945,10 +1945,10 @@ version(DLIB_TEST) unittest u8[] data_valid, data_test; - File f = File("dlib/platform.d", "rb"); + File f = File("../dlib/platform.d", "rb"); data_valid = f.rawRead(new u8[f.size()]); - data_test = LoadFile(&arena, "dlib/platform.d"); + data_test = LoadFile(&arena, "../dlib/platform.d"); assert(data_valid == data_test); } diff --git a/dub.json b/dub.json index 91ecaf0..bb48a89 100644 --- a/dub.json +++ b/dub.json @@ -6,8 +6,8 @@ { "name": "core", "targetType": "sourceLibrary", - "sourcePaths": ["dlib"], - "importPaths": ["dlib"], + "sourcePaths": ["dlib", "vulkan", "opengl"], + "importPaths": ["dlib", "vulkan", "opengl"], "sourceFiles-linux": ["build/libstb.a"], "sourceFiles-windows": [], "libs-linux": [ @@ -27,6 +27,9 @@ "--Xcc=-DBUILD_WASM", "-gcc=clang" ], + "dflags": ["-v"], + "dflags-ldc": ["--Xcc=-DBUILD_VULKAN"], + "dlfags-dmd": ["-Xcc=-DBUILD_VULKAN"], "libs-windows": [], "preGenerateCommands-linux": ["./build.sh"], "buildTypes": { @@ -45,8 +48,6 @@ "sourceFiles-linux": ["build/libvma.a"], "sourceFiles-windows": [], "stringImportPaths": ["build"], - "dflags-ldc": ["--Xcc=-DBUILD_VULKAN"], - "dflags-dmd": ["-Xcc=-DBUILD_VULKAN"], "libs-linux": [ "vulkan", "stdc++" diff --git a/vulkan/vulkan.d b/vulkan/vulkan.d index e3be259..588c5ec 100644 --- a/vulkan/vulkan.d +++ b/vulkan/vulkan.d @@ -9,11 +9,11 @@ import vulkan_funcs; import std.stdio; import std.algorithm.comparison; import std.algorithm.searching : canFind; -import std.traits : isPointer, isArray; -import core.stdc.string : strcmp, memcpy, strlen; -import core.stdc.stdio : Printf = printf; -import std.format : sformat; -import std.math.rounding : Ceil = ceil; +import std.traits : isPointer, isArray; +import core.stdc.string : strcmp, memcpy, strlen; +import core.stdc.stdio : Printf = printf; +import std.format : sformat; +import std.math.rounding : Ceil = ceil; version(VULKAN_DEBUG) { @@ -68,6 +68,8 @@ version(Windows) struct PlatformHandles { + bool sdl; + SDL_Window* sdl_window; version(linux) { Display* display; @@ -80,18 +82,18 @@ struct PlatformHandles } } -const char*[] VK_INSTANCE_LAYERS = []; +const char*[] VK_INSTANCE_LAYERS = []; const char*[] VK_INSTANCE_LAYERS_DEBUG = [ "VK_LAYER_KHRONOS_validation" ]; version(linux) { - const char*[] VK_INSTANCE_EXT = [ cast(char*)VK_KHR_SURFACE_EXTENSION_NAME, cast(char*)VK_KHR_XLIB_SURFACE_EXTENSION_NAME ]; + const char*[] VK_INSTANCE_EXT = [ cast(char*)VK_KHR_SURFACE_EXTENSION_NAME, cast(char*)VK_KHR_XLIB_SURFACE_EXTENSION_NAME ]; const char*[] VK_INSTANCE_EXT_DEBUG = VK_INSTANCE_EXT ~ [ cast(char*)VK_EXT_DEBUG_UTILS_EXTENSION_NAME ]; } version(Windows) { - const char*[] VK_INSTANCE_EXT = [ cast(char*)VK_KHR_SURFACE_EXTENSION_NAME, cast(char*)VK_KHR_WIN32_SURFACE_EXTENSION_NAME ]; + const char*[] VK_INSTANCE_EXT = [ cast(char*)VK_KHR_SURFACE_EXTENSION_NAME, cast(char*)VK_KHR_WIN32_SURFACE_EXTENSION_NAME ]; const char*[] VK_INSTANCE_EXT_DEBUG = VK_INSTANCE_EXT ~ [ cast(char*)VK_EXT_DEBUG_UTILS_EXTENSION_NAME ]; } @@ -828,6 +830,8 @@ BeginFrame() result = vkResetFences(g_vk.device, 1, g_vk.render_fence_ptr); VkCheckA("BeginFrame failure: vkResetFences error", result); + + Reset(g_vk.FrameArena()); // ?? dont know why this is 3 (should have commented it) for(u64 i = 0; i < 3; i += 1) @@ -2715,8 +2719,15 @@ SetStencilOp(StencilFace face, StencilOp fail_op, StencilOp pass_op, StencilOp d vkCmdSetStencilOp(g_vk.cmd, face, fail_op, pass_op, depth_fail_op, cmp_op); } +struct VulkanBuildInfo +{ + PlatformHandles platform_handles; + string application_name; + string engine_name; +} + void -Init(PlatformHandles platform_handles, u64 permanent_mem, u64 frame_mem) +Init(VulkanBuildInfo build_info, u64 permanent_mem, u64 frame_mem) { bool success; @@ -2726,11 +2737,13 @@ Init(PlatformHandles platform_handles, u64 permanent_mem, u64 frame_mem) CreateArena(frame_mem), CreateArena(frame_mem), ], - platform_handles: platform_handles, + platform_handles: build_info.platform_handles, }; g_vk = vk; + Arena* arena = &g_vk.frame_arenas[0]; + Library lib; Function fn; foreach(name; VULKAN_LIBS) @@ -2759,8 +2772,6 @@ Init(PlatformHandles platform_handles, u64 permanent_mem, u64 frame_mem) if(success) { - Arena* arena = &g_vk.frame_arenas[0]; - u32 count; vkEnumerateInstanceLayerProperties(&count, null); VkLayerProperties[] layers = Alloc!(VkLayerProperties)(arena, count); @@ -2775,24 +2786,79 @@ Init(PlatformHandles platform_handles, u64 permanent_mem, u64 frame_mem) } } - const char*[] instance_layers = g_VLAYER_SUPPORT && BUILD_DEBUG ? VK_INSTANCE_LAYERS_DEBUG : VK_INSTANCE_LAYERS; - const char*[] instance_ext = g_VLAYER_SUPPORT && BUILD_DEBUG ? VK_INSTANCE_EXT_DEBUG : VK_INSTANCE_EXT; + char*[] instance_layers = cast(char*[])(g_VLAYER_SUPPORT && BUILD_DEBUG ? VK_INSTANCE_LAYERS_DEBUG : VK_INSTANCE_LAYERS); + char*[] instance_ext_base = cast(char*[])(g_VLAYER_SUPPORT && BUILD_DEBUG ? VK_INSTANCE_EXT_DEBUG : VK_INSTANCE_EXT); + + char*[] instance_ext = instance_ext_base; + if(build_info.platform_handles.sdl) + { + u32 total_extension_count = cast(u32)instance_ext.length; + + u32 sdl_extension_count; + const char** sdl_extensions_ptr = SDL_Vulkan_GetInstanceExtensions(&sdl_extension_count); + const char*[] sdl_extensions = sdl_extensions_ptr[0 .. sdl_extension_count]; + if(sdl_extensions == null) + { + Errf("Failed to query Vulkan extensions for SDL, make sure the SDL_WINDOW_VULKAN flag is passed to SDL_CreateWindow [%s]", SDL_GetError()); + assert(false); + } + + foreach(i; 0 .. sdl_extensions.length) + { + bool exists; + foreach(j; 0 .. instance_ext.length) + { + if(strcmp(sdl_extensions[i], instance_ext[i]) == 0) + { + exists = true; + break; + } + } + + if(!exists) + { + total_extension_count += 1; + } + } + + instance_ext = Alloc!(char*)(arena, total_extension_count); + instance_ext[0 .. instance_ext.length] = instance_ext_base[0 .. $]; + + u32 ext_count = cast(u32)instance_ext_base.length; + foreach(i; 0 .. sdl_extensions.length) + { + bool exists; + foreach(j; 0 .. instance_ext_base.length) + { + if(strcmp(sdl_extensions[i], instance_ext_base[i]) == 0) + { + exists = true; + break; + } + } + + if(!exists) + { + instance_ext[ext_count++] = cast(char*)sdl_extensions[i]; + } + } + } VkApplicationInfo app_info = { - sType: VK_STRUCTURE_TYPE_APPLICATION_INFO, - pApplicationName: "Video Game", + sType: VK_STRUCTURE_TYPE_APPLICATION_INFO, + pApplicationName: build_info.application_name.ptr, applicationVersion: VK_MAKE_API_VERSION(0, 0, 0, 1), - pEngineName: "Gears", - engineVersion: VK_MAKE_API_VERSION(0, 0, 0, 1), - apiVersion: VK_MAKE_API_VERSION(0, 1, 2, 0), + pEngineName: build_info.engine_name.ptr, + engineVersion: VK_MAKE_API_VERSION(0, 0, 0, 1), + apiVersion: VK_MAKE_API_VERSION(0, 1, 2, 0), }; VkInstanceCreateInfo instance_info = { - sType: VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, - pApplicationInfo: &app_info, - enabledLayerCount: cast(u32)instance_layers.length, - ppEnabledLayerNames: instance_layers.ptr, - enabledExtensionCount: cast(u32)instance_ext.length, + sType: VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, + pApplicationInfo: &app_info, + enabledLayerCount: cast(u32)instance_layers.length, + ppEnabledLayerNames: instance_layers.ptr, + enabledExtensionCount: cast(u32)instance_ext.length, ppEnabledExtensionNames: instance_ext.ptr, }; @@ -2858,37 +2924,46 @@ Init(PlatformHandles platform_handles, u64 permanent_mem, u64 frame_mem) // Surface if(success) { - version(linux) - { - VkXlibSurfaceCreateInfoKHR surface_info = { - sType: VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, - dpy: g_vk.platform_handles.display, - window: g_vk.platform_handles.window, - }; + if(g_vk.platform_handles.sdl) + { + if(!SDL_Vulkan_CreateSurface(g_vk.platform_handles.sdl_window, g_vk.instance, null, &g_vk.surface)) + { + Errf("Failed to initialize Vulkan surface through SDL [%s]", Str(SDL_GetError())); + assert(false); + } + } + else + { + version(linux) + { + VkXlibSurfaceCreateInfoKHR surface_info = { + sType: VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, + dpy: g_vk.platform_handles.display, + window: g_vk.platform_handles.window, + }; - VkResult result = vkCreateXlibSurfaceKHR(g_vk.instance, &surface_info, null, &g_vk.surface); - } + VkResult result = vkCreateXlibSurfaceKHR(g_vk.instance, &surface_info, null, &g_vk.surface); + } - version(Windows) - { - VkWin32SurfaceCreateInfoKHR surface_info = { - sType: VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR, - hinstance: g_vk.platform_handles.instance, - hwnd: g_vk.platform_handles.handle, - }; + version(Windows) + { + VkWin32SurfaceCreateInfoKHR surface_info = { + sType: VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR, + hinstance: g_vk.platform_handles.instance, + hwnd: g_vk.platform_handles.handle, + }; - VkResult result = vkCreateWin32SurfaceKHR(g_vk.instance, &surface_info, null, &g_vk.surface); - } + VkResult result = vkCreateWin32SurfaceKHR(g_vk.instance, &surface_info, null, &g_vk.surface); + } - success &= VkCheck("InitSurface failure", result); + success &= VkCheck("InitSurface failure", result); + } } if(success) { success = false; - Arena* arena = &g_vk.frame_arenas[0]; - u32 count; vkEnumeratePhysicalDevices(g_vk.instance, &count, null); VkPhysicalDevice[] devices = Alloc!(VkPhysicalDevice)(arena, count); @@ -3202,8 +3277,6 @@ Init(PlatformHandles platform_handles, u64 permanent_mem, u64 frame_mem) { CreateDrawImages(); - Arena* arena = &g_vk.frame_arenas[0]; - VkSemaphoreCreateInfo sem_info = { sType: VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO }; VkCommandPoolCreateInfo pool_info = { @@ -3514,6 +3587,9 @@ VkResultStr(VkResult result) version(VULKAN_RENDERER_TEST) unittest { - PlatformHandles handles; - Init(handles, 10*1000*1000, 10*1000*1000); + VulkanBuildInfo build_info = { + application_name: "Test", + engine_name: "Test", + }; + Init(build_info, 10*1000*1000, 10*1000*1000); }