Skip to content

Commit 3108d84

Browse files
fixed windows resizing crash
1 parent 19b60a9 commit 3108d84

9 files changed

Lines changed: 122 additions & 59 deletions

File tree

ZEngine/ZEngine/Applications/AppRenderPipeline.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ namespace ZEngine::Applications
5151
for (uint8_t thread_idx = 0; thread_idx < Device->CommandBufferMgr->TotalThreadCount; ++thread_idx)
5252
{
5353
Device->CommandBufferMgr->ResetPool(swapchain->CurrentFrame->Index, thread_idx);
54+
Device->AsyncResLoader->ResetCommandBuffers(swapchain->CurrentFrame->Index, thread_idx);
5455
}
5556

5657
Device->AsyncResLoader->CompleteDeferrals();
@@ -60,12 +61,18 @@ namespace ZEngine::Applications
6061
// {
6162
// auto thread_idx = render_worker_thread_idx + worker_thread_idx;
6263
// }
63-
CurrentCmdBuf = Device->CommandBufferMgr->GetCommandBuffer(Rendering::QueueType::GRAPHIC_QUEUE, swapchain->CurrentFrame->Index, RenderMainThreadIndex, 0, true);
64+
CurrentCmdBuf = Device->CommandBufferMgr->GetCommandBuffer(Rendering::QueueType::GRAPHIC_QUEUE, swapchain->CurrentFrame->Index, RenderMainThreadIndex, 0, false);
65+
vkResetCommandBuffer(CurrentCmdBuf->GetHandle(), 0);
66+
CurrentCmdBuf->ResetState();
67+
CurrentCmdBuf->Begin();
6468
}
6569

6670
void AppRenderPipeline::EndFrame()
6771
{
72+
Device->AsyncResLoader->SubmitAsyncJobs();
6873
Device->CommandBufferMgr->EnqueueBuffer(CurrentCmdBuf);
74+
Device->CommandBufferMgr->EndEnqueuedBuffers();
75+
6976
Device->SwapchainPtr->Present();
7077
}
7178

ZEngine/ZEngine/Applications/AppRenderPipeline.h

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,15 @@
22
#include <Hardwares/VulkanDevice.h>
33
#include <Rendering/Renderers/GraphicRenderer.h>
44
#include <Rendering/Renderers/ImGUIRenderer.h>
5-
#include <new>
65

