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

Implement motion vectors in mobile renderer #100283

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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 @@ -308,6 +308,10 @@ bool OpenXRVulkanExtension::get_swapchain_image_data(XrSwapchain p_swapchain, in
format = RenderingDevice::DATA_FORMAT_B8G8R8A8_UINT;
usage_flags |= RenderingDevice::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
break;
case VK_FORMAT_R16G16B16A16_SFLOAT:
format = RenderingDevice::DATA_FORMAT_R16G16B16A16_SFLOAT;
usage_flags |= RenderingDevice::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
break;
case VK_FORMAT_D32_SFLOAT:
format = RenderingDevice::DATA_FORMAT_D32_SFLOAT;
usage_flags |= RenderingDevice::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,34 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RenderSceneBu
ERR_FAIL_NULL(render_buffers); // Huh? really?
}

RID RendererSceneRenderImplementation::RenderForwardMobile::RenderBufferDataForwardMobile::get_motion_vectors_fb() {
ERR_FAIL_NULL_V(render_buffers, RID());

RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
ERR_FAIL_NULL_V(texture_storage, RID());

RID velocity = render_buffers->get_velocity_buffer(false);
RID velocity_depth = render_buffers->get_velocity_depth_buffer();

if (velocity.is_valid() && velocity_depth.is_valid()) {
Vector<RID> textures;
textures.push_back(velocity);
textures.push_back(velocity_depth);

Vector<RD::FramebufferPass> passes;
RD::FramebufferPass pass;
pass.color_attachments.push_back(0);
pass.depth_attachment = 1;
passes.push_back(pass);

uint32_t view_count = render_buffers->get_view_count();

return FramebufferCacheRD::get_singleton()->get_cache_multipass(textures, passes, view_count);
}

return RID();
}

RID RenderForwardMobile::RenderBufferDataForwardMobile::get_color_fbs(FramebufferConfigType p_config_type) {
ERR_FAIL_NULL_V(render_buffers, RID());

Expand Down Expand Up @@ -754,19 +782,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color

RENDER_TIMESTAMP("Setup 3D Scene");

/* TODO
// check if we need motion vectors
if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_MOTION_VECTORS) {
p_render_data->scene_data->calculate_motion_vectors = true;
} else if (_compositor_effects_has_flag(p_render_data, RS::COMPOSITOR_EFFECT_FLAG_NEEDS_MOTION_VECTORS)) {
p_render_data->scene_data->calculate_motion_vectors = true;
} else if (render target has velocity override) { // TODO
p_render_data->scene_data->calculate_motion_vectors = true;
} else {
p_render_data->scene_data->calculate_motion_vectors = false;
}
*/
p_render_data->scene_data->calculate_motion_vectors = false; // for now, not yet supported...
p_render_data->scene_data->calculate_motion_vectors = RendererRD::TextureStorage::get_singleton()->render_target_get_override_velocity(rb->get_render_target()).is_valid();

p_render_data->scene_data->directional_light_count = 0;
p_render_data->scene_data->opaque_prepass_threshold = 0.0;
Expand Down Expand Up @@ -1050,6 +1066,25 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
breadcrumb = RDD::BreadcrumbMarker::REFLECTION_PROBES;
}

if (rb_data.is_valid()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (rb_data.is_valid()) {
if (rb_data.is_valid() && p_render_data->scene_data->calculate_motion_vectors) {

RID mv_fb = rb_data->get_motion_vectors_fb();

if (mv_fb.is_valid()) {
RENDER_TIMESTAMP("Render Motion Vectors");

Vector<Color> mv_pass_clear;
mv_pass_clear.push_back(Color(0, 0, 0, 0));

RD::get_singleton()->draw_command_begin_label("Render Motion Vectors");

RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_OPAQUE, nullptr, RID(), samplers);
clayjohn marked this conversation as resolved.
Show resolved Hide resolved
RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, PASS_MODE_MOTION_VECTORS, rp_uniform_set, base_specialization);
_render_list_with_draw_list(&render_list_params, mv_fb, RD::DRAW_CLEAR_ALL, mv_pass_clear);

RD::get_singleton()->draw_command_end_label();
}
}

// opaque pass
RD::get_singleton()->draw_command_begin_label("Render Opaque");

