vkQuake2 doxygen  1.0 dev
vk_swapchain.c File Reference
#include "vk_local.h"

Go to the source code of this file.

Macros

#define PMSTR(r)   case VK_ ##r: return "VK_"#r
 

Functions

static const char * presentModeString (VkPresentModeKHR presentMode)
 
static VkSurfaceFormatKHR getSwapSurfaceFormat (const VkSurfaceFormatKHR *surfaceFormats, uint32_t formatCount)
 
static VkPresentModeKHR getSwapPresentMode (const VkPresentModeKHR *presentModes, uint32_t presentModesCount, VkPresentModeKHR desiredMode)
 
static VkCompositeAlphaFlagBitsKHR getSupportedCompositeAlpha (VkCompositeAlphaFlagsKHR supportedFlags)
 
VkResult QVk_CreateSwapchain ()
 

Macro Definition Documentation

◆ PMSTR

#define PMSTR (   r)    case VK_ ##r: return "VK_"#r

Function Documentation

◆ getSupportedCompositeAlpha()

static VkCompositeAlphaFlagBitsKHR getSupportedCompositeAlpha ( VkCompositeAlphaFlagsKHR  supportedFlags)
static

Definition at line 99 of file vk_swapchain.c.

100 {
101  VkCompositeAlphaFlagBitsKHR compositeAlphaFlags[] = {
102  VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
103  VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR,
104  VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR,
105  VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR
106  };
107 
108  for (int i = 0; i < 4; ++i)
109  {
110  if (supportedFlags & compositeAlphaFlags[i])
111  return compositeAlphaFlags[i];
112  }
113 
114  return VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR;
115 }

Referenced by QVk_CreateSwapchain().

◆ getSwapPresentMode()

static VkPresentModeKHR getSwapPresentMode ( const VkPresentModeKHR *  presentModes,
uint32_t  presentModesCount,
VkPresentModeKHR  desiredMode 
)
static

Definition at line 62 of file vk_swapchain.c.

63 {
64  // check if the desired present mode is supported
65  for (uint32_t i = 0; i < presentModesCount; ++i)
66  {
67  // mode supported, nothing to do here
68  if (presentModes[i] == desiredMode)
69  {
71  ri.Con_Printf(PRINT_ALL, "...using present mode: %s\n", vk_config.present_mode);
72  return desiredMode;
73  }
74  }
75 
76  // PRESENT_MODE_FIFO_KHR is guaranteed to exist due to spec requirements
77  VkPresentModeKHR usedPresentMode = VK_PRESENT_MODE_FIFO_KHR;
78  // preferred present mode not found - choose the next best thing
79  for (uint32_t i = 0; i < presentModesCount; ++i)
80  {
81  // always prefer mailbox for triple buffering
82  if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR)
83  {
84  usedPresentMode = presentModes[i];
85  break;
86  }
87  else if (presentModes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR)
88  {
89  usedPresentMode = presentModes[i];
90  }
91  }
92 
93  vk_config.present_mode = presentModeString(usedPresentMode);
94  ri.Con_Printf(PRINT_ALL, "...present mode %s not supported, using present mode: %s\n", presentModeString(desiredMode), vk_config.present_mode);
95  return usedPresentMode;
96 }

Referenced by QVk_CreateSwapchain().

◆ getSwapSurfaceFormat()

static VkSurfaceFormatKHR getSwapSurfaceFormat ( const VkSurfaceFormatKHR *  surfaceFormats,
uint32_t  formatCount 
)
static

Definition at line 40 of file vk_swapchain.c.

41 {
42  VkSurfaceFormatKHR swapSurfaceFormat;
43 
44  for (size_t i = 0; i < formatCount; ++i)
45  {
46  if (surfaceFormats[i].colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR &&
47  surfaceFormats[i].format == VK_FORMAT_B8G8R8A8_UNORM)
48  {
49  swapSurfaceFormat.colorSpace = surfaceFormats[i].colorSpace;
50  swapSurfaceFormat.format = surfaceFormats[i].format;
51  return swapSurfaceFormat;
52  }
53  }
54  // no preferred format, so get the first one from list
55  swapSurfaceFormat.colorSpace = surfaceFormats[0].colorSpace;
56  swapSurfaceFormat.format = surfaceFormats[0].format;
57 
58  return swapSurfaceFormat;
59 }

Referenced by QVk_CreateSwapchain().

◆ presentModeString()

static const char* presentModeString ( VkPresentModeKHR  presentMode)
static

Definition at line 24 of file vk_swapchain.c.

