Skip to content

Commit

Permalink
Add ability to call code on rendering thread
Browse files Browse the repository at this point in the history
As more users use compute in Godot 4, the way they do is most likely incompatible when running
on separate threads and will start erroring soon as we improve the thread safety of the render thread.

To properly run code on the render thread, this function was added. Use like this:

```GDScript

func initialize_compute_code():
	....

func update_compute_code(custom_data):
	...

func _ready():
	RenderingServer.call_on_render_thread( initialize_compute_code )

func _process():
	RenderingServer.call_on_render_thread( update_compute_code.bind(with_data) )

```
  • Loading branch information
reduz committed Jul 26, 2023
1 parent 202e4b2 commit c7fb6ce
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 0 deletions.
7 changes: 7 additions & 0 deletions doc/classes/RenderingServer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@
Bakes the material data of the Mesh passed in the [param base] parameter with optional [param material_overrides] to a set of [Image]s of size [param image_size]. Returns an array of [Image]s containing material properties as specified in [enum BakeChannels].
</description>
</method>
<method name="call_on_render_thread">
<return type="void" />
<param index="0" name="callable" type="Callable" />
<description>
As the RenderingServer actual logic may run on an separate thread, accessing its internals from the main (or any other) thread will result in errors. To make it easier to run code that can safely access the rendering internals (such as [RenderingDevice] and similar RD classes), push a callable via this function so it will be executed on the render thread.
</description>
</method>
<method name="camera_attributes_create">
<return type="RID" />
<description>
Expand Down
6 changes: 6 additions & 0 deletions servers/rendering/rendering_server_default.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,12 @@ void RenderingServerDefault::draw(bool p_swap_buffers, double frame_step) {
}
}

void RenderingServerDefault::_call_on_render_thread(const Callable &p_callable) {
Variant ret;
Callable::CallError ce;
p_callable.callp(nullptr, 0, ret, ce);
}

RenderingServerDefault::RenderingServerDefault(bool p_create_thread) :
command_queue(p_create_thread) {
RenderingServer::init();
Expand Down
11 changes: 11 additions & 0 deletions servers/rendering/rendering_server_default.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ class RenderingServerDefault : public RenderingServer {

void _free(RID p_rid);

void _call_on_render_thread(const Callable &p_callable);

public:
//if editor is redrawing when it shouldn't, enable this and put a breakpoint in _changes_changed()
//#define DEBUG_CHANGES
Expand Down Expand Up @@ -987,6 +989,15 @@ class RenderingServerDefault : public RenderingServer {
virtual void init() override;
virtual void finish() override;

virtual void call_on_render_thread(const Callable &p_callable) override {
if (Thread::get_caller_id() == server_thread) {
command_queue.flush_if_pending();
_call_on_render_thread(p_callable);
} else {
command_queue.push(this, &RenderingServerDefault::_call_on_render_thread, p_callable);
}
}

/* TESTING */

virtual double get_frame_setup_time_cpu() const override;
Expand Down
2 changes: 2 additions & 0 deletions servers/rendering_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2808,6 +2808,8 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("force_draw", "swap_buffers", "frame_step"), &RenderingServer::draw, DEFVAL(true), DEFVAL(0.0));
ClassDB::bind_method(D_METHOD("get_rendering_device"), &RenderingServer::get_rendering_device);
ClassDB::bind_method(D_METHOD("create_local_rendering_device"), &RenderingServer::create_local_rendering_device);

ClassDB::bind_method(D_METHOD("call_on_render_thread", "callable"), &RenderingServer::call_on_render_thread);
}

void RenderingServer::mesh_add_surface_from_mesh_data(RID p_mesh, const Geometry3D::MeshData &p_mesh_data) {
Expand Down
2 changes: 2 additions & 0 deletions servers/rendering_server.h
Original file line number Diff line number Diff line change
Expand Up @@ -1599,6 +1599,8 @@ class RenderingServer : public Object {
bool is_render_loop_enabled() const;
void set_render_loop_enabled(bool p_enabled);

virtual void call_on_render_thread(const Callable &p_callable) = 0;

RenderingServer();
virtual ~RenderingServer();

Expand Down

0 comments on commit c7fb6ce

Please sign in to comment.