Replace RenderWindow with swapchains

This commit is contained in:
SirLynix 2023-01-21 12:02:34 +01:00 committed by Jérôme Leclercq
parent 8db1c04568
commit 18851c9185
66 changed files with 1404 additions and 2048 deletions

View File

@ -13,6 +13,7 @@
#include <Nazara/Graphics/Graphics.hpp>
#include <Nazara/Graphics/Components/GraphicsComponent.hpp>
#include <Nazara/Graphics/Components/LightComponent.hpp>
#include <Nazara/Renderer/WindowSwapchain.hpp>
#include <Nazara/Utility/Node.hpp>
#include <Nazara/Utility/Skeleton.hpp>
#include <Nazara/Utils/MemoryPool.hpp>
@ -27,7 +28,6 @@ namespace Nz
class CommandBufferBuilder;
class FramePipeline;
class RenderFrame;
class RenderWindow;
class UploadPool;
class NAZARA_GRAPHICS_API RenderSystem
@ -41,7 +41,7 @@ namespace Nz
RenderSystem(RenderSystem&&) = delete;
~RenderSystem();
template<typename T = RenderWindow, typename... Args> T& CreateWindow(Args&&... args);
WindowSwapchain& CreateSwapchain(Window& window, const SwapchainParameters& parameters = SwapchainParameters{});
inline FramePipeline& GetFramePipeline();
inline const FramePipeline& GetFramePipeline() const;
@ -133,7 +133,7 @@ namespace Nz
std::unordered_set<GraphicsEntity*> m_newlyVisibleGfxEntities;
std::unordered_set<LightEntity*> m_newlyHiddenLightEntities;
std::unordered_set<LightEntity*> m_newlyVisibleLightEntities;
std::vector<std::unique_ptr<RenderWindow>> m_renderWindows;
std::vector<std::unique_ptr<WindowSwapchain>> m_windowSwapchains;
ElementRendererRegistry m_elementRegistry;
MemoryPool<CameraEntity> m_cameraEntityPool;
MemoryPool<GraphicsEntity> m_graphicsEntityPool;

View File

