mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-26 22:31:05 +00:00
17c3f12ba2
My laptop can't have a buffer larger than 128MB, but 16M fragments wants 512MB. Also, someone running at 4k will probably want a larger buffer.
282 lines
7.4 KiB
C
282 lines
7.4 KiB
C
/*
|
|
vid_common_vulkan.c
|
|
|
|
Common Vulkan video driver functions
|
|
|
|
Copyright (C) 2019 Bill Currie <bill@taniwha.org>
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; either version 2
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
See the GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to:
|
|
|
|
Free Software Foundation, Inc.
|
|
59 Temple Place - Suite 330
|
|
Boston, MA 02111-1307, USA
|
|
|
|
*/
|
|
#ifdef HAVE_CONFIG_H
|
|
# include "config.h"
|
|
#endif
|
|
|
|
#ifdef HAVE_MATH_H
|
|
# include <math.h>
|
|
#endif
|
|
|
|
#include <string.h>
|
|
|
|
#include "QF/cexpr.h"
|
|
#include "QF/cmem.h"
|
|
#include "QF/cvar.h"
|
|
#include "QF/dstring.h"
|
|
#include "QF/hash.h"
|
|
#include "QF/heapsort.h"
|
|
#include "QF/plist.h"
|
|
#include "QF/va.h"
|
|
#include "QF/scene/entity.h"
|
|
#include "QF/Vulkan/capture.h"
|
|
#include "QF/Vulkan/command.h"
|
|
#include "QF/Vulkan/debug.h"
|
|
#include "QF/Vulkan/device.h"
|
|
#include "QF/Vulkan/instance.h"
|
|
#include "QF/Vulkan/staging.h"
|
|
#include "QF/Vulkan/swapchain.h"
|
|
|
|
#include "QF/Vulkan/qf_lighting.h"
|
|
#include "QF/Vulkan/qf_main.h"
|
|
#include "QF/Vulkan/qf_output.h"
|
|
#include "QF/Vulkan/qf_particles.h"
|
|
#include "QF/Vulkan/qf_renderpass.h"
|
|
#include "QF/Vulkan/qf_translucent.h"
|
|
#include "QF/Vulkan/qf_vid.h"
|
|
|
|
#include "r_internal.h"
|
|
#include "vid_vulkan.h"
|
|
#include "vkparse.h"
|
|
|
|
int vulkan_frame_width;
|
|
static cvar_t vulkan_frame_width_cvar = {
|
|
.name = "vulkan_frame_width",
|
|
.description =
|
|
"Width of 3D view buffer. Set to 0 for automatic sizing.",
|
|
.default_value = "0",
|
|
.flags = CVAR_NONE,
|
|
.value = { .type = &cexpr_int, .value = &vulkan_frame_width },
|
|
};
|
|
|
|
int vulkan_frame_height;
|
|
static cvar_t vulkan_frame_height_cvar = {
|
|
.name = "vulkan_frame_height",
|
|
.description =
|
|
"Height of 3D view buffer. Set to 0 for automatic sizing.",
|
|
.default_value = "0",
|
|
.flags = CVAR_NONE,
|
|
.value = { .type = &cexpr_int, .value = &vulkan_frame_height },
|
|
};
|
|
int vulkan_oit_fragments;
|
|
static cvar_t vulkan_oit_fragments_cvar = {
|
|
.name = "vulkan_oit_fragments",
|
|
.description =
|
|
"Size of fragment buffer (M) for order independent transparency.",
|
|
.default_value = "16",
|
|
.flags = CVAR_ROM,
|
|
.value = { .type = &cexpr_int, .value = &vulkan_oit_fragments },
|
|
};
|
|
|
|
static const char *instance_extensions[] = {
|
|
VK_KHR_SURFACE_EXTENSION_NAME,
|
|
VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
|
|
0,
|
|
};
|
|
|
|
static const char *device_extensions[] = {
|
|
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
|
|
0,
|
|
};
|
|
|
|
void
|
|
Vulkan_Init_Common (vulkan_ctx_t *ctx)
|
|
{
|
|
Sys_MaskPrintf (SYS_vulkan, "Vulkan_Init_Common\n");
|
|
|
|
Cvar_Register (&vulkan_frame_width_cvar, 0, 0);
|
|
Cvar_Register (&vulkan_frame_height_cvar, 0, 0);
|
|
Cvar_Register (&vulkan_oit_fragments_cvar, 0, 0);
|
|
Vulkan_Init_Cvars ();
|
|
R_Init_Cvars ();
|
|
Vulkan_Script_Init (ctx);
|
|
ctx->instance = QFV_CreateInstance (ctx, PACKAGE_STRING, 0x000702ff, 0,
|
|
instance_extensions);//FIXME version
|
|
DARRAY_INIT (&ctx->renderPasses, 4);
|
|
}
|
|
|
|
void
|
|
Vulkan_Shutdown_Common (vulkan_ctx_t *ctx)
|
|
{
|
|
if (ctx->capture) {
|
|
QFV_DestroyCapture (ctx->capture);
|
|
}
|
|
if (ctx->frames.size) {
|
|
Vulkan_DestroyFrames (ctx);
|
|
}
|
|
if (ctx->swapchain) {
|
|
QFV_DestroySwapchain (ctx->swapchain);
|
|
}
|
|
ctx->instance->funcs->vkDestroySurfaceKHR (ctx->instance->instance,
|
|
ctx->surface, 0);
|
|
Vulkan_Script_Shutdown (ctx);
|
|
if (ctx->device) {
|
|
QFV_DestroyDevice (ctx->device);
|
|
}
|
|
if (ctx->instance) {
|
|
QFV_DestroyInstance (ctx->instance);
|
|
}
|
|
ctx->instance = 0;
|
|
ctx->unload_vulkan (ctx);
|
|
}
|
|
|
|
void
|
|
Vulkan_CreateDevice (vulkan_ctx_t *ctx)
|
|
{
|
|
ctx->device = QFV_CreateDevice (ctx, device_extensions);
|
|
|
|
//FIXME msaa and deferred rendering...
|
|
//also, location
|
|
ctx->msaaSamples = 1;
|
|
/*ctx->msaaSamples = min ((VkSampleCountFlagBits) msaaSamples,
|
|
QFV_GetMaxSampleCount (device->physDev));
|
|
if (ctx->msaaSamples > 1) {
|
|
name = "renderpass_msaa";
|
|
}*/
|
|
}
|
|
|
|
void
|
|
Vulkan_CreateStagingBuffers (vulkan_ctx_t *ctx)
|
|
{
|
|
// FIXME configurable?
|
|
ctx->staging = QFV_CreateStagingBuffer (ctx->device, "vulkan_ctx",
|
|
32*1024*1024, ctx->cmdpool);
|
|
}
|
|
|
|
void
|
|
Vulkan_CreateSwapchain (vulkan_ctx_t *ctx)
|
|
{
|
|
VkSwapchainKHR old_swapchain = 0;
|
|
if (ctx->swapchain) {
|
|
//FIXME this shouldn't be here
|
|
qfv_device_t *device = ctx->swapchain->device;
|
|
VkDevice dev = device->dev;
|
|
qfv_devfuncs_t *dfunc = device->funcs;
|
|
old_swapchain = ctx->swapchain->swapchain;
|
|
for (size_t i = 0; i < ctx->swapchain->imageViews->size; i++) {
|
|
dfunc->vkDestroyImageView(dev, ctx->swapchain->imageViews->a[i], 0);
|
|
}
|
|
free (ctx->swapchain->images);
|
|
free (ctx->swapchain->imageViews);
|
|
free (ctx->swapchain);
|
|
}
|
|
ctx->swapchain = QFV_CreateSwapchain (ctx, old_swapchain);
|
|
}
|
|
|
|
static int
|
|
renderpass_cmp (const void *_a, const void *_b)
|
|
{
|
|
__auto_type a = (const qfv_renderpass_t **) _a;
|
|
__auto_type b = (const qfv_renderpass_t **) _b;
|
|
return (*a)->order - (*b)->order;
|
|
}
|
|
|
|
void
|
|
Vulkan_CreateRenderPasses (vulkan_ctx_t *ctx)
|
|
{
|
|
Vulkan_Output_CreateRenderPasses (ctx);
|
|
Vulkan_Main_CreateRenderPasses (ctx);
|
|
Vulkan_Particles_CreateRenderPasses (ctx);
|
|
Vulkan_Lighting_CreateRenderPasses (ctx);
|
|
Vulkan_Translucent_CreateRenderPasses (ctx);
|
|
|
|
heapsort (ctx->renderPasses.a, ctx->renderPasses.size,
|
|
sizeof (qfv_renderpass_t *), renderpass_cmp);
|
|
}
|
|
|
|
void
|
|
Vulkan_DestroyRenderPasses (vulkan_ctx_t *ctx)
|
|
{
|
|
for (size_t i = 0; i < ctx->renderPasses.size; i++) {
|
|
QFV_RenderPass_Delete (ctx->renderPasses.a[i]);
|
|
}
|
|
}
|
|
|
|
void
|
|
Vulkan_CreateFrames (vulkan_ctx_t *ctx)
|
|
{
|
|
qfv_device_t *device = ctx->device;
|
|
VkCommandPool cmdpool = ctx->cmdpool;
|
|
|
|
if (!ctx->frames.grow) {
|
|
DARRAY_INIT (&ctx->frames, 4);
|
|
}
|
|
|
|
DARRAY_RESIZE (&ctx->frames, vulkan_frame_count);
|
|
|
|
__auto_type cmdBuffers = QFV_AllocCommandBufferSet (ctx->frames.size,
|
|
alloca);
|
|
QFV_AllocateCommandBuffers (device, cmdpool, 0, cmdBuffers);
|
|
|
|
for (size_t i = 0; i < ctx->frames.size; i++) {
|
|
__auto_type frame = &ctx->frames.a[i];
|
|
frame->fence = QFV_CreateFence (device, 1);
|
|
frame->imageAvailableSemaphore = QFV_CreateSemaphore (device);
|
|
frame->renderDoneSemaphore = QFV_CreateSemaphore (device);
|
|
frame->cmdBuffer = cmdBuffers->a[i];
|
|
}
|
|
}
|
|
|
|
void
|
|
Vulkan_CreateCapture (vulkan_ctx_t *ctx)
|
|
{
|
|
ctx->capture = QFV_CreateCapture (ctx->device, ctx->frames.size,
|
|
ctx->swapchain, ctx->cmdpool);
|
|
}
|
|
|
|
void
|
|
Vulkan_DestroyFrames (vulkan_ctx_t *ctx)
|
|
{
|
|
qfv_device_t *device = ctx->device;
|
|
qfv_devfuncs_t *df = device->funcs;
|
|
VkDevice dev = device->dev;
|
|
|
|
for (size_t i = 0; i < ctx->frames.size; i++) {
|
|
__auto_type frame = &ctx->frames.a[i];
|
|
df->vkDestroyFence (dev, frame->fence, 0);
|
|
df->vkDestroySemaphore (dev, frame->imageAvailableSemaphore, 0);
|
|
df->vkDestroySemaphore (dev, frame->renderDoneSemaphore, 0);
|
|
}
|
|
|
|
DARRAY_CLEAR (&ctx->frames);
|
|
}
|
|
|
|
void
|
|
Vulkan_BeginEntityLabel (vulkan_ctx_t *ctx, VkCommandBuffer cmd, entity_t ent)
|
|
{
|
|
qfv_device_t *device = ctx->device;
|
|
uint32_t entgen = Ent_Generation (ent.id);
|
|
uint32_t entind = Ent_Index (ent.id);
|
|
transform_t transform = Entity_Transform (ent);
|
|
vec4f_t pos = Transform_GetWorldPosition (transform);
|
|
vec4f_t dir = normalf (pos - (vec4f_t) { 0, 0, 0, 1 });
|
|
vec4f_t color = 0.5 * dir + (vec4f_t) {0.5, 0.5, 0.5, 1 };
|
|
|
|
QFV_CmdBeginLabel (device, cmd,
|
|
va (ctx->va_ctx, "ent %03x.%05x [%g, %g, %g]",
|
|
entgen, entind, VectorExpand (pos)), color);
|
|
}
|