76
namespace ZEngine::Applications
87
{
9-
#ifdef __cpp_lib_hardware_interference_size
10-
constexpr auto CACHE_LINE_SIZE = std::hardware_destructive_interference_size;
11-
#else
12-
constexpr auto CACHE_LINE_SIZE = 64;
13-
#endif
14-
15-
struct alignas(CACHE_LINE_SIZE) PaddedAtomicInt
16-
{
17-
std::atomic_uint32_t value = 0;
18-
};
19-
208
struct RenderPayload
219
{
22-
bool RenderUIOverlay = false;
23-
bool ResizeRenderTarget = false;
2410
uint32_t RenderTargetW = 0;
2511
uint32_t RenderTargetH = 0;
12+
PaddedAtomic<bool> RenderUIOverlay = {.value = false};
13+
PaddedAtomic<bool> ResizeRenderTarget = {.value = false};
2614
Rendering::Cameras::CameraPtr Camera = nullptr;
2715
Rendering::Scenes::RenderScenePtr Scene = nullptr;
2816
Rendering::Renderers::RenderOverlayPayload UIOverlay = {};
@@ -35,8 +23,8 @@ namespace ZEngine::Applications
3523
uint8_t RenderWorkerThreadCount = 0;
3624
uint8_t UICommandBufferIndex = 0xff;
3725
uint32_t CurrentMailBoxBufferHead = 0;
38-
PaddedAtomicInt MailBoxBufferHead = {};
39-
PaddedAtomicInt MailBoxBufferTail = {};
26+
PaddedAtomic<int> MailBoxBufferHead = {.value = 0};
27+
PaddedAtomic<int> MailBoxBufferTail = {.value = 0};
4028
RenderPayload RenderPayloads[3] = {};
4129
ZEngine::Core::Memory::ArenaAllocator LocalArena = {};
4230
Hardwares::VulkanDevicePtr Device = nullptr;

ZEngine/ZEngine/Applications/GameApplication.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,9 @@ namespace ZEngine::Applications
5252
RenderTargetResizeRequest request = {};
5353
if (State->RenderTargetResizeRequests.Pop(request))
5454
{
55-
payload.ResizeRenderTarget = true;
56-
payload.RenderTargetW = request.Width;
57-
payload.RenderTargetH = request.Height;
55+
payload.ResizeRenderTarget.value.store(true, std::memory_order_release);
56+
payload.RenderTargetW = request.Width;
57+
payload.RenderTargetH = request.Height;
5858
}
5959

6060
payload.Scene = CurrentScene;

ZEngine/ZEngine/Engine.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -110,15 +110,15 @@ namespace ZEngine
110110

111111
auto& r_payload = pipeline->RenderPayloads[head];
112112
r_payload.UIOverlay.DrawDataIndex = 0;
113-
r_payload.RenderUIOverlay = false;
113+
r_payload.RenderUIOverlay.value.store(false, std::memory_order_release);
114114

115115
if (g_app->EnableRenderOverlay)
116116
{
117117
pipeline->BeginOverlayFrame();
118118
g_app->OnRenderUI();
119119
pipeline->EndOverlayFrame();
120120

121-
r_payload.RenderUIOverlay = true;
121+
r_payload.RenderUIOverlay.value.store(true, std::memory_order_release);
122122
pipeline->FillOverlayPayload(r_payload.UIOverlay);
123123
}
124124

@@ -163,15 +163,15 @@ namespace ZEngine
163163
pipeline->CurrentMailBoxBufferHead = tail;
164164
Applications::RenderPayload& r_payload = pipeline->RenderPayloads[tail];
165165

166-
if (r_payload.ResizeRenderTarget)
166+
if (r_payload.ResizeRenderTarget.value.load(std::memory_order_acquire))
167167
{
168168
pipeline->ResizeRenderTarget(r_payload.RenderTargetW, r_payload.RenderTargetH);
169-
r_payload.ResizeRenderTarget = false;
169+
r_payload.ResizeRenderTarget.value.store(false, std::memory_order_release);
170170
}
171171

172172
pipeline->BeginFrame();
173173
pipeline->RenderScene(r_payload.Camera, r_payload.Scene);
174-
if (r_payload.RenderUIOverlay)
174+
if (r_payload.RenderUIOverlay.value.load(std::memory_order_acquire))
175175
{
176176
pipeline->RenderOverlay(r_payload.UIOverlay);
177177
}

ZEngine/ZEngine/Hardwares/AsyncResourceLoader.cpp

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,17 @@ namespace ZEngine::Hardwares
2525

2626
void AsyncResourceLoader::Initialize(VulkanDevice* device)
2727
{
28-
Device = device;
29-
auto max_buffers = Device->CommandBufferMgr->MaxBufferPerPool * Device->CommandBufferMgr->MaxBufferPerPool;
28+
Device = device;
29+
TotalCommandBufferCount = Device->CommandBufferMgr->MaxBufferPerPool * Device->CommandBufferMgr->MaxBufferPerPool;
30+
3031
Timelines.init(Device->Arena, Device->CommandBufferMgr->TotalPoolCount, Device->CommandBufferMgr->TotalPoolCount);
3132
NextValues.init(Device->Arena, Device->CommandBufferMgr->TotalPoolCount, Device->CommandBufferMgr->TotalPoolCount);
3233
RetireValues.init(Device->Arena, Device->CommandBufferMgr->TotalPoolCount, Device->CommandBufferMgr->TotalPoolCount);
3334

3435
for (uint32_t i = 0; i < Device->CommandBufferMgr->TotalPoolCount; ++i)
3536
{
3637
Timelines[i] = ZPushStructCtorArgs(Device->Arena, Rendering::Primitives::Semaphore, Device, true);
37-
RetireValues[i].init(Device->Arena, max_buffers, max_buffers);
38+
RetireValues[i].init(Device->Arena, TotalCommandBufferCount, TotalCommandBufferCount);
3839
NextValues[i].store(1, std::memory_order_release);
3940
}
4041

@@ -47,7 +48,7 @@ namespace ZEngine::Hardwares
4748
for (uint32_t i = 0; i < Device->CommandBufferMgr->TotalPoolCount; ++i)
4849
{
4950
TransferTimelines[i] = ZPushStructCtorArgs(Device->Arena, Rendering::Primitives::Semaphore, Device, true);
50-
TransferRetireValues[i].init(Device->Arena, max_buffers, max_buffers);
51+
TransferRetireValues[i].init(Device->Arena, TotalCommandBufferCount, TotalCommandBufferCount);
5152
TransferNextValues[i].store(1, std::memory_order_release);
5253
}
5354
}
@@ -524,10 +525,9 @@ namespace ZEngine::Hardwares
524525
void AsyncResourceLoader::ResetCommandBuffers(uint8_t frame_index, uint8_t thread_index)
525526
{
526527
uint32_t pool_index = (frame_index * Device->CommandBufferMgr->TotalThreadCount) + thread_index;
527-
auto& retire_values = RetireValues[pool_index];
528528

529-
// Check graphics timeline
530529
uint64_t graphics_value = 0;
530+
auto& retire_values = RetireValues[pool_index];
531531
vkGetSemaphoreCounterValue(Device->LogicalDevice, Timelines[pool_index]->GetHandle(), &graphics_value);
532532

533533
for (int i = 0; i < retire_values.size(); ++i)
@@ -724,4 +724,31 @@ namespace ZEngine::Hardwares
724724
// We are safe to call destructor to clean up semaphore resources
725725
// Timeline->~Semaphore();
726726
}
727+
728+
void AsyncResourceLoader::Reset()
729+
{
730+
auto total_thread_count = Device->CommandBufferMgr->TotalThreadCount;
731+
auto frame_count = Device->SwapchainPtr->BufferredFrameCount;
732+
733+
for (uint32_t f = 0; f < frame_count; ++f)
734+
{
735+
for (uint32_t t = 0; t < total_thread_count; ++t)
736+
{
737+
ResetCommandBuffers(f, t);
738+
739+
uint32_t pool_index = (f * Device->CommandBufferMgr->TotalThreadCount) + t;
740+
741+
uint64_t grahic_value = 0;
742+
vkGetSemaphoreCounterValue(Device->LogicalDevice, Timelines[pool_index]->GetHandle(), &grahic_value);
743+
NextValues[pool_index].store(grahic_value + 1, std::memory_order_release);
744+
745+
if (Device->HasSeperateTransfertQueueFamily)
746+
{
747+
uint64_t transfer_value = 0;
748+
vkGetSemaphoreCounterValue(Device->LogicalDevice, TransferTimelines[pool_index]->GetHandle(), &transfer_value);
749+
TransferNextValues[pool_index].store(transfer_value + 1, std::memory_order_release);
750+
}
751+
}
752+
}
753+
}
727754
} // namespace ZEngine::Hardwares

ZEngine/ZEngine/Hardwares/AsyncResourceLoader.h

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -84,16 +84,16 @@ namespace ZEngine::Hardwares
8484
Rendering::Textures::TextureHandle TexHandle = {};
8585
};
8686

