Get rendering

This commit is contained in:
Joshua Ashton 2022-08-04 22:18:11 +01:00
parent 6009d3178f
commit 65954d2dcf
8 changed files with 186 additions and 1 deletions

View File

@ -3,6 +3,7 @@
#include <Orange/Core/Log.h>
#include <Orange/Core/AlignedStorage.h>
#include <Orange/Core/Traits.h>
#include <cstddef>
namespace orange
{
@ -17,6 +18,10 @@ namespace orange
Success = 0,
};
struct VoidResult
{
};
template <typename T, typename ErrorCode = BasicErrorCode, ErrorCode SuccessCode = BasicErrorCode::Success, ErrorCode InvalidCode = BasicErrorCode::Invalid, ErrorCode DefaultFail = BasicErrorCode::Failed>
class Result
{
@ -128,4 +133,51 @@ namespace orange
ErrorCode m_error = InvalidCode;
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;
};
}

View File

@ -26,6 +26,8 @@ namespace orange
VulkanResult<VkFence> CreateFence(bool signalled);
VulkanResult<VkSemaphore> CreateSemaphore();
VulkanResult<VoidResult> BeginCommandBuffer(VkCommandBuffer buffer);
VulkanResult<VoidResult> EndCommandBuffer(VkCommandBuffer buffer);
protected:
friend VulkanResult<RenderContext>;
RenderContext(VkInstance instance, VkPhysicalDevice physicalDevice, VkDevice device,

View File

@ -18,7 +18,12 @@ namespace orange
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:
friend class Result<Swapchain>;
Swapchain(RenderContext& context, VkSurfaceKHR surface, VkFormat format, VkExtent2D extent, VkSwapchainKHR swapchain,

View File

@ -19,6 +19,8 @@ namespace orange
static const char* GetError();
static Result<Window> Create();
bool Update();
protected:
friend Result<Window>;
Window(SDL_Window* window);

View File

@ -3,6 +3,7 @@
#include <Orange/Render/Window.h>
#include <Orange/Render/RenderContext.h>
#include <Orange/Render/Swapchain.h>
#include <vulkan/vulkan_core.h>
using namespace orange;
@ -26,5 +27,34 @@ int main(int argc, char** argv)
if (!r_swapchain)
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;
}

View File

@ -33,4 +33,26 @@ namespace orange
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();
}
}

View File

@ -154,6 +154,12 @@ namespace orange
// TODO: Handle failure
uint32_t 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()
@ -162,4 +168,51 @@ namespace orange
vkDestroyImageView(m_ctx.Device(), imageView, 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);
}
}

View File

@ -5,6 +5,7 @@
#include <SDL2/SDL.h>
#include <SDL2/SDL_error.h>
#include <SDL2/SDL_events.h>
#include <SDL2/SDL_vulkan.h>
namespace orange
@ -56,4 +57,22 @@ namespace orange
{
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;
}
}