@ -8,19 +8,6 @@
namespace Nz
{
template<typename T, typename ...Args>
T& RenderSystem::CreateWindow(Args&& ...args)
{
static_assert(std::is_base_of_v<RenderWindow, T>, "T must inherit RenderWindow");
auto windowPtr = std::make_unique<T>(std::forward<Args>(args)...);
T& windowRef = *windowPtr;
m_renderWindows.emplace_back(std::move(windowPtr));
return windowRef;
}
inline FramePipeline& RenderSystem::GetFramePipeline()
{
return *m_pipeline;

View File

@ -30,7 +30,6 @@
#define NAZARA_GLOBAL_OPENGLRENDERER_HPP
#include <Nazara/OpenGLRenderer/Config.hpp>
#include <Nazara/OpenGLRenderer/DummySurface.hpp>
#include <Nazara/OpenGLRenderer/OpenGLBuffer.hpp>
#include <Nazara/OpenGLRenderer/OpenGLCommandBuffer.hpp>
#include <Nazara/OpenGLRenderer/OpenGLCommandBufferBuilder.hpp>
@ -44,9 +43,9 @@
#include <Nazara/OpenGLRenderer/OpenGLRenderPass.hpp>
#include <Nazara/OpenGLRenderer/OpenGLRenderPipeline.hpp>
#include <Nazara/OpenGLRenderer/OpenGLRenderPipelineLayout.hpp>
#include <Nazara/OpenGLRenderer/OpenGLRenderWindow.hpp>
#include <Nazara/OpenGLRenderer/OpenGLShaderBinding.hpp>
#include <Nazara/OpenGLRenderer/OpenGLShaderModule.hpp>
#include <Nazara/OpenGLRenderer/OpenGLSwapchain.hpp>
#include <Nazara/OpenGLRenderer/OpenGLTexture.hpp>
#include <Nazara/OpenGLRenderer/OpenGLTextureSampler.hpp>
#include <Nazara/OpenGLRenderer/OpenGLUploadPool.hpp>

View File

@ -1,34 +0,0 @@
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - OpenGL renderer"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_OPENGLRENDERER_DUMMYSURFACE_HPP
#define NAZARA_OPENGLRENDERER_DUMMYSURFACE_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/OpenGLRenderer/Config.hpp>
#include <Nazara/Renderer/RenderSurface.hpp>
namespace Nz
{
class NAZARA_OPENGLRENDERER_API DummySurface : public RenderSurface
{
public:
DummySurface() = default;
~DummySurface() = default;
bool Create(WindowHandle handle) override;
void Destroy() override;
inline WindowHandle GetWindowHandle() const;
private:
WindowHandle m_handle;
};
}
#include <Nazara/OpenGLRenderer/DummySurface.inl>
#endif // NAZARA_OPENGLRENDERER_DUMMYSURFACE_HPP

View File

@ -1,16 +0,0 @@
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - OpenGL renderer"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/OpenGLRenderer/DummySurface.hpp>
#include <Nazara/OpenGLRenderer/Debug.hpp>
namespace Nz
{
inline WindowHandle DummySurface::GetWindowHandle() const
{
return m_handle;
}
}
#include <Nazara/OpenGLRenderer/DebugOff.hpp>

View File

@ -45,6 +45,7 @@ namespace Nz
std::shared_ptr<RenderPipelineLayout> InstantiateRenderPipelineLayout(RenderPipelineLayoutInfo pipelineLayoutInfo) override;
std::shared_ptr<ShaderModule> InstantiateShaderModule(nzsl::ShaderStageTypeFlags shaderStages, const nzsl::Ast::Module& shaderModule, const nzsl::ShaderWriter::States& states) override;
std::shared_ptr<ShaderModule> InstantiateShaderModule(nzsl::ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize, const nzsl::ShaderWriter::States& states) override;
std::shared_ptr<Swapchain> InstantiateSwapchain(WindowHandle windowHandle, const Vector2ui& windowSize, const SwapchainParameters& parameters) override;
std::shared_ptr<Texture> InstantiateTexture(const TextureInfo& params) override;
std::shared_ptr<TextureSampler> InstantiateTextureSampler(const TextureSamplerInfo& params) override;

View File

@ -15,12 +15,12 @@
namespace Nz
{
class OpenGLCommandBuffer;
class OpenGLRenderWindow;
class OpenGLSwapchain;
class NAZARA_OPENGLRENDERER_API OpenGLRenderImage : public RenderImage
{
public:
OpenGLRenderImage(OpenGLRenderWindow& owner);
OpenGLRenderImage(OpenGLSwapchain& owner);
void Execute(const FunctionRef<void(CommandBufferBuilder& builder)>& callback, QueueTypeFlags queueTypeFlags) override;
@ -31,7 +31,7 @@ namespace Nz
void SubmitCommandBuffer(CommandBuffer* commandBuffer, QueueTypeFlags queueTypeFlags) override;
private:
OpenGLRenderWindow& m_owner;
OpenGLSwapchain& m_owner;
OpenGLUploadPool m_uploadPool;
};
}

View File

@ -22,9 +22,6 @@ namespace Nz
OpenGLRenderer() = default;
~OpenGLRenderer();
std::unique_ptr<RenderSurface> CreateRenderSurfaceImpl() override;
std::unique_ptr<RenderWindowImpl> CreateRenderWindowImpl(RenderWindow& owner) override;
std::shared_ptr<RenderDevice> InstanciateRenderDevice(std::size_t deviceIndex, const RenderDeviceFeatures& enabledFeatures) override;
RenderAPI QueryAPI() const override;

View File

@ -14,23 +14,21 @@
#include <Nazara/OpenGLRenderer/OpenGLRenderPass.hpp>
#include <Nazara/OpenGLRenderer/OpenGLWindowFramebuffer.hpp>
#include <Nazara/OpenGLRenderer/Wrapper/Context.hpp>
#include <Nazara/Renderer/RenderWindowImpl.hpp>
#include <Nazara/Renderer/Swapchain.hpp>
#include <Nazara/Renderer/SwapchainParameters.hpp>
#include <optional>
#include <vector>
namespace Nz
{
class RenderWindow;
class NAZARA_OPENGLRENDERER_API OpenGLRenderWindow final : public RenderWindowImpl
class NAZARA_OPENGLRENDERER_API OpenGLSwapchain final : public Swapchain
{
public:
OpenGLRenderWindow(RenderWindow& owner);
~OpenGLRenderWindow() = default;
OpenGLSwapchain(OpenGLDevice& device, WindowHandle windowHandle, const Vector2ui& windowSize, const SwapchainParameters& parameters);
~OpenGLSwapchain() = default;
RenderFrame Acquire() override;
RenderFrame AcquireFrame() override;
bool Create(RendererImpl* renderer, RenderSurface* surface, const RenderWindowParameters& parameters) override;
std::shared_ptr<CommandPool> CreateCommandPool(QueueType queueType) override;
inline GL::Context& GetContext();
@ -39,6 +37,8 @@ namespace Nz
const OpenGLRenderPass& GetRenderPass() const override;
const Vector2ui& GetSize() const override;
void NotifyResize(const Vector2ui& newSize) override;
void Present();
private:
@ -47,11 +47,11 @@ namespace Nz
std::vector<std::unique_ptr<OpenGLRenderImage>> m_renderImage;
std::unique_ptr<GL::Context> m_context;
OpenGLWindowFramebuffer m_framebuffer;
RenderWindow& m_owner;
Vector2ui m_size;
bool m_sizeInvalidated;
};
}
#include <Nazara/OpenGLRenderer/OpenGLRenderWindow.inl>
#include <Nazara/OpenGLRenderer/OpenGLSwapchain.inl>
#endif // NAZARA_OPENGLRENDERER_OPENGLRENDERWINDOW_HPP

View File

@ -2,13 +2,13 @@
// This file is part of the "Nazara Engine - OpenGL renderer"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/OpenGLRenderer/OpenGLRenderWindow.hpp>
#include <Nazara/OpenGLRenderer/OpenGLSwapchain.hpp>
#include <cassert>
#include <Nazara/OpenGLRenderer/Debug.hpp>
namespace Nz
{
inline GL::Context& OpenGLRenderWindow::GetContext()
inline GL::Context& OpenGLSwapchain::GetContext()
{
assert(m_context);
return *m_context;

View File

@ -12,12 +12,12 @@
namespace Nz
{
class OpenGLRenderWindow;
class OpenGLSwapchain;
class NAZARA_OPENGLRENDERER_API OpenGLWindowFramebuffer : public OpenGLFramebuffer
{
public:
inline OpenGLWindowFramebuffer(OpenGLRenderWindow& renderWindow);
inline OpenGLWindowFramebuffer(OpenGLSwapchain& renderWindow);
OpenGLWindowFramebuffer(const OpenGLWindowFramebuffer&) = delete;
OpenGLWindowFramebuffer(OpenGLWindowFramebuffer&&) noexcept = default;
~OpenGLWindowFramebuffer() = default;
@ -34,7 +34,7 @@ namespace Nz
OpenGLWindowFramebuffer& operator=(OpenGLWindowFramebuffer&&) = delete;
private:
OpenGLRenderWindow& m_renderWindow;
OpenGLSwapchain& m_renderWindow;
};
}

View File

@ -7,7 +7,7 @@
namespace Nz
{
inline OpenGLWindowFramebuffer::OpenGLWindowFramebuffer(OpenGLRenderWindow& renderWindow) :
inline OpenGLWindowFramebuffer::OpenGLWindowFramebuffer(OpenGLSwapchain& renderWindow) :
OpenGLFramebuffer(FramebufferType::Window),
m_renderWindow(renderWindow)
{

View File

@ -34,8 +34,8 @@
#include <Nazara/Platform/Cursor.hpp>
#include <Nazara/Platform/CursorController.hpp>
#include <Nazara/Platform/Enums.hpp>
#include <Nazara/Platform/Event.hpp>
#include <Nazara/Platform/EventHandler.hpp>
#include <Nazara/Platform/WindowEvent.hpp>
#include <Nazara/Platform/WindowEventHandler.hpp>
#include <Nazara/Platform/Icon.hpp>
#include <Nazara/Platform/Joystick.hpp>
#include <Nazara/Platform/Keyboard.hpp>

View File

@ -48,10 +48,13 @@ namespace Nz
enum class WindowEventType
{
Created,
Destruction,
GainedFocus,
LostFocus,
KeyPressed,
KeyReleased,
Minimized,
MouseButtonPressed,
MouseButtonReleased,
MouseEntered,
@ -61,6 +64,7 @@ namespace Nz
Moved,
Quit,
Resized,
Restored,
TextEdited,
TextEntered,

View File

@ -1,57 +0,0 @@
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Platform module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_PLATFORM_EVENTHANDLER_HPP
#define NAZARA_PLATFORM_EVENTHANDLER_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Core/HandledObject.hpp>
#include <Nazara/Core/ObjectHandle.hpp>
#include <Nazara/Platform/Config.hpp>
#include <Nazara/Platform/Event.hpp>
#include <Nazara/Utils/Signal.hpp>
namespace Nz
{
class EventHandler;
using EventHandlerHandle = ObjectHandle<EventHandler>;
class EventHandler : public HandledObject<EventHandler>
{
public:
EventHandler() = default;
explicit EventHandler(const EventHandler&);
EventHandler(EventHandler&&) noexcept = default;
~EventHandler() = default;
inline void Dispatch(const WindowEvent& event);
EventHandler& operator=(const EventHandler&) = delete;
EventHandler& operator=(EventHandler&&) noexcept = default;
NazaraSignal(OnEvent, const EventHandler* /*eventHandler*/, const WindowEvent& /*event*/);
NazaraSignal(OnGainedFocus, const EventHandler* /*eventHandler*/);
NazaraSignal(OnLostFocus, const EventHandler* /*eventHandler*/);
NazaraSignal(OnKeyPressed, const EventHandler* /*eventHandler*/, const WindowEvent::KeyEvent& /*event*/);
NazaraSignal(OnKeyReleased, const EventHandler* /*eventHandler*/, const WindowEvent::KeyEvent& /*event*/);
NazaraSignal(OnMouseButtonPressed, const EventHandler* /*eventHandler*/, const WindowEvent::MouseButtonEvent& /*event*/);
NazaraSignal(OnMouseButtonReleased, const EventHandler* /*eventHandler*/, const WindowEvent::MouseButtonEvent& /*event*/);
NazaraSignal(OnMouseEntered, const EventHandler* /*eventHandler*/);
NazaraSignal(OnMouseLeft, const EventHandler* /*eventHandler*/);
NazaraSignal(OnMouseMoved, const EventHandler* /*eventHandler*/, const WindowEvent::MouseMoveEvent& /*event*/);
NazaraSignal(OnMouseWheelMoved, const EventHandler* /*eventHandler*/, const WindowEvent::MouseWheelEvent& /*event*/);
NazaraSignal(OnMoved, const EventHandler* /*eventHandler*/, const WindowEvent::PositionEvent& /*event*/);
NazaraSignal(OnQuit, const EventHandler* /*eventHandler*/);
NazaraSignal(OnResized, const EventHandler* /*eventHandler*/, const WindowEvent::SizeEvent& /*event*/);
NazaraSignal(OnTextEntered, const EventHandler* /*eventHandler*/, const WindowEvent::TextEvent& /*event*/);
NazaraSignal(OnTextEdited, const EventHandler* /*eventHandler*/, const WindowEvent::EditEvent& /*event*/);
};
}
#include <Nazara/Platform/EventHandler.inl>
#endif // NAZARA_PLATFORM_EVENTHANDLER_HPP

View File

@ -15,7 +15,7 @@
#include <Nazara/Platform/Cursor.hpp>
#include <Nazara/Platform/CursorController.hpp>
#include <Nazara/Platform/Enums.hpp>
#include <Nazara/Platform/EventHandler.hpp>
#include <Nazara/Platform/WindowEventHandler.hpp>
#include <Nazara/Platform/Icon.hpp>
#include <Nazara/Platform/VideoMode.hpp>
#include <Nazara/Platform/WindowHandle.hpp>
@ -38,35 +38,31 @@ namespace Nz
public:
Window();
inline Window(VideoMode mode, const std::string& title, WindowStyleFlags style = WindowStyle_Default);
inline explicit Window(void* handle);
inline explicit Window(WindowHandle handle);
Window(const Window&) = delete;
Window(Window&& window);
virtual ~Window();
Window(Window&& window) noexcept;
~Window();
inline void Close();
bool Create(VideoMode mode, const std::string& title, WindowStyleFlags style = WindowStyle_Default);
bool Create(void* handle);
bool Create(WindowHandle handle);
void Destroy();
inline void EnableCloseOnQuit(bool closeOnQuit);
NAZARA_DEPRECATED("Event pooling/waiting is deprecated, please use the EventHandler system")
inline void EnableEventPolling(bool enable);
void EnableKeyRepeat(bool enable);
void EnableSmoothScrolling(bool enable);
inline const std::shared_ptr<Cursor>& GetCursor() const;
inline CursorController& GetCursorController();
inline EventHandler& GetEventHandler();
inline WindowEventHandler& GetEventHandler();
WindowHandle GetHandle() const;
Vector2i GetPosition() const;
Vector2ui GetSize() const;
WindowStyleFlags GetStyle() const;
WindowHandle GetSystemHandle() const;
std::string GetTitle() const;
void HandleEvent(const WindowEvent& event);
bool HasFocus() const;
bool IsMinimized() const;
@ -75,16 +71,8 @@ namespace Nz
inline bool IsValid() const;
bool IsVisible() const;
NAZARA_DEPRECATED("Event pooling/waiting is deprecated, please use the EventHandler system")
bool PollEvent(WindowEvent* event);
void PushEvent(const WindowEvent& event);
void ProcessEvents(bool block = false);
void SetCursor(std::shared_ptr<Cursor> cursor);
inline void SetCursor(SystemCursor systemCursor);
void SetEventListener(bool listener);
void SetFocus();
void SetIcon(std::shared_ptr<Icon> icon);
void SetMaximumSize(const Vector2i& maxSize);
@ -99,20 +87,10 @@ namespace Nz
void SetTitle(const std::string& title);
void SetVisible(bool visible);
NAZARA_DEPRECATED("Event pooling/waiting is deprecated, please use the EventHandler system")
bool WaitEvent(WindowEvent* event);
Window& operator=(const Window&) = delete;
Window& operator=(Window&& window);
Window& operator=(Window&& window) noexcept;
protected:
void* GetHandle();
virtual bool OnWindowCreated();
virtual void OnWindowDestroy();
virtual void OnWindowResized();
MovablePtr<WindowImpl> m_impl;
static void ProcessEvents();
private:
void ConnectSlots();
@ -122,26 +100,21 @@ namespace Nz
inline const WindowImpl* GetImpl() const;
void IgnoreNextMouseEvent(int mouseX, int mouseY) const;
void HandleEvent(const WindowEvent& event);
static bool Initialize();
static void Uninitialize();
NazaraSlot(CursorController, OnCursorUpdated, m_cursorUpdateSlot);
std::queue<WindowEvent> m_events;
std::vector<WindowEvent> m_pendingEvents;
std::condition_variable m_eventCondition;
CursorController m_cursorController;
std::shared_ptr<Cursor> m_cursor;
EventHandler m_eventHandler;
std::shared_ptr<Icon> m_icon;
std::mutex m_eventMutex;
std::mutex m_eventConditionMutex;
bool m_asyncWindow;
std::unique_ptr<WindowImpl> m_impl;
CursorController m_cursorController;
Vector2i m_position;
Vector2ui m_size;
WindowEventHandler m_eventHandler;
bool m_closed;
bool m_closeOnQuit;
bool m_eventPolling;
bool m_ownsWindow;
bool m_waitForEvent;
};

View File

@ -19,7 +19,7 @@ namespace Nz
Create(mode, title, style);
}
inline Window::Window(void* handle) :
inline Window::Window(WindowHandle handle) :
Window()
{
ErrorFlags flags(ErrorMode::ThrowException, true);
@ -36,16 +36,6 @@ namespace Nz
m_closeOnQuit = closeOnQuit;
}
inline void Window::EnableEventPolling(bool enable)
{
m_eventPolling = enable;
if (!m_eventPolling)
{
while (!m_events.empty())
m_events.pop();
}
}
inline const std::shared_ptr<Cursor>& Window::GetCursor() const
{
return m_cursor;
@ -56,7 +46,7 @@ namespace Nz
return m_cursorController;
}
inline EventHandler& Nz::Window::GetEventHandler()
inline WindowEventHandler& Nz::Window::GetEventHandler()
{
return m_eventHandler;
}
@ -90,34 +80,14 @@ namespace Nz
SetCursor(Cursor::Get(systemCursor));
}
inline void Window::PushEvent(const WindowEvent& event)
{
if (!m_asyncWindow)
HandleEvent(event);
else
{
{
std::lock_guard<std::mutex> eventLock(m_eventMutex);
m_pendingEvents.push_back(event);
}
if (m_waitForEvent)
{
std::lock_guard<std::mutex> lock(m_eventConditionMutex);
m_eventCondition.notify_all();
}
}
}
inline WindowImpl* Window::GetImpl()
{
return m_impl;
return m_impl.get();
}
inline const WindowImpl* Window::GetImpl() const
{
return m_impl;
return m_impl.get();
}
}

View File

@ -9,11 +9,10 @@
#ifndef NAZARA_PLATFORM_EVENT_HPP
#define NAZARA_PLATFORM_EVENT_HPP
#include <array>
#include <Nazara/Platform/Enums.hpp>
#include <Nazara/Platform/Keyboard.hpp>
#include <Nazara/Platform/Mouse.hpp>
#include <array>
namespace Nz
{

View File

@ -0,0 +1,61 @@
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Platform module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_PLATFORM_EVENTHANDLER_HPP
#define NAZARA_PLATFORM_EVENTHANDLER_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Core/HandledObject.hpp>
#include <Nazara/Core/ObjectHandle.hpp>
#include <Nazara/Platform/Config.hpp>
#include <Nazara/Platform/WindowEvent.hpp>
#include <Nazara/Utils/Signal.hpp>
namespace Nz
{
class WindowEventHandler;
using EventHandlerHandle = ObjectHandle<WindowEventHandler>;
class WindowEventHandler : public HandledObject<WindowEventHandler>
{
public:
WindowEventHandler() = default;
explicit WindowEventHandler(const WindowEventHandler&);
WindowEventHandler(WindowEventHandler&&) noexcept = default;
~WindowEventHandler() = default;
inline void Dispatch(const WindowEvent& event);
WindowEventHandler& operator=(const WindowEventHandler&) = delete;
WindowEventHandler& operator=(WindowEventHandler&&) noexcept = default;
NazaraSignal(OnCreated, const WindowEventHandler* /*eventHandler*/);
NazaraSignal(OnDestruction, const WindowEventHandler* /*eventHandler*/);
NazaraSignal(OnEvent, const WindowEventHandler* /*eventHandler*/, const WindowEvent& /*event*/);
NazaraSignal(OnGainedFocus, const WindowEventHandler* /*eventHandler*/);
NazaraSignal(OnLostFocus, const WindowEventHandler* /*eventHandler*/);
NazaraSignal(OnKeyPressed, const WindowEventHandler* /*eventHandler*/, const WindowEvent::KeyEvent& /*event*/);
NazaraSignal(OnKeyReleased, const WindowEventHandler* /*eventHandler*/, const WindowEvent::KeyEvent& /*event*/);
NazaraSignal(OnMinimized, const WindowEventHandler* /*eventHandler*/);
NazaraSignal(OnMouseButtonPressed, const WindowEventHandler* /*eventHandler*/, const WindowEvent::MouseButtonEvent& /*event*/);
NazaraSignal(OnMouseButtonReleased, const WindowEventHandler* /*eventHandler*/, const WindowEvent::MouseButtonEvent& /*event*/);
NazaraSignal(OnMouseEntered, const WindowEventHandler* /*eventHandler*/);
NazaraSignal(OnMouseLeft, const WindowEventHandler* /*eventHandler*/);
NazaraSignal(OnMouseMoved, const WindowEventHandler* /*eventHandler*/, const WindowEvent::MouseMoveEvent& /*event*/);
NazaraSignal(OnMouseWheelMoved, const WindowEventHandler* /*eventHandler*/, const WindowEvent::MouseWheelEvent& /*event*/);
NazaraSignal(OnMoved, const WindowEventHandler* /*eventHandler*/, const WindowEvent::PositionEvent& /*event*/);
NazaraSignal(OnQuit, const WindowEventHandler* /*eventHandler*/);
NazaraSignal(OnResized, const WindowEventHandler* /*eventHandler*/, const WindowEvent::SizeEvent& /*event*/);
NazaraSignal(OnRestored, const WindowEventHandler* /*eventHandler*/);
NazaraSignal(OnTextEntered, const WindowEventHandler* /*eventHandler*/, const WindowEvent::TextEvent& /*event*/);
NazaraSignal(OnTextEdited, const WindowEventHandler* /*eventHandler*/, const WindowEvent::EditEvent& /*event*/);
};
}
#include <Nazara/Platform/WindowEventHandler.inl>
#endif // NAZARA_PLATFORM_EVENTHANDLER_HPP

View File

@ -2,23 +2,31 @@
// This file is part of the "Nazara Engine - Platform module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Platform/EventHandler.hpp>
#include <Nazara/Platform/WindowEventHandler.hpp>
#include <memory>
#include <Nazara/Platform/Debug.hpp>
namespace Nz
{
inline EventHandler::EventHandler(const EventHandler& other) :
inline WindowEventHandler::WindowEventHandler(const WindowEventHandler& other) :
HandledObject(other)
{
}
inline void EventHandler::Dispatch(const WindowEvent& event)
inline void WindowEventHandler::Dispatch(const WindowEvent& event)
{
OnEvent(this, event);
switch (event.type)
{
case WindowEventType::Created:
OnCreated(this);
break;
case WindowEventType::Destruction:
OnDestruction(this);
break;
case WindowEventType::GainedFocus:
OnGainedFocus(this);
break;
@ -35,6 +43,10 @@ namespace Nz
OnLostFocus(this);
break;
case WindowEventType::Minimized:
OnMinimized(this);
break;
case WindowEventType::MouseButtonPressed:
OnMouseButtonPressed(this, event.mouseButton);
break;
@ -71,6 +83,10 @@ namespace Nz
OnResized(this, event.size);
break;
case WindowEventType::Restored:
OnRestored(this);
break;
case WindowEventType::TextEntered:
OnTextEntered(this, event.text);
break;

View File

@ -51,15 +51,14 @@
#include <Nazara/Renderer/RenderPipeline.hpp>
#include <Nazara/Renderer/RenderPipelineLayout.hpp>
#include <Nazara/Renderer/RenderStates.hpp>
#include <Nazara/Renderer/RenderSurface.hpp>
#include <Nazara/Renderer/RenderTarget.hpp>
#include <Nazara/Renderer/RenderWindow.hpp>
#include <Nazara/Renderer/RenderWindowImpl.hpp>
#include <Nazara/Renderer/RenderWindowParameters.hpp>
#include <Nazara/Renderer/ShaderBinding.hpp>
#include <Nazara/Renderer/ShaderModule.hpp>
#include <Nazara/Renderer/Swapchain.hpp>
#include <Nazara/Renderer/SwapchainParameters.hpp>
#include <Nazara/Renderer/Texture.hpp>
#include <Nazara/Renderer/TextureSampler.hpp>
#include <Nazara/Renderer/UploadPool.hpp>
#include <Nazara/Renderer/WindowSwapchain.hpp>
#endif // NAZARA_GLOBAL_RENDERER_HPP

View File

@ -17,6 +17,8 @@
#include <Nazara/Renderer/RenderPass.hpp>
#include <Nazara/Renderer/RenderPipeline.hpp>
#include <Nazara/Renderer/RenderPipelineLayout.hpp>
#include <Nazara/Renderer/Swapchain.hpp>
#include <Nazara/Renderer/SwapchainParameters.hpp>
#include <Nazara/Renderer/Texture.hpp>
#include <Nazara/Renderer/TextureSampler.hpp>
#include <Nazara/Utility/PixelFormat.hpp>
@ -49,6 +51,7 @@ namespace Nz
virtual std::shared_ptr<ShaderModule> InstantiateShaderModule(nzsl::ShaderStageTypeFlags shaderStages, const nzsl::Ast::Module& shaderModule, const nzsl::ShaderWriter::States& states) = 0;
virtual std::shared_ptr<ShaderModule> InstantiateShaderModule(nzsl::ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize, const nzsl::ShaderWriter::States& states) = 0;
std::shared_ptr<ShaderModule> InstantiateShaderModule(nzsl::ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const std::filesystem::path& sourcePath, const nzsl::ShaderWriter::States& states);
virtual std::shared_ptr<Swapchain> InstantiateSwapchain(WindowHandle windowHandle, const Vector2ui& windowSize, const SwapchainParameters& parameters) = 0;
virtual std::shared_ptr<Texture> InstantiateTexture(const TextureInfo& params) = 0;
virtual std::shared_ptr<TextureSampler> InstantiateTextureSampler(const TextureSamplerInfo& params) = 0;

View File

@ -1,30 +0,0 @@
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// 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_RENDERER_RENDERSURFACE_HPP
#define NAZARA_RENDERER_RENDERSURFACE_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Platform/WindowHandle.hpp>
#include <Nazara/Renderer/Config.hpp>
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 <Nazara/Renderer/RenderSurface.inl>
#endif // NAZARA_RENDERER_RENDERSURFACE_HPP

View File

@ -1,12 +0,0 @@
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Renderer module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Renderer/RenderSurface.hpp>
#include <Nazara/Renderer/Debug.hpp>
namespace Nz
{
}
#include <Nazara/Renderer/DebugOff.hpp>

View File

@ -1,67 +0,0 @@
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// 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_RENDERER_RENDERWINDOW_HPP
#define NAZARA_RENDERER_RENDERWINDOW_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Core/Clock.hpp>
#include <Nazara/Math/Rect.hpp>
#include <Nazara/Math/Vector3.hpp>
#include <Nazara/Platform/Window.hpp>
#include <Nazara/Renderer/RenderSurface.hpp>
#include <Nazara/Renderer/RenderWindowImpl.hpp>
#include <Nazara/Renderer/RenderWindowParameters.hpp>
#include <memory>
namespace Nz
{
class RenderDevice;
class NAZARA_RENDERER_API RenderWindow : public Window
{
public:
inline RenderWindow();
inline RenderWindow(std::shared_ptr<RenderDevice> renderDevice, VideoMode mode, const std::string& title, WindowStyleFlags style = WindowStyle_Default, const RenderWindowParameters& parameters = RenderWindowParameters());
inline RenderWindow(std::shared_ptr<RenderDevice> renderDevice, void* handle, const RenderWindowParameters& parameters = RenderWindowParameters());
inline ~RenderWindow();
RenderFrame AcquireFrame();
bool Create(std::shared_ptr<RenderDevice> renderDevice, VideoMode mode, const std::string& title, WindowStyleFlags style = WindowStyle_Default, const RenderWindowParameters& parameters = RenderWindowParameters());
bool Create(std::shared_ptr<RenderDevice> renderDevice, void* handle, const RenderWindowParameters &parameters = RenderWindowParameters());
void EnableVerticalSync(bool enabled);
inline const std::shared_ptr<RenderDevice>& GetRenderDevice() const;
inline const RenderTarget* GetRenderTarget() const;
inline RenderSurface* GetSurface();
inline bool IsValid() const;
inline void SetFramerateLimit(unsigned int limit);
RenderWindow &operator=(const RenderWindow &) = delete;
RenderWindow &operator=(RenderWindow &&) = delete; ///TODO
protected:
bool OnWindowCreated() override;
void OnWindowDestroy() override;
void OnWindowResized() override;
private:
std::shared_ptr<RenderDevice> m_renderDevice;
std::unique_ptr<RenderSurface> m_surface;
std::unique_ptr<RenderWindowImpl> m_impl;
MillisecondClock m_clock;
RenderWindowParameters m_parameters;
unsigned int m_framerateLimit;
};
} // namespace Nz
#include <Nazara/Renderer/RenderWindow.inl>
#endif // NAZARA_RENDERER_RENDERWINDOW_HPP

View File

@ -1,62 +0,0 @@
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Renderer module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Renderer/RenderWindow.hpp>
#include <Nazara/Core/ErrorFlags.hpp>
#include <Nazara/Renderer/Debug.hpp>
namespace Nz
{
inline RenderWindow::RenderWindow() :
m_framerateLimit(0U)
{
}
inline RenderWindow::RenderWindow(std::shared_ptr<RenderDevice> renderDevice, VideoMode mode, const std::string& title, WindowStyleFlags style, const RenderWindowParameters& parameters) :
RenderWindow()
{
ErrorFlags errFlags(ErrorMode::ThrowException, true);
Create(std::move(renderDevice), mode, title, style, parameters);
}
inline RenderWindow::RenderWindow(std::shared_ptr<RenderDevice> renderDevice, void* handle, const RenderWindowParameters& parameters)
{
ErrorFlags errFlags(ErrorMode::ThrowException, true);
Create(std::move(renderDevice), handle, parameters);
}
inline RenderWindow::~RenderWindow()
{
Destroy();
}
inline const std::shared_ptr<RenderDevice>& RenderWindow::GetRenderDevice() const
{
return m_renderDevice;
}
inline const RenderTarget* RenderWindow::GetRenderTarget() const
{
return m_impl.get();
}
inline RenderSurface* RenderWindow::GetSurface()
{
return m_surface.get();
}
inline bool RenderWindow::IsValid() const
{
return m_impl != nullptr;
}
inline void RenderWindow::SetFramerateLimit(unsigned int limit)
{
m_framerateLimit = limit;
}
}
#include <Nazara/Renderer/DebugOff.hpp>

View File

@ -23,8 +23,8 @@ namespace Nz
class RendererImpl;
class RenderDevice;
class RenderSurface;
class RenderWindow;
class RenderWindowImpl;
class WindowSwapchain;
class Swapchain;
using CreateRendererImplFunc = RendererImpl*(*)();
@ -34,9 +34,6 @@ namespace Nz
RendererImpl() = default;
virtual ~RendererImpl();
virtual std::unique_ptr<RenderSurface> CreateRenderSurfaceImpl() = 0;
virtual std::unique_ptr<RenderWindowImpl> CreateRenderWindowImpl(RenderWindow& owner) = 0;
virtual std::shared_ptr<RenderDevice> InstanciateRenderDevice(std::size_t deviceIndex, const RenderDeviceFeatures& enabledFeatures) = 0;
virtual RenderAPI QueryAPI() const = 0;

View File

@ -4,41 +4,38 @@
#pragma once
#ifndef NAZARA_RENDERER_RENDERWINDOWIMPL_HPP
#define NAZARA_RENDERER_RENDERWINDOWIMPL_HPP
#ifndef NAZARA_RENDERER_SWAPCHAIN_HPP
#define NAZARA_RENDERER_SWAPCHAIN_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Math/Vector2.hpp>
#include <Nazara/Platform/WindowHandle.hpp>
#include <Nazara/Renderer/Config.hpp>
#include <Nazara/Renderer/RenderDevice.hpp>
#include <Nazara/Renderer/RenderFrame.hpp>
#include <Nazara/Renderer/RenderPass.hpp>
#include <Nazara/Renderer/RenderTarget.hpp>
#include <Nazara/Renderer/RenderWindowParameters.hpp>
#include <vector>
namespace Nz
{
class CommandPool;
class RendererImpl;
class RenderDevice;
class RenderSurface;
class NAZARA_RENDERER_API RenderWindowImpl : public RenderTarget
class NAZARA_RENDERER_API Swapchain : public RenderTarget
{
public:
RenderWindowImpl() = default;
virtual ~RenderWindowImpl();
Swapchain() = default;
virtual ~Swapchain();
virtual RenderFrame Acquire() = 0;
virtual RenderFrame AcquireFrame() = 0;
virtual bool Create(RendererImpl* renderer, RenderSurface* surface, const RenderWindowParameters& parameters) = 0;
virtual std::shared_ptr<CommandPool> CreateCommandPool(QueueType queueType) = 0;
virtual void NotifyResize(const Vector2ui& newSize) = 0;
protected:
static void BuildRenderPass(PixelFormat colorFormat, PixelFormat depthFormat, std::vector<RenderPass::Attachment>& attachments, std::vector<RenderPass::SubpassDescription>& subpassDescriptions, std::vector<RenderPass::SubpassDependency>& subpassDependencies);
};
}
#endif // NAZARA_RENDERER_RENDERWINDOWIMPL_HPP
#endif // NAZARA_RENDERER_SWAPCHAIN_HPP

View File

@ -13,7 +13,7 @@
namespace Nz
{
struct RenderWindowParameters
struct SwapchainParameters
{
std::vector<PixelFormat> depthFormats = {Nz::PixelFormat::Depth24Stencil8, Nz::PixelFormat::Depth32FStencil8, Nz::PixelFormat::Depth16Stencil8, Nz::PixelFormat::Depth32F, Nz::PixelFormat::Depth24}; //< By order of preference
bool verticalSync = false;

View File

@ -0,0 +1,65 @@
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// 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_RENDERER_RENDERWINDOW_HPP
#define NAZARA_RENDERER_RENDERWINDOW_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Platform/WindowEventHandler.hpp>
#include <Nazara/Renderer/Swapchain.hpp>
#include <Nazara/Renderer/SwapchainParameters.hpp>
#include <memory>
namespace Nz
{
class RenderDevice;
class Window;
class NAZARA_RENDERER_API WindowSwapchain
{
public:
WindowSwapchain(std::shared_ptr<RenderDevice> renderDevice, Window& window, SwapchainParameters parameters = SwapchainParameters());
WindowSwapchain(const WindowSwapchain&) = delete;
inline WindowSwapchain(WindowSwapchain&& windowSwapchain) noexcept;
~WindowSwapchain() = default;
inline RenderFrame AcquireFrame();
inline bool DoesRenderOnlyIfFocused() const;
inline void EnableRenderOnlyIfFocused(bool enable = true);
inline Swapchain& GetSwapchain();
inline const Swapchain& GetSwapchain() const;
WindowSwapchain& operator=(const WindowSwapchain&) = default;
inline WindowSwapchain& operator=(WindowSwapchain&& windowSwapchain) noexcept;
private:
void ConnectSignals();
inline void DisconnectSignals();
NazaraSlot(WindowEventHandler, OnCreated, m_onCreated);
NazaraSlot(WindowEventHandler, OnDestruction, m_onDestruction);
NazaraSlot(WindowEventHandler, OnGainedFocus, m_onGainedFocus);
NazaraSlot(WindowEventHandler, OnLostFocus, m_onLostFocus);
NazaraSlot(WindowEventHandler, OnMinimized, m_onMinimized);
NazaraSlot(WindowEventHandler, OnResized, m_onResized);
NazaraSlot(WindowEventHandler, OnRestored, m_onRestored);
std::shared_ptr<RenderDevice> m_renderDevice;
std::shared_ptr<Swapchain> m_swapchain;
MovablePtr<Window> m_window;
SwapchainParameters m_parameters;
bool m_renderOnlyIfFocused;
bool m_hasFocus;
bool m_isMinimized;
};
}
#include <Nazara/Renderer/WindowSwapchain.inl>
#endif // NAZARA_RENDERER_RENDERWINDOW_HPP

View File

@ -0,0 +1,76 @@
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Renderer module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Renderer/WindowSwapchain.hpp>
#include <Nazara/Core/ErrorFlags.hpp>
#include <Nazara/Renderer/Debug.hpp>
namespace Nz
{
inline WindowSwapchain::WindowSwapchain(WindowSwapchain&& windowSwapchain) noexcept :
m_renderDevice(std::move(windowSwapchain.m_renderDevice)),
m_swapchain(std::move(windowSwapchain.m_swapchain)),
m_window(std::move(windowSwapchain.m_window)),
m_renderOnlyIfFocused(windowSwapchain.m_renderOnlyIfFocused),
m_hasFocus(windowSwapchain.m_hasFocus),
m_isMinimized(windowSwapchain.m_isMinimized)
{
ConnectSignals();
}
inline RenderFrame WindowSwapchain::AcquireFrame()
{
if (m_isMinimized || (!m_hasFocus && m_renderOnlyIfFocused))
return RenderFrame{};
return m_swapchain->AcquireFrame();
}
inline bool WindowSwapchain::DoesRenderOnlyIfFocused() const
{
return m_renderOnlyIfFocused;
}
inline void WindowSwapchain::EnableRenderOnlyIfFocused(bool enable)
{
m_renderOnlyIfFocused = enable;
}
inline Swapchain& WindowSwapchain::GetSwapchain()
{
return *m_swapchain;
}
inline const Swapchain& WindowSwapchain::GetSwapchain() const
{
return *m_swapchain;
}
inline WindowSwapchain& WindowSwapchain::operator=(WindowSwapchain&& windowSwapchain) noexcept
{
windowSwapchain.DisconnectSignals();
m_renderDevice = std::move(windowSwapchain.m_renderDevice);
m_swapchain = std::move(windowSwapchain.m_swapchain);
m_window = std::move(windowSwapchain.m_window);
m_renderOnlyIfFocused = windowSwapchain.m_renderOnlyIfFocused;
m_hasFocus = windowSwapchain.m_hasFocus;
m_isMinimized = windowSwapchain.m_isMinimized;
ConnectSignals();
return *this;
}
void WindowSwapchain::DisconnectSignals()
{
m_onGainedFocus.Disconnect();
m_onLostFocus.Disconnect();
m_onMinimized.Disconnect();
m_onResized.Disconnect();
m_onRestored.Disconnect();
}
}
#include <Nazara/Renderer/DebugOff.hpp>

View File

@ -45,10 +45,9 @@
#include <Nazara/VulkanRenderer/VulkanRenderPass.hpp>
#include <Nazara/VulkanRenderer/VulkanRenderPipeline.hpp>
#include <Nazara/VulkanRenderer/VulkanRenderPipelineLayout.hpp>
#include <Nazara/VulkanRenderer/VulkanRenderWindow.hpp>
#include <Nazara/VulkanRenderer/VulkanShaderBinding.hpp>
#include <Nazara/VulkanRenderer/VulkanShaderModule.hpp>
#include <Nazara/VulkanRenderer/VulkanSurface.hpp>
#include <Nazara/VulkanRenderer/VulkanSwapchain.hpp>
#include <Nazara/VulkanRenderer/VulkanTexture.hpp>
#include <Nazara/VulkanRenderer/VulkanTextureFramebuffer.hpp>
#include <Nazara/VulkanRenderer/VulkanTextureSampler.hpp>

View File

@ -35,6 +35,7 @@ namespace Nz
std::shared_ptr<RenderPipelineLayout> InstantiateRenderPipelineLayout(RenderPipelineLayoutInfo pipelineLayoutInfo) override;
std::shared_ptr<ShaderModule> InstantiateShaderModule(nzsl::ShaderStageTypeFlags stages, const nzsl::Ast::Module& shaderModule, const nzsl::ShaderWriter::States& states) override;
std::shared_ptr<ShaderModule> InstantiateShaderModule(nzsl::ShaderStageTypeFlags stages, ShaderLanguage lang, const void* source, std::size_t sourceSize, const nzsl::ShaderWriter::States& states) override;
std::shared_ptr<Swapchain> InstantiateSwapchain(WindowHandle windowHandle, const Vector2ui& windowSize, const SwapchainParameters& parameters) override;
std::shared_ptr<Texture> InstantiateTexture(const TextureInfo& params) override;
std::shared_ptr<TextureSampler> InstantiateTextureSampler(const TextureSamplerInfo& params) override;

View File

@ -18,12 +18,12 @@
namespace Nz
{
class VulkanRenderWindow;
class VulkanSwapchain;
class NAZARA_VULKANRENDERER_API VulkanRenderImage : public RenderImage
{
public:
VulkanRenderImage(VulkanRenderWindow& owner);
VulkanRenderImage(VulkanSwapchain& owner);
VulkanRenderImage(const VulkanRenderImage&) = delete;
VulkanRenderImage(VulkanRenderImage&&) = delete;
~VulkanRenderImage();
@ -50,7 +50,7 @@ namespace Nz
std::size_t m_currentCommandBuffer;
std::vector<Vk::AutoCommandBuffer> m_inFlightCommandBuffers;
std::vector<VkCommandBuffer> m_graphicalCommandsBuffers;
VulkanRenderWindow& m_owner;
VulkanSwapchain& m_owner;
Vk::CommandPool m_commandPool;
Vk::Fence m_inFlightFence;
Vk::Semaphore m_imageAvailableSemaphore;

View File

@ -25,9 +25,6 @@ namespace Nz
VulkanRenderer() = default;
~VulkanRenderer();
std::unique_ptr<RenderSurface> CreateRenderSurfaceImpl() override;
std::unique_ptr<RenderWindowImpl> CreateRenderWindowImpl(RenderWindow& owner) override;
std::shared_ptr<RenderDevice> InstanciateRenderDevice(std::size_t deviceIndex, const RenderDeviceFeatures& enabledFeatures) override;
RenderAPI QueryAPI() const override;

View File

@ -1,40 +0,0 @@
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// 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_VULKANSURFACE_HPP
#define NAZARA_VULKANRENDERER_VULKANSURFACE_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Renderer/RenderSurface.hpp>
#include <Nazara/VulkanRenderer/Wrapper/Surface.hpp>
#include <Nazara/VulkanRenderer/Wrapper/Swapchain.hpp>
namespace Nz
{
class NAZARA_VULKANRENDERER_API VulkanSurface : public RenderSurface
{
public:
VulkanSurface();
VulkanSurface(const VulkanSurface&) = delete;
VulkanSurface(VulkanSurface&&) = delete; ///TODO
~VulkanSurface() = default;
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 <Nazara/VulkanRenderer/VulkanSurface.inl>
#endif // NAZARA_VULKANRENDERER_VULKANSURFACE_HPP

View File

@ -1,16 +0,0 @@
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Vulkan renderer"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/VulkanRenderer/VulkanSurface.hpp>
#include <Nazara/VulkanRenderer/Debug.hpp>
namespace Nz
{
inline Vk::Surface& VulkanSurface::GetSurface()
{
return m_surface;
}
}
#include <Nazara/VulkanRenderer/DebugOff.hpp>

View File

@ -12,8 +12,9 @@
#include <Nazara/Math/Rect.hpp>
#include <Nazara/Math/Vector3.hpp>
#include <Nazara/Renderer/Enums.hpp>
#include <Nazara/Renderer/RenderWindowImpl.hpp>
#include <Nazara/Renderer/Swapchain.hpp>
#include <Nazara/Renderer/RendererImpl.hpp>
#include <Nazara/Renderer/SwapchainParameters.hpp>
#include <Nazara/VulkanRenderer/Config.hpp>
#include <Nazara/VulkanRenderer/VulkanDevice.hpp>
#include <Nazara/VulkanRenderer/VulkanRenderImage.hpp>
@ -33,17 +34,15 @@
namespace Nz
{
class NAZARA_VULKANRENDERER_API VulkanRenderWindow : public RenderWindowImpl
class NAZARA_VULKANRENDERER_API VulkanSwapchain : public Swapchain
{
public:
VulkanRenderWindow(RenderWindow& owner);
VulkanRenderWindow(const VulkanRenderWindow&) = delete;
VulkanRenderWindow(VulkanRenderWindow&&) = delete; ///TODO
~VulkanRenderWindow();
VulkanSwapchain(VulkanDevice& device, WindowHandle windowHandle, const Vector2ui& windowSize, const SwapchainParameters& parameters);
VulkanSwapchain(const VulkanSwapchain&) = delete;
VulkanSwapchain(VulkanSwapchain&&) = delete;
~VulkanSwapchain();
RenderFrame Acquire() override;
bool Create(RendererImpl* renderer, RenderSurface* surface, const RenderWindowParameters& parameters) override;
RenderFrame AcquireFrame() override;
std::shared_ptr<CommandPool> CreateCommandPool(QueueType queueType) override;
@ -56,20 +55,22 @@ namespace Nz
const Vector2ui& GetSize() const override;
inline const Vk::Swapchain& GetSwapchain() const;
void NotifyResize(const Vector2ui& newSize) override;
void Present(UInt32 imageIndex, VkSemaphore waitSemaphore = VK_NULL_HANDLE);
VulkanRenderWindow& operator=(const VulkanRenderWindow&) = delete;
VulkanRenderWindow& operator=(VulkanRenderWindow&&) = delete; ///TODO
VulkanSwapchain& operator=(const VulkanSwapchain&) = delete;
VulkanSwapchain& operator=(VulkanSwapchain&&) = delete;
private:
bool CreateSwapchain(Vk::Surface& surface, const Vector2ui& size);
bool SetupDepthBuffer(const Vector2ui& size);
bool SetupFrameBuffers(const Vector2ui& size);
bool CreateSwapchain();
bool SetupDepthBuffer();
bool SetupFrameBuffers();
bool SetupRenderPass();
bool SetupSwapchain(const Vk::PhysicalDevice& deviceInfo, Vk::Surface& surface, const Vector2ui& size);
bool SetupSurface(WindowHandle windowHandle);
bool SetupSwapchain(const Vk::PhysicalDevice& deviceInfo);
std::optional<VulkanRenderPass> m_renderPass;
std::shared_ptr<VulkanDevice> m_device;
std::size_t m_currentFrame;
std::vector<VulkanWindowFramebuffer> m_framebuffers;
std::vector<Vk::Fence*> m_inflightFences;
@ -80,15 +81,16 @@ namespace Nz
Vk::QueueHandle m_graphicsQueue;
Vk::QueueHandle m_presentQueue;
Vk::QueueHandle m_transferQueue;
Vk::Surface m_surface;
Vk::Swapchain m_swapchain;
RenderWindow& m_owner;
Vector2ui m_swapchainSize;
VkFormat m_depthStencilFormat;
VkSurfaceFormatKHR m_surfaceFormat;
VulkanDevice& m_device;
bool m_shouldRecreateSwapchain;
};
}
#include <Nazara/VulkanRenderer/VulkanRenderWindow.inl>
#include <Nazara/VulkanRenderer/VulkanSwapchain.inl>
#endif // NAZARA_VULKANRENDERER_VULKANRENDERWINDOW_HPP

View File

@ -2,27 +2,27 @@
// This file is part of the "Nazara Engine - Vulkan renderer"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/VulkanRenderer/VulkanRenderWindow.hpp>
#include <Nazara/VulkanRenderer/VulkanSwapchain.hpp>
#include <Nazara/VulkanRenderer/Debug.hpp>
namespace Nz
{
inline VulkanDevice& VulkanRenderWindow::GetDevice()
inline VulkanDevice& VulkanSwapchain::GetDevice()
{
return *m_device;
return m_device;
}
inline const VulkanDevice& VulkanRenderWindow::GetDevice() const
inline const VulkanDevice& VulkanSwapchain::GetDevice() const
{
return *m_device;
return m_device;
}
inline Vk::QueueHandle& VulkanRenderWindow::GetGraphicsQueue()
inline Vk::QueueHandle& VulkanSwapchain::GetGraphicsQueue()
{
return m_graphicsQueue;
}
inline const Vk::Swapchain& VulkanRenderWindow::GetSwapchain() const
inline const Vk::Swapchain& VulkanSwapchain::GetSwapchain() const
{
return m_swapchain;
}

View File

@ -17,78 +17,75 @@
#include <vulkan/vulkan_metal.h>
#endif
namespace Nz
namespace Nz::Vk
{
namespace Vk
class Surface
{
class Surface
{
public:
inline Surface(Instance& instance);
Surface(const Surface&) = delete;
Surface(Surface&& surface);
inline ~Surface();
public:
inline Surface(Instance& instance);
Surface(const Surface&) = delete;
Surface(Surface&& surface) noexcept;
inline ~Surface();
#ifdef VK_USE_PLATFORM_ANDROID_KHR
// VK_KHR_android_surface
inline bool Create(const VkAndroidSurfaceCreateInfoKHR& createInfo, const VkAllocationCallbacks* allocator = nullptr);
inline bool Create(ANativeWindow* window, VkAndroidSurfaceCreateFlagsKHR flags = 0, const VkAllocationCallbacks* allocator = nullptr);
#endif
#ifdef VK_USE_PLATFORM_ANDROID_KHR
// VK_KHR_android_surface
inline bool Create(const VkAndroidSurfaceCreateInfoKHR& createInfo, const VkAllocationCallbacks* allocator = nullptr);
inline bool Create(ANativeWindow* window, VkAndroidSurfaceCreateFlagsKHR flags = 0, const VkAllocationCallbacks* allocator = nullptr);
#endif
#ifdef VK_USE_PLATFORM_XCB_KHR
// VK_KHR_xcb_surface
inline bool Create(const VkXcbSurfaceCreateInfoKHR& createInfo, const VkAllocationCallbacks* allocator = nullptr);
inline bool Create(xcb_connection_t* connection, xcb_window_t window, VkXcbSurfaceCreateFlagsKHR flags = 0, const VkAllocationCallbacks* allocator = nullptr);
#endif
#ifdef VK_USE_PLATFORM_XCB_KHR
// VK_KHR_xcb_surface
inline bool Create(const VkXcbSurfaceCreateInfoKHR& createInfo, const VkAllocationCallbacks* allocator = nullptr);
inline bool Create(xcb_connection_t* connection, xcb_window_t window, VkXcbSurfaceCreateFlagsKHR flags = 0, const VkAllocationCallbacks* allocator = nullptr);
#endif
#ifdef VK_USE_PLATFORM_XLIB_KHR
// VK_KHR_xlib_surface
inline bool Create(const VkXlibSurfaceCreateInfoKHR& createInfo, const VkAllocationCallbacks* allocator = nullptr);
inline bool Create(Display* display, Window window, VkXlibSurfaceCreateFlagsKHR flags = 0, const VkAllocationCallbacks* allocator = nullptr);
#endif
#ifdef VK_USE_PLATFORM_XLIB_KHR
// VK_KHR_xlib_surface
inline bool Create(const VkXlibSurfaceCreateInfoKHR& createInfo, const VkAllocationCallbacks* allocator = nullptr);
inline bool Create(Display* display, Window window, VkXlibSurfaceCreateFlagsKHR flags = 0, const VkAllocationCallbacks* allocator = nullptr);
#endif
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
// VK_KHR_wayland_surface
inline bool Create(const VkWaylandSurfaceCreateInfoKHR& createInfo, const VkAllocationCallbacks* allocator = nullptr);
inline bool Create(wl_display* display, wl_surface* surface, VkWaylandSurfaceCreateFlagsKHR flags = 0, const VkAllocationCallbacks* allocator = nullptr);
#endif
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
// VK_KHR_wayland_surface
inline bool Create(const VkWaylandSurfaceCreateInfoKHR& createInfo, const VkAllocationCallbacks* allocator = nullptr);
inline bool Create(wl_display* display, wl_surface* surface, VkWaylandSurfaceCreateFlagsKHR flags = 0, const VkAllocationCallbacks* allocator = nullptr);
#endif
#ifdef VK_USE_PLATFORM_WIN32_KHR
// VK_KHR_win32_surface
inline bool Create(const VkWin32SurfaceCreateInfoKHR& createInfo, const VkAllocationCallbacks* allocator = nullptr);
inline bool Create(HINSTANCE instance, HWND handle, VkWin32SurfaceCreateFlagsKHR flags = 0, const VkAllocationCallbacks* allocator = nullptr);
#endif
#ifdef VK_USE_PLATFORM_WIN32_KHR
// VK_KHR_win32_surface
inline bool Create(const VkWin32SurfaceCreateInfoKHR& createInfo, const VkAllocationCallbacks* allocator = nullptr);
inline bool Create(HINSTANCE instance, HWND handle, VkWin32SurfaceCreateFlagsKHR flags = 0, const VkAllocationCallbacks* allocator = nullptr);
#endif
#ifdef VK_USE_PLATFORM_METAL_EXT
inline bool Create(const VkMetalSurfaceCreateInfoEXT& createInfo, const VkAllocationCallbacks* allocator = nullptr);
inline bool Create(id layer, const VkAllocationCallbacks* allocator = nullptr);
#endif
#ifdef VK_USE_PLATFORM_METAL_EXT
inline bool Create(const VkMetalSurfaceCreateInfoEXT& createInfo, const VkAllocationCallbacks* allocator = nullptr);
inline bool Create(id layer, const VkAllocationCallbacks* allocator = nullptr);
#endif
inline void Destroy();
inline void Destroy();
bool GetCapabilities(VkPhysicalDevice physicalDevice, VkSurfaceCapabilitiesKHR* surfaceCapabilities) const;
bool GetFormats(VkPhysicalDevice physicalDevice, std::vector<VkSurfaceFormatKHR>* surfaceFormats) const;
bool GetPresentModes(VkPhysicalDevice physicalDevice, std::vector<VkPresentModeKHR>* presentModes) const;
bool GetSupportPresentation(VkPhysicalDevice physicalDevice, UInt32 queueFamilyIndex, bool* supported) const;
bool GetCapabilities(VkPhysicalDevice physicalDevice, VkSurfaceCapabilitiesKHR* surfaceCapabilities) const;
bool GetFormats(VkPhysicalDevice physicalDevice, std::vector<VkSurfaceFormatKHR>* surfaceFormats) const;
bool GetPresentModes(VkPhysicalDevice physicalDevice, std::vector<VkPresentModeKHR>* presentModes) const;
bool GetSupportPresentation(VkPhysicalDevice physicalDevice, UInt32 queueFamilyIndex, bool* supported) const;
inline VkResult GetLastErrorCode() const;
inline VkResult GetLastErrorCode() const;
Surface& operator=(const Surface&) = delete;
Surface& operator=(Surface&&) = delete;
Surface& operator=(const Surface&) = delete;
Surface& operator=(Surface&&) = delete;
inline operator VkSurfaceKHR() const;
inline operator VkSurfaceKHR() const;
static inline bool IsSupported(const Instance& instance);
static inline bool IsSupported(const Instance& instance);
private:
inline bool Create(const VkAllocationCallbacks* allocator);
private:
inline bool Create(const VkAllocationCallbacks* allocator);
Instance& m_instance;
VkAllocationCallbacks m_allocator;
VkSurfaceKHR m_surface;
mutable VkResult m_lastErrorCode;
};
}
Instance& m_instance;
VkAllocationCallbacks m_allocator;
VkSurfaceKHR m_surface;
mutable VkResult m_lastErrorCode;
};
}
#include <Nazara/VulkanRenderer/Wrapper/Surface.inl>

View File

@ -7,305 +7,302 @@
#include <Nazara/VulkanRenderer/Utils.hpp>
#include <Nazara/VulkanRenderer/Debug.hpp>
namespace Nz
namespace Nz::Vk
{
namespace Vk
inline Surface::Surface(Instance& instance) :
m_instance(instance),
m_surface(VK_NULL_HANDLE)
{
inline Surface::Surface(Instance& instance) :
m_instance(instance),
m_surface(VK_NULL_HANDLE)
}
inline Surface::Surface(Surface&& surface) noexcept :
m_instance(surface.m_instance),
m_allocator(surface.m_allocator),
m_surface(surface.m_surface),
m_lastErrorCode(surface.m_lastErrorCode)
{
surface.m_surface = VK_NULL_HANDLE;
}
inline Surface::~Surface()
{
Destroy();
}
#ifdef VK_USE_PLATFORM_ANDROID_KHR
inline bool Surface::Create(const VkAndroidSurfaceCreateInfoKHR& createInfo, const VkAllocationCallbacks* allocator)
{
m_lastErrorCode = m_instance.vkCreateAndroidSurfaceKHR(m_instance, &createInfo, allocator, &m_surface);
return Create(allocator);
}
inline bool Surface::Create(ANativeWindow* window, VkAndroidSurfaceCreateFlagsKHR flags, const VkAllocationCallbacks* allocator)
{
VkAndroidSurfaceCreateInfoKHR createInfo =
{
}
VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR,
nullptr,
flags,
window
};
inline Surface::Surface(Surface&& surface) :
m_instance(surface.m_instance),
m_allocator(surface.m_allocator),
m_surface(surface.m_surface),
m_lastErrorCode(surface.m_lastErrorCode)
return Create(createInfo, allocator);
}
#endif
#ifdef VK_USE_PLATFORM_XCB_KHR
inline bool Surface::Create(const VkXcbSurfaceCreateInfoKHR& createInfo, const VkAllocationCallbacks* allocator)
{
m_lastErrorCode = m_instance.vkCreateXcbSurfaceKHR(m_instance, &createInfo, allocator, &m_surface);
return Create(allocator);
}
inline bool Surface::Create(xcb_connection_t* connection, xcb_window_t window, VkXcbSurfaceCreateFlagsKHR flags, const VkAllocationCallbacks* allocator)
{
VkXcbSurfaceCreateInfoKHR createInfo =
{
surface.m_surface = VK_NULL_HANDLE;
}
VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR,
nullptr,
flags,
connection,
window
};
inline Surface::~Surface()
return Create(createInfo, allocator);
}
#endif
#ifdef VK_USE_PLATFORM_XLIB_KHR
inline bool Surface::Create(const VkXlibSurfaceCreateInfoKHR& createInfo, const VkAllocationCallbacks* allocator)
{
m_lastErrorCode = m_instance.vkCreateXlibSurfaceKHR(m_instance, &createInfo, allocator, &m_surface);
return Create(allocator);
}
inline bool Surface::Create(Display* display, Window window, VkXlibSurfaceCreateFlagsKHR flags, const VkAllocationCallbacks* allocator)
{
VkXlibSurfaceCreateInfoKHR createInfo =
{
Destroy();
}
VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR,
nullptr,
flags,
display,
window
};
#ifdef VK_USE_PLATFORM_ANDROID_KHR
inline bool Surface::Create(const VkAndroidSurfaceCreateInfoKHR& createInfo, const VkAllocationCallbacks* allocator)
return Create(createInfo, allocator);
}
#endif
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
inline bool Surface::Create(const VkWaylandSurfaceCreateInfoKHR& createInfo, const VkAllocationCallbacks* allocator)
{
m_lastErrorCode = m_instance.vkCreateWaylandSurfaceKHR(m_instance, &createInfo, allocator, &m_surface);
return Create(allocator);
}
inline bool Surface::Create(wl_display* display, wl_surface* surface, VkWaylandSurfaceCreateFlagsKHR flags, const VkAllocationCallbacks* allocator)
{
VkWaylandSurfaceCreateInfoKHR createInfo =
{
m_lastErrorCode = m_instance.vkCreateAndroidSurfaceKHR(m_instance, &createInfo, allocator, &m_surface);
return Create(allocator);
}
VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR,
nullptr,
flags,
display,
surface
};
inline bool Surface::Create(ANativeWindow* window, VkAndroidSurfaceCreateFlagsKHR flags, const VkAllocationCallbacks* allocator)
return Create(createInfo, allocator);
}
#endif
#ifdef VK_USE_PLATFORM_WIN32_KHR
inline bool Surface::Create(const VkWin32SurfaceCreateInfoKHR& createInfo, const VkAllocationCallbacks* allocator)
{
m_lastErrorCode = m_instance.vkCreateWin32SurfaceKHR(m_instance, &createInfo, allocator, &m_surface);
return Create(allocator);
}
inline bool Surface::Create(HINSTANCE instance, HWND handle, VkWin32SurfaceCreateFlagsKHR flags, const VkAllocationCallbacks* allocator)
{
VkWin32SurfaceCreateInfoKHR createInfo =
{
VkAndroidSurfaceCreateInfoKHR createInfo =
{
VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR,
nullptr,
flags,
window
};
VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR,
nullptr,
flags,
instance,
handle
};
return Create(createInfo, allocator);
}
#endif
return Create(createInfo, allocator);
}
#endif
#ifdef VK_USE_PLATFORM_XCB_KHR
inline bool Surface::Create(const VkXcbSurfaceCreateInfoKHR& createInfo, const VkAllocationCallbacks* allocator)
#ifdef VK_USE_PLATFORM_METAL_EXT
inline bool Surface::Create(const VkMetalSurfaceCreateInfoEXT& createInfo, const VkAllocationCallbacks* allocator)
{
m_lastErrorCode = m_instance.vkCreateMetalSurfaceEXT(m_instance, &createInfo, allocator, &m_surface);
return Create(allocator);
}
inline bool Surface::Create(id layer, const VkAllocationCallbacks* allocator)
{
VkMetalSurfaceCreateInfoEXT createInfo =
{
m_lastErrorCode = m_instance.vkCreateXcbSurfaceKHR(m_instance, &createInfo, allocator, &m_surface);
return Create(allocator);
}
VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT,
nullptr,
0,
layer
};
inline bool Surface::Create(xcb_connection_t* connection, xcb_window_t window, VkXcbSurfaceCreateFlagsKHR flags, const VkAllocationCallbacks* allocator)
return Create(createInfo, allocator);
}
#endif
inline void Surface::Destroy()
{
if (m_surface != VK_NULL_HANDLE)
{
VkXcbSurfaceCreateInfoKHR createInfo =
{
VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR,
nullptr,
flags,
connection,
window
};
return Create(createInfo, allocator);
}
#endif
#ifdef VK_USE_PLATFORM_XLIB_KHR
inline bool Surface::Create(const VkXlibSurfaceCreateInfoKHR& createInfo, const VkAllocationCallbacks* allocator)
{
m_lastErrorCode = m_instance.vkCreateXlibSurfaceKHR(m_instance, &createInfo, allocator, &m_surface);
return Create(allocator);
}
inline bool Surface::Create(Display* display, Window window, VkXlibSurfaceCreateFlagsKHR flags, const VkAllocationCallbacks* allocator)
{
VkXlibSurfaceCreateInfoKHR createInfo =
{
VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR,
nullptr,
flags,
display,
window
};
return Create(createInfo, allocator);
}
#endif
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
inline bool Surface::Create(const VkWaylandSurfaceCreateInfoKHR& createInfo, const VkAllocationCallbacks* allocator)
{
m_lastErrorCode = m_instance.vkCreateWaylandSurfaceKHR(m_instance, &createInfo, allocator, &m_surface);
return Create(allocator);
}
inline bool Surface::Create(wl_display* display, wl_surface* surface, VkWaylandSurfaceCreateFlagsKHR flags, const VkAllocationCallbacks* allocator)
{
VkWaylandSurfaceCreateInfoKHR createInfo =
{
VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR,
nullptr,
flags,
display,
surface
};
return Create(createInfo, allocator);
}
#endif
#ifdef VK_USE_PLATFORM_WIN32_KHR
inline bool Surface::Create(const VkWin32SurfaceCreateInfoKHR& createInfo, const VkAllocationCallbacks* allocator)
{
m_lastErrorCode = m_instance.vkCreateWin32SurfaceKHR(m_instance, &createInfo, allocator, &m_surface);
return Create(allocator);
}
inline bool Surface::Create(HINSTANCE instance, HWND handle, VkWin32SurfaceCreateFlagsKHR flags, const VkAllocationCallbacks* allocator)
{
VkWin32SurfaceCreateInfoKHR createInfo =
{
VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR,
nullptr,
flags,
instance,
handle
};
return Create(createInfo, allocator);
}
#endif
#ifdef VK_USE_PLATFORM_METAL_EXT
inline bool Surface::Create(const VkMetalSurfaceCreateInfoEXT& createInfo, const VkAllocationCallbacks* allocator)
{
m_lastErrorCode = m_instance.vkCreateMetalSurfaceEXT(m_instance, &createInfo, allocator, &m_surface);
return Create(allocator);
}
inline bool Surface::Create(id layer, const VkAllocationCallbacks* allocator)
{
VkMetalSurfaceCreateInfoEXT createInfo =
{
VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT,
nullptr,
0,
layer
};
return Create(createInfo, allocator);
}
#endif
inline void Surface::Destroy()
{
if (m_surface != VK_NULL_HANDLE)
{
m_instance.vkDestroySurfaceKHR(m_instance, m_surface, (m_allocator.pfnAllocation) ? &m_allocator : nullptr);
m_surface = VK_NULL_HANDLE;
}
m_instance.vkDestroySurfaceKHR(m_instance, m_surface, (m_allocator.pfnAllocation) ? &m_allocator : nullptr);
m_surface = VK_NULL_HANDLE;
}
}
inline VkResult Surface::GetLastErrorCode() const
inline VkResult Surface::GetLastErrorCode() const
{
return m_lastErrorCode;
}
inline bool Surface::GetCapabilities(VkPhysicalDevice physicalDevice, VkSurfaceCapabilitiesKHR* surfaceCapabilities) const
{
m_lastErrorCode = m_instance.vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, m_surface, surfaceCapabilities);
if (m_lastErrorCode != VkResult::VK_SUCCESS)
{
return m_lastErrorCode;
}
inline bool Surface::GetCapabilities(VkPhysicalDevice physicalDevice, VkSurfaceCapabilitiesKHR* surfaceCapabilities) const
{
m_lastErrorCode = m_instance.vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, m_surface, surfaceCapabilities);
if (m_lastErrorCode != VkResult::VK_SUCCESS)
{
NazaraError("Failed to query surface capabilities: " + TranslateVulkanError(m_lastErrorCode));
return false;
}
return true;
}
inline bool Surface::GetFormats(VkPhysicalDevice physicalDevice, std::vector<VkSurfaceFormatKHR>* surfaceFormats) const
{
// First, query format count
UInt32 surfaceCount = 0; // Remember, Nz::UInt32 is a typedef on uint32_t
m_lastErrorCode = m_instance.vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, m_surface, &surfaceCount, nullptr);
if (m_lastErrorCode != VkResult::VK_SUCCESS || surfaceCount == 0)
{
NazaraError("Failed to query format count: " + TranslateVulkanError(m_lastErrorCode));
return false;
}
// Now we can get the list of the available physical device
surfaceFormats->resize(surfaceCount);
m_lastErrorCode = m_instance.vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, m_surface, &surfaceCount, surfaceFormats->data());
if (m_lastErrorCode != VkResult::VK_SUCCESS)
{
NazaraError("Failed to query formats: " + TranslateVulkanError(m_lastErrorCode));
return false;
}
return true;
}
inline bool Surface::GetPresentModes(VkPhysicalDevice physicalDevice, std::vector<VkPresentModeKHR>* presentModes) const
{
// First, query present modes count
UInt32 presentModeCount = 0; // Remember, Nz::UInt32 is a typedef on uint32_t
m_lastErrorCode = m_instance.vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, m_surface, &presentModeCount, nullptr);
if (m_lastErrorCode != VkResult::VK_SUCCESS || presentModeCount == 0)
{
NazaraError("Failed to query present mode count");
return false;
}
// Now we can get the list of the available physical device
presentModes->resize(presentModeCount);
m_lastErrorCode = m_instance.vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, m_surface, &presentModeCount, presentModes->data());
if (m_lastErrorCode != VkResult::VK_SUCCESS)
{
NazaraError("Failed to query present modes: " + TranslateVulkanError(m_lastErrorCode));
return false;
}
return true;
}
inline bool Surface::GetSupportPresentation(VkPhysicalDevice physicalDevice, UInt32 queueFamilyIndex, bool* supported) const
{
VkBool32 presentationSupported = VK_FALSE;
m_lastErrorCode = m_instance.vkGetPhysicalDeviceSurfaceSupportKHR(physicalDevice, queueFamilyIndex, m_surface, &presentationSupported);
if (m_lastErrorCode != VkResult::VK_SUCCESS)
{
NazaraError("Failed to query surface capabilities: " + TranslateVulkanError(m_lastErrorCode));
return false;
}
*supported = (presentationSupported == VK_TRUE);
return true;
}
inline Surface::operator VkSurfaceKHR() const
{
return m_surface;
}
inline bool Surface::IsSupported(const Instance& instance)
{
if (!instance.IsExtensionLoaded(VK_KHR_SURFACE_EXTENSION_NAME))
return false;
#ifdef VK_USE_PLATFORM_ANDROID_KHR
if (instance.IsExtensionLoaded(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME))
return true;
#endif
#ifdef VK_USE_PLATFORM_XCB_KHR
if (instance.IsExtensionLoaded(VK_KHR_XCB_SURFACE_EXTENSION_NAME))
return true;
#endif
#ifdef VK_USE_PLATFORM_XLIB_KHR
if (instance.IsExtensionLoaded(VK_KHR_XLIB_SURFACE_EXTENSION_NAME))
return true;
#endif
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
if (instance.IsExtensionLoaded(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME))
return true;
#endif
#ifdef VK_USE_PLATFORM_WIN32_KHR
if (instance.IsExtensionLoaded(VK_KHR_WIN32_SURFACE_EXTENSION_NAME))
return true;
#endif
#ifdef VK_USE_PLATFORM_METAL_EXT
if (instance.IsExtensionLoaded(VK_EXT_METAL_SURFACE_EXTENSION_NAME))
return true;
#endif
NazaraError("Failed to query surface capabilities: " + TranslateVulkanError(m_lastErrorCode));
return false;
}
inline bool Surface::Create(const VkAllocationCallbacks* allocator)
return true;
}
inline bool Surface::GetFormats(VkPhysicalDevice physicalDevice, std::vector<VkSurfaceFormatKHR>* surfaceFormats) const
{
// First, query format count
UInt32 surfaceCount = 0; // Remember, Nz::UInt32 is a typedef on uint32_t
m_lastErrorCode = m_instance.vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, m_surface, &surfaceCount, nullptr);
if (m_lastErrorCode != VkResult::VK_SUCCESS || surfaceCount == 0)
{
if (m_lastErrorCode != VkResult::VK_SUCCESS)
{
NazaraError("Failed to create Vulkan surface: " + TranslateVulkanError(m_lastErrorCode));
return false;
}
// Store the allocator to access them when needed
if (allocator)
m_allocator = *allocator;
else
m_allocator.pfnAllocation = nullptr;
return true;
NazaraError("Failed to query format count: " + TranslateVulkanError(m_lastErrorCode));
return false;
}
// Now we can get the list of the available physical device
surfaceFormats->resize(surfaceCount);
m_lastErrorCode = m_instance.vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, m_surface, &surfaceCount, surfaceFormats->data());
if (m_lastErrorCode != VkResult::VK_SUCCESS)
{
NazaraError("Failed to query formats: " + TranslateVulkanError(m_lastErrorCode));
return false;
}
return true;
}
inline bool Surface::GetPresentModes(VkPhysicalDevice physicalDevice, std::vector<VkPresentModeKHR>* presentModes) const
{
// First, query present modes count
UInt32 presentModeCount = 0; // Remember, Nz::UInt32 is a typedef on uint32_t
m_lastErrorCode = m_instance.vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, m_surface, &presentModeCount, nullptr);
if (m_lastErrorCode != VkResult::VK_SUCCESS || presentModeCount == 0)
{
NazaraError("Failed to query present mode count");
return false;
}
// Now we can get the list of the available physical device
presentModes->resize(presentModeCount);
m_lastErrorCode = m_instance.vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, m_surface, &presentModeCount, presentModes->data());
if (m_lastErrorCode != VkResult::VK_SUCCESS)
{
NazaraError("Failed to query present modes: " + TranslateVulkanError(m_lastErrorCode));
return false;
}
return true;
}
inline bool Surface::GetSupportPresentation(VkPhysicalDevice physicalDevice, UInt32 queueFamilyIndex, bool* supported) const
{
VkBool32 presentationSupported = VK_FALSE;
m_lastErrorCode = m_instance.vkGetPhysicalDeviceSurfaceSupportKHR(physicalDevice, queueFamilyIndex, m_surface, &presentationSupported);
if (m_lastErrorCode != VkResult::VK_SUCCESS)
{
NazaraError("Failed to query surface capabilities: " + TranslateVulkanError(m_lastErrorCode));
return false;
}
*supported = (presentationSupported == VK_TRUE);
return true;
}
inline Surface::operator VkSurfaceKHR() const
{
return m_surface;
}
inline bool Surface::IsSupported(const Instance& instance)
{
if (!instance.IsExtensionLoaded(VK_KHR_SURFACE_EXTENSION_NAME))
return false;
#ifdef VK_USE_PLATFORM_ANDROID_KHR
if (instance.IsExtensionLoaded(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME))
return true;
#endif
#ifdef VK_USE_PLATFORM_XCB_KHR
if (instance.IsExtensionLoaded(VK_KHR_XCB_SURFACE_EXTENSION_NAME))
return true;
#endif
#ifdef VK_USE_PLATFORM_XLIB_KHR
if (instance.IsExtensionLoaded(VK_KHR_XLIB_SURFACE_EXTENSION_NAME))
return true;
#endif
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
if (instance.IsExtensionLoaded(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME))
return true;
#endif
#ifdef VK_USE_PLATFORM_WIN32_KHR
if (instance.IsExtensionLoaded(VK_KHR_WIN32_SURFACE_EXTENSION_NAME))
return true;
#endif
#ifdef VK_USE_PLATFORM_METAL_EXT
if (instance.IsExtensionLoaded(VK_EXT_METAL_SURFACE_EXTENSION_NAME))
return true;
#endif
return false;
}
inline bool Surface::Create(const VkAllocationCallbacks* allocator)
{
if (m_lastErrorCode != VkResult::VK_SUCCESS)
{
NazaraError("Failed to create Vulkan surface: " + TranslateVulkanError(m_lastErrorCode));
return false;
}
// Store the allocator to access them when needed
if (allocator)
m_allocator = *allocator;
else
m_allocator.pfnAllocation = nullptr;
return true;
}
}

