Skip to main content

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::{
22    graphics::{
23        buffer::BufferUsage, error::FrameworkError, geometry_buffer::GpuGeometryBuffer,
24        server::GraphicsServer,
25    },
26    renderer::{
27        cache::{TemporaryCache, TimeToLive},
28        framework::GeometryBufferExt,
29    },
30    scene::mesh::surface::{SurfaceData, SurfaceResource},
31};
32
33struct SurfaceRenderData {
34    buffer: GpuGeometryBuffer,
35    vertex_modifications_count: u64,
36    triangles_modifications_count: u64,
37    layout_hash: u64,
38}
39
40#[derive(Default)]
41pub struct GeometryCache {
42    buffer: TemporaryCache<SurfaceRenderData>,
43}
44
45fn create_geometry_buffer(
46    data: &SurfaceData,
47    server: &dyn GraphicsServer,
48) -> Result<SurfaceRenderData, FrameworkError> {
49    let geometry_buffer = GpuGeometryBuffer::from_surface_data(
50        // TODO: It might be worth to add more informative name using a combination of the name of
51        // the parent scene node, surface index.
52        "GeometryBuffer",
53        data,
54        BufferUsage::StaticDraw,
55        server,
56    )?;
57
58    Ok(SurfaceRenderData {
59        buffer: geometry_buffer,
60        vertex_modifications_count: data.vertex_buffer.modifications_count(),
61        triangles_modifications_count: data.geometry_buffer.modifications_count(),
62        layout_hash: data.vertex_buffer.layout_hash(),
63    })
64}
65
66impl GeometryCache {
67    pub fn get<'a>(
68        &'a mut self,
69        server: &dyn GraphicsServer,
70        data: &SurfaceResource,
71        time_to_live: TimeToLive,
72    ) -> Result<&'a GpuGeometryBuffer, FrameworkError> {
73        let data = data.data_ref();
74
75        match self
76            .buffer
77            .get_entry_mut_or_insert_with(&data.cache_index, time_to_live, || {
78                create_geometry_buffer(&data, server)
79            }) {
80            Ok(entry) => {
81                // We also must check if buffer's layout changed, and if so - recreate the entire
82                // buffer.
83                if entry.layout_hash == data.vertex_buffer.layout_hash() {
84                    if data.vertex_buffer.modifications_count() != entry.vertex_modifications_count
85                    {
86                        // Vertices has changed, upload the new content.
87                        entry
88                            .buffer
89                            .set_buffer_data(0, data.vertex_buffer.raw_data());
90
91                        entry.vertex_modifications_count = data.vertex_buffer.modifications_count();
92                    }
93
94                    if data.geometry_buffer.modifications_count()
95                        != entry.triangles_modifications_count
96                    {
97                        // Triangles has changed, upload the new content.
98                        entry
99                            .buffer
100                            .set_triangles(data.geometry_buffer.triangles_ref());
101
102                        entry.triangles_modifications_count =
103                            data.geometry_buffer.modifications_count();
104                    }
105                } else {
106                    let SurfaceRenderData {
107                        buffer,
108                        vertex_modifications_count,
109                        triangles_modifications_count,
110                        layout_hash,
111                    } = create_geometry_buffer(&data, server)?;
112                    entry.buffer = buffer;
113                    entry.vertex_modifications_count = vertex_modifications_count;
114                    entry.triangles_modifications_count = triangles_modifications_count;
115                    entry.layout_hash = layout_hash;
116                }
117                Ok(&entry.buffer)
118            }
119            Err(err) => Err(err),
120        }
121    }
122
123    pub fn update(&mut self, dt: f32) {
124        self.buffer.update(dt);
125    }
126
127    pub fn clear(&mut self) {
128        self.buffer.clear();
129    }
130
131    pub fn alive_count(&self) -> usize {
132        self.buffer.alive_count()
133    }
134}