diff --git a/include/Nazara/OpenGLRenderer/OpenGLCommandBuffer.inl b/include/Nazara/OpenGLRenderer/OpenGLCommandBuffer.inl index 334b6af1f..89135f196 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLCommandBuffer.inl +++ b/include/Nazara/OpenGLRenderer/OpenGLCommandBuffer.inl @@ -119,12 +119,12 @@ namespace Nz m_commands.emplace_back(EndDebugRegionData{}); } - inline std::size_t Nz::OpenGLCommandBuffer::GetBindingIndex() const + inline std::size_t OpenGLCommandBuffer::GetBindingIndex() const { return m_bindingIndex; } - inline std::size_t Nz::OpenGLCommandBuffer::GetPoolIndex() const + inline std::size_t OpenGLCommandBuffer::GetPoolIndex() const { return m_poolIndex; } diff --git a/include/Nazara/OpenGLRenderer/OpenGLRenderer.hpp b/include/Nazara/OpenGLRenderer/OpenGLRenderer.hpp index 4ca7ee683..cd71983f5 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLRenderer.hpp +++ b/include/Nazara/OpenGLRenderer/OpenGLRenderer.hpp @@ -25,7 +25,7 @@ namespace Nz std::unique_ptr CreateRenderSurfaceImpl() override; std::unique_ptr CreateRenderWindowImpl(RenderWindow& owner) override; - std::shared_ptr InstanciateRenderDevice(std::size_t deviceIndex) override; + std::shared_ptr InstanciateRenderDevice(std::size_t deviceIndex, const RenderDeviceFeatures& enabledFeatures) override; RenderAPI QueryAPI() const override; std::string QueryAPIString() const override; diff --git a/include/Nazara/Renderer/RenderDeviceInfo.hpp b/include/Nazara/Renderer/RenderDeviceInfo.hpp index d11f9e7c6..b151ce9a5 100644 --- a/include/Nazara/Renderer/RenderDeviceInfo.hpp +++ b/include/Nazara/Renderer/RenderDeviceInfo.hpp @@ -13,6 +13,11 @@ namespace Nz { + struct RenderDeviceFeatures + { + bool anisotropicFiltering = false; + }; + struct RenderDeviceLimits { UInt64 minUniformBufferOffsetAlignment; @@ -20,6 +25,7 @@ namespace Nz struct RenderDeviceInfo { + RenderDeviceFeatures features; RenderDeviceLimits limits; RenderDeviceType type; std::string name; diff --git a/include/Nazara/Renderer/Renderer.hpp b/include/Nazara/Renderer/Renderer.hpp index 2a97441a3..6e222bed8 100644 --- a/include/Nazara/Renderer/Renderer.hpp +++ b/include/Nazara/Renderer/Renderer.hpp @@ -34,7 +34,7 @@ namespace Nz inline RendererImpl* GetRendererImpl(); - std::shared_ptr InstanciateRenderDevice(std::size_t deviceIndex); + std::shared_ptr InstanciateRenderDevice(std::size_t deviceIndex, const RenderDeviceFeatures& enabledFeatures = {}); RenderAPI QueryAPI() const; std::string QueryAPIString() const; diff --git a/include/Nazara/Renderer/RendererImpl.hpp b/include/Nazara/Renderer/RendererImpl.hpp index 54518ece8..117c91e35 100644 --- a/include/Nazara/Renderer/RendererImpl.hpp +++ b/include/Nazara/Renderer/RendererImpl.hpp @@ -37,7 +37,7 @@ namespace Nz virtual std::unique_ptr CreateRenderSurfaceImpl() = 0; virtual std::unique_ptr CreateRenderWindowImpl(RenderWindow& owner) = 0; - virtual std::shared_ptr InstanciateRenderDevice(std::size_t deviceIndex) = 0; + virtual std::shared_ptr InstanciateRenderDevice(std::size_t deviceIndex, const RenderDeviceFeatures& enabledFeatures) = 0; virtual RenderAPI QueryAPI() const = 0; virtual std::string QueryAPIString() const = 0; diff --git a/include/Nazara/VulkanRenderer/Vulkan.hpp b/include/Nazara/VulkanRenderer/Vulkan.hpp index 44368576e..2b6795cea 100644 --- a/include/Nazara/VulkanRenderer/Vulkan.hpp +++ b/include/Nazara/VulkanRenderer/Vulkan.hpp @@ -38,9 +38,9 @@ namespace Nz static RenderDeviceInfo BuildRenderDeviceInfo(const Vk::PhysicalDevice& physDevice); - static std::shared_ptr CreateDevice(const Vk::PhysicalDevice& deviceInfo); - static std::shared_ptr CreateDevice(const Vk::PhysicalDevice& deviceInfo, const Vk::Surface& surface, UInt32* graphicsFamilyIndex, UInt32* presentableFamilyIndex, UInt32* transferFamilyIndex); - static std::shared_ptr CreateDevice(const Vk::PhysicalDevice& deviceInfo, const QueueFamily* queueFamilies, std::size_t queueFamilyCount); + static std::shared_ptr CreateDevice(const Vk::PhysicalDevice& deviceInfo, const RenderDeviceFeatures& enabledFeatures); + static std::shared_ptr CreateDevice(const Vk::PhysicalDevice& deviceInfo, const RenderDeviceFeatures& enabledFeatures, const Vk::Surface& surface, UInt32* graphicsFamilyIndex, UInt32* presentableFamilyIndex, UInt32* transferFamilyIndex); + static std::shared_ptr CreateDevice(const Vk::PhysicalDevice& deviceInfo, const RenderDeviceFeatures& enabledFeatures, const QueueFamily* queueFamilies, std::size_t queueFamilyCount); static Vk::Instance& GetInstance(); @@ -51,13 +51,9 @@ namespace Nz static bool IsInitialized(); - static std::shared_ptr SelectDevice(const Vk::PhysicalDevice& deviceInfo); - static std::shared_ptr SelectDevice(const Vk::PhysicalDevice& deviceInfo, const Vk::Surface& surface, UInt32* graphicsFamilyIndex, UInt32* presentableFamilyIndex, UInt32* transferFamilyIndex); - static void Uninitialize(); private: - static std::vector> s_devices; static std::vector s_physDevices; static Vk::Instance s_instance; static ParameterList s_initializationParameters; diff --git a/include/Nazara/VulkanRenderer/VulkanRenderer.hpp b/include/Nazara/VulkanRenderer/VulkanRenderer.hpp index bd772716b..51cda0914 100644 --- a/include/Nazara/VulkanRenderer/VulkanRenderer.hpp +++ b/include/Nazara/VulkanRenderer/VulkanRenderer.hpp @@ -28,7 +28,7 @@ namespace Nz std::unique_ptr CreateRenderSurfaceImpl() override; std::unique_ptr CreateRenderWindowImpl(RenderWindow& owner) override; - std::shared_ptr InstanciateRenderDevice(std::size_t deviceIndex) override; + std::shared_ptr InstanciateRenderDevice(std::size_t deviceIndex, const RenderDeviceFeatures& enabledFeatures) override; RenderAPI QueryAPI() const override; std::string QueryAPIString() const override; diff --git a/src/Nazara/Graphics/Graphics.cpp b/src/Nazara/Graphics/Graphics.cpp index 433df28ef..4d3050952 100644 --- a/src/Nazara/Graphics/Graphics.cpp +++ b/src/Nazara/Graphics/Graphics.cpp @@ -40,7 +40,10 @@ namespace Nz } } - m_renderDevice = renderer->InstanciateRenderDevice(bestRenderDeviceIndex); + RenderDeviceFeatures enabledFeatures; + enabledFeatures.anisotropicFiltering = renderDeviceInfo[bestRenderDeviceIndex].features.anisotropicFiltering; + + m_renderDevice = renderer->InstanciateRenderDevice(bestRenderDeviceIndex, enabledFeatures); if (!m_renderDevice) throw std::runtime_error("failed to instantiate render device"); diff --git a/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp b/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp index 61e072e38..ec26ddf27 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp @@ -49,6 +49,14 @@ namespace Nz m_deviceInfo.type = RenderDeviceType::Unknown; + const GL::ContextParams& params = m_referenceContext->GetParams(); + unsigned int glVersion = params.glMajorVersion * 100 + params.glMinorVersion; + + // Features + if ((params.type == GL::ContextType::OpenGL && glVersion >= 460) || m_referenceContext->IsExtensionSupported(GL::Extension::TextureFilterAnisotropic)) + m_deviceInfo.features.anisotropicFiltering = true; + + // Limits GLint minUboOffsetAlignment; m_referenceContext->glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &minUboOffsetAlignment); diff --git a/src/Nazara/OpenGLRenderer/OpenGLRenderer.cpp b/src/Nazara/OpenGLRenderer/OpenGLRenderer.cpp index bced38769..e1417f521 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLRenderer.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLRenderer.cpp @@ -47,7 +47,7 @@ namespace Nz return std::make_unique(owner); } - std::shared_ptr OpenGLRenderer::InstanciateRenderDevice(std::size_t deviceIndex) + std::shared_ptr OpenGLRenderer::InstanciateRenderDevice(std::size_t deviceIndex, const RenderDeviceFeatures& /*enabledFeatures*/) { assert(deviceIndex == 0); return m_device; diff --git a/src/Nazara/Renderer/Renderer.cpp b/src/Nazara/Renderer/Renderer.cpp index beb12588c..91a66d722 100644 --- a/src/Nazara/Renderer/Renderer.cpp +++ b/src/Nazara/Renderer/Renderer.cpp @@ -47,9 +47,9 @@ namespace Nz m_rendererImpl.reset(); } - std::shared_ptr Renderer::InstanciateRenderDevice(std::size_t deviceIndex) + std::shared_ptr Renderer::InstanciateRenderDevice(std::size_t deviceIndex, const RenderDeviceFeatures& enabledFeatures) { - return m_rendererImpl->InstanciateRenderDevice(deviceIndex); + return m_rendererImpl->InstanciateRenderDevice(deviceIndex, enabledFeatures); } RenderAPI Renderer::QueryAPI() const diff --git a/src/Nazara/VulkanRenderer/VkRenderWindow.cpp b/src/Nazara/VulkanRenderer/VkRenderWindow.cpp index b4b609958..9606bd7bb 100644 --- a/src/Nazara/VulkanRenderer/VkRenderWindow.cpp +++ b/src/Nazara/VulkanRenderer/VkRenderWindow.cpp @@ -105,22 +105,74 @@ namespace Nz bool VkRenderWindow::Create(RendererImpl* /*renderer*/, RenderSurface* surface, const RenderWindowParameters& parameters) { - VulkanDevice& referenceDevice = static_cast(*m_owner.GetRenderDevice()); + std::shared_ptr device = std::static_pointer_cast(m_owner.GetRenderDevice()); - const auto& physDeviceInfo = referenceDevice.GetPhysicalDeviceInfo(); + const auto& physDeviceInfo = device->GetPhysicalDeviceInfo(); Vk::Surface& vulkanSurface = static_cast(surface)->GetSurface(); - UInt32 graphicsFamilyQueueIndex; - UInt32 presentableFamilyQueueIndex; - UInt32 transferFamilyQueueIndex; - m_device = Vulkan::SelectDevice(physDeviceInfo, vulkanSurface, &graphicsFamilyQueueIndex, &presentableFamilyQueueIndex, &transferFamilyQueueIndex); - if (!m_device) + const std::vector& queueFamilyInfo = device->GetEnabledQueues(); + UInt32 graphicsFamilyQueueIndex = UINT32_MAX; + UInt32 presentableFamilyQueueIndex = UINT32_MAX; + + for (const Vk::Device::QueueFamilyInfo& queueInfo : queueFamilyInfo) { - NazaraError("Failed to get compatible Vulkan device"); + 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); diff --git a/src/Nazara/VulkanRenderer/Vulkan.cpp b/src/Nazara/VulkanRenderer/Vulkan.cpp index cc4150d0c..fdee3ba0e 100644 --- a/src/Nazara/VulkanRenderer/Vulkan.cpp +++ b/src/Nazara/VulkanRenderer/Vulkan.cpp @@ -53,6 +53,8 @@ namespace Nz RenderDeviceInfo deviceInfo; deviceInfo.name = physDevice.properties.deviceName; + deviceInfo.features.anisotropicFiltering = physDevice.features.samplerAnisotropy; + deviceInfo.limits.minUniformBufferOffsetAlignment = physDevice.properties.limits.minUniformBufferOffsetAlignment; switch (physDevice.properties.deviceType) @@ -370,7 +372,7 @@ namespace Nz return s_instance.IsValid(); } - std::shared_ptr Vulkan::CreateDevice(const Vk::PhysicalDevice& deviceInfo) + std::shared_ptr Vulkan::CreateDevice(const Vk::PhysicalDevice& deviceInfo, const RenderDeviceFeatures& enabledFeatures) { Nz::ErrorFlags errFlags(ErrorMode::ThrowException, true); @@ -404,10 +406,10 @@ namespace Nz } }; - return CreateDevice(deviceInfo, queuesFamilies.data(), queuesFamilies.size()); + return CreateDevice(deviceInfo, enabledFeatures, queuesFamilies.data(), queuesFamilies.size()); } - std::shared_ptr Vulkan::CreateDevice(const Vk::PhysicalDevice& deviceInfo, const Vk::Surface& surface, UInt32* graphicsFamilyIndex, UInt32* presentableFamilyIndex, UInt32* transferFamilyIndex) + std::shared_ptr Vulkan::CreateDevice(const Vk::PhysicalDevice& deviceInfo, const RenderDeviceFeatures& enabledFeatures, const Vk::Surface& surface, UInt32* graphicsFamilyIndex, UInt32* presentableFamilyIndex, UInt32* transferFamilyIndex) { Nz::ErrorFlags errFlags(ErrorMode::ThrowException, true); @@ -476,10 +478,10 @@ namespace Nz *presentableFamilyIndex = presentQueueNodeIndex; *transferFamilyIndex = transferQueueNodeFamily; - return CreateDevice(deviceInfo, queuesFamilies.data(), queuesFamilies.size()); + return CreateDevice(deviceInfo, enabledFeatures, queuesFamilies.data(), queuesFamilies.size()); } - std::shared_ptr Vulkan::CreateDevice(const Vk::PhysicalDevice& deviceInfo, const QueueFamily* queueFamilies, std::size_t queueFamilyCount) + std::shared_ptr Vulkan::CreateDevice(const Vk::PhysicalDevice& deviceInfo, const RenderDeviceFeatures& enabledFeatures, const QueueFamily* queueFamilies, std::size_t queueFamilyCount) { std::vector queueCreateInfos; queueCreateInfos.reserve(queueFamilyCount); @@ -571,6 +573,10 @@ namespace Nz } } + VkPhysicalDeviceFeatures deviceFeatures = {}; + if (enabledFeatures.anisotropicFiltering) + deviceFeatures.samplerAnisotropy = VK_TRUE; + VkDeviceCreateInfo createInfo = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, nullptr, @@ -581,7 +587,7 @@ namespace Nz enabledLayers.data(), UInt32(enabledExtensions.size()), enabledExtensions.data(), - nullptr + &deviceFeatures }; std::shared_ptr device = std::make_shared(s_instance, BuildRenderDeviceInfo(deviceInfo)); @@ -591,104 +597,17 @@ namespace Nz return {}; } - s_devices.emplace_back(device); - return device; } - std::shared_ptr Vulkan::SelectDevice(const Vk::PhysicalDevice& deviceInfo) - { - for (auto it = s_devices.begin(); it != s_devices.end();) - { - const auto& devicePtr = *it; - if (devicePtr->GetPhysicalDevice() == deviceInfo.physDevice) - return devicePtr; - } - - return CreateDevice(deviceInfo); - } - - std::shared_ptr Vulkan::SelectDevice(const Vk::PhysicalDevice& deviceInfo, const Vk::Surface& surface, UInt32* graphicsFamilyIndex, UInt32* presentableFamilyIndex, UInt32* transferFamilyIndex) - { - // First, try to find a device compatible with that surface - for (auto it = s_devices.begin(); it != s_devices.end();) - { - const auto& devicePtr = *it; - if (devicePtr->GetPhysicalDevice() == deviceInfo.physDevice) - { - const std::vector& queueFamilyInfo = devicePtr->GetEnabledQueues(); - UInt32 graphicsQueueFamilyIndex = UINT32_MAX; - UInt32 presentableQueueFamilyIndex = UINT32_MAX; - for (const Vk::Device::QueueFamilyInfo& queueInfo : queueFamilyInfo) - { - bool supported = false; - if (surface.GetSupportPresentation(deviceInfo.physDevice, queueInfo.familyIndex, &supported) && supported) - { - if (presentableQueueFamilyIndex == UINT32_MAX || queueInfo.flags & VK_QUEUE_GRAPHICS_BIT) - { - presentableQueueFamilyIndex = queueInfo.familyIndex; - if (queueInfo.flags & VK_QUEUE_GRAPHICS_BIT) - { - *graphicsFamilyIndex = queueInfo.familyIndex; - break; - } - } - } - } - - if (graphicsQueueFamilyIndex == UINT32_MAX) - { - for (const Vk::Device::QueueFamilyInfo& queueInfo : queueFamilyInfo) - { - if (queueInfo.flags & VK_QUEUE_GRAPHICS_BIT) - { - *graphicsFamilyIndex = queueInfo.familyIndex; - break; - } - } - } - - if (presentableQueueFamilyIndex != UINT32_MAX) - { - *presentableFamilyIndex = presentableQueueFamilyIndex; - - UInt32 transferQueueNodeFamily = 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)) - { - transferQueueNodeFamily = queueInfo.familyIndex; - if (transferQueueNodeFamily != *graphicsFamilyIndex) - break; - } - } - assert(transferQueueNodeFamily != UINT32_MAX); - - *transferFamilyIndex = transferQueueNodeFamily; - - return devicePtr; - } - } - - ++it; - } - - // No device had support for that surface, create one - return CreateDevice(deviceInfo, surface, graphicsFamilyIndex, presentableFamilyIndex, transferFamilyIndex); - } - void Vulkan::Uninitialize() { // Uninitialize module here - s_devices.clear(); s_instance.Destroy(); Vk::Loader::Uninitialize(); } - std::vector> Vulkan::s_devices; std::vector Vulkan::s_physDevices; Vk::Instance Vulkan::s_instance; ParameterList Vulkan::s_initializationParameters; diff --git a/src/Nazara/VulkanRenderer/VulkanRenderer.cpp b/src/Nazara/VulkanRenderer/VulkanRenderer.cpp index ab9db0069..ab3d420ad 100644 --- a/src/Nazara/VulkanRenderer/VulkanRenderer.cpp +++ b/src/Nazara/VulkanRenderer/VulkanRenderer.cpp @@ -30,12 +30,12 @@ namespace Nz return std::make_unique(owner); } - std::shared_ptr VulkanRenderer::InstanciateRenderDevice(std::size_t deviceIndex) + std::shared_ptr VulkanRenderer::InstanciateRenderDevice(std::size_t deviceIndex, const RenderDeviceFeatures& enabledFeatures) { const auto& physDevices = Vulkan::GetPhysicalDevices(); assert(deviceIndex < physDevices.size()); - return Vulkan::SelectDevice(physDevices[deviceIndex]); + return Vulkan::CreateDevice(physDevices[deviceIndex], enabledFeatures); } bool VulkanRenderer::Prepare(const ParameterList& parameters)