Reached shader lessons. Stopping to refactor code.
This commit is contained in:
2026-01-21 15:05:14 -05:00
parent 586ae1d18e
commit 15b3e294b5
21 changed files with 749 additions and 286 deletions

View File

@@ -89,7 +89,6 @@ cpp_includes_use_forward_slash = true
[*.{cpp,h}] [*.{cpp,h}]
# Naming convention rules (note: currently need to be ordered from more to less specific) # Naming convention rules (note: currently need to be ordered from more to less specific)
cpp_naming_rule.aactor_prefixed.symbols = aactor_class cpp_naming_rule.aactor_prefixed.symbols = aactor_class
cpp_naming_rule.aactor_prefixed.style = aactor_style cpp_naming_rule.aactor_prefixed.style = aactor_style
@@ -115,7 +114,6 @@ cpp_naming_rule.general_names.symbols = all_symbols
cpp_naming_rule.general_names.style = unreal_engine_default cpp_naming_rule.general_names.style = unreal_engine_default
# Naming convention symbols # Naming convention symbols
cpp_naming_symbols.aactor_class.applicable_kinds = class cpp_naming_symbols.aactor_class.applicable_kinds = class
cpp_naming_symbols.aactor_class.applicable_type = AActor cpp_naming_symbols.aactor_class.applicable_type = AActor
@@ -137,6 +135,15 @@ cpp_naming_symbols.structs.applicable_kinds = struct
cpp_naming_symbols.all_symbols.applicable_kinds = * cpp_naming_symbols.all_symbols.applicable_kinds = *
# Naming convention styles # Naming convention styles
cpp_naming_style.member_variables_style.capitalization = camel_case
cpp_naming_style.member_variables_style.required_prefix = m_
cpp_naming_style.member_variables_style.required_suffix =
cpp_naming_style.member_variables_style.word_separator =
cpp_naming_style.parameters_in_style.capitalization = camel_case
cpp_naming_style.parameters_in_style.required_prefix = in_
cpp_naming_style.parameters_in_style.required_suffix =
cpp_naming_style.parameters_in_style.word_separator =
cpp_naming_style.unreal_engine_default.capitalization = pascal_case cpp_naming_style.unreal_engine_default.capitalization = pascal_case
cpp_naming_style.unreal_engine_default.required_prefix = cpp_naming_style.unreal_engine_default.required_prefix =

View File

@@ -1,39 +1,40 @@
#include "GlfwWindowManager.h" #include "GlfwWindowManager.h"
#include <algorithm> #include <algorithm>
#include "Logger.h" #include "Logger.h"
// bool WindowManager::bGlfwInitialized = false; VkSurfaceKHR GlfwWindowManager::Surface = VK_NULL_HANDLE;
GLFWwindow* GlfwWindowManager::Window = nullptr;
GlfwWindowManager::GlfwWindowManager() = default; GlfwWindowManager::GlfwWindowManager() = default;
GlfwWindowManager::~GlfwWindowManager() GlfwWindowManager::~GlfwWindowManager()
{ {
Cleanup(); // Cleanup();
} }
GlfwWindowManager::GlfwWindowManager(GlfwWindowManager&& Other) noexcept // GlfwWindowManager::GlfwWindowManager(GlfwWindowManager&& Other) noexcept
: Window(Other.Window), Title(std::move(Other.Title)), Width(Other.Width), Height(Other.Height) // : Window(Other.Window), Config(Other.Config), Surface(Other.Surface)
{ //{
Other.Window = nullptr; // Other.Window = nullptr;
} // }
//
GlfwWindowManager& GlfwWindowManager::operator=(GlfwWindowManager&& Other) noexcept // GlfwWindowManager& GlfwWindowManager::operator=(GlfwWindowManager&& Other) noexcept
{ //{
if (this != &Other) // if (this != &Other)
{ // {
Cleanup(); // Cleanup();
//
Window = Other.Window; // Window = Other.Window;
Title = std::move(Other.Title); // Config = Other.Config;
Width = Other.Width; // Surface = Other.Surface;
Height = Other.Height; //
// Other.Window = nullptr;
Other.Window = nullptr; // }
} //
// return *this;
return *this; // }
}
void GlfwWindowManager::Initialize(const FWindowConfig& Config) void GlfwWindowManager::Initialize(const FWindowConfig& Config)
{ {
@@ -42,29 +43,12 @@ void GlfwWindowManager::Initialize(const FWindowConfig& Config)
return; return;
} }
this->Config = Config;
InitializeGlfw(); InitializeGlfw();
Title = Config.Title;
Width = Config.Width;
Height = Config.Height;
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
glfwWindowHint(GLFW_RESIZABLE, Config.bResizable ? GLFW_TRUE : GLFW_FALSE);
Window = glfwCreateWindow(
Width,
Height,
Title.c_str(),
Config.bFullscreen ? glfwGetPrimaryMonitor() : nullptr,
nullptr);
if (!Window)
{
Log::Error("Failed to create GLFW window");
}
} }
void GlfwWindowManager::Cleanup() void GlfwWindowManager::Cleanup(VkInstance Instance)
{ {
if (!IsInitialized()) if (!IsInitialized())
{ {
@@ -100,7 +84,7 @@ void GlfwWindowManager::WaitEvents() const
void GlfwWindowManager::SetTitle(const std::string& Title) void GlfwWindowManager::SetTitle(const std::string& Title)
{ {
this->Title = Title; // this->Title = Title;
if (Window) if (Window)
{ {
@@ -108,20 +92,44 @@ void GlfwWindowManager::SetTitle(const std::string& Title)
} }
} }
VkSurfaceKHR GlfwWindowManager::CreateSurface(VkInstance Instance) const void GlfwWindowManager::CreateSurface(VkInstance Instance)
{ {
if (!Window || !Instance) if (!Window)
{ {
return VK_NULL_HANDLE; Log::Error("Window not initialized.");
} }
VkSurfaceKHR Surface = VK_NULL_HANDLE; if (!Instance)
if (glfwCreateWindowSurface(Instance, Window, nullptr, &Surface) != VK_SUCCESS)
{ {
Log::Error("Failed to create window surface"); Log::Error("Instance is null.");
} }
return Surface; VkResult result = glfwCreateWindowSurface(Instance, Window, nullptr, &Surface);
if (result != VK_SUCCESS)
{
std::string errorMsg;
switch (result)
{
case VK_ERROR_EXTENSION_NOT_PRESENT:
errorMsg = "VK_ERROR_EXTENSION_NOT_PRESENT - Required extension not present";
break;
case VK_ERROR_INITIALIZATION_FAILED:
errorMsg = "VK_ERROR_INITIALIZATION_FAILED - Initialization failed";
break;
case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR:
errorMsg = "VK_ERROR_NATIVE_WINDOW_IN_USE_KHR - Native window already in use";
break;
default:
errorMsg = "Unknown error code: " + std::to_string(result);
break;
}
Log::Error("Failed to create window surface: " + errorMsg);
}
else
{
Log::Info("Window surface created successfully.");
}
} }
void GlfwWindowManager::SetResizeCallback(GLFWwindowsizefun Callback) void GlfwWindowManager::SetResizeCallback(GLFWwindowsizefun Callback)
@@ -182,4 +190,23 @@ void GlfwWindowManager::InitializeGlfw()
Log::Error("Failed to initialize GLFW"); Log::Error("Failed to initialize GLFW");
} }
} }
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
glfwWindowHint(GLFW_RESIZABLE, Config.bResizable ? GLFW_TRUE : GLFW_FALSE);
Window = glfwCreateWindow(
Config.Width,
Config.Height,
Config.Title.c_str(),
Config.bFullscreen ? glfwGetPrimaryMonitor() : nullptr,
nullptr);
if (!Window)
{
Log::Error("Failed to create GLFW window");
}
else
{
Log::Info("Created GLFW window successfully.");
}
} }