87-
VulkanDevice* Device = nullptr;
88-
89-
Core::Containers::Array<std::atomic_uint64_t> NextValues = {};
90-
Core::Containers::Array<std::atomic_uint64_t> TransferNextValues = {};
91-
Core::Containers::Array<Rendering::Primitives::Semaphore*> Timelines = {};
92-
Core::Containers::Array<Rendering::Primitives::Semaphore*> TransferTimelines = {};
93-
Core::Containers::Array<Core::Containers::Array<uint64_t>> RetireValues = {};
94-
Core::Containers::Array<Core::Containers::Array<uint64_t>> TransferRetireValues = {};
95-
Helpers::ThreadSafeQueue<TimelineJob> AsyncTimelineJobQueue = {};
96-
Helpers::ThreadSafeQueue<DeferralUpload> DeferralUploadQueue = {};
87+
VulkanDevice* Device = nullptr;
88+
uint32_t TotalCommandBufferCount = 0;
89+
Core::Containers::Array<std::atomic_uint64_t> NextValues = {};
90+
Core::Containers::Array<std::atomic_uint64_t> TransferNextValues = {};
91+
Core::Containers::Array<Rendering::Primitives::Semaphore*> Timelines = {};
92+
Core::Containers::Array<Rendering::Primitives::Semaphore*> TransferTimelines = {};
93+
Core::Containers::Array<Core::Containers::Array<uint64_t>> RetireValues = {};
94+
Core::Containers::Array<Core::Containers::Array<uint64_t>> TransferRetireValues = {};
95+
Helpers::ThreadSafeQueue<TimelineJob> AsyncTimelineJobQueue = {};
96+
Helpers::ThreadSafeQueue<DeferralUpload> DeferralUploadQueue = {};
9797

9898
void Initialize(VulkanDevice* device);
9999

@@ -110,10 +110,11 @@ namespace ZEngine::Hardwares
110110
void CompleteDeferrals();
111111
void SubmitAsyncJobs();
112112
void ResetCommandBuffers(uint8_t frame_index, uint8_t thread_index);
113-
void ClearAsyncJobs();
113+
void ClearAsyncJobs();
114114

115115
void Run();
116116
void Shutdown();
117+
void Reset();
117118

118119
private:
119120
std::atomic_bool m_cancellation_token{false};

ZEngine/ZEngine/Hardwares/DeviceSwapchain.cpp

