1 #include "SwapChainStateVk.h"
2
3 #include "vulkan/vk_util.h"
4
SwapChainStateVk(const goldfish_vk::VulkanDispatch & vk,VkDevice vkDevice,const VkSwapchainCreateInfoKHR & swapChainCi)5 SwapChainStateVk::SwapChainStateVk(const goldfish_vk::VulkanDispatch &vk,
6 VkDevice vkDevice,
7 const VkSwapchainCreateInfoKHR &swapChainCi)
8 : m_vk(vk),
9 m_vkDevice(vkDevice),
10 m_vkSwapChain(VK_NULL_HANDLE),
11 m_vkImages(0),
12 m_vkImageViews(0) {
13 VK_CHECK(m_vk.vkCreateSwapchainKHR(m_vkDevice, &swapChainCi, nullptr,
14 &m_vkSwapChain));
15 uint32_t imageCount = 0;
16 VK_CHECK(m_vk.vkGetSwapchainImagesKHR(m_vkDevice, m_vkSwapChain,
17 &imageCount, nullptr));
18 m_vkImages.resize(imageCount);
19 VK_CHECK(m_vk.vkGetSwapchainImagesKHR(m_vkDevice, m_vkSwapChain,
20 &imageCount, m_vkImages.data()));
21 for (auto i = 0; i < m_vkImages.size(); i++) {
22 VkImageViewCreateInfo imageViewCi = {
23 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
24 .image = m_vkImages[i],
25 .viewType = VK_IMAGE_VIEW_TYPE_2D,
26 .format = k_vkFormat,
27 .components = {.r = VK_COMPONENT_SWIZZLE_IDENTITY,
28 .g = VK_COMPONENT_SWIZZLE_IDENTITY,
29 .b = VK_COMPONENT_SWIZZLE_IDENTITY,
30 .a = VK_COMPONENT_SWIZZLE_IDENTITY},
31 .subresourceRange = {.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
32 .baseMipLevel = 0,
33 .levelCount = 1,
34 .baseArrayLayer = 0,
35 .layerCount = 1}};
36 VkImageView vkImageView;
37 VK_CHECK(m_vk.vkCreateImageView(m_vkDevice, &imageViewCi, nullptr,
38 &vkImageView));
39 m_vkImageViews.push_back(vkImageView);
40 }
41 }
42
~SwapChainStateVk()43 SwapChainStateVk::~SwapChainStateVk() {
44 for (auto imageView : m_vkImageViews) {
45 m_vk.vkDestroyImageView(m_vkDevice, imageView, nullptr);
46 }
47 m_vk.vkDestroySwapchainKHR(m_vkDevice, m_vkSwapChain, nullptr);
48 }
49
getRequiredInstanceExtensions()50 std::vector<const char *> SwapChainStateVk::getRequiredInstanceExtensions() {
51 return {
52 VK_KHR_SURFACE_EXTENSION_NAME,
53 #ifdef _WIN32
54 VK_KHR_WIN32_SURFACE_EXTENSION_NAME,
55 #endif
56 #ifdef __APPLE__
57 VK_EXT_METAL_SURFACE_EXTENSION_NAME,
58 #endif
59 #ifdef VK_USE_PLATFORM_XCB_KHR
60 VK_KHR_XCB_SURFACE_EXTENSION_NAME,
61 #endif
62 };
63 }
64
getRequiredDeviceExtensions()65 std::vector<const char *> SwapChainStateVk::getRequiredDeviceExtensions() {
66 return {
67 VK_KHR_SWAPCHAIN_EXTENSION_NAME,
68 };
69 }
70
validateQueueFamilyProperties(const goldfish_vk::VulkanDispatch & vk,VkPhysicalDevice physicalDevice,VkSurfaceKHR surface,uint32_t queueFamilyIndex)71 bool SwapChainStateVk::validateQueueFamilyProperties(
72 const goldfish_vk::VulkanDispatch &vk, VkPhysicalDevice physicalDevice,
73 VkSurfaceKHR surface, uint32_t queueFamilyIndex) {
74 VkBool32 presentSupport = VK_FALSE;
75 VK_CHECK(vk.vkGetPhysicalDeviceSurfaceSupportKHR(
76 physicalDevice, queueFamilyIndex, surface, &presentSupport));
77 return presentSupport;
78 }
79
80 SwapChainStateVk::VkSwapchainCreateInfoKHRPtr
createSwapChainCi(const goldfish_vk::VulkanDispatch & vk,VkSurfaceKHR surface,VkPhysicalDevice physicalDevice,uint32_t width,uint32_t height,const std::unordered_set<uint32_t> & queueFamilyIndices)81 SwapChainStateVk::createSwapChainCi(
82 const goldfish_vk::VulkanDispatch &vk, VkSurfaceKHR surface,
83 VkPhysicalDevice physicalDevice, uint32_t width, uint32_t height,
84 const std::unordered_set<uint32_t> &queueFamilyIndices) {
85 uint32_t formatCount = 0;
86 VK_CHECK(vk.vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface,
87 &formatCount, nullptr));
88 std::vector<VkSurfaceFormatKHR> formats(formatCount);
89 VK_CHECK(vk.vkGetPhysicalDeviceSurfaceFormatsKHR(
90 physicalDevice, surface, &formatCount, formats.data()));
91 auto iSurfaceFormat = std::find_if(
92 formats.begin(), formats.end(), [](const VkSurfaceFormatKHR &format) {
93 return format.format == k_vkFormat &&
94 format.colorSpace == k_vkColorSpace;
95 });
96 if (iSurfaceFormat == formats.end()) {
97 return nullptr;
98 }
99
100 uint32_t presentModeCount = 0;
101 VK_CHECK(vk.vkGetPhysicalDeviceSurfacePresentModesKHR(
102 physicalDevice, surface, &presentModeCount, nullptr));
103 std::vector<VkPresentModeKHR> presentModes(presentModeCount);
104 auto iPresentMode =
105 std::find_if(presentModes.begin(), presentModes.end(),
106 [](const VkPresentModeKHR &presentMode) {
107 return presentMode == VK_PRESENT_MODE_IMMEDIATE_KHR;
108 });
109 if (iPresentMode == presentModes.end()) {
110 return nullptr;
111 }
112 VkSurfaceCapabilitiesKHR surfaceCaps;
113 VK_CHECK(vk.vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
114 physicalDevice, surface, &surfaceCaps));
115 std::optional<VkExtent2D> maybeExtent = std::nullopt;
116 if (surfaceCaps.currentExtent.width != UINT32_MAX &&
117 surfaceCaps.currentExtent.width == width &&
118 surfaceCaps.currentExtent.height == height) {
119 maybeExtent = surfaceCaps.currentExtent;
120 } else if (width >= surfaceCaps.minImageExtent.width &&
121 width <= surfaceCaps.maxImageExtent.width &&
122 height >= surfaceCaps.minImageExtent.height &&
123 height <= surfaceCaps.maxImageExtent.height) {
124 maybeExtent = VkExtent2D({width, height});
125 }
126 if (!maybeExtent.has_value()) {
127 return nullptr;
128 }
129 auto extent = maybeExtent.value();
130 uint32_t imageCount = surfaceCaps.minImageCount + 1;
131 if (surfaceCaps.maxImageCount != 0 &&
132 surfaceCaps.maxImageCount < imageCount) {
133 imageCount = surfaceCaps.maxImageCount;
134 }
135 VkSwapchainCreateInfoKHRPtr swapChainCi(
136 new VkSwapchainCreateInfoKHR{
137 .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
138 .surface = surface,
139 .minImageCount = imageCount,
140 .imageFormat = iSurfaceFormat->format,
141 .imageColorSpace = iSurfaceFormat->colorSpace,
142 .imageExtent = extent,
143 .imageArrayLayers = 1,
144 .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
145 .preTransform = surfaceCaps.currentTransform,
146 .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
147 .presentMode = *iPresentMode,
148 .clipped = VK_TRUE,
149 .oldSwapchain = VK_NULL_HANDLE},
150 [](VkSwapchainCreateInfoKHR *p) {
151 if (p->pQueueFamilyIndices != nullptr) {
152 delete[] p->pQueueFamilyIndices;
153 }
154 });
155 if (queueFamilyIndices.empty()) {
156 return nullptr;
157 }
158 if (queueFamilyIndices.size() == 1) {
159 swapChainCi->imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
160 swapChainCi->queueFamilyIndexCount = 0;
161 swapChainCi->pQueueFamilyIndices = nullptr;
162 } else {
163 swapChainCi->imageSharingMode = VK_SHARING_MODE_CONCURRENT;
164 swapChainCi->queueFamilyIndexCount =
165 static_cast<uint32_t>(queueFamilyIndices.size());
166 uint32_t *pQueueFamilyIndices = new uint32_t[queueFamilyIndices.size()];
167 std::copy(queueFamilyIndices.begin(), queueFamilyIndices.end(),
168 pQueueFamilyIndices);
169 swapChainCi->pQueueFamilyIndices = pQueueFamilyIndices;
170 }
171 return swapChainCi;
172 }
173
getFormat()174 VkFormat SwapChainStateVk::getFormat() { return k_vkFormat; }
175
getVkImages() const176 const std::vector<VkImage> &SwapChainStateVk::getVkImages() const {
177 return m_vkImages;
178 }
179
getVkImageViews() const180 const std::vector<VkImageView> &SwapChainStateVk::getVkImageViews() const {
181 return m_vkImageViews;
182 }
183
getSwapChain() const184 VkSwapchainKHR SwapChainStateVk::getSwapChain() const { return m_vkSwapChain; }