Reached shader lessons. Stopping to refactor code.
This commit is contained in:
@@ -89,7 +89,6 @@ cpp_includes_use_forward_slash = true
|
||||
[*.{cpp,h}]
|
||||
|
||||
# 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.style = aactor_style
|
||||
|
||||
@@ -115,7 +114,6 @@ cpp_naming_rule.general_names.symbols = all_symbols
|
||||
cpp_naming_rule.general_names.style = unreal_engine_default
|
||||
|
||||
# Naming convention symbols
|
||||
|
||||
cpp_naming_symbols.aactor_class.applicable_kinds = class
|
||||
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 = *
|
||||
|
||||
# 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.required_prefix =
|
||||
|
||||
@@ -1,39 +1,40 @@
|
||||
#include "GlfwWindowManager.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "Logger.h"
|
||||
|
||||
// bool WindowManager::bGlfwInitialized = false;
|
||||
VkSurfaceKHR GlfwWindowManager::Surface = VK_NULL_HANDLE;
|
||||
GLFWwindow* GlfwWindowManager::Window = nullptr;
|
||||
|
||||
GlfwWindowManager::GlfwWindowManager() = default;
|
||||
|
||||
GlfwWindowManager::~GlfwWindowManager()
|
||||
{
|
||||
Cleanup();
|
||||
// Cleanup();
|
||||
}
|
||||
|
||||
GlfwWindowManager::GlfwWindowManager(GlfwWindowManager&& Other) noexcept
|
||||
: Window(Other.Window), Title(std::move(Other.Title)), Width(Other.Width), Height(Other.Height)
|
||||
{
|
||||
Other.Window = nullptr;
|
||||
}
|
||||
|
||||
GlfwWindowManager& GlfwWindowManager::operator=(GlfwWindowManager&& Other) noexcept
|
||||
{
|
||||
if (this != &Other)
|
||||
{
|
||||
Cleanup();
|
||||
|
||||
Window = Other.Window;
|
||||
Title = std::move(Other.Title);
|
||||
Width = Other.Width;
|
||||
Height = Other.Height;
|
||||
|
||||
Other.Window = nullptr;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
// GlfwWindowManager::GlfwWindowManager(GlfwWindowManager&& Other) noexcept
|
||||
// : Window(Other.Window), Config(Other.Config), Surface(Other.Surface)
|
||||
//{
|
||||
// Other.Window = nullptr;
|
||||
// }
|
||||
//
|
||||
// GlfwWindowManager& GlfwWindowManager::operator=(GlfwWindowManager&& Other) noexcept
|
||||
//{
|
||||
// if (this != &Other)
|
||||
// {
|
||||
// Cleanup();
|
||||
//
|
||||
// Window = Other.Window;
|
||||
// Config = Other.Config;
|
||||
// Surface = Other.Surface;
|
||||
//
|
||||
// Other.Window = nullptr;
|
||||
// }
|
||||
//
|
||||
// return *this;
|
||||
// }
|
||||
|
||||
void GlfwWindowManager::Initialize(const FWindowConfig& Config)
|
||||
{
|
||||
@@ -42,29 +43,12 @@ void GlfwWindowManager::Initialize(const FWindowConfig& Config)
|
||||
return;
|
||||
}
|
||||
|
||||
this->Config = Config;
|
||||
|
||||
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())
|
||||
{
|
||||
@@ -100,7 +84,7 @@ void GlfwWindowManager::WaitEvents() const
|
||||
|
||||
void GlfwWindowManager::SetTitle(const std::string& Title)
|
||||
{
|
||||
this->Title = Title;
|
||||
// this->Title = Title;
|
||||
|
||||
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 (glfwCreateWindowSurface(Instance, Window, nullptr, &Surface) != VK_SUCCESS)
|
||||
if (!Instance)
|
||||
{
|
||||
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)
|
||||
@@ -182,4 +190,23 @@ void GlfwWindowManager::InitializeGlfw()
|
||||
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.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,11 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#define VK_USE_PLATFORM_WIN32_KHR
|
||||
#define GLFW_INCLUDE_VULKAN
|
||||
#include <GLFW/glfw3.h>
|
||||
#define GLFW_EXPOSE_NATIVE_WIN32
|
||||
#include <GLFW/glfw3native.h>
|
||||
|
||||
struct FWindowConfig
|
||||
{
|
||||
@@ -20,14 +23,14 @@ public:
|
||||
GlfwWindowManager();
|
||||
~GlfwWindowManager();
|
||||
|
||||
GlfwWindowManager(const GlfwWindowManager&) = delete;
|
||||
GlfwWindowManager& operator=(const GlfwWindowManager&) = delete;
|
||||
// GlfwWindowManager(const GlfwWindowManager&) = delete;
|
||||
// GlfwWindowManager& operator=(const GlfwWindowManager&) = delete;
|
||||
|
||||
GlfwWindowManager(GlfwWindowManager&& Other) noexcept;
|
||||
GlfwWindowManager& operator=(GlfwWindowManager&& Other) noexcept;
|
||||
// GlfwWindowManager(GlfwWindowManager&& Other) noexcept;
|
||||
// GlfwWindowManager& operator=(GlfwWindowManager&& Other) noexcept;
|
||||
|
||||
void Initialize(const FWindowConfig& Config);
|
||||
void Cleanup();
|
||||
void Cleanup(VkInstance Instance);
|
||||
|
||||
bool ShouldClose() const;
|
||||
void PollEvents();
|
||||
@@ -35,12 +38,11 @@ public:
|
||||
void SetTitle(const std::string& Title);
|
||||
|
||||
GLFWwindow* GetHandle() const { return Window; }
|
||||
uint32_t GetWidth() const { return Width; }
|
||||
uint32_t GetHeight() const { return Height; }
|
||||
const std::string& GetTitle() const { return Title; }
|
||||
bool IsInitialized() const { return Window != nullptr; }
|
||||
uint32_t GetWidth() const { return Config.Width; }
|
||||
uint32_t GetHeight() const { return Config.Height; }
|
||||
const std::string& GetTitle() const { return Config.Title; }
|
||||
|
||||
VkSurfaceKHR CreateSurface(VkInstance Instance) const;
|
||||
bool IsInitialized() const { return Window && Surface; }
|
||||
|
||||
void SetResizeCallback(GLFWwindowsizefun Callback);
|
||||
void SetKeyCallback(GLFWkeyfun Callback);
|
||||
@@ -48,14 +50,18 @@ public:
|
||||
void SetCursorPositionCallback(GLFWcursorposfun Callback);
|
||||
void SetScrollCallback(GLFWscrollfun Callback);
|
||||
|
||||
private:
|
||||
// static bool bGlfwInitialized;
|
||||
void InitializeGlfw();
|
||||
void CreateSurface(VkInstance Instance);
|
||||
|
||||
GLFWwindow* Window = nullptr;
|
||||
std::string Title;
|
||||
uint32_t Width = 0;
|
||||
uint32_t Height = 0;
|
||||
static VkSurfaceKHR Surface;
|
||||
|
||||
static GLFWwindow* Window;
|
||||
|
||||
private:
|
||||
FWindowConfig Config;
|
||||
|
||||
// VkSurfaceKHR Surface = VK_NULL_HANDLE;
|
||||
|
||||
void InitializeGlfw();
|
||||
|
||||
void DestroyWindow();
|
||||
};
|
||||
|
||||
@@ -131,6 +131,7 @@
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="VulkanContext.cpp" />
|
||||
<ClCompile Include="VulkanDebugManager.cpp" />
|
||||
<ClCompile Include="main.cpp" />
|
||||
<ClCompile Include="Logger.cpp" />
|
||||
@@ -139,6 +140,9 @@
|
||||
<ClCompile Include="GlfwWindowManager.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="VulkanGraphicsPipeline.h" />
|
||||
<ClInclude Include="Utilities\FileReader.h" />
|
||||
<ClInclude Include="VulkanContext.h" />
|
||||
<ClInclude Include="VulkanDebugManager.h" />
|
||||
<ClInclude Include="Logger.h" />
|
||||
<ClInclude Include="VulkanDeviceManager.h" />
|
||||
@@ -147,6 +151,8 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include=".clang-format" />
|
||||
<None Include="Shaders\shader.frag" />
|
||||
<None Include="Shaders\shader.vert" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
<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>
|
||||
</Filter>
|
||||
<Filter Include="Shaders">
|
||||
<UniqueIdentifier>{699a4173-18fe-4109-979d-1612d035b2d6}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp">
|
||||
@@ -33,6 +36,9 @@
|
||||
<ClCompile Include="VulkanDeviceManager.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="VulkanContext.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Logger.h">
|
||||
@@ -50,8 +56,23 @@
|
||||
<ClInclude Include="VulkanDeviceManager.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</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>
|
||||
<None Include=".clang-format" />
|
||||
<None Include="Shaders\shader.vert">
|
||||
<Filter>Shaders</Filter>
|
||||
</None>
|
||||
<None Include="Shaders\shader.frag">
|
||||
<Filter>Shaders</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
3
Shaders/compile.bat
Normal file
3
Shaders/compile.bat
Normal 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
BIN
Shaders/frag.spv
Normal file
Binary file not shown.
9
Shaders/shader.frag
Normal file
9
Shaders/shader.frag
Normal 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
20
Shaders/shader.vert
Normal 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
BIN
Shaders/vert.spv
Normal file
Binary file not shown.
26
Utilities/FileReader.h
Normal file
26
Utilities/FileReader.h
Normal 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;
|
||||
}
|
||||
77
VkDebug.h
77
VkDebug.h
@@ -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;
|
||||
}
|
||||
65
VkSetup.h
65
VkSetup.h
@@ -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;
|
||||
}
|
||||
};
|
||||
@@ -1,11 +1,12 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
// #include <vector>
|
||||
// #include <memory>
|
||||
//
|
||||
#include "Logger.h"
|
||||
#include "VulkanInstanceManager.h"
|
||||
#include "VulkanDeviceManager.h"
|
||||
#include "VulkanDebugManager.h"
|
||||
#include "VulkanGraphicsPipeline.h"
|
||||
#include "GlfwWindowManager.h"
|
||||
|
||||
#define GLFW_INCLUDE_VULKAN
|
||||
@@ -27,7 +28,7 @@ public:
|
||||
VulkanContext();
|
||||
~VulkanContext();
|
||||
|
||||
void Initialize(FVulkanConfig& inConfig);
|
||||
void Initialize(FVulkanConfig& Config);
|
||||
void Cleanup();
|
||||
|
||||
private:
|
||||
@@ -40,6 +41,12 @@ private:
|
||||
VkSurfaceKHR Surface = VK_NULL_HANDLE;
|
||||
VkDebugUtilsMessengerEXT debugMessenger = VK_NULL_HANDLE;
|
||||
|
||||
public:
|
||||
static VulkanDebugManager DebugManager;
|
||||
|
||||
private:
|
||||
VulkanInstanceManager InstanceManager;
|
||||
|
||||
public:
|
||||
VkInstance GetInstance() const { return Instance; }
|
||||
VkPhysicalDevice GetPhysicalDevice() const { return PhysicalDevice; }
|
||||
|
||||
@@ -7,7 +7,7 @@ VulkanDebugManager::VulkanDebugManager()
|
||||
|
||||
VulkanDebugManager::~VulkanDebugManager()
|
||||
{
|
||||
Cleanup();
|
||||
// Cleanup();
|
||||
}
|
||||
|
||||
VulkanDebugManager::VulkanDebugManager(VulkanDebugManager&& Other) noexcept
|
||||
@@ -30,6 +30,7 @@ VulkanDebugManager& VulkanDebugManager::operator=(VulkanDebugManager&& Other) no
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void VulkanDebugManager::Initialize(VkInstance Instance)
|
||||
{
|
||||
if (IsInitialized())
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
#include "VulkanDeviceManager.h"
|
||||
|
||||
#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 <map>
|
||||
#include "GlfwWindowManager.h"
|
||||
#include <set>
|
||||
|
||||
std::vector<VkImage> VulkanDeviceManager::SwapChainImages = {};
|
||||
|
||||
VulkanDeviceManager::VulkanDeviceManager()
|
||||
{
|
||||
@@ -11,10 +18,16 @@ VulkanDeviceManager::VulkanDeviceManager()
|
||||
|
||||
VulkanDeviceManager::~VulkanDeviceManager()
|
||||
{
|
||||
Cleanup();
|
||||
// Cleanup();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
void VulkanDeviceManager::Initialize(VkInstance Instance)
|
||||
|
||||
void VulkanDeviceManager::Initialize(
|
||||
VkInstance Instance,
|
||||
bool bEnableValidationLayers,
|
||||
const std::vector<const char*>& ValidationLayers)
|
||||
{
|
||||
if (IsInitialized())
|
||||
{
|
||||
Log::Warning("Already Initialized.");
|
||||
return;
|
||||
}
|
||||
|
||||
this->Instance = Instance;
|
||||
this->bEnableValidationLayers = bEnableValidationLayers;
|
||||
this->ValidationLayers = &ValidationLayers;
|
||||
|
||||
PickPhysicalDevice();
|
||||
CreateLogicalDevice();
|
||||
CreateSwapChain();
|
||||
CreateImageViews();
|
||||
}
|
||||
|
||||
void VulkanDeviceManager::Cleanup()
|
||||
{
|
||||
if (!IsInitialized())
|
||||
{
|
||||
Log::Warning("Not Initialized.");
|
||||
return;
|
||||
}
|
||||
for (auto ImageView : SwapChainImageViews)
|
||||
{
|
||||
vkDestroyImageView(Device, ImageView, nullptr);
|
||||
}
|
||||
vkDestroySwapchainKHR(Device, SwapChain, nullptr);
|
||||
|
||||
vkDestroySurfaceKHR(Instance, GlfwWindowManager::Surface, nullptr);
|
||||
vkDestroyDevice(Device, nullptr);
|
||||
}
|
||||
|
||||
void VulkanDeviceManager::PickPhysicalDevice()
|
||||
@@ -50,7 +93,7 @@ void VulkanDeviceManager::PickPhysicalDevice()
|
||||
|
||||
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);
|
||||
@@ -60,30 +103,39 @@ void VulkanDeviceManager::PickPhysicalDevice()
|
||||
|
||||
for (const auto& Device : Devices)
|
||||
{
|
||||
int Score = RateDeviceSuitability(Device);
|
||||
Candidates.insert(std::make_pair(Score, Device));
|
||||
if (IsDeviceSuitable(Device))
|
||||
{
|
||||
int Score = RateDeviceSuitability(Device);
|
||||
Candidates.insert(std::make_pair(Score, Device));
|
||||
}
|
||||
}
|
||||
|
||||
if (Candidates.rbegin()->first > 0)
|
||||
{
|
||||
PhysicalDevice = Candidates.rbegin()->second;
|
||||
Log::Info("Suitable GPU found.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::Error("Failed to find a suitable GPU");
|
||||
Log::Error("Failed to find a suitable GPU.");
|
||||
}
|
||||
}
|
||||
|
||||
// bool VulkanDeviceManager::IsDeviceSuitable(VkPhysicalDevice Device)
|
||||
//{
|
||||
// VkPhysicalDeviceProperties DeviceProperties;
|
||||
// vkGetPhysicalDeviceProperties(Device, &DeviceProperties);
|
||||
//
|
||||
// VkPhysicalDeviceFeatures DeviceFeatures;
|
||||
// vkGetPhysicalDeviceFeatures(Device, &DeviceFeatures);
|
||||
//
|
||||
// return DeviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU && DeviceFeatures.geometryShader;
|
||||
// }
|
||||
bool VulkanDeviceManager::IsDeviceSuitable(VkPhysicalDevice Device)
|
||||
{
|
||||
QueueFamilyIndices Indices = FindQueueFamilies(Device);
|
||||
|
||||
bool bExtensionsSupported = CheckDeviceExtensionSupport(Device);
|
||||
|
||||
bool bSwapChainAdequate = false;
|
||||
if (bExtensionsSupported)
|
||||
{
|
||||
SwapChainSupportDetails SwapChainSupport = QuerySwapChainSupport(Device);
|
||||
bSwapChainAdequate = !SwapChainSupport.Formats.empty() && !SwapChainSupport.PresentModes.empty();
|
||||
}
|
||||
|
||||
return Indices.IsComplete() && bExtensionsSupported && bSwapChainAdequate;
|
||||
}
|
||||
|
||||
int VulkanDeviceManager::RateDeviceSuitability(VkPhysicalDevice Device)
|
||||
{
|
||||
@@ -109,3 +161,282 @@ int VulkanDeviceManager::RateDeviceSuitability(VkPhysicalDevice Device)
|
||||
|
||||
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.");
|
||||
}
|
||||
@@ -1,22 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include "Logger.h"
|
||||
|
||||
#define GLFW_INCLUDE_VULKAN
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
// struct FCreateDebugUtilsMessengerExtParams
|
||||
//{
|
||||
// VkInstance Instance;
|
||||
// const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo;
|
||||
// const VkAllocationCallbacks* pAllocator;
|
||||
// VkDebugUtilsMessengerEXT* pDebugMessenger;
|
||||
// };
|
||||
//
|
||||
// struct FDestroyDebugUtilsMessengerExtParams
|
||||
//{
|
||||
// VkInstance Instance;
|
||||
// VkDebugUtilsMessengerEXT DebugMessenger;
|
||||
// const VkAllocationCallbacks* pAllocator;
|
||||
// };
|
||||
const std::vector<const char*> DeviceExtensions = {
|
||||
VK_KHR_SWAPCHAIN_EXTENSION_NAME
|
||||
};
|
||||
|
||||
struct QueueFamilyIndices
|
||||
{
|
||||
std::optional<uint32_t> GraphicsFamily;
|
||||
std::optional<uint32_t> PresentFamily;
|
||||
|
||||
bool IsComplete()
|
||||
{
|
||||
return GraphicsFamily.has_value() && PresentFamily.has_value();
|
||||
}
|
||||
};
|
||||
|
||||
struct SwapChainSupportDetails
|
||||
{
|
||||
VkSurfaceCapabilitiesKHR Capabilities;
|
||||
std::vector<VkSurfaceFormatKHR> Formats;
|
||||
std::vector<VkPresentModeKHR> PresentModes;
|
||||
};
|
||||
|
||||
class VulkanDeviceManager
|
||||
{
|
||||
@@ -30,18 +43,59 @@ public:
|
||||
VulkanDeviceManager(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();
|
||||
|
||||
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:
|
||||
VkPhysicalDevice PhysicalDevice = 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();
|
||||
|
||||
// bool IsDeviceSuitable(VkPhysicalDevice Device);
|
||||
bool IsDeviceSuitable(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
27
VulkanGraphicsPipeline.h
Normal 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))
|
||||
}
|
||||
};
|
||||
@@ -8,11 +8,11 @@ VulkanInstanceManager::VulkanInstanceManager()
|
||||
|
||||
VulkanInstanceManager::~VulkanInstanceManager()
|
||||
{
|
||||
Cleanup();
|
||||
// Cleanup();
|
||||
}
|
||||
|
||||
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.bValidationEnabled = false;
|
||||
@@ -34,7 +34,28 @@ VulkanInstanceManager& VulkanInstanceManager::operator=(VulkanInstanceManager&&
|
||||
|
||||
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())
|
||||
{
|
||||
@@ -42,24 +63,27 @@ void VulkanInstanceManager::Initialize(const FVulkanConfig& Config)
|
||||
return;
|
||||
}
|
||||
|
||||
bValidationEnabled = Config.bValidationEnabled;
|
||||
bVerboseLogging = Config.bVerboseLogging;
|
||||
|
||||
if (bValidationEnabled)
|
||||
if (bEnableValidationLayers)
|
||||
{
|
||||
Log::Info("DebugManager created with validation enabled.");
|
||||
VkDebugManager = std::make_unique<VulkanDebugManager>();
|
||||
}
|
||||
|
||||
CreateInstance();
|
||||
}
|
||||
|
||||
if (VkDebugManager)
|
||||
void VulkanInstanceManager::SetupDebug()
|
||||
{
|
||||
if (bValidationEnabled)
|
||||
{
|
||||
VkDebugManager->Initialize(Instance);
|
||||
}
|
||||
}
|
||||
|
||||
void VulkanInstanceManager::SetupDevice()
|
||||
{
|
||||
VkDeviceManager = std::make_unique<VulkanDeviceManager>();
|
||||
VkDeviceManager->Initialize(Instance);
|
||||
VkDeviceManager->Initialize(Instance, bValidationEnabled, ValidationLayers);
|
||||
}
|
||||
|
||||
void VulkanInstanceManager::Cleanup()
|
||||
@@ -70,16 +94,16 @@ void VulkanInstanceManager::Cleanup()
|
||||
return;
|
||||
}
|
||||
|
||||
if (VkDebugManager)
|
||||
{
|
||||
VkDebugManager->Cleanup();
|
||||
}
|
||||
|
||||
if (VkDeviceManager)
|
||||
{
|
||||
VkDeviceManager->Cleanup();
|
||||
}
|
||||
|
||||
if (VkDebugManager)
|
||||
{
|
||||
VkDebugManager->Cleanup();
|
||||
}
|
||||
|
||||
vkDestroyInstance(Instance, nullptr);
|
||||
Instance = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
@@ -3,11 +3,13 @@
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
#define GLFW_INCLUDE_VULKAN
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include "Logger.h"
|
||||
#include "VulkanDebugManager.h"
|
||||
#include "VulkanDeviceManager.h"
|
||||
#include "GlfwWindowManager.h"
|
||||
|
||||
#define GLFW_INCLUDE_VULKAN
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
const std::vector<const char*> ValidationLayers = {
|
||||
"VK_LAYER_KHRONOS_validation"
|
||||
@@ -31,11 +33,23 @@ public:
|
||||
VulkanInstanceManager(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();
|
||||
|
||||
bool IsInitialized() const { return Instance != VK_NULL_HANDLE; }
|
||||
|
||||
const std::vector<const char*>& GetValidationLayers() const
|
||||
{
|
||||
return ValidationLayers;
|
||||
}
|
||||
|
||||
const VkInstance GetInstance() const { return Instance; }
|
||||
|
||||
private:
|
||||
std::unique_ptr<VulkanDebugManager> VkDebugManager = nullptr;
|
||||
std::unique_ptr<VulkanDeviceManager> VkDeviceManager = nullptr;
|
||||
|
||||
48
main.cpp
48
main.cpp
@@ -1,7 +1,11 @@
|
||||
|
||||
#include "Logger.h"
|
||||
#include "VulkanInstanceManager.h"
|
||||
#include "VulkanDeviceManager.h"
|
||||
#include "VulkanDebugManager.h"
|
||||
#include "GlfwWindowManager.h"
|
||||
#include "VulkanGraphicsPipeline.h"
|
||||
// #include "VulkanContext.h"
|
||||
|
||||
struct AppConfig
|
||||
{
|
||||
@@ -19,41 +23,59 @@ class HelloTriangleApplication
|
||||
public:
|
||||
void Run()
|
||||
{
|
||||
InitGlfw();
|
||||
InitVulkan();
|
||||
Initialization();
|
||||
MainLoop();
|
||||
Cleanup();
|
||||
}
|
||||
|
||||
private:
|
||||
VulkanInstanceManager VkInstanceManager;
|
||||
GlfwWindowManager GlfwWindowManager;
|
||||
AppConfig Settings = {};
|
||||
AppConfig Settings = {};
|
||||
|
||||
VulkanInstanceManager InstanceManager;
|
||||
GlfwWindowManager WindowManager;
|
||||
|
||||
void Initialization()
|
||||
{
|
||||
InitGlfw();
|
||||
InitVulkan();
|
||||
InstanceManager.SetupDebug();
|
||||
WindowManager.CreateSurface(InstanceManager.GetInstance());
|
||||
InstanceManager.SetupDevice();
|
||||
}
|
||||
|
||||
void InitVulkan()
|
||||
{
|
||||
FVulkanConfig Config = { Settings.bValidationEnabled, Settings.bVerboseLogging };
|
||||
VkInstanceManager.Initialize(Config);
|
||||
FVulkanConfig Config = {
|
||||
Settings.bValidationEnabled,
|
||||
Settings.bVerboseLogging
|
||||
};
|
||||
InstanceManager.Initialize(Config);
|
||||
}
|
||||
|
||||
void InitGlfw()
|
||||
{
|
||||
FWindowConfig Config = { Settings.Title, Settings.Width, Settings.Height, Settings.bResizable, Settings.bFullscreen };
|
||||
GlfwWindowManager.Initialize(Config);
|
||||
FWindowConfig Config = {
|
||||
Settings.Title,
|
||||
Settings.Width,
|
||||
Settings.Height,
|
||||
Settings.bResizable,
|
||||
Settings.bFullscreen
|
||||
};
|
||||
WindowManager.Initialize(Config);
|
||||
}
|
||||
|
||||
void MainLoop()
|
||||
{
|
||||
while (!GlfwWindowManager.ShouldClose())
|
||||
while (!WindowManager.ShouldClose())
|
||||
{
|
||||
GlfwWindowManager.PollEvents();
|
||||
WindowManager.PollEvents();
|
||||
}
|
||||
}
|
||||
|
||||
void Cleanup()
|
||||
{
|
||||
// VkInstanceManager.Cleanup();
|
||||
// GlfwWindowManager.Cleanup();
|
||||
WindowManager.Cleanup(InstanceManager.GetInstance());
|
||||
InstanceManager.Cleanup();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user