Use WorkerThreadPool for Server threads
* Servers now use WorkerThreadPool for background computation. * This helps keep the number of threads used fixed at all times. * It also ensures everything works on HTML5 with threads. * And makes it easier to support disabling threads for also HTML5. CommandQueueMT now syncs with the servers via the WorkerThreadPool yielding mechanism, which makes its classic main sync semaphore superfluous. Also, some warnings about calls that kill performance when using threaded rendering are removed because there's a mechanism that warns about that in a more general fashion. Co-authored-by: Pedro J. Estébanez <pedrojrulez@gmail.com>
This commit is contained in:
parent
c28f5901c7
commit
65686dedf9
@ -82,6 +82,17 @@ int Engine::get_audio_output_latency() const {
|
|||||||
return _audio_output_latency;
|
return _audio_output_latency;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Engine::increment_frames_drawn() {
|
||||||
|
if (frame_server_synced) {
|
||||||
|
server_syncs++;
|
||||||
|
} else {
|
||||||
|
server_syncs = 0;
|
||||||
|
}
|
||||||
|
frame_server_synced = false;
|
||||||
|
|
||||||
|
frames_drawn++;
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t Engine::get_frames_drawn() {
|
uint64_t Engine::get_frames_drawn() {
|
||||||
return frames_drawn;
|
return frames_drawn;
|
||||||
}
|
}
|
||||||
@ -364,6 +375,11 @@ Engine *Engine::get_singleton() {
|
|||||||
return singleton;
|
return singleton;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Engine::notify_frame_server_synced() {
|
||||||
|
frame_server_synced = true;
|
||||||
|
return server_syncs > SERVER_SYNC_FRAME_COUNT_WARNING;
|
||||||
|
}
|
||||||
|
|
||||||
Engine::Engine() {
|
Engine::Engine() {
|
||||||
singleton = this;
|
singleton = this;
|
||||||
}
|
}
|
||||||
|
@ -91,6 +91,10 @@ private:
|
|||||||
String write_movie_path;
|
String write_movie_path;
|
||||||
String shader_cache_path;
|
String shader_cache_path;
|
||||||
|
|
||||||
|
static constexpr int SERVER_SYNC_FRAME_COUNT_WARNING = 5;
|
||||||
|
int server_syncs = 0;
|
||||||
|
bool frame_server_synced = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static Engine *get_singleton();
|
static Engine *get_singleton();
|
||||||
|
|
||||||
@ -179,6 +183,9 @@ public:
|
|||||||
bool is_generate_spirv_debug_info_enabled() const;
|
bool is_generate_spirv_debug_info_enabled() const;
|
||||||
int32_t get_gpu_index() const;
|
int32_t get_gpu_index() const;
|
||||||
|
|
||||||
|
void increment_frames_drawn();
|
||||||
|
bool notify_frame_server_synced();
|
||||||
|
|
||||||
Engine();
|
Engine();
|
||||||
virtual ~Engine() {}
|
virtual ~Engine() {}
|
||||||
};
|
};
|
||||||
|
@ -70,14 +70,8 @@ CommandQueueMT::SyncSemaphore *CommandQueueMT::_alloc_sync_sem() {
|
|||||||
return &sync_sems[idx];
|
return &sync_sems[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandQueueMT::CommandQueueMT(bool p_sync) {
|
CommandQueueMT::CommandQueueMT() {
|
||||||
if (p_sync) {
|
|
||||||
sync = memnew(Semaphore);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandQueueMT::~CommandQueueMT() {
|
CommandQueueMT::~CommandQueueMT() {
|
||||||
if (sync) {
|
|
||||||
memdelete(sync);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -255,9 +255,10 @@
|
|||||||
cmd->instance = p_instance; \
|
cmd->instance = p_instance; \
|
||||||
cmd->method = p_method; \
|
cmd->method = p_method; \
|
||||||
SEMIC_SEP_LIST(CMD_ASSIGN_PARAM, N); \
|
SEMIC_SEP_LIST(CMD_ASSIGN_PARAM, N); \
|
||||||
|
if (pump_task_id != WorkerThreadPool::INVALID_TASK_ID) { \
|
||||||
|
WorkerThreadPool::get_singleton()->notify_yield_over(pump_task_id); \
|
||||||
|
} \
|
||||||
unlock(); \
|
unlock(); \
|
||||||
if (sync) \
|
|
||||||
sync->post(); \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CMD_RET_TYPE(N) CommandRet##N<T, M, COMMA_SEP_LIST(TYPE_ARG, N) COMMA(N) R>
|
#define CMD_RET_TYPE(N) CommandRet##N<T, M, COMMA_SEP_LIST(TYPE_ARG, N) COMMA(N) R>
|
||||||
@ -272,9 +273,10 @@
|
|||||||
SEMIC_SEP_LIST(CMD_ASSIGN_PARAM, N); \
|
SEMIC_SEP_LIST(CMD_ASSIGN_PARAM, N); \
|
||||||
cmd->ret = r_ret; \
|
cmd->ret = r_ret; \
|
||||||
cmd->sync_sem = ss; \
|
cmd->sync_sem = ss; \
|
||||||
|
if (pump_task_id != WorkerThreadPool::INVALID_TASK_ID) { \
|
||||||
|
WorkerThreadPool::get_singleton()->notify_yield_over(pump_task_id); \
|
||||||
|
} \
|
||||||
unlock(); \
|
unlock(); \
|
||||||
if (sync) \
|
|
||||||
sync->post(); \
|
|
||||||
ss->sem.wait(); \
|
ss->sem.wait(); \
|
||||||
ss->in_use = false; \
|
ss->in_use = false; \
|
||||||
}
|
}
|
||||||
@ -290,9 +292,10 @@
|
|||||||
cmd->method = p_method; \
|
cmd->method = p_method; \
|
||||||
SEMIC_SEP_LIST(CMD_ASSIGN_PARAM, N); \
|
SEMIC_SEP_LIST(CMD_ASSIGN_PARAM, N); \
|
||||||
cmd->sync_sem = ss; \
|
cmd->sync_sem = ss; \
|
||||||
|
if (pump_task_id != WorkerThreadPool::INVALID_TASK_ID) { \
|
||||||
|
WorkerThreadPool::get_singleton()->notify_yield_over(pump_task_id); \
|
||||||
|
} \
|
||||||
unlock(); \
|
unlock(); \
|
||||||
if (sync) \
|
|
||||||
sync->post(); \
|
|
||||||
ss->sem.wait(); \
|
ss->sem.wait(); \
|
||||||
ss->in_use = false; \
|
ss->in_use = false; \
|
||||||
}
|
}
|
||||||
@ -340,7 +343,7 @@ class CommandQueueMT {
|
|||||||
LocalVector<uint8_t> command_mem;
|
LocalVector<uint8_t> command_mem;
|
||||||
SyncSemaphore sync_sems[SYNC_SEMAPHORES];
|
SyncSemaphore sync_sems[SYNC_SEMAPHORES];
|
||||||
Mutex mutex;
|
Mutex mutex;
|
||||||
Semaphore *sync = nullptr;
|
WorkerThreadPool::TaskID pump_task_id = WorkerThreadPool::INVALID_TASK_ID;
|
||||||
uint64_t flush_read_ptr = 0;
|
uint64_t flush_read_ptr = 0;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -421,12 +424,16 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void wait_and_flush() {
|
void wait_and_flush() {
|
||||||
ERR_FAIL_NULL(sync);
|
ERR_FAIL_COND(pump_task_id == WorkerThreadPool::INVALID_TASK_ID);
|
||||||
sync->wait();
|
WorkerThreadPool::get_singleton()->wait_for_task_completion(pump_task_id);
|
||||||
_flush();
|
_flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandQueueMT(bool p_sync);
|
void set_pump_task_id(WorkerThreadPool::TaskID p_task_id) {
|
||||||
|
pump_task_id = p_task_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
CommandQueueMT();
|
||||||
~CommandQueueMT();
|
~CommandQueueMT();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -135,7 +135,6 @@ bool ParticlesStorage::particles_get_emitting(RID p_particles) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ERR_FAIL_COND_V_MSG(RSG::threaded, false, "This function should never be used with threaded rendering, as it stalls the renderer.");
|
|
||||||
Particles *particles = particles_owner.get_or_null(p_particles);
|
Particles *particles = particles_owner.get_or_null(p_particles);
|
||||||
ERR_FAIL_NULL_V(particles, false);
|
ERR_FAIL_NULL_V(particles, false);
|
||||||
|
|
||||||
@ -380,10 +379,6 @@ void ParticlesStorage::particles_request_process(RID p_particles) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
AABB ParticlesStorage::particles_get_current_aabb(RID p_particles) {
|
AABB ParticlesStorage::particles_get_current_aabb(RID p_particles) {
|
||||||
if (RSG::threaded) {
|
|
||||||
WARN_PRINT_ONCE("Calling this function with threaded rendering enabled stalls the renderer, use with care.");
|
|
||||||
}
|
|
||||||
|
|
||||||
const Particles *particles = particles_owner.get_or_null(p_particles);
|
const Particles *particles = particles_owner.get_or_null(p_particles);
|
||||||
ERR_FAIL_NULL_V(particles, AABB());
|
ERR_FAIL_NULL_V(particles, AABB());
|
||||||
|
|
||||||
@ -1207,7 +1202,6 @@ Dependency *ParticlesStorage::particles_get_dependency(RID p_particles) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool ParticlesStorage::particles_is_inactive(RID p_particles) const {
|
bool ParticlesStorage::particles_is_inactive(RID p_particles) const {
|
||||||
ERR_FAIL_COND_V_MSG(RSG::threaded, false, "This function should never be used with threaded rendering, as it stalls the renderer.");
|
|
||||||
const Particles *particles = particles_owner.get_or_null(p_particles);
|
const Particles *particles = particles_owner.get_or_null(p_particles);
|
||||||
ERR_FAIL_NULL_V(particles, false);
|
ERR_FAIL_NULL_V(particles, false);
|
||||||
return !particles->emitting && particles->inactive;
|
return !particles->emitting && particles->inactive;
|
||||||
|
@ -2274,6 +2274,9 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
|
|||||||
// Editor and project manager cannot run with rendering in a separate thread (they will crash on startup).
|
// Editor and project manager cannot run with rendering in a separate thread (they will crash on startup).
|
||||||
rtm = OS::RENDER_THREAD_SAFE;
|
rtm = OS::RENDER_THREAD_SAFE;
|
||||||
}
|
}
|
||||||
|
#if !defined(THREADS_ENABLED)
|
||||||
|
rtm = OS::RENDER_THREAD_SAFE;
|
||||||
|
#endif
|
||||||
OS::get_singleton()->_render_thread_mode = OS::RenderThreadMode(rtm);
|
OS::get_singleton()->_render_thread_mode = OS::RenderThreadMode(rtm);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2717,7 +2720,9 @@ Error Main::setup2() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (OS::get_singleton()->_render_thread_mode == OS::RENDER_SEPARATE_THREAD) {
|
if (OS::get_singleton()->_render_thread_mode == OS::RENDER_SEPARATE_THREAD) {
|
||||||
WARN_PRINT("The Multi-Threaded rendering thread model is experimental, and has known issues which can lead to project crashes. Use the Single-Safe option in the project settings instead.");
|
WARN_PRINT("The Multi-Threaded rendering thread model is experimental. Feel free to try it since it will eventually become a stable feature.\n"
|
||||||
|
"However, bear in mind that at the moment it can lead to project crashes or instability.\n"
|
||||||
|
"So, unless you want to test the engine, use the Single-Safe option in the project settings instead.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize Pen Tablet Driver */
|
/* Initialize Pen Tablet Driver */
|
||||||
@ -4025,11 +4030,11 @@ bool Main::iteration() {
|
|||||||
if ((!force_redraw_requested) && OS::get_singleton()->is_in_low_processor_usage_mode()) {
|
if ((!force_redraw_requested) && OS::get_singleton()->is_in_low_processor_usage_mode()) {
|
||||||
if (RenderingServer::get_singleton()->has_changed()) {
|
if (RenderingServer::get_singleton()->has_changed()) {
|
||||||
RenderingServer::get_singleton()->draw(true, scaled_step); // flush visual commands
|
RenderingServer::get_singleton()->draw(true, scaled_step); // flush visual commands
|
||||||
Engine::get_singleton()->frames_drawn++;
|
Engine::get_singleton()->increment_frames_drawn();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
RenderingServer::get_singleton()->draw(true, scaled_step); // flush visual commands
|
RenderingServer::get_singleton()->draw(true, scaled_step); // flush visual commands
|
||||||
Engine::get_singleton()->frames_drawn++;
|
Engine::get_singleton()->increment_frames_drawn();
|
||||||
force_redraw_requested = false;
|
force_redraw_requested = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
#include "core/os/os.h"
|
#include "core/os/os.h"
|
||||||
|
|
||||||
void PhysicsServer2DWrapMT::thread_exit() {
|
void PhysicsServer2DWrapMT::thread_exit() {
|
||||||
exit.set();
|
exit = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicsServer2DWrapMT::thread_step(real_t p_delta) {
|
void PhysicsServer2DWrapMT::thread_step(real_t p_delta) {
|
||||||
@ -41,25 +41,18 @@ void PhysicsServer2DWrapMT::thread_step(real_t p_delta) {
|
|||||||
step_sem.post();
|
step_sem.post();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicsServer2DWrapMT::_thread_callback(void *_instance) {
|
|
||||||
PhysicsServer2DWrapMT *vsmt = reinterpret_cast<PhysicsServer2DWrapMT *>(_instance);
|
|
||||||
|
|
||||||
vsmt->thread_loop();
|
|
||||||
}
|
|
||||||
|
|
||||||
void PhysicsServer2DWrapMT::thread_loop() {
|
void PhysicsServer2DWrapMT::thread_loop() {
|
||||||
server_thread = Thread::get_caller_id();
|
server_thread = Thread::get_caller_id();
|
||||||
|
|
||||||
physics_server_2d->init();
|
physics_server_2d->init();
|
||||||
|
|
||||||
exit.clear();
|
command_queue.set_pump_task_id(server_task_id);
|
||||||
step_thread_up.set();
|
while (!exit) {
|
||||||
while (!exit.is_set()) {
|
WorkerThreadPool::get_singleton()->yield();
|
||||||
// flush commands one by one, until exit is requested
|
command_queue.flush_all();
|
||||||
command_queue.wait_and_flush();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
command_queue.flush_all(); // flush all
|
command_queue.flush_all();
|
||||||
|
|
||||||
physics_server_2d->finish();
|
physics_server_2d->finish();
|
||||||
}
|
}
|
||||||
@ -70,18 +63,14 @@ void PhysicsServer2DWrapMT::step(real_t p_step) {
|
|||||||
if (create_thread) {
|
if (create_thread) {
|
||||||
command_queue.push(this, &PhysicsServer2DWrapMT::thread_step, p_step);
|
command_queue.push(this, &PhysicsServer2DWrapMT::thread_step, p_step);
|
||||||
} else {
|
} else {
|
||||||
command_queue.flush_all(); //flush all pending from other threads
|
command_queue.flush_all(); // Flush all pending from other threads.
|
||||||
physics_server_2d->step(p_step);
|
physics_server_2d->step(p_step);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicsServer2DWrapMT::sync() {
|
void PhysicsServer2DWrapMT::sync() {
|
||||||
if (create_thread) {
|
if (create_thread) {
|
||||||
if (first_frame) {
|
step_sem.wait();
|
||||||
first_frame = false;
|
|
||||||
} else {
|
|
||||||
step_sem.wait(); //must not wait if a step was not issued
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
physics_server_2d->sync();
|
physics_server_2d->sync();
|
||||||
}
|
}
|
||||||
@ -96,39 +85,34 @@ void PhysicsServer2DWrapMT::end_sync() {
|
|||||||
|
|
||||||
void PhysicsServer2DWrapMT::init() {
|
void PhysicsServer2DWrapMT::init() {
|
||||||
if (create_thread) {
|
if (create_thread) {
|
||||||
thread.start(_thread_callback, this);
|
exit = false;
|
||||||
while (!step_thread_up.is_set()) {
|
server_task_id = WorkerThreadPool::get_singleton()->add_task(callable_mp(this, &PhysicsServer2DWrapMT::thread_loop), true);
|
||||||
OS::get_singleton()->delay_usec(1000);
|
step_sem.post();
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
physics_server_2d->init();
|
physics_server_2d->init();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicsServer2DWrapMT::finish() {
|
void PhysicsServer2DWrapMT::finish() {
|
||||||
if (thread.is_started()) {
|
if (create_thread) {
|
||||||
command_queue.push(this, &PhysicsServer2DWrapMT::thread_exit);
|
command_queue.push(this, &PhysicsServer2DWrapMT::thread_exit);
|
||||||
thread.wait_to_finish();
|
if (server_task_id != WorkerThreadPool::INVALID_TASK_ID) {
|
||||||
|
WorkerThreadPool::get_singleton()->wait_for_task_completion(server_task_id);
|
||||||
|
server_task_id = WorkerThreadPool::INVALID_TASK_ID;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
physics_server_2d->finish();
|
physics_server_2d->finish();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PhysicsServer2DWrapMT::PhysicsServer2DWrapMT(PhysicsServer2D *p_contained, bool p_create_thread) :
|
PhysicsServer2DWrapMT::PhysicsServer2DWrapMT(PhysicsServer2D *p_contained, bool p_create_thread) {
|
||||||
command_queue(p_create_thread) {
|
|
||||||
physics_server_2d = p_contained;
|
physics_server_2d = p_contained;
|
||||||
create_thread = p_create_thread;
|
create_thread = p_create_thread;
|
||||||
|
if (!create_thread) {
|
||||||
if (!p_create_thread) {
|
server_thread = Thread::MAIN_ID;
|
||||||
server_thread = Thread::get_caller_id();
|
|
||||||
} else {
|
|
||||||
server_thread = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
main_thread = Thread::get_caller_id();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PhysicsServer2DWrapMT::~PhysicsServer2DWrapMT() {
|
PhysicsServer2DWrapMT::~PhysicsServer2DWrapMT() {
|
||||||
memdelete(physics_server_2d);
|
memdelete(physics_server_2d);
|
||||||
//finish();
|
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#define PHYSICS_SERVER_2D_WRAP_MT_H
|
#define PHYSICS_SERVER_2D_WRAP_MT_H
|
||||||
|
|
||||||
#include "core/config/project_settings.h"
|
#include "core/config/project_settings.h"
|
||||||
|
#include "core/object/worker_thread_pool.h"
|
||||||
#include "core/os/thread.h"
|
#include "core/os/thread.h"
|
||||||
#include "core/templates/command_queue_mt.h"
|
#include "core/templates/command_queue_mt.h"
|
||||||
#include "core/templates/safe_refcount.h"
|
#include "core/templates/safe_refcount.h"
|
||||||
@ -43,30 +44,27 @@
|
|||||||
#define SYNC_DEBUG
|
#define SYNC_DEBUG
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
#define MAIN_THREAD_SYNC_WARN WARN_PRINT("Call to " + String(__FUNCTION__) + " causing PhysicsServer2D synchronizations on every frame. This significantly affects performance.");
|
||||||
|
#endif
|
||||||
|
|
||||||
class PhysicsServer2DWrapMT : public PhysicsServer2D {
|
class PhysicsServer2DWrapMT : public PhysicsServer2D {
|
||||||
mutable PhysicsServer2D *physics_server_2d;
|
mutable PhysicsServer2D *physics_server_2d = nullptr;
|
||||||
|
|
||||||
mutable CommandQueueMT command_queue;
|
mutable CommandQueueMT command_queue;
|
||||||
|
|
||||||
static void _thread_callback(void *_instance);
|
|
||||||
void thread_loop();
|
void thread_loop();
|
||||||
|
|
||||||
Thread::ID server_thread;
|
Thread::ID server_thread = Thread::UNASSIGNED_ID;
|
||||||
Thread::ID main_thread;
|
WorkerThreadPool::TaskID server_task_id = WorkerThreadPool::INVALID_TASK_ID;
|
||||||
SafeFlag exit;
|
bool exit = false;
|
||||||
Thread thread;
|
Semaphore step_sem;
|
||||||
SafeFlag step_thread_up;
|
|
||||||
bool create_thread = false;
|
bool create_thread = false;
|
||||||
|
|
||||||
Semaphore step_sem;
|
|
||||||
void thread_step(real_t p_delta);
|
void thread_step(real_t p_delta);
|
||||||
|
|
||||||
void thread_exit();
|
void thread_exit();
|
||||||
|
|
||||||
bool first_frame = true;
|
|
||||||
|
|
||||||
Mutex alloc_mutex;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
#define ServerName PhysicsServer2D
|
#define ServerName PhysicsServer2D
|
||||||
#define ServerNameWrapMT PhysicsServer2DWrapMT
|
#define ServerNameWrapMT PhysicsServer2DWrapMT
|
||||||
@ -94,7 +92,7 @@ public:
|
|||||||
|
|
||||||
//these work well, but should be used from the main thread only
|
//these work well, but should be used from the main thread only
|
||||||
bool shape_collide(RID p_shape_A, const Transform2D &p_xform_A, const Vector2 &p_motion_A, RID p_shape_B, const Transform2D &p_xform_B, const Vector2 &p_motion_B, Vector2 *r_results, int p_result_max, int &r_result_count) override {
|
bool shape_collide(RID p_shape_A, const Transform2D &p_xform_A, const Vector2 &p_motion_A, RID p_shape_B, const Transform2D &p_xform_B, const Vector2 &p_motion_B, Vector2 *r_results, int p_result_max, int &r_result_count) override {
|
||||||
ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false);
|
ERR_FAIL_COND_V(!Thread::is_main_thread(), false);
|
||||||
return physics_server_2d->shape_collide(p_shape_A, p_xform_A, p_motion_A, p_shape_B, p_xform_B, p_motion_B, r_results, p_result_max, r_result_count);
|
return physics_server_2d->shape_collide(p_shape_A, p_xform_A, p_motion_A, p_shape_B, p_xform_B, p_motion_B, r_results, p_result_max, r_result_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,18 +107,18 @@ public:
|
|||||||
|
|
||||||
// this function only works on physics process, errors and returns null otherwise
|
// this function only works on physics process, errors and returns null otherwise
|
||||||
PhysicsDirectSpaceState2D *space_get_direct_state(RID p_space) override {
|
PhysicsDirectSpaceState2D *space_get_direct_state(RID p_space) override {
|
||||||
ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), nullptr);
|
ERR_FAIL_COND_V(!Thread::is_main_thread(), nullptr);
|
||||||
return physics_server_2d->space_get_direct_state(p_space);
|
return physics_server_2d->space_get_direct_state(p_space);
|
||||||
}
|
}
|
||||||
|
|
||||||
FUNC2(space_set_debug_contacts, RID, int);
|
FUNC2(space_set_debug_contacts, RID, int);
|
||||||
virtual Vector<Vector2> space_get_contacts(RID p_space) const override {
|
virtual Vector<Vector2> space_get_contacts(RID p_space) const override {
|
||||||
ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), Vector<Vector2>());
|
ERR_FAIL_COND_V(!Thread::is_main_thread(), Vector<Vector2>());
|
||||||
return physics_server_2d->space_get_contacts(p_space);
|
return physics_server_2d->space_get_contacts(p_space);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int space_get_contact_count(RID p_space) const override {
|
virtual int space_get_contact_count(RID p_space) const override {
|
||||||
ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), 0);
|
ERR_FAIL_COND_V(!Thread::is_main_thread(), 0);
|
||||||
return physics_server_2d->space_get_contact_count(p_space);
|
return physics_server_2d->space_get_contact_count(p_space);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,13 +259,13 @@ public:
|
|||||||
FUNC2(body_set_pickable, RID, bool);
|
FUNC2(body_set_pickable, RID, bool);
|
||||||
|
|
||||||
bool body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result = nullptr) override {
|
bool body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result = nullptr) override {
|
||||||
ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false);
|
ERR_FAIL_COND_V(!Thread::is_main_thread(), false);
|
||||||
return physics_server_2d->body_test_motion(p_body, p_parameters, r_result);
|
return physics_server_2d->body_test_motion(p_body, p_parameters, r_result);
|
||||||
}
|
}
|
||||||
|
|
||||||
// this function only works on physics process, errors and returns null otherwise
|
// this function only works on physics process, errors and returns null otherwise
|
||||||
PhysicsDirectBodyState2D *body_get_direct_state(RID p_body) override {
|
PhysicsDirectBodyState2D *body_get_direct_state(RID p_body) override {
|
||||||
ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), nullptr);
|
ERR_FAIL_COND_V(!Thread::is_main_thread(), nullptr);
|
||||||
return physics_server_2d->body_get_direct_state(p_body);
|
return physics_server_2d->body_get_direct_state(p_body);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -338,4 +336,8 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
#undef SYNC_DEBUG
|
#undef SYNC_DEBUG
|
||||||
|
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
#undef MAIN_THREAD_SYNC_WARN
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // PHYSICS_SERVER_2D_WRAP_MT_H
|
#endif // PHYSICS_SERVER_2D_WRAP_MT_H
|
||||||
|
@ -41,22 +41,15 @@ void PhysicsServer3DWrapMT::thread_step(real_t p_delta) {
|
|||||||
step_sem.post();
|
step_sem.post();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicsServer3DWrapMT::_thread_callback(void *_instance) {
|
|
||||||
PhysicsServer3DWrapMT *vsmt = reinterpret_cast<PhysicsServer3DWrapMT *>(_instance);
|
|
||||||
|
|
||||||
vsmt->thread_loop();
|
|
||||||
}
|
|
||||||
|
|
||||||
void PhysicsServer3DWrapMT::thread_loop() {
|
void PhysicsServer3DWrapMT::thread_loop() {
|
||||||
server_thread = Thread::get_caller_id();
|
server_thread = Thread::get_caller_id();
|
||||||
|
|
||||||
physics_server_3d->init();
|
physics_server_3d->init();
|
||||||
|
|
||||||
exit = false;
|
command_queue.set_pump_task_id(server_task_id);
|
||||||
step_thread_up = true;
|
|
||||||
while (!exit) {
|
while (!exit) {
|
||||||
// flush commands one by one, until exit is requested
|
WorkerThreadPool::get_singleton()->yield();
|
||||||
command_queue.wait_and_flush();
|
command_queue.flush_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
command_queue.flush_all(); // flush all
|
command_queue.flush_all(); // flush all
|
||||||
@ -70,18 +63,14 @@ void PhysicsServer3DWrapMT::step(real_t p_step) {
|
|||||||
if (create_thread) {
|
if (create_thread) {
|
||||||
command_queue.push(this, &PhysicsServer3DWrapMT::thread_step, p_step);
|
command_queue.push(this, &PhysicsServer3DWrapMT::thread_step, p_step);
|
||||||
} else {
|
} else {
|
||||||
command_queue.flush_all(); //flush all pending from other threads
|
command_queue.flush_all(); // Flush all pending from other threads.
|
||||||
physics_server_3d->step(p_step);
|
physics_server_3d->step(p_step);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicsServer3DWrapMT::sync() {
|
void PhysicsServer3DWrapMT::sync() {
|
||||||
if (create_thread) {
|
if (create_thread) {
|
||||||
if (first_frame) {
|
step_sem.wait();
|
||||||
first_frame = false;
|
|
||||||
} else {
|
|
||||||
step_sem.wait(); //must not wait if a step was not issued
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
physics_server_3d->sync();
|
physics_server_3d->sync();
|
||||||
}
|
}
|
||||||
@ -96,39 +85,34 @@ void PhysicsServer3DWrapMT::end_sync() {
|
|||||||
|
|
||||||
void PhysicsServer3DWrapMT::init() {
|
void PhysicsServer3DWrapMT::init() {
|
||||||
if (create_thread) {
|
if (create_thread) {
|
||||||
thread.start(_thread_callback, this);
|
exit = false;
|
||||||
while (!step_thread_up) {
|
server_task_id = WorkerThreadPool::get_singleton()->add_task(callable_mp(this, &PhysicsServer3DWrapMT::thread_loop), true);
|
||||||
OS::get_singleton()->delay_usec(1000);
|
step_sem.post();
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
physics_server_3d->init();
|
physics_server_3d->init();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicsServer3DWrapMT::finish() {
|
void PhysicsServer3DWrapMT::finish() {
|
||||||
if (thread.is_started()) {
|
if (create_thread) {
|
||||||
command_queue.push(this, &PhysicsServer3DWrapMT::thread_exit);
|
command_queue.push(this, &PhysicsServer3DWrapMT::thread_exit);
|
||||||
thread.wait_to_finish();
|
if (server_task_id != WorkerThreadPool::INVALID_TASK_ID) {
|
||||||
|
WorkerThreadPool::get_singleton()->wait_for_task_completion(server_task_id);
|
||||||
|
server_task_id = WorkerThreadPool::INVALID_TASK_ID;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
physics_server_3d->finish();
|
physics_server_3d->finish();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PhysicsServer3DWrapMT::PhysicsServer3DWrapMT(PhysicsServer3D *p_contained, bool p_create_thread) :
|
PhysicsServer3DWrapMT::PhysicsServer3DWrapMT(PhysicsServer3D *p_contained, bool p_create_thread) {
|
||||||
command_queue(p_create_thread) {
|
|
||||||
physics_server_3d = p_contained;
|
physics_server_3d = p_contained;
|
||||||
create_thread = p_create_thread;
|
create_thread = p_create_thread;
|
||||||
|
if (!create_thread) {
|
||||||
if (!p_create_thread) {
|
server_thread = Thread::MAIN_ID;
|
||||||
server_thread = Thread::get_caller_id();
|
|
||||||
} else {
|
|
||||||
server_thread = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
main_thread = Thread::get_caller_id();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PhysicsServer3DWrapMT::~PhysicsServer3DWrapMT() {
|
PhysicsServer3DWrapMT::~PhysicsServer3DWrapMT() {
|
||||||
memdelete(physics_server_3d);
|
memdelete(physics_server_3d);
|
||||||
//finish();
|
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#define PHYSICS_SERVER_3D_WRAP_MT_H
|
#define PHYSICS_SERVER_3D_WRAP_MT_H
|
||||||
|
|
||||||
#include "core/config/project_settings.h"
|
#include "core/config/project_settings.h"
|
||||||
|
#include "core/object/worker_thread_pool.h"
|
||||||
#include "core/os/thread.h"
|
#include "core/os/thread.h"
|
||||||
#include "core/templates/command_queue_mt.h"
|
#include "core/templates/command_queue_mt.h"
|
||||||
#include "servers/physics_server_3d.h"
|
#include "servers/physics_server_3d.h"
|
||||||
@ -42,30 +43,27 @@
|
|||||||
#define SYNC_DEBUG
|
#define SYNC_DEBUG
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
#define MAIN_THREAD_SYNC_WARN WARN_PRINT("Call to " + String(__FUNCTION__) + " causing PhysicsServer3D synchronizations on every frame. This significantly affects performance.");
|
||||||
|
#endif
|
||||||
|
|
||||||
class PhysicsServer3DWrapMT : public PhysicsServer3D {
|
class PhysicsServer3DWrapMT : public PhysicsServer3D {
|
||||||
mutable PhysicsServer3D *physics_server_3d;
|
mutable PhysicsServer3D *physics_server_3d = nullptr;
|
||||||
|
|
||||||
mutable CommandQueueMT command_queue;
|
mutable CommandQueueMT command_queue;
|
||||||
|
|
||||||
static void _thread_callback(void *_instance);
|
|
||||||
void thread_loop();
|
void thread_loop();
|
||||||
|
|
||||||
Thread::ID server_thread;
|
Thread::ID server_thread = Thread::UNASSIGNED_ID;
|
||||||
Thread::ID main_thread;
|
WorkerThreadPool::TaskID server_task_id = WorkerThreadPool::INVALID_TASK_ID;
|
||||||
volatile bool exit = false;
|
bool exit = false;
|
||||||
Thread thread;
|
Semaphore step_sem;
|
||||||
volatile bool step_thread_up = false;
|
|
||||||
bool create_thread = false;
|
bool create_thread = false;
|
||||||
|
|
||||||
Semaphore step_sem;
|
|
||||||
void thread_step(real_t p_delta);
|
void thread_step(real_t p_delta);
|
||||||
|
|
||||||
void thread_exit();
|
void thread_exit();
|
||||||
|
|
||||||
bool first_frame = true;
|
|
||||||
|
|
||||||
Mutex alloc_mutex;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
#define ServerName PhysicsServer3D
|
#define ServerName PhysicsServer3D
|
||||||
#define ServerNameWrapMT PhysicsServer3DWrapMT
|
#define ServerNameWrapMT PhysicsServer3DWrapMT
|
||||||
@ -98,7 +96,7 @@ public:
|
|||||||
#if 0
|
#if 0
|
||||||
//these work well, but should be used from the main thread only
|
//these work well, but should be used from the main thread only
|
||||||
bool shape_collide(RID p_shape_A, const Transform &p_xform_A, const Vector3 &p_motion_A, RID p_shape_B, const Transform &p_xform_B, const Vector3 &p_motion_B, Vector3 *r_results, int p_result_max, int &r_result_count) {
|
bool shape_collide(RID p_shape_A, const Transform &p_xform_A, const Vector3 &p_motion_A, RID p_shape_B, const Transform &p_xform_B, const Vector3 &p_motion_B, Vector3 *r_results, int p_result_max, int &r_result_count) {
|
||||||
ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false);
|
ERR_FAIL_COND_V(!Thread::is_main_thread(), false);
|
||||||
return physics_server_3d->shape_collide(p_shape_A, p_xform_A, p_motion_A, p_shape_B, p_xform_B, p_motion_B, r_results, p_result_max, r_result_count);
|
return physics_server_3d->shape_collide(p_shape_A, p_xform_A, p_motion_A, p_shape_B, p_xform_B, p_motion_B, r_results, p_result_max, r_result_count);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -113,18 +111,18 @@ public:
|
|||||||
|
|
||||||
// this function only works on physics process, errors and returns null otherwise
|
// this function only works on physics process, errors and returns null otherwise
|
||||||
PhysicsDirectSpaceState3D *space_get_direct_state(RID p_space) override {
|
PhysicsDirectSpaceState3D *space_get_direct_state(RID p_space) override {
|
||||||
ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), nullptr);
|
ERR_FAIL_COND_V(!Thread::is_main_thread(), nullptr);
|
||||||
return physics_server_3d->space_get_direct_state(p_space);
|
return physics_server_3d->space_get_direct_state(p_space);
|
||||||
}
|
}
|
||||||
|
|
||||||
FUNC2(space_set_debug_contacts, RID, int);
|
FUNC2(space_set_debug_contacts, RID, int);
|
||||||
virtual Vector<Vector3> space_get_contacts(RID p_space) const override {
|
virtual Vector<Vector3> space_get_contacts(RID p_space) const override {
|
||||||
ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), Vector<Vector3>());
|
ERR_FAIL_COND_V(!Thread::is_main_thread(), Vector<Vector3>());
|
||||||
return physics_server_3d->space_get_contacts(p_space);
|
return physics_server_3d->space_get_contacts(p_space);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int space_get_contact_count(RID p_space) const override {
|
virtual int space_get_contact_count(RID p_space) const override {
|
||||||
ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), 0);
|
ERR_FAIL_COND_V(!Thread::is_main_thread(), 0);
|
||||||
return physics_server_3d->space_get_contact_count(p_space);
|
return physics_server_3d->space_get_contact_count(p_space);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -260,13 +258,13 @@ public:
|
|||||||
FUNC2(body_set_ray_pickable, RID, bool);
|
FUNC2(body_set_ray_pickable, RID, bool);
|
||||||
|
|
||||||
bool body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result = nullptr) override {
|
bool body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result = nullptr) override {
|
||||||
ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false);
|
ERR_FAIL_COND_V(!Thread::is_main_thread(), false);
|
||||||
return physics_server_3d->body_test_motion(p_body, p_parameters, r_result);
|
return physics_server_3d->body_test_motion(p_body, p_parameters, r_result);
|
||||||
}
|
}
|
||||||
|
|
||||||
// this function only works on physics process, errors and returns null otherwise
|
// this function only works on physics process, errors and returns null otherwise
|
||||||
PhysicsDirectBodyState3D *body_get_direct_state(RID p_body) override {
|
PhysicsDirectBodyState3D *body_get_direct_state(RID p_body) override {
|
||||||
ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), nullptr);
|
ERR_FAIL_COND_V(!Thread::is_main_thread(), nullptr);
|
||||||
return physics_server_3d->body_get_direct_state(p_body);
|
return physics_server_3d->body_get_direct_state(p_body);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -411,4 +409,8 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
#undef SYNC_DEBUG
|
#undef SYNC_DEBUG
|
||||||
|
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
#undef MAIN_THREAD_SYNC_WARN
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // PHYSICS_SERVER_3D_WRAP_MT_H
|
#endif // PHYSICS_SERVER_3D_WRAP_MT_H
|
||||||
|
@ -257,7 +257,6 @@ void ParticlesStorage::particles_set_emitting(RID p_particles, bool p_emitting)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool ParticlesStorage::particles_get_emitting(RID p_particles) {
|
bool ParticlesStorage::particles_get_emitting(RID p_particles) {
|
||||||
ERR_FAIL_COND_V_MSG(RSG::threaded, false, "This function should never be used with threaded rendering, as it stalls the renderer.");
|
|
||||||
Particles *particles = particles_owner.get_or_null(p_particles);
|
Particles *particles = particles_owner.get_or_null(p_particles);
|
||||||
ERR_FAIL_NULL_V(particles, false);
|
ERR_FAIL_NULL_V(particles, false);
|
||||||
|
|
||||||
@ -608,10 +607,6 @@ void ParticlesStorage::particles_request_process(RID p_particles) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
AABB ParticlesStorage::particles_get_current_aabb(RID p_particles) {
|
AABB ParticlesStorage::particles_get_current_aabb(RID p_particles) {
|
||||||
if (RSG::threaded) {
|
|
||||||
WARN_PRINT_ONCE("Calling this function with threaded rendering enabled stalls the renderer, use with care.");
|
|
||||||
}
|
|
||||||
|
|
||||||
const Particles *particles = particles_owner.get_or_null(p_particles);
|
const Particles *particles = particles_owner.get_or_null(p_particles);
|
||||||
ERR_FAIL_NULL_V(particles, AABB());
|
ERR_FAIL_NULL_V(particles, AABB());
|
||||||
|
|
||||||
@ -1642,7 +1637,6 @@ Dependency *ParticlesStorage::particles_get_dependency(RID p_particles) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool ParticlesStorage::particles_is_inactive(RID p_particles) const {
|
bool ParticlesStorage::particles_is_inactive(RID p_particles) const {
|
||||||
ERR_FAIL_COND_V_MSG(RSG::threaded, false, "This function should never be used with threaded rendering, as it stalls the renderer.");
|
|
||||||
const Particles *particles = particles_owner.get_or_null(p_particles);
|
const Particles *particles = particles_owner.get_or_null(p_particles);
|
||||||
ERR_FAIL_NULL_V(particles, false);
|
ERR_FAIL_NULL_V(particles, false);
|
||||||
return !particles->emitting && particles->inactive;
|
return !particles->emitting && particles->inactive;
|
||||||
|
@ -69,9 +69,6 @@ void RenderingServerDefault::request_frame_drawn_callback(const Callable &p_call
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
|
void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
|
||||||
//needs to be done before changes is reset to 0, to not force the editor to redraw
|
|
||||||
RS::get_singleton()->emit_signal(SNAME("frame_pre_draw"));
|
|
||||||
|
|
||||||
changes = 0;
|
changes = 0;
|
||||||
|
|
||||||
RSG::rasterizer->begin_frame(frame_step);
|
RSG::rasterizer->begin_frame(frame_step);
|
||||||
@ -220,16 +217,9 @@ void RenderingServerDefault::_finish() {
|
|||||||
|
|
||||||
void RenderingServerDefault::init() {
|
void RenderingServerDefault::init() {
|
||||||
if (create_thread) {
|
if (create_thread) {
|
||||||
print_verbose("RenderingServerWrapMT: Creating render thread");
|
|
||||||
DisplayServer::get_singleton()->release_rendering_thread();
|
|
||||||
if (create_thread) {
|
|
||||||
thread.start(_thread_callback, this);
|
|
||||||
print_verbose("RenderingServerWrapMT: Starting render thread");
|
print_verbose("RenderingServerWrapMT: Starting render thread");
|
||||||
}
|
DisplayServer::get_singleton()->release_rendering_thread();
|
||||||
while (!draw_thread_up.is_set()) {
|
server_task_id = WorkerThreadPool::get_singleton()->add_task(callable_mp(this, &RenderingServerDefault::_thread_loop), true);
|
||||||
OS::get_singleton()->delay_usec(1000);
|
|
||||||
}
|
|
||||||
print_verbose("RenderingServerWrapMT: Finished render thread");
|
|
||||||
} else {
|
} else {
|
||||||
_init();
|
_init();
|
||||||
}
|
}
|
||||||
@ -238,8 +228,9 @@ void RenderingServerDefault::init() {
|
|||||||
void RenderingServerDefault::finish() {
|
void RenderingServerDefault::finish() {
|
||||||
if (create_thread) {
|
if (create_thread) {
|
||||||
command_queue.push(this, &RenderingServerDefault::_thread_exit);
|
command_queue.push(this, &RenderingServerDefault::_thread_exit);
|
||||||
if (thread.is_started()) {
|
if (server_task_id != WorkerThreadPool::INVALID_TASK_ID) {
|
||||||
thread.wait_to_finish();
|
WorkerThreadPool::get_singleton()->wait_for_task_completion(server_task_id);
|
||||||
|
server_task_id = WorkerThreadPool::INVALID_TASK_ID;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_finish();
|
_finish();
|
||||||
@ -337,37 +328,29 @@ Size2i RenderingServerDefault::get_maximum_viewport_size() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RenderingServerDefault::_thread_exit() {
|
void RenderingServerDefault::_thread_exit() {
|
||||||
exit.set();
|
exit = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderingServerDefault::_thread_draw(bool p_swap_buffers, double frame_step) {
|
void RenderingServerDefault::_thread_draw(bool p_swap_buffers, double frame_step) {
|
||||||
_draw(p_swap_buffers, frame_step);
|
_draw(p_swap_buffers, frame_step);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderingServerDefault::_thread_flush() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderingServerDefault::_thread_callback(void *_instance) {
|
|
||||||
RenderingServerDefault *vsmt = reinterpret_cast<RenderingServerDefault *>(_instance);
|
|
||||||
|
|
||||||
vsmt->_thread_loop();
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderingServerDefault::_thread_loop() {
|
void RenderingServerDefault::_thread_loop() {
|
||||||
server_thread = Thread::get_caller_id();
|
server_thread = Thread::get_caller_id();
|
||||||
|
|
||||||
DisplayServer::get_singleton()->gl_window_make_current(DisplayServer::MAIN_WINDOW_ID); // Move GL to this thread.
|
DisplayServer::get_singleton()->gl_window_make_current(DisplayServer::MAIN_WINDOW_ID); // Move GL to this thread.
|
||||||
_init();
|
_init();
|
||||||
|
|
||||||
draw_thread_up.set();
|
command_queue.set_pump_task_id(server_task_id);
|
||||||
while (!exit.is_set()) {
|
while (!exit) {
|
||||||
// flush commands one by one, until exit is requested
|
WorkerThreadPool::get_singleton()->yield();
|
||||||
command_queue.wait_and_flush();
|
command_queue.flush_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
command_queue.flush_all(); // flush all
|
command_queue.flush_all();
|
||||||
|
|
||||||
_finish();
|
_finish();
|
||||||
|
DisplayServer::get_singleton()->release_rendering_thread();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* INTERPOLATION */
|
/* INTERPOLATION */
|
||||||
@ -383,15 +366,15 @@ void RenderingServerDefault::set_physics_interpolation_enabled(bool p_enabled) {
|
|||||||
/* EVENT QUEUING */
|
/* EVENT QUEUING */
|
||||||
|
|
||||||
void RenderingServerDefault::sync() {
|
void RenderingServerDefault::sync() {
|
||||||
if (create_thread) {
|
if (!create_thread) {
|
||||||
command_queue.push_and_sync(this, &RenderingServerDefault::_thread_flush);
|
command_queue.flush_all(); // Flush all pending from other threads.
|
||||||
} else {
|
|
||||||
command_queue.flush_all(); //flush all pending from other threads
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderingServerDefault::draw(bool p_swap_buffers, double frame_step) {
|
void RenderingServerDefault::draw(bool p_swap_buffers, double frame_step) {
|
||||||
ERR_FAIL_COND_MSG(!Thread::is_main_thread(), "Manually triggering the draw function from the RenderingServer can only be done on the main thread. Call this function from the main thread or use call_deferred().");
|
ERR_FAIL_COND_MSG(!Thread::is_main_thread(), "Manually triggering the draw function from the RenderingServer can only be done on the main thread. Call this function from the main thread or use call_deferred().");
|
||||||
|
// Needs to be done before changes is reset to 0, to not force the editor to redraw.
|
||||||
|
RS::get_singleton()->emit_signal(SNAME("frame_pre_draw"));
|
||||||
if (create_thread) {
|
if (create_thread) {
|
||||||
command_queue.push(this, &RenderingServerDefault::_thread_draw, p_swap_buffers, frame_step);
|
command_queue.push(this, &RenderingServerDefault::_thread_draw, p_swap_buffers, frame_step);
|
||||||
} else {
|
} else {
|
||||||
@ -403,21 +386,14 @@ void RenderingServerDefault::_call_on_render_thread(const Callable &p_callable)
|
|||||||
p_callable.call();
|
p_callable.call();
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderingServerDefault::RenderingServerDefault(bool p_create_thread) :
|
RenderingServerDefault::RenderingServerDefault(bool p_create_thread) {
|
||||||
command_queue(p_create_thread) {
|
|
||||||
RenderingServer::init();
|
RenderingServer::init();
|
||||||
|
|
||||||
#ifdef THREADS_ENABLED
|
|
||||||
create_thread = p_create_thread;
|
create_thread = p_create_thread;
|
||||||
if (!create_thread) {
|
if (!create_thread) {
|
||||||
server_thread = Thread::get_caller_id();
|
server_thread = Thread::MAIN_ID;
|
||||||
} else {
|
|
||||||
server_thread = 0;
|
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
create_thread = false;
|
|
||||||
server_thread = Thread::get_main_id();
|
|
||||||
#endif
|
|
||||||
RSG::threaded = create_thread;
|
RSG::threaded = create_thread;
|
||||||
|
|
||||||
RSG::canvas = memnew(RendererCanvasCull);
|
RSG::canvas = memnew(RendererCanvasCull);
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#ifndef RENDERING_SERVER_DEFAULT_H
|
#ifndef RENDERING_SERVER_DEFAULT_H
|
||||||
#define RENDERING_SERVER_DEFAULT_H
|
#define RENDERING_SERVER_DEFAULT_H
|
||||||
|
|
||||||
|
#include "core/object/worker_thread_pool.h"
|
||||||
#include "core/os/thread.h"
|
#include "core/os/thread.h"
|
||||||
#include "core/templates/command_queue_mt.h"
|
#include "core/templates/command_queue_mt.h"
|
||||||
#include "core/templates/hash_map.h"
|
#include "core/templates/hash_map.h"
|
||||||
@ -75,22 +76,17 @@ class RenderingServerDefault : public RenderingServer {
|
|||||||
|
|
||||||
mutable CommandQueueMT command_queue;
|
mutable CommandQueueMT command_queue;
|
||||||
|
|
||||||
static void _thread_callback(void *_instance);
|
|
||||||
void _thread_loop();
|
void _thread_loop();
|
||||||
|
|
||||||
Thread::ID server_thread = 0;
|
Thread::ID server_thread = Thread::UNASSIGNED_ID;
|
||||||
SafeFlag exit;
|
WorkerThreadPool::TaskID server_task_id = WorkerThreadPool::INVALID_TASK_ID;
|
||||||
Thread thread;
|
bool exit = false;
|
||||||
SafeFlag draw_thread_up;
|
bool create_thread = false;
|
||||||
bool create_thread;
|
|
||||||
|
|
||||||
void _thread_draw(bool p_swap_buffers, double frame_step);
|
void _thread_draw(bool p_swap_buffers, double frame_step);
|
||||||
void _thread_flush();
|
|
||||||
|
|
||||||
void _thread_exit();
|
void _thread_exit();
|
||||||
|
|
||||||
Mutex alloc_mutex;
|
|
||||||
|
|
||||||
void _draw(bool p_swap_buffers, double frame_step);
|
void _draw(bool p_swap_buffers, double frame_step);
|
||||||
void _init();
|
void _init();
|
||||||
void _finish();
|
void _finish();
|
||||||
@ -127,6 +123,10 @@ public:
|
|||||||
#define SYNC_DEBUG
|
#define SYNC_DEBUG
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
#define MAIN_THREAD_SYNC_WARN WARN_PRINT("Call to " + String(__FUNCTION__) + " causing RenderingServer synchronizations on every frame. This significantly affects performance.");
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "servers/server_wrap_mt_common.h"
|
#include "servers/server_wrap_mt_common.h"
|
||||||
|
|
||||||
/* TEXTURE API */
|
/* TEXTURE API */
|
||||||
@ -1013,6 +1013,9 @@ public:
|
|||||||
#undef ServerName
|
#undef ServerName
|
||||||
#undef WRITE_ACTION
|
#undef WRITE_ACTION
|
||||||
#undef SYNC_DEBUG
|
#undef SYNC_DEBUG
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
#undef MAIN_THREAD_SYNC_WARN
|
||||||
|
#endif
|
||||||
|
|
||||||
virtual uint64_t get_rendering_info(RenderingInfo p_info) override;
|
virtual uint64_t get_rendering_info(RenderingInfo p_info) override;
|
||||||
virtual RenderingDevice::DeviceType get_video_adapter_type() const override;
|
virtual RenderingDevice::DeviceType get_video_adapter_type() const override;
|
||||||
|
@ -83,25 +83,16 @@ static PackedInt64Array to_int_array(const Vector<ObjectID> &ids) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
PackedInt64Array RenderingServer::_instances_cull_aabb_bind(const AABB &p_aabb, RID p_scenario) const {
|
PackedInt64Array RenderingServer::_instances_cull_aabb_bind(const AABB &p_aabb, RID p_scenario) const {
|
||||||
if (RSG::threaded) {
|
|
||||||
WARN_PRINT_ONCE("Using this function with a threaded renderer hurts performance, as it causes a server stall.");
|
|
||||||
}
|
|
||||||
Vector<ObjectID> ids = instances_cull_aabb(p_aabb, p_scenario);
|
Vector<ObjectID> ids = instances_cull_aabb(p_aabb, p_scenario);
|
||||||
return to_int_array(ids);
|
return to_int_array(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
PackedInt64Array RenderingServer::_instances_cull_ray_bind(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario) const {
|
PackedInt64Array RenderingServer::_instances_cull_ray_bind(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario) const {
|
||||||
if (RSG::threaded) {
|
|
||||||
WARN_PRINT_ONCE("Using this function with a threaded renderer hurts performance, as it causes a server stall.");
|
|
||||||
}
|
|
||||||
Vector<ObjectID> ids = instances_cull_ray(p_from, p_to, p_scenario);
|
Vector<ObjectID> ids = instances_cull_ray(p_from, p_to, p_scenario);
|
||||||
return to_int_array(ids);
|
return to_int_array(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
PackedInt64Array RenderingServer::_instances_cull_convex_bind(const TypedArray<Plane> &p_convex, RID p_scenario) const {
|
PackedInt64Array RenderingServer::_instances_cull_convex_bind(const TypedArray<Plane> &p_convex, RID p_scenario) const {
|
||||||
if (RSG::threaded) {
|
|
||||||
WARN_PRINT_ONCE("Using this function with a threaded renderer hurts performance, as it causes a server stall.");
|
|
||||||
}
|
|
||||||
Vector<Plane> planes;
|
Vector<Plane> planes;
|
||||||
for (int i = 0; i < p_convex.size(); ++i) {
|
for (int i = 0; i < p_convex.size(); ++i) {
|
||||||
const Variant &v = p_convex[i];
|
const Variant &v = p_convex[i];
|
||||||
|
@ -31,12 +31,22 @@
|
|||||||
#ifndef SERVER_WRAP_MT_COMMON_H
|
#ifndef SERVER_WRAP_MT_COMMON_H
|
||||||
#define SERVER_WRAP_MT_COMMON_H
|
#define SERVER_WRAP_MT_COMMON_H
|
||||||
|
|
||||||
|
#ifdef DEBIG_ENABLED
|
||||||
|
#define MAIN_THREAD_SYNC_CHECK \
|
||||||
|
if (unlikely(Thread::is_main_thread() && Engine::get_singleton()->notify_frame_server_synced())) { \
|
||||||
|
MAIN_THREAD_SYNC_WARN \
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define MAIN_THREAD_SYNC_CHECK
|
||||||
|
#endif
|
||||||
|
|
||||||
#define FUNC0R(m_r, m_type) \
|
#define FUNC0R(m_r, m_type) \
|
||||||
virtual m_r m_type() override { \
|
virtual m_r m_type() override { \
|
||||||
if (Thread::get_caller_id() != server_thread) { \
|
if (Thread::get_caller_id() != server_thread) { \
|
||||||
m_r ret; \
|
m_r ret; \
|
||||||
command_queue.push_and_ret(server_name, &ServerName::m_type, &ret); \
|
command_queue.push_and_ret(server_name, &ServerName::m_type, &ret); \
|
||||||
SYNC_DEBUG \
|
SYNC_DEBUG \
|
||||||
|
MAIN_THREAD_SYNC_CHECK \
|
||||||
return ret; \
|
return ret; \
|
||||||
} else { \
|
} else { \
|
||||||
command_queue.flush_if_pending(); \
|
command_queue.flush_if_pending(); \
|
||||||
@ -68,6 +78,7 @@
|
|||||||
m_r ret; \
|
m_r ret; \
|
||||||
command_queue.push_and_ret(server_name, &ServerName::m_type, &ret); \
|
command_queue.push_and_ret(server_name, &ServerName::m_type, &ret); \
|
||||||
SYNC_DEBUG \
|
SYNC_DEBUG \
|
||||||
|
MAIN_THREAD_SYNC_CHECK \
|
||||||
return ret; \
|
return ret; \
|
||||||
} else { \
|
} else { \
|
||||||
command_queue.flush_if_pending(); \
|
command_queue.flush_if_pending(); \
|
||||||
@ -102,6 +113,7 @@
|
|||||||
if (Thread::get_caller_id() != server_thread) { \
|
if (Thread::get_caller_id() != server_thread) { \
|
||||||
command_queue.push_and_sync(server_name, &ServerName::m_type); \
|
command_queue.push_and_sync(server_name, &ServerName::m_type); \
|
||||||
SYNC_DEBUG \
|
SYNC_DEBUG \
|
||||||
|
MAIN_THREAD_SYNC_CHECK \
|
||||||
} else { \
|
} else { \
|
||||||
command_queue.flush_if_pending(); \
|
command_queue.flush_if_pending(); \
|
||||||
server_name->m_type(); \
|
server_name->m_type(); \
|
||||||
@ -113,6 +125,7 @@
|
|||||||
if (Thread::get_caller_id() != server_thread) { \
|
if (Thread::get_caller_id() != server_thread) { \
|
||||||
command_queue.push_and_sync(server_name, &ServerName::m_type); \
|
command_queue.push_and_sync(server_name, &ServerName::m_type); \
|
||||||
SYNC_DEBUG \
|
SYNC_DEBUG \
|
||||||
|
MAIN_THREAD_SYNC_CHECK \
|
||||||
} else { \
|
} else { \
|
||||||
command_queue.flush_if_pending(); \
|
command_queue.flush_if_pending(); \
|
||||||
server_name->m_type(); \
|
server_name->m_type(); \
|
||||||
@ -128,6 +141,7 @@
|
|||||||
m_r ret; \
|
m_r ret; \
|
||||||
command_queue.push_and_ret(server_name, &ServerName::m_type, p1, &ret); \
|
command_queue.push_and_ret(server_name, &ServerName::m_type, p1, &ret); \
|
||||||
SYNC_DEBUG \
|
SYNC_DEBUG \
|
||||||
|
MAIN_THREAD_SYNC_CHECK \
|
||||||
return ret; \
|
return ret; \
|
||||||
} else { \
|
} else { \
|
||||||
command_queue.flush_if_pending(); \
|
command_queue.flush_if_pending(); \
|
||||||
@ -141,6 +155,7 @@
|
|||||||
m_r ret; \
|
m_r ret; \
|
||||||
command_queue.push_and_ret(server_name, &ServerName::m_type, p1, &ret); \
|
command_queue.push_and_ret(server_name, &ServerName::m_type, p1, &ret); \
|
||||||
SYNC_DEBUG \
|
SYNC_DEBUG \
|
||||||
|
MAIN_THREAD_SYNC_CHECK \
|
||||||
return ret; \
|
return ret; \
|
||||||
} else { \
|
} else { \
|
||||||
command_queue.flush_if_pending(); \
|
command_queue.flush_if_pending(); \
|
||||||
@ -154,6 +169,7 @@
|
|||||||
if (Thread::get_caller_id() != server_thread) { \
|
if (Thread::get_caller_id() != server_thread) { \
|
||||||
command_queue.push_and_sync(server_name, &ServerName::m_type, p1); \
|
command_queue.push_and_sync(server_name, &ServerName::m_type, p1); \
|
||||||
SYNC_DEBUG \
|
SYNC_DEBUG \
|
||||||
|
MAIN_THREAD_SYNC_CHECK \
|
||||||
} else { \
|
} else { \
|
||||||
command_queue.flush_if_pending(); \
|
command_queue.flush_if_pending(); \
|
||||||
server_name->m_type(p1); \
|
server_name->m_type(p1); \
|
||||||
@ -165,6 +181,7 @@
|
|||||||
if (Thread::get_caller_id() != server_thread) { \
|
if (Thread::get_caller_id() != server_thread) { \
|
||||||
command_queue.push_and_sync(server_name, &ServerName::m_type, p1); \
|
command_queue.push_and_sync(server_name, &ServerName::m_type, p1); \
|
||||||
SYNC_DEBUG \
|
SYNC_DEBUG \
|
||||||
|
MAIN_THREAD_SYNC_CHECK \
|
||||||
} else { \
|
} else { \
|
||||||
command_queue.flush_if_pending(); \
|
command_queue.flush_if_pending(); \
|
||||||
server_name->m_type(p1); \
|
server_name->m_type(p1); \
|
||||||
@ -199,6 +216,7 @@
|
|||||||
m_r ret; \
|
m_r ret; \
|
||||||
command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, &ret); \
|
command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, &ret); \
|
||||||
SYNC_DEBUG \
|
SYNC_DEBUG \
|
||||||
|
MAIN_THREAD_SYNC_CHECK \
|
||||||
return ret; \
|
return ret; \
|
||||||
} else { \
|
} else { \
|
||||||
command_queue.flush_if_pending(); \
|
command_queue.flush_if_pending(); \
|
||||||
@ -212,6 +230,7 @@
|
|||||||
m_r ret; \
|
m_r ret; \
|
||||||
command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, &ret); \
|
command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, &ret); \
|
||||||
SYNC_DEBUG \
|
SYNC_DEBUG \
|
||||||
|
MAIN_THREAD_SYNC_CHECK \
|
||||||
return ret; \
|
return ret; \
|
||||||
} else { \
|
} else { \
|
||||||
command_queue.flush_if_pending(); \
|
command_queue.flush_if_pending(); \
|
||||||
@ -225,6 +244,7 @@
|
|||||||
if (Thread::get_caller_id() != server_thread) { \
|
if (Thread::get_caller_id() != server_thread) { \
|
||||||
command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2); \
|
command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2); \
|
||||||
SYNC_DEBUG \
|
SYNC_DEBUG \
|
||||||
|
MAIN_THREAD_SYNC_CHECK \
|
||||||
} else { \
|
} else { \
|
||||||
command_queue.flush_if_pending(); \
|
command_queue.flush_if_pending(); \
|
||||||
server_name->m_type(p1, p2); \
|
server_name->m_type(p1, p2); \
|
||||||
@ -236,6 +256,7 @@
|
|||||||
if (Thread::get_caller_id() != server_thread) { \
|
if (Thread::get_caller_id() != server_thread) { \
|
||||||
command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2); \
|
command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2); \
|
||||||
SYNC_DEBUG \
|
SYNC_DEBUG \
|
||||||
|
MAIN_THREAD_SYNC_CHECK \
|
||||||
} else { \
|
} else { \
|
||||||
command_queue.flush_if_pending(); \
|
command_queue.flush_if_pending(); \
|
||||||
server_name->m_type(p1, p2); \
|
server_name->m_type(p1, p2); \
|
||||||
@ -270,6 +291,7 @@
|
|||||||
m_r ret; \
|
m_r ret; \
|
||||||
command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, &ret); \
|
command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, &ret); \
|
||||||
SYNC_DEBUG \
|
SYNC_DEBUG \
|
||||||
|
MAIN_THREAD_SYNC_CHECK \
|
||||||
return ret; \
|
return ret; \
|
||||||
} else { \
|
} else { \
|
||||||
command_queue.flush_if_pending(); \
|
command_queue.flush_if_pending(); \
|
||||||
@ -283,6 +305,7 @@
|
|||||||
m_r ret; \
|
m_r ret; \
|
||||||
command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, &ret); \
|
command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, &ret); \
|
||||||
SYNC_DEBUG \
|
SYNC_DEBUG \
|
||||||
|
MAIN_THREAD_SYNC_CHECK \
|
||||||
return ret; \
|
return ret; \
|
||||||
} else { \
|
} else { \
|
||||||
command_queue.flush_if_pending(); \
|
command_queue.flush_if_pending(); \
|
||||||
@ -296,6 +319,7 @@
|
|||||||
if (Thread::get_caller_id() != server_thread) { \
|
if (Thread::get_caller_id() != server_thread) { \
|
||||||
command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3); \
|
command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3); \
|
||||||
SYNC_DEBUG \
|
SYNC_DEBUG \
|
||||||
|
MAIN_THREAD_SYNC_CHECK \
|
||||||
} else { \
|
} else { \
|
||||||
command_queue.flush_if_pending(); \
|
command_queue.flush_if_pending(); \
|
||||||
server_name->m_type(p1, p2, p3); \
|
server_name->m_type(p1, p2, p3); \
|
||||||
@ -307,6 +331,7 @@
|
|||||||
if (Thread::get_caller_id() != server_thread) { \
|
if (Thread::get_caller_id() != server_thread) { \
|
||||||
command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3); \
|
command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3); \
|
||||||
SYNC_DEBUG \
|
SYNC_DEBUG \
|
||||||
|
MAIN_THREAD_SYNC_CHECK \
|
||||||
} else { \
|
} else { \
|
||||||
command_queue.flush_if_pending(); \
|
command_queue.flush_if_pending(); \
|
||||||
server_name->m_type(p1, p2, p3); \
|
server_name->m_type(p1, p2, p3); \
|
||||||
@ -341,6 +366,7 @@
|
|||||||
m_r ret; \
|
m_r ret; \
|
||||||
command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, &ret); \
|
command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, &ret); \
|
||||||
SYNC_DEBUG \
|
SYNC_DEBUG \
|
||||||
|
MAIN_THREAD_SYNC_CHECK \
|
||||||
return ret; \
|
return ret; \
|
||||||
} else { \
|
} else { \
|
||||||
command_queue.flush_if_pending(); \
|
command_queue.flush_if_pending(); \
|
||||||
@ -354,6 +380,7 @@
|
|||||||
m_r ret; \
|
m_r ret; \
|
||||||
command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, &ret); \
|
command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, &ret); \
|
||||||
SYNC_DEBUG \
|
SYNC_DEBUG \
|
||||||
|
MAIN_THREAD_SYNC_CHECK \
|
||||||
return ret; \
|
return ret; \
|
||||||
} else { \
|
} else { \
|
||||||
command_queue.flush_if_pending(); \
|
command_queue.flush_if_pending(); \
|
||||||
@ -367,6 +394,7 @@
|
|||||||
if (Thread::get_caller_id() != server_thread) { \
|
if (Thread::get_caller_id() != server_thread) { \
|
||||||
command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4); \
|
command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4); \
|
||||||
SYNC_DEBUG \
|
SYNC_DEBUG \
|
||||||
|
MAIN_THREAD_SYNC_CHECK \
|
||||||
} else { \
|
} else { \
|
||||||
command_queue.flush_if_pending(); \
|
command_queue.flush_if_pending(); \
|
||||||
server_name->m_type(p1, p2, p3, p4); \
|
server_name->m_type(p1, p2, p3, p4); \
|
||||||
@ -378,6 +406,7 @@
|
|||||||
if (Thread::get_caller_id() != server_thread) { \
|
if (Thread::get_caller_id() != server_thread) { \
|
||||||
command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4); \
|
command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4); \
|
||||||
SYNC_DEBUG \
|
SYNC_DEBUG \
|
||||||
|
MAIN_THREAD_SYNC_CHECK \
|
||||||
} else { \
|
} else { \
|
||||||
command_queue.flush_if_pending(); \
|
command_queue.flush_if_pending(); \
|
||||||
server_name->m_type(p1, p2, p3, p4); \
|
server_name->m_type(p1, p2, p3, p4); \
|
||||||
@ -412,6 +441,7 @@
|
|||||||
m_r ret; \
|
m_r ret; \
|
||||||
command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, &ret); \
|
command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, &ret); \
|
||||||
SYNC_DEBUG \
|
SYNC_DEBUG \
|
||||||
|
MAIN_THREAD_SYNC_CHECK \
|
||||||
return ret; \
|
return ret; \
|
||||||
} else { \
|
} else { \
|
||||||
command_queue.flush_if_pending(); \
|
command_queue.flush_if_pending(); \
|
||||||
@ -425,6 +455,7 @@
|
|||||||
m_r ret; \
|
m_r ret; \
|
||||||
command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, &ret); \
|
command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, &ret); \
|
||||||
SYNC_DEBUG \
|
SYNC_DEBUG \
|
||||||
|
MAIN_THREAD_SYNC_CHECK \
|
||||||
return ret; \
|
return ret; \
|
||||||
} else { \
|
} else { \
|
||||||
command_queue.flush_if_pending(); \
|
command_queue.flush_if_pending(); \
|
||||||
@ -438,6 +469,7 @@
|
|||||||
if (Thread::get_caller_id() != server_thread) { \
|
if (Thread::get_caller_id() != server_thread) { \
|
||||||
command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5); \
|
command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5); \
|
||||||
SYNC_DEBUG \
|
SYNC_DEBUG \
|
||||||
|
MAIN_THREAD_SYNC_CHECK \
|
||||||
} else { \
|
} else { \
|
||||||
command_queue.flush_if_pending(); \
|
command_queue.flush_if_pending(); \
|
||||||
server_name->m_type(p1, p2, p3, p4, p5); \
|
server_name->m_type(p1, p2, p3, p4, p5); \
|
||||||
@ -449,6 +481,7 @@
|
|||||||
if (Thread::get_caller_id() != server_thread) { \
|
if (Thread::get_caller_id() != server_thread) { \
|
||||||
command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5); \
|
command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5); \
|
||||||
SYNC_DEBUG \
|
SYNC_DEBUG \
|
||||||
|
MAIN_THREAD_SYNC_CHECK \
|
||||||
} else { \
|
} else { \
|
||||||
command_queue.flush_if_pending(); \
|
command_queue.flush_if_pending(); \
|
||||||
server_name->m_type(p1, p2, p3, p4, p5); \
|
server_name->m_type(p1, p2, p3, p4, p5); \
|
||||||
@ -483,6 +516,7 @@
|
|||||||
m_r ret; \
|
m_r ret; \
|
||||||
command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, &ret); \
|
command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, &ret); \
|
||||||
SYNC_DEBUG \
|
SYNC_DEBUG \
|
||||||
|
MAIN_THREAD_SYNC_CHECK \
|
||||||
return ret; \
|
return ret; \
|
||||||
} else { \
|
} else { \
|
||||||
command_queue.flush_if_pending(); \
|
command_queue.flush_if_pending(); \
|
||||||
@ -496,6 +530,7 @@
|
|||||||
m_r ret; \
|
m_r ret; \
|
||||||
command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, &ret); \
|
command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, &ret); \
|
||||||
SYNC_DEBUG \
|
SYNC_DEBUG \
|
||||||
|
MAIN_THREAD_SYNC_CHECK \
|
||||||
return ret; \
|
return ret; \
|
||||||
} else { \
|
} else { \
|
||||||
command_queue.flush_if_pending(); \
|
command_queue.flush_if_pending(); \
|
||||||
@ -509,6 +544,7 @@
|
|||||||
if (Thread::get_caller_id() != server_thread) { \
|
if (Thread::get_caller_id() != server_thread) { \
|
||||||
command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6); \
|
command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6); \
|
||||||
SYNC_DEBUG \
|
SYNC_DEBUG \
|
||||||
|
MAIN_THREAD_SYNC_CHECK \
|
||||||
} else { \
|
} else { \
|
||||||
command_queue.flush_if_pending(); \
|
command_queue.flush_if_pending(); \
|
||||||
server_name->m_type(p1, p2, p3, p4, p5, p6); \
|
server_name->m_type(p1, p2, p3, p4, p5, p6); \
|
||||||
@ -520,6 +556,7 @@
|
|||||||
if (Thread::get_caller_id() != server_thread) { \
|
if (Thread::get_caller_id() != server_thread) { \
|
||||||
command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6); \
|
command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6); \
|
||||||
SYNC_DEBUG \
|
SYNC_DEBUG \
|
||||||
|
MAIN_THREAD_SYNC_CHECK \
|
||||||
} else { \
|
} else { \
|
||||||
command_queue.flush_if_pending(); \
|
command_queue.flush_if_pending(); \
|
||||||
server_name->m_type(p1, p2, p3, p4, p5, p6); \
|
server_name->m_type(p1, p2, p3, p4, p5, p6); \
|
||||||
@ -554,6 +591,7 @@
|
|||||||
m_r ret; \
|
m_r ret; \
|
||||||
command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, &ret); \
|
command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, &ret); \
|
||||||
SYNC_DEBUG \
|
SYNC_DEBUG \
|
||||||
|
MAIN_THREAD_SYNC_CHECK \
|
||||||
return ret; \
|
return ret; \
|
||||||
} else { \
|
} else { \
|
||||||
command_queue.flush_if_pending(); \
|
command_queue.flush_if_pending(); \
|
||||||
@ -567,6 +605,7 @@
|
|||||||
m_r ret; \
|
m_r ret; \
|
||||||
command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, &ret); \
|
command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, &ret); \
|
||||||
SYNC_DEBUG \
|
SYNC_DEBUG \
|
||||||
|
MAIN_THREAD_SYNC_CHECK \
|
||||||
return ret; \
|
return ret; \
|
||||||
} else { \
|
} else { \
|
||||||
command_queue.flush_if_pending(); \
|
command_queue.flush_if_pending(); \
|
||||||
@ -580,6 +619,7 @@
|
|||||||
if (Thread::get_caller_id() != server_thread) { \
|
if (Thread::get_caller_id() != server_thread) { \
|
||||||
command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7); \
|
command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7); \
|
||||||
SYNC_DEBUG \
|
SYNC_DEBUG \
|
||||||
|
MAIN_THREAD_SYNC_CHECK \
|
||||||
} else { \
|
} else { \
|
||||||
command_queue.flush_if_pending(); \
|
command_queue.flush_if_pending(); \
|
||||||
server_name->m_type(p1, p2, p3, p4, p5, p6, p7); \
|
server_name->m_type(p1, p2, p3, p4, p5, p6, p7); \
|
||||||
@ -591,6 +631,7 @@
|
|||||||
if (Thread::get_caller_id() != server_thread) { \
|
if (Thread::get_caller_id() != server_thread) { \
|
||||||
command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7); \
|
command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7); \
|
||||||
SYNC_DEBUG \
|
SYNC_DEBUG \
|
||||||
|
MAIN_THREAD_SYNC_CHECK \
|
||||||
} else { \
|
} else { \
|
||||||
command_queue.flush_if_pending(); \
|
command_queue.flush_if_pending(); \
|
||||||
server_name->m_type(p1, p2, p3, p4, p5, p6, p7); \
|
server_name->m_type(p1, p2, p3, p4, p5, p6, p7); \
|
||||||
@ -625,6 +666,7 @@
|
|||||||
m_r ret; \
|
m_r ret; \
|
||||||
command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8, &ret); \
|
command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8, &ret); \
|
||||||
SYNC_DEBUG \
|
SYNC_DEBUG \
|
||||||
|
MAIN_THREAD_SYNC_CHECK \
|
||||||
return ret; \
|
return ret; \
|
||||||
} else { \
|
} else { \
|
||||||
command_queue.flush_if_pending(); \
|
command_queue.flush_if_pending(); \
|
||||||
@ -638,6 +680,7 @@
|
|||||||
m_r ret; \
|
m_r ret; \
|
||||||
command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8, &ret); \
|
command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8, &ret); \
|
||||||
SYNC_DEBUG \
|
SYNC_DEBUG \
|
||||||
|
MAIN_THREAD_SYNC_CHECK \
|
||||||
return ret; \
|
return ret; \
|
||||||
} else { \
|
} else { \
|
||||||
command_queue.flush_if_pending(); \
|
command_queue.flush_if_pending(); \
|
||||||
@ -651,6 +694,7 @@
|
|||||||
if (Thread::get_caller_id() != server_thread) { \
|
if (Thread::get_caller_id() != server_thread) { \
|
||||||
command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8); \
|
command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8); \
|
||||||
SYNC_DEBUG \
|
SYNC_DEBUG \
|
||||||
|
MAIN_THREAD_SYNC_CHECK \
|
||||||
} else { \
|
} else { \
|
||||||
command_queue.flush_if_pending(); \
|
command_queue.flush_if_pending(); \
|
||||||
server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8); \
|
server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8); \
|
||||||
@ -662,6 +706,7 @@
|
|||||||
if (Thread::get_caller_id() != server_thread) { \
|
if (Thread::get_caller_id() != server_thread) { \
|
||||||
command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8); \
|
command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8); \
|
||||||
SYNC_DEBUG \
|
SYNC_DEBUG \
|
||||||
|
MAIN_THREAD_SYNC_CHECK \
|
||||||
} else { \
|
} else { \
|
||||||
command_queue.flush_if_pending(); \
|
command_queue.flush_if_pending(); \
|
||||||
server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8); \
|
server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8); \
|
||||||
|
Loading…
Reference in New Issue
Block a user