Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/servers/rendering/rendering_device.cpp
10277 views
1
/**************************************************************************/
2
/* rendering_device.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_device.h"
32
#include "rendering_device.compat.inc"
33
34
#include "rendering_device_binds.h"
35
#include "shader_include_db.h"
36
37
#include "core/config/project_settings.h"
38
#include "core/io/dir_access.h"
39
#include "modules/modules_enabled.gen.h"
40
41
#ifdef MODULE_GLSLANG_ENABLED
42
#include "modules/glslang/shader_compile.h"
43
#endif
44
45
#define FORCE_SEPARATE_PRESENT_QUEUE 0
46
#define PRINT_FRAMEBUFFER_FORMAT 0
47
48
#define ERR_RENDER_THREAD_MSG String("This function (") + String(__func__) + String(") can only be called from the render thread. ")
49
#define ERR_RENDER_THREAD_GUARD() ERR_FAIL_COND_MSG(render_thread_id != Thread::get_caller_id(), ERR_RENDER_THREAD_MSG);
50
#define ERR_RENDER_THREAD_GUARD_V(m_ret) ERR_FAIL_COND_V_MSG(render_thread_id != Thread::get_caller_id(), (m_ret), ERR_RENDER_THREAD_MSG);
51
52
/**************************/
53
/**** HELPER FUNCTIONS ****/
54
/**************************/
55
56
static String _get_device_vendor_name(const RenderingContextDriver::Device &p_device) {
57
switch (p_device.vendor) {
58
case RenderingContextDriver::Vendor::VENDOR_AMD:
59
return "AMD";
60
case RenderingContextDriver::Vendor::VENDOR_IMGTEC:
61
return "ImgTec";
62
case RenderingContextDriver::Vendor::VENDOR_APPLE:
63
return "Apple";
64
case RenderingContextDriver::Vendor::VENDOR_NVIDIA:
65
return "NVIDIA";
66
case RenderingContextDriver::Vendor::VENDOR_ARM:
67
return "ARM";
68
case RenderingContextDriver::Vendor::VENDOR_MICROSOFT:
69
return "Microsoft";
70
case RenderingContextDriver::Vendor::VENDOR_QUALCOMM:
71
return "Qualcomm";
72
case RenderingContextDriver::Vendor::VENDOR_INTEL:
73
return "Intel";
74
default:
75
return "Unknown";
76
}
77
}
78
79
static String _get_device_type_name(const RenderingContextDriver::Device &p_device) {
80
switch (p_device.type) {
81
case RenderingContextDriver::DEVICE_TYPE_INTEGRATED_GPU:
82
return "Integrated";
83
case RenderingContextDriver::DEVICE_TYPE_DISCRETE_GPU:
84
return "Discrete";
85
case RenderingContextDriver::DEVICE_TYPE_VIRTUAL_GPU:
86
return "Virtual";
87
case RenderingContextDriver::DEVICE_TYPE_CPU:
88
return "CPU";
89
case RenderingContextDriver::DEVICE_TYPE_OTHER:
90
default:
91
return "Other";
92
}
93
}
94
95
static uint32_t _get_device_type_score(const RenderingContextDriver::Device &p_device) {
96
static const bool prefer_integrated = OS::get_singleton()->get_user_prefers_integrated_gpu();
97
switch (p_device.type) {
98
case RenderingContextDriver::DEVICE_TYPE_INTEGRATED_GPU:
99
return prefer_integrated ? 5 : 4;
100
case RenderingContextDriver::DEVICE_TYPE_DISCRETE_GPU:
101
return prefer_integrated ? 4 : 5;
102
case RenderingContextDriver::DEVICE_TYPE_VIRTUAL_GPU:
103
return 3;
104
case RenderingContextDriver::DEVICE_TYPE_CPU:
105
return 2;
106
case RenderingContextDriver::DEVICE_TYPE_OTHER:
107
default:
108
return 1;
109
}
110
}
111
112
/**************************/
113
/**** RENDERING DEVICE ****/
114
/**************************/
115
116
// When true, the command graph will attempt to reorder the rendering commands submitted by the user based on the dependencies detected from
117
// the commands automatically. This should improve rendering performance in most scenarios at the cost of some extra CPU overhead.
118
//
119
// This behavior can be disabled if it's suspected that the graph is not detecting dependencies correctly and more control over the order of
120
// the commands is desired (e.g. debugging).
121
122
#define RENDER_GRAPH_REORDER 1
123
124
// Synchronization barriers are issued between the graph's levels only with the necessary amount of detail to achieve the correct result. If
125
// it's suspected that the graph is not doing this correctly, full barriers can be issued instead that will block all types of operations
126
// between the synchronization levels. This setting will have a very negative impact on performance when enabled, so it's only intended for
127
// debugging purposes.
128
129
#define RENDER_GRAPH_FULL_BARRIERS 0
130
131
// The command graph can automatically issue secondary command buffers and record them on background threads when they reach an arbitrary
132
// size threshold. This can be very beneficial towards reducing the time the main thread takes to record all the rendering commands. However,
133
// this setting is not enabled by default as it's been shown to cause some strange issues with certain IHVs that have yet to be understood.
134
135
#define SECONDARY_COMMAND_BUFFERS_PER_FRAME 0
136
137
RenderingDevice *RenderingDevice::singleton = nullptr;
138
139
RenderingDevice *RenderingDevice::get_singleton() {
140
return singleton;
141
}
142
143
/***************************/
144
/**** ID INFRASTRUCTURE ****/
145
/***************************/
146
147
void RenderingDevice::_add_dependency(RID p_id, RID p_depends_on) {
148
_THREAD_SAFE_METHOD_
149
150
HashSet<RID> *set = dependency_map.getptr(p_depends_on);
151
if (set == nullptr) {
152
set = &dependency_map.insert(p_depends_on, HashSet<RID>())->value;
153
}
154
set->insert(p_id);
155
156
set = reverse_dependency_map.getptr(p_id);
157
if (set == nullptr) {
158
set = &reverse_dependency_map.insert(p_id, HashSet<RID>())->value;
159
}
160
set->insert(p_depends_on);
161
}
162
163
void RenderingDevice::_free_dependencies(RID p_id) {
164
_THREAD_SAFE_METHOD_
165
166
// Direct dependencies must be freed.
167
168
HashMap<RID, HashSet<RID>>::Iterator E = dependency_map.find(p_id);
169
if (E) {
170
while (E->value.size()) {
171
free(*E->value.begin());
172
}
173
dependency_map.remove(E);
174
}
175
176
// Reverse dependencies must be unreferenced.
177
E = reverse_dependency_map.find(p_id);
178
179
if (E) {
180
for (const RID &F : E->value) {
181
HashMap<RID, HashSet<RID>>::Iterator G = dependency_map.find(F);
182
ERR_CONTINUE(!G);
183
ERR_CONTINUE(!G->value.has(p_id));
184
G->value.erase(p_id);
185
}
186
187
reverse_dependency_map.remove(E);
188
}
189
}
190
191
/*******************************/
192
/**** SHADER INFRASTRUCTURE ****/
193
/*******************************/
194
195
Vector<uint8_t> RenderingDevice::shader_compile_spirv_from_source(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language, String *r_error, bool p_allow_cache) {
196
switch (p_language) {
197
#ifdef MODULE_GLSLANG_ENABLED
198
case ShaderLanguage::SHADER_LANGUAGE_GLSL: {
199
ShaderLanguageVersion language_version = driver->get_shader_container_format().get_shader_language_version();
200
ShaderSpirvVersion spirv_version = driver->get_shader_container_format().get_shader_spirv_version();
201
return compile_glslang_shader(p_stage, ShaderIncludeDB::parse_include_files(p_source_code), language_version, spirv_version, r_error);
202
}
203
#endif
204
default:
205
ERR_FAIL_V_MSG(Vector<uint8_t>(), "Shader language is not supported.");
206
}
207
}
208
209
RID RenderingDevice::shader_create_from_spirv(const Vector<ShaderStageSPIRVData> &p_spirv, const String &p_shader_name) {
210
Vector<uint8_t> bytecode = shader_compile_binary_from_spirv(p_spirv, p_shader_name);
211
ERR_FAIL_COND_V(bytecode.is_empty(), RID());
212
return shader_create_from_bytecode(bytecode);
213
}
214
215
/***************************/
216
/**** BUFFER MANAGEMENT ****/
217
/***************************/
218
219
RenderingDevice::Buffer *RenderingDevice::_get_buffer_from_owner(RID p_buffer) {
220
Buffer *buffer = nullptr;
221
if (vertex_buffer_owner.owns(p_buffer)) {
222
buffer = vertex_buffer_owner.get_or_null(p_buffer);
223
} else if (index_buffer_owner.owns(p_buffer)) {
224
buffer = index_buffer_owner.get_or_null(p_buffer);
225
} else if (uniform_buffer_owner.owns(p_buffer)) {
226
buffer = uniform_buffer_owner.get_or_null(p_buffer);
227
} else if (texture_buffer_owner.owns(p_buffer)) {
228
DEV_ASSERT(false && "FIXME: Broken.");
229
//buffer = texture_buffer_owner.get_or_null(p_buffer)->buffer;
230
} else if (storage_buffer_owner.owns(p_buffer)) {
231
buffer = storage_buffer_owner.get_or_null(p_buffer);
232
}
233
return buffer;
234
}
235
236
Error RenderingDevice::_buffer_initialize(Buffer *p_buffer, Span<uint8_t> p_data, uint32_t p_required_align) {
237
uint32_t transfer_worker_offset;
238
TransferWorker *transfer_worker = _acquire_transfer_worker(p_data.size(), p_required_align, transfer_worker_offset);
239
p_buffer->transfer_worker_index = transfer_worker->index;
240
241
{
242
MutexLock lock(transfer_worker->operations_mutex);
243
p_buffer->transfer_worker_operation = ++transfer_worker->operations_counter;
244
}
245
246
// Copy to the worker's staging buffer.
247
uint8_t *data_ptr = driver->buffer_map(transfer_worker->staging_buffer);
248
ERR_FAIL_NULL_V(data_ptr, ERR_CANT_CREATE);
249
250
memcpy(data_ptr + transfer_worker_offset, p_data.ptr(), p_data.size());
251
driver->buffer_unmap(transfer_worker->staging_buffer);
252
253
// Copy from the staging buffer to the real buffer.
254
RDD::BufferCopyRegion region;
255
region.src_offset = transfer_worker_offset;
256
region.dst_offset = 0;
257
region.size = p_data.size();
258
driver->command_copy_buffer(transfer_worker->command_buffer, transfer_worker->staging_buffer, p_buffer->driver_id, region);
259
260
_release_transfer_worker(transfer_worker);
261
262
return OK;
263
}
264
265
Error RenderingDevice::_insert_staging_block(StagingBuffers &p_staging_buffers) {
266
StagingBufferBlock block;
267
268
block.driver_id = driver->buffer_create(p_staging_buffers.block_size, p_staging_buffers.usage_bits, RDD::MEMORY_ALLOCATION_TYPE_CPU);
269
ERR_FAIL_COND_V(!block.driver_id, ERR_CANT_CREATE);
270
271
block.frame_used = 0;
272
block.fill_amount = 0;
273
274
p_staging_buffers.blocks.insert(p_staging_buffers.current, block);
275
return OK;
276
}
277
278
Error RenderingDevice::_staging_buffer_allocate(StagingBuffers &p_staging_buffers, uint32_t p_amount, uint32_t p_required_align, uint32_t &r_alloc_offset, uint32_t &r_alloc_size, StagingRequiredAction &r_required_action, bool p_can_segment) {
279
// Determine a block to use.
280
281
r_alloc_size = p_amount;
282
r_required_action = STAGING_REQUIRED_ACTION_NONE;
283
284
while (true) {
285
r_alloc_offset = 0;
286
287
// See if we can use current block.
288
if (p_staging_buffers.blocks[p_staging_buffers.current].frame_used == frames_drawn) {
289
// We used this block this frame, let's see if there is still room.
290
291
uint32_t write_from = p_staging_buffers.blocks[p_staging_buffers.current].fill_amount;
292
293
{
294
uint32_t align_remainder = write_from % p_required_align;
295
if (align_remainder != 0) {
296
write_from += p_required_align - align_remainder;
297
}
298
}
299
300
int32_t available_bytes = int32_t(p_staging_buffers.block_size) - int32_t(write_from);
301
302
if ((int32_t)p_amount < available_bytes) {
303
// All is good, we should be ok, all will fit.
304
r_alloc_offset = write_from;
305
} else if (p_can_segment && available_bytes >= (int32_t)p_required_align) {
306
// Ok all won't fit but at least we can fit a chunkie.
307
// All is good, update what needs to be written to.
308
r_alloc_offset = write_from;
309
r_alloc_size = available_bytes - (available_bytes % p_required_align);
310
311
} else {
312
// Can't fit it into this buffer.
313
// Will need to try next buffer.
314
315
p_staging_buffers.current = (p_staging_buffers.current + 1) % p_staging_buffers.blocks.size();
316
317
// Before doing anything, though, let's check that we didn't manage to fill all blocks.
318
// Possible in a single frame.
319
if (p_staging_buffers.blocks[p_staging_buffers.current].frame_used == frames_drawn) {
320
// Guess we did.. ok, let's see if we can insert a new block.
321
if ((uint64_t)p_staging_buffers.blocks.size() * p_staging_buffers.block_size < p_staging_buffers.max_size) {
322
// We can, so we are safe.
323
Error err = _insert_staging_block(p_staging_buffers);
324
if (err) {
325
return err;
326
}
327
// Claim for this frame.
328
p_staging_buffers.blocks.write[p_staging_buffers.current].frame_used = frames_drawn;
329
} else {
330
// Ok, worst case scenario, all the staging buffers belong to this frame
331
// and this frame is not even done.
332
// If this is the main thread, it means the user is likely loading a lot of resources at once,.
333
// Otherwise, the thread should just be blocked until the next frame (currently unimplemented).
334
r_required_action = STAGING_REQUIRED_ACTION_FLUSH_AND_STALL_ALL;
335
}
336
337
} else {
338
// Not from current frame, so continue and try again.
339
continue;
340
}
341
}
342
343
} else if (p_staging_buffers.blocks[p_staging_buffers.current].frame_used <= frames_drawn - frames.size()) {
344
// This is an old block, which was already processed, let's reuse.
345
p_staging_buffers.blocks.write[p_staging_buffers.current].frame_used = frames_drawn;
346
p_staging_buffers.blocks.write[p_staging_buffers.current].fill_amount = 0;
347
} else {
348
// This block may still be in use, let's not touch it unless we have to, so.. can we create a new one?
349
if ((uint64_t)p_staging_buffers.blocks.size() * p_staging_buffers.block_size < p_staging_buffers.max_size) {
350
// We are still allowed to create a new block, so let's do that and insert it for current pos.
351
Error err = _insert_staging_block(p_staging_buffers);
352
if (err) {
353
return err;
354
}
355
// Claim for this frame.
356
p_staging_buffers.blocks.write[p_staging_buffers.current].frame_used = frames_drawn;
357
} else {
358
// Oops, we are out of room and we can't create more.
359
// Let's flush older frames.
360
// The logic here is that if a game is loading a lot of data from the main thread, it will need to be stalled anyway.
361
// If loading from a separate thread, we can block that thread until next frame when more room is made (not currently implemented, though).
362
r_required_action = STAGING_REQUIRED_ACTION_STALL_PREVIOUS;
363
}
364
}
365
366
// All was good, break.
367
break;
368
}
369
370
p_staging_buffers.used = true;
371
372
return OK;
373
}
374
375
void RenderingDevice::_staging_buffer_execute_required_action(StagingBuffers &p_staging_buffers, StagingRequiredAction p_required_action) {
376
switch (p_required_action) {
377
case STAGING_REQUIRED_ACTION_NONE: {
378
// Do nothing.
379
} break;
380
case STAGING_REQUIRED_ACTION_FLUSH_AND_STALL_ALL: {
381
_flush_and_stall_for_all_frames();
382
383
// Clear the whole staging buffer.
384
for (int i = 0; i < p_staging_buffers.blocks.size(); i++) {
385
p_staging_buffers.blocks.write[i].frame_used = 0;
386
p_staging_buffers.blocks.write[i].fill_amount = 0;
387
}
388
389
// Claim for current frame.
390
p_staging_buffers.blocks.write[p_staging_buffers.current].frame_used = frames_drawn;
391
} break;
392
case STAGING_REQUIRED_ACTION_STALL_PREVIOUS: {
393
_stall_for_previous_frames();
394
395
for (int i = 0; i < p_staging_buffers.blocks.size(); i++) {
396
// Clear all blocks but the ones from this frame.
397
int block_idx = (i + p_staging_buffers.current) % p_staging_buffers.blocks.size();
398
if (p_staging_buffers.blocks[block_idx].frame_used == frames_drawn) {
399
break; // Ok, we reached something from this frame, abort.
400
}
401
402
p_staging_buffers.blocks.write[block_idx].frame_used = 0;
403
p_staging_buffers.blocks.write[block_idx].fill_amount = 0;
404
}
405
406
// Claim for current frame.
407
p_staging_buffers.blocks.write[p_staging_buffers.current].frame_used = frames_drawn;
408
} break;
409
default: {
410
DEV_ASSERT(false && "Unknown required action.");
411
} break;
412
}
413
}
414
415
Error RenderingDevice::buffer_copy(RID p_src_buffer, RID p_dst_buffer, uint32_t p_src_offset, uint32_t p_dst_offset, uint32_t p_size) {
416
ERR_RENDER_THREAD_GUARD_V(ERR_UNAVAILABLE);
417
418
ERR_FAIL_COND_V_MSG(draw_list.active, ERR_INVALID_PARAMETER,
419
"Copying buffers is forbidden during creation of a draw list");
420
ERR_FAIL_COND_V_MSG(compute_list.active, ERR_INVALID_PARAMETER,
421
"Copying buffers is forbidden during creation of a compute list");
422
423
Buffer *src_buffer = _get_buffer_from_owner(p_src_buffer);
424
if (!src_buffer) {
425
ERR_FAIL_V_MSG(ERR_INVALID_PARAMETER, "Source buffer argument is not a valid buffer of any type.");
426
}
427
428
Buffer *dst_buffer = _get_buffer_from_owner(p_dst_buffer);
429
if (!dst_buffer) {
430
ERR_FAIL_V_MSG(ERR_INVALID_PARAMETER, "Destination buffer argument is not a valid buffer of any type.");
431
}
432
433
// Validate the copy's dimensions for both buffers.
434
ERR_FAIL_COND_V_MSG((p_size + p_src_offset) > src_buffer->size, ERR_INVALID_PARAMETER, "Size is larger than the source buffer.");
435
ERR_FAIL_COND_V_MSG((p_size + p_dst_offset) > dst_buffer->size, ERR_INVALID_PARAMETER, "Size is larger than the destination buffer.");
436
437
_check_transfer_worker_buffer(src_buffer);
438
_check_transfer_worker_buffer(dst_buffer);
439
440
// Perform the copy.
441
RDD::BufferCopyRegion region;
442
region.src_offset = p_src_offset;
443
region.dst_offset = p_dst_offset;
444
region.size = p_size;
445
446
if (_buffer_make_mutable(dst_buffer, p_dst_buffer)) {
447
// The destination buffer must be mutable to be used as a copy destination.
448
draw_graph.add_synchronization();
449
}
450
451
draw_graph.add_buffer_copy(src_buffer->driver_id, src_buffer->draw_tracker, dst_buffer->driver_id, dst_buffer->draw_tracker, region);
452
453
return OK;
454
}
455
456
Error RenderingDevice::buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const void *p_data) {
457
ERR_RENDER_THREAD_GUARD_V(ERR_UNAVAILABLE);
458
459
copy_bytes_count += p_size;
460
ERR_FAIL_COND_V_MSG(draw_list.active, ERR_INVALID_PARAMETER,
461
"Updating buffers is forbidden during creation of a draw list");
462
ERR_FAIL_COND_V_MSG(compute_list.active, ERR_INVALID_PARAMETER,
463
"Updating buffers is forbidden during creation of a compute list");
464
465
Buffer *buffer = _get_buffer_from_owner(p_buffer);
466
ERR_FAIL_NULL_V_MSG(buffer, ERR_INVALID_PARAMETER, "Buffer argument is not a valid buffer of any type.");
467
ERR_FAIL_COND_V_MSG(p_offset + p_size > buffer->size, ERR_INVALID_PARAMETER, "Attempted to write buffer (" + itos((p_offset + p_size) - buffer->size) + " bytes) past the end.");
468
469
_check_transfer_worker_buffer(buffer);
470
471
// Submitting may get chunked for various reasons, so convert this to a task.
472
size_t to_submit = p_size;
473
size_t submit_from = 0;
474
475
thread_local LocalVector<RDG::RecordedBufferCopy> command_buffer_copies_vector;
476
command_buffer_copies_vector.clear();
477
478
const uint8_t *src_data = reinterpret_cast<const uint8_t *>(p_data);
479
const uint32_t required_align = 32;
480
while (to_submit > 0) {
481
uint32_t block_write_offset;
482
uint32_t block_write_amount;
483
StagingRequiredAction required_action;
484
485
Error err = _staging_buffer_allocate(upload_staging_buffers, MIN(to_submit, upload_staging_buffers.block_size), required_align, block_write_offset, block_write_amount, required_action);
486
if (err) {
487
return err;
488
}
489
490
if (!command_buffer_copies_vector.is_empty() && required_action == STAGING_REQUIRED_ACTION_FLUSH_AND_STALL_ALL) {
491
if (_buffer_make_mutable(buffer, p_buffer)) {
492
// The buffer must be mutable to be used as a copy destination.
493
draw_graph.add_synchronization();
494
}
495
496
draw_graph.add_buffer_update(buffer->driver_id, buffer->draw_tracker, command_buffer_copies_vector);
497
command_buffer_copies_vector.clear();
498
}
499
500
_staging_buffer_execute_required_action(upload_staging_buffers, required_action);
501
502
// Map staging buffer (It's CPU and coherent).
503
uint8_t *data_ptr = driver->buffer_map(upload_staging_buffers.blocks[upload_staging_buffers.current].driver_id);
504
ERR_FAIL_NULL_V(data_ptr, ERR_CANT_CREATE);
505
506
// Copy to staging buffer.
507
memcpy(data_ptr + block_write_offset, src_data + submit_from, block_write_amount);
508
509
// Unmap.
510
driver->buffer_unmap(upload_staging_buffers.blocks[upload_staging_buffers.current].driver_id);
511
512
// Insert a command to copy this.
513
RDD::BufferCopyRegion region;
514
region.src_offset = block_write_offset;
515
region.dst_offset = submit_from + p_offset;
516
region.size = block_write_amount;
517
518
RDG::RecordedBufferCopy buffer_copy;
519
buffer_copy.source = upload_staging_buffers.blocks[upload_staging_buffers.current].driver_id;
520
buffer_copy.region = region;
521
command_buffer_copies_vector.push_back(buffer_copy);
522
523
upload_staging_buffers.blocks.write[upload_staging_buffers.current].fill_amount = block_write_offset + block_write_amount;
524
525
to_submit -= block_write_amount;
526
submit_from += block_write_amount;
527
}
528
529
if (!command_buffer_copies_vector.is_empty()) {
530
if (_buffer_make_mutable(buffer, p_buffer)) {
531
// The buffer must be mutable to be used as a copy destination.
532
draw_graph.add_synchronization();
533
}
534
535
draw_graph.add_buffer_update(buffer->driver_id, buffer->draw_tracker, command_buffer_copies_vector);
536
}
537
538
gpu_copy_count++;
539
540
return OK;
541
}
542
543
Error RenderingDevice::driver_callback_add(RDD::DriverCallback p_callback, void *p_userdata, VectorView<CallbackResource> p_resources) {
544
ERR_RENDER_THREAD_GUARD_V(ERR_UNAVAILABLE);
545
546
ERR_FAIL_COND_V_MSG(draw_list.active, ERR_INVALID_PARAMETER,
547
"Driver callback is forbidden during creation of a draw list");
548
ERR_FAIL_COND_V_MSG(compute_list.active, ERR_INVALID_PARAMETER,
549
"Driver callback is forbidden during creation of a compute list");
550
551
thread_local LocalVector<RDG::ResourceTracker *> trackers;
552
thread_local LocalVector<RDG::ResourceUsage> usages;
553
554
uint32_t resource_count = p_resources.size();
555
trackers.resize(resource_count);
556
usages.resize(resource_count);
557
558
if (resource_count > 0) {
559
for (uint32_t i = 0; i < p_resources.size(); i++) {
560
const CallbackResource &cr = p_resources[i];
561
switch (cr.type) {
562
case CALLBACK_RESOURCE_TYPE_BUFFER: {
563
Buffer *buffer = _get_buffer_from_owner(cr.rid);
564
if (!buffer) {
565
ERR_FAIL_V_MSG(ERR_INVALID_PARAMETER, vformat("Argument %d is not a valid buffer of any type.", i));
566
}
567
if (_buffer_make_mutable(buffer, cr.rid)) {
568
draw_graph.add_synchronization();
569
}
570
trackers[i] = buffer->draw_tracker;
571
usages[i] = (RDG::ResourceUsage)cr.usage;
572
} break;
573
case CALLBACK_RESOURCE_TYPE_TEXTURE: {
574
Texture *texture = texture_owner.get_or_null(cr.rid);
575
if (!texture) {
576
ERR_FAIL_V_MSG(ERR_INVALID_PARAMETER, vformat("Argument %d is not a valid texture.", i));
577
}
578
if (_texture_make_mutable(texture, cr.rid)) {
579
draw_graph.add_synchronization();
580
}
581
trackers[i] = texture->draw_tracker;
582
usages[i] = (RDG::ResourceUsage)cr.usage;
583
} break;
584
default: {
585
CRASH_NOW_MSG("Invalid callback resource type.");
586
} break;
587
}
588
}
589
}
590
591
draw_graph.add_driver_callback(p_callback, p_userdata, trackers, usages);
592
593
return OK;
594
}
595
596
String RenderingDevice::get_perf_report() const {
597
String perf_report_text;
598
perf_report_text += " gpu:" + String::num_int64(prev_gpu_copy_count);
599
perf_report_text += " bytes:" + String::num_int64(prev_copy_bytes_count);
600
601
perf_report_text += " lazily alloc:" + String::num_int64(driver->get_lazily_memory_used());
602
return perf_report_text;
603
}
604
605
void RenderingDevice::update_perf_report() {
606
prev_gpu_copy_count = gpu_copy_count;
607
prev_copy_bytes_count = copy_bytes_count;
608
gpu_copy_count = 0;
609
copy_bytes_count = 0;
610
}
611
612
Error RenderingDevice::buffer_clear(RID p_buffer, uint32_t p_offset, uint32_t p_size) {
613
ERR_RENDER_THREAD_GUARD_V(ERR_UNAVAILABLE);
614
615
ERR_FAIL_COND_V_MSG((p_size % 4) != 0, ERR_INVALID_PARAMETER,
616
"Size must be a multiple of four");
617
ERR_FAIL_COND_V_MSG(draw_list.active, ERR_INVALID_PARAMETER,
618
"Updating buffers in is forbidden during creation of a draw list");
619
ERR_FAIL_COND_V_MSG(compute_list.active, ERR_INVALID_PARAMETER,
620
"Updating buffers is forbidden during creation of a compute list");
621
622
Buffer *buffer = _get_buffer_from_owner(p_buffer);
623
if (!buffer) {
624
ERR_FAIL_V_MSG(ERR_INVALID_PARAMETER, "Buffer argument is not a valid buffer of any type.");
625
}
626
627
ERR_FAIL_COND_V_MSG(p_offset + p_size > buffer->size, ERR_INVALID_PARAMETER,
628
"Attempted to write buffer (" + itos((p_offset + p_size) - buffer->size) + " bytes) past the end.");
629
630
_check_transfer_worker_buffer(buffer);
631
632
if (_buffer_make_mutable(buffer, p_buffer)) {
633
// The destination buffer must be mutable to be used as a clear destination.
634
draw_graph.add_synchronization();
635
}
636
637
draw_graph.add_buffer_clear(buffer->driver_id, buffer->draw_tracker, p_offset, p_size);
638
639
return OK;
640
}
641
642
Vector<uint8_t> RenderingDevice::buffer_get_data(RID p_buffer, uint32_t p_offset, uint32_t p_size) {
643
ERR_RENDER_THREAD_GUARD_V(Vector<uint8_t>());
644
645
Buffer *buffer = _get_buffer_from_owner(p_buffer);
646
if (!buffer) {
647
ERR_FAIL_V_MSG(Vector<uint8_t>(), "Buffer is either invalid or this type of buffer can't be retrieved.");
648
}
649
650
// Size of buffer to retrieve.
651
if (!p_size) {
652
p_size = buffer->size;
653
} else {
654
ERR_FAIL_COND_V_MSG(p_size + p_offset > buffer->size, Vector<uint8_t>(),
655
"Size is larger than the buffer.");
656
}
657
658
_check_transfer_worker_buffer(buffer);
659
660
RDD::BufferID tmp_buffer = driver->buffer_create(buffer->size, RDD::BUFFER_USAGE_TRANSFER_TO_BIT, RDD::MEMORY_ALLOCATION_TYPE_CPU);
661
ERR_FAIL_COND_V(!tmp_buffer, Vector<uint8_t>());
662
663
RDD::BufferCopyRegion region;
664
region.src_offset = p_offset;
665
region.size = p_size;
666
667
draw_graph.add_buffer_get_data(buffer->driver_id, buffer->draw_tracker, tmp_buffer, region);
668
669
// Flush everything so memory can be safely mapped.
670
_flush_and_stall_for_all_frames();
671
672
uint8_t *buffer_mem = driver->buffer_map(tmp_buffer);
673
ERR_FAIL_NULL_V(buffer_mem, Vector<uint8_t>());
674
675
Vector<uint8_t> buffer_data;
676
{
677
buffer_data.resize(p_size);
678
uint8_t *w = buffer_data.ptrw();
679
memcpy(w, buffer_mem, p_size);
680
}
681
682
driver->buffer_unmap(tmp_buffer);
683
684
driver->buffer_free(tmp_buffer);
685
686
return buffer_data;
687
}
688
689
Error RenderingDevice::buffer_get_data_async(RID p_buffer, const Callable &p_callback, uint32_t p_offset, uint32_t p_size) {
690
ERR_RENDER_THREAD_GUARD_V(ERR_UNAVAILABLE);
691
692
Buffer *buffer = _get_buffer_from_owner(p_buffer);
693
if (buffer == nullptr) {
694
ERR_FAIL_V_MSG(ERR_INVALID_PARAMETER, "Buffer is either invalid or this type of buffer can't be retrieved.");
695
}
696
697
if (p_size == 0) {
698
p_size = buffer->size;
699
}
700
701
ERR_FAIL_COND_V_MSG(p_size + p_offset > buffer->size, ERR_INVALID_PARAMETER, "Size is larger than the buffer.");
702
ERR_FAIL_COND_V_MSG(!p_callback.is_valid(), ERR_INVALID_PARAMETER, "Callback must be valid.");
703
704
_check_transfer_worker_buffer(buffer);
705
706
BufferGetDataRequest get_data_request;
707
get_data_request.callback = p_callback;
708
get_data_request.frame_local_index = frames[frame].download_buffer_copy_regions.size();
709
get_data_request.size = p_size;
710
711
const uint32_t required_align = 32;
712
uint32_t block_write_offset;
713
uint32_t block_write_amount;
714
StagingRequiredAction required_action;
715
uint32_t to_submit = p_size;
716
uint32_t submit_from = 0;
717
while (to_submit > 0) {
718
Error err = _staging_buffer_allocate(download_staging_buffers, MIN(to_submit, download_staging_buffers.block_size), required_align, block_write_offset, block_write_amount, required_action);
719
if (err) {
720
return err;
721
}
722
723
const bool flush_frames = (get_data_request.frame_local_count > 0) && required_action == STAGING_REQUIRED_ACTION_FLUSH_AND_STALL_ALL;
724
if (flush_frames) {
725
if (_buffer_make_mutable(buffer, p_buffer)) {
726
// The buffer must be mutable to be used as a copy source.
727
draw_graph.add_synchronization();
728
}
729
730
for (uint32_t i = 0; i < get_data_request.frame_local_count; i++) {
731
uint32_t local_index = get_data_request.frame_local_index + i;
732
draw_graph.add_buffer_get_data(buffer->driver_id, buffer->draw_tracker, frames[frame].download_buffer_staging_buffers[local_index], frames[frame].download_buffer_copy_regions[local_index]);
733
}
734
}
735
736
_staging_buffer_execute_required_action(download_staging_buffers, required_action);
737
738
if (flush_frames) {
739
get_data_request.frame_local_count = 0;
740
get_data_request.frame_local_index = frames[frame].download_buffer_copy_regions.size();
741
}
742
743
RDD::BufferCopyRegion region;
744
region.src_offset = submit_from + p_offset;
745
region.dst_offset = block_write_offset;
746
region.size = block_write_amount;
747
748
frames[frame].download_buffer_staging_buffers.push_back(download_staging_buffers.blocks[download_staging_buffers.current].driver_id);
749
frames[frame].download_buffer_copy_regions.push_back(region);
750
get_data_request.frame_local_count++;
751
752
download_staging_buffers.blocks.write[download_staging_buffers.current].fill_amount = block_write_offset + block_write_amount;
753
754
to_submit -= block_write_amount;
755
submit_from += block_write_amount;
756
}
757
758
if (get_data_request.frame_local_count > 0) {
759
if (_buffer_make_mutable(buffer, p_buffer)) {
760
// The buffer must be mutable to be used as a copy source.
761
draw_graph.add_synchronization();
762
}
763
764
for (uint32_t i = 0; i < get_data_request.frame_local_count; i++) {
765
uint32_t local_index = get_data_request.frame_local_index + i;
766
draw_graph.add_buffer_get_data(buffer->driver_id, buffer->draw_tracker, frames[frame].download_buffer_staging_buffers[local_index], frames[frame].download_buffer_copy_regions[local_index]);
767
}
768
769
frames[frame].download_buffer_get_data_requests.push_back(get_data_request);
770
}
771
772
return OK;
773
}
774
775
uint64_t RenderingDevice::buffer_get_device_address(RID p_buffer) {
776
ERR_RENDER_THREAD_GUARD_V(0);
777
778
Buffer *buffer = _get_buffer_from_owner(p_buffer);
779
ERR_FAIL_NULL_V_MSG(buffer, 0, "Buffer argument is not a valid buffer of any type.");
780
ERR_FAIL_COND_V_MSG(!buffer->usage.has_flag(RDD::BUFFER_USAGE_DEVICE_ADDRESS_BIT), 0, "Buffer was not created with device address flag.");
781
782
return driver->buffer_get_device_address(buffer->driver_id);
783
}
784
785
RID RenderingDevice::storage_buffer_create(uint32_t p_size_bytes, Span<uint8_t> p_data, BitField<StorageBufferUsage> p_usage, BitField<BufferCreationBits> p_creation_bits) {
786
ERR_FAIL_COND_V(p_data.size() && (uint32_t)p_data.size() != p_size_bytes, RID());
787
788
Buffer buffer;
789
buffer.size = p_size_bytes;
790
buffer.usage = (RDD::BUFFER_USAGE_TRANSFER_FROM_BIT | RDD::BUFFER_USAGE_TRANSFER_TO_BIT | RDD::BUFFER_USAGE_STORAGE_BIT);
791
if (p_usage.has_flag(STORAGE_BUFFER_USAGE_DISPATCH_INDIRECT)) {
792
buffer.usage.set_flag(RDD::BUFFER_USAGE_INDIRECT_BIT);
793
}
794
if (p_creation_bits.has_flag(BUFFER_CREATION_DEVICE_ADDRESS_BIT)) {
795
#ifdef DEBUG_ENABLED
796
ERR_FAIL_COND_V_MSG(!has_feature(SUPPORTS_BUFFER_DEVICE_ADDRESS), RID(),
797
"The GPU doesn't support buffer address flag.");
798
#endif
799
800
buffer.usage.set_flag(RDD::BUFFER_USAGE_DEVICE_ADDRESS_BIT);
801
}
802
buffer.driver_id = driver->buffer_create(buffer.size, buffer.usage, RDD::MEMORY_ALLOCATION_TYPE_GPU);
803
ERR_FAIL_COND_V(!buffer.driver_id, RID());
804
805
// Storage buffers are assumed to be mutable.
806
buffer.draw_tracker = RDG::resource_tracker_create();
807
buffer.draw_tracker->buffer_driver_id = buffer.driver_id;
808
809
if (p_data.size()) {
810
_buffer_initialize(&buffer, p_data);
811
}
812
813
_THREAD_SAFE_LOCK_
814
buffer_memory += buffer.size;
815
_THREAD_SAFE_UNLOCK_
816
817
RID id = storage_buffer_owner.make_rid(buffer);
818
#ifdef DEV_ENABLED
819
set_resource_name(id, "RID:" + itos(id.get_id()));
820
#endif
821
return id;
822
}
823
824
RID RenderingDevice::texture_buffer_create(uint32_t p_size_elements, DataFormat p_format, Span<uint8_t> p_data) {
825
uint32_t element_size = get_format_vertex_size(p_format);
826
ERR_FAIL_COND_V_MSG(element_size == 0, RID(), "Format requested is not supported for texture buffers");
827
uint64_t size_bytes = uint64_t(element_size) * p_size_elements;
828
829
ERR_FAIL_COND_V(p_data.size() && (uint32_t)p_data.size() != size_bytes, RID());
830
831
Buffer texture_buffer;
832
texture_buffer.size = size_bytes;
833
BitField<RDD::BufferUsageBits> usage = (RDD::BUFFER_USAGE_TRANSFER_FROM_BIT | RDD::BUFFER_USAGE_TRANSFER_TO_BIT | RDD::BUFFER_USAGE_TEXEL_BIT);
834
texture_buffer.driver_id = driver->buffer_create(size_bytes, usage, RDD::MEMORY_ALLOCATION_TYPE_GPU);
835
ERR_FAIL_COND_V(!texture_buffer.driver_id, RID());
836
837
// Texture buffers are assumed to be immutable unless they don't have initial data.
838
if (p_data.is_empty()) {
839
texture_buffer.draw_tracker = RDG::resource_tracker_create();
840
texture_buffer.draw_tracker->buffer_driver_id = texture_buffer.driver_id;
841
}
842
843
bool ok = driver->buffer_set_texel_format(texture_buffer.driver_id, p_format);
844
if (!ok) {
845
driver->buffer_free(texture_buffer.driver_id);
846
ERR_FAIL_V(RID());
847
}
848
849
if (p_data.size()) {
850
_buffer_initialize(&texture_buffer, p_data);
851
}
852
853
_THREAD_SAFE_LOCK_
854
buffer_memory += size_bytes;
855
_THREAD_SAFE_UNLOCK_
856
857
RID id = texture_buffer_owner.make_rid(texture_buffer);
858
#ifdef DEV_ENABLED
859
set_resource_name(id, "RID:" + itos(id.get_id()));
860
#endif
861
return id;
862
}
863
864
/*****************/
865
/**** TEXTURE ****/
866
/*****************/
867
868
RID RenderingDevice::texture_create(const TextureFormat &p_format, const TextureView &p_view, const Vector<Vector<uint8_t>> &p_data) {
869
// Some adjustments will happen.
870
TextureFormat format = p_format;
871
872
if (format.shareable_formats.size()) {
873
ERR_FAIL_COND_V_MSG(!format.shareable_formats.has(format.format), RID(),
874
"If supplied a list of shareable formats, the current format must be present in the list");
875
ERR_FAIL_COND_V_MSG(p_view.format_override != DATA_FORMAT_MAX && !format.shareable_formats.has(p_view.format_override), RID(),
876
"If supplied a list of shareable formats, the current view format override must be present in the list");
877
}
878
879
ERR_FAIL_INDEX_V(format.texture_type, RDD::TEXTURE_TYPE_MAX, RID());
880
881
ERR_FAIL_COND_V_MSG(format.width < 1, RID(), "Width must be equal or greater than 1 for all textures");
882
883
if (format.texture_type != TEXTURE_TYPE_1D && format.texture_type != TEXTURE_TYPE_1D_ARRAY) {
884
ERR_FAIL_COND_V_MSG(format.height < 1, RID(), "Height must be equal or greater than 1 for 2D and 3D textures");
885
}
886
887
if (format.texture_type == TEXTURE_TYPE_3D) {
888
ERR_FAIL_COND_V_MSG(format.depth < 1, RID(), "Depth must be equal or greater than 1 for 3D textures");
889
}
890
891
ERR_FAIL_COND_V(format.mipmaps < 1, RID());
892
893
if (format.texture_type == TEXTURE_TYPE_1D_ARRAY || format.texture_type == TEXTURE_TYPE_2D_ARRAY || format.texture_type == TEXTURE_TYPE_CUBE_ARRAY || format.texture_type == TEXTURE_TYPE_CUBE) {
894
ERR_FAIL_COND_V_MSG(format.array_layers < 1, RID(),
895
"Number of layers must be equal or greater than 1 for arrays and cubemaps.");
896
ERR_FAIL_COND_V_MSG((format.texture_type == TEXTURE_TYPE_CUBE_ARRAY || format.texture_type == TEXTURE_TYPE_CUBE) && (format.array_layers % 6) != 0, RID(),
897
"Cubemap and cubemap array textures must provide a layer number that is multiple of 6");
898
ERR_FAIL_COND_V_MSG(((format.texture_type == TEXTURE_TYPE_CUBE_ARRAY || format.texture_type == TEXTURE_TYPE_CUBE)) && (format.width != format.height), RID(),
899
"Cubemap and cubemap array textures must have equal width and height.");
900
ERR_FAIL_COND_V_MSG(format.array_layers > driver->limit_get(LIMIT_MAX_TEXTURE_ARRAY_LAYERS), RID(), "Number of layers exceeds device maximum.");
901
} else {
902
format.array_layers = 1;
903
}
904
905
ERR_FAIL_INDEX_V(format.samples, TEXTURE_SAMPLES_MAX, RID());
906
907
ERR_FAIL_COND_V_MSG(format.usage_bits == 0, RID(), "No usage bits specified (at least one is needed)");
908
909
format.height = format.texture_type != TEXTURE_TYPE_1D && format.texture_type != TEXTURE_TYPE_1D_ARRAY ? format.height : 1;
910
format.depth = format.texture_type == TEXTURE_TYPE_3D ? format.depth : 1;
911
912
uint64_t size_max = 0;
913
switch (format.texture_type) {
914
case TEXTURE_TYPE_1D:
915
case TEXTURE_TYPE_1D_ARRAY:
916
size_max = driver->limit_get(LIMIT_MAX_TEXTURE_SIZE_1D);
917
break;
918
case TEXTURE_TYPE_2D:
919
case TEXTURE_TYPE_2D_ARRAY:
920
size_max = driver->limit_get(LIMIT_MAX_TEXTURE_SIZE_2D);
921
break;
922
case TEXTURE_TYPE_CUBE:
923
case TEXTURE_TYPE_CUBE_ARRAY:
924
size_max = driver->limit_get(LIMIT_MAX_TEXTURE_SIZE_CUBE);
925
break;
926
case TEXTURE_TYPE_3D:
927
size_max = driver->limit_get(LIMIT_MAX_TEXTURE_SIZE_3D);
928
break;
929
case TEXTURE_TYPE_MAX:
930
break;
931
}
932
ERR_FAIL_COND_V_MSG(format.width > size_max || format.height > size_max || format.depth > size_max, RID(), "Texture dimensions exceed device maximum.");
933
934
uint32_t required_mipmaps = get_image_required_mipmaps(format.width, format.height, format.depth);
935
936
ERR_FAIL_COND_V_MSG(required_mipmaps < format.mipmaps, RID(),
937
"Too many mipmaps requested for texture format and dimensions (" + itos(format.mipmaps) + "), maximum allowed: (" + itos(required_mipmaps) + ").");
938
939
Vector<Vector<uint8_t>> data = p_data;
940
bool immediate_flush = false;
941
942
// If this is a VRS texture, we make sure that it is created with valid initial data. This prevents a crash on Qualcomm Snapdragon XR2 Gen 1
943
// (used in Quest 2, Quest Pro, Pico 4, HTC Vive XR Elite and others) where the driver will read the texture before we've had time to finish updating it.
944
if (data.is_empty() && (p_format.usage_bits & TEXTURE_USAGE_VRS_ATTACHMENT_BIT)) {
945
immediate_flush = true;
946
for (uint32_t i = 0; i < format.array_layers; i++) {
947
uint32_t required_size = get_image_format_required_size(format.format, format.width, format.height, format.depth, format.mipmaps);
948
Vector<uint8_t> layer;
949
layer.resize(required_size);
950
layer.fill(255);
951
data.push_back(layer);
952
}
953
}
954
955
uint32_t forced_usage_bits = _texture_vrs_method_to_usage_bits();
956
if (data.size()) {
957
ERR_FAIL_COND_V_MSG(data.size() != (int)format.array_layers, RID(),
958
"Default supplied data for image format is of invalid length (" + itos(data.size()) + "), should be (" + itos(format.array_layers) + ").");
959
960
for (uint32_t i = 0; i < format.array_layers; i++) {
961
uint32_t required_size = get_image_format_required_size(format.format, format.width, format.height, format.depth, format.mipmaps);
962
ERR_FAIL_COND_V_MSG((uint32_t)data[i].size() != required_size, RID(),
963
"Data for slice index " + itos(i) + " (mapped to layer " + itos(i) + ") differs in size (supplied: " + itos(data[i].size()) + ") than what is required by the format (" + itos(required_size) + ").");
964
}
965
966
ERR_FAIL_COND_V_MSG(format.usage_bits & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, RID(),
967
"Textures created as depth attachments can't be initialized with data directly. Use RenderingDevice::texture_update() instead.");
968
969
if (!(format.usage_bits & TEXTURE_USAGE_CAN_UPDATE_BIT)) {
970
forced_usage_bits |= TEXTURE_USAGE_CAN_UPDATE_BIT;
971
}
972
}
973
974
{
975
// Validate that this image is supported for the intended use.
976
bool cpu_readable = (format.usage_bits & RDD::TEXTURE_USAGE_CPU_READ_BIT);
977
BitField<RDD::TextureUsageBits> supported_usage = driver->texture_get_usages_supported_by_format(format.format, cpu_readable);
978
979
String format_text = "'" + String(FORMAT_NAMES[format.format]) + "'";
980
981
if ((format.usage_bits & TEXTURE_USAGE_SAMPLING_BIT) && !supported_usage.has_flag(TEXTURE_USAGE_SAMPLING_BIT)) {
982
ERR_FAIL_V_MSG(RID(), "Format " + format_text + " does not support usage as sampling texture.");
983
}
984
if ((format.usage_bits & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) && !supported_usage.has_flag(TEXTURE_USAGE_COLOR_ATTACHMENT_BIT)) {
985
ERR_FAIL_V_MSG(RID(), "Format " + format_text + " does not support usage as color attachment.");
986
}
987
if ((format.usage_bits & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) && !supported_usage.has_flag(TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) {
988
ERR_FAIL_V_MSG(RID(), "Format " + format_text + " does not support usage as depth-stencil attachment.");
989
}
990
if ((format.usage_bits & TEXTURE_USAGE_STORAGE_BIT) && !supported_usage.has_flag(TEXTURE_USAGE_STORAGE_BIT)) {
991
ERR_FAIL_V_MSG(RID(), "Format " + format_text + " does not support usage as storage image.");
992
}
993
if ((format.usage_bits & TEXTURE_USAGE_STORAGE_ATOMIC_BIT) && !supported_usage.has_flag(TEXTURE_USAGE_STORAGE_ATOMIC_BIT)) {
994
ERR_FAIL_V_MSG(RID(), "Format " + format_text + " does not support usage as atomic storage image.");
995
}
996
if ((format.usage_bits & TEXTURE_USAGE_VRS_ATTACHMENT_BIT) && !supported_usage.has_flag(TEXTURE_USAGE_VRS_ATTACHMENT_BIT)) {
997
ERR_FAIL_V_MSG(RID(), "Format " + format_text + " does not support usage as variable shading rate attachment.");
998
}
999
}
1000
1001
// Transfer and validate view info.
1002
1003
RDD::TextureView tv;
1004
if (p_view.format_override == DATA_FORMAT_MAX) {
1005
tv.format = format.format;
1006
} else {
1007
ERR_FAIL_INDEX_V(p_view.format_override, DATA_FORMAT_MAX, RID());
1008
tv.format = p_view.format_override;
1009
}
1010
ERR_FAIL_INDEX_V(p_view.swizzle_r, TEXTURE_SWIZZLE_MAX, RID());
1011
ERR_FAIL_INDEX_V(p_view.swizzle_g, TEXTURE_SWIZZLE_MAX, RID());
1012
ERR_FAIL_INDEX_V(p_view.swizzle_b, TEXTURE_SWIZZLE_MAX, RID());
1013
ERR_FAIL_INDEX_V(p_view.swizzle_a, TEXTURE_SWIZZLE_MAX, RID());
1014
tv.swizzle_r = p_view.swizzle_r;
1015
tv.swizzle_g = p_view.swizzle_g;
1016
tv.swizzle_b = p_view.swizzle_b;
1017
tv.swizzle_a = p_view.swizzle_a;
1018
1019
// Create.
1020
1021
Texture texture;
1022
format.usage_bits |= forced_usage_bits;
1023
texture.driver_id = driver->texture_create(format, tv);
1024
ERR_FAIL_COND_V(!texture.driver_id, RID());
1025
texture.type = format.texture_type;
1026
texture.format = format.format;
1027
texture.width = format.width;
1028
texture.height = format.height;
1029
texture.depth = format.depth;
1030
texture.layers = format.array_layers;
1031
texture.mipmaps = format.mipmaps;
1032
texture.base_mipmap = 0;
1033
texture.base_layer = 0;
1034
texture.is_resolve_buffer = format.is_resolve_buffer;
1035
texture.is_discardable = format.is_discardable;
1036
texture.usage_flags = format.usage_bits & ~forced_usage_bits;
1037
texture.samples = format.samples;
1038
texture.allowed_shared_formats = format.shareable_formats;
1039
texture.has_initial_data = !data.is_empty();
1040
1041
if ((format.usage_bits & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) {
1042
texture.read_aspect_flags.set_flag(RDD::TEXTURE_ASPECT_DEPTH_BIT);
1043
texture.barrier_aspect_flags.set_flag(RDD::TEXTURE_ASPECT_DEPTH_BIT);
1044
if (format_has_stencil(format.format)) {
1045
texture.barrier_aspect_flags.set_flag(RDD::TEXTURE_ASPECT_STENCIL_BIT);
1046
}
1047
} else {
1048
texture.read_aspect_flags.set_flag(RDD::TEXTURE_ASPECT_COLOR_BIT);
1049
texture.barrier_aspect_flags.set_flag(RDD::TEXTURE_ASPECT_COLOR_BIT);
1050
}
1051
1052
texture.bound = false;
1053
1054
// Textures are only assumed to be immutable if they have initial data and none of the other bits that indicate write usage are enabled.
1055
bool texture_mutable_by_default = texture.usage_flags & (TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | TEXTURE_USAGE_STORAGE_BIT | TEXTURE_USAGE_STORAGE_ATOMIC_BIT);
1056
if (data.is_empty() || texture_mutable_by_default) {
1057
_texture_make_mutable(&texture, RID());
1058
}
1059
1060
texture_memory += driver->texture_get_allocation_size(texture.driver_id);
1061
1062
RID id = texture_owner.make_rid(texture);
1063
#ifdef DEV_ENABLED
1064
set_resource_name(id, "RID:" + itos(id.get_id()));
1065
#endif
1066
1067
if (data.size()) {
1068
const bool use_general_in_copy_queues = driver->api_trait_get(RDD::API_TRAIT_USE_GENERAL_IN_COPY_QUEUES);
1069
const RDD::TextureLayout dst_layout = use_general_in_copy_queues ? RDD::TEXTURE_LAYOUT_GENERAL : RDD::TEXTURE_LAYOUT_COPY_DST_OPTIMAL;
1070
for (uint32_t i = 0; i < format.array_layers; i++) {
1071
_texture_initialize(id, i, data[i], dst_layout, immediate_flush);
1072
}
1073
1074
if (texture.draw_tracker != nullptr) {
1075
texture.draw_tracker->usage = use_general_in_copy_queues ? RDG::RESOURCE_USAGE_GENERAL : RDG::RESOURCE_USAGE_COPY_TO;
1076
}
1077
}
1078
1079
return id;
1080
}
1081
1082
RID RenderingDevice::texture_create_shared(const TextureView &p_view, RID p_with_texture) {
1083
Texture *src_texture = texture_owner.get_or_null(p_with_texture);
1084
ERR_FAIL_NULL_V(src_texture, RID());
1085
1086
if (src_texture->owner.is_valid()) { // Ahh this is a share. The RenderingDeviceDriver needs the actual owner.
1087
p_with_texture = src_texture->owner;
1088
src_texture = texture_owner.get_or_null(src_texture->owner);
1089
ERR_FAIL_NULL_V(src_texture, RID()); // This is a bug.
1090
}
1091
1092
// Create view.
1093
1094
Texture texture = *src_texture;
1095
texture.slice_trackers = nullptr;
1096
texture.shared_fallback = nullptr;
1097
1098
RDD::TextureView tv;
1099
bool create_shared = true;
1100
bool raw_reintepretation = false;
1101
if (p_view.format_override == DATA_FORMAT_MAX || p_view.format_override == texture.format) {
1102
tv.format = texture.format;
1103
} else {
1104
ERR_FAIL_INDEX_V(p_view.format_override, DATA_FORMAT_MAX, RID());
1105
1106
ERR_FAIL_COND_V_MSG(!texture.allowed_shared_formats.has(p_view.format_override), RID(),
1107
"Format override is not in the list of allowed shareable formats for original texture.");
1108
tv.format = p_view.format_override;
1109
create_shared = driver->texture_can_make_shared_with_format(texture.driver_id, p_view.format_override, raw_reintepretation);
1110
}
1111
tv.swizzle_r = p_view.swizzle_r;
1112
tv.swizzle_g = p_view.swizzle_g;
1113
tv.swizzle_b = p_view.swizzle_b;
1114
tv.swizzle_a = p_view.swizzle_a;
1115
1116
if (create_shared) {
1117
texture.driver_id = driver->texture_create_shared(texture.driver_id, tv);
1118
} else {
1119
// The regular view will use the same format as the main texture.
1120
RDD::TextureView regular_view = tv;
1121
regular_view.format = src_texture->format;
1122
texture.driver_id = driver->texture_create_shared(texture.driver_id, regular_view);
1123
1124
// Create the independent texture for the alias.
1125
RDD::TextureFormat alias_format = texture.texture_format();
1126
alias_format.format = tv.format;
1127
alias_format.usage_bits = TEXTURE_USAGE_SAMPLING_BIT | TEXTURE_USAGE_CAN_COPY_TO_BIT;
1128
1129
_texture_check_shared_fallback(src_texture);
1130
_texture_check_shared_fallback(&texture);
1131
1132
texture.shared_fallback->texture = driver->texture_create(alias_format, tv);
1133
texture.shared_fallback->raw_reinterpretation = raw_reintepretation;
1134
texture_memory += driver->texture_get_allocation_size(texture.shared_fallback->texture);
1135
1136
RDG::ResourceTracker *tracker = RDG::resource_tracker_create();
1137
tracker->texture_driver_id = texture.shared_fallback->texture;
1138
tracker->texture_size = Size2i(texture.width, texture.height);
1139
tracker->texture_subresources = texture.barrier_range();
1140
tracker->texture_usage = alias_format.usage_bits;
1141
tracker->is_discardable = texture.is_discardable;
1142
tracker->reference_count = 1;
1143
texture.shared_fallback->texture_tracker = tracker;
1144
texture.shared_fallback->revision = 0;
1145
1146
if (raw_reintepretation && src_texture->shared_fallback->buffer.id == 0) {
1147
// For shared textures of the same size, we create the buffer on the main texture if it doesn't have it already.
1148
_texture_create_reinterpret_buffer(src_texture);
1149
}
1150
}
1151
1152
ERR_FAIL_COND_V(!texture.driver_id, RID());
1153
1154
if (texture.draw_tracker != nullptr) {
1155
texture.draw_tracker->reference_count++;
1156
}
1157
1158
texture.owner = p_with_texture;
1159
RID id = texture_owner.make_rid(texture);
1160
#ifdef DEV_ENABLED
1161
set_resource_name(id, "RID:" + itos(id.get_id()));
1162
#endif
1163
_add_dependency(id, p_with_texture);
1164
1165
return id;
1166
}
1167
1168
RID RenderingDevice::texture_create_from_extension(TextureType p_type, DataFormat p_format, TextureSamples p_samples, BitField<RenderingDevice::TextureUsageBits> p_usage, uint64_t p_image, uint64_t p_width, uint64_t p_height, uint64_t p_depth, uint64_t p_layers, uint64_t p_mipmaps) {
1169
// This method creates a texture object using a VkImage created by an extension, module or other external source (OpenXR uses this).
1170
1171
Texture texture;
1172
texture.type = p_type;
1173
texture.format = p_format;
1174
texture.samples = p_samples;
1175
texture.width = p_width;
1176
texture.height = p_height;
1177
texture.depth = p_depth;
1178
texture.layers = p_layers;
1179
texture.mipmaps = p_mipmaps;
1180
texture.usage_flags = p_usage;
1181
texture.base_mipmap = 0;
1182
texture.base_layer = 0;
1183
texture.allowed_shared_formats.push_back(RD::DATA_FORMAT_R8G8B8A8_UNORM);
1184
texture.allowed_shared_formats.push_back(RD::DATA_FORMAT_R8G8B8A8_SRGB);
1185
1186
if (p_usage.has_flag(TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) {
1187
texture.read_aspect_flags.set_flag(RDD::TEXTURE_ASPECT_DEPTH_BIT);
1188
texture.barrier_aspect_flags.set_flag(RDD::TEXTURE_ASPECT_DEPTH_BIT);
1189
/*if (format_has_stencil(p_format.format)) {
1190
texture.barrier_aspect_flags.set_flag(RDD::TEXTURE_ASPECT_STENCIL_BIT);
1191
}*/
1192
} else {
1193
texture.read_aspect_flags.set_flag(RDD::TEXTURE_ASPECT_COLOR_BIT);
1194
texture.barrier_aspect_flags.set_flag(RDD::TEXTURE_ASPECT_COLOR_BIT);
1195
}
1196
1197
texture.driver_id = driver->texture_create_from_extension(p_image, p_type, p_format, p_layers, (texture.usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT), p_mipmaps);
1198
ERR_FAIL_COND_V(!texture.driver_id, RID());
1199
1200
_texture_make_mutable(&texture, RID());
1201
1202
RID id = texture_owner.make_rid(texture);
1203
#ifdef DEV_ENABLED
1204
set_resource_name(id, "RID:" + itos(id.get_id()));
1205
#endif
1206
1207
return id;
1208
}
1209
1210
RID RenderingDevice::texture_create_shared_from_slice(const TextureView &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap, uint32_t p_mipmaps, TextureSliceType p_slice_type, uint32_t p_layers) {
1211
Texture *src_texture = texture_owner.get_or_null(p_with_texture);
1212
ERR_FAIL_NULL_V(src_texture, RID());
1213
1214
if (src_texture->owner.is_valid()) { // // Ahh this is a share. The RenderingDeviceDriver needs the actual owner.
1215
p_with_texture = src_texture->owner;
1216
src_texture = texture_owner.get_or_null(src_texture->owner);
1217
ERR_FAIL_NULL_V(src_texture, RID()); // This is a bug.
1218
}
1219
1220
ERR_FAIL_COND_V_MSG(p_slice_type == TEXTURE_SLICE_CUBEMAP && (src_texture->type != TEXTURE_TYPE_CUBE && src_texture->type != TEXTURE_TYPE_CUBE_ARRAY), RID(),
1221
"Can only create a cubemap slice from a cubemap or cubemap array mipmap");
1222
1223
ERR_FAIL_COND_V_MSG(p_slice_type == TEXTURE_SLICE_3D && src_texture->type != TEXTURE_TYPE_3D, RID(),
1224
"Can only create a 3D slice from a 3D texture");
1225
1226
ERR_FAIL_COND_V_MSG(p_slice_type == TEXTURE_SLICE_2D_ARRAY && (src_texture->type != TEXTURE_TYPE_2D_ARRAY), RID(),
1227
"Can only create an array slice from a 2D array mipmap");
1228
1229
// Create view.
1230
1231
ERR_FAIL_UNSIGNED_INDEX_V(p_mipmap, src_texture->mipmaps, RID());
1232
ERR_FAIL_COND_V(p_mipmap + p_mipmaps > src_texture->mipmaps, RID());
1233
ERR_FAIL_UNSIGNED_INDEX_V(p_layer, src_texture->layers, RID());
1234
1235
int slice_layers = 1;
1236
if (p_layers != 0) {
1237
ERR_FAIL_COND_V_MSG(p_layers > 1 && p_slice_type != TEXTURE_SLICE_2D_ARRAY, RID(), "layer slicing only supported for 2D arrays");
1238
ERR_FAIL_COND_V_MSG(p_layer + p_layers > src_texture->layers, RID(), "layer slice is out of bounds");
1239
slice_layers = p_layers;
1240
} else if (p_slice_type == TEXTURE_SLICE_2D_ARRAY) {
1241
ERR_FAIL_COND_V_MSG(p_layer != 0, RID(), "layer must be 0 when obtaining a 2D array mipmap slice");
1242
slice_layers = src_texture->layers;
1243
} else if (p_slice_type == TEXTURE_SLICE_CUBEMAP) {
1244
slice_layers = 6;
1245
}
1246
1247
Texture texture = *src_texture;
1248
texture.slice_trackers = nullptr;
1249
texture.shared_fallback = nullptr;
1250
1251
get_image_format_required_size(texture.format, texture.width, texture.height, texture.depth, p_mipmap + 1, &texture.width, &texture.height);
1252
texture.mipmaps = p_mipmaps;
1253
texture.layers = slice_layers;
1254
texture.base_mipmap = p_mipmap;
1255
texture.base_layer = p_layer;
1256
1257
if (p_slice_type == TEXTURE_SLICE_2D) {
1258
texture.type = TEXTURE_TYPE_2D;
1259
} else if (p_slice_type == TEXTURE_SLICE_3D) {
1260
texture.type = TEXTURE_TYPE_3D;
1261
}
1262
1263
RDD::TextureView tv;
1264
bool create_shared = true;
1265
bool raw_reintepretation = false;
1266
if (p_view.format_override == DATA_FORMAT_MAX || p_view.format_override == texture.format) {
1267
tv.format = texture.format;
1268
} else {
1269
ERR_FAIL_INDEX_V(p_view.format_override, DATA_FORMAT_MAX, RID());
1270
1271
ERR_FAIL_COND_V_MSG(!texture.allowed_shared_formats.has(p_view.format_override), RID(),
1272
"Format override is not in the list of allowed shareable formats for original texture.");
1273
tv.format = p_view.format_override;
1274
create_shared = driver->texture_can_make_shared_with_format(texture.driver_id, p_view.format_override, raw_reintepretation);
1275
}
1276
1277
tv.swizzle_r = p_view.swizzle_r;
1278
tv.swizzle_g = p_view.swizzle_g;
1279
tv.swizzle_b = p_view.swizzle_b;
1280
tv.swizzle_a = p_view.swizzle_a;
1281
1282
if (p_slice_type == TEXTURE_SLICE_CUBEMAP) {
1283
ERR_FAIL_COND_V_MSG(p_layer >= src_texture->layers, RID(),
1284
"Specified layer is invalid for cubemap");
1285
ERR_FAIL_COND_V_MSG((p_layer % 6) != 0, RID(),
1286
"Specified layer must be a multiple of 6.");
1287
}
1288
1289
if (create_shared) {
1290
texture.driver_id = driver->texture_create_shared_from_slice(src_texture->driver_id, tv, p_slice_type, p_layer, slice_layers, p_mipmap, p_mipmaps);
1291
} else {
1292
// The regular view will use the same format as the main texture.
1293
RDD::TextureView regular_view = tv;
1294
regular_view.format = src_texture->format;
1295
texture.driver_id = driver->texture_create_shared_from_slice(src_texture->driver_id, regular_view, p_slice_type, p_layer, slice_layers, p_mipmap, p_mipmaps);
1296
1297
// Create the independent texture for the slice.
1298
RDD::TextureSubresourceRange slice_range = texture.barrier_range();
1299
slice_range.base_mipmap = 0;
1300
slice_range.base_layer = 0;
1301
1302
RDD::TextureFormat slice_format = texture.texture_format();
1303
slice_format.width = MAX(texture.width >> p_mipmap, 1U);
1304
slice_format.height = MAX(texture.height >> p_mipmap, 1U);
1305
slice_format.depth = MAX(texture.depth >> p_mipmap, 1U);
1306
slice_format.format = tv.format;
1307
slice_format.usage_bits = TEXTURE_USAGE_SAMPLING_BIT | TEXTURE_USAGE_CAN_COPY_TO_BIT;
1308
1309
_texture_check_shared_fallback(src_texture);
1310
_texture_check_shared_fallback(&texture);
1311
1312
texture.shared_fallback->texture = driver->texture_create(slice_format, tv);
1313
texture.shared_fallback->raw_reinterpretation = raw_reintepretation;
1314
texture_memory += driver->texture_get_allocation_size(texture.shared_fallback->texture);
1315
1316
RDG::ResourceTracker *tracker = RDG::resource_tracker_create();
1317
tracker->texture_driver_id = texture.shared_fallback->texture;
1318
tracker->texture_size = Size2i(texture.width, texture.height);
1319
tracker->texture_subresources = slice_range;
1320
tracker->texture_usage = slice_format.usage_bits;
1321
tracker->is_discardable = slice_format.is_discardable;
1322
tracker->reference_count = 1;
1323
texture.shared_fallback->texture_tracker = tracker;
1324
texture.shared_fallback->revision = 0;
1325
1326
if (raw_reintepretation && src_texture->shared_fallback->buffer.id == 0) {
1327
// For shared texture slices, we create the buffer on the slice if the source texture has no reinterpretation buffer.
1328
_texture_create_reinterpret_buffer(&texture);
1329
}
1330
}
1331
1332
ERR_FAIL_COND_V(!texture.driver_id, RID());
1333
1334
const Rect2i slice_rect(p_mipmap, p_layer, p_mipmaps, slice_layers);
1335
texture.owner = p_with_texture;
1336
texture.slice_type = p_slice_type;
1337
texture.slice_rect = slice_rect;
1338
1339
// If parent is mutable, make slice mutable by default.
1340
if (src_texture->draw_tracker != nullptr) {
1341
texture.draw_tracker = nullptr;
1342
_texture_make_mutable(&texture, RID());
1343
}
1344
1345
RID id = texture_owner.make_rid(texture);
1346
#ifdef DEV_ENABLED
1347
set_resource_name(id, "RID:" + itos(id.get_id()));
1348
#endif
1349
_add_dependency(id, p_with_texture);
1350
1351
return id;
1352
}
1353
1354
static _ALWAYS_INLINE_ void _copy_region(uint8_t const *__restrict p_src, uint8_t *__restrict p_dst, uint32_t p_src_x, uint32_t p_src_y, uint32_t p_src_w, uint32_t p_src_h, uint32_t p_src_full_w, uint32_t p_dst_pitch, uint32_t p_unit_size) {
1355
uint32_t src_offset = (p_src_y * p_src_full_w + p_src_x) * p_unit_size;
1356
uint32_t dst_offset = 0;
1357
for (uint32_t y = p_src_h; y > 0; y--) {
1358
uint8_t const *__restrict src = p_src + src_offset;
1359
uint8_t *__restrict dst = p_dst + dst_offset;
1360
for (uint32_t x = p_src_w * p_unit_size; x > 0; x--) {
1361
*dst = *src;
1362
src++;
1363
dst++;
1364
}
1365
src_offset += p_src_full_w * p_unit_size;
1366
dst_offset += p_dst_pitch;
1367
}
1368
}
1369
1370
static _ALWAYS_INLINE_ void _copy_region_block_or_regular(const uint8_t *p_read_ptr, uint8_t *p_write_ptr, uint32_t p_x, uint32_t p_y, uint32_t p_width, uint32_t p_region_w, uint32_t p_region_h, uint32_t p_block_w, uint32_t p_block_h, uint32_t p_dst_pitch, uint32_t p_pixel_size, uint32_t p_block_size) {
1371
if (p_block_w != 1 || p_block_h != 1) {
1372
// Block format.
1373
uint32_t xb = p_x / p_block_w;
1374
uint32_t yb = p_y / p_block_h;
1375
uint32_t wb = p_width / p_block_w;
1376
uint32_t region_wb = p_region_w / p_block_w;
1377
uint32_t region_hb = p_region_h / p_block_h;
1378
_copy_region(p_read_ptr, p_write_ptr, xb, yb, region_wb, region_hb, wb, p_dst_pitch, p_block_size);
1379
} else {
1380
// Regular format.
1381
_copy_region(p_read_ptr, p_write_ptr, p_x, p_y, p_region_w, p_region_h, p_width, p_dst_pitch, p_pixel_size);
1382
}
1383
}
1384
1385
uint32_t RenderingDevice::_texture_layer_count(Texture *p_texture) const {
1386
switch (p_texture->type) {
1387
case TEXTURE_TYPE_CUBE:
1388
case TEXTURE_TYPE_CUBE_ARRAY:
1389
return p_texture->layers * 6;
1390
default:
1391
return p_texture->layers;
1392
}
1393
}
1394
1395
uint32_t greatest_common_denominator(uint32_t a, uint32_t b) {
1396
// Euclidean algorithm.
1397
uint32_t t;
1398
while (b != 0) {
1399
t = b;
1400
b = a % b;
1401
a = t;
1402
}
1403
1404
return a;
1405
}
1406
1407
uint32_t least_common_multiple(uint32_t a, uint32_t b) {
1408
if (a == 0 || b == 0) {
1409
return 0;
1410
}
1411
1412
return (a / greatest_common_denominator(a, b)) * b;
1413
}
1414
1415
uint32_t RenderingDevice::_texture_alignment(Texture *p_texture) const {
1416
uint32_t alignment = get_compressed_image_format_block_byte_size(p_texture->format);
1417
if (alignment == 1) {
1418
alignment = get_image_format_pixel_size(p_texture->format);
1419
}
1420
1421
return least_common_multiple(alignment, driver->api_trait_get(RDD::API_TRAIT_TEXTURE_TRANSFER_ALIGNMENT));
1422
}
1423
1424
Error RenderingDevice::_texture_initialize(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data, RDD::TextureLayout p_dst_layout, bool p_immediate_flush) {
1425
Texture *texture = texture_owner.get_or_null(p_texture);
1426
ERR_FAIL_NULL_V(texture, ERR_INVALID_PARAMETER);
1427
1428
if (texture->owner != RID()) {
1429
p_texture = texture->owner;
1430
texture = texture_owner.get_or_null(texture->owner);
1431
ERR_FAIL_NULL_V(texture, ERR_BUG); // This is a bug.
1432
}
1433
1434
uint32_t layer_count = _texture_layer_count(texture);
1435
ERR_FAIL_COND_V(p_layer >= layer_count, ERR_INVALID_PARAMETER);
1436
1437
uint32_t width, height;
1438
uint32_t tight_mip_size = get_image_format_required_size(texture->format, texture->width, texture->height, texture->depth, texture->mipmaps, &width, &height);
1439
uint32_t required_size = tight_mip_size;
1440
uint32_t required_align = _texture_alignment(texture);
1441
1442
ERR_FAIL_COND_V_MSG(required_size != (uint32_t)p_data.size(), ERR_INVALID_PARAMETER,
1443
"Required size for texture update (" + itos(required_size) + ") does not match data supplied size (" + itos(p_data.size()) + ").");
1444
1445
uint32_t block_w, block_h;
1446
get_compressed_image_format_block_dimensions(texture->format, block_w, block_h);
1447
1448
uint32_t pixel_size = get_image_format_pixel_size(texture->format);
1449
uint32_t pixel_rshift = get_compressed_image_format_pixel_rshift(texture->format);
1450
uint32_t block_size = get_compressed_image_format_block_byte_size(texture->format);
1451
1452
// The algorithm operates on two passes, one to figure out the total size the staging buffer will require to allocate and another one where the copy is actually performed.
1453
uint32_t staging_worker_offset = 0;
1454
uint32_t staging_local_offset = 0;
1455
TransferWorker *transfer_worker = nullptr;
1456
const uint8_t *read_ptr = p_data.ptr();
1457
uint8_t *write_ptr = nullptr;
1458
for (uint32_t pass = 0; pass < 2; pass++) {
1459
const bool copy_pass = (pass == 1);
1460
if (copy_pass) {
1461
transfer_worker = _acquire_transfer_worker(staging_local_offset, required_align, staging_worker_offset);
1462
texture->transfer_worker_index = transfer_worker->index;
1463
1464
{
1465
MutexLock lock(transfer_worker->operations_mutex);
1466
texture->transfer_worker_operation = ++transfer_worker->operations_counter;
1467
}
1468
1469
staging_local_offset = 0;
1470
1471
write_ptr = driver->buffer_map(transfer_worker->staging_buffer);
1472
ERR_FAIL_NULL_V(write_ptr, ERR_CANT_CREATE);
1473
1474
if (driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) {
1475
// Transition the texture to the optimal layout.
1476
RDD::TextureBarrier tb;
1477
tb.texture = texture->driver_id;
1478
tb.dst_access = RDD::BARRIER_ACCESS_COPY_WRITE_BIT;
1479
tb.prev_layout = RDD::TEXTURE_LAYOUT_UNDEFINED;
1480
tb.next_layout = p_dst_layout;
1481
tb.subresources.aspect = texture->barrier_aspect_flags;
1482
tb.subresources.mipmap_count = texture->mipmaps;
1483
tb.subresources.base_layer = p_layer;
1484
tb.subresources.layer_count = 1;
1485
driver->command_pipeline_barrier(transfer_worker->command_buffer, RDD::PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, RDD::PIPELINE_STAGE_COPY_BIT, {}, {}, tb);
1486
}
1487
}
1488
1489
uint32_t mipmap_offset = 0;
1490
uint32_t logic_width = texture->width;
1491
uint32_t logic_height = texture->height;
1492
for (uint32_t mm_i = 0; mm_i < texture->mipmaps; mm_i++) {
1493
uint32_t depth = 0;
1494
uint32_t image_total = get_image_format_required_size(texture->format, texture->width, texture->height, texture->depth, mm_i + 1, &width, &height, &depth);
1495
1496
const uint8_t *read_ptr_mipmap = read_ptr + mipmap_offset;
1497
tight_mip_size = image_total - mipmap_offset;
1498
1499
for (uint32_t z = 0; z < depth; z++) {
1500
if (required_align > 0) {
1501
uint32_t align_offset = staging_local_offset % required_align;
1502
if (align_offset != 0) {
1503
staging_local_offset += required_align - align_offset;
1504
}
1505
}
1506
1507
uint32_t pitch = (width * pixel_size * block_w) >> pixel_rshift;
1508
uint32_t pitch_step = driver->api_trait_get(RDD::API_TRAIT_TEXTURE_DATA_ROW_PITCH_STEP);
1509
pitch = STEPIFY(pitch, pitch_step);
1510
uint32_t to_allocate = pitch * height;
1511
to_allocate >>= pixel_rshift;
1512
1513
if (copy_pass) {
1514
const uint8_t *read_ptr_mipmap_layer = read_ptr_mipmap + (tight_mip_size / depth) * z;
1515
uint64_t staging_buffer_offset = staging_worker_offset + staging_local_offset;
1516
uint8_t *write_ptr_mipmap_layer = write_ptr + staging_buffer_offset;
1517
_copy_region_block_or_regular(read_ptr_mipmap_layer, write_ptr_mipmap_layer, 0, 0, width, width, height, block_w, block_h, pitch, pixel_size, block_size);
1518
1519
RDD::BufferTextureCopyRegion copy_region;
1520
copy_region.buffer_offset = staging_buffer_offset;
1521
copy_region.texture_subresources.aspect = texture->read_aspect_flags;
1522
copy_region.texture_subresources.mipmap = mm_i;
1523
copy_region.texture_subresources.base_layer = p_layer;
1524
copy_region.texture_subresources.layer_count = 1;
1525
copy_region.texture_offset = Vector3i(0, 0, z);
1526
copy_region.texture_region_size = Vector3i(logic_width, logic_height, 1);
1527
driver->command_copy_buffer_to_texture(transfer_worker->command_buffer, transfer_worker->staging_buffer, texture->driver_id, p_dst_layout, copy_region);
1528
}
1529
1530
staging_local_offset += to_allocate;
1531
}
1532
1533
mipmap_offset = image_total;
1534
logic_width = MAX(1u, logic_width >> 1);
1535
logic_height = MAX(1u, logic_height >> 1);
1536
}
1537
1538
if (copy_pass) {
1539
driver->buffer_unmap(transfer_worker->staging_buffer);
1540
1541
// If the texture does not have a tracker, it means it must be transitioned to the sampling state.
1542
if (texture->draw_tracker == nullptr && driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) {
1543
RDD::TextureBarrier tb;
1544
tb.texture = texture->driver_id;
1545
tb.src_access = RDD::BARRIER_ACCESS_COPY_WRITE_BIT;
1546
tb.prev_layout = p_dst_layout;
1547
tb.next_layout = RDD::TEXTURE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
1548
tb.subresources.aspect = texture->barrier_aspect_flags;
1549
tb.subresources.mipmap_count = texture->mipmaps;
1550
tb.subresources.base_layer = p_layer;
1551
tb.subresources.layer_count = 1;
1552
transfer_worker->texture_barriers.push_back(tb);
1553
}
1554
1555
if (p_immediate_flush) {
1556
_end_transfer_worker(transfer_worker);
1557
_submit_transfer_worker(transfer_worker);
1558
_wait_for_transfer_worker(transfer_worker);
1559
}
1560
1561
_release_transfer_worker(transfer_worker);
1562
}
1563
}
1564
1565
return OK;
1566
}
1567
1568
Error RenderingDevice::texture_update(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data) {
1569
ERR_RENDER_THREAD_GUARD_V(ERR_UNAVAILABLE);
1570
1571
ERR_FAIL_COND_V_MSG(draw_list.active || compute_list.active, ERR_INVALID_PARAMETER, "Updating textures is forbidden during creation of a draw or compute list");
1572
1573
Texture *texture = texture_owner.get_or_null(p_texture);
1574
ERR_FAIL_NULL_V(texture, ERR_INVALID_PARAMETER);
1575
1576
if (texture->owner != RID()) {
1577
p_texture = texture->owner;
1578
texture = texture_owner.get_or_null(texture->owner);
1579
ERR_FAIL_NULL_V(texture, ERR_BUG); // This is a bug.
1580
}
1581
1582
ERR_FAIL_COND_V_MSG(texture->bound, ERR_CANT_ACQUIRE_RESOURCE,
1583
"Texture can't be updated while a draw list that uses it as part of a framebuffer is being created. Ensure the draw list is finalized (and that the color/depth texture using it is not set to `RenderingDevice.FINAL_ACTION_CONTINUE`) to update this texture.");
1584
1585
ERR_FAIL_COND_V_MSG(!(texture->usage_flags & TEXTURE_USAGE_CAN_UPDATE_BIT), ERR_INVALID_PARAMETER, "Texture requires the `RenderingDevice.TEXTURE_USAGE_CAN_UPDATE_BIT` to be set to be updatable.");
1586
1587
uint32_t layer_count = _texture_layer_count(texture);
1588
ERR_FAIL_COND_V(p_layer >= layer_count, ERR_INVALID_PARAMETER);
1589
1590
uint32_t width, height;
1591
uint32_t tight_mip_size = get_image_format_required_size(texture->format, texture->width, texture->height, texture->depth, texture->mipmaps, &width, &height);
1592
uint32_t required_size = tight_mip_size;
1593
uint32_t required_align = _texture_alignment(texture);
1594
1595
ERR_FAIL_COND_V_MSG(required_size != (uint32_t)p_data.size(), ERR_INVALID_PARAMETER,
1596
"Required size for texture update (" + itos(required_size) + ") does not match data supplied size (" + itos(p_data.size()) + ").");
1597
1598
_check_transfer_worker_texture(texture);
1599
1600
uint32_t block_w, block_h;
1601
get_compressed_image_format_block_dimensions(texture->format, block_w, block_h);
1602
1603
uint32_t pixel_size = get_image_format_pixel_size(texture->format);
1604
uint32_t pixel_rshift = get_compressed_image_format_pixel_rshift(texture->format);
1605
uint32_t block_size = get_compressed_image_format_block_byte_size(texture->format);
1606
1607
uint32_t region_size = texture_upload_region_size_px;
1608
1609
const uint8_t *read_ptr = p_data.ptr();
1610
1611
thread_local LocalVector<RDG::RecordedBufferToTextureCopy> command_buffer_to_texture_copies_vector;
1612
command_buffer_to_texture_copies_vector.clear();
1613
1614
// Indicate the texture will get modified for the shared texture fallback.
1615
_texture_update_shared_fallback(p_texture, texture, true);
1616
1617
uint32_t mipmap_offset = 0;
1618
1619
uint32_t logic_width = texture->width;
1620
uint32_t logic_height = texture->height;
1621
1622
for (uint32_t mm_i = 0; mm_i < texture->mipmaps; mm_i++) {
1623
uint32_t depth = 0;
1624
uint32_t image_total = get_image_format_required_size(texture->format, texture->width, texture->height, texture->depth, mm_i + 1, &width, &height, &depth);
1625
1626
const uint8_t *read_ptr_mipmap = read_ptr + mipmap_offset;
1627
tight_mip_size = image_total - mipmap_offset;
1628
1629
for (uint32_t z = 0; z < depth; z++) {
1630
const uint8_t *read_ptr_mipmap_layer = read_ptr_mipmap + (tight_mip_size / depth) * z;
1631
for (uint32_t y = 0; y < height; y += region_size) {
1632
for (uint32_t x = 0; x < width; x += region_size) {
1633
uint32_t region_w = MIN(region_size, width - x);
1634
uint32_t region_h = MIN(region_size, height - y);
1635
1636
uint32_t region_logic_w = MIN(region_size, logic_width - x);
1637
uint32_t region_logic_h = MIN(region_size, logic_height - y);
1638
1639
uint32_t region_pitch = (region_w * pixel_size * block_w) >> pixel_rshift;
1640
uint32_t pitch_step = driver->api_trait_get(RDD::API_TRAIT_TEXTURE_DATA_ROW_PITCH_STEP);
1641
region_pitch = STEPIFY(region_pitch, pitch_step);
1642
uint32_t to_allocate = region_pitch * region_h;
1643
uint32_t alloc_offset = 0, alloc_size = 0;
1644
StagingRequiredAction required_action;
1645
Error err = _staging_buffer_allocate(upload_staging_buffers, to_allocate, required_align, alloc_offset, alloc_size, required_action, false);
1646
ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
1647
1648
if (!command_buffer_to_texture_copies_vector.is_empty() && required_action == STAGING_REQUIRED_ACTION_FLUSH_AND_STALL_ALL) {
1649
if (_texture_make_mutable(texture, p_texture)) {
1650
// The texture must be mutable to be used as a copy destination.
1651
draw_graph.add_synchronization();
1652
}
1653
1654
// If the staging buffer requires flushing everything, we submit the command early and clear the current vector.
1655
draw_graph.add_texture_update(texture->driver_id, texture->draw_tracker, command_buffer_to_texture_copies_vector);
1656
command_buffer_to_texture_copies_vector.clear();
1657
}
1658
1659
_staging_buffer_execute_required_action(upload_staging_buffers, required_action);
1660
1661
uint8_t *write_ptr;
1662
1663
{ // Map.
1664
uint8_t *data_ptr = driver->buffer_map(upload_staging_buffers.blocks[upload_staging_buffers.current].driver_id);
1665
ERR_FAIL_NULL_V(data_ptr, ERR_CANT_CREATE);
1666
write_ptr = data_ptr;
1667
write_ptr += alloc_offset;
1668
}
1669
1670
ERR_FAIL_COND_V(region_w % block_w, ERR_BUG);
1671
ERR_FAIL_COND_V(region_h % block_h, ERR_BUG);
1672
1673
_copy_region_block_or_regular(read_ptr_mipmap_layer, write_ptr, x, y, width, region_w, region_h, block_w, block_h, region_pitch, pixel_size, block_size);
1674
1675
{ // Unmap.
1676
driver->buffer_unmap(upload_staging_buffers.blocks[upload_staging_buffers.current].driver_id);
1677
}
1678
1679
RDD::BufferTextureCopyRegion copy_region;
1680
copy_region.buffer_offset = alloc_offset;
1681
copy_region.texture_subresources.aspect = texture->read_aspect_flags;
1682
copy_region.texture_subresources.mipmap = mm_i;
1683
copy_region.texture_subresources.base_layer = p_layer;
1684
copy_region.texture_subresources.layer_count = 1;
1685
copy_region.texture_offset = Vector3i(x, y, z);
1686
copy_region.texture_region_size = Vector3i(region_logic_w, region_logic_h, 1);
1687
1688
RDG::RecordedBufferToTextureCopy buffer_to_texture_copy;
1689
buffer_to_texture_copy.from_buffer = upload_staging_buffers.blocks[upload_staging_buffers.current].driver_id;
1690
buffer_to_texture_copy.region = copy_region;
1691
command_buffer_to_texture_copies_vector.push_back(buffer_to_texture_copy);
1692
1693
upload_staging_buffers.blocks.write[upload_staging_buffers.current].fill_amount = alloc_offset + alloc_size;
1694
}
1695
}
1696
}
1697
1698
mipmap_offset = image_total;
1699
logic_width = MAX(1u, logic_width >> 1);
1700
logic_height = MAX(1u, logic_height >> 1);
1701
}
1702
1703
if (_texture_make_mutable(texture, p_texture)) {
1704
// The texture must be mutable to be used as a copy destination.
1705
draw_graph.add_synchronization();
1706
}
1707
1708
draw_graph.add_texture_update(texture->driver_id, texture->draw_tracker, command_buffer_to_texture_copies_vector);
1709
1710
return OK;
1711
}
1712
1713
void RenderingDevice::_texture_check_shared_fallback(Texture *p_texture) {
1714
if (p_texture->shared_fallback == nullptr) {
1715
p_texture->shared_fallback = memnew(Texture::SharedFallback);
1716
}
1717
}
1718
1719
void RenderingDevice::_texture_update_shared_fallback(RID p_texture_rid, Texture *p_texture, bool p_for_writing) {
1720
if (p_texture->shared_fallback == nullptr) {
1721
// This texture does not use any of the shared texture fallbacks.
1722
return;
1723
}
1724
1725
if (p_texture->owner.is_valid()) {
1726
Texture *owner_texture = texture_owner.get_or_null(p_texture->owner);
1727
ERR_FAIL_NULL(owner_texture);
1728
if (p_for_writing) {
1729
// Only the main texture is used for writing when using the shared fallback.
1730
owner_texture->shared_fallback->revision++;
1731
} else if (p_texture->shared_fallback->revision != owner_texture->shared_fallback->revision) {
1732
// Copy the contents of the main texture into the shared texture fallback slice. Update the revision.
1733
_texture_copy_shared(p_texture->owner, owner_texture, p_texture_rid, p_texture);
1734
p_texture->shared_fallback->revision = owner_texture->shared_fallback->revision;
1735
}
1736
} else if (p_for_writing) {
1737
// Increment the revision of the texture so shared texture fallback slices must be updated.
1738
p_texture->shared_fallback->revision++;
1739
}
1740
}
1741
1742
void RenderingDevice::_texture_free_shared_fallback(Texture *p_texture) {
1743
if (p_texture->shared_fallback != nullptr) {
1744
if (p_texture->shared_fallback->texture_tracker != nullptr) {
1745
RDG::resource_tracker_free(p_texture->shared_fallback->texture_tracker);
1746
}
1747
1748
if (p_texture->shared_fallback->buffer_tracker != nullptr) {
1749
RDG::resource_tracker_free(p_texture->shared_fallback->buffer_tracker);
1750
}
1751
1752
if (p_texture->shared_fallback->texture.id != 0) {
1753
texture_memory -= driver->texture_get_allocation_size(p_texture->shared_fallback->texture);
1754
driver->texture_free(p_texture->shared_fallback->texture);
1755
}
1756
1757
if (p_texture->shared_fallback->buffer.id != 0) {
1758
buffer_memory -= driver->buffer_get_allocation_size(p_texture->shared_fallback->buffer);
1759
driver->buffer_free(p_texture->shared_fallback->buffer);
1760
}
1761
1762
memdelete(p_texture->shared_fallback);
1763
p_texture->shared_fallback = nullptr;
1764
}
1765
}
1766
1767
void RenderingDevice::_texture_copy_shared(RID p_src_texture_rid, Texture *p_src_texture, RID p_dst_texture_rid, Texture *p_dst_texture) {
1768
// The only type of copying allowed is from the main texture to the slice texture, as slice textures are not allowed to be used for writing when using this fallback.
1769
DEV_ASSERT(p_src_texture != nullptr);
1770
DEV_ASSERT(p_dst_texture != nullptr);
1771
DEV_ASSERT(p_src_texture->owner.is_null());
1772
DEV_ASSERT(p_dst_texture->owner == p_src_texture_rid);
1773
1774
bool src_made_mutable = _texture_make_mutable(p_src_texture, p_src_texture_rid);
1775
bool dst_made_mutable = _texture_make_mutable(p_dst_texture, p_dst_texture_rid);
1776
if (src_made_mutable || dst_made_mutable) {
1777
draw_graph.add_synchronization();
1778
}
1779
1780
if (p_dst_texture->shared_fallback->raw_reinterpretation) {
1781
// If one of the textures is a main texture and they have a reinterpret buffer, we prefer using that as it's guaranteed to be big enough to hold
1782
// anything and it's how the shared textures that don't use slices are created.
1783
bool src_has_buffer = p_src_texture->shared_fallback->buffer.id != 0;
1784
bool dst_has_buffer = p_dst_texture->shared_fallback->buffer.id != 0;
1785
bool from_src = p_src_texture->owner.is_null() && src_has_buffer;
1786
bool from_dst = p_dst_texture->owner.is_null() && dst_has_buffer;
1787
if (!from_src && !from_dst) {
1788
// If neither texture passed the condition, we just pick whichever texture has a reinterpretation buffer.
1789
from_src = src_has_buffer;
1790
from_dst = dst_has_buffer;
1791
}
1792
1793
// Pick the buffer and tracker to use from the right texture.
1794
RDD::BufferID shared_buffer;
1795
RDG::ResourceTracker *shared_buffer_tracker = nullptr;
1796
if (from_src) {
1797
shared_buffer = p_src_texture->shared_fallback->buffer;
1798
shared_buffer_tracker = p_src_texture->shared_fallback->buffer_tracker;
1799
} else if (from_dst) {
1800
shared_buffer = p_dst_texture->shared_fallback->buffer;
1801
shared_buffer_tracker = p_dst_texture->shared_fallback->buffer_tracker;
1802
} else {
1803
DEV_ASSERT(false && "This path should not be reachable.");
1804
}
1805
1806
// FIXME: When using reinterpretation buffers, the only texture aspect supported is color. Depth or stencil contents won't get copied.
1807
RDD::BufferTextureCopyRegion get_data_region;
1808
RDG::RecordedBufferToTextureCopy update_copy;
1809
RDD::TextureCopyableLayout first_copyable_layout;
1810
RDD::TextureCopyableLayout copyable_layout;
1811
RDD::TextureSubresource texture_subresource;
1812
texture_subresource.aspect = RDD::TEXTURE_ASPECT_COLOR;
1813
texture_subresource.layer = 0;
1814
texture_subresource.mipmap = 0;
1815
driver->texture_get_copyable_layout(p_dst_texture->shared_fallback->texture, texture_subresource, &first_copyable_layout);
1816
1817
// Copying each mipmap from main texture to a buffer and then to the slice texture.
1818
thread_local LocalVector<RDD::BufferTextureCopyRegion> get_data_vector;
1819
thread_local LocalVector<RDG::RecordedBufferToTextureCopy> update_vector;
1820
get_data_vector.clear();
1821
update_vector.clear();
1822
for (uint32_t i = 0; i < p_dst_texture->mipmaps; i++) {
1823
driver->texture_get_copyable_layout(p_dst_texture->shared_fallback->texture, texture_subresource, &copyable_layout);
1824
1825
uint32_t mipmap = p_dst_texture->base_mipmap + i;
1826
get_data_region.buffer_offset = copyable_layout.offset - first_copyable_layout.offset;
1827
get_data_region.texture_subresources.aspect = RDD::TEXTURE_ASPECT_COLOR_BIT;
1828
get_data_region.texture_subresources.base_layer = p_dst_texture->base_layer;
1829
get_data_region.texture_subresources.mipmap = mipmap;
1830
get_data_region.texture_subresources.layer_count = p_dst_texture->layers;
1831
get_data_region.texture_region_size.x = MAX(1U, p_src_texture->width >> mipmap);
1832
get_data_region.texture_region_size.y = MAX(1U, p_src_texture->height >> mipmap);
1833
get_data_region.texture_region_size.z = MAX(1U, p_src_texture->depth >> mipmap);
1834
get_data_vector.push_back(get_data_region);
1835
1836
update_copy.from_buffer = shared_buffer;
1837
update_copy.region.buffer_offset = get_data_region.buffer_offset;
1838
update_copy.region.texture_subresources.aspect = RDD::TEXTURE_ASPECT_COLOR_BIT;
1839
update_copy.region.texture_subresources.base_layer = texture_subresource.layer;
1840
update_copy.region.texture_subresources.mipmap = texture_subresource.mipmap;
1841
update_copy.region.texture_subresources.layer_count = get_data_region.texture_subresources.layer_count;
1842
update_copy.region.texture_region_size.x = get_data_region.texture_region_size.x;
1843
update_copy.region.texture_region_size.y = get_data_region.texture_region_size.y;
1844
update_copy.region.texture_region_size.z = get_data_region.texture_region_size.z;
1845
update_vector.push_back(update_copy);
1846
1847
texture_subresource.mipmap++;
1848
}
1849
1850
draw_graph.add_texture_get_data(p_src_texture->driver_id, p_src_texture->draw_tracker, shared_buffer, get_data_vector, shared_buffer_tracker);
1851
draw_graph.add_texture_update(p_dst_texture->shared_fallback->texture, p_dst_texture->shared_fallback->texture_tracker, update_vector, shared_buffer_tracker);
1852
} else {
1853
// Raw reinterpretation is not required. Use a regular texture copy.
1854
RDD::TextureCopyRegion copy_region;
1855
copy_region.src_subresources.aspect = p_src_texture->read_aspect_flags;
1856
copy_region.src_subresources.base_layer = p_dst_texture->base_layer;
1857
copy_region.src_subresources.layer_count = p_dst_texture->layers;
1858
copy_region.dst_subresources.aspect = p_dst_texture->read_aspect_flags;
1859
copy_region.dst_subresources.base_layer = 0;
1860
copy_region.dst_subresources.layer_count = copy_region.src_subresources.layer_count;
1861
1862
// Copying each mipmap from main texture to to the slice texture.
1863
thread_local LocalVector<RDD::TextureCopyRegion> region_vector;
1864
region_vector.clear();
1865
for (uint32_t i = 0; i < p_dst_texture->mipmaps; i++) {
1866
uint32_t mipmap = p_dst_texture->base_mipmap + i;
1867
copy_region.src_subresources.mipmap = mipmap;
1868
copy_region.dst_subresources.mipmap = i;
1869
copy_region.size.x = MAX(1U, p_src_texture->width >> mipmap);
1870
copy_region.size.y = MAX(1U, p_src_texture->height >> mipmap);
1871
copy_region.size.z = MAX(1U, p_src_texture->depth >> mipmap);
1872
region_vector.push_back(copy_region);
1873
}
1874
1875
draw_graph.add_texture_copy(p_src_texture->driver_id, p_src_texture->draw_tracker, p_dst_texture->shared_fallback->texture, p_dst_texture->shared_fallback->texture_tracker, region_vector);
1876
}
1877
}
1878
1879
void RenderingDevice::_texture_create_reinterpret_buffer(Texture *p_texture) {
1880
uint64_t row_pitch_step = driver->api_trait_get(RDD::API_TRAIT_TEXTURE_DATA_ROW_PITCH_STEP);
1881
uint64_t transfer_alignment = driver->api_trait_get(RDD::API_TRAIT_TEXTURE_TRANSFER_ALIGNMENT);
1882
uint32_t pixel_bytes = get_image_format_pixel_size(p_texture->format);
1883
uint32_t row_pitch = STEPIFY(p_texture->width * pixel_bytes, row_pitch_step);
1884
uint64_t buffer_size = STEPIFY(pixel_bytes * row_pitch * p_texture->height * p_texture->depth, transfer_alignment);
1885
p_texture->shared_fallback->buffer = driver->buffer_create(buffer_size, RDD::BUFFER_USAGE_TRANSFER_FROM_BIT | RDD::BUFFER_USAGE_TRANSFER_TO_BIT, RDD::MEMORY_ALLOCATION_TYPE_GPU);
1886
buffer_memory += driver->buffer_get_allocation_size(p_texture->shared_fallback->buffer);
1887
1888
RDG::ResourceTracker *tracker = RDG::resource_tracker_create();
1889
tracker->buffer_driver_id = p_texture->shared_fallback->buffer;
1890
p_texture->shared_fallback->buffer_tracker = tracker;
1891
}
1892
1893
uint32_t RenderingDevice::_texture_vrs_method_to_usage_bits() const {
1894
switch (vrs_method) {
1895
case VRS_METHOD_FRAGMENT_SHADING_RATE:
1896
return RDD::TEXTURE_USAGE_VRS_FRAGMENT_SHADING_RATE_BIT;
1897
case VRS_METHOD_FRAGMENT_DENSITY_MAP:
1898
return RDD::TEXTURE_USAGE_VRS_FRAGMENT_DENSITY_MAP_BIT;
1899
default:
1900
return 0;
1901
}
1902
}
1903
1904
Vector<uint8_t> RenderingDevice::_texture_get_data(Texture *tex, uint32_t p_layer, bool p_2d) {
1905
uint32_t width, height, depth;
1906
uint32_t tight_mip_size = get_image_format_required_size(tex->format, tex->width, tex->height, p_2d ? 1 : tex->depth, tex->mipmaps, &width, &height, &depth);
1907
1908
Vector<uint8_t> image_data;
1909
image_data.resize(tight_mip_size);
1910
1911
uint32_t blockw, blockh;
1912
get_compressed_image_format_block_dimensions(tex->format, blockw, blockh);
1913
uint32_t block_size = get_compressed_image_format_block_byte_size(tex->format);
1914
uint32_t pixel_size = get_image_format_pixel_size(tex->format);
1915
1916
{
1917
uint8_t *w = image_data.ptrw();
1918
1919
uint32_t mipmap_offset = 0;
1920
for (uint32_t mm_i = 0; mm_i < tex->mipmaps; mm_i++) {
1921
uint32_t image_total = get_image_format_required_size(tex->format, tex->width, tex->height, p_2d ? 1 : tex->depth, mm_i + 1, &width, &height, &depth);
1922
1923
uint8_t *write_ptr_mipmap = w + mipmap_offset;
1924
tight_mip_size = image_total - mipmap_offset;
1925
1926
RDD::TextureSubresource subres;
1927
subres.aspect = RDD::TEXTURE_ASPECT_COLOR;
1928
subres.layer = p_layer;
1929
subres.mipmap = mm_i;
1930
RDD::TextureCopyableLayout layout;
1931
driver->texture_get_copyable_layout(tex->driver_id, subres, &layout);
1932
1933
uint8_t *img_mem = driver->texture_map(tex->driver_id, subres);
1934
ERR_FAIL_NULL_V(img_mem, Vector<uint8_t>());
1935
1936
for (uint32_t z = 0; z < depth; z++) {
1937
uint8_t *write_ptr = write_ptr_mipmap + z * tight_mip_size / depth;
1938
const uint8_t *slice_read_ptr = img_mem + z * layout.depth_pitch;
1939
1940
if (block_size > 1) {
1941
// Compressed.
1942
uint32_t line_width = (block_size * (width / blockw));
1943
for (uint32_t y = 0; y < height / blockh; y++) {
1944
const uint8_t *rptr = slice_read_ptr + y * layout.row_pitch;
1945
uint8_t *wptr = write_ptr + y * line_width;
1946
1947
memcpy(wptr, rptr, line_width);
1948
}
1949
1950
} else {
1951
// Uncompressed.
1952
for (uint32_t y = 0; y < height; y++) {
1953
const uint8_t *rptr = slice_read_ptr + y * layout.row_pitch;
1954
uint8_t *wptr = write_ptr + y * pixel_size * width;
1955
memcpy(wptr, rptr, (uint64_t)pixel_size * width);
1956
}
1957
}
1958
}
1959
1960
driver->texture_unmap(tex->driver_id);
1961
1962
mipmap_offset = image_total;
1963
}
1964
}
1965
1966
return image_data;
1967
}
1968
1969
Vector<uint8_t> RenderingDevice::texture_get_data(RID p_texture, uint32_t p_layer) {
1970
ERR_RENDER_THREAD_GUARD_V(Vector<uint8_t>());
1971
1972
Texture *tex = texture_owner.get_or_null(p_texture);
1973
ERR_FAIL_NULL_V(tex, Vector<uint8_t>());
1974
1975
ERR_FAIL_COND_V_MSG(tex->bound, Vector<uint8_t>(),
1976
"Texture can't be retrieved while a draw list that uses it as part of a framebuffer is being created. Ensure the draw list is finalized (and that the color/depth texture using it is not set to `RenderingDevice.FINAL_ACTION_CONTINUE`) to retrieve this texture.");
1977
ERR_FAIL_COND_V_MSG(!(tex->usage_flags & TEXTURE_USAGE_CAN_COPY_FROM_BIT), Vector<uint8_t>(),
1978
"Texture requires the `RenderingDevice.TEXTURE_USAGE_CAN_COPY_FROM_BIT` to be set to be retrieved.");
1979
1980
ERR_FAIL_COND_V(p_layer >= tex->layers, Vector<uint8_t>());
1981
1982
_check_transfer_worker_texture(tex);
1983
1984
if (tex->usage_flags & TEXTURE_USAGE_CPU_READ_BIT) {
1985
// Does not need anything fancy, map and read.
1986
return _texture_get_data(tex, p_layer);
1987
} else {
1988
LocalVector<RDD::TextureCopyableLayout> mip_layouts;
1989
uint32_t work_mip_alignment = driver->api_trait_get(RDD::API_TRAIT_TEXTURE_TRANSFER_ALIGNMENT);
1990
uint32_t work_buffer_size = 0;
1991
mip_layouts.resize(tex->mipmaps);
1992
for (uint32_t i = 0; i < tex->mipmaps; i++) {
1993
RDD::TextureSubresource subres;
1994
subres.aspect = RDD::TEXTURE_ASPECT_COLOR;
1995
subres.layer = p_layer;
1996
subres.mipmap = i;
1997
driver->texture_get_copyable_layout(tex->driver_id, subres, &mip_layouts[i]);
1998
1999
// Assuming layers are tightly packed. If this is not true on some driver, we must modify the copy algorithm.
2000
DEV_ASSERT(mip_layouts[i].layer_pitch == mip_layouts[i].size / tex->layers);
2001
2002
work_buffer_size = STEPIFY(work_buffer_size, work_mip_alignment) + mip_layouts[i].size;
2003
}
2004
2005
RDD::BufferID tmp_buffer = driver->buffer_create(work_buffer_size, RDD::BUFFER_USAGE_TRANSFER_TO_BIT, RDD::MEMORY_ALLOCATION_TYPE_CPU);
2006
ERR_FAIL_COND_V(!tmp_buffer, Vector<uint8_t>());
2007
2008
thread_local LocalVector<RDD::BufferTextureCopyRegion> command_buffer_texture_copy_regions_vector;
2009
command_buffer_texture_copy_regions_vector.clear();
2010
2011
uint32_t w = tex->width;
2012
uint32_t h = tex->height;
2013
uint32_t d = tex->depth;
2014
for (uint32_t i = 0; i < tex->mipmaps; i++) {
2015
RDD::BufferTextureCopyRegion copy_region;
2016
copy_region.buffer_offset = mip_layouts[i].offset;
2017
copy_region.texture_subresources.aspect = tex->read_aspect_flags;
2018
copy_region.texture_subresources.mipmap = i;
2019
copy_region.texture_subresources.base_layer = p_layer;
2020
copy_region.texture_subresources.layer_count = 1;
2021
copy_region.texture_region_size.x = w;
2022
copy_region.texture_region_size.y = h;
2023
copy_region.texture_region_size.z = d;
2024
command_buffer_texture_copy_regions_vector.push_back(copy_region);
2025
2026
w = MAX(1u, w >> 1);
2027
h = MAX(1u, h >> 1);
2028
d = MAX(1u, d >> 1);
2029
}
2030
2031
if (_texture_make_mutable(tex, p_texture)) {
2032
// The texture must be mutable to be used as a copy source due to layout transitions.
2033
draw_graph.add_synchronization();
2034
}
2035
2036
draw_graph.add_texture_get_data(tex->driver_id, tex->draw_tracker, tmp_buffer, command_buffer_texture_copy_regions_vector);
2037
2038
// Flush everything so memory can be safely mapped.
2039
_flush_and_stall_for_all_frames();
2040
2041
const uint8_t *read_ptr = driver->buffer_map(tmp_buffer);
2042
ERR_FAIL_NULL_V(read_ptr, Vector<uint8_t>());
2043
2044
uint32_t block_w = 0;
2045
uint32_t block_h = 0;
2046
get_compressed_image_format_block_dimensions(tex->format, block_w, block_h);
2047
2048
Vector<uint8_t> buffer_data;
2049
uint32_t tight_buffer_size = get_image_format_required_size(tex->format, tex->width, tex->height, tex->depth, tex->mipmaps);
2050
buffer_data.resize(tight_buffer_size);
2051
2052
uint8_t *write_ptr = buffer_data.ptrw();
2053
2054
w = tex->width;
2055
h = tex->height;
2056
d = tex->depth;
2057
for (uint32_t i = 0; i < tex->mipmaps; i++) {
2058
uint32_t width = 0, height = 0, depth = 0;
2059
uint32_t tight_mip_size = get_image_format_required_size(tex->format, w, h, d, 1, &width, &height, &depth);
2060
uint32_t tight_row_pitch = tight_mip_size / ((height / block_h) * depth);
2061
2062
// Copy row-by-row to erase padding due to alignments.
2063
const uint8_t *rp = read_ptr;
2064
uint8_t *wp = write_ptr;
2065
for (uint32_t row = h * d / block_h; row != 0; row--) {
2066
memcpy(wp, rp, tight_row_pitch);
2067
rp += mip_layouts[i].row_pitch;
2068
wp += tight_row_pitch;
2069
}
2070
2071
w = MAX(block_w, w >> 1);
2072
h = MAX(block_h, h >> 1);
2073
d = MAX(1u, d >> 1);
2074
read_ptr += mip_layouts[i].size;
2075
write_ptr += tight_mip_size;
2076
}
2077
2078
driver->buffer_unmap(tmp_buffer);
2079
driver->buffer_free(tmp_buffer);
2080
2081
return buffer_data;
2082
}
2083
}
2084
2085
Error RenderingDevice::texture_get_data_async(RID p_texture, uint32_t p_layer, const Callable &p_callback) {
2086
ERR_RENDER_THREAD_GUARD_V(ERR_UNAVAILABLE);
2087
2088
Texture *tex = texture_owner.get_or_null(p_texture);
2089
ERR_FAIL_NULL_V(tex, ERR_INVALID_PARAMETER);
2090
2091
ERR_FAIL_COND_V_MSG(tex->bound, ERR_INVALID_PARAMETER, "Texture can't be retrieved while a draw list that uses it as part of a framebuffer is being created. Ensure the draw list is finalized (and that the color/depth texture using it is not set to `RenderingDevice.FINAL_ACTION_CONTINUE`) to retrieve this texture.");
2092
ERR_FAIL_COND_V_MSG(!(tex->usage_flags & TEXTURE_USAGE_CAN_COPY_FROM_BIT), ERR_INVALID_PARAMETER, "Texture requires the `RenderingDevice.TEXTURE_USAGE_CAN_COPY_FROM_BIT` to be set to be retrieved.");
2093
ERR_FAIL_COND_V(p_layer >= tex->layers, ERR_INVALID_PARAMETER);
2094
2095
_check_transfer_worker_texture(tex);
2096
2097
thread_local LocalVector<RDD::TextureCopyableLayout> mip_layouts;
2098
mip_layouts.resize(tex->mipmaps);
2099
for (uint32_t i = 0; i < tex->mipmaps; i++) {
2100
RDD::TextureSubresource subres;
2101
subres.aspect = RDD::TEXTURE_ASPECT_COLOR;
2102
subres.layer = p_layer;
2103
subres.mipmap = i;
2104
driver->texture_get_copyable_layout(tex->driver_id, subres, &mip_layouts[i]);
2105
2106
// Assuming layers are tightly packed. If this is not true on some driver, we must modify the copy algorithm.
2107
DEV_ASSERT(mip_layouts[i].layer_pitch == mip_layouts[i].size / tex->layers);
2108
}
2109
2110
ERR_FAIL_COND_V(mip_layouts.is_empty(), ERR_INVALID_PARAMETER);
2111
2112
if (_texture_make_mutable(tex, p_texture)) {
2113
// The texture must be mutable to be used as a copy source due to layout transitions.
2114
draw_graph.add_synchronization();
2115
}
2116
2117
TextureGetDataRequest get_data_request;
2118
get_data_request.callback = p_callback;
2119
get_data_request.frame_local_index = frames[frame].download_buffer_texture_copy_regions.size();
2120
get_data_request.width = tex->width;
2121
get_data_request.height = tex->height;
2122
get_data_request.depth = tex->depth;
2123
get_data_request.format = tex->format;
2124
get_data_request.mipmaps = tex->mipmaps;
2125
2126
uint32_t block_w, block_h;
2127
get_compressed_image_format_block_dimensions(tex->format, block_w, block_h);
2128
2129
uint32_t pixel_size = get_image_format_pixel_size(tex->format);
2130
uint32_t pixel_rshift = get_compressed_image_format_pixel_rshift(tex->format);
2131
2132
uint32_t w, h, d;
2133
uint32_t required_align = driver->api_trait_get(RDD::API_TRAIT_TEXTURE_TRANSFER_ALIGNMENT);
2134
uint32_t pitch_step = driver->api_trait_get(RDD::API_TRAIT_TEXTURE_DATA_ROW_PITCH_STEP);
2135
uint32_t region_size = texture_download_region_size_px;
2136
uint32_t logic_w = tex->width;
2137
uint32_t logic_h = tex->height;
2138
uint32_t mipmap_offset = 0;
2139
uint32_t block_write_offset;
2140
uint32_t block_write_amount;
2141
StagingRequiredAction required_action;
2142
for (uint32_t i = 0; i < tex->mipmaps; i++) {
2143
uint32_t image_total = get_image_format_required_size(tex->format, tex->width, tex->height, tex->depth, i + 1, &w, &h, &d);
2144
uint32_t tight_mip_size = image_total - mipmap_offset;
2145
for (uint32_t z = 0; z < d; z++) {
2146
for (uint32_t y = 0; y < h; y += region_size) {
2147
for (uint32_t x = 0; x < w; x += region_size) {
2148
uint32_t region_w = MIN(region_size, w - x);
2149
uint32_t region_h = MIN(region_size, h - y);
2150
ERR_FAIL_COND_V(region_w % block_w, ERR_BUG);
2151
ERR_FAIL_COND_V(region_h % block_h, ERR_BUG);
2152
2153
uint32_t region_logic_w = MIN(region_size, logic_w - x);
2154
uint32_t region_logic_h = MIN(region_size, logic_h - y);
2155
uint32_t region_pitch = (region_w * pixel_size * block_w) >> pixel_rshift;
2156
region_pitch = STEPIFY(region_pitch, pitch_step);
2157
2158
uint32_t to_allocate = region_pitch * region_h;
2159
Error err = _staging_buffer_allocate(download_staging_buffers, to_allocate, required_align, block_write_offset, block_write_amount, required_action, false);
2160
ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
2161
2162
const bool flush_frames = (get_data_request.frame_local_count > 0) && required_action == STAGING_REQUIRED_ACTION_FLUSH_AND_STALL_ALL;
2163
if (flush_frames) {
2164
for (uint32_t j = 0; j < get_data_request.frame_local_count; j++) {
2165
uint32_t local_index = get_data_request.frame_local_index + j;
2166
draw_graph.add_texture_get_data(tex->driver_id, tex->draw_tracker, frames[frame].download_texture_staging_buffers[local_index], frames[frame].download_buffer_texture_copy_regions[local_index]);
2167
}
2168
}
2169
2170
_staging_buffer_execute_required_action(download_staging_buffers, required_action);
2171
2172
if (flush_frames) {
2173
get_data_request.frame_local_count = 0;
2174
get_data_request.frame_local_index = frames[frame].download_buffer_texture_copy_regions.size();
2175
}
2176
2177
RDD::BufferTextureCopyRegion copy_region;
2178
copy_region.buffer_offset = block_write_offset;
2179
copy_region.texture_subresources.aspect = tex->read_aspect_flags;
2180
copy_region.texture_subresources.mipmap = i;
2181
copy_region.texture_subresources.base_layer = p_layer;
2182
copy_region.texture_subresources.layer_count = 1;
2183
copy_region.texture_offset = Vector3i(x, y, z);
2184
copy_region.texture_region_size = Vector3i(region_logic_w, region_logic_h, 1);
2185
frames[frame].download_texture_staging_buffers.push_back(download_staging_buffers.blocks[download_staging_buffers.current].driver_id);
2186
frames[frame].download_buffer_texture_copy_regions.push_back(copy_region);
2187
frames[frame].download_texture_mipmap_offsets.push_back(mipmap_offset + (tight_mip_size / d) * z);
2188
get_data_request.frame_local_count++;
2189
2190
download_staging_buffers.blocks.write[download_staging_buffers.current].fill_amount = block_write_offset + block_write_amount;
2191
}
2192
}
2193
}
2194
2195
mipmap_offset = image_total;
2196
logic_w = MAX(1u, logic_w >> 1);
2197
logic_h = MAX(1u, logic_h >> 1);
2198
}
2199
2200
if (get_data_request.frame_local_count > 0) {
2201
for (uint32_t i = 0; i < get_data_request.frame_local_count; i++) {
2202
uint32_t local_index = get_data_request.frame_local_index + i;
2203
draw_graph.add_texture_get_data(tex->driver_id, tex->draw_tracker, frames[frame].download_texture_staging_buffers[local_index], frames[frame].download_buffer_texture_copy_regions[local_index]);
2204
}
2205
2206
frames[frame].download_texture_get_data_requests.push_back(get_data_request);
2207
}
2208
2209
return OK;
2210
}
2211
2212
bool RenderingDevice::texture_is_shared(RID p_texture) {
2213
ERR_RENDER_THREAD_GUARD_V(false);
2214
2215
Texture *tex = texture_owner.get_or_null(p_texture);
2216
ERR_FAIL_NULL_V(tex, false);
2217
return tex->owner.is_valid();
2218
}
2219
2220
bool RenderingDevice::texture_is_valid(RID p_texture) {
2221
ERR_RENDER_THREAD_GUARD_V(false);
2222
2223
return texture_owner.owns(p_texture);
2224
}
2225
2226
RD::TextureFormat RenderingDevice::texture_get_format(RID p_texture) {
2227
ERR_RENDER_THREAD_GUARD_V(TextureFormat());
2228
2229
Texture *tex = texture_owner.get_or_null(p_texture);
2230
ERR_FAIL_NULL_V(tex, TextureFormat());
2231
2232
TextureFormat tf;
2233
2234
tf.format = tex->format;
2235
tf.width = tex->width;
2236
tf.height = tex->height;
2237
tf.depth = tex->depth;
2238
tf.array_layers = tex->layers;
2239
tf.mipmaps = tex->mipmaps;
2240
tf.texture_type = tex->type;
2241
tf.samples = tex->samples;
2242
tf.usage_bits = tex->usage_flags;
2243
tf.shareable_formats = tex->allowed_shared_formats;
2244
tf.is_resolve_buffer = tex->is_resolve_buffer;
2245
tf.is_discardable = tex->is_discardable;
2246
2247
return tf;
2248
}
2249
2250
Size2i RenderingDevice::texture_size(RID p_texture) {
2251
ERR_RENDER_THREAD_GUARD_V(Size2i());
2252
2253
Texture *tex = texture_owner.get_or_null(p_texture);
2254
ERR_FAIL_NULL_V(tex, Size2i());
2255
return Size2i(tex->width, tex->height);
2256
}
2257
2258
#ifndef DISABLE_DEPRECATED
2259
uint64_t RenderingDevice::texture_get_native_handle(RID p_texture) {
2260
return get_driver_resource(DRIVER_RESOURCE_TEXTURE, p_texture);
2261
}
2262
#endif
2263
2264
Error RenderingDevice::texture_copy(RID p_from_texture, RID p_to_texture, const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_size, uint32_t p_src_mipmap, uint32_t p_dst_mipmap, uint32_t p_src_layer, uint32_t p_dst_layer) {
2265
ERR_RENDER_THREAD_GUARD_V(ERR_UNAVAILABLE);
2266
2267
Texture *src_tex = texture_owner.get_or_null(p_from_texture);
2268
ERR_FAIL_NULL_V(src_tex, ERR_INVALID_PARAMETER);
2269
2270
ERR_FAIL_COND_V_MSG(src_tex->bound, ERR_INVALID_PARAMETER,
2271
"Source texture can't be copied while a draw list that uses it as part of a framebuffer is being created. Ensure the draw list is finalized (and that the color/depth texture using it is not set to `RenderingDevice.FINAL_ACTION_CONTINUE`) to copy this texture.");
2272
ERR_FAIL_COND_V_MSG(!(src_tex->usage_flags & TEXTURE_USAGE_CAN_COPY_FROM_BIT), ERR_INVALID_PARAMETER,
2273
"Source texture requires the `RenderingDevice.TEXTURE_USAGE_CAN_COPY_FROM_BIT` to be set to be retrieved.");
2274
2275
uint32_t src_width, src_height, src_depth;
2276
get_image_format_required_size(src_tex->format, src_tex->width, src_tex->height, src_tex->depth, p_src_mipmap + 1, &src_width, &src_height, &src_depth);
2277
2278
ERR_FAIL_COND_V(p_from.x < 0 || p_from.x + p_size.x > src_width, ERR_INVALID_PARAMETER);
2279
ERR_FAIL_COND_V(p_from.y < 0 || p_from.y + p_size.y > src_height, ERR_INVALID_PARAMETER);
2280
ERR_FAIL_COND_V(p_from.z < 0 || p_from.z + p_size.z > src_depth, ERR_INVALID_PARAMETER);
2281
ERR_FAIL_COND_V(p_src_mipmap >= src_tex->mipmaps, ERR_INVALID_PARAMETER);
2282
ERR_FAIL_COND_V(p_src_layer >= src_tex->layers, ERR_INVALID_PARAMETER);
2283
2284
Texture *dst_tex = texture_owner.get_or_null(p_to_texture);
2285
ERR_FAIL_NULL_V(dst_tex, ERR_INVALID_PARAMETER);
2286
2287
ERR_FAIL_COND_V_MSG(dst_tex->bound, ERR_INVALID_PARAMETER,
2288
"Destination texture can't be copied while a draw list that uses it as part of a framebuffer is being created. Ensure the draw list is finalized (and that the color/depth texture using it is not set to `RenderingDevice.FINAL_ACTION_CONTINUE`) to copy this texture.");
2289
ERR_FAIL_COND_V_MSG(!(dst_tex->usage_flags & TEXTURE_USAGE_CAN_COPY_TO_BIT), ERR_INVALID_PARAMETER,
2290
"Destination texture requires the `RenderingDevice.TEXTURE_USAGE_CAN_COPY_TO_BIT` to be set to be retrieved.");
2291
2292
uint32_t dst_width, dst_height, dst_depth;
2293
get_image_format_required_size(dst_tex->format, dst_tex->width, dst_tex->height, dst_tex->depth, p_dst_mipmap + 1, &dst_width, &dst_height, &dst_depth);
2294
2295
ERR_FAIL_COND_V(p_to.x < 0 || p_to.x + p_size.x > dst_width, ERR_INVALID_PARAMETER);
2296
ERR_FAIL_COND_V(p_to.y < 0 || p_to.y + p_size.y > dst_height, ERR_INVALID_PARAMETER);
2297
ERR_FAIL_COND_V(p_to.z < 0 || p_to.z + p_size.z > dst_depth, ERR_INVALID_PARAMETER);
2298
ERR_FAIL_COND_V(p_dst_mipmap >= dst_tex->mipmaps, ERR_INVALID_PARAMETER);
2299
ERR_FAIL_COND_V(p_dst_layer >= dst_tex->layers, ERR_INVALID_PARAMETER);
2300
2301
ERR_FAIL_COND_V_MSG(src_tex->read_aspect_flags != dst_tex->read_aspect_flags, ERR_INVALID_PARAMETER,
2302
"Source and destination texture must be of the same type (color or depth).");
2303
2304
_check_transfer_worker_texture(src_tex);
2305
_check_transfer_worker_texture(dst_tex);
2306
2307
RDD::TextureCopyRegion copy_region;
2308
copy_region.src_subresources.aspect = src_tex->read_aspect_flags;
2309
copy_region.src_subresources.mipmap = p_src_mipmap;
2310
copy_region.src_subresources.base_layer = p_src_layer;
2311
copy_region.src_subresources.layer_count = 1;
2312
copy_region.src_offset = p_from;
2313
2314
copy_region.dst_subresources.aspect = dst_tex->read_aspect_flags;
2315
copy_region.dst_subresources.mipmap = p_dst_mipmap;
2316
copy_region.dst_subresources.base_layer = p_dst_layer;
2317
copy_region.dst_subresources.layer_count = 1;
2318
copy_region.dst_offset = p_to;
2319
2320
copy_region.size = p_size;
2321
2322
// Indicate the texture will get modified for the shared texture fallback.
2323
_texture_update_shared_fallback(p_to_texture, dst_tex, true);
2324
2325
// The textures must be mutable to be used in the copy operation.
2326
bool src_made_mutable = _texture_make_mutable(src_tex, p_from_texture);
2327
bool dst_made_mutable = _texture_make_mutable(dst_tex, p_to_texture);
2328
if (src_made_mutable || dst_made_mutable) {
2329
draw_graph.add_synchronization();
2330
}
2331
2332
draw_graph.add_texture_copy(src_tex->driver_id, src_tex->draw_tracker, dst_tex->driver_id, dst_tex->draw_tracker, copy_region);
2333
2334
return OK;
2335
}
2336
2337
Error RenderingDevice::texture_resolve_multisample(RID p_from_texture, RID p_to_texture) {
2338
ERR_RENDER_THREAD_GUARD_V(ERR_UNAVAILABLE);
2339
2340
Texture *src_tex = texture_owner.get_or_null(p_from_texture);
2341
ERR_FAIL_NULL_V(src_tex, ERR_INVALID_PARAMETER);
2342
2343
ERR_FAIL_COND_V_MSG(src_tex->bound, ERR_INVALID_PARAMETER,
2344
"Source texture can't be copied while a draw list that uses it as part of a framebuffer is being created. Ensure the draw list is finalized (and that the color/depth texture using it is not set to `RenderingDevice.FINAL_ACTION_CONTINUE`) to copy this texture.");
2345
ERR_FAIL_COND_V_MSG(!(src_tex->usage_flags & TEXTURE_USAGE_CAN_COPY_FROM_BIT), ERR_INVALID_PARAMETER,
2346
"Source texture requires the `RenderingDevice.TEXTURE_USAGE_CAN_COPY_FROM_BIT` to be set to be retrieved.");
2347
2348
ERR_FAIL_COND_V_MSG(src_tex->type != TEXTURE_TYPE_2D, ERR_INVALID_PARAMETER, "Source texture must be 2D (or a slice of a 3D/Cube texture)");
2349
ERR_FAIL_COND_V_MSG(src_tex->samples == TEXTURE_SAMPLES_1, ERR_INVALID_PARAMETER, "Source texture must be multisampled.");
2350
2351
Texture *dst_tex = texture_owner.get_or_null(p_to_texture);
2352
ERR_FAIL_NULL_V(dst_tex, ERR_INVALID_PARAMETER);
2353
2354
ERR_FAIL_COND_V_MSG(dst_tex->bound, ERR_INVALID_PARAMETER,
2355
"Destination texture can't be copied while a draw list that uses it as part of a framebuffer is being created. Ensure the draw list is finalized (and that the color/depth texture using it is not set to `RenderingDevice.FINAL_ACTION_CONTINUE`) to copy this texture.");
2356
ERR_FAIL_COND_V_MSG(!(dst_tex->usage_flags & TEXTURE_USAGE_CAN_COPY_TO_BIT), ERR_INVALID_PARAMETER,
2357
"Destination texture requires the `RenderingDevice.TEXTURE_USAGE_CAN_COPY_TO_BIT` to be set to be retrieved.");
2358
2359
ERR_FAIL_COND_V_MSG(dst_tex->type != TEXTURE_TYPE_2D, ERR_INVALID_PARAMETER, "Destination texture must be 2D (or a slice of a 3D/Cube texture).");
2360
ERR_FAIL_COND_V_MSG(dst_tex->samples != TEXTURE_SAMPLES_1, ERR_INVALID_PARAMETER, "Destination texture must not be multisampled.");
2361
2362
ERR_FAIL_COND_V_MSG(src_tex->format != dst_tex->format, ERR_INVALID_PARAMETER, "Source and Destination textures must be the same format.");
2363
ERR_FAIL_COND_V_MSG(src_tex->width != dst_tex->width && src_tex->height != dst_tex->height && src_tex->depth != dst_tex->depth, ERR_INVALID_PARAMETER, "Source and Destination textures must have the same dimensions.");
2364
2365
ERR_FAIL_COND_V_MSG(src_tex->read_aspect_flags != dst_tex->read_aspect_flags, ERR_INVALID_PARAMETER,
2366
"Source and destination texture must be of the same type (color or depth).");
2367
2368
// Indicate the texture will get modified for the shared texture fallback.
2369
_texture_update_shared_fallback(p_to_texture, dst_tex, true);
2370
2371
_check_transfer_worker_texture(src_tex);
2372
_check_transfer_worker_texture(dst_tex);
2373
2374
// The textures must be mutable to be used in the resolve operation.
2375
bool src_made_mutable = _texture_make_mutable(src_tex, p_from_texture);
2376
bool dst_made_mutable = _texture_make_mutable(dst_tex, p_to_texture);
2377
if (src_made_mutable || dst_made_mutable) {
2378
draw_graph.add_synchronization();
2379
}
2380
2381
draw_graph.add_texture_resolve(src_tex->driver_id, src_tex->draw_tracker, dst_tex->driver_id, dst_tex->draw_tracker, src_tex->base_layer, src_tex->base_mipmap, dst_tex->base_layer, dst_tex->base_mipmap);
2382
2383
return OK;
2384
}
2385
2386
void RenderingDevice::texture_set_discardable(RID p_texture, bool p_discardable) {
2387
ERR_RENDER_THREAD_GUARD();
2388
2389
Texture *texture = texture_owner.get_or_null(p_texture);
2390
ERR_FAIL_NULL(texture);
2391
2392
texture->is_discardable = p_discardable;
2393
2394
if (texture->draw_tracker != nullptr) {
2395
texture->draw_tracker->is_discardable = p_discardable;
2396
}
2397
2398
if (texture->shared_fallback != nullptr && texture->shared_fallback->texture_tracker != nullptr) {
2399
texture->shared_fallback->texture_tracker->is_discardable = p_discardable;
2400
}
2401
}
2402
2403
bool RenderingDevice::texture_is_discardable(RID p_texture) {
2404
ERR_RENDER_THREAD_GUARD_V(false);
2405
2406
Texture *texture = texture_owner.get_or_null(p_texture);
2407
ERR_FAIL_NULL_V(texture, false);
2408
2409
return texture->is_discardable;
2410
}
2411
2412
Error RenderingDevice::texture_clear(RID p_texture, const Color &p_color, uint32_t p_base_mipmap, uint32_t p_mipmaps, uint32_t p_base_layer, uint32_t p_layers) {
2413
ERR_RENDER_THREAD_GUARD_V(ERR_UNAVAILABLE);
2414
2415
Texture *src_tex = texture_owner.get_or_null(p_texture);
2416
ERR_FAIL_NULL_V(src_tex, ERR_INVALID_PARAMETER);
2417
2418
ERR_FAIL_COND_V_MSG(src_tex->bound, ERR_INVALID_PARAMETER,
2419
"Source texture can't be cleared while a draw list that uses it as part of a framebuffer is being created. Ensure the draw list is finalized (and that the color/depth texture using it is not set to `RenderingDevice.FINAL_ACTION_CONTINUE`) to clear this texture.");
2420
2421
ERR_FAIL_COND_V(p_layers == 0, ERR_INVALID_PARAMETER);
2422
ERR_FAIL_COND_V(p_mipmaps == 0, ERR_INVALID_PARAMETER);
2423
2424
ERR_FAIL_COND_V_MSG(!(src_tex->usage_flags & TEXTURE_USAGE_CAN_COPY_TO_BIT), ERR_INVALID_PARAMETER,
2425
"Source texture requires the `RenderingDevice.TEXTURE_USAGE_CAN_COPY_TO_BIT` to be set to be cleared.");
2426
2427
ERR_FAIL_COND_V(p_base_mipmap + p_mipmaps > src_tex->mipmaps, ERR_INVALID_PARAMETER);
2428
ERR_FAIL_COND_V(p_base_layer + p_layers > src_tex->layers, ERR_INVALID_PARAMETER);
2429
2430
_check_transfer_worker_texture(src_tex);
2431
2432
RDD::TextureSubresourceRange range;
2433
range.aspect = src_tex->read_aspect_flags;
2434
range.base_mipmap = src_tex->base_mipmap + p_base_mipmap;
2435
range.mipmap_count = p_mipmaps;
2436
range.base_layer = src_tex->base_layer + p_base_layer;
2437
range.layer_count = p_layers;
2438
2439
// Indicate the texture will get modified for the shared texture fallback.
2440
_texture_update_shared_fallback(p_texture, src_tex, true);
2441
2442
if (_texture_make_mutable(src_tex, p_texture)) {
2443
// The texture must be mutable to be used as a clear destination.
2444
draw_graph.add_synchronization();
2445
}
2446
2447
draw_graph.add_texture_clear(src_tex->driver_id, src_tex->draw_tracker, p_color, range);
2448
2449
return OK;
2450
}
2451
2452
bool RenderingDevice::texture_is_format_supported_for_usage(DataFormat p_format, BitField<RenderingDevice::TextureUsageBits> p_usage) const {
2453
ERR_FAIL_INDEX_V(p_format, DATA_FORMAT_MAX, false);
2454
2455
bool cpu_readable = (p_usage & RDD::TEXTURE_USAGE_CPU_READ_BIT);
2456
BitField<TextureUsageBits> supported = driver->texture_get_usages_supported_by_format(p_format, cpu_readable);
2457
bool any_unsupported = (((int64_t)supported) | ((int64_t)p_usage)) != ((int64_t)supported);
2458
return !any_unsupported;
2459
}
2460
2461
/*********************/
2462
/**** FRAMEBUFFER ****/
2463
/*********************/
2464
2465
RDD::RenderPassID RenderingDevice::_render_pass_create(RenderingDeviceDriver *p_driver, const Vector<AttachmentFormat> &p_attachments, const Vector<FramebufferPass> &p_passes, VectorView<RDD::AttachmentLoadOp> p_load_ops, VectorView<RDD::AttachmentStoreOp> p_store_ops, uint32_t p_view_count, VRSMethod p_vrs_method, int32_t p_vrs_attachment, Size2i p_vrs_texel_size, Vector<TextureSamples> *r_samples) {
2466
// NOTE:
2467
// Before the refactor to RenderingDevice-RenderingDeviceDriver, there was commented out code to
2468
// specify dependencies to external subpasses. Since it had been unused for a long timel it wasn't ported
2469
// to the new architecture.
2470
2471
LocalVector<int32_t> attachment_last_pass;
2472
attachment_last_pass.resize(p_attachments.size());
2473
2474
if (p_view_count > 1) {
2475
const RDD::MultiviewCapabilities &capabilities = p_driver->get_multiview_capabilities();
2476
2477
// This only works with multiview!
2478
ERR_FAIL_COND_V_MSG(!capabilities.is_supported, RDD::RenderPassID(), "Multiview not supported");
2479
2480
// Make sure we limit this to the number of views we support.
2481
ERR_FAIL_COND_V_MSG(p_view_count > capabilities.max_view_count, RDD::RenderPassID(), "Hardware does not support requested number of views for Multiview render pass");
2482
}
2483
2484
LocalVector<RDD::Attachment> attachments;
2485
LocalVector<uint32_t> attachment_remap;
2486
2487
for (int i = 0; i < p_attachments.size(); i++) {
2488
if (p_attachments[i].usage_flags == AttachmentFormat::UNUSED_ATTACHMENT) {
2489
attachment_remap.push_back(RDD::AttachmentReference::UNUSED);
2490
continue;
2491
}
2492
2493
ERR_FAIL_INDEX_V(p_attachments[i].format, DATA_FORMAT_MAX, RDD::RenderPassID());
2494
ERR_FAIL_INDEX_V(p_attachments[i].samples, TEXTURE_SAMPLES_MAX, RDD::RenderPassID());
2495
ERR_FAIL_COND_V_MSG(!(p_attachments[i].usage_flags & (TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | TEXTURE_USAGE_INPUT_ATTACHMENT_BIT | TEXTURE_USAGE_VRS_ATTACHMENT_BIT)),
2496
RDD::RenderPassID(), "Texture format for index (" + itos(i) + ") requires an attachment (color, depth-stencil, input or VRS) bit set.");
2497
2498
RDD::Attachment description;
2499
description.format = p_attachments[i].format;
2500
description.samples = p_attachments[i].samples;
2501
2502
// We can setup a framebuffer where we write to our VRS texture to set it up.
2503
// We make the assumption here that if our texture is actually used as our VRS attachment.
2504
// It is used as such for each subpass. This is fairly certain seeing the restrictions on subpasses.
2505
bool is_vrs = (p_attachments[i].usage_flags & TEXTURE_USAGE_VRS_ATTACHMENT_BIT) && i == p_vrs_attachment;
2506
if (is_vrs) {
2507
description.load_op = RDD::ATTACHMENT_LOAD_OP_LOAD;
2508
description.store_op = RDD::ATTACHMENT_STORE_OP_DONT_CARE;
2509
description.stencil_load_op = RDD::ATTACHMENT_LOAD_OP_DONT_CARE;
2510
description.stencil_store_op = RDD::ATTACHMENT_STORE_OP_DONT_CARE;
2511
description.initial_layout = _vrs_layout_from_method(p_vrs_method);
2512
description.final_layout = _vrs_layout_from_method(p_vrs_method);
2513
} else {
2514
if (p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
2515
description.load_op = p_load_ops[i];
2516
description.store_op = p_store_ops[i];
2517
description.stencil_load_op = RDD::ATTACHMENT_LOAD_OP_DONT_CARE;
2518
description.stencil_store_op = RDD::ATTACHMENT_STORE_OP_DONT_CARE;
2519
description.initial_layout = RDD::TEXTURE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
2520
description.final_layout = RDD::TEXTURE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
2521
} else if (p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
2522
description.load_op = p_load_ops[i];
2523
description.store_op = p_store_ops[i];
2524
description.stencil_load_op = p_load_ops[i];
2525
description.stencil_store_op = p_store_ops[i];
2526
description.initial_layout = RDD::TEXTURE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
2527
description.final_layout = RDD::TEXTURE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
2528
} else {
2529
description.load_op = RDD::ATTACHMENT_LOAD_OP_DONT_CARE;
2530
description.store_op = RDD::ATTACHMENT_STORE_OP_DONT_CARE;
2531
description.stencil_load_op = RDD::ATTACHMENT_LOAD_OP_DONT_CARE;
2532
description.stencil_store_op = RDD::ATTACHMENT_STORE_OP_DONT_CARE;
2533
description.initial_layout = RDD::TEXTURE_LAYOUT_UNDEFINED;
2534
description.final_layout = RDD::TEXTURE_LAYOUT_UNDEFINED;
2535
}
2536
}
2537
2538
attachment_last_pass[i] = -1;
2539
attachment_remap.push_back(attachments.size());
2540
attachments.push_back(description);
2541
}
2542
2543
LocalVector<RDD::Subpass> subpasses;
2544
subpasses.resize(p_passes.size());
2545
LocalVector<RDD::SubpassDependency> subpass_dependencies;
2546
2547
for (int i = 0; i < p_passes.size(); i++) {
2548
const FramebufferPass *pass = &p_passes[i];
2549
RDD::Subpass &subpass = subpasses[i];
2550
2551
TextureSamples texture_samples = TEXTURE_SAMPLES_1;
2552
bool is_multisample_first = true;
2553
2554
for (int j = 0; j < pass->color_attachments.size(); j++) {
2555
int32_t attachment = pass->color_attachments[j];
2556
RDD::AttachmentReference reference;
2557
if (attachment == ATTACHMENT_UNUSED) {
2558
reference.attachment = RDD::AttachmentReference::UNUSED;
2559
reference.layout = RDD::TEXTURE_LAYOUT_UNDEFINED;
2560
} else {
2561
ERR_FAIL_INDEX_V_MSG(attachment, p_attachments.size(), RDD::RenderPassID(), "Invalid framebuffer format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), color attachment (" + itos(j) + ").");
2562
ERR_FAIL_COND_V_MSG(!(p_attachments[attachment].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT), RDD::RenderPassID(), "Invalid framebuffer format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), it's marked as depth, but it's not usable as color attachment.");
2563
ERR_FAIL_COND_V_MSG(attachment_last_pass[attachment] == i, RDD::RenderPassID(), "Invalid framebuffer format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), it already was used for something else before in this pass.");
2564
2565
if (is_multisample_first) {
2566
texture_samples = p_attachments[attachment].samples;
2567
is_multisample_first = false;
2568
} else {
2569
ERR_FAIL_COND_V_MSG(texture_samples != p_attachments[attachment].samples, RDD::RenderPassID(), "Invalid framebuffer format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), if an attachment is marked as multisample, all of them should be multisample and use the same number of samples.");
2570
}
2571
reference.attachment = attachment_remap[attachment];
2572
reference.layout = RDD::TEXTURE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
2573
attachment_last_pass[attachment] = i;
2574
}
2575
reference.aspect = RDD::TEXTURE_ASPECT_COLOR_BIT;
2576
subpass.color_references.push_back(reference);
2577
}
2578
2579
for (int j = 0; j < pass->input_attachments.size(); j++) {
2580
int32_t attachment = pass->input_attachments[j];
2581
RDD::AttachmentReference reference;
2582
if (attachment == ATTACHMENT_UNUSED) {
2583
reference.attachment = RDD::AttachmentReference::UNUSED;
2584
reference.layout = RDD::TEXTURE_LAYOUT_UNDEFINED;
2585
} else {
2586
ERR_FAIL_INDEX_V_MSG(attachment, p_attachments.size(), RDD::RenderPassID(), "Invalid framebuffer format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), input attachment (" + itos(j) + ").");
2587
ERR_FAIL_COND_V_MSG(!(p_attachments[attachment].usage_flags & TEXTURE_USAGE_INPUT_ATTACHMENT_BIT), RDD::RenderPassID(), "Invalid framebuffer format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), it isn't marked as an input texture.");
2588
ERR_FAIL_COND_V_MSG(attachment_last_pass[attachment] == i, RDD::RenderPassID(), "Invalid framebuffer format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), it already was used for something else before in this pass.");
2589
reference.attachment = attachment_remap[attachment];
2590
reference.layout = RDD::TEXTURE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
2591
attachment_last_pass[attachment] = i;
2592
}
2593
reference.aspect = RDD::TEXTURE_ASPECT_COLOR_BIT;
2594
subpass.input_references.push_back(reference);
2595
}
2596
2597
if (pass->resolve_attachments.size() > 0) {
2598
ERR_FAIL_COND_V_MSG(pass->resolve_attachments.size() != pass->color_attachments.size(), RDD::RenderPassID(), "The amount of resolve attachments (" + itos(pass->resolve_attachments.size()) + ") must match the number of color attachments (" + itos(pass->color_attachments.size()) + ").");
2599
ERR_FAIL_COND_V_MSG(texture_samples == TEXTURE_SAMPLES_1, RDD::RenderPassID(), "Resolve attachments specified, but color attachments are not multisample.");
2600
}
2601
for (int j = 0; j < pass->resolve_attachments.size(); j++) {
2602
int32_t attachment = pass->resolve_attachments[j];
2603
attachments[attachment].load_op = RDD::ATTACHMENT_LOAD_OP_DONT_CARE;
2604
2605
RDD::AttachmentReference reference;
2606
if (attachment == ATTACHMENT_UNUSED) {
2607
reference.attachment = RDD::AttachmentReference::UNUSED;
2608
reference.layout = RDD::TEXTURE_LAYOUT_UNDEFINED;
2609
} else {
2610
ERR_FAIL_INDEX_V_MSG(attachment, p_attachments.size(), RDD::RenderPassID(), "Invalid framebuffer format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), resolve attachment (" + itos(j) + ").");
2611
ERR_FAIL_COND_V_MSG(pass->color_attachments[j] == ATTACHMENT_UNUSED, RDD::RenderPassID(), "Invalid framebuffer format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), resolve attachment (" + itos(j) + "), the respective color attachment is marked as unused.");
2612
ERR_FAIL_COND_V_MSG(!(p_attachments[attachment].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT), RDD::RenderPassID(), "Invalid framebuffer format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), resolve attachment, it isn't marked as a color texture.");
2613
ERR_FAIL_COND_V_MSG(attachment_last_pass[attachment] == i, RDD::RenderPassID(), "Invalid framebuffer format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), it already was used for something else before in this pass.");
2614
bool multisample = p_attachments[attachment].samples > TEXTURE_SAMPLES_1;
2615
ERR_FAIL_COND_V_MSG(multisample, RDD::RenderPassID(), "Invalid framebuffer format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), resolve attachments can't be multisample.");
2616
reference.attachment = attachment_remap[attachment];
2617
reference.layout = RDD::TEXTURE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; // RDD::TEXTURE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
2618
attachment_last_pass[attachment] = i;
2619
}
2620
reference.aspect = RDD::TEXTURE_ASPECT_COLOR_BIT;
2621
subpass.resolve_references.push_back(reference);
2622
}
2623
2624
if (pass->depth_attachment != ATTACHMENT_UNUSED) {
2625
int32_t attachment = pass->depth_attachment;
2626
ERR_FAIL_INDEX_V_MSG(attachment, p_attachments.size(), RDD::RenderPassID(), "Invalid framebuffer depth format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), depth attachment.");
2627
ERR_FAIL_COND_V_MSG(!(p_attachments[attachment].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT), RDD::RenderPassID(), "Invalid framebuffer depth format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), it's marked as depth, but it's not a depth attachment.");
2628
ERR_FAIL_COND_V_MSG(attachment_last_pass[attachment] == i, RDD::RenderPassID(), "Invalid framebuffer depth format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), it already was used for something else before in this pass.");
2629
subpass.depth_stencil_reference.attachment = attachment_remap[attachment];
2630
subpass.depth_stencil_reference.layout = RDD::TEXTURE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
2631
attachment_last_pass[attachment] = i;
2632
2633
if (is_multisample_first) {
2634
texture_samples = p_attachments[attachment].samples;
2635
is_multisample_first = false;
2636
} else {
2637
ERR_FAIL_COND_V_MSG(texture_samples != p_attachments[attachment].samples, RDD::RenderPassID(), "Invalid framebuffer depth format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), if an attachment is marked as multisample, all of them should be multisample and use the same number of samples including the depth.");
2638
}
2639
2640
} else {
2641
subpass.depth_stencil_reference.attachment = RDD::AttachmentReference::UNUSED;
2642
subpass.depth_stencil_reference.layout = RDD::TEXTURE_LAYOUT_UNDEFINED;
2643
}
2644
2645
if (p_vrs_method == VRS_METHOD_FRAGMENT_SHADING_RATE && p_vrs_attachment >= 0) {
2646
int32_t attachment = p_vrs_attachment;
2647
ERR_FAIL_INDEX_V_MSG(attachment, p_attachments.size(), RDD::RenderPassID(), "Invalid framebuffer VRS format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), VRS attachment.");
2648
ERR_FAIL_COND_V_MSG(!(p_attachments[attachment].usage_flags & TEXTURE_USAGE_VRS_ATTACHMENT_BIT), RDD::RenderPassID(), "Invalid framebuffer VRS format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), it's marked as VRS, but it's not a VRS attachment.");
2649
ERR_FAIL_COND_V_MSG(attachment_last_pass[attachment] == i, RDD::RenderPassID(), "Invalid framebuffer VRS attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), it already was used for something else before in this pass.");
2650
2651
subpass.fragment_shading_rate_reference.attachment = attachment_remap[attachment];
2652
subpass.fragment_shading_rate_reference.layout = RDD::TEXTURE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL;
2653
subpass.fragment_shading_rate_texel_size = p_vrs_texel_size;
2654
2655
attachment_last_pass[attachment] = i;
2656
}
2657
2658
for (int j = 0; j < pass->preserve_attachments.size(); j++) {
2659
int32_t attachment = pass->preserve_attachments[j];
2660
2661
ERR_FAIL_COND_V_MSG(attachment == ATTACHMENT_UNUSED, RDD::RenderPassID(), "Invalid framebuffer format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), preserve attachment (" + itos(j) + "). Preserve attachments can't be unused.");
2662
2663
ERR_FAIL_INDEX_V_MSG(attachment, p_attachments.size(), RDD::RenderPassID(), "Invalid framebuffer format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), preserve attachment (" + itos(j) + ").");
2664
2665
if (attachment_last_pass[attachment] != i) {
2666
// Preserve can still be used to keep depth or color from being discarded after use.
2667
attachment_last_pass[attachment] = i;
2668
subpasses[i].preserve_attachments.push_back(attachment);
2669
}
2670
}
2671
2672
if (r_samples) {
2673
r_samples->push_back(texture_samples);
2674
}
2675
2676
if (i > 0) {
2677
RDD::SubpassDependency dependency;
2678
dependency.src_subpass = i - 1;
2679
dependency.dst_subpass = i;
2680
dependency.src_stages = (RDD::PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | RDD::PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | RDD::PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
2681
dependency.dst_stages = (RDD::PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | RDD::PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | RDD::PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | RDD::PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
2682
dependency.src_access = (RDD::BARRIER_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | RDD::BARRIER_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT);
2683
dependency.dst_access = (RDD::BARRIER_ACCESS_COLOR_ATTACHMENT_READ_BIT | RDD::BARRIER_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | RDD::BARRIER_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | RDD::BARRIER_ACCESS_INPUT_ATTACHMENT_READ_BIT);
2684
subpass_dependencies.push_back(dependency);
2685
}
2686
}
2687
2688
RDD::AttachmentReference fragment_density_map_attachment_reference;
2689
if (p_vrs_method == VRS_METHOD_FRAGMENT_DENSITY_MAP && p_vrs_attachment >= 0) {
2690
fragment_density_map_attachment_reference.attachment = p_vrs_attachment;
2691
fragment_density_map_attachment_reference.layout = RDD::TEXTURE_LAYOUT_FRAGMENT_DENSITY_MAP_ATTACHMENT_OPTIMAL;
2692
}
2693
2694
RDD::RenderPassID render_pass = p_driver->render_pass_create(attachments, subpasses, subpass_dependencies, p_view_count, fragment_density_map_attachment_reference);
2695
ERR_FAIL_COND_V(!render_pass, RDD::RenderPassID());
2696
2697
return render_pass;
2698
}
2699
2700
RDD::RenderPassID RenderingDevice::_render_pass_create_from_graph(RenderingDeviceDriver *p_driver, VectorView<RDD::AttachmentLoadOp> p_load_ops, VectorView<RDD::AttachmentStoreOp> p_store_ops, void *p_user_data) {
2701
DEV_ASSERT(p_driver != nullptr);
2702
DEV_ASSERT(p_user_data != nullptr);
2703
2704
// The graph delegates the creation of the render pass to the user according to the load and store ops that were determined as necessary after
2705
// resolving the dependencies between commands. This function creates a render pass for the framebuffer accordingly.
2706
Framebuffer *framebuffer = (Framebuffer *)(p_user_data);
2707
const FramebufferFormatKey &key = framebuffer->rendering_device->framebuffer_formats[framebuffer->format_id].E->key();
2708
return _render_pass_create(p_driver, key.attachments, key.passes, p_load_ops, p_store_ops, framebuffer->view_count, key.vrs_method, key.vrs_attachment, key.vrs_texel_size);
2709
}
2710
2711
RDG::ResourceUsage RenderingDevice::_vrs_usage_from_method(VRSMethod p_method) {
2712
switch (p_method) {
2713
case VRS_METHOD_FRAGMENT_SHADING_RATE:
2714
return RDG::RESOURCE_USAGE_ATTACHMENT_FRAGMENT_SHADING_RATE_READ;
2715
case VRS_METHOD_FRAGMENT_DENSITY_MAP:
2716
return RDG::RESOURCE_USAGE_ATTACHMENT_FRAGMENT_DENSITY_MAP_READ;
2717
default:
2718
return RDG::RESOURCE_USAGE_NONE;
2719
}
2720
}
2721
2722
RDD::PipelineStageBits RenderingDevice::_vrs_stages_from_method(VRSMethod p_method) {
2723
switch (p_method) {
2724
case VRS_METHOD_FRAGMENT_SHADING_RATE:
2725
return RDD::PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT;
2726
case VRS_METHOD_FRAGMENT_DENSITY_MAP:
2727
return RDD::PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT;
2728
default:
2729
return RDD::PipelineStageBits(0);
2730
}
2731
}
2732
2733
RDD::TextureLayout RenderingDevice::_vrs_layout_from_method(VRSMethod p_method) {
2734
switch (p_method) {
2735
case VRS_METHOD_FRAGMENT_SHADING_RATE:
2736
return RDD::TEXTURE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL;
2737
case VRS_METHOD_FRAGMENT_DENSITY_MAP:
2738
return RDD::TEXTURE_LAYOUT_FRAGMENT_DENSITY_MAP_ATTACHMENT_OPTIMAL;
2739
default:
2740
return RDD::TEXTURE_LAYOUT_UNDEFINED;
2741
}
2742
}
2743
2744
void RenderingDevice::_vrs_detect_method() {
2745
const RDD::FragmentShadingRateCapabilities &fsr_capabilities = driver->get_fragment_shading_rate_capabilities();
2746
const RDD::FragmentDensityMapCapabilities &fdm_capabilities = driver->get_fragment_density_map_capabilities();
2747
if (fsr_capabilities.attachment_supported) {
2748
vrs_method = VRS_METHOD_FRAGMENT_SHADING_RATE;
2749
} else if (fdm_capabilities.attachment_supported) {
2750
vrs_method = VRS_METHOD_FRAGMENT_DENSITY_MAP;
2751
}
2752
2753
switch (vrs_method) {
2754
case VRS_METHOD_FRAGMENT_SHADING_RATE:
2755
vrs_format = DATA_FORMAT_R8_UINT;
2756
vrs_texel_size = Vector2i(16, 16).clamp(fsr_capabilities.min_texel_size, fsr_capabilities.max_texel_size);
2757
break;
2758
case VRS_METHOD_FRAGMENT_DENSITY_MAP:
2759
vrs_format = DATA_FORMAT_R8G8_UNORM;
2760
vrs_texel_size = Vector2i(32, 32).clamp(fdm_capabilities.min_texel_size, fdm_capabilities.max_texel_size);
2761
break;
2762
default:
2763
break;
2764
}
2765
}
2766
2767
RD::VRSMethod RenderingDevice::vrs_get_method() const {
2768
return vrs_method;
2769
}
2770
2771
RD::DataFormat RenderingDevice::vrs_get_format() const {
2772
return vrs_format;
2773
}
2774
2775
Size2i RenderingDevice::vrs_get_texel_size() const {
2776
return vrs_texel_size;
2777
}
2778
2779
RenderingDevice::FramebufferFormatID RenderingDevice::framebuffer_format_create(const Vector<AttachmentFormat> &p_format, uint32_t p_view_count, int32_t p_fragment_density_map_attachment) {
2780
FramebufferPass pass;
2781
for (int i = 0; i < p_format.size(); i++) {
2782
if (p_format[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
2783
pass.depth_attachment = i;
2784
} else {
2785
pass.color_attachments.push_back(i);
2786
}
2787
}
2788
2789
Vector<FramebufferPass> passes;
2790
passes.push_back(pass);
2791
return framebuffer_format_create_multipass(p_format, passes, p_view_count, p_fragment_density_map_attachment);
2792
}
2793
2794
RenderingDevice::FramebufferFormatID RenderingDevice::framebuffer_format_create_multipass(const Vector<AttachmentFormat> &p_attachments, const Vector<FramebufferPass> &p_passes, uint32_t p_view_count, int32_t p_vrs_attachment) {
2795
_THREAD_SAFE_METHOD_
2796
2797
FramebufferFormatKey key;
2798
key.attachments = p_attachments;
2799
key.passes = p_passes;
2800
key.view_count = p_view_count;
2801
key.vrs_method = vrs_method;
2802
key.vrs_attachment = p_vrs_attachment;
2803
key.vrs_texel_size = vrs_texel_size;
2804
2805
const RBMap<FramebufferFormatKey, FramebufferFormatID>::Element *E = framebuffer_format_cache.find(key);
2806
if (E) {
2807
// Exists, return.
2808
return E->get();
2809
}
2810
2811
Vector<TextureSamples> samples;
2812
LocalVector<RDD::AttachmentLoadOp> load_ops;
2813
LocalVector<RDD::AttachmentStoreOp> store_ops;
2814
for (int64_t i = 0; i < p_attachments.size(); i++) {
2815
load_ops.push_back(RDD::ATTACHMENT_LOAD_OP_CLEAR);
2816
store_ops.push_back(RDD::ATTACHMENT_STORE_OP_STORE);
2817
}
2818
2819
RDD::RenderPassID render_pass = _render_pass_create(driver, p_attachments, p_passes, load_ops, store_ops, p_view_count, vrs_method, p_vrs_attachment, vrs_texel_size, &samples); // Actions don't matter for this use case.
2820
if (!render_pass) { // Was likely invalid.
2821
return INVALID_ID;
2822
}
2823
2824
FramebufferFormatID id = FramebufferFormatID(framebuffer_format_cache.size()) | (FramebufferFormatID(ID_TYPE_FRAMEBUFFER_FORMAT) << FramebufferFormatID(ID_BASE_SHIFT));
2825
E = framebuffer_format_cache.insert(key, id);
2826
2827
FramebufferFormat fb_format;
2828
fb_format.E = E;
2829
fb_format.render_pass = render_pass;
2830
fb_format.pass_samples = samples;
2831
fb_format.view_count = p_view_count;
2832
framebuffer_formats[id] = fb_format;
2833
2834
#if PRINT_FRAMEBUFFER_FORMAT
2835
print_line("FRAMEBUFFER FORMAT:", id, "ATTACHMENTS:", p_attachments.size(), "PASSES:", p_passes.size());
2836
for (RD::AttachmentFormat attachment : p_attachments) {
2837
print_line("FORMAT:", attachment.format, "SAMPLES:", attachment.samples, "USAGE FLAGS:", attachment.usage_flags);
2838
}
2839
#endif
2840
2841
return id;
2842
}
2843
2844
RenderingDevice::FramebufferFormatID RenderingDevice::framebuffer_format_create_empty(TextureSamples p_samples) {
2845
_THREAD_SAFE_METHOD_
2846
2847
FramebufferFormatKey key;
2848
key.passes.push_back(FramebufferPass());
2849
2850
const RBMap<FramebufferFormatKey, FramebufferFormatID>::Element *E = framebuffer_format_cache.find(key);
2851
if (E) {
2852
// Exists, return.
2853
return E->get();
2854
}
2855
2856
LocalVector<RDD::Subpass> subpass;
2857
subpass.resize(1);
2858
2859
RDD::RenderPassID render_pass = driver->render_pass_create({}, subpass, {}, 1, RDD::AttachmentReference());
2860
ERR_FAIL_COND_V(!render_pass, FramebufferFormatID());
2861
2862
FramebufferFormatID id = FramebufferFormatID(framebuffer_format_cache.size()) | (FramebufferFormatID(ID_TYPE_FRAMEBUFFER_FORMAT) << FramebufferFormatID(ID_BASE_SHIFT));
2863
2864
E = framebuffer_format_cache.insert(key, id);
2865
2866
FramebufferFormat fb_format;
2867
fb_format.E = E;
2868
fb_format.render_pass = render_pass;
2869
fb_format.pass_samples.push_back(p_samples);
2870
framebuffer_formats[id] = fb_format;
2871
2872
#if PRINT_FRAMEBUFFER_FORMAT
2873
print_line("FRAMEBUFFER FORMAT:", id, "ATTACHMENTS: EMPTY");
2874
#endif
2875
2876
return id;
2877
}
2878
2879
RenderingDevice::TextureSamples RenderingDevice::framebuffer_format_get_texture_samples(FramebufferFormatID p_format, uint32_t p_pass) {
2880
_THREAD_SAFE_METHOD_
2881
2882
HashMap<FramebufferFormatID, FramebufferFormat>::Iterator E = framebuffer_formats.find(p_format);
2883
ERR_FAIL_COND_V(!E, TEXTURE_SAMPLES_1);
2884
ERR_FAIL_COND_V(p_pass >= uint32_t(E->value.pass_samples.size()), TEXTURE_SAMPLES_1);
2885
2886
return E->value.pass_samples[p_pass];
2887
}
2888
2889
RID RenderingDevice::framebuffer_create_empty(const Size2i &p_size, TextureSamples p_samples, FramebufferFormatID p_format_check) {
2890
_THREAD_SAFE_METHOD_
2891
2892
Framebuffer framebuffer;
2893
framebuffer.rendering_device = this;
2894
framebuffer.format_id = framebuffer_format_create_empty(p_samples);
2895
ERR_FAIL_COND_V(p_format_check != INVALID_FORMAT_ID && framebuffer.format_id != p_format_check, RID());
2896
framebuffer.size = p_size;
2897
framebuffer.view_count = 1;
2898
2899
RDG::FramebufferCache *framebuffer_cache = RDG::framebuffer_cache_create();
2900
framebuffer_cache->width = p_size.width;
2901
framebuffer_cache->height = p_size.height;
2902
framebuffer.framebuffer_cache = framebuffer_cache;
2903
2904
RID id = framebuffer_owner.make_rid(framebuffer);
2905
#ifdef DEV_ENABLED
2906
set_resource_name(id, "RID:" + itos(id.get_id()));
2907
#endif
2908
2909
framebuffer_cache->render_pass_creation_user_data = framebuffer_owner.get_or_null(id);
2910
2911
return id;
2912
}
2913
2914
RID RenderingDevice::framebuffer_create(const Vector<RID> &p_texture_attachments, FramebufferFormatID p_format_check, uint32_t p_view_count) {
2915
_THREAD_SAFE_METHOD_
2916
2917
FramebufferPass pass;
2918
2919
for (int i = 0; i < p_texture_attachments.size(); i++) {
2920
Texture *texture = texture_owner.get_or_null(p_texture_attachments[i]);
2921
2922
ERR_FAIL_COND_V_MSG(texture && texture->layers != p_view_count, RID(), "Layers of our texture doesn't match view count for this framebuffer");
2923
2924
if (texture != nullptr) {
2925
_check_transfer_worker_texture(texture);
2926
}
2927
2928
if (texture && texture->usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
2929
pass.depth_attachment = i;
2930
} else if (texture && texture->usage_flags & TEXTURE_USAGE_VRS_ATTACHMENT_BIT) {
2931
// Prevent the VRS attachment from being added to the color_attachments.
2932
} else {
2933
if (texture && texture->is_resolve_buffer) {
2934
pass.resolve_attachments.push_back(i);
2935
} else {
2936
pass.color_attachments.push_back(texture ? i : ATTACHMENT_UNUSED);
2937
}
2938
}
2939
}
2940
2941
Vector<FramebufferPass> passes;
2942
passes.push_back(pass);
2943
2944
return framebuffer_create_multipass(p_texture_attachments, passes, p_format_check, p_view_count);
2945
}
2946
2947
RID RenderingDevice::framebuffer_create_multipass(const Vector<RID> &p_texture_attachments, const Vector<FramebufferPass> &p_passes, FramebufferFormatID p_format_check, uint32_t p_view_count) {
2948
_THREAD_SAFE_METHOD_
2949
2950
Vector<AttachmentFormat> attachments;
2951
LocalVector<RDD::TextureID> textures;
2952
LocalVector<RDG::ResourceTracker *> trackers;
2953
int32_t vrs_attachment = -1;
2954
attachments.resize(p_texture_attachments.size());
2955
Size2i size;
2956
bool size_set = false;
2957
for (int i = 0; i < p_texture_attachments.size(); i++) {
2958
AttachmentFormat af;
2959
Texture *texture = texture_owner.get_or_null(p_texture_attachments[i]);
2960
if (!texture) {
2961
af.usage_flags = AttachmentFormat::UNUSED_ATTACHMENT;
2962
trackers.push_back(nullptr);
2963
} else {
2964
ERR_FAIL_COND_V_MSG(texture->layers != p_view_count, RID(), "Layers of our texture doesn't match view count for this framebuffer");
2965
2966
_check_transfer_worker_texture(texture);
2967
2968
if (i != 0 && texture->usage_flags & TEXTURE_USAGE_VRS_ATTACHMENT_BIT) {
2969
// Detect if the texture is the fragment density map and it's not the first attachment.
2970
vrs_attachment = i;
2971
}
2972
2973
if (!size_set) {
2974
size.width = texture->width;
2975
size.height = texture->height;
2976
size_set = true;
2977
} else if (texture->usage_flags & TEXTURE_USAGE_VRS_ATTACHMENT_BIT) {
2978
// If this is not the first attachment we assume this is used as the VRS attachment.
2979
// In this case this texture will be 1/16th the size of the color attachment.
2980
// So we skip the size check.
2981
} else {
2982
ERR_FAIL_COND_V_MSG((uint32_t)size.width != texture->width || (uint32_t)size.height != texture->height, RID(),
2983
"All textures in a framebuffer should be the same size.");
2984
}
2985
2986
af.format = texture->format;
2987
af.samples = texture->samples;
2988
af.usage_flags = texture->usage_flags;
2989
2990
_texture_make_mutable(texture, p_texture_attachments[i]);
2991
2992
textures.push_back(texture->driver_id);
2993
trackers.push_back(texture->draw_tracker);
2994
}
2995
attachments.write[i] = af;
2996
}
2997
2998
ERR_FAIL_COND_V_MSG(!size_set, RID(), "All attachments unused.");
2999
3000
FramebufferFormatID format_id = framebuffer_format_create_multipass(attachments, p_passes, p_view_count, vrs_attachment);
3001
if (format_id == INVALID_ID) {
3002
return RID();
3003
}
3004
3005
ERR_FAIL_COND_V_MSG(p_format_check != INVALID_ID && format_id != p_format_check, RID(),
3006
"The format used to check this framebuffer differs from the intended framebuffer format.");
3007
3008
Framebuffer framebuffer;
3009
framebuffer.rendering_device = this;
3010
framebuffer.format_id = format_id;
3011
framebuffer.texture_ids = p_texture_attachments;
3012
framebuffer.size = size;
3013
framebuffer.view_count = p_view_count;
3014
3015
RDG::FramebufferCache *framebuffer_cache = RDG::framebuffer_cache_create();
3016
framebuffer_cache->width = size.width;
3017
framebuffer_cache->height = size.height;
3018
framebuffer_cache->textures = textures;
3019
framebuffer_cache->trackers = trackers;
3020
framebuffer.framebuffer_cache = framebuffer_cache;
3021
3022
RID id = framebuffer_owner.make_rid(framebuffer);
3023
#ifdef DEV_ENABLED
3024
set_resource_name(id, "RID:" + itos(id.get_id()));
3025
#endif
3026
3027
for (int i = 0; i < p_texture_attachments.size(); i++) {
3028
if (p_texture_attachments[i].is_valid()) {
3029
_add_dependency(id, p_texture_attachments[i]);
3030
}
3031
}
3032
3033
framebuffer_cache->render_pass_creation_user_data = framebuffer_owner.get_or_null(id);
3034
3035
return id;
3036
}
3037
3038
RenderingDevice::FramebufferFormatID RenderingDevice::framebuffer_get_format(RID p_framebuffer) {
3039
_THREAD_SAFE_METHOD_
3040
3041
Framebuffer *framebuffer = framebuffer_owner.get_or_null(p_framebuffer);
3042
ERR_FAIL_NULL_V(framebuffer, INVALID_ID);
3043
3044
return framebuffer->format_id;
3045
}
3046
3047
Size2 RenderingDevice::framebuffer_get_size(RID p_framebuffer) {
3048
_THREAD_SAFE_METHOD_
3049
3050
Framebuffer *framebuffer = framebuffer_owner.get_or_null(p_framebuffer);
3051
ERR_FAIL_NULL_V(framebuffer, Size2(0, 0));
3052
3053
return framebuffer->size;
3054
}
3055
3056
bool RenderingDevice::framebuffer_is_valid(RID p_framebuffer) const {
3057
_THREAD_SAFE_METHOD_
3058
3059
return framebuffer_owner.owns(p_framebuffer);
3060
}
3061
3062
void RenderingDevice::framebuffer_set_invalidation_callback(RID p_framebuffer, InvalidationCallback p_callback, void *p_userdata) {
3063
_THREAD_SAFE_METHOD_
3064
3065
Framebuffer *framebuffer = framebuffer_owner.get_or_null(p_framebuffer);
3066
ERR_FAIL_NULL(framebuffer);
3067
3068
framebuffer->invalidated_callback = p_callback;
3069
framebuffer->invalidated_callback_userdata = p_userdata;
3070
}
3071
3072
/*****************/
3073
/**** SAMPLER ****/
3074
/*****************/
3075
3076
RID RenderingDevice::sampler_create(const SamplerState &p_state) {
3077
_THREAD_SAFE_METHOD_
3078
3079
ERR_FAIL_INDEX_V(p_state.repeat_u, SAMPLER_REPEAT_MODE_MAX, RID());
3080
ERR_FAIL_INDEX_V(p_state.repeat_v, SAMPLER_REPEAT_MODE_MAX, RID());
3081
ERR_FAIL_INDEX_V(p_state.repeat_w, SAMPLER_REPEAT_MODE_MAX, RID());
3082
ERR_FAIL_INDEX_V(p_state.compare_op, COMPARE_OP_MAX, RID());
3083
ERR_FAIL_INDEX_V(p_state.border_color, SAMPLER_BORDER_COLOR_MAX, RID());
3084
3085
RDD::SamplerID sampler = driver->sampler_create(p_state);
3086
ERR_FAIL_COND_V(!sampler, RID());
3087
3088
RID id = sampler_owner.make_rid(sampler);
3089
#ifdef DEV_ENABLED
3090
set_resource_name(id, "RID:" + itos(id.get_id()));
3091
#endif
3092
return id;
3093
}
3094
3095
bool RenderingDevice::sampler_is_format_supported_for_filter(DataFormat p_format, SamplerFilter p_sampler_filter) const {
3096
_THREAD_SAFE_METHOD_
3097
3098
ERR_FAIL_INDEX_V(p_format, DATA_FORMAT_MAX, false);
3099
3100
return driver->sampler_is_format_supported_for_filter(p_format, p_sampler_filter);
3101
}
3102
3103
/***********************/
3104
/**** VERTEX BUFFER ****/
3105
/***********************/
3106
3107
RID RenderingDevice::vertex_buffer_create(uint32_t p_size_bytes, Span<uint8_t> p_data, BitField<BufferCreationBits> p_creation_bits) {
3108
ERR_FAIL_COND_V(p_data.size() && (uint32_t)p_data.size() != p_size_bytes, RID());
3109
3110
Buffer buffer;
3111
buffer.size = p_size_bytes;
3112
buffer.usage = RDD::BUFFER_USAGE_TRANSFER_FROM_BIT | RDD::BUFFER_USAGE_TRANSFER_TO_BIT | RDD::BUFFER_USAGE_VERTEX_BIT;
3113
if (p_creation_bits.has_flag(BUFFER_CREATION_AS_STORAGE_BIT)) {
3114
buffer.usage.set_flag(RDD::BUFFER_USAGE_STORAGE_BIT);
3115
}
3116
if (p_creation_bits.has_flag(BUFFER_CREATION_DEVICE_ADDRESS_BIT)) {
3117
buffer.usage.set_flag(RDD::BUFFER_USAGE_DEVICE_ADDRESS_BIT);
3118
}
3119
buffer.driver_id = driver->buffer_create(buffer.size, buffer.usage, RDD::MEMORY_ALLOCATION_TYPE_GPU);
3120
ERR_FAIL_COND_V(!buffer.driver_id, RID());
3121
3122
// Vertex buffers are assumed to be immutable unless they don't have initial data or they've been marked for storage explicitly.
3123
if (p_data.is_empty() || p_creation_bits.has_flag(BUFFER_CREATION_AS_STORAGE_BIT)) {
3124
buffer.draw_tracker = RDG::resource_tracker_create();
3125
buffer.draw_tracker->buffer_driver_id = buffer.driver_id;
3126
}
3127
3128
if (p_data.size()) {
3129
_buffer_initialize(&buffer, p_data);
3130
}
3131
3132
_THREAD_SAFE_LOCK_
3133
buffer_memory += buffer.size;
3134
_THREAD_SAFE_UNLOCK_
3135
3136
RID id = vertex_buffer_owner.make_rid(buffer);
3137
#ifdef DEV_ENABLED
3138
set_resource_name(id, "RID:" + itos(id.get_id()));
3139
#endif
3140
return id;
3141
}
3142
3143
// Internally reference counted, this ID is warranted to be unique for the same description, but needs to be freed as many times as it was allocated.
3144
RenderingDevice::VertexFormatID RenderingDevice::vertex_format_create(const Vector<VertexAttribute> &p_vertex_descriptions) {
3145
_THREAD_SAFE_METHOD_
3146
3147
VertexDescriptionKey key;
3148
key.vertex_formats = p_vertex_descriptions;
3149
3150
VertexFormatID *idptr = vertex_format_cache.getptr(key);
3151
if (idptr) {
3152
return *idptr;
3153
}
3154
3155
HashSet<int> used_locations;
3156
for (int i = 0; i < p_vertex_descriptions.size(); i++) {
3157
ERR_CONTINUE(p_vertex_descriptions[i].format >= DATA_FORMAT_MAX);
3158
ERR_FAIL_COND_V(used_locations.has(p_vertex_descriptions[i].location), INVALID_ID);
3159
3160
ERR_FAIL_COND_V_MSG(get_format_vertex_size(p_vertex_descriptions[i].format) == 0, INVALID_ID,
3161
"Data format for attachment (" + itos(i) + "), '" + FORMAT_NAMES[p_vertex_descriptions[i].format] + "', is not valid for a vertex array.");
3162
3163
used_locations.insert(p_vertex_descriptions[i].location);
3164
}
3165
3166
RDD::VertexFormatID driver_id = driver->vertex_format_create(p_vertex_descriptions);
3167
ERR_FAIL_COND_V(!driver_id, 0);
3168
3169
VertexFormatID id = (vertex_format_cache.size() | ((int64_t)ID_TYPE_VERTEX_FORMAT << ID_BASE_SHIFT));
3170
vertex_format_cache[key] = id;
3171
vertex_formats[id].vertex_formats = p_vertex_descriptions;
3172
vertex_formats[id].driver_id = driver_id;
3173
return id;
3174
}
3175
3176
RID RenderingDevice::vertex_array_create(uint32_t p_vertex_count, VertexFormatID p_vertex_format, const Vector<RID> &p_src_buffers, const Vector<uint64_t> &p_offsets) {
3177
_THREAD_SAFE_METHOD_
3178
3179
ERR_FAIL_COND_V(!vertex_formats.has(p_vertex_format), RID());
3180
const VertexDescriptionCache &vd = vertex_formats[p_vertex_format];
3181
3182
ERR_FAIL_COND_V(vd.vertex_formats.size() != p_src_buffers.size(), RID());
3183
3184
for (int i = 0; i < p_src_buffers.size(); i++) {
3185
ERR_FAIL_COND_V(!vertex_buffer_owner.owns(p_src_buffers[i]), RID());
3186
}
3187
3188
VertexArray vertex_array;
3189
3190
if (p_offsets.is_empty()) {
3191
vertex_array.offsets.resize_initialized(p_src_buffers.size());
3192
} else {
3193
ERR_FAIL_COND_V(p_offsets.size() != p_src_buffers.size(), RID());
3194
vertex_array.offsets = p_offsets;
3195
}
3196
3197
vertex_array.vertex_count = p_vertex_count;
3198
vertex_array.description = p_vertex_format;
3199
vertex_array.max_instances_allowed = 0xFFFFFFFF; // By default as many as you want.
3200
for (int i = 0; i < p_src_buffers.size(); i++) {
3201
Buffer *buffer = vertex_buffer_owner.get_or_null(p_src_buffers[i]);
3202
3203
// Validate with buffer.
3204
{
3205
const VertexAttribute &atf = vd.vertex_formats[i];
3206
3207
uint32_t element_size = get_format_vertex_size(atf.format);
3208
ERR_FAIL_COND_V(element_size == 0, RID()); // Should never happens since this was prevalidated.
3209
3210
if (atf.frequency == VERTEX_FREQUENCY_VERTEX) {
3211
// Validate size for regular drawing.
3212
uint64_t total_size = uint64_t(atf.stride) * (p_vertex_count - 1) + atf.offset + element_size;
3213
ERR_FAIL_COND_V_MSG(total_size > buffer->size, RID(),
3214
"Attachment (" + itos(i) + ") will read past the end of the buffer.");
3215
3216
} else {
3217
// Validate size for instances drawing.
3218
uint64_t available = buffer->size - atf.offset;
3219
ERR_FAIL_COND_V_MSG(available < element_size, RID(),
3220
"Attachment (" + itos(i) + ") uses instancing, but it's just too small.");
3221
3222
uint32_t instances_allowed = available / atf.stride;
3223
vertex_array.max_instances_allowed = MIN(instances_allowed, vertex_array.max_instances_allowed);
3224
}
3225
}
3226
3227
vertex_array.buffers.push_back(buffer->driver_id);
3228
3229
if (buffer->draw_tracker != nullptr) {
3230
vertex_array.draw_trackers.push_back(buffer->draw_tracker);
3231
} else {
3232
vertex_array.untracked_buffers.insert(p_src_buffers[i]);
3233
}
3234
3235
if (buffer->transfer_worker_index >= 0) {
3236
vertex_array.transfer_worker_indices.push_back(buffer->transfer_worker_index);
3237
vertex_array.transfer_worker_operations.push_back(buffer->transfer_worker_operation);
3238
}
3239
}
3240
3241
RID id = vertex_array_owner.make_rid(vertex_array);
3242
for (int i = 0; i < p_src_buffers.size(); i++) {
3243
_add_dependency(id, p_src_buffers[i]);
3244
}
3245
3246
return id;
3247
}
3248
3249
RID RenderingDevice::index_buffer_create(uint32_t p_index_count, IndexBufferFormat p_format, Span<uint8_t> p_data, bool p_use_restart_indices, BitField<BufferCreationBits> p_creation_bits) {
3250
ERR_FAIL_COND_V(p_index_count == 0, RID());
3251
3252
IndexBuffer index_buffer;
3253
index_buffer.format = p_format;
3254
index_buffer.supports_restart_indices = p_use_restart_indices;
3255
index_buffer.index_count = p_index_count;
3256
uint32_t size_bytes = p_index_count * ((p_format == INDEX_BUFFER_FORMAT_UINT16) ? 2 : 4);
3257
#ifdef DEBUG_ENABLED
3258
if (p_data.size()) {
3259
index_buffer.max_index = 0;
3260
ERR_FAIL_COND_V_MSG((uint32_t)p_data.size() != size_bytes, RID(),
3261
"Default index buffer initializer array size (" + itos(p_data.size()) + ") does not match format required size (" + itos(size_bytes) + ").");
3262
const uint8_t *r = p_data.ptr();
3263
if (p_format == INDEX_BUFFER_FORMAT_UINT16) {
3264
const uint16_t *index16 = (const uint16_t *)r;
3265
for (uint32_t i = 0; i < p_index_count; i++) {
3266
if (p_use_restart_indices && index16[i] == 0xFFFF) {
3267
continue; // Restart index, ignore.
3268
}
3269
index_buffer.max_index = MAX(index16[i], index_buffer.max_index);
3270
}
3271
} else {
3272
const uint32_t *index32 = (const uint32_t *)r;
3273
for (uint32_t i = 0; i < p_index_count; i++) {
3274
if (p_use_restart_indices && index32[i] == 0xFFFFFFFF) {
3275
continue; // Restart index, ignore.
3276
}
3277
index_buffer.max_index = MAX(index32[i], index_buffer.max_index);
3278
}
3279
}
3280
} else {
3281
index_buffer.max_index = 0xFFFFFFFF;
3282
}
3283
#else
3284
index_buffer.max_index = 0xFFFFFFFF;
3285
#endif
3286
index_buffer.size = size_bytes;
3287
index_buffer.usage = (RDD::BUFFER_USAGE_TRANSFER_FROM_BIT | RDD::BUFFER_USAGE_TRANSFER_TO_BIT | RDD::BUFFER_USAGE_INDEX_BIT);
3288
if (p_creation_bits.has_flag(BUFFER_CREATION_DEVICE_ADDRESS_BIT)) {
3289
index_buffer.usage.set_flag(RDD::BUFFER_USAGE_DEVICE_ADDRESS_BIT);
3290
}
3291
index_buffer.driver_id = driver->buffer_create(index_buffer.size, index_buffer.usage, RDD::MEMORY_ALLOCATION_TYPE_GPU);
3292
ERR_FAIL_COND_V(!index_buffer.driver_id, RID());
3293
3294
// Index buffers are assumed to be immutable unless they don't have initial data.
3295
if (p_data.is_empty()) {
3296
index_buffer.draw_tracker = RDG::resource_tracker_create();
3297
index_buffer.draw_tracker->buffer_driver_id = index_buffer.driver_id;
3298
}
3299
3300
if (p_data.size()) {
3301
_buffer_initialize(&index_buffer, p_data);
3302
}
3303
3304
_THREAD_SAFE_LOCK_
3305
buffer_memory += index_buffer.size;
3306
_THREAD_SAFE_UNLOCK_
3307
3308
RID id = index_buffer_owner.make_rid(index_buffer);
3309
#ifdef DEV_ENABLED
3310
set_resource_name(id, "RID:" + itos(id.get_id()));
3311
#endif
3312
return id;
3313
}
3314
3315
RID RenderingDevice::index_array_create(RID p_index_buffer, uint32_t p_index_offset, uint32_t p_index_count) {
3316
_THREAD_SAFE_METHOD_
3317
3318
ERR_FAIL_COND_V(!index_buffer_owner.owns(p_index_buffer), RID());
3319
3320
IndexBuffer *index_buffer = index_buffer_owner.get_or_null(p_index_buffer);
3321
3322
ERR_FAIL_COND_V(p_index_count == 0, RID());
3323
ERR_FAIL_COND_V(p_index_offset + p_index_count > index_buffer->index_count, RID());
3324
3325
IndexArray index_array;
3326
index_array.max_index = index_buffer->max_index;
3327
index_array.driver_id = index_buffer->driver_id;
3328
index_array.draw_tracker = index_buffer->draw_tracker;
3329
index_array.offset = p_index_offset;
3330
index_array.indices = p_index_count;
3331
index_array.format = index_buffer->format;
3332
index_array.supports_restart_indices = index_buffer->supports_restart_indices;
3333
index_array.transfer_worker_index = index_buffer->transfer_worker_index;
3334
index_array.transfer_worker_operation = index_buffer->transfer_worker_operation;
3335
3336
RID id = index_array_owner.make_rid(index_array);
3337
_add_dependency(id, p_index_buffer);
3338
return id;
3339
}
3340
3341
/****************/
3342
/**** SHADER ****/
3343
/****************/
3344
3345
static const char *SHADER_UNIFORM_NAMES[RenderingDevice::UNIFORM_TYPE_MAX] = {
3346
"Sampler", "CombinedSampler", "Texture", "Image", "TextureBuffer", "SamplerTextureBuffer", "ImageBuffer", "UniformBuffer", "StorageBuffer", "InputAttachment"
3347
};
3348
3349
String RenderingDevice::_shader_uniform_debug(RID p_shader, int p_set) {
3350
String ret;
3351
const Shader *shader = shader_owner.get_or_null(p_shader);
3352
ERR_FAIL_NULL_V(shader, String());
3353
for (int i = 0; i < shader->uniform_sets.size(); i++) {
3354
if (p_set >= 0 && i != p_set) {
3355
continue;
3356
}
3357
for (int j = 0; j < shader->uniform_sets[i].size(); j++) {
3358
const ShaderUniform &ui = shader->uniform_sets[i][j];
3359
if (!ret.is_empty()) {
3360
ret += "\n";
3361
}
3362
ret += "Set: " + itos(i) + " Binding: " + itos(ui.binding) + " Type: " + SHADER_UNIFORM_NAMES[ui.type] + " Writable: " + (ui.writable ? "Y" : "N") + " Length: " + itos(ui.length);
3363
}
3364
}
3365
return ret;
3366
}
3367
3368
Vector<uint8_t> RenderingDevice::shader_compile_binary_from_spirv(const Vector<ShaderStageSPIRVData> &p_spirv, const String &p_shader_name) {
3369
ShaderReflection shader_refl;
3370
if (reflect_spirv(p_spirv, shader_refl) != OK) {
3371
return Vector<uint8_t>();
3372
}
3373
3374
const RenderingShaderContainerFormat &container_format = driver->get_shader_container_format();
3375
Ref<RenderingShaderContainer> shader_container = container_format.create_container();
3376
ERR_FAIL_COND_V(shader_container.is_null(), Vector<uint8_t>());
3377
3378
shader_container->set_from_shader_reflection(p_shader_name, shader_refl);
3379
3380
// Compile shader binary from SPIR-V.
3381
bool code_compiled = shader_container->set_code_from_spirv(p_spirv);
3382
ERR_FAIL_COND_V_MSG(!code_compiled, Vector<uint8_t>(), vformat("Failed to compile code to native for SPIR-V."));
3383
3384
return shader_container->to_bytes();
3385
}
3386
3387
RID RenderingDevice::shader_create_from_bytecode(const Vector<uint8_t> &p_shader_binary, RID p_placeholder) {
3388
// Immutable samplers :
3389
// Expanding api when creating shader to allow passing optionally a set of immutable samplers
3390
// keeping existing api but extending it by sending an empty set.
3391
Vector<PipelineImmutableSampler> immutable_samplers;
3392
return shader_create_from_bytecode_with_samplers(p_shader_binary, p_placeholder, immutable_samplers);
3393
}
3394
3395
RID RenderingDevice::shader_create_from_bytecode_with_samplers(const Vector<uint8_t> &p_shader_binary, RID p_placeholder, const Vector<PipelineImmutableSampler> &p_immutable_samplers) {
3396
_THREAD_SAFE_METHOD_
3397
3398
Ref<RenderingShaderContainer> shader_container = driver->get_shader_container_format().create_container();
3399
ERR_FAIL_COND_V(shader_container.is_null(), RID());
3400
3401
bool parsed_container = shader_container->from_bytes(p_shader_binary);
3402
ERR_FAIL_COND_V_MSG(!parsed_container, RID(), "Failed to parse shader container from binary.");
3403
3404
Vector<RDD::ImmutableSampler> driver_immutable_samplers;
3405
for (const PipelineImmutableSampler &source_sampler : p_immutable_samplers) {
3406
RDD::ImmutableSampler driver_sampler;
3407
driver_sampler.type = source_sampler.uniform_type;
3408
driver_sampler.binding = source_sampler.binding;
3409
3410
for (uint32_t j = 0; j < source_sampler.get_id_count(); j++) {
3411
RDD::SamplerID *sampler_driver_id = sampler_owner.get_or_null(source_sampler.get_id(j));
3412
driver_sampler.ids.push_back(*sampler_driver_id);
3413
}
3414
3415
driver_immutable_samplers.append(driver_sampler);
3416
}
3417
3418
RDD::ShaderID shader_id = driver->shader_create_from_container(shader_container, driver_immutable_samplers);
3419
ERR_FAIL_COND_V(!shader_id, RID());
3420
3421
// All good, let's create modules.
3422
3423
RID id;
3424
if (p_placeholder.is_null()) {
3425
id = shader_owner.make_rid();
3426
} else {
3427
id = p_placeholder;
3428
}
3429
3430
Shader *shader = shader_owner.get_or_null(id);
3431
ERR_FAIL_NULL_V(shader, RID());
3432
3433
*((ShaderReflection *)shader) = shader_container->get_shader_reflection();
3434
shader->name.clear();
3435
shader->name.append_utf8(shader_container->shader_name);
3436
shader->driver_id = shader_id;
3437
shader->layout_hash = driver->shader_get_layout_hash(shader_id);
3438
3439
for (int i = 0; i < shader->uniform_sets.size(); i++) {
3440
uint32_t format = 0; // No format, default.
3441
3442
if (shader->uniform_sets[i].size()) {
3443
// Sort and hash.
3444
3445
shader->uniform_sets.write[i].sort();
3446
3447
UniformSetFormat usformat;
3448
usformat.uniforms = shader->uniform_sets[i];
3449
RBMap<UniformSetFormat, uint32_t>::Element *E = uniform_set_format_cache.find(usformat);
3450
if (E) {
3451
format = E->get();
3452
} else {
3453
format = uniform_set_format_cache.size() + 1;
3454
uniform_set_format_cache.insert(usformat, format);
3455
}
3456
}
3457
3458
shader->set_formats.push_back(format);
3459
}
3460
3461
for (ShaderStage stage : shader->stages_vector) {
3462
switch (stage) {
3463
case SHADER_STAGE_VERTEX:
3464
shader->stage_bits.set_flag(RDD::PIPELINE_STAGE_VERTEX_SHADER_BIT);
3465
break;
3466
case SHADER_STAGE_FRAGMENT:
3467
shader->stage_bits.set_flag(RDD::PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
3468
break;
3469
case SHADER_STAGE_TESSELATION_CONTROL:
3470
shader->stage_bits.set_flag(RDD::PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT);
3471
break;
3472
case SHADER_STAGE_TESSELATION_EVALUATION:
3473
shader->stage_bits.set_flag(RDD::PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT);
3474
break;
3475
case SHADER_STAGE_COMPUTE:
3476
shader->stage_bits.set_flag(RDD::PIPELINE_STAGE_COMPUTE_SHADER_BIT);
3477
break;
3478
default:
3479
DEV_ASSERT(false && "Unknown shader stage.");
3480
break;
3481
}
3482
}
3483
3484
#ifdef DEV_ENABLED
3485
set_resource_name(id, "RID:" + itos(id.get_id()));
3486
#endif
3487
return id;
3488
}
3489
3490
void RenderingDevice::shader_destroy_modules(RID p_shader) {
3491
Shader *shader = shader_owner.get_or_null(p_shader);
3492
ERR_FAIL_NULL(shader);
3493
driver->shader_destroy_modules(shader->driver_id);
3494
}
3495
3496
RID RenderingDevice::shader_create_placeholder() {
3497
_THREAD_SAFE_METHOD_
3498
3499
Shader shader;
3500
return shader_owner.make_rid(shader);
3501
}
3502
3503
uint64_t RenderingDevice::shader_get_vertex_input_attribute_mask(RID p_shader) {
3504
_THREAD_SAFE_METHOD_
3505
3506
const Shader *shader = shader_owner.get_or_null(p_shader);
3507
ERR_FAIL_NULL_V(shader, 0);
3508
return shader->vertex_input_mask;
3509
}
3510
3511
/******************/
3512
/**** UNIFORMS ****/
3513
/******************/
3514
3515
RID RenderingDevice::uniform_buffer_create(uint32_t p_size_bytes, Span<uint8_t> p_data, BitField<BufferCreationBits> p_creation_bits) {
3516
ERR_FAIL_COND_V(p_data.size() && (uint32_t)p_data.size() != p_size_bytes, RID());
3517
3518
Buffer buffer;
3519
buffer.size = p_size_bytes;
3520
buffer.usage = (RDD::BUFFER_USAGE_TRANSFER_TO_BIT | RDD::BUFFER_USAGE_UNIFORM_BIT);
3521
if (p_creation_bits.has_flag(BUFFER_CREATION_DEVICE_ADDRESS_BIT)) {
3522
buffer.usage.set_flag(RDD::BUFFER_USAGE_DEVICE_ADDRESS_BIT);
3523
}
3524
buffer.driver_id = driver->buffer_create(buffer.size, buffer.usage, RDD::MEMORY_ALLOCATION_TYPE_GPU);
3525
ERR_FAIL_COND_V(!buffer.driver_id, RID());
3526
3527
// Uniform buffers are assumed to be immutable unless they don't have initial data.
3528
if (p_data.is_empty()) {
3529
buffer.draw_tracker = RDG::resource_tracker_create();
3530
buffer.draw_tracker->buffer_driver_id = buffer.driver_id;
3531
}
3532
3533
if (p_data.size()) {
3534
_buffer_initialize(&buffer, p_data);
3535
}
3536
3537
_THREAD_SAFE_LOCK_
3538
buffer_memory += buffer.size;
3539
_THREAD_SAFE_UNLOCK_
3540
3541
RID id = uniform_buffer_owner.make_rid(buffer);
3542
#ifdef DEV_ENABLED
3543
set_resource_name(id, "RID:" + itos(id.get_id()));
3544
#endif
3545
return id;
3546
}
3547
3548
void RenderingDevice::_uniform_set_update_shared(UniformSet *p_uniform_set) {
3549
for (UniformSet::SharedTexture shared : p_uniform_set->shared_textures_to_update) {
3550
Texture *texture = texture_owner.get_or_null(shared.texture);
3551
ERR_CONTINUE(texture == nullptr);
3552
_texture_update_shared_fallback(shared.texture, texture, shared.writing);
3553
}
3554
}
3555
3556
RID RenderingDevice::uniform_set_create(const VectorView<RD::Uniform> &p_uniforms, RID p_shader, uint32_t p_shader_set, bool p_linear_pool) {
3557
_THREAD_SAFE_METHOD_
3558
3559
ERR_FAIL_COND_V(p_uniforms.size() == 0, RID());
3560
3561
Shader *shader = shader_owner.get_or_null(p_shader);
3562
ERR_FAIL_NULL_V(shader, RID());
3563
3564
ERR_FAIL_COND_V_MSG(p_shader_set >= (uint32_t)shader->uniform_sets.size() || shader->uniform_sets[p_shader_set].is_empty(), RID(),
3565
"Desired set (" + itos(p_shader_set) + ") not used by shader.");
3566
// See that all sets in shader are satisfied.
3567
3568
const Vector<ShaderUniform> &set = shader->uniform_sets[p_shader_set];
3569
3570
uint32_t uniform_count = p_uniforms.size();
3571
const Uniform *uniforms = p_uniforms.ptr();
3572
3573
uint32_t set_uniform_count = set.size();
3574
const ShaderUniform *set_uniforms = set.ptr();
3575
3576
LocalVector<RDD::BoundUniform> driver_uniforms;
3577
driver_uniforms.resize(set_uniform_count);
3578
3579
// Used for verification to make sure a uniform set does not use a framebuffer bound texture.
3580
LocalVector<UniformSet::AttachableTexture> attachable_textures;
3581
Vector<RDG::ResourceTracker *> draw_trackers;
3582
Vector<RDG::ResourceUsage> draw_trackers_usage;
3583
HashMap<RID, RDG::ResourceUsage> untracked_usage;
3584
Vector<UniformSet::SharedTexture> shared_textures_to_update;
3585
3586
for (uint32_t i = 0; i < set_uniform_count; i++) {
3587
const ShaderUniform &set_uniform = set_uniforms[i];
3588
int uniform_idx = -1;
3589
for (int j = 0; j < (int)uniform_count; j++) {
3590
if (uniforms[j].binding == set_uniform.binding) {
3591
uniform_idx = j;
3592
break;
3593
}
3594
}
3595
ERR_FAIL_COND_V_MSG(uniform_idx == -1, RID(),
3596
"All the shader bindings for the given set must be covered by the uniforms provided. Binding (" + itos(set_uniform.binding) + "), set (" + itos(p_shader_set) + ") was not provided.");
3597
3598
const Uniform &uniform = uniforms[uniform_idx];
3599
3600
ERR_FAIL_INDEX_V(uniform.uniform_type, RD::UNIFORM_TYPE_MAX, RID());
3601
ERR_FAIL_COND_V_MSG(uniform.uniform_type != set_uniform.type, RID(),
3602
"Mismatch uniform type for binding (" + itos(set_uniform.binding) + "), set (" + itos(p_shader_set) + "). Expected '" + SHADER_UNIFORM_NAMES[set_uniform.type] + "', supplied: '" + SHADER_UNIFORM_NAMES[uniform.uniform_type] + "'.");
3603
3604
RDD::BoundUniform &driver_uniform = driver_uniforms[i];
3605
driver_uniform.type = uniform.uniform_type;
3606
driver_uniform.binding = uniform.binding;
3607
3608
// Mark immutable samplers to be skipped when creating uniform set.
3609
driver_uniform.immutable_sampler = uniform.immutable_sampler;
3610
3611
switch (uniform.uniform_type) {
3612
case UNIFORM_TYPE_SAMPLER: {
3613
if (uniform.get_id_count() != (uint32_t)set_uniform.length) {
3614
if (set_uniform.length > 1) {
3615
ERR_FAIL_V_MSG(RID(), "Sampler (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") sampler elements, so it should be provided equal number of sampler IDs to satisfy it (IDs provided: " + itos(uniform.get_id_count()) + ").");
3616
} else {
3617
ERR_FAIL_V_MSG(RID(), "Sampler (binding: " + itos(uniform.binding) + ") should provide one ID referencing a sampler (IDs provided: " + itos(uniform.get_id_count()) + ").");
3618
}
3619
}
3620
3621
for (uint32_t j = 0; j < uniform.get_id_count(); j++) {
3622
RDD::SamplerID *sampler_driver_id = sampler_owner.get_or_null(uniform.get_id(j));
3623
ERR_FAIL_NULL_V_MSG(sampler_driver_id, RID(), "Sampler (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") is not a valid sampler.");
3624
3625
driver_uniform.ids.push_back(*sampler_driver_id);
3626
}
3627
} break;
3628
case UNIFORM_TYPE_SAMPLER_WITH_TEXTURE: {
3629
if (uniform.get_id_count() != (uint32_t)set_uniform.length * 2) {
3630
if (set_uniform.length > 1) {
3631
ERR_FAIL_V_MSG(RID(), "SamplerTexture (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") sampler&texture elements, so it should provided twice the amount of IDs (sampler,texture pairs) to satisfy it (IDs provided: " + itos(uniform.get_id_count()) + ").");
3632
} else {
3633
ERR_FAIL_V_MSG(RID(), "SamplerTexture (binding: " + itos(uniform.binding) + ") should provide two IDs referencing a sampler and then a texture (IDs provided: " + itos(uniform.get_id_count()) + ").");
3634
}
3635
}
3636
3637
for (uint32_t j = 0; j < uniform.get_id_count(); j += 2) {
3638
RDD::SamplerID *sampler_driver_id = sampler_owner.get_or_null(uniform.get_id(j + 0));
3639
ERR_FAIL_NULL_V_MSG(sampler_driver_id, RID(), "SamplerBuffer (binding: " + itos(uniform.binding) + ", index " + itos(j + 1) + ") is not a valid sampler.");
3640
3641
RID texture_id = uniform.get_id(j + 1);
3642
Texture *texture = texture_owner.get_or_null(texture_id);
3643
ERR_FAIL_NULL_V_MSG(texture, RID(), "Texture (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") is not a valid texture.");
3644
3645
ERR_FAIL_COND_V_MSG(!(texture->usage_flags & TEXTURE_USAGE_SAMPLING_BIT), RID(),
3646
"Texture (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") needs the TEXTURE_USAGE_SAMPLING_BIT usage flag set in order to be used as uniform.");
3647
3648
if ((texture->usage_flags & (TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | TEXTURE_USAGE_INPUT_ATTACHMENT_BIT))) {
3649
UniformSet::AttachableTexture attachable_texture;
3650
attachable_texture.bind = set_uniform.binding;
3651
attachable_texture.texture = texture->owner.is_valid() ? texture->owner : uniform.get_id(j + 1);
3652
attachable_textures.push_back(attachable_texture);
3653
}
3654
3655
RDD::TextureID driver_id = texture->driver_id;
3656
RDG::ResourceTracker *tracker = texture->draw_tracker;
3657
if (texture->shared_fallback != nullptr && texture->shared_fallback->texture.id != 0) {
3658
driver_id = texture->shared_fallback->texture;
3659
tracker = texture->shared_fallback->texture_tracker;
3660
shared_textures_to_update.push_back({ false, texture_id });
3661
}
3662
3663
if (tracker != nullptr) {
3664
draw_trackers.push_back(tracker);
3665
draw_trackers_usage.push_back(RDG::RESOURCE_USAGE_TEXTURE_SAMPLE);
3666
} else {
3667
untracked_usage[texture_id] = RDG::RESOURCE_USAGE_TEXTURE_SAMPLE;
3668
}
3669
3670
DEV_ASSERT(!texture->owner.is_valid() || texture_owner.get_or_null(texture->owner));
3671
3672
driver_uniform.ids.push_back(*sampler_driver_id);
3673
driver_uniform.ids.push_back(driver_id);
3674
_check_transfer_worker_texture(texture);
3675
}
3676
} break;
3677
case UNIFORM_TYPE_TEXTURE: {
3678
if (uniform.get_id_count() != (uint32_t)set_uniform.length) {
3679
if (set_uniform.length > 1) {
3680
ERR_FAIL_V_MSG(RID(), "Texture (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") textures, so it should be provided equal number of texture IDs to satisfy it (IDs provided: " + itos(uniform.get_id_count()) + ").");
3681
} else {
3682
ERR_FAIL_V_MSG(RID(), "Texture (binding: " + itos(uniform.binding) + ") should provide one ID referencing a texture (IDs provided: " + itos(uniform.get_id_count()) + ").");
3683
}
3684
}
3685
3686
for (uint32_t j = 0; j < uniform.get_id_count(); j++) {
3687
RID texture_id = uniform.get_id(j);
3688
Texture *texture = texture_owner.get_or_null(texture_id);
3689
ERR_FAIL_NULL_V_MSG(texture, RID(), "Texture (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") is not a valid texture.");
3690
3691
ERR_FAIL_COND_V_MSG(!(texture->usage_flags & TEXTURE_USAGE_SAMPLING_BIT), RID(),
3692
"Texture (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") needs the TEXTURE_USAGE_SAMPLING_BIT usage flag set in order to be used as uniform.");
3693
3694
if ((texture->usage_flags & (TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | TEXTURE_USAGE_INPUT_ATTACHMENT_BIT))) {
3695
UniformSet::AttachableTexture attachable_texture;
3696
attachable_texture.bind = set_uniform.binding;
3697
attachable_texture.texture = texture->owner.is_valid() ? texture->owner : uniform.get_id(j);
3698
attachable_textures.push_back(attachable_texture);
3699
}
3700
3701
RDD::TextureID driver_id = texture->driver_id;
3702
RDG::ResourceTracker *tracker = texture->draw_tracker;
3703
if (texture->shared_fallback != nullptr && texture->shared_fallback->texture.id != 0) {
3704
driver_id = texture->shared_fallback->texture;
3705
tracker = texture->shared_fallback->texture_tracker;
3706
shared_textures_to_update.push_back({ false, texture_id });
3707
}
3708
3709
if (tracker != nullptr) {
3710
draw_trackers.push_back(tracker);
3711
draw_trackers_usage.push_back(RDG::RESOURCE_USAGE_TEXTURE_SAMPLE);
3712
} else {
3713
untracked_usage[texture_id] = RDG::RESOURCE_USAGE_TEXTURE_SAMPLE;
3714
}
3715
3716
DEV_ASSERT(!texture->owner.is_valid() || texture_owner.get_or_null(texture->owner));
3717
3718
driver_uniform.ids.push_back(driver_id);
3719
_check_transfer_worker_texture(texture);
3720
}
3721
} break;
3722
case UNIFORM_TYPE_IMAGE: {
3723
if (uniform.get_id_count() != (uint32_t)set_uniform.length) {
3724
if (set_uniform.length > 1) {
3725
ERR_FAIL_V_MSG(RID(), "Image (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") textures, so it should be provided equal number of texture IDs to satisfy it (IDs provided: " + itos(uniform.get_id_count()) + ").");
3726
} else {
3727
ERR_FAIL_V_MSG(RID(), "Image (binding: " + itos(uniform.binding) + ") should provide one ID referencing a texture (IDs provided: " + itos(uniform.get_id_count()) + ").");
3728
}
3729
}
3730
3731
for (uint32_t j = 0; j < uniform.get_id_count(); j++) {
3732
RID texture_id = uniform.get_id(j);
3733
Texture *texture = texture_owner.get_or_null(texture_id);
3734
3735
ERR_FAIL_NULL_V_MSG(texture, RID(),
3736
"Image (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") is not a valid texture.");
3737
3738
ERR_FAIL_COND_V_MSG(!(texture->usage_flags & TEXTURE_USAGE_STORAGE_BIT), RID(),
3739
"Image (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") needs the TEXTURE_USAGE_STORAGE_BIT usage flag set in order to be used as uniform.");
3740
3741
if (texture->owner.is_null() && texture->shared_fallback != nullptr) {
3742
shared_textures_to_update.push_back({ true, texture_id });
3743
}
3744
3745
if (_texture_make_mutable(texture, texture_id)) {
3746
// The texture must be mutable as a layout transition will be required.
3747
draw_graph.add_synchronization();
3748
}
3749
3750
if (texture->draw_tracker != nullptr) {
3751
draw_trackers.push_back(texture->draw_tracker);
3752
3753
if (set_uniform.writable) {
3754
draw_trackers_usage.push_back(RDG::RESOURCE_USAGE_STORAGE_IMAGE_READ_WRITE);
3755
} else {
3756
draw_trackers_usage.push_back(RDG::RESOURCE_USAGE_STORAGE_IMAGE_READ);
3757
}
3758
}
3759
3760
DEV_ASSERT(!texture->owner.is_valid() || texture_owner.get_or_null(texture->owner));
3761
3762
driver_uniform.ids.push_back(texture->driver_id);
3763
_check_transfer_worker_texture(texture);
3764
}
3765
} break;
3766
case UNIFORM_TYPE_TEXTURE_BUFFER: {
3767
if (uniform.get_id_count() != (uint32_t)set_uniform.length) {
3768
if (set_uniform.length > 1) {
3769
ERR_FAIL_V_MSG(RID(), "Buffer (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") texture buffer elements, so it should be provided equal number of texture buffer IDs to satisfy it (IDs provided: " + itos(uniform.get_id_count()) + ").");
3770
} else {
3771
ERR_FAIL_V_MSG(RID(), "Buffer (binding: " + itos(uniform.binding) + ") should provide one ID referencing a texture buffer (IDs provided: " + itos(uniform.get_id_count()) + ").");
3772
}
3773
}
3774
3775
for (uint32_t j = 0; j < uniform.get_id_count(); j++) {
3776
RID buffer_id = uniform.get_id(j);
3777
Buffer *buffer = texture_buffer_owner.get_or_null(buffer_id);
3778
ERR_FAIL_NULL_V_MSG(buffer, RID(), "Texture Buffer (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") is not a valid texture buffer.");
3779
3780
if (set_uniform.writable && _buffer_make_mutable(buffer, buffer_id)) {
3781
// The buffer must be mutable if it's used for writing.
3782
draw_graph.add_synchronization();
3783
}
3784
3785
if (buffer->draw_tracker != nullptr) {
3786
draw_trackers.push_back(buffer->draw_tracker);
3787
3788
if (set_uniform.writable) {
3789
draw_trackers_usage.push_back(RDG::RESOURCE_USAGE_TEXTURE_BUFFER_READ_WRITE);
3790
} else {
3791
draw_trackers_usage.push_back(RDG::RESOURCE_USAGE_TEXTURE_BUFFER_READ);
3792
}
3793
} else {
3794
untracked_usage[buffer_id] = RDG::RESOURCE_USAGE_TEXTURE_BUFFER_READ;
3795
}
3796
3797
driver_uniform.ids.push_back(buffer->driver_id);
3798
_check_transfer_worker_buffer(buffer);
3799
}
3800
} break;
3801
case UNIFORM_TYPE_SAMPLER_WITH_TEXTURE_BUFFER: {
3802
if (uniform.get_id_count() != (uint32_t)set_uniform.length * 2) {
3803
if (set_uniform.length > 1) {
3804
ERR_FAIL_V_MSG(RID(), "SamplerBuffer (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") sampler buffer elements, so it should provided twice the amount of IDs (sampler,buffer pairs) to satisfy it (IDs provided: " + itos(uniform.get_id_count()) + ").");
3805
} else {
3806
ERR_FAIL_V_MSG(RID(), "SamplerBuffer (binding: " + itos(uniform.binding) + ") should provide two IDs referencing a sampler and then a texture buffer (IDs provided: " + itos(uniform.get_id_count()) + ").");
3807
}
3808
}
3809
3810
for (uint32_t j = 0; j < uniform.get_id_count(); j += 2) {
3811
RDD::SamplerID *sampler_driver_id = sampler_owner.get_or_null(uniform.get_id(j + 0));
3812
ERR_FAIL_NULL_V_MSG(sampler_driver_id, RID(), "SamplerBuffer (binding: " + itos(uniform.binding) + ", index " + itos(j + 1) + ") is not a valid sampler.");
3813
3814
RID buffer_id = uniform.get_id(j + 1);
3815
Buffer *buffer = texture_buffer_owner.get_or_null(buffer_id);
3816
ERR_FAIL_NULL_V_MSG(buffer, RID(), "SamplerBuffer (binding: " + itos(uniform.binding) + ", index " + itos(j + 1) + ") is not a valid texture buffer.");
3817
3818
if (buffer->draw_tracker != nullptr) {
3819
draw_trackers.push_back(buffer->draw_tracker);
3820
draw_trackers_usage.push_back(RDG::RESOURCE_USAGE_TEXTURE_BUFFER_READ);
3821
} else {
3822
untracked_usage[buffer_id] = RDG::RESOURCE_USAGE_TEXTURE_BUFFER_READ;
3823
}
3824
3825
driver_uniform.ids.push_back(*sampler_driver_id);
3826
driver_uniform.ids.push_back(buffer->driver_id);
3827
_check_transfer_worker_buffer(buffer);
3828
}
3829
} break;
3830
case UNIFORM_TYPE_IMAGE_BUFFER: {
3831
// Todo.
3832
} break;
3833
case UNIFORM_TYPE_UNIFORM_BUFFER: {
3834
ERR_FAIL_COND_V_MSG(uniform.get_id_count() != 1, RID(),
3835
"Uniform buffer supplied (binding: " + itos(uniform.binding) + ") must provide one ID (" + itos(uniform.get_id_count()) + " provided).");
3836
3837
RID buffer_id = uniform.get_id(0);
3838
Buffer *buffer = uniform_buffer_owner.get_or_null(buffer_id);
3839
ERR_FAIL_NULL_V_MSG(buffer, RID(), "Uniform buffer supplied (binding: " + itos(uniform.binding) + ") is invalid.");
3840
3841
ERR_FAIL_COND_V_MSG(buffer->size < (uint32_t)set_uniform.length, RID(),
3842
"Uniform buffer supplied (binding: " + itos(uniform.binding) + ") size (" + itos(buffer->size) + ") is smaller than size of shader uniform: (" + itos(set_uniform.length) + ").");
3843
3844
if (buffer->draw_tracker != nullptr) {
3845
draw_trackers.push_back(buffer->draw_tracker);
3846
draw_trackers_usage.push_back(RDG::RESOURCE_USAGE_UNIFORM_BUFFER_READ);
3847
} else {
3848
untracked_usage[buffer_id] = RDG::RESOURCE_USAGE_UNIFORM_BUFFER_READ;
3849
}
3850
3851
driver_uniform.ids.push_back(buffer->driver_id);
3852
_check_transfer_worker_buffer(buffer);
3853
} break;
3854
case UNIFORM_TYPE_STORAGE_BUFFER: {
3855
ERR_FAIL_COND_V_MSG(uniform.get_id_count() != 1, RID(),
3856
"Storage buffer supplied (binding: " + itos(uniform.binding) + ") must provide one ID (" + itos(uniform.get_id_count()) + " provided).");
3857
3858
Buffer *buffer = nullptr;
3859
3860
RID buffer_id = uniform.get_id(0);
3861
if (storage_buffer_owner.owns(buffer_id)) {
3862
buffer = storage_buffer_owner.get_or_null(buffer_id);
3863
} else if (vertex_buffer_owner.owns(buffer_id)) {
3864
buffer = vertex_buffer_owner.get_or_null(buffer_id);
3865
3866
ERR_FAIL_COND_V_MSG(!(buffer->usage.has_flag(RDD::BUFFER_USAGE_STORAGE_BIT)), RID(), "Vertex buffer supplied (binding: " + itos(uniform.binding) + ") was not created with storage flag.");
3867
}
3868
ERR_FAIL_NULL_V_MSG(buffer, RID(), "Storage buffer supplied (binding: " + itos(uniform.binding) + ") is invalid.");
3869
3870
// If 0, then it's sized on link time.
3871
ERR_FAIL_COND_V_MSG(set_uniform.length > 0 && buffer->size != (uint32_t)set_uniform.length, RID(),
3872
"Storage buffer supplied (binding: " + itos(uniform.binding) + ") size (" + itos(buffer->size) + ") does not match size of shader uniform: (" + itos(set_uniform.length) + ").");
3873
3874
if (set_uniform.writable && _buffer_make_mutable(buffer, buffer_id)) {
3875
// The buffer must be mutable if it's used for writing.
3876
draw_graph.add_synchronization();
3877
}
3878
3879
if (buffer->draw_tracker != nullptr) {
3880
draw_trackers.push_back(buffer->draw_tracker);
3881
3882
if (set_uniform.writable) {
3883
draw_trackers_usage.push_back(RDG::RESOURCE_USAGE_STORAGE_BUFFER_READ_WRITE);
3884
} else {
3885
draw_trackers_usage.push_back(RDG::RESOURCE_USAGE_STORAGE_BUFFER_READ);
3886
}
3887
} else {
3888
untracked_usage[buffer_id] = RDG::RESOURCE_USAGE_STORAGE_BUFFER_READ;
3889
}
3890
3891
driver_uniform.ids.push_back(buffer->driver_id);
3892
_check_transfer_worker_buffer(buffer);
3893
} break;
3894
case UNIFORM_TYPE_INPUT_ATTACHMENT: {
3895
ERR_FAIL_COND_V_MSG(shader->is_compute, RID(), "InputAttachment (binding: " + itos(uniform.binding) + ") supplied for compute shader (this is not allowed).");
3896
3897
if (uniform.get_id_count() != (uint32_t)set_uniform.length) {
3898
if (set_uniform.length > 1) {
3899
ERR_FAIL_V_MSG(RID(), "InputAttachment (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") textures, so it should be provided equal number of texture IDs to satisfy it (IDs provided: " + itos(uniform.get_id_count()) + ").");
3900
} else {
3901
ERR_FAIL_V_MSG(RID(), "InputAttachment (binding: " + itos(uniform.binding) + ") should provide one ID referencing a texture (IDs provided: " + itos(uniform.get_id_count()) + ").");
3902
}
3903
}
3904
3905
for (uint32_t j = 0; j < uniform.get_id_count(); j++) {
3906
RID texture_id = uniform.get_id(j);
3907
Texture *texture = texture_owner.get_or_null(texture_id);
3908
3909
ERR_FAIL_NULL_V_MSG(texture, RID(),
3910
"InputAttachment (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") is not a valid texture.");
3911
3912
ERR_FAIL_COND_V_MSG(!(texture->usage_flags & TEXTURE_USAGE_SAMPLING_BIT), RID(),
3913
"InputAttachment (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") needs the TEXTURE_USAGE_SAMPLING_BIT usage flag set in order to be used as uniform.");
3914
3915
DEV_ASSERT(!texture->owner.is_valid() || texture_owner.get_or_null(texture->owner));
3916
3917
driver_uniform.ids.push_back(texture->driver_id);
3918
_check_transfer_worker_texture(texture);
3919
}
3920
} break;
3921
default: {
3922
}
3923
}
3924
}
3925
3926
RDD::UniformSetID driver_uniform_set = driver->uniform_set_create(driver_uniforms, shader->driver_id, p_shader_set, p_linear_pool ? frame : -1);
3927
ERR_FAIL_COND_V(!driver_uniform_set, RID());
3928
3929
UniformSet uniform_set;
3930
uniform_set.driver_id = driver_uniform_set;
3931
uniform_set.format = shader->set_formats[p_shader_set];
3932
uniform_set.attachable_textures = attachable_textures;
3933
uniform_set.draw_trackers = draw_trackers;
3934
uniform_set.draw_trackers_usage = draw_trackers_usage;
3935
uniform_set.untracked_usage = untracked_usage;
3936
uniform_set.shared_textures_to_update = shared_textures_to_update;
3937
uniform_set.shader_set = p_shader_set;
3938
uniform_set.shader_id = p_shader;
3939
3940
RID id = uniform_set_owner.make_rid(uniform_set);
3941
#ifdef DEV_ENABLED
3942
set_resource_name(id, "RID:" + itos(id.get_id()));
3943
#endif
3944
// Add dependencies.
3945
_add_dependency(id, p_shader);
3946
for (uint32_t i = 0; i < uniform_count; i++) {
3947
const Uniform &uniform = uniforms[i];
3948
int id_count = uniform.get_id_count();
3949
for (int j = 0; j < id_count; j++) {
3950
_add_dependency(id, uniform.get_id(j));
3951
}
3952
}
3953
3954
return id;
3955
}
3956
3957
bool RenderingDevice::uniform_set_is_valid(RID p_uniform_set) {
3958
_THREAD_SAFE_METHOD_
3959
3960
return uniform_set_owner.owns(p_uniform_set);
3961
}
3962
3963
void RenderingDevice::uniform_set_set_invalidation_callback(RID p_uniform_set, InvalidationCallback p_callback, void *p_userdata) {
3964
_THREAD_SAFE_METHOD_
3965
3966
UniformSet *us = uniform_set_owner.get_or_null(p_uniform_set);
3967
ERR_FAIL_NULL(us);
3968
us->invalidated_callback = p_callback;
3969
us->invalidated_callback_userdata = p_userdata;
3970
}
3971
3972
bool RenderingDevice::uniform_sets_have_linear_pools() const {
3973
return driver->uniform_sets_have_linear_pools();
3974
}
3975
3976
/*******************/
3977
/**** PIPELINES ****/
3978
/*******************/
3979
3980
RID RenderingDevice::render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const PipelineRasterizationState &p_rasterization_state, const PipelineMultisampleState &p_multisample_state, const PipelineDepthStencilState &p_depth_stencil_state, const PipelineColorBlendState &p_blend_state, BitField<PipelineDynamicStateFlags> p_dynamic_state_flags, uint32_t p_for_render_pass, const Vector<PipelineSpecializationConstant> &p_specialization_constants) {
3981
// Needs a shader.
3982
Shader *shader = shader_owner.get_or_null(p_shader);
3983
ERR_FAIL_NULL_V(shader, RID());
3984
ERR_FAIL_COND_V_MSG(shader->is_compute, RID(), "Compute shaders can't be used in render pipelines");
3985
3986
// Validate pre-raster shader. One of stages must be vertex shader or mesh shader (not implemented yet).
3987
ERR_FAIL_COND_V_MSG(!shader->stage_bits.has_flag(RDD::PIPELINE_STAGE_VERTEX_SHADER_BIT), RID(), "Pre-raster shader (vertex shader) is not provided for pipeline creation.");
3988
3989
FramebufferFormat fb_format;
3990
{
3991
_THREAD_SAFE_METHOD_
3992
3993
if (p_framebuffer_format == INVALID_ID) {
3994
// If nothing provided, use an empty one (no attachments).
3995
p_framebuffer_format = framebuffer_format_create(Vector<AttachmentFormat>());
3996
}
3997
ERR_FAIL_COND_V(!framebuffer_formats.has(p_framebuffer_format), RID());
3998
fb_format = framebuffer_formats[p_framebuffer_format];
3999
}
4000
4001
// Validate shader vs. framebuffer.
4002
{
4003
ERR_FAIL_COND_V_MSG(p_for_render_pass >= uint32_t(fb_format.E->key().passes.size()), RID(), "Render pass requested for pipeline creation (" + itos(p_for_render_pass) + ") is out of bounds");
4004
const FramebufferPass &pass = fb_format.E->key().passes[p_for_render_pass];
4005
uint32_t output_mask = 0;
4006
for (int i = 0; i < pass.color_attachments.size(); i++) {
4007
if (pass.color_attachments[i] != ATTACHMENT_UNUSED) {
4008
output_mask |= 1 << i;
4009
}
4010
}
4011
ERR_FAIL_COND_V_MSG(shader->fragment_output_mask != output_mask, RID(),
4012
"Mismatch fragment shader output mask (" + itos(shader->fragment_output_mask) + ") and framebuffer color output mask (" + itos(output_mask) + ") when binding both in render pipeline.");
4013
}
4014
4015
RDD::VertexFormatID driver_vertex_format;
4016
if (p_vertex_format != INVALID_ID) {
4017
// Uses vertices, else it does not.
4018
ERR_FAIL_COND_V(!vertex_formats.has(p_vertex_format), RID());
4019
const VertexDescriptionCache &vd = vertex_formats[p_vertex_format];
4020
driver_vertex_format = vertex_formats[p_vertex_format].driver_id;
4021
4022
// Validate with inputs.
4023
for (uint32_t i = 0; i < 64; i++) {
4024
if (!(shader->vertex_input_mask & ((uint64_t)1) << i)) {
4025
continue;
4026
}
4027
bool found = false;
4028
for (int j = 0; j < vd.vertex_formats.size(); j++) {
4029
if (vd.vertex_formats[j].location == i) {
4030
found = true;
4031
break;
4032
}
4033
}
4034
4035
ERR_FAIL_COND_V_MSG(!found, RID(),
4036
"Shader vertex input location (" + itos(i) + ") not provided in vertex input description for pipeline creation.");
4037
}
4038
4039
} else {
4040
ERR_FAIL_COND_V_MSG(shader->vertex_input_mask != 0, RID(),
4041
"Shader contains vertex inputs, but no vertex input description was provided for pipeline creation.");
4042
}
4043
4044
ERR_FAIL_INDEX_V(p_render_primitive, RENDER_PRIMITIVE_MAX, RID());
4045
4046
ERR_FAIL_INDEX_V(p_rasterization_state.cull_mode, 3, RID());
4047
4048
if (p_multisample_state.sample_mask.size()) {
4049
// Use sample mask.
4050
ERR_FAIL_COND_V((int)TEXTURE_SAMPLES_COUNT[p_multisample_state.sample_count] != p_multisample_state.sample_mask.size(), RID());
4051
}
4052
4053
ERR_FAIL_INDEX_V(p_depth_stencil_state.depth_compare_operator, COMPARE_OP_MAX, RID());
4054
4055
ERR_FAIL_INDEX_V(p_depth_stencil_state.front_op.fail, STENCIL_OP_MAX, RID());
4056
ERR_FAIL_INDEX_V(p_depth_stencil_state.front_op.pass, STENCIL_OP_MAX, RID());
4057
ERR_FAIL_INDEX_V(p_depth_stencil_state.front_op.depth_fail, STENCIL_OP_MAX, RID());
4058
ERR_FAIL_INDEX_V(p_depth_stencil_state.front_op.compare, COMPARE_OP_MAX, RID());
4059
4060
ERR_FAIL_INDEX_V(p_depth_stencil_state.back_op.fail, STENCIL_OP_MAX, RID());
4061
ERR_FAIL_INDEX_V(p_depth_stencil_state.back_op.pass, STENCIL_OP_MAX, RID());
4062
ERR_FAIL_INDEX_V(p_depth_stencil_state.back_op.depth_fail, STENCIL_OP_MAX, RID());
4063
ERR_FAIL_INDEX_V(p_depth_stencil_state.back_op.compare, COMPARE_OP_MAX, RID());
4064
4065
ERR_FAIL_INDEX_V(p_blend_state.logic_op, LOGIC_OP_MAX, RID());
4066
4067
const FramebufferPass &pass = fb_format.E->key().passes[p_for_render_pass];
4068
ERR_FAIL_COND_V(p_blend_state.attachments.size() < pass.color_attachments.size(), RID());
4069
for (int i = 0; i < pass.color_attachments.size(); i++) {
4070
if (pass.color_attachments[i] != ATTACHMENT_UNUSED) {
4071
ERR_FAIL_INDEX_V(p_blend_state.attachments[i].src_color_blend_factor, BLEND_FACTOR_MAX, RID());
4072
ERR_FAIL_INDEX_V(p_blend_state.attachments[i].dst_color_blend_factor, BLEND_FACTOR_MAX, RID());
4073
ERR_FAIL_INDEX_V(p_blend_state.attachments[i].color_blend_op, BLEND_OP_MAX, RID());
4074
4075
ERR_FAIL_INDEX_V(p_blend_state.attachments[i].src_alpha_blend_factor, BLEND_FACTOR_MAX, RID());
4076
ERR_FAIL_INDEX_V(p_blend_state.attachments[i].dst_alpha_blend_factor, BLEND_FACTOR_MAX, RID());
4077
ERR_FAIL_INDEX_V(p_blend_state.attachments[i].alpha_blend_op, BLEND_OP_MAX, RID());
4078
}
4079
}
4080
4081
for (int i = 0; i < shader->specialization_constants.size(); i++) {
4082
const ShaderSpecializationConstant &sc = shader->specialization_constants[i];
4083
for (int j = 0; j < p_specialization_constants.size(); j++) {
4084
const PipelineSpecializationConstant &psc = p_specialization_constants[j];
4085
if (psc.constant_id == sc.constant_id) {
4086
ERR_FAIL_COND_V_MSG(psc.type != sc.type, RID(), "Specialization constant provided for id (" + itos(sc.constant_id) + ") is of the wrong type.");
4087
break;
4088
}
4089
}
4090
}
4091
4092
RenderPipeline pipeline;
4093
pipeline.driver_id = driver->render_pipeline_create(
4094
shader->driver_id,
4095
driver_vertex_format,
4096
p_render_primitive,
4097
p_rasterization_state,
4098
p_multisample_state,
4099
p_depth_stencil_state,
4100
p_blend_state,
4101
pass.color_attachments,
4102
p_dynamic_state_flags,
4103
fb_format.render_pass,
4104
p_for_render_pass,
4105
p_specialization_constants);
4106
ERR_FAIL_COND_V(!pipeline.driver_id, RID());
4107
4108
if (pipeline_cache_enabled) {
4109
_update_pipeline_cache();
4110
}
4111
4112
pipeline.shader = p_shader;
4113
pipeline.shader_driver_id = shader->driver_id;
4114
pipeline.shader_layout_hash = shader->layout_hash;
4115
pipeline.set_formats = shader->set_formats;
4116
pipeline.push_constant_size = shader->push_constant_size;
4117
pipeline.stage_bits = shader->stage_bits;
4118
4119
#ifdef DEBUG_ENABLED
4120
pipeline.validation.dynamic_state = p_dynamic_state_flags;
4121
pipeline.validation.framebuffer_format = p_framebuffer_format;
4122
pipeline.validation.render_pass = p_for_render_pass;
4123
pipeline.validation.vertex_format = p_vertex_format;
4124
pipeline.validation.uses_restart_indices = p_render_primitive == RENDER_PRIMITIVE_TRIANGLE_STRIPS_WITH_RESTART_INDEX;
4125
4126
static const uint32_t primitive_divisor[RENDER_PRIMITIVE_MAX] = {
4127
1, 2, 1, 1, 1, 3, 1, 1, 1, 1, 1
4128
};
4129
pipeline.validation.primitive_divisor = primitive_divisor[p_render_primitive];
4130
static const uint32_t primitive_minimum[RENDER_PRIMITIVE_MAX] = {
4131
1,
4132
2,
4133
2,
4134
2,
4135
2,
4136
3,
4137
3,
4138
3,
4139
3,
4140
3,
4141
1,
4142
};
4143
pipeline.validation.primitive_minimum = primitive_minimum[p_render_primitive];
4144
#endif
4145
4146
// Create ID to associate with this pipeline.
4147
RID id = render_pipeline_owner.make_rid(pipeline);
4148
{
4149
_THREAD_SAFE_METHOD_
4150
4151
#ifdef DEV_ENABLED
4152
set_resource_name(id, "RID:" + itos(id.get_id()));
4153
#endif
4154
// Now add all the dependencies.
4155
_add_dependency(id, p_shader);
4156
}
4157
4158
return id;
4159
}
4160
4161
bool RenderingDevice::render_pipeline_is_valid(RID p_pipeline) {
4162
_THREAD_SAFE_METHOD_
4163
4164
return render_pipeline_owner.owns(p_pipeline);
4165
}
4166
4167
RID RenderingDevice::compute_pipeline_create(RID p_shader, const Vector<PipelineSpecializationConstant> &p_specialization_constants) {
4168
Shader *shader;
4169
4170
{
4171
_THREAD_SAFE_METHOD_
4172
4173
// Needs a shader.
4174
shader = shader_owner.get_or_null(p_shader);
4175
ERR_FAIL_NULL_V(shader, RID());
4176
4177
ERR_FAIL_COND_V_MSG(!shader->is_compute, RID(),
4178
"Non-compute shaders can't be used in compute pipelines");
4179
}
4180
4181
for (int i = 0; i < shader->specialization_constants.size(); i++) {
4182
const ShaderSpecializationConstant &sc = shader->specialization_constants[i];
4183
for (int j = 0; j < p_specialization_constants.size(); j++) {
4184
const PipelineSpecializationConstant &psc = p_specialization_constants[j];
4185
if (psc.constant_id == sc.constant_id) {
4186
ERR_FAIL_COND_V_MSG(psc.type != sc.type, RID(), "Specialization constant provided for id (" + itos(sc.constant_id) + ") is of the wrong type.");
4187
break;
4188
}
4189
}
4190
}
4191
4192
ComputePipeline pipeline;
4193
pipeline.driver_id = driver->compute_pipeline_create(shader->driver_id, p_specialization_constants);
4194
ERR_FAIL_COND_V(!pipeline.driver_id, RID());
4195
4196
if (pipeline_cache_enabled) {
4197
_update_pipeline_cache();
4198
}
4199
4200
pipeline.shader = p_shader;
4201
pipeline.shader_driver_id = shader->driver_id;
4202
pipeline.shader_layout_hash = shader->layout_hash;
4203
pipeline.set_formats = shader->set_formats;
4204
pipeline.push_constant_size = shader->push_constant_size;
4205
pipeline.local_group_size[0] = shader->compute_local_size[0];
4206
pipeline.local_group_size[1] = shader->compute_local_size[1];
4207
pipeline.local_group_size[2] = shader->compute_local_size[2];
4208
4209
// Create ID to associate with this pipeline.
4210
RID id = compute_pipeline_owner.make_rid(pipeline);
4211
{
4212
_THREAD_SAFE_METHOD_
4213
4214
#ifdef DEV_ENABLED
4215
set_resource_name(id, "RID:" + itos(id.get_id()));
4216
#endif
4217
// Now add all the dependencies.
4218
_add_dependency(id, p_shader);
4219
}
4220
4221
return id;
4222
}
4223
4224
bool RenderingDevice::compute_pipeline_is_valid(RID p_pipeline) {
4225
_THREAD_SAFE_METHOD_
4226
4227
return compute_pipeline_owner.owns(p_pipeline);
4228
}
4229
4230
/****************/
4231
/**** SCREEN ****/
4232
/****************/
4233
4234
uint32_t RenderingDevice::_get_swap_chain_desired_count() const {
4235
return MAX(2U, uint32_t(GLOBAL_GET_CACHED(uint32_t, "rendering/rendering_device/vsync/swapchain_image_count")));
4236
}
4237
4238
Error RenderingDevice::screen_create(DisplayServer::WindowID p_screen) {
4239
_THREAD_SAFE_METHOD_
4240
4241
RenderingContextDriver::SurfaceID surface = context->surface_get_from_window(p_screen);
4242
ERR_FAIL_COND_V_MSG(surface == 0, ERR_CANT_CREATE, "A surface was not created for the screen.");
4243
4244
HashMap<DisplayServer::WindowID, RDD::SwapChainID>::ConstIterator it = screen_swap_chains.find(p_screen);
4245
ERR_FAIL_COND_V_MSG(it != screen_swap_chains.end(), ERR_CANT_CREATE, "A swap chain was already created for the screen.");
4246
4247
RDD::SwapChainID swap_chain = driver->swap_chain_create(surface);
4248
ERR_FAIL_COND_V_MSG(swap_chain.id == 0, ERR_CANT_CREATE, "Unable to create swap chain.");
4249
4250
screen_swap_chains[p_screen] = swap_chain;
4251
4252
return OK;
4253
}
4254
4255
Error RenderingDevice::screen_prepare_for_drawing(DisplayServer::WindowID p_screen) {
4256
_THREAD_SAFE_METHOD_
4257
4258
// After submitting work, acquire the swapchain image(s).
4259
HashMap<DisplayServer::WindowID, RDD::SwapChainID>::ConstIterator it = screen_swap_chains.find(p_screen);
4260
ERR_FAIL_COND_V_MSG(it == screen_swap_chains.end(), ERR_CANT_CREATE, "A swap chain was not created for the screen.");
4261
4262
// Erase the framebuffer corresponding to this screen from the map in case any of the operations fail.
4263
screen_framebuffers.erase(p_screen);
4264
4265
// If this frame has already queued this swap chain for presentation, we present it and remove it from the pending list.
4266
uint32_t to_present_index = 0;
4267
while (to_present_index < frames[frame].swap_chains_to_present.size()) {
4268
if (frames[frame].swap_chains_to_present[to_present_index] == it->value) {
4269
driver->command_queue_execute_and_present(present_queue, {}, {}, {}, {}, it->value);
4270
frames[frame].swap_chains_to_present.remove_at(to_present_index);
4271
} else {
4272
to_present_index++;
4273
}
4274
}
4275
4276
bool resize_required = false;
4277
RDD::FramebufferID framebuffer = driver->swap_chain_acquire_framebuffer(main_queue, it->value, resize_required);
4278
if (resize_required) {
4279
// Flush everything so nothing can be using the swap chain before resizing it.
4280
_flush_and_stall_for_all_frames();
4281
4282
Error err = driver->swap_chain_resize(main_queue, it->value, _get_swap_chain_desired_count());
4283
if (err != OK) {
4284
// Resize is allowed to fail silently because the window can be minimized.
4285
return err;
4286
}
4287
4288
framebuffer = driver->swap_chain_acquire_framebuffer(main_queue, it->value, resize_required);
4289
}
4290
4291
if (framebuffer.id == 0) {
4292
// Some drivers like NVIDIA are fast enough to invalidate the swap chain between resizing and acquisition (GH-94104).
4293
// This typically occurs during continuous window resizing operations, especially if done quickly.
4294
// Allow this to fail silently since it has no visual consequences.
4295
return ERR_CANT_CREATE;
4296
}
4297
4298
// Store the framebuffer that will be used next to draw to this screen.
4299
screen_framebuffers[p_screen] = framebuffer;
4300
frames[frame].swap_chains_to_present.push_back(it->value);
4301
4302
return OK;
4303
}
4304
4305
int RenderingDevice::screen_get_width(DisplayServer::WindowID p_screen) const {
4306
_THREAD_SAFE_METHOD_
4307
4308
RenderingContextDriver::SurfaceID surface = context->surface_get_from_window(p_screen);
4309
ERR_FAIL_COND_V_MSG(surface == 0, 0, "A surface was not created for the screen.");
4310
return context->surface_get_width(surface);
4311
}
4312
4313
int RenderingDevice::screen_get_height(DisplayServer::WindowID p_screen) const {
4314
_THREAD_SAFE_METHOD_
4315
4316
RenderingContextDriver::SurfaceID surface = context->surface_get_from_window(p_screen);
4317
ERR_FAIL_COND_V_MSG(surface == 0, 0, "A surface was not created for the screen.");
4318
return context->surface_get_height(surface);
4319
}
4320
4321
int RenderingDevice::screen_get_pre_rotation_degrees(DisplayServer::WindowID p_screen) const {
4322
_THREAD_SAFE_METHOD_
4323
4324
HashMap<DisplayServer::WindowID, RDD::SwapChainID>::ConstIterator it = screen_swap_chains.find(p_screen);
4325
ERR_FAIL_COND_V_MSG(it == screen_swap_chains.end(), ERR_CANT_CREATE, "A swap chain was not created for the screen.");
4326
4327
return driver->swap_chain_get_pre_rotation_degrees(it->value);
4328
}
4329
4330
RenderingDevice::FramebufferFormatID RenderingDevice::screen_get_framebuffer_format(DisplayServer::WindowID p_screen) const {
4331
_THREAD_SAFE_METHOD_
4332
4333
HashMap<DisplayServer::WindowID, RDD::SwapChainID>::ConstIterator it = screen_swap_chains.find(p_screen);
4334
ERR_FAIL_COND_V_MSG(it == screen_swap_chains.end(), FAILED, "Screen was never prepared.");
4335
4336
DataFormat format = driver->swap_chain_get_format(it->value);
4337
ERR_FAIL_COND_V(format == DATA_FORMAT_MAX, INVALID_ID);
4338
4339
AttachmentFormat attachment;
4340
attachment.format = format;
4341
attachment.samples = TEXTURE_SAMPLES_1;
4342
attachment.usage_flags = TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
4343
Vector<AttachmentFormat> screen_attachment;
4344
screen_attachment.push_back(attachment);
4345
return const_cast<RenderingDevice *>(this)->framebuffer_format_create(screen_attachment);
4346
}
4347
4348
Error RenderingDevice::screen_free(DisplayServer::WindowID p_screen) {
4349
_THREAD_SAFE_METHOD_
4350
4351
HashMap<DisplayServer::WindowID, RDD::SwapChainID>::ConstIterator it = screen_swap_chains.find(p_screen);
4352
ERR_FAIL_COND_V_MSG(it == screen_swap_chains.end(), FAILED, "Screen was never created.");
4353
4354
// Flush everything so nothing can be using the swap chain before erasing it.
4355
_flush_and_stall_for_all_frames();
4356
4357
const DisplayServer::WindowID screen = it->key;
4358
const RDD::SwapChainID swap_chain = it->value;
4359
driver->swap_chain_free(swap_chain);
4360
screen_framebuffers.erase(screen);
4361
screen_swap_chains.erase(screen);
4362
4363
return OK;
4364
}
4365
4366
/*******************/
4367
/**** DRAW LIST ****/
4368
/*******************/
4369
4370
RenderingDevice::DrawListID RenderingDevice::draw_list_begin_for_screen(DisplayServer::WindowID p_screen, const Color &p_clear_color) {
4371
ERR_RENDER_THREAD_GUARD_V(INVALID_ID);
4372
4373
ERR_FAIL_COND_V_MSG(draw_list.active, INVALID_ID, "Only one draw list can be active at the same time.");
4374
ERR_FAIL_COND_V_MSG(compute_list.active, INVALID_ID, "Only one draw/compute list can be active at the same time.");
4375
4376
RenderingContextDriver::SurfaceID surface = context->surface_get_from_window(p_screen);
4377
HashMap<DisplayServer::WindowID, RDD::SwapChainID>::ConstIterator sc_it = screen_swap_chains.find(p_screen);
4378
HashMap<DisplayServer::WindowID, RDD::FramebufferID>::ConstIterator fb_it = screen_framebuffers.find(p_screen);
4379
ERR_FAIL_COND_V_MSG(surface == 0, 0, "A surface was not created for the screen.");
4380
ERR_FAIL_COND_V_MSG(sc_it == screen_swap_chains.end(), INVALID_ID, "Screen was never prepared.");
4381
ERR_FAIL_COND_V_MSG(fb_it == screen_framebuffers.end(), INVALID_ID, "Framebuffer was never prepared.");
4382
4383
Rect2i viewport = Rect2i(0, 0, context->surface_get_width(surface), context->surface_get_height(surface));
4384
4385
_draw_list_start(viewport);
4386
#ifdef DEBUG_ENABLED
4387
draw_list_framebuffer_format = screen_get_framebuffer_format(p_screen);
4388
#endif
4389
draw_list_subpass_count = 1;
4390
4391
RDD::RenderPassClearValue clear_value;
4392
clear_value.color = p_clear_color;
4393
4394
RDD::RenderPassID render_pass = driver->swap_chain_get_render_pass(sc_it->value);
4395
draw_graph.add_draw_list_begin(render_pass, fb_it->value, viewport, RDG::ATTACHMENT_OPERATION_CLEAR, clear_value, RDD::PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, RDD::BreadcrumbMarker::BLIT_PASS, split_swapchain_into_its_own_cmd_buffer);
4396
4397
draw_graph.add_draw_list_set_viewport(viewport);
4398
draw_graph.add_draw_list_set_scissor(viewport);
4399
4400
return int64_t(ID_TYPE_DRAW_LIST) << ID_BASE_SHIFT;
4401
}
4402
4403
RenderingDevice::DrawListID RenderingDevice::_draw_list_begin_bind(RID p_framebuffer, BitField<DrawFlags> p_draw_flags, const Vector<Color> &p_clear_color_values, float p_clear_depth_value, uint32_t p_clear_stencil_value, const Rect2 &p_region, uint32_t p_breadcrumb) {
4404
return draw_list_begin(p_framebuffer, p_draw_flags, p_clear_color_values, p_clear_depth_value, p_clear_stencil_value, p_region, p_breadcrumb);
4405
}
4406
4407
RenderingDevice::DrawListID RenderingDevice::draw_list_begin(RID p_framebuffer, BitField<DrawFlags> p_draw_flags, VectorView<Color> p_clear_color_values, float p_clear_depth_value, uint32_t p_clear_stencil_value, const Rect2 &p_region, uint32_t p_breadcrumb) {
4408
ERR_RENDER_THREAD_GUARD_V(INVALID_ID);
4409
4410
ERR_FAIL_COND_V_MSG(draw_list.active, INVALID_ID, "Only one draw list can be active at the same time.");
4411
4412
Framebuffer *framebuffer = framebuffer_owner.get_or_null(p_framebuffer);
4413
ERR_FAIL_NULL_V(framebuffer, INVALID_ID);
4414
4415
const FramebufferFormatKey &framebuffer_key = framebuffer_formats[framebuffer->format_id].E->key();
4416
Point2i viewport_offset;
4417
Point2i viewport_size = framebuffer->size;
4418
4419
if (p_region != Rect2() && p_region != Rect2(Vector2(), viewport_size)) { // Check custom region.
4420
Rect2i viewport(viewport_offset, viewport_size);
4421
Rect2i regioni = p_region;
4422
if (!((regioni.position.x >= viewport.position.x) && (regioni.position.y >= viewport.position.y) &&
4423
((regioni.position.x + regioni.size.x) <= (viewport.position.x + viewport.size.x)) &&
4424
((regioni.position.y + regioni.size.y) <= (viewport.position.y + viewport.size.y)))) {
4425
ERR_FAIL_V_MSG(INVALID_ID, "When supplying a custom region, it must be contained within the framebuffer rectangle");
4426
}
4427
4428
viewport_offset = regioni.position;
4429
viewport_size = regioni.size;
4430
}
4431
4432
thread_local LocalVector<RDG::AttachmentOperation> operations;
4433
thread_local LocalVector<RDD::RenderPassClearValue> clear_values;
4434
thread_local LocalVector<RDG::ResourceTracker *> resource_trackers;
4435
thread_local LocalVector<RDG::ResourceUsage> resource_usages;
4436
BitField<RDD::PipelineStageBits> stages = {};
4437
operations.resize(framebuffer->texture_ids.size());
4438
clear_values.resize(framebuffer->texture_ids.size());
4439
resource_trackers.clear();
4440
resource_usages.clear();
4441
stages.clear();
4442
4443
uint32_t color_index = 0;
4444
for (int i = 0; i < framebuffer->texture_ids.size(); i++) {
4445
RID texture_rid = framebuffer->texture_ids[i];
4446
Texture *texture = texture_owner.get_or_null(texture_rid);
4447
if (texture == nullptr) {
4448
operations[i] = RDG::ATTACHMENT_OPERATION_DEFAULT;
4449
clear_values[i] = RDD::RenderPassClearValue();
4450
continue;
4451
}
4452
4453
// Indicate the texture will get modified for the shared texture fallback.
4454
_texture_update_shared_fallback(texture_rid, texture, true);
4455
4456
RDG::AttachmentOperation operation = RDG::ATTACHMENT_OPERATION_DEFAULT;
4457
RDD::RenderPassClearValue clear_value;
4458
if (framebuffer_key.vrs_attachment == i && (texture->usage_flags & TEXTURE_USAGE_VRS_ATTACHMENT_BIT)) {
4459
resource_trackers.push_back(texture->draw_tracker);
4460
resource_usages.push_back(_vrs_usage_from_method(framebuffer_key.vrs_method));
4461
stages.set_flag(_vrs_stages_from_method(framebuffer_key.vrs_method));
4462
} else if (texture->usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
4463
if (p_draw_flags.has_flag(DrawFlags(DRAW_CLEAR_COLOR_0 << color_index))) {
4464
ERR_FAIL_COND_V_MSG(color_index >= p_clear_color_values.size(), INVALID_ID, vformat("Color texture (%d) was specified to be cleared but no color value was provided.", color_index));
4465
operation = RDG::ATTACHMENT_OPERATION_CLEAR;
4466
clear_value.color = p_clear_color_values[color_index];
4467
} else if (p_draw_flags.has_flag(DrawFlags(DRAW_IGNORE_COLOR_0 << color_index))) {
4468
operation = RDG::ATTACHMENT_OPERATION_IGNORE;
4469
}
4470
4471
resource_trackers.push_back(texture->draw_tracker);
4472
resource_usages.push_back(RDG::RESOURCE_USAGE_ATTACHMENT_COLOR_READ_WRITE);
4473
stages.set_flag(RDD::PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
4474
color_index++;
4475
} else if (texture->usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
4476
if (p_draw_flags.has_flag(DRAW_CLEAR_DEPTH) || p_draw_flags.has_flag(DRAW_CLEAR_STENCIL)) {
4477
operation = RDG::ATTACHMENT_OPERATION_CLEAR;
4478
clear_value.depth = p_clear_depth_value;
4479
clear_value.stencil = p_clear_stencil_value;
4480
} else if (p_draw_flags.has_flag(DRAW_IGNORE_DEPTH) || p_draw_flags.has_flag(DRAW_IGNORE_STENCIL)) {
4481
operation = RDG::ATTACHMENT_OPERATION_IGNORE;
4482
}
4483
4484
resource_trackers.push_back(texture->draw_tracker);
4485
resource_usages.push_back(RDG::RESOURCE_USAGE_ATTACHMENT_DEPTH_STENCIL_READ_WRITE);
4486
stages.set_flag(RDD::PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT);
4487
stages.set_flag(RDD::PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
4488
}
4489
4490
operations[i] = operation;
4491
clear_values[i] = clear_value;
4492
}
4493
4494
draw_graph.add_draw_list_begin(framebuffer->framebuffer_cache, Rect2i(viewport_offset, viewport_size), operations, clear_values, stages, p_breadcrumb);
4495
draw_graph.add_draw_list_usages(resource_trackers, resource_usages);
4496
4497
// Mark textures as bound.
4498
draw_list_bound_textures.clear();
4499
4500
for (int i = 0; i < framebuffer->texture_ids.size(); i++) {
4501
Texture *texture = texture_owner.get_or_null(framebuffer->texture_ids[i]);
4502
if (texture == nullptr) {
4503
continue;
4504
}
4505
4506
texture->bound = true;
4507
draw_list_bound_textures.push_back(framebuffer->texture_ids[i]);
4508
}
4509
4510
_draw_list_start(Rect2i(viewport_offset, viewport_size));
4511
#ifdef DEBUG_ENABLED
4512
draw_list_framebuffer_format = framebuffer->format_id;
4513
#endif
4514
draw_list_current_subpass = 0;
4515
draw_list_subpass_count = framebuffer_key.passes.size();
4516
4517
Rect2i viewport_rect(viewport_offset, viewport_size);
4518
draw_graph.add_draw_list_set_viewport(viewport_rect);
4519
draw_graph.add_draw_list_set_scissor(viewport_rect);
4520
4521
return int64_t(ID_TYPE_DRAW_LIST) << ID_BASE_SHIFT;
4522
}
4523
4524
#ifndef DISABLE_DEPRECATED
4525
Error RenderingDevice::draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, DrawListID *r_split_ids, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region, const Vector<RID> &p_storage_textures) {
4526
ERR_FAIL_V_MSG(ERR_UNAVAILABLE, "Deprecated. Split draw lists are used automatically by RenderingDevice.");
4527
}
4528
#endif
4529
4530
void RenderingDevice::draw_list_set_blend_constants(DrawListID p_list, const Color &p_color) {
4531
ERR_RENDER_THREAD_GUARD();
4532
4533
ERR_FAIL_COND(!draw_list.active);
4534
4535
draw_graph.add_draw_list_set_blend_constants(p_color);
4536
}
4537
4538
void RenderingDevice::draw_list_bind_render_pipeline(DrawListID p_list, RID p_render_pipeline) {
4539
ERR_RENDER_THREAD_GUARD();
4540
4541
ERR_FAIL_COND(!draw_list.active);
4542
4543
const RenderPipeline *pipeline = render_pipeline_owner.get_or_null(p_render_pipeline);
4544
ERR_FAIL_NULL(pipeline);
4545
#ifdef DEBUG_ENABLED
4546
ERR_FAIL_COND(pipeline->validation.framebuffer_format != draw_list_framebuffer_format && pipeline->validation.render_pass != draw_list_current_subpass);
4547
#endif
4548
4549
if (p_render_pipeline == draw_list.state.pipeline) {
4550
return; // Redundant state, return.
4551
}
4552
4553
draw_list.state.pipeline = p_render_pipeline;
4554
4555
draw_graph.add_draw_list_bind_pipeline(pipeline->driver_id, pipeline->stage_bits);
4556
4557
if (draw_list.state.pipeline_shader != pipeline->shader) {
4558
// Shader changed, so descriptor sets may become incompatible.
4559
4560
uint32_t pcount = pipeline->set_formats.size(); // Formats count in this pipeline.
4561
draw_list.state.set_count = MAX(draw_list.state.set_count, pcount);
4562
const uint32_t *pformats = pipeline->set_formats.ptr(); // Pipeline set formats.
4563
4564
uint32_t first_invalid_set = UINT32_MAX; // All valid by default.
4565
if (pipeline->push_constant_size != draw_list.state.pipeline_push_constant_size) {
4566
// All sets must be invalidated as the pipeline layout is not compatible if the push constant range is different.
4567
draw_list.state.pipeline_push_constant_size = pipeline->push_constant_size;
4568
first_invalid_set = 0;
4569
} else {
4570
switch (driver->api_trait_get(RDD::API_TRAIT_SHADER_CHANGE_INVALIDATION)) {
4571
case RDD::SHADER_CHANGE_INVALIDATION_ALL_BOUND_UNIFORM_SETS: {
4572
first_invalid_set = 0;
4573
} break;
4574
case RDD::SHADER_CHANGE_INVALIDATION_INCOMPATIBLE_SETS_PLUS_CASCADE: {
4575
for (uint32_t i = 0; i < pcount; i++) {
4576
if (draw_list.state.sets[i].pipeline_expected_format != pformats[i]) {
4577
first_invalid_set = i;
4578
break;
4579
}
4580
}
4581
} break;
4582
case RDD::SHADER_CHANGE_INVALIDATION_ALL_OR_NONE_ACCORDING_TO_LAYOUT_HASH: {
4583
if (draw_list.state.pipeline_shader_layout_hash != pipeline->shader_layout_hash) {
4584
first_invalid_set = 0;
4585
}
4586
} break;
4587
}
4588
}
4589
4590
if (pipeline->push_constant_size) {
4591
#ifdef DEBUG_ENABLED
4592
draw_list.validation.pipeline_push_constant_supplied = false;
4593
#endif
4594
}
4595
4596
for (uint32_t i = 0; i < pcount; i++) {
4597
draw_list.state.sets[i].bound = draw_list.state.sets[i].bound && i < first_invalid_set;
4598
draw_list.state.sets[i].pipeline_expected_format = pformats[i];
4599
}
4600
4601
for (uint32_t i = pcount; i < draw_list.state.set_count; i++) {
4602
// Unbind the ones above (not used) if exist.
4603
draw_list.state.sets[i].bound = false;
4604
}
4605
4606
draw_list.state.set_count = pcount; // Update set count.
4607
4608
draw_list.state.pipeline_shader = pipeline->shader;
4609
draw_list.state.pipeline_shader_driver_id = pipeline->shader_driver_id;
4610
draw_list.state.pipeline_shader_layout_hash = pipeline->shader_layout_hash;
4611
}
4612
4613
#ifdef DEBUG_ENABLED
4614
// Update render pass pipeline info.
4615
draw_list.validation.pipeline_active = true;
4616
draw_list.validation.pipeline_dynamic_state = pipeline->validation.dynamic_state;
4617
draw_list.validation.pipeline_vertex_format = pipeline->validation.vertex_format;
4618
draw_list.validation.pipeline_uses_restart_indices = pipeline->validation.uses_restart_indices;
4619
draw_list.validation.pipeline_primitive_divisor = pipeline->validation.primitive_divisor;
4620
draw_list.validation.pipeline_primitive_minimum = pipeline->validation.primitive_minimum;
4621
draw_list.validation.pipeline_push_constant_size = pipeline->push_constant_size;
4622
#endif
4623
}
4624
4625
void RenderingDevice::draw_list_bind_uniform_set(DrawListID p_list, RID p_uniform_set, uint32_t p_index) {
4626
ERR_RENDER_THREAD_GUARD();
4627
4628
#ifdef DEBUG_ENABLED
4629
ERR_FAIL_COND_MSG(p_index >= driver->limit_get(LIMIT_MAX_BOUND_UNIFORM_SETS) || p_index >= MAX_UNIFORM_SETS,
4630
"Attempting to bind a descriptor set (" + itos(p_index) + ") greater than what the hardware supports (" + itos(driver->limit_get(LIMIT_MAX_BOUND_UNIFORM_SETS)) + ").");
4631
#endif
4632
4633
ERR_FAIL_COND(!draw_list.active);
4634
4635
const UniformSet *uniform_set = uniform_set_owner.get_or_null(p_uniform_set);
4636
ERR_FAIL_NULL(uniform_set);
4637
4638
if (p_index > draw_list.state.set_count) {
4639
draw_list.state.set_count = p_index;
4640
}
4641
4642
draw_list.state.sets[p_index].uniform_set_driver_id = uniform_set->driver_id; // Update set pointer.
4643
draw_list.state.sets[p_index].bound = false; // Needs rebind.
4644
draw_list.state.sets[p_index].uniform_set_format = uniform_set->format;
4645
draw_list.state.sets[p_index].uniform_set = p_uniform_set;
4646
4647
#ifdef DEBUG_ENABLED
4648
{ // Validate that textures bound are not attached as framebuffer bindings.
4649
uint32_t attachable_count = uniform_set->attachable_textures.size();
4650
const UniformSet::AttachableTexture *attachable_ptr = uniform_set->attachable_textures.ptr();
4651
uint32_t bound_count = draw_list_bound_textures.size();
4652
const RID *bound_ptr = draw_list_bound_textures.ptr();
4653
for (uint32_t i = 0; i < attachable_count; i++) {
4654
for (uint32_t j = 0; j < bound_count; j++) {
4655
ERR_FAIL_COND_MSG(attachable_ptr[i].texture == bound_ptr[j],
4656
"Attempted to use the same texture in framebuffer attachment and a uniform (set: " + itos(p_index) + ", binding: " + itos(attachable_ptr[i].bind) + "), this is not allowed.");
4657
}
4658
}
4659
}
4660
#endif
4661
}
4662
4663
void RenderingDevice::draw_list_bind_vertex_array(DrawListID p_list, RID p_vertex_array) {
4664
ERR_RENDER_THREAD_GUARD();
4665
4666
ERR_FAIL_COND(!draw_list.active);
4667
4668
VertexArray *vertex_array = vertex_array_owner.get_or_null(p_vertex_array);
4669
ERR_FAIL_NULL(vertex_array);
4670
4671
if (draw_list.state.vertex_array == p_vertex_array) {
4672
return; // Already set.
4673
}
4674
4675
_check_transfer_worker_vertex_array(vertex_array);
4676
4677
draw_list.state.vertex_array = p_vertex_array;
4678
4679
#ifdef DEBUG_ENABLED
4680
draw_list.validation.vertex_format = vertex_array->description;
4681
draw_list.validation.vertex_max_instances_allowed = vertex_array->max_instances_allowed;
4682
#endif
4683
draw_list.validation.vertex_array_size = vertex_array->vertex_count;
4684
4685
draw_graph.add_draw_list_bind_vertex_buffers(vertex_array->buffers, vertex_array->offsets);
4686
4687
for (int i = 0; i < vertex_array->draw_trackers.size(); i++) {
4688
draw_graph.add_draw_list_usage(vertex_array->draw_trackers[i], RDG::RESOURCE_USAGE_VERTEX_BUFFER_READ);
4689
}
4690
}
4691
4692
void RenderingDevice::draw_list_bind_index_array(DrawListID p_list, RID p_index_array) {
4693
ERR_RENDER_THREAD_GUARD();
4694
4695
ERR_FAIL_COND(!draw_list.active);
4696
4697
IndexArray *index_array = index_array_owner.get_or_null(p_index_array);
4698
ERR_FAIL_NULL(index_array);
4699
4700
if (draw_list.state.index_array == p_index_array) {
4701
return; // Already set.
4702
}
4703
4704
_check_transfer_worker_index_array(index_array);
4705
4706
draw_list.state.index_array = p_index_array;
4707
#ifdef DEBUG_ENABLED
4708
draw_list.validation.index_array_max_index = index_array->max_index;
4709
#endif
4710
draw_list.validation.index_array_count = index_array->indices;
4711
4712
const uint64_t offset_bytes = index_array->offset * (index_array->format == INDEX_BUFFER_FORMAT_UINT16 ? sizeof(uint16_t) : sizeof(uint32_t));
4713
draw_graph.add_draw_list_bind_index_buffer(index_array->driver_id, index_array->format, offset_bytes);
4714
4715
if (index_array->draw_tracker != nullptr) {
4716
draw_graph.add_draw_list_usage(index_array->draw_tracker, RDG::RESOURCE_USAGE_INDEX_BUFFER_READ);
4717
}
4718
}
4719
4720
void RenderingDevice::draw_list_set_line_width(DrawListID p_list, float p_width) {
4721
ERR_RENDER_THREAD_GUARD();
4722
4723
ERR_FAIL_COND(!draw_list.active);
4724
4725
draw_graph.add_draw_list_set_line_width(p_width);
4726
}
4727
4728
void RenderingDevice::draw_list_set_push_constant(DrawListID p_list, const void *p_data, uint32_t p_data_size) {
4729
ERR_RENDER_THREAD_GUARD();
4730
4731
ERR_FAIL_COND(!draw_list.active);
4732
4733
#ifdef DEBUG_ENABLED
4734
ERR_FAIL_COND_MSG(p_data_size != draw_list.validation.pipeline_push_constant_size,
4735
"This render pipeline requires (" + itos(draw_list.validation.pipeline_push_constant_size) + ") bytes of push constant data, supplied: (" + itos(p_data_size) + ")");
4736
#endif
4737
4738
draw_graph.add_draw_list_set_push_constant(draw_list.state.pipeline_shader_driver_id, p_data, p_data_size);
4739
4740
#ifdef DEBUG_ENABLED
4741
draw_list.validation.pipeline_push_constant_supplied = true;
4742
#endif
4743
}
4744
4745
void RenderingDevice::draw_list_draw(DrawListID p_list, bool p_use_indices, uint32_t p_instances, uint32_t p_procedural_vertices) {
4746
ERR_RENDER_THREAD_GUARD();
4747
4748
ERR_FAIL_COND(!draw_list.active);
4749
4750
#ifdef DEBUG_ENABLED
4751
ERR_FAIL_COND_MSG(!draw_list.validation.pipeline_active,
4752
"No render pipeline was set before attempting to draw.");
4753
if (draw_list.validation.pipeline_vertex_format != INVALID_ID) {
4754
// Pipeline uses vertices, validate format.
4755
ERR_FAIL_COND_MSG(draw_list.validation.vertex_format == INVALID_ID,
4756
"No vertex array was bound, and render pipeline expects vertices.");
4757
// Make sure format is right.
4758
ERR_FAIL_COND_MSG(draw_list.validation.pipeline_vertex_format != draw_list.validation.vertex_format,
4759
"The vertex format used to create the pipeline does not match the vertex format bound.");
4760
// Make sure number of instances is valid.
4761
ERR_FAIL_COND_MSG(p_instances > draw_list.validation.vertex_max_instances_allowed,
4762
"Number of instances requested (" + itos(p_instances) + " is larger than the maximum number supported by the bound vertex array (" + itos(draw_list.validation.vertex_max_instances_allowed) + ").");
4763
}
4764
4765
if (draw_list.validation.pipeline_push_constant_size > 0) {
4766
// Using push constants, check that they were supplied.
4767
ERR_FAIL_COND_MSG(!draw_list.validation.pipeline_push_constant_supplied,
4768
"The shader in this pipeline requires a push constant to be set before drawing, but it's not present.");
4769
}
4770
4771
#endif
4772
4773
#ifdef DEBUG_ENABLED
4774
for (uint32_t i = 0; i < draw_list.state.set_count; i++) {
4775
if (draw_list.state.sets[i].pipeline_expected_format == 0) {
4776
// Nothing expected by this pipeline.
4777
continue;
4778
}
4779
4780
if (draw_list.state.sets[i].pipeline_expected_format != draw_list.state.sets[i].uniform_set_format) {
4781
if (draw_list.state.sets[i].uniform_set_format == 0) {
4782
ERR_FAIL_MSG("Uniforms were never supplied for set (" + itos(i) + ") at the time of drawing, which are required by the pipeline.");
4783
} else if (uniform_set_owner.owns(draw_list.state.sets[i].uniform_set)) {
4784
UniformSet *us = uniform_set_owner.get_or_null(draw_list.state.sets[i].uniform_set);
4785
ERR_FAIL_MSG("Uniforms supplied for set (" + itos(i) + "):\n" + _shader_uniform_debug(us->shader_id, us->shader_set) + "\nare not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n" + _shader_uniform_debug(draw_list.state.pipeline_shader));
4786
} else {
4787
ERR_FAIL_MSG("Uniforms supplied for set (" + itos(i) + ", which was just freed) are not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n" + _shader_uniform_debug(draw_list.state.pipeline_shader));
4788
}
4789
}
4790
}
4791
#endif
4792
thread_local LocalVector<RDD::UniformSetID> valid_descriptor_ids;
4793
valid_descriptor_ids.clear();
4794
valid_descriptor_ids.resize(draw_list.state.set_count);
4795
uint32_t valid_set_count = 0;
4796
uint32_t first_set_index = 0;
4797
uint32_t last_set_index = 0;
4798
bool found_first_set = false;
4799
4800
for (uint32_t i = 0; i < draw_list.state.set_count; i++) {
4801
if (draw_list.state.sets[i].pipeline_expected_format == 0) {
4802
continue; // Nothing expected by this pipeline.
4803
}
4804
4805
if (!draw_list.state.sets[i].bound && !found_first_set) {
4806
first_set_index = i;
4807
found_first_set = true;
4808
}
4809
// Prepare descriptor sets if the API doesn't use pipeline barriers.
4810
if (!driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) {
4811
draw_graph.add_draw_list_uniform_set_prepare_for_use(draw_list.state.pipeline_shader_driver_id, draw_list.state.sets[i].uniform_set_driver_id, i);
4812
}
4813
}
4814
4815
// Bind descriptor sets.
4816
for (uint32_t i = first_set_index; i < draw_list.state.set_count; i++) {
4817
if (draw_list.state.sets[i].pipeline_expected_format == 0) {
4818
continue; // Nothing expected by this pipeline.
4819
}
4820
4821
if (!draw_list.state.sets[i].bound) {
4822
// Batch contiguous descriptor sets in a single call.
4823
if (descriptor_set_batching) {
4824
// All good, see if this requires re-binding.
4825
if (i - last_set_index > 1) {
4826
// If the descriptor sets are not contiguous, bind the previous ones and start a new batch.
4827
draw_graph.add_draw_list_bind_uniform_sets(draw_list.state.pipeline_shader_driver_id, valid_descriptor_ids, first_set_index, valid_set_count);
4828
4829
first_set_index = i;
4830
valid_set_count = 1;
4831
valid_descriptor_ids[0] = draw_list.state.sets[i].uniform_set_driver_id;
4832
} else {
4833
// Otherwise, keep storing in the current batch.
4834
valid_descriptor_ids[valid_set_count] = draw_list.state.sets[i].uniform_set_driver_id;
4835
valid_set_count++;
4836
}
4837
4838
UniformSet *uniform_set = uniform_set_owner.get_or_null(draw_list.state.sets[i].uniform_set);
4839
_uniform_set_update_shared(uniform_set);
4840
draw_graph.add_draw_list_usages(uniform_set->draw_trackers, uniform_set->draw_trackers_usage);
4841
draw_list.state.sets[i].bound = true;
4842
4843
last_set_index = i;
4844
} else {
4845
draw_graph.add_draw_list_bind_uniform_set(draw_list.state.pipeline_shader_driver_id, draw_list.state.sets[i].uniform_set_driver_id, i);
4846
}
4847
}
4848
}
4849
4850
// Bind the remaining batch.
4851
if (descriptor_set_batching && valid_set_count > 0) {
4852
draw_graph.add_draw_list_bind_uniform_sets(draw_list.state.pipeline_shader_driver_id, valid_descriptor_ids, first_set_index, valid_set_count);
4853
}
4854
4855
if (p_use_indices) {
4856
#ifdef DEBUG_ENABLED
4857
ERR_FAIL_COND_MSG(p_procedural_vertices > 0,
4858
"Procedural vertices can't be used together with indices.");
4859
4860
ERR_FAIL_COND_MSG(!draw_list.validation.index_array_count,
4861
"Draw command requested indices, but no index buffer was set.");
4862
4863
ERR_FAIL_COND_MSG(draw_list.validation.pipeline_uses_restart_indices != draw_list.validation.index_buffer_uses_restart_indices,
4864
"The usage of restart indices in index buffer does not match the render primitive in the pipeline.");
4865
#endif
4866
uint32_t to_draw = draw_list.validation.index_array_count;
4867
4868
#ifdef DEBUG_ENABLED
4869
ERR_FAIL_COND_MSG(to_draw < draw_list.validation.pipeline_primitive_minimum,
4870
"Too few indices (" + itos(to_draw) + ") for the render primitive set in the render pipeline (" + itos(draw_list.validation.pipeline_primitive_minimum) + ").");
4871
4872
ERR_FAIL_COND_MSG((to_draw % draw_list.validation.pipeline_primitive_divisor) != 0,
4873
"Index amount (" + itos(to_draw) + ") must be a multiple of the amount of indices required by the render primitive (" + itos(draw_list.validation.pipeline_primitive_divisor) + ").");
4874
#endif
4875
4876
draw_graph.add_draw_list_draw_indexed(to_draw, p_instances, 0);
4877
} else {
4878
uint32_t to_draw;
4879
4880
if (p_procedural_vertices > 0) {
4881
#ifdef DEBUG_ENABLED
4882
ERR_FAIL_COND_MSG(draw_list.validation.pipeline_vertex_format != INVALID_ID,
4883
"Procedural vertices requested, but pipeline expects a vertex array.");
4884
#endif
4885
to_draw = p_procedural_vertices;
4886
} else {
4887
#ifdef DEBUG_ENABLED
4888
ERR_FAIL_COND_MSG(draw_list.validation.pipeline_vertex_format == INVALID_ID,
4889
"Draw command lacks indices, but pipeline format does not use vertices.");
4890
#endif
4891
to_draw = draw_list.validation.vertex_array_size;
4892
}
4893
4894
#ifdef DEBUG_ENABLED
4895
ERR_FAIL_COND_MSG(to_draw < draw_list.validation.pipeline_primitive_minimum,
4896
"Too few vertices (" + itos(to_draw) + ") for the render primitive set in the render pipeline (" + itos(draw_list.validation.pipeline_primitive_minimum) + ").");
4897
4898
ERR_FAIL_COND_MSG((to_draw % draw_list.validation.pipeline_primitive_divisor) != 0,
4899
"Vertex amount (" + itos(to_draw) + ") must be a multiple of the amount of vertices required by the render primitive (" + itos(draw_list.validation.pipeline_primitive_divisor) + ").");
4900
#endif
4901
4902
draw_graph.add_draw_list_draw(to_draw, p_instances);
4903
}
4904
4905
draw_list.state.draw_count++;
4906
}
4907
4908
void RenderingDevice::draw_list_draw_indirect(DrawListID p_list, bool p_use_indices, RID p_buffer, uint32_t p_offset, uint32_t p_draw_count, uint32_t p_stride) {
4909
ERR_RENDER_THREAD_GUARD();
4910
4911
ERR_FAIL_COND(!draw_list.active);
4912
4913
Buffer *buffer = storage_buffer_owner.get_or_null(p_buffer);
4914
ERR_FAIL_NULL(buffer);
4915
4916
ERR_FAIL_COND_MSG(!buffer->usage.has_flag(RDD::BUFFER_USAGE_INDIRECT_BIT), "Buffer provided was not created to do indirect dispatch.");
4917
4918
#ifdef DEBUG_ENABLED
4919
ERR_FAIL_COND_MSG(!draw_list.validation.pipeline_active,
4920
"No render pipeline was set before attempting to draw.");
4921
if (draw_list.validation.pipeline_vertex_format != INVALID_ID) {
4922
// Pipeline uses vertices, validate format.
4923
ERR_FAIL_COND_MSG(draw_list.validation.vertex_format == INVALID_ID,
4924
"No vertex array was bound, and render pipeline expects vertices.");
4925
// Make sure format is right.
4926
ERR_FAIL_COND_MSG(draw_list.validation.pipeline_vertex_format != draw_list.validation.vertex_format,
4927
"The vertex format used to create the pipeline does not match the vertex format bound.");
4928
}
4929
4930
if (draw_list.validation.pipeline_push_constant_size > 0) {
4931
// Using push constants, check that they were supplied.
4932
ERR_FAIL_COND_MSG(!draw_list.validation.pipeline_push_constant_supplied,
4933
"The shader in this pipeline requires a push constant to be set before drawing, but it's not present.");
4934
}
4935
#endif
4936
4937
#ifdef DEBUG_ENABLED
4938
for (uint32_t i = 0; i < draw_list.state.set_count; i++) {
4939
if (draw_list.state.sets[i].pipeline_expected_format == 0) {
4940
// Nothing expected by this pipeline.
4941
continue;
4942
}
4943
4944
if (draw_list.state.sets[i].pipeline_expected_format != draw_list.state.sets[i].uniform_set_format) {
4945
if (draw_list.state.sets[i].uniform_set_format == 0) {
4946
ERR_FAIL_MSG(vformat("Uniforms were never supplied for set (%d) at the time of drawing, which are required by the pipeline.", i));
4947
} else if (uniform_set_owner.owns(draw_list.state.sets[i].uniform_set)) {
4948
UniformSet *us = uniform_set_owner.get_or_null(draw_list.state.sets[i].uniform_set);
4949
ERR_FAIL_MSG(vformat("Uniforms supplied for set (%d):\n%s\nare not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n%s", i, _shader_uniform_debug(us->shader_id, us->shader_set), _shader_uniform_debug(draw_list.state.pipeline_shader)));
4950
} else {
4951
ERR_FAIL_MSG(vformat("Uniforms supplied for set (%s, which was just freed) are not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n%s", i, _shader_uniform_debug(draw_list.state.pipeline_shader)));
4952
}
4953
}
4954
}
4955
#endif
4956
4957
// Prepare descriptor sets if the API doesn't use pipeline barriers.
4958
if (!driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) {
4959
for (uint32_t i = 0; i < draw_list.state.set_count; i++) {
4960
if (draw_list.state.sets[i].pipeline_expected_format == 0) {
4961
// Nothing expected by this pipeline.
4962
continue;
4963
}
4964
4965
draw_graph.add_draw_list_uniform_set_prepare_for_use(draw_list.state.pipeline_shader_driver_id, draw_list.state.sets[i].uniform_set_driver_id, i);
4966
}
4967
}
4968
4969
// Bind descriptor sets.
4970
for (uint32_t i = 0; i < draw_list.state.set_count; i++) {
4971
if (draw_list.state.sets[i].pipeline_expected_format == 0) {
4972
continue; // Nothing expected by this pipeline.
4973
}
4974
if (!draw_list.state.sets[i].bound) {
4975
// All good, see if this requires re-binding.
4976
draw_graph.add_draw_list_bind_uniform_set(draw_list.state.pipeline_shader_driver_id, draw_list.state.sets[i].uniform_set_driver_id, i);
4977
4978
UniformSet *uniform_set = uniform_set_owner.get_or_null(draw_list.state.sets[i].uniform_set);
4979
_uniform_set_update_shared(uniform_set);
4980
4981
draw_graph.add_draw_list_usages(uniform_set->draw_trackers, uniform_set->draw_trackers_usage);
4982
4983
draw_list.state.sets[i].bound = true;
4984
}
4985
}
4986
4987
if (p_use_indices) {
4988
#ifdef DEBUG_ENABLED
4989
ERR_FAIL_COND_MSG(!draw_list.validation.index_array_count,
4990
"Draw command requested indices, but no index buffer was set.");
4991
4992
ERR_FAIL_COND_MSG(draw_list.validation.pipeline_uses_restart_indices != draw_list.validation.index_buffer_uses_restart_indices,
4993
"The usage of restart indices in index buffer does not match the render primitive in the pipeline.");
4994
#endif
4995
4996
ERR_FAIL_COND_MSG(p_offset + 20 > buffer->size, "Offset provided (+20) is past the end of buffer.");
4997
4998
draw_graph.add_draw_list_draw_indexed_indirect(buffer->driver_id, p_offset, p_draw_count, p_stride);
4999
} else {
5000
ERR_FAIL_COND_MSG(p_offset + 16 > buffer->size, "Offset provided (+16) is past the end of buffer.");
5001
5002
draw_graph.add_draw_list_draw_indirect(buffer->driver_id, p_offset, p_draw_count, p_stride);
5003
}
5004
5005
draw_list.state.draw_count++;
5006
5007
if (buffer->draw_tracker != nullptr) {
5008
draw_graph.add_draw_list_usage(buffer->draw_tracker, RDG::RESOURCE_USAGE_INDIRECT_BUFFER_READ);
5009
}
5010
5011
_check_transfer_worker_buffer(buffer);
5012
}
5013
5014
void RenderingDevice::draw_list_set_viewport(DrawListID p_list, const Rect2 &p_rect) {
5015
ERR_FAIL_COND(!draw_list.active);
5016
5017
if (p_rect.get_area() == 0) {
5018
return;
5019
}
5020
5021
draw_list.viewport = p_rect;
5022
draw_graph.add_draw_list_set_viewport(p_rect);
5023
}
5024
5025
void RenderingDevice::draw_list_enable_scissor(DrawListID p_list, const Rect2 &p_rect) {
5026
ERR_RENDER_THREAD_GUARD();
5027
5028
ERR_FAIL_COND(!draw_list.active);
5029
5030
Rect2i rect = p_rect;
5031
rect.position += draw_list.viewport.position;
5032
5033
rect = draw_list.viewport.intersection(rect);
5034
5035
if (rect.get_area() == 0) {
5036
return;
5037
}
5038
5039
draw_graph.add_draw_list_set_scissor(rect);
5040
}
5041
5042
void RenderingDevice::draw_list_disable_scissor(DrawListID p_list) {
5043
ERR_RENDER_THREAD_GUARD();
5044
5045
ERR_FAIL_COND(!draw_list.active);
5046
5047
draw_graph.add_draw_list_set_scissor(draw_list.viewport);
5048
}
5049
5050
uint32_t RenderingDevice::draw_list_get_current_pass() {
5051
ERR_RENDER_THREAD_GUARD_V(0);
5052
5053
return draw_list_current_subpass;
5054
}
5055
5056
RenderingDevice::DrawListID RenderingDevice::draw_list_switch_to_next_pass() {
5057
ERR_RENDER_THREAD_GUARD_V(INVALID_ID);
5058
5059
ERR_FAIL_COND_V(!draw_list.active, INVALID_FORMAT_ID);
5060
ERR_FAIL_COND_V(draw_list_current_subpass >= draw_list_subpass_count - 1, INVALID_FORMAT_ID);
5061
5062
draw_list_current_subpass++;
5063
5064
Rect2i viewport;
5065
_draw_list_end(&viewport);
5066
5067
draw_graph.add_draw_list_next_subpass(RDD::COMMAND_BUFFER_TYPE_PRIMARY);
5068
5069
_draw_list_start(viewport);
5070
5071
return int64_t(ID_TYPE_DRAW_LIST) << ID_BASE_SHIFT;
5072
}
5073
5074
#ifndef DISABLE_DEPRECATED
5075
Error RenderingDevice::draw_list_switch_to_next_pass_split(uint32_t p_splits, DrawListID *r_split_ids) {
5076
ERR_FAIL_V_MSG(ERR_UNAVAILABLE, "Deprecated. Split draw lists are used automatically by RenderingDevice.");
5077
}
5078
#endif
5079
5080
void RenderingDevice::_draw_list_start(const Rect2i &p_viewport) {
5081
draw_list.viewport = p_viewport;
5082
draw_list.active = true;
5083
}
5084
5085
void RenderingDevice::_draw_list_end(Rect2i *r_last_viewport) {
5086
if (r_last_viewport) {
5087
*r_last_viewport = draw_list.viewport;
5088
}
5089
5090
draw_list = DrawList();
5091
}
5092
5093
void RenderingDevice::draw_list_end() {
5094
ERR_RENDER_THREAD_GUARD();
5095
5096
ERR_FAIL_COND_MSG(!draw_list.active, "Immediate draw list is already inactive.");
5097
5098
draw_graph.add_draw_list_end();
5099
5100
_draw_list_end();
5101
5102
for (uint32_t i = 0; i < draw_list_bound_textures.size(); i++) {
5103
Texture *texture = texture_owner.get_or_null(draw_list_bound_textures[i]);
5104
ERR_CONTINUE(!texture); // Wtf.
5105
if (texture->usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
5106
texture->bound = false;
5107
}
5108
if (texture->usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
5109
texture->bound = false;
5110
}
5111
}
5112
5113
draw_list_bound_textures.clear();
5114
}
5115
5116
/***********************/
5117
/**** COMPUTE LISTS ****/
5118
/***********************/
5119
5120
RenderingDevice::ComputeListID RenderingDevice::compute_list_begin() {
5121
ERR_RENDER_THREAD_GUARD_V(INVALID_ID);
5122
5123
ERR_FAIL_COND_V_MSG(compute_list.active, INVALID_ID, "Only one draw/compute list can be active at the same time.");
5124
5125
compute_list.active = true;
5126
5127
draw_graph.add_compute_list_begin();
5128
5129
return ID_TYPE_COMPUTE_LIST;
5130
}
5131
5132
void RenderingDevice::compute_list_bind_compute_pipeline(ComputeListID p_list, RID p_compute_pipeline) {
5133
ERR_RENDER_THREAD_GUARD();
5134
5135
ERR_FAIL_COND(p_list != ID_TYPE_COMPUTE_LIST);
5136
ERR_FAIL_COND(!compute_list.active);
5137
5138
const ComputePipeline *pipeline = compute_pipeline_owner.get_or_null(p_compute_pipeline);
5139
ERR_FAIL_NULL(pipeline);
5140
5141
if (p_compute_pipeline == compute_list.state.pipeline) {
5142
return; // Redundant state, return.
5143
}
5144
5145
compute_list.state.pipeline = p_compute_pipeline;
5146
5147
draw_graph.add_compute_list_bind_pipeline(pipeline->driver_id);
5148
5149
if (compute_list.state.pipeline_shader != pipeline->shader) {
5150
// Shader changed, so descriptor sets may become incompatible.
5151
5152
uint32_t pcount = pipeline->set_formats.size(); // Formats count in this pipeline.
5153
compute_list.state.set_count = MAX(compute_list.state.set_count, pcount);
5154
const uint32_t *pformats = pipeline->set_formats.ptr(); // Pipeline set formats.
5155
5156
uint32_t first_invalid_set = UINT32_MAX; // All valid by default.
5157
switch (driver->api_trait_get(RDD::API_TRAIT_SHADER_CHANGE_INVALIDATION)) {
5158
case RDD::SHADER_CHANGE_INVALIDATION_ALL_BOUND_UNIFORM_SETS: {
5159
first_invalid_set = 0;
5160
} break;
5161
case RDD::SHADER_CHANGE_INVALIDATION_INCOMPATIBLE_SETS_PLUS_CASCADE: {
5162
for (uint32_t i = 0; i < pcount; i++) {
5163
if (compute_list.state.sets[i].pipeline_expected_format != pformats[i]) {
5164
first_invalid_set = i;
5165
break;
5166
}
5167
}
5168
} break;
5169
case RDD::SHADER_CHANGE_INVALIDATION_ALL_OR_NONE_ACCORDING_TO_LAYOUT_HASH: {
5170
if (compute_list.state.pipeline_shader_layout_hash != pipeline->shader_layout_hash) {
5171
first_invalid_set = 0;
5172
}
5173
} break;
5174
}
5175
5176
for (uint32_t i = 0; i < pcount; i++) {
5177
compute_list.state.sets[i].bound = compute_list.state.sets[i].bound && i < first_invalid_set;
5178
compute_list.state.sets[i].pipeline_expected_format = pformats[i];
5179
}
5180
5181
for (uint32_t i = pcount; i < compute_list.state.set_count; i++) {
5182
// Unbind the ones above (not used) if exist.
5183
compute_list.state.sets[i].bound = false;
5184
}
5185
5186
compute_list.state.set_count = pcount; // Update set count.
5187
5188
if (pipeline->push_constant_size) {
5189
#ifdef DEBUG_ENABLED
5190
compute_list.validation.pipeline_push_constant_supplied = false;
5191
#endif
5192
}
5193
5194
compute_list.state.pipeline_shader = pipeline->shader;
5195
compute_list.state.pipeline_shader_driver_id = pipeline->shader_driver_id;
5196
compute_list.state.pipeline_shader_layout_hash = pipeline->shader_layout_hash;
5197
compute_list.state.local_group_size[0] = pipeline->local_group_size[0];
5198
compute_list.state.local_group_size[1] = pipeline->local_group_size[1];
5199
compute_list.state.local_group_size[2] = pipeline->local_group_size[2];
5200
}
5201
5202
#ifdef DEBUG_ENABLED
5203
// Update compute pass pipeline info.
5204
compute_list.validation.pipeline_active = true;
5205
compute_list.validation.pipeline_push_constant_size = pipeline->push_constant_size;
5206
#endif
5207
}
5208
5209
void RenderingDevice::compute_list_bind_uniform_set(ComputeListID p_list, RID p_uniform_set, uint32_t p_index) {
5210
ERR_RENDER_THREAD_GUARD();
5211
5212
ERR_FAIL_COND(p_list != ID_TYPE_COMPUTE_LIST);
5213
ERR_FAIL_COND(!compute_list.active);
5214
5215
#ifdef DEBUG_ENABLED
5216
ERR_FAIL_COND_MSG(p_index >= driver->limit_get(LIMIT_MAX_BOUND_UNIFORM_SETS) || p_index >= MAX_UNIFORM_SETS,
5217
"Attempting to bind a descriptor set (" + itos(p_index) + ") greater than what the hardware supports (" + itos(driver->limit_get(LIMIT_MAX_BOUND_UNIFORM_SETS)) + ").");
5218
#endif
5219
5220
UniformSet *uniform_set = uniform_set_owner.get_or_null(p_uniform_set);
5221
ERR_FAIL_NULL(uniform_set);
5222
5223
if (p_index > compute_list.state.set_count) {
5224
compute_list.state.set_count = p_index;
5225
}
5226
5227
compute_list.state.sets[p_index].uniform_set_driver_id = uniform_set->driver_id; // Update set pointer.
5228
compute_list.state.sets[p_index].bound = false; // Needs rebind.
5229
compute_list.state.sets[p_index].uniform_set_format = uniform_set->format;
5230
compute_list.state.sets[p_index].uniform_set = p_uniform_set;
5231
5232
#if 0
5233
{ // Validate that textures bound are not attached as framebuffer bindings.
5234
uint32_t attachable_count = uniform_set->attachable_textures.size();
5235
const RID *attachable_ptr = uniform_set->attachable_textures.ptr();
5236
uint32_t bound_count = draw_list_bound_textures.size();
5237
const RID *bound_ptr = draw_list_bound_textures.ptr();
5238
for (uint32_t i = 0; i < attachable_count; i++) {
5239
for (uint32_t j = 0; j < bound_count; j++) {
5240
ERR_FAIL_COND_MSG(attachable_ptr[i] == bound_ptr[j],
5241
"Attempted to use the same texture in framebuffer attachment and a uniform set, this is not allowed.");
5242
}
5243
}
5244
}
5245
#endif
5246
}
5247
5248
void RenderingDevice::compute_list_set_push_constant(ComputeListID p_list, const void *p_data, uint32_t p_data_size) {
5249
ERR_RENDER_THREAD_GUARD();
5250
5251
ERR_FAIL_COND(p_list != ID_TYPE_COMPUTE_LIST);
5252
ERR_FAIL_COND(!compute_list.active);
5253
ERR_FAIL_COND_MSG(p_data_size > MAX_PUSH_CONSTANT_SIZE, "Push constants can't be bigger than 128 bytes to maintain compatibility.");
5254
5255
#ifdef DEBUG_ENABLED
5256
ERR_FAIL_COND_MSG(p_data_size != compute_list.validation.pipeline_push_constant_size,
5257
"This compute pipeline requires (" + itos(compute_list.validation.pipeline_push_constant_size) + ") bytes of push constant data, supplied: (" + itos(p_data_size) + ")");
5258
#endif
5259
5260
draw_graph.add_compute_list_set_push_constant(compute_list.state.pipeline_shader_driver_id, p_data, p_data_size);
5261
5262
// Store it in the state in case we need to restart the compute list.
5263
memcpy(compute_list.state.push_constant_data, p_data, p_data_size);
5264
compute_list.state.push_constant_size = p_data_size;
5265
5266
#ifdef DEBUG_ENABLED
5267
compute_list.validation.pipeline_push_constant_supplied = true;
5268
#endif
5269
}
5270
5271
void RenderingDevice::compute_list_dispatch(ComputeListID p_list, uint32_t p_x_groups, uint32_t p_y_groups, uint32_t p_z_groups) {
5272
ERR_RENDER_THREAD_GUARD();
5273
5274
ERR_FAIL_COND(p_list != ID_TYPE_COMPUTE_LIST);
5275
ERR_FAIL_COND(!compute_list.active);
5276
5277
#ifdef DEBUG_ENABLED
5278
ERR_FAIL_COND_MSG(p_x_groups == 0, "Dispatch amount of X compute groups (" + itos(p_x_groups) + ") is zero.");
5279
ERR_FAIL_COND_MSG(p_z_groups == 0, "Dispatch amount of Z compute groups (" + itos(p_z_groups) + ") is zero.");
5280
ERR_FAIL_COND_MSG(p_y_groups == 0, "Dispatch amount of Y compute groups (" + itos(p_y_groups) + ") is zero.");
5281
ERR_FAIL_COND_MSG(p_x_groups > driver->limit_get(LIMIT_MAX_COMPUTE_WORKGROUP_COUNT_X),
5282
"Dispatch amount of X compute groups (" + itos(p_x_groups) + ") is larger than device limit (" + itos(driver->limit_get(LIMIT_MAX_COMPUTE_WORKGROUP_COUNT_X)) + ")");
5283
ERR_FAIL_COND_MSG(p_y_groups > driver->limit_get(LIMIT_MAX_COMPUTE_WORKGROUP_COUNT_Y),
5284
"Dispatch amount of Y compute groups (" + itos(p_y_groups) + ") is larger than device limit (" + itos(driver->limit_get(LIMIT_MAX_COMPUTE_WORKGROUP_COUNT_Y)) + ")");
5285
ERR_FAIL_COND_MSG(p_z_groups > driver->limit_get(LIMIT_MAX_COMPUTE_WORKGROUP_COUNT_Z),
5286
"Dispatch amount of Z compute groups (" + itos(p_z_groups) + ") is larger than device limit (" + itos(driver->limit_get(LIMIT_MAX_COMPUTE_WORKGROUP_COUNT_Z)) + ")");
5287
#endif
5288
5289
#ifdef DEBUG_ENABLED
5290
5291
ERR_FAIL_COND_MSG(!compute_list.validation.pipeline_active, "No compute pipeline was set before attempting to draw.");
5292
5293
if (compute_list.validation.pipeline_push_constant_size > 0) {
5294
// Using push constants, check that they were supplied.
5295
ERR_FAIL_COND_MSG(!compute_list.validation.pipeline_push_constant_supplied,
5296
"The shader in this pipeline requires a push constant to be set before drawing, but it's not present.");
5297
}
5298
5299
#endif
5300
5301
#ifdef DEBUG_ENABLED
5302
for (uint32_t i = 0; i < compute_list.state.set_count; i++) {
5303
if (compute_list.state.sets[i].pipeline_expected_format == 0) {
5304
// Nothing expected by this pipeline.
5305
continue;
5306
}
5307
5308
if (compute_list.state.sets[i].pipeline_expected_format != compute_list.state.sets[i].uniform_set_format) {
5309
if (compute_list.state.sets[i].uniform_set_format == 0) {
5310
ERR_FAIL_MSG("Uniforms were never supplied for set (" + itos(i) + ") at the time of drawing, which are required by the pipeline.");
5311
} else if (uniform_set_owner.owns(compute_list.state.sets[i].uniform_set)) {
5312
UniformSet *us = uniform_set_owner.get_or_null(compute_list.state.sets[i].uniform_set);
5313
ERR_FAIL_MSG("Uniforms supplied for set (" + itos(i) + "):\n" + _shader_uniform_debug(us->shader_id, us->shader_set) + "\nare not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n" + _shader_uniform_debug(compute_list.state.pipeline_shader));
5314
} else {
5315
ERR_FAIL_MSG("Uniforms supplied for set (" + itos(i) + ", which was just freed) are not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n" + _shader_uniform_debug(compute_list.state.pipeline_shader));
5316
}
5317
}
5318
}
5319
#endif
5320
thread_local LocalVector<RDD::UniformSetID> valid_descriptor_ids;
5321
valid_descriptor_ids.clear();
5322
valid_descriptor_ids.resize(compute_list.state.set_count);
5323
5324
uint32_t valid_set_count = 0;
5325
uint32_t first_set_index = 0;
5326
uint32_t last_set_index = 0;
5327
bool found_first_set = false;
5328
5329
for (uint32_t i = 0; i < compute_list.state.set_count; i++) {
5330
if (compute_list.state.sets[i].pipeline_expected_format == 0) {
5331
// Nothing expected by this pipeline.
5332
continue;
5333
}
5334
5335
if (!compute_list.state.sets[i].bound && !found_first_set) {
5336
first_set_index = i;
5337
found_first_set = true;
5338
}
5339
// Prepare descriptor sets if the API doesn't use pipeline barriers.
5340
if (!driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) {
5341
draw_graph.add_compute_list_uniform_set_prepare_for_use(compute_list.state.pipeline_shader_driver_id, compute_list.state.sets[i].uniform_set_driver_id, i);
5342
}
5343
}
5344
5345
// Bind descriptor sets.
5346
for (uint32_t i = first_set_index; i < compute_list.state.set_count; i++) {
5347
if (compute_list.state.sets[i].pipeline_expected_format == 0) {
5348
continue; // Nothing expected by this pipeline.
5349
}
5350
5351
if (!compute_list.state.sets[i].bound) {
5352
// Descriptor set batching
5353
if (descriptor_set_batching) {
5354
// All good, see if this requires re-binding.
5355
if (i - last_set_index > 1) {
5356
// If the descriptor sets are not contiguous, bind the previous ones and start a new batch.
5357
draw_graph.add_compute_list_bind_uniform_sets(compute_list.state.pipeline_shader_driver_id, valid_descriptor_ids, first_set_index, valid_set_count);
5358
5359
first_set_index = i;
5360
valid_set_count = 1;
5361
valid_descriptor_ids[0] = compute_list.state.sets[i].uniform_set_driver_id;
5362
} else {
5363
// Otherwise, keep storing in the current batch.
5364
valid_descriptor_ids[valid_set_count] = compute_list.state.sets[i].uniform_set_driver_id;
5365
valid_set_count++;
5366
}
5367
5368
last_set_index = i;
5369
} else {
5370
draw_graph.add_compute_list_bind_uniform_set(compute_list.state.pipeline_shader_driver_id, compute_list.state.sets[i].uniform_set_driver_id, i);
5371
}
5372
UniformSet *uniform_set = uniform_set_owner.get_or_null(compute_list.state.sets[i].uniform_set);
5373
_uniform_set_update_shared(uniform_set);
5374
5375
draw_graph.add_compute_list_usages(uniform_set->draw_trackers, uniform_set->draw_trackers_usage);
5376
compute_list.state.sets[i].bound = true;
5377
}
5378
}
5379
5380
// Bind the remaining batch.
5381
if (valid_set_count > 0) {
5382
draw_graph.add_compute_list_bind_uniform_sets(compute_list.state.pipeline_shader_driver_id, valid_descriptor_ids, first_set_index, valid_set_count);
5383
}
5384
draw_graph.add_compute_list_dispatch(p_x_groups, p_y_groups, p_z_groups);
5385
compute_list.state.dispatch_count++;
5386
}
5387
5388
void RenderingDevice::compute_list_dispatch_threads(ComputeListID p_list, uint32_t p_x_threads, uint32_t p_y_threads, uint32_t p_z_threads) {
5389
ERR_RENDER_THREAD_GUARD();
5390
5391
ERR_FAIL_COND(p_list != ID_TYPE_COMPUTE_LIST);
5392
ERR_FAIL_COND(!compute_list.active);
5393
5394
#ifdef DEBUG_ENABLED
5395
ERR_FAIL_COND_MSG(p_x_threads == 0, "Dispatch amount of X compute threads (" + itos(p_x_threads) + ") is zero.");
5396
ERR_FAIL_COND_MSG(p_y_threads == 0, "Dispatch amount of Y compute threads (" + itos(p_y_threads) + ") is zero.");
5397
ERR_FAIL_COND_MSG(p_z_threads == 0, "Dispatch amount of Z compute threads (" + itos(p_z_threads) + ") is zero.");
5398
#endif
5399
5400
#ifdef DEBUG_ENABLED
5401
5402
ERR_FAIL_COND_MSG(!compute_list.validation.pipeline_active, "No compute pipeline was set before attempting to draw.");
5403
5404
if (compute_list.validation.pipeline_push_constant_size > 0) {
5405
// Using push constants, check that they were supplied.
5406
ERR_FAIL_COND_MSG(!compute_list.validation.pipeline_push_constant_supplied,
5407
"The shader in this pipeline requires a push constant to be set before drawing, but it's not present.");
5408
}
5409
5410
#endif
5411
5412
compute_list_dispatch(p_list, Math::division_round_up(p_x_threads, compute_list.state.local_group_size[0]), Math::division_round_up(p_y_threads, compute_list.state.local_group_size[1]), Math::division_round_up(p_z_threads, compute_list.state.local_group_size[2]));
5413
}
5414
5415
void RenderingDevice::compute_list_dispatch_indirect(ComputeListID p_list, RID p_buffer, uint32_t p_offset) {
5416
ERR_RENDER_THREAD_GUARD();
5417
5418
ERR_FAIL_COND(p_list != ID_TYPE_COMPUTE_LIST);
5419
ERR_FAIL_COND(!compute_list.active);
5420
5421
Buffer *buffer = storage_buffer_owner.get_or_null(p_buffer);
5422
ERR_FAIL_NULL(buffer);
5423
5424
ERR_FAIL_COND_MSG(!buffer->usage.has_flag(RDD::BUFFER_USAGE_INDIRECT_BIT), "Buffer provided was not created to do indirect dispatch.");
5425
5426
ERR_FAIL_COND_MSG(p_offset + 12 > buffer->size, "Offset provided (+12) is past the end of buffer.");
5427
5428
#ifdef DEBUG_ENABLED
5429
5430
ERR_FAIL_COND_MSG(!compute_list.validation.pipeline_active, "No compute pipeline was set before attempting to draw.");
5431
5432
if (compute_list.validation.pipeline_push_constant_size > 0) {
5433
// Using push constants, check that they were supplied.
5434
ERR_FAIL_COND_MSG(!compute_list.validation.pipeline_push_constant_supplied,
5435
"The shader in this pipeline requires a push constant to be set before drawing, but it's not present.");
5436
}
5437
5438
#endif
5439
5440
#ifdef DEBUG_ENABLED
5441
for (uint32_t i = 0; i < compute_list.state.set_count; i++) {
5442
if (compute_list.state.sets[i].pipeline_expected_format == 0) {
5443
// Nothing expected by this pipeline.
5444
continue;
5445
}
5446
5447
if (compute_list.state.sets[i].pipeline_expected_format != compute_list.state.sets[i].uniform_set_format) {
5448
if (compute_list.state.sets[i].uniform_set_format == 0) {
5449
ERR_FAIL_MSG("Uniforms were never supplied for set (" + itos(i) + ") at the time of drawing, which are required by the pipeline.");
5450
} else if (uniform_set_owner.owns(compute_list.state.sets[i].uniform_set)) {
5451
UniformSet *us = uniform_set_owner.get_or_null(compute_list.state.sets[i].uniform_set);
5452
ERR_FAIL_MSG("Uniforms supplied for set (" + itos(i) + "):\n" + _shader_uniform_debug(us->shader_id, us->shader_set) + "\nare not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n" + _shader_uniform_debug(compute_list.state.pipeline_shader));
5453
} else {
5454
ERR_FAIL_MSG("Uniforms supplied for set (" + itos(i) + ", which was just freed) are not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n" + _shader_uniform_debug(compute_list.state.pipeline_shader));
5455
}
5456
}
5457
}
5458
#endif
5459
thread_local LocalVector<RDD::UniformSetID> valid_descriptor_ids;
5460
valid_descriptor_ids.clear();
5461
valid_descriptor_ids.resize(compute_list.state.set_count);
5462
5463
uint32_t valid_set_count = 0;
5464
uint32_t first_set_index = 0;
5465
uint32_t last_set_index = 0;
5466
bool found_first_set = false;
5467
5468
for (uint32_t i = 0; i < compute_list.state.set_count; i++) {
5469
if (compute_list.state.sets[i].pipeline_expected_format == 0) {
5470
// Nothing expected by this pipeline.
5471
continue;
5472
}
5473
5474
if (!compute_list.state.sets[i].bound && !found_first_set) {
5475
first_set_index = i;
5476
found_first_set = true;
5477
}
5478
5479
// Prepare descriptor sets if the API doesn't use pipeline barriers.
5480
if (!driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) {
5481
draw_graph.add_compute_list_uniform_set_prepare_for_use(compute_list.state.pipeline_shader_driver_id, compute_list.state.sets[i].uniform_set_driver_id, i);
5482
}
5483
}
5484
5485
// Bind descriptor sets.
5486
for (uint32_t i = first_set_index; i < compute_list.state.set_count; i++) {
5487
if (compute_list.state.sets[i].pipeline_expected_format == 0) {
5488
continue; // Nothing expected by this pipeline.
5489
}
5490
5491
if (!compute_list.state.sets[i].bound) {
5492
// All good, see if this requires re-binding.
5493
if (i - last_set_index > 1) {
5494
// If the descriptor sets are not contiguous, bind the previous ones and start a new batch.
5495
draw_graph.add_compute_list_bind_uniform_sets(compute_list.state.pipeline_shader_driver_id, valid_descriptor_ids, first_set_index, valid_set_count);
5496
5497
first_set_index = i;
5498
valid_set_count = 1;
5499
valid_descriptor_ids[0] = compute_list.state.sets[i].uniform_set_driver_id;
5500
} else {
5501
// Otherwise, keep storing in the current batch.
5502
valid_descriptor_ids[valid_set_count] = compute_list.state.sets[i].uniform_set_driver_id;
5503
valid_set_count++;
5504
}
5505
5506
last_set_index = i;
5507
5508
UniformSet *uniform_set = uniform_set_owner.get_or_null(compute_list.state.sets[i].uniform_set);
5509
_uniform_set_update_shared(uniform_set);
5510
5511
draw_graph.add_compute_list_usages(uniform_set->draw_trackers, uniform_set->draw_trackers_usage);
5512
compute_list.state.sets[i].bound = true;
5513
}
5514
}
5515
5516
// Bind the remaining batch.
5517
if (valid_set_count > 0) {
5518
draw_graph.add_compute_list_bind_uniform_sets(compute_list.state.pipeline_shader_driver_id, valid_descriptor_ids, first_set_index, valid_set_count);
5519
}
5520
5521
draw_graph.add_compute_list_dispatch_indirect(buffer->driver_id, p_offset);
5522
compute_list.state.dispatch_count++;
5523
5524
if (buffer->draw_tracker != nullptr) {
5525
draw_graph.add_compute_list_usage(buffer->draw_tracker, RDG::RESOURCE_USAGE_INDIRECT_BUFFER_READ);
5526
}
5527
5528
_check_transfer_worker_buffer(buffer);
5529
}
5530
5531
void RenderingDevice::compute_list_add_barrier(ComputeListID p_list) {
5532
ERR_RENDER_THREAD_GUARD();
5533
5534
compute_list_barrier_state = compute_list.state;
5535
compute_list_end();
5536
compute_list_begin();
5537
5538
if (compute_list_barrier_state.pipeline.is_valid()) {
5539
compute_list_bind_compute_pipeline(p_list, compute_list_barrier_state.pipeline);
5540
}
5541
5542
for (uint32_t i = 0; i < compute_list_barrier_state.set_count; i++) {
5543
if (compute_list_barrier_state.sets[i].uniform_set.is_valid()) {
5544
compute_list_bind_uniform_set(p_list, compute_list_barrier_state.sets[i].uniform_set, i);
5545
}
5546
}
5547
5548
if (compute_list_barrier_state.push_constant_size > 0) {
5549
compute_list_set_push_constant(p_list, compute_list_barrier_state.push_constant_data, compute_list_barrier_state.push_constant_size);
5550
}
5551
}
5552
5553
void RenderingDevice::compute_list_end() {
5554
ERR_RENDER_THREAD_GUARD();
5555
5556
ERR_FAIL_COND(!compute_list.active);
5557
5558
draw_graph.add_compute_list_end();
5559
5560
compute_list = ComputeList();
5561
}
5562
5563
#ifndef DISABLE_DEPRECATED
5564
void RenderingDevice::barrier(BitField<BarrierMask> p_from, BitField<BarrierMask> p_to) {
5565
WARN_PRINT("Deprecated. Barriers are automatically inserted by RenderingDevice.");
5566
}
5567
5568
void RenderingDevice::full_barrier() {
5569
WARN_PRINT("Deprecated. Barriers are automatically inserted by RenderingDevice.");
5570
}
5571
#endif
5572
5573
/*************************/
5574
/**** TRANSFER WORKER ****/
5575
/*************************/
5576
5577
static uint32_t _get_alignment_offset(uint32_t p_offset, uint32_t p_required_align) {
5578
uint32_t alignment_offset = (p_required_align > 0) ? (p_offset % p_required_align) : 0;
5579
if (alignment_offset != 0) {
5580
// If a particular alignment is required, add the offset as part of the required size.
5581
alignment_offset = p_required_align - alignment_offset;
5582
}
5583
5584
return alignment_offset;
5585
}
5586
5587
RenderingDevice::TransferWorker *RenderingDevice::_acquire_transfer_worker(uint32_t p_transfer_size, uint32_t p_required_align, uint32_t &r_staging_offset) {
5588
// Find the first worker that is not currently executing anything and has enough size for the transfer.
5589
// If no workers are available, we make a new one. If we're not allowed to make new ones, we wait until one of them is available.
5590
TransferWorker *transfer_worker = nullptr;
5591
uint32_t available_list_index = 0;
5592
bool transfer_worker_busy = true;
5593
bool transfer_worker_full = true;
5594
{
5595
MutexLock pool_lock(transfer_worker_pool_mutex);
5596
5597
// If no workers are available and we've reached the max pool capacity, wait until one of them becomes available.
5598
bool transfer_worker_pool_full = transfer_worker_pool.size() >= transfer_worker_pool_max_size;
5599
while (transfer_worker_pool_available_list.is_empty() && transfer_worker_pool_full) {
5600
transfer_worker_pool_condition.wait(pool_lock);
5601
}
5602
5603
// Look at all available workers first.
5604
for (uint32_t i = 0; i < transfer_worker_pool_available_list.size(); i++) {
5605
uint32_t worker_index = transfer_worker_pool_available_list[i];
5606
TransferWorker *candidate_worker = transfer_worker_pool[worker_index];
5607
candidate_worker->thread_mutex.lock();
5608
5609
// Figure out if the worker can fit the transfer.
5610
uint32_t alignment_offset = _get_alignment_offset(candidate_worker->staging_buffer_size_in_use, p_required_align);
5611
uint32_t required_size = candidate_worker->staging_buffer_size_in_use + p_transfer_size + alignment_offset;
5612
bool candidate_worker_busy = candidate_worker->submitted;
5613
bool candidate_worker_full = required_size > candidate_worker->staging_buffer_size_allocated;
5614
bool pick_candidate = false;
5615
if (!candidate_worker_busy && !candidate_worker_full) {
5616
// A worker that can fit the transfer and is not waiting for a previous execution is the best possible candidate.
5617
pick_candidate = true;
5618
} else if (!candidate_worker_busy) {
5619
// The worker can't fit the transfer but it's not currently doing anything.
5620
// We pick it as a possible candidate if the current one is busy.
5621
pick_candidate = transfer_worker_busy;
5622
} else if (!candidate_worker_full) {
5623
// The worker can fit the transfer but it's currently executing previous work.
5624
// We pick it as a possible candidate if the current one is both busy and full.
5625
pick_candidate = transfer_worker_busy && transfer_worker_full;
5626
} else if (transfer_worker == nullptr) {
5627
// The worker can't fit the transfer and it's currently executing work, so it's the worst candidate.
5628
// We only pick if no candidate has been picked yet.
5629
pick_candidate = true;
5630
}
5631
5632
if (pick_candidate) {
5633
if (transfer_worker != nullptr) {
5634
// Release the lock for the worker that was picked previously.
5635
transfer_worker->thread_mutex.unlock();
5636
}
5637
5638
// Keep the lock active for this worker.
5639
transfer_worker = candidate_worker;
5640
transfer_worker_busy = candidate_worker_busy;
5641
transfer_worker_full = candidate_worker_full;
5642
available_list_index = i;
5643
5644
if (!transfer_worker_busy && !transfer_worker_full) {
5645
// Best possible candidate, stop searching early.
5646
break;
5647
}
5648
} else {
5649
// Release the lock for the candidate.
5650
candidate_worker->thread_mutex.unlock();
5651
}
5652
}
5653
5654
if (transfer_worker != nullptr) {
5655
// A worker was picked, remove it from the available list.
5656
transfer_worker_pool_available_list.remove_at(available_list_index);
5657
} else {
5658
DEV_ASSERT(!transfer_worker_pool_full && "A transfer worker should never be created when the pool is full.");
5659
5660
// No existing worker was picked, we create a new one.
5661
transfer_worker = memnew(TransferWorker);
5662
transfer_worker->command_fence = driver->fence_create();
5663
transfer_worker->command_pool = driver->command_pool_create(transfer_queue_family, RDD::COMMAND_BUFFER_TYPE_PRIMARY);
5664
transfer_worker->command_buffer = driver->command_buffer_create(transfer_worker->command_pool);
5665
transfer_worker->index = transfer_worker_pool.size();
5666
transfer_worker_pool.push_back(transfer_worker);
5667
transfer_worker_operation_used_by_draw.push_back(0);
5668
transfer_worker->thread_mutex.lock();
5669
}
5670
}
5671
5672
if (transfer_worker->submitted) {
5673
// Wait for the worker if the command buffer was submitted but it hasn't finished processing yet.
5674
_wait_for_transfer_worker(transfer_worker);
5675
}
5676
5677
uint32_t alignment_offset = _get_alignment_offset(transfer_worker->staging_buffer_size_in_use, p_required_align);
5678
transfer_worker->max_transfer_size = MAX(transfer_worker->max_transfer_size, p_transfer_size);
5679
5680
uint32_t required_size = transfer_worker->staging_buffer_size_in_use + p_transfer_size + alignment_offset;
5681
if (required_size > transfer_worker->staging_buffer_size_allocated) {
5682
// If there's not enough bytes to use on the staging buffer, we submit everything pending from the worker and wait for the work to be finished.
5683
if (transfer_worker->recording) {
5684
_end_transfer_worker(transfer_worker);
5685
_submit_transfer_worker(transfer_worker);
5686
}
5687
5688
if (transfer_worker->submitted) {
5689
_wait_for_transfer_worker(transfer_worker);
5690
}
5691
5692
alignment_offset = 0;
5693
5694
// If the staging buffer can't fit the transfer, we recreate the buffer.
5695
const uint32_t expected_buffer_size_minimum = 16 * 1024;
5696
uint32_t expected_buffer_size = MAX(transfer_worker->max_transfer_size, expected_buffer_size_minimum);
5697
if (expected_buffer_size > transfer_worker->staging_buffer_size_allocated) {
5698
if (transfer_worker->staging_buffer.id != 0) {
5699
driver->buffer_free(transfer_worker->staging_buffer);
5700
}
5701
5702
uint32_t new_staging_buffer_size = next_power_of_2(expected_buffer_size);
5703
transfer_worker->staging_buffer_size_allocated = new_staging_buffer_size;
5704
transfer_worker->staging_buffer = driver->buffer_create(new_staging_buffer_size, RDD::BUFFER_USAGE_TRANSFER_FROM_BIT, RDD::MEMORY_ALLOCATION_TYPE_CPU);
5705
}
5706
}
5707
5708
// Add the alignment before storing the offset that will be returned.
5709
transfer_worker->staging_buffer_size_in_use += alignment_offset;
5710
5711
// Store the offset to return and increment the current size.
5712
r_staging_offset = transfer_worker->staging_buffer_size_in_use;
5713
transfer_worker->staging_buffer_size_in_use += p_transfer_size;
5714
5715
if (!transfer_worker->recording) {
5716
// Begin the command buffer if the worker wasn't recording yet.
5717
driver->command_buffer_begin(transfer_worker->command_buffer);
5718
transfer_worker->recording = true;
5719
}
5720
5721
return transfer_worker;
5722
}
5723
5724
void RenderingDevice::_release_transfer_worker(TransferWorker *p_transfer_worker) {
5725
p_transfer_worker->thread_mutex.unlock();
5726
5727
transfer_worker_pool_mutex.lock();
5728
transfer_worker_pool_available_list.push_back(p_transfer_worker->index);
5729
transfer_worker_pool_mutex.unlock();
5730
transfer_worker_pool_condition.notify_one();
5731
}
5732
5733
void RenderingDevice::_end_transfer_worker(TransferWorker *p_transfer_worker) {
5734
driver->command_buffer_end(p_transfer_worker->command_buffer);
5735
p_transfer_worker->recording = false;
5736
}
5737
5738
void RenderingDevice::_submit_transfer_worker(TransferWorker *p_transfer_worker, VectorView<RDD::SemaphoreID> p_signal_semaphores) {
5739
driver->command_queue_execute_and_present(transfer_queue, {}, p_transfer_worker->command_buffer, p_signal_semaphores, p_transfer_worker->command_fence, {});
5740
5741
for (uint32_t i = 0; i < p_signal_semaphores.size(); i++) {
5742
// Indicate the frame should wait on these semaphores before executing the main command buffer.
5743
frames[frame].semaphores_to_wait_on.push_back(p_signal_semaphores[i]);
5744
}
5745
5746
p_transfer_worker->submitted = true;
5747
5748
{
5749
MutexLock lock(p_transfer_worker->operations_mutex);
5750
p_transfer_worker->operations_submitted = p_transfer_worker->operations_counter;
5751
}
5752
}
5753
5754
void RenderingDevice::_wait_for_transfer_worker(TransferWorker *p_transfer_worker) {
5755
driver->fence_wait(p_transfer_worker->command_fence);
5756
driver->command_pool_reset(p_transfer_worker->command_pool);
5757
p_transfer_worker->staging_buffer_size_in_use = 0;
5758
p_transfer_worker->submitted = false;
5759
5760
{
5761
MutexLock lock(p_transfer_worker->operations_mutex);
5762
p_transfer_worker->operations_processed = p_transfer_worker->operations_submitted;
5763
}
5764
5765
_flush_barriers_for_transfer_worker(p_transfer_worker);
5766
}
5767
5768
void RenderingDevice::_flush_barriers_for_transfer_worker(TransferWorker *p_transfer_worker) {
5769
// Caller must have already acquired the mutex for the worker.
5770
if (!p_transfer_worker->texture_barriers.is_empty()) {
5771
MutexLock transfer_worker_lock(transfer_worker_pool_texture_barriers_mutex);
5772
for (uint32_t i = 0; i < p_transfer_worker->texture_barriers.size(); i++) {
5773
transfer_worker_pool_texture_barriers.push_back(p_transfer_worker->texture_barriers[i]);
5774
}
5775
5776
p_transfer_worker->texture_barriers.clear();
5777
}
5778
}
5779
5780
void RenderingDevice::_check_transfer_worker_operation(uint32_t p_transfer_worker_index, uint64_t p_transfer_worker_operation) {
5781
TransferWorker *transfer_worker = transfer_worker_pool[p_transfer_worker_index];
5782
MutexLock lock(transfer_worker->operations_mutex);
5783
uint64_t &dst_operation = transfer_worker_operation_used_by_draw[transfer_worker->index];
5784
dst_operation = MAX(dst_operation, p_transfer_worker_operation);
5785
}
5786
5787
void RenderingDevice::_check_transfer_worker_buffer(Buffer *p_buffer) {
5788
if (p_buffer->transfer_worker_index >= 0) {
5789
_check_transfer_worker_operation(p_buffer->transfer_worker_index, p_buffer->transfer_worker_operation);
5790
p_buffer->transfer_worker_index = -1;
5791
}
5792
}
5793
5794
void RenderingDevice::_check_transfer_worker_texture(Texture *p_texture) {
5795
if (p_texture->transfer_worker_index >= 0) {
5796
_check_transfer_worker_operation(p_texture->transfer_worker_index, p_texture->transfer_worker_operation);
5797
p_texture->transfer_worker_index = -1;
5798
}
5799
}
5800
5801
void RenderingDevice::_check_transfer_worker_vertex_array(VertexArray *p_vertex_array) {
5802
if (!p_vertex_array->transfer_worker_indices.is_empty()) {
5803
for (int i = 0; i < p_vertex_array->transfer_worker_indices.size(); i++) {
5804
_check_transfer_worker_operation(p_vertex_array->transfer_worker_indices[i], p_vertex_array->transfer_worker_operations[i]);
5805
}
5806
5807
p_vertex_array->transfer_worker_indices.clear();
5808
p_vertex_array->transfer_worker_operations.clear();
5809
}
5810
}
5811
5812
void RenderingDevice::_check_transfer_worker_index_array(IndexArray *p_index_array) {
5813
if (p_index_array->transfer_worker_index >= 0) {
5814
_check_transfer_worker_operation(p_index_array->transfer_worker_index, p_index_array->transfer_worker_operation);
5815
p_index_array->transfer_worker_index = -1;
5816
}
5817
}
5818
5819
void RenderingDevice::_submit_transfer_workers(RDD::CommandBufferID p_draw_command_buffer) {
5820
MutexLock transfer_worker_lock(transfer_worker_pool_mutex);
5821
for (uint32_t i = 0; i < transfer_worker_pool.size(); i++) {
5822
TransferWorker *worker = transfer_worker_pool[i];
5823
if (p_draw_command_buffer) {
5824
MutexLock lock(worker->operations_mutex);
5825
if (worker->operations_processed >= transfer_worker_operation_used_by_draw[worker->index]) {
5826
// The operation used by the draw has already been processed, we don't need to wait on the worker.
5827
continue;
5828
}
5829
}
5830
5831
{
5832
MutexLock lock(worker->thread_mutex);
5833
if (worker->recording) {
5834
VectorView<RDD::SemaphoreID> semaphores = p_draw_command_buffer ? frames[frame].transfer_worker_semaphores[i] : VectorView<RDD::SemaphoreID>();
5835
_end_transfer_worker(worker);
5836
_submit_transfer_worker(worker, semaphores);
5837
}
5838
5839
if (p_draw_command_buffer) {
5840
_flush_barriers_for_transfer_worker(worker);
5841
}
5842
}
5843
}
5844
}
5845
5846
void RenderingDevice::_submit_transfer_barriers(RDD::CommandBufferID p_draw_command_buffer) {
5847
MutexLock transfer_worker_lock(transfer_worker_pool_texture_barriers_mutex);
5848
if (!transfer_worker_pool_texture_barriers.is_empty()) {
5849
driver->command_pipeline_barrier(p_draw_command_buffer, RDD::PIPELINE_STAGE_COPY_BIT, RDD::PIPELINE_STAGE_ALL_COMMANDS_BIT, {}, {}, transfer_worker_pool_texture_barriers);
5850
transfer_worker_pool_texture_barriers.clear();
5851
}
5852
}
5853
5854
void RenderingDevice::_wait_for_transfer_workers() {
5855
MutexLock transfer_worker_lock(transfer_worker_pool_mutex);
5856
for (TransferWorker *worker : transfer_worker_pool) {
5857
MutexLock lock(worker->thread_mutex);
5858
if (worker->submitted) {
5859
_wait_for_transfer_worker(worker);
5860
}
5861
}
5862
}
5863
5864
void RenderingDevice::_free_transfer_workers() {
5865
MutexLock transfer_worker_lock(transfer_worker_pool_mutex);
5866
for (TransferWorker *worker : transfer_worker_pool) {
5867
driver->fence_free(worker->command_fence);
5868
driver->buffer_free(worker->staging_buffer);
5869
driver->command_pool_free(worker->command_pool);
5870
memdelete(worker);
5871
}
5872
5873
transfer_worker_pool.clear();
5874
}
5875
5876
/***********************/
5877
/**** COMMAND GRAPH ****/
5878
/***********************/
5879
5880
bool RenderingDevice::_texture_make_mutable(Texture *p_texture, RID p_texture_id) {
5881
if (p_texture->draw_tracker != nullptr) {
5882
// Texture already has a tracker.
5883
return false;
5884
} else {
5885
if (p_texture->owner.is_valid()) {
5886
// Texture has an owner.
5887
Texture *owner_texture = texture_owner.get_or_null(p_texture->owner);
5888
ERR_FAIL_NULL_V(owner_texture, false);
5889
5890
if (owner_texture->draw_tracker != nullptr) {
5891
// Create a tracker for this dependency in particular.
5892
if (p_texture->slice_type == TEXTURE_SLICE_MAX) {
5893
// Shared texture.
5894
p_texture->draw_tracker = owner_texture->draw_tracker;
5895
p_texture->draw_tracker->reference_count++;
5896
} else {
5897
// Slice texture.
5898
if (owner_texture->slice_trackers == nullptr) {
5899
owner_texture->slice_trackers = memnew((HashMap<Rect2i, RDG::ResourceTracker *>));
5900
}
5901
HashMap<Rect2i, RDG::ResourceTracker *>::ConstIterator draw_tracker_iterator = owner_texture->slice_trackers->find(p_texture->slice_rect);
5902
RDG::ResourceTracker *draw_tracker = nullptr;
5903
if (draw_tracker_iterator != owner_texture->slice_trackers->end()) {
5904
// Reuse the tracker at the matching rectangle.
5905
draw_tracker = draw_tracker_iterator->value;
5906
} else {
5907
// Create a new tracker and store it on the map.
5908
draw_tracker = RDG::resource_tracker_create();
5909
draw_tracker->parent = owner_texture->draw_tracker;
5910
draw_tracker->texture_driver_id = p_texture->driver_id;
5911
draw_tracker->texture_size = Size2i(p_texture->width, p_texture->height);
5912
draw_tracker->texture_subresources = p_texture->barrier_range();
5913
draw_tracker->texture_usage = p_texture->usage_flags;
5914
draw_tracker->texture_slice_or_dirty_rect = p_texture->slice_rect;
5915
(*owner_texture->slice_trackers)[p_texture->slice_rect] = draw_tracker;
5916
}
5917
5918
p_texture->draw_tracker = draw_tracker;
5919
p_texture->draw_tracker->reference_count++;
5920
}
5921
5922
if (p_texture_id.is_valid()) {
5923
_dependencies_make_mutable(p_texture_id, p_texture->draw_tracker);
5924
}
5925
} else {
5926
// Delegate this to the owner instead, as it'll make all its dependencies mutable.
5927
_texture_make_mutable(owner_texture, p_texture->owner);
5928
}
5929
} else {
5930
// Regular texture.
5931
p_texture->draw_tracker = RDG::resource_tracker_create();
5932
p_texture->draw_tracker->texture_driver_id = p_texture->driver_id;
5933
p_texture->draw_tracker->texture_size = Size2i(p_texture->width, p_texture->height);
5934
p_texture->draw_tracker->texture_subresources = p_texture->barrier_range();
5935
p_texture->draw_tracker->texture_usage = p_texture->usage_flags;
5936
p_texture->draw_tracker->is_discardable = p_texture->is_discardable;
5937
p_texture->draw_tracker->reference_count = 1;
5938
5939
if (p_texture_id.is_valid()) {
5940
if (p_texture->has_initial_data) {
5941
// If the texture was initialized with initial data but wasn't made mutable from the start, assume the texture sampling usage.
5942
p_texture->draw_tracker->usage = RDG::RESOURCE_USAGE_TEXTURE_SAMPLE;
5943
}
5944
5945
_dependencies_make_mutable(p_texture_id, p_texture->draw_tracker);
5946
}
5947
}
5948
5949
return true;
5950
}
5951
}
5952
5953
bool RenderingDevice::_buffer_make_mutable(Buffer *p_buffer, RID p_buffer_id) {
5954
if (p_buffer->draw_tracker != nullptr) {
5955
// Buffer already has a tracker.
5956
return false;
5957
} else {
5958
// Create a tracker for the buffer and make all its dependencies mutable.
5959
p_buffer->draw_tracker = RDG::resource_tracker_create();
5960
p_buffer->draw_tracker->buffer_driver_id = p_buffer->driver_id;
5961
if (p_buffer_id.is_valid()) {
5962
_dependencies_make_mutable(p_buffer_id, p_buffer->draw_tracker);
5963
}
5964
5965
return true;
5966
}
5967
}
5968
5969
bool RenderingDevice::_vertex_array_make_mutable(VertexArray *p_vertex_array, RID p_resource_id, RDG::ResourceTracker *p_resource_tracker) {
5970
if (!p_vertex_array->untracked_buffers.has(p_resource_id)) {
5971
// Vertex array thinks the buffer is already tracked or does not use it.
5972
return false;
5973
} else {
5974
// Vertex array is aware of the buffer but it isn't being tracked.
5975
p_vertex_array->draw_trackers.push_back(p_resource_tracker);
5976
p_vertex_array->untracked_buffers.erase(p_resource_id);
5977
return true;
5978
}
5979
}
5980
5981
bool RenderingDevice::_index_array_make_mutable(IndexArray *p_index_array, RDG::ResourceTracker *p_resource_tracker) {
5982
if (p_index_array->draw_tracker != nullptr) {
5983
// Index array already has a tracker.
5984
return false;
5985
} else {
5986
// Index array should assign the tracker from the buffer.
5987
p_index_array->draw_tracker = p_resource_tracker;
5988
return true;
5989
}
5990
}
5991
5992
bool RenderingDevice::_uniform_set_make_mutable(UniformSet *p_uniform_set, RID p_resource_id, RDG::ResourceTracker *p_resource_tracker) {
5993
HashMap<RID, RDG::ResourceUsage>::Iterator E = p_uniform_set->untracked_usage.find(p_resource_id);
5994
if (!E) {
5995
// Uniform set thinks the resource is already tracked or does not use it.
5996
return false;
5997
} else {
5998
// Uniform set has seen the resource but hasn't added its tracker yet.
5999
p_uniform_set->draw_trackers.push_back(p_resource_tracker);
6000
p_uniform_set->draw_trackers_usage.push_back(E->value);
6001
p_uniform_set->untracked_usage.remove(E);
6002
return true;
6003
}
6004
}
6005
6006
bool RenderingDevice::_dependency_make_mutable(RID p_id, RID p_resource_id, RDG::ResourceTracker *p_resource_tracker) {
6007
if (texture_owner.owns(p_id)) {
6008
Texture *texture = texture_owner.get_or_null(p_id);
6009
return _texture_make_mutable(texture, p_id);
6010
} else if (vertex_array_owner.owns(p_id)) {
6011
VertexArray *vertex_array = vertex_array_owner.get_or_null(p_id);
6012
return _vertex_array_make_mutable(vertex_array, p_resource_id, p_resource_tracker);
6013
} else if (index_array_owner.owns(p_id)) {
6014
IndexArray *index_array = index_array_owner.get_or_null(p_id);
6015
return _index_array_make_mutable(index_array, p_resource_tracker);
6016
} else if (uniform_set_owner.owns(p_id)) {
6017
UniformSet *uniform_set = uniform_set_owner.get_or_null(p_id);
6018
return _uniform_set_make_mutable(uniform_set, p_resource_id, p_resource_tracker);
6019
} else {
6020
DEV_ASSERT(false && "Unknown resource type to make mutable.");
6021
return false;
6022
}
6023
}
6024
6025
bool RenderingDevice::_dependencies_make_mutable_recursive(RID p_id, RDG::ResourceTracker *p_resource_tracker) {
6026
bool made_mutable = false;
6027
HashMap<RID, HashSet<RID>>::Iterator E = dependency_map.find(p_id);
6028
if (E) {
6029
for (RID rid : E->value) {
6030
made_mutable = _dependency_make_mutable(rid, p_id, p_resource_tracker) || made_mutable;
6031
}
6032
}
6033
6034
return made_mutable;
6035
}
6036
6037
bool RenderingDevice::_dependencies_make_mutable(RID p_id, RDG::ResourceTracker *p_resource_tracker) {
6038
_THREAD_SAFE_METHOD_
6039
return _dependencies_make_mutable_recursive(p_id, p_resource_tracker);
6040
}
6041
6042
/**************************/
6043
/**** FRAME MANAGEMENT ****/
6044
/**************************/
6045
6046
void RenderingDevice::free(RID p_id) {
6047
ERR_RENDER_THREAD_GUARD();
6048
6049
_free_dependencies(p_id); // Recursively erase dependencies first, to avoid potential API problems.
6050
_free_internal(p_id);
6051
}
6052
6053
void RenderingDevice::_free_internal(RID p_id) {
6054
#ifdef DEV_ENABLED
6055
String resource_name;
6056
if (resource_names.has(p_id)) {
6057
resource_name = resource_names[p_id];
6058
resource_names.erase(p_id);
6059
}
6060
#endif
6061
6062
// Push everything so it's disposed of next time this frame index is processed (means, it's safe to do it).
6063
if (texture_owner.owns(p_id)) {
6064
Texture *texture = texture_owner.get_or_null(p_id);
6065
_check_transfer_worker_texture(texture);
6066
6067
RDG::ResourceTracker *draw_tracker = texture->draw_tracker;
6068
if (draw_tracker != nullptr) {
6069
draw_tracker->reference_count--;
6070
if (draw_tracker->reference_count == 0) {
6071
RDG::resource_tracker_free(draw_tracker);
6072
6073
if (texture->owner.is_valid() && (texture->slice_type != TEXTURE_SLICE_MAX)) {
6074
// If this was a texture slice, erase the tracker from the map.
6075
Texture *owner_texture = texture_owner.get_or_null(texture->owner);
6076
if (owner_texture != nullptr && owner_texture->slice_trackers != nullptr) {
6077
owner_texture->slice_trackers->erase(texture->slice_rect);
6078
6079
if (owner_texture->slice_trackers->is_empty()) {
6080
memdelete(owner_texture->slice_trackers);
6081
owner_texture->slice_trackers = nullptr;
6082
}
6083
}
6084
}
6085
}
6086
}
6087
6088
frames[frame].textures_to_dispose_of.push_back(*texture);
6089
texture_owner.free(p_id);
6090
} else if (framebuffer_owner.owns(p_id)) {
6091
Framebuffer *framebuffer = framebuffer_owner.get_or_null(p_id);
6092
frames[frame].framebuffers_to_dispose_of.push_back(*framebuffer);
6093
6094
if (framebuffer->invalidated_callback != nullptr) {
6095
framebuffer->invalidated_callback(framebuffer->invalidated_callback_userdata);
6096
}
6097
6098
framebuffer_owner.free(p_id);
6099
} else if (sampler_owner.owns(p_id)) {
6100
RDD::SamplerID sampler_driver_id = *sampler_owner.get_or_null(p_id);
6101
frames[frame].samplers_to_dispose_of.push_back(sampler_driver_id);
6102
sampler_owner.free(p_id);
6103
} else if (vertex_buffer_owner.owns(p_id)) {
6104
Buffer *vertex_buffer = vertex_buffer_owner.get_or_null(p_id);
6105
_check_transfer_worker_buffer(vertex_buffer);
6106
6107
RDG::resource_tracker_free(vertex_buffer->draw_tracker);
6108
frames[frame].buffers_to_dispose_of.push_back(*vertex_buffer);
6109
vertex_buffer_owner.free(p_id);
6110
} else if (vertex_array_owner.owns(p_id)) {
6111
vertex_array_owner.free(p_id);
6112
} else if (index_buffer_owner.owns(p_id)) {
6113
IndexBuffer *index_buffer = index_buffer_owner.get_or_null(p_id);
6114
_check_transfer_worker_buffer(index_buffer);
6115
6116
RDG::resource_tracker_free(index_buffer->draw_tracker);
6117
frames[frame].buffers_to_dispose_of.push_back(*index_buffer);
6118
index_buffer_owner.free(p_id);
6119
} else if (index_array_owner.owns(p_id)) {
6120
index_array_owner.free(p_id);
6121
} else if (shader_owner.owns(p_id)) {
6122
Shader *shader = shader_owner.get_or_null(p_id);
6123
if (shader->driver_id) { // Not placeholder?
6124
frames[frame].shaders_to_dispose_of.push_back(*shader);
6125
}
6126
shader_owner.free(p_id);
6127
} else if (uniform_buffer_owner.owns(p_id)) {
6128
Buffer *uniform_buffer = uniform_buffer_owner.get_or_null(p_id);
6129
_check_transfer_worker_buffer(uniform_buffer);
6130
6131
RDG::resource_tracker_free(uniform_buffer->draw_tracker);
6132
frames[frame].buffers_to_dispose_of.push_back(*uniform_buffer);
6133
uniform_buffer_owner.free(p_id);
6134
} else if (texture_buffer_owner.owns(p_id)) {
6135
Buffer *texture_buffer = texture_buffer_owner.get_or_null(p_id);
6136
_check_transfer_worker_buffer(texture_buffer);
6137
6138
RDG::resource_tracker_free(texture_buffer->draw_tracker);
6139
frames[frame].buffers_to_dispose_of.push_back(*texture_buffer);
6140
texture_buffer_owner.free(p_id);
6141
} else if (storage_buffer_owner.owns(p_id)) {
6142
Buffer *storage_buffer = storage_buffer_owner.get_or_null(p_id);
6143
_check_transfer_worker_buffer(storage_buffer);
6144
6145
RDG::resource_tracker_free(storage_buffer->draw_tracker);
6146
frames[frame].buffers_to_dispose_of.push_back(*storage_buffer);
6147
storage_buffer_owner.free(p_id);
6148
} else if (uniform_set_owner.owns(p_id)) {
6149
UniformSet *uniform_set = uniform_set_owner.get_or_null(p_id);
6150
frames[frame].uniform_sets_to_dispose_of.push_back(*uniform_set);
6151
uniform_set_owner.free(p_id);
6152
6153
if (uniform_set->invalidated_callback != nullptr) {
6154
uniform_set->invalidated_callback(uniform_set->invalidated_callback_userdata);
6155
}
6156
} else if (render_pipeline_owner.owns(p_id)) {
6157
RenderPipeline *pipeline = render_pipeline_owner.get_or_null(p_id);
6158
frames[frame].render_pipelines_to_dispose_of.push_back(*pipeline);
6159
render_pipeline_owner.free(p_id);
6160
} else if (compute_pipeline_owner.owns(p_id)) {
6161
ComputePipeline *pipeline = compute_pipeline_owner.get_or_null(p_id);
6162
frames[frame].compute_pipelines_to_dispose_of.push_back(*pipeline);
6163
compute_pipeline_owner.free(p_id);
6164
} else {
6165
#ifdef DEV_ENABLED
6166
ERR_PRINT("Attempted to free invalid ID: " + itos(p_id.get_id()) + " " + resource_name);
6167
#else
6168
ERR_PRINT("Attempted to free invalid ID: " + itos(p_id.get_id()));
6169
#endif
6170
}
6171
6172
frames_pending_resources_for_processing = uint32_t(frames.size());
6173
}
6174
6175
// The full list of resources that can be named is in the VkObjectType enum.
6176
// We just expose the resources that are owned and can be accessed easily.
6177
void RenderingDevice::set_resource_name(RID p_id, const String &p_name) {
6178
_THREAD_SAFE_METHOD_
6179
6180
if (texture_owner.owns(p_id)) {
6181
Texture *texture = texture_owner.get_or_null(p_id);
6182
driver->set_object_name(RDD::OBJECT_TYPE_TEXTURE, texture->driver_id, p_name);
6183
} else if (framebuffer_owner.owns(p_id)) {
6184
//Framebuffer *framebuffer = framebuffer_owner.get_or_null(p_id);
6185
// Not implemented for now as the relationship between Framebuffer and RenderPass is very complex.
6186
} else if (sampler_owner.owns(p_id)) {
6187
RDD::SamplerID sampler_driver_id = *sampler_owner.get_or_null(p_id);
6188
driver->set_object_name(RDD::OBJECT_TYPE_SAMPLER, sampler_driver_id, p_name);
6189
} else if (vertex_buffer_owner.owns(p_id)) {
6190
Buffer *vertex_buffer = vertex_buffer_owner.get_or_null(p_id);
6191
driver->set_object_name(RDD::OBJECT_TYPE_BUFFER, vertex_buffer->driver_id, p_name);
6192
} else if (index_buffer_owner.owns(p_id)) {
6193
IndexBuffer *index_buffer = index_buffer_owner.get_or_null(p_id);
6194
driver->set_object_name(RDD::OBJECT_TYPE_BUFFER, index_buffer->driver_id, p_name);
6195
} else if (shader_owner.owns(p_id)) {
6196
Shader *shader = shader_owner.get_or_null(p_id);
6197
driver->set_object_name(RDD::OBJECT_TYPE_SHADER, shader->driver_id, p_name);
6198
} else if (uniform_buffer_owner.owns(p_id)) {
6199
Buffer *uniform_buffer = uniform_buffer_owner.get_or_null(p_id);
6200
driver->set_object_name(RDD::OBJECT_TYPE_BUFFER, uniform_buffer->driver_id, p_name);
6201
} else if (texture_buffer_owner.owns(p_id)) {
6202
Buffer *texture_buffer = texture_buffer_owner.get_or_null(p_id);
6203
driver->set_object_name(RDD::OBJECT_TYPE_BUFFER, texture_buffer->driver_id, p_name);
6204
} else if (storage_buffer_owner.owns(p_id)) {
6205
Buffer *storage_buffer = storage_buffer_owner.get_or_null(p_id);
6206
driver->set_object_name(RDD::OBJECT_TYPE_BUFFER, storage_buffer->driver_id, p_name);
6207
} else if (uniform_set_owner.owns(p_id)) {
6208
UniformSet *uniform_set = uniform_set_owner.get_or_null(p_id);
6209
driver->set_object_name(RDD::OBJECT_TYPE_UNIFORM_SET, uniform_set->driver_id, p_name);
6210
} else if (render_pipeline_owner.owns(p_id)) {
6211
RenderPipeline *pipeline = render_pipeline_owner.get_or_null(p_id);
6212
driver->set_object_name(RDD::OBJECT_TYPE_PIPELINE, pipeline->driver_id, p_name);
6213
} else if (compute_pipeline_owner.owns(p_id)) {
6214
ComputePipeline *pipeline = compute_pipeline_owner.get_or_null(p_id);
6215
driver->set_object_name(RDD::OBJECT_TYPE_PIPELINE, pipeline->driver_id, p_name);
6216
} else {
6217
ERR_PRINT("Attempted to name invalid ID: " + itos(p_id.get_id()));
6218
return;
6219
}
6220
#ifdef DEV_ENABLED
6221
resource_names[p_id] = p_name;
6222
#endif
6223
}
6224
6225
void RenderingDevice::_draw_command_begin_label(String p_label_name, const Color &p_color) {
6226
draw_command_begin_label(p_label_name.utf8().span(), p_color);
6227
}
6228
6229
void RenderingDevice::draw_command_begin_label(const Span<char> p_label_name, const Color &p_color) {
6230
ERR_RENDER_THREAD_GUARD();
6231
6232
if (!context->is_debug_utils_enabled()) {
6233
return;
6234
}
6235
6236
draw_graph.begin_label(p_label_name, p_color);
6237
}
6238
6239
#ifndef DISABLE_DEPRECATED
6240
void RenderingDevice::draw_command_insert_label(String p_label_name, const Color &p_color) {
6241
WARN_PRINT("Deprecated. Inserting labels no longer applies due to command reordering.");
6242
}
6243
#endif
6244
6245
void RenderingDevice::draw_command_end_label() {
6246
ERR_RENDER_THREAD_GUARD();
6247
6248
draw_graph.end_label();
6249
}
6250
6251
String RenderingDevice::get_device_vendor_name() const {
6252
return _get_device_vendor_name(device);
6253
}
6254
6255
String RenderingDevice::get_device_name() const {
6256
return device.name;
6257
}
6258
6259
RenderingDevice::DeviceType RenderingDevice::get_device_type() const {
6260
return DeviceType(device.type);
6261
}
6262
6263
String RenderingDevice::get_device_api_name() const {
6264
return driver->get_api_name();
6265
}
6266
6267
bool RenderingDevice::is_composite_alpha_supported() const {
6268
return driver->is_composite_alpha_supported(main_queue);
6269
}
6270
6271
String RenderingDevice::get_device_api_version() const {
6272
return driver->get_api_version();
6273
}
6274
6275
String RenderingDevice::get_device_pipeline_cache_uuid() const {
6276
return driver->get_pipeline_cache_uuid();
6277
}
6278
6279
void RenderingDevice::swap_buffers(bool p_present) {
6280
ERR_RENDER_THREAD_GUARD();
6281
6282
_end_frame();
6283
_execute_frame(p_present);
6284
6285
// Advance to the next frame and begin recording again.
6286
frame = (frame + 1) % frames.size();
6287
6288
_begin_frame(true);
6289
}
6290
6291
void RenderingDevice::submit() {
6292
ERR_RENDER_THREAD_GUARD();
6293
ERR_FAIL_COND_MSG(is_main_instance, "Only local devices can submit and sync.");
6294
ERR_FAIL_COND_MSG(local_device_processing, "device already submitted, call sync to wait until done.");
6295
6296
_end_frame();
6297
_execute_frame(false);
6298
local_device_processing = true;
6299
}
6300
6301
void RenderingDevice::sync() {
6302
ERR_RENDER_THREAD_GUARD();
6303
ERR_FAIL_COND_MSG(is_main_instance, "Only local devices can submit and sync.");
6304
ERR_FAIL_COND_MSG(!local_device_processing, "sync can only be called after a submit");
6305
6306
_begin_frame(true);
6307
local_device_processing = false;
6308
}
6309
6310
void RenderingDevice::_free_pending_resources(int p_frame) {
6311
// Free in dependency usage order, so nothing weird happens.
6312
// Pipelines.
6313
while (frames[p_frame].render_pipelines_to_dispose_of.front()) {
6314
RenderPipeline *pipeline = &frames[p_frame].render_pipelines_to_dispose_of.front()->get();
6315
6316
driver->pipeline_free(pipeline->driver_id);
6317
6318
frames[p_frame].render_pipelines_to_dispose_of.pop_front();
6319
}
6320
6321
while (frames[p_frame].compute_pipelines_to_dispose_of.front()) {
6322
ComputePipeline *pipeline = &frames[p_frame].compute_pipelines_to_dispose_of.front()->get();
6323
6324
driver->pipeline_free(pipeline->driver_id);
6325
6326
frames[p_frame].compute_pipelines_to_dispose_of.pop_front();
6327
}
6328
6329
// Uniform sets.
6330
while (frames[p_frame].uniform_sets_to_dispose_of.front()) {
6331
UniformSet *uniform_set = &frames[p_frame].uniform_sets_to_dispose_of.front()->get();
6332
6333
driver->uniform_set_free(uniform_set->driver_id);
6334
6335
frames[p_frame].uniform_sets_to_dispose_of.pop_front();
6336
}
6337
6338
// Shaders.
6339
while (frames[p_frame].shaders_to_dispose_of.front()) {
6340
Shader *shader = &frames[p_frame].shaders_to_dispose_of.front()->get();
6341
6342
driver->shader_free(shader->driver_id);
6343
6344
frames[p_frame].shaders_to_dispose_of.pop_front();
6345
}
6346
6347
// Samplers.
6348
while (frames[p_frame].samplers_to_dispose_of.front()) {
6349
RDD::SamplerID sampler = frames[p_frame].samplers_to_dispose_of.front()->get();
6350
6351
driver->sampler_free(sampler);
6352
6353
frames[p_frame].samplers_to_dispose_of.pop_front();
6354
}
6355
6356
// Framebuffers.
6357
while (frames[p_frame].framebuffers_to_dispose_of.front()) {
6358
Framebuffer *framebuffer = &frames[p_frame].framebuffers_to_dispose_of.front()->get();
6359
draw_graph.framebuffer_cache_free(driver, framebuffer->framebuffer_cache);
6360
frames[p_frame].framebuffers_to_dispose_of.pop_front();
6361
}
6362
6363
// Textures.
6364
while (frames[p_frame].textures_to_dispose_of.front()) {
6365
Texture *texture = &frames[p_frame].textures_to_dispose_of.front()->get();
6366
if (texture->bound) {
6367
WARN_PRINT("Deleted a texture while it was bound.");
6368
}
6369
6370
_texture_free_shared_fallback(texture);
6371
6372
texture_memory -= driver->texture_get_allocation_size(texture->driver_id);
6373
driver->texture_free(texture->driver_id);
6374
6375
frames[p_frame].textures_to_dispose_of.pop_front();
6376
}
6377
6378
// Buffers.
6379
while (frames[p_frame].buffers_to_dispose_of.front()) {
6380
Buffer &buffer = frames[p_frame].buffers_to_dispose_of.front()->get();
6381
driver->buffer_free(buffer.driver_id);
6382
buffer_memory -= buffer.size;
6383
6384
frames[p_frame].buffers_to_dispose_of.pop_front();
6385
}
6386
6387
if (frames_pending_resources_for_processing > 0u) {
6388
--frames_pending_resources_for_processing;
6389
}
6390
}
6391
6392
uint32_t RenderingDevice::get_frame_delay() const {
6393
return frames.size();
6394
}
6395
6396
uint64_t RenderingDevice::get_memory_usage(MemoryType p_type) const {
6397
switch (p_type) {
6398
case MEMORY_BUFFERS: {
6399
return buffer_memory;
6400
}
6401
case MEMORY_TEXTURES: {
6402
return texture_memory;
6403
}
6404
case MEMORY_TOTAL: {
6405
return driver->get_total_memory_used();
6406
}
6407
default: {
6408
DEV_ASSERT(false);
6409
return 0;
6410
}
6411
}
6412
}
6413
6414
void RenderingDevice::_begin_frame(bool p_presented) {
6415
// Before writing to this frame, wait for it to be finished.
6416
_stall_for_frame(frame);
6417
6418
if (command_pool_reset_enabled) {
6419
bool reset = driver->command_pool_reset(frames[frame].command_pool);
6420
ERR_FAIL_COND(!reset);
6421
}
6422
6423
if (p_presented) {
6424
update_perf_report();
6425
driver->linear_uniform_set_pools_reset(frame);
6426
}
6427
6428
// Begin recording on the frame's command buffers.
6429
driver->begin_segment(frame, frames_drawn++);
6430
driver->command_buffer_begin(frames[frame].command_buffer);
6431
6432
// Reset the graph.
6433
draw_graph.begin();
6434
6435
// Erase pending resources.
6436
_free_pending_resources(frame);
6437
6438
// Advance staging buffers if used.
6439
if (upload_staging_buffers.used) {
6440
upload_staging_buffers.current = (upload_staging_buffers.current + 1) % upload_staging_buffers.blocks.size();
6441
upload_staging_buffers.used = false;
6442
}
6443
6444
if (download_staging_buffers.used) {
6445
download_staging_buffers.current = (download_staging_buffers.current + 1) % download_staging_buffers.blocks.size();
6446
download_staging_buffers.used = false;
6447
}
6448
6449
if (frames[frame].timestamp_count) {
6450
driver->timestamp_query_pool_get_results(frames[frame].timestamp_pool, frames[frame].timestamp_count, frames[frame].timestamp_result_values.ptr());
6451
driver->command_timestamp_query_pool_reset(frames[frame].command_buffer, frames[frame].timestamp_pool, frames[frame].timestamp_count);
6452
SWAP(frames[frame].timestamp_names, frames[frame].timestamp_result_names);
6453
SWAP(frames[frame].timestamp_cpu_values, frames[frame].timestamp_cpu_result_values);
6454
}
6455
6456
frames[frame].timestamp_result_count = frames[frame].timestamp_count;
6457
frames[frame].timestamp_count = 0;
6458
frames[frame].index = Engine::get_singleton()->get_frames_drawn();
6459
}
6460
6461
void RenderingDevice::_end_frame() {
6462
if (draw_list.active) {
6463
ERR_PRINT("Found open draw list at the end of the frame, this should never happen (further drawing will likely not work).");
6464
}
6465
6466
if (compute_list.active) {
6467
ERR_PRINT("Found open compute list at the end of the frame, this should never happen (further compute will likely not work).");
6468
}
6469
6470
// The command buffer must be copied into a stack variable as the driver workarounds can change the command buffer in use.
6471
RDD::CommandBufferID command_buffer = frames[frame].command_buffer;
6472
_submit_transfer_workers(command_buffer);
6473
_submit_transfer_barriers(command_buffer);
6474
6475
draw_graph.end(RENDER_GRAPH_REORDER, RENDER_GRAPH_FULL_BARRIERS, command_buffer, frames[frame].command_buffer_pool);
6476
driver->command_buffer_end(command_buffer);
6477
driver->end_segment();
6478
}
6479
6480
void RenderingDevice::execute_chained_cmds(bool p_present_swap_chain, RenderingDeviceDriver::FenceID p_draw_fence,
6481
RenderingDeviceDriver::SemaphoreID p_dst_draw_semaphore_to_signal) {
6482
// Execute command buffers and use semaphores to wait on the execution of the previous one.
6483
// Normally there's only one command buffer, but driver workarounds can force situations where
6484
// there'll be more.
6485
uint32_t command_buffer_count = 1;
6486
RDG::CommandBufferPool &buffer_pool = frames[frame].command_buffer_pool;
6487
if (buffer_pool.buffers_used > 0) {
6488
command_buffer_count += buffer_pool.buffers_used;
6489
buffer_pool.buffers_used = 0;
6490
}
6491
6492
thread_local LocalVector<RDD::SwapChainID> swap_chains;
6493
swap_chains.clear();
6494
6495
// Instead of having just one command; we have potentially many (which had to be split due to an
6496
// Adreno workaround on mobile, only if the workaround is active). Thus we must execute all of them
6497
// and chain them together via semaphores as dependent executions.
6498
thread_local LocalVector<RDD::SemaphoreID> wait_semaphores;
6499
wait_semaphores = frames[frame].semaphores_to_wait_on;
6500
6501
for (uint32_t i = 0; i < command_buffer_count; i++) {
6502
RDD::CommandBufferID command_buffer;
6503
RDD::SemaphoreID signal_semaphore;
6504
RDD::FenceID signal_fence;
6505
if (i > 0) {
6506
command_buffer = buffer_pool.buffers[i - 1];
6507
} else {
6508
command_buffer = frames[frame].command_buffer;
6509
}
6510
6511
if (i == (command_buffer_count - 1)) {
6512
// This is the last command buffer, it should signal the semaphore & fence.
6513
signal_semaphore = p_dst_draw_semaphore_to_signal;
6514
signal_fence = p_draw_fence;
6515
6516
if (p_present_swap_chain) {
6517
// Just present the swap chains as part of the last command execution.
6518
swap_chains = frames[frame].swap_chains_to_present;
6519
}
6520
} else {
6521
signal_semaphore = buffer_pool.semaphores[i];
6522
// Semaphores always need to be signaled if it's not the last command buffer.
6523
}
6524
6525
driver->command_queue_execute_and_present(main_queue, wait_semaphores, command_buffer,
6526
signal_semaphore ? signal_semaphore : VectorView<RDD::SemaphoreID>(), signal_fence,
6527
swap_chains);
6528
6529
// Make the next command buffer wait on the semaphore signaled by this one.
6530
wait_semaphores.resize(1);
6531
wait_semaphores[0] = signal_semaphore;
6532
}
6533
6534
frames[frame].semaphores_to_wait_on.clear();
6535
}
6536
6537
void RenderingDevice::_execute_frame(bool p_present) {
6538
// Check whether this frame should present the swap chains and in which queue.
6539
const bool frame_can_present = p_present && !frames[frame].swap_chains_to_present.is_empty();
6540
const bool separate_present_queue = main_queue != present_queue;
6541
6542
// The semaphore is required if the frame can be presented and a separate present queue is used;
6543
// since the separate queue will wait for that semaphore before presenting.
6544
const RDD::SemaphoreID semaphore = (frame_can_present && separate_present_queue)
6545
? frames[frame].semaphore
6546
: RDD::SemaphoreID(nullptr);
6547
const bool present_swap_chain = frame_can_present && !separate_present_queue;
6548
6549
execute_chained_cmds(present_swap_chain, frames[frame].fence, semaphore);
6550
// Indicate the fence has been signaled so the next time the frame's contents need to be
6551
// used, the CPU needs to wait on the work to be completed.
6552
frames[frame].fence_signaled = true;
6553
6554
if (frame_can_present) {
6555
if (separate_present_queue) {
6556
// Issue the presentation separately if the presentation queue is different from the main queue.
6557
driver->command_queue_execute_and_present(present_queue, frames[frame].semaphore, {}, {}, {}, frames[frame].swap_chains_to_present);
6558
}
6559
6560
frames[frame].swap_chains_to_present.clear();
6561
}
6562
}
6563
6564
void RenderingDevice::_stall_for_frame(uint32_t p_frame) {
6565
thread_local PackedByteArray packed_byte_array;
6566
6567
if (frames[p_frame].fence_signaled) {
6568
driver->fence_wait(frames[p_frame].fence);
6569
frames[p_frame].fence_signaled = false;
6570
6571
// Flush any pending requests for asynchronous buffer downloads.
6572
if (!frames[p_frame].download_buffer_get_data_requests.is_empty()) {
6573
for (uint32_t i = 0; i < frames[p_frame].download_buffer_get_data_requests.size(); i++) {
6574
const BufferGetDataRequest &request = frames[p_frame].download_buffer_get_data_requests[i];
6575
packed_byte_array.resize(request.size);
6576
6577
uint32_t array_offset = 0;
6578
for (uint32_t j = 0; j < request.frame_local_count; j++) {
6579
uint32_t local_index = request.frame_local_index + j;
6580
const RDD::BufferCopyRegion &region = frames[p_frame].download_buffer_copy_regions[local_index];
6581
uint8_t *buffer_data = driver->buffer_map(frames[p_frame].download_buffer_staging_buffers[local_index]);
6582
memcpy(&packed_byte_array.write[array_offset], &buffer_data[region.dst_offset], region.size);
6583
driver->buffer_unmap(frames[p_frame].download_buffer_staging_buffers[local_index]);
6584
array_offset += region.size;
6585
}
6586
6587
request.callback.call(packed_byte_array);
6588
}
6589
6590
frames[p_frame].download_buffer_staging_buffers.clear();
6591
frames[p_frame].download_buffer_copy_regions.clear();
6592
frames[p_frame].download_buffer_get_data_requests.clear();
6593
}
6594
6595
// Flush any pending requests for asynchronous texture downloads.
6596
if (!frames[p_frame].download_texture_get_data_requests.is_empty()) {
6597
uint32_t pitch_step = driver->api_trait_get(RDD::API_TRAIT_TEXTURE_DATA_ROW_PITCH_STEP);
6598
for (uint32_t i = 0; i < frames[p_frame].download_texture_get_data_requests.size(); i++) {
6599
const TextureGetDataRequest &request = frames[p_frame].download_texture_get_data_requests[i];
6600
uint32_t texture_size = get_image_format_required_size(request.format, request.width, request.height, request.depth, request.mipmaps);
6601
packed_byte_array.resize(texture_size);
6602
6603
// Find the block size of the texture's format.
6604
uint32_t block_w = 0;
6605
uint32_t block_h = 0;
6606
get_compressed_image_format_block_dimensions(request.format, block_w, block_h);
6607
6608
uint32_t block_size = get_compressed_image_format_block_byte_size(request.format);
6609
uint32_t pixel_size = get_image_format_pixel_size(request.format);
6610
uint32_t pixel_rshift = get_compressed_image_format_pixel_rshift(request.format);
6611
uint32_t region_size = texture_download_region_size_px;
6612
6613
for (uint32_t j = 0; j < request.frame_local_count; j++) {
6614
uint32_t local_index = request.frame_local_index + j;
6615
const RDD::BufferTextureCopyRegion &region = frames[p_frame].download_buffer_texture_copy_regions[local_index];
6616
uint32_t w = STEPIFY(request.width >> region.texture_subresources.mipmap, block_w);
6617
uint32_t h = STEPIFY(request.height >> region.texture_subresources.mipmap, block_h);
6618
uint32_t region_w = MIN(region_size, w - region.texture_offset.x);
6619
uint32_t region_h = MIN(region_size, h - region.texture_offset.y);
6620
uint32_t region_pitch = (region_w * pixel_size * block_w) >> pixel_rshift;
6621
region_pitch = STEPIFY(region_pitch, pitch_step);
6622
6623
uint8_t *buffer_data = driver->buffer_map(frames[p_frame].download_texture_staging_buffers[local_index]);
6624
const uint8_t *read_ptr = buffer_data + region.buffer_offset;
6625
uint8_t *write_ptr = packed_byte_array.ptrw() + frames[p_frame].download_texture_mipmap_offsets[local_index];
6626
uint32_t unit_size = pixel_size;
6627
if (block_w != 1 || block_h != 1) {
6628
unit_size = block_size;
6629
}
6630
6631
write_ptr += ((region.texture_offset.y / block_h) * (w / block_w) + (region.texture_offset.x / block_w)) * unit_size;
6632
for (uint32_t y = region_h / block_h; y > 0; y--) {
6633
memcpy(write_ptr, read_ptr, (region_w / block_w) * unit_size);
6634
write_ptr += (w / block_w) * unit_size;
6635
read_ptr += region_pitch;
6636
}
6637
6638
driver->buffer_unmap(frames[p_frame].download_texture_staging_buffers[local_index]);
6639
}
6640
6641
request.callback.call(packed_byte_array);
6642
}
6643
6644
frames[p_frame].download_texture_staging_buffers.clear();
6645
frames[p_frame].download_buffer_texture_copy_regions.clear();
6646
frames[p_frame].download_texture_mipmap_offsets.clear();
6647
frames[p_frame].download_texture_get_data_requests.clear();
6648
}
6649
}
6650
}
6651
6652
void RenderingDevice::_stall_for_previous_frames() {
6653
for (uint32_t i = 0; i < frames.size(); i++) {
6654
_stall_for_frame(i);
6655
}
6656
}
6657
6658
void RenderingDevice::_flush_and_stall_for_all_frames() {
6659
_stall_for_previous_frames();
6660
_end_frame();
6661
_execute_frame(false);
6662
_begin_frame();
6663
}
6664
6665
Error RenderingDevice::initialize(RenderingContextDriver *p_context, DisplayServer::WindowID p_main_window) {
6666
ERR_RENDER_THREAD_GUARD_V(ERR_UNAVAILABLE);
6667
6668
Error err;
6669
RenderingContextDriver::SurfaceID main_surface = 0;
6670
is_main_instance = (singleton == this) && (p_main_window != DisplayServer::INVALID_WINDOW_ID);
6671
if (p_main_window != DisplayServer::INVALID_WINDOW_ID) {
6672
// Retrieve the surface from the main window if it was specified.
6673
main_surface = p_context->surface_get_from_window(p_main_window);
6674
ERR_FAIL_COND_V(main_surface == 0, FAILED);
6675
}
6676
6677
context = p_context;
6678
driver = context->driver_create();
6679
6680
print_verbose("Devices:");
6681
int32_t device_index = Engine::get_singleton()->get_gpu_index();
6682
const uint32_t device_count = context->device_get_count();
6683
const bool detect_device = (device_index < 0) || (device_index >= int32_t(device_count));
6684
uint32_t device_type_score = 0;
6685
for (uint32_t i = 0; i < device_count; i++) {
6686
RenderingContextDriver::Device device_option = context->device_get(i);
6687
String name = device_option.name;
6688
String vendor = _get_device_vendor_name(device_option);
6689
String type = _get_device_type_name(device_option);
6690
bool present_supported = main_surface != 0 ? context->device_supports_present(i, main_surface) : false;
6691
print_verbose(" #" + itos(i) + ": " + vendor + " " + name + " - " + (present_supported ? "Supported" : "Unsupported") + ", " + type);
6692
if (detect_device && (present_supported || main_surface == 0)) {
6693
// If a window was specified, present must be supported by the device to be available as an option.
6694
// Assign a score for each type of device and prefer the device with the higher score.
6695
uint32_t option_score = _get_device_type_score(device_option);
6696
if (option_score > device_type_score) {
6697
device_index = i;
6698
device_type_score = option_score;
6699
}
6700
}
6701
}
6702
6703
ERR_FAIL_COND_V_MSG((device_index < 0) || (device_index >= int32_t(device_count)), ERR_CANT_CREATE, "None of the devices supports both graphics and present queues.");
6704
6705
uint32_t frame_count = 1;
6706
if (main_surface != 0) {
6707
frame_count = MAX(2U, uint32_t(GLOBAL_GET("rendering/rendering_device/vsync/frame_queue_size")));
6708
}
6709
6710
frame = 0;
6711
max_timestamp_query_elements = GLOBAL_GET("debug/settings/profiler/max_timestamp_query_elements");
6712
6713
device = context->device_get(device_index);
6714
err = driver->initialize(device_index, frame_count);
6715
ERR_FAIL_COND_V_MSG(err != OK, FAILED, "Failed to initialize driver for device.");
6716
6717
if (is_main_instance) {
6718
// Only the singleton instance with a display should print this information.
6719
String rendering_method;
6720
if (OS::get_singleton()->get_current_rendering_method() == "mobile") {
6721
rendering_method = "Forward Mobile";
6722
} else {
6723
rendering_method = "Forward+";
6724
}
6725
6726
// Output our device version.
6727
Engine::get_singleton()->print_header(vformat("%s %s - %s - Using Device #%d: %s - %s", get_device_api_name(), get_device_api_version(), rendering_method, device_index, _get_device_vendor_name(device), device.name));
6728
}
6729
6730
// Pick the main queue family. It is worth noting we explicitly do not request the transfer bit, as apparently the specification defines
6731
// that the existence of either the graphics or compute bit implies that the queue can also do transfer operations, but it is optional
6732
// to indicate whether it supports them or not with the dedicated transfer bit if either is set.
6733
BitField<RDD::CommandQueueFamilyBits> main_queue_bits = {};
6734
main_queue_bits.set_flag(RDD::COMMAND_QUEUE_FAMILY_GRAPHICS_BIT);
6735
main_queue_bits.set_flag(RDD::COMMAND_QUEUE_FAMILY_COMPUTE_BIT);
6736
6737
#if !FORCE_SEPARATE_PRESENT_QUEUE
6738
// Needing to use a separate queue for presentation is an edge case that remains to be seen what hardware triggers it at all.
6739
main_queue_family = driver->command_queue_family_get(main_queue_bits, main_surface);
6740
if (!main_queue_family && (main_surface != 0))
6741
#endif
6742
{
6743
// If it was not possible to find a main queue that supports the surface, we attempt to get two different queues instead.
6744
main_queue_family = driver->command_queue_family_get(main_queue_bits);
6745
present_queue_family = driver->command_queue_family_get(BitField<RDD::CommandQueueFamilyBits>(), main_surface);
6746
ERR_FAIL_COND_V(!present_queue_family, FAILED);
6747
}
6748
6749
ERR_FAIL_COND_V(!main_queue_family, FAILED);
6750
6751
// Create the main queue.
6752
main_queue = driver->command_queue_create(main_queue_family, true);
6753
ERR_FAIL_COND_V(!main_queue, FAILED);
6754
6755
transfer_queue_family = driver->command_queue_family_get(RDD::COMMAND_QUEUE_FAMILY_TRANSFER_BIT);
6756
if (transfer_queue_family) {
6757
// Create the transfer queue.
6758
transfer_queue = driver->command_queue_create(transfer_queue_family);
6759
ERR_FAIL_COND_V(!transfer_queue, FAILED);
6760
} else {
6761
// Use main queue as the transfer queue.
6762
transfer_queue = main_queue;
6763
transfer_queue_family = main_queue_family;
6764
}
6765
6766
if (present_queue_family) {
6767
// Create the present queue.
6768
present_queue = driver->command_queue_create(present_queue_family);
6769
ERR_FAIL_COND_V(!present_queue, FAILED);
6770
} else {
6771
// Use main queue as the present queue.
6772
present_queue = main_queue;
6773
present_queue_family = main_queue_family;
6774
}
6775
6776
// Use the processor count as the max amount of transfer workers that can be created.
6777
transfer_worker_pool_max_size = OS::get_singleton()->get_processor_count();
6778
6779
frames.resize(frame_count);
6780
6781
// Create data for all the frames.
6782
for (uint32_t i = 0; i < frames.size(); i++) {
6783
frames[i].index = 0;
6784
6785
// Create command pool, command buffers, semaphores and fences.
6786
frames[i].command_pool = driver->command_pool_create(main_queue_family, RDD::COMMAND_BUFFER_TYPE_PRIMARY);
6787
ERR_FAIL_COND_V(!frames[i].command_pool, FAILED);
6788
frames[i].command_buffer = driver->command_buffer_create(frames[i].command_pool);
6789
ERR_FAIL_COND_V(!frames[i].command_buffer, FAILED);
6790
frames[i].semaphore = driver->semaphore_create();
6791
ERR_FAIL_COND_V(!frames[i].semaphore, FAILED);
6792
frames[i].fence = driver->fence_create();
6793
ERR_FAIL_COND_V(!frames[i].fence, FAILED);
6794
frames[i].fence_signaled = false;
6795
6796
// Create query pool.
6797
frames[i].timestamp_pool = driver->timestamp_query_pool_create(max_timestamp_query_elements);
6798
frames[i].timestamp_names.resize(max_timestamp_query_elements);
6799
frames[i].timestamp_cpu_values.resize(max_timestamp_query_elements);
6800
frames[i].timestamp_count = 0;
6801
frames[i].timestamp_result_names.resize(max_timestamp_query_elements);
6802
frames[i].timestamp_cpu_result_values.resize(max_timestamp_query_elements);
6803
frames[i].timestamp_result_values.resize(max_timestamp_query_elements);
6804
frames[i].timestamp_result_count = 0;
6805
6806
// Assign the main queue family and command pool to the command buffer pool.
6807
frames[i].command_buffer_pool.pool = frames[i].command_pool;
6808
6809
// Create the semaphores for the transfer workers.
6810
frames[i].transfer_worker_semaphores.resize(transfer_worker_pool_max_size);
6811
for (uint32_t j = 0; j < transfer_worker_pool_max_size; j++) {
6812
frames[i].transfer_worker_semaphores[j] = driver->semaphore_create();
6813
ERR_FAIL_COND_V(!frames[i].transfer_worker_semaphores[j], FAILED);
6814
}
6815
}
6816
6817
// Start from frame count, so everything else is immediately old.
6818
frames_drawn = frames.size();
6819
6820
// Initialize recording on the first frame.
6821
driver->begin_segment(frame, frames_drawn++);
6822
driver->command_buffer_begin(frames[0].command_buffer);
6823
6824
// Create draw graph and start it initialized as well.
6825
draw_graph.initialize(driver, device, &_render_pass_create_from_graph, frames.size(), main_queue_family, SECONDARY_COMMAND_BUFFERS_PER_FRAME);
6826
draw_graph.begin();
6827
6828
for (uint32_t i = 0; i < frames.size(); i++) {
6829
// Reset all queries in a query pool before doing any operations with them..
6830
driver->command_timestamp_query_pool_reset(frames[0].command_buffer, frames[i].timestamp_pool, max_timestamp_query_elements);
6831
}
6832
6833
// Convert block size from KB.
6834
upload_staging_buffers.block_size = GLOBAL_GET("rendering/rendering_device/staging_buffer/block_size_kb");
6835
upload_staging_buffers.block_size = MAX(4u, upload_staging_buffers.block_size);
6836
upload_staging_buffers.block_size *= 1024;
6837
6838
// Convert staging buffer size from MB.
6839
upload_staging_buffers.max_size = GLOBAL_GET("rendering/rendering_device/staging_buffer/max_size_mb");
6840
upload_staging_buffers.max_size = MAX(1u, upload_staging_buffers.max_size);
6841
upload_staging_buffers.max_size *= 1024 * 1024;
6842
upload_staging_buffers.max_size = MAX(upload_staging_buffers.max_size, upload_staging_buffers.block_size * 4);
6843
6844
// Copy the sizes to the download staging buffers.
6845
download_staging_buffers.block_size = upload_staging_buffers.block_size;
6846
download_staging_buffers.max_size = upload_staging_buffers.max_size;
6847
6848
texture_upload_region_size_px = GLOBAL_GET("rendering/rendering_device/staging_buffer/texture_upload_region_size_px");
6849
texture_upload_region_size_px = nearest_power_of_2_templated(texture_upload_region_size_px);
6850
6851
texture_download_region_size_px = GLOBAL_GET("rendering/rendering_device/staging_buffer/texture_download_region_size_px");
6852
texture_download_region_size_px = nearest_power_of_2_templated(texture_download_region_size_px);
6853
6854
// Ensure current staging block is valid and at least one per frame exists.
6855
upload_staging_buffers.current = 0;
6856
upload_staging_buffers.used = false;
6857
upload_staging_buffers.usage_bits = RDD::BUFFER_USAGE_TRANSFER_FROM_BIT;
6858
6859
download_staging_buffers.current = 0;
6860
download_staging_buffers.used = false;
6861
download_staging_buffers.usage_bits = RDD::BUFFER_USAGE_TRANSFER_TO_BIT;
6862
6863
for (uint32_t i = 0; i < frames.size(); i++) {
6864
// Staging was never used, create the blocks.
6865
err = _insert_staging_block(upload_staging_buffers);
6866
ERR_FAIL_COND_V(err, FAILED);
6867
6868
err = _insert_staging_block(download_staging_buffers);
6869
ERR_FAIL_COND_V(err, FAILED);
6870
}
6871
6872
draw_list = DrawList();
6873
compute_list = ComputeList();
6874
6875
bool project_pipeline_cache_enable = GLOBAL_GET("rendering/rendering_device/pipeline_cache/enable");
6876
if (is_main_instance && project_pipeline_cache_enable) {
6877
// Only the instance that is not a local device and is also the singleton is allowed to manage a pipeline cache.
6878
pipeline_cache_file_path = vformat("user://vulkan/pipelines.%s.%s",
6879
OS::get_singleton()->get_current_rendering_method(),
6880
device.name.validate_filename().replace_char(' ', '_').to_lower());
6881
if (Engine::get_singleton()->is_editor_hint()) {
6882
pipeline_cache_file_path += ".editor";
6883
}
6884
pipeline_cache_file_path += ".cache";
6885
6886
Vector<uint8_t> cache_data = _load_pipeline_cache();
6887
pipeline_cache_enabled = driver->pipeline_cache_create(cache_data);
6888
if (pipeline_cache_enabled) {
6889
pipeline_cache_size = driver->pipeline_cache_query_size();
6890
print_verbose(vformat("Startup PSO cache (%.1f MiB)", pipeline_cache_size / (1024.0f * 1024.0f)));
6891
}
6892
}
6893
6894
// Find the best method available for VRS on the current hardware.
6895
_vrs_detect_method();
6896
6897
return OK;
6898
}
6899
6900
Vector<uint8_t> RenderingDevice::_load_pipeline_cache() {
6901
DirAccess::make_dir_recursive_absolute(pipeline_cache_file_path.get_base_dir());
6902
6903
if (FileAccess::exists(pipeline_cache_file_path)) {
6904
Error file_error;
6905
Vector<uint8_t> file_data = FileAccess::get_file_as_bytes(pipeline_cache_file_path, &file_error);
6906
return file_data;
6907
} else {
6908
return Vector<uint8_t>();
6909
}
6910
}
6911
6912
void RenderingDevice::_update_pipeline_cache(bool p_closing) {
6913
_THREAD_SAFE_METHOD_
6914
6915
{
6916
bool still_saving = pipeline_cache_save_task != WorkerThreadPool::INVALID_TASK_ID && !WorkerThreadPool::get_singleton()->is_task_completed(pipeline_cache_save_task);
6917
if (still_saving) {
6918
if (p_closing) {
6919
WorkerThreadPool::get_singleton()->wait_for_task_completion(pipeline_cache_save_task);
6920
pipeline_cache_save_task = WorkerThreadPool::INVALID_TASK_ID;
6921
} else {
6922
// We can't save until the currently running save is done. We'll retry next time; worst case, we'll save when exiting.
6923
return;
6924
}
6925
}
6926
}
6927
6928
{
6929
size_t new_pipelines_cache_size = driver->pipeline_cache_query_size();
6930
ERR_FAIL_COND(!new_pipelines_cache_size);
6931
size_t difference = new_pipelines_cache_size - pipeline_cache_size;
6932
6933
bool must_save = false;
6934
6935
if (p_closing) {
6936
must_save = difference > 0;
6937
} else {
6938
float save_interval = GLOBAL_GET("rendering/rendering_device/pipeline_cache/save_chunk_size_mb");
6939
must_save = difference > 0 && difference / (1024.0f * 1024.0f) >= save_interval;
6940
}
6941
6942
if (must_save) {
6943
pipeline_cache_size = new_pipelines_cache_size;
6944
} else {
6945
return;
6946
}
6947
}
6948
6949
if (p_closing) {
6950
_save_pipeline_cache(this);
6951
} else {
6952
pipeline_cache_save_task = WorkerThreadPool::get_singleton()->add_native_task(&_save_pipeline_cache, this, false, "PipelineCacheSave");
6953
}
6954
}
6955
6956
void RenderingDevice::_save_pipeline_cache(void *p_data) {
6957
RenderingDevice *self = static_cast<RenderingDevice *>(p_data);
6958
6959
self->_thread_safe_.lock();
6960
Vector<uint8_t> cache_blob = self->driver->pipeline_cache_serialize();
6961
self->_thread_safe_.unlock();
6962
6963
if (cache_blob.is_empty()) {
6964
return;
6965
}
6966
print_verbose(vformat("Updated PSO cache (%.1f MiB)", cache_blob.size() / (1024.0f * 1024.0f)));
6967
6968
Ref<FileAccess> f = FileAccess::open(self->pipeline_cache_file_path, FileAccess::WRITE, nullptr);
6969
if (f.is_valid()) {
6970
f->store_buffer(cache_blob);
6971
}
6972
}
6973
6974
template <typename T>
6975
void RenderingDevice::_free_rids(T &p_owner, const char *p_type) {
6976
LocalVector<RID> owned = p_owner.get_owned_list();
6977
if (owned.size()) {
6978
if (owned.size() == 1) {
6979
WARN_PRINT(vformat("1 RID of type \"%s\" was leaked.", p_type));
6980
} else {
6981
WARN_PRINT(vformat("%d RIDs of type \"%s\" were leaked.", owned.size(), p_type));
6982
}
6983
for (const RID &rid : owned) {
6984
#ifdef DEV_ENABLED
6985
if (resource_names.has(rid)) {
6986
print_line(String(" - ") + resource_names[rid]);
6987
}
6988
#endif
6989
free(rid);
6990
}
6991
}
6992
}
6993
6994
void RenderingDevice::capture_timestamp(const String &p_name) {
6995
ERR_RENDER_THREAD_GUARD();
6996
6997
ERR_FAIL_COND_MSG(draw_list.active && draw_list.state.draw_count > 0, "Capturing timestamps during draw list creation is not allowed. Offending timestamp was: " + p_name);
6998
ERR_FAIL_COND_MSG(compute_list.active && compute_list.state.dispatch_count > 0, "Capturing timestamps during compute list creation is not allowed. Offending timestamp was: " + p_name);
6999
ERR_FAIL_COND_MSG(frames[frame].timestamp_count >= max_timestamp_query_elements, vformat("Tried capturing more timestamps than the configured maximum (%d). You can increase this limit in the project settings under 'Debug/Settings' called 'Max Timestamp Query Elements'.", max_timestamp_query_elements));
7000
7001
draw_graph.add_capture_timestamp(frames[frame].timestamp_pool, frames[frame].timestamp_count);
7002
7003
frames[frame].timestamp_names[frames[frame].timestamp_count] = p_name;
7004
frames[frame].timestamp_cpu_values[frames[frame].timestamp_count] = OS::get_singleton()->get_ticks_usec();
7005
frames[frame].timestamp_count++;
7006
}
7007
7008
uint64_t RenderingDevice::get_driver_resource(DriverResource p_resource, RID p_rid, uint64_t p_index) {
7009
ERR_RENDER_THREAD_GUARD_V(0);
7010
7011
uint64_t driver_id = 0;
7012
switch (p_resource) {
7013
case DRIVER_RESOURCE_LOGICAL_DEVICE:
7014
case DRIVER_RESOURCE_PHYSICAL_DEVICE:
7015
case DRIVER_RESOURCE_TOPMOST_OBJECT:
7016
break;
7017
case DRIVER_RESOURCE_COMMAND_QUEUE:
7018
driver_id = main_queue.id;
7019
break;
7020
case DRIVER_RESOURCE_QUEUE_FAMILY:
7021
driver_id = main_queue_family.id;
7022
break;
7023
case DRIVER_RESOURCE_TEXTURE:
7024
case DRIVER_RESOURCE_TEXTURE_VIEW:
7025
case DRIVER_RESOURCE_TEXTURE_DATA_FORMAT: {
7026
Texture *tex = texture_owner.get_or_null(p_rid);
7027
ERR_FAIL_NULL_V(tex, 0);
7028
7029
driver_id = tex->driver_id.id;
7030
} break;
7031
case DRIVER_RESOURCE_SAMPLER: {
7032
RDD::SamplerID *sampler_driver_id = sampler_owner.get_or_null(p_rid);
7033
ERR_FAIL_NULL_V(sampler_driver_id, 0);
7034
7035
driver_id = (*sampler_driver_id).id;
7036
} break;
7037
case DRIVER_RESOURCE_UNIFORM_SET: {
7038
UniformSet *uniform_set = uniform_set_owner.get_or_null(p_rid);
7039
ERR_FAIL_NULL_V(uniform_set, 0);
7040
7041
driver_id = uniform_set->driver_id.id;
7042
} break;
7043
case DRIVER_RESOURCE_BUFFER: {
7044
Buffer *buffer = nullptr;
7045
if (vertex_buffer_owner.owns(p_rid)) {
7046
buffer = vertex_buffer_owner.get_or_null(p_rid);
7047
} else if (index_buffer_owner.owns(p_rid)) {
7048
buffer = index_buffer_owner.get_or_null(p_rid);
7049
} else if (uniform_buffer_owner.owns(p_rid)) {
7050
buffer = uniform_buffer_owner.get_or_null(p_rid);
7051
} else if (texture_buffer_owner.owns(p_rid)) {
7052
buffer = texture_buffer_owner.get_or_null(p_rid);
7053
} else if (storage_buffer_owner.owns(p_rid)) {
7054
buffer = storage_buffer_owner.get_or_null(p_rid);
7055
}
7056
ERR_FAIL_NULL_V(buffer, 0);
7057
7058
driver_id = buffer->driver_id.id;
7059
} break;
7060
case DRIVER_RESOURCE_COMPUTE_PIPELINE: {
7061
ComputePipeline *compute_pipeline = compute_pipeline_owner.get_or_null(p_rid);
7062
ERR_FAIL_NULL_V(compute_pipeline, 0);
7063
7064
driver_id = compute_pipeline->driver_id.id;
7065
} break;
7066
case DRIVER_RESOURCE_RENDER_PIPELINE: {
7067
RenderPipeline *render_pipeline = render_pipeline_owner.get_or_null(p_rid);
7068
ERR_FAIL_NULL_V(render_pipeline, 0);
7069
7070
driver_id = render_pipeline->driver_id.id;
7071
} break;
7072
default: {
7073
ERR_FAIL_V(0);
7074
} break;
7075
}
7076
7077
return driver->get_resource_native_handle(p_resource, driver_id);
7078
}
7079
7080
String RenderingDevice::get_driver_and_device_memory_report() const {
7081
return context->get_driver_and_device_memory_report();
7082
}
7083
7084
String RenderingDevice::get_tracked_object_name(uint32_t p_type_index) const {
7085
return context->get_tracked_object_name(p_type_index);
7086
}
7087
7088
uint64_t RenderingDevice::get_tracked_object_type_count() const {
7089
return context->get_tracked_object_type_count();
7090
}
7091
7092
uint64_t RenderingDevice::get_driver_total_memory() const {
7093
return context->get_driver_total_memory();
7094
}
7095
7096
uint64_t RenderingDevice::get_driver_allocation_count() const {
7097
return context->get_driver_allocation_count();
7098
}
7099
7100
uint64_t RenderingDevice::get_driver_memory_by_object_type(uint32_t p_type) const {
7101
return context->get_driver_memory_by_object_type(p_type);
7102
}
7103
7104
uint64_t RenderingDevice::get_driver_allocs_by_object_type(uint32_t p_type) const {
7105
return context->get_driver_allocs_by_object_type(p_type);
7106
}
7107
7108
uint64_t RenderingDevice::get_device_total_memory() const {
7109
return context->get_device_total_memory();
7110
}
7111
7112
uint64_t RenderingDevice::get_device_allocation_count() const {
7113
return context->get_device_allocation_count();
7114
}
7115
7116
uint64_t RenderingDevice::get_device_memory_by_object_type(uint32_t type) const {
7117
return context->get_device_memory_by_object_type(type);
7118
}
7119
7120
uint64_t RenderingDevice::get_device_allocs_by_object_type(uint32_t type) const {
7121
return context->get_device_allocs_by_object_type(type);
7122
}
7123
7124
uint32_t RenderingDevice::get_captured_timestamps_count() const {
7125
ERR_RENDER_THREAD_GUARD_V(0);
7126
return frames[frame].timestamp_result_count;
7127
}
7128
7129
uint64_t RenderingDevice::get_captured_timestamps_frame() const {
7130
ERR_RENDER_THREAD_GUARD_V(0);
7131
return frames[frame].index;
7132
}
7133
7134
uint64_t RenderingDevice::get_captured_timestamp_gpu_time(uint32_t p_index) const {
7135
ERR_RENDER_THREAD_GUARD_V(0);
7136
ERR_FAIL_UNSIGNED_INDEX_V(p_index, frames[frame].timestamp_result_count, 0);
7137
return driver->timestamp_query_result_to_time(frames[frame].timestamp_result_values[p_index]);
7138
}
7139
7140
uint64_t RenderingDevice::get_captured_timestamp_cpu_time(uint32_t p_index) const {
7141
ERR_RENDER_THREAD_GUARD_V(0);
7142
ERR_FAIL_UNSIGNED_INDEX_V(p_index, frames[frame].timestamp_result_count, 0);
7143
return frames[frame].timestamp_cpu_result_values[p_index];
7144
}
7145
7146
String RenderingDevice::get_captured_timestamp_name(uint32_t p_index) const {
7147
ERR_FAIL_UNSIGNED_INDEX_V(p_index, frames[frame].timestamp_result_count, String());
7148
return frames[frame].timestamp_result_names[p_index];
7149
}
7150
7151
uint64_t RenderingDevice::limit_get(Limit p_limit) const {
7152
return driver->limit_get(p_limit);
7153
}
7154
7155
void RenderingDevice::finalize() {
7156
ERR_RENDER_THREAD_GUARD();
7157
7158
if (!frames.is_empty()) {
7159
// Wait for all frames to have finished rendering.
7160
_flush_and_stall_for_all_frames();
7161
}
7162
7163
// Wait for transfer workers to finish.
7164
_submit_transfer_workers();
7165
_wait_for_transfer_workers();
7166
7167
// Delete everything the graph has created.
7168
draw_graph.finalize();
7169
7170
// Free all resources.
7171
_free_rids(render_pipeline_owner, "Pipeline");
7172
_free_rids(compute_pipeline_owner, "Compute");
7173
_free_rids(uniform_set_owner, "UniformSet");
7174
_free_rids(texture_buffer_owner, "TextureBuffer");
7175
_free_rids(storage_buffer_owner, "StorageBuffer");
7176
_free_rids(uniform_buffer_owner, "UniformBuffer");
7177
_free_rids(shader_owner, "Shader");
7178
_free_rids(index_array_owner, "IndexArray");
7179
_free_rids(index_buffer_owner, "IndexBuffer");
7180
_free_rids(vertex_array_owner, "VertexArray");
7181
_free_rids(vertex_buffer_owner, "VertexBuffer");
7182
_free_rids(framebuffer_owner, "Framebuffer");
7183
_free_rids(sampler_owner, "Sampler");
7184
{
7185
// For textures it's a bit more difficult because they may be shared.
7186
LocalVector<RID> owned = texture_owner.get_owned_list();
7187
if (owned.size()) {
7188
if (owned.size() == 1) {
7189
WARN_PRINT("1 RID of type \"Texture\" was leaked.");
7190
} else {
7191
WARN_PRINT(vformat("%d RIDs of type \"Texture\" were leaked.", owned.size()));
7192
}
7193
LocalVector<RID> owned_non_shared;
7194
// Free shared first.
7195
for (const RID &texture_rid : owned) {
7196
if (texture_is_shared(texture_rid)) {
7197
#ifdef DEV_ENABLED
7198
if (resource_names.has(texture_rid)) {
7199
print_line(String(" - ") + resource_names[texture_rid]);
7200
}
7201
#endif
7202
free(texture_rid);
7203
} else {
7204
owned_non_shared.push_back(texture_rid);
7205
}
7206
}
7207
// Free non shared second, this will avoid an error trying to free unexisting textures due to dependencies.
7208
for (const RID &texture_rid : owned_non_shared) {
7209
#ifdef DEV_ENABLED
7210
if (resource_names.has(texture_rid)) {
7211
print_line(String(" - ") + resource_names[texture_rid]);
7212
}
7213
#endif
7214
free(texture_rid);
7215
}
7216
}
7217
}
7218
7219
// Erase the transfer workers after all resources have been freed.
7220
_free_transfer_workers();
7221
7222
// Free everything pending.
7223
for (uint32_t i = 0; i < frames.size(); i++) {
7224
int f = (frame + i) % frames.size();
7225
_free_pending_resources(f);
7226
driver->command_pool_free(frames[i].command_pool);
7227
driver->timestamp_query_pool_free(frames[i].timestamp_pool);
7228
driver->semaphore_free(frames[i].semaphore);
7229
driver->fence_free(frames[i].fence);
7230
7231
RDG::CommandBufferPool &buffer_pool = frames[i].command_buffer_pool;
7232
for (uint32_t j = 0; j < buffer_pool.buffers.size(); j++) {
7233
driver->semaphore_free(buffer_pool.semaphores[j]);
7234
}
7235
7236
for (uint32_t j = 0; j < frames[i].transfer_worker_semaphores.size(); j++) {
7237
driver->semaphore_free(frames[i].transfer_worker_semaphores[j]);
7238
}
7239
}
7240
7241
if (pipeline_cache_enabled) {
7242
_update_pipeline_cache(true);
7243
driver->pipeline_cache_free();
7244
}
7245
7246
frames.clear();
7247
7248
for (int i = 0; i < upload_staging_buffers.blocks.size(); i++) {
7249
driver->buffer_free(upload_staging_buffers.blocks[i].driver_id);
7250
}
7251
7252
for (int i = 0; i < download_staging_buffers.blocks.size(); i++) {
7253
driver->buffer_free(download_staging_buffers.blocks[i].driver_id);
7254
}
7255
7256
while (vertex_formats.size()) {
7257
HashMap<VertexFormatID, VertexDescriptionCache>::Iterator temp = vertex_formats.begin();
7258
driver->vertex_format_free(temp->value.driver_id);
7259
vertex_formats.remove(temp);
7260
}
7261
7262
for (KeyValue<FramebufferFormatID, FramebufferFormat> &E : framebuffer_formats) {
7263
driver->render_pass_free(E.value.render_pass);
7264
}
7265
framebuffer_formats.clear();
7266
7267
// Delete the swap chains created for the screens.
7268
for (const KeyValue<DisplayServer::WindowID, RDD::SwapChainID> &it : screen_swap_chains) {
7269
driver->swap_chain_free(it.value);
7270
}
7271
7272
screen_swap_chains.clear();
7273
7274
// Delete the command queues.
7275
if (present_queue) {
7276
if (main_queue != present_queue) {
7277
// Only delete the present queue if it's unique.
7278
driver->command_queue_free(present_queue);
7279
}
7280
7281
present_queue = RDD::CommandQueueID();
7282
}
7283
7284
if (transfer_queue) {
7285
if (main_queue != transfer_queue) {
7286
// Only delete the transfer queue if it's unique.
7287
driver->command_queue_free(transfer_queue);
7288
}
7289
7290
transfer_queue = RDD::CommandQueueID();
7291
}
7292
7293
if (main_queue) {
7294
driver->command_queue_free(main_queue);
7295
main_queue = RDD::CommandQueueID();
7296
}
7297
7298
// Delete the driver once everything else has been deleted.
7299
if (driver != nullptr) {
7300
context->driver_free(driver);
7301
driver = nullptr;
7302
}
7303
7304
// All these should be clear at this point.
7305
ERR_FAIL_COND(dependency_map.size());
7306
ERR_FAIL_COND(reverse_dependency_map.size());
7307
}
7308
7309
void RenderingDevice::_set_max_fps(int p_max_fps) {
7310
for (const KeyValue<DisplayServer::WindowID, RDD::SwapChainID> &it : screen_swap_chains) {
7311
driver->swap_chain_set_max_fps(it.value, p_max_fps);
7312
}
7313
}
7314
7315
RenderingDevice *RenderingDevice::create_local_device() {
7316
RenderingDevice *rd = memnew(RenderingDevice);
7317
if (rd->initialize(context) != OK) {
7318
memdelete(rd);
7319
return nullptr;
7320
}
7321
return rd;
7322
}
7323
7324
bool RenderingDevice::has_feature(const Features p_feature) const {
7325
// Some features can be deduced from the capabilities without querying the driver and looking at the capabilities.
7326
switch (p_feature) {
7327
case SUPPORTS_MULTIVIEW: {
7328
const RDD::MultiviewCapabilities &multiview_capabilities = driver->get_multiview_capabilities();
7329
return multiview_capabilities.is_supported && multiview_capabilities.max_view_count > 1;
7330
}
7331
case SUPPORTS_ATTACHMENT_VRS: {
7332
const RDD::FragmentShadingRateCapabilities &fsr_capabilities = driver->get_fragment_shading_rate_capabilities();
7333
const RDD::FragmentDensityMapCapabilities &fdm_capabilities = driver->get_fragment_density_map_capabilities();
7334
return fsr_capabilities.attachment_supported || fdm_capabilities.attachment_supported;
7335
}
7336
default:
7337
return driver->has_feature(p_feature);
7338
}
7339
}
7340
7341
void RenderingDevice::_bind_methods() {
7342
ClassDB::bind_method(D_METHOD("texture_create", "format", "view", "data"), &RenderingDevice::_texture_create, DEFVAL(Array()));
7343
ClassDB::bind_method(D_METHOD("texture_create_shared", "view", "with_texture"), &RenderingDevice::_texture_create_shared);
7344
ClassDB::bind_method(D_METHOD("texture_create_shared_from_slice", "view", "with_texture", "layer", "mipmap", "mipmaps", "slice_type"), &RenderingDevice::_texture_create_shared_from_slice, DEFVAL(1), DEFVAL(TEXTURE_SLICE_2D));
7345
ClassDB::bind_method(D_METHOD("texture_create_from_extension", "type", "format", "samples", "usage_flags", "image", "width", "height", "depth", "layers", "mipmaps"), &RenderingDevice::texture_create_from_extension, DEFVAL(1));
7346
7347
ClassDB::bind_method(D_METHOD("texture_update", "texture", "layer", "data"), &RenderingDevice::texture_update);
7348
ClassDB::bind_method(D_METHOD("texture_get_data", "texture", "layer"), &RenderingDevice::texture_get_data);
7349
ClassDB::bind_method(D_METHOD("texture_get_data_async", "texture", "layer", "callback"), &RenderingDevice::texture_get_data_async);
7350
7351
ClassDB::bind_method(D_METHOD("texture_is_format_supported_for_usage", "format", "usage_flags"), &RenderingDevice::texture_is_format_supported_for_usage);
7352
7353
ClassDB::bind_method(D_METHOD("texture_is_shared", "texture"), &RenderingDevice::texture_is_shared);
7354
ClassDB::bind_method(D_METHOD("texture_is_valid", "texture"), &RenderingDevice::texture_is_valid);
7355
7356
ClassDB::bind_method(D_METHOD("texture_set_discardable", "texture", "discardable"), &RenderingDevice::texture_set_discardable);
7357
ClassDB::bind_method(D_METHOD("texture_is_discardable", "texture"), &RenderingDevice::texture_is_discardable);
7358
7359
ClassDB::bind_method(D_METHOD("texture_copy", "from_texture", "to_texture", "from_pos", "to_pos", "size", "src_mipmap", "dst_mipmap", "src_layer", "dst_layer"), &RenderingDevice::texture_copy);
7360
ClassDB::bind_method(D_METHOD("texture_clear", "texture", "color", "base_mipmap", "mipmap_count", "base_layer", "layer_count"), &RenderingDevice::texture_clear);
7361
ClassDB::bind_method(D_METHOD("texture_resolve_multisample", "from_texture", "to_texture"), &RenderingDevice::texture_resolve_multisample);
7362
7363
ClassDB::bind_method(D_METHOD("texture_get_format", "texture"), &RenderingDevice::_texture_get_format);
7364
#ifndef DISABLE_DEPRECATED
7365
ClassDB::bind_method(D_METHOD("texture_get_native_handle", "texture"), &RenderingDevice::texture_get_native_handle);
7366
#endif
7367
7368
ClassDB::bind_method(D_METHOD("framebuffer_format_create", "attachments", "view_count"), &RenderingDevice::_framebuffer_format_create, DEFVAL(1));
7369
ClassDB::bind_method(D_METHOD("framebuffer_format_create_multipass", "attachments", "passes", "view_count"), &RenderingDevice::_framebuffer_format_create_multipass, DEFVAL(1));
7370
ClassDB::bind_method(D_METHOD("framebuffer_format_create_empty", "samples"), &RenderingDevice::framebuffer_format_create_empty, DEFVAL(TEXTURE_SAMPLES_1));
7371
ClassDB::bind_method(D_METHOD("framebuffer_format_get_texture_samples", "format", "render_pass"), &RenderingDevice::framebuffer_format_get_texture_samples, DEFVAL(0));
7372
ClassDB::bind_method(D_METHOD("framebuffer_create", "textures", "validate_with_format", "view_count"), &RenderingDevice::_framebuffer_create, DEFVAL(INVALID_FORMAT_ID), DEFVAL(1));
7373
ClassDB::bind_method(D_METHOD("framebuffer_create_multipass", "textures", "passes", "validate_with_format", "view_count"), &RenderingDevice::_framebuffer_create_multipass, DEFVAL(INVALID_FORMAT_ID), DEFVAL(1));
7374
ClassDB::bind_method(D_METHOD("framebuffer_create_empty", "size", "samples", "validate_with_format"), &RenderingDevice::framebuffer_create_empty, DEFVAL(TEXTURE_SAMPLES_1), DEFVAL(INVALID_FORMAT_ID));
7375
ClassDB::bind_method(D_METHOD("framebuffer_get_format", "framebuffer"), &RenderingDevice::framebuffer_get_format);
7376
ClassDB::bind_method(D_METHOD("framebuffer_is_valid", "framebuffer"), &RenderingDevice::framebuffer_is_valid);
7377
7378
ClassDB::bind_method(D_METHOD("sampler_create", "state"), &RenderingDevice::_sampler_create);
7379
ClassDB::bind_method(D_METHOD("sampler_is_format_supported_for_filter", "format", "sampler_filter"), &RenderingDevice::sampler_is_format_supported_for_filter);
7380
7381
ClassDB::bind_method(D_METHOD("vertex_buffer_create", "size_bytes", "data", "creation_bits"), &RenderingDevice::_vertex_buffer_create, DEFVAL(Vector<uint8_t>()), DEFVAL(0));
7382
ClassDB::bind_method(D_METHOD("vertex_format_create", "vertex_descriptions"), &RenderingDevice::_vertex_format_create);
7383
ClassDB::bind_method(D_METHOD("vertex_array_create", "vertex_count", "vertex_format", "src_buffers", "offsets"), &RenderingDevice::_vertex_array_create, DEFVAL(Vector<int64_t>()));
7384
7385
ClassDB::bind_method(D_METHOD("index_buffer_create", "size_indices", "format", "data", "use_restart_indices", "creation_bits"), &RenderingDevice::_index_buffer_create, DEFVAL(Vector<uint8_t>()), DEFVAL(false), DEFVAL(0));
7386
ClassDB::bind_method(D_METHOD("index_array_create", "index_buffer", "index_offset", "index_count"), &RenderingDevice::index_array_create);
7387
7388
ClassDB::bind_method(D_METHOD("shader_compile_spirv_from_source", "shader_source", "allow_cache"), &RenderingDevice::_shader_compile_spirv_from_source, DEFVAL(true));
7389
ClassDB::bind_method(D_METHOD("shader_compile_binary_from_spirv", "spirv_data", "name"), &RenderingDevice::_shader_compile_binary_from_spirv, DEFVAL(""));
7390
ClassDB::bind_method(D_METHOD("shader_create_from_spirv", "spirv_data", "name"), &RenderingDevice::_shader_create_from_spirv, DEFVAL(""));
7391
ClassDB::bind_method(D_METHOD("shader_create_from_bytecode", "binary_data", "placeholder_rid"), &RenderingDevice::shader_create_from_bytecode, DEFVAL(RID()));
7392
ClassDB::bind_method(D_METHOD("shader_create_placeholder"), &RenderingDevice::shader_create_placeholder);
7393
7394
ClassDB::bind_method(D_METHOD("shader_get_vertex_input_attribute_mask", "shader"), &RenderingDevice::shader_get_vertex_input_attribute_mask);
7395
7396
ClassDB::bind_method(D_METHOD("uniform_buffer_create", "size_bytes", "data", "creation_bits"), &RenderingDevice::_uniform_buffer_create, DEFVAL(Vector<uint8_t>()), DEFVAL(0));
7397
ClassDB::bind_method(D_METHOD("storage_buffer_create", "size_bytes", "data", "usage", "creation_bits"), &RenderingDevice::_storage_buffer_create, DEFVAL(Vector<uint8_t>()), DEFVAL(0), DEFVAL(0));
7398
ClassDB::bind_method(D_METHOD("texture_buffer_create", "size_bytes", "format", "data"), &RenderingDevice::_texture_buffer_create, DEFVAL(Vector<uint8_t>()));
7399
7400
ClassDB::bind_method(D_METHOD("uniform_set_create", "uniforms", "shader", "shader_set"), &RenderingDevice::_uniform_set_create);
7401
ClassDB::bind_method(D_METHOD("uniform_set_is_valid", "uniform_set"), &RenderingDevice::uniform_set_is_valid);
7402
7403
ClassDB::bind_method(D_METHOD("buffer_copy", "src_buffer", "dst_buffer", "src_offset", "dst_offset", "size"), &RenderingDevice::buffer_copy);
7404
ClassDB::bind_method(D_METHOD("buffer_update", "buffer", "offset", "size_bytes", "data"), &RenderingDevice::_buffer_update_bind);
7405
ClassDB::bind_method(D_METHOD("buffer_clear", "buffer", "offset", "size_bytes"), &RenderingDevice::buffer_clear);
7406
ClassDB::bind_method(D_METHOD("buffer_get_data", "buffer", "offset_bytes", "size_bytes"), &RenderingDevice::buffer_get_data, DEFVAL(0), DEFVAL(0));
7407
ClassDB::bind_method(D_METHOD("buffer_get_data_async", "buffer", "callback", "offset_bytes", "size_bytes"), &RenderingDevice::buffer_get_data_async, DEFVAL(0), DEFVAL(0));
7408
ClassDB::bind_method(D_METHOD("buffer_get_device_address", "buffer"), &RenderingDevice::buffer_get_device_address);
7409
7410
ClassDB::bind_method(D_METHOD("render_pipeline_create", "shader", "framebuffer_format", "vertex_format", "primitive", "rasterization_state", "multisample_state", "stencil_state", "color_blend_state", "dynamic_state_flags", "for_render_pass", "specialization_constants"), &RenderingDevice::_render_pipeline_create, DEFVAL(0), DEFVAL(0), DEFVAL(TypedArray<RDPipelineSpecializationConstant>()));
7411
ClassDB::bind_method(D_METHOD("render_pipeline_is_valid", "render_pipeline"), &RenderingDevice::render_pipeline_is_valid);
7412
7413
ClassDB::bind_method(D_METHOD("compute_pipeline_create", "shader", "specialization_constants"), &RenderingDevice::_compute_pipeline_create, DEFVAL(TypedArray<RDPipelineSpecializationConstant>()));
7414
ClassDB::bind_method(D_METHOD("compute_pipeline_is_valid", "compute_pipeline"), &RenderingDevice::compute_pipeline_is_valid);
7415
7416
ClassDB::bind_method(D_METHOD("screen_get_width", "screen"), &RenderingDevice::screen_get_width, DEFVAL(DisplayServer::MAIN_WINDOW_ID));
7417
ClassDB::bind_method(D_METHOD("screen_get_height", "screen"), &RenderingDevice::screen_get_height, DEFVAL(DisplayServer::MAIN_WINDOW_ID));
7418
ClassDB::bind_method(D_METHOD("screen_get_framebuffer_format", "screen"), &RenderingDevice::screen_get_framebuffer_format, DEFVAL(DisplayServer::MAIN_WINDOW_ID));
7419
7420
ClassDB::bind_method(D_METHOD("draw_list_begin_for_screen", "screen", "clear_color"), &RenderingDevice::draw_list_begin_for_screen, DEFVAL(DisplayServer::MAIN_WINDOW_ID), DEFVAL(Color()));
7421
7422
ClassDB::bind_method(D_METHOD("draw_list_begin", "framebuffer", "draw_flags", "clear_color_values", "clear_depth_value", "clear_stencil_value", "region", "breadcrumb"), &RenderingDevice::_draw_list_begin_bind, DEFVAL(DRAW_DEFAULT_ALL), DEFVAL(Vector<Color>()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2()), DEFVAL(0));
7423
#ifndef DISABLE_DEPRECATED
7424
ClassDB::bind_method(D_METHOD("draw_list_begin_split", "framebuffer", "splits", "initial_color_action", "final_color_action", "initial_depth_action", "final_depth_action", "clear_color_values", "clear_depth", "clear_stencil", "region", "storage_textures"), &RenderingDevice::_draw_list_begin_split, DEFVAL(Vector<Color>()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2()), DEFVAL(TypedArray<RID>()));
7425
#endif
7426
7427
ClassDB::bind_method(D_METHOD("draw_list_set_blend_constants", "draw_list", "color"), &RenderingDevice::draw_list_set_blend_constants);
7428
ClassDB::bind_method(D_METHOD("draw_list_bind_render_pipeline", "draw_list", "render_pipeline"), &RenderingDevice::draw_list_bind_render_pipeline);
7429
ClassDB::bind_method(D_METHOD("draw_list_bind_uniform_set", "draw_list", "uniform_set", "set_index"), &RenderingDevice::draw_list_bind_uniform_set);
7430
ClassDB::bind_method(D_METHOD("draw_list_bind_vertex_array", "draw_list", "vertex_array"), &RenderingDevice::draw_list_bind_vertex_array);
7431
ClassDB::bind_method(D_METHOD("draw_list_bind_index_array", "draw_list", "index_array"), &RenderingDevice::draw_list_bind_index_array);
7432
ClassDB::bind_method(D_METHOD("draw_list_set_push_constant", "draw_list", "buffer", "size_bytes"), &RenderingDevice::_draw_list_set_push_constant);
7433
7434
ClassDB::bind_method(D_METHOD("draw_list_draw", "draw_list", "use_indices", "instances", "procedural_vertex_count"), &RenderingDevice::draw_list_draw, DEFVAL(0));
7435
ClassDB::bind_method(D_METHOD("draw_list_draw_indirect", "draw_list", "use_indices", "buffer", "offset", "draw_count", "stride"), &RenderingDevice::draw_list_draw_indirect, DEFVAL(0), DEFVAL(1), DEFVAL(0));
7436
7437
ClassDB::bind_method(D_METHOD("draw_list_enable_scissor", "draw_list", "rect"), &RenderingDevice::draw_list_enable_scissor, DEFVAL(Rect2()));
7438
ClassDB::bind_method(D_METHOD("draw_list_disable_scissor", "draw_list"), &RenderingDevice::draw_list_disable_scissor);
7439
7440
ClassDB::bind_method(D_METHOD("draw_list_switch_to_next_pass"), &RenderingDevice::draw_list_switch_to_next_pass);
7441
#ifndef DISABLE_DEPRECATED
7442
ClassDB::bind_method(D_METHOD("draw_list_switch_to_next_pass_split", "splits"), &RenderingDevice::_draw_list_switch_to_next_pass_split);
7443
#endif
7444
7445
ClassDB::bind_method(D_METHOD("draw_list_end"), &RenderingDevice::draw_list_end);
7446
7447
ClassDB::bind_method(D_METHOD("compute_list_begin"), &RenderingDevice::compute_list_begin);
7448
ClassDB::bind_method(D_METHOD("compute_list_bind_compute_pipeline", "compute_list", "compute_pipeline"), &RenderingDevice::compute_list_bind_compute_pipeline);
7449
ClassDB::bind_method(D_METHOD("compute_list_set_push_constant", "compute_list", "buffer", "size_bytes"), &RenderingDevice::_compute_list_set_push_constant);
7450
ClassDB::bind_method(D_METHOD("compute_list_bind_uniform_set", "compute_list", "uniform_set", "set_index"), &RenderingDevice::compute_list_bind_uniform_set);
7451
ClassDB::bind_method(D_METHOD("compute_list_dispatch", "compute_list", "x_groups", "y_groups", "z_groups"), &RenderingDevice::compute_list_dispatch);
7452
ClassDB::bind_method(D_METHOD("compute_list_dispatch_indirect", "compute_list", "buffer", "offset"), &RenderingDevice::compute_list_dispatch_indirect);
7453
ClassDB::bind_method(D_METHOD("compute_list_add_barrier", "compute_list"), &RenderingDevice::compute_list_add_barrier);
7454
ClassDB::bind_method(D_METHOD("compute_list_end"), &RenderingDevice::compute_list_end);
7455
7456
ClassDB::bind_method(D_METHOD("free_rid", "rid"), &RenderingDevice::free);
7457
7458
ClassDB::bind_method(D_METHOD("capture_timestamp", "name"), &RenderingDevice::capture_timestamp);
7459
ClassDB::bind_method(D_METHOD("get_captured_timestamps_count"), &RenderingDevice::get_captured_timestamps_count);
7460
ClassDB::bind_method(D_METHOD("get_captured_timestamps_frame"), &RenderingDevice::get_captured_timestamps_frame);
7461
ClassDB::bind_method(D_METHOD("get_captured_timestamp_gpu_time", "index"), &RenderingDevice::get_captured_timestamp_gpu_time);
7462
ClassDB::bind_method(D_METHOD("get_captured_timestamp_cpu_time", "index"), &RenderingDevice::get_captured_timestamp_cpu_time);
7463
ClassDB::bind_method(D_METHOD("get_captured_timestamp_name", "index"), &RenderingDevice::get_captured_timestamp_name);
7464
7465
ClassDB::bind_method(D_METHOD("has_feature", "feature"), &RenderingDevice::has_feature);
7466
ClassDB::bind_method(D_METHOD("limit_get", "limit"), &RenderingDevice::limit_get);
7467
ClassDB::bind_method(D_METHOD("get_frame_delay"), &RenderingDevice::get_frame_delay);
7468
ClassDB::bind_method(D_METHOD("submit"), &RenderingDevice::submit);
7469
ClassDB::bind_method(D_METHOD("sync"), &RenderingDevice::sync);
7470
7471
#ifndef DISABLE_DEPRECATED
7472
ClassDB::bind_method(D_METHOD("barrier", "from", "to"), &RenderingDevice::barrier, DEFVAL(BARRIER_MASK_ALL_BARRIERS), DEFVAL(BARRIER_MASK_ALL_BARRIERS));
7473
ClassDB::bind_method(D_METHOD("full_barrier"), &RenderingDevice::full_barrier);
7474
#endif
7475
7476
ClassDB::bind_method(D_METHOD("create_local_device"), &RenderingDevice::create_local_device);
7477
7478
ClassDB::bind_method(D_METHOD("set_resource_name", "id", "name"), &RenderingDevice::set_resource_name);
7479
7480
ClassDB::bind_method(D_METHOD("draw_command_begin_label", "name", "color"), &RenderingDevice::_draw_command_begin_label);
7481
#ifndef DISABLE_DEPRECATED
7482
ClassDB::bind_method(D_METHOD("draw_command_insert_label", "name", "color"), &RenderingDevice::draw_command_insert_label);
7483
#endif
7484
ClassDB::bind_method(D_METHOD("draw_command_end_label"), &RenderingDevice::draw_command_end_label);
7485
7486
ClassDB::bind_method(D_METHOD("get_device_vendor_name"), &RenderingDevice::get_device_vendor_name);
7487
ClassDB::bind_method(D_METHOD("get_device_name"), &RenderingDevice::get_device_name);
7488
ClassDB::bind_method(D_METHOD("get_device_pipeline_cache_uuid"), &RenderingDevice::get_device_pipeline_cache_uuid);
7489
7490
ClassDB::bind_method(D_METHOD("get_memory_usage", "type"), &RenderingDevice::get_memory_usage);
7491
7492
ClassDB::bind_method(D_METHOD("get_driver_resource", "resource", "rid", "index"), &RenderingDevice::get_driver_resource);
7493
7494
ClassDB::bind_method(D_METHOD("get_perf_report"), &RenderingDevice::get_perf_report);
7495
7496
ClassDB::bind_method(D_METHOD("get_driver_and_device_memory_report"), &RenderingDevice::get_driver_and_device_memory_report);
7497
ClassDB::bind_method(D_METHOD("get_tracked_object_name", "type_index"), &RenderingDevice::get_tracked_object_name);
7498
ClassDB::bind_method(D_METHOD("get_tracked_object_type_count"), &RenderingDevice::get_tracked_object_type_count);
7499
ClassDB::bind_method(D_METHOD("get_driver_total_memory"), &RenderingDevice::get_driver_total_memory);
7500
ClassDB::bind_method(D_METHOD("get_driver_allocation_count"), &RenderingDevice::get_driver_allocation_count);
7501
ClassDB::bind_method(D_METHOD("get_driver_memory_by_object_type", "type"), &RenderingDevice::get_driver_memory_by_object_type);
7502
ClassDB::bind_method(D_METHOD("get_driver_allocs_by_object_type", "type"), &RenderingDevice::get_driver_allocs_by_object_type);
7503
ClassDB::bind_method(D_METHOD("get_device_total_memory"), &RenderingDevice::get_device_total_memory);
7504
ClassDB::bind_method(D_METHOD("get_device_allocation_count"), &RenderingDevice::get_device_allocation_count);
7505
ClassDB::bind_method(D_METHOD("get_device_memory_by_object_type", "type"), &RenderingDevice::get_device_memory_by_object_type);
7506
ClassDB::bind_method(D_METHOD("get_device_allocs_by_object_type", "type"), &RenderingDevice::get_device_allocs_by_object_type);
7507
7508
BIND_ENUM_CONSTANT(DEVICE_TYPE_OTHER);
7509
BIND_ENUM_CONSTANT(DEVICE_TYPE_INTEGRATED_GPU);
7510
BIND_ENUM_CONSTANT(DEVICE_TYPE_DISCRETE_GPU);
7511
BIND_ENUM_CONSTANT(DEVICE_TYPE_VIRTUAL_GPU);
7512
BIND_ENUM_CONSTANT(DEVICE_TYPE_CPU);
7513
BIND_ENUM_CONSTANT(DEVICE_TYPE_MAX);
7514
7515
BIND_ENUM_CONSTANT(DRIVER_RESOURCE_LOGICAL_DEVICE);
7516
BIND_ENUM_CONSTANT(DRIVER_RESOURCE_PHYSICAL_DEVICE);
7517
BIND_ENUM_CONSTANT(DRIVER_RESOURCE_TOPMOST_OBJECT);
7518
BIND_ENUM_CONSTANT(DRIVER_RESOURCE_COMMAND_QUEUE);
7519
BIND_ENUM_CONSTANT(DRIVER_RESOURCE_QUEUE_FAMILY);
7520
BIND_ENUM_CONSTANT(DRIVER_RESOURCE_TEXTURE);
7521
BIND_ENUM_CONSTANT(DRIVER_RESOURCE_TEXTURE_VIEW);
7522
BIND_ENUM_CONSTANT(DRIVER_RESOURCE_TEXTURE_DATA_FORMAT);
7523
BIND_ENUM_CONSTANT(DRIVER_RESOURCE_SAMPLER);
7524
BIND_ENUM_CONSTANT(DRIVER_RESOURCE_UNIFORM_SET);
7525
BIND_ENUM_CONSTANT(DRIVER_RESOURCE_BUFFER);
7526
BIND_ENUM_CONSTANT(DRIVER_RESOURCE_COMPUTE_PIPELINE);
7527
BIND_ENUM_CONSTANT(DRIVER_RESOURCE_RENDER_PIPELINE);
7528
#ifndef DISABLE_DEPRECATED
7529
BIND_ENUM_CONSTANT(DRIVER_RESOURCE_VULKAN_DEVICE);
7530
BIND_ENUM_CONSTANT(DRIVER_RESOURCE_VULKAN_PHYSICAL_DEVICE);
7531
BIND_ENUM_CONSTANT(DRIVER_RESOURCE_VULKAN_INSTANCE);
7532
BIND_ENUM_CONSTANT(DRIVER_RESOURCE_VULKAN_QUEUE);
7533
BIND_ENUM_CONSTANT(DRIVER_RESOURCE_VULKAN_QUEUE_FAMILY_INDEX);
7534
BIND_ENUM_CONSTANT(DRIVER_RESOURCE_VULKAN_IMAGE);
7535
BIND_ENUM_CONSTANT(DRIVER_RESOURCE_VULKAN_IMAGE_VIEW);
7536
BIND_ENUM_CONSTANT(DRIVER_RESOURCE_VULKAN_IMAGE_NATIVE_TEXTURE_FORMAT);
7537
BIND_ENUM_CONSTANT(DRIVER_RESOURCE_VULKAN_SAMPLER);
7538
BIND_ENUM_CONSTANT(DRIVER_RESOURCE_VULKAN_DESCRIPTOR_SET);
7539
BIND_ENUM_CONSTANT(DRIVER_RESOURCE_VULKAN_BUFFER);
7540
BIND_ENUM_CONSTANT(DRIVER_RESOURCE_VULKAN_COMPUTE_PIPELINE);
7541
BIND_ENUM_CONSTANT(DRIVER_RESOURCE_VULKAN_RENDER_PIPELINE);
7542
#endif
7543
7544
BIND_ENUM_CONSTANT(DATA_FORMAT_R4G4_UNORM_PACK8);
7545
BIND_ENUM_CONSTANT(DATA_FORMAT_R4G4B4A4_UNORM_PACK16);
7546
BIND_ENUM_CONSTANT(DATA_FORMAT_B4G4R4A4_UNORM_PACK16);
7547
BIND_ENUM_CONSTANT(DATA_FORMAT_R5G6B5_UNORM_PACK16);
7548
BIND_ENUM_CONSTANT(DATA_FORMAT_B5G6R5_UNORM_PACK16);
7549
BIND_ENUM_CONSTANT(DATA_FORMAT_R5G5B5A1_UNORM_PACK16);
7550
BIND_ENUM_CONSTANT(DATA_FORMAT_B5G5R5A1_UNORM_PACK16);
7551
BIND_ENUM_CONSTANT(DATA_FORMAT_A1R5G5B5_UNORM_PACK16);
7552
BIND_ENUM_CONSTANT(DATA_FORMAT_R8_UNORM);
7553
BIND_ENUM_CONSTANT(DATA_FORMAT_R8_SNORM);
7554
BIND_ENUM_CONSTANT(DATA_FORMAT_R8_USCALED);
7555
BIND_ENUM_CONSTANT(DATA_FORMAT_R8_SSCALED);
7556
BIND_ENUM_CONSTANT(DATA_FORMAT_R8_UINT);
7557
BIND_ENUM_CONSTANT(DATA_FORMAT_R8_SINT);
7558
BIND_ENUM_CONSTANT(DATA_FORMAT_R8_SRGB);
7559
BIND_ENUM_CONSTANT(DATA_FORMAT_R8G8_UNORM);
7560
BIND_ENUM_CONSTANT(DATA_FORMAT_R8G8_SNORM);
7561
BIND_ENUM_CONSTANT(DATA_FORMAT_R8G8_USCALED);
7562
BIND_ENUM_CONSTANT(DATA_FORMAT_R8G8_SSCALED);
7563
BIND_ENUM_CONSTANT(DATA_FORMAT_R8G8_UINT);
7564
BIND_ENUM_CONSTANT(DATA_FORMAT_R8G8_SINT);
7565
BIND_ENUM_CONSTANT(DATA_FORMAT_R8G8_SRGB);
7566
BIND_ENUM_CONSTANT(DATA_FORMAT_R8G8B8_UNORM);
7567
BIND_ENUM_CONSTANT(DATA_FORMAT_R8G8B8_SNORM);
7568
BIND_ENUM_CONSTANT(DATA_FORMAT_R8G8B8_USCALED);
7569
BIND_ENUM_CONSTANT(DATA_FORMAT_R8G8B8_SSCALED);
7570
BIND_ENUM_CONSTANT(DATA_FORMAT_R8G8B8_UINT);
7571
BIND_ENUM_CONSTANT(DATA_FORMAT_R8G8B8_SINT);
7572
BIND_ENUM_CONSTANT(DATA_FORMAT_R8G8B8_SRGB);
7573
BIND_ENUM_CONSTANT(DATA_FORMAT_B8G8R8_UNORM);
7574
BIND_ENUM_CONSTANT(DATA_FORMAT_B8G8R8_SNORM);
7575
BIND_ENUM_CONSTANT(DATA_FORMAT_B8G8R8_USCALED);
7576
BIND_ENUM_CONSTANT(DATA_FORMAT_B8G8R8_SSCALED);
7577
BIND_ENUM_CONSTANT(DATA_FORMAT_B8G8R8_UINT);
7578
BIND_ENUM_CONSTANT(DATA_FORMAT_B8G8R8_SINT);
7579
BIND_ENUM_CONSTANT(DATA_FORMAT_B8G8R8_SRGB);
7580
BIND_ENUM_CONSTANT(DATA_FORMAT_R8G8B8A8_UNORM);
7581
BIND_ENUM_CONSTANT(DATA_FORMAT_R8G8B8A8_SNORM);
7582
BIND_ENUM_CONSTANT(DATA_FORMAT_R8G8B8A8_USCALED);
7583
BIND_ENUM_CONSTANT(DATA_FORMAT_R8G8B8A8_SSCALED);
7584
BIND_ENUM_CONSTANT(DATA_FORMAT_R8G8B8A8_UINT);
7585
BIND_ENUM_CONSTANT(DATA_FORMAT_R8G8B8A8_SINT);
7586
BIND_ENUM_CONSTANT(DATA_FORMAT_R8G8B8A8_SRGB);
7587
BIND_ENUM_CONSTANT(DATA_FORMAT_B8G8R8A8_UNORM);
7588
BIND_ENUM_CONSTANT(DATA_FORMAT_B8G8R8A8_SNORM);
7589
BIND_ENUM_CONSTANT(DATA_FORMAT_B8G8R8A8_USCALED);
7590
BIND_ENUM_CONSTANT(DATA_FORMAT_B8G8R8A8_SSCALED);
7591
BIND_ENUM_CONSTANT(DATA_FORMAT_B8G8R8A8_UINT);
7592
BIND_ENUM_CONSTANT(DATA_FORMAT_B8G8R8A8_SINT);
7593
BIND_ENUM_CONSTANT(DATA_FORMAT_B8G8R8A8_SRGB);
7594
BIND_ENUM_CONSTANT(DATA_FORMAT_A8B8G8R8_UNORM_PACK32);
7595
BIND_ENUM_CONSTANT(DATA_FORMAT_A8B8G8R8_SNORM_PACK32);
7596
BIND_ENUM_CONSTANT(DATA_FORMAT_A8B8G8R8_USCALED_PACK32);
7597
BIND_ENUM_CONSTANT(DATA_FORMAT_A8B8G8R8_SSCALED_PACK32);
7598
BIND_ENUM_CONSTANT(DATA_FORMAT_A8B8G8R8_UINT_PACK32);
7599
BIND_ENUM_CONSTANT(DATA_FORMAT_A8B8G8R8_SINT_PACK32);
7600
BIND_ENUM_CONSTANT(DATA_FORMAT_A8B8G8R8_SRGB_PACK32);
7601
BIND_ENUM_CONSTANT(DATA_FORMAT_A2R10G10B10_UNORM_PACK32);
7602
BIND_ENUM_CONSTANT(DATA_FORMAT_A2R10G10B10_SNORM_PACK32);
7603
BIND_ENUM_CONSTANT(DATA_FORMAT_A2R10G10B10_USCALED_PACK32);
7604
BIND_ENUM_CONSTANT(DATA_FORMAT_A2R10G10B10_SSCALED_PACK32);
7605
BIND_ENUM_CONSTANT(DATA_FORMAT_A2R10G10B10_UINT_PACK32);
7606
BIND_ENUM_CONSTANT(DATA_FORMAT_A2R10G10B10_SINT_PACK32);
7607
BIND_ENUM_CONSTANT(DATA_FORMAT_A2B10G10R10_UNORM_PACK32);
7608
BIND_ENUM_CONSTANT(DATA_FORMAT_A2B10G10R10_SNORM_PACK32);
7609
BIND_ENUM_CONSTANT(DATA_FORMAT_A2B10G10R10_USCALED_PACK32);
7610
BIND_ENUM_CONSTANT(DATA_FORMAT_A2B10G10R10_SSCALED_PACK32);
7611
BIND_ENUM_CONSTANT(DATA_FORMAT_A2B10G10R10_UINT_PACK32);
7612
BIND_ENUM_CONSTANT(DATA_FORMAT_A2B10G10R10_SINT_PACK32);
7613
BIND_ENUM_CONSTANT(DATA_FORMAT_R16_UNORM);
7614
BIND_ENUM_CONSTANT(DATA_FORMAT_R16_SNORM);
7615
BIND_ENUM_CONSTANT(DATA_FORMAT_R16_USCALED);
7616
BIND_ENUM_CONSTANT(DATA_FORMAT_R16_SSCALED);
7617
BIND_ENUM_CONSTANT(DATA_FORMAT_R16_UINT);
7618
BIND_ENUM_CONSTANT(DATA_FORMAT_R16_SINT);
7619
BIND_ENUM_CONSTANT(DATA_FORMAT_R16_SFLOAT);
7620
BIND_ENUM_CONSTANT(DATA_FORMAT_R16G16_UNORM);
7621
BIND_ENUM_CONSTANT(DATA_FORMAT_R16G16_SNORM);
7622
BIND_ENUM_CONSTANT(DATA_FORMAT_R16G16_USCALED);
7623
BIND_ENUM_CONSTANT(DATA_FORMAT_R16G16_SSCALED);
7624
BIND_ENUM_CONSTANT(DATA_FORMAT_R16G16_UINT);
7625
BIND_ENUM_CONSTANT(DATA_FORMAT_R16G16_SINT);
7626
BIND_ENUM_CONSTANT(DATA_FORMAT_R16G16_SFLOAT);
7627
BIND_ENUM_CONSTANT(DATA_FORMAT_R16G16B16_UNORM);
7628
BIND_ENUM_CONSTANT(DATA_FORMAT_R16G16B16_SNORM);
7629
BIND_ENUM_CONSTANT(DATA_FORMAT_R16G16B16_USCALED);
7630
BIND_ENUM_CONSTANT(DATA_FORMAT_R16G16B16_SSCALED);
7631
BIND_ENUM_CONSTANT(DATA_FORMAT_R16G16B16_UINT);
7632
BIND_ENUM_CONSTANT(DATA_FORMAT_R16G16B16_SINT);
7633
BIND_ENUM_CONSTANT(DATA_FORMAT_R16G16B16_SFLOAT);
7634
BIND_ENUM_CONSTANT(DATA_FORMAT_R16G16B16A16_UNORM);
7635
BIND_ENUM_CONSTANT(DATA_FORMAT_R16G16B16A16_SNORM);
7636
BIND_ENUM_CONSTANT(DATA_FORMAT_R16G16B16A16_USCALED);
7637
BIND_ENUM_CONSTANT(DATA_FORMAT_R16G16B16A16_SSCALED);
7638
BIND_ENUM_CONSTANT(DATA_FORMAT_R16G16B16A16_UINT);
7639
BIND_ENUM_CONSTANT(DATA_FORMAT_R16G16B16A16_SINT);
7640
BIND_ENUM_CONSTANT(DATA_FORMAT_R16G16B16A16_SFLOAT);
7641
BIND_ENUM_CONSTANT(DATA_FORMAT_R32_UINT);
7642
BIND_ENUM_CONSTANT(DATA_FORMAT_R32_SINT);
7643
BIND_ENUM_CONSTANT(DATA_FORMAT_R32_SFLOAT);
7644
BIND_ENUM_CONSTANT(DATA_FORMAT_R32G32_UINT);
7645
BIND_ENUM_CONSTANT(DATA_FORMAT_R32G32_SINT);
7646
BIND_ENUM_CONSTANT(DATA_FORMAT_R32G32_SFLOAT);
7647
BIND_ENUM_CONSTANT(DATA_FORMAT_R32G32B32_UINT);
7648
BIND_ENUM_CONSTANT(DATA_FORMAT_R32G32B32_SINT);
7649
BIND_ENUM_CONSTANT(DATA_FORMAT_R32G32B32_SFLOAT);
7650
BIND_ENUM_CONSTANT(DATA_FORMAT_R32G32B32A32_UINT);
7651
BIND_ENUM_CONSTANT(DATA_FORMAT_R32G32B32A32_SINT);
7652
BIND_ENUM_CONSTANT(DATA_FORMAT_R32G32B32A32_SFLOAT);
7653
BIND_ENUM_CONSTANT(DATA_FORMAT_R64_UINT);
7654
BIND_ENUM_CONSTANT(DATA_FORMAT_R64_SINT);
7655
BIND_ENUM_CONSTANT(DATA_FORMAT_R64_SFLOAT);
7656
BIND_ENUM_CONSTANT(DATA_FORMAT_R64G64_UINT);
7657
BIND_ENUM_CONSTANT(DATA_FORMAT_R64G64_SINT);
7658
BIND_ENUM_CONSTANT(DATA_FORMAT_R64G64_SFLOAT);
7659
BIND_ENUM_CONSTANT(DATA_FORMAT_R64G64B64_UINT);
7660
BIND_ENUM_CONSTANT(DATA_FORMAT_R64G64B64_SINT);
7661
BIND_ENUM_CONSTANT(DATA_FORMAT_R64G64B64_SFLOAT);
7662
BIND_ENUM_CONSTANT(DATA_FORMAT_R64G64B64A64_UINT);
7663
BIND_ENUM_CONSTANT(DATA_FORMAT_R64G64B64A64_SINT);
7664
BIND_ENUM_CONSTANT(DATA_FORMAT_R64G64B64A64_SFLOAT);
7665
BIND_ENUM_CONSTANT(DATA_FORMAT_B10G11R11_UFLOAT_PACK32);
7666
BIND_ENUM_CONSTANT(DATA_FORMAT_E5B9G9R9_UFLOAT_PACK32);
7667
BIND_ENUM_CONSTANT(DATA_FORMAT_D16_UNORM);
7668
BIND_ENUM_CONSTANT(DATA_FORMAT_X8_D24_UNORM_PACK32);
7669
BIND_ENUM_CONSTANT(DATA_FORMAT_D32_SFLOAT);
7670
BIND_ENUM_CONSTANT(DATA_FORMAT_S8_UINT);
7671
BIND_ENUM_CONSTANT(DATA_FORMAT_D16_UNORM_S8_UINT);
7672
BIND_ENUM_CONSTANT(DATA_FORMAT_D24_UNORM_S8_UINT);
7673
BIND_ENUM_CONSTANT(DATA_FORMAT_D32_SFLOAT_S8_UINT);
7674
BIND_ENUM_CONSTANT(DATA_FORMAT_BC1_RGB_UNORM_BLOCK);
7675
BIND_ENUM_CONSTANT(DATA_FORMAT_BC1_RGB_SRGB_BLOCK);
7676
BIND_ENUM_CONSTANT(DATA_FORMAT_BC1_RGBA_UNORM_BLOCK);
7677
BIND_ENUM_CONSTANT(DATA_FORMAT_BC1_RGBA_SRGB_BLOCK);
7678
BIND_ENUM_CONSTANT(DATA_FORMAT_BC2_UNORM_BLOCK);
7679
BIND_ENUM_CONSTANT(DATA_FORMAT_BC2_SRGB_BLOCK);
7680
BIND_ENUM_CONSTANT(DATA_FORMAT_BC3_UNORM_BLOCK);
7681
BIND_ENUM_CONSTANT(DATA_FORMAT_BC3_SRGB_BLOCK);
7682
BIND_ENUM_CONSTANT(DATA_FORMAT_BC4_UNORM_BLOCK);
7683
BIND_ENUM_CONSTANT(DATA_FORMAT_BC4_SNORM_BLOCK);
7684
BIND_ENUM_CONSTANT(DATA_FORMAT_BC5_UNORM_BLOCK);
7685
BIND_ENUM_CONSTANT(DATA_FORMAT_BC5_SNORM_BLOCK);
7686
BIND_ENUM_CONSTANT(DATA_FORMAT_BC6H_UFLOAT_BLOCK);
7687
BIND_ENUM_CONSTANT(DATA_FORMAT_BC6H_SFLOAT_BLOCK);
7688
BIND_ENUM_CONSTANT(DATA_FORMAT_BC7_UNORM_BLOCK);
7689
BIND_ENUM_CONSTANT(DATA_FORMAT_BC7_SRGB_BLOCK);
7690
BIND_ENUM_CONSTANT(DATA_FORMAT_ETC2_R8G8B8_UNORM_BLOCK);
7691
BIND_ENUM_CONSTANT(DATA_FORMAT_ETC2_R8G8B8_SRGB_BLOCK);
7692
BIND_ENUM_CONSTANT(DATA_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK);
7693
BIND_ENUM_CONSTANT(DATA_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK);
7694
BIND_ENUM_CONSTANT(DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK);
7695
BIND_ENUM_CONSTANT(DATA_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK);
7696
BIND_ENUM_CONSTANT(DATA_FORMAT_EAC_R11_UNORM_BLOCK);
7697
BIND_ENUM_CONSTANT(DATA_FORMAT_EAC_R11_SNORM_BLOCK);
7698
BIND_ENUM_CONSTANT(DATA_FORMAT_EAC_R11G11_UNORM_BLOCK);
7699
BIND_ENUM_CONSTANT(DATA_FORMAT_EAC_R11G11_SNORM_BLOCK);
7700
BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_4x4_UNORM_BLOCK);
7701
BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_4x4_SRGB_BLOCK);
7702
BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_5x4_UNORM_BLOCK);
7703
BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_5x4_SRGB_BLOCK);
7704
BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_5x5_UNORM_BLOCK);
7705
BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_5x5_SRGB_BLOCK);
7706
BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_6x5_UNORM_BLOCK);
7707
BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_6x5_SRGB_BLOCK);
7708
BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_6x6_UNORM_BLOCK);
7709
BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_6x6_SRGB_BLOCK);
7710
BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_8x5_UNORM_BLOCK);
7711
BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_8x5_SRGB_BLOCK);
7712
BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_8x6_UNORM_BLOCK);
7713
BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_8x6_SRGB_BLOCK);
7714
BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_8x8_UNORM_BLOCK);
7715
BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_8x8_SRGB_BLOCK);
7716
BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_10x5_UNORM_BLOCK);
7717
BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_10x5_SRGB_BLOCK);
7718
BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_10x6_UNORM_BLOCK);
7719
BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_10x6_SRGB_BLOCK);
7720
BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_10x8_UNORM_BLOCK);
7721
BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_10x8_SRGB_BLOCK);
7722
BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_10x10_UNORM_BLOCK);
7723
BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_10x10_SRGB_BLOCK);
7724
BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_12x10_UNORM_BLOCK);
7725
BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_12x10_SRGB_BLOCK);
7726
BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_12x12_UNORM_BLOCK);
7727
BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_12x12_SRGB_BLOCK);
7728
BIND_ENUM_CONSTANT(DATA_FORMAT_G8B8G8R8_422_UNORM);
7729
BIND_ENUM_CONSTANT(DATA_FORMAT_B8G8R8G8_422_UNORM);
7730
BIND_ENUM_CONSTANT(DATA_FORMAT_G8_B8_R8_3PLANE_420_UNORM);
7731
BIND_ENUM_CONSTANT(DATA_FORMAT_G8_B8R8_2PLANE_420_UNORM);
7732
BIND_ENUM_CONSTANT(DATA_FORMAT_G8_B8_R8_3PLANE_422_UNORM);
7733
BIND_ENUM_CONSTANT(DATA_FORMAT_G8_B8R8_2PLANE_422_UNORM);
7734
BIND_ENUM_CONSTANT(DATA_FORMAT_G8_B8_R8_3PLANE_444_UNORM);
7735
BIND_ENUM_CONSTANT(DATA_FORMAT_R10X6_UNORM_PACK16);
7736
BIND_ENUM_CONSTANT(DATA_FORMAT_R10X6G10X6_UNORM_2PACK16);
7737
BIND_ENUM_CONSTANT(DATA_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16);
7738
BIND_ENUM_CONSTANT(DATA_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16);
7739
BIND_ENUM_CONSTANT(DATA_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16);
7740
BIND_ENUM_CONSTANT(DATA_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16);
7741
BIND_ENUM_CONSTANT(DATA_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16);
7742
BIND_ENUM_CONSTANT(DATA_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16);
7743
BIND_ENUM_CONSTANT(DATA_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16);
7744
BIND_ENUM_CONSTANT(DATA_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16);
7745
BIND_ENUM_CONSTANT(DATA_FORMAT_R12X4_UNORM_PACK16);
7746
BIND_ENUM_CONSTANT(DATA_FORMAT_R12X4G12X4_UNORM_2PACK16);
7747
BIND_ENUM_CONSTANT(DATA_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16);
7748
BIND_ENUM_CONSTANT(DATA_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16);
7749
BIND_ENUM_CONSTANT(DATA_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16);
7750
BIND_ENUM_CONSTANT(DATA_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16);
7751
BIND_ENUM_CONSTANT(DATA_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16);
7752
BIND_ENUM_CONSTANT(DATA_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16);
7753
BIND_ENUM_CONSTANT(DATA_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16);
7754
BIND_ENUM_CONSTANT(DATA_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16);
7755
BIND_ENUM_CONSTANT(DATA_FORMAT_G16B16G16R16_422_UNORM);
7756
BIND_ENUM_CONSTANT(DATA_FORMAT_B16G16R16G16_422_UNORM);
7757
BIND_ENUM_CONSTANT(DATA_FORMAT_G16_B16_R16_3PLANE_420_UNORM);
7758
BIND_ENUM_CONSTANT(DATA_FORMAT_G16_B16R16_2PLANE_420_UNORM);
7759
BIND_ENUM_CONSTANT(DATA_FORMAT_G16_B16_R16_3PLANE_422_UNORM);
7760
BIND_ENUM_CONSTANT(DATA_FORMAT_G16_B16R16_2PLANE_422_UNORM);
7761
BIND_ENUM_CONSTANT(DATA_FORMAT_G16_B16_R16_3PLANE_444_UNORM);
7762
BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_4x4_SFLOAT_BLOCK);
7763
BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_5x4_SFLOAT_BLOCK);
7764
BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_5x5_SFLOAT_BLOCK);
7765
BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_6x5_SFLOAT_BLOCK);
7766
BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_6x6_SFLOAT_BLOCK);
7767
BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_8x5_SFLOAT_BLOCK);
7768
BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_8x6_SFLOAT_BLOCK);
7769
BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_8x8_SFLOAT_BLOCK);
7770
BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_10x5_SFLOAT_BLOCK);
7771
BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_10x6_SFLOAT_BLOCK);
7772
BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_10x8_SFLOAT_BLOCK);
7773
BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_10x10_SFLOAT_BLOCK);
7774
BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_12x10_SFLOAT_BLOCK);
7775
BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_12x12_SFLOAT_BLOCK);
7776
BIND_ENUM_CONSTANT(DATA_FORMAT_MAX);
7777
7778
#ifndef DISABLE_DEPRECATED
7779
BIND_BITFIELD_FLAG(BARRIER_MASK_VERTEX);
7780
BIND_BITFIELD_FLAG(BARRIER_MASK_FRAGMENT);
7781
BIND_BITFIELD_FLAG(BARRIER_MASK_COMPUTE);
7782
BIND_BITFIELD_FLAG(BARRIER_MASK_TRANSFER);
7783
BIND_BITFIELD_FLAG(BARRIER_MASK_RASTER);
7784
BIND_BITFIELD_FLAG(BARRIER_MASK_ALL_BARRIERS);
7785
BIND_BITFIELD_FLAG(BARRIER_MASK_NO_BARRIER);
7786
#endif
7787
7788
BIND_ENUM_CONSTANT(TEXTURE_TYPE_1D);
7789
BIND_ENUM_CONSTANT(TEXTURE_TYPE_2D);
7790
BIND_ENUM_CONSTANT(TEXTURE_TYPE_3D);
7791
BIND_ENUM_CONSTANT(TEXTURE_TYPE_CUBE);
7792
BIND_ENUM_CONSTANT(TEXTURE_TYPE_1D_ARRAY);
7793
BIND_ENUM_CONSTANT(TEXTURE_TYPE_2D_ARRAY);
7794
BIND_ENUM_CONSTANT(TEXTURE_TYPE_CUBE_ARRAY);
7795
BIND_ENUM_CONSTANT(TEXTURE_TYPE_MAX);
7796
7797
BIND_ENUM_CONSTANT(TEXTURE_SAMPLES_1);
7798
BIND_ENUM_CONSTANT(TEXTURE_SAMPLES_2);
7799
BIND_ENUM_CONSTANT(TEXTURE_SAMPLES_4);
7800
BIND_ENUM_CONSTANT(TEXTURE_SAMPLES_8);
7801
BIND_ENUM_CONSTANT(TEXTURE_SAMPLES_16);
7802
BIND_ENUM_CONSTANT(TEXTURE_SAMPLES_32);
7803
BIND_ENUM_CONSTANT(TEXTURE_SAMPLES_64);
7804
BIND_ENUM_CONSTANT(TEXTURE_SAMPLES_MAX);
7805
7806
BIND_BITFIELD_FLAG(TEXTURE_USAGE_SAMPLING_BIT);
7807
BIND_BITFIELD_FLAG(TEXTURE_USAGE_COLOR_ATTACHMENT_BIT);
7808
BIND_BITFIELD_FLAG(TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
7809
BIND_BITFIELD_FLAG(TEXTURE_USAGE_STORAGE_BIT);
7810
BIND_BITFIELD_FLAG(TEXTURE_USAGE_STORAGE_ATOMIC_BIT);
7811
BIND_BITFIELD_FLAG(TEXTURE_USAGE_CPU_READ_BIT);
7812
BIND_BITFIELD_FLAG(TEXTURE_USAGE_CAN_UPDATE_BIT);
7813
BIND_BITFIELD_FLAG(TEXTURE_USAGE_CAN_COPY_FROM_BIT);
7814
BIND_BITFIELD_FLAG(TEXTURE_USAGE_CAN_COPY_TO_BIT);
7815
BIND_BITFIELD_FLAG(TEXTURE_USAGE_INPUT_ATTACHMENT_BIT);
7816
7817
BIND_ENUM_CONSTANT(TEXTURE_SWIZZLE_IDENTITY);
7818
BIND_ENUM_CONSTANT(TEXTURE_SWIZZLE_ZERO);
7819
BIND_ENUM_CONSTANT(TEXTURE_SWIZZLE_ONE);
7820
BIND_ENUM_CONSTANT(TEXTURE_SWIZZLE_R);
7821
BIND_ENUM_CONSTANT(TEXTURE_SWIZZLE_G);
7822
BIND_ENUM_CONSTANT(TEXTURE_SWIZZLE_B);
7823
BIND_ENUM_CONSTANT(TEXTURE_SWIZZLE_A);
7824
BIND_ENUM_CONSTANT(TEXTURE_SWIZZLE_MAX);
7825
7826
BIND_ENUM_CONSTANT(TEXTURE_SLICE_2D);
7827
BIND_ENUM_CONSTANT(TEXTURE_SLICE_CUBEMAP);
7828
BIND_ENUM_CONSTANT(TEXTURE_SLICE_3D);
7829
7830
BIND_ENUM_CONSTANT(SAMPLER_FILTER_NEAREST);
7831
BIND_ENUM_CONSTANT(SAMPLER_FILTER_LINEAR);
7832
BIND_ENUM_CONSTANT(SAMPLER_REPEAT_MODE_REPEAT);
7833
BIND_ENUM_CONSTANT(SAMPLER_REPEAT_MODE_MIRRORED_REPEAT);
7834
BIND_ENUM_CONSTANT(SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE);
7835
BIND_ENUM_CONSTANT(SAMPLER_REPEAT_MODE_CLAMP_TO_BORDER);
7836
BIND_ENUM_CONSTANT(SAMPLER_REPEAT_MODE_MIRROR_CLAMP_TO_EDGE);
7837
BIND_ENUM_CONSTANT(SAMPLER_REPEAT_MODE_MAX);
7838
7839
BIND_ENUM_CONSTANT(SAMPLER_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK);
7840
BIND_ENUM_CONSTANT(SAMPLER_BORDER_COLOR_INT_TRANSPARENT_BLACK);
7841
BIND_ENUM_CONSTANT(SAMPLER_BORDER_COLOR_FLOAT_OPAQUE_BLACK);
7842
BIND_ENUM_CONSTANT(SAMPLER_BORDER_COLOR_INT_OPAQUE_BLACK);
7843
BIND_ENUM_CONSTANT(SAMPLER_BORDER_COLOR_FLOAT_OPAQUE_WHITE);
7844
BIND_ENUM_CONSTANT(SAMPLER_BORDER_COLOR_INT_OPAQUE_WHITE);
7845
BIND_ENUM_CONSTANT(SAMPLER_BORDER_COLOR_MAX);
7846
7847
BIND_ENUM_CONSTANT(VERTEX_FREQUENCY_VERTEX);
7848
BIND_ENUM_CONSTANT(VERTEX_FREQUENCY_INSTANCE);
7849
7850
BIND_ENUM_CONSTANT(INDEX_BUFFER_FORMAT_UINT16);
7851
BIND_ENUM_CONSTANT(INDEX_BUFFER_FORMAT_UINT32);
7852
7853
BIND_BITFIELD_FLAG(STORAGE_BUFFER_USAGE_DISPATCH_INDIRECT);
7854
7855
BIND_BITFIELD_FLAG(BUFFER_CREATION_DEVICE_ADDRESS_BIT);
7856
BIND_BITFIELD_FLAG(BUFFER_CREATION_AS_STORAGE_BIT);
7857
7858
BIND_ENUM_CONSTANT(UNIFORM_TYPE_SAMPLER); //for sampling only (sampler GLSL type)
7859
BIND_ENUM_CONSTANT(UNIFORM_TYPE_SAMPLER_WITH_TEXTURE); // for sampling only); but includes a texture); (samplerXX GLSL type)); first a sampler then a texture
7860
BIND_ENUM_CONSTANT(UNIFORM_TYPE_TEXTURE); //only texture); (textureXX GLSL type)
7861
BIND_ENUM_CONSTANT(UNIFORM_TYPE_IMAGE); // storage image (imageXX GLSL type)); for compute mostly
7862
BIND_ENUM_CONSTANT(UNIFORM_TYPE_TEXTURE_BUFFER); // buffer texture (or TBO); textureBuffer type)
7863
BIND_ENUM_CONSTANT(UNIFORM_TYPE_SAMPLER_WITH_TEXTURE_BUFFER); // buffer texture with a sampler(or TBO); samplerBuffer type)
7864
BIND_ENUM_CONSTANT(UNIFORM_TYPE_IMAGE_BUFFER); //texel buffer); (imageBuffer type)); for compute mostly
7865
BIND_ENUM_CONSTANT(UNIFORM_TYPE_UNIFORM_BUFFER); //regular uniform buffer (or UBO).
7866
BIND_ENUM_CONSTANT(UNIFORM_TYPE_STORAGE_BUFFER); //storage buffer ("buffer" qualifier) like UBO); but supports storage); for compute mostly
7867
BIND_ENUM_CONSTANT(UNIFORM_TYPE_INPUT_ATTACHMENT); //used for sub-pass read/write); for mobile mostly
7868
BIND_ENUM_CONSTANT(UNIFORM_TYPE_MAX);
7869
7870
BIND_ENUM_CONSTANT(RENDER_PRIMITIVE_POINTS);
7871
BIND_ENUM_CONSTANT(RENDER_PRIMITIVE_LINES);
7872
BIND_ENUM_CONSTANT(RENDER_PRIMITIVE_LINES_WITH_ADJACENCY);
7873
BIND_ENUM_CONSTANT(RENDER_PRIMITIVE_LINESTRIPS);
7874
BIND_ENUM_CONSTANT(RENDER_PRIMITIVE_LINESTRIPS_WITH_ADJACENCY);
7875
BIND_ENUM_CONSTANT(RENDER_PRIMITIVE_TRIANGLES);
7876
BIND_ENUM_CONSTANT(RENDER_PRIMITIVE_TRIANGLES_WITH_ADJACENCY);
7877
BIND_ENUM_CONSTANT(RENDER_PRIMITIVE_TRIANGLE_STRIPS);
7878
BIND_ENUM_CONSTANT(RENDER_PRIMITIVE_TRIANGLE_STRIPS_WITH_AJACENCY);
7879
BIND_ENUM_CONSTANT(RENDER_PRIMITIVE_TRIANGLE_STRIPS_WITH_RESTART_INDEX);
7880
BIND_ENUM_CONSTANT(RENDER_PRIMITIVE_TESSELATION_PATCH);
7881
BIND_ENUM_CONSTANT(RENDER_PRIMITIVE_MAX);
7882
7883
BIND_ENUM_CONSTANT(POLYGON_CULL_DISABLED);
7884
BIND_ENUM_CONSTANT(POLYGON_CULL_FRONT);
7885
BIND_ENUM_CONSTANT(POLYGON_CULL_BACK);
7886
7887
BIND_ENUM_CONSTANT(POLYGON_FRONT_FACE_CLOCKWISE);
7888
BIND_ENUM_CONSTANT(POLYGON_FRONT_FACE_COUNTER_CLOCKWISE);
7889
7890
BIND_ENUM_CONSTANT(STENCIL_OP_KEEP);
7891
BIND_ENUM_CONSTANT(STENCIL_OP_ZERO);
7892
BIND_ENUM_CONSTANT(STENCIL_OP_REPLACE);
7893
BIND_ENUM_CONSTANT(STENCIL_OP_INCREMENT_AND_CLAMP);
7894
BIND_ENUM_CONSTANT(STENCIL_OP_DECREMENT_AND_CLAMP);
7895
BIND_ENUM_CONSTANT(STENCIL_OP_INVERT);
7896
BIND_ENUM_CONSTANT(STENCIL_OP_INCREMENT_AND_WRAP);
7897
BIND_ENUM_CONSTANT(STENCIL_OP_DECREMENT_AND_WRAP);
7898
BIND_ENUM_CONSTANT(STENCIL_OP_MAX); //not an actual operator); just the amount of operators :D
7899
7900
BIND_ENUM_CONSTANT(COMPARE_OP_NEVER);
7901
BIND_ENUM_CONSTANT(COMPARE_OP_LESS);
7902
BIND_ENUM_CONSTANT(COMPARE_OP_EQUAL);
7903
BIND_ENUM_CONSTANT(COMPARE_OP_LESS_OR_EQUAL);
7904
BIND_ENUM_CONSTANT(COMPARE_OP_GREATER);
7905
BIND_ENUM_CONSTANT(COMPARE_OP_NOT_EQUAL);
7906
BIND_ENUM_CONSTANT(COMPARE_OP_GREATER_OR_EQUAL);
7907
BIND_ENUM_CONSTANT(COMPARE_OP_ALWAYS);
7908
BIND_ENUM_CONSTANT(COMPARE_OP_MAX);
7909
7910
BIND_ENUM_CONSTANT(LOGIC_OP_CLEAR);
7911
BIND_ENUM_CONSTANT(LOGIC_OP_AND);
7912
BIND_ENUM_CONSTANT(LOGIC_OP_AND_REVERSE);
7913
BIND_ENUM_CONSTANT(LOGIC_OP_COPY);
7914
BIND_ENUM_CONSTANT(LOGIC_OP_AND_INVERTED);
7915
BIND_ENUM_CONSTANT(LOGIC_OP_NO_OP);
7916
BIND_ENUM_CONSTANT(LOGIC_OP_XOR);
7917
BIND_ENUM_CONSTANT(LOGIC_OP_OR);
7918
BIND_ENUM_CONSTANT(LOGIC_OP_NOR);
7919
BIND_ENUM_CONSTANT(LOGIC_OP_EQUIVALENT);
7920
BIND_ENUM_CONSTANT(LOGIC_OP_INVERT);
7921
BIND_ENUM_CONSTANT(LOGIC_OP_OR_REVERSE);
7922
BIND_ENUM_CONSTANT(LOGIC_OP_COPY_INVERTED);
7923
BIND_ENUM_CONSTANT(LOGIC_OP_OR_INVERTED);
7924
BIND_ENUM_CONSTANT(LOGIC_OP_NAND);
7925
BIND_ENUM_CONSTANT(LOGIC_OP_SET);
7926
BIND_ENUM_CONSTANT(LOGIC_OP_MAX); //not an actual operator); just the amount of operators :D
7927
7928
BIND_ENUM_CONSTANT(BLEND_FACTOR_ZERO);
7929
BIND_ENUM_CONSTANT(BLEND_FACTOR_ONE);
7930
BIND_ENUM_CONSTANT(BLEND_FACTOR_SRC_COLOR);
7931
BIND_ENUM_CONSTANT(BLEND_FACTOR_ONE_MINUS_SRC_COLOR);
7932
BIND_ENUM_CONSTANT(BLEND_FACTOR_DST_COLOR);
7933
BIND_ENUM_CONSTANT(BLEND_FACTOR_ONE_MINUS_DST_COLOR);
7934
BIND_ENUM_CONSTANT(BLEND_FACTOR_SRC_ALPHA);
7935
BIND_ENUM_CONSTANT(BLEND_FACTOR_ONE_MINUS_SRC_ALPHA);
7936
BIND_ENUM_CONSTANT(BLEND_FACTOR_DST_ALPHA);
7937
BIND_ENUM_CONSTANT(BLEND_FACTOR_ONE_MINUS_DST_ALPHA);
7938
BIND_ENUM_CONSTANT(BLEND_FACTOR_CONSTANT_COLOR);
7939
BIND_ENUM_CONSTANT(BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR);
7940
BIND_ENUM_CONSTANT(BLEND_FACTOR_CONSTANT_ALPHA);
7941
BIND_ENUM_CONSTANT(BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA);
7942
BIND_ENUM_CONSTANT(BLEND_FACTOR_SRC_ALPHA_SATURATE);
7943
BIND_ENUM_CONSTANT(BLEND_FACTOR_SRC1_COLOR);
7944
BIND_ENUM_CONSTANT(BLEND_FACTOR_ONE_MINUS_SRC1_COLOR);
7945
BIND_ENUM_CONSTANT(BLEND_FACTOR_SRC1_ALPHA);
7946
BIND_ENUM_CONSTANT(BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA);
7947
BIND_ENUM_CONSTANT(BLEND_FACTOR_MAX);
7948
7949
BIND_ENUM_CONSTANT(BLEND_OP_ADD);
7950
BIND_ENUM_CONSTANT(BLEND_OP_SUBTRACT);
7951
BIND_ENUM_CONSTANT(BLEND_OP_REVERSE_SUBTRACT);
7952
BIND_ENUM_CONSTANT(BLEND_OP_MINIMUM);
7953
BIND_ENUM_CONSTANT(BLEND_OP_MAXIMUM);
7954
BIND_ENUM_CONSTANT(BLEND_OP_MAX);
7955
7956
BIND_BITFIELD_FLAG(DYNAMIC_STATE_LINE_WIDTH);
7957
BIND_BITFIELD_FLAG(DYNAMIC_STATE_DEPTH_BIAS);
7958
BIND_BITFIELD_FLAG(DYNAMIC_STATE_BLEND_CONSTANTS);
7959
BIND_BITFIELD_FLAG(DYNAMIC_STATE_DEPTH_BOUNDS);
7960
BIND_BITFIELD_FLAG(DYNAMIC_STATE_STENCIL_COMPARE_MASK);
7961
BIND_BITFIELD_FLAG(DYNAMIC_STATE_STENCIL_WRITE_MASK);
7962
BIND_BITFIELD_FLAG(DYNAMIC_STATE_STENCIL_REFERENCE);
7963
7964
#ifndef DISABLE_DEPRECATED
7965
BIND_ENUM_CONSTANT(INITIAL_ACTION_LOAD);
7966
BIND_ENUM_CONSTANT(INITIAL_ACTION_CLEAR);
7967
BIND_ENUM_CONSTANT(INITIAL_ACTION_DISCARD);
7968
BIND_ENUM_CONSTANT(INITIAL_ACTION_MAX);
7969
BIND_ENUM_CONSTANT(INITIAL_ACTION_CLEAR_REGION);
7970
BIND_ENUM_CONSTANT(INITIAL_ACTION_CLEAR_REGION_CONTINUE);
7971
BIND_ENUM_CONSTANT(INITIAL_ACTION_KEEP);
7972
BIND_ENUM_CONSTANT(INITIAL_ACTION_DROP);
7973
BIND_ENUM_CONSTANT(INITIAL_ACTION_CONTINUE);
7974
7975
BIND_ENUM_CONSTANT(FINAL_ACTION_STORE);
7976
BIND_ENUM_CONSTANT(FINAL_ACTION_DISCARD);
7977
BIND_ENUM_CONSTANT(FINAL_ACTION_MAX);
7978
BIND_ENUM_CONSTANT(FINAL_ACTION_READ);
7979
BIND_ENUM_CONSTANT(FINAL_ACTION_CONTINUE);
7980
#endif
7981
7982
BIND_ENUM_CONSTANT(SHADER_STAGE_VERTEX);
7983
BIND_ENUM_CONSTANT(SHADER_STAGE_FRAGMENT);
7984
BIND_ENUM_CONSTANT(SHADER_STAGE_TESSELATION_CONTROL);
7985
BIND_ENUM_CONSTANT(SHADER_STAGE_TESSELATION_EVALUATION);
7986
BIND_ENUM_CONSTANT(SHADER_STAGE_COMPUTE);
7987
BIND_ENUM_CONSTANT(SHADER_STAGE_MAX);
7988
BIND_ENUM_CONSTANT(SHADER_STAGE_VERTEX_BIT);
7989
BIND_ENUM_CONSTANT(SHADER_STAGE_FRAGMENT_BIT);
7990
BIND_ENUM_CONSTANT(SHADER_STAGE_TESSELATION_CONTROL_BIT);
7991
BIND_ENUM_CONSTANT(SHADER_STAGE_TESSELATION_EVALUATION_BIT);
7992
BIND_ENUM_CONSTANT(SHADER_STAGE_COMPUTE_BIT);
7993
7994
BIND_ENUM_CONSTANT(SHADER_LANGUAGE_GLSL);
7995
BIND_ENUM_CONSTANT(SHADER_LANGUAGE_HLSL);
7996
7997
BIND_ENUM_CONSTANT(PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL);
7998
BIND_ENUM_CONSTANT(PIPELINE_SPECIALIZATION_CONSTANT_TYPE_INT);
7999
BIND_ENUM_CONSTANT(PIPELINE_SPECIALIZATION_CONSTANT_TYPE_FLOAT);
8000
8001
BIND_ENUM_CONSTANT(SUPPORTS_METALFX_SPATIAL);
8002
BIND_ENUM_CONSTANT(SUPPORTS_METALFX_TEMPORAL);
8003
BIND_ENUM_CONSTANT(SUPPORTS_BUFFER_DEVICE_ADDRESS);
8004
BIND_ENUM_CONSTANT(SUPPORTS_IMAGE_ATOMIC_32_BIT);
8005
8006
BIND_ENUM_CONSTANT(LIMIT_MAX_BOUND_UNIFORM_SETS);
8007
BIND_ENUM_CONSTANT(LIMIT_MAX_FRAMEBUFFER_COLOR_ATTACHMENTS);
8008
BIND_ENUM_CONSTANT(LIMIT_MAX_TEXTURES_PER_UNIFORM_SET);
8009
BIND_ENUM_CONSTANT(LIMIT_MAX_SAMPLERS_PER_UNIFORM_SET);
8010
BIND_ENUM_CONSTANT(LIMIT_MAX_STORAGE_BUFFERS_PER_UNIFORM_SET);
8011
BIND_ENUM_CONSTANT(LIMIT_MAX_STORAGE_IMAGES_PER_UNIFORM_SET);
8012
BIND_ENUM_CONSTANT(LIMIT_MAX_UNIFORM_BUFFERS_PER_UNIFORM_SET);
8013
BIND_ENUM_CONSTANT(LIMIT_MAX_DRAW_INDEXED_INDEX);
8014
BIND_ENUM_CONSTANT(LIMIT_MAX_FRAMEBUFFER_HEIGHT);
8015
BIND_ENUM_CONSTANT(LIMIT_MAX_FRAMEBUFFER_WIDTH);
8016
BIND_ENUM_CONSTANT(LIMIT_MAX_TEXTURE_ARRAY_LAYERS);
8017
BIND_ENUM_CONSTANT(LIMIT_MAX_TEXTURE_SIZE_1D);
8018
BIND_ENUM_CONSTANT(LIMIT_MAX_TEXTURE_SIZE_2D);
8019
BIND_ENUM_CONSTANT(LIMIT_MAX_TEXTURE_SIZE_3D);
8020
BIND_ENUM_CONSTANT(LIMIT_MAX_TEXTURE_SIZE_CUBE);
8021
BIND_ENUM_CONSTANT(LIMIT_MAX_TEXTURES_PER_SHADER_STAGE);
8022
BIND_ENUM_CONSTANT(LIMIT_MAX_SAMPLERS_PER_SHADER_STAGE);
8023
BIND_ENUM_CONSTANT(LIMIT_MAX_STORAGE_BUFFERS_PER_SHADER_STAGE);
8024
BIND_ENUM_CONSTANT(LIMIT_MAX_STORAGE_IMAGES_PER_SHADER_STAGE);
8025
BIND_ENUM_CONSTANT(LIMIT_MAX_UNIFORM_BUFFERS_PER_SHADER_STAGE);
8026
BIND_ENUM_CONSTANT(LIMIT_MAX_PUSH_CONSTANT_SIZE);
8027
BIND_ENUM_CONSTANT(LIMIT_MAX_UNIFORM_BUFFER_SIZE);
8028
BIND_ENUM_CONSTANT(LIMIT_MAX_VERTEX_INPUT_ATTRIBUTE_OFFSET);
8029
BIND_ENUM_CONSTANT(LIMIT_MAX_VERTEX_INPUT_ATTRIBUTES);
8030
BIND_ENUM_CONSTANT(LIMIT_MAX_VERTEX_INPUT_BINDINGS);
8031
BIND_ENUM_CONSTANT(LIMIT_MAX_VERTEX_INPUT_BINDING_STRIDE);
8032
BIND_ENUM_CONSTANT(LIMIT_MIN_UNIFORM_BUFFER_OFFSET_ALIGNMENT);
8033
BIND_ENUM_CONSTANT(LIMIT_MAX_COMPUTE_SHARED_MEMORY_SIZE);
8034
BIND_ENUM_CONSTANT(LIMIT_MAX_COMPUTE_WORKGROUP_COUNT_X);
8035
BIND_ENUM_CONSTANT(LIMIT_MAX_COMPUTE_WORKGROUP_COUNT_Y);
8036
BIND_ENUM_CONSTANT(LIMIT_MAX_COMPUTE_WORKGROUP_COUNT_Z);
8037
BIND_ENUM_CONSTANT(LIMIT_MAX_COMPUTE_WORKGROUP_INVOCATIONS);
8038
BIND_ENUM_CONSTANT(LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_X);
8039
BIND_ENUM_CONSTANT(LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_Y);
8040
BIND_ENUM_CONSTANT(LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_Z);
8041
BIND_ENUM_CONSTANT(LIMIT_MAX_VIEWPORT_DIMENSIONS_X);
8042
BIND_ENUM_CONSTANT(LIMIT_MAX_VIEWPORT_DIMENSIONS_Y);
8043
BIND_ENUM_CONSTANT(LIMIT_METALFX_TEMPORAL_SCALER_MIN_SCALE);
8044
BIND_ENUM_CONSTANT(LIMIT_METALFX_TEMPORAL_SCALER_MAX_SCALE);
8045
8046
BIND_ENUM_CONSTANT(MEMORY_TEXTURES);
8047
BIND_ENUM_CONSTANT(MEMORY_BUFFERS);
8048
BIND_ENUM_CONSTANT(MEMORY_TOTAL);
8049
8050
BIND_CONSTANT(INVALID_ID);
8051
BIND_CONSTANT(INVALID_FORMAT_ID);
8052
8053
BIND_ENUM_CONSTANT(NONE);
8054
BIND_ENUM_CONSTANT(REFLECTION_PROBES);
8055
BIND_ENUM_CONSTANT(SKY_PASS);
8056
BIND_ENUM_CONSTANT(LIGHTMAPPER_PASS);
8057
BIND_ENUM_CONSTANT(SHADOW_PASS_DIRECTIONAL);
8058
BIND_ENUM_CONSTANT(SHADOW_PASS_CUBE);
8059
BIND_ENUM_CONSTANT(OPAQUE_PASS);
8060
BIND_ENUM_CONSTANT(ALPHA_PASS);
8061
BIND_ENUM_CONSTANT(TRANSPARENT_PASS);
8062
BIND_ENUM_CONSTANT(POST_PROCESSING_PASS);
8063
BIND_ENUM_CONSTANT(BLIT_PASS);
8064
BIND_ENUM_CONSTANT(UI_PASS);
8065
BIND_ENUM_CONSTANT(DEBUG_PASS);
8066
8067
BIND_BITFIELD_FLAG(DRAW_DEFAULT_ALL);
8068
BIND_BITFIELD_FLAG(DRAW_CLEAR_COLOR_0);
8069
BIND_BITFIELD_FLAG(DRAW_CLEAR_COLOR_1);
8070
BIND_BITFIELD_FLAG(DRAW_CLEAR_COLOR_2);
8071
BIND_BITFIELD_FLAG(DRAW_CLEAR_COLOR_3);
8072
BIND_BITFIELD_FLAG(DRAW_CLEAR_COLOR_4);
8073
BIND_BITFIELD_FLAG(DRAW_CLEAR_COLOR_5);
8074
BIND_BITFIELD_FLAG(DRAW_CLEAR_COLOR_6);
8075
BIND_BITFIELD_FLAG(DRAW_CLEAR_COLOR_7);
8076
BIND_BITFIELD_FLAG(DRAW_CLEAR_COLOR_MASK);
8077
BIND_BITFIELD_FLAG(DRAW_CLEAR_COLOR_ALL);
8078
BIND_BITFIELD_FLAG(DRAW_IGNORE_COLOR_0);
8079
BIND_BITFIELD_FLAG(DRAW_IGNORE_COLOR_1);
8080
BIND_BITFIELD_FLAG(DRAW_IGNORE_COLOR_2);
8081
BIND_BITFIELD_FLAG(DRAW_IGNORE_COLOR_3);
8082
BIND_BITFIELD_FLAG(DRAW_IGNORE_COLOR_4);
8083
BIND_BITFIELD_FLAG(DRAW_IGNORE_COLOR_5);
8084
BIND_BITFIELD_FLAG(DRAW_IGNORE_COLOR_6);
8085
BIND_BITFIELD_FLAG(DRAW_IGNORE_COLOR_7);
8086
BIND_BITFIELD_FLAG(DRAW_IGNORE_COLOR_MASK);
8087
BIND_BITFIELD_FLAG(DRAW_IGNORE_COLOR_ALL);
8088
BIND_BITFIELD_FLAG(DRAW_CLEAR_DEPTH);
8089
BIND_BITFIELD_FLAG(DRAW_IGNORE_DEPTH);
8090
BIND_BITFIELD_FLAG(DRAW_CLEAR_STENCIL);
8091
BIND_BITFIELD_FLAG(DRAW_IGNORE_STENCIL);
8092
BIND_BITFIELD_FLAG(DRAW_CLEAR_ALL);
8093
BIND_BITFIELD_FLAG(DRAW_IGNORE_ALL);
8094
}
8095
8096
void RenderingDevice::make_current() {
8097
render_thread_id = Thread::get_caller_id();
8098
}
8099
8100
RenderingDevice::~RenderingDevice() {
8101
finalize();
8102
8103
if (singleton == this) {
8104
singleton = nullptr;
8105
}
8106
}
8107
8108
RenderingDevice::RenderingDevice() {
8109
if (singleton == nullptr) {
8110
singleton = this;
8111
}
8112
8113
render_thread_id = Thread::get_caller_id();
8114
}
8115
8116
/*****************/
8117
/**** BINDERS ****/
8118
/*****************/
8119
8120
RID RenderingDevice::_texture_create(const Ref<RDTextureFormat> &p_format, const Ref<RDTextureView> &p_view, const TypedArray<PackedByteArray> &p_data) {
8121
ERR_FAIL_COND_V(p_format.is_null(), RID());
8122
ERR_FAIL_COND_V(p_view.is_null(), RID());
8123
Vector<Vector<uint8_t>> data;
8124
for (int i = 0; i < p_data.size(); i++) {
8125
Vector<uint8_t> byte_slice = p_data[i];
8126
ERR_FAIL_COND_V(byte_slice.is_empty(), RID());
8127
data.push_back(byte_slice);
8128
}
8129
return texture_create(p_format->base, p_view->base, data);
8130
}
8131
8132
RID RenderingDevice::_texture_create_shared(const Ref<RDTextureView> &p_view, RID p_with_texture) {
8133
ERR_FAIL_COND_V(p_view.is_null(), RID());
8134
8135
return texture_create_shared(p_view->base, p_with_texture);
8136
}
8137
8138
RID RenderingDevice::_texture_create_shared_from_slice(const Ref<RDTextureView> &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap, uint32_t p_mipmaps, TextureSliceType p_slice_type) {
8139
ERR_FAIL_COND_V(p_view.is_null(), RID());
8140
8141
return texture_create_shared_from_slice(p_view->base, p_with_texture, p_layer, p_mipmap, p_mipmaps, p_slice_type);
8142
}
8143
8144
Ref<RDTextureFormat> RenderingDevice::_texture_get_format(RID p_rd_texture) {
8145
Ref<RDTextureFormat> rtf;
8146
rtf.instantiate();
8147
rtf->base = texture_get_format(p_rd_texture);
8148
8149
return rtf;
8150
}
8151
8152
RenderingDevice::FramebufferFormatID RenderingDevice::_framebuffer_format_create(const TypedArray<RDAttachmentFormat> &p_attachments, uint32_t p_view_count) {
8153
Vector<AttachmentFormat> attachments;
8154
attachments.resize(p_attachments.size());
8155
8156
for (int i = 0; i < p_attachments.size(); i++) {
8157
Ref<RDAttachmentFormat> af = p_attachments[i];
8158
ERR_FAIL_COND_V(af.is_null(), INVALID_FORMAT_ID);
8159
attachments.write[i] = af->base;
8160
}
8161
return framebuffer_format_create(attachments, p_view_count);
8162
}
8163
8164
RenderingDevice::FramebufferFormatID RenderingDevice::_framebuffer_format_create_multipass(const TypedArray<RDAttachmentFormat> &p_attachments, const TypedArray<RDFramebufferPass> &p_passes, uint32_t p_view_count) {
8165
Vector<AttachmentFormat> attachments;
8166
attachments.resize(p_attachments.size());
8167
8168
for (int i = 0; i < p_attachments.size(); i++) {
8169
Ref<RDAttachmentFormat> af = p_attachments[i];
8170
ERR_FAIL_COND_V(af.is_null(), INVALID_FORMAT_ID);
8171
attachments.write[i] = af->base;
8172
}
8173
8174
Vector<FramebufferPass> passes;
8175
for (int i = 0; i < p_passes.size(); i++) {
8176
Ref<RDFramebufferPass> pass = p_passes[i];
8177
ERR_CONTINUE(pass.is_null());
8178
passes.push_back(pass->base);
8179
}
8180
8181
return framebuffer_format_create_multipass(attachments, passes, p_view_count);
8182
}
8183
8184
RID RenderingDevice::_framebuffer_create(const TypedArray<RID> &p_textures, FramebufferFormatID p_format_check, uint32_t p_view_count) {
8185
Vector<RID> textures = Variant(p_textures);
8186
return framebuffer_create(textures, p_format_check, p_view_count);
8187
}
8188
8189
RID RenderingDevice::_framebuffer_create_multipass(const TypedArray<RID> &p_textures, const TypedArray<RDFramebufferPass> &p_passes, FramebufferFormatID p_format_check, uint32_t p_view_count) {
8190
Vector<RID> textures = Variant(p_textures);
8191
Vector<FramebufferPass> passes;
8192
for (int i = 0; i < p_passes.size(); i++) {
8193
Ref<RDFramebufferPass> pass = p_passes[i];
8194
ERR_CONTINUE(pass.is_null());
8195
passes.push_back(pass->base);
8196
}
8197
return framebuffer_create_multipass(textures, passes, p_format_check, p_view_count);
8198
}
8199
8200
RID RenderingDevice::_sampler_create(const Ref<RDSamplerState> &p_state) {
8201
ERR_FAIL_COND_V(p_state.is_null(), RID());
8202
8203
return sampler_create(p_state->base);
8204
}
8205
8206
RenderingDevice::VertexFormatID RenderingDevice::_vertex_format_create(const TypedArray<RDVertexAttribute> &p_vertex_formats) {
8207
Vector<VertexAttribute> descriptions;
8208
descriptions.resize(p_vertex_formats.size());
8209
8210
for (int i = 0; i < p_vertex_formats.size(); i++) {
8211
Ref<RDVertexAttribute> af = p_vertex_formats[i];
8212
ERR_FAIL_COND_V(af.is_null(), INVALID_FORMAT_ID);
8213
descriptions.write[i] = af->base;
8214
}
8215
return vertex_format_create(descriptions);
8216
}
8217
8218
RID RenderingDevice::_vertex_array_create(uint32_t p_vertex_count, VertexFormatID p_vertex_format, const TypedArray<RID> &p_src_buffers, const Vector<int64_t> &p_offsets) {
8219
Vector<RID> buffers = Variant(p_src_buffers);
8220
8221
Vector<uint64_t> offsets;
8222
offsets.resize(p_offsets.size());
8223
for (int i = 0; i < p_offsets.size(); i++) {
8224
offsets.write[i] = p_offsets[i];
8225
}
8226
8227
return vertex_array_create(p_vertex_count, p_vertex_format, buffers, offsets);
8228
}
8229
8230
Ref<RDShaderSPIRV> RenderingDevice::_shader_compile_spirv_from_source(const Ref<RDShaderSource> &p_source, bool p_allow_cache) {
8231
ERR_FAIL_COND_V(p_source.is_null(), Ref<RDShaderSPIRV>());
8232
8233
Ref<RDShaderSPIRV> bytecode;
8234
bytecode.instantiate();
8235
for (int i = 0; i < RD::SHADER_STAGE_MAX; i++) {
8236
String error;
8237
8238
ShaderStage stage = ShaderStage(i);
8239
String source = p_source->get_stage_source(stage);
8240
8241
if (!source.is_empty()) {
8242
Vector<uint8_t> spirv = shader_compile_spirv_from_source(stage, source, p_source->get_language(), &error, p_allow_cache);
8243
bytecode->set_stage_bytecode(stage, spirv);
8244
bytecode->set_stage_compile_error(stage, error);
8245
}
8246
}
8247
return bytecode;
8248
}
8249
8250
Vector<uint8_t> RenderingDevice::_shader_compile_binary_from_spirv(const Ref<RDShaderSPIRV> &p_spirv, const String &p_shader_name) {
8251
ERR_FAIL_COND_V(p_spirv.is_null(), Vector<uint8_t>());
8252
8253
Vector<ShaderStageSPIRVData> stage_data;
8254
for (int i = 0; i < RD::SHADER_STAGE_MAX; i++) {
8255
ShaderStage stage = ShaderStage(i);
8256
ShaderStageSPIRVData sd;
8257
sd.shader_stage = stage;
8258
String error = p_spirv->get_stage_compile_error(stage);
8259
ERR_FAIL_COND_V_MSG(!error.is_empty(), Vector<uint8_t>(), "Can't create a shader from an errored bytecode. Check errors in source bytecode.");
8260
sd.spirv = p_spirv->get_stage_bytecode(stage);
8261
if (sd.spirv.is_empty()) {
8262
continue;
8263
}
8264
stage_data.push_back(sd);
8265
}
8266
8267
return shader_compile_binary_from_spirv(stage_data, p_shader_name);
8268
}
8269
8270
RID RenderingDevice::_shader_create_from_spirv(const Ref<RDShaderSPIRV> &p_spirv, const String &p_shader_name) {
8271
ERR_FAIL_COND_V(p_spirv.is_null(), RID());
8272
8273
Vector<ShaderStageSPIRVData> stage_data;
8274
for (int i = 0; i < RD::SHADER_STAGE_MAX; i++) {
8275
ShaderStage stage = ShaderStage(i);
8276
ShaderStageSPIRVData sd;
8277
sd.shader_stage = stage;
8278
String error = p_spirv->get_stage_compile_error(stage);
8279
ERR_FAIL_COND_V_MSG(!error.is_empty(), RID(), "Can't create a shader from an errored bytecode. Check errors in source bytecode.");
8280
sd.spirv = p_spirv->get_stage_bytecode(stage);
8281
if (sd.spirv.is_empty()) {
8282
continue;
8283
}
8284
stage_data.push_back(sd);
8285
}
8286
return shader_create_from_spirv(stage_data);
8287
}
8288
8289
RID RenderingDevice::_uniform_set_create(const TypedArray<RDUniform> &p_uniforms, RID p_shader, uint32_t p_shader_set) {
8290
LocalVector<Uniform> uniforms;
8291
uniforms.resize(p_uniforms.size());
8292
for (int i = 0; i < p_uniforms.size(); i++) {
8293
Ref<RDUniform> uniform = p_uniforms[i];
8294
ERR_FAIL_COND_V(uniform.is_null(), RID());
8295
uniforms[i] = uniform->base;
8296
}
8297
return uniform_set_create(uniforms, p_shader, p_shader_set);
8298
}
8299
8300
Error RenderingDevice::_buffer_update_bind(RID p_buffer, uint32_t p_offset, uint32_t p_size, const Vector<uint8_t> &p_data) {
8301
return buffer_update(p_buffer, p_offset, p_size, p_data.ptr());
8302
}
8303
8304
static Vector<RenderingDevice::PipelineSpecializationConstant> _get_spec_constants(const TypedArray<RDPipelineSpecializationConstant> &p_constants) {
8305
Vector<RenderingDevice::PipelineSpecializationConstant> ret;
8306
ret.resize(p_constants.size());
8307
for (int i = 0; i < p_constants.size(); i++) {
8308
Ref<RDPipelineSpecializationConstant> c = p_constants[i];
8309
ERR_CONTINUE(c.is_null());
8310
RenderingDevice::PipelineSpecializationConstant &sc = ret.write[i];
8311
Variant value = c->get_value();
8312
switch (value.get_type()) {
8313
case Variant::BOOL: {
8314
sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL;
8315
sc.bool_value = value;
8316
} break;
8317
case Variant::INT: {
8318
sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_INT;
8319
sc.int_value = value;
8320
} break;
8321
case Variant::FLOAT: {
8322
sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_FLOAT;
8323
sc.float_value = value;
8324
} break;
8325
default: {
8326
}
8327
}
8328
8329
sc.constant_id = c->get_constant_id();
8330
}
8331
return ret;
8332
}
8333
8334
RID RenderingDevice::_render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const Ref<RDPipelineRasterizationState> &p_rasterization_state, const Ref<RDPipelineMultisampleState> &p_multisample_state, const Ref<RDPipelineDepthStencilState> &p_depth_stencil_state, const Ref<RDPipelineColorBlendState> &p_blend_state, BitField<PipelineDynamicStateFlags> p_dynamic_state_flags, uint32_t p_for_render_pass, const TypedArray<RDPipelineSpecializationConstant> &p_specialization_constants) {
8335
PipelineRasterizationState rasterization_state;
8336
if (p_rasterization_state.is_valid()) {
8337
rasterization_state = p_rasterization_state->base;
8338
}
8339
8340
PipelineMultisampleState multisample_state;
8341
if (p_multisample_state.is_valid()) {
8342
multisample_state = p_multisample_state->base;
8343
for (int i = 0; i < p_multisample_state->sample_masks.size(); i++) {
8344
int64_t mask = p_multisample_state->sample_masks[i];
8345
multisample_state.sample_mask.push_back(mask);
8346
}
8347
}
8348
8349
PipelineDepthStencilState depth_stencil_state;
8350
if (p_depth_stencil_state.is_valid()) {
8351
depth_stencil_state = p_depth_stencil_state->base;
8352
}
8353
8354
PipelineColorBlendState color_blend_state;
8355
if (p_blend_state.is_valid()) {
8356
color_blend_state = p_blend_state->base;
8357
for (int i = 0; i < p_blend_state->attachments.size(); i++) {
8358
Ref<RDPipelineColorBlendStateAttachment> attachment = p_blend_state->attachments[i];
8359
if (attachment.is_valid()) {
8360
color_blend_state.attachments.push_back(attachment->base);
8361
}
8362
}
8363
}
8364
8365
return render_pipeline_create(p_shader, p_framebuffer_format, p_vertex_format, p_render_primitive, rasterization_state, multisample_state, depth_stencil_state, color_blend_state, p_dynamic_state_flags, p_for_render_pass, _get_spec_constants(p_specialization_constants));
8366
}
8367
8368
RID RenderingDevice::_compute_pipeline_create(RID p_shader, const TypedArray<RDPipelineSpecializationConstant> &p_specialization_constants = TypedArray<RDPipelineSpecializationConstant>()) {
8369
return compute_pipeline_create(p_shader, _get_spec_constants(p_specialization_constants));
8370
}
8371
8372
#ifndef DISABLE_DEPRECATED
8373
Vector<int64_t> RenderingDevice::_draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region, const TypedArray<RID> &p_storage_textures) {
8374
ERR_FAIL_V_MSG(Vector<int64_t>(), "Deprecated. Split draw lists are used automatically by RenderingDevice.");
8375
}
8376
8377
Vector<int64_t> RenderingDevice::_draw_list_switch_to_next_pass_split(uint32_t p_splits) {
8378
ERR_FAIL_V_MSG(Vector<int64_t>(), "Deprecated. Split draw lists are used automatically by RenderingDevice.");
8379
}
8380
#endif
8381
8382
void RenderingDevice::_draw_list_set_push_constant(DrawListID p_list, const Vector<uint8_t> &p_data, uint32_t p_data_size) {
8383
ERR_FAIL_COND(p_data_size > (uint32_t)p_data.size());
8384
draw_list_set_push_constant(p_list, p_data.ptr(), p_data_size);
8385
}
8386
8387
void RenderingDevice::_compute_list_set_push_constant(ComputeListID p_list, const Vector<uint8_t> &p_data, uint32_t p_data_size) {
8388
ERR_FAIL_COND(p_data_size > (uint32_t)p_data.size());
8389
compute_list_set_push_constant(p_list, p_data.ptr(), p_data_size);
8390
}
8391
8392
static_assert(ENUM_MEMBERS_EQUAL(RD::CALLBACK_RESOURCE_USAGE_NONE, RDG::RESOURCE_USAGE_NONE));
8393
static_assert(ENUM_MEMBERS_EQUAL(RD::CALLBACK_RESOURCE_USAGE_COPY_FROM, RDG::RESOURCE_USAGE_COPY_FROM));
8394
static_assert(ENUM_MEMBERS_EQUAL(RD::CALLBACK_RESOURCE_USAGE_COPY_TO, RDG::RESOURCE_USAGE_COPY_TO));
8395
static_assert(ENUM_MEMBERS_EQUAL(RD::CALLBACK_RESOURCE_USAGE_RESOLVE_FROM, RDG::RESOURCE_USAGE_RESOLVE_FROM));
8396
static_assert(ENUM_MEMBERS_EQUAL(RD::CALLBACK_RESOURCE_USAGE_RESOLVE_TO, RDG::RESOURCE_USAGE_RESOLVE_TO));
8397
static_assert(ENUM_MEMBERS_EQUAL(RD::CALLBACK_RESOURCE_USAGE_UNIFORM_BUFFER_READ, RDG::RESOURCE_USAGE_UNIFORM_BUFFER_READ));
8398
static_assert(ENUM_MEMBERS_EQUAL(RD::CALLBACK_RESOURCE_USAGE_INDIRECT_BUFFER_READ, RDG::RESOURCE_USAGE_INDIRECT_BUFFER_READ));
8399
static_assert(ENUM_MEMBERS_EQUAL(RD::CALLBACK_RESOURCE_USAGE_TEXTURE_BUFFER_READ, RDG::RESOURCE_USAGE_TEXTURE_BUFFER_READ));
8400
static_assert(ENUM_MEMBERS_EQUAL(RD::CALLBACK_RESOURCE_USAGE_TEXTURE_BUFFER_READ_WRITE, RDG::RESOURCE_USAGE_TEXTURE_BUFFER_READ_WRITE));
8401
static_assert(ENUM_MEMBERS_EQUAL(RD::CALLBACK_RESOURCE_USAGE_STORAGE_BUFFER_READ, RDG::RESOURCE_USAGE_STORAGE_BUFFER_READ));
8402
static_assert(ENUM_MEMBERS_EQUAL(RD::CALLBACK_RESOURCE_USAGE_STORAGE_BUFFER_READ_WRITE, RDG::RESOURCE_USAGE_STORAGE_BUFFER_READ_WRITE));
8403
static_assert(ENUM_MEMBERS_EQUAL(RD::CALLBACK_RESOURCE_USAGE_VERTEX_BUFFER_READ, RDG::RESOURCE_USAGE_VERTEX_BUFFER_READ));
8404
static_assert(ENUM_MEMBERS_EQUAL(RD::CALLBACK_RESOURCE_USAGE_INDEX_BUFFER_READ, RDG::RESOURCE_USAGE_INDEX_BUFFER_READ));
8405
static_assert(ENUM_MEMBERS_EQUAL(RD::CALLBACK_RESOURCE_USAGE_TEXTURE_SAMPLE, RDG::RESOURCE_USAGE_TEXTURE_SAMPLE));
8406
static_assert(ENUM_MEMBERS_EQUAL(RD::CALLBACK_RESOURCE_USAGE_STORAGE_IMAGE_READ, RDG::RESOURCE_USAGE_STORAGE_IMAGE_READ));
8407
static_assert(ENUM_MEMBERS_EQUAL(RD::CALLBACK_RESOURCE_USAGE_STORAGE_IMAGE_READ_WRITE, RDG::RESOURCE_USAGE_STORAGE_IMAGE_READ_WRITE));
8408
static_assert(ENUM_MEMBERS_EQUAL(RD::CALLBACK_RESOURCE_USAGE_ATTACHMENT_COLOR_READ_WRITE, RDG::RESOURCE_USAGE_ATTACHMENT_COLOR_READ_WRITE));
8409
static_assert(ENUM_MEMBERS_EQUAL(RD::CALLBACK_RESOURCE_USAGE_ATTACHMENT_DEPTH_STENCIL_READ_WRITE, RDG::RESOURCE_USAGE_ATTACHMENT_DEPTH_STENCIL_READ_WRITE));
8410
static_assert(ENUM_MEMBERS_EQUAL(RD::CALLBACK_RESOURCE_USAGE_GENERAL, RDG::RESOURCE_USAGE_GENERAL));
8411
static_assert(ENUM_MEMBERS_EQUAL(RD::CALLBACK_RESOURCE_USAGE_MAX, RDG::RESOURCE_USAGE_MAX));
8412
8413