mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-13 08:27:39 +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 (vkEnumeratePhysicalDevices)
|
||||||
INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceProperties)
|
INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceProperties)
|
||||||
INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceFeatures)
|
INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceFeatures)
|
||||||
|
INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceQueueFamilyProperties)
|
||||||
INSTANCE_LEVEL_VULKAN_FUNCTION (vkCreateDevice)
|
INSTANCE_LEVEL_VULKAN_FUNCTION (vkCreateDevice)
|
||||||
INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetDeviceProcAddr)
|
INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetDeviceProcAddr)
|
||||||
|
INSTANCE_LEVEL_VULKAN_FUNCTION (vkDestroyInstance)
|
||||||
INSTANCE_LEVEL_VULKAN_FUNCTION (vkEnumerateDeviceLayerProperties)
|
INSTANCE_LEVEL_VULKAN_FUNCTION (vkEnumerateDeviceLayerProperties)
|
||||||
INSTANCE_LEVEL_VULKAN_FUNCTION (vkEnumerateDeviceExtensionProperties)
|
INSTANCE_LEVEL_VULKAN_FUNCTION (vkEnumerateDeviceExtensionProperties)
|
||||||
INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceMemoryProperties)
|
INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceMemoryProperties)
|
||||||
INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceQueueFamilyProperties)
|
|
||||||
INSTANCE_LEVEL_VULKAN_FUNCTION (vkDestroyInstance)
|
|
||||||
|
|
||||||
#undef INSTANCE_LEVEL_VULKAN_FUNCTION
|
#undef INSTANCE_LEVEL_VULKAN_FUNCTION
|
||||||
|
|
||||||
|
@ -46,6 +46,8 @@ INSTANCE_LEVEL_VULKAN_FUNCTION_EXTENSION (vkCreateDebugUtilsMessengerEXT)
|
||||||
#define DEVICE_LEVEL_VULKAN_FUNCTION(function)
|
#define DEVICE_LEVEL_VULKAN_FUNCTION(function)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
DEVICE_LEVEL_VULKAN_FUNCTION (vkGetDeviceQueue)
|
||||||
|
|
||||||
#undef DEVICE_LEVEL_VULKAN_FUNCTION
|
#undef DEVICE_LEVEL_VULKAN_FUNCTION
|
||||||
|
|
||||||
#ifndef DEVICE_LEVEL_VULKAN_FUNCTION_EXTENSION
|
#ifndef DEVICE_LEVEL_VULKAN_FUNCTION_EXTENSION
|
||||||
|
|
|
@ -31,14 +31,23 @@
|
||||||
#include "QF/qtypes.h"
|
#include "QF/qtypes.h"
|
||||||
#include "QF/Vulkan/funcs.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 {
|
typedef struct {
|
||||||
VkPhysicalDevice device;
|
VkPhysicalDevice device;
|
||||||
|
VkPhysicalDeviceFeatures features;
|
||||||
VkPhysicalDeviceProperties properties;
|
VkPhysicalDeviceProperties properties;
|
||||||
uint32_t numLayers;
|
uint32_t numLayers;
|
||||||
VkLayerProperties *layers;
|
VkLayerProperties *layers;
|
||||||
uint32_t numExtensions;
|
uint32_t numExtensions;
|
||||||
VkExtensionProperties *extensions;
|
VkExtensionProperties *extensions;
|
||||||
VkPhysicalDeviceFeatures features;
|
|
||||||
VkPhysicalDeviceMemoryProperties memory;
|
VkPhysicalDeviceMemoryProperties memory;
|
||||||
uint32_t numQueueFamilies;
|
uint32_t numQueueFamilies;
|
||||||
VkQueueFamilyProperties *queueFamilies;
|
VkQueueFamilyProperties *queueFamilies;
|
||||||
|
@ -61,5 +70,8 @@ VulkanInstance_t *Vulkan_CreateInstance (const char *appName,
|
||||||
const char **layers,
|
const char **layers,
|
||||||
const char **extensions);
|
const char **extensions);
|
||||||
void Vulkan_DestroyInstance (VulkanInstance_t *instance);
|
void Vulkan_DestroyInstance (VulkanInstance_t *instance);
|
||||||
|
int Vulkan_ExtensionsSupported (const VkExtensionProperties *extensions,
|
||||||
|
int numExtensions,
|
||||||
|
const char * const *requested);
|
||||||
|
|
||||||
#endif // __QF_Vulkan_init_h
|
#endif // __QF_Vulkan_init_h
|
||||||
|
|
|
@ -388,3 +388,23 @@ Vulkan_DestroyInstance (VulkanInstance_t *instance)
|
||||||
instance->vkDestroyInstance (instance->instance, 0);
|
instance->vkDestroyInstance (instance->instance, 0);
|
||||||
free (instance);
|
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 void *vulkan_library;
|
||||||
|
|
||||||
static VulkanInstance_t *vulkan_instance;
|
static VulkanInstance_t *vulkan_instance;
|
||||||
|
static VulkanDevice_t *vulkan_device;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
load_vulkan_library (void)
|
load_vulkan_library (void)
|
||||||
|
@ -102,21 +103,117 @@ Vulkan_Init_Cvars ()
|
||||||
"restart).");
|
"restart).");
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *extensions[] = {
|
static const char *instance_extensions[] = {
|
||||||
"foo",
|
|
||||||
0,
|
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
|
void
|
||||||
Vulkan_Init_Common (void)
|
Vulkan_Init_Common (void)
|
||||||
{
|
{
|
||||||
|
Sys_Printf ("Vulkan_Init_Common\n");
|
||||||
Vulkan_Init_Cvars ();
|
Vulkan_Init_Cvars ();
|
||||||
|
|
||||||
load_vulkan_library ();
|
load_vulkan_library ();
|
||||||
|
|
||||||
vulkan_instance = Vulkan_CreateInstance (PACKAGE_STRING, 0x000702ff, 0, extensions);//FIXME version
|
vulkan_instance = Vulkan_CreateInstance (PACKAGE_STRING, 0x000702ff, 0, instance_extensions);//FIXME version
|
||||||
Sys_Printf ("Vulkan_Init_Common\n");
|
vulkan_device = create_suitable_device (vulkan_instance);
|
||||||
|
if (!vulkan_device) {
|
||||||
|
Sys_Error ("no suitable vulkan device found");
|
||||||
|
}
|
||||||
if (developer->int_val & SYS_VID) {
|
if (developer->int_val & SYS_VID) {
|
||||||
|
Sys_Printf ("%p %p\n", vulkan_device->device, vulkan_device->queue);
|
||||||
Vulkan_DestroyInstance (vulkan_instance);
|
Vulkan_DestroyInstance (vulkan_instance);
|
||||||
Sys_Quit();
|
Sys_Quit();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue