Create a window and a surface for vulkan

Yay, segfaults in R_Init :)
This commit is contained in:
Bill Currie 2019-07-09 16:33:44 +09:00
parent 0f511e8342
commit 68449d0f6f
9 changed files with 180 additions and 77 deletions

View file

@ -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

View file

@ -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);

View file

@ -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"

View file

@ -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

View file

@ -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;
}

View file

@ -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) {

View file

@ -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

View file

@ -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);
}

View file

@ -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;