mirror of
https://github.com/godotengine/godot.git
synced 2025-01-26 20:42:55 -05:00
Merge pull request #80414 from DarioSamo/multimesh-motion-vectors
Improve handling of motion vectors for multimesh instances.
This commit is contained in:
commit
67543e963d
5 changed files with 47 additions and 26 deletions
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
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;
|
||||
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());
|
||||
}
|
||||
return false; // Update the transforms uniform set cache
|
||||
|
||||
if (multimesh->buffer.is_valid()) {
|
||||
RD::get_singleton()->free(multimesh->buffer);
|
||||
}
|
||||
|
||||
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) {
|
||||
|
@ -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);
|
||||
|
||||
{
|
||||
|
@ -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();
|
||||
|
||||
|
|
|
@ -234,6 +234,7 @@ private:
|
|||
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);
|
||||
|
@ -593,7 +594,6 @@ public:
|
|||
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 {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -198,6 +198,8 @@ public:
|
|||
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);
|
||||
|
@ -302,6 +304,7 @@ public:
|
|||
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);
|
||||
|
|
Loading…
Add table
Reference in a new issue