Rendering-device .sync() freezes main thread

Godot Version

v4.6.1.stable.steam [14d19694e]

Question

Im running a compute shader on a separate thread with a local rendering-device.

When i call rd.sync() after rd.submit() my main thread freezes.

All issues i found only stated that using a separte thread with a local rendering-device should avoid these freezes, but for me this doesnt stop the main thread from freezing for a short time.

Am i misunderstanding something or can i somehow avoid the freezing?

The documentation says the following:

“
void sync()

Forces a synchronization between the CPU and GPU, which may be required in certain cases. Only call this when needed, as CPU-GPU synchronization has a performance cost.

Note: Only available in local RenderingDevices.

Note: sync() can only be called after a submit().

“

but what is the alternative? when i tried to use a sort of polling (requesting every few miliseconds if its done) i get the error when calling a new shader that the device is already submitted(because of the previous run) and in the source code:

void RenderingDevice::submit() {
	ERR_RENDER_THREAD_GUARD();
	ERR_FAIL_COND_MSG(is_main_instance, "Only local devices can submit and sync.");
	ERR_FAIL_COND_MSG(local_device_processing, "device already submitted, call sync to wait until done.");

	_end_frame();
	_execute_frame(false);
	local_device_processing = true;
}

void RenderingDevice::sync() {
	ERR_RENDER_THREAD_GUARD();
	ERR_FAIL_COND_MSG(is_main_instance, "Only local devices can submit and sync.");
	ERR_FAIL_COND_MSG(!local_device_processing, "sync can only be called after a submit");

	_begin_frame(true);
	local_device_processing = false;
}

here it shows you cant call submit again without setting local_device_processing to false and the only way i see to do that, is by calling sync()…

Doing work on a separate thread avoids freeze by allowing the work to run independetly from the main thread. By calling sync() however you tell it to get the result from the GPU; if there is no result ready yet it will have to sit and wait for it. This is described in the compute shader tutorial albeit poorly.

Yes but it runs on a seperate thread, so why does the main thread freeze? clayjohn said this in the following github post:
”Yep, just create your local RD on a different thread and do everything on a separate thread, then none of the operations will block the main thread.”

The whole purpose of sync() is to block the caller. I think what was meant here is to call sync() from a cpu thread. That way it will block that thread but not the main thread.

1 Like

But it does block my main thread

Are you sure you’re calling it from a thread?

yes… im very sure

Does it block for the entire time gpu is busy? Try giving it seconds worth of work and check if it blocks for all that time.

As a quick fix you can always call sync() “later”.

thats what im already doing, but it always has freezes as soon as sync is called

You didn’t provide enough information. Does it block the entire time gpu is busy? Or just for a short time? What happens if the gpu is doing something for 10 seconds? Is the main thread blocked for 10 seconds?

Can you post the code?

1 Like

it blocks only when im calling sync() no matter the progress of the gpu. the code is

rd.submit()
# optional waiting here
rd.sync()

with or without waiting doesnt matter. One execution takes a maximum amount of ~1second (max) and even if i wait 2 or 4 seconds it will still freeze for a short time when i call rd.sync()

I meant the actual code, including thread creation.

Is the behavior same as when calling sync from the main thread? Are you sure sync() is freezing it? Print out some timestamps.

1 Like

Two threads interacting should really have no way to stall a third one, unless it itself is reaching for some blocked resource.

i know, thats why im confused and created this issue

Best to make and post a MRP.

Here is my mrp:

press “space” to execute the compute shader once. for me it causes stutter for a short moment, i put in a moving csg-shape to visualize the stutter clearly.

my pc is running on a geforce gtx 1060. my laptop with geforce gtx 1650 has way less noticeable stutter, but you can still feel it a little.

This still doesnt explain why the side-thread freezes the main thread, and i dont see an alternative to sync()

You’re compiling the shader anew every time. Try creating the rendering device and compiling the shader only once at startup.

If the problem persists, make the project more minimal. This still has unneeded elements of your actual project.

1 Like

in this specific case yes so i can easily switch between threaded and not threaded but in my main project i dont. it doesnt really matter. there is nothing more to reduce, you can comment out everything but it will still lag. does it lag for you aswell? have you tried it out?

Yes, the lag is there. It looks like the compute shader is just doing too much work, stealing away resources from rendering. The main thread appears to be waiting to be able to render the frame.

Thats what i feared, but if i dont call sync it doesnt lag? Thats what i dont understand, because the shader runs as soon as i call submit right? without calling sync it runs smoothly, so what exactly is the issue with sync is the question