Add Device and Window abstraction

This commit is contained in:
Thraix
2023-03-04 23:02:42 +01:00
parent 1e7d08250e
commit c975ed2674
47 changed files with 854 additions and 614 deletions
+34 -25
View File
@@ -2,6 +2,10 @@
#include "copium/mesh/Vertex.h"
#include "copium/mesh/VertexPassthrough.h"
#include "copium/core/Device.h"
#include "copium/core/Instance.h"
#include "copium/core/SwapChain.h"
#include "copium/core/Window.h"
#include <glm/gtc/matrix_transform.hpp>
@@ -44,7 +48,7 @@ namespace Copium
Application::Application()
{
InitializeInstance();
InitializeVulkan();
InitializeFrameBuffer();
InitializeGraphicsPipeline();
InitializeTextureSampler();
@@ -56,56 +60,61 @@ namespace Copium
Application::~Application()
{
vkDeviceWaitIdle(instance->GetDevice());
vkDeviceWaitIdle(vulkan->GetDevice());
}
bool Application::Update()
{
if (framebuffer->GetWidth() != instance->GetSwapChain().GetExtent().width || framebuffer->GetHeight() != instance->GetSwapChain().GetExtent().height)
if (framebuffer->GetWidth() != vulkan->GetSwapChain().GetExtent().width || framebuffer->GetHeight() != vulkan->GetSwapChain().GetExtent().height)
{
framebuffer->Resize(instance->GetSwapChain().GetExtent().width / 8, instance->GetSwapChain().GetExtent().height / 8);
framebuffer->Resize(vulkan->GetSwapChain().GetExtent().width / 8, vulkan->GetSwapChain().GetExtent().height / 8);
descriptorSetPassthrough->AddSampler(framebuffer->GetColorAttachment(), 0);
}
if (!instance->BeginPresent())
{
if (!vulkan->GetSwapChain().BeginPresent())
return true;
}
RecordCommandBuffer();
commandBuffer->SubmitAsGraphicsQueue();
vulkan->GetSwapChain().SubmitToGraphicsQueue(*commandBuffer);
return instance->EndPresent();
vulkan->GetSwapChain().EndPresent();
return !glfwWindowShouldClose(vulkan->GetWindow().GetWindow());
}
void Application::InitializeInstance()
void Application::InitializeVulkan()
{
instance = std::make_unique<Instance>("Copium Engine");
vulkan = std::make_unique<Vulkan>();
vulkan->SetInstance(std::make_unique<Instance>("Copium Engine"));
vulkan->SetWindow(std::make_unique<Window>(*vulkan, "Copium Engine", 1920, 1080, Window::Mode::Windowed));
vulkan->SetDevice(std::make_unique<Device>(*vulkan));
vulkan->SetSwapChain(std::make_unique<SwapChain>(*vulkan));
CP_ASSERT(vulkan->Valid(), "Vulkan Manager was not initialized correctly");
}
void Application::InitializeFrameBuffer()
{
framebuffer = std::make_unique<Framebuffer>(*instance, instance->GetSwapChain().GetExtent().width, instance->GetSwapChain().GetExtent().height);
framebuffer = std::make_unique<Framebuffer>(*vulkan, vulkan->GetSwapChain().GetExtent().width, vulkan->GetSwapChain().GetExtent().height);
}
void Application::InitializeTextureSampler()
{
texture2D = std::make_unique<Texture2D>(*instance, "res/textures/texture.png");
texture2D = std::make_unique<Texture2D>(*vulkan, "res/textures/texture.png");
}
void Application::InitializeUniformBuffer()
{
shaderUniformBuffer = std::make_unique<UniformBuffer>(*instance, sizeof(ShaderUniform));
shaderUniformBuffer = std::make_unique<UniformBuffer>(*vulkan, sizeof(ShaderUniform));
}
void Application::InitializeDescriptorSets()
{
descriptorPool = std::make_unique<DescriptorPool>(*instance);
descriptorPool = std::make_unique<DescriptorPool>(*vulkan);
descriptorSet = std::make_unique<DescriptorSet>(*instance, *descriptorPool, graphicsPipeline->GetDescriptorSetLayout(0));
descriptorSet = std::make_unique<DescriptorSet>(*vulkan, *descriptorPool, graphicsPipeline->GetDescriptorSetLayout(0));
descriptorSet->AddUniform(*shaderUniformBuffer, 0);
descriptorSet->AddSampler(*texture2D, 1);
descriptorSetPassthrough = std::make_unique<DescriptorSet>(*instance, *descriptorPool, graphicsPipelinePassthrough->GetDescriptorSetLayout(0));
descriptorSetPassthrough = std::make_unique<DescriptorSet>(*vulkan, *descriptorPool, graphicsPipelinePassthrough->GetDescriptorSetLayout(0));
descriptorSetPassthrough->AddSampler(framebuffer->GetColorAttachment(), 0);
}
@@ -116,24 +125,24 @@ namespace Copium
creator.AddDescriptorSetLayoutBinding(0, 1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
creator.SetVertexDescriptor(Vertex::GetDescriptor());
creator.SetCullMode(VK_CULL_MODE_NONE);
graphicsPipeline = std::make_unique<Pipeline>(*instance, creator);
graphicsPipeline = std::make_unique<Pipeline>(*vulkan, creator);
PipelineCreator creatorPassthrough{instance->GetSwapChain().GetRenderPass(), "res/shaders/passthrough.vert", "res/shaders/passthrough.frag"};
PipelineCreator creatorPassthrough{vulkan->GetSwapChain().GetRenderPass(), "res/shaders/passthrough.vert", "res/shaders/passthrough.frag"};
creatorPassthrough.AddDescriptorSetLayoutBinding(0, 0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
creatorPassthrough.SetVertexDescriptor(VertexPassthrough::GetDescriptor());
creatorPassthrough.SetCullMode(VK_CULL_MODE_NONE);
graphicsPipelinePassthrough = std::make_unique<Pipeline>(*instance, creatorPassthrough);
graphicsPipelinePassthrough = std::make_unique<Pipeline>(*vulkan, creatorPassthrough);
}
void Application::InitializeMesh()
{
mesh = std::make_unique<Mesh>(*instance, vertices, indices);
meshPassthrough = std::make_unique<Mesh>(*instance, verticesPassthrough, indicesPassthrough);
mesh = std::make_unique<Mesh>(*vulkan, vertices, indices);
meshPassthrough = std::make_unique<Mesh>(*vulkan, verticesPassthrough, indicesPassthrough);
}
void Application::InitializeCommandBuffer()
{
commandBuffer = std::make_unique<CommandBuffer>(*instance, CommandBuffer::Type::Dynamic);
commandBuffer = std::make_unique<CommandBuffer>(*vulkan, CommandBuffer::Type::Dynamic);
}
void Application::RecordCommandBuffer()
@@ -153,7 +162,7 @@ namespace Copium
framebuffer->Unbind(*commandBuffer);
instance->GetSwapChain().BeginFrameBuffer(*commandBuffer);
vulkan->GetSwapChain().BeginFrameBuffer(*commandBuffer);
graphicsPipelinePassthrough->Bind(*commandBuffer);
graphicsPipelinePassthrough->SetDescriptorSet(0, *descriptorSetPassthrough);
@@ -162,7 +171,7 @@ namespace Copium
meshPassthrough->Bind(*commandBuffer);
meshPassthrough->Render(*commandBuffer);
instance->GetSwapChain().EndFrameBuffer(*commandBuffer);
vulkan->GetSwapChain().EndFrameBuffer(*commandBuffer);
commandBuffer->End();
}
+4 -2
View File
@@ -4,7 +4,9 @@
#include "copium/buffer/IndexBuffer.h"
#include "copium/buffer/UniformBuffer.h"
#include "copium/buffer/VertexBuffer.h"
#include "copium/core/Device.h"
#include "copium/core/Instance.h"
#include "copium/core/Vulkan.h"
#include "copium/mesh/Mesh.h"
#include "copium/pipeline/DescriptorPool.h"
#include "copium/pipeline/DescriptorSet.h"
@@ -17,6 +19,7 @@ namespace Copium
{
CP_DELETE_COPY_AND_MOVE_CTOR(Application);
private:
std::unique_ptr<Vulkan> vulkan;
std::unique_ptr<Instance> instance;
std::unique_ptr<Framebuffer> framebuffer;
std::unique_ptr<Texture2D> texture2D;
@@ -30,14 +33,13 @@ namespace Copium
std::unique_ptr<Mesh> meshPassthrough;
std::unique_ptr<CommandBuffer> commandBuffer;
public:
Application();
~Application();
bool Update();
private:
void InitializeInstance();
void InitializeVulkan();
void InitializeFrameBuffer();
void InitializeTextureSampler();
void InitializeUniformBuffer();
+189
View File
@@ -0,0 +1,189 @@
#include "Device.h"
#include "copium/core/Instance.h"
#include "copium/core/SwapChain.h"
#include "copium/core/Window.h"
namespace Copium
{
Device::Device(Vulkan& vulkan)
: vulkan{vulkan}
{
SelectPhysicalDevice();
InitializeLogicalDevice();
InitializeCommandPool();
}
Device::~Device()
{
vkDestroyCommandPool(device, commandPool, nullptr);
vkDestroyDevice(device, nullptr);
}
VkQueue Device::GetGraphicsQueue() const
{
return graphicsQueue;
}
VkQueue Device::GetPresentQueue() const
{
return presentQueue;
}
VkCommandPool Device::GetCommandPool() const
{
return commandPool;
}
VkPhysicalDevice Device::GetPhysicalDevice() const
{
return physicalDevice;
}
Device::operator VkDevice() const
{
return device;
}
uint32_t Device::FindMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties)
{
VkPhysicalDeviceMemoryProperties memoryProperties;
vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memoryProperties);
for (uint32_t i = 0; i < memoryProperties.memoryTypeCount; ++i)
{
if ((typeFilter & (1 << i)) && (memoryProperties.memoryTypes[i].propertyFlags & properties) == properties)
return i;
}
CP_ABORT("FindMemoryType : Failed to find suitable memory type");
}
void Device::SelectPhysicalDevice()
{
uint32_t deviceCount;
vkEnumeratePhysicalDevices(vulkan.GetInstance(), &deviceCount, nullptr);
CP_ASSERT(deviceCount != 0, "SelectPhysicaDevice : No available devices support Vulkan");
std::vector<VkPhysicalDevice> devices(deviceCount);
vkEnumeratePhysicalDevices(vulkan.GetInstance(), &deviceCount, devices.data());
CP_INFO("SelectPhysicaDevice : Available devices:");
for (auto&& device : devices)
{
VkPhysicalDeviceProperties deviceProperties;
vkGetPhysicalDeviceProperties(device, &deviceProperties);
CP_INFO_CONT("\t%s", deviceProperties.deviceName);
}
for (auto&& device : devices)
{
if (IsPhysicalDeviceSuitable(device))
{
VkPhysicalDeviceProperties deviceProperties;
vkGetPhysicalDeviceProperties(device, &deviceProperties);
physicalDevice = device;
CP_INFO("SelectPhysicaDevice : Selecting device: %s", deviceProperties.deviceName);
break;
}
}
CP_ASSERT(physicalDevice != VK_NULL_HANDLE, "SelectPhysicaDevice : Failed to find suitable GPU");
}
void Device::InitializeLogicalDevice()
{
QueueFamiliesQuery query{vulkan.GetWindow().GetSurface(), physicalDevice};
float queuePriority = 1.0f;
std::vector<VkDeviceQueueCreateInfo> queueCreateInfos{};
std::set<uint32_t> uniqueQueueFamilies{query.graphicsFamily.value(), query.presentFamily.value()};
for (auto&& queueFamily : uniqueQueueFamilies)
{
VkDeviceQueueCreateInfo queueCreateInfo{};
queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queueCreateInfo.queueFamilyIndex = queueFamily;
queueCreateInfo.queueCount = 1;
queueCreateInfo.pQueuePriorities = &queuePriority;
queueCreateInfos.emplace_back(queueCreateInfo);
}
std::vector<const char*> deviceExtensions = GetRequiredDeviceExtensions();
VkPhysicalDeviceFeatures deviceFeatures{};
deviceFeatures.fillModeNonSolid = VK_TRUE;
deviceFeatures.samplerAnisotropy = VK_TRUE;
VkDeviceCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
createInfo.pQueueCreateInfos = queueCreateInfos.data();
createInfo.queueCreateInfoCount = queueCreateInfos.size();
createInfo.pEnabledFeatures = &deviceFeatures;
createInfo.ppEnabledExtensionNames = deviceExtensions.data();
createInfo.enabledExtensionCount = deviceExtensions.size();
CP_VK_ASSERT(vkCreateDevice(physicalDevice, &createInfo, nullptr, &device), "InitializeLogicalDevice : Failed to initialize logical device");
graphicsQueueIndex = query.graphicsFamily.value();
presentQueueIndex = query.presentFamily.value();
vkGetDeviceQueue(device, graphicsQueueIndex, 0, &graphicsQueue);
vkGetDeviceQueue(device, presentQueueIndex, 0, &presentQueue);
}
void Device::InitializeCommandPool()
{
VkCommandPoolCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
createInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
createInfo.queueFamilyIndex = graphicsQueueIndex;
CP_VK_ASSERT(vkCreateCommandPool(device, &createInfo, nullptr, &commandPool), "InitializeCommandPool : Failed to initialize command pool");
}
bool Device::IsPhysicalDeviceSuitable(VkPhysicalDevice device)
{
VkPhysicalDeviceProperties deviceProperties;
vkGetPhysicalDeviceProperties(device, &deviceProperties);
if (deviceProperties.deviceType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
return false;
VkPhysicalDeviceFeatures deviceFeatures;
vkGetPhysicalDeviceFeatures(device, &deviceFeatures);
if (!deviceFeatures.fillModeNonSolid || !deviceFeatures.samplerAnisotropy)
return false;
QueueFamiliesQuery query{vulkan.GetWindow().GetSurface(), device};
if (!query.AllRequiredFamiliesSupported())
return false;
if (!CheckDeviceExtensionSupport(device))
return false;
SwapChainSupportDetails details{vulkan.GetWindow().GetSurface(), device};
if (!details.Valid())
return false;
return true;
}
bool Device::CheckDeviceExtensionSupport(VkPhysicalDevice device)
{
uint32_t extensionCount;
vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr);
std::vector<VkExtensionProperties> extensions{extensionCount};
vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, extensions.data());
for (auto&& requiredExtension : GetRequiredDeviceExtensions())
{
bool found = false;
for (auto&& extension : extensions)
{
if (std::strcmp(requiredExtension, extension.extensionName) == 0)
{
found = true;
break;
}
}
if (!found)
return false;
}
return true;
}
std::vector<const char*> Device::GetRequiredDeviceExtensions()
{
return {VK_KHR_SWAPCHAIN_EXTENSION_NAME};
}
}
+48
View File
@@ -0,0 +1,48 @@
#pragma once
#include "copium/core/QueueFamilies.h"
#include "copium/core/Vulkan.h"
#include "copium/util/Common.h"
#include <vulkan/vulkan.hpp>
namespace Copium
{
class Vulkan;
class Device
{
CP_DELETE_COPY_AND_MOVE_CTOR(Device);
private:
Vulkan& vulkan;
VkPhysicalDevice physicalDevice;
VkDevice device;
VkCommandPool commandPool;
// TODO: Move to SwapChain?
uint32_t graphicsQueueIndex;
uint32_t presentQueueIndex;
VkQueue graphicsQueue;
VkQueue presentQueue;
// TODO end
public:
Device(Vulkan& vulkan);
~Device();
VkQueue GetGraphicsQueue() const;
VkQueue GetPresentQueue() const;
VkCommandPool GetCommandPool() const;
VkPhysicalDevice GetPhysicalDevice() const;
operator VkDevice() const;
uint32_t FindMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties);
private:
void SelectPhysicalDevice();
void InitializeLogicalDevice();
void InitializeCommandPool();
bool IsPhysicalDeviceSuitable(VkPhysicalDevice device);
bool CheckDeviceExtensionSupport(VkPhysicalDevice device);
std::vector<const char*> GetRequiredDeviceExtensions();
};
}
+4 -294
View File
@@ -1,6 +1,7 @@
#include "Instance.h"
#include "copium/core/QueueFamilies.h"
#include "copium/core/SwapChain.h"
#include "copium/util/Common.h"
namespace Copium
@@ -8,126 +9,15 @@ namespace Copium
Instance::Instance(const std::string& applicationName)
{
timer.Start();
InitializeWindow(applicationName);
InitializeInstance(applicationName);
InitializeDebugMessenger();
InitializeSurface();
SelectPhysicalDevice();
InitializeLogicalDevice();
InitializeCommandPool();
InitializeSwapChain();
InitializeSyncObjects();
CP_INFO("Instance : Initialized Vulkan in %f seconds", timer.Elapsed());
}
Instance::~Instance()
{
for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i)
{
vkDestroyFence(device, inFlightFences[i], nullptr);
vkDestroySemaphore(device, renderFinishedSemaphores[i], nullptr);
vkDestroySemaphore(device, imageAvailableSemaphores[i], nullptr);
}
vkDestroyCommandPool(device, commandPool, nullptr);
swapChain.reset();
vkDestroyDevice(device, nullptr);
vkDestroySurfaceKHR(instance, surface, nullptr);
debugMessenger.reset();
vkDestroyInstance(instance, nullptr);
glfwDestroyWindow(window);
}
bool Instance::BeginPresent()
{
vkWaitForFences(device, 1, &inFlightFences[flightIndex], VK_TRUE, UINT64_MAX);
if (!swapChain->BeginPresent(imageAvailableSemaphores[flightIndex]))
return false;
vkResetFences(device, 1, &inFlightFences[flightIndex]);
return true;
}
bool Instance::EndPresent()
{
swapChain->EndPresent(presentQueue, &renderFinishedSemaphores[flightIndex], framebufferResized);
framebufferResized = false;
flightIndex = (flightIndex + 1) % MAX_FRAMES_IN_FLIGHT;
return !glfwWindowShouldClose(window);
}
void Instance::SubmitGraphicsQueue(const std::vector<VkCommandBuffer>& commandBuffers)
{
VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
VkSubmitInfo submitInfo{};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.waitSemaphoreCount = 1;
submitInfo.pWaitSemaphores = &imageAvailableSemaphores[flightIndex];
submitInfo.pWaitDstStageMask = waitStages;
submitInfo.commandBufferCount = commandBuffers.size();
submitInfo.pCommandBuffers = commandBuffers.data();
submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = &renderFinishedSemaphores[flightIndex];
CP_VK_ASSERT(vkQueueSubmit(graphicsQueue, 1, &submitInfo, inFlightFences[flightIndex]), "SubmitGraphicsQueue : Failed to submit command buffer");
}
GLFWwindow* Instance::GetWindow() const
{
return window;
}
VkSurfaceKHR Instance::GetSurface() const
{
return surface;
}
VkPhysicalDevice Instance::GetPhysicalDevice() const
{
return physicalDevice;
}
VkDevice Instance::GetDevice() const
{
return device;
}
VkCommandPool Instance::GetCommandPool() const
{
return commandPool;
}
VkQueue Instance::GetGraphicsQueue() const
{
return graphicsQueue;
}
int Instance::GetFlightIndex() const
{
return flightIndex;
}
int Instance::GetMaxFramesInFlight() const
{
return MAX_FRAMES_IN_FLIGHT;
}
const SwapChain& Instance::GetSwapChain() const
{
return *swapChain;
}
uint32_t Instance::FindMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties)
{
VkPhysicalDeviceMemoryProperties memoryProperties;
vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memoryProperties);
for (uint32_t i = 0; i < memoryProperties.memoryTypeCount; ++i)
{
if ((typeFilter & (1 << i)) && (memoryProperties.memoryTypes[i].propertyFlags & properties) == properties)
return i;
}
CP_ABORT("FindMemoryType : Failed to find suitable memory type");
}
Instance::operator VkInstance() const
@@ -135,29 +25,6 @@ namespace Copium
return instance;
}
void Instance::InitializeWindow(const std::string& applicationName)
{
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
#if defined(FULLSCREEN)
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
window = glfwCreateWindow(mode->width, mode->height, applicationName.c_str(), glfwGetPrimaryMonitor(), nullptr);
#elif defined(BORDERLESS_WINDOWED)
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
window = glfwCreateWindow(mode->width, mode->height, applicationName.c_str(), nullptr, nullptr);
glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height, mode->refreshRate);
#else
window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, applicationName.c_str(), nullptr, nullptr);
#endif
CP_ASSERT(window, "InitializeWindow : Failed to initialize glfw window");
glfwSetWindowUserPointer(window, this);
glfwSetFramebufferSizeCallback(window, FramebufferResizeCallback);
}
void Instance::InitializeInstance(const std::string& applicationName)
{
VkApplicationInfo appInfo{};
@@ -200,111 +67,6 @@ namespace Copium
debugMessenger = std::make_unique<DebugMessenger>(*this);
}
void Instance::InitializeSurface()
{
CP_VK_ASSERT(glfwCreateWindowSurface(instance, window, nullptr, &surface), "InitializeSurface : Failed to create Vulkan surface");
}
void Instance::SelectPhysicalDevice()
{
uint32_t deviceCount;
vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr);
CP_ASSERT(deviceCount != 0, "SelectPhysicaDevice : No available devices support Vulkan");
std::vector<VkPhysicalDevice> devices(deviceCount);
vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data());
CP_INFO("SelectPhysicaDevice : Available devices:");
for (auto&& device : devices)
{
VkPhysicalDeviceProperties deviceProperties;
vkGetPhysicalDeviceProperties(device, &deviceProperties);
CP_INFO_CONT("\t%s", deviceProperties.deviceName);
}
for (auto&& device : devices)
{
if (IsPhysicalDeviceSuitable(device))
{
VkPhysicalDeviceProperties deviceProperties;
vkGetPhysicalDeviceProperties(device, &deviceProperties);
physicalDevice = device;
CP_INFO("SelectPhysicaDevice : Selecting device: %s", deviceProperties.deviceName);
break;
}
}
CP_ASSERT(physicalDevice != VK_NULL_HANDLE, "SelectPhysicaDevice : Failed to find suitable GPU");
}
void Instance::InitializeLogicalDevice()
{
QueueFamiliesQuery query{surface, physicalDevice};
float queuePriority = 1.0f;
std::vector<VkDeviceQueueCreateInfo> queueCreateInfos{};
std::set<uint32_t> uniqueQueueFamilies{query.graphicsFamily.value(), query.presentFamily.value()};
for (auto&& queueFamily : uniqueQueueFamilies)
{
VkDeviceQueueCreateInfo queueCreateInfo{};
queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queueCreateInfo.queueFamilyIndex = queueFamily;
queueCreateInfo.queueCount = 1;
queueCreateInfo.pQueuePriorities = &queuePriority;
queueCreateInfos.emplace_back(queueCreateInfo);
}
std::vector<const char*> deviceExtensions = GetRequiredDeviceExtensions();
VkPhysicalDeviceFeatures deviceFeatures{};
deviceFeatures.fillModeNonSolid = VK_TRUE;
deviceFeatures.samplerAnisotropy = VK_TRUE;
VkDeviceCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
createInfo.pQueueCreateInfos = queueCreateInfos.data();
createInfo.queueCreateInfoCount = queueCreateInfos.size();
createInfo.pEnabledFeatures = &deviceFeatures;
createInfo.ppEnabledExtensionNames = deviceExtensions.data();
createInfo.enabledExtensionCount = deviceExtensions.size();
CP_VK_ASSERT(vkCreateDevice(physicalDevice, &createInfo, nullptr, &device), "InitializeLogicalDevice : Failed to initialize logical device");
graphicsQueueIndex = query.graphicsFamily.value();
presentQueueIndex = query.presentFamily.value();
vkGetDeviceQueue(device, graphicsQueueIndex, 0, &graphicsQueue);
vkGetDeviceQueue(device, presentQueueIndex, 0, &presentQueue);
}
void Instance::InitializeSwapChain()
{
swapChain = std::make_unique<SwapChain>(*this);
}
void Instance::InitializeCommandPool()
{
VkCommandPoolCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
createInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
createInfo.queueFamilyIndex = graphicsQueueIndex;
CP_VK_ASSERT(vkCreateCommandPool(device, &createInfo, nullptr, &commandPool), "InitializeCommandPool : Failed to initialize command pool");
}
void Instance::InitializeSyncObjects()
{
imageAvailableSemaphores.resize(MAX_FRAMES_IN_FLIGHT);
renderFinishedSemaphores.resize(MAX_FRAMES_IN_FLIGHT);
inFlightFences.resize(MAX_FRAMES_IN_FLIGHT);
VkSemaphoreCreateInfo semaphoreCreateInfo{};
semaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i)
{
CP_VK_ASSERT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &imageAvailableSemaphores[i]), "InitializeSyncObjects : Failed to initialize available image semaphore");
CP_VK_ASSERT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &renderFinishedSemaphores[i]), "InitializeSyncObjects : Failed to initialize render finished semaphore");
VkFenceCreateInfo fenceCreateInfo{};
fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
fenceCreateInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
CP_VK_ASSERT(vkCreateFence(device, &fenceCreateInfo, nullptr, &inFlightFences[i]), "InitializeSyncObjects : Failed to initialize in flight fence");
}
}
std::vector<const char*> Instance::GetRequiredExtensions()
{
uint32_t glfwExtensionCount;
@@ -349,63 +111,11 @@ namespace Copium
return true;
}
bool Instance::IsPhysicalDeviceSuitable(VkPhysicalDevice device)
{
VkPhysicalDeviceProperties deviceProperties;
vkGetPhysicalDeviceProperties(device, &deviceProperties);
if (deviceProperties.deviceType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
return false;
VkPhysicalDeviceFeatures deviceFeatures;
vkGetPhysicalDeviceFeatures(device, &deviceFeatures);
if (!deviceFeatures.fillModeNonSolid || !deviceFeatures.samplerAnisotropy)
return false;
QueueFamiliesQuery query{surface, device};
if (!query.AllRequiredFamiliesSupported())
return false;
if (!CheckDeviceExtensionSupport(device))
return false;
SwapChainSupportDetails details{surface, device};
if (!details.Valid())
return false;
return true;
}
bool Instance::CheckDeviceExtensionSupport(VkPhysicalDevice device)
{
uint32_t extensionCount;
vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr);
std::vector<VkExtensionProperties> extensions{extensionCount};
vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, extensions.data());
for (auto&& requiredExtension : GetRequiredDeviceExtensions())
{
bool found = false;
for (auto&& extension : extensions)
{
if (std::strcmp(requiredExtension, extension.extensionName) == 0)
{
found = true;
break;
}
}
if (!found)
return false;
}
return true;
}
std::vector<const char*> Instance::GetRequiredDeviceExtensions()
{
return {VK_KHR_SWAPCHAIN_EXTENSION_NAME};
}
void Instance::FramebufferResizeCallback(GLFWwindow* window, int width, int height)
{
Instance* instance = static_cast<Instance*>(glfwGetWindowUserPointer(window));
instance->framebufferResized = true;
// TODO: Fix swap chain resizing again
// instance->swapChain->ResizeFramebuffer(); // TODO: Should maybe be handled by an event system?
CP_UNIMPLEMENTED("Framebuffer resizing currently not supported");
}
}
+3 -42
View File
@@ -1,7 +1,6 @@
#pragma once
#include "copium/core/DebugMessenger.h"
#include "copium/core/SwapChain.h"
#include "copium/util/Timer.h"
#include <vulkan/vulkan.hpp>
@@ -14,67 +13,29 @@ namespace Copium
{
CP_DELETE_COPY_AND_MOVE_CTOR(Instance);
private:
static const int MAX_FRAMES_IN_FLIGHT = 2;
static const int WINDOW_WIDTH = 1920;
static const int WINDOW_HEIGHT = 1080;
VkInstance instance;
GLFWwindow* window;
VkSurfaceKHR surface;
std::unique_ptr<DebugMessenger> debugMessenger;
VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
VkDevice device;
// TODO: Move to SwapChain?
uint32_t graphicsQueueIndex;
uint32_t presentQueueIndex;
VkQueue graphicsQueue;
VkQueue presentQueue;
std::unique_ptr<SwapChain> swapChain;
int flightIndex;
std::vector<VkSemaphore> imageAvailableSemaphores;
std::vector<VkSemaphore> renderFinishedSemaphores;
std::vector<VkFence> inFlightFences;
VkCommandPool commandPool;
bool framebufferResized = false;
// TODO end
int frameCount = 0;
Timer timer;
public:
Instance(const std::string& applicationName);
~Instance();
bool BeginPresent();
bool EndPresent();
void SubmitGraphicsQueue(const std::vector<VkCommandBuffer>& commandBuffers);
GLFWwindow* GetWindow() const;
VkSurfaceKHR GetSurface() const;
VkPhysicalDevice GetPhysicalDevice() const;
VkDevice GetDevice() const;
VkCommandPool GetCommandPool() const;
VkQueue GetGraphicsQueue() const;
int GetFlightIndex() const;
int GetMaxFramesInFlight() const;
const SwapChain& GetSwapChain() const;
// TODO: Create Device class and move this there
uint32_t FindMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties);
operator VkInstance() const;
private:
void InitializeWindow(const std::string& applicationName);
void InitializeInstance(const std::string& applicationName);
void InitializeDebugMessenger();
void InitializeSurface();
void SelectPhysicalDevice();
void InitializeLogicalDevice();
void InitializeSwapChain();
void InitializeCommandPool();
void InitializeSyncObjects();
std::vector<const char*> GetRequiredExtensions();
bool CheckLayerSupport(const std::vector<const char*>& layers);
bool IsPhysicalDeviceSuitable(VkPhysicalDevice device);
bool CheckDeviceExtensionSupport(VkPhysicalDevice device);
std::vector<const char*> GetRequiredDeviceExtensions();
static void FramebufferResizeCallback(GLFWwindow* window, int width, int height);
};
}
+89 -33
View File
@@ -1,15 +1,11 @@
#include "copium/core/SwapChain.h"
#include "copium/buffer/CommandBuffer.h"
#include "copium/core/Device.h"
#include "copium/core/Instance.h"
#include "copium/core/QueueFamilies.h"
#include "copium/sampler/DepthAttachment.h"
#include "copium/core/Window.h"
#include "copium/sampler/Image.h"
#include <glfw/glfw3.h>
#include <vector>
#include <vulkan/vulkan.h>
namespace Copium
{
SwapChainSupportDetails::SwapChainSupportDetails(VkSurfaceKHR surface, VkPhysicalDevice physicalDevice)
@@ -38,20 +34,27 @@ namespace Copium
return !formats.empty() && !presentModes.empty();
}
SwapChain::SwapChain(Instance& instance)
: instance{instance}
SwapChain::SwapChain(Vulkan& vulkan)
: vulkan{vulkan}
{
Initialize();
InitializeImageViews();
InitializeDepthAttachment();
InitializeRenderPass();
InitializeFramebuffers();
InitializeSyncObjects();
}
SwapChain::~SwapChain()
{
for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i)
{
vkDestroyFence(vulkan.GetDevice(), inFlightFences[i], nullptr);
vkDestroySemaphore(vulkan.GetDevice(), renderFinishedSemaphores[i], nullptr);
vkDestroySemaphore(vulkan.GetDevice(), imageAvailableSemaphores[i], nullptr);
}
Destroy();
vkDestroyRenderPass(instance.GetDevice(), renderPass, nullptr);
vkDestroyRenderPass(vulkan.GetDevice(), renderPass, nullptr);
}
void SwapChain::BeginFrameBuffer(const CommandBuffer& commandBuffer) const
@@ -109,47 +112,75 @@ namespace Copium
return framebuffers[imageIndex];
}
bool SwapChain::BeginPresent(VkSemaphore signalSemaphore)
bool SwapChain::BeginPresent()
{
VkResult result = vkAcquireNextImageKHR(instance.GetDevice(), handle, UINT64_MAX, signalSemaphore, VK_NULL_HANDLE, &imageIndex);
vkWaitForFences(vulkan.GetDevice(), 1, &inFlightFences[flightIndex], VK_TRUE, UINT64_MAX);
VkResult result = vkAcquireNextImageKHR(vulkan.GetDevice(), handle, UINT64_MAX, imageAvailableSemaphores[flightIndex], VK_NULL_HANDLE, &imageIndex);
if (result == VK_ERROR_OUT_OF_DATE_KHR)
{
Recreate();
return false;
}
vkResetFences(vulkan.GetDevice(), 1, &inFlightFences[flightIndex]);
return true;
}
void SwapChain::EndPresent(VkQueue presentQueue, VkSemaphore* waitSemaphore, bool framebufferResized)
void SwapChain::SubmitToGraphicsQueue(const CommandBuffer& commandBuffer)
{
VkCommandBuffer cmd = commandBuffer;
VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
VkSubmitInfo submitInfo{};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.waitSemaphoreCount = 1;
submitInfo.pWaitSemaphores = &imageAvailableSemaphores[flightIndex];
submitInfo.pWaitDstStageMask = waitStages;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &cmd;
submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = &renderFinishedSemaphores[flightIndex];
CP_VK_ASSERT(vkQueueSubmit(vulkan.GetDevice().GetGraphicsQueue(), 1, &submitInfo, inFlightFences[flightIndex]), "SubmitGraphicsQueue : Failed to submit command buffer");
}
void SwapChain::EndPresent()
{
VkPresentInfoKHR presentInfo{};
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
presentInfo.waitSemaphoreCount = 1;
presentInfo.pWaitSemaphores = waitSemaphore;
presentInfo.pWaitSemaphores = &renderFinishedSemaphores[flightIndex];
presentInfo.swapchainCount = 1;
presentInfo.pSwapchains = &handle;
presentInfo.pImageIndices = &imageIndex;
presentInfo.pResults = nullptr;
VkResult result = vkQueuePresentKHR(presentQueue, &presentInfo);
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || framebufferResized)
VkResult result = vkQueuePresentKHR(vulkan.GetDevice().GetPresentQueue(), &presentInfo);
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || resizeFramebuffer)
{
Recreate();
resizeFramebuffer = false;
}
flightIndex = (flightIndex + 1) % MAX_FRAMES_IN_FLIGHT;
}
void SwapChain::ResizeFramebuffer()
{
resizeFramebuffer = true;
}
void SwapChain::Recreate()
{
int width = 0;
int height = 0;
glfwGetFramebufferSize(instance.GetWindow(), &width, &height);
glfwGetFramebufferSize(vulkan.GetWindow().GetWindow(), &width, &height);
while (width == 0 || height == 0)
{
glfwGetFramebufferSize(instance.GetWindow(), &width, &height);
glfwGetFramebufferSize(vulkan.GetWindow().GetWindow(), &width, &height);
glfwWaitEvents();
}
vkDeviceWaitIdle(instance.GetDevice());
vkDeviceWaitIdle(vulkan.GetDevice());
Destroy();
@@ -159,13 +190,18 @@ namespace Copium
InitializeFramebuffers();
}
int SwapChain::GetFlightIndex() const
{
return flightIndex;
}
void SwapChain::Initialize()
{
SwapChainSupportDetails swapChainSupport{instance.GetSurface(), instance.GetPhysicalDevice()};
SwapChainSupportDetails swapChainSupport{vulkan.GetWindow().GetSurface(), vulkan.GetDevice().GetPhysicalDevice()};
VkSurfaceFormatKHR format = SelectSwapSurfaceFormat(swapChainSupport.formats);
VkPresentModeKHR presentMode = SelectSwapPresentMode(swapChainSupport.presentModes);
extent = SelectSwapExtent(instance.GetWindow(), swapChainSupport.capabilities);
extent = SelectSwapExtent(vulkan.GetWindow().GetWindow(), swapChainSupport.capabilities);
imageFormat = format.format;
uint32_t imageCount = swapChainSupport.capabilities.minImageCount + 1;
if (swapChainSupport.capabilities.maxImageCount != 0)
@@ -173,12 +209,12 @@ namespace Copium
imageCount = std::min(imageCount, swapChainSupport.capabilities.maxImageCount);
}
QueueFamiliesQuery queueFamilies{instance.GetSurface(), instance.GetPhysicalDevice()};
QueueFamiliesQuery queueFamilies{vulkan.GetWindow().GetSurface(), vulkan.GetDevice().GetPhysicalDevice()};
std::vector<uint32_t> queueFamilyIndices{queueFamilies.graphicsFamily.value(), queueFamilies.presentFamily.value()};
VkSwapchainCreateInfoKHR createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
createInfo.surface = instance.GetSurface();
createInfo.surface = vulkan.GetWindow().GetSurface();
createInfo.minImageCount = imageCount;
createInfo.imageFormat = format.format;
createInfo.imageColorSpace = format.colorSpace;
@@ -203,11 +239,11 @@ namespace Copium
createInfo.pQueueFamilyIndices = nullptr;
}
CP_VK_ASSERT(vkCreateSwapchainKHR(instance.GetDevice(), &createInfo, nullptr, &handle), "Initialize : Failed to initialize the swapchain");
CP_VK_ASSERT(vkCreateSwapchainKHR(vulkan.GetDevice(), &createInfo, nullptr, &handle), "Initialize : Failed to initialize the swapchain");
vkGetSwapchainImagesKHR(instance.GetDevice(), handle, &imageCount, nullptr);
vkGetSwapchainImagesKHR(vulkan.GetDevice(), handle, &imageCount, nullptr);
images.resize(imageCount);
vkGetSwapchainImagesKHR(instance.GetDevice(), handle, &imageCount, images.data());
vkGetSwapchainImagesKHR(vulkan.GetDevice(), handle, &imageCount, images.data());
}
void SwapChain::InitializeImageViews()
@@ -215,13 +251,13 @@ namespace Copium
imageViews.resize(images.size());
for (size_t i = 0; i < images.size(); i++)
{
imageViews[i] = Image::InitializeImageView(instance, images[i], imageFormat, VK_IMAGE_ASPECT_COLOR_BIT);
imageViews[i] = Image::InitializeImageView(vulkan, images[i], imageFormat, VK_IMAGE_ASPECT_COLOR_BIT);
}
}
void SwapChain::InitializeDepthAttachment()
{
depthAttachment = std::make_unique<DepthAttachment>(instance, extent.width, extent.height);
depthAttachment = std::make_unique<DepthAttachment>(vulkan, extent.width, extent.height);
}
void SwapChain::InitializeRenderPass()
@@ -237,7 +273,7 @@ namespace Copium
colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
VkAttachmentDescription depthAttachment{};
depthAttachment.format = Image::SelectDepthFormat(instance);
depthAttachment.format = Image::SelectDepthFormat(vulkan);
depthAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
depthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
depthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
@@ -278,7 +314,7 @@ namespace Copium
renderPassCreateInfo.dependencyCount = 1;
renderPassCreateInfo.pDependencies = &dependency;
CP_VK_ASSERT(vkCreateRenderPass(instance.GetDevice(), &renderPassCreateInfo, nullptr, &renderPass), "InitializeRenderPass : Failed to initialze render pass");
CP_VK_ASSERT(vkCreateRenderPass(vulkan.GetDevice(), &renderPassCreateInfo, nullptr, &renderPass), "InitializeRenderPass : Failed to initialze render pass");
}
void SwapChain::InitializeFramebuffers()
@@ -298,7 +334,27 @@ namespace Copium
createInfo.height = extent.height;
createInfo.layers = 1;
CP_VK_ASSERT(vkCreateFramebuffer(instance.GetDevice(), &createInfo, nullptr, &framebuffers[i]), "InitializeFramebuffers : Failed to initialize swap chain framebuffer");
CP_VK_ASSERT(vkCreateFramebuffer(vulkan.GetDevice(), &createInfo, nullptr, &framebuffers[i]), "InitializeFramebuffers : Failed to initialize swap chain framebuffer");
}
}
void SwapChain::InitializeSyncObjects()
{
imageAvailableSemaphores.resize(MAX_FRAMES_IN_FLIGHT);
renderFinishedSemaphores.resize(MAX_FRAMES_IN_FLIGHT);
inFlightFences.resize(MAX_FRAMES_IN_FLIGHT);
VkSemaphoreCreateInfo semaphoreCreateInfo{};
semaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i)
{
CP_VK_ASSERT(vkCreateSemaphore(vulkan.GetDevice(), &semaphoreCreateInfo, nullptr, &imageAvailableSemaphores[i]), "InitializeSyncObjects : Failed to initialize available image semaphore");
CP_VK_ASSERT(vkCreateSemaphore(vulkan.GetDevice(), &semaphoreCreateInfo, nullptr, &renderFinishedSemaphores[i]), "InitializeSyncObjects : Failed to initialize render finished semaphore");
VkFenceCreateInfo fenceCreateInfo{};
fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
fenceCreateInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
CP_VK_ASSERT(vkCreateFence(vulkan.GetDevice(), &fenceCreateInfo, nullptr, &inFlightFences[i]), "InitializeSyncObjects : Failed to initialize in flight fence");
}
}
@@ -306,13 +362,13 @@ namespace Copium
{
for (auto&& framebuffer : framebuffers)
{
vkDestroyFramebuffer(instance.GetDevice(), framebuffer, nullptr);
vkDestroyFramebuffer(vulkan.GetDevice(), framebuffer, nullptr);
}
for (auto&& swapChainImageView : imageViews)
{
vkDestroyImageView(instance.GetDevice(), swapChainImageView, nullptr);
vkDestroyImageView(vulkan.GetDevice(), swapChainImageView, nullptr);
}
vkDestroySwapchainKHR(instance.GetDevice(), handle, nullptr);
vkDestroySwapchainKHR(vulkan.GetDevice(), handle, nullptr);
}
VkSurfaceFormatKHR SwapChain::SelectSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& availableFormats)
+19 -8
View File
@@ -1,5 +1,8 @@
#pragma once
#include "copium/buffer/CommandBuffer.h"
#include "copium/core/Vulkan.h"
#include "copium/sampler/DepthAttachment.h"
#include "copium/util/Common.h"
#include <GLFW/glfw3.h>
@@ -8,10 +11,6 @@
namespace Copium
{
class Instance;
class CommandBuffer;
class DepthAttachment;
struct SwapChainSupportDetails
{
VkSurfaceCapabilitiesKHR capabilities;
@@ -25,8 +24,10 @@ namespace Copium
class SwapChain final
{
CP_DELETE_COPY_AND_MOVE_CTOR(SwapChain);
public:
static const int MAX_FRAMES_IN_FLIGHT = 2;
private:
Instance& instance;
Vulkan& vulkan;
VkSwapchainKHR handle;
VkRenderPass renderPass;
@@ -37,9 +38,15 @@ namespace Copium
std::vector<VkImage> images;
std::vector<VkFramebuffer> framebuffers;
uint32_t imageIndex;
bool resizeFramebuffer;
int flightIndex;
std::vector<VkSemaphore> imageAvailableSemaphores;
std::vector<VkSemaphore> renderFinishedSemaphores;
std::vector<VkFence> inFlightFences;
public:
SwapChain(Instance& instance);
SwapChain(Vulkan& vulkan);
~SwapChain();
void BeginFrameBuffer(const CommandBuffer& commandBuffer) const;
@@ -48,10 +55,13 @@ namespace Copium
VkRenderPass GetRenderPass() const;
VkExtent2D GetExtent() const;
VkFramebuffer GetFramebuffer() const;
bool BeginPresent(VkSemaphore signalSemaphore);
void EndPresent(VkQueue presentQueue, VkSemaphore* waitSemaphore, bool framebufferResized);
bool BeginPresent();
void SubmitToGraphicsQueue(const CommandBuffer& commandBuffer);
void EndPresent();
void ResizeFramebuffer();
void Recreate();
int GetFlightIndex() const;
private:
void Initialize();
@@ -59,6 +69,7 @@ namespace Copium
void InitializeDepthAttachment();
void InitializeRenderPass();
void InitializeFramebuffers();
void InitializeSyncObjects();
void Destroy();
VkSurfaceFormatKHR SelectSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& availableFormats);
+54
View File
@@ -0,0 +1,54 @@
#include "copium/core/Vulkan.h"
#include "copium/core/Device.h"
#include "copium/core/Instance.h"
#include "copium/core/SwapChain.h"
#include "copium/core/Window.h"
namespace Copium
{
void Vulkan::SetInstance(std::unique_ptr<Instance>&& instance)
{
this->instance = std::move(instance);
}
void Vulkan::SetWindow(std::unique_ptr<Window>&& window)
{
this->window = std::move(window);
}
void Vulkan::SetDevice(std::unique_ptr<Device>&& device)
{
this->device = std::move(device);
}
void Vulkan::SetSwapChain(std::unique_ptr<SwapChain>&& swapChain)
{
this->swapChain = std::move(swapChain);
}
Instance& Vulkan::GetInstance() const
{
return *instance;
}
Window& Vulkan::GetWindow() const
{
return *window;
}
Device& Vulkan::GetDevice() const
{
return *device;
}
SwapChain& Vulkan::GetSwapChain() const
{
return *swapChain;
}
bool Vulkan::Valid()
{
return instance && window && device && swapChain;
}
}
+31
View File
@@ -0,0 +1,31 @@
#pragma once
#include <memory>
namespace Copium
{
class Instance;
class Window;
class Device;
class SwapChain;
class Vulkan
{
private:
std::unique_ptr<Instance> instance;
std::unique_ptr<Window> window;
std::unique_ptr<Device> device;
std::unique_ptr<SwapChain> swapChain;
public:
void SetInstance(std::unique_ptr<Instance>&& instance);
void SetWindow(std::unique_ptr<Window>&& window);
void SetDevice(std::unique_ptr<Device>&& device);
void SetSwapChain(std::unique_ptr<SwapChain>&& swapChain);
Instance& GetInstance() const;
Window& GetWindow() const;
Device& GetDevice() const;
SwapChain& GetSwapChain() const;
bool Valid();
};
}
+78
View File
@@ -0,0 +1,78 @@
#include "copium/core/Window.h"
#include "copium/core/Instance.h"
#include "copium/core/SwapChain.h"
namespace Copium
{
Window::Window(Vulkan& vulkan, const std::string& windowName, int width, int height, Mode mode)
: vulkan{vulkan}
{
InitializeWindow(windowName, width, height, mode);
InitializeSurface();
}
Window::~Window()
{
vkDestroySurfaceKHR(vulkan.GetInstance(), surface, nullptr);
glfwDestroyWindow(window);
}
VkSurfaceKHR Window::GetSurface() const
{
return surface;
}
GLFWwindow* Window::GetWindow()
{
return window;
}
void Window::InitializeWindow(const std::string& windowName, int width, int height, Mode mode)
{
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
switch (mode)
{
case Mode::Fullscreen:
{
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
window = glfwCreateWindow(mode->width, mode->height, windowName.c_str(), glfwGetPrimaryMonitor(), nullptr);
break;
}
case Mode::BorderlessWindowed:
{
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
window = glfwCreateWindow(mode->width, mode->height, windowName.c_str(), nullptr, nullptr);
glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height, mode->refreshRate);
break;
}
case Mode::Windowed:
{
window = glfwCreateWindow(width, height, windowName.c_str(), nullptr, nullptr);
break;
}
default:
CP_ABORT("Window : Unreachable switch case");
}
CP_ASSERT(window, "InitializeWindow : Failed to initialize glfw window");
glfwSetWindowUserPointer(window, this);
glfwSetFramebufferSizeCallback(window, FramebufferResizeCallback);
}
void Window::InitializeSurface()
{
CP_VK_ASSERT(glfwCreateWindowSurface(vulkan.GetInstance(), window, nullptr, &surface), "InitializeSurface : Failed to create Vulkan surface");
}
void Window::FramebufferResizeCallback(GLFWwindow* glfwWindow, int width, int height)
{
Window* window = static_cast<Window*>(glfwGetWindowUserPointer(glfwWindow));
window->vulkan.GetSwapChain().ResizeFramebuffer(); // TODO: Should maybe be handled by an event system?
}
}
+37
View File
@@ -0,0 +1,37 @@
#pragma once
#include "copium/core/Vulkan.h"
#include "copium/util/Common.h"
#include <GLFW/glfw3.h>
namespace Copium
{
class Window final
{
CP_DELETE_COPY_AND_MOVE_CTOR(Window);
public:
enum class Mode
{
Fullscreen, BorderlessWindowed, Windowed
};
private:
Vulkan& vulkan;
GLFWwindow* window;
VkSurfaceKHR surface;
public:
Window(Vulkan& vulkan, const std::string& windowName, int width, int height, Mode mode);
~Window();
VkSurfaceKHR GetSurface() const;
GLFWwindow* GetWindow();
private:
void InitializeWindow(const std::string& windowName, int width, int height, Mode mode);
void InitializeSurface();
static void FramebufferResizeCallback(GLFWwindow* glfwWindow, int width, int height);
};
}