Skip to content

Commit 8ba6f93

Browse files
authored
Merge pull request #17 from CapsCollective/feature/swapchain-vulkan-separation
Refactored swapchain class to be more readable
2 parents 5580eb0 + 4007a2b commit 8ba6f93

36 files changed

+1658
-883
lines changed

README.md

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ If you want to build with validation layers then the setup scripts should be run
100100

101101
```console
102102
// Linux & macOS
103-
$ ./scripts/install.sh --include-validation-layers
103+
$ ./scripts/setup.sh --include-validation-layers
104104
```
105105
```console
106106
// Windows
@@ -111,7 +111,7 @@ $ ./scripts/install.sh --include-validation-layers
111111

112112
### Building the Project
113113

114-
Assuming all dependencies have been satisfied, the project can be build and run using the following command:
114+
Assuming all dependencies have been satisfied, the project can be build using the following command:
115115

116116
```console
117117
// Linux and macOS
@@ -128,9 +128,7 @@ $ make CXXFLAGS="-DENABLE_VALIDATION_LAYERS=1"
128128
> mingw32-make CXXFLAGS="-DENABLE_VALIDATION_LAYERS=1"
129129
```
130130

131-
These commands should build the project and immediately run executable.
132-
133-
Once these are done the project should be built and ready to go. Enjoy!
131+
Once it completes, all targets should be built and ready to run from the newly generated `output` directory.
134132

135133
### Working With Siege
136134

engine/render/renderer/Renderer.cpp

Lines changed: 35 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
#include "Renderer.h"
1212

13+
#include "platform/vulkan/utils/Types.h"
14+
1315
namespace Siege
1416
{
1517
Renderer* Renderer::instance {nullptr};
@@ -19,9 +21,11 @@ Renderer::Renderer(Window& window) : window {window}
1921
{
2022
if (instance == nullptr) instance = this;
2123

22-
context.Init(Window::GetRequiredExtensions, Window::CreateWindowSurface);
24+
auto extent = window.GetExtent();
2325

24-
swapChain.SetWindowExtents(window.GetExtent());
26+
context.Init({extent.width, extent.height},
27+
Window::GetRequiredExtensions,
28+
Window::CreateWindowSurface);
2529

2630
DescriptorPool::AddPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 10);
2731
DescriptorPool::AddPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 10);
@@ -45,7 +49,7 @@ Renderer::~Renderer()
4549

4650
void Renderer::CreateCommandBuffers()
4751
{
48-
commandBuffers = Utils::MHArray<VkCommandBuffer>(SwapChain::MAX_FRAMES_IN_FLIGHT);
52+
commandBuffers = Utils::MHArray<VkCommandBuffer>(Vulkan::Swapchain::MAX_FRAMES_IN_FLIGHT);
4953

5054
VkCommandBufferAllocateInfo allocInfo {};
5155
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
@@ -79,15 +83,16 @@ void Renderer::RecreateSwapChain()
7983
window.WaitEvents();
8084
}
8185

82-
auto oldImageFormat = swapChain.GetImageFormat();
83-
auto oldDepthFormat = swapChain.GetDepthFormat();
86+
auto& swapchain = context.GetSwapchain();
87+
88+
auto oldImageFormat = swapchain.GetImageFormat();
89+
auto oldDepthFormat = swapchain.GetDepthFormat();
8490

85-
// Re-create swapchain
86-
swapChain.RecreateSwapchain();
91+
context.RecreateSwapchain({extent.width, extent.height});
8792

8893
// Re-create the pipeline once the swapchain renderpass
8994
// becomes available again.
90-
if (!swapChain.CompareSwapFormats(oldImageFormat, oldDepthFormat))
95+
if (!swapchain.IsSameSwapFormat(oldImageFormat, oldDepthFormat))
9196
{
9297
Renderer3D::RecreateMaterials();
9398
Renderer2D::RecreateMaterials();
@@ -98,15 +103,17 @@ bool Renderer::StartFrame()
98103
{
99104
CC_ASSERT(!isFrameStarted, "Can't start a frame when a frame is already in progress!");
100105

101-
auto result = swapChain.AcquireNextImage(&currentImageIndex);
106+
auto& swapchain = context.GetSwapchain();
102107

103-
if (result == VK_ERROR_OUT_OF_DATE_KHR)
108+
auto result = swapchain.AcquireNextImage(&currentImageIndex);
109+
110+
if (result == Vulkan::Utils::ERROR_OUT_OF_DATE)
104111
{
105112
RecreateSwapChain();
106113
return false;
107114
}
108115

109-
CC_ASSERT(result == VK_SUCCESS || result == VK_SUBOPTIMAL_KHR,
116+
CC_ASSERT(result == Vulkan::Utils::SUCCESS || result == Vulkan::Utils::SUBOPTIMAL,
110117
"Failed to acquire swapchain image!");
111118

112119
isFrameStarted = true;
@@ -126,7 +133,9 @@ bool Renderer::StartFrame()
126133

127134
void Renderer::EndFrame()
128135
{
129-
CC_ASSERT(isFrameStarted, "Can't end frame while frame is not in progress!");
136+
CC_ASSERT(isFrameStarted, "Can't end frame while frame is not in progress!")
137+
138+
auto& swapchain = context.GetSwapchain();
130139

131140
DrawFrame();
132141

@@ -137,63 +146,54 @@ void Renderer::EndFrame()
137146
CC_ASSERT(vkEndCommandBuffer(OUT commandBuffer) == VK_SUCCESS,
138147
"Failed to record command buffer!");
139148

140-
auto result = swapChain.SubmitCommandBuffers(&commandBuffer, &currentImageIndex);
149+
auto result = swapchain.SubmitCommandBuffers(&commandBuffer, &currentImageIndex);
141150

142-
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || window.WasResized())
151+
if (result == Vulkan::Utils::ERROR_RESIZED || window.WasResized())
143152
{
144153
window.ResetWindowResized();
145154
RecreateSwapChain();
146155
}
147-
else if (result != VK_SUCCESS)
148-
{
149-
CC_ASSERT(result == VK_SUCCESS, "Failed to submit command buffer for drawing!");
150-
}
151156

152157
isFrameStarted = false;
153-
currentFrameIndex = (currentFrameIndex + 1) % SwapChain::MAX_FRAMES_IN_FLIGHT;
158+
currentFrameIndex = (currentFrameIndex + 1) % Vulkan::Swapchain::MAX_FRAMES_IN_FLIGHT;
154159

155160
Renderer3D::Flush();
156161
Renderer2D::Flush();
157162
}
158163

159164
void Renderer::BeginSwapChainRenderPass(VkCommandBuffer commandBuffer)
160165
{
166+
auto& swapchain = context.GetSwapchain();
167+
161168
CC_ASSERT(isFrameStarted, "Can't start render pass while the frame hasn't started!");
162169
CC_ASSERT(commandBuffer == GetCurrentCommandBuffer(),
163170
"Can't begin a render pass on a command buffer from another frame!");
164171

165-
uint32_t clearValueCount = 2;
166-
VkClearValue clearValues[clearValueCount];
167-
clearValues[0].color = clearValue;
168-
clearValues[1].depthStencil = {1.0f, 0};
172+
auto swapExtent = swapchain.GetExtent();
169173

170-
RenderPass::Begin(swapChain.GetRenderPass()->GetRenderPass(),
171-
OUT commandBuffer,
172-
swapChain.GetFrameBuffer(currentImageIndex),
173-
{0, 0},
174-
swapChain.GetSwapChainExtent(),
175-
clearValues,
176-
clearValueCount);
174+
swapchain.BeginRenderPass(OUT commandBuffer, currentImageIndex, {{clearValue}, {{{1.f, 0.f}}}});
177175

178176
VkViewport viewport {};
179177
viewport.x = 0.0f;
180178
viewport.y = 0.0f;
181-
viewport.width = static_cast<float>(swapChain.GetSwapChainExtent().width);
182-
viewport.height = static_cast<float>(swapChain.GetSwapChainExtent().height);
179+
viewport.width = static_cast<float>(swapExtent.width);
180+
viewport.height = static_cast<float>(swapExtent.height);
183181
viewport.minDepth = 0.0f;
184182
viewport.maxDepth = 1.0f;
185-
VkRect2D scissor {{0, 0}, swapChain.GetSwapChainExtent()};
183+
VkRect2D scissor {{0, 0}, {swapExtent.width, swapExtent.height}};
186184

187185
vkCmdSetViewport(commandBuffer, 0, 1, &viewport);
188186
vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
189187
}
190188

191189
void Renderer::EndSwapChainRenderPass(VkCommandBuffer commandBuffer)
192190
{
191+
auto& swapchain = context.GetSwapchain();
192+
193193
CC_ASSERT(isFrameStarted, "Can't end render pass while the frame hasn't started!");
194194
CC_ASSERT(commandBuffer == GetCurrentCommandBuffer(),
195-
"Can't begin a render pass on a command buffer from another frame!");
195+
"Can't end a render pass on a command buffer from another frame!");
196196

197-
RenderPass::End(commandBuffer);
197+
swapchain.EndRenderPass(commandBuffer);
198198
}
199199
} // namespace Siege

engine/render/renderer/Renderer.h

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
#include "render/window/Window.h"
2121
#include "renderer/Renderer2D.h"
2222
#include "renderer/Renderer3D.h"
23-
#include "swapchain/Swapchain.h"
2423

2524
namespace Siege
2625
{
@@ -32,16 +31,6 @@ class Renderer
3231

3332
~Renderer();
3433

35-
SwapChain& GetSwapChain()
36-
{
37-
return swapChain;
38-
}
39-
40-
VkRenderPass GetSwapChanRenderPass()
41-
{
42-
return swapChain.GetRenderPass()->GetRenderPass();
43-
}
44-
4534
int GetCurrentFrameIndex() const
4635
{
4736
CC_ASSERT(!isFrameStarted, "Can't get frame index when frame is not in progress!");
@@ -50,19 +39,14 @@ class Renderer
5039

5140
float GetAspectRatio() const
5241
{
53-
return swapChain.ExtentAspectRatio();
42+
return static_cast<float>(window.GetWidth()) / static_cast<float>(window.GetHeight());
5443
}
5544

5645
void SetProjection(const Mat4& projectionMat, const Mat4& viewMat)
5746
{
5847
projection = {projectionMat, viewMat};
5948
}
6049

61-
bool IsFrameStarted() const
62-
{
63-
return isFrameStarted;
64-
}
65-
6650
VkCommandBuffer GetCurrentCommandBuffer() const
6751
{
6852
CC_ASSERT(isFrameStarted, "Can't get command buffer when frame is not in progress!")
@@ -113,8 +97,6 @@ class Renderer
11397

11498
Window& window;
11599

116-
SwapChain swapChain;
117-
118100
uint32_t currentImageIndex;
119101
bool isFrameStarted {false};
120102
int currentFrameIndex {0};
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
//
2+
// Created by Aryeh Zinn on 29/9/2022.
3+
//
4+
5+
#include "Renderer3D.h"
6+
7+
namespace Siege
8+
{} // namespace Siege
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//
2+
// Created by Aryeh Zinn on 29/9/2022.
3+
//
4+
5+
#ifndef SIEGE_ENGINE_RENDERER3D_H
6+
#define SIEGE_ENGINE_RENDERER3D_H
7+
8+
namespace Siege
9+
{
10+
11+
class Renderer3D
12+
{};
13+
14+
} // namespace Siege
15+
16+
#endif // SIEGE_ENGINE_RENDERER3D_H

engine/render/renderer/material/Material.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
#include <utils/Logging.h>
1212

1313
#include "../mesh/Mesh.h"
14-
#include "../swapchain/Swapchain.h"
1514
#include "render/renderer/platform/vulkan/Context.h"
1615
#include "render/renderer/platform/vulkan/utils/Descriptor.h"
1716

@@ -127,7 +126,7 @@ void Material::CreatePipeline()
127126
pipelineConfig.rasterizationInfo.polygonMode = (VkPolygonMode) shaderSettings.mode;
128127
pipelineConfig.inputAssemblyInfo.topology = (VkPrimitiveTopology) shaderSettings.topology;
129128

130-
pipelineConfig.renderPass = SwapChain::GetInstance()->GetRenderPass()->GetRenderPass();
129+
pipelineConfig.renderPass = Vulkan::Context::GetSwapchain().GetRenderPass()->GetRenderPass();
131130
pipelineConfig.pipelineLayout = pipelineLayout;
132131

133132
pipelineConfig.vertexData =

engine/render/renderer/pass/RenderPass.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,20 @@ RenderPass::~RenderPass()
2222

2323
void RenderPass::DestroyRenderPass()
2424
{
25-
vkDestroyRenderPass(Vulkan::Context::GetVkLogicalDevice(), renderPass, nullptr);
25+
auto device = Vulkan::Context::GetVkLogicalDevice();
26+
if (device)
27+
{
28+
vkDestroyRenderPass(device, renderPass, nullptr);
29+
renderPass = VK_NULL_HANDLE;
30+
}
2631
}
2732

2833
void RenderPass::Begin(VkRenderPass renderPass,
2934
VkCommandBuffer commandBuffer,
3035
VkFramebuffer frameBuffer,
3136
VkOffset2D offset,
3237
VkExtent2D extent,
33-
VkClearValue* clearValues,
38+
const VkClearValue* clearValues,
3439
uint32_t clearValueCount)
3540
{
3641
VkRenderPassBeginInfo renderPassInfo {};

engine/render/renderer/pass/RenderPass.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,11 @@ class RenderPass
144144
Initialise(config);
145145
}
146146

147+
inline RenderPass(RenderPass&& other)
148+
{
149+
Swap(other);
150+
}
151+
147152
/**
148153
* @brief Initialises the RenderPass. Creating a RenderPass requires us to explicitly state what
149154
* operations the RenderPass will be responsible for, along with any graphics stages the
@@ -190,7 +195,7 @@ class RenderPass
190195
VkFramebuffer frameBuffer,
191196
VkOffset2D offset,
192197
VkExtent2D extent,
193-
VkClearValue* clearValues,
198+
const VkClearValue* clearValues,
194199
uint32_t clearValueCount);
195200

196201
/**

engine/render/renderer/platform/vulkan/Context.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,14 @@ namespace Siege::Vulkan
1717
{
1818
Context::~Context()
1919
{
20+
swapchain.~Swapchain();
2021
logicalDevice.~LogicalDevice();
2122
vkDestroySurfaceKHR(vulkanInstance.GetInstance(), surface, nullptr);
2223
vulkanInstance.~Instance();
2324
}
2425

25-
void Context::Init(Instance::GetSurfaceExtensionsCallback surfaceExtensionsCallback,
26+
void Context::Init(const Utils::Extent2D& extent,
27+
Instance::GetSurfaceExtensionsCallback surfaceExtensionsCallback,
2628
GetWindowSurfaceCallBack windowSurfaceCallback)
2729
{
2830
CC_ASSERT(volkInitialize() == VK_SUCCESS, "Unable to initialise Volk!")
@@ -35,10 +37,24 @@ void Context::Init(Instance::GetSurfaceExtensionsCallback surfaceExtensionsCallb
3537
physicalDevice = PhysicalDevice(surface, vulkanInstance);
3638

3739
logicalDevice = LogicalDevice(surface, physicalDevice);
40+
41+
swapchain = Swapchain(extent);
3842
}
3943

4044
Context& Context::Get()
4145
{
4246
return Renderer::Context();
4347
}
48+
49+
void Context::RecreateSwapchain(const Utils::Extent2D& extent)
50+
{
51+
auto oldSwapchain = Get().GetSwapchain().GetRaw();
52+
Get().RecreateSwapchain(extent, oldSwapchain);
53+
}
54+
55+
void Context::RecreateSwapchain(const Utils::Extent2D& extent, VkSwapchainKHR oldSwapchain)
56+
{
57+
swapchain = Swapchain(extent, oldSwapchain);
58+
}
59+
4460
} // namespace Siege::Vulkan

0 commit comments

Comments
 (0)