Lines changed: 41 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,12 @@ namespace ZEngine::Hardwares
5050

5151
ImageInFlights.init(&Arena, SwapchainImageCount, SwapchainImageCount);
5252
RenderCompletes.init(&Arena, SwapchainImageCount, SwapchainImageCount);
53+
PresentCompletes.init(&Arena, SwapchainImageCount, SwapchainImageCount);
5354
for (uint32_t i = 0; i < SwapchainImageCount; ++i)
5455
{
55-
ImageInFlights[i] = nullptr;
56-
RenderCompletes[i] = ZPushStructCtorArgs(&Arena, Primitives::Semaphore, Device);
56+
ImageInFlights[i] = nullptr;
57+
RenderCompletes[i] = ZPushStructCtorArgs(&Arena, Primitives::Semaphore, Device);
58+
PresentCompletes[i] = ZPushStructCtorArgs(&Arena, Primitives::Fence, Device);
5759
}
5860
}
5961

@@ -67,6 +69,7 @@ namespace ZEngine::Hardwares
6769
SwapchainImageHeight = capabilities.currentExtent.height;
6870
}
6971

72+
VkSwapchainKHR old_swapchain = (SwapchainHandle != VK_NULL_HANDLE) ? SwapchainHandle : VK_NULL_HANDLE;
7073
auto min_image_count = std::clamp(capabilities.minImageCount, capabilities.minImageCount, capabilities.maxImageCount == 0 ? capabilities.minImageCount + 1 : capabilities.maxImageCount);
7174
VkSwapchainCreateInfoKHR swapchain_create_info = {
7275
.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
@@ -82,7 +85,7 @@ namespace ZEngine::Hardwares
8285
.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
8386
.presentMode = Device->PresentMode,
8487
.clipped = VK_TRUE,
85-
.oldSwapchain = (SwapchainHandle != VK_NULL_HANDLE) ? SwapchainHandle : VK_NULL_HANDLE
88+
.oldSwapchain = old_swapchain,
8689
};
8790

8891
auto scratch = ZGetScratch(&Arena);
@@ -129,6 +132,11 @@ namespace ZEngine::Hardwares
129132
}
130133

131134
ZReleaseScratch(scratch);
135+
136+
if (old_swapchain != VK_NULL_HANDLE)
137+
{
138+
ZENGINE_DESTROY_VULKAN_HANDLE(Device->LogicalDevice, vkDestroySwapchainKHR, old_swapchain, nullptr)
139+
}
132140
}
133141

134142
void DeviceSwapchain::Clear()
@@ -183,13 +191,23 @@ namespace ZEngine::Hardwares
183191
}
184192
}
185193

194+
for (uint32_t i = 0; i < PresentCompletes.size(); ++i)
195+
{
196+
if (PresentCompletes[i]->GetState() == Rendering::Primitives::FenceState::Submitted)
197+
{
198+
PresentCompletes[i]->Wait(UINT64_MAX);
199+
PresentCompletes[i]->Reset();
200+
}
201+
}
202+
186203
for (int i = 0; i < FrameContextPoolSizeFactor; ++i)
187204
{
188205
FrameContext& frame = FrameContexts[i + FrameContextOffset];
189206
frame.Acquired->SetState(Primitives::SemaphoreState::Idle);
190207
}
191208

192209
Device->AsyncResLoader->ClearAsyncJobs();
210+
Device->AsyncResLoader->Reset();
193211

194212
uint64_t timeline_value = 0;
195213
vkGetSemaphoreCounterValue(Device->LogicalDevice, RenderTimeline->GetHandle(), &timeline_value);
@@ -198,7 +216,9 @@ namespace ZEngine::Hardwares
198216
ZENGINE_VALIDATE_ASSERT(timeline_value < UINT64_MAX, "Render Timeline value is corrupted, this should never happen.")
199217
RenderTimelineNextValue = timeline_value;
200218

201-
FrameContextOffset = (FrameContextOffset + FrameContextPoolSizeFactor) % FrameContextPoolSize;
219+
FrameContextOffset = (FrameContextOffset + FrameContextPoolSizeFactor) % FrameContextPoolSize;
220+
// CurrentFrame = nullptr;
221+
202222
Clear();
203223
Create();
204224

@@ -207,17 +227,22 @@ namespace ZEngine::Hardwares
207227
}
208228

