diff options
Diffstat (limited to 'servers/rendering/rendering_device.cpp')
-rw-r--r-- | servers/rendering/rendering_device.cpp | 406 |
1 files changed, 192 insertions, 214 deletions
diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp index cd0c23564c..96f72b53d0 100644 --- a/servers/rendering/rendering_device.cpp +++ b/servers/rendering/rendering_device.cpp @@ -848,6 +848,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_discardable = format.is_discardable; texture.usage_flags = format.usage_bits & ~forced_usage_bits; texture.samples = format.samples; texture.allowed_shared_formats = format.shareable_formats; @@ -951,6 +952,7 @@ RID RenderingDevice::texture_create_shared(const TextureView &p_view, RID p_with tracker->texture_size = Size2i(texture.width, texture.height); tracker->texture_subresources = texture.barrier_range(); tracker->texture_usage = alias_format.usage_bits; + tracker->is_discardable = texture.is_discardable; tracker->reference_count = 1; texture.shared_fallback->texture_tracker = tracker; texture.shared_fallback->revision = 0; @@ -1131,6 +1133,7 @@ RID RenderingDevice::texture_create_shared_from_slice(const TextureView &p_view, tracker->texture_size = Size2i(texture.width, texture.height); tracker->texture_subresources = slice_range; tracker->texture_usage = slice_format.usage_bits; + tracker->is_discardable = slice_format.is_discardable; tracker->reference_count = 1; texture.shared_fallback->texture_tracker = tracker; texture.shared_fallback->revision = 0; @@ -1891,6 +1894,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_discardable = tex->is_discardable; return tf; } @@ -2031,6 +2035,32 @@ Error RenderingDevice::texture_resolve_multisample(RID p_from_texture, RID p_to_ return OK; } +void RenderingDevice::texture_set_discardable(RID p_texture, bool p_discardable) { + ERR_RENDER_THREAD_GUARD(); + + Texture *texture = texture_owner.get_or_null(p_texture); + ERR_FAIL_NULL(texture); + + texture->is_discardable = p_discardable; + + if (texture->draw_tracker != nullptr) { + texture->draw_tracker->is_discardable = p_discardable; + } + + if (texture->shared_fallback != nullptr && texture->shared_fallback->texture_tracker != nullptr) { + texture->shared_fallback->texture_tracker->is_discardable = p_discardable; + } +} + +bool RenderingDevice::texture_is_discardable(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_discardable; +} + 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); @@ -2084,31 +2114,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<AttachmentFormat> &p_attachments, const Vector<FramebufferPass> &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<TextureSamples> *r_samples) { +RDD::RenderPassID RenderingDevice::_render_pass_create(RenderingDeviceDriver *p_driver, const Vector<AttachmentFormat> &p_attachments, const Vector<FramebufferPass> &p_passes, VectorView<RDD::AttachmentLoadOp> p_load_ops, VectorView<RDD::AttachmentStoreOp> p_store_ops, uint32_t p_view_count, Vector<TextureSamples> *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 @@ -2118,7 +2124,7 @@ RDD::RenderPassID RenderingDevice::_render_pass_create(const Vector<AttachmentFo attachment_last_pass.resize(p_attachments.size()); if (p_view_count > 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"); @@ -2159,17 +2165,17 @@ RDD::RenderPassID RenderingDevice::_render_pass_create(const Vector<AttachmentFo description.final_layout = RDD::TEXTURE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; } else { if (p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) { - description.load_op = initial_action_to_load_op(p_initial_action); - description.store_op = final_action_to_store_op(p_final_action); + description.load_op = p_load_ops[i]; + description.store_op = p_store_ops[i]; description.stencil_load_op = RDD::ATTACHMENT_LOAD_OP_DONT_CARE; description.stencil_store_op = RDD::ATTACHMENT_STORE_OP_DONT_CARE; description.initial_layout = RDD::TEXTURE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; description.final_layout = RDD::TEXTURE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; } else if (p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { - description.load_op = initial_action_to_load_op(p_initial_depth_action); - description.store_op = final_action_to_store_op(p_final_depth_action); - description.stencil_load_op = initial_action_to_load_op(p_initial_depth_action); - description.stencil_store_op = final_action_to_store_op(p_final_depth_action); + description.load_op = p_load_ops[i]; + description.store_op = p_store_ops[i]; + description.stencil_load_op = p_load_ops[i]; + description.stencil_store_op = p_store_ops[i]; description.initial_layout = RDD::TEXTURE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; description.final_layout = RDD::TEXTURE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; } else { @@ -2331,12 +2337,23 @@ RDD::RenderPassID RenderingDevice::_render_pass_create(const Vector<AttachmentFo } } - RDD::RenderPassID render_pass = driver->render_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<RDD::AttachmentLoadOp> p_load_ops, VectorView<RDD::AttachmentStoreOp> 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<AttachmentFormat> &p_format, uint32_t p_view_count) { FramebufferPass pass; for (int i = 0; i < p_format.size(); i++) { @@ -2351,6 +2368,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<AttachmentFormat> &p_attachments, const Vector<FramebufferPass> &p_passes, uint32_t p_view_count) { _THREAD_SAFE_METHOD_ @@ -2366,14 +2384,21 @@ RenderingDevice::FramebufferFormatID RenderingDevice::framebuffer_format_create_ } Vector<TextureSamples> 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<RDD::AttachmentLoadOp> load_ops; + LocalVector<RDD::AttachmentStoreOp> 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; @@ -2440,15 +2465,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; } @@ -2489,6 +2523,8 @@ RID RenderingDevice::framebuffer_create_multipass(const Vector<RID> &p_texture_a _THREAD_SAFE_METHOD_ Vector<AttachmentFormat> attachments; + LocalVector<RDD::TextureID> textures; + LocalVector<RDG::ResourceTracker *> trackers; attachments.resize(p_texture_attachments.size()); Size2i size; bool size_set = false; @@ -2497,6 +2533,7 @@ RID RenderingDevice::framebuffer_create_multipass(const Vector<RID> &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"); @@ -2518,6 +2555,11 @@ RID RenderingDevice::framebuffer_create_multipass(const Vector<RID> &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; } @@ -2533,11 +2575,19 @@ RID RenderingDevice::framebuffer_create_multipass(const Vector<RID> &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())); @@ -2549,6 +2599,8 @@ RID RenderingDevice::framebuffer_create_multipass(const Vector<RID> &p_texture_a } } + framebuffer_cache->render_pass_creation_user_data = framebuffer_owner.get_or_null(id); + return id; } @@ -3835,7 +3887,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, RDG::ATTACHMENT_OPERATION_CLEAR, clear_value, true, false, RDD::BreadcrumbMarker::BLIT_PASS); draw_graph.add_draw_list_set_viewport(viewport); draw_graph.add_draw_list_set_scissor(viewport); @@ -3843,150 +3895,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<RDD::TextureID> 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<Color> &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<RDD::RenderPassClearValue> clear_values; - thread_local LocalVector<RDG::ResourceTracker *> resource_trackers; - thread_local LocalVector<RDG::ResourceUsage> 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<Color> &p_clear_colors, bool p_clear_depth, float p_depth, uint32_t p_stencil) { - LocalVector<RDD::AttachmentClear> 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<Color> &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<DrawFlags> p_draw_flags, const Vector<Color> &p_clear_color_values, float p_clear_depth_value, 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."); @@ -4010,43 +3919,88 @@ 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<RDG::AttachmentOperation> operations; + thread_local LocalVector<RDD::RenderPassClearValue> clear_values; + thread_local LocalVector<RDG::ResourceTracker *> resource_trackers; + thread_local LocalVector<RDG::ResourceUsage> resource_usages; + bool uses_color = false; + bool uses_depth = false; + operations.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) { + operations[i] = RDG::ATTACHMENT_OPERATION_DEFAULT; + 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); + + RDG::AttachmentOperation operation = RDG::ATTACHMENT_OPERATION_DEFAULT; + RDD::RenderPassClearValue clear_value; + if (texture->usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) { + if (p_draw_flags.has_flag(DrawFlags(DRAW_CLEAR_COLOR_0 << color_index))) { + ERR_FAIL_COND_V_MSG(color_index >= p_clear_color_values.size(), INVALID_ID, vformat("Color texture (%d) was specified to be cleared but no color value was provided.", color_index)); + operation = RDG::ATTACHMENT_OPERATION_CLEAR; + clear_value.color = p_clear_color_values[color_index]; + } else if (p_draw_flags.has_flag(DrawFlags(DRAW_IGNORE_COLOR_0 << color_index))) { + operation = RDG::ATTACHMENT_OPERATION_IGNORE; + } + + 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_draw_flags.has_flag(DRAW_CLEAR_DEPTH) || p_draw_flags.has_flag(DRAW_CLEAR_STENCIL)) { + operation = RDG::ATTACHMENT_OPERATION_CLEAR; + clear_value.depth = p_clear_depth_value; + clear_value.stencil = p_clear_stencil_value; + } else if (p_draw_flags.has_flag(DRAW_IGNORE_DEPTH) || p_draw_flags.has_flag(DRAW_IGNORE_STENCIL)) { + operation = RDG::ATTACHMENT_OPERATION_IGNORE; } + + 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) + ")."); + + operations[i] = operation; + 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), operations, 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); @@ -5445,6 +5399,7 @@ bool RenderingDevice::_texture_make_mutable(Texture *p_texture, RID p_texture_id p_texture->draw_tracker->texture_size = Size2i(p_texture->width, p_texture->height); 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_discardable = p_texture->is_discardable; p_texture->draw_tracker->reference_count = 1; if (p_texture_id.is_valid()) { @@ -5855,13 +5810,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<Framebuffer::VersionKey, Framebuffer::Version> &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(); } @@ -6213,7 +6162,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++) { @@ -6711,6 +6660,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_discardable", "texture", "discardable"), &RenderingDevice::texture_set_discardable); + ClassDB::bind_method(D_METHOD("texture_is_discardable", "texture"), &RenderingDevice::texture_is_discardable); + 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); @@ -6772,7 +6724,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<Color>()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2()), DEFVAL(0)); + ClassDB::bind_method(D_METHOD("draw_list_begin", "framebuffer", "draw_flags", "clear_color_values", "clear_depth_value", "clear_stencil_value", "region", "breadcrumb"), &RenderingDevice::draw_list_begin, DEFVAL(DRAW_DEFAULT_ALL), DEFVAL(Vector<Color>()), DEFVAL(1.0), 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<Color>()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2()), DEFVAL(TypedArray<RID>())); #endif @@ -7296,22 +7248,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 @@ -7393,6 +7343,34 @@ void RenderingDevice::_bind_methods() { BIND_ENUM_CONSTANT(BLIT_PASS); BIND_ENUM_CONSTANT(UI_PASS); BIND_ENUM_CONSTANT(DEBUG_PASS); + + BIND_BITFIELD_FLAG(DRAW_DEFAULT_ALL); + BIND_BITFIELD_FLAG(DRAW_CLEAR_COLOR_0); + BIND_BITFIELD_FLAG(DRAW_CLEAR_COLOR_1); + BIND_BITFIELD_FLAG(DRAW_CLEAR_COLOR_2); + BIND_BITFIELD_FLAG(DRAW_CLEAR_COLOR_3); + BIND_BITFIELD_FLAG(DRAW_CLEAR_COLOR_4); + BIND_BITFIELD_FLAG(DRAW_CLEAR_COLOR_5); + BIND_BITFIELD_FLAG(DRAW_CLEAR_COLOR_6); + BIND_BITFIELD_FLAG(DRAW_CLEAR_COLOR_7); + BIND_BITFIELD_FLAG(DRAW_CLEAR_COLOR_MASK); + BIND_BITFIELD_FLAG(DRAW_CLEAR_COLOR_ALL); + BIND_BITFIELD_FLAG(DRAW_IGNORE_COLOR_0); + BIND_BITFIELD_FLAG(DRAW_IGNORE_COLOR_1); + BIND_BITFIELD_FLAG(DRAW_IGNORE_COLOR_2); + BIND_BITFIELD_FLAG(DRAW_IGNORE_COLOR_3); + BIND_BITFIELD_FLAG(DRAW_IGNORE_COLOR_4); + BIND_BITFIELD_FLAG(DRAW_IGNORE_COLOR_5); + BIND_BITFIELD_FLAG(DRAW_IGNORE_COLOR_6); + BIND_BITFIELD_FLAG(DRAW_IGNORE_COLOR_7); + BIND_BITFIELD_FLAG(DRAW_IGNORE_COLOR_MASK); + BIND_BITFIELD_FLAG(DRAW_IGNORE_COLOR_ALL); + BIND_BITFIELD_FLAG(DRAW_CLEAR_DEPTH); + BIND_BITFIELD_FLAG(DRAW_IGNORE_DEPTH); + BIND_BITFIELD_FLAG(DRAW_CLEAR_STENCIL); + BIND_BITFIELD_FLAG(DRAW_IGNORE_STENCIL); + BIND_BITFIELD_FLAG(DRAW_CLEAR_ALL); + BIND_BITFIELD_FLAG(DRAW_IGNORE_ALL); } void RenderingDevice::make_current() { |