1#![warn(missing_docs)]
26
27pub mod framework;
28
29pub mod bundle;
30pub mod cache;
31pub mod debug_renderer;
32pub mod observer;
33pub mod resources;
34pub mod stats;
35pub mod storage;
36pub mod ui_renderer;
37pub mod utils;
38pub mod visibility;
39
40mod bloom;
41mod convolution;
42mod fxaa;
43mod gbuffer;
44mod hdr;
45mod light;
46mod light_volume;
47mod occlusion;
48mod settings;
49mod shadow;
50mod ssao;
51
52use crate::{
53 asset::{event::ResourceEvent, manager::ResourceManager},
54 core::{
55 algebra::{Matrix4, Vector2, Vector3},
56 color::Color,
57 info,
58 log::{Log, MessageKind},
59 math::Rect,
60 pool::Handle,
61 sstorage::ImmutableString,
62 },
63 engine::error::EngineError,
64 graphics::{
65 error::FrameworkError,
66 framebuffer::{Attachment, DrawCallStatistics, GpuFrameBuffer},
67 gpu_texture::{GpuTexture, GpuTextureDescriptor, GpuTextureKind, PixelKind},
68 server::{GraphicsServer, SharedGraphicsServer},
69 PolygonFace, PolygonFillMode,
70 },
71 material::shader::Shader,
72 renderer::{
73 bloom::BloomRenderer,
74 bundle::{BundleRenderContext, RenderDataBundleStorage, RenderDataBundleStorageOptions},
75 cache::texture::convert_pixel_kind,
76 cache::{
77 geometry::GeometryCache,
78 shader::{
79 binding, property, PropertyGroup, RenderMaterial, RenderPassContainer, ShaderCache,
80 },
81 texture::TextureCache,
82 uniform::{UniformBufferCache, UniformMemoryAllocator},
83 },
84 convolution::{EnvironmentMapIrradianceConvolution, EnvironmentMapSpecularConvolution},
85 debug_renderer::DebugRenderer,
86 fxaa::FxaaRenderer,
87 gbuffer::{GBuffer, GBufferRenderContext},
88 hdr::HighDynamicRangeRenderer,
89 light::{DeferredLightRenderer, DeferredRendererContext},
90 ssao::ScreenSpaceAmbientOcclusionRenderer,
91 ui_renderer::UiRenderInfo,
92 ui_renderer::{UiRenderContext, UiRenderer},
93 visibility::VisibilityCache,
94 },
95 resource::texture::{Texture, TextureKind, TextureResource},
96 scene::{mesh::RenderPath, node::Node, Scene, SceneContainer},
97};
98use cache::DynamicSurfaceCache;
99use fxhash::FxHashMap;
100use fyrox_graph::BaseSceneGraph;
101use lazy_static::lazy_static;
102use observer::{Observer, ObserversCollection};
103use resources::RendererResources;
104pub use settings::*;
105pub use stats::*;
106use std::{
107 any::{Any, TypeId},
108 cell::RefCell,
109 collections::hash_map::Entry,
110 rc::Rc,
111 sync::mpsc::Receiver,
112};
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
130pub struct SceneRenderData {
132 pub camera_data: FxHashMap<Handle<Node>, RenderDataContainer>,
134 pub scene_data: RenderDataContainer,
136}
137
138impl SceneRenderData {
139 pub fn new(
141 server: &dyn GraphicsServer,
142 frame_size: Vector2<f32>,
143 final_frame_texture: FrameTextureKind,
144 ) -> Result<Self, FrameworkError> {
145 Ok(Self {
146 camera_data: Default::default(),
147 scene_data: RenderDataContainer::new(server, frame_size, final_frame_texture)?,
148 })
149 }
150
151 pub fn set_quality_settings(&mut self, settings: &QualitySettings) {
153 for camera_data in self.camera_data.values_mut() {
154 camera_data.set_quality_settings(settings);
155 }
156 self.scene_data.set_quality_settings(settings);
157 }
158}
159
160fn recreate_render_data_if_needed<T: Any>(
161 parent: Handle<T>,
162 server: &dyn GraphicsServer,
163 data: &mut RenderDataContainer,
164 frame_size: Vector2<f32>,
165 final_frame_texture: FrameTextureKind,
166) -> Result<(), FrameworkError> {
167 if data.gbuffer.width != frame_size.x as i32 || data.gbuffer.height != frame_size.y as i32 {
168 Log::info(format!(
169 "Associated scene rendering data was re-created for {} ({}), because render \
170 frame size was changed. Old is {}x{}, new {}x{}!",
171 parent,
172 std::any::type_name::<T>(),
173 data.gbuffer.width,
174 data.gbuffer.height,
175 frame_size.x,
176 frame_size.y
177 ));
178
179 *data = RenderDataContainer::new(server, frame_size, final_frame_texture)?;
180 }
181
182 Ok(())
183}
184
185pub struct RenderDataContainer {
187 pub environment_map_specular_convolution: Option<EnvironmentMapSpecularConvolution>,
190
191 pub environment_map_irradiance_convolution: EnvironmentMapIrradianceConvolution,
193
194 pub need_recalculate_convolution: bool,
197
198 pub ssao_renderer: ScreenSpaceAmbientOcclusionRenderer,
200
201 pub gbuffer: GBuffer,
203
204 pub hdr_scene_framebuffer: GpuFrameBuffer,
206
207 pub ldr_scene_framebuffer: GpuFrameBuffer,
209
210 pub ldr_temp_framebuffer: [GpuFrameBuffer; 2],
212
213 pub hdr_renderer: HighDynamicRangeRenderer,
216
217 pub bloom_renderer: BloomRenderer,
220
221 pub statistics: SceneStatistics,
223}
224
225#[derive(Default)]
227pub enum FrameTextureKind {
228 #[default]
230 Rectangle,
231 Cube,
233}
234
235impl RenderDataContainer {
236 pub fn new(
238 server: &dyn GraphicsServer,
239 frame_size: Vector2<f32>,
240 final_frame_texture: FrameTextureKind,
241 ) -> Result<Self, FrameworkError> {
242 let width = frame_size.x as usize;
243 let height = frame_size.y as usize;
244
245 if matches!(final_frame_texture, FrameTextureKind::Cube) {
246 assert_eq!(width, height);
247 }
248
249 let depth_stencil = server.create_2d_render_target(
250 "ObserverDepthStencil",
251 PixelKind::D24S8,
252 width,
253 height,
254 )?;
255 let hdr_frame_texture = server.create_2d_render_target(
257 "ObserverHdrFrame",
258 PixelKind::RGBA16F,
259 width,
260 height,
261 )?;
262
263 let hdr_scene_framebuffer = server.create_frame_buffer(
264 Some(Attachment::depth_stencil(depth_stencil.clone())),
265 vec![Attachment::color(hdr_frame_texture)],
266 )?;
267
268 let ldr_frame_texture = server.create_texture(GpuTextureDescriptor {
269 name: "LdrFrameTexture",
270 kind: match final_frame_texture {
271 FrameTextureKind::Rectangle => GpuTextureKind::Rectangle { width, height },
272 FrameTextureKind::Cube => GpuTextureKind::Cube { size: width },
273 },
274 pixel_kind: PixelKind::RGBA8,
276 ..Default::default()
277 })?;
278
279 let ldr_scene_framebuffer = server.create_frame_buffer(
280 Some(Attachment::depth_stencil(depth_stencil.clone())),
281 vec![Attachment::color(ldr_frame_texture)],
282 )?;
283
284 fn make_ldr_temp_frame_buffer(
285 server: &dyn GraphicsServer,
286 width: usize,
287 height: usize,
288 depth_stencil: GpuTexture,
289 ) -> Result<GpuFrameBuffer, FrameworkError> {
290 let ldr_temp_texture = server.create_texture(GpuTextureDescriptor {
291 name: "LdrTempTexture",
292 kind: GpuTextureKind::Rectangle { width, height },
293 pixel_kind: PixelKind::RGBA8,
295 ..Default::default()
296 })?;
297
298 server.create_frame_buffer(
299 Some(Attachment::depth_stencil(depth_stencil)),
300 vec![Attachment::color(ldr_temp_texture)],
301 )
302 }
303
304 Ok(Self {
305 need_recalculate_convolution: true,
306 environment_map_specular_convolution: Default::default(),
307 environment_map_irradiance_convolution: EnvironmentMapIrradianceConvolution::new(
308 server, 32,
309 )?,
310 ssao_renderer: ScreenSpaceAmbientOcclusionRenderer::new(server, width, height)?,
311 gbuffer: GBuffer::new(server, width, height)?,
312 hdr_renderer: HighDynamicRangeRenderer::new(server)?,
313 bloom_renderer: BloomRenderer::new(server, width, height)?,
314 hdr_scene_framebuffer,
315 ldr_scene_framebuffer,
316 ldr_temp_framebuffer: [
317 make_ldr_temp_frame_buffer(server, width, height, depth_stencil.clone())?,
318 make_ldr_temp_frame_buffer(server, width, height, depth_stencil.clone())?,
319 ],
320 statistics: Default::default(),
321 })
322 }
323
324 fn copy_depth_stencil_to_scene_framebuffer(&mut self) {
325 self.gbuffer.framebuffer().blit_to(
326 &self.hdr_scene_framebuffer,
327 0,
328 0,
329 self.gbuffer.width,
330 self.gbuffer.height,
331 0,
332 0,
333 self.gbuffer.width,
334 self.gbuffer.height,
335 false,
336 true,
337 true,
338 );
339 }
340
341 pub fn hdr_scene_frame_texture(&self) -> &GpuTexture {
343 &self.hdr_scene_framebuffer.color_attachments()[0].texture
344 }
345
346 pub fn ldr_scene_frame_texture(&self) -> &GpuTexture {
348 &self.ldr_scene_framebuffer.color_attachments()[0].texture
349 }
350
351 pub fn ldr_temp_frame_texture(&self, i: usize) -> &GpuTexture {
353 &self.ldr_temp_framebuffer[i].color_attachments()[0].texture
354 }
355
356 pub fn set_quality_settings(&mut self, settings: &QualitySettings) {
358 self.ssao_renderer.set_radius(settings.ssao_radius);
359 }
360}
361
362pub fn make_viewport_matrix(viewport: Rect<i32>) -> Matrix4<f32> {
364 Matrix4::new_orthographic(
365 0.0,
366 viewport.w() as f32,
367 viewport.h() as f32,
368 0.0,
369 -1.0,
370 1.0,
371 ) * Matrix4::new_nonuniform_scaling(&Vector3::new(
372 viewport.w() as f32,
373 viewport.h() as f32,
374 0.0,
375 ))
376}
377
378pub struct Renderer {
380 backbuffer: GpuFrameBuffer,
381 scene_render_passes: Vec<Rc<RefCell<dyn SceneRenderPass>>>,
382 deferred_light_renderer: DeferredLightRenderer,
383 pub renderer_resources: RendererResources,
386 pub ui_renderer: UiRenderer,
388 statistics: Statistics,
389 frame_size: (u32, u32),
390 quality_settings: QualitySettings,
391 pub debug_renderer: DebugRenderer,
393 pub screen_space_debug_renderer: DebugRenderer,
396 pub scene_data_map: FxHashMap<Handle<Scene>, SceneRenderData>,
398 backbuffer_clear_color: Color,
399 pub texture_cache: TextureCache,
401 pub uniform_buffer_cache: UniformBufferCache,
403 shader_cache: ShaderCache,
404 geometry_cache: GeometryCache,
405 fxaa_renderer: FxaaRenderer,
406 texture_event_receiver: Receiver<ResourceEvent>,
407 shader_event_receiver: Receiver<ResourceEvent>,
408 pub ui_frame_buffers: FxHashMap<u64, GpuFrameBuffer>,
411 uniform_memory_allocator: UniformMemoryAllocator,
412 pub dynamic_surface_cache: DynamicSurfaceCache,
414 pub visibility_cache: VisibilityCache,
416 pub server: SharedGraphicsServer,
418}
419
420fn make_ui_frame_buffer(
421 frame_size: Vector2<f32>,
422 server: &dyn GraphicsServer,
423 pixel_kind: PixelKind,
424) -> Result<GpuFrameBuffer, FrameworkError> {
425 let color_texture = server.create_texture(GpuTextureDescriptor {
426 name: "UiFbTexture",
427 kind: GpuTextureKind::Rectangle {
428 width: frame_size.x as usize,
429 height: frame_size.y as usize,
430 },
431 pixel_kind,
432 ..Default::default()
433 })?;
434
435 let depth_stencil = server.create_2d_render_target(
436 "UiDepthStencil",
437 PixelKind::D24S8,
438 frame_size.x as usize,
439 frame_size.y as usize,
440 )?;
441
442 server.create_frame_buffer(
443 Some(Attachment::depth_stencil(depth_stencil)),
444 vec![Attachment::color(color_texture)],
445 )
446}
447
448pub struct SceneRenderPassContext<'a, 'b> {
450 pub elapsed_time: f32,
454 pub server: &'a dyn GraphicsServer,
456
457 pub texture_cache: &'a mut TextureCache,
460
461 pub geometry_cache: &'a mut GeometryCache,
465
466 pub shader_cache: &'a mut ShaderCache,
470
471 pub bundle_storage: &'a RenderDataBundleStorage,
473
474 pub quality_settings: &'a QualitySettings,
476
477 pub framebuffer: &'a GpuFrameBuffer,
479
480 pub scene: &'b Scene,
482
483 pub observer: &'b Observer,
485
486 pub scene_handle: Handle<Scene>,
488
489 pub renderer_resources: &'a RendererResources,
492
493 pub depth_texture: &'a GpuTexture,
501
502 pub normal_texture: &'a GpuTexture,
509
510 pub ambient_texture: &'a GpuTexture,
517
518 pub ui_renderer: &'a mut UiRenderer,
520
521 pub uniform_buffer_cache: &'a mut UniformBufferCache,
523
524 pub uniform_memory_allocator: &'a mut UniformMemoryAllocator,
527
528 pub dynamic_surface_cache: &'a mut DynamicSurfaceCache,
530
531 pub resource_manager: &'a ResourceManager,
533}
534
535pub trait SceneRenderPass {
537 fn on_hdr_render(
540 &mut self,
541 _ctx: SceneRenderPassContext,
542 ) -> Result<RenderPassStatistics, FrameworkError> {
543 Ok(RenderPassStatistics::default())
544 }
545
546 fn on_ldr_render(
549 &mut self,
550 _ctx: SceneRenderPassContext,
551 ) -> Result<RenderPassStatistics, FrameworkError> {
552 Ok(RenderPassStatistics::default())
553 }
554
555 fn source_type_id(&self) -> TypeId;
559}
560
561fn blit_pixels(
562 uniform_buffer_cache: &mut UniformBufferCache,
563 framebuffer: &GpuFrameBuffer,
564 texture: &GpuTexture,
565 blit_shader: &RenderPassContainer,
566 viewport: Rect<i32>,
567 renderer_resources: &RendererResources,
568) -> Result<DrawCallStatistics, FrameworkError> {
569 let wvp = make_viewport_matrix(viewport);
570 let properties = PropertyGroup::from([property("worldViewProjection", &wvp)]);
571 let material = RenderMaterial::from([
572 binding(
573 "diffuseTexture",
574 (texture, &renderer_resources.linear_clamp_sampler),
575 ),
576 binding("properties", &properties),
577 ]);
578 blit_shader.run_pass(
579 1,
580 &ImmutableString::new("Primary"),
581 framebuffer,
582 &renderer_resources.quad,
583 viewport,
584 &material,
585 uniform_buffer_cache,
586 Default::default(),
587 None,
588 )
589}
590
591fn render_target_size(
592 render_target: &TextureResource,
593) -> Result<(Vector2<f32>, FrameTextureKind), FrameworkError> {
594 render_target
595 .data_ref()
596 .as_loaded_ref()
597 .and_then(|rt| match rt.kind() {
598 TextureKind::Rectangle { width, height } => Some((
599 Vector2::new(width as f32, height as f32),
600 FrameTextureKind::Rectangle,
601 )),
602 TextureKind::Cube { size } => Some((
603 Vector2::new(size as f32, size as f32),
604 FrameTextureKind::Cube,
605 )),
606 _ => None,
607 })
608 .ok_or_else(|| {
609 FrameworkError::Custom(
610 "Render target must be a valid rectangle or cube texture!".to_string(),
611 )
612 })
613}
614
615impl Renderer {
616 pub fn new(
618 server: Rc<dyn GraphicsServer>,
619 frame_size: (u32, u32),
620 resource_manager: &ResourceManager,
621 ) -> Result<Self, EngineError> {
622 let settings = QualitySettings::default();
623
624 let (texture_event_sender, texture_event_receiver) = std::sync::mpsc::channel();
625
626 resource_manager
627 .state()
628 .event_broadcaster
629 .add(texture_event_sender);
630
631 let (shader_event_sender, shader_event_receiver) = std::sync::mpsc::channel();
632
633 resource_manager
634 .state()
635 .event_broadcaster
636 .add(shader_event_sender);
637
638 let caps = server.capabilities();
639 Log::info(format!("Graphics Server Capabilities\n{caps:?}",));
640
641 let shader_cache = ShaderCache::default();
642
643 let one_megabyte = 1024 * 1024;
644 let uniform_memory_allocator = UniformMemoryAllocator::new(
645 caps.max_uniform_block_size.min(one_megabyte),
649 caps.uniform_buffer_offset_alignment,
650 );
651
652 Ok(Self {
653 backbuffer: server.back_buffer(),
654 frame_size,
655 deferred_light_renderer: DeferredLightRenderer::new(&*server, &settings)?,
656 renderer_resources: RendererResources::new(&*server)?,
657 ui_renderer: UiRenderer::new(&*server)?,
658 quality_settings: settings,
659 debug_renderer: DebugRenderer::new(&*server)?,
660 screen_space_debug_renderer: DebugRenderer::new(&*server)?,
661 scene_data_map: Default::default(),
662 backbuffer_clear_color: Color::BLACK,
663 texture_cache: Default::default(),
664 geometry_cache: Default::default(),
665 ui_frame_buffers: Default::default(),
666 fxaa_renderer: FxaaRenderer::default(),
667 statistics: Statistics::default(),
668 shader_event_receiver,
669 texture_event_receiver,
670 shader_cache,
671 scene_render_passes: Default::default(),
672 uniform_buffer_cache: UniformBufferCache::new(server.clone()),
673 server,
674 visibility_cache: Default::default(),
675 uniform_memory_allocator,
676 dynamic_surface_cache: DynamicSurfaceCache::new(),
677 })
678 }
679
680 pub fn add_render_pass(&mut self, pass: Rc<RefCell<dyn SceneRenderPass>>) {
682 self.scene_render_passes.push(pass);
683 }
684
685 pub fn remove_render_pass(&mut self, pass: Rc<RefCell<dyn SceneRenderPass>>) {
687 if let Some(index) = self
688 .scene_render_passes
689 .iter()
690 .position(|p| Rc::ptr_eq(p, &pass))
691 {
692 self.scene_render_passes.remove(index);
693 }
694 }
695
696 pub fn render_passes(&self) -> &[Rc<RefCell<dyn SceneRenderPass>>] {
698 &self.scene_render_passes
699 }
700
701 pub fn clear_render_passes(&mut self) {
703 self.scene_render_passes.clear()
704 }
705
706 pub fn get_statistics(&self) -> Statistics {
708 self.statistics
709 }
710
711 pub fn unload_texture(&mut self, texture: &TextureResource) {
713 self.texture_cache.unload(texture)
714 }
715
716 pub fn set_backbuffer_clear_color(&mut self, color: Color) {
718 self.backbuffer_clear_color = color;
719 }
720
721 pub fn graphics_server(&self) -> &dyn GraphicsServer {
723 &*self.server
724 }
725
726 pub(crate) fn set_frame_size(&mut self, new_size: (u32, u32)) -> Result<(), FrameworkError> {
735 self.frame_size.0 = new_size.0.max(1);
736 self.frame_size.1 = new_size.1.max(1);
737
738 self.graphics_server().set_frame_size(new_size);
739
740 Ok(())
741 }
742
743 pub fn get_frame_size(&self) -> (u32, u32) {
745 self.frame_size
746 }
747
748 pub fn get_frame_bounds(&self) -> Vector2<f32> {
750 Vector2::new(self.frame_size.0 as f32, self.frame_size.1 as f32)
751 }
752
753 pub fn set_quality_settings(
757 &mut self,
758 settings: &QualitySettings,
759 ) -> Result<(), FrameworkError> {
760 self.quality_settings = *settings;
761 for data in self.scene_data_map.values_mut() {
762 data.set_quality_settings(settings);
763 }
764 self.deferred_light_renderer
765 .set_quality_settings(&*self.server, settings)
766 }
767
768 pub fn get_quality_settings(&self) -> QualitySettings {
770 self.quality_settings
771 }
772
773 pub fn flush(&mut self) {
777 self.texture_cache.clear();
778 self.geometry_cache.clear();
779 }
780
781 pub fn render_ui(&mut self, render_info: UiRenderInfo) -> Result<(), FrameworkError> {
787 let (frame_buffer, rt_size) = if let Some(render_target) =
788 render_info.render_target.as_ref()
789 {
790 let (rt_size, rt_pixel_kind) = render_target
791 .data_ref()
792 .as_loaded_ref()
793 .and_then(|rt| {
794 rt.kind()
795 .rectangle_size()
796 .map(|s| (s.cast::<f32>(), convert_pixel_kind(rt.pixel_kind())))
797 })
798 .ok_or_else(|| FrameworkError::Custom("invalid render target state".to_string()))?;
799
800 let frame_buffer = match self.ui_frame_buffers.entry(render_target.key()) {
802 Entry::Occupied(entry) => {
803 let frame_buffer = entry.into_mut();
804 let frame = frame_buffer.color_attachments().first().unwrap();
805 let color_texture_kind = frame.texture.kind();
806 if let GpuTextureKind::Rectangle { width, height } = color_texture_kind {
807 if width != rt_size.x as usize
808 || height != rt_size.y as usize
809 || frame.texture.pixel_kind() != rt_pixel_kind
810 {
811 *frame_buffer =
812 make_ui_frame_buffer(rt_size, &*self.server, rt_pixel_kind)?;
813 }
814 } else {
815 return Err(FrameworkError::Custom(
816 "ui can be rendered only in rectangle texture!".to_string(),
817 ));
818 }
819 frame_buffer
820 }
821 Entry::Vacant(entry) => {
822 entry.insert(make_ui_frame_buffer(rt_size, &*self.server, rt_pixel_kind)?)
823 }
824 };
825
826 let viewport = Rect::new(0, 0, rt_size.x as i32, rt_size.y as i32);
827 frame_buffer.clear(viewport, Some(render_info.clear_color), Some(0.0), Some(0));
828
829 (frame_buffer, rt_size)
830 } else {
831 (
832 &mut self.backbuffer,
833 Vector2::new(self.frame_size.0 as f32, self.frame_size.1 as f32),
834 )
835 };
836
837 self.statistics += self.ui_renderer.render(UiRenderContext {
838 server: &*self.server,
839 viewport: Rect::new(0, 0, rt_size.x as i32, rt_size.y as i32),
840 frame_buffer,
841 frame_width: rt_size.x,
842 frame_height: rt_size.y,
843 drawing_context: &render_info.ui.drawing_context,
844 renderer_resources: &self.renderer_resources,
845 texture_cache: &mut self.texture_cache,
846 uniform_buffer_cache: &mut self.uniform_buffer_cache,
847 render_pass_cache: &mut self.shader_cache,
848 uniform_memory_allocator: &mut self.uniform_memory_allocator,
849 resource_manager: render_info.resource_manager,
850 })?;
851
852 if let Some(render_target) = render_info.render_target.as_ref() {
853 self.texture_cache.try_register(
856 &*self.server,
857 render_target,
858 frame_buffer
859 .color_attachments()
860 .first()
861 .unwrap()
862 .texture
863 .clone(),
864 )?;
865 }
866
867 Ok(())
868 }
869
870 fn update_texture_cache(&mut self, resource_manager: &ResourceManager, dt: f32) {
871 const THROUGHPUT: usize = 5;
875
876 let mut uploaded = 0;
877 while let Ok(event) = self.texture_event_receiver.try_recv() {
878 if let ResourceEvent::Loaded(resource) | ResourceEvent::Reloaded(resource) = event {
879 if let Some(texture) = resource.try_cast::<Texture>() {
880 match self
881 .texture_cache
882 .upload(&*self.server, resource_manager, &texture)
883 {
884 Ok(_) => {
885 uploaded += 1;
886 if uploaded >= THROUGHPUT {
887 break;
888 }
889 }
890 Err(e) => {
891 Log::writeln(
892 MessageKind::Error,
893 format!("Failed to upload texture to GPU. Reason: {e:?}"),
894 );
895 }
896 }
897 }
898 }
899 }
900
901 self.texture_cache.update(dt);
902 }
903
904 fn update_shader_cache(&mut self, dt: f32) {
905 while let Ok(event) = self.shader_event_receiver.try_recv() {
906 if let ResourceEvent::Loaded(resource) | ResourceEvent::Reloaded(resource) = event {
907 if let Some(shader) = resource.try_cast::<Shader>() {
908 self.shader_cache.remove(&shader);
910 let _ = self.shader_cache.get(&*self.server, &shader);
911 }
912 }
913 }
914
915 self.shader_cache.update(dt)
916 }
917
918 pub fn update_caches(&mut self, resource_manager: &ResourceManager, dt: f32) {
923 self.update_texture_cache(resource_manager, dt);
924 self.update_shader_cache(dt);
925 self.geometry_cache.update(dt);
926 }
927
928 fn render_scene_observer(
929 &mut self,
930 observer: &Observer,
931 scene_handle: Handle<Scene>,
932 scene: &Scene,
933 elapsed_time: f32,
934 dt: f32,
935 resource_manager: &ResourceManager,
936 need_recalculate_convolution: bool,
937 ) -> Result<&mut RenderDataContainer, FrameworkError> {
938 let server = &*self.server;
939
940 let scene_render_data = self.scene_data_map.get_mut(&scene_handle).ok_or_else(|| {
941 FrameworkError::Custom(format!(
942 "No assocated render data for {scene_handle} scene!"
943 ))
944 })?;
945 let render_data = if let Some(render_target) = observer.render_target.as_ref() {
946 let (rt_size, final_frame_texture) = render_target_size(render_target)?;
947 let observer_render_data = match scene_render_data.camera_data.entry(observer.handle) {
948 Entry::Occupied(entry) => {
949 let observer_render_data = entry.into_mut();
950 recreate_render_data_if_needed(
951 scene_handle,
952 server,
953 observer_render_data,
954 rt_size,
955 final_frame_texture,
956 )?;
957 observer_render_data
958 }
959 Entry::Vacant(entry) => {
960 let render_data = entry.insert(RenderDataContainer::new(
961 server,
962 rt_size,
963 final_frame_texture,
964 )?);
965 info!(
966 "A new associated scene rendering data was created for observer {}!",
967 observer.handle
968 );
969 render_data
970 }
971 };
972
973 if let Some(probe_data) = observer.reflection_probe_data.as_ref() {
974 observer_render_data.ldr_scene_framebuffer.set_cubemap_face(
975 0,
976 probe_data.cube_map_face,
977 0,
978 );
979 }
980
981 self.texture_cache.try_register(
982 server,
983 render_target,
984 observer_render_data.ldr_scene_frame_texture().clone(),
985 )?;
986
987 observer_render_data
988 } else {
989 &mut scene_render_data.scene_data
990 };
991
992 render_data.need_recalculate_convolution |= need_recalculate_convolution;
993
994 let visibility_cache = self
995 .visibility_cache
996 .get_or_register(&scene.graph, observer.handle);
997
998 let mut bundle_storage = RenderDataBundleStorage::from_graph(
999 &scene.graph,
1000 observer.render_mask,
1001 elapsed_time,
1002 &observer.position,
1003 GBUFFER_PASS_NAME.clone(),
1004 RenderDataBundleStorageOptions {
1005 collect_lights: true,
1006 },
1007 &mut self.dynamic_surface_cache,
1008 );
1009 if observer.reflection_probe_data.is_some() {
1010 bundle_storage.environment_map = None;
1011 }
1012
1013 server.set_polygon_fill_mode(
1014 PolygonFace::FrontAndBack,
1015 scene.rendering_options.polygon_rasterization_mode,
1016 );
1017
1018 render_data.statistics += render_data.gbuffer.fill(GBufferRenderContext {
1019 server,
1020 observer,
1021 geom_cache: &mut self.geometry_cache,
1022 bundle_storage: &bundle_storage,
1023 texture_cache: &mut self.texture_cache,
1024 shader_cache: &mut self.shader_cache,
1025 quality_settings: &self.quality_settings,
1026 renderer_resources: &self.renderer_resources,
1027 graph: &scene.graph,
1028 uniform_buffer_cache: &mut self.uniform_buffer_cache,
1029 uniform_memory_allocator: &mut self.uniform_memory_allocator,
1030 screen_space_debug_renderer: &mut self.screen_space_debug_renderer,
1031 resource_manager,
1032 })?;
1033
1034 server.set_polygon_fill_mode(PolygonFace::FrontAndBack, PolygonFillMode::Fill);
1035
1036 render_data.copy_depth_stencil_to_scene_framebuffer();
1037
1038 render_data.hdr_scene_framebuffer.clear(
1039 observer.viewport,
1040 Some(
1041 scene
1042 .rendering_options
1043 .clear_color
1044 .unwrap_or(self.backbuffer_clear_color),
1045 ),
1046 None, Some(0),
1048 );
1049
1050 let (pass_stats, light_stats) =
1051 self.deferred_light_renderer
1052 .render(DeferredRendererContext {
1053 elapsed_time,
1054 server,
1055 scene,
1056 observer,
1057 gbuffer: &mut render_data.gbuffer,
1058 ambient_color: match observer.reflection_probe_data.as_ref() {
1059 None => scene.rendering_options.ambient_lighting_color,
1060 Some(probe_data) => probe_data.ambient_lighting_color,
1061 },
1062 environment_lighting_source: match observer.reflection_probe_data.as_ref() {
1063 None => scene.rendering_options.environment_lighting_source,
1064 Some(probe_data) => probe_data.environment_lighting_source,
1065 },
1066 render_data_bundle: &bundle_storage,
1067 settings: &self.quality_settings,
1068 textures: &mut self.texture_cache,
1069 geometry_cache: &mut self.geometry_cache,
1070 frame_buffer: &render_data.hdr_scene_framebuffer,
1071 shader_cache: &mut self.shader_cache,
1072 renderer_resources: &self.renderer_resources,
1073 uniform_buffer_cache: &mut self.uniform_buffer_cache,
1074 visibility_cache,
1075 uniform_memory_allocator: &mut self.uniform_memory_allocator,
1076 dynamic_surface_cache: &mut self.dynamic_surface_cache,
1077 ssao_renderer: &render_data.ssao_renderer,
1078 resource_manager,
1079 environment_map_specular_convolution: &mut render_data
1080 .environment_map_specular_convolution,
1081 environment_map_irradiance_convolution: &render_data
1082 .environment_map_irradiance_convolution,
1083 need_recalculate_convolution: &mut render_data.need_recalculate_convolution,
1084 })?;
1085
1086 render_data.statistics += light_stats;
1087 render_data.statistics += pass_stats;
1088
1089 let depth = render_data.gbuffer.depth();
1090
1091 render_data.statistics += bundle_storage.render_to_frame_buffer(
1092 server,
1093 &mut self.geometry_cache,
1094 &mut self.shader_cache,
1095 |bundle| bundle.render_path == RenderPath::Forward,
1096 |_| true,
1097 BundleRenderContext {
1098 texture_cache: &mut self.texture_cache,
1099 render_pass_name: &ImmutableString::new("Forward"),
1100 frame_buffer: &render_data.hdr_scene_framebuffer,
1101 viewport: observer.viewport,
1102 uniform_memory_allocator: &mut self.uniform_memory_allocator,
1103 resource_manager,
1104 use_pom: self.quality_settings.use_parallax_mapping,
1105 light_position: &Default::default(),
1106 renderer_resources: &self.renderer_resources,
1107 ambient_light: scene.rendering_options.ambient_lighting_color,
1108 scene_depth: Some(depth),
1109 },
1110 )?;
1111
1112 for render_pass in self.scene_render_passes.iter() {
1113 render_data.statistics +=
1114 render_pass
1115 .borrow_mut()
1116 .on_hdr_render(SceneRenderPassContext {
1117 elapsed_time,
1118 server,
1119 texture_cache: &mut self.texture_cache,
1120 geometry_cache: &mut self.geometry_cache,
1121 shader_cache: &mut self.shader_cache,
1122 quality_settings: &self.quality_settings,
1123 bundle_storage: &bundle_storage,
1124 scene,
1125 observer,
1126 scene_handle,
1127 renderer_resources: &self.renderer_resources,
1128 depth_texture: render_data.gbuffer.depth(),
1129 normal_texture: render_data.gbuffer.normal_texture(),
1130 ambient_texture: render_data.gbuffer.ambient_texture(),
1131 framebuffer: &render_data.hdr_scene_framebuffer,
1132 ui_renderer: &mut self.ui_renderer,
1133 uniform_buffer_cache: &mut self.uniform_buffer_cache,
1134 uniform_memory_allocator: &mut self.uniform_memory_allocator,
1135 dynamic_surface_cache: &mut self.dynamic_surface_cache,
1136 resource_manager,
1137 })?;
1138 }
1139
1140 render_data.statistics += render_data.bloom_renderer.render(
1142 render_data.hdr_scene_frame_texture(),
1143 &mut self.uniform_buffer_cache,
1144 &self.renderer_resources,
1145 )?;
1146
1147 let mut dest_buf = 0;
1149 let mut src_buf = 1;
1150 render_data.statistics += render_data.hdr_renderer.render(
1151 server,
1152 render_data.hdr_scene_frame_texture(),
1153 render_data.bloom_renderer.result(),
1154 &render_data.ldr_temp_framebuffer[dest_buf],
1155 observer.viewport,
1156 dt,
1157 observer.exposure,
1158 observer.color_grading_lut.as_ref(),
1159 observer.color_grading_enabled,
1160 &mut self.texture_cache,
1161 &mut self.uniform_buffer_cache,
1162 &self.renderer_resources,
1163 resource_manager,
1164 )?;
1165 std::mem::swap(&mut dest_buf, &mut src_buf);
1166
1167 if self.quality_settings.fxaa {
1169 render_data.statistics += self.fxaa_renderer.render(
1170 observer.viewport,
1171 render_data.ldr_temp_frame_texture(src_buf),
1172 &render_data.ldr_temp_framebuffer[dest_buf],
1173 &mut self.uniform_buffer_cache,
1174 &self.renderer_resources,
1175 )?;
1176 std::mem::swap(&mut dest_buf, &mut src_buf);
1177 }
1178
1179 render_data.statistics += blit_pixels(
1180 &mut self.uniform_buffer_cache,
1181 &render_data.ldr_scene_framebuffer,
1182 render_data.ldr_temp_frame_texture(src_buf),
1183 &self.renderer_resources.shaders.blit,
1184 observer.viewport,
1185 &self.renderer_resources,
1186 )?;
1187
1188 self.debug_renderer.set_lines(&scene.drawing_context.lines);
1190 render_data.statistics += self.debug_renderer.render(
1191 &mut self.uniform_buffer_cache,
1192 observer.viewport,
1193 &render_data.ldr_scene_framebuffer,
1194 observer.position.view_projection_matrix,
1195 &self.renderer_resources,
1196 )?;
1197
1198 for render_pass in self.scene_render_passes.iter() {
1199 render_data.statistics +=
1200 render_pass
1201 .borrow_mut()
1202 .on_ldr_render(SceneRenderPassContext {
1203 elapsed_time,
1204 server,
1205 texture_cache: &mut self.texture_cache,
1206 geometry_cache: &mut self.geometry_cache,
1207 shader_cache: &mut self.shader_cache,
1208 quality_settings: &self.quality_settings,
1209 bundle_storage: &bundle_storage,
1210 scene,
1211 observer,
1212 scene_handle,
1213 renderer_resources: &self.renderer_resources,
1214 depth_texture: render_data.gbuffer.depth(),
1215 normal_texture: render_data.gbuffer.normal_texture(),
1216 ambient_texture: render_data.gbuffer.ambient_texture(),
1217 framebuffer: &render_data.ldr_scene_framebuffer,
1218 ui_renderer: &mut self.ui_renderer,
1219 uniform_buffer_cache: &mut self.uniform_buffer_cache,
1220 uniform_memory_allocator: &mut self.uniform_memory_allocator,
1221 dynamic_surface_cache: &mut self.dynamic_surface_cache,
1222 resource_manager,
1223 })?;
1224 }
1225
1226 Ok(render_data)
1227 }
1228
1229 pub fn render_scene(
1232 &mut self,
1233 scene_handle: Handle<Scene>,
1234 scene: &Scene,
1235 elapsed_time: f32,
1236 dt: f32,
1237 resource_manager: &ResourceManager,
1238 ) -> Result<&SceneRenderData, FrameworkError> {
1239 let graph = &scene.graph;
1240
1241 let backbuffer_width = self.frame_size.0 as f32;
1242 let backbuffer_height = self.frame_size.1 as f32;
1243
1244 let window_viewport = Rect::new(0, 0, self.frame_size.0 as i32, self.frame_size.1 as i32);
1245
1246 let frame_size = scene
1247 .rendering_options
1248 .render_target
1249 .as_ref()
1250 .map_or_else(
1251 || Vector2::new(backbuffer_width, backbuffer_height),
1253 |rt| {
1255 if let TextureKind::Rectangle { width, height } = rt.data_ref().kind() {
1256 Vector2::new(width as f32, height as f32)
1257 } else {
1258 panic!("only rectangle textures can be used as render target!")
1259 }
1260 },
1261 )
1262 .sup(&Vector2::new(1.0, 1.0));
1264
1265 let scene_render_data = match self.scene_data_map.entry(scene_handle) {
1266 Entry::Occupied(entry) => {
1267 let render_data = entry.into_mut();
1268 recreate_render_data_if_needed(
1269 scene_handle,
1270 &*self.server,
1271 &mut render_data.scene_data,
1272 frame_size,
1273 FrameTextureKind::Rectangle,
1274 )?;
1275 render_data
1276 }
1277 Entry::Vacant(entry) => {
1278 let render_data = entry.insert(SceneRenderData::new(
1279 &*self.server,
1280 frame_size,
1281 FrameTextureKind::Rectangle,
1282 )?);
1283 info!(
1284 "A new associated scene rendering data was created for scene {scene_handle}!"
1285 );
1286 render_data
1287 }
1288 };
1289
1290 let pipeline_stats = &self.server.pipeline_statistics();
1291 scene_render_data.scene_data.statistics = Default::default();
1292
1293 if let Some(rt) = scene.rendering_options.render_target.clone() {
1297 self.texture_cache.try_register(
1298 &*self.server,
1299 &rt,
1300 scene_render_data
1301 .scene_data
1302 .ldr_scene_frame_texture()
1303 .clone(),
1304 )?;
1305 }
1306
1307 scene_render_data
1308 .camera_data
1309 .retain(|h, _| graph.is_valid_handle(*h));
1310
1311 let observers = ObserversCollection::from_scene(scene, frame_size);
1312
1313 let mut need_recalculate_convolution = false;
1315 for observer in observers.reflection_probes.iter() {
1316 self.render_scene_observer(
1317 observer,
1318 scene_handle,
1319 scene,
1320 elapsed_time,
1321 dt,
1322 resource_manager,
1323 false,
1326 )?;
1327 need_recalculate_convolution = true;
1328 }
1329
1330 for observer in observers.cameras.iter() {
1332 self.render_scene_observer(
1333 observer,
1334 scene_handle,
1335 scene,
1336 elapsed_time,
1337 dt,
1338 resource_manager,
1339 need_recalculate_convolution,
1340 )?;
1341 }
1342
1343 self.visibility_cache.update(graph);
1344
1345 let scene_render_data = self.scene_data_map.get_mut(&scene_handle).unwrap();
1346
1347 if scene.rendering_options.render_target.is_none() {
1349 scene_render_data.scene_data.statistics += blit_pixels(
1350 &mut self.uniform_buffer_cache,
1351 &self.backbuffer,
1352 scene_render_data.scene_data.ldr_scene_frame_texture(),
1353 &self.renderer_resources.shaders.blit,
1354 window_viewport,
1355 &self.renderer_resources,
1356 )?;
1357 }
1358
1359 self.statistics += scene_render_data.scene_data.statistics;
1360 scene_render_data.scene_data.statistics.pipeline =
1361 self.server.pipeline_statistics() - *pipeline_stats;
1362
1363 Ok(scene_render_data)
1364 }
1365
1366 fn render_frame<'a>(
1367 &mut self,
1368 scenes: &SceneContainer,
1369 elapsed_time: f32,
1370 resource_manager: &ResourceManager,
1371 ui_render_info: impl Iterator<Item = UiRenderInfo<'a>>,
1372 ) -> Result<(), FrameworkError> {
1373 if self.frame_size.0 == 0 || self.frame_size.1 == 0 {
1374 return Ok(());
1375 }
1376
1377 self.uniform_buffer_cache.mark_all_unused();
1378 self.uniform_memory_allocator.clear();
1379 self.dynamic_surface_cache.clear();
1380
1381 self.scene_data_map
1383 .retain(|h, _| scenes.is_valid_handle(*h));
1384
1385 self.server.invalidate_resource_bindings_cache();
1390 let dt = self.statistics.capped_frame_time;
1391 self.statistics.begin_frame();
1392
1393 let window_viewport = Rect::new(0, 0, self.frame_size.0 as i32, self.frame_size.1 as i32);
1394 self.backbuffer.clear(
1395 window_viewport,
1396 Some(self.backbuffer_clear_color),
1397 Some(1.0),
1398 Some(0),
1399 );
1400
1401 let backbuffer_width = self.frame_size.0 as f32;
1402 let backbuffer_height = self.frame_size.1 as f32;
1403
1404 for (scene_handle, scene) in scenes.pair_iter().filter(|(_, s)| *s.enabled) {
1405 self.render_scene(scene_handle, scene, elapsed_time, dt, resource_manager)?;
1406 }
1407
1408 self.graphics_server()
1409 .set_polygon_fill_mode(PolygonFace::FrontAndBack, PolygonFillMode::Fill);
1410
1411 for info in ui_render_info {
1413 self.render_ui(info)?;
1414 }
1415
1416 let screen_matrix =
1417 Matrix4::new_orthographic(0.0, backbuffer_width, backbuffer_height, 0.0, -1.0, 1.0);
1418 self.screen_space_debug_renderer.render(
1419 &mut self.uniform_buffer_cache,
1420 window_viewport,
1421 &self.backbuffer,
1422 screen_matrix,
1423 &self.renderer_resources,
1424 )?;
1425
1426 self.statistics.geometry_cache_size = self.geometry_cache.alive_count();
1427 self.statistics.texture_cache_size = self.texture_cache.alive_count();
1428 self.statistics.shader_cache_size = self.shader_cache.alive_count();
1429 self.statistics.uniform_buffer_cache_size = self.uniform_buffer_cache.alive_count();
1430
1431 Ok(())
1432 }
1433
1434 pub(crate) fn render_and_swap_buffers<'a>(
1435 &mut self,
1436 scenes: &SceneContainer,
1437 elapsed_time: f32,
1438 ui_info: impl Iterator<Item = UiRenderInfo<'a>>,
1439 window: &Window,
1440 resource_manager: &ResourceManager,
1441 ) -> Result<(), FrameworkError> {
1442 self.render_frame(scenes, elapsed_time, resource_manager, ui_info)?;
1443 self.statistics.end_frame();
1444 window.pre_present_notify();
1445 self.graphics_server().swap_buffers()?;
1446 self.statistics.finalize();
1447 self.statistics.pipeline = self.server.pipeline_statistics();
1448 Ok(())
1449 }
1450}