View File

@ -8,7 +8,7 @@
#define NAZARA_WIDGETS_BASEWIDGET_HPP
#include <Nazara/Graphics/Sprite.hpp>
#include <Nazara/Platform/Event.hpp>
#include <Nazara/Platform/WindowEvent.hpp>
#include <Nazara/Platform/Mouse.hpp>
#include <Nazara/Utility/Node.hpp>
#include <Nazara/Widgets/Config.hpp>

View File

@ -8,7 +8,7 @@
#define NAZARA_WIDGETS_CANVAS_HPP
#include <Nazara/Platform/CursorController.hpp>
#include <Nazara/Platform/EventHandler.hpp>
#include <Nazara/Platform/WindowEventHandler.hpp>
#include <Nazara/Widgets/BaseWidget.hpp>
#include <entt/entity/registry.hpp>
#include <bitset>
@ -20,7 +20,7 @@ namespace Nz
friend BaseWidget;
public:
Canvas(entt::registry& registry, EventHandler& eventHandler, CursorControllerHandle cursorController, UInt32 renderMask, int initialRenderLayer = 0);
Canvas(entt::registry& registry, WindowEventHandler& eventHandler, CursorControllerHandle cursorController, UInt32 renderMask, int initialRenderLayer = 0);
Canvas(const Canvas&) = delete;
Canvas(Canvas&&) = delete;
inline ~Canvas();
@ -32,8 +32,8 @@ namespace Nz
Canvas& operator=(const Canvas&) = delete;
Canvas& operator=(Canvas&&) = delete;
NazaraSignal(OnUnhandledKeyPressed, const EventHandler* /*eventHandler*/, const WindowEvent::KeyEvent& /*event*/);
NazaraSignal(OnUnhandledKeyReleased, const EventHandler* /*eventHandler*/, const WindowEvent::KeyEvent& /*event*/);
NazaraSignal(OnUnhandledKeyPressed, const WindowEventHandler* /*eventHandler*/, const WindowEvent::KeyEvent& /*event*/);
NazaraSignal(OnUnhandledKeyReleased, const WindowEventHandler* /*eventHandler*/, const WindowEvent::KeyEvent& /*event*/);
protected:
inline void ClearKeyboardOwner(std::size_t canvasIndex);
@ -57,17 +57,17 @@ namespace Nz
private:
template<typename F> void DispatchEvent(std::size_t widgetIndex, F&& functor);
void OnEventMouseButtonPressed(const EventHandler* eventHandler, const WindowEvent::MouseButtonEvent& event);
void OnEventMouseButtonRelease(const EventHandler* eventHandler, const WindowEvent::MouseButtonEvent& event);
void OnEventMouseEntered(const EventHandler* eventHandler);
void OnEventMouseLeft(const EventHandler* eventHandler);
void OnEventMouseMoved(const EventHandler* eventHandler, const WindowEvent::MouseMoveEvent& event);
void OnEventMouseButtonPressed(const WindowEventHandler* eventHandler, const WindowEvent::MouseButtonEvent& event);
void OnEventMouseButtonRelease(const WindowEventHandler* eventHandler, const WindowEvent::MouseButtonEvent& event);
void OnEventMouseEntered(const WindowEventHandler* eventHandler);
void OnEventMouseLeft(const WindowEventHandler* eventHandler);
void OnEventMouseMoved(const WindowEventHandler* eventHandler, const WindowEvent::MouseMoveEvent& event);
void OnEventMouseWheelMoved(const EventHandler* eventHandler, const WindowEvent::MouseWheelEvent& event);
void OnEventKeyPressed(const EventHandler* eventHandler, const WindowEvent::KeyEvent& event);
void OnEventKeyReleased(const EventHandler* eventHandler, const WindowEvent::KeyEvent& event);
void OnEventTextEntered(const EventHandler* eventHandler, const WindowEvent::TextEvent& event);
void OnEventTextEdited(const EventHandler* eventHandler, const WindowEvent::EditEvent& event);
void OnEventMouseWheelMoved(const WindowEventHandler* eventHandler, const WindowEvent::MouseWheelEvent& event);
void OnEventKeyPressed(const WindowEventHandler* eventHandler, const WindowEvent::KeyEvent& event);
void OnEventKeyReleased(const WindowEventHandler* eventHandler, const WindowEvent::KeyEvent& event);
void OnEventTextEntered(const WindowEventHandler* eventHandler, const WindowEvent::TextEvent& event);
void OnEventTextEdited(const WindowEventHandler* eventHandler, const WindowEvent::EditEvent& event);
void UpdateHoveredWidget(int x, int y);
@ -78,16 +78,16 @@ namespace Nz
SystemCursor cursor;
};
NazaraSlot(EventHandler, OnKeyPressed, m_keyPressedSlot);
NazaraSlot(EventHandler, OnKeyReleased, m_keyReleasedSlot);
NazaraSlot(EventHandler, OnMouseButtonPressed, m_mouseButtonPressedSlot);
NazaraSlot(EventHandler, OnMouseButtonReleased, m_mouseButtonReleasedSlot);
NazaraSlot(EventHandler, OnMouseEntered, m_mouseEnteredSlot);
NazaraSlot(EventHandler, OnMouseLeft, m_mouseLeftSlot);
NazaraSlot(EventHandler, OnMouseMoved, m_mouseMovedSlot);
NazaraSlot(EventHandler, OnMouseWheelMoved, m_mouseWheelMovedSlot);
NazaraSlot(EventHandler, OnTextEntered, m_textEnteredSlot);
NazaraSlot(EventHandler, OnTextEdited, m_textEditedSlot);
NazaraSlot(WindowEventHandler, OnKeyPressed, m_keyPressedSlot);
NazaraSlot(WindowEventHandler, OnKeyReleased, m_keyReleasedSlot);
NazaraSlot(WindowEventHandler, OnMouseButtonPressed, m_mouseButtonPressedSlot);
NazaraSlot(WindowEventHandler, OnMouseButtonReleased, m_mouseButtonReleasedSlot);
NazaraSlot(WindowEventHandler, OnMouseEntered, m_mouseEnteredSlot);
NazaraSlot(WindowEventHandler, OnMouseLeft, m_mouseLeftSlot);
NazaraSlot(WindowEventHandler, OnMouseMoved, m_mouseMovedSlot);
NazaraSlot(WindowEventHandler, OnMouseWheelMoved, m_mouseWheelMovedSlot);
NazaraSlot(WindowEventHandler, OnTextEntered, m_textEnteredSlot);
NazaraSlot(WindowEventHandler, OnTextEdited, m_textEditedSlot);
CursorControllerHandle m_cursorController;
UInt32 m_renderMask;