View File

@@ -2,8 +2,11 @@
#include <string> #include <string>
#define VK_USE_PLATFORM_WIN32_KHR
#define GLFW_INCLUDE_VULKAN #define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#define GLFW_EXPOSE_NATIVE_WIN32
#include <GLFW/glfw3native.h>
struct FWindowConfig struct FWindowConfig
{ {
@@ -20,14 +23,14 @@ public:
GlfwWindowManager(); GlfwWindowManager();
~GlfwWindowManager(); ~GlfwWindowManager();
GlfwWindowManager(const GlfwWindowManager&) = delete; // GlfwWindowManager(const GlfwWindowManager&) = delete;
GlfwWindowManager& operator=(const GlfwWindowManager&) = delete; // GlfwWindowManager& operator=(const GlfwWindowManager&) = delete;
GlfwWindowManager(GlfwWindowManager&& Other) noexcept; // GlfwWindowManager(GlfwWindowManager&& Other) noexcept;
GlfwWindowManager& operator=(GlfwWindowManager&& Other) noexcept; // GlfwWindowManager& operator=(GlfwWindowManager&& Other) noexcept;
void Initialize(const FWindowConfig& Config); void Initialize(const FWindowConfig& Config);
void Cleanup(); void Cleanup(VkInstance Instance);
bool ShouldClose() const; bool ShouldClose() const;
void PollEvents(); void PollEvents();
@@ -35,12 +38,11 @@ public:
void SetTitle(const std::string& Title); void SetTitle(const std::string& Title);
GLFWwindow* GetHandle() const { return Window; } GLFWwindow* GetHandle() const { return Window; }
uint32_t GetWidth() const { return Width; } uint32_t GetWidth() const { return Config.Width; }
uint32_t GetHeight() const { return Height; } uint32_t GetHeight() const { return Config.Height; }
const std::string& GetTitle() const { return Title; } const std::string& GetTitle() const { return Config.Title; }
bool IsInitialized() const { return Window != nullptr; }
VkSurfaceKHR CreateSurface(VkInstance Instance) const; bool IsInitialized() const { return Window && Surface; }
void SetResizeCallback(GLFWwindowsizefun Callback); void SetResizeCallback(GLFWwindowsizefun Callback);
void SetKeyCallback(GLFWkeyfun Callback); void SetKeyCallback(GLFWkeyfun Callback);
@@ -48,14 +50,18 @@ public:
void SetCursorPositionCallback(GLFWcursorposfun Callback); void SetCursorPositionCallback(GLFWcursorposfun Callback);
void SetScrollCallback(GLFWscrollfun Callback); void SetScrollCallback(GLFWscrollfun Callback);
private: void CreateSurface(VkInstance Instance);
// static bool bGlfwInitialized;
void InitializeGlfw();
GLFWwindow* Window = nullptr; static VkSurfaceKHR Surface;
std::string Title;
uint32_t Width = 0; static GLFWwindow* Window;
uint32_t Height = 0;
private:
FWindowConfig Config;
// VkSurfaceKHR Surface = VK_NULL_HANDLE;
void InitializeGlfw();
void DestroyWindow(); void DestroyWindow();
}; };

View File

@@ -131,6 +131,7 @@
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="VulkanContext.cpp" />
<ClCompile Include="VulkanDebugManager.cpp" /> <ClCompile Include="VulkanDebugManager.cpp" />
<ClCompile Include="main.cpp" /> <ClCompile Include="main.cpp" />
<ClCompile Include="Logger.cpp" /> <ClCompile Include="Logger.cpp" />
@@ -139,6 +140,9 @@
<ClCompile Include="GlfwWindowManager.cpp" /> <ClCompile Include="GlfwWindowManager.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="VulkanGraphicsPipeline.h" />
<ClInclude Include="Utilities\FileReader.h" />
<ClInclude Include="VulkanContext.h" />
<ClInclude Include="VulkanDebugManager.h" /> <ClInclude Include="VulkanDebugManager.h" />
<ClInclude Include="Logger.h" /> <ClInclude Include="Logger.h" />
<ClInclude Include="VulkanDeviceManager.h" /> <ClInclude Include="VulkanDeviceManager.h" />
@@ -147,6 +151,8 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include=".clang-format" /> <None Include=".clang-format" />
<None Include="Shaders\shader.frag" />
<None Include="Shaders\shader.vert" />
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"> <ImportGroup Label="ExtensionTargets">

View File

