RecordingDevice: lend cached geometry instead of copying it per draw
A geometry-cache hit moved every vertex vector out of the cache into the draw (deep copy of positions/normals/uv/diffuse/indices/bones each frame). The cache now lends its vectors to the frame's first draw of that geometry and takes them back in Render3DBeginFrame; later draws of the same key+revision in the frame (terrain splat layers, shadow-map pass) are marked shared_geometry and carry no vectors -- the native host looks the GPU geometry up by key+revision, and draw captures expand them (Render3DExpandSharedGeometry). Index reads reuse a scratch buffer. Desktop live game: RenderGame rnd 1.7 -> 1.2 ms, no visual change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
44a020f01e
commit
6bfcac7d68
@@ -362,7 +362,9 @@ int run_live_client(
|
||||
renderer.touch_controller.update_screen_size(int(ui_w), int(ui_h));
|
||||
renderer.touch_controller.append_ui_commands(cap_ui);
|
||||
}
|
||||
native_draw_capture::write(capture_out, Render3DDraws(), cap_textures, ui_w, ui_h, cap_ui);
|
||||
std::vector<Render3DDraw> cap_draws = Render3DDraws();
|
||||
Render3DExpandSharedGeometry(cap_draws);
|
||||
native_draw_capture::write(capture_out, cap_draws, cap_textures, ui_w, ui_h, cap_ui);
|
||||
}
|
||||
|
||||
if (!screenshot_out.empty() && frames > 0) {
|
||||
|
||||
@@ -66,7 +66,7 @@ FixedFunctionState make_fixed_function_state(const Render3DDraw& draw) {
|
||||
const std::uint32_t fog_mode = draw.fog_enable
|
||||
? (draw.fog_table_mode ? draw.fog_table_mode : (draw.pretransformed ? 4u : draw.fog_vertex_mode)) : 0;
|
||||
state.flags = {1u, !draw.texture0.empty() ? 1u : 0u, !draw.texture1.empty() ? 1u : 0u, fog_mode};
|
||||
state.lighting_flags = {draw.lighting, draw.color_vertex, draw.diffuse.empty() ? 0u : 1u,
|
||||
state.lighting_flags = {draw.lighting, draw.color_vertex, (draw.shared_geometry ? draw.shared_diffuse : !draw.diffuse.empty()) ? 1u : 0u,
|
||||
draw.normalize_normals};
|
||||
state.material_sources = {draw.diffuse_material_source, draw.ambient_material_source,
|
||||
draw.emissive_material_source, draw.local_viewer};
|
||||
|
||||
+14
-5
@@ -8,6 +8,7 @@
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <stdexcept>
|
||||
#include <tuple>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace mt_host {
|
||||
@@ -191,14 +192,22 @@ void VulkanWindow::prepare_draws(const std::vector<Render3DDraw>& draws, const T
|
||||
back_buffer_list(in_scene).push_back(clear);
|
||||
continue;
|
||||
}
|
||||
if (draw.positions.empty() || draw.indices.empty()) continue;
|
||||
const auto signature = draw.geometry_key ? draw.geometry_revision : geometry_hash(draw);
|
||||
const GeometryId id{draw.geometry_key, signature};
|
||||
auto [it, inserted] = geometries_.try_emplace(id);
|
||||
decltype(geometries_)::iterator it;
|
||||
bool inserted = false;
|
||||
if (draw.shared_geometry) {
|
||||
// Repeats an earlier draw of this frame, which uploaded (or kept) the geometry.
|
||||
it = geometries_.find(GeometryId{draw.geometry_key, draw.geometry_revision});
|
||||
if (it == geometries_.end()) continue;
|
||||
} else {
|
||||
if (draw.positions.empty() || draw.indices.empty()) continue;
|
||||
const auto signature = draw.geometry_key ? draw.geometry_revision : geometry_hash(draw);
|
||||
std::tie(it, inserted) = geometries_.try_emplace(GeometryId{draw.geometry_key, signature});
|
||||
}
|
||||
auto& geometry = it->second;
|
||||
if (inserted) {
|
||||
upload_geometry(draw, geometry);
|
||||
} else if (geometry.vertex_count != draw.positions.size() / 3 || geometry.index_count != draw.indices.size()) {
|
||||
} else if (!draw.shared_geometry && (geometry.vertex_count != draw.positions.size() / 3 ||
|
||||
geometry.index_count != draw.indices.size())) {
|
||||
throw std::runtime_error("geometry key/revision reused with a different size");
|
||||
}
|
||||
geometry.last_used_frame = frame_number_;
|
||||
|
||||
Reference in New Issue
Block a user