Skip to content

Commit

Permalink
Merge pull request #80414 from DarioSamo/multimesh-motion-vectors
Browse files Browse the repository at this point in the history
Improve handling of motion vectors for multimesh instances.
  • Loading branch information
akien-mga committed Aug 10, 2023
2 parents b78d52b + 5155870 commit 67543e9
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1010,13 +1010,6 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con
if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_DEPTH_TEXTURE) {
scene_state.used_depth_texture = true;
}

if (p_color_pass_flags & COLOR_PASS_FLAG_MOTION_VECTORS) {
if ((flags & (INSTANCE_DATA_FLAG_MULTIMESH | INSTANCE_DATA_FLAG_PARTICLES)) == INSTANCE_DATA_FLAG_MULTIMESH && RendererRD::MeshStorage::get_singleton()->_multimesh_enable_motion_vectors(inst->data->base)) {
inst->transforms_uniform_set = mesh_storage->multimesh_get_3d_uniform_set(inst->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
}
}

} else if (p_pass_mode == PASS_MODE_SHADOW || p_pass_mode == PASS_MODE_SHADOW_DP) {
if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_SHADOW) {
rl->add_element(surf);
Expand Down
48 changes: 32 additions & 16 deletions servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1289,12 +1289,9 @@ void MeshStorage::multimesh_allocate_data(RID p_multimesh, int p_instances, RS::
multimesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MULTIMESH);
}

