This commit is contained in:
Joshua Ashton 2022-08-04 17:23:08 +00:00
parent dc3b3dbe80
commit 0495fd870a
7 changed files with 115 additions and 44 deletions

View File

@ -58,6 +58,20 @@ namespace orange
return res; return res;
} }
template <typename... Args>
static Result PrintError(const char* message, Args&&... args)
{
log::err(message, Forward<Args>(args)...);
return Error();
}
template <typename... Args>
static Result PrintError(ErrorCode code, const char* message, Args&&... args)
{
log::err(message, Forward<Args>(args)...);
return Error(code);
}
template <typename... Args> template <typename... Args>
static Result Success(Args&&... args) static Result Success(Args&&... args)
{ {
@ -75,6 +89,13 @@ namespace orange
return Error(x.Code()); return Error(x.Code());
} }
template <typename OtherResult, typename... Args>
static Result PrintForwardError(OtherResult& x, const char* message, Args&&... args)
{
log::err(message, Forward<Args>(args)...);
return Error(x.Code());
}
protected: protected:
Result() = default; Result() = default;

View File

@ -16,20 +16,23 @@ namespace orange
public: public:
~RenderContext(); ~RenderContext();
static Result<RenderContext> Create(const char *appName); static VulkanResult<RenderContext> Create(const char *appName);
VkInstance Instance() const { return m_instance; } VkInstance Instance() const { return m_instance; }
VkPhysicalDevice PhysicalDevice() const { return m_physicalDevice; } VkPhysicalDevice PhysicalDevice() const { return m_physicalDevice; }
VkDevice Device() const { return m_device; } VkDevice Device() const { return m_device; }
VkQueue Queue() const { return m_queue; } VkQueue Queue() const { return m_queue; }
protected: protected:
friend class Result<RenderContext>; friend VulkanResult<RenderContext>;
RenderContext(VkInstance instance, VkPhysicalDevice physicalDevice, VkDevice device, VkQueue queue) RenderContext(VkInstance instance, VkPhysicalDevice physicalDevice, VkDevice device,
: m_instance{ instance }, m_physicalDevice{ physicalDevice }, m_device{ device }, m_queue{ queue } {} VkQueue queue, VkCommandPool commandPool)
: m_instance{ instance }, m_physicalDevice{ physicalDevice }, m_device{ device }
, m_queue{ queue }, m_commandPool{ commandPool } {}
private: private:
VkInstance m_instance = VK_NULL_HANDLE; VkInstance m_instance = VK_NULL_HANDLE;
VkPhysicalDevice m_physicalDevice = VK_NULL_HANDLE; VkPhysicalDevice m_physicalDevice = VK_NULL_HANDLE;
VkDevice m_device = VK_NULL_HANDLE; VkDevice m_device = VK_NULL_HANDLE;
VkQueue m_queue = VK_NULL_HANDLE; VkQueue m_queue = VK_NULL_HANDLE;
VkCommandPool m_commandPool = VK_NULL_HANDLE;
}; };
} }

View File

