Merge pull request #115865 from blueskythlikesclouds/transfer-worker-race-condition

Fix transfer worker race condition.
This commit is contained in:
Thaddeus Crews 2026-02-05 09:32:39 -06:00
commit 2b44ed5299
No known key found for this signature in database
GPG key ID: 8C6E5FEB5FC03CCC
2 changed files with 20 additions and 10 deletions

View file

@ -6417,7 +6417,7 @@ RenderingDevice::TransferWorker *RenderingDevice::_acquire_transfer_worker(uint3
MutexLock pool_lock(transfer_worker_pool_mutex);
// If no workers are available and we've reached the max pool capacity, wait until one of them becomes available.
bool transfer_worker_pool_full = transfer_worker_pool.size() >= transfer_worker_pool_max_size;
bool transfer_worker_pool_full = transfer_worker_pool_size >= transfer_worker_pool_max_size;
while (transfer_worker_pool_available_list.is_empty() && transfer_worker_pool_full) {
transfer_worker_pool_condition.wait(pool_lock);
}
@ -6480,13 +6480,16 @@ RenderingDevice::TransferWorker *RenderingDevice::_acquire_transfer_worker(uint3
DEV_ASSERT(!transfer_worker_pool_full && "A transfer worker should never be created when the pool is full.");
// No existing worker was picked, we create a new one.
uint32_t transfer_worker_index = transfer_worker_pool_size;
++transfer_worker_pool_size;
transfer_worker = memnew(TransferWorker);
transfer_worker->command_fence = driver->fence_create();
transfer_worker->command_pool = driver->command_pool_create(transfer_queue_family, RDD::COMMAND_BUFFER_TYPE_PRIMARY);
transfer_worker->command_buffer = driver->command_buffer_create(transfer_worker->command_pool);
transfer_worker->index = transfer_worker_pool.size();
transfer_worker_pool.push_back(transfer_worker);
transfer_worker_operation_used_by_draw.push_back(0);
transfer_worker->index = transfer_worker_index;
transfer_worker_pool[transfer_worker_index] = transfer_worker;
transfer_worker_operation_used_by_draw[transfer_worker_index] = 0;
transfer_worker->thread_mutex.lock();
}
}
@ -6640,7 +6643,7 @@ void RenderingDevice::_check_transfer_worker_index_array(IndexArray *p_index_arr
void RenderingDevice::_submit_transfer_workers(RDD::CommandBufferID p_draw_command_buffer) {
MutexLock transfer_worker_lock(transfer_worker_pool_mutex);
for (uint32_t i = 0; i < transfer_worker_pool.size(); i++) {
for (uint32_t i = 0; i < transfer_worker_pool_size; i++) {
TransferWorker *worker = transfer_worker_pool[i];
if (p_draw_command_buffer) {
MutexLock lock(worker->operations_mutex);
@ -6675,7 +6678,8 @@ void RenderingDevice::_submit_transfer_barriers(RDD::CommandBufferID p_draw_comm
void RenderingDevice::_wait_for_transfer_workers() {
MutexLock transfer_worker_lock(transfer_worker_pool_mutex);
for (TransferWorker *worker : transfer_worker_pool) {
for (uint32_t i = 0; i < transfer_worker_pool_size; i++) {
TransferWorker *worker = transfer_worker_pool[i];
MutexLock lock(worker->thread_mutex);
if (worker->submitted) {
_wait_for_transfer_worker(worker);
@ -6685,14 +6689,15 @@ void RenderingDevice::_wait_for_transfer_workers() {
void RenderingDevice::_free_transfer_workers() {
MutexLock transfer_worker_lock(transfer_worker_pool_mutex);
for (TransferWorker *worker : transfer_worker_pool) {
for (uint32_t i = 0; i < transfer_worker_pool_size; i++) {
TransferWorker *worker = transfer_worker_pool[i];
driver->fence_free(worker->command_fence);
driver->buffer_free(worker->staging_buffer);
driver->command_pool_free(worker->command_pool);
memdelete(worker);
}
transfer_worker_pool.clear();
transfer_worker_pool_size = 0;
}
/***********************/
@ -7666,6 +7671,10 @@ Error RenderingDevice::initialize(RenderingContextDriver *p_context, DisplayServ
// Use the processor count as the max amount of transfer workers that can be created.
transfer_worker_pool_max_size = OS::get_singleton()->get_processor_count();
// Pre-allocate to avoid locking a mutex when indexing into them.
transfer_worker_pool.resize(transfer_worker_pool_max_size);
transfer_worker_operation_used_by_draw.resize(transfer_worker_pool_max_size);
frames.resize(frame_count);
// Create data for all the frames.

View file

@ -1598,9 +1598,10 @@ private:
BinaryMutex operations_mutex;
};
LocalVector<TransferWorker *> transfer_worker_pool;
TightLocalVector<TransferWorker *> transfer_worker_pool;
uint32_t transfer_worker_pool_size = 0;
uint32_t transfer_worker_pool_max_size = 1;
LocalVector<uint64_t> transfer_worker_operation_used_by_draw;
TightLocalVector<uint64_t> transfer_worker_operation_used_by_draw;
LocalVector<uint32_t> transfer_worker_pool_available_list;
LocalVector<RDD::TextureBarrier> transfer_worker_pool_texture_barriers;
BinaryMutex transfer_worker_pool_mutex;