// Copyright (C) 2017 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp #include #include #include #include #include #include #include #include #include #include #include namespace Nz { bool Renderer::Initialize() { if (s_moduleReferenceCounter > 0) { s_moduleReferenceCounter++; return true; // Already initialized } // Initialize module dependencies if (!Utility::Initialize()) { NazaraError("Failed to initialize Utility module"); return false; } if (!Platform::Initialize()) { NazaraError("Failed to initialize Platform module"); return false; } s_moduleReferenceCounter++; CallOnExit onExit(Renderer::Uninitialize); NazaraDebug("Searching for renderer implementation"); Directory dir("."); dir.SetPattern("Nazara?*Renderer*" NAZARA_DYNLIB_EXTENSION); //< Ex: NazaraVulkanRenderer.dll if (!dir.Open()) { NazaraError("Failed to open directory"); return false; } DynLib chosenLib; std::unique_ptr chosenImpl; while (dir.NextResult()) { NazaraDebug("Trying to load " + dir.GetResultName()); DynLib implLib; if (!implLib.Load(dir.GetResultPath())) { NazaraWarning("Failed to load " + dir.GetResultName() + ": " + implLib.GetLastError()); continue; } CreateRendererImplFunc createRenderer = reinterpret_cast(implLib.GetSymbol("NazaraRenderer_Instantiate")); if (!createRenderer) { NazaraDebug("Skipped " + dir.GetResultName() + " (symbol not found)"); continue; } std::unique_ptr impl(createRenderer()); if (!impl || !impl->Prepare(s_initializationParameters)) { NazaraError("Failed to create renderer implementation"); continue; } NazaraDebug("Loaded " + impl->QueryAPIString()); if (!chosenImpl || impl->IsBetterThan(chosenImpl.get())) { if (chosenImpl) NazaraDebug("Choose " + impl->QueryAPIString() + " over " + chosenImpl->QueryAPIString()); chosenLib = std::move(implLib); chosenImpl = std::move(impl); } } if (!chosenImpl) { NazaraError("No renderer found"); return false; } s_rendererImpl = std::move(chosenImpl); s_rendererLib = std::move(chosenLib); NazaraDebug("Using " + s_rendererImpl->QueryAPIString() + " as renderer"); Buffer::SetBufferFactory(DataStorage_Hardware, CreateHardwareBufferImpl); onExit.Reset(); NazaraNotice("Initialized: Renderer module"); return true; } void Renderer::Uninitialize() { if (s_moduleReferenceCounter != 1) { // Either the module is not initialized, either it was initialized multiple times if (s_moduleReferenceCounter > 1) s_moduleReferenceCounter--; return; } s_moduleReferenceCounter = 0; // Uninitialize module here Buffer::SetBufferFactory(DataStorage_Hardware, nullptr); s_rendererImpl.reset(); s_rendererLib.Unload(); NazaraNotice("Uninitialized: Renderer module"); // Free module dependencies Platform::Uninitialize(); Utility::Uninitialize(); } AbstractBuffer* Renderer::CreateHardwareBufferImpl(Buffer* parent, BufferType type) { return new RenderBuffer(parent, type); } std::unique_ptr Renderer::s_rendererImpl; DynLib Renderer::s_rendererLib; ParameterList Renderer::s_initializationParameters; unsigned int Renderer::s_moduleReferenceCounter = 0; }