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;
}
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>
static Result Success(Args&&... args)
{
@ -75,6 +89,13 @@ namespace orange
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:
Result() = default;

View File

@ -16,20 +16,23 @@ namespace orange
public:
~RenderContext();
static Result<RenderContext> Create(const char *appName);
static VulkanResult<RenderContext> Create(const char *appName);
VkInstance Instance() const { return m_instance; }
VkPhysicalDevice PhysicalDevice() const { return m_physicalDevice; }
VkDevice Device() const { return m_device; }
VkQueue Queue() const { return m_queue; }
protected:
friend class Result<RenderContext>;
RenderContext(VkInstance instance, VkPhysicalDevice physicalDevice, VkDevice device, VkQueue queue)
: m_instance{ instance }, m_physicalDevice{ physicalDevice }, m_device{ device }, m_queue{ queue } {}
friend VulkanResult<RenderContext>;
RenderContext(VkInstance instance, VkPhysicalDevice physicalDevice, VkDevice device,
VkQueue queue, VkCommandPool commandPool)
: m_instance{ instance }, m_physicalDevice{ physicalDevice }, m_device{ device }
, m_queue{ queue }, m_commandPool{ commandPool } {}
private:
VkInstance m_instance = VK_NULL_HANDLE;
VkPhysicalDevice m_physicalDevice = VK_NULL_HANDLE;
VkDevice m_device = 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);
protected:
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:
VkDevice m_device;
VkSurfaceKHR m_surface;
VkFormat m_format;
VkExtent2D m_extent;
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
#include <Orange/Core/Traits.h>
#include <vulkan/vulkan_core.h>
namespace orange
{
@ -17,4 +18,13 @@ namespace orange
function(Forward<Args>(arguments)..., &count, outArray.Data());
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;
Result<Window> r_window = Window::Create();
auto r_window = Window::Create();
if (!r_window)
return 1;
Result<RenderContext> r_renderContext = RenderContext::Create("Cube Test");
auto r_renderContext = RenderContext::Create("Cube Test");
if (!r_renderContext)
return 1;
Result<VkSurfaceKHR> r_surface = r_window->CreateSurface(r_renderContext->Instance());
auto r_surface = r_window->CreateSurface(r_renderContext->Instance());
if (!r_surface)
return 1;
Result<Swapchain> r_swapchain = Swapchain::Create(*r_renderContext, *r_surface);
auto r_swapchain = Swapchain::Create(*r_renderContext, *r_surface);
if (!r_swapchain)
return 1;

View File

@ -13,13 +13,12 @@ namespace orange
{
auto r_tempWindow = Window::Create();
if (!r_tempWindow)
{
log::err("Failed to create temporary window for grabbing instance extensions: %s", Window::GetError());
return VulkanResult<VkInstance>::Error(VK_ERROR_NATIVE_WINDOW_IN_USE_KHR);
}
return VulkanResult<VkInstance>::PrintError(
"Failed to create temporary window for grabbing instance extensions: %s", Window::GetError());
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 =
@ -36,17 +35,14 @@ namespace orange
{
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
.pApplicationInfo = &appInfo,
.enabledExtensionCount = instanceExtensions.Size(),
.enabledExtensionCount = uint32_t(instanceExtensions.Size()),
.ppEnabledExtensionNames = instanceExtensions.Data(),
};
VkResult result = VK_SUCCESS;
VkInstance instance = VK_NULL_HANDLE;
if ((result = vkCreateInstance(&instanceInfo, nullptr, &instance)) != VK_SUCCESS)
{
log::err("Failed to create Vulkan instance.");
return VulkanResult<VkInstance>::Error(result);
}
return VulkanResult<VkInstance>::PrintError(result, "Failed to create Vulkan instance.");
return VulkanResult<VkInstance>::Success(instance);
}
@ -100,10 +96,7 @@ namespace orange
}
if (!bestPhysicalDevice)
{
log::err("Failed to find a suitable physical device");
return Result<VkPhysicalDevice>::Error(BasicErrorCode::Failed);
}
return Result<VkPhysicalDevice>::PrintError("Failed to find a suitable physical device");
return Result<VkPhysicalDevice>::Success(bestPhysicalDevice);
}
@ -139,34 +132,52 @@ namespace orange
VkDevice device = VK_NULL_HANDLE;
VkResult result;
if ((result = vkCreateDevice(physicalDevice, &deviceInfo, nullptr, &device)) != VK_SUCCESS)
{
log::err("Failed to create Vulkan logical device");
return VulkanResult<VkDevice>::Error(result);
}
return VulkanResult<VkDevice>::PrintError(result, "Failed to create Vulkan logical 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);
if (!r_instance)
return Result<RenderContext>::Error(BasicErrorCode::Failed);
return VulkanResult<RenderContext>::ForwardError(r_instance);
auto r_physicalDevice = PickPhysicalDevice(*r_instance);
if (!r_physicalDevice)
return Result<RenderContext>::Error(BasicErrorCode::Failed);
return VulkanResult<RenderContext>::Error();
uint32_t graphicsQueueFamilyIndex = *PickQueueFamilyIndex(*r_physicalDevice);
auto r_device = CreateVkDevice(*r_physicalDevice, graphicsQueueFamilyIndex);
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;
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()

View File

@ -70,7 +70,7 @@ namespace orange
Result<VkSurfaceFormatKHR> r_format = ChooseSwapChainFormat(context.PhysicalDevice(), surface);
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);
@ -89,27 +89,42 @@ namespace orange
.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
.presentMode = ChoosePresentMode(context.PhysicalDevice(), surface),
.clipped = VK_TRUE,
.oldSwapchain = VK_NULL_HANDLE, // TODO
.oldSwapchain = VK_NULL_HANDLE, // TODO
};
VkSwapchainKHR swapchain = VK_NULL_HANDLE;
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");
return Result<Swapchain>::Error();
VkImageViewCreateInfo imageViewInfo =
{
.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);
}
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);
return Result<Swapchain>::Success(
context.Device(), surface, r_format->format, extent, swapchain,
swapchainImages, swapchainImageViews);
}
Swapchain::~Swapchain()
{
for (const auto& imageView : m_imageViews)
vkDestroyImageView(m_device, imageView, nullptr);
vkDestroySwapchainKHR(m_device, m_swapchain, nullptr);
}
}