| 692 | } |
| 693 | |
| 694 | Error RenderingDevice::buffer_get_data_async(RID p_buffer, const Callable &p_callback, uint32_t p_offset, uint32_t p_size) { |
| 695 | ERR_RENDER_THREAD_GUARD_V(ERR_UNAVAILABLE); |
| 696 | |
| 697 | Buffer *buffer = _get_buffer_from_owner(p_buffer); |
| 698 | if (buffer == nullptr) { |
| 699 | ERR_FAIL_V_MSG(ERR_INVALID_PARAMETER, "Buffer is either invalid or this type of buffer can't be retrieved."); |
| 700 | } |
| 701 | |
| 702 | if (p_size == 0) { |
| 703 | p_size = buffer->size; |
| 704 | } |
| 705 | |
| 706 | ERR_FAIL_COND_V_MSG(p_size + p_offset > buffer->size, ERR_INVALID_PARAMETER, "Size is larger than the buffer."); |
| 707 | ERR_FAIL_COND_V_MSG(!p_callback.is_valid(), ERR_INVALID_PARAMETER, "Callback must be valid."); |
| 708 | |
| 709 | _check_transfer_worker_buffer(buffer); |
| 710 | |
| 711 | BufferGetDataRequest get_data_request; |
| 712 | get_data_request.callback = p_callback; |
| 713 | get_data_request.frame_local_index = frames[frame].download_buffer_copy_regions.size(); |
| 714 | get_data_request.size = p_size; |
| 715 | |
| 716 | const uint32_t required_align = 32; |
| 717 | uint32_t block_write_offset; |
| 718 | uint32_t block_write_amount; |
| 719 | StagingRequiredAction required_action; |
| 720 | uint32_t to_submit = p_size; |
| 721 | uint32_t submit_from = 0; |
| 722 | while (to_submit > 0) { |
| 723 | Error err = _staging_buffer_allocate(download_staging_buffers, MIN(to_submit, download_staging_buffers.block_size), required_align, block_write_offset, block_write_amount, required_action); |
| 724 | if (err) { |
| 725 | return err; |
| 726 | } |
| 727 | |
| 728 | const bool flush_frames = (get_data_request.frame_local_count > 0) && required_action == STAGING_REQUIRED_ACTION_FLUSH_AND_STALL_ALL; |
| 729 | if (flush_frames) { |
| 730 | if (_buffer_make_mutable(buffer, p_buffer)) { |
| 731 | // The buffer must be mutable to be used as a copy source. |
| 732 | draw_graph.add_synchronization(); |
| 733 | } |
| 734 | |
| 735 | for (uint32_t i = 0; i < get_data_request.frame_local_count; i++) { |
| 736 | uint32_t local_index = get_data_request.frame_local_index + i; |
| 737 | draw_graph.add_buffer_get_data(buffer->driver_id, buffer->draw_tracker, frames[frame].download_buffer_staging_buffers[local_index], frames[frame].download_buffer_copy_regions[local_index]); |
| 738 | } |
| 739 | } |
| 740 | |
| 741 | _staging_buffer_execute_required_action(download_staging_buffers, required_action); |
| 742 | |
| 743 | if (flush_frames) { |
| 744 | get_data_request.frame_local_count = 0; |
| 745 | get_data_request.frame_local_index = frames[frame].download_buffer_copy_regions.size(); |
| 746 | } |
| 747 | |
| 748 | RDD::BufferCopyRegion region; |
| 749 | region.src_offset = submit_from + p_offset; |
| 750 | region.dst_offset = block_write_offset; |
| 751 | region.size = block_write_amount; |
nothing calls this directly
no test coverage detected