create vulkan instance; fix instance extension ref api
This commit is contained in:
parent
fa683fb882
commit
0dcedece06
|
@ -142,7 +142,7 @@ typedef uint64_t vulkan_non_dispatchable_handle_t;
|
|||
typedef void* vulkan_handle_t;
|
||||
// FIXME END MAXIMUM DUMB
|
||||
|
||||
int VK_GetInstanceExtensions( const char ***pNames );
|
||||
int VK_GetInstanceExtensions( unsigned int count, const char **pNames );
|
||||
void *VK_GetVkGetInstanceProcAddr( void );
|
||||
vulkan_non_dispatchable_handle_t VK_CreateSurface( vulkan_handle_t vkInstance );
|
||||
|
||||
|
|
|
@ -965,23 +965,15 @@ int GL_GetAttribute( int attr, int *val )
|
|||
#define EGL_LIB NULL
|
||||
#endif
|
||||
|
||||
int VK_GetInstanceExtensions( const char ***pNames )
|
||||
int VK_GetInstanceExtensions( unsigned int count, const char **pNames )
|
||||
{
|
||||
int pCount = 0;
|
||||
if (!SDL_Vulkan_GetInstanceExtensions(host.hWnd, (unsigned int*)&pCount, NULL))
|
||||
if (!SDL_Vulkan_GetInstanceExtensions(host.hWnd, &count, pNames))
|
||||
{
|
||||
Con_Reportf( S_ERROR "Couldn't get Vulkan extensions: %s\n", SDL_GetError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
*pNames = Mem_Malloc(host.mempool, pCount * sizeof(const char*));
|
||||
if (!SDL_Vulkan_GetInstanceExtensions(host.hWnd, (unsigned int*)&pCount, *pNames))
|
||||
{
|
||||
Con_Reportf( S_ERROR "Couldn't get Vulkan extensions: %s\n", SDL_GetError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
return pCount;
|
||||
return (int)count;
|
||||
}
|
||||
|
||||
void *VK_GetVkGetInstanceProcAddr( void )
|
||||
|
|
|
@ -442,7 +442,7 @@ typedef struct ref_api_s
|
|||
render_interface_t *drawFuncs;
|
||||
|
||||
// Vulkan
|
||||
int (*VK_GetInstanceExtensions)( const char ***pNames );
|
||||
int (*VK_GetInstanceExtensions)( unsigned int count, const char **pNames );
|
||||
void *(*VK_GetVkGetInstanceProcAddr)( void );
|
||||
vulkan_non_dispatchable_handle_t (*VK_CreateSurface)( vulkan_handle_t vkInstance );
|
||||
} ref_api_t;
|
||||
|
|
238
ref_vk/vk_core.c
238
ref_vk/vk_core.c
|
@ -7,6 +7,7 @@
|
|||
#include "ref_api.h"
|
||||
#include "crtlib.h"
|
||||
#include "com_strings.h"
|
||||
#include "eiface.h"
|
||||
|
||||
#define VK_NO_PROTOTYPES
|
||||
#include <vulkan/vulkan.h>
|
||||
|
@ -15,6 +16,9 @@ typedef struct vulkan_core_s {
|
|||
PFN_vkGetInstanceProcAddr get_proc_addr;
|
||||
uint32_t vulkan_version;
|
||||
VkInstance instance;
|
||||
VkDebugUtilsMessengerEXT debug_messenger;
|
||||
|
||||
byte *pool;
|
||||
} vulkan_core_t;
|
||||
|
||||
vulkan_core_t vk_core = {0};
|
||||
|
@ -27,10 +31,143 @@ vulkan_core_t vk_core = {0};
|
|||
#define XVK_INSTANCE_FUNC(f) \
|
||||
((PFN_ ##f)vk_core.get_proc_addr(vk_core.instance, #f))
|
||||
|
||||
static PFN_vkEnumerateInstanceVersion vkEnumerateInstanceVersion;
|
||||
#define NULLINST_FUNCS(X) \
|
||||
X(vkEnumerateInstanceVersion) \
|
||||
X(vkCreateInstance) \
|
||||
|
||||
#define INSTANCE_FUNCS(X) \
|
||||
X(vkDestroyInstance) \
|
||||
X(vkEnumeratePhysicalDevices) \
|
||||
X(vkGetPhysicalDeviceProperties2) \
|
||||
X(vkGetPhysicalDeviceFeatures2) \
|
||||
X(vkGetPhysicalDeviceQueueFamilyProperties) \
|
||||
X(vkGetPhysicalDeviceSurfaceSupportKHR) \
|
||||
X(vkGetPhysicalDeviceMemoryProperties) \
|
||||
X(vkCreateDevice) \
|
||||
|
||||
#define INSTANCE_DEBUG_FUNCS(X) \
|
||||
X(vkCreateDebugUtilsMessengerEXT) \
|
||||
X(vkDestroyDebugUtilsMessengerEXT) \
|
||||
|
||||
#define X(f) PFN_##f f = NULL;
|
||||
NULLINST_FUNCS(X)
|
||||
INSTANCE_FUNCS(X)
|
||||
INSTANCE_DEBUG_FUNCS(X)
|
||||
#undef X
|
||||
|
||||
static dllfunc_t nullinst_funcs[] = {
|
||||
#define X(f) {#f, (void**)&f},
|
||||
NULLINST_FUNCS(X)
|
||||
#undef X
|
||||
};
|
||||
|
||||
static dllfunc_t instance_funcs[] = {
|
||||
#define X(f) {#f, (void**)&f},
|
||||
INSTANCE_FUNCS(X)
|
||||
#undef X
|
||||
};
|
||||
|
||||
static dllfunc_t instance_debug_funcs[] = {
|
||||
#define X(f) {#f, (void**)&f},
|
||||
INSTANCE_DEBUG_FUNCS(X)
|
||||
#undef X
|
||||
};
|
||||
|
||||
static const char *resultName(VkResult result) {
|
||||
switch (result) {
|
||||
case VK_SUCCESS: return "VK_SUCCESS";
|
||||
case VK_NOT_READY: return "VK_NOT_READY";
|
||||
case VK_TIMEOUT: return "VK_TIMEOUT";
|
||||
case VK_EVENT_SET: return "VK_EVENT_SET";
|
||||
case VK_EVENT_RESET: return "VK_EVENT_RESET";
|
||||
case VK_INCOMPLETE: return "VK_INCOMPLETE";
|
||||
case VK_ERROR_OUT_OF_HOST_MEMORY: return "VK_ERROR_OUT_OF_HOST_MEMORY";
|
||||
case VK_ERROR_OUT_OF_DEVICE_MEMORY: return "VK_ERROR_OUT_OF_DEVICE_MEMORY";
|
||||
case VK_ERROR_INITIALIZATION_FAILED: return "VK_ERROR_INITIALIZATION_FAILED";
|
||||
case VK_ERROR_DEVICE_LOST: return "VK_ERROR_DEVICE_LOST";
|
||||
case VK_ERROR_MEMORY_MAP_FAILED: return "VK_ERROR_MEMORY_MAP_FAILED";
|
||||
case VK_ERROR_LAYER_NOT_PRESENT: return "VK_ERROR_LAYER_NOT_PRESENT";
|
||||
case VK_ERROR_EXTENSION_NOT_PRESENT: return "VK_ERROR_EXTENSION_NOT_PRESENT";
|
||||
case VK_ERROR_FEATURE_NOT_PRESENT: return "VK_ERROR_FEATURE_NOT_PRESENT";
|
||||
case VK_ERROR_INCOMPATIBLE_DRIVER: return "VK_ERROR_INCOMPATIBLE_DRIVER";
|
||||
case VK_ERROR_TOO_MANY_OBJECTS: return "VK_ERROR_TOO_MANY_OBJECTS";
|
||||
case VK_ERROR_FORMAT_NOT_SUPPORTED: return "VK_ERROR_FORMAT_NOT_SUPPORTED";
|
||||
case VK_ERROR_FRAGMENTED_POOL: return "VK_ERROR_FRAGMENTED_POOL";
|
||||
case VK_ERROR_UNKNOWN: return "VK_ERROR_UNKNOWN";
|
||||
case VK_ERROR_OUT_OF_POOL_MEMORY: return "VK_ERROR_OUT_OF_POOL_MEMORY";
|
||||
case VK_ERROR_INVALID_EXTERNAL_HANDLE: return "VK_ERROR_INVALID_EXTERNAL_HANDLE";
|
||||
case VK_ERROR_FRAGMENTATION: return "VK_ERROR_FRAGMENTATION";
|
||||
case VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS: return "VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS";
|
||||
case VK_ERROR_SURFACE_LOST_KHR: return "VK_ERROR_SURFACE_LOST_KHR";
|
||||
case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR: return "VK_ERROR_NATIVE_WINDOW_IN_USE_KHR";
|
||||
case VK_SUBOPTIMAL_KHR: return "VK_SUBOPTIMAL_KHR";
|
||||
case VK_ERROR_OUT_OF_DATE_KHR: return "VK_ERROR_OUT_OF_DATE_KHR";
|
||||
case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR: return "VK_ERROR_INCOMPATIBLE_DISPLAY_KHR";
|
||||
case VK_ERROR_VALIDATION_FAILED_EXT: return "VK_ERROR_VALIDATION_FAILED_EXT";
|
||||
case VK_ERROR_INVALID_SHADER_NV: return "VK_ERROR_INVALID_SHADER_NV";
|
||||
case VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT:
|
||||
return "VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT";
|
||||
case VK_ERROR_NOT_PERMITTED_EXT: return "VK_ERROR_NOT_PERMITTED_EXT";
|
||||
case VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT: return "VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT";
|
||||
case VK_THREAD_IDLE_KHR: return "VK_THREAD_IDLE_KHR";
|
||||
case VK_THREAD_DONE_KHR: return "VK_THREAD_DONE_KHR";
|
||||
case VK_OPERATION_DEFERRED_KHR: return "VK_OPERATION_DEFERRED_KHR";
|
||||
case VK_OPERATION_NOT_DEFERRED_KHR: return "VK_OPERATION_NOT_DEFERRED_KHR";
|
||||
case VK_PIPELINE_COMPILE_REQUIRED_EXT: return "VK_PIPELINE_COMPILE_REQUIRED_EXT";
|
||||
default: return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
#define XVK_CHECK(f) do { \
|
||||
const VkResult result = f; \
|
||||
if (result != VK_SUCCESS) { \
|
||||
gEngine.Host_Error( S_ERROR "%s:%d " #f " failed (%d): %s\n", \
|
||||
__FILE__, __LINE__, result, resultName(result)); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
static const char *validation_layers[] = {
|
||||
"VK_LAYER_KHRONOS_validation",
|
||||
};
|
||||
|
||||
static void loadInstanceFunctions(dllfunc_t *funcs, int count)
|
||||
{
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
*funcs[i].func = vk_core.get_proc_addr(vk_core.instance, funcs[i].name);
|
||||
if (!*funcs[i].func)
|
||||
{
|
||||
gEngine.Con_Printf( S_WARN "Function %s was not loaded\n", funcs[i].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VkBool32 debugCallback(
|
||||
VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
|
||||
VkDebugUtilsMessageTypeFlagsEXT messageTypes,
|
||||
const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
|
||||
void *pUserData) {
|
||||
(void)(pUserData);
|
||||
(void)(messageTypes);
|
||||
(void)(messageSeverity);
|
||||
|
||||
// TODO better messages, not only errors, what are other arguments for, ...
|
||||
if (messageSeverity == VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) {
|
||||
gEngine.Con_Printf(S_ERROR "Validation: %s\n", pCallbackData->pMessage);
|
||||
#ifdef DEBUG
|
||||
#ifdef _MSC_VER
|
||||
__debugbreak();
|
||||
#else
|
||||
__builtin_trap();
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
return VK_FALSE;
|
||||
}
|
||||
|
||||
qboolean R_VkInit( void )
|
||||
{
|
||||
const qboolean debug = !!(gEngine.Sys_CheckParm("-vkdebug") || gEngine.Sys_CheckParm("-gldebug"));
|
||||
|
||||
if( !gEngine.R_Init_Video( REF_VULKAN )) // request Vulkan surface
|
||||
{
|
||||
|
@ -38,15 +175,17 @@ qboolean R_VkInit( void )
|
|||
return false;
|
||||
}
|
||||
|
||||
// TODO VkInstance create ...
|
||||
vk_core.get_proc_addr = gEngine.VK_GetVkGetInstanceProcAddr();
|
||||
if (!vk_core.get_proc_addr)
|
||||
{
|
||||
gEngine.Con_Printf( S_ERROR "Cannot get vkGetInstanceProcAddr address" );
|
||||
return false;
|
||||
gEngine.Con_Printf( S_ERROR "Cannot get vkGetInstanceProcAddr address" );
|
||||
return false;
|
||||
}
|
||||
|
||||
vkEnumerateInstanceVersion = XVK_INSTANCE_FUNC(vkEnumerateInstanceVersion);
|
||||
vk_core.pool = Mem_AllocPool("Vulkan pool");
|
||||
|
||||
loadInstanceFunctions(nullinst_funcs, ARRAYSIZE(nullinst_funcs));
|
||||
|
||||
if (vkEnumerateInstanceVersion)
|
||||
{
|
||||
vkEnumerateInstanceVersion(&vk_core.vulkan_version);
|
||||
|
@ -59,21 +198,86 @@ qboolean R_VkInit( void )
|
|||
gEngine.Con_Printf( "Vulkan version %u.%u.%u\n", XVK_PARSE_VERSION(vk_core.vulkan_version));
|
||||
|
||||
{
|
||||
const char **instance_exts = NULL;
|
||||
const int num_instance_exts = gEngine.VK_GetInstanceExtensions(&instance_exts);
|
||||
if (num_instance_exts < 0)
|
||||
const char **instance_extensions = NULL;
|
||||
unsigned int num_instance_extensions = debug ? 1 : 0;
|
||||
VkApplicationInfo app_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
|
||||
.apiVersion = VK_API_VERSION_1_0,
|
||||
.applicationVersion = VK_MAKE_VERSION(0, 0, 0), // TODO
|
||||
.engineVersion = VK_MAKE_VERSION(0, 0, 0),
|
||||
.pApplicationName = "",
|
||||
.pEngineName = "xash3d-fwgs",
|
||||
};
|
||||
VkInstanceCreateInfo create_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
|
||||
.pApplicationInfo = &app_info,
|
||||
};
|
||||
|
||||
int vid_extensions = gEngine.VK_GetInstanceExtensions(0, NULL);
|
||||
if (vid_extensions < 0)
|
||||
{
|
||||
gEngine.Con_Printf( S_ERROR "Cannot get Vulkan instance extensions" );
|
||||
gEngine.Con_Printf( S_ERROR "Cannot get Vulkan instance extensions\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
gEngine.Con_Reportf("Vulkan instance extensions: %d\n", num_instance_exts);
|
||||
for (int i = 0; i < num_instance_exts; ++i)
|
||||
num_instance_extensions += vid_extensions;
|
||||
|
||||
instance_extensions = Mem_Malloc(vk_core.pool, sizeof(const char*) * num_instance_extensions);
|
||||
vid_extensions = gEngine.VK_GetInstanceExtensions(vid_extensions, instance_extensions);
|
||||
if (vid_extensions < 0)
|
||||
{
|
||||
gEngine.Con_Reportf("\t%d: %s\n", i, instance_exts[i]);
|
||||
gEngine.Con_Printf( S_ERROR "Cannot get Vulkan instance extensions\n" );
|
||||
Mem_Free(instance_extensions);
|
||||
return false;
|
||||
}
|
||||
|
||||
Mem_Free(instance_exts);
|
||||
if (debug)
|
||||
{
|
||||
instance_extensions[vid_extensions] = VK_EXT_DEBUG_UTILS_EXTENSION_NAME;
|
||||
}
|
||||
|
||||
gEngine.Con_Reportf("Requesting instance extensions: %d\n", num_instance_extensions);
|
||||
for (int i = 0; i < num_instance_extensions; ++i)
|
||||
{
|
||||
gEngine.Con_Reportf("\t%d: %s\n", i, instance_extensions[i]);
|
||||
}
|
||||
|
||||
create_info.enabledExtensionCount = num_instance_extensions;
|
||||
create_info.ppEnabledExtensionNames = instance_extensions;
|
||||
|
||||
if (debug)
|
||||
{
|
||||
create_info.enabledLayerCount = ARRAYSIZE(validation_layers);
|
||||
create_info.ppEnabledLayerNames = validation_layers;
|
||||
|
||||
gEngine.Con_Printf(S_WARN "Using Vulkan validation layers, expect severely degraded performance\n");
|
||||
}
|
||||
|
||||
// TODO handle errors gracefully -- let it try next renderer
|
||||
XVK_CHECK(vkCreateInstance(&create_info, NULL, &vk_core.instance));
|
||||
|
||||
loadInstanceFunctions(instance_funcs, ARRAYSIZE(instance_funcs));
|
||||
|
||||
if (debug)
|
||||
{
|
||||
loadInstanceFunctions(instance_debug_funcs, ARRAYSIZE(instance_debug_funcs));
|
||||
|
||||
if (vkCreateDebugUtilsMessengerEXT)
|
||||
{
|
||||
VkDebugUtilsMessengerCreateInfoEXT debug_create_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
|
||||
.messageSeverity = 0x1111, //:vovka: VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT,
|
||||
.messageType = 0x07,
|
||||
.pfnUserCallback = debugCallback,
|
||||
};
|
||||
XVK_CHECK(vkCreateDebugUtilsMessengerEXT(vk_core.instance, &debug_create_info, NULL, &vk_core.debug_messenger));
|
||||
} else
|
||||
{
|
||||
gEngine.Con_Printf(S_WARN "Vulkan debug utils messenger is not available\n");
|
||||
}
|
||||
}
|
||||
|
||||
Mem_Free(instance_extensions);
|
||||
}
|
||||
|
||||
initTextures();
|
||||
|
@ -83,9 +287,11 @@ qboolean R_VkInit( void )
|
|||
|
||||
void R_VkShutdown( void )
|
||||
{
|
||||
gEngine.Con_Printf("VK FIXME: %s\n", __FUNCTION__);
|
||||
if (vk_core.debug_messenger)
|
||||
{
|
||||
vkDestroyDebugUtilsMessengerEXT(vk_core.instance, vk_core.debug_messenger, NULL);
|
||||
}
|
||||
|
||||
// TODO destroy everything
|
||||
//vkDestroyInstance(vk_core.instance, NULL);
|
||||
vkDestroyInstance(vk_core.instance, NULL);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue