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 184237257c9..397dec3d5f0 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -3293,9 +3293,8 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend uniforms.push_back(u); } { - RD::Uniform u; - u.binding = 7; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + Vector textures; + textures.resize(scene_state.max_lightmaps * 2); RID default_tex = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); for (uint32_t i = 0; i < scene_state.max_lightmaps * 2; i++) { @@ -3315,14 +3314,14 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend if (texture.is_valid()) { RID rd_texture = texture_storage->texture_get_rd_texture(texture); - u.append_id(rd_texture); + textures.write[i] = rd_texture; continue; } } - u.append_id(default_tex); + textures.write[i] = default_tex; } - + RD::Uniform u(RD::UNIFORM_TYPE_TEXTURE, 7, textures); uniforms.push_back(u); } { diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index cc6a630dbfc..0264d74de33 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -1022,8 +1022,7 @@ void RendererCanvasRenderRD::light_update_shadow(RID p_rid, int p_shadow_index, cl->shadow.z_far = p_far; cl->shadow.y_offset = float(p_shadow_index * 2 + 1) / float(state.max_lights_per_render * 2); - Vector cc; - cc.push_back(Color(p_far, p_far, p_far, 1.0)); + Color cc = Color(p_far, p_far, p_far, 1.0); // First, do a culling pass and record what occluders need to be drawn for this light. static thread_local LocalVector occluders; @@ -1076,7 +1075,7 @@ void RendererCanvasRenderRD::light_update_shadow(RID p_rid, int p_shadow_index, } 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::DRAW_CLEAR_ALL, cc, 1.0f, 0, rect); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(state.shadow_fb, RD::DRAW_CLEAR_ALL, VectorView(&cc, 1), 1.0f, 0, rect); if (state.shadow_occluder_buffer.is_valid()) { RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, shadow_render.render_pipelines[SHADOW_RENDER_MODE_POSITIONAL_SHADOW]); @@ -2220,7 +2219,7 @@ void RendererCanvasRenderRD::_render_batch_items(RenderTarget p_to_render_target RID framebuffer; RID fb_uniform_set; bool clear = false; - Vector clear_colors; + Color clear_color; if (p_to_backbuffer) { framebuffer = texture_storage->render_target_get_rd_backbuffer_framebuffer(p_to_render_target.render_target); @@ -2231,7 +2230,7 @@ void RendererCanvasRenderRD::_render_batch_items(RenderTarget p_to_render_target if (texture_storage->render_target_is_clear_requested(p_to_render_target.render_target)) { clear = true; - clear_colors.push_back(texture_storage->render_target_get_clear_request_color(p_to_render_target.render_target)); + clear_color = texture_storage->render_target_get_clear_request_color(p_to_render_target.render_target); texture_storage->render_target_disable_clear_request(p_to_render_target.render_target); } // TODO: Obtain from framebuffer format eventually when this is implemented. @@ -2244,7 +2243,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::DRAW_CLEAR_COLOR_0 : RD::DRAW_DEFAULT_ALL, clear_colors, 1.0f, 0, Rect2(), RDD::BreadcrumbMarker::UI_PASS); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, clear ? RD::DRAW_CLEAR_COLOR_0 : RD::DRAW_DEFAULT_ALL, clear_color, 1.0f, 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_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h index 8250bf80564..23b293767c8 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h @@ -525,7 +525,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender { uint32_t flags = 0; }; - HashMap> texture_info_map; + HashMap, HashMapComparatorDefault, PagedAllocator>> texture_info_map; // per-frame buffers struct DataBuffer { diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp index 950a04b5dc9..13b8db1ebfa 100644 --- a/servers/rendering/rendering_device.cpp +++ b/servers/rendering/rendering_device.cpp @@ -432,9 +432,9 @@ void RenderingDevice::_staging_buffer_execute_required_action(StagingBuffers &p_ Error RenderingDevice::buffer_copy(RID p_src_buffer, RID p_dst_buffer, uint32_t p_src_offset, uint32_t p_dst_offset, uint32_t p_size) { ERR_RENDER_THREAD_GUARD_V(ERR_UNAVAILABLE); - ERR_FAIL_COND_V_MSG(draw_list, ERR_INVALID_PARAMETER, + ERR_FAIL_COND_V_MSG(draw_list.active, ERR_INVALID_PARAMETER, "Copying buffers is forbidden during creation of a draw list"); - ERR_FAIL_COND_V_MSG(compute_list, ERR_INVALID_PARAMETER, + ERR_FAIL_COND_V_MSG(compute_list.active, ERR_INVALID_PARAMETER, "Copying buffers is forbidden during creation of a compute list"); Buffer *src_buffer = _get_buffer_from_owner(p_src_buffer); @@ -474,10 +474,9 @@ Error RenderingDevice::buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p ERR_RENDER_THREAD_GUARD_V(ERR_UNAVAILABLE); copy_bytes_count += p_size; - - ERR_FAIL_COND_V_MSG(draw_list, ERR_INVALID_PARAMETER, + ERR_FAIL_COND_V_MSG(draw_list.active, ERR_INVALID_PARAMETER, "Updating buffers is forbidden during creation of a draw list"); - ERR_FAIL_COND_V_MSG(compute_list, ERR_INVALID_PARAMETER, + ERR_FAIL_COND_V_MSG(compute_list.active, ERR_INVALID_PARAMETER, "Updating buffers is forbidden during creation of a compute list"); Buffer *buffer = _get_buffer_from_owner(p_buffer); @@ -561,9 +560,9 @@ Error RenderingDevice::buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p Error RenderingDevice::driver_callback_add(RDD::DriverCallback p_callback, void *p_userdata, VectorView p_resources) { ERR_RENDER_THREAD_GUARD_V(ERR_UNAVAILABLE); - ERR_FAIL_COND_V_MSG(draw_list, ERR_INVALID_PARAMETER, + ERR_FAIL_COND_V_MSG(draw_list.active, ERR_INVALID_PARAMETER, "Driver callback is forbidden during creation of a draw list"); - ERR_FAIL_COND_V_MSG(compute_list, ERR_INVALID_PARAMETER, + ERR_FAIL_COND_V_MSG(compute_list.active, ERR_INVALID_PARAMETER, "Driver callback is forbidden during creation of a compute list"); thread_local LocalVector trackers; @@ -632,9 +631,9 @@ Error RenderingDevice::buffer_clear(RID p_buffer, uint32_t p_offset, uint32_t p_ ERR_FAIL_COND_V_MSG((p_size % 4) != 0, ERR_INVALID_PARAMETER, "Size must be a multiple of four"); - ERR_FAIL_COND_V_MSG(draw_list, ERR_INVALID_PARAMETER, + ERR_FAIL_COND_V_MSG(draw_list.active, ERR_INVALID_PARAMETER, "Updating buffers in is forbidden during creation of a draw list"); - ERR_FAIL_COND_V_MSG(compute_list, ERR_INVALID_PARAMETER, + ERR_FAIL_COND_V_MSG(compute_list.active, ERR_INVALID_PARAMETER, "Updating buffers is forbidden during creation of a compute list"); Buffer *buffer = _get_buffer_from_owner(p_buffer); @@ -1542,7 +1541,7 @@ Error RenderingDevice::_texture_initialize(RID p_texture, uint32_t p_layer, cons Error RenderingDevice::texture_update(RID p_texture, uint32_t p_layer, const Vector &p_data) { ERR_RENDER_THREAD_GUARD_V(ERR_UNAVAILABLE); - ERR_FAIL_COND_V_MSG(draw_list || compute_list, ERR_INVALID_PARAMETER, "Updating textures is forbidden during creation of a draw or compute list"); + ERR_FAIL_COND_V_MSG(draw_list.active || compute_list.active, ERR_INVALID_PARAMETER, "Updating textures is forbidden during creation of a draw or compute list"); Texture *texture = texture_owner.get_or_null(p_texture); ERR_FAIL_NULL_V(texture, ERR_INVALID_PARAMETER); @@ -4233,8 +4232,8 @@ Error RenderingDevice::screen_free(DisplayServer::WindowID p_screen) { RenderingDevice::DrawListID RenderingDevice::draw_list_begin_for_screen(DisplayServer::WindowID p_screen, const Color &p_clear_color) { 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."); - ERR_FAIL_COND_V_MSG(compute_list != nullptr, INVALID_ID, "Only one draw/compute list can be active at the same time."); + ERR_FAIL_COND_V_MSG(draw_list.active, INVALID_ID, "Only one draw list can be active at the same time."); + ERR_FAIL_COND_V_MSG(compute_list.active, INVALID_ID, "Only one draw/compute list can be active at the same time."); RenderingContextDriver::SurfaceID surface = context->surface_get_from_window(p_screen); HashMap::ConstIterator sc_it = screen_swap_chains.find(p_screen); @@ -4245,7 +4244,7 @@ RenderingDevice::DrawListID RenderingDevice::draw_list_begin_for_screen(DisplayS Rect2i viewport = Rect2i(0, 0, context->surface_get_width(surface), context->surface_get_height(surface)); - _draw_list_allocate(viewport, 0); + _draw_list_start(viewport); #ifdef DEBUG_ENABLED draw_list_framebuffer_format = screen_get_framebuffer_format(p_screen); #endif @@ -4263,10 +4262,14 @@ RenderingDevice::DrawListID RenderingDevice::draw_list_begin_for_screen(DisplayS return int64_t(ID_TYPE_DRAW_LIST) << ID_BASE_SHIFT; } -RenderingDevice::DrawListID RenderingDevice::draw_list_begin(RID p_framebuffer, BitField p_draw_flags, const Vector &p_clear_color_values, float p_clear_depth_value, uint32_t p_clear_stencil_value, const Rect2 &p_region, uint32_t p_breadcrumb) { +RenderingDevice::DrawListID RenderingDevice::_draw_list_begin_bind(RID p_framebuffer, BitField p_draw_flags, const Vector &p_clear_color_values, float p_clear_depth_value, uint32_t p_clear_stencil_value, const Rect2 &p_region, uint32_t p_breadcrumb) { + return draw_list_begin(p_framebuffer, p_draw_flags, p_clear_color_values, p_clear_depth_value, p_clear_stencil_value, p_region, p_breadcrumb); +} + +RenderingDevice::DrawListID RenderingDevice::draw_list_begin(RID p_framebuffer, BitField p_draw_flags, VectorView 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."); + ERR_FAIL_COND_V_MSG(draw_list.active, INVALID_ID, "Only one draw list can be active at the same time."); Framebuffer *framebuffer = framebuffer_owner.get_or_null(p_framebuffer); ERR_FAIL_NULL_V(framebuffer, INVALID_ID); @@ -4360,7 +4363,7 @@ RenderingDevice::DrawListID RenderingDevice::draw_list_begin(RID p_framebuffer, draw_list_bound_textures.push_back(framebuffer->texture_ids[i]); } - _draw_list_allocate(Rect2i(viewport_offset, viewport_size), 0); + _draw_list_start(Rect2i(viewport_offset, viewport_size)); #ifdef DEBUG_ENABLED draw_list_framebuffer_format = framebuffer->format_id; #endif @@ -4382,28 +4385,10 @@ Error RenderingDevice::draw_list_begin_split(RID p_framebuffer, uint32_t p_split } #endif -RenderingDevice::DrawList *RenderingDevice::_get_draw_list_ptr(DrawListID p_id) { - if (p_id < 0) { - return nullptr; - } - - if (!draw_list) { - return nullptr; - } else if (p_id == (int64_t(ID_TYPE_DRAW_LIST) << ID_BASE_SHIFT)) { - return draw_list; - } else { - return nullptr; - } -} - void RenderingDevice::draw_list_set_blend_constants(DrawListID p_list, const Color &p_color) { ERR_RENDER_THREAD_GUARD(); - DrawList *dl = _get_draw_list_ptr(p_list); - ERR_FAIL_NULL(dl); -#ifdef DEBUG_ENABLED - ERR_FAIL_COND_MSG(!dl->validation.active, "Submitted Draw Lists can no longer be modified."); -#endif + ERR_FAIL_COND(!draw_list.active); draw_graph.add_draw_list_set_blend_constants(p_color); } @@ -4411,11 +4396,7 @@ void RenderingDevice::draw_list_set_blend_constants(DrawListID p_list, const Col void RenderingDevice::draw_list_bind_render_pipeline(DrawListID p_list, RID p_render_pipeline) { ERR_RENDER_THREAD_GUARD(); - DrawList *dl = _get_draw_list_ptr(p_list); - ERR_FAIL_NULL(dl); -#ifdef DEBUG_ENABLED - ERR_FAIL_COND_MSG(!dl->validation.active, "Submitted Draw Lists can no longer be modified."); -#endif + ERR_FAIL_COND(!draw_list.active); const RenderPipeline *pipeline = render_pipeline_owner.get_or_null(p_render_pipeline); ERR_FAIL_NULL(pipeline); @@ -4423,25 +4404,25 @@ void RenderingDevice::draw_list_bind_render_pipeline(DrawListID p_list, RID p_re ERR_FAIL_COND(pipeline->validation.framebuffer_format != draw_list_framebuffer_format && pipeline->validation.render_pass != draw_list_current_subpass); #endif - if (p_render_pipeline == dl->state.pipeline) { + if (p_render_pipeline == draw_list.state.pipeline) { return; // Redundant state, return. } - dl->state.pipeline = p_render_pipeline; + draw_list.state.pipeline = p_render_pipeline; draw_graph.add_draw_list_bind_pipeline(pipeline->driver_id, pipeline->stage_bits); - if (dl->state.pipeline_shader != pipeline->shader) { + if (draw_list.state.pipeline_shader != pipeline->shader) { // Shader changed, so descriptor sets may become incompatible. uint32_t pcount = pipeline->set_formats.size(); // Formats count in this pipeline. - dl->state.set_count = MAX(dl->state.set_count, pcount); + draw_list.state.set_count = MAX(draw_list.state.set_count, pcount); const uint32_t *pformats = pipeline->set_formats.ptr(); // Pipeline set formats. uint32_t first_invalid_set = UINT32_MAX; // All valid by default. - if (pipeline->push_constant_size != dl->state.pipeline_push_constant_size) { + if (pipeline->push_constant_size != draw_list.state.pipeline_push_constant_size) { // All sets must be invalidated as the pipeline layout is not compatible if the push constant range is different. - dl->state.pipeline_push_constant_size = pipeline->push_constant_size; + draw_list.state.pipeline_push_constant_size = pipeline->push_constant_size; first_invalid_set = 0; } else { switch (driver->api_trait_get(RDD::API_TRAIT_SHADER_CHANGE_INVALIDATION)) { @@ -4450,14 +4431,14 @@ void RenderingDevice::draw_list_bind_render_pipeline(DrawListID p_list, RID p_re } break; case RDD::SHADER_CHANGE_INVALIDATION_INCOMPATIBLE_SETS_PLUS_CASCADE: { for (uint32_t i = 0; i < pcount; i++) { - if (dl->state.sets[i].pipeline_expected_format != pformats[i]) { + if (draw_list.state.sets[i].pipeline_expected_format != pformats[i]) { first_invalid_set = i; break; } } } break; case RDD::SHADER_CHANGE_INVALIDATION_ALL_OR_NONE_ACCORDING_TO_LAYOUT_HASH: { - if (dl->state.pipeline_shader_layout_hash != pipeline->shader_layout_hash) { + if (draw_list.state.pipeline_shader_layout_hash != pipeline->shader_layout_hash) { first_invalid_set = 0; } } break; @@ -4466,36 +4447,36 @@ void RenderingDevice::draw_list_bind_render_pipeline(DrawListID p_list, RID p_re if (pipeline->push_constant_size) { #ifdef DEBUG_ENABLED - dl->validation.pipeline_push_constant_supplied = false; + draw_list.validation.pipeline_push_constant_supplied = false; #endif } for (uint32_t i = 0; i < pcount; i++) { - dl->state.sets[i].bound = dl->state.sets[i].bound && i < first_invalid_set; - dl->state.sets[i].pipeline_expected_format = pformats[i]; + draw_list.state.sets[i].bound = draw_list.state.sets[i].bound && i < first_invalid_set; + draw_list.state.sets[i].pipeline_expected_format = pformats[i]; } - for (uint32_t i = pcount; i < dl->state.set_count; i++) { + for (uint32_t i = pcount; i < draw_list.state.set_count; i++) { // Unbind the ones above (not used) if exist. - dl->state.sets[i].bound = false; + draw_list.state.sets[i].bound = false; } - dl->state.set_count = pcount; // Update set count. + draw_list.state.set_count = pcount; // Update set count. - dl->state.pipeline_shader = pipeline->shader; - dl->state.pipeline_shader_driver_id = pipeline->shader_driver_id; - dl->state.pipeline_shader_layout_hash = pipeline->shader_layout_hash; + draw_list.state.pipeline_shader = pipeline->shader; + draw_list.state.pipeline_shader_driver_id = pipeline->shader_driver_id; + draw_list.state.pipeline_shader_layout_hash = pipeline->shader_layout_hash; } #ifdef DEBUG_ENABLED // Update render pass pipeline info. - dl->validation.pipeline_active = true; - dl->validation.pipeline_dynamic_state = pipeline->validation.dynamic_state; - dl->validation.pipeline_vertex_format = pipeline->validation.vertex_format; - dl->validation.pipeline_uses_restart_indices = pipeline->validation.uses_restart_indices; - dl->validation.pipeline_primitive_divisor = pipeline->validation.primitive_divisor; - dl->validation.pipeline_primitive_minimum = pipeline->validation.primitive_minimum; - dl->validation.pipeline_push_constant_size = pipeline->push_constant_size; + draw_list.validation.pipeline_active = true; + draw_list.validation.pipeline_dynamic_state = pipeline->validation.dynamic_state; + draw_list.validation.pipeline_vertex_format = pipeline->validation.vertex_format; + draw_list.validation.pipeline_uses_restart_indices = pipeline->validation.uses_restart_indices; + draw_list.validation.pipeline_primitive_divisor = pipeline->validation.primitive_divisor; + draw_list.validation.pipeline_primitive_minimum = pipeline->validation.primitive_minimum; + draw_list.validation.pipeline_push_constant_size = pipeline->push_constant_size; #endif } @@ -4506,24 +4487,20 @@ void RenderingDevice::draw_list_bind_uniform_set(DrawListID p_list, RID p_unifor ERR_FAIL_COND_MSG(p_index >= driver->limit_get(LIMIT_MAX_BOUND_UNIFORM_SETS) || p_index >= MAX_UNIFORM_SETS, "Attempting to bind a descriptor set (" + itos(p_index) + ") greater than what the hardware supports (" + itos(driver->limit_get(LIMIT_MAX_BOUND_UNIFORM_SETS)) + ")."); #endif - DrawList *dl = _get_draw_list_ptr(p_list); - ERR_FAIL_NULL(dl); -#ifdef DEBUG_ENABLED - ERR_FAIL_COND_MSG(!dl->validation.active, "Submitted Draw Lists can no longer be modified."); -#endif + ERR_FAIL_COND(!draw_list.active); const UniformSet *uniform_set = uniform_set_owner.get_or_null(p_uniform_set); ERR_FAIL_NULL(uniform_set); - if (p_index > dl->state.set_count) { - dl->state.set_count = p_index; + if (p_index > draw_list.state.set_count) { + draw_list.state.set_count = p_index; } - dl->state.sets[p_index].uniform_set_driver_id = uniform_set->driver_id; // Update set pointer. - dl->state.sets[p_index].bound = false; // Needs rebind. - dl->state.sets[p_index].uniform_set_format = uniform_set->format; - dl->state.sets[p_index].uniform_set = p_uniform_set; + draw_list.state.sets[p_index].uniform_set_driver_id = uniform_set->driver_id; // Update set pointer. + draw_list.state.sets[p_index].bound = false; // Needs rebind. + draw_list.state.sets[p_index].uniform_set_format = uniform_set->format; + draw_list.state.sets[p_index].uniform_set = p_uniform_set; #ifdef DEBUG_ENABLED { // Validate that textures bound are not attached as framebuffer bindings. @@ -4544,28 +4521,24 @@ void RenderingDevice::draw_list_bind_uniform_set(DrawListID p_list, RID p_unifor void RenderingDevice::draw_list_bind_vertex_array(DrawListID p_list, RID p_vertex_array) { ERR_RENDER_THREAD_GUARD(); - DrawList *dl = _get_draw_list_ptr(p_list); - ERR_FAIL_NULL(dl); -#ifdef DEBUG_ENABLED - ERR_FAIL_COND_MSG(!dl->validation.active, "Submitted Draw Lists can no longer be modified."); -#endif + ERR_FAIL_COND(!draw_list.active); VertexArray *vertex_array = vertex_array_owner.get_or_null(p_vertex_array); ERR_FAIL_NULL(vertex_array); - if (dl->state.vertex_array == p_vertex_array) { + if (draw_list.state.vertex_array == p_vertex_array) { return; // Already set. } _check_transfer_worker_vertex_array(vertex_array); - dl->state.vertex_array = p_vertex_array; + draw_list.state.vertex_array = p_vertex_array; #ifdef DEBUG_ENABLED - dl->validation.vertex_format = vertex_array->description; - dl->validation.vertex_max_instances_allowed = vertex_array->max_instances_allowed; + draw_list.validation.vertex_format = vertex_array->description; + draw_list.validation.vertex_max_instances_allowed = vertex_array->max_instances_allowed; #endif - dl->validation.vertex_array_size = vertex_array->vertex_count; + draw_list.validation.vertex_array_size = vertex_array->vertex_count; draw_graph.add_draw_list_bind_vertex_buffers(vertex_array->buffers, vertex_array->offsets); @@ -4577,26 +4550,22 @@ void RenderingDevice::draw_list_bind_vertex_array(DrawListID p_list, RID p_verte void RenderingDevice::draw_list_bind_index_array(DrawListID p_list, RID p_index_array) { ERR_RENDER_THREAD_GUARD(); - DrawList *dl = _get_draw_list_ptr(p_list); - ERR_FAIL_NULL(dl); -#ifdef DEBUG_ENABLED - ERR_FAIL_COND_MSG(!dl->validation.active, "Submitted Draw Lists can no longer be modified."); -#endif + ERR_FAIL_COND(!draw_list.active); IndexArray *index_array = index_array_owner.get_or_null(p_index_array); ERR_FAIL_NULL(index_array); - if (dl->state.index_array == p_index_array) { + if (draw_list.state.index_array == p_index_array) { return; // Already set. } _check_transfer_worker_index_array(index_array); - dl->state.index_array = p_index_array; + draw_list.state.index_array = p_index_array; #ifdef DEBUG_ENABLED - dl->validation.index_array_max_index = index_array->max_index; + draw_list.validation.index_array_max_index = index_array->max_index; #endif - dl->validation.index_array_count = index_array->indices; + draw_list.validation.index_array_count = index_array->indices; const uint64_t offset_bytes = index_array->offset * (index_array->format == INDEX_BUFFER_FORMAT_UINT16 ? sizeof(uint16_t) : sizeof(uint32_t)); draw_graph.add_draw_list_bind_index_buffer(index_array->driver_id, index_array->format, offset_bytes); @@ -4609,11 +4578,7 @@ void RenderingDevice::draw_list_bind_index_array(DrawListID p_list, RID p_index_ void RenderingDevice::draw_list_set_line_width(DrawListID p_list, float p_width) { ERR_RENDER_THREAD_GUARD(); - DrawList *dl = _get_draw_list_ptr(p_list); - ERR_FAIL_NULL(dl); -#ifdef DEBUG_ENABLED - ERR_FAIL_COND_MSG(!dl->validation.active, "Submitted Draw Lists can no longer be modified."); -#endif + ERR_FAIL_COND(!draw_list.active); draw_graph.add_draw_list_set_line_width(p_width); } @@ -4621,137 +4586,128 @@ void RenderingDevice::draw_list_set_line_width(DrawListID p_list, float p_width) void RenderingDevice::draw_list_set_push_constant(DrawListID p_list, const void *p_data, uint32_t p_data_size) { ERR_RENDER_THREAD_GUARD(); - DrawList *dl = _get_draw_list_ptr(p_list); - ERR_FAIL_NULL(dl); + ERR_FAIL_COND(!draw_list.active); #ifdef DEBUG_ENABLED - ERR_FAIL_COND_MSG(!dl->validation.active, "Submitted Draw Lists can no longer be modified."); + ERR_FAIL_COND_MSG(p_data_size != draw_list.validation.pipeline_push_constant_size, + "This render pipeline requires (" + itos(draw_list.validation.pipeline_push_constant_size) + ") bytes of push constant data, supplied: (" + itos(p_data_size) + ")"); #endif -#ifdef DEBUG_ENABLED - ERR_FAIL_COND_MSG(p_data_size != dl->validation.pipeline_push_constant_size, - "This render pipeline requires (" + itos(dl->validation.pipeline_push_constant_size) + ") bytes of push constant data, supplied: (" + itos(p_data_size) + ")"); -#endif - - draw_graph.add_draw_list_set_push_constant(dl->state.pipeline_shader_driver_id, p_data, p_data_size); + draw_graph.add_draw_list_set_push_constant(draw_list.state.pipeline_shader_driver_id, p_data, p_data_size); #ifdef DEBUG_ENABLED - dl->validation.pipeline_push_constant_supplied = true; + draw_list.validation.pipeline_push_constant_supplied = true; #endif } void RenderingDevice::draw_list_draw(DrawListID p_list, bool p_use_indices, uint32_t p_instances, uint32_t p_procedural_vertices) { ERR_RENDER_THREAD_GUARD(); - DrawList *dl = _get_draw_list_ptr(p_list); - ERR_FAIL_NULL(dl); -#ifdef DEBUG_ENABLED - ERR_FAIL_COND_MSG(!dl->validation.active, "Submitted Draw Lists can no longer be modified."); -#endif + ERR_FAIL_COND(!draw_list.active); #ifdef DEBUG_ENABLED - ERR_FAIL_COND_MSG(!dl->validation.pipeline_active, + ERR_FAIL_COND_MSG(!draw_list.validation.pipeline_active, "No render pipeline was set before attempting to draw."); - if (dl->validation.pipeline_vertex_format != INVALID_ID) { + if (draw_list.validation.pipeline_vertex_format != INVALID_ID) { // Pipeline uses vertices, validate format. - ERR_FAIL_COND_MSG(dl->validation.vertex_format == INVALID_ID, + ERR_FAIL_COND_MSG(draw_list.validation.vertex_format == INVALID_ID, "No vertex array was bound, and render pipeline expects vertices."); // Make sure format is right. - ERR_FAIL_COND_MSG(dl->validation.pipeline_vertex_format != dl->validation.vertex_format, + ERR_FAIL_COND_MSG(draw_list.validation.pipeline_vertex_format != draw_list.validation.vertex_format, "The vertex format used to create the pipeline does not match the vertex format bound."); // Make sure number of instances is valid. - ERR_FAIL_COND_MSG(p_instances > dl->validation.vertex_max_instances_allowed, - "Number of instances requested (" + itos(p_instances) + " is larger than the maximum number supported by the bound vertex array (" + itos(dl->validation.vertex_max_instances_allowed) + ")."); + ERR_FAIL_COND_MSG(p_instances > draw_list.validation.vertex_max_instances_allowed, + "Number of instances requested (" + itos(p_instances) + " is larger than the maximum number supported by the bound vertex array (" + itos(draw_list.validation.vertex_max_instances_allowed) + ")."); } - if (dl->validation.pipeline_push_constant_size > 0) { + if (draw_list.validation.pipeline_push_constant_size > 0) { // Using push constants, check that they were supplied. - ERR_FAIL_COND_MSG(!dl->validation.pipeline_push_constant_supplied, + ERR_FAIL_COND_MSG(!draw_list.validation.pipeline_push_constant_supplied, "The shader in this pipeline requires a push constant to be set before drawing, but it's not present."); } #endif #ifdef DEBUG_ENABLED - for (uint32_t i = 0; i < dl->state.set_count; i++) { - if (dl->state.sets[i].pipeline_expected_format == 0) { + for (uint32_t i = 0; i < draw_list.state.set_count; i++) { + if (draw_list.state.sets[i].pipeline_expected_format == 0) { // Nothing expected by this pipeline. continue; } - if (dl->state.sets[i].pipeline_expected_format != dl->state.sets[i].uniform_set_format) { - if (dl->state.sets[i].uniform_set_format == 0) { + if (draw_list.state.sets[i].pipeline_expected_format != draw_list.state.sets[i].uniform_set_format) { + if (draw_list.state.sets[i].uniform_set_format == 0) { ERR_FAIL_MSG("Uniforms were never supplied for set (" + itos(i) + ") at the time of drawing, which are required by the pipeline."); - } else if (uniform_set_owner.owns(dl->state.sets[i].uniform_set)) { - UniformSet *us = uniform_set_owner.get_or_null(dl->state.sets[i].uniform_set); - ERR_FAIL_MSG("Uniforms supplied for set (" + itos(i) + "):\n" + _shader_uniform_debug(us->shader_id, us->shader_set) + "\nare not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n" + _shader_uniform_debug(dl->state.pipeline_shader)); + } else if (uniform_set_owner.owns(draw_list.state.sets[i].uniform_set)) { + UniformSet *us = uniform_set_owner.get_or_null(draw_list.state.sets[i].uniform_set); + ERR_FAIL_MSG("Uniforms supplied for set (" + itos(i) + "):\n" + _shader_uniform_debug(us->shader_id, us->shader_set) + "\nare not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n" + _shader_uniform_debug(draw_list.state.pipeline_shader)); } else { - ERR_FAIL_MSG("Uniforms supplied for set (" + itos(i) + ", which was just freed) are not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n" + _shader_uniform_debug(dl->state.pipeline_shader)); + ERR_FAIL_MSG("Uniforms supplied for set (" + itos(i) + ", which was just freed) are not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n" + _shader_uniform_debug(draw_list.state.pipeline_shader)); } } } #endif thread_local LocalVector valid_descriptor_ids; valid_descriptor_ids.clear(); - valid_descriptor_ids.resize(dl->state.set_count); + valid_descriptor_ids.resize(draw_list.state.set_count); uint32_t valid_set_count = 0; uint32_t first_set_index = 0; uint32_t last_set_index = 0; bool found_first_set = false; - for (uint32_t i = 0; i < dl->state.set_count; i++) { - if (dl->state.sets[i].pipeline_expected_format == 0) { + for (uint32_t i = 0; i < draw_list.state.set_count; i++) { + if (draw_list.state.sets[i].pipeline_expected_format == 0) { continue; // Nothing expected by this pipeline. } - if (!dl->state.sets[i].bound && !found_first_set) { + if (!draw_list.state.sets[i].bound && !found_first_set) { first_set_index = i; found_first_set = true; } // Prepare descriptor sets if the API doesn't use pipeline barriers. if (!driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) { - draw_graph.add_draw_list_uniform_set_prepare_for_use(dl->state.pipeline_shader_driver_id, dl->state.sets[i].uniform_set_driver_id, i); + draw_graph.add_draw_list_uniform_set_prepare_for_use(draw_list.state.pipeline_shader_driver_id, draw_list.state.sets[i].uniform_set_driver_id, i); } } // Bind descriptor sets. - for (uint32_t i = first_set_index; i < dl->state.set_count; i++) { - if (dl->state.sets[i].pipeline_expected_format == 0) { + for (uint32_t i = first_set_index; i < draw_list.state.set_count; i++) { + if (draw_list.state.sets[i].pipeline_expected_format == 0) { continue; // Nothing expected by this pipeline. } - if (!dl->state.sets[i].bound) { + if (!draw_list.state.sets[i].bound) { // Batch contiguous descriptor sets in a single call. if (descriptor_set_batching) { // All good, see if this requires re-binding. if (i - last_set_index > 1) { // If the descriptor sets are not contiguous, bind the previous ones and start a new batch. - draw_graph.add_draw_list_bind_uniform_sets(dl->state.pipeline_shader_driver_id, valid_descriptor_ids, first_set_index, valid_set_count); + draw_graph.add_draw_list_bind_uniform_sets(draw_list.state.pipeline_shader_driver_id, valid_descriptor_ids, first_set_index, valid_set_count); first_set_index = i; valid_set_count = 1; - valid_descriptor_ids[0] = dl->state.sets[i].uniform_set_driver_id; + valid_descriptor_ids[0] = draw_list.state.sets[i].uniform_set_driver_id; } else { // Otherwise, keep storing in the current batch. - valid_descriptor_ids[valid_set_count] = dl->state.sets[i].uniform_set_driver_id; + valid_descriptor_ids[valid_set_count] = draw_list.state.sets[i].uniform_set_driver_id; valid_set_count++; } - UniformSet *uniform_set = uniform_set_owner.get_or_null(dl->state.sets[i].uniform_set); + UniformSet *uniform_set = uniform_set_owner.get_or_null(draw_list.state.sets[i].uniform_set); _uniform_set_update_shared(uniform_set); draw_graph.add_draw_list_usages(uniform_set->draw_trackers, uniform_set->draw_trackers_usage); - dl->state.sets[i].bound = true; + draw_list.state.sets[i].bound = true; last_set_index = i; } else { - draw_graph.add_draw_list_bind_uniform_set(dl->state.pipeline_shader_driver_id, dl->state.sets[i].uniform_set_driver_id, i); + draw_graph.add_draw_list_bind_uniform_set(draw_list.state.pipeline_shader_driver_id, draw_list.state.sets[i].uniform_set_driver_id, i); } } } // Bind the remaining batch. if (descriptor_set_batching && valid_set_count > 0) { - draw_graph.add_draw_list_bind_uniform_sets(dl->state.pipeline_shader_driver_id, valid_descriptor_ids, first_set_index, valid_set_count); + draw_graph.add_draw_list_bind_uniform_sets(draw_list.state.pipeline_shader_driver_id, valid_descriptor_ids, first_set_index, valid_set_count); } if (p_use_indices) { @@ -4759,20 +4715,20 @@ void RenderingDevice::draw_list_draw(DrawListID p_list, bool p_use_indices, uint ERR_FAIL_COND_MSG(p_procedural_vertices > 0, "Procedural vertices can't be used together with indices."); - ERR_FAIL_COND_MSG(!dl->validation.index_array_count, + ERR_FAIL_COND_MSG(!draw_list.validation.index_array_count, "Draw command requested indices, but no index buffer was set."); - ERR_FAIL_COND_MSG(dl->validation.pipeline_uses_restart_indices != dl->validation.index_buffer_uses_restart_indices, + ERR_FAIL_COND_MSG(draw_list.validation.pipeline_uses_restart_indices != draw_list.validation.index_buffer_uses_restart_indices, "The usage of restart indices in index buffer does not match the render primitive in the pipeline."); #endif - uint32_t to_draw = dl->validation.index_array_count; + uint32_t to_draw = draw_list.validation.index_array_count; #ifdef DEBUG_ENABLED - ERR_FAIL_COND_MSG(to_draw < dl->validation.pipeline_primitive_minimum, - "Too few indices (" + itos(to_draw) + ") for the render primitive set in the render pipeline (" + itos(dl->validation.pipeline_primitive_minimum) + ")."); + ERR_FAIL_COND_MSG(to_draw < draw_list.validation.pipeline_primitive_minimum, + "Too few indices (" + itos(to_draw) + ") for the render primitive set in the render pipeline (" + itos(draw_list.validation.pipeline_primitive_minimum) + ")."); - ERR_FAIL_COND_MSG((to_draw % dl->validation.pipeline_primitive_divisor) != 0, - "Index amount (" + itos(to_draw) + ") must be a multiple of the amount of indices required by the render primitive (" + itos(dl->validation.pipeline_primitive_divisor) + ")."); + ERR_FAIL_COND_MSG((to_draw % draw_list.validation.pipeline_primitive_divisor) != 0, + "Index amount (" + itos(to_draw) + ") must be a multiple of the amount of indices required by the render primitive (" + itos(draw_list.validation.pipeline_primitive_divisor) + ")."); #endif draw_graph.add_draw_list_draw_indexed(to_draw, p_instances, 0); @@ -4781,37 +4737,36 @@ void RenderingDevice::draw_list_draw(DrawListID p_list, bool p_use_indices, uint if (p_procedural_vertices > 0) { #ifdef DEBUG_ENABLED - ERR_FAIL_COND_MSG(dl->validation.pipeline_vertex_format != INVALID_ID, + ERR_FAIL_COND_MSG(draw_list.validation.pipeline_vertex_format != INVALID_ID, "Procedural vertices requested, but pipeline expects a vertex array."); #endif to_draw = p_procedural_vertices; } else { #ifdef DEBUG_ENABLED - ERR_FAIL_COND_MSG(dl->validation.pipeline_vertex_format == INVALID_ID, + ERR_FAIL_COND_MSG(draw_list.validation.pipeline_vertex_format == INVALID_ID, "Draw command lacks indices, but pipeline format does not use vertices."); #endif - to_draw = dl->validation.vertex_array_size; + to_draw = draw_list.validation.vertex_array_size; } #ifdef DEBUG_ENABLED - ERR_FAIL_COND_MSG(to_draw < dl->validation.pipeline_primitive_minimum, - "Too few vertices (" + itos(to_draw) + ") for the render primitive set in the render pipeline (" + itos(dl->validation.pipeline_primitive_minimum) + ")."); + ERR_FAIL_COND_MSG(to_draw < draw_list.validation.pipeline_primitive_minimum, + "Too few vertices (" + itos(to_draw) + ") for the render primitive set in the render pipeline (" + itos(draw_list.validation.pipeline_primitive_minimum) + ")."); - ERR_FAIL_COND_MSG((to_draw % dl->validation.pipeline_primitive_divisor) != 0, - "Vertex amount (" + itos(to_draw) + ") must be a multiple of the amount of vertices required by the render primitive (" + itos(dl->validation.pipeline_primitive_divisor) + ")."); + ERR_FAIL_COND_MSG((to_draw % draw_list.validation.pipeline_primitive_divisor) != 0, + "Vertex amount (" + itos(to_draw) + ") must be a multiple of the amount of vertices required by the render primitive (" + itos(draw_list.validation.pipeline_primitive_divisor) + ")."); #endif draw_graph.add_draw_list_draw(to_draw, p_instances); } - dl->state.draw_count++; + draw_list.state.draw_count++; } void RenderingDevice::draw_list_draw_indirect(DrawListID p_list, bool p_use_indices, RID p_buffer, uint32_t p_offset, uint32_t p_draw_count, uint32_t p_stride) { ERR_RENDER_THREAD_GUARD(); - DrawList *dl = _get_draw_list_ptr(p_list); - ERR_FAIL_NULL(dl); + ERR_FAIL_COND(!draw_list.active); Buffer *buffer = storage_buffer_owner.get_or_null(p_buffer); ERR_FAIL_NULL(buffer); @@ -4819,43 +4774,39 @@ void RenderingDevice::draw_list_draw_indirect(DrawListID p_list, bool p_use_indi ERR_FAIL_COND_MSG(!buffer->usage.has_flag(RDD::BUFFER_USAGE_INDIRECT_BIT), "Buffer provided was not created to do indirect dispatch."); #ifdef DEBUG_ENABLED - ERR_FAIL_COND_MSG(!dl->validation.active, "Submitted Draw Lists can no longer be modified."); -#endif - -#ifdef DEBUG_ENABLED - ERR_FAIL_COND_MSG(!dl->validation.pipeline_active, + ERR_FAIL_COND_MSG(!draw_list.validation.pipeline_active, "No render pipeline was set before attempting to draw."); - if (dl->validation.pipeline_vertex_format != INVALID_ID) { + if (draw_list.validation.pipeline_vertex_format != INVALID_ID) { // Pipeline uses vertices, validate format. - ERR_FAIL_COND_MSG(dl->validation.vertex_format == INVALID_ID, + ERR_FAIL_COND_MSG(draw_list.validation.vertex_format == INVALID_ID, "No vertex array was bound, and render pipeline expects vertices."); // Make sure format is right. - ERR_FAIL_COND_MSG(dl->validation.pipeline_vertex_format != dl->validation.vertex_format, + ERR_FAIL_COND_MSG(draw_list.validation.pipeline_vertex_format != draw_list.validation.vertex_format, "The vertex format used to create the pipeline does not match the vertex format bound."); } - if (dl->validation.pipeline_push_constant_size > 0) { + if (draw_list.validation.pipeline_push_constant_size > 0) { // Using push constants, check that they were supplied. - ERR_FAIL_COND_MSG(!dl->validation.pipeline_push_constant_supplied, + ERR_FAIL_COND_MSG(!draw_list.validation.pipeline_push_constant_supplied, "The shader in this pipeline requires a push constant to be set before drawing, but it's not present."); } #endif #ifdef DEBUG_ENABLED - for (uint32_t i = 0; i < dl->state.set_count; i++) { - if (dl->state.sets[i].pipeline_expected_format == 0) { + for (uint32_t i = 0; i < draw_list.state.set_count; i++) { + if (draw_list.state.sets[i].pipeline_expected_format == 0) { // Nothing expected by this pipeline. continue; } - if (dl->state.sets[i].pipeline_expected_format != dl->state.sets[i].uniform_set_format) { - if (dl->state.sets[i].uniform_set_format == 0) { + if (draw_list.state.sets[i].pipeline_expected_format != draw_list.state.sets[i].uniform_set_format) { + if (draw_list.state.sets[i].uniform_set_format == 0) { ERR_FAIL_MSG(vformat("Uniforms were never supplied for set (%d) at the time of drawing, which are required by the pipeline.", i)); - } else if (uniform_set_owner.owns(dl->state.sets[i].uniform_set)) { - UniformSet *us = uniform_set_owner.get_or_null(dl->state.sets[i].uniform_set); - ERR_FAIL_MSG(vformat("Uniforms supplied for set (%d):\n%s\nare not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n%s", i, _shader_uniform_debug(us->shader_id, us->shader_set), _shader_uniform_debug(dl->state.pipeline_shader))); + } else if (uniform_set_owner.owns(draw_list.state.sets[i].uniform_set)) { + UniformSet *us = uniform_set_owner.get_or_null(draw_list.state.sets[i].uniform_set); + ERR_FAIL_MSG(vformat("Uniforms supplied for set (%d):\n%s\nare not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n%s", i, _shader_uniform_debug(us->shader_id, us->shader_set), _shader_uniform_debug(draw_list.state.pipeline_shader))); } else { - ERR_FAIL_MSG(vformat("Uniforms supplied for set (%s, which was just freed) are not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n%s", i, _shader_uniform_debug(dl->state.pipeline_shader))); + ERR_FAIL_MSG(vformat("Uniforms supplied for set (%s, which was just freed) are not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n%s", i, _shader_uniform_debug(draw_list.state.pipeline_shader))); } } } @@ -4863,40 +4814,40 @@ void RenderingDevice::draw_list_draw_indirect(DrawListID p_list, bool p_use_indi // Prepare descriptor sets if the API doesn't use pipeline barriers. if (!driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) { - for (uint32_t i = 0; i < dl->state.set_count; i++) { - if (dl->state.sets[i].pipeline_expected_format == 0) { + for (uint32_t i = 0; i < draw_list.state.set_count; i++) { + if (draw_list.state.sets[i].pipeline_expected_format == 0) { // Nothing expected by this pipeline. continue; } - draw_graph.add_draw_list_uniform_set_prepare_for_use(dl->state.pipeline_shader_driver_id, dl->state.sets[i].uniform_set_driver_id, i); + draw_graph.add_draw_list_uniform_set_prepare_for_use(draw_list.state.pipeline_shader_driver_id, draw_list.state.sets[i].uniform_set_driver_id, i); } } // Bind descriptor sets. - for (uint32_t i = 0; i < dl->state.set_count; i++) { - if (dl->state.sets[i].pipeline_expected_format == 0) { + for (uint32_t i = 0; i < draw_list.state.set_count; i++) { + if (draw_list.state.sets[i].pipeline_expected_format == 0) { continue; // Nothing expected by this pipeline. } - if (!dl->state.sets[i].bound) { + if (!draw_list.state.sets[i].bound) { // All good, see if this requires re-binding. - draw_graph.add_draw_list_bind_uniform_set(dl->state.pipeline_shader_driver_id, dl->state.sets[i].uniform_set_driver_id, i); + draw_graph.add_draw_list_bind_uniform_set(draw_list.state.pipeline_shader_driver_id, draw_list.state.sets[i].uniform_set_driver_id, i); - UniformSet *uniform_set = uniform_set_owner.get_or_null(dl->state.sets[i].uniform_set); + UniformSet *uniform_set = uniform_set_owner.get_or_null(draw_list.state.sets[i].uniform_set); _uniform_set_update_shared(uniform_set); draw_graph.add_draw_list_usages(uniform_set->draw_trackers, uniform_set->draw_trackers_usage); - dl->state.sets[i].bound = true; + draw_list.state.sets[i].bound = true; } } if (p_use_indices) { #ifdef DEBUG_ENABLED - ERR_FAIL_COND_MSG(!dl->validation.index_array_count, + ERR_FAIL_COND_MSG(!draw_list.validation.index_array_count, "Draw command requested indices, but no index buffer was set."); - ERR_FAIL_COND_MSG(dl->validation.pipeline_uses_restart_indices != dl->validation.index_buffer_uses_restart_indices, + ERR_FAIL_COND_MSG(draw_list.validation.pipeline_uses_restart_indices != draw_list.validation.index_buffer_uses_restart_indices, "The usage of restart indices in index buffer does not match the render primitive in the pipeline."); #endif @@ -4909,7 +4860,7 @@ void RenderingDevice::draw_list_draw_indirect(DrawListID p_list, bool p_use_indi draw_graph.add_draw_list_draw_indirect(buffer->driver_id, p_offset, p_draw_count, p_stride); } - dl->state.draw_count++; + draw_list.state.draw_count++; if (buffer->draw_tracker != nullptr) { draw_graph.add_draw_list_usage(buffer->draw_tracker, RDG::RESOURCE_USAGE_INDIRECT_BUFFER_READ); @@ -4919,34 +4870,25 @@ void RenderingDevice::draw_list_draw_indirect(DrawListID p_list, bool p_use_indi } void RenderingDevice::draw_list_set_viewport(DrawListID p_list, const Rect2 &p_rect) { - DrawList *dl = _get_draw_list_ptr(p_list); - - ERR_FAIL_NULL(dl); -#ifdef DEBUG_ENABLED - ERR_FAIL_COND_MSG(!dl->validation.active, "Submitted Draw Lists can no longer be modified."); -#endif + ERR_FAIL_COND(!draw_list.active); if (p_rect.get_area() == 0) { return; } - dl->viewport = p_rect; + draw_list.viewport = p_rect; draw_graph.add_draw_list_set_viewport(p_rect); } void RenderingDevice::draw_list_enable_scissor(DrawListID p_list, const Rect2 &p_rect) { ERR_RENDER_THREAD_GUARD(); - DrawList *dl = _get_draw_list_ptr(p_list); + ERR_FAIL_COND(!draw_list.active); - ERR_FAIL_NULL(dl); -#ifdef DEBUG_ENABLED - ERR_FAIL_COND_MSG(!dl->validation.active, "Submitted Draw Lists can no longer be modified."); -#endif Rect2i rect = p_rect; - rect.position += dl->viewport.position; + rect.position += draw_list.viewport.position; - rect = dl->viewport.intersection(rect); + rect = draw_list.viewport.intersection(rect); if (rect.get_area() == 0) { return; @@ -4958,13 +4900,9 @@ void RenderingDevice::draw_list_enable_scissor(DrawListID p_list, const Rect2 &p void RenderingDevice::draw_list_disable_scissor(DrawListID p_list) { ERR_RENDER_THREAD_GUARD(); - DrawList *dl = _get_draw_list_ptr(p_list); - ERR_FAIL_NULL(dl); -#ifdef DEBUG_ENABLED - ERR_FAIL_COND_MSG(!dl->validation.active, "Submitted Draw Lists can no longer be modified."); -#endif + ERR_FAIL_COND(!draw_list.active); - draw_graph.add_draw_list_set_scissor(dl->viewport); + draw_graph.add_draw_list_set_scissor(draw_list.viewport); } uint32_t RenderingDevice::draw_list_get_current_pass() { @@ -4976,17 +4914,17 @@ uint32_t RenderingDevice::draw_list_get_current_pass() { RenderingDevice::DrawListID RenderingDevice::draw_list_switch_to_next_pass() { ERR_RENDER_THREAD_GUARD_V(INVALID_ID); - ERR_FAIL_NULL_V(draw_list, INVALID_ID); + ERR_FAIL_COND_V(draw_list.active, INVALID_FORMAT_ID); ERR_FAIL_COND_V(draw_list_current_subpass >= draw_list_subpass_count - 1, INVALID_FORMAT_ID); draw_list_current_subpass++; Rect2i viewport; - _draw_list_free(&viewport); + _draw_list_end(&viewport); draw_graph.add_draw_list_next_subpass(RDD::COMMAND_BUFFER_TYPE_PRIMARY); - _draw_list_allocate(viewport, draw_list_current_subpass); + _draw_list_start(viewport); return int64_t(ID_TYPE_DRAW_LIST) << ID_BASE_SHIFT; } @@ -4997,32 +4935,29 @@ Error RenderingDevice::draw_list_switch_to_next_pass_split(uint32_t p_splits, Dr } #endif -Error RenderingDevice::_draw_list_allocate(const Rect2i &p_viewport, uint32_t p_subpass) { - draw_list = memnew(DrawList); - draw_list->viewport = p_viewport; - - return OK; +void RenderingDevice::_draw_list_start(const Rect2i &p_viewport) { + draw_list.viewport = p_viewport; + draw_list.active = true; } -void RenderingDevice::_draw_list_free(Rect2i *r_last_viewport) { +void RenderingDevice::_draw_list_end(Rect2i *r_last_viewport) { if (r_last_viewport) { - *r_last_viewport = draw_list->viewport; + *r_last_viewport = draw_list.viewport; } - // Just end the list. - memdelete(draw_list); - draw_list = nullptr; + + draw_list = DrawList(); } void RenderingDevice::draw_list_end() { ERR_RENDER_THREAD_GUARD(); - ERR_FAIL_NULL_MSG(draw_list, "Immediate draw list is already inactive."); + ERR_FAIL_COND_MSG(!draw_list.active, "Immediate draw list is already inactive."); draw_graph.add_draw_list_end(); - _draw_list_free(); + _draw_list_end(); - for (int i = 0; i < draw_list_bound_textures.size(); i++) { + for (uint32_t i = 0; i < draw_list_bound_textures.size(); i++) { Texture *texture = texture_owner.get_or_null(draw_list_bound_textures[i]); ERR_CONTINUE(!texture); // Wtf. if (texture->usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) { @@ -5043,9 +4978,9 @@ void RenderingDevice::draw_list_end() { RenderingDevice::ComputeListID RenderingDevice::compute_list_begin() { ERR_RENDER_THREAD_GUARD_V(INVALID_ID); - ERR_FAIL_COND_V_MSG(compute_list != nullptr, INVALID_ID, "Only one draw/compute list can be active at the same time."); + ERR_FAIL_COND_V_MSG(compute_list.active, INVALID_ID, "Only one draw/compute list can be active at the same time."); - compute_list = memnew(ComputeList); + compute_list.active = true; draw_graph.add_compute_list_begin(); @@ -5056,26 +4991,24 @@ void RenderingDevice::compute_list_bind_compute_pipeline(ComputeListID p_list, R ERR_RENDER_THREAD_GUARD(); ERR_FAIL_COND(p_list != ID_TYPE_COMPUTE_LIST); - ERR_FAIL_NULL(compute_list); - - ComputeList *cl = compute_list; + ERR_FAIL_COND(!compute_list.active); const ComputePipeline *pipeline = compute_pipeline_owner.get_or_null(p_compute_pipeline); ERR_FAIL_NULL(pipeline); - if (p_compute_pipeline == cl->state.pipeline) { + if (p_compute_pipeline == compute_list.state.pipeline) { return; // Redundant state, return. } - cl->state.pipeline = p_compute_pipeline; + compute_list.state.pipeline = p_compute_pipeline; draw_graph.add_compute_list_bind_pipeline(pipeline->driver_id); - if (cl->state.pipeline_shader != pipeline->shader) { + if (compute_list.state.pipeline_shader != pipeline->shader) { // Shader changed, so descriptor sets may become incompatible. uint32_t pcount = pipeline->set_formats.size(); // Formats count in this pipeline. - cl->state.set_count = MAX(cl->state.set_count, pcount); + compute_list.state.set_count = MAX(compute_list.state.set_count, pcount); const uint32_t *pformats = pipeline->set_formats.ptr(); // Pipeline set formats. uint32_t first_invalid_set = UINT32_MAX; // All valid by default. @@ -5085,49 +5018,49 @@ void RenderingDevice::compute_list_bind_compute_pipeline(ComputeListID p_list, R } break; case RDD::SHADER_CHANGE_INVALIDATION_INCOMPATIBLE_SETS_PLUS_CASCADE: { for (uint32_t i = 0; i < pcount; i++) { - if (cl->state.sets[i].pipeline_expected_format != pformats[i]) { + if (compute_list.state.sets[i].pipeline_expected_format != pformats[i]) { first_invalid_set = i; break; } } } break; case RDD::SHADER_CHANGE_INVALIDATION_ALL_OR_NONE_ACCORDING_TO_LAYOUT_HASH: { - if (cl->state.pipeline_shader_layout_hash != pipeline->shader_layout_hash) { + if (compute_list.state.pipeline_shader_layout_hash != pipeline->shader_layout_hash) { first_invalid_set = 0; } } break; } for (uint32_t i = 0; i < pcount; i++) { - cl->state.sets[i].bound = cl->state.sets[i].bound && i < first_invalid_set; - cl->state.sets[i].pipeline_expected_format = pformats[i]; + compute_list.state.sets[i].bound = compute_list.state.sets[i].bound && i < first_invalid_set; + compute_list.state.sets[i].pipeline_expected_format = pformats[i]; } - for (uint32_t i = pcount; i < cl->state.set_count; i++) { + for (uint32_t i = pcount; i < compute_list.state.set_count; i++) { // Unbind the ones above (not used) if exist. - cl->state.sets[i].bound = false; + compute_list.state.sets[i].bound = false; } - cl->state.set_count = pcount; // Update set count. + compute_list.state.set_count = pcount; // Update set count. if (pipeline->push_constant_size) { #ifdef DEBUG_ENABLED - cl->validation.pipeline_push_constant_supplied = false; + compute_list.validation.pipeline_push_constant_supplied = false; #endif } - cl->state.pipeline_shader = pipeline->shader; - cl->state.pipeline_shader_driver_id = pipeline->shader_driver_id; - cl->state.pipeline_shader_layout_hash = pipeline->shader_layout_hash; - cl->state.local_group_size[0] = pipeline->local_group_size[0]; - cl->state.local_group_size[1] = pipeline->local_group_size[1]; - cl->state.local_group_size[2] = pipeline->local_group_size[2]; + compute_list.state.pipeline_shader = pipeline->shader; + compute_list.state.pipeline_shader_driver_id = pipeline->shader_driver_id; + compute_list.state.pipeline_shader_layout_hash = pipeline->shader_layout_hash; + compute_list.state.local_group_size[0] = pipeline->local_group_size[0]; + compute_list.state.local_group_size[1] = pipeline->local_group_size[1]; + compute_list.state.local_group_size[2] = pipeline->local_group_size[2]; } #ifdef DEBUG_ENABLED // Update compute pass pipeline info. - cl->validation.pipeline_active = true; - cl->validation.pipeline_push_constant_size = pipeline->push_constant_size; + compute_list.validation.pipeline_active = true; + compute_list.validation.pipeline_push_constant_size = pipeline->push_constant_size; #endif } @@ -5135,30 +5068,24 @@ void RenderingDevice::compute_list_bind_uniform_set(ComputeListID p_list, RID p_ ERR_RENDER_THREAD_GUARD(); ERR_FAIL_COND(p_list != ID_TYPE_COMPUTE_LIST); - ERR_FAIL_NULL(compute_list); - - ComputeList *cl = compute_list; + ERR_FAIL_COND(!compute_list.active); #ifdef DEBUG_ENABLED ERR_FAIL_COND_MSG(p_index >= driver->limit_get(LIMIT_MAX_BOUND_UNIFORM_SETS) || p_index >= MAX_UNIFORM_SETS, "Attempting to bind a descriptor set (" + itos(p_index) + ") greater than what the hardware supports (" + itos(driver->limit_get(LIMIT_MAX_BOUND_UNIFORM_SETS)) + ")."); #endif -#ifdef DEBUG_ENABLED - ERR_FAIL_COND_MSG(!cl->validation.active, "Submitted Compute Lists can no longer be modified."); -#endif - UniformSet *uniform_set = uniform_set_owner.get_or_null(p_uniform_set); ERR_FAIL_NULL(uniform_set); - if (p_index > cl->state.set_count) { - cl->state.set_count = p_index; + if (p_index > compute_list.state.set_count) { + compute_list.state.set_count = p_index; } - cl->state.sets[p_index].uniform_set_driver_id = uniform_set->driver_id; // Update set pointer. - cl->state.sets[p_index].bound = false; // Needs rebind. - cl->state.sets[p_index].uniform_set_format = uniform_set->format; - cl->state.sets[p_index].uniform_set = p_uniform_set; + compute_list.state.sets[p_index].uniform_set_driver_id = uniform_set->driver_id; // Update set pointer. + compute_list.state.sets[p_index].bound = false; // Needs rebind. + compute_list.state.sets[p_index].uniform_set_format = uniform_set->format; + compute_list.state.sets[p_index].uniform_set = p_uniform_set; #if 0 { // Validate that textures bound are not attached as framebuffer bindings. @@ -5180,28 +5107,22 @@ void RenderingDevice::compute_list_set_push_constant(ComputeListID p_list, const ERR_RENDER_THREAD_GUARD(); ERR_FAIL_COND(p_list != ID_TYPE_COMPUTE_LIST); - ERR_FAIL_NULL(compute_list); + ERR_FAIL_COND(!compute_list.active); ERR_FAIL_COND_MSG(p_data_size > MAX_PUSH_CONSTANT_SIZE, "Push constants can't be bigger than 128 bytes to maintain compatibility."); - ComputeList *cl = compute_list; - #ifdef DEBUG_ENABLED - ERR_FAIL_COND_MSG(!cl->validation.active, "Submitted Compute Lists can no longer be modified."); + ERR_FAIL_COND_MSG(p_data_size != compute_list.validation.pipeline_push_constant_size, + "This compute pipeline requires (" + itos(compute_list.validation.pipeline_push_constant_size) + ") bytes of push constant data, supplied: (" + itos(p_data_size) + ")"); #endif -#ifdef DEBUG_ENABLED - ERR_FAIL_COND_MSG(p_data_size != cl->validation.pipeline_push_constant_size, - "This compute pipeline requires (" + itos(cl->validation.pipeline_push_constant_size) + ") bytes of push constant data, supplied: (" + itos(p_data_size) + ")"); -#endif - - draw_graph.add_compute_list_set_push_constant(cl->state.pipeline_shader_driver_id, p_data, p_data_size); + draw_graph.add_compute_list_set_push_constant(compute_list.state.pipeline_shader_driver_id, p_data, p_data_size); // Store it in the state in case we need to restart the compute list. - memcpy(cl->state.push_constant_data, p_data, p_data_size); - cl->state.push_constant_size = p_data_size; + memcpy(compute_list.state.push_constant_data, p_data, p_data_size); + compute_list.state.push_constant_size = p_data_size; #ifdef DEBUG_ENABLED - cl->validation.pipeline_push_constant_supplied = true; + compute_list.validation.pipeline_push_constant_supplied = true; #endif } @@ -5209,9 +5130,7 @@ void RenderingDevice::compute_list_dispatch(ComputeListID p_list, uint32_t p_x_g ERR_RENDER_THREAD_GUARD(); ERR_FAIL_COND(p_list != ID_TYPE_COMPUTE_LIST); - ERR_FAIL_NULL(compute_list); - - ComputeList *cl = compute_list; + ERR_FAIL_COND(!compute_list.active); #ifdef DEBUG_ENABLED ERR_FAIL_COND_MSG(p_x_groups == 0, "Dispatch amount of X compute groups (" + itos(p_x_groups) + ") is zero."); @@ -5223,114 +5142,112 @@ void RenderingDevice::compute_list_dispatch(ComputeListID p_list, uint32_t p_x_g "Dispatch amount of Y compute groups (" + itos(p_y_groups) + ") is larger than device limit (" + itos(driver->limit_get(LIMIT_MAX_COMPUTE_WORKGROUP_COUNT_Y)) + ")"); ERR_FAIL_COND_MSG(p_z_groups > driver->limit_get(LIMIT_MAX_COMPUTE_WORKGROUP_COUNT_Z), "Dispatch amount of Z compute groups (" + itos(p_z_groups) + ") is larger than device limit (" + itos(driver->limit_get(LIMIT_MAX_COMPUTE_WORKGROUP_COUNT_Z)) + ")"); - - ERR_FAIL_COND_MSG(!cl->validation.active, "Submitted Compute Lists can no longer be modified."); #endif #ifdef DEBUG_ENABLED - ERR_FAIL_COND_MSG(!cl->validation.pipeline_active, "No compute pipeline was set before attempting to draw."); + ERR_FAIL_COND_MSG(!compute_list.validation.pipeline_active, "No compute pipeline was set before attempting to draw."); - if (cl->validation.pipeline_push_constant_size > 0) { + if (compute_list.validation.pipeline_push_constant_size > 0) { // Using push constants, check that they were supplied. - ERR_FAIL_COND_MSG(!cl->validation.pipeline_push_constant_supplied, + ERR_FAIL_COND_MSG(!compute_list.validation.pipeline_push_constant_supplied, "The shader in this pipeline requires a push constant to be set before drawing, but it's not present."); } #endif #ifdef DEBUG_ENABLED - for (uint32_t i = 0; i < cl->state.set_count; i++) { - if (cl->state.sets[i].pipeline_expected_format == 0) { + for (uint32_t i = 0; i < compute_list.state.set_count; i++) { + if (compute_list.state.sets[i].pipeline_expected_format == 0) { // Nothing expected by this pipeline. continue; } - if (cl->state.sets[i].pipeline_expected_format != cl->state.sets[i].uniform_set_format) { - if (cl->state.sets[i].uniform_set_format == 0) { + if (compute_list.state.sets[i].pipeline_expected_format != compute_list.state.sets[i].uniform_set_format) { + if (compute_list.state.sets[i].uniform_set_format == 0) { ERR_FAIL_MSG("Uniforms were never supplied for set (" + itos(i) + ") at the time of drawing, which are required by the pipeline."); - } else if (uniform_set_owner.owns(cl->state.sets[i].uniform_set)) { - UniformSet *us = uniform_set_owner.get_or_null(cl->state.sets[i].uniform_set); - ERR_FAIL_MSG("Uniforms supplied for set (" + itos(i) + "):\n" + _shader_uniform_debug(us->shader_id, us->shader_set) + "\nare not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n" + _shader_uniform_debug(cl->state.pipeline_shader)); + } else if (uniform_set_owner.owns(compute_list.state.sets[i].uniform_set)) { + UniformSet *us = uniform_set_owner.get_or_null(compute_list.state.sets[i].uniform_set); + ERR_FAIL_MSG("Uniforms supplied for set (" + itos(i) + "):\n" + _shader_uniform_debug(us->shader_id, us->shader_set) + "\nare not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n" + _shader_uniform_debug(compute_list.state.pipeline_shader)); } else { - ERR_FAIL_MSG("Uniforms supplied for set (" + itos(i) + ", which was just freed) are not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n" + _shader_uniform_debug(cl->state.pipeline_shader)); + ERR_FAIL_MSG("Uniforms supplied for set (" + itos(i) + ", which was just freed) are not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n" + _shader_uniform_debug(compute_list.state.pipeline_shader)); } } } #endif thread_local LocalVector valid_descriptor_ids; valid_descriptor_ids.clear(); - valid_descriptor_ids.resize(cl->state.set_count); + valid_descriptor_ids.resize(compute_list.state.set_count); uint32_t valid_set_count = 0; uint32_t first_set_index = 0; uint32_t last_set_index = 0; bool found_first_set = false; - for (uint32_t i = 0; i < cl->state.set_count; i++) { - if (cl->state.sets[i].pipeline_expected_format == 0) { + for (uint32_t i = 0; i < compute_list.state.set_count; i++) { + if (compute_list.state.sets[i].pipeline_expected_format == 0) { // Nothing expected by this pipeline. continue; } - if (!cl->state.sets[i].bound && !found_first_set) { + if (!compute_list.state.sets[i].bound && !found_first_set) { first_set_index = i; found_first_set = true; } // Prepare descriptor sets if the API doesn't use pipeline barriers. if (!driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) { - draw_graph.add_compute_list_uniform_set_prepare_for_use(cl->state.pipeline_shader_driver_id, cl->state.sets[i].uniform_set_driver_id, i); + draw_graph.add_compute_list_uniform_set_prepare_for_use(compute_list.state.pipeline_shader_driver_id, compute_list.state.sets[i].uniform_set_driver_id, i); } } // Bind descriptor sets. - for (uint32_t i = first_set_index; i < cl->state.set_count; i++) { - if (cl->state.sets[i].pipeline_expected_format == 0) { + for (uint32_t i = first_set_index; i < compute_list.state.set_count; i++) { + if (compute_list.state.sets[i].pipeline_expected_format == 0) { continue; // Nothing expected by this pipeline. } - if (!cl->state.sets[i].bound) { + if (!compute_list.state.sets[i].bound) { // Descriptor set batching if (descriptor_set_batching) { // All good, see if this requires re-binding. if (i - last_set_index > 1) { // If the descriptor sets are not contiguous, bind the previous ones and start a new batch. - draw_graph.add_compute_list_bind_uniform_sets(cl->state.pipeline_shader_driver_id, valid_descriptor_ids, first_set_index, valid_set_count); + draw_graph.add_compute_list_bind_uniform_sets(compute_list.state.pipeline_shader_driver_id, valid_descriptor_ids, first_set_index, valid_set_count); first_set_index = i; valid_set_count = 1; - valid_descriptor_ids[0] = cl->state.sets[i].uniform_set_driver_id; + valid_descriptor_ids[0] = compute_list.state.sets[i].uniform_set_driver_id; } else { // Otherwise, keep storing in the current batch. - valid_descriptor_ids[valid_set_count] = cl->state.sets[i].uniform_set_driver_id; + valid_descriptor_ids[valid_set_count] = compute_list.state.sets[i].uniform_set_driver_id; valid_set_count++; } last_set_index = i; } else { - draw_graph.add_compute_list_bind_uniform_set(cl->state.pipeline_shader_driver_id, cl->state.sets[i].uniform_set_driver_id, i); + draw_graph.add_compute_list_bind_uniform_set(compute_list.state.pipeline_shader_driver_id, compute_list.state.sets[i].uniform_set_driver_id, i); } - UniformSet *uniform_set = uniform_set_owner.get_or_null(cl->state.sets[i].uniform_set); + UniformSet *uniform_set = uniform_set_owner.get_or_null(compute_list.state.sets[i].uniform_set); _uniform_set_update_shared(uniform_set); draw_graph.add_compute_list_usages(uniform_set->draw_trackers, uniform_set->draw_trackers_usage); - cl->state.sets[i].bound = true; + compute_list.state.sets[i].bound = true; } } // Bind the remaining batch. if (valid_set_count > 0) { - draw_graph.add_compute_list_bind_uniform_sets(cl->state.pipeline_shader_driver_id, valid_descriptor_ids, first_set_index, valid_set_count); + draw_graph.add_compute_list_bind_uniform_sets(compute_list.state.pipeline_shader_driver_id, valid_descriptor_ids, first_set_index, valid_set_count); } draw_graph.add_compute_list_dispatch(p_x_groups, p_y_groups, p_z_groups); - cl->state.dispatch_count++; + compute_list.state.dispatch_count++; } void RenderingDevice::compute_list_dispatch_threads(ComputeListID p_list, uint32_t p_x_threads, uint32_t p_y_threads, uint32_t p_z_threads) { ERR_RENDER_THREAD_GUARD(); ERR_FAIL_COND(p_list != ID_TYPE_COMPUTE_LIST); - ERR_FAIL_NULL(compute_list); + ERR_FAIL_COND(!compute_list.active); #ifdef DEBUG_ENABLED ERR_FAIL_COND_MSG(p_x_threads == 0, "Dispatch amount of X compute threads (" + itos(p_x_threads) + ") is zero."); @@ -5338,30 +5255,27 @@ void RenderingDevice::compute_list_dispatch_threads(ComputeListID p_list, uint32 ERR_FAIL_COND_MSG(p_z_threads == 0, "Dispatch amount of Z compute threads (" + itos(p_z_threads) + ") is zero."); #endif - ComputeList *cl = compute_list; - #ifdef DEBUG_ENABLED - ERR_FAIL_COND_MSG(!cl->validation.pipeline_active, "No compute pipeline was set before attempting to draw."); + ERR_FAIL_COND_MSG(!compute_list.validation.pipeline_active, "No compute pipeline was set before attempting to draw."); - if (cl->validation.pipeline_push_constant_size > 0) { + if (compute_list.validation.pipeline_push_constant_size > 0) { // Using push constants, check that they were supplied. - ERR_FAIL_COND_MSG(!cl->validation.pipeline_push_constant_supplied, + ERR_FAIL_COND_MSG(!compute_list.validation.pipeline_push_constant_supplied, "The shader in this pipeline requires a push constant to be set before drawing, but it's not present."); } #endif - compute_list_dispatch(p_list, Math::division_round_up(p_x_threads, cl->state.local_group_size[0]), Math::division_round_up(p_y_threads, cl->state.local_group_size[1]), Math::division_round_up(p_z_threads, cl->state.local_group_size[2])); + compute_list_dispatch(p_list, Math::division_round_up(p_x_threads, compute_list.state.local_group_size[0]), Math::division_round_up(p_y_threads, compute_list.state.local_group_size[1]), Math::division_round_up(p_z_threads, compute_list.state.local_group_size[2])); } void RenderingDevice::compute_list_dispatch_indirect(ComputeListID p_list, RID p_buffer, uint32_t p_offset) { ERR_RENDER_THREAD_GUARD(); ERR_FAIL_COND(p_list != ID_TYPE_COMPUTE_LIST); - ERR_FAIL_NULL(compute_list); + ERR_FAIL_COND(!compute_list.active); - ComputeList *cl = compute_list; Buffer *buffer = storage_buffer_owner.get_or_null(p_buffer); ERR_FAIL_NULL(buffer); @@ -5370,104 +5284,100 @@ void RenderingDevice::compute_list_dispatch_indirect(ComputeListID p_list, RID p ERR_FAIL_COND_MSG(p_offset + 12 > buffer->size, "Offset provided (+12) is past the end of buffer."); #ifdef DEBUG_ENABLED - ERR_FAIL_COND_MSG(!cl->validation.active, "Submitted Compute Lists can no longer be modified."); -#endif -#ifdef DEBUG_ENABLED + ERR_FAIL_COND_MSG(!compute_list.validation.pipeline_active, "No compute pipeline was set before attempting to draw."); - ERR_FAIL_COND_MSG(!cl->validation.pipeline_active, "No compute pipeline was set before attempting to draw."); - - if (cl->validation.pipeline_push_constant_size > 0) { + if (compute_list.validation.pipeline_push_constant_size > 0) { // Using push constants, check that they were supplied. - ERR_FAIL_COND_MSG(!cl->validation.pipeline_push_constant_supplied, + ERR_FAIL_COND_MSG(!compute_list.validation.pipeline_push_constant_supplied, "The shader in this pipeline requires a push constant to be set before drawing, but it's not present."); } #endif #ifdef DEBUG_ENABLED - for (uint32_t i = 0; i < cl->state.set_count; i++) { - if (cl->state.sets[i].pipeline_expected_format == 0) { + for (uint32_t i = 0; i < compute_list.state.set_count; i++) { + if (compute_list.state.sets[i].pipeline_expected_format == 0) { // Nothing expected by this pipeline. continue; } - if (cl->state.sets[i].pipeline_expected_format != cl->state.sets[i].uniform_set_format) { - if (cl->state.sets[i].uniform_set_format == 0) { + if (compute_list.state.sets[i].pipeline_expected_format != compute_list.state.sets[i].uniform_set_format) { + if (compute_list.state.sets[i].uniform_set_format == 0) { ERR_FAIL_MSG("Uniforms were never supplied for set (" + itos(i) + ") at the time of drawing, which are required by the pipeline."); - } else if (uniform_set_owner.owns(cl->state.sets[i].uniform_set)) { - UniformSet *us = uniform_set_owner.get_or_null(cl->state.sets[i].uniform_set); - ERR_FAIL_MSG("Uniforms supplied for set (" + itos(i) + "):\n" + _shader_uniform_debug(us->shader_id, us->shader_set) + "\nare not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n" + _shader_uniform_debug(cl->state.pipeline_shader)); + } else if (uniform_set_owner.owns(compute_list.state.sets[i].uniform_set)) { + UniformSet *us = uniform_set_owner.get_or_null(compute_list.state.sets[i].uniform_set); + ERR_FAIL_MSG("Uniforms supplied for set (" + itos(i) + "):\n" + _shader_uniform_debug(us->shader_id, us->shader_set) + "\nare not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n" + _shader_uniform_debug(compute_list.state.pipeline_shader)); } else { - ERR_FAIL_MSG("Uniforms supplied for set (" + itos(i) + ", which was just freed) are not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n" + _shader_uniform_debug(cl->state.pipeline_shader)); + ERR_FAIL_MSG("Uniforms supplied for set (" + itos(i) + ", which was just freed) are not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n" + _shader_uniform_debug(compute_list.state.pipeline_shader)); } } } #endif thread_local LocalVector valid_descriptor_ids; valid_descriptor_ids.clear(); - valid_descriptor_ids.resize(cl->state.set_count); + valid_descriptor_ids.resize(compute_list.state.set_count); uint32_t valid_set_count = 0; uint32_t first_set_index = 0; uint32_t last_set_index = 0; bool found_first_set = false; - for (uint32_t i = 0; i < cl->state.set_count; i++) { - if (cl->state.sets[i].pipeline_expected_format == 0) { + for (uint32_t i = 0; i < compute_list.state.set_count; i++) { + if (compute_list.state.sets[i].pipeline_expected_format == 0) { // Nothing expected by this pipeline. continue; } - if (!cl->state.sets[i].bound && !found_first_set) { + if (!compute_list.state.sets[i].bound && !found_first_set) { first_set_index = i; found_first_set = true; } // Prepare descriptor sets if the API doesn't use pipeline barriers. if (!driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) { - draw_graph.add_compute_list_uniform_set_prepare_for_use(cl->state.pipeline_shader_driver_id, cl->state.sets[i].uniform_set_driver_id, i); + draw_graph.add_compute_list_uniform_set_prepare_for_use(compute_list.state.pipeline_shader_driver_id, compute_list.state.sets[i].uniform_set_driver_id, i); } } // Bind descriptor sets. - for (uint32_t i = first_set_index; i < cl->state.set_count; i++) { - if (cl->state.sets[i].pipeline_expected_format == 0) { + for (uint32_t i = first_set_index; i < compute_list.state.set_count; i++) { + if (compute_list.state.sets[i].pipeline_expected_format == 0) { continue; // Nothing expected by this pipeline. } - if (!cl->state.sets[i].bound) { + if (!compute_list.state.sets[i].bound) { // All good, see if this requires re-binding. if (i - last_set_index > 1) { // If the descriptor sets are not contiguous, bind the previous ones and start a new batch. - draw_graph.add_compute_list_bind_uniform_sets(cl->state.pipeline_shader_driver_id, valid_descriptor_ids, first_set_index, valid_set_count); + draw_graph.add_compute_list_bind_uniform_sets(compute_list.state.pipeline_shader_driver_id, valid_descriptor_ids, first_set_index, valid_set_count); first_set_index = i; valid_set_count = 1; - valid_descriptor_ids[0] = cl->state.sets[i].uniform_set_driver_id; + valid_descriptor_ids[0] = compute_list.state.sets[i].uniform_set_driver_id; } else { // Otherwise, keep storing in the current batch. - valid_descriptor_ids[valid_set_count] = cl->state.sets[i].uniform_set_driver_id; + valid_descriptor_ids[valid_set_count] = compute_list.state.sets[i].uniform_set_driver_id; valid_set_count++; } last_set_index = i; - UniformSet *uniform_set = uniform_set_owner.get_or_null(cl->state.sets[i].uniform_set); + UniformSet *uniform_set = uniform_set_owner.get_or_null(compute_list.state.sets[i].uniform_set); _uniform_set_update_shared(uniform_set); draw_graph.add_compute_list_usages(uniform_set->draw_trackers, uniform_set->draw_trackers_usage); - cl->state.sets[i].bound = true; + compute_list.state.sets[i].bound = true; } } // Bind the remaining batch. if (valid_set_count > 0) { - draw_graph.add_compute_list_bind_uniform_sets(cl->state.pipeline_shader_driver_id, valid_descriptor_ids, first_set_index, valid_set_count); + draw_graph.add_compute_list_bind_uniform_sets(compute_list.state.pipeline_shader_driver_id, valid_descriptor_ids, first_set_index, valid_set_count); } draw_graph.add_compute_list_dispatch_indirect(buffer->driver_id, p_offset); - cl->state.dispatch_count++; + compute_list.state.dispatch_count++; if (buffer->draw_tracker != nullptr) { draw_graph.add_compute_list_usage(buffer->draw_tracker, RDG::RESOURCE_USAGE_INDIRECT_BUFFER_READ); @@ -5479,7 +5389,7 @@ void RenderingDevice::compute_list_dispatch_indirect(ComputeListID p_list, RID p void RenderingDevice::compute_list_add_barrier(ComputeListID p_list) { ERR_RENDER_THREAD_GUARD(); - compute_list_barrier_state = compute_list->state; + compute_list_barrier_state = compute_list.state; compute_list_end(); compute_list_begin(); @@ -5501,12 +5411,11 @@ void RenderingDevice::compute_list_add_barrier(ComputeListID p_list) { void RenderingDevice::compute_list_end() { ERR_RENDER_THREAD_GUARD(); - ERR_FAIL_NULL(compute_list); + ERR_FAIL_COND(!compute_list.active); draw_graph.add_compute_list_end(); - memdelete(compute_list); - compute_list = nullptr; + compute_list = ComputeList(); } #ifndef DISABLE_DEPRECATED @@ -6397,11 +6306,11 @@ void RenderingDevice::_begin_frame(bool p_presented) { } void RenderingDevice::_end_frame() { - if (draw_list) { + if (draw_list.active) { ERR_PRINT("Found open draw list at the end of the frame, this should never happen (further drawing will likely not work)."); } - if (compute_list) { + if (compute_list.active) { ERR_PRINT("Found open compute list at the end of the frame, this should never happen (further compute will likely not work)."); } @@ -6806,8 +6715,8 @@ Error RenderingDevice::initialize(RenderingContextDriver *p_context, DisplayServ ERR_FAIL_COND_V(err, FAILED); } - draw_list = nullptr; - compute_list = nullptr; + draw_list = DrawList(); + compute_list = ComputeList(); bool project_pipeline_cache_enable = GLOBAL_GET("rendering/rendering_device/pipeline_cache/enable"); if (is_main_instance && project_pipeline_cache_enable) { @@ -6929,8 +6838,8 @@ void RenderingDevice::_free_rids(T &p_owner, const char *p_type) { void RenderingDevice::capture_timestamp(const String &p_name) { ERR_RENDER_THREAD_GUARD(); - ERR_FAIL_COND_MSG(draw_list != nullptr && draw_list->state.draw_count > 0, "Capturing timestamps during draw list creation is not allowed. Offending timestamp was: " + p_name); - ERR_FAIL_COND_MSG(compute_list != nullptr && compute_list->state.dispatch_count > 0, "Capturing timestamps during compute list creation is not allowed. Offending timestamp was: " + p_name); + ERR_FAIL_COND_MSG(draw_list.active && draw_list.state.draw_count > 0, "Capturing timestamps during draw list creation is not allowed. Offending timestamp was: " + p_name); + ERR_FAIL_COND_MSG(compute_list.active && compute_list.state.dispatch_count > 0, "Capturing timestamps during compute list creation is not allowed. Offending timestamp was: " + p_name); ERR_FAIL_COND_MSG(frames[frame].timestamp_count >= max_timestamp_query_elements, vformat("Tried capturing more timestamps than the configured maximum (%d). You can increase this limit in the project settings under 'Debug/Settings' called 'Max Timestamp Query Elements'.", max_timestamp_query_elements)); draw_graph.add_capture_timestamp(frames[frame].timestamp_pool, frames[frame].timestamp_count); @@ -7339,7 +7248,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", "draw_flags", "clear_color_values", "clear_depth_value", "clear_stencil_value", "region", "breadcrumb"), &RenderingDevice::draw_list_begin, DEFVAL(DRAW_DEFAULT_ALL), DEFVAL(Vector()), 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_bind, DEFVAL(DRAW_DEFAULT_ALL), DEFVAL(Vector()), 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()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2()), DEFVAL(TypedArray())); #endif diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h index 3b06fc6dfb0..2a6ecbe5d8b 100644 --- a/servers/rendering/rendering_device.h +++ b/servers/rendering/rendering_device.h @@ -1173,7 +1173,7 @@ private: struct DrawList { Rect2i viewport; - bool viewport_set = false; + bool active = false; struct SetState { uint32_t pipeline_expected_format = 0; @@ -1198,7 +1198,6 @@ private: #ifdef DEBUG_ENABLED struct Validation { - bool active = true; // Means command buffer was not closed, so you can keep adding things. // Actual render pass values. uint32_t dynamic_state = 0; VertexFormatID vertex_format = INVALID_ID; @@ -1229,18 +1228,17 @@ private: #endif }; - DrawList *draw_list = nullptr; + DrawList draw_list; uint32_t draw_list_subpass_count = 0; #ifdef DEBUG_ENABLED FramebufferFormatID draw_list_framebuffer_format = INVALID_ID; #endif uint32_t draw_list_current_subpass = 0; - Vector draw_list_bound_textures; + LocalVector draw_list_bound_textures; - _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); + void _draw_list_start(const Rect2i &p_viewport); + void _draw_list_end(Rect2i *r_last_viewport = nullptr); public: enum DrawFlags { @@ -1274,7 +1272,8 @@ public: }; DrawListID draw_list_begin_for_screen(DisplayServer::WindowID p_screen = 0, const Color &p_clear_color = Color()); - DrawListID draw_list_begin(RID p_framebuffer, BitField p_draw_flags = DRAW_DEFAULT_ALL, const Vector &p_clear_color_values = Vector(), float p_clear_depth_value = 1.0f, uint32_t p_clear_stencil_value = 0, const Rect2 &p_region = Rect2(), uint32_t p_breadcrumb = 0); + DrawListID draw_list_begin(RID p_framebuffer, BitField p_draw_flags = DRAW_DEFAULT_ALL, VectorView p_clear_color_values = VectorView(), float p_clear_depth_value = 1.0f, uint32_t p_clear_stencil_value = 0, const Rect2 &p_region = Rect2(), uint32_t p_breadcrumb = 0); + DrawListID _draw_list_begin_bind(RID p_framebuffer, BitField p_draw_flags = DRAW_DEFAULT_ALL, const Vector &p_clear_color_values = Vector(), float p_clear_depth_value = 1.0f, 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); @@ -1302,6 +1301,7 @@ private: /***********************/ struct ComputeList { + bool active = false; struct SetState { uint32_t pipeline_expected_format = 0; uint32_t uniform_set_format = 0; @@ -1325,7 +1325,6 @@ private: #ifdef DEBUG_ENABLED struct Validation { - bool active = true; // Means command buffer was not closed, so you can keep adding things. Vector set_formats; Vector set_bound; Vector set_rids; @@ -1339,7 +1338,7 @@ private: #endif }; - ComputeList *compute_list = nullptr; + ComputeList compute_list; ComputeList::State compute_list_barrier_state; public: