Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve handling of motion vectors for multimesh instances. #80414

Merged
merged 1 commit into from
Aug 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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