@ -16,13 +16,24 @@ namespace orange
static Result<Swapchain> Create(RenderContext& context, VkSurfaceKHR surface); static Result<Swapchain> Create(RenderContext& context, VkSurfaceKHR surface);
protected: protected:
friend class Result<Swapchain>; friend class Result<Swapchain>;
Swapchain(VkDevice device, VkSurfaceKHR surface, VkExtent2D extent, VkSwapchainKHR swapchain); Swapchain(VkDevice device, VkSurfaceKHR surface, VkFormat format, VkExtent2D extent, VkSwapchainKHR swapchain,
Span<VkImage> images, Span<VkImageView> imageViews)
: m_device { device }
, m_surface { surface }
, m_format { format }
, m_extent { extent }
, m_swapchain { swapchain }
, m_images { images }
, m_imageViews{ imageViews }
{}
private: private:
VkDevice m_device; VkDevice m_device;
VkSurfaceKHR m_surface; VkSurfaceKHR m_surface;
VkFormat m_format;
VkExtent2D m_extent; VkExtent2D m_extent;
VkSwapchainKHR m_swapchain; VkSwapchainKHR m_swapchain;
SmallVector<VkImage, 8> m_images; SmallVector<VkImage, 8> m_images;
SmallVector<VkImageView, 8> m_imageViews;
}; };
} }

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <Orange/Core/Traits.h> #include <Orange/Core/Traits.h>
#include <vulkan/vulkan_core.h>
namespace orange namespace orange
{ {
@ -17,4 +18,13 @@ namespace orange
function(Forward<Args>(arguments)..., &count, outArray.Data()); function(Forward<Args>(arguments)..., &count, outArray.Data());
return count; return count;
} }
static constexpr VkImageSubresourceRange FirstMipSubresourceRange =
{
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.baseMipLevel = 0,
.levelCount = 1,
.baseArrayLayer = 0,
.layerCount = 1,
};
} }

View File

