mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-25 22:01:33 +00:00
Create a logical device with a single queue
A single graphics-capable queue should be enough for now. However, I'm not sure I'm happy with a lot of the code: it's a bit difficult to write flexibly configured code for Vulkan (or seems to be at this stage), especially in C.
This commit is contained in:
parent
2bc78e7f0a
commit
ab08e4f207
4 changed files with 138 additions and 7 deletions
|
@ -24,13 +24,13 @@ GLOBAL_LEVEL_VULKAN_FUNCTION (vkCreateInstance)
|
|||
INSTANCE_LEVEL_VULKAN_FUNCTION (vkEnumeratePhysicalDevices)
|
||||
INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceProperties)
|
||||
INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceFeatures)
|
||||
INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceQueueFamilyProperties)
|
||||
INSTANCE_LEVEL_VULKAN_FUNCTION (vkCreateDevice)
|
||||
INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetDeviceProcAddr)
|
||||
INSTANCE_LEVEL_VULKAN_FUNCTION (vkDestroyInstance)
|
||||
INSTANCE_LEVEL_VULKAN_FUNCTION (vkEnumerateDeviceLayerProperties)
|
||||
INSTANCE_LEVEL_VULKAN_FUNCTION (vkEnumerateDeviceExtensionProperties)
|
||||
INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceMemoryProperties)
|
||||
INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceQueueFamilyProperties)
|
||||
INSTANCE_LEVEL_VULKAN_FUNCTION (vkDestroyInstance)
|
||||
|
||||
#undef INSTANCE_LEVEL_VULKAN_FUNCTION
|
||||
|
||||
|
@ -46,6 +46,8 @@ INSTANCE_LEVEL_VULKAN_FUNCTION_EXTENSION (vkCreateDebugUtilsMessengerEXT)
|
|||
#define DEVICE_LEVEL_VULKAN_FUNCTION(function)
|
||||
#endif
|
||||
|
||||
DEVICE_LEVEL_VULKAN_FUNCTION (vkGetDeviceQueue)
|
||||
|
||||
#undef DEVICE_LEVEL_VULKAN_FUNCTION
|
||||
|
||||
#ifndef DEVICE_LEVEL_VULKAN_FUNCTION_EXTENSION
|
||||
|
|
|
@ -31,14 +31,23 @@
|
|||
#include "QF/qtypes.h"
|
||||
#include "QF/Vulkan/funcs.h"
|
||||
|
||||
typedef struct {
|
||||
VkDevice device;
|
||||
VkQueue queue;
|
||||
|
||||
#define DEVICE_LEVEL_VULKAN_FUNCTION(name) PFN_##name name;
|
||||
#define DEVICE_LEVEL_VULKAN_FUNCTION_EXTENSION(name) PFN_##name name;
|
||||
#include "QF/Vulkan/funclist.h"
|
||||
} VulkanDevice_t;
|
||||
|
||||
typedef struct {
|
||||
VkPhysicalDevice device;
|
||||
VkPhysicalDeviceFeatures features;
|
||||
VkPhysicalDeviceProperties properties;
|
||||
uint32_t numLayers;
|
||||
VkLayerProperties *layers;
|
||||
uint32_t numExtensions;
|
||||
VkExtensionProperties *extensions;
|
||||
VkPhysicalDeviceFeatures features;
|
||||
VkPhysicalDeviceMemoryProperties memory;
|
||||
uint32_t numQueueFamilies;
|
||||
VkQueueFamilyProperties *queueFamilies;
|
||||
|
@ -61,5 +70,8 @@ VulkanInstance_t *Vulkan_CreateInstance (const char *appName,
|
|||
const char **layers,
|
||||
const char **extensions);
|
||||
void Vulkan_DestroyInstance (VulkanInstance_t *instance);
|
||||
int Vulkan_ExtensionsSupported (const VkExtensionProperties *extensions,
|
||||
int numExtensions,
|
||||
const char * const *requested);
|
||||
|
||||
#endif // __QF_Vulkan_init_h
|
||||
|
|
|
@ -388,3 +388,23 @@ Vulkan_DestroyInstance (VulkanInstance_t *instance)
|
|||
instance->vkDestroyInstance (instance->instance, 0);
|
||||
free (instance);
|
||||
}
|
||||
|
||||
int
|
||||
Vulkan_ExtensionsSupported (const VkExtensionProperties *extensions,
|
||||
int numExtensions,
|
||||
const char * const *requested)
|
||||
{
|
||||
while (*requested) {
|
||||
int i;
|
||||
for (i = 0; i < numExtensions; i++) {
|
||||
if (!strcmp (*requested, extensions[i].extensionName)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < numExtensions) {
|
||||
// requested extension not found
|
||||
break;
|
||||
}
|
||||
}
|
||||
return !*requested;
|
||||
}
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
static void *vulkan_library;
|
||||
|
||||
static VulkanInstance_t *vulkan_instance;
|
||||
static VulkanDevice_t *vulkan_device;
|
||||
|
||||
static void
|
||||
load_vulkan_library (void)
|
||||
|
@ -102,21 +103,117 @@ Vulkan_Init_Cvars ()
|
|||
"restart).");
|
||||
}
|
||||
|
||||
const char *extensions[] = {
|
||||
"foo",
|
||||
static const char *instance_extensions[] = {
|
||||
0,
|
||||
};
|
||||
|
||||
static const char *device_extensions[] = {
|
||||
0,
|
||||
};
|
||||
|
||||
static int
|
||||
count_bits (uint32_t val)
|
||||
{
|
||||
int bits = 0;
|
||||
while (val) {
|
||||
bits += val & 1;
|
||||
val >>= 1;
|
||||
}
|
||||
return bits;
|
||||
}
|
||||
|
||||
static int
|
||||
find_queue_family (VulkanPhysDevice_t *dev, uint32_t flags)
|
||||
{
|
||||
int best_diff = 32;
|
||||
uint32_t family = -1;
|
||||
|
||||
for (uint32_t i = 0; i < dev->numQueueFamilies; i++) {
|
||||
VkQueueFamilyProperties *queue = &dev->queueFamilies[i];
|
||||
|
||||
if ((queue->queueFlags & flags) == flags) {
|
||||
int diff = count_bits (queue->queueFlags & ~flags);
|
||||
if (diff < best_diff) {
|
||||
best_diff = diff;
|
||||
family = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return family;
|
||||
}
|
||||
|
||||
static void
|
||||
load_device_funcs (VulkanInstance_t *inst, VulkanDevice_t *dev)
|
||||
{
|
||||
#define DEVICE_LEVEL_VULKAN_FUNCTION(name) \
|
||||
dev->name = (PFN_##name) inst->vkGetDeviceProcAddr (dev->device, #name); \
|
||||
if (!dev->name) { \
|
||||
Sys_Error ("Couldn't find device level function %s", #name); \
|
||||
}
|
||||
|
||||
#define DEVICE_LEVEL_VULKAN_FUNCTION_EXTENSION(name) \
|
||||
dev->name = (PFN_##name) inst->vkGetDeviceProcAddr (dev->device, #name); \
|
||||
if (!dev->name) { \
|
||||
Sys_Printf ("Couldn't find device level function %s", #name); \
|
||||
}
|
||||
|
||||
#include "QF/Vulkan/funclist.h"
|
||||
}
|
||||
|
||||
static VulkanDevice_t *
|
||||
create_suitable_device (VulkanInstance_t *instance)
|
||||
{
|
||||
for (uint32_t i = 0; i < instance->numDevices; i++) {
|
||||
VulkanPhysDevice_t *phys = &instance->devices[i];
|
||||
if (!Vulkan_ExtensionsSupported (phys->extensions, phys->numExtensions,
|
||||
device_extensions)) {
|
||||
return 0;
|
||||
}
|
||||
int family = find_queue_family (phys, VK_QUEUE_GRAPHICS_BIT);
|
||||
if (family < 0) {
|
||||
return 0;
|
||||
}
|
||||
float priority = 1;
|
||||
VkDeviceQueueCreateInfo qCreateInfo = {
|
||||
VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, 0, 0,
|
||||
family, 1, &priority
|
||||
};
|
||||
VkPhysicalDeviceFeatures features;
|
||||
VkDeviceCreateInfo dCreateInfo = {
|
||||
VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, 0, 0,
|
||||
1, &qCreateInfo,
|
||||
0, 0,
|
||||
0, device_extensions,
|
||||
&features
|
||||
};
|
||||
memset (&features, 0, sizeof (features));
|
||||
VulkanDevice_t *device = calloc (1, sizeof (VulkanDevice_t));
|
||||
if (instance->vkCreateDevice (phys->device, &dCreateInfo, 0,
|
||||
&device->device) == VK_SUCCESS) {
|
||||
load_device_funcs (instance, device);
|
||||
device->vkGetDeviceQueue (device->device, family,
|
||||
0, &device->queue);
|
||||
return device;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
Vulkan_Init_Common (void)
|
||||
{
|
||||
Sys_Printf ("Vulkan_Init_Common\n");
|
||||
Vulkan_Init_Cvars ();
|
||||
|
||||
load_vulkan_library ();
|
||||
|
||||
vulkan_instance = Vulkan_CreateInstance (PACKAGE_STRING, 0x000702ff, 0, extensions);//FIXME version
|
||||
Sys_Printf ("Vulkan_Init_Common\n");
|
||||
vulkan_instance = Vulkan_CreateInstance (PACKAGE_STRING, 0x000702ff, 0, instance_extensions);//FIXME version
|
||||
vulkan_device = create_suitable_device (vulkan_instance);
|
||||
if (!vulkan_device) {
|
||||
Sys_Error ("no suitable vulkan device found");
|
||||
}
|
||||
if (developer->int_val & SYS_VID) {
|
||||
Sys_Printf ("%p %p\n", vulkan_device->device, vulkan_device->queue);
|
||||
Vulkan_DestroyInstance (vulkan_instance);
|
||||
Sys_Quit();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue