diff options
Diffstat (limited to 'servers/rendering')
88 files changed, 1970 insertions, 1603 deletions
diff --git a/servers/rendering/dummy/rasterizer_scene_dummy.h b/servers/rendering/dummy/rasterizer_scene_dummy.h index bc8f7c523b..918f5c1fb7 100644 --- a/servers/rendering/dummy/rasterizer_scene_dummy.h +++ b/servers/rendering/dummy/rasterizer_scene_dummy.h @@ -49,6 +49,7 @@ public: virtual void set_surface_materials(const Vector<RID> &p_materials) override {} virtual void set_mesh_instance(RID p_mesh_instance) override {} virtual void set_transform(const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) override {} + virtual void set_pivot_data(float p_sorting_offset, bool p_use_aabb_center) override {} virtual void set_lod_bias(float p_lod_bias) override {} virtual void set_layer_mask(uint32_t p_layer_mask) override {} virtual void set_fade_range(bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) override {} @@ -112,7 +113,6 @@ public: /* ENVIRONMENT API */ void environment_glow_set_use_bicubic_upscale(bool p_enable) override {} - void environment_glow_set_use_high_quality(bool p_enable) override {} void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) override {} diff --git a/servers/rendering/dummy/storage/light_storage.h b/servers/rendering/dummy/storage/light_storage.h index 13c342d823..960f5a867a 100644 --- a/servers/rendering/dummy/storage/light_storage.h +++ b/servers/rendering/dummy/storage/light_storage.h @@ -135,6 +135,7 @@ public: virtual bool reflection_probe_instance_needs_redraw(RID p_instance) override { return false; } virtual bool reflection_probe_instance_has_reflection(RID p_instance) override { return false; } virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) override { return false; } + virtual Ref<RenderSceneBuffers> reflection_probe_atlas_get_render_buffers(RID p_reflection_atlas) override { return Ref<RenderSceneBuffers>(); } virtual bool reflection_probe_instance_postprocess_step(RID p_instance) override { return true; } /* LIGHTMAP CAPTURE */ diff --git a/servers/rendering/dummy/storage/mesh_storage.cpp b/servers/rendering/dummy/storage/mesh_storage.cpp index adf736eee3..52de998835 100644 --- a/servers/rendering/dummy/storage/mesh_storage.cpp +++ b/servers/rendering/dummy/storage/mesh_storage.cpp @@ -56,3 +56,10 @@ void MeshStorage::mesh_free(RID p_rid) { mesh_owner.free(p_rid); } + +void MeshStorage::mesh_clear(RID p_mesh) { + DummyMesh *m = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND(!m); + + m->surfaces.clear(); +} diff --git a/servers/rendering/dummy/storage/mesh_storage.h b/servers/rendering/dummy/storage/mesh_storage.h index 4399f4ab66..28fe8cb80d 100644 --- a/servers/rendering/dummy/storage/mesh_storage.h +++ b/servers/rendering/dummy/storage/mesh_storage.h @@ -116,7 +116,7 @@ public: virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID()) override { return AABB(); } virtual void mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) override {} - virtual void mesh_clear(RID p_mesh) override {} + virtual void mesh_clear(RID p_mesh) override; /* MESH INSTANCE */ diff --git a/servers/rendering/dummy/storage/particles_storage.h b/servers/rendering/dummy/storage/particles_storage.h index 7cee55922d..beedff0a76 100644 --- a/servers/rendering/dummy/storage/particles_storage.h +++ b/servers/rendering/dummy/storage/particles_storage.h @@ -89,8 +89,6 @@ public: virtual void particles_add_collision(RID p_particles, RID p_instance) override {} virtual void particles_remove_collision(RID p_particles, RID p_instance) override {} - virtual void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) override {} - virtual void update_particles() override {} /* PARTICLES COLLISION */ @@ -111,7 +109,6 @@ public: virtual void particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) override {} virtual AABB particles_collision_get_aabb(RID p_particles_collision) const override { return AABB(); } virtual bool particles_collision_is_heightfield(RID p_particles_collision) const override { return false; } - virtual RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const override { return RID(); } virtual RID particles_collision_instance_create(RID p_collision) override { return RID(); } virtual void particles_collision_instance_free(RID p_rid) override {} diff --git a/servers/rendering/dummy/storage/texture_storage.h b/servers/rendering/dummy/storage/texture_storage.h index ad28dd68c3..dd89504f38 100644 --- a/servers/rendering/dummy/storage/texture_storage.h +++ b/servers/rendering/dummy/storage/texture_storage.h @@ -80,6 +80,7 @@ public: virtual void texture_free(RID p_rid) override { // delete the texture DummyTexture *texture = texture_owner.get_or_null(p_rid); + ERR_FAIL_COND(!texture); texture_owner.free(p_rid); memdelete(texture); }; @@ -126,6 +127,8 @@ public: virtual Size2 texture_size_with_proxy(RID p_proxy) override { return Size2(); }; + virtual RID texture_get_rd_texture_rid(RID p_texture, bool p_srgb = false) const override { return RID(); }; + /* DECAL API */ virtual RID decal_allocate() override { return RID(); } virtual void decal_initialize(RID p_rid) override {} diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp index 16d382a5f3..6be0419d98 100644 --- a/servers/rendering/renderer_canvas_cull.cpp +++ b/servers/rendering/renderer_canvas_cull.cpp @@ -275,12 +275,12 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2 if (ci->clip) { if (p_canvas_clip != nullptr) { ci->final_clip_rect = p_canvas_clip->final_clip_rect.intersection(global_rect); - if (ci->final_clip_rect == Rect2()) { - // Clip rects do not intersect, so don't draw this item. - return; - } } else { - ci->final_clip_rect = global_rect; + ci->final_clip_rect = p_clip_rect.intersection(global_rect); + } + if (ci->final_clip_rect.size.width < 0.5 || ci->final_clip_rect.size.height < 0.5) { + // The clip rect area is 0, so don't draw the item. + return; } ci->final_clip_rect.position = ci->final_clip_rect.position.round(); ci->final_clip_rect.size = ci->final_clip_rect.size.round(); @@ -1075,18 +1075,36 @@ void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point void RendererCanvasCull::canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width) { ERR_FAIL_COND(p_points.size() < 2); - Item *canvas_item = canvas_item_owner.get_or_null(p_item); - ERR_FAIL_COND(!canvas_item); - - Item::CommandPolygon *pline = canvas_item->alloc_command<Item::CommandPolygon>(); - ERR_FAIL_COND(!pline); - if (true || p_width <= 1) { -#define TODO make thick lines possible + // TODO: `canvas_item_add_line`(`multiline`, `polyline`) share logic, should factor out. + if (p_width <= 1) { + Item *canvas_item = canvas_item_owner.get_or_null(p_item); + ERR_FAIL_COND(!canvas_item); + Item::CommandPolygon *pline = canvas_item->alloc_command<Item::CommandPolygon>(); + ERR_FAIL_COND(!pline); pline->primitive = RS::PRIMITIVE_LINES; pline->polygon.create(Vector<int>(), p_points, p_colors); } else { + if (p_colors.size() == 1) { + Color color = p_colors[0]; + for (int i = 0; i < p_points.size() >> 1; i++) { + Vector2 from = p_points[i * 2 + 0]; + Vector2 to = p_points[i * 2 + 1]; + + canvas_item_add_line(p_item, from, to, color, p_width); + } + } else if (p_colors.size() == p_points.size() >> 1) { + for (int i = 0; i < p_points.size() >> 1; i++) { + Color color = p_colors[i]; + Vector2 from = p_points[i * 2 + 0]; + Vector2 to = p_points[i * 2 + 1]; + + canvas_item_add_line(p_item, from, to, color, p_width); + } + } else { + ERR_FAIL_MSG("Length of p_colors is invalid."); + } } } @@ -1167,7 +1185,7 @@ void RendererCanvasCull::canvas_item_add_texture_rect(RID p_item, const Rect2 &p rect->texture = p_texture; } -void RendererCanvasCull::canvas_item_add_msdf_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate, int p_outline_size, float p_px_range) { +void RendererCanvasCull::canvas_item_add_msdf_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate, int p_outline_size, float p_px_range, float p_scale) { Item *canvas_item = canvas_item_owner.get_or_null(p_item); ERR_FAIL_COND(!canvas_item); @@ -1197,7 +1215,7 @@ void RendererCanvasCull::canvas_item_add_msdf_texture_rect_region(RID p_item, co rect->flags ^= RendererCanvasRender::CANVAS_RECT_FLIP_V; rect->source.size.y = -rect->source.size.y; } - rect->outline = p_outline_size; + rect->outline = (float)p_outline_size / p_scale / 4.0; rect->px_range = p_px_range; } diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h index 198e1020f0..808c0acc35 100644 --- a/servers/rendering/renderer_canvas_cull.h +++ b/servers/rendering/renderer_canvas_cull.h @@ -228,7 +228,7 @@ public: void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color); void canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false); void canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, bool p_clip_uv = false); - void canvas_item_add_msdf_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, float p_px_range = 1.0); + void canvas_item_add_msdf_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, float p_px_range = 1.0, float p_scale = 1.0); void canvas_item_add_lcd_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1)); void canvas_item_add_nine_patch(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector2 &p_topleft, const Vector2 &p_bottomright, RS::NinePatchAxisMode p_x_axis_mode = RS::NINE_PATCH_STRETCH, RS::NinePatchAxisMode p_y_axis_mode = RS::NINE_PATCH_STRETCH, bool p_draw_center = true, const Color &p_modulate = Color(1, 1, 1)); void canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width = 1.0); diff --git a/servers/rendering/renderer_canvas_render.cpp b/servers/rendering/renderer_canvas_render.cpp index 623f0c647b..07394b49a3 100644 --- a/servers/rendering/renderer_canvas_render.cpp +++ b/servers/rendering/renderer_canvas_render.cpp @@ -32,7 +32,7 @@ #include "servers/rendering/rendering_server_globals.h" const Rect2 &RendererCanvasRender::Item::get_rect() const { - if (custom_rect || (!rect_dirty && !update_when_visible)) { + if (custom_rect || (!rect_dirty && !update_when_visible && skeleton == RID())) { return rect; } @@ -80,7 +80,7 @@ const Rect2 &RendererCanvasRender::Item::get_rect() const { } break; case Item::Command::TYPE_MESH: { const Item::CommandMesh *mesh = static_cast<const Item::CommandMesh *>(c); - AABB aabb = RSG::mesh_storage->mesh_get_aabb(mesh->mesh, RID()); + AABB aabb = RSG::mesh_storage->mesh_get_aabb(mesh->mesh, skeleton); r = Rect2(aabb.position.x, aabb.position.y, aabb.size.x, aabb.size.y); diff --git a/servers/rendering/renderer_geometry_instance.cpp b/servers/rendering/renderer_geometry_instance.cpp index 675659f4c8..f4681916f4 100644 --- a/servers/rendering/renderer_geometry_instance.cpp +++ b/servers/rendering/renderer_geometry_instance.cpp @@ -80,6 +80,11 @@ void RenderGeometryInstanceBase::set_transform(const Transform3D &p_transform, c lod_model_scale = max_scale; } +void RenderGeometryInstanceBase::set_pivot_data(float p_sorting_offset, bool p_use_aabb_center) { + sorting_offset = p_sorting_offset; + use_aabb_center = p_use_aabb_center; +} + void RenderGeometryInstanceBase::set_lod_bias(float p_lod_bias) { lod_bias = p_lod_bias; } diff --git a/servers/rendering/renderer_geometry_instance.h b/servers/rendering/renderer_geometry_instance.h index fecb9878c2..37fde9e1f6 100644 --- a/servers/rendering/renderer_geometry_instance.h +++ b/servers/rendering/renderer_geometry_instance.h @@ -50,6 +50,7 @@ public: virtual void set_surface_materials(const Vector<RID> &p_materials) = 0; virtual void set_mesh_instance(RID p_mesh_instance) = 0; virtual void set_transform(const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) = 0; + virtual void set_pivot_data(float p_sorting_offset, bool p_use_aabb_center) = 0; virtual void set_lod_bias(float p_lod_bias) = 0; virtual void set_layer_mask(uint32_t p_layer_mask) = 0; virtual void set_fade_range(bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) = 0; @@ -86,11 +87,13 @@ public: RID mesh_instance; Transform3D transform; - bool mirror = false; // move into data? - AABB transformed_aabb; //needed for LOD + bool mirror = false; + AABB transformed_aabb; bool non_uniform_scale = false; float lod_model_scale = 1.0; float lod_bias = 0.0; + float sorting_offset = 0.0; + bool use_aabb_center = true; uint32_t layer_mask = 1; @@ -133,6 +136,7 @@ public: virtual void set_surface_materials(const Vector<RID> &p_materials) override; virtual void set_mesh_instance(RID p_mesh_instance) override; virtual void set_transform(const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) override; + virtual void set_pivot_data(float p_sorting_offset, bool p_use_aabb_center) override; virtual void set_lod_bias(float p_lod_bias) override; virtual void set_layer_mask(uint32_t p_layer_mask) override; virtual void set_fade_range(bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) override; diff --git a/servers/rendering/renderer_rd/SCsub b/servers/rendering/renderer_rd/SCsub index 10b83dca11..a27439e931 100644 --- a/servers/rendering/renderer_rd/SCsub +++ b/servers/rendering/renderer_rd/SCsub @@ -9,4 +9,5 @@ SConscript("environment/SCsub") SConscript("forward_clustered/SCsub") SConscript("forward_mobile/SCsub") SConscript("shaders/SCsub") +SConscript("spirv-reflect/SCsub") SConscript("storage_rd/SCsub") diff --git a/servers/rendering/renderer_rd/effects/copy_effects.cpp b/servers/rendering/renderer_rd/effects/copy_effects.cpp index a14228eb3d..9fda54a34d 100644 --- a/servers/rendering/renderer_rd/effects/copy_effects.cpp +++ b/servers/rendering/renderer_rd/effects/copy_effects.cpp @@ -56,6 +56,7 @@ CopyEffects::CopyEffects(bool p_prefer_raster_effects) { blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n"); // BLUR_MODE_GAUSSIAN_GLOW blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n#define GLOW_USE_AUTO_EXPOSURE\n"); // BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE blur_modes.push_back("\n#define MODE_COPY\n"); // BLUR_MODE_COPY + blur_modes.push_back("\n#define MODE_SET_COLOR\n"); // BLUR_MODE_SET_COLOR blur_raster.shader.initialize(blur_modes); memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant)); @@ -105,6 +106,7 @@ CopyEffects::CopyEffects(bool p_prefer_raster_effects) { copy_modes.push_back("\n#define MODE_TWO_SOURCES\n"); // COPY_TO_FB_COPY2 copy_modes.push_back("\n#define MULTIVIEW\n"); // COPY_TO_FB_MULTIVIEW copy_modes.push_back("\n#define MULTIVIEW\n#define MODE_TWO_SOURCES\n"); // COPY_TO_FB_MULTIVIEW_WITH_DEPTH + copy_modes.push_back("\n#define MODE_SET_COLOR\n"); // COPY_TO_FB_SET_COLOR copy_to_fb.shader.initialize(copy_modes); @@ -508,16 +510,18 @@ void CopyEffects::copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuff memset(©_to_fb.push_constant, 0, sizeof(CopyToFbPushConstant)); - copy_to_fb.push_constant.use_section = true; + copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_USE_SECTION; copy_to_fb.push_constant.section[0] = p_uv_rect.position.x; copy_to_fb.push_constant.section[1] = p_uv_rect.position.y; copy_to_fb.push_constant.section[2] = p_uv_rect.size.x; copy_to_fb.push_constant.section[3] = p_uv_rect.size.y; if (p_flip_y) { - copy_to_fb.push_constant.flip_y = true; + copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_FLIP_Y; } + copy_to_fb.push_constant.luminance_multiplier = 1.0; + // setup our uniforms RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); @@ -535,25 +539,35 @@ void CopyEffects::copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuff RD::get_singleton()->draw_list_draw(draw_list, true); } -void CopyEffects::copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance, bool p_alpha_to_zero, bool p_srgb, RID p_secondary, bool p_multiview) { +void CopyEffects::copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance, bool p_alpha_to_zero, bool p_srgb, RID p_secondary, bool p_multiview, bool p_alpha_to_one, bool p_linear) { UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); ERR_FAIL_NULL(uniform_set_cache); MaterialStorage *material_storage = MaterialStorage::get_singleton(); ERR_FAIL_NULL(material_storage); memset(©_to_fb.push_constant, 0, sizeof(CopyToFbPushConstant)); + copy_to_fb.push_constant.luminance_multiplier = 1.0; if (p_flip_y) { - copy_to_fb.push_constant.flip_y = true; + copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_FLIP_Y; } if (p_force_luminance) { - copy_to_fb.push_constant.force_luminance = true; + copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_FORCE_LUMINANCE; } if (p_alpha_to_zero) { - copy_to_fb.push_constant.alpha_to_zero = true; + copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_ALPHA_TO_ZERO; } if (p_srgb) { - copy_to_fb.push_constant.srgb = true; + copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_SRGB; + } + if (p_alpha_to_one) { + copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_ALPHA_TO_ONE; + } + if (p_linear) { + // Used for copying to a linear buffer. In the mobile renderer we divide the contents of the linear buffer + // to allow for a wider effective range. + copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_LINEAR; + copy_to_fb.push_constant.luminance_multiplier = prefer_raster_effects ? 2.0 : 1.0; } // setup our uniforms @@ -608,15 +622,13 @@ void CopyEffects::copy_raster(RID p_source_texture, RID p_dest_framebuffer) { RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[BLUR_MODE_COPY].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_texture), 0); RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array()); - - memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant)); RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant)); RD::get_singleton()->draw_list_draw(draw_list, true); RD::get_singleton()->draw_list_end(); } -void CopyEffects::gaussian_blur(RID p_source_rd_texture, RID p_texture, const Rect2i &p_region, bool p_8bit_dst) { +void CopyEffects::gaussian_blur(RID p_source_rd_texture, RID p_texture, const Rect2i &p_region, const Size2i &p_size, bool p_8bit_dst) { ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the gaussian blur with the mobile renderer."); UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); @@ -628,8 +640,10 @@ void CopyEffects::gaussian_blur(RID p_source_rd_texture, RID p_texture, const Re copy.push_constant.section[0] = p_region.position.x; copy.push_constant.section[1] = p_region.position.y; - copy.push_constant.section[2] = p_region.size.width; - copy.push_constant.section[3] = p_region.size.height; + copy.push_constant.target[0] = p_region.position.x; + copy.push_constant.target[1] = p_region.position.y; + copy.push_constant.section[2] = p_size.width; + copy.push_constant.section[3] = p_size.height; // setup our uniforms RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); @@ -641,7 +655,6 @@ void CopyEffects::gaussian_blur(RID p_source_rd_texture, RID p_texture, const Re RID shader = copy.shader.version_get_shader(copy.shader_version, mode); ERR_FAIL_COND(shader.is_null()); - //HORIZONTAL RD::DrawListID compute_list = RD::get_singleton()->compute_list_begin(); RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode]); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0); @@ -654,7 +667,44 @@ void CopyEffects::gaussian_blur(RID p_source_rd_texture, RID p_texture, const Re RD::get_singleton()->compute_list_end(); } -void CopyEffects::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_scale) { +void CopyEffects::gaussian_blur_raster(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_region, const Size2i &p_size) { + ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of the gaussian blur with the clustered renderer."); + + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + RID dest_framebuffer = FramebufferCacheRD::get_singleton()->get_cache(p_dest_texture); + + memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant)); + + BlurRasterMode blur_mode = BLUR_MODE_GAUSSIAN_BLUR; + + blur_raster.push_constant.pixel_size[0] = 1.0 / float(p_size.x); + blur_raster.push_constant.pixel_size[1] = 1.0 / float(p_size.y); + + // setup our uniforms + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture })); + + RID shader = blur_raster.shader.version_get_shader(blur_raster.shader_version, blur_mode); + ERR_FAIL_COND(shader.is_null()); + + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(dest_framebuffer))); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0); + + RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array()); + + RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant)); + + RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_list_end(); +} + +void CopyEffects::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_scale) { ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the gaussian glow with the mobile renderer."); UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); @@ -698,14 +748,14 @@ void CopyEffects::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, con RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_auto_exposure), 1); } - copy.push_constant.flags = base_flags | (p_first_pass ? COPY_FLAG_GLOW_FIRST_PASS : 0) | (p_high_quality ? COPY_FLAG_HIGH_QUALITY_GLOW : 0); + copy.push_constant.flags = base_flags | (p_first_pass ? COPY_FLAG_GLOW_FIRST_PASS : 0); RD::get_singleton()->compute_list_set_push_constant(compute_list, ©.push_constant, sizeof(CopyPushConstant)); RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_size.width, p_size.height, 1); RD::get_singleton()->compute_list_end(); } -void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, RID p_half_texture, RID p_dest_texture, float p_luminance_multiplier, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_scale) { +void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, RID p_half_texture, RID p_dest_texture, float p_luminance_multiplier, const Size2i &p_size, float p_strength, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_scale) { ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of the gaussian glow with the clustered renderer."); UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); @@ -882,6 +932,36 @@ void CopyEffects::set_color(RID p_dest_texture, const Color &p_color, const Rect RD::get_singleton()->compute_list_end(); } +void CopyEffects::set_color_raster(RID p_dest_texture, const Color &p_color, const Rect2i &p_region) { + ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of the set_color shader with the clustered renderer."); + + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + memset(©_to_fb.push_constant, 0, sizeof(CopyToFbPushConstant)); + + copy_to_fb.push_constant.set_color[0] = p_color.r; + copy_to_fb.push_constant.set_color[1] = p_color.g; + copy_to_fb.push_constant.set_color[2] = p_color.b; + copy_to_fb.push_constant.set_color[3] = p_color.a; + + RID dest_framebuffer = FramebufferCacheRD::get_singleton()->get_cache(p_dest_texture); + + CopyToFBMode mode = COPY_TO_FB_SET_COLOR; + + RID shader = copy_to_fb.shader.version_get_shader(copy_to_fb.shader_version, mode); + ERR_FAIL_COND(shader.is_null()); + + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, p_region); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy_to_fb.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(dest_framebuffer))); + RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array()); + RD::get_singleton()->draw_list_set_push_constant(draw_list, ©_to_fb.push_constant, sizeof(CopyToFbPushConstant)); + RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_list_end(); +} + void CopyEffects::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuffer, const Rect2 &p_rect, const Vector2 &p_dst_size, float p_z_near, float p_z_far, bool p_dp_flip) { UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); ERR_FAIL_NULL(uniform_set_cache); @@ -1075,7 +1155,8 @@ void CopyEffects::cubemap_roughness(RID p_source_rd_texture, RID p_dest_texture, memset(&roughness.push_constant, 0, sizeof(CubemapRoughnessPushConstant)); roughness.push_constant.face_id = p_face_id > 9 ? 0 : p_face_id; - roughness.push_constant.roughness = p_roughness * p_roughness; // Shader expects roughness, not perceptual roughness, so multiply before passing in. + // Remap to perceptual-roughness^2 to create more detail in lower mips and match the mapping of cubemap_filter. + roughness.push_constant.roughness = p_roughness * p_roughness; roughness.push_constant.sample_count = p_sample_count; roughness.push_constant.use_direct_write = p_roughness == 0.0; roughness.push_constant.face_size = p_size; @@ -1122,8 +1203,8 @@ void CopyEffects::cubemap_roughness_raster(RID p_source_rd_texture, RID p_dest_f roughness.push_constant.use_direct_write = p_roughness == 0.0; roughness.push_constant.face_size = p_size; - // setup our uniforms - RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + // Setup our uniforms. + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture })); diff --git a/servers/rendering/renderer_rd/effects/copy_effects.h b/servers/rendering/renderer_rd/effects/copy_effects.h index 0ddb60ebef..a0904f0b8e 100644 --- a/servers/rendering/renderer_rd/effects/copy_effects.h +++ b/servers/rendering/renderer_rd/effects/copy_effects.h @@ -63,6 +63,8 @@ private: BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE, BLUR_MODE_COPY, + BLUR_MODE_SET_COLOR, + BLUR_MODE_MAX }; @@ -130,8 +132,7 @@ private: COPY_FLAG_FLIP_Y = (1 << 5), COPY_FLAG_FORCE_LUMINANCE = (1 << 6), COPY_FLAG_ALL_SOURCE = (1 << 7), - COPY_FLAG_HIGH_QUALITY_GLOW = (1 << 8), - COPY_FLAG_ALPHA_TO_ONE = (1 << 9), + COPY_FLAG_ALPHA_TO_ONE = (1 << 8), }; struct CopyPushConstant { @@ -174,19 +175,28 @@ private: COPY_TO_FB_MULTIVIEW, COPY_TO_FB_MULTIVIEW_WITH_DEPTH, + + COPY_TO_FB_SET_COLOR, COPY_TO_FB_MAX, }; + enum CopyToFBFlags { + COPY_TO_FB_FLAG_FLIP_Y = (1 << 0), + COPY_TO_FB_FLAG_USE_SECTION = (1 << 1), + COPY_TO_FB_FLAG_FORCE_LUMINANCE = (1 << 2), + COPY_TO_FB_FLAG_ALPHA_TO_ZERO = (1 << 3), + COPY_TO_FB_FLAG_SRGB = (1 << 4), + COPY_TO_FB_FLAG_ALPHA_TO_ONE = (1 << 5), + COPY_TO_FB_FLAG_LINEAR = (1 << 6), + }; + struct CopyToFbPushConstant { float section[4]; float pixel_size[2]; - uint32_t flip_y; - uint32_t use_section; + float luminance_multiplier; + uint32_t flags; - uint32_t force_luminance; - uint32_t alpha_to_zero; - uint32_t srgb; - uint32_t pad; + float set_color[4]; }; struct CopyToFb { @@ -316,18 +326,20 @@ public: void copy_cubemap_to_panorama(RID p_source_cube, RID p_dest_panorama, const Size2i &p_panorama_size, float p_lod, bool p_is_array); void copy_depth_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false); void copy_depth_to_rect_and_linearize(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, float p_z_near, float p_z_far); - void copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_alpha_to_zero = false, bool p_srgb = false, RID p_secondary = RID(), bool p_multiview = false); + void copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_alpha_to_zero = false, bool p_srgb = false, RID p_secondary = RID(), bool p_multiview = false, bool alpha_to_one = false, bool p_linear = false); void copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_uv_rect, RD::DrawListID p_draw_list, bool p_flip_y = false, bool p_panorama = false); void copy_raster(RID p_source_texture, RID p_dest_framebuffer); - void gaussian_blur(RID p_source_rd_texture, RID p_texture, const Rect2i &p_region, bool p_8bit_dst = false); - void gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_scale = 1.0); - void gaussian_glow_raster(RID p_source_rd_texture, RID p_half_texture, RID p_dest_texture, float p_luminance_multiplier, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_scale = 1.0); + void gaussian_blur(RID p_source_rd_texture, RID p_texture, const Rect2i &p_region, const Size2i &p_size, bool p_8bit_dst = false); + void gaussian_blur_raster(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_region, const Size2i &p_size); + void gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength = 1.0, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_scale = 1.0); + void gaussian_glow_raster(RID p_source_rd_texture, RID p_half_texture, RID p_dest_texture, float p_luminance_multiplier, const Size2i &p_size, float p_strength = 1.0, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_scale = 1.0); void make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size); void make_mipmap_raster(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size); void set_color(RID p_dest_texture, const Color &p_color, const Rect2i &p_region, bool p_8bit_dst = false); + void set_color_raster(RID p_dest_texture, const Color &p_color, const Rect2i &p_region); void copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuffer, const Rect2 &p_rect, const Vector2 &p_dst_size, float p_z_near, float p_z_far, bool p_dp_flip); void cubemap_downsample(RID p_source_cubemap, RID p_dest_cubemap, const Size2i &p_size); diff --git a/servers/rendering/renderer_rd/effects/resolve.h b/servers/rendering/renderer_rd/effects/resolve.h index 2a4cd06827..49fba921d5 100644 --- a/servers/rendering/renderer_rd/effects/resolve.h +++ b/servers/rendering/renderer_rd/effects/resolve.h @@ -65,8 +65,8 @@ public: Resolve(); ~Resolve(); - void resolve_gi(RID p_source_depth, RID p_source_normal_roughness, RID p_source_voxel_gi, RID p_dest_depth, RID p_dest_normal_roughness, RID p_dest_voxel_gi, Vector2i p_screen_size, int p_samples, uint32_t p_barrier = RD::BARRIER_MASK_ALL); - void resolve_depth(RID p_source_depth, RID p_dest_depth, Vector2i p_screen_size, int p_samples, uint32_t p_barrier = RD::BARRIER_MASK_ALL); + void resolve_gi(RID p_source_depth, RID p_source_normal_roughness, RID p_source_voxel_gi, RID p_dest_depth, RID p_dest_normal_roughness, RID p_dest_voxel_gi, Vector2i p_screen_size, int p_samples, uint32_t p_barrier = RD::BARRIER_MASK_ALL_BARRIERS); + void resolve_depth(RID p_source_depth, RID p_dest_depth, Vector2i p_screen_size, int p_samples, uint32_t p_barrier = RD::BARRIER_MASK_ALL_BARRIERS); }; } // namespace RendererRD diff --git a/servers/rendering/renderer_rd/effects/ss_effects.cpp b/servers/rendering/renderer_rd/effects/ss_effects.cpp index 9653382e96..8e43869b4d 100644 --- a/servers/rendering/renderer_rd/effects/ss_effects.cpp +++ b/servers/rendering/renderer_rd/effects/ss_effects.cpp @@ -1332,7 +1332,6 @@ void SSEffects::generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_bu for (int pass = 0; pass < blur_passes; pass++) { int blur_pipeline = SSAO_BLUR_PASS; if (ssao_quality > RS::ENV_SSAO_QUALITY_VERY_LOW) { - blur_pipeline = SSAO_BLUR_PASS_SMART; if (pass < blur_passes - 2) { blur_pipeline = SSAO_BLUR_PASS_WIDE; } else { diff --git a/servers/rendering/renderer_rd/effects/ss_effects.h b/servers/rendering/renderer_rd/effects/ss_effects.h index dfaf3881bb..a04dfc4a74 100644 --- a/servers/rendering/renderer_rd/effects/ss_effects.h +++ b/servers/rendering/renderer_rd/effects/ss_effects.h @@ -100,7 +100,7 @@ public: float sharpness = 0.98; float normal_rejection = 1.0; - Size2i full_screen_size = Size2i(); + Size2i full_screen_size; }; void ssil_allocate_buffers(SSILRenderBuffers &p_ssil_buffers, const SSILSettings &p_settings, RID p_linear_depth); @@ -137,7 +137,7 @@ public: float horizon = 0.06; float sharpness = 0.98; - Size2i full_screen_size = Size2i(); + Size2i full_screen_size; }; void ssao_allocate_buffers(SSAORenderBuffers &p_ssao_buffers, const SSAOSettings &p_settings, RID p_linear_depth); diff --git a/servers/rendering/renderer_rd/effects/vrs.cpp b/servers/rendering/renderer_rd/effects/vrs.cpp index 5ff00aa94c..701d53b41d 100644 --- a/servers/rendering/renderer_rd/effects/vrs.cpp +++ b/servers/rendering/renderer_rd/effects/vrs.cpp @@ -92,18 +92,15 @@ void VRS::copy_vrs(RID p_source_rd_texture, RID p_dest_framebuffer, bool p_multi } Size2i VRS::get_vrs_texture_size(const Size2i p_base_size) const { - // TODO we should find some way to store this properly, we're assuming 16x16 as this seems to be the standard but in our vrs_capacities we - // obtain a minimum and maximum size, and we should choose something within this range and then make sure that is consistently set when creating - // our frame buffer. Also it is important that we make the resulting size we calculate down below available to the end user so they know the size - // of the VRS buffer to supply. - Size2i texel_size = Size2i(16, 16); - - int width = p_base_size.x / texel_size.x; - if (p_base_size.x % texel_size.x != 0) { + int32_t texel_width = RD::get_singleton()->limit_get(RD::LIMIT_VRS_TEXEL_WIDTH); + int32_t texel_height = RD::get_singleton()->limit_get(RD::LIMIT_VRS_TEXEL_HEIGHT); + + int width = p_base_size.x / texel_width; + if (p_base_size.x % texel_width != 0) { width++; } - int height = p_base_size.y / texel_size.y; - if (p_base_size.y % texel_size.y != 0) { + int height = p_base_size.y / texel_height; + if (p_base_size.y % texel_height != 0) { height++; } return Size2i(width, height); diff --git a/servers/rendering/renderer_rd/environment/fog.cpp b/servers/rendering/renderer_rd/environment/fog.cpp index 74082906c4..38066b6613 100644 --- a/servers/rendering/renderer_rd/environment/fog.cpp +++ b/servers/rendering/renderer_rd/environment/fog.cpp @@ -319,10 +319,6 @@ void Fog::free_fog_shader() { material_storage->material_free(volumetric_fog.default_material); } -void Fog::FogShaderData::set_path_hint(const String &p_path) { - path = p_path; -} - void Fog::FogShaderData::set_code(const String &p_code) { //compile @@ -366,83 +362,6 @@ void Fog::FogShaderData::set_code(const String &p_code) { valid = true; } -void Fog::FogShaderData::set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index) { - if (!p_texture.is_valid()) { - if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) { - default_texture_params[p_name].erase(p_index); - - if (default_texture_params[p_name].is_empty()) { - default_texture_params.erase(p_name); - } - } - } else { - if (!default_texture_params.has(p_name)) { - default_texture_params[p_name] = HashMap<int, RID>(); - } - default_texture_params[p_name][p_index] = p_texture; - } -} - -void Fog::FogShaderData::get_shader_uniform_list(List<PropertyInfo> *p_param_list) const { - RBMap<int, StringName> order; - - for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { - if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { - continue; - } - - if (E.value.texture_order >= 0) { - order[E.value.texture_order + 100000] = E.key; - } else { - order[E.value.order] = E.key; - } - } - - String last_group; - for (const KeyValue<int, StringName> &E : order) { - String group = uniforms[E.value].group; - if (!uniforms[E.value].subgroup.is_empty()) { - group += "::" + uniforms[E.value].subgroup; - } - - if (group != last_group) { - PropertyInfo pi; - pi.usage = PROPERTY_USAGE_GROUP; - pi.name = group; - p_param_list->push_back(pi); - - last_group = group; - } - - PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]); - pi.name = E.value; - p_param_list->push_back(pi); - } -} - -void Fog::FogShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const { - for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { - if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { - continue; - } - - RendererMaterialStorage::InstanceShaderParam p; - p.info = ShaderLanguage::uniform_to_property_info(E.value); - p.info.name = E.key; //supply name - p.index = E.value.instance_index; - p.default_value = ShaderLanguage::constant_value_to_variant(E.value.default_value, E.value.type, E.value.array_size, E.value.hint); - p_param_list->push_back(p); - } -} - -bool Fog::FogShaderData::is_parameter_texture(const StringName &p_param) const { - if (!uniforms.has(p_param)) { - return false; - } - - return uniforms[p_param].texture_order >= 0; -} - bool Fog::FogShaderData::is_animated() const { return false; } @@ -451,15 +370,6 @@ bool Fog::FogShaderData::casts_shadows() const { return false; } -Variant Fog::FogShaderData::get_default_parameter(const StringName &p_parameter) const { - if (uniforms.has(p_parameter)) { - ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter]; - Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value; - return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.array_size, uniform.hint); - } - return Variant(); -} - RS::ShaderNativeSourceCode Fog::FogShaderData::get_native_source_code() const { Fog *fog_singleton = Fog::get_singleton(); @@ -727,9 +637,9 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P any_uses_time |= shader_data->uses_time; - Vector3i min = Vector3i(); - Vector3i max = Vector3i(); - Vector3i kernel_size = Vector3i(); + Vector3i min; + Vector3i max; + Vector3i kernel_size; Vector3 position = fog_volume_instance->transform.get_origin(); RS::FogVolumeShape volume_type = RendererRD::Fog::get_singleton()->fog_volume_get_shape(fog_volume); @@ -789,6 +699,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P RD::get_singleton()->compute_list_bind_uniform_set(compute_list, volumetric_fog.base_uniform_set, VolumetricFogShader::FogSet::FOG_SET_BASE); if (material->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(material->uniform_set)) { // Material may not have a uniform set. RD::get_singleton()->compute_list_bind_uniform_set(compute_list, material->uniform_set, VolumetricFogShader::FogSet::FOG_SET_MATERIAL); + material->set_as_used(); } RD::get_singleton()->compute_list_dispatch_threads(compute_list, kernel_size.x, kernel_size.y, kernel_size.z); diff --git a/servers/rendering/renderer_rd/environment/fog.h b/servers/rendering/renderer_rd/environment/fog.h index 0ade995758..a5f06a129d 100644 --- a/servers/rendering/renderer_rd/environment/fog.h +++ b/servers/rendering/renderer_rd/environment/fog.h @@ -188,27 +188,18 @@ private: RID version; RID pipeline; - HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms; Vector<uint32_t> ubo_offsets; uint32_t ubo_size = 0; - String path; String code; - HashMap<StringName, HashMap<int, RID>> default_texture_params; bool uses_time = false; - virtual void set_path_hint(const String &p_hint); virtual void set_code(const String &p_Code); - virtual void set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index); - virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const; - virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; - virtual bool is_parameter_texture(const StringName &p_param) const; virtual bool is_animated() const; virtual bool casts_shadows() const; - virtual Variant get_default_parameter(const StringName &p_parameter) const; virtual RS::ShaderNativeSourceCode get_native_source_code() const; FogShaderData() {} diff --git a/servers/rendering/renderer_rd/environment/gi.cpp b/servers/rendering/renderer_rd/environment/gi.cpp index 550fe27e4c..61b7dd4504 100644 --- a/servers/rendering/renderer_rd/environment/gi.cpp +++ b/servers/rendering/renderer_rd/environment/gi.cpp @@ -3496,6 +3496,10 @@ void GI::init(SkyRD *p_sky) { { //calculate tables String defines = "\n#define SDFGI_OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n"; + if (RendererSceneRenderRD::get_singleton()->is_vrs_supported()) { + defines += "\n#define USE_VRS\n"; + } + Vector<String> gi_modes; gi_modes.push_back("\n#define USE_VOXEL_GI_INSTANCES\n"); // MODE_VOXEL_GI @@ -4011,7 +4015,7 @@ void GI::process_gi(Ref<RenderSceneBuffersRD> p_render_buffers, const RID *p_nor u.append_id(rbgi->scene_data_ubo); uniforms.push_back(u); } - { + if (RendererSceneRenderRD::get_singleton()->is_vrs_supported()) { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 19; diff --git a/servers/rendering/renderer_rd/environment/sky.cpp b/servers/rendering/renderer_rd/environment/sky.cpp index 0acd48c22a..19546968cd 100644 --- a/servers/rendering/renderer_rd/environment/sky.cpp +++ b/servers/rendering/renderer_rd/environment/sky.cpp @@ -32,23 +32,25 @@ #include "core/config/project_settings.h" #include "core/math/math_defs.h" #include "servers/rendering/renderer_rd/effects/copy_effects.h" +#include "servers/rendering/renderer_rd/framebuffer_cache_rd.h" #include "servers/rendering/renderer_rd/renderer_compositor_rd.h" #include "servers/rendering/renderer_rd/renderer_scene_render_rd.h" #include "servers/rendering/renderer_rd/storage_rd/material_storage.h" #include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h" #include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" +#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h" #include "servers/rendering/rendering_server_default.h" #include "servers/rendering/rendering_server_globals.h" using namespace RendererRD; +#define RB_SCOPE_SKY SNAME("sky_buffers") +#define RB_HALF_TEXTURE SNAME("half_texture") +#define RB_QUARTER_TEXTURE SNAME("quarter_texture") + //////////////////////////////////////////////////////////////////////////////// // SKY SHADER -void SkyRD::SkyShaderData::set_path_hint(const String &p_path) { - path = p_path; -} - void SkyRD::SkyShaderData::set_code(const String &p_code) { //compile @@ -152,82 +154,6 @@ void SkyRD::SkyShaderData::set_code(const String &p_code) { valid = true; } -void SkyRD::SkyShaderData::set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index) { - if (!p_texture.is_valid()) { - if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) { - default_texture_params[p_name].erase(p_index); - - if (default_texture_params[p_name].is_empty()) { - default_texture_params.erase(p_name); - } - } - } else { - if (!default_texture_params.has(p_name)) { - default_texture_params[p_name] = HashMap<int, RID>(); - } - default_texture_params[p_name][p_index] = p_texture; - } -} - -void SkyRD::SkyShaderData::get_shader_uniform_list(List<PropertyInfo> *p_param_list) const { - HashMap<int, StringName> order; - - for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { - if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { - continue; - } - - if (E.value.texture_order >= 0) { - order[E.value.texture_order + 100000] = E.key; - } else { - order[E.value.order] = E.key; - } - } - String last_group; - for (const KeyValue<int, StringName> &E : order) { - String group = uniforms[E.value].group; - if (!uniforms[E.value].subgroup.is_empty()) { - group += "::" + uniforms[E.value].subgroup; - } - - if (group != last_group) { - PropertyInfo pi; - pi.usage = PROPERTY_USAGE_GROUP; - pi.name = group; - p_param_list->push_back(pi); - - last_group = group; - } - - PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]); - pi.name = E.value; - p_param_list->push_back(pi); - } -} - -void SkyRD::SkyShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const { - for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { - if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { - continue; - } - - RendererMaterialStorage::InstanceShaderParam p; - p.info = ShaderLanguage::uniform_to_property_info(E.value); - p.info.name = E.key; //supply name - p.index = E.value.instance_index; - p.default_value = ShaderLanguage::constant_value_to_variant(E.value.default_value, E.value.type, E.value.array_size, E.value.hint); - p_param_list->push_back(p); - } -} - -bool SkyRD::SkyShaderData::is_parameter_texture(const StringName &p_param) const { - if (!uniforms.has(p_param)) { - return false; - } - - return uniforms[p_param].texture_order >= 0; -} - bool SkyRD::SkyShaderData::is_animated() const { return false; } @@ -236,15 +162,6 @@ bool SkyRD::SkyShaderData::casts_shadows() const { return false; } -Variant SkyRD::SkyShaderData::get_default_parameter(const StringName &p_parameter) const { - if (uniforms.has(p_parameter)) { - ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter]; - Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value; - return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.array_size, uniform.hint); - } - return Variant(); -} - RS::ShaderNativeSourceCode SkyRD::SkyShaderData::get_native_source_code() const { RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton); @@ -293,18 +210,17 @@ static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_basis, float *p_ar p_array[11] = 0; } -void SkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const Projection *p_projections, const Basis &p_orientation, const Vector3 &p_position, float p_luminance_multiplier) { +void SkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, const Projection &p_projection, const Basis &p_orientation, const Vector3 &p_position, float p_luminance_multiplier) { SkyPushConstant sky_push_constant; memset(&sky_push_constant, 0, sizeof(SkyPushConstant)); - for (uint32_t v = 0; v < p_view_count; v++) { - // We only need key components of our projection matrix - sky_push_constant.projections[v][0] = p_projections[v].columns[2][0]; - sky_push_constant.projections[v][1] = p_projections[v].columns[0][0]; - sky_push_constant.projections[v][2] = p_projections[v].columns[2][1]; - sky_push_constant.projections[v][3] = p_projections[v].columns[1][1]; - } + // We only need key components of our projection matrix + sky_push_constant.projection[0] = p_projection.columns[2][0]; + sky_push_constant.projection[1] = p_projection.columns[0][0]; + sky_push_constant.projection[2] = p_projection.columns[2][1]; + sky_push_constant.projection[3] = p_projection.columns[1][1]; + sky_push_constant.position[0] = p_position.x; sky_push_constant.position[1] = p_position.y; sky_push_constant.position[2] = p_position.z; @@ -629,28 +545,15 @@ void SkyRD::Sky::free() { uniform_buffer = RID(); } - if (half_res_pass.is_valid()) { - RD::get_singleton()->free(half_res_pass); - half_res_pass = RID(); - } - - if (quarter_res_pass.is_valid()) { - RD::get_singleton()->free(quarter_res_pass); - quarter_res_pass = RID(); - } - if (material.is_valid()) { RSG::material_storage->material_free(material); material = RID(); } } -RID SkyRD::Sky::get_textures(SkyTextureSetVersion p_version, RID p_default_shader_rd) { +RID SkyRD::Sky::get_textures(SkyTextureSetVersion p_version, RID p_default_shader_rd, Ref<RenderSceneBuffersRD> p_render_buffers) { RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); - if (texture_uniform_sets[p_version].is_valid() && RD::get_singleton()->uniform_set_is_valid(texture_uniform_sets[p_version])) { - return texture_uniform_sets[p_version]; - } Vector<RD::Uniform> uniforms; { RD::Uniform u; @@ -667,17 +570,18 @@ RID SkyRD::Sky::get_textures(SkyTextureSetVersion p_version, RID p_default_shade RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 1; // half res - if (half_res_pass.is_valid() && p_version != SKY_TEXTURE_SET_HALF_RES && p_version != SKY_TEXTURE_SET_CUBEMAP_HALF_RES) { - if (p_version >= SKY_TEXTURE_SET_CUBEMAP) { + if (p_version >= SKY_TEXTURE_SET_CUBEMAP) { + if (reflection.layers[0].views[1].is_valid() && p_version != SKY_TEXTURE_SET_CUBEMAP_HALF_RES) { u.append_id(reflection.layers[0].views[1]); } else { - u.append_id(half_res_pass); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); } } else { - if (p_version < SKY_TEXTURE_SET_CUBEMAP) { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE)); + RID half_texture = p_render_buffers->has_texture(RB_SCOPE_SKY, RB_HALF_TEXTURE) ? p_render_buffers->get_texture(RB_SCOPE_SKY, RB_HALF_TEXTURE) : RID(); + if (half_texture.is_valid() && p_version != SKY_TEXTURE_SET_HALF_RES) { + u.append_id(half_texture); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE)); } } uniforms.push_back(u); @@ -686,24 +590,24 @@ RID SkyRD::Sky::get_textures(SkyTextureSetVersion p_version, RID p_default_shade RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 2; // quarter res - if (quarter_res_pass.is_valid() && p_version != SKY_TEXTURE_SET_QUARTER_RES && p_version != SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES) { - if (p_version >= SKY_TEXTURE_SET_CUBEMAP) { + if (p_version >= SKY_TEXTURE_SET_CUBEMAP) { + if (reflection.layers[0].views[2].is_valid() && p_version != SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES) { u.append_id(reflection.layers[0].views[2]); } else { - u.append_id(quarter_res_pass); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); } } else { - if (p_version < SKY_TEXTURE_SET_CUBEMAP) { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE)); + RID quarter_texture = p_render_buffers->has_texture(RB_SCOPE_SKY, RB_QUARTER_TEXTURE) ? p_render_buffers->get_texture(RB_SCOPE_SKY, RB_QUARTER_TEXTURE) : RID(); + if (quarter_texture.is_valid() && p_version != SKY_TEXTURE_SET_QUARTER_RES) { + u.append_id(quarter_texture); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE)); } } uniforms.push_back(u); } - texture_uniform_sets[p_version] = RD::get_singleton()->uniform_set_create(uniforms, p_default_shader_rd, SKY_SET_TEXTURES); - return texture_uniform_sets[p_version]; + return UniformSetCacheRD::get_singleton()->get_cache_vec(p_default_shader_rd, SKY_SET_TEXTURES, uniforms); } bool SkyRD::Sky::set_radiance_size(int p_radiance_size) { @@ -1109,11 +1013,17 @@ SkyRD::~SkyRD() { RD::get_singleton()->free(index_buffer); //array gets freed as dependency } -void SkyRD::setup(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, const PagedArray<RID> &p_lights, RID p_camera_attributes, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render) { +void SkyRD::setup_sky(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, const PagedArray<RID> &p_lights, RID p_camera_attributes, uint32_t p_view_count, const Projection *p_view_projections, const Vector3 *p_view_eye_offsets, const Transform3D &p_cam_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render) { RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); ERR_FAIL_COND(p_env.is_null()); + ERR_FAIL_COND(p_render_buffers.is_null()); + + // make sure we support our view count + ERR_FAIL_COND(p_view_count == 0); + ERR_FAIL_COND(p_view_count > RendererSceneRender::MAX_RENDER_VIEWS); + SkyMaterialData *material = nullptr; Sky *sky = get_sky(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env)); @@ -1142,31 +1052,14 @@ void SkyRD::setup(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, const P ERR_FAIL_COND(!shader_data); - // Invalidate supbass buffers if screen size changes - if (sky->screen_size != p_screen_size) { - sky->screen_size = p_screen_size; - sky->screen_size.x = sky->screen_size.x < 4 ? 4 : sky->screen_size.x; - sky->screen_size.y = sky->screen_size.y < 4 ? 4 : sky->screen_size.y; - if (shader_data->uses_half_res) { - if (sky->half_res_pass.is_valid()) { - RD::get_singleton()->free(sky->half_res_pass); - sky->half_res_pass = RID(); - } - invalidate_sky(sky); - } - if (shader_data->uses_quarter_res) { - if (sky->quarter_res_pass.is_valid()) { - RD::get_singleton()->free(sky->quarter_res_pass); - sky->quarter_res_pass = RID(); - } - invalidate_sky(sky); - } - } + material->set_as_used(); + + // Save our screen size, our buffers will already have been cleared + sky->screen_size.x = p_screen_size.x < 4 ? 4 : p_screen_size.x; + sky->screen_size.y = p_screen_size.y < 4 ? 4 : p_screen_size.y; - // Create new subpass buffers if necessary - if ((shader_data->uses_half_res && sky->half_res_pass.is_null()) || - (shader_data->uses_quarter_res && sky->quarter_res_pass.is_null()) || - sky->radiance.is_null()) { + // Trigger updating radiance buffers + if (sky->radiance.is_null()) { invalidate_sky(sky); update_dirty_skys(); } @@ -1187,8 +1080,8 @@ void SkyRD::setup(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, const P sky->reflection.dirty = true; } - if (!p_transform.origin.is_equal_approx(sky->prev_position) && shader_data->uses_position) { - sky->prev_position = p_transform.origin; + if (!p_cam_transform.origin.is_equal_approx(sky->prev_position) && shader_data->uses_position) { + sky->prev_position = p_cam_transform.origin; sky->reflection.dirty = true; } @@ -1316,7 +1209,20 @@ void SkyRD::setup(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, const P } } - sky_scene_state.ubo.z_far = p_projection.get_z_far(); + sky_scene_state.view_count = p_view_count; + sky_scene_state.cam_transform = p_cam_transform; + sky_scene_state.cam_projection = p_view_projections[0]; // We only use this when rendering a single view + + // Our info in our UBO is only used if we're rendering stereo + for (uint32_t i = 0; i < p_view_count; i++) { + RendererRD::MaterialStorage::store_camera(p_view_projections[i].inverse(), sky_scene_state.ubo.view_inv_projections[i]); + sky_scene_state.ubo.view_eye_offsets[i][0] = p_view_eye_offsets[i].x; + sky_scene_state.ubo.view_eye_offsets[i][1] = p_view_eye_offsets[i].y; + sky_scene_state.ubo.view_eye_offsets[i][2] = p_view_eye_offsets[i].z; + sky_scene_state.ubo.view_eye_offsets[i][3] = 0.0; + } + + sky_scene_state.ubo.z_far = p_view_projections[0].get_z_far(); // Should be the same for all projection sky_scene_state.ubo.fog_enabled = RendererSceneRenderRD::get_singleton()->environment_get_fog_enabled(p_env); sky_scene_state.ubo.fog_density = RendererSceneRenderRD::get_singleton()->environment_get_fog_density(p_env); sky_scene_state.ubo.fog_aerial_perspective = RendererSceneRenderRD::get_singleton()->environment_get_fog_aerial_perspective(p_env); @@ -1333,7 +1239,8 @@ void SkyRD::setup(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, const P RD::get_singleton()->buffer_update(sky_scene_state.uniform_buffer, 0, sizeof(SkySceneState::UBO), &sky_scene_state.ubo); } -void SkyRD::update(RID p_env, const Projection &p_projection, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) { +void SkyRD::update_radiance_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_env, const Vector3 &p_global_pos, double p_time, float p_luminance_multiplier) { + ERR_FAIL_COND(p_render_buffers.is_null()); RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); ERR_FAIL_COND(p_env.is_null()); @@ -1411,6 +1318,8 @@ void SkyRD::update(RID p_env, const Projection &p_projection, const Transform3D correction.set_depth_correction(true); cm = correction * cm; + // Note, we ignore environment_get_sky_orientation here as this is applied when we do our lookup in our scene shader. + if (shader_data->uses_quarter_res) { RD::get_singleton()->draw_command_begin_label("Render Sky to Quarter Res Cubemap"); PipelineCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_CUBEMAP_QUARTER_RES]; @@ -1421,10 +1330,10 @@ void SkyRD::update(RID p_env, const Projection &p_projection, const Transform3D for (int i = 0; i < 6; i++) { Basis local_view = Basis::looking_at(view_normals[i], view_up[i]); - RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES, sky_shader.default_shader_rd); + RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES, sky_shader.default_shader_rd, p_render_buffers); cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[2].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); - _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[2].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, p_transform.origin, p_luminance_multiplier); + _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[2].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, cm, local_view, p_global_pos, p_luminance_multiplier); RD::get_singleton()->draw_list_end(); } RD::get_singleton()->draw_command_end_label(); @@ -1440,10 +1349,10 @@ void SkyRD::update(RID p_env, const Projection &p_projection, const Transform3D for (int i = 0; i < 6; i++) { Basis local_view = Basis::looking_at(view_normals[i], view_up[i]); - RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_CUBEMAP_HALF_RES, sky_shader.default_shader_rd); + RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_CUBEMAP_HALF_RES, sky_shader.default_shader_rd, p_render_buffers); cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[1].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); - _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[1].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, p_transform.origin, p_luminance_multiplier); + _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[1].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, cm, local_view, p_global_pos, p_luminance_multiplier); RD::get_singleton()->draw_list_end(); } RD::get_singleton()->draw_command_end_label(); @@ -1455,10 +1364,10 @@ void SkyRD::update(RID p_env, const Projection &p_projection, const Transform3D RD::get_singleton()->draw_command_begin_label("Render Sky Cubemap"); for (int i = 0; i < 6; i++) { Basis local_view = Basis::looking_at(view_normals[i], view_up[i]); - RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_CUBEMAP, sky_shader.default_shader_rd); + RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_CUBEMAP, sky_shader.default_shader_rd, p_render_buffers); cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[0].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); - _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[0].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, p_transform.origin, p_luminance_multiplier); + _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[0].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, cm, local_view, p_global_pos, p_luminance_multiplier); RD::get_singleton()->draw_list_end(); } RD::get_singleton()->draw_command_end_label(); @@ -1500,13 +1409,11 @@ void SkyRD::update(RID p_env, const Projection &p_projection, const Transform3D } } -void SkyRD::draw(RID p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) { +void SkyRD::update_res_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_env, double p_time, float p_luminance_multiplier) { + ERR_FAIL_COND(p_render_buffers.is_null()); RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); ERR_FAIL_COND(p_env.is_null()); - ERR_FAIL_COND(p_view_count == 0); - ERR_FAIL_COND(p_view_count > RendererSceneRender::MAX_RENDER_VIEWS); - Sky *sky = get_sky(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env)); SkyMaterialData *material = nullptr; @@ -1539,105 +1446,16 @@ void SkyRD::draw(RID p_env, bool p_can_continue_color, bool p_can_continue_depth ERR_FAIL_COND(!material); SkyShaderData *shader_data = material->shader_data; - ERR_FAIL_COND(!shader_data); - Basis sky_transform = RendererSceneRenderRD::get_singleton()->environment_get_sky_orientation(p_env); - sky_transform.invert(); - - float custom_fov = RendererSceneRenderRD::get_singleton()->environment_get_sky_custom_fov(p_env); - - // Camera - Projection camera; - uint32_t view_count = p_view_count; - const Projection *projections = p_projections; - - if (custom_fov) { - // With custom fov we don't support stereo... - float near_plane = p_projections[0].get_z_near(); - float far_plane = p_projections[0].get_z_far(); - float aspect = p_projections[0].get_aspect(); - - camera.set_perspective(custom_fov, aspect, near_plane, far_plane); - - view_count = 1; - projections = &camera; - } - - sky_transform = sky_transform * p_transform.basis; - - if (shader_data->uses_quarter_res) { - PipelineCacheRD *pipeline = &shader_data->pipelines[view_count > 1 ? SKY_VERSION_QUARTER_RES_MULTIVIEW : SKY_VERSION_QUARTER_RES]; - - RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_QUARTER_RES, sky_shader.default_shader_rd); - - Vector<Color> clear_colors; - clear_colors.push_back(Color(0.0, 0.0, 0.0)); - - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->quarter_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors); - _render_sky(draw_list, p_time, sky->quarter_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, p_transform.origin, p_luminance_multiplier); - RD::get_singleton()->draw_list_end(); - } - - if (shader_data->uses_half_res) { - PipelineCacheRD *pipeline = &shader_data->pipelines[view_count > 1 ? SKY_VERSION_HALF_RES_MULTIVIEW : SKY_VERSION_HALF_RES]; - - RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_HALF_RES, sky_shader.default_shader_rd); - - Vector<Color> clear_colors; - clear_colors.push_back(Color(0.0, 0.0, 0.0)); - - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->half_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors); - _render_sky(draw_list, p_time, sky->half_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, p_transform.origin, p_luminance_multiplier); - RD::get_singleton()->draw_list_end(); - } - - PipelineCacheRD *pipeline = &shader_data->pipelines[view_count > 1 ? SKY_VERSION_BACKGROUND_MULTIVIEW : SKY_VERSION_BACKGROUND]; - - RID texture_uniform_set; - if (sky) { - texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_BACKGROUND, sky_shader.default_shader_rd); - } else { - texture_uniform_set = sky_scene_state.fog_only_texture_uniform_set; - } - - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_fb, RD::INITIAL_ACTION_CONTINUE, p_can_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, p_can_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ); - _render_sky(draw_list, p_time, p_fb, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, p_transform.origin, p_luminance_multiplier); - RD::get_singleton()->draw_list_end(); -} - -void SkyRD::update_res_buffers(RID p_env, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) { - RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); - ERR_FAIL_COND(p_env.is_null()); - - ERR_FAIL_COND(p_view_count == 0); - ERR_FAIL_COND(p_view_count > RendererSceneRender::MAX_RENDER_VIEWS); - - Sky *sky = get_sky(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env)); - ERR_FAIL_COND(!sky); - - SkyMaterialData *material = nullptr; - RID sky_material; - - sky_material = sky_get_material(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env)); - - if (sky_material.is_valid()) { - material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); - if (!material || !material->shader_data->valid) { - material = nullptr; - } - } - - if (!material) { - sky_material = sky_shader.default_material; - material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); + if (!shader_data->uses_quarter_res && !shader_data->uses_half_res) { + return; } - ERR_FAIL_COND(!material); + material->set_as_used(); - SkyShaderData *shader_data = material->shader_data; - - ERR_FAIL_COND(!shader_data); + RENDER_TIMESTAMP("Setup Sky Resolution Buffers"); + RD::get_singleton()->draw_command_begin_label("Setup Sky Resolution Buffers"); Basis sky_transform = RendererSceneRenderRD::get_singleton()->environment_get_sky_orientation(p_env); sky_transform.invert(); @@ -1645,58 +1463,65 @@ void SkyRD::update_res_buffers(RID p_env, uint32_t p_view_count, const Projectio float custom_fov = RendererSceneRenderRD::get_singleton()->environment_get_sky_custom_fov(p_env); // Camera - Projection camera; - uint32_t view_count = p_view_count; - const Projection *projections = p_projections; + Projection projection = sky_scene_state.cam_projection; - if (custom_fov) { + if (custom_fov && sky_scene_state.view_count == 1) { // With custom fov we don't support stereo... - float near_plane = p_projections[0].get_z_near(); - float far_plane = p_projections[0].get_z_far(); - float aspect = p_projections[0].get_aspect(); - - camera.set_perspective(custom_fov, aspect, near_plane, far_plane); + float near_plane = projection.get_z_near(); + float far_plane = projection.get_z_far(); + float aspect = projection.get_aspect(); - view_count = 1; - projections = &camera; + projection.set_perspective(custom_fov, aspect, near_plane, far_plane); } - sky_transform = p_transform.basis * sky_transform; + sky_transform = sky_transform * sky_scene_state.cam_transform.basis; if (shader_data->uses_quarter_res) { - PipelineCacheRD *pipeline = &shader_data->pipelines[view_count > 1 ? SKY_VERSION_QUARTER_RES_MULTIVIEW : SKY_VERSION_QUARTER_RES]; + PipelineCacheRD *pipeline = &shader_data->pipelines[sky_scene_state.view_count > 1 ? SKY_VERSION_QUARTER_RES_MULTIVIEW : SKY_VERSION_QUARTER_RES]; + + // Grab texture and framebuffer from cache, create if needed... + uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + Size2i quarter_size = sky->screen_size / 4; + RID texture = p_render_buffers->create_texture(RB_SCOPE_SKY, RB_QUARTER_TEXTURE, texture_format, usage_bits, RD::TEXTURE_SAMPLES_1, quarter_size); + RID framebuffer = FramebufferCacheRD::get_singleton()->get_cache_multiview(sky_scene_state.view_count, texture); - RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_QUARTER_RES, sky_shader.default_shader_rd); + RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_QUARTER_RES, sky_shader.default_shader_rd, p_render_buffers); Vector<Color> clear_colors; clear_colors.push_back(Color(0.0, 0.0, 0.0)); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->quarter_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors); - _render_sky(draw_list, p_time, sky->quarter_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, p_transform.origin, p_luminance_multiplier); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors); + _render_sky(draw_list, p_time, framebuffer, pipeline, material->uniform_set, texture_uniform_set, projection, sky_transform, sky_scene_state.cam_transform.origin, p_luminance_multiplier); RD::get_singleton()->draw_list_end(); } if (shader_data->uses_half_res) { - PipelineCacheRD *pipeline = &shader_data->pipelines[view_count > 1 ? SKY_VERSION_HALF_RES_MULTIVIEW : SKY_VERSION_HALF_RES]; + PipelineCacheRD *pipeline = &shader_data->pipelines[sky_scene_state.view_count > 1 ? SKY_VERSION_HALF_RES_MULTIVIEW : SKY_VERSION_HALF_RES]; - RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_HALF_RES, sky_shader.default_shader_rd); + // Grab texture and framebuffer from cache, create if needed... + uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + Size2i half_size = sky->screen_size / 2; + RID texture = p_render_buffers->create_texture(RB_SCOPE_SKY, RB_HALF_TEXTURE, texture_format, usage_bits, RD::TEXTURE_SAMPLES_1, half_size); + RID framebuffer = FramebufferCacheRD::get_singleton()->get_cache_multiview(sky_scene_state.view_count, texture); + + RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_HALF_RES, sky_shader.default_shader_rd, p_render_buffers); Vector<Color> clear_colors; clear_colors.push_back(Color(0.0, 0.0, 0.0)); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->half_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors); - _render_sky(draw_list, p_time, sky->half_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, p_transform.origin, p_luminance_multiplier); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors); + _render_sky(draw_list, p_time, framebuffer, pipeline, material->uniform_set, texture_uniform_set, projection, sky_transform, sky_scene_state.cam_transform.origin, p_luminance_multiplier); RD::get_singleton()->draw_list_end(); } + + RD::get_singleton()->draw_command_end_label(); // Setup Sky resolution buffers } -void SkyRD::draw(RD::DrawListID p_draw_list, RID p_env, RID p_fb, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) { +void SkyRD::draw_sky(RD::DrawListID p_draw_list, Ref<RenderSceneBuffersRD> p_render_buffers, RID p_env, RID p_fb, double p_time, float p_luminance_multiplier) { + ERR_FAIL_COND(p_render_buffers.is_null()); RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); ERR_FAIL_COND(p_env.is_null()); - ERR_FAIL_COND(p_view_count == 0); - ERR_FAIL_COND(p_view_count > RendererSceneRender::MAX_RENDER_VIEWS); - Sky *sky = get_sky(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env)); SkyMaterialData *material = nullptr; @@ -1729,43 +1554,39 @@ void SkyRD::draw(RD::DrawListID p_draw_list, RID p_env, RID p_fb, uint32_t p_vie ERR_FAIL_COND(!material); SkyShaderData *shader_data = material->shader_data; - ERR_FAIL_COND(!shader_data); + material->set_as_used(); + Basis sky_transform = RendererSceneRenderRD::get_singleton()->environment_get_sky_orientation(p_env); sky_transform.invert(); float custom_fov = RendererSceneRenderRD::get_singleton()->environment_get_sky_custom_fov(p_env); // Camera - Projection camera; - uint32_t view_count = p_view_count; - const Projection *projections = p_projections; + Projection projection = sky_scene_state.cam_projection; - if (custom_fov) { + if (custom_fov && sky_scene_state.view_count == 1) { // With custom fov we don't support stereo... - float near_plane = p_projections[0].get_z_near(); - float far_plane = p_projections[0].get_z_far(); - float aspect = p_projections[0].get_aspect(); + float near_plane = projection.get_z_near(); + float far_plane = projection.get_z_far(); + float aspect = projection.get_aspect(); - camera.set_perspective(custom_fov, aspect, near_plane, far_plane); - - view_count = 1; - projections = &camera; + projection.set_perspective(custom_fov, aspect, near_plane, far_plane); } - sky_transform = p_transform.basis * sky_transform; + sky_transform = sky_transform * sky_scene_state.cam_transform.basis; - PipelineCacheRD *pipeline = &shader_data->pipelines[view_count > 1 ? SKY_VERSION_BACKGROUND_MULTIVIEW : SKY_VERSION_BACKGROUND]; + PipelineCacheRD *pipeline = &shader_data->pipelines[sky_scene_state.view_count > 1 ? SKY_VERSION_BACKGROUND_MULTIVIEW : SKY_VERSION_BACKGROUND]; RID texture_uniform_set; if (sky) { - texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_BACKGROUND, sky_shader.default_shader_rd); + texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_BACKGROUND, sky_shader.default_shader_rd, p_render_buffers); } else { texture_uniform_set = sky_scene_state.fog_only_texture_uniform_set; } - _render_sky(p_draw_list, p_time, p_fb, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, p_transform.origin, p_luminance_multiplier); + _render_sky(p_draw_list, p_time, p_fb, pipeline, material->uniform_set, texture_uniform_set, projection, sky_transform, sky_scene_state.cam_transform.origin, p_luminance_multiplier); } void SkyRD::invalidate_sky(Sky *p_sky) { @@ -1780,9 +1601,11 @@ void SkyRD::update_dirty_skys() { Sky *sky = dirty_sky_list; while (sky) { - bool texture_set_dirty = false; //update sky configuration if texture is missing + // TODO See if we can move this into `update_radiance_buffers` and remove our dirty_sky logic. + // As this is basically a duplicate of the logic in reflection probes we could move this logic + // into RenderSceneBuffersRD and use that from both places. if (sky->radiance.is_null()) { int mipmaps = Image::get_image_required_mipmaps(sky->radiance_size, sky->radiance_size, Image::FORMAT_RGBAH) + 1; @@ -1825,47 +1648,6 @@ void SkyRD::update_dirty_skys() { sky->reflection.update_reflection_data(sky->radiance_size, MIN(mipmaps, layers), false, sky->radiance, 0, sky->mode == RS::SKY_MODE_REALTIME, roughness_layers, texture_format); } - texture_set_dirty = true; - } - - // Create subpass buffers if they haven't been created already - if (sky->half_res_pass.is_null() && !RD::get_singleton()->texture_is_valid(sky->half_res_pass) && sky->screen_size.x >= 4 && sky->screen_size.y >= 4) { - RD::TextureFormat tformat; - tformat.format = texture_format; - tformat.width = sky->screen_size.x / 2; - tformat.height = sky->screen_size.y / 2; - tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; - tformat.texture_type = RD::TEXTURE_TYPE_2D; - - sky->half_res_pass = RD::get_singleton()->texture_create(tformat, RD::TextureView()); - Vector<RID> texs; - texs.push_back(sky->half_res_pass); - sky->half_res_framebuffer = RD::get_singleton()->framebuffer_create(texs); - texture_set_dirty = true; - } - - if (sky->quarter_res_pass.is_null() && !RD::get_singleton()->texture_is_valid(sky->quarter_res_pass) && sky->screen_size.x >= 4 && sky->screen_size.y >= 4) { - RD::TextureFormat tformat; - tformat.format = texture_format; - tformat.width = sky->screen_size.x / 4; - tformat.height = sky->screen_size.y / 4; - tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; - tformat.texture_type = RD::TEXTURE_TYPE_2D; - - sky->quarter_res_pass = RD::get_singleton()->texture_create(tformat, RD::TextureView()); - Vector<RID> texs; - texs.push_back(sky->quarter_res_pass); - sky->quarter_res_framebuffer = RD::get_singleton()->framebuffer_create(texs); - texture_set_dirty = true; - } - - if (texture_set_dirty) { - for (int i = 0; i < SKY_TEXTURE_SET_MAX; i++) { - if (sky->texture_uniform_sets[i].is_valid() && RD::get_singleton()->uniform_set_is_valid(sky->texture_uniform_sets[i])) { - RD::get_singleton()->free(sky->texture_uniform_sets[i]); - sky->texture_uniform_sets[i] = RID(); - } - } } sky->reflection.dirty = true; diff --git a/servers/rendering/renderer_rd/environment/sky.h b/servers/rendering/renderer_rd/environment/sky.h index 45c4f9bda7..6e0ebb5f8e 100644 --- a/servers/rendering/renderer_rd/environment/sky.h +++ b/servers/rendering/renderer_rd/environment/sky.h @@ -99,11 +99,11 @@ private: struct SkyPushConstant { float orientation[12]; // 48 - 48 - float projections[RendererSceneRender::MAX_RENDER_VIEWS][4]; // 2 x 16 - 80 - float position[3]; // 12 - 92 - float time; // 4 - 96 - float pad[3]; // 12 - 108 - float luminance_multiplier; // 4 - 112 + float projection[4]; // 16 - 64 + float position[3]; // 12 - 76 + float time; // 4 - 80 + float pad[3]; // 12 - 92 + float luminance_multiplier; // 4 - 96 // 128 is the max size of a push constant. We can replace "pad" but we can't add any more. }; @@ -112,15 +112,12 @@ private: RID version; PipelineCacheRD pipelines[SKY_VERSION_MAX]; - HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms; Vector<uint32_t> ubo_offsets; uint32_t ubo_size = 0; - String path; String code; - HashMap<StringName, HashMap<int, RID>> default_texture_params; bool uses_time = false; bool uses_position = false; @@ -129,46 +126,47 @@ private: bool uses_light = false; virtual void set_code(const String &p_Code); - virtual void set_path_hint(const String &p_hint); - virtual void set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index); - virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const; - virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; - virtual bool is_parameter_texture(const StringName &p_param) const; virtual bool is_animated() const; virtual bool casts_shadows() const; - virtual Variant get_default_parameter(const StringName &p_parameter) const; virtual RS::ShaderNativeSourceCode get_native_source_code() const; SkyShaderData() {} virtual ~SkyShaderData(); }; - void _render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const Projection *p_projections, const Basis &p_orientation, const Vector3 &p_position, float p_luminance_multiplier); + void _render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, const Projection &p_projection, const Basis &p_orientation, const Vector3 &p_position, float p_luminance_multiplier); public: struct SkySceneState { struct UBO { - uint32_t volumetric_fog_enabled; // 4 - 4 - float volumetric_fog_inv_length; // 4 - 8 - float volumetric_fog_detail_spread; // 4 - 12 - float volumetric_fog_sky_affect; // 4 - 16 - - uint32_t fog_enabled; // 4 - 20 - float fog_sky_affect; // 4 - 24 - float fog_density; // 4 - 28 - float fog_sun_scatter; // 4 - 32 - - float fog_light_color[3]; // 12 - 44 - float fog_aerial_perspective; // 4 - 48 - - float z_far; // 4 - 52 - uint32_t directional_light_count; // 4 - 56 - uint32_t pad1; // 4 - 60 - uint32_t pad2; // 4 - 64 + float view_inv_projections[RendererSceneRender::MAX_RENDER_VIEWS][16]; // 2 x 64 - 128 + float view_eye_offsets[RendererSceneRender::MAX_RENDER_VIEWS][4]; // 2 x 16 - 160 + + uint32_t volumetric_fog_enabled; // 4 - 164 + float volumetric_fog_inv_length; // 4 - 168 + float volumetric_fog_detail_spread; // 4 - 172 + float volumetric_fog_sky_affect; // 4 - 176 + + uint32_t fog_enabled; // 4 - 180 + float fog_sky_affect; // 4 - 184 + float fog_density; // 4 - 188 + float fog_sun_scatter; // 4 - 192 + + float fog_light_color[3]; // 12 - 204 + float fog_aerial_perspective; // 4 - 208 + + float z_far; // 4 - 212 + uint32_t directional_light_count; // 4 - 216 + uint32_t pad1; // 4 - 220 + uint32_t pad2; // 4 - 224 }; UBO ubo; + uint32_t view_count = 1; + Transform3D cam_transform; + Projection cam_projection; + SkyDirectionalLightData *directional_lights = nullptr; SkyDirectionalLightData *last_frame_directional_lights = nullptr; uint32_t max_directional_lights; @@ -247,13 +245,10 @@ public: struct Sky { RID radiance; - RID half_res_pass; - RID half_res_framebuffer; RID quarter_res_pass; RID quarter_res_framebuffer; Size2i screen_size; - RID texture_uniform_sets[SKY_TEXTURE_SET_MAX]; RID uniform_set; RID material; @@ -276,7 +271,7 @@ public: void free(); - RID get_textures(SkyTextureSetVersion p_version, RID p_default_shader_rd); + RID get_textures(SkyTextureSetVersion p_version, RID p_default_shader_rd, Ref<RenderSceneBuffersRD> p_render_buffers); bool set_radiance_size(int p_radiance_size); bool set_mode(RS::SkyMode p_mode); bool set_material(RID p_material); @@ -300,11 +295,10 @@ public: void set_texture_format(RD::DataFormat p_texture_format); ~SkyRD(); - void setup(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, const PagedArray<RID> &p_lights, RID p_camera_attributes, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render); - void update(RID p_env, const Projection &p_projection, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0); - void draw(RID p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0); // only called by clustered renderer - void update_res_buffers(RID p_env, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0); - void draw(RD::DrawListID p_draw_list, RID p_env, RID p_fb, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0); + void setup_sky(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, const PagedArray<RID> &p_lights, RID p_camera_attributes, uint32_t p_view_count, const Projection *p_view_projections, const Vector3 *p_view_eye_offsets, const Transform3D &p_cam_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render); + void update_radiance_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_env, const Vector3 &p_global_pos, double p_time, float p_luminance_multiplier = 1.0); + void update_res_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_env, double p_time, float p_luminance_multiplier = 1.0); + void draw_sky(RD::DrawListID p_draw_list, Ref<RenderSceneBuffersRD> p_render_buffers, RID p_env, RID p_fb, double p_time, float p_luminance_multiplier = 1.0); void invalidate_sky(Sky *p_sky); void update_dirty_skys(); diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp index ceed287184..a741fb4c6a 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -348,6 +348,7 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p #endif material_uniform_set = surf->material_uniform_set; shader = surf->shader; + surf->material->set_as_used(); #ifdef DEBUG_ENABLED } #endif @@ -830,8 +831,18 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con for (int i = 0; i < (int)p_render_data->instances->size(); i++) { GeometryInstanceForwardClustered *inst = static_cast<GeometryInstanceForwardClustered *>((*p_render_data->instances)[i]); - Vector3 support_min = inst->transformed_aabb.get_support(-near_plane.normal); - inst->depth = near_plane.distance_to(support_min); + Vector3 center = inst->transform.origin; + if (p_render_data->scene_data->cam_orthogonal) { + if (inst->use_aabb_center) { + center = inst->transformed_aabb.get_support(-near_plane.normal); + } + inst->depth = near_plane.distance_to(center) - inst->sorting_offset; + } else { + if (inst->use_aabb_center) { + center = inst->transformed_aabb.position + (inst->transformed_aabb.size * 0.5); + } + inst->depth = p_render_data->scene_data->cam_transform.origin.distance_to(center) - inst->sorting_offset; + } uint32_t depth_layer = CLAMP(int(inst->depth * 16 / z_max), 0, 15); uint32_t flags = inst->base_flags; //fill flags if appropriate @@ -1446,7 +1457,7 @@ void RenderForwardClustered::_pre_opaque_render(RenderDataRD *p_render_data, boo } //full barrier here, we need raster, transfer and compute and it depends from the previous work - RD::get_singleton()->barrier(RD::BARRIER_MASK_ALL, RD::BARRIER_MASK_ALL); + RD::get_singleton()->barrier(RD::BARRIER_MASK_ALL_BARRIERS, RD::BARRIER_MASK_ALL_BARRIERS); if (current_cluster_builder) { current_cluster_builder->begin(p_render_data->scene_data->cam_transform, p_render_data->scene_data->cam_projection, !p_render_data->reflection_probe.is_valid()); @@ -1622,10 +1633,24 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co bool using_ssr = false; bool using_sdfgi = false; bool using_voxelgi = false; - bool reverse_cull = false; + bool reverse_cull = p_render_data->scene_data->cam_transform.basis.determinant() < 0; bool using_ssil = p_render_data->environment.is_valid() && environment_get_ssil_enabled(p_render_data->environment); - if (rb.is_valid()) { + if (p_render_data->reflection_probe.is_valid()) { + uint32_t resolution = light_storage->reflection_probe_instance_get_resolution(p_render_data->reflection_probe); + screen_size.x = resolution; + screen_size.y = resolution; + + color_framebuffer = light_storage->reflection_probe_instance_get_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass); + color_only_framebuffer = color_framebuffer; + depth_framebuffer = light_storage->reflection_probe_instance_get_depth_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass); + + if (light_storage->reflection_probe_is_interior(light_storage->reflection_probe_instance_get_probe(p_render_data->reflection_probe))) { + p_render_data->environment = RID(); //no environment on interiors + } + + reverse_cull = true; // for some reason our views are inverted + } else if (rb.is_valid()) { screen_size = rb->get_internal_size(); if (rb->get_use_taa() || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_MOTION_VECTORS) { @@ -1677,20 +1702,6 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co color_framebuffer = rb_data->get_color_pass_fb(color_pass_flags); color_only_framebuffer = rb_data->get_color_only_fb(); - } else if (p_render_data->reflection_probe.is_valid()) { - uint32_t resolution = light_storage->reflection_probe_instance_get_resolution(p_render_data->reflection_probe); - screen_size.x = resolution; - screen_size.y = resolution; - - color_framebuffer = light_storage->reflection_probe_instance_get_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass); - color_only_framebuffer = color_framebuffer; - depth_framebuffer = light_storage->reflection_probe_instance_get_depth_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass); - - if (light_storage->reflection_probe_is_interior(light_storage->reflection_probe_instance_get_probe(p_render_data->reflection_probe))) { - p_render_data->environment = RID(); //no environment on interiors - } - - reverse_cull = true; // for some reason our views are inverted } else { ERR_FAIL(); //bug? } @@ -1765,6 +1776,10 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co draw_sky = true; } break; case RS::ENV_BG_CANVAS: { + if (rb.is_valid()) { + RID texture = RendererRD::TextureStorage::get_singleton()->render_target_get_rd_texture(rb->get_render_target()); + copy_effects->copy_to_fb_rect(texture, color_only_framebuffer, Rect2i(), false, false, false, false, RID(), false, false, true); + } keep_color = true; } break; case RS::ENV_BG_KEEP: { @@ -1775,29 +1790,40 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co default: { } } + // setup sky if used for ambient, reflections, or background if (draw_sky || draw_sky_fog_only || environment_get_reflection_source(p_render_data->environment) == RS::ENV_REFLECTION_SOURCE_SKY || environment_get_ambient_source(p_render_data->environment) == RS::ENV_AMBIENT_SOURCE_SKY) { RENDER_TIMESTAMP("Setup Sky"); RD::get_singleton()->draw_command_begin_label("Setup Sky"); - Projection projection = p_render_data->scene_data->cam_projection; + + // Setup our sky render information for this frame/viewport if (p_render_data->reflection_probe.is_valid()) { + Vector3 eye_offset; Projection correction; correction.set_depth_correction(true); - projection = correction * p_render_data->scene_data->cam_projection; - } + Projection projection = correction * p_render_data->scene_data->cam_projection; - sky.setup(p_render_data->environment, rb, *p_render_data->lights, p_render_data->camera_attributes, projection, p_render_data->scene_data->cam_transform, screen_size, this); + sky.setup_sky(p_render_data->environment, rb, *p_render_data->lights, p_render_data->camera_attributes, 1, &projection, &eye_offset, p_render_data->scene_data->cam_transform, screen_size, this); + } else { + sky.setup_sky(p_render_data->environment, rb, *p_render_data->lights, p_render_data->camera_attributes, p_render_data->scene_data->view_count, p_render_data->scene_data->view_projection, p_render_data->scene_data->view_eye_offset, p_render_data->scene_data->cam_transform, screen_size, this); + } sky_energy_multiplier *= bg_energy_multiplier; RID sky_rid = environment_get_sky(p_render_data->environment); if (sky_rid.is_valid()) { - sky.update(p_render_data->environment, projection, p_render_data->scene_data->cam_transform, time, sky_energy_multiplier); + sky.update_radiance_buffers(rb, p_render_data->environment, p_render_data->scene_data->cam_transform.origin, time, sky_energy_multiplier); radiance_texture = sky.sky_get_radiance_texture_rd(sky_rid); } else { // do not try to draw sky if invalid draw_sky = false; } + + if (draw_sky || draw_sky_fog_only) { + // update sky half/quarter res buffers (if required) + sky.update_res_buffers(rb, p_render_data->environment, time, sky_energy_multiplier); + } + RD::get_singleton()->draw_command_end_label(); } } else { @@ -1947,15 +1973,11 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co RENDER_TIMESTAMP("Render Sky"); RD::get_singleton()->draw_command_begin_label("Draw Sky"); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(color_only_framebuffer, RD::INITIAL_ACTION_CONTINUE, can_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, can_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ); - if (p_render_data->reflection_probe.is_valid()) { - Projection correction; - correction.set_depth_correction(true); - Projection projection = correction * p_render_data->scene_data->cam_projection; - sky.draw(p_render_data->environment, can_continue_color, can_continue_depth, color_only_framebuffer, 1, &projection, p_render_data->scene_data->cam_transform, time, sky_energy_multiplier); - } else { - sky.draw(p_render_data->environment, can_continue_color, can_continue_depth, color_only_framebuffer, p_render_data->scene_data->view_count, p_render_data->scene_data->view_projection, p_render_data->scene_data->cam_transform, time, sky_energy_multiplier); - } + sky.draw_sky(draw_list, rb, p_render_data->environment, color_only_framebuffer, time, sky_energy_multiplier); + + RD::get_singleton()->draw_list_end(); RD::get_singleton()->draw_command_end_label(); } @@ -2311,6 +2333,8 @@ void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const Page scene_data.lod_distance_multiplier = p_lod_distance_multiplier; scene_data.dual_paraboloid_side = p_use_dp_flip ? -1 : 1; scene_data.opaque_prepass_threshold = 0.1f; + scene_data.time = time; + scene_data.time_step = time_step; RenderDataRD render_data; render_data.scene_data = &scene_data; @@ -2401,6 +2425,8 @@ void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, con scene_data.z_far = p_cam_projection.get_z_far(); scene_data.dual_paraboloid_side = 0; scene_data.opaque_prepass_threshold = 0.0; + scene_data.time = time; + scene_data.time_step = time_step; RenderDataRD render_data; render_data.scene_data = &scene_data; @@ -2443,6 +2469,8 @@ void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform scene_data.material_uv2_mode = false; scene_data.opaque_prepass_threshold = 0.0f; scene_data.emissive_exposure_normalization = p_exposure_normalization; + scene_data.time = time; + scene_data.time_step = time_step; RenderDataRD render_data; render_data.scene_data = &scene_data; @@ -3083,7 +3111,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend RD::Uniform u; u.binding = 19; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID vfog = RID(); + RID vfog; if (rb_data.is_valid() && rb->has_custom_data(RB_SCOPE_FOG)) { Ref<RendererRD::Fog::VolumetricFog> fog = rb->get_custom_data(RB_SCOPE_FOG); vfog = fog->fog_map; @@ -3281,6 +3309,99 @@ void RenderForwardClustered::sub_surface_scattering_set_scale(float p_scale, flo RenderForwardClustered *RenderForwardClustered::singleton = nullptr; +void RenderForwardClustered::sdfgi_update(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, const Vector3 &p_world_position) { + Ref<RenderSceneBuffersRD> rb = p_render_buffers; + ERR_FAIL_COND(rb.is_null()); + Ref<RendererRD::GI::SDFGI> sdfgi; + if (rb->has_custom_data(RB_SCOPE_SDFGI)) { + sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI); + } + + bool needs_sdfgi = p_environment.is_valid() && environment_get_sdfgi_enabled(p_environment); + + if (!needs_sdfgi) { + if (sdfgi.is_valid()) { + // delete it + sdfgi.unref(); + rb->set_custom_data(RB_SCOPE_SDFGI, sdfgi); + } + return; + } + + static const uint32_t history_frames_to_converge[RS::ENV_SDFGI_CONVERGE_MAX] = { 5, 10, 15, 20, 25, 30 }; + uint32_t requested_history_size = history_frames_to_converge[gi.sdfgi_frames_to_converge]; + + if (sdfgi.is_valid() && (sdfgi->num_cascades != environment_get_sdfgi_cascades(p_environment) || sdfgi->min_cell_size != environment_get_sdfgi_min_cell_size(p_environment) || requested_history_size != sdfgi->history_size || sdfgi->uses_occlusion != environment_get_sdfgi_use_occlusion(p_environment) || sdfgi->y_scale_mode != environment_get_sdfgi_y_scale(p_environment))) { + //configuration changed, erase + sdfgi.unref(); + rb->set_custom_data(RB_SCOPE_SDFGI, sdfgi); + } + + if (sdfgi.is_null()) { + // re-create + sdfgi = gi.create_sdfgi(p_environment, p_world_position, requested_history_size); + rb->set_custom_data(RB_SCOPE_SDFGI, sdfgi); + } else { + //check for updates + sdfgi->update(p_environment, p_world_position); + } +} + +int RenderForwardClustered::sdfgi_get_pending_region_count(const Ref<RenderSceneBuffers> &p_render_buffers) const { + Ref<RenderSceneBuffersRD> rb = p_render_buffers; + ERR_FAIL_COND_V(rb.is_null(), 0); + + if (!rb->has_custom_data(RB_SCOPE_SDFGI)) { + return 0; + } + Ref<RendererRD::GI::SDFGI> sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI); + + int dirty_count = 0; + for (uint32_t i = 0; i < sdfgi->cascades.size(); i++) { + const RendererRD::GI::SDFGI::Cascade &c = sdfgi->cascades[i]; + + if (c.dirty_regions == RendererRD::GI::SDFGI::Cascade::DIRTY_ALL) { + dirty_count++; + } else { + for (int j = 0; j < 3; j++) { + if (c.dirty_regions[j] != 0) { + dirty_count++; + } + } + } + } + + return dirty_count; +} + +AABB RenderForwardClustered::sdfgi_get_pending_region_bounds(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const { + AABB bounds; + Vector3i from; + Vector3i size; + + Ref<RenderSceneBuffersRD> rb = p_render_buffers; + ERR_FAIL_COND_V(rb.is_null(), AABB()); + Ref<RendererRD::GI::SDFGI> sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI); + ERR_FAIL_COND_V(sdfgi.is_null(), AABB()); + + int c = sdfgi->get_pending_region_data(p_region, from, size, bounds); + ERR_FAIL_COND_V(c == -1, AABB()); + return bounds; +} + +uint32_t RenderForwardClustered::sdfgi_get_pending_region_cascade(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const { + AABB bounds; + Vector3i from; + Vector3i size; + + Ref<RenderSceneBuffersRD> rb = p_render_buffers; + ERR_FAIL_COND_V(rb.is_null(), -1); + Ref<RendererRD::GI::SDFGI> sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI); + ERR_FAIL_COND_V(sdfgi.is_null(), -1); + + return sdfgi->get_pending_region_data(p_region, from, size, bounds); +} + void RenderForwardClustered::GeometryInstanceForwardClustered::_mark_dirty() { if (dirty_list_element.in_list()) { return; @@ -3349,7 +3470,7 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet SceneShaderForwardClustered::MaterialData *material_shadow = nullptr; void *surface_shadow = nullptr; - if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_position && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_pre_pass && !p_material->shader_data->uses_alpha_clip && p_material->shader_data->cull_mode == SceneShaderForwardClustered::ShaderData::CULL_BACK) { + if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_position && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_pre_pass && !p_material->shader_data->uses_alpha_clip && p_material->shader_data->cull_mode == SceneShaderForwardClustered::ShaderData::CULL_BACK && !p_material->shader_data->uses_point_size) { flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SHARED_SHADOW_MATERIAL; material_shadow = static_cast<SceneShaderForwardClustered::MaterialData *>(RendererRD::MaterialStorage::get_singleton()->material_get_data(scene_shader.default_material, RendererRD::MaterialStorage::SHADER_TYPE_3D)); @@ -3368,6 +3489,7 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet sdcache->flags = flags; sdcache->shader = p_material->shader_data; + sdcache->material = p_material; sdcache->material_uniform_set = p_material->uniform_set; sdcache->surface = mesh_storage->mesh_get_surface(p_mesh, p_surface); sdcache->primitive = mesh_storage->mesh_surface_get_primitive(sdcache->surface); @@ -3586,6 +3708,10 @@ void RenderForwardClustered::_geometry_instance_update(RenderGeometryInstance *p } ginstance->transforms_uniform_set = particles_storage->particles_get_instance_buffer_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET); + if (particles_storage->particles_get_frame_counter(ginstance->data->base) == 0) { + // Particles haven't been cleared or updated, update once now to ensure they are ready to render. + particles_storage->update_particles(); + } } else if (ginstance->data->base_type == RS::INSTANCE_MESH) { if (mesh_storage->skeleton_is_valid(ginstance->data->skeleton)) { ginstance->transforms_uniform_set = mesh_storage->skeleton_get_3d_uniform_set(ginstance->data->skeleton, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET); diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h index 670eb93e20..3399382b56 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h @@ -210,10 +210,10 @@ class RenderForwardClustered : public RendererSceneRenderRD { float screen_mesh_lod_threshold = 0.0; RD::FramebufferFormatID framebuffer_format = 0; uint32_t element_offset = 0; - uint32_t barrier = RD::BARRIER_MASK_ALL; + uint32_t barrier = RD::BARRIER_MASK_ALL_BARRIERS; bool use_directional_soft_shadow = false; - RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, uint32_t p_color_pass_flags, bool p_no_gi, bool p_use_directional_soft_shadows, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL) { + RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, uint32_t p_color_pass_flags, bool p_no_gi, bool p_use_directional_soft_shadows, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL_BARRIERS) { elements = p_elements; element_info = p_element_info; element_count = p_element_count; @@ -441,6 +441,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { void *surface = nullptr; RID material_uniform_set; SceneShaderForwardClustered::ShaderData *shader = nullptr; + SceneShaderForwardClustered::MaterialData *material = nullptr; void *surface_shadow = nullptr; RID material_uniform_set_shadow; @@ -596,7 +597,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { void _render_shadow_begin(); void _render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RenderingMethod::RenderInfo *p_render_info = nullptr); void _render_shadow_process(); - void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL); + void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL_BARRIERS); /* Render Scene */ void _process_ssao(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection); @@ -649,6 +650,16 @@ public: _update_render_base_uniform_set(); } + /* SDFGI UPDATE */ + + virtual void sdfgi_update(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, const Vector3 &p_world_position) override; + virtual int sdfgi_get_pending_region_count(const Ref<RenderSceneBuffers> &p_render_buffers) const override; + virtual AABB sdfgi_get_pending_region_bounds(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const override; + virtual uint32_t sdfgi_get_pending_region_cascade(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const override; + RID sdfgi_get_ubo() const { return gi.sdfgi_ubo; } + + /* GEOMETRY INSTANCE */ + virtual RenderGeometryInstance *geometry_instance_create(RID p_base) override; virtual void geometry_instance_free(RenderGeometryInstance *p_geometry_instance) override; diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp index c1b23af82f..914ca25899 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp @@ -37,10 +37,6 @@ using namespace RendererSceneRenderImplementation; -void SceneShaderForwardClustered::ShaderData::set_path_hint(const String &p_path) { - path = p_path; -} - void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { //compile @@ -115,6 +111,9 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { actions.usage_flag_pointers["ALPHA"] = &uses_alpha; actions.usage_flag_pointers["ALPHA_SCISSOR_THRESHOLD"] = &uses_alpha_clip; + // Use alpha clip pipeline for alpha hash/dither. + // This prevents sorting issues inherent to alpha blending and allows such materials to cast shadows. + actions.usage_flag_pointers["ALPHA_HASH_SCALE"] = &uses_alpha_clip; actions.render_mode_flags["depth_prepass_alpha"] = &uses_depth_pre_pass; actions.usage_flag_pointers["SSS_STRENGTH"] = &uses_sss; @@ -151,6 +150,8 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { depth_test = DepthTest(depth_testi); cull_mode = Cull(cull_modei); uses_screen_texture_mipmaps = gen_code.uses_screen_texture_mipmaps; + uses_vertex_time = gen_code.uses_vertex_time; + uses_fragment_time = gen_code.uses_fragment_time; #if 0 print_line("**compiling shader:"); @@ -255,6 +256,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { depth_stencil_state.depth_compare_operator = RD::COMPARE_OP_LESS_OR_EQUAL; depth_stencil_state.enable_depth_write = depth_draw != DEPTH_DRAW_DISABLED ? true : false; } + bool depth_pre_pass_enabled = bool(GLOBAL_GET("rendering/driver/depth_prepass/enable")); for (int i = 0; i < CULL_VARIANT_MAX; i++) { RD::PolygonCullMode cull_mode_rd_table[CULL_VARIANT_MAX][3] = { @@ -306,8 +308,16 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { continue; } - RD::PipelineColorBlendState blend_state; RD::PipelineDepthStencilState depth_stencil = depth_stencil_state; + if (depth_pre_pass_enabled && casts_shadows()) { + // We already have a depth from the depth pre-pass, there is no need to write it again. + // In addition we can use COMPARE_OP_EQUAL instead of COMPARE_OP_LESS_OR_EQUAL. + // This way we can use the early depth test to discard transparent fragments before the fragment shader even starts. + depth_stencil.depth_compare_operator = RD::COMPARE_OP_EQUAL; + depth_stencil.enable_depth_write = false; + } + + RD::PipelineColorBlendState blend_state; RD::PipelineMultisampleState multisample_state; int shader_flags = 0; @@ -375,102 +385,16 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { valid = true; } -void SceneShaderForwardClustered::ShaderData::set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index) { - if (!p_texture.is_valid()) { - if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) { - default_texture_params[p_name].erase(p_index); - - if (default_texture_params[p_name].is_empty()) { - default_texture_params.erase(p_name); - } - } - } else { - if (!default_texture_params.has(p_name)) { - default_texture_params[p_name] = HashMap<int, RID>(); - } - default_texture_params[p_name][p_index] = p_texture; - } -} - -void SceneShaderForwardClustered::ShaderData::get_shader_uniform_list(List<PropertyInfo> *p_param_list) const { - HashMap<int, StringName> order; - - for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { - if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL || - E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE || - E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE || - E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) { - // Don't expose any of these. - continue; - } - - if (E.value.texture_order >= 0) { - order[E.value.texture_order + 100000] = E.key; - } else { - order[E.value.order] = E.key; - } - } - - String last_group; - for (const KeyValue<int, StringName> &E : order) { - String group = uniforms[E.value].group; - if (!uniforms[E.value].subgroup.is_empty()) { - group += "::" + uniforms[E.value].subgroup; - } - - if (group != last_group) { - PropertyInfo pi; - pi.usage = PROPERTY_USAGE_GROUP; - pi.name = group; - p_param_list->push_back(pi); - - last_group = group; - } - - PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]); - pi.name = E.value; - p_param_list->push_back(pi); - } -} - -void SceneShaderForwardClustered::ShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const { - for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { - if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { - continue; - } - - RendererMaterialStorage::InstanceShaderParam p; - p.info = ShaderLanguage::uniform_to_property_info(E.value); - p.info.name = E.key; //supply name - p.index = E.value.instance_index; - p.default_value = ShaderLanguage::constant_value_to_variant(E.value.default_value, E.value.type, E.value.array_size, E.value.hint); - p_param_list->push_back(p); - } -} - -bool SceneShaderForwardClustered::ShaderData::is_parameter_texture(const StringName &p_param) const { - if (!uniforms.has(p_param)) { - return false; - } - - return uniforms[p_param].texture_order >= 0; -} - bool SceneShaderForwardClustered::ShaderData::is_animated() const { - return false; + return (uses_fragment_time && uses_discard) || (uses_vertex_time && uses_vertex); } bool SceneShaderForwardClustered::ShaderData::casts_shadows() const { - return false; -} + bool has_read_screen_alpha = uses_screen_texture || uses_depth_texture || uses_normal_texture; + bool has_base_alpha = (uses_alpha && !uses_alpha_clip) || has_read_screen_alpha; + bool has_alpha = has_base_alpha || uses_blend_alpha; -Variant SceneShaderForwardClustered::ShaderData::get_default_parameter(const StringName &p_parameter) const { - if (uniforms.has(p_parameter)) { - ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter]; - Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value; - return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.array_size, uniform.hint); - } - return Variant(); + return !has_alpha || (uses_depth_pre_pass && !(depth_draw == DEPTH_DRAW_DISABLED || depth_test == DEPTH_TEST_DISABLED)); } RS::ShaderNativeSourceCode SceneShaderForwardClustered::ShaderData::get_native_source_code() const { @@ -700,6 +624,7 @@ void SceneShaderForwardClustered::init(const String p_defines) { actions.renames["NODE_POSITION_WORLD"] = "read_model_matrix[3].xyz"; actions.renames["CAMERA_POSITION_WORLD"] = "scene_data.inv_view_matrix[3].xyz"; actions.renames["CAMERA_DIRECTION_WORLD"] = "scene_data.view_matrix[3].xyz"; + actions.renames["CAMERA_VISIBLE_LAYERS"] = "scene_data.camera_visible_layers"; actions.renames["NODE_POSITION_VIEW"] = "(read_model_matrix * scene_data.view_matrix)[3].xyz"; actions.renames["VIEW_INDEX"] = "ViewIndex"; diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h index a9a9fa94de..51e4dd44d5 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h @@ -139,19 +139,15 @@ public: PipelineCacheRD pipelines[CULL_VARIANT_MAX][RS::PRIMITIVE_MAX][PIPELINE_VERSION_MAX]; PipelineCacheRD color_pipelines[CULL_VARIANT_MAX][RS::PRIMITIVE_MAX][PIPELINE_COLOR_PASS_FLAG_COUNT]; - String path; - - HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms; Vector<uint32_t> ubo_offsets; uint32_t ubo_size = 0; String code; - HashMap<StringName, HashMap<int, RID>> default_texture_params; - DepthDraw depth_draw; - DepthTest depth_test; + DepthDraw depth_draw = DEPTH_DRAW_OPAQUE; + DepthTest depth_test = DEPTH_TEST_ENABLED; bool uses_point_size = false; bool uses_alpha = false; @@ -172,6 +168,8 @@ public: bool uses_depth_texture = false; bool uses_normal_texture = false; bool uses_time = false; + bool uses_vertex_time = false; + bool uses_fragment_time = false; bool writes_modelview_or_projection = false; bool uses_world_coordinates = false; bool uses_screen_texture_mipmaps = false; @@ -181,15 +179,9 @@ public: uint32_t index = 0; virtual void set_code(const String &p_Code); - virtual void set_path_hint(const String &p_path); - virtual void set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index); - virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const; - void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; - virtual bool is_parameter_texture(const StringName &p_param) const; virtual bool is_animated() const; virtual bool casts_shadows() const; - virtual Variant get_default_parameter(const StringName &p_parameter) const; virtual RS::ShaderNativeSourceCode get_native_source_code() const; SelfList<ShaderData> shader_list_element; diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp index f76d016ae7..7f567bcc2e 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -70,17 +70,17 @@ void RenderForwardMobile::ForwardIDStorageMobile::map_forward_id(RendererRD::For void RenderForwardMobile::ForwardIDStorageMobile::fill_push_constant_instance_indices(GeometryInstanceForwardMobile::PushConstant *p_push_constant, uint32_t &spec_constants, const GeometryInstanceForwardMobile *p_instance) { // first zero out our indices - p_push_constant->omni_lights[0] = 0xFFFF; - p_push_constant->omni_lights[1] = 0xFFFF; + p_push_constant->omni_lights[0] = 0xFFFFFFFF; + p_push_constant->omni_lights[1] = 0xFFFFFFFF; - p_push_constant->spot_lights[0] = 0xFFFF; - p_push_constant->spot_lights[1] = 0xFFFF; + p_push_constant->spot_lights[0] = 0xFFFFFFFF; + p_push_constant->spot_lights[1] = 0xFFFFFFFF; - p_push_constant->decals[0] = 0xFFFF; - p_push_constant->decals[1] = 0xFFFF; + p_push_constant->decals[0] = 0xFFFFFFFF; + p_push_constant->decals[1] = 0xFFFFFFFF; - p_push_constant->reflection_probes[0] = 0xFFFF; - p_push_constant->reflection_probes[1] = 0xFFFF; + p_push_constant->reflection_probes[0] = 0xFFFFFFFF; + p_push_constant->reflection_probes[1] = 0xFFFFFFFF; if (p_instance->omni_light_count == 0) { spec_constants |= 1 << SPEC_CONSTANT_DISABLE_OMNI_LIGHTS; @@ -154,8 +154,8 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RenderSceneBu render_buffers->create_texture(RB_SCOPE_MOBILE, RB_TEX_COLOR_MSAA, format, usage_bits, texture_samples); - format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT; usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; + format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, usage_bits) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT; render_buffers->create_texture(RB_SCOPE_MOBILE, RB_TEX_DEPTH_MSAA, format, usage_bits, texture_samples); } @@ -361,7 +361,9 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ Ref<RenderSceneBuffersRD> rb; if (p_render_data && p_render_data->render_buffers.is_valid()) { rb = p_render_data->render_buffers; - rb_data = rb->get_custom_data(RB_SCOPE_MOBILE); + if (rb->has_custom_data(RB_SCOPE_MOBILE)) { + rb_data = rb->get_custom_data(RB_SCOPE_MOBILE); + } } // default render buffer and scene state uniform set @@ -612,7 +614,7 @@ void RenderForwardMobile::_pre_opaque_render(RenderDataRD *p_render_data) { } //full barrier here, we need raster, transfer and compute and it depends from the previous work - RD::get_singleton()->barrier(RD::BARRIER_MASK_ALL, RD::BARRIER_MASK_ALL); + RD::get_singleton()->barrier(RD::BARRIER_MASK_ALL_BARRIERS, RD::BARRIER_MASK_ALL_BARRIERS); bool using_shadows = true; @@ -640,7 +642,9 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color Ref<RenderBufferDataForwardMobile> rb_data; if (p_render_data->render_buffers.is_valid()) { rb = p_render_data->render_buffers; - rb_data = rb->get_custom_data(RB_SCOPE_MOBILE); + if (rb->has_custom_data(RB_SCOPE_MOBILE)) { + rb_data = rb->get_custom_data(RB_SCOPE_MOBILE); + } } RENDER_TIMESTAMP("Prepare 3D Scene"); @@ -673,7 +677,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color Size2i screen_size; RID framebuffer; - bool reverse_cull = false; + bool reverse_cull = p_render_data->scene_data->cam_transform.basis.determinant() < 0; bool using_subpass_transparent = true; bool using_subpass_post_process = true; @@ -689,7 +693,21 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME] = p_render_data->instances->size(); } - if (rb_data.is_valid()) { + if (p_render_data->reflection_probe.is_valid()) { + uint32_t resolution = light_storage->reflection_probe_instance_get_resolution(p_render_data->reflection_probe); + screen_size.x = resolution; + screen_size.y = resolution; + + framebuffer = light_storage->reflection_probe_instance_get_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass); + + if (light_storage->reflection_probe_is_interior(light_storage->reflection_probe_instance_get_probe(p_render_data->reflection_probe))) { + p_render_data->environment = RID(); //no environment on interiors + } + + reverse_cull = true; + using_subpass_transparent = true; // we ignore our screen/depth texture here + using_subpass_post_process = false; // not applicable at all for reflection probes. + } else if (rb_data.is_valid()) { // setup rendering to render buffer screen_size = p_render_data->render_buffers->get_internal_size(); @@ -717,20 +735,6 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color // only opaque and sky as subpasses framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_TWO_SUBPASSES); } - } else if (p_render_data->reflection_probe.is_valid()) { - uint32_t resolution = light_storage->reflection_probe_instance_get_resolution(p_render_data->reflection_probe); - screen_size.x = resolution; - screen_size.y = resolution; - - framebuffer = light_storage->reflection_probe_instance_get_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass); - - if (light_storage->reflection_probe_is_interior(light_storage->reflection_probe_instance_get_probe(p_render_data->reflection_probe))) { - p_render_data->environment = RID(); //no environment on interiors - } - - reverse_cull = true; - using_subpass_transparent = true; // we ignore our screen/depth texture here - using_subpass_post_process = false; // not applicable at all for reflection probes. } else { ERR_FAIL(); //bug? } @@ -796,6 +800,11 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color draw_sky = true; } break; case RS::ENV_BG_CANVAS: { + if (rb_data.is_valid()) { + RID dest_framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_ONE_PASS); + RID texture = RendererRD::TextureStorage::get_singleton()->render_target_get_rd_texture(rb->get_render_target()); + copy_effects->copy_to_fb_rect(texture, dest_framebuffer, Rect2i(), false, false, false, false, RID(), false, false, true); + } keep_color = true; } break; case RS::ENV_BG_KEEP: { @@ -806,55 +815,45 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color default: { } } + // setup sky if used for ambient, reflections, or background if (draw_sky || draw_sky_fog_only || environment_get_reflection_source(p_render_data->environment) == RS::ENV_REFLECTION_SOURCE_SKY || environment_get_ambient_source(p_render_data->environment) == RS::ENV_AMBIENT_SOURCE_SKY) { RENDER_TIMESTAMP("Setup Sky"); RD::get_singleton()->draw_command_begin_label("Setup Sky"); - Projection projection = p_render_data->scene_data->cam_projection; + + // Setup our sky render information for this frame/viewport if (p_render_data->reflection_probe.is_valid()) { + Vector3 eye_offset; Projection correction; correction.set_depth_correction(true); - projection = correction * p_render_data->scene_data->cam_projection; - } + Projection projection = correction * p_render_data->scene_data->cam_projection; - sky.setup(p_render_data->environment, p_render_data->render_buffers, *p_render_data->lights, p_render_data->camera_attributes, projection, p_render_data->scene_data->cam_transform, screen_size, this); + sky.setup_sky(p_render_data->environment, p_render_data->render_buffers, *p_render_data->lights, p_render_data->camera_attributes, 1, &projection, &eye_offset, p_render_data->scene_data->cam_transform, screen_size, this); + } else { + sky.setup_sky(p_render_data->environment, p_render_data->render_buffers, *p_render_data->lights, p_render_data->camera_attributes, p_render_data->scene_data->view_count, p_render_data->scene_data->view_projection, p_render_data->scene_data->view_eye_offset, p_render_data->scene_data->cam_transform, screen_size, this); + } sky_energy_multiplier *= bg_energy_multiplier; RID sky_rid = environment_get_sky(p_render_data->environment); if (sky_rid.is_valid()) { - sky.update(p_render_data->environment, projection, p_render_data->scene_data->cam_transform, time, sky_energy_multiplier); + sky.update_radiance_buffers(rb, p_render_data->environment, p_render_data->scene_data->cam_transform.origin, time, sky_energy_multiplier); radiance_texture = sky.sky_get_radiance_texture_rd(sky_rid); } else { // do not try to draw sky if invalid draw_sky = false; } + + if (draw_sky || draw_sky_fog_only) { + // update sky half/quarter res buffers (if required) + sky.update_res_buffers(rb, p_render_data->environment, time, sky_energy_multiplier); + } RD::get_singleton()->draw_command_end_label(); // Setup Sky } } else { clear_color = p_default_bg_color; } - // update sky buffers (if required) - if (draw_sky || draw_sky_fog_only) { - // !BAS! @TODO See if we can limit doing some things double and maybe even move this into _pre_opaque_render - // and change Forward Clustered in the same way as we have here (but without using subpasses) - RENDER_TIMESTAMP("Setup Sky Resolution Buffers"); - - RD::get_singleton()->draw_command_begin_label("Setup Sky Resolution Buffers"); - - if (p_render_data->reflection_probe.is_valid()) { - Projection correction; - correction.set_depth_correction(true); - Projection projection = correction * p_render_data->scene_data->cam_projection; - sky.update_res_buffers(p_render_data->environment, 1, &projection, p_render_data->scene_data->cam_transform, time, sky_energy_multiplier); - } else { - sky.update_res_buffers(p_render_data->environment, p_render_data->scene_data->view_count, p_render_data->scene_data->view_projection, p_render_data->scene_data->cam_transform, time, sky_energy_multiplier); - } - - RD::get_singleton()->draw_command_end_label(); // Setup Sky resolution buffers - } - _pre_opaque_render(p_render_data); uint32_t spec_constant_base_flags = 0; @@ -939,16 +938,11 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color if (draw_sky || draw_sky_fog_only) { RD::get_singleton()->draw_command_begin_label("Draw Sky Subpass"); + // Note, sky.setup should have been called up above and setup stuff we need. + RD::DrawListID draw_list = RD::get_singleton()->draw_list_switch_to_next_pass(); - if (p_render_data->reflection_probe.is_valid()) { - Projection correction; - correction.set_depth_correction(true); - Projection projection = correction * p_render_data->scene_data->cam_projection; - sky.draw(draw_list, p_render_data->environment, framebuffer, 1, &projection, p_render_data->scene_data->cam_transform, time, sky_energy_multiplier); - } else { - sky.draw(draw_list, p_render_data->environment, framebuffer, p_render_data->scene_data->view_count, p_render_data->scene_data->view_projection, p_render_data->scene_data->cam_transform, time, sky_energy_multiplier); - } + sky.draw_sky(draw_list, rb, p_render_data->environment, framebuffer, time, sky_energy_multiplier); RD::get_singleton()->draw_command_end_label(); // Draw Sky Subpass @@ -960,7 +954,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color if (!using_subpass_transparent) { // We're done with our subpasses so end our container pass - RD::get_singleton()->draw_list_end(RD::BARRIER_MASK_ALL); + RD::get_singleton()->draw_list_end(RD::BARRIER_MASK_ALL_BARRIERS); RD::get_singleton()->draw_command_end_label(); // Render 3D Pass / Render Reflection Probe Pass } @@ -1012,11 +1006,13 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color RD::get_singleton()->draw_command_end_label(); // Render 3D Pass / Render Reflection Probe Pass - RD::get_singleton()->draw_list_end(RD::BARRIER_MASK_ALL); + RD::get_singleton()->draw_list_end(RD::BARRIER_MASK_ALL_BARRIERS); } else { RENDER_TIMESTAMP("Render Transparent"); - framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_ONE_PASS); + if (rb_data.is_valid()) { + framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_ONE_PASS); + } // this may be needed if we re-introduced steps that change info, not sure which do so in the previous implementation // _setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false); @@ -1032,12 +1028,12 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &RenderForwardMobile::_render_list_thread_function, &render_list_params, thread_draw_lists.size(), -1, true, SNAME("ForwardMobileRenderSubpass")); WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task); - RD::get_singleton()->draw_list_end(RD::BARRIER_MASK_ALL); + RD::get_singleton()->draw_list_end(RD::BARRIER_MASK_ALL_BARRIERS); } else { //single threaded RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, can_continue_color ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, can_continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ); _render_list(draw_list, fb_format, &render_list_params, 0, render_list_params.element_count); - RD::get_singleton()->draw_list_end(RD::BARRIER_MASK_ALL); + RD::get_singleton()->draw_list_end(RD::BARRIER_MASK_ALL_BARRIERS); } RD::get_singleton()->draw_command_end_label(); // Render Transparent Subpass @@ -1269,6 +1265,8 @@ void RenderForwardMobile::_render_shadow_append(RID p_framebuffer, const PagedAr scene_data.lod_distance_multiplier = p_lod_distance_multiplier; scene_data.dual_paraboloid_side = p_use_dp_flip ? -1 : 1; scene_data.opaque_prepass_threshold = 0.1; + scene_data.time = time; + scene_data.time_step = time_step; RenderDataRD render_data; render_data.scene_data = &scene_data; @@ -1361,6 +1359,8 @@ void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, c scene_data.material_uv2_mode = false; scene_data.opaque_prepass_threshold = 0.0f; scene_data.emissive_exposure_normalization = p_exposure_normalization; + scene_data.time = time; + scene_data.time_step = time_step; RenderDataRD render_data; render_data.scene_data = &scene_data; @@ -1484,6 +1484,8 @@ void RenderForwardMobile::_render_particle_collider_heightfield(RID p_fb, const scene_data.z_far = p_cam_projection.get_z_far(); scene_data.dual_paraboloid_side = 0; scene_data.opaque_prepass_threshold = 0.0; + scene_data.time = time; + scene_data.time_step = time_step; RenderDataRD render_data; render_data.scene_data = &scene_data; @@ -1746,8 +1748,18 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const for (int i = 0; i < (int)p_render_data->instances->size(); i++) { GeometryInstanceForwardMobile *inst = static_cast<GeometryInstanceForwardMobile *>((*p_render_data->instances)[i]); - Vector3 support_min = inst->transformed_aabb.get_support(-near_plane.normal); - inst->depth = near_plane.distance_to(support_min); + Vector3 center = inst->transform.origin; + if (p_render_data->scene_data->cam_orthogonal) { + if (inst->use_aabb_center) { + center = inst->transformed_aabb.get_support(-near_plane.normal); + } + inst->depth = near_plane.distance_to(center) - inst->sorting_offset; + } else { + if (inst->use_aabb_center) { + center = inst->transformed_aabb.position + (inst->transformed_aabb.size * 0.5); + } + inst->depth = p_render_data->scene_data->cam_transform.origin.distance_to(center) - inst->sorting_offset; + } uint32_t depth_layer = CLAMP(int(inst->depth * 16 / z_max), 0, 15); uint32_t flags = inst->base_flags; //fill flags if appropriate @@ -2004,6 +2016,7 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr RID prev_index_array_rd; RID prev_pipeline_rd; RID prev_xforms_uniform_set; + bool should_request_redraw = false; bool shadow_pass = (p_params->pass_mode == PASS_MODE_SHADOW) || (p_params->pass_mode == PASS_MODE_SHADOW_DP); @@ -2080,6 +2093,7 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr #endif material_uniform_set = surf->material_uniform_set; shader = surf->shader; + surf->material->set_as_used(); #ifdef DEBUG_ENABLED } #endif @@ -2090,6 +2104,11 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr continue; } + //request a redraw if one of the shaders uses TIME + if (shader->uses_time) { + should_request_redraw = true; + } + //find cull variant SceneShaderForwardMobile::ShaderData::CullVariant cull_variant; @@ -2191,6 +2210,11 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr RD::get_singleton()->draw_list_draw(draw_list, index_array_rd.is_valid(), instance_count); } + + // Make the actual redraw request + if (should_request_redraw) { + RenderingServerDefault::redraw_request(); + } } /* Geometry instance */ @@ -2385,6 +2409,7 @@ void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryI sdcache->flags = flags; sdcache->shader = p_material->shader_data; + sdcache->material = p_material; sdcache->material_uniform_set = p_material->uniform_set; sdcache->surface = mesh_storage->mesh_get_surface(p_mesh, p_surface); sdcache->primitive = mesh_storage->mesh_surface_get_primitive(sdcache->surface); @@ -2602,6 +2627,10 @@ void RenderForwardMobile::_geometry_instance_update(RenderGeometryInstance *p_ge } ginstance->transforms_uniform_set = particles_storage->particles_get_instance_buffer_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET); + if (particles_storage->particles_get_frame_counter(ginstance->data->base) == 0) { + // Particles haven't been cleared or updated, update once now to ensure they are ready to render. + particles_storage->update_particles(); + } } else if (ginstance->data->base_type == RS::INSTANCE_MESH) { if (mesh_storage->skeleton_is_valid(ginstance->data->skeleton)) { ginstance->transforms_uniform_set = mesh_storage->skeleton_get_3d_uniform_set(ginstance->data->skeleton, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET); diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h index ce64d805b7..7ed6061def 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h @@ -168,10 +168,10 @@ private: float screen_mesh_lod_threshold = 0.0; RD::FramebufferFormatID framebuffer_format = 0; uint32_t element_offset = 0; - uint32_t barrier = RD::BARRIER_MASK_ALL; + uint32_t barrier = RD::BARRIER_MASK_ALL_BARRIERS; uint32_t subpass = 0; - RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, RID p_render_pass_uniform_set, uint32_t p_spec_constant_base_flags = 0, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL) { + RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, RID p_render_pass_uniform_set, uint32_t p_spec_constant_base_flags = 0, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL_BARRIERS) { elements = p_elements; element_info = p_element_info; element_count = p_element_count; @@ -196,7 +196,7 @@ private: void _render_shadow_begin(); void _render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RenderingMethod::RenderInfo *p_render_info = nullptr); void _render_shadow_process(); - void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL); + void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL_BARRIERS); /* Render Scene */ @@ -440,6 +440,7 @@ protected: void *surface = nullptr; RID material_uniform_set; SceneShaderForwardMobile::ShaderData *shader = nullptr; + SceneShaderForwardMobile::MaterialData *material = nullptr; void *surface_shadow = nullptr; RID material_uniform_set_shadow; @@ -554,6 +555,15 @@ public: virtual RID reflection_probe_create_framebuffer(RID p_color, RID p_depth) override; + /* SDFGI UPDATE */ + + virtual void sdfgi_update(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, const Vector3 &p_world_position) override {} + virtual int sdfgi_get_pending_region_count(const Ref<RenderSceneBuffers> &p_render_buffers) const override { return 0; } + virtual AABB sdfgi_get_pending_region_bounds(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const override { return AABB(); } + virtual uint32_t sdfgi_get_pending_region_cascade(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const override { return 0; } + + /* GEOMETRY INSTANCE */ + static void _geometry_instance_dependency_changed(Dependency::DependencyChangedNotification p_notification, DependencyTracker *p_tracker); static void _geometry_instance_dependency_deleted(const RID &p_dependency, DependencyTracker *p_tracker); diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp index 02bd30d32d..224bb34189 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp @@ -39,10 +39,6 @@ using namespace RendererSceneRenderImplementation; /* ShaderData */ -void SceneShaderForwardMobile::ShaderData::set_path_hint(const String &p_path) { - path = p_path; -} - void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) { //compile @@ -116,6 +112,9 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) { actions.usage_flag_pointers["ALPHA"] = &uses_alpha; actions.usage_flag_pointers["ALPHA_SCISSOR_THRESHOLD"] = &uses_alpha_clip; + // Use alpha clip pipeline for alpha hash/dither. + // This prevents sorting issues inherent to alpha blending and allows such materials to cast shadows. + actions.usage_flag_pointers["ALPHA_HASH_SCALE"] = &uses_alpha_clip; actions.render_mode_flags["depth_prepass_alpha"] = &uses_depth_pre_pass; // actions.usage_flag_pointers["SSS_STRENGTH"] = &uses_sss; @@ -150,6 +149,8 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) { depth_draw = DepthDraw(depth_drawi); depth_test = DepthTest(depth_testi); + uses_vertex_time = gen_code.uses_vertex_time; + uses_fragment_time = gen_code.uses_fragment_time; #if 0 print_line("**compiling shader:"); @@ -331,101 +332,16 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) { valid = true; } -void SceneShaderForwardMobile::ShaderData::set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index) { - if (!p_texture.is_valid()) { - if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) { - default_texture_params[p_name].erase(p_index); - - if (default_texture_params[p_name].is_empty()) { - default_texture_params.erase(p_name); - } - } - } else { - if (!default_texture_params.has(p_name)) { - default_texture_params[p_name] = HashMap<int, RID>(); - } - default_texture_params[p_name][p_index] = p_texture; - } -} - -void SceneShaderForwardMobile::ShaderData::get_shader_uniform_list(List<PropertyInfo> *p_param_list) const { - HashMap<int, StringName> order; - - for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { - if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL || - E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE || - E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE || - E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) { - continue; - } - - if (E.value.texture_order >= 0) { - order[E.value.texture_order + 100000] = E.key; - } else { - order[E.value.order] = E.key; - } - } - - String last_group; - for (const KeyValue<int, StringName> &E : order) { - String group = uniforms[E.value].group; - if (!uniforms[E.value].subgroup.is_empty()) { - group += "::" + uniforms[E.value].subgroup; - } - - if (group != last_group) { - PropertyInfo pi; - pi.usage = PROPERTY_USAGE_GROUP; - pi.name = group; - p_param_list->push_back(pi); - - last_group = group; - } - - PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]); - pi.name = E.value; - p_param_list->push_back(pi); - } -} - -void SceneShaderForwardMobile::ShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const { - for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { - if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { - continue; - } - - RendererMaterialStorage::InstanceShaderParam p; - p.info = ShaderLanguage::uniform_to_property_info(E.value); - p.info.name = E.key; //supply name - p.index = E.value.instance_index; - p.default_value = ShaderLanguage::constant_value_to_variant(E.value.default_value, E.value.type, E.value.array_size, E.value.hint); - p_param_list->push_back(p); - } -} - -bool SceneShaderForwardMobile::ShaderData::is_parameter_texture(const StringName &p_param) const { - if (!uniforms.has(p_param)) { - return false; - } - - return uniforms[p_param].texture_order >= 0; -} - bool SceneShaderForwardMobile::ShaderData::is_animated() const { - return false; + return (uses_fragment_time && uses_discard) || (uses_vertex_time && uses_vertex); } bool SceneShaderForwardMobile::ShaderData::casts_shadows() const { - return false; -} + bool has_read_screen_alpha = uses_screen_texture || uses_depth_texture || uses_normal_texture; + bool has_base_alpha = (uses_alpha && !uses_alpha_clip) || has_read_screen_alpha; + bool has_alpha = has_base_alpha || uses_blend_alpha; -Variant SceneShaderForwardMobile::ShaderData::get_default_parameter(const StringName &p_parameter) const { - if (uniforms.has(p_parameter)) { - ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter]; - Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value; - return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.array_size, uniform.hint); - } - return Variant(); + return !has_alpha || (uses_depth_pre_pass && !(depth_draw == DEPTH_DRAW_DISABLED || depth_test == DEPTH_TEST_DISABLED)); } RS::ShaderNativeSourceCode SceneShaderForwardMobile::ShaderData::get_native_source_code() const { @@ -600,6 +516,7 @@ void SceneShaderForwardMobile::init(const String p_defines) { actions.renames["NODE_POSITION_WORLD"] = "read_model_matrix[3].xyz"; actions.renames["CAMERA_POSITION_WORLD"] = "scene_data.inv_view_matrix[3].xyz"; actions.renames["CAMERA_DIRECTION_WORLD"] = "scene_data.view_matrix[3].xyz"; + actions.renames["CAMERA_VISIBLE_LAYERS"] = "scene_data.camera_visible_layers"; actions.renames["NODE_POSITION_VIEW"] = "(read_model_matrix * scene_data.view_matrix)[3].xyz"; actions.renames["VIEW_INDEX"] = "ViewIndex"; diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h index f67665a02f..18a897a9e9 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h @@ -100,16 +100,12 @@ public: uint32_t vertex_input_mask = 0; PipelineCacheRD pipelines[CULL_VARIANT_MAX][RS::PRIMITIVE_MAX][SHADER_VERSION_MAX]; - String path; - - HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms; Vector<uint32_t> ubo_offsets; uint32_t ubo_size = 0; String code; - HashMap<StringName, HashMap<int, RID>> default_texture_params; DepthDraw depth_draw; DepthTest depth_test; @@ -132,6 +128,8 @@ public: bool uses_depth_texture = false; bool uses_normal_texture = false; bool uses_time = false; + bool uses_vertex_time = false; + bool uses_fragment_time = false; bool writes_modelview_or_projection = false; bool uses_world_coordinates = false; @@ -139,16 +137,8 @@ public: uint32_t index = 0; virtual void set_code(const String &p_Code); - virtual void set_path_hint(const String &p_path); - - virtual void set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index); - virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const; - void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; - - virtual bool is_parameter_texture(const StringName &p_param) const; virtual bool is_animated() const; virtual bool casts_shadows() const; - virtual Variant get_default_parameter(const StringName &p_parameter) const; virtual RS::ShaderNativeSourceCode get_native_source_code() const; SelfList<ShaderData> shader_list_element; diff --git a/servers/rendering/renderer_rd/framebuffer_cache_rd.h b/servers/rendering/renderer_rd/framebuffer_cache_rd.h index f50d6baa30..8cf25cf44a 100644 --- a/servers/rendering/renderer_rd/framebuffer_cache_rd.h +++ b/servers/rendering/renderer_rd/framebuffer_cache_rd.h @@ -254,11 +254,11 @@ public: RID get_cache_multipass(const Vector<RID> &p_textures, const Vector<RD::FramebufferPass> &p_passes, uint32_t p_views = 1) { uint32_t h = hash_murmur3_one_32(p_views); - h = hash_murmur3_one_32(p_textures.size()); + h = hash_murmur3_one_32(p_textures.size(), h); for (int i = 0; i < p_textures.size(); i++) { h = hash_murmur3_one_64(p_textures[i].get_id(), h); } - h = hash_murmur3_one_32(p_passes.size()); + h = hash_murmur3_one_32(p_passes.size(), h); for (int i = 0; i < p_passes.size(); i++) { h = _hash_pass(p_passes[i], h); } diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index cbc5cc337c..96690ceac1 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -398,7 +398,7 @@ void RendererCanvasRenderRD::_bind_canvas_texture(RD::DrawListID p_draw_list, RI r_last_texture = p_texture; } -void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_render_target, const Item *p_item, RD::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, Light *p_lights, PipelineVariants *p_pipeline_variants) { +void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_render_target, const Item *p_item, RD::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, Light *p_lights, PipelineVariants *p_pipeline_variants, bool &r_sdf_used) { //create an empty push constant RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton(); @@ -706,7 +706,7 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend //bind textures - _bind_canvas_texture(p_draw_list, RID(), current_filter, current_repeat, last_texture, push_constant, texpixel_size); + _bind_canvas_texture(p_draw_list, primitive->texture, current_filter, current_repeat, last_texture, push_constant, texpixel_size); RD::get_singleton()->draw_list_bind_index_array(p_draw_list, primitive_arrays.index_array[MIN(3u, primitive->point_count) - 1]); @@ -790,13 +790,12 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend ERR_BREAK(particles_storage->particles_get_mode(pt->particles) != RS::PARTICLES_MODE_2D); particles_storage->particles_request_process(pt->particles); - if (particles_storage->particles_is_inactive(pt->particles)) { + if (particles_storage->particles_is_inactive(pt->particles) || particles_storage->particles_get_frame_counter(pt->particles) == 0) { break; } RenderingServerDefault::redraw_request(); // active particles means redraw request - bool local_coords = true; int dpc = particles_storage->particles_get_draw_passes(pt->particles); if (dpc == 0) { break; //nothing to draw @@ -818,12 +817,7 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend if (particles_storage->particles_has_collision(pt->particles) && texture_storage->render_target_is_sdf_enabled(p_render_target)) { //pass collision information - Transform2D xform; - if (local_coords) { - xform = p_item->final_transform; - } else { - xform = p_canvas_transform_inverse; - } + Transform2D xform = p_item->final_transform; RID sdf_texture = texture_storage->render_target_get_sdf_texture(p_render_target); @@ -839,6 +833,9 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend } else { particles_storage->particles_set_canvas_sdf_collision(pt->particles, false, Transform2D(), Rect2(), RID()); } + + // Signal that SDF texture needs to be updated. + r_sdf_used |= particles_storage->particles_has_collision(pt->particles); } if (mesh.is_null()) { @@ -1051,7 +1048,7 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo return uniform_set; } -void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool p_to_backbuffer) { +void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool &r_sdf_used, bool p_to_backbuffer) { RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); @@ -1139,6 +1136,7 @@ void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_co // Update uniform set. if (material_data->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(material_data->uniform_set)) { // Material may not have a uniform set. RD::get_singleton()->draw_list_bind_uniform_set(draw_list, material_data->uniform_set, MATERIAL_UNIFORM_SET); + material_data->set_as_used(); } } else { pipeline_variants = &shader.pipeline_variants; @@ -1148,7 +1146,7 @@ void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_co } } - _render_item(draw_list, p_to_render_target, ci, fb_format, canvas_transform_inverse, current_clip, p_lights, pipeline_variants); + _render_item(draw_list, p_to_render_target, ci, fb_format, canvas_transform_inverse, current_clip, p_lights, pipeline_variants, r_sdf_used); prev_material = material; } @@ -1446,7 +1444,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p update_skeletons = false; } - _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list); + _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, r_sdf_used); item_count = 0; if (ci->canvas_group_owner->canvas_group->mode != RS::CANVAS_GROUP_MODE_TRANSPARENT) { @@ -1478,7 +1476,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p update_skeletons = false; } - _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, true); + _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, r_sdf_used, true); item_count = 0; if (ci->canvas_group->blur_mipmaps) { @@ -1497,7 +1495,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p update_skeletons = false; } - _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list); + _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, r_sdf_used); item_count = 0; texture_storage->render_target_copy_to_back_buffer(p_to_render_target, back_buffer_rect, backbuffer_gen_mipmaps); @@ -1523,7 +1521,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p update_skeletons = false; } - _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list); + _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, r_sdf_used, false); //then reset item_count = 0; } @@ -2004,10 +2002,6 @@ void RendererCanvasRenderRD::occluder_polygon_set_cull_mode(RID p_occluder, RS:: oc->cull_mode = p_mode; } -void RendererCanvasRenderRD::CanvasShaderData::set_path_hint(const String &p_path) { - path = p_path; -} - void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) { //compile @@ -2219,86 +2213,6 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) { valid = true; } -void RendererCanvasRenderRD::CanvasShaderData::set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index) { - if (!p_texture.is_valid()) { - if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) { - default_texture_params[p_name].erase(p_index); - - if (default_texture_params[p_name].is_empty()) { - default_texture_params.erase(p_name); - } - } - } else { - if (!default_texture_params.has(p_name)) { - default_texture_params[p_name] = HashMap<int, RID>(); - } - default_texture_params[p_name][p_index] = p_texture; - } -} - -void RendererCanvasRenderRD::CanvasShaderData::get_shader_uniform_list(List<PropertyInfo> *p_param_list) const { - HashMap<int, StringName> order; - - for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { - if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL || - E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE || - E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE || - E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) { - // Don't expose any of these. - continue; - } - if (E.value.texture_order >= 0) { - order[E.value.texture_order + 100000] = E.key; - } else { - order[E.value.order] = E.key; - } - } - - String last_group; - for (const KeyValue<int, StringName> &E : order) { - String group = uniforms[E.value].group; - if (!uniforms[E.value].subgroup.is_empty()) { - group += "::" + uniforms[E.value].subgroup; - } - - if (group != last_group) { - PropertyInfo pi; - pi.usage = PROPERTY_USAGE_GROUP; - pi.name = group; - p_param_list->push_back(pi); - - last_group = group; - } - - PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]); - pi.name = E.value; - p_param_list->push_back(pi); - } -} - -void RendererCanvasRenderRD::CanvasShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const { - for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { - if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { - continue; - } - - RendererMaterialStorage::InstanceShaderParam p; - p.info = ShaderLanguage::uniform_to_property_info(E.value); - p.info.name = E.key; //supply name - p.index = E.value.instance_index; - p.default_value = ShaderLanguage::constant_value_to_variant(E.value.default_value, E.value.type, E.value.array_size, E.value.hint); - p_param_list->push_back(p); - } -} - -bool RendererCanvasRenderRD::CanvasShaderData::is_parameter_texture(const StringName &p_param) const { - if (!uniforms.has(p_param)) { - return false; - } - - return uniforms[p_param].texture_order >= 0; -} - bool RendererCanvasRenderRD::CanvasShaderData::is_animated() const { return false; } @@ -2307,15 +2221,6 @@ bool RendererCanvasRenderRD::CanvasShaderData::casts_shadows() const { return false; } -Variant RendererCanvasRenderRD::CanvasShaderData::get_default_parameter(const StringName &p_parameter) const { - if (uniforms.has(p_parameter)) { - ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter]; - Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value; - return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.array_size, uniform.hint); - } - return Variant(); -} - RS::ShaderNativeSourceCode RendererCanvasRenderRD::CanvasShaderData::get_native_source_code() const { RendererCanvasRenderRD *canvas_singleton = static_cast<RendererCanvasRenderRD *>(RendererCanvasRender::singleton); return canvas_singleton->shader.canvas_shader.version_get_native_source_code(version); @@ -2681,16 +2586,6 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() { primitive_arrays.index_array[3] = shader.quad_index_array = RD::get_singleton()->index_array_create(shader.quad_index_buffer, 0, 6); } - { //default skeleton buffer - - shader.default_skeleton_uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SkeletonUniform)); - SkeletonUniform su; - _update_transform_2d_to_mat4(Transform2D(), su.skeleton_inverse); - _update_transform_2d_to_mat4(Transform2D(), su.skeleton_transform); - RD::get_singleton()->buffer_update(shader.default_skeleton_uniform_buffer, 0, sizeof(SkeletonUniform), &su); - - shader.default_skeleton_texture_buffer = RD::get_singleton()->texture_buffer_create(32, RD::DATA_FORMAT_R32G32B32A32_SFLOAT); - } { //default shadow texture to keep uniform set happy RD::TextureFormat tf; @@ -2834,8 +2729,6 @@ RendererCanvasRenderRD::~RendererCanvasRenderRD() { memdelete_arr(state.light_uniforms); RD::get_singleton()->free(state.lights_uniform_buffer); - RD::get_singleton()->free(shader.default_skeleton_uniform_buffer); - RD::get_singleton()->free(shader.default_skeleton_texture_buffer); } //shadow rendering diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h index d1f3c9ec6a..f809c7f046 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h @@ -144,10 +144,6 @@ class RendererCanvasRenderRD : public RendererCanvasRender { RID quad_index_array; PipelineVariants pipeline_variants; - // default_skeleton uniform set - RID default_skeleton_uniform_buffer; - RID default_skeleton_texture_buffer; - ShaderCompiler compiler; } shader; @@ -164,16 +160,13 @@ class RendererCanvasRenderRD : public RendererCanvasRender { bool valid = false; RID version; PipelineVariants pipeline_variants; - String path; - HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms; Vector<uint32_t> ubo_offsets; uint32_t ubo_size = 0; String code; - HashMap<StringName, HashMap<int, RID>> default_texture_params; bool uses_screen_texture = false; bool uses_screen_texture_mipmaps = false; @@ -181,15 +174,8 @@ class RendererCanvasRenderRD : public RendererCanvasRender { bool uses_time = false; virtual void set_code(const String &p_Code); - virtual void set_path_hint(const String &p_path); - virtual void set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index); - virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const; - virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; - - virtual bool is_parameter_texture(const StringName &p_param) const; virtual bool is_animated() const; virtual bool casts_shadows() const; - virtual Variant get_default_parameter(const StringName &p_parameter) const; virtual RS::ShaderNativeSourceCode get_native_source_code() const; CanvasShaderData() {} @@ -409,11 +395,6 @@ class RendererCanvasRenderRD : public RendererCanvasRender { uint32_t lights[4]; }; - struct SkeletonUniform { - float skeleton_transform[16]; - float skeleton_inverse[16]; - }; - Item *items[MAX_RENDER_ITEMS]; bool using_directional_lights = false; @@ -430,8 +411,8 @@ class RendererCanvasRenderRD : public RendererCanvasRender { RID _create_base_uniform_set(RID p_to_render_target, bool p_backbuffer); inline void _bind_canvas_texture(RD::DrawListID p_draw_list, RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID &r_last_texture, PushConstant &push_constant, Size2 &r_texpixel_size); //recursive, so regular inline used instead. - void _render_item(RenderingDevice::DrawListID p_draw_list, RID p_render_target, const Item *p_item, RenderingDevice::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, Light *p_lights, PipelineVariants *p_pipeline_variants); - void _render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool p_to_backbuffer = false); + void _render_item(RenderingDevice::DrawListID p_draw_list, RID p_render_target, const Item *p_item, RenderingDevice::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, Light *p_lights, PipelineVariants *p_pipeline_variants, bool &r_sdf_used); + void _render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool &r_sdf_used, bool p_to_backbuffer = false); _FORCE_INLINE_ void _update_transform_2d_to_mat2x4(const Transform2D &p_transform, float *p_mat2x4); _FORCE_INLINE_ void _update_transform_2d_to_mat2x3(const Transform2D &p_transform, float *p_mat2x3); diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp index 3289bfb0ea..f488fd63fe 100644 --- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp @@ -174,13 +174,19 @@ void RendererCompositorRD::set_boot_image(const Ref<Image> &p_image, const Color texture_storage->texture_2d_initialize(texture, p_image); RID rd_texture = texture_storage->texture_get_rd_texture(texture); + RD::SamplerState sampler_state; + sampler_state.min_filter = p_use_filter ? RD::SAMPLER_FILTER_LINEAR : RD::SAMPLER_FILTER_NEAREST; + sampler_state.mag_filter = p_use_filter ? RD::SAMPLER_FILTER_LINEAR : RD::SAMPLER_FILTER_NEAREST; + sampler_state.max_lod = 0; + RID sampler = RD::get_singleton()->sampler_create(sampler_state); + RID uset; { Vector<RD::Uniform> uniforms; RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; u.binding = 0; - u.append_id(blit.sampler); + u.append_id(sampler); u.append_id(rd_texture); uniforms.push_back(u); uset = RD::get_singleton()->uniform_set_create(uniforms, blit.shader.version_get_shader(blit.shader_version, BLIT_MODE_NORMAL), 0); @@ -241,6 +247,7 @@ void RendererCompositorRD::set_boot_image(const Ref<Image> &p_image, const Color RD::get_singleton()->swap_buffers(); texture_storage->texture_free(texture); + RD::get_singleton()->free(sampler); } RendererCompositorRD *RendererCompositorRD::singleton = nullptr; diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index 75fe84f46b..1242c11bea 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -51,99 +51,6 @@ void get_vogel_disk(float *r_kernel, int p_sample_count) { } } -void RendererSceneRenderRD::sdfgi_update(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, const Vector3 &p_world_position) { - Ref<RenderSceneBuffersRD> rb = p_render_buffers; - ERR_FAIL_COND(rb.is_null()); - Ref<RendererRD::GI::SDFGI> sdfgi; - if (rb->has_custom_data(RB_SCOPE_SDFGI)) { - sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI); - } - - bool needs_sdfgi = p_environment.is_valid() && environment_get_sdfgi_enabled(p_environment); - - if (!needs_sdfgi) { - if (sdfgi.is_valid()) { - // delete it - sdfgi.unref(); - rb->set_custom_data(RB_SCOPE_SDFGI, sdfgi); - } - return; - } - - static const uint32_t history_frames_to_converge[RS::ENV_SDFGI_CONVERGE_MAX] = { 5, 10, 15, 20, 25, 30 }; - uint32_t requested_history_size = history_frames_to_converge[gi.sdfgi_frames_to_converge]; - - if (sdfgi.is_valid() && (sdfgi->num_cascades != environment_get_sdfgi_cascades(p_environment) || sdfgi->min_cell_size != environment_get_sdfgi_min_cell_size(p_environment) || requested_history_size != sdfgi->history_size || sdfgi->uses_occlusion != environment_get_sdfgi_use_occlusion(p_environment) || sdfgi->y_scale_mode != environment_get_sdfgi_y_scale(p_environment))) { - //configuration changed, erase - sdfgi.unref(); - rb->set_custom_data(RB_SCOPE_SDFGI, sdfgi); - } - - if (sdfgi.is_null()) { - // re-create - sdfgi = gi.create_sdfgi(p_environment, p_world_position, requested_history_size); - rb->set_custom_data(RB_SCOPE_SDFGI, sdfgi); - } else { - //check for updates - sdfgi->update(p_environment, p_world_position); - } -} - -int RendererSceneRenderRD::sdfgi_get_pending_region_count(const Ref<RenderSceneBuffers> &p_render_buffers) const { - Ref<RenderSceneBuffersRD> rb = p_render_buffers; - ERR_FAIL_COND_V(rb.is_null(), 0); - - if (!rb->has_custom_data(RB_SCOPE_SDFGI)) { - return 0; - } - Ref<RendererRD::GI::SDFGI> sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI); - - int dirty_count = 0; - for (uint32_t i = 0; i < sdfgi->cascades.size(); i++) { - const RendererRD::GI::SDFGI::Cascade &c = sdfgi->cascades[i]; - - if (c.dirty_regions == RendererRD::GI::SDFGI::Cascade::DIRTY_ALL) { - dirty_count++; - } else { - for (int j = 0; j < 3; j++) { - if (c.dirty_regions[j] != 0) { - dirty_count++; - } - } - } - } - - return dirty_count; -} - -AABB RendererSceneRenderRD::sdfgi_get_pending_region_bounds(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const { - AABB bounds; - Vector3i from; - Vector3i size; - - Ref<RenderSceneBuffersRD> rb = p_render_buffers; - ERR_FAIL_COND_V(rb.is_null(), AABB()); - Ref<RendererRD::GI::SDFGI> sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI); - ERR_FAIL_COND_V(sdfgi.is_null(), AABB()); - - int c = sdfgi->get_pending_region_data(p_region, from, size, bounds); - ERR_FAIL_COND_V(c == -1, AABB()); - return bounds; -} - -uint32_t RendererSceneRenderRD::sdfgi_get_pending_region_cascade(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const { - AABB bounds; - Vector3i from; - Vector3i size; - - Ref<RenderSceneBuffersRD> rb = p_render_buffers; - ERR_FAIL_COND_V(rb.is_null(), -1); - Ref<RendererRD::GI::SDFGI> sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI); - ERR_FAIL_COND_V(sdfgi.is_null(), -1); - - return sdfgi->get_pending_region_data(p_region, from, size, bounds); -} - RID RendererSceneRenderRD::sky_allocate() { return sky.allocate_sky_rid(); } @@ -171,10 +78,6 @@ void RendererSceneRenderRD::environment_glow_set_use_bicubic_upscale(bool p_enab glow_bicubic_upscale = p_enable; } -void RendererSceneRenderRD::environment_glow_set_use_high_quality(bool p_enable) { - glow_high_quality = p_enable; -} - void RendererSceneRenderRD::environment_set_volumetric_fog_volume_size(int p_size, int p_depth) { volumetric_fog_size = p_size; volumetric_fog_depth = p_depth; @@ -599,20 +502,20 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende RID source = rb->get_internal_texture(l); RID dest = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, l, i); if (can_use_storage) { - copy_effects->gaussian_glow(source, dest, vp_size, environment_get_glow_strength(p_render_data->environment), glow_high_quality, true, environment_get_glow_hdr_luminance_cap(p_render_data->environment), environment_get_exposure(p_render_data->environment), environment_get_glow_bloom(p_render_data->environment), environment_get_glow_hdr_bleed_threshold(p_render_data->environment), environment_get_glow_hdr_bleed_scale(p_render_data->environment), luminance_texture, auto_exposure_scale); + copy_effects->gaussian_glow(source, dest, vp_size, environment_get_glow_strength(p_render_data->environment), true, environment_get_glow_hdr_luminance_cap(p_render_data->environment), environment_get_exposure(p_render_data->environment), environment_get_glow_bloom(p_render_data->environment), environment_get_glow_hdr_bleed_threshold(p_render_data->environment), environment_get_glow_hdr_bleed_scale(p_render_data->environment), luminance_texture, auto_exposure_scale); } else { RID half = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_HALF_BLUR, 0, i); // we can reuse this for each view - copy_effects->gaussian_glow_raster(source, half, dest, luminance_multiplier, vp_size, environment_get_glow_strength(p_render_data->environment), glow_high_quality, true, environment_get_glow_hdr_luminance_cap(p_render_data->environment), environment_get_exposure(p_render_data->environment), environment_get_glow_bloom(p_render_data->environment), environment_get_glow_hdr_bleed_threshold(p_render_data->environment), environment_get_glow_hdr_bleed_scale(p_render_data->environment), luminance_texture, auto_exposure_scale); + copy_effects->gaussian_glow_raster(source, half, dest, luminance_multiplier, vp_size, environment_get_glow_strength(p_render_data->environment), true, environment_get_glow_hdr_luminance_cap(p_render_data->environment), environment_get_exposure(p_render_data->environment), environment_get_glow_bloom(p_render_data->environment), environment_get_glow_hdr_bleed_threshold(p_render_data->environment), environment_get_glow_hdr_bleed_scale(p_render_data->environment), luminance_texture, auto_exposure_scale); } } else { RID source = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, l, i - 1); RID dest = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, l, i); if (can_use_storage) { - copy_effects->gaussian_glow(source, dest, vp_size, environment_get_glow_strength(p_render_data->environment), glow_high_quality); + copy_effects->gaussian_glow(source, dest, vp_size, environment_get_glow_strength(p_render_data->environment)); } else { RID half = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_HALF_BLUR, 0, i); // we can reuse this for each view - copy_effects->gaussian_glow_raster(source, half, dest, luminance_multiplier, vp_size, environment_get_glow_strength(p_render_data->environment), glow_high_quality); + copy_effects->gaussian_glow_raster(source, half, dest, luminance_multiplier, vp_size, environment_get_glow_strength(p_render_data->environment)); } } } @@ -1006,10 +909,20 @@ bool RendererSceneRenderRD::is_using_radiance_cubemap_array() const { } void RendererSceneRenderRD::_update_vrs(Ref<RenderSceneBuffersRD> p_render_buffers) { - if (p_render_buffers.is_valid() && vrs) { + if (p_render_buffers.is_null()) { + return; + } + + RID render_target = p_render_buffers->get_render_target(); + if (render_target.is_null()) { + // must be rendering reflection probes + return; + } + + if (vrs) { RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); - RS::ViewportVRSMode vrs_mode = texture_storage->render_target_get_vrs_mode(p_render_buffers->get_render_target()); + RS::ViewportVRSMode vrs_mode = texture_storage->render_target_get_vrs_mode(render_target); if (vrs_mode != RS::VIEWPORT_VRS_DISABLED) { RID vrs_texture = p_render_buffers->get_texture(RB_SCOPE_VRS, RB_TEXTURE); @@ -1078,6 +991,7 @@ void RendererSceneRenderRD::render_scene(const Ref<RenderSceneBuffers> &p_render scene_data.cam_transform = p_camera_data->main_transform; scene_data.cam_projection = p_camera_data->main_projection; scene_data.cam_orthogonal = p_camera_data->is_orthogonal; + scene_data.camera_visible_layers = p_camera_data->visible_layers; scene_data.taa_jitter = p_camera_data->taa_jitter; scene_data.view_count = p_camera_data->view_count; @@ -1160,7 +1074,7 @@ void RendererSceneRenderRD::render_scene(const Ref<RenderSceneBuffers> &p_render } Color clear_color; - if (p_render_buffers.is_valid()) { + if (p_render_buffers.is_valid() && p_reflection_probe.is_null()) { clear_color = texture_storage->render_target_get_clear_request_color(rb->get_render_target()); } else { clear_color = RSG::texture_storage->get_default_clear_color(); @@ -1400,7 +1314,6 @@ void RendererSceneRenderRD::init() { screen_space_roughness_limiter_amount = GLOBAL_GET("rendering/anti_aliasing/screen_space_roughness_limiter/amount"); screen_space_roughness_limiter_limit = GLOBAL_GET("rendering/anti_aliasing/screen_space_roughness_limiter/limit"); glow_bicubic_upscale = int(GLOBAL_GET("rendering/environment/glow/upscale_mode")) > 0; - glow_high_quality = GLOBAL_GET("rendering/environment/glow/use_high_quality"); directional_penumbra_shadow_kernel = memnew_arr(float, 128); directional_soft_shadow_kernel = memnew_arr(float, 128); @@ -1418,10 +1331,13 @@ void RendererSceneRenderRD::init() { cull_argument.set_page_pool(&cull_argument_pool); bool can_use_storage = _render_buffers_can_be_storage(); + bool can_use_vrs = is_vrs_supported(); bokeh_dof = memnew(RendererRD::BokehDOF(!can_use_storage)); copy_effects = memnew(RendererRD::CopyEffects(!can_use_storage)); tone_mapper = memnew(RendererRD::ToneMapper); - vrs = memnew(RendererRD::VRS); + if (can_use_vrs) { + vrs = memnew(RendererRD::VRS); + } if (can_use_storage) { fsr = memnew(RendererRD::FSR); } diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h index 2312603829..704cb37c91 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h @@ -114,7 +114,6 @@ protected: /* ENVIRONMENT */ bool glow_bicubic_upscale = false; - bool glow_high_quality = false; bool use_physical_light_units = false; @@ -218,14 +217,6 @@ public: RendererRD::SkyRD *get_sky() { return &sky; } - /* SDFGI UPDATE */ - - virtual void sdfgi_update(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, const Vector3 &p_world_position) override; - virtual int sdfgi_get_pending_region_count(const Ref<RenderSceneBuffers> &p_render_buffers) const override; - virtual AABB sdfgi_get_pending_region_bounds(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const override; - virtual uint32_t sdfgi_get_pending_region_cascade(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const override; - RID sdfgi_get_ubo() const { return gi.sdfgi_ubo; } - /* SKY API */ virtual RID sky_allocate() override; @@ -239,7 +230,6 @@ public: /* ENVIRONMENT API */ virtual void environment_glow_set_use_bicubic_upscale(bool p_enable) override; - virtual void environment_glow_set_use_high_quality(bool p_enable) override; virtual void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) override; virtual void environment_set_volumetric_fog_filter_active(bool p_enable) override; diff --git a/servers/rendering/renderer_rd/shaders/canvas.glsl b/servers/rendering/renderer_rd/shaders/canvas.glsl index 8593e6b265..eb5f68849e 100644 --- a/servers/rendering/renderer_rd/shaders/canvas.glsl +++ b/servers/rendering/renderer_rd/shaders/canvas.glsl @@ -191,48 +191,6 @@ void main() { uv += 1e-5; } -#ifdef USE_ATTRIBUTES -#if 0 - if (bool(draw_data.flags & FLAGS_USE_SKELETON) && bone_weights != vec4(0.0)) { //must be a valid bone - //skeleton transform - ivec4 bone_indicesi = ivec4(bone_indices); - - uvec2 tex_ofs = bone_indicesi.x * 2; - - mat2x4 m; - m = mat2x4( - texelFetch(skeleton_buffer, tex_ofs + 0), - texelFetch(skeleton_buffer, tex_ofs + 1)) * - bone_weights.x; - - tex_ofs = bone_indicesi.y * 2; - - m += mat2x4( - texelFetch(skeleton_buffer, tex_ofs + 0), - texelFetch(skeleton_buffer, tex_ofs + 1)) * - bone_weights.y; - - tex_ofs = bone_indicesi.z * 2; - - m += mat2x4( - texelFetch(skeleton_buffer, tex_ofs + 0), - texelFetch(skeleton_buffer, tex_ofs + 1)) * - bone_weights.z; - - tex_ofs = bone_indicesi.w * 2; - - m += mat2x4( - texelFetch(skeleton_buffer, tex_ofs + 0), - texelFetch(skeleton_buffer, tex_ofs + 1)) * - bone_weights.w; - - mat4 bone_matrix = skeleton_data.skeleton_transform * transpose(mat4(m[0], m[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))) * skeleton_data.skeleton_transform_inverse; - - //outvec = bone_matrix * outvec; - } -#endif -#endif - vertex = (canvas_data.canvas_transform * vec4(vertex, 0.0, 1.0)).xy; vertex_interp = vertex; diff --git a/servers/rendering/renderer_rd/shaders/cluster_render.glsl b/servers/rendering/renderer_rd/shaders/cluster_render.glsl index 932312de82..8c26a67926 100644 --- a/servers/rendering/renderer_rd/shaders/cluster_render.glsl +++ b/servers/rendering/renderer_rd/shaders/cluster_render.glsl @@ -142,7 +142,11 @@ void main() { } } #else - if (!gl_HelperInvocation) { +// MoltenVK/Metal fails to compile shaders using gl_HelperInvocation for some GPUs +#ifndef MOLTENVK_USED + if (!gl_HelperInvocation) +#endif + { atomicOr(cluster_render.data[usage_write_offset], usage_write_bit); } #endif @@ -162,7 +166,11 @@ void main() { } } #else - if (!gl_HelperInvocation) { +// MoltenVK/Metal fails to compile shaders using gl_HelperInvocation for some GPUs +#ifndef MOLTENVK_USED + if (!gl_HelperInvocation) +#endif + { atomicOr(cluster_render.data[z_write_offset], z_write_bit); } #endif diff --git a/servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl b/servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl index cb06250cf2..31aabbe9d2 100644 --- a/servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl @@ -53,30 +53,31 @@ void main() { #ifdef MODE_GAUSSIAN_BLUR - // Simpler blur uses SIGMA2 for the gaussian kernel for a stronger effect - - // note, for blur blur.luminance_multiplier is irrelavant, we would be multiplying and then dividing by this amount. - - if (bool(blur.flags & FLAG_HORIZONTAL)) { - vec2 pix_size = blur.pixel_size; - pix_size *= 0.5; //reading from larger buffer, so use more samples - vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.214607; - color += texture(source_color, uv_interp + vec2(1.0, 0.0) * pix_size) * 0.189879; - color += texture(source_color, uv_interp + vec2(2.0, 0.0) * pix_size) * 0.131514; - color += texture(source_color, uv_interp + vec2(3.0, 0.0) * pix_size) * 0.071303; - color += texture(source_color, uv_interp + vec2(-1.0, 0.0) * pix_size) * 0.189879; - color += texture(source_color, uv_interp + vec2(-2.0, 0.0) * pix_size) * 0.131514; - color += texture(source_color, uv_interp + vec2(-3.0, 0.0) * pix_size) * 0.071303; - frag_color = color; - } else { - vec2 pix_size = blur.pixel_size; - vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.38774; - color += texture(source_color, uv_interp + vec2(0.0, 1.0) * pix_size) * 0.24477; - color += texture(source_color, uv_interp + vec2(0.0, 2.0) * pix_size) * 0.06136; - color += texture(source_color, uv_interp + vec2(0.0, -1.0) * pix_size) * 0.24477; - color += texture(source_color, uv_interp + vec2(0.0, -2.0) * pix_size) * 0.06136; - frag_color = color; - } + // For Gaussian Blur we use 13 taps in a single pass instead of 12 taps over 2 passes. + // This minimizes the number of times we change framebuffers which is very important for mobile. + // Source: http://www.iryoku.com/next-generation-post-processing-in-call-of-duty-advanced-warfare + vec4 A = texture(source_color, uv_interp + blur.pixel_size * vec2(-1.0, -1.0)); + vec4 B = texture(source_color, uv_interp + blur.pixel_size * vec2(0.0, -1.0)); + vec4 C = texture(source_color, uv_interp + blur.pixel_size * vec2(1.0, -1.0)); + vec4 D = texture(source_color, uv_interp + blur.pixel_size * vec2(-0.5, -0.5)); + vec4 E = texture(source_color, uv_interp + blur.pixel_size * vec2(0.5, -0.5)); + vec4 F = texture(source_color, uv_interp + blur.pixel_size * vec2(-1.0, 0.0)); + vec4 G = texture(source_color, uv_interp); + vec4 H = texture(source_color, uv_interp + blur.pixel_size * vec2(1.0, 0.0)); + vec4 I = texture(source_color, uv_interp + blur.pixel_size * vec2(-0.5, 0.5)); + vec4 J = texture(source_color, uv_interp + blur.pixel_size * vec2(0.5, 0.5)); + vec4 K = texture(source_color, uv_interp + blur.pixel_size * vec2(-1.0, 1.0)); + vec4 L = texture(source_color, uv_interp + blur.pixel_size * vec2(0.0, 1.0)); + vec4 M = texture(source_color, uv_interp + blur.pixel_size * vec2(1.0, 1.0)); + + float base_weight = 0.5 / 4.0; + float lesser_weight = 0.125 / 4.0; + + frag_color = (D + E + I + J) * base_weight; + frag_color += (A + B + G + F) * lesser_weight; + frag_color += (B + C + H + G) * lesser_weight; + frag_color += (F + G + L + K) * lesser_weight; + frag_color += (G + H + M + L) * lesser_weight; #endif #ifdef MODE_GAUSSIAN_GLOW diff --git a/servers/rendering/renderer_rd/shaders/effects/copy.glsl b/servers/rendering/renderer_rd/shaders/effects/copy.glsl index bfe329b8ec..3a82861057 100644 --- a/servers/rendering/renderer_rd/shaders/effects/copy.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/copy.glsl @@ -14,8 +14,7 @@ layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; #define FLAG_FLIP_Y (1 << 5) #define FLAG_FORCE_LUMINANCE (1 << 6) #define FLAG_COPY_ALL_SOURCE (1 << 7) -#define FLAG_HIGH_QUALITY_GLOW (1 << 8) -#define FLAG_ALPHA_TO_ONE (1 << 9) +#define FLAG_ALPHA_TO_ONE (1 << 8) layout(push_constant, std430) uniform Params { ivec4 section; @@ -93,25 +92,14 @@ void main() { #ifdef MODE_GAUSSIAN_BLUR // First pass copy texture into 16x16 local memory for every 8x8 thread block - vec2 quad_center_uv = clamp(vec2(gl_GlobalInvocationID.xy + gl_LocalInvocationID.xy - 3.5) / params.section.zw, vec2(0.5 / params.section.zw), vec2(1.0 - 1.5 / params.section.zw)); + vec2 quad_center_uv = clamp(vec2(params.section.xy + gl_GlobalInvocationID.xy + gl_LocalInvocationID.xy - 3.5) / params.section.zw, vec2(0.5 / params.section.zw), vec2(1.0 - 1.5 / params.section.zw)); uint dest_index = gl_LocalInvocationID.x * 2 + gl_LocalInvocationID.y * 2 * 16; -#ifdef MODE_GLOW - if (bool(params.flags & FLAG_HIGH_QUALITY_GLOW)) { - vec2 quad_offset_uv = clamp((vec2(gl_GlobalInvocationID.xy + gl_LocalInvocationID.xy - 3.0)) / params.section.zw, vec2(0.5 / params.section.zw), vec2(1.0 - 1.5 / params.section.zw)); - - local_cache[dest_index] = (textureLod(source_color, quad_center_uv, 0) + textureLod(source_color, quad_offset_uv, 0)) * 0.5; - local_cache[dest_index + 1] = (textureLod(source_color, quad_center_uv + vec2(1.0 / params.section.z, 0.0), 0) + textureLod(source_color, quad_offset_uv + vec2(1.0 / params.section.z, 0.0), 0)) * 0.5; - local_cache[dest_index + 16] = (textureLod(source_color, quad_center_uv + vec2(0.0, 1.0 / params.section.w), 0) + textureLod(source_color, quad_offset_uv + vec2(0.0, 1.0 / params.section.w), 0)) * 0.5; - local_cache[dest_index + 16 + 1] = (textureLod(source_color, quad_center_uv + vec2(1.0 / params.section.zw), 0) + textureLod(source_color, quad_offset_uv + vec2(1.0 / params.section.zw), 0)) * 0.5; - } else -#endif - { - local_cache[dest_index] = textureLod(source_color, quad_center_uv, 0); - local_cache[dest_index + 1] = textureLod(source_color, quad_center_uv + vec2(1.0 / params.section.z, 0.0), 0); - local_cache[dest_index + 16] = textureLod(source_color, quad_center_uv + vec2(0.0, 1.0 / params.section.w), 0); - local_cache[dest_index + 16 + 1] = textureLod(source_color, quad_center_uv + vec2(1.0 / params.section.zw), 0); - } + local_cache[dest_index] = textureLod(source_color, quad_center_uv, 0); + local_cache[dest_index + 1] = textureLod(source_color, quad_center_uv + vec2(1.0 / params.section.z, 0.0), 0); + local_cache[dest_index + 16] = textureLod(source_color, quad_center_uv + vec2(0.0, 1.0 / params.section.w), 0); + local_cache[dest_index + 16 + 1] = textureLod(source_color, quad_center_uv + vec2(1.0 / params.section.zw), 0); + #ifdef MODE_GLOW if (bool(params.flags & FLAG_GLOW_FIRST_PASS)) { // Tonemap initial samples to reduce weight of fireflies: https://graphicrants.blogspot.com/2013/12/tone-mapping.html @@ -194,10 +182,10 @@ void main() { color = min(color * feedback, vec4(params.glow_luminance_cap)); } -#endif +#endif // MODE_GLOW imageStore(dest_buffer, pos + params.target, color); -#endif +#endif // MODE_GAUSSIAN_BLUR #ifdef MODE_SIMPLE_COPY @@ -227,7 +215,7 @@ void main() { imageStore(dest_buffer, pos + params.target, color); -#endif +#endif // MODE_SIMPLE_COPY #ifdef MODE_SIMPLE_COPY_DEPTH @@ -239,7 +227,7 @@ void main() { imageStore(dest_buffer, pos + params.target, vec4(color.r)); -#endif +#endif // MODE_SIMPLE_COPY_DEPTH #ifdef MODE_LINEARIZE_DEPTH_COPY @@ -253,7 +241,7 @@ void main() { } imageStore(dest_buffer, pos + params.target, color); -#endif +#endif // MODE_LINEARIZE_DEPTH_COPY #if defined(MODE_CUBEMAP_TO_PANORAMA) || defined(MODE_CUBEMAP_ARRAY_TO_PANORAMA) @@ -276,7 +264,7 @@ void main() { vec4 color = textureLod(source_color, vec4(normal, params.camera_z_far), 0.0); //the biggest the lod the least the acne #endif imageStore(dest_buffer, pos + params.target, color); -#endif +#endif // defined(MODE_CUBEMAP_TO_PANORAMA) || defined(MODE_CUBEMAP_ARRAY_TO_PANORAMA) #ifdef MODE_SET_COLOR imageStore(dest_buffer, pos + params.target, params.set_color); diff --git a/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl b/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl index 1c17eabb56..6137224162 100644 --- a/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl @@ -13,6 +13,14 @@ #endif // has_VK_KHR_multiview #endif //MULTIVIEW +#define FLAG_FLIP_Y (1 << 0) +#define FLAG_USE_SECTION (1 << 1) +#define FLAG_FORCE_LUMINANCE (1 << 2) +#define FLAG_ALPHA_TO_ZERO (1 << 3) +#define FLAG_SRGB (1 << 4) +#define FLAG_ALPHA_TO_ONE (1 << 5) +#define FLAG_LINEAR (1 << 6) + #ifdef MULTIVIEW layout(location = 0) out vec3 uv_interp; #else @@ -22,11 +30,10 @@ layout(location = 0) out vec2 uv_interp; layout(push_constant, std430) uniform Params { vec4 section; vec2 pixel_size; - bool flip_y; - bool use_section; + float luminance_multiplier; + uint flags; - bool force_luminance; - uint pad[3]; + vec4 color; } params; @@ -37,13 +44,13 @@ void main() { uv_interp.z = ViewIndex; #endif vec2 vpos = uv_interp.xy; - if (params.use_section) { + if (bool(params.flags & FLAG_USE_SECTION)) { vpos = params.section.xy + vpos * params.section.zw; } gl_Position = vec4(vpos * 2.0 - 1.0, 0.0, 1.0); - if (params.flip_y) { + if (bool(params.flags & FLAG_FLIP_Y)) { uv_interp.y = 1.0 - uv_interp.y; } } @@ -63,19 +70,25 @@ void main() { #endif // has_VK_KHR_multiview #endif //MULTIVIEW +#define FLAG_FLIP_Y (1 << 0) +#define FLAG_USE_SECTION (1 << 1) +#define FLAG_FORCE_LUMINANCE (1 << 2) +#define FLAG_ALPHA_TO_ZERO (1 << 3) +#define FLAG_SRGB (1 << 4) +#define FLAG_ALPHA_TO_ONE (1 << 5) +#define FLAG_LINEAR (1 << 6) + layout(push_constant, std430) uniform Params { vec4 section; vec2 pixel_size; - bool flip_y; - bool use_section; + float luminance_multiplier; + uint flags; - bool force_luminance; - bool alpha_to_zero; - bool srgb; - uint pad; + vec4 color; } params; +#ifndef MODE_SET_COLOR #ifdef MULTIVIEW layout(location = 0) in vec3 uv_interp; #else @@ -94,6 +107,7 @@ layout(set = 0, binding = 0) uniform sampler2D source_color; layout(set = 1, binding = 0) uniform sampler2D source_color2; #endif /* MODE_TWO_SOURCES */ #endif /* MULTIVIEW */ +#endif /* !SET_COLOR */ layout(location = 0) out vec4 frag_color; @@ -104,7 +118,15 @@ vec3 linear_to_srgb(vec3 color) { return mix((vec3(1.0f) + a) * pow(color.rgb, vec3(1.0f / 2.4f)) - a, 12.92f * color.rgb, lessThan(color.rgb, vec3(0.0031308f))); } +vec3 srgb_to_linear(vec3 color) { + return mix(pow((color.rgb + vec3(0.055)) * (1.0 / (1.0 + 0.055)), vec3(2.4)), color.rgb * (1.0 / 12.92), lessThan(color.rgb, vec3(0.04045))); +} + void main() { +#ifdef MODE_SET_COLOR + frag_color = params.color; +#else + #ifdef MULTIVIEW vec3 uv = uv_interp; #else @@ -155,15 +177,22 @@ void main() { #endif /* MODE_TWO_SOURCES */ #endif /* MULTIVIEW */ - if (params.force_luminance) { + if (bool(params.flags & FLAG_FORCE_LUMINANCE)) { color.rgb = vec3(max(max(color.r, color.g), color.b)); } - if (params.alpha_to_zero) { + if (bool(params.flags & FLAG_ALPHA_TO_ZERO)) { color.rgb *= color.a; } - if (params.srgb) { + if (bool(params.flags & FLAG_SRGB)) { color.rgb = linear_to_srgb(color.rgb); } + if (bool(params.flags & FLAG_ALPHA_TO_ONE)) { + color.a = 1.0; + } + if (bool(params.flags & FLAG_LINEAR)) { + color.rgb = srgb_to_linear(color.rgb); + } - frag_color = color; + frag_color = color / params.luminance_multiplier; +#endif // MODE_SET_COLOR } diff --git a/servers/rendering/renderer_rd/shaders/effects/cubemap_roughness_inc.glsl b/servers/rendering/renderer_rd/shaders/effects/cubemap_roughness_inc.glsl index 1bee428a6f..c0597fe3f3 100644 --- a/servers/rendering/renderer_rd/shaders/effects/cubemap_roughness_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/cubemap_roughness_inc.glsl @@ -70,17 +70,6 @@ float DistributionGGX(float NdotH, float roughness4) { return roughness4 / denom; } -// https://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html -float GGX(float NdotV, float a) { - float k = a / 2.0; - return NdotV / (NdotV * (1.0 - k) + k); -} - -// https://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html -float G_Smith(float a, float nDotV, float nDotL) { - return GGX(nDotL, a * a) * GGX(nDotV, a * a); -} - float radicalInverse_VdC(uint bits) { bits = (bits << 16u) | (bits >> 16u); bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); diff --git a/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl index 9d8294a7da..631d1968b0 100644 --- a/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl @@ -66,6 +66,19 @@ void main() { vec4 normal_roughness = imageLoad(source_normal_roughness, ssC); vec3 normal = normal_roughness.xyz * 2.0 - 1.0; + float roughness = normal_roughness.w; + + // The roughness cutoff of 0.6 is chosen to match the roughness fadeout from GH-69828. + if (roughness > 0.6) { + // Do not compute SSR for rough materials to improve performance at the cost of + // subtle artifacting. +#ifdef MODE_ROUGH + imageStore(blur_radius_image, ssC, vec4(0.0)); +#endif + imageStore(ssr_image, ssC, vec4(0.0)); + return; + } + normal = normalize(normal); normal.y = -normal.y; //because this code reads flipped @@ -81,8 +94,6 @@ void main() { imageStore(ssr_image, ssC, vec4(0.0)); return; } - //ray_dir = normalize(view_dir - normal * dot(normal,view_dir) * 2.0); - //ray_dir = normalize(vec3(1.0, 1.0, -1.0)); //////////////// @@ -212,6 +223,9 @@ void main() { float grad = (steps_taken + 1.0) / float(params.num_steps); float initial_fade = params.curve_fade_in == 0.0 ? 1.0 : pow(clamp(grad, 0.0, 1.0), params.curve_fade_in); float fade = pow(clamp(1.0 - grad, 0.0, 1.0), params.distance_fade) * initial_fade; + // This is an ad-hoc term to fade out the SSR as roughness increases. Values used + // are meant to match the visual appearance of a ReflectionProbe. + float roughness_fade = smoothstep(0.4, 0.7, 1.0 - normal_roughness.w); final_pos = pos; vec4 final_color; @@ -220,7 +234,6 @@ void main() { // if roughness is enabled, do screen space cone tracing float blur_radius = 0.0; - float roughness = normal_roughness.w; if (roughness > 0.001) { float cone_angle = min(roughness, 0.999) * M_PI * 0.5; @@ -246,7 +259,7 @@ void main() { #endif // MODE_ROUGH - final_color = vec4(imageLoad(source_diffuse, ivec2(final_pos - 0.5)).rgb, fade * margin_blend); + final_color = vec4(imageLoad(source_diffuse, ivec2(final_pos - 0.5)).rgb, fade * margin_blend * roughness_fade); // Schlick term. float metallic = texelFetch(source_metallic, ssC << 1, 0).w; diff --git a/servers/rendering/renderer_rd/shaders/effects/vrs.glsl b/servers/rendering/renderer_rd/shaders/effects/vrs.glsl index 5ef83c0b44..b450bb9fe9 100644 --- a/servers/rendering/renderer_rd/shaders/effects/vrs.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/vrs.glsl @@ -63,10 +63,18 @@ void main() { #ifdef MULTIVIEW vec4 color = textureLod(source_color, uv, 0.0); + frag_color = uint(color.r * 255.0); #else /* MULTIVIEW */ vec4 color = textureLod(source_color, uv, 0.0); -#endif /* MULTIVIEW */ - // See if we can change the sampler to one that returns int... - frag_color = uint(color.r * 256.0); + // for user supplied VRS map we do a color mapping + color.r *= 3.0; + frag_color = int(color.r) << 2; + + color.g *= 3.0; + frag_color += int(color.g); + + // note 1x4, 4x1, 1x8, 8x1, 2x8 and 8x2 are not supported + // 4x8, 8x4 and 8x8 are only available on some GPUs +#endif /* MULTIVIEW */ } diff --git a/servers/rendering/renderer_rd/shaders/environment/gi.glsl b/servers/rendering/renderer_rd/shaders/environment/gi.glsl index ab927df678..459c4dcb1d 100644 --- a/servers/rendering/renderer_rd/shaders/environment/gi.glsl +++ b/servers/rendering/renderer_rd/shaders/environment/gi.glsl @@ -108,7 +108,9 @@ layout(set = 0, binding = 18, std140) uniform SceneData { } scene_data; +#ifdef USE_VRS layout(r8ui, set = 0, binding = 19) uniform restrict readonly uimage2D vrs_buffer; +#endif layout(push_constant, std430) uniform Params { uint max_voxel_gi_instances; @@ -661,6 +663,7 @@ void main() { ivec2 pos = ivec2(gl_GlobalInvocationID.xy); uint vrs_x, vrs_y; +#ifdef USE_VRS if (sc_use_vrs) { ivec2 vrs_pos; @@ -684,6 +687,7 @@ void main() { return; } } +#endif if (sc_half_res) { pos <<= 1; @@ -708,6 +712,7 @@ void main() { imageStore(ambient_buffer, pos, ambient_light); imageStore(reflection_buffer, pos, reflection_light); +#ifdef USE_VRS if (sc_use_vrs) { if (vrs_x > 1) { imageStore(ambient_buffer, pos + ivec2(1, 0), ambient_light); @@ -766,4 +771,5 @@ void main() { imageStore(reflection_buffer, pos + ivec2(3, 3), reflection_light); } } +#endif } diff --git a/servers/rendering/renderer_rd/shaders/environment/sky.glsl b/servers/rendering/renderer_rd/shaders/environment/sky.glsl index d523461600..bf974a3fd5 100644 --- a/servers/rendering/renderer_rd/shaders/environment/sky.glsl +++ b/servers/rendering/renderer_rd/shaders/environment/sky.glsl @@ -14,7 +14,7 @@ layout(location = 0) out vec2 uv_interp; layout(push_constant, std430) uniform Params { mat3 orientation; - vec4 projections[MAX_VIEWS]; + vec4 projection; // only applicable if not multiview vec3 position; float time; vec3 pad; @@ -54,7 +54,7 @@ layout(location = 0) in vec2 uv_interp; layout(push_constant, std430) uniform Params { mat3 orientation; - vec4 projections[MAX_VIEWS]; + vec4 projection; // only applicable if not multiview vec3 position; float time; vec3 pad; @@ -82,7 +82,10 @@ layout(set = 0, binding = 1, std430) restrict readonly buffer GlobalShaderUnifor } global_shader_uniforms; -layout(set = 0, binding = 2, std140) uniform SceneData { +layout(set = 0, binding = 2, std140) uniform SkySceneData { + mat4 view_inv_projections[2]; + vec4 view_eye_offsets[2]; + bool volumetric_fog_enabled; // 4 - 4 float volumetric_fog_inv_length; // 4 - 8 float volumetric_fog_detail_spread; // 4 - 12 @@ -101,7 +104,7 @@ layout(set = 0, binding = 2, std140) uniform SceneData { uint pad1; // 4 - 60 uint pad2; // 4 - 64 } -scene_data; +sky_scene_data; struct DirectionalLightData { vec4 direction_energy; @@ -124,6 +127,9 @@ layout(set = 2, binding = 0) uniform textureCube radiance; #ifdef USE_CUBEMAP_PASS layout(set = 2, binding = 1) uniform textureCube half_res; layout(set = 2, binding = 2) uniform textureCube quarter_res; +#elif defined(USE_MULTIVIEW) +layout(set = 2, binding = 1) uniform texture2DArray half_res; +layout(set = 2, binding = 2) uniform texture2DArray quarter_res; #else layout(set = 2, binding = 1) uniform texture2D half_res; layout(set = 2, binding = 2) uniform texture2D quarter_res; @@ -169,15 +175,15 @@ vec4 volumetric_fog_process(vec2 screen_uv) { } vec4 fog_process(vec3 view, vec3 sky_color) { - vec3 fog_color = mix(scene_data.fog_light_color, sky_color, scene_data.fog_aerial_perspective); + vec3 fog_color = mix(sky_scene_data.fog_light_color, sky_color, sky_scene_data.fog_aerial_perspective); - if (scene_data.fog_sun_scatter > 0.001) { + if (sky_scene_data.fog_sun_scatter > 0.001) { vec4 sun_scatter = vec4(0.0); float sun_total = 0.0; - for (uint i = 0; i < scene_data.directional_light_count; i++) { + for (uint i = 0; i < sky_scene_data.directional_light_count; i++) { vec3 light_color = directional_lights.data[i].color_size.xyz * directional_lights.data[i].direction_energy.w; float light_amount = pow(max(dot(view, directional_lights.data[i].direction_energy.xyz), 0.0), 8.0); - fog_color += light_color * light_amount * scene_data.fog_sun_scatter; + fog_color += light_color * light_amount * sky_scene_data.fog_sun_scatter; } } @@ -186,9 +192,17 @@ vec4 fog_process(vec3 view, vec3 sky_color) { void main() { vec3 cube_normal; +#ifdef USE_MULTIVIEW + // In multiview our projection matrices will contain positional and rotational offsets that we need to properly unproject. + vec4 unproject = vec4(uv_interp.x, -uv_interp.y, 1.0, 1.0); + vec4 unprojected = sky_scene_data.view_inv_projections[ViewIndex] * unproject; + cube_normal = unprojected.xyz / unprojected.w; + cube_normal += sky_scene_data.view_eye_offsets[ViewIndex].xyz; +#else cube_normal.z = -1.0; - cube_normal.x = (cube_normal.z * (-uv_interp.x - params.projections[ViewIndex].x)) / params.projections[ViewIndex].y; - cube_normal.y = -(cube_normal.z * (-uv_interp.y - params.projections[ViewIndex].z)) / params.projections[ViewIndex].w; + cube_normal.x = (cube_normal.z * (-uv_interp.x - params.projection.x)) / params.projection.y; + cube_normal.y = -(cube_normal.z * (-uv_interp.y - params.projection.z)) / params.projection.w; +#endif cube_normal = mat3(params.orientation) * cube_normal; cube_normal = normalize(cube_normal); @@ -209,20 +223,33 @@ void main() { vec4 custom_fog = vec4(0.0); #ifdef USE_CUBEMAP_PASS + #ifdef USES_HALF_RES_COLOR half_res_color = texture(samplerCube(half_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), cube_normal) / params.luminance_multiplier; #endif #ifdef USES_QUARTER_RES_COLOR quarter_res_color = texture(samplerCube(quarter_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), cube_normal) / params.luminance_multiplier; #endif + #else + #ifdef USES_HALF_RES_COLOR +#ifdef USE_MULTIVIEW + half_res_color = textureLod(sampler2DArray(half_res, material_samplers[SAMPLER_LINEAR_CLAMP]), vec3(uv, ViewIndex), 0.0) / params.luminance_multiplier; +#else half_res_color = textureLod(sampler2D(half_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0) / params.luminance_multiplier; -#endif +#endif // USE_MULTIVIEW +#endif // USES_HALF_RES_COLOR + #ifdef USES_QUARTER_RES_COLOR +#ifdef USE_MULTIVIEW + quarter_res_color = textureLod(sampler2DArray(quarter_res, material_samplers[SAMPLER_LINEAR_CLAMP]), vec3(uv, ViewIndex), 0.0) / params.luminance_multiplier; +#else quarter_res_color = textureLod(sampler2D(quarter_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0) / params.luminance_multiplier; -#endif -#endif +#endif // USE_MULTIVIEW +#endif // USES_QUARTER_RES_COLOR + +#endif //USE_CUBEMAP_PASS { @@ -236,14 +263,14 @@ void main() { #if !defined(DISABLE_FOG) && !defined(USE_CUBEMAP_PASS) // Draw "fixed" fog before volumetric fog to ensure volumetric fog can appear in front of the sky. - if (scene_data.fog_enabled) { + if (sky_scene_data.fog_enabled) { vec4 fog = fog_process(cube_normal, frag_color.rgb); - frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a * scene_data.fog_sky_affect); + frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a * sky_scene_data.fog_sky_affect); } - if (scene_data.volumetric_fog_enabled) { + if (sky_scene_data.volumetric_fog_enabled) { vec4 fog = volumetric_fog_process(uv); - frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a * scene_data.volumetric_fog_sky_affect); + frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a * sky_scene_data.volumetric_fog_sky_affect); } if (custom_fog.a > 0.0) { diff --git a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl index 0bdf0e50aa..be53a7ae49 100644 --- a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl @@ -62,7 +62,7 @@ vec3 oct_to_vec3(vec2 e) { vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y)); float t = max(-v.z, 0.0); v.xy += t * -sign(v.xy); - return v; + return normalize(v); } /* Varyings */ @@ -826,7 +826,8 @@ void fragment_shader(in SceneData scene_data) { // alpha hash can be used in unison with alpha antialiasing #ifdef ALPHA_HASH_USED - if (alpha < compute_alpha_hash_threshold(vertex, alpha_hash_scale)) { + vec3 object_pos = (inverse(read_model_matrix) * inv_view_matrix * vec4(vertex, 1.0)).xyz; + if (alpha < compute_alpha_hash_threshold(object_pos, alpha_hash_scale)) { discard; } #endif // ALPHA_HASH_USED @@ -1083,12 +1084,13 @@ void fragment_shader(in SceneData scene_data) { #ifdef USE_RADIANCE_CUBEMAP_ARRAY float lod, blend; - blend = modf(roughness * MAX_ROUGHNESS_LOD, lod); + + blend = modf(sqrt(roughness) * MAX_ROUGHNESS_LOD, lod); specular_light = texture(samplerCubeArray(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(ref_vec, lod)).rgb; specular_light = mix(specular_light, texture(samplerCubeArray(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(ref_vec, lod + 1)).rgb, blend); #else - specular_light = textureLod(samplerCube(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), ref_vec, roughness * MAX_ROUGHNESS_LOD).rgb; + specular_light = textureLod(samplerCube(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), ref_vec, sqrt(roughness) * MAX_ROUGHNESS_LOD).rgb; #endif //USE_RADIANCE_CUBEMAP_ARRAY specular_light *= scene_data.IBL_exposure_normalization; @@ -1136,7 +1138,7 @@ void fragment_shader(in SceneData scene_data) { ref_vec = mix(ref_vec, n, clearcoat_roughness * clearcoat_roughness); float horizon = min(1.0 + dot(ref_vec, normal), 1.0); ref_vec = scene_data.radiance_inverse_xform * ref_vec; - float roughness_lod = mix(0.001, 0.1, clearcoat_roughness) * MAX_ROUGHNESS_LOD; + float roughness_lod = mix(0.001, 0.1, sqrt(clearcoat_roughness)) * MAX_ROUGHNESS_LOD; #ifdef USE_RADIANCE_CUBEMAP_ARRAY float lod, blend; @@ -1483,7 +1485,7 @@ void fragment_shader(in SceneData scene_data) { float a004 = min(r.x * r.x, exp2(-9.28 * ndotv)) * r.x + r.y; vec2 env = vec2(-1.04, 1.04) * a004 + r.zw; - specular_light *= env.x * f0 + env.y * clamp(50.0 * f0.g, 0.0, 1.0); + specular_light *= env.x * f0 + env.y * clamp(50.0 * f0.g, metallic, 1.0); #endif } diff --git a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl index 9aeaa6d978..b45c68db5a 100644 --- a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl @@ -63,7 +63,7 @@ vec3 oct_to_vec3(vec2 e) { vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y)); float t = max(-v.z, 0.0); v.xy += t * -sign(v.xy); - return v; + return normalize(v); } /* Varyings */ @@ -779,7 +779,8 @@ void main() { // alpha hash can be used in unison with alpha antialiasing #ifdef ALPHA_HASH_USED - if (alpha < compute_alpha_hash_threshold(vertex, alpha_hash_scale)) { + vec3 object_pos = (inverse(read_model_matrix) * inv_view_matrix * vec4(vertex, 1.0)).xyz; + if (alpha < compute_alpha_hash_threshold(object_pos, alpha_hash_scale)) { discard; } #endif // ALPHA_HASH_USED @@ -986,12 +987,12 @@ void main() { #ifdef USE_RADIANCE_CUBEMAP_ARRAY float lod, blend; - blend = modf(roughness * MAX_ROUGHNESS_LOD, lod); + blend = modf(sqrt(roughness) * MAX_ROUGHNESS_LOD, lod); specular_light = texture(samplerCubeArray(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(ref_vec, lod)).rgb; specular_light = mix(specular_light, texture(samplerCubeArray(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(ref_vec, lod + 1)).rgb, blend); #else // USE_RADIANCE_CUBEMAP_ARRAY - specular_light = textureLod(samplerCube(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), ref_vec, roughness * MAX_ROUGHNESS_LOD).rgb; + specular_light = textureLod(samplerCube(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), ref_vec, sqrt(roughness) * MAX_ROUGHNESS_LOD).rgb; #endif //USE_RADIANCE_CUBEMAP_ARRAY specular_light *= sc_luminance_multiplier; @@ -1041,7 +1042,7 @@ void main() { float horizon = min(1.0 + dot(ref_vec, normal), 1.0); ref_vec = scene_data.radiance_inverse_xform * ref_vec; - float roughness_lod = mix(0.001, 0.1, clearcoat_roughness) * MAX_ROUGHNESS_LOD; + float roughness_lod = mix(0.001, 0.1, sqrt(clearcoat_roughness)) * MAX_ROUGHNESS_LOD; #ifdef USE_RADIANCE_CUBEMAP_ARRAY float lod, blend; @@ -1204,7 +1205,7 @@ void main() { float a004 = min(r.x * r.x, exp2(-9.28 * ndotv)) * r.x + r.y; vec2 env = vec2(-1.04, 1.04) * a004 + r.zw; - specular_light *= env.x * f0 + env.y; + specular_light *= env.x * f0 + env.y * clamp(50.0 * f0.g, metallic, 1.0); #endif } diff --git a/servers/rendering/renderer_rd/shaders/particles.glsl b/servers/rendering/renderer_rd/shaders/particles.glsl index 3a6dd579b9..a609076e2c 100644 --- a/servers/rendering/renderer_rd/shaders/particles.glsl +++ b/servers/rendering/renderer_rd/shaders/particles.glsl @@ -243,8 +243,14 @@ void main() { if (params.trail_size > 1) { if (params.trail_pass) { + if (particle >= params.total_particles * (params.trail_size - 1)) { + return; + } particle += (particle / (params.trail_size - 1)) + 1; } else { + if (particle >= params.total_particles) { + return; + } particle *= params.trail_size; } } @@ -298,12 +304,17 @@ void main() { PARTICLE.flags = PARTICLE_FLAG_TRAILED | ((frame_history.data[0].frame & PARTICLE_FRAME_MASK) << PARTICLE_FRAME_SHIFT); //mark it as trailed, save in which frame it will start PARTICLE.xform = particles.data[src_idx].xform; } - + if (!bool(particles.data[src_idx].flags & PARTICLE_FLAG_ACTIVE)) { + // Disable the entire trail if the parent is no longer active. + PARTICLE.flags = 0; + return; + } if (bool(PARTICLE.flags & PARTICLE_FLAG_TRAILED) && ((PARTICLE.flags >> PARTICLE_FRAME_SHIFT) == (FRAME.frame & PARTICLE_FRAME_MASK))) { //check this is trailed and see if it should start now // we just assume that this is the first frame of the particle, the rest is deterministic PARTICLE.flags = PARTICLE_FLAG_ACTIVE | (particles.data[src_idx].flags & (PARTICLE_FRAME_MASK << PARTICLE_FRAME_SHIFT)); return; //- this appears like it should be correct, but it seems not to be.. wonder why. } + } else { PARTICLE.flags &= ~PARTICLE_FLAG_STARTED; } @@ -462,7 +473,7 @@ void main() { if (any(lessThan(uvw_pos, vec3(0.0))) || any(greaterThan(uvw_pos, vec3(1.0)))) { continue; } - vec3 s = texture(sampler3D(sdf_vec_textures[FRAME.attractors[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos).xyz * 2.0 - 1.0; + vec3 s = texture(sampler3D(sdf_vec_textures[FRAME.attractors[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos).xyz * -2.0 + 1.0; dir = mat3(FRAME.attractors[i].transform) * safe_normalize(s); //revert direction amount = length(s); diff --git a/servers/rendering/renderer_rd/shaders/scene_data_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_data_inc.glsl index 048257e9ef..b57ee18521 100644 --- a/servers/rendering/renderer_rd/shaders/scene_data_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_data_inc.glsl @@ -63,7 +63,7 @@ struct SceneData { float IBL_exposure_normalization; bool pancake_shadows; - uint pad1; + uint camera_visible_layers; uint pad2; uint pad3; }; diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_aa_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_aa_inc.glsl index 97c913d489..71510ee06a 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_aa_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_aa_inc.glsl @@ -11,7 +11,8 @@ float hash_3d(vec3 p) { float compute_alpha_hash_threshold(vec3 pos, float hash_scale) { vec3 dx = dFdx(pos); - vec3 dy = dFdx(pos); + vec3 dy = dFdy(pos); + float delta_max_sqr = max(length(dx), length(dy)); float pix_scale = 1.0 / (hash_scale * delta_max_sqr); @@ -32,9 +33,9 @@ float compute_alpha_hash_threshold(vec3 pos, float hash_scale) { 1.0 - ((1.0 - a_interp) * (1.0 - a_interp) / (2.0 * min_lerp * (1.0 - min_lerp)))); float alpha_hash_threshold = - (lerp_factor < (1.0 - min_lerp)) ? ((lerp_factor < min_lerp) ? cases.x : cases.y) : cases.z; + (a_interp < (1.0 - min_lerp)) ? ((a_interp < min_lerp) ? cases.x : cases.y) : cases.z; - return clamp(alpha_hash_threshold, 0.0, 1.0); + return clamp(alpha_hash_threshold, 0.00001, 1.0); } #endif // ALPHA_HASH_USED diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl index 2fba1351f7..b30b0c8169 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl @@ -134,7 +134,8 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte #endif #if defined(LIGHT_RIM_USED) - float rim_light = pow(max(0.0, 1.0 - cNdotV), max(0.0, (1.0 - roughness) * 16.0)); + // Epsilon min to prevent pow(0, 0) singularity which results in undefined behavior. + float rim_light = pow(max(1e-4, 1.0 - cNdotV), max(0.0, (1.0 - roughness) * 16.0)); diffuse_light += rim_light * rim * mix(vec3(1.0), albedo, rim_tint) * light_color; #endif @@ -202,7 +203,7 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte float cLdotH5 = SchlickFresnel(cLdotH); // Calculate Fresnel using specular occlusion term from Filament: // https://google.github.io/filament/Filament.html#lighting/occlusion/specularocclusion - float f90 = clamp(dot(f0, vec3(50.0 * 0.33)), 0.0, 1.0); + float f90 = clamp(dot(f0, vec3(50.0 * 0.33)), metallic, 1.0); vec3 F = f0 + (f90 - f0) * cLdotH5; vec3 specular_brdf_NL = cNdotL * D * F * G; diff --git a/servers/rendering/renderer_rd/shaders/skeleton.glsl b/servers/rendering/renderer_rd/shaders/skeleton.glsl index 75bea9300b..f5b233cca0 100644 --- a/servers/rendering/renderer_rd/shaders/skeleton.glsl +++ b/servers/rendering/renderer_rd/shaders/skeleton.glsl @@ -63,7 +63,7 @@ vec3 oct_to_vec3(vec2 oct) { vec3 v = vec3(oct.xy, 1.0 - abs(oct.x) - abs(oct.y)); float t = max(-v.z, 0.0); v.xy += t * -sign(v.xy); - return v; + return normalize(v); } vec3 decode_uint_oct_to_norm(uint base) { @@ -143,8 +143,8 @@ void main() { uint skin_offset = params.skin_stride * index; uvec2 bones = uvec2(src_bone_weights.data[skin_offset + 0], src_bone_weights.data[skin_offset + 1]); - uvec2 bones_01 = uvec2(bones.x & 0xFFFF, bones.x >> 16) * 3; //pre-add xform offset - uvec2 bones_23 = uvec2(bones.y & 0xFFFF, bones.y >> 16) * 3; + uvec2 bones_01 = uvec2(bones.x & 0xFFFF, bones.x >> 16) * 2; //pre-add xform offset + uvec2 bones_23 = uvec2(bones.y & 0xFFFF, bones.y >> 16) * 2; skin_offset += params.skin_weight_offset; @@ -161,6 +161,13 @@ void main() { //reverse order because its transposed vertex = (vec4(vertex, 0.0, 1.0) * m).xy; } + + uint dst_offset = index * params.vertex_stride; + + uvec2 uvertex = floatBitsToUint(vertex); + dst_vertices.data[dst_offset + 0] = uvertex.x; + dst_vertices.data[dst_offset + 1] = uvertex.y; + #else vec3 vertex; vec3 normal; diff --git a/servers/rendering/renderer_rd/spirv-reflect/SCsub b/servers/rendering/renderer_rd/spirv-reflect/SCsub new file mode 100644 index 0000000000..4c27e5bef7 --- /dev/null +++ b/servers/rendering/renderer_rd/spirv-reflect/SCsub @@ -0,0 +1,17 @@ +#!/usr/bin/env python + +Import("env") + +# Thirdparty source files + +thirdparty_dir = "#thirdparty/spirv-reflect/" +thirdparty_sources = [ + "spirv_reflect.c", +] + +thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] + +env_thirdparty = env.Clone() +env_thirdparty.disable_warnings() + +env_thirdparty.add_source_files(env.servers_sources, thirdparty_sources) diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp index c83473ef07..637aff9aac 100644 --- a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp @@ -653,6 +653,14 @@ void LightStorage::update_light_buffers(RenderDataRD *p_render_data, const Paged if (light_data.shadow_opacity > 0.001) { RS::LightDirectionalShadowMode smode = light->directional_shadow_mode; + light_data.soft_shadow_scale = light->param[RS::LIGHT_PARAM_SHADOW_BLUR]; + light_data.softshadow_angle = angular_diameter; + light_data.bake_mode = light->bake_mode; + + if (angular_diameter <= 0.0) { + light_data.soft_shadow_scale *= RendererSceneRenderRD::get_singleton()->directional_shadow_quality_radius_get(); // Only use quality radius for PCF + } + int limit = smode == RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL ? 0 : (smode == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS ? 1 : 3); light_data.blend_splits = (smode != RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL) && light->directional_blend_splits; for (int j = 0; j < 4; j++) { @@ -669,7 +677,7 @@ void LightStorage::update_light_buffers(RenderDataRD *p_render_data, const Paged Projection shadow_mtx = rectm * bias * matrix * modelview; light_data.shadow_split_offsets[j] = split; - float bias_scale = light_instance->shadow_transform[j].bias_scale; + float bias_scale = light_instance->shadow_transform[j].bias_scale * light_data.soft_shadow_scale; light_data.shadow_bias[j] = light->param[RS::LIGHT_PARAM_SHADOW_BIAS] / 100.0 * bias_scale; light_data.shadow_normal_bias[j] = light->param[RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] * light_instance->shadow_transform[j].shadow_texel_size; light_data.shadow_transmittance_bias[j] = light->param[RS::LIGHT_PARAM_TRANSMITTANCE_BIAS] * bias_scale; @@ -702,14 +710,6 @@ void LightStorage::update_light_buffers(RenderDataRD *p_render_data, const Paged float fade_start = light->param[RS::LIGHT_PARAM_SHADOW_FADE_START]; light_data.fade_from = -light_data.shadow_split_offsets[3] * MIN(fade_start, 0.999); //using 1.0 would break smoothstep light_data.fade_to = -light_data.shadow_split_offsets[3]; - - light_data.soft_shadow_scale = light->param[RS::LIGHT_PARAM_SHADOW_BLUR]; - light_data.softshadow_angle = angular_diameter; - light_data.bake_mode = light->bake_mode; - - if (angular_diameter <= 0.0) { - light_data.soft_shadow_scale *= RendererSceneRenderRD::get_singleton()->directional_shadow_quality_radius_get(); // Only use quality radius for PCF - } } r_directional_light_count++; @@ -978,6 +978,7 @@ void LightStorage::update_light_buffers(RenderDataRD *p_render_data, const Paged light_data.soft_shadow_size = 0.0; light_data.soft_shadow_scale *= RendererSceneRenderRD::get_singleton()->shadows_quality_radius_get(); // Only use quality radius for PCF } + light_data.shadow_bias *= light_data.soft_shadow_scale; } } else { light_data.shadow_opacity = 0.0; @@ -1314,6 +1315,10 @@ void LightStorage::reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_s ra->reflections.clear(); } + + if (ra->render_buffers.is_valid()) { + ra->render_buffers->cleanup(); + } } int LightStorage::reflection_atlas_get_size(RID p_ref_atlas) const { @@ -1359,6 +1364,9 @@ void LightStorage::reflection_probe_release_atlas_index(RID p_instance) { ERR_FAIL_COND(!atlas); ERR_FAIL_INDEX(rpi->atlas_index, atlas->reflections.size()); atlas->reflections.write[rpi->atlas_index].owner = RID(); + + // TODO investigate if this is enough? shouldn't we be freeing our textures and framebuffers? + rpi->atlas_index = -1; rpi->atlas = RID(); } @@ -1397,6 +1405,10 @@ bool LightStorage::reflection_probe_instance_begin_render(RID p_instance, RID p_ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); ERR_FAIL_COND_V(!rpi, false); + if (atlas->render_buffers.is_null()) { + atlas->render_buffers.instantiate(); + } + RD::get_singleton()->draw_command_begin_label("Reflection probe render"); if (LightStorage::get_singleton()->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS && atlas->reflection.is_valid() && atlas->size != 256) { @@ -1454,6 +1466,9 @@ bool LightStorage::reflection_probe_instance_begin_render(RID p_instance, RID p_ Vector<RID> fb; fb.push_back(atlas->depth_buffer); atlas->depth_fb = RD::get_singleton()->framebuffer_create(fb); + + atlas->render_buffers->cleanup(); + atlas->render_buffers->configure_for_reflections(Size2i(atlas->size, atlas->size)); } if (rpi->atlas_index == -1) { @@ -1493,6 +1508,13 @@ bool LightStorage::reflection_probe_instance_begin_render(RID p_instance, RID p_ return true; } +Ref<RenderSceneBuffers> LightStorage::reflection_probe_atlas_get_render_buffers(RID p_reflection_atlas) { + ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(p_reflection_atlas); + ERR_FAIL_COND_V(!atlas, Ref<RenderSceneBuffersRD>()); + + return atlas->render_buffers; +} + bool LightStorage::reflection_probe_instance_postprocess_step(RID p_instance) { ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); ERR_FAIL_COND_V(!rpi, false); @@ -1725,13 +1747,13 @@ void LightStorage::lightmap_set_textures(RID p_lightmap, RID p_light, bool p_use //erase lightmap users if (lm->light_texture.is_valid()) { - TextureStorage::Texture *t = texture_storage->get_singleton()->get_texture(lm->light_texture); + TextureStorage::Texture *t = texture_storage->get_texture(lm->light_texture); if (t) { t->lightmap_users.erase(p_lightmap); } } - TextureStorage::Texture *t = texture_storage->get_singleton()->get_texture(p_light); + TextureStorage::Texture *t = texture_storage->get_texture(p_light); lm->light_texture = p_light; lm->uses_spherical_harmonics = p_uses_spherical_haromics; diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.h b/servers/rendering/renderer_rd/storage_rd/light_storage.h index 79006ad982..d31924eeb0 100644 --- a/servers/rendering/renderer_rd/storage_rd/light_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/light_storage.h @@ -38,6 +38,7 @@ #include "servers/rendering/renderer_rd/cluster_builder_rd.h" #include "servers/rendering/renderer_rd/environment/sky.h" #include "servers/rendering/renderer_rd/storage_rd/forward_id_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h" #include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" #include "servers/rendering/storage/light_storage.h" #include "servers/rendering/storage/utilities.h" @@ -256,6 +257,8 @@ private: Vector<Reflection> reflections; + Ref<RenderSceneBuffersRD> render_buffers; // Further render buffers used. + ClusterBuilderRD *cluster_builder = nullptr; // only used if cluster builder is supported by the renderer. }; @@ -846,6 +849,7 @@ public: virtual bool reflection_probe_instance_needs_redraw(RID p_instance) override; virtual bool reflection_probe_instance_has_reflection(RID p_instance) override; virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) override; + virtual Ref<RenderSceneBuffers> reflection_probe_atlas_get_render_buffers(RID p_reflection_atlas) override; virtual bool reflection_probe_instance_postprocess_step(RID p_instance) override; uint32_t reflection_probe_instance_get_resolution(RID p_instance); diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp index 6703d8e7d0..709e4b449f 100644 --- a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp @@ -928,6 +928,104 @@ _FORCE_INLINE_ static void _fill_std140_ubo_empty(ShaderLanguage::DataType type, } /////////////////////////////////////////////////////////////////////////// +// MaterialStorage::ShaderData + +void MaterialStorage::ShaderData::set_path_hint(const String &p_hint) { + path = p_hint; +} + +void MaterialStorage::ShaderData::set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index) { + if (!p_texture.is_valid()) { + if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) { + default_texture_params[p_name].erase(p_index); + + if (default_texture_params[p_name].is_empty()) { + default_texture_params.erase(p_name); + } + } + } else { + if (!default_texture_params.has(p_name)) { + default_texture_params[p_name] = HashMap<int, RID>(); + } + default_texture_params[p_name][p_index] = p_texture; + } +} + +Variant MaterialStorage::ShaderData::get_default_parameter(const StringName &p_parameter) const { + if (uniforms.has(p_parameter)) { + ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter]; + Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value; + return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.array_size, uniform.hint); + } + return Variant(); +} + +void MaterialStorage::ShaderData::get_shader_uniform_list(List<PropertyInfo> *p_param_list) const { + SortArray<Pair<StringName, int>, ShaderLanguage::UniformOrderComparator> sorter; + LocalVector<Pair<StringName, int>> filtered_uniforms; + + for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { + if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) { + continue; + } + if (E.value.texture_order >= 0) { + filtered_uniforms.push_back(Pair<StringName, int>(E.key, E.value.texture_order + 100000)); + } else { + filtered_uniforms.push_back(Pair<StringName, int>(E.key, E.value.order)); + } + } + int uniform_count = filtered_uniforms.size(); + sorter.sort(filtered_uniforms.ptr(), uniform_count); + + String last_group; + for (int i = 0; i < uniform_count; i++) { + const StringName &uniform_name = filtered_uniforms[i].first; + const ShaderLanguage::ShaderNode::Uniform &uniform = uniforms[uniform_name]; + + String group = uniform.group; + if (!uniform.subgroup.is_empty()) { + group += "::" + uniform.subgroup; + } + + if (group != last_group) { + PropertyInfo pi; + pi.usage = PROPERTY_USAGE_GROUP; + pi.name = group; + p_param_list->push_back(pi); + + last_group = group; + } + + PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniform); + pi.name = uniform_name; + p_param_list->push_back(pi); + } +} + +void MaterialStorage::ShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const { + for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { + if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { + continue; + } + + RendererMaterialStorage::InstanceShaderParam p; + p.info = ShaderLanguage::uniform_to_property_info(E.value); + p.info.name = E.key; //supply name + p.index = E.value.instance_index; + p.default_value = ShaderLanguage::constant_value_to_variant(E.value.default_value, E.value.type, E.value.array_size, E.value.hint); + p_param_list->push_back(p); + } +} + +bool MaterialStorage::ShaderData::is_parameter_texture(const StringName &p_param) const { + if (!uniforms.has(p_param)) { + return false; + } + + return uniforms[p_param].texture_order >= 0; +} + +/////////////////////////////////////////////////////////////////////////// // MaterialStorage::MaterialData void MaterialStorage::MaterialData::update_uniform_buffer(const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const HashMap<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color) { @@ -1221,6 +1319,10 @@ void MaterialStorage::MaterialData::update_textures(const HashMap<StringName, Va roughness_detect_texture = tex; roughness_channel = RS::TextureDetectRoughnessChannel(p_texture_uniforms[i].hint - ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_R); } + if (tex->render_target) { + tex->render_target->was_used = true; + render_target_cache.push_back(tex->render_target); + } #endif } if (rd_texture.is_null()) { @@ -1307,6 +1409,7 @@ bool MaterialStorage::MaterialData::update_parameters_uniform_set(const HashMap< if ((uint32_t)texture_cache.size() != tex_uniform_count || p_textures_dirty) { texture_cache.resize(tex_uniform_count); + render_target_cache.clear(); p_textures_dirty = true; //clear previous uniform set @@ -1367,6 +1470,12 @@ bool MaterialStorage::MaterialData::update_parameters_uniform_set(const HashMap< return true; } +void MaterialStorage::MaterialData::set_as_used() { + for (int i = 0; i < render_target_cache.size(); i++) { + render_target_cache[i]->was_used = true; + } +} + /////////////////////////////////////////////////////////////////////////// // MaterialStorage diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.h b/servers/rendering/renderer_rd/storage_rd/material_storage.h index fb25e56ed3..989a0f7b45 100644 --- a/servers/rendering/renderer_rd/storage_rd/material_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/material_storage.h @@ -31,6 +31,8 @@ #ifndef MATERIAL_STORAGE_RD_H #define MATERIAL_STORAGE_RD_H +#include "texture_storage.h" + #include "core/math/projection.h" #include "core/templates/local_vector.h" #include "core/templates/rid_owner.h" @@ -54,24 +56,30 @@ public: }; struct ShaderData { - virtual void set_code(const String &p_Code) = 0; - virtual void set_path_hint(const String &p_hint) = 0; - virtual void set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index) = 0; - virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const = 0; + String path; + HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; + HashMap<StringName, HashMap<int, RID>> default_texture_params; - virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const = 0; - virtual bool is_parameter_texture(const StringName &p_param) const = 0; + virtual void set_path_hint(const String &p_hint); + virtual void set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index); + virtual Variant get_default_parameter(const StringName &p_parameter) const; + virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const; + virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; + virtual bool is_parameter_texture(const StringName &p_param) const; + + virtual void set_code(const String &p_Code) = 0; virtual bool is_animated() const = 0; virtual bool casts_shadows() const = 0; - virtual Variant get_default_parameter(const StringName &p_parameter) const = 0; virtual RS::ShaderNativeSourceCode get_native_source_code() const { return RS::ShaderNativeSourceCode(); } virtual ~ShaderData() {} }; struct MaterialData { + Vector<RendererRD::TextureStorage::RenderTarget *> render_target_cache; void update_uniform_buffer(const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const HashMap<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color); void update_textures(const HashMap<StringName, Variant> &p_parameters, const HashMap<StringName, HashMap<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color); + void set_as_used(); virtual void set_render_priority(int p_priority) = 0; virtual void set_next_pass(RID p_pass) = 0; @@ -79,7 +87,7 @@ public: virtual ~MaterialData(); //to be used internally by update_parameters, in the most common configuration of material parameters - bool update_parameters_uniform_set(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const HashMap<StringName, HashMap<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, bool p_use_linear_color, uint32_t p_barrier = RD::BARRIER_MASK_ALL); + bool update_parameters_uniform_set(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const HashMap<StringName, HashMap<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, bool p_use_linear_color, uint32_t p_barrier = RD::BARRIER_MASK_ALL_BARRIERS); void free_parameters_uniform_set(RID p_uniform_set); private: diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp index 1e74d31383..35fa3931f8 100644 --- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp @@ -434,20 +434,8 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) } if (mesh->surface_count == 0) { - mesh->bone_aabbs = p_surface.bone_aabbs; mesh->aabb = p_surface.aabb; } else { - if (mesh->bone_aabbs.size() < p_surface.bone_aabbs.size()) { - // ArrayMesh::_surface_set_data only allocates bone_aabbs up to max_bone - // Each surface may affect different numbers of bones. - mesh->bone_aabbs.resize(p_surface.bone_aabbs.size()); - } - for (int i = 0; i < p_surface.bone_aabbs.size(); i++) { - const AABB &bone = p_surface.bone_aabbs[i]; - if (bone.has_volume()) { - mesh->bone_aabbs.write[i].merge_with(bone); - } - } mesh->aabb.merge_with(p_surface.aabb); } @@ -616,7 +604,7 @@ AABB MeshStorage::mesh_get_aabb(RID p_mesh, RID p_skeleton) { Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); - if (!skeleton || skeleton->size == 0) { + if (!skeleton || skeleton->size == 0 || mesh->skeleton_aabb_version == skeleton->version) { return mesh->aabb; } @@ -708,6 +696,9 @@ AABB MeshStorage::mesh_get_aabb(RID p_mesh, RID p_skeleton) { } } + mesh->aabb = aabb; + + mesh->skeleton_aabb_version = skeleton->version; return aabb; } @@ -1841,7 +1832,7 @@ void MeshStorage::_update_dirty_multimeshes() { RD::get_singleton()->buffer_update(multimesh->buffer, buffer_offset * sizeof(float) + offset, MIN(region_size, size - offset), &data[region_start_index], RD::BARRIER_MASK_NO_BARRIER); } } - RD::get_singleton()->barrier(RD::BARRIER_MASK_NO_BARRIER, RD::BARRIER_MASK_ALL); + RD::get_singleton()->barrier(RD::BARRIER_MASK_NO_BARRIER, RD::BARRIER_MASK_ALL_BARRIERS); } memcpy(multimesh->previous_data_cache_dirty_regions, multimesh->data_cache_dirty_regions, data_cache_dirty_region_count * sizeof(bool)); diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h index 6a7400631d..a8feddc3b9 100644 --- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h @@ -138,12 +138,11 @@ private: Surface **surfaces = nullptr; uint32_t surface_count = 0; - Vector<AABB> bone_aabbs; - bool has_bone_weights = false; AABB aabb; AABB custom_aabb; + uint64_t skeleton_aabb_version = 0; Vector<RID> material_cache; @@ -664,7 +663,6 @@ public: virtual void skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) override; virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) override; - void skeleton_set_world_transform(RID p_skeleton, bool p_enable, const Transform3D &p_world_transform); virtual int skeleton_get_bone_count(RID p_skeleton) const override; virtual void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform) override; virtual Transform3D skeleton_bone_get_transform(RID p_skeleton, int p_bone) const override; diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp index 854976692e..708455706b 100644 --- a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp @@ -810,6 +810,15 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta //2D collision Transform2D xform = p_particles->sdf_collision_transform; //will use dotproduct manually so invert beforehand + + if (!p_particles->use_local_coords) { + Transform2D emission; + emission.columns[0] = Vector2(p_particles->emission_transform.basis.get_column(0).x, p_particles->emission_transform.basis.get_column(0).y); + emission.columns[1] = Vector2(p_particles->emission_transform.basis.get_column(1).x, p_particles->emission_transform.basis.get_column(1).y); + emission.set_origin(Vector2(p_particles->emission_transform.origin.x, p_particles->emission_transform.origin.y)); + xform = xform * emission.affine_inverse(); + } + Transform2D revert = xform.affine_inverse(); frame_params.collider_count = 1; frame_params.colliders[0].transform[0] = xform.columns[0][0]; @@ -1027,6 +1036,7 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta uniforms.push_back(u); } p_particles->collision_textures_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.default_shader_rd, 2); + p_particles->collision_heightmap_texture = collision_heightmap_texture; } } @@ -1106,6 +1116,7 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta if (m->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(m->uniform_set)) { RD::get_singleton()->compute_list_bind_uniform_set(compute_list, m->uniform_set, 3); + m->set_as_used(); } RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ParticlesShader::PushConstant)); @@ -1404,6 +1415,7 @@ void ParticlesStorage::update_particles() { } bool zero_time_scale = Engine::get_singleton()->get_time_scale() <= 0.0; + bool updated = false; if (particles->clear && particles->pre_process_time > 0.0) { double frame_time; @@ -1418,6 +1430,7 @@ void ParticlesStorage::update_particles() { while (todo >= 0) { _particles_process(particles, frame_time); todo -= frame_time; + updated = true; } } @@ -1439,9 +1452,10 @@ void ParticlesStorage::update_particles() { } double todo = particles->frame_remainder + delta; - while (todo >= frame_time) { + while (todo >= frame_time || (particles->clear && !updated)) { _particles_process(particles, frame_time); todo -= decr; + updated = true; } particles->frame_remainder = todo; @@ -1449,14 +1463,16 @@ void ParticlesStorage::update_particles() { } else { if (zero_time_scale) { _particles_process(particles, 0.0); + updated = true; } else { _particles_process(particles, RendererCompositorRD::singleton->get_frame_delta_time()); + updated = true; } } //copy particles to instance buffer - if (particles->draw_order != RS::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY) { + if (updated && particles->draw_order != RS::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY) { //does not need view dependent operation, do copy here ParticlesShader::CopyPushConstant copy_push_constant; @@ -1533,9 +1549,6 @@ bool ParticlesStorage::particles_is_inactive(RID p_particles) const { /* Particles SHADER */ -void ParticlesStorage::ParticlesShaderData::set_path_hint(const String &p_path) { - path = p_path; -} void ParticlesStorage::ParticlesShaderData::set_code(const String &p_code) { ParticlesStorage *particles_storage = ParticlesStorage::get_singleton(); //compile @@ -1601,83 +1614,6 @@ void ParticlesStorage::ParticlesShaderData::set_code(const String &p_code) { valid = true; } -void ParticlesStorage::ParticlesShaderData::set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index) { - if (!p_texture.is_valid()) { - if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) { - default_texture_params[p_name].erase(p_index); - - if (default_texture_params[p_name].is_empty()) { - default_texture_params.erase(p_name); - } - } - } else { - if (!default_texture_params.has(p_name)) { - default_texture_params[p_name] = HashMap<int, RID>(); - } - default_texture_params[p_name][p_index] = p_texture; - } -} - -void ParticlesStorage::ParticlesShaderData::get_shader_uniform_list(List<PropertyInfo> *p_param_list) const { - HashMap<int, StringName> order; - - for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { - if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { - continue; - } - - if (E.value.texture_order >= 0) { - order[E.value.texture_order + 100000] = E.key; - } else { - order[E.value.order] = E.key; - } - } - - String last_group; - for (const KeyValue<int, StringName> &E : order) { - String group = uniforms[E.value].group; - if (!uniforms[E.value].subgroup.is_empty()) { - group += "::" + uniforms[E.value].subgroup; - } - - if (group != last_group) { - PropertyInfo pi; - pi.usage = PROPERTY_USAGE_GROUP; - pi.name = group; - p_param_list->push_back(pi); - - last_group = group; - } - - PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]); - pi.name = E.value; - p_param_list->push_back(pi); - } -} - -void ParticlesStorage::ParticlesShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const { - for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { - if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { - continue; - } - - RendererMaterialStorage::InstanceShaderParam p; - p.info = ShaderLanguage::uniform_to_property_info(E.value); - p.info.name = E.key; //supply name - p.index = E.value.instance_index; - p.default_value = ShaderLanguage::constant_value_to_variant(E.value.default_value, E.value.type, E.value.array_size, E.value.hint); - p_param_list->push_back(p); - } -} - -bool ParticlesStorage::ParticlesShaderData::is_parameter_texture(const StringName &p_param) const { - if (!uniforms.has(p_param)) { - return false; - } - - return uniforms[p_param].texture_order >= 0; -} - bool ParticlesStorage::ParticlesShaderData::is_animated() const { return false; } @@ -1686,15 +1622,6 @@ bool ParticlesStorage::ParticlesShaderData::casts_shadows() const { return false; } -Variant ParticlesStorage::ParticlesShaderData::get_default_parameter(const StringName &p_parameter) const { - if (uniforms.has(p_parameter)) { - ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter]; - Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value; - return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.array_size, uniform.hint); - } - return Variant(); -} - RS::ShaderNativeSourceCode ParticlesStorage::ParticlesShaderData::get_native_source_code() const { return ParticlesStorage::get_singleton()->particles_shader.shader.version_get_native_source_code(version); } diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.h b/servers/rendering/renderer_rd/storage_rd/particles_storage.h index 6478e2b5dc..0701dc95dd 100644 --- a/servers/rendering/renderer_rd/storage_rd/particles_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.h @@ -54,8 +54,7 @@ private: float velocity[3]; uint32_t active; float color[4]; - float custom[3]; - float lifetime; + float custom[4]; }; struct ParticlesFrameParams { @@ -97,7 +96,7 @@ private: uint32_t type; uint32_t texture_index; //texture index for vector field - real_t scale; + float scale; uint32_t pad[2]; }; @@ -106,8 +105,8 @@ private: float prev_system_phase; uint32_t cycle; - real_t explosiveness; - real_t randomness; + float explosiveness; + float randomness; float time; float delta; @@ -127,9 +126,6 @@ private: Collider colliders[MAX_COLLIDERS]; }; - struct ParticleEmissionBufferData { - }; - struct ParticleEmissionBuffer { struct Data { float xform[16]; @@ -317,15 +313,12 @@ private: RID version; bool uses_collision = false; - HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms; Vector<uint32_t> ubo_offsets; uint32_t ubo_size = 0; - String path; String code; - HashMap<StringName, HashMap<int, RID>> default_texture_params; RID pipeline; @@ -335,14 +328,8 @@ private: uint32_t userdata_count = 0; virtual void set_code(const String &p_Code); - virtual void set_path_hint(const String &p_hint); - virtual void set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index); - virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const; - virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; - virtual bool is_parameter_texture(const StringName &p_param) const; virtual bool is_animated() const; virtual bool casts_shadows() const; - virtual Variant get_default_parameter(const StringName &p_parameter) const; virtual RS::ShaderNativeSourceCode get_native_source_code() const; ParticlesShaderData() {} @@ -412,7 +399,7 @@ public: bool owns_particles(RID p_rid) { return particles_owner.owns(p_rid); } virtual RID particles_allocate() override; - virtual void particles_initialize(RID p_particles_collision) override; + virtual void particles_initialize(RID p_rid) override; virtual void particles_free(RID p_rid) override; virtual void particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) override; @@ -468,6 +455,12 @@ public: return particles->mode; } + _FORCE_INLINE_ uint32_t particles_get_frame_counter(RID p_particles) { + Particles *particles = particles_owner.get_or_null(p_particles); + ERR_FAIL_COND_V(!particles, false); + return particles->frame_counter; + } + _FORCE_INLINE_ uint32_t particles_get_amount(RID p_particles, uint32_t &r_trail_divisor) { Particles *particles = particles_owner.get_or_null(p_particles); ERR_FAIL_COND_V(!particles, 0); @@ -498,9 +491,8 @@ public: _FORCE_INLINE_ RID particles_get_instance_buffer_uniform_set(RID p_particles, RID p_shader, uint32_t p_set) { Particles *particles = particles_owner.get_or_null(p_particles); ERR_FAIL_COND_V(!particles, RID()); - if (particles->particles_transforms_buffer_uniform_set.is_null()) { + if (particles->particles_transforms_buffer_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(particles->particles_transforms_buffer_uniform_set)) { _particles_update_buffers(particles); - Vector<RD::Uniform> uniforms; { @@ -519,7 +511,7 @@ public: virtual void particles_add_collision(RID p_particles, RID p_particles_collision_instance) override; virtual void particles_remove_collision(RID p_particles, RID p_particles_collision_instance) override; - virtual void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) override; + void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture); virtual void update_particles() override; @@ -546,7 +538,7 @@ public: virtual AABB particles_collision_get_aabb(RID p_particles_collision) const override; Vector3 particles_collision_get_extents(RID p_particles_collision) const; virtual bool particles_collision_is_heightfield(RID p_particles_collision) const override; - virtual RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const override; + RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const; Dependency *particles_collision_get_dependency(RID p_particles) const; diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp index 0c2092f03e..fd7b62cd6c 100644 --- a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp +++ b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp @@ -207,6 +207,21 @@ void RenderSceneBuffersRD::configure(RID p_render_target, const Size2i p_interna } } +void RenderSceneBuffersRD::configure_for_reflections(const Size2i p_reflection_size) { + // For now our render buffers for reflections are only used for effects/environment (Sky/Fog/Etc) + // Possibly at some point move our entire reflection atlas buffer management into this class + + target_size = p_reflection_size; + internal_size = p_reflection_size; + render_target = RID(); + fsr_sharpness = 0.0; + msaa_3d = RS::VIEWPORT_MSAA_DISABLED; + screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED; + use_taa = false; + use_debanding = false; + view_count = 1; +} + void RenderSceneBuffersRD::set_fsr_sharpness(float p_fsr_sharpness) { fsr_sharpness = p_fsr_sharpness; } @@ -483,6 +498,10 @@ void RenderSceneBuffersRD::set_custom_data(const StringName &p_name, Ref<RenderB } Ref<RenderBufferCustomDataRD> RenderSceneBuffersRD::get_custom_data(const StringName &p_name) const { + if (!data_buffers.has(p_name)) { + print_line("test"); + } + ERR_FAIL_COND_V(!data_buffers.has(p_name), Ref<RenderBufferCustomDataRD>()); Ref<RenderBufferCustomDataRD> ret = data_buffers[p_name]; diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h index 6907f69b93..4b82f70e1a 100644 --- a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h +++ b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h @@ -140,6 +140,7 @@ public: void cleanup(); virtual void configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa_3d, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override; + void configure_for_reflections(const Size2i p_reflection_size); virtual void set_fsr_sharpness(float p_fsr_sharpness) override; virtual void set_texture_mipmap_bias(float p_texture_mipmap_bias) override; virtual void set_use_debanding(bool p_use_debanding) override; diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp index 7dd790d1da..9b3d5a2d29 100644 --- a/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp +++ b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp @@ -88,6 +88,7 @@ void RenderSceneDataRD::update_ubo(RID p_uniform_buffer, RS::ViewportDebugDraw p RendererRD::MaterialStorage::store_soft_shadow_kernel(render_scene_render->directional_soft_shadow_kernel_get(), ubo.directional_soft_shadow_kernel); RendererRD::MaterialStorage::store_soft_shadow_kernel(render_scene_render->penumbra_shadow_kernel_get(), ubo.penumbra_shadow_kernel); RendererRD::MaterialStorage::store_soft_shadow_kernel(render_scene_render->soft_shadow_kernel_get(), ubo.soft_shadow_kernel); + ubo.camera_visible_layers = camera_visible_layers; ubo.viewport_size[0] = p_screen_size.x; ubo.viewport_size[1] = p_screen_size.y; diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h index 9c031acc1e..5ea4991e8e 100644 --- a/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h +++ b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h @@ -45,6 +45,7 @@ public: Transform3D cam_transform; Projection cam_projection; Vector2 taa_jitter; + uint32_t camera_visible_layers; bool cam_orthogonal = false; // For stereo rendering @@ -142,7 +143,7 @@ private: float IBL_exposure_normalization; // Adjusts for baked exposure. uint32_t pancake_shadows; - uint32_t pad1; + uint32_t camera_visible_layers; uint32_t pad2; uint32_t pad3; }; diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp index 3785c3899b..6a4359faf3 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp @@ -419,11 +419,12 @@ TextureStorage::TextureStorage() { tformat.format = RD::DATA_FORMAT_R8_UINT; tformat.width = 4; tformat.height = 4; - tformat.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; - if (RD::get_singleton()->has_feature(RD::SUPPORTS_ATTACHMENT_VRS)) { - tformat.usage_bits |= RD::TEXTURE_USAGE_VRS_ATTACHMENT_BIT; - } + tformat.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_VRS_ATTACHMENT_BIT; tformat.texture_type = RD::TEXTURE_TYPE_2D; + if (!RD::get_singleton()->has_feature(RD::SUPPORTS_ATTACHMENT_VRS)) { + tformat.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; + tformat.format = RD::DATA_FORMAT_R8_UNORM; + } Vector<uint8_t> pv; pv.resize(4 * 4); @@ -560,6 +561,7 @@ void TextureStorage::canvas_texture_set_texture_filter(RID p_canvas_texture, RS: void TextureStorage::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat) { CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture); ERR_FAIL_NULL(ct); + ct->texture_repeat = p_repeat; ct->clear_sets(); } @@ -580,6 +582,9 @@ bool TextureStorage::canvas_texture_get_uniform_set(RID p_texture, RS::CanvasIte } ct = t->canvas_texture; + if (t->render_target) { + t->render_target->was_used = true; + } } else { ct = canvas_texture_owner.get_or_null(p_texture); } @@ -610,6 +615,9 @@ bool TextureStorage::canvas_texture_get_uniform_set(RID p_texture, RS::CanvasIte } else { u.append_id(t->rd_texture); ct->size_cache = Size2i(t->width_2d, t->height_2d); + if (t->render_target) { + t->render_target->was_used = true; + } } uniforms.push_back(u); } @@ -625,6 +633,9 @@ bool TextureStorage::canvas_texture_get_uniform_set(RID p_texture, RS::CanvasIte } else { u.append_id(t->rd_texture); ct->use_normal_cache = true; + if (t->render_target) { + t->render_target->was_used = true; + } } uniforms.push_back(u); } @@ -640,6 +651,9 @@ bool TextureStorage::canvas_texture_get_uniform_set(RID p_texture, RS::CanvasIte } else { u.append_id(t->rd_texture); ct->use_specular_cache = true; + if (t->render_target) { + t->render_target->was_used = true; + } } uniforms.push_back(u); } @@ -1336,6 +1350,13 @@ Size2 TextureStorage::texture_size_with_proxy(RID p_proxy) { return texture_2d_get_size(p_proxy); } +RID TextureStorage::texture_get_rd_texture_rid(RID p_texture, bool p_srgb) const { + Texture *tex = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND_V(!tex, RID()); + + return (p_srgb && tex->rd_texture_srgb.is_valid()) ? tex->rd_texture_srgb : tex->rd_texture; +} + Ref<Image> TextureStorage::_validate_texture_format(const Ref<Image> &p_image, TextureToRDFormat &r_format) { Ref<Image> image = p_image->duplicate(); @@ -1756,6 +1777,46 @@ Ref<Image> TextureStorage::_validate_texture_format(const Ref<Image> &p_image, T r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; } break; + case Image::FORMAT_ASTC_4x4: + case Image::FORMAT_ASTC_4x4_HDR: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ASTC_4x4_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_ASTC_4x4_UNORM_BLOCK; + if (p_image->get_format() == Image::FORMAT_ASTC_4x4) { + r_format.format_srgb = RD::DATA_FORMAT_ASTC_4x4_SRGB_BLOCK; + } + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + image->decompress(); + image->convert(Image::FORMAT_RGBA8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + + } break; // astc 4x4 + case Image::FORMAT_ASTC_8x8: + case Image::FORMAT_ASTC_8x8_HDR: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ASTC_8x8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_ASTC_8x8_UNORM_BLOCK; + if (p_image->get_format() == Image::FORMAT_ASTC_8x8) { + r_format.format_srgb = RD::DATA_FORMAT_ASTC_8x8_SRGB_BLOCK; + } + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + image->decompress(); + image->convert(Image::FORMAT_RGBA8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + + } break; // astc 8x8 default: { } @@ -2390,6 +2451,10 @@ void TextureStorage::_clear_render_target(RenderTarget *rt) { rt->color = RID(); rt->color_multisample = RID(); + if (rt->texture.is_valid()) { + Texture *tex = get_texture(rt->texture); + tex->render_target = nullptr; + } } void TextureStorage::_update_render_target(RenderTarget *rt) { @@ -2470,6 +2535,7 @@ void TextureStorage::_update_render_target(RenderTarget *rt) { tex->rd_texture = RID(); tex->rd_texture_srgb = RID(); + tex->render_target = rt; //create shared textures to the color buffer, //so transparent can be supported @@ -3112,9 +3178,11 @@ void TextureStorage::render_target_copy_to_back_buffer(RID p_render_target, cons // TODO figure out stereo support here - //single texture copy for backbuffer - //RD::get_singleton()->texture_copy(rt->color, rt->backbuffer_mipmap0, Vector3(region.position.x, region.position.y, 0), Vector3(region.position.x, region.position.y, 0), Vector3(region.size.x, region.size.y, 1), 0, 0, 0, 0, true); - copy_effects->copy_to_rect(rt->color, rt->backbuffer_mipmap0, region, false, false, false, true, true); + if (RendererSceneRenderRD::get_singleton()->_render_buffers_can_be_storage()) { + copy_effects->copy_to_rect(rt->color, rt->backbuffer_mipmap0, region, false, false, false, true, true); + } else { + copy_effects->copy_to_fb_rect(rt->color, rt->backbuffer_fb, region, false, false, false, false, RID(), false, true); + } if (!p_gen_mipmaps) { return; @@ -3123,14 +3191,22 @@ void TextureStorage::render_target_copy_to_back_buffer(RID p_render_target, cons //then mipmap blur RID prev_texture = rt->color; //use color, not backbuffer, as bb has mipmaps. + Size2i texture_size = rt->size; + for (int i = 0; i < rt->backbuffer_mipmaps.size(); i++) { region.position.x >>= 1; region.position.y >>= 1; region.size.x = MAX(1, region.size.x >> 1); region.size.y = MAX(1, region.size.y >> 1); + texture_size.x = MAX(1, texture_size.x >> 1); + texture_size.y = MAX(1, texture_size.y >> 1); RID mipmap = rt->backbuffer_mipmaps[i]; - copy_effects->gaussian_blur(prev_texture, mipmap, region, true); + if (RendererSceneRenderRD::get_singleton()->_render_buffers_can_be_storage()) { + copy_effects->gaussian_blur(prev_texture, mipmap, region, texture_size, true); + } else { + copy_effects->gaussian_blur_raster(prev_texture, mipmap, region, texture_size); + } prev_texture = mipmap; } RD::get_singleton()->draw_command_end_label(); @@ -3158,7 +3234,11 @@ void TextureStorage::render_target_clear_back_buffer(RID p_render_target, const } //single texture copy for backbuffer - copy_effects->set_color(rt->backbuffer_mipmap0, p_color, region, true); + if (RendererSceneRenderRD::get_singleton()->_render_buffers_can_be_storage()) { + copy_effects->set_color(rt->backbuffer_mipmap0, p_color, region, true); + } else { + copy_effects->set_color_raster(rt->backbuffer_mipmap0, p_color, region); + } } void TextureStorage::render_target_gen_back_buffer_mipmaps(RID p_render_target, const Rect2i &p_region) { @@ -3184,15 +3264,23 @@ void TextureStorage::render_target_gen_back_buffer_mipmaps(RID p_render_target, RD::get_singleton()->draw_command_begin_label("Gaussian Blur Mipmaps2"); //then mipmap blur RID prev_texture = rt->backbuffer_mipmap0; + Size2i texture_size = rt->size; for (int i = 0; i < rt->backbuffer_mipmaps.size(); i++) { region.position.x >>= 1; region.position.y >>= 1; region.size.x = MAX(1, region.size.x >> 1); region.size.y = MAX(1, region.size.y >> 1); + texture_size.x = MAX(1, texture_size.x >> 1); + texture_size.y = MAX(1, texture_size.y >> 1); RID mipmap = rt->backbuffer_mipmaps[i]; - copy_effects->gaussian_blur(prev_texture, mipmap, region, true); + + if (RendererSceneRenderRD::get_singleton()->_render_buffers_can_be_storage()) { + copy_effects->gaussian_blur(prev_texture, mipmap, region, texture_size, true); + } else { + copy_effects->gaussian_blur_raster(prev_texture, mipmap, region, texture_size); + } prev_texture = mipmap; } RD::get_singleton()->draw_command_end_label(); diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.h b/servers/rendering/renderer_rd/storage_rd/texture_storage.h index 72d4c90159..0c70d3f938 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.h @@ -108,6 +108,8 @@ private: /* Texture API */ + struct RenderTarget; + class Texture { public: TextureType type; @@ -141,6 +143,7 @@ private: Vector<BufferSlice3D> buffer_slices_3d; uint32_t buffer_size_3d = 0; + RenderTarget *render_target = nullptr; bool is_render_target; bool is_proxy; @@ -491,6 +494,8 @@ public: virtual Size2 texture_size_with_proxy(RID p_proxy) override; + virtual RID texture_get_rd_texture_rid(RID p_texture, bool p_srgb = false) const override; + //internal usage _FORCE_INLINE_ TextureType texture_get_type(RID p_texture) { RendererRD::TextureStorage::Texture *tex = texture_owner.get_or_null(p_texture); diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp index 348f6e4695..675e81c62a 100644 --- a/servers/rendering/renderer_scene_cull.cpp +++ b/servers/rendering/renderer_scene_cull.cpp @@ -646,6 +646,7 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) { geom->geometry_instance->set_surface_materials(instance->materials); geom->geometry_instance->set_transform(instance->transform, instance->aabb, instance->transformed_aabb); geom->geometry_instance->set_layer_mask(instance->layer_mask); + geom->geometry_instance->set_pivot_data(instance->sorting_offset, instance->use_aabb_center); geom->geometry_instance->set_lod_bias(instance->lod_bias); geom->geometry_instance->set_transparency(instance->transparency); geom->geometry_instance->set_use_baked_light(instance->baked_light); @@ -844,6 +845,20 @@ void RendererSceneCull::instance_set_layer_mask(RID p_instance, uint32_t p_mask) } } +void RendererSceneCull::instance_set_pivot_data(RID p_instance, float p_sorting_offset, bool p_use_aabb_center) { + Instance *instance = instance_owner.get_or_null(p_instance); + ERR_FAIL_COND(!instance); + + instance->sorting_offset = p_sorting_offset; + instance->use_aabb_center = p_use_aabb_center; + + if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) { + InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data); + ERR_FAIL_NULL(geom->geometry_instance); + geom->geometry_instance->set_pivot_data(p_sorting_offset, p_use_aabb_center); + } +} + void RendererSceneCull::instance_geometry_set_transparency(RID p_instance, float p_transparency) { Instance *instance = instance_owner.get_or_null(p_instance); ERR_FAIL_COND(!instance); @@ -2512,7 +2527,7 @@ void RendererSceneCull::render_camera(const Ref<RenderSceneBuffers> &p_render_bu } break; } - camera_data.set_camera(transform, projection, is_orthogonal, vaspect, jitter); + camera_data.set_camera(transform, projection, is_orthogonal, vaspect, jitter, camera->visible_layers); } else { // Setup our camera for our XR interface. // We can support multiple views here each with their own camera @@ -2520,7 +2535,7 @@ void RendererSceneCull::render_camera(const Ref<RenderSceneBuffers> &p_render_bu Projection projections[RendererSceneRender::MAX_RENDER_VIEWS]; uint32_t view_count = p_xr_interface->get_view_count(); - ERR_FAIL_COND_MSG(view_count > RendererSceneRender::MAX_RENDER_VIEWS, "Requested view count is not supported"); + ERR_FAIL_COND_MSG(view_count == 0 || view_count > RendererSceneRender::MAX_RENDER_VIEWS, "Requested view count is not supported"); float aspect = p_viewport_size.width / (float)p_viewport_size.height; @@ -2534,7 +2549,7 @@ void RendererSceneCull::render_camera(const Ref<RenderSceneBuffers> &p_render_bu } if (view_count == 1) { - camera_data.set_camera(transforms[0], projections[0], false, camera->vaspect, jitter); + camera_data.set_camera(transforms[0], projections[0], false, camera->vaspect, jitter, camera->visible_layers); } else if (view_count == 2) { camera_data.set_multiview_camera(view_count, transforms, projections, false, camera->vaspect); } else { @@ -2930,7 +2945,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c scene_render->set_scene_pass(render_pass); - if (p_render_buffers.is_valid()) { + if (p_render_buffers.is_valid() && p_reflection_probe.is_null()) { //no rendering code here, this is only to set up what needs to be done, request regions, etc. scene_render->sdfgi_update(p_render_buffers, p_environment, p_camera_data->main_transform.origin); //update conditions for SDFGI (whether its used or not) } @@ -3012,7 +3027,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c { //sdfgi cull.sdfgi.region_count = 0; - if (p_render_buffers.is_valid()) { + if (p_render_buffers.is_valid() && p_reflection_probe.is_null()) { cull.sdfgi.cascade_light_count = 0; uint32_t prev_cascade = 0xFFFFFFFF; @@ -3214,6 +3229,8 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c //render SDFGI { + // Q: Should this whole block be skipped if we're rendering our reflection probe? + sdfgi_update_data.update_static = false; if (cull.sdfgi.region_count > 0) { @@ -3239,7 +3256,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c } } - if (p_render_buffers.is_valid()) { + if (p_render_buffers.is_valid() && p_reflection_probe.is_null()) { sdfgi_update_data.directional_lights = &directional_lights; sdfgi_update_data.positional_light_instances = scenario->dynamic_lights.ptr(); sdfgi_update_data.positional_light_count = scenario->dynamic_lights.size(); @@ -3319,7 +3336,7 @@ void RendererSceneCull::render_empty_scene(const Ref<RenderSceneBuffers> &p_rend RendererSceneRender::CameraData camera_data; camera_data.set_camera(Transform3D(), Projection(), true, false); - scene_render->render_scene(p_render_buffers, &camera_data, &camera_data, PagedArray<RenderGeometryInstance *>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), RID(), RID(), p_shadow_atlas, RID(), scenario->reflection_atlas, RID(), 0, 0, nullptr, 0, nullptr, 0, nullptr); + scene_render->render_scene(p_render_buffers, &camera_data, &camera_data, PagedArray<RenderGeometryInstance *>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), environment, RID(), p_shadow_atlas, RID(), scenario->reflection_atlas, RID(), 0, 0, nullptr, 0, nullptr, 0, nullptr); #endif } @@ -3392,7 +3409,7 @@ bool RendererSceneCull::_render_reflection_probe_step(Instance *p_instance, int RendererSceneRender::CameraData camera_data; camera_data.set_camera(xform, cm, false, false); - Ref<RenderSceneBuffers> render_buffers; + Ref<RenderSceneBuffers> render_buffers = RSG::light_storage->reflection_probe_atlas_get_render_buffers(scenario->reflection_atlas); _render_scene(&camera_data, render_buffers, environment, RID(), RSG::light_storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, RID(), shadow_atlas, reflection_probe->instance, p_step, mesh_lod_threshold, use_shadows); } else { diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h index d085b84a8c..106871edfd 100644 --- a/servers/rendering/renderer_scene_cull.h +++ b/servers/rendering/renderer_scene_cull.h @@ -459,6 +459,10 @@ public: float extra_margin; ObjectID object_id; + // sorting + float sorting_offset = 0.0; + bool use_aabb_center = true; + Vector<Color> lightmap_target_sh; //target is used for incrementally changing the SH over time, this avoids pops in some corner cases and when going interior <-> exterior uint64_t last_frame_pass; @@ -476,6 +480,7 @@ public: Instance *instance = (Instance *)tracker->userdata; switch (p_notification) { case Dependency::DEPENDENCY_CHANGED_SKELETON_DATA: + case Dependency::DEPENDENCY_CHANGED_SKELETON_BONES: case Dependency::DEPENDENCY_CHANGED_AABB: { singleton->_instance_queue_update(instance, true, false); @@ -491,8 +496,7 @@ public: case Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE: { singleton->_instance_queue_update(instance, true, true); } break; - case Dependency::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: - case Dependency::DEPENDENCY_CHANGED_SKELETON_BONES: { + case Dependency::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: { //ignored } break; case Dependency::DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR: { @@ -933,6 +937,7 @@ public: virtual void instance_set_base(RID p_instance, RID p_base); virtual void instance_set_scenario(RID p_instance, RID p_scenario); virtual void instance_set_layer_mask(RID p_instance, uint32_t p_mask); + virtual void instance_set_pivot_data(RID p_instance, float p_sorting_offset, bool p_use_aabb_center); virtual void instance_set_transform(RID p_instance, const Transform3D &p_transform); virtual void instance_attach_object_instance_id(RID p_instance, ObjectID p_id); virtual void instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight); @@ -1173,7 +1178,6 @@ public: PASS1RC(RID, environment_get_glow_map, RID) PASS1(environment_glow_set_use_bicubic_upscale, bool) - PASS1(environment_glow_set_use_high_quality, bool) // SSR PASS6(environment_set_ssr, RID, bool, int, float, float, float) diff --git a/servers/rendering/renderer_scene_render.cpp b/servers/rendering/renderer_scene_render.cpp index f085168df3..3c069f6e2e 100644 --- a/servers/rendering/renderer_scene_render.cpp +++ b/servers/rendering/renderer_scene_render.cpp @@ -33,7 +33,7 @@ ///////////////////////////////////////////////////////////////////////////// // CameraData -void RendererSceneRender::CameraData::set_camera(const Transform3D p_transform, const Projection p_projection, bool p_is_orthogonal, bool p_vaspect, const Vector2 &p_taa_jitter) { +void RendererSceneRender::CameraData::set_camera(const Transform3D p_transform, const Projection p_projection, bool p_is_orthogonal, bool p_vaspect, const Vector2 &p_taa_jitter, const uint32_t p_visible_layers) { view_count = 1; is_orthogonal = p_is_orthogonal; vaspect = p_vaspect; @@ -41,6 +41,7 @@ void RendererSceneRender::CameraData::set_camera(const Transform3D p_transform, main_transform = p_transform; main_projection = p_projection; + visible_layers = p_visible_layers; view_offset[0] = Transform3D(); view_projection[0] = p_projection; taa_jitter = p_taa_jitter; @@ -49,6 +50,7 @@ void RendererSceneRender::CameraData::set_camera(const Transform3D p_transform, void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const Projection *p_projections, bool p_is_orthogonal, bool p_vaspect) { ERR_FAIL_COND_MSG(p_view_count != 2, "Incorrect view count for stereoscopic view"); + visible_layers = 0xFFFFFFFF; view_count = p_view_count; is_orthogonal = p_is_orthogonal; vaspect = p_vaspect; diff --git a/servers/rendering/renderer_scene_render.h b/servers/rendering/renderer_scene_render.h index a8df897077..71f0a78ef3 100644 --- a/servers/rendering/renderer_scene_render.h +++ b/servers/rendering/renderer_scene_render.h @@ -162,7 +162,6 @@ public: RID environment_get_glow_map(RID p_env) const; virtual void environment_glow_set_use_bicubic_upscale(bool p_enable) = 0; - virtual void environment_glow_set_use_high_quality(bool p_enable) = 0; // SSR void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance); @@ -268,6 +267,7 @@ public: // flags uint32_t view_count; bool is_orthogonal; + uint32_t visible_layers; bool vaspect; // Main/center projection @@ -278,7 +278,7 @@ public: Projection view_projection[RendererSceneRender::MAX_RENDER_VIEWS]; Vector2 taa_jitter; - void set_camera(const Transform3D p_transform, const Projection p_projection, bool p_is_orthogonal, bool p_vaspect, const Vector2 &p_taa_jitter = Vector2()); + void set_camera(const Transform3D p_transform, const Projection p_projection, bool p_is_orthogonal, bool p_vaspect, const Vector2 &p_taa_jitter = Vector2(), uint32_t p_visible_layers = 0xFFFFFFFF); void set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const Projection *p_projections, bool p_is_orthogonal, bool p_vaspect); }; diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp index 2836889de5..8cec531393 100644 --- a/servers/rendering/renderer_viewport.cpp +++ b/servers/rendering/renderer_viewport.cpp @@ -550,6 +550,9 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) { if (!can_draw_3d) { RSG::scene->render_empty_scene(p_viewport->render_buffers, p_viewport->scenario, p_viewport->shadow_atlas); } else { + // There may be an outstanding clear request if a clear was requested, but no 2D elements were drawn. + // Clear now otherwise we copy over garbage from the render target. + RSG::texture_storage->render_target_do_clear_request(p_viewport->render_target); _draw_3d(p_viewport); } } diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp index 93118f39e7..28408ddb8e 100644 --- a/servers/rendering/rendering_device.cpp +++ b/servers/rendering/rendering_device.cpp @@ -32,8 +32,18 @@ #include "rendering_device_binds.h" +#include "thirdparty/spirv-reflect/spirv_reflect.h" + RenderingDevice *RenderingDevice::singleton = nullptr; +const char *RenderingDevice::shader_stage_names[RenderingDevice::SHADER_STAGE_MAX] = { + "Vertex", + "Fragment", + "TesselationControl", + "TesselationEvaluation", + "Compute", +}; + RenderingDevice *RenderingDevice::get_singleton() { return singleton; } @@ -170,10 +180,16 @@ RenderingDevice::VertexFormatID RenderingDevice::_vertex_format_create(const Typ return vertex_format_create(descriptions); } -RID RenderingDevice::_vertex_array_create(uint32_t p_vertex_count, VertexFormatID p_vertex_format, const TypedArray<RID> &p_src_buffers) { +RID RenderingDevice::_vertex_array_create(uint32_t p_vertex_count, VertexFormatID p_vertex_format, const TypedArray<RID> &p_src_buffers, const Vector<int64_t> &p_offsets) { Vector<RID> buffers = Variant(p_src_buffers); - return vertex_array_create(p_vertex_count, p_vertex_format, buffers); + Vector<uint64_t> offsets; + offsets.resize(p_offsets.size()); + for (int i = 0; i < p_offsets.size(); i++) { + offsets.write[i] = p_offsets[i]; + } + + return vertex_array_create(p_vertex_count, p_vertex_format, buffers, offsets); } Ref<RDShaderSPIRV> RenderingDevice::_shader_compile_spirv_from_source(const Ref<RDShaderSource> &p_source, bool p_allow_cache) { @@ -246,7 +262,7 @@ RID RenderingDevice::_uniform_set_create(const TypedArray<RDUniform> &p_uniforms return uniform_set_create(uniforms, p_shader, p_shader_set); } -Error RenderingDevice::_buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const Vector<uint8_t> &p_data, uint32_t p_post_barrier) { +Error RenderingDevice::_buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const Vector<uint8_t> &p_data, BitField<BarrierMask> p_post_barrier) { return buffer_update(p_buffer, p_offset, p_size, p_data.ptr(), p_post_barrier); } @@ -280,7 +296,7 @@ static Vector<RenderingDevice::PipelineSpecializationConstant> _get_spec_constan return ret; } -RID RenderingDevice::_render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const Ref<RDPipelineRasterizationState> &p_rasterization_state, const Ref<RDPipelineMultisampleState> &p_multisample_state, const Ref<RDPipelineDepthStencilState> &p_depth_stencil_state, const Ref<RDPipelineColorBlendState> &p_blend_state, int p_dynamic_state_flags, uint32_t p_for_render_pass, const TypedArray<RDPipelineSpecializationConstant> &p_specialization_constants) { +RID RenderingDevice::_render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const Ref<RDPipelineRasterizationState> &p_rasterization_state, const Ref<RDPipelineMultisampleState> &p_multisample_state, const Ref<RDPipelineDepthStencilState> &p_depth_stencil_state, const Ref<RDPipelineColorBlendState> &p_blend_state, BitField<PipelineDynamicStateFlags> p_dynamic_state_flags, uint32_t p_for_render_pass, const TypedArray<RDPipelineSpecializationConstant> &p_specialization_constants) { PipelineRasterizationState rasterization_state; if (p_rasterization_state.is_valid()) { rasterization_state = p_rasterization_state->base; @@ -362,12 +378,329 @@ void RenderingDevice::_compute_list_set_push_constant(ComputeListID p_list, cons compute_list_set_push_constant(p_list, p_data.ptr(), p_data_size); } +Error RenderingDevice::_reflect_spirv(const Vector<ShaderStageSPIRVData> &p_spirv, SpirvReflectionData &r_reflection_data) { + r_reflection_data = {}; + + for (int i = 0; i < p_spirv.size(); i++) { + ShaderStage stage = p_spirv[i].shader_stage; + ShaderStage stage_flag = (ShaderStage)(1 << p_spirv[i].shader_stage); + + if (p_spirv[i].shader_stage == SHADER_STAGE_COMPUTE) { + r_reflection_data.is_compute = true; + ERR_FAIL_COND_V_MSG(p_spirv.size() != 1, FAILED, + "Compute shaders can only receive one stage, dedicated to compute."); + } + ERR_FAIL_COND_V_MSG(r_reflection_data.stages_mask.has_flag(stage_flag), FAILED, + "Stage " + String(shader_stage_names[p_spirv[i].shader_stage]) + " submitted more than once."); + + { + SpvReflectShaderModule module; + const uint8_t *spirv = p_spirv[i].spir_v.ptr(); + SpvReflectResult result = spvReflectCreateShaderModule(p_spirv[i].spir_v.size(), spirv, &module); + ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, FAILED, + "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "' failed parsing shader."); + + if (r_reflection_data.is_compute) { + r_reflection_data.compute_local_size[0] = module.entry_points->local_size.x; + r_reflection_data.compute_local_size[1] = module.entry_points->local_size.y; + r_reflection_data.compute_local_size[2] = module.entry_points->local_size.z; + } + uint32_t binding_count = 0; + result = spvReflectEnumerateDescriptorBindings(&module, &binding_count, nullptr); + ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, FAILED, + "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "' failed enumerating descriptor bindings."); + + if (binding_count > 0) { + // Parse bindings. + + Vector<SpvReflectDescriptorBinding *> bindings; + bindings.resize(binding_count); + result = spvReflectEnumerateDescriptorBindings(&module, &binding_count, bindings.ptrw()); + + ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, FAILED, + "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "' failed getting descriptor bindings."); + + for (uint32_t j = 0; j < binding_count; j++) { + const SpvReflectDescriptorBinding &binding = *bindings[j]; + + SpirvReflectionData::Uniform info{}; + + bool need_array_dimensions = false; + bool need_block_size = false; + bool may_be_writable = false; + + switch (binding.descriptor_type) { + case SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLER: { + info.type = UNIFORM_TYPE_SAMPLER; + need_array_dimensions = true; + } break; + case SPV_REFLECT_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: { + info.type = UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; + need_array_dimensions = true; + } break; + case SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLED_IMAGE: { + info.type = UNIFORM_TYPE_TEXTURE; + need_array_dimensions = true; + } break; + case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_IMAGE: { + info.type = UNIFORM_TYPE_IMAGE; + need_array_dimensions = true; + may_be_writable = true; + } break; + case SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: { + info.type = UNIFORM_TYPE_TEXTURE_BUFFER; + need_array_dimensions = true; + } break; + case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: { + info.type = UNIFORM_TYPE_IMAGE_BUFFER; + need_array_dimensions = true; + may_be_writable = true; + } break; + case SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER: { + info.type = UNIFORM_TYPE_UNIFORM_BUFFER; + need_block_size = true; + } break; + case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER: { + info.type = UNIFORM_TYPE_STORAGE_BUFFER; + need_block_size = true; + may_be_writable = true; + } break; + case SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: { + ERR_PRINT("Dynamic uniform buffer not supported."); + continue; + } break; + case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: { + ERR_PRINT("Dynamic storage buffer not supported."); + continue; + } break; + case SPV_REFLECT_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: { + info.type = UNIFORM_TYPE_INPUT_ATTACHMENT; + need_array_dimensions = true; + } break; + case SPV_REFLECT_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR: { + ERR_PRINT("Acceleration structure not supported."); + continue; + } break; + } + + if (need_array_dimensions) { + if (binding.array.dims_count == 0) { + info.length = 1; + } else { + for (uint32_t k = 0; k < binding.array.dims_count; k++) { + if (k == 0) { + info.length = binding.array.dims[0]; + } else { + info.length *= binding.array.dims[k]; + } + } + } + + } else if (need_block_size) { + info.length = binding.block.size; + } else { + info.length = 0; + } + + if (may_be_writable) { + info.writable = !(binding.type_description->decoration_flags & SPV_REFLECT_DECORATION_NON_WRITABLE) && !(binding.block.decoration_flags & SPV_REFLECT_DECORATION_NON_WRITABLE); + } else { + info.writable = false; + } + + info.binding = binding.binding; + uint32_t set = binding.set; + + ERR_FAIL_COND_V_MSG(set >= MAX_UNIFORM_SETS, FAILED, + "On shader stage '" + String(shader_stage_names[stage]) + "', uniform '" + binding.name + "' uses a set (" + itos(set) + ") index larger than what is supported (" + itos(MAX_UNIFORM_SETS) + ")."); + + if (set < (uint32_t)r_reflection_data.uniforms.size()) { + // Check if this already exists. + bool exists = false; + for (int k = 0; k < r_reflection_data.uniforms[set].size(); k++) { + if (r_reflection_data.uniforms[set][k].binding == (uint32_t)info.binding) { + // Already exists, verify that it's the same type. + ERR_FAIL_COND_V_MSG(r_reflection_data.uniforms[set][k].type != info.type, FAILED, + "On shader stage '" + String(shader_stage_names[stage]) + "', uniform '" + binding.name + "' trying to re-use location for set=" + itos(set) + ", binding=" + itos(info.binding) + " with different uniform type."); + + // Also, verify that it's the same size. + ERR_FAIL_COND_V_MSG(r_reflection_data.uniforms[set][k].length != info.length, FAILED, + "On shader stage '" + String(shader_stage_names[stage]) + "', uniform '" + binding.name + "' trying to re-use location for set=" + itos(set) + ", binding=" + itos(info.binding) + " with different uniform size."); + + // Also, verify that it has the same writability. + ERR_FAIL_COND_V_MSG(r_reflection_data.uniforms[set][k].writable != info.writable, FAILED, + "On shader stage '" + String(shader_stage_names[stage]) + "', uniform '" + binding.name + "' trying to re-use location for set=" + itos(set) + ", binding=" + itos(info.binding) + " with different writability."); + + // Just append stage mask and return. + r_reflection_data.uniforms.write[set].write[k].stages_mask.set_flag(stage_flag); + exists = true; + break; + } + } + + if (exists) { + continue; // Merged. + } + } + + info.stages_mask.set_flag(stage_flag); + + if (set >= (uint32_t)r_reflection_data.uniforms.size()) { + r_reflection_data.uniforms.resize(set + 1); + } + + r_reflection_data.uniforms.write[set].push_back(info); + } + } + + { + // Specialization constants. + + uint32_t sc_count = 0; + result = spvReflectEnumerateSpecializationConstants(&module, &sc_count, nullptr); + ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, FAILED, + "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "' failed enumerating specialization constants."); + + if (sc_count) { + Vector<SpvReflectSpecializationConstant *> spec_constants; + spec_constants.resize(sc_count); + + result = spvReflectEnumerateSpecializationConstants(&module, &sc_count, spec_constants.ptrw()); + ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, FAILED, + "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "' failed obtaining specialization constants."); + + for (uint32_t j = 0; j < sc_count; j++) { + int32_t existing = -1; + SpirvReflectionData::SpecializationConstant sconst{}; + SpvReflectSpecializationConstant *spc = spec_constants[j]; + + sconst.constant_id = spc->constant_id; + sconst.int_value = 0; // Clear previous value JIC. + switch (spc->constant_type) { + case SPV_REFLECT_SPECIALIZATION_CONSTANT_BOOL: { + sconst.type = PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL; + sconst.bool_value = spc->default_value.int_bool_value != 0; + } break; + case SPV_REFLECT_SPECIALIZATION_CONSTANT_INT: { + sconst.type = PIPELINE_SPECIALIZATION_CONSTANT_TYPE_INT; + sconst.int_value = spc->default_value.int_bool_value; + } break; + case SPV_REFLECT_SPECIALIZATION_CONSTANT_FLOAT: { + sconst.type = PIPELINE_SPECIALIZATION_CONSTANT_TYPE_FLOAT; + sconst.float_value = spc->default_value.float_value; + } break; + } + sconst.stages_mask.set_flag(stage_flag); + + for (int k = 0; k < r_reflection_data.specialization_constants.size(); k++) { + if (r_reflection_data.specialization_constants[k].constant_id == sconst.constant_id) { + ERR_FAIL_COND_V_MSG(r_reflection_data.specialization_constants[k].type != sconst.type, FAILED, "More than one specialization constant used for id (" + itos(sconst.constant_id) + "), but their types differ."); + ERR_FAIL_COND_V_MSG(r_reflection_data.specialization_constants[k].int_value != sconst.int_value, FAILED, "More than one specialization constant used for id (" + itos(sconst.constant_id) + "), but their default values differ."); + existing = k; + break; + } + } + + if (existing > 0) { + r_reflection_data.specialization_constants.write[existing].stages_mask.set_flag(stage_flag); + } else { + r_reflection_data.specialization_constants.push_back(sconst); + } + } + } + } + + if (stage == SHADER_STAGE_VERTEX) { + uint32_t iv_count = 0; + result = spvReflectEnumerateInputVariables(&module, &iv_count, nullptr); + ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, FAILED, + "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "' failed enumerating input variables."); + + if (iv_count) { + Vector<SpvReflectInterfaceVariable *> input_vars; + input_vars.resize(iv_count); + + result = spvReflectEnumerateInputVariables(&module, &iv_count, input_vars.ptrw()); + ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, FAILED, + "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "' failed obtaining input variables."); + + for (uint32_t j = 0; j < iv_count; j++) { + if (input_vars[j] && input_vars[j]->decoration_flags == 0) { // Regular input. + r_reflection_data.vertex_input_mask |= (1 << uint32_t(input_vars[j]->location)); + } + } + } + } + + if (stage == SHADER_STAGE_FRAGMENT) { + uint32_t ov_count = 0; + result = spvReflectEnumerateOutputVariables(&module, &ov_count, nullptr); + ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, FAILED, + "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "' failed enumerating output variables."); + + if (ov_count) { + Vector<SpvReflectInterfaceVariable *> output_vars; + output_vars.resize(ov_count); + + result = spvReflectEnumerateOutputVariables(&module, &ov_count, output_vars.ptrw()); + ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, FAILED, + "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "' failed obtaining output variables."); + + for (uint32_t j = 0; j < ov_count; j++) { + const SpvReflectInterfaceVariable *refvar = output_vars[j]; + if (refvar != nullptr && refvar->built_in != SpvBuiltInFragDepth) { + r_reflection_data.fragment_output_mask |= 1 << refvar->location; + } + } + } + } + + uint32_t pc_count = 0; + result = spvReflectEnumeratePushConstantBlocks(&module, &pc_count, nullptr); + ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, FAILED, + "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "' failed enumerating push constants."); + + if (pc_count) { + ERR_FAIL_COND_V_MSG(pc_count > 1, FAILED, + "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "': Only one push constant is supported, which should be the same across shader stages."); + + Vector<SpvReflectBlockVariable *> pconstants; + pconstants.resize(pc_count); + result = spvReflectEnumeratePushConstantBlocks(&module, &pc_count, pconstants.ptrw()); + ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, FAILED, + "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "' failed obtaining push constants."); +#if 0 + if (pconstants[0] == nullptr) { + Ref<FileAccess> f = FileAccess::open("res://popo.spv", FileAccess::WRITE); + f->store_buffer((const uint8_t *)&SpirV[0], SpirV.size() * sizeof(uint32_t)); + } +#endif + + ERR_FAIL_COND_V_MSG(r_reflection_data.push_constant_size && r_reflection_data.push_constant_size != pconstants[0]->size, FAILED, + "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "': Push constant block must be the same across shader stages."); + + r_reflection_data.push_constant_size = pconstants[0]->size; + r_reflection_data.push_constant_stages_mask.set_flag(stage_flag); + + //print_line("Stage: " + String(shader_stage_names[stage]) + " push constant of size=" + itos(push_constant.push_constant_size)); + } + + // Destroy the reflection data when no longer required. + spvReflectDestroyShaderModule(&module); + } + + r_reflection_data.stages_mask.set_flag(stage_flag); + } + + return OK; +} + void RenderingDevice::_bind_methods() { ClassDB::bind_method(D_METHOD("texture_create", "format", "view", "data"), &RenderingDevice::_texture_create, DEFVAL(Array())); ClassDB::bind_method(D_METHOD("texture_create_shared", "view", "with_texture"), &RenderingDevice::_texture_create_shared); ClassDB::bind_method(D_METHOD("texture_create_shared_from_slice", "view", "with_texture", "layer", "mipmap", "mipmaps", "slice_type"), &RenderingDevice::_texture_create_shared_from_slice, DEFVAL(1), DEFVAL(TEXTURE_SLICE_2D)); - ClassDB::bind_method(D_METHOD("texture_update", "texture", "layer", "data", "post_barrier"), &RenderingDevice::texture_update, DEFVAL(BARRIER_MASK_ALL)); + ClassDB::bind_method(D_METHOD("texture_update", "texture", "layer", "data", "post_barrier"), &RenderingDevice::texture_update, DEFVAL(BARRIER_MASK_ALL_BARRIERS)); ClassDB::bind_method(D_METHOD("texture_get_data", "texture", "layer"), &RenderingDevice::texture_get_data); ClassDB::bind_method(D_METHOD("texture_is_format_supported_for_usage", "format", "usage_flags"), &RenderingDevice::texture_is_format_supported_for_usage); @@ -375,9 +708,9 @@ void RenderingDevice::_bind_methods() { ClassDB::bind_method(D_METHOD("texture_is_shared", "texture"), &RenderingDevice::texture_is_shared); ClassDB::bind_method(D_METHOD("texture_is_valid", "texture"), &RenderingDevice::texture_is_valid); - ClassDB::bind_method(D_METHOD("texture_copy", "from_texture", "to_texture", "from_pos", "to_pos", "size", "src_mipmap", "dst_mipmap", "src_layer", "dst_layer", "post_barrier"), &RenderingDevice::texture_copy, DEFVAL(BARRIER_MASK_ALL)); - ClassDB::bind_method(D_METHOD("texture_clear", "texture", "color", "base_mipmap", "mipmap_count", "base_layer", "layer_count", "post_barrier"), &RenderingDevice::texture_clear, DEFVAL(BARRIER_MASK_ALL)); - ClassDB::bind_method(D_METHOD("texture_resolve_multisample", "from_texture", "to_texture", "post_barrier"), &RenderingDevice::texture_resolve_multisample, DEFVAL(BARRIER_MASK_ALL)); + ClassDB::bind_method(D_METHOD("texture_copy", "from_texture", "to_texture", "from_pos", "to_pos", "size", "src_mipmap", "dst_mipmap", "src_layer", "dst_layer", "post_barrier"), &RenderingDevice::texture_copy, DEFVAL(BARRIER_MASK_ALL_BARRIERS)); + ClassDB::bind_method(D_METHOD("texture_clear", "texture", "color", "base_mipmap", "mipmap_count", "base_layer", "layer_count", "post_barrier"), &RenderingDevice::texture_clear, DEFVAL(BARRIER_MASK_ALL_BARRIERS)); + ClassDB::bind_method(D_METHOD("texture_resolve_multisample", "from_texture", "to_texture", "post_barrier"), &RenderingDevice::texture_resolve_multisample, DEFVAL(BARRIER_MASK_ALL_BARRIERS)); ClassDB::bind_method(D_METHOD("framebuffer_format_create", "attachments", "view_count"), &RenderingDevice::_framebuffer_format_create, DEFVAL(1)); ClassDB::bind_method(D_METHOD("framebuffer_format_create_multipass", "attachments", "passes", "view_count"), &RenderingDevice::_framebuffer_format_create_multipass, DEFVAL(1)); @@ -393,6 +726,7 @@ void RenderingDevice::_bind_methods() { ClassDB::bind_method(D_METHOD("vertex_buffer_create", "size_bytes", "data", "use_as_storage"), &RenderingDevice::vertex_buffer_create, DEFVAL(Vector<uint8_t>()), DEFVAL(false)); ClassDB::bind_method(D_METHOD("vertex_format_create", "vertex_descriptions"), &RenderingDevice::_vertex_format_create); + ClassDB::bind_method(D_METHOD("vertex_array_create", "vertex_count", "vertex_format", "src_buffers", "offsets"), &RenderingDevice::_vertex_array_create, DEFVAL(Vector<int64_t>())); ClassDB::bind_method(D_METHOD("index_buffer_create", "size_indices", "format", "data", "use_restart_indices"), &RenderingDevice::index_buffer_create, DEFVAL(Vector<uint8_t>()), DEFVAL(false)); ClassDB::bind_method(D_METHOD("index_array_create", "index_buffer", "index_offset", "index_count"), &RenderingDevice::index_array_create); @@ -410,8 +744,8 @@ void RenderingDevice::_bind_methods() { ClassDB::bind_method(D_METHOD("uniform_set_create", "uniforms", "shader", "shader_set"), &RenderingDevice::_uniform_set_create); ClassDB::bind_method(D_METHOD("uniform_set_is_valid", "uniform_set"), &RenderingDevice::uniform_set_is_valid); - ClassDB::bind_method(D_METHOD("buffer_update", "buffer", "offset", "size_bytes", "data", "post_barrier"), &RenderingDevice::_buffer_update, DEFVAL(BARRIER_MASK_ALL)); - ClassDB::bind_method(D_METHOD("buffer_clear", "buffer", "offset", "size_bytes", "post_barrier"), &RenderingDevice::buffer_clear, DEFVAL(BARRIER_MASK_ALL)); + ClassDB::bind_method(D_METHOD("buffer_update", "buffer", "offset", "size_bytes", "data", "post_barrier"), &RenderingDevice::_buffer_update, DEFVAL(BARRIER_MASK_ALL_BARRIERS)); + ClassDB::bind_method(D_METHOD("buffer_clear", "buffer", "offset", "size_bytes", "post_barrier"), &RenderingDevice::buffer_clear, DEFVAL(BARRIER_MASK_ALL_BARRIERS)); ClassDB::bind_method(D_METHOD("buffer_get_data", "buffer"), &RenderingDevice::buffer_get_data); ClassDB::bind_method(D_METHOD("render_pipeline_create", "shader", "framebuffer_format", "vertex_format", "primitive", "rasterization_state", "multisample_state", "stencil_state", "color_blend_state", "dynamic_state_flags", "for_render_pass", "specialization_constants"), &RenderingDevice::_render_pipeline_create, DEFVAL(0), DEFVAL(0), DEFVAL(TypedArray<RDPipelineSpecializationConstant>())); @@ -444,7 +778,7 @@ void RenderingDevice::_bind_methods() { ClassDB::bind_method(D_METHOD("draw_list_switch_to_next_pass"), &RenderingDevice::draw_list_switch_to_next_pass); ClassDB::bind_method(D_METHOD("draw_list_switch_to_next_pass_split", "splits"), &RenderingDevice::_draw_list_switch_to_next_pass_split); - ClassDB::bind_method(D_METHOD("draw_list_end", "post_barrier"), &RenderingDevice::draw_list_end, DEFVAL(BARRIER_MASK_ALL)); + ClassDB::bind_method(D_METHOD("draw_list_end", "post_barrier"), &RenderingDevice::draw_list_end, DEFVAL(BARRIER_MASK_ALL_BARRIERS)); ClassDB::bind_method(D_METHOD("compute_list_begin", "allow_draw_overlap"), &RenderingDevice::compute_list_begin, DEFVAL(false)); ClassDB::bind_method(D_METHOD("compute_list_bind_compute_pipeline", "compute_list", "compute_pipeline"), &RenderingDevice::compute_list_bind_compute_pipeline); @@ -452,7 +786,7 @@ void RenderingDevice::_bind_methods() { ClassDB::bind_method(D_METHOD("compute_list_bind_uniform_set", "compute_list", "uniform_set", "set_index"), &RenderingDevice::compute_list_bind_uniform_set); ClassDB::bind_method(D_METHOD("compute_list_dispatch", "compute_list", "x_groups", "y_groups", "z_groups"), &RenderingDevice::compute_list_dispatch); ClassDB::bind_method(D_METHOD("compute_list_add_barrier", "compute_list"), &RenderingDevice::compute_list_add_barrier); - ClassDB::bind_method(D_METHOD("compute_list_end", "post_barrier"), &RenderingDevice::compute_list_end, DEFVAL(BARRIER_MASK_ALL)); + ClassDB::bind_method(D_METHOD("compute_list_end", "post_barrier"), &RenderingDevice::compute_list_end, DEFVAL(BARRIER_MASK_ALL_BARRIERS)); ClassDB::bind_method(D_METHOD("free_rid", "rid"), &RenderingDevice::free); @@ -468,7 +802,7 @@ void RenderingDevice::_bind_methods() { ClassDB::bind_method(D_METHOD("submit"), &RenderingDevice::submit); ClassDB::bind_method(D_METHOD("sync"), &RenderingDevice::sync); - ClassDB::bind_method(D_METHOD("barrier", "from", "to"), &RenderingDevice::barrier, DEFVAL(BARRIER_MASK_ALL), DEFVAL(BARRIER_MASK_ALL)); + ClassDB::bind_method(D_METHOD("barrier", "from", "to"), &RenderingDevice::barrier, DEFVAL(BARRIER_MASK_ALL_BARRIERS), DEFVAL(BARRIER_MASK_ALL_BARRIERS)); ClassDB::bind_method(D_METHOD("full_barrier"), &RenderingDevice::full_barrier); ClassDB::bind_method(D_METHOD("create_local_device"), &RenderingDevice::create_local_device); @@ -487,12 +821,6 @@ void RenderingDevice::_bind_methods() { ClassDB::bind_method(D_METHOD("get_driver_resource", "resource", "rid", "index"), &RenderingDevice::get_driver_resource); - BIND_CONSTANT(BARRIER_MASK_RASTER); - BIND_CONSTANT(BARRIER_MASK_COMPUTE); - BIND_CONSTANT(BARRIER_MASK_TRANSFER); - BIND_CONSTANT(BARRIER_MASK_ALL); - BIND_CONSTANT(BARRIER_MASK_NO_BARRIER); - BIND_ENUM_CONSTANT(DEVICE_TYPE_OTHER); BIND_ENUM_CONSTANT(DEVICE_TYPE_INTEGRATED_GPU); BIND_ENUM_CONSTANT(DEVICE_TYPE_DISCRETE_GPU); @@ -734,6 +1062,12 @@ void RenderingDevice::_bind_methods() { BIND_ENUM_CONSTANT(DATA_FORMAT_G16_B16_R16_3PLANE_444_UNORM); BIND_ENUM_CONSTANT(DATA_FORMAT_MAX); + BIND_BITFIELD_FLAG(BARRIER_MASK_RASTER); + BIND_BITFIELD_FLAG(BARRIER_MASK_COMPUTE); + BIND_BITFIELD_FLAG(BARRIER_MASK_TRANSFER); + BIND_BITFIELD_FLAG(BARRIER_MASK_ALL_BARRIERS); + BIND_BITFIELD_FLAG(BARRIER_MASK_NO_BARRIER); + BIND_ENUM_CONSTANT(TEXTURE_TYPE_1D); BIND_ENUM_CONSTANT(TEXTURE_TYPE_2D); BIND_ENUM_CONSTANT(TEXTURE_TYPE_3D); @@ -752,16 +1086,16 @@ void RenderingDevice::_bind_methods() { BIND_ENUM_CONSTANT(TEXTURE_SAMPLES_64); BIND_ENUM_CONSTANT(TEXTURE_SAMPLES_MAX); - BIND_ENUM_CONSTANT(TEXTURE_USAGE_SAMPLING_BIT); - BIND_ENUM_CONSTANT(TEXTURE_USAGE_COLOR_ATTACHMENT_BIT); - BIND_ENUM_CONSTANT(TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); - BIND_ENUM_CONSTANT(TEXTURE_USAGE_STORAGE_BIT); - BIND_ENUM_CONSTANT(TEXTURE_USAGE_STORAGE_ATOMIC_BIT); - BIND_ENUM_CONSTANT(TEXTURE_USAGE_CPU_READ_BIT); - BIND_ENUM_CONSTANT(TEXTURE_USAGE_CAN_UPDATE_BIT); - BIND_ENUM_CONSTANT(TEXTURE_USAGE_CAN_COPY_FROM_BIT); - BIND_ENUM_CONSTANT(TEXTURE_USAGE_CAN_COPY_TO_BIT); - BIND_ENUM_CONSTANT(TEXTURE_USAGE_INPUT_ATTACHMENT_BIT); + BIND_BITFIELD_FLAG(TEXTURE_USAGE_SAMPLING_BIT); + BIND_BITFIELD_FLAG(TEXTURE_USAGE_COLOR_ATTACHMENT_BIT); + BIND_BITFIELD_FLAG(TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); + BIND_BITFIELD_FLAG(TEXTURE_USAGE_STORAGE_BIT); + BIND_BITFIELD_FLAG(TEXTURE_USAGE_STORAGE_ATOMIC_BIT); + BIND_BITFIELD_FLAG(TEXTURE_USAGE_CPU_READ_BIT); + BIND_BITFIELD_FLAG(TEXTURE_USAGE_CAN_UPDATE_BIT); + BIND_BITFIELD_FLAG(TEXTURE_USAGE_CAN_COPY_FROM_BIT); + BIND_BITFIELD_FLAG(TEXTURE_USAGE_CAN_COPY_TO_BIT); + BIND_BITFIELD_FLAG(TEXTURE_USAGE_INPUT_ATTACHMENT_BIT); BIND_ENUM_CONSTANT(TEXTURE_SWIZZLE_IDENTITY); BIND_ENUM_CONSTANT(TEXTURE_SWIZZLE_ZERO); @@ -799,7 +1133,7 @@ void RenderingDevice::_bind_methods() { BIND_ENUM_CONSTANT(INDEX_BUFFER_FORMAT_UINT16); BIND_ENUM_CONSTANT(INDEX_BUFFER_FORMAT_UINT32); - BIND_ENUM_CONSTANT(STORAGE_BUFFER_USAGE_DISPATCH_INDIRECT); + BIND_BITFIELD_FLAG(STORAGE_BUFFER_USAGE_DISPATCH_INDIRECT); BIND_ENUM_CONSTANT(UNIFORM_TYPE_SAMPLER); //for sampling only (sampler GLSL type) BIND_ENUM_CONSTANT(UNIFORM_TYPE_SAMPLER_WITH_TEXTURE); // for sampling only); but includes a texture); (samplerXX GLSL type)); first a sampler then a texture @@ -899,13 +1233,13 @@ void RenderingDevice::_bind_methods() { BIND_ENUM_CONSTANT(BLEND_OP_MAXIMUM); BIND_ENUM_CONSTANT(BLEND_OP_MAX); - BIND_ENUM_CONSTANT(DYNAMIC_STATE_LINE_WIDTH); - BIND_ENUM_CONSTANT(DYNAMIC_STATE_DEPTH_BIAS); - BIND_ENUM_CONSTANT(DYNAMIC_STATE_BLEND_CONSTANTS); - BIND_ENUM_CONSTANT(DYNAMIC_STATE_DEPTH_BOUNDS); - BIND_ENUM_CONSTANT(DYNAMIC_STATE_STENCIL_COMPARE_MASK); - BIND_ENUM_CONSTANT(DYNAMIC_STATE_STENCIL_WRITE_MASK); - BIND_ENUM_CONSTANT(DYNAMIC_STATE_STENCIL_REFERENCE); + BIND_BITFIELD_FLAG(DYNAMIC_STATE_LINE_WIDTH); + BIND_BITFIELD_FLAG(DYNAMIC_STATE_DEPTH_BIAS); + BIND_BITFIELD_FLAG(DYNAMIC_STATE_BLEND_CONSTANTS); + BIND_BITFIELD_FLAG(DYNAMIC_STATE_DEPTH_BOUNDS); + BIND_BITFIELD_FLAG(DYNAMIC_STATE_STENCIL_COMPARE_MASK); + BIND_BITFIELD_FLAG(DYNAMIC_STATE_STENCIL_WRITE_MASK); + BIND_BITFIELD_FLAG(DYNAMIC_STATE_STENCIL_REFERENCE); BIND_ENUM_CONSTANT(INITIAL_ACTION_CLEAR); //start rendering and clear the framebuffer (supply params) BIND_ENUM_CONSTANT(INITIAL_ACTION_CLEAR_REGION); //start rendering and clear the framebuffer (supply params) diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h index d0b85d8220..0adc78894a 100644 --- a/servers/rendering/rendering_device.h +++ b/servers/rendering/rendering_device.h @@ -396,8 +396,8 @@ public: BARRIER_MASK_RASTER = 1, BARRIER_MASK_COMPUTE = 2, BARRIER_MASK_TRANSFER = 4, + BARRIER_MASK_ALL_BARRIERS = BARRIER_MASK_RASTER | BARRIER_MASK_COMPUTE | BARRIER_MASK_TRANSFER, // 7 BARRIER_MASK_NO_BARRIER = 8, - BARRIER_MASK_ALL = BARRIER_MASK_RASTER | BARRIER_MASK_COMPUTE | BARRIER_MASK_TRANSFER }; /*****************/ @@ -532,17 +532,17 @@ public: virtual RID texture_create_shared_from_slice(const TextureView &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap, uint32_t p_mipmaps = 1, TextureSliceType p_slice_type = TEXTURE_SLICE_2D) = 0; - virtual Error texture_update(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data, uint32_t p_post_barrier = BARRIER_MASK_ALL) = 0; + virtual Error texture_update(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data, BitField<BarrierMask> p_post_barrier = BARRIER_MASK_ALL_BARRIERS) = 0; virtual Vector<uint8_t> texture_get_data(RID p_texture, uint32_t p_layer) = 0; // CPU textures will return immediately, while GPU textures will most likely force a flush - virtual bool texture_is_format_supported_for_usage(DataFormat p_format, uint32_t p_usage) const = 0; + virtual bool texture_is_format_supported_for_usage(DataFormat p_format, BitField<RenderingDevice::TextureUsageBits> p_usage) const = 0; virtual bool texture_is_shared(RID p_texture) = 0; virtual bool texture_is_valid(RID p_texture) = 0; virtual Size2i texture_size(RID p_texture) = 0; - virtual Error texture_copy(RID p_from_texture, RID p_to_texture, const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_size, uint32_t p_src_mipmap, uint32_t p_dst_mipmap, uint32_t p_src_layer, uint32_t p_dst_layer, uint32_t p_post_barrier = BARRIER_MASK_ALL) = 0; - virtual Error texture_clear(RID p_texture, const Color &p_color, uint32_t p_base_mipmap, uint32_t p_mipmaps, uint32_t p_base_layer, uint32_t p_layers, uint32_t p_post_barrier = BARRIER_MASK_ALL) = 0; - virtual Error texture_resolve_multisample(RID p_from_texture, RID p_to_texture, uint32_t p_post_barrier = BARRIER_MASK_ALL) = 0; + virtual Error texture_copy(RID p_from_texture, RID p_to_texture, const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_size, uint32_t p_src_mipmap, uint32_t p_dst_mipmap, uint32_t p_src_layer, uint32_t p_dst_layer, BitField<BarrierMask> p_post_barrier = BARRIER_MASK_ALL_BARRIERS) = 0; + virtual Error texture_clear(RID p_texture, const Color &p_color, uint32_t p_base_mipmap, uint32_t p_mipmaps, uint32_t p_base_layer, uint32_t p_layers, BitField<BarrierMask> p_post_barrier = BARRIER_MASK_ALL_BARRIERS) = 0; + virtual Error texture_resolve_multisample(RID p_from_texture, RID p_to_texture, BitField<BarrierMask> p_post_barrier = BARRIER_MASK_ALL_BARRIERS) = 0; /*********************/ /**** FRAMEBUFFER ****/ @@ -683,7 +683,7 @@ public: // This ID is warranted to be unique for the same formats, does not need to be freed virtual VertexFormatID vertex_format_create(const Vector<VertexAttribute> &p_vertex_formats) = 0; - virtual RID vertex_array_create(uint32_t p_vertex_count, VertexFormatID p_vertex_format, const Vector<RID> &p_src_buffers) = 0; + virtual RID vertex_array_create(uint32_t p_vertex_count, VertexFormatID p_vertex_format, const Vector<RID> &p_src_buffers, const Vector<uint64_t> &p_offsets = Vector<uint64_t>()) = 0; enum IndexBufferFormat { INDEX_BUFFER_FORMAT_UINT16, @@ -749,11 +749,11 @@ public: }; enum StorageBufferUsage { - STORAGE_BUFFER_USAGE_DISPATCH_INDIRECT = 1 + STORAGE_BUFFER_USAGE_DISPATCH_INDIRECT = 1, }; virtual RID uniform_buffer_create(uint32_t p_size_bytes, const Vector<uint8_t> &p_data = Vector<uint8_t>()) = 0; - virtual RID storage_buffer_create(uint32_t p_size, const Vector<uint8_t> &p_data = Vector<uint8_t>(), uint32_t p_usage = 0) = 0; + virtual RID storage_buffer_create(uint32_t p_size, const Vector<uint8_t> &p_data = Vector<uint8_t>(), BitField<StorageBufferUsage> p_usage = 0) = 0; virtual RID texture_buffer_create(uint32_t p_size_elements, DataFormat p_format, const Vector<uint8_t> &p_data = Vector<uint8_t>()) = 0; struct Uniform { @@ -826,8 +826,8 @@ public: virtual bool uniform_set_is_valid(RID p_uniform_set) = 0; virtual void uniform_set_set_invalidation_callback(RID p_uniform_set, InvalidationCallback p_callback, void *p_userdata) = 0; - virtual Error buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const void *p_data, uint32_t p_post_barrier = BARRIER_MASK_ALL) = 0; - virtual Error buffer_clear(RID p_buffer, uint32_t p_offset, uint32_t p_size, uint32_t p_post_barrier = BARRIER_MASK_ALL) = 0; + virtual Error buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const void *p_data, BitField<BarrierMask> p_post_barrier = BARRIER_MASK_ALL_BARRIERS) = 0; + virtual Error buffer_clear(RID p_buffer, uint32_t p_offset, uint32_t p_size, BitField<BarrierMask> p_post_barrier = BARRIER_MASK_ALL_BARRIERS) = 0; virtual Vector<uint8_t> buffer_get_data(RID p_buffer) = 0; //this causes stall, only use to retrieve large buffers for saving /******************************************/ @@ -1112,7 +1112,7 @@ public: }; virtual bool render_pipeline_is_valid(RID p_pipeline) = 0; - virtual RID render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const PipelineRasterizationState &p_rasterization_state, const PipelineMultisampleState &p_multisample_state, const PipelineDepthStencilState &p_depth_stencil_state, const PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags = 0, uint32_t p_for_render_pass = 0, const Vector<PipelineSpecializationConstant> &p_specialization_constants = Vector<PipelineSpecializationConstant>()) = 0; + virtual RID render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const PipelineRasterizationState &p_rasterization_state, const PipelineMultisampleState &p_multisample_state, const PipelineDepthStencilState &p_depth_stencil_state, const PipelineColorBlendState &p_blend_state, BitField<PipelineDynamicStateFlags> p_dynamic_state_flags = 0, uint32_t p_for_render_pass = 0, const Vector<PipelineSpecializationConstant> &p_specialization_constants = Vector<PipelineSpecializationConstant>()) = 0; /**************************/ /**** COMPUTE PIPELINE ****/ @@ -1173,7 +1173,7 @@ public: virtual DrawListID draw_list_switch_to_next_pass() = 0; virtual Error draw_list_switch_to_next_pass_split(uint32_t p_splits, DrawListID *r_split_ids) = 0; - virtual void draw_list_end(uint32_t p_post_barrier = BARRIER_MASK_ALL) = 0; + virtual void draw_list_end(BitField<BarrierMask> p_post_barrier = BARRIER_MASK_ALL_BARRIERS) = 0; /***********************/ /**** COMPUTE LISTS ****/ @@ -1190,9 +1190,9 @@ public: virtual void compute_list_dispatch_indirect(ComputeListID p_list, RID p_buffer, uint32_t p_offset) = 0; virtual void compute_list_add_barrier(ComputeListID p_list) = 0; - virtual void compute_list_end(uint32_t p_post_barrier = BARRIER_MASK_ALL) = 0; + virtual void compute_list_end(BitField<BarrierMask> p_post_barrier = BARRIER_MASK_ALL_BARRIERS) = 0; - virtual void barrier(uint32_t p_from = BARRIER_MASK_ALL, uint32_t p_to = BARRIER_MASK_ALL) = 0; + virtual void barrier(BitField<BarrierMask> p_from = BARRIER_MASK_ALL_BARRIERS, BitField<BarrierMask> p_to = BARRIER_MASK_ALL_BARRIERS) = 0; virtual void full_barrier() = 0; /***************/ @@ -1257,6 +1257,8 @@ public: LIMIT_SUBGROUP_SIZE, LIMIT_SUBGROUP_IN_SHADERS, // Set flags using SHADER_STAGE_VERTEX_BIT, SHADER_STAGE_FRAGMENT_BIT, etc. LIMIT_SUBGROUP_OPERATIONS, + LIMIT_VRS_TEXEL_WIDTH, + LIMIT_VRS_TEXEL_HEIGHT, }; virtual uint64_t limit_get(Limit p_limit) const = 0; @@ -1299,6 +1301,10 @@ public: RenderingDevice(); protected: + static const char *shader_stage_names[RenderingDevice::SHADER_STAGE_MAX]; + + static const uint32_t MAX_UNIFORM_SETS = 16; + //binders to script API RID _texture_create(const Ref<RDTextureFormat> &p_format, const Ref<RDTextureView> &p_view, const TypedArray<PackedByteArray> &p_data = Array()); RID _texture_create_shared(const Ref<RDTextureView> &p_view, RID p_with_texture); @@ -1310,7 +1316,7 @@ protected: RID _framebuffer_create_multipass(const TypedArray<RID> &p_textures, const TypedArray<RDFramebufferPass> &p_passes, FramebufferFormatID p_format_check = INVALID_ID, uint32_t p_view_count = 1); RID _sampler_create(const Ref<RDSamplerState> &p_state); VertexFormatID _vertex_format_create(const TypedArray<RDVertexAttribute> &p_vertex_formats); - RID _vertex_array_create(uint32_t p_vertex_count, VertexFormatID p_vertex_format, const TypedArray<RID> &p_src_buffers); + RID _vertex_array_create(uint32_t p_vertex_count, VertexFormatID p_vertex_format, const TypedArray<RID> &p_src_buffers, const Vector<int64_t> &p_offsets = Vector<int64_t>()); Ref<RDShaderSPIRV> _shader_compile_spirv_from_source(const Ref<RDShaderSource> &p_source, bool p_allow_cache = true); Vector<uint8_t> _shader_compile_binary_from_spirv(const Ref<RDShaderSPIRV> &p_bytecode, const String &p_shader_name = ""); @@ -1318,15 +1324,48 @@ protected: RID _uniform_set_create(const TypedArray<RDUniform> &p_uniforms, RID p_shader, uint32_t p_shader_set); - Error _buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const Vector<uint8_t> &p_data, uint32_t p_post_barrier = BARRIER_MASK_ALL); + Error _buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const Vector<uint8_t> &p_data, BitField<BarrierMask> p_post_barrier = BARRIER_MASK_ALL_BARRIERS); - RID _render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const Ref<RDPipelineRasterizationState> &p_rasterization_state, const Ref<RDPipelineMultisampleState> &p_multisample_state, const Ref<RDPipelineDepthStencilState> &p_depth_stencil_state, const Ref<RDPipelineColorBlendState> &p_blend_state, int p_dynamic_state_flags, uint32_t p_for_render_pass, const TypedArray<RDPipelineSpecializationConstant> &p_specialization_constants); + RID _render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const Ref<RDPipelineRasterizationState> &p_rasterization_state, const Ref<RDPipelineMultisampleState> &p_multisample_state, const Ref<RDPipelineDepthStencilState> &p_depth_stencil_state, const Ref<RDPipelineColorBlendState> &p_blend_state, BitField<PipelineDynamicStateFlags> p_dynamic_state_flags, uint32_t p_for_render_pass, const TypedArray<RDPipelineSpecializationConstant> &p_specialization_constants); RID _compute_pipeline_create(RID p_shader, const TypedArray<RDPipelineSpecializationConstant> &p_specialization_constants); Vector<int64_t> _draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const TypedArray<RID> &p_storage_textures = TypedArray<RID>()); void _draw_list_set_push_constant(DrawListID p_list, const Vector<uint8_t> &p_data, uint32_t p_data_size); void _compute_list_set_push_constant(ComputeListID p_list, const Vector<uint8_t> &p_data, uint32_t p_data_size); Vector<int64_t> _draw_list_switch_to_next_pass_split(uint32_t p_splits); + + struct SpirvReflectionData { + BitField<ShaderStage> stages_mask; + uint32_t vertex_input_mask; + uint32_t fragment_output_mask; + bool is_compute; + uint32_t compute_local_size[3]; + uint32_t push_constant_size; + BitField<ShaderStage> push_constant_stages_mask; + + struct Uniform { + UniformType type; + uint32_t binding; + BitField<ShaderStage> stages_mask; + uint32_t length; // Size of arrays (in total elements), or ubos (in bytes * total elements). + bool writable; + }; + Vector<Vector<Uniform>> uniforms; + + struct SpecializationConstant { + PipelineSpecializationConstantType type; + uint32_t constant_id; + union { + uint32_t int_value; + float float_value; + bool bool_value; + }; + BitField<ShaderStage> stages_mask; + }; + Vector<SpecializationConstant> specialization_constants; + }; + + Error _reflect_spirv(const Vector<ShaderStageSPIRVData> &p_spirv, SpirvReflectionData &r_reflection_data); }; VARIANT_ENUM_CAST(RenderingDevice::DeviceType) @@ -1335,9 +1374,10 @@ VARIANT_ENUM_CAST(RenderingDevice::ShaderStage) VARIANT_ENUM_CAST(RenderingDevice::ShaderLanguage) VARIANT_ENUM_CAST(RenderingDevice::CompareOperator) VARIANT_ENUM_CAST(RenderingDevice::DataFormat) +VARIANT_BITFIELD_CAST(RenderingDevice::BarrierMask); VARIANT_ENUM_CAST(RenderingDevice::TextureType) VARIANT_ENUM_CAST(RenderingDevice::TextureSamples) -VARIANT_ENUM_CAST(RenderingDevice::TextureUsageBits) +VARIANT_BITFIELD_CAST(RenderingDevice::TextureUsageBits) VARIANT_ENUM_CAST(RenderingDevice::TextureSwizzle) VARIANT_ENUM_CAST(RenderingDevice::TextureSliceType) VARIANT_ENUM_CAST(RenderingDevice::SamplerFilter) @@ -1345,7 +1385,7 @@ VARIANT_ENUM_CAST(RenderingDevice::SamplerRepeatMode) VARIANT_ENUM_CAST(RenderingDevice::SamplerBorderColor) VARIANT_ENUM_CAST(RenderingDevice::VertexFrequency) VARIANT_ENUM_CAST(RenderingDevice::IndexBufferFormat) -VARIANT_ENUM_CAST(RenderingDevice::StorageBufferUsage) +VARIANT_BITFIELD_CAST(RenderingDevice::StorageBufferUsage) VARIANT_ENUM_CAST(RenderingDevice::UniformType) VARIANT_ENUM_CAST(RenderingDevice::RenderPrimitive) VARIANT_ENUM_CAST(RenderingDevice::PolygonCullMode) @@ -1354,7 +1394,7 @@ VARIANT_ENUM_CAST(RenderingDevice::StencilOperation) VARIANT_ENUM_CAST(RenderingDevice::LogicOperation) VARIANT_ENUM_CAST(RenderingDevice::BlendFactor) VARIANT_ENUM_CAST(RenderingDevice::BlendOperation) -VARIANT_ENUM_CAST(RenderingDevice::PipelineDynamicStateFlags) +VARIANT_BITFIELD_CAST(RenderingDevice::PipelineDynamicStateFlags) VARIANT_ENUM_CAST(RenderingDevice::PipelineSpecializationConstantType) VARIANT_ENUM_CAST(RenderingDevice::InitialAction) VARIANT_ENUM_CAST(RenderingDevice::FinalAction) diff --git a/servers/rendering/rendering_device_binds.h b/servers/rendering/rendering_device_binds.h index c710bd0a10..dbff305794 100644 --- a/servers/rendering/rendering_device_binds.h +++ b/servers/rendering/rendering_device_binds.h @@ -66,7 +66,7 @@ public: RD_SETGET(uint32_t, mipmaps) RD_SETGET(RD::TextureType, texture_type) RD_SETGET(RD::TextureSamples, samples) - RD_SETGET(uint32_t, usage_bits) + RD_SETGET(BitField<RenderingDevice::TextureUsageBits>, usage_bits) void add_shareable_format(RD::DataFormat p_format) { base.shareable_formats.push_back(p_format); } void remove_shareable_format(RD::DataFormat p_format) { base.shareable_formats.erase(p_format); } diff --git a/servers/rendering/rendering_method.h b/servers/rendering/rendering_method.h index c4d9e25ecd..e3f29b51d5 100644 --- a/servers/rendering/rendering_method.h +++ b/servers/rendering/rendering_method.h @@ -72,6 +72,7 @@ public: virtual void instance_set_base(RID p_instance, RID p_base) = 0; virtual void instance_set_scenario(RID p_instance, RID p_scenario) = 0; virtual void instance_set_layer_mask(RID p_instance, uint32_t p_mask) = 0; + virtual void instance_set_pivot_data(RID p_instance, float p_sorting_offset, bool p_use_aabb_center) = 0; virtual void instance_set_transform(RID p_instance, const Transform3D &p_transform) = 0; virtual void instance_attach_object_instance_id(RID p_instance, ObjectID p_id) = 0; virtual void instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight) = 0; @@ -203,7 +204,6 @@ public: virtual RID environment_get_glow_map(RID p_env) const = 0; virtual void environment_glow_set_use_bicubic_upscale(bool p_enable) = 0; - virtual void environment_glow_set_use_high_quality(bool p_enable) = 0; // SSR diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index 6d2d0d9906..3f5b135d2a 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -212,6 +212,7 @@ public: FUNC1(texture_debug_usage, List<TextureInfo> *) FUNC2(texture_set_force_redraw_if_visible, RID, bool) + FUNC2RC(RID, texture_get_rd_texture_rid, RID, bool) /* SHADER API */ @@ -697,7 +698,6 @@ public: FUNC13(environment_set_glow, RID, bool, Vector<float>, float, float, float, float, EnvironmentGlowBlendMode, float, float, float, float, RID) FUNC1(environment_glow_set_use_bicubic_upscale, bool) - FUNC1(environment_glow_set_use_high_quality, bool) FUNC4(environment_set_tonemap, RID, EnvironmentToneMapper, float, float) @@ -762,6 +762,7 @@ public: FUNC2(instance_set_base, RID, RID) FUNC2(instance_set_scenario, RID, RID) FUNC2(instance_set_layer_mask, RID, uint32_t) + FUNC3(instance_set_pivot_data, RID, float, bool) FUNC2(instance_set_transform, RID, const Transform3D &) FUNC2(instance_attach_object_instance_id, RID, ObjectID) FUNC3(instance_set_blend_shape_weight, RID, int, float) @@ -850,7 +851,7 @@ public: FUNC4(canvas_item_add_circle, RID, const Point2 &, float, const Color &) FUNC6(canvas_item_add_texture_rect, RID, const Rect2 &, RID, bool, const Color &, bool) FUNC7(canvas_item_add_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, bool, bool) - FUNC7(canvas_item_add_msdf_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, int, float) + FUNC8(canvas_item_add_msdf_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, int, float, float) FUNC5(canvas_item_add_lcd_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &) FUNC10(canvas_item_add_nine_patch, RID, const Rect2 &, const Rect2 &, RID, const Vector2 &, const Vector2 &, NinePatchAxisMode, NinePatchAxisMode, bool, const Color &) FUNC6(canvas_item_add_primitive, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, float) diff --git a/servers/rendering/shader_compiler.cpp b/servers/rendering/shader_compiler.cpp index fc644fcae6..00b6a8c44c 100644 --- a/servers/rendering/shader_compiler.cpp +++ b/servers/rendering/shader_compiler.cpp @@ -134,6 +134,8 @@ static String _interpstr(SL::DataInterpolation p_interp) { return "flat "; case SL::INTERPOLATION_SMOOTH: return ""; + case SL::INTERPOLATION_DEFAULT: + return ""; } return ""; } @@ -667,6 +669,9 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene fragment_varyings.insert(varying_name); continue; } + if (varying.type < SL::TYPE_INT) { + continue; // Ignore boolean types to prevent crashing (if varying is just declared). + } String vcode; String interp_mode = _interpstr(varying.interpolation); @@ -1141,8 +1146,18 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene case SL::OP_STRUCT: case SL::OP_CONSTRUCT: { ERR_FAIL_COND_V(onode->arguments[0]->type != SL::Node::TYPE_VARIABLE, String()); - - SL::VariableNode *vnode = (SL::VariableNode *)onode->arguments[0]; + const SL::VariableNode *vnode = static_cast<const SL::VariableNode *>(onode->arguments[0]); + const SL::FunctionNode *func = nullptr; + const bool is_internal_func = internal_functions.has(vnode->name); + + if (!is_internal_func) { + for (int i = 0; i < shader->functions.size(); i++) { + if (shader->functions[i].name == vnode->name) { + func = shader->functions[i].function; + break; + } + } + } bool is_texture_func = false; bool is_screen_texture = false; @@ -1156,7 +1171,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene used_flag_pointers.insert(vnode->name); } - if (internal_functions.has(vnode->name)) { + if (is_internal_func) { code += vnode->name; is_texture_func = texture_functions.has(vnode->name); } else if (p_default_actions.renames.has(vnode->name)) { @@ -1172,6 +1187,44 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene if (i > 1) { code += ", "; } + + bool is_out_qualifier = false; + if (is_internal_func) { + is_out_qualifier = SL::is_builtin_func_out_parameter(vnode->name, i - 1); + } else if (func != nullptr) { + const SL::ArgumentQualifier qualifier = func->arguments[i - 1].qualifier; + is_out_qualifier = qualifier == SL::ARGUMENT_QUALIFIER_OUT || qualifier == SL::ARGUMENT_QUALIFIER_INOUT; + } + + if (is_out_qualifier) { + StringName name; + bool found = false; + { + const SL::Node *node = onode->arguments[i]; + + bool done = false; + do { + switch (node->type) { + case SL::Node::TYPE_VARIABLE: { + name = static_cast<const SL::VariableNode *>(node)->name; + done = true; + found = true; + } break; + case SL::Node::TYPE_MEMBER: { + node = static_cast<const SL::MemberNode *>(node)->owner; + } break; + default: { + done = true; + } break; + } + } while (!done); + } + + if (found && p_actions.write_flag_pointers.has(name)) { + *p_actions.write_flag_pointers[name] = true; + } + } + String node_code = _dump_node_code(onode->arguments[i], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); if (!RS::get_singleton()->is_low_end() && is_texture_func && i == 1) { //need to map from texture to sampler in order to sample when using Vulkan GLSL @@ -1239,7 +1292,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene } code += ")"; if (is_screen_texture && actions.apply_luminance_multiplier) { - code = "(" + code + " / vec4(vec3(sc_luminance_multiplier), 1.0))"; + code = "(" + code + " * vec4(vec3(sc_luminance_multiplier), 1.0))"; } } break; case SL::OP_INDEX: { diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index 2f5846f520..8c732b3d5a 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -989,6 +989,18 @@ String ShaderLanguage::get_precision_name(DataPrecision p_type) { return ""; } +String ShaderLanguage::get_interpolation_name(DataInterpolation p_interpolation) { + switch (p_interpolation) { + case INTERPOLATION_FLAT: + return "flat"; + case INTERPOLATION_SMOOTH: + return "smooth"; + default: + break; + } + return ""; +} + String ShaderLanguage::get_datatype_name(DataType p_type) { switch (p_type) { case TYPE_VOID: @@ -3645,7 +3657,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C switch (p_type) { case ShaderLanguage::TYPE_BOOL: if (array_size > 0) { - PackedInt32Array array = PackedInt32Array(); + PackedInt32Array array; for (int i = 0; i < array_size; i++) { array.push_back(p_value[i].boolean); } @@ -3658,7 +3670,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C array_size *= 2; if (array_size > 0) { - PackedInt32Array array = PackedInt32Array(); + PackedInt32Array array; for (int i = 0; i < array_size; i++) { array.push_back(p_value[i].boolean); } @@ -3671,7 +3683,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C array_size *= 3; if (array_size > 0) { - PackedInt32Array array = PackedInt32Array(); + PackedInt32Array array; for (int i = 0; i < array_size; i++) { array.push_back(p_value[i].boolean); } @@ -3684,7 +3696,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C array_size *= 4; if (array_size > 0) { - PackedInt32Array array = PackedInt32Array(); + PackedInt32Array array; for (int i = 0; i < array_size; i++) { array.push_back(p_value[i].boolean); } @@ -3695,7 +3707,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C break; case ShaderLanguage::TYPE_INT: if (array_size > 0) { - PackedInt32Array array = PackedInt32Array(); + PackedInt32Array array; for (int i = 0; i < array_size; i++) { array.push_back(p_value[i].sint); } @@ -3708,7 +3720,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C if (array_size > 0) { array_size *= 2; - PackedInt32Array array = PackedInt32Array(); + PackedInt32Array array; for (int i = 0; i < array_size; i++) { array.push_back(p_value[i].sint); } @@ -3721,7 +3733,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C if (array_size > 0) { array_size *= 3; - PackedInt32Array array = PackedInt32Array(); + PackedInt32Array array; for (int i = 0; i < array_size; i++) { array.push_back(p_value[i].sint); } @@ -3734,7 +3746,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C if (array_size > 0) { array_size *= 4; - PackedInt32Array array = PackedInt32Array(); + PackedInt32Array array; for (int i = 0; i < array_size; i++) { array.push_back(p_value[i].sint); } @@ -3745,7 +3757,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C break; case ShaderLanguage::TYPE_UINT: if (array_size > 0) { - PackedInt32Array array = PackedInt32Array(); + PackedInt32Array array; for (int i = 0; i < array_size; i++) { array.push_back(p_value[i].uint); } @@ -3758,7 +3770,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C if (array_size > 0) { array_size *= 2; - PackedInt32Array array = PackedInt32Array(); + PackedInt32Array array; for (int i = 0; i < array_size; i++) { array.push_back(p_value[i].uint); } @@ -3771,7 +3783,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C if (array_size > 0) { array_size *= 3; - PackedInt32Array array = PackedInt32Array(); + PackedInt32Array array; for (int i = 0; i < array_size; i++) { array.push_back(p_value[i].uint); } @@ -3784,7 +3796,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C if (array_size > 0) { array_size *= 4; - PackedInt32Array array = PackedInt32Array(); + PackedInt32Array array; for (int i = 0; i < array_size; i++) { array.push_back(p_value[i].uint); } @@ -3795,7 +3807,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C break; case ShaderLanguage::TYPE_FLOAT: if (array_size > 0) { - PackedFloat32Array array = PackedFloat32Array(); + PackedFloat32Array array; for (int i = 0; i < array_size; i++) { array.push_back(p_value[i].real); } @@ -3808,7 +3820,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C if (array_size > 0) { array_size *= 2; - PackedVector2Array array = PackedVector2Array(); + PackedVector2Array array; for (int i = 0; i < array_size; i += 2) { array.push_back(Vector2(p_value[i].real, p_value[i + 1].real)); } @@ -3822,13 +3834,13 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C array_size *= 3; if (p_hint == ShaderLanguage::ShaderNode::Uniform::HINT_SOURCE_COLOR) { - PackedColorArray array = PackedColorArray(); + PackedColorArray array; for (int i = 0; i < array_size; i += 3) { array.push_back(Color(p_value[i].real, p_value[i + 1].real, p_value[i + 2].real)); } value = Variant(array); } else { - PackedVector3Array array = PackedVector3Array(); + PackedVector3Array array; for (int i = 0; i < array_size; i += 3) { array.push_back(Vector3(p_value[i].real, p_value[i + 1].real, p_value[i + 2].real)); } @@ -3847,13 +3859,13 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C array_size *= 4; if (p_hint == ShaderLanguage::ShaderNode::Uniform::HINT_SOURCE_COLOR) { - PackedColorArray array = PackedColorArray(); + PackedColorArray array; for (int i = 0; i < array_size; i += 4) { array.push_back(Color(p_value[i].real, p_value[i + 1].real, p_value[i + 2].real, p_value[i + 3].real)); } value = Variant(array); } else { - PackedFloat32Array array = PackedFloat32Array(); + PackedFloat32Array array; for (int i = 0; i < array_size; i += 4) { array.push_back(p_value[i].real); array.push_back(p_value[i + 1].real); @@ -3874,7 +3886,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C if (array_size > 0) { array_size *= 4; - PackedFloat32Array array = PackedFloat32Array(); + PackedFloat32Array array; for (int i = 0; i < array_size; i += 4) { array.push_back(p_value[i].real); array.push_back(p_value[i + 1].real); @@ -3890,7 +3902,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C if (array_size > 0) { array_size *= 9; - PackedFloat32Array array = PackedFloat32Array(); + PackedFloat32Array array; for (int i = 0; i < array_size; i += 9) { for (int j = 0; j < 9; j++) { array.push_back(p_value[i + j].real); @@ -3916,7 +3928,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C if (array_size > 0) { array_size *= 16; - PackedFloat32Array array = PackedFloat32Array(); + PackedFloat32Array array; for (int i = 0; i < array_size; i += 16) { for (int j = 0; j < 16; j++) { array.push_back(p_value[i + j].real); @@ -4110,43 +4122,41 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform case ShaderLanguage::TYPE_USAMPLER2D: { if (p_uniform.array_size > 0) { pi.type = Variant::ARRAY; + pi.hint = PROPERTY_HINT_ARRAY_TYPE; + pi.hint_string = MAKE_RESOURCE_TYPE_HINT("Texture2D"); } else { pi.type = Variant::OBJECT; + pi.hint = PROPERTY_HINT_RESOURCE_TYPE; + pi.hint_string = "Texture2D"; } - pi.hint = PROPERTY_HINT_RESOURCE_TYPE; - pi.hint_string = "Texture2D"; } break; case ShaderLanguage::TYPE_SAMPLER2DARRAY: case ShaderLanguage::TYPE_ISAMPLER2DARRAY: - case ShaderLanguage::TYPE_USAMPLER2DARRAY: { + case ShaderLanguage::TYPE_USAMPLER2DARRAY: + case ShaderLanguage::TYPE_SAMPLERCUBE: + case ShaderLanguage::TYPE_SAMPLERCUBEARRAY: { if (p_uniform.array_size > 0) { pi.type = Variant::ARRAY; + pi.hint = PROPERTY_HINT_ARRAY_TYPE; + pi.hint_string = MAKE_RESOURCE_TYPE_HINT("TextureLayered"); } else { pi.type = Variant::OBJECT; + pi.hint = PROPERTY_HINT_RESOURCE_TYPE; + pi.hint_string = "TextureLayered"; } - pi.hint = PROPERTY_HINT_RESOURCE_TYPE; - pi.hint_string = "TextureLayered"; } break; case ShaderLanguage::TYPE_SAMPLER3D: case ShaderLanguage::TYPE_ISAMPLER3D: case ShaderLanguage::TYPE_USAMPLER3D: { if (p_uniform.array_size > 0) { pi.type = Variant::ARRAY; + pi.hint = PROPERTY_HINT_ARRAY_TYPE; + pi.hint_string = MAKE_RESOURCE_TYPE_HINT("Texture3D"); } else { pi.type = Variant::OBJECT; + pi.hint = PROPERTY_HINT_RESOURCE_TYPE; + pi.hint_string = "Texture3D"; } - pi.hint = PROPERTY_HINT_RESOURCE_TYPE; - pi.hint_string = "Texture3D"; - } break; - case ShaderLanguage::TYPE_SAMPLERCUBE: - case ShaderLanguage::TYPE_SAMPLERCUBEARRAY: { - if (p_uniform.array_size > 0) { - pi.type = Variant::ARRAY; - } else { - pi.type = Variant::OBJECT; - } - pi.hint = PROPERTY_HINT_RESOURCE_TYPE; - pi.hint_string = "TextureLayered"; } break; case ShaderLanguage::TYPE_STRUCT: { // FIXME: Implement this. @@ -4309,8 +4319,18 @@ ShaderLanguage::DataType ShaderLanguage::get_scalar_type(DataType p_type) { TYPE_INT, TYPE_UINT, TYPE_FLOAT, + TYPE_INT, + TYPE_UINT, + TYPE_FLOAT, + TYPE_INT, + TYPE_UINT, + TYPE_FLOAT, + TYPE_FLOAT, + TYPE_VOID, }; + static_assert(sizeof(scalar_types) / sizeof(*scalar_types) == TYPE_MAX); + return scalar_types[p_type]; } @@ -4340,8 +4360,18 @@ int ShaderLanguage::get_cardinality(DataType p_type) { 1, 1, 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, }; + static_assert(sizeof(cardinality_table) / sizeof(*cardinality_table) == TYPE_MAX); + return cardinality_table[p_type]; } @@ -4399,13 +4429,17 @@ bool ShaderLanguage::_is_operator_assign(Operator p_op) const { } bool ShaderLanguage::_validate_varying_assign(ShaderNode::Varying &p_varying, String *r_message) { - if (current_function != String("vertex") && current_function != String("fragment")) { + if (current_function != "vertex" && current_function != "fragment") { *r_message = vformat(RTR("Varying may not be assigned in the '%s' function."), current_function); return false; } switch (p_varying.stage) { case ShaderNode::Varying::STAGE_UNKNOWN: // first assign if (current_function == varying_function_names.vertex) { + if (p_varying.type < TYPE_INT) { + *r_message = vformat(RTR("Varying with '%s' data type may only be assigned in the 'fragment' function."), get_datatype_name(p_varying.type)); + return false; + } p_varying.stage = ShaderNode::Varying::STAGE_VERTEX; } else if (current_function == varying_function_names.fragment) { p_varying.stage = ShaderNode::Varying::STAGE_FRAGMENT; @@ -5205,7 +5239,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons if (shader->varyings.has(varname)) { switch (shader->varyings[varname].stage) { case ShaderNode::Varying::STAGE_UNKNOWN: { - _set_error(vformat(RTR("Varying '%s' must be assigned in the vertex or fragment function first."), varname)); + _set_error(vformat(RTR("Varying '%s' must be assigned in the 'vertex' or 'fragment' function first."), varname)); return nullptr; } case ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT_LIGHT: @@ -5389,6 +5423,16 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons } } else { switch (var.stage) { + case ShaderNode::Varying::STAGE_UNKNOWN: { + if (var.type < TYPE_INT) { + if (current_function == varying_function_names.vertex) { + _set_error(vformat(RTR("Varying with '%s' data type may only be used in the 'fragment' function."), get_datatype_name(var.type))); + } else { + _set_error(vformat(RTR("Varying '%s' must be assigned in the 'fragment' function first."), identifier)); + } + return nullptr; + } + } break; case ShaderNode::Varying::STAGE_VERTEX: if (current_function == varying_function_names.fragment || current_function == varying_function_names.light) { var.stage = ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT_LIGHT; @@ -7570,7 +7614,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun return ERR_BUG; } - if (b && b->parent_function && p_function_info.main_function) { + if (b->parent_function && p_function_info.main_function) { _set_error(vformat(RTR("Using '%s' in the '%s' processor function is incorrect."), "return", b->parent_function->name)); return ERR_PARSE_ERROR; } @@ -8170,21 +8214,27 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f }; [[fallthrough]]; case TK_INSTANCE: { + if (tk.type == TK_INSTANCE) { #ifdef DEBUG_ENABLED - keyword_completion_context = CF_UNIFORM_KEYWORD; - if (_lookup_next(next)) { - if (next.type == TK_UNIFORM) { - keyword_completion_context ^= CF_UNIFORM_KEYWORD; + keyword_completion_context = CF_UNIFORM_KEYWORD; + if (_lookup_next(next)) { + if (next.type == TK_UNIFORM) { + keyword_completion_context ^= CF_UNIFORM_KEYWORD; + } } - } #endif // DEBUG_ENABLED - if (uniform_scope == ShaderNode::Uniform::SCOPE_LOCAL) { - tk = _get_token(); - if (tk.type != TK_UNIFORM) { - _set_expected_after_error("uniform", "instance"); + if (String(shader_type_identifier) != "spatial") { + _set_error(vformat(RTR("Uniform instances are not yet implemented for '%s' shaders."), shader_type_identifier)); return ERR_PARSE_ERROR; } - uniform_scope = ShaderNode::Uniform::SCOPE_INSTANCE; + if (uniform_scope == ShaderNode::Uniform::SCOPE_LOCAL) { + tk = _get_token(); + if (tk.type != TK_UNIFORM) { + _set_expected_after_error("uniform", "instance"); + return ERR_PARSE_ERROR; + } + uniform_scope = ShaderNode::Uniform::SCOPE_INSTANCE; + } } }; [[fallthrough]]; @@ -8201,7 +8251,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f } } DataPrecision precision = PRECISION_DEFAULT; - DataInterpolation interpolation = INTERPOLATION_SMOOTH; + DataInterpolation interpolation = INTERPOLATION_DEFAULT; DataType type; StringName name; int array_size = 0; @@ -8310,6 +8360,11 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f return ERR_PARSE_ERROR; } + if (!is_uniform && interpolation != INTERPOLATION_DEFAULT && type < TYPE_INT) { + _set_error(vformat(RTR("Interpolation modifier '%s' cannot be used with boolean types."), get_interpolation_name(interpolation))); + return ERR_PARSE_ERROR; + } + if (!is_uniform && type > TYPE_MAT4) { _set_error(RTR("Invalid data type for varying.")); return ERR_PARSE_ERROR; @@ -8854,7 +8909,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f _set_error(RTR("Expected an uniform group identifier or `;`.")); } return ERR_PARSE_ERROR; - } else if (tk.type == TK_SEMICOLON && current_uniform_group_name.is_empty()) { + } else if (current_uniform_group_name.is_empty()) { _set_error(RTR("Group needs to be opened before.")); return ERR_PARSE_ERROR; } else { @@ -9713,6 +9768,25 @@ String ShaderLanguage::get_shader_type(const String &p_code) { return String(); } +bool ShaderLanguage::is_builtin_func_out_parameter(const String &p_name, int p_param) { + int i = 0; + while (builtin_func_out_args[i].name) { + if (p_name == builtin_func_out_args[i].name) { + for (int j = 0; j < BuiltinFuncOutArgs::MAX_ARGS; j++) { + int arg = builtin_func_out_args[i].arguments[j]; + if (arg == p_param) { + return true; + } + if (arg < 0) { + return false; + } + } + } + i++; + } + return false; +} + #ifdef DEBUG_ENABLED void ShaderLanguage::_check_warning_accums() { for (const KeyValue<ShaderWarning::Code, HashMap<StringName, HashMap<StringName, Usage>> *> &E : warnings_check_map2) { diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h index 1e302f5805..d34114589f 100644 --- a/servers/rendering/shader_language.h +++ b/servers/rendering/shader_language.h @@ -247,6 +247,7 @@ public: enum DataInterpolation { INTERPOLATION_FLAT, INTERPOLATION_SMOOTH, + INTERPOLATION_DEFAULT, }; enum Operator { @@ -720,6 +721,12 @@ public: Node(TYPE_SHADER) {} }; + struct UniformOrderComparator { + _FORCE_INLINE_ bool operator()(const Pair<StringName, int> &A, const Pair<StringName, int> &B) const { + return A.second < B.second; + } + }; + struct Expression { bool is_op; union { @@ -768,6 +775,7 @@ public: static bool is_token_arg_qual(TokenType p_type); static DataPrecision get_token_precision(TokenType p_type); static String get_precision_name(DataPrecision p_type); + static String get_interpolation_name(DataInterpolation p_interpolation); static String get_datatype_name(DataType p_type); static String get_uniform_hint_name(ShaderNode::Uniform::Hint p_hint); static String get_texture_filter_name(TextureFilter p_filter); @@ -1119,6 +1127,7 @@ public: void clear(); static String get_shader_type(const String &p_code); + static bool is_builtin_func_out_parameter(const String &p_name, int p_param); struct ShaderCompileInfo { HashMap<StringName, FunctionInfo> functions; diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp index 5e1da7c15d..86dd6a8b7e 100644 --- a/servers/rendering/shader_types.cpp +++ b/servers/rendering/shader_types.cpp @@ -100,6 +100,7 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["NODE_POSITION_WORLD"] = ShaderLanguage::TYPE_VEC3; shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["CAMERA_POSITION_WORLD"] = ShaderLanguage::TYPE_VEC3; shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["CAMERA_DIRECTION_WORLD"] = ShaderLanguage::TYPE_VEC3; + shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["CAMERA_VISIBLE_LAYERS"] = ShaderLanguage::TYPE_UINT; shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["NODE_POSITION_VIEW"] = ShaderLanguage::TYPE_VEC3; shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEW_INDEX"] = constt(ShaderLanguage::TYPE_INT); @@ -147,6 +148,7 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["NODE_POSITION_WORLD"] = ShaderLanguage::TYPE_VEC3; shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["CAMERA_POSITION_WORLD"] = ShaderLanguage::TYPE_VEC3; shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["CAMERA_DIRECTION_WORLD"] = ShaderLanguage::TYPE_VEC3; + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["CAMERA_VISIBLE_LAYERS"] = ShaderLanguage::TYPE_UINT; shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["NODE_POSITION_VIEW"] = ShaderLanguage::TYPE_VEC3; shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEW_INDEX"] = constt(ShaderLanguage::TYPE_INT); diff --git a/servers/rendering/storage/environment_storage.cpp b/servers/rendering/storage/environment_storage.cpp index 9b1842f1d9..78ce4eb4d0 100644 --- a/servers/rendering/storage/environment_storage.cpp +++ b/servers/rendering/storage/environment_storage.cpp @@ -283,7 +283,7 @@ void RendererEnvironmentStorage::environment_set_volumetric_fog(RID p_env, bool env->volumetric_fog_scattering = p_albedo; env->volumetric_fog_emission = p_emission; env->volumetric_fog_emission_energy = p_emission_energy; - env->volumetric_fog_anisotropy = p_anisotropy, + env->volumetric_fog_anisotropy = p_anisotropy; env->volumetric_fog_length = p_length; env->volumetric_fog_detail_spread = p_detail_spread; env->volumetric_fog_gi_inject = p_gi_inject; diff --git a/servers/rendering/storage/environment_storage.h b/servers/rendering/storage/environment_storage.h index 17bde94902..dea9487af6 100644 --- a/servers/rendering/storage/environment_storage.h +++ b/servers/rendering/storage/environment_storage.h @@ -98,7 +98,7 @@ private: float glow_hdr_luminance_cap = 12.0; float glow_hdr_bleed_scale = 2.0; float glow_map_strength = 0.0f; // 1.0f in GLES3 ?? - RID glow_map = RID(); + RID glow_map; // SSR bool ssr_enabled = false; @@ -143,7 +143,7 @@ private: float adjustments_contrast = 1.0f; float adjustments_saturation = 1.0f; bool use_1d_color_correction = false; - RID color_correction = RID(); + RID color_correction; }; mutable RID_Owner<Environment, true> environment_owner; diff --git a/servers/rendering/storage/light_storage.h b/servers/rendering/storage/light_storage.h index df5b893cd5..ea3b4d4c44 100644 --- a/servers/rendering/storage/light_storage.h +++ b/servers/rendering/storage/light_storage.h @@ -31,6 +31,7 @@ #ifndef LIGHT_STORAGE_H #define LIGHT_STORAGE_H +#include "render_scene_buffers.h" #include "servers/rendering_server.h" class RendererLightStorage { @@ -142,6 +143,7 @@ public: virtual bool reflection_probe_instance_needs_redraw(RID p_instance) = 0; virtual bool reflection_probe_instance_has_reflection(RID p_instance) = 0; virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) = 0; + virtual Ref<RenderSceneBuffers> reflection_probe_atlas_get_render_buffers(RID p_reflection_atlas) = 0; virtual bool reflection_probe_instance_postprocess_step(RID p_instance) = 0; /* LIGHTMAP */ diff --git a/servers/rendering/storage/particles_storage.h b/servers/rendering/storage/particles_storage.h index ee4b8679b3..5ef54346f2 100644 --- a/servers/rendering/storage/particles_storage.h +++ b/servers/rendering/storage/particles_storage.h @@ -94,8 +94,6 @@ public: virtual void particles_add_collision(RID p_particles, RID p_particles_collision_instance) = 0; virtual void particles_remove_collision(RID p_particles, RID p_particles_collision_instance) = 0; - virtual void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) = 0; - virtual void update_particles() = 0; /* PARTICLES COLLISION */ @@ -116,7 +114,6 @@ public: virtual void particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) = 0; //for SDF and vector field virtual AABB particles_collision_get_aabb(RID p_particles_collision) const = 0; virtual bool particles_collision_is_heightfield(RID p_particles_collision) const = 0; - virtual RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const = 0; //used from 2D and 3D virtual RID particles_collision_instance_create(RID p_collision) = 0; diff --git a/servers/rendering/storage/texture_storage.h b/servers/rendering/storage/texture_storage.h index 3207181471..31fb5e8791 100644 --- a/servers/rendering/storage/texture_storage.h +++ b/servers/rendering/storage/texture_storage.h @@ -100,6 +100,8 @@ public: virtual Size2 texture_size_with_proxy(RID p_proxy) = 0; + virtual RID texture_get_rd_texture_rid(RID p_texture, bool p_srgb = false) const = 0; + /* Decal API */ virtual RID decal_allocate() = 0; virtual void decal_initialize(RID p_rid) = 0; |