how to get posts ids inside pre_get_posts filter?

We could try to use the the_posts filter, that’s applied on the queried posts, if the suppress_filters query variable is false, to collect relevant post IDs.

We can then use the pre_get_posts hook, in each query, to exclude the accumulated array of post IDs.

Here’s a schema example for the process:

// Main query
$wp_query = new WP_Query( $args );
$wp_query->posts filtered and collected post IDs [1,2] from the 'post' post type

// Sub query #1
$q1 = new WP_Query( [ 'wpse_exclude' => true, ... ] );
pre_get_posts excludes accumulated [1,2]
$q1->posts filtered and collected [3,4] 

// Sub query #2
$q2 = new WP_Query( [ 'wpse_exclude' => true, ... ] );
pre_get_posts excludes accumulated [1,2,3,4]
$q2->posts filtered and collected  [5,6]

// Sub query #3
$q3 = new WP_Query( $args );
No exclusion because 'wpse_exclude' argument is missing
$q3->posts filtered and collected [7]

// Sub query #4
$q4 = new WP_Query( [ 'wpse_exclude' => true, ... ] );
pre_get_posts excludes accumulated [1,2,3,4,5,6,7]
$q4->posts filtered and collected [8,9]

Here are possible building blocks for a demo class that could help with that:

The init() method:

public function init( $collect_post_type="post" )
{
    // Collect post IDs
    add_filter( 'the_posts', [ $this, 'the_posts' ] );

    // Exclude accumulated post IDs in queries
    add_action( 'pre_get_posts', [ $this, 'pre_get_posts' ] );

    // Initialize accumulated post IDs for exclusion
    $this->exclude_pids = [];

    // Collect post IDs only from this post type
    $this->collect_post_type = $collect_post_type;
}

The pre_get_posts() method:

public function pre_get_posts( \WP_Query $q )
{
    if( 
        $q->is_home()                 // Target the home page
        && $q->get( 'wpse_exclude' )  // Target queries with wpse_exclude set as true
     // && ... etc
    ) {     
        // Exclude accumulated set of post IDs
        if( ! empty( $this->exclude_pids ) )
            $q->set( 'post__not_in', $this->exclude_pids );
    }
}

Here we should also consider preserving any previous post__not_in arguments.

The the_posts() method:

public function the_posts( array $posts )
{
    // Collect post IDs from 'post' post type and merge to the $pids array
    $this->exclude_pids = array_merge( 
        $this->exclude_pids , 
        (array) wp_filter_object_list( 
            $posts,
            [ 'post_type' => $this->collect_post_type ], 
            'AND', 
            'ID' 
        )  
    );

    return $posts;
}

Hope you can adjust this to your needs.