1/**************************************************************************/
2/* rendering_server_default.cpp */
3/**************************************************************************/
4/* This file is part of: */
5/* GODOT ENGINE */
6/* https://godotengine.org */
7/**************************************************************************/
8/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10/* */
11/* Permission is hereby granted, free of charge, to any person obtaining */
12/* a copy of this software and associated documentation files (the */
13/* "Software"), to deal in the Software without restriction, including */
14/* without limitation the rights to use, copy, modify, merge, publish, */
15/* distribute, sublicense, and/or sell copies of the Software, and to */
16/* permit persons to whom the Software is furnished to do so, subject to */
17/* the following conditions: */
18/* */
19/* The above copyright notice and this permission notice shall be */
20/* included in all copies or substantial portions of the Software. */
21/* */
22/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29/**************************************************************************/
30
31#include "rendering_server_default.h"
32
33#include "core/config/project_settings.h"
34#include "core/io/marshalls.h"
35#include "core/os/os.h"
36#include "core/templates/sort_array.h"
37#include "renderer_canvas_cull.h"
38#include "renderer_scene_cull.h"
39#include "rendering_server_globals.h"
40
41// careful, these may run in different threads than the rendering server
42
43int RenderingServerDefault::changes = 0;
44
45/* FREE */
46
47void RenderingServerDefault::_free(RID p_rid) {
48 if (unlikely(p_rid.is_null())) {
49 return;
50 }
51 if (RSG::utilities->free(p_rid)) {
52 return;
53 }
54 if (RSG::canvas->free(p_rid)) {
55 return;
56 }
57 if (RSG::viewport->free(p_rid)) {
58 return;
59 }
60 if (RSG::scene->free(p_rid)) {
61 return;
62 }
63}
64
65/* EVENT QUEUING */
66
67void RenderingServerDefault::request_frame_drawn_callback(const Callable &p_callable) {
68 frame_drawn_callbacks.push_back(p_callable);
69}
70
71void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
72 //needs to be done before changes is reset to 0, to not force the editor to redraw
73 RS::get_singleton()->emit_signal(SNAME("frame_pre_draw"));
74
75 changes = 0;
76
77 RSG::rasterizer->begin_frame(frame_step);
78
79 TIMESTAMP_BEGIN()
80
81 uint64_t time_usec = OS::get_singleton()->get_ticks_usec();
82
83 RSG::scene->update(); //update scenes stuff before updating instances
84
85 frame_setup_time = double(OS::get_singleton()->get_ticks_usec() - time_usec) / 1000.0;
86
87 RSG::particles_storage->update_particles(); //need to be done after instances are updated (colliders and particle transforms), and colliders are rendered
88
89 RSG::scene->render_probes();
90
91 RSG::viewport->draw_viewports();
92 RSG::canvas_render->update();
93
94 if (OS::get_singleton()->get_current_rendering_driver_name() != "opengl3") {
95 // Already called for gl_compatibility renderer.
96 RSG::rasterizer->end_frame(p_swap_buffers);
97 }
98
99 XRServer *xr_server = XRServer::get_singleton();
100 if (xr_server != nullptr) {
101 // let our XR server know we're done so we can get our frame timing
102 xr_server->end_frame();
103 }
104
105 RSG::canvas->update_visibility_notifiers();
106 RSG::scene->update_visibility_notifiers();
107
108 while (frame_drawn_callbacks.front()) {
109 Callable c = frame_drawn_callbacks.front()->get();
110 Variant result;
111 Callable::CallError ce;
112 c.callp(nullptr, 0, result, ce);
113 if (ce.error != Callable::CallError::CALL_OK) {
114 String err = Variant::get_callable_error_text(c, nullptr, 0, ce);
115 ERR_PRINT("Error calling frame drawn function: " + err);
116 }
117
118 frame_drawn_callbacks.pop_front();
119 }
120 RS::get_singleton()->emit_signal(SNAME("frame_post_draw"));
121
122 if (RSG::utilities->get_captured_timestamps_count()) {
123 Vector<FrameProfileArea> new_profile;
124 if (RSG::utilities->capturing_timestamps) {
125 new_profile.resize(RSG::utilities->get_captured_timestamps_count());
126 }
127
128 uint64_t base_cpu = RSG::utilities->get_captured_timestamp_cpu_time(0);
129 uint64_t base_gpu = RSG::utilities->get_captured_timestamp_gpu_time(0);
130 for (uint32_t i = 0; i < RSG::utilities->get_captured_timestamps_count(); i++) {
131 uint64_t time_cpu = RSG::utilities->get_captured_timestamp_cpu_time(i);
132 uint64_t time_gpu = RSG::utilities->get_captured_timestamp_gpu_time(i);
133
134 String name = RSG::utilities->get_captured_timestamp_name(i);
135
136 if (name.begins_with("vp_")) {
137 RSG::viewport->handle_timestamp(name, time_cpu, time_gpu);
138 }
139
140 if (RSG::utilities->capturing_timestamps) {
141 new_profile.write[i].gpu_msec = double((time_gpu - base_gpu) / 1000) / 1000.0;
142 new_profile.write[i].cpu_msec = double(time_cpu - base_cpu) / 1000.0;
143 new_profile.write[i].name = RSG::utilities->get_captured_timestamp_name(i);
144 }
145 }
146
147 frame_profile = new_profile;
148 }
149
150 frame_profile_frame = RSG::utilities->get_captured_timestamps_frame();
151
152 if (print_gpu_profile) {
153 if (print_frame_profile_ticks_from == 0) {
154 print_frame_profile_ticks_from = OS::get_singleton()->get_ticks_usec();
155 }
156 double total_time = 0.0;
157
158 for (int i = 0; i < frame_profile.size() - 1; i++) {
159 String name = frame_profile[i].name;
160 if (name[0] == '<' || name[0] == '>') {
161 continue;
162 }
163
164 double time = frame_profile[i + 1].gpu_msec - frame_profile[i].gpu_msec;
165
166 if (name[0] != '<' && name[0] != '>') {
167 if (print_gpu_profile_task_time.has(name)) {
168 print_gpu_profile_task_time[name] += time;
169 } else {
170 print_gpu_profile_task_time[name] = time;
171 }
172 }
173 }
174
175 if (frame_profile.size()) {
176 total_time = frame_profile[frame_profile.size() - 1].gpu_msec;
177 }
178
179 uint64_t ticks_elapsed = OS::get_singleton()->get_ticks_usec() - print_frame_profile_ticks_from;
180 print_frame_profile_frame_count++;
181 if (ticks_elapsed > 1000000) {
182 print_line("GPU PROFILE (total " + rtos(total_time) + "ms): ");
183
184 float print_threshold = 0.01;
185 for (const KeyValue<String, float> &E : print_gpu_profile_task_time) {
186 double time = E.value / double(print_frame_profile_frame_count);
187 if (time > print_threshold) {
188 print_line("\t-" + E.key + ": " + rtos(time) + "ms");
189 }
190 }
191 print_gpu_profile_task_time.clear();
192 print_frame_profile_ticks_from = OS::get_singleton()->get_ticks_usec();
193 print_frame_profile_frame_count = 0;
194 }
195 }
196
197 RSG::utilities->update_memory_info();
198}
199
200double RenderingServerDefault::get_frame_setup_time_cpu() const {
201 return frame_setup_time;
202}
203
204bool RenderingServerDefault::has_changed() const {
205 return changes > 0;
206}
207
208void RenderingServerDefault::_init() {
209 RSG::rasterizer->initialize();
210}
211
212void RenderingServerDefault::_finish() {
213 if (test_cube.is_valid()) {
214 free(test_cube);
215 }
216
217 RSG::rasterizer->finalize();
218}
219
220void RenderingServerDefault::init() {
221 if (create_thread) {
222 print_verbose("RenderingServerWrapMT: Creating render thread");
223 DisplayServer::get_singleton()->release_rendering_thread();
224 if (create_thread) {
225 thread.start(_thread_callback, this);
226 print_verbose("RenderingServerWrapMT: Starting render thread");
227 }
228 while (!draw_thread_up.is_set()) {
229 OS::get_singleton()->delay_usec(1000);
230 }
231 print_verbose("RenderingServerWrapMT: Finished render thread");
232 } else {
233 _init();
234 }
235}
236
237void RenderingServerDefault::finish() {
238 if (create_thread) {
239 command_queue.push(this, &RenderingServerDefault::_thread_exit);
240 if (thread.is_started()) {
241 thread.wait_to_finish();
242 }
243 } else {
244 _finish();
245 }
246}
247
248/* STATUS INFORMATION */
249
250uint64_t RenderingServerDefault::get_rendering_info(RenderingInfo p_info) {
251 if (p_info == RENDERING_INFO_TOTAL_OBJECTS_IN_FRAME) {
252 return RSG::viewport->get_total_objects_drawn();
253 } else if (p_info == RENDERING_INFO_TOTAL_PRIMITIVES_IN_FRAME) {
254 return RSG::viewport->get_total_primitives_drawn();
255 } else if (p_info == RENDERING_INFO_TOTAL_DRAW_CALLS_IN_FRAME) {
256 return RSG::viewport->get_total_draw_calls_used();
257 }
258 return RSG::utilities->get_rendering_info(p_info);
259}
260
261RenderingDevice::DeviceType RenderingServerDefault::get_video_adapter_type() const {
262 return RSG::utilities->get_video_adapter_type();
263}
264
265void RenderingServerDefault::set_frame_profiling_enabled(bool p_enable) {
266 RSG::utilities->capturing_timestamps = p_enable;
267}
268
269uint64_t RenderingServerDefault::get_frame_profile_frame() {
270 return frame_profile_frame;
271}
272
273Vector<RenderingServer::FrameProfileArea> RenderingServerDefault::get_frame_profile() {
274 return frame_profile;
275}
276
277/* TESTING */
278
279void RenderingServerDefault::set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter) {
280 redraw_request();
281 RSG::rasterizer->set_boot_image(p_image, p_color, p_scale, p_use_filter);
282}
283
284Color RenderingServerDefault::get_default_clear_color() {
285 return RSG::texture_storage->get_default_clear_color();
286}
287
288void RenderingServerDefault::set_default_clear_color(const Color &p_color) {
289 RSG::viewport->set_default_clear_color(p_color);
290}
291
292bool RenderingServerDefault::has_feature(Features p_feature) const {
293 return false;
294}
295
296void RenderingServerDefault::sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) {
297 RSG::scene->sdfgi_set_debug_probe_select(p_position, p_dir);
298}
299
300void RenderingServerDefault::set_print_gpu_profile(bool p_enable) {
301 RSG::utilities->capturing_timestamps = p_enable;
302 print_gpu_profile = p_enable;
303}
304
305RID RenderingServerDefault::get_test_cube() {
306 if (!test_cube.is_valid()) {
307 test_cube = _make_test_cube();
308 }
309 return test_cube;
310}
311
312bool RenderingServerDefault::has_os_feature(const String &p_feature) const {
313 if (RSG::utilities) {
314 return RSG::utilities->has_os_feature(p_feature);
315 } else {
316 return false;
317 }
318}
319
320void RenderingServerDefault::set_debug_generate_wireframes(bool p_generate) {
321 RSG::utilities->set_debug_generate_wireframes(p_generate);
322}
323
324bool RenderingServerDefault::is_low_end() const {
325 return RendererCompositor::is_low_end();
326}
327
328Size2i RenderingServerDefault::get_maximum_viewport_size() const {
329 if (RSG::utilities) {
330 return RSG::utilities->get_maximum_viewport_size();
331 } else {
332 return Size2i();
333 }
334}
335
336void RenderingServerDefault::_thread_exit() {
337 exit.set();
338}
339
340void RenderingServerDefault::_thread_draw(bool p_swap_buffers, double frame_step) {
341 _draw(p_swap_buffers, frame_step);
342}
343
344void RenderingServerDefault::_thread_flush() {
345}
346
347void RenderingServerDefault::_thread_callback(void *_instance) {
348 RenderingServerDefault *vsmt = reinterpret_cast<RenderingServerDefault *>(_instance);
349
350 vsmt->_thread_loop();
351}
352
353void RenderingServerDefault::_thread_loop() {
354 server_thread = Thread::get_caller_id();
355
356 DisplayServer::get_singleton()->make_rendering_thread();
357
358 _init();
359
360 draw_thread_up.set();
361 while (!exit.is_set()) {
362 // flush commands one by one, until exit is requested
363 command_queue.wait_and_flush();
364 }
365
366 command_queue.flush_all(); // flush all
367
368 _finish();
369}
370
371/* EVENT QUEUING */
372
373void RenderingServerDefault::sync() {
374 if (create_thread) {
375 command_queue.push_and_sync(this, &RenderingServerDefault::_thread_flush);
376 } else {
377 command_queue.flush_all(); //flush all pending from other threads
378 }
379}
380
381void RenderingServerDefault::draw(bool p_swap_buffers, double frame_step) {
382 if (create_thread) {
383 command_queue.push(this, &RenderingServerDefault::_thread_draw, p_swap_buffers, frame_step);
384 } else {
385 _draw(p_swap_buffers, frame_step);
386 }
387}
388
389void RenderingServerDefault::_call_on_render_thread(const Callable &p_callable) {
390 Variant ret;
391 Callable::CallError ce;
392 p_callable.callp(nullptr, 0, ret, ce);
393}
394
395RenderingServerDefault::RenderingServerDefault(bool p_create_thread) :
396 command_queue(p_create_thread) {
397 RenderingServer::init();
398
399 create_thread = p_create_thread;
400
401 if (!p_create_thread) {
402 server_thread = Thread::get_caller_id();
403 } else {
404 server_thread = 0;
405 }
406
407 RSG::threaded = p_create_thread;
408 RSG::canvas = memnew(RendererCanvasCull);
409 RSG::viewport = memnew(RendererViewport);
410 RendererSceneCull *sr = memnew(RendererSceneCull);
411 RSG::camera_attributes = memnew(RendererCameraAttributes);
412 RSG::scene = sr;
413 RSG::rasterizer = RendererCompositor::create();
414 RSG::utilities = RSG::rasterizer->get_utilities();
415 RSG::light_storage = RSG::rasterizer->get_light_storage();
416 RSG::material_storage = RSG::rasterizer->get_material_storage();
417 RSG::mesh_storage = RSG::rasterizer->get_mesh_storage();
418 RSG::particles_storage = RSG::rasterizer->get_particles_storage();
419 RSG::texture_storage = RSG::rasterizer->get_texture_storage();
420 RSG::gi = RSG::rasterizer->get_gi();
421 RSG::fog = RSG::rasterizer->get_fog();
422 RSG::canvas_render = RSG::rasterizer->get_canvas();
423 sr->set_scene_render(RSG::rasterizer->get_scene());
424
425 frame_profile_frame = 0;
426}
427
428RenderingServerDefault::~RenderingServerDefault() {
429 memdelete(RSG::canvas);
430 memdelete(RSG::viewport);
431 memdelete(RSG::rasterizer);
432 memdelete(RSG::scene);
433 memdelete(RSG::camera_attributes);
434}
435