Work
This commit is contained in:
parent
dc3b3dbe80
commit
0495fd870a
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
}
|
|
@ -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;
|
||||
};
|
||||
}
|
|
@ -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,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue