add sdl vulkan support, dub broken

This commit is contained in:
Matthew 2026-06-12 13:57:09 +10:00
parent 09ce86257e
commit 6126144f7c
4 changed files with 137 additions and 55 deletions

View File

@ -44,6 +44,11 @@
#ifndef BUILD_WASM #ifndef BUILD_WASM
# include <SDL3/SDL.h> # include <SDL3/SDL.h>
# ifdef BUILD_VULKAN
# include <SDL3/SDL_vulkan.h>
# endif
#endif #endif
#ifdef BUILD_GL #ifdef BUILD_GL

View File

@ -1945,10 +1945,10 @@ version(DLIB_TEST) unittest
u8[] data_valid, data_test; 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_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); assert(data_valid == data_test);
} }

View File

@ -6,8 +6,8 @@
{ {
"name": "core", "name": "core",
"targetType": "sourceLibrary", "targetType": "sourceLibrary",
"sourcePaths": ["dlib"], "sourcePaths": ["dlib", "vulkan", "opengl"],
"importPaths": ["dlib"], "importPaths": ["dlib", "vulkan", "opengl"],
"sourceFiles-linux": ["build/libstb.a"], "sourceFiles-linux": ["build/libstb.a"],
"sourceFiles-windows": [], "sourceFiles-windows": [],
"libs-linux": [ "libs-linux": [
@ -27,6 +27,9 @@
"--Xcc=-DBUILD_WASM", "--Xcc=-DBUILD_WASM",
"-gcc=clang" "-gcc=clang"
], ],
"dflags": ["-v"],
"dflags-ldc": ["--Xcc=-DBUILD_VULKAN"],
"dlfags-dmd": ["-Xcc=-DBUILD_VULKAN"],
"libs-windows": [], "libs-windows": [],
"preGenerateCommands-linux": ["./build.sh"], "preGenerateCommands-linux": ["./build.sh"],
"buildTypes": { "buildTypes": {
@ -45,8 +48,6 @@
"sourceFiles-linux": ["build/libvma.a"], "sourceFiles-linux": ["build/libvma.a"],
"sourceFiles-windows": [], "sourceFiles-windows": [],
"stringImportPaths": ["build"], "stringImportPaths": ["build"],
"dflags-ldc": ["--Xcc=-DBUILD_VULKAN"],
"dflags-dmd": ["-Xcc=-DBUILD_VULKAN"],
"libs-linux": [ "libs-linux": [
"vulkan", "vulkan",
"stdc++" "stdc++"

View File

@ -9,11 +9,11 @@ import vulkan_funcs;
import std.stdio; import std.stdio;
import std.algorithm.comparison; import std.algorithm.comparison;
import std.algorithm.searching : canFind; import std.algorithm.searching : canFind;
import std.traits : isPointer, isArray; import std.traits : isPointer, isArray;
import core.stdc.string : strcmp, memcpy, strlen; import core.stdc.string : strcmp, memcpy, strlen;
import core.stdc.stdio : Printf = printf; import core.stdc.stdio : Printf = printf;
import std.format : sformat; import std.format : sformat;
import std.math.rounding : Ceil = ceil; import std.math.rounding : Ceil = ceil;
version(VULKAN_DEBUG) version(VULKAN_DEBUG)
{ {
@ -68,6 +68,8 @@ version(Windows)
struct PlatformHandles struct PlatformHandles
{ {
bool sdl;
SDL_Window* sdl_window;
version(linux) version(linux)
{ {
Display* display; 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" ]; const char*[] VK_INSTANCE_LAYERS_DEBUG = [ "VK_LAYER_KHRONOS_validation" ];
version(linux) 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 ]; const char*[] VK_INSTANCE_EXT_DEBUG = VK_INSTANCE_EXT ~ [ cast(char*)VK_EXT_DEBUG_UTILS_EXTENSION_NAME ];
} }
version(Windows) 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 ]; const char*[] VK_INSTANCE_EXT_DEBUG = VK_INSTANCE_EXT ~ [ cast(char*)VK_EXT_DEBUG_UTILS_EXTENSION_NAME ];
} }
@ -829,6 +831,8 @@ BeginFrame()
result = vkResetFences(g_vk.device, 1, g_vk.render_fence_ptr); result = vkResetFences(g_vk.device, 1, g_vk.render_fence_ptr);
VkCheckA("BeginFrame failure: vkResetFences error", result); VkCheckA("BeginFrame failure: vkResetFences error", result);
Reset(g_vk.FrameArena());
// ?? dont know why this is 3 (should have commented it) // ?? dont know why this is 3 (should have commented it)
for(u64 i = 0; i < 3; i += 1) 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); 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 void
Init(PlatformHandles platform_handles, u64 permanent_mem, u64 frame_mem) Init(VulkanBuildInfo build_info, u64 permanent_mem, u64 frame_mem)
{ {
bool success; bool success;
@ -2726,11 +2737,13 @@ Init(PlatformHandles platform_handles, u64 permanent_mem, u64 frame_mem)
CreateArena(frame_mem), CreateArena(frame_mem),
CreateArena(frame_mem), CreateArena(frame_mem),
], ],
platform_handles: platform_handles, platform_handles: build_info.platform_handles,
}; };
g_vk = vk; g_vk = vk;
Arena* arena = &g_vk.frame_arenas[0];
Library lib; Library lib;
Function fn; Function fn;
foreach(name; VULKAN_LIBS) foreach(name; VULKAN_LIBS)
@ -2759,8 +2772,6 @@ Init(PlatformHandles platform_handles, u64 permanent_mem, u64 frame_mem)
if(success) if(success)
{ {
Arena* arena = &g_vk.frame_arenas[0];
u32 count; u32 count;
vkEnumerateInstanceLayerProperties(&count, null); vkEnumerateInstanceLayerProperties(&count, null);
VkLayerProperties[] layers = Alloc!(VkLayerProperties)(arena, count); 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; char*[] instance_layers = cast(char*[])(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_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 = { VkApplicationInfo app_info = {
sType: VK_STRUCTURE_TYPE_APPLICATION_INFO, sType: VK_STRUCTURE_TYPE_APPLICATION_INFO,
pApplicationName: "Video Game", pApplicationName: build_info.application_name.ptr,
applicationVersion: VK_MAKE_API_VERSION(0, 0, 0, 1), applicationVersion: VK_MAKE_API_VERSION(0, 0, 0, 1),
pEngineName: "Gears", pEngineName: build_info.engine_name.ptr,
engineVersion: VK_MAKE_API_VERSION(0, 0, 0, 1), engineVersion: VK_MAKE_API_VERSION(0, 0, 0, 1),
apiVersion: VK_MAKE_API_VERSION(0, 1, 2, 0), apiVersion: VK_MAKE_API_VERSION(0, 1, 2, 0),
}; };
VkInstanceCreateInfo instance_info = { VkInstanceCreateInfo instance_info = {
sType: VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, sType: VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
pApplicationInfo: &app_info, pApplicationInfo: &app_info,
enabledLayerCount: cast(u32)instance_layers.length, enabledLayerCount: cast(u32)instance_layers.length,
ppEnabledLayerNames: instance_layers.ptr, ppEnabledLayerNames: instance_layers.ptr,
enabledExtensionCount: cast(u32)instance_ext.length, enabledExtensionCount: cast(u32)instance_ext.length,
ppEnabledExtensionNames: instance_ext.ptr, ppEnabledExtensionNames: instance_ext.ptr,
}; };
@ -2858,37 +2924,46 @@ Init(PlatformHandles platform_handles, u64 permanent_mem, u64 frame_mem)
// Surface // Surface
if(success) if(success)
{ {
version(linux) if(g_vk.platform_handles.sdl)
{ {
VkXlibSurfaceCreateInfoKHR surface_info = { if(!SDL_Vulkan_CreateSurface(g_vk.platform_handles.sdl_window, g_vk.instance, null, &g_vk.surface))
sType: VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, {
dpy: g_vk.platform_handles.display, Errf("Failed to initialize Vulkan surface through SDL [%s]", Str(SDL_GetError()));
window: g_vk.platform_handles.window, 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) version(Windows)
{ {
VkWin32SurfaceCreateInfoKHR surface_info = { VkWin32SurfaceCreateInfoKHR surface_info = {
sType: VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR, sType: VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR,
hinstance: g_vk.platform_handles.instance, hinstance: g_vk.platform_handles.instance,
hwnd: g_vk.platform_handles.handle, 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) if(success)
{ {
success = false; success = false;
Arena* arena = &g_vk.frame_arenas[0];
u32 count; u32 count;
vkEnumeratePhysicalDevices(g_vk.instance, &count, null); vkEnumeratePhysicalDevices(g_vk.instance, &count, null);
VkPhysicalDevice[] devices = Alloc!(VkPhysicalDevice)(arena, count); VkPhysicalDevice[] devices = Alloc!(VkPhysicalDevice)(arena, count);
@ -3202,8 +3277,6 @@ Init(PlatformHandles platform_handles, u64 permanent_mem, u64 frame_mem)
{ {
CreateDrawImages(); CreateDrawImages();
Arena* arena = &g_vk.frame_arenas[0];
VkSemaphoreCreateInfo sem_info = { sType: VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO }; VkSemaphoreCreateInfo sem_info = { sType: VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO };
VkCommandPoolCreateInfo pool_info = { VkCommandPoolCreateInfo pool_info = {
@ -3514,6 +3587,9 @@ VkResultStr(VkResult result)
version(VULKAN_RENDERER_TEST) unittest version(VULKAN_RENDERER_TEST) unittest
{ {
PlatformHandles handles; VulkanBuildInfo build_info = {
Init(handles, 10*1000*1000, 10*1000*1000); application_name: "Test",
engine_name: "Test",
};
Init(build_info, 10*1000*1000, 10*1000*1000);
} }