25 {
26 #define PMSTR(r) case VK_ ##r: return "VK_"#r
27  switch (presentMode)
28  {
29  PMSTR(PRESENT_MODE_IMMEDIATE_KHR);
30  PMSTR(PRESENT_MODE_MAILBOX_KHR);
31  PMSTR(PRESENT_MODE_FIFO_KHR);
32  PMSTR(PRESENT_MODE_FIFO_RELAXED_KHR);
33  default: return "<unknown>";
34  }
35 #undef PMSTR
36  return "UNKNOWN PRESENT MODE";
37 }

Referenced by getSwapPresentMode(), and QVk_CreateSwapchain().

◆ QVk_CreateSwapchain()

VkResult QVk_CreateSwapchain ( )

Definition at line 117 of file vk_swapchain.c.

118 {
119  VkSurfaceCapabilitiesKHR surfaceCaps;
120  VkSurfaceFormatKHR *surfaceFormats = NULL;
121  VkPresentModeKHR *presentModes = NULL;
122  uint32_t formatCount, presentModesCount;
123  VK_VERIFY(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(vk_device.physical, vk_surface, &surfaceCaps));
124  VK_VERIFY(vkGetPhysicalDeviceSurfaceFormatsKHR(vk_device.physical, vk_surface, &formatCount, NULL));
125  VK_VERIFY(vkGetPhysicalDeviceSurfacePresentModesKHR(vk_device.physical, vk_surface, &presentModesCount, NULL));
126 
127  if (formatCount > 0)
128  {
129  surfaceFormats = (VkSurfaceFormatKHR *)malloc(formatCount * sizeof(VkSurfaceFormatKHR));
130  VK_VERIFY(vkGetPhysicalDeviceSurfaceFormatsKHR(vk_device.physical, vk_surface, &formatCount, surfaceFormats));
131  }
132 
133  if (presentModesCount > 0)
134  {
135  presentModes = (VkPresentModeKHR *)malloc(presentModesCount * sizeof(VkPresentModeKHR));
136  VK_VERIFY(vkGetPhysicalDeviceSurfacePresentModesKHR(vk_device.physical, vk_surface, &presentModesCount, presentModes));
137 
138  ri.Con_Printf(PRINT_ALL, "Supported present modes: ");
139  for (int i = 0; i < presentModesCount; i++)
140  {
141  ri.Con_Printf(PRINT_ALL, "%s ", presentModeString(presentModes[i]));
143  }
144  ri.Con_Printf(PRINT_ALL, "\n");
145  }
146 
147  VkSurfaceFormatKHR swapSurfaceFormat = getSwapSurfaceFormat(surfaceFormats, formatCount);
148  VkPresentModeKHR swapPresentMode = getSwapPresentMode(presentModes, presentModesCount, vk_vsync->value > 0 ? VK_PRESENT_MODE_FIFO_KHR : VK_PRESENT_MODE_MAILBOX_KHR);
149  free(surfaceFormats);
150  free(presentModes);
151 
152  VkExtent2D extent = surfaceCaps.currentExtent;
153  if(extent.width == UINT32_MAX || extent.height == UINT32_MAX)
154  {
155  extent.width = max(surfaceCaps.minImageExtent.width, min(surfaceCaps.maxImageExtent.width, vid.width));
156  extent.height = max(surfaceCaps.minImageExtent.height, min(surfaceCaps.maxImageExtent.height, vid.height));
157  }
158 
159  // request at least 2 images - this fixes fullscreen crashes on AMD when launching the game in fullscreen
160  uint32_t imageCount = max(2, surfaceCaps.minImageCount);
161  if (swapPresentMode == VK_PRESENT_MODE_MAILBOX_KHR)
162  imageCount = max(3, surfaceCaps.minImageCount);
163 
164  if (surfaceCaps.maxImageCount > 0)
165  imageCount = min(imageCount, surfaceCaps.maxImageCount);
166 
167  VkSwapchainKHR oldSwapchain = vk_swapchain.sc;
168  VkSwapchainCreateInfoKHR scCreateInfo = {
169  .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
170  .pNext = NULL,
171  .flags = 0,
172  .surface = vk_surface,
173  .minImageCount = imageCount,
174  .imageFormat = swapSurfaceFormat.format,
175  .imageColorSpace = swapSurfaceFormat.colorSpace,
176  .imageExtent = extent,
177  .imageArrayLayers = 1,
178  .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // TRANSFER_SRC_BIT is required for taking screenshots
179  .imageSharingMode = VK_SHARING_MODE_EXCLUSIVE,
180  .queueFamilyIndexCount = 0,
181  .pQueueFamilyIndices = NULL,
182  .preTransform = surfaceCaps.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR ? VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR : surfaceCaps.currentTransform,
183  .compositeAlpha = getSupportedCompositeAlpha(surfaceCaps.supportedCompositeAlpha),
184  .presentMode = swapPresentMode,
185  .clipped = VK_TRUE,
186  .oldSwapchain = oldSwapchain
187  };
188 
189  uint32_t queueFamilyIndices[] = { (uint32_t)vk_device.gfxFamilyIndex, (uint32_t)vk_device.presentFamilyIndex };
191  {
192  scCreateInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
193  scCreateInfo.queueFamilyIndexCount = 2;
194  scCreateInfo.pQueueFamilyIndices = queueFamilyIndices;
195  }
196 
197  vk_swapchain.format = swapSurfaceFormat.format;
198  vk_swapchain.extent = extent;
199  ri.Con_Printf(PRINT_ALL, "...trying swapchain extent: %dx%d\n", vk_swapchain.extent.width, vk_swapchain.extent.height);
200  ri.Con_Printf(PRINT_ALL, "...trying swapchain image format: %d\n", vk_swapchain.format);
201 
202  VkResult res = vkCreateSwapchainKHR(vk_device.logical, &scCreateInfo, NULL, &vk_swapchain.sc);
203  if (res != VK_SUCCESS)
204  return res;
205 
206  VK_VERIFY(vkGetSwapchainImagesKHR(vk_device.logical, vk_swapchain.sc, &imageCount, NULL));
207  vk_swapchain.images = (VkImage *)malloc(imageCount * sizeof(VkImage));
208  vk_swapchain.imageCount = imageCount;
209  res = vkGetSwapchainImagesKHR(vk_device.logical, vk_swapchain.sc, &imageCount, vk_swapchain.images);
210 
211  if (oldSwapchain != VK_NULL_HANDLE)
212  vkDestroySwapchainKHR(vk_device.logical, oldSwapchain, NULL);
213 
214  return res;
215 }

