• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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; }