bool MeshStorage::_multimesh_enable_motion_vectors(RID p_multimesh) {
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_COND_V(!multimesh, false);

void MeshStorage::_multimesh_enable_motion_vectors(MultiMesh *multimesh) {
if (multimesh->motion_vectors_enabled) {
return false;
return;
}

multimesh->motion_vectors_enabled = true;
Expand All @@ -1307,22 +1304,30 @@ bool MeshStorage::_multimesh_enable_motion_vectors(RID p_multimesh) {
multimesh->data_cache.append_array(multimesh->data_cache);
}

if (multimesh->buffer_set) {
uint32_t buffer_size = multimesh->instances * multimesh->stride_cache * sizeof(float);
uint32_t new_buffer_size = buffer_size * 2;
RID new_buffer = RD::get_singleton()->storage_buffer_create(new_buffer_size);

if (multimesh->buffer_set && multimesh->data_cache.is_empty()) {
// If the buffer was set but there's no data cached in the CPU, we must download it from the GPU and
// upload it because RD does not provide a way to copy the buffer directly yet.
RD::get_singleton()->barrier();
Vector<uint8_t> buffer_data = RD::get_singleton()->buffer_get_data(multimesh->buffer);
if (!multimesh->data_cache.is_empty()) {
memcpy(buffer_data.ptrw(), multimesh->data_cache.ptr(), buffer_data.size());
}
ERR_FAIL_COND(buffer_data.size() != int(buffer_size));
RD::get_singleton()->buffer_update(new_buffer, 0, buffer_size, buffer_data.ptr(), RD::BARRIER_MASK_NO_BARRIER);
RD::get_singleton()->buffer_update(new_buffer, buffer_size, buffer_size, buffer_data.ptr());
} else if (!multimesh->data_cache.is_empty()) {
// Simply upload the data cached in the CPU, which should already be doubled in size.
ERR_FAIL_COND(multimesh->data_cache.size() != int(new_buffer_size));
RD::get_singleton()->buffer_update(new_buffer, 0, new_buffer_size, multimesh->data_cache.ptr());
}

if (multimesh->buffer.is_valid()) {
RD::get_singleton()->free(multimesh->buffer);
uint32_t buffer_size = multimesh->instances * multimesh->stride_cache * sizeof(float) * 2;
multimesh->buffer = RD::get_singleton()->storage_buffer_create(buffer_size);
RD::get_singleton()->buffer_update(multimesh->buffer, 0, buffer_data.size(), buffer_data.ptr(), RD::BARRIER_MASK_NO_BARRIER);
RD::get_singleton()->buffer_update(multimesh->buffer, buffer_data.size(), buffer_data.size(), buffer_data.ptr());
multimesh->uniform_set_3d = RID(); // Cleared by dependency
return true;
}
return false; // Update the transforms uniform set cache

multimesh->buffer = new_buffer;
multimesh->uniform_set_3d = RID(); // Cleared by dependency.
}

void MeshStorage::_multimesh_get_motion_vectors_offsets(RID p_multimesh, uint32_t &r_current_offset, uint32_t &r_prev_offset) {
Expand Down Expand Up @@ -1531,6 +1536,12 @@ void MeshStorage::multimesh_instance_set_transform(RID p_multimesh, int p_index,
ERR_FAIL_COND(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_3D);

_multimesh_make_local(multimesh);

bool uses_motion_vectors = (RSG::viewport->get_num_viewports_with_motion_vectors() > 0);
if (uses_motion_vectors) {
_multimesh_enable_motion_vectors(multimesh);
}

_multimesh_update_motion_vectors_data_cache(multimesh);

{
Expand Down Expand Up @@ -1749,6 +1760,11 @@ void MeshStorage::multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_b
ERR_FAIL_COND(!multimesh);
ERR_FAIL_COND(p_buffer.size() != (multimesh->instances * (int)multimesh->stride_cache));

bool uses_motion_vectors = (RSG::viewport->get_num_viewports_with_motion_vectors() > 0);
if (uses_motion_vectors) {
_multimesh_enable_motion_vectors(multimesh);
}

if (multimesh->motion_vectors_enabled) {
uint32_t frame = RSG::rasterizer->get_frame_number();

Expand Down
2 changes: 1 addition & 1 deletion servers/rendering/renderer_rd/storage_rd/mesh_storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ class MeshStorage : public RendererMeshStorage {
MultiMesh *multimesh_dirty_list = nullptr;

_FORCE_INLINE_ void _multimesh_make_local(MultiMesh *multimesh) const;
_FORCE_INLINE_ void _multimesh_enable_motion_vectors(MultiMesh *multimesh);
_FORCE_INLINE_ void _multimesh_update_motion_vectors_data_cache(MultiMesh *multimesh);
_FORCE_INLINE_ void _multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool p_aabb);
_FORCE_INLINE_ void _multimesh_mark_all_dirty(MultiMesh *multimesh, bool p_data, bool p_aabb);
Expand Down Expand Up @@ -593,7 +594,6 @@ class MeshStorage : public RendererMeshStorage {
virtual AABB multimesh_get_aabb(RID p_multimesh) const override;

void _update_dirty_multimeshes();
bool _multimesh_enable_motion_vectors(RID p_multimesh);
void _multimesh_get_motion_vectors_offsets(RID p_multimesh, uint32_t &r_current_offset, uint32_t &r_prev_offset);

_FORCE_INLINE_ RS::MultimeshTransformFormat multimesh_get_transform_format(RID p_multimesh) const {
Expand Down
9 changes: 9 additions & 0 deletions servers/rendering/renderer_viewport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1194,6 +1194,7 @@ void RendererViewport::viewport_set_use_taa(RID p_viewport, bool p_use_taa) {
return;
}
viewport->use_taa = p_use_taa;
num_viewports_with_motion_vectors += p_use_taa ? 1 : -1;
_configure_3d_render_buffers(viewport);
}

Expand Down Expand Up @@ -1378,6 +1379,10 @@ bool RendererViewport::free(RID p_rid) {
RendererSceneOcclusionCull::get_singleton()->remove_buffer(p_rid);
}

if (viewport->use_taa) {
num_viewports_with_motion_vectors--;
}

viewport_owner.free(p_rid);

return true;
Expand Down Expand Up @@ -1433,6 +1438,10 @@ int RendererViewport::get_total_draw_calls_used() const {
return total_draw_calls_used;
}

int RendererViewport::get_num_viewports_with_motion_vectors() const {
return num_viewports_with_motion_vectors;
}

RendererViewport::RendererViewport() {
occlusion_rays_per_thread = GLOBAL_GET("rendering/occlusion_culling/occlusion_rays_per_thread");
}
3 changes: 3 additions & 0 deletions servers/rendering/renderer_viewport.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,8 @@ class RendererViewport {
int total_vertices_drawn = 0;
int total_draw_calls_used = 0;

int num_viewports_with_motion_vectors = 0;

private:
Vector<Viewport *> _sort_active_viewports();
void _viewport_set_size(Viewport *p_viewport, int p_width, int p_height, uint32_t p_view_count);
Expand Down Expand Up @@ -302,6 +304,7 @@ class RendererViewport {
int get_total_objects_drawn() const;
int get_total_primitives_drawn() const;
int get_total_draw_calls_used() const;
int get_num_viewports_with_motion_vectors() const;

// Workaround for setting this on thread.
void call_set_vsync_mode(DisplayServer::VSyncMode p_mode, DisplayServer::WindowID p_window);
Expand Down

0 comments on commit 67543e9

Please sign in to comment.