Quake II RTX doxygen  1.0 dev
main.c
Go to the documentation of this file.
1 /*
2 Copyright (C) 2018 Christoph Schied
3 Copyright (C) 2019, NVIDIA CORPORATION. All rights reserved.
4 
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 
20 #include "shared/shared.h"
21 #include "common/bsp.h"
22 #include "common/cmd.h"
23 #include "common/common.h"
24 #include "common/cvar.h"
25 #include "common/files.h"
26 #include "common/math.h"
27 #include "client/video.h"
28 #include "client/client.h"
29 #include "refresh/refresh.h"
30 #include "refresh/images.h"
31 #include "refresh/models.h"
32 #include "system/hunk.h"
33 #include "vkpt.h"
34 #include "material.h"
35 #include "physical_sky.h"
36 #include "../../client/client.h"
37 #include "../../client/ui/ui.h"
38 
39 #include "shader/vertex_buffer.h"
40 
41 #include <vulkan/vulkan.h>
42 #include <SDL.h>
43 #include <SDL_vulkan.h>
44 
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <assert.h>
49 
50 cvar_t *cvar_profiler = NULL;
51 cvar_t *cvar_vsync = NULL;
52 cvar_t *cvar_pt_caustics = NULL;
53 cvar_t *cvar_pt_enable_nodraw = NULL;
56 cvar_t *cvar_pt_projection = NULL;
57 cvar_t *cvar_pt_dof = NULL;
58 cvar_t *cvar_pt_freecam = NULL;
59 cvar_t *cvar_drs_enable = NULL;
60 cvar_t *cvar_drs_target = NULL;
61 cvar_t *cvar_drs_minscale = NULL;
62 cvar_t *cvar_drs_maxscale = NULL;
63 cvar_t *cvar_drs_adjust_up = NULL;
64 cvar_t *cvar_drs_adjust_down = NULL;
65 cvar_t *cvar_drs_gain = NULL;
66 extern cvar_t *scr_viewsize;
67 extern cvar_t *cvar_bloom_enable;
68 static int drs_current_scale = 0;
69 static int drs_effective_scale = 0;
70 
71 cvar_t *cvar_min_driver_version = NULL;
72 
73 extern uiStatic_t uis;
74 
75 #ifdef VKPT_DEVICE_GROUPS
76 cvar_t *cvar_sli = NULL;
77 #endif
78 
79 #ifdef VKPT_IMAGE_DUMPS
80 cvar_t *cvar_dump_image = NULL;
81 #endif
82 
83 char cluster_debug_mask[VIS_MAX_BYTES];
85 
86 #define UBO_CVAR_DO(name, default_value) cvar_t *cvar_##name;
88 #undef UBO_CVAR_DO
89 
90 static bsp_t *bsp_world_model;
91 
92 static qboolean temporal_frame_valid = qfalse;
93 
94 static int world_anim_frame = 0;
95 
96 static vec3_t avg_envmap_color = { 0.f };
97 
99 
101 
102 static qboolean frame_ready = qfalse;
103 
104 static float sky_rotation = 0.f;
105 static vec3_t sky_axis = { 0.f };
106 
107 typedef enum {
112 
113 typedef struct VkptInit_s {
114  const char *name;
115  VkResult (*initialize)();
116  VkResult (*destroy)();
119 } VkptInit_t;
141 
147 };
148 
149 void debug_output(const char* format, ...);
150 static void recreate_swapchain();
151 
152 static void viewsize_changed(cvar_t *self)
153 {
155  Com_Printf("Resolution scale: %d%%\n", scr_viewsize->integer);
156 }
157 
158 static void drs_target_changed(cvar_t *self)
159 {
160  Cvar_ClampInteger(self, 30, 240);
161 }
162 
163 static void drs_minscale_changed(cvar_t *self)
164 {
165  Cvar_ClampInteger(self, 25, 100);
166 }
167 
168 static void drs_maxscale_changed(cvar_t *self)
169 {
170  Cvar_ClampInteger(self, 50, 200);
171 }
172 
173 static void accumulation_cvar_changed(cvar_t* self)
174 {
175  // Reset accumulation rendering on DoF parameter change
177 }
178 
179 static inline qboolean extents_equal(VkExtent2D a, VkExtent2D b)
180 {
181  return a.width == b.width && a.height == b.height;
182 }
183 
184 static VkExtent2D get_render_extent()
185 {
186  int scale = (drs_effective_scale != 0) ? drs_effective_scale : scr_viewsize->integer;
187 
188  VkExtent2D result;
189  result.width = (uint32_t)(qvk.extent_unscaled.width * (float)scale / 100.f);
190  result.height = (uint32_t)(qvk.extent_unscaled.height * (float)scale / 100.f);
191 
192  result.width = (result.width + 7) & ~7;
193  result.height = (result.height + 7) & ~7;
194 
195  return result;
196 }
197 
198 static VkExtent2D get_screen_image_extent()
199 {
200  VkExtent2D result;
201  if (cvar_drs_enable->integer)
202  {
203  int drs_maxscale = max(cvar_drs_minscale->integer, cvar_drs_maxscale->integer);
204  result.width = (uint32_t)(qvk.extent_unscaled.width * (float)drs_maxscale / 100.f);
205  result.height = (uint32_t)(qvk.extent_unscaled.height * (float)drs_maxscale / 100.f);
206  }
207  else
208  {
209  result.width = max(qvk.extent_render.width, qvk.extent_unscaled.width);
210  result.height = max(qvk.extent_render.height, qvk.extent_unscaled.height);
211  }
212 
213  result.width = (result.width + 7) & ~7;
214  result.height = (result.height + 7) & ~7;
215 
216  return result;
217 }
218 
220 {
222 }
223 
224 VkResult
226 {
227  vkDeviceWaitIdle(qvk.device);
228 
232 
233  for(int i = 0; i < LENGTH(vkpt_initialization); i++) {
234  VkptInit_t *init = vkpt_initialization + i;
235  if((init->flags & init_flags) != init_flags)
236  continue;
237 
238  // some entries will respond to multiple events --- do not initialize twice
239  if (init->is_initialized)
240  continue;
241 
242  init->is_initialized = init->initialize
243  ? (init->initialize() == VK_SUCCESS)
244  : 1;
245  assert(init->is_initialized);
246  }
247 
248  if ((VKPT_INIT_DEFAULT & init_flags) == init_flags)
249  {
251  return VK_RESULT_MAX_ENUM;
252  }
253 
255 
256  water_normal_texture = IMG_Find("textures/water_n.tga", IT_SKIN, IF_PERMANENT);
257 
258  return VK_SUCCESS;
259 }
260 
261 VkResult
263 {
264  vkDeviceWaitIdle(qvk.device);
265 
266  for(int i = LENGTH(vkpt_initialization) - 1; i >= 0; i--) {
267  VkptInit_t *init = vkpt_initialization + i;
268  if((init->flags & destroy_flags) != destroy_flags)
269  continue;
270 
271  // some entries will respond to multiple events --- do not destroy twice
272  if (!init->is_initialized)
273  continue;
274 
275  init->is_initialized = init->destroy
276  ? !(init->destroy() == VK_SUCCESS)
277  : 0;
278  assert(!init->is_initialized);
279  }
280 
281  if ((VKPT_INIT_DEFAULT & destroy_flags) == destroy_flags)
282  {
285  }
286 
287  return VK_SUCCESS;
288 }
289 
290 void
292 {
293  char buf[1024];
294 #ifdef _WIN32
295  FILE *f = _popen("compile_shaders.bat", "r");
296 #else
297  FILE *f = popen("make -j compile_shaders", "r");
298 #endif
299  if(f) {
300  while(fgets(buf, sizeof buf, f)) {
301  Com_Printf("%s", buf);
302  }
303 #ifdef _WIN32
304  _pclose(f);
305 #else
306  pclose(f);
307 #endif
308  }
309 
312 
315 }
316 
317 void
319 {
320  IMG_ReloadAll();
321 }
322 
323 //
324 // materials commands
325 //
326 void
328 {
331 }
332 
333 void
335 {
337 }
338 
339 void
341 {
342  pbr_material_t * mat = MAT_FindPBRMaterial(vkpt_refdef.fd->feedback.view_material);
343  if (!mat)
344  {
345  Com_EPrintf("Cannot find material '%s' in table\n");
346  return;
347  }
348 
349  char const * token = Cmd_Argc() > 1 ? Cmd_Argv(1) : NULL,
350  * value = Cmd_Argc() > 2 ? Cmd_Argv(2) : NULL;
351 
352  MAT_SetPBRMaterialAttribute(mat, token, value);
353 }
354 
355 void
357 {
358  pbr_material_t * mat = MAT_FindPBRMaterial(vkpt_refdef.fd->feedback.view_material);
359  if (!mat)
360  {
361  Com_EPrintf("Cannot find material '%s' in table\n");
362  return;
363  }
365 }
366 
367 //
368 //
369 //
370 
373  .z_near = 1.0f,
374  .z_far = 4096.0f,
375 };
376 
378  .win_width = 1920,
379  .win_height = 1080,
380  .frame_counter = 0,
381 };
382 
383 #define _VK_INST_EXTENSION_DO(a) PFN_##a q##a;
385 #undef _VK_INST_EXTENSION_DO
386 
387 #define _VK_EXTENSION_DO(a) PFN_##a q##a;
389 #undef _VK_EXTENSION_DO
390 
391 #ifdef VKPT_ENABLE_VALIDATION
392 const char *vk_requested_layers[] = {
393  "VK_LAYER_LUNARG_standard_validation"
394 };
395 #endif
396 
398  VK_EXT_DEBUG_UTILS_EXTENSION_NAME,
399  VK_EXT_DEBUG_REPORT_EXTENSION_NAME,
400 #ifdef VKPT_DEVICE_GROUPS
401  VK_KHR_DEVICE_GROUP_CREATION_EXTENSION_NAME,
402 #endif
403 };
404 
406  VK_NV_RAY_TRACING_EXTENSION_NAME,
407  VK_KHR_SWAPCHAIN_EXTENSION_NAME,
408  VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME,
409  VK_EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME,
410 #ifdef VKPT_ENABLE_VALIDATION
411  VK_EXT_DEBUG_MARKER_EXTENSION_NAME,
412 #endif
413 #ifdef VKPT_DEVICE_GROUPS
414  VK_KHR_DEVICE_GROUP_EXTENSION_NAME,
415  VK_KHR_BIND_MEMORY_2_EXTENSION_NAME,
416 #endif
417 };
418 
419 static const VkApplicationInfo vk_app_info = {
420  .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
421  .pApplicationName = "quake 2 pathtracing",
422  .applicationVersion = VK_MAKE_VERSION(1, 0, 0),
423  .pEngineName = "vkpt",
424  .engineVersion = VK_MAKE_VERSION(1, 0, 0),
425  .apiVersion = VK_API_VERSION_1_1,
426 };
427 
428 /* use this to override file names */
430 
432 
433 void
435  const char *layer,
436  uint32_t *num_extensions,
437  VkExtensionProperties **ext)
438 {
439  _VK(vkEnumerateInstanceExtensionProperties(layer, num_extensions, NULL));
440  *ext = malloc(sizeof(**ext) * *num_extensions);
441  _VK(vkEnumerateInstanceExtensionProperties(layer, num_extensions, *ext));
442 }
443 
444 void
446  uint32_t *num_layers,
447  VkLayerProperties **ext)
448 {
449  _VK(vkEnumerateInstanceLayerProperties(num_layers, NULL));
450  *ext = malloc(sizeof(**ext) * *num_layers);
451  _VK(vkEnumerateInstanceLayerProperties(num_layers, *ext));
452 }
453 
454 int
455 layer_requested(const char *name)
456 {
457 #ifdef VKPT_ENABLE_VALIDATION
458  for (int i = 0; i < LENGTH(vk_requested_layers); i++)
459  if(!strcmp(name, vk_requested_layers[i]))
460  return 1;
461 #endif
462  return 0;
463 }
464 
465 static VKAPI_ATTR VkBool32 VKAPI_CALL
467  VkDebugUtilsMessageSeverityFlagBitsEXT severity,
468  VkDebugUtilsMessageTypeFlagsEXT type,
469  const VkDebugUtilsMessengerCallbackDataEXT* callback_data,
470  void *user_data)
471 {
472  Com_EPrintf("validation layer %i %i: %s\n", (int32_t)type, (int32_t)severity, callback_data->pMessage);
473  debug_output("Vulkan error: %s\n", callback_data->pMessage);
474 
475  if (callback_data->cmdBufLabelCount)
476  {
477  Com_EPrintf("~~~ ");
478  for (uint32_t i = 0; i < callback_data->cmdBufLabelCount; ++i)
479  {
480  VkDebugUtilsLabelEXT* label = &callback_data->pCmdBufLabels[i];
481  Com_EPrintf("%s ~ ", label->pLabelName);
482  }
483  Com_EPrintf("\n");
484  }
485 
486  if (callback_data->objectCount)
487  {
488  for (uint32_t i = 0; i < callback_data->objectCount; ++i)
489  {
490  VkDebugUtilsObjectNameInfoEXT* obj = &callback_data->pObjects[i];
491  Com_EPrintf("--- %s %i\n", obj->pObjectName, (int32_t)obj->objectType);
492  }
493  }
494 
495  Com_EPrintf("\n");
496  return VK_FALSE;
497 }
498 
499 VkResult
501  VkInstance instance,
502  const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo,
503  const VkAllocationCallbacks* pAllocator,
504  VkDebugUtilsMessengerEXT* pCallback)
505 {
506  PFN_vkCreateDebugUtilsMessengerEXT func = (PFN_vkCreateDebugUtilsMessengerEXT)
507  vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT");
508  if(func)
509  return func(instance, pCreateInfo, pAllocator, pCallback);
510  return VK_ERROR_EXTENSION_NOT_PRESENT;
511 }
512 
513 VkResult
515  VkInstance instance,
516  VkDebugUtilsMessengerEXT callback,
517  const VkAllocationCallbacks* pAllocator)
518 {
519  PFN_vkDestroyDebugUtilsMessengerEXT func = (PFN_vkDestroyDebugUtilsMessengerEXT)
520  vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT");
521  if(func) {
522  func(instance, callback, pAllocator);
523  return VK_SUCCESS;
524  }
525  return VK_ERROR_EXTENSION_NOT_PRESENT;
526 }
527 
528 VkResult
530 {
531  /* create swapchain (query details and ignore them afterwards :-) )*/
532  VkSurfaceCapabilitiesKHR surf_capabilities;
533  vkGetPhysicalDeviceSurfaceCapabilitiesKHR(qvk.physical_device, qvk.surface, &surf_capabilities);
534 
535  uint32_t num_formats = 0;
536  vkGetPhysicalDeviceSurfaceFormatsKHR(qvk.physical_device, qvk.surface, &num_formats, NULL);
537  VkSurfaceFormatKHR *avail_surface_formats = alloca(sizeof(VkSurfaceFormatKHR) * num_formats);
538  vkGetPhysicalDeviceSurfaceFormatsKHR(qvk.physical_device, qvk.surface, &num_formats, avail_surface_formats);
539  /* Com_Printf("num surface formats: %d\n", num_formats);
540 
541  Com_Printf("available surface formats:\n");
542  for(int i = 0; i < num_formats; i++)
543  Com_Printf(" %s\n", vk_format_to_string(avail_surface_formats[i].format)); */
544 
545 
546  VkFormat acceptable_formats[] = {
547  VK_FORMAT_R8G8B8A8_SRGB, VK_FORMAT_B8G8R8A8_SRGB,
548  };
549 
550  //qvk.surf_format.format = VK_FORMAT_R8G8B8A8_SRGB;
551  //qvk.surf_format.format = VK_FORMAT_B8G8R8A8_SRGB;
552  for(int i = 0; i < LENGTH(acceptable_formats); i++) {
553  for(int j = 0; j < num_formats; j++)
554  if(acceptable_formats[i] == avail_surface_formats[j].format) {
555  qvk.surf_format = avail_surface_formats[j];
556  goto out;
557  }
558  }
559 out:;
560 
561  uint32_t num_present_modes = 0;
562  vkGetPhysicalDeviceSurfacePresentModesKHR(qvk.physical_device, qvk.surface, &num_present_modes, NULL);
563  VkPresentModeKHR *avail_present_modes = alloca(sizeof(VkPresentModeKHR) * num_present_modes);
564  vkGetPhysicalDeviceSurfacePresentModesKHR(qvk.physical_device, qvk.surface, &num_present_modes, avail_present_modes);
565  qboolean immediate_mode_available = qfalse;
566 
567  for (int i = 0; i < num_present_modes; i++) {
568  if (avail_present_modes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR) {
569  immediate_mode_available = qtrue;
570  break;
571  }
572  }
573 
574  if (cvar_vsync->integer) {
575  qvk.present_mode = VK_PRESENT_MODE_FIFO_KHR;
576  } else if (immediate_mode_available) {
577  qvk.present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR;
578  } else {
579  qvk.present_mode = VK_PRESENT_MODE_MAILBOX_KHR;
580  }
581 
582  if(surf_capabilities.currentExtent.width != ~0u) {
583  qvk.extent_unscaled = surf_capabilities.currentExtent;
584  }
585  else {
586  qvk.extent_unscaled.width = MIN(surf_capabilities.maxImageExtent.width, qvk.win_width);
587  qvk.extent_unscaled.height = MIN(surf_capabilities.maxImageExtent.height, qvk.win_height);
588 
589  qvk.extent_unscaled.width = MAX(surf_capabilities.minImageExtent.width, qvk.extent_unscaled.width);
590  qvk.extent_unscaled.height = MAX(surf_capabilities.minImageExtent.height, qvk.extent_unscaled.height);
591  }
592 
593  uint32_t num_images = 2;
594  //uint32_t num_images = surf_capabilities.minImageCount + 1;
595  if(surf_capabilities.maxImageCount > 0)
596  num_images = MIN(num_images, surf_capabilities.maxImageCount);
597 
598  VkSwapchainCreateInfoKHR swpch_create_info = {
599  .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
600  .surface = qvk.surface,
601  .minImageCount = num_images,
602  .imageFormat = qvk.surf_format.format,
603  .imageColorSpace = qvk.surf_format.colorSpace,
604  .imageExtent = qvk.extent_unscaled,
605  .imageArrayLayers = 1, /* only needs to be changed for stereoscopic rendering */
606  .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
607  | VK_IMAGE_USAGE_TRANSFER_SRC_BIT
608  | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
609  .imageSharingMode = VK_SHARING_MODE_EXCLUSIVE, /* VK_SHARING_MODE_CONCURRENT if not using same queue */
610  .queueFamilyIndexCount = 0,
611  .pQueueFamilyIndices = NULL,
612  .preTransform = surf_capabilities.currentTransform,
613  .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, /* no alpha for window transparency */
614  .presentMode = qvk.present_mode,
615  .clipped = VK_FALSE, /* do not render pixels that are occluded by other windows */
616  //.clipped = VK_TRUE, /* do not render pixels that are occluded by other windows */
617  .oldSwapchain = VK_NULL_HANDLE, /* need to provide previous swapchain in case of window resize */
618  };
619 
620  if(vkCreateSwapchainKHR(qvk.device, &swpch_create_info, NULL, &qvk.swap_chain) != VK_SUCCESS) {
621  Com_EPrintf("error creating swapchain\n");
622  return 1;
623  }
624 
625  vkGetSwapchainImagesKHR(qvk.device, qvk.swap_chain, &qvk.num_swap_chain_images, NULL);
626  //qvk.swap_chain_images = malloc(qvk.num_swap_chain_images * sizeof(*qvk.swap_chain_images));
628  vkGetSwapchainImagesKHR(qvk.device, qvk.swap_chain, &qvk.num_swap_chain_images, qvk.swap_chain_images);
629 
630  //qvk.swap_chain_image_views = malloc(qvk.num_swap_chain_images * sizeof(*qvk.swap_chain_image_views));
631  for(int i = 0; i < qvk.num_swap_chain_images; i++) {
632  VkImageViewCreateInfo img_create_info = {
633  .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
634  .image = qvk.swap_chain_images[i],
635  .viewType = VK_IMAGE_VIEW_TYPE_2D,
636  .format = qvk.surf_format.format,
637 #if 1
638  .components = {
639  VK_COMPONENT_SWIZZLE_R,
640  VK_COMPONENT_SWIZZLE_G,
641  VK_COMPONENT_SWIZZLE_B,
642  VK_COMPONENT_SWIZZLE_A
643  },
644 #endif
645  .subresourceRange = {
646  .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
647  .baseMipLevel = 0,
648  .levelCount = 1,
649  .baseArrayLayer = 0,
650  .layerCount = 1
651  }
652  };
653 
654  if(vkCreateImageView(qvk.device, &img_create_info, NULL, qvk.swap_chain_image_views + i) != VK_SUCCESS) {
655  Com_EPrintf("error creating image view!");
656  return 1;
657  }
658  }
659 
660  VkCommandBuffer cmd_buf = vkpt_begin_command_buffer(&qvk.cmd_buffers_graphics);
661 
662  for (int image_index = 0; image_index < qvk.num_swap_chain_images; image_index++)
663  {
664  IMAGE_BARRIER(cmd_buf,
665  .image = qvk.swap_chain_images[image_index],
666  .subresourceRange = {
667  .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
668  .baseMipLevel = 0,
669  .levelCount = 1,
670  .baseArrayLayer = 0,
671  .layerCount = 1
672  },
673  .srcAccessMask = 0,
674  .dstAccessMask = 0,
675  .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
676  .newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
677  );
678  }
679 
682 
684 
685  return VK_SUCCESS;
686 }
687 
688 VkResult
690 {
691  VkCommandPoolCreateInfo cmd_pool_create_info = {
692  .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
693  .queueFamilyIndex = qvk.queue_idx_graphics,
694  .flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
695  };
696 
697  /* command pool and buffers */
698  _VK(vkCreateCommandPool(qvk.device, &cmd_pool_create_info, NULL, &qvk.cmd_buffers_graphics.command_pool));
699 
700  cmd_pool_create_info.queueFamilyIndex = qvk.queue_idx_compute;
701  _VK(vkCreateCommandPool(qvk.device, &cmd_pool_create_info, NULL, &qvk.cmd_buffers_compute.command_pool));
702 
703  cmd_pool_create_info.queueFamilyIndex = qvk.queue_idx_transfer;
704  _VK(vkCreateCommandPool(qvk.device, &cmd_pool_create_info, NULL, &qvk.cmd_buffers_transfer.command_pool));
705 
706  /* fences and semaphores */
707  for (int frame = 0; frame < MAX_FRAMES_IN_FLIGHT; frame++)
708  {
709  for (int gpu = 0; gpu < qvk.device_count; gpu++)
710  {
711  semaphore_group_t* group = &qvk.semaphores[frame][gpu];
712 
713  VkSemaphoreCreateInfo semaphore_info = { .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO };
714 
715  _VK(vkCreateSemaphore(qvk.device, &semaphore_info, NULL, &group->image_available));
716  _VK(vkCreateSemaphore(qvk.device, &semaphore_info, NULL, &group->render_finished));
717  _VK(vkCreateSemaphore(qvk.device, &semaphore_info, NULL, &group->transfer_finished));
718  _VK(vkCreateSemaphore(qvk.device, &semaphore_info, NULL, &group->trace_finished));
719 
720  ATTACH_LABEL_VARIABLE(group->image_available, SEMAPHORE);
721  ATTACH_LABEL_VARIABLE(group->render_finished, SEMAPHORE);
722  ATTACH_LABEL_VARIABLE(group->transfer_finished, SEMAPHORE);
723  ATTACH_LABEL_VARIABLE(group->trace_finished, SEMAPHORE);
724 
725  group->trace_signaled = qfalse;
726  }
727  }
728 
729  VkFenceCreateInfo fence_info = {
730  .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
731  .flags = VK_FENCE_CREATE_SIGNALED_BIT, /* fence's initial state set to be signaled
732  to make program not hang */
733  };
734  for(int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
735  _VK(vkCreateFence(qvk.device, &fence_info, NULL, qvk.fences_frame_sync + i));
737  }
738  _VK(vkCreateFence(qvk.device, &fence_info, NULL, &qvk.fence_vertex_sync));
740 
741  return VK_SUCCESS;
742 }
743 
744 qboolean
746 {
747  Com_Printf("----- init_vulkan -----\n");
748 
749  /* layers */
751  Com_Printf("Available Vulkan layers: \n");
752  for(int i = 0; i < qvk.num_layers; i++) {
753  int requested = layer_requested(qvk.layers[i].layerName);
754  Com_Printf(" %s%s\n", qvk.layers[i].layerName, requested ? " (requested)" : "");
755  }
756 
757  /* instance extensions */
758 
759  if (!SDL_Vulkan_GetInstanceExtensions(qvk.window, &qvk.num_sdl2_extensions, NULL)) {
760  Com_EPrintf("Couldn't get SDL2 Vulkan extension count\n");
761  return qfalse;
762  }
763 
764  qvk.sdl2_extensions = malloc(sizeof(char*) * qvk.num_sdl2_extensions);
765  if (!SDL_Vulkan_GetInstanceExtensions(qvk.window, &qvk.num_sdl2_extensions, qvk.sdl2_extensions)) {
766  Com_EPrintf("Couldn't get SDL2 Vulkan extensions\n");
767  return qfalse;
768  }
769 
770  Com_Printf("Vulkan instance extensions required by SDL2: \n");
771  for (int i = 0; i < qvk.num_sdl2_extensions; i++) {
772  Com_Printf(" %s\n", qvk.sdl2_extensions[i]);
773  }
774 
775  int num_inst_ext_combined = qvk.num_sdl2_extensions + LENGTH(vk_requested_instance_extensions);
776  char **ext = alloca(sizeof(char *) * num_inst_ext_combined);
779 
780  get_vk_extension_list(NULL, &qvk.num_extensions, &qvk.extensions); /* valid here? */
781  Com_Printf("Supported Vulkan instance extensions: \n");
782  for(int i = 0; i < qvk.num_extensions; i++) {
783  int requested = 0;
784  for(int j = 0; j < num_inst_ext_combined; j++) {
785  if(!strcmp(qvk.extensions[i].extensionName, ext[j])) {
786  requested = 1;
787  break;
788  }
789  }
790  Com_Printf(" %s%s\n", qvk.extensions[i].extensionName, requested ? " (requested)" : "");
791  }
792 
793  /* create instance */
794  VkInstanceCreateInfo inst_create_info = {
795  .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
796  .pApplicationInfo = &vk_app_info,
797 #ifdef VKPT_ENABLE_VALIDATION
798  .enabledLayerCount = LENGTH(vk_requested_layers),
799  .ppEnabledLayerNames = vk_requested_layers,
800 #endif
801  .enabledExtensionCount = num_inst_ext_combined,
802  .ppEnabledExtensionNames = (const char * const*)ext,
803  };
804 
805  VkResult result = vkCreateInstance(&inst_create_info, NULL, &qvk.instance);
806  if (result != VK_SUCCESS)
807  {
808  Com_Error(ERR_FATAL, "Failed to initialize a Vulkan instance.\nError code: %s", qvk_result_to_string(result));
809  return qfalse;
810  }
811 
812 #define _VK_INST_EXTENSION_DO(a) \
813  q##a = (PFN_##a) vkGetInstanceProcAddr(qvk.instance, #a); \
814  if (!q##a) { Com_EPrintf("warning: could not load instance function %s\n", #a); }
816 #undef _VK_INST_EXTENSION_DO
817 
818  /* setup debug callback */
819  VkDebugUtilsMessengerCreateInfoEXT dbg_create_info = {
820  .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
821  .messageSeverity =
822  VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT
823  | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT,
824  .messageType =
825  VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT
826  | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT,
827  .pfnUserCallback = vk_debug_callback,
828  .pUserData = NULL
829  };
830 
831  _VK(qvkCreateDebugUtilsMessengerEXT(qvk.instance, &dbg_create_info, NULL, &qvk.dbg_messenger));
832 
833  /* create surface */
834  if(!SDL_Vulkan_CreateSurface(qvk.window, qvk.instance, &qvk.surface)) {
835  Com_EPrintf("SDL2 could not create a surface!\n");
836  return qfalse;
837  }
838 
839  /* pick physical device (iterate over all but pick device 0 anyways) */
840  uint32_t num_devices = 0;
841  _VK(vkEnumeratePhysicalDevices(qvk.instance, &num_devices, NULL));
842  if(num_devices == 0)
843  return qfalse;
844  VkPhysicalDevice *devices = alloca(sizeof(VkPhysicalDevice) *num_devices);
845  _VK(vkEnumeratePhysicalDevices(qvk.instance, &num_devices, devices));
846 
847 #ifdef VKPT_DEVICE_GROUPS
848  uint32_t num_device_groups = 0;
849 
850  if (cvar_sli->integer)
851  _VK(qvkEnumeratePhysicalDeviceGroupsKHR(qvk.instance, &num_device_groups, NULL));
852 
853  VkDeviceGroupDeviceCreateInfoKHR device_group_create_info;
854  VkPhysicalDeviceGroupPropertiesKHR device_group_info;
855 
856  if(num_device_groups > 0) {
857  // we always use the first group
858  num_device_groups = 1;
859  _VK(qvkEnumeratePhysicalDeviceGroupsKHR(qvk.instance, &num_device_groups, &device_group_info));
860 
861  if (device_group_info.physicalDeviceCount > VKPT_MAX_GPUS) {
862  return qfalse;
863  }
864 
865  device_group_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHR;
866  device_group_create_info.pNext = NULL;
867  device_group_create_info.physicalDeviceCount = device_group_info.physicalDeviceCount;
868  device_group_create_info.pPhysicalDevices = device_group_info.physicalDevices;
869 
870  qvk.device_count = device_group_create_info.physicalDeviceCount;
871  for(int i = 0; i < qvk.device_count; i++) {
872  qvk.device_group_physical_devices[i] = device_group_create_info.pPhysicalDevices[i];
873  }
874  } else
875 #endif
876  qvk.device_count = 1;
877 
878  int picked_device = -1;
879  for(int i = 0; i < num_devices; i++) {
880  VkPhysicalDeviceProperties dev_properties;
881  VkPhysicalDeviceFeatures dev_features;
882  vkGetPhysicalDeviceProperties(devices[i], &dev_properties);
883  vkGetPhysicalDeviceFeatures (devices[i], &dev_features);
884 
885  Com_Printf("Physical device %d: %s\n", i, dev_properties.deviceName);
886  Com_Printf("Max number of allocations: %d\n", dev_properties.limits.maxMemoryAllocationCount);
887  uint32_t num_ext;
888  vkEnumerateDeviceExtensionProperties(devices[i], NULL, &num_ext, NULL);
889 
890  VkExtensionProperties *ext_properties = alloca(sizeof(VkExtensionProperties) * num_ext);
891  vkEnumerateDeviceExtensionProperties(devices[i], NULL, &num_ext, ext_properties);
892 
893  Com_Printf("Supported Vulkan device extensions:\n");
894  for(int j = 0; j < num_ext; j++) {
895  Com_Printf(" %s\n", ext_properties[j].extensionName);
896  if(!strcmp(ext_properties[j].extensionName, VK_NV_RAY_TRACING_EXTENSION_NAME)) {
897  if(picked_device < 0)
898  picked_device = i;
899  }
900  }
901  }
902 
903  if(picked_device < 0) {
904  Com_Error(ERR_FATAL, "No ray tracing capable GPU found.");
905  }
906 
907  qvk.physical_device = devices[picked_device];
908 
909  {
910  VkPhysicalDeviceProperties dev_properties;
911  vkGetPhysicalDeviceProperties(devices[picked_device], &dev_properties);
912 
913  Com_Printf("Picked physical device %d: %s\n", picked_device, dev_properties.deviceName);
914 
915 #ifdef _WIN32
916  if (dev_properties.vendorID == 0x10de) // NVIDIA vendor ID
917  {
918  uint32_t driver_major = (dev_properties.driverVersion >> 22) & 0x3ff;
919  uint32_t driver_minor = (dev_properties.driverVersion >> 14) & 0xff;
920 
921  Com_Printf("NVIDIA GPU detected. Driver version: %u.%02u\n", driver_major, driver_minor);
922 
923  uint32_t required_major = 0;
924  uint32_t required_minor = 0;
925  int nfields = sscanf(cvar_min_driver_version->string, "%u.%u", &required_major, &required_minor);
926  if (nfields == 2)
927  {
928  if (driver_major < required_major || driver_major == required_major && driver_minor < required_minor)
929  {
930  Com_Error(ERR_FATAL, "This game requires NVIDIA Graphics Driver version to be at least %u.%02u, while the installed version is %u.%02u.\nPlease update the NVIDIA Graphics Driver.",
931  required_major, required_minor, driver_major, driver_minor);
932  }
933  }
934  }
935 #endif
936  }
937 
938  vkGetPhysicalDeviceMemoryProperties(qvk.physical_device, &qvk.mem_properties);
939 
940  /* queue family and create physical device */
941  uint32_t num_queue_families = 0;
942  vkGetPhysicalDeviceQueueFamilyProperties(qvk.physical_device, &num_queue_families, NULL);
943  VkQueueFamilyProperties *queue_families = alloca(sizeof(VkQueueFamilyProperties) * num_queue_families);
944  vkGetPhysicalDeviceQueueFamilyProperties(qvk.physical_device, &num_queue_families, queue_families);
945 
946  // Com_Printf("num queue families: %d\n", num_queue_families);
947 
948  qvk.queue_idx_graphics = -1;
949  qvk.queue_idx_compute = -1;
950  qvk.queue_idx_transfer = -1;
951 
952  for(int i = 0; i < num_queue_families; i++) {
953  if(!queue_families[i].queueCount)
954  continue;
955  VkBool32 present_support = 0;
956  vkGetPhysicalDeviceSurfaceSupportKHR(qvk.physical_device, i, qvk.surface, &present_support);
957 
958  const int supports_graphics = queue_families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT;
959  const int supports_compute = queue_families[i].queueFlags & VK_QUEUE_COMPUTE_BIT;
960  const int supports_transfer = queue_families[i].queueFlags & VK_QUEUE_TRANSFER_BIT;
961 
962  if(supports_graphics && supports_compute && supports_transfer && qvk.queue_idx_graphics < 0) {
963  if(!present_support)
964  continue;
966  }
967  else if(supports_compute && qvk.queue_idx_compute < 0) {
969  }
970  else if(supports_transfer && qvk.queue_idx_transfer < 0) {
972  }
973  }
974 
976  Com_Error(ERR_FATAL, "Could not find a suitable Vulkan queue family!\n");
977  return qfalse;
978  }
979 
980  float queue_priorities = 1.0f;
981  int num_create_queues = 0;
982  VkDeviceQueueCreateInfo queue_create_info[3];
983 
984  {
985  VkDeviceQueueCreateInfo q = {
986  .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
987  .queueCount = 1,
988  .pQueuePriorities = &queue_priorities,
989  .queueFamilyIndex = qvk.queue_idx_graphics,
990  };
991 
992  queue_create_info[num_create_queues++] = q;
993  };
995  VkDeviceQueueCreateInfo q = {
996  .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
997  .queueCount = 1,
998  .pQueuePriorities = &queue_priorities,
999  .queueFamilyIndex = qvk.queue_idx_compute,
1000  };
1001  queue_create_info[num_create_queues++] = q;
1002  };
1004  VkDeviceQueueCreateInfo q = {
1005  .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
1006  .queueCount = 1,
1007  .pQueuePriorities = &queue_priorities,
1008  .queueFamilyIndex = qvk.queue_idx_transfer,
1009  };
1010  queue_create_info[num_create_queues++] = q;
1011  };
1012 
1013  VkPhysicalDeviceDescriptorIndexingFeaturesEXT idx_features = {
1014  .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT,
1015  .runtimeDescriptorArray = 1,
1016  .shaderSampledImageArrayNonUniformIndexing = 1,
1017  };
1018 
1019 #ifdef VKPT_DEVICE_GROUPS
1020  if (qvk.device_count > 1) {
1021  Com_Printf("Enabling multi-GPU support\n");
1022  idx_features.pNext = &device_group_create_info;
1023  }
1024 #endif
1025 
1026  VkPhysicalDeviceFeatures2 device_features = {
1027  .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR,
1028  .pNext = &idx_features,
1029 
1030  .features = {
1031  .robustBufferAccess = 1,
1032  .fullDrawIndexUint32 = 1,
1033  .imageCubeArray = 1,
1034  .independentBlend = 1,
1035  .geometryShader = 1,
1036  .tessellationShader = 1,
1037  .sampleRateShading = 0,
1038  .dualSrcBlend = 1,
1039  .logicOp = 1,
1040  .multiDrawIndirect = 1,
1041  .drawIndirectFirstInstance = 1,
1042  .depthClamp = 1,
1043  .depthBiasClamp = 1,
1044  .fillModeNonSolid = 0,
1045  .depthBounds = 1,
1046  .wideLines = 0,
1047  .largePoints = 0,
1048  .alphaToOne = 1,
1049  .multiViewport = 0,
1050  .samplerAnisotropy = 1,
1051  .textureCompressionETC2 = 0,
1052  .textureCompressionASTC_LDR = 0,
1053  .textureCompressionBC = 0,
1054  .occlusionQueryPrecise = 0,
1055  .pipelineStatisticsQuery = 1,
1056  .vertexPipelineStoresAndAtomics = 1,
1057  .fragmentStoresAndAtomics = 1,
1058  .shaderTessellationAndGeometryPointSize = 1,
1059  .shaderImageGatherExtended = 1,
1060  .shaderStorageImageExtendedFormats = 1,
1061  .shaderStorageImageMultisample = 1,
1062  .shaderStorageImageReadWithoutFormat = 1,
1063  .shaderStorageImageWriteWithoutFormat = 1,
1064  .shaderUniformBufferArrayDynamicIndexing = 1,
1065  .shaderSampledImageArrayDynamicIndexing = 1,
1066  .shaderStorageBufferArrayDynamicIndexing = 1,
1067  .shaderStorageImageArrayDynamicIndexing = 1,
1068  .shaderClipDistance = 1,
1069  .shaderCullDistance = 1,
1070  .shaderFloat64 = 1,
1071  .shaderInt64 = 1,
1072  .shaderInt16 = 1,
1073  .shaderResourceResidency = 1,
1074  .shaderResourceMinLod = 1,
1075  .sparseBinding = 1,
1076  .sparseResidencyBuffer = 1,
1077  .sparseResidencyImage2D = 1,
1078  .sparseResidencyImage3D = 1,
1079  .sparseResidency2Samples = 1,
1080  .sparseResidency4Samples = 1,
1081  .sparseResidency8Samples = 1,
1082  .sparseResidency16Samples = 1,
1083  .sparseResidencyAliased = 1,
1084  .variableMultisampleRate = 0,
1085  .inheritedQueries = 1,
1086  }
1087  };
1088  VkDeviceCreateInfo dev_create_info = {
1089  .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
1090  .pNext = &device_features,
1091  .pQueueCreateInfos = queue_create_info,
1092  .queueCreateInfoCount = num_create_queues,
1093  .enabledExtensionCount = LENGTH(vk_requested_device_extensions),
1094  .ppEnabledExtensionNames = vk_requested_device_extensions,
1095  };
1096 
1097  /* create device and queue */
1098  result = vkCreateDevice(qvk.physical_device, &dev_create_info, NULL, &qvk.device);
1099  if (result != VK_SUCCESS)
1100  {
1101  Com_Error(ERR_FATAL, "Failed to create a Vulkan device.\nError code: %s", qvk_result_to_string(result));
1102  return qfalse;
1103  }
1104 
1105  vkGetDeviceQueue(qvk.device, qvk.queue_idx_graphics, 0, &qvk.queue_graphics);
1106  vkGetDeviceQueue(qvk.device, qvk.queue_idx_compute, 0, &qvk.queue_compute);
1107  vkGetDeviceQueue(qvk.device, qvk.queue_idx_transfer, 0, &qvk.queue_transfer);
1108 
1109 #define _VK_EXTENSION_DO(a) \
1110  q##a = (PFN_##a) vkGetDeviceProcAddr(qvk.device, #a); \
1111  if(!q##a) { Com_EPrintf("warning: could not load function %s\n", #a); }
1113 #undef _VK_EXTENSION_DO
1114 
1115  Com_Printf("-----------------------\n");
1116 
1117  return qtrue;
1118 }
1119 
1120 static VkShaderModule
1121 create_shader_module_from_file(const char *name, const char *enum_name)
1122 {
1123  char path[1024];
1124  snprintf(path, sizeof path, SHADER_PATH_TEMPLATE, name ? name : (enum_name + 8));
1125  if(!name) {
1126  int len = 0;
1127  for(len = 0; path[len]; len++)
1128  path[len] = tolower(path[len]);
1129  while(--len >= 0) {
1130  if(path[len] == '_') {
1131  path[len] = '.';
1132  break;
1133  }
1134  }
1135  }
1136 
1137  char *data;
1138  size_t size;
1139 
1140  size = FS_LoadFile(path, &data);
1141  if(!data) {
1142  Com_EPrintf("Couldn't find shader module %s!\n", path);
1143  return VK_NULL_HANDLE;
1144  }
1145 
1146  VkShaderModule module;
1147 
1148  VkShaderModuleCreateInfo create_info = {
1149  .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
1150  .codeSize = size,
1151  .pCode = (uint32_t *) data,
1152  };
1153 
1154  _VK(vkCreateShaderModule(qvk.device, &create_info, NULL, &module));
1155 
1156  Z_Free(data);
1157 
1158  return module;
1159 }
1160 
1161 VkResult
1163 {
1164  VkResult ret = VK_SUCCESS;
1165 #define SHADER_MODULE_DO(a) do { \
1166  qvk.shader_modules[a] = create_shader_module_from_file(shader_module_file_names[a], #a); \
1167  ret = (ret == VK_SUCCESS && qvk.shader_modules[a]) ? VK_SUCCESS : VK_ERROR_INITIALIZATION_FAILED; \
1168  if(qvk.shader_modules[a]) { \
1169  ATTACH_LABEL_VARIABLE_NAME((uint64_t)qvk.shader_modules[a], SHADER_MODULE, #a); \
1170  }\
1171  } while(0);
1172 
1174 
1175 #undef SHADER_MODULE_DO
1176  return ret;
1177 }
1178 
1179 VkResult
1181 {
1182 #define SHADER_MODULE_DO(a) \
1183  vkDestroyShaderModule(qvk.device, qvk.shader_modules[a], NULL); \
1184  qvk.shader_modules[a] = VK_NULL_HANDLE;
1185 
1187 
1188 #undef SHADER_MODULE_DO
1189 
1190  return VK_SUCCESS;
1191 }
1192 
1193 VkResult
1195 {
1196  for(int i = 0; i < qvk.num_swap_chain_images; i++) {
1197  vkDestroyImageView (qvk.device, qvk.swap_chain_image_views[i], NULL);
1198  }
1199 
1200  vkDestroySwapchainKHR(qvk.device, qvk.swap_chain, NULL);
1201  return VK_SUCCESS;
1202 }
1203 
1204 int
1206 {
1207  vkDeviceWaitIdle(qvk.device);
1208 
1210  vkDestroySurfaceKHR(qvk.instance, qvk.surface, NULL);
1211 
1212  for (int frame = 0; frame < MAX_FRAMES_IN_FLIGHT; frame++)
1213  {
1214  for (int gpu = 0; gpu < qvk.device_count; gpu++)
1215  {
1216  semaphore_group_t* group = &qvk.semaphores[frame][gpu];
1217 
1218  vkDestroySemaphore(qvk.device, group->image_available, NULL);
1219  vkDestroySemaphore(qvk.device, group->render_finished, NULL);
1220  vkDestroySemaphore(qvk.device, group->transfer_finished, NULL);
1221  vkDestroySemaphore(qvk.device, group->trace_finished, NULL);
1222  }
1223  }
1224 
1225  for(int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
1226  vkDestroyFence(qvk.device, qvk.fences_frame_sync[i], NULL);
1227  }
1228  vkDestroyFence(qvk.device, qvk.fence_vertex_sync, NULL);
1229 
1233 
1234  vkDestroyCommandPool(qvk.device, qvk.cmd_buffers_graphics.command_pool, NULL);
1235  vkDestroyCommandPool(qvk.device, qvk.cmd_buffers_compute.command_pool, NULL);
1236  vkDestroyCommandPool(qvk.device, qvk.cmd_buffers_transfer.command_pool, NULL);
1237 
1238  vkDestroyDevice(qvk.device, NULL);
1240  vkDestroyInstance(qvk.instance, NULL);
1241 
1242  free(qvk.extensions);
1243  qvk.extensions = NULL;
1244  qvk.num_extensions = 0;
1245 
1246  free(qvk.layers);
1247  qvk.layers = NULL;
1248  qvk.num_layers = 0;
1249 
1250  return 0;
1251 }
1252 
1253 typedef struct entity_hash_s {
1254  unsigned int mesh : 8;
1255  unsigned int model : 9;
1256  unsigned int entity : 15;
1257 } entity_hash_t;
1258 
1259 static int entity_frame_num = 0;
1260 static int model_entity_ids[2][MAX_ENTITIES];
1261 static int world_entity_ids[2][MAX_ENTITIES];
1264 
1265 #define MAX_MODEL_LIGHTS 1024
1266 static int num_model_lights = 0;
1268 
1269 static pbr_material_t const * get_mesh_material(const entity_t* entity, const maliasmesh_t* mesh)
1270 {
1271  if (entity->skin)
1272  {
1273  return MAT_UpdatePBRMaterialSkin(IMG_ForHandle(entity->skin));
1274  }
1275 
1276  int skinnum = 0;
1277  if (mesh->materials[entity->skinnum])
1278  skinnum = entity->skinnum;
1279 
1280  return mesh->materials[skinnum];
1281 }
1282 
1283 static inline uint32_t fill_model_instance(const entity_t* entity, const model_t* model, const maliasmesh_t* mesh,
1284  const float* transform, int model_instance_index, qboolean is_viewer_weapon, qboolean is_double_sided)
1285 {
1286  pbr_material_t const * material = get_mesh_material(entity, mesh);
1287 
1288  if (!material)
1289  {
1290  Com_EPrintf("Cannot find material for model '%s'\n", model->name);
1291  return 0;
1292  }
1293 
1294  int material_id = material->flags;
1295 
1296  if(MAT_IsKind(material_id, MATERIAL_KIND_INVISIBLE))
1297  return 0; // skip the mesh
1298 
1299  if(MAT_IsKind(material_id, MATERIAL_KIND_CHROME))
1300  material_id = MAT_SetKind(material_id, MATERIAL_KIND_CHROME_MODEL);
1301 
1302  if (model->model_class == MCLASS_EXPLOSION)
1303  {
1304  material_id = MAT_SetKind(material_id, MATERIAL_KIND_EXPLOSION);
1305  material_id |= MATERIAL_FLAG_LIGHT;
1306  }
1307 
1308  if (is_viewer_weapon)
1309  material_id |= MATERIAL_FLAG_WEAPON;
1310 
1311  if (is_double_sided)
1312  material_id |= MATERIAL_FLAG_DOUBLE_SIDED;
1313 
1314  if (!MAT_IsKind(material_id, MATERIAL_KIND_GLASS))
1315  {
1316  if (entity->flags & RF_SHELL_RED)
1317  material_id |= MATERIAL_FLAG_SHELL_RED;
1318  if (entity->flags & RF_SHELL_GREEN)
1319  material_id |= MATERIAL_FLAG_SHELL_GREEN;
1320  if (entity->flags & RF_SHELL_BLUE)
1321  material_id |= MATERIAL_FLAG_SHELL_BLUE;
1322  }
1323 
1324  ModelInstance* instance = &vkpt_refdef.uniform_instance_buffer.model_instances[model_instance_index];
1325 
1326  int frame = entity->frame;
1327  int oldframe = entity->oldframe;
1328  if (frame >= model->numframes) frame = 0;
1329  if (oldframe >= model->numframes) oldframe = 0;
1330 
1331  memcpy(instance->M, transform, sizeof(float) * 16);
1332  instance->offset_curr = mesh->vertex_offset + frame * mesh->numverts;
1333  instance->offset_prev = mesh->vertex_offset + oldframe * mesh->numverts;
1334  instance->backlerp = entity->backlerp;
1335  instance->material = material_id;
1336  instance->alpha = (entity->flags & RF_TRANSLUCENT) ? entity->alpha : 1.0f;
1337 
1338  return material_id;
1339 }
1340 
1341 static void
1342 add_dlights(const dlight_t* lights, int num_lights, QVKUniformBuffer_t* ubo)
1343 {
1344  ubo->num_sphere_lights = 0;
1345 
1346  for (int i = 0; i < num_lights; i++)
1347  {
1348  const dlight_t* light = lights + i;
1349 
1350  float* dynlight_data = (float*)(ubo->sphere_light_data + ubo->num_sphere_lights * 2);
1351  float* center = dynlight_data;
1352  float* radius = dynlight_data + 3;
1353  float* color = dynlight_data + 4;
1354  dynlight_data[7] = 0.f;
1355 
1356  VectorCopy(light->origin, center);
1357  VectorScale(light->color, light->intensity / 25.f, color);
1358  *radius = light->radius;
1359 
1360  ubo->num_sphere_lights++;
1361  }
1362 }
1363 
1364 static inline void transform_point(const float* p, const float* matrix, float* result)
1365 {
1366  vec4_t point = { p[0], p[1], p[2], 1.f };
1367  vec4_t transformed;
1368  mult_matrix_vector(transformed, matrix, point);
1369  VectorCopy(transformed, result); // vec4 -> vec3
1370 }
1371 
1372 static void process_bsp_entity(const entity_t* entity, int* bsp_mesh_idx, int* instance_idx, int* num_instanced_vert)
1373 {
1374  QVKInstanceBuffer_t* uniform_instance_buffer = &vkpt_refdef.uniform_instance_buffer;
1375  uint32_t* ubo_bsp_cluster_id = (uint32_t*)uniform_instance_buffer->bsp_cluster_id;
1376  uint32_t* ubo_bsp_prim_offset = (uint32_t*)uniform_instance_buffer->bsp_prim_offset;
1377  uint32_t* ubo_instance_buf_offset = (uint32_t*)uniform_instance_buffer->bsp_instance_buf_offset;
1378  uint32_t* ubo_instance_buf_size = (uint32_t*)uniform_instance_buffer->bsp_instance_buf_size;
1379 
1380  const int current_bsp_mesh_index = *bsp_mesh_idx;
1381  if (current_bsp_mesh_index >= SHADER_MAX_BSP_ENTITIES)
1382  {
1383  assert(!"BSP entity count overflow");
1384  return;
1385  }
1386 
1387  if (*instance_idx >= (SHADER_MAX_ENTITIES + SHADER_MAX_BSP_ENTITIES))
1388  {
1389  assert(!"Total entity count overflow");
1390  return;
1391  }
1392 
1393  world_entity_ids[entity_frame_num][current_bsp_mesh_index] = entity->id;
1394 
1395  float transform[16];
1396  create_entity_matrix(transform, (entity_t*)entity, qfalse);
1397  BspMeshInstance* ubo_instance_info = uniform_instance_buffer->bsp_mesh_instances + current_bsp_mesh_index;
1398  memcpy(&ubo_instance_info->M, transform, sizeof(transform));
1399  ubo_instance_info->frame = entity->frame;
1400  memset(ubo_instance_info->padding, 0, sizeof(ubo_instance_info->padding));
1401 
1402  bsp_model_t* model = vkpt_refdef.bsp_mesh_world.models + (~entity->model);
1403 
1404  vec3_t origin;
1405  transform_point(model->center, transform, origin);
1406  int cluster = BSP_PointLeaf(bsp_world_model->nodes, origin)->cluster;
1407 
1408  if (cluster < 0)
1409  {
1410  // In some cases, a model slides into a wall, like a push button, so that its center
1411  // is no longer in any BSP node. We still need to assign a cluster to the model,
1412  // so try the corners of the model instead, see if any of them has a valid cluster.
1413 
1414  for (int corner = 0; corner < 8; corner++)
1415  {
1416  vec3_t corner_pt = {
1417  (corner & 1) ? model->aabb_max[0] : model->aabb_min[0],
1418  (corner & 2) ? model->aabb_max[1] : model->aabb_min[1],
1419  (corner & 4) ? model->aabb_max[2] : model->aabb_min[2]
1420  };
1421 
1422  vec3_t corner_pt_world;
1423  transform_point(corner_pt, transform, corner_pt_world);
1424 
1425  cluster = BSP_PointLeaf(bsp_world_model->nodes, corner_pt_world)->cluster;
1426 
1427  if(cluster >= 0)
1428  break;
1429  }
1430  }
1431  ubo_bsp_cluster_id[current_bsp_mesh_index] = cluster;
1432 
1433  ubo_bsp_prim_offset[current_bsp_mesh_index] = model->idx_offset / 3;
1434 
1435  const int mesh_vertex_num = model->idx_count;
1436 
1437  ubo_instance_buf_offset[current_bsp_mesh_index] = *num_instanced_vert / 3;
1438  ubo_instance_buf_size[current_bsp_mesh_index] = mesh_vertex_num / 3;
1439 
1440  ((int*)uniform_instance_buffer->model_indices)[*instance_idx] = ~current_bsp_mesh_index;
1441 
1442  *num_instanced_vert += mesh_vertex_num;
1443 
1444  for (int nlight = 0; nlight < model->num_light_polys; nlight++)
1445  {
1447  {
1448  assert(!"Model light count overflow");
1449  break;
1450  }
1451 
1452  const light_poly_t* src_light = model->light_polys + nlight;
1454 
1455  // Transform the light's positions and center
1456  transform_point(src_light->positions + 0, transform, dst_light->positions + 0);
1457  transform_point(src_light->positions + 3, transform, dst_light->positions + 3);
1458  transform_point(src_light->positions + 6, transform, dst_light->positions + 6);
1459  transform_point(src_light->off_center, transform, dst_light->off_center);
1460 
1461  // Find the cluster based on the center. Maybe it's OK to use the model's cluster, need to test.
1462  dst_light->cluster = BSP_PointLeaf(bsp_world_model->nodes, dst_light->off_center)->cluster;
1463 
1464  // We really need to map these lights to a cluster
1465  if(dst_light->cluster < 0)
1466  continue;
1467 
1468  // Copy the other light properties
1469  VectorCopy(src_light->color, dst_light->color);
1470  dst_light->material = src_light->material;
1471 
1472  num_model_lights++;
1473  }
1474 
1475  (*bsp_mesh_idx)++;
1476  (*instance_idx)++;
1477 }
1478 
1479 static inline qboolean is_transparent_material(uint32_t material)
1480 {
1481  return MAT_IsKind(material, MATERIAL_KIND_SLIME)
1482  || MAT_IsKind(material, MATERIAL_KIND_WATER)
1483  || MAT_IsKind(material, MATERIAL_KIND_GLASS)
1484  || MAT_IsKind(material, MATERIAL_KIND_TRANSPARENT);
1485 }
1486 
1487 #define MESH_FILTER_TRANSPARENT 1
1488 #define MESH_FILTER_OPAQUE 2
1489 #define MESH_FILTER_ALL 3
1490 
1492  const entity_t* entity,
1493  const model_t* model,
1494  qboolean is_viewer_weapon,
1495  qboolean is_double_sided,
1496  int* model_instance_idx,
1497  int* instance_idx,
1498  int* num_instanced_vert,
1499  int mesh_filter,
1500  qboolean* contains_transparent)
1501 {
1502  QVKInstanceBuffer_t* uniform_instance_buffer = &vkpt_refdef.uniform_instance_buffer;
1503  uint32_t* ubo_instance_buf_offset = (uint32_t*)uniform_instance_buffer->model_instance_buf_offset;
1504  uint32_t* ubo_instance_buf_size = (uint32_t*)uniform_instance_buffer->model_instance_buf_size;
1505  uint32_t* ubo_model_idx_offset = (uint32_t*)uniform_instance_buffer->model_idx_offset;
1506  uint32_t* ubo_model_cluster_id = (uint32_t*)uniform_instance_buffer->model_cluster_id;
1507 
1508  float transform[16];
1509  create_entity_matrix(transform, (entity_t*)entity, is_viewer_weapon);
1510 
1511  int current_model_instance_index = *model_instance_idx;
1512  int current_instance_index = *instance_idx;
1513  int current_num_instanced_vert = *num_instanced_vert;
1514 
1515  if (contains_transparent)
1516  *contains_transparent = qfalse;
1517 
1518  for (int i = 0; i < model->nummeshes; i++)
1519  {
1520  const maliasmesh_t* mesh = model->meshes + i;
1521 
1522  if (current_model_instance_index >= SHADER_MAX_ENTITIES)
1523  {
1524  assert(!"Model entity count overflow");
1525  break;
1526  }
1527 
1528  if (current_instance_index >= (SHADER_MAX_ENTITIES + SHADER_MAX_BSP_ENTITIES))
1529  {
1530  assert(!"Total entity count overflow");
1531  break;
1532  }
1533 
1534  uint32_t material_id = fill_model_instance(entity, model, mesh, transform, current_model_instance_index, is_viewer_weapon, is_double_sided);
1535  if (!material_id)
1536  continue;
1537 
1538  if (is_transparent_material(material_id))
1539  {
1540  if(contains_transparent)
1541  *contains_transparent = qtrue;
1542 
1543  if(!(mesh_filter & MESH_FILTER_TRANSPARENT))
1544  continue;
1545  }
1546  else
1547  {
1548  if (!(mesh_filter & MESH_FILTER_OPAQUE))
1549  continue;
1550  }
1551 
1552  entity_hash_t hash;
1553  hash.entity = entity->id;
1554  hash.model = entity->model;
1555  hash.mesh = i;
1556 
1557  model_entity_ids[entity_frame_num][current_model_instance_index] = *(uint32_t*)&hash;
1558 
1559  uint32_t cluster_id = ~0u;
1560  if(bsp_world_model)
1561  cluster_id = BSP_PointLeaf(bsp_world_model->nodes, ((entity_t*)entity)->origin)->cluster;
1562  ubo_model_cluster_id[current_model_instance_index] = cluster_id;
1563 
1564  ubo_model_idx_offset[current_model_instance_index] = mesh->idx_offset;
1565 
1566  ubo_instance_buf_offset[current_model_instance_index] = current_num_instanced_vert / 3;
1567  ubo_instance_buf_size[current_model_instance_index] = mesh->numtris;
1568 
1569  ((int*)uniform_instance_buffer->model_indices)[current_instance_index] = current_model_instance_index;
1570 
1571  current_model_instance_index++;
1572  current_instance_index++;
1573  current_num_instanced_vert += mesh->numtris * 3;
1574  }
1575 
1576  // add cylinder lights for wall lamps
1577  if (model->model_class == MCLASS_STATIC_LIGHT)
1578  {
1579  vec4_t begin, end, color;
1580  vec4_t offset1 = { 0.f, 0.5f, -10.f, 1.f };
1581  vec4_t offset2 = { 0.f, 0.5f, 10.f, 1.f };
1582 
1583  mult_matrix_vector(begin, transform, offset1);
1584  mult_matrix_vector(end, transform, offset2);
1585  VectorSet(color, 0.25f, 0.5f, 0.07f);
1586 
1588  }
1589 
1590  *model_instance_idx = current_model_instance_index;
1591  *instance_idx = current_instance_index;
1592  *num_instanced_vert = current_num_instanced_vert;
1593 }
1594 
1595 #if CL_RTX_SHADERBALLS
1596 extern vec3_t cl_dev_shaderballs_pos;
1597 
1598 void
1599 vkpt_drop_shaderballs()
1600 {
1601  VectorCopy(vkpt_refdef.fd->vieworg, cl_dev_shaderballs_pos);
1602  cl_dev_shaderballs_pos[2] -= 46.12f; // player eye-level
1603 }
1604 #endif
1605 
1606 static void
1608 {
1610 
1612 
1613  memcpy(instance_buffer->bsp_mesh_instances_prev, instance_buffer->bsp_mesh_instances,
1614  sizeof(instance_buffer->bsp_mesh_instances_prev));
1615  memcpy(instance_buffer->model_instances_prev, instance_buffer->model_instances,
1616  sizeof(instance_buffer->model_instances_prev));
1617 
1618  memcpy(instance_buffer->bsp_cluster_id_prev, instance_buffer->bsp_cluster_id, sizeof(instance_buffer->bsp_cluster_id));
1619  memcpy(instance_buffer->model_cluster_id_prev, instance_buffer->model_cluster_id, sizeof(instance_buffer->model_cluster_id));
1620 
1621  static int transparent_model_indices[MAX_ENTITIES];
1622  static int viewer_model_indices[MAX_ENTITIES];
1623  static int viewer_weapon_indices[MAX_ENTITIES];
1624  static int explosion_indices[MAX_ENTITIES];
1625  int transparent_model_num = 0;
1626  int viewer_model_num = 0;
1627  int viewer_weapon_num = 0;
1628  int explosion_num = 0;
1629 
1630  int model_instance_idx = 0;
1631  int bsp_mesh_idx = 0;
1632  int num_instanced_vert = 0; /* need to track this here to find lights */
1633  int instance_idx = 0;
1634 
1635  const qboolean first_person_model = (cl_player_model->integer == CL_PLAYER_MODEL_FIRST_PERSON) && cl.baseclientinfo.model;
1636 
1637  for (int i = 0; i < vkpt_refdef.fd->num_entities; i++)
1638  {
1639  const entity_t* entity = vkpt_refdef.fd->entities + i;
1640 
1641  if (entity->model & 0x80000000)
1642  {
1643  const bsp_model_t* model = vkpt_refdef.bsp_mesh_world.models + (~entity->model);
1644  if (model->transparent)
1645  transparent_model_indices[transparent_model_num++] = i;
1646  else
1647  process_bsp_entity(entity, &bsp_mesh_idx, &instance_idx, &num_instanced_vert); /* embedded in bsp */
1648  }
1649  else
1650  {
1651  const model_t* model = MOD_ForHandle(entity->model);
1652  if (model == NULL || model->meshes == NULL)
1653  continue;
1654 
1655  if (entity->flags & RF_VIEWERMODEL)
1656  viewer_model_indices[viewer_model_num++] = i;
1657  else if (first_person_model && entity->flags & RF_WEAPONMODEL)
1658  viewer_weapon_indices[viewer_weapon_num++] = i;
1659  else if (model->model_class == MCLASS_EXPLOSION || model->model_class == MCLASS_SMOKE)
1660  explosion_indices[explosion_num++] = i;
1661  else
1662  {
1663  qboolean contains_transparent = qfalse;
1664  process_regular_entity(entity, model, qfalse, qfalse, &model_instance_idx, &instance_idx, &num_instanced_vert, MESH_FILTER_OPAQUE, &contains_transparent);
1665 
1666  if(contains_transparent)
1667  transparent_model_indices[transparent_model_num++] = i;
1668  }
1669  }
1670  }
1671 
1672  upload_info->dynamic_vertex_num = num_instanced_vert;
1673 
1674  const uint32_t transparent_model_base_vertex_num = num_instanced_vert;
1675  for (int i = 0; i < transparent_model_num; i++)
1676  {
1677  const entity_t* entity = vkpt_refdef.fd->entities + transparent_model_indices[i];
1678 
1679  if (entity->model & 0x80000000)
1680  {
1681  process_bsp_entity(entity, &bsp_mesh_idx, &instance_idx, &num_instanced_vert);
1682  }
1683  else
1684  {
1685  const model_t* model = MOD_ForHandle(entity->model);
1686  process_regular_entity(entity, model, qfalse, qfalse, &model_instance_idx, &instance_idx, &num_instanced_vert, MESH_FILTER_TRANSPARENT, NULL);
1687  }
1688  }
1689 
1690  upload_info->transparent_model_vertex_offset = transparent_model_base_vertex_num;
1691  upload_info->transparent_model_vertex_num = num_instanced_vert - transparent_model_base_vertex_num;
1692 
1693  const uint32_t viewer_model_base_vertex_num = num_instanced_vert;
1694  if (first_person_model)
1695  {
1696  for (int i = 0; i < viewer_model_num; i++)
1697  {
1698  const entity_t* entity = vkpt_refdef.fd->entities + viewer_model_indices[i];
1699  const model_t* model = MOD_ForHandle(entity->model);
1700  process_regular_entity(entity, model, qfalse, qtrue, &model_instance_idx, &instance_idx, &num_instanced_vert, MESH_FILTER_ALL, NULL);
1701  }
1702  }
1703 
1704  upload_info->viewer_model_vertex_offset = viewer_model_base_vertex_num;
1705  upload_info->viewer_model_vertex_num = num_instanced_vert - viewer_model_base_vertex_num;
1706 
1707  upload_info->weapon_left_handed = qfalse;
1708 
1709  const uint32_t viewer_weapon_base_vertex_num = num_instanced_vert;
1710  for (int i = 0; i < viewer_weapon_num; i++)
1711  {
1712  const entity_t* entity = vkpt_refdef.fd->entities + viewer_weapon_indices[i];
1713  const model_t* model = MOD_ForHandle(entity->model);
1714  process_regular_entity(entity, model, qtrue, qfalse, &model_instance_idx, &instance_idx, &num_instanced_vert, MESH_FILTER_ALL, NULL);
1715 
1716  if (entity->flags & RF_LEFTHAND)
1717  upload_info->weapon_left_handed = qtrue;
1718  }
1719 
1720  upload_info->viewer_weapon_vertex_offset = viewer_weapon_base_vertex_num;
1721  upload_info->viewer_weapon_vertex_num = num_instanced_vert - viewer_weapon_base_vertex_num;
1722 
1723  const uint32_t explosion_base_vertex_num = num_instanced_vert;
1724  for (int i = 0; i < explosion_num; i++)
1725  {
1726  const entity_t* entity = vkpt_refdef.fd->entities + explosion_indices[i];
1727  const model_t* model = MOD_ForHandle(entity->model);
1728  process_regular_entity(entity, model, qfalse, qfalse, &model_instance_idx, &instance_idx, &num_instanced_vert, MESH_FILTER_ALL, NULL);
1729  }
1730 
1731  upload_info->explosions_vertex_offset = explosion_base_vertex_num;
1732  upload_info->explosions_vertex_num = num_instanced_vert - explosion_base_vertex_num;
1733 
1734  upload_info->num_instances = instance_idx;
1735  upload_info->num_vertices = num_instanced_vert;
1736 
1737  memset(instance_buffer->world_current_to_prev, ~0u, sizeof(instance_buffer->world_current_to_prev));
1738  memset(instance_buffer->world_prev_to_current, ~0u, sizeof(instance_buffer->world_prev_to_current));
1739  memset(instance_buffer->model_current_to_prev, ~0u, sizeof(instance_buffer->model_current_to_prev));
1740  memset(instance_buffer->model_prev_to_current, ~0u, sizeof(instance_buffer->model_prev_to_current));
1741 
1742  world_entity_id_count[entity_frame_num] = bsp_mesh_idx;
1743  for(int i = 0; i < world_entity_id_count[entity_frame_num]; i++) {
1744  for(int j = 0; j < world_entity_id_count[!entity_frame_num]; j++) {
1746  instance_buffer->world_current_to_prev[i] = j;
1747  instance_buffer->world_prev_to_current[j] = i;
1748  }
1749  }
1750  }
1751 
1752  model_entity_id_count[entity_frame_num] = model_instance_idx;
1753  for(int i = 0; i < model_entity_id_count[entity_frame_num]; i++) {
1754  for(int j = 0; j < model_entity_id_count[!entity_frame_num]; j++) {
1756 
1758  instance_buffer->model_current_to_prev[i] = j;
1759  instance_buffer->model_prev_to_current[j] = i;
1760  }
1761  }
1762  }
1763 }
1764 
1765 #ifdef VKPT_IMAGE_DUMPS
1766 static void
1767 copy_to_dump_texture(VkCommandBuffer cmd_buf, int src_image_index)
1768 {
1769  VkImage src_image = qvk.images[src_image_index];
1770  VkImage dst_image = qvk.dump_image;
1771 
1772  VkImageCopy image_copy_region = {
1773  .srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
1774  .srcSubresource.mipLevel = 0,
1775  .srcSubresource.baseArrayLayer = 0,
1776  .srcSubresource.layerCount = 1,
1777 
1778  .srcOffset.x = 0,
1779  .srcOffset.y = 0,
1780  .srcOffset.z = 0,
1781 
1782  .dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
1783  .dstSubresource.mipLevel = 0,
1784  .dstSubresource.baseArrayLayer = 0,
1785  .dstSubresource.layerCount = 1,
1786 
1787  .dstOffset.x = 0,
1788  .dstOffset.y = 0,
1789  .dstOffset.z = 0,
1790 
1791  .extent.width = IMG_WIDTH,
1792  .extent.height = IMG_HEIGHT,
1793  .extent.depth = 1
1794  };
1795 
1796  VkImageSubresourceRange subresource_range = {
1797  .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
1798  .baseMipLevel = 0,
1799  .levelCount = 1,
1800  .baseArrayLayer = 0,
1801  .layerCount = 1
1802  };
1803 
1804  IMAGE_BARRIER(cmd_buf,
1805  .image = src_image,
1806  .subresourceRange = subresource_range,
1807  .srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT,
1808  .dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT,
1809  .oldLayout = VK_IMAGE_LAYOUT_GENERAL,
1810  .newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
1811  );
1812 
1813  IMAGE_BARRIER(cmd_buf,
1814  .image = dst_image,
1815  .subresourceRange = subresource_range,
1816  .srcAccessMask = VK_ACCESS_HOST_READ_BIT,
1817  .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
1818  .oldLayout = VK_IMAGE_LAYOUT_GENERAL,
1819  .newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
1820  );
1821 
1822  vkCmdCopyImage(cmd_buf,
1823  src_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1824  dst_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1825  1, &image_copy_region);
1826 
1827  IMAGE_BARRIER(cmd_buf,
1828  .image = src_image,
1829  .subresourceRange = subresource_range,
1830  .srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT,
1831  .dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT,
1832  .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1833  .newLayout = VK_IMAGE_LAYOUT_GENERAL
1834  );
1835 
1836  IMAGE_BARRIER(cmd_buf,
1837  .image = dst_image,
1838  .subresourceRange = subresource_range,
1839  .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
1840  .dstAccessMask = VK_ACCESS_HOST_READ_BIT,
1841  .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1842  .newLayout = VK_IMAGE_LAYOUT_GENERAL
1843  );
1844 }
1845 #endif
1846 
1848 {
1850 }
1851 
1852 static void
1853 process_render_feedback(ref_feedback_t *feedback, mleaf_t* viewleaf, qboolean* sun_visible, float* adapted_luminance)
1854 {
1855  if (viewleaf)
1856  feedback->viewcluster = viewleaf->cluster;
1857  else
1858  feedback->viewcluster = -1;
1859 
1860  {
1861  static char const * unknown = "<unknown>";
1862  char const * view_material = unknown;
1863  char const * view_material_override = unknown;
1864  ReadbackBuffer readback;
1865  vkpt_readback(&readback);
1866  if (readback.material != ~0u)
1867  {
1868  int material_id = readback.material & MATERIAL_INDEX_MASK;
1869  pbr_material_t const * material = MAT_GetPBRMaterial(material_id);
1870  if (material)
1871  {
1872  image_t const * image = material->image_diffuse;
1873  if (image)
1874  {
1875  view_material = image->name;
1876  view_material_override = image->filepath;
1877  }
1878  }
1879  }
1880  strcpy(feedback->view_material, view_material);
1881  strcpy(feedback->view_material_override, view_material_override);
1882 
1883  feedback->lookatcluster = readback.cluster;
1884  feedback->num_light_polys = 0;
1885 
1886  if (vkpt_refdef.bsp_mesh_world_loaded && feedback->lookatcluster >= 0 && feedback->lookatcluster < vkpt_refdef.bsp_mesh_world.num_clusters)
1887  {
1888  int* light_offsets = vkpt_refdef.bsp_mesh_world.cluster_light_offsets + feedback->lookatcluster;
1889  feedback->num_light_polys = light_offsets[1] - light_offsets[0];
1890  }
1891 
1892  VectorCopy(readback.hdr_color, feedback->hdr_color);
1893 
1894  *sun_visible = readback.sun_luminance > 0.f;
1895  *adapted_luminance = readback.adapted_luminance;
1896  }
1897 }
1898 
1899 typedef struct reference_mode_s
1900 {
1907 
1908 static int
1910 {
1911  return max(128, cvar_pt_accumulation_rendering_framenum->integer);
1912 }
1913 
1915 {
1916  return cl_paused->integer == 2 && sv_paused->integer && cvar_pt_accumulation_rendering->integer > 0;
1917 }
1918 
1919 static void draw_shadowed_string(int x, int y, int flags, size_t maxlen, const char* s)
1920 {
1921  R_SetColor(0xff000000u);
1922  SCR_DrawStringEx(x + 1, y + 1, flags, maxlen, s, SCR_GetFont());
1923  R_SetColor(~0u);
1924  SCR_DrawStringEx(x, y, flags, maxlen, s, SCR_GetFont());
1925 }
1926 
1927 static void
1929 {
1931  {
1933 
1934  const int num_warmup_frames = 5;
1935  const int num_frames_to_accumulate = get_accumulation_rendering_framenum();
1936 
1937  ref_mode->enable_accumulation = qtrue;
1938  ref_mode->enable_denoiser = qfalse;
1939  ref_mode->num_bounce_rays = 2;
1940  ref_mode->temporal_blend_factor = 1.f / min(max(1, num_accumulated_frames - num_warmup_frames), num_frames_to_accumulate);
1941  ref_mode->reflect_refract = max(4, cvar_pt_reflect_refract->integer);
1942 
1943  switch (cvar_pt_accumulation_rendering->integer)
1944  {
1945  case 1: {
1946  char text[MAX_QPATH];
1947  float percentage = powf(max(0.f, (num_accumulated_frames - num_warmup_frames) / (float)num_frames_to_accumulate), 0.5f);
1948  Q_snprintf(text, sizeof(text), "Photo mode: accumulating samples... %d%%", (int)(min(1.f, percentage) * 100.f));
1949 
1950  int frames_after_accumulation_finished = num_accumulated_frames - num_warmup_frames - num_frames_to_accumulate;
1951  float hud_alpha = max(0.f, min(1.f, (50 - frames_after_accumulation_finished) * 0.02f)); // fade out for 50 frames after accumulation finishes
1952 
1953  int x = r_config.width / 4;
1954  int y = 30;
1955  R_SetScale(0.5f);
1957  draw_shadowed_string(x, y, UI_CENTER, MAX_QPATH, text);
1958 
1959  if (cvar_pt_dof->integer)
1960  {
1961  x = 5;
1962  y = r_config.height / 2 - 55;
1963  Q_snprintf(text, sizeof(text), "Focal Distance: %.1f", cvar_pt_focus->value);
1964  draw_shadowed_string(x, y, UI_LEFT, MAX_QPATH, text);
1965 
1966  y += 10;
1967  Q_snprintf(text, sizeof(text), "Aperture: %.2f", cvar_pt_aperture->value);
1968  draw_shadowed_string(x, y, UI_LEFT, MAX_QPATH, text);
1969 
1970  y += 10;
1971  draw_shadowed_string(x, y, UI_LEFT, MAX_QPATH, "Use Mouse Wheel, Shift, Ctrl to adjust");
1972  }
1973 
1974  R_SetAlphaScale(1.f);
1975 
1977  break;
1978  }
1979  case 2:
1980  SCR_SetHudAlpha(0.f);
1981  break;
1982  }
1983  }
1984  else
1985  {
1987 
1988  ref_mode->enable_accumulation = qfalse;
1989  ref_mode->enable_denoiser = !!cvar_flt_enable->integer;
1990  if (cvar_pt_num_bounce_rays->value == 0.5f)
1991  ref_mode->num_bounce_rays = 0.5f;
1992  else
1993  ref_mode->num_bounce_rays = max(0, min(2, round(cvar_pt_num_bounce_rays->value)));
1994  ref_mode->temporal_blend_factor = 0.f;
1995  ref_mode->reflect_refract = max(0, cvar_pt_reflect_refract->integer);
1996  }
1997 
1998  ref_mode->reflect_refract = min(10, ref_mode->reflect_refract);
1999 }
2000 
2001 static void
2002 prepare_sky_matrix(float time, vec3_t sky_matrix[3])
2003 {
2004  if (sky_rotation != 0.f)
2005  {
2006  SetupRotationMatrix(sky_matrix, sky_axis, time * sky_rotation);
2007  }
2008  else
2009  {
2010  VectorSet(sky_matrix[0], 1.f, 0.f, 0.f);
2011  VectorSet(sky_matrix[1], 0.f, 1.f, 0.f);
2012  VectorSet(sky_matrix[2], 0.f, 0.f, 1.f);
2013  }
2014 }
2015 
2016 static void
2017 prepare_camera(const vec3_t position, const vec3_t direction, mat4_t data)
2018 {
2019  vec3_t forward, right, up;
2020  VectorCopy(direction, forward);
2022 
2023  if (fabs(forward[2]) < 0.99f)
2024  VectorSet(up, 0.f, 0.f, 1.f);
2025  else
2026  VectorSet(up, 0.f, 1.f, 0.f);
2027 
2028  CrossProduct(forward, up, right);
2029  CrossProduct(right, forward, up);
2032 
2033  float aspect = 1.75f;
2034  float tan_half_fov_x = 1.f;
2035  float tan_half_fov_y = tan_half_fov_x / aspect;
2036 
2037  VectorCopy(position, data + 0);
2038  VectorCopy(forward, data + 4);
2039  VectorMA(data + 4, -tan_half_fov_x, right, data + 4);
2040  VectorMA(data + 4, tan_half_fov_y, up, data + 4);
2041  VectorScale(right, 2.f * tan_half_fov_x, data + 8);
2042  VectorScale(up, -2.f * tan_half_fov_y, data + 12);
2043 }
2044 
2045 static void
2046 prepare_ubo(refdef_t *fd, mleaf_t* viewleaf, const reference_mode_t* ref_mode, const vec3_t sky_matrix[3], qboolean render_world)
2047 {
2048  float P[16];
2049  float V[16];
2050 
2052  memcpy(ubo->V_prev, ubo->V, sizeof(float) * 16);
2053  memcpy(ubo->P_prev, ubo->P, sizeof(float) * 16);
2054  memcpy(ubo->invP_prev, ubo->invP, sizeof(float) * 16);
2055  ubo->cylindrical_hfov_prev = ubo->cylindrical_hfov;
2056 
2057  {
2058  float raw_proj[16];
2059  create_projection_matrix(raw_proj, vkpt_refdef.z_near, vkpt_refdef.z_far, fd->fov_x, fd->fov_y);
2060 
2061  // In some cases (ex.: player setup), 'fd' will describe a viewport that is not full screen.
2062  // Simulate that with a projection matrix adjustment to avoid modifying the rendering code.
2063 
2064  float viewport_proj[16] = {
2065  [0] = (float)fd->width / (float)qvk.extent_unscaled.width,
2066  [12] = (float)(fd->x * 2 + fd->width - (int)qvk.extent_unscaled.width) / (float)qvk.extent_unscaled.width,
2067  [5] = (float)fd->height / (float)qvk.extent_unscaled.height,
2068  [13] = -(float)(fd->y * 2 + fd->height - (int)qvk.extent_unscaled.height) / (float)qvk.extent_unscaled.height,
2069  [10] = 1.f,
2070  [15] = 1.f
2071  };
2072 
2073  mult_matrix_matrix(P, viewport_proj, raw_proj);
2074  }
2075  create_view_matrix(V, fd);
2076  memcpy(ubo->V, V, sizeof(float) * 16);
2077  memcpy(ubo->P, P, sizeof(float) * 16);
2078  inverse(V, ubo->invV);
2079  inverse(P, ubo->invP);
2080 
2081  if (cvar_pt_projection->integer == 1 && render_world)
2082  {
2083  float rad_per_pixel = atanf(tanf(fd->fov_y * M_PI / 360.0f) / ((float)qvk.extent_unscaled.height * 0.5f));
2084  ubo->cylindrical_hfov = rad_per_pixel * (float)qvk.extent_unscaled.width;
2085  }
2086  else
2087  {
2088  ubo->cylindrical_hfov = 0.f;
2089  }
2090 
2091  ubo->current_frame_idx = qvk.frame_counter;
2092  ubo->width = qvk.extent_render.width;
2093  ubo->height = qvk.extent_render.height;
2094  ubo->prev_width = qvk.extent_render_prev.width;
2095  ubo->prev_height = qvk.extent_render_prev.height;
2096  ubo->inv_width = 1.0f / (float)qvk.extent_render.width;
2097  ubo->inv_height = 1.0f / (float)qvk.extent_render.height;
2098  ubo->current_gpu_slice_width = qvk.gpu_slice_width;
2099  ubo->prev_gpu_slice_width = qvk.gpu_slice_width_prev;
2100  ubo->screen_image_width = qvk.extent_screen_images.width;
2101  ubo->screen_image_height = qvk.extent_screen_images.height;
2102  ubo->water_normal_texture = water_normal_texture - r_images;
2103  ubo->pt_swap_checkerboard = 0;
2106 
2107  int camera_cluster_contents = viewleaf ? viewleaf->contents : 0;
2108 
2109  if (camera_cluster_contents & CONTENTS_WATER)
2110  ubo->medium = MEDIUM_WATER;
2111  else if (camera_cluster_contents & CONTENTS_SLIME)
2112  ubo->medium = MEDIUM_SLIME;
2113  else if (camera_cluster_contents & CONTENTS_LAVA)
2114  ubo->medium = MEDIUM_LAVA;
2115  else
2116  ubo->medium = MEDIUM_NONE;
2117 
2118  ubo->time = fd->time;
2120  ubo->num_static_lights = vkpt_refdef.bsp_mesh_world.num_light_polys;
2121 
2122 #define UBO_CVAR_DO(name, default_value) ubo->name = cvar_##name->value;
2124 #undef UBO_CVAR_DO
2125 
2126  if (!ref_mode->enable_denoiser)
2127  {
2128  // disable fake specular because it is not supported without denoiser, and the result
2129  // looks too dark with it missing
2130  ubo->pt_fake_roughness_threshold = 1.f;
2131 
2132  // swap the checkerboard fields every frame in reference or noisy mode to accumulate
2133  // both reflection and refraction in every pixel
2134  ubo->pt_swap_checkerboard = (qvk.frame_counter & 1);
2135 
2136  if (ref_mode->enable_accumulation)
2137  {
2138  ubo->pt_texture_lod_bias = -log2(sqrt(get_accumulation_rendering_framenum()));
2139 
2140  // disable the other stabilization hacks
2141  ubo->pt_specular_anti_flicker = 0.f;
2142  ubo->pt_sun_bounce_range = 10000.f;
2143  ubo->pt_ndf_trim = 1.f;
2144  }
2145  }
2146 
2147  {
2148  // figure out if DoF should be enabled in the current rendering mode
2149 
2150  qboolean enable_dof = qtrue;
2151 
2152  switch (cvar_pt_dof->integer)
2153  {
2154  case 0: enable_dof = qfalse; break;
2155  case 1: enable_dof = ref_mode->enable_accumulation; break;
2156  case 2: enable_dof = !ref_mode->enable_denoiser; break;
2157  default: enable_dof = qtrue; break;
2158  }
2159 
2160  if (cvar_pt_projection->integer != 0)
2161  {
2162  // DoF does not make physical sense with the cylindrical projection
2163  enable_dof = qfalse;
2164  }
2165 
2166  if (!enable_dof)
2167  {
2168  // if DoF should not be enabled, make the aperture size zero
2169  ubo->pt_aperture = 0.f;
2170  }
2171  }
2172 
2173  // number of polygon vertices must be an integer
2174  ubo->pt_aperture_type = roundf(ubo->pt_aperture_type);
2175 
2176  ubo->temporal_blend_factor = ref_mode->temporal_blend_factor;
2177  ubo->flt_enable = ref_mode->enable_denoiser;
2178  ubo->flt_taa = ubo->flt_taa && ref_mode->enable_denoiser;
2179  ubo->pt_num_bounce_rays = ref_mode->num_bounce_rays;
2180  ubo->pt_reflect_refract = ref_mode->reflect_refract;
2181 
2182  if (ref_mode->num_bounce_rays < 1.f)
2183  ubo->pt_direct_area_threshold = 10.f; // disable MIS if there are no specular rays
2184 
2185  ubo->pt_min_log_sky_luminance = exp2f(ubo->pt_min_log_sky_luminance);
2186  ubo->pt_max_log_sky_luminance = exp2f(ubo->pt_max_log_sky_luminance);
2187 
2188  memcpy(ubo->cam_pos, fd->vieworg, sizeof(float) * 3);
2189  ubo->cluster_debug_index = cluster_debug_index;
2190 
2191  if (!temporal_frame_valid)
2192  {
2193  ubo->flt_temporal_lf = 0;
2194  ubo->flt_temporal_hf = 0;
2195  ubo->flt_temporal_spec = 0;
2196  ubo->flt_taa = 0;
2197  }
2198 
2199  ubo->first_person_model = cl_player_model->integer == CL_PLAYER_MODEL_FIRST_PERSON;
2200 
2201  memset(ubo->environment_rotation_matrix, 0, sizeof(ubo->environment_rotation_matrix));
2202  VectorCopy(sky_matrix[0], ubo->environment_rotation_matrix + 0);
2203  VectorCopy(sky_matrix[1], ubo->environment_rotation_matrix + 4);
2204  VectorCopy(sky_matrix[2], ubo->environment_rotation_matrix + 8);
2205 
2206  add_dlights(vkpt_refdef.fd->dlights, vkpt_refdef.fd->num_dlights, ubo);
2207 
2208  const bsp_mesh_t* wm = &vkpt_refdef.bsp_mesh_world;
2209  if (wm->num_cameras > 0)
2210  {
2211  for (int n = 0; n < wm->num_cameras; n++)
2212  {
2213  prepare_camera(wm->cameras[n].pos, wm->cameras[n].dir, ubo->security_camera_data[n]);
2214  }
2215  }
2216  else
2217  {
2218  ubo->pt_cameras = 0;
2219  }
2220 
2221  ubo->num_cameras = wm->num_cameras;
2222 }
2223 
2224 
2225 /* renders the map ingame */
2226 void
2227 R_RenderFrame_RTX(refdef_t *fd)
2228 {
2229  vkpt_refdef.fd = fd;
2230  qboolean render_world = (fd->rdflags & RDF_NOWORLDMODEL) == 0;
2231 
2232  static float previous_time = -1.f;
2233  float frame_time = min(1.f, max(0.f, fd->time - previous_time));
2234  previous_time = fd->time;
2235 
2237 
2238  static unsigned previous_wallclock_time = 0;
2239  unsigned current_wallclock_time = Sys_Milliseconds();
2240  float frame_wallclock_time = (previous_wallclock_time != 0) ? (float)(current_wallclock_time - previous_wallclock_time) * 1e-3f : 0.f;
2241  previous_wallclock_time = current_wallclock_time;
2242 
2243  if (!temporal_frame_valid)
2244  {
2245  if (vkpt_refdef.fd && vkpt_refdef.fd->lightstyles)
2246  memcpy(vkpt_refdef.prev_lightstyles, vkpt_refdef.fd->lightstyles, sizeof(vkpt_refdef.prev_lightstyles));
2247  else
2249  }
2250 
2251  mleaf_t* viewleaf = bsp_world_model ? BSP_PointLeaf(bsp_world_model->nodes, fd->vieworg) : NULL;
2252 
2253  qboolean sun_visible_prev = qfalse;
2254  static float prev_adapted_luminance = 0.f;
2255  float adapted_luminance = 0.f;
2256  process_render_feedback(&fd->feedback, viewleaf, &sun_visible_prev, &adapted_luminance);
2257 
2258  // Sometimes, the readback returns 1.0 luminance instead of the real value.
2259  // Ignore these mysterious spikes.
2260  if (adapted_luminance != 1.0f)
2261  prev_adapted_luminance = adapted_luminance;
2262 
2263  if (prev_adapted_luminance <= 0.f)
2264  prev_adapted_luminance = 0.005f;
2265 
2266  LOG_FUNC();
2267  if (!vkpt_refdef.bsp_mesh_world_loaded && render_world)
2268  return;
2269 
2270  vec3_t sky_matrix[3];
2271  prepare_sky_matrix(fd->time, sky_matrix);
2272 
2273  sun_light_t sun_light = { 0 };
2274  if (render_world)
2275  {
2276  vkpt_evaluate_sun_light(&sun_light, sky_matrix, fd->time);
2277 
2279  sun_light.visible = sun_light.visible && sun_visible_prev;
2280  }
2281 
2282  reference_mode_t ref_mode;
2283  evaluate_reference_mode(&ref_mode);
2284 
2285  qboolean menu_mode = cl_paused->integer == 1 && uis.menuDepth > 0 && render_world;
2286 
2287  num_model_lights = 0;
2288  EntityUploadInfo upload_info = { 0 };
2289  prepare_entities(&upload_info);
2290  if (bsp_world_model)
2291  {
2292  vkpt_build_beam_lights(model_lights, &num_model_lights, MAX_MODEL_LIGHTS, bsp_world_model, fd->entities, fd->num_entities, prev_adapted_luminance);
2293  }
2294 
2296  prepare_ubo(fd, viewleaf, &ref_mode, sky_matrix, render_world);
2297  ubo->prev_adapted_luminance = prev_adapted_luminance;
2298 
2299  vkpt_physical_sky_update_ubo(ubo, &sun_light, render_world);
2300  vkpt_bloom_update(ubo, frame_time, ubo->medium != MEDIUM_NONE, menu_mode);
2301 
2302  vec3_t sky_radiance;
2303  VectorScale(avg_envmap_color, ubo->pt_env_scale, sky_radiance);
2305 
2306  float shadowmap_view_proj[16];
2307  float shadowmap_depth_scale;
2309  &sun_light,
2312  shadowmap_view_proj,
2313  &shadowmap_depth_scale,
2315 
2317  ubo,
2319  ubo->P,
2320  ubo->V,
2321  shadowmap_view_proj,
2322  shadowmap_depth_scale);
2323 
2324  qboolean god_rays_enabled = vkpt_god_rays_enabled(&sun_light) && render_world;
2325 
2326  VkSemaphore transfer_semaphores[VKPT_MAX_GPUS];
2327  VkSemaphore trace_semaphores[VKPT_MAX_GPUS];
2328  VkSemaphore prev_trace_semaphores[VKPT_MAX_GPUS];
2329  VkPipelineStageFlags wait_stages[VKPT_MAX_GPUS];
2330  uint32_t device_indices[VKPT_MAX_GPUS];
2331  uint32_t all_device_mask = (1 << qvk.device_count) - 1;
2332  qboolean* prev_trace_signaled = &qvk.semaphores[(qvk.current_frame_index - 1) % MAX_FRAMES_IN_FLIGHT][0].trace_signaled;
2333  qboolean* curr_trace_signaled = &qvk.semaphores[qvk.current_frame_index][0].trace_signaled;
2334 
2335  {
2336  // Transfer the light buffer from staging into device memory.
2337  // Previous frame's tracing still uses device memory, so only do the copy after that is finished.
2338 
2339  VkCommandBuffer transfer_cmd_buf = vkpt_begin_command_buffer(&qvk.cmd_buffers_transfer);
2340 
2341  vkpt_light_buffer_upload_staging(transfer_cmd_buf);
2342 
2343  for (int gpu = 0; gpu < qvk.device_count; gpu++)
2344  {
2345  device_indices[gpu] = gpu;
2346  transfer_semaphores[gpu] = qvk.semaphores[qvk.current_frame_index][gpu].transfer_finished;
2347  trace_semaphores[gpu] = qvk.semaphores[qvk.current_frame_index][gpu].trace_finished;
2348  prev_trace_semaphores[gpu] = qvk.semaphores[(qvk.current_frame_index - 1) % MAX_FRAMES_IN_FLIGHT][gpu].trace_finished;
2349  wait_stages[gpu] = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
2350  }
2351 
2353  transfer_cmd_buf,
2355  all_device_mask,
2356  (*prev_trace_signaled) ? qvk.device_count : 0, prev_trace_semaphores, wait_stages, device_indices,
2357  qvk.device_count, transfer_semaphores, device_indices,
2358  VK_NULL_HANDLE);
2359 
2360  *prev_trace_signaled = qfalse;
2361  }
2362 
2363  {
2364  VkCommandBuffer trace_cmd_buf = vkpt_begin_command_buffer(&qvk.cmd_buffers_graphics);
2365 
2366  update_transparency(trace_cmd_buf, ubo->V, fd->particles, fd->num_particles, fd->entities, fd->num_entities);
2367 
2368  _VK(vkpt_uniform_buffer_update(trace_cmd_buf));
2369 
2370  // put a profiler query without a marker for the frame begin/end - because markers do not
2371  // work well across different command lists
2372  _VK(vkpt_profiler_query(trace_cmd_buf, PROFILER_FRAME_TIME, PROFILER_START));
2373 
2374  BEGIN_PERF_MARKER(trace_cmd_buf, PROFILER_UPDATE_ENVIRONMENT);
2375  if (render_world)
2376  {
2377  vkpt_physical_sky_record_cmd_buffer(trace_cmd_buf);
2378  }
2379  END_PERF_MARKER(trace_cmd_buf, PROFILER_UPDATE_ENVIRONMENT);
2380 
2381  int new_world_anim_frame = (int)(fd->time * 2);
2382  qboolean update_world_animations = (new_world_anim_frame != world_anim_frame);
2383  world_anim_frame = new_world_anim_frame;
2384 
2385  BEGIN_PERF_MARKER(trace_cmd_buf, PROFILER_INSTANCE_GEOMETRY);
2386  vkpt_vertex_buffer_create_instance(trace_cmd_buf, upload_info.num_instances, update_world_animations);
2387  END_PERF_MARKER(trace_cmd_buf, PROFILER_INSTANCE_GEOMETRY);
2388 
2389  BEGIN_PERF_MARKER(trace_cmd_buf, PROFILER_ASVGF_GRADIENT_SAMPLES);
2391  END_PERF_MARKER(trace_cmd_buf, PROFILER_ASVGF_GRADIENT_SAMPLES);
2392 
2393  BEGIN_PERF_MARKER(trace_cmd_buf, PROFILER_BVH_UPDATE);
2394  assert(upload_info.num_vertices % 3 == 0);
2395  build_transparency_blas(trace_cmd_buf);
2396  vkpt_pt_create_all_dynamic(trace_cmd_buf, qvk.current_frame_index, qvk.buf_vertex.buffer, &upload_info);
2397  vkpt_pt_create_toplevel(trace_cmd_buf, qvk.current_frame_index, render_world, upload_info.weapon_left_handed);
2399  END_PERF_MARKER(trace_cmd_buf, PROFILER_BVH_UPDATE);
2400 
2401  BEGIN_PERF_MARKER(trace_cmd_buf, PROFILER_SHADOW_MAP);
2402  if (god_rays_enabled)
2403  {
2404  vkpt_shadow_map_render(trace_cmd_buf, shadowmap_view_proj,
2406  upload_info.dynamic_vertex_num,
2409  }
2410  END_PERF_MARKER(trace_cmd_buf, PROFILER_SHADOW_MAP);
2411 
2412  vkpt_pt_trace_primary_rays(trace_cmd_buf);
2413 
2415  trace_cmd_buf,
2417  all_device_mask,
2418  qvk.device_count, transfer_semaphores, wait_stages, device_indices,
2419  0, 0, 0,
2420  VK_NULL_HANDLE);
2421  }
2422 
2423  {
2424  VkCommandBuffer trace_cmd_buf = vkpt_begin_command_buffer(&qvk.cmd_buffers_graphics);
2425 
2426  if (god_rays_enabled)
2427  {
2428  BEGIN_PERF_MARKER(trace_cmd_buf, PROFILER_GOD_RAYS);
2430  END_PERF_MARKER(trace_cmd_buf, PROFILER_GOD_RAYS);
2431  }
2432 
2433  if (ref_mode.reflect_refract > 0)
2434  {
2435  BEGIN_PERF_MARKER(trace_cmd_buf, PROFILER_REFLECT_REFRACT_1);
2436  vkpt_pt_trace_reflections(trace_cmd_buf, 0);
2437  END_PERF_MARKER(trace_cmd_buf, PROFILER_REFLECT_REFRACT_1);
2438  }
2439 
2440  if (god_rays_enabled)
2441  {
2442  if (ref_mode.reflect_refract > 0)
2443  {
2444  BEGIN_PERF_MARKER(trace_cmd_buf, PROFILER_GOD_RAYS_REFLECT_REFRACT);
2446  END_PERF_MARKER(trace_cmd_buf, PROFILER_GOD_RAYS_REFLECT_REFRACT);
2447  }
2448 
2449  BEGIN_PERF_MARKER(trace_cmd_buf, PROFILER_GOD_RAYS_FILTER);
2451  END_PERF_MARKER(trace_cmd_buf, PROFILER_GOD_RAYS_FILTER);
2452  }
2453 
2454  if (ref_mode.reflect_refract > 1)
2455  {
2456  BEGIN_PERF_MARKER(trace_cmd_buf, PROFILER_REFLECT_REFRACT_2);
2457  for (int pass = 0; pass < ref_mode.reflect_refract - 1; pass++)
2458  {
2459  vkpt_pt_trace_reflections(trace_cmd_buf, pass + 1);
2460  }
2461  END_PERF_MARKER(trace_cmd_buf, PROFILER_REFLECT_REFRACT_2);
2462  }
2463 
2464  vkpt_pt_trace_lighting(trace_cmd_buf, ref_mode.num_bounce_rays);
2465 
2467  trace_cmd_buf,
2469  all_device_mask,
2470  0, 0, 0, 0,
2471  qvk.device_count, trace_semaphores, device_indices,
2472  VK_NULL_HANDLE);
2473 
2474  *curr_trace_signaled = qtrue;
2475  }
2476 
2477  {
2478  VkCommandBuffer post_cmd_buf = vkpt_begin_command_buffer(&qvk.cmd_buffers_graphics);
2479 
2480  BEGIN_PERF_MARKER(post_cmd_buf, PROFILER_ASVGF_FULL);
2481  if (ref_mode.enable_denoiser)
2482  {
2483  vkpt_asvgf_filter(post_cmd_buf, cvar_pt_num_bounce_rays->value >= 0.5f);
2484  }
2485  else
2486  {
2487  vkpt_compositing(post_cmd_buf);
2488  }
2489  END_PERF_MARKER(post_cmd_buf, PROFILER_ASVGF_FULL);
2490 
2491  vkpt_interleave(post_cmd_buf);
2492 
2493  vkpt_taa(post_cmd_buf);
2494 
2495  BEGIN_PERF_MARKER(post_cmd_buf, PROFILER_BLOOM);
2496  if (cvar_bloom_enable->integer != 0 || menu_mode)
2497  {
2498  vkpt_bloom_record_cmd_buffer(post_cmd_buf);
2499  }
2500  END_PERF_MARKER(post_cmd_buf, PROFILER_BLOOM);
2501 
2502 #ifdef VKPT_IMAGE_DUMPS
2503  if (cvar_dump_image->integer)
2504  {
2505  copy_to_dump_texture(post_cmd_buf, VKPT_IMG_TAA_OUTPUT);
2506  }
2507 #endif
2508 
2509  BEGIN_PERF_MARKER(post_cmd_buf, PROFILER_TONE_MAPPING);
2510  if (cvar_tm_enable->integer != 0)
2511  {
2512  vkpt_tone_mapping_record_cmd_buffer(post_cmd_buf, frame_time <= 0.f ? frame_wallclock_time : frame_time);
2513  }
2514  END_PERF_MARKER(post_cmd_buf, PROFILER_TONE_MAPPING);
2515 
2516  {
2517  VkBufferCopy copyRegion = { 0, 0, sizeof(ReadbackBuffer) };
2518  vkCmdCopyBuffer(post_cmd_buf, qvk.buf_readback.buffer, qvk.buf_readback_staging[qvk.current_frame_index].buffer, 1, &copyRegion);
2519  }
2520 
2521  _VK(vkpt_profiler_query(post_cmd_buf, PROFILER_FRAME_TIME, PROFILER_STOP));
2522 
2524  }
2525 
2527 
2528  frame_ready = qtrue;
2529 
2530  if (vkpt_refdef.fd && vkpt_refdef.fd->lightstyles) {
2531  memcpy(vkpt_refdef.prev_lightstyles, vkpt_refdef.fd->lightstyles, sizeof(vkpt_refdef.prev_lightstyles));
2532  }
2533 }
2534 
2535 static void temporal_cvar_changed(cvar_t *self)
2536 {
2537  temporal_frame_valid = qfalse;
2538 }
2539 
2540 static void
2542 {
2543  vkDeviceWaitIdle(qvk.device);
2546  SDL_GetWindowSize(qvk.window, &qvk.win_width, &qvk.win_height);
2547  create_swapchain();
2549 
2551 }
2552 
2553 static int compare_doubles(const void* pa, const void* pb)
2554 {
2555  double a = *(double*)pa;
2556  double b = *(double*)pb;
2557 
2558  if (a < b) return -1;
2559  if (a > b) return 1;
2560  return 0;
2561 }
2562 
2563 // DRS (Dynamic Resolution Scaling) functions
2564 
2565 static void drs_init()
2566 {
2567  cvar_drs_enable = Cvar_Get("drs_enable", "0", CVAR_ARCHIVE);
2568  // Target FPS value
2569  cvar_drs_target = Cvar_Get("drs_target", "60", CVAR_ARCHIVE);
2571  // Minimum resolution scale in percents
2572  cvar_drs_minscale = Cvar_Get("drs_minscale", "50", 0);
2574  // Maximum resolution scale in percents
2575  cvar_drs_maxscale = Cvar_Get("drs_maxscale", "100", 0);
2577  // Resolution regulator parameters, see the `dynamic_resolution_scaling()` function
2578  cvar_drs_gain = Cvar_Get("drs_gain", "20", 0);
2579  cvar_drs_adjust_up = Cvar_Get("drs_adjust_up", "0.92", 0);
2580  cvar_drs_adjust_down = Cvar_Get("drs_adjust_down", "0.98", 0);
2581 }
2582 
2583 static void drs_process()
2584 {
2585 #define SCALING_FRAMES 5
2586  static int num_valid_frames = 0;
2587  static double valid_frame_times[SCALING_FRAMES];
2588 
2589  if (cvar_drs_enable->integer == 0)
2590  {
2591  num_valid_frames = 0;
2592  drs_effective_scale = 0;
2593  return;
2594  }
2595 
2597  {
2598  num_valid_frames = 0;
2599  drs_effective_scale = max(cvar_drs_minscale->integer, cvar_drs_maxscale->integer);
2600  return;
2601  }
2602 
2604 
2605  double ms = vkpt_get_profiler_result(PROFILER_FRAME_TIME);
2606 
2607  if (ms < 0 || ms > 1000)
2608  return;
2609 
2610  valid_frame_times[num_valid_frames] = ms;
2611  num_valid_frames++;
2612 
2613  if (num_valid_frames < SCALING_FRAMES)
2614  return;
2615 
2616  num_valid_frames = 0;
2617 
2618  qsort(valid_frame_times, SCALING_FRAMES, sizeof(double), compare_doubles);
2619 
2620  double representative_time = 0;
2621  for(int i = 1; i < SCALING_FRAMES - 1; i++)
2622  representative_time += valid_frame_times[i];
2623  representative_time /= (SCALING_FRAMES - 2);
2624 
2625  double target_time = 1000.0 / cvar_drs_target->value;
2626  double f = cvar_drs_gain->value * (1.0 - representative_time / target_time) - 1.0;
2627 
2628  int scale = drs_current_scale;
2629  if (representative_time < target_time * cvar_drs_adjust_up->value)
2630  {
2631  f += 0.5;
2632  clamp(f, 1, 10);
2633  scale += (int)f;
2634  }
2635  else if (representative_time > target_time * cvar_drs_adjust_down->value)
2636  {
2637  f -= 0.5;
2638  clamp(f, -1, -10);
2639  scale += f;
2640  }
2641 
2642  drs_current_scale = max(cvar_drs_minscale->integer, min(cvar_drs_maxscale->integer, scale));
2644 }
2645 
2646 void
2648 {
2649  LOG_FUNC();
2650 
2652 
2653  VkResult res_fence = vkWaitForFences(qvk.device, 1, qvk.fences_frame_sync + qvk.current_frame_index, VK_TRUE, ~((uint64_t) 0));
2654 
2655  if (res_fence == VK_ERROR_DEVICE_LOST)
2656  {
2657  // TODO implement a good error box or vid_restart or something
2658  Com_EPrintf("Device lost!\n");
2659  exit(1);
2660  }
2661 
2662  drs_process();
2663  if (vkpt_refdef.fd)
2664  {
2665  vkpt_refdef.fd->feedback.resolution_scale = (drs_effective_scale != 0) ? drs_effective_scale : scr_viewsize->integer;
2666  }
2667 
2670 
2671  VkExtent2D extent_screen_images = get_screen_image_extent();
2672 
2673  if(!extents_equal(extent_screen_images, qvk.extent_screen_images))
2674  {
2675  qvk.extent_screen_images = extent_screen_images;
2677  }
2678 
2679 retry:;
2680 #ifdef VKPT_DEVICE_GROUPS
2681  VkAcquireNextImageInfoKHR acquire_info = {
2682  .sType = VK_STRUCTURE_TYPE_ACQUIRE_NEXT_IMAGE_INFO_KHR,
2683  .swapchain = qvk.swap_chain,
2684  .timeout = (~((uint64_t) 0)),
2686  .fence = VK_NULL_HANDLE,
2687  .deviceMask = (1 << qvk.device_count) - 1,
2688  };
2689 
2690  VkResult res_swapchain = vkAcquireNextImage2KHR(qvk.device, &acquire_info, &qvk.current_swap_chain_image_index);
2691 #else
2692  VkResult res_swapchain = vkAcquireNextImageKHR(qvk.device, qvk.swap_chain, ~((uint64_t) 0),
2694 #endif
2695  if(res_swapchain == VK_ERROR_OUT_OF_DATE_KHR || res_swapchain == VK_SUBOPTIMAL_KHR) {
2697  goto retry;
2698  }
2699  else if(res_swapchain != VK_SUCCESS) {
2700  _VK(res_swapchain);
2701  }
2702 
2703  if (qvk.wait_for_idle_frames) {
2704  vkDeviceWaitIdle(qvk.device);
2706  }
2707 
2708  vkResetFences(qvk.device, 1, qvk.fences_frame_sync + qvk.current_frame_index);
2709 
2713 
2714  // Process the profiler queries - always enabled to support DRS
2715  {
2716  VkCommandBuffer reset_cmd_buf = vkpt_begin_command_buffer(&qvk.cmd_buffers_graphics);
2717 
2718  _VK(vkpt_profiler_next_frame(reset_cmd_buf));
2719 
2720  vkpt_submit_command_buffer_simple(reset_cmd_buf, qvk.queue_graphics, qtrue);
2721  }
2722 
2726 
2727  /* cannot be called in R_EndRegistration as it would miss the initially textures (charset etc) */
2728  if(register_model_dirty) {
2732  }
2734 
2735  SCR_SetHudAlpha(1.f);
2736 }
2737 
2738 void
2740 {
2741  LOG_FUNC();
2742 
2743  if(cvar_profiler->integer)
2744  draw_profiler(cvar_flt_enable->integer != 0);
2745 
2746  VkCommandBuffer cmd_buf = vkpt_begin_command_buffer(&qvk.cmd_buffers_graphics);
2747 
2748  if (frame_ready)
2749  {
2750  VkExtent2D extent_render_double;
2751  extent_render_double.width = qvk.extent_render.width * 2;
2752  extent_render_double.height = qvk.extent_render.height * 2;
2753 
2755  extents_equal(extent_render_double, qvk.extent_unscaled) && drs_current_scale == 0) // don't do nearest filter 2x upscale with DRS enabled
2756  vkpt_final_blit_simple(cmd_buf);
2757  else
2758  vkpt_final_blit_filtered(cmd_buf);
2759 
2760  frame_ready = qfalse;
2761  }
2762 
2764 
2765  VkSemaphore wait_semaphores[] = { qvk.semaphores[qvk.current_frame_index][0].image_available };
2766  VkPipelineStageFlags wait_stages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
2767  uint32_t wait_device_indices[] = { 0 };
2768 
2769  VkSemaphore signal_semaphores[VKPT_MAX_GPUS];
2770  uint32_t signal_device_indices[VKPT_MAX_GPUS];
2771  for (int gpu = 0; gpu < qvk.device_count; gpu++)
2772  {
2773  signal_semaphores[gpu] = qvk.semaphores[qvk.current_frame_index][gpu].render_finished;
2774  signal_device_indices[gpu] = gpu;
2775  }
2776 
2778  cmd_buf,
2780  (1 << qvk.device_count) - 1,
2781  LENGTH(wait_semaphores), wait_semaphores, wait_stages, wait_device_indices,
2782  qvk.device_count, signal_semaphores, signal_device_indices,
2784 
2785 
2786 #ifdef VKPT_IMAGE_DUMPS
2787  if (cvar_dump_image->integer) {
2788  _VK(vkQueueWaitIdle(qvk.queue_graphics));
2789 
2790  VkImageSubresource subresource = {
2791  .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
2792  .arrayLayer = 0,
2793  .mipLevel = 0
2794  };
2795 
2796  VkSubresourceLayout subresource_layout;
2797  vkGetImageSubresourceLayout(qvk.device, qvk.dump_image, &subresource, &subresource_layout);
2798 
2799  void *data;
2800  _VK(vkMapMemory(qvk.device, qvk.dump_image_memory, 0, qvk.dump_image_memory_size, 0, &data));
2801  save_to_pfm_file("color_buffer", qvk.frame_counter, IMG_WIDTH, IMG_HEIGHT, (char *)data, subresource_layout.rowPitch, 0);
2802  vkUnmapMemory(qvk.device, qvk.dump_image_memory);
2803 
2804  Cvar_SetInteger(cvar_dump_image, 0, FROM_CODE);
2805  }
2806 #endif
2807 
2808  VkPresentInfoKHR present_info = {
2809  .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
2810  .waitSemaphoreCount = qvk.device_count,
2811  .pWaitSemaphores = signal_semaphores,
2812  .swapchainCount = 1,
2813  .pSwapchains = &qvk.swap_chain,
2814  .pImageIndices = &qvk.current_swap_chain_image_index,
2815  .pResults = NULL,
2816  };
2817 
2818 #ifdef VKPT_DEVICE_GROUPS
2819  uint32_t present_device_mask = 1;
2820  VkDeviceGroupPresentInfoKHR group_present_info = {
2821  .sType = VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_INFO_KHR,
2822  .swapchainCount = 1,
2823  .pDeviceMasks = &present_device_mask,
2824  .mode = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR,
2825  };
2826 
2827  if (qvk.device_count > 1) {
2828  present_info.pNext = &group_present_info;
2829  }
2830 #endif
2831 
2832  VkResult res_present = vkQueuePresentKHR(qvk.queue_graphics, &present_info);
2833  if(res_present == VK_ERROR_OUT_OF_DATE_KHR || res_present == VK_SUBOPTIMAL_KHR) {
2835  }
2836  qvk.frame_counter++;
2837 }
2838 
2839 void
2840 R_ModeChanged_RTX(int width, int height, int flags, int rowbytes, void *pixels)
2841 {
2842  Com_Printf("mode changed %d %d\n", width, height);
2843 
2844  r_config.width = width;
2845  r_config.height = height;
2846  r_config.flags = flags;
2847 
2849 }
2850 
2851 static void
2853 {
2854  if (!vkpt_refdef.fd)
2855  return;
2856 
2857  if (vkpt_refdef.fd->feedback.lookatcluster < 0)
2858  {
2859  memset(cluster_debug_mask, 0, sizeof(cluster_debug_mask));
2860  cluster_debug_index = -1;
2861  return;
2862  }
2863 
2864  BSP_ClusterVis(bsp_world_model, cluster_debug_mask, vkpt_refdef.fd->feedback.lookatcluster, DVIS_PVS);
2865  cluster_debug_index = vkpt_refdef.fd->feedback.lookatcluster;
2866 }
2867 
2868 /* called when the library is loaded */
2869 qboolean
2870 R_Init_RTX(qboolean total)
2871 {
2873 
2874  if (!VID_Init(GAPI_VULKAN)) {
2875  Com_Error(ERR_FATAL, "VID_Init failed\n");
2876  return qfalse;
2877  }
2878 
2879  extern SDL_Window *sdl_window;
2880  qvk.window = sdl_window;
2881 
2882  cvar_profiler = Cvar_Get("profiler", "0", 0);
2883  cvar_vsync = Cvar_Get("vid_vsync", "0", CVAR_REFRESH | CVAR_ARCHIVE);
2884  cvar_vsync->changed = NULL; // in case the GL renderer has set it
2885  cvar_pt_caustics = Cvar_Get("pt_caustics", "1", CVAR_ARCHIVE);
2886  cvar_pt_enable_nodraw = Cvar_Get("pt_enable_nodraw", "0", 0);
2887 
2888  // 0 -> disabled, regular pause; 1 -> enabled; 2 -> enabled, hide GUI
2889  cvar_pt_accumulation_rendering = Cvar_Get("pt_accumulation_rendering", "1", CVAR_ARCHIVE);
2890 
2891  // number of frames to accumulate with linear weights in accumulation rendering modes
2892  cvar_pt_accumulation_rendering_framenum = Cvar_Get("pt_accumulation_rendering_framenum", "500", 0);
2893 
2894  // 0 -> perspective, 1 -> cylindrical
2895  cvar_pt_projection = Cvar_Get("pt_projection", "0", CVAR_ARCHIVE);
2896 
2897  // depth of field control:
2898  // 0 -> disabled
2899  // 1 -> enabled only in the reference mode
2900  // 2 -> enabled in the reference and no-denoiser modes
2901  // 3 -> always enabled (where are my glasses?)
2902  cvar_pt_dof = Cvar_Get("pt_dof", "1", CVAR_ARCHIVE);
2903 
2904  // freecam mode toggle
2905  cvar_pt_freecam = Cvar_Get("pt_freecam", "1", CVAR_ARCHIVE);
2906 
2907 #ifdef VKPT_DEVICE_GROUPS
2908  cvar_sli = Cvar_Get("sli", "1", CVAR_REFRESH | CVAR_ARCHIVE);
2909 #endif
2910 
2911 #ifdef VKPT_IMAGE_DUMPS
2912  cvar_dump_image = Cvar_Get("dump_image", "0", 0);
2913 #endif
2914 
2915  scr_viewsize = Cvar_Get("viewsize", "100", CVAR_ARCHIVE);
2916  scr_viewsize->changed = viewsize_changed;
2917 
2918  drs_init();
2919 
2920  // Minimum NVIDIA driver version - this is a cvar in case something changes in the future,
2921  // and the current test no longer works.
2922  cvar_min_driver_version = Cvar_Get("min_driver_version", "430.86", 0);
2923 
2925 
2926  if (MAT_InitializePBRmaterials() != Q_ERR_SUCCESS)
2927  {
2928  Com_Error(ERR_FATAL, "Couldn't initialize the material system.\n");
2929  }
2930 
2931 #define UBO_CVAR_DO(name, default_value) cvar_##name = Cvar_Get(#name, #default_value, 0);
2933 #undef UBO_CVAR_LIST
2934 
2935  cvar_flt_temporal_hf->changed = temporal_cvar_changed;
2936  cvar_flt_temporal_lf->changed = temporal_cvar_changed;
2937  cvar_flt_temporal_spec->changed = temporal_cvar_changed;
2938  cvar_flt_taa->changed = temporal_cvar_changed;
2939  cvar_flt_enable->changed = temporal_cvar_changed;
2940 
2943  cvar_pt_aperture_type->changed = accumulation_cvar_changed;
2944  cvar_pt_aperture_angle->changed = accumulation_cvar_changed;
2948 
2949  cvar_pt_num_bounce_rays->flags |= CVAR_ARCHIVE;
2950 
2951  qvk.win_width = r_config.width;
2952  qvk.win_height = r_config.height;
2953 
2954  IMG_Init();
2955  IMG_GetPalette();
2956  MOD_Init();
2957 
2958  if(!init_vulkan()) {
2959  Com_Error(ERR_FATAL, "Couldn't initialize Vulkan.\n");
2960  return qfalse;
2961  }
2962 
2964  _VK(create_swapchain());
2965 
2967 
2971 
2972  Cmd_AddCommand("reload_shader", (xcommand_t)&vkpt_reload_shader);
2973  Cmd_AddCommand("reload_textures", (xcommand_t)&vkpt_reload_textures);
2974  Cmd_AddCommand("reload_materials", (xcommand_t)&vkpt_reload_materials);
2975  Cmd_AddCommand("save_materials", (xcommand_t)&vkpt_save_materials);
2976  Cmd_AddCommand("set_material", (xcommand_t)&vkpt_set_material);
2977  Cmd_AddCommand("print_material", (xcommand_t)&vkpt_print_material);
2978  Cmd_AddCommand("show_pvs", (xcommand_t)&vkpt_show_pvs);
2979  Cmd_AddCommand("next_sun", (xcommand_t)&vkpt_next_sun_preset);
2980 #if CL_RTX_SHADERBALLS
2981  Cmd_AddCommand("drop_balls", (xcommand_t)&vkpt_drop_shaderballs);
2982 #endif
2983 
2984  for (int i = 0; i < 256; i++) {
2985  qvk.sintab[i] = sinf(i * (2 * M_PI / 255));
2986  }
2987 
2988  return qtrue;
2989 }
2990 
2991 /* called before the library is unloaded */
2992 void
2993 R_Shutdown_RTX(qboolean total)
2994 {
2996 
2997  vkDeviceWaitIdle(qvk.device);
2998 
2999  Cmd_RemoveCommand("reload_shader");
3000  Cmd_RemoveCommand("reload_textures");
3001  Cmd_RemoveCommand("reload_materials");
3002  Cmd_RemoveCommand("save_materials");
3003  Cmd_RemoveCommand("set_material");
3004  Cmd_RemoveCommand("print_material");
3005  Cmd_RemoveCommand("show_pvs");
3006  Cmd_RemoveCommand("next_sun");
3007 #if CL_RTX_SHADERBALLS
3008  Cmd_RemoveCommand("drop_balls");
3009 #endif
3010 
3011  IMG_FreeAll();
3013 
3016 
3017  if(destroy_vulkan()) {
3018  Com_EPrintf("destroy_vulkan failed\n");
3019  }
3020 
3021  IMG_Shutdown();
3022  MOD_Shutdown(); // todo: currently leaks memory, need to clear submeshes
3023  VID_Shutdown();
3024 }
3025 
3026 // for screenshots
3027 byte *
3028 IMG_ReadPixels_RTX(int *width, int *height, int *rowbytes)
3029 {
3030  if (qvk.surf_format.format != VK_FORMAT_B8G8R8A8_SRGB &&
3031  qvk.surf_format.format != VK_FORMAT_R8G8B8A8_SRGB)
3032  {
3033  Com_EPrintf("IMG_ReadPixels: unsupported swap chain format (%d)!\n", qvk.surf_format.format);
3034  return NULL;
3035  }
3036 
3037  VkCommandBuffer cmd_buf = vkpt_begin_command_buffer(&qvk.cmd_buffers_graphics);
3038 
3039  VkImage swap_chain_image = qvk.swap_chain_images[qvk.current_swap_chain_image_index];
3040 
3041  VkImageSubresourceRange subresource_range = {
3042  .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
3043  .baseMipLevel = 0,
3044  .levelCount = 1,
3045  .baseArrayLayer = 0,
3046  .layerCount = 1
3047  };
3048 
3049  IMAGE_BARRIER(cmd_buf,
3050  .image = swap_chain_image,
3051  .subresourceRange = subresource_range,
3052  .srcAccessMask = 0,
3053  .dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT,
3054  .oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
3055  .newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
3056  );
3057 
3058  IMAGE_BARRIER(cmd_buf,
3059  .image = qvk.screenshot_image,
3060  .subresourceRange = subresource_range,
3061  .srcAccessMask = VK_ACCESS_HOST_READ_BIT,
3062  .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
3063  .oldLayout = VK_IMAGE_LAYOUT_GENERAL,
3064  .newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
3065  );
3066 
3067  VkImageCopy img_copy_region = {
3068  .srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 },
3069  .dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 },
3070  .extent = { qvk.extent_unscaled.width, qvk.extent_unscaled.height, 1 }
3071  };
3072 
3073  vkCmdCopyImage(cmd_buf,
3074  swap_chain_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
3075  qvk.screenshot_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
3076  1, &img_copy_region);
3077 
3078  IMAGE_BARRIER(cmd_buf,
3079  .image = swap_chain_image,
3080  .subresourceRange = subresource_range,
3081  .srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT,
3082  .dstAccessMask = 0,
3083  .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
3084  .newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR
3085  );
3086 
3087  IMAGE_BARRIER(cmd_buf,
3088  .image = qvk.screenshot_image,
3089  .subresourceRange = subresource_range,
3090  .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
3091  .dstAccessMask = VK_ACCESS_HOST_READ_BIT,
3092  .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
3093  .newLayout = VK_IMAGE_LAYOUT_GENERAL
3094  );
3095 
3098 
3099  VkImageSubresource subresource = {
3100  .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
3101  .arrayLayer = 0,
3102  .mipLevel = 0
3103  };
3104 
3105  VkSubresourceLayout subresource_layout;
3106  vkGetImageSubresourceLayout(qvk.device, qvk.screenshot_image, &subresource, &subresource_layout);
3107 
3108  void *device_data;
3109  _VK(vkMapMemory(qvk.device, qvk.screenshot_image_memory, 0, qvk.screenshot_image_memory_size, 0, &device_data));
3110 
3111  int pitch = qvk.extent_unscaled.width * 3;
3112  byte *pixels = FS_AllocTempMem(pitch * qvk.extent_unscaled.height);
3113 
3114  for (int row = 0; row < qvk.extent_unscaled.height; row++)
3115  {
3116  byte* src_row = (byte*)device_data + subresource_layout.rowPitch * row;
3117  byte* dst_row = pixels + pitch * (qvk.extent_unscaled.height - row - 1);
3118 
3119  if (qvk.surf_format.format == VK_FORMAT_B8G8R8A8_SRGB)
3120  {
3121  for (int col = 0; col < qvk.extent_unscaled.width; col++)
3122  {
3123  dst_row[0] = src_row[2];
3124  dst_row[1] = src_row[1];
3125  dst_row[2] = src_row[0];
3126 
3127  src_row += 4;
3128  dst_row += 3;
3129  }
3130  }
3131  else // must be VK_FORMAT_R8G8B8A8_SRGB then
3132  {
3133  for (int col = 0; col < qvk.extent_unscaled.width; col++)
3134  {
3135  dst_row[0] = src_row[0];
3136  dst_row[1] = src_row[1];
3137  dst_row[2] = src_row[2];
3138 
3139  src_row += 4;
3140  dst_row += 3;
3141  }
3142  }
3143  }
3144 
3145  vkUnmapMemory(qvk.device, qvk.screenshot_image_memory);
3146 
3147  *width = qvk.extent_unscaled.width;
3148  *height = qvk.extent_unscaled.height;
3149  *rowbytes = pitch;
3150  return pixels;
3151 }
3152 
3153 void
3154 R_SetSky_RTX(const char *name, float rotate, vec3_t axis)
3155 {
3156  int i;
3157  char pathname[MAX_QPATH];
3158  // 3dstudio environment map names
3159  const char *suf[6] = { "ft", "bk", "up", "dn", "rt", "lf" };
3160 
3161  byte *data = NULL;
3162 
3163  sky_rotation = rotate;
3164  VectorNormalize2(axis, sky_axis);
3165 
3166  int avg_color[3] = { 0 };
3167  int w_prev, h_prev;
3168  for (i = 0; i < 6; i++) {
3169  Q_concat(pathname, sizeof(pathname), "env/", name, suf[i], ".tga", NULL);
3170  FS_NormalizePath(pathname, pathname);
3171  image_t *img = IMG_Find(pathname, IT_SKY, IF_NONE);
3172 
3173  if(img == R_NOTEXTURE) {
3174  if(data) {
3175  Z_Free(data);
3176  }
3177  data = Z_Malloc(6 * sizeof(uint32_t));
3178  for(int j = 0; j < 6; j++)
3179  ((uint32_t *)data)[j] = 0xff00ffffu;
3180  w_prev = h_prev = 1;
3181  break;
3182  }
3183 
3184  size_t s = img->upload_width * img->upload_height * 4;
3185  if(!data) {
3186  data = Z_Malloc(s * 6);
3187  w_prev = img->upload_width;
3188  h_prev = img->upload_height;
3189  }
3190 
3191  memcpy(data + s * i, img->pix_data, s);
3192 
3193  for (int p = 0; p < img->upload_width * img->upload_height; p++)
3194  {
3195  uint32_t pix = *((uint32_t*)img->pix_data + p);
3196  avg_color[0] += pix & 0xff;
3197  avg_color[1] += (pix >> 8) & 0xff;
3198  avg_color[2] += (pix >> 16) & 0xff;
3199  }
3200 
3201  assert(w_prev == img->upload_width);
3202  assert(h_prev == img->upload_height);
3203 
3204  List_Remove(&img->entry);
3205 
3206  IMG_Unload(img);
3207 
3208  memset(img, 0, sizeof(*img));
3209  }
3210 
3211  float inv_num_pixels = 1.0f / (w_prev * h_prev * 6);
3212 
3213  VectorSet(avg_envmap_color,
3214  (float)avg_color[0] * inv_num_pixels / 255.f,
3215  (float)avg_color[1] * inv_num_pixels / 255.f,
3216  (float)avg_color[2] * inv_num_pixels / 255.f
3217  );
3218 
3219  vkpt_textures_upload_envmap(w_prev, h_prev, data);
3220  Z_Free(data);
3221 }
3222 
3223 void R_AddDecal_RTX(decal_t *d)
3224 { }
3225 
3226 void
3227 R_BeginRegistration_RTX(const char *name)
3228 {
3230  LOG_FUNC();
3231  Com_Printf("loading %s\n", name);
3232  vkDeviceWaitIdle(qvk.device);
3233 
3234  Com_AddConfigFile("maps/default.cfg", 0);
3235  Com_AddConfigFile(va("maps/%s.cfg", name), 0);
3236 
3240  }
3241 
3242  if(bsp_world_model) {
3244  bsp_world_model = NULL;
3245  }
3246 
3247  char bsp_path[MAX_QPATH];
3248  Q_concat(bsp_path, sizeof(bsp_path), "maps/", name, ".bsp", NULL);
3249  bsp_t *bsp;
3250  qerror_t ret = BSP_Load(bsp_path, &bsp);
3251  if(!bsp) {
3252  Com_Error(ERR_DROP, "%s: couldn't load %s: %s", __func__, bsp_path, Q_ErrorString(ret));
3253  }
3254  bsp_world_model = bsp;
3261  bsp = NULL;
3262  world_anim_frame = 0;
3263 
3264  Cvar_Set("sv_novis", vkpt_refdef.bsp_mesh_world.num_cameras > 0 ? "1" : "0");
3265 
3266  // register physical sky attributes based on map name lookup
3269 
3271  vkpt_bloom_reset();
3274 
3279  offsetof(VertexBuffer, positions_bsp),
3280  m->world_idx_count,
3281  m->world_transparent_count,
3282  m->world_sky_count,
3283  m->world_custom_sky_count));
3284 
3285  memset(cluster_debug_mask, 0, sizeof(cluster_debug_mask));
3286  cluster_debug_index = -1;
3287 }
3288 
3289 void
3291 {
3292  LOG_FUNC();
3293 
3295 
3296  IMG_FreeUnused();
3297  MOD_FreeUnused();
3298  MAT_ResetUnused();
3299 }
3300 
3302 {
3303  if (group->used_this_frame == group->count_per_frame)
3304  {
3305  uint32_t new_count = max(4, group->count_per_frame * 2);
3306  VkCommandBuffer* new_buffers = Z_Mallocz(new_count * MAX_FRAMES_IN_FLIGHT * sizeof(VkCommandBuffer));
3307 
3308  for (int frame = 0; frame < MAX_FRAMES_IN_FLIGHT; frame++)
3309  {
3310  if (group->count_per_frame > 0)
3311  {
3312  memcpy(new_buffers + new_count * frame, group->buffers + group->count_per_frame * frame, group->count_per_frame * sizeof(VkCommandBuffer));
3313  }
3314 
3315  VkCommandBufferAllocateInfo cmd_buf_alloc_info = {
3316  .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
3317  .commandPool = group->command_pool,
3318  .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
3319  .commandBufferCount = new_count - group->count_per_frame
3320  };
3321 
3322  _VK(vkAllocateCommandBuffers(qvk.device, &cmd_buf_alloc_info, new_buffers + new_count * frame + group->count_per_frame));
3323  }
3324 
3325 #ifdef _DEBUG
3326  void** new_addrs = Z_Mallocz(new_count * MAX_FRAMES_IN_FLIGHT * sizeof(void*));
3327 
3328  if (group->count_per_frame > 0)
3329  {
3330  for (int frame = 0; frame < MAX_FRAMES_IN_FLIGHT; frame++)
3331  {
3332  memcpy(new_addrs + new_count * frame, group->buffer_begin_addrs + group->count_per_frame * frame, group->count_per_frame * sizeof(void*));
3333  }
3334  }
3335 
3336  Z_Free(group->buffer_begin_addrs);
3337  group->buffer_begin_addrs = new_addrs;
3338 #endif
3339 
3340  Z_Free(group->buffers);
3341  group->buffers = new_buffers;
3342  group->count_per_frame = new_count;
3343  }
3344 
3345  VkCommandBuffer cmd_buf = group->buffers[group->count_per_frame * qvk.current_frame_index + group->used_this_frame];
3346 
3347  VkCommandBufferBeginInfo begin_info = {
3348  .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
3349  .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
3350  .pInheritanceInfo = NULL,
3351  };
3352  _VK(vkResetCommandBuffer(cmd_buf, 0));
3353  _VK(vkBeginCommandBuffer(cmd_buf, &begin_info));
3354 
3355 
3356 #ifdef _DEBUG
3357  void** begin_addr = group->buffer_begin_addrs + group->count_per_frame * qvk.current_frame_index + group->used_this_frame;
3358 
3359 #if (defined __GNUC__)
3360  *begin_addr = __builtin_return_address(0);
3361 #elif (defined _MSC_VER)
3362  *begin_addr = _ReturnAddress();
3363 #else
3364  *begin_addr = NULL;
3365 #endif
3366 #endif
3367 
3368  group->used_this_frame += 1;
3369 
3370  return cmd_buf;
3371 }
3372 
3374 {
3375  if (group->count_per_frame == 0)
3376  return;
3377 
3378  vkFreeCommandBuffers(qvk.device, group->command_pool, group->count_per_frame * MAX_FRAMES_IN_FLIGHT, group->buffers);
3379 
3380  Z_Free(group->buffers);
3381  group->buffers = NULL;
3382 
3383 #ifdef _DEBUG
3384  Z_Free(group->buffer_begin_addrs);
3385  group->buffer_begin_addrs = NULL;
3386 #endif
3387 
3388  group->count_per_frame = 0;
3389  group->used_this_frame = 0;
3390 }
3391 
3393 {
3394  group->used_this_frame = 0;
3395 
3396 #ifdef _DEBUG
3397  for (int i = 0; i < group->count_per_frame; i++)
3398  {
3399  void* addr = group->buffer_begin_addrs[group->count_per_frame * qvk.current_frame_index + i];
3400  assert(addr == 0);
3401  }
3402 #endif
3403 }
3404 
3405 void vkpt_wait_idle(VkQueue queue, cmd_buf_group_t* group)
3406 {
3407  vkQueueWaitIdle(queue);
3409 }
3410 
3412  VkCommandBuffer cmd_buf,
3413  VkQueue queue,
3414  uint32_t execute_device_mask,
3415  int wait_semaphore_count,
3416  VkSemaphore* wait_semaphores,
3417  VkPipelineStageFlags* wait_stages,
3418  uint32_t* wait_device_indices,
3419  int signal_semaphore_count,
3420  VkSemaphore* signal_semaphores,
3421  uint32_t* signal_device_indices,
3422  VkFence fence)
3423 {
3424  _VK(vkEndCommandBuffer(cmd_buf));
3425 
3426  VkSubmitInfo submit_info = {
3427  .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
3428  .waitSemaphoreCount = wait_semaphore_count,
3429  .pWaitSemaphores = wait_semaphores,
3430  .pWaitDstStageMask = wait_stages,
3431  .signalSemaphoreCount = signal_semaphore_count,
3432  .pSignalSemaphores = signal_semaphores,
3433  .commandBufferCount = 1,
3434  .pCommandBuffers = &cmd_buf,
3435  };
3436 
3437 #ifdef VKPT_DEVICE_GROUPS
3438  VkDeviceGroupSubmitInfoKHR device_group_submit_info = {
3439  .sType = VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO_KHR,
3440  .pNext = NULL,
3441  .waitSemaphoreCount = wait_semaphore_count,
3442  .pWaitSemaphoreDeviceIndices = wait_device_indices,
3443  .commandBufferCount = 1,
3444  .pCommandBufferDeviceMasks = &execute_device_mask,
3445  .signalSemaphoreCount = signal_semaphore_count,
3446  .pSignalSemaphoreDeviceIndices = signal_device_indices,
3447  };
3448 
3449  if (qvk.device_count > 1) {
3450  submit_info.pNext = &device_group_submit_info;
3451  }
3452 #endif
3453 
3454  _VK(vkQueueSubmit(queue, 1, &submit_info, fence));
3455 
3456 #ifdef _DEBUG
3458  for (int ngroup = 0; ngroup < LENGTH(groups); ngroup++)
3459  {
3460  cmd_buf_group_t* group = groups[ngroup];
3461  for (int i = 0; i < MAX_FRAMES_IN_FLIGHT * group->count_per_frame; i++)
3462  {
3463  if (group->buffers[i] == cmd_buf)
3464  {
3465  group->buffer_begin_addrs[i] = NULL;
3466  return;
3467  }
3468  }
3469  }
3470 #endif
3471 }
3472 
3474  VkCommandBuffer cmd_buf,
3475  VkQueue queue,
3476  qboolean all_gpus)
3477 {
3478  vkpt_submit_command_buffer(cmd_buf, queue, all_gpus ? (1 << qvk.device_count) - 1 : 1, 0, NULL, NULL, NULL, 0, NULL, NULL, 0);
3479 }
3480 
3481 #if _WIN32
3482  #include <windows.h>
3483 #else
3484  #include <stdio.h>
3485 #endif
3486 
3487 void debug_output(const char* format, ...)
3488 {
3489  char buffer[2048];
3490 
3491  va_list args;
3492  va_start(args, format);
3493  vsnprintf(buffer, sizeof(buffer), format, args);
3494  va_end(args);
3495 
3496 #if _WIN32
3497  OutputDebugStringA(buffer);
3498 #else
3499  fprintf(stderr, "%s", buffer);
3500 #endif
3501 }
3502 
3504 {
3505  R_Init = R_Init_RTX;
3534  MOD_LoadMD3 = MOD_LoadMD3_RTX;
3536 }
3537 
3538 // vim: shiftwidth=4 noexpandtab tabstop=4 cindent
R_LightPoint_RTX
void R_LightPoint_RTX(vec3_t origin, vec3_t light)
Definition: draw.c:670
MESH_FILTER_TRANSPARENT
#define MESH_FILTER_TRANSPARENT
Definition: main.c:1487
vkpt_destroy_shader_modules
VkResult vkpt_destroy_shader_modules()
Definition: main.c:1180
MATERIAL_KIND_TRANSPARENT
#define MATERIAL_KIND_TRANSPARENT
Definition: constants.h:68
draw_profiler
void draw_profiler(int enable_asvgf)
Definition: profiler.c:134
QVK_s::win_height
int win_height
Definition: vkpt.h:211
IMG_ReadPixels
byte * IMG_ReadPixels(int *width, int *height, int *rowbytes)
Definition: main.c:768
cvar_pt_dof
cvar_t * cvar_pt_dof
Definition: main.c:57
sun_light_s
Definition: vkpt.h:414
MEDIUM_LAVA
#define MEDIUM_LAVA
Definition: constants.h:95
bsp_mesh_s::num_clusters
int num_clusters
Definition: vkpt.h:366
R_TileClear
void(* R_TileClear)(int x, int y, int w, int h, qhandle_t pic)
Definition: refresh.c:421
MATERIAL_FLAG_SHELL_GREEN
#define MATERIAL_FLAG_SHELL_GREEN
Definition: constants.h:81
vkpt_readback
VkResult vkpt_readback(ReadbackBuffer *dst)
Definition: vertex_buffer.c:659
MOD_Reference
void(* MOD_Reference)(model_t *model)
Definition: refresh.c:438
maliasmesh_s
Definition: gl.h:232
R_EndRegistration
void(* R_EndRegistration)(void)
Definition: refresh.c:407
vkpt_draw_destroy
VkResult vkpt_draw_destroy()
Definition: draw.c:295
Cvar_Set
cvar_t * Cvar_Set(const char *var_name, const char *value)
Definition: cvar.c:466
QVKUniformBuffer_s
Definition: global_ubo.h:247
vkpt_textures_destroy
VkResult vkpt_textures_destroy()
Definition: textures.c:1045
vkpt_shadow_map_setup
void vkpt_shadow_map_setup(const sun_light_t *light, const float *bbox_min, const float *bbox_max, float *VP, float *depth_scale, qboolean random_sampling)
Definition: shadow_map.c:460
R_SetClipRect_RTX
void R_SetClipRect_RTX(const clipRect_t *clip)
Definition: draw.c:629
MEDIUM_SLIME
#define MEDIUM_SLIME
Definition: constants.h:94
cmd_buf_group_s::used_this_frame
uint32_t used_this_frame
Definition: vkpt.h:145
light_poly_s
Definition: vkpt.h:315
r_config
refcfg_t r_config
Definition: main.c:24
R_SetColor
void(* R_SetColor)(uint32_t color)
Definition: refresh.c:413
cvar_drs_target
cvar_t * cvar_drs_target
Definition: main.c:60
IMG_GetPalette
void IMG_GetPalette(void)
Definition: images.c:1376
R_InterceptKey
qboolean(* R_InterceptKey)(unsigned key, qboolean down)
Definition: refresh.c:428
cvar_drs_adjust_down
cvar_t * cvar_drs_adjust_down
Definition: main.c:64
LOG_FUNC
#define LOG_FUNC()
Definition: vkpt.h:54
QVK_s::frame_counter
uint64_t frame_counter
Definition: vkpt.h:212
register_model_dirty
int register_model_dirty
Definition: main.c:431
vkpt_draw_destroy_pipelines
VkResult vkpt_draw_destroy_pipelines()
Definition: draw.c:309
evaluate_reference_mode
static void evaluate_reference_mode(reference_mode_t *ref_mode)
Definition: main.c:1928
SHADER_PATH_TEMPLATE
#define SHADER_PATH_TEMPLATE
Definition: vkpt.h:114
IMG_FreeAll
void IMG_FreeAll(void)
Definition: images.c:1343
cvar_drs_gain
cvar_t * cvar_drs_gain
Definition: main.c:65
QVK_s::sintab
float sintab[256]
Definition: vkpt.h:259
PROFILER_START
@ PROFILER_START
Definition: vkpt.h:469
prepare_sky_matrix
static void prepare_sky_matrix(float time, vec3_t sky_matrix[3])
Definition: main.c:2002
vkpt_final_blit_filtered
VkResult vkpt_final_blit_filtered(VkCommandBuffer cmd_buf)
Definition: draw.c:604
bsp_mesh_register_textures
void bsp_mesh_register_textures(bsp_t *bsp)
Definition: bsp_mesh.c:1781
vkpt_textures_end_registration
VkResult vkpt_textures_end_registration()
Definition: textures.c:1087
QVK_s::num_swap_chain_images
uint32_t num_swap_chain_images
Definition: vkpt.h:189
Com_AddConfigFile
void Com_AddConfigFile(const char *name, unsigned flags)
Definition: common.c:876
_VK_EXTENSION_LIST
#define _VK_EXTENSION_LIST
Definition: vkpt.h:284
MAX_FRAMES_IN_FLIGHT
#define MAX_FRAMES_IN_FLIGHT
Definition: vkpt.h:140
R_SetSky
void(* R_SetSky)(const char *name, float rotate, vec3_t axis)
Definition: refresh.c:406
MAT_SavePBRMaterials
qerror_t MAT_SavePBRMaterials()
Definition: material.c:391
reference_mode_s::enable_denoiser
qboolean enable_denoiser
Definition: main.c:1902
R_SetAlpha
void(* R_SetAlpha)(float clpha)
Definition: refresh.c:411
height
static int height
Definition: physical_sky.c:39
vkpt_light_stats_create
VkResult vkpt_light_stats_create(bsp_mesh_t *bsp_mesh)
Definition: vertex_buffer.c:699
IMG_Load_RTX
void IMG_Load_RTX(image_t *image, byte *pic)
Definition: textures.c:632
Q_snprintf
size_t Q_snprintf(char *dest, size_t size, const char *fmt,...)
Definition: shared.c:846
vkpt_pt_destroy_pipelines
VkResult vkpt_pt_destroy_pipelines()
Definition: path_tracer.c:1410
vkpt_vertex_buffer_create_pipelines
VkResult vkpt_vertex_buffer_create_pipelines()
Definition: vertex_buffer.c:759
vkpt_god_rays_destroy_pipelines
VkResult vkpt_god_rays_destroy_pipelines()
Definition: god_rays.c:85
MAT_PrintMaterialProperties
void MAT_PrintMaterialProperties(pbr_material_t const *mat)
Definition: material.c:549
vkpt_taa
VkResult vkpt_taa(VkCommandBuffer cmd_buf)
Definition: asvgf.c:555
R_BeginFrame_RTX
void R_BeginFrame_RTX(void)
Definition: main.c:2647
vkpt_vertex_buffer_create
VkResult vkpt_vertex_buffer_create()
Definition: vertex_buffer.c:492
num_accumulated_frames
int num_accumulated_frames
Definition: main.c:100
VkptInit_s
Definition: main.c:113
vkpt_final_blit_simple
VkResult vkpt_final_blit_simple(VkCommandBuffer cmd_buf)
Definition: draw.c:535
drs_effective_scale
static int drs_effective_scale
Definition: main.c:69
image_t
struct image_s image_t
Definition: material.h:27
vkpt_vertex_buffer_destroy_pipelines
VkResult vkpt_vertex_buffer_destroy_pipelines()
Definition: vertex_buffer.c:800
BspMeshInstance::M
float M[16]
Definition: global_ubo.h:242
cvar_profiler
cvar_t * cvar_profiler
Definition: main.c:50
vk_app_info
static const VkApplicationInfo vk_app_info
Definition: main.c:419
vertex_buffer.h
EntityUploadInfo::viewer_model_vertex_num
uint32_t viewer_model_vertex_num
Definition: vkpt.h:481
maliasmesh_s::vertex_offset
int vertex_offset
Definition: vkpt.h:697
is_accumulation_rendering_active
static qboolean is_accumulation_rendering_active()
Definition: main.c:1914
QVK_s::device
VkDevice device
Definition: vkpt.h:172
vkpt_uniform_buffer_update
VkResult vkpt_uniform_buffer_update(VkCommandBuffer command_buffer)
Definition: uniform_buffer.c:142
MOD_ForHandle
model_t * MOD_ForHandle(qhandle_t h)
Definition: models.c:430
drs_process
static void drs_process()
Definition: main.c:2583
Cmd_AddCommand
void Cmd_AddCommand(const char *name, xcommand_t function)
Definition: cmd.c:1562
debug_output
void debug_output(const char *format,...)
Definition: main.c:3487
get_render_extent
static VkExtent2D get_render_extent()
Definition: main.c:184
IMG_Load
void(* IMG_Load)(image_t *image, byte *pic)
Definition: refresh.c:431
temporal_frame_valid
static qboolean temporal_frame_valid
Definition: main.c:92
cvar_pt_caustics
cvar_t * cvar_pt_caustics
Definition: main.c:52
ReadbackBuffer::cluster
uint32_t cluster
Definition: vertex_buffer.h:137
EntityUploadInfo::dynamic_vertex_num
uint32_t dynamic_vertex_num
Definition: vkpt.h:477
vkpt_refdef
vkpt_refdef_t vkpt_refdef
Definition: main.c:372
cmd_buf_group_s::count_per_frame
uint32_t count_per_frame
Definition: vkpt.h:144
EntityUploadInfo::weapon_left_handed
qboolean weapon_left_handed
Definition: vkpt.h:486
MOD_LoadMD3_RTX
qerror_t MOD_LoadMD3_RTX(model_t *model, const void *rawdata, size_t length)
Cvar_Get
cvar_t * Cvar_Get(const char *var_name, const char *var_value, int flags)
Definition: cvar.c:257
vk_requested_device_extensions
const char * vk_requested_device_extensions[]
Definition: main.c:405
sky_rotation
static float sky_rotation
Definition: main.c:104
Q_ErrorString
const char * Q_ErrorString(qerror_t error)
Definition: error.c:51
bsp_model_s::light_polys
light_poly_t * light_polys
Definition: vkpt.h:333
bsp_mesh_s
Definition: vkpt.h:343
BSP_ClusterVis
byte * BSP_ClusterVis(bsp_t *bsp, byte *mask, int cluster, int vis)
Definition: bsp.c:1339
QVK_s::instance
VkInstance instance
Definition: vkpt.h:162
R_EndFrame_RTX
void R_EndFrame_RTX(void)
Definition: main.c:2739
QVK_s
Definition: vkpt.h:161
ModelInstance::material
uint32_t material
Definition: global_ubo.h:237
QVK_s::cmd_buffers_transfer
cmd_buf_group_t cmd_buffers_transfer
Definition: vkpt.h:195
vkpt_free_command_buffers
void vkpt_free_command_buffers(cmd_buf_group_t *group)
Definition: main.c:3373
vkpt_save_materials
void vkpt_save_materials()
Definition: main.c:334
vkpt_asvgf_destroy
VkResult vkpt_asvgf_destroy()
Definition: asvgf.c:81
MAX_MODEL_LIGHTS
#define MAX_MODEL_LIGHTS
Definition: main.c:1265
MOD_Init
void MOD_Init(void)
Definition: models.c:450
R_ClearColor
void(* R_ClearColor)(void)
Definition: refresh.c:410
cvar_pt_freecam
cvar_t * cvar_pt_freecam
Definition: main.c:58
vkpt_profiler_next_frame
VkResult vkpt_profiler_next_frame(VkCommandBuffer cmd_buf)
Definition: profiler.c:66
cvar_pt_projection
cvar_t * cvar_pt_projection
Definition: main.c:56
QVKInstanceBuffer_s
Definition: global_ubo.h:253
P
#define P(name, type)
Definition: g_save.c:51
R_LightPoint
void(* R_LightPoint)(vec3_t origin, vec3_t light)
Definition: refresh.c:409
cvar_drs_adjust_up
cvar_t * cvar_drs_adjust_up
Definition: main.c:63
R_Init_RTX
qboolean R_Init_RTX(qboolean total)
Definition: main.c:2870
light_poly_s::color
vec3_t color
Definition: vkpt.h:318
QVK_s::buf_vertex
BufferResource_t buf_vertex
Definition: vkpt.h:243
QVK_s::extensions
VkExtensionProperties * extensions
Definition: vkpt.h:199
MATERIAL_KIND_CHROME_MODEL
#define MATERIAL_KIND_CHROME_MODEL
Definition: constants.h:71
pbr_material_s::flags
uint32_t flags
Definition: material.h:42
R_SetColor_RTX
void R_SetColor_RTX(uint32_t color)
Definition: draw.c:663
ModelInstance::alpha
float alpha
Definition: global_ubo.h:238
R_DrawFill8_RTX
void R_DrawFill8_RTX(int x, int y, int w, int h, int c)
Definition: draw.c:708
light_poly_s::material
struct pbr_material_s * material
Definition: vkpt.h:319
MESH_FILTER_ALL
#define MESH_FILTER_ALL
Definition: main.c:1489
MAT_SetPBRMaterialAttribute
qerror_t MAT_SetPBRMaterialAttribute(pbr_material_t *mat, char const *token, char const *value)
Definition: material.c:570
vkpt_build_cylinder_light
qboolean vkpt_build_cylinder_light(light_poly_t *light_list, int *num_lights, int max_lights, bsp_t *bsp, vec3_t begin, vec3_t end, vec3_t color, float radius)
Definition: transparency.c:408
avg_envmap_color
static vec3_t avg_envmap_color
Definition: main.c:96
MAX
#define MAX(a, b)
Definition: vkpt.h:50
QVK_s::current_frame_index
uint32_t current_frame_index
Definition: vkpt.h:219
vkpt.h
shader_module_file_names
static const char * shader_module_file_names[NUM_QVK_SHADER_MODULES]
Definition: main.c:429
R_RenderFrame_RTX
void R_RenderFrame_RTX(refdef_t *fd)
Definition: main.c:2227
ModelInstance
Definition: global_ubo.h:235
QVK_s::buf_readback
BufferResource_t buf_readback
Definition: vkpt.h:249
QVK_s::gpu_slice_width
uint32_t gpu_slice_width
Definition: vkpt.h:187
vkpt_textures_destroy_unused
void vkpt_textures_destroy_unused()
Definition: textures.c:144
MAT_GetPBRMaterial
pbr_material_t * MAT_GetPBRMaterial(int index)
Definition: material.c:457
semaphore_group_s
Definition: vkpt.h:153
QVK_s::sdl2_extensions
const char ** sdl2_extensions
Definition: vkpt.h:216
vkpt_create_images
VkResult vkpt_create_images()
Definition: textures.c:1442
vkpt_uniform_buffer_destroy
VkResult vkpt_uniform_buffer_destroy()
Definition: uniform_buffer.c:127
vkpt_draw_submit_stretch_pics
VkResult vkpt_draw_submit_stretch_pics(VkCommandBuffer cmd_buf)
Definition: draw.c:499
R_DrawFill8
void(* R_DrawFill8)(int x, int y, int w, int h, int c)
Definition: refresh.c:422
sv_paused
cvar_t * sv_paused
Definition: common.c:96
R_Shutdown
void R_Shutdown(qboolean total)
Definition: main.c:280
QVK_s::fence_vertex_sync
VkFence fence_vertex_sync
Definition: vkpt.h:207
R_SetAlpha_RTX
void R_SetAlpha_RTX(float alpha)
Definition: draw.c:650
MATERIAL_FLAG_LIGHT
#define MATERIAL_FLAG_LIGHT
Definition: constants.h:73
R_DrawString_RTX
int R_DrawString_RTX(int x, int y, int flags, size_t maxlen, const char *s, qhandle_t font)
Definition: draw.c:756
IMG_Unload_RTX
void IMG_Unload_RTX(image_t *image)
Definition: textures.c:639
vkpt_asvgf_create_pipelines
VkResult vkpt_asvgf_create_pipelines()
Definition: asvgf.c:91
entity_hash_t
struct entity_hash_s entity_hash_t
bsp_mesh_s::pos
vec3_t pos
Definition: vkpt.h:381
vkpt_initialize_god_rays
VkResult vkpt_initialize_god_rays()
Definition: god_rays.c:51
R_RegisterFunctionsRTX
void R_RegisterFunctionsRTX()
Definition: main.c:3503
vkpt_pt_trace_reflections
VkResult vkpt_pt_trace_reflections(VkCommandBuffer cmd_buf, int bounce)
Definition: path_tracer.c:1063
bsp_mesh_create_from_bsp
void bsp_mesh_create_from_bsp(bsp_mesh_t *wm, bsp_t *bsp, const char *map_name)
Definition: bsp_mesh.c:1623
QVK_s::queue_compute
VkQueue queue_compute
Definition: vkpt.h:174
entity_hash_s::model
unsigned int model
Definition: main.c:1255
vkpt_refdef_s::z_near
float z_near
Definition: vkpt.h:404
reference_mode_s::num_bounce_rays
float num_bounce_rays
Definition: main.c:1903
bsp_mesh_s::dir
vec3_t dir
Definition: vkpt.h:381
R_EndFrame
void R_EndFrame(void)
Definition: main.c:863
ext
char ext[4]
Definition: images.c:657
vkpt_light_buffer_upload_staging
VkResult vkpt_light_buffer_upload_staging(VkCommandBuffer cmd_buf)
Definition: vertex_buffer.c:69
world_anim_frame
static int world_anim_frame
Definition: main.c:94
cvar_pt_aperture
cvar_t * cvar_pt_aperture
MIN
#define MIN(a, b)
Definition: vkpt.h:49
vkpt_record_god_rays_trace_command_buffer
void vkpt_record_god_rays_trace_command_buffer(VkCommandBuffer command_buffer, int pass)
Definition: god_rays.c:140
ModelInstance::offset_curr
int offset_curr
Definition: global_ubo.h:237
vkpt_initialize_all
VkResult vkpt_initialize_all(VkptInitFlags_t init_flags)
Definition: main.c:225
vkpt_physical_sky_destroy_pipelines
VkResult vkpt_physical_sky_destroy_pipelines()
Definition: physical_sky.c:402
R_SetScale_RTX
void R_SetScale_RTX(float scale)
Definition: draw.c:676
MAT_UpdatePBRMaterialSkin
const pbr_material_t * MAT_UpdatePBRMaterialSkin(image_t *image_diffuse)
Definition: material.c:517
bsp_mesh_destroy
void bsp_mesh_destroy(bsp_mesh_t *wm)
Definition: bsp_mesh.c:1760
get_screen_image_extent
static VkExtent2D get_screen_image_extent()
Definition: main.c:198
aabb_s::mins
vec3_t mins
Definition: vkpt.h:339
QVK_s::cmd_buffers_graphics
cmd_buf_group_t cmd_buffers_graphics
Definition: vkpt.h:193
vkpt_shadow_map_destroy_pipelines
VkResult vkpt_shadow_map_destroy_pipelines()
Definition: shadow_map.c:351
prepare_camera
static void prepare_camera(const vec3_t position, const vec3_t direction, mat4_t data)
Definition: main.c:2017
bsp_model_s::center
vec3_t center
Definition: vkpt.h:327
Cmd_Argv
char * Cmd_Argv(int arg)
Definition: cmd.c:899
SHADER_MAX_BSP_ENTITIES
#define SHADER_MAX_BSP_ENTITIES
Definition: constants.h:103
Sys_Milliseconds
unsigned Sys_Milliseconds(void)
Definition: system.c:644
MATERIAL_FLAG_DOUBLE_SIDED
#define MATERIAL_FLAG_DOUBLE_SIDED
Definition: constants.h:79
BSP_PointLeaf
mleaf_t * BSP_PointLeaf(mnode_t *node, vec3_t p)
Definition: bsp.c:1439
QVK_s::dbg_messenger
VkDebugUtilsMessengerEXT dbg_messenger
Definition: vkpt.h:204
vkpt_tone_mapping_create_pipelines
VkResult vkpt_tone_mapping_create_pipelines()
Definition: tone_mapping.c:146
Cmd_Argc
int Cmd_Argc(void)
Definition: cmd.c:889
bsp_model_s::aabb_min
vec3_t aabb_min
Definition: vkpt.h:328
QVK_s::physical_device
VkPhysicalDevice physical_device
Definition: vkpt.h:163
MAT_ReloadPBRMaterials
qerror_t MAT_ReloadPBRMaterials()
Definition: material.c:347
END_PERF_MARKER
#define END_PERF_MARKER(command_buffer, name)
Definition: vkpt.h:743
vkpt_pt_create_pipelines
VkResult vkpt_pt_create_pipelines()
Definition: path_tracer.c:1216
MATERIAL_FLAG_WEAPON
#define MATERIAL_FLAG_WEAPON
Definition: constants.h:76
cvar_pt_enable_nodraw
cvar_t * cvar_pt_enable_nodraw
Definition: main.c:53
VkptInitFlags_t
VkptInitFlags_t
Definition: main.c:107
vkpt_print_material
void vkpt_print_material()
Definition: main.c:356
MAT_ResetUnused
qerror_t MAT_ResetUnused()
Definition: material.c:433
vkpt_compositing
VkResult vkpt_compositing(VkCommandBuffer cmd_buf)
Definition: asvgf.c:460
vkpt_reload_shader
void vkpt_reload_shader()
Definition: main.c:291
uiStatic_s
Definition: ui.h:289
physical_sky.h
MOD_FreeUnused
void MOD_FreeUnused(void)
Definition: models.c:105
QVK_s::desc_set_textures_even
VkDescriptorSet desc_set_textures_even
Definition: vkpt.h:229
SHADER_MAX_ENTITIES
#define SHADER_MAX_ENTITIES
Definition: constants.h:102
vkpt_build_beam_lights
void vkpt_build_beam_lights(light_poly_t *light_list, int *num_lights, int max_lights, bsp_t *bsp, entity_t *entities, int num_entites, float adapted_luminance)
Definition: transparency.c:492
vkpt_pt_update_descripter_set_bindings
VkResult vkpt_pt_update_descripter_set_bindings(int idx)
Definition: path_tracer.c:251
init_vulkan
qboolean init_vulkan()
Definition: main.c:745
sun_light_s::visible
qboolean visible
Definition: vkpt.h:420
QVK_s::screenshot_image_memory
VkDeviceMemory screenshot_image_memory
Definition: vkpt.h:262
maliasmesh_s::numverts
int numverts
Definition: gl.h:233
R_SetAlphaScale
void(* R_SetAlphaScale)(float alpha)
Definition: refresh.c:412
vkpt_bloom_initialize
VkResult vkpt_bloom_initialize()
Definition: bloom.c:127
vkpt_asvgf_initialize
VkResult vkpt_asvgf_initialize()
Definition: asvgf.c:45
vkpt_next_sun_preset
void vkpt_next_sun_preset()
Definition: physical_sky.c:603
width
static int width
Definition: physical_sky.c:38
SCR_GetFont
qhandle_t SCR_GetFont(void)
Definition: screen.c:2196
QVK_s::mem_properties
VkPhysicalDeviceMemoryProperties mem_properties
Definition: vkpt.h:164
vkpt_refdef_s::fd
refdef_t * fd
Definition: vkpt.h:396
R_Init
qboolean R_Init(qboolean total)
Definition: main.c:234
cvar_pt_reflect_refract
cvar_t * cvar_pt_reflect_refract
uis
uiStatic_t uis
Definition: ui.c:24
qvkCreateDebugUtilsMessengerEXT
VkResult qvkCreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDebugUtilsMessengerEXT *pCallback)
Definition: main.c:500
_VK
#define _VK(...)
Definition: vkpt.h:65
_VK_INST_EXTENSION_LIST
#define _VK_INST_EXTENSION_LIST
Definition: vkpt.h:275
vkpt_pt_create_toplevel
VkResult vkpt_pt_create_toplevel(VkCommandBuffer cmd_buf, int idx, qboolean include_world, qboolean weapon_left_handed)
Definition: path_tracer.c:852
vkpt_refdef_s::bsp_mesh_world
bsp_mesh_t bsp_mesh_world
Definition: vkpt.h:406
vkpt_physical_sky_initialize
VkResult vkpt_physical_sky_initialize()
Definition: physical_sky.c:249
clientinfo_s::model
qhandle_t model
Definition: client.h:118
bsp_model_s::idx_count
uint32_t idx_count
Definition: vkpt.h:326
prepare_ubo
static void prepare_ubo(refdef_t *fd, mleaf_t *viewleaf, const reference_mode_t *ref_mode, const vec3_t sky_matrix[3], qboolean render_world)
Definition: main.c:2046
vkpt_light_buffer_reset_counts
void vkpt_light_buffer_reset_counts()
Definition: vertex_buffer.c:131
MATERIAL_FLAG_SHELL_BLUE
#define MATERIAL_FLAG_SHELL_BLUE
Definition: constants.h:82
Com_Error
void Com_Error(error_type_t type, const char *fmt,...)
Definition: g_main.c:258
BSP_Free
void BSP_Free(bsp_t *bsp)
Definition: bsp.c:932
BspMeshInstance
Definition: global_ubo.h:241
QVK_s::semaphores
semaphore_group_t semaphores[MAX_FRAMES_IN_FLIGHT][VKPT_MAX_GPUS]
Definition: vkpt.h:196
draw_shadowed_string
static void draw_shadowed_string(int x, int y, int flags, size_t maxlen, const char *s)
Definition: main.c:1919
QVK_s::queue_idx_compute
int32_t queue_idx_compute
Definition: vkpt.h:177
Cmd_RemoveCommand
void Cmd_RemoveCommand(const char *name)
Definition: cmd.c:1593
vkpt_profiler_destroy
VkResult vkpt_profiler_destroy()
Definition: profiler.c:42
UBO_CVAR_LIST
#define UBO_CVAR_LIST
Definition: global_ubo.h:36
vkpt_physical_sky_endRegistration
VkResult vkpt_physical_sky_endRegistration()
Definition: physical_sky.c:346
bsp_mesh_s::cluster_light_offsets
int * cluster_light_offsets
Definition: vkpt.h:370
ModelInstance::backlerp
float backlerp
Definition: global_ubo.h:237
QVK_s::queue_idx_graphics
int32_t queue_idx_graphics
Definition: vkpt.h:176
QVK_s::extent_screen_images
VkExtent2D extent_screen_images
Definition: vkpt.h:183
VKPT_INIT_SWAPCHAIN_RECREATE
@ VKPT_INIT_SWAPCHAIN_RECREATE
Definition: main.c:109
VkptInit_s::initialize
VkResult(* initialize)()
Definition: main.c:115
BspMeshInstance::frame
int frame
Definition: global_ubo.h:243
vkpt_god_rays_update_images
VkResult vkpt_god_rays_update_images()
Definition: god_rays.c:108
R_TileClear_RTX
void R_TileClear_RTX(int x, int y, int w, int h, qhandle_t pic)
Definition: draw.c:700
QVK_s::current_swap_chain_image_index
uint32_t current_swap_chain_image_index
Definition: vkpt.h:218
entity_hash_s::mesh
unsigned int mesh
Definition: main.c:1254
MOD_LoadMD2
qerror_t(* MOD_LoadMD2)(model_t *model, const void *rawdata, size_t length)
Definition: refresh.c:434
forward
static vec3_t forward
Definition: p_view.c:27
cmd_buf_group_s
Definition: vkpt.h:143
vkpt_tone_mapping_initialize
VkResult vkpt_tone_mapping_initialize()
Definition: tone_mapping.c:76
inverse
void inverse(const float *m, float *inv)
Definition: matrix.c:158
QVK_s::queue_idx_transfer
int32_t queue_idx_transfer
Definition: vkpt.h:178
material.h
vkpt_refdef_s::prev_lightstyles
lightstyle_t prev_lightstyles[MAX_LIGHTSTYLES]
Definition: vkpt.h:409
model_entity_id_count
static int model_entity_id_count[2]
Definition: main.c:1262
semaphore_group_s::trace_signaled
qboolean trace_signaled
Definition: vkpt.h:158
world_entity_ids
static int world_entity_ids[2][MAX_ENTITIES]
Definition: main.c:1261
PROFILER_STOP
@ PROFILER_STOP
Definition: vkpt.h:470
pbr_material_s
Definition: material.h:33
vkpt_asvgf_destroy_pipelines
VkResult vkpt_asvgf_destroy_pipelines()
Definition: asvgf.c:185
ModelInstance::offset_prev
int offset_prev
Definition: global_ubo.h:237
vkpt_light_buffer_upload_to_staging
VkResult vkpt_light_buffer_upload_to_staging(qboolean render_world, bsp_mesh_t *bsp_mesh, bsp_t *bsp, int num_model_lights, light_poly_t *transformed_model_lights, const float *sky_radiance)
Definition: vertex_buffer.c:310
maliasmesh_s::materials
struct pbr_material_s * materials[MAX_ALIAS_SKINS]
Definition: vkpt.h:703
create_entity_matrix
void create_entity_matrix(float matrix[16], entity_t *e, qboolean enable_left_hand)
Definition: matrix.c:23
va
char * va(const char *format,...)
Definition: shared.c:429
R_AddDecal_RTX
void R_AddDecal_RTX(decal_t *d)
Definition: main.c:3223
Z_Free
void Z_Free(void *ptr)
Definition: zone.c:147
vkpt_bloom_create_pipelines
VkResult vkpt_bloom_create_pipelines()
Definition: bloom.c:176
VKPT_INIT_RELOAD_SHADER
@ VKPT_INIT_RELOAD_SHADER
Definition: main.c:110
VKPT_INIT_DEFAULT
@ VKPT_INIT_DEFAULT
Definition: main.c:108
VkptInit_s::is_initialized
int is_initialized
Definition: main.c:118
BufferResource_s::buffer
VkBuffer buffer
Definition: vk_util.h:34
entity_hash_s
Definition: main.c:1253
R_DrawPic
void(* R_DrawPic)(int x, int y, qhandle_t pic)
Definition: refresh.c:419
cvar_pt_focus
cvar_t * cvar_pt_focus
vkpt_evaluate_sun_light
void vkpt_evaluate_sun_light(sun_light_t *light, const vec3_t sky_matrix[3], float time)
Definition: physical_sky.c:620
IMG_Shutdown
void IMG_Shutdown(void)
Definition: images.c:1448
semaphore_group_s::transfer_finished
VkSemaphore transfer_finished
Definition: vkpt.h:156
vkpt_get_profiler_result
double vkpt_get_profiler_result(int idx)
Definition: profiler.c:183
get_mesh_material
static const pbr_material_t * get_mesh_material(const entity_t *entity, const maliasmesh_t *mesh)
Definition: main.c:1269
QVK_s::swap_chain_images
VkImage swap_chain_images[MAX_SWAPCHAIN_IMAGES]
Definition: vkpt.h:190
destroy_transparency
void destroy_transparency()
Definition: transparency.c:151
R_RenderFrame
void R_RenderFrame(refdef_t *fd)
Definition: main.c:803
m
static struct mdfour * m
Definition: mdfour.c:32
CL_PLAYER_MODEL_FIRST_PERSON
#define CL_PLAYER_MODEL_FIRST_PERSON
Definition: client.h:555
ReadbackBuffer::adapted_luminance
float adapted_luminance
Definition: vertex_buffer.h:141
QVK_s::swap_chain
VkSwapchainKHR swap_chain
Definition: vkpt.h:180
VID_Shutdown
void VID_Shutdown(void)
Definition: glimp.c:54
vkpt_draw_create_pipelines
VkResult vkpt_draw_create_pipelines()
Definition: draw.c:323
cmd_buf_group_s::buffers
VkCommandBuffer * buffers
Definition: vkpt.h:146
is_transparent_material
static qboolean is_transparent_material(uint32_t material)
Definition: main.c:1479
origin
static vec3_t origin
Definition: mesh.c:27
R_DrawString
int(* R_DrawString)(int x, int y, int flags, size_t maxChars, const char *string, qhandle_t font)
Definition: refresh.c:417
R_DrawStretchPic_RTX
void R_DrawStretchPic_RTX(int x, int y, int w, int h, qhandle_t pic)
Definition: draw.c:682
client_state_s::baseclientinfo
clientinfo_t baseclientinfo
Definition: client.h:309
IMG_WIDTH
#define IMG_WIDTH
Definition: global_textures.h:25
bsp_mesh_s::models
bsp_model_t * models
Definition: vkpt.h:345
NUM_QVK_SHADER_MODULES
@ NUM_QVK_SHADER_MODULES
Definition: vkpt.h:137
r_images
image_t r_images[MAX_RIMAGES]
Definition: images.c:651
vkpt_destroy_god_rays
VkResult vkpt_destroy_god_rays()
Definition: god_rays.c:65
cvar_pt_accumulation_rendering_framenum
cvar_t * cvar_pt_accumulation_rendering_framenum
Definition: main.c:55
fill_model_instance
static uint32_t fill_model_instance(const entity_t *entity, const model_t *model, const maliasmesh_t *mesh, const float *transform, int model_instance_index, qboolean is_viewer_weapon, qboolean is_double_sided)
Definition: main.c:1283
vkpt_god_rays_prepare_ubo
void vkpt_god_rays_prepare_ubo(QVKUniformBuffer_t *ubo, const aabb_t *world_aabb, const float *proj, const float *view, const float *shadowmap_viewproj, float shadowmap_depth_scale)
Definition: god_rays.c:203
vkpt_reload_textures
void vkpt_reload_textures()
Definition: main.c:318
mult_matrix_vector
void mult_matrix_vector(float *p, const float *a, const float *b)
Definition: matrix.c:295
cl_player_model
cvar_t * cl_player_model
Definition: main.c:47
vkpt_physical_sky_create_pipelines
VkResult vkpt_physical_sky_create_pipelines()
Definition: physical_sky.c:364
QVK_s::images
VkImage images[NUM_VKPT_IMAGES]
Definition: vkpt.h:231
UpdatePhysicalSkyCVars
void UpdatePhysicalSkyCVars()
Definition: physical_sky.c:947
hud_alpha
float hud_alpha
Definition: screen.c:51
destroy_vulkan
int destroy_vulkan()
Definition: main.c:1205
ModelInstance::M
float M[16]
Definition: global_ubo.h:236
reference_mode_t
struct reference_mode_s reference_mode_t
QVK_s::screenshot_image
VkImage screenshot_image
Definition: vkpt.h:261
vkpt_physical_sky_beginRegistration
VkResult vkpt_physical_sky_beginRegistration()
Definition: physical_sky.c:338
build_transparency_blas
void build_transparency_blas(VkCommandBuffer cmd_buf)
Definition: transparency.c:217
IMG_HEIGHT
#define IMG_HEIGHT
Definition: global_textures.h:26
MATERIAL_KIND_CHROME
#define MATERIAL_KIND_CHROME
Definition: constants.h:60
VkptInit_t
struct VkptInit_s VkptInit_t
vkpt_god_rays_noop
VkResult vkpt_god_rays_noop()
Definition: god_rays.c:116
R_BeginRegistration_RTX
void R_BeginRegistration_RTX(const char *name)
Definition: main.c:3227
MOD_LoadMD2_RTX
qerror_t MOD_LoadMD2_RTX(model_t *model, const void *rawdata, size_t length)
Definition: models.c:186
ReadbackBuffer
Definition: vertex_buffer.h:134
vkpt_reset_command_buffers
void vkpt_reset_command_buffers(cmd_buf_group_t *group)
Definition: main.c:3392
vkpt_wait_idle
void vkpt_wait_idle(VkQueue queue, cmd_buf_group_t *group)
Definition: main.c:3405
bsp_model_s
Definition: vkpt.h:324
SetupRotationMatrix
void SetupRotationMatrix(vec3_t matrix[3], const vec3_t dir, float degrees)
Definition: math.c:367
vkpt_shadow_map_initialize
VkResult vkpt_shadow_map_initialize()
Definition: shadow_map.c:87
QVK_s::win_width
int win_width
Definition: vkpt.h:210
LENGTH
#define LENGTH(a)
Definition: tent.c:228
QVK_s::present_mode
VkPresentModeKHR present_mode
Definition: vkpt.h:182
cmd_buf_group_s::command_pool
VkCommandPool command_pool
Definition: vkpt.h:147
R_InterceptKey_RTX
qboolean R_InterceptKey_RTX(unsigned key, qboolean down)
Definition: freecam.c:185
BspMeshInstance::padding
float padding[3]
Definition: global_ubo.h:243
pbr_material_s::image_diffuse
image_t * image_diffuse
Definition: material.h:35
vkpt_record_god_rays_filter_command_buffer
void vkpt_record_god_rays_filter_command_buffer(VkCommandBuffer command_buffer)
Definition: god_rays.c:169
MATERIAL_FLAG_SHELL_RED
#define MATERIAL_FLAG_SHELL_RED
Definition: constants.h:80
Cvar_SetInteger
void Cvar_SetInteger(cvar_t *var, int value, from_t from)
Definition: cvar.c:509
uiStatic_s::menuDepth
int menuDepth
Definition: ui.h:294
vkpt_load_shader_modules
VkResult vkpt_load_shader_modules()
Definition: main.c:1162
BEGIN_PERF_MARKER
#define BEGIN_PERF_MARKER(command_buffer, name)
Definition: vkpt.h:742
R_AddDecal
void R_AddDecal(decal_t *d)
Definition: main.c:923
vkpt_vertex_buffer_upload_bsp_mesh_to_staging
VkResult vkpt_vertex_buffer_upload_bsp_mesh_to_staging(bsp_mesh_t *bsp_mesh)
Definition: vertex_buffer.c:90
get_accumulation_rendering_framenum
static int get_accumulation_rendering_framenum()
Definition: main.c:1909
entity_hash_s::entity
unsigned int entity
Definition: main.c:1256
MAT_IsKind
qboolean MAT_IsKind(uint32_t material, uint32_t kind)
Definition: material.c:665
R_DrawFill32
void(* R_DrawFill32)(int x, int y, int w, int h, uint32_t color)
Definition: refresh.c:423
VKPT_MAX_GPUS
#define VKPT_MAX_GPUS
Definition: vk_util.h:30
vkpt_interleave
VkResult vkpt_interleave(VkCommandBuffer cmd_buf)
Definition: asvgf.c:492
qvkDestroyDebugUtilsMessengerEXT
VkResult qvkDestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT callback, const VkAllocationCallbacks *pAllocator)
Definition: main.c:514
reference_mode_s::temporal_blend_factor
float temporal_blend_factor
Definition: main.c:1904
vkpt_textures_prefetch
void vkpt_textures_prefetch()
Definition: textures.c:75
IMG_Unload
void(* IMG_Unload)(image_t *image)
Definition: refresh.c:430
vkpt_pt_create_all_dynamic
VkResult vkpt_pt_create_all_dynamic(VkCommandBuffer cmd_buf, int idx, VkBuffer vertex_buffer, const EntityUploadInfo *upload_info)
Definition: path_tracer.c:781
VID_Init
qboolean VID_Init(void)
Definition: glimp.c:430
vkpt_pt_trace_lighting
VkResult vkpt_pt_trace_lighting(VkCommandBuffer cmd_buf, float num_bounce_rays)
Definition: path_tracer.c:1105
semaphore_group_s::render_finished
VkSemaphore render_finished
Definition: vkpt.h:155
process_render_feedback
static void process_render_feedback(ref_feedback_t *feedback, mleaf_t *viewleaf, qboolean *sun_visible, float *adapted_luminance)
Definition: main.c:1853
vkpt_vertex_buffer_create_instance
VkResult vkpt_vertex_buffer_create_instance(VkCommandBuffer cmd_buf, uint32_t num_instances, qboolean update_world_animations)
Definition: vertex_buffer.c:818
VectorNormalize2
vec_t VectorNormalize2(vec3_t v, vec3_t out)
Definition: shared.c:73
QVK_s::layers
VkLayerProperties * layers
Definition: vkpt.h:202
V
#define V(name)
Definition: g_save.c:48
SCALING_FRAMES
#define SCALING_FRAMES
vkpt_set_material
void vkpt_set_material()
Definition: main.c:340
MATERIAL_KIND_EXPLOSION
#define MATERIAL_KIND_EXPLOSION
Definition: constants.h:67
vkpt_shadow_map_render
VkResult vkpt_shadow_map_render(VkCommandBuffer cmd_buf, float *view_projection_matrix, int num_static_verts, int num_dynamic_verts, int transparent_offset, int num_transparent_verts)
Definition: shadow_map.c:364
entity_frame_num
static int entity_frame_num
Definition: main.c:1259
light_poly_s::off_center
vec3_t off_center
Definition: vkpt.h:317
vkpt_physical_sky_needs_update
qboolean vkpt_physical_sky_needs_update()
Definition: physical_sky.c:459
VkptInit_s::flags
VkptInitFlags_t flags
Definition: main.c:117
MOD_Shutdown
void MOD_Shutdown(void)
Definition: models.c:459
SCR_SetHudAlpha
void SCR_SetHudAlpha(float alpha)
Definition: screen.c:2201
QVK_s::desc_set_textures_odd
VkDescriptorSet desc_set_textures_odd
Definition: vkpt.h:230
QVK_s::cmd_buffers_compute
cmd_buf_group_t cmd_buffers_compute
Definition: vkpt.h:194
IMG_Find
image_t * IMG_Find(const char *name, imagetype_t type, imageflags_t flags)
Definition: images.c:1122
cvar_pt_accumulation_rendering
cvar_t * cvar_pt_accumulation_rendering
Definition: main.c:54
vkpt_physical_sky_record_cmd_buffer
VkResult vkpt_physical_sky_record_cmd_buffer(VkCommandBuffer cmd_buf)
Definition: physical_sky.c:467
client_static_s::frametime
float frametime
Definition: client.h:390
QVK_s::num_sdl2_extensions
uint32_t num_sdl2_extensions
Definition: vkpt.h:215
drs_minscale_changed
static void drs_minscale_changed(cvar_t *self)
Definition: main.c:163
MEDIUM_WATER
#define MEDIUM_WATER
Definition: constants.h:93
qvk
QVK_t qvk
Definition: main.c:377
vkpt_tone_mapping_destroy
VkResult vkpt_tone_mapping_destroy()
Definition: tone_mapping.c:126
maliasmesh_s::idx_offset
int idx_offset
Definition: vkpt.h:696
QVK_s::screenshot_image_memory_size
VkDeviceSize screenshot_image_memory_size
Definition: vkpt.h:263
vkpt_asvgf_create_gradient_samples
VkResult vkpt_asvgf_create_gradient_samples(VkCommandBuffer cmd_buf, uint32_t frame_num, int do_gradient_samples)
Definition: asvgf.c:251
QVK_s::gpu_slice_width_prev
uint32_t gpu_slice_width_prev
Definition: vkpt.h:188
bsp_mesh_s::world_transparent_count
uint32_t world_transparent_count
Definition: vkpt.h:351
bsp_model_s::aabb_max
vec3_t aabb_max
Definition: vkpt.h:329
vkpt_god_rays_create_pipelines
VkResult vkpt_god_rays_create_pipelines()
Definition: god_rays.c:73
vkpt_pt_init
VkResult vkpt_pt_init()
Definition: path_tracer.c:134
cluster_debug_index
int cluster_debug_index
Definition: main.c:84
num_model_lights
static int num_model_lights
Definition: main.c:1266
InitialiseSkyCVars
void InitialiseSkyCVars()
Definition: physical_sky.c:881
create_swapchain
VkResult create_swapchain()
Definition: main.c:529
R_ModeChanged
void R_ModeChanged(int width, int height, int flags, int rowbytes, void *pixels)
Definition: main.c:191
IMG_ReloadAll
void IMG_ReloadAll(void)
Definition: textures.c:665
MATERIAL_KIND_SLIME
#define MATERIAL_KIND_SLIME
Definition: constants.h:63
QVK_s::window
SDL_Window * window
Definition: vkpt.h:214
vkpt_draw_initialize
VkResult vkpt_draw_initialize()
Definition: draw.c:217
vkpt_submit_command_buffer_simple
void vkpt_submit_command_buffer_simple(VkCommandBuffer cmd_buf, VkQueue queue, qboolean all_gpus)
Definition: main.c:3473
ReadbackBuffer
struct ReadbackBuffer ReadbackBuffer
Definition: vertex_buffer.h:161
vkpt_refdef_s::bsp_mesh_world_loaded
int bsp_mesh_world_loaded
Definition: vkpt.h:407
QVK_s::wait_for_idle_frames
uint32_t wait_for_idle_frames
Definition: vkpt.h:221
vk_debug_callback
static VKAPI_ATTR VkBool32 VKAPI_CALL vk_debug_callback(VkDebugUtilsMessageSeverityFlagBitsEXT severity, VkDebugUtilsMessageTypeFlagsEXT type, const VkDebugUtilsMessengerCallbackDataEXT *callback_data, void *user_data)
Definition: main.c:466
bsp_model_s::num_light_polys
int num_light_polys
Definition: vkpt.h:331
vk_requested_instance_extensions
const _VK_EXTENSION_LIST char * vk_requested_instance_extensions[]
Definition: main.c:397
vkpt_profiler_initialize
VkResult vkpt_profiler_initialize()
Definition: profiler.c:30
registration_sequence
int registration_sequence
Definition: main.c:34
vkpt_textures_upload_envmap
VkResult vkpt_textures_upload_envmap(int w, int h, byte *data)
Definition: textures.c:150
up
static vec3_t up
Definition: p_view.c:27
vkpt_pt_destroy_static
VkResult vkpt_pt_destroy_static()
Definition: path_tracer.c:345
vkpt_tone_mapping_record_cmd_buffer
VkResult vkpt_tone_mapping_record_cmd_buffer(VkCommandBuffer cmd_buf, float frame_time)
Definition: tone_mapping.c:241
vkpt_bloom_record_cmd_buffer
VkResult vkpt_bloom_record_cmd_buffer(VkCommandBuffer cmd_buf)
Definition: bloom.c:301
bsp_mesh_s::num_light_polys
int num_light_polys
Definition: vkpt.h:373
Cvar_ClampInteger
int Cvar_ClampInteger(cvar_t *var, int min, int max)
Definition: cvar.c:549
QVK_s::extent_render
VkExtent2D extent_render
Definition: vkpt.h:184
IMG_ReadPixels_RTX
byte * IMG_ReadPixels_RTX(int *width, int *height, int *rowbytes)
Definition: main.c:3028
world_entity_id_count
static int world_entity_id_count[2]
Definition: main.c:1263
right
static vec3_t right
Definition: p_view.c:27
vkpt_refdef_s::z_far
float z_far
Definition: vkpt.h:404
MESH_FILTER_OPAQUE
#define MESH_FILTER_OPAQUE
Definition: main.c:1488
drs_init
static void drs_init()
Definition: main.c:2565
initialize_transparency
qboolean initialize_transparency()
Definition: transparency.c:114
R_BeginRegistration
void(* R_BeginRegistration)(const char *map)
Definition: refresh.c:405
extents_equal
static qboolean extents_equal(VkExtent2D a, VkExtent2D b)
Definition: main.c:179
QVK_s::extent_unscaled
VkExtent2D extent_unscaled
Definition: vkpt.h:186
EntityUploadInfo
Definition: vkpt.h:473
mult_matrix_matrix
void mult_matrix_matrix(float *p, const float *a, const float *b)
Definition: matrix.c:281
R_DrawPic_RTX
void R_DrawPic_RTX(int x, int y, qhandle_t pic)
Definition: draw.c:691
process_regular_entity
static void process_regular_entity(const entity_t *entity, const model_t *model, qboolean is_viewer_weapon, qboolean is_double_sided, int *model_instance_idx, int *instance_idx, int *num_instanced_vert, int mesh_filter, qboolean *contains_transparent)
Definition: main.c:1491
vkpt_bloom_destroy_pipelines
VkResult vkpt_bloom_destroy_pipelines()
Definition: bloom.c:196
R_SetClipRect
void(* R_SetClipRect)(const clipRect_t *clip)
Definition: refresh.c:414
drs_target_changed
static void drs_target_changed(cvar_t *self)
Definition: main.c:158
compare_doubles
static int compare_doubles(const void *pa, const void *pb)
Definition: main.c:2553
vkpt_reset_accumulation
void vkpt_reset_accumulation()
Definition: main.c:219
R_DrawStretchPic
void(* R_DrawStretchPic)(int x, int y, int w, int h, qhandle_t pic)
Definition: refresh.c:420
scr_viewsize
cvar_t * scr_viewsize
Definition: screen.c:54
viewsize_changed
static void viewsize_changed(cvar_t *self)
Definition: main.c:152
cvar_vsync
cvar_t * cvar_vsync
Definition: main.c:51
EntityUploadInfo::explosions_vertex_offset
uint32_t explosions_vertex_offset
Definition: vkpt.h:484
vkpt_pt_create_static
VkResult vkpt_pt_create_static(VkBuffer vertex_buffer, size_t buffer_offset, int num_vertices, int num_vertices_transparent, int num_vertices_sky, int num_vertices_custom_sky)
Definition: path_tracer.c:574
EntityUploadInfo::explosions_vertex_num
uint32_t explosions_vertex_num
Definition: vkpt.h:485
vkpt_reload_materials
void vkpt_reload_materials()
Definition: main.c:327
client.h
R_ModeChanged_RTX
void R_ModeChanged_RTX(int width, int height, int flags, int rowbytes, void *pixels)
Definition: main.c:2840
vkpt_tone_mapping_request_reset
void vkpt_tone_mapping_request_reset()
Definition: tone_mapping.c:138
QVK_s::num_layers
uint32_t num_layers
Definition: vkpt.h:201
EntityUploadInfo::transparent_model_vertex_num
uint32_t transparent_model_vertex_num
Definition: vkpt.h:479
maliasmesh_s::numtris
int numtris
Definition: gl.h:234
vkpt_refdef_s::uniform_instance_buffer
QVKInstanceBuffer_t uniform_instance_buffer
Definition: vkpt.h:395
vkpt_textures_update_descriptor_set
void vkpt_textures_update_descriptor_set()
Definition: textures.c:1346
R_DrawFill32_RTX
void R_DrawFill32_RTX(int x, int y, int w, int h, uint32_t color)
Definition: draw.c:717
R_SetScale
void(* R_SetScale)(float scale)
Definition: refresh.c:415
VertexBuffer
Definition: vertex_buffer.h:96
MOD_Reference_RTX
void MOD_Reference_RTX(model_t *model)
Definition: models.c:731
R_Shutdown_RTX
void R_Shutdown_RTX(qboolean total)
Definition: main.c:2993
create_projection_matrix
void create_projection_matrix(float matrix[16], float znear, float zfar, float fov_x, float fov_y)
Definition: matrix.c:63
LIST_SHADER_MODULES
#define LIST_SHADER_MODULES
Definition: vkpt.h:70
drs_current_scale
static int drs_current_scale
Definition: main.c:68
vkpt_vertex_buffer_upload_staging
VkResult vkpt_vertex_buffer_upload_staging()
Definition: vertex_buffer.c:36
create_command_pool_and_fences
VkResult create_command_pool_and_fences()
Definition: main.c:689
get_vk_extension_list
void get_vk_extension_list(const char *layer, uint32_t *num_extensions, VkExtensionProperties **ext)
Definition: main.c:434
bsp_mesh_s::world_idx_count
uint32_t world_idx_count
Definition: vkpt.h:344
add_dlights
static void add_dlights(const dlight_t *lights, int num_lights, QVKUniformBuffer_t *ubo)
Definition: main.c:1342
vkpt_destroy_all
VkResult vkpt_destroy_all(VkptInitFlags_t destroy_flags)
Definition: main.c:262
reference_mode_s
Definition: main.c:1899
cls
client_static_t cls
Definition: main.c:98
cvar_min_driver_version
cvar_t * cvar_min_driver_version
Definition: main.c:71
QVK_s::fences_frame_sync
VkFence fences_frame_sync[MAX_FRAMES_IN_FLIGHT]
Definition: vkpt.h:206
destroy_swapchain
VkResult destroy_swapchain()
Definition: main.c:1194
vkpt_show_pvs
static void vkpt_show_pvs(void)
Definition: main.c:2852
R_DrawChar
void(* R_DrawChar)(int x, int y, int flags, int ch, qhandle_t font)
Definition: refresh.c:416
EntityUploadInfo::viewer_weapon_vertex_num
uint32_t viewer_weapon_vertex_num
Definition: vkpt.h:483
R_ClearColor_RTX
void R_ClearColor_RTX(void)
Definition: draw.c:643
layer_requested
int layer_requested(const char *name)
Definition: main.c:455
IMAGE_BARRIER
#define IMAGE_BARRIER(cmd_buf,...)
Definition: vk_util.h:55
bsp_mesh_s::world_aabb
aabb_t world_aabb
Definition: vkpt.h:348
vkpt_vertex_buffer_upload_models_to_staging
VkResult vkpt_vertex_buffer_upload_models_to_staging()
Definition: vertex_buffer.c:412
vkpt_tone_mapping_destroy_pipelines
VkResult vkpt_tone_mapping_destroy_pipelines()
Definition: tone_mapping.c:207
sky_axis
static vec3_t sky_axis
Definition: main.c:105
accumulation_cvar_changed
static void accumulation_cvar_changed(cvar_t *self)
Definition: main.c:173
update_transparency
void update_transparency(VkCommandBuffer command_buffer, const float *view_matrix, const particle_t *particles, int particle_num, const entity_t *entities, int entity_num)
Definition: transparency.c:171
BSP_Load
qerror_t BSP_Load(const char *name, bsp_t **bsp_p)
Definition: bsp.c:1087
vkpt_pt_trace_primary_rays
VkResult vkpt_pt_trace_primary_rays(VkCommandBuffer cmd_buf)
Definition: path_tracer.c:1009
color
static vec4_t color
Definition: mesh.c:33
IMG_ForHandle
image_t * IMG_ForHandle(qhandle_t h)
Definition: images.c:1156
cvar_drs_enable
cvar_t * cvar_drs_enable
Definition: main.c:59
ATTACH_LABEL_VARIABLE
#define ATTACH_LABEL_VARIABLE(a, type)
Definition: vk_util.h:137
cl
client_state_t cl
Definition: main.c:99
ReadbackBuffer::sun_luminance
float sun_luminance
Definition: vertex_buffer.h:138
vkpt_begin_command_buffer
VkCommandBuffer vkpt_begin_command_buffer(cmd_buf_group_t *group)
Definition: main.c:3301
IMG_FreeUnused
void IMG_FreeUnused(void)
Definition: images.c:1310
vkpt_freecam_reset
void vkpt_freecam_reset()
Definition: freecam.c:55
Q_concat
size_t Q_concat(char *dest, size_t size,...)
Definition: shared.c:758
bsp_mesh_s::world_transparent_offset
uint32_t world_transparent_offset
Definition: vkpt.h:350
model_entity_ids
static int model_entity_ids[2][MAX_ENTITIES]
Definition: main.c:1260
cvar_drs_minscale
cvar_t * cvar_drs_minscale
Definition: main.c:61
VkptInit_s::destroy
VkResult(* destroy)()
Definition: main.c:116
QVK_s::buf_readback_staging
BufferResource_t buf_readback_staging[MAX_FRAMES_IN_FLIGHT]
Definition: vkpt.h:250
cvar_drs_maxscale
cvar_t * cvar_drs_maxscale
Definition: main.c:62
MAT_InitializePBRmaterials
qerror_t MAT_InitializePBRmaterials()
Definition: material.c:341
MATERIAL_KIND_INVISIBLE
#define MATERIAL_KIND_INVISIBLE
Definition: constants.h:66
cvar_bloom_enable
cvar_t * cvar_bloom_enable
Definition: bloom.c:45
aabb_s::maxs
vec3_t maxs
Definition: vkpt.h:340
cluster_debug_mask
char cluster_debug_mask[VIS_MAX_BYTES]
Definition: main.c:83
create_shader_module_from_file
static VkShaderModule create_shader_module_from_file(const char *name, const char *enum_name)
Definition: main.c:1121
MATERIAL_INDEX_MASK
#define MATERIAL_INDEX_MASK
Definition: constants.h:86
EntityUploadInfo::num_vertices
uint32_t num_vertices
Definition: vkpt.h:476
R_BeginFrame
void R_BeginFrame(void)
Definition: main.c:858
vkpt_bloom_update
void vkpt_bloom_update(QVKUniformBuffer_t *ubo, float frame_time, qboolean under_water, qboolean menu_mode)
Definition: bloom.c:88
vkpt_textures_initialize
VkResult vkpt_textures_initialize()
Definition: textures.c:821
vkpt_asvgf_filter
VkResult vkpt_asvgf_filter(VkCommandBuffer cmd_buf, qboolean enable_lf)
Definition: asvgf.c:325
R_DrawChar_RTX
void R_DrawChar_RTX(int x, int y, int flags, int c, qhandle_t font)
Definition: draw.c:750
vkpt_initialization
VkptInit_t vkpt_initialization[]
Definition: main.c:120
int
CONST PIXELFORMATDESCRIPTOR int
Definition: wgl.c:26
QVK_s::surf_format
VkSurfaceFormatKHR surf_format
Definition: vkpt.h:181
vkpt_destroy_images
VkResult vkpt_destroy_images()
Definition: textures.c:1757
semaphore_group_s::image_available
VkSemaphore image_available
Definition: vkpt.h:154
MATERIAL_KIND_WATER
#define MATERIAL_KIND_WATER
Definition: constants.h:61
vkpt_draw_clear_stretch_pics
VkResult vkpt_draw_clear_stretch_pics()
Definition: draw.c:492
vkpt_god_rays_enabled
qboolean vkpt_god_rays_enabled(const sun_light_t *sun_light)
Definition: god_rays.c:379
semaphore_group_s::trace_finished
VkSemaphore trace_finished
Definition: vkpt.h:157
bsp_world_model
static UBO_CVAR_LIST bsp_t * bsp_world_model
Definition: main.c:90
create_view_matrix
void create_view_matrix(float matrix[16], refdef_t *fd)
Definition: matrix.c:131
QVK_s::swap_chain_image_views
VkImageView swap_chain_image_views[MAX_SWAPCHAIN_IMAGES]
Definition: vkpt.h:191
vkpt_shadow_map_create_pipelines
VkResult vkpt_shadow_map_create_pipelines()
Definition: shadow_map.c:209
vkpt_vertex_buffer_destroy
VkResult vkpt_vertex_buffer_destroy()
Definition: vertex_buffer.c:675
vkpt_profiler_query
VkResult vkpt_profiler_query(VkCommandBuffer cmd_buf, int idx, VKPTProfilerAction action)
Definition: profiler.c:49
vkpt_refdef_s
Definition: vkpt.h:393
vkpt_bloom_destroy
VkResult vkpt_bloom_destroy()
Definition: bloom.c:165
temporal_cvar_changed
static void temporal_cvar_changed(cvar_t *self)
Definition: main.c:2535
R_EndRegistration_RTX
void R_EndRegistration_RTX(void)
Definition: main.c:3290
vkpt_physical_sky_update_ubo
VkResult vkpt_physical_sky_update_ubo(QVKUniformBuffer_t *ubo, const sun_light_t *light, qboolean render_world)
Definition: physical_sky.c:774
vkpt_shadow_map_destroy
VkResult vkpt_shadow_map_destroy()
Definition: shadow_map.c:182
vkpt_submit_command_buffer
void vkpt_submit_command_buffer(VkCommandBuffer cmd_buf, VkQueue queue, uint32_t execute_device_mask, int wait_semaphore_count, VkSemaphore *wait_semaphores, VkPipelineStageFlags *wait_stages, uint32_t *wait_device_indices, int signal_semaphore_count, VkSemaphore *signal_semaphores, uint32_t *signal_device_indices, VkFence fence)
Definition: main.c:3411
ReadbackBuffer::material
uint32_t material
Definition: vertex_buffer.h:136
model_lights
static light_poly_t model_lights[MAX_MODEL_LIGHTS]
Definition: main.c:1267
vkpt_physical_sky_destroy
VkResult vkpt_physical_sky_destroy()
Definition: physical_sky.c:315
qvk_result_to_string
const char * qvk_result_to_string(VkResult result)
Definition: vk_util.c:439
VkptInit_s::name
const char * name
Definition: main.c:114
QVK_s::surface
VkSurfaceKHR surface
Definition: vkpt.h:179
IMG_Init
void IMG_Init(void)
Definition: images.c:1419
EntityUploadInfo::viewer_model_vertex_offset
uint32_t viewer_model_vertex_offset
Definition: vkpt.h:480
vkpt_light_stats_destroy
VkResult vkpt_light_stats_destroy()
Definition: vertex_buffer.c:748
bsp_model_s::idx_offset
uint32_t idx_offset
Definition: vkpt.h:325
process_bsp_entity
static void process_bsp_entity(const entity_t *entity, int *bsp_mesh_idx, int *instance_idx, int *num_instanced_vert)
Definition: main.c:1372
QVK_s::extent_render_prev
VkExtent2D extent_render_prev
Definition: vkpt.h:185
vkpt_freecam_update
void vkpt_freecam_update(float frame_time)
Definition: freecam.c:120
vkpt_refdef_s::uniform_buffer
QVKUniformBuffer_t uniform_buffer
Definition: vkpt.h:394
vkpt_pt_destroy
VkResult vkpt_pt_destroy()
Definition: path_tracer.c:1196
light_poly_s::cluster
int cluster
Definition: vkpt.h:320
VectorNormalize
vec_t VectorNormalize(vec3_t v)
Definition: shared.c:55
MAT_SetKind
uint32_t MAT_SetKind(uint32_t material, uint32_t kind)
Definition: material.c:660
FS_NormalizePath
size_t FS_NormalizePath(char *out, const char *in)
Definition: files.c:331
qvk_get_current_desc_set_textures
VkDescriptorSet qvk_get_current_desc_set_textures()
Definition: main.c:1847
EntityUploadInfo::transparent_model_vertex_offset
uint32_t transparent_model_vertex_offset
Definition: vkpt.h:478
MAT_FindPBRMaterial
pbr_material_t * MAT_FindPBRMaterial(char const *name)
Definition: material.c:465
QVK_s::queue_graphics
VkQueue queue_graphics
Definition: vkpt.h:173
QVK_s::device_count
int device_count
Definition: vkpt.h:167
MEDIUM_NONE
#define MEDIUM_NONE
Definition: constants.h:92
QVK_s::queue_transfer
VkQueue queue_transfer
Definition: vkpt.h:175
QVK_s::num_extensions
uint32_t num_extensions
Definition: vkpt.h:198
MATERIAL_KIND_GLASS
#define MATERIAL_KIND_GLASS
Definition: constants.h:64
MAX_SWAPCHAIN_IMAGES
#define MAX_SWAPCHAIN_IMAGES
Definition: vkpt.h:141
light_poly_s::positions
float positions[9]
Definition: vkpt.h:316
transform_point
static void transform_point(const float *p, const float *matrix, float *result)
Definition: main.c:1364
bsp_mesh_s::cameras
struct bsp_mesh_s::@19 cameras[MAX_CAMERAS]
reference_mode_s::enable_accumulation
qboolean enable_accumulation
Definition: main.c:1901
vkpt_uniform_buffer_create
VkResult vkpt_uniform_buffer_create()
Definition: uniform_buffer.c:30
water_normal_texture
static image_t * water_normal_texture
Definition: main.c:98
reference_mode_s::reflect_refract
int reflect_refract
Definition: main.c:1905
R_SetAlphaScale_RTX
void R_SetAlphaScale_RTX(float alpha)
Definition: draw.c:657
R_SetSky_RTX
void R_SetSky_RTX(const char *name, float rotate, vec3_t axis)
Definition: main.c:3154
bsp_model_s::transparent
qboolean transparent
Definition: vkpt.h:335
vkpt_physical_sky_latch_local_time
void vkpt_physical_sky_latch_local_time()
Definition: physical_sky.c:75
ReadbackBuffer::hdr_color
vec3_t hdr_color
Definition: vertex_buffer.h:140
drs_maxscale_changed
static void drs_maxscale_changed(cvar_t *self)
Definition: main.c:168
frame_ready
static qboolean frame_ready
Definition: main.c:102
vkpt_bloom_reset
void vkpt_bloom_reset()
Definition: bloom.c:76
recreate_swapchain
static void recreate_swapchain()
Definition: main.c:2541
EntityUploadInfo::num_instances
uint32_t num_instances
Definition: vkpt.h:475
bsp_mesh_s::num_cameras
int num_cameras
Definition: vkpt.h:382
SCR_DrawStringEx
int SCR_DrawStringEx(int x, int y, int flags, size_t maxlen, const char *s, qhandle_t font)
Definition: screen.c:139
EntityUploadInfo::viewer_weapon_vertex_offset
uint32_t viewer_weapon_vertex_offset
Definition: vkpt.h:482
prepare_entities
static void prepare_entities(EntityUploadInfo *upload_info)
Definition: main.c:1607
get_vk_layer_list
void get_vk_layer_list(uint32_t *num_layers, VkLayerProperties **ext)
Definition: main.c:445