diff options
author | Spartan322 <Megacake1234@gmail.com> | 2024-10-30 05:22:24 -0400 |
---|---|---|
committer | Spartan322 <Megacake1234@gmail.com> | 2024-10-30 05:22:24 -0400 |
commit | 82de309d58c5f0e221b85463cca2983cd7ed0289 (patch) | |
tree | 5c87dc486c61310a1eafc2e7cb2fd52be0d52e22 /servers/rendering | |
parent | 77eaec766e2e40f2a5d399989d827f9582a3be15 (diff) | |
parent | 8004c7524fb9f43425c4d6f614410a76678e0f7c (diff) | |
download | redot-engine-82de309d58c5f0e221b85463cca2983cd7ed0289.tar.gz |
Merge commit godotengine/godot@8004c7524fb9f43425c4d6f614410a76678e0f7c
Diffstat (limited to 'servers/rendering')
37 files changed, 655 insertions, 242 deletions
diff --git a/servers/rendering/dummy/rasterizer_dummy.h b/servers/rendering/dummy/rasterizer_dummy.h index d7996a2ec1..11a019b563 100644 --- a/servers/rendering/dummy/rasterizer_dummy.h +++ b/servers/rendering/dummy/rasterizer_dummy.h @@ -68,14 +68,14 @@ protected: RasterizerSceneDummy scene; public: - RendererUtilities *get_utilities() override { return &utilities; }; - RendererLightStorage *get_light_storage() override { return &light_storage; }; - RendererMaterialStorage *get_material_storage() override { return &material_storage; }; - RendererMeshStorage *get_mesh_storage() override { return &mesh_storage; }; - RendererParticlesStorage *get_particles_storage() override { return &particles_storage; }; - RendererTextureStorage *get_texture_storage() override { return &texture_storage; }; - RendererGI *get_gi() override { return &gi; }; - RendererFog *get_fog() override { return &fog; }; + RendererUtilities *get_utilities() override { return &utilities; } + RendererLightStorage *get_light_storage() override { return &light_storage; } + RendererMaterialStorage *get_material_storage() override { return &material_storage; } + RendererMeshStorage *get_mesh_storage() override { return &mesh_storage; } + RendererParticlesStorage *get_particles_storage() override { return &particles_storage; } + RendererTextureStorage *get_texture_storage() override { return &texture_storage; } + RendererGI *get_gi() override { return &gi; } + RendererFog *get_fog() override { return &fog; } RendererCanvasRender *get_canvas() override { return &canvas; } RendererSceneRender *get_scene() override { return &scene; } diff --git a/servers/rendering/dummy/storage/material_storage.h b/servers/rendering/dummy/storage/material_storage.h index 423544201c..f55ef24473 100644 --- a/servers/rendering/dummy/storage/material_storage.h +++ b/servers/rendering/dummy/storage/material_storage.h @@ -94,7 +94,7 @@ public: virtual RID shader_get_default_texture_parameter(RID p_shader, const StringName &p_name, int p_index) const override { return RID(); } virtual Variant shader_get_parameter_default(RID p_material, const StringName &p_param) const override { return Variant(); } - virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const override { return RS::ShaderNativeSourceCode(); }; + virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const override { return RS::ShaderNativeSourceCode(); } /* MATERIAL API */ virtual RID material_allocate() override { return RID(); } diff --git a/servers/rendering/dummy/storage/mesh_storage.h b/servers/rendering/dummy/storage/mesh_storage.h index 41381e2b2f..37959ffb7f 100644 --- a/servers/rendering/dummy/storage/mesh_storage.h +++ b/servers/rendering/dummy/storage/mesh_storage.h @@ -66,7 +66,7 @@ public: /* MESH API */ - bool owns_mesh(RID p_rid) { return mesh_owner.owns(p_rid); }; + bool owns_mesh(RID p_rid) { return mesh_owner.owns(p_rid); } virtual RID mesh_allocate() override; virtual void mesh_initialize(RID p_rid) override; diff --git a/servers/rendering/dummy/storage/texture_storage.h b/servers/rendering/dummy/storage/texture_storage.h index e5167af9ed..4b61ac1722 100644 --- a/servers/rendering/dummy/storage/texture_storage.h +++ b/servers/rendering/dummy/storage/texture_storage.h @@ -55,7 +55,7 @@ public: /* Canvas Texture API */ - virtual RID canvas_texture_allocate() override { return RID(); }; + virtual RID canvas_texture_allocate() override { return RID(); } virtual void canvas_texture_initialize(RID p_rid) override {} virtual void canvas_texture_free(RID p_rid) override {} @@ -67,13 +67,13 @@ public: /* Texture API */ - bool owns_texture(RID p_rid) { return texture_owner.owns(p_rid); }; + bool owns_texture(RID p_rid) { return texture_owner.owns(p_rid); } virtual RID texture_allocate() override { DummyTexture *texture = memnew(DummyTexture); ERR_FAIL_NULL_V(texture, RID()); return texture_owner.make_rid(texture); - }; + } virtual void texture_free(RID p_rid) override { // delete the texture @@ -81,13 +81,13 @@ public: ERR_FAIL_NULL(texture); texture_owner.free(p_rid); memdelete(texture); - }; + } virtual void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) override { DummyTexture *t = texture_owner.get_or_null(p_texture); ERR_FAIL_NULL(t); t->image = p_image->duplicate(); - }; + } virtual void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) override {} virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) override {} virtual void texture_external_initialize(RID p_texture, int p_width, int p_height, uint64_t p_external_buffer) override {} @@ -109,15 +109,15 @@ public: DummyTexture *t = texture_owner.get_or_null(p_texture); ERR_FAIL_NULL_V(t, Ref<Image>()); return t->image; - }; - virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const override { return Ref<Image>(); }; - virtual Vector<Ref<Image>> texture_3d_get(RID p_texture) const override { return Vector<Ref<Image>>(); }; + } + virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const override { return Ref<Image>(); } + virtual Vector<Ref<Image>> texture_3d_get(RID p_texture) const override { return Vector<Ref<Image>>(); } - virtual void texture_replace(RID p_texture, RID p_by_texture) override { texture_free(p_by_texture); }; + virtual void texture_replace(RID p_texture, RID p_by_texture) override { texture_free(p_by_texture); } virtual void texture_set_size_override(RID p_texture, int p_width, int p_height) override {} virtual void texture_set_path(RID p_texture, const String &p_path) override {} - virtual String texture_get_path(RID p_texture) const override { return String(); }; + virtual String texture_get_path(RID p_texture) const override { return String(); } virtual Image::Format texture_get_format(RID p_texture) const override { return Image::FORMAT_MAX; } @@ -129,11 +129,11 @@ public: virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) override {} - virtual Size2 texture_size_with_proxy(RID p_proxy) override { return Size2(); }; + virtual Size2 texture_size_with_proxy(RID p_proxy) override { return Size2(); } virtual void texture_rd_initialize(RID p_texture, const RID &p_rd_texture, const RS::TextureLayeredType p_layer_type = RS::TEXTURE_LAYERED_2D_ARRAY) override {} - virtual RID texture_get_rd_texture(RID p_texture, bool p_srgb = false) const override { return RID(); }; - virtual uint64_t texture_get_native_handle(RID p_texture, bool p_srgb = false) const override { return 0; }; + virtual RID texture_get_rd_texture(RID p_texture, bool p_srgb = false) const override { return RID(); } + virtual uint64_t texture_get_native_handle(RID p_texture, bool p_srgb = false) const override { return 0; } /* DECAL API */ virtual RID decal_allocate() override { return RID(); } diff --git a/servers/rendering/dummy/storage/utilities.h b/servers/rendering/dummy/storage/utilities.h index 009d3ca5ad..d4faad59f5 100644 --- a/servers/rendering/dummy/storage/utilities.h +++ b/servers/rendering/dummy/storage/utilities.h @@ -126,7 +126,7 @@ public: virtual RenderingDevice::DeviceType get_video_adapter_type() const override { return RenderingDevice::DeviceType::DEVICE_TYPE_OTHER; } virtual String get_video_adapter_api_version() const override { return String(); } - virtual Size2i get_maximum_viewport_size() const override { return Size2i(); }; + virtual Size2i get_maximum_viewport_size() const override { return Size2i(); } }; } // namespace RendererDummy diff --git a/servers/rendering/renderer_compositor.h b/servers/rendering/renderer_compositor.h index 75567a8f1a..ddfc29cd2c 100644 --- a/servers/rendering/renderer_compositor.h +++ b/servers/rendering/renderer_compositor.h @@ -108,7 +108,7 @@ public: virtual double get_total_time() const = 0; virtual bool can_create_resources_async() const = 0; - static bool is_low_end() { return low_end; }; + static bool is_low_end() { return low_end; } virtual bool is_xr_enabled() const; static RendererCompositor *get_singleton() { return singleton; } diff --git a/servers/rendering/renderer_rd/environment/fog.cpp b/servers/rendering/renderer_rd/environment/fog.cpp index 4cdb38fd29..48300571d4 100644 --- a/servers/rendering/renderer_rd/environment/fog.cpp +++ b/servers/rendering/renderer_rd/environment/fog.cpp @@ -159,7 +159,7 @@ RendererRD::MaterialStorage::ShaderData *Fog::_create_fog_shader_func() { RendererRD::MaterialStorage::ShaderData *Fog::_create_fog_shader_funcs() { return Fog::get_singleton()->_create_fog_shader_func(); -}; +} RendererRD::MaterialStorage::MaterialData *Fog::_create_fog_material_func(FogShaderData *p_shader) { FogMaterialData *material_data = memnew(FogMaterialData); @@ -170,7 +170,7 @@ RendererRD::MaterialStorage::MaterialData *Fog::_create_fog_material_func(FogSha RendererRD::MaterialStorage::MaterialData *Fog::_create_fog_material_funcs(RendererRD::MaterialStorage::ShaderData *p_shader) { return Fog::get_singleton()->_create_fog_material_func(static_cast<FogShaderData *>(p_shader)); -}; +} //////////////////////////////////////////////////////////////////////////////// // FOG VOLUMES INSTANCE diff --git a/servers/rendering/renderer_rd/environment/fog.h b/servers/rendering/renderer_rd/environment/fog.h index a05a48b064..390829962f 100644 --- a/servers/rendering/renderer_rd/environment/fog.h +++ b/servers/rendering/renderer_rd/environment/fog.h @@ -235,7 +235,7 @@ public: /* FOG VOLUMES */ - bool owns_fog_volume(RID p_rid) { return fog_volume_owner.owns(p_rid); }; + bool owns_fog_volume(RID p_rid) { return fog_volume_owner.owns(p_rid); } virtual RID fog_volume_allocate() override; virtual void fog_volume_initialize(RID p_rid) override; @@ -252,7 +252,7 @@ public: /* FOG VOLUMES INSTANCE */ - bool owns_fog_volume_instance(RID p_rid) { return fog_volume_instance_owner.owns(p_rid); }; + bool owns_fog_volume_instance(RID p_rid) { return fog_volume_instance_owner.owns(p_rid); } RID fog_volume_instance_create(RID p_fog_volume); void fog_instance_free(RID p_rid); diff --git a/servers/rendering/renderer_rd/environment/gi.h b/servers/rendering/renderer_rd/environment/gi.h index 7c83f7b954..e3c5f4fea2 100644 --- a/servers/rendering/renderer_rd/environment/gi.h +++ b/servers/rendering/renderer_rd/environment/gi.h @@ -469,7 +469,7 @@ public: /* VOXEL GI API */ - bool owns_voxel_gi(RID p_rid) { return voxel_gi_owner.owns(p_rid); }; + bool owns_voxel_gi(RID p_rid) { return voxel_gi_owner.owns(p_rid); } virtual RID voxel_gi_allocate() override; virtual void voxel_gi_free(RID p_voxel_gi) override; @@ -526,14 +526,14 @@ public: VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe); ERR_FAIL_NULL_V(voxel_gi, RID()); return voxel_gi->texture; - }; + } _FORCE_INLINE_ void voxel_gi_instance_set_render_index(RID p_probe, uint32_t p_index) { VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe); ERR_FAIL_NULL(voxel_gi); voxel_gi->render_index = p_index; - }; + } bool voxel_gi_instance_owns(RID p_rid) const { return voxel_gi_instance_owner.owns(p_rid); diff --git a/servers/rendering/renderer_rd/environment/sky.cpp b/servers/rendering/renderer_rd/environment/sky.cpp index 9464d6e249..e71e3f6efb 100644 --- a/servers/rendering/renderer_rd/environment/sky.cpp +++ b/servers/rendering/renderer_rd/environment/sky.cpp @@ -703,7 +703,7 @@ RendererRD::MaterialStorage::ShaderData *SkyRD::_create_sky_shader_func() { RendererRD::MaterialStorage::ShaderData *SkyRD::_create_sky_shader_funcs() { // !BAS! Why isn't _create_sky_shader_func not just static too? return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->sky._create_sky_shader_func(); -}; +} RendererRD::MaterialStorage::MaterialData *SkyRD::_create_sky_material_func(SkyShaderData *p_shader) { SkyMaterialData *material_data = memnew(SkyMaterialData); @@ -715,7 +715,7 @@ RendererRD::MaterialStorage::MaterialData *SkyRD::_create_sky_material_func(SkyS RendererRD::MaterialStorage::MaterialData *SkyRD::_create_sky_material_funcs(RendererRD::MaterialStorage::ShaderData *p_shader) { // !BAS! same here, we could just make _create_sky_material_func static? return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->sky._create_sky_material_func(static_cast<SkyShaderData *>(p_shader)); -}; +} SkyRD::SkyRD() { roughness_layers = GLOBAL_GET("rendering/reflections/sky_reflections/roughness_layers"); 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 b58ed162ef..014bdeba8d 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 @@ -110,10 +110,10 @@ public: uint32_t projector_use_mipmaps : 1; uint32_t use_depth_fog : 1; uint32_t use_lightmap_bicubic_filter : 1; - uint32_t soft_shadow_samples : 4; - uint32_t penumbra_shadow_samples : 4; - uint32_t directional_soft_shadow_samples : 4; - uint32_t directional_penumbra_shadow_samples : 4; + uint32_t soft_shadow_samples : 6; + uint32_t penumbra_shadow_samples : 6; + uint32_t directional_soft_shadow_samples : 6; + uint32_t directional_penumbra_shadow_samples : 6; }; uint32_t packed_0; 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 2de13593c3..71f071e44e 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 @@ -324,7 +324,12 @@ void SceneShaderForwardMobile::ShaderData::_create_pipeline(PipelineKey p_pipeli specialization_constants.push_back(sc); sc.constant_id = 1; - sc.float_value = p_pipeline_key.shader_specialization.packed_1; + sc.int_value = p_pipeline_key.shader_specialization.packed_1; + sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_INT; + specialization_constants.push_back(sc); + + sc.constant_id = 2; + sc.float_value = p_pipeline_key.shader_specialization.packed_2; sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_FLOAT; specialization_constants.push_back(sc); 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 e338ef09df..60216e9b48 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 @@ -76,22 +76,23 @@ public: uint32_t use_depth_fog : 1; uint32_t is_multimesh : 1; uint32_t use_lightmap_bicubic_filter : 1; - uint32_t pad : 2; - uint32_t soft_shadow_samples : 4; - uint32_t penumbra_shadow_samples : 4; - uint32_t directional_soft_shadow_samples : 4; - uint32_t directional_penumbra_shadow_samples : 4; + uint32_t soft_shadow_samples : 6; + uint32_t penumbra_shadow_samples : 6; + uint32_t directional_soft_shadow_samples : 6; }; uint32_t packed_0; }; union { - float luminance_multiplier; - float packed_1; + uint32_t directional_penumbra_shadow_samples : 6; + uint32_t packed_1; }; - uint32_t packed_2; + union { + float luminance_multiplier; + float packed_2; + }; }; struct UbershaderConstants { diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index 16b4a5792f..42c73c544a 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -913,7 +913,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p RenderingServerDefault::redraw_request(); } - state.current_data_buffer_index = (state.current_data_buffer_index + 1) % state.canvas_instance_data_buffers.size(); + state.current_data_buffer_index = (state.current_data_buffer_index + 1) % BATCH_DATA_BUFFER_COUNT; state.current_instance_buffer_index = 0; } @@ -1649,6 +1649,9 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() { default_samplers.default_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED; } + // preallocate 5 slots for uniform set 3 + state.batch_texture_uniforms.resize(5); + { //shader variants String global_defines; @@ -1976,15 +1979,18 @@ void fragment() { } { + uint32_t cache_size = uint32_t(GLOBAL_GET("rendering/2d/batching/uniform_set_cache_size")); + rid_set_to_uniform_set.set_capacity(cache_size); + } + + { state.max_instances_per_buffer = uint32_t(GLOBAL_GET("rendering/2d/batching/item_buffer_size")); state.max_instance_buffer_size = state.max_instances_per_buffer * sizeof(InstanceData); - state.canvas_instance_data_buffers.resize(3); state.canvas_instance_batches.reserve(200); - for (int i = 0; i < 3; i++) { - DataBuffer db; + for (uint32_t i = 0; i < BATCH_DATA_BUFFER_COUNT; i++) { + DataBuffer &db = state.canvas_instance_data_buffers[i]; db.instance_buffers.push_back(RD::get_singleton()->storage_buffer_create(state.max_instance_buffer_size)); - state.canvas_instance_data_buffers[i] = db; } state.instance_data_array = memnew_arr(InstanceData, state.max_instances_per_buffer); } @@ -2161,7 +2167,7 @@ void RendererCanvasRenderRD::_render_batch_items(RenderTarget p_to_render_target RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(framebuffer); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, clear ? RD::INITIAL_ACTION_CLEAR : RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD, clear_colors); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, clear ? RD::INITIAL_ACTION_CLEAR : RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD, clear_colors, 1, 0, Rect2(), RDD::BreadcrumbMarker::UI_PASS); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, fb_uniform_set, BASE_UNIFORM_SET); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, state.default_transforms_uniform_set, TRANSFORMS_UNIFORM_SET); @@ -2205,14 +2211,47 @@ void RendererCanvasRenderRD::_render_batch_items(RenderTarget p_to_render_target RD::get_singleton()->draw_list_end(); + texture_info_map.clear(); state.current_batch_index = 0; state.canvas_instance_batches.clear(); state.last_instance_index += instance_index; } +RendererCanvasRenderRD::InstanceData *RendererCanvasRenderRD::new_instance_data(float *p_world, uint32_t *p_lights, uint32_t p_base_flags, uint32_t p_index, TextureInfo *p_info) { + InstanceData *instance_data = &state.instance_data_array[p_index]; + // Zero out most fields. + for (int i = 0; i < 4; i++) { + instance_data->modulation[i] = 0.0; + instance_data->ninepatch_margins[i] = 0.0; + instance_data->src_rect[i] = 0.0; + instance_data->dst_rect[i] = 0.0; + } + + instance_data->pad[0] = 0.0; + instance_data->pad[1] = 0.0; + + instance_data->lights[0] = p_lights[0]; + instance_data->lights[1] = p_lights[1]; + instance_data->lights[2] = p_lights[2]; + instance_data->lights[3] = p_lights[3]; + + for (int i = 0; i < 6; i++) { + instance_data->world[i] = p_world[i]; + } + + instance_data->flags = p_base_flags | p_info->flags; // Reset on each command for safety, keep canvas texture binding config. + + instance_data->color_texture_pixel_size[0] = p_info->texpixel_size.width; + instance_data->color_texture_pixel_size[1] = p_info->texpixel_size.height; + + instance_data->pad1 = 0; + + return instance_data; +} + void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTarget p_render_target, const Transform2D &p_base_transform, Item *&r_current_clip, Light *p_lights, uint32_t &r_index, bool &r_batch_broken, bool &r_sdf_used, Batch *&r_current_batch) { - RenderingServer::CanvasItemTextureFilter texture_filter = p_item->texture_filter == RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT ? default_filter : p_item->texture_filter; - RenderingServer::CanvasItemTextureRepeat texture_repeat = p_item->texture_repeat == RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT ? default_repeat : p_item->texture_repeat; + const RenderingServer::CanvasItemTextureFilter texture_filter = p_item->texture_filter == RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT ? default_filter : p_item->texture_filter; + const RenderingServer::CanvasItemTextureRepeat texture_repeat = p_item->texture_repeat == RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT ? default_repeat : p_item->texture_repeat; Transform2D base_transform = p_base_transform; @@ -2243,7 +2282,7 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar light_count++; - if (light_count == state.max_lights_per_item - 1) { + if (light_count == MAX_LIGHTS_PER_ITEM - 1) { break; } } @@ -2260,38 +2299,6 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar r_current_batch->use_lighting = use_lighting; } - // new_instance_data should be called after the current_batch is set. - auto new_instance_data = [&]() -> InstanceData * { - InstanceData *instance_data = &state.instance_data_array[r_index]; - // Zero out most fields. - for (int i = 0; i < 4; i++) { - instance_data->modulation[i] = 0.0; - instance_data->ninepatch_margins[i] = 0.0; - instance_data->src_rect[i] = 0.0; - instance_data->dst_rect[i] = 0.0; - } - - instance_data->pad[0] = 0.0; - instance_data->pad[1] = 0.0; - - instance_data->lights[0] = lights[0]; - instance_data->lights[1] = lights[1]; - instance_data->lights[2] = lights[2]; - instance_data->lights[3] = lights[3]; - - for (int i = 0; i < 6; i++) { - instance_data->world[i] = world[i]; - } - - instance_data->flags = base_flags | r_current_batch->tex_info.flags; // Reset on each command for safety, keep canvas texture binding config. - - instance_data->color_texture_pixel_size[0] = r_current_batch->tex_info.texpixel_size.width; - instance_data->color_texture_pixel_size[1] = r_current_batch->tex_info.texpixel_size.height; - instance_data->specular_shininess = r_current_batch->tex_info.specular_shininess; - - return instance_data; - }; - const Item::Command *c = p_item->commands; while (c) { if (skipping && c->type != Item::Command::TYPE_ANIMATION_SLICE) { @@ -2313,17 +2320,9 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar r_current_batch->render_primitive = RD::RENDER_PRIMITIVE_TRIANGLES; } + RenderingServer::CanvasItemTextureRepeat rect_repeat = texture_repeat; if (bool(rect->flags & CANVAS_RECT_TILE)) { - texture_repeat = RenderingServer::CanvasItemTextureRepeat::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED; - } - - bool has_msdf = bool(rect->flags & CANVAS_RECT_MSDF); - TextureState tex_state(rect->texture, texture_filter, texture_repeat, has_msdf, use_linear_colors); - - if (tex_state != r_current_batch->tex_info.state) { - r_current_batch = _new_batch(r_batch_broken); - r_current_batch->tex_info.state = tex_state; - _prepare_batch_texture_info(r_current_batch, rect->texture); + rect_repeat = RenderingServer::CanvasItemTextureRepeat::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED; } Color modulated = rect->modulate * base_color; @@ -2342,12 +2341,25 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar r_current_batch->render_primitive = RD::RENDER_PRIMITIVE_TRIANGLES; } - InstanceData *instance_data = new_instance_data(); + bool has_msdf = bool(rect->flags & CANVAS_RECT_MSDF); + TextureState tex_state(rect->texture, texture_filter, rect_repeat, has_msdf, use_linear_colors); + TextureInfo *tex_info = texture_info_map.getptr(tex_state); + if (!tex_info) { + tex_info = &texture_info_map.insert(tex_state, TextureInfo())->value; + _prepare_batch_texture_info(rect->texture, tex_state, tex_info); + } + + if (r_current_batch->tex_info != tex_info) { + r_current_batch = _new_batch(r_batch_broken); + r_current_batch->tex_info = tex_info; + } + + InstanceData *instance_data = new_instance_data(world, lights, base_flags, r_index, tex_info); Rect2 src_rect; Rect2 dst_rect; if (rect->texture.is_valid()) { - src_rect = (rect->flags & CANVAS_RECT_REGION) ? Rect2(rect->source.position * r_current_batch->tex_info.texpixel_size, rect->source.size * r_current_batch->tex_info.texpixel_size) : Rect2(0, 0, 1, 1); + src_rect = (rect->flags & CANVAS_RECT_REGION) ? Rect2(rect->source.position * tex_info->texpixel_size, rect->source.size * tex_info->texpixel_size) : Rect2(0, 0, 1, 1); dst_rect = Rect2(rect->rect.position, rect->rect.size); if (dst_rect.size.width < 0) { @@ -2433,13 +2445,18 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar } TextureState tex_state(np->texture, texture_filter, texture_repeat, false, use_linear_colors); - if (tex_state != r_current_batch->tex_info.state) { + TextureInfo *tex_info = texture_info_map.getptr(tex_state); + if (!tex_info) { + tex_info = &texture_info_map.insert(tex_state, TextureInfo())->value; + _prepare_batch_texture_info(np->texture, tex_state, tex_info); + } + + if (r_current_batch->tex_info != tex_info) { r_current_batch = _new_batch(r_batch_broken); - r_current_batch->tex_info.state = tex_state; - _prepare_batch_texture_info(r_current_batch, np->texture); + r_current_batch->tex_info = tex_info; } - InstanceData *instance_data = new_instance_data(); + InstanceData *instance_data = new_instance_data(world, lights, base_flags, r_index, tex_info); Rect2 src_rect; Rect2 dst_rect(np->rect.position.x, np->rect.position.y, np->rect.size.x, np->rect.size.y); @@ -2448,7 +2465,7 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar src_rect = Rect2(0, 0, 1, 1); } else { if (np->source != Rect2()) { - src_rect = Rect2(np->source.position.x * r_current_batch->tex_info.texpixel_size.width, np->source.position.y * r_current_batch->tex_info.texpixel_size.height, np->source.size.x * r_current_batch->tex_info.texpixel_size.width, np->source.size.y * r_current_batch->tex_info.texpixel_size.height); + src_rect = Rect2(np->source.position.x * tex_info->texpixel_size.width, np->source.position.y * tex_info->texpixel_size.height, np->source.size.x * tex_info->texpixel_size.width, np->source.size.y * tex_info->texpixel_size.height); instance_data->color_texture_pixel_size[0] = 1.0 / np->source.size.width; instance_data->color_texture_pixel_size[1] = 1.0 / np->source.size.height; } else { @@ -2502,10 +2519,15 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar r_current_batch->command = c; TextureState tex_state(polygon->texture, texture_filter, texture_repeat, false, use_linear_colors); - if (tex_state != r_current_batch->tex_info.state) { + TextureInfo *tex_info = texture_info_map.getptr(tex_state); + if (!tex_info) { + tex_info = &texture_info_map.insert(tex_state, TextureInfo())->value; + _prepare_batch_texture_info(polygon->texture, tex_state, tex_info); + } + + if (r_current_batch->tex_info != tex_info) { r_current_batch = _new_batch(r_batch_broken); - r_current_batch->tex_info.state = tex_state; - _prepare_batch_texture_info(r_current_batch, polygon->texture); + r_current_batch->tex_info = tex_info; } // pipeline variant @@ -2515,7 +2537,7 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar r_current_batch->render_primitive = _primitive_type_to_render_primitive(polygon->primitive); } - InstanceData *instance_data = new_instance_data(); + InstanceData *instance_data = new_instance_data(world, lights, base_flags, r_index, tex_info); Color color = base_color; if (use_linear_colors) { @@ -2559,17 +2581,22 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar default: // Unknown point count. break; - }; - - TextureState tex_state(primitive->texture, texture_filter, texture_repeat, false, use_linear_colors); - if (tex_state != r_current_batch->tex_info.state) { - r_current_batch = _new_batch(r_batch_broken); - r_current_batch->tex_info.state = tex_state; - _prepare_batch_texture_info(r_current_batch, primitive->texture); } } - InstanceData *instance_data = new_instance_data(); + TextureState tex_state(primitive->texture, texture_filter, texture_repeat, false, use_linear_colors); + TextureInfo *tex_info = texture_info_map.getptr(tex_state); + if (!tex_info) { + tex_info = &texture_info_map.insert(tex_state, TextureInfo())->value; + _prepare_batch_texture_info(primitive->texture, tex_state, tex_info); + } + + if (r_current_batch->tex_info != tex_info) { + r_current_batch = _new_batch(r_batch_broken); + r_current_batch->tex_info = tex_info; + } + + InstanceData *instance_data = new_instance_data(world, lights, base_flags, r_index, tex_info); for (uint32_t j = 0; j < MIN(3u, primitive->point_count); j++) { instance_data->points[j * 2 + 0] = primitive->points[j].x; @@ -2587,7 +2614,7 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar _add_to_batch(r_index, r_batch_broken, r_current_batch); if (primitive->point_count == 4) { - instance_data = new_instance_data(); + instance_data = new_instance_data(world, lights, base_flags, r_index, tex_info); for (uint32_t j = 0; j < 3; j++) { int offset = j == 0 ? 0 : 1; @@ -2596,7 +2623,7 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar instance_data->points[j * 2 + 1] = primitive->points[j + offset].y; instance_data->uvs[j * 2 + 0] = primitive->uvs[j + offset].x; instance_data->uvs[j * 2 + 1] = primitive->uvs[j + offset].y; - Color col = primitive->colors[j] * base_color; + Color col = primitive->colors[j + offset] * base_color; if (use_linear_colors) { col = col.srgb_to_linear(); } @@ -2623,9 +2650,13 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar if (c->type == Item::Command::TYPE_MESH) { const Item::CommandMesh *m = static_cast<const Item::CommandMesh *>(c); TextureState tex_state(m->texture, texture_filter, texture_repeat, false, use_linear_colors); - r_current_batch->tex_info.state = tex_state; - _prepare_batch_texture_info(r_current_batch, m->texture); - instance_data = new_instance_data(); + TextureInfo *tex_info = texture_info_map.getptr(tex_state); + if (!tex_info) { + tex_info = &texture_info_map.insert(tex_state, TextureInfo())->value; + _prepare_batch_texture_info(m->texture, tex_state, tex_info); + } + r_current_batch->tex_info = tex_info; + instance_data = new_instance_data(world, lights, base_flags, r_index, tex_info); r_current_batch->mesh_instance_count = 1; _update_transform_2d_to_mat2x3(base_transform * draw_transform * m->transform, instance_data->world); @@ -2646,9 +2677,13 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar } TextureState tex_state(mm->texture, texture_filter, texture_repeat, false, use_linear_colors); - r_current_batch->tex_info.state = tex_state; - _prepare_batch_texture_info(r_current_batch, mm->texture); - instance_data = new_instance_data(); + TextureInfo *tex_info = texture_info_map.getptr(tex_state); + if (!tex_info) { + tex_info = &texture_info_map.insert(tex_state, TextureInfo())->value; + _prepare_batch_texture_info(mm->texture, tex_state, tex_info); + } + r_current_batch->tex_info = tex_info; + instance_data = new_instance_data(world, lights, base_flags, r_index, tex_info); instance_data->flags |= 1; // multimesh, trails disabled @@ -2664,10 +2699,13 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar const Item::CommandParticles *pt = static_cast<const Item::CommandParticles *>(c); TextureState tex_state(pt->texture, texture_filter, texture_repeat, false, use_linear_colors); - r_current_batch->tex_info.state = tex_state; - _prepare_batch_texture_info(r_current_batch, pt->texture); - - instance_data = new_instance_data(); + TextureInfo *tex_info = texture_info_map.getptr(tex_state); + if (!tex_info) { + tex_info = &texture_info_map.insert(tex_state, TextureInfo())->value; + _prepare_batch_texture_info(pt->texture, tex_state, tex_info); + } + r_current_batch->tex_info = tex_info; + instance_data = new_instance_data(world, lights, base_flags, r_index, tex_info); uint32_t divisor = 1; r_current_batch->mesh_instance_count = particles_storage->particles_get_amount(pt->particles, divisor); @@ -2749,36 +2787,137 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar r_batch_broken = false; } +#ifdef DEBUG_ENABLED + if (debug_redraw && p_item->debug_redraw_time > 0.0) { + Color dc = debug_redraw_color; + dc.a *= p_item->debug_redraw_time / debug_redraw_time; + + // 1: If commands are different, start a new batch. + if (r_current_batch->command_type != Item::Command::TYPE_RECT) { + r_current_batch = _new_batch(r_batch_broken); + r_current_batch->command_type = Item::Command::TYPE_RECT; + // it is ok to be null for a TYPE_RECT + r_current_batch->command = nullptr; + // default variant + r_current_batch->shader_variant = SHADER_VARIANT_QUAD; + r_current_batch->render_primitive = RD::RENDER_PRIMITIVE_TRIANGLES; + } + + // 2: If the current batch has lighting, start a new batch. + if (r_current_batch->use_lighting) { + r_current_batch = _new_batch(r_batch_broken); + r_current_batch->use_lighting = false; + } + + // 3: If the current batch has blend, start a new batch. + if (r_current_batch->has_blend) { + r_current_batch = _new_batch(r_batch_broken); + r_current_batch->has_blend = false; + } + + TextureState tex_state(default_canvas_texture, texture_filter, texture_repeat, false, use_linear_colors); + TextureInfo *tex_info = texture_info_map.getptr(tex_state); + if (!tex_info) { + tex_info = &texture_info_map.insert(tex_state, TextureInfo())->value; + _prepare_batch_texture_info(default_canvas_texture, tex_state, tex_info); + } + + if (r_current_batch->tex_info != tex_info) { + r_current_batch = _new_batch(r_batch_broken); + r_current_batch->tex_info = tex_info; + } + + InstanceData *instance_data = new_instance_data(world, lights, base_flags, r_index, tex_info); + + Rect2 src_rect; + Rect2 dst_rect; + + dst_rect = Rect2(Vector2(), p_item->rect.size); + if (dst_rect.size.width < 0) { + dst_rect.position.x += dst_rect.size.width; + dst_rect.size.width *= -1; + } + if (dst_rect.size.height < 0) { + dst_rect.position.y += dst_rect.size.height; + dst_rect.size.height *= -1; + } + + src_rect = Rect2(0, 0, 1, 1); + + instance_data->modulation[0] = dc.r; + instance_data->modulation[1] = dc.g; + instance_data->modulation[2] = dc.b; + instance_data->modulation[3] = dc.a; + + instance_data->src_rect[0] = src_rect.position.x; + instance_data->src_rect[1] = src_rect.position.y; + instance_data->src_rect[2] = src_rect.size.width; + instance_data->src_rect[3] = src_rect.size.height; + + instance_data->dst_rect[0] = dst_rect.position.x; + instance_data->dst_rect[1] = dst_rect.position.y; + instance_data->dst_rect[2] = dst_rect.size.width; + instance_data->dst_rect[3] = dst_rect.size.height; + + _add_to_batch(r_index, r_batch_broken, r_current_batch); + + p_item->debug_redraw_time -= RSG::rasterizer->get_frame_delta_time(); + + RenderingServerDefault::redraw_request(); + + r_batch_broken = false; + } +#endif + if (r_current_clip && reclip) { // will make it re-enable clipping if needed afterwards r_current_clip = nullptr; } } -void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, CanvasShaderData *p_shader_data, RenderingDevice::FramebufferFormatID p_framebuffer_format, Light *p_lights, Batch const *p_batch, RenderingMethod::RenderInfo *r_render_info) { - UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); - ERR_FAIL_NULL(uniform_set_cache); +void RendererCanvasRenderRD::_before_evict(RendererCanvasRenderRD::RIDSetKey &p_key, RID &p_rid) { + RD::get_singleton()->uniform_set_set_invalidation_callback(p_rid, nullptr, nullptr); + RD::get_singleton()->free(p_rid); +} - ERR_FAIL_NULL(p_batch->command); +void RendererCanvasRenderRD::_uniform_set_invalidation_callback(void *p_userdata) { + const RIDSetKey *key = static_cast<RIDSetKey *>(p_userdata); + static_cast<RendererCanvasRenderRD *>(singleton)->rid_set_to_uniform_set.erase(*key); +} +void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, CanvasShaderData *p_shader_data, RenderingDevice::FramebufferFormatID p_framebuffer_format, Light *p_lights, Batch const *p_batch, RenderingMethod::RenderInfo *r_render_info) { { - RD::Uniform u_diffuse(RD::UNIFORM_TYPE_TEXTURE, 0, p_batch->tex_info.diffuse); - RD::Uniform u_normal(RD::UNIFORM_TYPE_TEXTURE, 1, p_batch->tex_info.normal); - RD::Uniform u_specular(RD::UNIFORM_TYPE_TEXTURE, 2, p_batch->tex_info.specular); - RD::Uniform u_sampler(RD::UNIFORM_TYPE_SAMPLER, 3, p_batch->tex_info.sampler); - RD::Uniform u_instance_data(RD::UNIFORM_TYPE_STORAGE_BUFFER, 4, state.canvas_instance_data_buffers[state.current_data_buffer_index].instance_buffers[p_batch->instance_buffer_index]); - - RID uniform_set = uniform_set_cache->get_cache(shader.default_version_rd_shader, BATCH_UNIFORM_SET, u_diffuse, u_normal, u_specular, u_sampler, u_instance_data); + RIDSetKey key( + p_batch->tex_info->state, + state.canvas_instance_data_buffers[state.current_data_buffer_index].instance_buffers[p_batch->instance_buffer_index]); + + const RID *uniform_set = rid_set_to_uniform_set.getptr(key); + if (uniform_set == nullptr) { + state.batch_texture_uniforms.write[0] = RD::Uniform(RD::UNIFORM_TYPE_TEXTURE, 0, p_batch->tex_info->diffuse); + state.batch_texture_uniforms.write[1] = RD::Uniform(RD::UNIFORM_TYPE_TEXTURE, 1, p_batch->tex_info->normal); + state.batch_texture_uniforms.write[2] = RD::Uniform(RD::UNIFORM_TYPE_TEXTURE, 2, p_batch->tex_info->specular); + state.batch_texture_uniforms.write[3] = RD::Uniform(RD::UNIFORM_TYPE_SAMPLER, 3, p_batch->tex_info->sampler); + state.batch_texture_uniforms.write[4] = RD::Uniform(RD::UNIFORM_TYPE_STORAGE_BUFFER, 4, state.canvas_instance_data_buffers[state.current_data_buffer_index].instance_buffers[p_batch->instance_buffer_index]); + + RID rid = RD::get_singleton()->uniform_set_create(state.batch_texture_uniforms, shader.default_version_rd_shader, BATCH_UNIFORM_SET); + ERR_FAIL_COND_MSG(rid.is_null(), "Failed to create uniform set for batch."); + + const RIDCache::Pair *iter = rid_set_to_uniform_set.insert(key, rid); + uniform_set = &iter->data; + RD::get_singleton()->uniform_set_set_invalidation_callback(rid, RendererCanvasRenderRD::_uniform_set_invalidation_callback, (void *)&iter->key); + } - if (state.current_batch_uniform_set != uniform_set) { - state.current_batch_uniform_set = uniform_set; - RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, uniform_set, BATCH_UNIFORM_SET); + if (state.current_batch_uniform_set != *uniform_set) { + state.current_batch_uniform_set = *uniform_set; + RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, *uniform_set, BATCH_UNIFORM_SET); } } + PushConstant push_constant; + push_constant.base_instance_index = p_batch->start; + push_constant.specular_shininess = p_batch->tex_info->specular_shininess; RID pipeline; PipelineKey pipeline_key; - PushConstant push_constant; pipeline_key.framebuffer_format_id = p_framebuffer_format; pipeline_key.variant = p_batch->shader_variant; pipeline_key.render_primitive = p_batch->render_primitive; @@ -2794,7 +2933,6 @@ void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, CanvasSha RD::get_singleton()->draw_list_set_blend_constants(p_draw_list, p_batch->modulate); } - push_constant.base_instance_index = p_batch->start; RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(PushConstant)); RD::get_singleton()->draw_list_bind_index_array(p_draw_list, shader.quad_index_array); RD::get_singleton()->draw_list_draw(p_draw_list, true, p_batch->instance_count); @@ -2807,6 +2945,8 @@ void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, CanvasSha } break; case Item::Command::TYPE_POLYGON: { + ERR_FAIL_NULL(p_batch->command); + const Item::CommandPolygon *polygon = static_cast<const Item::CommandPolygon *>(p_batch->command); PolygonBuffers *pb = polygon_buffers.polygons.getptr(polygon->polygon.polygon_id); @@ -2816,7 +2956,6 @@ void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, CanvasSha pipeline = _get_pipeline_specialization_or_ubershader(p_shader_data, pipeline_key, push_constant); RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline); - push_constant.base_instance_index = p_batch->start; RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(PushConstant)); RD::get_singleton()->draw_list_bind_vertex_array(p_draw_list, pb->vertex_array); if (pb->indices.is_valid()) { @@ -2832,12 +2971,13 @@ void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, CanvasSha } break; case Item::Command::TYPE_PRIMITIVE: { + ERR_FAIL_NULL(p_batch->command); + const Item::CommandPrimitive *primitive = static_cast<const Item::CommandPrimitive *>(p_batch->command); pipeline = _get_pipeline_specialization_or_ubershader(p_shader_data, pipeline_key, push_constant); RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline); - push_constant.base_instance_index = p_batch->start; RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(PushConstant)); RD::get_singleton()->draw_list_bind_index_array(p_draw_list, primitive_arrays.index_array[MIN(3u, primitive->point_count) - 1]); uint32_t instance_count = p_batch->instance_count; @@ -2854,6 +2994,8 @@ void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, CanvasSha case Item::Command::TYPE_MESH: case Item::Command::TYPE_MULTIMESH: case Item::Command::TYPE_PARTICLES: { + ERR_FAIL_NULL(p_batch->command); + RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton(); RendererRD::ParticlesStorage *particles_storage = RendererRD::ParticlesStorage::get_singleton(); @@ -2914,7 +3056,6 @@ void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, CanvasSha pipeline = _get_pipeline_specialization_or_ubershader(p_shader_data, pipeline_key, push_constant, mesh_instance, surface, j, &vertex_array); RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline); - push_constant.base_instance_index = p_batch->start; RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(PushConstant)); RID index_array = mesh_storage->mesh_surface_get_index_array(surface, 0); @@ -2996,7 +3137,7 @@ void RendererCanvasRenderRD::_allocate_instance_buffer() { state.canvas_instance_data_buffers[state.current_data_buffer_index].instance_buffers.push_back(buf); } -void RendererCanvasRenderRD::_prepare_batch_texture_info(Batch *p_current_batch, RID p_texture) const { +void RendererCanvasRenderRD::_prepare_batch_texture_info(RID p_texture, TextureState &p_state, TextureInfo *p_info) { if (p_texture.is_null()) { p_texture = default_canvas_texture; } @@ -3004,38 +3145,38 @@ void RendererCanvasRenderRD::_prepare_batch_texture_info(Batch *p_current_batch, RendererRD::TextureStorage::CanvasTextureInfo info = RendererRD::TextureStorage::get_singleton()->canvas_texture_get_info( p_texture, - p_current_batch->tex_info.state.texture_filter(), - p_current_batch->tex_info.state.texture_repeat(), - p_current_batch->tex_info.state.linear_colors(), - p_current_batch->tex_info.state.texture_is_data()); - + p_state.texture_filter(), + p_state.texture_repeat(), + p_state.linear_colors(), + p_state.texture_is_data()); // something odd happened if (info.is_null()) { - _prepare_batch_texture_info(p_current_batch, default_canvas_texture); + _prepare_batch_texture_info(default_canvas_texture, p_state, p_info); return; } - p_current_batch->tex_info.diffuse = info.diffuse; - p_current_batch->tex_info.normal = info.normal; - p_current_batch->tex_info.specular = info.specular; - p_current_batch->tex_info.sampler = info.sampler; + p_info->state = p_state; + p_info->diffuse = info.diffuse; + p_info->normal = info.normal; + p_info->specular = info.specular; + p_info->sampler = info.sampler; // cache values to be copied to instance data if (info.specular_color.a < 0.999) { - p_current_batch->tex_info.flags |= FLAGS_DEFAULT_SPECULAR_MAP_USED; + p_info->flags |= FLAGS_DEFAULT_SPECULAR_MAP_USED; } if (info.use_normal) { - p_current_batch->tex_info.flags |= FLAGS_DEFAULT_NORMAL_MAP_USED; + p_info->flags |= FLAGS_DEFAULT_NORMAL_MAP_USED; } uint8_t a = uint8_t(CLAMP(info.specular_color.a * 255.0, 0.0, 255.0)); uint8_t b = uint8_t(CLAMP(info.specular_color.b * 255.0, 0.0, 255.0)); uint8_t g = uint8_t(CLAMP(info.specular_color.g * 255.0, 0.0, 255.0)); uint8_t r = uint8_t(CLAMP(info.specular_color.r * 255.0, 0.0, 255.0)); - p_current_batch->tex_info.specular_shininess = uint32_t(a) << 24 | uint32_t(b) << 16 | uint32_t(g) << 8 | uint32_t(r); + p_info->specular_shininess = uint32_t(a) << 24 | uint32_t(b) << 16 | uint32_t(g) << 8 | uint32_t(r); - p_current_batch->tex_info.texpixel_size = Vector2(1.0 / float(info.size.width), 1.0 / float(info.size.height)); + p_info->texpixel_size = Vector2(1.0 / float(info.size.width), 1.0 / float(info.size.height)); } RendererCanvasRenderRD::~RendererCanvasRenderRD() { @@ -3077,7 +3218,7 @@ RendererCanvasRenderRD::~RendererCanvasRenderRD() { RD::get_singleton()->free(state.shadow_texture); memdelete_arr(state.instance_data_array); - for (uint32_t i = 0; i < state.canvas_instance_data_buffers.size(); i++) { + for (uint32_t i = 0; i < BATCH_DATA_BUFFER_COUNT; i++) { for (uint32_t j = 0; j < state.canvas_instance_data_buffers[i].instance_buffers.size(); j++) { RD::get_singleton()->free(state.canvas_instance_data_buffers[i].instance_buffers[j]); } diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h index 8ef1221108..a2c39d7181 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h @@ -33,6 +33,7 @@ #ifndef RENDERER_CANVAS_RENDER_RD_H #define RENDERER_CANVAS_RENDER_RD_H +#include "core/templates/lru.h" #include "servers/rendering/renderer_canvas_render.h" #include "servers/rendering/renderer_compositor.h" #include "servers/rendering/renderer_rd/pipeline_cache_rd.h" @@ -52,6 +53,8 @@ class RendererCanvasRenderRD : public RendererCanvasRender { }; const int SAMPLERS_BINDING_FIRST_INDEX = 10; + // The size of the ring buffer to store GPU buffers. Triple-buffering the max expected frames in flight. + static const uint32_t BATCH_DATA_BUFFER_COUNT = 3; enum ShaderVariant { SHADER_VARIANT_QUAD, @@ -341,7 +344,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender { struct InstanceData { float world[6]; uint32_t flags; - uint32_t specular_shininess; + uint32_t pad1; union { //rect struct { @@ -368,8 +371,8 @@ class RendererCanvasRenderRD : public RendererCanvasRender { struct PushConstant { uint32_t base_instance_index; ShaderSpecialization shader_specialization; - uint32_t pad2; - uint32_t pad3; + uint32_t specular_shininess; + uint32_t pad; }; // TextureState is used to determine when a new batch is required due to a change of texture state. @@ -400,50 +403,91 @@ class RendererCanvasRenderRD : public RendererCanvasRender { (((uint32_t)p_use_linear_colors & LINEAR_COLORS_MASK) << LINEAR_COLORS_SHIFT); } - _FORCE_INLINE_ RS::CanvasItemTextureFilter texture_filter() const { + _ALWAYS_INLINE_ RS::CanvasItemTextureFilter texture_filter() const { return (RS::CanvasItemTextureFilter)((other >> FILTER_SHIFT) & FILTER_MASK); } - _FORCE_INLINE_ RS::CanvasItemTextureRepeat texture_repeat() const { + _ALWAYS_INLINE_ RS::CanvasItemTextureRepeat texture_repeat() const { return (RS::CanvasItemTextureRepeat)((other >> REPEAT_SHIFT) & REPEAT_MASK); } - _FORCE_INLINE_ bool linear_colors() const { + _ALWAYS_INLINE_ bool linear_colors() const { return (other >> LINEAR_COLORS_SHIFT) & LINEAR_COLORS_MASK; } - _FORCE_INLINE_ bool texture_is_data() const { + _ALWAYS_INLINE_ bool texture_is_data() const { return (other >> TEXTURE_IS_DATA_SHIFT) & TEXTURE_IS_DATA_MASK; } - bool operator==(const TextureState &p_val) const { + _ALWAYS_INLINE_ bool operator==(const TextureState &p_val) const { return (texture == p_val.texture) && (other == p_val.other); } - bool operator!=(const TextureState &p_val) const { + _ALWAYS_INLINE_ bool operator!=(const TextureState &p_val) const { return (texture != p_val.texture) || (other != p_val.other); } + + _ALWAYS_INLINE_ bool is_valid() const { return texture.is_valid(); } + _ALWAYS_INLINE_ bool is_null() const { return texture.is_null(); } + + uint32_t hash() const { + uint32_t hash = hash_murmur3_one_64(texture.get_id()); + return hash_murmur3_one_32(other, hash); + } }; struct TextureInfo { TextureState state; - uint32_t specular_shininess = 0; - uint32_t flags = 0; - Vector2 texpixel_size; - RID diffuse; RID normal; RID specular; RID sampler; + Vector2 texpixel_size; + uint32_t specular_shininess = 0; + uint32_t flags = 0; + }; + + /// A key used to uniquely identify a distinct BATCH_UNIFORM_SET + struct RIDSetKey { + TextureState state; + RID instance_data; + + RIDSetKey() { + } + + RIDSetKey(TextureState p_state, RID p_instance_data) : + state(p_state), + instance_data(p_instance_data) { + } + + _ALWAYS_INLINE_ bool operator==(const RIDSetKey &p_val) const { + return state == p_val.state && instance_data == p_val.instance_data; + } + + _ALWAYS_INLINE_ bool operator!=(const RIDSetKey &p_val) const { + return !(*this == p_val); + } + + _ALWAYS_INLINE_ uint32_t hash() const { + uint32_t h = state.hash(); + h = hash_murmur3_one_64(instance_data.get_id(), h); + return hash_fmix32(h); + } }; + static void _before_evict(RendererCanvasRenderRD::RIDSetKey &p_key, RID &p_rid); + static void _uniform_set_invalidation_callback(void *p_userdata); + + typedef LRUCache<RIDSetKey, RID, HashableHasher<RIDSetKey>, HashMapComparatorDefault<RIDSetKey>, _before_evict> RIDCache; + RIDCache rid_set_to_uniform_set; + struct Batch { // Position in the UBO measured in bytes uint32_t start = 0; uint32_t instance_count = 0; uint32_t instance_buffer_index = 0; - TextureInfo tex_info; + TextureInfo *tex_info; Color modulate = Color(1.0, 1.0, 1.0, 1.0); @@ -468,6 +512,9 @@ class RendererCanvasRenderRD : public RendererCanvasRender { bool has_blend = false; }; + HashMap<TextureState, TextureInfo, HashableHasher<TextureState>> texture_info_map; + + // per-frame buffers struct DataBuffer { LocalVector<RID> instance_buffers; }; @@ -494,7 +541,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender { uint32_t pad2; }; - LocalVector<DataBuffer> canvas_instance_data_buffers; + DataBuffer canvas_instance_data_buffers[BATCH_DATA_BUFFER_COUNT]; LocalVector<Batch> canvas_instance_batches; uint32_t current_data_buffer_index = 0; uint32_t current_instance_buffer_index = 0; @@ -505,6 +552,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender { uint32_t max_instances_per_buffer = 16384; uint32_t max_instance_buffer_size = 16384 * sizeof(InstanceData); + Vector<RD::Uniform> batch_texture_uniforms; RID current_batch_uniform_set; LightUniform *light_uniforms = nullptr; @@ -520,7 +568,6 @@ class RendererCanvasRenderRD : public RendererCanvasRender { RID default_transforms_uniform_set; uint32_t max_lights_per_render; - uint32_t max_lights_per_item; double time; @@ -560,7 +607,8 @@ class RendererCanvasRenderRD : public RendererCanvasRender { void _render_batch_items(RenderTarget 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, RenderingMethod::RenderInfo *r_render_info = nullptr); void _record_item_commands(const Item *p_item, RenderTarget p_render_target, const Transform2D &p_base_transform, Item *&r_current_clip, Light *p_lights, uint32_t &r_index, bool &r_batch_broken, bool &r_sdf_used, Batch *&r_current_batch); void _render_batch(RD::DrawListID p_draw_list, CanvasShaderData *p_shader_data, RenderingDevice::FramebufferFormatID p_framebuffer_format, Light *p_lights, Batch const *p_batch, RenderingMethod::RenderInfo *r_render_info = nullptr); - void _prepare_batch_texture_info(Batch *p_current_batch, RID p_texture) const; + void _prepare_batch_texture_info(RID p_texture, TextureState &p_state, TextureInfo *p_info); + InstanceData *new_instance_data(float *p_world, uint32_t *p_lights, uint32_t p_base_flags, uint32_t p_index, TextureInfo *p_info); [[nodiscard]] Batch *_new_batch(bool &r_batch_broken); void _add_to_batch(uint32_t &r_index, bool &r_batch_broken, Batch *&r_current_batch); void _allocate_instance_buffer(); diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp index 9df54e372e..7514e1d5af 100644 --- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp @@ -68,6 +68,16 @@ void RendererCompositorRD::blit_render_targets_to_screen(DisplayServer::WindowID RD::get_singleton()->draw_list_bind_index_array(draw_list, blit.array); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, render_target_descriptors[rd_texture], 0); + // We need to invert the phone rotation. + int screen_rotation_degrees = -DisplayServer::get_singleton()->screen_get_internal_current_rotation(); + float screen_rotation = Math::deg_to_rad((float)screen_rotation_degrees); + + blit.push_constant.rotation_cos = Math::cos(screen_rotation); + blit.push_constant.rotation_sin = Math::sin(screen_rotation); + // Swap width and height when the orientation is not the native one. + if (screen_rotation_degrees % 180 != 0) { + SWAP(screen_size.width, screen_size.height); + } blit.push_constant.src_rect[0] = p_render_targets[i].src_rect.position.x; blit.push_constant.src_rect[1] = p_render_targets[i].src_rect.position.y; blit.push_constant.src_rect[2] = p_render_targets[i].src_rect.size.width; @@ -230,6 +240,10 @@ void RendererCompositorRD::set_boot_image(const Ref<Image> &p_image, const Color RD::get_singleton()->draw_list_bind_index_array(draw_list, blit.array); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uset, 0); + int screen_rotation_degrees = DisplayServer::get_singleton()->screen_get_internal_current_rotation(); + float screen_rotation = Math::deg_to_rad((float)screen_rotation_degrees); + blit.push_constant.rotation_cos = Math::cos(screen_rotation); + blit.push_constant.rotation_sin = Math::sin(screen_rotation); blit.push_constant.src_rect[0] = 0.0; blit.push_constant.src_rect[1] = 0.0; blit.push_constant.src_rect[2] = 1.0; diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.h b/servers/rendering/renderer_rd/renderer_compositor_rd.h index 9a4ad87bf0..728879134f 100644 --- a/servers/rendering/renderer_rd/renderer_compositor_rd.h +++ b/servers/rendering/renderer_rd/renderer_compositor_rd.h @@ -76,6 +76,10 @@ protected: float src_rect[4]; float dst_rect[4]; + float rotation_sin; + float rotation_cos; + float pad[2]; + float eye_center[2]; float k1; float k2; @@ -105,7 +109,7 @@ protected: static RendererCompositorRD *singleton; public: - RendererUtilities *get_utilities() { return utilities; }; + RendererUtilities *get_utilities() { return utilities; } RendererLightStorage *get_light_storage() { return light_storage; } RendererMaterialStorage *get_material_storage() { return material_storage; } RendererMeshStorage *get_mesh_storage() { return mesh_storage; } diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h index 7c1b014af1..25a55debdd 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h @@ -80,7 +80,7 @@ protected: //////////////////////////////// - virtual RendererRD::ForwardIDStorage *create_forward_id_storage() { return memnew(RendererRD::ForwardIDStorage); }; + virtual RendererRD::ForwardIDStorage *create_forward_id_storage() { return memnew(RendererRD::ForwardIDStorage); } void _update_vrs(Ref<RenderSceneBuffersRD> p_render_buffers); diff --git a/servers/rendering/renderer_rd/shaders/blit.glsl b/servers/rendering/renderer_rd/shaders/blit.glsl index d451647bec..fe6416f03c 100644 --- a/servers/rendering/renderer_rd/shaders/blit.glsl +++ b/servers/rendering/renderer_rd/shaders/blit.glsl @@ -8,6 +8,10 @@ layout(push_constant, std140) uniform Pos { vec4 src_rect; vec4 dst_rect; + float rotation_sin; + float rotation_cos; + vec2 pad; + vec2 eye_center; float k1; float k2; @@ -15,17 +19,23 @@ layout(push_constant, std140) uniform Pos { float upscale; float aspect_ratio; uint layer; - uint pad1; + bool convert_to_srgb; } data; layout(location = 0) out vec2 uv; void main() { + mat4 swapchain_transform = mat4(1.0); + swapchain_transform[0][0] = data.rotation_cos; + swapchain_transform[0][1] = -data.rotation_sin; + swapchain_transform[1][0] = data.rotation_sin; + swapchain_transform[1][1] = data.rotation_cos; + vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0)); uv = data.src_rect.xy + base_arr[gl_VertexIndex] * data.src_rect.zw; vec2 vtx = data.dst_rect.xy + base_arr[gl_VertexIndex] * data.dst_rect.zw; - gl_Position = vec4(vtx * 2.0 - 1.0, 0.0, 1.0); + gl_Position = swapchain_transform * vec4(vtx * 2.0 - 1.0, 0.0, 1.0); } #[fragment] @@ -38,6 +48,10 @@ layout(push_constant, std140) uniform Pos { vec4 src_rect; vec4 dst_rect; + float rotation_sin; + float rotation_cos; + vec2 pad; + vec2 eye_center; float k1; float k2; diff --git a/servers/rendering/renderer_rd/shaders/canvas.glsl b/servers/rendering/renderer_rd/shaders/canvas.glsl index dafcce37ad..f665bc24a4 100644 --- a/servers/rendering/renderer_rd/shaders/canvas.glsl +++ b/servers/rendering/renderer_rd/shaders/canvas.glsl @@ -28,7 +28,7 @@ layout(location = 11) in vec4 weight_attrib; layout(location = 4) out flat uint instance_index_interp; -#endif // USE_ATTRIBUTES +#endif // !USE_ATTRIBUTES layout(location = 0) out vec2 uv_interp; layout(location = 1) out vec4 color_interp; @@ -322,11 +322,7 @@ vec4 light_compute( #ifdef USE_NINEPATCH float map_ninepatch_axis(float pixel, float draw_size, float tex_pixel_size, float margin_begin, float margin_end, int np_repeat, inout int draw_center) { -#ifdef USE_ATTRIBUTES - const InstanceData draw_data = instances.data[params.base_instance_index]; -#else const InstanceData draw_data = instances.data[instance_index]; -#endif // USE_ATTRIBUTES float tex_size = 1.0 / tex_pixel_size; @@ -567,7 +563,7 @@ void main() { if (specular_shininess_used || (using_light && normal_used && bool(draw_data.flags & FLAGS_DEFAULT_SPECULAR_MAP_USED))) { specular_shininess = texture(sampler2D(specular_texture, texture_sampler), uv); - specular_shininess *= unpackUnorm4x8(draw_data.specular_shininess); + specular_shininess *= unpackUnorm4x8(params.specular_shininess); specular_shininess_used = true; } else { specular_shininess = vec4(1.0); diff --git a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl index ead8c459a4..84017a1fe1 100644 --- a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl @@ -37,7 +37,7 @@ struct InstanceData { vec2 world_y; vec2 world_ofs; uint flags; - uint specular_shininess; + uint pad2; #ifdef USE_PRIMITIVE vec2 points[3]; vec2 uvs[3]; @@ -57,8 +57,8 @@ struct InstanceData { layout(push_constant, std430) uniform Params { uint base_instance_index; // base index to instance data uint sc_packed_0; - uint pad2; - uint pad3; + uint specular_shininess; + uint pad; } params; @@ -68,7 +68,7 @@ params; // Pull the constants from the draw call's push constants. uint sc_packed_0() { - return draw_call.sc_packed_0; + return params.sc_packed_0; } #else diff --git a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl index 9f68d59be2..7bfcb2fb12 100644 --- a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl @@ -107,19 +107,19 @@ bool sc_use_lightmap_bicubic_filter() { } uint sc_soft_shadow_samples() { - return (sc_packed_0() >> 8) & 15U; + return (sc_packed_0() >> 8) & 63U; } uint sc_penumbra_shadow_samples() { - return (sc_packed_0() >> 12) & 15U; + return (sc_packed_0() >> 14) & 63U; } uint sc_directional_soft_shadow_samples() { - return (sc_packed_0() >> 16) & 15U; + return (sc_packed_0() >> 20) & 63U; } uint sc_directional_penumbra_shadow_samples() { - return (sc_packed_0() >> 20) & 15U; + return (sc_packed_0() >> 26) & 63U; } float sc_luminance_multiplier() { diff --git a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl index 495e52a29e..df528973da 100644 --- a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl @@ -22,8 +22,8 @@ layout(push_constant, std430) uniform DrawCall { uint pad; #ifdef UBERSHADER uint sc_packed_0; - float sc_packed_1; - uint sc_packed_2; + uint sc_packed_1; + float sc_packed_2; uint uc_packed_0; #endif } @@ -42,10 +42,14 @@ uint sc_packed_0() { return draw_call.sc_packed_0; } -float sc_packed_1() { +uint sc_packed_1() { return draw_call.sc_packed_1; } +float sc_packed_2() { + return draw_call.sc_packed_2; +} + uint uc_cull_mode() { return (draw_call.uc_packed_0 >> 0) & 3U; } @@ -54,16 +58,21 @@ uint uc_cull_mode() { // Pull the constants from the pipeline's specialization constants. layout(constant_id = 0) const uint pso_sc_packed_0 = 0; -layout(constant_id = 1) const float pso_sc_packed_1 = 2.0; +layout(constant_id = 1) const uint pso_sc_packed_1 = 0; +layout(constant_id = 2) const float pso_sc_packed_2 = 2.0; uint sc_packed_0() { return pso_sc_packed_0; } -float sc_packed_1() { +uint sc_packed_1() { return pso_sc_packed_1; } +float sc_packed_2() { + return pso_sc_packed_2; +} + #endif bool sc_use_light_projector() { @@ -123,23 +132,23 @@ bool sc_use_lightmap_bicubic_filter() { } uint sc_soft_shadow_samples() { - return (sc_packed_0() >> 16) & 15U; + return (sc_packed_0() >> 14) & 63U; } uint sc_penumbra_shadow_samples() { - return (sc_packed_0() >> 20) & 15U; + return (sc_packed_0() >> 20) & 63U; } uint sc_directional_soft_shadow_samples() { - return (sc_packed_0() >> 24) & 15U; + return (sc_packed_0() >> 26) & 63U; } uint sc_directional_penumbra_shadow_samples() { - return (sc_packed_0() >> 28) & 15U; + return (sc_packed_1() >> 0) & 63U; } float sc_luminance_multiplier() { - return sc_packed_1(); + return sc_packed_2(); } /* Set 0: Base Pass (never changes) */ diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp index d219047cba..410a6ae5c6 100644 --- a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp @@ -1051,7 +1051,7 @@ void LightStorage::reflection_probe_free(RID p_rid) { ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_rid); reflection_probe->dependency.deleted_notify(p_rid); reflection_probe_owner.free(p_rid); -}; +} void LightStorage::reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) { ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe); diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.h b/servers/rendering/renderer_rd/storage_rd/light_storage.h index 210e4c3035..7cd7d3e363 100644 --- a/servers/rendering/renderer_rd/storage_rd/light_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/light_storage.h @@ -592,7 +592,7 @@ public: /* LIGHT INSTANCE API */ - bool owns_light_instance(RID p_rid) { return light_instance_owner.owns(p_rid); }; + bool owns_light_instance(RID p_rid) { return light_instance_owner.owns(p_rid); } virtual RID light_instance_create(RID p_light) override; virtual void light_instance_free(RID p_light) override; @@ -813,7 +813,7 @@ public: /* REFLECTION PROBE */ - bool owns_reflection_probe(RID p_rid) { return reflection_probe_owner.owns(p_rid); }; + bool owns_reflection_probe(RID p_rid) { return reflection_probe_owner.owns(p_rid); } virtual RID reflection_probe_allocate() override; virtual void reflection_probe_initialize(RID p_reflection_probe) override; @@ -955,7 +955,7 @@ public: /* LIGHTMAP */ - bool owns_lightmap(RID p_rid) { return lightmap_owner.owns(p_rid); }; + bool owns_lightmap(RID p_rid) { return lightmap_owner.owns(p_rid); } virtual RID lightmap_allocate() override; virtual void lightmap_initialize(RID p_lightmap) override; @@ -1021,7 +1021,7 @@ public: /* LIGHTMAP INSTANCE */ - bool owns_lightmap_instance(RID p_rid) { return lightmap_instance_owner.owns(p_rid); }; + bool owns_lightmap_instance(RID p_rid) { return lightmap_instance_owner.owns(p_rid); } virtual RID lightmap_instance_create(RID p_lightmap) override; virtual void lightmap_instance_free(RID p_lightmap) override; @@ -1041,7 +1041,7 @@ public: /* SHADOW ATLAS API */ - bool owns_shadow_atlas(RID p_rid) { return shadow_atlas_owner.owns(p_rid); }; + bool owns_shadow_atlas(RID p_rid) { return shadow_atlas_owner.owns(p_rid); } virtual RID shadow_atlas_create() override; virtual void shadow_atlas_free(RID p_atlas) override; diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.h b/servers/rendering/renderer_rd/storage_rd/material_storage.h index 2f477c4196..e6a25c547a 100644 --- a/servers/rendering/renderer_rd/storage_rd/material_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/material_storage.h @@ -256,7 +256,7 @@ private: MaterialDataRequestFunction material_data_request_func[SHADER_TYPE_MAX]; mutable RID_Owner<Material, true> material_owner; - Material *get_material(RID p_rid) { return material_owner.get_or_null(p_rid); }; + Material *get_material(RID p_rid) { return material_owner.get_or_null(p_rid); } SelfList<Material>::List material_update_list; Mutex material_update_list_mutex; @@ -405,7 +405,7 @@ public: /* SHADER API */ - bool owns_shader(RID p_rid) { return shader_owner.owns(p_rid); }; + bool owns_shader(RID p_rid) { return shader_owner.owns(p_rid); } virtual RID shader_allocate() override; virtual void shader_initialize(RID p_shader) override; @@ -425,7 +425,7 @@ public: /* MATERIAL API */ - bool owns_material(RID p_rid) { return material_owner.owns(p_rid); }; + bool owns_material(RID p_rid) { return material_owner.owns(p_rid); } void _material_queue_update(Material *material, bool p_uniform, bool p_texture); void _update_queued_materials(); diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h index 79bd8d0be2..e70b7568e0 100644 --- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h @@ -353,7 +353,7 @@ public: /* MESH API */ - bool owns_mesh(RID p_rid) { return mesh_owner.owns(p_rid); }; + bool owns_mesh(RID p_rid) { return mesh_owner.owns(p_rid); } virtual RID mesh_allocate() override; virtual void mesh_initialize(RID p_mesh) override; @@ -618,7 +618,7 @@ public: /* MESH INSTANCE API */ - bool owns_mesh_instance(RID p_rid) const { return mesh_instance_owner.owns(p_rid); }; + bool owns_mesh_instance(RID p_rid) const { return mesh_instance_owner.owns(p_rid); } virtual RID mesh_instance_create(RID p_base) override; virtual void mesh_instance_free(RID p_rid) override; @@ -630,7 +630,7 @@ public: /* MULTIMESH API */ - bool owns_multimesh(RID p_rid) { return multimesh_owner.owns(p_rid); }; + bool owns_multimesh(RID p_rid) { return multimesh_owner.owns(p_rid); } virtual RID _multimesh_allocate() override; virtual void _multimesh_initialize(RID p_multimesh) override; @@ -739,7 +739,7 @@ public: /* SKELETON API */ - bool owns_skeleton(RID p_rid) const { return skeleton_owner.owns(p_rid); }; + bool owns_skeleton(RID p_rid) const { return skeleton_owner.owns(p_rid); } virtual RID skeleton_allocate() override; virtual void skeleton_initialize(RID p_skeleton) override; diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.h b/servers/rendering/renderer_rd/storage_rd/texture_storage.h index 4e257f0e04..2d59b822a0 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.h @@ -124,7 +124,6 @@ private: Size2i size_cache = Size2i(1, 1); bool use_normal_cache = false; bool use_specular_cache = false; - bool cleared_cache = true; void clear_cache(); ~CanvasTexture(); @@ -197,7 +196,7 @@ private: // Textures can be created from threads, so this RID_Owner is thread safe. mutable RID_Owner<Texture, true> texture_owner; - Texture *get_texture(RID p_rid) { return texture_owner.get_or_null(p_rid); }; + Texture *get_texture(RID p_rid) { return texture_owner.get_or_null(p_rid); } struct TextureToRDFormat { RD::DataFormat format; @@ -441,7 +440,7 @@ private: }; mutable RID_Owner<RenderTarget> render_target_owner; - RenderTarget *get_render_target(RID p_rid) const { return render_target_owner.get_or_null(p_rid); }; + RenderTarget *get_render_target(RID p_rid) const { return render_target_owner.get_or_null(p_rid); } void _clear_render_target(RenderTarget *rt); void _update_render_target(RenderTarget *rt); @@ -488,7 +487,7 @@ public: /* Canvas Texture API */ - bool owns_canvas_texture(RID p_rid) { return canvas_texture_owner.owns(p_rid); }; + bool owns_canvas_texture(RID p_rid) { return canvas_texture_owner.owns(p_rid); } virtual RID canvas_texture_allocate() override; virtual void canvas_texture_initialize(RID p_rid) override; @@ -504,7 +503,7 @@ public: /* Texture API */ - bool owns_texture(RID p_rid) const { return texture_owner.owns(p_rid); }; + bool owns_texture(RID p_rid) const { return texture_owner.owns(p_rid); } virtual RID texture_allocate() override; virtual void texture_free(RID p_rid) override; @@ -593,7 +592,7 @@ public: void update_decal_atlas(); - bool owns_decal(RID p_rid) const { return decal_owner.owns(p_rid); }; + bool owns_decal(RID p_rid) const { return decal_owner.owns(p_rid); } RID decal_atlas_get_texture() const; RID decal_atlas_get_texture_srgb() const; @@ -733,7 +732,7 @@ public: /* RENDER TARGET API */ - bool owns_render_target(RID p_rid) const { return render_target_owner.owns(p_rid); }; + bool owns_render_target(RID p_rid) const { return render_target_owner.owns(p_rid); } virtual RID render_target_create() override; virtual void render_target_free(RID p_rid) override; diff --git a/servers/rendering/renderer_rd/storage_rd/utilities.h b/servers/rendering/renderer_rd/storage_rd/utilities.h index 5fafe2752d..bdbe7af803 100644 --- a/servers/rendering/renderer_rd/storage_rd/utilities.h +++ b/servers/rendering/renderer_rd/storage_rd/utilities.h @@ -79,8 +79,8 @@ public: /* VISIBILITY NOTIFIER */ - VisibilityNotifier *get_visibility_notifier(RID p_rid) { return visibility_notifier_owner.get_or_null(p_rid); }; - bool owns_visibility_notifier(RID p_rid) const { return visibility_notifier_owner.owns(p_rid); }; + VisibilityNotifier *get_visibility_notifier(RID p_rid) { return visibility_notifier_owner.get_or_null(p_rid); } + bool owns_visibility_notifier(RID p_rid) const { return visibility_notifier_owner.owns(p_rid); } virtual RID visibility_notifier_allocate() override; virtual void visibility_notifier_initialize(RID p_notifier) override; diff --git a/servers/rendering/renderer_scene_occlusion_cull.h b/servers/rendering/renderer_scene_occlusion_cull.h index 51272d803c..94159f72bb 100644 --- a/servers/rendering/renderer_scene_occlusion_cull.h +++ b/servers/rendering/renderer_scene_occlusion_cull.h @@ -86,7 +86,7 @@ public: Vector3 view = p_cam_inv_transform.xform(corner); if (p_cam_projection.is_orthogonal()) { - min_depth = MIN(min_depth, view.z); + min_depth = MIN(min_depth, -view.z); } Plane vp = Plane(view, 1.0); @@ -236,11 +236,11 @@ public: RendererSceneOcclusionCull() { singleton = this; - }; + } virtual ~RendererSceneOcclusionCull() { singleton = nullptr; - }; + } }; #endif // RENDERER_SCENE_OCCLUSION_CULL_H diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp index 3c328ab34d..df94d320c3 100644 --- a/servers/rendering/rendering_device.cpp +++ b/servers/rendering/rendering_device.cpp @@ -1262,8 +1262,6 @@ Error RenderingDevice::_texture_initialize(RID p_texture, uint32_t p_layer, cons write_ptr = driver->buffer_map(transfer_worker->staging_buffer); ERR_FAIL_NULL_V(write_ptr, ERR_CANT_CREATE); - write_ptr += staging_worker_offset; - if (driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) { // Transition the texture to the optimal layout. RDD::TextureBarrier tb; @@ -1305,11 +1303,12 @@ Error RenderingDevice::_texture_initialize(RID p_texture, uint32_t p_layer, cons if (copy_pass) { const uint8_t *read_ptr_mipmap_layer = read_ptr_mipmap + (tight_mip_size / depth) * z; - _copy_region_block_or_regular(read_ptr_mipmap_layer, write_ptr, 0, 0, width, width, height, block_w, block_h, pitch, pixel_size, block_size); - write_ptr += to_allocate; + uint64_t staging_buffer_offset = staging_worker_offset + staging_local_offset; + uint8_t *write_ptr_mipmap_layer = write_ptr + staging_buffer_offset; + _copy_region_block_or_regular(read_ptr_mipmap_layer, write_ptr_mipmap_layer, 0, 0, width, width, height, block_w, block_h, pitch, pixel_size, block_size); RDD::BufferTextureCopyRegion copy_region; - copy_region.buffer_offset = staging_worker_offset + staging_local_offset; + copy_region.buffer_offset = staging_buffer_offset; copy_region.texture_subresources.aspect = texture->read_aspect_flags; copy_region.texture_subresources.mipmap = mm_i; copy_region.texture_subresources.base_layer = p_layer; @@ -4443,6 +4442,117 @@ void RenderingDevice::draw_list_draw(DrawListID p_list, bool p_use_indices, uint dl->state.draw_count++; } +void RenderingDevice::draw_list_draw_indirect(DrawListID p_list, bool p_use_indices, RID p_buffer, uint32_t p_offset, uint32_t p_draw_count, uint32_t p_stride) { + ERR_RENDER_THREAD_GUARD(); + + DrawList *dl = _get_draw_list_ptr(p_list); + ERR_FAIL_NULL(dl); + + Buffer *buffer = storage_buffer_owner.get_or_null(p_buffer); + ERR_FAIL_NULL(buffer); + + ERR_FAIL_COND_MSG(!buffer->usage.has_flag(RDD::BUFFER_USAGE_INDIRECT_BIT), "Buffer provided was not created to do indirect dispatch."); + +#ifdef DEBUG_ENABLED + ERR_FAIL_COND_MSG(!dl->validation.active, "Submitted Draw Lists can no longer be modified."); +#endif + +#ifdef DEBUG_ENABLED + ERR_FAIL_COND_MSG(!dl->validation.pipeline_active, + "No render pipeline was set before attempting to draw."); + if (dl->validation.pipeline_vertex_format != INVALID_ID) { + // Pipeline uses vertices, validate format. + ERR_FAIL_COND_MSG(dl->validation.vertex_format == INVALID_ID, + "No vertex array was bound, and render pipeline expects vertices."); + // Make sure format is right. + ERR_FAIL_COND_MSG(dl->validation.pipeline_vertex_format != dl->validation.vertex_format, + "The vertex format used to create the pipeline does not match the vertex format bound."); + } + + if (dl->validation.pipeline_push_constant_size > 0) { + // Using push constants, check that they were supplied. + ERR_FAIL_COND_MSG(!dl->validation.pipeline_push_constant_supplied, + "The shader in this pipeline requires a push constant to be set before drawing, but it's not present."); + } +#endif + +#ifdef DEBUG_ENABLED + for (uint32_t i = 0; i < dl->state.set_count; i++) { + if (dl->state.sets[i].pipeline_expected_format == 0) { + // Nothing expected by this pipeline. + continue; + } + + if (dl->state.sets[i].pipeline_expected_format != dl->state.sets[i].uniform_set_format) { + if (dl->state.sets[i].uniform_set_format == 0) { + ERR_FAIL_MSG(vformat("Uniforms were never supplied for set (%d) at the time of drawing, which are required by the pipeline.", i)); + } else if (uniform_set_owner.owns(dl->state.sets[i].uniform_set)) { + UniformSet *us = uniform_set_owner.get_or_null(dl->state.sets[i].uniform_set); + ERR_FAIL_MSG(vformat("Uniforms supplied for set (%d):\n%s\nare not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n%s", i, _shader_uniform_debug(us->shader_id, us->shader_set), _shader_uniform_debug(dl->state.pipeline_shader))); + } else { + ERR_FAIL_MSG(vformat("Uniforms supplied for set (%s, which was just freed) are not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n%s", i, _shader_uniform_debug(dl->state.pipeline_shader))); + } + } + } +#endif + + // Prepare descriptor sets if the API doesn't use pipeline barriers. + if (!driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) { + for (uint32_t i = 0; i < dl->state.set_count; i++) { + if (dl->state.sets[i].pipeline_expected_format == 0) { + // Nothing expected by this pipeline. + continue; + } + + draw_graph.add_draw_list_uniform_set_prepare_for_use(dl->state.pipeline_shader_driver_id, dl->state.sets[i].uniform_set_driver_id, i); + } + } + + // Bind descriptor sets. + for (uint32_t i = 0; i < dl->state.set_count; i++) { + if (dl->state.sets[i].pipeline_expected_format == 0) { + continue; // Nothing expected by this pipeline. + } + if (!dl->state.sets[i].bound) { + // All good, see if this requires re-binding. + draw_graph.add_draw_list_bind_uniform_set(dl->state.pipeline_shader_driver_id, dl->state.sets[i].uniform_set_driver_id, i); + + UniformSet *uniform_set = uniform_set_owner.get_or_null(dl->state.sets[i].uniform_set); + _uniform_set_update_shared(uniform_set); + + draw_graph.add_draw_list_usages(uniform_set->draw_trackers, uniform_set->draw_trackers_usage); + + dl->state.sets[i].bound = true; + } + } + + if (p_use_indices) { +#ifdef DEBUG_ENABLED + ERR_FAIL_COND_MSG(!dl->validation.index_array_count, + "Draw command requested indices, but no index buffer was set."); + + ERR_FAIL_COND_MSG(dl->validation.pipeline_uses_restart_indices != dl->validation.index_buffer_uses_restart_indices, + "The usage of restart indices in index buffer does not match the render primitive in the pipeline."); +#endif + + ERR_FAIL_COND_MSG(p_offset + 20 > buffer->size, "Offset provided (+20) is past the end of buffer."); + + draw_graph.add_draw_list_draw_indexed_indirect(buffer->driver_id, p_offset, p_draw_count, p_stride); + } else { + ERR_FAIL_COND_MSG(p_offset + 16 > buffer->size, "Offset provided (+16) is past the end of buffer."); + + draw_graph.add_draw_list_draw_indirect(buffer->driver_id, p_offset, p_draw_count, p_stride); + } + + dl->state.draw_count++; + + if (buffer->draw_tracker != nullptr) { + draw_graph.add_draw_list_usage(buffer->draw_tracker, RDG::RESOURCE_USAGE_INDIRECT_BUFFER_READ); + } + + _check_transfer_worker_buffer(buffer); +} + void RenderingDevice::draw_list_enable_scissor(DrawListID p_list, const Rect2 &p_rect) { ERR_RENDER_THREAD_GUARD(); @@ -6555,6 +6665,12 @@ void RenderingDevice::finalize() { ERR_FAIL_COND(reverse_dependency_map.size()); } +void RenderingDevice::_set_max_fps(int p_max_fps) { + for (const KeyValue<DisplayServer::WindowID, RDD::SwapChainID> &it : screen_swap_chains) { + driver->swap_chain_set_max_fps(it.value, p_max_fps); + } +} + RenderingDevice *RenderingDevice::create_local_device() { RenderingDevice *rd = memnew(RenderingDevice); rd->initialize(context); @@ -6653,6 +6769,7 @@ void RenderingDevice::_bind_methods() { ClassDB::bind_method(D_METHOD("draw_list_set_push_constant", "draw_list", "buffer", "size_bytes"), &RenderingDevice::_draw_list_set_push_constant); ClassDB::bind_method(D_METHOD("draw_list_draw", "draw_list", "use_indices", "instances", "procedural_vertex_count"), &RenderingDevice::draw_list_draw, DEFVAL(0)); + ClassDB::bind_method(D_METHOD("draw_list_draw_indirect", "draw_list", "use_indices", "buffer", "offset", "draw_count", "stride"), &RenderingDevice::draw_list_draw_indirect, DEFVAL(0), DEFVAL(1), DEFVAL(0)); ClassDB::bind_method(D_METHOD("draw_list_enable_scissor", "draw_list", "rect"), &RenderingDevice::draw_list_enable_scissor, DEFVAL(Rect2())); ClassDB::bind_method(D_METHOD("draw_list_disable_scissor", "draw_list"), &RenderingDevice::draw_list_disable_scissor); diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h index 0a3663523e..6831f3df2b 100644 --- a/servers/rendering/rendering_device.h +++ b/servers/rendering/rendering_device.h @@ -1188,6 +1188,7 @@ public: void draw_list_set_push_constant(DrawListID p_list, const void *p_data, uint32_t p_data_size); void draw_list_draw(DrawListID p_list, bool p_use_indices, uint32_t p_instances = 1, uint32_t p_procedural_vertices = 0); + void draw_list_draw_indirect(DrawListID p_list, bool p_use_indices, RID p_buffer, uint32_t p_offset = 0, uint32_t p_draw_count = 1, uint32_t p_stride = 0); void draw_list_enable_scissor(DrawListID p_list, const Rect2 &p_rect); void draw_list_disable_scissor(DrawListID p_list); @@ -1429,6 +1430,8 @@ public: Error initialize(RenderingContextDriver *p_context, DisplayServer::WindowID p_main_window = DisplayServer::INVALID_WINDOW_ID); void finalize(); + void _set_max_fps(int p_max_fps); + void free(RID p_id); /****************/ diff --git a/servers/rendering/rendering_device_driver.h b/servers/rendering/rendering_device_driver.h index 22ef46a1c8..258717091d 100644 --- a/servers/rendering/rendering_device_driver.h +++ b/servers/rendering/rendering_device_driver.h @@ -459,6 +459,10 @@ public: // Retrieve the format used by the swap chain's framebuffers. virtual DataFormat swap_chain_get_format(SwapChainID p_swap_chain) = 0; + // Tells the swapchain the max_fps so it can use the proper frame pacing. + // Android uses this with Swappy library. Some implementations or platforms may ignore this hint. + virtual void swap_chain_set_max_fps(SwapChainID p_swap_chain, int p_max_fps) {} + // Wait until all rendering associated to the swap chain is finished before deleting it. virtual void swap_chain_free(SwapChainID p_swap_chain) = 0; diff --git a/servers/rendering/rendering_device_graph.cpp b/servers/rendering/rendering_device_graph.cpp index fa26fdd79d..2e394df0bb 100644 --- a/servers/rendering/rendering_device_graph.cpp +++ b/servers/rendering/rendering_device_graph.cpp @@ -710,6 +710,16 @@ void RenderingDeviceGraph::_run_draw_list_command(RDD::CommandBufferID p_command driver->command_render_draw_indexed(p_command_buffer, draw_indexed_instruction->index_count, draw_indexed_instruction->instance_count, draw_indexed_instruction->first_index, 0, 0); instruction_data_cursor += sizeof(DrawListDrawIndexedInstruction); } break; + case DrawListInstruction::TYPE_DRAW_INDIRECT: { + const DrawListDrawIndirectInstruction *draw_indirect_instruction = reinterpret_cast<const DrawListDrawIndirectInstruction *>(instruction); + driver->command_render_draw_indirect(p_command_buffer, draw_indirect_instruction->buffer, draw_indirect_instruction->offset, draw_indirect_instruction->draw_count, draw_indirect_instruction->stride); + instruction_data_cursor += sizeof(DrawListDrawIndirectInstruction); + } break; + case DrawListInstruction::TYPE_DRAW_INDEXED_INDIRECT: { + const DrawListDrawIndexedIndirectInstruction *draw_indexed_indirect_instruction = reinterpret_cast<const DrawListDrawIndexedIndirectInstruction *>(instruction); + driver->command_render_draw_indexed_indirect(p_command_buffer, draw_indexed_indirect_instruction->buffer, draw_indexed_indirect_instruction->offset, draw_indexed_indirect_instruction->draw_count, draw_indexed_indirect_instruction->stride); + instruction_data_cursor += sizeof(DrawListDrawIndexedIndirectInstruction); + } break; case DrawListInstruction::TYPE_EXECUTE_COMMANDS: { const DrawListExecuteCommandsInstruction *execute_commands_instruction = reinterpret_cast<const DrawListExecuteCommandsInstruction *>(instruction); driver->command_buffer_execute_secondary(p_command_buffer, execute_commands_instruction->command_buffer); @@ -1191,6 +1201,16 @@ void RenderingDeviceGraph::_print_draw_list(const uint8_t *p_instruction_data, u print_line("\tDRAW INDICES", draw_indexed_instruction->index_count, "INSTANCES", draw_indexed_instruction->instance_count, "FIRST INDEX", draw_indexed_instruction->first_index); instruction_data_cursor += sizeof(DrawListDrawIndexedInstruction); } break; + case DrawListInstruction::TYPE_DRAW_INDIRECT: { + const DrawListDrawIndirectInstruction *draw_indirect_instruction = reinterpret_cast<const DrawListDrawIndirectInstruction *>(instruction); + print_line("\tDRAW INDIRECT BUFFER ID", itos(draw_indirect_instruction->buffer.id), "OFFSET", draw_indirect_instruction->offset, "DRAW COUNT", draw_indirect_instruction->draw_count, "STRIDE", draw_indirect_instruction->stride); + instruction_data_cursor += sizeof(DrawListDrawIndirectInstruction); + } break; + case DrawListInstruction::TYPE_DRAW_INDEXED_INDIRECT: { + const DrawListDrawIndexedIndirectInstruction *draw_indexed_indirect_instruction = reinterpret_cast<const DrawListDrawIndexedIndirectInstruction *>(instruction); + print_line("\tDRAW INDEXED INDIRECT BUFFER ID", itos(draw_indexed_indirect_instruction->buffer.id), "OFFSET", draw_indexed_indirect_instruction->offset, "DRAW COUNT", draw_indexed_indirect_instruction->draw_count, "STRIDE", draw_indexed_indirect_instruction->stride); + instruction_data_cursor += sizeof(DrawListDrawIndexedIndirectInstruction); + } break; case DrawListInstruction::TYPE_EXECUTE_COMMANDS: { print_line("\tEXECUTE COMMANDS"); instruction_data_cursor += sizeof(DrawListExecuteCommandsInstruction); @@ -1613,6 +1633,26 @@ void RenderingDeviceGraph::add_draw_list_draw_indexed(uint32_t p_index_count, ui instruction->first_index = p_first_index; } +void RenderingDeviceGraph::add_draw_list_draw_indirect(RDD::BufferID p_buffer, uint32_t p_offset, uint32_t p_draw_count, uint32_t p_stride) { + DrawListDrawIndirectInstruction *instruction = reinterpret_cast<DrawListDrawIndirectInstruction *>(_allocate_draw_list_instruction(sizeof(DrawListDrawIndirectInstruction))); + instruction->type = DrawListInstruction::TYPE_DRAW_INDIRECT; + instruction->buffer = p_buffer; + instruction->offset = p_offset; + instruction->draw_count = p_draw_count; + instruction->stride = p_stride; + draw_instruction_list.stages.set_flag(RDD::PIPELINE_STAGE_DRAW_INDIRECT_BIT); +} + +void RenderingDeviceGraph::add_draw_list_draw_indexed_indirect(RDD::BufferID p_buffer, uint32_t p_offset, uint32_t p_draw_count, uint32_t p_stride) { + DrawListDrawIndexedIndirectInstruction *instruction = reinterpret_cast<DrawListDrawIndexedIndirectInstruction *>(_allocate_draw_list_instruction(sizeof(DrawListDrawIndexedIndirectInstruction))); + instruction->type = DrawListInstruction::TYPE_DRAW_INDEXED_INDIRECT; + instruction->buffer = p_buffer; + instruction->offset = p_offset; + instruction->draw_count = p_draw_count; + instruction->stride = p_stride; + draw_instruction_list.stages.set_flag(RDD::PIPELINE_STAGE_DRAW_INDIRECT_BIT); +} + void RenderingDeviceGraph::add_draw_list_execute_commands(RDD::CommandBufferID p_command_buffer) { DrawListExecuteCommandsInstruction *instruction = reinterpret_cast<DrawListExecuteCommandsInstruction *>(_allocate_draw_list_instruction(sizeof(DrawListExecuteCommandsInstruction))); instruction->type = DrawListInstruction::TYPE_EXECUTE_COMMANDS; diff --git a/servers/rendering/rendering_device_graph.h b/servers/rendering/rendering_device_graph.h index f4d2e8534f..0148c6b78d 100644 --- a/servers/rendering/rendering_device_graph.h +++ b/servers/rendering/rendering_device_graph.h @@ -71,6 +71,8 @@ public: TYPE_CLEAR_ATTACHMENTS, TYPE_DRAW, TYPE_DRAW_INDEXED, + TYPE_DRAW_INDIRECT, + TYPE_DRAW_INDEXED_INDIRECT, TYPE_EXECUTE_COMMANDS, TYPE_NEXT_SUBPASS, TYPE_SET_BLEND_CONSTANTS, @@ -474,6 +476,20 @@ private: uint32_t first_index = 0; }; + struct DrawListDrawIndirectInstruction : DrawListInstruction { + RDD::BufferID buffer; + uint32_t offset = 0; + uint32_t draw_count = 0; + uint32_t stride = 0; + }; + + struct DrawListDrawIndexedIndirectInstruction : DrawListInstruction { + RDD::BufferID buffer; + uint32_t offset = 0; + uint32_t draw_count = 0; + uint32_t stride = 0; + }; + struct DrawListEndRenderPassInstruction : DrawListInstruction { // No contents. }; @@ -686,6 +702,8 @@ public: void add_draw_list_clear_attachments(VectorView<RDD::AttachmentClear> p_attachments_clear, VectorView<Rect2i> p_attachments_clear_rect); void add_draw_list_draw(uint32_t p_vertex_count, uint32_t p_instance_count); void add_draw_list_draw_indexed(uint32_t p_index_count, uint32_t p_instance_count, uint32_t p_first_index); + void add_draw_list_draw_indirect(RDD::BufferID p_buffer, uint32_t p_offset, uint32_t p_draw_count, uint32_t p_stride); + void add_draw_list_draw_indexed_indirect(RDD::BufferID p_buffer, uint32_t p_offset, uint32_t p_draw_count, uint32_t p_stride); void add_draw_list_execute_commands(RDD::CommandBufferID p_command_buffer); void add_draw_list_next_subpass(RDD::CommandBufferType p_command_buffer_type); void add_draw_list_set_blend_constants(const Color &p_color); diff --git a/servers/rendering/storage/camera_attributes_storage.h b/servers/rendering/storage/camera_attributes_storage.h index 05a44c38e7..0fff7cf72f 100644 --- a/servers/rendering/storage/camera_attributes_storage.h +++ b/servers/rendering/storage/camera_attributes_storage.h @@ -74,8 +74,8 @@ public: RendererCameraAttributes(); ~RendererCameraAttributes(); - CameraAttributes *get_camera_attributes(RID p_rid) { return camera_attributes_owner.get_or_null(p_rid); }; - bool owns_camera_attributes(RID p_rid) { return camera_attributes_owner.owns(p_rid); }; + CameraAttributes *get_camera_attributes(RID p_rid) { return camera_attributes_owner.get_or_null(p_rid); } + bool owns_camera_attributes(RID p_rid) { return camera_attributes_owner.owns(p_rid); } RID camera_attributes_allocate(); void camera_attributes_initialize(RID p_rid); diff --git a/servers/rendering/storage/render_scene_buffers.cpp b/servers/rendering/storage/render_scene_buffers.cpp index 3894559dc9..fd4131e1fa 100644 --- a/servers/rendering/storage/render_scene_buffers.cpp +++ b/servers/rendering/storage/render_scene_buffers.cpp @@ -83,7 +83,7 @@ void RenderSceneBuffersExtension::_bind_methods() { void RenderSceneBuffersExtension::configure(const RenderSceneBuffersConfiguration *p_config) { GDVIRTUAL_CALL(_configure, p_config); -}; +} void RenderSceneBuffersExtension::set_fsr_sharpness(float p_fsr_sharpness) { GDVIRTUAL_CALL(_set_fsr_sharpness, p_fsr_sharpness); |