Referenced by QVk_Init(), and QVk_RecreateSwapchain().

qvkdevice_t::logical
VkDevice logical
Definition: qvk.h:40
ri
refimport_t ri
Definition: r_main.c:25
i
int i
Definition: q_shared.c:305
qvkdevice_t::gfxFamilyIndex
int gfxFamilyIndex
Definition: qvk.h:46
vk_device
qvkdevice_t vk_device
Definition: vk_common.c:51
qvkdevice_t::presentFamilyIndex
int presentFamilyIndex
Definition: qvk.h:47
presentModeString
static const char * presentModeString(VkPresentModeKHR presentMode)
Definition: vk_swapchain.c:24
refimport_t::Con_Printf
void(* Con_Printf)(int print_level, char *str,...)
Definition: ref.h:202
PRINT_ALL
#define PRINT_ALL
Definition: qcommon.h:751
vkconfig_t::present_mode
const char * present_mode
Definition: vk_local.h:309
vk_vsync
static cvar_t * vk_vsync
Definition: vid_menu.c:48
qvkswapchain_t::format
VkFormat format
Definition: qvk.h:55
qvkswapchain_t::extent
VkExtent2D extent
Definition: qvk.h:57
viddef_t::width
unsigned width
Definition: vid.h:29
vk_swapchain
qvkswapchain_t vk_swapchain
Definition: vk_common.c:63
min
#define min(a, b)
Definition: vk_local.h:72
viddef_t::height
unsigned height
Definition: vid.h:29
cvar_s::value
float value
Definition: q_shared.h:331
qvkswapchain_t::imageCount
int imageCount
Definition: qvk.h:59
NULL
#define NULL
Definition: q_shared.h:67
vk_config
vkconfig_t vk_config
Definition: vk_rmain.c:30
VK_VERIFY
#define VK_VERIFY(x)
Definition: vk_local.h:59
PMSTR
#define PMSTR(r)
qvkswapchain_t::sc
VkSwapchainKHR sc
Definition: qvk.h:54
qvkswapchain_t::images
VkImage * images
Definition: qvk.h:58
getSupportedCompositeAlpha
static VkCompositeAlphaFlagBitsKHR getSupportedCompositeAlpha(VkCompositeAlphaFlagsKHR supportedFlags)
Definition: vk_swapchain.c:99
format
GLsizei GLenum format
Definition: qgl_win.c:131
vk_surface
VkSurfaceKHR vk_surface
Definition: vk_common.c:47
getSwapSurfaceFormat
static VkSurfaceFormatKHR getSwapSurfaceFormat(const VkSurfaceFormatKHR *surfaceFormats, uint32_t formatCount)
Definition: vk_swapchain.c:40
getSwapPresentMode
static VkPresentModeKHR getSwapPresentMode(const VkPresentModeKHR *presentModes, uint32_t presentModesCount, VkPresentModeKHR desiredMode)
Definition: vk_swapchain.c:62
max
#define max(a, b)
Definition: vk_local.h:75
qvkdevice_t::physical
VkPhysicalDevice physical
Definition: qvk.h:39
vkconfig_t::supported_present_modes
const char * supported_present_modes[256]
Definition: vk_local.h:310
vid
viddef_t vid
Definition: r_main.c:24