@@ -13,6 +13,9 @@
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter> </Filter>
<Filter Include="Shaders">
<UniqueIdentifier>{699a4173-18fe-4109-979d-1612d035b2d6}</UniqueIdentifier>
</Filter>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="main.cpp"> <ClCompile Include="main.cpp">
@@ -33,6 +36,9 @@
<ClCompile Include="VulkanDeviceManager.cpp"> <ClCompile Include="VulkanDeviceManager.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="VulkanContext.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="Logger.h"> <ClInclude Include="Logger.h">
@@ -50,8 +56,23 @@
<ClInclude Include="VulkanDeviceManager.h"> <ClInclude Include="VulkanDeviceManager.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="VulkanContext.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="VulkanGraphicsPipeline.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Utilities\FileReader.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include=".clang-format" /> <None Include=".clang-format" />
<None Include="Shaders\shader.vert">
<Filter>Shaders</Filter>
</None>
<None Include="Shaders\shader.frag">
<Filter>Shaders</Filter>
</None>
</ItemGroup> </ItemGroup>
</Project> </Project>

3
Shaders/compile.bat Normal file
View File

@@ -0,0 +1,3 @@
C:/Users/jorda/Development/Libraries/Vulkan/1.4.335.0/Bin/glslc.exe shader.vert -o vert.spv
C:/Users/jorda/Development/Libraries/Vulkan/1.4.335.0/Bin/glslc.exe shader.frag -o frag.spv
pause

BIN
Shaders/frag.spv Normal file

Binary file not shown.

9
Shaders/shader.frag Normal file
View File

@@ -0,0 +1,9 @@
#version 450
layout(location = 0) in vec3 fragColor;
layout(location = 0) out vec4 outColor;
void main() {
outColor = vec4(fragColor, 1.0);
}

20
Shaders/shader.vert Normal file
View File

@@ -0,0 +1,20 @@
#version 450
layout(location = 0) out vec3 fragColor;
vec2 positions[3] = vec2[](
vec2(0.0, -0.5),
vec2(0.5, 0.5),
vec2(-0.5, 0.5)
);
vec3 colors[3] = vec3[](
vec3(1.0, 0.0, 0.0),
vec3(0.0, 1.0, 0.0),
vec3(0.0, 0.0, 1.0)
);
void main() {
gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);
fragColor = colors[gl_VertexIndex];
}

BIN
Shaders/vert.spv Normal file

Binary file not shown.

26
Utilities/FileReader.h Normal file
View File

@@ -0,0 +1,26 @@
#pragma once
#include <fstream>
#include <vector>
#include "Logger.h"
static std::vector<char> ReadFile(const std::string& FileName)
{
std::ifstream File(FileName, std::ios::ate | std::ios::binary);
if (!File.is_open())
{
Log::Error("Failed to open file: " + FileName);
}
size_t FileSize = (size_t)File.tellg();
std::vector<char> Buffer(FileSize);
File.seekg(0);
File.read(Buffer.data(), FileSize);
File.close();
return Buffer;
}

View File

@@ -1,77 +0,0 @@
#pragma once
#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>
#include <iostream>
#include <vector>
#ifdef NDEBUG
const bool enableValidationLayers = false;
#else
const bool enableValidationLayers = true;
#endif
VkDebugUtilsMessengerEXT debugMessenger;
VkResult CreateDebugUtilsMessengerEXT(
VkInstance instance,
const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkDebugUtilsMessengerEXT* pDebugMessenger)
{
auto func = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT");
if (func != nullptr)
{
return func(instance, pCreateInfo, pAllocator, pDebugMessenger);
}
else
{
return VK_ERROR_EXTENSION_NOT_PRESENT;
}
}
static VKAPI_ATTR VkBool32 VKAPI_CALL DebugCallback(
VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
VkDebugUtilsMessageTypeFlagsEXT messageType,
const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
void* pUserData)
{
std::cerr << "validation layer: " << pCallbackData->pMessage << std::endl;
if (messageSeverity >= VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT)
{
}
return VK_FALSE;
}
bool CheckValidationLayerSupport()
{
uint32_t layerCount;
vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
std::vector<VkLayerProperties> availableLayers(layerCount);
vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data());
for (const char* layerName : validationLayers)
{
bool layerFound = false;
for (const auto& layerProperties : availableLayers)
{
if (strcmp(layerName, layerProperties.layerName) == 0)
{
layerFound = true;
break;
}
}
if (!layerFound)
{
return false;
}
}
return true;
}

View File

@@ -1,65 +0,0 @@
#pragma once
#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>
#include <vector>
#ifdef NDEBUG
const bool enableValidationLayers = false;
#else
const bool enableValidationLayers = true;
#endif
class VkSetup
{
GLFWwindow* window;
VkInstance instance;
std::vector<const char*> GetRequiredExtensions()
{
uint32_t glfwExtensionCount = 0;
const char** glfwExtensions;
glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
std::vector<const char*> extensions(glfwExtensions, glfwExtensions + glfwExtensionCount);
if (enableValidationLayers)
{
extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
}
return extensions;
}
bool CheckValidationLayerSupport()
{
uint32_t layerCount;
vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
std::vector<VkLayerProperties> availableLayers(layerCount);
vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data());
for (const char* layerName : validationLayers)
{
bool layerFound = false;
for (const auto& layerProperties : availableLayers)
{
if (strcmp(layerName, layerProperties.layerName) == 0)
{
layerFound = true;
break;
}
}
if (!layerFound)
{
return false;
}
}
return true;
}
};

View File

@@ -1,11 +1,12 @@
#pragma once #pragma once
#include <vector> // #include <vector>
#include <memory> // #include <memory>
//
#include "Logger.h" #include "Logger.h"
#include "VulkanInstanceManager.h" #include "VulkanInstanceManager.h"
#include "VulkanDeviceManager.h" #include "VulkanDeviceManager.h"
#include "VulkanDebugManager.h" #include "VulkanDebugManager.h"
#include "VulkanGraphicsPipeline.h"
#include "GlfwWindowManager.h" #include "GlfwWindowManager.h"
#define GLFW_INCLUDE_VULKAN #define GLFW_INCLUDE_VULKAN
@@ -27,7 +28,7 @@ public:
VulkanContext(); VulkanContext();
~VulkanContext(); ~VulkanContext();
void Initialize(FVulkanConfig& inConfig); void Initialize(FVulkanConfig& Config);
void Cleanup(); void Cleanup();
private: private:
@@ -40,6 +41,12 @@ private:
VkSurfaceKHR Surface = VK_NULL_HANDLE; VkSurfaceKHR Surface = VK_NULL_HANDLE;
VkDebugUtilsMessengerEXT debugMessenger = VK_NULL_HANDLE; VkDebugUtilsMessengerEXT debugMessenger = VK_NULL_HANDLE;
public:
static VulkanDebugManager DebugManager;
private:
VulkanInstanceManager InstanceManager;
public: public:
VkInstance GetInstance() const { return Instance; } VkInstance GetInstance() const { return Instance; }
VkPhysicalDevice GetPhysicalDevice() const { return PhysicalDevice; } VkPhysicalDevice GetPhysicalDevice() const { return PhysicalDevice; }

