Replace RenderWindow with swapchains
This commit is contained in:
committed by
Jérôme Leclercq
parent
8db1c04568
commit
18851c9185
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
@@ -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>
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user