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