View File

@@ -7,7 +7,7 @@ VulkanDebugManager::VulkanDebugManager()
VulkanDebugManager::~VulkanDebugManager() VulkanDebugManager::~VulkanDebugManager()
{ {
Cleanup(); // Cleanup();
} }
VulkanDebugManager::VulkanDebugManager(VulkanDebugManager&& Other) noexcept VulkanDebugManager::VulkanDebugManager(VulkanDebugManager&& Other) noexcept
@@ -30,6 +30,7 @@ VulkanDebugManager& VulkanDebugManager::operator=(VulkanDebugManager&& Other) no
return *this; return *this;
} }
void VulkanDebugManager::Initialize(VkInstance Instance) void VulkanDebugManager::Initialize(VkInstance Instance)
{ {
if (IsInitialized()) if (IsInitialized())

View File

@@ -1,9 +1,16 @@
#include "VulkanDeviceManager.h" #include "VulkanDeviceManager.h"
#include <vector> #include <vector>
#include <map>
#include <cstdint> // Necessary for uint32_t
#include <limits> // Necessary for std::numeric_limits
#include <algorithm> // Necessary for std::clamp
#include "Logger.h" #include "Logger.h"
#include <map> #include "GlfwWindowManager.h"
#include <set>
std::vector<VkImage> VulkanDeviceManager::SwapChainImages = {};
VulkanDeviceManager::VulkanDeviceManager() VulkanDeviceManager::VulkanDeviceManager()
{ {
@@ -11,10 +18,16 @@ VulkanDeviceManager::VulkanDeviceManager()
VulkanDeviceManager::~VulkanDeviceManager() VulkanDeviceManager::~VulkanDeviceManager()
{ {
Cleanup(); // Cleanup();
} }
VulkanDeviceManager::VulkanDeviceManager(VulkanDeviceManager&& Other) noexcept VulkanDeviceManager::VulkanDeviceManager(VulkanDeviceManager&& Other) noexcept
: PhysicalDevice(std::exchange(Other.PhysicalDevice, VK_NULL_HANDLE))
, Instance(std::exchange(Other.Instance, VK_NULL_HANDLE))
, Device(std::exchange(Other.Device, VK_NULL_HANDLE))
, GraphicsQueue(std::exchange(Other.GraphicsQueue, VK_NULL_HANDLE))
, bEnableValidationLayers(std::exchange(Other.bEnableValidationLayers, false))
, ValidationLayers(std::move(Other.ValidationLayers))
{ {
} }
@@ -22,25 +35,55 @@ VulkanDeviceManager& VulkanDeviceManager::operator=(VulkanDeviceManager&& Other)
{ {
if (this != &Other) if (this != &Other)
{ {
Cleanup(); Cleanup(); // Clean up current resources
}
// Transfer resources from Other
PhysicalDevice = std::exchange(Other.PhysicalDevice, VK_NULL_HANDLE);
Instance = std::exchange(Other.Instance, VK_NULL_HANDLE);
Device = std::exchange(Other.Device, VK_NULL_HANDLE);
GraphicsQueue = std::exchange(Other.GraphicsQueue, VK_NULL_HANDLE);
bEnableValidationLayers = std::exchange(Other.bEnableValidationLayers, false);
ValidationLayers = std::move(Other.ValidationLayers);
}
return *this; return *this;
} }
void VulkanDeviceManager::Initialize(VkInstance Instance)
void VulkanDeviceManager::Initialize(
VkInstance Instance,
bool bEnableValidationLayers,
const std::vector<const char*>& ValidationLayers)
{ {
if (IsInitialized()) if (IsInitialized())
{ {
Log::Warning("Already Initialized.");
return; return;
} }
this->Instance = Instance;
this->bEnableValidationLayers = bEnableValidationLayers;
this->ValidationLayers = &ValidationLayers;
PickPhysicalDevice();
CreateLogicalDevice();
CreateSwapChain();
CreateImageViews();
} }
void VulkanDeviceManager::Cleanup() void VulkanDeviceManager::Cleanup()
{ {
if (!IsInitialized()) if (!IsInitialized())
{ {
Log::Warning("Not Initialized.");
return; return;
} }
for (auto ImageView : SwapChainImageViews)
{
vkDestroyImageView(Device, ImageView, nullptr);
}
vkDestroySwapchainKHR(Device, SwapChain, nullptr);
vkDestroySurfaceKHR(Instance, GlfwWindowManager::Surface, nullptr);
vkDestroyDevice(Device, nullptr);
} }
void VulkanDeviceManager::PickPhysicalDevice() void VulkanDeviceManager::PickPhysicalDevice()
@@ -50,7 +93,7 @@ void VulkanDeviceManager::PickPhysicalDevice()
if (DeviceCount == 0) if (DeviceCount == 0)
{ {
Log::Error("Failed to find GPU with Vulkan Support"); Log::Error("Failed to find GPU with Vulkan Support.");
} }
std::vector<VkPhysicalDevice> Devices(DeviceCount); std::vector<VkPhysicalDevice> Devices(DeviceCount);
@@ -60,30 +103,39 @@ void VulkanDeviceManager::PickPhysicalDevice()
for (const auto& Device : Devices) for (const auto& Device : Devices)
{ {
int Score = RateDeviceSuitability(Device); if (IsDeviceSuitable(Device))
Candidates.insert(std::make_pair(Score, Device)); {
int Score = RateDeviceSuitability(Device);
Candidates.insert(std::make_pair(Score, Device));
}
} }
if (Candidates.rbegin()->first > 0) if (Candidates.rbegin()->first > 0)
{ {
PhysicalDevice = Candidates.rbegin()->second; PhysicalDevice = Candidates.rbegin()->second;
Log::Info("Suitable GPU found.");
} }
else else
{ {
Log::Error("Failed to find a suitable GPU"); Log::Error("Failed to find a suitable GPU.");
} }
} }
// bool VulkanDeviceManager::IsDeviceSuitable(VkPhysicalDevice Device) bool VulkanDeviceManager::IsDeviceSuitable(VkPhysicalDevice Device)
//{ {
// VkPhysicalDeviceProperties DeviceProperties; QueueFamilyIndices Indices = FindQueueFamilies(Device);
// vkGetPhysicalDeviceProperties(Device, &DeviceProperties);
// bool bExtensionsSupported = CheckDeviceExtensionSupport(Device);
// VkPhysicalDeviceFeatures DeviceFeatures;
// vkGetPhysicalDeviceFeatures(Device, &DeviceFeatures); bool bSwapChainAdequate = false;
// if (bExtensionsSupported)
// return DeviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU && DeviceFeatures.geometryShader; {
// } SwapChainSupportDetails SwapChainSupport = QuerySwapChainSupport(Device);
bSwapChainAdequate = !SwapChainSupport.Formats.empty() && !SwapChainSupport.PresentModes.empty();
}
return Indices.IsComplete() && bExtensionsSupported && bSwapChainAdequate;
}
int VulkanDeviceManager::RateDeviceSuitability(VkPhysicalDevice Device) int VulkanDeviceManager::RateDeviceSuitability(VkPhysicalDevice Device)
{ {
@@ -109,3 +161,282 @@ int VulkanDeviceManager::RateDeviceSuitability(VkPhysicalDevice Device)
return Score; return Score;
} }
bool VulkanDeviceManager::CheckDeviceExtensionSupport(VkPhysicalDevice Device)
{
uint32_t ExtensionCount;
vkEnumerateDeviceExtensionProperties(Device, nullptr, &ExtensionCount, nullptr);
std::vector<VkExtensionProperties> AvailableExtensions(ExtensionCount);
vkEnumerateDeviceExtensionProperties(Device, nullptr, &ExtensionCount, AvailableExtensions.data());
std::set<std::string> RequiredExtensions(DeviceExtensions.begin(), DeviceExtensions.end());
for (const auto& Extension : AvailableExtensions)
{
RequiredExtensions.erase(Extension.extensionName);
}
return RequiredExtensions.empty();
}
QueueFamilyIndices VulkanDeviceManager::FindQueueFamilies(VkPhysicalDevice Device)
{
QueueFamilyIndices Indices;
uint32_t QueueFamilyCount = 0;
vkGetPhysicalDeviceQueueFamilyProperties(Device, &QueueFamilyCount, nullptr);
std::vector<VkQueueFamilyProperties> QueueFamilies(QueueFamilyCount);
vkGetPhysicalDeviceQueueFamilyProperties(Device, &QueueFamilyCount, QueueFamilies.data());
int i = 0;
for (const auto& QueueFamily : QueueFamilies)
{
if (QueueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT)
{
Indices.GraphicsFamily = i;
}
VkBool32 PresentSupport = false;
vkGetPhysicalDeviceSurfaceSupportKHR(Device, i, GlfwWindowManager::Surface, &PresentSupport);
if (PresentSupport)
{
Indices.PresentFamily = i;
}
if (Indices.IsComplete())
{
break;
}
i++;
}
return Indices;
}
void VulkanDeviceManager::CreateLogicalDevice()
{
QueueFamilyIndices Indices = FindQueueFamilies(PhysicalDevice);
std::vector<VkDeviceQueueCreateInfo> QueueCreateInfos;
std::set<uint32_t> UniqueQueueFamilies = { Indices.GraphicsFamily.value(), Indices.PresentFamily.value() };
float QueuePriority = 1.0f;
for (uint32_t QueueFamily : UniqueQueueFamilies)
{
VkDeviceQueueCreateInfo QueueCreateInfo{};
QueueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
QueueCreateInfo.queueFamilyIndex = Indices.GraphicsFamily.value();
QueueCreateInfo.queueCount = 1;
QueueCreateInfo.pQueuePriorities = &QueuePriority;
QueueCreateInfos.push_back(QueueCreateInfo);
}
VkPhysicalDeviceFeatures DeviceFeatures{};
VkDeviceCreateInfo CreateInfo{};
CreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
CreateInfo.queueCreateInfoCount = static_cast<uint32_t>(QueueCreateInfos.size());
CreateInfo.pQueueCreateInfos = QueueCreateInfos.data();
CreateInfo.pEnabledFeatures = &DeviceFeatures;
CreateInfo.enabledExtensionCount = static_cast<uint32_t>(DeviceExtensions.size());
CreateInfo.ppEnabledExtensionNames = DeviceExtensions.data();
if (bEnableValidationLayers)
{
CreateInfo.enabledLayerCount = static_cast<uint32_t>(ValidationLayers->size());
CreateInfo.ppEnabledLayerNames = ValidationLayers->data();
}
else
{
CreateInfo.enabledLayerCount = 0;
}
if (vkCreateDevice(PhysicalDevice, &CreateInfo, nullptr, &Device) != VK_SUCCESS)
{
Log::Error("Failed to create logical device!");
}
vkGetDeviceQueue(Device, Indices.GraphicsFamily.value(), 0, &GraphicsQueue);
vkGetDeviceQueue(Device, Indices.PresentFamily.value(), 0, &PresentQueue);
}
SwapChainSupportDetails VulkanDeviceManager::QuerySwapChainSupport(VkPhysicalDevice Device)
{
SwapChainSupportDetails Details;
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(Device, GlfwWindowManager::Surface, &Details.Capabilities);
uint32_t FormatCount;
vkGetPhysicalDeviceSurfaceFormatsKHR(Device, GlfwWindowManager::Surface, &FormatCount, nullptr);
if (FormatCount != 0)
{
Details.Formats.resize(FormatCount);
vkGetPhysicalDeviceSurfaceFormatsKHR(Device, GlfwWindowManager::Surface, &FormatCount, Details.Formats.data());
}
uint32_t PresentModeCount;
vkGetPhysicalDeviceSurfacePresentModesKHR(Device, GlfwWindowManager::Surface, &PresentModeCount, nullptr);
if (PresentModeCount != 0)
{
Details.PresentModes.resize(PresentModeCount);
vkGetPhysicalDeviceSurfacePresentModesKHR(Device, GlfwWindowManager::Surface, &PresentModeCount, Details.PresentModes.data());
}
return Details;
}
VkSurfaceFormatKHR VulkanDeviceManager::ChooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& AvailableFormats)
{
for (const auto& AvailableFormat : AvailableFormats)
{
if (AvailableFormat.format == VK_FORMAT_B8G8R8A8_SRGB && AvailableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
{
return AvailableFormat;
}
}
return AvailableFormats[0];
}
VkPresentModeKHR VulkanDeviceManager::ChooseSwapPresentMode(const std::vector<VkPresentModeKHR>& AvailablePresentModes)
{
for (const auto& AvailablePresentMode : AvailablePresentModes)
{
if (AvailablePresentMode == VK_PRESENT_MODE_MAILBOX_KHR)
{
return AvailablePresentMode;
}
}
return VK_PRESENT_MODE_FIFO_KHR;
}
VkExtent2D VulkanDeviceManager::ChooseSwapExtent(const VkSurfaceCapabilitiesKHR& Capabilities)
{
if (Capabilities.currentExtent.width != (std::numeric_limits<uint32_t>::max)())
{
return Capabilities.currentExtent;
}
else
{
int Width, Height;
glfwGetFramebufferSize(GlfwWindowManager::Window, &Width, &Height);
VkExtent2D ActualExtent = {
static_cast<uint32_t>(Width),
static_cast<uint32_t>(Height)
};
ActualExtent.width = std::clamp(ActualExtent.width, Capabilities.minImageExtent.width, Capabilities.maxImageExtent.width);
ActualExtent.height = std::clamp(ActualExtent.height, Capabilities.minImageExtent.height, Capabilities.maxImageExtent.height);
return ActualExtent;
}
}
void VulkanDeviceManager::CreateSwapChain()
{
SwapChainSupportDetails SwapChainSupport = QuerySwapChainSupport(PhysicalDevice);
VkSurfaceFormatKHR SurfaceFormat = ChooseSwapSurfaceFormat(SwapChainSupport.Formats);
VkPresentModeKHR PresentMode = ChooseSwapPresentMode(SwapChainSupport.PresentModes);
VkExtent2D Extent = ChooseSwapExtent(SwapChainSupport.Capabilities);
uint32_t ImageCount = SwapChainSupport.Capabilities.minImageCount + 1;
if (SwapChainSupport.Capabilities.maxImageCount > 0 && ImageCount > SwapChainSupport.Capabilities.maxImageCount)
{
ImageCount = SwapChainSupport.Capabilities.maxImageCount;
}
VkSwapchainCreateInfoKHR CreateInfo{};
CreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
CreateInfo.surface = GlfwWindowManager::Surface;
CreateInfo.minImageCount = ImageCount;
CreateInfo.imageFormat = SurfaceFormat.format;
CreateInfo.imageColorSpace = SurfaceFormat.colorSpace;
CreateInfo.imageExtent = Extent;
CreateInfo.imageArrayLayers = 1;
CreateInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; // may need VK_IMAGE_USAGE_TRANSFER_DST_BIT for post processing https://vulkan-tutorial.com/Drawing_a_triangle/Presentation/Swap_chain#:~:text=VK%5FIMAGE%5FUSAGE%5FTRANSFER%5FDST%5FBIT
QueueFamilyIndices Indices = FindQueueFamilies(PhysicalDevice);
uint32_t QueueFamilyIndices[] = { Indices.GraphicsFamily.value(),
Indices.PresentFamily.value() };
if (Indices.GraphicsFamily != Indices.PresentFamily)
{
CreateInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
CreateInfo.queueFamilyIndexCount = 2;
CreateInfo.pQueueFamilyIndices = QueueFamilyIndices;
}
else
{
CreateInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
CreateInfo.queueFamilyIndexCount = 0;
CreateInfo.pQueueFamilyIndices = nullptr;
}
CreateInfo.preTransform = SwapChainSupport.Capabilities.currentTransform;
CreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
CreateInfo.presentMode = PresentMode;
CreateInfo.clipped = VK_TRUE;
CreateInfo.oldSwapchain = VK_NULL_HANDLE;
if (vkCreateSwapchainKHR(Device, &CreateInfo, nullptr, &SwapChain) != VK_SUCCESS)
{
Log::Error("Failed to create swap chain.");
}
else
{
Log::Info("Successfully created swap chain.");
}
vkGetSwapchainImagesKHR(Device, SwapChain, &ImageCount, nullptr);
SwapChainImages.resize(ImageCount);
vkGetSwapchainImagesKHR(Device, SwapChain, &ImageCount, SwapChainImages.data());
SwapChainImageFormat = SurfaceFormat.format;
SwapChainExtent = Extent;
}
void VulkanDeviceManager::CreateImageViews()
{
SwapChainImageViews.resize(SwapChainImages.size());
int CreatedViews = 0;
for (size_t i = 0; i < SwapChainImages.size(); i++)
{
VkImageViewCreateInfo CreateInfo{};
CreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
CreateInfo.image = SwapChainImages[i];
CreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
CreateInfo.format = SwapChainImageFormat;
CreateInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
CreateInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
CreateInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
CreateInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
CreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
CreateInfo.subresourceRange.baseMipLevel = 0;
CreateInfo.subresourceRange.levelCount = 1;
CreateInfo.subresourceRange.baseArrayLayer = 0;
CreateInfo.subresourceRange.layerCount = 1;
if (vkCreateImageView(Device, &CreateInfo, nullptr, &SwapChainImageViews[i]) != VK_SUCCESS)
{
Log::Error("Failed to create image views.");
}
else
{
CreatedViews++;
}
}
Log::Info("Successfully created " + std::to_string(CreatedViews) + " image views.");
}

View File

@@ -1,22 +1,35 @@
#pragma once #pragma once
#include <optional>
#include <vector>
#include <map>
#include "Logger.h"
#define GLFW_INCLUDE_VULKAN #define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
// struct FCreateDebugUtilsMessengerExtParams const std::vector<const char*> DeviceExtensions = {
//{ VK_KHR_SWAPCHAIN_EXTENSION_NAME
// VkInstance Instance; };
// const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo;
// const VkAllocationCallbacks* pAllocator; struct QueueFamilyIndices
// VkDebugUtilsMessengerEXT* pDebugMessenger; {
// }; std::optional<uint32_t> GraphicsFamily;
// std::optional<uint32_t> PresentFamily;
// struct FDestroyDebugUtilsMessengerExtParams
//{ bool IsComplete()
// VkInstance Instance; {
// VkDebugUtilsMessengerEXT DebugMessenger; return GraphicsFamily.has_value() && PresentFamily.has_value();
// const VkAllocationCallbacks* pAllocator; }
// }; };
struct SwapChainSupportDetails
{
VkSurfaceCapabilitiesKHR Capabilities;
std::vector<VkSurfaceFormatKHR> Formats;
std::vector<VkPresentModeKHR> PresentModes;
};
class VulkanDeviceManager class VulkanDeviceManager
{ {
@@ -30,18 +43,59 @@ public:
VulkanDeviceManager(VulkanDeviceManager&& Other) noexcept; VulkanDeviceManager(VulkanDeviceManager&& Other) noexcept;
VulkanDeviceManager& operator=(VulkanDeviceManager&& Other) noexcept; VulkanDeviceManager& operator=(VulkanDeviceManager&& Other) noexcept;
void Initialize(VkInstance Instance); void Initialize(
VkInstance Instance,
bool EnableValidationLayers,
const std::vector<const char*>& ValidationLayers);
void Cleanup(); void Cleanup();
bool IsInitialized() const { return PhysicalDevice != VK_NULL_HANDLE; } bool IsInitialized() const
{
bool bInitialized = PhysicalDevice && Device && Instance && GraphicsQueue;
return bInitialized;
}
static std::vector<VkImage> SwapChainImages;
private: private:
VkPhysicalDevice PhysicalDevice = VK_NULL_HANDLE; VkPhysicalDevice PhysicalDevice = VK_NULL_HANDLE;
VkInstance Instance = VK_NULL_HANDLE; VkInstance Instance = VK_NULL_HANDLE;
VkDevice Device = VK_NULL_HANDLE;
VkQueue GraphicsQueue = VK_NULL_HANDLE;
VkQueue PresentQueue = VK_NULL_HANDLE;
VkSwapchainKHR SwapChain = VK_NULL_HANDLE;
VkFormat SwapChainImageFormat;
VkExtent2D SwapChainExtent;
std::vector<VkImageView> SwapChainImageViews;
bool bEnableValidationLayers = false;
const std::vector<const char*>* ValidationLayers = nullptr;
void PickPhysicalDevice(); void PickPhysicalDevice();
// bool IsDeviceSuitable(VkPhysicalDevice Device); bool IsDeviceSuitable(VkPhysicalDevice Device);
int RateDeviceSuitability(VkPhysicalDevice Device); int RateDeviceSuitability(VkPhysicalDevice Device);
bool CheckDeviceExtensionSupport(VkPhysicalDevice Device);
QueueFamilyIndices FindQueueFamilies(VkPhysicalDevice Device);
void CreateLogicalDevice();
SwapChainSupportDetails QuerySwapChainSupport(VkPhysicalDevice Device);
VkSurfaceFormatKHR ChooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& AvailableFormats);
VkPresentModeKHR ChooseSwapPresentMode(const std::vector<VkPresentModeKHR>& AvailablePresentModes);
VkExtent2D ChooseSwapExtent(const VkSurfaceCapabilitiesKHR& Capabilities);
void CreateSwapChain();
void CreateImageViews();
}; };