Expand Down Expand Up @@ -1814,14 +1849,22 @@ void RenderForwardMobile::_fill_instance_data(RenderListType p_render_list, uint
scene_state.instance_data[p_render_list].resize(p_offset + element_total);
rl->element_info.resize(p_offset + element_total);

uint64_t frame = RSG::rasterizer->get_frame_number();

for (uint32_t i = 0; i < element_total; i++) {
GeometryInstanceSurfaceDataCache *surface = rl->elements[i + p_offset];
GeometryInstanceForwardMobile *inst = surface->owner;

SceneState::InstanceData &instance_data = scene_state.instance_data[p_render_list][i + p_offset];

if (inst->prev_transform_dirty && frame > inst->prev_transform_change_frame + 1 && inst->prev_transform_change_frame) {
inst->prev_transform = inst->transform;
inst->prev_transform_dirty = false;
}

if (inst->store_transform_cache) {
RendererRD::MaterialStorage::store_transform(inst->transform, instance_data.transform);
RendererRD::MaterialStorage::store_transform(inst->prev_transform, instance_data.prev_transform);

#ifdef REAL_T_IS_DOUBLE
// Split the origin into two components, the float approximation and the missing precision.
Expand All @@ -1832,6 +1875,7 @@ void RenderForwardMobile::_fill_instance_data(RenderListType p_render_list, uint
#endif
} else {
RendererRD::MaterialStorage::store_transform(Transform3D(), instance_data.transform);
RendererRD::MaterialStorage::store_transform(Transform3D(), instance_data.prev_transform);
}

instance_data.flags = inst->flags_cache;
Expand Down Expand Up @@ -2026,7 +2070,7 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const
}

// ADD Element
if (p_pass_mode == PASS_MODE_COLOR || p_pass_mode == PASS_MODE_COLOR_TRANSPARENT) {
if (p_pass_mode == PASS_MODE_COLOR || p_pass_mode == PASS_MODE_COLOR_TRANSPARENT || p_pass_mode == PASS_MODE_MOTION_VECTORS) {
#ifdef DEBUG_ENABLED
bool force_alpha = unlikely(get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_OVERDRAW);
#else
Expand Down Expand Up @@ -2115,6 +2159,9 @@ void RenderForwardMobile::_render_list(RenderingDevice::DrawListID p_draw_list,
case PASS_MODE_DEPTH_MATERIAL: {
_render_list_template<PASS_MODE_DEPTH_MATERIAL>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element);
} break;
case PASS_MODE_MOTION_VECTORS: {
_render_list_template<PASS_MODE_MOTION_VECTORS>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element);
}
}
}

Expand All @@ -2130,6 +2177,7 @@ void RenderForwardMobile::_render_list_with_draw_list(RenderListParameters *p_pa
template <RenderForwardMobile::PassMode p_pass_mode>
void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element) {
RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
RendererRD::ParticlesStorage *particles_storage = RendererRD::ParticlesStorage::get_singleton();

RD::DrawListID draw_list = p_draw_list;
RD::FramebufferFormatID framebuffer_format = p_framebuffer_Format;
Expand Down Expand Up @@ -2261,6 +2309,9 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr
ERR_FAIL_COND_MSG(p_params->view_count > 1, "Multiview not supported for material pass");
pipeline_key.version = SceneShaderForwardMobile::SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL;
} break;
case PASS_MODE_MOTION_VECTORS: {
pipeline_key.version = SceneShaderForwardMobile::SHADER_VERSION_MOTION_VECTORS;
}
}

pipeline_key.framebuffer_format_id = framebuffer_format;
Expand All @@ -2279,9 +2330,9 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr
// Skeleton and blend shape.
uint64_t input_mask = shader->get_vertex_input_mask(pipeline_key.version, pipeline_key.ubershader);
if (surf->owner->mesh_instance.is_valid()) {
mesh_storage->mesh_instance_surface_get_vertex_arrays_and_format(surf->owner->mesh_instance, surf->surface_index, input_mask, false, vertex_array_rd, vertex_format);
mesh_storage->mesh_instance_surface_get_vertex_arrays_and_format(surf->owner->mesh_instance, surf->surface_index, input_mask, p_pass_mode == PASS_MODE_MOTION_VECTORS, vertex_array_rd, vertex_format);
} else {
mesh_storage->mesh_surface_get_vertex_arrays_and_format(mesh_surface, input_mask, false, vertex_array_rd, vertex_format);
mesh_storage->mesh_surface_get_vertex_arrays_and_format(mesh_surface, input_mask, p_pass_mode == PASS_MODE_MOTION_VECTORS, vertex_array_rd, vertex_format);
}

