Index: ps/trunk/source/graphics/ShaderManager.cpp =================================================================== --- ps/trunk/source/graphics/ShaderManager.cpp +++ ps/trunk/source/graphics/ShaderManager.cpp @@ -139,8 +139,10 @@ if (ret != PSRETURN_OK) return false; + Renderer::Backend::IDevice* device = g_VideoMode.GetBackendDevice(); + // By default we assume that we have techinques for every dummy shader. - if (g_VideoMode.GetBackend() == CVideoMode::Backend::DUMMY) + if (device->GetBackend() == Renderer::Backend::Backend::DUMMY) { const Renderer::Backend::GraphicsPipelineStateDesc passPipelineStateDesc = Renderer::Backend::MakeDefaultGraphicsPipelineStateDesc(); @@ -210,15 +212,15 @@ { if (Attrs.GetNamedItem(at_shaders) == "arb") { - if (g_VideoMode.GetBackend() != CVideoMode::Backend::GL_ARB || - !g_VideoMode.GetBackendDevice()->GetCapabilities().ARBShaders) + if (device->GetBackend() != Renderer::Backend::Backend::GL_ARB || + !device->GetCapabilities().ARBShaders) { isUsable = false; } } else if (Attrs.GetNamedItem(at_shaders) == "glsl") { - if (g_VideoMode.GetBackend() != CVideoMode::Backend::GL) + if (device->GetBackend() != Renderer::Backend::Backend::GL) isUsable = false; } else if (!Attrs.GetNamedItem(at_context).empty()) Index: ps/trunk/source/ps/Profiler2GPU.cpp =================================================================== --- ps/trunk/source/ps/Profiler2GPU.cpp +++ ps/trunk/source/ps/Profiler2GPU.cpp @@ -28,6 +28,7 @@ #include "ps/ConfigDB.h" #include "ps/Profiler2.h" #include "ps/VideoMode.h" +#include "renderer/backend/IDevice.h" #include #include @@ -70,7 +71,7 @@ public: static bool IsSupported() { - if (g_VideoMode.GetBackend() != CVideoMode::Backend::GL) + if (g_VideoMode.GetBackendDevice()->GetBackend() != Renderer::Backend::Backend::GL) return false; return ogl_HaveExtension("GL_ARB_timer_query"); } Index: ps/trunk/source/ps/VideoMode.h =================================================================== --- ps/trunk/source/ps/VideoMode.h +++ ps/trunk/source/ps/VideoMode.h @@ -19,6 +19,7 @@ #define INCLUDED_VIDEOMODE #include "ps/CStrForward.h" +#include "renderer/backend/Backend.h" #include @@ -35,13 +36,6 @@ class CVideoMode { public: - enum class Backend - { - GL, - GL_ARB, - DUMMY - }; - CVideoMode(); ~CVideoMode(); @@ -124,8 +118,6 @@ void SetCursor(const CStrW& name); void ResetCursor(); - Backend GetBackend() const { return m_Backend; } - Renderer::Backend::IDevice* GetBackendDevice() { return m_BackendDevice.get(); } private: @@ -181,7 +173,7 @@ class CCursor; std::unique_ptr m_Cursor; - Backend m_Backend = Backend::GL; + Renderer::Backend::Backend m_Backend = Renderer::Backend::Backend::GL; std::unique_ptr m_BackendDevice; }; Index: ps/trunk/source/ps/VideoMode.cpp =================================================================== --- ps/trunk/source/ps/VideoMode.cpp +++ ps/trunk/source/ps/VideoMode.cpp @@ -32,8 +32,9 @@ #include "ps/Game.h" #include "ps/GameSetup/Config.h" #include "ps/Pyrogenesis.h" -#include "renderer/backend/dummy/Device.h" -#include "renderer/backend/gl/Device.h" +#include "renderer/backend/dummy/DeviceForward.h" +#include "renderer/backend/gl/DeviceForward.h" +#include "renderer/backend/IDevice.h" #include "renderer/Renderer.h" namespace @@ -235,11 +236,11 @@ CStr rendererBackend; CFG_GET_VAL("rendererbackend", rendererBackend); if (rendererBackend == "glarb") - m_Backend = Backend::GL_ARB; + m_Backend = Renderer::Backend::Backend::GL_ARB; else if (rendererBackend == "dummy") - m_Backend = Backend::DUMMY; + m_Backend = Renderer::Backend::Backend::DUMMY; else - m_Backend = Backend::GL; + m_Backend = Renderer::Backend::Backend::GL; } bool CVideoMode::SetVideoMode(int w, int h, int bpp, bool fullscreen) @@ -529,16 +530,17 @@ bool CVideoMode::CreateBackendDevice(const bool createSDLContext) { - if (m_Backend == Backend::DUMMY) + if (m_Backend == Renderer::Backend::Backend::DUMMY) { - m_BackendDevice = std::make_unique(); + m_BackendDevice = Renderer::Backend::Dummy::CreateDevice(m_Window); + ENSURE(m_BackendDevice); return true; } - m_BackendDevice = Renderer::Backend::GL::CDevice::Create(createSDLContext ? m_Window : nullptr, m_Backend == Backend::GL_ARB); - if (!m_BackendDevice && m_Backend == Backend::GL) + m_BackendDevice = Renderer::Backend::GL::CreateDevice(createSDLContext ? m_Window : nullptr, m_Backend == Renderer::Backend::Backend::GL_ARB); + if (!m_BackendDevice && m_Backend == Renderer::Backend::Backend::GL) { LOGERROR("Unable to create device for GL backend, switching to ARB.", static_cast(m_Backend)); - m_Backend = Backend::GL_ARB; + m_Backend = Renderer::Backend::Backend::GL_ARB; return CreateBackendDevice(createSDLContext); } return !!m_BackendDevice; Index: ps/trunk/source/renderer/PostprocManager.cpp =================================================================== --- ps/trunk/source/renderer/PostprocManager.cpp +++ ps/trunk/source/renderer/PostprocManager.cpp @@ -49,11 +49,11 @@ bool CPostprocManager::IsEnabled() const { + Renderer::Backend::IDevice* device = g_VideoMode.GetBackendDevice(); return g_RenderingOptions.GetPostProc() && - g_VideoMode.GetBackend() != CVideoMode::Backend::GL_ARB && - g_VideoMode.GetBackendDevice()->IsTextureFormatSupported( - Renderer::Backend::Format::D24_S8); + device->GetBackend() != Renderer::Backend::Backend::GL_ARB && + device->IsTextureFormatSupported(Renderer::Backend::Format::D24_S8); } void CPostprocManager::Cleanup() @@ -507,7 +507,7 @@ // Don't do anything if we are using the default effect and no AA. const bool hasEffects = m_PostProcEffect != L"default"; - const bool hasARB = g_VideoMode.GetBackend() == CVideoMode::Backend::GL_ARB; + const bool hasARB = g_VideoMode.GetBackendDevice()->GetBackend() == Renderer::Backend::Backend::GL_ARB; const bool hasAA = m_AATech && !hasARB; const bool hasSharp = m_SharpTech && !hasARB; if (!hasEffects && !hasAA && !hasSharp) @@ -577,7 +577,8 @@ void CPostprocManager::UpdateAntiAliasingTechnique() { - if (g_VideoMode.GetBackend() == CVideoMode::Backend::GL_ARB || !m_IsInitialized) + Renderer::Backend::IDevice* device = g_VideoMode.GetBackendDevice(); + if (device->GetBackend() == Renderer::Backend::Backend::GL_ARB || !m_IsInitialized) return; CStr newAAName; @@ -606,7 +607,7 @@ // We don't want to enable MSAA in Atlas, because it uses wxWidgets and its canvas. if (g_AtlasGameLoop && g_AtlasGameLoop->running) return; - if (!g_VideoMode.GetBackendDevice()->GetCapabilities().multisampling || m_AllowedSampleCounts.empty()) + if (!device->GetCapabilities().multisampling || m_AllowedSampleCounts.empty()) { LOGWARNING("MSAA is unsupported."); return; @@ -616,7 +617,7 @@ if (std::find(std::begin(m_AllowedSampleCounts), std::end(m_AllowedSampleCounts), m_MultisampleCount) == std::end(m_AllowedSampleCounts)) { - m_MultisampleCount = std::min(4u, g_VideoMode.GetBackendDevice()->GetCapabilities().maxSampleCount); + m_MultisampleCount = std::min(4u, device->GetCapabilities().maxSampleCount); LOGWARNING("Wrong MSAA sample count: %s.", m_AAName.EscapeToPrintableASCII().c_str()); } m_UsingMultisampleBuffer = true; @@ -626,7 +627,7 @@ void CPostprocManager::UpdateSharpeningTechnique() { - if (g_VideoMode.GetBackend() == CVideoMode::Backend::GL_ARB || !m_IsInitialized) + if (g_VideoMode.GetBackendDevice()->GetBackend() == Renderer::Backend::Backend::GL_ARB || !m_IsInitialized) return; CStr newSharpName; Index: ps/trunk/source/renderer/Renderer.cpp =================================================================== --- ps/trunk/source/renderer/Renderer.cpp +++ ps/trunk/source/renderer/Renderer.cpp @@ -373,7 +373,7 @@ // Renderer has been opened, so validate the selected renderpath const bool hasShadersSupport = g_VideoMode.GetBackendDevice()->GetCapabilities().ARBShaders || - g_VideoMode.GetBackend() != CVideoMode::Backend::GL_ARB; + g_VideoMode.GetBackendDevice()->GetBackend() != Renderer::Backend::Backend::GL_ARB; if (rp == RenderPath::DEFAULT) { if (hasShadersSupport) Index: ps/trunk/source/renderer/RenderingOptions.cpp =================================================================== --- ps/trunk/source/renderer/RenderingOptions.cpp +++ ps/trunk/source/renderer/RenderingOptions.cpp @@ -25,6 +25,7 @@ #include "ps/CStr.h" #include "ps/CStrInternStatic.h" #include "ps/VideoMode.h" +#include "renderer/backend/IDevice.h" #include "renderer/Renderer.h" #include "renderer/PostprocManager.h" #include "renderer/SceneRenderer.h" @@ -239,7 +240,7 @@ m_ConfigHooks->Setup("gpuskinning", [this]() { bool enabled; CFG_GET_VAL("gpuskinning", enabled); - if (enabled && g_VideoMode.GetBackend() == CVideoMode::Backend::GL_ARB) + if (enabled && g_VideoMode.GetBackendDevice()->GetBackend() == Renderer::Backend::Backend::GL_ARB) LOGWARNING("GPUSkinning has been disabled, because it is not supported with ARB shaders."); else if (enabled) m_GPUSkinning = true; Index: ps/trunk/source/renderer/SceneRenderer.cpp =================================================================== --- ps/trunk/source/renderer/SceneRenderer.cpp +++ ps/trunk/source/renderer/SceneRenderer.cpp @@ -215,11 +215,13 @@ { m->globalContext = CShaderDefines(); + Renderer::Backend::IDevice* device = g_VideoMode.GetBackendDevice(); + if (g_RenderingOptions.GetShadows()) { m->globalContext.Add(str_USE_SHADOW, str_1); - if (g_VideoMode.GetBackend() == CVideoMode::Backend::GL_ARB && - g_VideoMode.GetBackendDevice()->GetCapabilities().ARBShadersShadow) + if (device->GetBackend() == Renderer::Backend::Backend::GL_ARB && + device->GetCapabilities().ARBShadersShadow) { m->globalContext.Add(str_USE_FP_SHADOW, str_1); } @@ -237,18 +239,18 @@ m->globalContext.Add(str_RENDER_DEBUG_MODE, RenderDebugModeEnum::ToString(g_RenderingOptions.GetRenderDebugMode())); - if (g_VideoMode.GetBackend() != CVideoMode::Backend::GL_ARB && g_RenderingOptions.GetFog()) + if (device->GetBackend() != Renderer::Backend::Backend::GL_ARB && g_RenderingOptions.GetFog()) m->globalContext.Add(str_USE_FOG, str_1); m->Model.ModShader = LitRenderModifierPtr(new ShaderRenderModifier()); ENSURE(g_RenderingOptions.GetRenderPath() != RenderPath::FIXED); m->Model.VertexRendererShader = ModelVertexRendererPtr(new ShaderModelVertexRenderer()); - m->Model.VertexInstancingShader = ModelVertexRendererPtr(new InstancingModelRenderer(false, g_VideoMode.GetBackend() != CVideoMode::Backend::GL_ARB)); + m->Model.VertexInstancingShader = ModelVertexRendererPtr(new InstancingModelRenderer(false, device->GetBackend() != Renderer::Backend::Backend::GL_ARB)); if (g_RenderingOptions.GetGPUSkinning()) // TODO: should check caps and GLSL etc too { - m->Model.VertexGPUSkinningShader = ModelVertexRendererPtr(new InstancingModelRenderer(true, g_VideoMode.GetBackend() != CVideoMode::Backend::GL_ARB)); + m->Model.VertexGPUSkinningShader = ModelVertexRendererPtr(new InstancingModelRenderer(true, device->GetBackend() != Renderer::Backend::Backend::GL_ARB)); m->Model.NormalSkinned = ModelRendererPtr(new ShaderModelRenderer(m->Model.VertexGPUSkinningShader)); m->Model.TranspSkinned = ModelRendererPtr(new ShaderModelRenderer(m->Model.VertexGPUSkinningShader)); } Index: ps/trunk/source/renderer/ShadowMap.cpp =================================================================== --- ps/trunk/source/renderer/ShadowMap.cpp +++ ps/trunk/source/renderer/ShadowMap.cpp @@ -124,7 +124,7 @@ CascadeCount = 1; CFG_GET_VAL("shadowscascadecount", CascadeCount); - if (CascadeCount < 1 || CascadeCount > MAX_CASCADE_COUNT || g_VideoMode.GetBackend() == CVideoMode::Backend::GL_ARB) + if (CascadeCount < 1 || CascadeCount > MAX_CASCADE_COUNT || g_VideoMode.GetBackendDevice()->GetBackend() == Renderer::Backend::Backend::GL_ARB) CascadeCount = 1; ShadowsCoverMap = false; Index: ps/trunk/source/renderer/WaterManager.cpp =================================================================== --- ps/trunk/source/renderer/WaterManager.cpp +++ ps/trunk/source/renderer/WaterManager.cpp @@ -1070,7 +1070,7 @@ bool WaterManager::WillRenderFancyWater() const { return - m_RenderWater && g_VideoMode.GetBackend() != CVideoMode::Backend::GL_ARB && + m_RenderWater && g_VideoMode.GetBackendDevice()->GetBackend() != Renderer::Backend::Backend::GL_ARB && g_RenderingOptions.GetWaterEffects(); } Index: ps/trunk/source/renderer/backend/Backend.h =================================================================== --- ps/trunk/source/renderer/backend/Backend.h +++ ps/trunk/source/renderer/backend/Backend.h @@ -0,0 +1,39 @@ +/* Copyright (C) 2022 Wildfire Games. + * This file is part of 0 A.D. + * + * 0 A.D. is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * 0 A.D. is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 0 A.D. If not, see . + */ + +#ifndef INCLUDED_RENDERER_BACKEND_BACKEND +#define INCLUDED_RENDERER_BACKEND_BACKEND + +namespace Renderer +{ + +namespace Backend +{ + +enum class Backend +{ + GL, + GL_ARB, + VULKAN, + DUMMY +}; + +} // namespace Backend + +} // namespace Renderer + +#endif // INCLUDED_RENDERER_BACKEND_BACKEND Index: ps/trunk/source/renderer/backend/IDevice.h =================================================================== --- ps/trunk/source/renderer/backend/IDevice.h +++ ps/trunk/source/renderer/backend/IDevice.h @@ -19,6 +19,7 @@ #define INCLUDED_RENDERER_BACKEND_IDEVICE #include "graphics/Color.h" +#include "renderer/backend/Backend.h" #include "renderer/backend/Format.h" #include "renderer/backend/IBuffer.h" #include "renderer/backend/IDevice.h" @@ -62,6 +63,8 @@ virtual ~IDevice() {} + virtual Backend GetBackend() const = 0; + virtual const std::string& GetName() const = 0; virtual const std::string& GetVersion() const = 0; virtual const std::string& GetDriverInformation() const = 0; Index: ps/trunk/source/renderer/backend/dummy/Device.h =================================================================== --- ps/trunk/source/renderer/backend/dummy/Device.h +++ ps/trunk/source/renderer/backend/dummy/Device.h @@ -18,6 +18,7 @@ #ifndef INCLUDED_RENDERER_BACKEND_DUMMY_DEVICE #define INCLUDED_RENDERER_BACKEND_DUMMY_DEVICE +#include "renderer/backend/dummy/DeviceForward.h" #include "renderer/backend/IDevice.h" class CShaderDefines; @@ -39,6 +40,8 @@ CDevice(); ~CDevice() override; + Backend GetBackend() const override { return Backend::DUMMY; } + const std::string& GetName() const override { return m_Name; } const std::string& GetVersion() const override { return m_Version; } const std::string& GetDriverInformation() const override { return m_DriverInformation; } Index: ps/trunk/source/renderer/backend/dummy/Device.cpp =================================================================== --- ps/trunk/source/renderer/backend/dummy/Device.cpp +++ ps/trunk/source/renderer/backend/dummy/Device.cpp @@ -134,6 +134,11 @@ return true; } +std::unique_ptr CreateDevice(SDL_Window* UNUSED(window)) +{ + return std::make_unique(); +} + } // namespace Dummy } // namespace Backend Index: ps/trunk/source/renderer/backend/dummy/DeviceForward.h =================================================================== --- ps/trunk/source/renderer/backend/dummy/DeviceForward.h +++ ps/trunk/source/renderer/backend/dummy/DeviceForward.h @@ -0,0 +1,46 @@ +/* Copyright (C) 2022 Wildfire Games. + * This file is part of 0 A.D. + * + * 0 A.D. is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * 0 A.D. is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 0 A.D. If not, see . + */ + +#ifndef INCLUDED_RENDERER_BACKEND_DUMMY_DEVICEFORWARD +#define INCLUDED_RENDERER_BACKEND_DUMMY_DEVICEFORWARD + +#include + +typedef struct SDL_Window SDL_Window; + +namespace Renderer +{ + +namespace Backend +{ + +class IDevice; + +namespace Dummy +{ + +class CDevice; + +std::unique_ptr CreateDevice(SDL_Window* window); + +} // namespace Dummy + +} // namespace Backend + +} // namespace Renderer + +#endif // INCLUDED_RENDERER_BACKEND_DUMMY_DEVICEFORWARD Index: ps/trunk/source/renderer/backend/gl/Device.h =================================================================== --- ps/trunk/source/renderer/backend/gl/Device.h +++ ps/trunk/source/renderer/backend/gl/Device.h @@ -20,6 +20,7 @@ #include "renderer/backend/Format.h" #include "renderer/backend/gl/Buffer.h" +#include "renderer/backend/gl/DeviceForward.h" #include "renderer/backend/gl/Framebuffer.h" #include "renderer/backend/gl/ShaderProgram.h" #include "renderer/backend/gl/Texture.h" @@ -54,6 +55,8 @@ */ static std::unique_ptr Create(SDL_Window* window, const bool arb); + Backend GetBackend() const override { return m_ARB ? Backend::GL_ARB : Backend::GL; } + const std::string& GetName() const override { return m_Name; } const std::string& GetVersion() const override { return m_Version; } const std::string& GetDriverInformation() const override { return m_DriverInformation; } Index: ps/trunk/source/renderer/backend/gl/Device.cpp =================================================================== --- ps/trunk/source/renderer/backend/gl/Device.cpp +++ ps/trunk/source/renderer/backend/gl/Device.cpp @@ -1003,6 +1003,11 @@ return supported; } +std::unique_ptr CreateDevice(SDL_Window* window, const bool arb) +{ + return GL::CDevice::Create(window, arb); +} + } // namespace GL } // namespace Backend Index: ps/trunk/source/renderer/backend/gl/DeviceForward.h =================================================================== --- ps/trunk/source/renderer/backend/gl/DeviceForward.h +++ ps/trunk/source/renderer/backend/gl/DeviceForward.h @@ -0,0 +1,46 @@ +/* Copyright (C) 2022 Wildfire Games. + * This file is part of 0 A.D. + * + * 0 A.D. is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * 0 A.D. is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 0 A.D. If not, see . + */ + +#ifndef INCLUDED_RENDERER_BACKEND_GL_DEVICEFORWARD +#define INCLUDED_RENDERER_BACKEND_GL_DEVICEFORWARD + +#include + +typedef struct SDL_Window SDL_Window; + +namespace Renderer +{ + +namespace Backend +{ + +class IDevice; + +namespace GL +{ + +class CDevice; + +std::unique_ptr CreateDevice(SDL_Window* window, const bool arb); + +} // namespace GL + +} // namespace Backend + +} // namespace Renderer + +#endif // INCLUDED_RENDERER_BACKEND_GL_DEVICEFORWARD Index: ps/trunk/source/renderer/backend/vulkan/Device.h =================================================================== --- ps/trunk/source/renderer/backend/vulkan/Device.h +++ ps/trunk/source/renderer/backend/vulkan/Device.h @@ -19,6 +19,7 @@ #define INCLUDED_RENDERER_BACKEND_VULKAN_DEVICE #include "renderer/backend/IDevice.h" +#include "renderer/backend/vulkan/DeviceForward.h" #include "scriptinterface/ScriptForward.h" #include @@ -44,6 +45,8 @@ ~CDevice() override; + Backend GetBackend() const override { return Backend::VULKAN; } + const std::string& GetName() const override { return m_Name; } const std::string& GetVersion() const override { return m_Version; } const std::string& GetDriverInformation() const override { return m_DriverInformation; } Index: ps/trunk/source/renderer/backend/vulkan/Device.cpp =================================================================== --- ps/trunk/source/renderer/backend/vulkan/Device.cpp +++ ps/trunk/source/renderer/backend/vulkan/Device.cpp @@ -170,6 +170,11 @@ return false; } +std::unique_ptr CreateDevice(SDL_Window* window) +{ + return Vulkan::CDevice::Create(window); +} + } // namespace Vulkan } // namespace Backend Index: ps/trunk/source/renderer/backend/vulkan/DeviceForward.h =================================================================== --- ps/trunk/source/renderer/backend/vulkan/DeviceForward.h +++ ps/trunk/source/renderer/backend/vulkan/DeviceForward.h @@ -0,0 +1,46 @@ +/* Copyright (C) 2022 Wildfire Games. + * This file is part of 0 A.D. + * + * 0 A.D. is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * 0 A.D. is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 0 A.D. If not, see . + */ + +#ifndef INCLUDED_RENDERER_BACKEND_VULKAN_DEVICEFORWARD +#define INCLUDED_RENDERER_BACKEND_VULKAN_DEVICEFORWARD + +#include + +typedef struct SDL_Window SDL_Window; + +namespace Renderer +{ + +namespace Backend +{ + +class IDevice; + +namespace Vulkan +{ + +class CDevice; + +std::unique_ptr CreateDevice(SDL_Window* window); + +} // namespace Vulkan + +} // namespace Backend + +} // namespace Renderer + +#endif // INCLUDED_RENDERER_BACKEND_VULKAN_DEVICEFORWARD