27
VulkanGraphicsPipeline.h Normal file
View File

@@ -0,0 +1,27 @@
#pragma once
#include "Utilities/FileReader.h"
class VulkanGraphicsPipeline
{
public:
void CreateGraphicsPipeline()
{
auto VertShaderCode = ReadFile("Shaders/vert.spv");
auto FragShaderCode = ReadFile("Shaders/frag.spv");
Log::Info("Vert buffer size: " + std::to_string(VertShaderCode.size()));
Log::Info("Frag buffer size: " + std::to_string(FragShaderCode.size()));
}
VkShaderModule CreateShaderModule(const std::vector<char>& Code)
{
VkShaderModuleCreateInfo CreateInfo{};
CreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
CreateInfo.codeSize = Code.size();
CreateInfo.pCode = reinterpret_cast<const uint32_t*>(Code.data());
VkShaderModule ShaderModule;
if (vkCreateShaderModule(Device))
}
};

View File

@@ -8,11 +8,11 @@ VulkanInstanceManager::VulkanInstanceManager()
VulkanInstanceManager::~VulkanInstanceManager() VulkanInstanceManager::~VulkanInstanceManager()
{ {
Cleanup(); // Cleanup();
} }
VulkanInstanceManager::VulkanInstanceManager(VulkanInstanceManager&& Other) noexcept VulkanInstanceManager::VulkanInstanceManager(VulkanInstanceManager&& Other) noexcept
: Instance(Other.Instance), bValidationEnabled(Other.bValidationEnabled), bVerboseLogging(Other.bVerboseLogging), VkDebugManager(std::move(Other.VkDebugManager)) : Instance(Other.Instance) /*, bValidationEnabled(Other.bValidationEnabled), bVerboseLogging(Other.bVerboseLogging), VkDebugManager(std::move(Other.VkDebugManager))*/
{ {
Other.Instance = VK_NULL_HANDLE; Other.Instance = VK_NULL_HANDLE;
Other.bValidationEnabled = false; Other.bValidationEnabled = false;
@@ -34,7 +34,28 @@ VulkanInstanceManager& VulkanInstanceManager::operator=(VulkanInstanceManager&&
return *this; return *this;
} }
void VulkanInstanceManager::Initialize(const FVulkanConfig& Config)
// void VulkanInstanceManager::Initialize(const FVulkanConfig& Config)
//{
// if (IsInitialized())
// {
// Log::Warning("Already Initialized.");
// return;
// }
//
// bValidationEnabled = Config.bValidationEnabled;
// bVerboseLogging = Config.bVerboseLogging;
//
// if (bValidationEnabled)
// {
// Log::Info("DebugManager created with validation enabled.");
// VkDebugManager = std::make_unique<VulkanDebugManager>();
// }
//
// CreateInstance();
// }
void VulkanInstanceManager::Initialize(bool bEnableValidationLayers)
{ {
if (IsInitialized()) if (IsInitialized())
{ {
@@ -42,24 +63,27 @@ void VulkanInstanceManager::Initialize(const FVulkanConfig& Config)
return; return;
} }
bValidationEnabled = Config.bValidationEnabled; if (bEnableValidationLayers)
bVerboseLogging = Config.bVerboseLogging;
if (bValidationEnabled)
{ {
Log::Info("DebugManager created with validation enabled."); Log::Info("DebugManager created with validation enabled.");
VkDebugManager = std::make_unique<VulkanDebugManager>(); VkDebugManager = std::make_unique<VulkanDebugManager>();
} }
CreateInstance(); CreateInstance();
}
if (VkDebugManager) void VulkanInstanceManager::SetupDebug()
{
if (bValidationEnabled)
{ {
VkDebugManager->Initialize(Instance); VkDebugManager->Initialize(Instance);
} }
}
void VulkanInstanceManager::SetupDevice()
{
VkDeviceManager = std::make_unique<VulkanDeviceManager>(); VkDeviceManager = std::make_unique<VulkanDeviceManager>();
VkDeviceManager->Initialize(Instance); VkDeviceManager->Initialize(Instance, bValidationEnabled, ValidationLayers);
} }
void VulkanInstanceManager::Cleanup() void VulkanInstanceManager::Cleanup()
@@ -70,16 +94,16 @@ void VulkanInstanceManager::Cleanup()
return; return;
} }
if (VkDebugManager)
{
VkDebugManager->Cleanup();
}
if (VkDeviceManager) if (VkDeviceManager)
{ {
VkDeviceManager->Cleanup(); VkDeviceManager->Cleanup();
} }
if (VkDebugManager)
{
VkDebugManager->Cleanup();
}
vkDestroyInstance(Instance, nullptr); vkDestroyInstance(Instance, nullptr);
Instance = VK_NULL_HANDLE; Instance = VK_NULL_HANDLE;
} }

