FCT
载入中...
搜索中...
未找到
VK_Swapchain.cpp
浏览该文件的文档.
1#include "../ThirdParty.h"
3#include "./VK_Swapchain.h"
4
5#include "./VK_Fence.h"
6#include "./Fence.h"
7#include "./Semaphore.h"
8#include "./Image.h"
9#include "./Pass.h"
11
12namespace FCT {
13 namespace RHI
14 {
16 m_ctx = ctx;
17 m_swapchain = nullptr;
18 m_fctImage = nullptr;
19 m_target = nullptr;
21 m_needRecreated = false;
22 m_depthStencilImage = nullptr;
23 m_recreatedFlag = false;
24 }
25
30 if (m_fctImages.size()) {
31 for (auto image : m_fctImages) {
32 image->release();
33 }
34 m_fctImages.clear();
35 }
36 }
37
39 auto phyDc = m_ctx->getPhysicalDevice();
40 auto dc = m_ctx->getDevice();
41 auto graphicsQueueFamily = m_ctx->getGraphicsQueueFamily();
42
43 m_presentQueueFamilyIndex = UINT32_MAX;
44
45 auto queueFamilyCount = phyDc.getQueueFamilyProperties().size();
46 for (uint32_t i = 0; i < queueFamilyCount; i++) {
47 if (phyDc.getSurfaceSupportKHR(i, m_surface)) {
49 break;
50 }
51 }
52
53 if (m_presentQueueFamilyIndex == UINT32_MAX) {
54 m_presentQueueFamilyIndex = graphicsQueueFamily;
55 }
56
57 m_presentQueues.clear();
58 m_presentQueues.push_back(dc.getQueue(m_presentQueueFamilyIndex, 0));
60 }
61 vk::SwapchainCreateInfoKHR VK_Swapchain::buildSwapchainCreateInfo(
62 const vk::SurfaceFormatKHR& format,
63 vk::PresentModeKHR presentMode,
64 const vk::Extent2D& extent,
65 uint32_t imageCount,
66 const vk::SurfaceCapabilitiesKHR& capabilities,
67 uint32_t graphicsQueueFamily) {
68
69 vk::SwapchainCreateInfoKHR createInfo{};
70 createInfo.setSurface(m_surface)
71 .setMinImageCount(imageCount)
72 .setImageFormat(format.format)
73 .setImageColorSpace(format.colorSpace)
74 .setImageExtent(extent)
75 .setCompositeAlpha(vk::CompositeAlphaFlagBitsKHR::eOpaque)
76 .setPreTransform(capabilities.currentTransform)
77 .setPresentMode(presentMode)
78 .setImageUsage(vk::ImageUsageFlagBits::eColorAttachment)
79 .setImageArrayLayers(1)
80 .setClipped(true);
81
82 uint32_t queueFamilyIndices[] = {graphicsQueueFamily, m_presentQueueFamilyIndex};
83 if (graphicsQueueFamily != m_presentQueueFamilyIndex) {
84 createInfo.setImageSharingMode(vk::SharingMode::eConcurrent)
85 .setQueueFamilyIndexCount(2)
86 .setPQueueFamilyIndices(queueFamilyIndices);
87 } else {
88 createInfo.setImageSharingMode(vk::SharingMode::eExclusive);
89 }
90
91 return createInfo;
92 }
93 void VK_Swapchain::createSwapchain(uint32_t width, uint32_t height) {
94 auto phyDc = m_ctx->getPhysicalDevice();
95 auto dc = m_ctx->getDevice();
96 auto graphicsQueueFamily = m_ctx->getGraphicsQueueFamily();
97
98 auto capabilities = phyDc.getSurfaceCapabilitiesKHR(m_surface);
99 auto formats = phyDc.getSurfaceFormatsKHR(m_surface);
100 auto presentModes = phyDc.getSurfacePresentModesKHR(m_surface);
101
102 auto format = chooseSwapSurfaceFormat(formats);
103 auto presentMode = chooseSwapPresentMode(presentModes);
104 m_imageFormat = format.format;
105
106 vk::Extent2D extent(
107 std::clamp(m_dstWidth, capabilities.minImageExtent.width, capabilities.maxImageExtent.width),
108 std::clamp(m_dstHeight, capabilities.minImageExtent.height, capabilities.maxImageExtent.height)
109 );
110
111 m_width = extent.width;
112 m_height = extent.height;
113
114
115 auto imageCount = std::clamp(3u, capabilities.minImageCount, capabilities.maxImageCount);
116 vk::SwapchainCreateInfoKHR createInfo = buildSwapchainCreateInfo(
117 format, presentMode, extent, imageCount, capabilities, graphicsQueueFamily
118 );
119
120 vk::SwapchainKHR oldSwapchain = m_swapchain;
121 if (oldSwapchain) {
122 createInfo.setOldSwapchain(oldSwapchain);
123 }
124
125 m_swapchain = dc.createSwapchainKHR(createInfo);
126 m_images = dc.getSwapchainImagesKHR(m_swapchain);
127
128 if (oldSwapchain) {
129 dc.destroySwapchainKHR(oldSwapchain);
130 }
131 }
133
134 for (auto image : m_images) {
135 auto ret = new VK_Image(m_ctx);
136 ret->samples(getSamples());
137 ret->format(getFormat());
138 ret->width(m_width);
139 ret->height(m_height);
140 ret->create(image);
141
142 m_fctImages.push_back(ret);
143 }
144 if (m_fctImage)
145 {
146 m_fctImage->create(m_fctImages);
147 } else
148 {
152 m_fctImage->create(m_fctImages);
153 }
154 if (m_target)
155 {
156
157 } else
158 {
160 m_target->renderTargetType(RenderTargetType::WindowTarget);
161 m_target->bindTarget(m_fctImage);
162 }
163
164 }
165
166 void VK_Swapchain::create(vk::SurfaceKHR surface, uint32_t width, uint32_t height) {
169 //dst size != real size
171 m_surface = surface;
175
178 }
179 }
180
182 {
183 create(*static_cast<vk::SurfaceKHR*>(m_nativeHandle),m_pendingWidth,m_pendingHeight);
184 }
185
187 const std::vector<vk::SurfaceFormatKHR> &availableFormats) {
188 for (const auto &availableFormat : availableFormats) {
189 if (availableFormat.format == vk::Format::eB8G8R8A8Unorm &&
190 availableFormat.colorSpace == vk::ColorSpaceKHR::eSrgbNonlinear) {
191 return availableFormat;
192 }
193 }
194 return availableFormats[0];
195 }
196
198 const std::vector<vk::PresentModeKHR> &availablePresentModes) {
199 for (const auto &availablePresentMode : availablePresentModes) {
200 if (availablePresentMode == vk::PresentModeKHR::eImmediate) {
201 return availablePresentMode;
202 }
203 }
204 return vk::PresentModeKHR::eFifo;
205 }
206
208
209 }
210
211
213 return m_currentImageIndex;
214 }
215
217 {
218 //reset all render finsh semaphores
219 auto dc = m_ctx->getDevice();
220 dc.waitIdle();
221 for (auto semaphore : m_renderFinshSemaphores)
222 {
223 semaphore->create();
224 }
225 create();
226 return acquireFirstImage();
227 }
228
230 {
232 while (m_recreatedFlag)
233 {
234 using namespace std::chrono;
235 auto now = high_resolution_clock::now();
236 auto timeSinceRequest = duration_cast<milliseconds>(
238 ).count();
239 while (timeSinceRequest < RECREATE_DEBOUNCE_MS || !m_pendingWidth || !m_pendingHeight)
240 {
241 now = high_resolution_clock::now();
242 timeSinceRequest = duration_cast<milliseconds>(
244 ).count();
245 std::this_thread::sleep_for(std::chrono::milliseconds(5));
246 }
247 if (doRecreate())
248 {
249 now = high_resolution_clock::now();
250 timeSinceRequest = duration_cast<milliseconds>(
252 ).count();
254 m_recreatedFlag = false;
255 }
257 }
259 {
262 this
263 });
264 }
265 }
266
268 {
269 auto dc = m_ctx->getDevice();
270
271 std::vector<vk::Semaphore> semaphores;
272 for (auto semaphore : m_renderFinshSemaphores)
273 {
274 semaphores.push_back(static_cast<VK_Semaphore*>(semaphore)->semaphore());
275 }
276 vk::PresentInfoKHR presentInfo{};
277 presentInfo.setWaitSemaphores(semaphores)
278 .setSwapchainCount(1)
279 .setPSwapchains(&m_swapchain)
280 .setPImageIndices(&m_currentImageIndex);
281
282 try {
283 auto result = m_presentQueues[m_ctx->currentSubmitFrameIndex() % m_presentQueues.size()].presentKHR(presentInfo);
284 if (result == vk::Result::eSuboptimalKHR) {
285 m_recreatedFlag = true;
286 for (auto fence : m_renderFinshFences)
287 {
288 fence->waitFor();
289 fence->reset();
290 }
291 return;
292 }
293 } catch (vk::OutOfDateKHRError& e) {
294 m_recreatedFlag = true;
295 for (auto fence : m_renderFinshFences)
296 {
297 fence->waitFor();
298 fence->reset();
299 }
300 return;
301 } catch (vk::SystemError& e)
302 {
303 ferr << "fetal error in VK_Swapchain::present()" << e.what() << std::endl;
304 return;
305 }
306 for (auto fence : m_renderFinshFences)
307 {
308 fence->waitFor();
309 fence->reset();
310 //fout << "nomarl reset fence" << std::endl;
311 }
312 try {
313 auto nextResult = dc.acquireNextImageKHR(
315 UINT64_MAX,
316 m_prensentFinshSemphore->semaphore(),
317 nullptr,
319 );
320
321 if (nextResult == vk::Result::eSuboptimalKHR) {
322 m_recreatedFlag = true;
323 return;
324 }
325 } catch (vk::OutOfDateKHRError& e) {
326 m_recreatedFlag = true;
327 return;
328 } catch (vk::SystemError& e) {
329 ferr << "fetal error in VK_Swapchain::present() - acquireNextImage" << e.what() << std::endl;
330 return;
331 }
332
333 m_fctImage->changeCurrentIndex(m_currentImageIndex);
335 {
336 m_depthStencilImage->changeCurrentIndex(m_currentImageIndex);
337 }
338 }
339
341 auto dc = m_ctx->getDevice();
342 VK_Fence* fence = nullptr;
343 try
344 {
346 {
347 m_prensentFinshSemphore->create();
348 auto nextResult = dc.acquireNextImageKHR(
350 UINT64_MAX,
351 m_prensentFinshSemphore->semaphore(),
352 nullptr,
354 );
355 if (nextResult == vk::Result::eSuboptimalKHR) {
356 return false;
357 }
358 } else
359 {
360 fence = new VK_Fence(m_ctx);
361 fence->create();
362 auto nextResult = dc.acquireNextImageKHR(
364 UINT64_MAX,
365 nullptr,
366 fence->fence(),
368 );
369 fence->waitFor();
370 fence->release();
371 if (nextResult == vk::Result::eSuboptimalKHR) {
372 return false;
373 }
374 }
375 } catch (vk::OutOfDateKHRError& e)
376 {
377 return false;
378 }
379 m_fctImage->changeCurrentIndex(m_currentImageIndex);
381 {
382 m_depthStencilImage->changeCurrentIndex(m_currentImageIndex);
383 }
384 return true;
385 }
386
388 {
389 m_lastRecreateRequestTime = std::chrono::high_resolution_clock::now();
390 m_recreatedFlag = true;
393 //m_needRecreated = true;
394 //m_recreated = false;
395 //FCT_WAIT_FOR(m_recreated);
396 }
397
398 bool VK_Swapchain::processRecreate(bool waitFence)
399 {
400 auto dc = m_ctx->getDevice();
401 if (m_needRecreated)
402 {
403 if (waitFence)
404 {
405 for (auto fence : m_renderFinshFences)
406 {
407 fence->waitFor();
408 fence->reset();
409 }
410 }
411 create();
412 m_needRecreated = false;
413 m_recreated = true;
414 return true;
415 }
416 return false;
417 }
418
419 vk::Extent2D VK_Swapchain::getExtent() const {
420 return m_extent;
421 }
422
427
429 {
430 return Samples::sample_1;
431 }
432
434 {
435 return m_target;
436 }
437
439 {
440 m_prensentFinshSemphore = static_cast<VK_Semaphore*>(semaphore);
441 }
442
447
452
453
455 {
456 m_depthStencilImage = m_ctx->createResource<MutilBufferImage>();
459 m_depthStencilImage->format(format);
462 m_depthStencilImage->imageCount(m_images.size());
463 m_depthStencilImage->create();
464 m_target->setDepthStencilBuffer(m_depthStencilImage);
465 }
466 }
467}
468
uint32_t width() const
uint32_t m_width
创建交换链后得到的实际大小
uint32_t m_dstHeight
目标大小
void * m_nativeHandle
交换链对应的surface
uint32_t m_height
创建交换链后得到的实际大小
uint32_t height() const
std::vector< RHI::Semaphore * > m_renderFinshSemaphores
uint32_t m_dstWidth
目标大小
std::vector< RHI::Fence * > m_renderFinshFences
void waitFor() override
void create() override
ImageRenderTarget * m_target
vk::PresentModeKHR chooseSwapPresentMode(const std::vector< vk::PresentModeKHR > &availablePresentModes)
Samples getSampleCount() const override
RHI::VK_Semaphore * m_prensentFinshSemphore
void setPresentFinshSemaphore(RHI::Semaphore *semaphore) override
FCT::Image * image() const override
vk::Extent2D getExtent() const
Samples getSamples() const override
vk::SurfaceFormatKHR chooseSwapSurfaceFormat(const std::vector< vk::SurfaceFormatKHR > &availableFormats)
static constexpr uint32_t RECREATE_DEBOUNCE_MS
uint32_t m_pendingWidth
窗口resize的时候传递的大小
void present() override
提交present命令
std::vector< RHI::Image * > m_fctImages
uint32_t getCurrentImageIndex() const
vk::SwapchainKHR m_swapchain
MutilBufferImage * m_depthStencilImage
std::chrono::high_resolution_clock::time_point m_lastRecreateRequestTime
std::vector< vk::Queue > m_presentQueues
void needRecreate(int width, int height) override
用于窗口通知需要 recreate
bool processRecreate(bool waitFence=false)
void createSwapchain(uint32_t width, uint32_t height)
std::vector< vk::Image > m_images
ImageRenderTarget * target() const override
获取交换链对应的target
RHI::Semaphore * getImageAvailableSemaphore() override
用于渲染命令同步的,获取到 图像,gpu可以执行渲染命令
void enableDepthBuffer(Format format) override
启用深度模板 缓存
Format getFormat() const override
vk::SwapchainCreateInfoKHR buildSwapchainCreateInfo(const vk::SurfaceFormatKHR &format, vk::PresentModeKHR presentMode, const vk::Extent2D &extent, uint32_t imageCount, const vk::SurfaceCapabilitiesKHR &capabilities, uint32_t graphicsQueueFamily)
MutilBufferImage * m_fctImage
std::ostream & ferr
Format FromVkFormat(vk::Format format)