source: ps/trunk/source/renderer/Renderer.cpp@ 27184

Last change on this file since 27184 was 27184, checked in by Vladislav Belov, 21 months ago

Makes AcquireNextBackbuffer returns true in case of successful backbuffer acquirement.

  • Property svn:eol-style set to native
File size: 19.8 KB
Line 
1/* Copyright (C) 2022 Wildfire Games.
2 * This file is part of 0 A.D.
3 *
4 * 0 A.D. is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * 0 A.D. is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "precompiled.h"
19
20#include "Renderer.h"
21
22#include "graphics/Canvas2D.h"
23#include "graphics/CinemaManager.h"
24#include "graphics/GameView.h"
25#include "graphics/LightEnv.h"
26#include "graphics/ModelDef.h"
27#include "graphics/TerrainTextureManager.h"
28#include "i18n/L10n.h"
29#include "lib/allocators/shared_ptr.h"
30#include "lib/tex/tex.h"
31#include "gui/GUIManager.h"
32#include "ps/CConsole.h"
33#include "ps/CLogger.h"
34#include "ps/ConfigDB.h"
35#include "ps/CStrInternStatic.h"
36#include "ps/Game.h"
37#include "ps/GameSetup/Config.h"
38#include "ps/GameSetup/GameSetup.h"
39#include "ps/Globals.h"
40#include "ps/Loader.h"
41#include "ps/Profile.h"
42#include "ps/Filesystem.h"
43#include "ps/World.h"
44#include "ps/ProfileViewer.h"
45#include "graphics/Camera.h"
46#include "graphics/FontManager.h"
47#include "graphics/ShaderManager.h"
48#include "graphics/Terrain.h"
49#include "graphics/Texture.h"
50#include "graphics/TextureManager.h"
51#include "ps/Util.h"
52#include "ps/VideoMode.h"
53#include "renderer/backend/IDevice.h"
54#include "renderer/DebugRenderer.h"
55#include "renderer/PostprocManager.h"
56#include "renderer/RenderingOptions.h"
57#include "renderer/RenderModifiers.h"
58#include "renderer/SceneRenderer.h"
59#include "renderer/TimeManager.h"
60#include "renderer/VertexBufferManager.h"
61#include "tools/atlas/GameInterface/GameLoop.h"
62#include "tools/atlas/GameInterface/View.h"
63
64#include <algorithm>
65
66namespace
67{
68
69size_t g_NextScreenShotNumber = 0;
70
71///////////////////////////////////////////////////////////////////////////////////
72// CRendererStatsTable - Profile display of rendering stats
73
74/**
75 * Class CRendererStatsTable: Implementation of AbstractProfileTable to
76 * display the renderer stats in-game.
77 *
78 * Accesses CRenderer::m_Stats by keeping the reference passed to the
79 * constructor.
80 */
81class CRendererStatsTable : public AbstractProfileTable
82{
83 NONCOPYABLE(CRendererStatsTable);
84public:
85 CRendererStatsTable(const CRenderer::Stats& st);
86
87 // Implementation of AbstractProfileTable interface
88 CStr GetName();
89 CStr GetTitle();
90 size_t GetNumberRows();
91 const std::vector<ProfileColumn>& GetColumns();
92 CStr GetCellText(size_t row, size_t col);
93 AbstractProfileTable* GetChild(size_t row);
94
95private:
96 /// Reference to the renderer singleton's stats
97 const CRenderer::Stats& Stats;
98
99 /// Column descriptions
100 std::vector<ProfileColumn> columnDescriptions;
101
102 enum
103 {
104 Row_DrawCalls = 0,
105 Row_TerrainTris,
106 Row_WaterTris,
107 Row_ModelTris,
108 Row_OverlayTris,
109 Row_BlendSplats,
110 Row_Particles,
111 Row_VBReserved,
112 Row_VBAllocated,
113 Row_TextureMemory,
114 Row_ShadersLoaded,
115
116 // Must be last to count number of rows
117 NumberRows
118 };
119};
120
121// Construction
122CRendererStatsTable::CRendererStatsTable(const CRenderer::Stats& st)
123 : Stats(st)
124{
125 columnDescriptions.push_back(ProfileColumn("Name", 230));
126 columnDescriptions.push_back(ProfileColumn("Value", 100));
127}
128
129// Implementation of AbstractProfileTable interface
130CStr CRendererStatsTable::GetName()
131{
132 return "renderer";
133}
134
135CStr CRendererStatsTable::GetTitle()
136{
137 return "Renderer statistics";
138}
139
140size_t CRendererStatsTable::GetNumberRows()
141{
142 return NumberRows;
143}
144
145const std::vector<ProfileColumn>& CRendererStatsTable::GetColumns()
146{
147 return columnDescriptions;
148}
149
150CStr CRendererStatsTable::GetCellText(size_t row, size_t col)
151{
152 char buf[256];
153
154 switch(row)
155 {
156 case Row_DrawCalls:
157 if (col == 0)
158 return "# draw calls";
159 sprintf_s(buf, sizeof(buf), "%lu", (unsigned long)Stats.m_DrawCalls);
160 return buf;
161
162 case Row_TerrainTris:
163 if (col == 0)
164 return "# terrain tris";
165 sprintf_s(buf, sizeof(buf), "%lu", (unsigned long)Stats.m_TerrainTris);
166 return buf;
167
168 case Row_WaterTris:
169 if (col == 0)
170 return "# water tris";
171 sprintf_s(buf, sizeof(buf), "%lu", (unsigned long)Stats.m_WaterTris);
172 return buf;
173
174 case Row_ModelTris:
175 if (col == 0)
176 return "# model tris";
177 sprintf_s(buf, sizeof(buf), "%lu", (unsigned long)Stats.m_ModelTris);
178 return buf;
179
180 case Row_OverlayTris:
181 if (col == 0)
182 return "# overlay tris";
183 sprintf_s(buf, sizeof(buf), "%lu", (unsigned long)Stats.m_OverlayTris);
184 return buf;
185
186 case Row_BlendSplats:
187 if (col == 0)
188 return "# blend splats";
189 sprintf_s(buf, sizeof(buf), "%lu", (unsigned long)Stats.m_BlendSplats);
190 return buf;
191
192 case Row_Particles:
193 if (col == 0)
194 return "# particles";
195 sprintf_s(buf, sizeof(buf), "%lu", (unsigned long)Stats.m_Particles);
196 return buf;
197
198 case Row_VBReserved:
199 if (col == 0)
200 return "VB reserved";
201 sprintf_s(buf, sizeof(buf), "%lu kB", (unsigned long)g_VBMan.GetBytesReserved() / 1024);
202 return buf;
203
204 case Row_VBAllocated:
205 if (col == 0)
206 return "VB allocated";
207 sprintf_s(buf, sizeof(buf), "%lu kB", (unsigned long)g_VBMan.GetBytesAllocated() / 1024);
208 return buf;
209
210 case Row_TextureMemory:
211 if (col == 0)
212 return "textures uploaded";
213 sprintf_s(buf, sizeof(buf), "%lu kB", (unsigned long)g_Renderer.GetTextureManager().GetBytesUploaded() / 1024);
214 return buf;
215
216 case Row_ShadersLoaded:
217 if (col == 0)
218 return "shader effects loaded";
219 sprintf_s(buf, sizeof(buf), "%lu", (unsigned long)g_Renderer.GetShaderManager().GetNumEffectsLoaded());
220 return buf;
221
222 default:
223 return "???";
224 }
225}
226
227AbstractProfileTable* CRendererStatsTable::GetChild(size_t UNUSED(row))
228{
229 return 0;
230}
231
232} // anonymous namespace
233
234///////////////////////////////////////////////////////////////////////////////////
235// CRenderer implementation
236
237/**
238 * Struct CRendererInternals: Truly hide data that is supposed to be hidden
239 * in this structure so it won't even appear in header files.
240 */
241class CRenderer::Internals
242{
243 NONCOPYABLE(Internals);
244public:
245 std::unique_ptr<Renderer::Backend::IDeviceCommandContext> deviceCommandContext;
246
247 /// true if CRenderer::Open has been called
248 bool IsOpen;
249
250 /// true if shaders need to be reloaded
251 bool ShadersDirty;
252
253 /// Table to display renderer stats in-game via profile system
254 CRendererStatsTable profileTable;
255
256 /// Shader manager
257 CShaderManager shaderManager;
258
259 /// Texture manager
260 CTextureManager textureManager;
261
262 /// Time manager
263 CTimeManager timeManager;
264
265 /// Postprocessing effect manager
266 CPostprocManager postprocManager;
267
268 CSceneRenderer sceneRenderer;
269
270 CDebugRenderer debugRenderer;
271
272 CFontManager fontManager;
273
274 Internals() :
275 IsOpen(false), ShadersDirty(true), profileTable(g_Renderer.m_Stats),
276 deviceCommandContext(g_VideoMode.GetBackendDevice()->CreateCommandContext()),
277 textureManager(g_VFS, false, g_VideoMode.GetBackendDevice())
278 {
279 }
280};
281
282CRenderer::CRenderer()
283{
284 TIMER(L"InitRenderer");
285
286 m = std::make_unique<Internals>();
287
288 g_ProfileViewer.AddRootTable(&m->profileTable);
289
290 m_Width = 0;
291 m_Height = 0;
292
293 m_Stats.Reset();
294
295 // Create terrain related stuff.
296 new CTerrainTextureManager;
297
298 Open(g_xres, g_yres);
299
300 // Setup lighting environment. Since the Renderer accesses the
301 // lighting environment through a pointer, this has to be done before
302 // the first Frame.
303 GetSceneRenderer().SetLightEnv(&g_LightEnv);
304
305 // I haven't seen the camera affecting GUI rendering and such, but the
306 // viewport has to be updated according to the video mode
307 SViewPort vp;
308 vp.m_X = 0;
309 vp.m_Y = 0;
310 vp.m_Width = g_xres;
311 vp.m_Height = g_yres;
312 SetViewport(vp);
313 ModelDefActivateFastImpl();
314 ColorActivateFastImpl();
315 ModelRenderer::Init();
316}
317
318CRenderer::~CRenderer()
319{
320 delete &g_TexMan;
321
322 // We no longer UnloadWaterTextures here -
323 // that is the responsibility of the module that asked for
324 // them to be loaded (i.e. CGameView).
325 m.reset();
326}
327
328void CRenderer::ReloadShaders()
329{
330 ENSURE(m->IsOpen);
331
332 m->sceneRenderer.ReloadShaders();
333 m->ShadersDirty = false;
334}
335
336bool CRenderer::Open(int width, int height)
337{
338 m->IsOpen = true;
339
340 // Dimensions
341 m_Width = width;
342 m_Height = height;
343
344 // Validate the currently selected render path
345 SetRenderPath(g_RenderingOptions.GetRenderPath());
346
347 if (m->postprocManager.IsEnabled())
348 m->postprocManager.Initialize();
349
350 m->sceneRenderer.Initialize();
351
352 return true;
353}
354
355void CRenderer::Resize(int width, int height)
356{
357 m_Width = width;
358 m_Height = height;
359
360 m->postprocManager.Resize();
361
362 m->sceneRenderer.Resize(width, height);
363}
364
365void CRenderer::SetRenderPath(RenderPath rp)
366{
367 if (!m->IsOpen)
368 {
369 // Delay until Open() is called.
370 return;
371 }
372
373 // Renderer has been opened, so validate the selected renderpath
374 const bool hasShadersSupport =
375 g_VideoMode.GetBackendDevice()->GetCapabilities().ARBShaders ||
376 g_VideoMode.GetBackendDevice()->GetBackend() != Renderer::Backend::Backend::GL_ARB;
377 if (rp == RenderPath::DEFAULT)
378 {
379 if (hasShadersSupport)
380 rp = RenderPath::SHADER;
381 else
382 rp = RenderPath::FIXED;
383 }
384
385 if (rp == RenderPath::SHADER)
386 {
387 if (!hasShadersSupport)
388 {
389 LOGWARNING("Falling back to fixed function\n");
390 rp = RenderPath::FIXED;
391 }
392 }
393
394 // TODO: remove this once capabilities have been properly extracted and the above checks have been moved elsewhere.
395 g_RenderingOptions.m_RenderPath = rp;
396
397 MakeShadersDirty();
398}
399
400bool CRenderer::ShouldRender() const
401{
402 return !g_app_minimized && (g_app_has_focus || !g_VideoMode.IsInFullscreen());
403}
404
405void CRenderer::RenderFrame(const bool needsPresent)
406{
407 // Do not render if not focused while in fullscreen or minimised,
408 // as that triggers a difficult-to-reproduce crash on some graphic cards.
409 if (!ShouldRender())
410 return;
411
412 if (m_ScreenShotType == ScreenShotType::BIG)
413 {
414 RenderBigScreenShot(needsPresent);
415 }
416 else if (m_ScreenShotType == ScreenShotType::DEFAULT)
417 {
418 RenderScreenShot(needsPresent);
419 }
420 else
421 {
422 if (needsPresent)
423 {
424 // In case of no acquired backbuffer we have nothing render to.
425 if (!g_VideoMode.GetBackendDevice()->AcquireNextBackbuffer())
426 return;
427 }
428
429 if (m_ShouldPreloadResourcesBeforeNextFrame)
430 {
431 m_ShouldPreloadResourcesBeforeNextFrame = false;
432 // We don't need to render logger for the preload.
433 RenderFrameImpl(true, false);
434 }
435
436 RenderFrameImpl(true, true);
437
438 m->deviceCommandContext->Flush();
439 if (needsPresent)
440 g_VideoMode.GetBackendDevice()->Present();
441 }
442}
443
444void CRenderer::RenderFrameImpl(const bool renderGUI, const bool renderLogger)
445{
446 PROFILE3("render");
447
448 g_Profiler2.RecordGPUFrameStart();
449
450 g_TexMan.UploadResourcesIfNeeded(m->deviceCommandContext.get());
451
452 m->textureManager.MakeUploadProgress(m->deviceCommandContext.get());
453
454 // prepare before starting the renderer frame
455 if (g_Game && g_Game->IsGameStarted())
456 g_Game->GetView()->BeginFrame();
457
458 if (g_Game)
459 m->sceneRenderer.SetSimulation(g_Game->GetSimulation2());
460
461 // start new frame
462 BeginFrame();
463
464 if (g_Game && g_Game->IsGameStarted())
465 {
466 g_Game->GetView()->Render();
467 }
468
469 m->deviceCommandContext->BeginFramebufferPass(
470 m->deviceCommandContext->GetDevice()->GetCurrentBackbuffer());
471
472 // If we're in Atlas game view, render special tools
473 if (g_AtlasGameLoop && g_AtlasGameLoop->view)
474 {
475 g_AtlasGameLoop->view->DrawCinemaPathTool();
476 }
477
478 if (g_Game && g_Game->IsGameStarted())
479 {
480 g_Game->GetView()->GetCinema()->Render();
481 }
482
483 RenderFrame2D(renderGUI, renderLogger);
484
485 m->deviceCommandContext->EndFramebufferPass();
486
487 EndFrame();
488
489 const Stats& stats = GetStats();
490 PROFILE2_ATTR("draw calls: %zu", stats.m_DrawCalls);
491 PROFILE2_ATTR("terrain tris: %zu", stats.m_TerrainTris);
492 PROFILE2_ATTR("water tris: %zu", stats.m_WaterTris);
493 PROFILE2_ATTR("model tris: %zu", stats.m_ModelTris);
494 PROFILE2_ATTR("overlay tris: %zu", stats.m_OverlayTris);
495 PROFILE2_ATTR("blend splats: %zu", stats.m_BlendSplats);
496 PROFILE2_ATTR("particles: %zu", stats.m_Particles);
497
498 g_Profiler2.RecordGPUFrameEnd();
499}
500
501void CRenderer::RenderFrame2D(const bool renderGUI, const bool renderLogger)
502{
503 CCanvas2D canvas(g_xres, g_yres, g_VideoMode.GetScale(), m->deviceCommandContext.get());
504
505 m->sceneRenderer.RenderTextOverlays(canvas);
506
507 if (renderGUI)
508 {
509 GPU_SCOPED_LABEL(m->deviceCommandContext.get(), "Render GUI");
510 // All GUI elements are drawn in Z order to render semi-transparent
511 // objects correctly.
512 g_GUI->Draw(canvas);
513 }
514
515 // If we're in Atlas game view, render special overlays (e.g. editor bandbox).
516 if (g_AtlasGameLoop && g_AtlasGameLoop->view)
517 {
518 g_AtlasGameLoop->view->DrawOverlays(canvas);
519 }
520
521 {
522 GPU_SCOPED_LABEL(m->deviceCommandContext.get(), "Render console");
523 g_Console->Render(canvas);
524 }
525
526 if (renderLogger)
527 {
528 GPU_SCOPED_LABEL(m->deviceCommandContext.get(), "Render logger");
529 g_Logger->Render(canvas);
530 }
531
532 {
533 GPU_SCOPED_LABEL(m->deviceCommandContext.get(), "Render profiler");
534 // Profile information
535 g_ProfileViewer.RenderProfile(canvas);
536 }
537}
538
539void CRenderer::RenderScreenShot(const bool needsPresent)
540{
541 m_ScreenShotType = ScreenShotType::NONE;
542
543 // get next available numbered filename
544 // note: %04d -> always 4 digits, so sorting by filename works correctly.
545 const VfsPath filenameFormat(L"screenshots/screenshot%04d.png");
546 VfsPath filename;
547 vfs::NextNumberedFilename(g_VFS, filenameFormat, g_NextScreenShotNumber, filename);
548
549 const size_t width = static_cast<size_t>(g_xres), height = static_cast<size_t>(g_yres);
550 const size_t bpp = 24;
551
552 if (needsPresent && !g_VideoMode.GetBackendDevice()->AcquireNextBackbuffer())
553 return;
554
555 // Hide log messages and re-render
556 RenderFrameImpl(true, false);
557
558 const size_t img_size = width * height * bpp / 8;
559 const size_t hdr_size = tex_hdr_size(filename);
560 std::shared_ptr<u8> buf;
561 AllocateAligned(buf, hdr_size + img_size, maxSectorSize);
562 void* img = buf.get() + hdr_size;
563 Tex t;
564 if (t.wrap(width, height, bpp, TEX_BOTTOM_UP, buf, hdr_size) < 0)
565 return;
566
567 m->deviceCommandContext->ReadbackFramebufferSync(0, 0, width, height, img);
568 m->deviceCommandContext->Flush();
569 if (needsPresent)
570 g_VideoMode.GetBackendDevice()->Present();
571
572 if (tex_write(&t, filename) == INFO::OK)
573 {
574 OsPath realPath;
575 g_VFS->GetRealPath(filename, realPath);
576
577 LOGMESSAGERENDER(g_L10n.Translate("Screenshot written to '%s'"), realPath.string8());
578
579 debug_printf(
580 CStr(g_L10n.Translate("Screenshot written to '%s'") + "\n").c_str(),
581 realPath.string8().c_str());
582 }
583 else
584 LOGERROR("Error writing screenshot to '%s'", filename.string8());
585}
586
587void CRenderer::RenderBigScreenShot(const bool needsPresent)
588{
589 m_ScreenShotType = ScreenShotType::NONE;
590
591 // If the game hasn't started yet then use WriteScreenshot to generate the image.
592 if (!g_Game)
593 return RenderScreenShot(needsPresent);
594
595 int tiles = 4, tileWidth = 256, tileHeight = 256;
596 CFG_GET_VAL("screenshot.tiles", tiles);
597 CFG_GET_VAL("screenshot.tilewidth", tileWidth);
598 CFG_GET_VAL("screenshot.tileheight", tileHeight);
599 if (tiles <= 0 || tileWidth <= 0 || tileHeight <= 0 || tileWidth * tiles % 4 != 0 || tileHeight * tiles % 4 != 0)
600 {
601 LOGWARNING("Invalid big screenshot size: tiles=%d tileWidth=%d tileHeight=%d", tiles, tileWidth, tileHeight);
602 return;
603 }
604
605 // get next available numbered filename
606 // note: %04d -> always 4 digits, so sorting by filename works correctly.
607 const VfsPath filenameFormat(L"screenshots/screenshot%04d.bmp");
608 VfsPath filename;
609 vfs::NextNumberedFilename(g_VFS, filenameFormat, g_NextScreenShotNumber, filename);
610
611 // Slightly ugly and inflexible: Always draw 640*480 tiles onto the screen, and
612 // hope the screen is actually large enough for that.
613 ENSURE(g_xres >= tileWidth && g_yres >= tileHeight);
614
615 const int imageWidth = tileWidth * tiles, imageHeight = tileHeight * tiles;
616 const int bpp = 24;
617
618 const size_t imageSize = imageWidth * imageHeight * bpp / 8;
619 const size_t tileSize = tileWidth * tileHeight * bpp / 8;
620 const size_t headerSize = tex_hdr_size(filename);
621 void* tileData = malloc(tileSize);
622 if (!tileData)
623 {
624 WARN_IF_ERR(ERR::NO_MEM);
625 return;
626 }
627 std::shared_ptr<u8> imageBuffer;
628 AllocateAligned(imageBuffer, headerSize + imageSize, maxSectorSize);
629
630 Tex t;
631 void* img = imageBuffer.get() + headerSize;
632 if (t.wrap(imageWidth, imageHeight, bpp, TEX_BOTTOM_UP, imageBuffer, headerSize) < 0)
633 {
634 free(tileData);
635 return;
636 }
637
638 CCamera oldCamera = *g_Game->GetView()->GetCamera();
639
640 // Resize various things so that the sizes and aspect ratios are correct
641 {
642 g_Renderer.Resize(tileWidth, tileHeight);
643 SViewPort vp = { 0, 0, tileWidth, tileHeight };
644 g_Game->GetView()->SetViewport(vp);
645 }
646
647 // Render each tile
648 CMatrix3D projection;
649 projection.SetIdentity();
650 const float aspectRatio = 1.0f * tileWidth / tileHeight;
651 for (int tileY = 0; tileY < tiles; ++tileY)
652 {
653 for (int tileX = 0; tileX < tiles; ++tileX)
654 {
655 // Adjust the camera to render the appropriate region
656 if (oldCamera.GetProjectionType() == CCamera::ProjectionType::PERSPECTIVE)
657 {
658 projection.SetPerspectiveTile(oldCamera.GetFOV(), aspectRatio, oldCamera.GetNearPlane(), oldCamera.GetFarPlane(), tiles, tileX, tileY);
659 }
660 g_Game->GetView()->GetCamera()->SetProjection(projection);
661
662 if (needsPresent && g_VideoMode.GetBackendDevice()->AcquireNextBackbuffer())
663 {
664 RenderFrameImpl(false, false);
665
666 m->deviceCommandContext->ReadbackFramebufferSync(0, 0, tileWidth, tileHeight, tileData);
667 m->deviceCommandContext->Flush();
668 g_VideoMode.GetBackendDevice()->Present();
669 }
670
671 // Copy the tile pixels into the main image
672 for (int y = 0; y < tileHeight; ++y)
673 {
674 void* dest = static_cast<char*>(img) + ((tileY * tileHeight + y) * imageWidth + (tileX * tileWidth)) * bpp / 8;
675 void* src = static_cast<char*>(tileData) + y * tileWidth * bpp / 8;
676 memcpy(dest, src, tileWidth * bpp / 8);
677 }
678 }
679 }
680
681 // Restore the viewport settings
682 {
683 g_Renderer.Resize(g_xres, g_yres);
684 SViewPort vp = { 0, 0, g_xres, g_yres };
685 g_Game->GetView()->SetViewport(vp);
686 g_Game->GetView()->GetCamera()->SetProjectionFromCamera(oldCamera);
687 }
688
689 if (tex_write(&t, filename) == INFO::OK)
690 {
691 OsPath realPath;
692 g_VFS->GetRealPath(filename, realPath);
693
694 LOGMESSAGERENDER(g_L10n.Translate("Screenshot written to '%s'"), realPath.string8());
695
696 debug_printf(
697 CStr(g_L10n.Translate("Screenshot written to '%s'") + "\n").c_str(),
698 realPath.string8().c_str());
699 }
700 else
701 LOGERROR("Error writing screenshot to '%s'", filename.string8());
702
703 free(tileData);
704}
705
706void CRenderer::BeginFrame()
707{
708 PROFILE("begin frame");
709
710 // Zero out all the per-frame stats.
711 m_Stats.Reset();
712
713 if (m->ShadersDirty)
714 ReloadShaders();
715
716 m->sceneRenderer.BeginFrame();
717}
718
719void CRenderer::EndFrame()
720{
721 PROFILE3("end frame");
722
723 m->sceneRenderer.EndFrame();
724}
725
726void CRenderer::SetViewport(const SViewPort &vp)
727{
728 m_Viewport = vp;
729 Renderer::Backend::IDeviceCommandContext::Rect viewportRect;
730 viewportRect.x = vp.m_X;
731 viewportRect.y = vp.m_Y;
732 viewportRect.width = vp.m_Width;
733 viewportRect.height = vp.m_Height;
734 m->deviceCommandContext->SetViewports(1, &viewportRect);
735}
736
737SViewPort CRenderer::GetViewport()
738{
739 return m_Viewport;
740}
741
742void CRenderer::MakeShadersDirty()
743{
744 m->ShadersDirty = true;
745 m->sceneRenderer.MakeShadersDirty();
746}
747
748CTextureManager& CRenderer::GetTextureManager()
749{
750 return m->textureManager;
751}
752
753CShaderManager& CRenderer::GetShaderManager()
754{
755 return m->shaderManager;
756}
757
758CTimeManager& CRenderer::GetTimeManager()
759{
760 return m->timeManager;
761}
762
763CPostprocManager& CRenderer::GetPostprocManager()
764{
765 return m->postprocManager;
766}
767
768CSceneRenderer& CRenderer::GetSceneRenderer()
769{
770 return m->sceneRenderer;
771}
772
773CDebugRenderer& CRenderer::GetDebugRenderer()
774{
775 return m->debugRenderer;
776}
777
778CFontManager& CRenderer::GetFontManager()
779{
780 return m->fontManager;
781}
782
783void CRenderer::PreloadResourcesBeforeNextFrame()
784{
785 m_ShouldPreloadResourcesBeforeNextFrame = true;
786}
787
788void CRenderer::MakeScreenShotOnNextFrame(ScreenShotType screenShotType)
789{
790 m_ScreenShotType = screenShotType;
791}
792
793Renderer::Backend::IDeviceCommandContext* CRenderer::GetDeviceCommandContext()
794{
795 return m->deviceCommandContext.get();
796}
Note: See TracBrowser for help on using the repository browser.