diff options
Diffstat (limited to 'drivers')
59 files changed, 2305 insertions, 2383 deletions
diff --git a/drivers/coreaudio/audio_driver_coreaudio.cpp b/drivers/coreaudio/audio_driver_coreaudio.cpp index 276e69e470..cc38c2352f 100644 --- a/drivers/coreaudio/audio_driver_coreaudio.cpp +++ b/drivers/coreaudio/audio_driver_coreaudio.cpp @@ -38,7 +38,7 @@ #define kOutputBus 0 #define kInputBus 1 -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED OSStatus AudioDriverCoreAudio::input_device_address_cb(AudioObjectID inObjectID, UInt32 inNumberAddresses, const AudioObjectPropertyAddress *inAddresses, void *inClientData) { @@ -72,7 +72,7 @@ Error AudioDriverCoreAudio::init() { AudioComponentDescription desc; memset(&desc, 0, sizeof(desc)); desc.componentType = kAudioUnitType_Output; -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED desc.componentSubType = kAudioUnitSubType_HALOutput; #else desc.componentSubType = kAudioUnitSubType_RemoteIO; @@ -85,7 +85,7 @@ Error AudioDriverCoreAudio::init() { OSStatus result = AudioComponentInstanceNew(comp, &audio_unit); ERR_FAIL_COND_V(result != noErr, FAILED); -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED AudioObjectPropertyAddress prop; prop.mSelector = kAudioHardwarePropertyDefaultOutputDevice; prop.mScope = kAudioObjectPropertyScopeGlobal; @@ -135,7 +135,7 @@ Error AudioDriverCoreAudio::init() { // Sample rate is independent of channels (ref: https://stackoverflow.com/questions/11048825/audio-sample-frequency-rely-on-channels) buffer_frames = closest_power_of_2(latency * mix_rate / 1000); -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED result = AudioUnitSetProperty(audio_unit, kAudioDevicePropertyBufferFrameSize, kAudioUnitScope_Global, kOutputBus, &buffer_frames, sizeof(UInt32)); ERR_FAIL_COND_V(result != noErr, FAILED); #endif @@ -313,7 +313,7 @@ void AudioDriverCoreAudio::finish() { ERR_PRINT("AudioUnitUninitialize failed"); } -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED AudioObjectPropertyAddress prop; prop.mSelector = kAudioHardwarePropertyDefaultOutputDevice; prop.mScope = kAudioObjectPropertyScopeGlobal; @@ -339,7 +339,7 @@ Error AudioDriverCoreAudio::capture_init() { AudioComponentDescription desc; memset(&desc, 0, sizeof(desc)); desc.componentType = kAudioUnitType_Output; -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED desc.componentSubType = kAudioUnitSubType_HALOutput; #else desc.componentSubType = kAudioUnitSubType_RemoteIO; @@ -352,7 +352,7 @@ Error AudioDriverCoreAudio::capture_init() { OSStatus result = AudioComponentInstanceNew(comp, &input_unit); ERR_FAIL_COND_V(result != noErr, FAILED); -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED AudioObjectPropertyAddress prop; prop.mSelector = kAudioHardwarePropertyDefaultInputDevice; prop.mScope = kAudioObjectPropertyScopeGlobal; @@ -370,7 +370,7 @@ Error AudioDriverCoreAudio::capture_init() { ERR_FAIL_COND_V(result != noErr, FAILED); UInt32 size; -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED AudioDeviceID deviceId; size = sizeof(AudioDeviceID); AudioObjectPropertyAddress property = { kAudioHardwarePropertyDefaultInputDevice, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; @@ -447,7 +447,7 @@ void AudioDriverCoreAudio::capture_finish() { ERR_PRINT("AudioUnitUninitialize failed"); } -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED AudioObjectPropertyAddress prop; prop.mSelector = kAudioHardwarePropertyDefaultInputDevice; prop.mScope = kAudioObjectPropertyScopeGlobal; @@ -491,7 +491,7 @@ Error AudioDriverCoreAudio::capture_stop() { return OK; } -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED Array AudioDriverCoreAudio::_get_device_list(bool capture) { Array list; diff --git a/drivers/coreaudio/audio_driver_coreaudio.h b/drivers/coreaudio/audio_driver_coreaudio.h index f86037f092..7fac8a99ed 100644 --- a/drivers/coreaudio/audio_driver_coreaudio.h +++ b/drivers/coreaudio/audio_driver_coreaudio.h @@ -28,15 +28,15 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifdef COREAUDIO_ENABLED - #ifndef AUDIO_DRIVER_COREAUDIO_H #define AUDIO_DRIVER_COREAUDIO_H +#ifdef COREAUDIO_ENABLED + #include "servers/audio_server.h" #import <AudioUnit/AudioUnit.h> -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED #import <CoreAudio/AudioHardware.h> #endif @@ -58,7 +58,7 @@ class AudioDriverCoreAudio : public AudioDriver { Vector<int32_t> samples_in; Vector<int16_t> input_buf; -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED Array _get_device_list(bool capture = false); void _set_device(const String &device, bool capture = false); @@ -106,7 +106,7 @@ public: bool try_lock(); void stop(); -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED virtual Array get_device_list(); virtual String get_device(); virtual void set_device(String device); @@ -120,6 +120,6 @@ public: ~AudioDriverCoreAudio() {} }; -#endif +#endif // COREAUDIO_ENABLED -#endif +#endif // AUDIO_DRIVER_COREAUDIO_H diff --git a/drivers/coremidi/midi_driver_coremidi.h b/drivers/coremidi/midi_driver_coremidi.h index 0085141c6d..ac2ad99eb3 100644 --- a/drivers/coremidi/midi_driver_coremidi.h +++ b/drivers/coremidi/midi_driver_coremidi.h @@ -28,11 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifdef COREMIDI_ENABLED - #ifndef MIDI_DRIVER_COREMIDI_H #define MIDI_DRIVER_COREMIDI_H +#ifdef COREMIDI_ENABLED + #include "core/os/midi_driver.h" #include "core/templates/vector.h" @@ -57,5 +57,6 @@ public: virtual ~MIDIDriverCoreMidi(); }; -#endif // MIDI_DRIVER_COREMIDI_H #endif // COREMIDI_ENABLED + +#endif // MIDI_DRIVER_COREMIDI_H diff --git a/drivers/gl_context/SCsub b/drivers/gl_context/SCsub index ddeec6f4c6..7e8bd22960 100644 --- a/drivers/gl_context/SCsub +++ b/drivers/gl_context/SCsub @@ -2,7 +2,7 @@ Import("env") -if env["platform"] in ["haiku", "osx", "windows", "linuxbsd"]: +if env["platform"] in ["haiku", "macos", "windows", "linuxbsd"]: # Thirdparty source files thirdparty_dir = "#thirdparty/glad/" thirdparty_sources = [ diff --git a/drivers/gles3/effects/copy_effects.h b/drivers/gles3/effects/copy_effects.h index 1cf1ac9404..b863e76579 100644 --- a/drivers/gles3/effects/copy_effects.h +++ b/drivers/gles3/effects/copy_effects.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef COPY_GL_H -#define COPY_GL_H +#ifndef COPY_EFFECTS_GLES3_H +#define COPY_EFFECTS_GLES3_H #ifdef GLES3_ENABLED @@ -70,4 +70,5 @@ public: } //namespace GLES3 #endif // GLES3_ENABLED -#endif // !COPY_GL_H + +#endif // COPY_EFFECTS_GLES3_H diff --git a/drivers/gles3/environment/fog.cpp b/drivers/gles3/environment/fog.cpp new file mode 100644 index 0000000000..02d88f6871 --- /dev/null +++ b/drivers/gles3/environment/fog.cpp @@ -0,0 +1,66 @@ +/*************************************************************************/ +/* fog.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* 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. */ +/*************************************************************************/ + +#ifdef GLES3_ENABLED + +#include "fog.h" + +using namespace GLES3; + +/* FOG */ + +RID Fog::fog_volume_allocate() { + return RID(); +} + +void Fog::fog_volume_initialize(RID p_rid) { +} + +void Fog::fog_free(RID p_rid) { +} + +void Fog::fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) { +} + +void Fog::fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) { +} + +void Fog::fog_volume_set_material(RID p_fog_volume, RID p_material) { +} + +AABB Fog::fog_volume_get_aabb(RID p_fog_volume) const { + return AABB(); +} + +RS::FogVolumeShape Fog::fog_volume_get_shape(RID p_fog_volume) const { + return RS::FOG_VOLUME_SHAPE_BOX; +} + +#endif // GLES3_ENABLED diff --git a/drivers/gles3/environment/fog.h b/drivers/gles3/environment/fog.h new file mode 100644 index 0000000000..350eb459cf --- /dev/null +++ b/drivers/gles3/environment/fog.h @@ -0,0 +1,62 @@ +/*************************************************************************/ +/* fog.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* 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 FOG_GLES3_H +#define FOG_GLES3_H + +#ifdef GLES3_ENABLED + +#include "core/templates/local_vector.h" +#include "core/templates/rid_owner.h" +#include "core/templates/self_list.h" +#include "servers/rendering/environment/renderer_fog.h" + +namespace GLES3 { + +class Fog : public RendererFog { +public: + /* FOG VOLUMES */ + + virtual RID fog_volume_allocate() override; + virtual void fog_volume_initialize(RID p_rid) override; + virtual void fog_free(RID p_rid) override; + + virtual void fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) override; + virtual void fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) override; + virtual void fog_volume_set_material(RID p_fog_volume, RID p_material) override; + virtual AABB fog_volume_get_aabb(RID p_fog_volume) const override; + virtual RS::FogVolumeShape fog_volume_get_shape(RID p_fog_volume) const override; +}; + +} // namespace GLES3 + +#endif // GLES3_ENABLED + +#endif // FOG_GLES3_H diff --git a/drivers/gles3/environment/gi.cpp b/drivers/gles3/environment/gi.cpp index 98d698b2ae..84cdb81d35 100644 --- a/drivers/gles3/environment/gi.cpp +++ b/drivers/gles3/environment/gi.cpp @@ -126,13 +126,6 @@ bool GI::voxel_gi_is_using_two_bounces(RID p_voxel_gi) const { return false; } -void GI::voxel_gi_set_anisotropy_strength(RID p_voxel_gi, float p_strength) { -} - -float GI::voxel_gi_get_anisotropy_strength(RID p_voxel_gi) const { - return 0; -} - uint32_t GI::voxel_gi_get_version(RID p_voxel_gi) const { return 0; } diff --git a/drivers/gles3/environment/gi.h b/drivers/gles3/environment/gi.h index bff482d7fa..7a0634f22b 100644 --- a/drivers/gles3/environment/gi.h +++ b/drivers/gles3/environment/gi.h @@ -86,9 +86,6 @@ public: virtual void voxel_gi_set_use_two_bounces(RID p_voxel_gi, bool p_enable) override; virtual bool voxel_gi_is_using_two_bounces(RID p_voxel_gi) const override; - virtual void voxel_gi_set_anisotropy_strength(RID p_voxel_gi, float p_strength) override; - virtual float voxel_gi_get_anisotropy_strength(RID p_voxel_gi) const override; - virtual uint32_t voxel_gi_get_version(RID p_voxel_gi) const override; }; @@ -96,4 +93,4 @@ public: #endif // GLES3_ENABLED -#endif // !GI_GLES3_H +#endif // GI_GLES3_H diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index d41c844d1d..d4ac3c993a 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -34,12 +34,12 @@ #include "core/os/os.h" #include "rasterizer_scene_gles3.h" -#include "rasterizer_storage_gles3.h" #include "core/config/project_settings.h" #include "servers/rendering/rendering_server_default.h" #include "storage/config.h" #include "storage/material_storage.h" +#include "storage/mesh_storage.h" #include "storage/texture_storage.h" #ifndef GLES_OVER_GL @@ -135,7 +135,7 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_ Size2i ssize = texture_storage->render_target_get_size(p_to_render_target); Transform3D screen_transform; - screen_transform.translate(-(ssize.width / 2.0f), -(ssize.height / 2.0f), 0.0f); + screen_transform.translate_local(-(ssize.width / 2.0f), -(ssize.height / 2.0f), 0.0f); screen_transform.scale(Vector3(2.0f / ssize.width, 2.0f / ssize.height, 1.0f)); _update_transform_to_mat4(screen_transform, state_buffer.screen_transform); _update_transform_2d_to_mat4(p_canvas_transform, state_buffer.canvas_transform); @@ -183,7 +183,7 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_ glBindBufferBase(GL_UNIFORM_BUFFER, BASE_UNIFORM_LOCATION, state.canvas_state_buffer); glBufferData(GL_UNIFORM_BUFFER, sizeof(StateBuffer), &state_buffer, GL_STREAM_DRAW); - GLuint global_buffer = material_storage->global_variables_get_uniform_buffer(); + GLuint global_buffer = material_storage->global_shader_uniforms_get_uniform_buffer(); glBindBufferBase(GL_UNIFORM_BUFFER, GLOBAL_UNIFORM_LOCATION, global_buffer); glBindBuffer(GL_UNIFORM_BUFFER, 0); @@ -815,10 +815,8 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item _bind_canvas_texture(texture, current_filter, current_repeat, r_index); if (instance_count == 1) { GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(state.current_shader_version, CanvasShaderGLES3::MODE_ATTRIBUTES); - } else if (instance_count > 1) { - GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(state.current_shader_version, CanvasShaderGLES3::MODE_INSTANCED); } else { - ERR_PRINT("Must have at least one mesh instance to draw mesh"); + GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(state.current_shader_version, CanvasShaderGLES3::MODE_INSTANCED); } uint32_t surf_count = mesh_storage->mesh_get_surface_count(mesh); @@ -882,7 +880,7 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item } else { glDrawArrays(primitive_gl, 0, mesh_storage->mesh_surface_get_vertices_drawn_count(surface)); } - } else if (instance_count > 1) { + } else { if (use_index_buffer) { glDrawElementsInstanced(primitive_gl, mesh_storage->mesh_surface_get_vertices_drawn_count(surface), mesh_storage->mesh_surface_get_index_type(surface), 0, instance_count); } else { @@ -1217,7 +1215,7 @@ void RasterizerCanvasGLES3::reset_canvas() { void RasterizerCanvasGLES3::canvas_debug_viewport_shadows(Light *p_lights_with_shadow) { } -void RasterizerCanvasGLES3::canvas_light_shadow_buffer_update(RID p_buffer, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders, CameraMatrix *p_xform_cache) { +void RasterizerCanvasGLES3::canvas_light_shadow_buffer_update(RID p_buffer, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders, Projection *p_xform_cache) { } void RasterizerCanvasGLES3::draw_lens_distortion_rect(const Rect2 &p_rect, float p_k1, float p_k2, const Vector2 &p_eye_center, float p_oversample) { @@ -1416,9 +1414,8 @@ RasterizerCanvasGLES3 *RasterizerCanvasGLES3::get_singleton() { return singleton; } -RasterizerCanvasGLES3::RasterizerCanvasGLES3(RasterizerStorageGLES3 *p_storage) { +RasterizerCanvasGLES3::RasterizerCanvasGLES3() { singleton = this; - storage = p_storage; GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton(); GLES3::Config *config = GLES3::Config::get_singleton(); @@ -1571,7 +1568,7 @@ RasterizerCanvasGLES3::RasterizerCanvasGLES3(RasterizerStorageGLES3 *p_storage) glBindBuffer(GL_UNIFORM_BUFFER, 0); String global_defines; - global_defines += "#define MAX_GLOBAL_VARIABLES 256\n"; // TODO: this is arbitrary for now + global_defines += "#define MAX_GLOBAL_SHADER_UNIFORMS 256\n"; // TODO: this is arbitrary for now global_defines += "#define MAX_LIGHTS " + itos(state.max_instances_per_batch) + "\n"; global_defines += "#define MAX_DRAW_DATA_INSTANCES " + itos(state.max_instances_per_batch) + "\n"; diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h index bf13c91e1c..f920e37130 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.h +++ b/drivers/gles3/rasterizer_canvas_gles3.h @@ -28,13 +28,12 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RASTERIZER_CANVAS_OPENGL_H -#define RASTERIZER_CANVAS_OPENGL_H +#ifndef RASTERIZER_CANVAS_GLES3_H +#define RASTERIZER_CANVAS_GLES3_H #ifdef GLES3_ENABLED #include "rasterizer_scene_gles3.h" -#include "rasterizer_storage_gles3.h" #include "servers/rendering/renderer_canvas_render.h" #include "servers/rendering/renderer_compositor.h" #include "storage/material_storage.h" @@ -204,15 +203,13 @@ public: typedef void Texture; - RasterizerStorageGLES3 *storage = nullptr; - void canvas_begin(RID p_to_render_target, bool p_to_backbuffer); //virtual void draw_window_margins(int *black_margin, RID *black_image) override; void draw_lens_distortion_rect(const Rect2 &p_rect, float p_k1, float p_k2, const Vector2 &p_eye_center, float p_oversample); void reset_canvas(); - void canvas_light_shadow_buffer_update(RID p_buffer, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders, CameraMatrix *p_xform_cache); + void canvas_light_shadow_buffer_update(RID p_buffer, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders, Projection *p_xform_cache); virtual void canvas_debug_viewport_shadows(Light *p_lights_with_shadow) override; @@ -260,9 +257,10 @@ public: void set_time(double p_time); static RasterizerCanvasGLES3 *get_singleton(); - RasterizerCanvasGLES3(RasterizerStorageGLES3 *p_storage); + RasterizerCanvasGLES3(); ~RasterizerCanvasGLES3(); }; #endif // GLES3_ENABLED -#endif // RASTERIZER_CANVAS_OPENGL_H + +#endif // RASTERIZER_CANVAS_GLES3_H diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp index 78ffb42557..33303b1e38 100644 --- a/drivers/gles3/rasterizer_gles3.cpp +++ b/drivers/gles3/rasterizer_gles3.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "rasterizer_gles3.h" +#include "storage/utilities.h" #ifdef GLES3_ENABLED @@ -68,7 +69,7 @@ #endif #endif -#if !defined(IPHONE_ENABLED) && !defined(JAVASCRIPT_ENABLED) +#if !defined(IOS_ENABLED) && !defined(JAVASCRIPT_ENABLED) // We include EGL below to get debug callback on GLES2 platforms, // but EGL is not available on iOS. #define CAN_DEBUG @@ -99,8 +100,9 @@ void RasterizerGLES3::begin_frame(double frame_step) { canvas->set_time(time_total); scene->set_time(time_total, frame_step); - storage->info.render_final = storage->info.render; - storage->info.render.reset(); + GLES3::Utilities *utilities = GLES3::Utilities::get_singleton(); + utilities->info.render_final = utilities->info.render; + utilities->info.render.reset(); //scene->iteration(); } @@ -197,14 +199,15 @@ void RasterizerGLES3::initialize() { void RasterizerGLES3::finalize() { memdelete(scene); memdelete(canvas); - memdelete(storage); memdelete(gi); + memdelete(fog); memdelete(copy_effects); memdelete(light_storage); memdelete(particles_storage); memdelete(mesh_storage); memdelete(material_storage); memdelete(texture_storage); + memdelete(utilities); memdelete(config); } @@ -265,6 +268,7 @@ RasterizerGLES3::RasterizerGLES3() { // OpenGL needs to be initialized before initializing the Rasterizers config = memnew(GLES3::Config); + utilities = memnew(GLES3::Utilities); texture_storage = memnew(GLES3::TextureStorage); material_storage = memnew(GLES3::MaterialStorage); mesh_storage = memnew(GLES3::MeshStorage); @@ -272,9 +276,9 @@ RasterizerGLES3::RasterizerGLES3() { light_storage = memnew(GLES3::LightStorage); copy_effects = memnew(GLES3::CopyEffects); gi = memnew(GLES3::GI); - storage = memnew(RasterizerStorageGLES3); - canvas = memnew(RasterizerCanvasGLES3(storage)); - scene = memnew(RasterizerSceneGLES3(storage)); + fog = memnew(GLES3::Fog); + canvas = memnew(RasterizerCanvasGLES3()); + scene = memnew(RasterizerSceneGLES3()); } RasterizerGLES3::~RasterizerGLES3() { diff --git a/drivers/gles3/rasterizer_gles3.h b/drivers/gles3/rasterizer_gles3.h index c0322dc45b..97543af0d5 100644 --- a/drivers/gles3/rasterizer_gles3.h +++ b/drivers/gles3/rasterizer_gles3.h @@ -28,16 +28,16 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RASTERIZER_OPENGL_H -#define RASTERIZER_OPENGL_H +#ifndef RASTERIZER_GLES3_H +#define RASTERIZER_GLES3_H #ifdef GLES3_ENABLED #include "effects/copy_effects.h" +#include "environment/fog.h" #include "environment/gi.h" #include "rasterizer_canvas_gles3.h" #include "rasterizer_scene_gles3.h" -#include "rasterizer_storage_gles3.h" #include "servers/rendering/renderer_compositor.h" #include "storage/config.h" #include "storage/light_storage.h" @@ -45,6 +45,7 @@ #include "storage/mesh_storage.h" #include "storage/particles_storage.h" #include "storage/texture_storage.h" +#include "storage/utilities.h" class RasterizerGLES3 : public RendererCompositor { private: @@ -55,27 +56,29 @@ private: protected: GLES3::Config *config = nullptr; + GLES3::Utilities *utilities = nullptr; GLES3::TextureStorage *texture_storage = nullptr; GLES3::MaterialStorage *material_storage = nullptr; GLES3::MeshStorage *mesh_storage = nullptr; GLES3::ParticlesStorage *particles_storage = nullptr; GLES3::LightStorage *light_storage = nullptr; GLES3::GI *gi = nullptr; + GLES3::Fog *fog = nullptr; GLES3::CopyEffects *copy_effects = nullptr; - RasterizerStorageGLES3 *storage = nullptr; RasterizerCanvasGLES3 *canvas = nullptr; RasterizerSceneGLES3 *scene = nullptr; void _blit_render_target_to_screen(RID p_render_target, DisplayServer::WindowID p_screen, const Rect2 &p_screen_rect); public: + RendererUtilities *get_utilities() { return utilities; } RendererLightStorage *get_light_storage() { return light_storage; } RendererMaterialStorage *get_material_storage() { return material_storage; } RendererMeshStorage *get_mesh_storage() { return mesh_storage; } RendererParticlesStorage *get_particles_storage() { return particles_storage; } RendererTextureStorage *get_texture_storage() { return texture_storage; } RendererGI *get_gi() { return gi; } - RendererStorage *get_storage() { return storage; } + RendererFog *get_fog() { return fog; } RendererCanvasRender *get_canvas() { return canvas; } RendererSceneRender *get_scene() { return scene; } @@ -109,4 +112,4 @@ public: #endif // GLES3_ENABLED -#endif +#endif // RASTERIZER_GLES3_H diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 33c7b9bf32..26d84aa6a3 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -32,20 +32,18 @@ #include "core/config/project_settings.h" #include "core/templates/sort_array.h" #include "servers/rendering/rendering_server_default.h" +#include "servers/rendering/rendering_server_globals.h" #include "storage/config.h" +#include "storage/light_storage.h" +#include "storage/mesh_storage.h" +#include "storage/texture_storage.h" #ifdef GLES3_ENABLED -uint64_t RasterizerSceneGLES3::auto_exposure_counter = 2; - RasterizerSceneGLES3 *RasterizerSceneGLES3::singleton = nullptr; -RasterizerSceneGLES3 *RasterizerSceneGLES3::get_singleton() { - return singleton; -} - -RendererSceneRender::GeometryInstance *RasterizerSceneGLES3::geometry_instance_create(RID p_base) { - RS::InstanceType type = storage->get_base_type(p_base); +RenderGeometryInstance *RasterizerSceneGLES3::geometry_instance_create(RID p_base) { + RS::InstanceType type = RSG::utilities->get_base_type(p_base); ERR_FAIL_COND_V(!((1 << type) & RS::INSTANCE_GEOMETRY_MASK), nullptr); GeometryInstanceGLES3 *ginstance = geometry_instance_alloc.alloc(); @@ -54,176 +52,36 @@ RendererSceneRender::GeometryInstance *RasterizerSceneGLES3::geometry_instance_c ginstance->data->base = p_base; ginstance->data->base_type = type; - _geometry_instance_mark_dirty(ginstance); + ginstance->_mark_dirty(); return ginstance; } -void RasterizerSceneGLES3::geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) { - GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->data->skeleton = p_skeleton; - - _geometry_instance_mark_dirty(ginstance); - ginstance->data->dirty_dependencies = true; -} - -void RasterizerSceneGLES3::geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) { - GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->data->material_override = p_override; - - _geometry_instance_mark_dirty(ginstance); - ginstance->data->dirty_dependencies = true; -} - -void RasterizerSceneGLES3::geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_overlay) { - GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->data->material_overlay = p_overlay; - - _geometry_instance_mark_dirty(ginstance); - ginstance->data->dirty_dependencies = true; -} - -void RasterizerSceneGLES3::geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials) { - GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->data->surface_materials = p_materials; - - _geometry_instance_mark_dirty(ginstance); - ginstance->data->dirty_dependencies = true; -} - -void RasterizerSceneGLES3::geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) { - GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ERR_FAIL_COND(!ginstance); - ginstance->mesh_instance = p_mesh_instance; - - _geometry_instance_mark_dirty(ginstance); -} - -void RasterizerSceneGLES3::geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) { - GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->transform = p_transform; - ginstance->mirror = p_transform.basis.determinant() < 0; - ginstance->data->aabb = p_aabb; - ginstance->transformed_aabb = p_transformed_aabb; - - Vector3 model_scale_vec = p_transform.basis.get_scale_abs(); - // handle non uniform scale here - - float max_scale = MAX(model_scale_vec.x, MAX(model_scale_vec.y, model_scale_vec.z)); - float min_scale = MIN(model_scale_vec.x, MIN(model_scale_vec.y, model_scale_vec.z)); - ginstance->non_uniform_scale = max_scale >= 0.0 && (min_scale / max_scale) < 0.9; - - ginstance->lod_model_scale = max_scale; -} - -void RasterizerSceneGLES3::geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) { - GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->layer_mask = p_layer_mask; -} - -void RasterizerSceneGLES3::geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) { - GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->lod_bias = p_lod_bias; -} - -void RasterizerSceneGLES3::geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) { - GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->force_alpha = CLAMP(1.0 - p_transparency, 0, 1); -} - -void RasterizerSceneGLES3::geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) { - GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->fade_near = p_enable_near; - ginstance->fade_near_begin = p_near_begin; - ginstance->fade_near_end = p_near_end; - ginstance->fade_far = p_enable_far; - ginstance->fade_far_begin = p_far_begin; - ginstance->fade_far_end = p_far_end; -} - -void RasterizerSceneGLES3::geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) { - GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->parent_fade_alpha = p_alpha; -} - -void RasterizerSceneGLES3::geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) { - GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->data->use_baked_light = p_enable; - - _geometry_instance_mark_dirty(ginstance); -} - -void RasterizerSceneGLES3::geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) { - GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->data->use_dynamic_gi = p_enable; - _geometry_instance_mark_dirty(ginstance); -} - -void RasterizerSceneGLES3::geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) { - GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); -} - -void RasterizerSceneGLES3::geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) { - GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); -} - -void RasterizerSceneGLES3::geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) { - GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->shader_parameters_offset = p_offset; - _geometry_instance_mark_dirty(ginstance); -} - -void RasterizerSceneGLES3::geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) { - GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - ginstance->data->cast_double_sided_shadows = p_enable; - _geometry_instance_mark_dirty(ginstance); -} - uint32_t RasterizerSceneGLES3::geometry_instance_get_pair_mask() { return (1 << RS::INSTANCE_LIGHT); } -void RasterizerSceneGLES3::geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) { - GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); - +void RasterizerSceneGLES3::GeometryInstanceGLES3::pair_light_instances(const RID *p_light_instances, uint32_t p_light_instance_count) { GLES3::Config *config = GLES3::Config::get_singleton(); - ginstance->omni_light_count = 0; - ginstance->spot_light_count = 0; - ginstance->omni_lights.clear(); - ginstance->spot_lights.clear(); + omni_light_count = 0; + spot_light_count = 0; + omni_lights.clear(); + spot_lights.clear(); for (uint32_t i = 0; i < p_light_instance_count; i++) { - RS::LightType type = light_instance_get_type(p_light_instances[i]); + RS::LightType type = RasterizerSceneGLES3::get_singleton()->light_instance_get_type(p_light_instances[i]); switch (type) { case RS::LIGHT_OMNI: { - if (ginstance->omni_light_count < (uint32_t)config->max_lights_per_object) { - ginstance->omni_lights.push_back(p_light_instances[i]); - ginstance->omni_light_count++; + if (omni_light_count < (uint32_t)config->max_lights_per_object) { + omni_lights.push_back(p_light_instances[i]); + omni_light_count++; } } break; case RS::LIGHT_SPOT: { - if (ginstance->spot_light_count < (uint32_t)config->max_lights_per_object) { - ginstance->spot_lights.push_back(p_light_instances[i]); - ginstance->spot_light_count++; + if (spot_light_count < (uint32_t)config->max_lights_per_object) { + spot_lights.push_back(p_light_instances[i]); + spot_light_count++; } } break; default: @@ -232,21 +90,7 @@ void RasterizerSceneGLES3::geometry_instance_pair_light_instances(GeometryInstan } } -void RasterizerSceneGLES3::geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) { -} - -void RasterizerSceneGLES3::geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) { -} - -void RasterizerSceneGLES3::geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) { -} - -void RasterizerSceneGLES3::geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) { - GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); - ERR_FAIL_COND(!ginstance); -} - -void RasterizerSceneGLES3::geometry_instance_free(GeometryInstance *p_geometry_instance) { +void RasterizerSceneGLES3::geometry_instance_free(RenderGeometryInstance *p_geometry_instance) { GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); ERR_FAIL_COND(!ginstance); GeometryInstanceSurface *surf = ginstance->surface_caches; @@ -259,24 +103,29 @@ void RasterizerSceneGLES3::geometry_instance_free(GeometryInstance *p_geometry_i geometry_instance_alloc.free(ginstance); } -void RasterizerSceneGLES3::_geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance) { - GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); - if (ginstance->dirty_list_element.in_list()) { +void RasterizerSceneGLES3::GeometryInstanceGLES3::_mark_dirty() { + if (dirty_list_element.in_list()) { return; } //clear surface caches - GeometryInstanceSurface *surf = ginstance->surface_caches; + GeometryInstanceSurface *surf = surface_caches; while (surf) { GeometryInstanceSurface *next = surf->next; - geometry_instance_surface_alloc.free(surf); + RasterizerSceneGLES3::get_singleton()->geometry_instance_surface_alloc.free(surf); surf = next; } - ginstance->surface_caches = nullptr; + surface_caches = nullptr; + + RasterizerSceneGLES3::get_singleton()->geometry_instance_dirty_list.add(&dirty_list_element); +} + +void RasterizerSceneGLES3::GeometryInstanceGLES3::set_use_lightmap(RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) { +} - geometry_instance_dirty_list.add(&ginstance->dirty_list_element); +void RasterizerSceneGLES3::GeometryInstanceGLES3::set_lightmap_capture(const Color *p_sh9) { } void RasterizerSceneGLES3::_update_dirty_geometry_instances() { @@ -285,16 +134,16 @@ void RasterizerSceneGLES3::_update_dirty_geometry_instances() { } } -void RasterizerSceneGLES3::_geometry_instance_dependency_changed(RendererStorage::DependencyChangedNotification p_notification, RendererStorage::DependencyTracker *p_tracker) { +void RasterizerSceneGLES3::_geometry_instance_dependency_changed(Dependency::DependencyChangedNotification p_notification, DependencyTracker *p_tracker) { switch (p_notification) { - case RendererStorage::DEPENDENCY_CHANGED_MATERIAL: - case RendererStorage::DEPENDENCY_CHANGED_MESH: - case RendererStorage::DEPENDENCY_CHANGED_PARTICLES: - case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH: - case RendererStorage::DEPENDENCY_CHANGED_SKELETON_DATA: { - static_cast<RasterizerSceneGLES3 *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata)); + case Dependency::DEPENDENCY_CHANGED_MATERIAL: + case Dependency::DEPENDENCY_CHANGED_MESH: + case Dependency::DEPENDENCY_CHANGED_PARTICLES: + case Dependency::DEPENDENCY_CHANGED_MULTIMESH: + case Dependency::DEPENDENCY_CHANGED_SKELETON_DATA: { + static_cast<RenderGeometryInstance *>(p_tracker->userdata)->_mark_dirty(); } break; - case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: { + case Dependency::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: { GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_tracker->userdata); if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) { ginstance->instance_count = GLES3::MeshStorage::get_singleton()->multimesh_get_instances_to_draw(ginstance->data->base); @@ -306,8 +155,8 @@ void RasterizerSceneGLES3::_geometry_instance_dependency_changed(RendererStorage } } -void RasterizerSceneGLES3::_geometry_instance_dependency_deleted(const RID &p_dependency, RendererStorage::DependencyTracker *p_tracker) { - static_cast<RasterizerSceneGLES3 *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata)); +void RasterizerSceneGLES3::_geometry_instance_dependency_deleted(const RID &p_dependency, DependencyTracker *p_tracker) { + static_cast<RenderGeometryInstance *>(p_tracker->userdata)->_mark_dirty(); } void RasterizerSceneGLES3::_geometry_instance_add_surface_with_material(GeometryInstanceGLES3 *ginstance, uint32_t p_surface, GLES3::SceneMaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh) { @@ -376,7 +225,7 @@ void RasterizerSceneGLES3::_geometry_instance_add_surface_with_material(Geometry sdcache->surface_index = p_surface; if (ginstance->data->dirty_dependencies) { - storage->base_update_dependency(p_mesh, &ginstance->data->dependency_tracker); + RSG::utilities->base_update_dependency(p_mesh, &ginstance->data->dependency_tracker); } //shadow @@ -464,7 +313,7 @@ void RasterizerSceneGLES3::_geometry_instance_add_surface(GeometryInstanceGLES3 } } -void RasterizerSceneGLES3::_geometry_instance_update(GeometryInstance *p_geometry_instance) { +void RasterizerSceneGLES3::_geometry_instance_update(RenderGeometryInstance *p_geometry_instance) { GLES3::MeshStorage *mesh_storage = GLES3::MeshStorage::get_singleton(); GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance); @@ -647,8 +496,7 @@ void RasterizerSceneGLES3::_update_dirty_skys() { while (sky) { if (sky->radiance == 0) { - sky->mipmap_count = Image::get_image_required_mipmaps(sky->radiance_size, sky->radiance_size, Image::FORMAT_RGBA8) + 1; - + sky->mipmap_count = Image::get_image_required_mipmaps(sky->radiance_size, sky->radiance_size, Image::FORMAT_RGBA8) - 2; // Left uninitialized, will attach a texture at render time glGenFramebuffers(1, &sky->radiance_framebuffer); @@ -712,13 +560,13 @@ void RasterizerSceneGLES3::_update_dirty_skys() { dirty_sky_list = nullptr; } -void RasterizerSceneGLES3::_setup_sky(Environment *p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const CameraMatrix &p_projection, const Transform3D &p_transform, const Size2i p_screen_size) { +void RasterizerSceneGLES3::_setup_sky(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size) { GLES3::LightStorage *light_storage = GLES3::LightStorage::get_singleton(); GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton(); - ERR_FAIL_COND(!p_env); + ERR_FAIL_COND(p_env.is_null()); GLES3::SkyMaterialData *material = nullptr; - Sky *sky = sky_owner.get_or_null(p_env->sky); + Sky *sky = sky_owner.get_or_null(environment_get_sky(p_env)); RID sky_material; @@ -858,17 +706,17 @@ void RasterizerSceneGLES3::_setup_sky(Environment *p_env, RID p_render_buffers, } } -void RasterizerSceneGLES3::_draw_sky(Environment *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform) { +void RasterizerSceneGLES3::_draw_sky(RID p_env, const Projection &p_projection, const Transform3D &p_transform) { GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton(); - ERR_FAIL_COND(!p_env); + ERR_FAIL_COND(p_env.is_null()); - Sky *sky = sky_owner.get_or_null(p_env->sky); + Sky *sky = sky_owner.get_or_null(environment_get_sky(p_env)); ERR_FAIL_COND(!sky); GLES3::SkyMaterialData *material_data = nullptr; RID sky_material; - RS::EnvironmentBG background = p_env->background; + RS::EnvironmentBG background = environment_get_background(p_env); if (sky) { ERR_FAIL_COND(!sky); @@ -898,18 +746,18 @@ void RasterizerSceneGLES3::_draw_sky(Environment *p_env, const CameraMatrix &p_p ERR_FAIL_COND(!shader_data); // Camera - CameraMatrix camera; + Projection camera; - if (p_env->sky_custom_fov) { + if (environment_get_sky_custom_fov(p_env)) { float near_plane = p_projection.get_z_near(); float far_plane = p_projection.get_z_far(); float aspect = p_projection.get_aspect(); - camera.set_perspective(p_env->sky_custom_fov, aspect, near_plane, far_plane); + camera.set_perspective(environment_get_sky_custom_fov(p_env), aspect, near_plane, far_plane); } else { camera = p_projection; } - Basis sky_transform = p_env->sky_orientation; + Basis sky_transform = environment_get_sky_orientation(p_env); sky_transform.invert(); sky_transform = p_transform.basis * sky_transform; @@ -923,17 +771,17 @@ void RasterizerSceneGLES3::_draw_sky(Environment *p_env, const CameraMatrix &p_p glDrawArrays(GL_TRIANGLES, 0, 3); } -void RasterizerSceneGLES3::_update_sky_radiance(Environment *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform) { +void RasterizerSceneGLES3::_update_sky_radiance(RID p_env, const Projection &p_projection, const Transform3D &p_transform) { GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton(); - ERR_FAIL_COND(!p_env); + ERR_FAIL_COND(p_env.is_null()); - Sky *sky = sky_owner.get_or_null(p_env->sky); + Sky *sky = sky_owner.get_or_null(environment_get_sky(p_env)); ERR_FAIL_COND(!sky); GLES3::SkyMaterialData *material_data = nullptr; RID sky_material; - RS::EnvironmentBG background = p_env->background; + RS::EnvironmentBG background = environment_get_background(p_env); if (sky) { ERR_FAIL_COND(!sky); @@ -987,7 +835,7 @@ void RasterizerSceneGLES3::_update_sky_radiance(Environment *p_env, const Camera int max_processing_layer = sky->mipmap_count; // Update radiance cubemap - if (sky->reflection_dirty && (sky->processing_layer >= max_processing_layer || update_single_frame)) { + if (sky->reflection_dirty && (sky->processing_layer > max_processing_layer || update_single_frame)) { static const Vector3 view_normals[6] = { Vector3(+1, 0, 0), Vector3(-1, 0, 0), @@ -1005,9 +853,9 @@ void RasterizerSceneGLES3::_update_sky_radiance(Environment *p_env, const Camera Vector3(0, -1, 0) }; - CameraMatrix cm; + Projection cm; cm.set_perspective(90, 1, 0.01, 10.0); - CameraMatrix correction; + Projection correction; correction.set_depth_correction(true); cm = correction * cm; @@ -1031,7 +879,7 @@ void RasterizerSceneGLES3::_update_sky_radiance(Environment *p_env, const Camera } if (update_single_frame) { - for (int i = 0; i < max_processing_layer; i++) { + for (int i = 0; i <= max_processing_layer; i++) { _filter_sky_radiance(sky, i); } } else { @@ -1041,13 +889,52 @@ void RasterizerSceneGLES3::_update_sky_radiance(Environment *p_env, const Camera sky->reflection_dirty = false; } else { - if (sky_mode == RS::SKY_MODE_INCREMENTAL && sky->processing_layer < max_processing_layer) { + if (sky_mode == RS::SKY_MODE_INCREMENTAL && sky->processing_layer <= max_processing_layer) { _filter_sky_radiance(sky, sky->processing_layer); sky->processing_layer++; } } } +// Helper functions for IBL filtering + +Vector3 importance_sample_GGX(Vector2 xi, float roughness4) { + // Compute distribution direction + float phi = 2.0 * Math_PI * xi.x; + float cos_theta = sqrt((1.0 - xi.y) / (1.0 + (roughness4 - 1.0) * xi.y)); + float sin_theta = sqrt(1.0 - cos_theta * cos_theta); + + // Convert to spherical direction + Vector3 half_vector; + half_vector.x = sin_theta * cos(phi); + half_vector.y = sin_theta * sin(phi); + half_vector.z = cos_theta; + + return half_vector; +} + +float distribution_GGX(float NdotH, float roughness4) { + float NdotH2 = NdotH * NdotH; + float denom = (NdotH2 * (roughness4 - 1.0) + 1.0); + denom = Math_PI * denom * denom; + + return roughness4 / denom; +} + +float radical_inverse_vdC(uint32_t bits) { + bits = (bits << 16) | (bits >> 16); + bits = ((bits & 0x55555555) << 1) | ((bits & 0xAAAAAAAA) >> 1); + bits = ((bits & 0x33333333) << 2) | ((bits & 0xCCCCCCCC) >> 2); + bits = ((bits & 0x0F0F0F0F) << 4) | ((bits & 0xF0F0F0F0) >> 4); + bits = ((bits & 0x00FF00FF) << 8) | ((bits & 0xFF00FF00) >> 8); + + return float(bits) * 2.3283064365386963e-10; +} + +Vector2 hammersley(uint32_t i, uint32_t N) { + return Vector2(float(i) / float(N), radical_inverse_vdC(i)); +} + void RasterizerSceneGLES3::_filter_sky_radiance(Sky *p_sky, int p_base_layer) { GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton(); @@ -1059,21 +946,60 @@ void RasterizerSceneGLES3::_filter_sky_radiance(Sky *p_sky, int p_base_layer) { if (p_base_layer == 0) { glGenerateMipmap(GL_TEXTURE_CUBE_MAP); + // Copy over base layer without filtering. mode = CubemapFilterShaderGLES3::MODE_COPY; - - //Copy over base layer } - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, sky_globals.radical_inverse_vdc_cache_tex); int size = p_sky->radiance_size >> p_base_layer; glViewport(0, 0, size, size); glBindVertexArray(sky_globals.screen_triangle_array); material_storage->shaders.cubemap_filter_shader.version_bind_shader(scene_globals.cubemap_filter_shader_version, mode); - material_storage->shaders.cubemap_filter_shader.version_set_uniform(CubemapFilterShaderGLES3::SAMPLE_COUNT, sky_globals.ggx_samples, scene_globals.cubemap_filter_shader_version, mode); - material_storage->shaders.cubemap_filter_shader.version_set_uniform(CubemapFilterShaderGLES3::ROUGHNESS, float(p_base_layer) / (p_sky->mipmap_count - 1.0), scene_globals.cubemap_filter_shader_version, mode); - material_storage->shaders.cubemap_filter_shader.version_set_uniform(CubemapFilterShaderGLES3::FACE_SIZE, float(size), scene_globals.cubemap_filter_shader_version, mode); + + if (p_base_layer > 0) { + const uint32_t sample_counts[4] = { 1, sky_globals.ggx_samples / 4, sky_globals.ggx_samples / 2, sky_globals.ggx_samples }; + uint32_t sample_count = sample_counts[MIN(3, p_base_layer)]; + + float roughness = float(p_base_layer) / (p_sky->mipmap_count); + float roughness4 = roughness * roughness; + roughness4 *= roughness4; + + float solid_angle_texel = 4.0 * Math_PI / float(6 * size * size); + + LocalVector<float> sample_directions; + sample_directions.resize(4 * sample_count); + + uint32_t index = 0; + float weight = 0.0; + for (uint32_t i = 0; i < sample_count; i++) { + Vector2 xi = hammersley(i, sample_count); + Vector3 dir = importance_sample_GGX(xi, roughness4); + Vector3 light_vec = (2.0 * dir.z * dir - Vector3(0.0, 0.0, 1.0)); + + if (light_vec.z < 0.0) { + continue; + } + + sample_directions[index * 4] = light_vec.x; + sample_directions[index * 4 + 1] = light_vec.y; + sample_directions[index * 4 + 2] = light_vec.z; + + float D = distribution_GGX(dir.z, roughness4); + float pdf = D * dir.z / (4.0 * dir.z) + 0.0001; + + float solid_angle_sample = 1.0 / (float(sample_count) * pdf + 0.0001); + + float mip_level = MAX(0.5 * log2(solid_angle_sample / solid_angle_texel) + float(MAX(1, p_base_layer - 3)), 1.0); + + sample_directions[index * 4 + 3] = mip_level; + weight += light_vec.z; + index++; + } + + glUniform4fv(material_storage->shaders.cubemap_filter_shader.version_get_uniform(CubemapFilterShaderGLES3::SAMPLE_DIRECTIONS_MIP, scene_globals.cubemap_filter_shader_version, mode), sample_count, sample_directions.ptr()); + material_storage->shaders.cubemap_filter_shader.version_set_uniform(CubemapFilterShaderGLES3::WEIGHT, weight, scene_globals.cubemap_filter_shader_version, mode); + material_storage->shaders.cubemap_filter_shader.version_set_uniform(CubemapFilterShaderGLES3::SAMPLE_COUNT, index, scene_globals.cubemap_filter_shader_version, mode); + } for (int i = 0; i < 6; i++) { glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, p_sky->radiance, p_base_layer); @@ -1096,84 +1022,6 @@ Ref<Image> RasterizerSceneGLES3::sky_bake_panorama(RID p_sky, float p_energy, bo /* ENVIRONMENT API */ -RID RasterizerSceneGLES3::environment_allocate() { - return environment_owner.allocate_rid(); -} - -void RasterizerSceneGLES3::environment_initialize(RID p_rid) { - environment_owner.initialize_rid(p_rid); -} - -void RasterizerSceneGLES3::environment_set_background(RID p_env, RS::EnvironmentBG p_bg) { - Environment *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND(!env); - env->background = p_bg; -} - -void RasterizerSceneGLES3::environment_set_sky(RID p_env, RID p_sky) { - Environment *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND(!env); - env->sky = p_sky; -} - -void RasterizerSceneGLES3::environment_set_sky_custom_fov(RID p_env, float p_scale) { - Environment *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND(!env); - env->sky_custom_fov = p_scale; -} - -void RasterizerSceneGLES3::environment_set_sky_orientation(RID p_env, const Basis &p_orientation) { - Environment *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND(!env); - env->sky_orientation = p_orientation; -} - -void RasterizerSceneGLES3::environment_set_bg_color(RID p_env, const Color &p_color) { - Environment *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND(!env); - env->bg_color = p_color; -} - -void RasterizerSceneGLES3::environment_set_bg_energy(RID p_env, float p_energy) { - Environment *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND(!env); - env->bg_energy = p_energy; -} - -void RasterizerSceneGLES3::environment_set_canvas_max_layer(RID p_env, int p_max_layer) { - Environment *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND(!env); - env->canvas_max_layer = p_max_layer; -} - -void RasterizerSceneGLES3::environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient, float p_energy, float p_sky_contribution, RS::EnvironmentReflectionSource p_reflection_source) { - Environment *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND(!env); - env->ambient_light = p_color; - env->ambient_source = p_ambient; - env->ambient_light_energy = p_energy; - env->ambient_sky_contribution = p_sky_contribution; - env->reflection_source = p_reflection_source; -} - -void RasterizerSceneGLES3::environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) { - Environment *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND(!env); - ERR_FAIL_COND_MSG(p_levels.size() != 7, "Size of array of glow levels must be 7"); - env->glow_enabled = p_enable; - env->glow_levels = p_levels; - env->glow_intensity = p_intensity; - env->glow_strength = p_strength; - env->glow_mix = p_mix; - env->glow_bloom = p_bloom_threshold; - env->glow_blend_mode = p_blend_mode; - env->glow_hdr_bleed_threshold = p_hdr_bleed_threshold; - env->glow_hdr_bleed_scale = p_hdr_bleed_scale; - env->glow_hdr_luminance_cap = p_hdr_luminance_cap; - env->glow_map_strength = p_glow_map_strength; - env->glow_map = p_glow_map; -} - void RasterizerSceneGLES3::environment_glow_set_use_bicubic_upscale(bool p_enable) { glow_bicubic_upscale = p_enable; } @@ -1182,35 +1030,15 @@ void RasterizerSceneGLES3::environment_glow_set_use_high_quality(bool p_enable) glow_high_quality = p_enable; } -void RasterizerSceneGLES3::environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) { - Environment *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND(!env); - env->ssr_enabled = p_enable; - env->ssr_max_steps = p_max_steps; - env->ssr_fade_in = p_fade_int; - env->ssr_fade_out = p_fade_out; - env->ssr_depth_tolerance = p_depth_tolerance; -} - void RasterizerSceneGLES3::environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) { } -void RasterizerSceneGLES3::environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) { - Environment *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND(!env); -} - void RasterizerSceneGLES3::environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) { } -void RasterizerSceneGLES3::environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection) { -} void RasterizerSceneGLES3::environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) { } -void RasterizerSceneGLES3::environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) { -} - void RasterizerSceneGLES3::environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) { } @@ -1220,49 +1048,6 @@ void RasterizerSceneGLES3::environment_set_sdfgi_frames_to_converge(RS::Environm void RasterizerSceneGLES3::environment_set_sdfgi_frames_to_update_light(RS::EnvironmentSDFGIFramesToUpdateLight p_update) { } -void RasterizerSceneGLES3::environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) { - Environment *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND(!env); - env->exposure = p_exposure; - env->tone_mapper = p_tone_mapper; - if (!env->auto_exposure && p_auto_exposure) { - env->auto_exposure_version = ++auto_exposure_counter; - } - env->auto_exposure = p_auto_exposure; - env->white = p_white; - env->min_luminance = p_min_luminance; - env->max_luminance = p_max_luminance; - env->auto_exp_speed = p_auto_exp_speed; - env->auto_exp_scale = p_auto_exp_scale; -} - -void RasterizerSceneGLES3::environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) { - Environment *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND(!env); - env->adjustments_enabled = p_enable; - env->adjustments_brightness = p_brightness; - env->adjustments_contrast = p_contrast; - env->adjustments_saturation = p_saturation; - env->use_1d_color_correction = p_use_1d_color_correction; - env->color_correction = p_color_correction; -} - -void RasterizerSceneGLES3::environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) { - Environment *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND(!env); - env->fog_enabled = p_enable; - env->fog_light_color = p_light_color; - env->fog_light_energy = p_light_energy; - env->fog_sun_scatter = p_sun_scatter; - env->fog_density = p_density; - env->fog_height = p_height; - env->fog_height_density = p_height_density; - env->fog_aerial_perspective = p_aerial_perspective; -} - -void RasterizerSceneGLES3::environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) { -} - void RasterizerSceneGLES3::environment_set_volumetric_fog_volume_size(int p_size, int p_depth) { } @@ -1270,27 +1055,9 @@ void RasterizerSceneGLES3::environment_set_volumetric_fog_filter_active(bool p_e } Ref<Image> RasterizerSceneGLES3::environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) { - Environment *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND_V(!env, Ref<Image>()); return Ref<Image>(); } -bool RasterizerSceneGLES3::is_environment(RID p_env) const { - return environment_owner.owns(p_env); -} - -RS::EnvironmentBG RasterizerSceneGLES3::environment_get_background(RID p_env) const { - Environment *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND_V(!env, RS::ENV_BG_MAX); - return env->background; -} - -int RasterizerSceneGLES3::environment_get_canvas_max_layer(RID p_env) const { - Environment *env = environment_owner.get_or_null(p_env); - ERR_FAIL_COND_V(!env, 0); - return env->canvas_max_layer; -} - RID RasterizerSceneGLES3::camera_effects_allocate() { return RID(); } @@ -1310,10 +1077,10 @@ void RasterizerSceneGLES3::camera_effects_set_dof_blur(RID p_camera_effects, boo void RasterizerSceneGLES3::camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) { } -void RasterizerSceneGLES3::shadows_quality_set(RS::ShadowQuality p_quality) { +void RasterizerSceneGLES3::positional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) { } -void RasterizerSceneGLES3::directional_shadow_quality_set(RS::ShadowQuality p_quality) { +void RasterizerSceneGLES3::directional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) { } RID RasterizerSceneGLES3::light_instance_create(RID p_light) { @@ -1342,7 +1109,7 @@ void RasterizerSceneGLES3::light_instance_set_aabb(RID p_light_instance, const A light_instance->aabb = p_aabb; } -void RasterizerSceneGLES3::light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &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) { +void RasterizerSceneGLES3::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) { } void RasterizerSceneGLES3::light_instance_mark_visible(RID p_light_instance) { @@ -1428,7 +1195,7 @@ bool RasterizerSceneGLES3::voxel_gi_needs_update(RID p_probe) const { return false; } -void RasterizerSceneGLES3::voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects) { +void RasterizerSceneGLES3::voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects) { } void RasterizerSceneGLES3::voxel_gi_set_quality(RS::VoxelGIQuality) { @@ -1605,14 +1372,14 @@ void RasterizerSceneGLES3::_fill_render_list(RenderListType p_render_list, const // Needs to be called after _setup_lights so that directional_light_count is accurate. void RasterizerSceneGLES3::_setup_environment(const RenderDataGLES3 *p_render_data, bool p_no_fog, const Size2i &p_screen_size, bool p_flip_y, const Color &p_default_bg_color, bool p_pancake_shadows) { - CameraMatrix correction; + Projection correction; correction.set_depth_correction(p_flip_y); - CameraMatrix projection = correction * p_render_data->cam_projection; + Projection projection = correction * p_render_data->cam_projection; //store camera into ubo - RasterizerStorageGLES3::store_camera(projection, scene_state.ubo.projection_matrix); - RasterizerStorageGLES3::store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix); - RasterizerStorageGLES3::store_transform(p_render_data->cam_transform, scene_state.ubo.inv_view_matrix); - RasterizerStorageGLES3::store_transform(p_render_data->inv_cam_transform, scene_state.ubo.view_matrix); + GLES3::MaterialStorage::store_camera(projection, scene_state.ubo.projection_matrix); + GLES3::MaterialStorage::store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix); + GLES3::MaterialStorage::store_transform(p_render_data->cam_transform, scene_state.ubo.inv_view_matrix); + GLES3::MaterialStorage::store_transform(p_render_data->inv_cam_transform, scene_state.ubo.view_matrix); scene_state.ubo.directional_light_count = p_render_data->directional_light_count; @@ -1630,18 +1397,17 @@ void RasterizerSceneGLES3::_setup_environment(const RenderDataGLES3 *p_render_da scene_state.ubo.time = time; if (is_environment(p_render_data->environment)) { - Environment *env = environment_owner.get_or_null(p_render_data->environment); - RS::EnvironmentBG env_bg = env->background; - RS::EnvironmentAmbientSource ambient_src = env->ambient_source; + RS::EnvironmentBG env_bg = environment_get_background(p_render_data->environment); + RS::EnvironmentAmbientSource ambient_src = environment_get_ambient_source(p_render_data->environment); - float bg_energy = env->bg_energy; + float bg_energy = environment_get_bg_energy(p_render_data->environment); scene_state.ubo.ambient_light_color_energy[3] = bg_energy; - scene_state.ubo.ambient_color_sky_mix = env->ambient_sky_contribution; + scene_state.ubo.ambient_color_sky_mix = environment_get_ambient_sky_contribution(p_render_data->environment); //ambient if (ambient_src == RS::ENV_AMBIENT_SOURCE_BG && (env_bg == RS::ENV_BG_CLEAR_COLOR || env_bg == RS::ENV_BG_COLOR)) { - Color color = env_bg == RS::ENV_BG_CLEAR_COLOR ? p_default_bg_color : env->bg_color; + Color color = env_bg == RS::ENV_BG_CLEAR_COLOR ? p_default_bg_color : environment_get_bg_color(p_render_data->environment); color = color.srgb_to_linear(); scene_state.ubo.ambient_light_color_energy[0] = color.r * bg_energy; @@ -1650,42 +1416,42 @@ void RasterizerSceneGLES3::_setup_environment(const RenderDataGLES3 *p_render_da scene_state.ubo.use_ambient_light = true; scene_state.ubo.use_ambient_cubemap = false; } else { - float energy = env->ambient_light_energy; - Color color = env->ambient_light; + float energy = environment_get_ambient_light_energy(p_render_data->environment); + Color color = environment_get_ambient_light(p_render_data->environment); color = color.srgb_to_linear(); scene_state.ubo.ambient_light_color_energy[0] = color.r * energy; scene_state.ubo.ambient_light_color_energy[1] = color.g * energy; scene_state.ubo.ambient_light_color_energy[2] = color.b * energy; - Basis sky_transform = env->sky_orientation; + Basis sky_transform = environment_get_sky_orientation(p_render_data->environment); sky_transform = sky_transform.inverse() * p_render_data->cam_transform.basis; - RasterizerStorageGLES3::store_transform_3x3(sky_transform, scene_state.ubo.radiance_inverse_xform); + GLES3::MaterialStorage::store_transform_3x3(sky_transform, scene_state.ubo.radiance_inverse_xform); scene_state.ubo.use_ambient_cubemap = (ambient_src == RS::ENV_AMBIENT_SOURCE_BG && env_bg == RS::ENV_BG_SKY) || ambient_src == RS::ENV_AMBIENT_SOURCE_SKY; scene_state.ubo.use_ambient_light = scene_state.ubo.use_ambient_cubemap || ambient_src == RS::ENV_AMBIENT_SOURCE_COLOR; } //specular - RS::EnvironmentReflectionSource ref_src = env->reflection_source; + RS::EnvironmentReflectionSource ref_src = environment_get_reflection_source(p_render_data->environment); if ((ref_src == RS::ENV_REFLECTION_SOURCE_BG && env_bg == RS::ENV_BG_SKY) || ref_src == RS::ENV_REFLECTION_SOURCE_SKY) { scene_state.ubo.use_reflection_cubemap = true; } else { scene_state.ubo.use_reflection_cubemap = false; } - scene_state.ubo.fog_enabled = env->fog_enabled; - scene_state.ubo.fog_density = env->fog_density; - scene_state.ubo.fog_height = env->fog_height; - scene_state.ubo.fog_height_density = env->fog_height_density; - scene_state.ubo.fog_aerial_perspective = env->fog_aerial_perspective; + scene_state.ubo.fog_enabled = environment_get_fog_enabled(p_render_data->environment); + scene_state.ubo.fog_density = environment_get_fog_density(p_render_data->environment); + scene_state.ubo.fog_height = environment_get_fog_height(p_render_data->environment); + scene_state.ubo.fog_height_density = environment_get_fog_height_density(p_render_data->environment); + scene_state.ubo.fog_aerial_perspective = environment_get_fog_aerial_perspective(p_render_data->environment); - Color fog_color = env->fog_light_color.srgb_to_linear(); - float fog_energy = env->fog_light_energy; + Color fog_color = environment_get_fog_light_color(p_render_data->environment).srgb_to_linear(); + float fog_energy = environment_get_fog_light_energy(p_render_data->environment); scene_state.ubo.fog_light_color[0] = fog_color.r * fog_energy; scene_state.ubo.fog_light_color[1] = fog_color.g * fog_energy; scene_state.ubo.fog_light_color[2] = fog_color.b * fog_energy; - scene_state.ubo.fog_sun_scatter = env->fog_sun_scatter; + scene_state.ubo.fog_sun_scatter = environment_get_fog_sun_scatter(p_render_data->environment); } else { } @@ -1902,7 +1668,7 @@ void RasterizerSceneGLES3::_setup_lights(const RenderDataGLES3 *p_render_data, b glBindBuffer(GL_UNIFORM_BUFFER, 0); } -void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data, RendererScene::RenderInfo *r_render_info) { +void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data, RendererScene::RenderInfo *r_render_info) { GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton(); GLES3::Config *config = GLES3::Config::get_singleton(); RENDER_TIMESTAMP("Setup 3D Scene"); @@ -1967,18 +1733,16 @@ void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData * // Fill Light lists here ////////// - GLuint global_buffer = GLES3::MaterialStorage::get_singleton()->global_variables_get_uniform_buffer(); + GLuint global_buffer = GLES3::MaterialStorage::get_singleton()->global_shader_uniforms_get_uniform_buffer(); glBindBufferBase(GL_UNIFORM_BUFFER, SCENE_GLOBALS_UNIFORM_LOCATION, global_buffer); Color clear_color; if (p_render_buffers.is_valid()) { clear_color = texture_storage->render_target_get_clear_request_color(rb->render_target); } else { - clear_color = storage->get_default_clear_color(); + clear_color = texture_storage->get_default_clear_color(); } - Environment *env = environment_owner.get_or_null(p_environment); - bool fb_cleared = false; Size2i screen_size; @@ -1988,10 +1752,10 @@ void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData * bool use_wireframe = get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME; SceneState::TonemapUBO tonemap_ubo; - if (env) { - tonemap_ubo.exposure = env->exposure; - tonemap_ubo.white = env->white; - tonemap_ubo.tonemapper = int32_t(env->tone_mapper); + if (render_data.environment.is_valid()) { + tonemap_ubo.exposure = environment_get_exposure(render_data.environment); + tonemap_ubo.white = environment_get_white(render_data.environment); + tonemap_ubo.tonemapper = int32_t(environment_get_tone_mapper(render_data.environment)); } if (scene_state.tonemap_buffer == 0) { @@ -2014,25 +1778,25 @@ void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData * if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_OVERDRAW) { clear_color = Color(0, 0, 0, 1); //in overdraw mode, BG should always be black - } else if (env) { - RS::EnvironmentBG bg_mode = env->background; - float bg_energy = env->bg_energy; + } else if (render_data.environment.is_valid()) { + RS::EnvironmentBG bg_mode = environment_get_background(render_data.environment); + float bg_energy = environment_get_bg_energy(render_data.environment); switch (bg_mode) { case RS::ENV_BG_CLEAR_COLOR: { clear_color.r *= bg_energy; clear_color.g *= bg_energy; clear_color.b *= bg_energy; - if (env->fog_enabled) { + if (environment_get_fog_enabled(render_data.environment)) { draw_sky_fog_only = true; GLES3::MaterialStorage::get_singleton()->material_set_param(sky_globals.fog_material, "clear_color", Variant(clear_color)); } } break; case RS::ENV_BG_COLOR: { - clear_color = env->bg_color; + clear_color = environment_get_bg_color(render_data.environment); clear_color.r *= bg_energy; clear_color.g *= bg_energy; clear_color.b *= bg_energy; - if (env->fog_enabled) { + if (environment_get_fog_enabled(render_data.environment)) { draw_sky_fog_only = true; GLES3::MaterialStorage::get_singleton()->material_set_param(sky_globals.fog_material, "clear_color", Variant(clear_color)); } @@ -2052,20 +1816,20 @@ void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData * } } // setup sky if used for ambient, reflections, or background - if (draw_sky || draw_sky_fog_only || env->reflection_source == RS::ENV_REFLECTION_SOURCE_SKY || env->ambient_source == RS::ENV_AMBIENT_SOURCE_SKY) { + if (draw_sky || draw_sky_fog_only || environment_get_reflection_source(render_data.environment) == RS::ENV_REFLECTION_SOURCE_SKY || environment_get_ambient_source(render_data.environment) == RS::ENV_AMBIENT_SOURCE_SKY) { RENDER_TIMESTAMP("Setup Sky"); - CameraMatrix projection = render_data.cam_projection; + Projection projection = render_data.cam_projection; if (render_data.reflection_probe.is_valid()) { - CameraMatrix correction; + Projection correction; correction.set_depth_correction(true); projection = correction * render_data.cam_projection; } - _setup_sky(env, p_render_buffers, *render_data.lights, projection, render_data.cam_transform, screen_size); + _setup_sky(render_data.environment, p_render_buffers, *render_data.lights, projection, render_data.cam_transform, screen_size); - if (env->sky.is_valid()) { - if (env->reflection_source == RS::ENV_REFLECTION_SOURCE_SKY || env->ambient_source == RS::ENV_AMBIENT_SOURCE_SKY || (env->reflection_source == RS::ENV_REFLECTION_SOURCE_BG && env->background == RS::ENV_BG_SKY)) { - _update_sky_radiance(env, projection, render_data.cam_transform); + if (environment_get_sky(render_data.environment).is_valid()) { + if (environment_get_reflection_source(render_data.environment) == RS::ENV_REFLECTION_SOURCE_SKY || environment_get_ambient_source(render_data.environment) == RS::ENV_AMBIENT_SOURCE_SKY || (environment_get_reflection_source(render_data.environment) == RS::ENV_REFLECTION_SOURCE_BG && environment_get_background(render_data.environment) == RS::ENV_BG_SKY)) { + _update_sky_radiance(render_data.environment, projection, render_data.cam_transform); } } else { // do not try to draw sky if invalid @@ -2145,7 +1909,7 @@ void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData * spec_constant_base_flags |= 1 << SPEC_CONSTANT_DISABLE_DIRECTIONAL_LIGHTS; } - if (!env || (env && !env->fog_enabled)) { + if (render_data.environment.is_null() || (render_data.environment.is_valid() && !environment_get_fog_enabled(render_data.environment))) { spec_constant_base_flags |= 1 << SPEC_CONSTANT_DISABLE_FOG; } } @@ -2169,7 +1933,7 @@ void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData * scene_state.current_depth_draw = GLES3::SceneShaderData::DEPTH_DRAW_DISABLED; scene_state.cull_mode = GLES3::SceneShaderData::CULL_BACK; - _draw_sky(env, render_data.cam_projection, render_data.cam_transform); + _draw_sky(render_data.environment, render_data.cam_projection, render_data.cam_transform); } RENDER_TIMESTAMP("Render 3D Transparent Pass"); @@ -2218,11 +1982,10 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params, } if (p_pass_mode == PASS_MODE_COLOR || p_pass_mode == PASS_MODE_COLOR_TRANSPARENT) { - Environment *env = environment_owner.get_or_null(p_render_data->environment); glActiveTexture(GL_TEXTURE0 + config->max_texture_image_units - 2); GLuint texture_to_bind = texture_storage->get_texture(texture_storage->texture_gl_get_default(GLES3::DEFAULT_GL_TEXTURE_CUBEMAP_BLACK))->tex_id; - if (env) { - Sky *sky = sky_owner.get_or_null(env->sky); + if (p_render_data->environment.is_valid()) { + Sky *sky = sky_owner.get_or_null(environment_get_sky(p_render_data->environment)); if (sky && sky->radiance != 0) { texture_to_bind = sky->radiance; // base_spec_constant |= USE_RADIANCE_MAP; @@ -2487,10 +2250,10 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params, } } -void RasterizerSceneGLES3::render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { +void RasterizerSceneGLES3::render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { } -void RasterizerSceneGLES3::render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) { +void RasterizerSceneGLES3::render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<RenderGeometryInstance *> &p_instances) { } void RasterizerSceneGLES3::set_time(double p_time, double p_step) { @@ -2507,7 +2270,7 @@ RID RasterizerSceneGLES3::render_buffers_create() { return render_buffers_owner.make_rid(rb); } -void RasterizerSceneGLES3::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) { +void RasterizerSceneGLES3::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) { GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton(); RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); @@ -2621,8 +2384,8 @@ TypedArray<Image> RasterizerSceneGLES3::bake_render_uv2(RID p_base, const Vector } bool RasterizerSceneGLES3::free(RID p_rid) { - if (environment_owner.owns(p_rid)) { - environment_owner.free(p_rid); + if (is_environment(p_rid)) { + environment_free(p_rid); } else if (sky_owner.owns(p_rid)) { Sky *sky = sky_owner.get_or_null(p_rid); ERR_FAIL_COND_V(!sky, false); @@ -2657,12 +2420,10 @@ void RasterizerSceneGLES3::decals_set_filter(RS::DecalFilter p_filter) { void RasterizerSceneGLES3::light_projectors_set_filter(RS::LightProjectorFilter p_filter) { } -RasterizerSceneGLES3::RasterizerSceneGLES3(RasterizerStorageGLES3 *p_storage) { +RasterizerSceneGLES3::RasterizerSceneGLES3() { GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton(); GLES3::Config *config = GLES3::Config::get_singleton(); - storage = p_storage; - { // Setup Lights @@ -2704,7 +2465,7 @@ RasterizerSceneGLES3::RasterizerSceneGLES3(RasterizerStorageGLES3 *p_storage) { { String global_defines; - global_defines += "#define MAX_GLOBAL_VARIABLES 256\n"; // TODO: this is arbitrary for now + global_defines += "#define MAX_GLOBAL_SHADER_UNIFORMS 256\n"; // TODO: this is arbitrary for now global_defines += "\n#define MAX_LIGHT_DATA_STRUCTS " + itos(config->max_renderable_lights) + "\n"; global_defines += "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(MAX_DIRECTIONAL_LIGHTS) + "\n"; global_defines += "\n#define MAX_FORWARD_LIGHTS " + itos(config->max_lights_per_object) + "\n"; @@ -2743,13 +2504,17 @@ void fragment() { sky_globals.ggx_samples = GLOBAL_GET("rendering/reflections/sky_reflections/ggx_samples"); String global_defines; - global_defines += "#define MAX_GLOBAL_VARIABLES 256\n"; // TODO: this is arbitrary for now + global_defines += "#define MAX_GLOBAL_SHADER_UNIFORMS 256\n"; // TODO: this is arbitrary for now global_defines += "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(sky_globals.max_directional_lights) + "\n"; material_storage->shaders.sky_shader.initialize(global_defines); sky_globals.shader_default_version = material_storage->shaders.sky_shader.version_create(); material_storage->shaders.sky_shader.version_bind_shader(sky_globals.shader_default_version, SkyShaderGLES3::MODE_BACKGROUND); + } - material_storage->shaders.cubemap_filter_shader.initialize(); + { + String global_defines; + global_defines += "\n#define MAX_SAMPLE_COUNT " + itos(sky_globals.ggx_samples) + "\n"; + material_storage->shaders.cubemap_filter_shader.initialize(global_defines); scene_globals.cubemap_filter_shader_version = material_storage->shaders.cubemap_filter_shader.version_create(); material_storage->shaders.cubemap_filter_shader.version_bind_shader(scene_globals.cubemap_filter_shader_version, CubemapFilterShaderGLES3::MODE_DEFAULT); } @@ -2819,36 +2584,6 @@ void sky() { glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind } - // Radical inverse vdc cache texture used for cubemap filtering. - { - glGenTextures(1, &sky_globals.radical_inverse_vdc_cache_tex); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, sky_globals.radical_inverse_vdc_cache_tex); - - uint8_t radical_inverse[512]; - - for (uint32_t i = 0; i < 512; i++) { - uint32_t bits = i; - - bits = (bits << 16) | (bits >> 16); - bits = ((bits & 0x55555555) << 1) | ((bits & 0xAAAAAAAA) >> 1); - bits = ((bits & 0x33333333) << 2) | ((bits & 0xCCCCCCCC) >> 2); - bits = ((bits & 0x0F0F0F0F) << 4) | ((bits & 0xF0F0F0F0) >> 4); - bits = ((bits & 0x00FF00FF) << 8) | ((bits & 0xFF00FF00) >> 8); - - float value = float(bits) * 2.3283064365386963e-10; - radical_inverse[i] = uint8_t(CLAMP(value * 255.0, 0, 255)); - } - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 512, 1, 0, GL_RED, GL_UNSIGNED_BYTE, radical_inverse); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); //need this for proper sampling - - glBindTexture(GL_TEXTURE_2D, 0); - } #ifdef GLES_OVER_GL glEnable(_EXT_TEXTURE_CUBE_MAP_SEAMLESS); #endif @@ -2870,15 +2605,15 @@ RasterizerSceneGLES3::~RasterizerSceneGLES3() { // Scene Shader GLES3::MaterialStorage::get_singleton()->shaders.scene_shader.version_free(scene_globals.shader_default_version); GLES3::MaterialStorage::get_singleton()->shaders.cubemap_filter_shader.version_free(scene_globals.cubemap_filter_shader_version); - storage->free(scene_globals.default_material); - storage->free(scene_globals.default_shader); + RSG::material_storage->material_free(scene_globals.default_material); + RSG::material_storage->shader_free(scene_globals.default_shader); // Sky Shader GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_free(sky_globals.shader_default_version); - storage->free(sky_globals.default_material); - storage->free(sky_globals.default_shader); - storage->free(sky_globals.fog_material); - storage->free(sky_globals.fog_shader); + RSG::material_storage->material_free(sky_globals.default_material); + RSG::material_storage->shader_free(sky_globals.default_shader); + RSG::material_storage->material_free(sky_globals.fog_material); + RSG::material_storage->shader_free(sky_globals.fog_shader); glDeleteBuffers(1, &sky_globals.screen_triangle); glDeleteVertexArrays(1, &sky_globals.screen_triangle_array); glDeleteTextures(1, &sky_globals.radical_inverse_vdc_cache_tex); diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index 4757a3f161..e227b2df82 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -28,16 +28,15 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RASTERIZER_SCENE_OPENGL_H -#define RASTERIZER_SCENE_OPENGL_H +#ifndef RASTERIZER_SCENE_GLES3_H +#define RASTERIZER_SCENE_GLES3_H #ifdef GLES3_ENABLED -#include "core/math/camera_matrix.h" +#include "core/math/projection.h" #include "core/templates/paged_allocator.h" #include "core/templates/rid_owner.h" #include "core/templates/self_list.h" -#include "rasterizer_storage_gles3.h" #include "scene/resources/mesh.h" #include "servers/rendering/renderer_compositor.h" #include "servers/rendering/renderer_scene_render.h" @@ -45,6 +44,8 @@ #include "shader_gles3.h" #include "shaders/cubemap_filter.glsl.gen.h" #include "shaders/sky.glsl.gen.h" +#include "storage/material_storage.h" +#include "storage/utilities.h" enum RenderListType { RENDER_LIST_OPAQUE, //used for opaque objects @@ -95,18 +96,18 @@ struct RenderDataGLES3 { Transform3D cam_transform = Transform3D(); Transform3D inv_cam_transform = Transform3D(); - CameraMatrix cam_projection = CameraMatrix(); + Projection cam_projection = Projection(); bool cam_orthogonal = false; // For stereo rendering uint32_t view_count = 1; Vector3 view_eye_offset[RendererSceneRender::MAX_RENDER_VIEWS]; - CameraMatrix view_projection[RendererSceneRender::MAX_RENDER_VIEWS]; + Projection view_projection[RendererSceneRender::MAX_RENDER_VIEWS]; float z_near = 0.0; float z_far = 0.0; - const PagedArray<RendererSceneRender::GeometryInstance *> *instances = nullptr; + const PagedArray<RenderGeometryInstance *> *instances = nullptr; const PagedArray<RID> *lights = nullptr; const PagedArray<RID> *reflection_probes = nullptr; RID environment = RID(); @@ -125,7 +126,6 @@ struct RenderDataGLES3 { RendererScene::RenderInfo *render_info = nullptr; }; -class RasterizerStorageGLES3; class RasterizerCanvasGLES3; class RasterizerSceneGLES3 : public RendererSceneRender { @@ -210,7 +210,7 @@ private: mutable RID_Owner<LightInstance> light_instance_owner; - struct GeometryInstanceGLES3; + class GeometryInstanceGLES3; // Cached data for drawing surfaces struct GeometryInstanceSurface { @@ -265,33 +265,16 @@ private: GeometryInstanceGLES3 *owner = nullptr; }; - struct GeometryInstanceGLES3 : public GeometryInstance { + class GeometryInstanceGLES3 : public RenderGeometryInstanceBase { + public: //used during rendering - bool mirror = false; - bool non_uniform_scale = false; - float lod_bias = 0.0; - float lod_model_scale = 1.0; - AABB transformed_aabb; //needed for LOD - float depth = 0; - uint32_t flags_cache = 0; bool store_transform_cache = true; - int32_t shader_parameters_offset = -1; - uint32_t layer_mask = 1; int32_t instance_count = 0; - RID mesh_instance; bool can_sdfgi = false; bool using_projectors = false; bool using_softshadows = false; - bool fade_near = false; - float fade_near_begin = 0; - float fade_near_end = 0; - bool fade_far = false; - float fade_far_begin = 0; - float fade_far_end = 0; - float force_alpha = 1.0; - float parent_fade_alpha = 1.0; uint32_t omni_light_count = 0; LocalVector<RID> omni_lights; @@ -301,35 +284,22 @@ private: LocalVector<uint32_t> spot_light_gl_cache; //used during setup - uint32_t base_flags = 0; - Transform3D transform; GeometryInstanceSurface *surface_caches = nullptr; SelfList<GeometryInstanceGLES3> dirty_list_element; - struct Data { - //data used less often goes into regular heap - RID base; - RS::InstanceType base_type; - - RID skeleton; - Vector<RID> surface_materials; - RID material_override; - RID material_overlay; - AABB aabb; - - bool use_dynamic_gi = false; - bool use_baked_light = false; - bool cast_double_sided_shadows = false; - bool mirror = false; - bool dirty_dependencies = false; + GeometryInstanceGLES3() : + dirty_list_element(this) {} - RendererStorage::DependencyTracker dependency_tracker; - }; + virtual void _mark_dirty() 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; - Data *data = nullptr; + virtual void pair_light_instances(const RID *p_light_instances, uint32_t p_light_instance_count) override; + virtual void pair_reflection_probe_instances(const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) override {} + virtual void pair_decal_instances(const RID *p_decal_instances, uint32_t p_decal_instance_count) override {} + virtual void pair_voxel_gi_instances(const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) override {} - GeometryInstanceGLES3() : - dirty_list_element(this) {} + virtual void set_softshadow_projector_pairing(bool p_softshadow, bool p_projector) override {} }; enum { @@ -345,8 +315,8 @@ private: INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA = 1 << 15, }; - static void _geometry_instance_dependency_changed(RendererStorage::DependencyChangedNotification p_notification, RendererStorage::DependencyTracker *p_tracker); - static void _geometry_instance_dependency_deleted(const RID &p_dependency, RendererStorage::DependencyTracker *p_tracker); + static void _geometry_instance_dependency_changed(Dependency::DependencyChangedNotification p_notification, DependencyTracker *p_tracker); + static void _geometry_instance_dependency_deleted(const RID &p_dependency, DependencyTracker *p_tracker); SelfList<GeometryInstanceGLES3>::List geometry_instance_dirty_list; @@ -357,8 +327,7 @@ private: void _geometry_instance_add_surface_with_material(GeometryInstanceGLES3 *ginstance, uint32_t p_surface, GLES3::SceneMaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh); void _geometry_instance_add_surface_with_material_chain(GeometryInstanceGLES3 *ginstance, uint32_t p_surface, GLES3::SceneMaterialData *p_material, RID p_mat_src, RID p_mesh); void _geometry_instance_add_surface(GeometryInstanceGLES3 *ginstance, uint32_t p_surface, RID p_material, RID p_mesh); - void _geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance); - void _geometry_instance_update(GeometryInstance *p_geometry_instance); + void _geometry_instance_update(RenderGeometryInstance *p_geometry_instance); void _update_dirty_geometry_instances(); struct SceneState { @@ -570,88 +539,8 @@ protected: /* Environment */ - struct Environment { - // BG - RS::EnvironmentBG background = RS::ENV_BG_CLEAR_COLOR; - RID sky; - float sky_custom_fov = 0.0; - Basis sky_orientation; - Color bg_color; - float bg_energy = 1.0; - int canvas_max_layer = 0; - RS::EnvironmentAmbientSource ambient_source = RS::ENV_AMBIENT_SOURCE_BG; - Color ambient_light; - float ambient_light_energy = 1.0; - float ambient_sky_contribution = 1.0; - RS::EnvironmentReflectionSource reflection_source = RS::ENV_REFLECTION_SOURCE_BG; - Color ao_color; - - /// Tonemap - - RS::EnvironmentToneMapper tone_mapper; - float exposure = 1.0; - float white = 1.0; - bool auto_exposure = false; - float min_luminance = 0.2; - float max_luminance = 8.0; - float auto_exp_speed = 0.2; - float auto_exp_scale = 0.5; - uint64_t auto_exposure_version = 0; - - // Fog - bool fog_enabled = false; - Color fog_light_color = Color(0.5, 0.6, 0.7); - float fog_light_energy = 1.0; - float fog_sun_scatter = 0.0; - float fog_density = 0.001; - float fog_height = 0.0; - float fog_height_density = 0.0; //can be negative to invert effect - float fog_aerial_perspective = 0.0; - - /// Glow - bool glow_enabled = false; - Vector<float> glow_levels; - float glow_intensity = 0.8; - float glow_strength = 1.0; - float glow_bloom = 0.0; - float glow_mix = 0.01; - RS::EnvironmentGlowBlendMode glow_blend_mode = RS::ENV_GLOW_BLEND_MODE_SOFTLIGHT; - float glow_hdr_bleed_threshold = 1.0; - float glow_hdr_luminance_cap = 12.0; - float glow_hdr_bleed_scale = 2.0; - float glow_map_strength = 1.0; - RID glow_map = RID(); - - /// SSAO - bool ssao_enabled = false; - float ssao_radius = 1.0; - float ssao_intensity = 2.0; - float ssao_power = 1.5; - float ssao_detail = 0.5; - float ssao_horizon = 0.06; - float ssao_sharpness = 0.98; - float ssao_direct_light_affect = 0.0; - float ssao_ao_channel_affect = 0.0; - - /// SSR - bool ssr_enabled = false; - int ssr_max_steps = 64; - float ssr_fade_in = 0.15; - float ssr_fade_out = 2.0; - float ssr_depth_tolerance = 0.2; - - /// Adjustments - bool adjustments_enabled = false; - float adjustments_brightness = 1.0f; - float adjustments_contrast = 1.0f; - float adjustments_saturation = 1.0f; - bool use_1d_color_correction = false; - RID color_correction = RID(); - }; - RS::EnvironmentSSAOQuality ssao_quality = RS::ENV_SSAO_QUALITY_MEDIUM; bool ssao_half_size = false; - bool ssao_using_half_size = false; float ssao_adaptive_target = 0.5; int ssao_blur_passes = 2; float ssao_fadeout_from = 50.0; @@ -661,10 +550,6 @@ protected: bool glow_high_quality = false; RS::EnvironmentSSRRoughnessQuality ssr_roughness_quality = RS::ENV_SSR_ROUGHNESS_QUALITY_LOW; - static uint64_t auto_exposure_counter; - - mutable RID_Owner<Environment, true> environment_owner; - /* Sky */ struct SkyGlobals { @@ -730,45 +615,23 @@ protected: Sky *dirty_sky_list = nullptr; mutable RID_Owner<Sky, true> sky_owner; - void _setup_sky(Environment *p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const CameraMatrix &p_projection, const Transform3D &p_transform, const Size2i p_screen_size); + void _setup_sky(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size); void _invalidate_sky(Sky *p_sky); void _update_dirty_skys(); - void _update_sky_radiance(Environment *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform); + void _update_sky_radiance(RID p_env, const Projection &p_projection, const Transform3D &p_transform); void _filter_sky_radiance(Sky *p_sky, int p_base_layer); - void _draw_sky(Environment *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform); + void _draw_sky(RID p_env, const Projection &p_projection, const Transform3D &p_transform); void _free_sky_data(Sky *p_sky); public: - RasterizerStorageGLES3 *storage; + static RasterizerSceneGLES3 *get_singleton() { return singleton; } + RasterizerCanvasGLES3 *canvas; - GeometryInstance *geometry_instance_create(RID p_base) override; - void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) override; - void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) override; - void geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_overlay) override; - void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_material) override; - void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) override; - void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabbb) override; - void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) override; - void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) override; - void geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) override; - void geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) override; - void geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) override; - void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) override; - void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) override; - void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override; - void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) override; - void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) override; - void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) override; + RenderGeometryInstance *geometry_instance_create(RID p_base) override; + void geometry_instance_free(RenderGeometryInstance *p_geometry_instance) override; uint32_t geometry_instance_get_pair_mask() override; - void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) override; - void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) override; - void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) override; - void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) override; - void geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) override; - - void geometry_instance_free(GeometryInstance *p_geometry_instance) override; /* SHADOW ATLAS API */ @@ -805,49 +668,24 @@ public: /* ENVIRONMENT API */ - RID environment_allocate() override; - void environment_initialize(RID p_rid) override; - void environment_set_background(RID p_env, RS::EnvironmentBG p_bg) override; - void environment_set_sky(RID p_env, RID p_sky) override; - void environment_set_sky_custom_fov(RID p_env, float p_scale) override; - void environment_set_sky_orientation(RID p_env, const Basis &p_orientation) override; - void environment_set_bg_color(RID p_env, const Color &p_color) override; - void environment_set_bg_energy(RID p_env, float p_energy) override; - void environment_set_canvas_max_layer(RID p_env, int p_max_layer) override; - void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG) override; - - void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) override; void environment_glow_set_use_bicubic_upscale(bool p_enable) override; void environment_glow_set_use_high_quality(bool p_enable) override; - void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) override; void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) override; - void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) override; + void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override; - void environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection) override; - void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override; - void environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) override; + void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override; void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) override; void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) override; void environment_set_sdfgi_frames_to_update_light(RS::EnvironmentSDFGIFramesToUpdateLight p_update) override; - void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) override; - - void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) override; - - void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) override; - void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) override; void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) override; void environment_set_volumetric_fog_filter_active(bool p_enable) override; Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) override; - bool is_environment(RID p_env) const override; - RS::EnvironmentBG environment_get_background(RID p_env) const override; - int environment_get_canvas_max_layer(RID p_env) const override; - RID camera_effects_allocate() override; void camera_effects_initialize(RID p_rid) override; void camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) override; @@ -856,13 +694,13 @@ public: void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) override; void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) override; - void shadows_quality_set(RS::ShadowQuality p_quality) override; - void directional_shadow_quality_set(RS::ShadowQuality p_quality) override; + void positional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) override; + void directional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) override; RID light_instance_create(RID p_light) override; void light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) override; void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) override; - void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) override; + void 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 = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) override; void light_instance_mark_visible(RID p_light_instance) override; _FORCE_INLINE_ RS::LightType light_instance_get_type(RID p_light_instance) { @@ -901,13 +739,13 @@ public: RID voxel_gi_instance_create(RID p_voxel_gi) override; void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) override; bool voxel_gi_needs_update(RID p_probe) const override; - void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects) override; + void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects) override; void voxel_gi_set_quality(RS::VoxelGIQuality) override; - void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) override; - void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; - void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) override; + void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) override; + void render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; + void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<RenderGeometryInstance *> &p_instances) override; void set_scene_pass(uint64_t p_pass) override { scene_pass = p_pass; @@ -924,7 +762,7 @@ public: } RID render_buffers_create() override; - void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override; + void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override; void gi_set_use_half_resolution(bool p_enable) override; void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_curve) override; @@ -942,11 +780,10 @@ public: void decals_set_filter(RS::DecalFilter p_filter) override; void light_projectors_set_filter(RS::LightProjectorFilter p_filter) override; - static RasterizerSceneGLES3 *get_singleton(); - RasterizerSceneGLES3(RasterizerStorageGLES3 *p_storage); + RasterizerSceneGLES3(); ~RasterizerSceneGLES3(); }; #endif // GLES3_ENABLED -#endif // RASTERIZER_SCENE_OPENGL_H +#endif // RASTERIZER_SCENE_GLES3_H diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp deleted file mode 100644 index 3b80d88666..0000000000 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ /dev/null @@ -1,569 +0,0 @@ -/*************************************************************************/ -/* rasterizer_storage_gles3.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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 "rasterizer_storage_gles3.h" - -#ifdef GLES3_ENABLED - -#include "core/config/project_settings.h" -#include "core/math/transform_3d.h" -// #include "rasterizer_canvas_gles3.h" -#include "rasterizer_scene_gles3.h" -#include "servers/rendering/shader_language.h" - -/* MISC */ - -void RasterizerStorageGLES3::base_update_dependency(RID p_base, DependencyTracker *p_instance) { - if (GLES3::MeshStorage::get_singleton()->owns_mesh(p_base)) { - GLES3::Mesh *mesh = GLES3::MeshStorage::get_singleton()->get_mesh(p_base); - p_instance->update_dependency(&mesh->dependency); - } else if (GLES3::MeshStorage::get_singleton()->owns_multimesh(p_base)) { - GLES3::MultiMesh *multimesh = GLES3::MeshStorage::get_singleton()->get_multimesh(p_base); - p_instance->update_dependency(&multimesh->dependency); - if (multimesh->mesh.is_valid()) { - base_update_dependency(multimesh->mesh, p_instance); - } - } else if (GLES3::LightStorage::get_singleton()->owns_light(p_base)) { - GLES3::Light *l = GLES3::LightStorage::get_singleton()->get_light(p_base); - p_instance->update_dependency(&l->dependency); - } -} - -Vector<uint8_t> RasterizerStorageGLES3::buffer_get_data(GLenum p_target, GLuint p_buffer, uint32_t p_buffer_size) { - Vector<uint8_t> ret; - ret.resize(p_buffer_size); - glBindBuffer(p_target, p_buffer); - -#if defined(__EMSCRIPTEN__) - { - uint8_t *w = ret.ptrw(); - glGetBufferSubData(p_target, 0, p_buffer_size, w); - } -#else - void *data = glMapBufferRange(p_target, 0, p_buffer_size, GL_MAP_READ_BIT); - ERR_FAIL_NULL_V(data, Vector<uint8_t>()); - { - uint8_t *w = ret.ptrw(); - memcpy(w, data, p_buffer_size); - } - glUnmapBuffer(p_target); -#endif - glBindBuffer(p_target, 0); - return ret; -} - -/* OCCLUDER */ - -void RasterizerStorageGLES3::occluder_set_mesh(RID p_occluder, const PackedVector3Array &p_vertices, const PackedInt32Array &p_indices) { -} - -/* FOG */ - -RID RasterizerStorageGLES3::fog_volume_allocate() { - return RID(); -} - -void RasterizerStorageGLES3::fog_volume_initialize(RID p_rid) { -} - -void RasterizerStorageGLES3::fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) { -} - -void RasterizerStorageGLES3::fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) { -} - -void RasterizerStorageGLES3::fog_volume_set_material(RID p_fog_volume, RID p_material) { -} - -AABB RasterizerStorageGLES3::fog_volume_get_aabb(RID p_fog_volume) const { - return AABB(); -} - -RS::FogVolumeShape RasterizerStorageGLES3::fog_volume_get_shape(RID p_fog_volume) const { - return RS::FOG_VOLUME_SHAPE_BOX; -} - -/* VISIBILITY NOTIFIER */ -RID RasterizerStorageGLES3::visibility_notifier_allocate() { - return RID(); -} - -void RasterizerStorageGLES3::visibility_notifier_initialize(RID p_notifier) { -} - -void RasterizerStorageGLES3::visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb) { -} - -void RasterizerStorageGLES3::visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable) { -} - -AABB RasterizerStorageGLES3::visibility_notifier_get_aabb(RID p_notifier) const { - return AABB(); -} - -void RasterizerStorageGLES3::visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) { -} - -/* CANVAS SHADOW */ - -RID RasterizerStorageGLES3::canvas_light_shadow_buffer_create(int p_width) { - CanvasLightShadow *cls = memnew(CanvasLightShadow); - - if (p_width > config->max_texture_size) { - p_width = config->max_texture_size; - } - - cls->size = p_width; - cls->height = 16; - - glActiveTexture(GL_TEXTURE0); - - glGenFramebuffers(1, &cls->fbo); - glBindFramebuffer(GL_FRAMEBUFFER, cls->fbo); - - glGenRenderbuffers(1, &cls->depth); - glBindRenderbuffer(GL_RENDERBUFFER, cls->depth); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, cls->size, cls->height); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, cls->depth); - - glGenTextures(1, &cls->distance); - glBindTexture(GL_TEXTURE_2D, cls->distance); - if (config->use_rgba_2d_shadows) { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, cls->size, cls->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - } else { - glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, cls->size, cls->height, 0, GL_RED, GL_FLOAT, nullptr); - } - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, cls->distance, 0); - - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - //printf("errnum: %x\n",status); - glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo); - - if (status != GL_FRAMEBUFFER_COMPLETE) { - memdelete(cls); - ERR_FAIL_COND_V(status != GL_FRAMEBUFFER_COMPLETE, RID()); - } - - return canvas_light_shadow_owner.make_rid(cls); -} - -/* LIGHT SHADOW MAPPING */ -/* - -RID RasterizerStorageGLES3::canvas_light_occluder_create() { - CanvasOccluder *co = memnew(CanvasOccluder); - co->index_id = 0; - co->vertex_id = 0; - co->len = 0; - - return canvas_occluder_owner.make_rid(co); -} - -void RasterizerStorageGLES3::canvas_light_occluder_set_polylines(RID p_occluder, const PoolVector<Vector2> &p_lines) { - CanvasOccluder *co = canvas_occluder_owner.get(p_occluder); - ERR_FAIL_COND(!co); - - co->lines = p_lines; - - if (p_lines.size() != co->len) { - if (co->index_id) { - glDeleteBuffers(1, &co->index_id); - } if (co->vertex_id) { - glDeleteBuffers(1, &co->vertex_id); - } - - co->index_id = 0; - co->vertex_id = 0; - co->len = 0; - } - - if (p_lines.size()) { - PoolVector<float> geometry; - PoolVector<uint16_t> indices; - int lc = p_lines.size(); - - geometry.resize(lc * 6); - indices.resize(lc * 3); - - PoolVector<float>::Write vw = geometry.write(); - PoolVector<uint16_t>::Write iw = indices.write(); - - PoolVector<Vector2>::Read lr = p_lines.read(); - - const int POLY_HEIGHT = 16384; - - for (int i = 0; i < lc / 2; i++) { - vw[i * 12 + 0] = lr[i * 2 + 0].x; - vw[i * 12 + 1] = lr[i * 2 + 0].y; - vw[i * 12 + 2] = POLY_HEIGHT; - - vw[i * 12 + 3] = lr[i * 2 + 1].x; - vw[i * 12 + 4] = lr[i * 2 + 1].y; - vw[i * 12 + 5] = POLY_HEIGHT; - - vw[i * 12 + 6] = lr[i * 2 + 1].x; - vw[i * 12 + 7] = lr[i * 2 + 1].y; - vw[i * 12 + 8] = -POLY_HEIGHT; - - vw[i * 12 + 9] = lr[i * 2 + 0].x; - vw[i * 12 + 10] = lr[i * 2 + 0].y; - vw[i * 12 + 11] = -POLY_HEIGHT; - - iw[i * 6 + 0] = i * 4 + 0; - iw[i * 6 + 1] = i * 4 + 1; - iw[i * 6 + 2] = i * 4 + 2; - - iw[i * 6 + 3] = i * 4 + 2; - iw[i * 6 + 4] = i * 4 + 3; - iw[i * 6 + 5] = i * 4 + 0; - } - - //if same buffer len is being set, just use BufferSubData to avoid a pipeline flush - - if (!co->vertex_id) { - glGenBuffers(1, &co->vertex_id); - glBindBuffer(GL_ARRAY_BUFFER, co->vertex_id); - glBufferData(GL_ARRAY_BUFFER, lc * 6 * sizeof(real_t), vw.ptr(), GL_STATIC_DRAW); - } else { - glBindBuffer(GL_ARRAY_BUFFER, co->vertex_id); - glBufferSubData(GL_ARRAY_BUFFER, 0, lc * 6 * sizeof(real_t), vw.ptr()); - } - - glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind - - if (!co->index_id) { - glGenBuffers(1, &co->index_id); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, co->index_id); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, lc * 3 * sizeof(uint16_t), iw.ptr(), GL_DYNAMIC_DRAW); - } else { - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, co->index_id); - glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, lc * 3 * sizeof(uint16_t), iw.ptr()); - } - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); //unbind - - co->len = lc; - } -} -*/ - -RS::InstanceType RasterizerStorageGLES3::get_base_type(RID p_rid) const { - if (GLES3::MeshStorage::get_singleton()->owns_mesh(p_rid)) { - return RS::INSTANCE_MESH; - } else if (GLES3::MeshStorage::get_singleton()->owns_multimesh(p_rid)) { - return RS::INSTANCE_MULTIMESH; - } else if (GLES3::LightStorage::get_singleton()->owns_light(p_rid)) { - return RS::INSTANCE_LIGHT; - } - return RS::INSTANCE_NONE; -} - -bool RasterizerStorageGLES3::free(RID p_rid) { - if (GLES3::TextureStorage::get_singleton()->owns_render_target(p_rid)) { - GLES3::TextureStorage::get_singleton()->render_target_free(p_rid); - return true; - } else if (GLES3::TextureStorage::get_singleton()->owns_texture(p_rid)) { - GLES3::TextureStorage::get_singleton()->texture_free(p_rid); - return true; - } else if (GLES3::TextureStorage::get_singleton()->owns_canvas_texture(p_rid)) { - GLES3::TextureStorage::get_singleton()->canvas_texture_free(p_rid); - return true; - } else if (GLES3::MaterialStorage::get_singleton()->owns_shader(p_rid)) { - GLES3::MaterialStorage::get_singleton()->shader_free(p_rid); - return true; - } else if (GLES3::MaterialStorage::get_singleton()->owns_material(p_rid)) { - GLES3::MaterialStorage::get_singleton()->material_free(p_rid); - return true; - } else if (GLES3::MeshStorage::get_singleton()->owns_mesh(p_rid)) { - GLES3::MeshStorage::get_singleton()->mesh_free(p_rid); - return true; - } else if (GLES3::MeshStorage::get_singleton()->owns_multimesh(p_rid)) { - GLES3::MeshStorage::get_singleton()->multimesh_free(p_rid); - return true; - } else if (GLES3::MeshStorage::get_singleton()->owns_mesh_instance(p_rid)) { - GLES3::MeshStorage::get_singleton()->mesh_instance_free(p_rid); - return true; - } else if (GLES3::LightStorage::get_singleton()->owns_light(p_rid)) { - GLES3::LightStorage::get_singleton()->light_free(p_rid); - return true; - } else { - return false; - } - /* - else if (reflection_probe_owner.owns(p_rid)) { - // delete the texture - ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_rid); - reflection_probe->instance_remove_deps(); - - reflection_probe_owner.free(p_rid); - memdelete(reflection_probe); - - return true; - } else if (lightmap_capture_data_owner.owns(p_rid)) { - // delete the texture - LightmapCapture *lightmap_capture = lightmap_capture_data_owner.get_or_null(p_rid); - lightmap_capture->instance_remove_deps(); - - lightmap_capture_data_owner.free(p_rid); - memdelete(lightmap_capture); - return true; - - } else if (canvas_occluder_owner.owns(p_rid)) { - CanvasOccluder *co = canvas_occluder_owner.get_or_null(p_rid); - if (co->index_id) { - glDeleteBuffers(1, &co->index_id); - } - if (co->vertex_id) { - glDeleteBuffers(1, &co->vertex_id); - } - - canvas_occluder_owner.free(p_rid); - memdelete(co); - - return true; - - } else if (canvas_light_shadow_owner.owns(p_rid)) { - CanvasLightShadow *cls = canvas_light_shadow_owner.get_or_null(p_rid); - glDeleteFramebuffers(1, &cls->fbo); - glDeleteRenderbuffers(1, &cls->depth); - glDeleteTextures(1, &cls->distance); - canvas_light_shadow_owner.free(p_rid); - memdelete(cls); - - return true; - */ -} - -bool RasterizerStorageGLES3::has_os_feature(const String &p_feature) const { - if (!config) { - return false; - } - - if (p_feature == "rgtc") { - return config->rgtc_supported; - } - - if (p_feature == "s3tc") { - return config->s3tc_supported; - } - - if (p_feature == "bptc") { - return config->bptc_supported; - } - - if (p_feature == "etc" || p_feature == "etc2") { - return config->etc2_supported; - } - - return false; -} - -//////////////////////////////////////////// - -void RasterizerStorageGLES3::set_debug_generate_wireframes(bool p_generate) { -} - -//void RasterizerStorageGLES3::render_info_begin_capture() { -// info.snap = info.render; -//} - -//void RasterizerStorageGLES3::render_info_end_capture() { -// info.snap.object_count = info.render.object_count - info.snap.object_count; -// info.snap.draw_call_count = info.render.draw_call_count - info.snap.draw_call_count; -// info.snap.material_switch_count = info.render.material_switch_count - info.snap.material_switch_count; -// info.snap.surface_switch_count = info.render.surface_switch_count - info.snap.surface_switch_count; -// info.snap.shader_rebind_count = info.render.shader_rebind_count - info.snap.shader_rebind_count; -// info.snap.vertices_count = info.render.vertices_count - info.snap.vertices_count; -// info.snap._2d_item_count = info.render._2d_item_count - info.snap._2d_item_count; -// info.snap._2d_draw_call_count = info.render._2d_draw_call_count - info.snap._2d_draw_call_count; -//} - -//int RasterizerStorageGLES3::get_captured_render_info(RS::RenderInfo p_info) { -// switch (p_info) { -// case RS::INFO_OBJECTS_IN_FRAME: { -// return info.snap.object_count; -// } break; -// case RS::INFO_VERTICES_IN_FRAME: { -// return info.snap.vertices_count; -// } break; -// case RS::INFO_MATERIAL_CHANGES_IN_FRAME: { -// return info.snap.material_switch_count; -// } break; -// case RS::INFO_SHADER_CHANGES_IN_FRAME: { -// return info.snap.shader_rebind_count; -// } break; -// case RS::INFO_SURFACE_CHANGES_IN_FRAME: { -// return info.snap.surface_switch_count; -// } break; -// case RS::INFO_DRAW_CALLS_IN_FRAME: { -// return info.snap.draw_call_count; -// } break; -// /* -// case RS::INFO_2D_ITEMS_IN_FRAME: { -// return info.snap._2d_item_count; -// } break; -// case RS::INFO_2D_DRAW_CALLS_IN_FRAME: { -// return info.snap._2d_draw_call_count; -// } break; -// */ -// default: { -// return get_render_info(p_info); -// } -// } -//} - -//int RasterizerStorageGLES3::get_render_info(RS::RenderInfo p_info) { -// switch (p_info) { -// case RS::INFO_OBJECTS_IN_FRAME: -// return info.render_final.object_count; -// case RS::INFO_VERTICES_IN_FRAME: -// return info.render_final.vertices_count; -// case RS::INFO_MATERIAL_CHANGES_IN_FRAME: -// return info.render_final.material_switch_count; -// case RS::INFO_SHADER_CHANGES_IN_FRAME: -// return info.render_final.shader_rebind_count; -// case RS::INFO_SURFACE_CHANGES_IN_FRAME: -// return info.render_final.surface_switch_count; -// case RS::INFO_DRAW_CALLS_IN_FRAME: -// return info.render_final.draw_call_count; -// /* -// case RS::INFO_2D_ITEMS_IN_FRAME: -// return info.render_final._2d_item_count; -// case RS::INFO_2D_DRAW_CALLS_IN_FRAME: -// return info.render_final._2d_draw_call_count; -//*/ -// case RS::INFO_USAGE_VIDEO_MEM_TOTAL: -// return 0; //no idea -// case RS::INFO_VIDEO_MEM_USED: -// return info.vertex_mem + info.texture_mem; -// case RS::INFO_TEXTURE_MEM_USED: -// return info.texture_mem; -// case RS::INFO_VERTEX_MEM_USED: -// return info.vertex_mem; -// default: -// return 0; //no idea either -// } -//} - -String RasterizerStorageGLES3::get_video_adapter_name() const { - return (const char *)glGetString(GL_RENDERER); -} - -String RasterizerStorageGLES3::get_video_adapter_vendor() const { - return (const char *)glGetString(GL_VENDOR); -} - -RenderingDevice::DeviceType RasterizerStorageGLES3::get_video_adapter_type() const { - return RenderingDevice::DeviceType::DEVICE_TYPE_OTHER; -} - -String RasterizerStorageGLES3::get_video_adapter_api_version() const { - return (const char *)glGetString(GL_VERSION); -} - -void RasterizerStorageGLES3::initialize() { - config = GLES3::Config::get_singleton(); - - // skeleton buffer - { - resources.skeleton_transform_buffer_size = 0; - glGenBuffers(1, &resources.skeleton_transform_buffer); - } - - // radical inverse vdc cache texture - // used for cubemap filtering - glGenTextures(1, &resources.radical_inverse_vdc_cache_tex); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, resources.radical_inverse_vdc_cache_tex); - /* - uint8_t radical_inverse[512]; - - for (uint32_t i = 0; i < 512; i++) { - uint32_t bits = i; - - bits = (bits << 16) | (bits >> 16); - bits = ((bits & 0x55555555) << 1) | ((bits & 0xAAAAAAAA) >> 1); - bits = ((bits & 0x33333333) << 2) | ((bits & 0xCCCCCCCC) >> 2); - bits = ((bits & 0x0F0F0F0F) << 4) | ((bits & 0xF0F0F0F0) >> 4); - bits = ((bits & 0x00FF00FF) << 8) | ((bits & 0xFF00FF00) >> 8); - - float value = float(bits) * 2.3283064365386963e-10; - radical_inverse[i] = uint8_t(CLAMP(value * 255.0, 0, 255)); - } - - //glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 512, 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, radical_inverse); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); //need this for proper sampling - */ - glBindTexture(GL_TEXTURE_2D, 0); - - { - glGenFramebuffers(1, &resources.mipmap_blur_fbo); - glGenTextures(1, &resources.mipmap_blur_color); - } - -#ifdef GLES_OVER_GL - glEnable(GL_PROGRAM_POINT_SIZE); -#endif -} - -void RasterizerStorageGLES3::finalize() { -} - -void RasterizerStorageGLES3::update_memory_info() { -} - -uint64_t RasterizerStorageGLES3::get_rendering_info(RS::RenderingInfo p_info) { - return 0; -} - -void RasterizerStorageGLES3::update_dirty_resources() { - GLES3::MaterialStorage::get_singleton()->_update_global_variables(); - GLES3::MaterialStorage::get_singleton()->_update_queued_materials(); - //GLES3::MeshStorage::get_singleton()->_update_dirty_skeletons(); - GLES3::MeshStorage::get_singleton()->_update_dirty_multimeshes(); -} - -RasterizerStorageGLES3::RasterizerStorageGLES3() { - initialize(); -} - -RasterizerStorageGLES3::~RasterizerStorageGLES3() { -} - -#endif // GLES3_ENABLED diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h deleted file mode 100644 index c42efbce19..0000000000 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ /dev/null @@ -1,266 +0,0 @@ -/*************************************************************************/ -/* rasterizer_storage_gles3.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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 RASTERIZER_STORAGE_OPENGL_H -#define RASTERIZER_STORAGE_OPENGL_H - -#ifdef GLES3_ENABLED - -#include "core/templates/local_vector.h" -#include "core/templates/rid_owner.h" -#include "core/templates/self_list.h" -#include "servers/rendering/renderer_compositor.h" -#include "servers/rendering/renderer_storage.h" -#include "servers/rendering/shader_compiler.h" -#include "servers/rendering/shader_language.h" -#include "storage/config.h" -#include "storage/light_storage.h" -#include "storage/material_storage.h" -#include "storage/mesh_storage.h" -#include "storage/texture_storage.h" - -// class RasterizerCanvasGLES3; -// class RasterizerSceneGLES3; - -class RasterizerStorageGLES3 : public RendererStorage { -public: - // RasterizerCanvasGLES3 *canvas; - // RasterizerSceneGLES3 *scene; - - GLES3::Config *config = nullptr; - - static _FORCE_INLINE_ void store_transform(const Transform3D &p_mtx, float *p_array) { - p_array[0] = p_mtx.basis.rows[0][0]; - p_array[1] = p_mtx.basis.rows[1][0]; - p_array[2] = p_mtx.basis.rows[2][0]; - p_array[3] = 0; - p_array[4] = p_mtx.basis.rows[0][1]; - p_array[5] = p_mtx.basis.rows[1][1]; - p_array[6] = p_mtx.basis.rows[2][1]; - p_array[7] = 0; - p_array[8] = p_mtx.basis.rows[0][2]; - p_array[9] = p_mtx.basis.rows[1][2]; - p_array[10] = p_mtx.basis.rows[2][2]; - p_array[11] = 0; - p_array[12] = p_mtx.origin.x; - p_array[13] = p_mtx.origin.y; - p_array[14] = p_mtx.origin.z; - p_array[15] = 1; - } - - static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_mtx, float *p_array) { - p_array[0] = p_mtx.rows[0][0]; - p_array[1] = p_mtx.rows[1][0]; - p_array[2] = p_mtx.rows[2][0]; - p_array[3] = 0; - p_array[4] = p_mtx.rows[0][1]; - p_array[5] = p_mtx.rows[1][1]; - p_array[6] = p_mtx.rows[2][1]; - p_array[7] = 0; - p_array[8] = p_mtx.rows[0][2]; - p_array[9] = p_mtx.rows[1][2]; - p_array[10] = p_mtx.rows[2][2]; - p_array[11] = 0; - } - - static _FORCE_INLINE_ void store_camera(const CameraMatrix &p_mtx, float *p_array) { - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { - p_array[i * 4 + j] = p_mtx.matrix[i][j]; - } - } - } - - // Buffer size is specified in bytes - static Vector<uint8_t> buffer_get_data(GLenum p_target, GLuint p_buffer, uint32_t p_buffer_size); - - struct Resources { - GLuint mipmap_blur_fbo; - GLuint mipmap_blur_color; - - GLuint radical_inverse_vdc_cache_tex; - bool use_rgba_2d_shadows; - - size_t skeleton_transform_buffer_size; - GLuint skeleton_transform_buffer; - LocalVector<float> skeleton_transform_cpu_buffer; - - } resources; - - struct Info { - uint64_t texture_mem = 0; - uint64_t vertex_mem = 0; - - struct Render { - uint32_t object_count; - uint32_t draw_call_count; - uint32_t material_switch_count; - uint32_t surface_switch_count; - uint32_t shader_rebind_count; - uint32_t vertices_count; - uint32_t _2d_item_count; - uint32_t _2d_draw_call_count; - - void reset() { - object_count = 0; - draw_call_count = 0; - material_switch_count = 0; - surface_switch_count = 0; - shader_rebind_count = 0; - vertices_count = 0; - _2d_item_count = 0; - _2d_draw_call_count = 0; - } - } render, render_final, snap; - - Info() { - render.reset(); - render_final.reset(); - } - - } info; - - ///////////////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////API//////////////////////////////////////////////////// - ///////////////////////////////////////////////////////////////////////////////////////// - -public: - virtual void base_update_dependency(RID p_base, DependencyTracker *p_instance) override; - - /* OCCLUDER */ - - void occluder_set_mesh(RID p_occluder, const PackedVector3Array &p_vertices, const PackedInt32Array &p_indices); - - /* FOG VOLUMES */ - - RID fog_volume_allocate() override; - void fog_volume_initialize(RID p_rid) override; - - void fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) override; - void fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) override; - void fog_volume_set_material(RID p_fog_volume, RID p_material) override; - AABB fog_volume_get_aabb(RID p_fog_volume) const override; - RS::FogVolumeShape fog_volume_get_shape(RID p_fog_volume) const override; - - /* VISIBILITY NOTIFIER */ - RID visibility_notifier_allocate() override; - void visibility_notifier_initialize(RID p_notifier) override; - void visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb) override; - void visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable) override; - - AABB visibility_notifier_get_aabb(RID p_notifier) const override; - void visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) override; - - // access from canvas - // GLES3::RenderTarget * render_target_get(RID p_render_target); - - /* CANVAS SHADOW */ - - struct CanvasLightShadow { - RID self; - int size; - int height; - GLuint fbo; - GLuint depth; - GLuint distance; //for older devices - }; - - RID_PtrOwner<CanvasLightShadow> canvas_light_shadow_owner; - - RID canvas_light_shadow_buffer_create(int p_width); - - /* LIGHT SHADOW MAPPING */ - /* - struct CanvasOccluder { - RID self; - - GLuint vertex_id; // 0 means, unconfigured - GLuint index_id; // 0 means, unconfigured - LocalVector<Vector2> lines; - int len; - }; - - RID_Owner<CanvasOccluder> canvas_occluder_owner; - - RID canvas_light_occluder_create(); - void canvas_light_occluder_set_polylines(RID p_occluder, const LocalVector<Vector2> &p_lines); -*/ - - RS::InstanceType get_base_type(RID p_rid) const override; - - bool free(RID p_rid) override; - - void initialize(); - void finalize(); - - void update_memory_info() override; - uint64_t get_rendering_info(RS::RenderingInfo p_info) override; - - bool has_os_feature(const String &p_feature) const override; - - void update_dirty_resources() override; - - void set_debug_generate_wireframes(bool p_generate) override; - - // void render_info_begin_capture() override; - // void render_info_end_capture() override; - // int get_captured_render_info(RS::RenderInfo p_info) override; - - // int get_render_info(RS::RenderInfo p_info) override; - String get_video_adapter_name() const override; - String get_video_adapter_vendor() const override; - RenderingDevice::DeviceType get_video_adapter_type() const override; - String get_video_adapter_api_version() const override; - - void capture_timestamps_begin() override {} - void capture_timestamp(const String &p_name) override {} - uint32_t get_captured_timestamps_count() const override { - return 0; - } - uint64_t get_captured_timestamps_frame() const override { - return 0; - } - uint64_t get_captured_timestamp_gpu_time(uint32_t p_index) const override { - return 0; - } - uint64_t get_captured_timestamp_cpu_time(uint32_t p_index) const override { - return 0; - } - String get_captured_timestamp_name(uint32_t p_index) const override { - return String(); - } - - RasterizerStorageGLES3(); - ~RasterizerStorageGLES3(); -}; - -#endif // GLES3_ENABLED - -#endif // RASTERIZER_STORAGE_OPENGL_H diff --git a/drivers/gles3/shader_gles3.h b/drivers/gles3/shader_gles3.h index e1385669cd..2b72549b5b 100644 --- a/drivers/gles3/shader_gles3.h +++ b/drivers/gles3/shader_gles3.h @@ -28,10 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SHADER_OPENGL_H -#define SHADER_OPENGL_H +#ifndef SHADER_GLES3_H +#define SHADER_GLES3_H -#include "core/math/camera_matrix.h" +#include "core/math/projection.h" #include "core/os/mutex.h" #include "core/string/string_builder.h" #include "core/templates/hash_map.h" @@ -248,5 +248,6 @@ public: virtual ~ShaderGLES3(); }; -#endif // SHADER_OPENGL_H -#endif +#endif // GLES3_ENABLED + +#endif // SHADER_GLES3_H diff --git a/drivers/gles3/shaders/SCsub b/drivers/gles3/shaders/SCsub index d8dd573f57..83ffe8b1e1 100644 --- a/drivers/gles3/shaders/SCsub +++ b/drivers/gles3/shaders/SCsub @@ -10,7 +10,7 @@ if "GLES3_GLSL" in env["BUILDERS"]: 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) + env.Depends([f + ".gen.h" for f in glsl_files], gl_include_files + ["#gles3_builders.py"]) env.GLES3_GLSL("canvas.glsl") env.GLES3_GLSL("copy.glsl") diff --git a/drivers/gles3/shaders/canvas_uniforms_inc.glsl b/drivers/gles3/shaders/canvas_uniforms_inc.glsl index e08a15e59d..852dccf415 100644 --- a/drivers/gles3/shaders/canvas_uniforms_inc.glsl +++ b/drivers/gles3/shaders/canvas_uniforms_inc.glsl @@ -58,8 +58,8 @@ struct DrawData { uvec4 lights; }; -layout(std140) uniform GlobalVariableData { //ubo:1 - vec4 global_variables[MAX_GLOBAL_VARIABLES]; +layout(std140) uniform GlobalShaderUniformData { //ubo:1 + vec4 global_shader_uniforms[MAX_GLOBAL_SHADER_UNIFORMS]; }; layout(std140) uniform CanvasData { //ubo:0 diff --git a/drivers/gles3/shaders/cubemap_filter.glsl b/drivers/gles3/shaders/cubemap_filter.glsl index ebf0c08ec4..57f0d7d0b8 100644 --- a/drivers/gles3/shaders/cubemap_filter.glsl +++ b/drivers/gles3/shaders/cubemap_filter.glsl @@ -29,19 +29,15 @@ uniform samplerCube source_cube; //texunit:0 /* clang-format on */ uniform int face_id; -uniform float roughness; -uniform float face_size; -uniform int sample_count; -//Todo, profile on low end hardware to see if fixed loop is faster -#ifdef USE_FIXED_SAMPLES -#define FIXED_SAMPLE_COUNT 32 +#ifndef MODE_DIRECT_WRITE +uniform int sample_count; +uniform vec4 sample_directions_mip[MAX_SAMPLE_COUNT]; +uniform float weight; #endif in highp vec2 uv_interp; -uniform sampler2D radical_inverse_vdc_cache; // texunit:1 - layout(location = 0) out vec4 frag_color; #define M_PI 3.14159265359 @@ -93,48 +89,6 @@ vec3 texelCoordToVec(vec2 uv, int faceID) { return normalize(result); } -vec3 ImportanceSampleGGX(vec2 xi, float roughness4) { - // Compute distribution direction - float Phi = 2.0 * M_PI * xi.x; - float CosTheta = sqrt((1.0 - xi.y) / (1.0 + (roughness4 - 1.0) * xi.y)); - float SinTheta = sqrt(1.0 - CosTheta * CosTheta); - - // Convert to spherical direction - vec3 H; - H.x = SinTheta * cos(Phi); - H.y = SinTheta * sin(Phi); - H.z = CosTheta; - - return H; -} - -float DistributionGGX(float NdotH, float roughness4) { - float NdotH2 = NdotH * NdotH; - float denom = (NdotH2 * (roughness4 - 1.0) + 1.0); - denom = M_PI * denom * denom; - - return roughness4 / denom; -} - -// https://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html -float GGX(float NdotV, float a) { - float k = a / 2.0; - return NdotV / (NdotV * (1.0 - k) + k); -} - -// https://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html -float G_Smith(float a, float nDotV, float nDotL) { - return GGX(nDotL, a * a) * GGX(nDotV, a * a); -} - -float radical_inverse_VdC(int i) { - return texture(radical_inverse_vdc_cache, vec2(float(i) / 512.0, 0.0)).x; -} - -vec2 Hammersley(int i, int N) { - return vec2(float(i) / float(N), radical_inverse_VdC(i)); -} - void main() { vec3 color = vec3(0.0); vec2 uv = uv_interp; @@ -145,9 +99,6 @@ void main() { #else vec4 sum = vec4(0.0); - float solid_angle_texel = 4.0 * M_PI / (6.0 * face_size * face_size); - float roughness2 = roughness * roughness; - float roughness4 = roughness2 * roughness2; vec3 UpVector = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); mat3 T; T[0] = normalize(cross(UpVector, N)); @@ -155,32 +106,15 @@ void main() { T[2] = N; for (int sample_num = 0; sample_num < sample_count; sample_num++) { - vec2 xi = Hammersley(sample_num, sample_count); - - vec3 H = T * ImportanceSampleGGX(xi, roughness4); - float NdotH = dot(N, H); - vec3 L = (2.0 * NdotH * H - N); - - float NdotL = clamp(dot(N, L), 0.0, 1.0); - - if (NdotL > 0.0) { - float D = DistributionGGX(NdotH, roughness4); - float pdf = D * NdotH / (4.0 * NdotH) + 0.0001; - - float solid_angle_sample = 1.0 / (float(sample_count) * pdf + 0.0001); - - float mipLevel = roughness == 0.0 ? 0.0 : 0.5 * log2(solid_angle_sample / solid_angle_texel); - - vec3 val = textureLod(source_cube, L, mipLevel).rgb; - // Mix using linear - val = srgb_to_linear(val); - - sum.rgb += val * NdotL; - sum.a += NdotL; - } + vec4 sample = sample_directions_mip[sample_num]; + vec3 L = T * sample.xyz; + vec3 val = textureLod(source_cube, L, sample.w).rgb; + // Mix using linear + val = srgb_to_linear(val); + sum.rgb += val * sample.z; } - sum /= sum.a; + sum /= weight; sum.rgb = linear_to_srgb(sum.rgb); frag_color = vec4(sum.rgb, 1.0); diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index 4f2be8bf60..93bb4c191d 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -104,8 +104,8 @@ layout(location = 14) in highp vec4 instance_xform2; layout(location = 15) in highp uvec4 instance_color_custom_data; // Color packed into xy, Custom data into zw. #endif -layout(std140) uniform GlobalVariableData { //ubo:1 - vec4 global_variables[MAX_GLOBAL_VARIABLES]; +layout(std140) uniform GlobalShaderUniformData { //ubo:1 + vec4 global_shader_uniforms[MAX_GLOBAL_SHADER_UNIFORMS]; }; layout(std140) uniform SceneData { // ubo:2 @@ -399,8 +399,8 @@ uniform samplerCube radiance_map; // texunit:-2 #endif -layout(std140) uniform GlobalVariableData { //ubo:1 - vec4 global_variables[MAX_GLOBAL_VARIABLES]; +layout(std140) uniform GlobalShaderUniformData { //ubo:1 + vec4 global_shader_uniforms[MAX_GLOBAL_SHADER_UNIFORMS]; }; /* Material Uniforms */ @@ -686,7 +686,10 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte #endif // LIGHT_ANISOTROPY_USED // F float cLdotH5 = SchlickFresnel(cLdotH); - vec3 F = mix(vec3(cLdotH5), vec3(1.0), f0); + // Calculate Fresnel using cheap approximate specular occlusion term from Filament: + // https://google.github.io/filament/Filament.html#lighting/occlusion/specularocclusion + float f90 = clamp(50.0 * f0.g, 0.0, 1.0); + vec3 F = f0 + (f90 - f0) * cLdotH5; vec3 specular_brdf_NL = cNdotL * D * F * G; @@ -1107,7 +1110,7 @@ void main() { float a004 = min(r.x * r.x, exp2(-9.28 * ndotv)) * r.x + r.y; vec2 env = vec2(-1.04, 1.04) * a004 + r.zw; - specular_light *= env.x * f0 + env.y; + specular_light *= env.x * f0 + env.y * clamp(50.0 * f0.g, 0.0, 1.0); #endif } diff --git a/drivers/gles3/shaders/sky.glsl b/drivers/gles3/shaders/sky.glsl index 50ab38bc31..eb1befe38e 100644 --- a/drivers/gles3/shaders/sky.glsl +++ b/drivers/gles3/shaders/sky.glsl @@ -42,8 +42,8 @@ uniform sampler2D half_res; //texunit:-2 uniform sampler2D quarter_res; //texunit:-3 #endif -layout(std140) uniform GlobalVariableData { //ubo:1 - vec4 global_variables[MAX_GLOBAL_VARIABLES]; +layout(std140) uniform GlobalShaderUniformData { //ubo:1 + vec4 global_shader_uniforms[MAX_GLOBAL_SHADER_UNIFORMS]; }; struct DirectionalLightData { diff --git a/drivers/gles3/storage/config.h b/drivers/gles3/storage/config.h index db76aa79fb..b83c83f425 100644 --- a/drivers/gles3/storage/config.h +++ b/drivers/gles3/storage/config.h @@ -90,4 +90,4 @@ public: #endif // GLES3_ENABLED -#endif // !CONFIG_GLES3_H +#endif // CONFIG_GLES3_H diff --git a/drivers/gles3/storage/light_storage.cpp b/drivers/gles3/storage/light_storage.cpp index 954aa11c0d..22578c9e91 100644 --- a/drivers/gles3/storage/light_storage.cpp +++ b/drivers/gles3/storage/light_storage.cpp @@ -139,12 +139,12 @@ void LightStorage::light_set_param(RID p_light, RS::LightParam p_param, float p_ case RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE: case RS::LIGHT_PARAM_SHADOW_BIAS: { light->version++; - light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT); + light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT); } break; case RS::LIGHT_PARAM_SIZE: { if ((light->param[p_param] > CMP_EPSILON) != (p_value > CMP_EPSILON)) { //changing from no size to size and the opposite - light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR); + light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR); } } break; default: { @@ -160,7 +160,7 @@ void LightStorage::light_set_shadow(RID p_light, bool p_enabled) { light->shadow = p_enabled; light->version++; - light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT); + light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT); } void LightStorage::light_set_projector(RID p_light, RID p_texture) { @@ -182,7 +182,7 @@ void LightStorage::light_set_projector(RID p_light, RID p_texture) { if (light->projector.is_valid()) { texture_storage->texture_add_to_decal_atlas(light->projector, light->type == RS::LIGHT_OMNI); } - light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR); + light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR); } } @@ -200,7 +200,7 @@ void LightStorage::light_set_cull_mask(RID p_light, uint32_t p_mask) { light->cull_mask = p_mask; light->version++; - light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT); + light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT); } void LightStorage::light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) { @@ -220,7 +220,7 @@ void LightStorage::light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) light->reverse_cull = p_enabled; light->version++; - light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT); + light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT); } void LightStorage::light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) { @@ -230,7 +230,7 @@ void LightStorage::light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mod light->bake_mode = p_bake_mode; light->version++; - light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT); + light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT); } void LightStorage::light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) { @@ -240,7 +240,7 @@ void LightStorage::light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMo light->omni_shadow_mode = p_mode; light->version++; - light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT); + light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT); } RS::LightOmniShadowMode LightStorage::light_omni_get_shadow_mode(RID p_light) { @@ -256,7 +256,7 @@ void LightStorage::light_directional_set_shadow_mode(RID p_light, RS::LightDirec light->directional_shadow_mode = p_mode; light->version++; - light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT); + light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT); } void LightStorage::light_directional_set_blend_splits(RID p_light, bool p_enable) { @@ -265,7 +265,7 @@ void LightStorage::light_directional_set_blend_splits(RID p_light, bool p_enable light->directional_blend_splits = p_enable; light->version++; - light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT); + light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT); } bool LightStorage::light_directional_get_blend_splits(RID p_light) const { @@ -476,4 +476,104 @@ float LightStorage::lightmap_get_probe_capture_update_speed() const { return 0; } +/* LIGHT SHADOW MAPPING */ +/* + +RID LightStorage::canvas_light_occluder_create() { + CanvasOccluder *co = memnew(CanvasOccluder); + co->index_id = 0; + co->vertex_id = 0; + co->len = 0; + + return canvas_occluder_owner.make_rid(co); +} + +void LightStorage::canvas_light_occluder_set_polylines(RID p_occluder, const PoolVector<Vector2> &p_lines) { + CanvasOccluder *co = canvas_occluder_owner.get(p_occluder); + ERR_FAIL_COND(!co); + + co->lines = p_lines; + + if (p_lines.size() != co->len) { + if (co->index_id) { + glDeleteBuffers(1, &co->index_id); + } if (co->vertex_id) { + glDeleteBuffers(1, &co->vertex_id); + } + + co->index_id = 0; + co->vertex_id = 0; + co->len = 0; + } + + if (p_lines.size()) { + PoolVector<float> geometry; + PoolVector<uint16_t> indices; + int lc = p_lines.size(); + + geometry.resize(lc * 6); + indices.resize(lc * 3); + + PoolVector<float>::Write vw = geometry.write(); + PoolVector<uint16_t>::Write iw = indices.write(); + + PoolVector<Vector2>::Read lr = p_lines.read(); + + const int POLY_HEIGHT = 16384; + + for (int i = 0; i < lc / 2; i++) { + vw[i * 12 + 0] = lr[i * 2 + 0].x; + vw[i * 12 + 1] = lr[i * 2 + 0].y; + vw[i * 12 + 2] = POLY_HEIGHT; + + vw[i * 12 + 3] = lr[i * 2 + 1].x; + vw[i * 12 + 4] = lr[i * 2 + 1].y; + vw[i * 12 + 5] = POLY_HEIGHT; + + vw[i * 12 + 6] = lr[i * 2 + 1].x; + vw[i * 12 + 7] = lr[i * 2 + 1].y; + vw[i * 12 + 8] = -POLY_HEIGHT; + + vw[i * 12 + 9] = lr[i * 2 + 0].x; + vw[i * 12 + 10] = lr[i * 2 + 0].y; + vw[i * 12 + 11] = -POLY_HEIGHT; + + iw[i * 6 + 0] = i * 4 + 0; + iw[i * 6 + 1] = i * 4 + 1; + iw[i * 6 + 2] = i * 4 + 2; + + iw[i * 6 + 3] = i * 4 + 2; + iw[i * 6 + 4] = i * 4 + 3; + iw[i * 6 + 5] = i * 4 + 0; + } + + //if same buffer len is being set, just use BufferSubData to avoid a pipeline flush + + if (!co->vertex_id) { + glGenBuffers(1, &co->vertex_id); + glBindBuffer(GL_ARRAY_BUFFER, co->vertex_id); + glBufferData(GL_ARRAY_BUFFER, lc * 6 * sizeof(real_t), vw.ptr(), GL_STATIC_DRAW); + } else { + glBindBuffer(GL_ARRAY_BUFFER, co->vertex_id); + glBufferSubData(GL_ARRAY_BUFFER, 0, lc * 6 * sizeof(real_t), vw.ptr()); + } + + glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind + + if (!co->index_id) { + glGenBuffers(1, &co->index_id); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, co->index_id); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, lc * 3 * sizeof(uint16_t), iw.ptr(), GL_DYNAMIC_DRAW); + } else { + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, co->index_id); + glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, lc * 3 * sizeof(uint16_t), iw.ptr()); + } + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); //unbind + + co->len = lc; + } +} +*/ + #endif // !GLES3_ENABLED diff --git a/drivers/gles3/storage/light_storage.h b/drivers/gles3/storage/light_storage.h index 5acaf45aa3..857a0261fa 100644 --- a/drivers/gles3/storage/light_storage.h +++ b/drivers/gles3/storage/light_storage.h @@ -37,8 +37,8 @@ #include "core/templates/rid_owner.h" #include "core/templates/self_list.h" #include "servers/rendering/renderer_compositor.h" -#include "servers/rendering/renderer_storage.h" #include "servers/rendering/storage/light_storage.h" +#include "servers/rendering/storage/utilities.h" #include "platform_config.h" #ifndef OPENGL_INCLUDE_H @@ -72,7 +72,7 @@ struct Light { RS::LightDirectionalSkyMode directional_sky_mode = RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_AND_SKY; uint64_t version = 0; - RendererStorage::Dependency dependency; + Dependency dependency; }; /* REFLECTION PROBE */ @@ -93,7 +93,7 @@ struct ReflectionProbe { uint32_t cull_mask = (1 << 20) - 1; float mesh_lod_threshold = 0.01; - RendererStorage::Dependency dependency; + Dependency dependency; }; /* LIGHTMAP */ @@ -115,7 +115,7 @@ struct Lightmap { int32_t over = EMPTY_LEAF, under = EMPTY_LEAF; }; - RendererStorage::Dependency dependency; + Dependency dependency; }; class LightStorage : public RendererLightStorage { @@ -321,10 +321,27 @@ public: virtual bool lightmap_is_interior(RID p_lightmap) const override; virtual void lightmap_set_probe_capture_update_speed(float p_speed) override; virtual float lightmap_get_probe_capture_update_speed() const override; + + /* LIGHT SHADOW MAPPING */ + /* + struct CanvasOccluder { + RID self; + + GLuint vertex_id; // 0 means, unconfigured + GLuint index_id; // 0 means, unconfigured + LocalVector<Vector2> lines; + int len; + }; + + RID_Owner<CanvasOccluder> canvas_occluder_owner; + + RID canvas_light_occluder_create(); + void canvas_light_occluder_set_polylines(RID p_occluder, const LocalVector<Vector2> &p_lines); + */ }; } // namespace GLES3 -#endif // !GLES3_ENABLED +#endif // GLES3_ENABLED -#endif // !LIGHT_STORAGE_GLES3_H +#endif // LIGHT_STORAGE_GLES3_H diff --git a/drivers/gles3/storage/material_storage.cpp b/drivers/gles3/storage/material_storage.cpp index fd50bdedbd..68045930b0 100644 --- a/drivers/gles3/storage/material_storage.cpp +++ b/drivers/gles3/storage/material_storage.cpp @@ -176,75 +176,86 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy } } break; case ShaderLanguage::TYPE_IVEC2: { - Vector<int> iv = value; - int s = iv.size(); int32_t *gui = (int32_t *)data; + if (p_array_size > 0) { + Vector<int> iv = value; + int s = iv.size(); + int count = 2 * p_array_size; - if (p_array_size <= 0) { - p_array_size = 1; - } - int count = 2 * p_array_size; - - const int *r = iv.ptr(); - for (int i = 0, j = 0; i < count; i += 2, j += 4) { - if (i < s) { - gui[j] = r[i]; - gui[j + 1] = r[i + 1]; - } else { - gui[j] = 0; - gui[j + 1] = 0; + const int *r = iv.ptr(); + for (int i = 0, j = 0; i < count; i += 2, j += 4) { + if (i < s) { + gui[j] = r[i]; + gui[j + 1] = r[i + 1]; + } else { + gui[j] = 0; + gui[j + 1] = 0; + } + gui[j + 2] = 0; // ignored + gui[j + 3] = 0; // ignored } - gui[j + 2] = 0; // ignored - gui[j + 3] = 0; // ignored + } else { + Vector2i v = value; + gui[0] = v.x; + gui[1] = v.y; } } break; case ShaderLanguage::TYPE_IVEC3: { - Vector<int> iv = value; - int s = iv.size(); int32_t *gui = (int32_t *)data; - if (p_array_size <= 0) { - p_array_size = 1; - } - int count = 3 * p_array_size; - - const int *r = iv.ptr(); - for (int i = 0, j = 0; i < count; i += 3, j += 4) { - if (i < s) { - gui[j] = r[i]; - gui[j + 1] = r[i + 1]; - gui[j + 2] = r[i + 2]; - } else { - gui[j] = 0; - gui[j + 1] = 0; - gui[j + 2] = 0; + if (p_array_size > 0) { + Vector<int> iv = value; + int s = iv.size(); + int count = 3 * p_array_size; + + const int *r = iv.ptr(); + for (int i = 0, j = 0; i < count; i += 3, j += 4) { + if (i < s) { + gui[j] = r[i]; + gui[j + 1] = r[i + 1]; + gui[j + 2] = r[i + 2]; + } else { + gui[j] = 0; + gui[j + 1] = 0; + gui[j + 2] = 0; + } + gui[j + 3] = 0; // ignored } - gui[j + 3] = 0; // ignored + } else { + Vector3i v = value; + gui[0] = v.x; + gui[1] = v.y; + gui[2] = v.z; } } break; case ShaderLanguage::TYPE_IVEC4: { - Vector<int> iv = value; - int s = iv.size(); int32_t *gui = (int32_t *)data; - if (p_array_size <= 0) { - p_array_size = 1; - } - int count = 4 * p_array_size; - - const int *r = iv.ptr(); - for (int i = 0; i < count; i += 4) { - if (i < s) { - gui[i] = r[i]; - gui[i + 1] = r[i + 1]; - gui[i + 2] = r[i + 2]; - gui[i + 3] = r[i + 3]; - } else { - gui[i] = 0; - gui[i + 1] = 0; - gui[i + 2] = 0; - gui[i + 3] = 0; + if (p_array_size > 0) { + Vector<int> iv = value; + int s = iv.size(); + int count = 4 * p_array_size; + + const int *r = iv.ptr(); + for (int i = 0; i < count; i += 4) { + if (i < s) { + gui[i] = r[i]; + gui[i + 1] = r[i + 1]; + gui[i + 2] = r[i + 2]; + gui[i + 3] = r[i + 3]; + } else { + gui[i] = 0; + gui[i + 1] = 0; + gui[i + 2] = 0; + gui[i + 3] = 0; + } } + } else { + Vector4i v = value; + gui[0] = v.x; + gui[1] = v.y; + gui[2] = v.z; + gui[3] = v.w; } } break; case ShaderLanguage::TYPE_UINT: { @@ -271,75 +282,86 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy } } break; case ShaderLanguage::TYPE_UVEC2: { - Vector<int> iv = value; - int s = iv.size(); uint32_t *gui = (uint32_t *)data; + if (p_array_size > 0) { + Vector<int> iv = value; + int s = iv.size(); + int count = 2 * p_array_size; - if (p_array_size <= 0) { - p_array_size = 1; - } - int count = 2 * p_array_size; - - const int *r = iv.ptr(); - for (int i = 0, j = 0; i < count; i += 2, j += 4) { - if (i < s) { - gui[j] = r[i]; - gui[j + 1] = r[i + 1]; - } else { - gui[j] = 0; - gui[j + 1] = 0; + const int *r = iv.ptr(); + for (int i = 0, j = 0; i < count; i += 2, j += 4) { + if (i < s) { + gui[j] = r[i]; + gui[j + 1] = r[i + 1]; + } else { + gui[j] = 0; + gui[j + 1] = 0; + } + gui[j + 2] = 0; // ignored + gui[j + 3] = 0; // ignored } - gui[j + 2] = 0; // ignored - gui[j + 3] = 0; // ignored + } else { + Vector2i v = value; + gui[0] = v.x; + gui[1] = v.y; } } break; case ShaderLanguage::TYPE_UVEC3: { - Vector<int> iv = value; - int s = iv.size(); uint32_t *gui = (uint32_t *)data; - if (p_array_size <= 0) { - p_array_size = 1; - } - int count = 3 * p_array_size; - - const int *r = iv.ptr(); - for (int i = 0, j = 0; i < count; i += 3, j += 4) { - if (i < s) { - gui[j] = r[i]; - gui[j + 1] = r[i + 1]; - gui[j + 2] = r[i + 2]; - } else { - gui[j] = 0; - gui[j + 1] = 0; - gui[j + 2] = 0; + if (p_array_size > 0) { + Vector<int> iv = value; + int s = iv.size(); + int count = 3 * p_array_size; + + const int *r = iv.ptr(); + for (int i = 0, j = 0; i < count; i += 3, j += 4) { + if (i < s) { + gui[j] = r[i]; + gui[j + 1] = r[i + 1]; + gui[j + 2] = r[i + 2]; + } else { + gui[j] = 0; + gui[j + 1] = 0; + gui[j + 2] = 0; + } + gui[j + 3] = 0; // ignored } - gui[j + 3] = 0; // ignored + } else { + Vector3i v = value; + gui[0] = v.x; + gui[1] = v.y; + gui[2] = v.z; } } break; case ShaderLanguage::TYPE_UVEC4: { - Vector<int> iv = value; - int s = iv.size(); uint32_t *gui = (uint32_t *)data; - if (p_array_size <= 0) { - p_array_size = 1; - } - int count = 4 * p_array_size; - - const int *r = iv.ptr(); - for (int i = 0; i < count; i++) { - if (i < s) { - gui[i] = r[i]; - gui[i + 1] = r[i + 1]; - gui[i + 2] = r[i + 2]; - gui[i + 3] = r[i + 3]; - } else { - gui[i] = 0; - gui[i + 1] = 0; - gui[i + 2] = 0; - gui[i + 3] = 0; + if (p_array_size > 0) { + Vector<int> iv = value; + int s = iv.size(); + int count = 4 * p_array_size; + + const int *r = iv.ptr(); + for (int i = 0; i < count; i++) { + if (i < s) { + gui[i] = r[i]; + gui[i + 1] = r[i + 1]; + gui[i + 2] = r[i + 2]; + gui[i + 3] = r[i + 3]; + } else { + gui[i] = 0; + gui[i + 1] = 0; + gui[i + 2] = 0; + gui[i + 3] = 0; + } } + } else { + Vector4i v = value; + gui[0] = v.x; + gui[1] = v.y; + gui[2] = v.z; + gui[3] = v.w; } } break; case ShaderLanguage::TYPE_FLOAT: { @@ -504,6 +526,13 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy gui[1] = v.y; gui[2] = v.z; gui[3] = v.w; + } else if (value.get_type() == Variant::VECTOR4) { + Vector4 v = value; + + gui[0] = v.x; + gui[1] = v.y; + gui[2] = v.z; + gui[3] = v.w; } else { Plane v = value; @@ -660,7 +689,7 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy gui[i + 15] = 1; } } - } else { + } else if (value.get_type() == Variant::TRANSFORM3D) { Transform3D v = value; gui[0] = v.basis.rows[0][0]; gui[1] = v.basis.rows[1][0]; @@ -681,6 +710,13 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy gui[13] = v.origin.y; gui[14] = v.origin.z; gui[15] = 1; + } else { + Projection v = value; + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + gui[i * 4 + j] = v.matrix[i][j]; + } + } } } break; default: { @@ -937,7 +973,7 @@ void MaterialData::update_uniform_buffer(const HashMap<StringName, ShaderLanguag if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) { //this is a global variable, get the index to it - GlobalVariables::Variable *gv = material_storage->global_variables.variables.getptr(E.key); + GlobalShaderUniforms::Variable *gv = material_storage->global_shader_uniforms.variables.getptr(E.key); uint32_t index = 0; if (gv) { index = gv->buffer_index; @@ -993,9 +1029,9 @@ void MaterialData::update_uniform_buffer(const HashMap<StringName, ShaderLanguag if (uses_global_buffer != (global_buffer_E != nullptr)) { if (uses_global_buffer) { - global_buffer_E = material_storage->global_variables.materials_using_buffer.push_back(self); + global_buffer_E = material_storage->global_shader_uniforms.materials_using_buffer.push_back(self); } else { - material_storage->global_variables.materials_using_buffer.erase(global_buffer_E); + material_storage->global_shader_uniforms.materials_using_buffer.erase(global_buffer_E); global_buffer_E = nullptr; } } @@ -1006,20 +1042,20 @@ MaterialData::~MaterialData() { if (global_buffer_E) { //unregister global buffers - material_storage->global_variables.materials_using_buffer.erase(global_buffer_E); + material_storage->global_shader_uniforms.materials_using_buffer.erase(global_buffer_E); } if (global_texture_E) { //unregister global textures for (const KeyValue<StringName, uint64_t> &E : used_global_textures) { - GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(E.key); + GlobalShaderUniforms::Variable *v = material_storage->global_shader_uniforms.variables.getptr(E.key); if (v) { v->texture_materials.erase(self); } } //unregister material from those using global textures - material_storage->global_variables.materials_using_texture.erase(global_texture_E); + material_storage->global_shader_uniforms.materials_using_texture.erase(global_texture_E); } if (uniform_buffer) { @@ -1050,7 +1086,7 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet if (p_texture_uniforms[i].global) { uses_global_textures = true; - GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(uniform_name); + GlobalShaderUniforms::Variable *v = material_storage->global_shader_uniforms.variables.getptr(uniform_name); if (v) { if (v->buffer_index >= 0) { WARN_PRINT("Shader uses global uniform texture '" + String(uniform_name) + "', but it changed type and is no longer a texture!."); @@ -1222,7 +1258,7 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet if (E.value != global_textures_pass) { to_delete.push_back(E.key); - GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(E.key); + GlobalShaderUniforms::Variable *v = material_storage->global_shader_uniforms.variables.getptr(E.key); if (v) { v->texture_materials.erase(self); } @@ -1236,9 +1272,9 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet //handle registering/unregistering global textures if (uses_global_textures != (global_texture_E != nullptr)) { if (uses_global_textures) { - global_texture_E = material_storage->global_variables.materials_using_texture.push_back(self); + global_texture_E = material_storage->global_shader_uniforms.materials_using_texture.push_back(self); } else { - material_storage->global_variables.materials_using_texture.erase(global_texture_E); + material_storage->global_shader_uniforms.materials_using_texture.erase(global_texture_E); global_texture_E = nullptr; } } @@ -1305,22 +1341,22 @@ MaterialStorage::MaterialStorage() { material_data_request_func[RS::SHADER_SKY] = _create_sky_material_func; material_data_request_func[RS::SHADER_FOG] = nullptr; - static_assert(sizeof(GlobalVariables::Value) == 16); + static_assert(sizeof(GlobalShaderUniforms::Value) == 16); - global_variables.buffer_size = MAX(4096, (int)GLOBAL_GET("rendering/limits/global_shader_variables/buffer_size")); - if (global_variables.buffer_size > uint32_t(Config::get_singleton()->max_uniform_buffer_size)) { - global_variables.buffer_size = uint32_t(Config::get_singleton()->max_uniform_buffer_size); + global_shader_uniforms.buffer_size = MAX(4096, (int)GLOBAL_GET("rendering/limits/global_shader_variables/buffer_size")); + if (global_shader_uniforms.buffer_size > uint32_t(Config::get_singleton()->max_uniform_buffer_size)) { + global_shader_uniforms.buffer_size = uint32_t(Config::get_singleton()->max_uniform_buffer_size); WARN_PRINT("Project setting: rendering/limits/global_shader_variables/buffer_size exceeds maximum uniform buffer size of: " + itos(Config::get_singleton()->max_uniform_buffer_size)); } - global_variables.buffer_values = memnew_arr(GlobalVariables::Value, global_variables.buffer_size); - memset(global_variables.buffer_values, 0, sizeof(GlobalVariables::Value) * global_variables.buffer_size); - global_variables.buffer_usage = memnew_arr(GlobalVariables::ValueUsage, global_variables.buffer_size); - global_variables.buffer_dirty_regions = memnew_arr(bool, global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE); - memset(global_variables.buffer_dirty_regions, 0, sizeof(bool) * global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE); - glGenBuffers(1, &global_variables.buffer); - glBindBuffer(GL_UNIFORM_BUFFER, global_variables.buffer); - glBufferData(GL_UNIFORM_BUFFER, sizeof(GlobalVariables::Value) * global_variables.buffer_size, nullptr, GL_DYNAMIC_DRAW); + global_shader_uniforms.buffer_values = memnew_arr(GlobalShaderUniforms::Value, global_shader_uniforms.buffer_size); + memset(global_shader_uniforms.buffer_values, 0, sizeof(GlobalShaderUniforms::Value) * global_shader_uniforms.buffer_size); + global_shader_uniforms.buffer_usage = memnew_arr(GlobalShaderUniforms::ValueUsage, global_shader_uniforms.buffer_size); + global_shader_uniforms.buffer_dirty_regions = memnew_arr(bool, global_shader_uniforms.buffer_size / GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE); + memset(global_shader_uniforms.buffer_dirty_regions, 0, sizeof(bool) * global_shader_uniforms.buffer_size / GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE); + glGenBuffers(1, &global_shader_uniforms.buffer); + glBindBuffer(GL_UNIFORM_BUFFER, global_shader_uniforms.buffer); + glBufferData(GL_UNIFORM_BUFFER, sizeof(GlobalShaderUniforms::Value) * global_shader_uniforms.buffer_size, nullptr, GL_DYNAMIC_DRAW); glBindBuffer(GL_UNIFORM_BUFFER, 0); { @@ -1378,6 +1414,7 @@ MaterialStorage::MaterialStorage() { actions.usage_defines["NORMAL"] = "#define NORMAL_USED\n"; actions.usage_defines["NORMAL_MAP"] = "#define NORMAL_MAP_USED\n"; actions.usage_defines["LIGHT"] = "#define LIGHT_SHADER_CODE_USED\n"; + actions.usage_defines["SPECULAR_SHININESS"] = "#define SPECULAR_SHININESS_USED\n"; actions.render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n"; actions.render_mode_defines["unshaded"] = "#define MODE_UNSHADED\n"; @@ -1457,7 +1494,7 @@ MaterialStorage::MaterialStorage() { actions.renames["NORMAL_ROUGHNESS_TEXTURE"] = "normal_roughness_buffer"; actions.renames["DEPTH"] = "gl_FragDepth"; actions.renames["OUTPUT_IS_SRGB"] = "true"; - actions.renames["FOG"] = "custom_fog"; + actions.renames["FOG"] = "fog"; actions.renames["RADIANCE"] = "custom_radiance"; actions.renames["IRRADIANCE"] = "custom_irradiance"; actions.renames["BONE_INDICES"] = "bone_attrib"; @@ -1613,7 +1650,7 @@ ShaderCompiler::DefaultIdentifierActions actions; actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP; actions.default_repeat = ShaderLanguage::REPEAT_ENABLE; - actions.global_buffer_array_variable = "global_variables.data"; + actions.global_buffer_array_variable = "global_shader_uniforms.data"; particles_shader.compiler.initialize(actions); */ @@ -1675,25 +1712,25 @@ ShaderCompiler::DefaultIdentifierActions actions; MaterialStorage::~MaterialStorage() { //shaders.copy.version_free(shaders.copy_version); - memdelete_arr(global_variables.buffer_values); - memdelete_arr(global_variables.buffer_usage); - memdelete_arr(global_variables.buffer_dirty_regions); - glDeleteBuffers(1, &global_variables.buffer); + memdelete_arr(global_shader_uniforms.buffer_values); + memdelete_arr(global_shader_uniforms.buffer_usage); + memdelete_arr(global_shader_uniforms.buffer_dirty_regions); + glDeleteBuffers(1, &global_shader_uniforms.buffer); singleton = nullptr; } -/* GLOBAL VARIABLE API */ +/* GLOBAL SHADER UNIFORM API */ -int32_t MaterialStorage::_global_variable_allocate(uint32_t p_elements) { +int32_t MaterialStorage::_global_shader_uniform_allocate(uint32_t p_elements) { int32_t idx = 0; - while (idx + p_elements <= global_variables.buffer_size) { - if (global_variables.buffer_usage[idx].elements == 0) { + while (idx + p_elements <= global_shader_uniforms.buffer_size) { + if (global_shader_uniforms.buffer_usage[idx].elements == 0) { bool valid = true; for (uint32_t i = 1; i < p_elements; i++) { - if (global_variables.buffer_usage[idx + i].elements > 0) { + if (global_shader_uniforms.buffer_usage[idx + i].elements > 0) { valid = false; - idx += i + global_variables.buffer_usage[idx + i].elements; + idx += i + global_shader_uniforms.buffer_usage[idx + i].elements; break; } } @@ -1704,17 +1741,17 @@ int32_t MaterialStorage::_global_variable_allocate(uint32_t p_elements) { return idx; } else { - idx += global_variables.buffer_usage[idx].elements; + idx += global_shader_uniforms.buffer_usage[idx].elements; } } return -1; } -void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::GlobalVariableType p_type, const Variant &p_value) { +void MaterialStorage::_global_shader_uniform_store_in_buffer(int32_t p_index, RS::GlobalShaderUniformType p_type, const Variant &p_value) { switch (p_type) { case RS::GLOBAL_VAR_TYPE_BOOL: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index]; bool b = p_value; bv.x = b ? 1.0 : 0.0; bv.y = 0.0; @@ -1723,7 +1760,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob } break; case RS::GLOBAL_VAR_TYPE_BVEC2: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index]; uint32_t bvec = p_value; bv.x = (bvec & 1) ? 1.0 : 0.0; bv.y = (bvec & 2) ? 1.0 : 0.0; @@ -1731,7 +1768,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = 0.0; } break; case RS::GLOBAL_VAR_TYPE_BVEC3: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index]; uint32_t bvec = p_value; bv.x = (bvec & 1) ? 1.0 : 0.0; bv.y = (bvec & 2) ? 1.0 : 0.0; @@ -1739,7 +1776,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = 0.0; } break; case RS::GLOBAL_VAR_TYPE_BVEC4: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index]; uint32_t bvec = p_value; bv.x = (bvec & 1) ? 1.0 : 0.0; bv.y = (bvec & 2) ? 1.0 : 0.0; @@ -1747,7 +1784,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = (bvec & 8) ? 1.0 : 0.0; } break; case RS::GLOBAL_VAR_TYPE_INT: { - GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index]; + GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index]; int32_t v = p_value; bv.x = v; bv.y = 0; @@ -1755,7 +1792,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = 0; } break; case RS::GLOBAL_VAR_TYPE_IVEC2: { - GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index]; + GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index]; Vector2i v = p_value; bv.x = v.x; bv.y = v.y; @@ -1763,7 +1800,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = 0; } break; case RS::GLOBAL_VAR_TYPE_IVEC3: { - GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index]; + GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index]; Vector3i v = p_value; bv.x = v.x; bv.y = v.y; @@ -1771,7 +1808,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = 0; } break; case RS::GLOBAL_VAR_TYPE_IVEC4: { - GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index]; + GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index]; Vector<int32_t> v = p_value; bv.x = v.size() >= 1 ? v[0] : 0; bv.y = v.size() >= 2 ? v[1] : 0; @@ -1779,7 +1816,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = v.size() >= 4 ? v[3] : 0; } break; case RS::GLOBAL_VAR_TYPE_RECT2I: { - GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index]; + GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index]; Rect2i v = p_value; bv.x = v.position.x; bv.y = v.position.y; @@ -1787,7 +1824,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = v.size.y; } break; case RS::GLOBAL_VAR_TYPE_UINT: { - GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index]; + GlobalShaderUniforms::ValueUInt &bv = *(GlobalShaderUniforms::ValueUInt *)&global_shader_uniforms.buffer_values[p_index]; uint32_t v = p_value; bv.x = v; bv.y = 0; @@ -1795,7 +1832,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = 0; } break; case RS::GLOBAL_VAR_TYPE_UVEC2: { - GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index]; + GlobalShaderUniforms::ValueUInt &bv = *(GlobalShaderUniforms::ValueUInt *)&global_shader_uniforms.buffer_values[p_index]; Vector2i v = p_value; bv.x = v.x; bv.y = v.y; @@ -1803,7 +1840,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = 0; } break; case RS::GLOBAL_VAR_TYPE_UVEC3: { - GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index]; + GlobalShaderUniforms::ValueUInt &bv = *(GlobalShaderUniforms::ValueUInt *)&global_shader_uniforms.buffer_values[p_index]; Vector3i v = p_value; bv.x = v.x; bv.y = v.y; @@ -1811,7 +1848,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = 0; } break; case RS::GLOBAL_VAR_TYPE_UVEC4: { - GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index]; + GlobalShaderUniforms::ValueUInt &bv = *(GlobalShaderUniforms::ValueUInt *)&global_shader_uniforms.buffer_values[p_index]; Vector<int32_t> v = p_value; bv.x = v.size() >= 1 ? v[0] : 0; bv.y = v.size() >= 2 ? v[1] : 0; @@ -1819,7 +1856,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = v.size() >= 4 ? v[3] : 0; } break; case RS::GLOBAL_VAR_TYPE_FLOAT: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index]; float v = p_value; bv.x = v; bv.y = 0; @@ -1827,7 +1864,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = 0; } break; case RS::GLOBAL_VAR_TYPE_VEC2: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index]; Vector2 v = p_value; bv.x = v.x; bv.y = v.y; @@ -1835,7 +1872,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = 0; } break; case RS::GLOBAL_VAR_TYPE_VEC3: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index]; Vector3 v = p_value; bv.x = v.x; bv.y = v.y; @@ -1843,7 +1880,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = 0; } break; case RS::GLOBAL_VAR_TYPE_VEC4: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index]; Plane v = p_value; bv.x = v.normal.x; bv.y = v.normal.y; @@ -1851,14 +1888,14 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = v.d; } break; case RS::GLOBAL_VAR_TYPE_COLOR: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index]; Color v = p_value; bv.x = v.r; bv.y = v.g; bv.z = v.b; bv.w = v.a; - GlobalVariables::Value &bv_linear = global_variables.buffer_values[p_index + 1]; + GlobalShaderUniforms::Value &bv_linear = global_shader_uniforms.buffer_values[p_index + 1]; //v = v.srgb_to_linear(); bv_linear.x = v.r; bv_linear.y = v.g; @@ -1867,7 +1904,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob } break; case RS::GLOBAL_VAR_TYPE_RECT2: { - GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; + GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index]; Rect2 v = p_value; bv.x = v.position.x; bv.y = v.position.y; @@ -1875,7 +1912,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = v.size.y; } break; case RS::GLOBAL_VAR_TYPE_MAT2: { - GlobalVariables::Value *bv = &global_variables.buffer_values[p_index]; + GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index]; Vector<float> m2 = p_value; if (m2.size() < 4) { m2.resize(4); @@ -1892,7 +1929,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob } break; case RS::GLOBAL_VAR_TYPE_MAT3: { - GlobalVariables::Value *bv = &global_variables.buffer_values[p_index]; + GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index]; Basis v = p_value; bv[0].x = v.rows[0][0]; bv[0].y = v.rows[1][0]; @@ -1911,7 +1948,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob } break; case RS::GLOBAL_VAR_TYPE_MAT4: { - GlobalVariables::Value *bv = &global_variables.buffer_values[p_index]; + GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index]; Vector<float> m2 = p_value; if (m2.size() < 16) { @@ -1940,7 +1977,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob } break; case RS::GLOBAL_VAR_TYPE_TRANSFORM_2D: { - GlobalVariables::Value *bv = &global_variables.buffer_values[p_index]; + GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index]; Transform2D v = p_value; bv[0].x = v.columns[0][0]; bv[0].y = v.columns[0][1]; @@ -1959,7 +1996,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob } break; case RS::GLOBAL_VAR_TYPE_TRANSFORM: { - GlobalVariables::Value *bv = &global_variables.buffer_values[p_index]; + GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index]; Transform3D v = p_value; bv[0].x = v.basis.rows[0][0]; bv[0].y = v.basis.rows[1][0]; @@ -1988,15 +2025,15 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob } } -void MaterialStorage::_global_variable_mark_buffer_dirty(int32_t p_index, int32_t p_elements) { +void MaterialStorage::_global_shader_uniform_mark_buffer_dirty(int32_t p_index, int32_t p_elements) { int32_t prev_chunk = -1; for (int32_t i = 0; i < p_elements; i++) { - int32_t chunk = (p_index + i) / GlobalVariables::BUFFER_DIRTY_REGION_SIZE; + int32_t chunk = (p_index + i) / GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE; if (chunk != prev_chunk) { - if (!global_variables.buffer_dirty_regions[chunk]) { - global_variables.buffer_dirty_regions[chunk] = true; - global_variables.buffer_dirty_region_count++; + if (!global_shader_uniforms.buffer_dirty_regions[chunk]) { + global_shader_uniforms.buffer_dirty_regions[chunk] = true; + global_shader_uniforms.buffer_dirty_region_count++; } } @@ -2004,16 +2041,16 @@ void MaterialStorage::_global_variable_mark_buffer_dirty(int32_t p_index, int32_ } } -void MaterialStorage::global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) { - ERR_FAIL_COND(global_variables.variables.has(p_name)); - GlobalVariables::Variable gv; +void MaterialStorage::global_shader_uniform_add(const StringName &p_name, RS::GlobalShaderUniformType p_type, const Variant &p_value) { + ERR_FAIL_COND(global_shader_uniforms.variables.has(p_name)); + GlobalShaderUniforms::Variable gv; gv.type = p_type; gv.value = p_value; gv.buffer_index = -1; if (p_type >= RS::GLOBAL_VAR_TYPE_SAMPLER2D) { //is texture - global_variables.must_update_texture_materials = true; //normally there are none + global_shader_uniforms.must_update_texture_materials = true; //normally there are none } else { gv.buffer_elements = 1; if (p_type == RS::GLOBAL_VAR_TYPE_COLOR || p_type == RS::GLOBAL_VAR_TYPE_MAT2) { @@ -2030,56 +2067,56 @@ void MaterialStorage::global_variable_add(const StringName &p_name, RS::GlobalVa } //is vector, allocate in buffer and update index - gv.buffer_index = _global_variable_allocate(gv.buffer_elements); + gv.buffer_index = _global_shader_uniform_allocate(gv.buffer_elements); ERR_FAIL_COND_MSG(gv.buffer_index < 0, vformat("Failed allocating global variable '%s' out of buffer memory. Consider increasing it in the Project Settings.", String(p_name))); - global_variables.buffer_usage[gv.buffer_index].elements = gv.buffer_elements; - _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value); - _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements); + global_shader_uniforms.buffer_usage[gv.buffer_index].elements = gv.buffer_elements; + _global_shader_uniform_store_in_buffer(gv.buffer_index, gv.type, gv.value); + _global_shader_uniform_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements); - global_variables.must_update_buffer_materials = true; //normally there are none + global_shader_uniforms.must_update_buffer_materials = true; //normally there are none } - global_variables.variables[p_name] = gv; + global_shader_uniforms.variables[p_name] = gv; } -void MaterialStorage::global_variable_remove(const StringName &p_name) { - if (!global_variables.variables.has(p_name)) { +void MaterialStorage::global_shader_uniform_remove(const StringName &p_name) { + if (!global_shader_uniforms.variables.has(p_name)) { return; } - GlobalVariables::Variable &gv = global_variables.variables[p_name]; + GlobalShaderUniforms::Variable &gv = global_shader_uniforms.variables[p_name]; if (gv.buffer_index >= 0) { - global_variables.buffer_usage[gv.buffer_index].elements = 0; - global_variables.must_update_buffer_materials = true; + global_shader_uniforms.buffer_usage[gv.buffer_index].elements = 0; + global_shader_uniforms.must_update_buffer_materials = true; } else { - global_variables.must_update_texture_materials = true; + global_shader_uniforms.must_update_texture_materials = true; } - global_variables.variables.erase(p_name); + global_shader_uniforms.variables.erase(p_name); } -Vector<StringName> MaterialStorage::global_variable_get_list() const { +Vector<StringName> MaterialStorage::global_shader_uniform_get_list() const { if (!Engine::get_singleton()->is_editor_hint()) { ERR_FAIL_V_MSG(Vector<StringName>(), "This function should never be used outside the editor, it can severely damage performance."); } Vector<StringName> names; - for (const KeyValue<StringName, GlobalVariables::Variable> &E : global_variables.variables) { + for (const KeyValue<StringName, GlobalShaderUniforms::Variable> &E : global_shader_uniforms.variables) { names.push_back(E.key); } names.sort_custom<StringName::AlphCompare>(); return names; } -void MaterialStorage::global_variable_set(const StringName &p_name, const Variant &p_value) { - ERR_FAIL_COND(!global_variables.variables.has(p_name)); - GlobalVariables::Variable &gv = global_variables.variables[p_name]; +void MaterialStorage::global_shader_uniform_set(const StringName &p_name, const Variant &p_value) { + ERR_FAIL_COND(!global_shader_uniforms.variables.has(p_name)); + GlobalShaderUniforms::Variable &gv = global_shader_uniforms.variables[p_name]; gv.value = p_value; if (gv.override.get_type() == Variant::NIL) { if (gv.buffer_index >= 0) { //buffer - _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value); - _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements); + _global_shader_uniform_store_in_buffer(gv.buffer_index, gv.type, gv.value); + _global_shader_uniform_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements); } else { //texture MaterialStorage *material_storage = MaterialStorage::get_singleton(); @@ -2092,26 +2129,26 @@ void MaterialStorage::global_variable_set(const StringName &p_name, const Varian } } -void MaterialStorage::global_variable_set_override(const StringName &p_name, const Variant &p_value) { - if (!global_variables.variables.has(p_name)) { +void MaterialStorage::global_shader_uniform_set_override(const StringName &p_name, const Variant &p_value) { + if (!global_shader_uniforms.variables.has(p_name)) { return; //variable may not exist } ERR_FAIL_COND(p_value.get_type() == Variant::OBJECT); - GlobalVariables::Variable &gv = global_variables.variables[p_name]; + GlobalShaderUniforms::Variable &gv = global_shader_uniforms.variables[p_name]; gv.override = p_value; if (gv.buffer_index >= 0) { //buffer if (gv.override.get_type() == Variant::NIL) { - _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value); + _global_shader_uniform_store_in_buffer(gv.buffer_index, gv.type, gv.value); } else { - _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.override); + _global_shader_uniform_store_in_buffer(gv.buffer_index, gv.type, gv.override); } - _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements); + _global_shader_uniform_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements); } else { //texture MaterialStorage *material_storage = MaterialStorage::get_singleton(); @@ -2123,35 +2160,35 @@ void MaterialStorage::global_variable_set_override(const StringName &p_name, con } } -Variant MaterialStorage::global_variable_get(const StringName &p_name) const { +Variant MaterialStorage::global_shader_uniform_get(const StringName &p_name) const { if (!Engine::get_singleton()->is_editor_hint()) { ERR_FAIL_V_MSG(Variant(), "This function should never be used outside the editor, it can severely damage performance."); } - if (!global_variables.variables.has(p_name)) { + if (!global_shader_uniforms.variables.has(p_name)) { return Variant(); } - return global_variables.variables[p_name].value; + return global_shader_uniforms.variables[p_name].value; } -RS::GlobalVariableType MaterialStorage::global_variable_get_type_internal(const StringName &p_name) const { - if (!global_variables.variables.has(p_name)) { +RS::GlobalShaderUniformType MaterialStorage::global_shader_uniform_get_type_internal(const StringName &p_name) const { + if (!global_shader_uniforms.variables.has(p_name)) { return RS::GLOBAL_VAR_TYPE_MAX; } - return global_variables.variables[p_name].type; + return global_shader_uniforms.variables[p_name].type; } -RS::GlobalVariableType MaterialStorage::global_variable_get_type(const StringName &p_name) const { +RS::GlobalShaderUniformType MaterialStorage::global_shader_uniform_get_type(const StringName &p_name) const { if (!Engine::get_singleton()->is_editor_hint()) { ERR_FAIL_V_MSG(RS::GLOBAL_VAR_TYPE_MAX, "This function should never be used outside the editor, it can severely damage performance."); } - return global_variable_get_type_internal(p_name); + return global_shader_uniform_get_type_internal(p_name); } -void MaterialStorage::global_variables_load_settings(bool p_load_textures) { +void MaterialStorage::global_shader_uniforms_load_settings(bool p_load_textures) { List<PropertyInfo> settings; ProjectSettings::get_singleton()->get_property_list(&settings); @@ -2196,11 +2233,11 @@ void MaterialStorage::global_variables_load_settings(bool p_load_textures) { "samplerCube", }; - RS::GlobalVariableType gvtype = RS::GLOBAL_VAR_TYPE_MAX; + RS::GlobalShaderUniformType gvtype = RS::GLOBAL_VAR_TYPE_MAX; for (int i = 0; i < RS::GLOBAL_VAR_TYPE_MAX; i++) { if (global_var_type_names[i] == type) { - gvtype = RS::GlobalVariableType(i); + gvtype = RS::GlobalShaderUniformType(i); break; } } @@ -2222,47 +2259,47 @@ void MaterialStorage::global_variables_load_settings(bool p_load_textures) { value = resource; } - if (global_variables.variables.has(name)) { + if (global_shader_uniforms.variables.has(name)) { //has it, update it - global_variable_set(name, value); + global_shader_uniform_set(name, value); } else { - global_variable_add(name, gvtype, value); + global_shader_uniform_add(name, gvtype, value); } } } } -void MaterialStorage::global_variables_clear() { - global_variables.variables.clear(); +void MaterialStorage::global_shader_uniforms_clear() { + global_shader_uniforms.variables.clear(); } -GLuint MaterialStorage::global_variables_get_uniform_buffer() const { - return global_variables.buffer; +GLuint MaterialStorage::global_shader_uniforms_get_uniform_buffer() const { + return global_shader_uniforms.buffer; } -int32_t MaterialStorage::global_variables_instance_allocate(RID p_instance) { - ERR_FAIL_COND_V(global_variables.instance_buffer_pos.has(p_instance), -1); - int32_t pos = _global_variable_allocate(ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES); - global_variables.instance_buffer_pos[p_instance] = pos; //save anyway +int32_t MaterialStorage::global_shader_uniforms_instance_allocate(RID p_instance) { + ERR_FAIL_COND_V(global_shader_uniforms.instance_buffer_pos.has(p_instance), -1); + int32_t pos = _global_shader_uniform_allocate(ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES); + global_shader_uniforms.instance_buffer_pos[p_instance] = pos; //save anyway ERR_FAIL_COND_V_MSG(pos < 0, -1, "Too many instances using shader instance variables. Increase buffer size in Project Settings."); - global_variables.buffer_usage[pos].elements = ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES; + global_shader_uniforms.buffer_usage[pos].elements = ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES; return pos; } -void MaterialStorage::global_variables_instance_free(RID p_instance) { - ERR_FAIL_COND(!global_variables.instance_buffer_pos.has(p_instance)); - int32_t pos = global_variables.instance_buffer_pos[p_instance]; +void MaterialStorage::global_shader_uniforms_instance_free(RID p_instance) { + ERR_FAIL_COND(!global_shader_uniforms.instance_buffer_pos.has(p_instance)); + int32_t pos = global_shader_uniforms.instance_buffer_pos[p_instance]; if (pos >= 0) { - global_variables.buffer_usage[pos].elements = 0; + global_shader_uniforms.buffer_usage[pos].elements = 0; } - global_variables.instance_buffer_pos.erase(p_instance); + global_shader_uniforms.instance_buffer_pos.erase(p_instance); } -void MaterialStorage::global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) { - if (!global_variables.instance_buffer_pos.has(p_instance)) { +void MaterialStorage::global_shader_uniforms_instance_update(RID p_instance, int p_index, const Variant &p_value) { + if (!global_shader_uniforms.instance_buffer_pos.has(p_instance)) { return; //just not allocated, ignore } - int32_t pos = global_variables.instance_buffer_pos[p_instance]; + int32_t pos = global_shader_uniforms.instance_buffer_pos[p_instance]; if (pos < 0) { return; //again, not allocated, ignore @@ -2297,59 +2334,59 @@ void MaterialStorage::global_variables_instance_update(RID p_instance, int p_ind pos += p_index; - _fill_std140_variant_ubo_value(datatype, 0, p_value, (uint8_t *)&global_variables.buffer_values[pos]); - _global_variable_mark_buffer_dirty(pos, 1); + _fill_std140_variant_ubo_value(datatype, 0, p_value, (uint8_t *)&global_shader_uniforms.buffer_values[pos]); + _global_shader_uniform_mark_buffer_dirty(pos, 1); } -void MaterialStorage::_update_global_variables() { +void MaterialStorage::_update_global_shader_uniforms() { MaterialStorage *material_storage = MaterialStorage::get_singleton(); - if (global_variables.buffer_dirty_region_count > 0) { - uint32_t total_regions = global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE; - if (total_regions / global_variables.buffer_dirty_region_count <= 4) { + if (global_shader_uniforms.buffer_dirty_region_count > 0) { + uint32_t total_regions = global_shader_uniforms.buffer_size / GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE; + if (total_regions / global_shader_uniforms.buffer_dirty_region_count <= 4) { // 25% of regions dirty, just update all buffer - glBindBuffer(GL_UNIFORM_BUFFER, global_variables.buffer); - glBufferData(GL_UNIFORM_BUFFER, sizeof(GlobalVariables::Value) * global_variables.buffer_size, global_variables.buffer_values, GL_DYNAMIC_DRAW); + glBindBuffer(GL_UNIFORM_BUFFER, global_shader_uniforms.buffer); + glBufferData(GL_UNIFORM_BUFFER, sizeof(GlobalShaderUniforms::Value) * global_shader_uniforms.buffer_size, global_shader_uniforms.buffer_values, GL_DYNAMIC_DRAW); glBindBuffer(GL_UNIFORM_BUFFER, 0); - memset(global_variables.buffer_dirty_regions, 0, sizeof(bool) * total_regions); + memset(global_shader_uniforms.buffer_dirty_regions, 0, sizeof(bool) * total_regions); } else { - uint32_t region_byte_size = sizeof(GlobalVariables::Value) * GlobalVariables::BUFFER_DIRTY_REGION_SIZE; - glBindBuffer(GL_UNIFORM_BUFFER, global_variables.buffer); + uint32_t region_byte_size = sizeof(GlobalShaderUniforms::Value) * GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE; + glBindBuffer(GL_UNIFORM_BUFFER, global_shader_uniforms.buffer); for (uint32_t i = 0; i < total_regions; i++) { - if (global_variables.buffer_dirty_regions[i]) { - glBufferSubData(GL_UNIFORM_BUFFER, i * region_byte_size, region_byte_size, &global_variables.buffer_values[i * GlobalVariables::BUFFER_DIRTY_REGION_SIZE]); - global_variables.buffer_dirty_regions[i] = false; + if (global_shader_uniforms.buffer_dirty_regions[i]) { + glBufferSubData(GL_UNIFORM_BUFFER, i * region_byte_size, region_byte_size, &global_shader_uniforms.buffer_values[i * GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE]); + global_shader_uniforms.buffer_dirty_regions[i] = false; } } glBindBuffer(GL_UNIFORM_BUFFER, 0); } - global_variables.buffer_dirty_region_count = 0; + global_shader_uniforms.buffer_dirty_region_count = 0; } - if (global_variables.must_update_buffer_materials) { + if (global_shader_uniforms.must_update_buffer_materials) { // only happens in the case of a buffer variable added or removed, // so not often. - for (const RID &E : global_variables.materials_using_buffer) { + for (const RID &E : global_shader_uniforms.materials_using_buffer) { Material *material = material_storage->get_material(E); ERR_CONTINUE(!material); //wtf material_storage->_material_queue_update(material, true, false); } - global_variables.must_update_buffer_materials = false; + global_shader_uniforms.must_update_buffer_materials = false; } - if (global_variables.must_update_texture_materials) { + if (global_shader_uniforms.must_update_texture_materials) { // only happens in the case of a buffer variable added or removed, // so not often. - for (const RID &E : global_variables.materials_using_texture) { + for (const RID &E : global_shader_uniforms.materials_using_texture) { Material *material = material_storage->get_material(E); ERR_CONTINUE(!material); //wtf material_storage->_material_queue_update(material, false, true); } - global_variables.must_update_texture_materials = false; + global_shader_uniforms.must_update_texture_materials = false; } } @@ -2456,11 +2493,18 @@ void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) { for (Material *E : shader->owners) { Material *material = E; - material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL); + material->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MATERIAL); _material_queue_update(material, true, true); } } +void MaterialStorage::shader_set_path_hint(RID p_shader, const String &p_path) { + GLES3::Shader *shader = shader_owner.get_or_null(p_shader); + ERR_FAIL_COND(!shader); + + shader->path_hint = p_path; +} + String MaterialStorage::shader_get_code(RID p_shader) const { const GLES3::Shader *shader = shader_owner.get_or_null(p_shader); ERR_FAIL_COND_V(!shader, String()); @@ -2593,7 +2637,7 @@ void MaterialStorage::material_set_shader(RID p_material, RID p_shader) { } if (p_shader.is_null()) { - material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL); + material->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MATERIAL); material->shader_id = 0; return; } @@ -2616,7 +2660,7 @@ void MaterialStorage::material_set_shader(RID p_material, RID p_shader) { material->data->set_next_pass(material->next_pass); material->data->set_render_priority(material->priority); //updating happens later - material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL); + material->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MATERIAL); _material_queue_update(material, true, true); } @@ -2662,7 +2706,7 @@ void MaterialStorage::material_set_next_pass(RID p_material, RID p_next_material material->data->set_next_pass(p_next_material); } - material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL); + material->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MATERIAL); } void MaterialStorage::material_set_render_priority(RID p_material, int priority) { @@ -2715,7 +2759,7 @@ void MaterialStorage::material_get_instance_shader_parameters(RID p_material, Li } } -void MaterialStorage::material_update_dependency(RID p_material, RendererStorage::DependencyTracker *p_instance) { +void MaterialStorage::material_update_dependency(RID p_material, DependencyTracker *p_instance) { Material *material = material_owner.get_or_null(p_material); ERR_FAIL_COND(!material); p_instance->update_dependency(&material->dependency); @@ -2832,7 +2876,22 @@ void CanvasShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { } } + String last_group; for (const KeyValue<int, StringName> &E : order) { + String group = uniforms[E.value].group; + if (!uniforms[E.value].subgroup.is_empty()) { + group += "::" + uniforms[E.value].subgroup; + } + + if (group != last_group) { + PropertyInfo pi; + pi.usage = PROPERTY_USAGE_GROUP; + pi.name = group; + p_param_list->push_back(pi); + + last_group = group; + } + PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]); pi.name = E.value; p_param_list->push_back(pi); @@ -3055,7 +3114,22 @@ void SkyShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { } } + String last_group; for (const KeyValue<int, StringName> &E : order) { + String group = uniforms[E.value].group; + if (!uniforms[E.value].subgroup.is_empty()) { + group += "::" + uniforms[E.value].subgroup; + } + + if (group != last_group) { + PropertyInfo pi; + pi.usage = PROPERTY_USAGE_GROUP; + pi.name = group; + p_param_list->push_back(pi); + + last_group = group; + } + PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]); pi.name = E.value; p_param_list->push_back(pi); @@ -3365,7 +3439,22 @@ void SceneShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { } } + String last_group; for (const KeyValue<int, StringName> &E : order) { + String group = uniforms[E.value].group; + if (!uniforms[E.value].subgroup.is_empty()) { + group += "::" + uniforms[E.value].subgroup; + } + + if (group != last_group) { + PropertyInfo pi; + pi.usage = PROPERTY_USAGE_GROUP; + pi.name = group; + p_param_list->push_back(pi); + + last_group = group; + } + PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]); pi.name = E.value; p_param_list->push_back(pi); diff --git a/drivers/gles3/storage/material_storage.h b/drivers/gles3/storage/material_storage.h index 09f6680bec..8fc15ddcba 100644 --- a/drivers/gles3/storage/material_storage.h +++ b/drivers/gles3/storage/material_storage.h @@ -37,10 +37,10 @@ #include "core/templates/rid_owner.h" #include "core/templates/self_list.h" #include "servers/rendering/renderer_compositor.h" -#include "servers/rendering/renderer_storage.h" #include "servers/rendering/shader_compiler.h" #include "servers/rendering/shader_language.h" #include "servers/rendering/storage/material_storage.h" +#include "servers/rendering/storage/utilities.h" #include "../shaders/canvas.glsl.gen.h" #include "../shaders/cubemap_filter.glsl.gen.h" @@ -73,6 +73,7 @@ struct Material; struct Shader { ShaderData *data = nullptr; String code; + String path_hint; RS::ShaderMode mode; HashMap<StringName, HashMap<int, RID>> default_texture_parameter; HashSet<Material *> owners; @@ -125,7 +126,7 @@ struct Material { RID next_pass; SelfList<Material> update_element; - RendererStorage::Dependency dependency; + Dependency dependency; Material() : update_element(this) {} @@ -364,15 +365,15 @@ struct SceneMaterialData : public MaterialData { MaterialData *_create_scene_material_func(ShaderData *p_shader); -/* Global variable structs */ -struct GlobalVariables { +/* Global shader uniform structs */ +struct GlobalShaderUniforms { enum { BUFFER_DIRTY_REGION_SIZE = 1024 }; struct Variable { HashSet<RID> texture_materials; // materials using this - RS::GlobalVariableType type; + RS::GlobalShaderUniformType type; Variant value; Variant override; int32_t buffer_index; //for vectors @@ -428,13 +429,13 @@ private: friend struct MaterialData; static MaterialStorage *singleton; - /* GLOBAL VARIABLE API */ + /* GLOBAL SHADER UNIFORM API */ - GlobalVariables global_variables; + GlobalShaderUniforms global_shader_uniforms; - int32_t _global_variable_allocate(uint32_t p_elements); - void _global_variable_store_in_buffer(int32_t p_index, RS::GlobalVariableType p_type, const Variant &p_value); - void _global_variable_mark_buffer_dirty(int32_t p_index, int32_t p_elements); + int32_t _global_shader_uniform_allocate(uint32_t p_elements); + void _global_shader_uniform_store_in_buffer(int32_t p_index, RS::GlobalShaderUniformType p_type, const Variant &p_value); + void _global_shader_uniform_mark_buffer_dirty(int32_t p_index, int32_t p_elements); /* SHADER API */ @@ -453,6 +454,48 @@ public: MaterialStorage(); virtual ~MaterialStorage(); + static _FORCE_INLINE_ void store_transform(const Transform3D &p_mtx, float *p_array) { + p_array[0] = p_mtx.basis.rows[0][0]; + p_array[1] = p_mtx.basis.rows[1][0]; + p_array[2] = p_mtx.basis.rows[2][0]; + p_array[3] = 0; + p_array[4] = p_mtx.basis.rows[0][1]; + p_array[5] = p_mtx.basis.rows[1][1]; + p_array[6] = p_mtx.basis.rows[2][1]; + p_array[7] = 0; + p_array[8] = p_mtx.basis.rows[0][2]; + p_array[9] = p_mtx.basis.rows[1][2]; + p_array[10] = p_mtx.basis.rows[2][2]; + p_array[11] = 0; + p_array[12] = p_mtx.origin.x; + p_array[13] = p_mtx.origin.y; + p_array[14] = p_mtx.origin.z; + p_array[15] = 1; + } + + static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_mtx, float *p_array) { + p_array[0] = p_mtx.rows[0][0]; + p_array[1] = p_mtx.rows[1][0]; + p_array[2] = p_mtx.rows[2][0]; + p_array[3] = 0; + p_array[4] = p_mtx.rows[0][1]; + p_array[5] = p_mtx.rows[1][1]; + p_array[6] = p_mtx.rows[2][1]; + p_array[7] = 0; + p_array[8] = p_mtx.rows[0][2]; + p_array[9] = p_mtx.rows[1][2]; + p_array[10] = p_mtx.rows[2][2]; + p_array[11] = 0; + } + + static _FORCE_INLINE_ void store_camera(const Projection &p_mtx, float *p_array) { + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + p_array[i * 4 + j] = p_mtx.matrix[i][j]; + } + } + } + struct Shaders { CanvasShaderGLES3 canvas_shader; SkyShaderGLES3 sky_shader; @@ -465,28 +508,28 @@ public: ShaderCompiler compiler_sky; } shaders; - /* GLOBAL VARIABLE API */ + /* GLOBAL SHADER UNIFORM API */ - void _update_global_variables(); + void _update_global_shader_uniforms(); - virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) override; - virtual void global_variable_remove(const StringName &p_name) override; - virtual Vector<StringName> global_variable_get_list() const override; + virtual void global_shader_uniform_add(const StringName &p_name, RS::GlobalShaderUniformType p_type, const Variant &p_value) override; + virtual void global_shader_uniform_remove(const StringName &p_name) override; + virtual Vector<StringName> global_shader_uniform_get_list() const override; - virtual void global_variable_set(const StringName &p_name, const Variant &p_value) override; - virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value) override; - virtual Variant global_variable_get(const StringName &p_name) const override; - virtual RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const override; - RS::GlobalVariableType global_variable_get_type_internal(const StringName &p_name) const; + virtual void global_shader_uniform_set(const StringName &p_name, const Variant &p_value) override; + virtual void global_shader_uniform_set_override(const StringName &p_name, const Variant &p_value) override; + virtual Variant global_shader_uniform_get(const StringName &p_name) const override; + virtual RS::GlobalShaderUniformType global_shader_uniform_get_type(const StringName &p_name) const override; + RS::GlobalShaderUniformType global_shader_uniform_get_type_internal(const StringName &p_name) const; - virtual void global_variables_load_settings(bool p_load_textures = true) override; - virtual void global_variables_clear() override; + virtual void global_shader_uniforms_load_settings(bool p_load_textures = true) override; + virtual void global_shader_uniforms_clear() override; - virtual int32_t global_variables_instance_allocate(RID p_instance) override; - virtual void global_variables_instance_free(RID p_instance) override; - virtual void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) override; + virtual int32_t global_shader_uniforms_instance_allocate(RID p_instance) override; + virtual void global_shader_uniforms_instance_free(RID p_instance) override; + virtual void global_shader_uniforms_instance_update(RID p_instance, int p_index, const Variant &p_value) override; - GLuint global_variables_get_uniform_buffer() const; + GLuint global_shader_uniforms_get_uniform_buffer() const; /* SHADER API */ @@ -500,6 +543,7 @@ public: virtual void shader_free(RID p_rid) override; virtual void shader_set_code(RID p_shader, const String &p_code) override; + virtual void shader_set_path_hint(RID p_shader, const String &p_path) override; virtual String shader_get_code(RID p_shader) const override; virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const override; @@ -534,7 +578,7 @@ public: virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) override; - virtual void material_update_dependency(RID p_material, RendererStorage::DependencyTracker *p_instance) override; + virtual void material_update_dependency(RID p_material, DependencyTracker *p_instance) override; _FORCE_INLINE_ uint32_t material_get_shader_id(RID p_material) { Material *material = material_owner.get_or_null(p_material); @@ -555,4 +599,4 @@ public: #endif // GLES3_ENABLED -#endif // !MATERIAL_STORAGE_GLES3_H +#endif // MATERIAL_STORAGE_GLES3_H diff --git a/drivers/gles3/storage/mesh_storage.cpp b/drivers/gles3/storage/mesh_storage.cpp index 5aa82bfcc1..88b81805fa 100644 --- a/drivers/gles3/storage/mesh_storage.cpp +++ b/drivers/gles3/storage/mesh_storage.cpp @@ -31,8 +31,8 @@ #ifdef GLES3_ENABLED #include "mesh_storage.h" -#include "../rasterizer_storage_gles3.h" #include "material_storage.h" +#include "utilities.h" using namespace GLES3; @@ -64,6 +64,8 @@ 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); + mesh->dependency.deleted_notify(p_rid); if (mesh->instances.size()) { ERR_PRINT("deleting mesh with active instances"); @@ -72,7 +74,7 @@ void MeshStorage::mesh_free(RID p_rid) { for (Mesh *E : mesh->shadow_owners) { Mesh *shadow_owner = E; shadow_owner->shadow_mesh = RID(); - shadow_owner->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH); + shadow_owner->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MESH); } } mesh_owner.free(p_rid); @@ -268,12 +270,12 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) _mesh_instance_add_surface(mi, mesh, mesh->surface_count - 1); } - mesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH); + mesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MESH); for (Mesh *E : mesh->shadow_owners) { Mesh *shadow_owner = E; shadow_owner->shadow_mesh = RID(); - shadow_owner->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH); + shadow_owner->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MESH); } mesh->material_cache.clear(); @@ -314,7 +316,7 @@ void MeshStorage::mesh_surface_set_material(RID p_mesh, int p_surface, RID p_mat ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count); mesh->surfaces[p_surface]->material = p_material; - mesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL); + mesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MATERIAL); mesh->material_cache.clear(); } @@ -335,10 +337,10 @@ RS::SurfaceData MeshStorage::mesh_get_surface(RID p_mesh, int p_surface) const { RS::SurfaceData sd; sd.format = s.format; - sd.vertex_data = RasterizerStorageGLES3::buffer_get_data(GL_ARRAY_BUFFER, s.vertex_buffer, s.vertex_buffer_size); + sd.vertex_data = Utilities::buffer_get_data(GL_ARRAY_BUFFER, s.vertex_buffer, s.vertex_buffer_size); if (s.attribute_buffer != 0) { - sd.attribute_data = RasterizerStorageGLES3::buffer_get_data(GL_ARRAY_BUFFER, s.attribute_buffer, s.attribute_buffer_size); + sd.attribute_data = Utilities::buffer_get_data(GL_ARRAY_BUFFER, s.attribute_buffer, s.attribute_buffer_size); } sd.vertex_count = s.vertex_count; @@ -346,14 +348,14 @@ RS::SurfaceData MeshStorage::mesh_get_surface(RID p_mesh, int p_surface) const { sd.primitive = s.primitive; if (sd.index_count) { - sd.index_data = RasterizerStorageGLES3::buffer_get_data(GL_ELEMENT_ARRAY_BUFFER, s.index_buffer, s.index_buffer_size); + sd.index_data = Utilities::buffer_get_data(GL_ELEMENT_ARRAY_BUFFER, s.index_buffer, s.index_buffer_size); } sd.aabb = s.aabb; for (uint32_t i = 0; i < s.lod_count; i++) { RS::SurfaceData::LOD lod; lod.edge_length = s.lods[i].edge_length; - lod.index_data = RasterizerStorageGLES3::buffer_get_data(GL_ELEMENT_ARRAY_BUFFER, s.lods[i].index_buffer, s.lods[i].index_buffer_size); + lod.index_data = Utilities::buffer_get_data(GL_ELEMENT_ARRAY_BUFFER, s.lods[i].index_buffer, s.lods[i].index_buffer_size); sd.lods.push_back(lod); } @@ -504,7 +506,7 @@ void MeshStorage::mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) { shadow_mesh->shadow_owners.insert(mesh); } - mesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH); + mesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MESH); } void MeshStorage::mesh_clear(RID p_mesh) { @@ -553,12 +555,12 @@ void MeshStorage::mesh_clear(RID p_mesh) { _mesh_instance_clear(mi); } mesh->has_bone_weights = false; - mesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH); + mesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MESH); for (Mesh *E : mesh->shadow_owners) { Mesh *shadow_owner = E; shadow_owner->shadow_mesh = RID(); - shadow_owner->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH); + shadow_owner->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MESH); } } @@ -899,7 +901,7 @@ void MeshStorage::multimesh_allocate_data(RID p_multimesh, int p_instances, RS:: glBindBuffer(GL_ARRAY_BUFFER, 0); } - multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MULTIMESH); + multimesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MULTIMESH); } int MeshStorage::multimesh_get_instance_count(RID p_multimesh) const { @@ -926,14 +928,14 @@ void MeshStorage::multimesh_set_mesh(RID p_multimesh, RID p_mesh) { } else if (multimesh->instances) { // Need to re-create AABB. Unfortunately, calling this has a penalty. if (multimesh->buffer_set) { - Vector<uint8_t> buffer = RasterizerStorageGLES3::buffer_get_data(GL_ARRAY_BUFFER, multimesh->buffer, multimesh->instances * multimesh->stride_cache * sizeof(float)); + Vector<uint8_t> buffer = Utilities::buffer_get_data(GL_ARRAY_BUFFER, multimesh->buffer, multimesh->instances * multimesh->stride_cache * sizeof(float)); const uint8_t *r = buffer.ptr(); const float *data = (const float *)r; _multimesh_re_create_aabb(multimesh, data, multimesh->instances); } } - multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH); + multimesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MESH); } #define MULTIMESH_DIRTY_REGION_SIZE 512 @@ -950,7 +952,7 @@ void MeshStorage::_multimesh_make_local(MultiMesh *multimesh) const { float *w = multimesh->data_cache.ptrw(); if (multimesh->buffer_set) { - Vector<uint8_t> buffer = RasterizerStorageGLES3::buffer_get_data(GL_ARRAY_BUFFER, multimesh->buffer, multimesh->instances * multimesh->stride_cache * sizeof(float)); + Vector<uint8_t> buffer = Utilities::buffer_get_data(GL_ARRAY_BUFFER, multimesh->buffer, multimesh->instances * multimesh->stride_cache * sizeof(float)); { const uint8_t *r = buffer.ptr(); @@ -1348,7 +1350,7 @@ void MeshStorage::multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_b const float *data = multimesh->data_cache.ptr(); _multimesh_re_create_aabb(multimesh, data, multimesh->instances); - multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB); + multimesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB); } } @@ -1363,7 +1365,7 @@ Vector<float> MeshStorage::multimesh_get_buffer(RID p_multimesh) const { } else { // Buffer not cached, so fetch from GPU memory. This can be a stalling operation, avoid whenever possible. - Vector<uint8_t> buffer = RasterizerStorageGLES3::buffer_get_data(GL_ARRAY_BUFFER, multimesh->buffer, multimesh->instances * multimesh->stride_cache * sizeof(float)); + Vector<uint8_t> buffer = Utilities::buffer_get_data(GL_ARRAY_BUFFER, multimesh->buffer, multimesh->instances * multimesh->stride_cache * sizeof(float)); ret.resize(multimesh->instances * multimesh->stride_cache); { float *w = ret.ptrw(); @@ -1439,7 +1441,7 @@ void MeshStorage::multimesh_set_visible_instances(RID p_multimesh, int p_visible multimesh->visible_instances = p_visible; - multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES); + multimesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES); } int MeshStorage::multimesh_get_visible_instances(RID p_multimesh) const { @@ -1493,7 +1495,7 @@ void MeshStorage::_update_dirty_multimeshes() { if (multimesh->aabb_dirty && multimesh->mesh.is_valid()) { _multimesh_re_create_aabb(multimesh, data, visible_instances); multimesh->aabb_dirty = false; - multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB); + multimesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB); } } @@ -1542,7 +1544,12 @@ Transform2D MeshStorage::skeleton_bone_get_transform_2d(RID p_skeleton, int p_bo return Transform2D(); } -void MeshStorage::skeleton_update_dependency(RID p_base, RendererStorage::DependencyTracker *p_instance) { +void MeshStorage::skeleton_update_dependency(RID p_base, DependencyTracker *p_instance) { +} + +/* OCCLUDER */ + +void MeshStorage::occluder_set_mesh(RID p_occluder, const PackedVector3Array &p_vertices, const PackedInt32Array &p_indices) { } #endif // GLES3_ENABLED diff --git a/drivers/gles3/storage/mesh_storage.h b/drivers/gles3/storage/mesh_storage.h index 3bb7061413..339380b3b0 100644 --- a/drivers/gles3/storage/mesh_storage.h +++ b/drivers/gles3/storage/mesh_storage.h @@ -37,6 +37,7 @@ #include "core/templates/rid_owner.h" #include "core/templates/self_list.h" #include "servers/rendering/storage/mesh_storage.h" +#include "servers/rendering/storage/utilities.h" #include "platform_config.h" #ifndef OPENGL_INCLUDE_H @@ -126,7 +127,7 @@ struct Mesh { RID shadow_mesh; HashSet<Mesh *> shadow_owners; - RendererStorage::Dependency dependency; + Dependency dependency; }; /* Mesh Instance */ @@ -179,7 +180,7 @@ struct MultiMesh { bool dirty = false; MultiMesh *dirty_list = nullptr; - RendererStorage::Dependency dependency; + Dependency dependency; }; struct Skeleton { @@ -194,7 +195,7 @@ struct Skeleton { uint64_t version = 1; - RendererStorage::Dependency dependency; + Dependency dependency; }; class MeshStorage : public RendererMeshStorage { @@ -531,11 +532,15 @@ public: virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) override; virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const override; - virtual void skeleton_update_dependency(RID p_base, RendererStorage::DependencyTracker *p_instance) override; + virtual void skeleton_update_dependency(RID p_base, DependencyTracker *p_instance) override; + + /* OCCLUDER */ + + void occluder_set_mesh(RID p_occluder, const PackedVector3Array &p_vertices, const PackedInt32Array &p_indices); }; } // namespace GLES3 #endif // GLES3_ENABLED -#endif // !MESH_STORAGE_GLES3_H +#endif // MESH_STORAGE_GLES3_H diff --git a/drivers/gles3/storage/particles_storage.h b/drivers/gles3/storage/particles_storage.h index cf47ada5d5..84d1f94d8c 100644 --- a/drivers/gles3/storage/particles_storage.h +++ b/drivers/gles3/storage/particles_storage.h @@ -137,4 +137,4 @@ public: #endif // GLES3_ENABLED -#endif // !PARTICLES_STORAGE_GLES3_H +#endif // PARTICLES_STORAGE_GLES3_H diff --git a/drivers/gles3/storage/texture_storage.cpp b/drivers/gles3/storage/texture_storage.cpp index 42c80da39a..c05f516548 100644 --- a/drivers/gles3/storage/texture_storage.cpp +++ b/drivers/gles3/storage/texture_storage.cpp @@ -183,6 +183,12 @@ TextureStorage::TextureStorage() { texture.gl_set_filter(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST); } } + + glBindTexture(GL_TEXTURE_2D, 0); + +#ifdef GLES_OVER_GL + glEnable(GL_PROGRAM_POINT_SIZE); +#endif } TextureStorage::~TextureStorage() { @@ -244,6 +250,55 @@ void TextureStorage::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS: ct->texture_repeat = p_repeat; } +/* CANVAS SHADOW */ + +RID TextureStorage::canvas_light_shadow_buffer_create(int p_width) { + Config *config = Config::get_singleton(); + CanvasLightShadow *cls = memnew(CanvasLightShadow); + + if (p_width > config->max_texture_size) { + p_width = config->max_texture_size; + } + + cls->size = p_width; + cls->height = 16; + + glActiveTexture(GL_TEXTURE0); + + glGenFramebuffers(1, &cls->fbo); + glBindFramebuffer(GL_FRAMEBUFFER, cls->fbo); + + glGenRenderbuffers(1, &cls->depth); + glBindRenderbuffer(GL_RENDERBUFFER, cls->depth); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, cls->size, cls->height); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, cls->depth); + + glGenTextures(1, &cls->distance); + glBindTexture(GL_TEXTURE_2D, cls->distance); + if (config->use_rgba_2d_shadows) { + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, cls->size, cls->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + } else { + glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, cls->size, cls->height, 0, GL_RED, GL_FLOAT, nullptr); + } + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, cls->distance, 0); + + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + //printf("errnum: %x\n",status); + glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo); + + if (status != GL_FRAMEBUFFER_COMPLETE) { + memdelete(cls); + ERR_FAIL_COND_V(status != GL_FRAMEBUFFER_COMPLETE, RID()); + } + + return canvas_light_shadow_owner.make_rid(cls); +} + /* Texture API */ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool p_force_decompress) const { diff --git a/drivers/gles3/storage/texture_storage.h b/drivers/gles3/storage/texture_storage.h index d6d04e45a1..77ec1da6f5 100644 --- a/drivers/gles3/storage/texture_storage.h +++ b/drivers/gles3/storage/texture_storage.h @@ -132,6 +132,17 @@ struct CanvasTexture { bool cleared_cache = true; }; +/* CANVAS SHADOW */ + +struct CanvasLightShadow { + RID self; + int size; + int height; + GLuint fbo; + GLuint depth; + GLuint distance; //for older devices +}; + struct RenderTarget; struct Texture { @@ -364,6 +375,10 @@ private: RID_Owner<CanvasTexture, true> canvas_texture_owner; + /* CANVAS SHADOW */ + + RID_PtrOwner<CanvasLightShadow> canvas_light_shadow_owner; + /* Texture API */ mutable RID_Owner<Texture> texture_owner; @@ -403,6 +418,10 @@ public: virtual void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) override; virtual void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) override; + /* CANVAS SHADOW */ + + RID canvas_light_shadow_buffer_create(int p_width); + /* Texture API */ Texture *get_texture(RID p_rid) { @@ -527,6 +546,16 @@ public: void render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region, bool p_gen_mipmaps); void render_target_clear_back_buffer(RID p_render_target, const Rect2i &p_region, const Color &p_color); void render_target_gen_back_buffer_mipmaps(RID p_render_target, const Rect2i &p_region); + virtual void render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) override{}; + virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) override{}; + + void bind_framebuffer(GLuint framebuffer) { + glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); + } + + void bind_framebuffer_system() { + glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo); + } String get_framebuffer_error(GLenum p_status); }; @@ -548,6 +577,6 @@ inline String TextureStorage::get_framebuffer_error(GLenum p_status) { } // namespace GLES3 -#endif // !GLES3_ENABLED +#endif // GLES3_ENABLED -#endif // !TEXTURE_STORAGE_GLES3_H +#endif // TEXTURE_STORAGE_GLES3_H diff --git a/drivers/gles3/storage/utilities.cpp b/drivers/gles3/storage/utilities.cpp new file mode 100644 index 0000000000..654104722b --- /dev/null +++ b/drivers/gles3/storage/utilities.cpp @@ -0,0 +1,353 @@ +/*************************************************************************/ +/* utilities.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* 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. */ +/*************************************************************************/ + +#ifdef GLES3_ENABLED + +#include "utilities.h" +#include "config.h" +#include "light_storage.h" +#include "material_storage.h" +#include "mesh_storage.h" +#include "particles_storage.h" +#include "texture_storage.h" + +using namespace GLES3; + +Utilities *Utilities::singleton = nullptr; + +Utilities::Utilities() { + singleton = this; +} + +Utilities::~Utilities() { + singleton = nullptr; +} + +Vector<uint8_t> Utilities::buffer_get_data(GLenum p_target, GLuint p_buffer, uint32_t p_buffer_size) { + Vector<uint8_t> ret; + ret.resize(p_buffer_size); + glBindBuffer(p_target, p_buffer); + +#if defined(__EMSCRIPTEN__) + { + uint8_t *w = ret.ptrw(); + glGetBufferSubData(p_target, 0, p_buffer_size, w); + } +#else + void *data = glMapBufferRange(p_target, 0, p_buffer_size, GL_MAP_READ_BIT); + ERR_FAIL_NULL_V(data, Vector<uint8_t>()); + { + uint8_t *w = ret.ptrw(); + memcpy(w, data, p_buffer_size); + } + glUnmapBuffer(p_target); +#endif + glBindBuffer(p_target, 0); + return ret; +} + +/* INSTANCES */ + +RS::InstanceType Utilities::get_base_type(RID p_rid) const { + if (GLES3::MeshStorage::get_singleton()->owns_mesh(p_rid)) { + return RS::INSTANCE_MESH; + } else if (GLES3::MeshStorage::get_singleton()->owns_multimesh(p_rid)) { + return RS::INSTANCE_MULTIMESH; + } else if (GLES3::LightStorage::get_singleton()->owns_light(p_rid)) { + return RS::INSTANCE_LIGHT; + } + return RS::INSTANCE_NONE; +} + +bool Utilities::free(RID p_rid) { + if (GLES3::TextureStorage::get_singleton()->owns_render_target(p_rid)) { + GLES3::TextureStorage::get_singleton()->render_target_free(p_rid); + return true; + } else if (GLES3::TextureStorage::get_singleton()->owns_texture(p_rid)) { + GLES3::TextureStorage::get_singleton()->texture_free(p_rid); + return true; + } else if (GLES3::TextureStorage::get_singleton()->owns_canvas_texture(p_rid)) { + GLES3::TextureStorage::get_singleton()->canvas_texture_free(p_rid); + return true; + } else if (GLES3::MaterialStorage::get_singleton()->owns_shader(p_rid)) { + GLES3::MaterialStorage::get_singleton()->shader_free(p_rid); + return true; + } else if (GLES3::MaterialStorage::get_singleton()->owns_material(p_rid)) { + GLES3::MaterialStorage::get_singleton()->material_free(p_rid); + return true; + } else if (GLES3::MeshStorage::get_singleton()->owns_mesh(p_rid)) { + GLES3::MeshStorage::get_singleton()->mesh_free(p_rid); + return true; + } else if (GLES3::MeshStorage::get_singleton()->owns_multimesh(p_rid)) { + GLES3::MeshStorage::get_singleton()->multimesh_free(p_rid); + return true; + } else if (GLES3::MeshStorage::get_singleton()->owns_mesh_instance(p_rid)) { + GLES3::MeshStorage::get_singleton()->mesh_instance_free(p_rid); + return true; + } else if (GLES3::LightStorage::get_singleton()->owns_light(p_rid)) { + GLES3::LightStorage::get_singleton()->light_free(p_rid); + return true; + } else { + return false; + } + /* + else if (reflection_probe_owner.owns(p_rid)) { + // delete the texture + ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_rid); + reflection_probe->instance_remove_deps(); + + reflection_probe_owner.free(p_rid); + memdelete(reflection_probe); + + return true; + } else if (lightmap_capture_data_owner.owns(p_rid)) { + // delete the texture + LightmapCapture *lightmap_capture = lightmap_capture_data_owner.get_or_null(p_rid); + lightmap_capture->instance_remove_deps(); + + lightmap_capture_data_owner.free(p_rid); + memdelete(lightmap_capture); + return true; + + } else if (canvas_occluder_owner.owns(p_rid)) { + CanvasOccluder *co = canvas_occluder_owner.get_or_null(p_rid); + if (co->index_id) { + glDeleteBuffers(1, &co->index_id); + } + if (co->vertex_id) { + glDeleteBuffers(1, &co->vertex_id); + } + + canvas_occluder_owner.free(p_rid); + memdelete(co); + + return true; + + } else if (canvas_light_shadow_owner.owns(p_rid)) { + CanvasLightShadow *cls = canvas_light_shadow_owner.get_or_null(p_rid); + glDeleteFramebuffers(1, &cls->fbo); + glDeleteRenderbuffers(1, &cls->depth); + glDeleteTextures(1, &cls->distance); + canvas_light_shadow_owner.free(p_rid); + memdelete(cls); + + return true; + } + */ +} + +/* DEPENDENCIES */ + +void Utilities::base_update_dependency(RID p_base, DependencyTracker *p_instance) { + if (MeshStorage::get_singleton()->owns_mesh(p_base)) { + Mesh *mesh = MeshStorage::get_singleton()->get_mesh(p_base); + p_instance->update_dependency(&mesh->dependency); + } else if (MeshStorage::get_singleton()->owns_multimesh(p_base)) { + MultiMesh *multimesh = MeshStorage::get_singleton()->get_multimesh(p_base); + p_instance->update_dependency(&multimesh->dependency); + if (multimesh->mesh.is_valid()) { + base_update_dependency(multimesh->mesh, p_instance); + } + } else if (LightStorage::get_singleton()->owns_light(p_base)) { + Light *l = LightStorage::get_singleton()->get_light(p_base); + p_instance->update_dependency(&l->dependency); + } +} + +/* VISIBILITY NOTIFIER */ + +RID Utilities::visibility_notifier_allocate() { + return RID(); +} + +void Utilities::visibility_notifier_initialize(RID p_notifier) { +} + +void Utilities::visibility_notifier_free(RID p_notifier) { +} + +void Utilities::visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb) { +} + +void Utilities::visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable) { +} + +AABB Utilities::visibility_notifier_get_aabb(RID p_notifier) const { + return AABB(); +} + +void Utilities::visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) { +} + +/* TIMING */ + +//void Utilities::render_info_begin_capture() { +// info.snap = info.render; +//} + +//void Utilities::render_info_end_capture() { +// info.snap.object_count = info.render.object_count - info.snap.object_count; +// info.snap.draw_call_count = info.render.draw_call_count - info.snap.draw_call_count; +// info.snap.material_switch_count = info.render.material_switch_count - info.snap.material_switch_count; +// info.snap.surface_switch_count = info.render.surface_switch_count - info.snap.surface_switch_count; +// info.snap.shader_rebind_count = info.render.shader_rebind_count - info.snap.shader_rebind_count; +// info.snap.vertices_count = info.render.vertices_count - info.snap.vertices_count; +// info.snap._2d_item_count = info.render._2d_item_count - info.snap._2d_item_count; +// info.snap._2d_draw_call_count = info.render._2d_draw_call_count - info.snap._2d_draw_call_count; +//} + +//int Utilities::get_captured_render_info(RS::RenderInfo p_info) { +// switch (p_info) { +// case RS::INFO_OBJECTS_IN_FRAME: { +// return info.snap.object_count; +// } break; +// case RS::INFO_VERTICES_IN_FRAME: { +// return info.snap.vertices_count; +// } break; +// case RS::INFO_MATERIAL_CHANGES_IN_FRAME: { +// return info.snap.material_switch_count; +// } break; +// case RS::INFO_SHADER_CHANGES_IN_FRAME: { +// return info.snap.shader_rebind_count; +// } break; +// case RS::INFO_SURFACE_CHANGES_IN_FRAME: { +// return info.snap.surface_switch_count; +// } break; +// case RS::INFO_DRAW_CALLS_IN_FRAME: { +// return info.snap.draw_call_count; +// } break; +// /* +// case RS::INFO_2D_ITEMS_IN_FRAME: { +// return info.snap._2d_item_count; +// } break; +// case RS::INFO_2D_DRAW_CALLS_IN_FRAME: { +// return info.snap._2d_draw_call_count; +// } break; +// */ +// default: { +// return get_render_info(p_info); +// } +// } +//} + +//int Utilities::get_render_info(RS::RenderInfo p_info) { +// switch (p_info) { +// case RS::INFO_OBJECTS_IN_FRAME: +// return info.render_final.object_count; +// case RS::INFO_VERTICES_IN_FRAME: +// return info.render_final.vertices_count; +// case RS::INFO_MATERIAL_CHANGES_IN_FRAME: +// return info.render_final.material_switch_count; +// case RS::INFO_SHADER_CHANGES_IN_FRAME: +// return info.render_final.shader_rebind_count; +// case RS::INFO_SURFACE_CHANGES_IN_FRAME: +// return info.render_final.surface_switch_count; +// case RS::INFO_DRAW_CALLS_IN_FRAME: +// return info.render_final.draw_call_count; +// /* +// case RS::INFO_2D_ITEMS_IN_FRAME: +// return info.render_final._2d_item_count; +// case RS::INFO_2D_DRAW_CALLS_IN_FRAME: +// return info.render_final._2d_draw_call_count; +//*/ +// case RS::INFO_USAGE_VIDEO_MEM_TOTAL: +// return 0; //no idea +// case RS::INFO_VIDEO_MEM_USED: +// return info.vertex_mem + info.texture_mem; +// case RS::INFO_TEXTURE_MEM_USED: +// return info.texture_mem; +// case RS::INFO_VERTEX_MEM_USED: +// return info.vertex_mem; +// default: +// return 0; //no idea either +// } +//} + +/* MISC */ + +void Utilities::update_dirty_resources() { + MaterialStorage::get_singleton()->_update_global_shader_uniforms(); + MaterialStorage::get_singleton()->_update_queued_materials(); + //MeshStorage::get_singleton()->_update_dirty_skeletons(); + MeshStorage::get_singleton()->_update_dirty_multimeshes(); +} + +void Utilities::set_debug_generate_wireframes(bool p_generate) { +} + +bool Utilities::has_os_feature(const String &p_feature) const { + Config *config = Config::get_singleton(); + if (!config) { + return false; + } + + if (p_feature == "rgtc") { + return config->rgtc_supported; + } + + if (p_feature == "s3tc") { + return config->s3tc_supported; + } + + if (p_feature == "bptc") { + return config->bptc_supported; + } + + if (p_feature == "etc" || p_feature == "etc2") { + return config->etc2_supported; + } + + return false; +} + +void Utilities::update_memory_info() { +} + +uint64_t Utilities::get_rendering_info(RS::RenderingInfo p_info) { + return 0; +} + +String Utilities::get_video_adapter_name() const { + return (const char *)glGetString(GL_RENDERER); +} + +String Utilities::get_video_adapter_vendor() const { + return (const char *)glGetString(GL_VENDOR); +} + +RenderingDevice::DeviceType Utilities::get_video_adapter_type() const { + return RenderingDevice::DeviceType::DEVICE_TYPE_OTHER; +} + +String Utilities::get_video_adapter_api_version() const { + return (const char *)glGetString(GL_VERSION); +} + +#endif // GLES3_ENABLED diff --git a/drivers/gles3/storage/utilities.h b/drivers/gles3/storage/utilities.h new file mode 100644 index 0000000000..e054f2f816 --- /dev/null +++ b/drivers/gles3/storage/utilities.h @@ -0,0 +1,159 @@ +/*************************************************************************/ +/* utilities.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* 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 UTILITIES_GLES3_H +#define UTILITIES_GLES3_H + +#ifdef GLES3_ENABLED + +#include "servers/rendering/storage/utilities.h" + +#include "platform_config.h" +#ifndef OPENGL_INCLUDE_H +#include <GLES3/gl3.h> +#else +#include OPENGL_INCLUDE_H +#endif + +namespace GLES3 { + +class Utilities : public RendererUtilities { +private: + static Utilities *singleton; + +public: + static Utilities *get_singleton() { return singleton; } + + Utilities(); + ~Utilities(); + + // Buffer size is specified in bytes + static Vector<uint8_t> buffer_get_data(GLenum p_target, GLuint p_buffer, uint32_t p_buffer_size); + + /* INSTANCES */ + + virtual RS::InstanceType get_base_type(RID p_rid) const override; + virtual bool free(RID p_rid) override; + + /* DEPENDENCIES */ + + virtual void base_update_dependency(RID p_base, DependencyTracker *p_instance) override; + + /* VISIBILITY NOTIFIER */ + virtual RID visibility_notifier_allocate() override; + virtual void visibility_notifier_initialize(RID p_notifier) override; + virtual void visibility_notifier_free(RID p_notifier) override; + + virtual void visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb) override; + virtual void visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable) override; + + virtual AABB visibility_notifier_get_aabb(RID p_notifier) const override; + virtual void visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) override; + + /* TIMING */ + + struct Info { + uint64_t texture_mem = 0; + uint64_t vertex_mem = 0; + + struct Render { + uint32_t object_count; + uint32_t draw_call_count; + uint32_t material_switch_count; + uint32_t surface_switch_count; + uint32_t shader_rebind_count; + uint32_t vertices_count; + uint32_t _2d_item_count; + uint32_t _2d_draw_call_count; + + void reset() { + object_count = 0; + draw_call_count = 0; + material_switch_count = 0; + surface_switch_count = 0; + shader_rebind_count = 0; + vertices_count = 0; + _2d_item_count = 0; + _2d_draw_call_count = 0; + } + } render, render_final, snap; + + Info() { + render.reset(); + render_final.reset(); + } + + } info; + + virtual void capture_timestamps_begin() override {} + virtual void capture_timestamp(const String &p_name) override {} + virtual uint32_t get_captured_timestamps_count() const override { + return 0; + } + virtual uint64_t get_captured_timestamps_frame() const override { + return 0; + } + virtual uint64_t get_captured_timestamp_gpu_time(uint32_t p_index) const override { + return 0; + } + virtual uint64_t get_captured_timestamp_cpu_time(uint32_t p_index) const override { + return 0; + } + virtual String get_captured_timestamp_name(uint32_t p_index) const override { + return String(); + } + + // void render_info_begin_capture() override; + // void render_info_end_capture() override; + // int get_captured_render_info(RS::RenderInfo p_info) override; + + // int get_render_info(RS::RenderInfo p_info) override; + + /* MISC */ + + virtual void update_dirty_resources() override; + virtual void set_debug_generate_wireframes(bool p_generate) override; + + virtual bool has_os_feature(const String &p_feature) const override; + + virtual void update_memory_info() override; + + virtual uint64_t get_rendering_info(RS::RenderingInfo p_info) override; + virtual String get_video_adapter_name() const override; + virtual String get_video_adapter_vendor() const override; + virtual RenderingDevice::DeviceType get_video_adapter_type() const override; + virtual String get_video_adapter_api_version() const override; +}; + +} // namespace GLES3 + +#endif // GLES3_ENABLED + +#endif // UTILITIES_GLES3_H diff --git a/drivers/png/image_loader_png.h b/drivers/png/image_loader_png.h index 522cc901d4..9bcfb720d3 100644 --- a/drivers/png/image_loader_png.h +++ b/drivers/png/image_loader_png.h @@ -45,4 +45,4 @@ public: ImageLoaderPNG(); }; -#endif +#endif // IMAGE_LOADER_PNG_H diff --git a/drivers/png/png_driver_common.h b/drivers/png/png_driver_common.h index 62302bbdbb..24546d4402 100644 --- a/drivers/png/png_driver_common.h +++ b/drivers/png/png_driver_common.h @@ -43,4 +43,4 @@ Error png_to_image(const uint8_t *p_source, size_t p_size, bool p_force_linear, Error image_to_png(const Ref<Image> &p_image, Vector<uint8_t> &p_buffer); } // namespace PNGDriverCommon -#endif +#endif // PNG_DRIVER_COMMON_H diff --git a/drivers/png/resource_saver_png.cpp b/drivers/png/resource_saver_png.cpp index 704ddca726..275f3240d7 100644 --- a/drivers/png/resource_saver_png.cpp +++ b/drivers/png/resource_saver_png.cpp @@ -35,7 +35,7 @@ #include "drivers/png/png_driver_common.h" #include "scene/resources/texture.h" -Error ResourceSaverPNG::save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags) { +Error ResourceSaverPNG::save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags) { Ref<ImageTexture> texture = p_resource; ERR_FAIL_COND_V_MSG(!texture.is_valid(), ERR_INVALID_PARAMETER, "Can't save invalid texture as PNG."); diff --git a/drivers/png/resource_saver_png.h b/drivers/png/resource_saver_png.h index 1a681faaec..260a643a1b 100644 --- a/drivers/png/resource_saver_png.h +++ b/drivers/png/resource_saver_png.h @@ -39,7 +39,7 @@ public: static Error save_image(const String &p_path, const Ref<Image> &p_img); static Vector<uint8_t> save_image_to_buffer(const Ref<Image> &p_img); - virtual Error save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags = 0); + virtual Error save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags = 0); virtual bool recognize(const Ref<Resource> &p_resource) const; virtual void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const; diff --git a/drivers/register_driver_types.h b/drivers/register_driver_types.h index c008d93185..41f95b57e7 100644 --- a/drivers/register_driver_types.h +++ b/drivers/register_driver_types.h @@ -37,4 +37,4 @@ void unregister_core_driver_types(); void register_driver_types(); void unregister_driver_types(); -#endif +#endif // REGISTER_DRIVER_TYPES_H diff --git a/drivers/unix/dir_access_unix.cpp b/drivers/unix/dir_access_unix.cpp index 7e6105f033..b8b72b8d30 100644 --- a/drivers/unix/dir_access_unix.cpp +++ b/drivers/unix/dir_access_unix.cpp @@ -33,6 +33,7 @@ #if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED) #include "core/os/memory.h" +#include "core/os/os.h" #include "core/string/print_string.h" #include "core/templates/list.h" @@ -49,10 +50,6 @@ #include <mntent.h> #endif -Ref<DirAccess> DirAccessUnix::create_fs() { - return memnew(DirAccessUnix); -} - Error DirAccessUnix::list_dir_begin() { list_dir_end(); //close any previous dir opening! @@ -216,10 +213,11 @@ static bool _filter_drive(struct mntent *mnt) { #endif static void _get_drives(List<String> *list) { + // Add root. list->push_back("/"); #if defined(HAVE_MNTENT) && defined(X11_ENABLED) - // Check /etc/mtab for the list of mounted partitions + // Check /etc/mtab for the list of mounted partitions. FILE *mtab = setmntent("/etc/mtab", "r"); if (mtab) { struct mntent mnt; @@ -239,7 +237,7 @@ static void _get_drives(List<String> *list) { } #endif - // Add $HOME + // Add $HOME. const char *home = getenv("HOME"); if (home) { // Only add if it's not a duplicate @@ -248,7 +246,8 @@ static void _get_drives(List<String> *list) { list->push_back(home_name); } - // Check $HOME/.config/gtk-3.0/bookmarks + // Check GTK+3 bookmarks for both XDG locations (Documents, Downloads, etc.) + // and potential user-defined bookmarks. char path[1024]; snprintf(path, 1024, "%s/.config/gtk-3.0/bookmarks", home); FILE *fd = fopen(path, "r"); @@ -257,7 +256,7 @@ static void _get_drives(List<String> *list) { while (fgets(string, 1024, fd)) { // Parse only file:// links if (strncmp(string, "file://", 7) == 0) { - // Strip any unwanted edges on the strings and push_back if it's not a duplicate + // Strip any unwanted edges on the strings and push_back if it's not a duplicate. String fpath = String::utf8(string + 7).strip_edges().split_spaces()[0].uri_decode(); if (!list->find(fpath)) { list->push_back(fpath); @@ -267,6 +266,12 @@ static void _get_drives(List<String> *list) { fclose(fd); } + + // Add Desktop dir. + String dpath = OS::get_singleton()->get_system_dir(OS::SystemDir::SYSTEM_DIR_DESKTOP); + if (dpath.length() > 0 && !list->find(dpath)) { + list->push_back(dpath); + } } list->sort(); @@ -338,7 +343,7 @@ Error DirAccessUnix::change_dir(String p_dir) { String prev_dir; char real_current_dir_name[2048]; ERR_FAIL_COND_V(getcwd(real_current_dir_name, 2048) == nullptr, ERR_BUG); - if (prev_dir.parse_utf8(real_current_dir_name)) { + if (prev_dir.parse_utf8(real_current_dir_name) != OK) { prev_dir = real_current_dir_name; //no utf8, maybe latin? } @@ -500,7 +505,7 @@ DirAccessUnix::DirAccessUnix() { // set current directory to an absolute path of the current directory char real_current_dir_name[2048]; ERR_FAIL_COND(getcwd(real_current_dir_name, 2048) == nullptr); - if (current_dir.parse_utf8(real_current_dir_name)) { + if (current_dir.parse_utf8(real_current_dir_name) != OK) { current_dir = real_current_dir_name; } @@ -511,4 +516,4 @@ DirAccessUnix::~DirAccessUnix() { list_dir_end(); } -#endif //posix_enabled +#endif // UNIX_ENABLED || LIBC_FILEIO_ENABLED diff --git a/drivers/unix/dir_access_unix.h b/drivers/unix/dir_access_unix.h index 69530de337..18f435f942 100644 --- a/drivers/unix/dir_access_unix.h +++ b/drivers/unix/dir_access_unix.h @@ -43,13 +43,11 @@ class DirAccessUnix : public DirAccess { DIR *dir_stream = nullptr; - static Ref<DirAccess> create_fs(); - - String current_dir; bool _cisdir = false; bool _cishidden = false; protected: + String current_dir; virtual String fix_unicode_name(const char *p_name) const { return String::utf8(p_name); } virtual bool is_hidden(const String &p_name); @@ -92,5 +90,6 @@ public: ~DirAccessUnix(); }; -#endif //UNIX ENABLED -#endif +#endif // UNIX_ENABLED || LIBC_FILEIO_ENABLED + +#endif // DIR_ACCESS_UNIX_H diff --git a/drivers/unix/file_access_unix.cpp b/drivers/unix/file_access_unix.cpp index e0b2994b63..388ad479b9 100644 --- a/drivers/unix/file_access_unix.cpp +++ b/drivers/unix/file_access_unix.cpp @@ -333,14 +333,10 @@ Error FileAccessUnix::_set_unix_permissions(const String &p_file, uint32_t p_per return FAILED; } -Ref<FileAccess> FileAccessUnix::create_libc() { - return memnew(FileAccessUnix); -} - CloseNotificationFunc FileAccessUnix::close_notification_func = nullptr; FileAccessUnix::~FileAccessUnix() { _close(); } -#endif +#endif // UNIX_ENABLED || LIBC_FILEIO_ENABLED diff --git a/drivers/unix/file_access_unix.h b/drivers/unix/file_access_unix.h index 4340bbbc82..d61fc08f57 100644 --- a/drivers/unix/file_access_unix.h +++ b/drivers/unix/file_access_unix.h @@ -49,7 +49,6 @@ class FileAccessUnix : public FileAccess { String path; String path_src; - static Ref<FileAccess> create_libc(); void _close(); public: @@ -87,5 +86,6 @@ public: virtual ~FileAccessUnix(); }; -#endif -#endif +#endif // UNIX_ENABLED || LIBC_FILEIO_ENABLED + +#endif // FILE_ACCESS_UNIX_H diff --git a/drivers/unix/ip_unix.h b/drivers/unix/ip_unix.h index 06fcdb6e17..798d02095c 100644 --- a/drivers/unix/ip_unix.h +++ b/drivers/unix/ip_unix.h @@ -50,4 +50,5 @@ public: }; #endif + #endif // IP_UNIX_H diff --git a/drivers/unix/net_socket_posix.h b/drivers/unix/net_socket_posix.h index 867513099a..5558114cb1 100644 --- a/drivers/unix/net_socket_posix.h +++ b/drivers/unix/net_socket_posix.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef NET_SOCKET_UNIX_H -#define NET_SOCKET_UNIX_H +#ifndef NET_SOCKET_POSIX_H +#define NET_SOCKET_POSIX_H #include "core/io/net_socket.h" @@ -104,4 +104,4 @@ public: ~NetSocketPosix(); }; -#endif +#endif // NET_SOCKET_POSIX_H diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index 52a4d538e1..5bf14056ab 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -65,7 +65,7 @@ #include <time.h> #include <unistd.h> -#if defined(OSX_ENABLED) || (defined(__ANDROID_API__) && __ANDROID_API__ >= 28) +#if defined(MACOS_ENABLED) || (defined(__ANDROID_API__) && __ANDROID_API__ >= 28) // Random location for getentropy. Fitting. #include <sys/random.h> #define UNIX_GET_ENTROPY @@ -313,7 +313,12 @@ Error OS_Unix::execute(const String &p_path, const List<String> &p_arguments, St if (p_pipe_mutex) { p_pipe_mutex->lock(); } - (*r_pipe) += String::utf8(buf); + String pipe_out; + if (pipe_out.parse_utf8(buf) == OK) { + (*r_pipe) += pipe_out; + } else { + (*r_pipe) += String(buf); // If not valid UTF-8 try decode as Latin-1 + } if (p_pipe_mutex) { p_pipe_mutex->unlock(); } diff --git a/drivers/unix/os_unix.h b/drivers/unix/os_unix.h index a1ed4bd501..f4609a565b 100644 --- a/drivers/unix/os_unix.h +++ b/drivers/unix/os_unix.h @@ -98,6 +98,6 @@ public: virtual ~UnixTerminalLogger(); }; -#endif +#endif // UNIX_ENABLED -#endif +#endif // OS_UNIX_H diff --git a/drivers/unix/syslog_logger.h b/drivers/unix/syslog_logger.h index 697a96a6f9..cc6617eb25 100644 --- a/drivers/unix/syslog_logger.h +++ b/drivers/unix/syslog_logger.h @@ -43,6 +43,6 @@ public: virtual ~SyslogLogger(); }; -#endif +#endif // UNIX_ENABLED -#endif +#endif // SYSLOG_LOGGER_H diff --git a/drivers/unix/thread_posix.h b/drivers/unix/thread_posix.h index 9cd3ecbe90..672adcba72 100644 --- a/drivers/unix/thread_posix.h +++ b/drivers/unix/thread_posix.h @@ -35,4 +35,4 @@ void init_thread_posix(); #endif -#endif +#endif // THREAD_POSIX_H diff --git a/drivers/vulkan/SCsub b/drivers/vulkan/SCsub index b6ceb1cdea..a076c0ac54 100644 --- a/drivers/vulkan/SCsub +++ b/drivers/vulkan/SCsub @@ -15,11 +15,11 @@ if env["use_volk"]: if env["platform"] == "android": env.AppendUnique(CPPDEFINES=["VK_USE_PLATFORM_ANDROID_KHR"]) -elif env["platform"] == "iphone": +elif env["platform"] == "ios": env.AppendUnique(CPPDEFINES=["VK_USE_PLATFORM_IOS_MVK"]) -elif env["platform"] == "linuxbsd": +elif env["platform"] == "linuxbsd" and env["x11"]: env.AppendUnique(CPPDEFINES=["VK_USE_PLATFORM_XLIB_KHR"]) -elif env["platform"] == "osx": +elif env["platform"] == "macos": env.AppendUnique(CPPDEFINES=["VK_USE_PLATFORM_MACOS_MVK"]) elif env["platform"] == "windows": env.AppendUnique(CPPDEFINES=["VK_USE_PLATFORM_WIN32_KHR"]) @@ -40,7 +40,7 @@ elif env["platform"] == "android": # Our current NDK version only provides old Vulkan headers, # so we have to limit VMA. env_thirdparty_vma.AppendUnique(CPPDEFINES=["VMA_VULKAN_VERSION=1000000"]) -elif env["platform"] == "osx" or env["platform"] == "iphone": +elif env["platform"] == "macos" or env["platform"] == "ios": # MoltenVK supports only Vulkan 1.1 API, limit VMA to the same version. env_thirdparty_vma.AppendUnique(CPPDEFINES=["VMA_VULKAN_VERSION=1001000"]) diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp index 10250bddb5..0979ae9e16 100644 --- a/drivers/vulkan/rendering_device_vulkan.cpp +++ b/drivers/vulkan/rendering_device_vulkan.cpp @@ -36,6 +36,7 @@ #include "core/io/marshalls.h" #include "core/os/os.h" #include "core/templates/hashfuncs.h" +#include "core/version.h" #include "drivers/vulkan/vulkan_context.h" #include "thirdparty/misc/smolv.h" @@ -106,7 +107,7 @@ RenderingDeviceVulkan::Buffer *RenderingDeviceVulkan::_get_buffer_from_owner(RID return buffer; } -static void update_external_dependency_for_store(VkSubpassDependency &dependency, bool is_sampled, bool is_storage, bool is_depth) { +static void update_external_dependency_for_store(VkSubpassDependency2KHR &dependency, bool is_sampled, bool is_storage, bool is_depth) { // Transitioning from write to read, protect the shaders that may use this next // Allow for copies/image layout transitions dependency.dstStageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT; @@ -1758,6 +1759,10 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T image_create_info.usage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; } + if (p_format.usage_bits & TEXTURE_USAGE_VRS_ATTACHMENT_BIT) { + image_create_info.usage |= VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR; + } + if (p_format.usage_bits & TEXTURE_USAGE_CAN_UPDATE_BIT) { image_create_info.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT; } @@ -1829,6 +1834,11 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T if (p_format.usage_bits & TEXTURE_USAGE_STORAGE_ATOMIC_BIT && !(flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT)) { ERR_FAIL_V_MSG(RID(), "Format " + format_text + " does not support usage as atomic storage image."); } + + // Validation via VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR fails if VRS attachment is not supported. + if (p_format.usage_bits & TEXTURE_USAGE_VRS_ATTACHMENT_BIT && p_format.format != DATA_FORMAT_R8_UINT) { + ERR_FAIL_V_MSG(RID(), "Format " + format_text + " does not support usage as VRS attachment."); + } } //some view validation @@ -3349,6 +3359,11 @@ bool RenderingDeviceVulkan::texture_is_format_supported_for_usage(DataFormat p_f return false; } + // Validation via VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR fails if VRS attachment is not supported. + if (p_usage & TEXTURE_USAGE_VRS_ATTACHMENT_BIT && p_format != DATA_FORMAT_R8_UINT) { + return false; + } + return true; } @@ -3362,17 +3377,24 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; // From Section 7.1 of Vulkan API Spec v1.1.148 + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | // From Section 7.1 of Vulkan API Spec v1.1.148 + VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR; VkPipelineStageFlags reading_stages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT; - VkSubpassDependency dependencies[2] = { { VK_SUBPASS_EXTERNAL, 0, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 0, default_access_mask, 0 }, - { 0, VK_SUBPASS_EXTERNAL, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, default_access_mask, 0, 0 } }; - VkSubpassDependency &dependency_from_external = dependencies[0]; - VkSubpassDependency &dependency_to_external = dependencies[1]; + VkSubpassDependency2KHR dependencies[2] = { + { VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR, nullptr, VK_SUBPASS_EXTERNAL, 0, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 0, default_access_mask, 0, 0 }, + { VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR, nullptr, 0, VK_SUBPASS_EXTERNAL, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, default_access_mask, 0, 0, 0 } + }; + VkSubpassDependency2KHR &dependency_from_external = dependencies[0]; + VkSubpassDependency2KHR &dependency_to_external = dependencies[1]; LocalVector<int32_t> attachment_last_pass; attachment_last_pass.resize(p_attachments.size()); - Vector<VkAttachmentDescription> attachments; + // These are only used if we use multiview but we need to define them in scope. + const uint32_t view_mask = (1 << p_view_count) - 1; + const uint32_t correlation_mask = (1 << p_view_count) - 1; + + Vector<VkAttachmentDescription2KHR> attachments; Vector<int> attachment_remap; for (int i = 0; i < p_attachments.size(); i++) { @@ -3383,10 +3405,12 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF ERR_FAIL_INDEX_V(p_attachments[i].format, DATA_FORMAT_MAX, VK_NULL_HANDLE); ERR_FAIL_INDEX_V(p_attachments[i].samples, TEXTURE_SAMPLES_MAX, VK_NULL_HANDLE); - ERR_FAIL_COND_V_MSG(!(p_attachments[i].usage_flags & (TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | TEXTURE_USAGE_INPUT_ATTACHMENT_BIT)), - VK_NULL_HANDLE, "Texture format for index (" + itos(i) + ") requires an attachment (color, depth, input or stencil) bit set."); + ERR_FAIL_COND_V_MSG(!(p_attachments[i].usage_flags & (TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | TEXTURE_USAGE_INPUT_ATTACHMENT_BIT | TEXTURE_USAGE_VRS_ATTACHMENT_BIT)), + VK_NULL_HANDLE, "Texture format for index (" + itos(i) + ") requires an attachment (color, depth-stencil, input or VRS) bit set."); - VkAttachmentDescription description = {}; + VkAttachmentDescription2KHR description = {}; + description.sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2_KHR; + description.pNext = nullptr; description.flags = 0; description.format = vulkan_formats[p_attachments[i].format]; description.samples = rasterization_sample_count[p_attachments[i].samples]; @@ -3395,83 +3419,95 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF bool is_storage = p_attachments[i].usage_flags & TEXTURE_USAGE_STORAGE_BIT; bool is_depth = p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - // For each UNDEFINED, assume the prior use was a *read*, as we'd be discarding the output of a write - // Also, each UNDEFINED will do an immediate layout transition (write), s.t. we must ensure execution synchronization vs. - // the read. If this is a performance issue, one could track the actual last accessor of each resource, adding only that - // stage - - switch (is_depth ? p_initial_depth_action : p_initial_action) { - case INITIAL_ACTION_CLEAR_REGION: - case INITIAL_ACTION_CLEAR: { - if (p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) { - description.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - description.initialLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - } else if (p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { - description.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - description.initialLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); - description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - dependency_from_external.srcStageMask |= reading_stages; - } else { - description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there - dependency_from_external.srcStageMask |= reading_stages; - } - } break; - case INITIAL_ACTION_KEEP: { - if (p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) { - description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; - description.initialLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - } else if (p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { - description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; - description.initialLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); - description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD; - dependency_from_external.srcStageMask |= reading_stages; - } else { - description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there - dependency_from_external.srcStageMask |= reading_stages; - } - } break; - case INITIAL_ACTION_DROP: { - if (p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) { - description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - description.initialLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - } else if (p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { - description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there - description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - dependency_from_external.srcStageMask |= reading_stages; - } else { - description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there - dependency_from_external.srcStageMask |= reading_stages; - } - } break; - case INITIAL_ACTION_CLEAR_REGION_CONTINUE: - case INITIAL_ACTION_CONTINUE: { - if (p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) { - description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; - description.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - } else if (p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { - description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; - description.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD; - } else { - description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there - dependency_from_external.srcStageMask |= reading_stages; + // We can setup a framebuffer where we write to our VRS texture to set it up. + // We make the assumption here that if our texture is actually used as our VRS attachment, + // it is used as such for each subpass. This is fairly certain seeing the restrictions on subpasses. + bool is_vrs = p_attachments[i].usage_flags & TEXTURE_USAGE_VRS_ATTACHMENT_BIT && i == p_passes[0].vrs_attachment; + + if (is_vrs) { + // For VRS we only read, there is no writing to this texture + description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + description.initialLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + } else { + // For each UNDEFINED, assume the prior use was a *read*, as we'd be discarding the output of a write + // Also, each UNDEFINED will do an immediate layout transition (write), s.t. we must ensure execution synchronization vs. + // the read. If this is a performance issue, one could track the actual last accessor of each resource, adding only that + // stage + + switch (is_depth ? p_initial_depth_action : p_initial_action) { + case INITIAL_ACTION_CLEAR_REGION: + case INITIAL_ACTION_CLEAR: { + if (p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) { + description.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + description.initialLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + } else if (p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { + description.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + description.initialLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + dependency_from_external.srcStageMask |= reading_stages; + } else { + description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there + dependency_from_external.srcStageMask |= reading_stages; + } + } break; + case INITIAL_ACTION_KEEP: { + if (p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) { + description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + description.initialLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + } else if (p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { + description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + description.initialLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + dependency_from_external.srcStageMask |= reading_stages; + } else { + description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there + dependency_from_external.srcStageMask |= reading_stages; + } + } break; + case INITIAL_ACTION_DROP: { + if (p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) { + description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + description.initialLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + } else if (p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { + description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there + description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + dependency_from_external.srcStageMask |= reading_stages; + } else { + description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there + dependency_from_external.srcStageMask |= reading_stages; + } + } break; + case INITIAL_ACTION_CLEAR_REGION_CONTINUE: + case INITIAL_ACTION_CONTINUE: { + if (p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) { + description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + description.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + } else if (p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { + description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + description.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + } else { + description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there + dependency_from_external.srcStageMask |= reading_stages; + } + } break; + default: { + ERR_FAIL_V(VK_NULL_HANDLE); //should never reach here } - } break; - default: { - ERR_FAIL_V(VK_NULL_HANDLE); //should never reach here } } @@ -3485,6 +3521,10 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF if (p_passes[last_pass].depth_attachment == i) { used_last = true; } + } else if (is_vrs) { + if (p_passes[last_pass].vrs_attachment == i) { + used_last = true; + } } else { if (p_passes[last_pass].resolve_attachments.size()) { //if using resolve attachments, check resolve attachments @@ -3526,58 +3566,69 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF } } - switch (is_depth ? final_depth_action : final_action) { - case FINAL_ACTION_READ: { - if (p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) { - description.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - description.finalLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - update_external_dependency_for_store(dependency_to_external, is_sampled, is_storage, false); - } else if (p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { - description.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; - description.finalLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); - update_external_dependency_for_store(dependency_to_external, is_sampled, is_storage, true); - } else { - description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there - // TODO: What does this mean about the next usage (and thus appropriate dependency masks - } - } break; - case FINAL_ACTION_DISCARD: { - if (p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) { - description.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - description.finalLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - } else if (p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { - description.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - description.finalLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); - } else { - description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there - } - } break; - case FINAL_ACTION_CONTINUE: { - if (p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) { - description.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - description.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - } else if (p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { - description.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; - description.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - } else { - description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there - } + if (is_vrs) { + // We don't change our VRS texture during this process - } break; - default: { - ERR_FAIL_V(VK_NULL_HANDLE); //should never reach here + description.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + description.finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + + // TODO do we need to update our external dependency ? + // update_external_dependency_for_store(dependency_to_external, is_sampled, is_storage, false); + } else { + switch (is_depth ? final_depth_action : final_action) { + case FINAL_ACTION_READ: { + if (p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) { + description.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + description.finalLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + update_external_dependency_for_store(dependency_to_external, is_sampled, is_storage, false); + } else if (p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { + description.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; + description.finalLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + update_external_dependency_for_store(dependency_to_external, is_sampled, is_storage, true); + } else { + description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there + // TODO: What does this mean about the next usage (and thus appropriate dependency masks + } + } break; + case FINAL_ACTION_DISCARD: { + if (p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) { + description.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + description.finalLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + } else if (p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { + description.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + description.finalLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + } else { + description.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + description.finalLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there + } + } break; + case FINAL_ACTION_CONTINUE: { + if (p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) { + description.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + description.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + } else if (p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { + description.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; + description.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + } else { + description.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + description.finalLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there + } + + } break; + default: { + ERR_FAIL_V(VK_NULL_HANDLE); //should never reach here + } } } @@ -3586,12 +3637,14 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF attachments.push_back(description); } - LocalVector<VkSubpassDescription> subpasses; - LocalVector<LocalVector<VkAttachmentReference>> color_reference_array; - LocalVector<LocalVector<VkAttachmentReference>> input_reference_array; - LocalVector<LocalVector<VkAttachmentReference>> resolve_reference_array; + LocalVector<VkSubpassDescription2KHR> subpasses; + LocalVector<LocalVector<VkAttachmentReference2KHR>> color_reference_array; + LocalVector<LocalVector<VkAttachmentReference2KHR>> input_reference_array; + LocalVector<LocalVector<VkAttachmentReference2KHR>> resolve_reference_array; LocalVector<LocalVector<uint32_t>> preserve_reference_array; - LocalVector<VkAttachmentReference> depth_reference_array; + LocalVector<VkAttachmentReference2KHR> depth_reference_array; + LocalVector<VkAttachmentReference2KHR> vrs_reference_array; + LocalVector<VkFragmentShadingRateAttachmentInfoKHR> vrs_attachment_info_array; subpasses.resize(p_passes.size()); color_reference_array.resize(p_passes.size()); @@ -3599,20 +3652,25 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF resolve_reference_array.resize(p_passes.size()); preserve_reference_array.resize(p_passes.size()); depth_reference_array.resize(p_passes.size()); + vrs_reference_array.resize(p_passes.size()); + vrs_attachment_info_array.resize(p_passes.size()); - LocalVector<VkSubpassDependency> subpass_dependencies; + LocalVector<VkSubpassDependency2KHR> subpass_dependencies; for (int i = 0; i < p_passes.size(); i++) { const FramebufferPass *pass = &p_passes[i]; - LocalVector<VkAttachmentReference> &color_references = color_reference_array[i]; + LocalVector<VkAttachmentReference2KHR> &color_references = color_reference_array[i]; TextureSamples texture_samples = TEXTURE_SAMPLES_1; bool is_multisample_first = true; + void *subpass_nextptr = nullptr; for (int j = 0; j < pass->color_attachments.size(); j++) { int32_t attachment = pass->color_attachments[j]; - VkAttachmentReference reference; + VkAttachmentReference2KHR reference; + reference.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR; + reference.pNext = nullptr; if (attachment == FramebufferPass::ATTACHMENT_UNUSED) { reference.attachment = VK_ATTACHMENT_UNUSED; reference.layout = VK_IMAGE_LAYOUT_UNDEFINED; @@ -3631,14 +3689,17 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; attachment_last_pass[attachment] = i; } + reference.aspectMask = 0; color_references.push_back(reference); } - LocalVector<VkAttachmentReference> &input_references = input_reference_array[i]; + LocalVector<VkAttachmentReference2KHR> &input_references = input_reference_array[i]; for (int j = 0; j < pass->input_attachments.size(); j++) { int32_t attachment = pass->input_attachments[j]; - VkAttachmentReference reference; + VkAttachmentReference2KHR reference; + reference.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR; + reference.pNext = nullptr; if (attachment == FramebufferPass::ATTACHMENT_UNUSED) { reference.attachment = VK_ATTACHMENT_UNUSED; reference.layout = VK_IMAGE_LAYOUT_UNDEFINED; @@ -3650,10 +3711,11 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF reference.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; attachment_last_pass[attachment] = i; } + reference.aspectMask = 0; // TODO we need to set this here, possibly VK_IMAGE_ASPECT_COLOR_BIT ?? input_references.push_back(reference); } - LocalVector<VkAttachmentReference> &resolve_references = resolve_reference_array[i]; + LocalVector<VkAttachmentReference2KHR> &resolve_references = resolve_reference_array[i]; if (pass->resolve_attachments.size() > 0) { ERR_FAIL_COND_V_MSG(pass->resolve_attachments.size() != pass->color_attachments.size(), VK_NULL_HANDLE, "The amount of resolve attachments (" + itos(pass->resolve_attachments.size()) + ") must match the number of color attachments (" + itos(pass->color_attachments.size()) + ")."); @@ -3661,7 +3723,9 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF } for (int j = 0; j < pass->resolve_attachments.size(); j++) { int32_t attachment = pass->resolve_attachments[j]; - VkAttachmentReference reference; + VkAttachmentReference2KHR reference; + reference.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR; + reference.pNext = nullptr; if (attachment == FramebufferPass::ATTACHMENT_UNUSED) { reference.attachment = VK_ATTACHMENT_UNUSED; reference.layout = VK_IMAGE_LAYOUT_UNDEFINED; @@ -3676,10 +3740,13 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; // VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; attachment_last_pass[attachment] = i; } + reference.aspectMask = 0; resolve_references.push_back(reference); } - VkAttachmentReference &depth_stencil_reference = depth_reference_array[i]; + VkAttachmentReference2KHR &depth_stencil_reference = depth_reference_array[i]; + depth_stencil_reference.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR; + depth_stencil_reference.pNext = nullptr; if (pass->depth_attachment != FramebufferPass::ATTACHMENT_UNUSED) { int32_t attachment = pass->depth_attachment; @@ -3688,6 +3755,7 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF ERR_FAIL_COND_V_MSG(attachment_last_pass[attachment] == i, VK_NULL_HANDLE, "Invalid framebuffer depth format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), it already was used for something else before in this pass."); depth_stencil_reference.attachment = attachment_remap[attachment]; depth_stencil_reference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + depth_stencil_reference.aspectMask = 0; attachment_last_pass[attachment] = i; if (is_multisample_first) { @@ -3702,6 +3770,32 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF depth_stencil_reference.layout = VK_IMAGE_LAYOUT_UNDEFINED; } + if (context->get_vrs_capabilities().attachment_vrs_supported && pass->vrs_attachment != FramebufferPass::ATTACHMENT_UNUSED) { + int32_t attachment = pass->vrs_attachment; + ERR_FAIL_INDEX_V_MSG(attachment, p_attachments.size(), VK_NULL_HANDLE, "Invalid framebuffer VRS format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), VRS attachment."); + ERR_FAIL_COND_V_MSG(!(p_attachments[attachment].usage_flags & TEXTURE_USAGE_VRS_ATTACHMENT_BIT), VK_NULL_HANDLE, "Invalid framebuffer VRS format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), it's marked as VRS, but it's not a VRS attachment."); + ERR_FAIL_COND_V_MSG(attachment_last_pass[attachment] == i, VK_NULL_HANDLE, "Invalid framebuffer VRS attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), it already was used for something else before in this pass."); + + VkAttachmentReference2KHR &vrs_reference = vrs_reference_array[i]; + vrs_reference.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR; + vrs_reference.pNext = nullptr; + vrs_reference.attachment = attachment_remap[attachment]; + vrs_reference.layout = VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR; + vrs_reference.aspectMask = 0; + + Size2i texel_size = context->get_vrs_capabilities().max_texel_size; + + VkFragmentShadingRateAttachmentInfoKHR &vrs_attachment_info = vrs_attachment_info_array[i]; + vrs_attachment_info.sType = VK_STRUCTURE_TYPE_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR; + vrs_attachment_info.pNext = nullptr; + vrs_attachment_info.pFragmentShadingRateAttachment = &vrs_reference; + vrs_attachment_info.shadingRateAttachmentTexelSize = { uint32_t(texel_size.x), uint32_t(texel_size.y) }; + + attachment_last_pass[attachment] = i; + + subpass_nextptr = &vrs_attachment_info; + } + LocalVector<uint32_t> &preserve_references = preserve_reference_array[i]; for (int j = 0; j < pass->preserve_attachments.size(); j++) { @@ -3718,9 +3812,17 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF } } - VkSubpassDescription &subpass = subpasses[i]; + VkSubpassDescription2KHR &subpass = subpasses[i]; + subpass.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR; + subpass.pNext = subpass_nextptr; subpass.flags = 0; subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + if (p_view_count == 1) { + // VUID-VkSubpassDescription2-multiview-06558: If the multiview feature is not enabled, viewMask must be 0. + subpass.viewMask = 0; + } else { + subpass.viewMask = view_mask; + } subpass.inputAttachmentCount = input_references.size(); if (input_references.size()) { subpass.pInputAttachments = input_references.ptr(); @@ -3757,7 +3859,9 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF } if (i > 0) { - VkSubpassDependency dependency; + VkSubpassDependency2KHR dependency; + dependency.sType = VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2_KHR; + dependency.pNext = nullptr; dependency.srcSubpass = i - 1; dependency.dstSubpass = i; dependency.srcStageMask = 0; @@ -3767,6 +3871,7 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF dependency.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT; dependency.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; + dependency.viewOffset = 0; subpass_dependencies.push_back(dependency); } /* @@ -3784,10 +3889,11 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF */ } - VkRenderPassCreateInfo render_pass_create_info; - render_pass_create_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + VkRenderPassCreateInfo2KHR render_pass_create_info; + render_pass_create_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2_KHR; render_pass_create_info.pNext = nullptr; render_pass_create_info.flags = 0; + render_pass_create_info.attachmentCount = attachments.size(); render_pass_create_info.pAttachments = attachments.ptr(); render_pass_create_info.subpassCount = subpasses.size(); @@ -3804,13 +3910,21 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF render_pass_create_info.pDependencies = nullptr; } - // These are only used if we use multiview but we need to define them in scope. - const uint32_t view_mask = (1 << p_view_count) - 1; - const uint32_t correlation_mask = (1 << p_view_count) - 1; + if (p_view_count == 1) { + // VUID-VkRenderPassCreateInfo2-viewMask-03057: If the VkSubpassDescription2::viewMask member of all elements of pSubpasses is 0, correlatedViewMaskCount must be 0. + render_pass_create_info.correlatedViewMaskCount = 0; + render_pass_create_info.pCorrelatedViewMasks = nullptr; + } else { + render_pass_create_info.correlatedViewMaskCount = 1; + render_pass_create_info.pCorrelatedViewMasks = &correlation_mask; + } + Vector<uint32_t> view_masks; VkRenderPassMultiviewCreateInfo render_pass_multiview_create_info; if (p_view_count > 1) { + // this may no longer be needed with the new settings already including this + const VulkanContext::MultiviewCapabilities capabilities = context->get_multiview_capabilities(); // For now this only works with multiview! @@ -3837,8 +3951,8 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF } VkRenderPass render_pass; - VkResult res = vkCreateRenderPass(device, &render_pass_create_info, nullptr, &render_pass); - ERR_FAIL_COND_V_MSG(res, VK_NULL_HANDLE, "vkCreateRenderPass failed with error " + itos(res) + "."); + VkResult res = context->vkCreateRenderPass2KHR(device, &render_pass_create_info, nullptr, &render_pass); + ERR_FAIL_COND_V_MSG(res, VK_NULL_HANDLE, "vkCreateRenderPass2KHR failed with error " + itos(res) + "."); return render_pass; } @@ -3899,9 +4013,12 @@ RenderingDevice::FramebufferFormatID RenderingDeviceVulkan::framebuffer_format_c return E->get(); } - VkSubpassDescription subpass; + VkSubpassDescription2KHR subpass; + subpass.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR; + subpass.pNext = nullptr; subpass.flags = 0; subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + subpass.viewMask = 0; subpass.inputAttachmentCount = 0; //unsupported for now subpass.pInputAttachments = nullptr; subpass.colorAttachmentCount = 0; @@ -3911,8 +4028,8 @@ RenderingDevice::FramebufferFormatID RenderingDeviceVulkan::framebuffer_format_c subpass.preserveAttachmentCount = 0; subpass.pPreserveAttachments = nullptr; - VkRenderPassCreateInfo render_pass_create_info; - render_pass_create_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + VkRenderPassCreateInfo2KHR render_pass_create_info; + render_pass_create_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2_KHR; render_pass_create_info.pNext = nullptr; render_pass_create_info.flags = 0; render_pass_create_info.attachmentCount = 0; @@ -3921,11 +4038,13 @@ RenderingDevice::FramebufferFormatID RenderingDeviceVulkan::framebuffer_format_c render_pass_create_info.pSubpasses = &subpass; render_pass_create_info.dependencyCount = 0; render_pass_create_info.pDependencies = nullptr; + render_pass_create_info.correlatedViewMaskCount = 0; + render_pass_create_info.pCorrelatedViewMasks = nullptr; VkRenderPass render_pass; - VkResult res = vkCreateRenderPass(device, &render_pass_create_info, nullptr, &render_pass); + VkResult res = context->vkCreateRenderPass2KHR(device, &render_pass_create_info, nullptr, &render_pass); - ERR_FAIL_COND_V_MSG(res, 0, "vkCreateRenderPass for empty fb failed with error " + itos(res) + "."); + ERR_FAIL_COND_V_MSG(res, 0, "vkCreateRenderPass2KHR for empty fb failed with error " + itos(res) + "."); if (render_pass == VK_NULL_HANDLE) { //was likely invalid return INVALID_ID; @@ -3978,6 +4097,8 @@ RID RenderingDeviceVulkan::framebuffer_create(const Vector<RID> &p_texture_attac if (texture && texture->usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { pass.depth_attachment = i; + } else if (texture && texture->usage_flags & TEXTURE_USAGE_VRS_ATTACHMENT_BIT) { + pass.vrs_attachment = i; } else { pass.color_attachments.push_back(texture ? i : FramebufferPass::ATTACHMENT_UNUSED); } @@ -4008,6 +4129,10 @@ RID RenderingDeviceVulkan::framebuffer_create_multipass(const Vector<RID> &p_tex size.width = texture->width; size.height = texture->height; size_set = true; + } else if (texture->usage_flags & TEXTURE_USAGE_VRS_ATTACHMENT_BIT) { + // If this is not the first attachement we assume this is used as the VRS attachment + // in this case this texture will be 1/16th the size of the color attachement. + // So we skip the size check } else { ERR_FAIL_COND_V_MSG((uint32_t)size.width != texture->width || (uint32_t)size.height != texture->height, RID(), "All textures in a framebuffer should be the same size."); @@ -4556,7 +4681,7 @@ bool RenderingDeviceVulkan::_uniform_add_binding(Vector<Vector<VkDescriptorSetLa #define SHADER_BINARY_VERSION 3 String RenderingDeviceVulkan::shader_get_binary_cache_key() const { - return "Vulkan-SV" + itos(SHADER_BINARY_VERSION); + return "Vulkan-SV" + itos(SHADER_BINARY_VERSION) + "-" + String(VERSION_NUMBER) + "-" + String(VERSION_HASH); } struct RenderingDeviceVulkanShaderBinaryDataBinding { @@ -4647,18 +4772,6 @@ Vector<uint8_t> RenderingDeviceVulkan::shader_compile_binary_from_spirv(const Ve ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, Vector<uint8_t>(), "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "' failed getting descriptor bindings."); - uint32_t interface_vars_count = 0; - result = spvReflectEnumerateInterfaceVariables(&module, &interface_vars_count, nullptr); - ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, Vector<uint8_t>(), - "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "' failed enumerating interface variables."); - - Vector<SpvReflectInterfaceVariable *> interface_vars; - interface_vars.resize(interface_vars_count); - result = spvReflectEnumerateInterfaceVariables(&module, &interface_vars_count, interface_vars.ptrw()); - - ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, Vector<uint8_t>(), - "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "' failed getting interface variables."); - for (uint32_t j = 0; j < binding_count; j++) { const SpvReflectDescriptorBinding &binding = *bindings[j]; @@ -4666,6 +4779,7 @@ Vector<uint8_t> RenderingDeviceVulkan::shader_compile_binary_from_spirv(const Ve bool need_array_dimensions = false; bool need_block_size = false; + bool may_be_writable = false; switch (binding.descriptor_type) { case SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLER: { @@ -4683,6 +4797,7 @@ Vector<uint8_t> RenderingDeviceVulkan::shader_compile_binary_from_spirv(const Ve case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_IMAGE: { info.type = UNIFORM_TYPE_IMAGE; need_array_dimensions = true; + may_be_writable = true; } break; case SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: { info.type = UNIFORM_TYPE_TEXTURE_BUFFER; @@ -4691,6 +4806,7 @@ Vector<uint8_t> RenderingDeviceVulkan::shader_compile_binary_from_spirv(const Ve case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: { info.type = UNIFORM_TYPE_IMAGE_BUFFER; need_array_dimensions = true; + may_be_writable = true; } break; case SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER: { info.type = UNIFORM_TYPE_UNIFORM_BUFFER; @@ -4699,6 +4815,7 @@ Vector<uint8_t> RenderingDeviceVulkan::shader_compile_binary_from_spirv(const Ve case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER: { info.type = UNIFORM_TYPE_STORAGE_BUFFER; need_block_size = true; + may_be_writable = true; } break; case SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: { ERR_PRINT("Dynamic uniform buffer not supported."); @@ -4737,17 +4854,11 @@ Vector<uint8_t> RenderingDeviceVulkan::shader_compile_binary_from_spirv(const Ve info.length = 0; } - SpvReflectInterfaceVariable *interface_var = nullptr; - for (uint32_t k = 0; k < interface_vars_count; k++) { - if (interface_vars[k]->spirv_id == binding.spirv_id) { - interface_var = interface_vars[k]; - break; - } + if (may_be_writable) { + info.writable = !(binding.type_description->decoration_flags & SPV_REFLECT_DECORATION_NON_WRITABLE) && !(binding.block.decoration_flags & SPV_REFLECT_DECORATION_NON_WRITABLE); + } else { + info.writable = false; } - ERR_FAIL_COND_V_MSG(!interface_var, Vector<uint8_t>(), - "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "' failed finding interface variable."); - - info.writable = !(bool)(interface_var->decoration_flags & SPV_REFLECT_DECORATION_NON_WRITABLE); info.binding = binding.binding; uint32_t set = binding.set; @@ -4771,6 +4882,10 @@ Vector<uint8_t> RenderingDeviceVulkan::shader_compile_binary_from_spirv(const Ve ERR_FAIL_COND_V_MSG(uniform_info[set][k].length != info.length, Vector<uint8_t>(), "On shader stage '" + String(shader_stage_names[stage]) + "', uniform '" + binding.name + "' trying to re-use location for set=" + itos(set) + ", binding=" + itos(info.binding) + " with different uniform size."); + //also, verify that it has the same writability + ERR_FAIL_COND_V_MSG(uniform_info[set][k].writable != info.writable, Vector<uint8_t>(), + "On shader stage '" + String(shader_stage_names[stage]) + "', uniform '" + binding.name + "' trying to re-use location for set=" + itos(set) + ", binding=" + itos(info.binding) + " with different writability."); + //just append stage mask and return uniform_info.write[set].write[k].stages |= 1 << stage; exists = true; @@ -5070,7 +5185,7 @@ RID RenderingDeviceVulkan::shader_create_from_bytecode(const Vector<uint8_t> &p_ ERR_FAIL_COND_V(binptr[0] != 'G' || binptr[1] != 'V' || binptr[2] != 'B' || binptr[3] != 'D', RID()); uint32_t bin_version = decode_uint32(binptr + 4); - ERR_FAIL_COND_V(bin_version > SHADER_BINARY_VERSION, RID()); + ERR_FAIL_COND_V(bin_version != SHADER_BINARY_VERSION, RID()); uint32_t bin_data_size = decode_uint32(binptr + 8); @@ -6566,11 +6681,28 @@ RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferForma dynamic_state_create_info.dynamicStateCount = dynamic_states.size(); dynamic_state_create_info.pDynamicStates = dynamic_states.ptr(); + void *graphics_pipeline_nextptr = nullptr; + + VkPipelineFragmentShadingRateStateCreateInfoKHR vrs_create_info; + if (context->get_vrs_capabilities().attachment_vrs_supported) { + // If VRS is used, this defines how the different VRS types are combined. + // combinerOps[0] decides how we use the output of pipeline and primitive (drawcall) VRS + // combinerOps[1] decides how we use the output of combinerOps[0] and our attachment VRS + + vrs_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_STATE_CREATE_INFO_KHR; + vrs_create_info.pNext = nullptr; + vrs_create_info.fragmentSize = { 4, 4 }; + vrs_create_info.combinerOps[0] = VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR; // We don't use pipeline/primitive VRS so this really doesn't matter + vrs_create_info.combinerOps[1] = VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR; // always use the outcome of attachment VRS if enabled + + graphics_pipeline_nextptr = &vrs_create_info; + } + //finally, pipeline create info VkGraphicsPipelineCreateInfo graphics_pipeline_create_info; graphics_pipeline_create_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - graphics_pipeline_create_info.pNext = nullptr; + graphics_pipeline_create_info.pNext = graphics_pipeline_nextptr; graphics_pipeline_create_info.flags = 0; Vector<VkPipelineShaderStageCreateInfo> pipeline_stages = shader->pipeline_stages; @@ -6735,7 +6867,7 @@ RID RenderingDeviceVulkan::compute_pipeline_create(RID p_shader, const Vector<Pi const PipelineSpecializationConstant &psc = p_specialization_constants[j]; if (psc.constant_id == sc.constant.constant_id) { ERR_FAIL_COND_V_MSG(psc.type != sc.constant.type, RID(), "Specialization constant provided for id (" + itos(sc.constant.constant_id) + ") is of the wrong type."); - data_ptr[i] = sc.constant.int_value; + data_ptr[i] = psc.int_value; break; } } @@ -6919,8 +7051,10 @@ Error RenderingDeviceVulkan::_draw_list_setup_framebuffer(Framebuffer *p_framebu Texture *texture = texture_owner.get_or_null(p_framebuffer->texture_ids[i]); if (texture) { attachments.push_back(texture->view); - ERR_FAIL_COND_V(texture->width != p_framebuffer->size.width, ERR_BUG); - ERR_FAIL_COND_V(texture->height != p_framebuffer->size.height, ERR_BUG); + if (!(texture->usage_flags & TEXTURE_USAGE_VRS_ATTACHMENT_BIT)) { // VRS attachment will be a different size. + ERR_FAIL_COND_V(texture->width != p_framebuffer->size.width, ERR_BUG); + ERR_FAIL_COND_V(texture->height != p_framebuffer->size.height, ERR_BUG); + } } } framebuffer_create_info.attachmentCount = attachments.size(); @@ -7055,7 +7189,6 @@ Error RenderingDeviceVulkan::_draw_list_render_pass_begin(Framebuffer *framebuff } void RenderingDeviceVulkan::_draw_list_insert_clear_region(DrawList *draw_list, Framebuffer *framebuffer, Point2i viewport_offset, Point2i viewport_size, bool p_clear_color, const Vector<Color> &p_clear_colors, bool p_clear_depth, float p_depth, uint32_t p_stencil) { - ERR_FAIL_COND_MSG(p_clear_color && p_clear_colors.size() != framebuffer->texture_ids.size(), "Clear color values supplied (" + itos(p_clear_colors.size()) + ") differ from the amount required for framebuffer color attachments (" + itos(framebuffer->texture_ids.size()) + ")."); Vector<VkClearAttachment> clear_attachments; int color_index = 0; int texture_index = 0; @@ -7144,11 +7277,14 @@ RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_begin(RID p_framebu } } - if (p_initial_color_action == INITIAL_ACTION_CLEAR) { //check clear values + if (p_initial_color_action == INITIAL_ACTION_CLEAR || needs_clear_color) { //check clear values int color_count = 0; for (int i = 0; i < framebuffer->texture_ids.size(); i++) { Texture *texture = texture_owner.get_or_null(framebuffer->texture_ids[i]); - if (!texture || !(texture->usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) { + // We only check for our VRS usage bit if this is not the first texture id. + // If it is the first we're likely populating our VRS texture. + // Bit dirty but.. + if (!texture || (!(texture->usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) && !(i != 0 && texture->usage_flags & TEXTURE_USAGE_VRS_ATTACHMENT_BIT))) { color_count++; } } @@ -7241,7 +7377,7 @@ Error RenderingDeviceVulkan::draw_list_begin_split(RID p_framebuffer, uint32_t p } } - if (p_initial_color_action == INITIAL_ACTION_CLEAR) { //check clear values + if (p_initial_color_action == INITIAL_ACTION_CLEAR || needs_clear_color) { //check clear values int color_count = 0; for (int i = 0; i < framebuffer->texture_ids.size(); i++) { @@ -9009,17 +9145,6 @@ void RenderingDeviceVulkan::initialize(VulkanContext *p_context, bool p_local_de { device_capabilities.version_major = p_context->get_vulkan_major(); device_capabilities.version_minor = p_context->get_vulkan_minor(); - - // get info about subgroups - VulkanContext::SubgroupCapabilities subgroup_capabilities = p_context->get_subgroup_capabilities(); - device_capabilities.subgroup_size = subgroup_capabilities.size; - device_capabilities.subgroup_in_shaders = subgroup_capabilities.supported_stages_flags_rd(); - device_capabilities.subgroup_operations = subgroup_capabilities.supported_operations_flags_rd(); - - // get info about further features - VulkanContext::MultiviewCapabilities multiview_capabilies = p_context->get_multiview_capabilities(); - device_capabilities.supports_multiview = multiview_capabilies.is_supported && multiview_capabilies.max_view_count > 1; - device_capabilities.supports_fsr_half_float = p_context->get_shader_capabilities().shader_float16_is_supported && p_context->get_storage_buffer_capabilities().storage_buffer_16_bit_access_is_supported; } context = p_context; @@ -9368,7 +9493,7 @@ String RenderingDeviceVulkan::get_captured_timestamp_name(uint32_t p_index) cons return frames[frame].timestamp_result_names[p_index]; } -uint64_t RenderingDeviceVulkan::limit_get(Limit p_limit) { +uint64_t RenderingDeviceVulkan::limit_get(Limit p_limit) const { switch (p_limit) { case LIMIT_MAX_BOUND_UNIFORM_SETS: return limits.maxBoundDescriptorSets; @@ -9438,7 +9563,18 @@ uint64_t RenderingDeviceVulkan::limit_get(Limit p_limit) { return limits.maxComputeWorkGroupSize[1]; case LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_Z: return limits.maxComputeWorkGroupSize[2]; - + case LIMIT_SUBGROUP_SIZE: { + VulkanContext::SubgroupCapabilities subgroup_capabilities = context->get_subgroup_capabilities(); + return subgroup_capabilities.size; + } + case LIMIT_SUBGROUP_IN_SHADERS: { + VulkanContext::SubgroupCapabilities subgroup_capabilities = context->get_subgroup_capabilities(); + return subgroup_capabilities.supported_stages_flags_rd(); + } + case LIMIT_SUBGROUP_OPERATIONS: { + VulkanContext::SubgroupCapabilities subgroup_capabilities = context->get_subgroup_capabilities(); + return subgroup_capabilities.supported_operations_flags_rd(); + } default: ERR_FAIL_V(0); } @@ -9538,6 +9674,25 @@ RenderingDevice *RenderingDeviceVulkan::create_local_device() { return rd; } +bool RenderingDeviceVulkan::has_feature(const Features p_feature) const { + switch (p_feature) { + case SUPPORTS_MULTIVIEW: { + VulkanContext::MultiviewCapabilities multiview_capabilies = context->get_multiview_capabilities(); + return multiview_capabilies.is_supported && multiview_capabilies.max_view_count > 1; + } break; + case SUPPORTS_FSR_HALF_FLOAT: { + return context->get_shader_capabilities().shader_float16_is_supported && context->get_storage_buffer_capabilities().storage_buffer_16_bit_access_is_supported; + } break; + case SUPPORTS_ATTACHMENT_VRS: { + VulkanContext::VRSCapabilities vrs_capabilities = context->get_vrs_capabilities(); + return vrs_capabilities.attachment_vrs_supported; + } break; + default: { + return false; + } + } +} + RenderingDeviceVulkan::RenderingDeviceVulkan() { device_capabilities.device_family = DEVICE_VULKAN; } diff --git a/drivers/vulkan/rendering_device_vulkan.h b/drivers/vulkan/rendering_device_vulkan.h index ec9e864370..7c8021251f 100644 --- a/drivers/vulkan/rendering_device_vulkan.h +++ b/drivers/vulkan/rendering_device_vulkan.h @@ -241,6 +241,7 @@ class RenderingDeviceVulkan : public RenderingDevice { Vector<AttachmentFormat> attachments; Vector<FramebufferPass> passes; uint32_t view_count = 1; + bool operator<(const FramebufferFormatKey &p_key) const { if (view_count != p_key.view_count) { return view_count < p_key.view_count; @@ -1203,7 +1204,7 @@ public: /**** Limits ****/ /****************/ - virtual uint64_t limit_get(Limit p_limit); + virtual uint64_t limit_get(Limit p_limit) const; virtual void prepare_screen_for_drawing(); void initialize(VulkanContext *p_context, bool p_local_device = false); @@ -1234,6 +1235,8 @@ public: virtual uint64_t get_driver_resource(DriverResource p_resource, RID p_rid = RID(), uint64_t p_index = 0); + virtual bool has_feature(const Features p_feature) const; + RenderingDeviceVulkan(); ~RenderingDeviceVulkan(); }; diff --git a/drivers/vulkan/vulkan_context.cpp b/drivers/vulkan/vulkan_context.cpp index 0301f5b7fa..0d8a3310fd 100644 --- a/drivers/vulkan/vulkan_context.cpp +++ b/drivers/vulkan/vulkan_context.cpp @@ -48,6 +48,18 @@ VulkanHooks *VulkanContext::vulkan_hooks = nullptr; +VkResult VulkanContext::vkCreateRenderPass2KHR(VkDevice device, const VkRenderPassCreateInfo2 *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass) { + if (fpCreateRenderPass2KHR == nullptr) { + fpCreateRenderPass2KHR = (PFN_vkCreateRenderPass2KHR)vkGetInstanceProcAddr(inst, "vkCreateRenderPass2KHR"); + } + + if (fpCreateRenderPass2KHR == nullptr) { + return VK_ERROR_EXTENSION_NOT_PRESENT; + } else { + return (fpCreateRenderPass2KHR)(device, pCreateInfo, pAllocator, pRenderPass); + } +} + VKAPI_ATTR VkBool32 VKAPI_CALL VulkanContext::_debug_messenger_callback( VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, @@ -72,20 +84,20 @@ VKAPI_ATTR VkBool32 VKAPI_CALL VulkanContext::_debug_messenger_callback( strstr(pCallbackData->pMessage, "must be a memory object") != nullptr) { return VK_FALSE; } - /* - // This is a valid warning because its illegal in Vulkan, but in practice it should work according to VK_KHR_maintenance2 - if (strstr(pCallbackData->pMessage, "VK_FORMAT_E5B9G9R9_UFLOAT_PACK32 with tiling VK_IMAGE_TILING_OPTIMAL does not support usage that includes VK_IMAGE_USAGE_STORAGE_BIT") != nullptr) { - return VK_FALSE; - } - if (strstr(pCallbackData->pMessage, "VK_FORMAT_R4G4B4A4_UNORM_PACK16 with tiling VK_IMAGE_TILING_OPTIMAL does not support usage that includes VK_IMAGE_USAGE_STORAGE_BIT") != nullptr) { - return VK_FALSE; - } -*/ // Workaround for Vulkan-Loader usability bug: https://github.com/KhronosGroup/Vulkan-Loader/issues/262. if (strstr(pCallbackData->pMessage, "wrong ELF class: ELFCLASS32") != nullptr) { return VK_FALSE; } + +#ifdef WINDOWS_ENABLED + // Some software installs Vulkan overlays in Windows registry and never cleans them up on uninstall. + // So we get spammy error level messages from the loader about those - make them verbose instead. + if (strstr(pCallbackData->pMessage, "loader_get_json: Failed to open JSON file") != nullptr) { + messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT; + } +#endif + if (pCallbackData->pMessageIdName && strstr(pCallbackData->pMessageIdName, "UNASSIGNED-CoreValidation-DrawState-ClearCmdBeforeDraw") != nullptr) { return VK_FALSE; } @@ -215,13 +227,13 @@ VkBool32 VulkanContext::_check_layers(uint32_t check_count, const char *const *c Error VulkanContext::_get_preferred_validation_layers(uint32_t *count, const char *const **names) { static const LocalVector<LocalVector<const char *>> instance_validation_layers_alt{ - // Preferred set of validation layers + // Preferred set of validation layers. { "VK_LAYER_KHRONOS_validation" }, - // Alternative (deprecated, removed in SDK 1.1.126.0) set of validation layers + // Alternative (deprecated, removed in SDK 1.1.126.0) set of validation layers. { "VK_LAYER_LUNARG_standard_validation" }, - // Alternative (deprecated, removed in SDK 1.1.121.1) set of validation layers + // Alternative (deprecated, removed in SDK 1.1.121.1) set of validation layers. { "VK_LAYER_GOOGLE_threading", "VK_LAYER_LUNARG_parameter_validation", "VK_LAYER_LUNARG_object_tracker", "VK_LAYER_LUNARG_core_validation", "VK_LAYER_GOOGLE_unique_objects" } }; @@ -269,7 +281,7 @@ typedef VkResult(VKAPI_PTR *_vkEnumerateInstanceVersion)(uint32_t *); Error VulkanContext::_obtain_vulkan_version() { // https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VkApplicationInfo.html#_description - // for Vulkan 1.0 vkEnumerateInstanceVersion is not available, including not in the loader we compile against on Android. + // For Vulkan 1.0 vkEnumerateInstanceVersion is not available, including not in the loader we compile against on Android. _vkEnumerateInstanceVersion func = (_vkEnumerateInstanceVersion)vkGetInstanceProcAddr(nullptr, "vkEnumerateInstanceVersion"); if (func != nullptr) { uint32_t api_version; @@ -279,15 +291,15 @@ Error VulkanContext::_obtain_vulkan_version() { vulkan_minor = VK_API_VERSION_MINOR(api_version); vulkan_patch = VK_API_VERSION_PATCH(api_version); } else { - // according to the documentation this shouldn't fail with anything except a memory allocation error - // in which case we're in deep trouble anyway + // According to the documentation this shouldn't fail with anything except a memory allocation error + // in which case we're in deep trouble anyway. ERR_FAIL_V(ERR_CANT_CREATE); } } else { print_line("vkEnumerateInstanceVersion not available, assuming Vulkan 1.0."); } - // we don't go above 1.2 + // We don't go above 1.2. if ((vulkan_major > 1) || (vulkan_major == 1 && vulkan_minor > 2)) { vulkan_major = 1; vulkan_minor = 2; @@ -303,7 +315,7 @@ Error VulkanContext::_initialize_extensions() { enabled_extension_count = 0; enabled_debug_utils = false; enabled_debug_report = false; - /* Look for instance extensions */ + // Look for instance extensions. VkBool32 surfaceExtFound = 0; VkBool32 platformSurfaceExtFound = 0; memset(extension_names, 0, sizeof(extension_names)); @@ -403,7 +415,7 @@ String VulkanContext::SubgroupCapabilities::supported_stages_desc() const { res += ", STAGE_COMPUTE"; } - /* these are not defined on Android GRMBL */ + // These are not defined on Android GRMBL. if (supportedStages & 0x00000100 /* VK_SHADER_STAGE_RAYGEN_BIT_KHR */) { res += ", STAGE_RAYGEN_KHR"; } @@ -429,7 +441,7 @@ String VulkanContext::SubgroupCapabilities::supported_stages_desc() const { res += ", STAGE_MESH_NV"; } - return res.substr(2); // remove first ", " + return res.substr(2); // Remove first ", " } uint32_t VulkanContext::SubgroupCapabilities::supported_operations_flags_rd() const { @@ -494,19 +506,22 @@ String VulkanContext::SubgroupCapabilities::supported_operations_desc() const { res += ", FEATURE_PARTITIONED_NV"; } - return res.substr(2); // remove first ", " + return res.substr(2); // Remove first ", " } Error VulkanContext::_check_capabilities() { // https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VK_KHR_multiview.html // https://www.khronos.org/blog/vulkan-subgroup-tutorial - // for Vulkan 1.0 vkGetPhysicalDeviceProperties2 is not available, including not in the loader we compile against on Android. + // For Vulkan 1.0 vkGetPhysicalDeviceProperties2 is not available, including not in the loader we compile against on Android. - // so we check if the functions are accessible by getting their function pointers and skipping if not - // (note that the desktop loader does a better job here but the android loader doesn't) + // So we check if the functions are accessible by getting their function pointers and skipping if not + // (note that the desktop loader does a better job here but the android loader doesn't.) - // assume not supported until proven otherwise + // Assume not supported until proven otherwise. + vrs_capabilities.pipeline_vrs_supported = false; + vrs_capabilities.primitive_vrs_supported = false; + vrs_capabilities.attachment_vrs_supported = false; multiview_capabilities.is_supported = false; multiview_capabilities.geometry_shader_is_supported = false; multiview_capabilities.tessellation_shader_is_supported = false; @@ -523,17 +538,25 @@ Error VulkanContext::_check_capabilities() { storage_buffer_capabilities.storage_push_constant_16_is_supported = false; storage_buffer_capabilities.storage_input_output_16 = false; - // check for extended features + // Check for extended features. PFN_vkGetPhysicalDeviceFeatures2 vkGetPhysicalDeviceFeatures2_func = (PFN_vkGetPhysicalDeviceFeatures2)vkGetInstanceProcAddr(inst, "vkGetPhysicalDeviceFeatures2"); if (vkGetPhysicalDeviceFeatures2_func == nullptr) { - // In Vulkan 1.0 might be accessible under its original extension name + // In Vulkan 1.0 might be accessible under its original extension name. vkGetPhysicalDeviceFeatures2_func = (PFN_vkGetPhysicalDeviceFeatures2)vkGetInstanceProcAddr(inst, "vkGetPhysicalDeviceFeatures2KHR"); } if (vkGetPhysicalDeviceFeatures2_func != nullptr) { - // check our extended features + // Check our extended features. + VkPhysicalDeviceFragmentShadingRateFeaturesKHR vrs_features = { + /*sType*/ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR, + /*pNext*/ nullptr, + /*pipelineFragmentShadingRate*/ false, + /*primitiveFragmentShadingRate*/ false, + /*attachmentFragmentShadingRate*/ false, + }; + VkPhysicalDeviceShaderFloat16Int8FeaturesKHR shader_features = { /*sType*/ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES_KHR, - /*pNext*/ nullptr, + /*pNext*/ &vrs_features, /*shaderFloat16*/ false, /*shaderInt8*/ false, }; @@ -561,6 +584,10 @@ Error VulkanContext::_check_capabilities() { vkGetPhysicalDeviceFeatures2_func(gpu, &device_features); + vrs_capabilities.pipeline_vrs_supported = vrs_features.pipelineFragmentShadingRate; + vrs_capabilities.primitive_vrs_supported = vrs_features.primitiveFragmentShadingRate; + vrs_capabilities.attachment_vrs_supported = vrs_features.attachmentFragmentShadingRate; + multiview_capabilities.is_supported = multiview_features.multiview; multiview_capabilities.geometry_shader_is_supported = multiview_features.multiviewGeometryShader; multiview_capabilities.tessellation_shader_is_supported = multiview_features.multiviewTessellationShader; @@ -574,31 +601,40 @@ Error VulkanContext::_check_capabilities() { storage_buffer_capabilities.storage_input_output_16 = storage_feature.storageInputOutput16; } - // check extended properties + // Check extended properties. PFN_vkGetPhysicalDeviceProperties2 device_properties_func = (PFN_vkGetPhysicalDeviceProperties2)vkGetInstanceProcAddr(inst, "vkGetPhysicalDeviceProperties2"); if (device_properties_func == nullptr) { - // In Vulkan 1.0 might be accessible under its original extension name + // In Vulkan 1.0 might be accessible under its original extension name. device_properties_func = (PFN_vkGetPhysicalDeviceProperties2)vkGetInstanceProcAddr(inst, "vkGetPhysicalDeviceProperties2KHR"); } if (device_properties_func != nullptr) { + VkPhysicalDeviceFragmentShadingRatePropertiesKHR vrsProperties; VkPhysicalDeviceMultiviewProperties multiviewProperties; VkPhysicalDeviceSubgroupProperties subgroupProperties; VkPhysicalDeviceProperties2 physicalDeviceProperties; + void *nextptr = nullptr; subgroupProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES; - subgroupProperties.pNext = nullptr; - - physicalDeviceProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; + subgroupProperties.pNext = nextptr; + nextptr = &subgroupProperties; if (multiview_capabilities.is_supported) { multiviewProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES; - multiviewProperties.pNext = &subgroupProperties; + multiviewProperties.pNext = nextptr; - physicalDeviceProperties.pNext = &multiviewProperties; - } else { - physicalDeviceProperties.pNext = &subgroupProperties; + nextptr = &multiviewProperties; } + if (vrs_capabilities.attachment_vrs_supported) { + vrsProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_PROPERTIES_KHR; + vrsProperties.pNext = nextptr; + + nextptr = &vrsProperties; + } + + physicalDeviceProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; + physicalDeviceProperties.pNext = nextptr; + device_properties_func(gpu, &physicalDeviceProperties); subgroup_capabilities.size = subgroupProperties.subgroupSize; @@ -609,6 +645,28 @@ Error VulkanContext::_check_capabilities() { // - supportedOperations has VK_SUBGROUP_FEATURE_QUAD_BIT subgroup_capabilities.quadOperationsInAllStages = subgroupProperties.quadOperationsInAllStages; + if (vrs_capabilities.pipeline_vrs_supported || vrs_capabilities.primitive_vrs_supported || vrs_capabilities.attachment_vrs_supported) { + print_verbose("- Vulkan Variable Rate Shading supported:"); + if (vrs_capabilities.pipeline_vrs_supported) { + print_verbose(" Pipeline fragment shading rate"); + } + if (vrs_capabilities.primitive_vrs_supported) { + print_verbose(" Primitive fragment shading rate"); + } + if (vrs_capabilities.attachment_vrs_supported) { + // TODO expose these somehow to the end user + vrs_capabilities.min_texel_size.x = vrsProperties.minFragmentShadingRateAttachmentTexelSize.width; + vrs_capabilities.min_texel_size.y = vrsProperties.minFragmentShadingRateAttachmentTexelSize.height; + vrs_capabilities.max_texel_size.x = vrsProperties.maxFragmentShadingRateAttachmentTexelSize.width; + vrs_capabilities.max_texel_size.y = vrsProperties.maxFragmentShadingRateAttachmentTexelSize.height; + + print_verbose(String(" Attachment fragment shading rate") + String(", min texel size: (") + itos(vrs_capabilities.min_texel_size.x) + String(", ") + itos(vrs_capabilities.min_texel_size.y) + String(")") + String(", max texel size: (") + itos(vrs_capabilities.max_texel_size.x) + String(", ") + itos(vrs_capabilities.max_texel_size.y) + String(")")); + } + + } else { + print_verbose("- Vulkan Variable Rate Shading not supported"); + } + if (multiview_capabilities.is_supported) { multiview_capabilities.max_view_count = multiviewProperties.maxMultiviewViewCount; multiview_capabilities.max_instance_count = multiviewProperties.maxMultiviewInstanceIndex; @@ -635,10 +693,10 @@ Error VulkanContext::_check_capabilities() { } Error VulkanContext::_create_instance() { - /* obtain version */ + // Obtain Vulkan version. _obtain_vulkan_version(); - /* initialise extensions */ + // Initialize extensions. { Error err = _initialize_extensions(); if (err != OK) { @@ -726,8 +784,7 @@ Error VulkanContext::_create_instance() { #endif if (enabled_debug_utils) { - // Setup VK_EXT_debug_utils function pointers always (we use them for - // debug labels and names). + // Setup VK_EXT_debug_utils function pointers always (we use them for debug labels and names). CreateDebugUtilsMessengerEXT = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(inst, "vkCreateDebugUtilsMessengerEXT"); DestroyDebugUtilsMessengerEXT = @@ -800,7 +857,7 @@ Error VulkanContext::_create_instance() { } Error VulkanContext::_create_physical_device(VkSurfaceKHR p_surface) { - /* Make initial call to query gpu_count, then second call for gpu info*/ + // Make initial call to query gpu_count, then second call for gpu info. uint32_t gpu_count = 0; VkResult err = vkEnumeratePhysicalDevices(inst, &gpu_count, nullptr); ERR_FAIL_COND_V(err, ERR_CANT_CREATE); @@ -836,7 +893,7 @@ Error VulkanContext::_create_physical_device(VkSurfaceKHR p_surface) { return ERR_CANT_CREATE; } - // not really needed but nice to print the correct entry + // Not really needed but nice to print the correct entry. for (uint32_t i = 0; i < gpu_count; ++i) { if (physical_devices[i] == gpu) { device_index = i; @@ -948,13 +1005,13 @@ Error VulkanContext::_create_physical_device(VkSurfaceKHR p_surface) { free(physical_devices); - /* Look for device extensions */ + // Look for device extensions. uint32_t device_extension_count = 0; VkBool32 swapchainExtFound = 0; enabled_extension_count = 0; memset(extension_names, 0, sizeof(extension_names)); - /* Get identifier properties */ + // Get identifier properties. vkGetPhysicalDeviceProperties(gpu, &gpu_props); device_name = gpu_props.deviceName; @@ -996,9 +1053,16 @@ Error VulkanContext::_create_physical_device(VkSurfaceKHR p_surface) { extension_names[enabled_extension_count++] = VK_KHR_SWAPCHAIN_EXTENSION_NAME; } if (!strcmp(VK_KHR_MULTIVIEW_EXTENSION_NAME, device_extensions[i].extensionName)) { - // if multiview is supported, enable it + // If multiview is supported, enable it. extension_names[enabled_extension_count++] = VK_KHR_MULTIVIEW_EXTENSION_NAME; } + if (!strcmp(VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME, device_extensions[i].extensionName)) { + // if shading rate image is supported, enable it + extension_names[enabled_extension_count++] = VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME; + } + if (!strcmp(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME, device_extensions[i].extensionName)) { + extension_names[enabled_extension_count++] = VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME; + } if (enabled_extension_count >= MAX_EXTENSIONS) { free(device_extensions); ERR_FAIL_V_MSG(ERR_BUG, "Enabled extension count reaches MAX_EXTENSIONS, BUG"); @@ -1049,19 +1113,18 @@ Error VulkanContext::_create_physical_device(VkSurfaceKHR p_surface) { " extension.\n\nDo you have a compatible Vulkan installable client driver (ICD) installed?\n" "vkCreateInstance Failure"); - /* Call with nullptr data to get count */ + // Call with nullptr data to get count. vkGetPhysicalDeviceQueueFamilyProperties(gpu, &queue_family_count, nullptr); ERR_FAIL_COND_V(queue_family_count == 0, ERR_CANT_CREATE); queue_props = (VkQueueFamilyProperties *)malloc(queue_family_count * sizeof(VkQueueFamilyProperties)); vkGetPhysicalDeviceQueueFamilyProperties(gpu, &queue_family_count, queue_props); - // Query fine-grained feature support for this device. // If app has specific feature requirements it should check supported // features based on this query vkGetPhysicalDeviceFeatures(gpu, &physical_device_features); - physical_device_features.robustBufferAccess = false; //turn off robust buffer access, which can hamper performance on some hardware + physical_device_features.robustBufferAccess = false; // Turn off robust buffer access, which can hamper performance on some hardware. #define GET_INSTANCE_PROC_ADDR(inst, entrypoint) \ { \ @@ -1076,7 +1139,7 @@ Error VulkanContext::_create_physical_device(VkSurfaceKHR p_surface) { GET_INSTANCE_PROC_ADDR(inst, GetPhysicalDeviceSurfacePresentModesKHR); GET_INSTANCE_PROC_ADDR(inst, GetSwapchainImagesKHR); - // get info about what our vulkan driver is capable off + // Gets capability info for current Vulkan driver. { Error res = _check_capabilities(); if (res != OK) { @@ -1110,11 +1173,23 @@ Error VulkanContext::_create_device() { }; nextptr = &shader_features; + VkPhysicalDeviceFragmentShadingRateFeaturesKHR vrs_features; + if (vrs_capabilities.pipeline_vrs_supported || vrs_capabilities.primitive_vrs_supported || vrs_capabilities.attachment_vrs_supported) { + // insert into our chain to enable these features if they are available + vrs_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR; + vrs_features.pNext = nextptr; + vrs_features.pipelineFragmentShadingRate = vrs_capabilities.pipeline_vrs_supported; + vrs_features.primitiveFragmentShadingRate = vrs_capabilities.primitive_vrs_supported; + vrs_features.attachmentFragmentShadingRate = vrs_capabilities.attachment_vrs_supported; + + nextptr = &vrs_features; + } + VkPhysicalDeviceVulkan11Features vulkan11features; VkPhysicalDevice16BitStorageFeaturesKHR storage_feature; VkPhysicalDeviceMultiviewFeatures multiview_features; if (vulkan_major > 1 || vulkan_minor >= 2) { - // In Vulkan 1.2 and newer we use a newer struct to enable various features + // In Vulkan 1.2 and newer we use a newer struct to enable various features. vulkan11features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES; vulkan11features.pNext = nextptr; @@ -1132,7 +1207,7 @@ Error VulkanContext::_create_device() { vulkan11features.shaderDrawParameters = 0; nextptr = &vulkan11features; } else { - // On Vulkan 1.0 and 1.1 we use our older structs to initialise these features + // On Vulkan 1.0 and 1.1 we use our older structs to initialise these features. storage_feature.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR; storage_feature.pNext = nextptr; storage_feature.storageBuffer16BitAccess = storage_buffer_capabilities.storage_buffer_16_bit_access_is_supported; @@ -1161,7 +1236,7 @@ Error VulkanContext::_create_device() { /*ppEnabledLayerNames*/ nullptr, /*enabledExtensionCount*/ enabled_extension_count, /*ppEnabledExtensionNames*/ (const char *const *)extension_names, - /*pEnabledFeatures*/ &physical_device_features, // If specific features are required, pass them in here + /*pEnabledFeatures*/ &physical_device_features, // If specific features are required, pass them in here. }; if (separate_present_queue) { queues[1].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; @@ -1193,7 +1268,7 @@ Error VulkanContext::_initialize_queues(VkSurfaceKHR p_surface) { } // Search for a graphics and a present queue in the array of queue - // families, try to find one that supports both + // families, try to find one that supports both. uint32_t graphicsQueueFamilyIndex = UINT32_MAX; uint32_t presentQueueFamilyIndex = UINT32_MAX; for (uint32_t i = 0; i < queue_family_count; i++) { @@ -1223,7 +1298,7 @@ Error VulkanContext::_initialize_queues(VkSurfaceKHR p_surface) { free(supportsPresent); - // Generate error if could not find both a graphics and a present queue + // Generate error if could not find both a graphics and a present queue. ERR_FAIL_COND_V_MSG(graphicsQueueFamilyIndex == UINT32_MAX || presentQueueFamilyIndex == UINT32_MAX, ERR_CANT_CREATE, "Could not find both graphics and present queues\n"); @@ -1279,7 +1354,7 @@ Error VulkanContext::_initialize_queues(VkSurfaceKHR p_surface) { color_space = surfFormats[0].colorSpace; } else { // These should be ordered with the ones we want to use on top and fallback modes further down - // we want an 32bit RGBA unsigned normalised buffer or similar + // we want a 32bit RGBA unsigned normalised buffer or similar. const VkFormat allowed_formats[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM @@ -1291,7 +1366,7 @@ Error VulkanContext::_initialize_queues(VkSurfaceKHR p_surface) { ERR_FAIL_V_MSG(ERR_CANT_CREATE, "formatCount less than 1"); } - // Find the first format that we support + // Find the first format that we support. format = VK_FORMAT_UNDEFINED; for (uint32_t af = 0; af < allowed_formats_count && format == VK_FORMAT_UNDEFINED; af++) { for (uint32_t sf = 0; sf < formatCount && format == VK_FORMAT_UNDEFINED; sf++) { @@ -1323,7 +1398,7 @@ Error VulkanContext::_create_semaphores() { VkResult err; // Create semaphores to synchronize acquiring presentable buffers before - // rendering and waiting for drawing to be complete before presenting + // rendering and waiting for drawing to be complete before presenting. VkSemaphoreCreateInfo semaphoreCreateInfo = { /*sType*/ VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, /*pNext*/ nullptr, @@ -1331,7 +1406,7 @@ Error VulkanContext::_create_semaphores() { }; // Create fences that we can use to throttle if we get too far - // ahead of the image presents + // ahead of the image presents. VkFenceCreateInfo fence_ci = { /*sType*/ VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, /*pNext*/ nullptr, @@ -1351,7 +1426,7 @@ Error VulkanContext::_create_semaphores() { } frame_index = 0; - // Get Memory information and properties + // Get Memory information and properties. vkGetPhysicalDeviceMemoryProperties(gpu, &memory_properties); return OK; @@ -1426,7 +1501,7 @@ bool VulkanContext::window_is_valid_swapchain(DisplayServer::WindowID p_window) VkRenderPass VulkanContext::window_get_render_pass(DisplayServer::WindowID p_window) { ERR_FAIL_COND_V(!windows.has(p_window), VK_NULL_HANDLE); Window *w = &windows[p_window]; - //vulkan use of currentbuffer + // Vulkan use of currentbuffer. return w->render_pass; } @@ -1434,7 +1509,7 @@ VkFramebuffer VulkanContext::window_get_framebuffer(DisplayServer::WindowID p_wi ERR_FAIL_COND_V(!windows.has(p_window), VK_NULL_HANDLE); ERR_FAIL_COND_V(!buffers_prepared, VK_NULL_HANDLE); Window *w = &windows[p_window]; - //vulkan use of currentbuffer + // Vulkan use of currentbuffer. if (w->swapchain_image_resources != VK_NULL_HANDLE) { return w->swapchain_image_resources[w->current_buffer].framebuffer; } else { @@ -1459,7 +1534,7 @@ Error VulkanContext::_clean_up_swap_chain(Window *window) { } vkDeviceWaitIdle(device); - //this destroys images associated it seems + // This destroys images associated it seems. fpDestroySwapchainKHR(device, window->swapchain, nullptr); window->swapchain = VK_NULL_HANDLE; vkDestroyRenderPass(device, window->render_pass, nullptr); @@ -1485,7 +1560,7 @@ Error VulkanContext::_update_swap_chain(Window *window) { _clean_up_swap_chain(window); } - // Check the surface capabilities and formats + // Check the surface capabilities and formats. VkSurfaceCapabilitiesKHR surfCapabilities; err = fpGetPhysicalDeviceSurfaceCapabilitiesKHR(gpu, window->surface, &surfCapabilities); ERR_FAIL_COND_V(err, ERR_CANT_CREATE); @@ -1502,7 +1577,7 @@ Error VulkanContext::_update_swap_chain(Window *window) { } VkExtent2D swapchainExtent; - // width and height are either both 0xFFFFFFFF, or both not 0xFFFFFFFF. + // Width and height are either both 0xFFFFFFFF, or both not 0xFFFFFFFF. if (surfCapabilities.currentExtent.width == 0xFFFFFFFF) { // If the surface size is undefined, the size is set to the size // of the images requested, which must fit within the minimum and @@ -1522,7 +1597,7 @@ Error VulkanContext::_update_swap_chain(Window *window) { swapchainExtent.height = surfCapabilities.maxImageExtent.height; } } else { - // If the surface size is defined, the swap chain size must match + // If the surface size is defined, the swap chain size must match. swapchainExtent = surfCapabilities.currentExtent; window->width = surfCapabilities.currentExtent.width; window->height = surfCapabilities.currentExtent.height; @@ -1530,7 +1605,7 @@ Error VulkanContext::_update_swap_chain(Window *window) { if (window->width == 0 || window->height == 0) { free(presentModes); - //likely window minimized, no swapchain created + // Likely window minimized, no swapchain created. return OK; } // The FIFO present mode is guaranteed by the spec to be supported @@ -1592,7 +1667,7 @@ Error VulkanContext::_update_swap_chain(Window *window) { window->presentMode = requested_present_mode; } else { WARN_PRINT("Requested VSync mode is not available!"); - window->vsync_mode = DisplayServer::VSYNC_ENABLED; //Set to default + window->vsync_mode = DisplayServer::VSYNC_ENABLED; // Set to default. } print_verbose("Using present mode: " + String(string_VkPresentModeKHR(window->presentMode))); @@ -1601,13 +1676,13 @@ Error VulkanContext::_update_swap_chain(Window *window) { // Determine the number of VkImages to use in the swap chain. // Application desires to acquire 3 images at a time for triple - // buffering + // buffering. uint32_t desiredNumOfSwapchainImages = 3; if (desiredNumOfSwapchainImages < surfCapabilities.minImageCount) { desiredNumOfSwapchainImages = surfCapabilities.minImageCount; } // If maxImageCount is 0, we can ask for as many images as we want; - // otherwise we're limited to maxImageCount + // otherwise we're limited to maxImageCount. if ((surfCapabilities.maxImageCount > 0) && (desiredNumOfSwapchainImages > surfCapabilities.maxImageCount)) { // Application must settle for fewer images than desired: desiredNumOfSwapchainImages = surfCapabilities.maxImageCount; @@ -1620,7 +1695,7 @@ Error VulkanContext::_update_swap_chain(Window *window) { preTransform = surfCapabilities.currentTransform; } - // Find a supported composite alpha mode - one of these is guaranteed to be set + // Find a supported composite alpha mode - one of these is guaranteed to be set. VkCompositeAlphaFlagBitsKHR compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; VkCompositeAlphaFlagBitsKHR compositeAlphaFlags[4] = { VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, @@ -1667,7 +1742,7 @@ Error VulkanContext::_update_swap_chain(Window *window) { ERR_FAIL_COND_V(err, ERR_CANT_CREATE); if (swapchainImageCount == 0) { - //assign here for the first time. + // Assign here for the first time. swapchainImageCount = sp_image_count; } else { ERR_FAIL_COND_V(swapchainImageCount != sp_image_count, ERR_BUG); @@ -1725,7 +1800,9 @@ Error VulkanContext::_update_swap_chain(Window *window) { /******** FRAMEBUFFER ************/ { - const VkAttachmentDescription attachment = { + const VkAttachmentDescription2KHR attachment = { + /*sType*/ VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2_KHR, + /*pNext*/ nullptr, /*flags*/ 0, /*format*/ format, /*samples*/ VK_SAMPLE_COUNT_1_BIT, @@ -1737,14 +1814,20 @@ Error VulkanContext::_update_swap_chain(Window *window) { /*finalLayout*/ VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, }; - const VkAttachmentReference color_reference = { + const VkAttachmentReference2KHR color_reference = { + /*sType*/ VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR, + /*pNext*/ nullptr, /*attachment*/ 0, /*layout*/ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + /*aspectMask*/ 0, }; - const VkSubpassDescription subpass = { + const VkSubpassDescription2KHR subpass = { + /*sType*/ VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR, + /*pNext*/ nullptr, /*flags*/ 0, /*pipelineBindPoint*/ VK_PIPELINE_BIND_POINT_GRAPHICS, + /*viewMask*/ 0, /*inputAttachmentCount*/ 0, /*pInputAttachments*/ nullptr, /*colorAttachmentCount*/ 1, @@ -1754,8 +1837,9 @@ Error VulkanContext::_update_swap_chain(Window *window) { /*preserveAttachmentCount*/ 0, /*pPreserveAttachments*/ nullptr, }; - const VkRenderPassCreateInfo rp_info = { - /*sTyp*/ VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, + + const VkRenderPassCreateInfo2KHR rp_info = { + /*sType*/ VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2_KHR, /*pNext*/ nullptr, /*flags*/ 0, /*attachmentCount*/ 1, @@ -1764,9 +1848,11 @@ Error VulkanContext::_update_swap_chain(Window *window) { /*pSubpasses*/ &subpass, /*dependencyCount*/ 0, /*pDependencies*/ nullptr, + /*correlatedViewMaskCount*/ 0, + /*pCorrelatedViewMasks*/ nullptr, }; - err = vkCreateRenderPass(device, &rp_info, nullptr, &window->render_pass); + err = vkCreateRenderPass2KHR(device, &rp_info, nullptr, &window->render_pass); ERR_FAIL_COND_V(err, ERR_CANT_CREATE); for (uint32_t i = 0; i < swapchainImageCount; i++) { @@ -1839,7 +1925,7 @@ Error VulkanContext::_update_swap_chain(Window *window) { } } - //reset current buffer + // Reset current buffer. window->current_buffer = 0; return OK; @@ -1874,16 +1960,16 @@ void VulkanContext::append_command_buffer(VkCommandBuffer p_command_buffer) { } void VulkanContext::flush(bool p_flush_setup, bool p_flush_pending) { - // ensure everything else pending is executed + // Ensure everything else pending is executed. vkDeviceWaitIdle(device); - //flush the pending setup buffer + // Flush the pending setup buffer. bool setup_flushable = p_flush_setup && command_buffer_queue[0]; bool pending_flushable = p_flush_pending && command_buffer_count > 1; if (setup_flushable) { - //use a fence to wait for everything done + // Use a fence to wait for everything done. VkSubmitInfo submit_info; submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; submit_info.pNext = nullptr; @@ -1900,7 +1986,7 @@ void VulkanContext::flush(bool p_flush_setup, bool p_flush_pending) { } if (pending_flushable) { - //use a fence to wait for everything done + // Use a fence to wait for everything to finish. VkSubmitInfo submit_info; submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; @@ -1928,7 +2014,7 @@ Error VulkanContext::prepare_buffers() { VkResult err; - // Ensure no more than FRAME_LAG renderings are outstanding + // Ensure no more than FRAME_LAG renderings are outstanding. vkWaitForFences(device, 1, &fences[frame_index], VK_TRUE, UINT64_MAX); vkResetFences(device, 1, &fences[frame_index]); @@ -1948,13 +2034,13 @@ Error VulkanContext::prepare_buffers() { w->image_acquired_semaphores[frame_index], VK_NULL_HANDLE, &w->current_buffer); if (err == VK_ERROR_OUT_OF_DATE_KHR) { - // swapchain is out of date (e.g. the window was resized) and + // Swapchain is out of date (e.g. the window was resized) and // must be recreated: print_verbose("Vulkan: Early out of date swapchain, recreating."); - //resize_notify(); + // resize_notify(); _update_swap_chain(w); } else if (err == VK_SUBOPTIMAL_KHR) { - // swapchain is not as optimal as it could be, but the platform's + // Swapchain is not as optimal as it could be, but the platform's // presentation engine will still present the image correctly. print_verbose("Vulkan: Early suboptimal swapchain."); break; @@ -2001,7 +2087,7 @@ Error VulkanContext::swap_buffers() { uint32_t commands_to_submit = 0; if (command_buffer_queue[0] == nullptr) { - //no setup command, but commands to submit, submit from the first and skip command + // No setup command, but commands to submit, submit from the first and skip command. if (command_buffer_count > 1) { commands_ptr = command_buffer_queue.ptr() + 1; commands_to_submit = command_buffer_count - 1; @@ -2044,7 +2130,7 @@ Error VulkanContext::swap_buffers() { if (separate_present_queue) { // If we are using separate queues, change image ownership to the // present queue before presenting, waiting for the draw complete - // semaphore and signalling the ownership released semaphore when finished + // semaphore and signalling the ownership released semaphore when finished. VkFence nullFence = VK_NULL_HANDLE; pipe_stage_flags[0] = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; submit_info.waitSemaphoreCount = 1; @@ -2071,7 +2157,7 @@ Error VulkanContext::swap_buffers() { } // If we are using separate queues, we have to wait for image ownership, - // otherwise wait for draw complete + // otherwise wait for draw complete. VkPresentInfoKHR present = { /*sType*/ VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, /*pNext*/ nullptr, @@ -2176,12 +2262,12 @@ Error VulkanContext::swap_buffers() { frame_index %= FRAME_LAG; if (err == VK_ERROR_OUT_OF_DATE_KHR) { - // swapchain is out of date (e.g. the window was resized) and + // Swapchain is out of date (e.g. the window was resized) and // must be recreated: print_verbose("Vulkan: Swapchain is out of date, recreating."); resize_notify(); } else if (err == VK_SUBOPTIMAL_KHR) { - // swapchain is not as optimal as it could be, but the platform's + // Swapchain is not as optimal as it could be, but the platform's // presentation engine will still present the image correctly. print_verbose("Vulkan: Swapchain is suboptimal."); } else { @@ -2226,7 +2312,7 @@ VkPhysicalDeviceLimits VulkanContext::get_device_limits() const { RID VulkanContext::local_device_create() { LocalDevice ld; - { //create device + { // Create device. VkResult err; float queue_priorities[1] = { 0.0 }; VkDeviceQueueCreateInfo queues[2]; @@ -2247,13 +2333,13 @@ RID VulkanContext::local_device_create() { /*ppEnabledLayerNames */ nullptr, /*enabledExtensionCount */ enabled_extension_count, /*ppEnabledExtensionNames */ (const char *const *)extension_names, - /*pEnabledFeatures */ &physical_device_features, // If specific features are required, pass them in here + /*pEnabledFeatures */ &physical_device_features, // If specific features are required, pass them in here. }; err = vkCreateDevice(gpu, &sdevice, nullptr, &ld.device); ERR_FAIL_COND_V(err, RID()); } - { //create graphics queue + { // Create graphics queue. vkGetDeviceQueue(ld.device, graphics_queue_family_index, 0, &ld.queue); } @@ -2315,7 +2401,7 @@ void VulkanContext::command_begin_label(VkCommandBuffer p_command_buffer, String return; } - CharString cs = p_label_name.utf8().get_data(); + CharString cs = p_label_name.utf8(); VkDebugUtilsLabelEXT label; label.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT; label.pNext = nullptr; @@ -2331,7 +2417,7 @@ void VulkanContext::command_insert_label(VkCommandBuffer p_command_buffer, Strin if (!enabled_debug_utils) { return; } - CharString cs = p_label_name.utf8().get_data(); + CharString cs = p_label_name.utf8(); VkDebugUtilsLabelEXT label; label.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT; label.pNext = nullptr; diff --git a/drivers/vulkan/vulkan_context.h b/drivers/vulkan/vulkan_context.h index e96facfacb..35e7ce7db8 100644 --- a/drivers/vulkan/vulkan_context.h +++ b/drivers/vulkan/vulkan_context.h @@ -69,6 +69,15 @@ public: uint32_t max_instance_count; }; + struct VRSCapabilities { + bool pipeline_vrs_supported; // We can specify our fragment rate on a pipeline level + bool primitive_vrs_supported; // We can specify our fragment rate on each drawcall + bool attachment_vrs_supported; // We can provide a density map attachment on our framebuffer + + Size2i min_texel_size; + Size2i max_texel_size; + }; + struct ShaderCapabilities { bool shader_float16_is_supported; bool shader_int8_is_supported; @@ -104,6 +113,7 @@ private: uint32_t vulkan_patch = 0; SubgroupCapabilities subgroup_capabilities; MultiviewCapabilities multiview_capabilities; + VRSCapabilities vrs_capabilities; ShaderCapabilities shader_capabilities; StorageBufferCapabilities storage_buffer_capabilities; @@ -206,6 +216,7 @@ private: PFN_vkQueuePresentKHR fpQueuePresentKHR = nullptr; PFN_vkGetRefreshCycleDurationGOOGLE fpGetRefreshCycleDurationGOOGLE = nullptr; PFN_vkGetPastPresentationTimingGOOGLE fpGetPastPresentationTimingGOOGLE = nullptr; + PFN_vkCreateRenderPass2KHR fpCreateRenderPass2KHR = nullptr; VkDebugUtilsMessengerEXT dbg_messenger = VK_NULL_HANDLE; VkDebugReportCallbackEXT dbg_debug_report = VK_NULL_HANDLE; @@ -256,12 +267,16 @@ protected: Error _get_preferred_validation_layers(uint32_t *count, const char *const **names); public: + // Extension calls + VkResult vkCreateRenderPass2KHR(VkDevice device, const VkRenderPassCreateInfo2 *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass); + uint32_t get_vulkan_major() const { return vulkan_major; }; uint32_t get_vulkan_minor() const { return vulkan_minor; }; - SubgroupCapabilities get_subgroup_capabilities() const { return subgroup_capabilities; }; - MultiviewCapabilities get_multiview_capabilities() const { return multiview_capabilities; }; - ShaderCapabilities get_shader_capabilities() const { return shader_capabilities; }; - StorageBufferCapabilities get_storage_buffer_capabilities() const { return storage_buffer_capabilities; }; + const SubgroupCapabilities &get_subgroup_capabilities() const { return subgroup_capabilities; }; + const MultiviewCapabilities &get_multiview_capabilities() const { return multiview_capabilities; }; + const VRSCapabilities &get_vrs_capabilities() const { return vrs_capabilities; }; + const ShaderCapabilities &get_shader_capabilities() const { return shader_capabilities; }; + const StorageBufferCapabilities &get_storage_buffer_capabilities() const { return storage_buffer_capabilities; }; VkDevice get_device(); VkPhysicalDevice get_physical_device(); @@ -315,4 +330,4 @@ public: virtual ~VulkanContext(); }; -#endif // VULKAN_DEVICE_H +#endif // VULKAN_CONTEXT_H diff --git a/drivers/vulkan/vulkan_hooks.h b/drivers/vulkan/vulkan_hooks.h index 3f244b4d45..dec2042d0d 100644 --- a/drivers/vulkan/vulkan_hooks.h +++ b/drivers/vulkan/vulkan_hooks.h @@ -45,4 +45,4 @@ public: virtual ~VulkanHooks(){}; }; -#endif +#endif // VULKAN_HOOKS_H diff --git a/drivers/wasapi/audio_driver_wasapi.h b/drivers/wasapi/audio_driver_wasapi.h index 89ed90e97b..9058077a1f 100644 --- a/drivers/wasapi/audio_driver_wasapi.h +++ b/drivers/wasapi/audio_driver_wasapi.h @@ -120,4 +120,5 @@ public: }; #endif // WASAPI_ENABLED + #endif // AUDIO_DRIVER_WASAPI_H diff --git a/drivers/winmidi/midi_driver_winmidi.h b/drivers/winmidi/midi_driver_winmidi.h index 6572ba0c16..e42f3df4cf 100644 --- a/drivers/winmidi/midi_driver_winmidi.h +++ b/drivers/winmidi/midi_driver_winmidi.h @@ -28,11 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifdef WINMIDI_ENABLED - #ifndef MIDI_DRIVER_WINMIDI_H #define MIDI_DRIVER_WINMIDI_H +#ifdef WINMIDI_ENABLED + #include "core/os/midi_driver.h" #include "core/templates/vector.h" @@ -57,5 +57,6 @@ public: virtual ~MIDIDriverWinMidi(); }; -#endif // MIDI_DRIVER_WINMIDI_H #endif // WINMIDI_ENABLED + +#endif // MIDI_DRIVER_WINMIDI_H diff --git a/drivers/xaudio2/audio_driver_xaudio2.h b/drivers/xaudio2/audio_driver_xaudio2.h index 9072269a0e..81432ceb8e 100644 --- a/drivers/xaudio2/audio_driver_xaudio2.h +++ b/drivers/xaudio2/audio_driver_xaudio2.h @@ -106,4 +106,4 @@ public: ~AudioDriverXAudio2() {} }; -#endif +#endif // AUDIO_DRIVER_XAUDIO2_H |