vulkan progress
This commit is contained in:
parent
a1cf0a46b5
commit
427e2f1998
37
.gitattributes
vendored
37
.gitattributes
vendored
@ -3,23 +3,28 @@
|
|||||||
##############################
|
##############################
|
||||||
#- Source files
|
#- Source files
|
||||||
|
|
||||||
*.c linguist-language=C
|
*.c linguist-language=C
|
||||||
*.h linguist-language=C
|
*.h linguist-language=C
|
||||||
*.g linguist-language=HLSL
|
*.g linguist-language=HLSL
|
||||||
*.gh linguist-language=HLSL
|
*.gh linguist-language=HLSL
|
||||||
*.cg linguist-language=C
|
*.cg linguist-language=C
|
||||||
*.cgh linguist-language=C
|
*.cgh linguist-language=C
|
||||||
*.lay linguist-generated
|
*.lay linguist-language=C
|
||||||
|
|
||||||
##############################
|
##############################
|
||||||
#- Binary files
|
#- Binary files
|
||||||
|
|
||||||
*.exe filter=lfs diff=lfs merge=lfs -text
|
*.exe filter=lfs diff=lfs merge=lfs -text
|
||||||
*.dll filter=lfs diff=lfs merge=lfs -text
|
*.dll filter=lfs diff=lfs merge=lfs -text
|
||||||
*.lib filter=lfs diff=lfs merge=lfs -text
|
*.lib filter=lfs diff=lfs merge=lfs -text
|
||||||
*.zip filter=lfs diff=lfs merge=lfs -text
|
*.zip filter=lfs diff=lfs merge=lfs -text
|
||||||
*.tga filter=lfs diff=lfs merge=lfs -text
|
*.tga filter=lfs diff=lfs merge=lfs -text
|
||||||
*.ase filter=lfs diff=lfs merge=lfs -text
|
*.ase filter=lfs diff=lfs merge=lfs -text
|
||||||
*.ttf filter=lfs diff=lfs merge=lfs -text
|
*.ttf filter=lfs diff=lfs merge=lfs -text
|
||||||
*.mp3 filter=lfs diff=lfs merge=lfs -text
|
*.mp3 filter=lfs diff=lfs merge=lfs -text
|
||||||
*.dat filter=lfs diff=lfs merge=lfs -text
|
*.dat filter=lfs diff=lfs merge=lfs -text
|
||||||
|
|
||||||
|
##############################
|
||||||
|
#- Libraries
|
||||||
|
|
||||||
|
# vulkan/* filter=lfs diff=lfs merge=lfs -text
|
||||||
|
|||||||
@ -794,6 +794,7 @@ Inline u64 MixU64s(u64 seed_a, u64 seed_b)
|
|||||||
|
|
||||||
#if IsCpu
|
#if IsCpu
|
||||||
StringList GetRawCommandline(void);
|
StringList GetRawCommandline(void);
|
||||||
|
String GetAppName(void);
|
||||||
String GetAppDirectory(void);
|
String GetAppDirectory(void);
|
||||||
void Echo(String msg);
|
void Echo(String msg);
|
||||||
b32 Panic(String msg);
|
b32 Panic(String msg);
|
||||||
|
|||||||
@ -43,6 +43,11 @@ StringList GetRawCommandline(void)
|
|||||||
return W32.raw_command_line;
|
return W32.raw_command_line;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String GetAppName(void)
|
||||||
|
{
|
||||||
|
return W32.app_name;
|
||||||
|
}
|
||||||
|
|
||||||
void Echo(String msg)
|
void Echo(String msg)
|
||||||
{
|
{
|
||||||
HANDLE console_handle = GetStdHandle(STD_OUTPUT_HANDLE);
|
HANDLE console_handle = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
@ -65,16 +70,22 @@ b32 Panic(String msg)
|
|||||||
LogPanic(msg);
|
LogPanic(msg);
|
||||||
char msg_cstr[4096];
|
char msg_cstr[4096];
|
||||||
CstrFromStringToBuff(StringFromFixedArray(msg_cstr), msg);
|
CstrFromStringToBuff(StringFromFixedArray(msg_cstr), msg);
|
||||||
|
b32 is_debug = IsRunningInDebugger();
|
||||||
|
i32 mb_result = 0;
|
||||||
{
|
{
|
||||||
u32 mb_flags = MB_SETFOREGROUND | MB_ICONERROR;
|
u32 mb_flags = MB_SETFOREGROUND | MB_ICONERROR;
|
||||||
MessageBoxExA(0, msg_cstr, "Fatal error", mb_flags, 0);
|
if (is_debug)
|
||||||
|
{
|
||||||
|
mb_flags |= MB_CANCELTRYCONTINUE;
|
||||||
|
}
|
||||||
|
mb_result = MessageBoxExA(0, msg_cstr, "Fatal error", mb_flags, 0);
|
||||||
}
|
}
|
||||||
HANDLE console_handle = GetStdHandle(STD_ERROR_HANDLE);
|
HANDLE console_handle = GetStdHandle(STD_ERROR_HANDLE);
|
||||||
if (console_handle != INVALID_HANDLE_VALUE)
|
if (console_handle != INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
WriteFile(console_handle, msg.text, msg.len, 0, 0);
|
WriteFile(console_handle, msg.text, msg.len, 0, 0);
|
||||||
}
|
}
|
||||||
if (IsRunningInDebugger())
|
if (is_debug && mb_result != IDCANCEL)
|
||||||
{
|
{
|
||||||
Assert(0);
|
Assert(0);
|
||||||
}
|
}
|
||||||
@ -508,18 +519,19 @@ i32 W32_Main(void)
|
|||||||
{
|
{
|
||||||
String appdir_path = Zi;
|
String appdir_path = Zi;
|
||||||
CommandlineArg appdir_arg = CommandlineArgFromName(Lit("appdir"));
|
CommandlineArg appdir_arg = CommandlineArgFromName(Lit("appdir"));
|
||||||
CommandlineArg appname_arg = CommandlineArgFromName(Lit("appname"));
|
CommandlineArg app_name_arg = CommandlineArgFromName(Lit("app_name"));
|
||||||
if (appdir_arg.exists && appdir_arg.value.len > 0)
|
if (appdir_arg.exists && appdir_arg.value.len > 0)
|
||||||
{
|
{
|
||||||
appdir_path = appdir_arg.value;
|
appdir_path = appdir_arg.value;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
String appname = Lit(Stringize(DefaultAppName));
|
String app_name = Lit(Stringize(DefaultAppName));
|
||||||
if (appname_arg.exists && appname_arg.value.len > 0)
|
if (app_name_arg.exists && app_name_arg.value.len > 0)
|
||||||
{
|
{
|
||||||
appname = appname_arg.value;
|
app_name = app_name_arg.value;
|
||||||
}
|
}
|
||||||
|
W32.app_name = app_name;
|
||||||
|
|
||||||
wchar_t *path_wstr = 0;
|
wchar_t *path_wstr = 0;
|
||||||
HRESULT hr = SHGetKnownFolderPath(&FOLDERID_LocalAppData, 0, 0, &path_wstr);
|
HRESULT hr = SHGetKnownFolderPath(&FOLDERID_LocalAppData, 0, 0, &path_wstr);
|
||||||
@ -529,7 +541,7 @@ i32 W32_Main(void)
|
|||||||
}
|
}
|
||||||
appdir_path = StringFromWstrNoLimit(perm, path_wstr);
|
appdir_path = StringFromWstrNoLimit(perm, path_wstr);
|
||||||
CoTaskMemFree(path_wstr);
|
CoTaskMemFree(path_wstr);
|
||||||
appdir_path = PathFromString(perm, StringF(perm, "%F\\Cabin\\%F\\", FmtString(appdir_path), FmtString(appname)), '/');
|
appdir_path = PathFromString(perm, StringF(perm, "%F\\Cabin\\%F\\", FmtString(appdir_path), FmtString(app_name)), '/');
|
||||||
}
|
}
|
||||||
// Create app dir
|
// Create app dir
|
||||||
{
|
{
|
||||||
|
|||||||
@ -95,6 +95,7 @@ Struct(W32_Ctx)
|
|||||||
i64 ns_per_qpc;
|
i64 ns_per_qpc;
|
||||||
|
|
||||||
StringList raw_command_line;
|
StringList raw_command_line;
|
||||||
|
String app_name;
|
||||||
String appdir_path;
|
String appdir_path;
|
||||||
|
|
||||||
//- Application control flow
|
//- Application control flow
|
||||||
|
|||||||
@ -28,4 +28,4 @@
|
|||||||
@IncludeC gpu_common.c
|
@IncludeC gpu_common.c
|
||||||
|
|
||||||
// @DefaultDownstream Win32 gpu_dx12
|
// @DefaultDownstream Win32 gpu_dx12
|
||||||
@DefaultDownstream Any gpu_vk
|
@DefaultDownstream Win32 gpu_vk
|
||||||
|
|||||||
@ -1,11 +1,588 @@
|
|||||||
G_VK_Ctx G_VK = Zi;
|
G_VK_Ctx G_VK = Zi;
|
||||||
ThreadLocal G_VK_ThreadLocalCtx G_VK_tl = Zi;
|
ThreadLocal G_VK_ThreadLocalCtx G_VK_tl = Zi;
|
||||||
|
|
||||||
|
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = 0;
|
||||||
|
|
||||||
|
// Define global procs
|
||||||
|
#define X(name, ...) CAT(PFN_, name) name = 0;
|
||||||
|
G_VK_ProcXList(X)
|
||||||
|
#undef X
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ @hookimpl Bootstrap
|
//~ @hookimpl Bootstrap
|
||||||
|
|
||||||
void G_Bootstrap(void)
|
void G_Bootstrap(void)
|
||||||
{
|
{
|
||||||
|
Arena *perm = PermArena();
|
||||||
|
TempArena scratch = BeginScratchNoConflict();
|
||||||
|
|
||||||
|
Struct(VKProcDesc)
|
||||||
|
{
|
||||||
|
char *name_cstr;
|
||||||
|
void **dst;
|
||||||
|
G_VK_ProcFlag flags;
|
||||||
|
};
|
||||||
|
VKProcDesc proc_descs[] = {
|
||||||
|
#define X(_name, _flags) { .name_cstr = #_name, .dst = (void **)&_name, .flags = _flags },
|
||||||
|
G_VK_ProcXList(X)
|
||||||
|
#undef X
|
||||||
|
};
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- Load vulkan
|
||||||
|
|
||||||
|
G_VK.lib = LoadLibraryW(L"vulkan-1.dll");
|
||||||
|
if (!G_VK.lib)
|
||||||
|
{
|
||||||
|
Panic(Lit("Vulkan-1.dll not found. Ensure drivers are up to date."));
|
||||||
|
}
|
||||||
|
|
||||||
|
vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)GetProcAddress(G_VK.lib, "vkGetInstanceProcAddr");
|
||||||
|
if (!vkGetInstanceProcAddr)
|
||||||
|
{
|
||||||
|
Panic(Lit("Failed to initialize Vulkan - proc 'vkGetInstanceProcAddr' not found"));
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- Load global procs
|
||||||
|
|
||||||
|
for (u32 proc_idx = 0; proc_idx < countof(proc_descs); ++proc_idx)
|
||||||
|
{
|
||||||
|
VKProcDesc desc = proc_descs[proc_idx];
|
||||||
|
if (AnyBit(desc.flags, G_VK_ProcFlag_Global))
|
||||||
|
{
|
||||||
|
void *proc = (void *)vkGetInstanceProcAddr(0, desc.name_cstr);
|
||||||
|
*desc.dst = proc;
|
||||||
|
if (!proc && !AnyBit(desc.flags, G_VK_ProcFlag_NoForce))
|
||||||
|
{
|
||||||
|
String name = StringFromCstrNoLimit(desc.name_cstr);
|
||||||
|
Panic(StringF(PermArena(), "Failed to initialize Vulkan - Unable to locate procedure '%F'", FmtString(name)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 instance_version = 0;
|
||||||
|
G_VK_ForceCall(vkEnumerateInstanceVersion, &instance_version);
|
||||||
|
LogInfoF("Vulkan instance version: %F", FmtUint(instance_version));
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- Fetch extensions
|
||||||
|
|
||||||
|
b32 validation_enabled = CommandlineArgFromName(Lit("gpu-debug-validation")).exists;
|
||||||
|
b32 debug_enabled = validation_enabled || CommandlineArgFromName(Lit("gpu-debug")).exists;
|
||||||
|
|
||||||
|
u32 extensions_count = 0;
|
||||||
|
String *extensions = 0;
|
||||||
|
char **extension_cstrs = 0;
|
||||||
|
{
|
||||||
|
u32 available_extensions_count = 0;
|
||||||
|
VkExtensionProperties *available_extensions = 0;
|
||||||
|
{
|
||||||
|
vkEnumerateInstanceExtensionProperties(0, &available_extensions_count, 0);
|
||||||
|
available_extensions = PushStructsNoZero(scratch.arena, VkExtensionProperties, available_extensions_count);
|
||||||
|
vkEnumerateInstanceExtensionProperties(0, &available_extensions_count, available_extensions);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Build required extensions list
|
||||||
|
StringList extensions_list = Zi;
|
||||||
|
{
|
||||||
|
PushStringToList(scratch.arena, &extensions_list, Lit("VK_KHR_surface"));
|
||||||
|
PushStringToList(scratch.arena, &extensions_list, Lit("VK_KHR_win32_surface"));
|
||||||
|
if (debug_enabled)
|
||||||
|
{
|
||||||
|
PushStringToList(scratch.arena, &extensions_list, Lit("VK_EXT_debug_report"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Create extension arrays
|
||||||
|
{
|
||||||
|
extensions_count = extensions_list.count;
|
||||||
|
extensions = PushStructsNoZero(scratch.arena, String, extensions_count);
|
||||||
|
extension_cstrs = PushStructsNoZero(scratch.arena, char *, extensions_count);
|
||||||
|
{
|
||||||
|
u32 extension_idx = 0;
|
||||||
|
for (StringListNode *n = extensions_list.first; n; n = n->next)
|
||||||
|
{
|
||||||
|
extension_cstrs[extension_idx] = CstrFromString(scratch.arena, n->s);
|
||||||
|
extensions[extension_idx] = n->s;
|
||||||
|
++extension_idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find missing extensions
|
||||||
|
StringList missing_extensions = Zi;
|
||||||
|
for (u32 extension_idx = 0; extension_idx < extensions_count; ++extension_idx)
|
||||||
|
{
|
||||||
|
String extension_name = extensions[extension_idx];
|
||||||
|
b32 found = 0;
|
||||||
|
for (u32 available_extension_idx = 0; available_extension_idx < available_extensions_count; ++available_extension_idx)
|
||||||
|
{
|
||||||
|
String available_extension_name = StringFromCstrNoLimit(available_extensions[available_extension_idx].extensionName);
|
||||||
|
if (MatchString(available_extension_name, extension_name))
|
||||||
|
{
|
||||||
|
found = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
PushStringToList(scratch.arena, &missing_extensions, StringF(scratch.arena, " - %F", FmtString(extension_name)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notify user if required extensions are missing
|
||||||
|
if (missing_extensions.count > 0)
|
||||||
|
{
|
||||||
|
String items = StringFromList(scratch.arena, missing_extensions, Lit("\n"));
|
||||||
|
String msg = StringF(
|
||||||
|
scratch.arena,
|
||||||
|
"Vulkan failed to initialize because the following instance extensions were not detected:\n\n"
|
||||||
|
"%F\n\n"
|
||||||
|
"Ensure that drivers are up to date.",
|
||||||
|
FmtString(items)
|
||||||
|
);
|
||||||
|
Panic(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- Create instance
|
||||||
|
|
||||||
|
VkInstance instance = Zi;
|
||||||
|
{
|
||||||
|
VkApplicationInfo app_info = Zi;
|
||||||
|
{
|
||||||
|
app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
|
||||||
|
app_info.pApplicationName = CstrFromString(perm, GetAppName());
|
||||||
|
app_info.applicationVersion = 0;
|
||||||
|
app_info.pEngineName = "Engine";
|
||||||
|
app_info.engineVersion = 0;
|
||||||
|
app_info.apiVersion = VK_API_VERSION_1_3;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkInstanceCreateInfo create_info = Zi;
|
||||||
|
{
|
||||||
|
create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
||||||
|
create_info.pApplicationInfo = &app_info;
|
||||||
|
create_info.enabledLayerCount = 0;
|
||||||
|
create_info.ppEnabledLayerNames = 0;
|
||||||
|
create_info.enabledExtensionCount = extensions_count;
|
||||||
|
create_info.ppEnabledExtensionNames = extension_cstrs;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkResult r = vkCreateInstance(&create_info, 0, &G_VK.instance);
|
||||||
|
if (r != VK_SUCCESS)
|
||||||
|
{
|
||||||
|
String result_str = G_VK_StringFromVkResult(r);
|
||||||
|
String err = StringF(perm, "Failed to initialize Vulkan - vkCreateInstance failed with '%F'. Ensure that drivers are up to date.", FmtString(result_str));
|
||||||
|
Panic(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- Load instance procs
|
||||||
|
|
||||||
|
for (u32 proc_idx = 0; proc_idx < countof(proc_descs); ++proc_idx)
|
||||||
|
{
|
||||||
|
VKProcDesc desc = proc_descs[proc_idx];
|
||||||
|
if (!AnyBit(desc.flags, G_VK_ProcFlag_Global))
|
||||||
|
{
|
||||||
|
void *proc = (void *)vkGetInstanceProcAddr(G_VK.instance, desc.name_cstr);
|
||||||
|
*desc.dst = proc;
|
||||||
|
if (!proc && !AnyBit(desc.flags, G_VK_ProcFlag_NoForce))
|
||||||
|
{
|
||||||
|
String name = StringFromCstrNoLimit(desc.name_cstr);
|
||||||
|
Panic(StringF(PermArena(), "Failed to initialize Vulkan - Unable to locate procedure '%F' on instance 0x%F", FmtString(name), FmtHex((u64)G_VK.instance, .z = 16)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- Register debug callback
|
||||||
|
|
||||||
|
if (debug_enabled && vkCreateDebugReportCallbackEXT)
|
||||||
|
{
|
||||||
|
VkDebugReportCallbackCreateInfoEXT desc = Zi;
|
||||||
|
{
|
||||||
|
desc.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT;
|
||||||
|
desc.pfnCallback = G_VK_DebugCallback;
|
||||||
|
desc.flags |= VK_DEBUG_REPORT_INFORMATION_BIT_EXT;
|
||||||
|
desc.flags |= VK_DEBUG_REPORT_WARNING_BIT_EXT;
|
||||||
|
desc.flags |= VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
|
||||||
|
desc.flags |= VK_DEBUG_REPORT_ERROR_BIT_EXT;
|
||||||
|
desc.flags |= VK_DEBUG_REPORT_DEBUG_BIT_EXT;
|
||||||
|
}
|
||||||
|
VkDebugReportCallbackEXT *debug_callback = 0;
|
||||||
|
G_VK_ForceCall(vkCreateDebugReportCallbackEXT, G_VK.instance, &desc, 0, (void *)&debug_callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- Fetch physical device
|
||||||
|
|
||||||
|
VkPhysicalDevice physical_device = Zi;
|
||||||
|
VkPhysicalDeviceProperties physical_device_props = Zi;
|
||||||
|
VkPhysicalDeviceFeatures physical_device_features = Zi;
|
||||||
|
String physical_device_name = Zi;
|
||||||
|
{
|
||||||
|
// TODO: Command-line option to force lower-score GPUs
|
||||||
|
u32 target_gpu_score_idx = 0;
|
||||||
|
|
||||||
|
u32 gpus_count = 0;
|
||||||
|
VkPhysicalDevice *gpus = 0;
|
||||||
|
{
|
||||||
|
vkEnumeratePhysicalDevices(G_VK.instance, &gpus_count, 0);
|
||||||
|
gpus = PushStructsNoZero(scratch.arena, VkPhysicalDevice, gpus_count);
|
||||||
|
vkEnumeratePhysicalDevices(G_VK.instance, &gpus_count, gpus);
|
||||||
|
}
|
||||||
|
|
||||||
|
Struct(ScoreEntry)
|
||||||
|
{
|
||||||
|
u64 score;
|
||||||
|
VkPhysicalDevice gpu;
|
||||||
|
VkPhysicalDeviceProperties props;
|
||||||
|
VkPhysicalDeviceFeatures features;
|
||||||
|
String name;
|
||||||
|
};
|
||||||
|
ScoreEntry *entries = PushStructs(scratch.arena, ScoreEntry, gpus_count);
|
||||||
|
|
||||||
|
u64 highest_score = 0;
|
||||||
|
u64 highest_score_idx = 0;
|
||||||
|
for (u32 gpu_idx = 0; gpu_idx < gpus_count; ++gpu_idx)
|
||||||
|
{
|
||||||
|
VkPhysicalDevice gpu = gpus[gpu_idx];
|
||||||
|
VkPhysicalDeviceProperties props = Zi;
|
||||||
|
VkPhysicalDeviceFeatures features = Zi;
|
||||||
|
u64 score = 0;
|
||||||
|
String name = Zi;
|
||||||
|
{
|
||||||
|
vkGetPhysicalDeviceProperties(gpu, &props);
|
||||||
|
vkGetPhysicalDeviceFeatures(gpu, &features);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = StringFromCstrNoLimit(props.deviceName);
|
||||||
|
String props_str = G_VK_StringFromVkPhysicalDeviceProperties(scratch.arena, props);
|
||||||
|
String features_str = G_VK_StringFromVkPhysicalDeviceFeatures(scratch.arena, features);
|
||||||
|
if (props.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
|
||||||
|
{
|
||||||
|
score += Tebi(256);
|
||||||
|
}
|
||||||
|
else if (props.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU)
|
||||||
|
{
|
||||||
|
score += Tebi(128);
|
||||||
|
}
|
||||||
|
// TODO: Score based on available video memory
|
||||||
|
LogInfoF(
|
||||||
|
"Enumerating physical Vulkan device #%F '%F', - Score: %F, Properties: %F, Features: %F",
|
||||||
|
FmtUint(gpu_idx),
|
||||||
|
FmtString(name),
|
||||||
|
FmtUint(score),
|
||||||
|
FmtString(props_str),
|
||||||
|
FmtString(features_str)
|
||||||
|
);
|
||||||
|
if (score > highest_score)
|
||||||
|
{
|
||||||
|
highest_score = score;
|
||||||
|
highest_score_idx = gpu_idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ScoreEntry *entry = &entries[gpu_idx];
|
||||||
|
entry->gpu = gpu;
|
||||||
|
entry->props = props;
|
||||||
|
entry->features = features;
|
||||||
|
entry->name = name;
|
||||||
|
entry->score = score;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (highest_score_idx < gpus_count)
|
||||||
|
{
|
||||||
|
physical_device = entries[highest_score_idx].gpu;
|
||||||
|
physical_device_props = entries[highest_score_idx].props;
|
||||||
|
physical_device_features = entries[highest_score_idx].features;
|
||||||
|
physical_device_name = entries[highest_score_idx].name;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!physical_device)
|
||||||
|
{
|
||||||
|
Panic(Lit("Failed to initialize Vulkan - No devices found"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- Enforce device capability
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- Create device
|
||||||
|
|
||||||
|
{
|
||||||
|
VkDeviceCreateInfo device_desc = Zi;
|
||||||
|
|
||||||
|
// vkCreateDevice(
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- Finish initialization
|
||||||
|
|
||||||
|
G_VK.initialized = 1;
|
||||||
|
EndScratch(scratch);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//~ Helpers
|
||||||
|
|
||||||
|
String G_VK_StringFromVkResult(VkResult v)
|
||||||
|
{
|
||||||
|
switch (v)
|
||||||
|
{
|
||||||
|
default: return Lit("Unknown error");
|
||||||
|
#define X(name) case name: return Lit(#name);
|
||||||
|
X(VK_SUCCESS)
|
||||||
|
X(VK_NOT_READY)
|
||||||
|
X(VK_TIMEOUT)
|
||||||
|
X(VK_EVENT_SET)
|
||||||
|
X(VK_EVENT_RESET)
|
||||||
|
X(VK_INCOMPLETE)
|
||||||
|
X(VK_ERROR_OUT_OF_HOST_MEMORY)
|
||||||
|
X(VK_ERROR_OUT_OF_DEVICE_MEMORY)
|
||||||
|
X(VK_ERROR_INITIALIZATION_FAILED)
|
||||||
|
X(VK_ERROR_DEVICE_LOST)
|
||||||
|
X(VK_ERROR_MEMORY_MAP_FAILED)
|
||||||
|
X(VK_ERROR_LAYER_NOT_PRESENT)
|
||||||
|
X(VK_ERROR_EXTENSION_NOT_PRESENT)
|
||||||
|
X(VK_ERROR_FEATURE_NOT_PRESENT)
|
||||||
|
X(VK_ERROR_INCOMPATIBLE_DRIVER)
|
||||||
|
X(VK_ERROR_TOO_MANY_OBJECTS)
|
||||||
|
X(VK_ERROR_FORMAT_NOT_SUPPORTED)
|
||||||
|
X(VK_ERROR_FRAGMENTED_POOL)
|
||||||
|
X(VK_ERROR_UNKNOWN)
|
||||||
|
X(VK_ERROR_VALIDATION_FAILED)
|
||||||
|
X(VK_ERROR_OUT_OF_POOL_MEMORY)
|
||||||
|
X(VK_ERROR_INVALID_EXTERNAL_HANDLE)
|
||||||
|
X(VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS)
|
||||||
|
X(VK_ERROR_FRAGMENTATION)
|
||||||
|
X(VK_PIPELINE_COMPILE_REQUIRED)
|
||||||
|
X(VK_ERROR_NOT_PERMITTED)
|
||||||
|
X(VK_ERROR_SURFACE_LOST_KHR)
|
||||||
|
X(VK_ERROR_NATIVE_WINDOW_IN_USE_KHR)
|
||||||
|
X(VK_SUBOPTIMAL_KHR)
|
||||||
|
X(VK_ERROR_OUT_OF_DATE_KHR)
|
||||||
|
X(VK_ERROR_INCOMPATIBLE_DISPLAY_KHR)
|
||||||
|
X(VK_ERROR_INVALID_SHADER_NV)
|
||||||
|
X(VK_ERROR_IMAGE_USAGE_NOT_SUPPORTED_KHR)
|
||||||
|
X(VK_ERROR_VIDEO_PICTURE_LAYOUT_NOT_SUPPORTED_KHR)
|
||||||
|
X(VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR)
|
||||||
|
X(VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR)
|
||||||
|
X(VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR)
|
||||||
|
X(VK_ERROR_VIDEO_STD_VERSION_NOT_SUPPORTED_KHR)
|
||||||
|
X(VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT)
|
||||||
|
X(VK_ERROR_PRESENT_TIMING_QUEUE_FULL_EXT)
|
||||||
|
X(VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT)
|
||||||
|
X(VK_THREAD_IDLE_KHR)
|
||||||
|
X(VK_THREAD_DONE_KHR)
|
||||||
|
X(VK_OPERATION_DEFERRED_KHR)
|
||||||
|
X(VK_OPERATION_NOT_DEFERRED_KHR)
|
||||||
|
X(VK_ERROR_INVALID_VIDEO_STD_PARAMETERS_KHR)
|
||||||
|
X(VK_ERROR_COMPRESSION_EXHAUSTED_EXT)
|
||||||
|
X(VK_INCOMPATIBLE_SHADER_BINARY_EXT)
|
||||||
|
X(VK_PIPELINE_BINARY_MISSING_KHR)
|
||||||
|
X(VK_ERROR_NOT_ENOUGH_SPACE_KHR)
|
||||||
|
#undef X
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String G_VK_StringFromVkPhysicalDeviceProperties(Arena *arena, VkPhysicalDeviceProperties props)
|
||||||
|
{
|
||||||
|
String device_type_str = (
|
||||||
|
props.deviceType == VK_PHYSICAL_DEVICE_TYPE_OTHER ? Lit("VK_PHYSICAL_DEVICE_TYPE_OTHER") :
|
||||||
|
props.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU ? Lit("VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU") :
|
||||||
|
props.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU ? Lit("VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU") :
|
||||||
|
props.deviceType == VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU ? Lit("VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU") :
|
||||||
|
props.deviceType == VK_PHYSICAL_DEVICE_TYPE_CPU ? Lit("VK_PHYSICAL_DEVICE_TYPE_CPU") :
|
||||||
|
Lit("Unknown")
|
||||||
|
);
|
||||||
|
|
||||||
|
String result = StringF(
|
||||||
|
arena,
|
||||||
|
"apiVersion: %F, "
|
||||||
|
"driverVersion: %F, "
|
||||||
|
"vendorID: %F, "
|
||||||
|
"deviceID: %F, "
|
||||||
|
"deviceType: %F, "
|
||||||
|
"deviceName[VK_MAX_PHYSICAL_DEVICE_NAME_SIZE]: %F, "
|
||||||
|
"pipelineCacheUUID[VK_UUID_SIZE]: %F, "
|
||||||
|
"limits: %F, "
|
||||||
|
"sparseProperties: %F",
|
||||||
|
FmtUint(props.apiVersion),
|
||||||
|
FmtUint(props.driverVersion),
|
||||||
|
FmtUint(props.vendorID),
|
||||||
|
FmtUint(props.deviceID),
|
||||||
|
FmtString(device_type_str),
|
||||||
|
FmtString(StringFromCstrNoLimit(props.deviceName)),
|
||||||
|
FmtString(Lit("...")),
|
||||||
|
FmtString(Lit("...")),
|
||||||
|
FmtString(Lit("..."))
|
||||||
|
);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
String G_VK_StringFromVkPhysicalDeviceFeatures(Arena *arena, VkPhysicalDeviceFeatures features)
|
||||||
|
{
|
||||||
|
String result = StringF(
|
||||||
|
arena,
|
||||||
|
"robustBufferAccess: %F, "
|
||||||
|
"fullDrawIndexUint32: %F, "
|
||||||
|
"imageCubeArray: %F, "
|
||||||
|
"independentBlend: %F, "
|
||||||
|
"geometryShader: %F, "
|
||||||
|
"tessellationShader: %F, "
|
||||||
|
"sampleRateShading: %F, "
|
||||||
|
"dualSrcBlend: %F, "
|
||||||
|
"logicOp: %F, "
|
||||||
|
"multiDrawIndirect: %F, "
|
||||||
|
"drawIndirectFirstInstance: %F, "
|
||||||
|
"depthClamp: %F, "
|
||||||
|
"depthBiasClamp: %F, "
|
||||||
|
"fillModeNonSolid: %F, "
|
||||||
|
"depthBounds: %F, "
|
||||||
|
"wideLines: %F, "
|
||||||
|
"largePoints: %F, "
|
||||||
|
"alphaToOne: %F, "
|
||||||
|
"multiViewport: %F, "
|
||||||
|
"samplerAnisotropy: %F, "
|
||||||
|
"textureCompressionETC2: %F, "
|
||||||
|
"textureCompressionASTC_LDR: %F, "
|
||||||
|
"textureCompressionBC: %F, "
|
||||||
|
"occlusionQueryPrecise: %F, "
|
||||||
|
"pipelineStatisticsQuery: %F, "
|
||||||
|
"vertexPipelineStoresAndAtomics: %F, "
|
||||||
|
"fragmentStoresAndAtomics: %F, "
|
||||||
|
"shaderTessellationAndGeometryPointSize: %F, "
|
||||||
|
"shaderImageGatherExtended: %F, "
|
||||||
|
"shaderStorageImageExtendedFormats: %F, "
|
||||||
|
"shaderStorageImageMultisample: %F, "
|
||||||
|
"shaderStorageImageReadWithoutFormat: %F, "
|
||||||
|
"shaderStorageImageWriteWithoutFormat: %F, "
|
||||||
|
"shaderUniformBufferArrayDynamicIndexing: %F, "
|
||||||
|
"shaderSampledImageArrayDynamicIndexing: %F, "
|
||||||
|
"shaderStorageBufferArrayDynamicIndexing: %F, "
|
||||||
|
"shaderStorageImageArrayDynamicIndexing: %F, "
|
||||||
|
"shaderClipDistance: %F, "
|
||||||
|
"shaderCullDistance: %F, "
|
||||||
|
"shaderFloat64: %F, "
|
||||||
|
"shaderInt64: %F, "
|
||||||
|
"shaderInt16: %F, "
|
||||||
|
"shaderResourceResidency: %F, "
|
||||||
|
"shaderResourceMinLod: %F, "
|
||||||
|
"sparseBinding: %F, "
|
||||||
|
"sparseResidencyBuffer: %F, "
|
||||||
|
"sparseResidencyImage2D: %F, "
|
||||||
|
"sparseResidencyImage3D: %F, "
|
||||||
|
"sparseResidency2Samples: %F, "
|
||||||
|
"sparseResidency4Samples: %F, "
|
||||||
|
"sparseResidency8Samples: %F, "
|
||||||
|
"sparseResidency16Samples: %F, "
|
||||||
|
"sparseResidencyAliased: %F, "
|
||||||
|
"variableMultisampleRate: %F, "
|
||||||
|
"inheritedQueries: %F",
|
||||||
|
FmtUint(features.robustBufferAccess),
|
||||||
|
FmtUint(features.fullDrawIndexUint32),
|
||||||
|
FmtUint(features.imageCubeArray),
|
||||||
|
FmtUint(features.independentBlend),
|
||||||
|
FmtUint(features.geometryShader),
|
||||||
|
FmtUint(features.tessellationShader),
|
||||||
|
FmtUint(features.sampleRateShading),
|
||||||
|
FmtUint(features.dualSrcBlend),
|
||||||
|
FmtUint(features.logicOp),
|
||||||
|
FmtUint(features.multiDrawIndirect),
|
||||||
|
FmtUint(features.drawIndirectFirstInstance),
|
||||||
|
FmtUint(features.depthClamp),
|
||||||
|
FmtUint(features.depthBiasClamp),
|
||||||
|
FmtUint(features.fillModeNonSolid),
|
||||||
|
FmtUint(features.depthBounds),
|
||||||
|
FmtUint(features.wideLines),
|
||||||
|
FmtUint(features.largePoints),
|
||||||
|
FmtUint(features.alphaToOne),
|
||||||
|
FmtUint(features.multiViewport),
|
||||||
|
FmtUint(features.samplerAnisotropy),
|
||||||
|
FmtUint(features.textureCompressionETC2),
|
||||||
|
FmtUint(features.textureCompressionASTC_LDR),
|
||||||
|
FmtUint(features.textureCompressionBC),
|
||||||
|
FmtUint(features.occlusionQueryPrecise),
|
||||||
|
FmtUint(features.pipelineStatisticsQuery),
|
||||||
|
FmtUint(features.vertexPipelineStoresAndAtomics),
|
||||||
|
FmtUint(features.fragmentStoresAndAtomics),
|
||||||
|
FmtUint(features.shaderTessellationAndGeometryPointSize),
|
||||||
|
FmtUint(features.shaderImageGatherExtended),
|
||||||
|
FmtUint(features.shaderStorageImageExtendedFormats),
|
||||||
|
FmtUint(features.shaderStorageImageMultisample),
|
||||||
|
FmtUint(features.shaderStorageImageReadWithoutFormat),
|
||||||
|
FmtUint(features.shaderStorageImageWriteWithoutFormat),
|
||||||
|
FmtUint(features.shaderUniformBufferArrayDynamicIndexing),
|
||||||
|
FmtUint(features.shaderSampledImageArrayDynamicIndexing),
|
||||||
|
FmtUint(features.shaderStorageBufferArrayDynamicIndexing),
|
||||||
|
FmtUint(features.shaderStorageImageArrayDynamicIndexing),
|
||||||
|
FmtUint(features.shaderClipDistance),
|
||||||
|
FmtUint(features.shaderCullDistance),
|
||||||
|
FmtUint(features.shaderFloat64),
|
||||||
|
FmtUint(features.shaderInt64),
|
||||||
|
FmtUint(features.shaderInt16),
|
||||||
|
FmtUint(features.shaderResourceResidency),
|
||||||
|
FmtUint(features.shaderResourceMinLod),
|
||||||
|
FmtUint(features.sparseBinding),
|
||||||
|
FmtUint(features.sparseResidencyBuffer),
|
||||||
|
FmtUint(features.sparseResidencyImage2D),
|
||||||
|
FmtUint(features.sparseResidencyImage3D),
|
||||||
|
FmtUint(features.sparseResidency2Samples),
|
||||||
|
FmtUint(features.sparseResidency4Samples),
|
||||||
|
FmtUint(features.sparseResidency8Samples),
|
||||||
|
FmtUint(features.sparseResidency16Samples),
|
||||||
|
FmtUint(features.sparseResidencyAliased),
|
||||||
|
FmtUint(features.variableMultisampleRate),
|
||||||
|
FmtUint(features.inheritedQueries)
|
||||||
|
);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkResult G_VK_ForceSuccess(VkResult result, String func_name)
|
||||||
|
{
|
||||||
|
if (result != VK_SUCCESS)
|
||||||
|
{
|
||||||
|
Arena *perm = PermArena();
|
||||||
|
String result_str = G_VK_StringFromVkResult(result);
|
||||||
|
String msg = Zi;
|
||||||
|
if (!G_VK.initialized)
|
||||||
|
{
|
||||||
|
msg = StringF(perm, "Failed to initialize Vulkan - %F returned '%F'", FmtString(func_name), FmtString(result_str));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
msg = StringF(perm, "Vulkan error - Call to %F failed with '%F'", FmtString(func_name), FmtString(result_str));
|
||||||
|
}
|
||||||
|
Panic(msg);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//~ Debug
|
||||||
|
|
||||||
|
VkBool32 G_VK_DebugCallback(
|
||||||
|
VkDebugReportFlagsEXT flags,
|
||||||
|
VkDebugReportObjectTypeEXT objectType,
|
||||||
|
uint64_t object,
|
||||||
|
size_t location,
|
||||||
|
int32_t messageCode,
|
||||||
|
const char* pLayerPrefix,
|
||||||
|
const char* pMessage,
|
||||||
|
void* pUserData
|
||||||
|
)
|
||||||
|
{
|
||||||
|
DEBUGBREAKABLE;
|
||||||
|
Panic(Lit("Testing"));
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@ -1,9 +1,43 @@
|
|||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//~ Vulkan API types
|
||||||
|
|
||||||
|
#define VK_NO_PROTOTYPES
|
||||||
|
#include "../../../vulkan/include/vulkan.h"
|
||||||
|
|
||||||
|
#define G_VK_ProcXList(X) \
|
||||||
|
X(vkEnumerateInstanceVersion, G_VK_ProcFlag_Global) \
|
||||||
|
X(vkEnumerateInstanceExtensionProperties, G_VK_ProcFlag_Global) \
|
||||||
|
X(vkEnumerateInstanceLayerProperties, G_VK_ProcFlag_Global) \
|
||||||
|
X(vkCreateInstance, G_VK_ProcFlag_Global) \
|
||||||
|
X(vkEnumeratePhysicalDevices, G_VK_ProcFlag_None) \
|
||||||
|
X(vkCreateDevice, G_VK_ProcFlag_None) \
|
||||||
|
X(vkCreateDebugReportCallbackEXT, G_VK_ProcFlag_NoForce) \
|
||||||
|
X(vkGetPhysicalDeviceProperties, G_VK_ProcFlag_None) \
|
||||||
|
X(vkGetPhysicalDeviceFeatures, G_VK_ProcFlag_None) \
|
||||||
|
/* ----------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
Enum(G_VK_ProcFlag)
|
||||||
|
{
|
||||||
|
G_VK_ProcFlag_None = 0,
|
||||||
|
G_VK_ProcFlag_Global = (1 << 0),
|
||||||
|
G_VK_ProcFlag_NoForce = (1 << 1),
|
||||||
|
};
|
||||||
|
|
||||||
|
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr;
|
||||||
|
#define X(name, ...) extern CAT(PFN_, name) name;
|
||||||
|
G_VK_ProcXList(X)
|
||||||
|
#undef X
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ State types
|
//~ State types
|
||||||
|
|
||||||
Struct(G_VK_Ctx)
|
Struct(G_VK_Ctx)
|
||||||
{
|
{
|
||||||
i32 _;
|
HMODULE lib;
|
||||||
|
b32 initialized;
|
||||||
|
|
||||||
|
VkInstance instance;
|
||||||
|
VkDevice device;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(G_VK_ThreadLocalCtx)
|
Struct(G_VK_ThreadLocalCtx)
|
||||||
@ -13,3 +47,27 @@ Struct(G_VK_ThreadLocalCtx)
|
|||||||
|
|
||||||
extern G_VK_Ctx G_Vk;
|
extern G_VK_Ctx G_Vk;
|
||||||
extern ThreadLocal G_VK_ThreadLocalCtx G_VK_tl;
|
extern ThreadLocal G_VK_ThreadLocalCtx G_VK_tl;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//~ Helpers
|
||||||
|
|
||||||
|
String G_VK_StringFromVkResult(VkResult v);
|
||||||
|
String G_VK_StringFromVkPhysicalDeviceProperties(Arena *arena, VkPhysicalDeviceProperties props);
|
||||||
|
String G_VK_StringFromVkPhysicalDeviceFeatures(Arena *arena, VkPhysicalDeviceFeatures features);
|
||||||
|
VkResult G_VK_ForceSuccess(VkResult result, String func_name);
|
||||||
|
|
||||||
|
#define G_VK_ForceCall(func, ...) G_VK_ForceSuccess(func(__VA_ARGS__), Lit(#func))
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//~ Debug
|
||||||
|
|
||||||
|
VkBool32 G_VK_DebugCallback(
|
||||||
|
VkDebugReportFlagsEXT flags,
|
||||||
|
VkDebugReportObjectTypeEXT objectType,
|
||||||
|
uint64_t object,
|
||||||
|
size_t location,
|
||||||
|
int32_t messageCode,
|
||||||
|
const char* pLayerPrefix,
|
||||||
|
const char* pMessage,
|
||||||
|
void* pUserData
|
||||||
|
);
|
||||||
|
|||||||
@ -484,6 +484,8 @@ void M_BuildEntryPoint(WaveLaneCtx *lane)
|
|||||||
PushStringToList(perm, &cp.warnings_msvc, Lit("-wd4702")); // unreachable code
|
PushStringToList(perm, &cp.warnings_msvc, Lit("-wd4702")); // unreachable code
|
||||||
PushStringToList(perm, &cp.warnings_msvc, Lit("-wd4305")); // 'initializing': truncation from 'double' to 'f32'
|
PushStringToList(perm, &cp.warnings_msvc, Lit("-wd4305")); // 'initializing': truncation from 'double' to 'f32'
|
||||||
|
|
||||||
|
// PushStringToList(perm, &cp.warnings_msvc, Lit("-wd4152")); // nonstandard extension, function/data pointer conversion in expression
|
||||||
|
|
||||||
// PushStringToList(perm, &cp.warnings_msvc, Lit("-wd4127")); // conditional expression is constant
|
// PushStringToList(perm, &cp.warnings_msvc, Lit("-wd4127")); // conditional expression is constant
|
||||||
// PushStringToList(perm, &cp.warnings_msvc, Lit("-wd4820")); // bytes padding added after data member
|
// PushStringToList(perm, &cp.warnings_msvc, Lit("-wd4820")); // bytes padding added after data member
|
||||||
// PushStringToList(perm, &cp.warnings_msvc, Lit("-wd4464")); // relative include path contains '..'
|
// PushStringToList(perm, &cp.warnings_msvc, Lit("-wd4464")); // relative include path contains '..'
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user