Get rendering
This commit is contained in:
parent
6009d3178f
commit
65954d2dcf
|
@ -3,6 +3,7 @@
|
||||||
#include <Orange/Core/Log.h>
|
#include <Orange/Core/Log.h>
|
||||||
#include <Orange/Core/AlignedStorage.h>
|
#include <Orange/Core/AlignedStorage.h>
|
||||||
#include <Orange/Core/Traits.h>
|
#include <Orange/Core/Traits.h>
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
namespace orange
|
namespace orange
|
||||||
{
|
{
|
||||||
|
@ -17,6 +18,10 @@ namespace orange
|
||||||
Success = 0,
|
Success = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct VoidResult
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
template <typename T, typename ErrorCode = BasicErrorCode, ErrorCode SuccessCode = BasicErrorCode::Success, ErrorCode InvalidCode = BasicErrorCode::Invalid, ErrorCode DefaultFail = BasicErrorCode::Failed>
|
template <typename T, typename ErrorCode = BasicErrorCode, ErrorCode SuccessCode = BasicErrorCode::Success, ErrorCode InvalidCode = BasicErrorCode::Invalid, ErrorCode DefaultFail = BasicErrorCode::Failed>
|
||||||
class Result
|
class Result
|
||||||
{
|
{
|
||||||
|
@ -128,4 +133,51 @@ namespace orange
|
||||||
ErrorCode m_error = InvalidCode;
|
ErrorCode m_error = InvalidCode;
|
||||||
bool m_created = false;
|
bool m_created = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// It's like a reference, but allows
|
||||||
|
// it to be nullptr once, at constructor time
|
||||||
|
// and never again.
|
||||||
|
template <typename T>
|
||||||
|
class WeakRef
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
WeakRef() {}
|
||||||
|
WeakRef(std::nullptr_t) = delete;
|
||||||
|
WeakRef(T& ref)
|
||||||
|
: m_ptr{ &ref } { }
|
||||||
|
|
||||||
|
WeakRef(const WeakRef& other)
|
||||||
|
: m_ptr { other.m_ptr } {}
|
||||||
|
|
||||||
|
WeakRef& operator = (T& object)
|
||||||
|
{
|
||||||
|
m_ptr = &object;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
WeakRef& operator = (const WeakRef& other)
|
||||||
|
{
|
||||||
|
m_ptr = other.m_ptr;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
WeakRef& operator = (std::nullptr_t) = delete;
|
||||||
|
|
||||||
|
T* operator -> () const { return m_ptr; }
|
||||||
|
|
||||||
|
T** operator & () { return &m_ptr; }
|
||||||
|
T* const* operator & () const { return &m_ptr; }
|
||||||
|
|
||||||
|
bool operator == (const WeakRef& other) const { return m_ptr == other.m_ptr; }
|
||||||
|
bool operator != (const WeakRef& other) const { return m_ptr != other.m_ptr; }
|
||||||
|
|
||||||
|
bool operator == (const T* other) const { return m_ptr == other; }
|
||||||
|
bool operator != (const T* other) const { return m_ptr != other; }
|
||||||
|
|
||||||
|
bool operator == (std::nullptr_t) const { return m_ptr == nullptr; }
|
||||||
|
bool operator != (std::nullptr_t) const { return m_ptr != nullptr; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
T* m_ptr = nullptr;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,8 @@ namespace orange
|
||||||
|
|
||||||
VulkanResult<VkFence> CreateFence(bool signalled);
|
VulkanResult<VkFence> CreateFence(bool signalled);
|
||||||
VulkanResult<VkSemaphore> CreateSemaphore();
|
VulkanResult<VkSemaphore> CreateSemaphore();
|
||||||
|
VulkanResult<VoidResult> BeginCommandBuffer(VkCommandBuffer buffer);
|
||||||
|
VulkanResult<VoidResult> EndCommandBuffer(VkCommandBuffer buffer);
|
||||||
protected:
|
protected:
|
||||||
friend VulkanResult<RenderContext>;
|
friend VulkanResult<RenderContext>;
|
||||||
RenderContext(VkInstance instance, VkPhysicalDevice physicalDevice, VkDevice device,
|
RenderContext(VkInstance instance, VkPhysicalDevice physicalDevice, VkDevice device,
|
||||||
|
|
|
@ -18,7 +18,12 @@ namespace orange
|
||||||
|
|
||||||
static Result<Swapchain> Create(RenderContext& context, VkSurfaceKHR surface);
|
static Result<Swapchain> Create(RenderContext& context, VkSurfaceKHR surface);
|
||||||
|
|
||||||
VkCommandBuffer CommandBuffer() const { return m_commandBuffers[m_currentImage]; }
|
VkImage Image() const { return m_images[m_currentImage]; }
|
||||||
|
VkImageView ImageView() const { return m_imageViews[m_currentImage]; }
|
||||||
|
VkCommandBuffer CommandBuffer() const { return m_commandBuffers[m_currentFrame]; }
|
||||||
|
VkExtent2D Extent() const { return m_extent; }
|
||||||
|
|
||||||
|
void Present();
|
||||||
protected:
|
protected:
|
||||||
friend class Result<Swapchain>;
|
friend class Result<Swapchain>;
|
||||||
Swapchain(RenderContext& context, VkSurfaceKHR surface, VkFormat format, VkExtent2D extent, VkSwapchainKHR swapchain,
|
Swapchain(RenderContext& context, VkSurfaceKHR surface, VkFormat format, VkExtent2D extent, VkSwapchainKHR swapchain,
|
||||||
|
|
|
@ -19,6 +19,8 @@ namespace orange
|
||||||
static const char* GetError();
|
static const char* GetError();
|
||||||
|
|
||||||
static Result<Window> Create();
|
static Result<Window> Create();
|
||||||
|
|
||||||
|
bool Update();
|
||||||
protected:
|
protected:
|
||||||
friend Result<Window>;
|
friend Result<Window>;
|
||||||
Window(SDL_Window* window);
|
Window(SDL_Window* window);
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <Orange/Render/Window.h>
|
#include <Orange/Render/Window.h>
|
||||||
#include <Orange/Render/RenderContext.h>
|
#include <Orange/Render/RenderContext.h>
|
||||||
#include <Orange/Render/Swapchain.h>
|
#include <Orange/Render/Swapchain.h>
|
||||||
|
#include <vulkan/vulkan_core.h>
|
||||||
|
|
||||||
using namespace orange;
|
using namespace orange;
|
||||||
|
|
||||||
|
@ -26,5 +27,34 @@ int main(int argc, char** argv)
|
||||||
if (!r_swapchain)
|
if (!r_swapchain)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
while (r_window->Update())
|
||||||
|
{
|
||||||
|
r_renderContext->BeginCommandBuffer(r_swapchain->CommandBuffer());
|
||||||
|
{
|
||||||
|
const VkRenderingAttachmentInfoKHR attachmentInfo =
|
||||||
|
{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR,
|
||||||
|
.imageView = r_swapchain->ImageView(),
|
||||||
|
.imageLayout = VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR,
|
||||||
|
.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
|
||||||
|
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
|
||||||
|
.clearValue = { .color = { .float32 = { 1.0f, 0.5f, 0.0f, 1.0f } } },
|
||||||
|
};
|
||||||
|
|
||||||
|
const VkRenderingInfo renderInfo =
|
||||||
|
{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
|
||||||
|
.renderArea = { {}, r_swapchain->Extent() },
|
||||||
|
.layerCount = 1,
|
||||||
|
.colorAttachmentCount = 1,
|
||||||
|
.pColorAttachments = &attachmentInfo,
|
||||||
|
};
|
||||||
|
vkCmdBeginRendering(r_swapchain->CommandBuffer(), &renderInfo);
|
||||||
|
vkCmdEndRendering(r_swapchain->CommandBuffer());
|
||||||
|
}
|
||||||
|
r_renderContext->EndCommandBuffer(r_swapchain->CommandBuffer());
|
||||||
|
r_swapchain->Present();
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,4 +33,26 @@ namespace orange
|
||||||
|
|
||||||
return VulkanResult<VkSemaphore>::Success(semaphore);
|
return VulkanResult<VkSemaphore>::Success(semaphore);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VulkanResult<VoidResult> RenderContext::BeginCommandBuffer(VkCommandBuffer buffer)
|
||||||
|
{
|
||||||
|
VkCommandBufferBeginInfo beginInfo =
|
||||||
|
{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
|
||||||
|
};
|
||||||
|
|
||||||
|
VkResult res = VK_SUCCESS;
|
||||||
|
if ((res = vkBeginCommandBuffer(buffer, &beginInfo)) != VK_SUCCESS)
|
||||||
|
return VulkanResult<VoidResult>::Error(res);
|
||||||
|
|
||||||
|
return VulkanResult<VoidResult>::Success();
|
||||||
|
}
|
||||||
|
VulkanResult<VoidResult> RenderContext::EndCommandBuffer(VkCommandBuffer buffer)
|
||||||
|
{
|
||||||
|
VkResult res = VK_SUCCESS;
|
||||||
|
if ((res = vkEndCommandBuffer(buffer)) != VK_SUCCESS)
|
||||||
|
return VulkanResult<VoidResult>::Error(res);
|
||||||
|
|
||||||
|
return VulkanResult<VoidResult>::Success();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -154,6 +154,12 @@ namespace orange
|
||||||
// TODO: Handle failure
|
// TODO: Handle failure
|
||||||
uint32_t imageIndex;
|
uint32_t imageIndex;
|
||||||
vkAcquireNextImageKHR(context.Device(), swapchain, ~0u, imageAvailableSemaphores[0], VK_NULL_HANDLE, &imageIndex);
|
vkAcquireNextImageKHR(context.Device(), swapchain, ~0u, imageAvailableSemaphores[0], VK_NULL_HANDLE, &imageIndex);
|
||||||
|
|
||||||
|
return Result<Swapchain>::Success(
|
||||||
|
context, surface, r_format->format, extent, swapchain,
|
||||||
|
swapchainImages, swapchainImageViews, commandBuffers,
|
||||||
|
imageAvailableSemaphores, renderFinishedSemaphores, inFlightFences,
|
||||||
|
imageIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
Swapchain::~Swapchain()
|
Swapchain::~Swapchain()
|
||||||
|
@ -162,4 +168,51 @@ namespace orange
|
||||||
vkDestroyImageView(m_ctx.Device(), imageView, nullptr);
|
vkDestroyImageView(m_ctx.Device(), imageView, nullptr);
|
||||||
vkDestroySwapchainKHR(m_ctx.Device(), m_swapchain, nullptr);
|
vkDestroySwapchainKHR(m_ctx.Device(), m_swapchain, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Swapchain::Present()
|
||||||
|
{
|
||||||
|
const VkPipelineStageFlags waitStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||||
|
VkSubmitInfo submitInfo =
|
||||||
|
{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
||||||
|
.waitSemaphoreCount = 1,
|
||||||
|
.pWaitSemaphores = &m_imageAvailableSemaphores[m_currentFrame],
|
||||||
|
.pWaitDstStageMask = &waitStage,
|
||||||
|
.commandBufferCount = 1,
|
||||||
|
.pCommandBuffers = &m_commandBuffers[m_currentFrame],
|
||||||
|
.signalSemaphoreCount = 1,
|
||||||
|
.pSignalSemaphores = &m_renderFinishedSemaphores[m_currentFrame],
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: Handle failure properly.
|
||||||
|
if (vkQueueSubmit(m_ctx.Queue(), 1, &submitInfo, m_inFlightFences[m_currentFrame]) != VK_SUCCESS) {
|
||||||
|
log::err("Failed to submit work");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkPresentInfoKHR presentInfo =
|
||||||
|
{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
|
||||||
|
.waitSemaphoreCount = 1,
|
||||||
|
.pWaitSemaphores = &m_renderFinishedSemaphores[m_currentFrame],
|
||||||
|
.swapchainCount = 1,
|
||||||
|
.pSwapchains = &m_swapchain,
|
||||||
|
.pImageIndices = &m_currentImage,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (vkQueuePresentKHR(m_ctx.Queue(), &presentInfo) != VK_SUCCESS) {
|
||||||
|
log::err("Failed to submit present");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare for next frame.
|
||||||
|
|
||||||
|
m_currentFrame = (m_currentFrame + 1) % DefaultFramesInFlight;
|
||||||
|
|
||||||
|
vkResetCommandBuffer(m_commandBuffers[m_currentFrame], 0u);
|
||||||
|
|
||||||
|
vkWaitForFences(m_ctx.Device(), 1, &m_inFlightFences[m_currentFrame], VK_TRUE, UINT64_MAX);
|
||||||
|
vkResetFences(m_ctx.Device(), 1, &m_inFlightFences[m_currentFrame]);
|
||||||
|
vkAcquireNextImageKHR(m_ctx.Device(), m_swapchain, ~0u, m_imageAvailableSemaphores[m_currentFrame], VK_NULL_HANDLE, &m_currentImage);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
#include <SDL2/SDL_error.h>
|
#include <SDL2/SDL_error.h>
|
||||||
|
#include <SDL2/SDL_events.h>
|
||||||
#include <SDL2/SDL_vulkan.h>
|
#include <SDL2/SDL_vulkan.h>
|
||||||
|
|
||||||
namespace orange
|
namespace orange
|
||||||
|
@ -56,4 +57,22 @@ namespace orange
|
||||||
{
|
{
|
||||||
return SDL_GetError();
|
return SDL_GetError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Window::Update()
|
||||||
|
{
|
||||||
|
bool quit = false;
|
||||||
|
|
||||||
|
SDL_Event e;
|
||||||
|
while (SDL_PollEvent(&e))
|
||||||
|
{
|
||||||
|
switch (e.type)
|
||||||
|
{
|
||||||
|
case SDL_QUIT:
|
||||||
|
quit = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return !quit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue