@@ -4440,6 +4440,117 @@ void RenderingDevice::draw_list_draw(DrawListID p_list, bool p_use_indices, uint
44404440 dl->state .draw_count ++;
44414441}
44424442
4443+ 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) {
4444+ ERR_RENDER_THREAD_GUARD ();
4445+
4446+ DrawList *dl = _get_draw_list_ptr (p_list);
4447+ ERR_FAIL_NULL (dl);
4448+
4449+ Buffer *buffer = storage_buffer_owner.get_or_null (p_buffer);
4450+ ERR_FAIL_NULL (buffer);
4451+
4452+ ERR_FAIL_COND_MSG (!buffer->usage .has_flag (RDD::BUFFER_USAGE_INDIRECT_BIT), " Buffer provided was not created to do indirect dispatch." );
4453+
4454+ #ifdef DEBUG_ENABLED
4455+ ERR_FAIL_COND_MSG (!dl->validation .active , " Submitted Draw Lists can no longer be modified." );
4456+ #endif
4457+
4458+ #ifdef DEBUG_ENABLED
4459+ ERR_FAIL_COND_MSG (!dl->validation .pipeline_active ,
4460+ " No render pipeline was set before attempting to draw." );
4461+ if (dl->validation .pipeline_vertex_format != INVALID_ID) {
4462+ // Pipeline uses vertices, validate format.
4463+ ERR_FAIL_COND_MSG (dl->validation .vertex_format == INVALID_ID,
4464+ " No vertex array was bound, and render pipeline expects vertices." );
4465+ // Make sure format is right.
4466+ ERR_FAIL_COND_MSG (dl->validation .pipeline_vertex_format != dl->validation .vertex_format ,
4467+ " The vertex format used to create the pipeline does not match the vertex format bound." );
4468+ }
4469+
4470+ if (dl->validation .pipeline_push_constant_size > 0 ) {
4471+ // Using push constants, check that they were supplied.
4472+ ERR_FAIL_COND_MSG (!dl->validation .pipeline_push_constant_supplied ,
4473+ " The shader in this pipeline requires a push constant to be set before drawing, but it's not present." );
4474+ }
4475+ #endif
4476+
4477+ #ifdef DEBUG_ENABLED
4478+ for (uint32_t i = 0 ; i < dl->state .set_count ; i++) {
4479+ if (dl->state .sets [i].pipeline_expected_format == 0 ) {
4480+ // Nothing expected by this pipeline.
4481+ continue ;
4482+ }
4483+
4484+ if (dl->state .sets [i].pipeline_expected_format != dl->state .sets [i].uniform_set_format ) {
4485+ if (dl->state .sets [i].uniform_set_format == 0 ) {
4486+ ERR_FAIL_MSG (vformat (" Uniforms were never supplied for set (%d) at the time of drawing, which are required by the pipeline." , i));
4487+ } else if (uniform_set_owner.owns (dl->state .sets [i].uniform_set )) {
4488+ UniformSet *us = uniform_set_owner.get_or_null (dl->state .sets [i].uniform_set );
4489+ ERR_FAIL_MSG (vformat (" Uniforms supplied for set (%d):\n %s\n are 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 )));
4490+ } else {
4491+ 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 )));
4492+ }
4493+ }
4494+ }
4495+ #endif
4496+
4497+ // Prepare descriptor sets if the API doesn't use pipeline barriers.
4498+ if (!driver->api_trait_get (RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) {
4499+ for (uint32_t i = 0 ; i < dl->state .set_count ; i++) {
4500+ if (dl->state .sets [i].pipeline_expected_format == 0 ) {
4501+ // Nothing expected by this pipeline.
4502+ continue ;
4503+ }
4504+
4505+ 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);
4506+ }
4507+ }
4508+
4509+ // Bind descriptor sets.
4510+ for (uint32_t i = 0 ; i < dl->state .set_count ; i++) {
4511+ if (dl->state .sets [i].pipeline_expected_format == 0 ) {
4512+ continue ; // Nothing expected by this pipeline.
4513+ }
4514+ if (!dl->state .sets [i].bound ) {
4515+ // All good, see if this requires re-binding.
4516+ draw_graph.add_draw_list_bind_uniform_set (dl->state .pipeline_shader_driver_id , dl->state .sets [i].uniform_set_driver_id , i);
4517+
4518+ UniformSet *uniform_set = uniform_set_owner.get_or_null (dl->state .sets [i].uniform_set );
4519+ _uniform_set_update_shared (uniform_set);
4520+
4521+ draw_graph.add_draw_list_usages (uniform_set->draw_trackers , uniform_set->draw_trackers_usage );
4522+
4523+ dl->state .sets [i].bound = true ;
4524+ }
4525+ }
4526+
4527+ if (p_use_indices) {
4528+ #ifdef DEBUG_ENABLED
4529+ ERR_FAIL_COND_MSG (!dl->validation .index_array_count ,
4530+ " Draw command requested indices, but no index buffer was set." );
4531+
4532+ ERR_FAIL_COND_MSG (dl->validation .pipeline_uses_restart_indices != dl->validation .index_buffer_uses_restart_indices ,
4533+ " The usage of restart indices in index buffer does not match the render primitive in the pipeline." );
4534+ #endif
4535+
4536+ ERR_FAIL_COND_MSG (p_offset + 20 > buffer->size , " Offset provided (+20) is past the end of buffer." );
4537+
4538+ draw_graph.add_draw_list_draw_indexed_indirect (buffer->driver_id , p_offset, p_draw_count, p_stride);
4539+ } else {
4540+ ERR_FAIL_COND_MSG (p_offset + 16 > buffer->size , " Offset provided (+16) is past the end of buffer." );
4541+
4542+ draw_graph.add_draw_list_draw_indirect (buffer->driver_id , p_offset, p_draw_count, p_stride);
4543+ }
4544+
4545+ dl->state .draw_count ++;
4546+
4547+ if (buffer->draw_tracker != nullptr ) {
4548+ draw_graph.add_draw_list_usage (buffer->draw_tracker , RDG::RESOURCE_USAGE_INDIRECT_BUFFER_READ);
4549+ }
4550+
4551+ _check_transfer_worker_buffer (buffer);
4552+ }
4553+
44434554void RenderingDevice::draw_list_enable_scissor (DrawListID p_list, const Rect2 &p_rect) {
44444555 ERR_RENDER_THREAD_GUARD ();
44454556
@@ -6656,6 +6767,7 @@ void RenderingDevice::_bind_methods() {
66566767 ClassDB::bind_method (D_METHOD (" draw_list_set_push_constant" , " draw_list" , " buffer" , " size_bytes" ), &RenderingDevice::_draw_list_set_push_constant);
66576768
66586769 ClassDB::bind_method (D_METHOD (" draw_list_draw" , " draw_list" , " use_indices" , " instances" , " procedural_vertex_count" ), &RenderingDevice::draw_list_draw, DEFVAL (0 ));
6770+ ClassDB::bind_method (D_METHOD (" draw_list_draw_indirect" , " draw_list" , " use_indices" , " buffer" , " offset" , " draw_count" , " stride" ), &RenderingDevice::draw_list_draw_indirect, DEFVAL (0 ), DEFVAL (1 ), DEFVAL (0 ));
66596771
66606772 ClassDB::bind_method (D_METHOD (" draw_list_enable_scissor" , " draw_list" , " rect" ), &RenderingDevice::draw_list_enable_scissor, DEFVAL (Rect2 ()));
66616773 ClassDB::bind_method (D_METHOD (" draw_list_disable_scissor" , " draw_list" ), &RenderingDevice::draw_list_disable_scissor);
0 commit comments