209229
FrameContext& frame = FrameContexts[frame_context_idx + FrameContextOffset];
210-
230+
if (frame.Fence->GetState() == Rendering::Primitives::FenceState::Submitted)
231+
{
232+
frame.Fence->Wait(UINT64_MAX);
233+
}
211234
frame.Fence->Reset();
212235
frame.Acquired->SetState(Rendering::Primitives::SemaphoreState::Idle);
213-
Device->AsyncResLoader->ResetCommandBuffers(frame.Index, 0);
214-
215-
ZENGINE_VALIDATE_ASSERT(frame.Acquired->GetState() != Primitives::SemaphoreState::Submitted, "")
216236

217237
uint32_t image_idx = 0;
218238
VkResult acquire_image_result = vkAcquireNextImageKHR(Device->LogicalDevice, SwapchainHandle, UINT64_MAX, frame.Acquired->GetHandle(), VK_NULL_HANDLE, &(image_idx));
219239
frame.Acquired->SetState(Primitives::SemaphoreState::Submitted);
220-
RenderCompletes[image_idx]->SetState(Rendering::Primitives::SemaphoreState::Idle);
240+
241+
if (PresentCompletes[image_idx]->GetState() == Rendering::Primitives::FenceState::Submitted)
242+
{
243+
PresentCompletes[image_idx]->Wait(UINT64_MAX);
244+
PresentCompletes[image_idx]->Reset();
245+
}
221246

222247
if (ImageInFlights[image_idx] != nullptr)
223248
{
@@ -226,6 +251,7 @@ namespace ZEngine::Hardwares
226251
ImageInFlights[image_idx]->Wait(UINT64_MAX);
227252
}
228253
}
254+
RenderCompletes[image_idx]->SetState(Rendering::Primitives::SemaphoreState::Idle);
229255

230256
ImageInFlights[image_idx] = frame.Fence;
231257
frame.ImageIndex = image_idx;
@@ -243,7 +269,6 @@ namespace ZEngine::Hardwares
243269
if (HasRecreationPending)
244270
{
245271
IdleFrameCount.fetch_add(1);
246-
Device->CommandBufferMgr->EndEnqueuedBuffers();
247272
Device->CommandBufferMgr->ResetEnqueuedBufferIndex();
248273
return;
249274
}
@@ -302,9 +327,6 @@ namespace ZEngine::Hardwares
302327
}
303328
}
304329

305-
Device->CommandBufferMgr->EndEnqueuedBuffers();
306-
Device->AsyncResLoader->SubmitAsyncJobs();
307-
308330
auto scratch = ZGetScratch(&Arena);
309331

310332
Array<VkCommandBuffer> buffer = {};
@@ -314,7 +336,8 @@ namespace ZEngine::Hardwares
314336
buffer[i] = Device->CommandBufferMgr->EnqueuedCommandBuffers[i]->GetHandle();
315337
}
316338

317-
auto render_complete = RenderCompletes[CurrentFrame->ImageIndex];
339+
auto render_complete = RenderCompletes[CurrentFrame->ImageIndex];
340+
auto present_complete = PresentCompletes[CurrentFrame->ImageIndex];
318341

319342
ZENGINE_VALIDATE_ASSERT(render_complete->GetState() != Rendering::Primitives::SemaphoreState::Submitted, "Signal semaphore is already in a signaled state.")
320343
ZENGINE_VALIDATE_ASSERT(CurrentFrame->Fence->GetState() != Rendering::Primitives::FenceState::Submitted, "Signal fence is already in a signaled state.")
@@ -450,9 +473,12 @@ namespace ZEngine::Hardwares
450473
.pSignalSemaphores = present_signal_semaphores,
451474
};
452475

453-
VkResult r2 = vkQueueSubmit(queue.Handle, 1, &submit2, VK_NULL_HANDLE);
476+
VkResult r2 = vkQueueSubmit(queue.Handle, 1, &submit2, present_complete->GetHandle());
454477
ZENGINE_VALIDATE_ASSERT(r2 == VK_SUCCESS, "Failed to submit present bridge")
455478

479+
render_complete->SetState(Rendering::Primitives::SemaphoreState::Submitted);
480+
present_complete->SetState(Rendering::Primitives::FenceState::Submitted);
481+
456482
VkSwapchainKHR swapchains[] = {SwapchainHandle};
457483
uint32_t frames[] = {CurrentFrame->ImageIndex};
458484
VkSemaphore semaphores[] = {render_complete->GetHandle()};
@@ -466,7 +492,6 @@ namespace ZEngine::Hardwares
466492
.pImageIndices = frames,
467493
};
468494
VkResult present_result = vkQueuePresentKHR(queue.Handle, &present_info);
469-
render_complete->SetState(Rendering::Primitives::SemaphoreState::Submitted);
470495

471496
IdleFrameCount.fetch_add(1);
472497

0 commit comments

Comments
 (0)