@@ -4191,6 +4191,117 @@ void RenderingDevice::draw_list_draw(DrawListID p_list, bool p_use_indices, uint
41914191 dl->state .draw_count ++;
41924192}
41934193
4194+ 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) {
4195+ ERR_RENDER_THREAD_GUARD ();
4196+
4197+ DrawList *dl = _get_draw_list_ptr (p_list);
4198+ ERR_FAIL_NULL (dl);
4199+
4200+ Buffer *buffer = storage_buffer_owner.get_or_null (p_buffer);
4201+ ERR_FAIL_NULL (buffer);
4202+
4203+ ERR_FAIL_COND_MSG (!buffer->usage .has_flag (RDD::BUFFER_USAGE_INDIRECT_BIT), " Buffer provided was not created to do indirect dispatch." );
4204+
4205+ #ifdef DEBUG_ENABLED
4206+ ERR_FAIL_COND_MSG (!dl->validation .active , " Submitted Draw Lists can no longer be modified." );
4207+ #endif
4208+
4209+ #ifdef DEBUG_ENABLED
4210+ ERR_FAIL_COND_MSG (!dl->validation .pipeline_active ,
4211+ " No render pipeline was set before attempting to draw." );
4212+ if (dl->validation .pipeline_vertex_format != INVALID_ID) {
4213+ // Pipeline uses vertices, validate format.
4214+ ERR_FAIL_COND_MSG (dl->validation .vertex_format == INVALID_ID,
4215+ " No vertex array was bound, and render pipeline expects vertices." );
4216+ // Make sure format is right.
4217+ ERR_FAIL_COND_MSG (dl->validation .pipeline_vertex_format != dl->validation .vertex_format ,
4218+ " The vertex format used to create the pipeline does not match the vertex format bound." );
4219+ }
4220+
4221+ if (dl->validation .pipeline_push_constant_size > 0 ) {
4222+ // Using push constants, check that they were supplied.
4223+ ERR_FAIL_COND_MSG (!dl->validation .pipeline_push_constant_supplied ,
4224+ " The shader in this pipeline requires a push constant to be set before drawing, but it's not present." );
4225+ }
4226+ #endif
4227+
4228+ #ifdef DEBUG_ENABLED
4229+ for (uint32_t i = 0 ; i < dl->state .set_count ; i++) {
4230+ if (dl->state .sets [i].pipeline_expected_format == 0 ) {
4231+ // Nothing expected by this pipeline.
4232+ continue ;
4233+ }
4234+
4235+ if (dl->state .sets [i].pipeline_expected_format != dl->state .sets [i].uniform_set_format ) {
4236+ if (dl->state .sets [i].uniform_set_format == 0 ) {
4237+ ERR_FAIL_MSG (vformat (" Uniforms were never supplied for set (%d) at the time of drawing, which are required by the pipeline." , i));
4238+ } else if (uniform_set_owner.owns (dl->state .sets [i].uniform_set )) {
4239+ UniformSet *us = uniform_set_owner.get_or_null (dl->state .sets [i].uniform_set );
4240+ 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 )));
4241+ } else {
4242+ 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 )));
4243+ }
4244+ }
4245+ }
4246+ #endif
4247+
4248+ // Prepare descriptor sets if the API doesn't use pipeline barriers.
4249+ if (!driver->api_trait_get (RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) {
4250+ for (uint32_t i = 0 ; i < dl->state .set_count ; i++) {
4251+ if (dl->state .sets [i].pipeline_expected_format == 0 ) {
4252+ // Nothing expected by this pipeline.
4253+ continue ;
4254+ }
4255+
4256+ 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);
4257+ }
4258+ }
4259+
4260+ // Bind descriptor sets.
4261+ for (uint32_t i = 0 ; i < dl->state .set_count ; i++) {
4262+ if (dl->state .sets [i].pipeline_expected_format == 0 ) {
4263+ continue ; // Nothing expected by this pipeline.
4264+ }
4265+ if (!dl->state .sets [i].bound ) {
4266+ // All good, see if this requires re-binding.
4267+ draw_graph.add_draw_list_bind_uniform_set (dl->state .pipeline_shader_driver_id , dl->state .sets [i].uniform_set_driver_id , i);
4268+
4269+ UniformSet *uniform_set = uniform_set_owner.get_or_null (dl->state .sets [i].uniform_set );
4270+ _uniform_set_update_shared (uniform_set);
4271+
4272+ draw_graph.add_draw_list_usages (uniform_set->draw_trackers , uniform_set->draw_trackers_usage );
4273+
4274+ dl->state .sets [i].bound = true ;
4275+ }
4276+ }
4277+
4278+ if (p_use_indices) {
4279+ #ifdef DEBUG_ENABLED
4280+ ERR_FAIL_COND_MSG (!dl->validation .index_array_count ,
4281+ " Draw command requested indices, but no index buffer was set." );
4282+
4283+ ERR_FAIL_COND_MSG (dl->validation .pipeline_uses_restart_indices != dl->validation .index_buffer_uses_restart_indices ,
4284+ " The usage of restart indices in index buffer does not match the render primitive in the pipeline." );
4285+ #endif
4286+
4287+ ERR_FAIL_COND_MSG (p_offset + 20 > buffer->size , " Offset provided (+20) is past the end of buffer." );
4288+
4289+ draw_graph.add_draw_list_draw_indexed_indirect (buffer->driver_id , p_offset, p_draw_count, p_stride);
4290+ } else {
4291+ ERR_FAIL_COND_MSG (p_offset + 16 > buffer->size , " Offset provided (+16) is past the end of buffer." );
4292+
4293+ draw_graph.add_draw_list_draw_indirect (buffer->driver_id , p_offset, p_draw_count, p_stride);
4294+ }
4295+
4296+ dl->state .draw_count ++;
4297+
4298+ if (buffer->draw_tracker != nullptr ) {
4299+ draw_graph.add_draw_list_usage (buffer->draw_tracker , RDG::RESOURCE_USAGE_INDIRECT_BUFFER_READ);
4300+ }
4301+
4302+ _check_transfer_worker_buffer (buffer);
4303+ }
4304+
41944305void RenderingDevice::draw_list_enable_scissor (DrawListID p_list, const Rect2 &p_rect) {
41954306 DrawList *dl = _get_draw_list_ptr (p_list);
41964307
@@ -6023,6 +6134,7 @@ void RenderingDevice::_bind_methods() {
60236134 ClassDB::bind_method (D_METHOD (" draw_list_set_push_constant" , " draw_list" , " buffer" , " size_bytes" ), &RenderingDevice::_draw_list_set_push_constant);
60246135
60256136 ClassDB::bind_method (D_METHOD (" draw_list_draw" , " draw_list" , " use_indices" , " instances" , " procedural_vertex_count" ), &RenderingDevice::draw_list_draw, DEFVAL (0 ));
6137+ 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 ));
60266138
60276139 ClassDB::bind_method (D_METHOD (" draw_list_enable_scissor" , " draw_list" , " rect" ), &RenderingDevice::draw_list_enable_scissor, DEFVAL (Rect2 ()));
60286140 ClassDB::bind_method (D_METHOD (" draw_list_disable_scissor" , " draw_list" ), &RenderingDevice::draw_list_disable_scissor);
0 commit comments