/* vid_common_vulkan.c Common Vulkan video driver functions Copyright (C) 2019 Bill Currie 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 #endif #include #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_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->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); } 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); } void Vulkan_ConfigOutput (vulkan_ctx_t *ctx, qfv_output_t *output) { *output = (qfv_output_t) { .extent = ctx->swapchain->extent, .frames = ctx->swapchain->numImages, }; if (vulkan_frame_width > 0) { output->extent.width = vulkan_frame_width; } if (vulkan_frame_height > 0) { output->extent.height = vulkan_frame_height; } if (scr_fisheye) {//FIXME auto w = output->extent.width; auto h = output->extent.height; output->extent.width = min (w, h); output->extent.height = min (w, h); } }