feat(renderer): Initialize vulkan
This commit is contained in:
		
							parent
							
								
									3059fce861
								
							
						
					
					
						commit
						e0904e84c4
					
				@ -339,7 +339,7 @@ static int Entry(int argc, char **argv) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Initialize the renderer */
 | 
					    /* Initialize the renderer */
 | 
				
			||||||
    rt_renderer_init_info renderer_init_info;
 | 
					    rt_renderer_window_info renderer_init_info;
 | 
				
			||||||
#ifdef _WIN32
 | 
					#ifdef _WIN32
 | 
				
			||||||
    renderer_init_info.hWnd = glfwGetWin32Window(window);
 | 
					    renderer_init_info.hWnd = glfwGetWin32Window(window);
 | 
				
			||||||
    renderer_init_info.hInstance = _hInstance;
 | 
					    renderer_init_info.hInstance = _hInstance;
 | 
				
			||||||
 | 
				
			|||||||
@ -4,8 +4,31 @@
 | 
				
			|||||||
#include "runtime/runtime.h"
 | 
					#include "runtime/runtime.h"
 | 
				
			||||||
#include "renderer.h"
 | 
					#include "renderer.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct rt_physical_resource_manager_i rt_physical_resource_manager_i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef rt_physical_resource_manager_i *rt_render_device_get_physical_resource_manager_fn(void *o);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Interface for the render device.
 | 
				
			||||||
 | 
					 * The device is responsible for executing command lists. */
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
					    void *o;
 | 
				
			||||||
 | 
					    rt_render_device_get_physical_resource_manager_fn *GetPhysicalResourceManager;
 | 
				
			||||||
 | 
					} rt_render_device_i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Interface for the physical resource manager.
 | 
				
			||||||
 | 
					 * The physical resource manager maps render resources to actual gpu memory (=api objects like VkImage)
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct rt_physical_resource_manager_i {
 | 
				
			||||||
 | 
					    void *o;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
					    rt_result result;
 | 
				
			||||||
 | 
					    rt_render_device_i device;
 | 
				
			||||||
 | 
					} rt_render_backend_init_result;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef void rt_render_backend_register_cvars_fn(void);
 | 
					typedef void rt_render_backend_register_cvars_fn(void);
 | 
				
			||||||
typedef rt_result rt_render_backend_init_fn(const rt_renderer_init_info *info);
 | 
					typedef rt_render_backend_init_result rt_render_backend_init_fn(const rt_renderer_window_info *info);
 | 
				
			||||||
