From f8bcde99ba1eace6b283e8d7f4f233225b07a566 Mon Sep 17 00:00:00 2001 From: Dario Date: Thu, 24 Oct 2024 16:01:00 -0300 Subject: [PATCH] Resolve load and store ops automatically for render passes for transient textures. --- doc/classes/RDTextureFormat.xml | 7 + doc/classes/RenderSceneBuffersRD.xml | 1 + doc/classes/RenderingDevice.xml | 99 +++-- .../4.3-stable.expected | 22 + modules/lightmapper_rd/lightmapper_rd.cpp | 7 +- .../renderer_rd/cluster_builder_rd.cpp | 2 +- .../renderer_rd/effects/bokeh_dof.cpp | 12 +- .../renderer_rd/effects/copy_effects.cpp | 24 +- .../renderer_rd/effects/debug_effects.cpp | 6 +- .../rendering/renderer_rd/effects/fsr2.cpp | 1 + .../renderer_rd/effects/luminance.cpp | 2 +- .../renderer_rd/effects/tone_mapper.cpp | 2 +- servers/rendering/renderer_rd/effects/vrs.cpp | 2 +- .../rendering/renderer_rd/environment/gi.cpp | 2 +- .../rendering/renderer_rd/environment/sky.cpp | 10 +- .../render_forward_clustered.cpp | 36 +- .../render_forward_clustered.h | 6 +- .../forward_mobile/render_forward_mobile.cpp | 22 +- .../forward_mobile/render_forward_mobile.h | 4 +- .../renderer_rd/renderer_canvas_render_rd.cpp | 9 +- .../renderer_rd/renderer_scene_render_rd.cpp | 2 +- .../render_scene_buffers_rd.compat.inc | 6 + .../storage_rd/render_scene_buffers_rd.cpp | 9 +- .../storage_rd/render_scene_buffers_rd.h | 4 +- .../storage_rd/texture_storage.cpp | 6 +- servers/rendering/rendering_device.compat.inc | 13 +- servers/rendering/rendering_device.cpp | 385 ++++++++---------- servers/rendering/rendering_device.h | 122 +++--- servers/rendering/rendering_device_binds.h | 5 + servers/rendering/rendering_device_commons.h | 1 + servers/rendering/rendering_device_graph.cpp | 255 +++++++++--- servers/rendering/rendering_device_graph.h | 72 +++- 32 files changed, 687 insertions(+), 469 deletions(-) diff --git a/doc/classes/RDTextureFormat.xml b/doc/classes/RDTextureFormat.xml index f8de7feda0bf..074282f14a17 100644 --- a/doc/classes/RDTextureFormat.xml +++ b/doc/classes/RDTextureFormat.xml @@ -35,6 +35,13 @@ The texture's height (in pixels). + + The texture will be used as the destination of a resolve operation. + + + If a texture is transient, its contents do not need to be preserved between frames. This flag is only relevant when the texture is used as target in a draw list. + This information is used by [RenderingDevice] to figure out if a texture's contents can be discarded and eliminate unnecessary writes to memory and boosting performance. + The number of mipmaps available in the texture. diff --git a/doc/classes/RenderSceneBuffersRD.xml b/doc/classes/RenderSceneBuffersRD.xml index 212a65337eac..83405e6166c3 100644 --- a/doc/classes/RenderSceneBuffersRD.xml +++ b/doc/classes/RenderSceneBuffersRD.xml @@ -30,6 +30,7 @@ + Create a new texture with the given definition and cache this under the given name. Will return the existing texture if it already exists. diff --git a/doc/classes/RenderingDevice.xml b/doc/classes/RenderingDevice.xml index fe23f7911924..fb5164c3e267 100644 --- a/doc/classes/RenderingDevice.xml +++ b/doc/classes/RenderingDevice.xml @@ -210,15 +210,14 @@ - - - - - - - - - + + + + + + + + Starts a list of raster drawing commands created with the [code]draw_*[/code] methods. The returned value should be passed to other [code]draw_list_*[/code] functions. Multiple draw lists cannot be created at the same time; you must finish the previous draw list first using [method draw_list_end]. @@ -226,7 +225,7 @@ [codeblock] var rd = RenderingDevice.new() var clear_colors = PackedColorArray([Color(0, 0, 0, 0), Color(0, 0, 0, 0), Color(0, 0, 0, 0)]) - var draw_list = rd.draw_list_begin(framebuffers[i], RenderingDevice.INITIAL_ACTION_CLEAR, RenderingDevice.FINAL_ACTION_READ, RenderingDevice.INITIAL_ACTION_CLEAR, RenderingDevice.FINAL_ACTION_DISCARD, clear_colors, RenderingDevice.OPAQUE_PASS) + var draw_list = rd.draw_list_begin(framebuffers[i], RenderingDevice.CLEAR_COLOR_ALL, clear_colors, true, 1.0f, true, 0, Rect2(), RenderingDevice.OPAQUE_PASS) # Draw opaque. rd.draw_list_bind_render_pipeline(draw_list, raster_pipeline) @@ -244,7 +243,7 @@ The [param breadcrumb] parameter can be an arbitrary 32-bit integer that is useful to diagnose GPU crashes. If Godot is built in dev or debug mode; when the GPU crashes Godot will dump all shaders that were being executed at the time of the crash and the breadcrumb is useful to diagnose what passes did those shaders belong to. It does not affect rendering behavior and can be set to 0. It is recommended to use [enum BreadcrumbMarker] enumerations for consistency but it's not required. It is also possible to use bitwise operations to add extra data. e.g. [codeblock] - rd.draw_list_begin(fb[i], RenderingDevice.INITIAL_ACTION_CLEAR, RenderingDevice.FINAL_ACTION_READ, RenderingDevice.INITIAL_ACTION_CLEAR, RenderingDevice.FINAL_ACTION_DISCARD, clear_colors, RenderingDevice.OPAQUE_PASS | 5) + rd.draw_list_begin(fb[i], RenderingDevice.CLEAR_COLOR_ALL, clear_colors, true, 1.0f, true, 0, Rect2(), RenderingDevice.OPAQUE_PASS | 5) [/codeblock] @@ -962,6 +961,13 @@ Returns [code]true[/code] if the [param texture] is shared, [code]false[/code] otherwise. See [RDTextureView]. + + + + + Returns [code]true[/code] if the [param texture] is transient, [code]false[/code] otherwise. See [RDTextureFormat] or [method texture_set_transient]. + + @@ -984,6 +990,16 @@ [b]Note:[/b] [param to_texture] texture must [b]not[/b] be multisampled and must also be 2D (or a slice of a 3D/cubemap texture). + + + + + + Updates the transient property of [param texture]. + If a texture is transient, its contents do not need to be preserved between frames. This flag is only relevant when the texture is used as target in a draw list. + This information is used by [RenderingDevice] to figure out if a texture's contents can be discarded and eliminate unnecessary writes to memory and boosting performance. + + @@ -2279,40 +2295,40 @@ - + Load the previous contents of the framebuffer. - + Clear the whole framebuffer or its specified region. - + Ignore the previous contents of the framebuffer. This is the fastest option if you'll overwrite all of the pixels and don't need to read any of them. - + Represents the size of the [enum InitialAction] enum. - + - + - + - + - + - + Store the result of the draw list in the framebuffer. This is generally what you want to do. - + Discard the contents of the framebuffer. This is the fastest option if you don't need to use the results of the draw list. - + Represents the size of the [enum FinalAction] enum. - + - + Vertex shader stage. This can be used to manipulate vertices from a shader (but not create new vertices). @@ -2514,5 +2530,38 @@ + + Do not clear any color attachments. + + + Clear the first color attachment. + + + Clear the second color attachment. + + + Clear the third color attachment. + + + Clear the fourth color attachment. + + + Clear the fifth color attachment. + + + Clear the sixth color attachment. + + + Clear the seventh color attachment. + + + Clear the eighth color attachment. + + + Mask for all color attachments. + + + Clear all color attachments. + diff --git a/misc/extension_api_validation/4.3-stable.expected b/misc/extension_api_validation/4.3-stable.expected index 9e169d474d7c..1ec62a5b4e49 100644 --- a/misc/extension_api_validation/4.3-stable.expected +++ b/misc/extension_api_validation/4.3-stable.expected @@ -102,3 +102,25 @@ GH-97020 Validate extension JSON: Error: Field 'classes/AnimationNode/methods/_process': is_const changed value in new API, from true to false. `_process` virtual method fixed to be non const instead. + + +GH-98670 +-------- +Validate extension JSON: Error: Field 'classes/RenderSceneBuffersRD/methods/create_texture/arguments': size changed value in new API, from 9 to 10. +Validate extension JSON: Error: Field 'classes/RenderingDevice/methods/draw_list_begin/arguments': meta was removed. +Validate extension JSON: Error: Field 'classes/RenderingDevice/methods/draw_list_begin/arguments/1': type changed value in new API, from "enum::RenderingDevice.InitialAction" to "bitfield::RenderingDevice.ClearColorFlags". +Validate extension JSON: Error: Field 'classes/RenderingDevice/methods/draw_list_begin/arguments/2': type changed value in new API, from "enum::RenderingDevice.FinalAction" to "PackedColorArray". +Validate extension JSON: Error: Field 'classes/RenderingDevice/methods/draw_list_begin/arguments/3': type changed value in new API, from "enum::RenderingDevice.InitialAction" to "bool". +Validate extension JSON: Error: Field 'classes/RenderingDevice/methods/draw_list_begin/arguments/4': type changed value in new API, from "enum::RenderingDevice.FinalAction" to "float". +Validate extension JSON: Error: Field 'classes/RenderingDevice/methods/draw_list_begin/arguments/5': default_value changed value in new API, from "PackedColorArray()" to "false". +Validate extension JSON: Error: Field 'classes/RenderingDevice/methods/draw_list_begin/arguments/5': type changed value in new API, from "PackedColorArray" to "bool". +Validate extension JSON: Error: Field 'classes/RenderingDevice/methods/draw_list_begin/arguments/6': default_value changed value in new API, from "1.0" to "0". +Validate extension JSON: Error: Field 'classes/RenderingDevice/methods/draw_list_begin/arguments/6': meta changed value in new API, from "float" to "uint32". +Validate extension JSON: Error: Field 'classes/RenderingDevice/methods/draw_list_begin/arguments/6': type changed value in new API, from "float" to "int". +Validate extension JSON: Error: Field 'classes/RenderingDevice/methods/draw_list_begin/arguments/7': default_value changed value in new API, from "0" to "Rect2(0, 0, 0, 0)". +Validate extension JSON: Error: Field 'classes/RenderingDevice/methods/draw_list_begin/arguments/7': type changed value in new API, from "int" to "Rect2". +Validate extension JSON: Error: Field 'classes/RenderingDevice/methods/draw_list_begin/arguments/8': default_value changed value in new API, from "Rect2(0, 0, 0, 0)" to "0". +Validate extension JSON: Error: Field 'classes/RenderingDevice/methods/draw_list_begin/arguments/8': type changed value in new API, from "Rect2" to "int". + +Draw lists no longer require the initial and final action for color and depth attachments to be specified. +Draw lists can now specify if a particular color, depth or stencil attachment should be cleared. diff --git a/modules/lightmapper_rd/lightmapper_rd.cpp b/modules/lightmapper_rd/lightmapper_rd.cpp index 8ba6f9e2ba03..e4ed3297eda7 100644 --- a/modules/lightmapper_rd/lightmapper_rd.cpp +++ b/modules/lightmapper_rd/lightmapper_rd.cpp @@ -718,7 +718,7 @@ void LightmapperRD::_raster_geometry(RenderingDevice *rd, Size2i atlas_size, int raster_push_constant.uv_offset[0] = -0.5f / float(atlas_size.x); raster_push_constant.uv_offset[1] = -0.5f / float(atlas_size.y); - RD::DrawListID draw_list = rd->draw_list_begin(framebuffers[i], RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors, 1.0, 0, Rect2(), RDD::BreadcrumbMarker::LIGHTMAPPER_PASS); + RD::DrawListID draw_list = rd->draw_list_begin(framebuffers[i], RD::CLEAR_COLOR_ALL, clear_colors, true, 1.0f, false, 0, Rect2(), RDD::BreadcrumbMarker::LIGHTMAPPER_PASS); //draw opaque rd->draw_list_bind_render_pipeline(draw_list, raster_pipeline); rd->draw_list_bind_uniform_set(draw_list, raster_base_uniform, 0); @@ -1405,6 +1405,7 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d tf.texture_type = RD::TEXTURE_TYPE_2D; tf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; tf.format = RD::DATA_FORMAT_D32_SFLOAT; + tf.is_transient = true; raster_depth_buffer = rd->texture_create(tf, RD::TextureView()); } @@ -1956,8 +1957,6 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d uint32_t seam_offset = 0; uint32_t triangle_offset = 0; - Vector clear_colors; - clear_colors.push_back(Color(0, 0, 0, 1)); for (int i = 0; i < atlas_slices; i++) { int subslices = (p_bake_sh ? 4 : 1); @@ -1971,7 +1970,7 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d seams_push_constant.debug = debug; // Store the current subslice in the breadcrumb. - RD::DrawListID draw_list = rd->draw_list_begin(framebuffers[i * subslices + k], RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors, 1.0, 0, Rect2(), RDD::BreadcrumbMarker::LIGHTMAPPER_PASS | seams_push_constant.slice); + RD::DrawListID draw_list = rd->draw_list_begin(framebuffers[i * subslices + k], RD::CLEAR_COLOR_NONE, Vector(), true, 1.0f, false, 0, Rect2(), RDD::BreadcrumbMarker::LIGHTMAPPER_PASS | seams_push_constant.slice); rd->draw_list_bind_uniform_set(draw_list, raster_base_uniform, 0); rd->draw_list_bind_uniform_set(draw_list, blendseams_raster_uniform, 1); diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.cpp b/servers/rendering/renderer_rd/cluster_builder_rd.cpp index 41df6107a8d4..752e0fe45319 100644 --- a/servers/rendering/renderer_rd/cluster_builder_rd.cpp +++ b/servers/rendering/renderer_rd/cluster_builder_rd.cpp @@ -452,7 +452,7 @@ void ClusterBuilderRD::bake_cluster() { // Render elements. { - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_DISCARD, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_DISCARD, RD::FINAL_ACTION_DISCARD); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer); ClusterBuilderSharedDataRD::ClusterRender::PushConstant push_constant = {}; RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, shared->cluster_render.shader_pipelines[use_msaa ? ClusterBuilderSharedDataRD::ClusterRender::PIPELINE_MSAA : ClusterBuilderSharedDataRD::ClusterRender::PIPELINE_NORMAL]); diff --git a/servers/rendering/renderer_rd/effects/bokeh_dof.cpp b/servers/rendering/renderer_rd/effects/bokeh_dof.cpp index e6262c83e2b3..398718e79fa6 100644 --- a/servers/rendering/renderer_rd/effects/bokeh_dof.cpp +++ b/servers/rendering/renderer_rd/effects/bokeh_dof.cpp @@ -356,7 +356,7 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, RID p_camera_attr ERR_FAIL_COND(shader.is_null()); RID framebuffer = p_buffers.base_weight_fb; - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[BOKEH_GEN_BLUR_SIZE].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer))); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_depth_texture), 0); @@ -388,7 +388,7 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, RID p_camera_attr RID framebuffer = bokeh.push_constant.half_size ? p_buffers.half_fb[0] : p_buffers.secondary_fb; // Pass 1 - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer))); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_base_texture), 0); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_weight_texture0), 1); @@ -412,7 +412,7 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, RID p_camera_attr RD::Uniform texture = bokeh.push_constant.half_size ? u_half_texture0 : u_secondary_texture; RD::Uniform weight = bokeh.push_constant.half_size ? u_weight_texture2 : u_weight_texture1; - draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD); + draw_list = RD::get_singleton()->draw_list_begin(framebuffer); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer))); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, texture), 0); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, weight), 1); @@ -430,7 +430,7 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, RID p_camera_attr framebuffer = p_buffers.base_fb; - draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD); + draw_list = RD::get_singleton()->draw_list_begin(framebuffer); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer))); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_half_texture1), 0); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_weight_texture3), 1); @@ -463,7 +463,7 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, RID p_camera_attr RID framebuffer = bokeh.push_constant.half_size ? p_buffers.half_fb[0] : p_buffers.secondary_fb; - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer))); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_base_texture), 0); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_weight_texture0), 1); @@ -481,7 +481,7 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, RID p_camera_attr framebuffer = p_buffers.base_fb; - draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD); + draw_list = RD::get_singleton()->draw_list_begin(framebuffer); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer))); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_half_texture0), 0); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_weight_texture2), 1); diff --git a/servers/rendering/renderer_rd/effects/copy_effects.cpp b/servers/rendering/renderer_rd/effects/copy_effects.cpp index c7a7532d7694..0a017f845935 100644 --- a/servers/rendering/renderer_rd/effects/copy_effects.cpp +++ b/servers/rendering/renderer_rd/effects/copy_effects.cpp @@ -591,7 +591,7 @@ void CopyEffects::copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffe 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(p_dest_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD, Vector(), 0.0, 0, p_rect); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::CLEAR_COLOR_NONE, Vector(), false, 1.0f, false, 0, p_rect); 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(p_dest_framebuffer))); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0); if (p_secondary.is_valid()) { @@ -658,7 +658,7 @@ void CopyEffects::copy_raster(RID p_source_texture, RID p_dest_framebuffer) { ERR_FAIL_COND(shader.is_null()); // Just copy it back (we use our blur raster shader here).. - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(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_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant)); @@ -731,7 +731,7 @@ void CopyEffects::gaussian_blur_raster(RID p_source_rd_texture, RID p_dest_textu 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_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(dest_framebuffer); 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); @@ -833,7 +833,7 @@ void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, RID p_half_textu ERR_FAIL_COND(shader.is_null()); //HORIZONTAL - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(half_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(half_framebuffer); 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(half_framebuffer))); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0); if (p_auto_exposure.is_valid() && p_first_pass) { @@ -853,7 +853,7 @@ void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, RID p_half_textu ERR_FAIL_COND(shader.is_null()); //VERTICAL - draw_list = RD::get_singleton()->draw_list_begin(dest_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD); + draw_list = RD::get_singleton()->draw_list_begin(dest_framebuffer); 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_half_texture), 0); @@ -923,7 +923,7 @@ void CopyEffects::make_mipmap_raster(RID p_source_rd_texture, RID p_dest_texture RID shader = blur_raster.shader.version_get_shader(blur_raster.shader_version, mode); ERR_FAIL_COND(shader.is_null()); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(dest_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(dest_framebuffer); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[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_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant)); @@ -988,7 +988,7 @@ void CopyEffects::set_color_raster(RID p_dest_texture, const Color &p_color, con 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_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD, Vector(), 0.0, 0, p_region); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(dest_framebuffer, RD::CLEAR_COLOR_NONE, Vector(), false, 1.0f, false, 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)); @@ -1021,7 +1021,7 @@ void CopyEffects::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuf RID shader = cube_to_dp.shader.version_get_shader(cube_to_dp.shader_version, 0); ERR_FAIL_COND(shader.is_null()); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dst_framebuffer, RD::INITIAL_ACTION_DISCARD, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dst_framebuffer, RD::CLEAR_COLOR_NONE, Vector()); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, cube_to_dp.pipeline.get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dst_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()); @@ -1086,7 +1086,7 @@ void CopyEffects::cubemap_downsample_raster(RID p_source_cubemap, RID p_dest_fra RID shader = cubemap_downsampler.raster_shader.version_get_shader(cubemap_downsampler.shader_version, 0); ERR_FAIL_COND(shader.is_null()); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, cubemap_downsampler.raster_pipeline.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_cubemap), 0); @@ -1165,7 +1165,7 @@ void CopyEffects::cubemap_filter_raster(RID p_source_cubemap, RID p_dest_framebu RID shader = filter.raster_shader.version_get_shader(filter.shader_version, mode); ERR_FAIL_COND(shader.is_null()); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, filter.raster_pipelines[mode].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_cubemap), 0); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, filter.uniform_set, 1); @@ -1243,7 +1243,7 @@ void CopyEffects::cubemap_roughness_raster(RID p_source_rd_texture, RID p_dest_f RID shader = roughness.raster_shader.version_get_shader(roughness.shader_version, 0); ERR_FAIL_COND(shader.is_null()); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, roughness.raster_pipeline.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_rd_texture), 0); @@ -1263,7 +1263,7 @@ void CopyEffects::merge_specular(RID p_dest_framebuffer, RID p_specular, RID p_b RD::get_singleton()->draw_command_begin_label("Merge specular"); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, Vector()); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer); int mode; if (p_reflection.is_valid()) { diff --git a/servers/rendering/renderer_rd/effects/debug_effects.cpp b/servers/rendering/renderer_rd/effects/debug_effects.cpp index 04afaf63d756..741bdb4db143 100644 --- a/servers/rendering/renderer_rd/effects/debug_effects.cpp +++ b/servers/rendering/renderer_rd/effects/debug_effects.cpp @@ -282,7 +282,7 @@ void DebugEffects::draw_shadow_frustum(RID p_light, const Projection &p_cam_proj // And draw our frustum. RD::FramebufferFormatID fb_format_id = RD::get_singleton()->framebuffer_get_format(p_dest_fb); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_fb, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD, Vector(), 0.0, 0, rect); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_fb, RD::CLEAR_COLOR_NONE, Vector(), false, 1.0f, false, 0, rect); RID pipeline = shadow_frustum.pipelines[SFP_TRANSPARENT].get_render_pipeline(frustum.vertex_format, fb_format_id); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, pipeline); @@ -326,7 +326,7 @@ void DebugEffects::draw_shadow_frustum(RID p_light, const Projection &p_cam_proj rect.size.x *= atlas_rect_norm.size.x; rect.size.y *= atlas_rect_norm.size.y; - draw_list = RD::get_singleton()->draw_list_begin(p_dest_fb, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD, Vector(), 0.0, 0, rect); + draw_list = RD::get_singleton()->draw_list_begin(p_dest_fb, RD::CLEAR_COLOR_NONE, Vector(), false, 1.0f, false, 0, rect); pipeline = shadow_frustum.pipelines[SFP_TRANSPARENT].get_render_pipeline(frustum.vertex_format, fb_format_id); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, pipeline); @@ -351,7 +351,7 @@ void DebugEffects::draw_motion_vectors(RID p_velocity, RID p_depth, RID p_dest_f RD::Uniform u_source_velocity(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector({ default_sampler, p_velocity })); RD::Uniform u_source_depth(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 1, Vector({ default_sampler, p_depth })); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_fb, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_DISCARD, RD::FINAL_ACTION_DISCARD); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_fb); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, motion_vectors.pipeline.get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_fb), false, RD::get_singleton()->draw_list_get_current_pass())); Projection correction; diff --git a/servers/rendering/renderer_rd/effects/fsr2.cpp b/servers/rendering/renderer_rd/effects/fsr2.cpp index 551ea5dd9728..4b3252985224 100644 --- a/servers/rendering/renderer_rd/effects/fsr2.cpp +++ b/servers/rendering/renderer_rd/effects/fsr2.cpp @@ -235,6 +235,7 @@ static FfxErrorCode create_resource_rd(FfxFsr2Interface *p_backend_interface, co texture_format.height = res_desc.height; texture_format.depth = res_desc.depth; texture_format.mipmaps = res_desc.mipCount; + texture_format.is_transient = true; RID texture = rd->texture_create(texture_format, RD::TextureView(), initial_data); ERR_FAIL_COND_V(texture.is_null(), FFX_ERROR_BACKEND_API_ERROR); diff --git a/servers/rendering/renderer_rd/effects/luminance.cpp b/servers/rendering/renderer_rd/effects/luminance.cpp index 61b2248b5cdf..4727e8fd9a9c 100644 --- a/servers/rendering/renderer_rd/effects/luminance.cpp +++ b/servers/rendering/renderer_rd/effects/luminance.cpp @@ -184,7 +184,7 @@ void Luminance::luminance_reduction(RID p_source_texture, const Size2i p_source_ RD::Uniform u_source_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector({ default_sampler, i == 0 ? p_source_texture : p_luminance_buffers->reduce[i - 1] })); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, luminance_reduce_raster.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer))); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_texture), 0); if (final) { diff --git a/servers/rendering/renderer_rd/effects/tone_mapper.cpp b/servers/rendering/renderer_rd/effects/tone_mapper.cpp index e943071f0e47..83cf2ed7195d 100644 --- a/servers/rendering/renderer_rd/effects/tone_mapper.cpp +++ b/servers/rendering/renderer_rd/effects/tone_mapper.cpp @@ -166,7 +166,7 @@ void ToneMapper::tonemapper(RID p_source_color, RID p_dst_framebuffer, const Ton RID shader = tonemap.shader.version_get_shader(tonemap.shader_version, mode); ERR_FAIL_COND(shader.is_null()); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dst_framebuffer, RD::INITIAL_ACTION_DISCARD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_DISCARD, RD::FINAL_ACTION_DISCARD); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dst_framebuffer); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, tonemap.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dst_framebuffer), false, RD::get_singleton()->draw_list_get_current_pass())); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_color), 0); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_exposure_texture), 1); diff --git a/servers/rendering/renderer_rd/effects/vrs.cpp b/servers/rendering/renderer_rd/effects/vrs.cpp index 94453bf95fb5..9cc22f6f5efc 100644 --- a/servers/rendering/renderer_rd/effects/vrs.cpp +++ b/servers/rendering/renderer_rd/effects/vrs.cpp @@ -94,7 +94,7 @@ void VRS::copy_vrs(RID p_source_rd_texture, RID p_dest_framebuffer, bool p_multi RID shader = vrs_shader.shader.version_get_shader(vrs_shader.shader_version, mode); ERR_FAIL_COND(shader.is_null()); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD, Vector()); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, vrs_shader.pipelines[mode].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_rd_texture), 0); RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(VRSPushConstant)); diff --git a/servers/rendering/renderer_rd/environment/gi.cpp b/servers/rendering/renderer_rd/environment/gi.cpp index 12ff28d7b054..241de1b18a7a 100644 --- a/servers/rendering/renderer_rd/environment/gi.cpp +++ b/servers/rendering/renderer_rd/environment/gi.cpp @@ -1721,7 +1721,7 @@ void GI::SDFGI::debug_probes(RID p_framebuffer, const uint32_t p_view_count, con SDFGIShader::ProbeDebugMode mode = p_view_count > 1 ? SDFGIShader::PROBE_DEBUG_PROBES_MULTIVIEW : SDFGIShader::PROBE_DEBUG_PROBES; - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer); RD::get_singleton()->draw_command_begin_label("Debug SDFGI"); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, gi->sdfgi_shader.debug_probes_pipeline[mode].get_render_pipeline(RD::INVALID_FORMAT_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer))); diff --git a/servers/rendering/renderer_rd/environment/sky.cpp b/servers/rendering/renderer_rd/environment/sky.cpp index 63956a7918f9..15a87bbb706d 100644 --- a/servers/rendering/renderer_rd/environment/sky.cpp +++ b/servers/rendering/renderer_rd/environment/sky.cpp @@ -1309,7 +1309,7 @@ void SkyRD::update_radiance_buffers(Ref p_render_buffers, 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, p_render_buffers); - cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[2].framebuffers[i], RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD); + cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[2].framebuffers[i]); _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(); } @@ -1330,7 +1330,7 @@ void SkyRD::update_radiance_buffers(Ref p_render_buffers, 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, p_render_buffers); - cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[1].framebuffers[i], RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD); + cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[1].framebuffers[i]); _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(); } @@ -1347,7 +1347,7 @@ void SkyRD::update_radiance_buffers(Ref p_render_buffers, 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, p_render_buffers); - cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[0].framebuffers[i], RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD, Vector(), 1.0, 0, Rect2(), RDD::BreadcrumbMarker::SKY_PASS | uint32_t(i)); + cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[0].framebuffers[i], RD::CLEAR_COLOR_NONE, Vector(), false, 1.0f, false, 0, Rect2(), RDD::BreadcrumbMarker::SKY_PASS | uint32_t(i)); _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(); } @@ -1471,7 +1471,7 @@ void SkyRD::update_res_buffers(Ref p_render_buffers, RID p Vector clear_colors; clear_colors.push_back(Color(0.0, 0.0, 0.0)); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors, 0.0); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::CLEAR_COLOR_ALL, 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(); } @@ -1490,7 +1490,7 @@ void SkyRD::update_res_buffers(Ref p_render_buffers, RID p Vector clear_colors; clear_colors.push_back(Color(0.0, 0.0, 0.0)); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors, 0.0); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::CLEAR_COLOR_ALL, 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(); } 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 76d8972ad98d..b1c7b216ebb8 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -639,11 +639,11 @@ void RenderForwardClustered::_render_list(RenderingDevice::DrawListID p_draw_lis } } -void RenderForwardClustered::_render_list_with_draw_list(RenderListParameters *p_params, RID p_framebuffer, RD::InitialAction p_initial_color_action, RD::FinalAction p_final_color_action, RD::InitialAction p_initial_depth_action, RD::FinalAction p_final_depth_action, const Vector &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region) { +void RenderForwardClustered::_render_list_with_draw_list(RenderListParameters *p_params, RID p_framebuffer, BitField p_clear_colors, const Vector &p_clear_color_values, bool p_clear_depth, float p_clear_depth_value, bool p_clear_stencil, uint32_t p_clear_stencil_value, const Rect2 &p_region) { RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(p_framebuffer); p_params->framebuffer_format = fb_format; - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, p_region); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, p_clear_colors, p_clear_color_values, p_clear_depth, p_clear_depth_value, p_clear_stencil, p_clear_stencil_value, p_region); _render_list(draw_list, fb_format, p_params, 0, p_params->element_count); RD::get_singleton()->draw_list_end(); } @@ -1472,7 +1472,7 @@ void RenderForwardClustered::_pre_opaque_render(RenderDataRD *p_render_data, boo if (p_render_data->directional_shadows.size()) { //open the pass for directional shadows light_storage->update_directional_shadow_atlas(); - RD::get_singleton()->draw_list_begin(light_storage->direction_shadow_get_fb(), RD::INITIAL_ACTION_DISCARD, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, Vector(), 0.0); + RD::get_singleton()->draw_list_begin(light_storage->direction_shadow_get_fb(), RD::CLEAR_COLOR_NONE, Vector(), true, 0.0f); RD::get_singleton()->draw_list_end(); } } @@ -2015,7 +2015,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co } if (needs_pre_resolve) { //pre clear the depth framebuffer, as AMD (and maybe others?) use compute for it, and barrier other compute shaders. - RD::get_singleton()->draw_list_begin(depth_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, depth_pass_clear, 0.0); + RD::get_singleton()->draw_list_begin(depth_framebuffer, RD::CLEAR_COLOR_ALL, depth_pass_clear, true, 0.0f); RD::get_singleton()->draw_list_end(); //start compute processes here, so they run at the same time as depth pre-pass _post_prepass_render(p_render_data, using_sdfgi || using_voxelgi); @@ -2027,7 +2027,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co bool finish_depth = using_ssao || using_ssil || using_sdfgi || using_voxelgi || ce_pre_opaque_resolved_depth || ce_post_opaque_resolved_depth; RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, depth_pass_mode, 0, rb_data.is_null(), p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count, 0, base_specialization); - _render_list_with_draw_list(&render_list_params, depth_framebuffer, needs_pre_resolve ? RD::INITIAL_ACTION_LOAD : RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, needs_pre_resolve ? RD::INITIAL_ACTION_LOAD : RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, needs_pre_resolve ? Vector() : depth_pass_clear); + _render_list_with_draw_list(&render_list_params, depth_framebuffer, needs_pre_resolve ? RD::CLEAR_COLOR_NONE : RD::CLEAR_COLOR_ALL, needs_pre_resolve ? Vector() : depth_pass_clear, !needs_pre_resolve, 0.0f); RD::get_singleton()->draw_command_end_label(); @@ -2106,7 +2106,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co uint32_t opaque_color_pass_flags = using_motion_pass ? (color_pass_flags & ~COLOR_PASS_FLAG_MOTION_VECTORS) : color_pass_flags; RID opaque_framebuffer = using_motion_pass ? rb_data->get_color_pass_fb(opaque_color_pass_flags) : color_framebuffer; RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, PASS_MODE_COLOR, opaque_color_pass_flags, rb_data.is_null(), p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count, 0, base_specialization); - _render_list_with_draw_list(&render_list_params, opaque_framebuffer, load_color ? RD::INITIAL_ACTION_LOAD : RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, depth_pre_pass ? RD::INITIAL_ACTION_LOAD : RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, c, 0.0, 0); + _render_list_with_draw_list(&render_list_params, opaque_framebuffer, load_color ? RD::CLEAR_COLOR_NONE : RD::CLEAR_COLOR_ALL, c, !depth_pre_pass, 0.0f); } RD::get_singleton()->draw_command_end_label(); @@ -2114,7 +2114,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co if (using_motion_pass) { Vector motion_vector_clear_colors; motion_vector_clear_colors.push_back(Color(-1, -1, 0, 0)); - RD::get_singleton()->draw_list_begin(rb_data->get_velocity_only_fb(), RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, motion_vector_clear_colors); + RD::get_singleton()->draw_list_begin(rb_data->get_velocity_only_fb(), RD::CLEAR_COLOR_ALL, motion_vector_clear_colors); RD::get_singleton()->draw_list_end(); } @@ -2126,7 +2126,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_MOTION, p_render_data, radiance_texture, samplers, true); RenderListParameters render_list_params(render_list[RENDER_LIST_MOTION].elements.ptr(), render_list[RENDER_LIST_MOTION].element_info.ptr(), render_list[RENDER_LIST_MOTION].elements.size(), reverse_cull, PASS_MODE_COLOR, color_pass_flags, rb_data.is_null(), p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count, 0, base_specialization); - _render_list_with_draw_list(&render_list_params, color_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE); + _render_list_with_draw_list(&render_list_params, color_framebuffer); RD::get_singleton()->draw_command_end_label(); } @@ -2153,7 +2153,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co Projection dc; dc.set_depth_correction(true); Projection cm = (dc * p_render_data->scene_data->cam_projection) * Projection(p_render_data->scene_data->cam_transform.affine_inverse()); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(color_only_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(color_only_framebuffer); RD::get_singleton()->draw_command_begin_label("Debug VoxelGIs"); for (int i = 0; i < (int)p_render_data->voxel_gi_instances->size(); i++) { gi.debug_voxel_gi((*p_render_data->voxel_gi_instances)[i], draw_list, color_only_framebuffer, cm, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_VOXEL_GI_LIGHTING, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_VOXEL_GI_EMISSION, 1.0); @@ -2176,7 +2176,7 @@ 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_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(color_only_framebuffer); sky.draw_sky(draw_list, rb, p_render_data->environment, color_only_framebuffer, time, sky_energy_multiplier); @@ -2241,7 +2241,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co RENDER_TIMESTAMP("Clear Separate Specular (Canvas Background Mode)"); Vector blank_clear_color; blank_clear_color.push_back(Color(0.0, 0.0, 0.0)); - RD::get_singleton()->draw_list_begin(rb_data->get_specular_only_fb(), RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_DISCARD, RD::FINAL_ACTION_DISCARD, blank_clear_color); + RD::get_singleton()->draw_list_begin(rb_data->get_specular_only_fb(), RD::CLEAR_COLOR_ALL, blank_clear_color); RD::get_singleton()->draw_list_end(); } @@ -2305,7 +2305,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co RID alpha_framebuffer = rb_data.is_valid() ? rb_data->get_color_pass_fb(transparent_color_pass_flags) : color_only_framebuffer; RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), reverse_cull, PASS_MODE_COLOR, transparent_color_pass_flags, rb_data.is_null(), p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count, 0, base_specialization); - _render_list_with_draw_list(&render_list_params, alpha_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE); + _render_list_with_draw_list(&render_list_params, alpha_framebuffer); } RD::get_singleton()->draw_command_end_label(); @@ -2704,7 +2704,7 @@ void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const Page shadow_pass.lod_distance_multiplier = scene_data.lod_distance_multiplier; shadow_pass.framebuffer = p_framebuffer; - shadow_pass.initial_depth_action = p_begin ? RD::INITIAL_ACTION_CLEAR : (p_clear_region ? RD::INITIAL_ACTION_CLEAR : RD::INITIAL_ACTION_LOAD); + shadow_pass.clear_depth = p_begin || p_clear_region; shadow_pass.rect = p_rect; scene_state.shadow_passes.push_back(shadow_pass); @@ -2728,7 +2728,7 @@ void RenderForwardClustered::_render_shadow_end() { for (SceneState::ShadowPass &shadow_pass : scene_state.shadow_passes) { RenderListParameters render_list_parameters(render_list[RENDER_LIST_SECONDARY].elements.ptr() + shadow_pass.element_from, render_list[RENDER_LIST_SECONDARY].element_info.ptr() + shadow_pass.element_from, shadow_pass.element_count, shadow_pass.flip_cull, shadow_pass.pass_mode, 0, true, false, shadow_pass.rp_uniform_set, false, Vector2(), shadow_pass.lod_distance_multiplier, shadow_pass.screen_mesh_lod_threshold, 1, shadow_pass.element_from); - _render_list_with_draw_list(&render_list_parameters, shadow_pass.framebuffer, RD::INITIAL_ACTION_DISCARD, RD::FINAL_ACTION_DISCARD, shadow_pass.initial_depth_action, RD::FINAL_ACTION_STORE, Vector(), 0.0, 0, shadow_pass.rect); + _render_list_with_draw_list(&render_list_parameters, shadow_pass.framebuffer, RD::CLEAR_COLOR_NONE, Vector(), shadow_pass.clear_depth, 0.0f, false, 0, shadow_pass.rect); } RD::get_singleton()->draw_command_end_label(); @@ -2775,7 +2775,7 @@ void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, con { //regular forward for now RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), false, pass_mode, 0, true, false, rp_uniform_set); - _render_list_with_draw_list(&render_list_params, p_fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE); + _render_list_with_draw_list(&render_list_params, p_fb); } RD::get_singleton()->draw_command_end_label(); } @@ -2829,7 +2829,7 @@ void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform Color(0, 0, 0, 0) }; - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, clear, 0.0, 0, p_region); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::CLEAR_COLOR_ALL, clear, true, 0.0f, false, 0, p_region); _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), &render_list_params, 0, render_list_params.element_count); RD::get_singleton()->draw_list_end(); } @@ -2879,7 +2879,7 @@ void RenderForwardClustered::_render_uv2(const PagedArraydraw_list_begin(p_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, clear, 0.0, 0, p_region); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::CLEAR_COLOR_ALL, clear, true, 0.0f, false, 0, p_region); const int uv_offset_count = 9; static const Vector2 uv_offsets[uv_offset_count] = { @@ -2988,7 +2988,7 @@ void RenderForwardClustered::_render_sdfgi(Ref p_render_bu } RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, 0, true, false, rp_uniform_set, false); - _render_list_with_draw_list(&render_list_params, E->value, RD::INITIAL_ACTION_DISCARD, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_DISCARD, RD::FINAL_ACTION_DISCARD, Vector(), 0.0, 0, Rect2()); + _render_list_with_draw_list(&render_list_params, E->value); } RD::get_singleton()->draw_command_end_label(); 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 ebc291e8031a..f7d37ceddeb7 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h @@ -350,7 +350,6 @@ class RenderForwardClustered : public RendererSceneRenderRD { struct ShadowPass { uint32_t element_from; uint32_t element_count; - bool flip_cull; PassMode pass_mode; RID rp_uniform_set; @@ -358,8 +357,9 @@ class RenderForwardClustered : public RendererSceneRenderRD { float screen_mesh_lod_threshold; RID framebuffer; - RD::InitialAction initial_depth_action; Rect2i rect; + bool clear_depth; + bool flip_cull; }; LocalVector shadow_passes; @@ -385,7 +385,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { template _FORCE_INLINE_ void _render_list_template(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element); void _render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element); - void _render_list_with_draw_list(RenderListParameters *p_params, RID p_framebuffer, RD::InitialAction p_initial_color_action, RD::FinalAction p_final_color_action, RD::InitialAction p_initial_depth_action, RD::FinalAction p_final_depth_action, const Vector &p_clear_color_values = Vector(), float p_clear_depth = 0.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2()); + void _render_list_with_draw_list(RenderListParameters *p_params, RID p_framebuffer, BitField p_clear_colors = RD::CLEAR_COLOR_NONE, const Vector &p_clear_color_values = Vector(), bool p_clear_depth = false, float p_clear_depth_value = 0.0, bool p_clear_stencil = false, uint32_t p_clear_stencil_value = 0, const Rect2 &p_region = Rect2()); void _update_instance_data_buffer(RenderListType p_render_list); void _fill_instance_data(RenderListType p_render_list, int *p_render_info = nullptr, uint32_t p_offset = 0, int32_t p_max_elements = -1, bool p_update_buffer = true); 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 978ce097d34a..bf9f7067487c 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -689,7 +689,7 @@ void RenderForwardMobile::_pre_opaque_render(RenderDataRD *p_render_data) { if (p_render_data->directional_shadows.size()) { //open the pass for directional shadows light_storage->update_directional_shadow_atlas(); - RD::get_singleton()->draw_list_begin(light_storage->direction_shadow_get_fb(), RD::INITIAL_ACTION_DISCARD, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, Vector(), 0.0); + RD::get_singleton()->draw_list_begin(light_storage->direction_shadow_get_fb(), RD::CLEAR_COLOR_NONE, Vector(), true, 0.0f); RD::get_singleton()->draw_list_end(); } } @@ -1057,7 +1057,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color // Set clear colors. Vector c; - { + if (!load_color) { Color cc = clear_color.srgb_to_linear() * inverse_luminance_multiplier; if (rb_data.is_valid()) { cc.a = 0; // For transparent viewport backgrounds. @@ -1074,7 +1074,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color } } - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, load_color ? RD::INITIAL_ACTION_LOAD : RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, c, 0.0, 0, Rect2(), breadcrumb); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::CLEAR_COLOR_ALL, c, true, 0.0f, false, 0, Rect2(), breadcrumb); RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(framebuffer); if (copy_canvas) { @@ -1171,7 +1171,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color render_list_params.framebuffer_format = fb_format; render_list_params.subpass = RD::get_singleton()->draw_list_get_current_pass(); // Should now always be 0. - draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, Vector(), 0, 0, Rect2(), breadcrumb); + draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::CLEAR_COLOR_NONE, Vector(), false, 1.0f, false, 0, Rect2(), breadcrumb); _render_list(draw_list, fb_format, &render_list_params, 0, render_list_params.element_count); RD::get_singleton()->draw_list_end(); @@ -1451,7 +1451,7 @@ void RenderForwardMobile::_render_shadow_append(RID p_framebuffer, const PagedAr shadow_pass.lod_distance_multiplier = scene_data.lod_distance_multiplier; shadow_pass.framebuffer = p_framebuffer; - shadow_pass.initial_depth_action = p_begin ? RD::INITIAL_ACTION_CLEAR : (p_clear_region ? RD::INITIAL_ACTION_CLEAR : RD::INITIAL_ACTION_LOAD); + shadow_pass.clear_depth = p_begin || p_clear_region; shadow_pass.rect = p_rect; scene_state.shadow_passes.push_back(shadow_pass); @@ -1475,7 +1475,7 @@ void RenderForwardMobile::_render_shadow_end() { for (SceneState::ShadowPass &shadow_pass : scene_state.shadow_passes) { RenderListParameters render_list_parameters(render_list[RENDER_LIST_SECONDARY].elements.ptr() + shadow_pass.element_from, render_list[RENDER_LIST_SECONDARY].element_info.ptr() + shadow_pass.element_from, shadow_pass.element_count, shadow_pass.flip_cull, shadow_pass.pass_mode, shadow_pass.rp_uniform_set, scene_shader.default_specialization, false, Vector2(), shadow_pass.lod_distance_multiplier, shadow_pass.screen_mesh_lod_threshold, 1, shadow_pass.element_from); - _render_list_with_draw_list(&render_list_parameters, shadow_pass.framebuffer, RD::INITIAL_ACTION_DISCARD, RD::FINAL_ACTION_DISCARD, shadow_pass.initial_depth_action, RD::FINAL_ACTION_STORE, Vector(), 0.0, 0, shadow_pass.rect); + _render_list_with_draw_list(&render_list_parameters, shadow_pass.framebuffer, RD::CLEAR_COLOR_NONE, Vector(), shadow_pass.clear_depth, 0.0f, false, 0, shadow_pass.rect); } RD::get_singleton()->draw_command_end_label(); @@ -1527,7 +1527,7 @@ void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, c Color(0, 0, 0, 0), Color(0, 0, 0, 0) }; - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, clear, 0.0, 0, p_region); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::CLEAR_COLOR_ALL, clear, true, 0.0f, false, 0, p_region); _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), &render_list_params, 0, render_list_params.element_count); RD::get_singleton()->draw_list_end(); } @@ -1573,7 +1573,7 @@ void RenderForwardMobile::_render_uv2(const PagedArray Color(0, 0, 0, 0) }; - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, clear, 0.0, 0, p_region); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::CLEAR_COLOR_ALL, clear, true, 0.0f, false, 0, p_region); const int uv_offset_count = 9; static const Vector2 uv_offsets[uv_offset_count] = { @@ -1648,7 +1648,7 @@ void RenderForwardMobile::_render_particle_collider_heightfield(RID p_fb, const { //regular forward for now RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), false, pass_mode, rp_uniform_set, scene_shader.default_specialization); - _render_list_with_draw_list(&render_list_params, p_fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE); + _render_list_with_draw_list(&render_list_params, p_fb); } RD::get_singleton()->draw_command_end_label(); } @@ -2096,11 +2096,11 @@ void RenderForwardMobile::_render_list(RenderingDevice::DrawListID p_draw_list, } } -void RenderForwardMobile::_render_list_with_draw_list(RenderListParameters *p_params, RID p_framebuffer, RD::InitialAction p_initial_color_action, RD::FinalAction p_final_color_action, RD::InitialAction p_initial_depth_action, RD::FinalAction p_final_depth_action, const Vector &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region) { +void RenderForwardMobile::_render_list_with_draw_list(RenderListParameters *p_params, RID p_framebuffer, BitField p_clear_colors, const Vector &p_clear_color_values, bool p_clear_depth, float p_clear_depth_value, bool p_clear_stencil, uint32_t p_clear_stencil_value, const Rect2 &p_region) { RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(p_framebuffer); p_params->framebuffer_format = fb_format; - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, p_region); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, p_clear_colors, p_clear_color_values, p_clear_depth, p_clear_depth_value, p_clear_stencil, p_clear_stencil_value, p_region); _render_list(draw_list, fb_format, p_params, 0, p_params->element_count); RD::get_singleton()->draw_list_end(); } 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 96f535ef459b..b6eda5917a23 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h @@ -257,8 +257,8 @@ class RenderForwardMobile : public RendererSceneRenderRD { float screen_mesh_lod_threshold; RID framebuffer; - RD::InitialAction initial_depth_action; Rect2i rect; + bool clear_depth; }; LocalVector shadow_passes; @@ -332,7 +332,7 @@ class RenderForwardMobile : public RendererSceneRenderRD { template _FORCE_INLINE_ void _render_list_template(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element); void _render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element); - void _render_list_with_draw_list(RenderListParameters *p_params, RID p_framebuffer, RD::InitialAction p_initial_color_action, RD::FinalAction p_final_color_action, RD::InitialAction p_initial_depth_action, RD::FinalAction p_final_depth_action, const Vector &p_clear_color_values = Vector(), float p_clear_depth = 0.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2()); + void _render_list_with_draw_list(RenderListParameters *p_params, RID p_framebuffer, BitField p_clear_colors = RD::CLEAR_COLOR_NONE, const Vector &p_clear_color_values = Vector(), bool p_clear_depth = false, float p_clear_depth_value = 0.0, bool p_clear_stencil = false, uint32_t p_clear_stencil_value = 0, const Rect2 &p_region = Rect2()); RenderList render_list[RENDER_LIST_MAX]; diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index c4a732fef17c..373b1ad8a862 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -973,6 +973,7 @@ void RendererCanvasRenderRD::_update_shadow_atlas() { tf.height = state.max_lights_per_render * 2; tf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; tf.format = RD::DATA_FORMAT_D32_SFLOAT; + tf.is_transient = true; //chunks to write state.shadow_depth_texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); fb_textures.push_back(state.shadow_depth_texture); @@ -999,7 +1000,7 @@ void RendererCanvasRenderRD::light_update_shadow(RID p_rid, int p_shadow_index, //light.basis.scale(Vector3(to_light.elements[0].length(),to_light.elements[1].length(),1)); Rect2i rect((state.shadow_texture_size / 4) * i, p_shadow_index * 2, (state.shadow_texture_size / 4), 2); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(state.shadow_fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, cc, 1.0, 0, rect); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(state.shadow_fb, RD::CLEAR_COLOR_ALL, cc, true, 1.0f, false, 0, rect); Projection projection; { @@ -1088,7 +1089,7 @@ void RendererCanvasRenderRD::light_update_directional_shadow(RID p_rid, int p_sh cc.push_back(Color(1, 1, 1, 1)); Rect2i rect(0, p_shadow_index * 2, state.shadow_texture_size, 2); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(state.shadow_fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, cc, 1.0, 0, rect); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(state.shadow_fb, RD::CLEAR_COLOR_ALL, cc, true, 1.0f, false, 0, rect); Projection projection; projection.set_orthogonal(-half_size, half_size, -0.5, 0.5, 0.0, distance); @@ -1158,7 +1159,7 @@ void RendererCanvasRenderRD::render_sdf(RID p_render_target, LightOccluderInstan Vector cc; cc.push_back(Color(0, 0, 0, 0)); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, cc); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(fb, RD::CLEAR_COLOR_ALL, cc); Projection projection; @@ -2165,7 +2166,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, 1, 0, Rect2(), RDD::BreadcrumbMarker::UI_PASS); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, clear ? RD::CLEAR_COLOR_ALL : RD::CLEAR_COLOR_NONE, clear_colors, false, 1.0f, false, 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); diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index dc2605b670d8..84310dfd6e02 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -646,7 +646,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende if (use_intermediate_fb) { // If we use FSR to upscale we need to write our result into an intermediate buffer. // Note that this is cached so we only create the texture the first time. - RID dest_texture = rb->create_texture(SNAME("Tonemapper"), SNAME("destination"), _render_buffers_get_color_format(), RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT); + RID dest_texture = rb->create_texture(SNAME("Tonemapper"), SNAME("destination"), _render_buffers_get_color_format(), RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT, RD::TEXTURE_SAMPLES_1, Size2i(), 0, 1, true, true); dest_fb = FramebufferCacheRD::get_singleton()->get_cache(dest_texture); } else { // If we do a bilinear upscale we just render into our render target and our shader will upscale automatically. diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.compat.inc b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.compat.inc index 75b9ee2da74e..719765e7b30e 100644 --- a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.compat.inc +++ b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.compat.inc @@ -54,6 +54,10 @@ RID RenderSceneBuffersRD::_get_velocity_layer_compat_80214(const uint32_t p_laye return _get_velocity_layer(p_layer, msaa_3d != RS::VIEWPORT_MSAA_DISABLED); } +RID RenderSceneBuffersRD::_create_texture_98670(const StringName &p_context, const StringName &p_texture_name, const RD::DataFormat p_data_format, const uint32_t p_usage_bits, const RD::TextureSamples p_texture_samples, const Size2i p_size, const uint32_t p_layers, const uint32_t p_mipmaps, bool p_unique) { + return create_texture(p_context, p_texture_name, p_data_format, p_usage_bits, p_texture_samples, p_size, p_layers, p_mipmaps, p_unique, false); +} + void RenderSceneBuffersRD::_bind_compatibility_methods() { ClassDB::bind_compatibility_method(D_METHOD("get_color_texture"), &RenderSceneBuffersRD::_get_color_texture_compat_80214); ClassDB::bind_compatibility_method(D_METHOD("get_color_layer", "layer"), &RenderSceneBuffersRD::_get_color_layer_compat_80214); @@ -61,6 +65,8 @@ void RenderSceneBuffersRD::_bind_compatibility_methods() { ClassDB::bind_compatibility_method(D_METHOD("get_depth_layer", "layer"), &RenderSceneBuffersRD::_get_depth_layer_compat_80214); ClassDB::bind_compatibility_method(D_METHOD("get_velocity_texture"), &RenderSceneBuffersRD::_get_velocity_texture_compat_80214); ClassDB::bind_compatibility_method(D_METHOD("get_velocity_layer", "layer"), &RenderSceneBuffersRD::_get_velocity_layer_compat_80214); + + ClassDB::bind_compatibility_method(D_METHOD("create_texture", "context", "name", "data_format", "usage_bits", "texture_samples", "size", "layers", "mipmaps", "unique"), &RenderSceneBuffersRD::_create_texture_98670); } #endif // DISABLE_DEPRECATED 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 ca44f4dd7ed5..9759ae8a7ada 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 @@ -48,7 +48,7 @@ RenderSceneBuffersRD::~RenderSceneBuffersRD() { void RenderSceneBuffersRD::_bind_methods() { ClassDB::bind_method(D_METHOD("has_texture", "context", "name"), &RenderSceneBuffersRD::has_texture); - ClassDB::bind_method(D_METHOD("create_texture", "context", "name", "data_format", "usage_bits", "texture_samples", "size", "layers", "mipmaps", "unique"), &RenderSceneBuffersRD::create_texture); + ClassDB::bind_method(D_METHOD("create_texture", "context", "name", "data_format", "usage_bits", "texture_samples", "size", "layers", "mipmaps", "unique", "transient"), &RenderSceneBuffersRD::create_texture); ClassDB::bind_method(D_METHOD("create_texture_from_format", "context", "name", "format", "view", "unique"), &RenderSceneBuffersRD::_create_texture_from_format); ClassDB::bind_method(D_METHOD("create_texture_view", "context", "name", "view_name", "view"), &RenderSceneBuffersRD::_create_texture_view); ClassDB::bind_method(D_METHOD("get_texture", "context", "name"), &RenderSceneBuffersRD::get_texture); @@ -179,8 +179,8 @@ void RenderSceneBuffersRD::configure(const RenderSceneBuffersConfiguration *p_co texture_samples = RD::TEXTURE_SAMPLES_1; } else { texture_samples = msaa_to_samples(msaa_3d); - create_texture(RB_SCOPE_BUFFERS, RB_TEX_COLOR_MSAA, base_data_format, get_color_usage_bits(false, true, can_be_storage), texture_samples); - create_texture(RB_SCOPE_BUFFERS, RB_TEX_DEPTH_MSAA, get_depth_format(false, true, can_be_storage), get_depth_usage_bits(false, true, can_be_storage), texture_samples); + create_texture(RB_SCOPE_BUFFERS, RB_TEX_COLOR_MSAA, base_data_format, get_color_usage_bits(false, true, can_be_storage), texture_samples, Size2i(), 0, 1, true, true); + create_texture(RB_SCOPE_BUFFERS, RB_TEX_DEPTH_MSAA, get_depth_format(false, true, can_be_storage), get_depth_usage_bits(false, true, can_be_storage), texture_samples, Size2i(), 0, 1, true, true); } // VRS (note, our vrs object will only be set if VRS is supported) @@ -242,7 +242,7 @@ bool RenderSceneBuffersRD::has_texture(const StringName &p_context, const String return named_textures.has(key); } -RID RenderSceneBuffersRD::create_texture(const StringName &p_context, const StringName &p_texture_name, const RD::DataFormat p_data_format, const uint32_t p_usage_bits, const RD::TextureSamples p_texture_samples, const Size2i p_size, const uint32_t p_layers, const uint32_t p_mipmaps, bool p_unique) { +RID RenderSceneBuffersRD::create_texture(const StringName &p_context, const StringName &p_texture_name, const RD::DataFormat p_data_format, const uint32_t p_usage_bits, const RD::TextureSamples p_texture_samples, const Size2i p_size, const uint32_t p_layers, const uint32_t p_mipmaps, bool p_unique, bool p_transient) { // Keep some useful data, we use default values when these are 0. Size2i size = p_size == Size2i(0, 0) ? internal_size : p_size; uint32_t layers = p_layers == 0 ? view_count : p_layers; @@ -262,6 +262,7 @@ RID RenderSceneBuffersRD::create_texture(const StringName &p_context, const Stri tf.mipmaps = mipmaps; tf.usage_bits = p_usage_bits; tf.samples = p_texture_samples; + tf.is_transient = p_transient; return create_texture_from_format(p_context, p_texture_name, tf, RD::TextureView(), p_unique); } 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 187dbab44509..ad6d2f20ff14 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 @@ -195,7 +195,7 @@ class RenderSceneBuffersRD : public RenderSceneBuffers { // Named Textures bool has_texture(const StringName &p_context, const StringName &p_texture_name) const; - RID create_texture(const StringName &p_context, const StringName &p_texture_name, const RD::DataFormat p_data_format, const uint32_t p_usage_bits, const RD::TextureSamples p_texture_samples = RD::TEXTURE_SAMPLES_1, const Size2i p_size = Size2i(0, 0), const uint32_t p_layers = 0, const uint32_t p_mipmaps = 1, bool p_unique = true); + RID create_texture(const StringName &p_context, const StringName &p_texture_name, const RD::DataFormat p_data_format, const uint32_t p_usage_bits, const RD::TextureSamples p_texture_samples = RD::TEXTURE_SAMPLES_1, const Size2i p_size = Size2i(0, 0), const uint32_t p_layers = 0, const uint32_t p_mipmaps = 1, bool p_unique = true, bool p_transient = false); RID create_texture_from_format(const StringName &p_context, const StringName &p_texture_name, const RD::TextureFormat &p_texture_format, RD::TextureView p_view = RD::TextureView(), bool p_unique = true); RID create_texture_view(const StringName &p_context, const StringName &p_texture_name, const StringName &p_view_name, RD::TextureView p_view = RD::TextureView()); RID get_texture(const StringName &p_context, const StringName &p_texture_name) const; @@ -423,6 +423,8 @@ class RenderSceneBuffersRD : public RenderSceneBuffers { RID _get_velocity_texture_compat_80214(); RID _get_velocity_layer_compat_80214(const uint32_t p_layer); + RID _create_texture_98670(const StringName &p_context, const StringName &p_texture_name, const RD::DataFormat p_data_format, const uint32_t p_usage_bits, const RD::TextureSamples p_texture_samples, const Size2i p_size, const uint32_t p_layers, const uint32_t p_mipmaps, bool p_unique); + static void _bind_compatibility_methods(); #endif // DISABLE_DEPRECATED diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp index 42fce65b2d22..03dadf35c579 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp @@ -2892,7 +2892,7 @@ void TextureStorage::update_decal_atlas() { Vector cc; cc.push_back(clear_color); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(mm.fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_DISCARD, RD::FINAL_ACTION_DISCARD, cc); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(mm.fb, RD::CLEAR_COLOR_ALL, cc); for (const KeyValue &E : decal_atlas.textures) { DecalAtlas::Texture *t = decal_atlas.textures.getptr(E.key); @@ -3573,7 +3573,7 @@ void TextureStorage::render_target_do_msaa_resolve(RID p_render_target) { if (!rt->msaa_needs_resolve) { return; } - RD::get_singleton()->draw_list_begin(rt->get_framebuffer(), RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD); + RD::get_singleton()->draw_list_begin(rt->get_framebuffer()); RD::get_singleton()->draw_list_end(); rt->msaa_needs_resolve = false; } @@ -3690,7 +3690,7 @@ void TextureStorage::render_target_do_clear_request(RID p_render_target) { } Vector clear_colors; clear_colors.push_back(rt->use_hdr ? rt->clear_color.srgb_to_linear() : rt->clear_color); - RD::get_singleton()->draw_list_begin(rt->get_framebuffer(), RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD, clear_colors); + RD::get_singleton()->draw_list_begin(rt->get_framebuffer(), RD::CLEAR_COLOR_ALL, clear_colors); RD::get_singleton()->draw_list_end(); rt->clear_requested = false; rt->msaa_needs_resolve = false; diff --git a/servers/rendering/rendering_device.compat.inc b/servers/rendering/rendering_device.compat.inc index 77e44bbc5efb..b86ed1d698b3 100644 --- a/servers/rendering/rendering_device.compat.inc +++ b/servers/rendering/rendering_device.compat.inc @@ -86,11 +86,18 @@ RenderingDevice::FinalAction RenderingDevice::_convert_final_action_84976(FinalA } RenderingDevice::DrawListID RenderingDevice::_draw_list_begin_bind_compat_84976(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region, const TypedArray &p_storage_textures) { - return draw_list_begin(p_framebuffer, _convert_initial_action_84976(p_initial_color_action), _convert_final_action_84976(p_final_color_action), _convert_initial_action_84976(p_initial_depth_action), _convert_final_action_84976(p_final_depth_action), p_clear_color_values, p_clear_depth, p_clear_stencil, p_region, RDD::BreadcrumbMarker::NONE); + return _draw_list_begin_bind_compat_98670(p_framebuffer, _convert_initial_action_84976(p_initial_color_action), _convert_final_action_84976(p_final_color_action), _convert_initial_action_84976(p_initial_depth_action), _convert_final_action_84976(p_final_depth_action), p_clear_color_values, p_clear_depth, p_clear_stencil, p_region, RDD::BreadcrumbMarker::NONE); } RenderingDevice::DrawListID RenderingDevice::_draw_list_begin_bind_compat_90993(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region) { - return draw_list_begin(p_framebuffer, p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, p_region, RDD::BreadcrumbMarker::NONE); + return _draw_list_begin_bind_compat_98670(p_framebuffer, p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, p_region, RDD::BreadcrumbMarker::NONE); +} + +RenderingDevice::DrawListID RenderingDevice::_draw_list_begin_bind_compat_98670(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region, uint32_t p_breadcrumb) { + BitField clear_colors = p_initial_color_action == RD::INITIAL_ACTION_CLEAR ? RD::CLEAR_COLOR_ALL : RD::CLEAR_COLOR_NONE; + bool clear_depth = p_initial_depth_action == RD::INITIAL_ACTION_CLEAR; + bool clear_stencil = p_initial_depth_action == RD::INITIAL_ACTION_CLEAR; + return draw_list_begin(p_framebuffer, clear_colors, p_clear_color_values, clear_depth, p_clear_depth, clear_stencil, p_clear_stencil, p_region, p_breadcrumb); } RenderingDevice::ComputeListID RenderingDevice::_compute_list_begin_bind_compat_84976(bool p_allow_draw_overlap) { @@ -146,6 +153,8 @@ void RenderingDevice::_bind_compatibility_methods() { ClassDB::bind_compatibility_method(D_METHOD("screen_get_framebuffer_format"), &RenderingDevice::_screen_get_framebuffer_format_bind_compat_87340); ClassDB::bind_compatibility_method(D_METHOD("draw_list_begin", "framebuffer", "initial_color_action", "final_color_action", "initial_depth_action", "final_depth_action", "clear_color_values", "clear_depth", "clear_stencil", "region"), &RenderingDevice::_draw_list_begin_bind_compat_90993, DEFVAL(Vector()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2())); + + ClassDB::bind_compatibility_method(D_METHOD("draw_list_begin", "framebuffer", "initial_color_action", "final_color_action", "initial_depth_action", "final_depth_action", "clear_color_values", "clear_depth", "clear_stencil", "region", "breadcrumb"), &RenderingDevice::_draw_list_begin_bind_compat_98670, DEFVAL(Vector()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2()), DEFVAL(0)); } #endif diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp index dc5a178aaa15..272496d141ff 100644 --- a/servers/rendering/rendering_device.cpp +++ b/servers/rendering/rendering_device.cpp @@ -846,6 +846,7 @@ RID RenderingDevice::texture_create(const TextureFormat &p_format, const Texture texture.base_mipmap = 0; texture.base_layer = 0; texture.is_resolve_buffer = format.is_resolve_buffer; + texture.is_transient = format.is_transient; texture.usage_flags = format.usage_bits & ~forced_usage_bits; texture.samples = format.samples; texture.allowed_shared_formats = format.shareable_formats; @@ -948,6 +949,7 @@ RID RenderingDevice::texture_create_shared(const TextureView &p_view, RID p_with tracker->texture_driver_id = texture.shared_fallback->texture; tracker->texture_subresources = texture.barrier_range(); tracker->texture_usage = alias_format.usage_bits; + tracker->is_transient = texture.is_transient; tracker->reference_count = 1; texture.shared_fallback->texture_tracker = tracker; texture.shared_fallback->revision = 0; @@ -1127,6 +1129,7 @@ RID RenderingDevice::texture_create_shared_from_slice(const TextureView &p_view, tracker->texture_driver_id = texture.shared_fallback->texture; tracker->texture_subresources = slice_range; tracker->texture_usage = slice_format.usage_bits; + tracker->is_transient = slice_format.is_transient; tracker->reference_count = 1; texture.shared_fallback->texture_tracker = tracker; texture.shared_fallback->revision = 0; @@ -1887,6 +1890,7 @@ RD::TextureFormat RenderingDevice::texture_get_format(RID p_texture) { tf.usage_bits = tex->usage_flags; tf.shareable_formats = tex->allowed_shared_formats; tf.is_resolve_buffer = tex->is_resolve_buffer; + tf.is_transient = tex->is_transient; return tf; } @@ -2027,6 +2031,32 @@ Error RenderingDevice::texture_resolve_multisample(RID p_from_texture, RID p_to_ return OK; } +void RenderingDevice::texture_set_transient(RID p_texture, bool p_transient) { + ERR_RENDER_THREAD_GUARD(); + + Texture *texture = texture_owner.get_or_null(p_texture); + ERR_FAIL_NULL(texture); + + texture->is_transient = p_transient; + + if (texture->draw_tracker != nullptr) { + texture->draw_tracker->is_transient = p_transient; + } + + if (texture->shared_fallback != nullptr && texture->shared_fallback->texture_tracker != nullptr) { + texture->shared_fallback->texture_tracker->is_transient = p_transient; + } +} + +bool RenderingDevice::texture_is_transient(RID p_texture) { + ERR_RENDER_THREAD_GUARD_V(false); + + Texture *texture = texture_owner.get_or_null(p_texture); + ERR_FAIL_NULL_V(texture, false); + + return texture->is_transient; +} + Error RenderingDevice::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) { ERR_RENDER_THREAD_GUARD_V(ERR_UNAVAILABLE); @@ -2080,31 +2110,7 @@ bool RenderingDevice::texture_is_format_supported_for_usage(DataFormat p_format, /**** FRAMEBUFFER ****/ /*********************/ -static RDD::AttachmentLoadOp initial_action_to_load_op(RenderingDevice::InitialAction p_action) { - switch (p_action) { - case RenderingDevice::INITIAL_ACTION_LOAD: - return RDD::ATTACHMENT_LOAD_OP_LOAD; - case RenderingDevice::INITIAL_ACTION_CLEAR: - return RDD::ATTACHMENT_LOAD_OP_CLEAR; - case RenderingDevice::INITIAL_ACTION_DISCARD: - return RDD::ATTACHMENT_LOAD_OP_DONT_CARE; - default: - ERR_FAIL_V_MSG(RDD::ATTACHMENT_LOAD_OP_DONT_CARE, "Invalid initial action value (" + itos(p_action) + ")"); - } -} - -static RDD::AttachmentStoreOp final_action_to_store_op(RenderingDevice::FinalAction p_action) { - switch (p_action) { - case RenderingDevice::FINAL_ACTION_STORE: - return RDD::ATTACHMENT_STORE_OP_STORE; - case RenderingDevice::FINAL_ACTION_DISCARD: - return RDD::ATTACHMENT_STORE_OP_DONT_CARE; - default: - ERR_FAIL_V_MSG(RDD::ATTACHMENT_STORE_OP_DONT_CARE, "Invalid final action value (" + itos(p_action) + ")"); - } -} - -RDD::RenderPassID RenderingDevice::_render_pass_create(const Vector &p_attachments, const Vector &p_passes, InitialAction p_initial_action, FinalAction p_final_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, uint32_t p_view_count, Vector *r_samples) { +RDD::RenderPassID RenderingDevice::_render_pass_create(RenderingDeviceDriver *p_driver, const Vector &p_attachments, const Vector &p_passes, VectorView p_load_ops, VectorView p_store_ops, uint32_t p_view_count, Vector *r_samples) { // NOTE: // Before the refactor to RenderingDevice-RenderingDeviceDriver, there was commented out code to // specify dependencies to external subpasses. Since it had been unused for a long timel it wasn't ported @@ -2114,7 +2120,7 @@ RDD::RenderPassID RenderingDevice::_render_pass_create(const Vector 1) { - const RDD::MultiviewCapabilities &capabilities = driver->get_multiview_capabilities(); + const RDD::MultiviewCapabilities &capabilities = p_driver->get_multiview_capabilities(); // This only works with multiview! ERR_FAIL_COND_V_MSG(!capabilities.is_supported, RDD::RenderPassID(), "Multiview not supported"); @@ -2155,17 +2161,17 @@ RDD::RenderPassID RenderingDevice::_render_pass_create(const Vectorrender_pass_create(attachments, subpasses, subpass_dependencies, p_view_count); + RDD::RenderPassID render_pass = p_driver->render_pass_create(attachments, subpasses, subpass_dependencies, p_view_count); ERR_FAIL_COND_V(!render_pass, RDD::RenderPassID()); return render_pass; } +RDD::RenderPassID RenderingDevice::_render_pass_create_from_graph(RenderingDeviceDriver *p_driver, VectorView p_load_ops, VectorView p_store_ops, void *p_user_data) { + DEV_ASSERT(p_driver != nullptr); + DEV_ASSERT(p_user_data != nullptr); + + // The graph delegates the creation of the render pass to the user according to the load and store ops that were determined as necessary after + // resolving the dependencies between commands. This function creates a render pass for the framebuffer accordingly. + Framebuffer *framebuffer = (Framebuffer *)(p_user_data); + const FramebufferFormatKey &key = framebuffer->rendering_device->framebuffer_formats[framebuffer->format_id].E->key(); + return _render_pass_create(p_driver, key.attachments, key.passes, p_load_ops, p_store_ops, framebuffer->view_count); +} + RenderingDevice::FramebufferFormatID RenderingDevice::framebuffer_format_create(const Vector &p_format, uint32_t p_view_count) { FramebufferPass pass; for (int i = 0; i < p_format.size(); i++) { @@ -2347,6 +2364,7 @@ RenderingDevice::FramebufferFormatID RenderingDevice::framebuffer_format_create( passes.push_back(pass); return framebuffer_format_create_multipass(p_format, passes, p_view_count); } + RenderingDevice::FramebufferFormatID RenderingDevice::framebuffer_format_create_multipass(const Vector &p_attachments, const Vector &p_passes, uint32_t p_view_count) { _THREAD_SAFE_METHOD_ @@ -2362,14 +2380,21 @@ RenderingDevice::FramebufferFormatID RenderingDevice::framebuffer_format_create_ } Vector samples; - RDD::RenderPassID render_pass = _render_pass_create(p_attachments, p_passes, INITIAL_ACTION_CLEAR, FINAL_ACTION_STORE, INITIAL_ACTION_CLEAR, FINAL_ACTION_STORE, p_view_count, &samples); // Actions don't matter for this use case. + LocalVector load_ops; + LocalVector store_ops; + for (int64_t i = 0; i < p_attachments.size(); i++) { + load_ops.push_back(RDD::ATTACHMENT_LOAD_OP_CLEAR); + store_ops.push_back(RDD::ATTACHMENT_STORE_OP_STORE); + } + RDD::RenderPassID render_pass = _render_pass_create(driver, p_attachments, p_passes, load_ops, store_ops, p_view_count, &samples); // Actions don't matter for this use case. if (!render_pass) { // Was likely invalid. return INVALID_ID; } - FramebufferFormatID id = FramebufferFormatID(framebuffer_format_cache.size()) | (FramebufferFormatID(ID_TYPE_FRAMEBUFFER_FORMAT) << FramebufferFormatID(ID_BASE_SHIFT)); + FramebufferFormatID id = FramebufferFormatID(framebuffer_format_cache.size()) | (FramebufferFormatID(ID_TYPE_FRAMEBUFFER_FORMAT) << FramebufferFormatID(ID_BASE_SHIFT)); E = framebuffer_format_cache.insert(key, id); + FramebufferFormat fb_format; fb_format.E = E; fb_format.render_pass = render_pass; @@ -2436,15 +2461,24 @@ RID RenderingDevice::framebuffer_create_empty(const Size2i &p_size, TextureSampl _THREAD_SAFE_METHOD_ Framebuffer framebuffer; + framebuffer.rendering_device = this; framebuffer.format_id = framebuffer_format_create_empty(p_samples); ERR_FAIL_COND_V(p_format_check != INVALID_FORMAT_ID && framebuffer.format_id != p_format_check, RID()); framebuffer.size = p_size; framebuffer.view_count = 1; + RDG::FramebufferCache *framebuffer_cache = RDG::framebuffer_cache_create(); + framebuffer_cache->width = p_size.width; + framebuffer_cache->height = p_size.height; + framebuffer.framebuffer_cache = framebuffer_cache; + RID id = framebuffer_owner.make_rid(framebuffer); #ifdef DEV_ENABLED set_resource_name(id, "RID:" + itos(id.get_id())); #endif + + framebuffer_cache->render_pass_creation_user_data = framebuffer_owner.get_or_null(id); + return id; } @@ -2485,6 +2519,8 @@ RID RenderingDevice::framebuffer_create_multipass(const Vector &p_texture_a _THREAD_SAFE_METHOD_ Vector attachments; + LocalVector textures; + LocalVector trackers; attachments.resize(p_texture_attachments.size()); Size2i size; bool size_set = false; @@ -2493,6 +2529,7 @@ RID RenderingDevice::framebuffer_create_multipass(const Vector &p_texture_a Texture *texture = texture_owner.get_or_null(p_texture_attachments[i]); if (!texture) { af.usage_flags = AttachmentFormat::UNUSED_ATTACHMENT; + trackers.push_back(nullptr); } else { ERR_FAIL_COND_V_MSG(texture->layers != p_view_count, RID(), "Layers of our texture doesn't match view count for this framebuffer"); @@ -2514,6 +2551,11 @@ RID RenderingDevice::framebuffer_create_multipass(const Vector &p_texture_a af.format = texture->format; af.samples = texture->samples; af.usage_flags = texture->usage_flags; + + _texture_make_mutable(texture, p_texture_attachments[i]); + + textures.push_back(texture->driver_id); + trackers.push_back(texture->draw_tracker); } attachments.write[i] = af; } @@ -2529,11 +2571,19 @@ RID RenderingDevice::framebuffer_create_multipass(const Vector &p_texture_a "The format used to check this framebuffer differs from the intended framebuffer format."); Framebuffer framebuffer; + framebuffer.rendering_device = this; framebuffer.format_id = format_id; framebuffer.texture_ids = p_texture_attachments; framebuffer.size = size; framebuffer.view_count = p_view_count; + RDG::FramebufferCache *framebuffer_cache = RDG::framebuffer_cache_create(); + framebuffer_cache->width = size.width; + framebuffer_cache->height = size.height; + framebuffer_cache->textures = textures; + framebuffer_cache->trackers = trackers; + framebuffer.framebuffer_cache = framebuffer_cache; + RID id = framebuffer_owner.make_rid(framebuffer); #ifdef DEV_ENABLED set_resource_name(id, "RID:" + itos(id.get_id())); @@ -2545,6 +2595,8 @@ RID RenderingDevice::framebuffer_create_multipass(const Vector &p_texture_a } } + framebuffer_cache->render_pass_creation_user_data = framebuffer_owner.get_or_null(id); + return id; } @@ -3822,7 +3874,7 @@ RenderingDevice::DrawListID RenderingDevice::draw_list_begin_for_screen(DisplayS clear_value.color = p_clear_color; RDD::RenderPassID render_pass = driver->swap_chain_get_render_pass(sc_it->value); - draw_graph.add_draw_list_begin(render_pass, fb_it->value, viewport, clear_value, true, false, RDD::BreadcrumbMarker::BLIT_PASS); + draw_graph.add_draw_list_begin(render_pass, fb_it->value, viewport, true, clear_value, true, false, RDD::BreadcrumbMarker::BLIT_PASS); draw_graph.add_draw_list_set_viewport(viewport); draw_graph.add_draw_list_set_scissor(viewport); @@ -3830,150 +3882,7 @@ RenderingDevice::DrawListID RenderingDevice::draw_list_begin_for_screen(DisplayS return int64_t(ID_TYPE_DRAW_LIST) << ID_BASE_SHIFT; } -Error RenderingDevice::_draw_list_setup_framebuffer(Framebuffer *p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, RDD::FramebufferID *r_framebuffer, RDD::RenderPassID *r_render_pass, uint32_t *r_subpass_count) { - Framebuffer::VersionKey vk; - vk.initial_color_action = p_initial_color_action; - vk.final_color_action = p_final_color_action; - vk.initial_depth_action = p_initial_depth_action; - vk.final_depth_action = p_final_depth_action; - vk.view_count = p_framebuffer->view_count; - - if (!p_framebuffer->framebuffers.has(vk)) { - // Need to create this version. - Framebuffer::Version version; - - version.render_pass = _render_pass_create(framebuffer_formats[p_framebuffer->format_id].E->key().attachments, framebuffer_formats[p_framebuffer->format_id].E->key().passes, p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_framebuffer->view_count); - - LocalVector attachments; - for (int i = 0; i < p_framebuffer->texture_ids.size(); i++) { - Texture *texture = texture_owner.get_or_null(p_framebuffer->texture_ids[i]); - if (texture) { - attachments.push_back(texture->driver_id); - if (!(texture->usage_flags & TEXTURE_USAGE_VRS_ATTACHMENT_BIT)) { // VRS attachment will be a different size. - ERR_FAIL_COND_V(texture->width != p_framebuffer->size.width, ERR_BUG); - ERR_FAIL_COND_V(texture->height != p_framebuffer->size.height, ERR_BUG); - } - } - } - - version.framebuffer = driver->framebuffer_create(version.render_pass, attachments, p_framebuffer->size.width, p_framebuffer->size.height); - ERR_FAIL_COND_V(!version.framebuffer, ERR_CANT_CREATE); - - version.subpass_count = framebuffer_formats[p_framebuffer->format_id].E->key().passes.size(); - - p_framebuffer->framebuffers.insert(vk, version); - } - const Framebuffer::Version &version = p_framebuffer->framebuffers[vk]; - *r_framebuffer = version.framebuffer; - *r_render_pass = version.render_pass; - *r_subpass_count = version.subpass_count; - - return OK; -} - -Error RenderingDevice::_draw_list_render_pass_begin(Framebuffer *p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector &p_clear_colors, float p_clear_depth, uint32_t p_clear_stencil, Point2i p_viewport_offset, Point2i p_viewport_size, RDD::FramebufferID p_framebuffer_driver_id, RDD::RenderPassID p_render_pass, uint32_t p_breadcrumb) { - thread_local LocalVector clear_values; - thread_local LocalVector resource_trackers; - thread_local LocalVector resource_usages; - bool uses_color = false; - bool uses_depth = false; - clear_values.clear(); - clear_values.resize(p_framebuffer->texture_ids.size()); - resource_trackers.clear(); - resource_usages.clear(); - int clear_values_count = 0; - { - int color_index = 0; - for (int i = 0; i < p_framebuffer->texture_ids.size(); i++) { - RDD::RenderPassClearValue clear_value; - - RID texture_rid = p_framebuffer->texture_ids[i]; - Texture *texture = texture_owner.get_or_null(texture_rid); - if (!texture) { - color_index++; - continue; - } - - // Indicate the texture will get modified for the shared texture fallback. - _texture_update_shared_fallback(texture_rid, texture, true); - - if (texture->usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) { - if (color_index < p_clear_colors.size()) { - ERR_FAIL_INDEX_V(color_index, p_clear_colors.size(), ERR_BUG); // A bug. - clear_value.color = p_clear_colors[color_index]; - color_index++; - } - - resource_trackers.push_back(texture->draw_tracker); - resource_usages.push_back(RDG::RESOURCE_USAGE_ATTACHMENT_COLOR_READ_WRITE); - uses_color = true; - } else if (texture->usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { - clear_value.depth = p_clear_depth; - clear_value.stencil = p_clear_stencil; - resource_trackers.push_back(texture->draw_tracker); - resource_usages.push_back(RDG::RESOURCE_USAGE_ATTACHMENT_DEPTH_STENCIL_READ_WRITE); - uses_depth = true; - } - - clear_values[clear_values_count++] = clear_value; - } - } - - draw_graph.add_draw_list_begin(p_render_pass, p_framebuffer_driver_id, Rect2i(p_viewport_offset, p_viewport_size), clear_values, uses_color, uses_depth, p_breadcrumb); - draw_graph.add_draw_list_usages(resource_trackers, resource_usages); - - // Mark textures as bound. - draw_list_bound_textures.clear(); - - for (int i = 0; i < p_framebuffer->texture_ids.size(); i++) { - Texture *texture = texture_owner.get_or_null(p_framebuffer->texture_ids[i]); - if (!texture) { - continue; - } - texture->bound = true; - draw_list_bound_textures.push_back(p_framebuffer->texture_ids[i]); - } - - return OK; -} - -void RenderingDevice::_draw_list_insert_clear_region(DrawList *p_draw_list, Framebuffer *p_framebuffer, Point2i p_viewport_offset, Point2i p_viewport_size, bool p_clear_color, const Vector &p_clear_colors, bool p_clear_depth, float p_depth, uint32_t p_stencil) { - LocalVector clear_attachments; - int color_index = 0; - int texture_index = 0; - for (int i = 0; i < p_framebuffer->texture_ids.size(); i++) { - Texture *texture = texture_owner.get_or_null(p_framebuffer->texture_ids[i]); - - if (!texture) { - texture_index++; - continue; - } - - RDD::AttachmentClear clear_at; - if (p_clear_color && (texture->usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT)) { - Color clear_color = p_clear_colors[texture_index++]; - clear_at.value.color = clear_color; - clear_at.color_attachment = color_index++; - clear_at.aspect = RDD::TEXTURE_ASPECT_COLOR_BIT; - } else if (p_clear_depth && (texture->usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) { - clear_at.value.depth = p_depth; - clear_at.value.stencil = p_stencil; - clear_at.color_attachment = 0; - clear_at.aspect = RDD::TEXTURE_ASPECT_DEPTH_BIT; - if (format_has_stencil(texture->format)) { - clear_at.aspect.set_flag(RDD::TEXTURE_ASPECT_STENCIL_BIT); - } - } else { - ERR_CONTINUE(true); - } - clear_attachments.push_back(clear_at); - } - - Rect2i rect = Rect2i(p_viewport_offset, p_viewport_size); - draw_graph.add_draw_list_clear_attachments(clear_attachments, rect); -} - -RenderingDevice::DrawListID RenderingDevice::draw_list_begin(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region, uint32_t p_breadcrumb) { +RenderingDevice::DrawListID RenderingDevice::draw_list_begin(RID p_framebuffer, BitField p_clear_colors, const Vector &p_clear_color_values, bool p_clear_depth, float p_clear_depth_value, bool p_clear_stencil, uint32_t p_clear_stencil_value, const Rect2 &p_region, uint32_t p_breadcrumb) { ERR_RENDER_THREAD_GUARD_V(INVALID_ID); ERR_FAIL_COND_V_MSG(draw_list != nullptr, INVALID_ID, "Only one draw list can be active at the same time."); @@ -3997,43 +3906,83 @@ RenderingDevice::DrawListID RenderingDevice::draw_list_begin(RID p_framebuffer, viewport_size = regioni.size; } - if (p_initial_color_action == INITIAL_ACTION_CLEAR) { // Check clear values. - int color_count = 0; - for (int i = 0; i < framebuffer->texture_ids.size(); i++) { - Texture *texture = texture_owner.get_or_null(framebuffer->texture_ids[i]); - // We only check for our VRS usage bit if this is not the first texture id. - // If it is the first we're likely populating our VRS texture. - // Bit dirty but... - if (!texture || (!(texture->usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) && !(i != 0 && texture->usage_flags & TEXTURE_USAGE_VRS_ATTACHMENT_BIT))) { - if (!texture || !texture->is_resolve_buffer) { - color_count++; - } + thread_local LocalVector clears; + thread_local LocalVector clear_values; + thread_local LocalVector resource_trackers; + thread_local LocalVector resource_usages; + bool uses_color = false; + bool uses_depth = false; + clears.resize(framebuffer->texture_ids.size()); + clear_values.resize(framebuffer->texture_ids.size()); + resource_trackers.clear(); + resource_usages.clear(); + + uint32_t color_index = 0; + for (int i = 0; i < framebuffer->texture_ids.size(); i++) { + RID texture_rid = framebuffer->texture_ids[i]; + Texture *texture = texture_owner.get_or_null(texture_rid); + if (texture == nullptr) { + clears[i] = false; + clear_values[i] = RDD::RenderPassClearValue(); + continue; + } + + // Indicate the texture will get modified for the shared texture fallback. + _texture_update_shared_fallback(texture_rid, texture, true); + + bool clear = false; + RDD::RenderPassClearValue clear_value; + if (texture->usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) { + if (p_clear_colors.has_flag(ClearColorFlags(1 << color_index)) && color_index < p_clear_color_values.size()) { + clear = true; + clear_value.color = p_clear_color_values[color_index]; + } + + resource_trackers.push_back(texture->draw_tracker); + resource_usages.push_back(RDG::RESOURCE_USAGE_ATTACHMENT_COLOR_READ_WRITE); + uses_color = true; + color_index++; + } else if (texture->usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { + if (p_clear_depth || p_clear_stencil) { + clear = true; + clear_value.depth = p_clear_depth_value; + clear_value.stencil = p_clear_stencil_value; } + + resource_trackers.push_back(texture->draw_tracker); + resource_usages.push_back(RDG::RESOURCE_USAGE_ATTACHMENT_DEPTH_STENCIL_READ_WRITE); + uses_depth = true; } - ERR_FAIL_COND_V_MSG(p_clear_color_values.size() != color_count, INVALID_ID, "Clear color values supplied (" + itos(p_clear_color_values.size()) + ") differ from the amount required for framebuffer color attachments (" + itos(color_count) + ")."); + + clears[i] = clear; + clear_values[i] = clear_value; } - RDD::FramebufferID fb_driver_id; - RDD::RenderPassID render_pass; + draw_graph.add_draw_list_begin(framebuffer->framebuffer_cache, Rect2i(viewport_offset, viewport_size), clears, clear_values, uses_color, uses_depth, p_breadcrumb); + draw_graph.add_draw_list_usages(resource_trackers, resource_usages); - Error err = _draw_list_setup_framebuffer(framebuffer, p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, &fb_driver_id, &render_pass, &draw_list_subpass_count); - ERR_FAIL_COND_V(err != OK, INVALID_ID); + // Mark textures as bound. + draw_list_bound_textures.clear(); - err = _draw_list_render_pass_begin(framebuffer, p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, viewport_offset, viewport_size, fb_driver_id, render_pass, p_breadcrumb); + for (int i = 0; i < framebuffer->texture_ids.size(); i++) { + Texture *texture = texture_owner.get_or_null(framebuffer->texture_ids[i]); + if (texture == nullptr) { + continue; + } - if (err != OK) { - return INVALID_ID; + texture->bound = true; + draw_list_bound_textures.push_back(framebuffer->texture_ids[i]); } - draw_list_render_pass = render_pass; - draw_list_vkframebuffer = fb_driver_id; - _draw_list_allocate(Rect2i(viewport_offset, viewport_size), 0); #ifdef DEBUG_ENABLED draw_list_framebuffer_format = framebuffer->format_id; #endif draw_list_current_subpass = 0; + const FramebufferFormatKey &key = framebuffer_formats[framebuffer->format_id].E->key(); + draw_list_subpass_count = key.passes.size(); + Rect2i viewport_rect(viewport_offset, viewport_size); draw_graph.add_draw_list_set_viewport(viewport_rect); draw_graph.add_draw_list_set_scissor(viewport_rect); @@ -5428,6 +5377,7 @@ bool RenderingDevice::_texture_make_mutable(Texture *p_texture, RID p_texture_id p_texture->draw_tracker->texture_driver_id = p_texture->driver_id; p_texture->draw_tracker->texture_subresources = p_texture->barrier_range(); p_texture->draw_tracker->texture_usage = p_texture->usage_flags; + p_texture->draw_tracker->is_transient = p_texture->is_transient; p_texture->draw_tracker->reference_count = 1; if (p_texture_id.is_valid()) { @@ -5838,13 +5788,7 @@ void RenderingDevice::_free_pending_resources(int p_frame) { // Framebuffers. while (frames[p_frame].framebuffers_to_dispose_of.front()) { Framebuffer *framebuffer = &frames[p_frame].framebuffers_to_dispose_of.front()->get(); - - for (const KeyValue &E : framebuffer->framebuffers) { - // First framebuffer, then render pass because it depends on it. - driver->framebuffer_free(E.value.framebuffer); - driver->render_pass_free(E.value.render_pass); - } - + draw_graph.framebuffer_cache_free(driver, framebuffer->framebuffer_cache); frames[p_frame].framebuffers_to_dispose_of.pop_front(); } @@ -6195,7 +6139,7 @@ Error RenderingDevice::initialize(RenderingContextDriver *p_context, DisplayServ driver->command_buffer_begin(frames[0].command_buffer); // Create draw graph and start it initialized as well. - draw_graph.initialize(driver, device, frames.size(), main_queue_family, SECONDARY_COMMAND_BUFFERS_PER_FRAME); + draw_graph.initialize(driver, device, &_render_pass_create_from_graph, frames.size(), main_queue_family, SECONDARY_COMMAND_BUFFERS_PER_FRAME); draw_graph.begin(); for (uint32_t i = 0; i < frames.size(); i++) { @@ -6693,6 +6637,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_set_transient", "texture", "transient"), &RenderingDevice::texture_set_transient); + ClassDB::bind_method(D_METHOD("texture_is_transient", "texture"), &RenderingDevice::texture_is_transient); + ClassDB::bind_method(D_METHOD("texture_copy", "from_texture", "to_texture", "from_pos", "to_pos", "size", "src_mipmap", "dst_mipmap", "src_layer", "dst_layer"), &RenderingDevice::texture_copy); ClassDB::bind_method(D_METHOD("texture_clear", "texture", "color", "base_mipmap", "mipmap_count", "base_layer", "layer_count"), &RenderingDevice::texture_clear); ClassDB::bind_method(D_METHOD("texture_resolve_multisample", "from_texture", "to_texture"), &RenderingDevice::texture_resolve_multisample); @@ -6754,7 +6701,7 @@ void RenderingDevice::_bind_methods() { ClassDB::bind_method(D_METHOD("draw_list_begin_for_screen", "screen", "clear_color"), &RenderingDevice::draw_list_begin_for_screen, DEFVAL(DisplayServer::MAIN_WINDOW_ID), DEFVAL(Color())); - ClassDB::bind_method(D_METHOD("draw_list_begin", "framebuffer", "initial_color_action", "final_color_action", "initial_depth_action", "final_depth_action", "clear_color_values", "clear_depth", "clear_stencil", "region", "breadcrumb"), &RenderingDevice::draw_list_begin, DEFVAL(Vector()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2()), DEFVAL(0)); + ClassDB::bind_method(D_METHOD("draw_list_begin", "framebuffer", "clear_colors", "clear_color_values", "clear_depth", "clear_depth_value", "clear_stencil", "clear_stencil_value", "region", "breadcrumb"), &RenderingDevice::draw_list_begin, DEFVAL(CLEAR_COLOR_NONE), DEFVAL(Vector()), DEFVAL(false), DEFVAL(1.0), DEFVAL(false), DEFVAL(0), DEFVAL(Rect2()), DEFVAL(0)); #ifndef DISABLE_DEPRECATED ClassDB::bind_method(D_METHOD("draw_list_begin_split", "framebuffer", "splits", "initial_color_action", "final_color_action", "initial_depth_action", "final_depth_action", "clear_color_values", "clear_depth", "clear_stencil", "region", "storage_textures"), &RenderingDevice::_draw_list_begin_split, DEFVAL(Vector()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2()), DEFVAL(TypedArray())); #endif @@ -7278,22 +7225,20 @@ void RenderingDevice::_bind_methods() { BIND_BITFIELD_FLAG(DYNAMIC_STATE_STENCIL_WRITE_MASK); BIND_BITFIELD_FLAG(DYNAMIC_STATE_STENCIL_REFERENCE); +#ifndef DISABLE_DEPRECATED BIND_ENUM_CONSTANT(INITIAL_ACTION_LOAD); BIND_ENUM_CONSTANT(INITIAL_ACTION_CLEAR); BIND_ENUM_CONSTANT(INITIAL_ACTION_DISCARD); BIND_ENUM_CONSTANT(INITIAL_ACTION_MAX); -#ifndef DISABLE_DEPRECATED BIND_ENUM_CONSTANT(INITIAL_ACTION_CLEAR_REGION); BIND_ENUM_CONSTANT(INITIAL_ACTION_CLEAR_REGION_CONTINUE); BIND_ENUM_CONSTANT(INITIAL_ACTION_KEEP); BIND_ENUM_CONSTANT(INITIAL_ACTION_DROP); BIND_ENUM_CONSTANT(INITIAL_ACTION_CONTINUE); -#endif BIND_ENUM_CONSTANT(FINAL_ACTION_STORE); BIND_ENUM_CONSTANT(FINAL_ACTION_DISCARD); BIND_ENUM_CONSTANT(FINAL_ACTION_MAX); -#ifndef DISABLE_DEPRECATED BIND_ENUM_CONSTANT(FINAL_ACTION_READ); BIND_ENUM_CONSTANT(FINAL_ACTION_CONTINUE); #endif @@ -7375,6 +7320,18 @@ void RenderingDevice::_bind_methods() { BIND_ENUM_CONSTANT(BLIT_PASS); BIND_ENUM_CONSTANT(UI_PASS); BIND_ENUM_CONSTANT(DEBUG_PASS); + + BIND_BITFIELD_FLAG(CLEAR_COLOR_NONE); + BIND_BITFIELD_FLAG(CLEAR_COLOR_0); + BIND_BITFIELD_FLAG(CLEAR_COLOR_1); + BIND_BITFIELD_FLAG(CLEAR_COLOR_2); + BIND_BITFIELD_FLAG(CLEAR_COLOR_3); + BIND_BITFIELD_FLAG(CLEAR_COLOR_4); + BIND_BITFIELD_FLAG(CLEAR_COLOR_5); + BIND_BITFIELD_FLAG(CLEAR_COLOR_6); + BIND_BITFIELD_FLAG(CLEAR_COLOR_7); + BIND_BITFIELD_FLAG(CLEAR_COLOR_MASK); + BIND_BITFIELD_FLAG(CLEAR_COLOR_ALL); } void RenderingDevice::make_current() { diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h index c7b93f2fc7c4..0c9e2d2fd97e 100644 --- a/servers/rendering/rendering_device.h +++ b/servers/rendering/rendering_device.h @@ -251,6 +251,7 @@ class RenderingDevice : public RenderingDeviceCommons { Vector allowed_shared_formats; bool is_resolve_buffer = false; + bool is_transient = false; bool has_initial_data = false; BitField read_aspect_flags; @@ -287,6 +288,7 @@ class RenderingDevice : public RenderingDeviceCommons { tf.usage_bits = usage_flags; tf.shareable_formats = allowed_shared_formats; tf.is_resolve_buffer = is_resolve_buffer; + tf.is_transient = is_transient; return tf; } }; @@ -349,33 +351,8 @@ class RenderingDevice : public RenderingDeviceCommons { 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); Error texture_resolve_multisample(RID p_from_texture, RID p_to_texture); - /************************/ - /**** DRAW LISTS (I) ****/ - /************************/ - - enum InitialAction { - INITIAL_ACTION_LOAD, - INITIAL_ACTION_CLEAR, - INITIAL_ACTION_DISCARD, - INITIAL_ACTION_MAX, -#ifndef DISABLE_DEPRECATED - INITIAL_ACTION_CLEAR_REGION = INITIAL_ACTION_CLEAR, - INITIAL_ACTION_CLEAR_REGION_CONTINUE = INITIAL_ACTION_CLEAR, - INITIAL_ACTION_KEEP = INITIAL_ACTION_LOAD, - INITIAL_ACTION_DROP = INITIAL_ACTION_DISCARD, - INITIAL_ACTION_CONTINUE = INITIAL_ACTION_LOAD, -#endif - }; - - enum FinalAction { - FINAL_ACTION_STORE, - FINAL_ACTION_DISCARD, - FINAL_ACTION_MAX, -#ifndef DISABLE_DEPRECATED - FINAL_ACTION_READ = FINAL_ACTION_STORE, - FINAL_ACTION_CONTINUE = FINAL_ACTION_STORE, -#endif - }; + void texture_set_transient(RID p_texture, bool p_transient); + bool texture_is_transient(RID p_texture); /*********************/ /**** FRAMEBUFFER ****/ @@ -523,7 +500,8 @@ class RenderingDevice : public RenderingDeviceCommons { } }; - RDD::RenderPassID _render_pass_create(const Vector &p_attachments, const Vector &p_passes, InitialAction p_initial_action, FinalAction p_final_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, uint32_t p_view_count = 1, Vector *r_samples = nullptr); + static RDD::RenderPassID _render_pass_create(RenderingDeviceDriver *p_driver, const Vector &p_attachments, const Vector &p_passes, VectorView p_load_ops, VectorView p_store_ops, uint32_t p_view_count = 1, Vector *r_samples = nullptr); + static RDD::RenderPassID _render_pass_create_from_graph(RenderingDeviceDriver *p_driver, VectorView p_load_ops, VectorView p_store_ops, void *p_user_data); // This is a cache and it's never freed, it ensures // IDs for a given format are always unique. @@ -538,47 +516,13 @@ class RenderingDevice : public RenderingDeviceCommons { HashMap framebuffer_formats; struct Framebuffer { + RenderingDevice *rendering_device = nullptr; FramebufferFormatID format_id; - struct VersionKey { - InitialAction initial_color_action; - FinalAction final_color_action; - InitialAction initial_depth_action; - FinalAction final_depth_action; - uint32_t view_count; - - bool operator<(const VersionKey &p_key) const { - if (initial_color_action == p_key.initial_color_action) { - if (final_color_action == p_key.final_color_action) { - if (initial_depth_action == p_key.initial_depth_action) { - if (final_depth_action == p_key.final_depth_action) { - return view_count < p_key.view_count; - } else { - return final_depth_action < p_key.final_depth_action; - } - } else { - return initial_depth_action < p_key.initial_depth_action; - } - } else { - return final_color_action < p_key.final_color_action; - } - } else { - return initial_color_action < p_key.initial_color_action; - } - } - }; - uint32_t storage_mask = 0; Vector texture_ids; InvalidationCallback invalidated_callback = nullptr; void *invalidated_callback_userdata = nullptr; - - struct Version { - RDD::FramebufferID framebuffer; - RDD::RenderPassID render_pass; // This one is owned. - uint32_t subpass_count = 1; - }; - - RBMap framebuffers; + RDG::FramebufferCache *framebuffer_cache = nullptr; Size2 size; uint32_t view_count; }; @@ -826,6 +770,26 @@ class RenderingDevice : public RenderingDeviceCommons { BARRIER_MASK_NO_BARRIER = 0x8000, }; + enum InitialAction { + INITIAL_ACTION_LOAD, + INITIAL_ACTION_CLEAR, + INITIAL_ACTION_DISCARD, + INITIAL_ACTION_MAX, + INITIAL_ACTION_CLEAR_REGION = INITIAL_ACTION_CLEAR, + INITIAL_ACTION_CLEAR_REGION_CONTINUE = INITIAL_ACTION_CLEAR, + INITIAL_ACTION_KEEP = INITIAL_ACTION_LOAD, + INITIAL_ACTION_DROP = INITIAL_ACTION_DISCARD, + INITIAL_ACTION_CONTINUE = INITIAL_ACTION_LOAD, + }; + + enum FinalAction { + FINAL_ACTION_STORE, + FINAL_ACTION_DISCARD, + FINAL_ACTION_MAX, + FINAL_ACTION_READ = FINAL_ACTION_STORE, + FINAL_ACTION_CONTINUE = FINAL_ACTION_STORE, + }; + void barrier(BitField p_from = BARRIER_MASK_ALL_BARRIERS, BitField p_to = BARRIER_MASK_ALL_BARRIERS); void full_barrier(); void draw_command_insert_label(String p_label_name, const Color &p_color = Color(1, 1, 1, 1)); @@ -854,7 +818,9 @@ class RenderingDevice : public RenderingDeviceCommons { FramebufferFormatID _screen_get_framebuffer_format_bind_compat_87340() const; - DrawListID _draw_list_begin_bind_compat_90993(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector &p_clear_color_values = Vector(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2()); + DrawListID _draw_list_begin_bind_compat_90993(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region); + + DrawListID _draw_list_begin_bind_compat_98670(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region, uint32_t p_breadcrumb); #endif public: @@ -1157,8 +1123,6 @@ class RenderingDevice : public RenderingDeviceCommons { DrawList *draw_list = nullptr; uint32_t draw_list_subpass_count = 0; - RDD::RenderPassID draw_list_render_pass; - RDD::FramebufferID draw_list_vkframebuffer; #ifdef DEBUG_ENABLED FramebufferFormatID draw_list_framebuffer_format = INVALID_ID; #endif @@ -1166,16 +1130,27 @@ class RenderingDevice : public RenderingDeviceCommons { Vector draw_list_bound_textures; - void _draw_list_insert_clear_region(DrawList *p_draw_list, Framebuffer *p_framebuffer, Point2i p_viewport_offset, Point2i p_viewport_size, bool p_clear_color, const Vector &p_clear_colors, bool p_clear_depth, float p_depth, uint32_t p_stencil); - Error _draw_list_setup_framebuffer(Framebuffer *p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, RDD::FramebufferID *r_framebuffer, RDD::RenderPassID *r_render_pass, uint32_t *r_subpass_count); - Error _draw_list_render_pass_begin(Framebuffer *p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector &p_clear_colors, float p_clear_depth, uint32_t p_clear_stencil, Point2i p_viewport_offset, Point2i p_viewport_size, RDD::FramebufferID p_framebuffer_driver_id, RDD::RenderPassID p_render_pass, uint32_t p_breadcrumb); _FORCE_INLINE_ DrawList *_get_draw_list_ptr(DrawListID p_id); Error _draw_list_allocate(const Rect2i &p_viewport, uint32_t p_subpass); void _draw_list_free(Rect2i *r_last_viewport = nullptr); public: + enum ClearColorFlags { + CLEAR_COLOR_NONE = 0, + CLEAR_COLOR_0 = (1 << 0), + CLEAR_COLOR_1 = (1 << 1), + CLEAR_COLOR_2 = (1 << 2), + CLEAR_COLOR_3 = (1 << 3), + CLEAR_COLOR_4 = (1 << 4), + CLEAR_COLOR_5 = (1 << 5), + CLEAR_COLOR_6 = (1 << 6), + CLEAR_COLOR_7 = (1 << 7), + CLEAR_COLOR_MASK = 255, + CLEAR_COLOR_ALL = CLEAR_COLOR_MASK + }; + DrawListID draw_list_begin_for_screen(DisplayServer::WindowID p_screen = 0, const Color &p_clear_color = Color()); - DrawListID draw_list_begin(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector &p_clear_color_values = Vector(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), uint32_t p_breadcrumb = 0); + DrawListID draw_list_begin(RID p_framebuffer, BitField p_clear_colors = CLEAR_COLOR_NONE, const Vector &p_clear_color_values = Vector(), bool p_clear_depth = false, float p_clear_depth_value = 1.0f, bool p_clear_stencil = false, uint32_t p_clear_stencil_value = 0, const Rect2 &p_region = Rect2(), uint32_t p_breadcrumb = 0); void draw_list_set_blend_constants(DrawListID p_list, const Color &p_color); void draw_list_bind_render_pipeline(DrawListID p_list, RID p_render_pipeline); @@ -1566,15 +1541,16 @@ VARIANT_ENUM_CAST(RenderingDevice::BlendFactor) VARIANT_ENUM_CAST(RenderingDevice::BlendOperation) VARIANT_BITFIELD_CAST(RenderingDevice::PipelineDynamicStateFlags) VARIANT_ENUM_CAST(RenderingDevice::PipelineSpecializationConstantType) -VARIANT_ENUM_CAST(RenderingDevice::InitialAction) -VARIANT_ENUM_CAST(RenderingDevice::FinalAction) VARIANT_ENUM_CAST(RenderingDevice::Limit) VARIANT_ENUM_CAST(RenderingDevice::MemoryType) VARIANT_ENUM_CAST(RenderingDevice::Features) VARIANT_ENUM_CAST(RenderingDevice::BreadcrumbMarker) +VARIANT_BITFIELD_CAST(RenderingDevice::ClearColorFlags); #ifndef DISABLE_DEPRECATED VARIANT_BITFIELD_CAST(RenderingDevice::BarrierMask); +VARIANT_ENUM_CAST(RenderingDevice::InitialAction) +VARIANT_ENUM_CAST(RenderingDevice::FinalAction) #endif typedef RenderingDevice RD; diff --git a/servers/rendering/rendering_device_binds.h b/servers/rendering/rendering_device_binds.h index 4d9b56508000..b7f49daa182f 100644 --- a/servers/rendering/rendering_device_binds.h +++ b/servers/rendering/rendering_device_binds.h @@ -69,6 +69,8 @@ class RDTextureFormat : public RefCounted { RD_SETGET(RD::TextureType, texture_type) RD_SETGET(RD::TextureSamples, samples) RD_SETGET(BitField, usage_bits) + RD_SETGET(bool, is_resolve_buffer) + RD_SETGET(bool, is_transient) 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); } @@ -84,6 +86,9 @@ class RDTextureFormat : public RefCounted { RD_BIND(Variant::INT, RDTextureFormat, texture_type); RD_BIND(Variant::INT, RDTextureFormat, samples); RD_BIND(Variant::INT, RDTextureFormat, usage_bits); + RD_BIND(Variant::BOOL, RDTextureFormat, is_resolve_buffer); + RD_BIND(Variant::BOOL, RDTextureFormat, is_transient); + ClassDB::bind_method(D_METHOD("add_shareable_format", "format"), &RDTextureFormat::add_shareable_format); ClassDB::bind_method(D_METHOD("remove_shareable_format", "format"), &RDTextureFormat::remove_shareable_format); } diff --git a/servers/rendering/rendering_device_commons.h b/servers/rendering/rendering_device_commons.h index d516d968af62..ce9bbeca8aa2 100644 --- a/servers/rendering/rendering_device_commons.h +++ b/servers/rendering/rendering_device_commons.h @@ -373,6 +373,7 @@ class RenderingDeviceCommons : public Object { uint32_t usage_bits = 0; Vector shareable_formats; bool is_resolve_buffer = false; + bool is_transient = false; bool operator==(const TextureFormat &b) const { if (format != b.format) { diff --git a/servers/rendering/rendering_device_graph.cpp b/servers/rendering/rendering_device_graph.cpp index 750753d796b2..5ca7194aa21a 100644 --- a/servers/rendering/rendering_device_graph.cpp +++ b/servers/rendering/rendering_device_graph.cpp @@ -211,6 +211,40 @@ RenderingDeviceGraph::ComputeListInstruction *RenderingDeviceGraph::_allocate_co return reinterpret_cast(&compute_instruction_list.data[compute_list_data_offset]); } +void RenderingDeviceGraph::_check_transient_attachment_dependency(ResourceTracker *p_resource_tracker, int32_t p_previous_command_index, int32_t p_command_index) { + if (!p_resource_tracker->is_transient) { + return; + } + + // Check if the command is a a draw list that clears the attachment completely. If it is, we don't need to modify the previous draw list. + uint32_t command_offset = command_data_offsets[p_command_index]; + RecordedDrawListCommand *draw_list_command = reinterpret_cast(&command_data[command_offset]); + if (draw_list_command->type == RecordedCommand::TYPE_DRAW_LIST) { + ResourceTracker **trackers = draw_list_command->trackers(); + for (uint32_t i = 0; i < draw_list_command->trackers_count; i++) { + if (trackers[i] == p_resource_tracker && draw_list_command->load_ops()[i] == RDD::ATTACHMENT_LOAD_OP_CLEAR) { + return; + } + } + } + + // Check if the previous command is a draw list. + uint32_t previous_command_offset = command_data_offsets[p_previous_command_index]; + RecordedDrawListCommand *previous_draw_list_command = reinterpret_cast(&command_data[previous_command_offset]); + if (previous_draw_list_command->type != RecordedCommand::TYPE_DRAW_LIST) { + return; + } + + // Search for the tracker inside the draw list command and modify the store operation accordingly. + ResourceTracker **trackers = previous_draw_list_command->trackers(); + for (uint32_t i = 0; i < previous_draw_list_command->trackers_count; i++) { + if (trackers[i] == p_resource_tracker) { + previous_draw_list_command->store_ops()[i] = RDD::ATTACHMENT_STORE_OP_STORE; + return; + } + } +} + void RenderingDeviceGraph::_add_command_to_graph(ResourceTracker **p_resource_trackers, ResourceUsage *p_resource_usages, uint32_t p_resource_count, int32_t p_command_index, RecordedCommand *r_command) { // Assign the next stages derived from the stages the command requires first. r_command->next_stages = r_command->self_stages; @@ -465,6 +499,8 @@ void RenderingDeviceGraph::_add_command_to_graph(ResourceTracker **p_resource_tr if (write_list_node.command_index == p_command_index) { ERR_FAIL_COND_MSG(!resource_has_parent, "Command can't have itself as a dependency."); } else { + _check_transient_attachment_dependency(search_tracker, write_list_node.command_index, p_command_index); + // Command is dependent on this command. Add this command to the adjacency list of the write command. _add_adjacent_command(write_list_node.command_index, p_command_index, r_command); @@ -491,6 +527,7 @@ void RenderingDeviceGraph::_add_command_to_graph(ResourceTracker **p_resource_tr if (search_tracker->write_command_or_list_index == p_command_index) { ERR_FAIL_MSG("Command can't have itself as a dependency."); } else { + _check_transient_attachment_dependency(search_tracker, search_tracker->write_command_or_list_index, p_command_index); _add_adjacent_command(search_tracker->write_command_or_list_index, p_command_index, r_command); } } @@ -660,6 +697,38 @@ void RenderingDeviceGraph::_run_compute_list_command(RDD::CommandBufferID p_comm } } +void RenderingDeviceGraph::_get_draw_list_render_pass_and_framebuffer(RecordedDrawListCommand *p_draw_list_command, RDD::RenderPassID &r_render_pass, RDD::FramebufferID &r_framebuffer) { + DEV_ASSERT(p_draw_list_command->trackers_count <= 21 && "Max amount of attachments that can be encoded into the key."); + + // Build a unique key from the load and store ops for each attachment. + RDD::AttachmentLoadOp *load_ops = p_draw_list_command->load_ops(); + RDD::AttachmentStoreOp *store_ops = p_draw_list_command->store_ops(); + uint64_t key = 0; + for (uint32_t i = 0; i < p_draw_list_command->trackers_count; i++) { + key |= uint64_t(load_ops[i]) << (i * 3); + key |= uint64_t(store_ops[i]) << (i * 3 + 2); + } + + // Check the storage map if the render pass and the framebuffer needs to be created. + FramebufferCache *framebuffer_cache = p_draw_list_command->framebuffer_cache; + HashMap::Iterator it = framebuffer_cache->storage_map.find(key); + if (it == framebuffer_cache->storage_map.end()) { + FramebufferStorage storage; + VectorView load_ops_view(load_ops, p_draw_list_command->trackers_count); + VectorView store_ops_view(store_ops, p_draw_list_command->trackers_count); + storage.render_pass = render_pass_creation_function(driver, load_ops_view, store_ops_view, framebuffer_cache->render_pass_creation_user_data); + ERR_FAIL_COND(!storage.render_pass); + + storage.framebuffer = driver->framebuffer_create(storage.render_pass, framebuffer_cache->textures, framebuffer_cache->width, framebuffer_cache->height); + ERR_FAIL_COND(!storage.framebuffer); + + it = framebuffer_cache->storage_map.insert(key, storage); + } + + r_render_pass = it->value.render_pass; + r_framebuffer = it->value.framebuffer; +} + void RenderingDeviceGraph::_run_draw_list_command(RDD::CommandBufferID p_command_buffer, const uint8_t *p_instruction_data, uint32_t p_instruction_data_size) { uint32_t instruction_data_cursor = 0; while (instruction_data_cursor < p_instruction_data_size) { @@ -767,6 +836,37 @@ void RenderingDeviceGraph::_run_draw_list_command(RDD::CommandBufferID p_command } } +void RenderingDeviceGraph::_add_draw_list_begin(FramebufferCache *p_framebuffer_cache, RDD::RenderPassID p_render_pass, RDD::FramebufferID p_framebuffer, Rect2i p_region, VectorView p_clear_attachments, VectorView p_clear_attachment_values, bool p_uses_color, bool p_uses_depth, uint32_t p_breadcrumb) { + DEV_ASSERT(p_clear_attachments.size() == p_clear_attachment_values.size()); + + draw_instruction_list.clear(); + draw_instruction_list.index++; + draw_instruction_list.framebuffer_cache = p_framebuffer_cache; + draw_instruction_list.render_pass = p_render_pass; + draw_instruction_list.framebuffer = p_framebuffer; + draw_instruction_list.region = p_region; + draw_instruction_list.clear_attachments.resize(p_clear_attachments.size()); + draw_instruction_list.clear_values.resize(p_clear_attachment_values.size()); + + for (uint32_t i = 0; i < p_clear_attachments.size(); i++) { + draw_instruction_list.clear_attachments[i] = p_clear_attachments[i]; + draw_instruction_list.clear_values[i] = p_clear_attachment_values[i]; + } + + if (p_uses_color) { + draw_instruction_list.stages.set_flag(RDD::PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT); + } + + if (p_uses_depth) { + draw_instruction_list.stages.set_flag(RDD::PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT); + draw_instruction_list.stages.set_flag(RDD::PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT); + } + +#if defined(DEBUG_ENABLED) || defined(DEV_ENABLED) + draw_instruction_list.breadcrumb = p_breadcrumb; +#endif +} + void RenderingDeviceGraph::_run_secondary_command_buffer_task(const SecondaryCommandBuffer *p_secondary) { driver->command_buffer_begin_secondary(p_secondary->command_buffer, p_secondary->render_pass, 0, p_secondary->framebuffer); _run_draw_list_command(p_secondary->command_buffer, p_secondary->instruction_data.ptr(), p_secondary->instruction_data.size()); @@ -787,7 +887,7 @@ void RenderingDeviceGraph::_run_render_commands(int32_t p_level, const RecordedC for (uint32_t i = 0; i < p_sorted_commands_count; i++) { const uint32_t command_index = p_sorted_commands[i].index; const uint32_t command_data_offset = command_data_offsets[command_index]; - const RecordedCommand *command = reinterpret_cast(&command_data[command_data_offset]); + RecordedCommand *command = reinterpret_cast(&command_data[command_data_offset]); _run_label_command_change(r_command_buffer, command->label_index, p_level, false, true, &p_sorted_commands[i], p_sorted_commands_count - i, r_current_label_index, r_current_label_level); switch (command->type) { @@ -840,14 +940,25 @@ void RenderingDeviceGraph::_run_render_commands(int32_t p_level, const RecordedC workarounds_state.draw_list_found = true; } - const RecordedDrawListCommand *draw_list_command = reinterpret_cast(command); + RecordedDrawListCommand *draw_list_command = reinterpret_cast(command); const VectorView clear_values(draw_list_command->clear_values(), draw_list_command->clear_values_count); #if defined(DEBUG_ENABLED) || defined(DEV_ENABLED) driver->command_insert_breadcrumb(r_command_buffer, draw_list_command->breadcrumb); #endif - driver->command_begin_render_pass(r_command_buffer, draw_list_command->render_pass, draw_list_command->framebuffer, draw_list_command->command_buffer_type, draw_list_command->region, clear_values); - _run_draw_list_command(r_command_buffer, draw_list_command->instruction_data(), draw_list_command->instruction_data_size); - driver->command_end_render_pass(r_command_buffer); + RDD::RenderPassID render_pass; + RDD::FramebufferID framebuffer; + if (draw_list_command->framebuffer_cache != nullptr) { + _get_draw_list_render_pass_and_framebuffer(draw_list_command, render_pass, framebuffer); + } else { + render_pass = draw_list_command->render_pass; + framebuffer = draw_list_command->framebuffer; + } + + if (framebuffer && render_pass) { + driver->command_begin_render_pass(r_command_buffer, render_pass, framebuffer, draw_list_command->command_buffer_type, draw_list_command->region, clear_values); + _run_draw_list_command(r_command_buffer, draw_list_command->instruction_data(), draw_list_command->instruction_data_size); + driver->command_end_render_pass(r_command_buffer); + } } break; case RecordedCommand::TYPE_TEXTURE_CLEAR: { const RecordedTextureClearCommand *texture_clear_command = reinterpret_cast(command); @@ -1300,9 +1411,14 @@ void RenderingDeviceGraph::_print_compute_list(const uint8_t *p_instruction_data } } -void RenderingDeviceGraph::initialize(RDD *p_driver, RenderingContextDriver::Device p_device, uint32_t p_frame_count, RDD::CommandQueueFamilyID p_secondary_command_queue_family, uint32_t p_secondary_command_buffers_per_frame) { +void RenderingDeviceGraph::initialize(RDD *p_driver, RenderingContextDriver::Device p_device, RenderPassCreationFunction p_render_pass_creation_function, uint32_t p_frame_count, RDD::CommandQueueFamilyID p_secondary_command_queue_family, uint32_t p_secondary_command_buffers_per_frame) { + DEV_ASSERT(p_driver != nullptr); + DEV_ASSERT(p_render_pass_creation_function != nullptr); + DEV_ASSERT(p_frame_count > 0); + driver = p_driver; device = p_device; + render_pass_creation_function = p_render_pass_creation_function; frames.resize(p_frame_count); for (uint32_t i = 0; i < p_frame_count; i++) { @@ -1527,28 +1643,12 @@ void RenderingDeviceGraph::add_compute_list_end() { _add_command_to_graph(compute_instruction_list.command_trackers.ptr(), compute_instruction_list.command_tracker_usages.ptr(), compute_instruction_list.command_trackers.size(), command_index, command); } -void RenderingDeviceGraph::add_draw_list_begin(RDD::RenderPassID p_render_pass, RDD::FramebufferID p_framebuffer, Rect2i p_region, VectorView p_clear_values, bool p_uses_color, bool p_uses_depth, uint32_t p_breadcrumb) { - draw_instruction_list.clear(); - draw_instruction_list.index++; - draw_instruction_list.render_pass = p_render_pass; - draw_instruction_list.framebuffer = p_framebuffer; - draw_instruction_list.region = p_region; -#if defined(DEBUG_ENABLED) || defined(DEV_ENABLED) - draw_instruction_list.breadcrumb = p_breadcrumb; -#endif - draw_instruction_list.clear_values.resize(p_clear_values.size()); - for (uint32_t i = 0; i < p_clear_values.size(); i++) { - draw_instruction_list.clear_values[i] = p_clear_values[i]; - } - - if (p_uses_color) { - draw_instruction_list.stages.set_flag(RDD::PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT); - } +void RenderingDeviceGraph::add_draw_list_begin(FramebufferCache *p_framebuffer_cache, Rect2i p_region, VectorView p_clear_attachments, VectorView p_clear_attachment_values, bool p_uses_color, bool p_uses_depth, uint32_t p_breadcrumb) { + _add_draw_list_begin(p_framebuffer_cache, RDD::RenderPassID(), RDD::FramebufferID(), p_region, p_clear_attachments, p_clear_attachment_values, p_uses_color, p_uses_depth, p_breadcrumb); +} - if (p_uses_depth) { - draw_instruction_list.stages.set_flag(RDD::PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT); - draw_instruction_list.stages.set_flag(RDD::PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT); - } +void RenderingDeviceGraph::add_draw_list_begin(RDD::RenderPassID p_render_pass, RDD::FramebufferID p_framebuffer, Rect2i p_region, VectorView p_clear_attachments, VectorView p_clear_attachment_values, bool p_uses_color, bool p_uses_depth, uint32_t p_breadcrumb) { + _add_draw_list_begin(nullptr, p_render_pass, p_framebuffer, p_region, p_clear_attachments, p_clear_attachment_values, p_uses_color, p_uses_depth, p_breadcrumb); } void RenderingDeviceGraph::add_draw_list_bind_index_buffer(RDD::BufferID p_buffer, RDD::IndexBufferFormat p_format, uint32_t p_offset) { @@ -1729,47 +1829,55 @@ void RenderingDeviceGraph::add_draw_list_usages(VectorView p_ } void RenderingDeviceGraph::add_draw_list_end() { - // Arbitrary size threshold to evaluate if it'd be best to record the draw list on the background as a secondary buffer. - const uint32_t instruction_data_threshold_for_secondary = 16384; - RDD::CommandBufferType command_buffer_type; - uint32_t &secondary_buffers_used = frames[frame].secondary_command_buffers_used; - if (draw_instruction_list.data.size() > instruction_data_threshold_for_secondary && secondary_buffers_used < frames[frame].secondary_command_buffers.size()) { - // Copy the current instruction list data into another array that will be used by the secondary command buffer worker. - SecondaryCommandBuffer &secondary = frames[frame].secondary_command_buffers[secondary_buffers_used]; - secondary.render_pass = draw_instruction_list.render_pass; - secondary.framebuffer = draw_instruction_list.framebuffer; - secondary.instruction_data.resize(draw_instruction_list.data.size()); - memcpy(secondary.instruction_data.ptr(), draw_instruction_list.data.ptr(), draw_instruction_list.data.size()); - - // Run a background task for recording the secondary command buffer. - secondary.task = WorkerThreadPool::get_singleton()->add_template_task(this, &RenderingDeviceGraph::_run_secondary_command_buffer_task, &secondary, true); - - // Clear the instruction list and add a single command for executing the secondary command buffer instead. - draw_instruction_list.data.clear(); - add_draw_list_execute_commands(secondary.command_buffer); - secondary_buffers_used++; - - command_buffer_type = RDD::COMMAND_BUFFER_TYPE_SECONDARY; - } else { - command_buffer_type = RDD::COMMAND_BUFFER_TYPE_PRIMARY; - } - + FramebufferCache *framebuffer_cache = draw_instruction_list.framebuffer_cache; int32_t command_index; uint32_t clear_values_size = sizeof(RDD::RenderPassClearValue) * draw_instruction_list.clear_values.size(); + uint32_t trackers_count = framebuffer_cache != nullptr ? framebuffer_cache->trackers.size() : 0; + uint32_t trackers_and_ops_size = (sizeof(ResourceTracker *) + sizeof(RDD::AttachmentLoadOp) + sizeof(RDD::AttachmentStoreOp)) * trackers_count; uint32_t instruction_data_size = draw_instruction_list.data.size(); - uint32_t command_size = sizeof(RecordedDrawListCommand) + clear_values_size + instruction_data_size; + uint32_t command_size = sizeof(RecordedDrawListCommand) + clear_values_size + trackers_and_ops_size + instruction_data_size; RecordedDrawListCommand *command = static_cast(_allocate_command(command_size, command_index)); command->type = RecordedCommand::TYPE_DRAW_LIST; command->self_stages = draw_instruction_list.stages; - command->instruction_data_size = instruction_data_size; + command->framebuffer_cache = framebuffer_cache; command->render_pass = draw_instruction_list.render_pass; command->framebuffer = draw_instruction_list.framebuffer; - command->command_buffer_type = command_buffer_type; + command->instruction_data_size = instruction_data_size; + command->command_buffer_type = RDD::COMMAND_BUFFER_TYPE_PRIMARY; command->region = draw_instruction_list.region; #if defined(DEBUG_ENABLED) || defined(DEV_ENABLED) command->breadcrumb = draw_instruction_list.breadcrumb; #endif command->clear_values_count = draw_instruction_list.clear_values.size(); + command->trackers_count = trackers_count; + + // Initialize the load and store operations to their default behaviors. The store behavior will be modified if a command depends on the result of this render pass. + ResourceTracker **trackers = command->trackers(); + RDD::AttachmentLoadOp *load_ops = command->load_ops(); + RDD::AttachmentStoreOp *store_ops = command->store_ops(); + for (uint32_t i = 0; i < command->trackers_count; i++) { + ResourceTracker *resource_tracker = framebuffer_cache->trackers[i]; + if (resource_tracker != nullptr) { + if (i < command->clear_values_count && draw_instruction_list.clear_attachments[i]) { + load_ops[i] = RDD::ATTACHMENT_LOAD_OP_CLEAR; + } else if (resource_tracker->is_transient) { + bool resource_has_parent = resource_tracker->parent != nullptr; + ResourceTracker *search_tracker = resource_has_parent ? resource_tracker->parent : resource_tracker; + search_tracker->reset_if_outdated(tracking_frame); + bool resource_was_modified_this_frame = search_tracker->write_command_or_list_index >= 0; + load_ops[i] = resource_was_modified_this_frame ? RDD::ATTACHMENT_LOAD_OP_LOAD : RDD::ATTACHMENT_LOAD_OP_DONT_CARE; + } else { + load_ops[i] = RDD::ATTACHMENT_LOAD_OP_LOAD; + } + + store_ops[i] = resource_tracker->is_transient ? RDD::ATTACHMENT_STORE_OP_DONT_CARE : RDD::ATTACHMENT_STORE_OP_STORE; + } else { + load_ops[i] = RDD::ATTACHMENT_LOAD_OP_DONT_CARE; + store_ops[i] = RDD::ATTACHMENT_STORE_OP_DONT_CARE; + } + + trackers[i] = resource_tracker; + } RDD::RenderPassClearValue *clear_values = command->clear_values(); for (uint32_t i = 0; i < command->clear_values_count; i++) { @@ -2143,20 +2251,20 @@ RenderingDeviceGraph::ResourceTracker *RenderingDeviceGraph::resource_tracker_cr return memnew(ResourceTracker); } -void RenderingDeviceGraph::resource_tracker_free(ResourceTracker *tracker) { - if (tracker == nullptr) { +void RenderingDeviceGraph::resource_tracker_free(ResourceTracker *p_tracker) { + if (p_tracker == nullptr) { return; } - if (tracker->in_parent_dirty_list) { + if (p_tracker->in_parent_dirty_list) { // Delete the tracker from the parent's dirty linked list. - if (tracker->parent->dirty_shared_list == tracker) { - tracker->parent->dirty_shared_list = tracker->next_shared; + if (p_tracker->parent->dirty_shared_list == p_tracker) { + p_tracker->parent->dirty_shared_list = p_tracker->next_shared; } else { - ResourceTracker *node = tracker->parent->dirty_shared_list; + ResourceTracker *node = p_tracker->parent->dirty_shared_list; while (node != nullptr) { - if (node->next_shared == tracker) { - node->next_shared = tracker->next_shared; + if (node->next_shared == p_tracker) { + node->next_shared = p_tracker->next_shared; node = nullptr; } else { node = node->next_shared; @@ -2165,9 +2273,28 @@ void RenderingDeviceGraph::resource_tracker_free(ResourceTracker *tracker) { } } - memdelete(tracker); + memdelete(p_tracker); #if PRINT_RESOURCE_TRACKER_TOTAL print_line("Resource trackers:", --resource_tracker_total); #endif } + +RenderingDeviceGraph::FramebufferCache *RenderingDeviceGraph::framebuffer_cache_create() { + return memnew(FramebufferCache); +} + +void RenderingDeviceGraph::framebuffer_cache_free(RDD *p_driver, FramebufferCache *p_cache) { + DEV_ASSERT(p_driver != nullptr); + + if (p_cache == nullptr) { + return; + } + + for (KeyValue &E : p_cache->storage_map) { + p_driver->framebuffer_free(E.value.framebuffer); + p_driver->render_pass_free(E.value.render_pass); + } + + memdelete(p_cache); +} diff --git a/servers/rendering/rendering_device_graph.h b/servers/rendering/rendering_device_graph.h index e52ab0c2f50b..94049353bc47 100644 --- a/servers/rendering/rendering_device_graph.h +++ b/servers/rendering/rendering_device_graph.h @@ -175,6 +175,7 @@ class RenderingDeviceGraph { Rect2i texture_slice_or_dirty_rect; bool in_parent_dirty_list = false; bool write_command_list_enabled = false; + bool is_transient = false; _FORCE_INLINE_ void reset_if_outdated(int64_t new_command_frame) { if (new_command_frame != command_frame) { @@ -192,6 +193,22 @@ class RenderingDeviceGraph { } }; + typedef RDD::RenderPassID (*RenderPassCreationFunction)(RenderingDeviceDriver *p_driver, VectorView p_load_ops, VectorView p_store_ops, void *p_user_data); + + struct FramebufferStorage { + RDD::FramebufferID framebuffer; + RDD::RenderPassID render_pass; + }; + + struct FramebufferCache { + uint32_t width = 0; + uint32_t height = 0; + LocalVector textures; + LocalVector trackers; + HashMap storage_map; + void *render_pass_creation_user_data = nullptr; + }; + struct CommandBufferPool { // Provided by RenderingDevice. RDD::CommandPoolID pool; @@ -229,13 +246,16 @@ class RenderingDeviceGraph { }; struct DrawInstructionList : InstructionList { + FramebufferCache *framebuffer_cache = nullptr; RDD::RenderPassID render_pass; RDD::FramebufferID framebuffer; Rect2i region; + LocalVector clear_attachments; + LocalVector clear_values; + #if defined(DEBUG_ENABLED) || defined(DEV_ENABLED) uint32_t breadcrumb; #endif - LocalVector clear_values; }; struct RecordedCommandSort { @@ -318,15 +338,18 @@ class RenderingDeviceGraph { }; struct RecordedDrawListCommand : RecordedCommand { - uint32_t instruction_data_size = 0; - RDD::RenderPassID render_pass; + FramebufferCache *framebuffer_cache = nullptr; RDD::FramebufferID framebuffer; + RDD::RenderPassID render_pass; + uint32_t instruction_data_size = 0; RDD::CommandBufferType command_buffer_type; Rect2i region; + uint32_t clear_values_count = 0; + uint32_t trackers_count = 0; + #if defined(DEBUG_ENABLED) || defined(DEV_ENABLED) uint32_t breadcrumb = 0; #endif - uint32_t clear_values_count = 0; _FORCE_INLINE_ RDD::RenderPassClearValue *clear_values() { return reinterpret_cast(&this[1]); @@ -336,12 +359,36 @@ class RenderingDeviceGraph { return reinterpret_cast(&this[1]); } + _FORCE_INLINE_ ResourceTracker **trackers() { + return reinterpret_cast(&clear_values()[clear_values_count]); + } + + _FORCE_INLINE_ ResourceTracker *const *trackers() const { + return reinterpret_cast(&clear_values()[clear_values_count]); + } + + _FORCE_INLINE_ RDD::AttachmentLoadOp *load_ops() { + return reinterpret_cast(&trackers()[trackers_count]); + } + + _FORCE_INLINE_ const RDD::AttachmentLoadOp *load_ops() const { + return reinterpret_cast(&trackers()[trackers_count]); + } + + _FORCE_INLINE_ RDD::AttachmentStoreOp *store_ops() { + return reinterpret_cast(&load_ops()[trackers_count]); + } + + _FORCE_INLINE_ const RDD::AttachmentStoreOp *store_ops() const { + return reinterpret_cast(&load_ops()[trackers_count]); + } + _FORCE_INLINE_ uint8_t *instruction_data() { - return reinterpret_cast(&clear_values()[clear_values_count]); + return reinterpret_cast(&store_ops()[trackers_count]); } _FORCE_INLINE_ const uint8_t *instruction_data() const { - return reinterpret_cast(&clear_values()[clear_values_count]); + return reinterpret_cast(&store_ops()[trackers_count]); } }; @@ -614,6 +661,7 @@ class RenderingDeviceGraph { RDD *driver = nullptr; RenderingContextDriver::Device device; + RenderPassCreationFunction render_pass_creation_function = nullptr; int64_t tracking_frame = 0; LocalVector command_data; LocalVector command_data_offsets; @@ -655,13 +703,16 @@ class RenderingDeviceGraph { RecordedCommand *_allocate_command(uint32_t p_command_size, int32_t &r_command_index); DrawListInstruction *_allocate_draw_list_instruction(uint32_t p_instruction_size); ComputeListInstruction *_allocate_compute_list_instruction(uint32_t p_instruction_size); + void _check_transient_attachment_dependency(ResourceTracker *p_resource_tracker, int32_t p_previous_command_index, int32_t p_command_index); void _add_command_to_graph(ResourceTracker **p_resource_trackers, ResourceUsage *p_resource_usages, uint32_t p_resource_count, int32_t p_command_index, RecordedCommand *r_command); void _add_texture_barrier_to_command(RDD::TextureID p_texture_id, BitField p_src_access, BitField p_dst_access, ResourceUsage p_prev_usage, ResourceUsage p_next_usage, RDD::TextureSubresourceRange p_subresources, LocalVector &r_barrier_vector, int32_t &r_barrier_index, int32_t &r_barrier_count); #if USE_BUFFER_BARRIERS void _add_buffer_barrier_to_command(RDD::BufferID p_buffer_id, BitField p_src_access, BitField p_dst_access, int32_t &r_barrier_index, int32_t &r_barrier_count); #endif void _run_compute_list_command(RDD::CommandBufferID p_command_buffer, const uint8_t *p_instruction_data, uint32_t p_instruction_data_size); + void _get_draw_list_render_pass_and_framebuffer(RecordedDrawListCommand *p_draw_list_command, RDD::RenderPassID &r_render_pass, RDD::FramebufferID &r_framebuffer); void _run_draw_list_command(RDD::CommandBufferID p_command_buffer, const uint8_t *p_instruction_data, uint32_t p_instruction_data_size); + void _add_draw_list_begin(FramebufferCache *p_framebuffer_cache, RDD::RenderPassID p_render_pass, RDD::FramebufferID p_framebuffer, Rect2i p_region, VectorView p_clear_attachments, VectorView p_clear_attachment_values, bool p_uses_color, bool p_uses_depth, uint32_t p_breadcrumb); void _run_secondary_command_buffer_task(const SecondaryCommandBuffer *p_secondary); void _wait_for_secondary_command_buffer_tasks(); void _run_render_commands(int32_t p_level, const RecordedCommandSort *p_sorted_commands, uint32_t p_sorted_commands_count, RDD::CommandBufferID &r_command_buffer, CommandBufferPool &r_command_buffer_pool, int32_t &r_current_label_index, int32_t &r_current_label_level); @@ -675,7 +726,7 @@ class RenderingDeviceGraph { public: RenderingDeviceGraph(); ~RenderingDeviceGraph(); - void initialize(RDD *p_driver, RenderingContextDriver::Device p_device, uint32_t p_frame_count, RDD::CommandQueueFamilyID p_secondary_command_queue_family, uint32_t p_secondary_command_buffers_per_frame); + void initialize(RDD *p_driver, RenderingContextDriver::Device p_device, RenderPassCreationFunction p_render_pass_creation_function, uint32_t p_frame_count, RDD::CommandQueueFamilyID p_secondary_command_queue_family, uint32_t p_secondary_command_buffers_per_frame); void finalize(); void begin(); void add_buffer_clear(RDD::BufferID p_dst, ResourceTracker *p_dst_tracker, uint32_t p_offset, uint32_t p_size); @@ -692,7 +743,8 @@ class RenderingDeviceGraph { void add_compute_list_usage(ResourceTracker *p_tracker, ResourceUsage p_usage); void add_compute_list_usages(VectorView p_trackers, VectorView p_usages); void add_compute_list_end(); - void add_draw_list_begin(RDD::RenderPassID p_render_pass, RDD::FramebufferID p_framebuffer, Rect2i p_region, VectorView p_clear_values, bool p_uses_color, bool p_uses_depth, uint32_t p_breadcrumb = 0); + void add_draw_list_begin(FramebufferCache *p_framebuffer_cache, Rect2i p_region, VectorView p_clear_attachments, VectorView p_clear_attachment_values, bool p_uses_color, bool p_uses_depth, uint32_t p_breadcrumb = 0); + void add_draw_list_begin(RDD::RenderPassID p_render_pass, RDD::FramebufferID p_framebuffer, Rect2i p_region, VectorView p_clear_attachments, VectorView p_clear_attachment_values, bool p_uses_color, bool p_uses_depth, uint32_t p_breadcrumb = 0); void add_draw_list_bind_index_buffer(RDD::BufferID p_buffer, RDD::IndexBufferFormat p_format, uint32_t p_offset); void add_draw_list_bind_pipeline(RDD::PipelineID p_pipeline, BitField p_pipeline_stage_bits); void add_draw_list_bind_uniform_set(RDD::ShaderID p_shader, RDD::UniformSetID p_uniform_set, uint32_t set_index); @@ -724,7 +776,9 @@ class RenderingDeviceGraph { void end_label(); void end(bool p_reorder_commands, bool p_full_barriers, RDD::CommandBufferID &r_command_buffer, CommandBufferPool &r_command_buffer_pool); static ResourceTracker *resource_tracker_create(); - static void resource_tracker_free(ResourceTracker *tracker); + static void resource_tracker_free(ResourceTracker *p_tracker); + static FramebufferCache *framebuffer_cache_create(); + static void framebuffer_cache_free(RDD *p_driver, FramebufferCache *p_cache); }; using RDG = RenderingDeviceGraph;