diff --git a/include/Nazara/OpenGLRenderer/OpenGLDevice.hpp b/include/Nazara/OpenGLRenderer/OpenGLDevice.hpp index 01b6c578a..a3de66041 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLDevice.hpp +++ b/include/Nazara/OpenGLRenderer/OpenGLDevice.hpp @@ -32,6 +32,7 @@ namespace Nz std::unique_ptr CreateContext(const GL::ContextParams& params, WindowHandle handle) const; const RenderDeviceInfo& GetDeviceInfo() const override; + const RenderDeviceFeatures& GetEnabledFeatures() const override; inline const GL::Context& GetReferenceContext() const; std::shared_ptr InstantiateBuffer(BufferType type) override; diff --git a/include/Nazara/OpenGLRenderer/OpenGLTextureSampler.hpp b/include/Nazara/OpenGLRenderer/OpenGLTextureSampler.hpp index 15799f642..4c64d791d 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLTextureSampler.hpp +++ b/include/Nazara/OpenGLRenderer/OpenGLTextureSampler.hpp @@ -17,7 +17,7 @@ namespace Nz class NAZARA_OPENGLRENDERER_API OpenGLTextureSampler : public TextureSampler { public: - OpenGLTextureSampler(OpenGLDevice& device, const TextureSamplerInfo& samplerInfo); + OpenGLTextureSampler(OpenGLDevice& device, TextureSamplerInfo samplerInfo); OpenGLTextureSampler(const OpenGLTextureSampler&) = delete; OpenGLTextureSampler(OpenGLTextureSampler&&) = delete; ~OpenGLTextureSampler() = default; diff --git a/include/Nazara/Renderer/RenderDevice.hpp b/include/Nazara/Renderer/RenderDevice.hpp index e25ba141c..d74131c4b 100644 --- a/include/Nazara/Renderer/RenderDevice.hpp +++ b/include/Nazara/Renderer/RenderDevice.hpp @@ -36,6 +36,7 @@ namespace Nz virtual ~RenderDevice(); virtual const RenderDeviceInfo& GetDeviceInfo() const = 0; + virtual const RenderDeviceFeatures& GetEnabledFeatures() const = 0; virtual std::shared_ptr InstantiateBuffer(BufferType type) = 0; virtual std::shared_ptr InstantiateCommandPool(QueueType queueType) = 0; @@ -50,6 +51,8 @@ namespace Nz virtual std::shared_ptr InstantiateTextureSampler(const TextureSamplerInfo& params) = 0; virtual bool IsTextureFormatSupported(PixelFormat format, TextureUsage usage) const = 0; + + static void ValidateFeatures(const RenderDeviceFeatures& supportedFeatures, RenderDeviceFeatures& enabledFeatures); }; } diff --git a/include/Nazara/Renderer/TextureSampler.hpp b/include/Nazara/Renderer/TextureSampler.hpp index 62195d6c3..06e7d0208 100644 --- a/include/Nazara/Renderer/TextureSampler.hpp +++ b/include/Nazara/Renderer/TextureSampler.hpp @@ -28,6 +28,8 @@ namespace Nz inline bool operator!=(const TextureSamplerInfo& samplerInfo) const; }; + class RenderDevice; + class NAZARA_RENDERER_API TextureSampler { public: @@ -38,6 +40,9 @@ namespace Nz TextureSampler& operator=(const TextureSampler&) = delete; TextureSampler& operator=(TextureSampler&&) = delete; + + protected: + static void ValidateSamplerInfo(const RenderDevice& device, TextureSamplerInfo& samplerInfo); }; } diff --git a/include/Nazara/VulkanRenderer/VulkanDevice.hpp b/include/Nazara/VulkanRenderer/VulkanDevice.hpp index 235f2f381..cd2333490 100644 --- a/include/Nazara/VulkanRenderer/VulkanDevice.hpp +++ b/include/Nazara/VulkanRenderer/VulkanDevice.hpp @@ -18,12 +18,13 @@ namespace Nz class NAZARA_VULKANRENDERER_API VulkanDevice : public RenderDevice, public Vk::Device { public: - inline VulkanDevice(Vk::Instance& instance, RenderDeviceInfo renderDeviceInfo); + inline VulkanDevice(Vk::Instance& instance, const RenderDeviceFeatures& enabledFeatures, RenderDeviceInfo renderDeviceInfo); VulkanDevice(const VulkanDevice&) = delete; VulkanDevice(VulkanDevice&&) = delete; ///TODO? ~VulkanDevice(); const RenderDeviceInfo& GetDeviceInfo() const override; + const RenderDeviceFeatures& GetEnabledFeatures() const override; std::shared_ptr InstantiateBuffer(BufferType type) override; std::shared_ptr InstantiateCommandPool(QueueType queueType) override; @@ -42,6 +43,7 @@ namespace Nz VulkanDevice& operator=(VulkanDevice&&) = delete; ///TODO? private: + RenderDeviceFeatures m_enabledFeatures; RenderDeviceInfo m_renderDeviceInfo; }; } diff --git a/include/Nazara/VulkanRenderer/VulkanDevice.inl b/include/Nazara/VulkanRenderer/VulkanDevice.inl index 6c5f8a58b..3a057dc2b 100644 --- a/include/Nazara/VulkanRenderer/VulkanDevice.inl +++ b/include/Nazara/VulkanRenderer/VulkanDevice.inl @@ -7,8 +7,9 @@ namespace Nz { - inline VulkanDevice::VulkanDevice(Vk::Instance& instance, RenderDeviceInfo renderDeviceInfo) : + inline VulkanDevice::VulkanDevice(Vk::Instance& instance, const RenderDeviceFeatures& enabledFeatures, RenderDeviceInfo renderDeviceInfo) : Device(instance), + m_enabledFeatures(enabledFeatures), m_renderDeviceInfo(std::move(renderDeviceInfo)) { } diff --git a/include/Nazara/VulkanRenderer/VulkanRenderPipeline.hpp b/include/Nazara/VulkanRenderer/VulkanRenderPipeline.hpp index aa0d44a98..f73a5bf03 100644 --- a/include/Nazara/VulkanRenderer/VulkanRenderPipeline.hpp +++ b/include/Nazara/VulkanRenderer/VulkanRenderPipeline.hpp @@ -19,12 +19,14 @@ namespace Nz { + class VulkanDevice; + class NAZARA_VULKANRENDERER_API VulkanRenderPipeline : public RenderPipeline { public: struct CreateInfo; - VulkanRenderPipeline(Vk::Device& device, RenderPipelineInfo pipelineInfo); + VulkanRenderPipeline(VulkanDevice& device, RenderPipelineInfo pipelineInfo); ~VulkanRenderPipeline() = default; VkPipeline Get(const VulkanRenderPass& renderPass, std::size_t subpassIndex) const; diff --git a/include/Nazara/VulkanRenderer/VulkanTextureSampler.hpp b/include/Nazara/VulkanRenderer/VulkanTextureSampler.hpp index a5f5a8052..f07670968 100644 --- a/include/Nazara/VulkanRenderer/VulkanTextureSampler.hpp +++ b/include/Nazara/VulkanRenderer/VulkanTextureSampler.hpp @@ -13,10 +13,12 @@ namespace Nz { + class VulkanDevice; + class NAZARA_VULKANRENDERER_API VulkanTextureSampler : public TextureSampler { public: - VulkanTextureSampler(Vk::Device& device, TextureSamplerInfo samplerInfo); + VulkanTextureSampler(VulkanDevice& device, TextureSamplerInfo samplerInfo); VulkanTextureSampler(const VulkanTextureSampler&) = delete; VulkanTextureSampler(VulkanTextureSampler&&) = delete; ~VulkanTextureSampler() = default; diff --git a/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp b/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp index e65d5c9cd..0a7d3b480 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp @@ -71,6 +71,7 @@ namespace Nz OpenGLDevice::~OpenGLDevice() { + // Free context first as it will unregister itself from m_contexts m_referenceContext.reset(); } @@ -95,6 +96,12 @@ namespace Nz return m_deviceInfo; } + const RenderDeviceFeatures& OpenGLDevice::GetEnabledFeatures() const + { + //FIXME + return m_deviceInfo.features; + } + std::shared_ptr OpenGLDevice::InstantiateBuffer(BufferType type) { return std::make_shared(*this, type); diff --git a/src/Nazara/OpenGLRenderer/OpenGLRenderPipeline.cpp b/src/Nazara/OpenGLRenderer/OpenGLRenderPipeline.cpp index 89cb79c8b..6f062f827 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLRenderPipeline.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLRenderPipeline.cpp @@ -19,6 +19,8 @@ namespace Nz m_pipelineInfo(std::move(pipelineInfo)), m_isViewportFlipped(false) { + ValidatePipelineInfo(device, m_pipelineInfo); + OpenGLRenderPipelineLayout& pipelineLayout = static_cast(*m_pipelineInfo.pipelineLayout); if (!m_program.Create(device)) diff --git a/src/Nazara/OpenGLRenderer/OpenGLRenderer.cpp b/src/Nazara/OpenGLRenderer/OpenGLRenderer.cpp index 3062f676f..3a875bcd9 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLRenderer.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLRenderer.cpp @@ -47,9 +47,16 @@ namespace Nz return std::make_unique(owner); } - std::shared_ptr OpenGLRenderer::InstanciateRenderDevice(std::size_t deviceIndex, const RenderDeviceFeatures& /*enabledFeatures*/) + std::shared_ptr OpenGLRenderer::InstanciateRenderDevice(std::size_t deviceIndex, const RenderDeviceFeatures& enabledFeatures) { assert(deviceIndex == 0); + + // For now, since we have to create a device to know its features, supported features are always reported as enabled + // We still call ValidateFeatures in order to trigger warnings if requested features are not supported + // TODO: Report disabled features as disabled (make OpenGLDeviceProxy?) + RenderDeviceFeatures validatedFeatures = enabledFeatures; + OpenGLDevice::ValidateFeatures(m_device->GetEnabledFeatures(), validatedFeatures); + return m_device; } diff --git a/src/Nazara/OpenGLRenderer/OpenGLTextureSampler.cpp b/src/Nazara/OpenGLRenderer/OpenGLTextureSampler.cpp index 1f49bbc30..22f71f76d 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLTextureSampler.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLTextureSampler.cpp @@ -9,8 +9,10 @@ namespace Nz { - OpenGLTextureSampler::OpenGLTextureSampler(OpenGLDevice& device, const TextureSamplerInfo& samplerInfo) + OpenGLTextureSampler::OpenGLTextureSampler(OpenGLDevice& device, TextureSamplerInfo samplerInfo) { + ValidateSamplerInfo(device, samplerInfo); + BuildSampler(device, m_samplerWithMipmaps, samplerInfo, true); BuildSampler(device, m_samplerWithoutMipmaps, samplerInfo, false); } diff --git a/src/Nazara/Renderer/RenderDevice.cpp b/src/Nazara/Renderer/RenderDevice.cpp index 826482736..9c6c32374 100644 --- a/src/Nazara/Renderer/RenderDevice.cpp +++ b/src/Nazara/Renderer/RenderDevice.cpp @@ -31,4 +31,25 @@ namespace Nz return InstantiateShaderModule(shaderStages, lang, source.data(), source.size(), states); } + + void RenderDevice::ValidateFeatures(const RenderDeviceFeatures& supportedFeatures, RenderDeviceFeatures& enabledFeatures) + { + if (enabledFeatures.anisotropicFiltering && !supportedFeatures.anisotropicFiltering) + { + NazaraWarning("anistropic filtering was enabled but device doesn't support it, disabling..."); + enabledFeatures.anisotropicFiltering = false; + } + + if (enabledFeatures.depthClamping && !supportedFeatures.depthClamping) + { + NazaraWarning("depth clamping was enabled but device doesn't support it, disabling..."); + enabledFeatures.depthClamping = false; + } + + if (enabledFeatures.nonSolidFaceFilling && !supportedFeatures.nonSolidFaceFilling) + { + NazaraWarning("non-solid face filling was enabled but device doesn't support it, disabling..."); + enabledFeatures.nonSolidFaceFilling = false; + } + } } diff --git a/src/Nazara/Renderer/RenderPipeline.cpp b/src/Nazara/Renderer/RenderPipeline.cpp index e8b585368..58ea90fce 100644 --- a/src/Nazara/Renderer/RenderPipeline.cpp +++ b/src/Nazara/Renderer/RenderPipeline.cpp @@ -3,9 +3,26 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include #include namespace Nz { RenderPipeline::~RenderPipeline() = default; + + void RenderPipeline::ValidatePipelineInfo(const RenderDevice& device, RenderPipelineInfo& pipelineInfo) + { + const RenderDeviceFeatures& deviceFeatures = device.GetEnabledFeatures(); + if (pipelineInfo.faceFilling != FaceFilling::Fill && !deviceFeatures.nonSolidFaceFilling) + { + NazaraWarning("pipeline has face filling set to non-solid but non-solid face filling is not enabled on the device, disabling..."); + pipelineInfo.faceFilling = FaceFilling::Fill; + } + + if (pipelineInfo.depthClamp && !deviceFeatures.depthClamping) + { + NazaraWarning("pipeline has depth clamp enabled but depth clamping is not enabled on the device, disabling..."); + pipelineInfo.depthClamp = false; + } + } } diff --git a/src/Nazara/Renderer/TextureSampler.cpp b/src/Nazara/Renderer/TextureSampler.cpp index f39f2dc73..c715bc5c7 100644 --- a/src/Nazara/Renderer/TextureSampler.cpp +++ b/src/Nazara/Renderer/TextureSampler.cpp @@ -3,9 +3,20 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include #include namespace Nz { TextureSampler::~TextureSampler() = default; + + void TextureSampler::ValidateSamplerInfo(const RenderDevice& device, TextureSamplerInfo& samplerInfo) + { + const RenderDeviceFeatures& deviceFeatures = device.GetEnabledFeatures(); + if (samplerInfo.anisotropyLevel > 1.f && !deviceFeatures.anisotropicFiltering) + { + NazaraWarning("texture sampler has anistropy level > 1.0 but anistropic filtering is not enabled on the device, disabling..."); + samplerInfo.anisotropyLevel = 0.f; + } + } } diff --git a/src/Nazara/VulkanRenderer/Vulkan.cpp b/src/Nazara/VulkanRenderer/Vulkan.cpp index 231d189b0..17c38d10e 100644 --- a/src/Nazara/VulkanRenderer/Vulkan.cpp +++ b/src/Nazara/VulkanRenderer/Vulkan.cpp @@ -598,7 +598,7 @@ namespace Nz &deviceFeatures }; - std::shared_ptr device = std::make_shared(s_instance, BuildRenderDeviceInfo(deviceInfo)); + std::shared_ptr device = std::make_shared(s_instance, enabledFeatures, BuildRenderDeviceInfo(deviceInfo)); if (!device->Create(deviceInfo, createInfo)) { NazaraError("Failed to create Vulkan Device: " + TranslateVulkanError(device->GetLastErrorCode())); diff --git a/src/Nazara/VulkanRenderer/VulkanDevice.cpp b/src/Nazara/VulkanRenderer/VulkanDevice.cpp index 2b0c925ad..2816449e7 100644 --- a/src/Nazara/VulkanRenderer/VulkanDevice.cpp +++ b/src/Nazara/VulkanRenderer/VulkanDevice.cpp @@ -22,6 +22,11 @@ namespace Nz return m_renderDeviceInfo; } + const RenderDeviceFeatures& VulkanDevice::GetEnabledFeatures() const + { + return m_enabledFeatures; + } + std::shared_ptr VulkanDevice::InstantiateBuffer(BufferType type) { return std::make_shared(*this, type); diff --git a/src/Nazara/VulkanRenderer/VulkanRenderPipeline.cpp b/src/Nazara/VulkanRenderer/VulkanRenderPipeline.cpp index 95b2e8a48..5afc9e537 100644 --- a/src/Nazara/VulkanRenderer/VulkanRenderPipeline.cpp +++ b/src/Nazara/VulkanRenderer/VulkanRenderPipeline.cpp @@ -13,10 +13,12 @@ namespace Nz { - VulkanRenderPipeline::VulkanRenderPipeline(Vk::Device& device, RenderPipelineInfo pipelineInfo) : + VulkanRenderPipeline::VulkanRenderPipeline(VulkanDevice& device, RenderPipelineInfo pipelineInfo) : m_device(&device), m_pipelineInfo(std::move(pipelineInfo)) { + ValidatePipelineInfo(device, m_pipelineInfo); + m_pipelineCreateInfo = BuildCreateInfo(m_pipelineInfo); } diff --git a/src/Nazara/VulkanRenderer/VulkanTextureSampler.cpp b/src/Nazara/VulkanRenderer/VulkanTextureSampler.cpp index 2a9d44035..59a140bb3 100644 --- a/src/Nazara/VulkanRenderer/VulkanTextureSampler.cpp +++ b/src/Nazara/VulkanRenderer/VulkanTextureSampler.cpp @@ -3,13 +3,16 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include #include #include namespace Nz { - VulkanTextureSampler::VulkanTextureSampler(Vk::Device& device, TextureSamplerInfo samplerInfo) + VulkanTextureSampler::VulkanTextureSampler(VulkanDevice& device, TextureSamplerInfo samplerInfo) { + ValidateSamplerInfo(device, samplerInfo); + VkSamplerCreateInfo createInfo = { VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO }; createInfo.magFilter = ToVulkan(samplerInfo.magFilter); createInfo.minFilter = ToVulkan(samplerInfo.minFilter);