mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-01-18 15:01:41 +00:00
Create a window and a surface for vulkan
Yay, segfaults in R_Init :)
This commit is contained in:
parent
0f511e8342
commit
68449d0f6f
9 changed files with 180 additions and 77 deletions
|
@ -30,9 +30,10 @@
|
|||
|
||||
#include "QF/qtypes.h"
|
||||
|
||||
typedef struct {
|
||||
typedef struct VulkanDevice_s {
|
||||
VkDevice device;
|
||||
VkQueue queue;
|
||||
VkSurfaceKHR surface;
|
||||
|
||||
#define DEVICE_LEVEL_VULKAN_FUNCTION(name) PFN_##name name;
|
||||
#define DEVICE_LEVEL_VULKAN_FUNCTION_EXTENSION(name) PFN_##name name;
|
||||
|
@ -63,6 +64,8 @@ typedef struct VulkanInstance_s {
|
|||
#include "QF/Vulkan/funclist.h"
|
||||
} VulkanInstance_t;
|
||||
|
||||
extern const char * const vulkanValidationLayers[];
|
||||
|
||||
void Vulkan_Init_Cvars (void);
|
||||
struct vulkan_ctx_s;
|
||||
VulkanInstance_t *Vulkan_CreateInstance (struct vulkan_ctx_s *ctx,
|
||||
|
@ -74,5 +77,8 @@ void Vulkan_DestroyInstance (VulkanInstance_t *instance);
|
|||
int Vulkan_ExtensionsSupported (const VkExtensionProperties *extensions,
|
||||
int numExtensions,
|
||||
const char * const *requested);
|
||||
int Vulkan_LayersSupported (const VkLayerProperties *extensions,
|
||||
int numLayers,
|
||||
const char * const *requested);
|
||||
|
||||
#endif // __QF_Vulkan_init_h
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "QF/Vulkan/cvars.h"
|
||||
|
||||
struct vulkan_ctx_s;
|
||||
void Vulkan_CreateDevice (struct vulkan_ctx_s *ctx);
|
||||
void Vulkan_Init_Common (struct vulkan_ctx_s *ctx);
|
||||
void Vulkan_Shutdown_Common (struct vulkan_ctx_s *ctx);
|
||||
|
||||
|
|
|
@ -15,10 +15,14 @@ typedef struct vulkan_ctx_s {
|
|||
int (*get_presentation_support) (struct vulkan_ctx_s *ctx,
|
||||
VkPhysicalDevice physicalDevice,
|
||||
uint32_t queueFamilyIndex);
|
||||
void (*choose_visual) (struct vulkan_ctx_s *ctx);
|
||||
void (*create_window) (struct vulkan_ctx_s *ctx);
|
||||
VkSurfaceKHR (*create_surface) (struct vulkan_ctx_s *ctx);
|
||||
|
||||
struct VulkanInstance_s *vtx;
|
||||
struct VulkanDevice_s *dev;
|
||||
VkInstance instance;
|
||||
VkDevice device;
|
||||
#define EXPORTED_VULKAN_FUNCTION(fname) PFN_##fname fname;
|
||||
#define GLOBAL_LEVEL_VULKAN_FUNCTION(fname) PFN_##fname fname;
|
||||
#include "QF/Vulkan/funclist.h"
|
||||
|
|
|
@ -31,10 +31,13 @@
|
|||
#define NH_DEFINE
|
||||
#include "vulkan/namehack.h"
|
||||
|
||||
#include "QF/sys.h"
|
||||
|
||||
#include "QF/plugin/general.h"
|
||||
#include "QF/plugin/vid_render.h"
|
||||
|
||||
#include "QF/Vulkan/qf_vid.h"
|
||||
#include "QF/Vulkan/init.h"
|
||||
|
||||
#include "mod_internal.h"
|
||||
#include "r_internal.h"
|
||||
|
@ -138,13 +141,16 @@ set_palette (const byte *palette)
|
|||
static void
|
||||
vulkan_vid_render_choose_visual (void)
|
||||
{
|
||||
//vulkan_ctx->coose_visual (vulkan_ctx);
|
||||
Vulkan_CreateDevice (vulkan_ctx);
|
||||
vulkan_ctx->choose_visual (vulkan_ctx);
|
||||
Sys_Printf ("%p %p\n", vulkan_ctx->dev->device, vulkan_ctx->dev->queue);
|
||||
}
|
||||
|
||||
static void
|
||||
vulkan_vid_render_create_context (void)
|
||||
{
|
||||
vulkan_ctx->create_surface (vulkan_ctx);
|
||||
vulkan_ctx->create_window (vulkan_ctx);
|
||||
vulkan_ctx->dev->surface = vulkan_ctx->create_surface (vulkan_ctx);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -56,17 +56,17 @@ static uint32_t numExtensions;
|
|||
static VkExtensionProperties *instanceExtensionProperties;
|
||||
static const char **instanceExtensionNames;
|
||||
|
||||
static const char *validationLayers[] = {
|
||||
const char * const vulkanValidationLayers[] = {
|
||||
"VK_LAYER_LUNARG_standard_validation",
|
||||
0,
|
||||
};
|
||||
|
||||
static const char *debugExtensions[] = {
|
||||
static const char * const debugExtensions[] = {
|
||||
VK_EXT_DEBUG_UTILS_EXTENSION_NAME,
|
||||
0,
|
||||
};
|
||||
|
||||
static const char *device_types[] = {
|
||||
static const char * const device_types[] = {
|
||||
"other",
|
||||
"integrated gpu",
|
||||
"discrete gpu",
|
||||
|
@ -278,28 +278,30 @@ Vulkan_CreateInstance (vulkan_ctx_t *ctx,
|
|||
get_instance_layers_and_extensions (ctx);
|
||||
}
|
||||
|
||||
createInfo.enabledLayerCount = count_strings (layers);
|
||||
createInfo.ppEnabledLayerNames = layers;
|
||||
createInfo.enabledExtensionCount = count_strings (extensions);
|
||||
createInfo.ppEnabledExtensionNames = extensions;
|
||||
uint32_t nlay = count_strings (layers);
|
||||
uint32_t next = count_strings (extensions)
|
||||
+ count_strings (ctx->required_extensions);
|
||||
if (vulkan_use_validation->int_val) {
|
||||
createInfo.enabledLayerCount += count_strings (validationLayers);
|
||||
createInfo.enabledExtensionCount += count_strings (debugExtensions);
|
||||
nlay += count_strings (vulkanValidationLayers);
|
||||
next += count_strings (debugExtensions);
|
||||
}
|
||||
const char **lay = alloca (createInfo.enabledLayerCount * sizeof (const char *));
|
||||
const char **ext = alloca (createInfo.enabledExtensionCount * sizeof (const char *));
|
||||
const char **lay = alloca (nlay * sizeof (const char *));
|
||||
const char **ext = alloca (next * sizeof (const char *));
|
||||
// ensure there are null pointers so merge_strings can act as append
|
||||
// since it does not add a null
|
||||
memset (lay, 0, nlay * sizeof (const char *));
|
||||
memset (ext, 0, next * sizeof (const char *));
|
||||
merge_strings (lay, layers, 0);
|
||||
merge_strings (ext, extensions, ctx->required_extensions);
|
||||
if (vulkan_use_validation->int_val) {
|
||||
merge_strings (lay, layers, validationLayers);
|
||||
merge_strings (ext, extensions, debugExtensions);
|
||||
} else {
|
||||
merge_strings (lay, layers, 0);
|
||||
merge_strings (ext, extensions, 0);
|
||||
merge_strings (lay, lay, vulkanValidationLayers);
|
||||
merge_strings (ext, ext, debugExtensions);
|
||||
}
|
||||
prune_strings (instanceLayerNames, lay,
|
||||
&createInfo.enabledLayerCount);
|
||||
prune_strings (instanceExtensionNames, ext,
|
||||
&createInfo.enabledExtensionCount);
|
||||
prune_strings (instanceLayerNames, lay, &nlay);
|
||||
prune_strings (instanceExtensionNames, ext, &next);
|
||||
createInfo.enabledLayerCount = nlay;
|
||||
createInfo.ppEnabledLayerNames = lay;
|
||||
createInfo.enabledExtensionCount = next;
|
||||
createInfo.ppEnabledExtensionNames = ext;
|
||||
|
||||
res = ctx->vkCreateInstance (&createInfo, 0, &instance);
|
||||
|
@ -348,6 +350,27 @@ Vulkan_DestroyInstance (VulkanInstance_t *instance)
|
|||
free (instance);
|
||||
}
|
||||
|
||||
int
|
||||
Vulkan_LayersSupported (const VkLayerProperties *layers,
|
||||
int numLayers,
|
||||
const char * const *requested)
|
||||
{
|
||||
while (*requested) {
|
||||
int i;
|
||||
for (i = 0; i < numLayers; i++) {
|
||||
if (!strcmp (*requested, layers[i].layerName)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == numLayers) {
|
||||
// requested layer not found
|
||||
break;
|
||||
}
|
||||
requested++;
|
||||
}
|
||||
return !*requested;
|
||||
}
|
||||
|
||||
int
|
||||
Vulkan_ExtensionsSupported (const VkExtensionProperties *extensions,
|
||||
int numExtensions,
|
||||
|
@ -360,10 +383,11 @@ Vulkan_ExtensionsSupported (const VkExtensionProperties *extensions,
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (i < numExtensions) {
|
||||
if (i == numExtensions) {
|
||||
// requested extension not found
|
||||
break;
|
||||
}
|
||||
requested++;
|
||||
}
|
||||
return !*requested;
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
#include "util.h"
|
||||
|
||||
int
|
||||
count_strings (const char **str)
|
||||
count_strings (const char * const *str)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
|
@ -49,7 +49,8 @@ count_strings (const char **str)
|
|||
}
|
||||
|
||||
void
|
||||
merge_strings (const char **out, const char **in1, const char **in2)
|
||||
merge_strings (const char **out, const char * const *in1,
|
||||
const char * const *in2)
|
||||
{
|
||||
if (in1) {
|
||||
while (*in1) {
|
||||
|
|
|
@ -2,8 +2,10 @@
|
|||
#define __util_h
|
||||
|
||||
#include <stdint.h>
|
||||
int count_strings (const char **str);
|
||||
void merge_strings (const char **out, const char **in1, const char **in2);
|
||||
void prune_strings (const char * const *reference, const char **strings, uint32_t *count);
|
||||
int count_strings (const char * const *str);
|
||||
void merge_strings (const char **out, const char * const *in1,
|
||||
const char * const *in2);
|
||||
void prune_strings (const char * const *reference, const char **strings,
|
||||
uint32_t *count);
|
||||
|
||||
#endif//__util_h
|
||||
|
|
|
@ -55,8 +55,7 @@
|
|||
#include "r_internal.h"
|
||||
#include "vid_vulkan.h"
|
||||
|
||||
static VulkanInstance_t *vulkan_instance;
|
||||
static VulkanDevice_t *vulkan_device;
|
||||
#include "util.h"
|
||||
|
||||
void
|
||||
Vulkan_Init_Cvars ()
|
||||
|
@ -74,6 +73,7 @@ static const char *instance_extensions[] = {
|
|||
};
|
||||
|
||||
static const char *device_extensions[] = {
|
||||
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
|
||||
0,
|
||||
};
|
||||
|
||||
|
@ -126,18 +126,61 @@ load_device_funcs (VulkanInstance_t *inst, VulkanDevice_t *dev)
|
|||
#include "QF/Vulkan/funclist.h"
|
||||
}
|
||||
|
||||
static VulkanDevice_t *
|
||||
create_suitable_device (VulkanInstance_t *instance)
|
||||
void
|
||||
Vulkan_Init_Common (vulkan_ctx_t *ctx)
|
||||
{
|
||||
for (uint32_t i = 0; i < instance->numDevices; i++) {
|
||||
VulkanPhysDevice_t *phys = &instance->devices[i];
|
||||
Sys_Printf ("Vulkan_Init_Common\n");
|
||||
Vulkan_Init_Cvars ();
|
||||
|
||||
ctx->vtx = Vulkan_CreateInstance (ctx, PACKAGE_STRING, 0x000702ff, 0, instance_extensions);//FIXME version
|
||||
ctx->instance = ctx->vtx->instance;
|
||||
}
|
||||
|
||||
void
|
||||
Vulkan_Shutdown_Common (vulkan_ctx_t *ctx)
|
||||
{
|
||||
Vulkan_DestroyInstance (ctx->vtx);
|
||||
ctx->vtx = 0;
|
||||
ctx->unload_vulkan (ctx);
|
||||
}
|
||||
|
||||
void
|
||||
Vulkan_CreateDevice (vulkan_ctx_t *ctx)
|
||||
{
|
||||
VulkanInstance_t *inst = ctx->vtx;
|
||||
|
||||
uint32_t nlay = 1; // ensure alloca doesn't see 0 and terminated
|
||||
uint32_t next = count_strings (device_extensions) + 1; // ensure terminated
|
||||
if (vulkan_use_validation->int_val) {
|
||||
nlay += count_strings (vulkanValidationLayers);
|
||||
}
|
||||
const char **lay = alloca (nlay * sizeof (const char *));
|
||||
const char **ext = alloca (next * sizeof (const char *));
|
||||
// ensure there are null pointers so merge_strings can act as append
|
||||
// since it does not add a null, but also make sure the counts reflect
|
||||
// actual numbers
|
||||
memset (lay, 0, nlay-- * sizeof (const char *));
|
||||
memset (ext, 0, next-- * sizeof (const char *));
|
||||
merge_strings (ext, device_extensions, 0);
|
||||
if (vulkan_use_validation->int_val) {
|
||||
merge_strings (lay, lay, vulkanValidationLayers);
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < inst->numDevices; i++) {
|
||||
VulkanPhysDevice_t *phys = &inst->devices[i];
|
||||
if (!Vulkan_LayersSupported (phys->layers, phys->numLayers, lay)) {
|
||||
continue;
|
||||
}
|
||||
if (!Vulkan_ExtensionsSupported (phys->extensions, phys->numExtensions,
|
||||
device_extensions)) {
|
||||
return 0;
|
||||
ext)) {
|
||||
continue;
|
||||
}
|
||||
int family = find_queue_family (phys, VK_QUEUE_GRAPHICS_BIT);
|
||||
if (family < 0) {
|
||||
return 0;
|
||||
continue;
|
||||
}
|
||||
if (!ctx->get_presentation_support (ctx, phys->device, family)) {
|
||||
continue;
|
||||
}
|
||||
float priority = 1;
|
||||
VkDeviceQueueCreateInfo qCreateInfo = {
|
||||
|
@ -148,52 +191,20 @@ create_suitable_device (VulkanInstance_t *instance)
|
|||
VkDeviceCreateInfo dCreateInfo = {
|
||||
VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, 0, 0,
|
||||
1, &qCreateInfo,
|
||||
0, 0,
|
||||
0, device_extensions,
|
||||
nlay, lay,
|
||||
next, ext,
|
||||
&features
|
||||
};
|
||||
memset (&features, 0, sizeof (features));
|
||||
VulkanDevice_t *device = calloc (1, sizeof (VulkanDevice_t));
|
||||
if (instance->vkCreateDevice (phys->device, &dCreateInfo, 0,
|
||||
if (inst->vkCreateDevice (phys->device, &dCreateInfo, 0,
|
||||
&device->device) == VK_SUCCESS) {
|
||||
load_device_funcs (instance, device);
|
||||
load_device_funcs (inst, device);
|
||||
device->vkGetDeviceQueue (device->device, family,
|
||||
0, &device->queue);
|
||||
return device;
|
||||
ctx->dev = device;
|
||||
ctx->device = device->device;
|
||||
return;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int x = 1;
|
||||
|
||||
void
|
||||
Vulkan_Init_Common (vulkan_ctx_t *ctx)
|
||||
{
|
||||
Sys_Printf ("Vulkan_Init_Common\n");
|
||||
Vulkan_Init_Cvars ();
|
||||
|
||||
vulkan_instance = Vulkan_CreateInstance (ctx, 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");
|
||||
}
|
||||
// only for now...
|
||||
Sys_Printf ("%p %p\n", vulkan_device->device, vulkan_device->queue);
|
||||
Vulkan_Shutdown_Common (ctx);
|
||||
if (x)
|
||||
Sys_Quit();
|
||||
}
|
||||
|
||||
void
|
||||
Vulkan_Shutdown_Common (vulkan_ctx_t *ctx)
|
||||
{
|
||||
if (vulkan_device) {
|
||||
vulkan_device->vkDestroyDevice (vulkan_device->device, 0);
|
||||
free (vulkan_device);
|
||||
vulkan_device = 0;
|
||||
}
|
||||
Vulkan_DestroyInstance (vulkan_instance);
|
||||
vulkan_instance = 0;
|
||||
ctx->unload_vulkan (ctx);
|
||||
}
|
||||
|
|
|
@ -110,11 +110,38 @@ unload_vulkan_library (vulkan_ctx_t *ctx)
|
|||
vulkan_library = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
x11_vulkan_init_presentation (vulkan_ctx_t *ctx)
|
||||
{
|
||||
ctx->presentation = calloc (1, sizeof (vulkan_presentation_t));
|
||||
vulkan_presentation_t *pres = ctx->presentation;
|
||||
VkInstance instance = ctx->instance;
|
||||
|
||||
#define INSTANCE_LEVEL_VULKAN_FUNCTION(name) \
|
||||
pres->name = (PFN_##name) ctx->vkGetInstanceProcAddr (instance, #name); \
|
||||
if (!pres->name) { \
|
||||
Sys_Error ("Couldn't find instance-level function %s", #name); \
|
||||
}
|
||||
#include "QF/Vulkan/funclist.h"
|
||||
|
||||
XVisualInfo template;
|
||||
Visual *defaultVisual = XDefaultVisual (x_disp, x_screen);
|
||||
template.visualid = XVisualIDFromVisual (defaultVisual);
|
||||
int template_mask = VisualIDMask;
|
||||
pres->display = x_disp;
|
||||
pres->usable_visuals = set_new ();
|
||||
pres->visinfo = XGetVisualInfo (x_disp, template_mask, &template,
|
||||
&pres->num_visuals);
|
||||
}
|
||||
|
||||
static int
|
||||
x11_vulkan_get_presentation_support (vulkan_ctx_t *ctx,
|
||||
VkPhysicalDevice physicalDevice,
|
||||
uint32_t queueFamilyIndex)
|
||||
{
|
||||
if (!ctx->presentation) {
|
||||
x11_vulkan_init_presentation (ctx);
|
||||
}
|
||||
vulkan_presentation_t *pres = ctx->presentation;
|
||||
|
||||
set_empty (pres->usable_visuals);
|
||||
|
@ -129,6 +156,25 @@ x11_vulkan_get_presentation_support (vulkan_ctx_t *ctx,
|
|||
return !set_is_empty (pres->usable_visuals);
|
||||
}
|
||||
|
||||
static void
|
||||
x11_vulkan_choose_visual (vulkan_ctx_t *ctx)
|
||||
{
|
||||
vulkan_presentation_t *pres = ctx->presentation;
|
||||
set_iter_t *first = set_first (pres->usable_visuals);
|
||||
if (first) {
|
||||
x_visinfo = pres->visinfo + first->element;
|
||||
x_vis = x_visinfo->visual;
|
||||
set_del_iter (first);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
x11_vulkan_create_window (vulkan_ctx_t *ctx)
|
||||
{
|
||||
vulkan_presentation_t *pres = ctx->presentation;
|
||||
pres->window = x_win;
|
||||
}
|
||||
|
||||
static VkSurfaceKHR
|
||||
x11_vulkan_create_surface (vulkan_ctx_t *ctx)
|
||||
{
|
||||
|
@ -155,6 +201,8 @@ X11_Vulkan_Context (void)
|
|||
ctx->load_vulkan = load_vulkan_library;
|
||||
ctx->unload_vulkan = unload_vulkan_library;
|
||||
ctx->get_presentation_support = x11_vulkan_get_presentation_support;
|
||||
ctx->choose_visual = x11_vulkan_choose_visual;
|
||||
ctx->create_window = x11_vulkan_create_window;
|
||||
ctx->create_surface = x11_vulkan_create_surface;
|
||||
ctx->required_extensions = required_extensions;
|
||||
return ctx;
|
||||
|
|
Loading…
Reference in a new issue