typedef void rt_render_backend_shutdown_fn(void);
 | 
					typedef void rt_render_backend_shutdown_fn(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Public renderer interface */
 | 
					/* Public renderer interface */
 | 
				
			||||||
 | 
				
			|||||||
@ -10,7 +10,7 @@ rt_dx11_device::rt_dx11_device() : m_is_initialized(false) {
 | 
				
			|||||||
rt_dx11_device::~rt_dx11_device() {
 | 
					rt_dx11_device::~rt_dx11_device() {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
rt_result rt_dx11_device::Initialize(const rt_renderer_init_info *info) {
 | 
					rt_result rt_dx11_device::Initialize(const rt_renderer_window_info *info *info) {
 | 
				
			||||||
    // Create the necessary objects (Device, SwapChain, Immediate Context)
 | 
					    // Create the necessary objects (Device, SwapChain, Immediate Context)
 | 
				
			||||||
    HRESULT hr = S_OK;
 | 
					    HRESULT hr = S_OK;
 | 
				
			||||||
    ComPtr<IDXGIFactory1> factory;
 | 
					    ComPtr<IDXGIFactory1> factory;
 | 
				
			||||||
 | 
				
			|||||||
@ -22,7 +22,7 @@ class rt_dx11_device {
 | 
				
			|||||||
        return &dev;
 | 
					        return &dev;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    rt_result Initialize(const rt_renderer_init_info *info);
 | 
					    rt_result Initialize(const rt_renderer_window_info *info *info);
 | 
				
			||||||
    void Shutdown(void);
 | 
					    void Shutdown(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private:
 | 
					  private:
 | 
				
			||||||
 | 
				
			|||||||
@ -5,11 +5,14 @@
 | 
				
			|||||||
void Dx11RegisterCVARs(void) {
 | 
					void Dx11RegisterCVARs(void) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
rt_result Dx11Init(const rt_renderer_init_info *info) {
 | 
					rt_render_backend_init_result Dx11Init(const rt_renderer_window_info *info *info) {
 | 
				
			||||||
    rt_result res = rt_dx11_device::GetInstance()->Initialize(info);
 | 
					    rt_result res = rt_dx11_device::GetInstance()->Initialize(info);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    rt_render_device_i iface = {reinterpret_cast<void*>(rt_dx11_device::GetInstance()), nullptr};
 | 
				
			||||||
 | 
					    rt_render_backend_init_result result = {.result = res, .device = iface};
 | 
				
			||||||
    if (res != RT_SUCCESS)
 | 
					    if (res != RT_SUCCESS)
 | 
				
			||||||
        return res;
 | 
					        return result;
 | 
				
			||||||
    return res;
 | 
					    return result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Dx11Shutdown(void) {
 | 
					void Dx11Shutdown(void) {
 | 
				
			||||||
 | 
				
			|||||||
@ -14,8 +14,9 @@ RT_DLLEXPORT void rtRegisterRenderBackendCVARs(void) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
RT_DLLEXPORT rt_result rtInitRenderer(const rt_renderer_init_info *info) {
 | 
					RT_DLLEXPORT rt_result rtInitRenderer(const rt_renderer_window_info *info) {
 | 
				
			||||||
    return g_render_backend.Init(info);
 | 
					    rt_render_backend_init_result backend_res = g_render_backend.Init(info);
 | 
				
			||||||
 | 
					    return backend_res.result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
RT_DLLEXPORT void rtShutdownRenderer(void) {
 | 
					RT_DLLEXPORT void rtShutdownRenderer(void) {
 | 
				
			||||||
 | 
				
			|||||||
@ -23,7 +23,7 @@ typedef struct {
 | 
				
			|||||||
    unsigned int width;
 | 
					    unsigned int width;
 | 
				
			||||||
    unsigned int height;
 | 
					    unsigned int height;
 | 
				
			||||||
    int is_fullscreen;
 | 
					    int is_fullscreen;
 | 
				
			||||||
} rt_renderer_init_info;
 | 
					} rt_renderer_window_info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef enum {
 | 
					typedef enum {
 | 
				
			||||||
    RT_SHADER_STAGE_VERTEX,
 | 
					    RT_SHADER_STAGE_VERTEX,
 | 
				
			||||||
@ -43,7 +43,7 @@ RT_DLLEXPORT rt_result rtLoadRenderBackend(void);
 | 
				
			|||||||
RT_DLLEXPORT void rtRegisterRenderBackendCVARs(void);
 | 
					RT_DLLEXPORT void rtRegisterRenderBackendCVARs(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
RT_DLLEXPORT rt_result rtInitRenderer(const rt_renderer_init_info *info);
 | 
					RT_DLLEXPORT rt_result rtInitRenderer(const rt_renderer_window_info *window);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
RT_DLLEXPORT void rtShutdownRenderer(void);
 | 
					RT_DLLEXPORT void rtShutdownRenderer(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										665
									
								
								src/renderer/vk/device.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										665
									
								
								src/renderer/vk/device.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,665 @@
 | 
				
			|||||||
 | 
					#include <malloc.h>
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <runtime/runtime.h>
 | 
				
			||||||
 | 
					#include <runtime/config.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "device.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define TARGET_API_VERSION VK_API_VERSION_1_3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RT_CVAR_I(r_VkEnableAPIAllocTracking,
 | 
				
			||||||
 | 
					          "Enable tracking of allocations done by the vulkan api. [0/1] Default: 0",
 | 
				
			||||||
 | 
					          0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RT_CVAR_S(r_VkPhysDeviceName, "Name of the selected physical device. Default: \"\"", "");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RT_CVAR_I(r_VkMaxFramesInFlight, "Maximum number of frames in flight. [2/3] Default: 2", 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static VkAllocationCallbacks _tracking_alloc_cbs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const char *AllocationScopeToString(VkSystemAllocationScope scope) {
 | 
				
			||||||
 | 
					    switch (scope) {
 | 
				
			||||||
 | 
					    case VK_SYSTEM_ALLOCATION_SCOPE_COMMAND:
 | 
				
			||||||
 | 
					        return "COMMAND";
 | 
				
			||||||
 | 
					    case VK_SYSTEM_ALLOCATION_SCOPE_OBJECT:
 | 
				
			||||||
 | 
					        return "OBJECT";
 | 
				
			||||||
 | 
					    case VK_SYSTEM_ALLOCATION_SCOPE_CACHE:
 | 
				
			||||||
 | 
					        return "CACHE";
 | 
				
			||||||
 | 
					    case VK_SYSTEM_ALLOCATION_SCOPE_DEVICE:
 | 
				
			||||||
 | 
					        return "DEVICE";
 | 
				
			||||||
 | 
					    case VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE:
 | 
				
			||||||
 | 
					        return "INSTANCE";
 | 
				
			||||||
 | 
					    default:
 | 
				
			||||||
 | 
					        return "UNKNOWN";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void *
 | 
				
			||||||
 | 
					TrackAllocation(void *userData, size_t size, size_t alignment, VkSystemAllocationScope scope) {
 | 
				
			||||||
 | 
					    rtLog("VK",
 | 
				
			||||||
 | 
					          "Allocation. Size: %zu, Alignment: %zu, Scope: %s",
 | 
				
			||||||
 | 
					          size,
 | 
				
			||||||
 | 
					          alignment,
 | 
				
			||||||
 | 
					          AllocationScopeToString(scope));
 | 
				
			||||||
 | 
					#ifdef _WIN32
 | 
				
			||||||
 | 
					    return _aligned_malloc(size, alignment);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					    return aligned_alloc(alignment, size);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void *TrackReallocation(void *userData,
 | 
				
			||||||
 | 
					                               void *original,
 | 
				
			||||||
 | 
					                               size_t size,
 | 
				
			||||||
 | 
					                               size_t alignment,
 | 
				
			||||||
 | 
					                               VkSystemAllocationScope scope) {
 | 
				
			||||||
 | 
					    rtLog("VK",
 | 
				
			||||||
 | 
					          "Reallocation. Size: %zu, Alignment: %zu, Scope: %s",
 | 
				
			||||||
 | 
					          size,
 | 
				
			||||||
 | 
					          alignment,
 | 
				
			||||||
 | 
					          AllocationScopeToString(scope));
 | 
				
			||||||
 | 
					    return realloc(original, size);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void TrackFree(void *userData, void *memory) {
 | 
				
			||||||
 | 
					    free(memory);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static VkBool32 VKAPI_PTR
 | 
				
			||||||
 | 
					DebugUtilsMessengerCb(VkDebugUtilsMessageSeverityFlagBitsEXT severity,
 | 
				
			||||||
 | 
					                      VkDebugUtilsMessageTypeFlagsEXT types,
 | 
				
			||||||
 | 
					                      const VkDebugUtilsMessengerCallbackDataEXT *callbackData,
 | 
				
			||||||
 | 
					                      void *userData) {
 | 
				
			||||||
 | 
					    if (severity < VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT)
 | 
				
			||||||
 | 
					        return VK_FALSE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const char *severity_str = "<UNKNOWN>";
 | 
				
			||||||
 | 
					    if (severity == VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT)
 | 
				
			||||||
 | 
					        severity_str = "WARNING";
 | 
				
			||||||
 | 
					    else if (severity == VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT)
 | 
				
			||||||
 | 
					        severity_str = "ERROR";
 | 
				
			||||||
 | 
					    rtLog("VK", "[%s] %s", severity_str, callbackData->pMessage);
 | 
				
			||||||
 | 
					    if (severity == VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT)
 | 
				
			||||||
 | 
					        RT_DEBUGBREAK;
 | 
				
			||||||
 | 
					    return VK_FALSE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static rt_result CreateInstance(rt_vk_device *dev) {
 | 
				
			||||||
 | 
					    VkResult result = volkInitialize();
 | 
				
			||||||
 | 
					    if (result != VK_SUCCESS) {
 | 
				
			||||||
 | 
					        rtReportError("vk", "Initialization failed: volkInitialize()");
 | 
				
			||||||
 | 
					        return 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    VkApplicationInfo app_info = {
 | 
				
			||||||
 | 
					        .apiVersion         = TARGET_API_VERSION,
 | 
				
			||||||
 | 
					        .applicationVersion = 0x00001000,
 | 
				
			||||||
 | 
					        .engineVersion      = 0x00001000,
 | 
				
			||||||
 | 
					        .pEngineName        = "voyageEngine",
 | 
				
			||||||
 | 
					        .pApplicationName   = "Voyage",
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const char *extensions[] = {
 | 
				
			||||||
 | 
					        VK_KHR_SURFACE_EXTENSION_NAME,
 | 
				
			||||||
 | 
					#ifdef _WIN32
 | 
				
			||||||
 | 
					        "VK_KHR_win32_surface",
 | 
				
			||||||
 | 
					#elif defined(RT_USE_XLIB)
 | 
				
			||||||
 | 
					        "VK_KHR_xlib_surface",
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef RT_DEBUG
 | 
				
			||||||
 | 
					        VK_EXT_DEBUG_UTILS_EXTENSION_NAME,
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const char *layers[1];
 | 
				
			||||||
 | 
					    unsigned int layer_count = 0;
 | 
				
			||||||
 | 
					#ifdef RT_DEBUG
 | 
				
			||||||
 | 
					    /* Search for layers we want to enable */
 | 
				
			||||||
 | 
					    uint32_t available_layer_count = 0;
 | 
				
			||||||
 | 
					    result = vkEnumerateInstanceLayerProperties(&available_layer_count, NULL);
 | 
				
			||||||
 | 
					    if (result == VK_SUCCESS) {
 | 
				
			||||||
 | 
					        VkLayerProperties *props = calloc(available_layer_count, sizeof(VkLayerProperties));
 | 
				
			||||||
 | 
					        if (props) {
 | 
				
			||||||
 | 
					            vkEnumerateInstanceLayerProperties(&available_layer_count, props);
 | 
				
			||||||
 | 
					            for (uint32_t i = 0; i < available_layer_count; ++i) {
 | 
				
			||||||
 | 
					                if (strcmp(props[i].layerName, "VK_LAYER_KHRONOS_validation") == 0) {
 | 
				
			||||||
 | 
					                    layers[0]   = "VK_LAYER_KHRONOS_validation";
 | 
				
			||||||
 | 
					                    layer_count = 1;
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            free(props);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            rtLog("VK", "Failed to allocate storage for instance layer properties.");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        rtLog("VK", "vkEnumerateInstanceLayerProperties failed.");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    VkInstanceCreateInfo instance_info = {
 | 
				
			||||||
 | 
					        .sType                   = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
 | 
				
			||||||
 | 
					        .pApplicationInfo        = &app_info,
 | 
				
			||||||
 | 
					        .ppEnabledExtensionNames = extensions,
 | 
				
			||||||
 | 
					        .enabledExtensionCount   = RT_ARRAY_COUNT(extensions),
 | 
				
			||||||
 | 
					        .ppEnabledLayerNames     = layers,
 | 
				
			||||||
 | 
					        .enabledLayerCount       = layer_count,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    result = vkCreateInstance(&instance_info, dev->alloc_cb, &dev->instance);
 | 
				
			||||||
 | 
					    if (result != VK_SUCCESS) {
 | 
				
			||||||
 | 
					        rtReportError("VK", "Failed to create the vulkan instance.");
 | 
				
			||||||
 | 
					        return 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    volkLoadInstance(dev->instance);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef RT_DEBUG
 | 
				
			||||||
 | 
					    /* Create the debug utils messenger */
 | 
				
			||||||
 | 
					    VkDebugUtilsMessengerCreateInfoEXT messenger_info = {
 | 
				
			||||||
 | 
					        .sType           = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
 | 
				
			||||||
 | 
					        .messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
 | 
				
			||||||
 | 
					                           VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT,
 | 
				
			||||||
 | 
					        .messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
 | 
				
			||||||
 | 
					                       VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT,
 | 
				
			||||||
 | 
					        .pfnUserCallback = DebugUtilsMessengerCb,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    vkCreateDebugUtilsMessengerEXT(dev->instance,
 | 
				
			||||||
 | 
					                                   &messenger_info,
 | 
				
			||||||
 | 
					                                   dev->alloc_cb,
 | 
				
			||||||
 | 
					                                   &dev->messenger);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    return RT_SUCCESS;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static rt_result CreateSurface(const rt_renderer_window_info *info, rt_vk_device *dev) {
 | 
				
			||||||
 | 
					#ifdef _WIN32
 | 
				
			||||||
 | 
					    dev->native_window.hInstance            = info->hInstance;
 | 
				
			||||||
 | 
					    dev->native_window.hWnd                 = info->hWnd;
 | 
				
			||||||
 | 
					    VkWin32SurfaceCreateInfoKHR surface_info = {
 | 
				
			||||||
 | 
					        .sType     = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR,
 | 
				
			||||||
 | 
					        .hinstance = info->hInstance,
 | 
				
			||||||
 | 
					        .hwnd      = info->hWnd,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    if (vkCreateWin32SurfaceKHR(dev->instance, &surface_info, dev->alloc_cb, &dev->surface) ==
 | 
				
			||||||
 | 
					        VK_SUCCESS)
 | 
				
			||||||
 | 
					        return RT_SUCCESS;
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        return RT_UNKNOWN_ERROR;
 | 
				
			||||||
 | 
					#elif defined(RT_USE_XLIB)
 | 
				
			||||||
 | 
					    dev->native_window.display             = info->display;
 | 
				
			||||||
 | 
					    dev->native_window.window              = info->window;
 | 
				
			||||||
 | 
					    VkXlibSurfaceCreateInfoKHR surface_info = {
 | 
				
			||||||
 | 
					        .sType  = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR,
 | 
				
			||||||
 | 
					        .dpy    = info->display,
 | 
				
			||||||
 | 
					        .window = info->window,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    if (vkCreateXlibSurfaceKHR(dev->instance, &surface_info, dev->alloc_cb, &dev->surface) == VK_SUCCESS)
 | 
				
			||||||
 | 
					        return RT_SUCCESS;
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        return RT_UNKNOWN_ERROR;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
					    uint32_t graphics;
 | 
				
			||||||
 | 
					    uint32_t compute;
 | 
				
			||||||
 | 
					    uint32_t present;
 | 
				
			||||||
 | 
					    uint32_t transfer;
 | 
				
			||||||
 | 
					} rt_queue_indices;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static rt_queue_indices RetrieveQueueIndices(VkPhysicalDevice phys_dev, VkSurfaceKHR surface) {
 | 
				
			||||||
 | 
					    rt_queue_indices indices = {.graphics = UINT32_MAX,
 | 
				
			||||||
 | 
					                                .compute  = UINT32_MAX,
 | 
				
			||||||
 | 
					                                .present  = UINT32_MAX,
 | 
				
			||||||
 | 
					                                .transfer = UINT32_MAX};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uint32_t count = 0;
 | 
				
			||||||
 | 
					    vkGetPhysicalDeviceQueueFamilyProperties(phys_dev, &count, NULL);
 | 
				
			||||||
 | 
					    VkQueueFamilyProperties *props = calloc(count, sizeof(VkQueueFamilyProperties));
 | 
				
			||||||
 | 
					    if (!props) {
 | 
				
			||||||
 | 
					        return indices;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    vkGetPhysicalDeviceQueueFamilyProperties(phys_dev, &count, props);
 | 
				
			||||||
 | 
					    for (uint32_t i = 0; i < count; ++i) {
 | 
				
			||||||
 | 
					        if (props[i].queueCount == 0)
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					        if ((props[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0)
 | 
				
			||||||
 | 
					            indices.graphics = i;
 | 
				
			||||||
 | 
					        if ((props[i].queueFlags & VK_QUEUE_COMPUTE_BIT) != 0)
 | 
				
			||||||
 | 
					            indices.compute = i;
 | 
				
			||||||
 | 
					        if ((props[i].queueFlags & VK_QUEUE_TRANSFER_BIT) != 0)
 | 
				
			||||||
 | 
					            indices.transfer = i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        VkBool32 present_supported = VK_FALSE;
 | 
				
			||||||
 | 
					        vkGetPhysicalDeviceSurfaceSupportKHR(phys_dev, i, surface, &present_supported);
 | 
				
			||||||
 | 
					        if (present_supported)
 | 
				
			||||||
 | 
					            indices.present = i;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (indices.transfer == UINT32_MAX && indices.graphics != UINT32_MAX)
 | 
				
			||||||
 | 
					        indices.transfer = indices.graphics;
 | 
				
			||||||
 | 
					    else if (indices.transfer == UINT32_MAX && indices.compute != UINT32_MAX)
 | 
				
			||||||
 | 
					        indices.transfer = indices.compute;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    free(props);
 | 
				
			||||||
 | 
					    return indices;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool CheckDeviceExtensionSupported(VkPhysicalDevice phys_dev) {
 | 
				
			||||||
 | 
					    const char *required_extensions[] = {
 | 
				
			||||||
 | 
					        VK_KHR_SWAPCHAIN_EXTENSION_NAME,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uint32_t extension_count;
 | 
				
			||||||
 | 
					    vkEnumerateDeviceExtensionProperties(phys_dev, NULL, &extension_count, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    VkExtensionProperties *supported_extensions =
 | 
				
			||||||
 | 
					        calloc(extension_count, sizeof(VkExtensionProperties));
 | 
				
			||||||
 | 
					    if (!supported_extensions)
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    vkEnumerateDeviceExtensionProperties(phys_dev, NULL, &extension_count, supported_extensions);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool supported = true;
 | 
				
			||||||
 | 
					    for (uint32_t i = 0; i < RT_ARRAY_COUNT(required_extensions); ++i) {
 | 
				
			||||||
 | 
					        bool found = false;
 | 
				
			||||||
 | 
					        for (uint32_t j = 0; j < extension_count; ++j) {
 | 
				
			||||||
 | 
					            if (strncmp(supported_extensions[j].extensionName,
 | 
				
			||||||
 | 
					                        required_extensions[i],
 | 
				
			||||||
 | 
					                        VK_MAX_EXTENSION_NAME_SIZE) == 0) {
 | 
				
			||||||
 | 
					                found = true;
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (!found) {
 | 
				
			||||||
 | 
					            supported = false;
 | 
				
			||||||
 | 
					            VkPhysicalDeviceProperties props;
 | 
				
			||||||
 | 
					            vkGetPhysicalDeviceProperties(phys_dev, &props);
 | 
				
			||||||
 | 
					            rtLog("VK", "Device %s does not support the required extension %s",
 | 
				
			||||||
 | 
					                  props.deviceName,
 | 
				
			||||||
 | 
					                  required_extensions[i]);
 | 
				
			||||||
 | 
					            goto out;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					out:
 | 
				
			||||||
 | 
					    free(supported_extensions);
 | 
				
			||||||
 | 
					    return supported;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static rt_result ChoosePhysicalDevice(rt_vk_device *dev) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dev->phys_device          = VK_NULL_HANDLE;
 | 
				
			||||||
 | 
					    uint32_t phys_device_count = 0;
 | 
				
			||||||
 | 
					    VkResult result = vkEnumeratePhysicalDevices(dev->instance, &phys_device_count, NULL);
 | 
				
			||||||
 | 
					    if (result != VK_SUCCESS) {
 | 
				
			||||||
 | 
					        rtReportError("VK", "Failed to enumerate the physical devices.");
 | 
				
			||||||
 | 
					        return 2;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    VkPhysicalDevice *phys_devices = calloc(phys_device_count, sizeof(VkPhysicalDevice));
 | 
				
			||||||
 | 
					    if (!phys_devices) {
 | 
				
			||||||
 | 
					        rtReportError("VK", "Failed to enumerate the physical devices: Out of memory.");
 | 
				
			||||||
 | 
					        return 2;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    vkEnumeratePhysicalDevices(dev->instance, &phys_device_count, phys_devices);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uint32_t highscore  = 0;
 | 
				
			||||||
 | 
					    uint32_t best_index = phys_device_count;
 | 
				
			||||||
 | 
					    for (uint32_t i = 0; i < phys_device_count; ++i) {
 | 
				
			||||||
 | 
					        VkPhysicalDeviceTimelineSemaphoreFeatures timeline_semaphore_features = {
 | 
				
			||||||
 | 
					            .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES,
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        VkPhysicalDeviceSynchronization2Features synchronization2_features = {
 | 
				
			||||||
 | 
					            .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES,
 | 
				
			||||||
 | 
					            .pNext = &timeline_semaphore_features,
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        VkPhysicalDeviceDynamicRenderingFeatures dynamic_rendering_features = {
 | 
				
			||||||
 | 
					            .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES,
 | 
				
			||||||
 | 
					            .pNext = &synchronization2_features,
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        VkPhysicalDeviceDescriptorIndexingFeatures descriptor_indexing_features = {
 | 
				
			||||||
 | 
					            .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES,
 | 
				
			||||||
 | 
					            .pNext = &dynamic_rendering_features,
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        VkPhysicalDeviceFeatures2 features = {
 | 
				
			||||||
 | 
					            .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
 | 
				
			||||||
 | 
					            .pNext = &descriptor_indexing_features,
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        vkGetPhysicalDeviceFeatures2(phys_devices[i], &features);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        VkPhysicalDeviceDescriptorIndexingProperties descriptor_indexing_props = {
 | 
				
			||||||
 | 
					            .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES,
 | 
				
			||||||
 | 
					            .pNext = NULL,
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        VkPhysicalDeviceProperties2 props = {
 | 
				
			||||||
 | 
					            .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
 | 
				
			||||||
 | 
					            .pNext = &descriptor_indexing_props,
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        vkGetPhysicalDeviceProperties2(phys_devices[i], &props);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!CheckDeviceExtensionSupported(phys_devices[i]))
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        rt_queue_indices indices = RetrieveQueueIndices(phys_devices[i], dev->surface);
 | 
				
			||||||
 | 
					        if (indices.compute == UINT32_MAX || indices.present == UINT32_MAX ||
 | 
				
			||||||
 | 
					            indices.graphics == UINT32_MAX)
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!synchronization2_features.synchronization2 ||
 | 
				
			||||||
 | 
					            !dynamic_rendering_features.dynamicRendering ||
 | 
				
			||||||
 | 
					            !timeline_semaphore_features.timelineSemaphore)
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Check for bindless support */
 | 
				
			||||||
 | 
					        if (!descriptor_indexing_features.runtimeDescriptorArray ||
 | 
				
			||||||
 | 
					            !descriptor_indexing_features.descriptorBindingPartiallyBound)
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        uint32_t score = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (props.properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
 | 
				
			||||||
 | 
					            score += 100;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        score += (props.properties.limits.maxFramebufferWidth / 100) *
 | 
				
			||||||
 | 
					                 (props.properties.limits.maxFramebufferHeight / 100);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        score +=
 | 
				
			||||||
 | 
					            (descriptor_indexing_props.shaderStorageBufferArrayNonUniformIndexingNative) ? 100 : 0;
 | 
				
			||||||
 | 
					        score +=
 | 
				
			||||||
 | 
					            (descriptor_indexing_props.shaderSampledImageArrayNonUniformIndexingNative) ? 100 : 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (score > highscore) {
 | 
				
			||||||
 | 
					            highscore  = score;
 | 
				
			||||||
 | 
					            best_index = i;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (strncmp(props.properties.deviceName,
 | 
				
			||||||
 | 
					                    r_VkPhysDeviceName.s,
 | 
				
			||||||
 | 
					                    VK_MAX_PHYSICAL_DEVICE_NAME_SIZE) == 0) {
 | 
				
			||||||
 | 
					            best_index = i;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (best_index < phys_device_count) {
 | 
				
			||||||
 | 
					        dev->phys_device = phys_devices[best_index];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        VkPhysicalDeviceDescriptorIndexingProperties descriptor_indexing_props = {
 | 
				
			||||||
 | 
					            .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES,
 | 
				
			||||||
 | 
					            .pNext = NULL,
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        VkPhysicalDeviceProperties2 props = {
 | 
				
			||||||
 | 
					            .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
 | 
				
			||||||
 | 
					            .pNext = &descriptor_indexing_props,
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        VkPhysicalDeviceDescriptorIndexingFeatures descriptor_indexing_features = {
 | 
				
			||||||
 | 
					            .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES,
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        VkPhysicalDeviceFeatures2 features = {
 | 
				
			||||||
 | 
					            .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
 | 
				
			||||||
 | 
					            .pNext = &descriptor_indexing_features,
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        vkGetPhysicalDeviceFeatures2(phys_devices[best_index], &features);
 | 
				
			||||||
 | 
					        vkGetPhysicalDeviceProperties2(phys_devices[best_index], &props);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        dev->phys_device_props            = props.properties;
 | 
				
			||||||
 | 
					        dev->descriptor_indexing_props    = descriptor_indexing_props;
 | 
				
			||||||
 | 
					        dev->phys_device_features         = features.features;
 | 
				
			||||||
 | 
					        dev->descriptor_indexing_features = descriptor_indexing_features;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    free(phys_devices);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (dev->phys_device == VK_NULL_HANDLE) {
 | 
				
			||||||
 | 
					        rtReportError("vk", "Failed to find a suitable physical device.");
 | 
				
			||||||
 | 
					        return 3;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return RT_SUCCESS;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static rt_result CreateDevice(rt_vk_device *dev) {
 | 
				
			||||||
 | 
					    const char *extensions[] = {
 | 
				
			||||||
 | 
					        VK_KHR_SWAPCHAIN_EXTENSION_NAME,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    rt_queue_indices queue_indices = RetrieveQueueIndices(dev->phys_device, dev->surface);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dev->compute_family  = queue_indices.compute;
 | 
				
			||||||
 | 
					    dev->graphics_family = queue_indices.graphics;
 | 
				
			||||||
 | 
					    dev->present_family  = queue_indices.present;
 | 
				
			||||||
 | 
					    dev->transfer_family = queue_indices.transfer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    float priority = 1.f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uint32_t distinct_queue_count = 1;
 | 
				
			||||||
 | 
					    VkDeviceQueueCreateInfo queue_info[4];
 | 
				
			||||||
 | 
					    queue_info[0].sType            = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
 | 
				
			||||||
 | 
					    queue_info[0].pNext            = NULL;
 | 
				
			||||||
 | 
					    queue_info[0].flags            = 0;
 | 
				
			||||||
 | 
					    queue_info[0].queueCount       = 1;
 | 
				
			||||||
 | 
					    queue_info[0].queueFamilyIndex = queue_indices.graphics;
 | 
				
			||||||
 | 
					    queue_info[0].pQueuePriorities = &priority;
 | 
				
			||||||
 | 
					    if (queue_indices.compute != queue_indices.graphics) {
 | 
				
			||||||
 | 
					        queue_info[1].sType            = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
 | 
				
			||||||
 | 
					        queue_info[1].pNext            = NULL;
 | 
				
			||||||
 | 
					        queue_info[1].flags            = 0;
 | 
				
			||||||
 | 
					        queue_info[1].queueCount       = 1;
 | 
				
			||||||
 | 
					        queue_info[1].queueFamilyIndex = queue_indices.compute;
 | 
				
			||||||
 | 
					        queue_info[1].pQueuePriorities = &priority;
 | 
				
			||||||
 | 
					        ++distinct_queue_count;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (queue_indices.present != queue_indices.graphics &&
 | 
				
			||||||
 | 
					        queue_indices.present != queue_indices.compute) {
 | 
				
			||||||
 | 
					        queue_info[distinct_queue_count].sType      = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
 | 
				
			||||||
 | 
					        queue_info[distinct_queue_count].pNext      = NULL;
 | 
				
			||||||
 | 
					        queue_info[distinct_queue_count].flags      = 0;
 | 
				
			||||||
 | 
					        queue_info[distinct_queue_count].queueCount = 1;
 | 
				
			||||||
 | 
					        queue_info[distinct_queue_count].queueFamilyIndex = queue_indices.present;
 | 
				
			||||||
 | 
					        queue_info[distinct_queue_count].pQueuePriorities = &priority;
 | 
				
			||||||
 | 
					        ++distinct_queue_count;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (queue_indices.transfer != queue_indices.graphics &&
 | 
				
			||||||
 | 
					        queue_indices.transfer != queue_indices.compute) {
 | 
				
			||||||
 | 
					        queue_info[distinct_queue_count].sType      = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
 | 
				
			||||||
 | 
					        queue_info[distinct_queue_count].pNext      = NULL;
 | 
				
			||||||
 | 
					        queue_info[distinct_queue_count].flags      = 0;
 | 
				
			||||||
 | 
					        queue_info[distinct_queue_count].queueCount = 1;
 | 
				
			||||||
 | 
					        queue_info[distinct_queue_count].queueFamilyIndex = queue_indices.transfer;
 | 
				
			||||||
 | 
					        queue_info[distinct_queue_count].pQueuePriorities = &priority;
 | 
				
			||||||
 | 
					        ++distinct_queue_count;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    VkPhysicalDeviceTimelineSemaphoreFeatures timeline_semaphore_features = {
 | 
				
			||||||
 | 
					        .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    VkPhysicalDeviceSynchronization2Features synchronization2_features = {
 | 
				
			||||||
 | 
					        .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES,
 | 
				
			||||||
 | 
					        .pNext = &timeline_semaphore_features,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    VkPhysicalDeviceDynamicRenderingFeatures dynamic_rendering_features = {
 | 
				
			||||||
 | 
					        .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES,
 | 
				
			||||||
 | 
					        .pNext = &synchronization2_features,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    VkPhysicalDeviceDescriptorIndexingFeatures indexing_features = {
 | 
				
			||||||
 | 
					        .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES,
 | 
				
			||||||
 | 
					        .pNext = &dynamic_rendering_features,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    VkPhysicalDeviceFeatures2 features = {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
 | 
				
			||||||
 | 
					                                          .pNext = &indexing_features};
 | 
				
			||||||
 | 
					    vkGetPhysicalDeviceFeatures2(dev->phys_device, &features);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    RT_ASSERT(indexing_features.runtimeDescriptorArray &&
 | 
				
			||||||
 | 
					                  indexing_features.descriptorBindingPartiallyBound,
 | 
				
			||||||
 | 
					              "We require a device that supports bindless vulkan.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    VkDeviceCreateInfo device_info = {
 | 
				
			||||||
 | 
					        .sType                   = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
 | 
				
			||||||
 | 
					        .pNext                   = &features,
 | 
				
			||||||
 | 
					        .enabledExtensionCount   = RT_ARRAY_COUNT(extensions),
 | 
				
			||||||
 | 
					        .ppEnabledExtensionNames = extensions,
 | 
				
			||||||
 | 
					        .pQueueCreateInfos       = queue_info,
 | 
				
			||||||
 | 
					        .queueCreateInfoCount    = distinct_queue_count,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    if (vkCreateDevice(dev->phys_device, &device_info, dev->alloc_cb, &dev->device) !=
 | 
				
			||||||
 | 
					        VK_SUCCESS) {
 | 
				
			||||||
 | 
					        rtReportError("VK", "Device creation failed.");
 | 
				
			||||||
 | 
					        return 10;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    vkGetDeviceQueue(dev->device, queue_indices.graphics, 0, &dev->graphics_queue);
 | 
				
			||||||
 | 
					    vkGetDeviceQueue(dev->device, queue_indices.compute, 0, &dev->compute_queue);
 | 
				
			||||||
 | 
					    vkGetDeviceQueue(dev->device, queue_indices.present, 0, &dev->present_queue);
 | 
				
			||||||
 | 
					    vkGetDeviceQueue(dev->device, queue_indices.transfer, 0, &dev->transfer_queue);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return RT_SUCCESS;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if 0
 | 
				
			||||||
 | 
					static rt_result CreateAllocator(rt_vk_device *dev) {
 | 
				
			||||||
 | 
					#define SET_FNC(name)     fncs.name = name
 | 
				
			||||||
 | 
					#define SET_KHR_FNC(name) (fncs).name##KHR = name
 | 
				
			||||||
 | 
					    VmaVulkanFunctions fncs                = {NULL};
 | 
				
			||||||
 | 
					    SET_FNC(vkGetInstanceProcAddr);
 | 
				
			||||||
 | 
					    SET_FNC(vkGetDeviceProcAddr);
 | 
				
			||||||
 | 
					    SET_FNC(vkGetPhysicalDeviceProperties);
 | 
				
			||||||
 | 
					    SET_FNC(vkGetPhysicalDeviceMemoryProperties);
 | 
				
			||||||
 | 
					    SET_FNC(vkAllocateMemory);
 | 
				
			||||||
 | 
					    SET_FNC(vkFreeMemory);
 | 
				
			||||||
 | 
					    SET_FNC(vkMapMemory);
 | 
				
			||||||
 | 
					    SET_FNC(vkUnmapMemory);
 | 
				
			||||||
 | 
					    SET_FNC(vkFlushMappedMemoryRanges);
 | 
				
			||||||
 | 
					    SET_FNC(vkInvalidateMappedMemoryRanges);
 | 
				
			||||||
 | 
					    SET_FNC(vkBindBufferMemory);
 | 
				
			||||||
 | 
					    SET_FNC(vkBindImageMemory);
 | 
				
			||||||
 | 
					    SET_FNC(vkGetBufferMemoryRequirements);
 | 
				
			||||||
 | 
					    SET_FNC(vkGetImageMemoryRequirements);
 | 
				
			||||||
 | 
					    SET_FNC(vkCreateBuffer);
 | 
				
			||||||
 | 
					    SET_FNC(vkDestroyBuffer);
 | 
				
			||||||
 | 
					    SET_FNC(vkCreateImage);
 | 
				
			||||||
 | 
					    SET_FNC(vkDestroyImage);
 | 
				
			||||||
 | 
					    SET_FNC(vkCmdCopyBuffer);
 | 
				
			||||||
 | 
					    SET_KHR_FNC(vkGetBufferMemoryRequirements2);
 | 
				
			||||||
 | 
					    SET_KHR_FNC(vkGetImageMemoryRequirements2);
 | 
				
			||||||
 | 
					    SET_KHR_FNC(vkBindBufferMemory2);
 | 
				
			||||||
 | 
					    SET_KHR_FNC(vkBindImageMemory2);
 | 
				
			||||||
 | 
					    SET_KHR_FNC(vkGetPhysicalDeviceMemoryProperties2);
 | 
				
			||||||
 | 
					    SET_FNC(vkGetDeviceBufferMemoryRequirements);
 | 
				
			||||||
 | 
					    SET_FNC(vkGetDeviceImageMemoryRequirements);
 | 
				
			||||||
 | 
					#undef SET_FNC
 | 
				
			||||||
 | 
					#undef SET_KHR_FNC
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    VmaAllocatorCreateInfo allocator_info = {
 | 
				
			||||||
 | 
					        .instance             = dev->instance,
 | 
				
			||||||
 | 
					        .physicalDevice       = dev->phys_device,
 | 
				
			||||||
 | 
					        .device               = dev->device,
 | 
				
			||||||
 | 
					        .pAllocationCallbacks = dev->alloc_cb,
 | 
				
			||||||
 | 
					        .vulkanApiVersion     = TARGET_API_VERSION,
 | 
				
			||||||
 | 
					        .pVulkanFunctions     = &fncs,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return vmaCreateAllocator(&allocator_info, &dev->allocator) == VK_SUCCESS ? RT_SUCCESS
 | 
				
			||||||
 | 
					                                                                               : RT_UNKNOWN_ERROR;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void DestroyAllocator(void) {
 | 
				
			||||||
 | 
					    vmaDestroyAllocator(dev->allocator);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static rt_result CreatePerFrameObjects(rt_vk_device *dev) {
 | 
				
			||||||
 | 
					    for (unsigned int i = 0; i < dev->max_frames_in_flight; ++i) {
 | 
				
			||||||
 | 
					        VkSemaphoreCreateInfo semaphore_info = {
 | 
				
			||||||
 | 
					            .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        if (vkCreateSemaphore(dev->device,
 | 
				
			||||||
 | 
					                              &semaphore_info,
 | 
				
			||||||
 | 
					                              dev->alloc_cb,
 | 
				
			||||||
 | 
					                              &dev->frames[i].render_finished) != VK_SUCCESS) {
 | 
				
			||||||
 | 
					            return RT_UNKNOWN_ERROR;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (vkCreateSemaphore(dev->device,
 | 
				
			||||||
 | 
					                              &semaphore_info,
 | 
				
			||||||
 | 
					                              dev->alloc_cb,
 | 
				
			||||||
 | 
					                              &dev->frames[i].image_available) != VK_SUCCESS) {
 | 
				
			||||||
 | 
					            return RT_UNKNOWN_ERROR;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (vkCreateSemaphore(dev->device,
 | 
				
			||||||
 | 
					                              &semaphore_info,
 | 
				
			||||||
 | 
					                              dev->alloc_cb,
 | 
				
			||||||
 | 
					                              &dev->frames[i].swapchain_transitioned) != VK_SUCCESS) {
 | 
				
			||||||
 | 
					            return RT_UNKNOWN_ERROR;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					#ifdef RT_DEBUG
 | 
				
			||||||
 | 
					        char name[128];
 | 
				
			||||||
 | 
					        rtSPrint(name, 128, "Render Finished Semaphore (%u)", i);
 | 
				
			||||||
 | 
					        VkDebugUtilsObjectNameInfoEXT name_info = {
 | 
				
			||||||
 | 
					            .sType        = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT,
 | 
				
			||||||
 | 
					            .objectHandle = (uint64_t)dev->frames[i].render_finished,
 | 
				
			||||||
 | 
					            .objectType   = VK_OBJECT_TYPE_SEMAPHORE,
 | 
				
			||||||
 | 
					            .pObjectName  = name,
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        vkSetDebugUtilsObjectNameEXT(dev->device, &name_info);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        rtSPrint(name, 128, "Image Available Semaphore (%u)", i);
 | 
				
			||||||
 | 
					        name_info.objectHandle = (uint64_t)dev->frames[i].image_available;
 | 
				
			||||||
 | 
					        vkSetDebugUtilsObjectNameEXT(dev->device, &name_info);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        rtSPrint(name, 128, "Swapchain Transitioned Semaphore (%u)", i);
 | 
				
			||||||
 | 
					        name_info.objectHandle = (uint64_t)dev->frames[i].swapchain_transitioned;
 | 
				
			||||||
 | 
					        vkSetDebugUtilsObjectNameEXT(dev->device, &name_info);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return RT_SUCCESS;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void DestroyPerFrameObjects(rt_vk_device *dev) {
 | 
				
			||||||
 | 
					    for (unsigned int i = 0; i < dev->max_frames_in_flight; ++i) {
 | 
				
			||||||
 | 
					        vkDestroySemaphore(dev->device, dev->frames[i].image_available, dev->alloc_cb);
 | 
				
			||||||
 | 
					        vkDestroySemaphore(dev->device, dev->frames[i].render_finished, dev->alloc_cb);
 | 
				
			||||||
 | 
					        vkDestroySemaphore(dev->device, dev->frames[i].swapchain_transitioned, dev->alloc_cb);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					rt_create_vk_device_result rtCreateVkDevice(const rt_renderer_window_info *info) {
 | 
				
			||||||
 | 
					    rtLog("vk", "Init");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    rt_vk_device dev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    _tracking_alloc_cbs.pUserData       = NULL;
 | 
				
			||||||
 | 
					    _tracking_alloc_cbs.pfnAllocation   = TrackAllocation;
 | 
				
			||||||
 | 
					    _tracking_alloc_cbs.pfnReallocation = TrackReallocation;
 | 
				
			||||||
 | 
					    _tracking_alloc_cbs.pfnFree         = TrackFree;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (r_VkEnableAPIAllocTracking.i) {
 | 
				
			||||||
 | 
					        dev.alloc_cb = &_tracking_alloc_cbs;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        dev.alloc_cb = NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    rt_result res;
 | 
				
			||||||
 | 
					    if ((res = CreateInstance(&dev)) != RT_SUCCESS)
 | 
				
			||||||
 | 
					        goto out;
 | 
				
			||||||
 | 
					    if ((res = CreateSurface(info, &dev)) != RT_SUCCESS)
 | 
				
			||||||
 | 
					        goto out;
 | 
				
			||||||
 | 
					    if ((res = ChoosePhysicalDevice(&dev)) != RT_SUCCESS)
 | 
				
			||||||
 | 
					        goto out;
 | 
				
			||||||
 | 
					    if ((res = CreateDevice(&dev)) != RT_SUCCESS)
 | 
				
			||||||
 | 
					        goto out;
 | 
				
			||||||
 | 
					    if ((res = CreatePerFrameObjects(&dev)) != RT_SUCCESS)
 | 
				
			||||||
 | 
					        goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					out:
 | 
				
			||||||
 | 
					    return (rt_create_vk_device_result) {.result = res, .device = dev};
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void rtDestroyVkDevice(rt_vk_device *dev) {
 | 
				
			||||||
 | 
					    rtLog("VK", "Shutdown");
 | 
				
			||||||
 | 
					    vkDeviceWaitIdle(dev->device);
 | 
				
			||||||
 | 
					    DestroyPerFrameObjects(dev);
 | 
				
			||||||
 | 
					    // DestroyAllocator();
 | 
				
			||||||
 | 
					    vkDestroyDevice(dev->device, dev->alloc_cb);
 | 
				
			||||||
 | 
					    vkDestroySurfaceKHR(dev->instance, dev->surface, dev->alloc_cb);
 | 
				
			||||||
 | 
					#ifdef RT_DEBUG
 | 
				
			||||||
 | 
					    vkDestroyDebugUtilsMessengerEXT(dev->instance, dev->messenger, dev->alloc_cb);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    vkDestroyInstance(dev->instance, dev->alloc_cb);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										79
									
								
								src/renderer/vk/device.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								src/renderer/vk/device.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,79 @@
 | 
				
			|||||||
 | 
					#ifndef RT_VK_DEVICE_H
 | 
				
			||||||
 | 
					#define RT_VK_DEVICE_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <volk/volk.h>
 | 
				
			||||||
 | 
					#include <runtime/runtime.h>
 | 
				
			||||||
 | 
					#include <renderer/renderer.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef _WIN32
 | 
				
			||||||
 | 
					struct HINSTANCE__;
 | 
				
			||||||
 | 
					struct HWND__;
 | 
				
			||||||
 | 
					#elif defined(RT_USE_XLIB)
 | 
				
			||||||
 | 
					struct _XDisplay;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
					#ifdef _WIN32
 | 
				
			||||||
 | 
					    struct HINSTANCE__ *hInstance;
 | 
				
			||||||
 | 
					    struct HWND__ *hWnd;
 | 
				
			||||||
 | 
					#elif defined(RT_USE_XLIB)
 | 
				
			||||||
 | 
					    struct _XDisplay *display;
 | 
				
			||||||
 | 
					    unsigned long window;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					} rt_vk_native_window;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
					    VkSemaphore render_finished;
 | 
				
			||||||
 | 
					    VkSemaphore image_available;
 | 
				
			||||||
 | 
					    VkSemaphore swapchain_transitioned;
 | 
				
			||||||
 | 
					} rt_vk_frame_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
					    /* *** Vulkan objects *** */
 | 
				
			||||||
 | 
					    VkInstance instance;
 | 
				
			||||||
 | 
					    VkDevice device;
 | 
				
			||||||
 | 
					    VkPhysicalDevice phys_device;
 | 
				
			||||||
 | 
					    VkAllocationCallbacks *alloc_cb;
 | 
				
			||||||
 | 
					    VkSurfaceKHR surface;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* *** Queues *** */
 | 
				
			||||||
 | 
					    uint32_t graphics_family;
 | 
				
			||||||
 | 
					    uint32_t compute_family;
 | 
				
			||||||
 | 
					    uint32_t transfer_family;
 | 
				
			||||||
 | 
					    uint32_t present_family;
 | 
				
			||||||
 | 
					    VkQueue graphics_queue;
 | 
				
			||||||
 | 
					    VkQueue compute_queue;
 | 
				
			||||||
 | 
					    VkQueue transfer_queue;
 | 
				
			||||||
 | 
					    VkQueue present_queue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* *** Properties and features *** */
 | 
				
			||||||
 | 
					    VkPhysicalDeviceDescriptorIndexingProperties descriptor_indexing_props;
 | 
				
			||||||
 | 
					    VkPhysicalDeviceDescriptorIndexingFeatures descriptor_indexing_features;
 | 
				
			||||||
 | 
					    VkPhysicalDeviceFeatures phys_device_features;
 | 
				
			||||||
 | 
					    VkPhysicalDeviceProperties phys_device_props;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* *** Per frame data *** */
 | 
				
			||||||
 | 
					    uint32_t max_frames_in_flight;
 | 
				
			||||||
 | 
					    rt_vk_frame_data frames[3];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* *** Windowing system *** */
 | 
				
			||||||
 | 
					    rt_vk_native_window native_window;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* *** Debug utils *** */
 | 
				
			||||||
 | 
					#ifdef RT_DEBUG
 | 
				
			||||||
 | 
					    VkDebugUtilsMessengerEXT messenger;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					} rt_vk_device;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
					    rt_result result;
 | 
				
			||||||
 | 
					    rt_vk_device device;
 | 
				
			||||||
 | 
					} rt_create_vk_device_result;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					rt_create_vk_device_result rtCreateVkDevice(const rt_renderer_window_info *info);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void rtDestroyVkDevice(rt_vk_device *dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1,14 +1,51 @@
 | 
				
			|||||||
#include "renderer/backend_api.h"
 | 
					#include <renderer/backend_api.h>
 | 
				
			||||||
 | 
					#include <runtime/runtime.h>
 | 
				
			||||||
 | 
					#include <runtime/config.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "device.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern rt_cvar r_VkEnableAPIAllocTracking;
 | 
				
			||||||
 | 
					extern rt_cvar r_VkPhysDeviceName;
 | 
				
			||||||
 | 
					extern rt_cvar r_VkMaxFramesInFlight;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if 0
 | 
				
			||||||
 | 
					extern rt_cvar r_VkPreferredSwapchainImages;
 | 
				
			||||||
 | 
					extern rt_cvar r_VkPreferMailboxMode;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void VkRegisterCVARs(void) {
 | 
					void VkRegisterCVARs(void) {
 | 
				
			||||||
    
 | 
					    rtRegisterCVAR(&r_VkEnableAPIAllocTracking);
 | 
				
			||||||
 | 
					    rtRegisterCVAR(&r_VkPhysDeviceName);
 | 
				
			||||||
 | 
					    rtRegisterCVAR(&r_VkMaxFramesInFlight);
 | 
				
			||||||
 | 
					#if 0
 | 
				
			||||||
 | 
					    rtRegisterCVAR(&r_VkPreferredSwapchainImages);
 | 
				
			||||||
 | 
					    rtRegisterCVAR(&r_VkPreferMailboxMode);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
rt_result VkInit(const rt_renderer_init_info *info) {
 | 
					static rt_vk_device _device;
 | 
				
			||||||
    return RT_SUCCESS;
 | 
					
 | 
				
			||||||
 | 
					rt_render_backend_init_result VkInit(const rt_renderer_window_info *info) {
 | 
				
			||||||
 | 
					    rt_render_backend_init_result res = {.result = RT_SUCCESS};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    rt_create_vk_device_result device_result = rtCreateVkDevice(info);
 | 
				
			||||||
 | 
					    if (device_result.result != RT_SUCCESS) {
 | 
				
			||||||
 | 
					        res.result = device_result.result;
 | 
				
			||||||
 | 
					        return res;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    /* Populate the device interface */
 | 
				
			||||||
 | 
					    _device = device_result.device;
 | 
				
			||||||
 | 
					    rt_render_device_i device_i = {
 | 
				
			||||||
 | 
					        .o =  &_device,
 | 
				
			||||||
 | 
					        .GetPhysicalResourceManager =  NULL
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    res.device = device_i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return res;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void VkShutdown(void) {
 | 
					void VkShutdown(void) {
 | 
				
			||||||
 | 
					    rtDestroyVkDevice(&_device);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Called by the application to retrieve the renderer api
 | 
					// Called by the application to retrieve the renderer api
 | 
				
			||||||
 | 
				
			|||||||
@ -3,19 +3,29 @@ if get_option('build_vk')
 | 
				
			|||||||
  vma_dep = vma_proj.get_variable('vma_allocator_dep')
 | 
					  vma_dep = vma_proj.get_variable('vma_allocator_dep')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  vk_inc_proj = subproject('vulkan-headers')
 | 
					  vk_inc_proj = subproject('vulkan-headers')
 | 
				
			||||||
  vk_inc_dep = vk_inc_proj.get_variable('vulkan_headers_dep')  
 | 
					  vk_inc_dep = vk_inc_proj.get_variable('vulkan_headers_dep')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  platform_defs = []
 | 
				
			||||||
 | 
					  if get_option('use_xlib')
 | 
				
			||||||
 | 
					    platform_defs = ['-DVK_USE_PLATFORM_XLIB_KHR']
 | 
				
			||||||
 | 
					  elif host_machine.system() == 'windows'
 | 
				
			||||||
 | 
					    platform_defs = ['-DVK_USE_PLATFORM_WIN32_KHR']
 | 
				
			||||||
 | 
					  endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  vk_renderer_lib = library('rtvk',
 | 
					  vk_renderer_lib = library('rtvk',
 | 
				
			||||||
 | 
					    'device.h',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    'device.c',
 | 
				
			||||||
    'init.c',
 | 
					    'init.c',
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    '../../../contrib/volk/volk.c',
 | 
					    '../../../contrib/volk/volk.c',
 | 
				
			||||||
    '../../../contrib/volk/volk.h',
 | 
					    '../../../contrib/volk/volk.h',
 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    dependencies: [m_dep, vk_inc_dep, vma_dep, thread_dep],
 | 
					    dependencies: [m_dep, vk_inc_dep, vma_dep, thread_dep],
 | 
				
			||||||
    include_directories: [engine_incdir, contrib_incdir],
 | 
					    include_directories: [engine_incdir, contrib_incdir],
 | 
				
			||||||
    link_with: [runtime_lib],
 | 
					    link_with: [runtime_lib],
 | 
				
			||||||
    cpp_pch: 'pch/vk_pch.h',
 | 
					    c_pch: 'pch/vk_pch.h',
 | 
				
			||||||
    override_options: ['b_sanitize=none'],
 | 
					    c_args: platform_defs,
 | 
				
			||||||
    install: true)
 | 
					    install: true)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  engine_libs += vk_renderer_lib
 | 
					  engine_libs += vk_renderer_lib
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user