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::renderer::hdr::HdrRendererArgs;
53use crate::{
54 asset::{event::ResourceEvent, manager::ResourceManager},
55 core::{
56 algebra::{Matrix4, Vector2, Vector3},
57 color::Color,
58 info,
59 log::{Log, MessageKind},
60 math::Rect,
61 pool::Handle,
62 sstorage::ImmutableString,
63 },
64 engine::error::EngineError,
65 graphics::{
66 error::FrameworkError,
67 framebuffer::{Attachment, DrawCallStatistics, GpuFrameBuffer},
68 gpu_texture::{GpuTexture, GpuTextureDescriptor, GpuTextureKind, PixelKind},
69 server::{GraphicsServer, SharedGraphicsServer},
70 PolygonFace, PolygonFillMode,
71 },
72 material::shader::Shader,
73 renderer::{
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::SceneGraph;
101use observer::{Observer, ObserversCollection};
102use resources::RendererResources;
103pub use settings::*;
104pub use stats::*;
105use std::sync::LazyLock;
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
115static GBUFFER_PASS_NAME: LazyLock<ImmutableString> =
116 LazyLock::new(|| ImmutableString::new("GBuffer"));
117
118static DIRECTIONAL_SHADOW_PASS_NAME: LazyLock<ImmutableString> =
119 LazyLock::new(|| ImmutableString::new("DirectionalShadow"));
120
121static SPOT_SHADOW_PASS_NAME: LazyLock<ImmutableString> =
122 LazyLock::new(|| ImmutableString::new("SpotShadow"));
123
124static POINT_SHADOW_PASS_NAME: LazyLock<ImmutableString> =
125 LazyLock::new(|| ImmutableString::new("PointShadow"));
126
127pub fn is_shadow_pass(render_pass_name: &str) -> bool {
129 render_pass_name == &**DIRECTIONAL_SHADOW_PASS_NAME
130 || render_pass_name == &**SPOT_SHADOW_PASS_NAME
131 || render_pass_name == &**POINT_SHADOW_PASS_NAME
132}
133
134pub struct SceneRenderData {
136 pub camera_data: FxHashMap<Handle<Node>, RenderDataContainer>,
138 pub scene_data: RenderDataContainer,
140}
141
142impl SceneRenderData {
143 pub fn new(
145 server: &dyn GraphicsServer,
146 frame_size: Vector2<f32>,
147 final_frame_texture: FrameTextureKind,
148 ) -> Result<Self, FrameworkError> {
149 Ok(Self {
150 camera_data: Default::default(),
151 scene_data: RenderDataContainer::new(server, frame_size, final_frame_texture)?,
152 })
153 }
154
155 pub fn set_quality_settings(&mut self, settings: &QualitySettings) {
157 for camera_data in self.camera_data.values_mut() {
158 camera_data.set_quality_settings(settings);
159 }
160 self.scene_data.set_quality_settings(settings);
161 }
162}
163
164fn recreate_render_data_if_needed<T: Any>(
165 parent: Handle<T>,
166 server: &dyn GraphicsServer,
167 data: &mut RenderDataContainer,
168 frame_size: Vector2<f32>,
169 final_frame_texture: FrameTextureKind,
170) -> Result<(), FrameworkError> {
171 if data.gbuffer.width != frame_size.x as i32 || data.gbuffer.height != frame_size.y as i32 {
172 Log::info(format!(
173 "Associated scene rendering data was re-created for {} ({}), because render \
174 frame size was changed. Old is {}x{}, new {}x{}!",
175 parent,
176 std::any::type_name::<T>(),
177 data.gbuffer.width,
178 data.gbuffer.height,
179 frame_size.x,
180 frame_size.y
181 ));
182
183 *data = RenderDataContainer::new(server, frame_size, final_frame_texture)?;
184 }
185
186 Ok(())
187}
188
189pub struct RenderDataContainer {
191 pub environment_map_specular_convolution: Option<EnvironmentMapSpecularConvolution>,
194
195 pub environment_map_irradiance_convolution: EnvironmentMapIrradianceConvolution,
197
198 pub need_recalculate_convolution: bool,
201
202 pub ssao_renderer: ScreenSpaceAmbientOcclusionRenderer,
204
205 pub gbuffer: GBuffer,
207
208 pub hdr_scene_framebuffer: GpuFrameBuffer,
210
211 pub ldr_scene_framebuffer: GpuFrameBuffer,
213
214 pub ldr_temp_framebuffer: [GpuFrameBuffer; 2],
216
217 pub hdr_renderer: HighDynamicRangeRenderer,
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(width, height, server)?,
313 hdr_scene_framebuffer,
314 ldr_scene_framebuffer,
315 ldr_temp_framebuffer: [
316 make_ldr_temp_frame_buffer(server, width, height, depth_stencil.clone())?,
317 make_ldr_temp_frame_buffer(server, width, height, depth_stencil.clone())?,
318 ],
319 statistics: Default::default(),
320 })
321 }
322
323 fn copy_depth_stencil_to_scene_framebuffer(&mut self) {
324 self.gbuffer.framebuffer().blit_to(
325 &self.hdr_scene_framebuffer,
326 0,
327 0,
328 self.gbuffer.width,
329 self.gbuffer.height,
330 0,
331 0,
332 self.gbuffer.width,
333 self.gbuffer.height,
334 false,
335 true,
336 true,
337 );
338 }
339
340 pub fn hdr_scene_frame_texture(&self) -> &GpuTexture {
342 &self.hdr_scene_framebuffer.color_attachments()[0].texture
343 }
344
345 pub fn ldr_scene_frame_texture(&self) -> &GpuTexture {
347 &self.ldr_scene_framebuffer.color_attachments()[0].texture
348 }
349
350 pub fn ldr_temp_frame_texture(&self, i: usize) -> &GpuTexture {
352 &self.ldr_temp_framebuffer[i].color_attachments()[0].texture
353 }
354
355 pub fn set_quality_settings(&mut self, settings: &QualitySettings) {
357 self.ssao_renderer.set_radius(settings.ssao_radius);
358 }
359}
360
361pub fn make_viewport_matrix(viewport: Rect<i32>) -> Matrix4<f32> {
363 Matrix4::new_orthographic(
364 0.0,
365 viewport.w() as f32,
366 viewport.h() as f32,
367 0.0,
368 -1.0,
369 1.0,
370 ) * Matrix4::new_nonuniform_scaling(&Vector3::new(
371 viewport.w() as f32,
372 viewport.h() as f32,
373 0.0,
374 ))
375}
376
377pub struct Renderer {
379 backbuffer: GpuFrameBuffer,
380 scene_render_passes: Vec<Rc<RefCell<dyn SceneRenderPass>>>,
381 deferred_light_renderer: DeferredLightRenderer,
382 pub renderer_resources: RendererResources,
385 pub ui_renderer: UiRenderer,
387 statistics: Statistics,
388 frame_size: (u32, u32),
389 quality_settings: QualitySettings,
390 pub debug_renderer: DebugRenderer,
392 pub screen_space_debug_renderer: DebugRenderer,
395 pub scene_data_map: FxHashMap<Handle<Scene>, SceneRenderData>,
397 backbuffer_clear_color: Color,
398 pub texture_cache: TextureCache,
400 pub uniform_buffer_cache: UniformBufferCache,
402 shader_cache: ShaderCache,
403 geometry_cache: GeometryCache,
404 fxaa_renderer: FxaaRenderer,
405 texture_event_receiver: Receiver<ResourceEvent>,
406 shader_event_receiver: Receiver<ResourceEvent>,
407 pub ui_frame_buffers: FxHashMap<u64, GpuFrameBuffer>,
410 uniform_memory_allocator: UniformMemoryAllocator,
411 pub dynamic_surface_cache: DynamicSurfaceCache,
413 pub visibility_cache: VisibilityCache,
415 pub server: SharedGraphicsServer,
417}
418
419fn make_ui_frame_buffer(
420 frame_size: Vector2<f32>,
421 server: &dyn GraphicsServer,
422 pixel_kind: PixelKind,
423) -> Result<GpuFrameBuffer, FrameworkError> {
424 let color_texture = server.create_texture(GpuTextureDescriptor {
425 name: "UiFbTexture",
426 kind: GpuTextureKind::Rectangle {
427 width: frame_size.x as usize,
428 height: frame_size.y as usize,
429 },
430 pixel_kind,
431 ..Default::default()
432 })?;
433
434 let depth_stencil = server.create_2d_render_target(
435 "UiDepthStencil",
436 PixelKind::D24S8,
437 frame_size.x as usize,
438 frame_size.y as usize,
439 )?;
440
441 server.create_frame_buffer(
442 Some(Attachment::depth_stencil(depth_stencil)),
443 vec![Attachment::color(color_texture)],
444 )
445}
446
447pub struct SceneRenderPassContext<'a, 'b> {
449 pub elapsed_time: f32,
453 pub server: &'a dyn GraphicsServer,
455
456 pub texture_cache: &'a mut TextureCache,
459
460 pub geometry_cache: &'a mut GeometryCache,
464
465 pub shader_cache: &'a mut ShaderCache,
469
470 pub bundle_storage: &'a RenderDataBundleStorage,
472
473 pub quality_settings: &'a QualitySettings,
475
476 pub framebuffer: &'a GpuFrameBuffer,
478
479 pub scene: &'b Scene,
481
482 pub observer: &'b Observer,
484
485 pub scene_handle: Handle<Scene>,
487
488 pub renderer_resources: &'a RendererResources,
491
492 pub depth_texture: &'a GpuTexture,
500
501 pub normal_texture: &'a GpuTexture,
508
509 pub ambient_texture: &'a GpuTexture,
516
517 pub ui_renderer: &'a mut UiRenderer,
519
520 pub uniform_buffer_cache: &'a mut UniformBufferCache,
522
523 pub uniform_memory_allocator: &'a mut UniformMemoryAllocator,
526
527 pub dynamic_surface_cache: &'a mut DynamicSurfaceCache,
529
530 pub resource_manager: &'a ResourceManager,
532}
533
534pub trait SceneRenderPass {
536 fn on_hdr_render(
539 &mut self,
540 _ctx: SceneRenderPassContext,
541 ) -> Result<RenderPassStatistics, FrameworkError> {
542 Ok(RenderPassStatistics::default())
543 }
544
545 fn on_ldr_render(
548 &mut self,
549 _ctx: SceneRenderPassContext,
550 ) -> Result<RenderPassStatistics, FrameworkError> {
551 Ok(RenderPassStatistics::default())
552 }
553
554 fn source_type_id(&self) -> TypeId;
558}
559
560fn blit_pixels(
561 uniform_buffer_cache: &mut UniformBufferCache,
562 framebuffer: &GpuFrameBuffer,
563 texture: &GpuTexture,
564 blit_shader: &RenderPassContainer,
565 viewport: Rect<i32>,
566 renderer_resources: &RendererResources,
567) -> Result<DrawCallStatistics, FrameworkError> {
568 let wvp = make_viewport_matrix(viewport);
569 let properties = PropertyGroup::from([property("worldViewProjection", &wvp)]);
570 let material = RenderMaterial::from([
571 binding(
572 "diffuseTexture",
573 (texture, &renderer_resources.linear_clamp_sampler),
574 ),
575 binding("properties", &properties),
576 ]);
577 blit_shader.run_pass(
578 1,
579 &ImmutableString::new("Primary"),
580 framebuffer,
581 &renderer_resources.quad,
582 viewport,
583 &material,
584 uniform_buffer_cache,
585 Default::default(),
586 None,
587 )
588}
589
590fn render_target_size(
591 render_target: &TextureResource,
592) -> Result<(Vector2<f32>, FrameTextureKind), FrameworkError> {
593 render_target
594 .data_ref()
595 .as_loaded_ref()
596 .and_then(|rt| match rt.kind() {
597 TextureKind::Rectangle { width, height } => Some((
598 Vector2::new(width as f32, height as f32),
599 FrameTextureKind::Rectangle,
600 )),
601 TextureKind::Cube { size } => Some((
602 Vector2::new(size as f32, size as f32),
603 FrameTextureKind::Cube,
604 )),
605 _ => None,
606 })
607 .ok_or_else(|| {
608 FrameworkError::Custom(
609 "Render target must be a valid rectangle or cube texture!".to_string(),
610 )
611 })
612}
613
614impl Renderer {
615 pub fn new(
617 server: Rc<dyn GraphicsServer>,
618 frame_size: (u32, u32),
619 resource_manager: &ResourceManager,
620 ) -> Result<Self, EngineError> {
621 let settings = QualitySettings::default();
622
623 let (texture_event_sender, texture_event_receiver) = std::sync::mpsc::channel();
624
625 resource_manager
626 .state()
627 .event_broadcaster
628 .add(texture_event_sender);
629
630 let (shader_event_sender, shader_event_receiver) = std::sync::mpsc::channel();
631
632 resource_manager
633 .state()
634 .event_broadcaster
635 .add(shader_event_sender);
636
637 let caps = server.capabilities();
638 Log::info(format!("Graphics Server Capabilities\n{caps:?}",));
639
640 let shader_cache = ShaderCache::default();
641
642 let one_megabyte = 1024 * 1024;
643 let uniform_memory_allocator = UniformMemoryAllocator::new(
644 caps.max_uniform_block_size.min(one_megabyte),
648 caps.uniform_buffer_offset_alignment,
649 );
650
651 Ok(Self {
652 backbuffer: server.back_buffer(),
653 frame_size,
654 deferred_light_renderer: DeferredLightRenderer::new(&*server, &settings)?,
655 renderer_resources: RendererResources::new(&*server)?,
656 ui_renderer: UiRenderer::new(&*server)?,
657 quality_settings: settings,
658 debug_renderer: DebugRenderer::new(&*server)?,
659 screen_space_debug_renderer: DebugRenderer::new(&*server)?,
660 scene_data_map: Default::default(),
661 backbuffer_clear_color: Color::BLACK,
662 texture_cache: Default::default(),
663 geometry_cache: Default::default(),
664 ui_frame_buffers: Default::default(),
665 fxaa_renderer: FxaaRenderer::default(),
666 statistics: Statistics::default(),
667 shader_event_receiver,
668 texture_event_receiver,
669 shader_cache,
670 scene_render_passes: Default::default(),
671 uniform_buffer_cache: UniformBufferCache::new(server.clone()),
672 server,
673 visibility_cache: Default::default(),
674 uniform_memory_allocator,
675 dynamic_surface_cache: DynamicSurfaceCache::new(),
676 })
677 }
678
679 pub fn add_render_pass(&mut self, pass: Rc<RefCell<dyn SceneRenderPass>>) {
681 self.scene_render_passes.push(pass);
682 }
683
684 pub fn remove_render_pass(&mut self, pass: Rc<RefCell<dyn SceneRenderPass>>) {
686 if let Some(index) = self
687 .scene_render_passes
688 .iter()
689 .position(|p| Rc::ptr_eq(p, &pass))
690 {
691 self.scene_render_passes.remove(index);
692 }
693 }
694
695 pub fn render_passes(&self) -> &[Rc<RefCell<dyn SceneRenderPass>>] {
697 &self.scene_render_passes
698 }
699
700 pub fn clear_render_passes(&mut self) {
702 self.scene_render_passes.clear()
703 }
704
705 pub fn get_statistics(&self) -> Statistics {
707 self.statistics
708 }
709
710 pub fn unload_texture(&mut self, texture: &TextureResource) {
712 self.texture_cache.unload(texture)
713 }
714
715 pub fn set_backbuffer_clear_color(&mut self, color: Color) {
717 self.backbuffer_clear_color = color;
718 }
719
720 pub fn graphics_server(&self) -> &dyn GraphicsServer {
722 &*self.server
723 }
724
725 pub(crate) fn set_frame_size(&mut self, new_size: (u32, u32)) -> Result<(), FrameworkError> {
734 self.frame_size.0 = new_size.0.max(1);
735 self.frame_size.1 = new_size.1.max(1);
736
737 self.graphics_server().set_frame_size(new_size);
738
739 Ok(())
740 }
741
742 pub fn get_frame_size(&self) -> (u32, u32) {
744 self.frame_size
745 }
746
747 pub fn get_frame_bounds(&self) -> Vector2<f32> {
749 Vector2::new(self.frame_size.0 as f32, self.frame_size.1 as f32)
750 }
751
752 pub fn set_quality_settings(
756 &mut self,
757 settings: &QualitySettings,
758 ) -> Result<(), FrameworkError> {
759 self.quality_settings = *settings;
760 for data in self.scene_data_map.values_mut() {
761 data.set_quality_settings(settings);
762 }
763 self.deferred_light_renderer
764 .set_quality_settings(&*self.server, settings)
765 }
766
767 pub fn get_quality_settings(&self) -> QualitySettings {
769 self.quality_settings
770 }
771
772 pub fn flush(&mut self) {
776 self.texture_cache.clear();
777 self.geometry_cache.clear();
778 }
779
780 pub fn render_ui(&mut self, render_info: UiRenderInfo) -> Result<(), FrameworkError> {
786 let _debug_scope = self.server.begin_scope(&format!("UI {:p}", render_info.ui));
787
788 let (frame_buffer, rt_size) = if let Some(render_target) =
789 render_info.render_target.as_ref()
790 {
791 let (rt_size, rt_pixel_kind) = render_target
792 .data_ref()
793 .as_loaded_ref()
794 .and_then(|rt| {
795 rt.kind()
796 .rectangle_size()
797 .map(|s| (s.cast::<f32>(), convert_pixel_kind(rt.pixel_kind())))
798 })
799 .ok_or_else(|| FrameworkError::Custom("invalid render target state".to_string()))?;
800
801 let frame_buffer = match self.ui_frame_buffers.entry(render_target.key()) {
803 Entry::Occupied(entry) => {
804 let frame_buffer = entry.into_mut();
805 let frame = frame_buffer.color_attachments().first().unwrap();
806 let color_texture_kind = frame.texture.kind();
807 if let GpuTextureKind::Rectangle { width, height } = color_texture_kind {
808 if width != rt_size.x as usize
809 || height != rt_size.y as usize
810 || frame.texture.pixel_kind() != rt_pixel_kind
811 {
812 *frame_buffer =
813 make_ui_frame_buffer(rt_size, &*self.server, rt_pixel_kind)?;
814 }
815 } else {
816 return Err(FrameworkError::Custom(
817 "ui can be rendered only in rectangle texture!".to_string(),
818 ));
819 }
820 frame_buffer
821 }
822 Entry::Vacant(entry) => {
823 entry.insert(make_ui_frame_buffer(rt_size, &*self.server, rt_pixel_kind)?)
824 }
825 };
826
827 let viewport = Rect::new(0, 0, rt_size.x as i32, rt_size.y as i32);
828 frame_buffer.clear(viewport, Some(render_info.clear_color), Some(0.0), Some(0));
829
830 (frame_buffer, rt_size)
831 } else {
832 (
833 &mut self.backbuffer,
834 Vector2::new(self.frame_size.0 as f32, self.frame_size.1 as f32),
835 )
836 };
837
838 self.statistics += self.ui_renderer.render(UiRenderContext {
839 server: &*self.server,
840 viewport: Rect::new(0, 0, rt_size.x as i32, rt_size.y as i32),
841 frame_buffer,
842 frame_width: rt_size.x,
843 frame_height: rt_size.y,
844 drawing_context: &render_info.ui.drawing_context,
845 renderer_resources: &self.renderer_resources,
846 texture_cache: &mut self.texture_cache,
847 uniform_buffer_cache: &mut self.uniform_buffer_cache,
848 render_pass_cache: &mut self.shader_cache,
849 uniform_memory_allocator: &mut self.uniform_memory_allocator,
850 resource_manager: render_info.resource_manager,
851 })?;
852
853 if let Some(render_target) = render_info.render_target.as_ref() {
854 self.texture_cache.try_register(
857 &*self.server,
858 render_target,
859 frame_buffer
860 .color_attachments()
861 .first()
862 .unwrap()
863 .texture
864 .clone(),
865 )?;
866 }
867
868 Ok(())
869 }
870
871 fn update_texture_cache(&mut self, resource_manager: &ResourceManager, dt: f32) {
872 const THROUGHPUT: usize = 5;
876
877 let mut uploaded = 0;
878 while let Ok(event) = self.texture_event_receiver.try_recv() {
879 if let ResourceEvent::Loaded(resource) | ResourceEvent::Reloaded(resource) = event {
880 if let Some(texture) = resource.try_cast::<Texture>() {
881 match self
882 .texture_cache
883 .upload(&*self.server, resource_manager, &texture)
884 {
885 Ok(_) => {
886 uploaded += 1;
887 if uploaded >= THROUGHPUT {
888 break;
889 }
890 }
891 Err(e) => {
892 Log::writeln(
893 MessageKind::Error,
894 format!("Failed to upload texture to GPU. Reason: {e:?}"),
895 );
896 }
897 }
898 }
899 }
900 }
901
902 self.texture_cache.update(dt);
903 }
904
905 fn update_shader_cache(&mut self, dt: f32) {
906 while let Ok(event) = self.shader_event_receiver.try_recv() {
907 if let ResourceEvent::Loaded(resource) | ResourceEvent::Reloaded(resource) = event {
908 if let Some(shader) = resource.try_cast::<Shader>() {
909 self.shader_cache.remove(&shader);
911 let _ = self.shader_cache.get(&*self.server, &shader);
912 }
913 }
914 }
915
916 self.shader_cache.update(dt)
917 }
918
919 pub fn update_caches(&mut self, resource_manager: &ResourceManager, dt: f32) {
924 self.update_texture_cache(resource_manager, dt);
925 self.update_shader_cache(dt);
926 self.geometry_cache.update(dt);
927 }
928
929 fn render_scene_observer(
930 &mut self,
931 observer: &Observer,
932 scene_handle: Handle<Scene>,
933 scene: &Scene,
934 elapsed_time: f32,
935 dt: f32,
936 resource_manager: &ResourceManager,
937 need_recalculate_convolution: bool,
938 ) -> Result<&mut RenderDataContainer, FrameworkError> {
939 let server = &*self.server;
940
941 let scene_render_data = self.scene_data_map.get_mut(&scene_handle).ok_or_else(|| {
942 FrameworkError::Custom(format!(
943 "No associated render data for {scene_handle} scene!"
944 ))
945 })?;
946 let render_data = if let Some(render_target) = observer.render_target.as_ref() {
947 let (rt_size, final_frame_texture) = render_target_size(render_target)?;
948 let observer_render_data = match scene_render_data.camera_data.entry(observer.handle) {
949 Entry::Occupied(entry) => {
950 let observer_render_data = entry.into_mut();
951 recreate_render_data_if_needed(
952 scene_handle,
953 server,
954 observer_render_data,
955 rt_size,
956 final_frame_texture,
957 )?;
958 observer_render_data
959 }
960 Entry::Vacant(entry) => {
961 let render_data = entry.insert(RenderDataContainer::new(
962 server,
963 rt_size,
964 final_frame_texture,
965 )?);
966 info!(
967 "A new associated scene rendering data was created for observer {}!",
968 observer.handle
969 );
970 render_data
971 }
972 };
973
974 if let Some(probe_data) = observer.reflection_probe_data.as_ref() {
975 observer_render_data.ldr_scene_framebuffer.set_cubemap_face(
976 0,
977 probe_data.cube_map_face,
978 0,
979 );
980 }
981
982 self.texture_cache.try_register(
983 server,
984 render_target,
985 observer_render_data.ldr_scene_frame_texture().clone(),
986 )?;
987
988 observer_render_data
989 } else {
990 &mut scene_render_data.scene_data
991 };
992
993 render_data.need_recalculate_convolution |= need_recalculate_convolution;
994
995 let visibility_cache = self
996 .visibility_cache
997 .get_or_register(&scene.graph, observer.handle);
998
999 let mut bundle_storage = RenderDataBundleStorage::from_graph(
1000 &scene.graph,
1001 observer.render_mask,
1002 elapsed_time,
1003 &observer.position,
1004 GBUFFER_PASS_NAME.clone(),
1005 RenderDataBundleStorageOptions {
1006 collect_lights: true,
1007 },
1008 &mut self.dynamic_surface_cache,
1009 );
1010 if observer.reflection_probe_data.is_some() {
1011 bundle_storage.environment_map = None;
1012 }
1013
1014 server.set_polygon_fill_mode(
1015 PolygonFace::FrontAndBack,
1016 scene.rendering_options.polygon_rasterization_mode,
1017 );
1018
1019 render_data.statistics += render_data.gbuffer.fill(GBufferRenderContext {
1020 server,
1021 observer,
1022 geom_cache: &mut self.geometry_cache,
1023 bundle_storage: &bundle_storage,
1024 texture_cache: &mut self.texture_cache,
1025 shader_cache: &mut self.shader_cache,
1026 quality_settings: &self.quality_settings,
1027 renderer_resources: &self.renderer_resources,
1028 graph: &scene.graph,
1029 uniform_buffer_cache: &mut self.uniform_buffer_cache,
1030 uniform_memory_allocator: &mut self.uniform_memory_allocator,
1031 screen_space_debug_renderer: &mut self.screen_space_debug_renderer,
1032 resource_manager,
1033 })?;
1034
1035 server.set_polygon_fill_mode(PolygonFace::FrontAndBack, PolygonFillMode::Fill);
1036
1037 render_data.copy_depth_stencil_to_scene_framebuffer();
1038
1039 render_data.hdr_scene_framebuffer.clear(
1040 observer.viewport,
1041 Some(
1042 scene
1043 .rendering_options
1044 .clear_color
1045 .unwrap_or(self.backbuffer_clear_color),
1046 ),
1047 None, Some(0),
1049 );
1050
1051 let (pass_stats, light_stats) =
1052 self.deferred_light_renderer
1053 .render(DeferredRendererContext {
1054 elapsed_time,
1055 server,
1056 scene,
1057 observer,
1058 gbuffer: &mut render_data.gbuffer,
1059 ambient_color: match observer.reflection_probe_data.as_ref() {
1060 None => scene.rendering_options.ambient_lighting_color,
1061 Some(probe_data) => probe_data.ambient_lighting_color,
1062 },
1063 environment_lighting_source: match observer.reflection_probe_data.as_ref() {
1064 None => scene.rendering_options.environment_lighting_source,
1065 Some(probe_data) => probe_data.environment_lighting_source,
1066 },
1067 render_data_bundle: &bundle_storage,
1068 settings: &self.quality_settings,
1069 textures: &mut self.texture_cache,
1070 geometry_cache: &mut self.geometry_cache,
1071 frame_buffer: &render_data.hdr_scene_framebuffer,
1072 shader_cache: &mut self.shader_cache,
1073 renderer_resources: &self.renderer_resources,
1074 uniform_buffer_cache: &mut self.uniform_buffer_cache,
1075 visibility_cache,
1076 uniform_memory_allocator: &mut self.uniform_memory_allocator,
1077 dynamic_surface_cache: &mut self.dynamic_surface_cache,
1078 ssao_renderer: &render_data.ssao_renderer,
1079 resource_manager,
1080 environment_map_specular_convolution: &mut render_data
1081 .environment_map_specular_convolution,
1082 environment_map_irradiance_convolution: &render_data
1083 .environment_map_irradiance_convolution,
1084 need_recalculate_convolution: &mut render_data.need_recalculate_convolution,
1085 })?;
1086
1087 render_data.statistics += light_stats;
1088 render_data.statistics += pass_stats;
1089
1090 let depth = render_data.gbuffer.depth();
1091
1092 {
1093 let _debug_scope = server.begin_scope("ForwardRendering");
1094
1095 render_data.statistics += bundle_storage.render_to_frame_buffer(
1096 server,
1097 &mut self.geometry_cache,
1098 &mut self.shader_cache,
1099 |bundle| bundle.render_path == RenderPath::Forward,
1100 |_| true,
1101 BundleRenderContext {
1102 texture_cache: &mut self.texture_cache,
1103 render_pass_name: &ImmutableString::new("Forward"),
1104 frame_buffer: &render_data.hdr_scene_framebuffer,
1105 viewport: observer.viewport,
1106 uniform_memory_allocator: &mut self.uniform_memory_allocator,
1107 resource_manager,
1108 use_pom: self.quality_settings.use_parallax_mapping,
1109 light_position: &Default::default(),
1110 renderer_resources: &self.renderer_resources,
1111 ambient_light: scene.rendering_options.ambient_lighting_color,
1112 scene_depth: Some(depth),
1113 },
1114 )?;
1115 }
1116
1117 for render_pass in self.scene_render_passes.iter() {
1118 let _debug_scope = server.begin_scope(&format!(
1119 "UserRenderPass::on_hdr_render {:p}",
1120 render_pass.as_ptr()
1121 ));
1122
1123 render_data.statistics +=
1124 render_pass
1125 .borrow_mut()
1126 .on_hdr_render(SceneRenderPassContext {
1127 elapsed_time,
1128 server,
1129 texture_cache: &mut self.texture_cache,
1130 geometry_cache: &mut self.geometry_cache,
1131 shader_cache: &mut self.shader_cache,
1132 quality_settings: &self.quality_settings,
1133 bundle_storage: &bundle_storage,
1134 scene,
1135 observer,
1136 scene_handle,
1137 renderer_resources: &self.renderer_resources,
1138 depth_texture: render_data.gbuffer.depth(),
1139 normal_texture: render_data.gbuffer.normal_texture(),
1140 ambient_texture: render_data.gbuffer.ambient_texture(),
1141 framebuffer: &render_data.hdr_scene_framebuffer,
1142 ui_renderer: &mut self.ui_renderer,
1143 uniform_buffer_cache: &mut self.uniform_buffer_cache,
1144 uniform_memory_allocator: &mut self.uniform_memory_allocator,
1145 dynamic_surface_cache: &mut self.dynamic_surface_cache,
1146 resource_manager,
1147 })?;
1148 }
1149
1150 let mut dest_buf = 0;
1152 let mut src_buf = 1;
1153 render_data.statistics += render_data.hdr_renderer.render(HdrRendererArgs {
1154 server,
1155 hdr_scene_frame: render_data.hdr_scene_frame_texture(),
1156 ldr_framebuffer: &render_data.ldr_temp_framebuffer[dest_buf],
1157 viewport: observer.viewport,
1158 speed: observer.hdr_adaptation_speed * dt,
1159 exposure: observer.exposure,
1160 color_grading_lut: observer.color_grading_lut.as_ref(),
1161 use_color_grading: observer.color_grading_enabled,
1162 texture_cache: &mut self.texture_cache,
1163 uniform_buffer_cache: &mut self.uniform_buffer_cache,
1164 renderer_resources: &self.renderer_resources,
1165 resource_manager,
1166 settings: &self.quality_settings,
1167 })?;
1168 std::mem::swap(&mut dest_buf, &mut src_buf);
1169
1170 if self.quality_settings.fxaa {
1172 render_data.statistics += self.fxaa_renderer.render(
1173 server,
1174 observer.viewport,
1175 render_data.ldr_temp_frame_texture(src_buf),
1176 &render_data.ldr_temp_framebuffer[dest_buf],
1177 &mut self.uniform_buffer_cache,
1178 &self.renderer_resources,
1179 )?;
1180 std::mem::swap(&mut dest_buf, &mut src_buf);
1181 }
1182
1183 render_data.statistics += blit_pixels(
1184 &mut self.uniform_buffer_cache,
1185 &render_data.ldr_scene_framebuffer,
1186 render_data.ldr_temp_frame_texture(src_buf),
1187 &self.renderer_resources.shaders.blit,
1188 observer.viewport,
1189 &self.renderer_resources,
1190 )?;
1191
1192 self.debug_renderer.set_lines(&scene.drawing_context.lines);
1194 render_data.statistics += self.debug_renderer.render(
1195 server,
1196 &mut self.uniform_buffer_cache,
1197 observer.viewport,
1198 &render_data.ldr_scene_framebuffer,
1199 observer.position.view_projection_matrix,
1200 &self.renderer_resources,
1201 )?;
1202
1203 for render_pass in self.scene_render_passes.iter() {
1204 let _debug_scope = server.begin_scope(&format!(
1205 "UserRenderPass::on_ldr_render {:p}",
1206 render_pass.as_ptr()
1207 ));
1208
1209 render_data.statistics +=
1210 render_pass
1211 .borrow_mut()
1212 .on_ldr_render(SceneRenderPassContext {
1213 elapsed_time,
1214 server,
1215 texture_cache: &mut self.texture_cache,
1216 geometry_cache: &mut self.geometry_cache,
1217 shader_cache: &mut self.shader_cache,
1218 quality_settings: &self.quality_settings,
1219 bundle_storage: &bundle_storage,
1220 scene,
1221 observer,
1222 scene_handle,
1223 renderer_resources: &self.renderer_resources,
1224 depth_texture: render_data.gbuffer.depth(),
1225 normal_texture: render_data.gbuffer.normal_texture(),
1226 ambient_texture: render_data.gbuffer.ambient_texture(),
1227 framebuffer: &render_data.ldr_scene_framebuffer,
1228 ui_renderer: &mut self.ui_renderer,
1229 uniform_buffer_cache: &mut self.uniform_buffer_cache,
1230 uniform_memory_allocator: &mut self.uniform_memory_allocator,
1231 dynamic_surface_cache: &mut self.dynamic_surface_cache,
1232 resource_manager,
1233 })?;
1234 }
1235
1236 Ok(render_data)
1237 }
1238
1239 pub fn render_scene(
1242 &mut self,
1243 scene_handle: Handle<Scene>,
1244 scene: &Scene,
1245 elapsed_time: f32,
1246 dt: f32,
1247 resource_manager: &ResourceManager,
1248 ) -> Result<&SceneRenderData, FrameworkError> {
1249 let graph = &scene.graph;
1250
1251 let _debug_scope = self.server.begin_scope(&format!("Scene {:p}", scene));
1252
1253 let backbuffer_width = self.frame_size.0 as f32;
1254 let backbuffer_height = self.frame_size.1 as f32;
1255
1256 let window_viewport = Rect::new(0, 0, self.frame_size.0 as i32, self.frame_size.1 as i32);
1257
1258 let frame_size = scene
1259 .rendering_options
1260 .render_target
1261 .as_ref()
1262 .map_or_else(
1263 || Vector2::new(backbuffer_width, backbuffer_height),
1265 |rt| {
1267 if let TextureKind::Rectangle { width, height } = rt.data_ref().kind() {
1268 Vector2::new(width as f32, height as f32)
1269 } else {
1270 panic!("only rectangle textures can be used as render target!")
1271 }
1272 },
1273 )
1274 .sup(&Vector2::new(1.0, 1.0));
1276
1277 let scene_render_data = match self.scene_data_map.entry(scene_handle) {
1278 Entry::Occupied(entry) => {
1279 let render_data = entry.into_mut();
1280 recreate_render_data_if_needed(
1281 scene_handle,
1282 &*self.server,
1283 &mut render_data.scene_data,
1284 frame_size,
1285 FrameTextureKind::Rectangle,
1286 )?;
1287 render_data
1288 }
1289 Entry::Vacant(entry) => {
1290 let render_data = entry.insert(SceneRenderData::new(
1291 &*self.server,
1292 frame_size,
1293 FrameTextureKind::Rectangle,
1294 )?);
1295 info!(
1296 "A new associated scene rendering data was created for scene {scene_handle}!"
1297 );
1298 render_data
1299 }
1300 };
1301
1302 let pipeline_stats = &self.server.pipeline_statistics();
1303 scene_render_data.scene_data.statistics = Default::default();
1304
1305 if let Some(rt) = scene.rendering_options.render_target.clone() {
1309 self.texture_cache.try_register(
1310 &*self.server,
1311 &rt,
1312 scene_render_data
1313 .scene_data
1314 .ldr_scene_frame_texture()
1315 .clone(),
1316 )?;
1317 }
1318
1319 scene_render_data
1320 .camera_data
1321 .retain(|h, _| graph.is_valid_handle(*h));
1322
1323 let observers = ObserversCollection::from_scene(scene, frame_size);
1324
1325 let mut need_recalculate_convolution = false;
1327 for observer in observers.reflection_probes.iter() {
1328 let _debug_scope = self
1329 .server
1330 .begin_scope(&format!("Reflection Probe {:p}", observer));
1331
1332 self.render_scene_observer(
1333 observer,
1334 scene_handle,
1335 scene,
1336 elapsed_time,
1337 dt,
1338 resource_manager,
1339 false,
1342 )?;
1343 need_recalculate_convolution = true;
1344 }
1345
1346 for observer in observers.cameras.iter() {
1348 let _debug_scope = self.server.begin_scope(&format!("Camera {:p}", observer));
1349
1350 self.render_scene_observer(
1351 observer,
1352 scene_handle,
1353 scene,
1354 elapsed_time,
1355 dt,
1356 resource_manager,
1357 need_recalculate_convolution,
1358 )?;
1359 }
1360
1361 self.visibility_cache.update(graph);
1362
1363 let scene_render_data = self.scene_data_map.get_mut(&scene_handle).unwrap();
1364
1365 if scene.rendering_options.render_target.is_none() {
1367 scene_render_data.scene_data.statistics += blit_pixels(
1368 &mut self.uniform_buffer_cache,
1369 &self.backbuffer,
1370 scene_render_data.scene_data.ldr_scene_frame_texture(),
1371 &self.renderer_resources.shaders.blit,
1372 window_viewport,
1373 &self.renderer_resources,
1374 )?;
1375 }
1376
1377 self.statistics += scene_render_data.scene_data.statistics;
1378 scene_render_data.scene_data.statistics.pipeline =
1379 self.server.pipeline_statistics() - *pipeline_stats;
1380
1381 Ok(scene_render_data)
1382 }
1383
1384 fn render_frame<'a>(
1385 &mut self,
1386 scenes: &SceneContainer,
1387 elapsed_time: f32,
1388 resource_manager: &ResourceManager,
1389 ui_render_info: impl Iterator<Item = UiRenderInfo<'a>>,
1390 ) -> Result<(), FrameworkError> {
1391 if self.frame_size.0 == 0 || self.frame_size.1 == 0 {
1392 return Ok(());
1393 }
1394
1395 self.uniform_buffer_cache.mark_all_unused();
1396 self.uniform_memory_allocator.clear();
1397 self.dynamic_surface_cache.clear();
1398
1399 self.scene_data_map
1401 .retain(|h, _| scenes.is_valid_handle(*h));
1402
1403 self.server.invalidate_resource_bindings_cache();
1408 let dt = self.statistics.capped_frame_time;
1409 self.statistics.begin_frame();
1410
1411 let window_viewport = Rect::new(0, 0, self.frame_size.0 as i32, self.frame_size.1 as i32);
1412 self.backbuffer.clear(
1413 window_viewport,
1414 Some(self.backbuffer_clear_color),
1415 Some(1.0),
1416 Some(0),
1417 );
1418
1419 let backbuffer_width = self.frame_size.0 as f32;
1420 let backbuffer_height = self.frame_size.1 as f32;
1421
1422 for (scene_handle, scene) in scenes.pair_iter().filter(|(_, s)| *s.enabled) {
1423 self.render_scene(scene_handle, scene, elapsed_time, dt, resource_manager)?;
1424 }
1425
1426 self.graphics_server()
1427 .set_polygon_fill_mode(PolygonFace::FrontAndBack, PolygonFillMode::Fill);
1428
1429 for info in ui_render_info {
1431 self.render_ui(info)?;
1432 }
1433
1434 let screen_matrix =
1435 Matrix4::new_orthographic(0.0, backbuffer_width, backbuffer_height, 0.0, -1.0, 1.0);
1436 self.screen_space_debug_renderer.render(
1437 &*self.server,
1438 &mut self.uniform_buffer_cache,
1439 window_viewport,
1440 &self.backbuffer,
1441 screen_matrix,
1442 &self.renderer_resources,
1443 )?;
1444
1445 self.statistics.geometry_cache_size = self.geometry_cache.alive_count();
1446 self.statistics.texture_cache_size = self.texture_cache.alive_count();
1447 self.statistics.shader_cache_size = self.shader_cache.alive_count();
1448 self.statistics.uniform_buffer_cache_size = self.uniform_buffer_cache.alive_count();
1449
1450 Ok(())
1451 }
1452
1453 pub(crate) fn render_and_swap_buffers<'a>(
1454 &mut self,
1455 scenes: &SceneContainer,
1456 elapsed_time: f32,
1457 ui_info: impl Iterator<Item = UiRenderInfo<'a>>,
1458 window: &Window,
1459 resource_manager: &ResourceManager,
1460 ) -> Result<(), FrameworkError> {
1461 self.render_frame(scenes, elapsed_time, resource_manager, ui_info)?;
1462 self.statistics.end_frame();
1463 window.pre_present_notify();
1464 self.graphics_server().swap_buffers()?;
1465 self.statistics.finalize();
1466 self.statistics.pipeline = self.server.pipeline_statistics();
1467 Ok(())
1468 }
1469}