Path: blob/master/servers/rendering/rendering_device.h
21212 views
/**************************************************************************/1/* rendering_device.h */2/**************************************************************************/3/* This file is part of: */4/* GODOT ENGINE */5/* https://godotengine.org */6/**************************************************************************/7/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */8/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */9/* */10/* Permission is hereby granted, free of charge, to any person obtaining */11/* a copy of this software and associated documentation files (the */12/* "Software"), to deal in the Software without restriction, including */13/* without limitation the rights to use, copy, modify, merge, publish, */14/* distribute, sublicense, and/or sell copies of the Software, and to */15/* permit persons to whom the Software is furnished to do so, subject to */16/* the following conditions: */17/* */18/* The above copyright notice and this permission notice shall be */19/* included in all copies or substantial portions of the Software. */20/* */21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */23/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */24/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */25/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */26/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */27/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */28/**************************************************************************/2930#pragma once3132#include "core/object/worker_thread_pool.h"33#include "core/os/condition_variable.h"34#include "core/os/thread_safe.h"35#include "core/templates/local_vector.h"36#include "core/templates/rb_map.h"37#include "core/templates/rid_owner.h"38#include "core/variant/typed_array.h"39#include "servers/display/display_server.h"40#include "servers/rendering/rendering_device_commons.h"41#include "servers/rendering/rendering_device_driver.h"42#include "servers/rendering/rendering_device_graph.h"4344class RDTextureFormat;45class RDTextureView;46class RDAttachmentFormat;47class RDSamplerState;48class RDVertexAttribute;49class RDShaderSource;50class RDShaderSPIRV;51class RDUniform;52class RDPipelineRasterizationState;53class RDPipelineMultisampleState;54class RDPipelineDepthStencilState;55class RDPipelineColorBlendState;56class RDFramebufferPass;57class RDPipelineSpecializationConstant;5859class RenderingDevice : public RenderingDeviceCommons {60GDCLASS(RenderingDevice, Object)6162_THREAD_SAFE_CLASS_6364private:65Thread::ID render_thread_id;6667public:68typedef int64_t DrawListID;69typedef int64_t ComputeListID;70typedef int64_t RaytracingListID;7172typedef void (*InvalidationCallback)(void *);7374private:75static RenderingDevice *singleton;7677RenderingContextDriver *context = nullptr;78RenderingDeviceDriver *driver = nullptr;79RenderingContextDriver::Device device;8081bool local_device_processing = false;82bool is_main_instance = false;8384protected:85static void _bind_methods();8687#ifndef DISABLE_DEPRECATED88RID _shader_create_from_bytecode_bind_compat_79606(const Vector<uint8_t> &p_shader_binary);89RID _texture_create_from_extension_compat_105570(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);90static void _bind_compatibility_methods();91#endif9293/***************************/94/**** ID INFRASTRUCTURE ****/95/***************************/96public:97//base numeric ID for all types98enum {99INVALID_FORMAT_ID = -1100};101102enum IDType {103ID_TYPE_FRAMEBUFFER_FORMAT,104ID_TYPE_VERTEX_FORMAT,105ID_TYPE_DRAW_LIST,106ID_TYPE_COMPUTE_LIST = 4,107ID_TYPE_RAYTRACING_LIST = 5,108ID_TYPE_MAX,109ID_BASE_SHIFT = 58, // 5 bits for ID types.110ID_MASK = (ID_BASE_SHIFT - 1),111};112113private:114HashMap<RID, HashSet<RID>> dependency_map; // IDs to IDs that depend on it.115HashMap<RID, HashSet<RID>> reverse_dependency_map; // Same as above, but in reverse.116117void _add_dependency(RID p_id, RID p_depends_on);118void _free_dependencies(RID p_id);119120private:121/***************************/122/**** BUFFER MANAGEMENT ****/123/***************************/124125// These are temporary buffers on CPU memory that hold126// the information until the CPU fetches it and places it127// either on GPU buffers, or images (textures). It ensures128// updates are properly synchronized with whatever the129// GPU is doing.130//131// The logic here is as follows, only 3 of these132// blocks are created at the beginning (one per frame)133// they can each belong to a frame (assigned to current when134// used) and they can only be reused after the same frame is135// recycled.136//137// When CPU requires to allocate more than what is available,138// more of these buffers are created. If a limit is reached,139// then a fence will ensure will wait for blocks allocated140// in previous frames are processed. If that fails, then141// another fence will ensure everything pending for the current142// frame is processed (effectively stalling).143//144// See the comments in the code to understand better how it works.145146enum StagingRequiredAction {147STAGING_REQUIRED_ACTION_NONE,148STAGING_REQUIRED_ACTION_FLUSH_AND_STALL_ALL,149STAGING_REQUIRED_ACTION_STALL_PREVIOUS,150};151152struct StagingBufferBlock {153RDD::BufferID driver_id;154uint64_t frame_used = 0;155uint32_t fill_amount = 0;156uint8_t *data_ptr = nullptr;157};158159struct StagingBuffers {160Vector<StagingBufferBlock> blocks;161int current = 0;162uint32_t block_size = 0;163uint64_t max_size = 0;164BitField<RDD::BufferUsageBits> usage_bits = {};165bool used = false;166};167168Error _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 = true);169void _staging_buffer_execute_required_action(StagingBuffers &p_staging_buffers, StagingRequiredAction p_required_action);170Error _insert_staging_block(StagingBuffers &p_staging_buffers);171172StagingBuffers upload_staging_buffers;173StagingBuffers download_staging_buffers;174175struct Buffer {176RDD::BufferID driver_id;177uint32_t size = 0;178BitField<RDD::BufferUsageBits> usage = {};179RDG::ResourceTracker *draw_tracker = nullptr;180int32_t transfer_worker_index = -1;181uint64_t transfer_worker_operation = 0;182};183184Buffer *_get_buffer_from_owner(RID p_buffer);185Error _buffer_initialize(Buffer *p_buffer, Span<uint8_t> p_data, uint32_t p_required_align = 32);186187void update_perf_report();188// Flag for batching descriptor sets.189bool descriptor_set_batching = true;190// When true, the final draw call that copies our offscreen result into the Swapchain is put into its191// own cmd buffer, so that the whole rendering can start early instead of having to wait for the192// swapchain semaphore to be signaled (which causes bubbles).193bool split_swapchain_into_its_own_cmd_buffer = true;194uint32_t gpu_copy_count = 0;195uint32_t direct_copy_count = 0;196uint32_t copy_bytes_count = 0;197uint32_t prev_gpu_copy_count = 0;198uint32_t prev_copy_bytes_count = 0;199200RID_Owner<Buffer, true> uniform_buffer_owner;201RID_Owner<Buffer, true> storage_buffer_owner;202RID_Owner<Buffer, true> texture_buffer_owner;203204struct BufferGetDataRequest {205uint32_t frame_local_index = 0;206uint32_t frame_local_count = 0;207Callable callback;208uint32_t size = 0;209};210211public:212Error buffer_copy(RID p_src_buffer, RID p_dst_buffer, uint32_t p_src_offset, uint32_t p_dst_offset, uint32_t p_size);213/**214* @brief Updates the given GPU buffer at offset and size with the given CPU data.215* @remarks216* Buffer update is queued into the render graph. The render graph will reorder this operation so217* that it happens together with other buffer_update() in bulk and before rendering operations218* (or compute dispatches) that need it.219*220* This means that the following will not work as intended:221* @code222* buffer_update(buffer_a, ..., data_source_x, ...);223* draw_list_draw(buffer_a); // render data_render_x.224* buffer_update(buffer_a, ..., data_source_y, ...);225* draw_list_draw(buffer_a); // render data_source_y.226* @endcode227*228* Because it will be *reordered* to become the following:229* @code230* buffer_update(buffer_a, ..., data_source_x, ...);231* buffer_update(buffer_a, ..., data_source_y, ...);232* draw_list_draw(buffer_a); // render data_source_y. <-- Oops! should be data_source_x233* draw_list_draw(buffer_a); // render data_source_y.234* @endcode235*236* When p_skip_check = true, we will perform checks to prevent this situation from happening237* (buffer_update must not be called while creating a draw or compute list).238* Do NOT set it to false for user-facing public API because users had trouble understanding239* this problem when manually creating draw lists.240*241* Godot internally can set p_skip_check = true when it believes it will only update242* the buffer once and it needs to be done while a draw/compute list is being created.243*244* Important: The Vulkan & Metal APIs do not allow issuing copies while inside a RenderPass.245* We can do it because Godot's render graph will reorder them.246*247* @param p_buffer GPU buffer to update.248* @param p_offset Offset in bytes (relative to p_buffer).249* @param p_size Size in bytes of the data.250* @param p_data CPU data to transfer to GPU.251* Pointer can be deleted after buffer_update returns.252* @param p_skip_check Must always be false for user-facing public API. See remarks.253* @return Status result of the operation.254*/255Error buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const void *p_data, bool p_skip_check = false);256Error buffer_clear(RID p_buffer, uint32_t p_offset, uint32_t p_size);257Vector<uint8_t> buffer_get_data(RID p_buffer, uint32_t p_offset = 0, uint32_t p_size = 0); // This causes stall, only use to retrieve large buffers for saving.258Error buffer_get_data_async(RID p_buffer, const Callable &p_callback, uint32_t p_offset = 0, uint32_t p_size = 0);259uint64_t buffer_get_device_address(RID p_buffer);260uint8_t *buffer_persistent_map_advance(RID p_buffer);261void buffer_flush(RID p_buffer);262263private:264/******************/265/**** CALLBACK ****/266/******************/267268public:269enum CallbackResourceType {270CALLBACK_RESOURCE_TYPE_TEXTURE,271CALLBACK_RESOURCE_TYPE_BUFFER,272};273274enum CallbackResourceUsage {275CALLBACK_RESOURCE_USAGE_NONE,276CALLBACK_RESOURCE_USAGE_COPY_FROM,277CALLBACK_RESOURCE_USAGE_COPY_TO,278CALLBACK_RESOURCE_USAGE_RESOLVE_FROM,279CALLBACK_RESOURCE_USAGE_RESOLVE_TO,280CALLBACK_RESOURCE_USAGE_UNIFORM_BUFFER_READ,281CALLBACK_RESOURCE_USAGE_INDIRECT_BUFFER_READ,282CALLBACK_RESOURCE_USAGE_TEXTURE_BUFFER_READ,283CALLBACK_RESOURCE_USAGE_TEXTURE_BUFFER_READ_WRITE,284CALLBACK_RESOURCE_USAGE_STORAGE_BUFFER_READ,285CALLBACK_RESOURCE_USAGE_STORAGE_BUFFER_READ_WRITE,286CALLBACK_RESOURCE_USAGE_VERTEX_BUFFER_READ,287CALLBACK_RESOURCE_USAGE_INDEX_BUFFER_READ,288CALLBACK_RESOURCE_USAGE_TEXTURE_SAMPLE,289CALLBACK_RESOURCE_USAGE_STORAGE_IMAGE_READ,290CALLBACK_RESOURCE_USAGE_STORAGE_IMAGE_READ_WRITE,291CALLBACK_RESOURCE_USAGE_ATTACHMENT_COLOR_READ_WRITE,292CALLBACK_RESOURCE_USAGE_ATTACHMENT_DEPTH_STENCIL_READ_WRITE,293CALLBACK_RESOURCE_USAGE_ATTACHMENT_FRAGMENT_SHADING_RATE_READ,294CALLBACK_RESOURCE_USAGE_ATTACHMENT_FRAGMENT_DENSITY_MAP_READ,295CALLBACK_RESOURCE_USAGE_GENERAL,296CALLBACK_RESOURCE_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT,297CALLBACK_RESOURCE_USAGE_ACCELERATION_STRUCTURE_READ,298CALLBACK_RESOURCE_USAGE_ACCELERATION_STRUCTURE_READ_WRITE,299CALLBACK_RESOURCE_USAGE_MAX300};301302struct CallbackResource {303RID rid;304CallbackResourceType type = CALLBACK_RESOURCE_TYPE_TEXTURE;305CallbackResourceUsage usage = CALLBACK_RESOURCE_USAGE_NONE;306};307308Error driver_callback_add(RDD::DriverCallback p_callback, void *p_userdata, VectorView<CallbackResource> p_resources);309310/*****************/311/**** TEXTURE ****/312/*****************/313314// In modern APIs, the concept of textures may not exist;315// instead there is the image (the memory pretty much,316// the view (how the memory is interpreted) and the317// sampler (how it's sampled from the shader).318//319// Texture here includes the first two stages, but320// It's possible to create textures sharing the image321// but with different views. The main use case for this322// is textures that can be read as both SRGB/Linear,323// or slices of a texture (a mipmap, a layer, a 3D slice)324// for a framebuffer to render into it.325326struct Texture {327struct SharedFallback {328uint32_t revision = 1;329RDD::TextureID texture;330RDG::ResourceTracker *texture_tracker = nullptr;331RDD::BufferID buffer;332RDG::ResourceTracker *buffer_tracker = nullptr;333bool raw_reinterpretation = false;334};335336RDD::TextureID driver_id;337338TextureType type = TEXTURE_TYPE_MAX;339DataFormat format = DATA_FORMAT_MAX;340TextureSamples samples = TEXTURE_SAMPLES_MAX;341TextureSliceType slice_type = TEXTURE_SLICE_MAX;342Rect2i slice_rect;343uint32_t width = 0;344uint32_t height = 0;345uint32_t depth = 0;346uint32_t layers = 0;347uint32_t mipmaps = 0;348uint32_t usage_flags = 0;349uint32_t base_mipmap = 0;350uint32_t base_layer = 0;351352Vector<DataFormat> allowed_shared_formats;353354bool is_resolve_buffer = false;355bool is_discardable = false;356bool has_initial_data = false;357bool pending_clear = false;358359BitField<RDD::TextureAspectBits> read_aspect_flags = {};360BitField<RDD::TextureAspectBits> barrier_aspect_flags = {};361bool bound = false; // Bound to framebuffer.362RID owner;363364RDG::ResourceTracker *draw_tracker = nullptr;365HashMap<Rect2i, RDG::ResourceTracker *> *slice_trackers = nullptr;366SharedFallback *shared_fallback = nullptr;367int32_t transfer_worker_index = -1;368uint64_t transfer_worker_operation = 0;369370RDD::TextureSubresourceRange barrier_range() const {371RDD::TextureSubresourceRange r;372r.aspect = barrier_aspect_flags;373r.base_mipmap = base_mipmap;374r.mipmap_count = mipmaps;375r.base_layer = base_layer;376r.layer_count = layers;377return r;378}379380TextureFormat texture_format() const {381TextureFormat tf;382tf.format = format;383tf.width = width;384tf.height = height;385tf.depth = depth;386tf.array_layers = layers;387tf.mipmaps = mipmaps;388tf.texture_type = type;389tf.samples = samples;390tf.usage_bits = usage_flags;391tf.shareable_formats = allowed_shared_formats;392tf.is_resolve_buffer = is_resolve_buffer;393tf.is_discardable = is_discardable;394return tf;395}396};397398RID_Owner<Texture, true> texture_owner;399uint32_t texture_upload_region_size_px = 0;400uint32_t texture_download_region_size_px = 0;401402uint32_t _texture_layer_count(Texture *p_texture) const;403uint32_t _texture_alignment(Texture *p_texture) const;404Error _texture_initialize(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data, RDD::TextureLayout p_dst_layout, bool p_immediate_flush);405void _texture_check_shared_fallback(Texture *p_texture);406void _texture_update_shared_fallback(RID p_texture_rid, Texture *p_texture, bool p_for_writing);407void _texture_free_shared_fallback(Texture *p_texture);408void _texture_copy_shared(RID p_src_texture_rid, Texture *p_src_texture, RID p_dst_texture_rid, Texture *p_dst_texture);409void _texture_create_reinterpret_buffer(Texture *p_texture);410void _texture_check_pending_clear(RID p_texture_rid, Texture *p_texture);411void _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);412void _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);413uint32_t _texture_vrs_method_to_usage_bits() const;414415struct TextureGetDataRequest {416uint32_t frame_local_index = 0;417uint32_t frame_local_count = 0;418Callable callback;419uint32_t width = 0;420uint32_t height = 0;421uint32_t depth = 0;422uint32_t mipmaps = 0;423RDD::DataFormat format = RDD::DATA_FORMAT_MAX;424};425426public:427struct TextureView {428DataFormat format_override = DATA_FORMAT_MAX; // // Means, use same as format.429TextureSwizzle swizzle_r = TEXTURE_SWIZZLE_R;430TextureSwizzle swizzle_g = TEXTURE_SWIZZLE_G;431TextureSwizzle swizzle_b = TEXTURE_SWIZZLE_B;432TextureSwizzle swizzle_a = TEXTURE_SWIZZLE_A;433434bool operator==(const TextureView &p_other) const {435if (format_override != p_other.format_override) {436return false;437} else if (swizzle_r != p_other.swizzle_r) {438return false;439} else if (swizzle_g != p_other.swizzle_g) {440return false;441} else if (swizzle_b != p_other.swizzle_b) {442return false;443} else if (swizzle_a != p_other.swizzle_a) {444return false;445} else {446return true;447}448}449};450451RID texture_create(const TextureFormat &p_format, const TextureView &p_view, const Vector<Vector<uint8_t>> &p_data = Vector<Vector<uint8_t>>());452RID texture_create_shared(const TextureView &p_view, RID p_with_texture);453RID 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 = 1);454RID 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 = 1, TextureSliceType p_slice_type = TEXTURE_SLICE_2D, uint32_t p_layers = 0);455Error texture_update(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data);456Vector<uint8_t> texture_get_data(RID p_texture, uint32_t p_layer); // CPU textures will return immediately, while GPU textures will most likely force a flush457Error texture_get_data_async(RID p_texture, uint32_t p_layer, const Callable &p_callback);458459bool texture_is_format_supported_for_usage(DataFormat p_format, BitField<TextureUsageBits> p_usage) const;460bool texture_is_shared(RID p_texture);461bool texture_is_valid(RID p_texture);462TextureFormat texture_get_format(RID p_texture);463Size2i texture_size(RID p_texture);464#ifndef DISABLE_DEPRECATED465uint64_t texture_get_native_handle(RID p_texture);466#endif467468Error 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);469Error 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);470Error texture_resolve_multisample(RID p_from_texture, RID p_to_texture);471472void texture_set_discardable(RID p_texture, bool p_discardable);473bool texture_is_discardable(RID p_texture);474475public:476/*************/477/**** VRS ****/478/*************/479480enum VRSMethod {481VRS_METHOD_NONE,482VRS_METHOD_FRAGMENT_SHADING_RATE,483VRS_METHOD_FRAGMENT_DENSITY_MAP,484};485486private:487VRSMethod vrs_method = VRS_METHOD_NONE;488DataFormat vrs_format = DATA_FORMAT_MAX;489Size2i vrs_texel_size;490491static RDG::ResourceUsage _vrs_usage_from_method(VRSMethod p_method);492static RDD::PipelineStageBits _vrs_stages_from_method(VRSMethod p_method);493static RDD::TextureLayout _vrs_layout_from_method(VRSMethod p_method);494void _vrs_detect_method();495496public:497VRSMethod vrs_get_method() const;498DataFormat vrs_get_format() const;499Size2i vrs_get_texel_size() const;500501/*********************/502/**** FRAMEBUFFER ****/503/*********************/504505// In modern APIs, generally, framebuffers work similar to how they506// do in OpenGL, with the exception that507// the "format" (RDD::RenderPassID) is not dynamic508// and must be more or less the same as the one509// used for the render pipelines.510511struct AttachmentFormat {512enum : uint32_t {513UNUSED_ATTACHMENT = 0xFFFFFFFF514};515DataFormat format;516TextureSamples samples;517uint32_t usage_flags;518AttachmentFormat() {519format = DATA_FORMAT_R8G8B8A8_UNORM;520samples = TEXTURE_SAMPLES_1;521usage_flags = 0;522}523};524525struct FramebufferPass {526Vector<int32_t> color_attachments;527Vector<int32_t> input_attachments;528Vector<int32_t> resolve_attachments;529Vector<int32_t> preserve_attachments;530int32_t depth_attachment = ATTACHMENT_UNUSED;531int32_t depth_resolve_attachment = ATTACHMENT_UNUSED;532};533534typedef int64_t FramebufferFormatID;535536private:537struct FramebufferFormatKey {538Vector<AttachmentFormat> attachments;539Vector<FramebufferPass> passes;540uint32_t view_count = 1;541VRSMethod vrs_method = VRS_METHOD_NONE;542int32_t vrs_attachment = ATTACHMENT_UNUSED;543Size2i vrs_texel_size;544545bool operator<(const FramebufferFormatKey &p_key) const {546if (vrs_texel_size != p_key.vrs_texel_size) {547return vrs_texel_size < p_key.vrs_texel_size;548}549550if (vrs_attachment != p_key.vrs_attachment) {551return vrs_attachment < p_key.vrs_attachment;552}553554if (vrs_method != p_key.vrs_method) {555return vrs_method < p_key.vrs_method;556}557558if (view_count != p_key.view_count) {559return view_count < p_key.view_count;560}561562uint32_t pass_size = passes.size();563uint32_t key_pass_size = p_key.passes.size();564if (pass_size != key_pass_size) {565return pass_size < key_pass_size;566}567const FramebufferPass *pass_ptr = passes.ptr();568const FramebufferPass *key_pass_ptr = p_key.passes.ptr();569570for (uint32_t i = 0; i < pass_size; i++) {571{ // Compare color attachments.572uint32_t attachment_size = pass_ptr[i].color_attachments.size();573uint32_t key_attachment_size = key_pass_ptr[i].color_attachments.size();574if (attachment_size != key_attachment_size) {575return attachment_size < key_attachment_size;576}577const int32_t *pass_attachment_ptr = pass_ptr[i].color_attachments.ptr();578const int32_t *key_pass_attachment_ptr = key_pass_ptr[i].color_attachments.ptr();579580for (uint32_t j = 0; j < attachment_size; j++) {581if (pass_attachment_ptr[j] != key_pass_attachment_ptr[j]) {582return pass_attachment_ptr[j] < key_pass_attachment_ptr[j];583}584}585}586{ // Compare input attachments.587uint32_t attachment_size = pass_ptr[i].input_attachments.size();588uint32_t key_attachment_size = key_pass_ptr[i].input_attachments.size();589if (attachment_size != key_attachment_size) {590return attachment_size < key_attachment_size;591}592const int32_t *pass_attachment_ptr = pass_ptr[i].input_attachments.ptr();593const int32_t *key_pass_attachment_ptr = key_pass_ptr[i].input_attachments.ptr();594595for (uint32_t j = 0; j < attachment_size; j++) {596if (pass_attachment_ptr[j] != key_pass_attachment_ptr[j]) {597return pass_attachment_ptr[j] < key_pass_attachment_ptr[j];598}599}600}601{ // Compare resolve attachments.602uint32_t attachment_size = pass_ptr[i].resolve_attachments.size();603uint32_t key_attachment_size = key_pass_ptr[i].resolve_attachments.size();604if (attachment_size != key_attachment_size) {605return attachment_size < key_attachment_size;606}607const int32_t *pass_attachment_ptr = pass_ptr[i].resolve_attachments.ptr();608const int32_t *key_pass_attachment_ptr = key_pass_ptr[i].resolve_attachments.ptr();609610for (uint32_t j = 0; j < attachment_size; j++) {611if (pass_attachment_ptr[j] != key_pass_attachment_ptr[j]) {612return pass_attachment_ptr[j] < key_pass_attachment_ptr[j];613}614}615}616{ // Compare preserve attachments.617uint32_t attachment_size = pass_ptr[i].preserve_attachments.size();618uint32_t key_attachment_size = key_pass_ptr[i].preserve_attachments.size();619if (attachment_size != key_attachment_size) {620return attachment_size < key_attachment_size;621}622const int32_t *pass_attachment_ptr = pass_ptr[i].preserve_attachments.ptr();623const int32_t *key_pass_attachment_ptr = key_pass_ptr[i].preserve_attachments.ptr();624625for (uint32_t j = 0; j < attachment_size; j++) {626if (pass_attachment_ptr[j] != key_pass_attachment_ptr[j]) {627return pass_attachment_ptr[j] < key_pass_attachment_ptr[j];628}629}630}631if (pass_ptr[i].depth_attachment != key_pass_ptr[i].depth_attachment) {632return pass_ptr[i].depth_attachment < key_pass_ptr[i].depth_attachment;633}634}635636int as = attachments.size();637int bs = p_key.attachments.size();638if (as != bs) {639return as < bs;640}641642const AttachmentFormat *af_a = attachments.ptr();643const AttachmentFormat *af_b = p_key.attachments.ptr();644for (int i = 0; i < as; i++) {645const AttachmentFormat &a = af_a[i];646const AttachmentFormat &b = af_b[i];647if (a.format != b.format) {648return a.format < b.format;649}650if (a.samples != b.samples) {651return a.samples < b.samples;652}653if (a.usage_flags != b.usage_flags) {654return a.usage_flags < b.usage_flags;655}656}657658return false; // Equal.659}660};661662static RDD::RenderPassID _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 = 1, VRSMethod p_vrs_method = VRS_METHOD_NONE, int32_t p_vrs_attachment = -1, Size2i p_vrs_texel_size = Size2i(), Vector<TextureSamples> *r_samples = nullptr);663static RDD::RenderPassID _render_pass_create_from_graph(RenderingDeviceDriver *p_driver, VectorView<RDD::AttachmentLoadOp> p_load_ops, VectorView<RDD::AttachmentStoreOp> p_store_ops, void *p_user_data);664665// This is a cache and it's never freed, it ensures666// IDs for a given format are always unique.667RBMap<FramebufferFormatKey, FramebufferFormatID> framebuffer_format_cache;668struct FramebufferFormat {669const RBMap<FramebufferFormatKey, FramebufferFormatID>::Element *E;670RDD::RenderPassID render_pass; // Here for constructing shaders, never used, see section (7.2. Render Pass Compatibility from Vulkan spec).671Vector<TextureSamples> pass_samples;672uint32_t view_count = 1; // Number of views.673};674675HashMap<FramebufferFormatID, FramebufferFormat> framebuffer_formats;676677struct Framebuffer {678FramebufferFormatID format_id;679uint32_t storage_mask = 0;680Vector<RID> texture_ids;681InvalidationCallback invalidated_callback = nullptr;682void *invalidated_callback_userdata = nullptr;683RDG::FramebufferCache *framebuffer_cache = nullptr;684Size2 size;685uint32_t view_count;686};687688RID_Owner<Framebuffer, true> framebuffer_owner;689690public:691// This ID is warranted to be unique for the same formats, does not need to be freed692FramebufferFormatID framebuffer_format_create(const Vector<AttachmentFormat> &p_format, uint32_t p_view_count = 1, int32_t p_vrs_attachment = -1);693FramebufferFormatID framebuffer_format_create_multipass(const Vector<AttachmentFormat> &p_attachments, const Vector<FramebufferPass> &p_passes, uint32_t p_view_count = 1, int32_t p_vrs_attachment = -1);694FramebufferFormatID framebuffer_format_create_empty(TextureSamples p_samples = TEXTURE_SAMPLES_1);695TextureSamples framebuffer_format_get_texture_samples(FramebufferFormatID p_format, uint32_t p_pass = 0);696697RID framebuffer_create(const Vector<RID> &p_texture_attachments, FramebufferFormatID p_format_check = INVALID_ID, uint32_t p_view_count = 1);698RID framebuffer_create_multipass(const Vector<RID> &p_texture_attachments, const Vector<FramebufferPass> &p_passes, FramebufferFormatID p_format_check = INVALID_ID, uint32_t p_view_count = 1);699RID framebuffer_create_empty(const Size2i &p_size, TextureSamples p_samples = TEXTURE_SAMPLES_1, FramebufferFormatID p_format_check = INVALID_ID);700bool framebuffer_is_valid(RID p_framebuffer) const;701void framebuffer_set_invalidation_callback(RID p_framebuffer, InvalidationCallback p_callback, void *p_userdata);702703FramebufferFormatID framebuffer_get_format(RID p_framebuffer);704Size2 framebuffer_get_size(RID p_framebuffer);705706/*****************/707/**** SAMPLER ****/708/*****************/709private:710RID_Owner<RDD::SamplerID, true> sampler_owner;711712public:713RID sampler_create(const SamplerState &p_state);714bool sampler_is_format_supported_for_filter(DataFormat p_format, SamplerFilter p_sampler_filter) const;715716/**********************/717/**** VERTEX ARRAY ****/718/**********************/719720typedef int64_t VertexFormatID;721722private:723// Vertex buffers in Vulkan are similar to how724// they work in OpenGL, except that instead of725// an attribute index, there is a buffer binding726// index (for binding the buffers in real-time)727// and a location index (what is used in the shader).728//729// This mapping is done here internally, and it's not730// exposed.731732RID_Owner<Buffer, true> vertex_buffer_owner;733734struct VertexDescriptionKey {735Vector<VertexAttribute> vertex_formats;736737bool operator==(const VertexDescriptionKey &p_key) const {738int vdc = vertex_formats.size();739int vdck = p_key.vertex_formats.size();740741if (vdc != vdck) {742return false;743} else {744const VertexAttribute *a_ptr = vertex_formats.ptr();745const VertexAttribute *b_ptr = p_key.vertex_formats.ptr();746for (int i = 0; i < vdc; i++) {747const VertexAttribute &a = a_ptr[i];748const VertexAttribute &b = b_ptr[i];749750if (a.location != b.location) {751return false;752}753if (a.offset != b.offset) {754return false;755}756if (a.format != b.format) {757return false;758}759if (a.stride != b.stride) {760return false;761}762if (a.frequency != b.frequency) {763return false;764}765}766return true; // They are equal.767}768}769770uint32_t hash() const {771int vdc = vertex_formats.size();772uint32_t h = hash_murmur3_one_32(vdc);773const VertexAttribute *ptr = vertex_formats.ptr();774for (int i = 0; i < vdc; i++) {775const VertexAttribute &vd = ptr[i];776h = hash_murmur3_one_32(vd.location, h);777h = hash_murmur3_one_32(vd.offset, h);778h = hash_murmur3_one_32(vd.format, h);779h = hash_murmur3_one_32(vd.stride, h);780h = hash_murmur3_one_32(vd.frequency, h);781}782return hash_fmix32(h);783}784};785786struct VertexDescriptionHash {787static _FORCE_INLINE_ uint32_t hash(const VertexDescriptionKey &p_key) {788return p_key.hash();789}790};791792// This is a cache and it's never freed, it ensures that793// ID used for a specific format always remain the same.794HashMap<VertexDescriptionKey, VertexFormatID, VertexDescriptionHash> vertex_format_cache;795796struct VertexDescriptionCache {797Vector<VertexAttribute> vertex_formats;798VertexAttributeBindingsMap bindings;799RDD::VertexFormatID driver_id;800};801802HashMap<VertexFormatID, VertexDescriptionCache> vertex_formats;803804struct VertexArray {805RID buffer;806VertexFormatID description;807int vertex_count = 0;808uint32_t max_instances_allowed = 0;809810Vector<RDD::BufferID> buffers; // Not owned, just referenced.811Vector<RDG::ResourceTracker *> draw_trackers; // Not owned, just referenced.812Vector<uint64_t> offsets;813Vector<int32_t> transfer_worker_indices;814Vector<uint64_t> transfer_worker_operations;815HashSet<RID> untracked_buffers;816};817818RID_Owner<VertexArray, true> vertex_array_owner;819820struct IndexBuffer : public Buffer {821uint32_t max_index = 0; // Used for validation.822uint32_t index_count = 0;823IndexBufferFormat format = INDEX_BUFFER_FORMAT_UINT16;824bool supports_restart_indices = false;825};826827RID_Owner<IndexBuffer, true> index_buffer_owner;828829struct IndexArray {830uint32_t max_index = 0; // Remember the maximum index here too, for validation.831RDD::BufferID driver_id; // Not owned, inherited from index buffer.832RDG::ResourceTracker *draw_tracker = nullptr; // Not owned, inherited from index buffer.833uint32_t offset = 0;834uint32_t indices = 0;835IndexBufferFormat format = INDEX_BUFFER_FORMAT_UINT16;836bool supports_restart_indices = false;837int32_t transfer_worker_index = -1;838uint64_t transfer_worker_operation = 0;839};840841RID_Owner<IndexArray, true> index_array_owner;842843public:844enum BufferCreationBits {845BUFFER_CREATION_DEVICE_ADDRESS_BIT = (1 << 0),846BUFFER_CREATION_AS_STORAGE_BIT = (1 << 1),847BUFFER_CREATION_DYNAMIC_PERSISTENT_BIT = (1 << 2),848BUFFER_CREATION_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT = (1 << 3),849};850851enum StorageBufferUsage {852STORAGE_BUFFER_USAGE_DISPATCH_INDIRECT = (1 << 0),853};854855RID vertex_buffer_create(uint32_t p_size_bytes, Span<uint8_t> p_data = {}, BitField<BufferCreationBits> p_creation_bits = 0);856RID _vertex_buffer_create(uint32_t p_size_bytes, const Vector<uint8_t> &p_data, BitField<BufferCreationBits> p_creation_bits = 0) {857return vertex_buffer_create(p_size_bytes, p_data, p_creation_bits);858}859860// This ID is warranted to be unique for the same formats, does not need to be freed861VertexFormatID vertex_format_create(const Vector<VertexAttribute> &p_vertex_descriptions);862RID vertex_array_create(uint32_t p_vertex_count, VertexFormatID p_vertex_format, const Vector<RID> &p_src_buffers, const Vector<uint64_t> &p_offsets = Vector<uint64_t>());863864RID index_buffer_create(uint32_t p_index_count, IndexBufferFormat p_format, Span<uint8_t> p_data = {}, bool p_use_restart_indices = false, BitField<BufferCreationBits> p_creation_bits = 0);865RID _index_buffer_create(uint32_t p_index_count, IndexBufferFormat p_format, const Vector<uint8_t> &p_data, bool p_use_restart_indices = false, BitField<BufferCreationBits> p_creation_bits = 0) {866return index_buffer_create(p_index_count, p_format, p_data, p_use_restart_indices, p_creation_bits);867}868869RID index_array_create(RID p_index_buffer, uint32_t p_index_offset, uint32_t p_index_count);870871private:872BitField<RDD::BufferUsageBits> _creation_to_usage_bits(BitField<BufferCreationBits> p_creation_bits);873874/****************/875/**** SHADER ****/876/****************/877878// Some APIs (e.g., Vulkan) specifies a really complex behavior for the application879// in order to tell when descriptor sets need to be re-bound (or not).880// "When binding a descriptor set (see Descriptor Set Binding) to set881// number N, if the previously bound descriptor sets for sets zero882// through N-1 were all bound using compatible pipeline layouts,883// then performing this binding does not disturb any of the lower numbered sets.884// If, additionally, the previous bound descriptor set for set N was885// bound using a pipeline layout compatible for set N, then the bindings886// in sets numbered greater than N are also not disturbed."887// As a result, we need to figure out quickly when something is no longer "compatible".888// in order to avoid costly rebinds.889890private:891struct UniformSetFormat {892Vector<ShaderUniform> uniforms;893894_FORCE_INLINE_ bool operator<(const UniformSetFormat &p_other) const {895if (uniforms.size() != p_other.uniforms.size()) {896return uniforms.size() < p_other.uniforms.size();897}898for (int i = 0; i < uniforms.size(); i++) {899if (uniforms[i] < p_other.uniforms[i]) {900return true;901} else if (p_other.uniforms[i] < uniforms[i]) {902return false;903}904}905return false;906}907};908909// Always grows, never shrinks, ensuring unique IDs, but we assume910// the amount of formats will never be a problem, as the amount of shaders911// in a game is limited.912RBMap<UniformSetFormat, uint32_t> uniform_set_format_cache;913914// Shaders in Vulkan are just pretty much915// precompiled blocks of SPIR-V bytecode. They916// are most likely not really compiled to host917// assembly until a pipeline is created.918//919// When supplying the shaders, this implementation920// will use the reflection abilities of glslang to921// understand and cache everything required to922// create and use the descriptor sets (Vulkan's923// biggest pain).924//925// Additionally, hashes are created for every set926// to do quick validation and ensuring the user927// does not submit something invalid.928929struct Shader : public ShaderReflection {930String name; // Used for debug.931RDD::ShaderID driver_id;932uint32_t layout_hash = 0;933BitField<RDD::PipelineStageBits> stage_bits = {};934Vector<uint32_t> set_formats;935};936937String _shader_uniform_debug(RID p_shader, int p_set = -1);938939RID_Owner<Shader, true> shader_owner;940941#ifndef DISABLE_DEPRECATED942public:943enum BarrierMask {944BARRIER_MASK_VERTEX = 1,945BARRIER_MASK_FRAGMENT = 8,946BARRIER_MASK_COMPUTE = 2,947BARRIER_MASK_TRANSFER = 4,948949BARRIER_MASK_RASTER = BARRIER_MASK_VERTEX | BARRIER_MASK_FRAGMENT, // 9,950BARRIER_MASK_ALL_BARRIERS = 0x7FFF, // all flags set951BARRIER_MASK_NO_BARRIER = 0x8000,952};953954enum InitialAction {955INITIAL_ACTION_LOAD,956INITIAL_ACTION_CLEAR,957INITIAL_ACTION_DISCARD,958INITIAL_ACTION_MAX,959INITIAL_ACTION_CLEAR_REGION = INITIAL_ACTION_CLEAR,960INITIAL_ACTION_CLEAR_REGION_CONTINUE = INITIAL_ACTION_CLEAR,961INITIAL_ACTION_KEEP = INITIAL_ACTION_LOAD,962INITIAL_ACTION_DROP = INITIAL_ACTION_DISCARD,963INITIAL_ACTION_CONTINUE = INITIAL_ACTION_LOAD,964};965966enum FinalAction {967FINAL_ACTION_STORE,968FINAL_ACTION_DISCARD,969FINAL_ACTION_MAX,970FINAL_ACTION_READ = FINAL_ACTION_STORE,971FINAL_ACTION_CONTINUE = FINAL_ACTION_STORE,972};973974void barrier(BitField<BarrierMask> p_from = BARRIER_MASK_ALL_BARRIERS, BitField<BarrierMask> p_to = BARRIER_MASK_ALL_BARRIERS);975void full_barrier();976void draw_command_insert_label(String p_label_name, const Color &p_color = Color(1, 1, 1, 1));977Error 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 = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const Vector<RID> &p_storage_textures = Vector<RID>());978Error draw_list_switch_to_next_pass_split(uint32_t p_splits, DrawListID *r_split_ids);979Vector<int64_t> _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 = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const TypedArray<RID> &p_storage_textures = TypedArray<RID>());980Vector<int64_t> _draw_list_switch_to_next_pass_split(uint32_t p_splits);981982private:983void _draw_list_end_bind_compat_81356(BitField<BarrierMask> p_post_barrier);984void _compute_list_end_bind_compat_81356(BitField<BarrierMask> p_post_barrier);985void _barrier_bind_compat_81356(BitField<BarrierMask> p_from, BitField<BarrierMask> p_to);986987void _draw_list_end_bind_compat_84976(BitField<BarrierMask> p_post_barrier);988void _compute_list_end_bind_compat_84976(BitField<BarrierMask> p_post_barrier);989InitialAction _convert_initial_action_84976(InitialAction p_old_initial_action);990FinalAction _convert_final_action_84976(FinalAction p_old_final_action);991DrawListID _draw_list_begin_bind_compat_84976(RID p_framebuffer, 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);992ComputeListID _compute_list_begin_bind_compat_84976(bool p_allow_draw_overlap);993Error _buffer_update_bind_compat_84976(RID p_buffer, uint32_t p_offset, uint32_t p_size, const Vector<uint8_t> &p_data, BitField<BarrierMask> p_post_barrier);994Error _buffer_clear_bind_compat_84976(RID p_buffer, uint32_t p_offset, uint32_t p_size, BitField<BarrierMask> p_post_barrier);995Error _texture_update_bind_compat_84976(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data, BitField<BarrierMask> p_post_barrier);996Error _texture_copy_bind_compat_84976(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, BitField<BarrierMask> p_post_barrier);997Error _texture_clear_bind_compat_84976(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, BitField<BarrierMask> p_post_barrier);998Error _texture_resolve_multisample_bind_compat_84976(RID p_from_texture, RID p_to_texture, BitField<BarrierMask> p_post_barrier);9991000FramebufferFormatID _screen_get_framebuffer_format_bind_compat_87340() const;10011002DrawListID _draw_list_begin_bind_compat_90993(RID p_framebuffer, 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);10031004DrawListID _draw_list_begin_bind_compat_98670(RID p_framebuffer, 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, uint32_t p_breadcrumb);10051006RID _uniform_buffer_create_bind_compat_101561(uint32_t p_size_bytes, const Vector<uint8_t> &p_data);1007RID _vertex_buffer_create_bind_compat_101561(uint32_t p_size_bytes, const Vector<uint8_t> &p_data, bool p_use_as_storage);1008RID _index_buffer_create_bind_compat_101561(uint32_t p_size_indices, IndexBufferFormat p_format, const Vector<uint8_t> &p_data, bool p_use_restart_indices);1009RID _storage_buffer_create_bind_compat_101561(uint32_t p_size, const Vector<uint8_t> &p_data, BitField<StorageBufferUsage> p_usage);1010#endif10111012public:1013RenderingDeviceDriver *get_device_driver() const { return driver; }1014RenderingContextDriver *get_context_driver() const { return context; }10151016const RDD::Capabilities &get_device_capabilities() const { return driver->get_capabilities(); }10171018bool has_feature(const Features p_feature) const;10191020Vector<uint8_t> shader_compile_spirv_from_source(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language = SHADER_LANGUAGE_GLSL, String *r_error = nullptr, bool p_allow_cache = true);1021Vector<uint8_t> shader_compile_binary_from_spirv(const Vector<ShaderStageSPIRVData> &p_spirv, const String &p_shader_name = "");10221023RID shader_create_from_spirv(const Vector<ShaderStageSPIRVData> &p_spirv, const String &p_shader_name = "");1024RID shader_create_from_bytecode(const Vector<uint8_t> &p_shader_binary, RID p_placeholder = RID());1025RID shader_create_placeholder();1026void shader_destroy_modules(RID p_shader);10271028uint64_t shader_get_vertex_input_attribute_mask(RID p_shader);10291030/******************/1031/**** UNIFORMS ****/1032/******************/1033String get_perf_report() const;10341035/*****************/1036/**** BUFFERS ****/1037/*****************/10381039RID uniform_buffer_create(uint32_t p_size_bytes, Span<uint8_t> p_data = {}, BitField<BufferCreationBits> p_creation_bits = 0);1040RID _uniform_buffer_create(uint32_t p_size_bytes, const Vector<uint8_t> &p_data, BitField<BufferCreationBits> p_creation_bits = 0) {1041return uniform_buffer_create(p_size_bytes, p_data, p_creation_bits);1042}10431044RID storage_buffer_create(uint32_t p_size_bytes, Span<uint8_t> p_data = {}, BitField<StorageBufferUsage> p_usage = 0, BitField<BufferCreationBits> p_creation_bits = 0);1045RID _storage_buffer_create(uint32_t p_size_bytes, const Vector<uint8_t> &p_data, BitField<StorageBufferUsage> p_usage = 0, BitField<BufferCreationBits> p_creation_bits = 0) {1046return storage_buffer_create(p_size_bytes, p_data, p_usage, p_creation_bits);1047}10481049RID texture_buffer_create(uint32_t p_size_elements, DataFormat p_format, Span<uint8_t> p_data = {});1050RID _texture_buffer_create(uint32_t p_size_elements, DataFormat p_format, const Vector<uint8_t> &p_data) {1051return texture_buffer_create(p_size_elements, p_format, p_data);1052}10531054struct Uniform {1055UniformType uniform_type = UNIFORM_TYPE_IMAGE;1056uint32_t binding = 0; // Binding index as specified in shader.1057// This flag specifies that this is an immutable sampler to be set when creating pipeline layout.1058bool immutable_sampler = false;10591060private:1061// In most cases only one ID is provided per binding, so avoid allocating memory unnecessarily for performance.1062RID id; // If only one is provided, this is used.1063Vector<RID> ids; // If multiple ones are provided, this is used instead.10641065public:1066_FORCE_INLINE_ uint32_t get_id_count() const {1067return (id.is_valid() ? 1 : ids.size());1068}10691070_FORCE_INLINE_ RID get_id(uint32_t p_idx) const {1071if (id.is_valid()) {1072ERR_FAIL_COND_V(p_idx != 0, RID());1073return id;1074} else {1075return ids[p_idx];1076}1077}1078_FORCE_INLINE_ void set_id(uint32_t p_idx, RID p_id) {1079if (id.is_valid()) {1080ERR_FAIL_COND(p_idx != 0);1081id = p_id;1082} else {1083ids.write[p_idx] = p_id;1084}1085}10861087_FORCE_INLINE_ void append_id(RID p_id) {1088if (ids.is_empty()) {1089if (id == RID()) {1090id = p_id;1091} else {1092ids.push_back(id);1093ids.push_back(p_id);1094id = RID();1095}1096} else {1097ids.push_back(p_id);1098}1099}11001101_FORCE_INLINE_ void clear_ids() {1102id = RID();1103ids.clear();1104}11051106_FORCE_INLINE_ Uniform(UniformType p_type, int p_binding, RID p_id) {1107uniform_type = p_type;1108binding = p_binding;1109id = p_id;1110}1111_FORCE_INLINE_ Uniform(UniformType p_type, int p_binding, const Vector<RID> &p_ids) {1112uniform_type = p_type;1113binding = p_binding;1114ids = p_ids;1115}1116_FORCE_INLINE_ Uniform() = default;1117};11181119typedef Uniform PipelineImmutableSampler;1120RID shader_create_from_bytecode_with_samplers(const Vector<uint8_t> &p_shader_binary, RID p_placeholder = RID(), const Vector<PipelineImmutableSampler> &p_immutable_samplers = Vector<PipelineImmutableSampler>());11211122private:1123static const uint32_t MAX_UNIFORM_SETS = 16;1124static const uint32_t MAX_PUSH_CONSTANT_SIZE = 128;11251126// This structure contains the descriptor set. They _need_ to be allocated1127// for a shader (and will be erased when this shader is erased), but should1128// work for other shaders as long as the hash matches. This covers using1129// them in shader variants.1130//1131// Keep also in mind that you can share buffers between descriptor sets, so1132// the above restriction is not too serious.11331134struct UniformSet {1135uint32_t format = 0;1136RID shader_id;1137uint32_t shader_set = 0;1138RDD::UniformSetID driver_id;1139struct AttachableTexture {1140uint32_t bind = 0;1141RID texture;1142};11431144struct SharedTexture {1145uint32_t writing = 0;1146RID texture;1147};11481149LocalVector<AttachableTexture> attachable_textures; // Used for validation.1150Vector<RDG::ResourceTracker *> draw_trackers;1151Vector<RDG::ResourceUsage> draw_trackers_usage;1152HashMap<RID, RDG::ResourceUsage> untracked_usage;1153LocalVector<SharedTexture> shared_textures_to_update;1154LocalVector<RID> pending_clear_textures;1155InvalidationCallback invalidated_callback = nullptr;1156void *invalidated_callback_userdata = nullptr;1157};11581159RID_Owner<UniformSet, true> uniform_set_owner;11601161void _uniform_set_update_shared(UniformSet *p_uniform_set);1162void _uniform_set_update_clears(UniformSet *p_uniform_set);11631164public:1165/** Bake a set of uniforms that can be bound at runtime with the given shader.1166* @remark Setting p_linear_pool = true while keeping the RID around for longer than the current frame will result in undefined behavior.1167* @param p_uniforms The uniforms to bake into a set.1168* @param p_shader The shader you intend to bind these uniforms with.1169* @param p_set_index The set. Should be in range [0; 4)1170* The value 4 comes from physical_device_properties.limits.maxBoundDescriptorSets. Vulkan only guarantees maxBoundDescriptorSets >= 4 (== 4 is very common on Mobile).1171* @param p_linear_pool If you call this function every frame (and free the returned RID within the same frame!), set it to true for better performance.1172* If you plan on keeping the return value around for more than one frame (e.g. Sets that are created once and reused forever) you MUST set it to false.1173* @return Baked descriptor set.1174*/1175RID uniform_set_create(const VectorView<Uniform> &p_uniforms, RID p_shader, uint32_t p_shader_set, bool p_linear_pool = false);1176bool uniform_set_is_valid(RID p_uniform_set);1177void uniform_set_set_invalidation_callback(RID p_uniform_set, InvalidationCallback p_callback, void *p_userdata);11781179bool uniform_sets_have_linear_pools() const;11801181/*******************/1182/**** PIPELINES ****/1183/*******************/11841185// Render pipeline contains ALL the1186// information required for drawing.1187// This includes all the rasterizer state1188// as well as shader used, framebuffer format,1189// etc.1190// While the pipeline is just a single object1191// (VkPipeline) a lot of values are also saved1192// here to do validation (vulkan does none by1193// default) and warn the user if something1194// was not supplied as intended.1195private:1196struct RenderPipeline {1197// Cached values for validation.1198#ifdef DEBUG_ENABLED1199struct Validation {1200FramebufferFormatID framebuffer_format;1201uint32_t render_pass = 0;1202uint32_t dynamic_state = 0;1203VertexFormatID vertex_format;1204bool uses_restart_indices = false;1205uint32_t primitive_minimum = 0;1206uint32_t primitive_divisor = 0;1207} validation;1208#endif1209// Actual pipeline.1210RID shader;1211RDD::ShaderID shader_driver_id;1212uint32_t shader_layout_hash = 0;1213Vector<uint32_t> set_formats;1214RDD::PipelineID driver_id;1215BitField<RDD::PipelineStageBits> stage_bits = {};1216uint32_t push_constant_size = 0;1217};12181219RID_Owner<RenderPipeline, true> render_pipeline_owner;12201221bool pipeline_cache_enabled = false;1222size_t pipeline_cache_size = 0;1223String pipeline_cache_file_path;1224WorkerThreadPool::TaskID pipeline_cache_save_task = WorkerThreadPool::INVALID_TASK_ID;12251226Vector<uint8_t> _load_pipeline_cache();1227static void _save_pipeline_cache(void *p_data);12281229struct ComputePipeline {1230RID shader;1231RDD::ShaderID shader_driver_id;1232uint32_t shader_layout_hash = 0;1233Vector<uint32_t> set_formats;1234RDD::PipelineID driver_id;1235uint32_t push_constant_size = 0;1236uint32_t local_group_size[3] = { 0, 0, 0 };1237};12381239RID_Owner<ComputePipeline, true> compute_pipeline_owner;12401241struct RaytracingPipeline {1242RID shader;1243RDD::ShaderID shader_driver_id;1244uint32_t shader_layout_hash = 0;1245Vector<uint32_t> set_formats;1246RDD::RaytracingPipelineID driver_id;1247uint32_t push_constant_size = 0;1248};12491250RID_Owner<RaytracingPipeline> raytracing_pipeline_owner;12511252public:1253RID 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 = 0, uint32_t p_for_render_pass = 0, const Vector<PipelineSpecializationConstant> &p_specialization_constants = Vector<PipelineSpecializationConstant>());1254bool render_pipeline_is_valid(RID p_pipeline);12551256RID compute_pipeline_create(RID p_shader, const Vector<PipelineSpecializationConstant> &p_specialization_constants = Vector<PipelineSpecializationConstant>());1257bool compute_pipeline_is_valid(RID p_pipeline);12581259RID raytracing_pipeline_create(RID p_shader, const Vector<PipelineSpecializationConstant> &p_specialization_constants = Vector<PipelineSpecializationConstant>());1260bool raytracing_pipeline_is_valid(RID p_pipeline);12611262void update_pipeline_cache(bool p_closing = false);12631264private:1265/****************/1266/**** SCREEN ****/1267/****************/1268HashMap<DisplayServer::WindowID, RDD::SwapChainID> screen_swap_chains;1269HashMap<DisplayServer::WindowID, RDD::FramebufferID> screen_framebuffers;12701271uint32_t _get_swap_chain_desired_count() const;12721273public:1274Error screen_create(DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID);1275Error screen_prepare_for_drawing(DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID);1276int screen_get_width(DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID) const;1277int screen_get_height(DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID) const;1278int screen_get_pre_rotation_degrees(DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID) const;1279FramebufferFormatID screen_get_framebuffer_format(DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID) const;1280Error screen_free(DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID);12811282private:1283/********************************/1284/**** ACCELERATION STRUCTURE ****/1285/********************************/12861287struct InstancesBuffer {1288Buffer buffer;1289uint32_t instance_count;1290Vector<RID> blases;1291};12921293struct AccelerationStructure {1294RDD::AccelerationStructureID driver_id;1295RDD::AccelerationStructureType type = RDD::ACCELERATION_STRUCTURE_TYPE_BLAS;1296RDG::ResourceTracker *draw_tracker = nullptr;1297Vector<RDG::ResourceTracker *> draw_trackers;12981299RID scratch_buffer;1300RID vertex_array;1301RID index_array;1302RID transform_buffer;1303RID instances_buffer;1304};13051306RID_Owner<InstancesBuffer, true> instances_buffer_owner;1307RID_Owner<AccelerationStructure> acceleration_structure_owner;13081309public:1310enum AccelerationStructureGeometryBits {1311ACCELERATION_STRUCTURE_GEOMETRY_OPAQUE = (1 << 0),1312ACCELERATION_STRUCTURE_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION = (1 << 1),1313};13141315RID blas_create(RID p_vertex_array, RID p_index_array, BitField<AccelerationStructureGeometryBits> p_geometry_bits = 0, uint32_t p_position_attribute_location = 0);1316RID tlas_instances_buffer_create(uint32_t p_instance_count, BitField<BufferCreationBits> p_creation_bits = 0);1317void tlas_instances_buffer_fill(RID p_buffer, const Vector<RID> &p_blases, VectorView<Transform3D> p_transforms);1318RID tlas_create(RID p_instances_buffer);1319Error acceleration_structure_build(RID p_acceleration_structure);13201321/*************************/1322/**** DRAW LISTS (II) ****/1323/*************************/13241325private:1326// Draw list contains both the command buffer1327// used for drawing as well as a LOT of1328// information used for validation. This1329// validation is cheap so most of it can1330// also run in release builds.13311332struct DrawList {1333Rect2i viewport;1334bool active = false;13351336struct SetState {1337uint32_t pipeline_expected_format = 0;1338uint32_t uniform_set_format = 0;1339RDD::UniformSetID uniform_set_driver_id;1340RID uniform_set;1341bool bound = false;1342};13431344struct State {1345SetState sets[MAX_UNIFORM_SETS];1346uint32_t set_count = 0;1347RID pipeline;1348RID pipeline_shader;1349RDD::ShaderID pipeline_shader_driver_id;1350uint32_t pipeline_shader_layout_hash = 0;1351uint32_t pipeline_push_constant_size = 0;1352RID vertex_array;1353RID index_array;1354uint32_t draw_count = 0;1355} state;13561357#ifdef DEBUG_ENABLED1358struct Validation {1359// Actual render pass values.1360uint32_t dynamic_state = 0;1361VertexFormatID vertex_format = INVALID_ID;1362uint32_t vertex_array_size = 0;1363uint32_t vertex_max_instances_allowed = 0xFFFFFFFF;1364bool index_buffer_uses_restart_indices = false;1365uint32_t index_array_count = 0;1366uint32_t index_array_max_index = 0;1367Vector<uint32_t> set_formats;1368Vector<bool> set_bound;1369Vector<RID> set_rids;1370// Last pipeline set values.1371bool pipeline_active = false;1372uint32_t pipeline_dynamic_state = 0;1373VertexFormatID pipeline_vertex_format = INVALID_ID;1374RID pipeline_shader;1375bool pipeline_uses_restart_indices = false;1376uint32_t pipeline_primitive_divisor = 0;1377uint32_t pipeline_primitive_minimum = 0;1378uint32_t pipeline_push_constant_size = 0;1379bool pipeline_push_constant_supplied = false;1380} validation;1381#else1382struct Validation {1383uint32_t vertex_array_size = 0;1384uint32_t index_array_count = 0;1385} validation;1386#endif1387};13881389DrawList draw_list;1390uint32_t draw_list_subpass_count = 0;1391#ifdef DEBUG_ENABLED1392FramebufferFormatID draw_list_framebuffer_format = INVALID_ID;1393#endif1394uint32_t draw_list_current_subpass = 0;13951396LocalVector<RID> draw_list_bound_textures;13971398void _draw_list_start(const Rect2i &p_viewport);1399void _draw_list_end(Rect2i *r_last_viewport = nullptr);14001401public:1402enum DrawFlags {1403DRAW_DEFAULT_ALL = 0,1404DRAW_CLEAR_COLOR_0 = (1 << 0),1405DRAW_CLEAR_COLOR_1 = (1 << 1),1406DRAW_CLEAR_COLOR_2 = (1 << 2),1407DRAW_CLEAR_COLOR_3 = (1 << 3),1408DRAW_CLEAR_COLOR_4 = (1 << 4),1409DRAW_CLEAR_COLOR_5 = (1 << 5),1410DRAW_CLEAR_COLOR_6 = (1 << 6),1411DRAW_CLEAR_COLOR_7 = (1 << 7),1412DRAW_CLEAR_COLOR_MASK = 0xFF,1413DRAW_CLEAR_COLOR_ALL = DRAW_CLEAR_COLOR_MASK,1414DRAW_IGNORE_COLOR_0 = (1 << 8),1415DRAW_IGNORE_COLOR_1 = (1 << 9),1416DRAW_IGNORE_COLOR_2 = (1 << 10),1417DRAW_IGNORE_COLOR_3 = (1 << 11),1418DRAW_IGNORE_COLOR_4 = (1 << 12),1419DRAW_IGNORE_COLOR_5 = (1 << 13),1420DRAW_IGNORE_COLOR_6 = (1 << 14),1421DRAW_IGNORE_COLOR_7 = (1 << 15),1422DRAW_IGNORE_COLOR_MASK = 0xFF00,1423DRAW_IGNORE_COLOR_ALL = DRAW_IGNORE_COLOR_MASK,1424DRAW_CLEAR_DEPTH = (1 << 16),1425DRAW_IGNORE_DEPTH = (1 << 17),1426DRAW_CLEAR_STENCIL = (1 << 18),1427DRAW_IGNORE_STENCIL = (1 << 19),1428DRAW_CLEAR_ALL = DRAW_CLEAR_COLOR_ALL | DRAW_CLEAR_DEPTH | DRAW_CLEAR_STENCIL,1429DRAW_IGNORE_ALL = DRAW_IGNORE_COLOR_ALL | DRAW_IGNORE_DEPTH | DRAW_IGNORE_STENCIL1430};14311432/**1433* @param p_clear_color Must use linear encoding when HDR 2D is active.1434*/1435DrawListID draw_list_begin_for_screen(DisplayServer::WindowID p_screen = 0, const Color &p_clear_color = Color());1436/**1437* @param p_clear_color_values Color values must use linear encoding when HDR 2D is active.1438*/1439DrawListID draw_list_begin(RID p_framebuffer, BitField<DrawFlags> p_draw_flags = DRAW_DEFAULT_ALL, VectorView<Color> p_clear_color_values = VectorView<Color>(), float p_clear_depth_value = 1.0f, uint32_t p_clear_stencil_value = 0, const Rect2 &p_region = Rect2(), uint32_t p_breadcrumb = 0);1440DrawListID _draw_list_begin_bind(RID p_framebuffer, BitField<DrawFlags> p_draw_flags = DRAW_DEFAULT_ALL, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth_value = 1.0f, uint32_t p_clear_stencil_value = 0, const Rect2 &p_region = Rect2(), uint32_t p_breadcrumb = 0);14411442void draw_list_set_blend_constants(DrawListID p_list, const Color &p_color);1443void draw_list_bind_render_pipeline(DrawListID p_list, RID p_render_pipeline);1444void draw_list_bind_uniform_set(DrawListID p_list, RID p_uniform_set, uint32_t p_index);1445void draw_list_bind_vertex_array(DrawListID p_list, RID p_vertex_array);1446void 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 = Vector<uint64_t>());1447void draw_list_bind_index_array(DrawListID p_list, RID p_index_array);1448void draw_list_set_line_width(DrawListID p_list, float p_width);1449void draw_list_set_push_constant(DrawListID p_list, const void *p_data, uint32_t p_data_size);14501451void draw_list_draw(DrawListID p_list, bool p_use_indices, uint32_t p_instances = 1, uint32_t p_procedural_vertices = 0);1452void draw_list_draw_indirect(DrawListID p_list, bool p_use_indices, RID p_buffer, uint32_t p_offset = 0, uint32_t p_draw_count = 1, uint32_t p_stride = 0);14531454void draw_list_set_viewport(DrawListID p_list, const Rect2 &p_rect);1455void draw_list_enable_scissor(DrawListID p_list, const Rect2 &p_rect);1456void draw_list_disable_scissor(DrawListID p_list);14571458uint32_t draw_list_get_current_pass();1459DrawListID draw_list_switch_to_next_pass();14601461void draw_list_end();14621463private:1464/**************************/1465/**** RAYTRACING LISTS ****/1466/**************************/14671468struct RaytracingList {1469bool active = false;1470struct SetState {1471uint32_t pipeline_expected_format = 0;1472uint32_t uniform_set_format = 0;1473RDD::UniformSetID uniform_set_driver_id;1474RID uniform_set;1475bool bound = false;1476};14771478struct State {1479SetState sets[MAX_UNIFORM_SETS];1480uint32_t set_count = 0;1481RID pipeline;1482RDD::RaytracingPipelineID pipeline_driver_id;1483RID pipeline_shader;1484RDD::ShaderID pipeline_shader_driver_id;1485uint32_t pipeline_shader_layout_hash = 0;1486uint8_t push_constant_data[MAX_PUSH_CONSTANT_SIZE] = {};1487uint32_t push_constant_size = 0;1488uint32_t trace_count = 0;1489} state;14901491#ifdef DEBUG_ENABLED1492struct Validation {1493bool active = true; // Means command buffer was not closed, so you can keep adding things.1494Vector<uint32_t> set_formats;1495Vector<bool> set_bound;1496Vector<RID> set_rids;1497// Last pipeline set values.1498bool pipeline_active = false;1499RID pipeline_shader;1500uint32_t invalid_set_from = 0;1501uint32_t pipeline_push_constant_size = 0;1502bool pipeline_push_constant_supplied = false;1503} validation;1504#endif1505};15061507RaytracingList raytracing_list;1508RaytracingList::State raytracing_list_barrier_state;15091510public:1511RaytracingListID raytracing_list_begin();1512void raytracing_list_bind_raytracing_pipeline(RaytracingListID p_list, RID p_raytracing_pipeline);1513void raytracing_list_bind_uniform_set(RaytracingListID p_list, RID p_uniform_set, uint32_t p_index);1514void raytracing_list_set_push_constant(RaytracingListID p_list, const void *p_data, uint32_t p_data_size);1515void raytracing_list_trace_rays(RaytracingListID p_list, uint32_t p_width, uint32_t p_height);1516void raytracing_list_end();15171518private:1519/***********************/1520/**** COMPUTE LISTS ****/1521/***********************/15221523struct ComputeList {1524bool active = false;1525struct SetState {1526uint32_t pipeline_expected_format = 0;1527uint32_t uniform_set_format = 0;1528RDD::UniformSetID uniform_set_driver_id;1529RID uniform_set;1530bool bound = false;1531};15321533struct State {1534SetState sets[MAX_UNIFORM_SETS];1535uint32_t set_count = 0;1536RID pipeline;1537RID pipeline_shader;1538RDD::ShaderID pipeline_shader_driver_id;1539uint32_t pipeline_shader_layout_hash = 0;1540uint32_t local_group_size[3] = { 0, 0, 0 };1541uint8_t push_constant_data[MAX_PUSH_CONSTANT_SIZE] = {};1542uint32_t push_constant_size = 0;1543uint32_t dispatch_count = 0;1544} state;15451546#ifdef DEBUG_ENABLED1547struct Validation {1548Vector<uint32_t> set_formats;1549Vector<bool> set_bound;1550Vector<RID> set_rids;1551// Last pipeline set values.1552bool pipeline_active = false;1553RID pipeline_shader;1554uint32_t invalid_set_from = 0;1555uint32_t pipeline_push_constant_size = 0;1556bool pipeline_push_constant_supplied = false;1557} validation;1558#endif1559};15601561ComputeList compute_list;1562ComputeList::State compute_list_barrier_state;15631564public:1565ComputeListID compute_list_begin();1566void compute_list_bind_compute_pipeline(ComputeListID p_list, RID p_compute_pipeline);1567void compute_list_bind_uniform_set(ComputeListID p_list, RID p_uniform_set, uint32_t p_index);1568void compute_list_set_push_constant(ComputeListID p_list, const void *p_data, uint32_t p_data_size);1569void compute_list_dispatch(ComputeListID p_list, uint32_t p_x_groups, uint32_t p_y_groups, uint32_t p_z_groups);1570void compute_list_dispatch_threads(ComputeListID p_list, uint32_t p_x_threads, uint32_t p_y_threads, uint32_t p_z_threads);1571void compute_list_dispatch_indirect(ComputeListID p_list, RID p_buffer, uint32_t p_offset);1572void compute_list_add_barrier(ComputeListID p_list);15731574void compute_list_end();15751576private:1577/*************************/1578/**** TRANSFER WORKER ****/1579/*************************/15801581struct TransferWorker {1582uint32_t index = 0;1583RDD::BufferID staging_buffer;1584uint32_t max_transfer_size = 0;1585uint32_t staging_buffer_size_in_use = 0;1586uint32_t staging_buffer_size_allocated = 0;1587RDD::CommandBufferID command_buffer;1588RDD::CommandPoolID command_pool;1589RDD::FenceID command_fence;1590LocalVector<RDD::TextureBarrier> texture_barriers;1591bool recording = false;1592bool submitted = false;1593BinaryMutex thread_mutex;1594uint64_t operations_processed = 0;1595uint64_t operations_submitted = 0;1596uint64_t operations_counter = 0;1597BinaryMutex operations_mutex;1598};15991600TightLocalVector<TransferWorker *> transfer_worker_pool;1601uint32_t transfer_worker_pool_size = 0;1602uint32_t transfer_worker_pool_max_size = 1;1603TightLocalVector<uint64_t> transfer_worker_operation_used_by_draw;1604LocalVector<uint32_t> transfer_worker_pool_available_list;1605LocalVector<RDD::TextureBarrier> transfer_worker_pool_texture_barriers;1606BinaryMutex transfer_worker_pool_mutex;1607BinaryMutex transfer_worker_pool_texture_barriers_mutex;1608ConditionVariable transfer_worker_pool_condition;16091610TransferWorker *_acquire_transfer_worker(uint32_t p_transfer_size, uint32_t p_required_align, uint32_t &r_staging_offset);1611void _release_transfer_worker(TransferWorker *p_transfer_worker);1612void _end_transfer_worker(TransferWorker *p_transfer_worker);1613void _submit_transfer_worker(TransferWorker *p_transfer_worker, VectorView<RDD::SemaphoreID> p_signal_semaphores = VectorView<RDD::SemaphoreID>());1614void _wait_for_transfer_worker(TransferWorker *p_transfer_worker);1615void _flush_barriers_for_transfer_worker(TransferWorker *p_transfer_worker);1616void _check_transfer_worker_operation(uint32_t p_transfer_worker_index, uint64_t p_transfer_worker_operation);1617void _check_transfer_worker_buffer(Buffer *p_buffer);1618void _check_transfer_worker_texture(Texture *p_texture);1619void _check_transfer_worker_vertex_array(VertexArray *p_vertex_array);1620void _check_transfer_worker_index_array(IndexArray *p_index_array);1621void _submit_transfer_workers(RDD::CommandBufferID p_draw_command_buffer = RDD::CommandBufferID());1622void _submit_transfer_barriers(RDD::CommandBufferID p_draw_command_buffer);1623void _wait_for_transfer_workers();1624void _free_transfer_workers();16251626/***********************/1627/**** COMMAND GRAPH ****/1628/***********************/16291630bool _texture_make_mutable(Texture *p_texture, RID p_texture_id);1631bool _buffer_make_mutable(Buffer *p_buffer, RID p_buffer_id);1632bool _vertex_array_make_mutable(VertexArray *p_vertex_array, RID p_resource_id, RDG::ResourceTracker *p_resource_tracker);1633bool _index_array_make_mutable(IndexArray *p_index_array, RDG::ResourceTracker *p_resource_tracker);1634bool _uniform_set_make_mutable(UniformSet *p_uniform_set, RID p_resource_id, RDG::ResourceTracker *p_resource_tracker);1635bool _dependency_make_mutable(RID p_id, RID p_resource_id, RDG::ResourceTracker *p_resource_tracker);1636bool _dependencies_make_mutable_recursive(RID p_id, RDG::ResourceTracker *p_resource_tracker);1637bool _dependencies_make_mutable(RID p_id, RDG::ResourceTracker *p_resource_tracker);16381639RenderingDeviceGraph draw_graph;16401641/**************************/1642/**** QUEUE MANAGEMENT ****/1643/**************************/16441645RDD::CommandQueueFamilyID main_queue_family;1646RDD::CommandQueueFamilyID transfer_queue_family;1647RDD::CommandQueueFamilyID present_queue_family;1648RDD::CommandQueueID main_queue;1649RDD::CommandQueueID transfer_queue;1650RDD::CommandQueueID present_queue;16511652/**************************/1653/**** FRAME MANAGEMENT ****/1654/**************************/16551656// This is the frame structure. There are normally1657// 3 of these (used for triple buffering), or 21658// (double buffering). They are cycled constantly.1659//1660// It contains two command buffers, one that is1661// used internally for setting up (creating stuff)1662// and another used mostly for drawing.1663//1664// They also contains a list of things that need1665// to be disposed of when deleted, which can't1666// happen immediately due to the asynchronous1667// nature of the GPU. They will get deleted1668// when the frame is cycled.16691670struct Frame {1671// List in usage order, from last to free to first to free.1672List<Buffer> buffers_to_dispose_of;1673List<Texture> textures_to_dispose_of;1674List<Framebuffer> framebuffers_to_dispose_of;1675List<RDD::SamplerID> samplers_to_dispose_of;1676List<Shader> shaders_to_dispose_of;1677List<UniformSet> uniform_sets_to_dispose_of;1678List<RenderPipeline> render_pipelines_to_dispose_of;1679List<ComputePipeline> compute_pipelines_to_dispose_of;1680List<AccelerationStructure> acceleration_structures_to_dispose_of;1681List<RaytracingPipeline> raytracing_pipelines_to_dispose_of;16821683// Pending asynchronous data transfer for buffers.1684LocalVector<RDD::BufferID> download_buffer_staging_buffers;1685LocalVector<RDD::BufferCopyRegion> download_buffer_copy_regions;1686LocalVector<BufferGetDataRequest> download_buffer_get_data_requests;16871688// Pending asynchronous data transfer for textures.1689LocalVector<RDD::BufferID> download_texture_staging_buffers;1690LocalVector<RDD::BufferTextureCopyRegion> download_buffer_texture_copy_regions;1691LocalVector<uint32_t> download_texture_mipmap_offsets;1692LocalVector<TextureGetDataRequest> download_texture_get_data_requests;16931694// The command pool used by the command buffer.1695RDD::CommandPoolID command_pool;16961697// The command buffer used by the main thread when recording the frame.1698RDD::CommandBufferID command_buffer;16991700// Signaled by the command buffer submission. Present must wait on this semaphore.1701RDD::SemaphoreID semaphore;17021703// Signaled by the command buffer submission. Must wait on this fence before beginning command recording for the frame.1704RDD::FenceID fence;1705bool fence_signaled = false;17061707// Semaphores the frame must wait on before executing the command buffer.1708LocalVector<RDD::SemaphoreID> semaphores_to_wait_on;17091710// Swap chains prepared for drawing during the frame that must be presented.1711LocalVector<RDD::SwapChainID> swap_chains_to_present;17121713// Semaphores the transfer workers can use to wait before rendering the frame.1714// This must have the same size of the transfer worker pool.1715TightLocalVector<RDD::SemaphoreID> transfer_worker_semaphores;17161717// Extra command buffer pool used for driver workarounds or to reduce GPU bubbles by1718// splitting the final render pass to the swapchain into its own cmd buffer.1719RDG::CommandBufferPool command_buffer_pool;17201721struct Timestamp {1722String description;1723uint64_t value = 0;1724};17251726RDD::QueryPoolID timestamp_pool;17271728TightLocalVector<String> timestamp_names;1729TightLocalVector<uint64_t> timestamp_cpu_values;1730uint32_t timestamp_count = 0;1731TightLocalVector<String> timestamp_result_names;1732TightLocalVector<uint64_t> timestamp_cpu_result_values;1733TightLocalVector<uint64_t> timestamp_result_values;1734uint32_t timestamp_result_count = 0;1735uint64_t index = 0;1736};17371738uint32_t max_timestamp_query_elements = 0;17391740int frame = 0;1741TightLocalVector<Frame> frames;1742uint64_t frames_drawn = 0;17431744// Whenever logic/physics request a graphics operation (not just deleting a resource) that requires1745// us to flush all graphics commands, we must set frames_pending_resources_for_processing = frames.size().1746// This is important for when the user requested for the logic loop to still be updated while1747// graphics should not (e.g. headless Multiplayer servers, minimized windows that need to still1748// process something on the background).1749uint32_t frames_pending_resources_for_processing = 0u;17501751public:1752bool has_pending_resources_for_processing() const { return frames_pending_resources_for_processing != 0u; }17531754private:1755void _free_pending_resources(int p_frame);17561757uint64_t texture_memory = 0;1758uint64_t buffer_memory = 0;17591760protected:1761void execute_chained_cmds(bool p_present_swap_chain,1762RenderingDeviceDriver::FenceID p_draw_fence,1763RenderingDeviceDriver::SemaphoreID p_dst_draw_semaphore_to_signal);17641765public:1766void _free_internal(RID p_id);1767void _begin_frame(bool p_presented = false);1768void _end_frame();1769void _execute_frame(bool p_present);1770void _stall_for_frame(uint32_t p_frame);1771void _stall_for_previous_frames();1772void _flush_and_stall_for_all_frames(bool p_begin_frame = true);17731774template <typename T>1775void _free_rids(T &p_owner, const char *p_type);17761777#ifdef DEV_ENABLED1778HashMap<RID, String> resource_names;1779#endif17801781public:1782Error initialize(RenderingContextDriver *p_context, DisplayServer::WindowID p_main_window = DisplayServer::INVALID_WINDOW_ID);1783void finalize();17841785void _set_max_fps(int p_max_fps);17861787void free_rid(RID p_rid);1788#ifndef DISABLE_DEPRECATED1789[[deprecated("Use `free_rid()` instead.")]] void free(RID p_rid) {1790free_rid(p_rid);1791}1792#endif // DISABLE_DEPRECATED17931794/****************/1795/**** Timing ****/1796/****************/17971798void capture_timestamp(const String &p_name);1799uint32_t get_captured_timestamps_count() const;1800uint64_t get_captured_timestamps_frame() const;1801uint64_t get_captured_timestamp_gpu_time(uint32_t p_index) const;1802uint64_t get_captured_timestamp_cpu_time(uint32_t p_index) const;1803String get_captured_timestamp_name(uint32_t p_index) const;18041805/****************/1806/**** LIMITS ****/1807/****************/18081809uint64_t limit_get(Limit p_limit) const;18101811void swap_buffers(bool p_present);18121813uint32_t get_frame_delay() const;18141815void submit();1816void sync();18171818enum MemoryType {1819MEMORY_TEXTURES,1820MEMORY_BUFFERS,1821MEMORY_TOTAL1822};18231824uint64_t get_memory_usage(MemoryType p_type) const;18251826RenderingDevice *create_local_device();18271828void set_resource_name(RID p_id, const String &p_name);18291830void _draw_command_begin_label(String p_label_name, const Color &p_color = Color(1, 1, 1, 1));1831void draw_command_begin_label(const Span<char> p_label_name, const Color &p_color = Color(1, 1, 1, 1));1832void draw_command_end_label();18331834String get_device_vendor_name() const;1835String get_device_name() const;1836DeviceType get_device_type() const;1837String get_device_api_name() const;1838String get_device_api_version() const;1839String get_device_pipeline_cache_uuid() const;18401841uint64_t get_frames_drawn() const { return frames_drawn; }18421843bool is_composite_alpha_supported() const;18441845uint64_t get_driver_resource(DriverResource p_resource, RID p_rid = RID(), uint64_t p_index = 0);18461847String get_driver_and_device_memory_report() const;18481849String get_tracked_object_name(uint32_t p_type_index) const;1850uint64_t get_tracked_object_type_count() const;18511852uint64_t get_driver_total_memory() const;1853uint64_t get_driver_allocation_count() const;1854uint64_t get_driver_memory_by_object_type(uint32_t p_type) const;1855uint64_t get_driver_allocs_by_object_type(uint32_t p_type) const;18561857uint64_t get_device_total_memory() const;1858uint64_t get_device_allocation_count() const;1859uint64_t get_device_memory_by_object_type(uint32_t p_type) const;1860uint64_t get_device_allocs_by_object_type(uint32_t p_type) const;18611862static RenderingDevice *get_singleton();18631864void make_current();18651866RenderingDevice();1867~RenderingDevice();18681869private:1870/*****************/1871/**** BINDERS ****/1872/*****************/18731874RID _texture_create(const Ref<RDTextureFormat> &p_format, const Ref<RDTextureView> &p_view, const TypedArray<PackedByteArray> &p_data = Array());1875RID _texture_create_shared(const Ref<RDTextureView> &p_view, RID p_with_texture);1876RID _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 = 1, TextureSliceType p_slice_type = TEXTURE_SLICE_2D);1877Ref<RDTextureFormat> _texture_get_format(RID p_rd_texture);18781879FramebufferFormatID _framebuffer_format_create(const TypedArray<RDAttachmentFormat> &p_attachments, uint32_t p_view_count);1880FramebufferFormatID _framebuffer_format_create_multipass(const TypedArray<RDAttachmentFormat> &p_attachments, const TypedArray<RDFramebufferPass> &p_passes, uint32_t p_view_count);1881RID _framebuffer_create(const TypedArray<RID> &p_textures, FramebufferFormatID p_format_check = INVALID_ID, uint32_t p_view_count = 1);1882RID _framebuffer_create_multipass(const TypedArray<RID> &p_textures, const TypedArray<RDFramebufferPass> &p_passes, FramebufferFormatID p_format_check = INVALID_ID, uint32_t p_view_count = 1);18831884RID _sampler_create(const Ref<RDSamplerState> &p_state);18851886VertexFormatID _vertex_format_create(const TypedArray<RDVertexAttribute> &p_vertex_formats);1887RID _vertex_array_create(uint32_t p_vertex_count, VertexFormatID p_vertex_format, const TypedArray<RID> &p_src_buffers, const Vector<int64_t> &p_offsets = Vector<int64_t>());1888void _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 = Vector<int64_t>());18891890Ref<RDShaderSPIRV> _shader_compile_spirv_from_source(const Ref<RDShaderSource> &p_source, bool p_allow_cache = true);1891Vector<uint8_t> _shader_compile_binary_from_spirv(const Ref<RDShaderSPIRV> &p_bytecode, const String &p_shader_name = "");1892RID _shader_create_from_spirv(const Ref<RDShaderSPIRV> &p_spirv, const String &p_shader_name = "");18931894RID _uniform_set_create(const TypedArray<RDUniform> &p_uniforms, RID p_shader, uint32_t p_shader_set);18951896Error _buffer_update_bind(RID p_buffer, uint32_t p_offset, uint32_t p_size, const Vector<uint8_t> &p_data);18971898void _tlas_instances_buffer_fill(RID p_buffer, const TypedArray<RID> &p_blases, const TypedArray<Transform3D> &p_transforms);18991900RID _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);1901RID _compute_pipeline_create(RID p_shader, const TypedArray<RDPipelineSpecializationConstant> &p_specialization_constants);1902RID _raytracing_pipeline_create(RID p_shader, const TypedArray<RDPipelineSpecializationConstant> &p_specialization_constants);19031904void _draw_list_set_push_constant(DrawListID p_list, const Vector<uint8_t> &p_data, uint32_t p_data_size);1905void _compute_list_set_push_constant(ComputeListID p_list, const Vector<uint8_t> &p_data, uint32_t p_data_size);1906void _raytracing_list_set_push_constant(RaytracingListID p_list, const Vector<uint8_t> &p_data, uint32_t p_data_size);1907};19081909VARIANT_ENUM_CAST(RenderingDevice::DeviceType)1910VARIANT_ENUM_CAST(RenderingDevice::DriverResource)1911VARIANT_ENUM_CAST(RenderingDevice::ShaderStage)1912VARIANT_ENUM_CAST(RenderingDevice::ShaderLanguage)1913VARIANT_ENUM_CAST(RenderingDevice::CompareOperator)1914VARIANT_ENUM_CAST(RenderingDevice::DataFormat)1915VARIANT_ENUM_CAST(RenderingDevice::TextureType)1916VARIANT_ENUM_CAST(RenderingDevice::TextureSamples)1917VARIANT_BITFIELD_CAST(RenderingDevice::TextureUsageBits)1918VARIANT_ENUM_CAST(RenderingDevice::TextureSwizzle)1919VARIANT_ENUM_CAST(RenderingDevice::TextureSliceType)1920VARIANT_ENUM_CAST(RenderingDevice::SamplerFilter)1921VARIANT_ENUM_CAST(RenderingDevice::SamplerRepeatMode)1922VARIANT_ENUM_CAST(RenderingDevice::SamplerBorderColor)1923VARIANT_ENUM_CAST(RenderingDevice::VertexFrequency)1924VARIANT_ENUM_CAST(RenderingDevice::IndexBufferFormat)1925VARIANT_BITFIELD_CAST(RenderingDevice::StorageBufferUsage)1926VARIANT_BITFIELD_CAST(RenderingDevice::BufferCreationBits)1927VARIANT_BITFIELD_CAST(RenderingDevice::AccelerationStructureGeometryBits)1928VARIANT_ENUM_CAST(RenderingDevice::UniformType)1929VARIANT_ENUM_CAST(RenderingDevice::RenderPrimitive)1930VARIANT_ENUM_CAST(RenderingDevice::PolygonCullMode)1931VARIANT_ENUM_CAST(RenderingDevice::PolygonFrontFace)1932VARIANT_ENUM_CAST(RenderingDevice::StencilOperation)1933VARIANT_ENUM_CAST(RenderingDevice::LogicOperation)1934VARIANT_ENUM_CAST(RenderingDevice::BlendFactor)1935VARIANT_ENUM_CAST(RenderingDevice::BlendOperation)1936VARIANT_BITFIELD_CAST(RenderingDevice::PipelineDynamicStateFlags)1937VARIANT_ENUM_CAST(RenderingDevice::PipelineSpecializationConstantType)1938VARIANT_ENUM_CAST(RenderingDevice::Limit)1939VARIANT_ENUM_CAST(RenderingDevice::MemoryType)1940VARIANT_ENUM_CAST(RenderingDevice::Features)1941VARIANT_ENUM_CAST(RenderingDevice::BreadcrumbMarker)1942VARIANT_BITFIELD_CAST(RenderingDevice::DrawFlags);19431944#ifndef DISABLE_DEPRECATED1945VARIANT_BITFIELD_CAST(RenderingDevice::BarrierMask);1946VARIANT_ENUM_CAST(RenderingDevice::InitialAction)1947VARIANT_ENUM_CAST(RenderingDevice::FinalAction)1948#endif19491950typedef RenderingDevice RD;195119521953