diff options
Diffstat (limited to 'servers/rendering/renderer_rd')
61 files changed, 2691 insertions, 870 deletions
diff --git a/servers/rendering/renderer_rd/effects/SCsub b/servers/rendering/renderer_rd/effects/SCsub index 86681f9c74..8e13715447 100644 --- a/servers/rendering/renderer_rd/effects/SCsub +++ b/servers/rendering/renderer_rd/effects/SCsub @@ -2,4 +2,33 @@ Import("env") -env.add_source_files(env.servers_sources, "*.cpp") +env_effects = env.Clone() + +# Thirdparty source files + +thirdparty_obj = [] + +thirdparty_dir = "#thirdparty/amd-fsr2/" +thirdparty_sources = ["ffx_assert.cpp", "ffx_fsr2.cpp"] +thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] + +env_effects.Prepend(CPPPATH=[thirdparty_dir]) + +# This flag doesn't actually control anything GCC specific in FSR2. It determines +# if symbols should be exported, which is not required for Godot. +env_effects.Append(CPPDEFINES=["FFX_GCC"]) + +env_thirdparty = env_effects.Clone() +env_thirdparty.disable_warnings() +env_thirdparty.add_source_files(thirdparty_obj, thirdparty_sources) +env.servers_sources += thirdparty_obj + +# Godot source files + +module_obj = [] + +env_effects.add_source_files(module_obj, "*.cpp") +env.servers_sources += module_obj + +# Needed to force rebuilding the module files when the thirdparty library is updated. +env.Depends(module_obj, thirdparty_obj) diff --git a/servers/rendering/renderer_rd/effects/copy_effects.cpp b/servers/rendering/renderer_rd/effects/copy_effects.cpp index 834653f5c2..aa1a87cdd7 100644 --- a/servers/rendering/renderer_rd/effects/copy_effects.cpp +++ b/servers/rendering/renderer_rd/effects/copy_effects.cpp @@ -281,8 +281,8 @@ CopyEffects::CopyEffects(bool p_prefer_raster_effects) { ba.enable_blend = true; ba.src_color_blend_factor = RD::BLEND_FACTOR_ONE; ba.dst_color_blend_factor = RD::BLEND_FACTOR_ONE; - ba.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE; - ba.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE; + ba.src_alpha_blend_factor = RD::BLEND_FACTOR_ZERO; + ba.dst_alpha_blend_factor = RD::BLEND_FACTOR_ZERO; ba.color_blend_op = RD::BLEND_OP_ADD; ba.alpha_blend_op = RD::BLEND_OP_ADD; diff --git a/servers/rendering/renderer_rd/effects/debug_effects.cpp b/servers/rendering/renderer_rd/effects/debug_effects.cpp index 357d035ae9..abcd9bbfae 100644 --- a/servers/rendering/renderer_rd/effects/debug_effects.cpp +++ b/servers/rendering/renderer_rd/effects/debug_effects.cpp @@ -340,25 +340,38 @@ void DebugEffects::draw_shadow_frustum(RID p_light, const Projection &p_cam_proj } } -void DebugEffects::draw_motion_vectors(RID p_velocity, RID p_dest_fb, Size2i p_velocity_size) { +void DebugEffects::draw_motion_vectors(RID p_velocity, RID p_depth, RID p_dest_fb, const Projection &p_current_projection, const Transform3D &p_current_transform, const Projection &p_previous_projection, const Transform3D &p_previous_transform, Size2i p_resolution) { MaterialStorage *material_storage = MaterialStorage::get_singleton(); ERR_FAIL_NULL(material_storage); UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); ERR_FAIL_NULL(uniform_set_cache); - RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); RD::Uniform u_source_velocity(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_velocity })); + RD::Uniform u_source_depth(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 1, Vector<RID>({ default_sampler, p_depth })); RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_fb, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, motion_vectors.pipeline.get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_fb), false, RD::get_singleton()->draw_list_get_current_pass())); - motion_vectors.push_constant.velocity_resolution[0] = p_velocity_size.width; - motion_vectors.push_constant.velocity_resolution[1] = p_velocity_size.height; + Projection reprojection = p_previous_projection.flipped_y() * p_previous_transform.affine_inverse() * p_current_transform * p_current_projection.flipped_y().inverse(); + RendererRD::MaterialStorage::store_camera(reprojection, motion_vectors.push_constant.reprojection_matrix); + + motion_vectors.push_constant.resolution[0] = p_resolution.width; + motion_vectors.push_constant.resolution[1] = p_resolution.height; + motion_vectors.push_constant.force_derive_from_depth = false; RID shader = motion_vectors.shader.version_get_shader(motion_vectors.shader_version, 0); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_velocity), 0); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_velocity, u_source_depth), 0); + RD::get_singleton()->draw_list_set_push_constant(draw_list, &motion_vectors.push_constant, sizeof(MotionVectorsPushConstant)); + RD::get_singleton()->draw_list_draw(draw_list, false, 1u, 3u); + +#ifdef DRAW_DERIVATION_FROM_DEPTH_ON_TOP + motion_vectors.push_constant.force_derive_from_depth = true; + RD::get_singleton()->draw_list_set_push_constant(draw_list, &motion_vectors.push_constant, sizeof(MotionVectorsPushConstant)); RD::get_singleton()->draw_list_draw(draw_list, false, 1u, 3u); +#endif + RD::get_singleton()->draw_list_end(); } diff --git a/servers/rendering/renderer_rd/effects/debug_effects.h b/servers/rendering/renderer_rd/effects/debug_effects.h index ae32d94912..b813d577e4 100644 --- a/servers/rendering/renderer_rd/effects/debug_effects.h +++ b/servers/rendering/renderer_rd/effects/debug_effects.h @@ -72,8 +72,10 @@ private: } shadow_frustum; struct MotionVectorsPushConstant { - float velocity_resolution[2]; - float pad[2]; + float reprojection_matrix[16]; + float resolution[2]; + uint32_t force_derive_from_depth; + float pad; }; struct { @@ -91,7 +93,7 @@ public: ~DebugEffects(); void draw_shadow_frustum(RID p_light, const Projection &p_cam_projection, const Transform3D &p_cam_transform, RID p_dest_fb, const Rect2 p_rect); - void draw_motion_vectors(RID p_velocity, RID p_dest_fb, Size2i p_velocity_size); + void draw_motion_vectors(RID p_velocity, RID p_depth, RID p_dest_fb, const Projection &p_current_projection, const Transform3D &p_current_transform, const Projection &p_previous_projection, const Transform3D &p_previous_transform, Size2i p_resolution); }; } // namespace RendererRD diff --git a/servers/rendering/renderer_rd/effects/fsr2.cpp b/servers/rendering/renderer_rd/effects/fsr2.cpp new file mode 100644 index 0000000000..0c38989304 --- /dev/null +++ b/servers/rendering/renderer_rd/effects/fsr2.cpp @@ -0,0 +1,891 @@ +/**************************************************************************/ +/* fsr2.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "fsr2.h" + +#include "../storage_rd/material_storage.h" +#include "../uniform_set_cache_rd.h" + +using namespace RendererRD; + +#ifndef _MSC_VER +#include <wchar.h> +#define wcscpy_s wcscpy +#endif + +static RD::TextureType ffx_resource_type_to_rd_texture_type(FfxResourceType p_type) { + switch (p_type) { + case FFX_RESOURCE_TYPE_TEXTURE1D: + return RD::TEXTURE_TYPE_1D; + case FFX_RESOURCE_TYPE_TEXTURE2D: + return RD::TEXTURE_TYPE_2D; + case FFX_RESOURCE_TYPE_TEXTURE3D: + return RD::TEXTURE_TYPE_3D; + default: + return RD::TEXTURE_TYPE_MAX; + } +} + +static FfxResourceType rd_texture_type_to_ffx_resource_type(RD::TextureType p_type) { + switch (p_type) { + case RD::TEXTURE_TYPE_1D: + return FFX_RESOURCE_TYPE_TEXTURE1D; + case RD::TEXTURE_TYPE_2D: + return FFX_RESOURCE_TYPE_TEXTURE2D; + case RD::TEXTURE_TYPE_3D: + return FFX_RESOURCE_TYPE_TEXTURE3D; + default: + return FFX_RESOURCE_TYPE_BUFFER; + } +} + +static RD::DataFormat ffx_surface_format_to_rd_format(FfxSurfaceFormat p_format) { + switch (p_format) { + case FFX_SURFACE_FORMAT_R32G32B32A32_TYPELESS: + return RD::DATA_FORMAT_R32G32B32A32_SFLOAT; + case FFX_SURFACE_FORMAT_R32G32B32A32_FLOAT: + return RD::DATA_FORMAT_R32G32B32A32_SFLOAT; + case FFX_SURFACE_FORMAT_R16G16B16A16_FLOAT: + return RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + case FFX_SURFACE_FORMAT_R16G16B16A16_UNORM: + return RD::DATA_FORMAT_R16G16B16A16_UNORM; + case FFX_SURFACE_FORMAT_R32G32_FLOAT: + return RD::DATA_FORMAT_R32G32_SFLOAT; + case FFX_SURFACE_FORMAT_R32_UINT: + return RD::DATA_FORMAT_R32_UINT; + case FFX_SURFACE_FORMAT_R8G8B8A8_TYPELESS: + return RD::DATA_FORMAT_R8G8B8A8_UNORM; + case FFX_SURFACE_FORMAT_R8G8B8A8_UNORM: + return RD::DATA_FORMAT_R8G8B8A8_UNORM; + case FFX_SURFACE_FORMAT_R11G11B10_FLOAT: + return RD::DATA_FORMAT_B10G11R11_UFLOAT_PACK32; + case FFX_SURFACE_FORMAT_R16G16_FLOAT: + return RD::DATA_FORMAT_R16G16_SFLOAT; + case FFX_SURFACE_FORMAT_R16G16_UINT: + return RD::DATA_FORMAT_R16G16_UINT; + case FFX_SURFACE_FORMAT_R16_FLOAT: + return RD::DATA_FORMAT_R16_SFLOAT; + case FFX_SURFACE_FORMAT_R16_UINT: + return RD::DATA_FORMAT_R16_UINT; + case FFX_SURFACE_FORMAT_R16_UNORM: + return RD::DATA_FORMAT_R16_UNORM; + case FFX_SURFACE_FORMAT_R16_SNORM: + return RD::DATA_FORMAT_R16_SNORM; + case FFX_SURFACE_FORMAT_R8_UNORM: + return RD::DATA_FORMAT_R8_UNORM; + case FFX_SURFACE_FORMAT_R8_UINT: + return RD::DATA_FORMAT_R8_UINT; + case FFX_SURFACE_FORMAT_R8G8_UNORM: + return RD::DATA_FORMAT_R8G8_UNORM; + case FFX_SURFACE_FORMAT_R32_FLOAT: + return RD::DATA_FORMAT_R32_SFLOAT; + default: + return RD::DATA_FORMAT_MAX; + } +} + +static FfxSurfaceFormat rd_format_to_ffx_surface_format(RD::DataFormat p_format) { + switch (p_format) { + case RD::DATA_FORMAT_R32G32B32A32_SFLOAT: + return FFX_SURFACE_FORMAT_R32G32B32A32_FLOAT; + case RD::DATA_FORMAT_R16G16B16A16_SFLOAT: + return FFX_SURFACE_FORMAT_R16G16B16A16_FLOAT; + case RD::DATA_FORMAT_R16G16B16A16_UNORM: + return FFX_SURFACE_FORMAT_R16G16B16A16_UNORM; + case RD::DATA_FORMAT_R32G32_SFLOAT: + return FFX_SURFACE_FORMAT_R32G32_FLOAT; + case RD::DATA_FORMAT_R32_UINT: + return FFX_SURFACE_FORMAT_R32_UINT; + case RD::DATA_FORMAT_R8G8B8A8_UNORM: + return FFX_SURFACE_FORMAT_R8G8B8A8_UNORM; + case RD::DATA_FORMAT_B10G11R11_UFLOAT_PACK32: + return FFX_SURFACE_FORMAT_R11G11B10_FLOAT; + case RD::DATA_FORMAT_R16G16_SFLOAT: + return FFX_SURFACE_FORMAT_R16G16_FLOAT; + case RD::DATA_FORMAT_R16G16_UINT: + return FFX_SURFACE_FORMAT_R16G16_UINT; + case RD::DATA_FORMAT_R16_SFLOAT: + return FFX_SURFACE_FORMAT_R16_FLOAT; + case RD::DATA_FORMAT_R16_UINT: + return FFX_SURFACE_FORMAT_R16_UINT; + case RD::DATA_FORMAT_R16_UNORM: + return FFX_SURFACE_FORMAT_R16_UNORM; + case RD::DATA_FORMAT_R16_SNORM: + return FFX_SURFACE_FORMAT_R16_SNORM; + case RD::DATA_FORMAT_R8_UNORM: + return FFX_SURFACE_FORMAT_R8_UNORM; + case RD::DATA_FORMAT_R8_UINT: + return FFX_SURFACE_FORMAT_R8_UINT; + case RD::DATA_FORMAT_R8G8_UNORM: + return FFX_SURFACE_FORMAT_R8G8_UNORM; + case RD::DATA_FORMAT_R32_SFLOAT: + return FFX_SURFACE_FORMAT_R32_FLOAT; + default: + return FFX_SURFACE_FORMAT_UNKNOWN; + } +} + +static uint32_t ffx_usage_to_rd_usage_flags(uint32_t p_flags) { + uint32_t ret = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; + + if (p_flags & FFX_RESOURCE_USAGE_RENDERTARGET) { + ret |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + } + + if (p_flags & FFX_RESOURCE_USAGE_UAV) { + ret |= RD::TEXTURE_USAGE_STORAGE_BIT; + ret |= RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; + ret |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; + } + + return ret; +} + +static FfxErrorCode create_backend_context_rd(FfxFsr2Interface *p_backend_interface, FfxDevice p_device) { + FSR2Context::Scratch &scratch = *reinterpret_cast<FSR2Context::Scratch *>(p_backend_interface->scratchBuffer); + + // Store pointer to the device common to all contexts. + scratch.device = p_device; + + // Create a ring buffer of uniform buffers. + // FIXME: This could be optimized to be a single memory block if it was possible for RD to create views into a particular memory range of a UBO. + for (uint32_t i = 0; i < FSR2_UBO_RING_BUFFER_SIZE; i++) { + scratch.ubo_ring_buffer[i] = RD::get_singleton()->uniform_buffer_create(FFX_MAX_CONST_SIZE * sizeof(uint32_t)); + ERR_FAIL_COND_V(scratch.ubo_ring_buffer[i].is_null(), FFX_ERROR_BACKEND_API_ERROR); + } + + return FFX_OK; +} + +static FfxErrorCode get_device_capabilities_rd(FfxFsr2Interface *p_backend_interface, FfxDeviceCapabilities *p_out_device_capabilities, FfxDevice p_device) { + FSR2Effect::Device &effect_device = *reinterpret_cast<FSR2Effect::Device *>(p_device); + + *p_out_device_capabilities = effect_device.capabilities; + + return FFX_OK; +} + +static FfxErrorCode destroy_backend_context_rd(FfxFsr2Interface *p_backend_interface) { + FSR2Context::Scratch &scratch = *reinterpret_cast<FSR2Context::Scratch *>(p_backend_interface->scratchBuffer); + + for (uint32_t i = 0; i < FSR2_UBO_RING_BUFFER_SIZE; i++) { + RD::get_singleton()->free(scratch.ubo_ring_buffer[i]); + } + + return FFX_OK; +} + +static FfxErrorCode create_resource_rd(FfxFsr2Interface *p_backend_interface, const FfxCreateResourceDescription *p_create_resource_description, FfxResourceInternal *p_out_resource) { + // FSR2's base implementation won't issue a call to create a heap type that isn't just default on its own, + // so we can safely ignore it as RD does not expose this concept. + ERR_FAIL_COND_V(p_create_resource_description->heapType != FFX_HEAP_TYPE_DEFAULT, FFX_ERROR_INVALID_ARGUMENT); + + RenderingDevice *rd = RD::get_singleton(); + FSR2Context::Scratch &scratch = *reinterpret_cast<FSR2Context::Scratch *>(p_backend_interface->scratchBuffer); + FfxResourceDescription res_desc = p_create_resource_description->resourceDescription; + + // FSR2's base implementation never requests buffer creation. + ERR_FAIL_COND_V(res_desc.type != FFX_RESOURCE_TYPE_TEXTURE1D && res_desc.type != FFX_RESOURCE_TYPE_TEXTURE2D && res_desc.type != FFX_RESOURCE_TYPE_TEXTURE3D, FFX_ERROR_INVALID_ARGUMENT); + + if (res_desc.mipCount == 0) { + // Mipmap count must be derived from the resource's dimensions. + res_desc.mipCount = uint32_t(1 + floor(log2(MAX(MAX(res_desc.width, res_desc.height), res_desc.depth)))); + } + + Vector<PackedByteArray> initial_data; + if (p_create_resource_description->initDataSize) { + PackedByteArray byte_array; + byte_array.resize(p_create_resource_description->initDataSize); + memcpy(byte_array.ptrw(), p_create_resource_description->initData, p_create_resource_description->initDataSize); + initial_data.push_back(byte_array); + } + + RD::TextureFormat texture_format; + texture_format.texture_type = ffx_resource_type_to_rd_texture_type(res_desc.type); + texture_format.format = ffx_surface_format_to_rd_format(res_desc.format); + texture_format.usage_bits = ffx_usage_to_rd_usage_flags(p_create_resource_description->usage); + texture_format.width = res_desc.width; + texture_format.height = res_desc.height; + texture_format.depth = res_desc.depth; + texture_format.mipmaps = res_desc.mipCount; + + RID texture = rd->texture_create(texture_format, RD::TextureView(), initial_data); + ERR_FAIL_COND_V(texture.is_null(), FFX_ERROR_BACKEND_API_ERROR); + + rd->set_resource_name(texture, String(p_create_resource_description->name)); + + // Add the resource to the storage and use the internal index to reference it. + p_out_resource->internalIndex = scratch.resources.add(texture, false, p_create_resource_description->id, res_desc); + + return FFX_OK; +} + +static FfxErrorCode register_resource_rd(FfxFsr2Interface *p_backend_interface, const FfxResource *p_in_resource, FfxResourceInternal *p_out_resource) { + if (p_in_resource->resource == nullptr) { + // Null resource case. + p_out_resource->internalIndex = -1; + return FFX_OK; + } + + FSR2Context::Scratch &scratch = *reinterpret_cast<FSR2Context::Scratch *>(p_backend_interface->scratchBuffer); + const RID &rid = *reinterpret_cast<const RID *>(p_in_resource->resource); + ERR_FAIL_COND_V(rid.is_null(), FFX_ERROR_INVALID_ARGUMENT); + + // Add the resource to the storage and use the internal index to reference it. + p_out_resource->internalIndex = scratch.resources.add(rid, true, FSR2Context::RESOURCE_ID_DYNAMIC, p_in_resource->description); + + return FFX_OK; +} + +static FfxErrorCode unregister_resources_rd(FfxFsr2Interface *p_backend_interface) { + FSR2Context::Scratch &scratch = *reinterpret_cast<FSR2Context::Scratch *>(p_backend_interface->scratchBuffer); + LocalVector<uint32_t> dynamic_list_copy = scratch.resources.dynamic_list; + for (uint32_t i : dynamic_list_copy) { + scratch.resources.remove(i); + } + + return FFX_OK; +} + +static FfxResourceDescription get_resource_description_rd(FfxFsr2Interface *p_backend_interface, FfxResourceInternal p_resource) { + if (p_resource.internalIndex != -1) { + FSR2Context::Scratch &scratch = *reinterpret_cast<FSR2Context::Scratch *>(p_backend_interface->scratchBuffer); + return scratch.resources.descriptions[p_resource.internalIndex]; + } else { + return {}; + } +} + +static FfxErrorCode destroy_resource_rd(FfxFsr2Interface *p_backend_interface, FfxResourceInternal p_resource) { + if (p_resource.internalIndex != -1) { + FSR2Context::Scratch &scratch = *reinterpret_cast<FSR2Context::Scratch *>(p_backend_interface->scratchBuffer); + if (scratch.resources.rids[p_resource.internalIndex].is_valid()) { + RD::get_singleton()->free(scratch.resources.rids[p_resource.internalIndex]); + scratch.resources.remove(p_resource.internalIndex); + } + } + + return FFX_OK; +} + +static FfxErrorCode create_pipeline_rd(FfxFsr2Interface *p_backend_interface, FfxFsr2Pass p_pass, const FfxPipelineDescription *p_pipeline_description, FfxPipelineState *p_out_pipeline) { + FSR2Context::Scratch &scratch = *reinterpret_cast<FSR2Context::Scratch *>(p_backend_interface->scratchBuffer); + FSR2Effect::Device &device = *reinterpret_cast<FSR2Effect::Device *>(scratch.device); + FSR2Effect::Pass &effect_pass = device.passes[p_pass]; + + if (effect_pass.pipeline.pipeline_rid.is_null()) { + // Create pipeline for the device if it hasn't been created yet. + effect_pass.root_signature.shader_rid = effect_pass.shader->version_get_shader(effect_pass.shader_version, effect_pass.shader_variant); + ERR_FAIL_COND_V(effect_pass.root_signature.shader_rid.is_null(), FFX_ERROR_BACKEND_API_ERROR); + + effect_pass.pipeline.pipeline_rid = RD::get_singleton()->compute_pipeline_create(effect_pass.root_signature.shader_rid); + ERR_FAIL_COND_V(effect_pass.pipeline.pipeline_rid.is_null(), FFX_ERROR_BACKEND_API_ERROR); + } + + // While this is not their intended use, we use the pipeline and root signature pointers to store the + // RIDs to the pipeline and shader that RD needs for the compute pipeline. + p_out_pipeline->pipeline = reinterpret_cast<FfxPipeline>(&effect_pass.pipeline); + p_out_pipeline->rootSignature = reinterpret_cast<FfxRootSignature>(&effect_pass.root_signature); + + p_out_pipeline->srvCount = effect_pass.sampled_bindings.size(); + ERR_FAIL_COND_V(p_out_pipeline->srvCount > FFX_MAX_NUM_SRVS, FFX_ERROR_OUT_OF_RANGE); + memcpy(p_out_pipeline->srvResourceBindings, effect_pass.sampled_bindings.ptr(), sizeof(FfxResourceBinding) * p_out_pipeline->srvCount); + + p_out_pipeline->uavCount = effect_pass.storage_bindings.size(); + ERR_FAIL_COND_V(p_out_pipeline->uavCount > FFX_MAX_NUM_UAVS, FFX_ERROR_OUT_OF_RANGE); + memcpy(p_out_pipeline->uavResourceBindings, effect_pass.storage_bindings.ptr(), sizeof(FfxResourceBinding) * p_out_pipeline->uavCount); + + p_out_pipeline->constCount = effect_pass.uniform_bindings.size(); + ERR_FAIL_COND_V(p_out_pipeline->constCount > FFX_MAX_NUM_CONST_BUFFERS, FFX_ERROR_OUT_OF_RANGE); + memcpy(p_out_pipeline->cbResourceBindings, effect_pass.uniform_bindings.ptr(), sizeof(FfxResourceBinding) * p_out_pipeline->constCount); + + bool low_resolution_mvs = (p_pipeline_description->contextFlags & FFX_FSR2_ENABLE_DISPLAY_RESOLUTION_MOTION_VECTORS) == 0; + + if (p_pass == FFX_FSR2_PASS_ACCUMULATE || p_pass == FFX_FSR2_PASS_ACCUMULATE_SHARPEN) { + // Change the binding for motion vectors in this particular pass if low resolution MVs are used. + if (low_resolution_mvs) { + FfxResourceBinding &binding = p_out_pipeline->srvResourceBindings[2]; + wcscpy_s(binding.name, L"r_dilated_motion_vectors"); + } + } + + return FFX_OK; +} + +static FfxErrorCode destroy_pipeline_rd(FfxFsr2Interface *p_backend_interface, FfxPipelineState *p_pipeline) { + // We don't want to destroy pipelines when the FSR2 API deems it necessary as it'll do so whenever the context is destroyed. + + return FFX_OK; +} + +static FfxErrorCode schedule_gpu_job_rd(FfxFsr2Interface *p_backend_interface, const FfxGpuJobDescription *p_job) { + ERR_FAIL_NULL_V(p_backend_interface, FFX_ERROR_INVALID_ARGUMENT); + ERR_FAIL_NULL_V(p_job, FFX_ERROR_INVALID_ARGUMENT); + + FSR2Context::Scratch &scratch = *reinterpret_cast<FSR2Context::Scratch *>(p_backend_interface->scratchBuffer); + scratch.gpu_jobs.push_back(*p_job); + + return FFX_OK; +} + +static FfxErrorCode execute_gpu_job_clear_float_rd(FSR2Context::Scratch &p_scratch, const FfxClearFloatJobDescription &p_job) { + RID resource = p_scratch.resources.rids[p_job.target.internalIndex]; + FfxResourceDescription &desc = p_scratch.resources.descriptions[p_job.target.internalIndex]; + + ERR_FAIL_COND_V(desc.type == FFX_RESOURCE_TYPE_BUFFER, FFX_ERROR_INVALID_ARGUMENT); + + Color color(p_job.color[0], p_job.color[1], p_job.color[2], p_job.color[3]); + RD::get_singleton()->texture_clear(resource, color, 0, desc.mipCount, 0, 1); + + return FFX_OK; +} + +static FfxErrorCode execute_gpu_job_copy_rd(FSR2Context::Scratch &p_scratch, const FfxCopyJobDescription &p_job) { + RID src = p_scratch.resources.rids[p_job.src.internalIndex]; + RID dst = p_scratch.resources.rids[p_job.dst.internalIndex]; + FfxResourceDescription &src_desc = p_scratch.resources.descriptions[p_job.src.internalIndex]; + FfxResourceDescription &dst_desc = p_scratch.resources.descriptions[p_job.dst.internalIndex]; + + ERR_FAIL_COND_V(src_desc.type == FFX_RESOURCE_TYPE_BUFFER, FFX_ERROR_INVALID_ARGUMENT); + ERR_FAIL_COND_V(dst_desc.type == FFX_RESOURCE_TYPE_BUFFER, FFX_ERROR_INVALID_ARGUMENT); + + for (uint32_t mip_level = 0; mip_level < src_desc.mipCount; mip_level++) { + // Only push the barriers on the last copy. + // FIXME: This could be optimized if RenderingDevice was able to copy multiple mip levels in a single command. + BitField<RD::BarrierMask> post_barrier = (mip_level == (src_desc.mipCount - 1)) ? RD::BARRIER_MASK_ALL_BARRIERS : RD::BARRIER_MASK_NO_BARRIER; + RD::get_singleton()->texture_copy(src, dst, Vector3(0, 0, 0), Vector3(0, 0, 0), Vector3(src_desc.width, src_desc.height, src_desc.depth), mip_level, mip_level, 0, 0, post_barrier); + } + + return FFX_OK; +} + +static FfxErrorCode execute_gpu_job_compute_rd(FSR2Context::Scratch &p_scratch, const FfxComputeJobDescription &p_job) { + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL_V(uniform_set_cache, FFX_ERROR_BACKEND_API_ERROR); + + FSR2Effect::RootSignature &root_signature = *reinterpret_cast<FSR2Effect::RootSignature *>(p_job.pipeline.rootSignature); + ERR_FAIL_COND_V(root_signature.shader_rid.is_null(), FFX_ERROR_INVALID_ARGUMENT); + + FSR2Effect::Pipeline &backend_pipeline = *reinterpret_cast<FSR2Effect::Pipeline *>(p_job.pipeline.pipeline); + ERR_FAIL_COND_V(backend_pipeline.pipeline_rid.is_null(), FFX_ERROR_INVALID_ARGUMENT); + + Vector<RD::Uniform> compute_uniforms; + for (uint32_t i = 0; i < p_job.pipeline.srvCount; i++) { + RID texture_rid = p_scratch.resources.rids[p_job.srvs[i].internalIndex]; + RD::Uniform texture_uniform(RD::UNIFORM_TYPE_TEXTURE, p_job.pipeline.srvResourceBindings[i].slotIndex, texture_rid); + compute_uniforms.push_back(texture_uniform); + } + + for (uint32_t i = 0; i < p_job.pipeline.uavCount; i++) { + RID image_rid = p_scratch.resources.rids[p_job.uavs[i].internalIndex]; + RD::Uniform storage_uniform; + storage_uniform.uniform_type = RD::UNIFORM_TYPE_IMAGE; + storage_uniform.binding = p_job.pipeline.uavResourceBindings[i].slotIndex; + + if (p_job.uavMip[i] > 0) { + LocalVector<RID> &mip_slice_rids = p_scratch.resources.mip_slice_rids[p_job.uavs[i].internalIndex]; + if (mip_slice_rids.is_empty()) { + mip_slice_rids.resize(p_scratch.resources.descriptions[p_job.uavs[i].internalIndex].mipCount); + } + + ERR_FAIL_COND_V(p_job.uavMip[i] >= mip_slice_rids.size(), FFX_ERROR_INVALID_ARGUMENT); + + if (mip_slice_rids[p_job.uavMip[i]].is_null()) { + mip_slice_rids[p_job.uavMip[i]] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), image_rid, 0, p_job.uavMip[i]); + } + + ERR_FAIL_COND_V(mip_slice_rids[p_job.uavMip[i]].is_null(), FFX_ERROR_BACKEND_API_ERROR); + + storage_uniform.append_id(mip_slice_rids[p_job.uavMip[i]]); + } else { + storage_uniform.append_id(image_rid); + } + + compute_uniforms.push_back(storage_uniform); + } + + for (uint32_t i = 0; i < p_job.pipeline.constCount; i++) { + RID buffer_rid = p_scratch.ubo_ring_buffer[p_scratch.ubo_ring_buffer_index]; + p_scratch.ubo_ring_buffer_index = (p_scratch.ubo_ring_buffer_index + 1) % FSR2_UBO_RING_BUFFER_SIZE; + + BitField<RD::BarrierMask> post_barrier = (i == (p_job.pipeline.constCount - 1)) ? RD::BARRIER_MASK_ALL_BARRIERS : RD::BARRIER_MASK_NO_BARRIER; + RD::get_singleton()->buffer_update(buffer_rid, 0, p_job.cbs[i].uint32Size * sizeof(uint32_t), p_job.cbs[i].data, post_barrier); + + RD::Uniform buffer_uniform(RD::UNIFORM_TYPE_UNIFORM_BUFFER, p_job.pipeline.cbResourceBindings[i].slotIndex, buffer_rid); + compute_uniforms.push_back(buffer_uniform); + } + + FSR2Effect::Device &device = *reinterpret_cast<FSR2Effect::Device *>(p_scratch.device); + RD::Uniform u_point_clamp_sampler(RD::UniformType::UNIFORM_TYPE_SAMPLER, 0, device.point_clamp_sampler); + RD::Uniform u_linear_clamp_sampler(RD::UniformType::UNIFORM_TYPE_SAMPLER, 1, device.linear_clamp_sampler); + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, backend_pipeline.pipeline_rid); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(root_signature.shader_rid, 0, u_point_clamp_sampler, u_linear_clamp_sampler), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache_vec(root_signature.shader_rid, 1, compute_uniforms), 1); + RD::get_singleton()->compute_list_dispatch(compute_list, p_job.dimensions[0], p_job.dimensions[1], p_job.dimensions[2]); + RD::get_singleton()->compute_list_end(); + + return FFX_OK; +} + +static FfxErrorCode execute_gpu_jobs_rd(FfxFsr2Interface *p_backend_interface, FfxCommandList p_command_list) { + ERR_FAIL_NULL_V(p_backend_interface, FFX_ERROR_INVALID_ARGUMENT); + + FSR2Context::Scratch &scratch = *reinterpret_cast<FSR2Context::Scratch *>(p_backend_interface->scratchBuffer); + FfxErrorCode error_code = FFX_OK; + for (const FfxGpuJobDescription &job : scratch.gpu_jobs) { + switch (job.jobType) { + case FFX_GPU_JOB_CLEAR_FLOAT: { + error_code = execute_gpu_job_clear_float_rd(scratch, job.clearJobDescriptor); + } break; + case FFX_GPU_JOB_COPY: { + error_code = execute_gpu_job_copy_rd(scratch, job.copyJobDescriptor); + } break; + case FFX_GPU_JOB_COMPUTE: { + error_code = execute_gpu_job_compute_rd(scratch, job.computeJobDescriptor); + } break; + default: { + error_code = FFX_ERROR_INVALID_ARGUMENT; + } break; + } + + if (error_code != FFX_OK) { + scratch.gpu_jobs.clear(); + return error_code; + } + } + + scratch.gpu_jobs.clear(); + + return FFX_OK; +} + +static FfxResource get_resource_rd(RID *p_rid, const wchar_t *p_name) { + FfxResource res = {}; + if (p_rid->is_null()) { + return res; + } + + wcscpy_s(res.name, p_name); + + RD::TextureFormat texture_format = RD::get_singleton()->texture_get_format(*p_rid); + res.description.type = rd_texture_type_to_ffx_resource_type(texture_format.texture_type); + res.description.format = rd_format_to_ffx_surface_format(texture_format.format); + res.description.width = texture_format.width; + res.description.height = texture_format.height; + res.description.depth = texture_format.depth; + res.description.mipCount = texture_format.mipmaps; + res.description.flags = FFX_RESOURCE_FLAGS_NONE; + res.resource = reinterpret_cast<void *>(p_rid); + res.isDepth = texture_format.usage_bits & RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + + return res; +} + +FSR2Context::~FSR2Context() { + ffxFsr2ContextDestroy(&fsr_context); +} + +FSR2Effect::FSR2Effect() { + FfxDeviceCapabilities &capabilities = device.capabilities; + uint64_t default_subgroup_size = RD::get_singleton()->limit_get(RD::LIMIT_SUBGROUP_SIZE); + capabilities.minimumSupportedShaderModel = FFX_SHADER_MODEL_5_1; + capabilities.waveLaneCountMin = RD::get_singleton()->limit_get(RD::LIMIT_SUBGROUP_MIN_SIZE); + capabilities.waveLaneCountMax = RD::get_singleton()->limit_get(RD::LIMIT_SUBGROUP_MAX_SIZE); + capabilities.fp16Supported = RD::get_singleton()->has_feature(RD::Features::SUPPORTS_FSR_HALF_FLOAT); + capabilities.raytracingSupported = false; + + bool force_wave_64 = default_subgroup_size == 32 && capabilities.waveLaneCountMax == 64; + bool use_lut = force_wave_64 || default_subgroup_size == 64; + + String general_defines_base = + "\n#define FFX_GPU\n" + "\n#define FFX_GLSL 1\n" + "\n#define FFX_FSR2_OPTION_LOW_RESOLUTION_MOTION_VECTORS 1\n" + "\n#define FFX_FSR2_OPTION_HDR_COLOR_INPUT 1\n" + "\n#define FFX_FSR2_OPTION_GODOT_REACTIVE_MASK_CLAMP 1\n" + "\n#define FFX_FSR2_OPTION_GODOT_DERIVE_INVALID_MOTION_VECTORS 1\n"; + + if (use_lut) { + general_defines_base += "\n#define FFX_FSR2_OPTION_REPROJECT_USE_LANCZOS_TYPE 1\n"; + } + + String general_defines = general_defines_base; + if (capabilities.fp16Supported) { + general_defines += "\n#define FFX_HALF 1\n"; + } + + Vector<String> modes; + modes.push_back(""); + + // Since Godot currently lacks a shader reflection mechanism to persist the name of the bindings in the shader cache and + // there's also no mechanism to compile the shaders offline, the bindings are created manually by looking at the GLSL + // files included in FSR2 and mapping the macro bindings (#define FSR2_BIND_*) to their respective implementation names. + // + // It is not guaranteed these will remain consistent at all between versions of FSR2, so it'll be necessary to keep these + // bindings up to date whenever the library is updated. In such cases, it is very likely the validation layer will throw an + // error if the bindings do not match. + + { + Pass &pass = device.passes[FFX_FSR2_PASS_DEPTH_CLIP]; + pass.shader = &shaders.depth_clip; + pass.shader->initialize(modes, general_defines); + pass.shader_version = pass.shader->version_create(); + + pass.sampled_bindings = { + FfxResourceBinding{ 0, 0, L"r_reconstructed_previous_nearest_depth" }, + FfxResourceBinding{ 1, 0, L"r_dilated_motion_vectors" }, + FfxResourceBinding{ 2, 0, L"r_dilatedDepth" }, + FfxResourceBinding{ 3, 0, L"r_reactive_mask" }, + FfxResourceBinding{ 4, 0, L"r_transparency_and_composition_mask" }, + FfxResourceBinding{ 5, 0, L"r_prepared_input_color" }, + FfxResourceBinding{ 6, 0, L"r_previous_dilated_motion_vectors" }, + FfxResourceBinding{ 7, 0, L"r_input_motion_vectors" }, + FfxResourceBinding{ 8, 0, L"r_input_color_jittered" }, + FfxResourceBinding{ 9, 0, L"r_input_depth" }, + FfxResourceBinding{ 10, 0, L"r_input_exposure" } + }; + + pass.storage_bindings = { + // FSR2_BIND_UAV_DEPTH_CLIP (11) does not point to anything. + FfxResourceBinding{ 12, 0, L"rw_dilated_reactive_masks" }, + FfxResourceBinding{ 13, 0, L"rw_prepared_input_color" } + }; + + pass.uniform_bindings = { + FfxResourceBinding{ 14, 0, L"cbFSR2" } + }; + } + + { + Pass &pass = device.passes[FFX_FSR2_PASS_RECONSTRUCT_PREVIOUS_DEPTH]; + pass.shader = &shaders.reconstruct_previous_depth; + pass.shader->initialize(modes, general_defines); + pass.shader_version = pass.shader->version_create(); + + pass.sampled_bindings = { + FfxResourceBinding{ 0, 0, L"r_input_motion_vectors" }, + FfxResourceBinding{ 1, 0, L"r_input_depth" }, + FfxResourceBinding{ 2, 0, L"r_input_color_jittered" }, + FfxResourceBinding{ 3, 0, L"r_input_exposure" }, + FfxResourceBinding{ 4, 0, L"r_luma_history" } + }; + + pass.storage_bindings = { + FfxResourceBinding{ 5, 0, L"rw_reconstructed_previous_nearest_depth" }, + FfxResourceBinding{ 6, 0, L"rw_dilated_motion_vectors" }, + FfxResourceBinding{ 7, 0, L"rw_dilatedDepth" }, + FfxResourceBinding{ 8, 0, L"rw_prepared_input_color" }, + FfxResourceBinding{ 9, 0, L"rw_luma_history" }, + // FSR2_BIND_UAV_LUMA_INSTABILITY (10) does not point to anything. + FfxResourceBinding{ 11, 0, L"rw_lock_input_luma" } + }; + + pass.uniform_bindings = { + FfxResourceBinding{ 12, 0, L"cbFSR2" } + }; + } + + { + Pass &pass = device.passes[FFX_FSR2_PASS_LOCK]; + pass.shader = &shaders.lock; + pass.shader->initialize(modes, general_defines); + pass.shader_version = pass.shader->version_create(); + + pass.sampled_bindings = { + FfxResourceBinding{ 0, 0, L"r_lock_input_luma" } + }; + + pass.storage_bindings = { + FfxResourceBinding{ 1, 0, L"rw_new_locks" }, + FfxResourceBinding{ 2, 0, L"rw_reconstructed_previous_nearest_depth" } + }; + + pass.uniform_bindings = { + FfxResourceBinding{ 3, 0, L"cbFSR2" } + }; + } + + { + Vector<String> accumulate_modes; + accumulate_modes.push_back("\n"); + accumulate_modes.push_back("\n#define FFX_FSR2_OPTION_APPLY_SHARPENING 1\n"); + + String general_defines_accumulate; + if (RD::get_singleton()->get_device_vendor_name() == "NVIDIA") { + // Workaround: Disable FP16 path for the accumulate pass on NVIDIA due to reduced occupancy and high VRAM throughput. + general_defines_accumulate = general_defines_base; + } else { + general_defines_accumulate = general_defines; + } + + Pass &pass = device.passes[FFX_FSR2_PASS_ACCUMULATE]; + pass.shader = &shaders.accumulate; + pass.shader->initialize(accumulate_modes, general_defines_accumulate); + pass.shader_version = pass.shader->version_create(); + + pass.sampled_bindings = { + FfxResourceBinding{ 0, 0, L"r_input_exposure" }, + FfxResourceBinding{ 1, 0, L"r_dilated_reactive_masks" }, + FfxResourceBinding{ 2, 0, L"r_input_motion_vectors" }, + FfxResourceBinding{ 3, 0, L"r_internal_upscaled_color" }, + FfxResourceBinding{ 4, 0, L"r_lock_status" }, + FfxResourceBinding{ 5, 0, L"r_input_depth" }, + FfxResourceBinding{ 6, 0, L"r_prepared_input_color" }, + // FSR2_BIND_SRV_LUMA_INSTABILITY(7) does not point to anything. + FfxResourceBinding{ 8, 0, L"r_lanczos_lut" }, + FfxResourceBinding{ 9, 0, L"r_upsample_maximum_bias_lut" }, + FfxResourceBinding{ 10, 0, L"r_imgMips" }, + FfxResourceBinding{ 11, 0, L"r_auto_exposure" }, + FfxResourceBinding{ 12, 0, L"r_luma_history" } + }; + + pass.storage_bindings = { + FfxResourceBinding{ 13, 0, L"rw_internal_upscaled_color" }, + FfxResourceBinding{ 14, 0, L"rw_lock_status" }, + FfxResourceBinding{ 15, 0, L"rw_upscaled_output" }, + FfxResourceBinding{ 16, 0, L"rw_new_locks" }, + FfxResourceBinding{ 17, 0, L"rw_luma_history" } + }; + + pass.uniform_bindings = { + FfxResourceBinding{ 18, 0, L"cbFSR2" } + }; + + // Sharpen pass is a clone of the accumulate pass. + Pass &sharpen_pass = device.passes[FFX_FSR2_PASS_ACCUMULATE_SHARPEN]; + sharpen_pass = pass; + sharpen_pass.shader_variant = 1; + } + + { + Pass &pass = device.passes[FFX_FSR2_PASS_RCAS]; + pass.shader = &shaders.rcas; + pass.shader->initialize(modes, general_defines_base); + pass.shader_version = pass.shader->version_create(); + + pass.sampled_bindings = { + FfxResourceBinding{ 0, 0, L"r_input_exposure" }, + FfxResourceBinding{ 1, 0, L"r_rcas_input" } + }; + + pass.storage_bindings = { + FfxResourceBinding{ 2, 0, L"rw_upscaled_output" } + }; + + pass.uniform_bindings = { + FfxResourceBinding{ 3, 0, L"cbFSR2" }, + FfxResourceBinding{ 4, 0, L"cbRCAS" } + }; + } + + { + Pass &pass = device.passes[FFX_FSR2_PASS_COMPUTE_LUMINANCE_PYRAMID]; + pass.shader = &shaders.compute_luminance_pyramid; + pass.shader->initialize(modes, general_defines_base); + pass.shader_version = pass.shader->version_create(); + + pass.sampled_bindings = { + FfxResourceBinding{ 0, 0, L"r_input_color_jittered" } + }; + + pass.storage_bindings = { + FfxResourceBinding{ 1, 0, L"rw_spd_global_atomic" }, + FfxResourceBinding{ 2, 0, L"rw_img_mip_shading_change" }, + FfxResourceBinding{ 3, 0, L"rw_img_mip_5" }, + FfxResourceBinding{ 4, 0, L"rw_auto_exposure" } + }; + + pass.uniform_bindings = { + FfxResourceBinding{ 5, 0, L"cbFSR2" }, + FfxResourceBinding{ 6, 0, L"cbSPD" } + }; + } + + { + Pass &pass = device.passes[FFX_FSR2_PASS_GENERATE_REACTIVE]; + pass.shader = &shaders.autogen_reactive; + pass.shader->initialize(modes, general_defines); + pass.shader_version = pass.shader->version_create(); + + pass.sampled_bindings = { + FfxResourceBinding{ 0, 0, L"r_input_opaque_only" }, + FfxResourceBinding{ 1, 0, L"r_input_color_jittered" } + }; + + pass.storage_bindings = { + FfxResourceBinding{ 2, 0, L"rw_output_autoreactive" } + }; + + pass.uniform_bindings = { + FfxResourceBinding{ 3, 0, L"cbGenerateReactive" }, + FfxResourceBinding{ 4, 0, L"cbFSR2" } + }; + } + + { + Pass &pass = device.passes[FFX_FSR2_PASS_TCR_AUTOGENERATE]; + pass.shader = &shaders.tcr_autogen; + pass.shader->initialize(modes, general_defines); + pass.shader_version = pass.shader->version_create(); + + pass.sampled_bindings = { + FfxResourceBinding{ 0, 0, L"r_input_opaque_only" }, + FfxResourceBinding{ 1, 0, L"r_input_color_jittered" }, + FfxResourceBinding{ 2, 0, L"r_input_motion_vectors" }, + FfxResourceBinding{ 3, 0, L"r_input_prev_color_pre_alpha" }, + FfxResourceBinding{ 4, 0, L"r_input_prev_color_post_alpha" }, + FfxResourceBinding{ 5, 0, L"r_reactive_mask" }, + FfxResourceBinding{ 6, 0, L"r_transparency_and_composition_mask" }, + FfxResourceBinding{ 13, 0, L"r_input_depth" } + }; + + pass.storage_bindings = { + FfxResourceBinding{ 7, 0, L"rw_output_autoreactive" }, + FfxResourceBinding{ 8, 0, L"rw_output_autocomposition" }, + FfxResourceBinding{ 9, 0, L"rw_output_prev_color_pre_alpha" }, + FfxResourceBinding{ 10, 0, L"rw_output_prev_color_post_alpha" } + }; + + pass.uniform_bindings = { + FfxResourceBinding{ 11, 0, L"cbFSR2" }, + FfxResourceBinding{ 12, 0, L"cbGenerateReactive" } + }; + } + + RD::SamplerState state; + state.mag_filter = RD::SAMPLER_FILTER_NEAREST; + state.min_filter = RD::SAMPLER_FILTER_NEAREST; + state.repeat_u = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE; + state.repeat_v = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE; + state.repeat_w = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE; + state.min_lod = -1000.0f; + state.max_lod = 1000.0f; + state.anisotropy_max = 1.0; + device.point_clamp_sampler = RD::get_singleton()->sampler_create(state); + ERR_FAIL_COND(device.point_clamp_sampler.is_null()); + + state.mag_filter = RD::SAMPLER_FILTER_LINEAR; + state.min_filter = RD::SAMPLER_FILTER_LINEAR; + device.linear_clamp_sampler = RD::get_singleton()->sampler_create(state); + ERR_FAIL_COND(device.linear_clamp_sampler.is_null()); +} + +FSR2Effect::~FSR2Effect() { + RD::get_singleton()->free(device.point_clamp_sampler); + RD::get_singleton()->free(device.linear_clamp_sampler); + + for (uint32_t i = 0; i < FFX_FSR2_PASS_COUNT; i++) { + if (device.passes[i].pipeline.pipeline_rid.is_valid()) { + RD::get_singleton()->free(device.passes[i].pipeline.pipeline_rid); + } + device.passes[i].shader->version_free(device.passes[i].shader_version); + } +} + +FSR2Context *FSR2Effect::create_context(Size2i p_internal_size, Size2i p_target_size) { + FSR2Context *context = memnew(RendererRD::FSR2Context); + context->fsr_desc.flags = FFX_FSR2_ENABLE_HIGH_DYNAMIC_RANGE; + context->fsr_desc.maxRenderSize.width = p_internal_size.x; + context->fsr_desc.maxRenderSize.height = p_internal_size.y; + context->fsr_desc.displaySize.width = p_target_size.x; + context->fsr_desc.displaySize.height = p_target_size.y; + context->fsr_desc.device = &device; + + FfxFsr2Interface &functions = context->fsr_desc.callbacks; + functions.fpCreateBackendContext = create_backend_context_rd; + functions.fpGetDeviceCapabilities = get_device_capabilities_rd; + functions.fpDestroyBackendContext = destroy_backend_context_rd; + functions.fpCreateResource = create_resource_rd; + functions.fpRegisterResource = register_resource_rd; + functions.fpUnregisterResources = unregister_resources_rd; + functions.fpGetResourceDescription = get_resource_description_rd; + functions.fpDestroyResource = destroy_resource_rd; + functions.fpCreatePipeline = create_pipeline_rd; + functions.fpDestroyPipeline = destroy_pipeline_rd; + functions.fpScheduleGpuJob = schedule_gpu_job_rd; + functions.fpExecuteGpuJobs = execute_gpu_jobs_rd; + functions.scratchBuffer = &context->scratch; + functions.scratchBufferSize = sizeof(context->scratch); + + FfxErrorCode result = ffxFsr2ContextCreate(&context->fsr_context, &context->fsr_desc); + if (result == FFX_OK) { + return context; + } else { + memdelete(context); + return nullptr; + } +} + +void FSR2Effect::upscale(const Parameters &p_params) { + // TODO: Transparency & Composition mask is not implemented. + FfxFsr2DispatchDescription dispatch_desc = {}; + RID color = p_params.color; + RID depth = p_params.depth; + RID velocity = p_params.velocity; + RID reactive = p_params.reactive; + RID exposure = p_params.exposure; + RID output = p_params.output; + dispatch_desc.commandList = nullptr; + dispatch_desc.color = get_resource_rd(&color, L"color"); + dispatch_desc.depth = get_resource_rd(&depth, L"depth"); + dispatch_desc.motionVectors = get_resource_rd(&velocity, L"velocity"); + dispatch_desc.reactive = get_resource_rd(&reactive, L"reactive"); + dispatch_desc.exposure = get_resource_rd(&exposure, L"exposure"); + dispatch_desc.transparencyAndComposition = {}; + dispatch_desc.output = get_resource_rd(&output, L"output"); + dispatch_desc.colorOpaqueOnly = {}; + dispatch_desc.jitterOffset.x = p_params.jitter.x; + dispatch_desc.jitterOffset.y = p_params.jitter.y; + dispatch_desc.motionVectorScale.x = float(p_params.internal_size.width); + dispatch_desc.motionVectorScale.y = float(p_params.internal_size.height); + dispatch_desc.reset = p_params.reset_accumulation; + dispatch_desc.renderSize.width = p_params.internal_size.width; + dispatch_desc.renderSize.height = p_params.internal_size.height; + dispatch_desc.enableSharpening = (p_params.sharpness > 1e-6f); + dispatch_desc.sharpness = p_params.sharpness; + dispatch_desc.frameTimeDelta = p_params.delta_time; + dispatch_desc.preExposure = 1.0f; + dispatch_desc.cameraNear = p_params.z_near; + dispatch_desc.cameraFar = p_params.z_far; + dispatch_desc.cameraFovAngleVertical = p_params.fovy; + dispatch_desc.viewSpaceToMetersFactor = 1.0f; + dispatch_desc.enableAutoReactive = false; + dispatch_desc.autoTcThreshold = 1.0f; + dispatch_desc.autoTcScale = 1.0f; + dispatch_desc.autoReactiveScale = 1.0f; + dispatch_desc.autoReactiveMax = 1.0f; + + RendererRD::MaterialStorage::store_camera(p_params.reprojection, dispatch_desc.reprojectionMatrix); + + FfxErrorCode result = ffxFsr2ContextDispatch(&p_params.context->fsr_context, &dispatch_desc); + ERR_FAIL_COND(result != FFX_OK); +} diff --git a/servers/rendering/renderer_rd/effects/fsr2.h b/servers/rendering/renderer_rd/effects/fsr2.h new file mode 100644 index 0000000000..789714cc77 --- /dev/null +++ b/servers/rendering/renderer_rd/effects/fsr2.h @@ -0,0 +1,199 @@ +/**************************************************************************/ +/* fsr2.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef FSR2_RD_H +#define FSR2_RD_H + +#include "servers/rendering/renderer_rd/shaders/effects/fsr2/fsr2_accumulate_pass.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/effects/fsr2/fsr2_autogen_reactive_pass.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/effects/fsr2/fsr2_compute_luminance_pyramid_pass.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/effects/fsr2/fsr2_depth_clip_pass.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/effects/fsr2/fsr2_lock_pass.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/effects/fsr2/fsr2_rcas_pass.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/effects/fsr2/fsr2_reconstruct_previous_depth_pass.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/effects/fsr2/fsr2_tcr_autogen_pass.glsl.gen.h" + +// This flag doesn't actually control anything GCC specific in FSR2. It determines +// if symbols should be exported, which is not required for Godot. +#ifndef FFX_GCC +#define FFX_GCC +#endif + +#include "thirdparty/amd-fsr2/ffx_fsr2.h" + +#define FSR2_MAX_QUEUED_FRAMES (4) +#define FSR2_MAX_UNIFORM_BUFFERS (4) +#define FSR2_MAX_BUFFERED_DESCRIPTORS (FFX_FSR2_PASS_COUNT * FSR2_MAX_QUEUED_FRAMES) +#define FSR2_UBO_RING_BUFFER_SIZE (FSR2_MAX_BUFFERED_DESCRIPTORS * FSR2_MAX_UNIFORM_BUFFERS) + +namespace RendererRD { +class FSR2Context { +public: + enum ResourceID : uint32_t { + RESOURCE_ID_DYNAMIC = 0xFFFFFFFF + }; + + struct Resources { + LocalVector<RID> rids; + LocalVector<LocalVector<RID>> mip_slice_rids; + LocalVector<uint32_t> ids; + LocalVector<FfxResourceDescription> descriptions; + LocalVector<uint32_t> dynamic_list; + LocalVector<uint32_t> free_list; + + uint32_t add(RID p_rid, bool p_dynamic, uint32_t p_id, FfxResourceDescription p_description) { + uint32_t ret_index; + if (free_list.is_empty()) { + ret_index = rids.size(); + uint32_t new_size = ret_index + 1; + rids.resize(new_size); + mip_slice_rids.resize(new_size); + ids.resize(new_size); + descriptions.resize(new_size); + } else { + uint32_t end_index = free_list.size() - 1; + ret_index = free_list[end_index]; + free_list.resize(end_index); + } + + rids[ret_index] = p_rid; + mip_slice_rids[ret_index].clear(); + ids[ret_index] = p_id; + descriptions[ret_index] = p_description; + + if (p_dynamic) { + dynamic_list.push_back(ret_index); + } + + return ret_index; + } + + void remove(uint32_t p_index) { + DEV_ASSERT(p_index < rids.size()); + free_list.push_back(p_index); + rids[p_index] = RID(); + mip_slice_rids[p_index].clear(); + ids[p_index] = 0; + descriptions[p_index] = {}; + dynamic_list.erase(p_index); + } + + uint32_t size() const { + return rids.size(); + } + }; + + struct Scratch { + Resources resources; + LocalVector<FfxGpuJobDescription> gpu_jobs; + RID ubo_ring_buffer[FSR2_UBO_RING_BUFFER_SIZE]; + uint32_t ubo_ring_buffer_index = 0; + FfxDevice device = nullptr; + }; + + Scratch scratch; + FfxFsr2Context fsr_context; + FfxFsr2ContextDescription fsr_desc; + + ~FSR2Context(); +}; + +class FSR2Effect { +public: + struct RootSignature { + // Proxy structure to store the shader required by RD that uses the terminology used by the FSR2 API. + RID shader_rid; + }; + + struct Pipeline { + RID pipeline_rid; + }; + + struct Pass { + ShaderRD *shader; + RID shader_version; + RootSignature root_signature; + uint32_t shader_variant = 0; + Pipeline pipeline; + Vector<FfxResourceBinding> sampled_bindings; + Vector<FfxResourceBinding> storage_bindings; + Vector<FfxResourceBinding> uniform_bindings; + }; + + struct Device { + Pass passes[FFX_FSR2_PASS_COUNT]; + FfxDeviceCapabilities capabilities; + RID point_clamp_sampler; + RID linear_clamp_sampler; + }; + + struct Parameters { + FSR2Context *context; + Size2i internal_size; + RID color; + RID depth; + RID velocity; + RID reactive; + RID exposure; + RID output; + float z_near = 0.0f; + float z_far = 0.0f; + float fovy = 0.0f; + Vector2 jitter; + float delta_time = 0.0f; + float sharpness = 0.0f; + bool reset_accumulation = false; + Projection reprojection; + }; + + FSR2Effect(); + ~FSR2Effect(); + FSR2Context *create_context(Size2i p_internal_size, Size2i p_target_size); + void upscale(const Parameters &p_params); + +private: + struct { + Fsr2DepthClipPassShaderRD depth_clip; + Fsr2ReconstructPreviousDepthPassShaderRD reconstruct_previous_depth; + Fsr2LockPassShaderRD lock; + Fsr2AccumulatePassShaderRD accumulate; + Fsr2AccumulatePassShaderRD accumulate_sharpen; + Fsr2RcasPassShaderRD rcas; + Fsr2ComputeLuminancePyramidPassShaderRD compute_luminance_pyramid; + Fsr2AutogenReactivePassShaderRD autogen_reactive; + Fsr2TcrAutogenPassShaderRD tcr_autogen; + } shaders; + + Device device; +}; + +} // namespace RendererRD + +#endif // FSR2_RD_H diff --git a/servers/rendering/renderer_rd/effects/taa.cpp b/servers/rendering/renderer_rd/effects/taa.cpp index 61e0d3866c..c1037ec11a 100644 --- a/servers/rendering/renderer_rd/effects/taa.cpp +++ b/servers/rendering/renderer_rd/effects/taa.cpp @@ -47,20 +47,6 @@ TAA::~TAA() { taa_shader.version_free(shader_version); } -void TAA::msaa_resolve(Ref<RenderSceneBuffersRD> p_render_buffers) { - if (!p_render_buffers->has_velocity_buffer(true)) { - // nothing to resolve - return; - } - - for (uint32_t v = 0; v < p_render_buffers->get_view_count(); v++) { - RID velocity_buffer_msaa = p_render_buffers->get_velocity_buffer(true, v); - RID velocity_buffer = p_render_buffers->get_velocity_buffer(false, v); - - RD::get_singleton()->texture_resolve_multisample(velocity_buffer_msaa, velocity_buffer); - } -} - void TAA::resolve(RID p_frame, RID p_temp, RID p_depth, RID p_velocity, RID p_prev_velocity, RID p_history, Size2 p_resolution, float p_z_near, float p_z_far) { UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); ERR_FAIL_NULL(uniform_set_cache); diff --git a/servers/rendering/renderer_rd/effects/taa.h b/servers/rendering/renderer_rd/effects/taa.h index 9e7ad76fb8..f50e297fe5 100644 --- a/servers/rendering/renderer_rd/effects/taa.h +++ b/servers/rendering/renderer_rd/effects/taa.h @@ -45,7 +45,6 @@ public: TAA(); ~TAA(); - void msaa_resolve(Ref<RenderSceneBuffersRD> p_render_buffers); void process(Ref<RenderSceneBuffersRD> p_render_buffers, RD::DataFormat p_format, float p_z_near, float p_z_far); private: diff --git a/servers/rendering/renderer_rd/environment/fog.cpp b/servers/rendering/renderer_rd/environment/fog.cpp index 634f8c69df..fc2d9ae11c 100644 --- a/servers/rendering/renderer_rd/environment/fog.cpp +++ b/servers/rendering/renderer_rd/environment/fog.cpp @@ -72,7 +72,7 @@ Dependency *Fog::fog_volume_get_dependency(RID p_fog_volume) const { void Fog::fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) { FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume); - ERR_FAIL_COND(!fog_volume); + ERR_FAIL_NULL(fog_volume); if (p_shape == fog_volume->shape) { return; @@ -84,7 +84,7 @@ void Fog::fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) { void Fog::fog_volume_set_size(RID p_fog_volume, const Vector3 &p_size) { FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume); - ERR_FAIL_COND(!fog_volume); + ERR_FAIL_NULL(fog_volume); fog_volume->size = p_size; fog_volume->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB); @@ -92,27 +92,27 @@ void Fog::fog_volume_set_size(RID p_fog_volume, const Vector3 &p_size) { void Fog::fog_volume_set_material(RID p_fog_volume, RID p_material) { FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume); - ERR_FAIL_COND(!fog_volume); + ERR_FAIL_NULL(fog_volume); fog_volume->material = p_material; } RID Fog::fog_volume_get_material(RID p_fog_volume) const { FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume); - ERR_FAIL_COND_V(!fog_volume, RID()); + ERR_FAIL_NULL_V(fog_volume, RID()); return fog_volume->material; } RS::FogVolumeShape Fog::fog_volume_get_shape(RID p_fog_volume) const { FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume); - ERR_FAIL_COND_V(!fog_volume, RS::FOG_VOLUME_SHAPE_BOX); + ERR_FAIL_NULL_V(fog_volume, RS::FOG_VOLUME_SHAPE_BOX); return fog_volume->shape; } AABB Fog::fog_volume_get_aabb(RID p_fog_volume) const { FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume); - ERR_FAIL_COND_V(!fog_volume, AABB()); + ERR_FAIL_NULL_V(fog_volume, AABB()); switch (fog_volume->shape) { case RS::FOG_VOLUME_SHAPE_ELLIPSOID: @@ -133,7 +133,7 @@ AABB Fog::fog_volume_get_aabb(RID p_fog_volume) const { Vector3 Fog::fog_volume_get_size(RID p_fog_volume) const { const FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume); - ERR_FAIL_COND_V(!fog_volume, Vector3()); + ERR_FAIL_NULL_V(fog_volume, Vector3()); return fog_volume->size; } @@ -370,7 +370,7 @@ RS::ShaderNativeSourceCode Fog::FogShaderData::get_native_source_code() const { Fog::FogShaderData::~FogShaderData() { Fog *fog_singleton = Fog::get_singleton(); - ERR_FAIL_COND(!fog_singleton); + ERR_FAIL_NULL(fog_singleton); //pipeline variants will clear themselves if shader is gone if (version.is_valid()) { fog_singleton->volumetric_fog.shader.version_free(version); @@ -543,7 +543,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P if (p_cam_projection.is_orthogonal()) { fog_near_size = fog_far_size; } else { - fog_near_size = Vector2(); + fog_near_size = frustum_near_size.max(Vector2(0.001, 0.001)); } params.fog_frustum_size_begin[0] = fog_near_size.x; @@ -627,7 +627,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P for (int i = 0; i < (int)p_fog_volumes.size(); i++) { FogVolumeInstance *fog_volume_instance = fog_volume_instance_owner.get_or_null(p_fog_volumes[i]); - ERR_FAIL_COND(!fog_volume_instance); + ERR_FAIL_NULL(fog_volume_instance); RID fog_volume = fog_volume_instance->volume; RID fog_material = RendererRD::Fog::get_singleton()->fog_volume_get_material(fog_volume); @@ -646,11 +646,11 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P material = static_cast<FogMaterialData *>(material_storage->material_get_data(fog_material, RendererRD::MaterialStorage::SHADER_TYPE_FOG)); } - ERR_FAIL_COND(!material); + ERR_FAIL_NULL(material); FogShaderData *shader_data = material->shader_data; - ERR_FAIL_COND(!shader_data); + ERR_FAIL_NULL(shader_data); any_uses_time |= shader_data->uses_time; @@ -1002,7 +1002,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P if (p_cam_projection.is_orthogonal()) { fog_near_size = fog_far_size; } else { - fog_near_size = Vector2(); + fog_near_size = frustum_near_size.max(Vector2(0.001, 0.001)); } params.fog_frustum_size_begin[0] = fog_near_size.x; diff --git a/servers/rendering/renderer_rd/environment/fog.h b/servers/rendering/renderer_rd/environment/fog.h index 206d7852a7..25fb190f44 100644 --- a/servers/rendering/renderer_rd/environment/fog.h +++ b/servers/rendering/renderer_rd/environment/fog.h @@ -257,25 +257,25 @@ public: void fog_volume_instance_set_transform(RID p_fog_volume_instance, const Transform3D &p_transform) { Fog::FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance); - ERR_FAIL_COND(!fvi); + ERR_FAIL_NULL(fvi); fvi->transform = p_transform; } void fog_volume_instance_set_active(RID p_fog_volume_instance, bool p_active) { Fog::FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance); - ERR_FAIL_COND(!fvi); + ERR_FAIL_NULL(fvi); fvi->active = p_active; } RID fog_volume_instance_get_volume(RID p_fog_volume_instance) const { Fog::FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance); - ERR_FAIL_COND_V(!fvi, RID()); + ERR_FAIL_NULL_V(fvi, RID()); return fvi->volume; } Vector3 fog_volume_instance_get_position(RID p_fog_volume_instance) const { Fog::FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance); - ERR_FAIL_COND_V(!fvi, Vector3()); + ERR_FAIL_NULL_V(fvi, Vector3()); return fvi->transform.get_origin(); } diff --git a/servers/rendering/renderer_rd/environment/gi.cpp b/servers/rendering/renderer_rd/environment/gi.cpp index d623553273..0667ae87e5 100644 --- a/servers/rendering/renderer_rd/environment/gi.cpp +++ b/servers/rendering/renderer_rd/environment/gi.cpp @@ -64,7 +64,7 @@ void GI::voxel_gi_initialize(RID p_voxel_gi) { void GI::voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) { VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND(!voxel_gi); + ERR_FAIL_NULL(voxel_gi); if (voxel_gi->octree_buffer.is_valid()) { RD::get_singleton()->free(voxel_gi->octree_buffer); @@ -191,20 +191,20 @@ void GI::voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D &p_to_cell_xfo AABB GI::voxel_gi_get_bounds(RID p_voxel_gi) const { VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND_V(!voxel_gi, AABB()); + ERR_FAIL_NULL_V(voxel_gi, AABB()); return voxel_gi->bounds; } Vector3i GI::voxel_gi_get_octree_size(RID p_voxel_gi) const { VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND_V(!voxel_gi, Vector3i()); + ERR_FAIL_NULL_V(voxel_gi, Vector3i()); return voxel_gi->octree_size; } Vector<uint8_t> GI::voxel_gi_get_octree_cells(RID p_voxel_gi) const { VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND_V(!voxel_gi, Vector<uint8_t>()); + ERR_FAIL_NULL_V(voxel_gi, Vector<uint8_t>()); if (voxel_gi->octree_buffer.is_valid()) { return RD::get_singleton()->buffer_get_data(voxel_gi->octree_buffer); @@ -214,7 +214,7 @@ Vector<uint8_t> GI::voxel_gi_get_octree_cells(RID p_voxel_gi) const { Vector<uint8_t> GI::voxel_gi_get_data_cells(RID p_voxel_gi) const { VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND_V(!voxel_gi, Vector<uint8_t>()); + ERR_FAIL_NULL_V(voxel_gi, Vector<uint8_t>()); if (voxel_gi->data_buffer.is_valid()) { return RD::get_singleton()->buffer_get_data(voxel_gi->data_buffer); @@ -224,7 +224,7 @@ Vector<uint8_t> GI::voxel_gi_get_data_cells(RID p_voxel_gi) const { Vector<uint8_t> GI::voxel_gi_get_distance_field(RID p_voxel_gi) const { VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND_V(!voxel_gi, Vector<uint8_t>()); + ERR_FAIL_NULL_V(voxel_gi, Vector<uint8_t>()); if (voxel_gi->data_buffer.is_valid()) { return RD::get_singleton()->texture_get_data(voxel_gi->sdf_texture, 0); @@ -234,21 +234,21 @@ Vector<uint8_t> GI::voxel_gi_get_distance_field(RID p_voxel_gi) const { Vector<int> GI::voxel_gi_get_level_counts(RID p_voxel_gi) const { VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND_V(!voxel_gi, Vector<int>()); + ERR_FAIL_NULL_V(voxel_gi, Vector<int>()); return voxel_gi->level_counts; } Transform3D GI::voxel_gi_get_to_cell_xform(RID p_voxel_gi) const { VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND_V(!voxel_gi, Transform3D()); + ERR_FAIL_NULL_V(voxel_gi, Transform3D()); return voxel_gi->to_cell_xform; } void GI::voxel_gi_set_dynamic_range(RID p_voxel_gi, float p_range) { VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND(!voxel_gi); + ERR_FAIL_NULL(voxel_gi); voxel_gi->dynamic_range = p_range; voxel_gi->version++; @@ -256,14 +256,14 @@ void GI::voxel_gi_set_dynamic_range(RID p_voxel_gi, float p_range) { float GI::voxel_gi_get_dynamic_range(RID p_voxel_gi) const { VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND_V(!voxel_gi, 0); + ERR_FAIL_NULL_V(voxel_gi, 0); return voxel_gi->dynamic_range; } void GI::voxel_gi_set_propagation(RID p_voxel_gi, float p_range) { VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND(!voxel_gi); + ERR_FAIL_NULL(voxel_gi); voxel_gi->propagation = p_range; voxel_gi->version++; @@ -271,72 +271,72 @@ void GI::voxel_gi_set_propagation(RID p_voxel_gi, float p_range) { float GI::voxel_gi_get_propagation(RID p_voxel_gi) const { VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND_V(!voxel_gi, 0); + ERR_FAIL_NULL_V(voxel_gi, 0); return voxel_gi->propagation; } void GI::voxel_gi_set_energy(RID p_voxel_gi, float p_energy) { VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND(!voxel_gi); + ERR_FAIL_NULL(voxel_gi); voxel_gi->energy = p_energy; } float GI::voxel_gi_get_energy(RID p_voxel_gi) const { VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND_V(!voxel_gi, 0); + ERR_FAIL_NULL_V(voxel_gi, 0); return voxel_gi->energy; } void GI::voxel_gi_set_baked_exposure_normalization(RID p_voxel_gi, float p_baked_exposure) { VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND(!voxel_gi); + ERR_FAIL_NULL(voxel_gi); voxel_gi->baked_exposure = p_baked_exposure; } float GI::voxel_gi_get_baked_exposure_normalization(RID p_voxel_gi) const { VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND_V(!voxel_gi, 0); + ERR_FAIL_NULL_V(voxel_gi, 0); return voxel_gi->baked_exposure; } void GI::voxel_gi_set_bias(RID p_voxel_gi, float p_bias) { VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND(!voxel_gi); + ERR_FAIL_NULL(voxel_gi); voxel_gi->bias = p_bias; } float GI::voxel_gi_get_bias(RID p_voxel_gi) const { VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND_V(!voxel_gi, 0); + ERR_FAIL_NULL_V(voxel_gi, 0); return voxel_gi->bias; } void GI::voxel_gi_set_normal_bias(RID p_voxel_gi, float p_normal_bias) { VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND(!voxel_gi); + ERR_FAIL_NULL(voxel_gi); voxel_gi->normal_bias = p_normal_bias; } float GI::voxel_gi_get_normal_bias(RID p_voxel_gi) const { VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND_V(!voxel_gi, 0); + ERR_FAIL_NULL_V(voxel_gi, 0); return voxel_gi->normal_bias; } void GI::voxel_gi_set_interior(RID p_voxel_gi, bool p_enable) { VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND(!voxel_gi); + ERR_FAIL_NULL(voxel_gi); voxel_gi->interior = p_enable; } void GI::voxel_gi_set_use_two_bounces(RID p_voxel_gi, bool p_enable) { VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND(!voxel_gi); + ERR_FAIL_NULL(voxel_gi); voxel_gi->use_two_bounces = p_enable; voxel_gi->version++; @@ -344,50 +344,50 @@ void GI::voxel_gi_set_use_two_bounces(RID p_voxel_gi, bool p_enable) { bool GI::voxel_gi_is_using_two_bounces(RID p_voxel_gi) const { VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND_V(!voxel_gi, false); + ERR_FAIL_NULL_V(voxel_gi, false); return voxel_gi->use_two_bounces; } bool GI::voxel_gi_is_interior(RID p_voxel_gi) const { VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND_V(!voxel_gi, 0); + ERR_FAIL_NULL_V(voxel_gi, 0); return voxel_gi->interior; } uint32_t GI::voxel_gi_get_version(RID p_voxel_gi) const { VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND_V(!voxel_gi, 0); + ERR_FAIL_NULL_V(voxel_gi, 0); return voxel_gi->version; } uint32_t GI::voxel_gi_get_data_version(RID p_voxel_gi) { VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND_V(!voxel_gi, 0); + ERR_FAIL_NULL_V(voxel_gi, 0); return voxel_gi->data_version; } RID GI::voxel_gi_get_octree_buffer(RID p_voxel_gi) const { VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND_V(!voxel_gi, RID()); + ERR_FAIL_NULL_V(voxel_gi, RID()); return voxel_gi->octree_buffer; } RID GI::voxel_gi_get_data_buffer(RID p_voxel_gi) const { VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND_V(!voxel_gi, RID()); + ERR_FAIL_NULL_V(voxel_gi, RID()); return voxel_gi->data_buffer; } RID GI::voxel_gi_get_sdf_texture(RID p_voxel_gi) { VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND_V(!voxel_gi, RID()); + ERR_FAIL_NULL_V(voxel_gi, RID()); return voxel_gi->sdf_texture; } Dependency *GI::voxel_gi_get_dependency(RID p_voxel_gi) const { VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND_V(!voxel_gi, nullptr); + ERR_FAIL_NULL_V(voxel_gi, nullptr); return &voxel_gi->dependency; } @@ -4054,28 +4054,28 @@ void GI::voxel_gi_instance_free(RID p_rid) { void GI::voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) { VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe); - ERR_FAIL_COND(!voxel_gi); + ERR_FAIL_NULL(voxel_gi); voxel_gi->transform = p_xform; } bool GI::voxel_gi_needs_update(RID p_probe) const { VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe); - ERR_FAIL_COND_V(!voxel_gi, false); + ERR_FAIL_NULL_V(voxel_gi, false); return voxel_gi->last_probe_version != voxel_gi_get_version(voxel_gi->probe); } void GI::voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects) { VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe); - ERR_FAIL_COND(!voxel_gi); + ERR_FAIL_NULL(voxel_gi); voxel_gi->update(p_update_light_instances, p_light_instances, p_dynamic_objects); } void GI::debug_voxel_gi(RID p_voxel_gi, RD::DrawListID p_draw_list, RID p_framebuffer, const Projection &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) { VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND(!voxel_gi); + ERR_FAIL_NULL(voxel_gi); voxel_gi->debug(p_draw_list, p_framebuffer, p_camera_with_transform, p_lighting, p_emission, p_alpha); } diff --git a/servers/rendering/renderer_rd/environment/gi.h b/servers/rendering/renderer_rd/environment/gi.h index 651a660f5c..9a45919a2f 100644 --- a/servers/rendering/renderer_rd/environment/gi.h +++ b/servers/rendering/renderer_rd/environment/gi.h @@ -522,7 +522,7 @@ public: _FORCE_INLINE_ RID voxel_gi_instance_get_texture(RID p_probe) { VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe); - ERR_FAIL_COND_V(!voxel_gi, RID()); + ERR_FAIL_NULL_V(voxel_gi, RID()); return voxel_gi->texture; }; diff --git a/servers/rendering/renderer_rd/environment/sky.cpp b/servers/rendering/renderer_rd/environment/sky.cpp index 310aefe1b1..ba72ab3b08 100644 --- a/servers/rendering/renderer_rd/environment/sky.cpp +++ b/servers/rendering/renderer_rd/environment/sky.cpp @@ -170,7 +170,7 @@ RS::ShaderNativeSourceCode SkyRD::SkyShaderData::get_native_source_code() const SkyRD::SkyShaderData::~SkyShaderData() { RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton); - ERR_FAIL_COND(!scene_singleton); + ERR_FAIL_NULL(scene_singleton); //pipeline variants will clear themselves if shader is gone if (version.is_valid()) { scene_singleton->sky.sky_shader.shader.version_free(version); @@ -973,7 +973,7 @@ SkyRD::~SkyRD() { } } -void SkyRD::setup_sky(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, const PagedArray<RID> &p_lights, RID p_camera_attributes, uint32_t p_view_count, const Projection *p_view_projections, const Vector3 *p_view_eye_offsets, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render) { +void SkyRD::setup_sky(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, const PagedArray<RID> &p_lights, RID p_camera_attributes, uint32_t p_view_count, const Projection *p_view_projections, const Vector3 *p_view_eye_offsets, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const Size2i p_screen_size, Vector2 p_jitter, RendererSceneRenderRD *p_scene_render) { RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); ERR_FAIL_COND(p_env.is_null()); @@ -1007,11 +1007,11 @@ void SkyRD::setup_sky(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, con material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); } - ERR_FAIL_COND(!material); + ERR_FAIL_NULL(material); shader_data = material->shader_data; - ERR_FAIL_COND(!shader_data); + ERR_FAIL_NULL(shader_data); material->set_as_used(); @@ -1173,18 +1173,21 @@ void SkyRD::setup_sky(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, con } } + Projection correction; + correction.add_jitter_offset(p_jitter); + sky_scene_state.view_count = p_view_count; sky_scene_state.cam_transform = p_cam_transform; - sky_scene_state.cam_projection = p_cam_projection; // We only use this when rendering a single view. + sky_scene_state.cam_projection = correction * p_cam_projection; // We only use this when rendering a single view. // Our info in our UBO is only used if we're rendering stereo. for (uint32_t i = 0; i < p_view_count; i++) { - Projection view_inv_projection = p_view_projections[i].inverse(); + Projection view_inv_projection = (correction * p_view_projections[i]).inverse(); if (p_view_count > 1) { RendererRD::MaterialStorage::store_camera(p_cam_projection * view_inv_projection, sky_scene_state.ubo.combined_reprojection[i]); } else { Projection ident; - RendererRD::MaterialStorage::store_camera(ident, sky_scene_state.ubo.combined_reprojection[i]); + RendererRD::MaterialStorage::store_camera(correction, sky_scene_state.ubo.combined_reprojection[i]); } RendererRD::MaterialStorage::store_camera(view_inv_projection, sky_scene_state.ubo.view_inv_projections[i]); @@ -1217,7 +1220,7 @@ void SkyRD::update_radiance_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, ERR_FAIL_COND(p_env.is_null()); Sky *sky = get_sky(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env)); - ERR_FAIL_COND(!sky); + ERR_FAIL_NULL(sky); RID sky_material = sky_get_material(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env)); @@ -1235,11 +1238,11 @@ void SkyRD::update_radiance_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); } - ERR_FAIL_COND(!material); + ERR_FAIL_NULL(material); SkyShaderData *shader_data = material->shader_data; - ERR_FAIL_COND(!shader_data); + ERR_FAIL_NULL(shader_data); bool update_single_frame = sky->mode == RS::SKY_MODE_REALTIME || sky->mode == RS::SKY_MODE_QUALITY; RS::SkyMode sky_mode = sky->mode; @@ -1398,7 +1401,7 @@ void SkyRD::update_res_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, RID p RS::EnvironmentBG background = RendererSceneRenderRD::get_singleton()->environment_get_background(p_env); if (!(background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) || sky) { - ERR_FAIL_COND(!sky); + ERR_FAIL_NULL(sky); sky_material = sky_get_material(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env)); if (sky_material.is_valid()) { @@ -1419,10 +1422,10 @@ void SkyRD::update_res_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, RID p material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); } - ERR_FAIL_COND(!material); + ERR_FAIL_NULL(material); SkyShaderData *shader_data = material->shader_data; - ERR_FAIL_COND(!shader_data); + ERR_FAIL_NULL(shader_data); if (!shader_data->uses_quarter_res && !shader_data->uses_half_res) { return; @@ -1506,7 +1509,7 @@ void SkyRD::draw_sky(RD::DrawListID p_draw_list, Ref<RenderSceneBuffersRD> p_ren RS::EnvironmentBG background = RendererSceneRenderRD::get_singleton()->environment_get_background(p_env); if (!(background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) || sky) { - ERR_FAIL_COND(!sky); + ERR_FAIL_NULL(sky); sky_material = sky_get_material(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env)); if (sky_material.is_valid()) { @@ -1527,10 +1530,10 @@ void SkyRD::draw_sky(RD::DrawListID p_draw_list, Ref<RenderSceneBuffersRD> p_ren material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); } - ERR_FAIL_COND(!material); + ERR_FAIL_NULL(material); SkyShaderData *shader_data = material->shader_data; - ERR_FAIL_COND(!shader_data); + ERR_FAIL_NULL(shader_data); material->set_as_used(); @@ -1646,14 +1649,14 @@ void SkyRD::update_dirty_skys() { RID SkyRD::sky_get_material(RID p_sky) const { Sky *sky = get_sky(p_sky); - ERR_FAIL_COND_V(!sky, RID()); + ERR_FAIL_NULL_V(sky, RID()); return sky->material; } float SkyRD::sky_get_baked_exposure(RID p_sky) const { Sky *sky = get_sky(p_sky); - ERR_FAIL_COND_V(!sky, 1.0); + ERR_FAIL_NULL_V(sky, 1.0); return sky->baked_exposure; } @@ -1672,7 +1675,7 @@ SkyRD::Sky *SkyRD::get_sky(RID p_sky) const { void SkyRD::free_sky(RID p_sky) { Sky *sky = get_sky(p_sky); - ERR_FAIL_COND(!sky); + ERR_FAIL_NULL(sky); sky->free(); sky_owner.free(p_sky); @@ -1680,7 +1683,7 @@ void SkyRD::free_sky(RID p_sky) { void SkyRD::sky_set_radiance_size(RID p_sky, int p_radiance_size) { Sky *sky = get_sky(p_sky); - ERR_FAIL_COND(!sky); + ERR_FAIL_NULL(sky); if (sky->set_radiance_size(p_radiance_size)) { invalidate_sky(sky); @@ -1689,7 +1692,7 @@ void SkyRD::sky_set_radiance_size(RID p_sky, int p_radiance_size) { void SkyRD::sky_set_mode(RID p_sky, RS::SkyMode p_mode) { Sky *sky = get_sky(p_sky); - ERR_FAIL_COND(!sky); + ERR_FAIL_NULL(sky); if (sky->set_mode(p_mode)) { invalidate_sky(sky); @@ -1698,7 +1701,7 @@ void SkyRD::sky_set_mode(RID p_sky, RS::SkyMode p_mode) { void SkyRD::sky_set_material(RID p_sky, RID p_material) { Sky *sky = get_sky(p_sky); - ERR_FAIL_COND(!sky); + ERR_FAIL_NULL(sky); if (sky->set_material(p_material)) { invalidate_sky(sky); @@ -1707,7 +1710,7 @@ void SkyRD::sky_set_material(RID p_sky, RID p_material) { Ref<Image> SkyRD::sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size) { Sky *sky = get_sky(p_sky); - ERR_FAIL_COND_V(!sky, Ref<Image>()); + ERR_FAIL_NULL_V(sky, Ref<Image>()); update_dirty_skys(); @@ -1716,7 +1719,7 @@ Ref<Image> SkyRD::sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irrad RID SkyRD::sky_get_radiance_texture_rd(RID p_sky) const { Sky *sky = get_sky(p_sky); - ERR_FAIL_COND_V(!sky, RID()); + ERR_FAIL_NULL_V(sky, RID()); return sky->radiance; } diff --git a/servers/rendering/renderer_rd/environment/sky.h b/servers/rendering/renderer_rd/environment/sky.h index ee2d81757c..b146a416f9 100644 --- a/servers/rendering/renderer_rd/environment/sky.h +++ b/servers/rendering/renderer_rd/environment/sky.h @@ -294,7 +294,7 @@ public: void set_texture_format(RD::DataFormat p_texture_format); ~SkyRD(); - void setup_sky(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, const PagedArray<RID> &p_lights, RID p_camera_attributes, uint32_t p_view_count, const Projection *p_view_projections, const Vector3 *p_view_eye_offsets, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render); + void setup_sky(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, const PagedArray<RID> &p_lights, RID p_camera_attributes, uint32_t p_view_count, const Projection *p_view_projections, const Vector3 *p_view_eye_offsets, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const Size2i p_screen_size, Vector2 p_jitter, RendererSceneRenderRD *p_scene_render); void update_radiance_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_env, const Vector3 &p_global_pos, double p_time, float p_luminance_multiplier = 1.0); void update_res_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_env, double p_time, float p_luminance_multiplier = 1.0); void draw_sky(RD::DrawListID p_draw_list, Ref<RenderSceneBuffersRD> p_render_buffers, RID p_env, RID p_fb, double p_time, float p_luminance_multiplier = 1.0); diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp index 5456e5b182..e65101d856 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -105,6 +105,12 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_voxelgi() } } +void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_fsr2(RendererRD::FSR2Effect *p_effect) { + if (fsr2_context == nullptr) { + fsr2_context = p_effect->create_context(render_buffers->get_internal_size(), render_buffers->get_target_size()); + } +} + void RenderForwardClustered::RenderBufferDataForwardClustered::free_data() { // JIC, should already have been cleared if (render_buffers) { @@ -120,6 +126,11 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::free_data() { cluster_builder = nullptr; } + if (fsr2_context) { + memdelete(fsr2_context); + fsr2_context = nullptr; + } + if (!render_sdfgi_uniform_set.is_null() && RD::get_singleton()->uniform_set_is_valid(render_sdfgi_uniform_set)) { RD::get_singleton()->free(render_sdfgi_uniform_set); } @@ -230,6 +241,14 @@ RID RenderForwardClustered::RenderBufferDataForwardClustered::get_specular_only_ return FramebufferCacheRD::get_singleton()->get_cache_multiview(render_buffers->get_view_count(), specular); } +RID RenderForwardClustered::RenderBufferDataForwardClustered::get_velocity_only_fb() { + bool use_msaa = render_buffers->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED; + + RID velocity = render_buffers->get_texture(RB_SCOPE_BUFFERS, use_msaa ? RB_TEX_VELOCITY_MSAA : RB_TEX_VELOCITY); + + return FramebufferCacheRD::get_singleton()->get_cache_multiview(render_buffers->get_view_count(), velocity); +} + void RenderForwardClustered::setup_render_buffer_data(Ref<RenderSceneBuffersRD> p_render_buffers) { Ref<RenderBufferDataForwardClustered> data; data.instantiate(); @@ -285,8 +304,10 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p const GeometryInstanceSurfaceDataCache *surf = p_params->elements[i]; const RenderElementInfo &element_info = p_params->element_info[i]; - if ((p_pass_mode == PASS_MODE_COLOR && !(p_color_pass_flags & COLOR_PASS_FLAG_TRANSPARENT)) && !(surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE)) { - continue; // Objects with "Depth-prepass" transparency are included in both render lists, but should only be rendered in the transparent pass + if (p_pass_mode == PASS_MODE_COLOR && surf->color_pass_inclusion_mask && (p_color_pass_flags & surf->color_pass_inclusion_mask) == 0) { + // Some surfaces can be repeated in multiple render lists. We exclude them from being rendered on the color pass based on the + // features supported by the pass compared to the exclusion mask. + continue; } if (surf->owner->instance_count == 0) { @@ -582,7 +603,7 @@ void RenderForwardClustered::_render_list_with_threads(RenderListParameters *p_p } } -void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_data, bool p_no_fog, const Size2i &p_screen_size, bool p_flip_y, const Color &p_default_bg_color, bool p_opaque_render_buffers, bool p_pancake_shadows, int p_index) { +void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_data, bool p_no_fog, const Size2i &p_screen_size, bool p_flip_y, const Color &p_default_bg_color, bool p_opaque_render_buffers, bool p_apply_alpha_multiplier, bool p_pancake_shadows, int p_index) { RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); Ref<RenderSceneBuffersRD> rd = p_render_data->render_buffers; @@ -598,7 +619,7 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat } } - p_render_data->scene_data->update_ubo(scene_state.uniform_buffers[p_index], get_debug_draw_mode(), env, reflection_probe_instance, p_render_data->camera_attributes, p_flip_y, p_pancake_shadows, p_screen_size, p_default_bg_color, _render_buffers_get_luminance_multiplier(), p_opaque_render_buffers); + p_render_data->scene_data->update_ubo(scene_state.uniform_buffers[p_index], get_debug_draw_mode(), env, reflection_probe_instance, p_render_data->camera_attributes, p_flip_y, p_pancake_shadows, p_screen_size, p_default_bg_color, _render_buffers_get_luminance_multiplier(), p_opaque_render_buffers, p_apply_alpha_multiplier); // now do implementation UBO @@ -707,7 +728,7 @@ void RenderForwardClustered::_fill_instance_data(RenderListType p_render_list, i RendererRD::MaterialStorage::store_transform(inst->prev_transform, instance_data.prev_transform); #ifdef REAL_T_IS_DOUBLE - // Split the origin into two components, the float approximation and the missing precision + // Split the origin into two components, the float approximation and the missing precision. // In the shader we will combine these back together to restore the lost precision. RendererRD::MaterialStorage::split_double(inst->transform.origin.x, &instance_data.transform[12], &instance_data.transform[3]); RendererRD::MaterialStorage::split_double(inst->transform.origin.y, &instance_data.transform[13], &instance_data.transform[7]); @@ -727,6 +748,28 @@ void RenderForwardClustered::_fill_instance_data(RenderListType p_render_list, i instance_data.lightmap_uv_scale[2] = inst->lightmap_uv_scale.size.x; instance_data.lightmap_uv_scale[3] = inst->lightmap_uv_scale.size.y; + AABB surface_aabb = AABB(Vector3(0.0, 0.0, 0.0), Vector3(1.0, 1.0, 1.0)); + uint64_t format = RendererRD::MeshStorage::get_singleton()->mesh_surface_get_format(surface->surface); + Vector4 uv_scale = Vector4(0.0, 0.0, 0.0, 0.0); + + if (format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES) { + surface_aabb = RendererRD::MeshStorage::get_singleton()->mesh_surface_get_aabb(surface->surface); + uv_scale = RendererRD::MeshStorage::get_singleton()->mesh_surface_get_uv_scale(surface->surface); + } + + instance_data.compressed_aabb_position[0] = surface_aabb.position.x; + instance_data.compressed_aabb_position[1] = surface_aabb.position.y; + instance_data.compressed_aabb_position[2] = surface_aabb.position.z; + + instance_data.compressed_aabb_size[0] = surface_aabb.size.x; + instance_data.compressed_aabb_size[1] = surface_aabb.size.y; + instance_data.compressed_aabb_size[2] = surface_aabb.size.z; + + instance_data.uv_scale[0] = uv_scale.x; + instance_data.uv_scale[1] = uv_scale.y; + instance_data.uv_scale[2] = uv_scale.z; + instance_data.uv_scale[3] = uv_scale.w; + bool cant_repeat = instance_data.flags & INSTANCE_DATA_FLAG_MULTIMESH || inst->mesh_instance.is_valid(); if (prev_surface != nullptr && !cant_repeat && prev_surface->sort.sort_key1 == surface->sort.sort_key1 && prev_surface->sort.sort_key2 == surface->sort.sort_key2 && inst->mirror == prev_surface->owner->mirror && repeats < RenderElementInfo::MAX_REPEATS) { @@ -775,8 +818,9 @@ _FORCE_INLINE_ static uint32_t _indices_to_primitives(RS::PrimitiveType p_primit static const uint32_t subtractor[RS::PRIMITIVE_MAX] = { 0, 0, 1, 0, 1 }; return (p_indices - subtractor[p_primitive]) / divisor[p_primitive]; } -void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, const RenderDataRD *p_render_data, PassMode p_pass_mode, uint32_t p_color_pass_flags = 0, bool p_using_sdfgi, bool p_using_opaque_gi, bool p_append) { +void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, const RenderDataRD *p_render_data, PassMode p_pass_mode, bool p_using_sdfgi, bool p_using_opaque_gi, bool p_using_motion_pass, bool p_append) { RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton(); + uint64_t frame = RSG::rasterizer->get_frame_number(); if (p_render_list == RENDER_LIST_OPAQUE) { scene_state.used_sss = false; @@ -797,7 +841,9 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con if (!p_append) { rl->clear(); if (p_render_list == RENDER_LIST_OPAQUE) { - render_list[RENDER_LIST_ALPHA].clear(); //opaque fills alpha too + // Opaque fills motion and alpha lists. + render_list[RENDER_LIST_MOTION].clear(); + render_list[RENDER_LIST_ALPHA].clear(); } } @@ -827,6 +873,7 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con } bool uses_lightmap = false; bool uses_gi = false; + bool uses_motion = false; float fade_alpha = 1.0; if (inst->fade_near || inst->fade_far) { @@ -914,6 +961,14 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con inst->gi_offset_cache = 0xFFFFFFFF; } } + + if (p_pass_mode == PASS_MODE_COLOR && p_using_motion_pass) { + bool transform_changed = inst->prev_transform_change_frame == frame; + bool has_mesh_instance = inst->mesh_instance.is_valid(); + bool uses_particles = inst->base_flags & INSTANCE_DATA_FLAG_PARTICLES; + bool is_multimesh_with_motion = !uses_particles && (inst->base_flags & INSTANCE_DATA_FLAG_MULTIMESH) && mesh_storage->_multimesh_uses_motion_vectors_offsets(inst->data->base); + uses_motion = transform_changed || has_mesh_instance || uses_particles || is_multimesh_with_motion; + } } inst->flags_cache = flags; @@ -990,11 +1045,18 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con if (!force_alpha && (surf->flags & (GeometryInstanceSurfaceDataCache::FLAG_PASS_DEPTH | GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE))) { rl->add_element(surf); } + if (force_alpha || (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_ALPHA)) { + surf->color_pass_inclusion_mask = COLOR_PASS_FLAG_TRANSPARENT; render_list[RENDER_LIST_ALPHA].add_element(surf); if (uses_gi) { surf->sort.uses_forward_gi = 1; } + } else if (p_using_motion_pass && (uses_motion || (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_MOTION_VECTOR))) { + surf->color_pass_inclusion_mask = COLOR_PASS_FLAG_MOTION_VECTORS; + render_list[RENDER_LIST_MOTION].add_element(surf); + } else { + surf->color_pass_inclusion_mask = 0; } if (uses_lightmap) { @@ -1580,16 +1642,24 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co RENDER_TIMESTAMP("Setup 3D Scene"); + bool using_debug_mvs = get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_MOTION_VECTORS; + bool using_taa = rb->get_use_taa(); + bool using_fsr2 = rb->get_scaling_3d_mode() == RS::VIEWPORT_SCALING_3D_MODE_FSR2; + // check if we need motion vectors - if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_MOTION_VECTORS) { - p_render_data->scene_data->calculate_motion_vectors = true; - } else if (!is_reflection_probe && rb->get_use_taa()) { - p_render_data->scene_data->calculate_motion_vectors = true; + bool motion_vectors_required; + if (using_debug_mvs) { + motion_vectors_required = true; + } else if (!is_reflection_probe && using_taa) { + motion_vectors_required = true; + } else if (!is_reflection_probe && using_fsr2) { + motion_vectors_required = true; } else { - p_render_data->scene_data->calculate_motion_vectors = false; + motion_vectors_required = false; } //p_render_data->scene_data->subsurface_scatter_width = subsurface_scatter_size; + p_render_data->scene_data->calculate_motion_vectors = motion_vectors_required; p_render_data->scene_data->directional_light_count = 0; p_render_data->scene_data->opaque_prepass_threshold = 0.99f; @@ -1607,6 +1677,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co bool using_voxelgi = false; bool reverse_cull = p_render_data->scene_data->cam_transform.basis.determinant() < 0; bool using_ssil = !is_reflection_probe && p_render_data->environment.is_valid() && environment_get_ssil_enabled(p_render_data->environment); + bool using_motion_pass = rb_data.is_valid() && using_fsr2; if (is_reflection_probe) { uint32_t resolution = light_storage->reflection_probe_instance_get_resolution(p_render_data->reflection_probe); @@ -1625,7 +1696,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co } else { screen_size = rb->get_internal_size(); - if (rb->get_use_taa() || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_MOTION_VECTORS) { + if (p_render_data->scene_data->calculate_motion_vectors) { color_pass_flags |= COLOR_PASS_FLAG_MOTION_VECTORS; scene_shader.enable_advanced_shader_group(); } @@ -1663,12 +1734,16 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co _setup_voxelgis(*p_render_data->voxel_gi_instances); _setup_environment(p_render_data, is_reflection_probe, screen_size, !is_reflection_probe, p_default_bg_color, false); - _update_render_base_uniform_set(rb->get_samplers()); //may have changed due to the above (light buffer enlarged, as an example) + _update_render_base_uniform_set(rb->get_samplers()); // May have changed due to the above (light buffer enlarged, as an example). - _fill_render_list(RENDER_LIST_OPAQUE, p_render_data, PASS_MODE_COLOR, color_pass_flags, using_sdfgi, using_sdfgi || using_voxelgi); + _fill_render_list(RENDER_LIST_OPAQUE, p_render_data, PASS_MODE_COLOR, using_sdfgi, using_sdfgi || using_voxelgi, using_motion_pass); render_list[RENDER_LIST_OPAQUE].sort_by_key(); + render_list[RENDER_LIST_MOTION].sort_by_key(); render_list[RENDER_LIST_ALPHA].sort_by_reverse_depth_and_priority(); - _fill_instance_data(RENDER_LIST_OPAQUE, p_render_data->render_info ? p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE] : (int *)nullptr); + + int *render_info = p_render_data->render_info ? p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE] : (int *)nullptr; + _fill_instance_data(RENDER_LIST_OPAQUE, render_info); + _fill_instance_data(RENDER_LIST_MOTION, render_info); _fill_instance_data(RENDER_LIST_ALPHA); RD::get_singleton()->draw_command_end_label(); @@ -1792,9 +1867,9 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co correction.set_depth_correction(true); Projection projection = correction * p_render_data->scene_data->cam_projection; - sky.setup_sky(p_render_data->environment, rb, *p_render_data->lights, p_render_data->camera_attributes, 1, &projection, &eye_offset, p_render_data->scene_data->cam_transform, projection, screen_size, this); + sky.setup_sky(p_render_data->environment, rb, *p_render_data->lights, p_render_data->camera_attributes, 1, &projection, &eye_offset, p_render_data->scene_data->cam_transform, projection, screen_size, Vector2(0.0f, 0.0f), this); } else { - sky.setup_sky(p_render_data->environment, rb, *p_render_data->lights, p_render_data->camera_attributes, p_render_data->scene_data->view_count, p_render_data->scene_data->view_projection, p_render_data->scene_data->view_eye_offset, p_render_data->scene_data->cam_transform, p_render_data->scene_data->cam_projection, screen_size, this); + sky.setup_sky(p_render_data->environment, rb, *p_render_data->lights, p_render_data->camera_attributes, p_render_data->scene_data->view_count, p_render_data->scene_data->view_projection, p_render_data->scene_data->view_eye_offset, p_render_data->scene_data->cam_transform, p_render_data->scene_data->cam_projection, screen_size, p_render_data->scene_data->taa_jitter, this); } sky_energy_multiplier *= bg_energy_multiplier; @@ -1892,37 +1967,71 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co // Shadow pass can change the base uniform set samplers. _update_render_base_uniform_set(rb->get_samplers()); - _setup_environment(p_render_data, is_reflection_probe, screen_size, !is_reflection_probe, p_default_bg_color, true); + _setup_environment(p_render_data, is_reflection_probe, screen_size, !is_reflection_probe, p_default_bg_color, true, using_motion_pass); RENDER_TIMESTAMP("Render Opaque Pass"); RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_OPAQUE, p_render_data, radiance_texture, true); - bool can_continue_color = !scene_state.used_screen_texture && !using_ssr && !using_sss; bool can_continue_depth = !(scene_state.used_depth_texture || scene_state.used_normal_texture) && !using_ssr && !using_sss; { + bool render_motion_pass = !render_list[RENDER_LIST_MOTION].elements.is_empty(); bool will_continue_color = (can_continue_color || draw_sky || draw_sky_fog_only || debug_voxelgis || debug_sdfgi_probes); bool will_continue_depth = (can_continue_depth || draw_sky || draw_sky_fog_only || debug_voxelgis || debug_sdfgi_probes); + RD::FinalAction final_color_action = will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ; + RD::FinalAction final_depth_action = will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ; - Vector<Color> c; { - Color cc = clear_color.srgb_to_linear(); - if (using_separate_specular || rb_data.is_valid()) { - cc.a = 0; //subsurf scatter must be 0 + Vector<Color> c; + { + Color cc = clear_color.srgb_to_linear(); + if (using_separate_specular || rb_data.is_valid()) { + // Effects that rely on separate specular, like subsurface scattering, must clear the alpha to zero. + cc.a = 0; + } + c.push_back(cc); + + if (rb_data.is_valid()) { + c.push_back(Color(0, 0, 0, 0)); // Separate specular. + c.push_back(Color(0, 0, 0, 0)); // Motion vector. Pushed to the clear color vector even if the framebuffer isn't bound. + } } - c.push_back(cc); - if (rb_data.is_valid()) { - c.push_back(Color(0, 0, 0, 0)); // Separate specular - c.push_back(Color(0, 0, 0, 0)); // Motion vectors + uint32_t opaque_color_pass_flags = using_motion_pass ? (color_pass_flags & ~COLOR_PASS_FLAG_MOTION_VECTORS) : color_pass_flags; + RID opaque_framebuffer = using_motion_pass ? rb_data->get_color_pass_fb(opaque_color_pass_flags) : color_framebuffer; + RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, PASS_MODE_COLOR, opaque_color_pass_flags, rb_data.is_null(), p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count); + _render_list_with_threads(&render_list_params, opaque_framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, render_motion_pass ? RD::FINAL_ACTION_CONTINUE : final_color_action, depth_pre_pass ? (continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP) : RD::INITIAL_ACTION_CLEAR, render_motion_pass ? RD::FINAL_ACTION_CONTINUE : final_depth_action, c, 1.0, 0); + } + + RD::get_singleton()->draw_command_end_label(); + + if (using_motion_pass) { + Vector<Color> motion_vector_clear_colors; + motion_vector_clear_colors.push_back(Color(-1, -1, 0, 0)); + RD::get_singleton()->draw_list_begin(rb_data->get_velocity_only_fb(), RD::INITIAL_ACTION_CLEAR, render_motion_pass ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_CONTINUE, motion_vector_clear_colors); + RD::get_singleton()->draw_list_end(); + } + + if (render_motion_pass) { + RD::get_singleton()->draw_command_begin_label("Render Motion Pass"); + + RENDER_TIMESTAMP("Render Motion Pass"); + + rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_MOTION, p_render_data, radiance_texture, true); + + RenderListParameters render_list_params(render_list[RENDER_LIST_MOTION].elements.ptr(), render_list[RENDER_LIST_MOTION].element_info.ptr(), render_list[RENDER_LIST_MOTION].elements.size(), reverse_cull, PASS_MODE_COLOR, color_pass_flags, rb_data.is_null(), p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count); + _render_list_with_threads(&render_list_params, color_framebuffer, RD::INITIAL_ACTION_CONTINUE, final_color_action, RD::INITIAL_ACTION_CONTINUE, final_depth_action); + + if (will_continue_color) { + // Close the motion vectors framebuffer as it'll no longer be used. + RD::get_singleton()->draw_list_begin(rb_data->get_velocity_only_fb(), RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_CONTINUE); + RD::get_singleton()->draw_list_end(); } } - RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, PASS_MODE_COLOR, color_pass_flags, rb_data.is_null(), p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count); - _render_list_with_threads(&render_list_params, color_framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, depth_pre_pass ? (continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP) : RD::INITIAL_ACTION_CLEAR, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0); if (will_continue_color && using_separate_specular) { - // close the specular framebuffer, as it's no longer used + // Close the specular framebuffer as it'll no longer be used. RD::get_singleton()->draw_list_begin(rb_data->get_specular_only_fb(), RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_CONTINUE); RD::get_singleton()->draw_list_end(); } @@ -2052,6 +2161,11 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co { uint32_t transparent_color_pass_flags = (color_pass_flags | COLOR_PASS_FLAG_TRANSPARENT) & ~(COLOR_PASS_FLAG_SEPARATE_SPECULAR); + if (using_motion_pass) { + // Motion vectors on transparent draw calls are not required when using the reactive mask. + transparent_color_pass_flags &= ~(COLOR_PASS_FLAG_MOTION_VECTORS); + } + RID alpha_framebuffer = rb_data.is_valid() ? rb_data->get_color_pass_fb(transparent_color_pass_flags) : color_only_framebuffer; RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), false, PASS_MODE_COLOR, transparent_color_pass_flags, rb_data.is_null(), p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count); _render_list_with_threads(&render_list_params, alpha_framebuffer, can_continue_color ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, can_continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ); @@ -2064,12 +2178,14 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co RD::get_singleton()->draw_command_begin_label("Resolve"); if (rb_data.is_valid() && rb->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) { + bool resolve_velocity_buffer = (using_taa || using_fsr2) && rb->has_velocity_buffer(true); for (uint32_t v = 0; v < rb->get_view_count(); v++) { RD::get_singleton()->texture_resolve_multisample(rb->get_color_msaa(v), rb->get_internal_texture(v)); resolve_effects->resolve_depth(rb->get_depth_msaa(v), rb->get_depth_texture(v), rb->get_internal_size(), texture_multisamples[rb->get_msaa_3d()]); - } - if (taa && rb->get_use_taa()) { - taa->msaa_resolve(rb); + + if (resolve_velocity_buffer) { + RD::get_singleton()->texture_resolve_multisample(rb->get_velocity_buffer(true, v), rb->get_velocity_buffer(false, v)); + } } } @@ -2082,9 +2198,51 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co } RD::get_singleton()->draw_command_end_label(); - if (rb_data.is_valid() && taa && rb->get_use_taa()) { - RENDER_TIMESTAMP("TAA") - taa->process(rb, _render_buffers_get_color_format(), p_render_data->scene_data->z_near, p_render_data->scene_data->z_far); + if (rb_data.is_valid() && (using_fsr2 || using_taa)) { + if (using_fsr2) { + rb->ensure_upscaled(); + rb_data->ensure_fsr2(fsr2_effect); + + RID exposure; + if (RSG::camera_attributes->camera_attributes_uses_auto_exposure(p_render_data->camera_attributes)) { + exposure = luminance->get_current_luminance_buffer(rb); + } + + RENDER_TIMESTAMP("FSR2"); + for (uint32_t v = 0; v < rb->get_view_count(); v++) { + real_t fov = p_render_data->scene_data->cam_projection.get_fov(); + real_t aspect = p_render_data->scene_data->cam_projection.get_aspect(); + real_t fovy = p_render_data->scene_data->cam_projection.get_fovy(fov, aspect); + Vector2 jitter = p_render_data->scene_data->taa_jitter * Vector2(rb->get_internal_size()) * 0.5f; + RendererRD::FSR2Effect::Parameters params; + params.context = rb_data->get_fsr2_context(); + params.internal_size = rb->get_internal_size(); + params.sharpness = CLAMP(1.0f - (rb->get_fsr_sharpness() / 2.0f), 0.0f, 1.0f); + params.color = rb->get_internal_texture(v); + params.depth = rb->get_depth_texture(v); + params.velocity = rb->get_velocity_buffer(false, v); + params.reactive = rb->get_internal_texture_reactive(v); + params.exposure = exposure; + params.output = rb->get_upscaled_texture(v); + params.z_near = p_render_data->scene_data->z_near; + params.z_far = p_render_data->scene_data->z_far; + params.fovy = fovy; + params.jitter = jitter; + params.delta_time = float(time_step); + params.reset_accumulation = false; // FIXME: The engine does not provide a way to reset the accumulation. + + const Projection &prev_proj = p_render_data->scene_data->prev_cam_projection; + const Projection &cur_proj = p_render_data->scene_data->cam_projection; + const Transform3D &prev_transform = p_render_data->scene_data->prev_cam_transform; + const Transform3D &cur_transform = p_render_data->scene_data->cam_transform; + params.reprojection = prev_proj.flipped_y() * prev_transform.affine_inverse() * cur_transform * cur_proj.flipped_y().inverse(); + + fsr2_effect->upscale(params); + } + } else if (using_taa) { + RENDER_TIMESTAMP("TAA"); + taa->process(rb, _render_buffers_get_color_format(), p_render_data->scene_data->z_near, p_render_data->scene_data->z_far); + } } if (rb_data.is_valid()) { @@ -2357,7 +2515,7 @@ void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const Page render_data.instances = &p_instances; render_data.render_info = p_render_info; - _setup_environment(&render_data, true, Vector2(1, 1), !p_flip_y, Color(), false, p_use_pancake, shadow_pass_index); + _setup_environment(&render_data, true, Vector2(1, 1), !p_flip_y, Color(), false, false, p_use_pancake, shadow_pass_index); if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_DISABLE_LOD) { scene_data.screen_mesh_lod_threshold = 0.0; @@ -2368,7 +2526,7 @@ void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const Page PassMode pass_mode = p_use_dp ? PASS_MODE_SHADOW_DP : PASS_MODE_SHADOW; uint32_t render_list_from = render_list[RENDER_LIST_SECONDARY].elements.size(); - _fill_render_list(RENDER_LIST_SECONDARY, &render_data, pass_mode, 0, false, false, true); + _fill_render_list(RENDER_LIST_SECONDARY, &render_data, pass_mode, false, false, false, true); uint32_t render_list_size = render_list[RENDER_LIST_SECONDARY].elements.size() - render_list_from; render_list[RENDER_LIST_SECONDARY].sort_by_key_range(render_list_from, render_list_size); _fill_instance_data(RENDER_LIST_SECONDARY, p_render_info ? p_render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW] : (int *)nullptr, render_list_from, render_list_size, false); @@ -2453,7 +2611,7 @@ void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, con _update_render_base_uniform_set(RendererRD::MaterialStorage::get_singleton()->samplers_rd_get_default()); - _setup_environment(&render_data, true, Vector2(1, 1), true, Color(), false, false); + _setup_environment(&render_data, true, Vector2(1, 1), true, Color(), false, false, false); PassMode pass_mode = PASS_MODE_SHADOW; @@ -3475,6 +3633,10 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_PARTICLE_TRAILS; } + if (p_material->shader_data->is_animated()) { + flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_MOTION_VECTOR; + } + SceneShaderForwardClustered::MaterialData *material_shadow = nullptr; void *surface_shadow = nullptr; if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_position && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_prepass_alpha && !p_material->shader_data->uses_alpha_clip && !p_material->shader_data->uses_alpha_antialiasing && p_material->shader_data->cull_mode == SceneShaderForwardClustered::ShaderData::CULL_BACK && !p_material->shader_data->uses_point_size) { @@ -3576,7 +3738,7 @@ void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForw m_src = scene_shader.default_material; } - ERR_FAIL_COND(!material); + ERR_FAIL_NULL(material); _geometry_instance_add_surface_with_material_chain(ginstance, p_surface, material, m_src, p_mesh); @@ -3802,7 +3964,7 @@ RenderGeometryInstance *RenderForwardClustered::geometry_instance_create(RID p_b return ginstance; } -void RenderForwardClustered::GeometryInstanceForwardClustered::set_transform(const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabbb) { +void RenderForwardClustered::GeometryInstanceForwardClustered::set_transform(const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) { uint64_t frame = RSG::rasterizer->get_frame_number(); if (frame != prev_transform_change_frame) { prev_transform = transform; @@ -3810,7 +3972,7 @@ void RenderForwardClustered::GeometryInstanceForwardClustered::set_transform(con prev_transform_dirty = true; } - RenderGeometryInstanceBase::set_transform(p_transform, p_aabb, p_transformed_aabbb); + RenderGeometryInstanceBase::set_transform(p_transform, p_aabb, p_transformed_aabb); } void RenderForwardClustered::GeometryInstanceForwardClustered::set_use_lightmap(RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) { @@ -3839,7 +4001,7 @@ void RenderForwardClustered::GeometryInstanceForwardClustered::set_lightmap_capt void RenderForwardClustered::geometry_instance_free(RenderGeometryInstance *p_geometry_instance) { GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); + ERR_FAIL_NULL(ginstance); if (ginstance->lightmap_sh != nullptr) { geometry_instance_lightmap_sh.free(ginstance->lightmap_sh); } @@ -3982,6 +4144,7 @@ RenderForwardClustered::RenderForwardClustered() { resolve_effects = memnew(RendererRD::Resolve()); taa = memnew(RendererRD::TAA); + fsr2_effect = memnew(RendererRD::FSR2Effect); ss_effects = memnew(RendererRD::SSEffects); } @@ -3996,6 +4159,11 @@ RenderForwardClustered::~RenderForwardClustered() { taa = nullptr; } + if (fsr2_effect) { + memdelete(fsr2_effect); + fsr2_effect = nullptr; + } + if (resolve_effects != nullptr) { memdelete(resolve_effects); resolve_effects = nullptr; diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h index 39584bae63..46deb30cde 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h @@ -33,6 +33,7 @@ #include "core/templates/paged_allocator.h" #include "servers/rendering/renderer_rd/cluster_builder_rd.h" +#include "servers/rendering/renderer_rd/effects/fsr2.h" #include "servers/rendering/renderer_rd/effects/resolve.h" #include "servers/rendering/renderer_rd/effects/ss_effects.h" #include "servers/rendering/renderer_rd/effects/taa.h" @@ -84,6 +85,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { enum RenderListType { RENDER_LIST_OPAQUE, //used for opaque objects + RENDER_LIST_MOTION, //used for opaque objects with motion RENDER_LIST_ALPHA, //used for transparent objects RENDER_LIST_SECONDARY, //used for shadows and other objects RENDER_LIST_MAX @@ -100,6 +102,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { private: RenderSceneBuffersRD *render_buffers = nullptr; + RendererRD::FSR2Context *fsr2_context = nullptr; public: ClusterBuilderRD *cluster_builder = nullptr; @@ -140,10 +143,14 @@ class RenderForwardClustered : public RendererSceneRenderRD { RID get_voxelgi(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_VOXEL_GI, p_layer, 0); } RID get_voxelgi_msaa(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_VOXEL_GI_MSAA, p_layer, 0); } + void ensure_fsr2(RendererRD::FSR2Effect *p_effect); + RendererRD::FSR2Context *get_fsr2_context() const { return fsr2_context; } + RID get_color_only_fb(); RID get_color_pass_fb(uint32_t p_color_pass_flags); RID get_depth_fb(DepthFrameBufferType p_type = DEPTH_FB); RID get_specular_only_fb(); + RID get_velocity_only_fb(); virtual void configure(RenderSceneBuffersRD *p_render_buffers) override; virtual void free_data() override; @@ -291,6 +298,9 @@ class RenderForwardClustered : public RendererSceneRenderRD { uint32_t gi_offset; //GI information when using lightmapping (VCT or lightmap index) uint32_t layer_mask; float lightmap_uv_scale[4]; + float compressed_aabb_position[4]; + float compressed_aabb_size[4]; + float uv_scale[4]; }; UBO ubo; @@ -345,7 +355,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { static RenderForwardClustered *singleton; - void _setup_environment(const RenderDataRD *p_render_data, bool p_no_fog, const Size2i &p_screen_size, bool p_flip_y, const Color &p_default_bg_color, bool p_opaque_render_buffers = false, bool p_pancake_shadows = false, int p_index = 0); + void _setup_environment(const RenderDataRD *p_render_data, bool p_no_fog, const Size2i &p_screen_size, bool p_flip_y, const Color &p_default_bg_color, bool p_opaque_render_buffers = false, bool p_apply_alpha_multiplier = false, bool p_pancake_shadows = false, int p_index = 0); void _setup_voxelgis(const PagedArray<RID> &p_voxelgis); void _setup_lightmaps(const RenderDataRD *p_render_data, const PagedArray<RID> &p_lightmaps, const Transform3D &p_cam_transform); @@ -372,7 +382,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { void _update_instance_data_buffer(RenderListType p_render_list); void _fill_instance_data(RenderListType p_render_list, int *p_render_info = nullptr, uint32_t p_offset = 0, int32_t p_max_elements = -1, bool p_update_buffer = true); - void _fill_render_list(RenderListType p_render_list, const RenderDataRD *p_render_data, PassMode p_pass_mode, uint32_t p_color_pass_flags, bool p_using_sdfgi = false, bool p_using_opaque_gi = false, bool p_append = false); + void _fill_render_list(RenderListType p_render_list, const RenderDataRD *p_render_data, PassMode p_pass_mode, bool p_using_sdfgi = false, bool p_using_opaque_gi = false, bool p_using_motion_pass = false, bool p_append = false); HashMap<Size2i, RID> sdfgi_framebuffer_size_cache; @@ -397,6 +407,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { FLAG_USES_NORMAL_TEXTURE = 16384, FLAG_USES_DOUBLE_SIDED_SHADOWS = 32768, FLAG_USES_PARTICLE_TRAILS = 65536, + FLAG_USES_MOTION_VECTOR = 131072, }; union { @@ -424,6 +435,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { RS::PrimitiveType primitive = RS::PRIMITIVE_MAX; uint32_t flags = 0; uint32_t surface_index = 0; + uint32_t color_pass_inclusion_mask = 0; void *surface = nullptr; RID material_uniform_set; @@ -470,7 +482,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { virtual void _mark_dirty() override; - virtual void set_transform(const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabbb) override; + virtual void set_transform(const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) override; virtual void set_use_lightmap(RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override; virtual void set_lightmap_capture(const Color *p_sh9) override; @@ -563,6 +575,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { RendererRD::Resolve *resolve_effects = nullptr; RendererRD::TAA *taa = nullptr; + RendererRD::FSR2Effect *fsr2_effect = nullptr; RendererRD::SSEffects *ss_effects = nullptr; /* Cluster builder */ diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp index 509072bbec..7e8dc358d0 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp @@ -412,7 +412,7 @@ SceneShaderForwardClustered::ShaderData::ShaderData() : SceneShaderForwardClustered::ShaderData::~ShaderData() { SceneShaderForwardClustered *shader_singleton = (SceneShaderForwardClustered *)SceneShaderForwardClustered::singleton; - ERR_FAIL_COND(!shader_singleton); + ERR_FAIL_NULL(shader_singleton); //pipeline variants will clear themselves if shader is gone if (version.is_valid()) { shader_singleton->shader.version_free(version); diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h index 761b74defa..0739cd9f86 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h @@ -142,7 +142,7 @@ public: bool valid = false; RID version; - uint32_t vertex_input_mask = 0; + uint64_t vertex_input_mask = 0; PipelineCacheRD pipelines[CULL_VARIANT_MAX][RS::PRIMITIVE_MAX][PIPELINE_VERSION_MAX]; PipelineCacheRD color_pipelines[CULL_VARIANT_MAX][RS::PRIMITIVE_MAX][PIPELINE_COLOR_PASS_FLAG_COUNT]; diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp index d5f81da29f..a032cf44b6 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -68,53 +68,40 @@ void RenderForwardMobile::ForwardIDStorageMobile::map_forward_id(RendererRD::For forward_id_allocators[p_type].map[p_id] = p_index; } -void RenderForwardMobile::ForwardIDStorageMobile::fill_push_constant_instance_indices(GeometryInstanceForwardMobile::PushConstant *p_push_constant, uint32_t &spec_constants, const GeometryInstanceForwardMobile *p_instance) { - // first zero out our indices +void RenderForwardMobile::fill_push_constant_instance_indices(SceneState::InstanceData *p_instance_data, const GeometryInstanceForwardMobile *p_instance) { + // First zero out our indices. - p_push_constant->omni_lights[0] = 0xFFFFFFFF; - p_push_constant->omni_lights[1] = 0xFFFFFFFF; + p_instance_data->omni_lights[0] = 0xFFFFFFFF; + p_instance_data->omni_lights[1] = 0xFFFFFFFF; - p_push_constant->spot_lights[0] = 0xFFFFFFFF; - p_push_constant->spot_lights[1] = 0xFFFFFFFF; + p_instance_data->spot_lights[0] = 0xFFFFFFFF; + p_instance_data->spot_lights[1] = 0xFFFFFFFF; - p_push_constant->decals[0] = 0xFFFFFFFF; - p_push_constant->decals[1] = 0xFFFFFFFF; + p_instance_data->decals[0] = 0xFFFFFFFF; + p_instance_data->decals[1] = 0xFFFFFFFF; - p_push_constant->reflection_probes[0] = 0xFFFFFFFF; - p_push_constant->reflection_probes[1] = 0xFFFFFFFF; - - if (p_instance->omni_light_count == 0) { - spec_constants |= 1 << SPEC_CONSTANT_DISABLE_OMNI_LIGHTS; - } - if (p_instance->spot_light_count == 0) { - spec_constants |= 1 << SPEC_CONSTANT_DISABLE_SPOT_LIGHTS; - } - if (p_instance->reflection_probe_count == 0) { - spec_constants |= 1 << SPEC_CONSTANT_DISABLE_REFLECTION_PROBES; - } - if (p_instance->decals_count == 0) { - spec_constants |= 1 << SPEC_CONSTANT_DISABLE_DECALS; - } + p_instance_data->reflection_probes[0] = 0xFFFFFFFF; + p_instance_data->reflection_probes[1] = 0xFFFFFFFF; for (uint32_t i = 0; i < MAX_RDL_CULL; i++) { uint32_t ofs = i < 4 ? 0 : 1; uint32_t shift = (i & 0x3) << 3; uint32_t mask = ~(0xFF << shift); if (i < p_instance->omni_light_count) { - p_push_constant->omni_lights[ofs] &= mask; - p_push_constant->omni_lights[ofs] |= uint32_t(forward_id_allocators[RendererRD::FORWARD_ID_TYPE_OMNI_LIGHT].map[p_instance->omni_lights[i]]) << shift; + p_instance_data->omni_lights[ofs] &= mask; + p_instance_data->omni_lights[ofs] |= uint32_t(forward_id_storage_mobile->forward_id_allocators[RendererRD::FORWARD_ID_TYPE_OMNI_LIGHT].map[p_instance->omni_lights[i]]) << shift; } if (i < p_instance->spot_light_count) { - p_push_constant->spot_lights[ofs] &= mask; - p_push_constant->spot_lights[ofs] |= uint32_t(forward_id_allocators[RendererRD::FORWARD_ID_TYPE_SPOT_LIGHT].map[p_instance->spot_lights[i]]) << shift; + p_instance_data->spot_lights[ofs] &= mask; + p_instance_data->spot_lights[ofs] |= uint32_t(forward_id_storage_mobile->forward_id_allocators[RendererRD::FORWARD_ID_TYPE_SPOT_LIGHT].map[p_instance->spot_lights[i]]) << shift; } if (i < p_instance->decals_count) { - p_push_constant->decals[ofs] &= mask; - p_push_constant->decals[ofs] |= uint32_t(forward_id_allocators[RendererRD::FORWARD_ID_TYPE_DECAL].map[p_instance->decals[i]]) << shift; + p_instance_data->decals[ofs] &= mask; + p_instance_data->decals[ofs] |= uint32_t(forward_id_storage_mobile->forward_id_allocators[RendererRD::FORWARD_ID_TYPE_DECAL].map[p_instance->decals[i]]) << shift; } if (i < p_instance->reflection_probe_count) { - p_push_constant->reflection_probes[ofs] &= mask; - p_push_constant->reflection_probes[ofs] |= uint32_t(forward_id_allocators[RendererRD::FORWARD_ID_TYPE_REFLECTION_PROBE].map[p_instance->reflection_probes[i]]) << shift; + p_instance_data->reflection_probes[ofs] &= mask; + p_instance_data->reflection_probes[ofs] |= uint32_t(forward_id_storage_mobile->forward_id_allocators[RendererRD::FORWARD_ID_TYPE_REFLECTION_PROBE].map[p_instance->reflection_probes[i]]) << shift; } } } @@ -367,6 +354,18 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ } { + RD::Uniform u; + u.binding = 1; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + RID instance_buffer = scene_state.instance_buffer[p_render_list]; + if (instance_buffer == RID()) { + instance_buffer = scene_shader.default_vec4_xform_buffer; // Any buffer will do since its not used. + } + u.append_id(instance_buffer); + uniforms.push_back(u); + } + + { RID radiance_texture; if (p_radiance_texture.is_valid()) { radiance_texture = p_radiance_texture; @@ -461,15 +460,6 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ uniforms.push_back(u); } - - { - RD::Uniform u; - u.binding = 8; - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - RID cb = p_cluster_buffer.is_valid() ? p_cluster_buffer : default_vec4_xform_buffer; - u.append_id(cb); - uniforms.push_back(u); - } */ { @@ -682,8 +672,8 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color _fill_render_list(RENDER_LIST_OPAQUE, p_render_data, PASS_MODE_COLOR); render_list[RENDER_LIST_OPAQUE].sort_by_key(); render_list[RENDER_LIST_ALPHA].sort_by_reverse_depth_and_priority(); - _fill_element_info(RENDER_LIST_OPAQUE); - _fill_element_info(RENDER_LIST_ALPHA); + _fill_instance_data(RENDER_LIST_OPAQUE); + _fill_instance_data(RENDER_LIST_ALPHA); if (p_render_data->render_info) { p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME] = p_render_data->instances->size(); @@ -823,9 +813,9 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color correction.set_depth_correction(true); Projection projection = correction * p_render_data->scene_data->cam_projection; - sky.setup_sky(p_render_data->environment, p_render_data->render_buffers, *p_render_data->lights, p_render_data->camera_attributes, 1, &projection, &eye_offset, p_render_data->scene_data->cam_transform, projection, screen_size, this); + sky.setup_sky(p_render_data->environment, p_render_data->render_buffers, *p_render_data->lights, p_render_data->camera_attributes, 1, &projection, &eye_offset, p_render_data->scene_data->cam_transform, projection, screen_size, Vector2(0.0f, 0.0f), this); } else { - sky.setup_sky(p_render_data->environment, p_render_data->render_buffers, *p_render_data->lights, p_render_data->camera_attributes, p_render_data->scene_data->view_count, p_render_data->scene_data->view_projection, p_render_data->scene_data->view_eye_offset, p_render_data->scene_data->cam_transform, p_render_data->scene_data->cam_projection, screen_size, this); + sky.setup_sky(p_render_data->environment, p_render_data->render_buffers, *p_render_data->lights, p_render_data->camera_attributes, p_render_data->scene_data->view_count, p_render_data->scene_data->view_projection, p_render_data->scene_data->view_eye_offset, p_render_data->scene_data->cam_transform, p_render_data->scene_data->cam_projection, screen_size, p_render_data->scene_data->taa_jitter, this); } sky_energy_multiplier *= bg_energy_multiplier; @@ -1290,7 +1280,7 @@ void RenderForwardMobile::_render_shadow_append(RID p_framebuffer, const PagedAr _fill_render_list(RENDER_LIST_SECONDARY, &render_data, pass_mode, true); uint32_t render_list_size = render_list[RENDER_LIST_SECONDARY].elements.size() - render_list_from; render_list[RENDER_LIST_SECONDARY].sort_by_key_range(render_list_from, render_list_size); - _fill_element_info(RENDER_LIST_SECONDARY, render_list_from, render_list_size); + _fill_instance_data(RENDER_LIST_SECONDARY, render_list_from, render_list_size); { //regular forward for now @@ -1373,7 +1363,7 @@ void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, c PassMode pass_mode = PASS_MODE_DEPTH_MATERIAL; _fill_render_list(RENDER_LIST_SECONDARY, &render_data, pass_mode); render_list[RENDER_LIST_SECONDARY].sort_by_key(); - _fill_element_info(RENDER_LIST_SECONDARY); + _fill_instance_data(RENDER_LIST_SECONDARY); RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_SECONDARY, nullptr, RID()); @@ -1418,7 +1408,7 @@ void RenderForwardMobile::_render_uv2(const PagedArray<RenderGeometryInstance *> PassMode pass_mode = PASS_MODE_DEPTH_MATERIAL; _fill_render_list(RENDER_LIST_SECONDARY, &render_data, pass_mode); render_list[RENDER_LIST_SECONDARY].sort_by_key(); - _fill_element_info(RENDER_LIST_SECONDARY); + _fill_instance_data(RENDER_LIST_SECONDARY); RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_SECONDARY, nullptr, RID()); @@ -1499,7 +1489,7 @@ void RenderForwardMobile::_render_particle_collider_heightfield(RID p_fb, const _fill_render_list(RENDER_LIST_SECONDARY, &render_data, pass_mode); render_list[RENDER_LIST_SECONDARY].sort_by_key(); - _fill_element_info(RENDER_LIST_SECONDARY); + _fill_instance_data(RENDER_LIST_SECONDARY); RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_SECONDARY, nullptr, RID()); @@ -1691,6 +1681,91 @@ RID RenderForwardMobile::_render_buffers_get_velocity_texture(Ref<RenderSceneBuf return RID(); } +void RenderForwardMobile::_update_instance_data_buffer(RenderListType p_render_list) { + if (scene_state.instance_data[p_render_list].size() > 0) { + if (scene_state.instance_buffer[p_render_list] == RID() || scene_state.instance_buffer_size[p_render_list] < scene_state.instance_data[p_render_list].size()) { + if (scene_state.instance_buffer[p_render_list] != RID()) { + RD::get_singleton()->free(scene_state.instance_buffer[p_render_list]); + } + uint32_t new_size = nearest_power_of_2_templated(MAX(uint64_t(INSTANCE_DATA_BUFFER_MIN_SIZE), scene_state.instance_data[p_render_list].size())); + scene_state.instance_buffer[p_render_list] = RD::get_singleton()->storage_buffer_create(new_size * sizeof(SceneState::InstanceData)); + scene_state.instance_buffer_size[p_render_list] = new_size; + } + RD::get_singleton()->buffer_update(scene_state.instance_buffer[p_render_list], 0, sizeof(SceneState::InstanceData) * scene_state.instance_data[p_render_list].size(), scene_state.instance_data[p_render_list].ptr(), RD::BARRIER_MASK_RASTER); + } +} + +void RenderForwardMobile::_fill_instance_data(RenderListType p_render_list, uint32_t p_offset, int32_t p_max_elements, bool p_update_buffer) { + RenderList *rl = &render_list[p_render_list]; + uint32_t element_total = p_max_elements >= 0 ? uint32_t(p_max_elements) : rl->elements.size(); + + scene_state.instance_data[p_render_list].resize(p_offset + element_total); + rl->element_info.resize(p_offset + element_total); + + for (uint32_t i = 0; i < element_total; i++) { + GeometryInstanceSurfaceDataCache *surface = rl->elements[i + p_offset]; + GeometryInstanceForwardMobile *inst = surface->owner; + + SceneState::InstanceData &instance_data = scene_state.instance_data[p_render_list][i + p_offset]; + + if (inst->store_transform_cache) { + RendererRD::MaterialStorage::store_transform(inst->transform, instance_data.transform); + +#ifdef REAL_T_IS_DOUBLE + // Split the origin into two components, the float approximation and the missing precision. + // In the shader we will combine these back together to restore the lost precision. + RendererRD::MaterialStorage::split_double(inst->transform.origin.x, &instance_data.transform[12], &instance_data.transform[3]); + RendererRD::MaterialStorage::split_double(inst->transform.origin.y, &instance_data.transform[13], &instance_data.transform[7]); + RendererRD::MaterialStorage::split_double(inst->transform.origin.z, &instance_data.transform[14], &instance_data.transform[11]); +#endif + } else { + RendererRD::MaterialStorage::store_transform(Transform3D(), instance_data.transform); + } + + instance_data.flags = inst->flags_cache; + instance_data.gi_offset = inst->gi_offset_cache; + instance_data.layer_mask = inst->layer_mask; + instance_data.instance_uniforms_ofs = uint32_t(inst->shader_uniforms_offset); + instance_data.lightmap_uv_scale[0] = inst->lightmap_uv_scale.position.x; + instance_data.lightmap_uv_scale[1] = inst->lightmap_uv_scale.position.y; + instance_data.lightmap_uv_scale[2] = inst->lightmap_uv_scale.size.x; + instance_data.lightmap_uv_scale[3] = inst->lightmap_uv_scale.size.y; + + AABB surface_aabb = AABB(Vector3(0.0, 0.0, 0.0), Vector3(1.0, 1.0, 1.0)); + uint64_t format = RendererRD::MeshStorage::get_singleton()->mesh_surface_get_format(surface->surface); + Vector4 uv_scale = Vector4(0.0, 0.0, 0.0, 0.0); + + if (format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES) { + surface_aabb = RendererRD::MeshStorage::get_singleton()->mesh_surface_get_aabb(surface->surface); + uv_scale = RendererRD::MeshStorage::get_singleton()->mesh_surface_get_uv_scale(surface->surface); + } + + fill_push_constant_instance_indices(&instance_data, inst); + + instance_data.compressed_aabb_position[0] = surface_aabb.position.x; + instance_data.compressed_aabb_position[1] = surface_aabb.position.y; + instance_data.compressed_aabb_position[2] = surface_aabb.position.z; + + instance_data.compressed_aabb_size[0] = surface_aabb.size.x; + instance_data.compressed_aabb_size[1] = surface_aabb.size.y; + instance_data.compressed_aabb_size[2] = surface_aabb.size.z; + + instance_data.uv_scale[0] = uv_scale.x; + instance_data.uv_scale[1] = uv_scale.y; + instance_data.uv_scale[2] = uv_scale.z; + instance_data.uv_scale[3] = uv_scale.w; + + RenderElementInfo &element_info = rl->element_info[p_offset + i]; + + element_info.lod_index = surface->lod_index; + element_info.uses_lightmap = surface->sort.uses_lightmap; + } + + if (p_update_buffer) { + _update_instance_data_buffer(p_render_list); + } +} + _FORCE_INLINE_ static uint32_t _indices_to_primitives(RS::PrimitiveType p_primitive, uint32_t p_indices) { static const uint32_t divisor[RS::PRIMITIVE_MAX] = { 1, 2, 1, 3, 1 }; static const uint32_t subtractor[RS::PRIMITIVE_MAX] = { 0, 0, 1, 0, 1 }; @@ -1908,22 +1983,7 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data, } } - p_render_data->scene_data->update_ubo(scene_state.uniform_buffers[p_index], get_debug_draw_mode(), env, reflection_probe_instance, p_render_data->camera_attributes, p_flip_y, p_pancake_shadows, p_screen_size, p_default_bg_color, _render_buffers_get_luminance_multiplier(), p_opaque_render_buffers); -} - -void RenderForwardMobile::_fill_element_info(RenderListType p_render_list, uint32_t p_offset, int32_t p_max_elements) { - RenderList *rl = &render_list[p_render_list]; - uint32_t element_total = p_max_elements >= 0 ? uint32_t(p_max_elements) : rl->elements.size(); - - rl->element_info.resize(p_offset + element_total); - - for (uint32_t i = 0; i < element_total; i++) { - GeometryInstanceSurfaceDataCache *surface = rl->elements[i + p_offset]; - RenderElementInfo &element_info = rl->element_info[p_offset + i]; - - element_info.lod_index = surface->lod_index; - element_info.uses_lightmap = surface->sort.uses_lightmap; - } + p_render_data->scene_data->update_ubo(scene_state.uniform_buffers[p_index], get_debug_draw_mode(), env, reflection_probe_instance, p_render_data->camera_attributes, p_flip_y, p_pancake_shadows, p_screen_size, p_default_bg_color, _render_buffers_get_luminance_multiplier(), p_opaque_render_buffers, false); } /// RENDERING /// @@ -2011,39 +2071,17 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr uint32_t base_spec_constants = p_params->spec_constant_base_flags; - // GeometryInstanceForwardMobile::PushConstant push_constant = inst->push_constant; - GeometryInstanceForwardMobile::PushConstant push_constant; - - if (inst->store_transform_cache) { - RendererRD::MaterialStorage::store_transform(inst->transform, push_constant.transform); + SceneState::PushConstant push_constant; + push_constant.base_index = i + p_params->element_offset; -#ifdef REAL_T_IS_DOUBLE - // Split the origin into two components, the float approximation and the missing precision - // In the shader we will combine these back together to restore the lost precision. - RendererRD::MaterialStorage::split_double(inst->transform.origin.x, &push_constant.transform[12], &push_constant.transform[3]); - RendererRD::MaterialStorage::split_double(inst->transform.origin.y, &push_constant.transform[13], &push_constant.transform[7]); - RendererRD::MaterialStorage::split_double(inst->transform.origin.z, &push_constant.transform[14], &push_constant.transform[11]); -#endif + if constexpr (p_pass_mode == PASS_MODE_DEPTH_MATERIAL) { + push_constant.uv_offset[0] = p_params->uv_offset.x; + push_constant.uv_offset[1] = p_params->uv_offset.y; } else { - RendererRD::MaterialStorage::store_transform(Transform3D(), push_constant.transform); + push_constant.uv_offset[0] = 0.0; + push_constant.uv_offset[1] = 0.0; } - push_constant.flags = inst->flags_cache; - push_constant.gi_offset = inst->gi_offset_cache; - push_constant.layer_mask = inst->layer_mask; - push_constant.instance_uniforms_ofs = uint32_t(inst->shader_uniforms_offset); - - if (p_params->pass_mode == PASS_MODE_DEPTH_MATERIAL) { - // abuse lightmap_uv_scale[0] here, should not be needed here - push_constant.lightmap_uv_scale[0] = p_params->uv_offset.x; - push_constant.lightmap_uv_scale[1] = p_params->uv_offset.y; - } else { - push_constant.lightmap_uv_scale[0] = inst->lightmap_uv_scale.position.x; - push_constant.lightmap_uv_scale[1] = inst->lightmap_uv_scale.position.y; - push_constant.lightmap_uv_scale[2] = inst->lightmap_uv_scale.size.x; - push_constant.lightmap_uv_scale[3] = inst->lightmap_uv_scale.size.y; - }; - RID material_uniform_set; SceneShaderForwardMobile::ShaderData *shader; void *mesh_surface; @@ -2060,7 +2098,19 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr if (inst->use_soft_shadow) { base_spec_constants |= 1 << SPEC_CONSTANT_USING_SOFT_SHADOWS; } - forward_id_storage_mobile->fill_push_constant_instance_indices(&push_constant, base_spec_constants, inst); + + if (inst->omni_light_count == 0) { + base_spec_constants |= 1 << SPEC_CONSTANT_DISABLE_OMNI_LIGHTS; + } + if (inst->spot_light_count == 0) { + base_spec_constants |= 1 << SPEC_CONSTANT_DISABLE_SPOT_LIGHTS; + } + if (inst->reflection_probe_count == 0) { + base_spec_constants |= 1 << SPEC_CONSTANT_DISABLE_REFLECTION_PROBES; + } + if (inst->decals_count == 0) { + base_spec_constants |= 1 << SPEC_CONSTANT_DISABLE_DECALS; + } #ifdef DEBUG_ENABLED if (unlikely(get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_LIGHTING)) { @@ -2184,7 +2234,7 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr prev_material_uniform_set = material_uniform_set; } - RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(GeometryInstanceForwardMobile::PushConstant)); + RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(SceneState::PushConstant)); uint32_t instance_count = surf->owner->instance_count > 1 ? surf->owner->instance_count : 1; if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_PARTICLE_TRAILS) { @@ -2246,7 +2296,7 @@ void RenderForwardMobile::GeometryInstanceForwardMobile::set_lightmap_capture(co void RenderForwardMobile::geometry_instance_free(RenderGeometryInstance *p_geometry_instance) { GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); + ERR_FAIL_NULL(ginstance); if (ginstance->lightmap_sh != nullptr) { geometry_instance_lightmap_sh.free(ginstance->lightmap_sh); } @@ -2473,7 +2523,7 @@ void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForward m_src = scene_shader.default_material; } - ERR_FAIL_COND(!material); + ERR_FAIL_NULL(material); _geometry_instance_add_surface_with_material_chain(ginstance, p_surface, material, m_src, p_mesh); diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h index 65723e5aa5..50bf83b612 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h @@ -202,9 +202,9 @@ private: void _update_render_base_uniform_set(const RendererRD::MaterialStorage::Samplers &p_samplers); + void _update_instance_data_buffer(RenderListType p_render_list); + void _fill_instance_data(RenderListType p_render_list, uint32_t p_offset = 0, int32_t p_max_elements = -1, bool p_update_buffer = true); void _fill_render_list(RenderListType p_render_list, const RenderDataRD *p_render_data, PassMode p_pass_mode, bool p_append = false); - void _fill_element_info(RenderListType p_render_list, uint32_t p_offset = 0, int32_t p_max_elements = -1); - // void _update_instance_data_buffer(RenderListType p_render_list); void _setup_environment(const RenderDataRD *p_render_data, bool p_no_fog, const Size2i &p_screen_size, bool p_flip_y, const Color &p_default_bg_color, bool p_opaque_render_buffers = false, bool p_pancake_shadows = false, int p_index = 0); void _setup_lightmaps(const RenderDataRD *p_render_data, const PagedArray<RID> &p_lightmaps, const Transform3D &p_cam_transform); @@ -229,6 +229,32 @@ private: struct SceneState { LocalVector<RID> uniform_buffers; + struct PushConstant { + float uv_offset[2]; + uint32_t base_index; + uint32_t pad; + }; + + struct InstanceData { + float transform[16]; + uint32_t flags; + uint32_t instance_uniforms_ofs; // Base offset in global buffer for instance variables. + uint32_t gi_offset; // GI information when using lightmapping (VCT or lightmap index). + uint32_t layer_mask = 1; + float lightmap_uv_scale[4]; // Doubles as uv_offset when needed. + uint32_t reflection_probes[2]; // Packed reflection probes. + uint32_t omni_lights[2]; // Packed omni lights. + uint32_t spot_lights[2]; // Packed spot lights. + uint32_t decals[2]; // Packed spot lights. + float compressed_aabb_position[4]; + float compressed_aabb_size[4]; + float uv_scale[4]; + }; + + RID instance_buffer[RENDER_LIST_MAX]; + uint32_t instance_buffer_size[RENDER_LIST_MAX] = { 0, 0, 0 }; + LocalVector<InstanceData> instance_data[RENDER_LIST_MAX]; + // !BAS! We need to change lightmaps, we're not going to do this with a buffer but pushing the used lightmap in LightmapData lightmaps[MAX_LIGHTMAPS]; RID lightmap_ids[MAX_LIGHTMAPS]; @@ -447,27 +473,11 @@ protected: class GeometryInstanceForwardMobile : public RenderGeometryInstanceBase { public: - // this structure maps to our push constant in our shader and is populated right before our draw call - struct PushConstant { - float transform[16]; - uint32_t flags; - uint32_t instance_uniforms_ofs; //base offset in global buffer for instance variables - uint32_t gi_offset; //GI information when using lightmapping (VCT or lightmap index) - uint32_t layer_mask = 1; - float lightmap_uv_scale[4]; // doubles as uv_offset when needed - uint32_t reflection_probes[2]; // packed reflection probes - uint32_t omni_lights[2]; // packed omni lights - uint32_t spot_lights[2]; // packed spot lights - uint32_t decals[2]; // packed spot lights - }; - - // PushConstant push_constant; // we populate this from our instance data - //used during rendering RID transforms_uniform_set; bool use_projector = false; bool use_soft_shadow = false; - bool store_transform_cache = true; // if true we copy our transform into our PushConstant, if false we use our transforms UBO and clear our PushConstants transform + bool store_transform_cache = true; // If true we copy our transform into our per-draw buffer, if false we use our transforms UBO and clear our per-draw transform. uint32_t instance_count = 0; uint32_t trail_steps = 1; @@ -534,12 +544,12 @@ protected: virtual void free_forward_id(RendererRD::ForwardIDType p_type, RendererRD::ForwardID p_id) override; virtual void map_forward_id(RendererRD::ForwardIDType p_type, RendererRD::ForwardID p_id, uint32_t p_index) override; virtual bool uses_forward_ids() const override { return true; } - - void fill_push_constant_instance_indices(GeometryInstanceForwardMobile::PushConstant *p_push_constant, uint32_t &spec_constants, const GeometryInstanceForwardMobile *p_instance); }; ForwardIDStorageMobile *forward_id_storage_mobile = nullptr; + void fill_push_constant_instance_indices(SceneState::InstanceData *p_instance_data, const GeometryInstanceForwardMobile *p_instance); + virtual RendererRD::ForwardIDStorage *create_forward_id_storage() override { forward_id_storage_mobile = memnew(ForwardIDStorageMobile); return forward_id_storage_mobile; diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp index ffbe7f7e59..311ca72c75 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp @@ -364,7 +364,7 @@ SceneShaderForwardMobile::ShaderData::ShaderData() : SceneShaderForwardMobile::ShaderData::~ShaderData() { SceneShaderForwardMobile *shader_singleton = (SceneShaderForwardMobile *)SceneShaderForwardMobile::singleton; - ERR_FAIL_COND(!shader_singleton); + ERR_FAIL_NULL(shader_singleton); //pipeline variants will clear themselves if shader is gone if (version.is_valid()) { shader_singleton->shader.version_free(version); @@ -620,7 +620,7 @@ void SceneShaderForwardMobile::init(const String p_defines) { actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP; actions.default_repeat = ShaderLanguage::REPEAT_ENABLE; actions.global_buffer_array_variable = "global_shader_uniforms.data"; - actions.instance_uniform_index_variable = "draw_call.instance_uniforms_ofs"; + actions.instance_uniform_index_variable = "instances.data[instance_index].instance_uniforms_ofs"; actions.apply_luminance_multiplier = true; // apply luminance multiplier to screen texture actions.check_multiview_samplers = RendererCompositorRD::get_singleton()->is_xr_enabled(); // Make sure we check sampling multiview textures. diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h index 0b98746d06..5c76d89247 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h @@ -97,7 +97,7 @@ public: bool valid = false; RID version; - uint32_t vertex_input_mask = 0; + uint64_t vertex_input_mask = 0; PipelineCacheRD pipelines[CULL_VARIANT_MAX][RS::PRIMITIVE_MAX][SHADER_VERSION_MAX]; Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms; diff --git a/servers/rendering/renderer_rd/pipeline_cache_rd.h b/servers/rendering/renderer_rd/pipeline_cache_rd.h index 52877109f7..2f1e79b397 100644 --- a/servers/rendering/renderer_rd/pipeline_cache_rd.h +++ b/servers/rendering/renderer_rd/pipeline_cache_rd.h @@ -91,7 +91,7 @@ public: return result; } - _FORCE_INLINE_ uint32_t get_vertex_input_mask() { + _FORCE_INLINE_ uint64_t get_vertex_input_mask() { if (input_mask == 0) { ERR_FAIL_COND_V(shader.is_null(), 0); input_mask = RD::get_singleton()->shader_get_vertex_input_attribute_mask(shader); diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index f3ffc688e7..885a00856e 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -329,7 +329,7 @@ RendererCanvasRender::PolygonID RendererCanvasRenderRD::request_polygon(const Ve void RendererCanvasRenderRD::free_polygon(PolygonID p_polygon) { PolygonBuffers *pb_ptr = polygon_buffers.polygons.getptr(p_polygon); - ERR_FAIL_COND(!pb_ptr); + ERR_FAIL_NULL(pb_ptr); PolygonBuffers &pb = *pb_ptr; @@ -894,7 +894,7 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend RS::PrimitiveType primitive = mesh_storage->mesh_surface_get_primitive(surface); ERR_CONTINUE(primitive < 0 || primitive >= RS::PRIMITIVE_MAX); - uint32_t input_mask = pipeline_variants->variants[light_mode][variant[primitive]].get_vertex_input_mask(); + uint64_t input_mask = pipeline_variants->variants[light_mode][variant[primitive]].get_vertex_input_mask(); RID vertex_array; RD::VertexFormatID vertex_format = RD::INVALID_FORMAT_ID; @@ -1561,7 +1561,7 @@ void RendererCanvasRenderRD::light_set_texture(RID p_rid, RID p_texture) { RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); CanvasLight *cl = canvas_light_owner.get_or_null(p_rid); - ERR_FAIL_COND(!cl); + ERR_FAIL_NULL(cl); if (cl->texture == p_texture) { return; } @@ -1580,7 +1580,7 @@ void RendererCanvasRenderRD::light_set_texture(RID p_rid, RID p_texture) { void RendererCanvasRenderRD::light_set_use_shadow(RID p_rid, bool p_enable) { CanvasLight *cl = canvas_light_owner.get_or_null(p_rid); - ERR_FAIL_COND(!cl); + ERR_FAIL_NULL(cl); cl->shadow.enabled = p_enable; } @@ -1849,7 +1849,7 @@ RID RendererCanvasRenderRD::occluder_polygon_create() { void RendererCanvasRenderRD::occluder_polygon_set_shape(RID p_occluder, const Vector<Vector2> &p_points, bool p_closed) { OccluderPolygon *oc = occluder_polygon_owner.get_or_null(p_occluder); - ERR_FAIL_COND(!oc); + ERR_FAIL_NULL(oc); Vector<Vector2> lines; @@ -2020,7 +2020,7 @@ void RendererCanvasRenderRD::occluder_polygon_set_shape(RID p_occluder, const Ve void RendererCanvasRenderRD::occluder_polygon_set_cull_mode(RID p_occluder, RS::CanvasOccluderPolygonCullMode p_mode) { OccluderPolygon *oc = occluder_polygon_owner.get_or_null(p_occluder); - ERR_FAIL_COND(!oc); + ERR_FAIL_NULL(oc); oc->cull_mode = p_mode; } @@ -2250,7 +2250,7 @@ RS::ShaderNativeSourceCode RendererCanvasRenderRD::CanvasShaderData::get_native_ RendererCanvasRenderRD::CanvasShaderData::~CanvasShaderData() { RendererCanvasRenderRD *canvas_singleton = static_cast<RendererCanvasRenderRD *>(RendererCanvasRender::singleton); - ERR_FAIL_COND(!canvas_singleton); + ERR_FAIL_NULL(canvas_singleton); //pipeline variants will clear themselves if shader is gone if (version.is_valid()) { canvas_singleton->shader.canvas_shader.version_free(version); @@ -2704,7 +2704,7 @@ void fragment() { bool RendererCanvasRenderRD::free(RID p_rid) { if (canvas_light_owner.owns(p_rid)) { CanvasLight *cl = canvas_light_owner.get_or_null(p_rid); - ERR_FAIL_COND_V(!cl, false); + ERR_FAIL_NULL_V(cl, false); light_set_use_shadow(p_rid, false); canvas_light_owner.free(p_rid); } else if (occluder_polygon_owner.owns(p_rid)) { diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp index 7eb8cbd02f..b9bda9329e 100644 --- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp @@ -103,8 +103,9 @@ void RendererCompositorRD::begin_frame(double frame_step) { } void RendererCompositorRD::end_frame(bool p_swap_buffers) { - // TODO: Likely pass a bool to swap buffers to avoid display? - RD::get_singleton()->swap_buffers(); + if (p_swap_buffers) { + RD::get_singleton()->swap_buffers(); + } } void RendererCompositorRD::initialize() { diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index 20e24dba0e..07d56eae0c 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -340,14 +340,16 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende // Glow, auto exposure and DoF (if enabled). - Size2i internal_size = rb->get_internal_size(); Size2i target_size = rb->get_target_size(); - bool can_use_effects = target_size.x >= 8 && target_size.y >= 8; // FIXME I think this should check internal size, we do all our post processing at this size... bool can_use_storage = _render_buffers_can_be_storage(); + bool use_fsr = fsr && can_use_effects && rb->get_scaling_3d_mode() == RS::VIEWPORT_SCALING_3D_MODE_FSR; + bool use_upscaled_texture = rb->has_upscaled_texture() && rb->get_scaling_3d_mode() == RS::VIEWPORT_SCALING_3D_MODE_FSR2; + RID render_target = rb->get_render_target(); - RID internal_texture = rb->get_internal_texture(); + RID color_texture = use_upscaled_texture ? rb->get_upscaled_texture() : rb->get_internal_texture(); + Size2i color_size = use_upscaled_texture ? target_size : rb->get_internal_size(); if (can_use_effects && RSG::camera_attributes->camera_attributes_uses_dof(p_render_data->camera_attributes)) { RENDER_TIMESTAMP("Depth of Field"); @@ -358,14 +360,14 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende RendererRD::BokehDOF::BokehBuffers buffers; // Textures we use - buffers.base_texture_size = rb->get_internal_size(); + buffers.base_texture_size = color_size; buffers.secondary_texture = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, 0, 0); buffers.half_texture[0] = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, 0, 0); buffers.half_texture[1] = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, 0, 1); if (can_use_storage) { for (uint32_t i = 0; i < rb->get_view_count(); i++) { - buffers.base_texture = rb->get_internal_texture(i); + buffers.base_texture = use_upscaled_texture ? rb->get_upscaled_texture(i) : rb->get_internal_texture(i); buffers.depth_texture = rb->get_depth_texture(i); // In stereo p_render_data->z_near and p_render_data->z_far can be offset for our combined frustum. @@ -387,7 +389,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende buffers.base_weight_fb = rb->weight_buffers[0].fb; for (uint32_t i = 0; i < rb->get_view_count(); i++) { - buffers.base_texture = rb->get_internal_texture(i); + buffers.base_texture = use_upscaled_texture ? rb->get_upscaled_texture(i) : rb->get_internal_texture(i); buffers.depth_texture = rb->get_depth_texture(i); buffers.base_fb = FramebufferCacheRD::get_singleton()->get_cache(buffers.base_texture); // TODO move this into bokeh_dof_raster, we can do this internally @@ -416,7 +418,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende double step = RSG::camera_attributes->camera_attributes_get_auto_exposure_adjust_speed(p_render_data->camera_attributes) * time_step; float auto_exposure_min_sensitivity = RSG::camera_attributes->camera_attributes_get_auto_exposure_min_sensitivity(p_render_data->camera_attributes); float auto_exposure_max_sensitivity = RSG::camera_attributes->camera_attributes_get_auto_exposure_max_sensitivity(p_render_data->camera_attributes); - luminance->luminance_reduction(internal_texture, internal_size, luminance_buffers, auto_exposure_min_sensitivity, auto_exposure_max_sensitivity, step, set_immediate); + luminance->luminance_reduction(rb->get_internal_texture(), rb->get_internal_size(), luminance_buffers, auto_exposure_min_sensitivity, auto_exposure_max_sensitivity, step, set_immediate); // Swap final reduce with prev luminance. @@ -525,7 +527,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende } tonemap.use_debanding = rb->get_use_debanding(); - tonemap.texture_size = Vector2i(rb->get_internal_size().x, rb->get_internal_size().y); + tonemap.texture_size = Vector2i(color_size.x, color_size.y); if (p_render_data->environment.is_valid()) { tonemap.tonemap_mode = environment_get_tone_mapper(p_render_data->environment); @@ -555,7 +557,8 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende tonemap.convert_to_srgb = !texture_storage->render_target_is_using_hdr(render_target); RID dest_fb; - if (fsr && can_use_effects && rb->get_scaling_3d_mode() == RS::VIEWPORT_SCALING_3D_MODE_FSR) { + bool use_intermediate_fb = use_fsr; + if (use_intermediate_fb) { // If we use FSR to upscale we need to write our result into an intermediate buffer. // Note that this is cached so we only create the texture the first time. RID dest_texture = rb->create_texture(SNAME("Tonemapper"), SNAME("destination"), _render_buffers_get_color_format(), RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT); @@ -567,12 +570,12 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende dest_fb = texture_storage->render_target_get_rd_framebuffer(render_target); } - tone_mapper->tonemapper(internal_texture, dest_fb, tonemap); + tone_mapper->tonemapper(color_texture, dest_fb, tonemap); RD::get_singleton()->draw_command_end_label(); } - if (fsr && can_use_effects && rb->get_scaling_3d_mode() == RS::VIEWPORT_SCALING_3D_MODE_FSR) { + if (use_fsr) { RD::get_singleton()->draw_command_begin_label("FSR 1.0 Upscale"); for (uint32_t v = 0; v < rb->get_view_count(); v++) { @@ -732,6 +735,11 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(const RenderDataRD *p_ren } } + if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_INTERNAL_BUFFER) { + Size2 rtsize = texture_storage->render_target_get_size(render_target); + copy_effects->copy_to_fb_rect(rb->get_internal_texture(), texture_storage->render_target_get_rd_framebuffer(render_target), Rect2(Vector2(), rtsize), false, false); + } + if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER && _render_buffers_get_normal_texture(rb).is_valid()) { Size2 rtsize = texture_storage->render_target_get_size(render_target); copy_effects->copy_to_fb_rect(_render_buffers_get_normal_texture(rb), texture_storage->render_target_get_rd_framebuffer(render_target), Rect2(Vector2(), rtsize), false, false); @@ -745,7 +753,12 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(const RenderDataRD *p_ren } if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_MOTION_VECTORS && _render_buffers_get_velocity_texture(rb).is_valid()) { - debug_effects->draw_motion_vectors(_render_buffers_get_velocity_texture(rb), texture_storage->render_target_get_rd_framebuffer(render_target), rb->get_internal_size()); + RID velocity = _render_buffers_get_velocity_texture(rb); + RID depth = rb->get_depth_texture(); + RID dest_fb = texture_storage->render_target_get_rd_framebuffer(render_target); + Size2i resolution = rb->get_internal_size(); + + debug_effects->draw_motion_vectors(velocity, depth, dest_fb, p_render_data->scene_data->cam_projection, p_render_data->scene_data->cam_transform, p_render_data->scene_data->prev_cam_projection, p_render_data->scene_data->prev_cam_transform, resolution); } } diff --git a/servers/rendering/renderer_rd/shader_rd.cpp b/servers/rendering/renderer_rd/shader_rd.cpp index 46ae2d9551..10e37c7da8 100644 --- a/servers/rendering/renderer_rd/shader_rd.cpp +++ b/servers/rendering/renderer_rd/shader_rd.cpp @@ -314,7 +314,7 @@ void ShaderRD::_compile_variant(uint32_t p_variant, const CompileData *p_data) { RS::ShaderNativeSourceCode ShaderRD::version_get_native_source_code(RID p_version) { Version *version = version_owner.get_or_null(p_version); RS::ShaderNativeSourceCode source_code; - ERR_FAIL_COND_V(!version, source_code); + ERR_FAIL_NULL_V(version, source_code); source_code.versions.resize(variant_defines.size()); @@ -567,7 +567,7 @@ void ShaderRD::version_set_code(RID p_version, const HashMap<String, String> &p_ ERR_FAIL_COND(is_compute); Version *version = version_owner.get_or_null(p_version); - ERR_FAIL_COND(!version); + ERR_FAIL_NULL(version); version->vertex_globals = p_vertex_globals.utf8(); version->fragment_globals = p_fragment_globals.utf8(); version->uniforms = p_uniforms.utf8(); @@ -599,7 +599,7 @@ void ShaderRD::version_set_compute_code(RID p_version, const HashMap<String, Str ERR_FAIL_COND(!is_compute); Version *version = version_owner.get_or_null(p_version); - ERR_FAIL_COND(!version); + ERR_FAIL_NULL(version); version->compute_globals = p_compute_globals.utf8(); version->uniforms = p_uniforms.utf8(); @@ -630,7 +630,7 @@ void ShaderRD::version_set_compute_code(RID p_version, const HashMap<String, Str bool ShaderRD::version_is_valid(RID p_version) { Version *version = version_owner.get_or_null(p_version); - ERR_FAIL_COND_V(!version, false); + ERR_FAIL_NULL_V(version, false); if (version->dirty) { _initialize_version(version); diff --git a/servers/rendering/renderer_rd/shader_rd.h b/servers/rendering/renderer_rd/shader_rd.h index 01eb99f7a2..9ce510386f 100644 --- a/servers/rendering/renderer_rd/shader_rd.h +++ b/servers/rendering/renderer_rd/shader_rd.h @@ -162,7 +162,7 @@ public: ERR_FAIL_COND_V(!variants_enabled[p_variant], RID()); Version *version = version_owner.get_or_null(p_version); - ERR_FAIL_COND_V(!version, RID()); + ERR_FAIL_NULL_V(version, RID()); if (version->dirty) { _initialize_version(version); diff --git a/servers/rendering/renderer_rd/shaders/effects/SCsub b/servers/rendering/renderer_rd/shaders/effects/SCsub index f06a2d86e2..810f781340 100644 --- a/servers/rendering/renderer_rd/shaders/effects/SCsub +++ b/servers/rendering/renderer_rd/shaders/effects/SCsub @@ -15,3 +15,5 @@ if "RD_GLSL" in env["BUILDERS"]: # compile shaders for glsl_file in glsl_files: env.RD_GLSL(glsl_file) + +SConscript("fsr2/SCsub") diff --git a/servers/rendering/renderer_rd/shaders/effects/copy.glsl b/servers/rendering/renderer_rd/shaders/effects/copy.glsl index 2b3d27b000..debf6b7367 100644 --- a/servers/rendering/renderer_rd/shaders/effects/copy.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/copy.glsl @@ -103,12 +103,13 @@ void main() { #ifdef MODE_GLOW if (bool(params.flags & FLAG_GLOW_FIRST_PASS)) { // Tonemap initial samples to reduce weight of fireflies: https://graphicrants.blogspot.com/2013/12/tone-mapping.html - local_cache[dest_index] /= 1.0 + dot(local_cache[dest_index].rgb, vec3(0.299, 0.587, 0.114)); - local_cache[dest_index + 1] /= 1.0 + dot(local_cache[dest_index + 1].rgb, vec3(0.299, 0.587, 0.114)); - local_cache[dest_index + 16] /= 1.0 + dot(local_cache[dest_index + 16].rgb, vec3(0.299, 0.587, 0.114)); - local_cache[dest_index + 16 + 1] /= 1.0 + dot(local_cache[dest_index + 16 + 1].rgb, vec3(0.299, 0.587, 0.114)); + vec3 tonemap_col = vec3(0.299, 0.587, 0.114) / max(params.glow_luminance_cap, 6.0); + local_cache[dest_index] /= 1.0 + dot(local_cache[dest_index].rgb, tonemap_col); + local_cache[dest_index + 1] /= 1.0 + dot(local_cache[dest_index + 1].rgb, tonemap_col); + local_cache[dest_index + 16] /= 1.0 + dot(local_cache[dest_index + 16].rgb, tonemap_col); + local_cache[dest_index + 16 + 1] /= 1.0 + dot(local_cache[dest_index + 16 + 1].rgb, tonemap_col); } - const float kernel[4] = { 0.174938, 0.165569, 0.140367, 0.106595 }; + const float kernel[5] = { 0.2024, 0.1790, 0.1240, 0.0672, 0.0285 }; #else // Simpler blur uses SIGMA2 for the gaussian kernel for a stronger effect. const float kernel[4] = { 0.214607, 0.189879, 0.131514, 0.071303 }; @@ -126,6 +127,10 @@ void main() { color_top += local_cache[read_index - 1] * kernel[1]; color_top += local_cache[read_index - 2] * kernel[2]; color_top += local_cache[read_index - 3] * kernel[3]; +#ifdef MODE_GLOW + color_top += local_cache[read_index + 4] * kernel[4]; + color_top += local_cache[read_index - 4] * kernel[4]; +#endif // MODE_GLOW vec4 color_bottom = vec4(0.0); color_bottom += local_cache[read_index + 16] * kernel[0]; @@ -135,6 +140,10 @@ void main() { color_bottom += local_cache[read_index - 1 + 16] * kernel[1]; color_bottom += local_cache[read_index - 2 + 16] * kernel[2]; color_bottom += local_cache[read_index - 3 + 16] * kernel[3]; +#ifdef MODE_GLOW + color_bottom += local_cache[read_index + 4 + 16] * kernel[4]; + color_bottom += local_cache[read_index - 4 + 16] * kernel[4]; +#endif // MODE_GLOW // rotate samples to take advantage of cache coherency uint write_index = gl_LocalInvocationID.y * 2 + gl_LocalInvocationID.x * 16; @@ -161,11 +170,15 @@ void main() { color += temp_cache[index - 1] * kernel[1]; color += temp_cache[index - 2] * kernel[2]; color += temp_cache[index - 3] * kernel[3]; +#ifdef MODE_GLOW + color += temp_cache[index + 4] * kernel[4]; + color += temp_cache[index - 4] * kernel[4]; +#endif // MODE_GLOW #ifdef MODE_GLOW if (bool(params.flags & FLAG_GLOW_FIRST_PASS)) { // Undo tonemap to restore range: https://graphicrants.blogspot.com/2013/12/tone-mapping.html - color /= 1.0 - dot(color.rgb, vec3(0.299, 0.587, 0.114)); + color /= 1.0 - dot(color.rgb, vec3(0.299, 0.587, 0.114) / max(params.glow_luminance_cap, 6.0)); } color *= params.glow_strength; diff --git a/servers/rendering/renderer_rd/shaders/effects/fsr2/SCsub b/servers/rendering/renderer_rd/shaders/effects/fsr2/SCsub new file mode 100644 index 0000000000..f06a2d86e2 --- /dev/null +++ b/servers/rendering/renderer_rd/shaders/effects/fsr2/SCsub @@ -0,0 +1,17 @@ +#!/usr/bin/env python + +Import("env") + +if "RD_GLSL" in env["BUILDERS"]: + # find all include files + gl_include_files = [str(f) for f in Glob("*_inc.glsl")] + [str(f) for f in Glob("../*_inc.glsl")] + + # find all shader code(all glsl files excluding our include files) + glsl_files = [str(f) for f in Glob("*.glsl") if str(f) not in gl_include_files] + + # make sure we recompile shaders if include files change + env.Depends([f + ".gen.h" for f in glsl_files], gl_include_files + ["#glsl_builders.py"]) + + # compile shaders + for glsl_file in glsl_files: + env.RD_GLSL(glsl_file) diff --git a/servers/rendering/renderer_rd/shaders/effects/fsr2/fsr2_accumulate_pass.glsl b/servers/rendering/renderer_rd/shaders/effects/fsr2/fsr2_accumulate_pass.glsl new file mode 100644 index 0000000000..67fce9a342 --- /dev/null +++ b/servers/rendering/renderer_rd/shaders/effects/fsr2/fsr2_accumulate_pass.glsl @@ -0,0 +1,8 @@ +#[compute] + +#version 450 + +#VERSION_DEFINES + +#include "../motion_vector_inc.glsl" +#include "thirdparty/amd-fsr2/shaders/ffx_fsr2_accumulate_pass.glsl" diff --git a/servers/rendering/renderer_rd/shaders/effects/fsr2/fsr2_autogen_reactive_pass.glsl b/servers/rendering/renderer_rd/shaders/effects/fsr2/fsr2_autogen_reactive_pass.glsl new file mode 100644 index 0000000000..d362958aa6 --- /dev/null +++ b/servers/rendering/renderer_rd/shaders/effects/fsr2/fsr2_autogen_reactive_pass.glsl @@ -0,0 +1,8 @@ +#[compute] + +#version 450 + +#VERSION_DEFINES + +#include "../motion_vector_inc.glsl" +#include "thirdparty/amd-fsr2/shaders/ffx_fsr2_autogen_reactive_pass.glsl" diff --git a/servers/rendering/renderer_rd/shaders/effects/fsr2/fsr2_compute_luminance_pyramid_pass.glsl b/servers/rendering/renderer_rd/shaders/effects/fsr2/fsr2_compute_luminance_pyramid_pass.glsl new file mode 100644 index 0000000000..37504c2e53 --- /dev/null +++ b/servers/rendering/renderer_rd/shaders/effects/fsr2/fsr2_compute_luminance_pyramid_pass.glsl @@ -0,0 +1,7 @@ +#[compute] + +#version 450 + +#VERSION_DEFINES + +#include "thirdparty/amd-fsr2/shaders/ffx_fsr2_compute_luminance_pyramid_pass.glsl" diff --git a/servers/rendering/renderer_rd/shaders/effects/fsr2/fsr2_depth_clip_pass.glsl b/servers/rendering/renderer_rd/shaders/effects/fsr2/fsr2_depth_clip_pass.glsl new file mode 100644 index 0000000000..0ee08e4c76 --- /dev/null +++ b/servers/rendering/renderer_rd/shaders/effects/fsr2/fsr2_depth_clip_pass.glsl @@ -0,0 +1,8 @@ +#[compute] + +#version 450 + +#VERSION_DEFINES + +#include "../motion_vector_inc.glsl" +#include "thirdparty/amd-fsr2/shaders/ffx_fsr2_depth_clip_pass.glsl" diff --git a/servers/rendering/renderer_rd/shaders/effects/fsr2/fsr2_lock_pass.glsl b/servers/rendering/renderer_rd/shaders/effects/fsr2/fsr2_lock_pass.glsl new file mode 100644 index 0000000000..8c8430d4b1 --- /dev/null +++ b/servers/rendering/renderer_rd/shaders/effects/fsr2/fsr2_lock_pass.glsl @@ -0,0 +1,7 @@ +#[compute] + +#version 450 + +#VERSION_DEFINES + +#include "thirdparty/amd-fsr2/shaders/ffx_fsr2_lock_pass.glsl" diff --git a/servers/rendering/renderer_rd/shaders/effects/fsr2/fsr2_rcas_pass.glsl b/servers/rendering/renderer_rd/shaders/effects/fsr2/fsr2_rcas_pass.glsl new file mode 100644 index 0000000000..4120cfe644 --- /dev/null +++ b/servers/rendering/renderer_rd/shaders/effects/fsr2/fsr2_rcas_pass.glsl @@ -0,0 +1,7 @@ +#[compute] + +#version 450 + +#VERSION_DEFINES + +#include "thirdparty/amd-fsr2/shaders/ffx_fsr2_rcas_pass.glsl" diff --git a/servers/rendering/renderer_rd/shaders/effects/fsr2/fsr2_reconstruct_previous_depth_pass.glsl b/servers/rendering/renderer_rd/shaders/effects/fsr2/fsr2_reconstruct_previous_depth_pass.glsl new file mode 100644 index 0000000000..f31abec215 --- /dev/null +++ b/servers/rendering/renderer_rd/shaders/effects/fsr2/fsr2_reconstruct_previous_depth_pass.glsl @@ -0,0 +1,8 @@ +#[compute] + +#version 450 + +#VERSION_DEFINES + +#include "../motion_vector_inc.glsl" +#include "thirdparty/amd-fsr2/shaders/ffx_fsr2_reconstruct_previous_depth_pass.glsl" diff --git a/servers/rendering/renderer_rd/shaders/effects/fsr2/fsr2_tcr_autogen_pass.glsl b/servers/rendering/renderer_rd/shaders/effects/fsr2/fsr2_tcr_autogen_pass.glsl new file mode 100644 index 0000000000..818374e43c --- /dev/null +++ b/servers/rendering/renderer_rd/shaders/effects/fsr2/fsr2_tcr_autogen_pass.glsl @@ -0,0 +1,8 @@ +#[compute] + +#version 450 + +#VERSION_DEFINES + +#include "../motion_vector_inc.glsl" +#include "thirdparty/amd-fsr2/shaders/ffx_fsr2_tcr_autogen_pass.glsl" diff --git a/servers/rendering/renderer_rd/shaders/effects/motion_vector_inc.glsl b/servers/rendering/renderer_rd/shaders/effects/motion_vector_inc.glsl new file mode 100644 index 0000000000..cbf202653e --- /dev/null +++ b/servers/rendering/renderer_rd/shaders/effects/motion_vector_inc.glsl @@ -0,0 +1,6 @@ +vec2 derive_motion_vector(vec2 uv, float depth, mat4 reprojection_matrix) { + vec4 previous_pos_ndc = reprojection_matrix * vec4(uv * 2.0f - 1.0f, depth * 2.0f - 1.0f, 1.0f); + return 0.5f + (previous_pos_ndc.xy / previous_pos_ndc.w) * 0.5f - uv; +} + +#define FFX_FSR2_OPTION_GODOT_DERIVE_INVALID_MOTION_VECTORS_FUNCTION(i, j, k) derive_motion_vector(i, j, k) diff --git a/servers/rendering/renderer_rd/shaders/effects/motion_vectors.glsl b/servers/rendering/renderer_rd/shaders/effects/motion_vectors.glsl index 80e4f51565..d02ffe0b4f 100644 --- a/servers/rendering/renderer_rd/shaders/effects/motion_vectors.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/motion_vectors.glsl @@ -18,14 +18,19 @@ void main() { #VERSION_DEFINES +#include "motion_vector_inc.glsl" + layout(location = 0) in vec2 uv_interp; layout(set = 0, binding = 0) uniform sampler2D source_velocity; +layout(set = 0, binding = 1) uniform sampler2D source_depth; layout(location = 0) out vec4 frag_color; layout(push_constant, std430) uniform Params { + highp mat4 reprojection_matrix; vec2 resolution; + bool force_derive_from_depth; } params; @@ -49,7 +54,14 @@ void main() { vec2 pos_pixel = uv_interp * params.resolution; vec2 cell_pos_pixel = floor(pos_pixel / cell_size) * cell_size + (cell_size * 0.5f); vec2 cell_pos_uv = cell_pos_pixel / params.resolution; - vec2 cell_pos_previous_uv = cell_pos_uv + textureLod(source_velocity, cell_pos_uv, 0.0f).xy; + vec2 cell_pos_velocity = textureLod(source_velocity, cell_pos_uv, 0.0f).xy; + bool derive_velocity = params.force_derive_from_depth || all(lessThanEqual(cell_pos_velocity, vec2(-1.0f, -1.0f))); + if (derive_velocity) { + float depth = textureLod(source_depth, cell_pos_uv, 0.0f).x; + cell_pos_velocity = derive_motion_vector(cell_pos_uv, depth, params.reprojection_matrix); + } + + vec2 cell_pos_previous_uv = cell_pos_uv + cell_pos_velocity; // Draw the shapes. float epsilon = 1e-6f; @@ -76,5 +88,10 @@ void main() { alpha = 0.0f; } + if (derive_velocity) { + color = vec3(1.0f, 1.0f, 1.0f) - color; + alpha *= 0.5f; + } + frag_color = vec4(color, alpha); } diff --git a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl index 2b8b8fa9d2..56e466ba98 100644 --- a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl @@ -10,21 +10,17 @@ /* INPUT ATTRIBS */ -layout(location = 0) in vec3 vertex_attrib; +// Always contains vertex position in XYZ, can contain tangent angle in W. +layout(location = 0) in vec4 vertex_angle_attrib; //only for pure render depth when normal is not used -#ifdef NORMAL_USED -layout(location = 1) in vec2 normal_attrib; +#if defined(NORMAL_USED) || defined(TANGENT_USED) +// Contains Normal/Axis in RG, can contain tangent in BA. +layout(location = 1) in vec4 axis_tangent_attrib; #endif -#if !defined(TANGENT_USED) && (defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)) -#define TANGENT_USED -#endif - -#ifdef TANGENT_USED -layout(location = 2) in vec2 tangent_attrib; -#endif +// Location 2 is unused. #if defined(COLOR_USED) layout(location = 3) in vec4 color_attrib; @@ -63,15 +59,12 @@ layout(location = 11) in vec4 weight_attrib; #endif #ifdef MOTION_VECTORS -layout(location = 12) in vec3 previous_vertex_attrib; +layout(location = 12) in vec4 previous_vertex_attrib; -#ifdef NORMAL_USED -layout(location = 13) in vec2 previous_normal_attrib; +#if defined(NORMAL_USED) || defined(TANGENT_USED) +layout(location = 13) in vec4 previous_normal_attrib; #endif -#ifdef TANGENT_USED -layout(location = 14) in vec2 previous_tangent_attrib; -#endif #endif // MOTION_VECTORS vec3 oct_to_vec3(vec2 e) { @@ -81,6 +74,16 @@ vec3 oct_to_vec3(vec2 e) { return normalize(v); } +void axis_angle_to_tbn(vec3 axis, float angle, out vec3 tangent, out vec3 binormal, out vec3 normal) { + float c = cos(angle); + float s = sin(angle); + vec3 omc_axis = (1.0 - c) * axis; + vec3 s_axis = s * axis; + tangent = omc_axis.xxx * axis + vec3(c, -s_axis.z, s_axis.y); + binormal = omc_axis.yyy * axis + vec3(s_axis.z, c, -s_axis.x); + normal = omc_axis.zzz * axis + vec3(-s_axis.y, s_axis.x, c); +} + /* Varyings */ layout(location = 0) out vec3 vertex_interp; @@ -179,10 +182,11 @@ vec3 double_add_vec3(vec3 base_a, vec3 prec_a, vec3 base_b, vec3 prec_b, out vec void vertex_shader(vec3 vertex_input, #ifdef NORMAL_USED - in vec2 normal_input, + in vec3 normal_input, #endif #ifdef TANGENT_USED - in vec2 tangent_input, + in vec3 tangent_input, + in vec3 binormal_input, #endif in uint instance_index, in bool is_multimesh, in uint multimesh_offset, in SceneData scene_data, in mat4 model_matrix, out vec4 screen_pos) { vec4 instance_custom = vec4(0.0); @@ -314,14 +318,12 @@ void vertex_shader(vec3 vertex_input, vec3 vertex = vertex_input; #ifdef NORMAL_USED - vec3 normal = oct_to_vec3(normal_input * 2.0 - 1.0); + vec3 normal = normal_input; #endif #ifdef TANGENT_USED - vec2 signed_tangent_input = tangent_input * 2.0 - 1.0; - vec3 tangent = oct_to_vec3(vec2(signed_tangent_input.x, abs(signed_tangent_input.y) * 2.0 - 1.0)); - float binormalf = sign(signed_tangent_input.y); - vec3 binormal = normalize(cross(normal, tangent) * binormalf); + vec3 tangent = tangent_input; + vec3 binormal = binormal_input; #endif #ifdef UV_USED @@ -332,6 +334,17 @@ void vertex_shader(vec3 vertex_input, uv2_interp = uv2_attrib; #endif + vec4 uv_scale = instances.data[instance_index].uv_scale; + + if (uv_scale != vec4(0.0)) { // Compression enabled +#ifdef UV_USED + uv_interp = (uv_interp - 0.5) * uv_scale.xy; +#endif +#if defined(UV2_USED) || defined(USE_LIGHTMAP) + uv2_interp = (uv2_interp - 0.5) * uv_scale.zw; +#endif + } + #ifdef OVERRIDE_POSITION vec4 position; #endif @@ -484,6 +497,46 @@ void vertex_shader(vec3 vertex_input, #endif } +void _unpack_vertex_attributes(vec4 p_vertex_in, vec3 p_compressed_aabb_position, vec3 p_compressed_aabb_size, +#if defined(NORMAL_USED) || defined(TANGENT_USED) + vec4 p_normal_in, +#ifdef NORMAL_USED + out vec3 r_normal, +#endif + out vec3 r_tangent, + out vec3 r_binormal, +#endif + out vec3 r_vertex) { + + r_vertex = p_vertex_in.xyz * p_compressed_aabb_size + p_compressed_aabb_position; +#ifdef NORMAL_USED + r_normal = oct_to_vec3(p_normal_in.xy * 2.0 - 1.0); +#endif + +#if defined(NORMAL_USED) || defined(TANGENT_USED) + + float binormal_sign; + + // This works because the oct value (0, 1) maps onto (0, 0, -1) which encodes to (1, 1). + // Accordingly, if p_normal_in.z contains octahedral values, it won't equal (0, 1). + if (p_normal_in.z > 0.0 || p_normal_in.w < 1.0) { + // Uncompressed format. + vec2 signed_tangent_attrib = p_normal_in.zw * 2.0 - 1.0; + r_tangent = oct_to_vec3(vec2(signed_tangent_attrib.x, abs(signed_tangent_attrib.y) * 2.0 - 1.0)); + binormal_sign = sign(signed_tangent_attrib.y); + r_binormal = normalize(cross(r_normal, r_tangent) * binormal_sign); + } else { + // Compressed format. + float angle = p_vertex_in.w; + binormal_sign = angle > 0.5 ? 1.0 : -1.0; // 0.5 does not exist in UNORM16, so values are either greater or smaller. + angle = abs(angle * 2.0 - 1.0) * M_PI; // 0.5 is basically zero, allowing to encode both signs reliably. + vec3 axis = r_normal; + axis_angle_to_tbn(axis, angle, r_tangent, r_binormal, r_normal); + r_binormal *= binormal_sign; + } +#endif +} + void main() { uint instance_index = draw_call.instance_index; @@ -498,13 +551,38 @@ void main() { #ifdef MOTION_VECTORS // Previous vertex. - global_time = scene_data_block.prev_data.time; - vertex_shader(previous_vertex_attrib, + vec3 prev_vertex; #ifdef NORMAL_USED + vec3 prev_normal; +#endif +#if defined(NORMAL_USED) || defined(TANGENT_USED) + vec3 prev_tangent; + vec3 prev_binormal; +#endif + + _unpack_vertex_attributes( + previous_vertex_attrib, + instances.data[instance_index].compressed_aabb_position_pad.xyz, + instances.data[instance_index].compressed_aabb_size_pad.xyz, + +#if defined(NORMAL_USED) || defined(TANGENT_USED) previous_normal_attrib, +#ifdef NORMAL_USED + prev_normal, +#endif + prev_tangent, + prev_binormal, +#endif + prev_vertex); + + global_time = scene_data_block.prev_data.time; + vertex_shader(prev_vertex, +#ifdef NORMAL_USED + prev_normal, #endif #ifdef TANGENT_USED - previous_tangent_attrib, + prev_tangent, + prev_binormal, #endif instance_index, is_multimesh, draw_call.multimesh_motion_vectors_previous_offset, scene_data_block.prev_data, instances.data[instance_index].prev_transform, prev_screen_position); #else @@ -512,14 +590,38 @@ void main() { vec4 screen_position; #endif + vec3 vertex; +#ifdef NORMAL_USED + vec3 normal; +#endif +#if defined(NORMAL_USED) || defined(TANGENT_USED) + vec3 tangent; + vec3 binormal; +#endif + + _unpack_vertex_attributes( + vertex_angle_attrib, + instances.data[instance_index].compressed_aabb_position_pad.xyz, + instances.data[instance_index].compressed_aabb_size_pad.xyz, +#if defined(NORMAL_USED) || defined(TANGENT_USED) + axis_tangent_attrib, +#ifdef NORMAL_USED + normal, +#endif + tangent, + binormal, +#endif + vertex); + // Current vertex. global_time = scene_data_block.data.time; - vertex_shader(vertex_attrib, + vertex_shader(vertex, #ifdef NORMAL_USED - normal_attrib, + normal, #endif #ifdef TANGENT_USED - tangent_attrib, + tangent, + binormal, #endif instance_index, is_multimesh, draw_call.multimesh_motion_vectors_current_offset, scene_data_block.data, model_matrix, screen_position); } @@ -575,10 +677,6 @@ layout(location = 3) in vec2 uv_interp; layout(location = 4) in vec2 uv2_interp; #endif -#if !defined(TANGENT_USED) && (defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)) -#define TANGENT_USED -#endif - #ifdef TANGENT_USED layout(location = 5) in vec3 tangent_interp; layout(location = 6) in vec3 binormal_interp; @@ -2280,6 +2378,8 @@ void fragment_shader(in SceneData scene_data) { #else //MODE_SEPARATE_SPECULAR + alpha *= scene_data.pass_alpha_multiplier; + #ifdef MODE_UNSHADED frag_color = vec4(albedo, alpha); #else diff --git a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl index 8ead363f3b..bfd87b4ea1 100644 --- a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl @@ -28,6 +28,10 @@ #endif #endif +#if !defined(TANGENT_USED) && (defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)) +#define TANGENT_USED +#endif + layout(push_constant, std430) uniform DrawCall { uint instance_index; uint uv_offset; @@ -211,6 +215,9 @@ struct InstanceData { uint gi_offset; //GI information when using lightmapping (VCT or lightmap index) uint layer_mask; vec4 lightmap_uv_scale; + vec4 compressed_aabb_position_pad; // Only .xyz is used. .w is padding. + vec4 compressed_aabb_size_pad; // Only .xyz is used. .w is padding. + vec4 uv_scale; }; layout(set = 1, binding = 2, std430) buffer restrict readonly InstanceDataBuffer { diff --git a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl index 7f6a9a50e5..ade40cbf7a 100644 --- a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl @@ -11,17 +11,17 @@ /* INPUT ATTRIBS */ -layout(location = 0) in vec3 vertex_attrib; +// Always contains vertex position in XYZ, can contain tangent angle in W. +layout(location = 0) in vec4 vertex_angle_attrib; //only for pure render depth when normal is not used #ifdef NORMAL_USED -layout(location = 1) in vec2 normal_attrib; +// Contains Normal/Axis in RG, can contain tangent in BA. +layout(location = 1) in vec4 axis_tangent_attrib; #endif -#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) -layout(location = 2) in vec2 tangent_attrib; -#endif +// Location 2 is unused. #if defined(COLOR_USED) layout(location = 3) in vec4 color_attrib; @@ -66,6 +66,16 @@ vec3 oct_to_vec3(vec2 e) { return normalize(v); } +void axis_angle_to_tbn(vec3 axis, float angle, out vec3 tangent, out vec3 binormal, out vec3 normal) { + float c = cos(angle); + float s = sin(angle); + vec3 omc_axis = (1.0 - c) * axis; + vec3 s_axis = s * axis; + tangent = omc_axis.xxx * axis + vec3(c, -s_axis.z, s_axis.y); + binormal = omc_axis.yyy * axis + vec3(s_axis.z, c, -s_axis.x); + normal = omc_axis.zzz * axis + vec3(-s_axis.y, s_axis.x, c); +} + /* Varyings */ layout(location = 0) highp out vec3 vertex_interp; @@ -162,9 +172,9 @@ void main() { color_interp = color_attrib; #endif - bool is_multimesh = bool(draw_call.flags & INSTANCE_FLAGS_MULTIMESH); + bool is_multimesh = bool(instances.data[draw_call.instance_index].flags & INSTANCE_FLAGS_MULTIMESH); - mat4 model_matrix = draw_call.transform; + mat4 model_matrix = instances.data[draw_call.instance_index].transform; mat4 inv_view_matrix = scene_data.inv_view_matrix; #ifdef USE_DOUBLE_PRECISION vec3 model_precision = vec3(model_matrix[0][3], model_matrix[1][3], model_matrix[2][3]); @@ -178,7 +188,7 @@ void main() { #endif mat3 model_normal_matrix; - if (bool(draw_call.flags & INSTANCE_FLAGS_NON_UNIFORM_SCALE)) { + if (bool(instances.data[draw_call.instance_index].flags & INSTANCE_FLAGS_NON_UNIFORM_SCALE)) { model_normal_matrix = transpose(inverse(mat3(model_matrix))); } else { model_normal_matrix = mat3(model_matrix); @@ -191,7 +201,7 @@ void main() { //multimesh, instances are for it #ifdef USE_PARTICLE_TRAILS - uint trail_size = (draw_call.flags >> INSTANCE_FLAGS_PARTICLE_TRAIL_SHIFT) & INSTANCE_FLAGS_PARTICLE_TRAIL_MASK; + uint trail_size = (instances.data[draw_call.instance_index].flags >> INSTANCE_FLAGS_PARTICLE_TRAIL_SHIFT) & INSTANCE_FLAGS_PARTICLE_TRAIL_MASK; uint stride = 3 + 1 + 1; //particles always uses this format uint offset = trail_size * stride * gl_InstanceIndex; @@ -238,22 +248,22 @@ void main() { uint stride = 0; { //TODO implement a small lookup table for the stride - if (bool(draw_call.flags & INSTANCE_FLAGS_MULTIMESH_FORMAT_2D)) { + if (bool(instances.data[draw_call.instance_index].flags & INSTANCE_FLAGS_MULTIMESH_FORMAT_2D)) { stride += 2; } else { stride += 3; } - if (bool(draw_call.flags & INSTANCE_FLAGS_MULTIMESH_HAS_COLOR)) { + if (bool(instances.data[draw_call.instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_COLOR)) { stride += 1; } - if (bool(draw_call.flags & INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA)) { + if (bool(instances.data[draw_call.instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA)) { stride += 1; } } uint offset = stride * gl_InstanceIndex; - if (bool(draw_call.flags & INSTANCE_FLAGS_MULTIMESH_FORMAT_2D)) { + if (bool(instances.data[draw_call.instance_index].flags & INSTANCE_FLAGS_MULTIMESH_FORMAT_2D)) { matrix = mat4(transforms.data[offset + 0], transforms.data[offset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0)); offset += 2; } else { @@ -261,14 +271,14 @@ void main() { offset += 3; } - if (bool(draw_call.flags & INSTANCE_FLAGS_MULTIMESH_HAS_COLOR)) { + if (bool(instances.data[draw_call.instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_COLOR)) { #ifdef COLOR_USED color_interp *= transforms.data[offset]; #endif offset += 1; } - if (bool(draw_call.flags & INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA)) { + if (bool(instances.data[draw_call.instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA)) { instance_custom = transforms.data[offset]; } @@ -287,16 +297,31 @@ void main() { model_normal_matrix = model_normal_matrix * mat3(matrix); } - vec3 vertex = vertex_attrib; + vec3 vertex = vertex_angle_attrib.xyz * instances.data[draw_call.instance_index].compressed_aabb_size_pad.xyz + instances.data[draw_call.instance_index].compressed_aabb_position_pad.xyz; #ifdef NORMAL_USED - vec3 normal = oct_to_vec3(normal_attrib * 2.0 - 1.0); + vec3 normal = oct_to_vec3(axis_tangent_attrib.xy * 2.0 - 1.0); #endif -#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) - vec2 signed_tangent_attrib = tangent_attrib * 2.0 - 1.0; - vec3 tangent = oct_to_vec3(vec2(signed_tangent_attrib.x, abs(signed_tangent_attrib.y) * 2.0 - 1.0)); - float binormalf = sign(signed_tangent_attrib.y); - vec3 binormal = normalize(cross(normal, tangent) * binormalf); +#if defined(NORMAL_USED) || defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) + + vec3 binormal; + float binormal_sign; + vec3 tangent; + if (axis_tangent_attrib.z > 0.0 || axis_tangent_attrib.w < 1.0) { + // Uncompressed format. + vec2 signed_tangent_attrib = axis_tangent_attrib.zw * 2.0 - 1.0; + tangent = oct_to_vec3(vec2(signed_tangent_attrib.x, abs(signed_tangent_attrib.y) * 2.0 - 1.0)); + binormal_sign = sign(signed_tangent_attrib.y); + binormal = normalize(cross(normal, tangent) * binormal_sign); + } else { + // Compressed format. + float angle = vertex_angle_attrib.w; + binormal_sign = angle > 0.5 ? 1.0 : -1.0; // 0.5 does not exist in UNORM16, so values are either greater or smaller. + angle = abs(angle * 2.0 - 1.0) * M_PI; // 0.5 is basically zero, allowing to encode both signs reliably. + vec3 axis = normal; + axis_angle_to_tbn(axis, angle, tangent, binormal, normal); + binormal *= binormal_sign; + } #endif #ifdef UV_USED @@ -307,6 +332,17 @@ void main() { uv2_interp = uv2_attrib; #endif + vec4 uv_scale = instances.data[draw_call.instance_index].uv_scale; + + if (uv_scale != vec4(0.0)) { // Compression enabled +#ifdef UV_USED + uv_interp = (uv_interp - 0.5) * uv_scale.xy; +#endif +#if defined(UV2_USED) || defined(USE_LIGHTMAP) + uv2_interp = (uv2_interp - 0.5) * uv_scale.zw; +#endif + } + #ifdef OVERRIDE_POSITION vec4 position; #endif @@ -441,8 +477,7 @@ void main() { #endif // MODE_RENDER_DEPTH #ifdef MODE_RENDER_MATERIAL if (scene_data.material_uv2_mode) { - vec2 uv_offset = draw_call.lightmap_uv_scale.xy; // we are abusing lightmap_uv_scale here, we shouldn't have a lightmap during a depth pass... - gl_Position.xy = (uv2_attrib.xy + uv_offset) * 2.0 - 1.0; + gl_Position.xy = (uv2_attrib.xy + draw_call.uv_offset) * 2.0 - 1.0; gl_Position.z = 0.00001; gl_Position.w = 1.0; } @@ -765,7 +800,7 @@ void main() { #endif // ALPHA_ANTIALIASING_EDGE_USED mat4 inv_view_matrix = scene_data.inv_view_matrix; - mat4 read_model_matrix = draw_call.transform; + mat4 read_model_matrix = instances.data[draw_call.instance_index].transform; #ifdef USE_DOUBLE_PRECISION read_model_matrix[0][3] = 0.0; read_model_matrix[1][3] = 0.0; @@ -890,11 +925,11 @@ void main() { if (!sc_disable_decals) { //Decals // must implement - uint decal_indices = draw_call.decals.x; + uint decal_indices = instances.data[draw_call.instance_index].decals.x; for (uint i = 0; i < 8; i++) { uint decal_index = decal_indices & 0xFF; if (i == 3) { - decal_indices = draw_call.decals.y; + decal_indices = instances.data[draw_call.instance_index].decals.y; } else { decal_indices = decal_indices >> 8; } @@ -903,7 +938,7 @@ void main() { break; } - if (!bool(decals.data[decal_index].mask & draw_call.layer_mask)) { + if (!bool(decals.data[decal_index].mask & instances.data[draw_call.instance_index].layer_mask)) { continue; //not masked } @@ -1097,8 +1132,8 @@ void main() { #ifdef USE_LIGHTMAP //lightmap - if (bool(draw_call.flags & INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE)) { //has lightmap capture - uint index = draw_call.gi_offset; + if (bool(instances.data[draw_call.instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE)) { //has lightmap capture + uint index = instances.data[draw_call.instance_index].gi_offset; vec3 wnormal = mat3(scene_data.inv_view_matrix) * normal; const float c1 = 0.429043; @@ -1118,12 +1153,12 @@ void main() { 2.0 * c2 * lightmap_captures.data[index].sh[2].rgb * wnormal.z) * scene_data.emissive_exposure_normalization; - } else if (bool(draw_call.flags & INSTANCE_FLAGS_USE_LIGHTMAP)) { // has actual lightmap - bool uses_sh = bool(draw_call.flags & INSTANCE_FLAGS_USE_SH_LIGHTMAP); - uint ofs = draw_call.gi_offset & 0xFFFF; - uint slice = draw_call.gi_offset >> 16; + } else if (bool(instances.data[draw_call.instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP)) { // has actual lightmap + bool uses_sh = bool(instances.data[draw_call.instance_index].flags & INSTANCE_FLAGS_USE_SH_LIGHTMAP); + uint ofs = instances.data[draw_call.instance_index].gi_offset & 0xFFFF; + uint slice = instances.data[draw_call.instance_index].gi_offset >> 16; vec3 uvw; - uvw.xy = uv2 * draw_call.lightmap_uv_scale.zw + draw_call.lightmap_uv_scale.xy; + uvw.xy = uv2 * instances.data[draw_call.instance_index].lightmap_uv_scale.zw + instances.data[draw_call.instance_index].lightmap_uv_scale.xy; uvw.z = float(slice); if (uses_sh) { @@ -1162,7 +1197,7 @@ void main() { vec4 reflection_accum = vec4(0.0, 0.0, 0.0, 0.0); vec4 ambient_accum = vec4(0.0, 0.0, 0.0, 0.0); - uint reflection_indices = draw_call.reflection_probes.x; + uint reflection_indices = instances.data[draw_call.instance_index].reflection_probes.x; #ifdef LIGHT_ANISOTROPY_USED // https://google.github.io/filament/Filament.html#lighting/imagebasedlights/anisotropy @@ -1179,7 +1214,7 @@ void main() { for (uint i = 0; i < 8; i++) { uint reflection_index = reflection_indices & 0xFF; if (i == 3) { - reflection_indices = draw_call.reflection_probes.y; + reflection_indices = instances.data[draw_call.instance_index].reflection_probes.y; } else { reflection_indices = reflection_indices >> 8; } @@ -1260,7 +1295,7 @@ void main() { break; } - if (!bool(directional_lights.data[i].mask & draw_call.layer_mask)) { + if (!bool(directional_lights.data[i].mask & instances.data[draw_call.instance_index].layer_mask)) { continue; //not masked } @@ -1532,7 +1567,7 @@ void main() { break; } - if (!bool(directional_lights.data[i].mask & draw_call.layer_mask)) { + if (!bool(directional_lights.data[i].mask & instances.data[draw_call.instance_index].layer_mask)) { continue; //not masked } @@ -1601,11 +1636,11 @@ void main() { } //directional light if (!sc_disable_omni_lights) { //omni lights - uint light_indices = draw_call.omni_lights.x; + uint light_indices = instances.data[draw_call.instance_index].omni_lights.x; for (uint i = 0; i < 8; i++) { uint light_index = light_indices & 0xFF; if (i == 3) { - light_indices = draw_call.omni_lights.y; + light_indices = instances.data[draw_call.instance_index].omni_lights.y; } else { light_indices = light_indices >> 8; } @@ -1646,11 +1681,11 @@ void main() { if (!sc_disable_spot_lights) { //spot lights - uint light_indices = draw_call.spot_lights.x; + uint light_indices = instances.data[draw_call.instance_index].spot_lights.x; for (uint i = 0; i < 8; i++) { uint light_index = light_indices & 0xFF; if (i == 3) { - light_indices = draw_call.spot_lights.y; + light_indices = instances.data[draw_call.instance_index].spot_lights.y; } else { light_indices = light_indices >> 8; } diff --git a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl index d0a315858d..3de5e76970 100644 --- a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl @@ -15,20 +15,11 @@ #endif #define USING_MOBILE_RENDERER -/* don't exceed 128 bytes!! */ -/* put instance data into our push content, not a array */ -layout(push_constant, std430) uniform DrawCall { - highp mat4 transform; // 64 - 64 - uint flags; // 04 - 68 - uint instance_uniforms_ofs; //base offset in global buffer for instance variables // 04 - 72 - uint gi_offset; //GI information when using lightmapping (VCT or lightmap index) // 04 - 76 - uint layer_mask; // 04 - 80 - highp vec4 lightmap_uv_scale; // 16 - 96 doubles as uv_offset when needed - uvec2 reflection_probes; // 08 - 104 - uvec2 omni_lights; // 08 - 112 - uvec2 spot_lights; // 08 - 120 - uvec2 decals; // 08 - 128 +layout(push_constant, std430) uniform DrawCall { + vec2 uv_offset; + uint instance_index; + uint pad; } draw_call; @@ -123,6 +114,29 @@ layout(set = 1, binding = 0, std140) uniform SceneDataBlock { } scene_data_block; +struct InstanceData { + highp mat4 transform; // 64 - 64 + uint flags; // 04 - 68 + uint instance_uniforms_ofs; // Base offset in global buffer for instance variables. // 04 - 72 + uint gi_offset; // GI information when using lightmapping (VCT or lightmap index). // 04 - 76 + uint layer_mask; // 04 - 80 + highp vec4 lightmap_uv_scale; // 16 - 96 Doubles as uv_offset when needed. + + uvec2 reflection_probes; // 08 - 104 + uvec2 omni_lights; // 08 - 112 + uvec2 spot_lights; // 08 - 120 + uvec2 decals; // 08 - 128 + + vec4 compressed_aabb_position_pad; // 16 - 144 // Only .xyz is used. .w is padding. + vec4 compressed_aabb_size_pad; // 16 - 160 // Only .xyz is used. .w is padding. + vec4 uv_scale; // 16 - 176 +}; + +layout(set = 1, binding = 1, std430) buffer restrict readonly InstanceDataBuffer { + InstanceData data[]; +} +instances; + #ifdef USE_RADIANCE_CUBEMAP_ARRAY layout(set = 1, binding = 2) uniform mediump textureCubeArray radiance_cubemap; diff --git a/servers/rendering/renderer_rd/shaders/scene_data_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_data_inc.glsl index b57ee18521..f42fafc68a 100644 --- a/servers/rendering/renderer_rd/shaders/scene_data_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_data_inc.glsl @@ -64,6 +64,6 @@ struct SceneData { bool pancake_shadows; uint camera_visible_layers; - uint pad2; + float pass_alpha_multiplier; uint pad3; }; diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl index aa90ad6876..4fb577d697 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl @@ -71,7 +71,7 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, bool is_di mat4 inv_view_matrix = scene_data_block.data.inv_view_matrix; #ifdef USING_MOBILE_RENDERER - mat4 read_model_matrix = draw_call.transform; + mat4 read_model_matrix = instances.data[draw_call.instance_index].transform; #else mat4 read_model_matrix = instances.data[instance_index_interp].transform; #endif diff --git a/servers/rendering/renderer_rd/shaders/skeleton.glsl b/servers/rendering/renderer_rd/shaders/skeleton.glsl index 59c161548c..894dee1728 100644 --- a/servers/rendering/renderer_rd/shaders/skeleton.glsl +++ b/servers/rendering/renderer_rd/shaders/skeleton.glsl @@ -49,7 +49,7 @@ layout(push_constant, std430) uniform Params { uint blend_shape_count; bool normalized_blend_shapes; - uint pad0; + uint normal_tangent_stride; uint pad1; vec2 skeleton_transform_x; @@ -188,15 +188,15 @@ void main() { vertex = uintBitsToFloat(uvec3(src_vertices.data[src_offset + 0], src_vertices.data[src_offset + 1], src_vertices.data[src_offset + 2])); - src_offset += 3; + uint src_normal = params.vertex_count * params.vertex_stride + index * params.normal_tangent_stride; if (params.has_normal) { - normal = decode_uint_oct_to_norm(src_vertices.data[src_offset]); - src_offset++; + normal = decode_uint_oct_to_norm(src_vertices.data[src_normal]); + src_normal++; } if (params.has_tangent) { - tangent = decode_uint_oct_to_tang(src_vertices.data[src_offset]); + tangent = decode_uint_oct_to_tang(src_vertices.data[src_normal]); } if (params.has_blend_shape) { @@ -208,19 +208,19 @@ void main() { for (uint i = 0; i < params.blend_shape_count; i++) { float w = blend_shape_weights.data[i]; if (abs(w) > 0.0001) { - uint base_offset = (params.vertex_count * i + index) * params.vertex_stride; + uint base_offset = params.vertex_count * i * (params.vertex_stride + params.normal_tangent_stride) + index * params.vertex_stride; blend_vertex += uintBitsToFloat(uvec3(src_blend_shapes.data[base_offset + 0], src_blend_shapes.data[base_offset + 1], src_blend_shapes.data[base_offset + 2])) * w; - base_offset += 3; + uint base_normal = params.vertex_count * i * (params.vertex_stride + params.normal_tangent_stride) + params.vertex_count * params.vertex_stride + index * params.normal_tangent_stride; if (params.has_normal) { - blend_normal += decode_uint_oct_to_norm(src_blend_shapes.data[base_offset]) * w; - base_offset++; + blend_normal += decode_uint_oct_to_norm(src_blend_shapes.data[base_normal]) * w; + base_normal++; } if (params.has_tangent) { - blend_tangent += decode_uint_oct_to_tang(src_blend_shapes.data[base_offset]).rgb * w; + blend_tangent += decode_uint_oct_to_tang(src_blend_shapes.data[base_normal]).rgb * w; } blend_total += w; @@ -291,15 +291,15 @@ void main() { dst_vertices.data[dst_offset + 1] = uvertex.y; dst_vertices.data[dst_offset + 2] = uvertex.z; - dst_offset += 3; + uint dst_normal = params.vertex_count * params.vertex_stride + index * params.normal_tangent_stride; if (params.has_normal) { - dst_vertices.data[dst_offset] = encode_norm_to_uint_oct(normal); - dst_offset++; + dst_vertices.data[dst_normal] = encode_norm_to_uint_oct(normal); + dst_normal++; } if (params.has_tangent) { - dst_vertices.data[dst_offset] = encode_tang_to_uint_oct(tangent); + dst_vertices.data[dst_normal] = encode_tang_to_uint_oct(tangent); } #endif diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp index a5ec62b546..4fd33ad71a 100644 --- a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp @@ -174,14 +174,14 @@ void LightStorage::light_free(RID p_rid) { void LightStorage::light_set_color(RID p_light, const Color &p_color) { Light *light = light_owner.get_or_null(p_light); - ERR_FAIL_COND(!light); + ERR_FAIL_NULL(light); light->color = p_color; } void LightStorage::light_set_param(RID p_light, RS::LightParam p_param, float p_value) { Light *light = light_owner.get_or_null(p_light); - ERR_FAIL_COND(!light); + ERR_FAIL_NULL(light); ERR_FAIL_INDEX(p_param, RS::LIGHT_PARAM_MAX); if (light->param[p_param] == p_value) { @@ -216,7 +216,7 @@ void LightStorage::light_set_param(RID p_light, RS::LightParam p_param, float p_ void LightStorage::light_set_shadow(RID p_light, bool p_enabled) { Light *light = light_owner.get_or_null(p_light); - ERR_FAIL_COND(!light); + ERR_FAIL_NULL(light); light->shadow = p_enabled; light->version++; @@ -226,7 +226,7 @@ void LightStorage::light_set_shadow(RID p_light, bool p_enabled) { void LightStorage::light_set_projector(RID p_light, RID p_texture) { TextureStorage *texture_storage = TextureStorage::get_singleton(); Light *light = light_owner.get_or_null(p_light); - ERR_FAIL_COND(!light); + ERR_FAIL_NULL(light); if (light->projector == p_texture) { return; @@ -250,14 +250,14 @@ void LightStorage::light_set_projector(RID p_light, RID p_texture) { void LightStorage::light_set_negative(RID p_light, bool p_enable) { Light *light = light_owner.get_or_null(p_light); - ERR_FAIL_COND(!light); + ERR_FAIL_NULL(light); light->negative = p_enable; } void LightStorage::light_set_cull_mask(RID p_light, uint32_t p_mask) { Light *light = light_owner.get_or_null(p_light); - ERR_FAIL_COND(!light); + ERR_FAIL_NULL(light); light->cull_mask = p_mask; @@ -267,7 +267,7 @@ void LightStorage::light_set_cull_mask(RID p_light, uint32_t p_mask) { void LightStorage::light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) { Light *light = light_owner.get_or_null(p_light); - ERR_FAIL_COND(!light); + ERR_FAIL_NULL(light); light->distance_fade = p_enabled; light->distance_fade_begin = p_begin; @@ -277,7 +277,7 @@ void LightStorage::light_set_distance_fade(RID p_light, bool p_enabled, float p_ void LightStorage::light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) { Light *light = light_owner.get_or_null(p_light); - ERR_FAIL_COND(!light); + ERR_FAIL_NULL(light); light->reverse_cull = p_enabled; @@ -287,7 +287,7 @@ void LightStorage::light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) void LightStorage::light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) { Light *light = light_owner.get_or_null(p_light); - ERR_FAIL_COND(!light); + ERR_FAIL_NULL(light); light->bake_mode = p_bake_mode; @@ -297,7 +297,7 @@ void LightStorage::light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mod void LightStorage::light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) { Light *light = light_owner.get_or_null(p_light); - ERR_FAIL_COND(!light); + ERR_FAIL_NULL(light); light->max_sdfgi_cascade = p_cascade; @@ -307,7 +307,7 @@ void LightStorage::light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) void LightStorage::light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) { Light *light = light_owner.get_or_null(p_light); - ERR_FAIL_COND(!light); + ERR_FAIL_NULL(light); light->omni_shadow_mode = p_mode; @@ -317,14 +317,14 @@ void LightStorage::light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMo RS::LightOmniShadowMode LightStorage::light_omni_get_shadow_mode(RID p_light) { const Light *light = light_owner.get_or_null(p_light); - ERR_FAIL_COND_V(!light, RS::LIGHT_OMNI_SHADOW_CUBE); + ERR_FAIL_NULL_V(light, RS::LIGHT_OMNI_SHADOW_CUBE); return light->omni_shadow_mode; } void LightStorage::light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) { Light *light = light_owner.get_or_null(p_light); - ERR_FAIL_COND(!light); + ERR_FAIL_NULL(light); light->directional_shadow_mode = p_mode; light->version++; @@ -333,7 +333,7 @@ void LightStorage::light_directional_set_shadow_mode(RID p_light, RS::LightDirec void LightStorage::light_directional_set_blend_splits(RID p_light, bool p_enable) { Light *light = light_owner.get_or_null(p_light); - ERR_FAIL_COND(!light); + ERR_FAIL_NULL(light); light->directional_blend_splits = p_enable; light->version++; @@ -342,63 +342,63 @@ void LightStorage::light_directional_set_blend_splits(RID p_light, bool p_enable bool LightStorage::light_directional_get_blend_splits(RID p_light) const { const Light *light = light_owner.get_or_null(p_light); - ERR_FAIL_COND_V(!light, false); + ERR_FAIL_NULL_V(light, false); return light->directional_blend_splits; } void LightStorage::light_directional_set_sky_mode(RID p_light, RS::LightDirectionalSkyMode p_mode) { Light *light = light_owner.get_or_null(p_light); - ERR_FAIL_COND(!light); + ERR_FAIL_NULL(light); light->directional_sky_mode = p_mode; } RS::LightDirectionalSkyMode LightStorage::light_directional_get_sky_mode(RID p_light) const { const Light *light = light_owner.get_or_null(p_light); - ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_AND_SKY); + ERR_FAIL_NULL_V(light, RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_AND_SKY); return light->directional_sky_mode; } RS::LightDirectionalShadowMode LightStorage::light_directional_get_shadow_mode(RID p_light) { const Light *light = light_owner.get_or_null(p_light); - ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL); + ERR_FAIL_NULL_V(light, RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL); return light->directional_shadow_mode; } uint32_t LightStorage::light_get_max_sdfgi_cascade(RID p_light) { const Light *light = light_owner.get_or_null(p_light); - ERR_FAIL_COND_V(!light, 0); + ERR_FAIL_NULL_V(light, 0); return light->max_sdfgi_cascade; } RS::LightBakeMode LightStorage::light_get_bake_mode(RID p_light) { const Light *light = light_owner.get_or_null(p_light); - ERR_FAIL_COND_V(!light, RS::LIGHT_BAKE_DISABLED); + ERR_FAIL_NULL_V(light, RS::LIGHT_BAKE_DISABLED); return light->bake_mode; } uint64_t LightStorage::light_get_version(RID p_light) const { const Light *light = light_owner.get_or_null(p_light); - ERR_FAIL_COND_V(!light, 0); + ERR_FAIL_NULL_V(light, 0); return light->version; } uint32_t LightStorage::light_get_cull_mask(RID p_light) const { const Light *light = light_owner.get_or_null(p_light); - ERR_FAIL_COND_V(!light, 0); + ERR_FAIL_NULL_V(light, 0); return light->cull_mask; } AABB LightStorage::light_get_aabb(RID p_light) const { const Light *light = light_owner.get_or_null(p_light); - ERR_FAIL_COND_V(!light, AABB()); + ERR_FAIL_NULL_V(light, AABB()); switch (light->type) { case RS::LIGHT_SPOT: { @@ -471,21 +471,21 @@ void LightStorage::light_instance_free(RID p_light) { void LightStorage::light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) { LightInstance *light_instance = light_instance_owner.get_or_null(p_light_instance); - ERR_FAIL_COND(!light_instance); + ERR_FAIL_NULL(light_instance); light_instance->transform = p_transform; } void LightStorage::light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) { LightInstance *light_instance = light_instance_owner.get_or_null(p_light_instance); - ERR_FAIL_COND(!light_instance); + ERR_FAIL_NULL(light_instance); light_instance->aabb = p_aabb; } void LightStorage::light_instance_set_shadow_transform(RID p_light_instance, const Projection &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale, float p_range_begin, const Vector2 &p_uv_scale) { LightInstance *light_instance = light_instance_owner.get_or_null(p_light_instance); - ERR_FAIL_COND(!light_instance); + ERR_FAIL_NULL(light_instance); ERR_FAIL_INDEX(p_pass, 6); @@ -501,7 +501,7 @@ void LightStorage::light_instance_set_shadow_transform(RID p_light_instance, con void LightStorage::light_instance_mark_visible(RID p_light_instance) { LightInstance *light_instance = light_instance_owner.get_or_null(p_light_instance); - ERR_FAIL_COND(!light_instance); + ERR_FAIL_NULL(light_instance); light_instance->last_scene_pass = RendererSceneRenderRD::get_singleton()->get_scene_pass(); } @@ -1026,7 +1026,7 @@ void LightStorage::reflection_probe_free(RID p_rid) { void LightStorage::reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) { ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe); - ERR_FAIL_COND(!reflection_probe); + ERR_FAIL_NULL(reflection_probe); reflection_probe->update_mode = p_mode; reflection_probe->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE); @@ -1034,35 +1034,35 @@ void LightStorage::reflection_probe_set_update_mode(RID p_probe, RS::ReflectionP void LightStorage::reflection_probe_set_intensity(RID p_probe, float p_intensity) { ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe); - ERR_FAIL_COND(!reflection_probe); + ERR_FAIL_NULL(reflection_probe); reflection_probe->intensity = p_intensity; } void LightStorage::reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode) { ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe); - ERR_FAIL_COND(!reflection_probe); + ERR_FAIL_NULL(reflection_probe); reflection_probe->ambient_mode = p_mode; } void LightStorage::reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) { ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe); - ERR_FAIL_COND(!reflection_probe); + ERR_FAIL_NULL(reflection_probe); reflection_probe->ambient_color = p_color; } void LightStorage::reflection_probe_set_ambient_energy(RID p_probe, float p_energy) { ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe); - ERR_FAIL_COND(!reflection_probe); + ERR_FAIL_NULL(reflection_probe); reflection_probe->ambient_color_energy = p_energy; } void LightStorage::reflection_probe_set_max_distance(RID p_probe, float p_distance) { ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe); - ERR_FAIL_COND(!reflection_probe); + ERR_FAIL_NULL(reflection_probe); reflection_probe->max_distance = p_distance; @@ -1071,7 +1071,7 @@ void LightStorage::reflection_probe_set_max_distance(RID p_probe, float p_distan void LightStorage::reflection_probe_set_size(RID p_probe, const Vector3 &p_size) { ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe); - ERR_FAIL_COND(!reflection_probe); + ERR_FAIL_NULL(reflection_probe); if (reflection_probe->size == p_size) { return; @@ -1082,7 +1082,7 @@ void LightStorage::reflection_probe_set_size(RID p_probe, const Vector3 &p_size) void LightStorage::reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) { ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe); - ERR_FAIL_COND(!reflection_probe); + ERR_FAIL_NULL(reflection_probe); reflection_probe->origin_offset = p_offset; reflection_probe->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE); @@ -1090,7 +1090,7 @@ void LightStorage::reflection_probe_set_origin_offset(RID p_probe, const Vector3 void LightStorage::reflection_probe_set_as_interior(RID p_probe, bool p_enable) { ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe); - ERR_FAIL_COND(!reflection_probe); + ERR_FAIL_NULL(reflection_probe); reflection_probe->interior = p_enable; reflection_probe->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE); @@ -1098,14 +1098,14 @@ void LightStorage::reflection_probe_set_as_interior(RID p_probe, bool p_enable) void LightStorage::reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) { ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe); - ERR_FAIL_COND(!reflection_probe); + ERR_FAIL_NULL(reflection_probe); reflection_probe->box_projection = p_enable; } void LightStorage::reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) { ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe); - ERR_FAIL_COND(!reflection_probe); + ERR_FAIL_NULL(reflection_probe); reflection_probe->enable_shadows = p_enable; reflection_probe->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE); @@ -1113,7 +1113,7 @@ void LightStorage::reflection_probe_set_enable_shadows(RID p_probe, bool p_enabl void LightStorage::reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) { ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe); - ERR_FAIL_COND(!reflection_probe); + ERR_FAIL_NULL(reflection_probe); reflection_probe->cull_mask = p_layers; reflection_probe->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE); @@ -1121,7 +1121,7 @@ void LightStorage::reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers void LightStorage::reflection_probe_set_resolution(RID p_probe, int p_resolution) { ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe); - ERR_FAIL_COND(!reflection_probe); + ERR_FAIL_NULL(reflection_probe); ERR_FAIL_COND(p_resolution < 32); reflection_probe->resolution = p_resolution; @@ -1129,7 +1129,7 @@ void LightStorage::reflection_probe_set_resolution(RID p_probe, int p_resolution void LightStorage::reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ratio) { ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe); - ERR_FAIL_COND(!reflection_probe); + ERR_FAIL_NULL(reflection_probe); reflection_probe->mesh_lod_threshold = p_ratio; @@ -1138,14 +1138,14 @@ void LightStorage::reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ void LightStorage::reflection_probe_set_baked_exposure(RID p_probe, float p_exposure) { ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe); - ERR_FAIL_COND(!reflection_probe); + ERR_FAIL_NULL(reflection_probe); reflection_probe->baked_exposure = p_exposure; } AABB LightStorage::reflection_probe_get_aabb(RID p_probe) const { const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe); - ERR_FAIL_COND_V(!reflection_probe, AABB()); + ERR_FAIL_NULL_V(reflection_probe, AABB()); AABB aabb; aabb.position = -reflection_probe->size / 2; @@ -1156,103 +1156,103 @@ AABB LightStorage::reflection_probe_get_aabb(RID p_probe) const { RS::ReflectionProbeUpdateMode LightStorage::reflection_probe_get_update_mode(RID p_probe) const { const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe); - ERR_FAIL_COND_V(!reflection_probe, RS::REFLECTION_PROBE_UPDATE_ALWAYS); + ERR_FAIL_NULL_V(reflection_probe, RS::REFLECTION_PROBE_UPDATE_ALWAYS); return reflection_probe->update_mode; } uint32_t LightStorage::reflection_probe_get_cull_mask(RID p_probe) const { const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe); - ERR_FAIL_COND_V(!reflection_probe, 0); + ERR_FAIL_NULL_V(reflection_probe, 0); return reflection_probe->cull_mask; } Vector3 LightStorage::reflection_probe_get_size(RID p_probe) const { const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe); - ERR_FAIL_COND_V(!reflection_probe, Vector3()); + ERR_FAIL_NULL_V(reflection_probe, Vector3()); return reflection_probe->size; } Vector3 LightStorage::reflection_probe_get_origin_offset(RID p_probe) const { const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe); - ERR_FAIL_COND_V(!reflection_probe, Vector3()); + ERR_FAIL_NULL_V(reflection_probe, Vector3()); return reflection_probe->origin_offset; } bool LightStorage::reflection_probe_renders_shadows(RID p_probe) const { const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe); - ERR_FAIL_COND_V(!reflection_probe, false); + ERR_FAIL_NULL_V(reflection_probe, false); return reflection_probe->enable_shadows; } float LightStorage::reflection_probe_get_origin_max_distance(RID p_probe) const { const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe); - ERR_FAIL_COND_V(!reflection_probe, 0); + ERR_FAIL_NULL_V(reflection_probe, 0); return reflection_probe->max_distance; } float LightStorage::reflection_probe_get_mesh_lod_threshold(RID p_probe) const { const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe); - ERR_FAIL_COND_V(!reflection_probe, 0); + ERR_FAIL_NULL_V(reflection_probe, 0); return reflection_probe->mesh_lod_threshold; } int LightStorage::reflection_probe_get_resolution(RID p_probe) const { const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe); - ERR_FAIL_COND_V(!reflection_probe, 0); + ERR_FAIL_NULL_V(reflection_probe, 0); return reflection_probe->resolution; } float LightStorage::reflection_probe_get_baked_exposure(RID p_probe) const { const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe); - ERR_FAIL_COND_V(!reflection_probe, 1.0); + ERR_FAIL_NULL_V(reflection_probe, 1.0); return reflection_probe->baked_exposure; } float LightStorage::reflection_probe_get_intensity(RID p_probe) const { const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe); - ERR_FAIL_COND_V(!reflection_probe, 0); + ERR_FAIL_NULL_V(reflection_probe, 0); return reflection_probe->intensity; } bool LightStorage::reflection_probe_is_interior(RID p_probe) const { const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe); - ERR_FAIL_COND_V(!reflection_probe, false); + ERR_FAIL_NULL_V(reflection_probe, false); return reflection_probe->interior; } bool LightStorage::reflection_probe_is_box_projection(RID p_probe) const { const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe); - ERR_FAIL_COND_V(!reflection_probe, false); + ERR_FAIL_NULL_V(reflection_probe, false); return reflection_probe->box_projection; } RS::ReflectionProbeAmbientMode LightStorage::reflection_probe_get_ambient_mode(RID p_probe) const { const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe); - ERR_FAIL_COND_V(!reflection_probe, RS::REFLECTION_PROBE_AMBIENT_DISABLED); + ERR_FAIL_NULL_V(reflection_probe, RS::REFLECTION_PROBE_AMBIENT_DISABLED); return reflection_probe->ambient_mode; } Color LightStorage::reflection_probe_get_ambient_color(RID p_probe) const { const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe); - ERR_FAIL_COND_V(!reflection_probe, Color()); + ERR_FAIL_NULL_V(reflection_probe, Color()); return reflection_probe->ambient_color; } float LightStorage::reflection_probe_get_ambient_color_energy(RID p_probe) const { const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe); - ERR_FAIL_COND_V(!reflection_probe, 0); + ERR_FAIL_NULL_V(reflection_probe, 0); return reflection_probe->ambient_color_energy; } @@ -1286,7 +1286,7 @@ void LightStorage::reflection_atlas_free(RID p_ref_atlas) { void LightStorage::reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) { ReflectionAtlas *ra = reflection_atlas_owner.get_or_null(p_ref_atlas); - ERR_FAIL_COND(!ra); + ERR_FAIL_NULL(ra); if (ra->size == p_reflection_size && ra->count == p_reflection_count) { return; //no changes @@ -1325,7 +1325,7 @@ void LightStorage::reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_s int LightStorage::reflection_atlas_get_size(RID p_ref_atlas) const { ReflectionAtlas *ra = reflection_atlas_owner.get_or_null(p_ref_atlas); - ERR_FAIL_COND_V(!ra, 0); + ERR_FAIL_NULL_V(ra, 0); return ra->size; } @@ -1349,7 +1349,7 @@ void LightStorage::reflection_probe_instance_free(RID p_instance) { void LightStorage::reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) { ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); - ERR_FAIL_COND(!rpi); + ERR_FAIL_NULL(rpi); rpi->transform = p_transform; rpi->dirty = true; @@ -1357,13 +1357,13 @@ void LightStorage::reflection_probe_instance_set_transform(RID p_instance, const void LightStorage::reflection_probe_release_atlas_index(RID p_instance) { ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); - ERR_FAIL_COND(!rpi); + ERR_FAIL_NULL(rpi); if (rpi->atlas.is_null()) { return; //nothing to release } ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(rpi->atlas); - ERR_FAIL_COND(!atlas); + ERR_FAIL_NULL(atlas); ERR_FAIL_INDEX(rpi->atlas_index, atlas->reflections.size()); atlas->reflections.write[rpi->atlas_index].owner = RID(); @@ -1375,7 +1375,7 @@ void LightStorage::reflection_probe_release_atlas_index(RID p_instance) { bool LightStorage::reflection_probe_instance_needs_redraw(RID p_instance) { ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); - ERR_FAIL_COND_V(!rpi, false); + ERR_FAIL_NULL_V(rpi, false); if (rpi->rendering) { return false; @@ -1394,7 +1394,7 @@ bool LightStorage::reflection_probe_instance_needs_redraw(RID p_instance) { bool LightStorage::reflection_probe_instance_has_reflection(RID p_instance) { ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); - ERR_FAIL_COND_V(!rpi, false); + ERR_FAIL_NULL_V(rpi, false); return rpi->atlas.is_valid(); } @@ -1402,10 +1402,10 @@ bool LightStorage::reflection_probe_instance_has_reflection(RID p_instance) { bool LightStorage::reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) { ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(p_reflection_atlas); - ERR_FAIL_COND_V(!atlas, false); + ERR_FAIL_NULL_V(atlas, false); ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); - ERR_FAIL_COND_V(!rpi, false); + ERR_FAIL_NULL_V(rpi, false); if (atlas->render_buffers.is_null()) { atlas->render_buffers.instantiate(); @@ -1511,14 +1511,14 @@ bool LightStorage::reflection_probe_instance_begin_render(RID p_instance, RID p_ Ref<RenderSceneBuffers> LightStorage::reflection_probe_atlas_get_render_buffers(RID p_reflection_atlas) { ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(p_reflection_atlas); - ERR_FAIL_COND_V(!atlas, Ref<RenderSceneBuffersRD>()); + ERR_FAIL_NULL_V(atlas, Ref<RenderSceneBuffersRD>()); return atlas->render_buffers; } bool LightStorage::reflection_probe_instance_postprocess_step(RID p_instance) { ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); - ERR_FAIL_COND_V(!rpi, false); + ERR_FAIL_NULL_V(rpi, false); ERR_FAIL_COND_V(!rpi->rendering, false); ERR_FAIL_COND_V(rpi->atlas.is_null(), false); @@ -1569,30 +1569,30 @@ bool LightStorage::reflection_probe_instance_postprocess_step(RID p_instance) { uint32_t LightStorage::reflection_probe_instance_get_resolution(RID p_instance) { ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); - ERR_FAIL_COND_V(!rpi, 0); + ERR_FAIL_NULL_V(rpi, 0); ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(rpi->atlas); - ERR_FAIL_COND_V(!atlas, 0); + ERR_FAIL_NULL_V(atlas, 0); return atlas->size; } RID LightStorage::reflection_probe_instance_get_framebuffer(RID p_instance, int p_index) { ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); - ERR_FAIL_COND_V(!rpi, RID()); + ERR_FAIL_NULL_V(rpi, RID()); ERR_FAIL_INDEX_V(p_index, 6, RID()); ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(rpi->atlas); - ERR_FAIL_COND_V(!atlas, RID()); + ERR_FAIL_NULL_V(atlas, RID()); return atlas->reflections[rpi->atlas_index].fbs[p_index]; } RID LightStorage::reflection_probe_instance_get_depth_framebuffer(RID p_instance, int p_index) { ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); - ERR_FAIL_COND_V(!rpi, RID()); + ERR_FAIL_NULL_V(rpi, RID()); ERR_FAIL_INDEX_V(p_index, 6, RID()); ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(rpi->atlas); - ERR_FAIL_COND_V(!atlas, RID()); + ERR_FAIL_NULL_V(atlas, RID()); return atlas->depth_fb; } @@ -1747,7 +1747,7 @@ void LightStorage::lightmap_set_textures(RID p_lightmap, RID p_light, bool p_use TextureStorage *texture_storage = TextureStorage::get_singleton(); Lightmap *lm = lightmap_owner.get_or_null(p_lightmap); - ERR_FAIL_COND(!lm); + ERR_FAIL_NULL(lm); lightmap_array_version++; @@ -1795,19 +1795,19 @@ void LightStorage::lightmap_set_textures(RID p_lightmap, RID p_light, bool p_use void LightStorage::lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) { Lightmap *lm = lightmap_owner.get_or_null(p_lightmap); - ERR_FAIL_COND(!lm); + ERR_FAIL_NULL(lm); lm->bounds = p_bounds; } void LightStorage::lightmap_set_probe_interior(RID p_lightmap, bool p_interior) { Lightmap *lm = lightmap_owner.get_or_null(p_lightmap); - ERR_FAIL_COND(!lm); + ERR_FAIL_NULL(lm); lm->interior = p_interior; } void LightStorage::lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) { Lightmap *lm = lightmap_owner.get_or_null(p_lightmap); - ERR_FAIL_COND(!lm); + ERR_FAIL_NULL(lm); if (p_points.size()) { ERR_FAIL_COND(p_points.size() * 9 != p_point_sh.size()); @@ -1823,33 +1823,33 @@ void LightStorage::lightmap_set_probe_capture_data(RID p_lightmap, const PackedV void LightStorage::lightmap_set_baked_exposure_normalization(RID p_lightmap, float p_exposure) { Lightmap *lm = lightmap_owner.get_or_null(p_lightmap); - ERR_FAIL_COND(!lm); + ERR_FAIL_NULL(lm); lm->baked_exposure = p_exposure; } PackedVector3Array LightStorage::lightmap_get_probe_capture_points(RID p_lightmap) const { Lightmap *lm = lightmap_owner.get_or_null(p_lightmap); - ERR_FAIL_COND_V(!lm, PackedVector3Array()); + ERR_FAIL_NULL_V(lm, PackedVector3Array()); return lm->points; } PackedColorArray LightStorage::lightmap_get_probe_capture_sh(RID p_lightmap) const { Lightmap *lm = lightmap_owner.get_or_null(p_lightmap); - ERR_FAIL_COND_V(!lm, PackedColorArray()); + ERR_FAIL_NULL_V(lm, PackedColorArray()); return lm->point_sh; } PackedInt32Array LightStorage::lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const { Lightmap *lm = lightmap_owner.get_or_null(p_lightmap); - ERR_FAIL_COND_V(!lm, PackedInt32Array()); + ERR_FAIL_NULL_V(lm, PackedInt32Array()); return lm->tetrahedra; } PackedInt32Array LightStorage::lightmap_get_probe_capture_bsp_tree(RID p_lightmap) const { Lightmap *lm = lightmap_owner.get_or_null(p_lightmap); - ERR_FAIL_COND_V(!lm, PackedInt32Array()); + ERR_FAIL_NULL_V(lm, PackedInt32Array()); return lm->bsp_tree; } @@ -1866,7 +1866,7 @@ Dependency *LightStorage::lightmap_get_dependency(RID p_lightmap) const { void LightStorage::lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) { Lightmap *lm = lightmap_owner.get_or_null(p_lightmap); - ERR_FAIL_COND(!lm); + ERR_FAIL_NULL(lm); for (int i = 0; i < 9; i++) { r_sh[i] = Color(0, 0, 0, 0); @@ -1916,13 +1916,13 @@ void LightStorage::lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, bool LightStorage::lightmap_is_interior(RID p_lightmap) const { const Lightmap *lm = lightmap_owner.get_or_null(p_lightmap); - ERR_FAIL_COND_V(!lm, false); + ERR_FAIL_NULL_V(lm, false); return lm->interior; } AABB LightStorage::lightmap_get_aabb(RID p_lightmap) const { const Lightmap *lm = lightmap_owner.get_or_null(p_lightmap); - ERR_FAIL_COND_V(!lm, AABB()); + ERR_FAIL_NULL_V(lm, AABB()); return lm->bounds; } @@ -1940,7 +1940,7 @@ void LightStorage::lightmap_instance_free(RID p_lightmap) { void LightStorage::lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) { LightmapInstance *li = lightmap_instance_owner.get_or_null(p_lightmap); - ERR_FAIL_COND(!li); + ERR_FAIL_NULL(li); li->transform = p_transform; } @@ -1972,7 +1972,7 @@ void LightStorage::_update_shadow_atlas(ShadowAtlas *shadow_atlas) { void LightStorage::shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits) { ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_atlas); - ERR_FAIL_COND(!shadow_atlas); + ERR_FAIL_NULL(shadow_atlas); ERR_FAIL_COND(p_size < 0); p_size = next_power_of_2(p_size); @@ -2007,7 +2007,7 @@ void LightStorage::shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits void LightStorage::shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) { ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_atlas); - ERR_FAIL_COND(!shadow_atlas); + ERR_FAIL_NULL(shadow_atlas); ERR_FAIL_INDEX(p_quadrant, 4); ERR_FAIL_INDEX(p_subdivision, 16384); @@ -2196,10 +2196,10 @@ bool LightStorage::_shadow_atlas_find_omni_shadows(ShadowAtlas *shadow_atlas, in bool LightStorage::shadow_atlas_update_light(RID p_atlas, RID p_light_instance, float p_coverage, uint64_t p_light_version) { ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_atlas); - ERR_FAIL_COND_V(!shadow_atlas, false); + ERR_FAIL_NULL_V(shadow_atlas, false); LightInstance *li = light_instance_owner.get_or_null(p_light_instance); - ERR_FAIL_COND_V(!li, false); + ERR_FAIL_NULL_V(li, false); if (shadow_atlas->size == 0 || shadow_atlas->smallest_subdiv == 0) { return false; @@ -2341,7 +2341,7 @@ void LightStorage::_shadow_atlas_invalidate_shadow(ShadowAtlas::Quadrant::Shadow void LightStorage::shadow_atlas_update(RID p_atlas) { ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_atlas); - ERR_FAIL_COND(!shadow_atlas); + ERR_FAIL_NULL(shadow_atlas); _update_shadow_atlas(shadow_atlas); } @@ -2416,7 +2416,7 @@ int LightStorage::get_directional_light_shadow_size(RID p_light_intance) { Rect2i r = _get_directional_shadow_rect(directional_shadow.size, directional_shadow.light_count, 0); LightInstance *light_instance = light_instance_owner.get_or_null(p_light_intance); - ERR_FAIL_COND_V(!light_instance, 0); + ERR_FAIL_NULL_V(light_instance, 0); switch (light_directional_get_shadow_mode(light_instance->light)) { case RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.h b/servers/rendering/renderer_rd/storage_rd/light_storage.h index 512c440ae8..f5b846362a 100644 --- a/servers/rendering/renderer_rd/storage_rd/light_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/light_storage.h @@ -490,7 +490,7 @@ public: virtual RS::LightType light_get_type(RID p_light) const override { const Light *light = light_owner.get_or_null(p_light); - ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL); + ERR_FAIL_NULL_V(light, RS::LIGHT_DIRECTIONAL); return light->type; } @@ -498,21 +498,21 @@ public: virtual float light_get_param(RID p_light, RS::LightParam p_param) override { const Light *light = light_owner.get_or_null(p_light); - ERR_FAIL_COND_V(!light, 0); + ERR_FAIL_NULL_V(light, 0); return light->param[p_param]; } _FORCE_INLINE_ RID light_get_projector(RID p_light) { const Light *light = light_owner.get_or_null(p_light); - ERR_FAIL_COND_V(!light, RID()); + ERR_FAIL_NULL_V(light, RID()); return light->projector; } virtual Color light_get_color(RID p_light) override { const Light *light = light_owner.get_or_null(p_light); - ERR_FAIL_COND_V(!light, Color()); + ERR_FAIL_NULL_V(light, Color()); return light->color; } @@ -539,35 +539,35 @@ public: virtual bool light_has_shadow(RID p_light) const override { const Light *light = light_owner.get_or_null(p_light); - ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL); + ERR_FAIL_NULL_V(light, RS::LIGHT_DIRECTIONAL); return light->shadow; } virtual bool light_has_projector(RID p_light) const override { const Light *light = light_owner.get_or_null(p_light); - ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL); + ERR_FAIL_NULL_V(light, RS::LIGHT_DIRECTIONAL); return TextureStorage::get_singleton()->owns_texture(light->projector); } _FORCE_INLINE_ bool light_is_negative(RID p_light) const { const Light *light = light_owner.get_or_null(p_light); - ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL); + ERR_FAIL_NULL_V(light, RS::LIGHT_DIRECTIONAL); return light->negative; } _FORCE_INLINE_ float light_get_transmittance_bias(RID p_light) const { const Light *light = light_owner.get_or_null(p_light); - ERR_FAIL_COND_V(!light, 0.0); + ERR_FAIL_NULL_V(light, 0.0); return light->param[RS::LIGHT_PARAM_TRANSMITTANCE_BIAS]; } virtual bool light_get_reverse_cull_face_mode(RID p_light) const override { const Light *light = light_owner.get_or_null(p_light); - ERR_FAIL_COND_V(!light, false); + ERR_FAIL_NULL_V(light, false); return light->reverse_cull; } @@ -657,7 +657,7 @@ public: ERR_FAIL_COND_V(!li->shadow_atlases.has(p_shadow_atlas), 0); #endif ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_shadow_atlas); - ERR_FAIL_COND_V(!shadow_atlas, 0); + ERR_FAIL_NULL_V(shadow_atlas, 0); #ifdef DEBUG_ENABLED ERR_FAIL_COND_V(!shadow_atlas->shadow_owners.has(p_light_instance), 0); #endif @@ -677,8 +677,7 @@ public: return li->shadow_transform[p_index].camera; } - _FORCE_INLINE_ Transform3D - light_instance_get_shadow_transform(RID p_light_instance, int p_index) { + _FORCE_INLINE_ Transform3D light_instance_get_shadow_transform(RID p_light_instance, int p_index) { LightInstance *li = light_instance_owner.get_or_null(p_light_instance); return li->shadow_transform[p_index].transform; } @@ -835,7 +834,7 @@ public: _FORCE_INLINE_ RID reflection_atlas_get_texture(RID p_ref_atlas) { ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(p_ref_atlas); - ERR_FAIL_COND_V(!atlas, RID()); + ERR_FAIL_NULL_V(atlas, RID()); return atlas->reflection; } @@ -859,47 +858,47 @@ public: _FORCE_INLINE_ RID reflection_probe_instance_get_probe(RID p_instance) { ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); - ERR_FAIL_COND_V(!rpi, RID()); + ERR_FAIL_NULL_V(rpi, RID()); return rpi->probe; } _FORCE_INLINE_ RendererRD::ForwardID reflection_probe_instance_get_forward_id(RID p_instance) { ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); - ERR_FAIL_COND_V(!rpi, 0); + ERR_FAIL_NULL_V(rpi, 0); return rpi->forward_id; } _FORCE_INLINE_ void reflection_probe_instance_set_cull_mask(RID p_instance, uint32_t p_render_pass) { ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); - ERR_FAIL_COND(!rpi); + ERR_FAIL_NULL(rpi); rpi->cull_mask = p_render_pass; } _FORCE_INLINE_ void reflection_probe_instance_set_render_pass(RID p_instance, uint32_t p_render_pass) { ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); - ERR_FAIL_COND(!rpi); + ERR_FAIL_NULL(rpi); rpi->last_pass = p_render_pass; } _FORCE_INLINE_ uint32_t reflection_probe_instance_get_render_pass(RID p_instance) { ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); - ERR_FAIL_COND_V(!rpi, 0); + ERR_FAIL_NULL_V(rpi, 0); return rpi->last_pass; } _FORCE_INLINE_ Transform3D reflection_probe_instance_get_transform(RID p_instance) { ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); - ERR_FAIL_COND_V(!rpi, Transform3D()); + ERR_FAIL_NULL_V(rpi, Transform3D()); return rpi->transform; } _FORCE_INLINE_ int reflection_probe_instance_get_atlas_index(RID p_instance) { ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance); - ERR_FAIL_COND_V(!rpi, -1); + ERR_FAIL_NULL_V(rpi, -1); return rpi->atlas_index; } @@ -942,12 +941,12 @@ public: } _FORCE_INLINE_ RID lightmap_get_texture(RID p_lightmap) const { const Lightmap *lm = lightmap_owner.get_or_null(p_lightmap); - ERR_FAIL_COND_V(!lm, RID()); + ERR_FAIL_NULL_V(lm, RID()); return lm->light_texture; } _FORCE_INLINE_ float lightmap_get_baked_exposure_normalization(RID p_lightmap) const { const Lightmap *lm = lightmap_owner.get_or_null(p_lightmap); - ERR_FAIL_COND_V(!lm, 1.0); + ERR_FAIL_NULL_V(lm, 1.0); return lm->baked_exposure; } _FORCE_INLINE_ int32_t lightmap_get_array_index(RID p_lightmap) const { @@ -1005,46 +1004,46 @@ public: virtual void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits = true) override; virtual void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) override; virtual bool shadow_atlas_update_light(RID p_atlas, RID p_light_instance, float p_coverage, uint64_t p_light_version) override; - _FORCE_INLINE_ bool shadow_atlas_owns_light_instance(RID p_atlas, RID p_light_intance) { + _FORCE_INLINE_ bool shadow_atlas_owns_light_instance(RID p_atlas, RID p_light_instance) { ShadowAtlas *atlas = shadow_atlas_owner.get_or_null(p_atlas); - ERR_FAIL_COND_V(!atlas, false); - return atlas->shadow_owners.has(p_light_intance); + ERR_FAIL_NULL_V(atlas, false); + return atlas->shadow_owners.has(p_light_instance); } - _FORCE_INLINE_ uint32_t shadow_atlas_get_light_instance_key(RID p_atlas, RID p_light_intance) { + _FORCE_INLINE_ uint32_t shadow_atlas_get_light_instance_key(RID p_atlas, RID p_light_instance) { ShadowAtlas *atlas = shadow_atlas_owner.get_or_null(p_atlas); - ERR_FAIL_COND_V(!atlas, -1); - return atlas->shadow_owners[p_light_intance]; + ERR_FAIL_NULL_V(atlas, -1); + return atlas->shadow_owners[p_light_instance]; } _FORCE_INLINE_ RID shadow_atlas_get_texture(RID p_atlas) { ShadowAtlas *atlas = shadow_atlas_owner.get_or_null(p_atlas); - ERR_FAIL_COND_V(!atlas, RID()); + ERR_FAIL_NULL_V(atlas, RID()); return atlas->depth; } _FORCE_INLINE_ int shadow_atlas_get_size(RID p_atlas) { ShadowAtlas *atlas = shadow_atlas_owner.get_or_null(p_atlas); - ERR_FAIL_COND_V(!atlas, 0); + ERR_FAIL_NULL_V(atlas, 0); return atlas->size; } _FORCE_INLINE_ int shadow_atlas_get_quadrant_shadow_size(RID p_atlas, uint32_t p_quadrant) { ShadowAtlas *atlas = shadow_atlas_owner.get_or_null(p_atlas); - ERR_FAIL_COND_V(!atlas, 0); + ERR_FAIL_NULL_V(atlas, 0); ERR_FAIL_UNSIGNED_INDEX_V(p_quadrant, 4, 0); return atlas->quadrants[p_quadrant].shadows.size(); } _FORCE_INLINE_ uint32_t shadow_atlas_get_quadrant_subdivision(RID p_atlas, uint32_t p_quadrant) { ShadowAtlas *atlas = shadow_atlas_owner.get_or_null(p_atlas); - ERR_FAIL_COND_V(!atlas, 0); + ERR_FAIL_NULL_V(atlas, 0); ERR_FAIL_UNSIGNED_INDEX_V(p_quadrant, 4, 0); return atlas->quadrants[p_quadrant].subdivision; } _FORCE_INLINE_ RID shadow_atlas_get_fb(RID p_atlas) { ShadowAtlas *atlas = shadow_atlas_owner.get_or_null(p_atlas); - ERR_FAIL_COND_V(!atlas, RID()); + ERR_FAIL_NULL_V(atlas, RID()); return atlas->fb; } @@ -1053,7 +1052,7 @@ public: /* DIRECTIONAL SHADOW */ virtual void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = true) override; - virtual int get_directional_light_shadow_size(RID p_light_intance) override; + virtual int get_directional_light_shadow_size(RID p_light_instance) override; virtual void set_directional_shadow_count(int p_count) override; Rect2i get_directional_shadow_rect(); diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp index c40b74743b..3bd35c53cc 100644 --- a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp @@ -931,11 +931,11 @@ void MaterialStorage::MaterialData::update_textures(const HashMap<StringName, Va roughness_detect_texture = tex; roughness_channel = RS::TextureDetectRoughnessChannel(p_texture_uniforms[i].hint - ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_R); } +#endif // TOOLS_ENABLED if (tex->render_target) { tex->render_target->was_used = true; render_target_cache.push_back(tex->render_target); } -#endif } if (rd_texture.is_null()) { rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_WHITE); @@ -1834,7 +1834,7 @@ void MaterialStorage::shader_initialize(RID p_rid) { void MaterialStorage::shader_free(RID p_rid) { Shader *shader = shader_owner.get_or_null(p_rid); - ERR_FAIL_COND(!shader); + ERR_FAIL_NULL(shader); //make material unreference this while (shader->owners.size()) { @@ -1850,7 +1850,7 @@ void MaterialStorage::shader_free(RID p_rid) { void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) { Shader *shader = shader_owner.get_or_null(p_shader); - ERR_FAIL_COND(!shader); + ERR_FAIL_NULL(shader); shader->code = p_code; String mode_string = ShaderLanguage::get_shader_type(p_code); @@ -1927,7 +1927,7 @@ void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) { void MaterialStorage::shader_set_path_hint(RID p_shader, const String &p_path) { Shader *shader = shader_owner.get_or_null(p_shader); - ERR_FAIL_COND(!shader); + ERR_FAIL_NULL(shader); shader->path_hint = p_path; if (shader->data) { @@ -1937,13 +1937,13 @@ void MaterialStorage::shader_set_path_hint(RID p_shader, const String &p_path) { String MaterialStorage::shader_get_code(RID p_shader) const { Shader *shader = shader_owner.get_or_null(p_shader); - ERR_FAIL_COND_V(!shader, String()); + ERR_FAIL_NULL_V(shader, String()); return shader->code; } void MaterialStorage::get_shader_parameter_list(RID p_shader, List<PropertyInfo> *p_param_list) const { Shader *shader = shader_owner.get_or_null(p_shader); - ERR_FAIL_COND(!shader); + ERR_FAIL_NULL(shader); if (shader->data) { return shader->data->get_shader_uniform_list(p_param_list); } @@ -1951,7 +1951,7 @@ void MaterialStorage::get_shader_parameter_list(RID p_shader, List<PropertyInfo> void MaterialStorage::shader_set_default_texture_parameter(RID p_shader, const StringName &p_name, RID p_texture, int p_index) { Shader *shader = shader_owner.get_or_null(p_shader); - ERR_FAIL_COND(!shader); + ERR_FAIL_NULL(shader); if (p_texture.is_valid() && TextureStorage::get_singleton()->owns_texture(p_texture)) { if (!shader->default_texture_parameter.has(p_name)) { @@ -1978,7 +1978,7 @@ void MaterialStorage::shader_set_default_texture_parameter(RID p_shader, const S RID MaterialStorage::shader_get_default_texture_parameter(RID p_shader, const StringName &p_name, int p_index) const { Shader *shader = shader_owner.get_or_null(p_shader); - ERR_FAIL_COND_V(!shader, RID()); + ERR_FAIL_NULL_V(shader, RID()); if (shader->default_texture_parameter.has(p_name) && shader->default_texture_parameter[p_name].has(p_index)) { return shader->default_texture_parameter[p_name][p_index]; } @@ -1988,7 +1988,7 @@ RID MaterialStorage::shader_get_default_texture_parameter(RID p_shader, const St Variant MaterialStorage::shader_get_parameter_default(RID p_shader, const StringName &p_param) const { Shader *shader = shader_owner.get_or_null(p_shader); - ERR_FAIL_COND_V(!shader, Variant()); + ERR_FAIL_NULL_V(shader, Variant()); if (shader->data) { return shader->data->get_default_parameter(p_param); } @@ -2002,7 +2002,7 @@ void MaterialStorage::shader_set_data_request_function(ShaderType p_shader_type, RS::ShaderNativeSourceCode MaterialStorage::shader_get_native_source_code(RID p_shader) const { Shader *shader = shader_owner.get_or_null(p_shader); - ERR_FAIL_COND_V(!shader, RS::ShaderNativeSourceCode()); + ERR_FAIL_NULL_V(shader, RS::ShaderNativeSourceCode()); if (shader->data) { return shader->data->get_native_source_code(); } @@ -2067,7 +2067,7 @@ void MaterialStorage::material_initialize(RID p_rid) { void MaterialStorage::material_free(RID p_rid) { Material *material = material_owner.get_or_null(p_rid); - ERR_FAIL_COND(!material); + ERR_FAIL_NULL(material); // Need to clear texture arrays to prevent spin locking of their RID's. // This happens when the app is being closed. @@ -2085,7 +2085,7 @@ void MaterialStorage::material_free(RID p_rid) { void MaterialStorage::material_set_shader(RID p_material, RID p_shader) { Material *material = material_owner.get_or_null(p_material); - ERR_FAIL_COND(!material); + ERR_FAIL_NULL(material); if (material->data) { memdelete(material->data); @@ -2105,7 +2105,7 @@ void MaterialStorage::material_set_shader(RID p_material, RID p_shader) { } Shader *shader = get_shader(p_shader); - ERR_FAIL_COND(!shader); + ERR_FAIL_NULL(shader); material->shader = shader; material->shader_type = shader->type; material->shader_id = p_shader.get_local_index(); @@ -2137,7 +2137,7 @@ MaterialStorage::ShaderData *MaterialStorage::material_get_shader_data(RID p_mat void MaterialStorage::material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) { Material *material = material_owner.get_or_null(p_material); - ERR_FAIL_COND(!material); + ERR_FAIL_NULL(material); if (p_value.get_type() == Variant::NIL) { material->params.erase(p_param); @@ -2156,7 +2156,7 @@ void MaterialStorage::material_set_param(RID p_material, const StringName &p_par Variant MaterialStorage::material_get_param(RID p_material, const StringName &p_param) const { Material *material = material_owner.get_or_null(p_material); - ERR_FAIL_COND_V(!material, Variant()); + ERR_FAIL_NULL_V(material, Variant()); if (material->params.has(p_param)) { return material->params[p_param]; } else { @@ -2166,7 +2166,7 @@ Variant MaterialStorage::material_get_param(RID p_material, const StringName &p_ void MaterialStorage::material_set_next_pass(RID p_material, RID p_next_material) { Material *material = material_owner.get_or_null(p_material); - ERR_FAIL_COND(!material); + ERR_FAIL_NULL(material); if (material->next_pass == p_next_material) { return; @@ -2182,7 +2182,7 @@ void MaterialStorage::material_set_next_pass(RID p_material, RID p_next_material void MaterialStorage::material_set_render_priority(RID p_material, int priority) { Material *material = material_owner.get_or_null(p_material); - ERR_FAIL_COND(!material); + ERR_FAIL_NULL(material); material->priority = priority; if (material->data) { material->data->set_render_priority(priority); @@ -2192,7 +2192,7 @@ void MaterialStorage::material_set_render_priority(RID p_material, int priority) bool MaterialStorage::material_is_animated(RID p_material) { Material *material = material_owner.get_or_null(p_material); - ERR_FAIL_COND_V(!material, false); + ERR_FAIL_NULL_V(material, false); if (material->shader && material->shader->data) { if (material->shader->data->is_animated()) { return true; @@ -2205,7 +2205,7 @@ bool MaterialStorage::material_is_animated(RID p_material) { bool MaterialStorage::material_casts_shadows(RID p_material) { Material *material = material_owner.get_or_null(p_material); - ERR_FAIL_COND_V(!material, true); + ERR_FAIL_NULL_V(material, true); if (material->shader && material->shader->data) { if (material->shader->data->casts_shadows()) { return true; @@ -2218,7 +2218,7 @@ bool MaterialStorage::material_casts_shadows(RID p_material) { void MaterialStorage::material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) { Material *material = material_owner.get_or_null(p_material); - ERR_FAIL_COND(!material); + ERR_FAIL_NULL(material); if (material->shader && material->shader->data) { material->shader->data->get_instance_param_list(r_parameters); @@ -2230,7 +2230,7 @@ void MaterialStorage::material_get_instance_shader_parameters(RID p_material, Li void MaterialStorage::material_update_dependency(RID p_material, DependencyTracker *p_instance) { Material *material = material_owner.get_or_null(p_material); - ERR_FAIL_COND(!material); + ERR_FAIL_NULL(material); p_instance->update_dependency(&material->dependency); if (material->next_pass.is_valid()) { material_update_dependency(material->next_pass, p_instance); diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp index 439d0702f5..14605b308e 100644 --- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp @@ -228,7 +228,7 @@ void MeshStorage::mesh_free(RID p_rid) { mesh_clear(p_rid); mesh_set_shadow_mesh(p_rid, RID()); Mesh *mesh = mesh_owner.get_or_null(p_rid); - ERR_FAIL_COND(!mesh); + ERR_FAIL_NULL(mesh); mesh->dependency.deleted_notify(p_rid); if (mesh->instances.size()) { @@ -248,7 +248,7 @@ void MeshStorage::mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count ERR_FAIL_COND(p_blend_shape_count < 0); Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND(!mesh); + ERR_FAIL_NULL(mesh); ERR_FAIL_COND(mesh->surface_count > 0); //surfaces already exist @@ -258,7 +258,7 @@ void MeshStorage::mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count /// Returns stride void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) { Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND(!mesh); + ERR_FAIL_NULL(mesh); ERR_FAIL_COND(mesh->surface_count == RS::MAX_MESH_SURFACES); @@ -270,10 +270,10 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) uint32_t skin_stride = 0; for (int i = 0; i < RS::ARRAY_WEIGHTS; i++) { - if ((p_surface.format & (1 << i))) { + if ((p_surface.format & (1ULL << i))) { switch (i) { case RS::ARRAY_VERTEX: { - if (p_surface.format & RS::ARRAY_FLAG_USE_2D_VERTICES) { + if ((p_surface.format & RS::ARRAY_FLAG_USE_2D_VERTICES) || (p_surface.format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES)) { stride += sizeof(float) * 2; } else { stride += sizeof(float) * 3; @@ -281,22 +281,31 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) } break; case RS::ARRAY_NORMAL: { - stride += sizeof(int32_t); + stride += sizeof(uint16_t) * 2; } break; case RS::ARRAY_TANGENT: { - stride += sizeof(int32_t); - + if (!(p_surface.format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES)) { + stride += sizeof(uint16_t) * 2; + } } break; case RS::ARRAY_COLOR: { attrib_stride += sizeof(uint32_t); } break; case RS::ARRAY_TEX_UV: { - attrib_stride += sizeof(float) * 2; + if (p_surface.format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES) { + attrib_stride += sizeof(uint16_t) * 2; + } else { + attrib_stride += sizeof(float) * 2; + } } break; case RS::ARRAY_TEX_UV2: { - attrib_stride += sizeof(float) * 2; + if (p_surface.format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES) { + attrib_stride += sizeof(uint16_t) * 2; + } else { + attrib_stride += sizeof(float) * 2; + } } break; case RS::ARRAY_CUSTOM0: @@ -338,59 +347,96 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) #endif - Mesh::Surface *s = memnew(Mesh::Surface); + uint64_t surface_version = p_surface.format & (uint64_t(RS::ARRAY_FLAG_FORMAT_VERSION_MASK) << RS::ARRAY_FLAG_FORMAT_VERSION_SHIFT); + RS::SurfaceData new_surface = p_surface; +#ifdef DISABLE_DEPRECATED - s->format = p_surface.format; - s->primitive = p_surface.primitive; + ERR_FAIL_COND_MSG(surface_version != RS::ARRAY_FLAG_FORMAT_CURRENT_VERSION, "Surface version provided (" + itos(int(surface_version >> RS::ARRAY_FLAG_FORMAT_VERSION_SHIFT)) + ") does not match current version (" + itos(RS::ARRAY_FLAG_FORMAT_CURRENT_VERSION >> RS::ARRAY_FLAG_FORMAT_VERSION_SHIFT) + ")"); - bool use_as_storage = (p_surface.skin_data.size() || mesh->blend_shape_count > 0); +#else - if (p_surface.vertex_data.size()) { - s->vertex_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.vertex_data.size(), p_surface.vertex_data, use_as_storage); - s->vertex_buffer_size = p_surface.vertex_data.size(); + if (surface_version != uint64_t(RS::ARRAY_FLAG_FORMAT_CURRENT_VERSION)) { + RS::_fix_surface_compatibility(new_surface); + surface_version = new_surface.format & (RS::ARRAY_FLAG_FORMAT_VERSION_MASK << RS::ARRAY_FLAG_FORMAT_VERSION_SHIFT); + ERR_FAIL_COND_MSG(surface_version != RS::ARRAY_FLAG_FORMAT_CURRENT_VERSION, + "Surface version provided (" + + itos((surface_version >> RS::ARRAY_FLAG_FORMAT_VERSION_SHIFT) & RS::ARRAY_FLAG_FORMAT_VERSION_MASK) + + ") does not match current version (" + + itos((RS::ARRAY_FLAG_FORMAT_CURRENT_VERSION >> RS::ARRAY_FLAG_FORMAT_VERSION_SHIFT) & RS::ARRAY_FLAG_FORMAT_VERSION_MASK) + + ")"); } +#endif + + Mesh::Surface *s = memnew(Mesh::Surface); - if (p_surface.attribute_data.size()) { - s->attribute_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.attribute_data.size(), p_surface.attribute_data); + s->format = new_surface.format; + s->primitive = new_surface.primitive; + + bool use_as_storage = (new_surface.skin_data.size() || mesh->blend_shape_count > 0); + + if (new_surface.vertex_data.size()) { + // If we have an uncompressed surface that contains normals, but not tangents, we need to differentiate the array + // from a compressed array in the shader. To do so, we allow the the normal to read 4 components out of the buffer + // But only give it 2 components per normal. So essentially, each vertex reads the next normal in normal.zw. + // This allows us to avoid adding a shader permutation, and avoid passing dummy tangents. Since the stride is kept small + // this should still be a net win for bandwidth. + // If we do this, then the last normal will read past the end of the array. So we need to pad the array with dummy data. + if (!(new_surface.format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES) && (new_surface.format & RS::ARRAY_FORMAT_NORMAL) && !(new_surface.format & RS::ARRAY_FORMAT_TANGENT)) { + // Unfortunately, we need to copy the buffer, which is fine as doing a resize triggers a CoW anyway. + Vector<uint8_t> new_vertex_data; + new_vertex_data.resize_zeroed(new_surface.vertex_data.size() + sizeof(uint16_t) * 2); + memcpy(new_vertex_data.ptrw(), new_surface.vertex_data.ptr(), new_surface.vertex_data.size()); + s->vertex_buffer = RD::get_singleton()->vertex_buffer_create(new_vertex_data.size(), new_vertex_data, use_as_storage); + s->vertex_buffer_size = new_vertex_data.size(); + } else { + s->vertex_buffer = RD::get_singleton()->vertex_buffer_create(new_surface.vertex_data.size(), new_surface.vertex_data, use_as_storage); + s->vertex_buffer_size = new_surface.vertex_data.size(); + } } - if (p_surface.skin_data.size()) { - s->skin_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.skin_data.size(), p_surface.skin_data, use_as_storage); - s->skin_buffer_size = p_surface.skin_data.size(); + + if (new_surface.attribute_data.size()) { + s->attribute_buffer = RD::get_singleton()->vertex_buffer_create(new_surface.attribute_data.size(), new_surface.attribute_data); + } + if (new_surface.skin_data.size()) { + s->skin_buffer = RD::get_singleton()->vertex_buffer_create(new_surface.skin_data.size(), new_surface.skin_data, use_as_storage); + s->skin_buffer_size = new_surface.skin_data.size(); } - s->vertex_count = p_surface.vertex_count; + s->vertex_count = new_surface.vertex_count; - if (p_surface.format & RS::ARRAY_FORMAT_BONES) { + if (new_surface.format & RS::ARRAY_FORMAT_BONES) { mesh->has_bone_weights = true; } - if (p_surface.index_count) { - bool is_index_16 = p_surface.vertex_count <= 65536 && p_surface.vertex_count > 0; + if (new_surface.index_count) { + bool is_index_16 = new_surface.vertex_count <= 65536 && new_surface.vertex_count > 0; - s->index_buffer = RD::get_singleton()->index_buffer_create(p_surface.index_count, is_index_16 ? RD::INDEX_BUFFER_FORMAT_UINT16 : RD::INDEX_BUFFER_FORMAT_UINT32, p_surface.index_data, false); - s->index_count = p_surface.index_count; + s->index_buffer = RD::get_singleton()->index_buffer_create(new_surface.index_count, is_index_16 ? RD::INDEX_BUFFER_FORMAT_UINT16 : RD::INDEX_BUFFER_FORMAT_UINT32, new_surface.index_data, false); + s->index_count = new_surface.index_count; s->index_array = RD::get_singleton()->index_array_create(s->index_buffer, 0, s->index_count); - if (p_surface.lods.size()) { - s->lods = memnew_arr(Mesh::Surface::LOD, p_surface.lods.size()); - s->lod_count = p_surface.lods.size(); + if (new_surface.lods.size()) { + s->lods = memnew_arr(Mesh::Surface::LOD, new_surface.lods.size()); + s->lod_count = new_surface.lods.size(); - for (int i = 0; i < p_surface.lods.size(); i++) { - uint32_t indices = p_surface.lods[i].index_data.size() / (is_index_16 ? 2 : 4); - s->lods[i].index_buffer = RD::get_singleton()->index_buffer_create(indices, is_index_16 ? RD::INDEX_BUFFER_FORMAT_UINT16 : RD::INDEX_BUFFER_FORMAT_UINT32, p_surface.lods[i].index_data); + for (int i = 0; i < new_surface.lods.size(); i++) { + uint32_t indices = new_surface.lods[i].index_data.size() / (is_index_16 ? 2 : 4); + s->lods[i].index_buffer = RD::get_singleton()->index_buffer_create(indices, is_index_16 ? RD::INDEX_BUFFER_FORMAT_UINT16 : RD::INDEX_BUFFER_FORMAT_UINT32, new_surface.lods[i].index_data); s->lods[i].index_array = RD::get_singleton()->index_array_create(s->lods[i].index_buffer, 0, indices); - s->lods[i].edge_length = p_surface.lods[i].edge_length; + s->lods[i].edge_length = new_surface.lods[i].edge_length; s->lods[i].index_count = indices; } } } - ERR_FAIL_COND_MSG(!p_surface.index_count && !p_surface.vertex_count, "Meshes must contain a vertex array, an index array, or both"); + ERR_FAIL_COND_MSG(!new_surface.index_count && !new_surface.vertex_count, "Meshes must contain a vertex array, an index array, or both"); + + s->aabb = new_surface.aabb; + s->bone_aabbs = new_surface.bone_aabbs; //only really useful for returning them. - s->aabb = p_surface.aabb; - s->bone_aabbs = p_surface.bone_aabbs; //only really useful for returning them. + s->uv_scale = new_surface.uv_scale; if (mesh->blend_shape_count > 0) { - s->blend_shape_buffer = RD::get_singleton()->storage_buffer_create(p_surface.blend_shape_data.size(), p_surface.blend_shape_data); + s->blend_shape_buffer = RD::get_singleton()->storage_buffer_create(new_surface.blend_shape_data.size(), new_surface.blend_shape_data); } if (use_as_storage) { @@ -433,13 +479,13 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) } if (mesh->surface_count == 0) { - mesh->aabb = p_surface.aabb; + mesh->aabb = new_surface.aabb; } else { - mesh->aabb.merge_with(p_surface.aabb); + mesh->aabb.merge_with(new_surface.aabb); } mesh->skeleton_aabb_version = 0; - s->material = p_surface.material; + s->material = new_surface.material; mesh->surfaces = (Mesh::Surface **)memrealloc(mesh->surfaces, sizeof(Mesh::Surface *) * (mesh->surface_count + 1)); mesh->surfaces[mesh->surface_count] = s; @@ -462,13 +508,13 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) int MeshStorage::mesh_get_blend_shape_count(RID p_mesh) const { const Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND_V(!mesh, -1); + ERR_FAIL_NULL_V(mesh, -1); return mesh->blend_shape_count; } void MeshStorage::mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) { Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND(!mesh); + ERR_FAIL_NULL(mesh); ERR_FAIL_INDEX((int)p_mode, 2); mesh->blend_shape_mode = p_mode; @@ -476,13 +522,13 @@ void MeshStorage::mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mod RS::BlendShapeMode MeshStorage::mesh_get_blend_shape_mode(RID p_mesh) const { Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND_V(!mesh, RS::BLEND_SHAPE_MODE_NORMALIZED); + ERR_FAIL_NULL_V(mesh, RS::BLEND_SHAPE_MODE_NORMALIZED); return mesh->blend_shape_mode; } void MeshStorage::mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) { Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND(!mesh); + ERR_FAIL_NULL(mesh); ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count); ERR_FAIL_COND(p_data.size() == 0); ERR_FAIL_COND(mesh->surfaces[p_surface]->vertex_buffer.is_null()); @@ -494,7 +540,7 @@ void MeshStorage::mesh_surface_update_vertex_region(RID p_mesh, int p_surface, i void MeshStorage::mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) { Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND(!mesh); + ERR_FAIL_NULL(mesh); ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count); ERR_FAIL_COND(p_data.size() == 0); ERR_FAIL_COND(mesh->surfaces[p_surface]->attribute_buffer.is_null()); @@ -506,7 +552,7 @@ void MeshStorage::mesh_surface_update_attribute_region(RID p_mesh, int p_surface void MeshStorage::mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) { Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND(!mesh); + ERR_FAIL_NULL(mesh); ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count); ERR_FAIL_COND(p_data.size() == 0); ERR_FAIL_COND(mesh->surfaces[p_surface]->skin_buffer.is_null()); @@ -518,7 +564,7 @@ void MeshStorage::mesh_surface_update_skin_region(RID p_mesh, int p_surface, int void MeshStorage::mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) { Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND(!mesh); + ERR_FAIL_NULL(mesh); ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count); mesh->surfaces[p_surface]->material = p_material; @@ -528,7 +574,7 @@ void MeshStorage::mesh_surface_set_material(RID p_mesh, int p_surface, RID p_mat RID MeshStorage::mesh_surface_get_material(RID p_mesh, int p_surface) const { Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND_V(!mesh, RID()); + ERR_FAIL_NULL_V(mesh, RID()); ERR_FAIL_UNSIGNED_INDEX_V((uint32_t)p_surface, mesh->surface_count, RID()); return mesh->surfaces[p_surface]->material; @@ -536,7 +582,7 @@ RID MeshStorage::mesh_surface_get_material(RID p_mesh, int p_surface) const { RS::SurfaceData MeshStorage::mesh_get_surface(RID p_mesh, int p_surface) const { Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND_V(!mesh, RS::SurfaceData()); + ERR_FAIL_NULL_V(mesh, RS::SurfaceData()); ERR_FAIL_UNSIGNED_INDEX_V((uint32_t)p_surface, mesh->surface_count, RS::SurfaceData()); Mesh::Surface &s = *mesh->surfaces[p_surface]; @@ -545,6 +591,11 @@ RS::SurfaceData MeshStorage::mesh_get_surface(RID p_mesh, int p_surface) const { sd.format = s.format; if (s.vertex_buffer.is_valid()) { sd.vertex_data = RD::get_singleton()->buffer_get_data(s.vertex_buffer); + // When using an uncompressed buffer with normals, but without tangents, we have to trim the padding. + if (!(s.format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES) && (s.format & RS::ARRAY_FORMAT_NORMAL) && !(s.format & RS::ARRAY_FORMAT_TANGENT)) { + Vector<uint8_t> new_vertex_data; + sd.vertex_data.resize(sd.vertex_data.size() - sizeof(uint16_t) * 2); + } } if (s.attribute_buffer.is_valid()) { sd.attribute_data = RD::get_singleton()->buffer_get_data(s.attribute_buffer); @@ -560,6 +611,7 @@ RS::SurfaceData MeshStorage::mesh_get_surface(RID p_mesh, int p_surface) const { sd.index_data = RD::get_singleton()->buffer_get_data(s.index_buffer); } sd.aabb = s.aabb; + sd.uv_scale = s.uv_scale; for (uint32_t i = 0; i < s.lod_count; i++) { RS::SurfaceData::LOD lod; lod.edge_length = s.lods[i].edge_length; @@ -578,13 +630,13 @@ RS::SurfaceData MeshStorage::mesh_get_surface(RID p_mesh, int p_surface) const { int MeshStorage::mesh_get_surface_count(RID p_mesh) const { Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND_V(!mesh, 0); + ERR_FAIL_NULL_V(mesh, 0); return mesh->surface_count; } void MeshStorage::mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) { Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND(!mesh); + ERR_FAIL_NULL(mesh); mesh->custom_aabb = p_aabb; mesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB); @@ -592,13 +644,13 @@ void MeshStorage::mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) { AABB MeshStorage::mesh_get_custom_aabb(RID p_mesh) const { Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND_V(!mesh, AABB()); + ERR_FAIL_NULL_V(mesh, AABB()); return mesh->custom_aabb; } AABB MeshStorage::mesh_get_aabb(RID p_mesh, RID p_skeleton) { Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND_V(!mesh, AABB()); + ERR_FAIL_NULL_V(mesh, AABB()); if (mesh->custom_aabb != AABB()) { return mesh->custom_aabb; @@ -706,7 +758,7 @@ AABB MeshStorage::mesh_get_aabb(RID p_mesh, RID p_skeleton) { void MeshStorage::mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) { Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND(!mesh); + ERR_FAIL_NULL(mesh); Mesh *shadow_mesh = mesh_owner.get_or_null(mesh->shadow_mesh); if (shadow_mesh) { @@ -725,7 +777,7 @@ void MeshStorage::mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) { void MeshStorage::mesh_clear(RID p_mesh) { Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND(!mesh); + ERR_FAIL_NULL(mesh); // Clear instance data before mesh data. for (MeshInstance *mi : mesh->instances) { @@ -783,14 +835,14 @@ void MeshStorage::mesh_clear(RID p_mesh) { bool MeshStorage::mesh_needs_instance(RID p_mesh, bool p_has_skeleton) { Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND_V(!mesh, false); + ERR_FAIL_NULL_V(mesh, false); return mesh->blend_shape_count > 0 || (mesh->has_bone_weights && p_has_skeleton); } Dependency *MeshStorage::mesh_get_dependency(RID p_mesh) const { Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND_V(!mesh, nullptr); + ERR_FAIL_NULL_V(mesh, nullptr); return &mesh->dependency; } @@ -799,7 +851,7 @@ Dependency *MeshStorage::mesh_get_dependency(RID p_mesh) const { RID MeshStorage::mesh_instance_create(RID p_base) { Mesh *mesh = mesh_owner.get_or_null(p_base); - ERR_FAIL_COND_V(!mesh, RID()); + ERR_FAIL_NULL_V(mesh, RID()); RID rid = mesh_instance_owner.make_rid(); MeshInstance *mi = mesh_instance_owner.get_or_null(rid); @@ -838,7 +890,7 @@ void MeshStorage::mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton void MeshStorage::mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) { MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance); - ERR_FAIL_COND(!mi); + ERR_FAIL_NULL(mi); ERR_FAIL_INDEX(p_shape, (int)mi->blend_weights.size()); mi->blend_weights[p_shape] = p_weight; mi->weights_dirty = true; @@ -1016,8 +1068,10 @@ void MeshStorage::update_mesh_instances() { push_constant.has_skeleton = sk != nullptr && sk->use_2d == array_is_2d && (mi->mesh->surfaces[i]->format & RS::ARRAY_FORMAT_BONES); push_constant.has_blend_shape = mi->mesh->blend_shape_count > 0; + push_constant.normal_tangent_stride = (push_constant.has_normal ? 1 : 0) + (push_constant.has_tangent ? 1 : 0); + push_constant.vertex_count = mi->mesh->surfaces[i]->vertex_count; - push_constant.vertex_stride = (mi->mesh->surfaces[i]->vertex_buffer_size / mi->mesh->surfaces[i]->vertex_count) / 4; + push_constant.vertex_stride = ((mi->mesh->surfaces[i]->vertex_buffer_size / mi->mesh->surfaces[i]->vertex_count) / 4) - push_constant.normal_tangent_stride; push_constant.skin_stride = (mi->mesh->surfaces[i]->skin_buffer_size / mi->mesh->surfaces[i]->vertex_count) / 4; push_constant.skin_weight_offset = (mi->mesh->surfaces[i]->format & RS::ARRAY_FLAG_USE_8_BONE_WEIGHTS) ? 4 : 2; @@ -1042,7 +1096,6 @@ void MeshStorage::update_mesh_instances() { push_constant.blend_shape_count = mi->mesh->blend_shape_count; push_constant.normalized_blend_shapes = mi->mesh->blend_shape_mode == RS::BLEND_SHAPE_MODE_NORMALIZED; - push_constant.pad0 = 0; push_constant.pad1 = 0; RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SkeletonShader::PushConstant)); @@ -1061,11 +1114,13 @@ void MeshStorage::update_mesh_instances() { RD::get_singleton()->compute_list_end(); } -void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::Version &v, Mesh::Surface *s, uint32_t p_input_mask, bool p_input_motion_vectors, MeshInstance::Surface *mis) { +void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::Version &v, Mesh::Surface *s, uint64_t p_input_mask, bool p_input_motion_vectors, MeshInstance::Surface *mis, uint32_t p_current_buffer, uint32_t p_previous_buffer) { Vector<RD::VertexAttribute> attributes; Vector<RID> buffers; + Vector<uint64_t> offsets; - uint32_t stride = 0; + uint32_t position_stride = 0; + uint32_t normal_tangent_stride = 0; uint32_t attribute_stride = 0; uint32_t skin_stride = 0; @@ -1073,8 +1128,9 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V RD::VertexAttribute vd; RID buffer; vd.location = i; + uint64_t offset = 0; - if (!(s->format & (1 << i))) { + if (!(s->format & (1ULL << i))) { // Not supplied by surface, use default value buffer = mesh_default_rd_buffers[i]; vd.stride = 0; @@ -1123,45 +1179,56 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V switch (i) { case RS::ARRAY_VERTEX: { - vd.offset = stride; + vd.offset = position_stride; if (s->format & RS::ARRAY_FLAG_USE_2D_VERTICES) { vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; - stride += sizeof(float) * 2; + position_stride = sizeof(float) * 2; } else { - vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT; - stride += sizeof(float) * 3; + if (!mis && (s->format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES)) { + vd.format = RD::DATA_FORMAT_R16G16B16A16_UNORM; + position_stride = sizeof(uint16_t) * 4; + } else { + vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT; + position_stride = sizeof(float) * 3; + } } if (mis) { - buffer = mis->vertex_buffer[mis->current_buffer]; + buffer = mis->vertex_buffer[p_current_buffer]; } else { buffer = s->vertex_buffer; } } break; case RS::ARRAY_NORMAL: { - vd.offset = stride; - vd.format = RD::DATA_FORMAT_R16G16_UNORM; - stride += sizeof(uint16_t) * 2; - - if (mis) { - buffer = mis->vertex_buffer[mis->current_buffer]; + vd.offset = 0; + offset = position_stride * s->vertex_count; + if (!mis && (s->format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES)) { + vd.format = RD::DATA_FORMAT_R16G16_UNORM; + normal_tangent_stride += sizeof(uint16_t) * 2; } else { - buffer = s->vertex_buffer; + vd.format = RD::DATA_FORMAT_R16G16B16A16_UNORM; + // A small trick here: if we are uncompressed and we have normals, but no tangents. We need + // the shader to think there are 4 components to "axis_tangent_attrib". So we give a size of 4, + // but a stride based on only having 2 elements. + if (!(s->format & RS::ARRAY_FORMAT_TANGENT)) { + normal_tangent_stride += sizeof(uint16_t) * 2; + } else { + normal_tangent_stride += sizeof(uint16_t) * 4; + } } - } break; - case RS::ARRAY_TANGENT: { - vd.offset = stride; - vd.format = RD::DATA_FORMAT_R16G16_UNORM; - stride += sizeof(uint16_t) * 2; - if (mis) { - buffer = mis->vertex_buffer[mis->current_buffer]; + buffer = mis->vertex_buffer[p_current_buffer]; } else { buffer = s->vertex_buffer; } } break; + case RS::ARRAY_TANGENT: { + buffer = mesh_default_rd_buffers[i]; + vd.stride = 0; + vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; + } break; case RS::ARRAY_COLOR: { vd.offset = attribute_stride; @@ -1171,17 +1238,25 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V } break; case RS::ARRAY_TEX_UV: { vd.offset = attribute_stride; - - vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; - attribute_stride += sizeof(float) * 2; + if (s->format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES) { + vd.format = RD::DATA_FORMAT_R16G16_UNORM; + attribute_stride += sizeof(uint16_t) * 2; + } else { + vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; + attribute_stride += sizeof(float) * 2; + } buffer = s->attribute_buffer; } break; case RS::ARRAY_TEX_UV2: { vd.offset = attribute_stride; - - vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; - attribute_stride += sizeof(float) * 2; + if (s->format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES) { + vd.format = RD::DATA_FORMAT_R16G16_UNORM; + attribute_stride += sizeof(uint16_t) * 2; + } else { + vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; + attribute_stride += sizeof(float) * 2; + } buffer = s->attribute_buffer; } break; case RS::ARRAY_CUSTOM0: @@ -1216,12 +1291,13 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V } } - if (!(p_input_mask & (1 << i))) { + if (!(p_input_mask & (1ULL << i))) { continue; // Shader does not need this, skip it (but computing stride was important anyway) } attributes.push_back(vd); buffers.push_back(buffer); + offsets.push_back(offset); if (p_input_motion_vectors) { // Since the previous vertex, normal and tangent can't be part of the vertex format but they are required when motion @@ -1241,11 +1317,12 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V if (int(vd.location) != i) { if (mis && buffer != mesh_default_rd_buffers[i]) { - buffer = mis->vertex_buffer[mis->previous_buffer]; + buffer = mis->vertex_buffer[p_previous_buffer]; } attributes.push_back(vd); buffers.push_back(buffer); + offsets.push_back(offset); } } } @@ -1256,9 +1333,10 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V continue; //default location } int loc = attributes[i].location; - - if ((loc < RS::ARRAY_COLOR) || ((loc >= ATTRIBUTE_LOCATION_PREV_VERTEX) && (loc <= ATTRIBUTE_LOCATION_PREV_TANGENT))) { - attributes.write[i].stride = stride; + if (loc == RS::ARRAY_VERTEX || loc == ATTRIBUTE_LOCATION_PREV_VERTEX) { + attributes.write[i].stride = position_stride; + } else if ((loc < RS::ARRAY_COLOR) || ((loc >= ATTRIBUTE_LOCATION_PREV_NORMAL) && (loc <= ATTRIBUTE_LOCATION_PREV_TANGENT))) { + attributes.write[i].stride = normal_tangent_stride; } else if (loc < RS::ARRAY_BONES) { attributes.write[i].stride = attribute_stride; } else { @@ -1267,11 +1345,11 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V } v.input_mask = p_input_mask; - v.current_buffer = mis ? mis->current_buffer : 0; - v.previous_buffer = mis ? mis->previous_buffer : 0; + v.current_buffer = p_current_buffer; + v.previous_buffer = p_previous_buffer; v.input_motion_vectors = p_input_motion_vectors; v.vertex_format = RD::get_singleton()->vertex_format_create(attributes); - v.vertex_array = RD::get_singleton()->vertex_array_create(s->vertex_count, v.vertex_format, buffers); + v.vertex_array = RD::get_singleton()->vertex_array_create(s->vertex_count, v.vertex_format, buffers, offsets); } ////////////////// MULTIMESH @@ -1293,7 +1371,7 @@ void MeshStorage::multimesh_free(RID p_rid) { void MeshStorage::multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors, bool p_use_custom_data) { MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND(!multimesh); + ERR_FAIL_NULL(multimesh); if (multimesh->instances == p_instances && multimesh->xform_format == p_transform_format && multimesh->uses_colors == p_use_colors && multimesh->uses_custom_data == p_use_custom_data) { return; @@ -1390,23 +1468,29 @@ void MeshStorage::_multimesh_enable_motion_vectors(MultiMesh *multimesh) { void MeshStorage::_multimesh_get_motion_vectors_offsets(RID p_multimesh, uint32_t &r_current_offset, uint32_t &r_prev_offset) { MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND(!multimesh); + ERR_FAIL_NULL(multimesh); r_current_offset = multimesh->motion_vectors_current_offset; - if (RSG::rasterizer->get_frame_number() - multimesh->motion_vectors_last_change >= 2) { + if (!_multimesh_uses_motion_vectors(multimesh)) { multimesh->motion_vectors_previous_offset = multimesh->motion_vectors_current_offset; } r_prev_offset = multimesh->motion_vectors_previous_offset; } +bool MeshStorage::_multimesh_uses_motion_vectors_offsets(RID p_multimesh) { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + ERR_FAIL_NULL_V(multimesh, false); + return _multimesh_uses_motion_vectors(multimesh); +} + int MeshStorage::multimesh_get_instance_count(RID p_multimesh) const { MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND_V(!multimesh, 0); + ERR_FAIL_NULL_V(multimesh, 0); return multimesh->instances; } void MeshStorage::multimesh_set_mesh(RID p_multimesh, RID p_mesh) { MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND(!multimesh); + ERR_FAIL_NULL(multimesh); if (multimesh->mesh == p_mesh) { return; } @@ -1500,6 +1584,10 @@ void MeshStorage::_multimesh_update_motion_vectors_data_cache(MultiMesh *multime } } +bool MeshStorage::_multimesh_uses_motion_vectors(MultiMesh *multimesh) { + return (RSG::rasterizer->get_frame_number() - multimesh->motion_vectors_last_change) < 2; +} + void MeshStorage::_multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool p_aabb) { uint32_t region_index = p_index / MULTIMESH_DIRTY_REGION_SIZE; #ifdef DEBUG_ENABLED @@ -1589,7 +1677,7 @@ void MeshStorage::_multimesh_re_create_aabb(MultiMesh *multimesh, const float *p void MeshStorage::multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) { MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND(!multimesh); + ERR_FAIL_NULL(multimesh); ERR_FAIL_INDEX(p_index, multimesh->instances); ERR_FAIL_COND(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_3D); @@ -1626,7 +1714,7 @@ void MeshStorage::multimesh_instance_set_transform(RID p_multimesh, int p_index, void MeshStorage::multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) { MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND(!multimesh); + ERR_FAIL_NULL(multimesh); ERR_FAIL_INDEX(p_index, multimesh->instances); ERR_FAIL_COND(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_2D); @@ -1653,7 +1741,7 @@ void MeshStorage::multimesh_instance_set_transform_2d(RID p_multimesh, int p_ind void MeshStorage::multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) { MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND(!multimesh); + ERR_FAIL_NULL(multimesh); ERR_FAIL_INDEX(p_index, multimesh->instances); ERR_FAIL_COND(!multimesh->uses_colors); @@ -1676,7 +1764,7 @@ void MeshStorage::multimesh_instance_set_color(RID p_multimesh, int p_index, con void MeshStorage::multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) { MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND(!multimesh); + ERR_FAIL_NULL(multimesh); ERR_FAIL_INDEX(p_index, multimesh->instances); ERR_FAIL_COND(!multimesh->uses_custom_data); @@ -1699,21 +1787,21 @@ void MeshStorage::multimesh_instance_set_custom_data(RID p_multimesh, int p_inde RID MeshStorage::multimesh_get_mesh(RID p_multimesh) const { MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND_V(!multimesh, RID()); + ERR_FAIL_NULL_V(multimesh, RID()); return multimesh->mesh; } Dependency *MeshStorage::multimesh_get_dependency(RID p_multimesh) const { MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND_V(!multimesh, nullptr); + ERR_FAIL_NULL_V(multimesh, nullptr); return &multimesh->dependency; } Transform3D MeshStorage::multimesh_instance_get_transform(RID p_multimesh, int p_index) const { MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND_V(!multimesh, Transform3D()); + ERR_FAIL_NULL_V(multimesh, Transform3D()); ERR_FAIL_INDEX_V(p_index, multimesh->instances, Transform3D()); ERR_FAIL_COND_V(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_3D, Transform3D()); @@ -1744,7 +1832,7 @@ Transform3D MeshStorage::multimesh_instance_get_transform(RID p_multimesh, int p Transform2D MeshStorage::multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const { MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND_V(!multimesh, Transform2D()); + ERR_FAIL_NULL_V(multimesh, Transform2D()); ERR_FAIL_INDEX_V(p_index, multimesh->instances, Transform2D()); ERR_FAIL_COND_V(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_2D, Transform2D()); @@ -1769,7 +1857,7 @@ Transform2D MeshStorage::multimesh_instance_get_transform_2d(RID p_multimesh, in Color MeshStorage::multimesh_instance_get_color(RID p_multimesh, int p_index) const { MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND_V(!multimesh, Color()); + ERR_FAIL_NULL_V(multimesh, Color()); ERR_FAIL_INDEX_V(p_index, multimesh->instances, Color()); ERR_FAIL_COND_V(!multimesh->uses_colors, Color()); @@ -1792,7 +1880,7 @@ Color MeshStorage::multimesh_instance_get_color(RID p_multimesh, int p_index) co Color MeshStorage::multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const { MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND_V(!multimesh, Color()); + ERR_FAIL_NULL_V(multimesh, Color()); ERR_FAIL_INDEX_V(p_index, multimesh->instances, Color()); ERR_FAIL_COND_V(!multimesh->uses_custom_data, Color()); @@ -1815,7 +1903,7 @@ Color MeshStorage::multimesh_instance_get_custom_data(RID p_multimesh, int p_ind void MeshStorage::multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) { MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND(!multimesh); + ERR_FAIL_NULL(multimesh); ERR_FAIL_COND(p_buffer.size() != (multimesh->instances * (int)multimesh->stride_cache)); bool uses_motion_vectors = (RSG::viewport->get_num_viewports_with_motion_vectors() > 0); @@ -1854,7 +1942,7 @@ void MeshStorage::multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_b Vector<float> MeshStorage::multimesh_get_buffer(RID p_multimesh) const { MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND_V(!multimesh, Vector<float>()); + ERR_FAIL_NULL_V(multimesh, Vector<float>()); if (multimesh->buffer.is_null()) { return Vector<float>(); } else { @@ -1876,7 +1964,7 @@ Vector<float> MeshStorage::multimesh_get_buffer(RID p_multimesh) const { void MeshStorage::multimesh_set_visible_instances(RID p_multimesh, int p_visible) { MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND(!multimesh); + ERR_FAIL_NULL(multimesh); ERR_FAIL_COND(p_visible < -1 || p_visible > multimesh->instances); if (multimesh->visible_instances == p_visible) { return; @@ -1898,13 +1986,13 @@ void MeshStorage::multimesh_set_visible_instances(RID p_multimesh, int p_visible int MeshStorage::multimesh_get_visible_instances(RID p_multimesh) const { MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND_V(!multimesh, 0); + ERR_FAIL_NULL_V(multimesh, 0); return multimesh->visible_instances; } AABB MeshStorage::multimesh_get_aabb(RID p_multimesh) const { MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); - ERR_FAIL_COND_V(!multimesh, AABB()); + ERR_FAIL_NULL_V(multimesh, AABB()); if (multimesh->aabb_dirty) { const_cast<MeshStorage *>(this)->_update_dirty_multimeshes(); } @@ -1994,7 +2082,7 @@ void MeshStorage::_skeleton_make_dirty(Skeleton *skeleton) { void MeshStorage::skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton) { Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); - ERR_FAIL_COND(!skeleton); + ERR_FAIL_NULL(skeleton); ERR_FAIL_COND(p_bones < 0); if (skeleton->size == p_bones && skeleton->use_2d == p_2d_skeleton) { @@ -2037,7 +2125,7 @@ void MeshStorage::skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_ int MeshStorage::skeleton_get_bone_count(RID p_skeleton) const { Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); - ERR_FAIL_COND_V(!skeleton, 0); + ERR_FAIL_NULL_V(skeleton, 0); return skeleton->size; } @@ -2045,7 +2133,7 @@ int MeshStorage::skeleton_get_bone_count(RID p_skeleton) const { void MeshStorage::skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform) { Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); - ERR_FAIL_COND(!skeleton); + ERR_FAIL_NULL(skeleton); ERR_FAIL_INDEX(p_bone, skeleton->size); ERR_FAIL_COND(skeleton->use_2d); @@ -2070,7 +2158,7 @@ void MeshStorage::skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D MeshStorage::skeleton_bone_get_transform(RID p_skeleton, int p_bone) const { Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); - ERR_FAIL_COND_V(!skeleton, Transform3D()); + ERR_FAIL_NULL_V(skeleton, Transform3D()); ERR_FAIL_INDEX_V(p_bone, skeleton->size, Transform3D()); ERR_FAIL_COND_V(skeleton->use_2d, Transform3D()); @@ -2097,7 +2185,7 @@ Transform3D MeshStorage::skeleton_bone_get_transform(RID p_skeleton, int p_bone) void MeshStorage::skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) { Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); - ERR_FAIL_COND(!skeleton); + ERR_FAIL_NULL(skeleton); ERR_FAIL_INDEX(p_bone, skeleton->size); ERR_FAIL_COND(!skeleton->use_2d); @@ -2118,7 +2206,7 @@ void MeshStorage::skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, con Transform2D MeshStorage::skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const { Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); - ERR_FAIL_COND_V(!skeleton, Transform2D()); + ERR_FAIL_NULL_V(skeleton, Transform2D()); ERR_FAIL_INDEX_V(p_bone, skeleton->size, Transform2D()); ERR_FAIL_COND_V(!skeleton->use_2d, Transform2D()); @@ -2167,7 +2255,7 @@ void MeshStorage::_update_dirty_skeletons() { void MeshStorage::skeleton_update_dependency(RID p_skeleton, DependencyTracker *p_instance) { Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); - ERR_FAIL_COND(!skeleton); + ERR_FAIL_NULL(skeleton); p_instance->update_dependency(&skeleton->dependency); } diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h index 99ba69f98a..f03334baac 100644 --- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h @@ -73,7 +73,7 @@ private: struct Mesh { struct Surface { RS::PrimitiveType primitive = RS::PRIMITIVE_POINTS; - uint32_t format = 0; + uint64_t format = 0; RID vertex_buffer; RID attribute_buffer; @@ -90,7 +90,7 @@ private: // cache-efficient structure. struct Version { - uint32_t input_mask = 0; + uint64_t input_mask = 0; uint32_t current_buffer = 0; uint32_t previous_buffer = 0; bool input_motion_vectors = false; @@ -120,6 +120,8 @@ private: Vector<AABB> bone_aabbs; + Vector4 uv_scale; + RID blend_shape_buffer; RID material; @@ -190,7 +192,7 @@ private: weight_update_list(this), array_update_list(this) {} }; - void _mesh_surface_generate_version_for_input_mask(Mesh::Surface::Version &v, Mesh::Surface *s, uint32_t p_input_mask, bool p_input_motion_vectors, MeshInstance::Surface *mis = nullptr); + void _mesh_surface_generate_version_for_input_mask(Mesh::Surface::Version &v, Mesh::Surface *s, uint64_t p_input_mask, bool p_input_motion_vectors, MeshInstance::Surface *mis = nullptr, uint32_t p_current_buffer = 0, uint32_t p_previous_buffer = 0); void _mesh_instance_clear(MeshInstance *mi); void _mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint32_t p_surface); @@ -244,6 +246,7 @@ private: _FORCE_INLINE_ void _multimesh_make_local(MultiMesh *multimesh) const; _FORCE_INLINE_ void _multimesh_enable_motion_vectors(MultiMesh *multimesh); _FORCE_INLINE_ void _multimesh_update_motion_vectors_data_cache(MultiMesh *multimesh); + _FORCE_INLINE_ bool _multimesh_uses_motion_vectors(MultiMesh *multimesh); _FORCE_INLINE_ void _multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool p_aabb); _FORCE_INLINE_ void _multimesh_mark_all_dirty(MultiMesh *multimesh, bool p_data, bool p_aabb); _FORCE_INLINE_ void _multimesh_re_create_aabb(MultiMesh *multimesh, const float *p_data, int p_instances); @@ -264,7 +267,7 @@ private: uint32_t blend_shape_count; uint32_t normalized_blend_shapes; - uint32_t pad0; + uint32_t normal_tangent_stride; uint32_t pad1; float skeleton_transform_x[2]; float skeleton_transform_y[2]; @@ -376,7 +379,7 @@ public: _FORCE_INLINE_ const RID *mesh_get_surface_count_and_materials(RID p_mesh, uint32_t &r_surface_count) { Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND_V(!mesh, nullptr); + ERR_FAIL_NULL_V(mesh, nullptr); r_surface_count = mesh->surface_count; if (r_surface_count == 0) { return nullptr; @@ -393,7 +396,7 @@ public: _FORCE_INLINE_ void *mesh_get_surface(RID p_mesh, uint32_t p_surface_index) { Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND_V(!mesh, nullptr); + ERR_FAIL_NULL_V(mesh, nullptr); ERR_FAIL_UNSIGNED_INDEX_V(p_surface_index, mesh->surface_count, nullptr); return mesh->surfaces[p_surface_index]; @@ -401,7 +404,7 @@ public: _FORCE_INLINE_ RID mesh_get_shadow_mesh(RID p_mesh) { Mesh *mesh = mesh_owner.get_or_null(p_mesh); - ERR_FAIL_COND_V(!mesh, RID()); + ERR_FAIL_NULL_V(mesh, RID()); return mesh->shadow_mesh; } @@ -421,6 +424,21 @@ public: return s->index_count ? s->index_count : s->vertex_count; } + _FORCE_INLINE_ AABB mesh_surface_get_aabb(void *p_surface) { + Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface); + return s->aabb; + } + + _FORCE_INLINE_ uint64_t mesh_surface_get_format(void *p_surface) { + Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface); + return s->format; + } + + _FORCE_INLINE_ Vector4 mesh_surface_get_uv_scale(void *p_surface) { + Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface); + return s->uv_scale; + } + _FORCE_INLINE_ uint32_t mesh_surface_get_lod(void *p_surface, float p_model_scale, float p_distance_threshold, float p_mesh_lod_threshold, uint32_t &r_index_count) const { Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface); @@ -483,9 +501,9 @@ public: s->version_lock.unlock(); } - _FORCE_INLINE_ void mesh_instance_surface_get_vertex_arrays_and_format(RID p_mesh_instance, uint32_t p_surface_index, uint32_t p_input_mask, bool p_input_motion_vectors, RID &r_vertex_array_rd, RD::VertexFormatID &r_vertex_format) { + _FORCE_INLINE_ void mesh_instance_surface_get_vertex_arrays_and_format(RID p_mesh_instance, uint64_t p_surface_index, uint32_t p_input_mask, bool p_input_motion_vectors, RID &r_vertex_array_rd, RD::VertexFormatID &r_vertex_format) { MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance); - ERR_FAIL_COND(!mi); + ERR_FAIL_NULL(mi); Mesh *mesh = mi->mesh; ERR_FAIL_UNSIGNED_INDEX(p_surface_index, mesh->surface_count); @@ -522,7 +540,7 @@ public: mis->version_count++; mis->versions = (Mesh::Surface::Version *)memrealloc(mis->versions, sizeof(Mesh::Surface::Version) * mis->version_count); - _mesh_surface_generate_version_for_input_mask(mis->versions[version], s, p_input_mask, p_input_motion_vectors, mis); + _mesh_surface_generate_version_for_input_mask(mis->versions[version], s, p_input_mask, p_input_motion_vectors, mis, current_buffer, previous_buffer); r_vertex_format = mis->versions[version].vertex_format; r_vertex_array_rd = mis->versions[version].vertex_array; @@ -622,6 +640,8 @@ public: void _update_dirty_multimeshes(); void _multimesh_get_motion_vectors_offsets(RID p_multimesh, uint32_t &r_current_offset, uint32_t &r_prev_offset); + bool _multimesh_uses_motion_vectors_offsets(RID p_multimesh); + bool _multimesh_uses_motion_vectors(RID p_multimesh); _FORCE_INLINE_ RS::MultimeshTransformFormat multimesh_get_transform_format(RID p_multimesh) const { MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); @@ -716,7 +736,7 @@ public: _FORCE_INLINE_ RID skeleton_get_3d_uniform_set(RID p_skeleton, RID p_shader, uint32_t p_set) const { Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); - ERR_FAIL_COND_V(!skeleton, RID()); + ERR_FAIL_NULL_V(skeleton, RID()); if (skeleton->size == 0) { return RID(); } diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp index 9f1b2d8c38..bf5a597bb9 100644 --- a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp @@ -234,7 +234,7 @@ void ParticlesStorage::particles_free(RID p_rid) { void ParticlesStorage::particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) { Particles *particles = particles_owner.get_or_null(p_particles); - ERR_FAIL_COND(!particles); + ERR_FAIL_NULL(particles); if (particles->mode == p_mode) { return; } @@ -246,7 +246,7 @@ void ParticlesStorage::particles_set_mode(RID p_particles, RS::ParticlesMode p_m void ParticlesStorage::particles_set_emitting(RID p_particles, bool p_emitting) { Particles *particles = particles_owner.get_or_null(p_particles); - ERR_FAIL_COND(!particles); + ERR_FAIL_NULL(particles); particles->emitting = p_emitting; } @@ -254,7 +254,7 @@ void ParticlesStorage::particles_set_emitting(RID p_particles, bool p_emitting) bool ParticlesStorage::particles_get_emitting(RID p_particles) { ERR_FAIL_COND_V_MSG(RSG::threaded, false, "This function should never be used with threaded rendering, as it stalls the renderer."); Particles *particles = particles_owner.get_or_null(p_particles); - ERR_FAIL_COND_V(!particles, false); + ERR_FAIL_NULL_V(particles, false); return particles->emitting; } @@ -311,7 +311,7 @@ void ParticlesStorage::_particles_free_data(Particles *particles) { void ParticlesStorage::particles_set_amount(RID p_particles, int p_amount) { Particles *particles = particles_owner.get_or_null(p_particles); - ERR_FAIL_COND(!particles); + ERR_FAIL_NULL(particles); if (particles->amount == p_amount) { return; @@ -331,48 +331,48 @@ void ParticlesStorage::particles_set_amount(RID p_particles, int p_amount) { void ParticlesStorage::particles_set_lifetime(RID p_particles, double p_lifetime) { Particles *particles = particles_owner.get_or_null(p_particles); - ERR_FAIL_COND(!particles); + ERR_FAIL_NULL(particles); particles->lifetime = p_lifetime; } void ParticlesStorage::particles_set_one_shot(RID p_particles, bool p_one_shot) { Particles *particles = particles_owner.get_or_null(p_particles); - ERR_FAIL_COND(!particles); + ERR_FAIL_NULL(particles); particles->one_shot = p_one_shot; } void ParticlesStorage::particles_set_pre_process_time(RID p_particles, double p_time) { Particles *particles = particles_owner.get_or_null(p_particles); - ERR_FAIL_COND(!particles); + ERR_FAIL_NULL(particles); particles->pre_process_time = p_time; } void ParticlesStorage::particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) { Particles *particles = particles_owner.get_or_null(p_particles); - ERR_FAIL_COND(!particles); + ERR_FAIL_NULL(particles); particles->explosiveness = p_ratio; } void ParticlesStorage::particles_set_randomness_ratio(RID p_particles, real_t p_ratio) { Particles *particles = particles_owner.get_or_null(p_particles); - ERR_FAIL_COND(!particles); + ERR_FAIL_NULL(particles); particles->randomness = p_ratio; } void ParticlesStorage::particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) { Particles *particles = particles_owner.get_or_null(p_particles); - ERR_FAIL_COND(!particles); + ERR_FAIL_NULL(particles); particles->custom_aabb = p_aabb; particles->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB); } void ParticlesStorage::particles_set_speed_scale(RID p_particles, double p_scale) { Particles *particles = particles_owner.get_or_null(p_particles); - ERR_FAIL_COND(!particles); + ERR_FAIL_NULL(particles); particles->speed_scale = p_scale; } void ParticlesStorage::particles_set_use_local_coordinates(RID p_particles, bool p_enable) { Particles *particles = particles_owner.get_or_null(p_particles); - ERR_FAIL_COND(!particles); + ERR_FAIL_NULL(particles); particles->use_local_coords = p_enable; particles->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_PARTICLES); @@ -380,7 +380,7 @@ void ParticlesStorage::particles_set_use_local_coordinates(RID p_particles, bool void ParticlesStorage::particles_set_fixed_fps(RID p_particles, int p_fps) { Particles *particles = particles_owner.get_or_null(p_particles); - ERR_FAIL_COND(!particles); + ERR_FAIL_NULL(particles); particles->fixed_fps = p_fps; @@ -396,21 +396,21 @@ void ParticlesStorage::particles_set_fixed_fps(RID p_particles, int p_fps) { void ParticlesStorage::particles_set_interpolate(RID p_particles, bool p_enable) { Particles *particles = particles_owner.get_or_null(p_particles); - ERR_FAIL_COND(!particles); + ERR_FAIL_NULL(particles); particles->interpolate = p_enable; } void ParticlesStorage::particles_set_fractional_delta(RID p_particles, bool p_enable) { Particles *particles = particles_owner.get_or_null(p_particles); - ERR_FAIL_COND(!particles); + ERR_FAIL_NULL(particles); particles->fractional_delta = p_enable; } void ParticlesStorage::particles_set_trails(RID p_particles, bool p_enable, double p_length) { Particles *particles = particles_owner.get_or_null(p_particles); - ERR_FAIL_COND(!particles); + ERR_FAIL_NULL(particles); ERR_FAIL_COND(p_length < 0.01); p_length = MIN(10.0, p_length); @@ -429,7 +429,7 @@ void ParticlesStorage::particles_set_trails(RID p_particles, bool p_enable, doub void ParticlesStorage::particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) { Particles *particles = particles_owner.get_or_null(p_particles); - ERR_FAIL_COND(!particles); + ERR_FAIL_NULL(particles); if (particles->trail_bind_pose_buffer.is_valid() && particles->trail_bind_poses.size() != p_bind_poses.size()) { _particles_free_data(particles); @@ -446,21 +446,21 @@ void ParticlesStorage::particles_set_trail_bind_poses(RID p_particles, const Vec void ParticlesStorage::particles_set_collision_base_size(RID p_particles, real_t p_size) { Particles *particles = particles_owner.get_or_null(p_particles); - ERR_FAIL_COND(!particles); + ERR_FAIL_NULL(particles); particles->collision_base_size = p_size; } void ParticlesStorage::particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) { Particles *particles = particles_owner.get_or_null(p_particles); - ERR_FAIL_COND(!particles); + ERR_FAIL_NULL(particles); particles->transform_align = p_transform_align; } void ParticlesStorage::particles_set_process_material(RID p_particles, RID p_material) { Particles *particles = particles_owner.get_or_null(p_particles); - ERR_FAIL_COND(!particles); + ERR_FAIL_NULL(particles); particles->process_material = p_material; particles->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_PARTICLES); //the instance buffer may have changed @@ -468,35 +468,35 @@ void ParticlesStorage::particles_set_process_material(RID p_particles, RID p_mat RID ParticlesStorage::particles_get_process_material(RID p_particles) const { Particles *particles = particles_owner.get_or_null(p_particles); - ERR_FAIL_COND_V(!particles, RID()); + ERR_FAIL_NULL_V(particles, RID()); return particles->process_material; } void ParticlesStorage::particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) { Particles *particles = particles_owner.get_or_null(p_particles); - ERR_FAIL_COND(!particles); + ERR_FAIL_NULL(particles); particles->draw_order = p_order; } void ParticlesStorage::particles_set_draw_passes(RID p_particles, int p_passes) { Particles *particles = particles_owner.get_or_null(p_particles); - ERR_FAIL_COND(!particles); + ERR_FAIL_NULL(particles); particles->draw_passes.resize(p_passes); } void ParticlesStorage::particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) { Particles *particles = particles_owner.get_or_null(p_particles); - ERR_FAIL_COND(!particles); + ERR_FAIL_NULL(particles); ERR_FAIL_INDEX(p_pass, particles->draw_passes.size()); particles->draw_passes.write[p_pass] = p_mesh; } void ParticlesStorage::particles_restart(RID p_particles) { Particles *particles = particles_owner.get_or_null(p_particles); - ERR_FAIL_COND(!particles); + ERR_FAIL_NULL(particles); particles->restart_request = true; } @@ -520,7 +520,7 @@ void ParticlesStorage::_particles_allocate_emission_buffer(Particles *particles) void ParticlesStorage::particles_set_subemitter(RID p_particles, RID p_subemitter_particles) { Particles *particles = particles_owner.get_or_null(p_particles); - ERR_FAIL_COND(!particles); + ERR_FAIL_NULL(particles); ERR_FAIL_COND(p_particles == p_subemitter_particles); particles->sub_emitter = p_subemitter_particles; @@ -533,7 +533,7 @@ void ParticlesStorage::particles_set_subemitter(RID p_particles, RID p_subemitte void ParticlesStorage::particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) { Particles *particles = particles_owner.get_or_null(p_particles); - ERR_FAIL_COND(!particles); + ERR_FAIL_NULL(particles); ERR_FAIL_COND(particles->amount == 0); if (particles->emitting) { @@ -573,7 +573,7 @@ void ParticlesStorage::particles_emit(RID p_particles, const Transform3D &p_tran void ParticlesStorage::particles_request_process(RID p_particles) { Particles *particles = particles_owner.get_or_null(p_particles); - ERR_FAIL_COND(!particles); + ERR_FAIL_NULL(particles); if (!particles->dirty) { particles->dirty = true; @@ -588,7 +588,7 @@ AABB ParticlesStorage::particles_get_current_aabb(RID p_particles) { } const Particles *particles = particles_owner.get_or_null(p_particles); - ERR_FAIL_COND_V(!particles, AABB()); + ERR_FAIL_NULL_V(particles, AABB()); int total_amount = particles->amount; if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) { @@ -639,28 +639,28 @@ AABB ParticlesStorage::particles_get_current_aabb(RID p_particles) { AABB ParticlesStorage::particles_get_aabb(RID p_particles) const { const Particles *particles = particles_owner.get_or_null(p_particles); - ERR_FAIL_COND_V(!particles, AABB()); + ERR_FAIL_NULL_V(particles, AABB()); return particles->custom_aabb; } void ParticlesStorage::particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) { Particles *particles = particles_owner.get_or_null(p_particles); - ERR_FAIL_COND(!particles); + ERR_FAIL_NULL(particles); particles->emission_transform = p_transform; } int ParticlesStorage::particles_get_draw_passes(RID p_particles) const { const Particles *particles = particles_owner.get_or_null(p_particles); - ERR_FAIL_COND_V(!particles, 0); + ERR_FAIL_NULL_V(particles, 0); return particles->draw_passes.size(); } RID ParticlesStorage::particles_get_draw_pass_mesh(RID p_particles, int p_pass) const { const Particles *particles = particles_owner.get_or_null(p_particles); - ERR_FAIL_COND_V(!particles, RID()); + ERR_FAIL_NULL_V(particles, RID()); ERR_FAIL_INDEX_V(p_pass, particles->draw_passes.size(), RID()); return particles->draw_passes[p_pass]; @@ -668,32 +668,32 @@ RID ParticlesStorage::particles_get_draw_pass_mesh(RID p_particles, int p_pass) void ParticlesStorage::particles_update_dependency(RID p_particles, DependencyTracker *p_instance) { Particles *particles = particles_owner.get_or_null(p_particles); - ERR_FAIL_COND(!particles); + ERR_FAIL_NULL(particles); p_instance->update_dependency(&particles->dependency); } void ParticlesStorage::particles_get_instance_buffer_motion_vectors_offsets(RID p_particles, uint32_t &r_current_offset, uint32_t &r_prev_offset) { Particles *particles = particles_owner.get_or_null(p_particles); - ERR_FAIL_COND(!particles); + ERR_FAIL_NULL(particles); r_current_offset = particles->instance_motion_vectors_current_offset; r_prev_offset = particles->instance_motion_vectors_previous_offset; } void ParticlesStorage::particles_add_collision(RID p_particles, RID p_particles_collision_instance) { Particles *particles = particles_owner.get_or_null(p_particles); - ERR_FAIL_COND(!particles); + ERR_FAIL_NULL(particles); particles->collisions.insert(p_particles_collision_instance); } void ParticlesStorage::particles_remove_collision(RID p_particles, RID p_particles_collision_instance) { Particles *particles = particles_owner.get_or_null(p_particles); - ERR_FAIL_COND(!particles); + ERR_FAIL_NULL(particles); particles->collisions.erase(p_particles_collision_instance); } void ParticlesStorage::particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) { Particles *particles = particles_owner.get_or_null(p_particles); - ERR_FAIL_COND(!particles); + ERR_FAIL_NULL(particles); particles->has_sdf_collision = p_enable; particles->sdf_collision_transform = p_xform; particles->sdf_collision_to_screen = p_to_screen; @@ -1106,7 +1106,7 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta m = static_cast<ParticleProcessMaterialData *>(material_storage->material_get_data(particles_shader.default_material, MaterialStorage::SHADER_TYPE_PARTICLES)); } - ERR_FAIL_COND(!m); + ERR_FAIL_NULL(m); p_particles->has_collision_cache = m->shader_data->uses_collision; @@ -1142,7 +1142,7 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta void ParticlesStorage::particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) { Particles *particles = particles_owner.get_or_null(p_particles); - ERR_FAIL_COND(!particles); + ERR_FAIL_NULL(particles); if (particles->draw_order != RS::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY) { return; @@ -1590,7 +1590,7 @@ Dependency *ParticlesStorage::particles_get_dependency(RID p_particles) const { bool ParticlesStorage::particles_is_inactive(RID p_particles) const { ERR_FAIL_COND_V_MSG(RSG::threaded, false, "This function should never be used with threaded rendering, as it stalls the renderer."); const Particles *particles = particles_owner.get_or_null(p_particles); - ERR_FAIL_COND_V(!particles, false); + ERR_FAIL_NULL_V(particles, false); return !particles->emitting && particles->inactive; } @@ -1722,7 +1722,7 @@ void ParticlesStorage::particles_collision_free(RID p_rid) { RID ParticlesStorage::particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const { ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision); - ERR_FAIL_COND_V(!particles_collision, RID()); + ERR_FAIL_NULL_V(particles_collision, RID()); ERR_FAIL_COND_V(particles_collision->type != RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE, RID()); if (particles_collision->heightfield_texture == RID()) { @@ -1757,7 +1757,7 @@ RID ParticlesStorage::particles_collision_get_heightfield_framebuffer(RID p_part void ParticlesStorage::particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) { ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision); - ERR_FAIL_COND(!particles_collision); + ERR_FAIL_NULL(particles_collision); if (p_type == particles_collision->type) { return; @@ -1773,13 +1773,13 @@ void ParticlesStorage::particles_collision_set_collision_type(RID p_particles_co void ParticlesStorage::particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) { ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision); - ERR_FAIL_COND(!particles_collision); + ERR_FAIL_NULL(particles_collision); particles_collision->cull_mask = p_cull_mask; } void ParticlesStorage::particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) { ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision); - ERR_FAIL_COND(!particles_collision); + ERR_FAIL_NULL(particles_collision); particles_collision->radius = p_radius; particles_collision->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB); @@ -1787,7 +1787,7 @@ void ParticlesStorage::particles_collision_set_sphere_radius(RID p_particles_col void ParticlesStorage::particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) { ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision); - ERR_FAIL_COND(!particles_collision); + ERR_FAIL_NULL(particles_collision); particles_collision->extents = p_extents; particles_collision->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB); @@ -1795,41 +1795,41 @@ void ParticlesStorage::particles_collision_set_box_extents(RID p_particles_colli void ParticlesStorage::particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) { ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision); - ERR_FAIL_COND(!particles_collision); + ERR_FAIL_NULL(particles_collision); particles_collision->attractor_strength = p_strength; } void ParticlesStorage::particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) { ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision); - ERR_FAIL_COND(!particles_collision); + ERR_FAIL_NULL(particles_collision); particles_collision->attractor_directionality = p_directionality; } void ParticlesStorage::particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) { ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision); - ERR_FAIL_COND(!particles_collision); + ERR_FAIL_NULL(particles_collision); particles_collision->attractor_attenuation = p_curve; } void ParticlesStorage::particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) { ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision); - ERR_FAIL_COND(!particles_collision); + ERR_FAIL_NULL(particles_collision); particles_collision->field_texture = p_texture; } void ParticlesStorage::particles_collision_height_field_update(RID p_particles_collision) { ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision); - ERR_FAIL_COND(!particles_collision); + ERR_FAIL_NULL(particles_collision); particles_collision->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB); } void ParticlesStorage::particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) { ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision); - ERR_FAIL_COND(!particles_collision); + ERR_FAIL_NULL(particles_collision); ERR_FAIL_INDEX(p_resolution, RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_MAX); if (particles_collision->heightfield_resolution == p_resolution) { @@ -1846,7 +1846,7 @@ void ParticlesStorage::particles_collision_set_height_field_resolution(RID p_par AABB ParticlesStorage::particles_collision_get_aabb(RID p_particles_collision) const { ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision); - ERR_FAIL_COND_V(!particles_collision, AABB()); + ERR_FAIL_NULL_V(particles_collision, AABB()); switch (particles_collision->type) { case RS::PARTICLES_COLLISION_TYPE_SPHERE_ATTRACT: @@ -1867,13 +1867,13 @@ AABB ParticlesStorage::particles_collision_get_aabb(RID p_particles_collision) c Vector3 ParticlesStorage::particles_collision_get_extents(RID p_particles_collision) const { const ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision); - ERR_FAIL_COND_V(!particles_collision, Vector3()); + ERR_FAIL_NULL_V(particles_collision, Vector3()); return particles_collision->extents; } bool ParticlesStorage::particles_collision_is_heightfield(RID p_particles_collision) const { const ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision); - ERR_FAIL_COND_V(!particles_collision, false); + ERR_FAIL_NULL_V(particles_collision, false); return particles_collision->type == RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE; } @@ -1898,12 +1898,12 @@ void ParticlesStorage::particles_collision_instance_free(RID p_rid) { void ParticlesStorage::particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) { ParticlesCollisionInstance *pci = particles_collision_instance_owner.get_or_null(p_collision_instance); - ERR_FAIL_COND(!pci); + ERR_FAIL_NULL(pci); pci->transform = p_transform; } void ParticlesStorage::particles_collision_instance_set_active(RID p_collision_instance, bool p_active) { ParticlesCollisionInstance *pci = particles_collision_instance_owner.get_or_null(p_collision_instance); - ERR_FAIL_COND(!pci); + ERR_FAIL_NULL(pci); pci->active = p_active; } diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.h b/servers/rendering/renderer_rd/storage_rd/particles_storage.h index 7cea706a8c..b93932f482 100644 --- a/servers/rendering/renderer_rd/storage_rd/particles_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.h @@ -471,19 +471,19 @@ public: _FORCE_INLINE_ RS::ParticlesMode particles_get_mode(RID p_particles) { Particles *particles = particles_owner.get_or_null(p_particles); - ERR_FAIL_COND_V(!particles, RS::PARTICLES_MODE_2D); + ERR_FAIL_NULL_V(particles, RS::PARTICLES_MODE_2D); return particles->mode; } _FORCE_INLINE_ uint32_t particles_get_frame_counter(RID p_particles) { Particles *particles = particles_owner.get_or_null(p_particles); - ERR_FAIL_COND_V(!particles, false); + ERR_FAIL_NULL_V(particles, false); return particles->frame_counter; } _FORCE_INLINE_ uint32_t particles_get_amount(RID p_particles, uint32_t &r_trail_divisor) { Particles *particles = particles_owner.get_or_null(p_particles); - ERR_FAIL_COND_V(!particles, 0); + ERR_FAIL_NULL_V(particles, 0); if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) { r_trail_divisor = particles->trail_bind_poses.size(); @@ -496,21 +496,21 @@ public: _FORCE_INLINE_ bool particles_has_collision(RID p_particles) { Particles *particles = particles_owner.get_or_null(p_particles); - ERR_FAIL_COND_V(!particles, 0); + ERR_FAIL_NULL_V(particles, 0); return particles->has_collision_cache; } _FORCE_INLINE_ uint32_t particles_is_using_local_coords(RID p_particles) { Particles *particles = particles_owner.get_or_null(p_particles); - ERR_FAIL_COND_V(!particles, false); + ERR_FAIL_NULL_V(particles, false); return particles->use_local_coords; } _FORCE_INLINE_ RID particles_get_instance_buffer_uniform_set(RID p_particles, RID p_shader, uint32_t p_set) { Particles *particles = particles_owner.get_or_null(p_particles); - ERR_FAIL_COND_V(!particles, RID()); + ERR_FAIL_NULL_V(particles, RID()); if (particles->particles_transforms_buffer_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(particles->particles_transforms_buffer_uniform_set)) { _particles_update_buffers(particles); Vector<RD::Uniform> uniforms; diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp index 5b59a453dd..5ff5adc59a 100644 --- a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp +++ b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp @@ -52,6 +52,7 @@ void RenderSceneBuffersRD::_bind_methods() { ClassDB::bind_method(D_METHOD("get_texture", "context", "name"), &RenderSceneBuffersRD::get_texture); ClassDB::bind_method(D_METHOD("get_texture_format", "context", "name"), &RenderSceneBuffersRD::_get_texture_format); ClassDB::bind_method(D_METHOD("get_texture_slice", "context", "name", "layer", "mipmap", "layers", "mipmaps"), &RenderSceneBuffersRD::get_texture_slice); + ClassDB::bind_method(D_METHOD("get_texture_slice_view", "context", "name", "layer", "mipmap", "layers", "mipmaps", "view"), &RenderSceneBuffersRD::_get_texture_slice_view); ClassDB::bind_method(D_METHOD("get_texture_slice_size", "context", "name", "mipmap"), &RenderSceneBuffersRD::get_texture_slice_size); ClassDB::bind_method(D_METHOD("clear_context", "context"), &RenderSceneBuffersRD::clear_context); @@ -95,8 +96,8 @@ void RenderSceneBuffersRD::free_named_texture(NamedTexture &p_named_texture) { void RenderSceneBuffersRD::update_samplers() { float computed_mipmap_bias = texture_mipmap_bias; - if (use_taa) { - // Use negative mipmap LOD bias when TAA is enabled to compensate for loss of sharpness. + if (use_taa || (scaling_3d_mode == RS::VIEWPORT_SCALING_3D_MODE_FSR2)) { + // Use negative mipmap LOD bias when TAA or FSR2 is enabled to compensate for loss of sharpness. // This restores sharpness in still images to be roughly at the same level as without TAA, // but moving scenes will still be blurrier. computed_mipmap_bias -= 0.5; @@ -388,6 +389,15 @@ Ref<RDTextureFormat> RenderSceneBuffersRD::_get_texture_format(const StringName return tf; } +RID RenderSceneBuffersRD::_get_texture_slice_view(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap, const uint32_t p_layers, const uint32_t p_mipmaps, const Ref<RDTextureView> p_view) { + RD::TextureView texture_view; + if (p_view.is_valid()) { + texture_view = p_view->base; + } + + return get_texture_slice_view(p_context, p_texture_name, p_layer, p_mipmap, p_layers, p_mipmaps, texture_view); +} + const RD::TextureFormat RenderSceneBuffersRD::get_texture_format(const StringName &p_context, const StringName &p_texture_name) const { NTKey key(p_context, p_texture_name); @@ -397,6 +407,10 @@ const RD::TextureFormat RenderSceneBuffersRD::get_texture_format(const StringNam } RID RenderSceneBuffersRD::get_texture_slice(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap, const uint32_t p_layers, const uint32_t p_mipmaps) { + return get_texture_slice_view(p_context, p_texture_name, p_layer, p_mipmap, p_layers, p_mipmaps, RD::TextureView()); +} + +RID RenderSceneBuffersRD::get_texture_slice_view(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap, const uint32_t p_layers, const uint32_t p_mipmaps, RD::TextureView p_view) { NTKey key(p_context, p_texture_name); // check if this is a known texture @@ -413,19 +427,20 @@ RID RenderSceneBuffersRD::get_texture_slice(const StringName &p_context, const S ERR_FAIL_COND_V(p_mipmap + p_mipmaps > named_texture.format.mipmaps, RID()); // asking the whole thing? just return the original - if (p_layer == 0 && p_mipmap == 0 && named_texture.format.array_layers == p_layers && named_texture.format.mipmaps == p_mipmaps) { + RD::TextureView default_view = RD::TextureView(); + if (p_layer == 0 && p_mipmap == 0 && named_texture.format.array_layers == p_layers && named_texture.format.mipmaps == p_mipmaps && p_view == default_view) { return named_texture.texture; } // see if we have this - NTSliceKey slice_key(p_layer, p_layers, p_mipmap, p_mipmaps); + NTSliceKey slice_key(p_layer, p_layers, p_mipmap, p_mipmaps, p_view); if (named_texture.slices.has(slice_key)) { return named_texture.slices[slice_key]; } // create our slice RID &slice = named_texture.slices[slice_key]; - slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), named_texture.texture, p_layer, p_mipmap, p_mipmaps, p_layers > 1 ? RD::TEXTURE_SLICE_2D_ARRAY : RD::TEXTURE_SLICE_2D, p_layers); + slice = RD::get_singleton()->texture_create_shared_from_slice(p_view, named_texture.texture, p_layer, p_mipmap, p_mipmaps, p_layers > 1 ? RD::TEXTURE_SLICE_2D_ARRAY : RD::TEXTURE_SLICE_2D, p_layers); Array arr; arr.push_back(p_context); @@ -434,7 +449,12 @@ RID RenderSceneBuffersRD::get_texture_slice(const StringName &p_context, const S arr.push_back(itos(p_layers)); arr.push_back(itos(p_mipmap)); arr.push_back(itos(p_mipmaps)); - RD::get_singleton()->set_resource_name(slice, String("RenderBuffer {0}/{1}, layer {2}/{3}, mipmap {4}/{5}").format(arr)); + arr.push_back(itos(p_view.format_override)); + arr.push_back(itos(p_view.swizzle_r)); + arr.push_back(itos(p_view.swizzle_g)); + arr.push_back(itos(p_view.swizzle_b)); + arr.push_back(itos(p_view.swizzle_a)); + RD::get_singleton()->set_resource_name(slice, String("RenderBuffer {0}/{1}, layer {2}/{3}, mipmap {4}/{5}, view {6}/{7}/{8}/{9}/{10}").format(arr)); // and return our slice return slice; @@ -479,7 +499,13 @@ void RenderSceneBuffersRD::allocate_blur_textures() { return; } - uint32_t mipmaps_required = Image::get_image_required_mipmaps(internal_size.x, internal_size.y, Image::FORMAT_RGBAH); + Size2i blur_size = internal_size; + if (scaling_3d_mode == RS::VIEWPORT_SCALING_3D_MODE_FSR2) { + // The blur texture should be as big as the target size when using an upscaler. + blur_size = target_size; + } + + uint32_t mipmaps_required = Image::get_image_required_mipmaps(blur_size.x, blur_size.y, Image::FORMAT_RGBAH); uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; if (can_be_storage) { @@ -488,12 +514,12 @@ void RenderSceneBuffersRD::allocate_blur_textures() { usage_bits += RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; } - create_texture(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, base_data_format, usage_bits, RD::TEXTURE_SAMPLES_1, internal_size, view_count, mipmaps_required); - create_texture(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, base_data_format, usage_bits, RD::TEXTURE_SAMPLES_1, Size2i(internal_size.x >> 1, internal_size.y >> 1), view_count, mipmaps_required - 1); + create_texture(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, base_data_format, usage_bits, RD::TEXTURE_SAMPLES_1, blur_size, view_count, mipmaps_required); + create_texture(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, base_data_format, usage_bits, RD::TEXTURE_SAMPLES_1, Size2i(blur_size.x >> 1, blur_size.y >> 1), view_count, mipmaps_required - 1); // if !can_be_storage we need a half width version if (!can_be_storage) { - create_texture(RB_SCOPE_BUFFERS, RB_TEX_HALF_BLUR, base_data_format, usage_bits, RD::TEXTURE_SAMPLES_1, Size2i(internal_size.x >> 1, internal_size.y), 1, mipmaps_required); + create_texture(RB_SCOPE_BUFFERS, RB_TEX_HALF_BLUR, base_data_format, usage_bits, RD::TEXTURE_SAMPLES_1, Size2i(blur_size.x >> 1, blur_size.y), 1, mipmaps_required); } // TODO redo this: @@ -502,8 +528,8 @@ void RenderSceneBuffersRD::allocate_blur_textures() { RD::TextureFormat tf; tf.format = RD::DATA_FORMAT_R16_SFLOAT; // We could probably use DATA_FORMAT_R8_SNORM if we don't pre-multiply by blur_size but that depends on whether we can remove DEPTH_GAP - tf.width = internal_size.x; - tf.height = internal_size.y; + tf.width = blur_size.x; + tf.height = blur_size.y; tf.texture_type = RD::TEXTURE_TYPE_2D; tf.array_layers = 1; // Our DOF effect handles one eye per turn tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; @@ -603,6 +629,16 @@ RID RenderSceneBuffersRD::get_depth_texture(const uint32_t p_layer) { } } +// Upscaled texture. + +void RenderSceneBuffersRD::ensure_upscaled() { + if (!has_upscaled_texture()) { + uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | (can_be_storage ? RD::TEXTURE_USAGE_STORAGE_BIT : 0) | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + usage_bits |= RD::TEXTURE_USAGE_INPUT_ATTACHMENT_BIT; + create_texture(RB_SCOPE_BUFFERS, RB_TEX_COLOR_UPSCALED, base_data_format, usage_bits, RD::TEXTURE_SAMPLES_1, target_size); + } +} + // Velocity texture. void RenderSceneBuffersRD::ensure_velocity() { diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h index ddd64cb41c..43704119e7 100644 --- a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h +++ b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h @@ -31,6 +31,7 @@ #ifndef RENDER_SCENE_BUFFERS_RD_H #define RENDER_SCENE_BUFFERS_RD_H +#include "../effects/fsr2.h" #include "../effects/vrs.h" #include "../framebuffer_cache_rd.h" #include "core/templates/hash_map.h" @@ -47,6 +48,7 @@ #define RB_TEXTURE SNAME("texture") #define RB_TEX_COLOR SNAME("color") #define RB_TEX_COLOR_MSAA SNAME("color_msaa") +#define RB_TEX_COLOR_UPSCALED SNAME("color_upscaled") #define RB_TEX_DEPTH SNAME("depth") #define RB_TEX_DEPTH_MSAA SNAME("depth_msaa") #define RB_TEX_VELOCITY SNAME("velocity") @@ -114,9 +116,10 @@ private: uint32_t layers; uint32_t mipmap; uint32_t mipmaps; + RD::TextureView texture_view; bool operator==(const NTSliceKey &p_val) const { - return (layer == p_val.layer) && (layers == p_val.layers) && (mipmap == p_val.mipmap) && (mipmaps == p_val.mipmaps); + return (layer == p_val.layer) && (layers == p_val.layers) && (mipmap == p_val.mipmap) && (mipmaps == p_val.mipmaps) && (texture_view == p_val.texture_view); } static uint32_t hash(const NTSliceKey &p_val) { @@ -124,15 +127,21 @@ private: h = hash_murmur3_one_32(p_val.layers, h); h = hash_murmur3_one_32(p_val.mipmap, h); h = hash_murmur3_one_32(p_val.mipmaps, h); + h = hash_murmur3_one_32(p_val.texture_view.format_override); + h = hash_murmur3_one_32(p_val.texture_view.swizzle_r, h); + h = hash_murmur3_one_32(p_val.texture_view.swizzle_g, h); + h = hash_murmur3_one_32(p_val.texture_view.swizzle_b, h); + h = hash_murmur3_one_32(p_val.texture_view.swizzle_a, h); return hash_fmix32(h); } NTSliceKey() {} - NTSliceKey(uint32_t p_layer, uint32_t p_layers, uint32_t p_mipmap, uint32_t p_mipmaps) { + NTSliceKey(uint32_t p_layer, uint32_t p_layers, uint32_t p_mipmap, uint32_t p_mipmaps, RD::TextureView p_texture_view) { layer = p_layer; layers = p_layers; mipmap = p_mipmap; mipmaps = p_mipmaps; + texture_view = p_texture_view; } }; @@ -190,6 +199,7 @@ public: RID get_texture(const StringName &p_context, const StringName &p_texture_name) const; const RD::TextureFormat get_texture_format(const StringName &p_context, const StringName &p_texture_name) const; RID get_texture_slice(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap, const uint32_t p_layers = 1, const uint32_t p_mipmaps = 1); + RID get_texture_slice_view(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap, const uint32_t p_layers = 1, const uint32_t p_mipmaps = 1, RD::TextureView p_view = RD::TextureView()); Size2i get_texture_slice_size(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_mipmap); void clear_context(const StringName &p_context); @@ -230,6 +240,14 @@ public: _FORCE_INLINE_ RID get_internal_texture(const uint32_t p_layer) { return get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_COLOR, p_layer, 0); } + _FORCE_INLINE_ RID get_internal_texture_reactive(const uint32_t p_layer) { + RD::TextureView alpha_only_view; + alpha_only_view.swizzle_r = RD::TEXTURE_SWIZZLE_A; + alpha_only_view.swizzle_g = RD::TEXTURE_SWIZZLE_A; + alpha_only_view.swizzle_b = RD::TEXTURE_SWIZZLE_A; + alpha_only_view.swizzle_a = RD::TEXTURE_SWIZZLE_A; + return get_texture_slice_view(RB_SCOPE_BUFFERS, RB_TEX_COLOR, p_layer, 0, 1, 1, alpha_only_view); + } _FORCE_INLINE_ RID get_color_msaa() const { return get_texture(RB_SCOPE_BUFFERS, RB_TEX_COLOR_MSAA); } @@ -251,6 +269,19 @@ public: // back buffer (color) RID get_back_buffer_texture() const { return has_texture(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0) ? get_texture(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0) : RID(); } // We (re)use our blur texture here. + // Upscaled. + void ensure_upscaled(); + + _FORCE_INLINE_ bool has_upscaled_texture() const { + return has_texture(RB_SCOPE_BUFFERS, RB_TEX_COLOR_UPSCALED); + } + _FORCE_INLINE_ RID get_upscaled_texture() const { + return get_texture(RB_SCOPE_BUFFERS, RB_TEX_COLOR_UPSCALED); + } + _FORCE_INLINE_ RID get_upscaled_texture(const uint32_t p_layer) { + return get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_COLOR_UPSCALED, p_layer, 0); + } + // Velocity, currently only used by TAA (Clustered) but we'll be using this in other places soon too. void ensure_velocity(); @@ -271,6 +302,7 @@ private: RID _create_texture_from_format(const StringName &p_context, const StringName &p_texture_name, const Ref<RDTextureFormat> &p_texture_format, const Ref<RDTextureView> &p_view = Ref<RDTextureView>(), bool p_unique = true); RID _create_texture_view(const StringName &p_context, const StringName &p_texture_name, const StringName p_view_name, const Ref<RDTextureView> p_view = Ref<RDTextureView>()); Ref<RDTextureFormat> _get_texture_format(const StringName &p_context, const StringName &p_texture_name) const; + RID _get_texture_slice_view(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap, const uint32_t p_layers = 1, const uint32_t p_mipmaps = 1, const Ref<RDTextureView> p_view = Ref<RDTextureView>()); // For color and depth as exposed to extensions, we return the buffer that we're rendering into. // Resolving happens after effects etc. are run. diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp index 27c435eeba..40891f9a63 100644 --- a/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp +++ b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp @@ -38,7 +38,7 @@ RID RenderSceneDataRD::create_uniform_buffer() { return RD::get_singleton()->uniform_buffer_create(sizeof(UBODATA)); } -void RenderSceneDataRD::update_ubo(RID p_uniform_buffer, RS::ViewportDebugDraw p_debug_mode, RID p_env, RID p_reflection_probe_instance, RID p_camera_attributes, bool p_flip_y, bool p_pancake_shadows, const Size2i &p_screen_size, const Color &p_default_bg_color, float p_luminance_multiplier, bool p_opaque_render_buffers) { +void RenderSceneDataRD::update_ubo(RID p_uniform_buffer, RS::ViewportDebugDraw p_debug_mode, RID p_env, RID p_reflection_probe_instance, RID p_camera_attributes, bool p_flip_y, bool p_pancake_shadows, const Size2i &p_screen_size, const Color &p_default_bg_color, float p_luminance_multiplier, bool p_opaque_render_buffers, bool p_apply_alpha_multiplier) { RendererSceneRenderRD *render_scene_render = RendererSceneRenderRD::get_singleton(); UBODATA ubo_data; @@ -89,6 +89,7 @@ void RenderSceneDataRD::update_ubo(RID p_uniform_buffer, RS::ViewportDebugDraw p RendererRD::MaterialStorage::store_soft_shadow_kernel(render_scene_render->penumbra_shadow_kernel_get(), ubo.penumbra_shadow_kernel); RendererRD::MaterialStorage::store_soft_shadow_kernel(render_scene_render->soft_shadow_kernel_get(), ubo.soft_shadow_kernel); ubo.camera_visible_layers = camera_visible_layers; + ubo.pass_alpha_multiplier = p_opaque_render_buffers && p_apply_alpha_multiplier ? 0.0f : 1.0f; ubo.viewport_size[0] = p_screen_size.x; ubo.viewport_size[1] = p_screen_size.y; diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h index 7546998a9b..f183207b57 100644 --- a/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h +++ b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h @@ -77,7 +77,7 @@ public: float time_step; RID create_uniform_buffer(); - void update_ubo(RID p_uniform_buffer, RS::ViewportDebugDraw p_debug_mode, RID p_env, RID p_reflection_probe_instance, RID p_camera_attributes, bool p_flip_y, bool p_pancake_shadows, const Size2i &p_screen_size, const Color &p_default_bg_color, float p_luminance_multiplier, bool p_opaque_render_buffers); + void update_ubo(RID p_uniform_buffer, RS::ViewportDebugDraw p_debug_mode, RID p_env, RID p_reflection_probe_instance, RID p_camera_attributes, bool p_flip_y, bool p_pancake_shadows, const Size2i &p_screen_size, const Color &p_default_bg_color, float p_luminance_multiplier, bool p_opaque_render_buffers, bool p_apply_alpha_multiplier); RID get_uniform_buffer(); private: @@ -144,7 +144,7 @@ private: uint32_t pancake_shadows; uint32_t camera_visible_layers; - uint32_t pad2; + float pass_alpha_multiplier; uint32_t pad3; }; diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp index 286a9528fc..166b850864 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp @@ -764,7 +764,7 @@ RID TextureStorage::texture_allocate() { void TextureStorage::texture_free(RID p_texture) { Texture *t = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!t); + ERR_FAIL_NULL(t); ERR_FAIL_COND(t->is_render_target); t->cleanup(); @@ -1089,7 +1089,7 @@ void TextureStorage::texture_3d_initialize(RID p_texture, Image::Format p_format void TextureStorage::texture_proxy_initialize(RID p_texture, RID p_base) { Texture *tex = texture_owner.get_or_null(p_base); - ERR_FAIL_COND(!tex); + ERR_FAIL_NULL(tex); Texture proxy_tex = *tex; proxy_tex.rd_view.format_override = tex->rd_format; @@ -1112,7 +1112,7 @@ void TextureStorage::_texture_2d_update(RID p_texture, const Ref<Image> &p_image ERR_FAIL_COND(p_image.is_null() || p_image->is_empty()); Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!tex); + ERR_FAIL_NULL(tex); ERR_FAIL_COND(tex->is_render_target); ERR_FAIL_COND(p_image->get_width() != tex->width || p_image->get_height() != tex->height); ERR_FAIL_COND(p_image->get_format() != tex->format); @@ -1136,7 +1136,7 @@ void TextureStorage::texture_2d_update(RID p_texture, const Ref<Image> &p_image, void TextureStorage::texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) { Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!tex); + ERR_FAIL_NULL(tex); ERR_FAIL_COND(tex->type != TextureStorage::TYPE_3D); Image::Image3DValidateError verr = Image::validate_3d_image(tex->format, tex->width, tex->height, tex->depth, tex->mipmaps > 1, p_data); @@ -1174,10 +1174,10 @@ void TextureStorage::texture_3d_update(RID p_texture, const Vector<Ref<Image>> & void TextureStorage::texture_proxy_update(RID p_texture, RID p_proxy_to) { Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!tex); + ERR_FAIL_NULL(tex); ERR_FAIL_COND(!tex->is_proxy); Texture *proxy_to = texture_owner.get_or_null(p_proxy_to); - ERR_FAIL_COND(!proxy_to); + ERR_FAIL_NULL(proxy_to); ERR_FAIL_COND(proxy_to->is_proxy); if (tex->proxy_to.is_valid()) { @@ -1191,7 +1191,7 @@ void TextureStorage::texture_proxy_update(RID p_texture, RID p_proxy_to) { tex->rd_texture_srgb = RID(); } Texture *prev_tex = texture_owner.get_or_null(tex->proxy_to); - ERR_FAIL_COND(!prev_tex); + ERR_FAIL_NULL(prev_tex); prev_tex->proxies.erase(p_texture); } @@ -1261,7 +1261,7 @@ void TextureStorage::texture_3d_placeholder_initialize(RID p_texture) { Ref<Image> TextureStorage::texture_2d_get(RID p_texture) const { Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND_V(!tex, Ref<Image>()); + ERR_FAIL_NULL_V(tex, Ref<Image>()); #ifdef TOOLS_ENABLED if (tex->image_cache_2d.is_valid() && !tex->is_render_target) { @@ -1315,7 +1315,7 @@ Ref<Image> TextureStorage::texture_2d_get(RID p_texture) const { Ref<Image> TextureStorage::texture_2d_layer_get(RID p_texture, int p_layer) const { Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND_V(!tex, Ref<Image>()); + ERR_FAIL_NULL_V(tex, Ref<Image>()); Vector<uint8_t> data = RD::get_singleton()->texture_get_data(tex->rd_texture, p_layer); ERR_FAIL_COND_V(data.size() == 0, Ref<Image>()); @@ -1330,7 +1330,7 @@ Ref<Image> TextureStorage::texture_2d_layer_get(RID p_texture, int p_layer) cons Vector<Ref<Image>> TextureStorage::texture_3d_get(RID p_texture) const { Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND_V(!tex, Vector<Ref<Image>>()); + ERR_FAIL_NULL_V(tex, Vector<Ref<Image>>()); ERR_FAIL_COND_V(tex->type != TextureStorage::TYPE_3D, Vector<Ref<Image>>()); Vector<uint8_t> all_data = RD::get_singleton()->texture_get_data(tex->rd_texture, 0); @@ -1359,10 +1359,10 @@ Vector<Ref<Image>> TextureStorage::texture_3d_get(RID p_texture) const { void TextureStorage::texture_replace(RID p_texture, RID p_by_texture) { Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!tex); + ERR_FAIL_NULL(tex); ERR_FAIL_COND(tex->proxy_to.is_valid()); //can't replace proxy Texture *by_tex = texture_owner.get_or_null(p_by_texture); - ERR_FAIL_COND(!by_tex); + ERR_FAIL_NULL(by_tex); ERR_FAIL_COND(by_tex->proxy_to.is_valid()); //can't replace proxy if (tex == by_tex) { @@ -1404,7 +1404,7 @@ void TextureStorage::texture_replace(RID p_texture, RID p_by_texture) { void TextureStorage::texture_set_size_override(RID p_texture, int p_width, int p_height) { Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!tex); + ERR_FAIL_NULL(tex); ERR_FAIL_COND(tex->type != TextureStorage::TYPE_2D); tex->width_2d = p_width; @@ -1413,28 +1413,28 @@ void TextureStorage::texture_set_size_override(RID p_texture, int p_width, int p void TextureStorage::texture_set_path(RID p_texture, const String &p_path) { Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!tex); + ERR_FAIL_NULL(tex); tex->path = p_path; } String TextureStorage::texture_get_path(RID p_texture) const { Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND_V(!tex, String()); + ERR_FAIL_NULL_V(tex, String()); return tex->path; } Image::Format TextureStorage::texture_get_format(RID p_texture) const { Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND_V(!tex, Image::FORMAT_MAX); + ERR_FAIL_NULL_V(tex, Image::FORMAT_MAX); return tex->format; } void TextureStorage::texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) { Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!tex); + ERR_FAIL_NULL(tex); tex->detect_3d_callback_ud = p_userdata; tex->detect_3d_callback = p_callback; @@ -1442,7 +1442,7 @@ void TextureStorage::texture_set_detect_3d_callback(RID p_texture, RS::TextureDe void TextureStorage::texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) { Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!tex); + ERR_FAIL_NULL(tex); tex->detect_normal_callback_ud = p_userdata; tex->detect_normal_callback = p_callback; @@ -1450,7 +1450,7 @@ void TextureStorage::texture_set_detect_normal_callback(RID p_texture, RS::Textu void TextureStorage::texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) { Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND(!tex); + ERR_FAIL_NULL(tex); tex->detect_roughness_callback_ud = p_userdata; tex->detect_roughness_callback = p_callback; @@ -1554,7 +1554,7 @@ RID TextureStorage::texture_get_rd_texture(RID p_texture, bool p_srgb) const { uint64_t TextureStorage::texture_get_native_handle(RID p_texture, bool p_srgb) const { Texture *tex = texture_owner.get_or_null(p_texture); - ERR_FAIL_COND_V(!tex, 0); + ERR_FAIL_NULL_V(tex, 0); if (p_srgb && tex->rd_texture_srgb.is_valid()) { return RD::get_singleton()->texture_get_native_handle(tex->rd_texture_srgb); @@ -2418,14 +2418,14 @@ void TextureStorage::decal_free(RID p_rid) { void TextureStorage::decal_set_size(RID p_decal, const Vector3 &p_size) { Decal *decal = decal_owner.get_or_null(p_decal); - ERR_FAIL_COND(!decal); + ERR_FAIL_NULL(decal); decal->size = p_size; decal->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB); } void TextureStorage::decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) { Decal *decal = decal_owner.get_or_null(p_decal); - ERR_FAIL_COND(!decal); + ERR_FAIL_NULL(decal); ERR_FAIL_INDEX(p_type, RS::DECAL_TEXTURE_MAX); if (decal->textures[p_type] == p_texture) { @@ -2449,32 +2449,32 @@ void TextureStorage::decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID void TextureStorage::decal_set_emission_energy(RID p_decal, float p_energy) { Decal *decal = decal_owner.get_or_null(p_decal); - ERR_FAIL_COND(!decal); + ERR_FAIL_NULL(decal); decal->emission_energy = p_energy; } void TextureStorage::decal_set_albedo_mix(RID p_decal, float p_mix) { Decal *decal = decal_owner.get_or_null(p_decal); - ERR_FAIL_COND(!decal); + ERR_FAIL_NULL(decal); decal->albedo_mix = p_mix; } void TextureStorage::decal_set_modulate(RID p_decal, const Color &p_modulate) { Decal *decal = decal_owner.get_or_null(p_decal); - ERR_FAIL_COND(!decal); + ERR_FAIL_NULL(decal); decal->modulate = p_modulate; } void TextureStorage::decal_set_cull_mask(RID p_decal, uint32_t p_layers) { Decal *decal = decal_owner.get_or_null(p_decal); - ERR_FAIL_COND(!decal); + ERR_FAIL_NULL(decal); decal->cull_mask = p_layers; decal->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_DECAL); } void TextureStorage::decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) { Decal *decal = decal_owner.get_or_null(p_decal); - ERR_FAIL_COND(!decal); + ERR_FAIL_NULL(decal); decal->distance_fade = p_enabled; decal->distance_fade_begin = p_begin; decal->distance_fade_length = p_length; @@ -2482,14 +2482,14 @@ void TextureStorage::decal_set_distance_fade(RID p_decal, bool p_enabled, float void TextureStorage::decal_set_fade(RID p_decal, float p_above, float p_below) { Decal *decal = decal_owner.get_or_null(p_decal); - ERR_FAIL_COND(!decal); + ERR_FAIL_NULL(decal); decal->upper_fade = p_above; decal->lower_fade = p_below; } void TextureStorage::decal_set_normal_fade(RID p_decal, float p_fade) { Decal *decal = decal_owner.get_or_null(p_decal); - ERR_FAIL_COND(!decal); + ERR_FAIL_NULL(decal); decal->normal_fade = p_fade; } @@ -2510,21 +2510,21 @@ void TextureStorage::decal_atlas_remove_texture(RID p_texture) { AABB TextureStorage::decal_get_aabb(RID p_decal) const { Decal *decal = decal_owner.get_or_null(p_decal); - ERR_FAIL_COND_V(!decal, AABB()); + ERR_FAIL_NULL_V(decal, AABB()); return AABB(-decal->size / 2, decal->size); } uint32_t TextureStorage::decal_get_cull_mask(RID p_decal) const { Decal *decal = decal_owner.get_or_null(p_decal); - ERR_FAIL_COND_V(!decal, 0); + ERR_FAIL_NULL_V(decal, 0); return decal->cull_mask; } Dependency *TextureStorage::decal_get_dependency(RID p_decal) { Decal *decal = decal_owner.get_or_null(p_decal); - ERR_FAIL_COND_V(!decal, nullptr); + ERR_FAIL_NULL_V(decal, nullptr); return &decal->dependency; } @@ -2742,7 +2742,7 @@ void TextureStorage::texture_add_to_decal_atlas(RID p_texture, bool p_panorama_t void TextureStorage::texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp) { DecalAtlas::Texture *t = decal_atlas.textures.getptr(p_texture); - ERR_FAIL_COND(!t); + ERR_FAIL_NULL(t); t->users--; if (p_panorama_to_dp) { ERR_FAIL_COND(t->panorama_to_dp_users == 0); @@ -2771,13 +2771,13 @@ void TextureStorage::decal_instance_free(RID p_decal_instance) { void TextureStorage::decal_instance_set_transform(RID p_decal_instance, const Transform3D &p_transform) { DecalInstance *di = decal_instance_owner.get_or_null(p_decal_instance); - ERR_FAIL_COND(!di); + ERR_FAIL_NULL(di); di->transform = p_transform; } void TextureStorage::decal_instance_set_sorting_offset(RID p_decal_instance, float p_sorting_offset) { DecalInstance *di = decal_instance_owner.get_or_null(p_decal_instance); - ERR_FAIL_COND(!di); + ERR_FAIL_NULL(di); di->sorting_offset = p_sorting_offset; } @@ -3222,7 +3222,7 @@ Point2i TextureStorage::render_target_get_position(RID p_render_target) const { void TextureStorage::render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - ERR_FAIL_COND(!rt); + ERR_FAIL_NULL(rt); if (rt->size.x != p_width || rt->size.y != p_height || rt->view_count != p_view_count) { rt->size.x = p_width; rt->size.y = p_height; @@ -3233,21 +3233,21 @@ void TextureStorage::render_target_set_size(RID p_render_target, int p_width, in Size2i TextureStorage::render_target_get_size(RID p_render_target) const { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - ERR_FAIL_COND_V(!rt, Size2i()); + ERR_FAIL_NULL_V(rt, Size2i()); return rt->size; } RID TextureStorage::render_target_get_texture(RID p_render_target) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - ERR_FAIL_COND_V(!rt, RID()); + ERR_FAIL_NULL_V(rt, RID()); return rt->texture; } void TextureStorage::render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - ERR_FAIL_COND(!rt); + ERR_FAIL_NULL(rt); rt->overridden.color = p_color_texture; rt->overridden.depth = p_depth_texture; @@ -3256,21 +3256,21 @@ void TextureStorage::render_target_set_override(RID p_render_target, RID p_color RID TextureStorage::render_target_get_override_color(RID p_render_target) const { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - ERR_FAIL_COND_V(!rt, RID()); + ERR_FAIL_NULL_V(rt, RID()); return rt->overridden.color; } RID TextureStorage::render_target_get_override_depth(RID p_render_target) const { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - ERR_FAIL_COND_V(!rt, RID()); + ERR_FAIL_NULL_V(rt, RID()); return rt->overridden.depth; } RID TextureStorage::render_target_get_override_depth_slice(RID p_render_target, const uint32_t p_layer) const { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - ERR_FAIL_COND_V(!rt, RID()); + ERR_FAIL_NULL_V(rt, RID()); if (rt->overridden.depth.is_null()) { return RID(); @@ -3289,14 +3289,14 @@ RID TextureStorage::render_target_get_override_depth_slice(RID p_render_target, RID TextureStorage::render_target_get_override_velocity(RID p_render_target) const { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - ERR_FAIL_COND_V(!rt, RID()); + ERR_FAIL_NULL_V(rt, RID()); return rt->overridden.velocity; } RID TextureStorage::render_target_get_override_velocity_slice(RID p_render_target, const uint32_t p_layer) const { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - ERR_FAIL_COND_V(!rt, RID()); + ERR_FAIL_NULL_V(rt, RID()); if (rt->overridden.velocity.is_null()) { return RID(); @@ -3315,14 +3315,14 @@ RID TextureStorage::render_target_get_override_velocity_slice(RID p_render_targe void TextureStorage::render_target_set_transparent(RID p_render_target, bool p_is_transparent) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - ERR_FAIL_COND(!rt); + ERR_FAIL_NULL(rt); rt->is_transparent = p_is_transparent; _update_render_target(rt); } bool TextureStorage::render_target_get_transparent(RID p_render_target) const { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - ERR_FAIL_COND_V(!rt, false); + ERR_FAIL_NULL_V(rt, false); return rt->is_transparent; } @@ -3336,19 +3336,19 @@ bool TextureStorage::render_target_get_direct_to_screen(RID p_render_target) con bool TextureStorage::render_target_was_used(RID p_render_target) const { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - ERR_FAIL_COND_V(!rt, false); + ERR_FAIL_NULL_V(rt, false); return rt->was_used; } void TextureStorage::render_target_set_as_unused(RID p_render_target) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - ERR_FAIL_COND(!rt); + ERR_FAIL_NULL(rt); rt->was_used = false; } void TextureStorage::render_target_set_msaa(RID p_render_target, RS::ViewportMSAA p_msaa) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - ERR_FAIL_COND(!rt); + ERR_FAIL_NULL(rt); if (p_msaa == rt->msaa) { return; } @@ -3359,14 +3359,14 @@ void TextureStorage::render_target_set_msaa(RID p_render_target, RS::ViewportMSA RS::ViewportMSAA TextureStorage::render_target_get_msaa(RID p_render_target) const { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - ERR_FAIL_COND_V(!rt, RS::VIEWPORT_MSAA_DISABLED); + ERR_FAIL_NULL_V(rt, RS::VIEWPORT_MSAA_DISABLED); return rt->msaa; } void TextureStorage::render_target_set_use_hdr(RID p_render_target, bool p_use_hdr) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - ERR_FAIL_COND(!rt); + ERR_FAIL_NULL(rt); if (p_use_hdr == rt->use_hdr) { return; @@ -3378,21 +3378,21 @@ void TextureStorage::render_target_set_use_hdr(RID p_render_target, bool p_use_h bool TextureStorage::render_target_is_using_hdr(RID p_render_target) const { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - ERR_FAIL_COND_V(!rt, false); + ERR_FAIL_NULL_V(rt, false); return rt->use_hdr; } RID TextureStorage::render_target_get_rd_framebuffer(RID p_render_target) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - ERR_FAIL_COND_V(!rt, RID()); + ERR_FAIL_NULL_V(rt, RID()); return rt->get_framebuffer(); } RID TextureStorage::render_target_get_rd_texture(RID p_render_target) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - ERR_FAIL_COND_V(!rt, RID()); + ERR_FAIL_NULL_V(rt, RID()); if (rt->overridden.color.is_valid()) { return rt->overridden.color; @@ -3403,7 +3403,7 @@ RID TextureStorage::render_target_get_rd_texture(RID p_render_target) { RID TextureStorage::render_target_get_rd_texture_slice(RID p_render_target, uint32_t p_layer) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - ERR_FAIL_COND_V(!rt, RID()); + ERR_FAIL_NULL_V(rt, RID()); if (rt->view_count == 1) { return rt->color; @@ -3421,20 +3421,20 @@ RID TextureStorage::render_target_get_rd_texture_slice(RID p_render_target, uint RID TextureStorage::render_target_get_rd_texture_msaa(RID p_render_target) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - ERR_FAIL_COND_V(!rt, RID()); + ERR_FAIL_NULL_V(rt, RID()); return rt->color_multisample; } RID TextureStorage::render_target_get_rd_backbuffer(RID p_render_target) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - ERR_FAIL_COND_V(!rt, RID()); + ERR_FAIL_NULL_V(rt, RID()); return rt->backbuffer; } RID TextureStorage::render_target_get_rd_backbuffer_framebuffer(RID p_render_target) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - ERR_FAIL_COND_V(!rt, RID()); + ERR_FAIL_NULL_V(rt, RID()); if (!rt->backbuffer.is_valid()) { _create_render_target_backbuffer(rt); @@ -3445,32 +3445,32 @@ RID TextureStorage::render_target_get_rd_backbuffer_framebuffer(RID p_render_tar void TextureStorage::render_target_request_clear(RID p_render_target, const Color &p_clear_color) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - ERR_FAIL_COND(!rt); + ERR_FAIL_NULL(rt); rt->clear_requested = true; rt->clear_color = p_clear_color; } bool TextureStorage::render_target_is_clear_requested(RID p_render_target) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - ERR_FAIL_COND_V(!rt, false); + ERR_FAIL_NULL_V(rt, false); return rt->clear_requested; } Color TextureStorage::render_target_get_clear_request_color(RID p_render_target) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - ERR_FAIL_COND_V(!rt, Color()); + ERR_FAIL_NULL_V(rt, Color()); return rt->use_hdr ? rt->clear_color.srgb_to_linear() : rt->clear_color; } void TextureStorage::render_target_disable_clear_request(RID p_render_target) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - ERR_FAIL_COND(!rt); + ERR_FAIL_NULL(rt); rt->clear_requested = false; } void TextureStorage::render_target_do_clear_request(RID p_render_target) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - ERR_FAIL_COND(!rt); + ERR_FAIL_NULL(rt); if (!rt->clear_requested) { return; } @@ -3483,7 +3483,7 @@ void TextureStorage::render_target_do_clear_request(RID p_render_target) { void TextureStorage::render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - ERR_FAIL_COND(!rt); + ERR_FAIL_NULL(rt); if (rt->sdf_oversize == p_size && rt->sdf_scale == p_scale) { return; } @@ -3525,28 +3525,28 @@ Rect2i TextureStorage::_render_target_get_sdf_rect(const RenderTarget *rt) const Rect2i TextureStorage::render_target_get_sdf_rect(RID p_render_target) const { const RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - ERR_FAIL_COND_V(!rt, Rect2i()); + ERR_FAIL_NULL_V(rt, Rect2i()); return _render_target_get_sdf_rect(rt); } void TextureStorage::render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - ERR_FAIL_COND(!rt); + ERR_FAIL_NULL(rt); rt->sdf_enabled = p_enabled; } bool TextureStorage::render_target_is_sdf_enabled(RID p_render_target) const { const RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - ERR_FAIL_COND_V(!rt, false); + ERR_FAIL_NULL_V(rt, false); return rt->sdf_enabled; } RID TextureStorage::render_target_get_sdf_texture(RID p_render_target) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - ERR_FAIL_COND_V(!rt, RID()); + ERR_FAIL_NULL_V(rt, RID()); if (rt->sdf_buffer_read.is_null()) { // no texture, create a dummy one for the 2D uniform set RD::TextureFormat tformat; @@ -3684,7 +3684,7 @@ void TextureStorage::_render_target_clear_sdf(RenderTarget *rt) { RID TextureStorage::render_target_get_sdf_framebuffer(RID p_render_target) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - ERR_FAIL_COND_V(!rt, RID()); + ERR_FAIL_NULL_V(rt, RID()); if (rt->sdf_buffer_write_fb.is_null()) { _render_target_allocate_sdf(rt); @@ -3694,7 +3694,7 @@ RID TextureStorage::render_target_get_sdf_framebuffer(RID p_render_target) { } void TextureStorage::render_target_sdf_process(RID p_render_target) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - ERR_FAIL_COND(!rt); + ERR_FAIL_NULL(rt); ERR_FAIL_COND(rt->sdf_buffer_write_fb.is_null()); RenderTargetSDF::PushConstant push_constant; @@ -3772,7 +3772,7 @@ void TextureStorage::render_target_copy_to_back_buffer(RID p_render_target, cons ERR_FAIL_NULL(copy_effects); RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - ERR_FAIL_COND(!rt); + ERR_FAIL_NULL(rt); if (!rt->backbuffer.is_valid()) { _create_render_target_backbuffer(rt); } @@ -3825,7 +3825,7 @@ void TextureStorage::render_target_copy_to_back_buffer(RID p_render_target, cons void TextureStorage::render_target_clear_back_buffer(RID p_render_target, const Rect2i &p_region, const Color &p_color) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - ERR_FAIL_COND(!rt); + ERR_FAIL_NULL(rt); CopyEffects *copy_effects = CopyEffects::get_singleton(); ERR_FAIL_NULL(copy_effects); @@ -3854,7 +3854,7 @@ void TextureStorage::render_target_clear_back_buffer(RID p_render_target, const void TextureStorage::render_target_gen_back_buffer_mipmaps(RID p_render_target, const Rect2i &p_region) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - ERR_FAIL_COND(!rt); + ERR_FAIL_NULL(rt); CopyEffects *copy_effects = CopyEffects::get_singleton(); ERR_FAIL_NULL(copy_effects); @@ -3899,51 +3899,51 @@ void TextureStorage::render_target_gen_back_buffer_mipmaps(RID p_render_target, RID TextureStorage::render_target_get_framebuffer_uniform_set(RID p_render_target) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - ERR_FAIL_COND_V(!rt, RID()); + ERR_FAIL_NULL_V(rt, RID()); return rt->framebuffer_uniform_set; } RID TextureStorage::render_target_get_backbuffer_uniform_set(RID p_render_target) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - ERR_FAIL_COND_V(!rt, RID()); + ERR_FAIL_NULL_V(rt, RID()); return rt->backbuffer_uniform_set; } void TextureStorage::render_target_set_framebuffer_uniform_set(RID p_render_target, RID p_uniform_set) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - ERR_FAIL_COND(!rt); + ERR_FAIL_NULL(rt); rt->framebuffer_uniform_set = p_uniform_set; } void TextureStorage::render_target_set_backbuffer_uniform_set(RID p_render_target, RID p_uniform_set) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - ERR_FAIL_COND(!rt); + ERR_FAIL_NULL(rt); rt->backbuffer_uniform_set = p_uniform_set; } void TextureStorage::render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - ERR_FAIL_COND(!rt); + ERR_FAIL_NULL(rt); rt->vrs_mode = p_mode; } RS::ViewportVRSMode TextureStorage::render_target_get_vrs_mode(RID p_render_target) const { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - ERR_FAIL_COND_V(!rt, RS::VIEWPORT_VRS_DISABLED); + ERR_FAIL_NULL_V(rt, RS::VIEWPORT_VRS_DISABLED); return rt->vrs_mode; } void TextureStorage::render_target_set_vrs_texture(RID p_render_target, RID p_texture) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - ERR_FAIL_COND(!rt); + ERR_FAIL_NULL(rt); rt->vrs_texture = p_texture; } RID TextureStorage::render_target_get_vrs_texture(RID p_render_target) const { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); - ERR_FAIL_COND_V(!rt, RID()); + ERR_FAIL_NULL_V(rt, RID()); return rt->vrs_texture; } diff --git a/servers/rendering/renderer_rd/storage_rd/utilities.cpp b/servers/rendering/renderer_rd/storage_rd/utilities.cpp index cabac4e9ee..cb035c494c 100644 --- a/servers/rendering/renderer_rd/storage_rd/utilities.cpp +++ b/servers/rendering/renderer_rd/storage_rd/utilities.cpp @@ -175,36 +175,34 @@ void Utilities::visibility_notifier_free(RID p_notifier) { void Utilities::visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb) { VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_notifier); - ERR_FAIL_COND(!vn); + ERR_FAIL_NULL(vn); vn->aabb = p_aabb; vn->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB); } void Utilities::visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable) { VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_notifier); - ERR_FAIL_COND(!vn); + ERR_FAIL_NULL(vn); vn->enter_callback = p_enter_callbable; vn->exit_callback = p_exit_callable; } AABB Utilities::visibility_notifier_get_aabb(RID p_notifier) const { const VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_notifier); - ERR_FAIL_COND_V(!vn, AABB()); + ERR_FAIL_NULL_V(vn, AABB()); return vn->aabb; } void Utilities::visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) { VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_notifier); - ERR_FAIL_COND(!vn); + ERR_FAIL_NULL(vn); if (p_enter) { if (!vn->enter_callback.is_null()) { if (p_deferred) { vn->enter_callback.call_deferred(); } else { - Variant r; - Callable::CallError ce; - vn->enter_callback.callp(nullptr, 0, r, ce); + vn->enter_callback.call(); } } } else { @@ -212,9 +210,7 @@ void Utilities::visibility_notifier_call(RID p_notifier, bool p_enter, bool p_de if (p_deferred) { vn->exit_callback.call_deferred(); } else { - Variant r; - Callable::CallError ce; - vn->exit_callback.callp(nullptr, 0, r, ce); + vn->exit_callback.call(); } } } |
