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