index_array_rd = mesh_storage->mesh_surface_get_index_array(mesh_surface, element_info.lod_index);
Expand Down Expand Up @@ -2349,6 +2400,15 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr
prev_material_uniform_set = material_uniform_set;
}

if (surf->owner->base_flags & INSTANCE_DATA_FLAG_PARTICLES) {
particles_storage->particles_get_instance_buffer_motion_vectors_offsets(surf->owner->data->base, push_constant.multimesh_motion_vectors_current_offset, push_constant.multimesh_motion_vectors_previous_offset);
} else if (surf->owner->base_flags & INSTANCE_DATA_FLAG_MULTIMESH) {
mesh_storage->_multimesh_get_motion_vectors_offsets(surf->owner->data->base, push_constant.multimesh_motion_vectors_current_offset, push_constant.multimesh_motion_vectors_previous_offset);
} else {
push_constant.multimesh_motion_vectors_current_offset = 0;
push_constant.multimesh_motion_vectors_previous_offset = 0;
}

size_t push_constant_size = 0;
if (pipeline_key.ubershader) {
push_constant_size = sizeof(SceneState::PushConstant);
Expand Down Expand Up @@ -2396,6 +2456,17 @@ RenderGeometryInstance *RenderForwardMobile::geometry_instance_create(RID p_base
return ginstance;
}

void RendererSceneRenderImplementation::RenderForwardMobile::GeometryInstanceForwardMobile::set_transform(const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) {
uint64_t frame = RSG::rasterizer->get_frame_number();
if (frame != prev_transform_change_frame) {
prev_transform = transform;
prev_transform_change_frame = frame;
prev_transform_dirty = true;
}

RenderGeometryInstanceBase::set_transform(p_transform, p_aabb, p_transformed_aabb);
}

void RenderForwardMobile::GeometryInstanceForwardMobile::set_use_lightmap(RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) {
lightmap_instance = p_lightmap_instance;
lightmap_uv_scale = p_lightmap_uv_scale;
Expand Down Expand Up @@ -2800,6 +2871,7 @@ void RenderForwardMobile::_geometry_instance_update(RenderGeometryInstance *p_ge
ginstance->transforms_uniform_set = mesh_storage->multimesh_get_3d_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);

} else if (ginstance->data->base_type == RS::INSTANCE_PARTICLES) {
ginstance->base_flags |= INSTANCE_DATA_FLAG_PARTICLES;
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH;
if (false) { // 2D particles
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ class RenderForwardMobile : public RendererSceneRenderRD {
virtual void free_data() override;
virtual void configure(RenderSceneBuffersRD *p_render_buffers) override;

RID get_motion_vectors_fb();

private:
RenderSceneBuffersRD *render_buffers = nullptr;
};
Expand All @@ -111,6 +113,7 @@ class RenderForwardMobile : public RendererSceneRenderRD {
// PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI,
PASS_MODE_DEPTH_MATERIAL,
// PASS_MODE_SDF,
PASS_MODE_MOTION_VECTORS,
};

struct RenderElementInfo;
Expand Down Expand Up @@ -205,11 +208,16 @@ class RenderForwardMobile : public RendererSceneRenderRD {
float uv_offset[2];
uint32_t base_index;
uint32_t pad;
uint32_t multimesh_motion_vectors_current_offset;
uint32_t multimesh_motion_vectors_previous_offset;
uint32_t pad2;
uint32_t pad3;
PushConstantUbershader ubershader;
};

struct InstanceData {
float transform[16];
float prev_transform[16];
uint32_t flags;
uint32_t instance_uniforms_ofs; // Base offset in global buffer for instance variables.
uint32_t gi_offset; // GI information when using lightmapping (VCT or lightmap index).
Expand Down Expand Up @@ -454,6 +462,10 @@ class RenderForwardMobile : public RendererSceneRenderRD {
uint32_t instance_count = 0;
uint32_t trail_steps = 1;

uint64_t prev_transform_change_frame = UINT_MAX;
bool prev_transform_dirty = true;
Transform3D prev_transform;

// lightmap
uint32_t gi_offset_cache = 0; // !BAS! Should rename this to lightmap_offset_cache, in forward clustered this was shared between gi and lightmap
RID lightmap_instance;
Expand Down Expand Up @@ -481,6 +493,7 @@ class RenderForwardMobile : public RendererSceneRenderRD {

virtual void _mark_dirty() override;

virtual void set_transform(const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) override;
virtual void set_use_lightmap(RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override;
virtual void set_lightmap_capture(const Color *p_sh9) override;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ void SceneShaderForwardMobile::ShaderData::_create_pipeline(PipelineKey p_pipeli
multisample_state.enable_alpha_to_one = true;
}

if (p_pipeline_key.version == SHADER_VERSION_COLOR_PASS || p_pipeline_key.version == SHADER_VERSION_COLOR_PASS_MULTIVIEW || p_pipeline_key.version == SHADER_VERSION_LIGHTMAP_COLOR_PASS || p_pipeline_key.version == SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW) {
if (p_pipeline_key.version == SHADER_VERSION_COLOR_PASS || p_pipeline_key.version == SHADER_VERSION_COLOR_PASS_MULTIVIEW || p_pipeline_key.version == SHADER_VERSION_LIGHTMAP_COLOR_PASS || p_pipeline_key.version == SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW || p_pipeline_key.version == SHADER_VERSION_MOTION_VECTORS) {
blend_state = blend_state_blend;
if (depth_draw == DEPTH_DRAW_OPAQUE && !uses_alpha_clip) {
// Alpha does not write to depth.
Expand All @@ -310,7 +310,7 @@ void SceneShaderForwardMobile::ShaderData::_create_pipeline(PipelineKey p_pipeli
// Do not use this version (error case).
}
} else {
if (p_pipeline_key.version == SHADER_VERSION_COLOR_PASS || p_pipeline_key.version == SHADER_VERSION_COLOR_PASS_MULTIVIEW || p_pipeline_key.version == SHADER_VERSION_LIGHTMAP_COLOR_PASS || p_pipeline_key.version == SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW) {
if (p_pipeline_key.version == SHADER_VERSION_COLOR_PASS || p_pipeline_key.version == SHADER_VERSION_COLOR_PASS_MULTIVIEW || p_pipeline_key.version == SHADER_VERSION_LIGHTMAP_COLOR_PASS || p_pipeline_key.version == SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW || p_pipeline_key.version == SHADER_VERSION_MOTION_VECTORS) {
blend_state = blend_state_opaque;
} else if (p_pipeline_key.version == SHADER_VERSION_SHADOW_PASS || p_pipeline_key.version == SHADER_VERSION_SHADOW_PASS_MULTIVIEW || p_pipeline_key.version == SHADER_VERSION_SHADOW_PASS_DP) {
// Contains nothing.
Expand Down Expand Up @@ -490,6 +490,7 @@ void SceneShaderForwardMobile::init(const String p_defines) {
shader_versions.push_back(base_define + "\n#define MODE_RENDER_DEPTH\n"); // SHADER_VERSION_SHADOW_PASS, should probably change this to MODE_RENDER_SHADOW because we don't have a depth pass here...
shader_versions.push_back(base_define + "\n#define MODE_RENDER_DEPTH\n#define MODE_DUAL_PARABOLOID\n"); // SHADER_VERSION_SHADOW_PASS_DP
shader_versions.push_back(base_define + "\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_MATERIAL\n"); // SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL
shader_versions.push_back(base_define + "\n#define MODE_RENDER_MOTION_VECTORS\n#define USE_MULTIVIEW\n"); // SHADER_VERSION_MOTION_VECTORS

// Multiview versions of our shaders.
shader_versions.push_back(base_define + "\n#define USE_MULTIVIEW\n"); // SHADER_VERSION_COLOR_PASS_MULTIVIEW
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class SceneShaderForwardMobile {
SHADER_VERSION_SHADOW_PASS,
SHADER_VERSION_SHADOW_PASS_DP,
SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL,
SHADER_VERSION_MOTION_VECTORS,

SHADER_VERSION_COLOR_PASS_MULTIVIEW,
SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW,
Expand Down
Loading
Loading