1#![warn(missing_docs)]
30
31pub mod framework;
32
33pub mod bundle;
34pub mod cache;
35pub mod debug_renderer;
36pub mod storage;
37pub mod ui_renderer;
38pub mod visibility;
39
40mod bloom;
41mod flat_shader;
42mod forward_renderer;
43mod fxaa;
44mod gbuffer;
45mod hdr;
46mod light;
47mod light_volume;
48mod occlusion;
49mod shadow;
50mod skybox_shader;
51mod ssao;
52mod stats;
53
54use crate::{
55 asset::{event::ResourceEvent, manager::ResourceManager},
56 core::{
57 algebra::{Matrix4, Vector2, Vector3, Vector4},
58 array_as_u8_slice,
59 color::Color,
60 instant,
61 log::{Log, MessageKind},
62 math::Rect,
63 pool::Handle,
64 reflect::prelude::*,
65 sstorage::ImmutableString,
66 uuid_provider,
67 },
68 engine::error::EngineError,
69 graph::SceneGraph,
70 gui::draw::DrawingContext,
71 material::shader::{Shader, ShaderDefinition},
72 renderer::{
73 bloom::BloomRenderer,
74 bundle::{ObserverInfo, RenderDataBundleStorage, RenderDataBundleStorageOptions},
75 cache::{
76 geometry::GeometryCache, shader::ShaderCache, texture::TextureCache,
77 uniform::UniformBufferCache, uniform::UniformMemoryAllocator,
78 },
79 debug_renderer::DebugRenderer,
80 flat_shader::FlatShader,
81 forward_renderer::{ForwardRenderContext, ForwardRenderer},
82 framework::{
83 buffer::{Buffer, BufferKind, BufferUsage},
84 error::FrameworkError,
85 framebuffer::{
86 Attachment, AttachmentKind, BufferLocation, FrameBuffer, ResourceBindGroup,
87 ResourceBinding,
88 },
89 geometry_buffer::GeometryBuffer,
90 gpu_program::SamplerFallback,
91 gpu_texture::{GpuTexture, GpuTextureDescriptor, GpuTextureKind, PixelKind},
92 server::{GraphicsServer, SharedGraphicsServer},
93 uniform::StaticUniformBuffer,
94 DrawParameters, ElementRange, GeometryBufferExt, PolygonFace, PolygonFillMode,
95 },
96 fxaa::FxaaRenderer,
97 gbuffer::{GBuffer, GBufferRenderContext},
98 hdr::HighDynamicRangeRenderer,
99 light::{DeferredLightRenderer, DeferredRendererContext},
100 ui_renderer::{UiRenderContext, UiRenderer},
101 visibility::VisibilityCache,
102 },
103 resource::texture::{Texture, TextureKind, TextureResource},
104 scene::{camera::Camera, mesh::surface::SurfaceData, Scene, SceneContainer},
105};
106use fxhash::FxHashMap;
107use fyrox_graphics::framebuffer::DrawCallStatistics;
108use lazy_static::lazy_static;
109use serde::{Deserialize, Serialize};
110pub use stats::*;
111use std::{any::TypeId, cell::RefCell, collections::hash_map::Entry, rc::Rc, sync::mpsc::Receiver};
112use strum_macros::{AsRefStr, EnumString, VariantNames};
113use winit::window::Window;
114
115lazy_static! {
116 static ref GBUFFER_PASS_NAME: ImmutableString = ImmutableString::new("GBuffer");
117 static ref DIRECTIONAL_SHADOW_PASS_NAME: ImmutableString =
118 ImmutableString::new("DirectionalShadow");
119 static ref SPOT_SHADOW_PASS_NAME: ImmutableString = ImmutableString::new("SpotShadow");
120 static ref POINT_SHADOW_PASS_NAME: ImmutableString = ImmutableString::new("PointShadow");
121}
122
123pub fn is_shadow_pass(render_pass_name: &str) -> bool {
125 render_pass_name == &**DIRECTIONAL_SHADOW_PASS_NAME
126 || render_pass_name == &**SPOT_SHADOW_PASS_NAME
127 || render_pass_name == &**POINT_SHADOW_PASS_NAME
128}
129
130#[derive(
132 Copy,
133 Clone,
134 Hash,
135 PartialOrd,
136 PartialEq,
137 Eq,
138 Ord,
139 Debug,
140 Serialize,
141 Deserialize,
142 Reflect,
143 AsRefStr,
144 EnumString,
145 VariantNames,
146)]
147pub enum ShadowMapPrecision {
148 Half,
151 Full,
154}
155
156uuid_provider!(ShadowMapPrecision = "f9b2755b-248e-46ba-bcab-473eac1acdb8");
157
158#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize, Reflect, Eq)]
160pub struct CsmSettings {
161 pub enabled: bool,
163
164 pub size: usize,
166
167 pub precision: ShadowMapPrecision,
170
171 pub pcf: bool,
173}
174
175impl Default for CsmSettings {
176 fn default() -> Self {
177 Self {
178 enabled: true,
179 size: 2048,
180 precision: ShadowMapPrecision::Full,
181 pcf: true,
182 }
183 }
184}
185
186#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize, Reflect)]
189pub struct QualitySettings {
190 pub point_shadow_map_size: usize,
193 pub point_soft_shadows: bool,
195 pub point_shadows_enabled: bool,
197 pub point_shadows_distance: f32,
199 pub point_shadow_map_precision: ShadowMapPrecision,
202 pub point_shadows_fade_out_range: f32,
206
207 pub spot_shadow_map_size: usize,
210 pub spot_soft_shadows: bool,
212 pub spot_shadows_enabled: bool,
214 pub spot_shadows_distance: f32,
216 pub spot_shadow_map_precision: ShadowMapPrecision,
219 pub spot_shadows_fade_out_range: f32,
222
223 pub csm_settings: CsmSettings,
225
226 pub use_ssao: bool,
228 pub ssao_radius: f32,
231
232 pub light_scatter_enabled: bool,
235
236 pub fxaa: bool,
238
239 pub use_parallax_mapping: bool,
241
242 pub use_bloom: bool,
244
245 #[serde(default)]
248 pub use_occlusion_culling: bool,
249
250 #[serde(default)]
253 pub use_light_occlusion_culling: bool,
254}
255
256impl Default for QualitySettings {
257 fn default() -> Self {
258 Self::high()
259 }
260}
261
262impl QualitySettings {
263 pub fn ultra() -> Self {
265 Self {
266 point_shadow_map_size: 2048,
267 point_shadows_distance: 20.0,
268 point_shadows_enabled: true,
269 point_soft_shadows: true,
270 point_shadows_fade_out_range: 1.0,
271
272 spot_shadow_map_size: 2048,
273 spot_shadows_distance: 20.0,
274 spot_shadows_enabled: true,
275 spot_soft_shadows: true,
276 spot_shadows_fade_out_range: 1.0,
277
278 use_ssao: true,
279 ssao_radius: 0.5,
280
281 light_scatter_enabled: true,
282
283 point_shadow_map_precision: ShadowMapPrecision::Full,
284 spot_shadow_map_precision: ShadowMapPrecision::Full,
285
286 fxaa: true,
287
288 use_bloom: true,
289
290 use_parallax_mapping: true,
291
292 csm_settings: Default::default(),
293
294 use_occlusion_culling: false,
295 use_light_occlusion_culling: false,
296 }
297 }
298
299 pub fn high() -> Self {
301 Self {
302 point_shadow_map_size: 1024,
303 point_shadows_distance: 15.0,
304 point_shadows_enabled: true,
305 point_soft_shadows: true,
306 point_shadows_fade_out_range: 1.0,
307
308 spot_shadow_map_size: 1024,
309 spot_shadows_distance: 15.0,
310 spot_shadows_enabled: true,
311 spot_soft_shadows: true,
312 spot_shadows_fade_out_range: 1.0,
313
314 use_ssao: true,
315 ssao_radius: 0.5,
316
317 light_scatter_enabled: true,
318
319 point_shadow_map_precision: ShadowMapPrecision::Full,
320 spot_shadow_map_precision: ShadowMapPrecision::Full,
321
322 fxaa: true,
323
324 use_bloom: true,
325
326 use_parallax_mapping: true,
327
328 csm_settings: CsmSettings {
329 enabled: true,
330 size: 2048,
331 precision: ShadowMapPrecision::Full,
332 pcf: true,
333 },
334
335 use_occlusion_culling: false,
336 use_light_occlusion_culling: false,
337 }
338 }
339
340 pub fn medium() -> Self {
342 Self {
343 point_shadow_map_size: 512,
344 point_shadows_distance: 5.0,
345 point_shadows_enabled: true,
346 point_soft_shadows: false,
347 point_shadows_fade_out_range: 1.0,
348
349 spot_shadow_map_size: 512,
350 spot_shadows_distance: 5.0,
351 spot_shadows_enabled: true,
352 spot_soft_shadows: false,
353 spot_shadows_fade_out_range: 1.0,
354
355 use_ssao: true,
356 ssao_radius: 0.5,
357
358 light_scatter_enabled: false,
359
360 point_shadow_map_precision: ShadowMapPrecision::Half,
361 spot_shadow_map_precision: ShadowMapPrecision::Half,
362
363 fxaa: true,
364
365 use_bloom: true,
366
367 use_parallax_mapping: false,
368
369 csm_settings: CsmSettings {
370 enabled: true,
371 size: 512,
372 precision: ShadowMapPrecision::Full,
373 pcf: false,
374 },
375
376 use_occlusion_culling: false,
377 use_light_occlusion_culling: false,
378 }
379 }
380
381 pub fn low() -> Self {
383 Self {
384 point_shadow_map_size: 1, point_shadows_distance: 0.0,
386 point_shadows_enabled: false,
387 point_soft_shadows: false,
388 point_shadows_fade_out_range: 1.0,
389
390 spot_shadow_map_size: 1,
391 spot_shadows_distance: 0.0,
392 spot_shadows_enabled: false,
393 spot_soft_shadows: false,
394 spot_shadows_fade_out_range: 1.0,
395
396 use_ssao: false,
397 ssao_radius: 0.5,
398
399 light_scatter_enabled: false,
400
401 point_shadow_map_precision: ShadowMapPrecision::Half,
402 spot_shadow_map_precision: ShadowMapPrecision::Half,
403
404 fxaa: false,
405
406 use_bloom: false,
407
408 use_parallax_mapping: false,
409
410 csm_settings: CsmSettings {
411 enabled: true,
412 size: 512,
413 precision: ShadowMapPrecision::Half,
414 pcf: false,
415 },
416
417 use_occlusion_culling: false,
418 use_light_occlusion_culling: false,
419 }
420 }
421}
422
423impl Statistics {
424 fn begin_frame(&mut self) {
426 self.frame_start_time = instant::Instant::now();
427 self.geometry = Default::default();
428 self.lighting = Default::default();
429 }
430
431 fn end_frame(&mut self) {
433 let current_time = instant::Instant::now();
434
435 self.pure_frame_time = current_time
436 .duration_since(self.frame_start_time)
437 .as_secs_f32();
438 self.frame_counter += 1;
439
440 if current_time
441 .duration_since(self.last_fps_commit_time)
442 .as_secs_f32()
443 >= 1.0
444 {
445 self.last_fps_commit_time = current_time;
446 self.frames_per_second = self.frame_counter;
447 self.frame_counter = 0;
448 }
449 }
450
451 fn finalize(&mut self) {
453 self.capped_frame_time = instant::Instant::now()
454 .duration_since(self.frame_start_time)
455 .as_secs_f32();
456 }
457}
458
459impl Default for Statistics {
460 fn default() -> Self {
461 Self {
462 pipeline: Default::default(),
463 lighting: Default::default(),
464 geometry: Default::default(),
465 pure_frame_time: 0.0,
466 capped_frame_time: 0.0,
467 frames_per_second: 0,
468 texture_cache_size: 0,
469 geometry_cache_size: 0,
470 shader_cache_size: 0,
471 uniform_buffer_cache_size: 0,
472 frame_counter: 0,
473 frame_start_time: instant::Instant::now(),
474 last_fps_commit_time: instant::Instant::now(),
475 }
476 }
477}
478
479pub struct AssociatedSceneData {
481 pub gbuffer: GBuffer,
483
484 pub hdr_scene_framebuffer: Box<dyn FrameBuffer>,
486
487 pub ldr_scene_framebuffer: Box<dyn FrameBuffer>,
489
490 pub ldr_temp_framebuffer: Box<dyn FrameBuffer>,
492
493 pub hdr_renderer: HighDynamicRangeRenderer,
496
497 pub bloom_renderer: BloomRenderer,
500
501 pub statistics: SceneStatistics,
503}
504
505impl AssociatedSceneData {
506 pub fn new(
508 server: &dyn GraphicsServer,
509 width: usize,
510 height: usize,
511 ) -> Result<Self, FrameworkError> {
512 let depth_stencil = server.create_2d_render_target(PixelKind::D24S8, width, height)?;
513 let hdr_frame_texture =
515 server.create_2d_render_target(PixelKind::RGBA16F, width, height)?;
516
517 let hdr_scene_framebuffer = server.create_frame_buffer(
518 Some(Attachment {
519 kind: AttachmentKind::DepthStencil,
520 texture: depth_stencil.clone(),
521 }),
522 vec![Attachment {
523 kind: AttachmentKind::Color,
524 texture: hdr_frame_texture,
525 }],
526 )?;
527
528 let ldr_frame_texture = server.create_texture(GpuTextureDescriptor {
529 kind: GpuTextureKind::Rectangle { width, height },
530 pixel_kind: PixelKind::RGBA8,
532 ..Default::default()
533 })?;
534
535 let ldr_scene_framebuffer = server.create_frame_buffer(
536 Some(Attachment {
537 kind: AttachmentKind::DepthStencil,
538 texture: depth_stencil.clone(),
539 }),
540 vec![Attachment {
541 kind: AttachmentKind::Color,
542 texture: ldr_frame_texture,
543 }],
544 )?;
545
546 let ldr_temp_texture = server.create_texture(GpuTextureDescriptor {
547 kind: GpuTextureKind::Rectangle { width, height },
548 pixel_kind: PixelKind::RGBA8,
550 ..Default::default()
551 })?;
552
553 let ldr_temp_framebuffer = server.create_frame_buffer(
554 Some(Attachment {
555 kind: AttachmentKind::DepthStencil,
556 texture: depth_stencil,
557 }),
558 vec![Attachment {
559 kind: AttachmentKind::Color,
560 texture: ldr_temp_texture,
561 }],
562 )?;
563
564 Ok(Self {
565 gbuffer: GBuffer::new(server, width, height)?,
566 hdr_renderer: HighDynamicRangeRenderer::new(server)?,
567 bloom_renderer: BloomRenderer::new(server, width, height)?,
568 hdr_scene_framebuffer,
569 ldr_scene_framebuffer,
570 ldr_temp_framebuffer,
571 statistics: Default::default(),
572 })
573 }
574
575 fn copy_depth_stencil_to_scene_framebuffer(&mut self) {
576 self.gbuffer.framebuffer().blit_to(
577 &*self.hdr_scene_framebuffer,
578 0,
579 0,
580 self.gbuffer.width,
581 self.gbuffer.height,
582 0,
583 0,
584 self.gbuffer.width,
585 self.gbuffer.height,
586 false,
587 true,
588 true,
589 );
590 }
591
592 pub fn hdr_scene_frame_texture(&self) -> Rc<RefCell<dyn GpuTexture>> {
594 self.hdr_scene_framebuffer.color_attachments()[0]
595 .texture
596 .clone()
597 }
598
599 pub fn ldr_scene_frame_texture(&self) -> Rc<RefCell<dyn GpuTexture>> {
601 self.ldr_scene_framebuffer.color_attachments()[0]
602 .texture
603 .clone()
604 }
605
606 pub fn ldr_temp_frame_texture(&self) -> Rc<RefCell<dyn GpuTexture>> {
608 self.ldr_temp_framebuffer.color_attachments()[0]
609 .texture
610 .clone()
611 }
612}
613
614pub fn make_viewport_matrix(viewport: Rect<i32>) -> Matrix4<f32> {
616 Matrix4::new_orthographic(
617 0.0,
618 viewport.w() as f32,
619 viewport.h() as f32,
620 0.0,
621 -1.0,
622 1.0,
623 ) * Matrix4::new_nonuniform_scaling(&Vector3::new(
624 viewport.w() as f32,
625 viewport.h() as f32,
626 0.0,
627 ))
628}
629
630pub struct FallbackResources {
633 pub white_dummy: Rc<RefCell<dyn GpuTexture>>,
636 pub black_dummy: Rc<RefCell<dyn GpuTexture>>,
638 pub environment_dummy: Rc<RefCell<dyn GpuTexture>>,
640 pub normal_dummy: Rc<RefCell<dyn GpuTexture>>,
643 pub metallic_dummy: Rc<RefCell<dyn GpuTexture>>,
646 pub volume_dummy: Rc<RefCell<dyn GpuTexture>>,
648 pub bone_matrices_stub_uniform_buffer: Box<dyn Buffer>,
650}
651
652impl FallbackResources {
653 pub fn sampler_fallback(
655 &self,
656 sampler_fallback: SamplerFallback,
657 ) -> &Rc<RefCell<dyn GpuTexture>> {
658 match sampler_fallback {
659 SamplerFallback::White => &self.white_dummy,
660 SamplerFallback::Normal => &self.normal_dummy,
661 SamplerFallback::Black => &self.black_dummy,
662 SamplerFallback::Volume => &self.volume_dummy,
663 }
664 }
665}
666
667pub struct Renderer {
669 backbuffer: Box<dyn FrameBuffer>,
670 scene_render_passes: Vec<Rc<RefCell<dyn SceneRenderPass>>>,
671 deferred_light_renderer: DeferredLightRenderer,
672 flat_shader: FlatShader,
673 pub fallback_resources: FallbackResources,
676 pub ui_renderer: UiRenderer,
678 statistics: Statistics,
679 quad: Box<dyn GeometryBuffer>,
680 frame_size: (u32, u32),
681 quality_settings: QualitySettings,
682 pub debug_renderer: DebugRenderer,
684 pub screen_space_debug_renderer: DebugRenderer,
687 pub scene_data_map: FxHashMap<Handle<Scene>, AssociatedSceneData>,
689 backbuffer_clear_color: Color,
690 pub texture_cache: TextureCache,
692 pub uniform_buffer_cache: UniformBufferCache,
694 shader_cache: ShaderCache,
695 geometry_cache: GeometryCache,
696 forward_renderer: ForwardRenderer,
697 fxaa_renderer: FxaaRenderer,
698 texture_event_receiver: Receiver<ResourceEvent>,
699 shader_event_receiver: Receiver<ResourceEvent>,
700 ui_frame_buffers: FxHashMap<u64, Box<dyn FrameBuffer>>,
703 uniform_memory_allocator: UniformMemoryAllocator,
704 pub visibility_cache: VisibilityCache,
706 pub server: SharedGraphicsServer,
708}
709
710fn make_ui_frame_buffer(
711 frame_size: Vector2<f32>,
712 server: &dyn GraphicsServer,
713 pixel_kind: PixelKind,
714) -> Result<Box<dyn FrameBuffer>, FrameworkError> {
715 let color_texture = server.create_texture(GpuTextureDescriptor {
716 kind: GpuTextureKind::Rectangle {
717 width: frame_size.x as usize,
718 height: frame_size.y as usize,
719 },
720 pixel_kind,
721 ..Default::default()
722 })?;
723
724 let depth_stencil = server.create_2d_render_target(
725 PixelKind::D24S8,
726 frame_size.x as usize,
727 frame_size.y as usize,
728 )?;
729
730 server.create_frame_buffer(
731 Some(Attachment {
732 kind: AttachmentKind::DepthStencil,
733 texture: depth_stencil,
734 }),
735 vec![Attachment {
736 kind: AttachmentKind::Color,
737 texture: color_texture,
738 }],
739 )
740}
741
742pub struct SceneRenderPassContext<'a, 'b> {
744 pub elapsed_time: f32,
748 pub server: &'a dyn GraphicsServer,
750
751 pub texture_cache: &'a mut TextureCache,
754
755 pub geometry_cache: &'a mut GeometryCache,
759
760 pub shader_cache: &'a mut ShaderCache,
764
765 pub bundle_storage: &'a RenderDataBundleStorage,
767
768 pub quality_settings: &'a QualitySettings,
770
771 pub framebuffer: &'a mut dyn FrameBuffer,
773
774 pub scene: &'b Scene,
776
777 pub camera: &'b Camera,
779
780 pub viewport: Rect<i32>,
782
783 pub scene_handle: Handle<Scene>,
785
786 pub fallback_resources: &'a FallbackResources,
789
790 pub depth_texture: Rc<RefCell<dyn GpuTexture>>,
798
799 pub normal_texture: Rc<RefCell<dyn GpuTexture>>,
806
807 pub ambient_texture: Rc<RefCell<dyn GpuTexture>>,
814
815 pub ui_renderer: &'a mut UiRenderer,
817
818 pub uniform_buffer_cache: &'a mut UniformBufferCache,
820
821 pub uniform_memory_allocator: &'a mut UniformMemoryAllocator,
824}
825
826pub trait SceneRenderPass {
828 fn on_hdr_render(
831 &mut self,
832 _ctx: SceneRenderPassContext,
833 ) -> Result<RenderPassStatistics, FrameworkError> {
834 Ok(RenderPassStatistics::default())
835 }
836
837 fn on_ldr_render(
840 &mut self,
841 _ctx: SceneRenderPassContext,
842 ) -> Result<RenderPassStatistics, FrameworkError> {
843 Ok(RenderPassStatistics::default())
844 }
845
846 fn source_type_id(&self) -> TypeId;
850}
851
852fn blit_pixels(
853 uniform_buffer_cache: &mut UniformBufferCache,
854 framebuffer: &mut dyn FrameBuffer,
855 texture: Rc<RefCell<dyn GpuTexture>>,
856 shader: &FlatShader,
857 viewport: Rect<i32>,
858 quad: &dyn GeometryBuffer,
859) -> Result<DrawCallStatistics, FrameworkError> {
860 let matrix = make_viewport_matrix(viewport);
861 let uniform_buffer =
862 uniform_buffer_cache.write(StaticUniformBuffer::<256>::new().with(&matrix))?;
863 framebuffer.draw(
864 quad,
865 viewport,
866 &*shader.program,
867 &DrawParameters {
868 cull_face: None,
869 color_write: Default::default(),
870 depth_write: true,
871 stencil_test: None,
872 depth_test: None,
873 blend: None,
874 stencil_op: Default::default(),
875 scissor_box: None,
876 },
877 &[ResourceBindGroup {
878 bindings: &[
879 ResourceBinding::texture(&texture, &shader.diffuse_texture),
880 ResourceBinding::Buffer {
881 buffer: uniform_buffer,
882 binding: BufferLocation::Auto {
883 shader_location: shader.uniform_buffer_binding,
884 },
885 data_usage: Default::default(),
886 },
887 ],
888 }],
889 ElementRange::Full,
890 )
891}
892
893#[allow(missing_docs)] pub struct LightData<const N: usize = 16> {
895 pub count: usize,
896 pub color_radius: [Vector4<f32>; N],
897 pub position: [Vector3<f32>; N],
898 pub direction: [Vector3<f32>; N],
899 pub parameters: [Vector2<f32>; N],
900}
901
902impl<const N: usize> Default for LightData<N> {
903 fn default() -> Self {
904 Self {
905 count: 0,
906 color_radius: [Default::default(); N],
907 position: [Default::default(); N],
908 direction: [Default::default(); N],
909 parameters: [Default::default(); N],
910 }
911 }
912}
913
914impl Renderer {
915 pub fn new(
917 server: Rc<dyn GraphicsServer>,
918 frame_size: (u32, u32),
919 resource_manager: &ResourceManager,
920 ) -> Result<Self, EngineError> {
921 let settings = QualitySettings::default();
922
923 let (texture_event_sender, texture_event_receiver) = std::sync::mpsc::channel();
924
925 resource_manager
926 .state()
927 .event_broadcaster
928 .add(texture_event_sender);
929
930 let (shader_event_sender, shader_event_receiver) = std::sync::mpsc::channel();
931
932 resource_manager
933 .state()
934 .event_broadcaster
935 .add(shader_event_sender);
936
937 let caps = server.capabilities();
938 Log::info(format!("Graphics Server Capabilities\n{caps:?}",));
939
940 let shader_cache = ShaderCache::default();
941
942 let one_megabyte = 1024 * 1024;
943 let uniform_memory_allocator = UniformMemoryAllocator::new(
944 caps.max_uniform_block_size.min(one_megabyte),
948 caps.uniform_buffer_offset_alignment,
949 );
950
951 let fallback_resources = FallbackResources {
952 white_dummy: server.create_texture(GpuTextureDescriptor {
953 kind: GpuTextureKind::Rectangle {
954 width: 1,
955 height: 1,
956 },
957 pixel_kind: PixelKind::RGBA8,
958 data: Some(&[255u8, 255u8, 255u8, 255u8]),
959 ..Default::default()
960 })?,
961 black_dummy: server.create_texture(GpuTextureDescriptor {
962 kind: GpuTextureKind::Rectangle {
963 width: 1,
964 height: 1,
965 },
966 pixel_kind: PixelKind::RGBA8,
967 data: Some(&[0u8, 0u8, 0u8, 255u8]),
968 ..Default::default()
969 })?,
970 environment_dummy: server.create_texture(GpuTextureDescriptor {
971 kind: GpuTextureKind::Cube {
972 width: 1,
973 height: 1,
974 },
975 pixel_kind: PixelKind::RGBA8,
976 data: Some(&[
977 0u8, 0u8, 0u8, 255u8, 0u8, 0u8, 0u8, 255u8, 0u8, 0u8, 0u8, 255u8, 0u8, 0u8, 0u8, 255u8, 0u8, 0u8, 0u8, 255u8, 0u8, 0u8, 0u8, 255u8, ]),
984 ..Default::default()
985 })?,
986 normal_dummy: server.create_texture(GpuTextureDescriptor {
987 kind: GpuTextureKind::Rectangle {
988 width: 1,
989 height: 1,
990 },
991 pixel_kind: PixelKind::RGBA8,
992 data: Some(&[128u8, 128u8, 255u8, 255u8]),
993 ..Default::default()
994 })?,
995 metallic_dummy: server.create_texture(GpuTextureDescriptor {
996 kind: GpuTextureKind::Rectangle {
997 width: 1,
998 height: 1,
999 },
1000 pixel_kind: PixelKind::RGBA8,
1001 data: Some(&[0u8, 0u8, 0u8, 0u8]),
1002 ..Default::default()
1003 })?,
1004 volume_dummy: server.create_texture(GpuTextureDescriptor {
1005 kind: GpuTextureKind::Volume {
1006 width: 1,
1007 height: 1,
1008 depth: 1,
1009 },
1010 pixel_kind: PixelKind::RGBA8,
1011 data: Some(&[0u8, 0u8, 0u8, 0u8]),
1012 ..Default::default()
1013 })?,
1014 bone_matrices_stub_uniform_buffer: {
1015 let buffer = server.create_buffer(
1016 ShaderDefinition::MAX_BONE_MATRICES * size_of::<Matrix4<f32>>(),
1017 BufferKind::Uniform,
1018 BufferUsage::StaticDraw,
1019 )?;
1020 const SIZE: usize = ShaderDefinition::MAX_BONE_MATRICES * size_of::<Matrix4<f32>>();
1021 let zeros = [0.0; SIZE];
1022 buffer.write_data(array_as_u8_slice(&zeros))?;
1023 buffer
1024 },
1025 };
1026
1027 Ok(Self {
1028 backbuffer: server.back_buffer(),
1029 frame_size,
1030 deferred_light_renderer: DeferredLightRenderer::new(&*server, frame_size, &settings)?,
1031 flat_shader: FlatShader::new(&*server)?,
1032 fallback_resources,
1033 quad: <dyn GeometryBuffer>::from_surface_data(
1034 &SurfaceData::make_unit_xy_quad(),
1035 BufferUsage::StaticDraw,
1036 &*server,
1037 )?,
1038
1039 ui_renderer: UiRenderer::new(&*server)?,
1040 quality_settings: settings,
1041 debug_renderer: DebugRenderer::new(&*server)?,
1042 screen_space_debug_renderer: DebugRenderer::new(&*server)?,
1043 scene_data_map: Default::default(),
1044 backbuffer_clear_color: Color::BLACK,
1045 texture_cache: Default::default(),
1046 geometry_cache: Default::default(),
1047 forward_renderer: ForwardRenderer::new(),
1048 ui_frame_buffers: Default::default(),
1049 fxaa_renderer: FxaaRenderer::new(&*server)?,
1050 statistics: Statistics::default(),
1051 shader_event_receiver,
1052 texture_event_receiver,
1053 shader_cache,
1054 scene_render_passes: Default::default(),
1055 uniform_buffer_cache: UniformBufferCache::new(server.clone()),
1056 server,
1057 visibility_cache: Default::default(),
1058 uniform_memory_allocator,
1059 })
1060 }
1061
1062 pub fn add_render_pass(&mut self, pass: Rc<RefCell<dyn SceneRenderPass>>) {
1064 self.scene_render_passes.push(pass);
1065 }
1066
1067 pub fn remove_render_pass(&mut self, pass: Rc<RefCell<dyn SceneRenderPass>>) {
1069 if let Some(index) = self
1070 .scene_render_passes
1071 .iter()
1072 .position(|p| Rc::ptr_eq(p, &pass))
1073 {
1074 self.scene_render_passes.remove(index);
1075 }
1076 }
1077
1078 pub fn render_passes(&self) -> &[Rc<RefCell<dyn SceneRenderPass>>] {
1080 &self.scene_render_passes
1081 }
1082
1083 pub fn clear_render_passes(&mut self) {
1085 self.scene_render_passes.clear()
1086 }
1087
1088 pub fn get_statistics(&self) -> Statistics {
1090 self.statistics
1091 }
1092
1093 pub fn unload_texture(&mut self, texture: TextureResource) {
1095 self.texture_cache.unload(texture)
1096 }
1097
1098 pub fn set_backbuffer_clear_color(&mut self, color: Color) {
1100 self.backbuffer_clear_color = color;
1101 }
1102
1103 pub fn graphics_server(&self) -> &dyn GraphicsServer {
1105 &*self.server
1106 }
1107
1108 pub(crate) fn set_frame_size(&mut self, new_size: (u32, u32)) -> Result<(), FrameworkError> {
1117 self.frame_size.0 = new_size.0.max(1);
1118 self.frame_size.1 = new_size.1.max(1);
1119
1120 self.deferred_light_renderer
1121 .set_frame_size(&*self.server, new_size)?;
1122
1123 self.graphics_server().set_frame_size(new_size);
1124
1125 Ok(())
1126 }
1127
1128 pub fn get_frame_size(&self) -> (u32, u32) {
1130 self.frame_size
1131 }
1132
1133 pub fn get_frame_bounds(&self) -> Vector2<f32> {
1135 Vector2::new(self.frame_size.0 as f32, self.frame_size.1 as f32)
1136 }
1137
1138 pub fn set_quality_settings(
1142 &mut self,
1143 settings: &QualitySettings,
1144 ) -> Result<(), FrameworkError> {
1145 self.quality_settings = *settings;
1146 self.deferred_light_renderer
1147 .set_quality_settings(&*self.server, settings)
1148 }
1149
1150 pub fn get_quality_settings(&self) -> QualitySettings {
1152 self.quality_settings
1153 }
1154
1155 pub fn flush(&mut self) {
1159 self.texture_cache.clear();
1160 self.geometry_cache.clear();
1161 }
1162
1163 pub fn render_ui_to_texture(
1166 &mut self,
1167 render_target: TextureResource,
1168 screen_size: Vector2<f32>,
1169 drawing_context: &DrawingContext,
1170 clear_color: Color,
1171 pixel_kind: PixelKind,
1172 ) -> Result<(), FrameworkError> {
1173 let new_width = screen_size.x as usize;
1174 let new_height = screen_size.y as usize;
1175
1176 let frame_buffer = match self.ui_frame_buffers.entry(render_target.key()) {
1178 Entry::Occupied(entry) => {
1179 let frame_buffer = entry.into_mut();
1180 let frame = frame_buffer.color_attachments().first().unwrap();
1181 let color_texture_kind = frame.texture.borrow().kind();
1182 if let GpuTextureKind::Rectangle { width, height } = color_texture_kind {
1183 if width != new_width
1184 || height != new_height
1185 || frame.texture.borrow().pixel_kind() != pixel_kind
1186 {
1187 *frame_buffer =
1188 make_ui_frame_buffer(screen_size, &*self.server, pixel_kind)?;
1189 }
1190 } else {
1191 panic!("ui can be rendered only in rectangle texture!")
1192 }
1193 frame_buffer
1194 }
1195 Entry::Vacant(entry) => entry.insert(make_ui_frame_buffer(
1196 screen_size,
1197 &*self.server,
1198 pixel_kind,
1199 )?),
1200 };
1201 let frame_buffer = &mut **frame_buffer;
1202
1203 let viewport = Rect::new(0, 0, new_width as i32, new_height as i32);
1204
1205 frame_buffer.clear(viewport, Some(clear_color), Some(0.0), Some(0));
1206
1207 self.statistics += self.ui_renderer.render(UiRenderContext {
1208 server: &*self.server,
1209 viewport,
1210 frame_buffer,
1211 frame_width: screen_size.x,
1212 frame_height: screen_size.y,
1213 drawing_context,
1214 fallback_resources: &self.fallback_resources,
1215 texture_cache: &mut self.texture_cache,
1216 uniform_buffer_cache: &mut self.uniform_buffer_cache,
1217 flat_shader: &self.flat_shader,
1218 })?;
1219
1220 self.texture_cache.try_register(
1223 &render_target,
1224 frame_buffer
1225 .color_attachments()
1226 .first()
1227 .unwrap()
1228 .texture
1229 .clone(),
1230 );
1231
1232 Ok(())
1233 }
1234
1235 fn update_texture_cache(&mut self, dt: f32) {
1236 const THROUGHPUT: usize = 5;
1240
1241 let mut uploaded = 0;
1242 while let Ok(event) = self.texture_event_receiver.try_recv() {
1243 if let ResourceEvent::Loaded(resource) | ResourceEvent::Reloaded(resource) = event {
1244 if let Some(texture) = resource.try_cast::<Texture>() {
1245 match self.texture_cache.upload(&*self.server, &texture) {
1246 Ok(_) => {
1247 uploaded += 1;
1248 if uploaded >= THROUGHPUT {
1249 break;
1250 }
1251 }
1252 Err(e) => {
1253 Log::writeln(
1254 MessageKind::Error,
1255 format!("Failed to upload texture to GPU. Reason: {e:?}"),
1256 );
1257 }
1258 }
1259 }
1260 }
1261 }
1262
1263 self.texture_cache.update(dt);
1264 }
1265
1266 fn update_shader_cache(&mut self, dt: f32) {
1267 while let Ok(event) = self.shader_event_receiver.try_recv() {
1268 if let ResourceEvent::Loaded(resource) | ResourceEvent::Reloaded(resource) = event {
1269 if let Some(shader) = resource.try_cast::<Shader>() {
1270 self.shader_cache.remove(&shader);
1272 let _ = self.shader_cache.get(&*self.server, &shader);
1273 }
1274 }
1275 }
1276
1277 self.shader_cache.update(dt)
1278 }
1279
1280 pub fn update_caches(&mut self, dt: f32) {
1285 self.update_texture_cache(dt);
1286 self.update_shader_cache(dt);
1287 self.geometry_cache.update(dt);
1288 }
1289
1290 pub fn render_scene(
1293 &mut self,
1294 scene_handle: Handle<Scene>,
1295 scene: &Scene,
1296 elapsed_time: f32,
1297 dt: f32,
1298 ) -> Result<&AssociatedSceneData, FrameworkError> {
1299 let graph = &scene.graph;
1300
1301 let backbuffer_width = self.frame_size.0 as f32;
1302 let backbuffer_height = self.frame_size.1 as f32;
1303
1304 let window_viewport = Rect::new(0, 0, self.frame_size.0 as i32, self.frame_size.1 as i32);
1305
1306 let frame_size = scene
1307 .rendering_options
1308 .render_target
1309 .as_ref()
1310 .map_or_else(
1311 || Vector2::new(backbuffer_width, backbuffer_height),
1313 |rt| {
1315 if let TextureKind::Rectangle { width, height } = rt.data_ref().kind() {
1316 Vector2::new(width as f32, height as f32)
1317 } else {
1318 panic!("only rectangle textures can be used as render target!")
1319 }
1320 },
1321 )
1322 .sup(&Vector2::new(1.0, 1.0));
1324
1325 let server = &*self.server;
1326
1327 let scene_associated_data = self
1328 .scene_data_map
1329 .entry(scene_handle)
1330 .and_modify(|data| {
1331 if data.gbuffer.width != frame_size.x as i32
1332 || data.gbuffer.height != frame_size.y as i32
1333 {
1334 let width = frame_size.x as usize;
1335 let height = frame_size.y as usize;
1336
1337 Log::info(format!(
1338 "Associated scene rendering data was re-created for scene {}, because render frame size was changed. Old is {}x{}, new {}x{}!",
1339 scene_handle,
1340 data.gbuffer.width,data.gbuffer.height,width,height
1341 ));
1342
1343 *data = AssociatedSceneData::new(server, width, height).unwrap();
1344 }
1345 })
1346 .or_insert_with(|| {
1347 let width = frame_size.x as usize;
1348 let height = frame_size.y as usize;
1349
1350 Log::info(format!(
1351 "A new associated scene rendering data was created for scene {scene_handle}!"
1352 ));
1353
1354 AssociatedSceneData::new(server, width, height).unwrap()
1355 });
1356
1357 let pipeline_stats = server.pipeline_statistics();
1358 scene_associated_data.statistics = Default::default();
1359
1360 if let Some(rt) = scene.rendering_options.render_target.clone() {
1364 self.texture_cache
1365 .try_register(&rt, scene_associated_data.ldr_scene_frame_texture());
1366 }
1367
1368 for (camera_handle, camera) in graph.pair_iter().filter_map(|(handle, node)| {
1369 if node.is_globally_enabled() {
1370 if let Some(camera) = node.cast::<Camera>() {
1371 if camera.is_enabled() {
1372 return Some((handle, camera));
1373 }
1374 }
1375 }
1376 None
1377 }) {
1378 let visibility_cache = self.visibility_cache.get_or_register(graph, camera_handle);
1379
1380 let viewport = camera.viewport_pixels(frame_size);
1381
1382 let bundle_storage = RenderDataBundleStorage::from_graph(
1383 graph,
1384 elapsed_time,
1385 ObserverInfo {
1386 observer_position: camera.global_position(),
1387 z_near: camera.projection().z_near(),
1388 z_far: camera.projection().z_far(),
1389 view_matrix: camera.view_matrix(),
1390 projection_matrix: camera.projection_matrix(),
1391 },
1392 GBUFFER_PASS_NAME.clone(),
1393 RenderDataBundleStorageOptions {
1394 collect_lights: true,
1395 },
1396 );
1397
1398 server.set_polygon_fill_mode(
1399 PolygonFace::FrontAndBack,
1400 scene.rendering_options.polygon_rasterization_mode,
1401 );
1402
1403 scene_associated_data.statistics +=
1404 scene_associated_data.gbuffer.fill(GBufferRenderContext {
1405 server,
1406 camera,
1407 geom_cache: &mut self.geometry_cache,
1408 bundle_storage: &bundle_storage,
1409 texture_cache: &mut self.texture_cache,
1410 shader_cache: &mut self.shader_cache,
1411 quality_settings: &self.quality_settings,
1412 fallback_resources: &self.fallback_resources,
1413 graph,
1414 uniform_buffer_cache: &mut self.uniform_buffer_cache,
1415 uniform_memory_allocator: &mut self.uniform_memory_allocator,
1416 screen_space_debug_renderer: &mut self.screen_space_debug_renderer,
1417 unit_quad: &*self.quad,
1418 })?;
1419
1420 server.set_polygon_fill_mode(PolygonFace::FrontAndBack, PolygonFillMode::Fill);
1421
1422 scene_associated_data.copy_depth_stencil_to_scene_framebuffer();
1423
1424 scene_associated_data.hdr_scene_framebuffer.clear(
1425 viewport,
1426 Some(
1427 scene
1428 .rendering_options
1429 .clear_color
1430 .unwrap_or(self.backbuffer_clear_color),
1431 ),
1432 None, Some(0),
1434 );
1435
1436 let (pass_stats, light_stats) =
1437 self.deferred_light_renderer
1438 .render(DeferredRendererContext {
1439 elapsed_time,
1440 server,
1441 scene,
1442 camera,
1443 gbuffer: &mut scene_associated_data.gbuffer,
1444 ambient_color: scene.rendering_options.ambient_lighting_color,
1445 render_data_bundle: &bundle_storage,
1446 settings: &self.quality_settings,
1447 textures: &mut self.texture_cache,
1448 geometry_cache: &mut self.geometry_cache,
1449 frame_buffer: &mut *scene_associated_data.hdr_scene_framebuffer,
1450 shader_cache: &mut self.shader_cache,
1451 fallback_resources: &self.fallback_resources,
1452 uniform_buffer_cache: &mut self.uniform_buffer_cache,
1453 visibility_cache,
1454 uniform_memory_allocator: &mut self.uniform_memory_allocator,
1455 })?;
1456
1457 scene_associated_data.statistics += light_stats;
1458 scene_associated_data.statistics += pass_stats;
1459
1460 let depth = scene_associated_data.gbuffer.depth();
1461
1462 scene_associated_data.statistics +=
1463 self.forward_renderer.render(ForwardRenderContext {
1464 state: server,
1465 geom_cache: &mut self.geometry_cache,
1466 texture_cache: &mut self.texture_cache,
1467 shader_cache: &mut self.shader_cache,
1468 bundle_storage: &bundle_storage,
1469 framebuffer: &mut *scene_associated_data.hdr_scene_framebuffer,
1470 viewport,
1471 quality_settings: &self.quality_settings,
1472 fallback_resources: &self.fallback_resources,
1473 scene_depth: depth,
1474 ambient_light: scene.rendering_options.ambient_lighting_color,
1475 uniform_memory_allocator: &mut self.uniform_memory_allocator,
1476 })?;
1477
1478 for render_pass in self.scene_render_passes.iter() {
1479 scene_associated_data.statistics +=
1480 render_pass
1481 .borrow_mut()
1482 .on_hdr_render(SceneRenderPassContext {
1483 elapsed_time,
1484 server,
1485 texture_cache: &mut self.texture_cache,
1486 geometry_cache: &mut self.geometry_cache,
1487 shader_cache: &mut self.shader_cache,
1488 quality_settings: &self.quality_settings,
1489 bundle_storage: &bundle_storage,
1490 viewport,
1491 scene,
1492 camera,
1493 scene_handle,
1494 fallback_resources: &self.fallback_resources,
1495 depth_texture: scene_associated_data.gbuffer.depth(),
1496 normal_texture: scene_associated_data.gbuffer.normal_texture(),
1497 ambient_texture: scene_associated_data.gbuffer.ambient_texture(),
1498 framebuffer: &mut *scene_associated_data.hdr_scene_framebuffer,
1499 ui_renderer: &mut self.ui_renderer,
1500 uniform_buffer_cache: &mut self.uniform_buffer_cache,
1501 uniform_memory_allocator: &mut self.uniform_memory_allocator,
1502 })?;
1503 }
1504
1505 let quad = &self.quad;
1506
1507 scene_associated_data.statistics += scene_associated_data.bloom_renderer.render(
1509 &**quad,
1510 scene_associated_data.hdr_scene_frame_texture(),
1511 &mut self.uniform_buffer_cache,
1512 )?;
1513
1514 scene_associated_data.statistics += scene_associated_data.hdr_renderer.render(
1516 server,
1517 scene_associated_data.hdr_scene_frame_texture(),
1518 scene_associated_data.bloom_renderer.result(),
1519 &mut *scene_associated_data.ldr_scene_framebuffer,
1520 viewport,
1521 &**quad,
1522 dt,
1523 camera.exposure(),
1524 camera.color_grading_lut_ref(),
1525 camera.color_grading_enabled(),
1526 &mut self.texture_cache,
1527 &mut self.uniform_buffer_cache,
1528 )?;
1529
1530 if self.quality_settings.fxaa {
1532 scene_associated_data.statistics += self.fxaa_renderer.render(
1533 viewport,
1534 scene_associated_data.ldr_scene_frame_texture(),
1535 &mut *scene_associated_data.ldr_temp_framebuffer,
1536 &mut self.uniform_buffer_cache,
1537 )?;
1538
1539 let quad = &self.quad;
1540 let temp_frame_texture = scene_associated_data.ldr_temp_frame_texture();
1541 scene_associated_data.statistics += blit_pixels(
1542 &mut self.uniform_buffer_cache,
1543 &mut *scene_associated_data.ldr_scene_framebuffer,
1544 temp_frame_texture,
1545 &self.flat_shader,
1546 viewport,
1547 &**quad,
1548 )?;
1549 }
1550
1551 self.debug_renderer.set_lines(&scene.drawing_context.lines);
1553 scene_associated_data.statistics += self.debug_renderer.render(
1554 &mut self.uniform_buffer_cache,
1555 viewport,
1556 &mut *scene_associated_data.ldr_scene_framebuffer,
1557 camera.view_projection_matrix(),
1558 )?;
1559
1560 for render_pass in self.scene_render_passes.iter() {
1561 scene_associated_data.statistics +=
1562 render_pass
1563 .borrow_mut()
1564 .on_ldr_render(SceneRenderPassContext {
1565 elapsed_time,
1566 server,
1567 texture_cache: &mut self.texture_cache,
1568 geometry_cache: &mut self.geometry_cache,
1569 shader_cache: &mut self.shader_cache,
1570 quality_settings: &self.quality_settings,
1571 bundle_storage: &bundle_storage,
1572 viewport,
1573 scene,
1574 camera,
1575 scene_handle,
1576 fallback_resources: &self.fallback_resources,
1577 depth_texture: scene_associated_data.gbuffer.depth(),
1578 normal_texture: scene_associated_data.gbuffer.normal_texture(),
1579 ambient_texture: scene_associated_data.gbuffer.ambient_texture(),
1580 framebuffer: &mut *scene_associated_data.ldr_scene_framebuffer,
1581 ui_renderer: &mut self.ui_renderer,
1582 uniform_buffer_cache: &mut self.uniform_buffer_cache,
1583 uniform_memory_allocator: &mut self.uniform_memory_allocator,
1584 })?;
1585 }
1586 }
1587
1588 self.visibility_cache.update(graph);
1589
1590 if scene.rendering_options.render_target.is_none() {
1592 let quad = &self.quad;
1593 scene_associated_data.statistics += blit_pixels(
1594 &mut self.uniform_buffer_cache,
1595 &mut *self.backbuffer,
1596 scene_associated_data.ldr_scene_frame_texture(),
1597 &self.flat_shader,
1598 window_viewport,
1599 &**quad,
1600 )?;
1601 }
1602
1603 self.statistics += scene_associated_data.statistics;
1604 scene_associated_data.statistics.pipeline = server.pipeline_statistics() - pipeline_stats;
1605
1606 Ok(scene_associated_data)
1607 }
1608
1609 fn render_frame<'a>(
1610 &mut self,
1611 scenes: &SceneContainer,
1612 elapsed_time: f32,
1613 drawing_contexts: impl Iterator<Item = &'a DrawingContext>,
1614 ) -> Result<(), FrameworkError> {
1615 if self.frame_size.0 == 0 || self.frame_size.1 == 0 {
1616 return Ok(());
1617 }
1618
1619 self.uniform_buffer_cache.mark_all_unused();
1620 self.uniform_memory_allocator.clear();
1621
1622 self.scene_data_map
1624 .retain(|h, _| scenes.is_valid_handle(*h));
1625
1626 self.server.invalidate_resource_bindings_cache();
1631 let dt = self.statistics.capped_frame_time;
1632 self.statistics.begin_frame();
1633
1634 let window_viewport = Rect::new(0, 0, self.frame_size.0 as i32, self.frame_size.1 as i32);
1635 self.backbuffer.clear(
1636 window_viewport,
1637 Some(self.backbuffer_clear_color),
1638 Some(1.0),
1639 Some(0),
1640 );
1641
1642 let backbuffer_width = self.frame_size.0 as f32;
1643 let backbuffer_height = self.frame_size.1 as f32;
1644
1645 for (scene_handle, scene) in scenes.pair_iter().filter(|(_, s)| *s.enabled) {
1646 self.render_scene(scene_handle, scene, elapsed_time, dt)?;
1647 }
1648
1649 self.graphics_server()
1650 .set_polygon_fill_mode(PolygonFace::FrontAndBack, PolygonFillMode::Fill);
1651
1652 for drawing_context in drawing_contexts {
1654 self.statistics += self.ui_renderer.render(UiRenderContext {
1655 server: &*self.server,
1656 viewport: window_viewport,
1657 frame_buffer: &mut *self.backbuffer,
1658 frame_width: backbuffer_width,
1659 frame_height: backbuffer_height,
1660 drawing_context,
1661 fallback_resources: &self.fallback_resources,
1662 texture_cache: &mut self.texture_cache,
1663 uniform_buffer_cache: &mut self.uniform_buffer_cache,
1664 flat_shader: &self.flat_shader,
1665 })?;
1666 }
1667
1668 let screen_matrix =
1669 Matrix4::new_orthographic(0.0, backbuffer_width, backbuffer_height, 0.0, -1.0, 1.0);
1670 self.screen_space_debug_renderer.render(
1671 &mut self.uniform_buffer_cache,
1672 window_viewport,
1673 &mut *self.backbuffer,
1674 screen_matrix,
1675 )?;
1676
1677 self.statistics.geometry_cache_size = self.geometry_cache.alive_count();
1678 self.statistics.texture_cache_size = self.texture_cache.alive_count();
1679 self.statistics.shader_cache_size = self.shader_cache.alive_count();
1680 self.statistics.uniform_buffer_cache_size = self.uniform_buffer_cache.alive_count();
1681
1682 Ok(())
1683 }
1684
1685 pub(crate) fn render_and_swap_buffers<'a>(
1686 &mut self,
1687 scenes: &SceneContainer,
1688 elapsed_time: f32,
1689 drawing_contexts: impl Iterator<Item = &'a DrawingContext>,
1690 window: &Window,
1691 ) -> Result<(), FrameworkError> {
1692 self.render_frame(scenes, elapsed_time, drawing_contexts)?;
1693 self.statistics.end_frame();
1694 window.pre_present_notify();
1695 self.graphics_server().swap_buffers()?;
1696 self.statistics.finalize();
1697 self.statistics.pipeline = self.server.pipeline_statistics();
1698 Ok(())
1699 }
1700}