fyrox_impl/renderer/cache/
geometry.rs

1// Copyright (c) 2019-present Dmitry Stepanov and Fyrox Engine contributors.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in all
11// copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19// SOFTWARE.
20
21use crate::renderer::framework::GeometryBufferExt;
22use crate::{
23    renderer::{
24        cache::{TemporaryCache, TimeToLive},
25        framework::{
26            error::FrameworkError, geometry_buffer::GeometryBuffer, server::GraphicsServer,
27        },
28    },
29    scene::mesh::surface::{SurfaceData, SurfaceResource},
30};
31use fyrox_core::log::Log;
32use fyrox_graphics::buffer::BufferUsage;
33
34struct SurfaceRenderData {
35    buffer: Box<dyn GeometryBuffer>,
36    vertex_modifications_count: u64,
37    triangles_modifications_count: u64,
38    layout_hash: u64,
39}
40
41#[derive(Default)]
42pub struct GeometryCache {
43    buffer: TemporaryCache<SurfaceRenderData>,
44}
45
46fn create_geometry_buffer(
47    data: &SurfaceData,
48    server: &dyn GraphicsServer,
49) -> Result<SurfaceRenderData, FrameworkError> {
50    let geometry_buffer =
51        <dyn GeometryBuffer>::from_surface_data(data, BufferUsage::StaticDraw, server)?;
52
53    Ok(SurfaceRenderData {
54        buffer: geometry_buffer,
55        vertex_modifications_count: data.vertex_buffer.modifications_count(),
56        triangles_modifications_count: data.geometry_buffer.modifications_count(),
57        layout_hash: data.vertex_buffer.layout_hash(),
58    })
59}
60
61impl GeometryCache {
62    pub fn get<'a>(
63        &'a mut self,
64        server: &dyn GraphicsServer,
65        data: &SurfaceResource,
66        time_to_live: TimeToLive,
67    ) -> Option<&'a dyn GeometryBuffer> {
68        let data = data.data_ref();
69
70        match self
71            .buffer
72            .get_entry_mut_or_insert_with(&data.cache_index, time_to_live, || {
73                create_geometry_buffer(&data, server)
74            }) {
75            Ok(entry) => {
76                // We also must check if buffer's layout changed, and if so - recreate the entire
77                // buffer.
78                if entry.layout_hash == data.vertex_buffer.layout_hash() {
79                    if data.vertex_buffer.modifications_count() != entry.vertex_modifications_count
80                    {
81                        // Vertices has changed, upload the new content.
82                        entry
83                            .buffer
84                            .set_buffer_data(0, data.vertex_buffer.raw_data());
85
86                        entry.vertex_modifications_count = data.vertex_buffer.modifications_count();
87                    }
88
89                    if data.geometry_buffer.modifications_count()
90                        != entry.triangles_modifications_count
91                    {
92                        // Triangles has changed, upload the new content.
93                        entry
94                            .buffer
95                            .set_triangles(data.geometry_buffer.triangles_ref());
96
97                        entry.triangles_modifications_count =
98                            data.geometry_buffer.modifications_count();
99                    }
100                }
101                Some(&*entry.buffer)
102            }
103            Err(err) => {
104                Log::err(err.to_string());
105                None
106            }
107        }
108    }
109
110    pub fn update(&mut self, dt: f32) {
111        self.buffer.update(dt);
112    }
113
114    pub fn clear(&mut self) {
115        self.buffer.clear();
116    }
117
118    pub fn alive_count(&self) -> usize {
119        self.buffer.alive_count()
120    }
121}