View File

@@ -3,11 +3,13 @@
#include <vector> #include <vector>
#include <memory> #include <memory>
#define GLFW_INCLUDE_VULKAN #include "Logger.h"
#include <GLFW/glfw3.h>
#include "VulkanDebugManager.h" #include "VulkanDebugManager.h"
#include "VulkanDeviceManager.h" #include "VulkanDeviceManager.h"
#include "GlfwWindowManager.h"
#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>
const std::vector<const char*> ValidationLayers = { const std::vector<const char*> ValidationLayers = {
"VK_LAYER_KHRONOS_validation" "VK_LAYER_KHRONOS_validation"
@@ -31,11 +33,23 @@ public:
VulkanInstanceManager(VulkanInstanceManager&& Other) noexcept; VulkanInstanceManager(VulkanInstanceManager&& Other) noexcept;
VulkanInstanceManager& operator=(VulkanInstanceManager&& Other) noexcept; VulkanInstanceManager& operator=(VulkanInstanceManager&& Other) noexcept;
void Initialize(const FVulkanConfig& Config); // void Initialize(const FVulkanConfig& Config);
void Initialize(bool bEnableValidationLayers);
void SetupDebug();
void SetupDevice();
// void Initialize(VulkanDebugManager& inDebugManager, bool inValidationEnabled);
void Cleanup(); void Cleanup();
bool IsInitialized() const { return Instance != VK_NULL_HANDLE; } bool IsInitialized() const { return Instance != VK_NULL_HANDLE; }
const std::vector<const char*>& GetValidationLayers() const
{
return ValidationLayers;
}
const VkInstance GetInstance() const { return Instance; }
private: private:
std::unique_ptr<VulkanDebugManager> VkDebugManager = nullptr; std::unique_ptr<VulkanDebugManager> VkDebugManager = nullptr;
std::unique_ptr<VulkanDeviceManager> VkDeviceManager = nullptr; std::unique_ptr<VulkanDeviceManager> VkDeviceManager = nullptr;

View File

@@ -1,7 +1,11 @@
#include "Logger.h" #include "Logger.h"
#include "VulkanInstanceManager.h" #include "VulkanInstanceManager.h"
#include "VulkanDeviceManager.h"
#include "VulkanDebugManager.h"
#include "GlfwWindowManager.h" #include "GlfwWindowManager.h"
#include "VulkanGraphicsPipeline.h"
// #include "VulkanContext.h"
struct AppConfig struct AppConfig
{ {
@@ -19,41 +23,59 @@ class HelloTriangleApplication
public: public:
void Run() void Run()
{ {
InitGlfw(); Initialization();
InitVulkan();
MainLoop(); MainLoop();
Cleanup(); Cleanup();
} }
private: private:
VulkanInstanceManager VkInstanceManager; AppConfig Settings = {};
GlfwWindowManager GlfwWindowManager;
AppConfig Settings = {}; VulkanInstanceManager InstanceManager;
GlfwWindowManager WindowManager;
void Initialization()
{
InitGlfw();
InitVulkan();
InstanceManager.SetupDebug();
WindowManager.CreateSurface(InstanceManager.GetInstance());
InstanceManager.SetupDevice();
}
void InitVulkan() void InitVulkan()
{ {
FVulkanConfig Config = { Settings.bValidationEnabled, Settings.bVerboseLogging }; FVulkanConfig Config = {
VkInstanceManager.Initialize(Config); Settings.bValidationEnabled,
Settings.bVerboseLogging
};
InstanceManager.Initialize(Config);
} }
void InitGlfw() void InitGlfw()
{ {
FWindowConfig Config = { Settings.Title, Settings.Width, Settings.Height, Settings.bResizable, Settings.bFullscreen }; FWindowConfig Config = {
GlfwWindowManager.Initialize(Config); Settings.Title,
Settings.Width,
Settings.Height,
Settings.bResizable,
Settings.bFullscreen
};
WindowManager.Initialize(Config);
} }
void MainLoop() void MainLoop()
{ {
while (!GlfwWindowManager.ShouldClose()) while (!WindowManager.ShouldClose())
{ {
GlfwWindowManager.PollEvents(); WindowManager.PollEvents();
} }
} }
void Cleanup() void Cleanup()
{ {
// VkInstanceManager.Cleanup(); WindowManager.Cleanup(InstanceManager.GetInstance());
// GlfwWindowManager.Cleanup(); InstanceManager.Cleanup();
} }
}; };