diff --git a/include/Nazara/Renderer/RenderDeviceInstance.hpp b/include/Nazara/Renderer/RenderDeviceInstance.hpp new file mode 100644 index 000000000..3c019fc20 --- /dev/null +++ b/include/Nazara/Renderer/RenderDeviceInstance.hpp @@ -0,0 +1,26 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Renderer module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_RENDERDEVICEINSTANCE_HPP +#define NAZARA_RENDERDEVICEINSTANCE_HPP + +#include +#include + +namespace Nz +{ + ///TODO: Rename + class NAZARA_RENDERER_API RenderDeviceInstance + { + public: + RenderDeviceInstance() = default; + virtual ~RenderDeviceInstance(); + }; +} + +#include + +#endif // NAZARA_RENDERDEVICEINSTANCE_HPP diff --git a/include/Nazara/Renderer/RenderDeviceInstance.inl b/include/Nazara/Renderer/RenderDeviceInstance.inl new file mode 100644 index 000000000..68ffbd5cd --- /dev/null +++ b/include/Nazara/Renderer/RenderDeviceInstance.inl @@ -0,0 +1,12 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Renderer module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ +} + +#include diff --git a/include/Nazara/Renderer/RenderSurface.hpp b/include/Nazara/Renderer/RenderSurface.hpp new file mode 100644 index 000000000..9835af794 --- /dev/null +++ b/include/Nazara/Renderer/RenderSurface.hpp @@ -0,0 +1,30 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Renderer module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_RENDERSURFACE_HPP +#define NAZARA_RENDERSURFACE_HPP + +#include +#include +#include + +namespace Nz +{ + ///TODO: Rename + class NAZARA_RENDERER_API RenderSurface + { + public: + RenderSurface() = default; + virtual ~RenderSurface(); + + virtual bool Create(WindowHandle handle) = 0; + virtual void Destroy() = 0; + }; +} + +#include + +#endif // NAZARA_RENDERSURFACE_HPP diff --git a/include/Nazara/Renderer/RenderSurface.inl b/include/Nazara/Renderer/RenderSurface.inl new file mode 100644 index 000000000..2d0103e88 --- /dev/null +++ b/include/Nazara/Renderer/RenderSurface.inl @@ -0,0 +1,12 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Renderer module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ +} + +#include diff --git a/include/Nazara/Renderer/RenderWindow.hpp b/include/Nazara/Renderer/RenderWindow.hpp index a0d5859e4..82c80b342 100644 --- a/include/Nazara/Renderer/RenderWindow.hpp +++ b/include/Nazara/Renderer/RenderWindow.hpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -52,6 +53,7 @@ namespace Nz private: std::unique_ptr m_impl; Clock m_clock; + std::unique_ptr m_surface; RenderWindowParameters m_parameters; unsigned int m_framerateLimit; }; diff --git a/include/Nazara/Renderer/RenderWindowImpl.hpp b/include/Nazara/Renderer/RenderWindowImpl.hpp index 19a831773..85b1b9c36 100644 --- a/include/Nazara/Renderer/RenderWindowImpl.hpp +++ b/include/Nazara/Renderer/RenderWindowImpl.hpp @@ -16,13 +16,15 @@ namespace Nz { + class RenderSurface; + class NAZARA_RENDERER_API RenderWindowImpl { public: RenderWindowImpl() = default; virtual ~RenderWindowImpl(); - virtual bool Create(WindowHandle handle, const Vector2ui& size, const RenderWindowParameters& parameters) = 0; + virtual bool Create(RenderSurface* surface, const Vector2ui& size, const RenderWindowParameters& parameters) = 0; }; } diff --git a/include/Nazara/Renderer/RendererImpl.hpp b/include/Nazara/Renderer/RendererImpl.hpp index 758765492..0c0501e99 100644 --- a/include/Nazara/Renderer/RendererImpl.hpp +++ b/include/Nazara/Renderer/RendererImpl.hpp @@ -21,6 +21,8 @@ namespace Nz class AbstractBuffer; class Buffer; class RendererImpl; + class RenderDeviceInstance; + class RenderSurface; class RenderWindowImpl; using CreateRendererImplFunc = RendererImpl*(*)(); @@ -32,8 +34,11 @@ namespace Nz virtual ~RendererImpl(); virtual std::unique_ptr CreateHardwareBufferImpl(Buffer* parent, BufferType type) = 0; + virtual std::unique_ptr CreateRenderSurfaceImpl() = 0; virtual std::unique_ptr CreateRenderWindowImpl() = 0; + virtual std::unique_ptr InstanciateRenderDevice(std::size_t deviceIndex) = 0; + virtual bool IsBetterThan(const RendererImpl* other) const = 0; virtual RenderAPI QueryAPI() const = 0; diff --git a/include/Nazara/VulkanRenderer/VkRenderWindow.hpp b/include/Nazara/VulkanRenderer/VkRenderWindow.hpp index 7a3246984..0ac221adc 100644 --- a/include/Nazara/VulkanRenderer/VkRenderWindow.hpp +++ b/include/Nazara/VulkanRenderer/VkRenderWindow.hpp @@ -39,13 +39,12 @@ namespace Nz void BuildPreRenderCommands(UInt32 imageIndex, Vk::CommandBuffer& commandBuffer) override; void BuildPostRenderCommands(UInt32 imageIndex, Vk::CommandBuffer& commandBuffer) override; - bool Create(WindowHandle handle, const Vector2ui& size, const RenderWindowParameters& parameters) override; + bool Create(RenderSurface* surface, const Vector2ui& size, const RenderWindowParameters& parameters) override; inline const Vk::Framebuffer& GetFrameBuffer(UInt32 imageIndex) const override; inline UInt32 GetFramebufferCount() const; inline const Vk::DeviceHandle& GetDevice() const; inline UInt32 GetPresentableFamilyQueue() const; - inline const Vk::Surface& GetSurface() const; inline const Vk::Swapchain& GetSwapchain() const; void Present(UInt32 imageIndex) override; @@ -56,7 +55,7 @@ namespace Nz private: bool SetupDepthBuffer(const Vector2ui& size); bool SetupRenderPass(const Vector2ui& size); - bool SetupSwapchain(const Vector2ui& size); + bool SetupSwapchain(Vk::Surface& surface, const Vector2ui& size); Clock m_clock; VkColorSpaceKHR m_colorSpace; @@ -69,7 +68,6 @@ namespace Nz Vk::Image m_depthBuffer; Vk::ImageView m_depthBufferView; Vk::Queue m_presentQueue; - Vk::Surface m_surface; Vk::Swapchain m_swapchain; UInt32 m_presentableFamilyQueue; }; diff --git a/include/Nazara/VulkanRenderer/VkRenderWindow.inl b/include/Nazara/VulkanRenderer/VkRenderWindow.inl index 0142c1d03..e207cc89a 100644 --- a/include/Nazara/VulkanRenderer/VkRenderWindow.inl +++ b/include/Nazara/VulkanRenderer/VkRenderWindow.inl @@ -27,11 +27,6 @@ namespace Nz return m_presentableFamilyQueue; } - inline const Vk::Surface& VkRenderWindow::GetSurface() const - { - return m_surface; - } - inline const Vk::Swapchain& VkRenderWindow::GetSwapchain() const { return m_swapchain; diff --git a/include/Nazara/VulkanRenderer/VulkanDevice.hpp b/include/Nazara/VulkanRenderer/VulkanDevice.hpp new file mode 100644 index 000000000..1e4344232 --- /dev/null +++ b/include/Nazara/VulkanRenderer/VulkanDevice.hpp @@ -0,0 +1,35 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_VULKANRENDERER_VULKANDEVICE_HPP +#define NAZARA_VULKANRENDERER_VULKANDEVICE_HPP + +#include +#include +#include +#include + +namespace Nz +{ + //TODO: Move all the software stuff to the Renderer + + class NAZARA_VULKANRENDERER_API VulkanDevice : public RenderDeviceInstance + { + public: + VulkanDevice(Vk::DeviceHandle device); + ~VulkanDevice(); + + VulkanDevice& operator=(const VulkanDevice&) = delete; + VulkanDevice& operator=(VulkanDevice&&) = delete; ///TODO + + private: + Vk::DeviceHandle m_device; + }; +} + +#include + +#endif // NAZARA_VULKANRENDERER_VULKANDEVICE_HPP diff --git a/include/Nazara/VulkanRenderer/VulkanDevice.inl b/include/Nazara/VulkanRenderer/VulkanDevice.inl new file mode 100644 index 000000000..3a751f921 --- /dev/null +++ b/include/Nazara/VulkanRenderer/VulkanDevice.inl @@ -0,0 +1,12 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ +} + +#include diff --git a/include/Nazara/VulkanRenderer/VulkanRenderer.hpp b/include/Nazara/VulkanRenderer/VulkanRenderer.hpp index 38dc8540f..74a2075a9 100644 --- a/include/Nazara/VulkanRenderer/VulkanRenderer.hpp +++ b/include/Nazara/VulkanRenderer/VulkanRenderer.hpp @@ -25,8 +25,12 @@ namespace Nz VulkanRenderer() = default; ~VulkanRenderer(); + std::unique_ptr CreateHardwareBufferImpl(Buffer* parent, BufferType type) override; + std::unique_ptr CreateRenderSurfaceImpl() override; std::unique_ptr CreateRenderWindowImpl() override; + std::unique_ptr InstanciateRenderDevice(std::size_t deviceIndex) override; + bool IsBetterThan(const RendererImpl* other) const override; RenderAPI QueryAPI() const override; diff --git a/include/Nazara/VulkanRenderer/VulkanSurface.hpp b/include/Nazara/VulkanRenderer/VulkanSurface.hpp new file mode 100644 index 000000000..e86d2fc2e --- /dev/null +++ b/include/Nazara/VulkanRenderer/VulkanSurface.hpp @@ -0,0 +1,40 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_VULKANRENDERER_SURFACE_HPP +#define NAZARA_VULKANRENDERER_SURFACE_HPP + +#include +#include +#include +#include + +namespace Nz +{ + class NAZARA_VULKANRENDERER_API VulkanSurface : public RenderSurface + { + public: + VulkanSurface(); + VulkanSurface(const VulkanSurface&) = delete; + VulkanSurface(VulkanSurface&&) = delete; ///TODO + virtual ~VulkanSurface(); + + bool Create(WindowHandle handle) override; + void Destroy() override; + + inline Vk::Surface& GetSurface(); + + VulkanSurface& operator=(const VulkanSurface&) = delete; + VulkanSurface& operator=(VulkanSurface&&) = delete; ///TODO + + private: + Vk::Surface m_surface; + }; +} + +#include + +#endif // NAZARA_VULKANRENDERER_SURFACE_HPP diff --git a/include/Nazara/VulkanRenderer/VulkanSurface.inl b/include/Nazara/VulkanRenderer/VulkanSurface.inl new file mode 100644 index 000000000..04dfc2968 --- /dev/null +++ b/include/Nazara/VulkanRenderer/VulkanSurface.inl @@ -0,0 +1,16 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ + inline Vk::Surface& VulkanSurface::GetSurface() + { + return m_surface; + } +} + +#include diff --git a/src/Nazara/Renderer/RenderDeviceInstance.cpp b/src/Nazara/Renderer/RenderDeviceInstance.cpp new file mode 100644 index 000000000..6d8078cfb --- /dev/null +++ b/src/Nazara/Renderer/RenderDeviceInstance.cpp @@ -0,0 +1,11 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Renderer module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ + RenderDeviceInstance::~RenderDeviceInstance() = default; +} diff --git a/src/Nazara/Renderer/RenderSurface.cpp b/src/Nazara/Renderer/RenderSurface.cpp new file mode 100644 index 000000000..e48c69f6c --- /dev/null +++ b/src/Nazara/Renderer/RenderSurface.cpp @@ -0,0 +1,11 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Renderer module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ + RenderSurface::~RenderSurface() = default; +} diff --git a/src/Nazara/Renderer/RenderWindow.cpp b/src/Nazara/Renderer/RenderWindow.cpp index 56626386e..117caaadf 100644 --- a/src/Nazara/Renderer/RenderWindow.cpp +++ b/src/Nazara/Renderer/RenderWindow.cpp @@ -35,14 +35,22 @@ namespace Nz bool RenderWindow::OnWindowCreated() { + auto surface = Renderer::GetRendererImpl()->CreateRenderSurfaceImpl(); + if (!surface->Create(GetHandle())) + { + NazaraError("Failed to create render surface: " + Error::GetLastError()); + return false; + } + auto impl = Renderer::GetRendererImpl()->CreateRenderWindowImpl(); - if (!impl->Create(GetHandle(), Vector2ui(GetWidth(), GetHeight()), m_parameters)) + if (!impl->Create(surface.get(), Vector2ui(GetWidth(), GetHeight()), m_parameters)) { NazaraError("Failed to create render window implementation: " + Error::GetLastError()); return false; } m_impl = std::move(impl); + m_surface = std::move(surface); m_clock.Restart(); @@ -52,6 +60,7 @@ namespace Nz void RenderWindow::OnWindowDestroy() { m_impl.reset(); + m_surface.reset(); } void RenderWindow::OnWindowResized() diff --git a/src/Nazara/VulkanRenderer/VkRenderWindow.cpp b/src/Nazara/VulkanRenderer/VkRenderWindow.cpp index b9a215318..524facc29 100644 --- a/src/Nazara/VulkanRenderer/VkRenderWindow.cpp +++ b/src/Nazara/VulkanRenderer/VkRenderWindow.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -14,7 +15,6 @@ namespace Nz { VkRenderWindow::VkRenderWindow() : - m_surface(Nz::Vulkan::GetInstance()), m_physicalDevice(nullptr), m_depthStencilFormat(VK_FORMAT_MAX_ENUM) { @@ -27,7 +27,6 @@ namespace Nz m_renderPass.Destroy(); m_swapchain.Destroy(); - m_surface.Destroy(); } bool VkRenderWindow::Acquire(UInt32* imageIndex) const @@ -65,25 +64,13 @@ namespace Nz //commandBuffer.SetImageLayout(m_swapchain.GetBuffer(imageIndex).image, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); } - bool VkRenderWindow::Create(WindowHandle handle, const Vector2ui& size, const RenderWindowParameters& parameters) + bool VkRenderWindow::Create(RenderSurface* surface, const Vector2ui& size, const RenderWindowParameters& parameters) { - #if defined(NAZARA_PLATFORM_WINDOWS) - HWND winHandle = reinterpret_cast(handle); - HINSTANCE instance = reinterpret_cast(GetWindowLongPtrW(winHandle, GWLP_HINSTANCE)); - bool success = m_surface.Create(instance, winHandle); - #else - #error This OS is not supported by Vulkan - #endif - - if (!success) - { - NazaraError("Failed to create Vulkan surface"); - return false; - } - m_physicalDevice = Vulkan::GetPhysicalDevices()[0].device; - m_device = Vulkan::SelectDevice(m_physicalDevice, m_surface, &m_presentableFamilyQueue); + Vk::Surface& vulkanSurface = static_cast(surface)->GetSurface(); + + m_device = Vulkan::SelectDevice(m_physicalDevice, vulkanSurface, &m_presentableFamilyQueue); if (!m_device) { NazaraError("Failed to get compatible Vulkan device"); @@ -93,7 +80,7 @@ namespace Nz m_presentQueue = m_device->GetQueue(m_presentableFamilyQueue, 0); std::vector surfaceFormats; - if (!m_surface.GetFormats(m_physicalDevice, &surfaceFormats)) + if (!vulkanSurface.GetFormats(m_physicalDevice, &surfaceFormats)) { NazaraError("Failed to query supported surface formats"); return false; @@ -159,7 +146,7 @@ namespace Nz } } - if (!SetupSwapchain(size)) + if (!SetupSwapchain(vulkanSurface, size)) { NazaraError("Failed to create swapchain"); return false; @@ -369,10 +356,10 @@ namespace Nz return m_renderPass.Create(m_device, createInfo); } - bool VkRenderWindow::SetupSwapchain(const Vector2ui& size) + bool VkRenderWindow::SetupSwapchain(Vk::Surface& surface, const Vector2ui& size) { VkSurfaceCapabilitiesKHR surfaceCapabilities; - if (!m_surface.GetCapabilities(m_physicalDevice, &surfaceCapabilities)) + if (!surface.GetCapabilities(m_physicalDevice, &surfaceCapabilities)) { NazaraError("Failed to query surface capabilities"); return false; @@ -392,7 +379,7 @@ namespace Nz extent = surfaceCapabilities.currentExtent; std::vector presentModes; - if (!m_surface.GetPresentModes(m_physicalDevice, &presentModes)) + if (!surface.GetPresentModes(m_physicalDevice, &presentModes)) { NazaraError("Failed to query supported present modes"); return false; @@ -415,7 +402,7 @@ namespace Nz VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, nullptr, 0, - m_surface, + surface, imageCount, m_colorFormat, m_colorSpace, diff --git a/src/Nazara/VulkanRenderer/Vulkan.cpp b/src/Nazara/VulkanRenderer/Vulkan.cpp index ce43249d3..3cab39710 100644 --- a/src/Nazara/VulkanRenderer/Vulkan.cpp +++ b/src/Nazara/VulkanRenderer/Vulkan.cpp @@ -392,7 +392,10 @@ namespace Nz } if (presentableQueueFamilyIndex != UINT32_MAX) + { *presentableFamilyQueue = presentableQueueFamilyIndex; + return device.CreateHandle(); + } } } diff --git a/src/Nazara/VulkanRenderer/VulkanDevice.cpp b/src/Nazara/VulkanRenderer/VulkanDevice.cpp new file mode 100644 index 000000000..bec1b3adb --- /dev/null +++ b/src/Nazara/VulkanRenderer/VulkanDevice.cpp @@ -0,0 +1,11 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ + VulkanDevice::~VulkanDevice() = default; +} diff --git a/src/Nazara/VulkanRenderer/VulkanRenderer.cpp b/src/Nazara/VulkanRenderer/VulkanRenderer.cpp index 861557507..7485be521 100644 --- a/src/Nazara/VulkanRenderer/VulkanRenderer.cpp +++ b/src/Nazara/VulkanRenderer/VulkanRenderer.cpp @@ -4,6 +4,9 @@ #include #include +#include +#include +#include #include #include #include @@ -15,11 +18,26 @@ namespace Nz Vulkan::Uninitialize(); } + std::unique_ptr VulkanRenderer::CreateHardwareBufferImpl(Buffer* parent, BufferType type) + { + return nullptr; //< TODO + } + + std::unique_ptr VulkanRenderer::CreateRenderSurfaceImpl() + { + return std::make_unique(); + } + std::unique_ptr VulkanRenderer::CreateRenderWindowImpl() { return std::make_unique(); } + std::unique_ptr VulkanRenderer::InstanciateRenderDevice(std::size_t deviceIndex) + { + return std::unique_ptr(); + } + bool VulkanRenderer::IsBetterThan(const RendererImpl* other) const { if (other->QueryAPI() == RenderAPI_Vulkan && QueryAPIVersion() < other->QueryAPIVersion()) @@ -41,14 +59,14 @@ namespace Nz String VulkanRenderer::QueryAPIString() const { StringStream ss; - ss << "Vulkan renderer " << VK_VERSION_MAJOR(m_apiVersion) << '.' << VK_VERSION_MINOR(m_apiVersion) << '.' << VK_VERSION_PATCH(m_apiVersion); + ss << "Vulkan renderer " << VK_VERSION_MAJOR(APIVersion) << '.' << VK_VERSION_MINOR(APIVersion) << '.' << VK_VERSION_PATCH(APIVersion); return ss; } UInt32 VulkanRenderer::QueryAPIVersion() const { - return m_apiVersion; + return APIVersion; } std::vector VulkanRenderer::QueryRenderDevices() const diff --git a/src/Nazara/VulkanRenderer/VulkanSurface.cpp b/src/Nazara/VulkanRenderer/VulkanSurface.cpp new file mode 100644 index 000000000..c7cd7f3d6 --- /dev/null +++ b/src/Nazara/VulkanRenderer/VulkanSurface.cpp @@ -0,0 +1,45 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include + +namespace Nz +{ + VulkanSurface::VulkanSurface() : + m_surface(Vulkan::GetInstance()) + { + } + + VulkanSurface::~VulkanSurface() = default; + + bool VulkanSurface::Create(WindowHandle handle) + { + bool success = false; + #if defined(NAZARA_PLATFORM_WINDOWS) + { + HWND winHandle = reinterpret_cast(handle); + HINSTANCE instance = reinterpret_cast(GetWindowLongPtrW(winHandle, GWLP_HINSTANCE)); + + success = m_surface.Create(instance, winHandle); + } + #else + #error This OS is not supported by Vulkan + #endif + + if (!success) + { + NazaraError("Failed to create Vulkan surface: " + TranslateVulkanError(m_surface.GetLastErrorCode())); + return false; + } + + return true; + } + + void VulkanSurface::Destroy() + { + m_surface.Destroy(); + } +}