Files
FlaxEngine/Source/Engine/Graphics/Graphics.cpp
Wojtek Figat 98834131f1 Add smooth shadows blending between directional light cascades
It was deprecated in 1.9 in favor for dithering between cascades. Bing back that option for games that don't use TAA.
2025-03-27 10:48:35 +01:00

235 lines
6.2 KiB
C++

// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
#include "Graphics.h"
#include "GPUDevice.h"
#include "PixelFormatExtensions.h"
#include "Async/GPUTasksManager.h"
#include "Engine/Core/Log.h"
#include "Engine/Core/Config/GraphicsSettings.h"
#include "Engine/Engine/CommandLine.h"
#include "Engine/Engine/EngineService.h"
#include "Engine/Profiler/ProfilerGPU.h"
#include "Engine/Render2D/Font.h"
bool Graphics::UseVSync = false;
Quality Graphics::AAQuality = Quality::Medium;
Quality Graphics::SSRQuality = Quality::Medium;
Quality Graphics::SSAOQuality = Quality::Medium;
Quality Graphics::VolumetricFogQuality = Quality::High;
Quality Graphics::ShadowsQuality = Quality::Medium;
Quality Graphics::ShadowMapsQuality = Quality::Medium;
float Graphics::ShadowUpdateRate = 1.0f;
bool Graphics::AllowCSMBlending = false;
Quality Graphics::GlobalSDFQuality = Quality::High;
Quality Graphics::GIQuality = Quality::High;
bool Graphics::GICascadesBlending = false;
PostProcessSettings Graphics::PostProcessSettings;
bool Graphics::SpreadWorkload = true;
#if GRAPHICS_API_NULL
extern GPUDevice* CreateGPUDeviceNull();
#endif
#if GRAPHICS_API_VULKAN
extern GPUDevice* CreateGPUDeviceVulkan();
#endif
#if GRAPHICS_API_DIRECTX11
extern GPUDevice* CreateGPUDeviceDX11();
#endif
#if GRAPHICS_API_DIRECTX12
extern GPUDevice* CreateGPUDeviceDX12();
#endif
#if GRAPHICS_API_PS4
extern GPUDevice* CreateGPUDevicePS4();
#endif
#if GRAPHICS_API_PS5
extern GPUDevice* CreateGPUDevicePS5();
#endif
class GraphicsService : public EngineService
{
public:
GraphicsService()
: EngineService(TEXT("Graphics"), -40)
{
}
bool Init() override;
void BeforeExit() override;
void Dispose() override;
};
GraphicsService GraphicsServiceInstance;
void GraphicsSettings::Apply()
{
Graphics::UseVSync = UseVSync;
Graphics::AAQuality = AAQuality;
Graphics::SSRQuality = SSRQuality;
Graphics::SSAOQuality = SSAOQuality;
Graphics::VolumetricFogQuality = VolumetricFogQuality;
Graphics::ShadowsQuality = ShadowsQuality;
Graphics::ShadowMapsQuality = ShadowMapsQuality;
Graphics::AllowCSMBlending = AllowCSMBlending;
Graphics::GlobalSDFQuality = GlobalSDFQuality;
Graphics::GIQuality = GIQuality;
Graphics::GICascadesBlending = GICascadesBlending;
Graphics::PostProcessSettings = ::PostProcessSettings();
Graphics::PostProcessSettings.BlendWith(PostProcessSettings, 1.0f);
#if !USE_EDITOR // OptionsModule handles fallback fonts in Editor
Font::FallbackFonts = FallbackFonts;
#endif
}
void Graphics::DisposeDevice()
{
if (GPUDevice::Instance)
{
// Clean any danging pointer to last task (might stay if engine is disposing after crash)
GPUDevice::Instance->CurrentTask = nullptr;
GPUDevice::Instance->Dispose();
LOG_FLUSH();
Delete(GPUDevice::Instance);
GPUDevice::Instance = nullptr;
}
}
bool GraphicsService::Init()
{
ASSERT(GPUDevice::Instance == nullptr);
// Create and initialize graphics device
Log::Logger::WriteFloor();
LOG(Info, "Creating Graphics Device...");
PixelFormatExtensions::Init();
GPUDevice* device = nullptr;
// Null
if (!device && CommandLine::Options.Null.IsTrue())
{
#if GRAPHICS_API_NULL
device = CreateGPUDeviceNull();
#else
LOG(Warning, "Null backend not available");
#endif
}
// Vulkan
if (!device && CommandLine::Options.Vulkan.IsTrue())
{
#if GRAPHICS_API_VULKAN
device = CreateGPUDeviceVulkan();
#else
LOG(Warning, "Vulkan backend not available");
#endif
}
// DirectX 12
if (!device && CommandLine::Options.D3D12.IsTrue())
{
#if GRAPHICS_API_DIRECTX12
if (Platform::IsWindows10())
{
device = CreateGPUDeviceDX12();
}
#else
LOG(Warning, "DirectX 12 backend not available");
#endif
}
// DirectX 11 and DirectX 10
if (!device && (CommandLine::Options.D3D11.IsTrue() || CommandLine::Options.D3D10.IsTrue()))
{
#if GRAPHICS_API_DIRECTX11
device = CreateGPUDeviceDX11();
#else
LOG(Warning, "DirectX 11 backend not available");
#endif
}
// Platform default
if (!device)
{
#if GRAPHICS_API_DIRECTX11
if (!device)
device = CreateGPUDeviceDX11();
#endif
#if GRAPHICS_API_DIRECTX12
if (!device && Platform::IsWindows10())
device = CreateGPUDeviceDX12();
#endif
#if GRAPHICS_API_VULKAN
if (!device)
device = CreateGPUDeviceVulkan();
#endif
#if GRAPHICS_API_PS4
if (!device)
device = CreateGPUDevicePS4();
#endif
#if GRAPHICS_API_PS5
if (!device)
device = CreateGPUDevicePS5();
#endif
}
// Null as a fallback
#if GRAPHICS_API_NULL
if (!device)
device = CreateGPUDeviceNull();
#endif
if (device == nullptr)
{
return true;
}
GPUDevice::Instance = device;
LOG(Info, "GPU Device created: {}", device->GetAdapter()->GetDescription());
LOG(Info, "Renderer: {}, Shader Profile: {}, Feature Level: {}, Driver: {}",
::ToString(device->GetRendererType()),
::ToString(device->GetShaderProfile()),
::ToString(device->GetFeatureLevel()),
device->GetAdapter()->GetDriverVersion().ToString()
);
// Initialize
if (device->IsDebugToolAttached
#if USE_EDITOR || !BUILD_RELEASE
|| CommandLine::Options.ShaderProfile.IsTrue()
#endif
#if USE_EDITOR
|| CommandLine::Options.ShaderDebug.IsTrue()
#endif
)
{
#if !USE_EDITOR && BUILD_RELEASE && !PLATFORM_LINUX // IsDebugToolAttached seams to be enabled on many Linux machines via VK_EXT_tooling_info
// Block graphics debugging to protect contents
Platform::Fatal(TEXT("Graphics debugger attached."));
#endif
#if COMPILE_WITH_PROFILER
// Auto-enable GPU events
ProfilerGPU::EventsEnabled = true;
#endif
}
if (device->LoadContent())
{
return true;
}
Log::Logger::WriteFloor();
return false;
}
void GraphicsService::BeforeExit()
{
if (GPUDevice::Instance)
{
// Start disposing
GPUDevice::Instance->GetTasksManager()->Dispose();
}
}
void GraphicsService::Dispose()
{
// Device is disposed AFTER Content (faster and safer because there is no assets so there is less gpu resources to cleanup)
}