Files
WickedEngine/WickedEngine/MainComponent.cpp
T
Turánszki János f3687dbf4e DX11 removal, Surfel GI
version 0.57.0:
- DX11 removed, DX12 is default now on Windows
- graphics interfaces improved:
	- Bindless descriptor support is now assumed
	- GPU Buffers with USAGE_UPLOAD and USAGE_READBACK will be persistently mapped after creation
	- Removed Map/Unmap
	- added BindDynamicConstantBuffer helper function
	- improved AllocateGPU helper function
	- GPU Queries resolving can be done directly into GPUBuffer
	- UpdateBuffer now doesn't synchronize internally, this allows batching updates
	- removed support for bindless constant buffers (uniform buffers)
	- BindConstantBuffer will accept offset
	- RESOURCE_STATES refactor, they can be combined now in the barriers
	- many other refactors
- gbuffer normals removed, implemented visibility buffer
- bindless decals, bindless lightmaps, bindless hair particles, bindless software path tracing
- hair particles path tracing support
- path tracing eye adaption supported
- Surfel GI (experimental)
2021-09-05 18:59:03 +02:00

412 lines
9.8 KiB
C++

#include "MainComponent.h"
#include "RenderPath.h"
#include "wiRenderer.h"
#include "wiHelper.h"
#include "wiTimer.h"
#include "wiInput.h"
#include "wiBackLog.h"
#include "MainComponent_BindLua.h"
#include "wiVersion.h"
#include "wiEnums.h"
#include "wiTextureHelper.h"
#include "wiProfiler.h"
#include "wiInitializer.h"
#include "wiStartupArguments.h"
#include "wiFont.h"
#include "wiImage.h"
#include "wiEvent.h"
#include "wiGraphicsDevice_DX12.h"
#include "wiGraphicsDevice_Vulkan.h"
#include "Utility/replace_new.h"
#include <sstream>
#include <algorithm>
using namespace wiGraphics;
void MainComponent::Initialize()
{
if (initialized)
{
return;
}
initialized = true;
wiInitializer::InitializeComponentsAsync();
}
void MainComponent::ActivatePath(RenderPath* component, float fadeSeconds, wiColor fadeColor)
{
if (component != nullptr)
{
component->init(canvas);
}
// Fade manager will activate on fadeout
fadeManager.Clear();
fadeManager.Start(fadeSeconds, fadeColor, [this, component]() {
if (GetActivePath() != nullptr)
{
GetActivePath()->Stop();
}
if (component != nullptr)
{
component->Start();
}
activePath = component;
});
fadeManager.Update(0); // If user calls ActivatePath without fadeout, it will be instant
}
void MainComponent::Run()
{
if (!initialized)
{
// Initialize in a lazy way, so the user application doesn't have to call this explicitly
Initialize();
initialized = true;
}
if (!wiInitializer::IsInitializeFinished())
{
// Until engine is not loaded, present initialization screen...
CommandList cmd = wiRenderer::GetDevice()->BeginCommandList();
wiRenderer::GetDevice()->RenderPassBegin(&swapChain, cmd);
wiImage::SetCanvas(canvas, cmd);
wiFont::SetCanvas(canvas, cmd);
Viewport viewport;
viewport.Width = (float)swapChain.desc.width;
viewport.Height = (float)swapChain.desc.height;
wiRenderer::GetDevice()->BindViewports(1, &viewport, cmd);
wiFontParams params;
params.posX = 5.f;
params.posY = 5.f;
std::string text = wiBackLog::getText();
float textheight = wiFont::textHeight(text, params);
float screenheight = canvas.GetLogicalHeight();
if (textheight > screenheight)
{
params.posY = screenheight - textheight;
}
wiFont::Draw(text, params, cmd);
wiRenderer::GetDevice()->RenderPassEnd(cmd);
wiRenderer::GetDevice()->SubmitCommandLists();
return;
}
static bool startup_script = false;
if (!startup_script)
{
startup_script = true;
wiLua::RegisterObject(MainComponent_BindLua::className, "main", new MainComponent_BindLua(this));
wiLua::RunFile("startup.lua");
}
if (!is_window_active)
{
// If the application is not active, disable Update loops:
deltaTimeAccumulator = 0;
return;
}
wiProfiler::BeginFrame();
deltaTime = float(std::max(0.0, timer.elapsed() / 1000.0));
timer.record();
// Wake up the events that need to be executed on the main thread, in thread safe manner:
wiEvent::FireEvent(SYSTEM_EVENT_THREAD_SAFE_POINT, 0);
const float dt = framerate_lock ? (1.0f / targetFrameRate) : deltaTime;
fadeManager.Update(dt);
if (GetActivePath() != nullptr)
{
GetActivePath()->init(canvas);
GetActivePath()->PreUpdate();
}
// Fixed time update:
auto range = wiProfiler::BeginRangeCPU("Fixed Update");
{
if (frameskip)
{
deltaTimeAccumulator += dt;
if (deltaTimeAccumulator > 10)
{
// application probably lost control, fixed update would take too long
deltaTimeAccumulator = 0;
}
const float targetFrameRateInv = 1.0f / targetFrameRate;
while (deltaTimeAccumulator >= targetFrameRateInv)
{
FixedUpdate();
deltaTimeAccumulator -= targetFrameRateInv;
}
}
else
{
FixedUpdate();
}
}
wiProfiler::EndRange(range); // Fixed Update
// Variable-timed update:
Update(dt);
Render();
wiInput::Update(window);
CommandList cmd = wiRenderer::GetDevice()->BeginCommandList();
wiRenderer::GetDevice()->RenderPassBegin(&swapChain, cmd);
{
wiImage::SetCanvas(canvas, cmd);
wiFont::SetCanvas(canvas, cmd);
Viewport viewport;
viewport.Width = (float)swapChain.desc.width;
viewport.Height = (float)swapChain.desc.height;
wiRenderer::GetDevice()->BindViewports(1, &viewport, cmd);
Compose(cmd);
}
wiRenderer::GetDevice()->RenderPassEnd(cmd);
wiProfiler::EndFrame(cmd);
wiRenderer::GetDevice()->SubmitCommandLists();
}
void MainComponent::Update(float dt)
{
auto range = wiProfiler::BeginRangeCPU("Update");
wiLua::SetDeltaTime(double(dt));
wiLua::Update();
if (GetActivePath() != nullptr)
{
GetActivePath()->Update(dt);
GetActivePath()->PostUpdate();
}
wiProfiler::EndRange(range); // Update
}
void MainComponent::FixedUpdate()
{
wiBackLog::Update(canvas);
wiLua::FixedUpdate();
if (GetActivePath() != nullptr)
{
GetActivePath()->FixedUpdate();
}
}
void MainComponent::Render()
{
auto range = wiProfiler::BeginRangeCPU("Render");
wiLua::Render();
if (GetActivePath() != nullptr)
{
GetActivePath()->Render();
}
wiProfiler::EndRange(range); // Render
}
void MainComponent::Compose(CommandList cmd)
{
auto range = wiProfiler::BeginRangeCPU("Compose");
if (GetActivePath() != nullptr)
{
GetActivePath()->Compose(cmd);
}
GraphicsDevice* device = wiRenderer::GetDevice();
if (fadeManager.IsActive())
{
// display fade rect
static wiImageParams fx;
fx.siz.x = canvas.GetLogicalWidth();
fx.siz.y = canvas.GetLogicalHeight();
fx.opacity = fadeManager.opacity;
wiImage::Draw(wiTextureHelper::getColor(fadeManager.color), fx, cmd);
}
// Draw the information display
if (infoDisplay.active)
{
std::stringstream ss("");
if (infoDisplay.watermark)
{
ss << "Wicked Engine " << wiVersion::GetVersionString() << " ";
#if defined(_ARM)
ss << "[ARM]";
#elif defined(_WIN64)
ss << "[64-bit]";
#elif defined(_WIN32)
ss << "[32-bit]";
#endif
#ifdef PLATFORM_UWP
ss << "[UWP]";
#endif
#ifdef WICKEDENGINE_BUILD_DX12
if (dynamic_cast<GraphicsDevice_DX12*>(device))
{
ss << "[DX12]";
}
#endif
#ifdef WICKEDENGINE_BUILD_VULKAN
if (dynamic_cast<GraphicsDevice_Vulkan*>(device))
{
ss << "[Vulkan]";
}
#endif
#ifdef _DEBUG
ss << "[DEBUG]";
#endif
if (device->IsDebugDevice())
{
ss << "[debugdevice]";
}
ss << std::endl;
}
if (infoDisplay.resolution)
{
ss << "Resolution: " << canvas.GetPhysicalWidth() << " x " << canvas.GetPhysicalHeight() << " (" << canvas.GetDPI() << " dpi)" << std::endl;
}
if (infoDisplay.fpsinfo)
{
deltatimes[fps_avg_counter++ % arraysize(deltatimes)] = deltaTime;
float displaydeltatime = deltaTime;
if (fps_avg_counter > arraysize(deltatimes))
{
float avg_time = 0;
for (int i = 0; i < arraysize(deltatimes); ++i)
{
avg_time += deltatimes[i];
}
displaydeltatime = avg_time / arraysize(deltatimes);
}
ss.precision(2);
ss << std::fixed << 1.0f / displaydeltatime << " FPS" << std::endl;
}
if (infoDisplay.heap_allocation_counter)
{
ss << "Heap allocations per frame: " << number_of_allocs.load() << std::endl;
number_of_allocs.store(0);
}
#ifdef _DEBUG
ss << "Warning: This is a [DEBUG] build, performance will be slow!" << std::endl;
#endif
if (wiRenderer::GetDevice()->IsDebugDevice())
{
ss << "Warning: Graphics is in [debugdevice] mode, performance will be slow!" << std::endl;
}
ss.precision(2);
wiFont::Draw(ss.str(), wiFontParams(4, 4, infoDisplay.size, WIFALIGN_LEFT, WIFALIGN_TOP, wiColor(255,255,255,255), wiColor(0,0,0,255)), cmd);
if (infoDisplay.colorgrading_helper)
{
wiImage::Draw(wiTextureHelper::getColorGradeDefault(), wiImageParams(0, 0, 256.0f / canvas.GetDPIScaling(), 16.0f / canvas.GetDPIScaling()), cmd);
}
}
wiProfiler::DrawData(canvas, 4, 120, cmd);
wiBackLog::Draw(canvas, cmd);
wiProfiler::EndRange(range); // Compose
}
void MainComponent::SetWindow(wiPlatform::window_type window, bool fullscreen)
{
this->window = window;
// User can also create a graphics device if custom logic is desired, but they must do before this function!
if (wiRenderer::GetDevice() == nullptr)
{
bool debugdevice = wiStartupArguments::HasArgument("debugdevice");
bool gpuvalidation = wiStartupArguments::HasArgument("gpuvalidation");
bool use_dx12 = wiStartupArguments::HasArgument("dx12");
bool use_vulkan = wiStartupArguments::HasArgument("vulkan");
#ifndef WICKEDENGINE_BUILD_DX12
if (use_dx12) {
wiHelper::messageBox("The engine was built without DX12 support!", "Error");
use_dx12 = false;
}
#endif
#ifndef WICKEDENGINE_BUILD_VULKAN
if (use_vulkan) {
wiHelper::messageBox("The engine was built without Vulkan support!", "Error");
use_vulkan = false;
}
#endif
if (!use_dx12 && !use_vulkan)
{
#if defined(WICKEDENGINE_BUILD_DX12)
use_dx12 = true;
#elif defined(WICKEDENGINE_BUILD_VULKAN)
use_vulkan = true;
#else
wiBackLog::post("No rendering backend is enabled! Please enable at least one so we can use it as default");
assert(false);
#endif
}
assert(use_dx12 || use_vulkan);
if (use_vulkan)
{
#ifdef WICKEDENGINE_BUILD_VULKAN
wiRenderer::SetShaderPath(wiRenderer::GetShaderPath() + "spirv/");
wiRenderer::SetDevice(std::make_shared<GraphicsDevice_Vulkan>(window, debugdevice));
#endif
}
else if (use_dx12)
{
#ifdef WICKEDENGINE_BUILD_DX12
wiRenderer::SetShaderPath(wiRenderer::GetShaderPath() + "hlsl6/");
wiRenderer::SetDevice(std::make_shared<GraphicsDevice_DX12>(debugdevice, gpuvalidation));
#endif
}
}
canvas.init(window);
SwapChainDesc desc;
desc.width = canvas.GetPhysicalWidth();
desc.height = canvas.GetPhysicalHeight();
desc.buffercount = 3;
desc.format = FORMAT_R10G10B10A2_UNORM;
bool success = wiRenderer::GetDevice()->CreateSwapChain(&desc, window, &swapChain);
assert(success);
swapChainVsyncChangeEvent = wiEvent::Subscribe(SYSTEM_EVENT_SET_VSYNC, [this](uint64_t userdata) {
SwapChainDesc desc = swapChain.desc;
desc.vsync = userdata != 0;
bool success = wiRenderer::GetDevice()->CreateSwapChain(&desc, nullptr, &swapChain);
assert(success);
});
}