vulkan progress

This commit is contained in:
jacob 2026-03-04 05:23:12 -06:00
parent a1cf0a46b5
commit 427e2f1998
8 changed files with 681 additions and 25 deletions

37
.gitattributes vendored
View File

@ -3,23 +3,28 @@
##############################
#- Source files
*.c linguist-language=C
*.h linguist-language=C
*.g linguist-language=HLSL
*.gh linguist-language=HLSL
*.cg linguist-language=C
*.cgh linguist-language=C
*.lay linguist-generated
*.c linguist-language=C
*.h linguist-language=C
*.g linguist-language=HLSL
*.gh linguist-language=HLSL
*.cg linguist-language=C
*.cgh linguist-language=C
*.lay linguist-language=C
##############################
#- Binary files
*.exe filter=lfs diff=lfs merge=lfs -text
*.dll filter=lfs diff=lfs merge=lfs -text
*.lib filter=lfs diff=lfs merge=lfs -text
*.zip filter=lfs diff=lfs merge=lfs -text
*.tga filter=lfs diff=lfs merge=lfs -text
*.ase filter=lfs diff=lfs merge=lfs -text
*.ttf filter=lfs diff=lfs merge=lfs -text
*.mp3 filter=lfs diff=lfs merge=lfs -text
*.dat filter=lfs diff=lfs merge=lfs -text
*.exe filter=lfs diff=lfs merge=lfs -text
*.dll filter=lfs diff=lfs merge=lfs -text
*.lib filter=lfs diff=lfs merge=lfs -text
*.zip filter=lfs diff=lfs merge=lfs -text
*.tga filter=lfs diff=lfs merge=lfs -text
*.ase filter=lfs diff=lfs merge=lfs -text
*.ttf filter=lfs diff=lfs merge=lfs -text
*.mp3 filter=lfs diff=lfs merge=lfs -text
*.dat filter=lfs diff=lfs merge=lfs -text
##############################
#- Libraries
# vulkan/* filter=lfs diff=lfs merge=lfs -text

View File

@ -794,6 +794,7 @@ Inline u64 MixU64s(u64 seed_a, u64 seed_b)
#if IsCpu
StringList GetRawCommandline(void);
String GetAppName(void);
String GetAppDirectory(void);
void Echo(String msg);
b32 Panic(String msg);

View File

@ -43,6 +43,11 @@ StringList GetRawCommandline(void)
return W32.raw_command_line;
}
String GetAppName(void)
{
return W32.app_name;
}
void Echo(String msg)
{
HANDLE console_handle = GetStdHandle(STD_OUTPUT_HANDLE);
@ -65,16 +70,22 @@ b32 Panic(String msg)
LogPanic(msg);
char msg_cstr[4096];
CstrFromStringToBuff(StringFromFixedArray(msg_cstr), msg);
b32 is_debug = IsRunningInDebugger();
i32 mb_result = 0;
{
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);
if (console_handle != INVALID_HANDLE_VALUE)
{
WriteFile(console_handle, msg.text, msg.len, 0, 0);
}
if (IsRunningInDebugger())
if (is_debug && mb_result != IDCANCEL)
{
Assert(0);
}
@ -508,18 +519,19 @@ i32 W32_Main(void)
{
String appdir_path = Zi;
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)
{
appdir_path = appdir_arg.value;
}
else
{
String appname = Lit(Stringize(DefaultAppName));
if (appname_arg.exists && appname_arg.value.len > 0)
String app_name = Lit(Stringize(DefaultAppName));
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;
HRESULT hr = SHGetKnownFolderPath(&FOLDERID_LocalAppData, 0, 0, &path_wstr);
@ -529,7 +541,7 @@ i32 W32_Main(void)
}
appdir_path = StringFromWstrNoLimit(perm, 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
{

View File

@ -95,6 +95,7 @@ Struct(W32_Ctx)
i64 ns_per_qpc;
StringList raw_command_line;
String app_name;
String appdir_path;
//- Application control flow

View File

@ -28,4 +28,4 @@
@IncludeC gpu_common.c
// @DefaultDownstream Win32 gpu_dx12
@DefaultDownstream Any gpu_vk
@DefaultDownstream Win32 gpu_vk

View File

@ -1,11 +1,588 @@
G_VK_Ctx G_VK = 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
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;
}
////////////////////////////////////////////////////////////

View File

@ -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
Struct(G_VK_Ctx)
{
i32 _;
HMODULE lib;
b32 initialized;
VkInstance instance;
VkDevice device;
};
Struct(G_VK_ThreadLocalCtx)
@ -13,3 +47,27 @@ Struct(G_VK_ThreadLocalCtx)
extern G_VK_Ctx G_Vk;
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
);

View File

@ -484,6 +484,8 @@ void M_BuildEntryPoint(WaveLaneCtx *lane)
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("-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("-wd4820")); // bytes padding added after data member
// PushStringToList(perm, &cp.warnings_msvc, Lit("-wd4464")); // relative include path contains '..'