@ -10,19 +10,19 @@ int main(int argc, char** argv)
{ {
(void)argc; (void)argv; (void)argc; (void)argv;
Result<Window> r_window = Window::Create(); auto r_window = Window::Create();
if (!r_window) if (!r_window)
return 1; return 1;
Result<RenderContext> r_renderContext = RenderContext::Create("Cube Test"); auto r_renderContext = RenderContext::Create("Cube Test");
if (!r_renderContext) if (!r_renderContext)
return 1; return 1;
Result<VkSurfaceKHR> r_surface = r_window->CreateSurface(r_renderContext->Instance()); auto r_surface = r_window->CreateSurface(r_renderContext->Instance());
if (!r_surface) if (!r_surface)
return 1; return 1;
Result<Swapchain> r_swapchain = Swapchain::Create(*r_renderContext, *r_surface); auto r_swapchain = Swapchain::Create(*r_renderContext, *r_surface);
if (!r_swapchain) if (!r_swapchain)
return 1; return 1;

View File

@ -13,13 +13,12 @@ namespace orange
{ {
auto r_tempWindow = Window::Create(); auto r_tempWindow = Window::Create();
if (!r_tempWindow) if (!r_tempWindow)
{ return VulkanResult<VkInstance>::PrintError(
log::err("Failed to create temporary window for grabbing instance extensions: %s", Window::GetError()); "Failed to create temporary window for grabbing instance extensions: %s", Window::GetError());
return VulkanResult<VkInstance>::Error(VK_ERROR_NATIVE_WINDOW_IN_USE_KHR);
}
if (!VkEnumerate(Window::GetInstanceExtensions, instanceExtensions, *r_tempWindow)) if (!VkEnumerate(Window::GetInstanceExtensions, instanceExtensions, *r_tempWindow))
return VulkanResult<VkInstance>::Error(VK_ERROR_NATIVE_WINDOW_IN_USE_KHR); return VulkanResult<VkInstance>::PrintError(
"Failed to get required instance extensions: %s", Window::GetError());
} }
VkApplicationInfo appInfo = VkApplicationInfo appInfo =
@ -36,17 +35,14 @@ namespace orange
{ {
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
.pApplicationInfo = &appInfo, .pApplicationInfo = &appInfo,
.enabledExtensionCount = instanceExtensions.Size(), .enabledExtensionCount = uint32_t(instanceExtensions.Size()),
.ppEnabledExtensionNames = instanceExtensions.Data(), .ppEnabledExtensionNames = instanceExtensions.Data(),
}; };
VkResult result = VK_SUCCESS; VkResult result = VK_SUCCESS;
VkInstance instance = VK_NULL_HANDLE; VkInstance instance = VK_NULL_HANDLE;
if ((result = vkCreateInstance(&instanceInfo, nullptr, &instance)) != VK_SUCCESS) if ((result = vkCreateInstance(&instanceInfo, nullptr, &instance)) != VK_SUCCESS)
{ return VulkanResult<VkInstance>::PrintError(result, "Failed to create Vulkan instance.");
log::err("Failed to create Vulkan instance.");
return VulkanResult<VkInstance>::Error(result);
}
return VulkanResult<VkInstance>::Success(instance); return VulkanResult<VkInstance>::Success(instance);
} }
@ -100,10 +96,7 @@ namespace orange
} }
if (!bestPhysicalDevice) if (!bestPhysicalDevice)
{ return Result<VkPhysicalDevice>::PrintError("Failed to find a suitable physical device");
log::err("Failed to find a suitable physical device");
return Result<VkPhysicalDevice>::Error(BasicErrorCode::Failed);
}
return Result<VkPhysicalDevice>::Success(bestPhysicalDevice); return Result<VkPhysicalDevice>::Success(bestPhysicalDevice);
} }
@ -139,34 +132,52 @@ namespace orange
VkDevice device = VK_NULL_HANDLE; VkDevice device = VK_NULL_HANDLE;
VkResult result; VkResult result;
if ((result = vkCreateDevice(physicalDevice, &deviceInfo, nullptr, &device)) != VK_SUCCESS) if ((result = vkCreateDevice(physicalDevice, &deviceInfo, nullptr, &device)) != VK_SUCCESS)
{ return VulkanResult<VkDevice>::PrintError(result, "Failed to create Vulkan logical device");
log::err("Failed to create Vulkan logical device");
return VulkanResult<VkDevice>::Error(result);
}
return VulkanResult<VkDevice>::Success(device); return VulkanResult<VkDevice>::Success(device);
} }
Result<RenderContext> RenderContext::Create(const char *appName) static VulkanResult<VkCommandPool> CreateVkCommandPool(VkDevice device, uint32_t graphicsQueueFamilyIndex)
{
VkCommandPoolCreateInfo poolInfo =
{
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
.queueFamilyIndex = graphicsQueueFamilyIndex,
};
VkResult res = VK_SUCCESS;
VkCommandPool commandPool = VK_NULL_HANDLE;
if ((res = vkCreateCommandPool(device, &poolInfo, nullptr, &commandPool)) != VK_SUCCESS)
return VulkanResult<VkCommandPool>::PrintError(res, "Failed to create command pool");
return VulkanResult<VkCommandPool>::Success(commandPool);
}
VulkanResult<RenderContext> RenderContext::Create(const char *appName)
{ {
auto r_instance = CreateVkInstance(appName); auto r_instance = CreateVkInstance(appName);
if (!r_instance) if (!r_instance)
return Result<RenderContext>::Error(BasicErrorCode::Failed); return VulkanResult<RenderContext>::ForwardError(r_instance);
auto r_physicalDevice = PickPhysicalDevice(*r_instance); auto r_physicalDevice = PickPhysicalDevice(*r_instance);
if (!r_physicalDevice) if (!r_physicalDevice)
return Result<RenderContext>::Error(BasicErrorCode::Failed); return VulkanResult<RenderContext>::Error();
uint32_t graphicsQueueFamilyIndex = *PickQueueFamilyIndex(*r_physicalDevice); uint32_t graphicsQueueFamilyIndex = *PickQueueFamilyIndex(*r_physicalDevice);
auto r_device = CreateVkDevice(*r_physicalDevice, graphicsQueueFamilyIndex); auto r_device = CreateVkDevice(*r_physicalDevice, graphicsQueueFamilyIndex);
if (!r_device) if (!r_device)
return Result<RenderContext>::Error(BasicErrorCode::Failed); return VulkanResult<RenderContext>::ForwardError(r_device);
auto r_commandPool = CreateVkCommandPool(*r_device, graphicsQueueFamilyIndex);
if (!r_commandPool)
return VulkanResult<RenderContext>::ForwardError(r_commandPool);
VkQueue queue = VK_NULL_HANDLE; VkQueue queue = VK_NULL_HANDLE;
vkGetDeviceQueue(*r_device, graphicsQueueFamilyIndex, 0, &queue); vkGetDeviceQueue(*r_device, graphicsQueueFamilyIndex, 0, &queue);
return Result<RenderContext>::Success(*r_instance, *r_physicalDevice, *r_device, queue); return VulkanResult<RenderContext>::Success(*r_instance, *r_physicalDevice, *r_device, queue, *r_commandPool);
} }
RenderContext::~RenderContext() RenderContext::~RenderContext()