View File

@ -10,7 +10,7 @@
#include <Nazara/Graphics/Components/GraphicsComponent.hpp>
#include <Nazara/Renderer/CommandBufferBuilder.hpp>
#include <Nazara/Renderer/RenderFrame.hpp>
#include <Nazara/Renderer/RenderWindow.hpp>
#include <Nazara/Renderer/WindowSwapchain.hpp>
#include <Nazara/Renderer/UploadPool.hpp>
#include <Nazara/Utility/Components/NodeComponent.hpp>
#include <Nazara/Utility/Components/SharedSkeletonComponent.hpp>
@ -48,13 +48,18 @@ namespace Nz
m_pipeline.reset();
}
WindowSwapchain& RenderSystem::CreateSwapchain(Window& window, const SwapchainParameters& parameters)
{
return *m_windowSwapchains.emplace_back(std::make_unique<WindowSwapchain>(Graphics::Instance()->GetRenderDevice(), window, parameters));
}
void RenderSystem::Update(Time /*elapsedTime*/)
{
UpdateObservers();
UpdateVisibility();
UpdateInstances();
for (auto& windowPtr : m_renderWindows)
for (auto& windowPtr : m_windowSwapchains)
{
RenderFrame frame = windowPtr->AcquireFrame();
if (!frame)

View File

@ -1,20 +0,0 @@
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - OpenGL renderer"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/OpenGLRenderer/DummySurface.hpp>
#include <Nazara/OpenGLRenderer/Debug.hpp>
namespace Nz
{
bool DummySurface::Create(WindowHandle handle)
{
m_handle = handle;
return true;
}
void DummySurface::Destroy()
{
m_handle = WindowHandle{};
}
}

View File

@ -11,6 +11,7 @@
#include <Nazara/OpenGLRenderer/OpenGLRenderPipeline.hpp>
#include <Nazara/OpenGLRenderer/OpenGLRenderPipelineLayout.hpp>
#include <Nazara/OpenGLRenderer/OpenGLShaderModule.hpp>
#include <Nazara/OpenGLRenderer/OpenGLSwapchain.hpp>
#include <Nazara/OpenGLRenderer/OpenGLTexture.hpp>
#include <Nazara/OpenGLRenderer/OpenGLTextureSampler.hpp>
#include <Nazara/OpenGLRenderer/Wrapper/Loader.hpp>
@ -200,6 +201,11 @@ namespace Nz
return std::make_shared<OpenGLShaderModule>(*this, shaderStages, lang, source, sourceSize, states);
}
std::shared_ptr<Swapchain> OpenGLDevice::InstantiateSwapchain(WindowHandle windowHandle, const Vector2ui& windowSize, const SwapchainParameters& parameters)
{
return std::make_shared<OpenGLSwapchain>(*this, windowHandle, windowSize, parameters);
}
std::shared_ptr<Texture> OpenGLDevice::InstantiateTexture(const TextureInfo& params)
{
return std::make_shared<OpenGLTexture>(*this, params);

View File

@ -5,13 +5,13 @@
#include <Nazara/OpenGLRenderer/OpenGLRenderImage.hpp>
#include <Nazara/OpenGLRenderer/OpenGLCommandBuffer.hpp>
#include <Nazara/OpenGLRenderer/OpenGLCommandBufferBuilder.hpp>
#include <Nazara/OpenGLRenderer/OpenGLRenderWindow.hpp>
#include <Nazara/OpenGLRenderer/OpenGLSwapchain.hpp>
#include <stdexcept>
#include <Nazara/OpenGLRenderer/Debug.hpp>
namespace Nz
{
OpenGLRenderImage::OpenGLRenderImage(OpenGLRenderWindow& owner) :
OpenGLRenderImage::OpenGLRenderImage(OpenGLSwapchain& owner) :
m_owner(owner),
m_uploadPool(2 * 1024 * 1024)
{

View File

@ -4,11 +4,9 @@
#include <Nazara/OpenGLRenderer/OpenGLRenderer.hpp>
#include <Nazara/Core/ErrorFlags.hpp>
#include <Nazara/OpenGLRenderer/DummySurface.hpp>
#include <Nazara/OpenGLRenderer/OpenGLRenderWindow.hpp>
#include <Nazara/OpenGLRenderer/OpenGLSwapchain.hpp>
#include <Nazara/Renderer/RenderDevice.hpp>
#include <Nazara/Renderer/RenderSurface.hpp>
#include <Nazara/Renderer/RenderWindowImpl.hpp>
#include <Nazara/Renderer/Swapchain.hpp>
#include <cassert>
#include <sstream>
@ -30,17 +28,7 @@ namespace Nz
m_device.reset();
}
std::unique_ptr<RenderSurface> OpenGLRenderer::CreateRenderSurfaceImpl()
{
return std::make_unique<DummySurface>();
}
std::unique_ptr<RenderWindowImpl> OpenGLRenderer::CreateRenderWindowImpl(RenderWindow& owner)
{
return std::make_unique<OpenGLRenderWindow>(owner);
}
std::shared_ptr<RenderDevice> OpenGLRenderer::InstanciateRenderDevice(std::size_t deviceIndex, const RenderDeviceFeatures& enabledFeatures)
std::shared_ptr<RenderDevice> OpenGLRenderer::InstanciateRenderDevice([[maybe_unused]] std::size_t deviceIndex, const RenderDeviceFeatures& enabledFeatures)
{
assert(deviceIndex == 0);

View File

@ -2,64 +2,36 @@
// This file is part of the "Nazara Engine - OpenGL renderer"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/OpenGLRenderer/OpenGLRenderWindow.hpp>
#include <Nazara/OpenGLRenderer/DummySurface.hpp>
#include <Nazara/OpenGLRenderer/OpenGLSwapchain.hpp>
#include <Nazara/OpenGLRenderer/OpenGLCommandPool.hpp>
#include <Nazara/OpenGLRenderer/OpenGLRenderer.hpp>
#include <Nazara/Renderer/CommandPool.hpp>
#include <Nazara/Renderer/RenderWindow.hpp>
#include <Nazara/Renderer/WindowSwapchain.hpp>
#include <Nazara/OpenGLRenderer/Debug.hpp>
namespace Nz
{
OpenGLRenderWindow::OpenGLRenderWindow(RenderWindow& owner) :
OpenGLSwapchain::OpenGLSwapchain(OpenGLDevice& device, WindowHandle windowHandle, const Vector2ui& windowSize, const SwapchainParameters& parameters) :
m_currentFrame(0),
m_framebuffer(*this),
m_owner(owner)
m_size(windowSize),
m_sizeInvalidated(false)
{
}
RenderFrame OpenGLRenderWindow::Acquire()
{
if (m_owner.IsMinimized())
return RenderFrame();
bool invalidateFramebuffer = false;
Vector2ui size = m_owner.GetSize();
if (m_size != size)
{
invalidateFramebuffer = true;
OnRenderTargetSizeChange(this, size);
m_size = size;
}
return RenderFrame(m_renderImage[m_currentFrame].get(), invalidateFramebuffer, m_size, 0);
}
bool OpenGLRenderWindow::Create(RendererImpl* /*renderer*/, RenderSurface* surface, const RenderWindowParameters& parameters)
{
DummySurface* dummySurface = static_cast<DummySurface*>(surface);
OpenGLDevice& device = static_cast<OpenGLDevice&>(*m_owner.GetRenderDevice());
GL::ContextParams contextParams;
#ifdef NAZARA_OPENGLRENDERER_DEBUG
contextParams.wrapErrorHandling = true;
#endif
//TODO: Pass render window parameters to context
//TODO: Pass swapchain parameters to context
m_context = device.CreateContext(contextParams, dummySurface->GetWindowHandle());
m_context = device.CreateContext(contextParams, windowHandle);
if (!m_context)
return false;
m_size = m_owner.GetSize();
throw std::runtime_error("failed to create swapchain context");
// TODO: extract the exact window pixel format
PixelFormat colorFormat;
switch (contextParams.bitsPerPixel)
{
case 8: colorFormat = PixelFormat::R8; break;
case 8: colorFormat = PixelFormat::R8; break;
case 16: colorFormat = PixelFormat::RG8; break;
case 24: colorFormat = PixelFormat::RGB8; break;
@ -94,38 +66,52 @@ namespace Nz
m_renderImage.reserve(RenderImageCount);
for (std::size_t i = 0; i < RenderImageCount; ++i)
m_renderImage.emplace_back(std::make_unique<OpenGLRenderImage>(*this));
return true;
}
std::shared_ptr<CommandPool> OpenGLRenderWindow::CreateCommandPool(QueueType /*queueType*/)
RenderFrame OpenGLSwapchain::AcquireFrame()
{
bool sizeInvalidated = m_sizeInvalidated;
m_sizeInvalidated = false;
return RenderFrame(m_renderImage[m_currentFrame].get(), sizeInvalidated, m_size, 0);
}
std::shared_ptr<CommandPool> OpenGLSwapchain::CreateCommandPool(QueueType /*queueType*/)
{
return std::make_unique<OpenGLCommandPool>();
}
const OpenGLFramebuffer& OpenGLRenderWindow::GetFramebuffer(std::size_t i) const
const OpenGLFramebuffer& OpenGLSwapchain::GetFramebuffer(std::size_t i) const
{
assert(i == 0);
NazaraUnused(i);
return m_framebuffer;
}
std::size_t OpenGLRenderWindow::GetFramebufferCount() const
std::size_t OpenGLSwapchain::GetFramebufferCount() const
{
return 1;
}
const OpenGLRenderPass& OpenGLRenderWindow::GetRenderPass() const
const OpenGLRenderPass& OpenGLSwapchain::GetRenderPass() const
{
return *m_renderPass;
}
const Vector2ui& OpenGLRenderWindow::GetSize() const
const Vector2ui& OpenGLSwapchain::GetSize() const
{
return m_size;
}
void OpenGLRenderWindow::Present()
void OpenGLSwapchain::NotifyResize(const Vector2ui& newSize)
{
OnRenderTargetSizeChange(this, newSize);
m_size = newSize;
m_sizeInvalidated = true;
}
void OpenGLSwapchain::Present()
{
m_context->SwapBuffers();
m_currentFrame = (m_currentFrame + 1) % m_renderImage.size();

View File

@ -3,7 +3,7 @@
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/OpenGLRenderer/OpenGLWindowFramebuffer.hpp>
#include <Nazara/OpenGLRenderer/OpenGLRenderWindow.hpp>
#include <Nazara/OpenGLRenderer/OpenGLSwapchain.hpp>
#include <stdexcept>
#include <Nazara/OpenGLRenderer/Debug.hpp>

View File

@ -3,12 +3,25 @@
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Platform/AppWindowingComponent.hpp>
#include <Nazara/Core/ApplicationBase.hpp>
#include <Nazara/Platform/Debug.hpp>
namespace Nz
{
void AppWindowingComponent::Update(Time elapsedTime)
{
// SDL_PollEvent
Window::ProcessEvents();
for (auto it = m_windows.begin(); it != m_windows.end();)
{
Window& window = **it;
if (!window.IsOpen(true))
it = m_windows.erase(it);
else
++it;
}
if (m_quitOnLastWindowClosed && m_windows.empty())
GetApp().Quit();
}
}

View File

@ -34,16 +34,11 @@ namespace Nz
{
switch (sdlButton)
{
case SDL_BUTTON_LEFT:
return Mouse::Left;
case SDL_BUTTON_MIDDLE:
return Mouse::Middle;
case SDL_BUTTON_RIGHT:
return Mouse::Right;
case SDL_BUTTON_X1:
return Mouse::XButton1;
case SDL_BUTTON_X2:
return Mouse::XButton2;
case SDL_BUTTON_LEFT: return Mouse::Left;
case SDL_BUTTON_MIDDLE: return Mouse::Middle;
case SDL_BUTTON_RIGHT: return Mouse::Right;
case SDL_BUTTON_X1: return Mouse::XButton1;
case SDL_BUTTON_X2: return Mouse::XButton2;
default:
NazaraAssert(false, "Unkown mouse button");
return Mouse::Left;
@ -54,30 +49,16 @@ namespace Nz
WindowImpl::WindowImpl(Window* parent) :
m_cursor(nullptr),
m_handle(nullptr),
//m_callback(0),
m_style(0),
m_maxSize(-1),
m_minSize(-1),
m_parent(parent),
m_keyRepeat(true),
m_mouseInside(false),
m_smoothScrolling(false),
m_scrolling(0)
m_eventListener(false),
m_ignoreNextMouseMove(false),
m_lastEditEventLength(0)
{
m_cursor = SDL_GetDefaultCursor();
}
bool WindowImpl::Create(const VideoMode& mode, const std::string& title, WindowStyleFlags style)
{
bool async = (style & WindowStyle::Threaded) != 0;
if (async)
{
NazaraError("SDL2 backend doesn't support asyn window for now");
return false;
}
bool fullscreen = (style & WindowStyle::Fullscreen) != 0;
Uint32 winStyle = 0;
@ -88,7 +69,6 @@ namespace Nz
if (fullscreen)
winStyle |= SDL_WINDOW_FULLSCREEN;
// Testé une seconde fois car sa valeur peut changer
if (fullscreen)
{
x = 0;
@ -105,72 +85,106 @@ namespace Nz
if (style & WindowStyle::Resizable)
winStyle |= SDL_WINDOW_RESIZABLE;
if (style & WindowStyle::Max)
winStyle |= SDL_WINDOW_MAXIMIZED;
m_eventListener = true;
m_ownsWindow = true;
m_sizemove = false;
m_style = style;
m_handle = SDL_CreateWindow(title.c_str(), x, y, width, height, winStyle);
if (!m_handle)
{
NazaraError("Failed to create window: " + Error::GetLastSystemError());
return false;
}
PrepareWindow(fullscreen);
SDL_AddEventWatch(HandleEvent, this);
m_windowId = SDL_GetWindowID(m_handle);
SetEventListener(true);
return true;
}
bool WindowImpl::Create(void* handle)
bool WindowImpl::Create(WindowHandle handle)
{
m_handle = SDL_CreateWindowFrom(handle);
void* systemHandle = nullptr;
switch (handle.type)
{
case WindowBackend::Invalid:
{
NazaraError("unsupported creation from a Wayland handle");
return false;
}
case WindowBackend::Wayland:
{
NazaraError("unsupported creation from a Wayland handle");
return false;
}
case WindowBackend::Cocoa: systemHandle = handle.cocoa.window; break;
case WindowBackend::X11: systemHandle = (void*) handle.x11.window; break;
case WindowBackend::Windows: systemHandle = handle.windows.window; break;
}
m_ownsWindow = false;
m_handle = SDL_CreateWindowFrom(systemHandle);
if (!m_handle)
{
NazaraError("Invalid handle");
return false;
}
m_eventListener = false;
m_ownsWindow = false;
m_sizemove = false;
SDL_GetWindowPosition(m_handle, &m_position.x, &m_position.y);
int width;
int height;
SDL_GetWindowSize(m_handle, &width, &height);
m_size.Set(width, height);
m_windowId = SDL_GetWindowID(m_handle);
SetEventListener(true);
return true;
}
void WindowImpl::Destroy()
{
if (m_ownsWindow && m_handle)
SetEventListener(false);
if (m_handle)
{
SDL_DelEventWatch(HandleEvent, this);
SDL_DestroyWindow(m_handle);
if (m_ownsWindow)
SDL_DestroyWindow(m_handle);
m_handle = nullptr;
}
else
SetEventListener(false);
}
void WindowImpl::EnableKeyRepeat(bool enable)
Vector2i WindowImpl::FetchPosition() const
{
m_keyRepeat = enable;
int x, y;
SDL_GetWindowPosition(m_handle, &x, &y);
return { x, y };
}
void WindowImpl::EnableSmoothScrolling(bool enable)
Vector2ui WindowImpl::FetchSize() const
{
m_smoothScrolling = enable;
int width, height;
SDL_GetWindowSize(m_handle, &width, &height);
return { SafeCast<unsigned int>(width), SafeCast<unsigned int>(height) };
}
WindowStyleFlags WindowImpl::FetchStyle() const
{
UInt32 windowFlags = SDL_GetWindowFlags(m_handle);
WindowStyleFlags styleFlags;
if (windowFlags & SDL_WINDOW_RESIZABLE)
styleFlags |= WindowStyle::Resizable;
if ((windowFlags & SDL_WINDOW_BORDERLESS) == 0)
styleFlags |= WindowStyle::Titlebar | WindowStyle::Closable;
if (windowFlags & SDL_WINDOW_FULLSCREEN)
styleFlags |= WindowStyle::Fullscreen;
return styleFlags;
}
std::string WindowImpl::FetchTitle() const
{
return SDL_GetWindowTitle(m_handle);
}
SDL_Window* WindowImpl::GetHandle() const
@ -178,21 +192,6 @@ namespace Nz
return m_handle;
}
Vector2i WindowImpl::GetPosition() const
{
return m_position;
}
Vector2ui WindowImpl::GetSize() const
{
return m_size;
}
WindowStyleFlags WindowImpl::GetStyle() const
{
return m_style;
}
WindowHandle WindowImpl::GetSystemHandle() const
{
SDL_SysWMinfo wmInfo;
@ -253,22 +252,14 @@ namespace Nz
return handle;
}
std::string WindowImpl::GetTitle() const
{
return SDL_GetWindowTitle(m_handle);
}
bool WindowImpl::HasFocus() const
{
return (SDL_GetWindowFlags(m_handle) & SDL_WINDOW_INPUT_FOCUS) != 0;
}
void WindowImpl::IgnoreNextMouseEvent(int mouseX, int mouseY)
void WindowImpl::IgnoreNextMouseEvent(int /*mouseX*/, int /*mouseY*/)
{
m_ignoreNextMouseMove = true;
// Petite astuce ... probablement foireuse dans certains cas :ahde:
m_mousePos.x = mouseX;
m_mousePos.y = mouseY;
}
bool WindowImpl::IsMinimized() const
@ -297,27 +288,7 @@ namespace Nz
}
}
void WindowImpl::ProcessEvents(bool block)
{
if (m_ownsWindow)
SDL_PumpEvents();
/*if (m_ownsWindow)
{
if (block)
WaitMessage();
MSG message;
while (PeekMessageW(&message, nullptr, 0, 0, PM_REMOVE))
{
TranslateMessage(&message);
DispatchMessageW(&message);
}
}*/
}
int WindowImpl::HandleEvent(void *userdata, SDL_Event* event)
int WindowImpl::HandleEvent(void* userdata, SDL_Event* event)
{
try
{
@ -327,7 +298,7 @@ namespace Nz
{
case SDL_WINDOWEVENT:
{
if (SDL_GetWindowID(window->m_handle) != event->window.windowID)
if (window->m_windowId != event->window.windowID)
return 0;
WindowEvent windowEvent;
@ -337,20 +308,16 @@ namespace Nz
windowEvent.type = WindowEventType::Quit;
break;
case SDL_WINDOWEVENT_RESIZED:
case SDL_WINDOWEVENT_SIZE_CHANGED:
windowEvent.type = WindowEventType::Resized;
windowEvent.size.width = static_cast<unsigned int>(std::max(0, event->window.data1));
windowEvent.size.height = static_cast<unsigned int>(std::max(0, event->window.data2));
window->m_size.Set(windowEvent.size.width, windowEvent.size.height);
break;
case SDL_WINDOWEVENT_MOVED:
windowEvent.type = WindowEventType::Moved;
windowEvent.position.x = event->window.data1;
windowEvent.position.y = event->window.data2;
window->m_position.Set(event->window.data1, event->window.data2);
break;
case SDL_WINDOWEVENT_FOCUS_GAINED:
@ -364,23 +331,35 @@ namespace Nz
case SDL_WINDOWEVENT_ENTER:
windowEvent.type = WindowEventType::MouseEntered;
window->RefreshCursor();
break;
case SDL_WINDOWEVENT_LEAVE:
windowEvent.type = WindowEventType::MouseLeft;
break;
case SDL_WINDOWEVENT_MINIMIZED:
windowEvent.type = WindowEventType::Minimized;
break;
case SDL_WINDOWEVENT_RESTORED:
windowEvent.type = WindowEventType::Restored;
break;
default:
return 0;
}
window->m_parent->PushEvent(windowEvent);
window->m_parent->HandleEvent(windowEvent);
break;
}
case SDL_MOUSEMOTION:
{
if (SDL_GetWindowID(window->m_handle) != event->motion.windowID)
if (window->m_windowId != event->motion.windowID)
return 0;
if (window->m_ignoreNextMouseMove /*&& event->motion.x == window->m_mousePos.x && event->motion.y == window->m_mousePos.y*/)
if (window->m_ignoreNextMouseMove)
{
window->m_ignoreNextMouseMove = false;
return 0;
@ -393,13 +372,13 @@ namespace Nz
windowEvent.mouseMove.deltaX = event->motion.xrel;
windowEvent.mouseMove.deltaY = event->motion.yrel;
window->m_parent->PushEvent(windowEvent);
window->m_parent->HandleEvent(windowEvent);
break;
}
case SDL_MOUSEBUTTONDOWN:
{
if (SDL_GetWindowID(window->m_handle) != event->button.windowID)
if (window->m_windowId != event->button.windowID)
return 0;
WindowEvent windowEvent;
@ -409,13 +388,13 @@ namespace Nz
windowEvent.mouseButton.y = event->button.y;
windowEvent.mouseButton.clickCount = event->button.clicks;
window->m_parent->PushEvent(windowEvent);
window->m_parent->HandleEvent(windowEvent);
break;
}
case SDL_MOUSEBUTTONUP:
{
if (SDL_GetWindowID(window->m_handle) != event->button.windowID)
if (window->m_windowId != event->button.windowID)
return 0;
WindowEvent windowEvent;
@ -424,25 +403,28 @@ namespace Nz
windowEvent.mouseButton.x = event->button.x;
windowEvent.mouseButton.y = event->button.y;
window->m_parent->PushEvent(windowEvent);
window->m_parent->HandleEvent(windowEvent);
break;
}
case SDL_MOUSEWHEEL:
{
if (SDL_GetWindowID(window->m_handle) != event->wheel.windowID)
if (window->m_windowId != event->wheel.windowID)
return 0;
WindowEvent windowEvent;
windowEvent.type = WindowEventType::MouseWheelMoved;
windowEvent.mouseWheel.delta = event->wheel.y;
windowEvent.mouseWheel.delta = event->wheel.preciseY;
windowEvent.mouseWheel.x = event->wheel.mouseX;
windowEvent.mouseWheel.y = event->wheel.mouseY;
window->m_parent->PushEvent(windowEvent);
window->m_parent->HandleEvent(windowEvent);
break;
}
case SDL_KEYDOWN:
if (SDL_GetWindowID(window->m_handle) != event->key.windowID)
{
if (window->m_windowId != event->key.windowID)
return 0;
WindowEvent windowEvent;
@ -455,7 +437,7 @@ namespace Nz
windowEvent.key.system = (event->key.keysym.mod & KMOD_GUI) != 0;
windowEvent.key.virtualKey = SDLHelper::FromSDL(event->key.keysym.sym);
window->m_parent->PushEvent(windowEvent);
window->m_parent->HandleEvent(windowEvent);
// implements X11/Win32 APIs behavior for Enter and Backspace
switch (windowEvent.key.virtualKey)
@ -470,7 +452,7 @@ namespace Nz
windowEvent.text.character = U'\n';
windowEvent.text.repeated = event->key.repeat != 0;
window->m_parent->PushEvent(windowEvent);
window->m_parent->HandleEvent(windowEvent);
break;
}
@ -479,7 +461,7 @@ namespace Nz
windowEvent.text.character = U'\b';
windowEvent.text.repeated = event->key.repeat != 0;
window->m_parent->PushEvent(windowEvent);
window->m_parent->HandleEvent(windowEvent);
break;
default:
@ -487,12 +469,14 @@ namespace Nz
}
break;
}
case SDL_KEYUP:
{
if (SDL_GetWindowID(window->m_handle) != event->key.windowID)
if (window->m_windowId != event->key.windowID)
return 0;
WindowEvent windowEvent;
windowEvent.type = WindowEventType::KeyReleased;
windowEvent.key.alt = (event->key.keysym.mod & KMOD_ALT) != 0;
windowEvent.key.control = (event->key.keysym.mod & KMOD_CTRL) != 0;
@ -502,15 +486,16 @@ namespace Nz
windowEvent.key.system = (event->key.keysym.mod & KMOD_GUI) != 0;
windowEvent.key.virtualKey = SDLHelper::FromSDL(event->key.keysym.sym);
window->m_parent->PushEvent(windowEvent);
window->m_parent->HandleEvent(windowEvent);
break;
}
case SDL_TEXTINPUT:
{
if (SDL_GetWindowID(window->m_handle) != event->text.windowID)
if (window->m_windowId != event->text.windowID)
return 0;
WindowEvent windowEvent;
windowEvent.type = WindowEventType::TextEntered;
windowEvent.text.repeated = false;
@ -519,7 +504,7 @@ namespace Nz
{
windowEvent.text.character = *it;
window->m_parent->PushEvent(windowEvent);
window->m_parent->HandleEvent(windowEvent);
}
while (*it++);
@ -528,9 +513,10 @@ namespace Nz
case SDL_TEXTEDITING:
{
if (SDL_GetWindowID(window->m_handle) != event->edit.windowID)
if (window->m_windowId != event->edit.windowID)
return 0;
WindowEvent windowEvent;
windowEvent.type = WindowEventType::TextEdited;
windowEvent.edit.length = event->edit.length;
window->m_lastEditEventLength = windowEvent.edit.length;
@ -540,7 +526,7 @@ namespace Nz
windowEvent.edit.text[i] = event->edit.text[i];
}
window->m_parent->PushEvent(windowEvent);
window->m_parent->HandleEvent(windowEvent);
break;
}
}
@ -557,7 +543,7 @@ namespace Nz
return 0;
}
void WindowImpl::SetCursor(const Cursor& cursor)
void WindowImpl::UpdateCursor(const Cursor& cursor)
{
m_cursor = cursor.m_impl->GetCursor();
@ -565,73 +551,57 @@ namespace Nz
RefreshCursor();
}
void WindowImpl::SetEventListener(bool listener)
{
if (m_ownsWindow)
return;
if (listener)
SDL_AddEventWatch(HandleEvent, this);
else
SDL_DelEventWatch(HandleEvent, this);
}
void WindowImpl::SetFocus()
void WindowImpl::RaiseFocus()
{
SDL_RaiseWindow(m_handle);
}
void WindowImpl::SetIcon(const Icon& icon)
void WindowImpl::UpdateIcon(const Icon& icon)
{
SDL_SetWindowIcon(m_handle, icon.m_impl->GetIcon());
}
void WindowImpl::SetMaximumSize(int width, int height)
void WindowImpl::UpdateMaximumSize(int width, int height)
{
SDL_SetWindowMaximumSize(m_handle, width, height);
}
void WindowImpl::SetMinimumSize(int width, int height)
void WindowImpl::UpdateMinimumSize(int width, int height)
{
SDL_SetWindowMinimumSize(m_handle, width, height);
}
void WindowImpl::SetPosition(int x, int y)
void WindowImpl::UpdatePosition(int x, int y)
{
SDL_SetWindowPosition(m_handle, x, y);
}
void WindowImpl::SetSize(unsigned int width, unsigned int height)
void WindowImpl::UpdateSize(unsigned int width, unsigned int height)
{
m_size.Set(width, height);
SDL_SetWindowSize(m_handle, width, height);
}
void WindowImpl::SetStayOnTop(bool stayOnTop)
void WindowImpl::UpdateStayOnTop(bool stayOnTop)
{
NazaraDebug("Stay on top isn't supported by SDL2 backend for now");
SDL_SetWindowAlwaysOnTop(m_handle, (stayOnTop) ? SDL_TRUE : SDL_FALSE);
}
void WindowImpl::SetTitle(const std::string& title)
void WindowImpl::UpdateTitle(const std::string& title)
{
SDL_SetWindowTitle(m_handle, title.c_str());
}
void WindowImpl::SetVisible(bool visible)
void WindowImpl::Show(bool visible)
{
visible ? SDL_ShowWindow(m_handle) : SDL_HideWindow(m_handle);
if (visible)
SDL_ShowWindow(m_handle);
else
SDL_HideWindow(m_handle);
}
void WindowImpl::PrepareWindow(bool fullscreen)
void WindowImpl::ProcessEvents()
{
(void)fullscreen; // ignore param warning
SDL_GetWindowPosition(m_handle, &m_position.x, &m_position.y);
int width, height;
SDL_GetWindowSize(m_handle, &width, &height);
m_size.Set(width, height);
SDL_PumpEvents();
}
bool WindowImpl::Initialize()
@ -650,27 +620,18 @@ namespace Nz
SDL_Quit();
}
// not implemented for now, wait for mainloop friendly input
//void WindowImpl::WindowThread(SDL_Window* handle, /*DWORD styleEx,*/ const String& title, /*DWORD style,*/ bool fullscreen, const Rectui& dimensions, WindowImpl* window, Mutex* mutex, ConditionVariable* condition)
//{
// SDL_Window& winHandle = *handle;
/*winHandle = CreateWindowExW(styleEx, className, title.GetWideString().data(), style, dimensions.x, dimensions.y, dimensions.width, dimensions.height, nullptr, nullptr, GetModuleHandle(nullptr), window);
void WindowImpl::SetEventListener(bool listener)
{
if (m_eventListener == listener)
return;
if (winHandle)
window->PrepareWindow(fullscreen);
if (listener)
SDL_AddEventWatch(HandleEvent, this);
else
SDL_DelEventWatch(HandleEvent, this);
mutex->Lock();
condition->Signal();
mutex->Unlock(); // mutex and condition may be destroyed after this line
if (!winHandle)
return;
while (window->m_threadActive)
window->ProcessEvents(true);
DestroyWindow(winHandle);*/
//}
m_eventListener = listener;
}
}
#if defined(NAZARA_PLATFORM_WINDOWS)

View File

@ -35,19 +35,17 @@ namespace Nz
~WindowImpl() = default;
bool Create(const VideoMode& mode, const std::string& title, WindowStyleFlags style);
bool Create(void* handle);
bool Create(WindowHandle handle);
void Destroy();
void EnableKeyRepeat(bool enable);
void EnableSmoothScrolling(bool enable);
Vector2i FetchPosition() const;
Vector2ui FetchSize() const;
WindowStyleFlags FetchStyle() const;
std::string FetchTitle() const;
SDL_Window* GetHandle() const;
Vector2i GetPosition() const;
Vector2ui GetSize() const;
WindowStyleFlags GetStyle() const;
WindowHandle GetSystemHandle() const;
std::string GetTitle() const;
bool HasFocus() const;
@ -56,52 +54,40 @@ namespace Nz
bool IsMinimized() const;
bool IsVisible() const;
void RaiseFocus();
void RefreshCursor();
void ProcessEvents(bool block);
void UpdateCursor(const Cursor& cursor);
void UpdateIcon(const Icon& icon);
void UpdateMaximumSize(int width, int height);
void UpdateMinimumSize(int width, int height);
void UpdatePosition(int x, int y);
void UpdateSize(unsigned int width, unsigned int height);
void UpdateStayOnTop(bool stayOnTop);
void UpdateTitle(const std::string& title);
void SetCursor(const Cursor& cursor);
void SetEventListener(bool listener);
void SetFocus();
void SetIcon(const Icon& icon);
void SetMaximumSize(int width, int height);
void SetMinimumSize(int width, int height);
void SetPosition(int x, int y);
void SetSize(unsigned int width, unsigned int height);
void SetStayOnTop(bool stayOnTop);
void SetTitle(const std::string& title);
void SetVisible(bool visible);
void Show(bool visible);
WindowImpl& operator=(const WindowImpl&) = delete;
WindowImpl& operator=(WindowImpl&&) = delete; ///TODO?
static void ProcessEvents();
static bool Initialize();
static void Uninitialize();
private:
void SetEventListener(bool listener);
static int SDLCALL HandleEvent(void* userdata, SDL_Event* event);
void PrepareWindow(bool fullscreen);
int m_lastEditEventLength = 0;
UInt32 m_windowId;
SDL_Cursor* m_cursor;
SDL_Window* m_handle;
WindowStyleFlags m_style;
Vector2i m_maxSize;
Vector2i m_minSize;
Vector2i m_mousePos;
Vector2i m_position;
Vector2ui m_size;
Window* m_parent;
bool m_eventListener;
bool m_ignoreNextMouseMove = false;
bool m_keyRepeat;
bool m_mouseInside;
bool m_ignoreNextMouseMove;
bool m_ownsWindow;
bool m_sizemove;
bool m_smoothScrolling;
bool m_threadActive;
short m_scrolling;
int m_lastEditEventLength;
};
}

View File

@ -12,33 +12,22 @@
namespace Nz
{
namespace NAZARA_ANONYMOUS_NAMESPACE
{
Window* s_fullscreenWindow = nullptr;
}
Window::Window() :
m_impl(nullptr),
m_asyncWindow(false),
m_closeOnQuit(true),
m_eventPolling(false),
m_waitForEvent(false)
{
ConnectSlots();
}
Window::Window(Window&& window) :
m_events(std::move(window.m_events)),
m_pendingEvents(std::move(window.m_pendingEvents)),
Window::Window(Window&& window) noexcept :
m_cursorController(std::move(window.m_cursorController)),
m_cursor(std::move(window.m_cursor)),
m_eventHandler(std::move(window.m_eventHandler)),
m_icon(std::move(window.m_icon)),
m_asyncWindow(window.m_asyncWindow),
m_closed(window.m_asyncWindow),
m_closed(window.m_closed),
m_closeOnQuit(window.m_closeOnQuit),
m_eventPolling(window.m_eventPolling),
m_ownsWindow(window.m_asyncWindow),
m_ownsWindow(window.m_ownsWindow),
m_waitForEvent(window.m_waitForEvent)
{
window.DisconnectSlots();
@ -52,214 +41,136 @@ namespace Nz
bool Window::Create(VideoMode mode, const std::string& title, WindowStyleFlags style)
{
NAZARA_USE_ANONYMOUS_NAMESPACE
// If the window is already open, we keep its position
bool opened = IsOpen();
Vector2i position;
if (opened)
position = m_impl->GetPosition();
position = m_position;
Destroy();
// Inspired by the code of the SFML by Laurent Gomila (and its team)
if (style & WindowStyle::Fullscreen)
{
if (s_fullscreenWindow)
{
NazaraError("Window " + PointerToString(s_fullscreenWindow) + " already in fullscreen mode");
style &= ~WindowStyle::Fullscreen;
}
else
{
if (!mode.IsFullscreenValid())
{
NazaraWarning("Video mode is not fullscreen valid");
mode = VideoMode::GetFullscreenModes()[0];
}
s_fullscreenWindow = this;
}
}
else if (style & WindowStyle::Closable || style & WindowStyle::Resizable)
if (style & WindowStyle::Closable || style & WindowStyle::Resizable)
style |= WindowStyle::Titlebar;
m_asyncWindow = (style & WindowStyle::Threaded) != 0;
std::unique_ptr<WindowImpl> impl = std::make_unique<WindowImpl>(this);
if (!impl->Create(mode, title, style))
m_impl = std::make_unique<WindowImpl>(this);
if (!m_impl->Create(mode, title, style))
{
NazaraError("Failed to create window implementation");
return false;
}
m_impl = impl.release();
CallOnExit destroyOnFailure([this] () { Destroy(); });
m_closed = false;
m_ownsWindow = true;
if (!OnWindowCreated())
{
NazaraError("Failed to initialize window extension");
return false;
}
m_position = m_impl->FetchPosition();
m_size = m_impl->FetchSize();
// Default parameters
m_impl->EnableKeyRepeat(true);
m_impl->EnableSmoothScrolling(false);
m_impl->SetMaximumSize(-1, -1);
m_impl->SetMinimumSize(-1, -1);
m_impl->SetVisible(true);
m_impl->UpdateMaximumSize(-1, -1);
m_impl->UpdateMinimumSize(-1, -1);
m_impl->Show(true);
if (opened)
m_impl->SetPosition(position.x, position.y);
OnWindowResized();
m_impl->UpdatePosition(position.x, position.y);
destroyOnFailure.Reset();
m_eventHandler.Dispatch({ WindowEventType::Created });
return true;
}
bool Window::Create(void* handle)
bool Window::Create(WindowHandle handle)
{
Destroy();
m_asyncWindow = false;
m_impl = new WindowImpl(this);
m_impl = std::make_unique<WindowImpl>(this);
if (!m_impl->Create(handle))
{
NazaraError("Unable to create window implementation");
delete m_impl;
m_impl = nullptr;
m_impl.reset();
return false;
}
m_position = m_impl->FetchPosition();
m_size = m_impl->FetchSize();
m_closed = false;
m_ownsWindow = false;
if (!OnWindowCreated())
{
NazaraError("Failed to initialize window's derivate");
delete m_impl;
m_impl = nullptr;
return false;
}
m_eventHandler.Dispatch({ WindowEventType::Created });
return true;
}
void Window::Destroy()
{
NAZARA_USE_ANONYMOUS_NAMESPACE
m_cursor.reset();
if (m_impl)
{
OnWindowDestroy();
m_eventHandler.Dispatch({ WindowEventType::Destruction });
m_impl->Destroy();
delete m_impl;
m_impl = nullptr;
if (s_fullscreenWindow == this)
s_fullscreenWindow = nullptr;
m_impl.reset();
}
}
void Window::EnableKeyRepeat(bool enable)
{
#if NAZARA_PLATFORM_SAFE
if (!m_impl)
{
NazaraError("Window not created");
return;
}
#endif
m_impl->EnableKeyRepeat(enable);
}
void Window::EnableSmoothScrolling(bool enable)
{
#if NAZARA_PLATFORM_SAFE
if (!m_impl)
{
NazaraError("Window not created");
return;
}
#endif
m_impl->EnableSmoothScrolling(enable);
m_cursor.reset();
}
Vector2i Window::GetPosition() const
{
#if NAZARA_PLATFORM_SAFE
if (!m_impl)
{
NazaraError("Window not created");
return Vector2i::Zero();
}
#endif
return m_impl->GetPosition();
NazaraAssert(m_impl, "Window not created");
return m_position;
}
Vector2ui Window::GetSize() const
{
#if NAZARA_PLATFORM_SAFE
if (!m_impl)
{
NazaraError("Window not created");
return Vector2ui::Zero();
}
#endif
return m_impl->GetSize();
NazaraAssert(m_impl, "Window not created");
return m_size;
}
WindowStyleFlags Window::GetStyle() const
{
#if NAZARA_PLATFORM_SAFE
if (!m_impl)
{
NazaraError("Window not created");
return 0;
}
#endif
return m_impl->GetStyle();
}
WindowHandle Window::GetSystemHandle() const
{
#if NAZARA_PLATFORM_SAFE
if (!m_impl)
{
NazaraError("Window not created");
return {};
}
#endif
return m_impl->GetSystemHandle();
NazaraAssert(m_impl, "Window not created");
return m_impl->FetchStyle();
}
std::string Window::GetTitle() const
{
#if NAZARA_PLATFORM_SAFE
if (!m_impl)
{
NazaraError("Window not created");
return {};
}
#endif
NazaraAssert(m_impl, "Window not created");
return m_impl->FetchTitle();
}
return m_impl->GetTitle();
void Window::HandleEvent(const WindowEvent& event)
{
m_eventHandler.Dispatch(event);
switch (event.type)
{
case WindowEventType::Moved:
{
m_position = { event.position.x, event.position.y };
break;
}
case WindowEventType::Quit:
{
if (m_closeOnQuit)
Close();
break;
}
case WindowEventType::Resized:
{
m_size = { event.size.width, event.size.height };
break;
}
default:
break;
}
}
bool Window::HasFocus() const
@ -301,76 +212,13 @@ namespace Nz
return m_impl->IsVisible();
}
bool Window::PollEvent(WindowEvent* event)
{
#if NAZARA_PLATFORM_SAFE
if (!m_impl)
{
NazaraError("Window not created");
return false;
}
#endif
if (!m_asyncWindow)
m_impl->ProcessEvents(false);
if (!m_events.empty())
{
if (event)
*event = m_events.front();
m_events.pop();
return true;
}
return false;
}
void Window::ProcessEvents(bool block)
{
NazaraAssert(m_impl, "Window not created");
NazaraUnused(block);
if (!m_asyncWindow)
m_impl->ProcessEvents(block);
else
{
std::lock_guard<std::mutex> eventLock(m_eventMutex);
for (const WindowEvent& event : m_pendingEvents)
HandleEvent(event);
m_pendingEvents.clear();
}
}
void Window::SetCursor(std::shared_ptr<Cursor> cursor)
{
NazaraAssert(m_impl, "Window not created");
NazaraAssert(cursor && cursor->IsValid(), "Invalid cursor");
m_cursor = std::move(cursor);
m_impl->SetCursor(*m_cursor);
}
void Window::SetEventListener(bool listener)
{
#if NAZARA_PLATFORM_SAFE
if (!m_impl)
{
NazaraError("Window not created");
return;
}
#endif
m_impl->SetEventListener(listener);
if (!listener)
{
// Empty the event queue
while (!m_events.empty())
m_events.pop();
}
m_impl->UpdateCursor(*m_cursor);
}
void Window::SetFocus()
@ -383,7 +231,7 @@ namespace Nz
}
#endif
m_impl->SetFocus();
m_impl->RaiseFocus();
}
void Window::SetIcon(std::shared_ptr<Icon> icon)
@ -392,7 +240,7 @@ namespace Nz
NazaraAssert(icon, "Invalid icon");
m_icon = std::move(icon);
m_impl->SetIcon(*m_icon);
m_impl->UpdateIcon(*m_icon);
}
void Window::SetMaximumSize(const Vector2i& maxSize)
@ -405,7 +253,7 @@ namespace Nz
}
#endif
m_impl->SetMaximumSize(maxSize.x, maxSize.y);
m_impl->UpdateMaximumSize(maxSize.x, maxSize.y);
}
void Window::SetMaximumSize(int width, int height)
@ -418,7 +266,7 @@ namespace Nz
}
#endif
m_impl->SetMaximumSize(width, height);
m_impl->UpdateMaximumSize(width, height);
}
void Window::SetMinimumSize(const Vector2i& minSize)
@ -431,7 +279,7 @@ namespace Nz
}
#endif
m_impl->SetMinimumSize(minSize.x, minSize.y);
m_impl->UpdateMinimumSize(minSize.x, minSize.y);
}
void Window::SetMinimumSize(int width, int height)
@ -444,7 +292,7 @@ namespace Nz
}
#endif
m_impl->SetMinimumSize(width, height);
m_impl->UpdateMinimumSize(width, height);
}
void Window::SetPosition(const Vector2i& position)
@ -457,7 +305,7 @@ namespace Nz
}
#endif
m_impl->SetPosition(position.x, position.y);
m_impl->UpdatePosition(position.x, position.y);
}
void Window::SetPosition(int x, int y)
@ -470,7 +318,7 @@ namespace Nz
}
#endif
m_impl->SetPosition(x, y);
m_impl->UpdatePosition(x, y);
}
void Window::SetSize(const Vector2i& size)
@ -483,7 +331,7 @@ namespace Nz
}
#endif
m_impl->SetSize(size.x, size.y);
m_impl->UpdateSize(size.x, size.y);
}
void Window::SetSize(unsigned int width, unsigned int height)
@ -496,7 +344,7 @@ namespace Nz
}
#endif
m_impl->SetSize(width, height);
m_impl->UpdateSize(width, height);
}
void Window::SetStayOnTop(bool stayOnTop)
@ -509,7 +357,7 @@ namespace Nz
}
#endif
m_impl->SetStayOnTop(stayOnTop);
m_impl->UpdateStayOnTop(stayOnTop);
}
void Window::SetTitle(const std::string& title)
@ -522,7 +370,7 @@ namespace Nz
}
#endif
m_impl->SetTitle(title);
m_impl->UpdateTitle(title);
}
void Window::SetVisible(bool visible)
@ -535,76 +383,18 @@ namespace Nz
}
#endif
m_impl->SetVisible(visible);
m_impl->Show(visible);
}
bool Window::WaitEvent(WindowEvent* event)
Window& Window::operator=(Window&& window) noexcept
{
#if NAZARA_PLATFORM_SAFE
if (!m_impl)
{
NazaraError("Window not created");
return false;
}
#endif
if (!m_asyncWindow)
{
while (m_events.empty())
m_impl->ProcessEvents(true);
if (event)
*event = m_events.front();
m_events.pop();
return true;
}
else
{
std::lock_guard<std::mutex> lock(m_eventMutex);
if (m_events.empty())
{
m_waitForEvent = true;
{
m_eventMutex.unlock();
std::unique_lock<std::mutex> eventConditionLock(m_eventConditionMutex);
m_eventCondition.wait(eventConditionLock);
m_eventMutex.lock();
}
m_waitForEvent = false;
}
if (!m_events.empty())
{
if (event)
*event = m_events.front();
m_events.pop();
return true;
}
return false;
}
}
Window& Window::operator=(Window&& window)
{
m_events = std::move(window.m_events);
m_pendingEvents = std::move(window.m_pendingEvents);
m_cursorController = std::move(window.m_cursorController);
m_cursor = std::move(window.m_cursor);
m_eventHandler = std::move(window.m_eventHandler);
m_icon = std::move(window.m_icon);
m_asyncWindow = window.m_asyncWindow;
m_closed = window.m_asyncWindow;
m_closed = window.m_closed;
m_closeOnQuit = window.m_closeOnQuit;
m_eventPolling = window.m_eventPolling;
m_ownsWindow = window.m_asyncWindow;
m_ownsWindow = window.m_ownsWindow;
m_waitForEvent = window.m_waitForEvent;
window.DisconnectSlots();
@ -613,22 +403,14 @@ namespace Nz
return *this;
}
void* Window::GetHandle()
void Window::ProcessEvents()
{
return (m_impl) ? m_impl->GetHandle() : nullptr;
WindowImpl::ProcessEvents();
}
bool Window::OnWindowCreated()
{
return true;
}
void Window::OnWindowDestroy()
{
}
void Window::OnWindowResized()
WindowHandle Window::GetHandle() const
{
return (m_impl) ? m_impl->GetSystemHandle() : WindowHandle{};
}
void Window::ConnectSlots()
@ -658,34 +440,6 @@ namespace Nz
m_impl->IgnoreNextMouseEvent(mouseX, mouseY);
}
void Window::HandleEvent(const WindowEvent& event)
{
if (m_eventPolling)
m_events.push(event);
m_eventHandler.Dispatch(event);
switch (event.type)
{
case WindowEventType::MouseEntered:
m_impl->RefreshCursor();
break;
case WindowEventType::Resized:
OnWindowResized();
break;
case WindowEventType::Quit:
if (m_closeOnQuit)
Close();
break;
default:
break;
}
}
bool Window::Initialize()
{
return WindowImpl::Initialize();

View File

@ -1,11 +0,0 @@
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Renderer module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Renderer/RenderSurface.hpp>
#include <Nazara/Renderer/Debug.hpp>
namespace Nz
{
RenderSurface::~RenderSurface() = default;
}

View File

@ -1,91 +0,0 @@
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Renderer module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Renderer/RenderWindow.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Renderer/Renderer.hpp>
#include <Nazara/Renderer/RendererImpl.hpp>
#include <chrono>
#include <thread>
#include <Nazara/Renderer/Debug.hpp>
namespace Nz
{
RenderFrame RenderWindow::AcquireFrame()
{
if (!m_impl)
{
NazaraError("window is not created");
return RenderFrame{};
}
if (m_framerateLimit > 0)
{
int remainingTime = 1000 / static_cast<int>(m_framerateLimit) - static_cast<int>(m_clock.GetElapsedTime().AsMilliseconds());
if (remainingTime > 0)
std::this_thread::sleep_for(std::chrono::milliseconds(remainingTime));
m_clock.Restart();
}
return m_impl->Acquire();
}
bool RenderWindow::Create(std::shared_ptr<RenderDevice> renderDevice, VideoMode mode, const std::string& title, WindowStyleFlags style, const RenderWindowParameters& parameters)
{
m_parameters = parameters;
m_renderDevice = std::move(renderDevice);
return Window::Create(mode, title, style);
}
bool RenderWindow::Create(std::shared_ptr<RenderDevice> renderDevice, void* handle, const RenderWindowParameters& parameters)
{
m_parameters = parameters;
m_renderDevice = std::move(renderDevice);
return Window::Create(handle);
}
void RenderWindow::EnableVerticalSync(bool enabled)
{
///TODO
}
bool RenderWindow::OnWindowCreated()
{
RendererImpl* rendererImpl = Renderer::Instance()->GetRendererImpl();
auto surface = rendererImpl->CreateRenderSurfaceImpl();
if (!surface->Create(GetSystemHandle()))
{
NazaraError("Failed to create render surface: " + Error::GetLastError());
return false;
}
auto impl = rendererImpl->CreateRenderWindowImpl(*this);
if (!impl->Create(rendererImpl, surface.get(), 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();
return true;
}
void RenderWindow::OnWindowDestroy()
{
m_impl.reset();
m_renderDevice.reset();
m_surface.reset();
}
void RenderWindow::OnWindowResized()
{
}
}

View File

@ -2,14 +2,14 @@
// This file is part of the "Nazara Engine - Renderer module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Renderer/RenderWindowImpl.hpp>
#include <Nazara/Renderer/Swapchain.hpp>
#include <Nazara/Renderer/Debug.hpp>
namespace Nz
{
RenderWindowImpl::~RenderWindowImpl() = default;
Swapchain::~Swapchain() = default;
void RenderWindowImpl::BuildRenderPass(PixelFormat colorFormat, PixelFormat depthFormat, std::vector<RenderPass::Attachment>& attachments, std::vector<RenderPass::SubpassDescription>& subpassDescriptions, std::vector<RenderPass::SubpassDependency>& subpassDependencies)
void Swapchain::BuildRenderPass(PixelFormat colorFormat, PixelFormat depthFormat, std::vector<RenderPass::Attachment>& attachments, std::vector<RenderPass::SubpassDescription>& subpassDescriptions, std::vector<RenderPass::SubpassDependency>& subpassDependencies)
{
assert(colorFormat != PixelFormat::Undefined);

View File

@ -0,0 +1,72 @@
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Renderer module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Renderer/WindowSwapchain.hpp>
#include <Nazara/Renderer/RenderDevice.hpp>
#include <Nazara/Platform/Window.hpp>
#include <Nazara/Renderer/Debug.hpp>
namespace Nz
{
WindowSwapchain::WindowSwapchain(std::shared_ptr<RenderDevice> renderDevice, Window& window, SwapchainParameters parameters) :
m_renderDevice(std::move(renderDevice)),
m_window(&window),
m_parameters(std::move(parameters)),
m_renderOnlyIfFocused(false)
{
NazaraAssert(m_renderDevice, "invalid render device");
if (m_window->IsValid())
{
m_swapchain = m_renderDevice->InstantiateSwapchain(window.GetHandle(), window.GetSize(), m_parameters);
m_isMinimized = window.IsMinimized();
}
else
m_isMinimized = true; //< consider it minimized so AcquireFrame returns no frame
ConnectSignals();
}
void WindowSwapchain::ConnectSignals()
{
WindowEventHandler& windowEvents = m_window->GetEventHandler();
m_onCreated.Connect(windowEvents.OnCreated, [this](const WindowEventHandler* /*eventHandler*/)
{
// Recreate swapchain
m_swapchain = m_renderDevice->InstantiateSwapchain(m_window->GetHandle(), m_window->GetSize(), m_parameters);
m_isMinimized = m_window->IsMinimized();
});
m_onDestruction.Connect(windowEvents.OnDestruction, [this](const WindowEventHandler* /*eventHandler*/)
{
m_swapchain.reset();
m_isMinimized = true;
});
m_onGainedFocus.Connect(windowEvents.OnGainedFocus, [this](const WindowEventHandler* /*eventHandler*/)
{
m_hasFocus = true;
});
m_onLostFocus.Connect(windowEvents.OnLostFocus, [this](const WindowEventHandler* /*eventHandler*/)
{
m_hasFocus = false;
});
m_onMinimized.Connect(windowEvents.OnMinimized, [this](const WindowEventHandler* /*eventHandler*/)
{
m_isMinimized = true;
});
m_onResized.Connect(windowEvents.OnResized, [this](const WindowEventHandler* /*eventHandler*/, const WindowEvent::SizeEvent& event)
{
m_swapchain->NotifyResize({ event.width, event.height });
});
m_onRestored.Connect(windowEvents.OnRestored, [this](const WindowEventHandler* /*eventHandler*/)
{
m_isMinimized = false;
});
}
}

View File

@ -9,6 +9,7 @@
#include <Nazara/VulkanRenderer/VulkanRenderPipeline.hpp>
#include <Nazara/VulkanRenderer/VulkanRenderPipelineLayout.hpp>
#include <Nazara/VulkanRenderer/VulkanShaderModule.hpp>
#include <Nazara/VulkanRenderer/VulkanSwapchain.hpp>
#include <Nazara/VulkanRenderer/VulkanTexture.hpp>
#include <Nazara/VulkanRenderer/VulkanTextureFramebuffer.hpp>
#include <Nazara/VulkanRenderer/VulkanTextureSampler.hpp>
@ -85,6 +86,11 @@ namespace Nz
return stage;
}
std::shared_ptr<Swapchain> VulkanDevice::InstantiateSwapchain(WindowHandle windowHandle, const Vector2ui& windowSize, const SwapchainParameters& parameters)
{
return std::make_shared<VulkanSwapchain>(*this, windowHandle, windowSize, parameters);
}
std::shared_ptr<Texture> VulkanDevice::InstantiateTexture(const TextureInfo& params)
{
return std::make_shared<VulkanTexture>(*this, params);

View File

@ -5,13 +5,13 @@
#include <Nazara/VulkanRenderer/VulkanRenderImage.hpp>
#include <Nazara/VulkanRenderer/VulkanCommandBuffer.hpp>
#include <Nazara/VulkanRenderer/VulkanCommandBufferBuilder.hpp>
#include <Nazara/VulkanRenderer/VulkanRenderWindow.hpp>
#include <Nazara/VulkanRenderer/VulkanSwapchain.hpp>
#include <stdexcept>
#include <Nazara/VulkanRenderer/Debug.hpp>
namespace Nz
{
VulkanRenderImage::VulkanRenderImage(VulkanRenderWindow& owner) :
VulkanRenderImage::VulkanRenderImage(VulkanSwapchain& owner) :
m_owner(owner),
m_uploadPool(m_owner.GetDevice(), 2 * 1024 * 1024)
{

View File

@ -6,8 +6,7 @@
#include <Nazara/Core/ErrorFlags.hpp>
#include <Nazara/Renderer/RenderDevice.hpp>
#include <Nazara/VulkanRenderer/VulkanBuffer.hpp>
#include <Nazara/VulkanRenderer/VulkanRenderWindow.hpp>
#include <Nazara/VulkanRenderer/VulkanSurface.hpp>
#include <Nazara/VulkanRenderer/VulkanSwapchain.hpp>
#include <Nazara/VulkanRenderer/Wrapper/Loader.hpp>
#include <cassert>
#include <sstream>
@ -20,16 +19,6 @@ namespace Nz
Vulkan::Uninitialize();
}
std::unique_ptr<RenderSurface> VulkanRenderer::CreateRenderSurfaceImpl()
{
return std::make_unique<VulkanSurface>();
}
std::unique_ptr<RenderWindowImpl> VulkanRenderer::CreateRenderWindowImpl(RenderWindow& owner)
{
return std::make_unique<VulkanRenderWindow>(owner);
}
std::shared_ptr<RenderDevice> VulkanRenderer::InstanciateRenderDevice(std::size_t deviceIndex, const RenderDeviceFeatures& enabledFeatures)
{
const auto& physDevices = Vulkan::GetPhysicalDevices();

View File

@ -1,98 +0,0 @@
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Vulkan renderer"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/VulkanRenderer/VulkanSurface.hpp>
#include <Nazara/VulkanRenderer/Vulkan.hpp>
#include <vulkan/vk_sdk_platform.h>
#include <Nazara/VulkanRenderer/Debug.hpp>
#ifdef VK_USE_PLATFORM_METAL_EXT
#include <objc/runtime.h>
#include <vulkan/vulkan_metal.h>
#endif
namespace Nz
{
#ifdef VK_USE_PLATFORM_METAL_EXT
id CreateAndAttachMetalLayer(void* window);
#endif
VulkanSurface::VulkanSurface() :
m_surface(Vulkan::GetInstance())
{
}
bool VulkanSurface::Create(WindowHandle handle)
{
bool success = false;
#if defined(NAZARA_PLATFORM_WINDOWS)
{
NazaraAssert(handle.type == WindowBackend::Windows, "expected Windows window");
HWND winHandle = reinterpret_cast<HWND>(handle.windows.window);
HINSTANCE instance = reinterpret_cast<HINSTANCE>(GetWindowLongPtrW(winHandle, GWLP_HINSTANCE));
success = m_surface.Create(instance, winHandle);
}
#elif defined(NAZARA_PLATFORM_LINUX)
{
switch (handle.type)
{
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
case WindowBackend::Wayland:
{
wl_display* display = static_cast<wl_display*>(handle.wayland.display);
wl_surface* surface = static_cast<wl_surface*>(handle.wayland.surface);
success = m_surface.Create(display, surface);
break;
}
#endif
#ifdef VK_USE_PLATFORM_XLIB_KHR
case WindowBackend::X11:
{
Display* display = static_cast<Display*>(handle.x11.display);
::Window window = static_cast<::Window>(handle.x11.window);
success = m_surface.Create(display, window);
break;
}
#endif
default:
{
NazaraError("unhandled window type");
return false;
}
}
}
#elif defined(NAZARA_PLATFORM_MACOS)
{
NazaraAssert(handle.type == WindowBackend::Cocoa, "expected cocoa window");
id layer = CreateAndAttachMetalLayer(handle.cocoa.window);
success = m_surface.Create(layer);
}
#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();
}
}
#if defined(NAZARA_PLATFORM_WINDOWS)
#include <Nazara/Core/AntiWindows.hpp>
#endif

View File

@ -4,13 +4,17 @@
namespace Nz
{
id CreateAndAttachMetalLayer(void* window) {
NSWindow* obj = (__bridge NSWindow*)window;
id CreateAndAttachMetalLayer(void* window)
{
NSWindow* obj = (__bridge NSWindow*) window;
NSView* view = [[NSView alloc] initWithFrame:obj.frame];
[view setLayer:[CAMetalLayer layer]];
[view setWantsLayer:YES];
view.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
[obj.contentView addSubview:view];
return view.layer;
}
}

View File

@ -2,34 +2,160 @@
// This file is part of the "Nazara Engine - Vulkan renderer"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/VulkanRenderer/VulkanRenderWindow.hpp>
#include <Nazara/VulkanRenderer/VulkanSwapchain.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/ErrorFlags.hpp>
#include <Nazara/Math/Vector2.hpp>
#include <Nazara/Renderer/RenderWindow.hpp>
#include <Nazara/Renderer/WindowSwapchain.hpp>
#include <Nazara/Utility/PixelFormat.hpp>
#include <Nazara/VulkanRenderer/Vulkan.hpp>
#include <Nazara/VulkanRenderer/VulkanCommandPool.hpp>
#include <Nazara/VulkanRenderer/VulkanDevice.hpp>
#include <Nazara/VulkanRenderer/VulkanSurface.hpp>
#include <Nazara/Utils/StackArray.hpp>
#include <array>
#include <stdexcept>
#ifdef VK_USE_PLATFORM_METAL_EXT
#include <objc/runtime.h>
#include <vulkan/vulkan_metal.h>
#endif
#include <Nazara/VulkanRenderer/Debug.hpp>
namespace Nz
{
VulkanRenderWindow::VulkanRenderWindow(RenderWindow& owner) :
#ifdef VK_USE_PLATFORM_METAL_EXT
id CreateAndAttachMetalLayer(void* window);
#endif
VulkanSwapchain::VulkanSwapchain(VulkanDevice& device, WindowHandle windowHandle, const Vector2ui& windowSize, const SwapchainParameters& parameters) :
m_currentFrame(0),
m_owner(owner),
m_surface(device.GetInstance()),
m_swapchainSize(windowSize),
m_device(device),
m_shouldRecreateSwapchain(false)
{
if (!SetupSurface(windowHandle))
throw std::runtime_error("failed to create surface");
const auto& physDeviceInfo = m_device.GetPhysicalDeviceInfo();
const std::vector<Vk::Device::QueueFamilyInfo>& queueFamilyInfo = m_device.GetEnabledQueues();
UInt32 graphicsFamilyQueueIndex = UINT32_MAX;
UInt32 presentableFamilyQueueIndex = UINT32_MAX;
for (const Vk::Device::QueueFamilyInfo& queueInfo : queueFamilyInfo)
{
bool supported = false;
if (m_surface.GetSupportPresentation(physDeviceInfo.physDevice, queueInfo.familyIndex, &supported) && supported)
{
if (presentableFamilyQueueIndex == UINT32_MAX || queueInfo.flags & VK_QUEUE_GRAPHICS_BIT)
{
presentableFamilyQueueIndex = queueInfo.familyIndex;
if (queueInfo.flags & VK_QUEUE_GRAPHICS_BIT)
{
graphicsFamilyQueueIndex = queueInfo.familyIndex;
break;
}
}
}
}
if (presentableFamilyQueueIndex == UINT32_MAX)
throw std::runtime_error("device doesn't support presenting to this surface");
if (graphicsFamilyQueueIndex == UINT32_MAX)
{
for (const Vk::Device::QueueFamilyInfo& queueInfo : queueFamilyInfo)
{
if (queueInfo.flags & VK_QUEUE_GRAPHICS_BIT)
{
graphicsFamilyQueueIndex = queueInfo.familyIndex;
break;
}
}
}
if (graphicsFamilyQueueIndex == UINT32_MAX)
throw std::runtime_error("device doesn't support graphics operation");
UInt32 transferFamilyQueueIndex = UINT32_MAX;
// Search for a transfer queue (first one being different to the graphics one)
for (const Vk::Device::QueueFamilyInfo& queueInfo : queueFamilyInfo)
{
// Transfer bit is not mandatory if compute and graphics bits are set (as they implicitly support transfer)
if (queueInfo.flags & (VK_QUEUE_COMPUTE_BIT | VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_TRANSFER_BIT))
{
transferFamilyQueueIndex = queueInfo.familyIndex;
if (transferFamilyQueueIndex != graphicsFamilyQueueIndex)
break;
}
}
assert(transferFamilyQueueIndex != UINT32_MAX);
m_graphicsQueue = m_device.GetQueue(graphicsFamilyQueueIndex, 0);
m_presentQueue = m_device.GetQueue(presentableFamilyQueueIndex, 0);
m_transferQueue = m_device.GetQueue(transferFamilyQueueIndex, 0);
std::vector<VkSurfaceFormatKHR> surfaceFormats;
if (!m_surface.GetFormats(physDeviceInfo.physDevice, &surfaceFormats))
throw std::runtime_error("failed to query supported surface formats");
m_surfaceFormat = [&]() -> VkSurfaceFormatKHR
{
if (surfaceFormats.size() == 1 && surfaceFormats.front().format == VK_FORMAT_UNDEFINED)
{
// If the list contains one undefined format, it means any format can be used
return { VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
}
else
{
// Search for RGBA8 and default to first format
for (const VkSurfaceFormatKHR& surfaceFormat : surfaceFormats)
{
if (surfaceFormat.format == VK_FORMAT_R8G8B8A8_UNORM)
return surfaceFormat;
}
return surfaceFormats.front();
}
}();
m_depthStencilFormat = VK_FORMAT_UNDEFINED;
if (!parameters.depthFormats.empty())
{
for (PixelFormat format : parameters.depthFormats)
{
PixelFormatContent formatContent = PixelFormatInfo::GetContent(format);
if (formatContent != PixelFormatContent::DepthStencil && formatContent != PixelFormatContent::Stencil)
NazaraWarning("Invalid format " + PixelFormatInfo::GetName(format) + " for depth-stencil attachment");
m_depthStencilFormat = ToVulkan(format);
if (m_depthStencilFormat == VK_FORMAT_UNDEFINED)
continue;
VkFormatProperties formatProperties = m_device.GetInstance().GetPhysicalDeviceFormatProperties(physDeviceInfo.physDevice, m_depthStencilFormat);
if (formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)
break; //< Found it
m_depthStencilFormat = VK_FORMAT_UNDEFINED;
}
if (m_depthStencilFormat == VK_FORMAT_UNDEFINED)
throw std::runtime_error("failed to find a support depth-stencil format");
}
if (!SetupRenderPass())
throw std::runtime_error("failed to create renderpass");
if (!CreateSwapchain())
throw std::runtime_error("failed to create swapchain");
}
VulkanRenderWindow::~VulkanRenderWindow()
VulkanSwapchain::~VulkanSwapchain()
{
if (m_device)
m_device->WaitForIdle();
m_device.WaitForIdle();
m_concurrentImageData.clear();
m_renderPass.reset();
@ -37,22 +163,13 @@ namespace Nz
m_swapchain.Destroy();
}
RenderFrame VulkanRenderWindow::Acquire()
RenderFrame VulkanSwapchain::AcquireFrame()
{
bool invalidateFramebuffer = false;
Vector2ui size = m_owner.GetSize();
// Special case: window is minimized
if (size == Nz::Vector2ui::Zero() || m_owner.IsMinimized())
return RenderFrame();
if (m_shouldRecreateSwapchain || size != m_swapchainSize)
if (m_shouldRecreateSwapchain)
{
Vk::Surface& vulkanSurface = static_cast<VulkanSurface*>(m_owner.GetSurface())->GetSurface();
OnRenderTargetSizeChange(this, size);
if (!CreateSwapchain(vulkanSurface, size))
if (!CreateSwapchain())
throw std::runtime_error("failed to recreate swapchain");
m_shouldRecreateSwapchain = false;
@ -79,7 +196,7 @@ namespace Nz
case VK_ERROR_OUT_OF_DATE_KHR:
m_shouldRecreateSwapchain = true;
return Acquire();
return AcquireFrame();
// Not expected (since timeout is infinite)
case VK_TIMEOUT:
@ -102,191 +219,16 @@ namespace Nz
currentFrame.Reset(imageIndex);
return RenderFrame(&currentFrame, invalidateFramebuffer, size, imageIndex);
return RenderFrame(&currentFrame, invalidateFramebuffer, m_swapchainSize, imageIndex);
}
bool VulkanRenderWindow::Create(RendererImpl* /*renderer*/, RenderSurface* surface, const RenderWindowParameters& parameters)
{
std::shared_ptr<VulkanDevice> device = std::static_pointer_cast<VulkanDevice>(m_owner.GetRenderDevice());
const auto& physDeviceInfo = device->GetPhysicalDeviceInfo();
Vk::Surface& vulkanSurface = static_cast<VulkanSurface*>(surface)->GetSurface();
const std::vector<Vk::Device::QueueFamilyInfo>& queueFamilyInfo = device->GetEnabledQueues();
UInt32 graphicsFamilyQueueIndex = UINT32_MAX;
UInt32 presentableFamilyQueueIndex = UINT32_MAX;
for (const Vk::Device::QueueFamilyInfo& queueInfo : queueFamilyInfo)
{
bool supported = false;
if (vulkanSurface.GetSupportPresentation(physDeviceInfo.physDevice, queueInfo.familyIndex, &supported) && supported)
{
if (presentableFamilyQueueIndex == UINT32_MAX || queueInfo.flags & VK_QUEUE_GRAPHICS_BIT)
{
presentableFamilyQueueIndex = queueInfo.familyIndex;
if (queueInfo.flags & VK_QUEUE_GRAPHICS_BIT)
{
graphicsFamilyQueueIndex = queueInfo.familyIndex;
break;
}
}
}
}
if (presentableFamilyQueueIndex == UINT32_MAX)
{
NazaraError("device doesn't support presenting to this surface");
return false;
}
if (graphicsFamilyQueueIndex == UINT32_MAX)
{
for (const Vk::Device::QueueFamilyInfo& queueInfo : queueFamilyInfo)
{
if (queueInfo.flags & VK_QUEUE_GRAPHICS_BIT)
{
graphicsFamilyQueueIndex = queueInfo.familyIndex;
break;
}
}
}
if (graphicsFamilyQueueIndex == UINT32_MAX)
{
NazaraError("device doesn't support graphics operations");
return false;
}
UInt32 transferFamilyQueueIndex = UINT32_MAX;
// Search for a transfer queue (first one being different to the graphics one)
for (const Vk::Device::QueueFamilyInfo& queueInfo : queueFamilyInfo)
{
// Transfer bit is not mandatory if compute and graphics bits are set (as they implicitly support transfer)
if (queueInfo.flags & (VK_QUEUE_COMPUTE_BIT | VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_TRANSFER_BIT))
{
transferFamilyQueueIndex = queueInfo.familyIndex;
if (transferFamilyQueueIndex != graphicsFamilyQueueIndex)
break;
}
}
assert(transferFamilyQueueIndex != UINT32_MAX);
m_device = std::move(device);
m_graphicsQueue = m_device->GetQueue(graphicsFamilyQueueIndex, 0);
m_presentQueue = m_device->GetQueue(presentableFamilyQueueIndex, 0);
m_transferQueue = m_device->GetQueue(transferFamilyQueueIndex, 0);
std::vector<VkSurfaceFormatKHR> surfaceFormats;
if (!vulkanSurface.GetFormats(physDeviceInfo.physDevice, &surfaceFormats))
{
NazaraError("Failed to query supported surface formats");
return false;
}
m_surfaceFormat = [&] () -> VkSurfaceFormatKHR
{
if (surfaceFormats.size() == 1 && surfaceFormats.front().format == VK_FORMAT_UNDEFINED)
{
// If the list contains one undefined format, it means any format can be used
return { VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
}
else
{
// Search for RGBA8 and default to first format
for (const VkSurfaceFormatKHR& surfaceFormat : surfaceFormats)
{
if (surfaceFormat.format == VK_FORMAT_R8G8B8A8_UNORM)
return surfaceFormat;
}
return surfaceFormats.front();
}
}();
m_depthStencilFormat = VK_FORMAT_MAX_ENUM;
if (!parameters.depthFormats.empty())
{
for (PixelFormat format : parameters.depthFormats)
{
switch (format)
{
case PixelFormat::Depth16:
m_depthStencilFormat = VK_FORMAT_D16_UNORM;
break;
case PixelFormat::Depth16Stencil8:
m_depthStencilFormat = VK_FORMAT_D16_UNORM_S8_UINT;
break;
case PixelFormat::Depth24:
case PixelFormat::Depth24Stencil8:
m_depthStencilFormat = VK_FORMAT_D24_UNORM_S8_UINT;
break;
case PixelFormat::Depth32F:
m_depthStencilFormat = VK_FORMAT_D32_SFLOAT;
break;
case PixelFormat::Depth32FStencil8:
m_depthStencilFormat = VK_FORMAT_D32_SFLOAT_S8_UINT;
break;
case PixelFormat::Stencil1:
case PixelFormat::Stencil4:
case PixelFormat::Stencil8:
m_depthStencilFormat = VK_FORMAT_S8_UINT;
break;
case PixelFormat::Stencil16:
continue;
default:
{
PixelFormatContent formatContent = PixelFormatInfo::GetContent(format);
if (formatContent != PixelFormatContent::DepthStencil && formatContent != PixelFormatContent::Stencil)
NazaraWarning("Invalid format " + PixelFormatInfo::GetName(format) + " for depth-stencil attachment");
m_depthStencilFormat = VK_FORMAT_MAX_ENUM;
break;
}
}
if (m_depthStencilFormat != VK_FORMAT_MAX_ENUM)
{
VkFormatProperties formatProperties = m_device->GetInstance().GetPhysicalDeviceFormatProperties(physDeviceInfo.physDevice, m_depthStencilFormat);
if (formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)
break; //< Found it
m_depthStencilFormat = VK_FORMAT_MAX_ENUM;
}
}
}
if (!SetupRenderPass())
{
NazaraError("Failed to create render pass");
return false;
}
if (!CreateSwapchain(vulkanSurface, m_owner.GetSize()))
{
NazaraError("failed to create swapchain");
return false;
}
return true;
}
std::shared_ptr<CommandPool> VulkanRenderWindow::CreateCommandPool(QueueType queueType)
std::shared_ptr<CommandPool> VulkanSwapchain::CreateCommandPool(QueueType queueType)
{
UInt32 queueFamilyIndex = [&] {
switch (queueType)
{
case QueueType::Compute:
return m_device->GetDefaultFamilyIndex(QueueType::Compute);
return m_device.GetDefaultFamilyIndex(QueueType::Compute);
case QueueType::Graphics:
return m_graphicsQueue.GetQueueFamilyIndex();
@ -298,31 +240,62 @@ namespace Nz
throw std::runtime_error("invalid queue type " + std::to_string(UnderlyingCast(queueType)));
}();
return std::make_shared<VulkanCommandPool>(*m_device, queueFamilyIndex);
return std::make_shared<VulkanCommandPool>(m_device, queueFamilyIndex);
}
const VulkanWindowFramebuffer& VulkanRenderWindow::GetFramebuffer(std::size_t i) const
bool VulkanSwapchain::CreateSwapchain()
{
if (!SetupSwapchain(m_device.GetPhysicalDeviceInfo()))
{
NazaraError("Failed to create swapchain");
return false;
}
if (m_depthStencilFormat != VK_FORMAT_MAX_ENUM && !SetupDepthBuffer())
{
NazaraError("Failed to create depth buffer");
return false;
}
if (!SetupFrameBuffers())
{
NazaraError("failed to create framebuffers");
return false;
}
return true;
}
const VulkanWindowFramebuffer& VulkanSwapchain::GetFramebuffer(std::size_t i) const
{
assert(i < m_framebuffers.size());
return m_framebuffers[i];
}
std::size_t VulkanRenderWindow::GetFramebufferCount() const
std::size_t VulkanSwapchain::GetFramebufferCount() const
{
return m_framebuffers.size();
}
const VulkanRenderPass& VulkanRenderWindow::GetRenderPass() const
const VulkanRenderPass& VulkanSwapchain::GetRenderPass() const
{
return *m_renderPass;
}
const Vector2ui& VulkanRenderWindow::GetSize() const
const Vector2ui& VulkanSwapchain::GetSize() const
{
return m_swapchainSize;
}
void VulkanRenderWindow::Present(UInt32 imageIndex, VkSemaphore waitSemaphore)
void VulkanSwapchain::NotifyResize(const Vector2ui& newSize)
{
OnRenderTargetSizeChange(this, newSize);
m_swapchainSize = newSize;
m_shouldRecreateSwapchain = true;
}
void VulkanSwapchain::Present(UInt32 imageIndex, VkSemaphore waitSemaphore)
{
NazaraAssert(imageIndex < m_inflightFences.size(), "Invalid image index");
@ -354,31 +327,7 @@ namespace Nz
}
}
bool VulkanRenderWindow::CreateSwapchain(Vk::Surface& surface, const Vector2ui& size)
{
assert(m_device);
if (!SetupSwapchain(m_device->GetPhysicalDeviceInfo(), surface, size))
{
NazaraError("Failed to create swapchain");
return false;
}
if (m_depthStencilFormat != VK_FORMAT_MAX_ENUM && !SetupDepthBuffer(size))
{
NazaraError("Failed to create depth buffer");
return false;
}
if (!SetupFrameBuffers(size))
{
NazaraError("failed to create framebuffers");
return false;
}
return true;
}
bool VulkanRenderWindow::SetupDepthBuffer(const Vector2ui& size)
bool VulkanSwapchain::SetupDepthBuffer()
{
VkImageCreateInfo imageCreateInfo = {
VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
@ -386,7 +335,7 @@ namespace Nz
0U, // VkImageCreateFlags flags;
VK_IMAGE_TYPE_2D, // VkImageType imageType;
m_depthStencilFormat, // VkFormat format;
{size.x, size.y, 1U}, // VkExtent3D extent;
{ m_swapchainSize.x, m_swapchainSize.y, 1U }, // VkExtent3D extent;
1U, // uint32_t mipLevels;
1U, // uint32_t arrayLayers;
VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
@ -398,14 +347,14 @@ namespace Nz
VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
};
if (!m_depthBuffer.Create(*m_device, imageCreateInfo))
if (!m_depthBuffer.Create(m_device, imageCreateInfo))
{
NazaraError("Failed to create depth buffer");
return false;
}
VkMemoryRequirements memoryReq = m_depthBuffer.GetMemoryRequirements();
if (!m_depthBufferMemory.Create(*m_device, memoryReq.size, memoryReq.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT))
if (!m_depthBufferMemory.Create(m_device, memoryReq.size, memoryReq.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT))
{
NazaraError("Failed to allocate depth buffer memory");
return false;
@ -433,21 +382,21 @@ namespace Nz
VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
m_depthStencilFormat, // VkFormat format;
{ // VkComponentMapping components;
VK_COMPONENT_SWIZZLE_R, // VkComponentSwizzle .r;
VK_COMPONENT_SWIZZLE_G, // VkComponentSwizzle .g;
VK_COMPONENT_SWIZZLE_B, // VkComponentSwizzle .b;
VK_COMPONENT_SWIZZLE_A // VkComponentSwizzle .a;
VK_COMPONENT_SWIZZLE_R, // VkComponentSwizzle .r;
VK_COMPONENT_SWIZZLE_G, // VkComponentSwizzle .g;
VK_COMPONENT_SWIZZLE_B, // VkComponentSwizzle .b;
VK_COMPONENT_SWIZZLE_A // VkComponentSwizzle .a;
},
{ // VkImageSubresourceRange subresourceRange;
aspectMask, // VkImageAspectFlags .aspectMask;
0, // uint32_t .baseMipLevel;
1, // uint32_t .levelCount;
0, // uint32_t .baseArrayLayer;
1 // uint32_t .layerCount;
aspectMask, // VkImageAspectFlags .aspectMask;
0, // uint32_t .baseMipLevel;
1, // uint32_t .levelCount;
0, // uint32_t .baseArrayLayer;
1 // uint32_t .layerCount;
}
};
if (!m_depthBufferView.Create(*m_device, imageViewCreateInfo))
if (!m_depthBufferView.Create(m_device, imageViewCreateInfo))
{
NazaraError("Failed to create depth buffer view");
return false;
@ -456,7 +405,7 @@ namespace Nz
return true;
}
bool VulkanRenderWindow::SetupFrameBuffers(const Vector2ui& size)
bool VulkanSwapchain::SetupFrameBuffers()
{
UInt32 imageCount = m_swapchain.GetImageCount();
@ -473,14 +422,14 @@ namespace Nz
m_renderPass->GetRenderPass(),
(attachments[1] != VK_NULL_HANDLE) ? 2U : 1U,
attachments.data(),
size.x,
size.y,
m_swapchainSize.x,
m_swapchainSize.y,
1U
};
Vk::Framebuffer framebuffer;
if (!framebuffer.Create(*m_device, frameBufferCreate))
if (!framebuffer.Create(*m_swapchain.GetDevice(), frameBufferCreate))
{
NazaraError("Failed to create framebuffer for image #" + NumberToString(i) + ": " + TranslateVulkanError(framebuffer.GetLastErrorCode()));
return false;
@ -492,7 +441,7 @@ namespace Nz
return true;
}
bool VulkanRenderWindow::SetupRenderPass()
bool VulkanSwapchain::SetupRenderPass()
{
std::optional<PixelFormat> colorFormat = FromVulkan(m_surfaceFormat.format);
if (!colorFormat)
@ -517,34 +466,98 @@ namespace Nz
std::vector<RenderPass::SubpassDependency> subpassDependencies;
BuildRenderPass(*colorFormat, depthStencilFormat.value_or(PixelFormat::Undefined), attachments, subpassDescriptions, subpassDependencies);
m_renderPass.emplace(*m_device, std::move(attachments), std::move(subpassDescriptions), std::move(subpassDependencies));
m_renderPass.emplace(m_device, std::move(attachments), std::move(subpassDescriptions), std::move(subpassDependencies));
return true;
}
bool VulkanRenderWindow::SetupSwapchain(const Vk::PhysicalDevice& deviceInfo, Vk::Surface& surface, const Vector2ui& size)
bool VulkanSwapchain::SetupSurface(WindowHandle windowHandle)
{
bool success = false;
#if defined(NAZARA_PLATFORM_WINDOWS)
{
NazaraAssert(windowHandle.type == WindowBackend::Windows, "expected Windows window");
HWND winHandle = reinterpret_cast<HWND>(windowHandle.windows.window);
HINSTANCE instance = reinterpret_cast<HINSTANCE>(GetWindowLongPtrW(winHandle, GWLP_HINSTANCE));
success = m_surface.Create(instance, winHandle);
}
#elif defined(NAZARA_PLATFORM_LINUX)
{
switch (windowHandle.type)
{
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
case WindowBackend::Wayland:
{
wl_display* display = static_cast<wl_display*>(windowHandle.wayland.display);
wl_surface* surface = static_cast<wl_surface*>(windowHandle.wayland.surface);
success = m_surface.Create(display, surface);
break;
}
#endif
#ifdef VK_USE_PLATFORM_XLIB_KHR
case WindowBackend::X11:
{
Display* display = static_cast<Display*>(windowHandle.x11.display);
::Window window = static_cast<::Window>(windowHandle.x11.window);
success = m_surface.Create(display, window);
break;
}
#endif
default:
{
NazaraError("unhandled window type");
return false;
}
}
}
#elif defined(NAZARA_PLATFORM_MACOS)
{
NazaraAssert(windowHandle.type == WindowBackend::Cocoa, "expected cocoa window");
id layer = CreateAndAttachMetalLayer(windowHandle.cocoa.window);
success = m_surface.Create(layer);
}
#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;
}
bool VulkanSwapchain::SetupSwapchain(const Vk::PhysicalDevice& deviceInfo)
{
VkSurfaceCapabilitiesKHR surfaceCapabilities;
if (!surface.GetCapabilities(deviceInfo.physDevice, &surfaceCapabilities))
if (!m_surface.GetCapabilities(deviceInfo.physDevice, &surfaceCapabilities))
{
NazaraError("Failed to query surface capabilities");
return false;
}
Nz::UInt32 imageCount = surfaceCapabilities.minImageCount + 1;
UInt32 imageCount = surfaceCapabilities.minImageCount + 1;
if (surfaceCapabilities.maxImageCount > 0 && imageCount > surfaceCapabilities.maxImageCount)
imageCount = surfaceCapabilities.maxImageCount;
VkExtent2D extent;
if (surfaceCapabilities.currentExtent.width == 0xFFFFFFFF)
{
extent.width = Nz::Clamp<Nz::UInt32>(size.x, surfaceCapabilities.minImageExtent.width, surfaceCapabilities.maxImageExtent.width);
extent.height = Nz::Clamp<Nz::UInt32>(size.y, surfaceCapabilities.minImageExtent.height, surfaceCapabilities.maxImageExtent.height);
extent.width = std::clamp<UInt32>(m_swapchainSize.x, surfaceCapabilities.minImageExtent.width, surfaceCapabilities.maxImageExtent.width);
extent.height = std::clamp<UInt32>(m_swapchainSize.y, surfaceCapabilities.minImageExtent.height, surfaceCapabilities.maxImageExtent.height);
}
else
extent = surfaceCapabilities.currentExtent;
std::vector<VkPresentModeKHR> presentModes;
if (!surface.GetPresentModes(deviceInfo.physDevice, &presentModes))
if (!m_surface.GetPresentModes(deviceInfo.physDevice, &presentModes))
{
NazaraError("Failed to query supported present modes");
return false;
@ -564,13 +577,13 @@ namespace Nz
}
// Ensure all operations on the device have been finished before recreating the swapchain (this can be avoided but is more complicated)
m_device->WaitForIdle();
m_device.WaitForIdle();
VkSwapchainCreateInfoKHR swapchainInfo = {
VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
nullptr,
0,
surface,
m_surface,
imageCount,
m_surfaceFormat.format,
m_surfaceFormat.colorSpace,
@ -587,14 +600,13 @@ namespace Nz
};
Vk::Swapchain newSwapchain;
if (!newSwapchain.Create(*m_device, swapchainInfo))
if (!newSwapchain.Create(m_device, swapchainInfo))
{
NazaraError("failed to create swapchain: " + TranslateVulkanError(newSwapchain.GetLastErrorCode()));
return false;
}
m_swapchain = std::move(newSwapchain);
m_swapchainSize = size;
// Framebuffers
imageCount = m_swapchain.GetImageCount();

View File

@ -9,7 +9,7 @@
namespace Nz
{
Canvas::Canvas(entt::registry& registry, Nz::EventHandler& eventHandler, Nz::CursorControllerHandle cursorController, UInt32 renderMask, int initialRenderLayer) :
Canvas::Canvas(entt::registry& registry, Nz::WindowEventHandler& eventHandler, Nz::CursorControllerHandle cursorController, UInt32 renderMask, int initialRenderLayer) :
BaseWidget(std::make_shared<DefaultWidgetTheme>()),
m_cursorController(cursorController),
m_renderMask(renderMask),
@ -106,7 +106,7 @@ namespace Nz
}
}
void Canvas::OnEventMouseButtonPressed(const EventHandler* /*eventHandler*/, const WindowEvent::MouseButtonEvent& event)
void Canvas::OnEventMouseButtonPressed(const WindowEventHandler* /*eventHandler*/, const WindowEvent::MouseButtonEvent& event)
{
UpdateHoveredWidget(event.x, event.y);
@ -130,7 +130,7 @@ namespace Nz
m_mouseOwnerButtons[event.button] = true;
}
void Canvas::OnEventMouseButtonRelease(const EventHandler* /*eventHandler*/, const WindowEvent::MouseButtonEvent& event)
void Canvas::OnEventMouseButtonRelease(const WindowEventHandler* /*eventHandler*/, const WindowEvent::MouseButtonEvent& event)
{
if (std::size_t targetWidgetIndex = GetMouseEventTarget(); targetWidgetIndex != InvalidCanvasIndex)
{
@ -150,7 +150,7 @@ namespace Nz
UpdateHoveredWidget(event.x, event.y);
}
void Canvas::OnEventMouseEntered(const EventHandler* /*eventHandler*/)
void Canvas::OnEventMouseEntered(const WindowEventHandler* /*eventHandler*/)
{
// Keep previous mouse states but not new ones
if (m_mouseOwner != InvalidCanvasIndex)
@ -176,7 +176,7 @@ namespace Nz
m_mouseOwnerButtons.reset();
}
void Canvas::OnEventMouseLeft(const EventHandler* /*eventHandler*/)
void Canvas::OnEventMouseLeft(const WindowEventHandler* /*eventHandler*/)
{
if (std::size_t targetWidgetIndex = GetMouseEventTarget(); targetWidgetIndex != InvalidCanvasIndex)
{
@ -185,7 +185,7 @@ namespace Nz
}
}
void Canvas::OnEventMouseMoved(const EventHandler* /*eventHandler*/, const WindowEvent::MouseMoveEvent& event)
void Canvas::OnEventMouseMoved(const WindowEventHandler* /*eventHandler*/, const WindowEvent::MouseMoveEvent& event)
{
// Don't update hovered widget while the user doesn't release its mouse
UpdateHoveredWidget(event.x, event.y);
@ -201,7 +201,7 @@ namespace Nz
}
}
void Canvas::OnEventMouseWheelMoved(const EventHandler* /*eventHandler*/, const WindowEvent::MouseWheelEvent& event)
void Canvas::OnEventMouseWheelMoved(const WindowEventHandler* /*eventHandler*/, const WindowEvent::MouseWheelEvent& event)
{
if (std::size_t targetWidgetIndex = GetMouseEventTarget(); targetWidgetIndex != InvalidCanvasIndex)
{
@ -215,7 +215,7 @@ namespace Nz
}
}
void Canvas::OnEventKeyPressed(const EventHandler* eventHandler, const WindowEvent::KeyEvent& event)
void Canvas::OnEventKeyPressed(const WindowEventHandler* eventHandler, const WindowEvent::KeyEvent& event)
{
if (m_keyboardOwner != InvalidCanvasIndex)
{
@ -273,7 +273,7 @@ namespace Nz
OnUnhandledKeyPressed(eventHandler, event);
}
void Canvas::OnEventKeyReleased(const EventHandler* eventHandler, const WindowEvent::KeyEvent& event)
void Canvas::OnEventKeyReleased(const WindowEventHandler* eventHandler, const WindowEvent::KeyEvent& event)
{
if (m_keyboardOwner != InvalidCanvasIndex)
m_widgetEntries[m_keyboardOwner].widget->OnKeyReleased(event);
@ -281,13 +281,13 @@ namespace Nz
OnUnhandledKeyReleased(eventHandler, event);
}
void Canvas::OnEventTextEntered(const EventHandler* /*eventHandler*/, const WindowEvent::TextEvent& event)
void Canvas::OnEventTextEntered(const WindowEventHandler* /*eventHandler*/, const WindowEvent::TextEvent& event)
{
if (m_keyboardOwner != InvalidCanvasIndex)
m_widgetEntries[m_keyboardOwner].widget->OnTextEntered(event.character, event.repeated);
}
void Canvas::OnEventTextEdited(const EventHandler* /*eventHandler*/, const WindowEvent::EditEvent& event)
void Canvas::OnEventTextEdited(const WindowEventHandler* /*eventHandler*/, const WindowEvent::EditEvent& event)
{
if (m_keyboardOwner != InvalidCanvasIndex)
m_widgetEntries[m_keyboardOwner].widget->OnTextEdited(event.text, event.length);

View File

@ -2,7 +2,6 @@
#include <Nazara/Math.hpp>
#include <Nazara/Platform.hpp>
#include <Nazara/Renderer.hpp>
#include <Nazara/Renderer/DebugDrawer.hpp>
#include <NZSL/FilesystemModuleResolver.hpp>
#include <NZSL/LangWriter.hpp>
#include <NZSL/Parser.hpp>
@ -12,6 +11,7 @@
#include <chrono>
#include <iostream>
#include <thread>
#include <Windows.h>
NAZARA_REQUEST_DEDICATED_GPU()
@ -101,10 +101,11 @@ int main()
std::shared_ptr<Nz::RenderDevice> device = Nz::Renderer::Instance()->InstanciateRenderDevice(0);
Nz::RenderWindow window;
Nz::Window window;
Nz::WindowSwapchain windowSwapchain(device, window);
std::string windowTitle = "Render Test";
if (!window.Create(device, Nz::VideoMode(800, 600, 32), windowTitle))
if (!window.Create(Nz::VideoMode(1280, 720), windowTitle))
{
std::cout << "Failed to create Window" << std::endl;
return __LINE__;
@ -153,15 +154,13 @@ int main()
std::cout << "Vertex count: " << meshVB->GetVertexCount() << std::endl;
// Create renderbuffers (GPU buffers)
const std::shared_ptr<Nz::RenderDevice>& renderDevice = window.GetRenderDevice();
assert(meshIB->GetBuffer()->GetStorage() == Nz::DataStorage::Software);
assert(meshVB->GetBuffer()->GetStorage() == Nz::DataStorage::Software);
const Nz::SoftwareBuffer* indexBufferContent = static_cast<const Nz::SoftwareBuffer*>(meshIB->GetBuffer().get());
const Nz::SoftwareBuffer* vertexBufferContent = static_cast<const Nz::SoftwareBuffer*>(meshVB->GetBuffer().get());
std::shared_ptr<Nz::RenderBuffer> renderBufferIB = renderDevice->InstantiateBuffer(Nz::BufferType::Index, indexBufferContent->GetSize(), Nz::BufferUsage::DeviceLocal, indexBufferContent->GetData());
std::shared_ptr<Nz::RenderBuffer> renderBufferVB = renderDevice->InstantiateBuffer(Nz::BufferType::Vertex, vertexBufferContent->GetSize(), Nz::BufferUsage::DeviceLocal, vertexBufferContent->GetData());
std::shared_ptr<Nz::RenderBuffer> renderBufferIB = device->InstantiateBuffer(Nz::BufferType::Index, indexBufferContent->GetSize(), Nz::BufferUsage::DeviceLocal, indexBufferContent->GetData());
std::shared_ptr<Nz::RenderBuffer> renderBufferVB = device->InstantiateBuffer(Nz::BufferType::Vertex, vertexBufferContent->GetSize(), Nz::BufferUsage::DeviceLocal, vertexBufferContent->GetData());
// Texture
Nz::TextureParams texParams;
@ -244,15 +243,13 @@ int main()
std::shared_ptr<Nz::RenderPipeline> pipeline = device->InstantiateRenderPipeline(pipelineInfo);
std::shared_ptr<Nz::CommandPool> commandPool = renderDevice->InstantiateCommandPool(Nz::QueueType::Graphics);
std::shared_ptr<Nz::CommandPool> commandPool = device->InstantiateCommandPool(Nz::QueueType::Graphics);
Nz::Vector3f viewerPos = Nz::Vector3f::Zero();
Nz::EulerAnglesf camAngles(0.f, 0.f, 0.f);
Nz::Quaternionf camQuat(camAngles);
window.EnableEventPolling(true);
Nz::MillisecondClock updateClock;
Nz::MillisecondClock secondClock;
unsigned int fps = 0;
@ -260,49 +257,42 @@ int main()
Nz::Mouse::SetRelativeMouseMode(true);
Nz::DebugDrawer debugDrawer(*renderDevice);
Nz::DebugDrawer debugDrawer(*device);
Nz::WindowEventHandler& windowEvents = window.GetEventHandler();
windowEvents.OnKeyPressed.Connect([&](const Nz::WindowEventHandler*, const Nz::WindowEvent::KeyEvent& key)
{
if (key.virtualKey == Nz::Keyboard::VKey::F1)
window.Create(Nz::VideoMode(1920, 1080), windowTitle);
});
windowEvents.OnMouseMoved.Connect([&](const Nz::WindowEventHandler*, const Nz::WindowEvent::MouseMoveEvent& mouseMove)
{
// Gestion de la caméra free-fly (Rotation)
float sensitivity = 0.3f; // Sensibilité de la souris
// On modifie l'angle de la caméra grâce au déplacement relatif sur X de la souris
camAngles.yaw = camAngles.yaw - mouseMove.deltaX * sensitivity;
camAngles.yaw.Normalize();
// Idem, mais pour éviter les problèmes de calcul de la matrice de vue, on restreint les angles
camAngles.pitch = Nz::Clamp(camAngles.pitch - mouseMove.deltaY * sensitivity, -89.f, 89.f);
camQuat = camAngles;
uboUpdate = true;
});
windowEvents.OnResized.Connect([&](const Nz::WindowEventHandler*, const Nz::WindowEvent::SizeEvent& sizeEvent)
{
windowSize = { sizeEvent.width, sizeEvent.height };
ubo.projectionMatrix = Nz::Matrix4f::Perspective(Nz::DegreeAnglef(70.f), float(windowSize.x) / windowSize.y, 0.1f, 1000.f);
uboUpdate = true;
});
while (window.IsOpen())
{
Nz::WindowEvent event;
while (window.PollEvent(&event))
{
switch (event.type)
{
case Nz::WindowEventType::Quit:
window.Close();
break;
case Nz::WindowEventType::MouseMoved: // La souris a bougé
{
// Gestion de la caméra free-fly (Rotation)
float sensitivity = 0.3f; // Sensibilité de la souris
// On modifie l'angle de la caméra grâce au déplacement relatif sur X de la souris
camAngles.yaw = camAngles.yaw - event.mouseMove.deltaX * sensitivity;
camAngles.yaw.Normalize();
// Idem, mais pour éviter les problèmes de calcul de la matrice de vue, on restreint les angles
camAngles.pitch = Nz::Clamp(camAngles.pitch - event.mouseMove.deltaY*sensitivity, -89.f, 89.f);
camQuat = camAngles;
uboUpdate = true;
break;
}
case Nz::WindowEventType::Resized:
{
windowSize = window.GetSize();
ubo.projectionMatrix = Nz::Matrix4f::Perspective(Nz::DegreeAnglef(70.f), float(windowSize.x) / windowSize.y, 0.1f, 1000.f);
uboUpdate = true;
break;
}
default:
break;
}
}
Nz::Window::ProcessEvents();
if (std::optional<Nz::Time> deltaTime = updateClock.RestartIfOver(Nz::Time::TickDuration(60)))
{
@ -334,7 +324,7 @@ int main()
uboUpdate = true;
}
Nz::RenderFrame frame = window.AcquireFrame();
Nz::RenderFrame frame = windowSwapchain.AcquireFrame();
if (!frame)
{
std::this_thread::sleep_for(std::chrono::milliseconds(1));
@ -373,10 +363,11 @@ int main()
debugDrawer.Prepare(frame);
const Nz::RenderTarget* windowRT = window.GetRenderTarget();
const Nz::RenderTarget& windowRT = windowSwapchain.GetSwapchain();
frame.Execute([&](Nz::CommandBufferBuilder& builder)
{
Nz::Recti renderRect(0, 0, window.GetSize().x, window.GetSize().y);
windowSize = window.GetSize();
Nz::Recti renderRect(0, 0, windowSize.x, windowSize.y);
Nz::CommandBufferBuilder::ClearValues clearValues[2];
clearValues[0].color = Nz::Color::Black();
@ -385,7 +376,7 @@ int main()
builder.BeginDebugRegion("Main window rendering", Nz::Color::Green());
{
builder.BeginRenderPass(windowRT->GetFramebuffer(frame.GetFramebufferIndex()), windowRT->GetRenderPass(), renderRect, { clearValues[0], clearValues[1] });
builder.BeginRenderPass(windowRT.GetFramebuffer(frame.GetFramebufferIndex()), windowRT.GetRenderPass(), renderRect, { clearValues[0], clearValues[1] });
{
builder.BindIndexBuffer(*renderBufferIB, Nz::IndexType::U16);
builder.BindRenderPipeline(*pipeline);