Index: ps/trunk/source/graphics/GameView.h =================================================================== --- ps/trunk/source/graphics/GameView.h +++ ps/trunk/source/graphics/GameView.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -37,7 +37,7 @@ { NONCOPYABLE(CGameView); public: - CGameView(CGame *pGame); + CGameView(Renderer::Backend::IDevice* device, CGame *pGame); ~CGameView() override; void SetViewport(const SViewPort& vp); Index: ps/trunk/source/graphics/GameView.cpp =================================================================== --- ps/trunk/source/graphics/GameView.cpp +++ ps/trunk/source/graphics/GameView.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -67,13 +67,13 @@ { NONCOPYABLE(CGameViewImpl); public: - CGameViewImpl(CGame* game) + CGameViewImpl(Renderer::Backend::IDevice* device, CGame* game) : Game(game), ColladaManager(g_VFS), MeshManager(ColladaManager), SkeletonAnimManager(ColladaManager), ObjectManager(MeshManager, SkeletonAnimManager, *game->GetSimulation2()), LOSTexture(*game->GetSimulation2()), TerritoryTexture(*game->GetSimulation2()), - MiniMapTexture(*game->GetSimulation2()), + MiniMapTexture(device, *game->GetSimulation2()), ViewCamera(), CullCamera(), LockCullCamera(false), @@ -158,8 +158,8 @@ #undef IMPLEMENT_BOOLEAN_SETTING -CGameView::CGameView(CGame *pGame): - m(new CGameViewImpl(pGame)) +CGameView::CGameView(Renderer::Backend::IDevice* device, CGame *pGame): + m(new CGameViewImpl(device, pGame)) { m->CullCamera = m->ViewCamera; g_Renderer.GetSceneRenderer().SetSceneCamera(m->ViewCamera, m->CullCamera); Index: ps/trunk/source/graphics/MiniMapTexture.h =================================================================== --- ps/trunk/source/graphics/MiniMapTexture.h +++ ps/trunk/source/graphics/MiniMapTexture.h @@ -41,7 +41,7 @@ { NONCOPYABLE(CMiniMapTexture); public: - CMiniMapTexture(CSimulation2& simulation); + CMiniMapTexture(Renderer::Backend::IDevice* device, CSimulation2& simulation); ~CMiniMapTexture(); /** Index: ps/trunk/source/graphics/MiniMapTexture.cpp =================================================================== --- ps/trunk/source/graphics/MiniMapTexture.cpp +++ ps/trunk/source/graphics/MiniMapTexture.cpp @@ -190,7 +190,7 @@ lhs.b == rhs.b; } -CMiniMapTexture::CMiniMapTexture(CSimulation2& simulation) +CMiniMapTexture::CMiniMapTexture(Renderer::Backend::IDevice* device, CSimulation2& simulation) : m_Simulation(simulation), m_IndexArray(false), m_VertexArray(Renderer::Backend::IBuffer::Type::VERTEX, true), m_InstanceVertexArray(Renderer::Backend::IBuffer::Type::VERTEX, false) @@ -252,7 +252,6 @@ }}; m_QuadVertexInputLayout = g_Renderer.GetVertexInputLayout(attributes); - Renderer::Backend::IDevice* device = g_VideoMode.GetBackendDevice(); m_Flipped = device->GetBackend() == Renderer::Backend::Backend::VULKAN; const uint32_t stride = m_VertexArray.GetStride(); Index: ps/trunk/source/graphics/ShaderManager.h =================================================================== --- ps/trunk/source/graphics/ShaderManager.h +++ ps/trunk/source/graphics/ShaderManager.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -37,7 +37,7 @@ class CShaderManager { public: - CShaderManager(); + CShaderManager(Renderer::Backend::IDevice* device); ~CShaderManager(); /** @@ -81,6 +81,8 @@ } }; + Renderer::Backend::IDevice* m_Device = nullptr; + // A CShaderProgram contains expensive backend state, so we ought to cache it. // The compiled state depends solely on the filename and list of defines, // so we store that in CacheKey. Index: ps/trunk/source/graphics/ShaderManager.cpp =================================================================== --- ps/trunk/source/graphics/ShaderManager.cpp +++ ps/trunk/source/graphics/ShaderManager.cpp @@ -31,10 +31,7 @@ #include "ps/Filesystem.h" #include "ps/Profile.h" #include "ps/XML/Xeromyces.h" -#include "ps/VideoMode.h" #include "renderer/backend/IDevice.h" -#include "renderer/Renderer.h" -#include "renderer/RenderingOptions.h" #define USE_SHADER_XML_VALIDATION 1 @@ -48,7 +45,8 @@ TIMER_ADD_CLIENT(tc_ShaderValidation); -CShaderManager::CShaderManager() +CShaderManager::CShaderManager(Renderer::Backend::IDevice* device) + : m_Device(device) { #if USE_SHADER_XML_VALIDATION { @@ -75,7 +73,7 @@ if (it != m_ProgramCache.end()) return it->second; - CShaderProgramPtr program = CShaderProgram::Create(name, defines); + CShaderProgramPtr program = CShaderProgram::Create(m_Device, name, defines); if (program) { for (const VfsPath& path : program->GetFileDependencies()) @@ -156,10 +154,8 @@ 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 (device->GetBackend() == Renderer::Backend::Backend::DUMMY) + if (m_Device->GetBackend() == Renderer::Backend::Backend::DUMMY) { CShaderProgramPtr shaderProgram = LoadProgram(str_dummy.string(), tech->GetShaderDefines()); std::vector techPasses; @@ -167,7 +163,7 @@ Renderer::Backend::MakeDefaultGraphicsPipelineStateDesc(); passPipelineStateDesc.shaderProgram = shaderProgram->GetBackendShaderProgram(); techPasses.emplace_back( - device->CreateGraphicsPipelineState(passPipelineStateDesc), shaderProgram); + m_Device->CreateGraphicsPipelineState(passPipelineStateDesc), shaderProgram); tech->SetPasses(std::move(techPasses)); return true; } @@ -233,20 +229,20 @@ { if (attrs.GetNamedItem(at_shaders) == "arb") { - if (device->GetBackend() != Renderer::Backend::Backend::GL_ARB || - !device->GetCapabilities().ARBShaders) + if (m_Device->GetBackend() != Renderer::Backend::Backend::GL_ARB || + !m_Device->GetCapabilities().ARBShaders) { isUsable = false; } } else if (attrs.GetNamedItem(at_shaders) == "glsl") { - if (device->GetBackend() != Renderer::Backend::Backend::GL) + if (m_Device->GetBackend() != Renderer::Backend::Backend::GL) isUsable = false; } else if (attrs.GetNamedItem(at_shaders) == "spirv") { - if (device->GetBackend() != Renderer::Backend::Backend::VULKAN) + if (m_Device->GetBackend() != Renderer::Backend::Backend::VULKAN) isUsable = false; } else if (!attrs.GetNamedItem(at_context).empty()) @@ -443,7 +439,7 @@ tech->GetPipelineStateDescCallback()(passPipelineStateDesc); passPipelineStateDesc.shaderProgram = shaderProgram->GetBackendShaderProgram(); techPasses.emplace_back( - device->CreateGraphicsPipelineState(passPipelineStateDesc), shaderProgram); + m_Device->CreateGraphicsPipelineState(passPipelineStateDesc), shaderProgram); } } } Index: ps/trunk/source/graphics/ShaderProgram.h =================================================================== --- ps/trunk/source/graphics/ShaderProgram.h +++ ps/trunk/source/graphics/ShaderProgram.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -35,7 +35,8 @@ NONCOPYABLE(CShaderProgram); public: - static CShaderProgramPtr Create(const CStr& name, const CShaderDefines& defines); + static CShaderProgramPtr Create( + Renderer::Backend::IDevice* device, const CStr& name, const CShaderDefines& defines); void Reload(); @@ -46,8 +47,10 @@ // TODO: add reloadable handles. protected: - CShaderProgram(const CStr& name, const CShaderDefines& defines); + CShaderProgram( + Renderer::Backend::IDevice* device, const CStr& name, const CShaderDefines& defines); + Renderer::Backend::IDevice* m_Device = nullptr; CStr m_Name; CShaderDefines m_Defines; std::unique_ptr m_BackendShaderProgram; Index: ps/trunk/source/graphics/ShaderProgram.cpp =================================================================== --- ps/trunk/source/graphics/ShaderProgram.cpp +++ ps/trunk/source/graphics/ShaderProgram.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -19,18 +19,19 @@ #include "ShaderProgram.h" -#include "ps/VideoMode.h" #include "renderer/backend/IDevice.h" -CShaderProgram::CShaderProgram(const CStr& name, const CShaderDefines& defines) - : m_Name(name), m_Defines(defines) +CShaderProgram::CShaderProgram( + Renderer::Backend::IDevice* device, const CStr& name, const CShaderDefines& defines) + : m_Device(device), m_Name(name), m_Defines(defines) { } // static -CShaderProgramPtr CShaderProgram::Create(const CStr& name, const CShaderDefines& defines) +CShaderProgramPtr CShaderProgram::Create( + Renderer::Backend::IDevice* device, const CStr& name, const CShaderDefines& defines) { - CShaderProgramPtr shaderProgram(new CShaderProgram(name, defines)); + CShaderProgramPtr shaderProgram(new CShaderProgram(device, name, defines)); shaderProgram->Reload(); return shaderProgram->m_BackendShaderProgram ? shaderProgram : nullptr; } @@ -38,7 +39,7 @@ void CShaderProgram::Reload() { std::unique_ptr backendShaderProgram = - g_VideoMode.GetBackendDevice()->CreateShaderProgram(m_Name, m_Defines); + m_Device->CreateShaderProgram(m_Name, m_Defines); if (backendShaderProgram) m_BackendShaderProgram = std::move(backendShaderProgram); } Index: ps/trunk/source/graphics/TerrainTextureManager.h =================================================================== --- ps/trunk/source/graphics/TerrainTextureManager.h +++ ps/trunk/source/graphics/TerrainTextureManager.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -94,7 +94,7 @@ using TerrainAlphaMap = std::map; // constructor, destructor - CTerrainTextureManager(); + CTerrainTextureManager(Renderer::Backend::IDevice* device); ~CTerrainTextureManager(); // Find all XML's in the directory (with subdirs) and try to load them as @@ -124,6 +124,8 @@ void UploadResourcesIfNeeded(Renderer::Backend::IDeviceCommandContext* deviceCommandContext); private: + Renderer::Backend::IDevice* m_Device = nullptr; + // All texture entries created by this class, for easy freeing now that // textures may be in several STextureType's std::vector m_TextureEntries; @@ -132,7 +134,7 @@ TerrainAlphaMap m_TerrainAlphas; - size_t m_LastGroupIndex; + size_t m_LastGroupIndex = 0; // A way to separate file loading and uploading to GPU to not stall uploading. // Once we get a properly threaded loading we might optimize that. Index: ps/trunk/source/graphics/TerrainTextureManager.cpp =================================================================== --- ps/trunk/source/graphics/TerrainTextureManager.cpp +++ ps/trunk/source/graphics/TerrainTextureManager.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -28,7 +28,6 @@ #include "lib/timer.h" #include "ps/CLogger.h" #include "ps/Filesystem.h" -#include "ps/VideoMode.h" #include "ps/XML/Xeromyces.h" #include "renderer/backend/IDevice.h" #include "renderer/Renderer.h" @@ -37,8 +36,8 @@ #include #include -CTerrainTextureManager::CTerrainTextureManager() - : m_LastGroupIndex(0) +CTerrainTextureManager::CTerrainTextureManager(Renderer::Backend::IDevice* device) + : m_Device(device) { if (!VfsDirectoryExists(L"art/terrains/")) return; @@ -292,7 +291,7 @@ ignore_result(da_free(&da)); #endif - result.m_CompositeAlphaMap = g_VideoMode.GetBackendDevice()->CreateTexture2D("CompositeAlphaMap", + result.m_CompositeAlphaMap = m_Device->CreateTexture2D("CompositeAlphaMap", Renderer::Backend::ITexture::Usage::TRANSFER_DST | Renderer::Backend::ITexture::Usage::SAMPLED, Renderer::Backend::Format::A8_UNORM, totalWidth, totalHeight, Index: ps/trunk/source/gui/tests/test_CGUIText.h =================================================================== --- ps/trunk/source/gui/tests/test_CGUIText.h +++ ps/trunk/source/gui/tests/test_CGUIText.h @@ -57,7 +57,7 @@ g_VideoMode.InitNonSDL(); g_VideoMode.CreateBackendDevice(false); m_Viewer = new CProfileViewer; - m_Renderer = new CRenderer; + m_Renderer = new CRenderer(g_VideoMode.GetBackendDevice()); } void tearDown() Index: ps/trunk/source/ps/Game.cpp =================================================================== --- ps/trunk/source/ps/Game.cpp +++ ps/trunk/source/ps/Game.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -32,12 +32,13 @@ #include "ps/CConsole.h" #include "ps/CLogger.h" #include "ps/CStr.h" +#include "ps/GameSetup/GameSetup.h" #include "ps/Loader.h" #include "ps/LoaderThunks.h" #include "ps/Profile.h" #include "ps/Replay.h" #include "ps/World.h" -#include "ps/GameSetup/GameSetup.h" +#include "ps/VideoMode.h" #include "renderer/Renderer.h" #include "renderer/SceneRenderer.h" #include "renderer/TimeManager.h" @@ -70,7 +71,9 @@ CGame::CGame(bool replayLog): m_World(new CWorld(this)), m_Simulation2(new CSimulation2(&m_World->GetUnitManager(), g_ScriptContext, m_World->GetTerrain())), - m_GameView(CRenderer::IsInitialised() ? new CGameView(this) : nullptr), + // TODO: we need to remove that global dependency. Maybe the game view + // should be created outside only if needed. + m_GameView(CRenderer::IsInitialised() ? new CGameView(g_VideoMode.GetBackendDevice(), this) : nullptr), m_GameStarted(false), m_Paused(false), m_SimRate(1.0f), Index: ps/trunk/source/ps/GameSetup/GameSetup.cpp =================================================================== --- ps/trunk/source/ps/GameSetup/GameSetup.cpp +++ ps/trunk/source/ps/GameSetup/GameSetup.cpp @@ -677,7 +677,7 @@ g_RenderingOptions.ReadConfigAndSetupHooks(); // create renderer - new CRenderer; + new CRenderer(g_VideoMode.GetBackendDevice()); InitInput(); Index: ps/trunk/source/renderer/PostprocManager.h =================================================================== --- ps/trunk/source/renderer/PostprocManager.h +++ ps/trunk/source/renderer/PostprocManager.h @@ -31,7 +31,7 @@ class CPostprocManager { public: - CPostprocManager(); + CPostprocManager(Renderer::Backend::IDevice* device); ~CPostprocManager(); // Returns true if the the manager can be used. @@ -91,6 +91,8 @@ void CreateMultisampleBuffer(); void DestroyMultisampleBuffer(); + Renderer::Backend::IDevice* m_Device = nullptr; + std::unique_ptr m_CaptureFramebuffer; // Two framebuffers, that we flip between at each shader pass. Index: ps/trunk/source/renderer/PostprocManager.cpp =================================================================== --- ps/trunk/source/renderer/PostprocManager.cpp +++ ps/trunk/source/renderer/PostprocManager.cpp @@ -29,7 +29,6 @@ #include "ps/CStrInternStatic.h" #include "ps/Filesystem.h" #include "ps/Game.h" -#include "ps/VideoMode.h" #include "ps/World.h" #include "renderer/backend/IDevice.h" #include "renderer/Renderer.h" @@ -82,9 +81,10 @@ } // anonymous namespace -CPostprocManager::CPostprocManager() - : m_IsInitialized(false), m_PostProcEffect(L"default"), m_WhichBuffer(true), - m_Sharpness(0.3f), m_UsingMultisampleBuffer(false), m_MultisampleCount(0) +CPostprocManager::CPostprocManager(Renderer::Backend::IDevice* device) + : m_Device(device), m_IsInitialized(false), m_PostProcEffect(L"default"), + m_WhichBuffer(true), m_Sharpness(0.3f), m_UsingMultisampleBuffer(false), + m_MultisampleCount(0) { } @@ -95,14 +95,13 @@ bool CPostprocManager::IsEnabled() const { - Renderer::Backend::IDevice* device = g_VideoMode.GetBackendDevice(); const bool isDepthStencilFormatPresent = - device->GetPreferredDepthStencilFormat( + m_Device->GetPreferredDepthStencilFormat( Renderer::Backend::ITexture::Usage::DEPTH_STENCIL_ATTACHMENT, true, true) != Renderer::Backend::Format::UNDEFINED; return g_RenderingOptions.GetPostProc() && - device->GetBackend() != Renderer::Backend::Backend::GL_ARB && + m_Device->GetBackend() != Renderer::Backend::Backend::GL_ARB && isDepthStencilFormatPresent; } @@ -145,7 +144,7 @@ }}; m_VertexInputLayout = g_Renderer.GetVertexInputLayout(attributes); - const uint32_t maxSamples = g_VideoMode.GetBackendDevice()->GetCapabilities().maxSampleCount; + const uint32_t maxSamples = m_Device->GetCapabilities().maxSampleCount; const uint32_t possibleSampleCounts[] = {2, 4, 8, 16}; std::copy_if( std::begin(possibleSampleCounts), std::end(possibleSampleCounts), @@ -182,10 +181,8 @@ { Cleanup(); - Renderer::Backend::IDevice* backendDevice = g_VideoMode.GetBackendDevice(); - #define GEN_BUFFER_RGBA(name, w, h) \ - name = backendDevice->CreateTexture2D( \ + name = m_Device->CreateTexture2D( \ "PostProc" #name, \ Renderer::Backend::ITexture::Usage::SAMPLED | \ Renderer::Backend::ITexture::Usage::COLOR_ATTACHMENT | \ @@ -215,7 +212,7 @@ colorAttachment.loadOp = Renderer::Backend::AttachmentLoadOp::LOAD; colorAttachment.storeOp = Renderer::Backend::AttachmentStoreOp::STORE; colorAttachment.clearColor = CColor{0.0f, 0.0f, 0.0f, 0.0f}; - step.framebuffer = backendDevice->CreateFramebuffer( + step.framebuffer = m_Device->CreateFramebuffer( "BlurScaleSteoFramebuffer", &colorAttachment, nullptr); } width /= 2; @@ -225,10 +222,10 @@ #undef GEN_BUFFER_RGBA // Allocate the Depth/Stencil texture. - m_DepthTex = backendDevice->CreateTexture2D("PostProcDepthTexture", + m_DepthTex = m_Device->CreateTexture2D("PostProcDepthTexture", Renderer::Backend::ITexture::Usage::SAMPLED | Renderer::Backend::ITexture::Usage::DEPTH_STENCIL_ATTACHMENT, - backendDevice->GetPreferredDepthStencilFormat( + m_Device->GetPreferredDepthStencilFormat( Renderer::Backend::ITexture::Usage::SAMPLED | Renderer::Backend::ITexture::Usage::DEPTH_STENCIL_ATTACHMENT, true, true), @@ -249,17 +246,17 @@ depthStencilAttachment.loadOp = Renderer::Backend::AttachmentLoadOp::CLEAR; depthStencilAttachment.storeOp = Renderer::Backend::AttachmentStoreOp::STORE; - m_CaptureFramebuffer = backendDevice->CreateFramebuffer("PostprocCaptureFramebuffer", + m_CaptureFramebuffer = m_Device->CreateFramebuffer("PostprocCaptureFramebuffer", &colorAttachment, &depthStencilAttachment); colorAttachment.texture = m_ColorTex1.get(); colorAttachment.loadOp = Renderer::Backend::AttachmentLoadOp::LOAD; colorAttachment.storeOp = Renderer::Backend::AttachmentStoreOp::STORE; - m_PingFramebuffer = backendDevice->CreateFramebuffer("PostprocPingFramebuffer", + m_PingFramebuffer = m_Device->CreateFramebuffer("PostprocPingFramebuffer", &colorAttachment, nullptr); colorAttachment.texture = m_ColorTex2.get(); - m_PongFramebuffer = backendDevice->CreateFramebuffer("PostprocPongFramebuffer", + m_PongFramebuffer = m_Device->CreateFramebuffer("PostprocPongFramebuffer", &colorAttachment, nullptr); if (!m_CaptureFramebuffer || !m_PingFramebuffer || !m_PongFramebuffer) @@ -479,7 +476,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.GetBackendDevice()->GetBackend() == Renderer::Backend::Backend::GL_ARB; + const bool hasARB = m_Device->GetBackend() == Renderer::Backend::Backend::GL_ARB; const bool hasAA = m_AATech && !hasARB; const bool hasSharp = m_SharpTech && !hasARB; if (!hasEffects && !hasAA && !hasSharp) @@ -549,8 +546,7 @@ void CPostprocManager::UpdateAntiAliasingTechnique() { - Renderer::Backend::IDevice* device = g_VideoMode.GetBackendDevice(); - if (device->GetBackend() == Renderer::Backend::Backend::GL_ARB || !m_IsInitialized) + if (m_Device->GetBackend() == Renderer::Backend::Backend::GL_ARB || !m_IsInitialized) return; CStr newAAName; @@ -580,7 +576,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 (!device->GetCapabilities().multisampling || m_AllowedSampleCounts.empty()) + if (!m_Device->GetCapabilities().multisampling || m_AllowedSampleCounts.empty()) { LOGWARNING("MSAA is unsupported."); return; @@ -590,7 +586,7 @@ if (std::find(std::begin(m_AllowedSampleCounts), std::end(m_AllowedSampleCounts), m_MultisampleCount) == std::end(m_AllowedSampleCounts)) { - m_MultisampleCount = std::min(4u, device->GetCapabilities().maxSampleCount); + m_MultisampleCount = std::min(4u, m_Device->GetCapabilities().maxSampleCount); LOGWARNING("Wrong MSAA sample count: %s.", m_AAName.EscapeToPrintableASCII().c_str()); } m_UsingMultisampleBuffer = true; @@ -600,7 +596,7 @@ void CPostprocManager::UpdateSharpeningTechnique() { - if (g_VideoMode.GetBackendDevice()->GetBackend() == Renderer::Backend::Backend::GL_ARB || !m_IsInitialized) + if (m_Device->GetBackend() == Renderer::Backend::Backend::GL_ARB || !m_IsInitialized) return; CStr newSharpName; @@ -629,9 +625,7 @@ void CPostprocManager::CreateMultisampleBuffer() { - Renderer::Backend::IDevice* backendDevice = g_VideoMode.GetBackendDevice(); - - m_MultisampleColorTex = backendDevice->CreateTexture("PostProcColorMS", + m_MultisampleColorTex = m_Device->CreateTexture("PostProcColorMS", Renderer::Backend::ITexture::Type::TEXTURE_2D_MULTISAMPLE, Renderer::Backend::ITexture::Usage::COLOR_ATTACHMENT | Renderer::Backend::ITexture::Usage::TRANSFER_SRC, @@ -641,11 +635,11 @@ Renderer::Backend::Sampler::AddressMode::CLAMP_TO_EDGE), 1, m_MultisampleCount); // Allocate the Depth/Stencil texture. - m_MultisampleDepthTex = backendDevice->CreateTexture("PostProcDepthMS", + m_MultisampleDepthTex = m_Device->CreateTexture("PostProcDepthMS", Renderer::Backend::ITexture::Type::TEXTURE_2D_MULTISAMPLE, Renderer::Backend::ITexture::Usage::DEPTH_STENCIL_ATTACHMENT | Renderer::Backend::ITexture::Usage::TRANSFER_SRC, - backendDevice->GetPreferredDepthStencilFormat( + m_Device->GetPreferredDepthStencilFormat( Renderer::Backend::ITexture::Usage::DEPTH_STENCIL_ATTACHMENT | Renderer::Backend::ITexture::Usage::TRANSFER_SRC, true, true), @@ -666,7 +660,7 @@ depthStencilAttachment.loadOp = Renderer::Backend::AttachmentLoadOp::CLEAR; depthStencilAttachment.storeOp = Renderer::Backend::AttachmentStoreOp::STORE; - m_MultisampleFramebuffer = backendDevice->CreateFramebuffer( + m_MultisampleFramebuffer = m_Device->CreateFramebuffer( "PostprocMultisampleFramebuffer", &colorAttachment, &depthStencilAttachment); if (!m_MultisampleFramebuffer) Index: ps/trunk/source/renderer/Renderer.h =================================================================== --- ps/trunk/source/renderer/Renderer.h +++ ps/trunk/source/renderer/Renderer.h @@ -77,7 +77,7 @@ }; public: - CRenderer(); + CRenderer(Renderer::Backend::IDevice* device); ~CRenderer(); // open up the renderer: performs any necessary initialisation Index: ps/trunk/source/renderer/Renderer.cpp =================================================================== --- ps/trunk/source/renderer/Renderer.cpp +++ ps/trunk/source/renderer/Renderer.cpp @@ -243,6 +243,8 @@ { NONCOPYABLE(Internals); public: + Renderer::Backend::IDevice* device; + std::unique_ptr deviceCommandContext; /// true if CRenderer::Open has been called @@ -281,10 +283,12 @@ std::vector, std::unique_ptr, VertexAttributesHash> vertexInputLayouts; - Internals() : + Internals(Renderer::Backend::IDevice* device) : + device(device), + deviceCommandContext(device->CreateCommandContext()), IsOpen(false), ShadersDirty(true), profileTable(g_Renderer.m_Stats), - deviceCommandContext(g_VideoMode.GetBackendDevice()->CreateCommandContext()), - textureManager(g_VFS, false, g_VideoMode.GetBackendDevice()) + shaderManager(device), textureManager(g_VFS, false, device), + postprocManager(device), sceneRenderer(device) { } }; @@ -306,11 +310,11 @@ return seed; } -CRenderer::CRenderer() +CRenderer::CRenderer(Renderer::Backend::IDevice* device) { TIMER(L"InitRenderer"); - m = std::make_unique(); + m = std::make_unique(device); g_ProfileViewer.AddRootTable(&m->profileTable); @@ -320,7 +324,7 @@ m_Stats.Reset(); // Create terrain related stuff. - new CTerrainTextureManager; + new CTerrainTextureManager(device); Open(g_xres, g_yres); @@ -348,7 +352,7 @@ { ENSURE(m->IsOpen); - m->sceneRenderer.ReloadShaders(); + m->sceneRenderer.ReloadShaders(m->device); m->ShadersDirty = false; } @@ -393,8 +397,8 @@ // Renderer has been opened, so validate the selected renderpath const bool hasShadersSupport = - g_VideoMode.GetBackendDevice()->GetCapabilities().ARBShaders || - g_VideoMode.GetBackendDevice()->GetBackend() != Renderer::Backend::Backend::GL_ARB; + m->device->GetCapabilities().ARBShaders || + m->device->GetBackend() != Renderer::Backend::Backend::GL_ARB; if (rp == RenderPath::DEFAULT) { if (hasShadersSupport) @@ -443,7 +447,7 @@ if (needsPresent) { // In case of no acquired backbuffer we have nothing render to. - if (!g_VideoMode.GetBackendDevice()->AcquireNextBackbuffer()) + if (!m->device->AcquireNextBackbuffer()) return; } @@ -458,7 +462,7 @@ m->deviceCommandContext->Flush(); if (needsPresent) - g_VideoMode.GetBackendDevice()->Present(); + m->device->Present(); } } @@ -651,7 +655,7 @@ const size_t width = static_cast(g_xres), height = static_cast(g_yres); const size_t bpp = 24; - if (needsPresent && !g_VideoMode.GetBackendDevice()->AcquireNextBackbuffer()) + if (needsPresent && !m->device->AcquireNextBackbuffer()) return; // Hide log messages and re-render @@ -669,7 +673,7 @@ m->deviceCommandContext->ReadbackFramebufferSync(0, 0, width, height, img); m->deviceCommandContext->Flush(); if (needsPresent) - g_VideoMode.GetBackendDevice()->Present(); + m->device->Present(); if (tex_write(&t, filename) == INFO::OK) { @@ -768,7 +772,7 @@ } g_Game->GetView()->GetCamera()->SetProjection(projection); - if (!needsPresent || g_VideoMode.GetBackendDevice()->AcquireNextBackbuffer()) + if (!needsPresent || m->device->AcquireNextBackbuffer()) { RenderFrameImpl(false, false); @@ -776,7 +780,7 @@ m->deviceCommandContext->Flush(); if (needsPresent) - g_VideoMode.GetBackendDevice()->Present(); + m->device->Present(); } // Copy the tile pixels into the main image @@ -896,6 +900,6 @@ const auto [it, inserted] = m->vertexInputLayouts.emplace( std::vector{attributes.begin(), attributes.end()}, nullptr); if (inserted) - it->second = g_VideoMode.GetBackendDevice()->CreateVertexInputLayout(attributes); + it->second = m->device->CreateVertexInputLayout(attributes); return it->second.get(); } Index: ps/trunk/source/renderer/SceneRenderer.h =================================================================== --- ps/trunk/source/renderer/SceneRenderer.h +++ ps/trunk/source/renderer/SceneRenderer.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -65,7 +65,7 @@ CULL_MAX }; - CSceneRenderer(); + CSceneRenderer(Renderer::Backend::IDevice* device); ~CSceneRenderer(); void Initialize(); @@ -195,7 +195,7 @@ */ void ResetState(); - void ReloadShaders(); + void ReloadShaders(Renderer::Backend::IDevice* device); protected: void Submit(CPatch* patch) override; Index: ps/trunk/source/renderer/SceneRenderer.cpp =================================================================== --- ps/trunk/source/renderer/SceneRenderer.cpp +++ ps/trunk/source/renderer/SceneRenderer.cpp @@ -42,7 +42,6 @@ #include "ps/CStrInternStatic.h" #include "ps/Game.h" #include "ps/Profile.h" -#include "ps/VideoMode.h" #include "ps/World.h" #include "renderer/backend/IDevice.h" #include "renderer/DebugRenderer.h" @@ -76,7 +75,11 @@ { NONCOPYABLE(Internals); public: - Internals() = default; + Internals(Renderer::Backend::IDevice* device) + : waterManager(device), shadow(device) + { + } + ~Internals() = default; /// Water manager @@ -186,9 +189,9 @@ } }; -CSceneRenderer::CSceneRenderer() +CSceneRenderer::CSceneRenderer(Renderer::Backend::IDevice* device) { - m = std::make_unique(); + m = std::make_unique(device); m_TerrainRenderMode = SOLID; m_WaterRenderMode = SOLID; @@ -210,12 +213,10 @@ m.reset(); } -void CSceneRenderer::ReloadShaders() +void CSceneRenderer::ReloadShaders(Renderer::Backend::IDevice* device) { m->globalContext = CShaderDefines(); - Renderer::Backend::IDevice* device = g_VideoMode.GetBackendDevice(); - if (g_RenderingOptions.GetShadows()) { m->globalContext.Add(str_USE_SHADOW, str_1); @@ -567,7 +568,7 @@ // Save the model-view-projection matrix so the shaders can use it for projective texturing wm.m_ReflectionMatrix = m_ViewCamera.GetViewProjection(); - if (g_VideoMode.GetBackendDevice()->GetBackend() == Renderer::Backend::Backend::VULKAN) + if (deviceCommandContext->GetDevice()->GetBackend() == Renderer::Backend::Backend::VULKAN) { CMatrix3D flip; flip.SetIdentity(); @@ -650,7 +651,7 @@ wm.m_RefractionProjInvMatrix = m_ViewCamera.GetProjection().GetInverse(); wm.m_RefractionViewInvMatrix = m_ViewCamera.GetOrientation(); - if (g_VideoMode.GetBackendDevice()->GetBackend() == Renderer::Backend::Backend::VULKAN) + if (deviceCommandContext->GetDevice()->GetBackend() == Renderer::Backend::Backend::VULKAN) { CMatrix3D flip; flip.SetIdentity(); Index: ps/trunk/source/renderer/ShadowMap.h =================================================================== --- ps/trunk/source/renderer/ShadowMap.h +++ ps/trunk/source/renderer/ShadowMap.h @@ -38,7 +38,7 @@ class ShadowMap { public: - ShadowMap(); + ShadowMap(Renderer::Backend::IDevice* device); ~ShadowMap(); /** Index: ps/trunk/source/renderer/ShadowMap.cpp =================================================================== --- ps/trunk/source/renderer/ShadowMap.cpp +++ ps/trunk/source/renderer/ShadowMap.cpp @@ -32,7 +32,6 @@ #include "ps/ConfigDB.h" #include "ps/CStrInternStatic.h" #include "ps/Profile.h" -#include "ps/VideoMode.h" #include "renderer/backend/IDevice.h" #include "renderer/backend/ITexture.h" #include "renderer/DebugRenderer.h" @@ -57,6 +56,8 @@ */ struct ShadowMapInternals { + Renderer::Backend::IDevice* Device = nullptr; + std::unique_ptr Framebuffer; std::unique_ptr Texture; @@ -124,7 +125,7 @@ CascadeCount = 1; CFG_GET_VAL("shadowscascadecount", CascadeCount); - if (CascadeCount < 1 || CascadeCount > MAX_CASCADE_COUNT || g_VideoMode.GetBackendDevice()->GetBackend() == Renderer::Backend::Backend::GL_ARB) + if (CascadeCount < 1 || CascadeCount > MAX_CASCADE_COUNT || Device->GetBackend() == Renderer::Backend::Backend::GL_ARB) CascadeCount = 1; ShadowsCoverMap = false; @@ -183,9 +184,10 @@ bbaa->Expand(insets); } -ShadowMap::ShadowMap() +ShadowMap::ShadowMap(Renderer::Backend::IDevice* device) { m = new ShadowMapInternals; + m->Device = device; m->Framebuffer = 0; m->Width = 0; m->Height = 0; @@ -460,7 +462,7 @@ lightToTex._34 = -shadowRenderBound[0].Z * texscalez; lightToTex._44 = 1.0; - if (g_VideoMode.GetBackendDevice()->GetBackend() == Renderer::Backend::Backend::VULKAN) + if (Device->GetBackend() == Renderer::Backend::Backend::VULKAN) { CMatrix3D flip; flip.SetIdentity(); @@ -480,8 +482,6 @@ Texture.reset(); DummyTexture.reset(); - Renderer::Backend::IDevice* backendDevice = g_VideoMode.GetBackendDevice(); - CFG_GET_VAL("shadowquality", QualityLevel); // Get shadow map size as next power of two up from view width/height. @@ -508,7 +508,7 @@ // Clamp to the maximum texture size. shadowMapSize = std::min( - shadowMapSize, static_cast(backendDevice->GetCapabilities().maxTextureSize)); + shadowMapSize, static_cast(Device->GetCapabilities().maxTextureSize)); Width = Height = shadowMapSize; @@ -529,7 +529,7 @@ case 32: formatName = "Format::D32_SFLOAT"; backendFormat = Renderer::Backend::Format::D32_SFLOAT; break; default: formatName = "Default"; - backendFormat = backendDevice->GetPreferredDepthStencilFormat( + backendFormat = Device->GetPreferredDepthStencilFormat( Renderer::Backend::ITexture::Usage::SAMPLED | Renderer::Backend::ITexture::Usage::DEPTH_STENCIL_ATTACHMENT, true, false); @@ -543,7 +543,7 @@ if (g_RenderingOptions.GetShadowAlphaFix()) { - DummyTexture = backendDevice->CreateTexture2D("ShadowMapDummy", + DummyTexture = Device->CreateTexture2D("ShadowMapDummy", Renderer::Backend::ITexture::Usage::COLOR_ATTACHMENT, Renderer::Backend::Format::R8G8B8A8_UNORM, Width, Height, Renderer::Backend::Sampler::MakeDefaultSampler( @@ -566,7 +566,7 @@ samplerDesc.compareEnabled = true; samplerDesc.compareOp = Renderer::Backend::CompareOp::LESS_OR_EQUAL; - Texture = backendDevice->CreateTexture2D("ShadowMapDepth", + Texture = Device->CreateTexture2D("ShadowMapDepth", Renderer::Backend::ITexture::Usage::SAMPLED | Renderer::Backend::ITexture::Usage::DEPTH_STENCIL_ATTACHMENT, backendFormat, Width, Height, samplerDesc); @@ -587,7 +587,7 @@ depthStencilAttachment.loadOp = Renderer::Backend::AttachmentLoadOp::CLEAR; depthStencilAttachment.storeOp = Renderer::Backend::AttachmentStoreOp::STORE; - Framebuffer = backendDevice->CreateFramebuffer("ShadowMapFramebuffer", + Framebuffer = Device->CreateFramebuffer("ShadowMapFramebuffer", useDummyTexture ? &colorAttachment : nullptr, &depthStencilAttachment); if (!Framebuffer) { Index: ps/trunk/source/renderer/SkyManager.cpp =================================================================== --- ps/trunk/source/renderer/SkyManager.cpp +++ ps/trunk/source/renderer/SkyManager.cpp @@ -32,7 +32,6 @@ #include "ps/CStrInternStatic.h" #include "ps/Filesystem.h" #include "ps/Game.h" -#include "ps/VideoMode.h" #include "renderer/backend/IDevice.h" #include "renderer/Renderer.h" #include "renderer/SceneRenderer.h" @@ -121,7 +120,7 @@ } std::unique_ptr skyCubeMap = - g_VideoMode.GetBackendDevice()->CreateTexture("SkyCubeMap", + deviceCommandContext->GetDevice()->CreateTexture("SkyCubeMap", Renderer::Backend::ITexture::Type::TEXTURE_CUBE, Renderer::Backend::ITexture::Usage::TRANSFER_DST | Renderer::Backend::ITexture::Usage::SAMPLED, Index: ps/trunk/source/renderer/WaterManager.h =================================================================== --- ps/trunk/source/renderer/WaterManager.h +++ ps/trunk/source/renderer/WaterManager.h @@ -130,7 +130,7 @@ float m_WindAngle; // In which direction the water waves go. public: - WaterManager(); + WaterManager(Renderer::Backend::IDevice* device); ~WaterManager(); void Initialize(); @@ -207,6 +207,9 @@ */ size_t GetCurrentTextureIndex(const double& period) const; size_t GetNextTextureIndex(const double& period) const; + +private: + Renderer::Backend::IDevice* m_Device = nullptr; }; Index: ps/trunk/source/renderer/WaterManager.cpp =================================================================== --- ps/trunk/source/renderer/WaterManager.cpp +++ ps/trunk/source/renderer/WaterManager.cpp @@ -28,7 +28,6 @@ #include "ps/CLogger.h" #include "ps/CStrInternStatic.h" #include "ps/Game.h" -#include "ps/VideoMode.h" #include "ps/World.h" #include "renderer/backend/IDevice.h" #include "renderer/Renderer.h" @@ -69,7 +68,8 @@ float m_TimeDiff; }; -WaterManager::WaterManager() +WaterManager::WaterManager(Renderer::Backend::IDevice* device) + : m_Device(device) { // water m_RenderWater = false; // disabled until textures are successfully loaded @@ -214,8 +214,6 @@ void WaterManager::RecreateOrLoadTexturesIfNeeded() { - Renderer::Backend::IDevice* backendDevice = g_VideoMode.GetBackendDevice(); - // Use screen-sized textures for minimum artifacts. const size_t newRefTextureSize = round_up_to_pow2(g_Renderer.GetHeight()); @@ -233,7 +231,7 @@ } const Renderer::Backend::Format depthFormat = - backendDevice->GetPreferredDepthStencilFormat( + m_Device->GetPreferredDepthStencilFormat( Renderer::Backend::ITexture::Usage::SAMPLED | Renderer::Backend::ITexture::Usage::DEPTH_STENCIL_ATTACHMENT, true, false); @@ -244,7 +242,7 @@ g_RenderingOptions.GetWaterReflection(); if (needsReflectionTextures && !m_ReflectionTexture) { - m_ReflectionTexture = backendDevice->CreateTexture2D("WaterReflectionTexture", + m_ReflectionTexture = m_Device->CreateTexture2D("WaterReflectionTexture", Renderer::Backend::ITexture::Usage::SAMPLED | Renderer::Backend::ITexture::Usage::COLOR_ATTACHMENT, Renderer::Backend::Format::R8G8B8A8_UNORM, m_RefTextureSize, m_RefTextureSize, @@ -252,7 +250,7 @@ Renderer::Backend::Sampler::Filter::LINEAR, Renderer::Backend::Sampler::AddressMode::MIRRORED_REPEAT)); - m_ReflFboDepthTexture = backendDevice->CreateTexture2D("WaterReflectionDepthTexture", + m_ReflFboDepthTexture = m_Device->CreateTexture2D("WaterReflectionDepthTexture", Renderer::Backend::ITexture::Usage::SAMPLED | Renderer::Backend::ITexture::Usage::DEPTH_STENCIL_ATTACHMENT, depthFormat, m_RefTextureSize, m_RefTextureSize, @@ -271,7 +269,7 @@ depthStencilAttachment.loadOp = Renderer::Backend::AttachmentLoadOp::CLEAR; depthStencilAttachment.storeOp = Renderer::Backend::AttachmentStoreOp::STORE; - m_ReflectionFramebuffer = backendDevice->CreateFramebuffer("ReflectionFramebuffer", + m_ReflectionFramebuffer = m_Device->CreateFramebuffer("ReflectionFramebuffer", &colorAttachment, &depthStencilAttachment); if (!m_ReflectionFramebuffer) { @@ -286,7 +284,7 @@ g_RenderingOptions.GetWaterRefraction(); if (needsRefractionTextures && !m_RefractionTexture) { - m_RefractionTexture = backendDevice->CreateTexture2D("WaterRefractionTexture", + m_RefractionTexture = m_Device->CreateTexture2D("WaterRefractionTexture", Renderer::Backend::ITexture::Usage::SAMPLED | Renderer::Backend::ITexture::Usage::COLOR_ATTACHMENT, Renderer::Backend::Format::R8G8B8A8_UNORM, m_RefTextureSize, m_RefTextureSize, @@ -294,7 +292,7 @@ Renderer::Backend::Sampler::Filter::LINEAR, Renderer::Backend::Sampler::AddressMode::MIRRORED_REPEAT)); - m_RefrFboDepthTexture = backendDevice->CreateTexture2D("WaterRefractionDepthTexture", + m_RefrFboDepthTexture = m_Device->CreateTexture2D("WaterRefractionDepthTexture", Renderer::Backend::ITexture::Usage::SAMPLED | Renderer::Backend::ITexture::Usage::DEPTH_STENCIL_ATTACHMENT, depthFormat, m_RefTextureSize, m_RefTextureSize, @@ -313,7 +311,7 @@ depthStencilAttachment.loadOp = Renderer::Backend::AttachmentLoadOp::CLEAR; depthStencilAttachment.storeOp = Renderer::Backend::AttachmentStoreOp::STORE; - m_RefractionFramebuffer = backendDevice->CreateFramebuffer("RefractionFramebuffer", + m_RefractionFramebuffer = m_Device->CreateFramebuffer("RefractionFramebuffer", &colorAttachment, &depthStencilAttachment); if (!m_RefractionFramebuffer) { @@ -338,7 +336,7 @@ g_RenderingOptions.GetWaterFancyEffects(); if (needsFancyTextures && !m_FancyTexture) { - m_FancyTexture = backendDevice->CreateTexture2D("WaterFancyTexture", + m_FancyTexture = m_Device->CreateTexture2D("WaterFancyTexture", Renderer::Backend::ITexture::Usage::SAMPLED | Renderer::Backend::ITexture::Usage::COLOR_ATTACHMENT, Renderer::Backend::Format::R8G8B8A8_UNORM, g_Renderer.GetWidth(), g_Renderer.GetHeight(), @@ -346,7 +344,7 @@ Renderer::Backend::Sampler::Filter::LINEAR, Renderer::Backend::Sampler::AddressMode::REPEAT)); - m_FancyTextureDepth = backendDevice->CreateTexture2D("WaterFancyDepthTexture", + m_FancyTextureDepth = m_Device->CreateTexture2D("WaterFancyDepthTexture", Renderer::Backend::ITexture::Usage::DEPTH_STENCIL_ATTACHMENT, depthFormat, g_Renderer.GetWidth(), g_Renderer.GetHeight(), Renderer::Backend::Sampler::MakeDefaultSampler( @@ -365,7 +363,7 @@ // We need to store depth for later rendering occluders. depthStencilAttachment.storeOp = Renderer::Backend::AttachmentStoreOp::STORE; - m_FancyEffectsFramebuffer = backendDevice->CreateFramebuffer("FancyEffectsFramebuffer", + m_FancyEffectsFramebuffer = m_Device->CreateFramebuffer("FancyEffectsFramebuffer", &colorAttachment, &depthStencilAttachment); Renderer::Backend::SColorAttachment occludersColorAttachment{}; @@ -379,7 +377,7 @@ occludersDepthStencilAttachment.loadOp = Renderer::Backend::AttachmentLoadOp::LOAD; occludersDepthStencilAttachment.storeOp = Renderer::Backend::AttachmentStoreOp::DONT_CARE; - m_FancyEffectsOccludersFramebuffer = backendDevice->CreateFramebuffer("FancyEffectsOccludersFramebuffer", + m_FancyEffectsOccludersFramebuffer = m_Device->CreateFramebuffer("FancyEffectsOccludersFramebuffer", &occludersColorAttachment, &occludersDepthStencilAttachment); if (!m_FancyEffectsFramebuffer || !m_FancyEffectsOccludersFramebuffer) { @@ -1129,7 +1127,7 @@ bool WaterManager::WillRenderFancyWater() const { return - m_RenderWater && g_VideoMode.GetBackendDevice()->GetBackend() != Renderer::Backend::Backend::GL_ARB && + m_RenderWater && m_Device->GetBackend() != Renderer::Backend::Backend::GL_ARB && g_RenderingOptions.GetWaterEffects(); } Index: ps/trunk/source/tools/atlas/GameInterface/ActorViewer.cpp =================================================================== --- ps/trunk/source/tools/atlas/GameInterface/ActorViewer.cpp +++ ps/trunk/source/tools/atlas/GameInterface/ActorViewer.cpp @@ -81,7 +81,7 @@ ObjectManager(MeshManager, SkeletonAnimManager, Simulation2), LOSTexture(Simulation2), TerritoryTexture(Simulation2), - MiniMapTexture(Simulation2) + MiniMapTexture(g_VideoMode.GetBackendDevice(), Simulation2) { UnitManager.SetObjectManager(ObjectManager); }