View File

@ -70,7 +70,7 @@ namespace orange
Result<VkSurfaceFormatKHR> r_format = ChooseSwapChainFormat(context.PhysicalDevice(), surface); Result<VkSurfaceFormatKHR> r_format = ChooseSwapChainFormat(context.PhysicalDevice(), surface);
if (!r_format) if (!r_format)
return Result<Swapchain>::ForwardError(r_format); return Result<Swapchain>::PrintForwardError(r_format, "Failed to pick swapchain format");
const VkExtent2D extent = ChooseSwapExtent(capabilities); const VkExtent2D extent = ChooseSwapExtent(capabilities);
@ -89,27 +89,42 @@ namespace orange
.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
.presentMode = ChoosePresentMode(context.PhysicalDevice(), surface), .presentMode = ChoosePresentMode(context.PhysicalDevice(), surface),
.clipped = VK_TRUE, .clipped = VK_TRUE,
.oldSwapchain = VK_NULL_HANDLE, // TODO .oldSwapchain = VK_NULL_HANDLE, // TODO
}; };
VkSwapchainKHR swapchain = VK_NULL_HANDLE; VkSwapchainKHR swapchain = VK_NULL_HANDLE;
if (vkCreateSwapchainKHR(context.Device(), &swapchainInfo, nullptr, &swapchain) != VK_SUCCESS) if (vkCreateSwapchainKHR(context.Device(), &swapchainInfo, nullptr, &swapchain) != VK_SUCCESS)
return Result<Swapchain>::PrintError("Failed to create swapchain");
SmallVector<VkImage, 8> swapchainImages;
if (!VkEnumerate(vkGetSwapchainImagesKHR, swapchainImages, context.Device(), swapchain))
return Result<Swapchain>::PrintError("Failed to get swapchain images");
SmallVector<VkImageView, 8> swapchainImageViews{ swapchainImages.Size() };
for (size_t i = 0; i < swapchainImages.Size(); i++)
{ {
log::err("Failed to create swapchain"); VkImageViewCreateInfo imageViewInfo =
return Result<Swapchain>::Error(); {
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
.image = swapchainImages[i],
.viewType = VK_IMAGE_VIEW_TYPE_2D,
.format = r_format->format,
.subresourceRange = FirstMipSubresourceRange,
};
if (vkCreateImageView(context.Device(), &imageViewInfo, nullptr, &swapchainImageViews[i]) != VK_SUCCESS)
return Result<Swapchain>::PrintError("Failed to get swapchain image view");
} }
return Result<Swapchain>::Success(context.Device(), surface, extent, swapchain); return Result<Swapchain>::Success(
} context.Device(), surface, r_format->format, extent, swapchain,
swapchainImages, swapchainImageViews);
Swapchain::Swapchain(VkDevice device, VkSurfaceKHR surface, VkExtent2D extent, VkSwapchainKHR swapchain)
: m_device{ device }, m_surface{ surface }, m_extent{ extent }, m_swapchain{ swapchain }
{
VkEnumerate(vkGetSwapchainImagesKHR, m_images, m_device, m_swapchain);
} }
Swapchain::~Swapchain() Swapchain::~Swapchain()
{ {
for (const auto& imageView : m_imageViews)
vkDestroyImageView(m_device, imageView, nullptr);
vkDestroySwapchainKHR(m_device, m_swapchain, nullptr); vkDestroySwapchainKHR(m_device, m_swapchain, nullptr);
} }
} }