3 #include "RenderEngine.hpp"
4 #include <SDL3/SDL_events.h>
6 #include <RmlUi/Core.h>
8 #include "Material.hpp"
9 #include "RMLFileInterface.hpp"
10 #include "InputManager.hpp"
13 #include "AudioPlayer.hpp"
15 #include <RGL/Swapchain.hpp>
16 #include <RGL/CommandBuffer.hpp>
17 #include "OpenXRIntegration.hpp"
18 #include "BuiltinTonemap.hpp"
21#include "MeshAsset.hpp"
23#include <steam/steamnetworkingsockets.h>
24#include <steam/isteamnetworkingutils.h>
26#include "Function.hpp"
30#include "VirtualFileSystem.hpp"
31#include "MeshAssetSkinned.hpp"
33#include "CameraComponent.hpp"
45 #include "AppleUtilities.h"
50using namespace std::chrono;
53static App* currentApp =
nullptr;
56void RGLFatalCallback(
const std::string& msg,
void* userData) {
60void RGLmsgCallback(RGL::MessageSeverity
severity,
const std::string& msg,
void* userData) {
62 case RGL::MessageSeverity::Info:
65 case RGL::MessageSeverity::Warning:
68 case RGL::MessageSeverity::Error:
77void crash_signal_handler(
int signum) {
79 Debug::PrintStacktraceHere();
101 ::signal(
SIGSEGV, &crash_signal_handler);
102 ::signal(
SIGABRT, &crash_signal_handler);
117 Resources = std::make_unique<VirtualFilesystem>();
121int App::run(
int argc,
char** argv) {
128 window = std::make_unique<Window>(960, 540,
"RavEngine");
130 auto config = OnConfigure(argc, argv);
133 RGL::API api = RGL::API::PlatformDefault;
136 auto envv = std::getenv(
"RGL_BACKEND");
138 if (
envv ==
nullptr) {
143 const std::unordered_map<std::string_view, RGL::API>
apis{
144 {
"metal",
decltype(
apis)::value_type::second_type::Metal},
145 {
"d3d12",
decltype(
apis)::value_type::second_type::Direct3D12 },
146 {
"vulkan",
decltype(
apis)::value_type::second_type::Vulkan },
150 if (it !=
apis.end()) {
154 std::cerr <<
"No backend \"" <<
backend <<
"\", expected one of:\n";
155 for (
const auto& api :
apis) {
156 std::cout <<
"\t - " << RGL::APIToString(api.second) <<
"\n";
164 .callback = RGLmsgCallback,
165 .fatal_callback = RGLFatalCallback,
166 .engineName =
"RavEngine",
170 device = RGL::IDevice::CreateSystemDefaultDevice();
172 Renderer = std::make_unique<RenderEngine>(config, device);
176 window->InitSwapchain(device, Renderer->mainCommandQueue);
178 auto size = window->GetSizeInPixels();
179 mainWindowView = { Renderer->CreateRenderTargetCollection({
static_cast<unsigned int>(size.width),
static_cast<unsigned int>(size.height) }) };
181#ifdef RVE_XR_AVAILABLE
183 OpenXRIntegration::init_openxr({
185 .commandQueue = Renderer->mainCommandQueue
187 xrRenderViewCollections = OpenXRIntegration::CreateRenderTargetCollections();
193 Rml::SetSystemInterface(&GetRenderEngine());
194 Rml::SetRenderInterface(&GetRenderEngine());
199 Renderer->InitDebugger();
203 enableSmoothScrolling();
207 App::Resources->IterateDirectory(
"fonts", [](
const std::string& filename) {
208 auto p = Filesystem::Path(filename);
209 if (p.extension() ==
".ttf") {
216 player = std::make_unique<AudioPlayer>();
221 if (NeedsNetworking()) {
231#if defined _WIN32 && !defined(_M_ARM64)
239 uint8_t data[] = {0xFF,0xFF,0xFF,0xFF};
243 .initialData = {{
reinterpret_cast<std::byte*
>(data),
sizeof(data)}}
246 uint8_t
normalData[] = {256/2,256/2, 0xFF,0xFF};
263 OnStartup(argc, argv);
265 lastFrameTime = clocktype::now();
279 auto now = clocktype::now();
282 float deltaSeconds = std::chrono::duration<decltype(deltaSeconds)>(deltaTimeMicroseconds).count();
283 time += deltaSeconds;
284 currentScale = deltaSeconds * evalNormal;
286 RVE_PROFILE_SECTION(events,
"Process all Events");
289 switch (
event.type) {
295 Renderer->mainCommandQueue->WaitUntilCompleted();
296 window->NotifySizeChanged(
event.window.data1,
event.window.data2);
299 auto size = window->GetSizeInPixels();
300 Renderer->ResizeRenderTargetCollection(mainWindowView.collection, {uint32_t(size.width), uint32_t(size.height)});
315 RVE_PROFILE_SECTION_END(events);
324 auto workEnd = clocktype::now();
327 if (delta > std::chrono::duration<double, std::milli>(3)) {
328 auto dc = std::chrono::duration_cast<std::chrono::milliseconds>(delta);
329 std::this_thread::sleep_for(std::chrono::duration<double, std::milli>(
dc.count()-1));
348 RVE_PROFILE_SECTION(
getSwapchain,
"Acquire Swapchain Image");
352 RenderEngine::debuggerInput->TickAxes();
355 inputManager->TickAxes();
361 auto scale = window->GetDPIScale();
365 for (
const auto world : loadedWorlds) {
366 world->Tick(currentScale);
369 if (
gui.Mode == GUIComponent::RenderMode::Screenspace) {
370 gui.SetDimensions(windowSize.width, windowSize.height);
371 gui.SetDPIScale(scale);
380 Function<void(
void)> front;
381 while (main_tasks.try_dequeue(front)) {
393 Debug::Fatal(
"Cannot render: World does not have a camera!");
395 mainWindowView.camDatas.clear();
398 auto projOnly = camera.GenerateProjectionMatrix(width, height);
399 auto viewOnly = camera.GenerateViewMatrix();
400 auto viewProj = projOnly * viewOnly;
401 auto camPos = camera.GetOwner().GetTransform().GetWorldPosition();
403 auto viewportOverride = camera.viewportOverride;
405 return RenderViewCollection::camData{ viewProj, projOnly, viewOnly, camPos,{camera.nearClip, camera.farClip} ,viewportOverride, camera.renderLayers, camera.FOV, width, height, &camera.postProcessingEffects, camera.tonemap.get(), camera.indirectLightingSettings};
407 std::vector<RenderViewCollection>
allViews;
409 if (!camera.IsActive()) {
416 auto& collection = camera.target->GetCollection();
417 auto size = collection.depthStencil->GetSize();
418 allViews.push_back({collection, {
MakeCamData(camera, size.width, size.height)}, {
static_cast<int>(size.width),
static_cast<int>(size.height)}});
422 if (!camera.IsActive()) {
432 mainWindowView.pixelDimensions = window->GetSizeInPixels();
434#ifdef RVE_XR_AVAILABLE
439 OpenXRIntegration::UpdateXRTargetCollections(xrRenderViewCollections,
xrBeginData.first);
440 allViews.insert(
allViews.end(), xrRenderViewCollections.begin(), xrRenderViewCollections.end());
446 mainWindowView.collection.finalFramebuffer =
nextTexture.texture;
448 auto mainCommandBuffer = Renderer->Draw(renderWorld,
allViews, scale);
453 .signalFence = window->swapchainFence,
457 window->swapchain->Present(
nextTexture.presentConfig);
460#ifdef RVE_XR_AVAILABLE
465 if (GetAudioActive()) {
466 player->SetWorld(renderWorld);
477float App::CurrentTPS() {
478 return App::evalNormal / currentScale;
487 if (!loadedWorlds.contains(
newWorld)) {
491 renderWorld->OnDeactivate();
492 renderWorld->isRendering =
false;
495 renderWorld->isRendering =
true;
496 renderWorld->OnActivate();
505 loadedWorlds.insert(world);
507 SetRenderedWorld(world);
511 if (networkManager.IsClient() && !networkManager.IsServer()) {
512 networkManager.client->SendSyncWorldRequest(world);
522 loadedWorlds.erase(world);
523 if (renderWorld == world) {
524 renderWorld->OnDeactivate();
534 for (
const auto& world : loadedWorlds) {
560 Debug::Fatal(
"Quit is not implemented on the server (TODO)");
571 window->BlockGetNextSwapchainImage({});
573 Renderer->DeactivateDebugger();
581 Texture::Manager::defaultTexture.reset();
582 Texture::Manager::defaultNormalTexture.reset();
583 Texture::Manager::zeroTexture.reset();
585 if (GetAudioActive()) {
589 networkManager.server.reset();
590 networkManager.client.reset();
593 inputManager =
nullptr;
595 renderWorld =
nullptr;
596 loadedWorlds.clear();
602 auto fsi = Rml::GetFileInterface();
608 currentApp =
nullptr;
617std::optional<Ref<World>> RavEngine::App::GetWorldByName(
const std::string& name) {
618 std::optional<Ref<World>> value;
619 for (
const auto& world : loadedWorlds) {
621 if (std::strncmp(world->worldID.data(), name.data(), World::id_size) == 0) {
622 value.emplace(world);
633bool RavEngine::App::GetAudioActive()
const
636 return player.operator
bool();
643App* RavEngine::GetApp()
virtual void OnDropAudioWorklets(uint32_t ndropped)
Definition App_priv.hpp:629
void AddReplaceWorld(Ref< World > oldWorld, Ref< World > newWorld)
Definition App_priv.hpp:545
void RemoveWorld(Ref< World > world)
Definition App_priv.hpp:521
void SetRenderedWorld(Ref< World > newWorld)
Definition App_priv.hpp:486
void SetWindowTitle(const char *title)
Definition App_priv.hpp:612
void AddWorld(Ref< World > world)
Definition App_priv.hpp:504
void Quit()
Definition App_priv.hpp:554
void RemoveAllWorlds()
Definition App_priv.hpp:533
Definition CameraComponent.hpp:14
static void Fatal(const std::string_view message)
Definition Debug.hpp:106
static void Warning(const char *message)
Definition Debug.hpp:64
static void Log(const std::string_view message)
Definition Debug.hpp:46
static void Error(const std::string_view message)
Definition Debug.hpp:86
static bool LoadFont(const std::string &filename)
Definition GUI.cpp:110
Definition RMLFileInterface.hpp:5
Definition concurrentqueue.h:747
uint32 uint32_t
Definition fwd.hpp:131
Definition Animation.hpp:6
Definition EditorCommon.h:232
Definition CommandBuffer.hpp:46
Definition Swapchain.hpp:8
static void Clear()
Definition Manager.hpp:85
Definition RenderTargetCollection.hpp:31
Definition Texture.hpp:18