summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/alsa/audio_driver_alsa.cpp6
-rw-r--r--drivers/alsa/audio_driver_alsa.h2
-rw-r--r--drivers/coreaudio/audio_driver_coreaudio.cpp28
-rw-r--r--drivers/coreaudio/audio_driver_coreaudio.h20
-rw-r--r--drivers/coremidi/midi_driver_coremidi.h7
-rw-r--r--drivers/gl_context/SCsub2
-rw-r--r--drivers/gles3/SCsub1
-rw-r--r--drivers/gles3/effects/copy_effects.cpp1
-rw-r--r--drivers/gles3/effects/copy_effects.h7
-rw-r--r--drivers/gles3/environment/SCsub5
-rw-r--r--drivers/gles3/environment/fog.cpp66
-rw-r--r--drivers/gles3/environment/fog.h62
-rw-r--r--drivers/gles3/environment/gi.cpp133
-rw-r--r--drivers/gles3/environment/gi.h96
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.cpp72
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.h16
-rw-r--r--drivers/gles3/rasterizer_gles3.cpp21
-rw-r--r--drivers/gles3/rasterizer_gles3.h18
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp810
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.h254
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.cpp640
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.h322
-rw-r--r--drivers/gles3/shader_gles3.h11
-rw-r--r--drivers/gles3/shaders/SCsub2
-rw-r--r--drivers/gles3/shaders/canvas.glsl10
-rw-r--r--drivers/gles3/shaders/canvas_uniforms_inc.glsl4
-rw-r--r--drivers/gles3/shaders/cubemap_filter.glsl88
-rw-r--r--drivers/gles3/shaders/scene.glsl68
-rw-r--r--drivers/gles3/shaders/sky.glsl4
-rw-r--r--drivers/gles3/storage/config.cpp7
-rw-r--r--drivers/gles3/storage/config.h2
-rw-r--r--drivers/gles3/storage/light_storage.cpp121
-rw-r--r--drivers/gles3/storage/light_storage.h29
-rw-r--r--drivers/gles3/storage/material_storage.cpp704
-rw-r--r--drivers/gles3/storage/material_storage.h114
-rw-r--r--drivers/gles3/storage/mesh_storage.cpp339
-rw-r--r--drivers/gles3/storage/mesh_storage.h24
-rw-r--r--drivers/gles3/storage/particles_storage.h2
-rw-r--r--drivers/gles3/storage/texture_storage.cpp66
-rw-r--r--drivers/gles3/storage/texture_storage.h34
-rw-r--r--drivers/gles3/storage/utilities.cpp353
-rw-r--r--drivers/gles3/storage/utilities.h159
-rw-r--r--drivers/png/image_loader_png.h2
-rw-r--r--drivers/png/png_driver_common.h2
-rw-r--r--drivers/png/resource_saver_png.cpp2
-rw-r--r--drivers/png/resource_saver_png.h2
-rw-r--r--drivers/pulseaudio/audio_driver_pulseaudio.cpp8
-rw-r--r--drivers/pulseaudio/audio_driver_pulseaudio.h8
-rw-r--r--drivers/register_driver_types.h2
-rw-r--r--drivers/unix/dir_access_unix.cpp27
-rw-r--r--drivers/unix/dir_access_unix.h55
-rw-r--r--drivers/unix/file_access_unix.cpp6
-rw-r--r--drivers/unix/file_access_unix.h44
-rw-r--r--drivers/unix/ip_unix.cpp4
-rw-r--r--drivers/unix/ip_unix.h1
-rw-r--r--drivers/unix/net_socket_posix.h6
-rw-r--r--drivers/unix/os_unix.cpp9
-rw-r--r--drivers/unix/os_unix.h4
-rw-r--r--drivers/unix/syslog_logger.h4
-rw-r--r--drivers/unix/thread_posix.h2
-rw-r--r--drivers/vulkan/SCsub8
-rw-r--r--drivers/vulkan/rendering_device_vulkan.cpp1534
-rw-r--r--drivers/vulkan/rendering_device_vulkan.h141
-rw-r--r--drivers/vulkan/vulkan_context.cpp368
-rw-r--r--drivers/vulkan/vulkan_context.h35
-rw-r--r--drivers/vulkan/vulkan_hooks.h2
-rw-r--r--drivers/wasapi/audio_driver_wasapi.cpp14
-rw-r--r--drivers/wasapi/audio_driver_wasapi.h7
-rw-r--r--drivers/windows/dir_access_windows.cpp2
-rw-r--r--drivers/windows/dir_access_windows.h38
-rw-r--r--drivers/windows/file_access_windows.h38
-rw-r--r--drivers/winmidi/midi_driver_winmidi.h7
-rw-r--r--drivers/xaudio2/audio_driver_xaudio2.h2
73 files changed, 3747 insertions, 3367 deletions
diff --git a/drivers/alsa/audio_driver_alsa.cpp b/drivers/alsa/audio_driver_alsa.cpp
index f86c4d82ef..1f40641b80 100644
--- a/drivers/alsa/audio_driver_alsa.cpp
+++ b/drivers/alsa/audio_driver_alsa.cpp
@@ -50,7 +50,7 @@ Error AudioDriverALSA::init_device() {
// If there is a specified device check that it is really present
if (device_name != "Default") {
- Array list = get_device_list();
+ PackedStringArray list = get_device_list();
if (list.find(device_name) == -1) {
device_name = "Default";
new_device = "Default";
@@ -266,8 +266,8 @@ AudioDriver::SpeakerMode AudioDriverALSA::get_speaker_mode() const {
return speaker_mode;
}
-Array AudioDriverALSA::get_device_list() {
- Array list;
+PackedStringArray AudioDriverALSA::get_device_list() {
+ PackedStringArray list;
list.push_back("Default");
diff --git a/drivers/alsa/audio_driver_alsa.h b/drivers/alsa/audio_driver_alsa.h
index dbb40fa088..3f9d9b33fb 100644
--- a/drivers/alsa/audio_driver_alsa.h
+++ b/drivers/alsa/audio_driver_alsa.h
@@ -77,7 +77,7 @@ public:
virtual void start();
virtual int get_mix_rate() const;
virtual SpeakerMode get_speaker_mode() const;
- virtual Array get_device_list();
+ virtual PackedStringArray get_device_list();
virtual String get_device();
virtual void set_device(String device);
virtual void lock();
diff --git a/drivers/coreaudio/audio_driver_coreaudio.cpp b/drivers/coreaudio/audio_driver_coreaudio.cpp
index 276e69e470..51fb1f99e0 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,10 +491,10 @@ Error AudioDriverCoreAudio::capture_stop() {
return OK;
}
-#ifdef OSX_ENABLED
+#ifdef MACOS_ENABLED
-Array AudioDriverCoreAudio::_get_device_list(bool capture) {
- Array list;
+PackedStringArray AudioDriverCoreAudio::_get_device_list(bool capture) {
+ PackedStringArray list;
list.push_back("Default");
@@ -637,7 +637,7 @@ void AudioDriverCoreAudio::_set_device(const String &device, bool capture) {
}
}
-Array AudioDriverCoreAudio::get_device_list() {
+PackedStringArray AudioDriverCoreAudio::get_device_list() {
return _get_device_list();
}
@@ -659,7 +659,7 @@ void AudioDriverCoreAudio::capture_set_device(const String &p_name) {
}
}
-Array AudioDriverCoreAudio::capture_get_device_list() {
+PackedStringArray AudioDriverCoreAudio::capture_get_device_list() {
return _get_device_list(true);
}
diff --git a/drivers/coreaudio/audio_driver_coreaudio.h b/drivers/coreaudio/audio_driver_coreaudio.h
index f86037f092..aac5077bb1 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,8 +58,8 @@ class AudioDriverCoreAudio : public AudioDriver {
Vector<int32_t> samples_in;
Vector<int16_t> input_buf;
-#ifdef OSX_ENABLED
- Array _get_device_list(bool capture = false);
+#ifdef MACOS_ENABLED
+ PackedStringArray _get_device_list(bool capture = false);
void _set_device(const String &device, bool capture = false);
static OSStatus input_device_address_cb(AudioObjectID inObjectID,
@@ -106,12 +106,12 @@ public:
bool try_lock();
void stop();
-#ifdef OSX_ENABLED
- virtual Array get_device_list();
+#ifdef MACOS_ENABLED
+ virtual PackedStringArray get_device_list();
virtual String get_device();
virtual void set_device(String device);
- virtual Array capture_get_device_list();
+ virtual PackedStringArray capture_get_device_list();
virtual void capture_set_device(const String &p_name);
virtual String capture_get_device();
#endif
@@ -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/SCsub b/drivers/gles3/SCsub
index 5760fd714e..506312df80 100644
--- a/drivers/gles3/SCsub
+++ b/drivers/gles3/SCsub
@@ -7,3 +7,4 @@ env.add_source_files(env.drivers_sources, "*.cpp")
SConscript("shaders/SCsub")
SConscript("storage/SCsub")
SConscript("effects/SCsub")
+SConscript("environment/SCsub")
diff --git a/drivers/gles3/effects/copy_effects.cpp b/drivers/gles3/effects/copy_effects.cpp
index c8e6c2b476..de0181f887 100644
--- a/drivers/gles3/effects/copy_effects.cpp
+++ b/drivers/gles3/effects/copy_effects.cpp
@@ -111,6 +111,7 @@ CopyEffects::~CopyEffects() {
glDeleteVertexArrays(1, &screen_triangle_array);
glDeleteBuffers(1, &quad);
glDeleteVertexArrays(1, &quad_array);
+ copy.shader.version_free(copy.shader_version);
}
void CopyEffects::copy_to_rect(const Rect2i &p_rect) {
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/SCsub b/drivers/gles3/environment/SCsub
new file mode 100644
index 0000000000..91e1140b75
--- /dev/null
+++ b/drivers/gles3/environment/SCsub
@@ -0,0 +1,5 @@
+#!/usr/bin/env python
+
+Import("env")
+
+env.add_source_files(env.drivers_sources, "*.cpp")
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
new file mode 100644
index 0000000000..84cdb81d35
--- /dev/null
+++ b/drivers/gles3/environment/gi.cpp
@@ -0,0 +1,133 @@
+/*************************************************************************/
+/* gi.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 "gi.h"
+
+using namespace GLES3;
+
+/* VOXEL GI API */
+
+RID GI::voxel_gi_allocate() {
+ return RID();
+}
+
+void GI::voxel_gi_free(RID p_rid) {
+}
+
+void GI::voxel_gi_initialize(RID p_rid) {
+}
+
+void GI::voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) {
+}
+
+AABB GI::voxel_gi_get_bounds(RID p_voxel_gi) const {
+ return AABB();
+}
+
+Vector3i GI::voxel_gi_get_octree_size(RID p_voxel_gi) const {
+ return Vector3i();
+}
+
+Vector<uint8_t> GI::voxel_gi_get_octree_cells(RID p_voxel_gi) const {
+ return Vector<uint8_t>();
+}
+
+Vector<uint8_t> GI::voxel_gi_get_data_cells(RID p_voxel_gi) const {
+ return Vector<uint8_t>();
+}
+
+Vector<uint8_t> GI::voxel_gi_get_distance_field(RID p_voxel_gi) const {
+ return Vector<uint8_t>();
+}
+
+Vector<int> GI::voxel_gi_get_level_counts(RID p_voxel_gi) const {
+ return Vector<int>();
+}
+
+Transform3D GI::voxel_gi_get_to_cell_xform(RID p_voxel_gi) const {
+ return Transform3D();
+}
+
+void GI::voxel_gi_set_dynamic_range(RID p_voxel_gi, float p_range) {
+}
+
+float GI::voxel_gi_get_dynamic_range(RID p_voxel_gi) const {
+ return 0;
+}
+
+void GI::voxel_gi_set_propagation(RID p_voxel_gi, float p_range) {
+}
+
+float GI::voxel_gi_get_propagation(RID p_voxel_gi) const {
+ return 0;
+}
+
+void GI::voxel_gi_set_energy(RID p_voxel_gi, float p_range) {
+}
+
+float GI::voxel_gi_get_energy(RID p_voxel_gi) const {
+ return 0.0;
+}
+
+void GI::voxel_gi_set_bias(RID p_voxel_gi, float p_range) {
+}
+
+float GI::voxel_gi_get_bias(RID p_voxel_gi) const {
+ return 0.0;
+}
+
+void GI::voxel_gi_set_normal_bias(RID p_voxel_gi, float p_range) {
+}
+
+float GI::voxel_gi_get_normal_bias(RID p_voxel_gi) const {
+ return 0.0;
+}
+
+void GI::voxel_gi_set_interior(RID p_voxel_gi, bool p_enable) {
+}
+
+bool GI::voxel_gi_is_interior(RID p_voxel_gi) const {
+ return false;
+}
+
+void GI::voxel_gi_set_use_two_bounces(RID p_voxel_gi, bool p_enable) {
+}
+
+bool GI::voxel_gi_is_using_two_bounces(RID p_voxel_gi) const {
+ return false;
+}
+
+uint32_t GI::voxel_gi_get_version(RID p_voxel_gi) const {
+ return 0;
+}
+
+#endif // GLES3_ENABLED
diff --git a/drivers/gles3/environment/gi.h b/drivers/gles3/environment/gi.h
new file mode 100644
index 0000000000..7a0634f22b
--- /dev/null
+++ b/drivers/gles3/environment/gi.h
@@ -0,0 +1,96 @@
+/*************************************************************************/
+/* gi.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 GI_GLES3_H
+#define GI_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_gi.h"
+
+#include "platform_config.h"
+#ifndef OPENGL_INCLUDE_H
+#include <GLES3/gl3.h>
+#else
+#include OPENGL_INCLUDE_H
+#endif
+
+namespace GLES3 {
+
+class GI : public RendererGI {
+public:
+ /* VOXEL GI API */
+
+ virtual RID voxel_gi_allocate() override;
+ virtual void voxel_gi_free(RID p_rid) override;
+ virtual void voxel_gi_initialize(RID p_rid) override;
+ virtual void voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) override;
+
+ virtual AABB voxel_gi_get_bounds(RID p_voxel_gi) const override;
+ virtual Vector3i voxel_gi_get_octree_size(RID p_voxel_gi) const override;
+ virtual Vector<uint8_t> voxel_gi_get_octree_cells(RID p_voxel_gi) const override;
+ virtual Vector<uint8_t> voxel_gi_get_data_cells(RID p_voxel_gi) const override;
+ virtual Vector<uint8_t> voxel_gi_get_distance_field(RID p_voxel_gi) const override;
+
+ virtual Vector<int> voxel_gi_get_level_counts(RID p_voxel_gi) const override;
+ virtual Transform3D voxel_gi_get_to_cell_xform(RID p_voxel_gi) const override;
+
+ virtual void voxel_gi_set_dynamic_range(RID p_voxel_gi, float p_range) override;
+ virtual float voxel_gi_get_dynamic_range(RID p_voxel_gi) const override;
+
+ virtual void voxel_gi_set_propagation(RID p_voxel_gi, float p_range) override;
+ virtual float voxel_gi_get_propagation(RID p_voxel_gi) const override;
+
+ virtual void voxel_gi_set_energy(RID p_voxel_gi, float p_range) override;
+ virtual float voxel_gi_get_energy(RID p_voxel_gi) const override;
+
+ virtual void voxel_gi_set_bias(RID p_voxel_gi, float p_range) override;
+ virtual float voxel_gi_get_bias(RID p_voxel_gi) const override;
+
+ virtual void voxel_gi_set_normal_bias(RID p_voxel_gi, float p_range) override;
+ virtual float voxel_gi_get_normal_bias(RID p_voxel_gi) const override;
+
+ virtual void voxel_gi_set_interior(RID p_voxel_gi, bool p_enable) override;
+ virtual bool voxel_gi_is_interior(RID p_voxel_gi) const override;
+
+ 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 uint32_t voxel_gi_get_version(RID p_voxel_gi) const override;
+};
+
+}; // namespace GLES3
+
+#endif // GLES3_ENABLED
+
+#endif // GI_GLES3_H
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp
index 32d279a635..28802f571c 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);
@@ -201,6 +201,7 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
bool material_screen_texture_found = false;
Rect2 back_buffer_rect;
bool backbuffer_copy = false;
+ bool backbuffer_gen_mipmaps = false;
Item *ci = p_item_list;
Item *canvas_group_owner = nullptr;
@@ -225,6 +226,7 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
if (!material_screen_texture_found) {
backbuffer_copy = true;
back_buffer_rect = Rect2();
+ backbuffer_gen_mipmaps = md->shader_data->uses_screen_texture_mipmaps;
}
}
@@ -282,7 +284,7 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list);
item_count = 0;
- texture_storage->render_target_copy_to_back_buffer(p_to_render_target, back_buffer_rect, true);
+ texture_storage->render_target_copy_to_back_buffer(p_to_render_target, back_buffer_rect, backbuffer_gen_mipmaps);
backbuffer_copy = false;
material_screen_texture_found = true; //after a backbuffer copy, screen texture makes no further copies
@@ -689,6 +691,10 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
_bind_instance_data_buffer(1);
glBindVertexArray(pb->vertex_array);
+ if (pb->color_disabled) {
+ glVertexAttrib4f(RS::ARRAY_COLOR, pb->color.r, pb->color.g, pb->color.b, pb->color.a);
+ }
+
if (pb->index_buffer != 0) {
glDrawElements(prim[polygon->primitive], pb->count, GL_UNSIGNED_INT, nullptr);
} else {
@@ -698,6 +704,11 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
state.fences[state.current_buffer] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
state.current_buffer = (state.current_buffer + 1) % state.canvas_instance_data_buffers.size();
+
+ if (pb->color_disabled) {
+ // Reset so this doesn't pollute other draw calls.
+ glVertexAttrib4f(RS::ARRAY_COLOR, 1.0, 1.0, 1.0, 1.0);
+ }
} break;
case Item::Command::TYPE_PRIMITIVE: {
@@ -758,7 +769,6 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
GLuint multimesh_buffer = 0;
uint32_t multimesh_stride = 0;
uint32_t multimesh_color_offset = 0;
- uint32_t multimesh_custom_data_offset = 0;
bool multimesh_uses_color = false;
bool multimesh_uses_custom_data = false;
@@ -788,7 +798,6 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
multimesh_buffer = mesh_storage->multimesh_get_gl_buffer(multimesh);
multimesh_stride = mesh_storage->multimesh_get_stride(multimesh);
multimesh_color_offset = mesh_storage->multimesh_get_color_offset(multimesh);
- multimesh_custom_data_offset = mesh_storage->multimesh_get_custom_data_offset(multimesh);
multimesh_uses_color = mesh_storage->multimesh_uses_colors(multimesh);
multimesh_uses_custom_data = mesh_storage->multimesh_uses_custom_data(multimesh);
}
@@ -808,10 +817,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);
@@ -854,22 +861,17 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
if (instance_count > 1) {
// Bind instance buffers.
glBindBuffer(GL_ARRAY_BUFFER, multimesh_buffer);
- glEnableVertexAttribArray(5);
- glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(0));
- glVertexAttribDivisor(5, 1);
- glEnableVertexAttribArray(6);
- glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(4 * 4));
- glVertexAttribDivisor(6, 1);
-
- if (multimesh_uses_color) {
- glEnableVertexAttribArray(7);
- glVertexAttribPointer(7, 4, GL_FLOAT, GL_FALSE, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(multimesh_color_offset * sizeof(float)));
- glVertexAttribDivisor(7, 1);
- }
- if (multimesh_uses_custom_data) {
- glEnableVertexAttribArray(8);
- glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(multimesh_custom_data_offset * sizeof(float)));
- glVertexAttribDivisor(8, 1);
+ glEnableVertexAttribArray(1);
+ glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(0));
+ glVertexAttribDivisor(1, 1);
+ glEnableVertexAttribArray(2);
+ glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(4 * 4));
+ glVertexAttribDivisor(2, 1);
+
+ if (multimesh_uses_color || multimesh_uses_custom_data) {
+ glEnableVertexAttribArray(5);
+ glVertexAttribIPointer(5, 4, GL_UNSIGNED_INT, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(multimesh_color_offset * sizeof(float)));
+ glVertexAttribDivisor(5, 1);
}
}
@@ -880,7 +882,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 {
@@ -1215,7 +1217,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) {
@@ -1268,11 +1270,7 @@ RendererCanvasRender::PolygonID RasterizerCanvasGLES3::request_polygon(const Vec
}
// Next add colors
- if (p_colors.size() == 1) {
- glDisableVertexAttribArray(RS::ARRAY_COLOR);
- Color m = p_colors[0];
- glVertexAttrib4f(RS::ARRAY_COLOR, m.r, m.g, m.b, m.a);
- } else if ((uint32_t)p_colors.size() == vertex_count) {
+ if ((uint32_t)p_colors.size() == vertex_count) {
glEnableVertexAttribArray(RS::ARRAY_COLOR);
glVertexAttribPointer(RS::ARRAY_COLOR, 4, GL_FLOAT, GL_FALSE, stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(base_offset * sizeof(float)));
@@ -1287,7 +1285,8 @@ RendererCanvasRender::PolygonID RasterizerCanvasGLES3::request_polygon(const Vec
base_offset += 4;
} else {
glDisableVertexAttribArray(RS::ARRAY_COLOR);
- glVertexAttrib4f(RS::ARRAY_COLOR, 1.0, 1.0, 1.0, 1.0);
+ pb.color_disabled = true;
+ pb.color = p_colors.size() == 1 ? p_colors[0] : Color(1.0, 1.0, 1.0, 1.0);
}
if ((uint32_t)p_uvs.size() == vertex_count) {
@@ -1417,9 +1416,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();
@@ -1572,7 +1570,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";
@@ -1612,6 +1610,8 @@ void fragment() {
RasterizerCanvasGLES3::~RasterizerCanvasGLES3() {
GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
+ memdelete_arr(state.instance_data_array);
+
GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_free(state.canvas_shader_default_version);
material_storage->material_free(default_canvas_group_material);
material_storage->shader_free(default_canvas_group_shader);
diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h
index 31e82401f9..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;
@@ -238,6 +235,8 @@ public:
GLuint vertex_array;
GLuint index_buffer;
int count;
+ bool color_disabled = false;
+ Color color;
};
struct {
@@ -258,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 c8705dc8c8..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,12 +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);
}
@@ -263,15 +268,17 @@ 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);
particles_storage = memnew(GLES3::ParticlesStorage);
light_storage = memnew(GLES3::LightStorage);
copy_effects = memnew(GLES3::CopyEffects);
- storage = memnew(RasterizerStorageGLES3);
- canvas = memnew(RasterizerCanvasGLES3(storage));
- scene = memnew(RasterizerSceneGLES3(storage));
+ gi = memnew(GLES3::GI);
+ 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 5f1cbab849..97543af0d5 100644
--- a/drivers/gles3/rasterizer_gles3.h
+++ b/drivers/gles3/rasterizer_gles3.h
@@ -28,15 +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"
@@ -44,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:
@@ -54,25 +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; }
- RendererStorage *get_storage() { return storage; }
+ RendererGI *get_gi() { return gi; }
+ RendererFog *get_fog() { return fog; }
RendererCanvasRender *get_canvas() { return canvas; }
RendererSceneRender *get_scene() { return scene; }
@@ -106,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 7ce1300d07..9bbe960d86 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;
- geometry_instance_dirty_list.add(&ginstance->dirty_list_element);
+ 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) {
+}
+
+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);
@@ -491,7 +340,7 @@ void RasterizerSceneGLES3::_geometry_instance_update(GeometryInstance *p_geometr
}
}
- ginstance->instance_count = 1;
+ ginstance->instance_count = -1;
} break;
@@ -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) - 1;
// Left uninitialized, will attach a texture at render time
glGenFramebuffers(1, &sky->radiance_framebuffer);
@@ -675,7 +523,7 @@ void RasterizerSceneGLES3::_update_dirty_skys() {
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 0);
- glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, sky->mipmap_count);
+ glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, sky->mipmap_count - 1);
glGenTextures(1, &sky->raw_radiance);
glBindTexture(GL_TEXTURE_CUBE_MAP, sky->raw_radiance);
@@ -696,7 +544,8 @@ void RasterizerSceneGLES3::_update_dirty_skys() {
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 0);
- glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, sky->mipmap_count);
+ glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, sky->mipmap_count - 1);
+
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
}
@@ -712,13 +561,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;
@@ -853,22 +702,23 @@ void RasterizerSceneGLES3::_setup_sky(Environment *p_env, RID p_render_buffers,
}
if (!sky->radiance) {
+ _invalidate_sky(sky);
_update_dirty_skys();
}
}
}
-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 +748,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 +773,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 +837,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 +855,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;
@@ -1017,7 +867,6 @@ void RasterizerSceneGLES3::_update_sky_radiance(Environment *p_env, const Camera
GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::TIME, time, shader_data->version, SkyShaderGLES3::MODE_CUBEMAP);
GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::PROJECTION, cm.matrix[2][0], cm.matrix[0][0], cm.matrix[2][1], cm.matrix[1][1], shader_data->version, SkyShaderGLES3::MODE_CUBEMAP);
- // Bind a vertex array or else OpenGL complains. We won't actually use it
glBindVertexArray(sky_globals.screen_triangle_array);
glViewport(0, 0, sky->radiance_size, sky->radiance_size);
@@ -1048,6 +897,45 @@ void RasterizerSceneGLES3::_update_sky_radiance(Environment *p_env, const Camera
}
}
+// 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,27 +947,68 @@ 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);
#ifdef DEBUG_ENABLED
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
- ERR_CONTINUE(status != GL_FRAMEBUFFER_COMPLETE);
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ WARN_PRINT("Could not bind sky radiance face: " + itos(i) + ", status: " + GLES3::TextureStorage::get_singleton()->get_framebuffer_error(status));
+ }
#endif
material_storage->shaders.cubemap_filter_shader.version_set_uniform(CubemapFilterShaderGLES3::FACE_ID, i, scene_globals.cubemap_filter_shader_version, mode);
@@ -1096,84 +1025,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 +1033,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 +1051,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 +1058,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 +1080,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 +1112,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 +1198,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 +1375,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 +1400,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 +1419,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 {
}
@@ -1880,29 +1649,29 @@ void RasterizerSceneGLES3::_setup_lights(const RenderDataGLES3 *p_render_data, b
light_data.specular_amount = light_storage->light_get_param(base, RS::LIGHT_PARAM_SPECULAR) * 2.0;
- light_data.shadow_enabled = false;
+ light_data.shadow_opacity = 0.0;
}
// TODO, to avoid stalls, should rotate between 3 buffers based on frame index.
// TODO, consider mapping the buffer as in 2D
+ glBindBufferBase(GL_UNIFORM_BUFFER, SCENE_OMNILIGHT_UNIFORM_LOCATION, scene_state.omni_light_buffer);
if (r_omni_light_count) {
- glBindBufferBase(GL_UNIFORM_BUFFER, SCENE_OMNILIGHT_UNIFORM_LOCATION, scene_state.omni_light_buffer);
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(LightData) * r_omni_light_count, scene_state.omni_lights);
}
+ glBindBufferBase(GL_UNIFORM_BUFFER, SCENE_SPOTLIGHT_UNIFORM_LOCATION, scene_state.spot_light_buffer);
if (r_spot_light_count) {
- glBindBufferBase(GL_UNIFORM_BUFFER, SCENE_SPOTLIGHT_UNIFORM_LOCATION, scene_state.spot_light_buffer);
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(LightData) * r_spot_light_count, scene_state.spot_lights);
}
+ glBindBufferBase(GL_UNIFORM_BUFFER, SCENE_DIRECTIONAL_LIGHT_UNIFORM_LOCATION, scene_state.directional_light_buffer);
if (r_directional_light_count) {
- glBindBufferBase(GL_UNIFORM_BUFFER, SCENE_DIRECTIONAL_LIGHT_UNIFORM_LOCATION, scene_state.directional_light_buffer);
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(DirectionalLightData) * r_directional_light_count, scene_state.directional_lights);
}
glBindBuffer(GL_UNIFORM_BUFFER, 0);
}
-void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData *p_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");
@@ -1923,11 +1692,11 @@ void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData *
render_data.cam_transform = p_camera_data->main_transform;
render_data.inv_cam_transform = render_data.cam_transform.affine_inverse();
render_data.cam_projection = p_camera_data->main_projection;
- render_data.view_projection[0] = p_camera_data->main_projection;
render_data.cam_orthogonal = p_camera_data->is_orthogonal;
render_data.view_count = p_camera_data->view_count;
for (uint32_t v = 0; v < p_camera_data->view_count; v++) {
+ render_data.view_eye_offset[v] = p_camera_data->view_offset[v].origin;
render_data.view_projection[v] = p_camera_data->view_projection[v];
}
@@ -1967,18 +1736,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 +1755,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 +1781,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 +1819,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 +1912,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 +1936,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");
@@ -2200,6 +1967,7 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
GLES3::SceneMaterialData *prev_material_data = nullptr;
GLES3::SceneShaderData *prev_shader = nullptr;
GeometryInstanceGLES3 *prev_inst = nullptr;
+ SceneShaderGLES3::ShaderVariant prev_variant = SceneShaderGLES3::ShaderVariant::MODE_COLOR;
SceneShaderGLES3::ShaderVariant shader_variant = SceneShaderGLES3::MODE_COLOR; // Assigned to silence wrong -Wmaybe-initialized.
@@ -2217,11 +1985,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;
@@ -2382,16 +2149,17 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
index_array_gl = mesh_storage->mesh_surface_get_index_buffer(mesh_surface, surf->lod_index);
if (prev_vertex_array_gl != vertex_array_gl) {
- glBindVertexArray(vertex_array_gl);
+ if (vertex_array_gl != 0) {
+ glBindVertexArray(vertex_array_gl);
+ }
prev_vertex_array_gl = vertex_array_gl;
}
- bool use_index_buffer = false;
+ bool use_index_buffer = index_array_gl != 0;
if (prev_index_array_gl != index_array_gl) {
if (index_array_gl != 0) {
// Bind index each time so we can use LODs
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_array_gl);
- use_index_buffer = true;
}
prev_index_array_gl = index_array_gl;
}
@@ -2406,8 +2174,13 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
prev_material_data = material_data;
}
- if (prev_shader != shader) {
- material_storage->shaders.scene_shader.version_bind_shader(shader->version, shader_variant);
+ SceneShaderGLES3::ShaderVariant instance_variant = shader_variant;
+ if (inst->instance_count > 0) {
+ instance_variant = SceneShaderGLES3::ShaderVariant(1 + int(shader_variant));
+ }
+
+ if (prev_shader != shader || prev_variant != instance_variant) {
+ material_storage->shaders.scene_shader.version_bind_shader(shader->version, instance_variant);
float opaque_prepass_threshold = 0.0;
if (p_pass_mode == PASS_MODE_DEPTH) {
opaque_prepass_threshold = 0.99;
@@ -2415,41 +2188,77 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
opaque_prepass_threshold = 0.1;
}
- material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::OPAQUE_PREPASS_THRESHOLD, opaque_prepass_threshold, shader->version, shader_variant);
+ material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::OPAQUE_PREPASS_THRESHOLD, opaque_prepass_threshold, shader->version, instance_variant);
prev_shader = shader;
+ prev_variant = instance_variant;
}
- if (prev_inst != inst) {
+ if (prev_inst != inst || prev_shader != shader || prev_variant != instance_variant) {
// Rebind the light indices.
- material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::OMNI_LIGHT_COUNT, inst->omni_light_count, shader->version, shader_variant);
- material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::SPOT_LIGHT_COUNT, inst->spot_light_count, shader->version, shader_variant);
+ material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::OMNI_LIGHT_COUNT, inst->omni_light_count, shader->version, instance_variant);
+ material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::SPOT_LIGHT_COUNT, inst->spot_light_count, shader->version, instance_variant);
if (inst->omni_light_count) {
- glUniform1uiv(material_storage->shaders.scene_shader.version_get_uniform(SceneShaderGLES3::OMNI_LIGHT_INDICES, shader->version, shader_variant), inst->omni_light_count, inst->omni_light_gl_cache.ptr());
+ glUniform1uiv(material_storage->shaders.scene_shader.version_get_uniform(SceneShaderGLES3::OMNI_LIGHT_INDICES, shader->version, instance_variant), inst->omni_light_count, inst->omni_light_gl_cache.ptr());
}
if (inst->spot_light_count) {
- glUniform1uiv(material_storage->shaders.scene_shader.version_get_uniform(SceneShaderGLES3::SPOT_LIGHT_INDICES, shader->version, shader_variant), inst->spot_light_count, inst->spot_light_gl_cache.ptr());
+ glUniform1uiv(material_storage->shaders.scene_shader.version_get_uniform(SceneShaderGLES3::SPOT_LIGHT_INDICES, shader->version, instance_variant), inst->spot_light_count, inst->spot_light_gl_cache.ptr());
}
prev_inst = inst;
}
- material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::WORLD_TRANSFORM, world_transform, shader->version, shader_variant);
-
- if (use_index_buffer) {
- glDrawElements(primitive_gl, mesh_storage->mesh_surface_get_vertices_drawn_count(mesh_surface), mesh_storage->mesh_surface_get_index_type(mesh_surface), 0);
+ material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::WORLD_TRANSFORM, world_transform, shader->version, instance_variant);
+ if (inst->instance_count > 0) {
+ // Using MultiMesh.
+ // Bind instance buffers.
+
+ GLuint multimesh_buffer = mesh_storage->multimesh_get_gl_buffer(inst->data->base);
+ glBindBuffer(GL_ARRAY_BUFFER, multimesh_buffer);
+ uint32_t multimesh_stride = mesh_storage->multimesh_get_stride(inst->data->base);
+ glEnableVertexAttribArray(12);
+ glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(0));
+ glVertexAttribDivisor(12, 1);
+ glEnableVertexAttribArray(13);
+ glVertexAttribPointer(13, 4, GL_FLOAT, GL_FALSE, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(4 * 4));
+ glVertexAttribDivisor(13, 1);
+ glEnableVertexAttribArray(14);
+ glVertexAttribPointer(14, 4, GL_FLOAT, GL_FALSE, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(4 * 8));
+ glVertexAttribDivisor(14, 1);
+
+ if (mesh_storage->multimesh_uses_colors(inst->data->base) || mesh_storage->multimesh_uses_custom_data(inst->data->base)) {
+ glEnableVertexAttribArray(15);
+ glVertexAttribIPointer(15, 4, GL_UNSIGNED_INT, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(mesh_storage->multimesh_get_color_offset(inst->data->base) * sizeof(float)));
+ glVertexAttribDivisor(15, 1);
+ }
+ if (use_index_buffer) {
+ glDrawElementsInstanced(primitive_gl, mesh_storage->mesh_surface_get_vertices_drawn_count(mesh_surface), mesh_storage->mesh_surface_get_index_type(mesh_surface), 0, inst->instance_count);
+ } else {
+ glDrawArraysInstanced(primitive_gl, 0, mesh_storage->mesh_surface_get_vertices_drawn_count(mesh_surface), inst->instance_count);
+ }
} else {
- glDrawArrays(primitive_gl, 0, mesh_storage->mesh_surface_get_vertices_drawn_count(mesh_surface));
+ // Using regular Mesh.
+ if (use_index_buffer) {
+ glDrawElements(primitive_gl, mesh_storage->mesh_surface_get_vertices_drawn_count(mesh_surface), mesh_storage->mesh_surface_get_index_type(mesh_surface), 0);
+ } else {
+ glDrawArrays(primitive_gl, 0, mesh_storage->mesh_surface_get_vertices_drawn_count(mesh_surface));
+ }
+ }
+ if (inst->instance_count > 0) {
+ glDisableVertexAttribArray(12);
+ glDisableVertexAttribArray(13);
+ glDisableVertexAttribArray(14);
+ glDisableVertexAttribArray(15);
}
}
}
-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) {
@@ -2466,7 +2275,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_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);
@@ -2499,7 +2308,7 @@ void RasterizerSceneGLES3::render_buffers_configure(RID p_render_buffers, RID p_
glGenTextures(1, &rb->depth_texture);
glBindTexture(GL_TEXTURE_2D, rb->depth_texture);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, rt->size.x, rt->size.y, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, rt->size.x, rt->size.y, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
@@ -2580,8 +2389,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);
@@ -2616,12 +2425,12 @@ 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() {
+ singleton = this;
+
GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
GLES3::Config *config = GLES3::Config::get_singleton();
- storage = p_storage;
-
{
// Setup Lights
@@ -2663,7 +2472,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";
@@ -2702,13 +2511,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);
}
@@ -2778,39 +2591,12 @@ 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
+
+ // MultiMesh may read from color when color is disabled, so make sure that the color defaults to white instead of black;
+ glVertexAttrib4f(RS::ARRAY_COLOR, 1.0, 1.0, 1.0, 1.0);
}
RasterizerSceneGLES3::~RasterizerSceneGLES3() {
@@ -2826,21 +2612,23 @@ 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);
glDeleteBuffers(1, &sky_globals.directional_light_buffer);
memdelete_arr(sky_globals.directional_lights);
memdelete_arr(sky_globals.last_frame_directional_lights);
+
+ singleton = nullptr;
}
#endif // GLES3_ENABLED
diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h
index ea6145d2a8..a54d87a3a3 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,17 +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;
- CameraMatrix view_projection[RendererSceneRender::MAX_RENDER_VIEWS];
+ Vector3 view_eye_offset[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();
@@ -124,7 +126,6 @@ struct RenderDataGLES3 {
RendererScene::RenderInfo *render_info = nullptr;
};
-class RasterizerStorageGLES3;
class RasterizerCanvasGLES3;
class RasterizerSceneGLES3 : public RendererSceneRender {
@@ -164,7 +165,7 @@ private:
float inv_spot_attenuation;
float cos_spot_angle;
float specular_amount;
- uint32_t shadow_enabled;
+ float shadow_opacity;
};
static_assert(sizeof(LightData) % 16 == 0, "LightData size must be a multiple of 16 bytes");
@@ -209,7 +210,7 @@ private:
mutable RID_Owner<LightInstance> light_instance_owner;
- struct GeometryInstanceGLES3;
+ class GeometryInstanceGLES3;
// Cached data for drawing surfaces
struct GeometryInstanceSurface {
@@ -264,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;
- uint32_t instance_count = 0;
+ 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;
@@ -300,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 {
@@ -344,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;
@@ -356,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 {
@@ -569,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;
@@ -660,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 {
@@ -729,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 */
@@ -804,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;
@@ -855,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) {
@@ -900,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 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;
@@ -923,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_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;
@@ -941,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 49c5045453..0000000000
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ /dev/null
@@ -1,640 +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"
-
-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);
- }
-}
-
-/* VOXEL GI API */
-
-RID RasterizerStorageGLES3::voxel_gi_allocate() {
- return RID();
-}
-
-void RasterizerStorageGLES3::voxel_gi_initialize(RID p_rid) {
-}
-
-void RasterizerStorageGLES3::voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) {
-}
-
-AABB RasterizerStorageGLES3::voxel_gi_get_bounds(RID p_voxel_gi) const {
- return AABB();
-}
-
-Vector3i RasterizerStorageGLES3::voxel_gi_get_octree_size(RID p_voxel_gi) const {
- return Vector3i();
-}
-
-Vector<uint8_t> RasterizerStorageGLES3::voxel_gi_get_octree_cells(RID p_voxel_gi) const {
- return Vector<uint8_t>();
-}
-
-Vector<uint8_t> RasterizerStorageGLES3::voxel_gi_get_data_cells(RID p_voxel_gi) const {
- return Vector<uint8_t>();
-}
-
-Vector<uint8_t> RasterizerStorageGLES3::voxel_gi_get_distance_field(RID p_voxel_gi) const {
- return Vector<uint8_t>();
-}
-
-Vector<int> RasterizerStorageGLES3::voxel_gi_get_level_counts(RID p_voxel_gi) const {
- return Vector<int>();
-}
-
-Transform3D RasterizerStorageGLES3::voxel_gi_get_to_cell_xform(RID p_voxel_gi) const {
- return Transform3D();
-}
-
-void RasterizerStorageGLES3::voxel_gi_set_dynamic_range(RID p_voxel_gi, float p_range) {
-}
-
-float RasterizerStorageGLES3::voxel_gi_get_dynamic_range(RID p_voxel_gi) const {
- return 0;
-}
-
-void RasterizerStorageGLES3::voxel_gi_set_propagation(RID p_voxel_gi, float p_range) {
-}
-
-float RasterizerStorageGLES3::voxel_gi_get_propagation(RID p_voxel_gi) const {
- return 0;
-}
-
-void RasterizerStorageGLES3::voxel_gi_set_energy(RID p_voxel_gi, float p_range) {
-}
-
-float RasterizerStorageGLES3::voxel_gi_get_energy(RID p_voxel_gi) const {
- return 0.0;
-}
-
-void RasterizerStorageGLES3::voxel_gi_set_bias(RID p_voxel_gi, float p_range) {
-}
-
-float RasterizerStorageGLES3::voxel_gi_get_bias(RID p_voxel_gi) const {
- return 0.0;
-}
-
-void RasterizerStorageGLES3::voxel_gi_set_normal_bias(RID p_voxel_gi, float p_range) {
-}
-
-float RasterizerStorageGLES3::voxel_gi_get_normal_bias(RID p_voxel_gi) const {
- return 0.0;
-}
-
-void RasterizerStorageGLES3::voxel_gi_set_interior(RID p_voxel_gi, bool p_enable) {
-}
-
-bool RasterizerStorageGLES3::voxel_gi_is_interior(RID p_voxel_gi) const {
- return false;
-}
-
-void RasterizerStorageGLES3::voxel_gi_set_use_two_bounces(RID p_voxel_gi, bool p_enable) {
-}
-
-bool RasterizerStorageGLES3::voxel_gi_is_using_two_bounces(RID p_voxel_gi) const {
- return false;
-}
-
-void RasterizerStorageGLES3::voxel_gi_set_anisotropy_strength(RID p_voxel_gi, float p_strength) {
-}
-
-float RasterizerStorageGLES3::voxel_gi_get_anisotropy_strength(RID p_voxel_gi) const {
- return 0;
-}
-
-uint32_t RasterizerStorageGLES3::voxel_gi_get_version(RID p_voxel_gi) {
- return 0;
-}
-
-/* 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 (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 7ac3db4537..0000000000
--- a/drivers/gles3/rasterizer_storage_gles3.h
+++ /dev/null
@@ -1,322 +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];
- }
- }
- }
-
- 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;
-
- /* VOXEL GI API */
-
- RID voxel_gi_allocate() override;
- void voxel_gi_initialize(RID p_rid) override;
- void voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) override;
-
- AABB voxel_gi_get_bounds(RID p_voxel_gi) const override;
- Vector3i voxel_gi_get_octree_size(RID p_voxel_gi) const override;
- Vector<uint8_t> voxel_gi_get_octree_cells(RID p_voxel_gi) const override;
- Vector<uint8_t> voxel_gi_get_data_cells(RID p_voxel_gi) const override;
- Vector<uint8_t> voxel_gi_get_distance_field(RID p_voxel_gi) const override;
-
- Vector<int> voxel_gi_get_level_counts(RID p_voxel_gi) const override;
- Transform3D voxel_gi_get_to_cell_xform(RID p_voxel_gi) const override;
-
- void voxel_gi_set_dynamic_range(RID p_voxel_gi, float p_range) override;
- float voxel_gi_get_dynamic_range(RID p_voxel_gi) const override;
-
- void voxel_gi_set_propagation(RID p_voxel_gi, float p_range) override;
- float voxel_gi_get_propagation(RID p_voxel_gi) const override;
-
- void voxel_gi_set_energy(RID p_voxel_gi, float p_range) override;
- float voxel_gi_get_energy(RID p_voxel_gi) const override;
-
- void voxel_gi_set_bias(RID p_voxel_gi, float p_range) override;
- float voxel_gi_get_bias(RID p_voxel_gi) const override;
-
- void voxel_gi_set_normal_bias(RID p_voxel_gi, float p_range) override;
- float voxel_gi_get_normal_bias(RID p_voxel_gi) const override;
-
- void voxel_gi_set_interior(RID p_voxel_gi, bool p_enable) override;
- bool voxel_gi_is_interior(RID p_voxel_gi) const override;
-
- void voxel_gi_set_use_two_bounces(RID p_voxel_gi, bool p_enable) override;
- bool voxel_gi_is_using_two_bounces(RID p_voxel_gi) const override;
-
- void voxel_gi_set_anisotropy_strength(RID p_voxel_gi, float p_strength) override;
- float voxel_gi_get_anisotropy_strength(RID p_voxel_gi) const override;
-
- uint32_t voxel_gi_get_version(RID p_voxel_gi) 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();
- }
-
- //bool validate_framebuffer(); // Validate currently bound framebuffer, does not touch global state
- String get_framebuffer_error(GLenum p_status);
-
- RasterizerStorageGLES3();
- ~RasterizerStorageGLES3();
-};
-
-inline String RasterizerStorageGLES3::get_framebuffer_error(GLenum p_status) {
-#if defined(DEBUG_ENABLED) && defined(GLES_OVER_GL)
- if (p_status == GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT) {
- return "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT";
- } else if (p_status == GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT) {
- return "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT";
- } else if (p_status == GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER) {
- return "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER";
- } else if (p_status == GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER) {
- return "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER";
- }
-#endif
- return itos(p_status);
-}
-
-#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.glsl b/drivers/gles3/shaders/canvas.glsl
index 9c426dd3ef..4df818cd4c 100644
--- a/drivers/gles3/shaders/canvas.glsl
+++ b/drivers/gles3/shaders/canvas.glsl
@@ -23,10 +23,9 @@ layout(location = 11) in vec4 weight_attrib;
#ifdef USE_INSTANCING
-layout(location = 5) in highp vec4 instance_xform0;
-layout(location = 6) in highp vec4 instance_xform1;
-layout(location = 7) in lowp vec4 instance_color;
-layout(location = 8) in highp vec4 instance_custom_data;
+layout(location = 1) in highp vec4 instance_xform0;
+layout(location = 2) in highp vec4 instance_xform1;
+layout(location = 5) in highp uvec4 instance_color_custom_data; // Color packed into xy, custom_data packed into zw for compatibility with 3D
#endif
@@ -98,8 +97,9 @@ void main() {
vec4 bone_weights = weight_attrib;
#ifdef USE_INSTANCING
+ vec4 instance_color = vec4(unpackHalf2x16(instance_color_custom_data.x), unpackHalf2x16(instance_color_custom_data.y));
color *= instance_color;
- instance_custom = instance_custom_data;
+ instance_custom = vec4(unpackHalf2x16(instance_color_custom_data.z), unpackHalf2x16(instance_color_custom_data.w));
#endif
#else
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..88464876f1 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_direction_mip = sample_directions_mip[sample_num];
+ vec3 L = T * sample_direction_mip.xyz;
+ vec3 val = textureLod(source_cube, L, sample_direction_mip.w).rgb;
+ // Mix using linear
+ val = srgb_to_linear(val);
+ sum.rgb += val * sample_direction_mip.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 fbea4bdbe4..c7fdd6ebd8 100644
--- a/drivers/gles3/shaders/scene.glsl
+++ b/drivers/gles3/shaders/scene.glsl
@@ -2,8 +2,11 @@
#[modes]
mode_color = #define BASE_PASS
+mode_color_instancing = #define BASE_PASS \n#define USE_INSTANCING
mode_additive = #define USE_ADDITIVE_LIGHTING
+mode_additive_instancing = #define USE_ADDITIVE_LIGHTING \n#define USE_INSTANCING
mode_depth = #define MODE_RENDER_DEPTH
+mode_depth_instancing = #define MODE_RENDER_DEPTH \n#define USE_INSTANCING
#[specializations]
@@ -32,8 +35,8 @@ USE_RADIANCE_MAP = true
/*
from RenderingServer:
ARRAY_VERTEX = 0, // RG32F or RGB32F (depending on 2D bit)
-ARRAY_NORMAL = 1, // A2B10G10R10, A is ignored.
-ARRAY_TANGENT = 2, // A2B10G10R10, A flips sign of binormal.
+ARRAY_NORMAL = 1, // RG16 octahedral compression
+ARRAY_TANGENT = 2, // RG16 octahedral compression, sign stored in sign of G
ARRAY_COLOR = 3, // RGBA8
ARRAY_TEX_UV = 4, // RG32F
ARRAY_TEX_UV2 = 5, // RG32F
@@ -43,8 +46,6 @@ ARRAY_CUSTOM2 = 8,
ARRAY_CUSTOM3 = 9,
ARRAY_BONES = 10, // RGBA16UI (x2 if 8 weights)
ARRAY_WEIGHTS = 11, // RGBA16UNORM (x2 if 8 weights)
-ARRAY_INDEX = 12, // 16 or 32 bits depending on length > 0xFFFF.
-ARRAY_MAX = 13
*/
/* INPUT ATTRIBS */
@@ -53,11 +54,11 @@ layout(location = 0) in highp vec3 vertex_attrib;
/* clang-format on */
#ifdef NORMAL_USED
-layout(location = 1) in vec3 normal_attrib;
+layout(location = 1) in vec2 normal_attrib;
#endif
#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
-layout(location = 2) in vec4 tangent_attrib;
+layout(location = 2) in vec2 tangent_attrib;
#endif
#if defined(COLOR_USED)
@@ -96,8 +97,22 @@ layout(location = 10) in uvec4 bone_attrib;
layout(location = 11) in vec4 weight_attrib;
#endif
-layout(std140) uniform GlobalVariableData { //ubo:1
- vec4 global_variables[MAX_GLOBAL_VARIABLES];
+vec3 oct_to_vec3(vec2 e) {
+ vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));
+ float t = max(-v.z, 0.0);
+ v.xy += t * -sign(v.xy);
+ return v;
+}
+
+#ifdef USE_INSTANCING
+layout(location = 12) in highp vec4 instance_xform0;
+layout(location = 13) in highp vec4 instance_xform1;
+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 GlobalShaderUniformData { //ubo:1
+ vec4 global_shader_uniforms[MAX_GLOBAL_SHADER_UNIFORMS];
};
layout(std140) uniform SceneData { // ubo:2
@@ -195,20 +210,29 @@ void main() {
highp vec3 vertex = vertex_attrib;
highp mat4 model_matrix = world_transform;
+#ifdef USE_INSTANCING
+ highp mat4 m = mat4(instance_xform0, instance_xform1, instance_xform2, vec4(0.0, 0.0, 0.0, 1.0));
+ model_matrix = model_matrix * transpose(m);
+#endif
#ifdef NORMAL_USED
- vec3 normal = normal_attrib * 2.0 - 1.0;
+ vec3 normal = oct_to_vec3(normal_attrib * 2.0 - 1.0);
#endif
highp mat3 model_normal_matrix = mat3(model_matrix);
#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
- vec3 tangent = tangent_attrib.xyz * 2.0 - 1.0;
- float binormalf = tangent_attrib.a * 2.0 - 1.0;
+ vec2 signed_tangent_attrib = tangent_attrib * 2.0 - 1.0;
+ vec3 tangent = oct_to_vec3(vec2(signed_tangent_attrib.x, abs(signed_tangent_attrib.y) * 2.0 - 1.0));
+ float binormalf = sign(signed_tangent_attrib.y);
vec3 binormal = normalize(cross(normal, tangent) * binormalf);
#endif
#if defined(COLOR_USED)
color_interp = color_attrib;
+#ifdef USE_INSTANCING
+ vec4 instance_color = vec4(unpackHalf2x16(instance_color_custom_data.x), unpackHalf2x16(instance_color_custom_data.y));
+ color_interp *= instance_color;
+#endif
#endif
#if defined(UV_USED)
@@ -229,7 +253,11 @@ void main() {
highp mat4 projection_matrix = scene_data.projection_matrix;
highp mat4 inv_projection_matrix = scene_data.inv_projection_matrix;
+#ifdef USE_INSTANCING
+ vec4 instance_custom = vec4(unpackHalf2x16(instance_color_custom_data.z), unpackHalf2x16(instance_color_custom_data.w));
+#else
vec4 instance_custom = vec4(0.0);
+#endif
// Using world coordinates
#if !defined(SKIP_TRANSFORM_USED) && defined(VERTEX_WORLD_COORDS_USED)
@@ -379,8 +407,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 */
@@ -475,7 +503,7 @@ struct LightData { //this structure needs to be as packed as possible
mediump float cone_attenuation;
mediump float cone_angle;
mediump float specular_amount;
- bool shadow_enabled;
+ mediump float shadow_opacity;
};
#ifndef DISABLE_LIGHT_OMNI
layout(std140) uniform OmniLightData { // ubo:5
@@ -666,7 +694,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;
@@ -731,7 +762,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 f
if (omni_lights[idx].size > 0.0) {
float t = omni_lights[idx].size / max(0.001, light_length);
- size_A = max(0.0, 1.0 - 1 / sqrt(1 + t * t));
+ size_A = max(0.0, 1.0 - 1.0 / sqrt(1.0 + t * t));
}
light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, omni_attenuation, f0, roughness, metallic, omni_lights[idx].specular_amount, albedo, alpha,
@@ -780,7 +811,7 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 f
if (spot_lights[idx].size > 0.0) {
float t = spot_lights[idx].size / max(0.001, light_length);
- size_A = max(0.0, 1.0 - 1 / sqrt(1 + t * t));
+ size_A = max(0.0, 1.0 - 1.0 / sqrt(1.0 + t * t));
}
light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, spot_attenuation, f0, roughness, metallic, spot_lights[idx].specular_amount, albedo, alpha,
@@ -1029,6 +1060,7 @@ void main() {
#else
vec3 ref_vec = reflect(-view, normal);
#endif
+ ref_vec = mix(ref_vec, normal, roughness * roughness);
float horizon = min(1.0 + dot(ref_vec, normal), 1.0);
ref_vec = scene_data.radiance_inverse_xform * ref_vec;
specular_light = textureLod(radiance_map, ref_vec, roughness * RADIANCE_MAX_LOD).rgb;
@@ -1087,7 +1119,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.cpp b/drivers/gles3/storage/config.cpp
index f2809734a9..6cc65e7bb2 100644
--- a/drivers/gles3/storage/config.cpp
+++ b/drivers/gles3/storage/config.cpp
@@ -64,7 +64,14 @@ Config::Config() {
#else
float_texture_supported = extensions.has("GL_ARB_texture_float") || extensions.has("GL_OES_texture_float");
etc2_supported = true;
+#if defined(ANDROID_ENABLED) || defined(IOS_ENABLED)
+ // Some Android devices report support for S3TC but we don't expect that and don't export the textures.
+ // This could be fixed but so few devices support it that it doesn't seem useful (and makes bigger APKs).
+ // For good measure we do the same hack for iOS, just in case.
+ s3tc_supported = false;
+#else
s3tc_supported = extensions.has("GL_EXT_texture_compression_dxt1") || extensions.has("GL_EXT_texture_compression_s3tc") || extensions.has("WEBGL_compressed_texture_s3tc");
+#endif
rgtc_supported = extensions.has("GL_EXT_texture_compression_rgtc") || extensions.has("GL_ARB_texture_compression_rgtc") || extensions.has("EXT_texture_compression_rgtc");
#endif
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..2e4bfdc15b 100644
--- a/drivers/gles3/storage/light_storage.cpp
+++ b/drivers/gles3/storage/light_storage.cpp
@@ -70,6 +70,7 @@ void LightStorage::_light_initialize(RID p_light, RS::LightType p_type) {
light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET] = 0.6;
light.param[RS::LIGHT_PARAM_SHADOW_FADE_START] = 0.8;
light.param[RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] = 1.0;
+ light.param[RS::LIGHT_PARAM_SHADOW_OPACITY] = 1.0;
light.param[RS::LIGHT_PARAM_SHADOW_BIAS] = 0.02;
light.param[RS::LIGHT_PARAM_SHADOW_BLUR] = 0;
light.param[RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE] = 20.0;
@@ -139,12 +140,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 +161,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 +183,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 +201,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 +221,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 +231,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 +241,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 +257,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 +266,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 +477,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..a64c7f7200 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) {
@@ -1047,10 +1083,16 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet
Vector<RID> textures;
+ if (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE ||
+ p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE ||
+ p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
+ continue;
+ }
+
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!.");
@@ -1120,6 +1162,9 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet
case ShaderLanguage::ShaderNode::Uniform::HINT_DEFAULT_BLACK: {
gl_texture = texture_storage->texture_gl_get_default(DEFAULT_GL_TEXTURE_BLACK);
} break;
+ case ShaderLanguage::ShaderNode::Uniform::HINT_DEFAULT_TRANSPARENT: {
+ gl_texture = texture_storage->texture_gl_get_default(DEFAULT_GL_TEXTURE_TRANSPARENT);
+ } break;
case ShaderLanguage::ShaderNode::Uniform::HINT_ANISOTROPY: {
gl_texture = texture_storage->texture_gl_get_default(DEFAULT_GL_TEXTURE_ANISO);
} break;
@@ -1222,7 +1267,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 +1281,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 +1350,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 +1423,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";
@@ -1410,8 +1456,8 @@ MaterialStorage::MaterialStorage() {
actions.renames["UV2"] = "uv2_interp";
actions.renames["COLOR"] = "color_interp";
actions.renames["POINT_SIZE"] = "gl_PointSize";
- actions.renames["INSTANCE_ID"] = "gl_InstanceIndex";
- actions.renames["VERTEX_ID"] = "gl_VertexIndex";
+ actions.renames["INSTANCE_ID"] = "gl_InstanceID";
+ actions.renames["VERTEX_ID"] = "gl_VertexID";
actions.renames["ALPHA_SCISSOR_THRESHOLD"] = "alpha_scissor_threshold";
actions.renames["ALPHA_HASH_SCALE"] = "alpha_hash_scale";
@@ -1452,12 +1498,12 @@ MaterialStorage::MaterialStorage() {
actions.renames["POINT_COORD"] = "gl_PointCoord";
actions.renames["INSTANCE_CUSTOM"] = "instance_custom";
actions.renames["SCREEN_UV"] = "screen_uv";
- actions.renames["SCREEN_TEXTURE"] = "color_buffer";
- actions.renames["DEPTH_TEXTURE"] = "depth_buffer";
- actions.renames["NORMAL_ROUGHNESS_TEXTURE"] = "normal_roughness_buffer";
+ //actions.renames["SCREEN_TEXTURE"] = "color_buffer"; //Not implemented in 3D yet.
+ //actions.renames["DEPTH_TEXTURE"] = "depth_buffer"; // Not implemented in 3D yet.
+ //actions.renames["NORMAL_ROUGHNESS_TEXTURE"] = "normal_roughness_buffer"; // Not implemented in 3D yet
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";
@@ -1468,6 +1514,11 @@ MaterialStorage::MaterialStorage() {
actions.renames["CUSTOM3"] = "custom3_attrib";
actions.renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB";
+ actions.renames["NODE_POSITION_WORLD"] = "model_matrix[3].xyz";
+ actions.renames["CAMERA_POSITION_WORLD"] = "scene_data.inv_view_matrix[3].xyz";
+ actions.renames["CAMERA_DIRECTION_WORLD"] = "scene_data.view_matrix[3].xyz";
+ actions.renames["NODE_POSITION_VIEW"] = "(model_matrix * scene_data.view_matrix)[3].xyz";
+
actions.renames["VIEW_INDEX"] = "ViewIndex";
actions.renames["VIEW_MONO_LEFT"] = "0";
actions.renames["VIEW_RIGHT"] = "1";
@@ -1613,7 +1664,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 +1726,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 +1755,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 +1774,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 +1782,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 +1790,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 +1798,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 +1806,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 +1814,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 +1822,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 +1830,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 +1838,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 +1846,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 +1854,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 +1862,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 +1870,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 +1878,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 +1886,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 +1894,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 +1902,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 +1918,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 +1926,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 +1943,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 +1962,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 +1991,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 +2010,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 +2039,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 +2055,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 +2081,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 +2143,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 +2174,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 +2247,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 +2273,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
@@ -2283,11 +2334,14 @@ void MaterialStorage::global_variables_instance_update(RID p_instance, int p_ind
ShaderLanguage::TYPE_VEC3, // vec3
ShaderLanguage::TYPE_IVEC3, //vec3i
ShaderLanguage::TYPE_MAX, //xform2d not supported here
+ ShaderLanguage::TYPE_VEC4, //vec4
+ ShaderLanguage::TYPE_IVEC4, //vec4i
ShaderLanguage::TYPE_VEC4, //plane
ShaderLanguage::TYPE_VEC4, //quat
ShaderLanguage::TYPE_MAX, //aabb not supported here
ShaderLanguage::TYPE_MAX, //basis not supported here
ShaderLanguage::TYPE_MAX, //xform not supported here
+ ShaderLanguage::TYPE_MAX, //projection not supported here
ShaderLanguage::TYPE_VEC4 //color
};
@@ -2297,59 +2351,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,22 +2510,29 @@ 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());
return shader->code;
}
-void MaterialStorage::shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const {
+void MaterialStorage::shader_get_shader_uniform_list(RID p_shader, List<PropertyInfo> *p_param_list) const {
GLES3::Shader *shader = shader_owner.get_or_null(p_shader);
ERR_FAIL_COND(!shader);
if (shader->data) {
- return shader->data->get_param_list(p_param_list);
+ return shader->data->get_shader_uniform_list(p_param_list);
}
}
@@ -2593,7 +2654,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 +2677,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 +2723,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) {
@@ -2703,19 +2764,19 @@ bool MaterialStorage::material_casts_shadows(RID p_material) {
return true; //by default everything casts shadows
}
-void MaterialStorage::material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) {
+void MaterialStorage::material_get_instance_shader_uniforms(RID p_material, List<InstanceShaderParam> *r_parameters) {
GLES3::Material *material = material_owner.get_or_null(p_material);
ERR_FAIL_COND(!material);
if (material->shader && material->shader->data) {
material->shader->data->get_instance_param_list(r_parameters);
if (material->next_pass.is_valid()) {
- material_get_instance_shader_parameters(material->next_pass, r_parameters);
+ material_get_instance_shader_uniforms(material->next_pass, r_parameters);
}
}
}
-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);
@@ -2734,6 +2795,7 @@ void CanvasShaderData::set_code(const String &p_code) {
ubo_size = 0;
uniforms.clear();
uses_screen_texture = false;
+ uses_screen_texture_mipmaps = false;
uses_sdf = false;
uses_time = false;
@@ -2744,7 +2806,6 @@ void CanvasShaderData::set_code(const String &p_code) {
ShaderCompiler::GeneratedCode gen_code;
int blend_modei = BLEND_MODE_MIX;
- uses_screen_texture = false;
ShaderCompiler::IdentifierActions actions;
actions.entry_point_stages["vertex"] = ShaderCompiler::STAGE_VERTEX;
@@ -2771,6 +2832,7 @@ void CanvasShaderData::set_code(const String &p_code) {
}
blend_mode = BlendMode(blend_modei);
+ uses_screen_texture_mipmaps = gen_code.uses_screen_texture_mipmaps;
#if 0
print_line("**compiling shader:");
@@ -2778,12 +2840,16 @@ void CanvasShaderData::set_code(const String &p_code) {
for (int i = 0; i < gen_code.defines.size(); i++) {
print_line(gen_code.defines[i]);
}
+
+ HashMap<String, String>::Iterator el = gen_code.code.begin();
+ while (el) {
+ print_line("\n**code " + el->key + ":\n" + el->value);
+ ++el;
+ }
+
print_line("\n**uniforms:\n" + gen_code.uniforms);
- print_line("\n**vertex_globals:\n" + gen_code.vertex_global);
- print_line("\n**vertex_code:\n" + gen_code.vertex);
- print_line("\n**fragment_globals:\n" + gen_code.fragment_global);
- print_line("\n**fragment_code:\n" + gen_code.fragment);
- print_line("\n**light_code:\n" + gen_code.light);
+ print_line("\n**vertex_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX]);
+ print_line("\n**fragment_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT]);
#endif
Vector<StringName> texture_uniform_names;
@@ -2818,11 +2884,14 @@ void CanvasShaderData::set_default_texture_param(const StringName &p_name, RID p
}
}
-void CanvasShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
+void CanvasShaderData::get_shader_uniform_list(List<PropertyInfo> *p_param_list) const {
HashMap<int, StringName> order;
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
- if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) {
+ if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
continue;
}
if (E.value.texture_order >= 0) {
@@ -2832,7 +2901,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);
@@ -3000,12 +3084,16 @@ void SkyShaderData::set_code(const String &p_code) {
for (int i = 0; i < gen_code.defines.size(); i++) {
print_line(gen_code.defines[i]);
}
+
+ HashMap<String, String>::Iterator el = gen_code.code.begin();
+ while (el) {
+ print_line("\n**code " + el->key + ":\n" + el->value);
+ ++el;
+ }
+
print_line("\n**uniforms:\n" + gen_code.uniforms);
- // print_line("\n**vertex_globals:\n" + gen_code.vertex_global);
- // print_line("\n**vertex_code:\n" + gen_code.vertex);
- print_line("\n**fragment_globals:\n" + gen_code.fragment_global);
- print_line("\n**fragment_code:\n" + gen_code.fragment);
- print_line("\n**light_code:\n" + gen_code.light);
+ print_line("\n**vertex_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX]);
+ print_line("\n**fragment_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT]);
#endif
Vector<StringName> texture_uniform_names;
@@ -3040,7 +3128,7 @@ void SkyShaderData::set_default_texture_param(const StringName &p_name, RID p_te
}
}
-void SkyShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
+void SkyShaderData::get_shader_uniform_list(List<PropertyInfo> *p_param_list) const {
RBMap<int, StringName> order;
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
@@ -3055,7 +3143,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);
@@ -3168,7 +3271,6 @@ void SceneShaderData::set_code(const String &p_code) {
valid = false;
ubo_size = 0;
uniforms.clear();
- uses_screen_texture = false;
if (code.is_empty()) {
return; //just invalid, but no error
@@ -3293,6 +3395,7 @@ void SceneShaderData::set_code(const String &p_code) {
vertex_input_mask |= uses_custom3 << 8;
vertex_input_mask |= uses_bones << 9;
vertex_input_mask |= uses_weights << 10;
+ uses_screen_texture_mipmaps = gen_code.uses_screen_texture_mipmaps;
#if 0
print_line("**compiling shader:");
@@ -3301,11 +3404,10 @@ void SceneShaderData::set_code(const String &p_code) {
print_line(gen_code.defines[i]);
}
- Map<String, String>::Element *el = gen_code.code.front();
+ HashMap<String, String>::Iterator el = gen_code.code.begin();
while (el) {
- print_line("\n**code " + el->key() + ":\n" + el->value());
-
- el = el->next();
+ print_line("\n**code " + el->key + ":\n" + el->value);
+ ++el;
}
print_line("\n**uniforms:\n" + gen_code.uniforms);
@@ -3350,11 +3452,14 @@ void SceneShaderData::set_default_texture_param(const StringName &p_name, RID p_
}
}
-void SceneShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
+void SceneShaderData::get_shader_uniform_list(List<PropertyInfo> *p_param_list) const {
RBMap<int, StringName> order;
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
- if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) {
+ if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
continue;
}
@@ -3365,7 +3470,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..d135357f6a 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"
@@ -54,7 +54,7 @@ namespace GLES3 {
struct ShaderData {
virtual void set_code(const String &p_Code) = 0;
virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) = 0;
- virtual void get_param_list(List<PropertyInfo> *p_param_list) const = 0;
+ virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const = 0;
virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const = 0;
virtual bool is_param_texture(const StringName &p_param) const = 0;
@@ -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) {}
@@ -158,12 +159,13 @@ struct CanvasShaderData : public ShaderData {
HashMap<StringName, HashMap<int, RID>> default_texture_params;
bool uses_screen_texture = false;
+ bool uses_screen_texture_mipmaps = false;
bool uses_sdf = false;
bool uses_time = false;
virtual void set_code(const String &p_Code);
virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
- virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
+ virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const;
virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
virtual bool is_param_texture(const StringName &p_param) const;
@@ -214,7 +216,7 @@ struct SkyShaderData : public ShaderData {
virtual void set_code(const String &p_Code);
virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
- virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
+ virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const;
virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
virtual bool is_param_texture(const StringName &p_param) const;
virtual bool is_animated() const;
@@ -311,6 +313,7 @@ struct SceneShaderData : public ShaderData {
bool uses_sss;
bool uses_transmittance;
bool uses_screen_texture;
+ bool uses_screen_texture_mipmaps;
bool uses_depth_texture;
bool uses_normal_texture;
bool uses_time;
@@ -334,7 +337,7 @@ struct SceneShaderData : public ShaderData {
virtual void set_code(const String &p_Code);
virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
- virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
+ virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const;
virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
virtual bool is_param_texture(const StringName &p_param) const;
@@ -364,15 +367,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 +431,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 +456,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 +510,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,8 +545,9 @@ 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;
+ virtual void shader_get_shader_uniform_list(RID p_shader, List<PropertyInfo> *p_param_list) const override;
virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) override;
virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const override;
@@ -532,9 +578,9 @@ public:
virtual bool material_is_animated(RID p_material) override;
virtual bool material_casts_shadows(RID p_material) override;
- virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) override;
+ virtual void material_get_instance_shader_uniforms(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 +601,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 822be25337..ddf94af5b8 100644
--- a/drivers/gles3/storage/mesh_storage.cpp
+++ b/drivers/gles3/storage/mesh_storage.cpp
@@ -32,6 +32,7 @@
#include "mesh_storage.h"
#include "material_storage.h"
+#include "utilities.h"
using namespace GLES3;
@@ -63,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");
@@ -71,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);
@@ -121,11 +124,11 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
} break;
case RS::ARRAY_NORMAL: {
- stride += sizeof(int32_t);
+ stride += sizeof(uint16_t) * 2;
} break;
case RS::ARRAY_TANGENT: {
- stride += sizeof(int32_t);
+ stride += sizeof(uint16_t) * 2;
} break;
case RS::ARRAY_COLOR: {
@@ -183,11 +186,13 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
s->format = p_surface.format;
s->primitive = p_surface.primitive;
- glGenBuffers(1, &s->vertex_buffer);
- glBindBuffer(GL_ARRAY_BUFFER, s->vertex_buffer);
- glBufferData(GL_ARRAY_BUFFER, p_surface.vertex_data.size(), p_surface.vertex_data.ptr(), (s->format & RS::ARRAY_FLAG_USE_DYNAMIC_UPDATE) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
- glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
- s->vertex_buffer_size = p_surface.vertex_data.size();
+ if (p_surface.vertex_data.size()) {
+ glGenBuffers(1, &s->vertex_buffer);
+ glBindBuffer(GL_ARRAY_BUFFER, s->vertex_buffer);
+ glBufferData(GL_ARRAY_BUFFER, p_surface.vertex_data.size(), p_surface.vertex_data.ptr(), (s->format & RS::ARRAY_FLAG_USE_DYNAMIC_UPDATE) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
+ glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
+ s->vertex_buffer_size = p_surface.vertex_data.size();
+ }
if (p_surface.attribute_data.size()) {
glGenBuffers(1, &s->attribute_buffer);
@@ -211,7 +216,7 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
}
if (p_surface.index_count) {
- bool is_index_16 = p_surface.vertex_count <= 65536;
+ bool is_index_16 = p_surface.vertex_count <= 65536 && p_surface.vertex_count > 0;
glGenBuffers(1, &s->index_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s->index_buffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, p_surface.index_data.size(), p_surface.index_data.ptr(), GL_STATIC_DRAW);
@@ -230,10 +235,13 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); //unbind
s->lods[i].edge_length = p_surface.lods[i].edge_length;
s->lods[i].index_count = p_surface.lods[i].index_data.size() / (is_index_16 ? 2 : 4);
+ s->lods[i].index_buffer_size = p_surface.lods[i].index_data.size();
}
}
}
+ ERR_FAIL_COND_MSG(!p_surface.index_count && !p_surface.vertex_count, "Meshes must contain a vertex array, an index array, or both");
+
s->aabb = p_surface.aabb;
s->bone_aabbs = p_surface.bone_aabbs; //only really useful for returning them.
@@ -251,7 +259,10 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
mesh->bone_aabbs.resize(p_surface.bone_aabbs.size());
}
for (int i = 0; i < p_surface.bone_aabbs.size(); i++) {
- mesh->bone_aabbs.write[i].merge_with(p_surface.bone_aabbs[i]);
+ const AABB &bone = p_surface.bone_aabbs[i];
+ if (!bone.has_no_volume()) {
+ mesh->bone_aabbs.write[i].merge_with(bone);
+ }
}
mesh->aabb.merge_with(p_surface.aabb);
}
@@ -266,12 +277,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();
@@ -312,7 +323,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();
}
@@ -333,48 +344,12 @@ RS::SurfaceData MeshStorage::mesh_get_surface(RID p_mesh, int p_surface) const {
RS::SurfaceData sd;
sd.format = s.format;
- {
- Vector<uint8_t> ret;
- ret.resize(s.vertex_buffer_size);
- glBindBuffer(GL_ARRAY_BUFFER, s.vertex_buffer);
-
-#if defined(__EMSCRIPTEN__)
- {
- uint8_t *w = ret.ptrw();
- glGetBufferSubData(GL_ARRAY_BUFFER, 0, s.vertex_buffer_size, w);
- }
-#else
- void *data = glMapBufferRange(GL_ARRAY_BUFFER, 0, s.vertex_buffer_size, GL_MAP_READ_BIT);
- ERR_FAIL_NULL_V(data, RS::SurfaceData());
- {
- uint8_t *w = ret.ptrw();
- memcpy(w, data, s.vertex_buffer_size);
- }
- glUnmapBuffer(GL_ARRAY_BUFFER);
-#endif
- sd.vertex_data = ret;
+ if (s.vertex_buffer != 0) {
+ sd.vertex_data = Utilities::buffer_get_data(GL_ARRAY_BUFFER, s.vertex_buffer, s.vertex_buffer_size);
}
if (s.attribute_buffer != 0) {
- Vector<uint8_t> ret;
- ret.resize(s.attribute_buffer_size);
- glBindBuffer(GL_ARRAY_BUFFER, s.attribute_buffer);
-
-#if defined(__EMSCRIPTEN__)
- {
- uint8_t *w = ret.ptrw();
- glGetBufferSubData(GL_ARRAY_BUFFER, 0, s.attribute_buffer_size, w);
- }
-#else
- void *data = glMapBufferRange(GL_ARRAY_BUFFER, 0, s.attribute_buffer_size, GL_MAP_READ_BIT);
- ERR_FAIL_NULL_V(data, RS::SurfaceData());
- {
- uint8_t *w = ret.ptrw();
- memcpy(w, data, s.attribute_buffer_size);
- }
- glUnmapBuffer(GL_ARRAY_BUFFER);
-#endif
- sd.attribute_data = ret;
+ sd.attribute_data = Utilities::buffer_get_data(GL_ARRAY_BUFFER, s.attribute_buffer, s.attribute_buffer_size);
}
sd.vertex_count = s.vertex_count;
@@ -382,33 +357,14 @@ RS::SurfaceData MeshStorage::mesh_get_surface(RID p_mesh, int p_surface) const {
sd.primitive = s.primitive;
if (sd.index_count) {
- Vector<uint8_t> ret;
- ret.resize(s.index_buffer_size);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s.index_buffer);
-
-#if defined(__EMSCRIPTEN__)
- {
- uint8_t *w = ret.ptrw();
- glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, s.index_buffer_size, w);
- }
-#else
- void *data = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, s.index_buffer_size, GL_MAP_READ_BIT);
- ERR_FAIL_NULL_V(data, RS::SurfaceData());
- {
- uint8_t *w = ret.ptrw();
- memcpy(w, data, s.index_buffer_size);
- }
- glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
-#endif
- sd.index_data = ret;
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+ 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 = RD::get_singleton()->buffer_get_data(s.lods[i].index_buffer);
+ 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);
}
@@ -559,7 +515,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) {
@@ -608,12 +564,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);
}
}
@@ -648,17 +604,16 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V
} break;
case RS::ARRAY_NORMAL: {
attribs[i].offset = vertex_stride;
- // Will need to change to accommodate octahedral compression
- attribs[i].size = 4;
- attribs[i].type = GL_UNSIGNED_INT_2_10_10_10_REV;
- vertex_stride += sizeof(float);
+ attribs[i].size = 2;
+ attribs[i].type = GL_UNSIGNED_SHORT;
+ vertex_stride += sizeof(uint16_t) * 2;
attribs[i].normalized = GL_TRUE;
} break;
case RS::ARRAY_TANGENT: {
attribs[i].offset = vertex_stride;
- attribs[i].size = 4;
- attribs[i].type = GL_UNSIGNED_INT_2_10_10_10_REV;
- vertex_stride += sizeof(float);
+ attribs[i].size = 2;
+ attribs[i].type = GL_UNSIGNED_SHORT;
+ vertex_stride += sizeof(uint16_t) * 2;
attribs[i].normalized = GL_TRUE;
} break;
case RS::ARRAY_COLOR: {
@@ -723,17 +678,6 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V
for (int i = 0; i < RS::ARRAY_INDEX; i++) {
if (!attribs[i].enabled) {
glDisableVertexAttribArray(i);
- if (s->format & RS::ARRAY_FLAG_USE_2D_VERTICES) {
- if (i == RS::ARRAY_COLOR) {
- glVertexAttrib4f(i, 1, 1, 1, 1);
- } else if (i == RS::ARRAY_TEX_UV) {
- glVertexAttrib2f(i, 1, 1);
- } else if (i == RS::ARRAY_BONES) {
- glVertexAttrib4f(i, 1, 1, 1, 1);
- } else if (i == RS::ARRAY_WEIGHTS) {
- glVertexAttrib4f(i, 1, 1, 1, 1);
- }
- }
continue;
}
if (i <= RS::ARRAY_TANGENT) {
@@ -949,8 +893,8 @@ void MeshStorage::multimesh_allocate_data(RID p_multimesh, int p_instances, RS::
multimesh->uses_colors = p_use_colors;
multimesh->color_offset_cache = p_transform_format == RS::MULTIMESH_TRANSFORM_2D ? 8 : 12;
multimesh->uses_custom_data = p_use_custom_data;
- multimesh->custom_data_offset_cache = multimesh->color_offset_cache + (p_use_colors ? 4 : 0);
- multimesh->stride_cache = multimesh->custom_data_offset_cache + (p_use_custom_data ? 4 : 0);
+ multimesh->custom_data_offset_cache = multimesh->color_offset_cache + (p_use_colors ? 2 : 0);
+ multimesh->stride_cache = multimesh->custom_data_offset_cache + (p_use_custom_data ? 2 : 0);
multimesh->buffer_set = false;
multimesh->data_cache = Vector<float>();
@@ -965,7 +909,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 {
@@ -977,7 +921,7 @@ int MeshStorage::multimesh_get_instance_count(RID p_multimesh) const {
void MeshStorage::multimesh_set_mesh(RID p_multimesh, RID p_mesh) {
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_COND(!multimesh);
- if (multimesh->mesh == p_mesh) {
+ if (multimesh->mesh == p_mesh || p_mesh.is_null()) {
return;
}
multimesh->mesh = p_mesh;
@@ -990,17 +934,16 @@ void MeshStorage::multimesh_set_mesh(RID p_multimesh, RID p_mesh) {
//we have a data cache, just mark it dirty
_multimesh_mark_all_dirty(multimesh, false, true);
} else if (multimesh->instances) {
- //need to re-create AABB unfortunately, calling this has a penalty
+ // Need to re-create AABB. Unfortunately, calling this has a penalty.
if (multimesh->buffer_set) {
- // TODO add a function to RasterizerStorage to get data from a buffer
- //Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer);
- //const uint8_t *r = buffer.ptr();
- //const float *data = (const float *)r;
- //_multimesh_re_create_aabb(multimesh, data, multimesh->instances);
+ 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
@@ -1017,10 +960,11 @@ void MeshStorage::_multimesh_make_local(MultiMesh *multimesh) const {
float *w = multimesh->data_cache.ptrw();
if (multimesh->buffer_set) {
- //Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer);
+ 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();
- // memcpy(w, r, buffer.size());
+ const uint8_t *r = buffer.ptr();
+ memcpy(w, r, buffer.size());
}
} else {
memset(w, 0, (size_t)multimesh->instances * multimesh->stride_cache * sizeof(float));
@@ -1186,14 +1130,12 @@ void MeshStorage::multimesh_instance_set_color(RID p_multimesh, int p_index, con
_multimesh_make_local(multimesh);
{
+ // Colors are packed into 2 floats.
float *w = multimesh->data_cache.ptrw();
float *dataptr = w + p_index * multimesh->stride_cache + multimesh->color_offset_cache;
-
- dataptr[0] = p_color.r;
- dataptr[1] = p_color.g;
- dataptr[2] = p_color.b;
- dataptr[3] = p_color.a;
+ uint16_t val[4] = { Math::make_half_float(p_color.r), Math::make_half_float(p_color.g), Math::make_half_float(p_color.b), Math::make_half_float(p_color.a) };
+ memcpy(dataptr, val, 2 * 4);
}
_multimesh_mark_dirty(multimesh, p_index, false);
@@ -1211,11 +1153,8 @@ void MeshStorage::multimesh_instance_set_custom_data(RID p_multimesh, int p_inde
float *w = multimesh->data_cache.ptrw();
float *dataptr = w + p_index * multimesh->stride_cache + multimesh->custom_data_offset_cache;
-
- dataptr[0] = p_color.r;
- dataptr[1] = p_color.g;
- dataptr[2] = p_color.b;
- dataptr[3] = p_color.a;
+ uint16_t val[4] = { Math::make_half_float(p_color.r), Math::make_half_float(p_color.g), Math::make_half_float(p_color.b), Math::make_half_float(p_color.a) };
+ memcpy(dataptr, val, 2 * 4);
}
_multimesh_mark_dirty(multimesh, p_index, false);
@@ -1306,11 +1245,12 @@ Color MeshStorage::multimesh_instance_get_color(RID p_multimesh, int p_index) co
const float *r = multimesh->data_cache.ptr();
const float *dataptr = r + p_index * multimesh->stride_cache + multimesh->color_offset_cache;
-
- c.r = dataptr[0];
- c.g = dataptr[1];
- c.b = dataptr[2];
- c.a = dataptr[3];
+ uint16_t raw_data[4];
+ memcpy(raw_data, dataptr, 2 * 4);
+ c.r = Math::half_to_float(raw_data[0]);
+ c.g = Math::half_to_float(raw_data[1]);
+ c.b = Math::half_to_float(raw_data[2]);
+ c.a = Math::half_to_float(raw_data[3]);
}
return c;
@@ -1329,11 +1269,12 @@ Color MeshStorage::multimesh_instance_get_custom_data(RID p_multimesh, int p_ind
const float *r = multimesh->data_cache.ptr();
const float *dataptr = r + p_index * multimesh->stride_cache + multimesh->custom_data_offset_cache;
-
- c.r = dataptr[0];
- c.g = dataptr[1];
- c.b = dataptr[2];
- c.a = dataptr[3];
+ uint16_t raw_data[4];
+ memcpy(raw_data, dataptr, 2 * 4);
+ c.r = Math::half_to_float(raw_data[0]);
+ c.g = Math::half_to_float(raw_data[1]);
+ c.b = Math::half_to_float(raw_data[2]);
+ c.a = Math::half_to_float(raw_data[3]);
}
return c;
@@ -1342,19 +1283,66 @@ Color MeshStorage::multimesh_instance_get_custom_data(RID p_multimesh, int p_ind
void MeshStorage::multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) {
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_COND(!multimesh);
- ERR_FAIL_COND(p_buffer.size() != (multimesh->instances * (int)multimesh->stride_cache));
- {
+ if (multimesh->uses_colors || multimesh->uses_custom_data) {
+ // Color and custom need to be packed so copy buffer to data_cache and pack.
+
+ _multimesh_make_local(multimesh);
+ multimesh->data_cache = p_buffer;
+
+ float *w = multimesh->data_cache.ptrw();
+ uint32_t old_stride = multimesh->xform_format == RS::MULTIMESH_TRANSFORM_2D ? 8 : 12;
+ old_stride += multimesh->uses_colors ? 4 : 0;
+ old_stride += multimesh->uses_custom_data ? 4 : 0;
+ for (int i = 0; i < multimesh->instances; i++) {
+ {
+ float *dataptr = w + i * old_stride;
+ float *newptr = w + i * multimesh->stride_cache;
+ float vals[8] = { dataptr[0], dataptr[1], dataptr[2], dataptr[3], dataptr[4], dataptr[5], dataptr[6], dataptr[7] };
+ memcpy(newptr, vals, 8 * 4);
+ }
+
+ if (multimesh->xform_format == RS::MULTIMESH_TRANSFORM_3D) {
+ float *dataptr = w + i * old_stride + 8;
+ float *newptr = w + i * multimesh->stride_cache + 8;
+ float vals[8] = { dataptr[0], dataptr[1], dataptr[2], dataptr[3] };
+ memcpy(newptr, vals, 4 * 4);
+ }
+
+ if (multimesh->uses_colors) {
+ float *dataptr = w + i * old_stride + (multimesh->xform_format == RS::MULTIMESH_TRANSFORM_2D ? 8 : 12);
+ float *newptr = w + i * multimesh->stride_cache + multimesh->color_offset_cache;
+ uint16_t val[4] = { Math::make_half_float(dataptr[0]), Math::make_half_float(dataptr[1]), Math::make_half_float(dataptr[2]), Math::make_half_float(dataptr[3]) };
+ memcpy(newptr, val, 2 * 4);
+ }
+ if (multimesh->uses_custom_data) {
+ float *dataptr = w + i * old_stride + (multimesh->xform_format == RS::MULTIMESH_TRANSFORM_2D ? 8 : 12) + (multimesh->uses_colors ? 4 : 0);
+ float *newptr = w + i * multimesh->stride_cache + multimesh->custom_data_offset_cache;
+ uint16_t val[4] = { Math::make_half_float(dataptr[0]), Math::make_half_float(dataptr[1]), Math::make_half_float(dataptr[2]), Math::make_half_float(dataptr[3]) };
+ memcpy(newptr, val, 2 * 4);
+ }
+ }
+
+ multimesh->data_cache.resize(multimesh->instances * (int)multimesh->stride_cache);
+ const float *r = multimesh->data_cache.ptr();
+ glBindBuffer(GL_ARRAY_BUFFER, multimesh->buffer);
+ glBufferData(GL_ARRAY_BUFFER, multimesh->data_cache.size() * sizeof(float), r, GL_STATIC_DRAW);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ } else {
+ // Only Transform is being used, so we can upload directly.
+ ERR_FAIL_COND(p_buffer.size() != (multimesh->instances * (int)multimesh->stride_cache));
const float *r = p_buffer.ptr();
glBindBuffer(GL_ARRAY_BUFFER, multimesh->buffer);
glBufferData(GL_ARRAY_BUFFER, p_buffer.size() * sizeof(float), r, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
- multimesh->buffer_set = true;
}
- if (multimesh->data_cache.size()) {
+ multimesh->buffer_set = true;
+
+ if (multimesh->data_cache.size() || multimesh->uses_colors || multimesh->uses_custom_data) {
//if we have a data cache, just update it
- multimesh->data_cache = p_buffer;
+ multimesh->data_cache = multimesh->data_cache;
{
//clear dirty since nothing will be dirty anymore
uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
@@ -1370,29 +1358,78 @@ void MeshStorage::multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_b
const float *data = p_buffer.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);
}
}
Vector<float> MeshStorage::multimesh_get_buffer(RID p_multimesh) const {
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_COND_V(!multimesh, Vector<float>());
+ Vector<float> ret;
if (multimesh->buffer == 0) {
return Vector<float>();
} else if (multimesh->data_cache.size()) {
- return multimesh->data_cache;
+ ret = multimesh->data_cache;
} else {
- //get from memory
+ // Buffer not cached, so fetch from GPU memory. This can be a stalling operation, avoid whenever possible.
- //Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer);
- Vector<float> ret;
+ 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();
- // const uint8_t *r = buffer.ptr();
- // memcpy(w, r, buffer.size());
- //}
+ {
+ float *w = ret.ptrw();
+ const uint8_t *r = buffer.ptr();
+ memcpy(w, r, buffer.size());
+ }
+ }
+ if (multimesh->uses_colors || multimesh->uses_custom_data) {
+ // Need to decompress buffer.
+ uint32_t new_stride = multimesh->xform_format == RS::MULTIMESH_TRANSFORM_2D ? 8 : 12;
+ new_stride += multimesh->uses_colors ? 4 : 0;
+ new_stride += multimesh->uses_custom_data ? 4 : 0;
+
+ Vector<float> decompressed;
+ decompressed.resize(multimesh->instances * (int)new_stride);
+ float *w = decompressed.ptrw();
+ const float *r = ret.ptr();
+
+ for (int i = 0; i < multimesh->instances; i++) {
+ {
+ float *newptr = w + i * new_stride;
+ const float *oldptr = r + i * multimesh->stride_cache;
+ float vals[8] = { oldptr[0], oldptr[1], oldptr[2], oldptr[3], oldptr[4], oldptr[5], oldptr[6], oldptr[7] };
+ memcpy(newptr, vals, 8 * 4);
+ }
+ if (multimesh->xform_format == RS::MULTIMESH_TRANSFORM_3D) {
+ float *newptr = w + i * new_stride + 8;
+ const float *oldptr = r + i * multimesh->stride_cache + 8;
+ float vals[8] = { oldptr[0], oldptr[1], oldptr[2], oldptr[3] };
+ memcpy(newptr, vals, 4 * 4);
+ }
+
+ if (multimesh->uses_colors) {
+ float *newptr = w + i * new_stride + (multimesh->xform_format == RS::MULTIMESH_TRANSFORM_2D ? 8 : 12);
+ const float *oldptr = r + i * multimesh->stride_cache + multimesh->color_offset_cache;
+ uint16_t raw_data[4];
+ memcpy(raw_data, oldptr, 2 * 4);
+ newptr[0] = Math::half_to_float(raw_data[0]);
+ newptr[1] = Math::half_to_float(raw_data[1]);
+ newptr[2] = Math::half_to_float(raw_data[2]);
+ newptr[3] = Math::half_to_float(raw_data[3]);
+ }
+ if (multimesh->uses_custom_data) {
+ float *newptr = w + i * new_stride + (multimesh->xform_format == RS::MULTIMESH_TRANSFORM_2D ? 8 : 12) + (multimesh->uses_colors ? 4 : 0);
+ const float *oldptr = r + i * multimesh->stride_cache + multimesh->custom_data_offset_cache;
+ uint16_t raw_data[4];
+ memcpy(raw_data, oldptr, 2 * 4);
+ newptr[0] = Math::half_to_float(raw_data[0]);
+ newptr[1] = Math::half_to_float(raw_data[1]);
+ newptr[2] = Math::half_to_float(raw_data[2]);
+ newptr[3] = Math::half_to_float(raw_data[3]);
+ }
+ }
+ return decompressed;
+ } else {
return ret;
}
}
@@ -1412,7 +1449,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 {
@@ -1439,7 +1476,7 @@ void MeshStorage::_update_dirty_multimeshes() {
if (multimesh->data_cache_used_dirty_regions > 32 || multimesh->data_cache_used_dirty_regions > visible_region_count / 2) {
// If there too many dirty regions, or represent the majority of regions, just copy all, else transfer cost piles up too much
glBindBuffer(GL_ARRAY_BUFFER, multimesh->buffer);
- glBufferData(GL_ARRAY_BUFFER, MIN(visible_region_count * region_size, multimesh->instances * (uint32_t)multimesh->stride_cache * (uint32_t)sizeof(float)), data, GL_STATIC_DRAW);
+ glBufferData(GL_ARRAY_BUFFER, MIN(visible_region_count * region_size, multimesh->instances * multimesh->stride_cache * sizeof(float)), data, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
} else {
// Not that many regions? update them all
@@ -1463,11 +1500,10 @@ void MeshStorage::_update_dirty_multimeshes() {
multimesh->data_cache_used_dirty_regions = 0;
}
- if (multimesh->aabb_dirty) {
- //aabb is dirty..
+ 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);
}
}
@@ -1516,7 +1552,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 068aa2fe40..74f5800795 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
@@ -74,7 +75,7 @@ struct Mesh {
// Cache vertex arrays so they can be created
struct Version {
uint32_t input_mask = 0;
- GLuint vertex_array;
+ GLuint vertex_array = 0;
Attrib attribs[RS::ARRAY_MAX];
};
@@ -90,7 +91,8 @@ struct Mesh {
struct LOD {
float edge_length = 0.0;
uint32_t index_count = 0;
- GLuint index_buffer;
+ uint32_t index_buffer_size = 0;
+ GLuint index_buffer = 0;
};
LOD *lods = nullptr;
@@ -125,7 +127,7 @@ struct Mesh {
RID shadow_mesh;
HashSet<Mesh *> shadow_owners;
- RendererStorage::Dependency dependency;
+ Dependency dependency;
};
/* Mesh Instance */
@@ -173,12 +175,12 @@ struct MultiMesh {
bool *data_cache_dirty_regions = nullptr;
uint32_t data_cache_used_dirty_regions = 0;
- GLuint buffer;
+ GLuint buffer = 0;
bool dirty = false;
MultiMesh *dirty_list = nullptr;
- RendererStorage::Dependency dependency;
+ Dependency dependency;
};
struct Skeleton {
@@ -193,7 +195,7 @@ struct Skeleton {
uint64_t version = 1;
- RendererStorage::Dependency dependency;
+ Dependency dependency;
};
class MeshStorage : public RendererMeshStorage {
@@ -360,7 +362,7 @@ public:
_FORCE_INLINE_ GLenum mesh_surface_get_index_type(void *p_surface) const {
Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
- return s->vertex_count <= 65536 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
+ return (s->vertex_count <= 65536 && s->vertex_count > 0) ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
}
// Use this to cache Vertex Array Objects so they are only generated once
@@ -530,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..543638e8ff 100644
--- a/drivers/gles3/storage/texture_storage.cpp
+++ b/drivers/gles3/storage/texture_storage.cpp
@@ -115,6 +115,17 @@ TextureStorage::TextureStorage() {
texture_2d_layered_initialize(default_gl_textures[DEFAULT_GL_TEXTURE_CUBEMAP_BLACK], images, RS::TEXTURE_LAYERED_CUBEMAP);
}
+ { // transparent black
+ Ref<Image> image;
+ image.instantiate();
+ image->create(4, 4, true, Image::FORMAT_RGBA8);
+ image->fill(Color(0, 0, 0, 0));
+ image->generate_mipmaps();
+
+ default_gl_textures[DEFAULT_GL_TEXTURE_TRANSPARENT] = texture_allocate();
+ texture_2d_initialize(default_gl_textures[DEFAULT_GL_TEXTURE_TRANSPARENT], image);
+ }
+
{
Ref<Image> image;
image.instantiate();
@@ -183,6 +194,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 +261,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..71f713bc9f 100644
--- a/drivers/gles3/storage/texture_storage.h
+++ b/drivers/gles3/storage/texture_storage.h
@@ -103,6 +103,7 @@ namespace GLES3 {
enum DefaultGLTexture {
DEFAULT_GL_TEXTURE_WHITE,
DEFAULT_GL_TEXTURE_BLACK,
+ DEFAULT_GL_TEXTURE_TRANSPARENT,
DEFAULT_GL_TEXTURE_NORMAL,
DEFAULT_GL_TEXTURE_ANISO,
DEFAULT_GL_TEXTURE_DEPTH,
@@ -132,6 +133,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 +376,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 +419,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 +547,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 +578,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/pulseaudio/audio_driver_pulseaudio.cpp b/drivers/pulseaudio/audio_driver_pulseaudio.cpp
index a6c35b6837..b18d383119 100644
--- a/drivers/pulseaudio/audio_driver_pulseaudio.cpp
+++ b/drivers/pulseaudio/audio_driver_pulseaudio.cpp
@@ -178,7 +178,7 @@ Error AudioDriverPulseAudio::detect_channels(bool capture) {
Error AudioDriverPulseAudio::init_device() {
// If there is a specified device check that it is really present
if (device_name != "Default") {
- Array list = get_device_list();
+ PackedStringArray list = get_device_list();
if (list.find(device_name) == -1) {
device_name = "Default";
new_device = "Default";
@@ -599,7 +599,7 @@ void AudioDriverPulseAudio::pa_sinklist_cb(pa_context *c, const pa_sink_info *l,
ad->pa_status++;
}
-Array AudioDriverPulseAudio::get_device_list() {
+PackedStringArray AudioDriverPulseAudio::get_device_list() {
pa_devices.clear();
pa_devices.push_back("Default");
@@ -681,7 +681,7 @@ void AudioDriverPulseAudio::finish() {
Error AudioDriverPulseAudio::capture_init_device() {
// If there is a specified device check that it is really present
if (capture_device_name != "Default") {
- Array list = capture_get_device_list();
+ PackedStringArray list = capture_get_device_list();
if (list.find(capture_device_name) == -1) {
capture_device_name = "Default";
capture_new_device = "Default";
@@ -785,7 +785,7 @@ void AudioDriverPulseAudio::pa_sourcelist_cb(pa_context *c, const pa_source_info
ad->pa_status++;
}
-Array AudioDriverPulseAudio::capture_get_device_list() {
+PackedStringArray AudioDriverPulseAudio::capture_get_device_list() {
pa_rec_devices.clear();
pa_rec_devices.push_back("Default");
diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.h b/drivers/pulseaudio/audio_driver_pulseaudio.h
index af96489972..27c684578e 100644
--- a/drivers/pulseaudio/audio_driver_pulseaudio.h
+++ b/drivers/pulseaudio/audio_driver_pulseaudio.h
@@ -67,8 +67,8 @@ class AudioDriverPulseAudio : public AudioDriver {
int channels = 0;
int pa_ready = 0;
int pa_status = 0;
- Array pa_devices;
- Array pa_rec_devices;
+ PackedStringArray pa_devices;
+ PackedStringArray pa_rec_devices;
bool active = false;
bool thread_exited = false;
@@ -103,11 +103,11 @@ public:
virtual int get_mix_rate() const;
virtual SpeakerMode get_speaker_mode() const;
- virtual Array get_device_list();
+ virtual PackedStringArray get_device_list();
virtual String get_device();
virtual void set_device(String device);
- virtual Array capture_get_device_list();
+ virtual PackedStringArray capture_get_device_list();
virtual void capture_set_device(const String &p_name);
virtual String capture_get_device();
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..f5dca7c282 100644
--- a/drivers/unix/dir_access_unix.h
+++ b/drivers/unix/dir_access_unix.h
@@ -43,54 +43,53 @@
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);
public:
- virtual Error list_dir_begin(); ///< This starts dir listing
- virtual String get_next();
- virtual bool current_is_dir() const;
- virtual bool current_is_hidden() const;
+ virtual Error list_dir_begin() override; ///< This starts dir listing
+ virtual String get_next() override;
+ virtual bool current_is_dir() const override;
+ virtual bool current_is_hidden() const override;
- virtual void list_dir_end(); ///<
+ virtual void list_dir_end() override; ///<
- virtual int get_drive_count();
- virtual String get_drive(int p_drive);
- virtual int get_current_drive();
- virtual bool drives_are_shortcuts();
+ virtual int get_drive_count() override;
+ virtual String get_drive(int p_drive) override;
+ virtual int get_current_drive() override;
+ virtual bool drives_are_shortcuts() override;
- virtual Error change_dir(String p_dir); ///< can be relative or absolute, return false on success
- virtual String get_current_dir(bool p_include_drive = true) const; ///< return current dir location
- virtual Error make_dir(String p_dir);
+ virtual Error change_dir(String p_dir) override; ///< can be relative or absolute, return false on success
+ virtual String get_current_dir(bool p_include_drive = true) const override; ///< return current dir location
+ virtual Error make_dir(String p_dir) override;
- virtual bool file_exists(String p_file);
- virtual bool dir_exists(String p_dir);
- virtual bool is_readable(String p_dir);
- virtual bool is_writable(String p_dir);
+ virtual bool file_exists(String p_file) override;
+ virtual bool dir_exists(String p_dir) override;
+ virtual bool is_readable(String p_dir) override;
+ virtual bool is_writable(String p_dir) override;
virtual uint64_t get_modified_time(String p_file);
- virtual Error rename(String p_path, String p_new_path);
- virtual Error remove(String p_path);
+ virtual Error rename(String p_path, String p_new_path) override;
+ virtual Error remove(String p_path) override;
- virtual bool is_link(String p_file);
- virtual String read_link(String p_file);
- virtual Error create_link(String p_source, String p_target);
+ virtual bool is_link(String p_file) override;
+ virtual String read_link(String p_file) override;
+ virtual Error create_link(String p_source, String p_target) override;
- virtual uint64_t get_space_left();
+ virtual uint64_t get_space_left() override;
- virtual String get_filesystem_type() const;
+ virtual String get_filesystem_type() const override;
DirAccessUnix();
~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..297c34e454 100644
--- a/drivers/unix/file_access_unix.h
+++ b/drivers/unix/file_access_unix.h
@@ -49,43 +49,43 @@ class FileAccessUnix : public FileAccess {
String path;
String path_src;
- static Ref<FileAccess> create_libc();
void _close();
public:
static CloseNotificationFunc close_notification_func;
- virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file
- virtual bool is_open() const; ///< true when file is open
+ virtual Error _open(const String &p_path, int p_mode_flags) override; ///< open a file
+ virtual bool is_open() const override; ///< true when file is open
- virtual String get_path() const; /// returns the path for the current open file
- virtual String get_path_absolute() const; /// returns the absolute path for the current open file
+ virtual String get_path() const override; /// returns the path for the current open file
+ virtual String get_path_absolute() const override; /// returns the absolute path for the current open file
- virtual void seek(uint64_t p_position); ///< seek to a given position
- virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file
- virtual uint64_t get_position() const; ///< get position in the file
- virtual uint64_t get_length() const; ///< get size of the file
+ virtual void seek(uint64_t p_position) override; ///< seek to a given position
+ virtual void seek_end(int64_t p_position = 0) override; ///< seek from the end of file
+ virtual uint64_t get_position() const override; ///< get position in the file
+ virtual uint64_t get_length() const override; ///< get size of the file
- virtual bool eof_reached() const; ///< reading passed EOF
+ virtual bool eof_reached() const override; ///< reading passed EOF
- virtual uint8_t get_8() const; ///< get a byte
- virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const;
+ virtual uint8_t get_8() const override; ///< get a byte
+ virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override;
- virtual Error get_error() const; ///< get last error
+ virtual Error get_error() const override; ///< get last error
- virtual void flush();
- virtual void store_8(uint8_t p_dest); ///< store a byte
- virtual void store_buffer(const uint8_t *p_src, uint64_t p_length); ///< store an array of bytes
+ virtual void flush() override;
+ virtual void store_8(uint8_t p_dest) override; ///< store a byte
+ virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override; ///< store an array of bytes
- virtual bool file_exists(const String &p_path); ///< return true if a file exists
+ virtual bool file_exists(const String &p_path) override; ///< return true if a file exists
- virtual uint64_t _get_modified_time(const String &p_file);
- virtual uint32_t _get_unix_permissions(const String &p_file);
- virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions);
+ virtual uint64_t _get_modified_time(const String &p_file) override;
+ virtual uint32_t _get_unix_permissions(const String &p_file) override;
+ virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override;
FileAccessUnix() {}
virtual ~FileAccessUnix();
};
-#endif
-#endif
+#endif // UNIX_ENABLED || LIBC_FILEIO_ENABLED
+
+#endif // FILE_ACCESS_UNIX_H
diff --git a/drivers/unix/ip_unix.cpp b/drivers/unix/ip_unix.cpp
index 2deeb79957..0dc2efedc1 100644
--- a/drivers/unix/ip_unix.cpp
+++ b/drivers/unix/ip_unix.cpp
@@ -95,12 +95,12 @@ void IPUnix::_resolve_hostname(List<IPAddress> &r_addresses, const String &p_hos
int s = getaddrinfo(p_hostname.utf8().get_data(), nullptr, &hints, &result);
if (s != 0) {
- ERR_PRINT("getaddrinfo failed! Cannot resolve hostname.");
+ print_verbose("getaddrinfo failed! Cannot resolve hostname.");
return;
}
if (result == nullptr || result->ai_addr == nullptr) {
- ERR_PRINT("Invalid response from getaddrinfo");
+ print_verbose("Invalid response from getaddrinfo");
if (result) {
freeaddrinfo(result);
}
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 77aab72d40..2debba1b83 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"
@@ -45,7 +46,7 @@
static const uint32_t SMALL_ALLOCATION_MAX_SIZE = 4096;
-// Get the Vulkan object information and possible stage access types (bitwise OR'd with incoming values)
+// Get the Vulkan object information and possible stage access types (bitwise OR'd with incoming values).
RenderingDeviceVulkan::Buffer *RenderingDeviceVulkan::_get_buffer_from_owner(RID p_buffer, VkPipelineStageFlags &r_stage_mask, VkAccessFlags &r_access_mask, uint32_t p_post_barrier) {
Buffer *buffer = nullptr;
if (vertex_buffer_owner.owns(p_buffer)) {
@@ -106,9 +107,9 @@ 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) {
- // Transitioning from write to read, protect the shaders that may use this next
- // Allow for copies/image layout transitions
+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;
dependency.dstAccessMask |= VK_ACCESS_TRANSFER_READ_BIT;
@@ -124,7 +125,7 @@ static void update_external_dependency_for_store(VkSubpassDependency &dependency
}
if (is_depth) {
- // Depth resources have additional stages that may be interested in them
+ // Depth resources have additional stages that may be interested in them.
dependency.dstStageMask |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
dependency.dstAccessMask |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
}
@@ -145,7 +146,7 @@ void RenderingDeviceVulkan::_add_dependency(RID p_id, RID p_depends_on) {
}
void RenderingDeviceVulkan::_free_dependencies(RID p_id) {
- //direct dependencies must be freed
+ // Direct dependencies must be freed.
HashMap<RID, HashSet<RID>>::Iterator E = dependency_map.find(p_id);
if (E) {
@@ -155,7 +156,7 @@ void RenderingDeviceVulkan::_free_dependencies(RID p_id) {
dependency_map.remove(E);
}
- //reverse dependencies must be unreferenced
+ // Reverse dependencies must be unreferenced.
E = reverse_dependency_map.find(p_id);
if (E) {
@@ -859,7 +860,7 @@ uint32_t RenderingDeviceVulkan::get_image_format_pixel_size(DataFormat p_format)
case DATA_FORMAT_D24_UNORM_S8_UINT:
return 4;
case DATA_FORMAT_D32_SFLOAT_S8_UINT:
- return 5; //?
+ return 5; // ?
case DATA_FORMAT_BC1_RGB_UNORM_BLOCK:
case DATA_FORMAT_BC1_RGB_SRGB_BLOCK:
case DATA_FORMAT_BC1_RGBA_UNORM_BLOCK:
@@ -994,7 +995,7 @@ void RenderingDeviceVulkan::get_compressed_image_format_block_dimensions(DataFor
case DATA_FORMAT_EAC_R11_SNORM_BLOCK:
case DATA_FORMAT_EAC_R11G11_UNORM_BLOCK:
case DATA_FORMAT_EAC_R11G11_SNORM_BLOCK:
- case DATA_FORMAT_ASTC_4x4_UNORM_BLOCK: //again, not sure about astc
+ case DATA_FORMAT_ASTC_4x4_UNORM_BLOCK: // Again, not sure about astc.
case DATA_FORMAT_ASTC_4x4_SRGB_BLOCK:
case DATA_FORMAT_ASTC_5x4_UNORM_BLOCK:
case DATA_FORMAT_ASTC_5x4_SRGB_BLOCK:
@@ -1072,7 +1073,7 @@ uint32_t RenderingDeviceVulkan::get_compressed_image_format_block_byte_size(Data
case DATA_FORMAT_EAC_R11G11_UNORM_BLOCK:
case DATA_FORMAT_EAC_R11G11_SNORM_BLOCK:
return 16;
- case DATA_FORMAT_ASTC_4x4_UNORM_BLOCK: //again, not sure about astc
+ case DATA_FORMAT_ASTC_4x4_UNORM_BLOCK: // Again, not sure about astc.
case DATA_FORMAT_ASTC_4x4_SRGB_BLOCK:
case DATA_FORMAT_ASTC_5x4_UNORM_BLOCK:
case DATA_FORMAT_ASTC_5x4_SRGB_BLOCK:
@@ -1100,7 +1101,7 @@ uint32_t RenderingDeviceVulkan::get_compressed_image_format_block_byte_size(Data
case DATA_FORMAT_ASTC_12x10_SRGB_BLOCK:
case DATA_FORMAT_ASTC_12x12_UNORM_BLOCK:
case DATA_FORMAT_ASTC_12x12_SRGB_BLOCK:
- return 8; //wrong
+ return 8; // Wrong.
default: {
}
}
@@ -1109,7 +1110,7 @@ uint32_t RenderingDeviceVulkan::get_compressed_image_format_block_byte_size(Data
uint32_t RenderingDeviceVulkan::get_compressed_image_format_pixel_rshift(DataFormat p_format) {
switch (p_format) {
- case DATA_FORMAT_BC1_RGB_UNORM_BLOCK: //these formats are half byte size, so rshift is 1
+ case DATA_FORMAT_BC1_RGB_UNORM_BLOCK: // These formats are half byte size, so rshift is 1.
case DATA_FORMAT_BC1_RGB_SRGB_BLOCK:
case DATA_FORMAT_BC1_RGBA_UNORM_BLOCK:
case DATA_FORMAT_BC1_RGBA_SRGB_BLOCK:
@@ -1183,7 +1184,7 @@ uint32_t RenderingDeviceVulkan::get_image_format_required_size(DataFormat p_form
}
uint32_t RenderingDeviceVulkan::get_image_required_mipmaps(uint32_t p_width, uint32_t p_height, uint32_t p_depth) {
- //formats and block size don't really matter here since they can all go down to 1px (even if block is larger)
+ // Formats and block size don't really matter here since they can all go down to 1px (even if block is larger).
uint32_t w = p_width;
uint32_t h = p_height;
uint32_t d = p_depth;
@@ -1400,17 +1401,17 @@ Error RenderingDeviceVulkan::_insert_staging_block() {
return OK;
}
-Error RenderingDeviceVulkan::_staging_buffer_allocate(uint32_t p_amount, uint32_t p_required_align, uint32_t &r_alloc_offset, uint32_t &r_alloc_size, bool p_can_segment, bool p_on_draw_command_buffer) {
- //determine a block to use
+Error RenderingDeviceVulkan::_staging_buffer_allocate(uint32_t p_amount, uint32_t p_required_align, uint32_t &r_alloc_offset, uint32_t &r_alloc_size, bool p_can_segment) {
+ // Determine a block to use.
r_alloc_size = p_amount;
while (true) {
r_alloc_offset = 0;
- //see if we can use current block
+ // See if we can use current block.
if (staging_buffer_blocks[staging_buffer_current].frame_used == frames_drawn) {
- //we used this block this frame, let's see if there is still room
+ // We used this block this frame, let's see if there is still room.
uint32_t write_from = staging_buffer_blocks[staging_buffer_current].fill_amount;
@@ -1424,107 +1425,107 @@ Error RenderingDeviceVulkan::_staging_buffer_allocate(uint32_t p_amount, uint32_
int32_t available_bytes = int32_t(staging_buffer_block_size) - int32_t(write_from);
if ((int32_t)p_amount < available_bytes) {
- //all is good, we should be ok, all will fit
+ // All is good, we should be ok, all will fit.
r_alloc_offset = write_from;
} else if (p_can_segment && available_bytes >= (int32_t)p_required_align) {
- //ok all won't fit but at least we can fit a chunkie
- //all is good, update what needs to be written to
+ // Ok all won't fit but at least we can fit a chunkie.
+ // All is good, update what needs to be written to.
r_alloc_offset = write_from;
r_alloc_size = available_bytes - (available_bytes % p_required_align);
} else {
- //can't fit it into this buffer.
- //will need to try next buffer
+ // Can't fit it into this buffer.
+ // Will need to try next buffer.
staging_buffer_current = (staging_buffer_current + 1) % staging_buffer_blocks.size();
- // before doing anything, though, let's check that we didn't manage to fill all blocks
- // possible in a single frame
+ // Before doing anything, though, let's check that we didn't manage to fill all blocks.
+ // Possible in a single frame.
if (staging_buffer_blocks[staging_buffer_current].frame_used == frames_drawn) {
- //guess we did.. ok, let's see if we can insert a new block..
+ // Guess we did.. ok, let's see if we can insert a new block.
if ((uint64_t)staging_buffer_blocks.size() * staging_buffer_block_size < staging_buffer_max_size) {
- //we can, so we are safe
+ // We can, so we are safe.
Error err = _insert_staging_block();
if (err) {
return err;
}
- //claim for this frame
+ // Claim for this frame.
staging_buffer_blocks.write[staging_buffer_current].frame_used = frames_drawn;
} else {
// Ok, worst case scenario, all the staging buffers belong to this frame
// and this frame is not even done.
- // If this is the main thread, it means the user is likely loading a lot of resources at once,
- // otherwise, the thread should just be blocked until the next frame (currently unimplemented)
+ // If this is the main thread, it means the user is likely loading a lot of resources at once,.
+ // Otherwise, the thread should just be blocked until the next frame (currently unimplemented).
- if (false) { //separate thread from render
+ if (false) { // Separate thread from render.
//block_until_next_frame()
continue;
} else {
- //flush EVERYTHING including setup commands. IF not immediate, also need to flush the draw commands
+ // Flush EVERYTHING including setup commands. IF not immediate, also need to flush the draw commands.
_flush(true);
- //clear the whole staging buffer
+ // Clear the whole staging buffer.
for (int i = 0; i < staging_buffer_blocks.size(); i++) {
staging_buffer_blocks.write[i].frame_used = 0;
staging_buffer_blocks.write[i].fill_amount = 0;
}
- //claim current
+ // Claim current.
staging_buffer_blocks.write[staging_buffer_current].frame_used = frames_drawn;
}
}
} else {
- //not from current frame, so continue and try again
+ // Not from current frame, so continue and try again.
continue;
}
}
} else if (staging_buffer_blocks[staging_buffer_current].frame_used <= frames_drawn - frame_count) {
- //this is an old block, which was already processed, let's reuse
+ // This is an old block, which was already processed, let's reuse.
staging_buffer_blocks.write[staging_buffer_current].frame_used = frames_drawn;
staging_buffer_blocks.write[staging_buffer_current].fill_amount = 0;
} else {
- //this block may still be in use, let's not touch it unless we have to, so.. can we create a new one?
+ // This block may still be in use, let's not touch it unless we have to, so.. can we create a new one?
if ((uint64_t)staging_buffer_blocks.size() * staging_buffer_block_size < staging_buffer_max_size) {
- //we are still allowed to create a new block, so let's do that and insert it for current pos
+ // We are still allowed to create a new block, so let's do that and insert it for current pos.
Error err = _insert_staging_block();
if (err) {
return err;
}
- //claim for this frame
+ // Claim for this frame.
staging_buffer_blocks.write[staging_buffer_current].frame_used = frames_drawn;
} else {
- // oops, we are out of room and we can't create more.
- // let's flush older frames.
+ // Oops, we are out of room and we can't create more.
+ // Let's flush older frames.
// The logic here is that if a game is loading a lot of data from the main thread, it will need to be stalled anyway.
// If loading from a separate thread, we can block that thread until next frame when more room is made (not currently implemented, though).
if (false) {
- //separate thread from render
+ // Separate thread from render.
//block_until_next_frame()
- continue; //and try again
+ continue; // And try again.
} else {
_flush(false);
for (int i = 0; i < staging_buffer_blocks.size(); i++) {
- //clear all blocks but the ones from this frame
+ // Clear all blocks but the ones from this frame.
int block_idx = (i + staging_buffer_current) % staging_buffer_blocks.size();
if (staging_buffer_blocks[block_idx].frame_used == frames_drawn) {
- break; //ok, we reached something from this frame, abort
+ break; // Ok, we reached something from this frame, abort.
}
staging_buffer_blocks.write[block_idx].frame_used = 0;
staging_buffer_blocks.write[block_idx].fill_amount = 0;
}
- //claim for current frame
+ // Claim for current frame.
staging_buffer_blocks.write[staging_buffer_current].frame_used = frames_drawn;
}
}
}
- //all was good, break
+ // All was good, break.
break;
}
@@ -1534,7 +1535,7 @@ Error RenderingDeviceVulkan::_staging_buffer_allocate(uint32_t p_amount, uint32_
}
Error RenderingDeviceVulkan::_buffer_update(Buffer *p_buffer, size_t p_offset, const uint8_t *p_data, size_t p_data_size, bool p_use_draw_command_buffer, uint32_t p_required_align) {
- //submitting may get chunked for various reasons, so convert this to a task
+ // Submitting may get chunked for various reasons, so convert this to a task.
size_t to_submit = p_data_size;
size_t submit_from = 0;
@@ -1542,12 +1543,12 @@ Error RenderingDeviceVulkan::_buffer_update(Buffer *p_buffer, size_t p_offset, c
uint32_t block_write_offset;
uint32_t block_write_amount;
- Error err = _staging_buffer_allocate(MIN(to_submit, staging_buffer_block_size), p_required_align, block_write_offset, block_write_amount, p_use_draw_command_buffer);
+ Error err = _staging_buffer_allocate(MIN(to_submit, staging_buffer_block_size), p_required_align, block_write_offset, block_write_amount);
if (err) {
return err;
}
- //map staging buffer (It's CPU and coherent)
+ // Map staging buffer (It's CPU and coherent).
void *data_ptr = nullptr;
{
@@ -1555,12 +1556,12 @@ Error RenderingDeviceVulkan::_buffer_update(Buffer *p_buffer, size_t p_offset, c
ERR_FAIL_COND_V_MSG(vkerr, ERR_CANT_CREATE, "vmaMapMemory failed with error " + itos(vkerr) + ".");
}
- //copy to staging buffer
+ // Copy to staging buffer.
memcpy(((uint8_t *)data_ptr) + block_write_offset, p_data + submit_from, block_write_amount);
- //unmap
+ // Unmap.
vmaUnmapMemory(allocator, staging_buffer_blocks[staging_buffer_current].allocation);
- //insert a command to copy this
+ // Insert a command to copy this.
VkBufferCopy region;
region.srcOffset = block_write_offset;
@@ -1586,13 +1587,13 @@ void RenderingDeviceVulkan::_memory_barrier(VkPipelineStageFlags p_src_stage_mas
mem_barrier.dstAccessMask = p_dst_sccess;
if (p_src_stage_mask == 0 || p_dst_stage_mask == 0) {
- return; //no barrier, since this is invalid
+ return; // No barrier, since this is invalid.
}
vkCmdPipelineBarrier(p_sync_with_draw ? frames[frame].draw_command_buffer : frames[frame].setup_command_buffer, p_src_stage_mask, p_dst_stage_mask, 0, 1, &mem_barrier, 0, nullptr, 0, nullptr);
}
void RenderingDeviceVulkan::_full_barrier(bool p_sync_with_draw) {
- //used for debug
+ // Used for debug.
_memory_barrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
VK_ACCESS_INDIRECT_COMMAND_READ_BIT |
VK_ACCESS_INDEX_READ_BIT |
@@ -1661,8 +1662,8 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T
#ifndef ANDROID_ENABLED
// vkCreateImage fails with format list on Android (VK_ERROR_OUT_OF_HOST_MEMORY)
- VkImageFormatListCreateInfoKHR format_list_create_info; //keep out of the if, needed for creation
- Vector<VkFormat> allowed_formats; //keep out of the if, needed for creation
+ VkImageFormatListCreateInfoKHR format_list_create_info; // Keep out of the if, needed for creation.
+ Vector<VkFormat> allowed_formats; // Keep out of the if, needed for creation.
#endif
if (p_format.shareable_formats.size()) {
image_create_info.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
@@ -1735,7 +1736,7 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T
image_create_info.samples = rasterization_sample_count[p_format.samples];
image_create_info.tiling = (p_format.usage_bits & TEXTURE_USAGE_CPU_READ_BIT) ? VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL;
- //usage
+ // Usage.
image_create_info.usage = 0;
if (p_format.usage_bits & TEXTURE_USAGE_SAMPLING_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;
}
@@ -1795,7 +1800,7 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T
}
{
- //validate that this image is supported for the intended use
+ // Validate that this image is supported for the intended use.
VkFormatProperties properties;
vkGetPhysicalDeviceFormatProperties(context->get_physical_device(), image_create_info.format, &properties);
VkFormatFeatureFlags flags;
@@ -1829,9 +1834,14 @@ 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
+ // Some view validation.
if (p_view.format_override != DATA_FORMAT_MAX) {
ERR_FAIL_INDEX_V(p_view.format_override, DATA_FORMAT_MAX, RID());
@@ -1841,7 +1851,7 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T
ERR_FAIL_INDEX_V(p_view.swizzle_b, TEXTURE_SWIZZLE_MAX, RID());
ERR_FAIL_INDEX_V(p_view.swizzle_a, TEXTURE_SWIZZLE_MAX, RID());
- //allocate memory
+ // Allocate memory.
uint32_t width, height;
uint32_t image_size = get_image_format_required_size(p_format.format, p_format.width, p_format.height, p_format.depth, p_format.mipmaps, &width, &height);
@@ -1878,19 +1888,19 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T
texture.samples = p_format.samples;
texture.allowed_shared_formats = p_format.shareable_formats;
- //set base layout based on usage priority
+ // Set base layout based on usage priority.
if (p_format.usage_bits & TEXTURE_USAGE_SAMPLING_BIT) {
- //first priority, readable
+ // First priority, readable.
texture.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
} else if (p_format.usage_bits & TEXTURE_USAGE_STORAGE_BIT) {
- //second priority, storage
+ // Second priority, storage.
texture.layout = VK_IMAGE_LAYOUT_GENERAL;
} else if (p_format.usage_bits & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
- //third priority, color or depth
+ // Third priority, color or depth.
texture.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
@@ -1915,7 +1925,7 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T
texture.bound = false;
- //create view
+ // Create view.
VkImageViewCreateInfo image_view_create_info;
image_view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
@@ -1972,7 +1982,7 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T
ERR_FAIL_V_MSG(RID(), "vkCreateImageView failed with error " + itos(err) + ".");
}
- //barrier to set layout
+ // Barrier to set layout.
{
VkImageMemoryBarrier image_memory_barrier;
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
@@ -1994,6 +2004,9 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T
}
RID id = texture_owner.make_rid(texture);
+#ifdef DEV_ENABLED
+ set_resource_name(id, "RID:" + itos(id.get_id()));
+#endif
if (p_data.size()) {
for (uint32_t i = 0; i < image_create_info.arrayLayers; i++) {
@@ -2009,13 +2022,13 @@ RID RenderingDeviceVulkan::texture_create_shared(const TextureView &p_view, RID
Texture *src_texture = texture_owner.get_or_null(p_with_texture);
ERR_FAIL_COND_V(!src_texture, RID());
- if (src_texture->owner.is_valid()) { //ahh this is a share
+ if (src_texture->owner.is_valid()) { // Ahh this is a share.
p_with_texture = src_texture->owner;
src_texture = texture_owner.get_or_null(src_texture->owner);
- ERR_FAIL_COND_V(!src_texture, RID()); //this is a bug
+ ERR_FAIL_COND_V(!src_texture, RID()); // This is a bug.
}
- //create view
+ // Create view.
Texture texture = *src_texture;
@@ -2076,7 +2089,7 @@ RID RenderingDeviceVulkan::texture_create_shared(const TextureView &p_view, RID
usage_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO;
usage_info.pNext = nullptr;
if (p_view.format_override != DATA_FORMAT_MAX) {
- //need to validate usage with vulkan
+ // Need to validate usage with vulkan.
usage_info.usage = 0;
@@ -2123,6 +2136,9 @@ RID RenderingDeviceVulkan::texture_create_shared(const TextureView &p_view, RID
texture.owner = p_with_texture;
RID id = texture_owner.make_rid(texture);
+#ifdef DEV_ENABLED
+ set_resource_name(id, "RID:" + itos(id.get_id()));
+#endif
_add_dependency(id, p_with_texture);
return id;
@@ -2135,9 +2151,9 @@ RID RenderingDeviceVulkan::texture_create_from_extension(TextureType p_type, Dat
Texture texture;
texture.image = image;
- // if we leave texture.allocation as a nullptr, would that be enough to detect we don't "own" the image?
- // also leave texture.allocation_info alone
- // we'll set texture.view later on
+ // If we leave texture.allocation as a nullptr, would that be enough to detect we don't "own" the image?
+ // Also leave texture.allocation_info alone.
+ // We'll set texture.view later on.
texture.type = p_type;
texture.format = p_format;
texture.samples = p_samples;
@@ -2145,14 +2161,14 @@ RID RenderingDeviceVulkan::texture_create_from_extension(TextureType p_type, Dat
texture.height = p_height;
texture.depth = p_depth;
texture.layers = p_layers;
- texture.mipmaps = 0; // maybe make this settable too?
+ texture.mipmaps = 0; // Maybe make this settable too?
texture.usage_flags = p_flags;
texture.base_mipmap = 0;
texture.base_layer = 0;
texture.allowed_shared_formats.push_back(RD::DATA_FORMAT_R8G8B8A8_UNORM);
texture.allowed_shared_formats.push_back(RD::DATA_FORMAT_R8G8B8A8_SRGB);
- // Do we need to do something with texture.layout ?
+ // Do we need to do something with texture.layout?
if (texture.usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
texture.read_aspect_mask = VK_IMAGE_ASPECT_DEPTH_BIT;
@@ -2166,7 +2182,7 @@ RID RenderingDeviceVulkan::texture_create_from_extension(TextureType p_type, Dat
texture.barrier_aspect_mask = VK_IMAGE_ASPECT_COLOR_BIT;
}
- // Create a view for us to use
+ // Create a view for us to use.
VkImageViewCreateInfo image_view_create_info;
image_view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
@@ -2197,7 +2213,7 @@ RID RenderingDeviceVulkan::texture_create_from_extension(TextureType p_type, Dat
VK_COMPONENT_SWIZZLE_A
};
- // hardcode for now, maybe make this settable from outside..
+ // Hardcode for now, maybe make this settable from outside.
image_view_create_info.components.r = component_swizzles[TEXTURE_SWIZZLE_R];
image_view_create_info.components.g = component_swizzles[TEXTURE_SWIZZLE_G];
image_view_create_info.components.b = component_swizzles[TEXTURE_SWIZZLE_B];
@@ -2220,7 +2236,7 @@ RID RenderingDeviceVulkan::texture_create_from_extension(TextureType p_type, Dat
ERR_FAIL_V_MSG(RID(), "vkCreateImageView failed with error " + itos(err) + ".");
}
- //barrier to set layout
+ // Barrier to set layout.
{
VkImageMemoryBarrier image_memory_barrier;
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
@@ -2242,6 +2258,9 @@ RID RenderingDeviceVulkan::texture_create_from_extension(TextureType p_type, Dat
}
RID id = texture_owner.make_rid(texture);
+#ifdef DEV_ENABLED
+ set_resource_name(id, "RID:" + itos(id.get_id()));
+#endif
return id;
}
@@ -2252,10 +2271,10 @@ RID RenderingDeviceVulkan::texture_create_shared_from_slice(const TextureView &p
Texture *src_texture = texture_owner.get_or_null(p_with_texture);
ERR_FAIL_COND_V(!src_texture, RID());
- if (src_texture->owner.is_valid()) { //ahh this is a share
+ if (src_texture->owner.is_valid()) { // Ahh this is a share.
p_with_texture = src_texture->owner;
src_texture = texture_owner.get_or_null(src_texture->owner);
- ERR_FAIL_COND_V(!src_texture, RID()); //this is a bug
+ ERR_FAIL_COND_V(!src_texture, RID()); // This is a bug.
}
ERR_FAIL_COND_V_MSG(p_slice_type == TEXTURE_SLICE_CUBEMAP && (src_texture->type != TEXTURE_TYPE_CUBE && src_texture->type != TEXTURE_TYPE_CUBE_ARRAY), RID(),
@@ -2267,7 +2286,7 @@ RID RenderingDeviceVulkan::texture_create_shared_from_slice(const TextureView &p
ERR_FAIL_COND_V_MSG(p_slice_type == TEXTURE_SLICE_2D_ARRAY && (src_texture->type != TEXTURE_TYPE_2D_ARRAY), RID(),
"Can only create an array slice from a 2D array mipmap");
- //create view
+ // Create view.
ERR_FAIL_UNSIGNED_INDEX_V(p_mipmap, src_texture->mipmaps, RID());
ERR_FAIL_COND_V(p_mipmap + p_mipmaps > src_texture->mipmaps, RID());
@@ -2314,6 +2333,12 @@ RID RenderingDeviceVulkan::texture_create_shared_from_slice(const TextureView &p
image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
}
+ if (p_slice_type == TEXTURE_SLICE_2D) {
+ texture.type = TEXTURE_TYPE_2D;
+ } else if (p_slice_type == TEXTURE_SLICE_3D) {
+ texture.type = TEXTURE_TYPE_3D;
+ }
+
if (p_view.format_override == DATA_FORMAT_MAX || p_view.format_override == texture.format) {
image_view_create_info.format = vulkan_formats[texture.format];
} else {
@@ -2361,6 +2386,9 @@ RID RenderingDeviceVulkan::texture_create_shared_from_slice(const TextureView &p
texture.owner = p_with_texture;
RID id = texture_owner.make_rid(texture);
+#ifdef DEV_ENABLED
+ set_resource_name(id, "RID:" + itos(id.get_id()));
+#endif
_add_dependency(id, p_with_texture);
return id;
@@ -2370,6 +2398,22 @@ Error RenderingDeviceVulkan::texture_update(RID p_texture, uint32_t p_layer, con
return _texture_update(p_texture, p_layer, p_data, p_post_barrier, false);
}
+static _ALWAYS_INLINE_ void _copy_region(uint8_t const *__restrict p_src, uint8_t *__restrict p_dst, uint32_t p_src_x, uint32_t p_src_y, uint32_t p_src_w, uint32_t p_src_h, uint32_t p_src_full_w, uint32_t p_unit_size) {
+ uint32_t src_offset = (p_src_y * p_src_full_w + p_src_x) * p_unit_size;
+ uint32_t dst_offset = 0;
+ for (uint32_t y = p_src_h; y > 0; y--) {
+ uint8_t const *__restrict src = p_src + src_offset;
+ uint8_t *__restrict dst = p_dst + dst_offset;
+ for (uint32_t x = p_src_w * p_unit_size; x > 0; x--) {
+ *dst = *src;
+ src++;
+ dst++;
+ }
+ src_offset += p_src_full_w * p_unit_size;
+ dst_offset += p_src_w * p_unit_size;
+ }
+}
+
Error RenderingDeviceVulkan::_texture_update(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data, uint32_t p_post_barrier, bool p_use_setup_queue) {
_THREAD_SAFE_METHOD_
@@ -2382,7 +2426,7 @@ Error RenderingDeviceVulkan::_texture_update(RID p_texture, uint32_t p_layer, co
if (texture->owner != RID()) {
p_texture = texture->owner;
texture = texture_owner.get_or_null(texture->owner);
- ERR_FAIL_COND_V(!texture, ERR_BUG); //this is a bug
+ ERR_FAIL_COND_V(!texture, ERR_BUG); // This is a bug.
}
ERR_FAIL_COND_V_MSG(texture->bound, ERR_CANT_ACQUIRE_RESOURCE,
@@ -2404,7 +2448,7 @@ Error RenderingDeviceVulkan::_texture_update(RID p_texture, uint32_t p_layer, co
if (required_align == 1) {
required_align = get_image_format_pixel_size(texture->format);
}
- if ((required_align % 4) != 0) { //alignment rules are really strange
+ if ((required_align % 4) != 0) { // Alignment rules are really strange.
required_align *= 4;
}
@@ -2417,7 +2461,7 @@ Error RenderingDeviceVulkan::_texture_update(RID p_texture, uint32_t p_layer, co
VkCommandBuffer command_buffer = p_use_setup_queue ? frames[frame].setup_command_buffer : frames[frame].draw_command_buffer;
- //barrier to transfer
+ // Barrier to transfer.
{
VkImageMemoryBarrier image_memory_barrier;
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
@@ -2451,12 +2495,12 @@ Error RenderingDeviceVulkan::_texture_update(RID p_texture, uint32_t p_layer, co
const uint8_t *read_ptr_mipmap = r + mipmap_offset;
image_size = image_total - mipmap_offset;
- for (uint32_t z = 0; z < depth; z++) { //for 3D textures, depth may be > 0
+ for (uint32_t z = 0; z < depth; z++) { // For 3D textures, depth may be > 0.
const uint8_t *read_ptr = read_ptr_mipmap + image_size * z / depth;
- for (uint32_t x = 0; x < width; x += region_size) {
- for (uint32_t y = 0; y < height; y += region_size) {
+ for (uint32_t y = 0; y < height; y += region_size) {
+ for (uint32_t x = 0; x < width; x += region_size) {
uint32_t region_w = MIN(region_size, width - x);
uint32_t region_h = MIN(region_size, height - y);
@@ -2468,12 +2512,12 @@ Error RenderingDeviceVulkan::_texture_update(RID p_texture, uint32_t p_layer, co
to_allocate >>= get_compressed_image_format_pixel_rshift(texture->format);
uint32_t alloc_offset, alloc_size;
- Error err = _staging_buffer_allocate(to_allocate, required_align, alloc_offset, alloc_size, false, !p_use_setup_queue);
+ Error err = _staging_buffer_allocate(to_allocate, required_align, alloc_offset, alloc_size, false);
ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
uint8_t *write_ptr;
- { //map
+ { // Map.
void *data_ptr = nullptr;
VkResult vkerr = vmaMapMemory(allocator, staging_buffer_blocks[staging_buffer_current].allocation, &data_ptr);
ERR_FAIL_COND_V_MSG(vkerr, ERR_CANT_CREATE, "vmaMapMemory failed with error " + itos(vkerr) + ".");
@@ -2488,52 +2532,32 @@ Error RenderingDeviceVulkan::_texture_update(RID p_texture, uint32_t p_layer, co
ERR_FAIL_COND_V(region_h % block_h, ERR_BUG);
if (block_w != 1 || block_h != 1) {
- //compressed image (blocks)
- //must copy a block region
+ // Compressed image (blocks).
+ // Must copy a block region.
uint32_t block_size = get_compressed_image_format_block_byte_size(texture->format);
- //re-create current variables in blocky format
+ // Re-create current variables in blocky format.
uint32_t xb = x / block_w;
uint32_t yb = y / block_h;
uint32_t wb = width / block_w;
//uint32_t hb = height / block_h;
uint32_t region_wb = region_w / block_w;
uint32_t region_hb = region_h / block_h;
- for (uint32_t xr = 0; xr < region_wb; xr++) {
- for (uint32_t yr = 0; yr < region_hb; yr++) {
- uint32_t src_offset = ((yr + yb) * wb + xr + xb) * block_size;
- uint32_t dst_offset = (yr * region_wb + xr) * block_size;
- //copy block
- for (uint32_t i = 0; i < block_size; i++) {
- write_ptr[dst_offset + i] = read_ptr[src_offset + i];
- }
- }
- }
-
+ _copy_region(read_ptr, write_ptr, xb, yb, region_wb, region_hb, wb, block_size);
} else {
- //regular image (pixels)
- //must copy a pixel region
-
- for (uint32_t xr = 0; xr < region_w; xr++) {
- for (uint32_t yr = 0; yr < region_h; yr++) {
- uint32_t src_offset = ((yr + y) * width + xr + x) * pixel_size;
- uint32_t dst_offset = (yr * region_w + xr) * pixel_size;
- //copy block
- for (uint32_t i = 0; i < pixel_size; i++) {
- write_ptr[dst_offset + i] = read_ptr[src_offset + i];
- }
- }
- }
+ // Regular image (pixels).
+ // Must copy a pixel region.
+ _copy_region(read_ptr, write_ptr, x, y, region_w, region_h, width, pixel_size);
}
- { //unmap
+ { // Unmap.
vmaUnmapMemory(allocator, staging_buffer_blocks[staging_buffer_current].allocation);
}
VkBufferImageCopy buffer_image_copy;
buffer_image_copy.bufferOffset = alloc_offset;
- buffer_image_copy.bufferRowLength = 0; //tightly packed
- buffer_image_copy.bufferImageHeight = 0; //tightly packed
+ buffer_image_copy.bufferRowLength = 0; // Tightly packed.
+ buffer_image_copy.bufferImageHeight = 0; // Tightly packed.
buffer_image_copy.imageSubresource.aspectMask = texture->read_aspect_mask;
buffer_image_copy.imageSubresource.mipLevel = mm_i;
@@ -2560,17 +2584,17 @@ Error RenderingDeviceVulkan::_texture_update(RID p_texture, uint32_t p_layer, co
logic_height = MAX(1u, logic_height >> 1);
}
- //barrier to restore layout
+ // Barrier to restore layout.
{
uint32_t barrier_flags = 0;
uint32_t access_flags = 0;
if (p_post_barrier & BARRIER_MASK_COMPUTE) {
barrier_flags |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
- access_flags |= VK_ACCESS_SHADER_READ_BIT;
+ access_flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
}
if (p_post_barrier & BARRIER_MASK_RASTER) {
barrier_flags |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
- access_flags |= VK_ACCESS_SHADER_READ_BIT;
+ access_flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
}
if (p_post_barrier & BARRIER_MASK_TRANSFER) {
barrier_flags |= VK_PIPELINE_STAGE_TRANSFER_BIT;
@@ -2647,7 +2671,7 @@ Vector<uint8_t> RenderingDeviceVulkan::_texture_get_data_from_image(Texture *tex
const uint8_t *slice_read_ptr = ((uint8_t *)img_mem) + layout.offset + z * layout.depthPitch;
if (block_size > 1) {
- //compressed
+ // Compressed.
uint32_t line_width = (block_size * (width / blockw));
for (uint32_t y = 0; y < height / blockh; y++) {
const uint8_t *rptr = slice_read_ptr + y * layout.rowPitch;
@@ -2657,7 +2681,7 @@ Vector<uint8_t> RenderingDeviceVulkan::_texture_get_data_from_image(Texture *tex
}
} else {
- //uncompressed
+ // Uncompressed.
for (uint32_t y = 0; y < height; y++) {
const uint8_t *rptr = slice_read_ptr + y * layout.rowPitch;
uint8_t *wptr = write_ptr + y * pixel_size * width;
@@ -2693,19 +2717,19 @@ Vector<uint8_t> RenderingDeviceVulkan::texture_get_data(RID p_texture, uint32_t
ERR_FAIL_COND_V(p_layer >= layer_count, Vector<uint8_t>());
if (tex->usage_flags & TEXTURE_USAGE_CPU_READ_BIT) {
- //does not need anything fancy, map and read.
+ // Does not need anything fancy, map and read.
return _texture_get_data_from_image(tex, tex->image, tex->allocation, p_layer);
} else {
- //compute total image size
+ // Compute total image size.
uint32_t width, height, depth;
uint32_t buffer_size = get_image_format_required_size(tex->format, tex->width, tex->height, tex->depth, tex->mipmaps, &width, &height, &depth);
- //allocate buffer
- VkCommandBuffer command_buffer = frames[frame].draw_command_buffer; //makes more sense to retrieve
+ // Allocate buffer.
+ VkCommandBuffer command_buffer = frames[frame].draw_command_buffer; // Makes more sense to retrieve.
Buffer tmp_buffer;
_buffer_allocate(&tmp_buffer, buffer_size, VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_AUTO_PREFER_HOST, VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT);
- { //Source image barrier
+ { // Source image barrier.
VkImageMemoryBarrier image_memory_barrier;
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
image_memory_barrier.pNext = nullptr;
@@ -2761,7 +2785,7 @@ Vector<uint8_t> RenderingDeviceVulkan::texture_get_data(RID p_texture, uint32_t
offset += size;
}
- { //restore src
+ { // Restore src.
VkImageMemoryBarrier image_memory_barrier;
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
image_memory_barrier.pNext = nullptr;
@@ -2876,9 +2900,9 @@ Error RenderingDeviceVulkan::texture_copy(RID p_from_texture, RID p_to_texture,
VkCommandBuffer command_buffer = frames[frame].draw_command_buffer;
{
- //PRE Copy the image
+ // PRE Copy the image.
- { //Source
+ { // Source.
VkImageMemoryBarrier image_memory_barrier;
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
image_memory_barrier.pNext = nullptr;
@@ -2898,7 +2922,7 @@ Error RenderingDeviceVulkan::texture_copy(RID p_from_texture, RID p_to_texture,
vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
}
- { //Dest
+ { // Dest.
VkImageMemoryBarrier image_memory_barrier;
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
image_memory_barrier.pNext = nullptr;
@@ -2919,7 +2943,7 @@ Error RenderingDeviceVulkan::texture_copy(RID p_from_texture, RID p_to_texture,
vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
}
- //COPY
+ // COPY.
{
VkImageCopy image_copy_region;
@@ -2946,7 +2970,7 @@ Error RenderingDeviceVulkan::texture_copy(RID p_from_texture, RID p_to_texture,
vkCmdCopyImage(command_buffer, src_tex->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dst_tex->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &image_copy_region);
}
- // RESTORE LAYOUT for SRC and DST
+ // RESTORE LAYOUT for SRC and DST.
uint32_t barrier_flags = 0;
uint32_t access_flags = 0;
@@ -2967,7 +2991,7 @@ Error RenderingDeviceVulkan::texture_copy(RID p_from_texture, RID p_to_texture,
barrier_flags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
}
- { //restore src
+ { // Restore src.
VkImageMemoryBarrier image_memory_barrier;
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
image_memory_barrier.pNext = nullptr;
@@ -2984,10 +3008,10 @@ Error RenderingDeviceVulkan::texture_copy(RID p_from_texture, RID p_to_texture,
image_memory_barrier.subresourceRange.baseArrayLayer = p_src_layer;
image_memory_barrier.subresourceRange.layerCount = 1;
- vkCmdPipelineBarrier(command_buffer, VK_ACCESS_TRANSFER_WRITE_BIT, barrier_flags, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
+ vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, barrier_flags, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
}
- { //make dst readable
+ { // Make dst readable.
VkImageMemoryBarrier image_memory_barrier;
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
@@ -3010,6 +3034,13 @@ Error RenderingDeviceVulkan::texture_copy(RID p_from_texture, RID p_to_texture,
}
}
+ if (dst_tex->used_in_frame != frames_drawn) {
+ dst_tex->used_in_raster = false;
+ dst_tex->used_in_compute = false;
+ dst_tex->used_in_frame = frames_drawn;
+ }
+ dst_tex->used_in_transfer = true;
+
return OK;
}
@@ -3047,9 +3078,9 @@ Error RenderingDeviceVulkan::texture_resolve_multisample(RID p_from_texture, RID
VkCommandBuffer command_buffer = frames[frame].draw_command_buffer;
{
- //PRE Copy the image
+ // PRE Copy the image.
- { //Source
+ { // Source.
VkImageMemoryBarrier image_memory_barrier;
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
image_memory_barrier.pNext = nullptr;
@@ -3069,7 +3100,7 @@ Error RenderingDeviceVulkan::texture_resolve_multisample(RID p_from_texture, RID
vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
}
- { //Dest
+ { // Dest.
VkImageMemoryBarrier image_memory_barrier;
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
image_memory_barrier.pNext = nullptr;
@@ -3090,7 +3121,7 @@ Error RenderingDeviceVulkan::texture_resolve_multisample(RID p_from_texture, RID
vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
}
- //COPY
+ // COPY.
{
VkImageResolve image_copy_region;
@@ -3117,7 +3148,7 @@ Error RenderingDeviceVulkan::texture_resolve_multisample(RID p_from_texture, RID
vkCmdResolveImage(command_buffer, src_tex->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dst_tex->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &image_copy_region);
}
- // RESTORE LAYOUT for SRC and DST
+ // RESTORE LAYOUT for SRC and DST.
uint32_t barrier_flags = 0;
uint32_t access_flags = 0;
@@ -3138,7 +3169,7 @@ Error RenderingDeviceVulkan::texture_resolve_multisample(RID p_from_texture, RID
barrier_flags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
}
- { //restore src
+ { // Restore src.
VkImageMemoryBarrier image_memory_barrier;
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
image_memory_barrier.pNext = nullptr;
@@ -3158,7 +3189,7 @@ Error RenderingDeviceVulkan::texture_resolve_multisample(RID p_from_texture, RID
vkCmdPipelineBarrier(command_buffer, VK_ACCESS_TRANSFER_WRITE_BIT, barrier_flags, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
}
- { //make dst readable
+ { // Make dst readable.
VkImageMemoryBarrier image_memory_barrier;
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
@@ -3211,13 +3242,13 @@ Error RenderingDeviceVulkan::texture_clear(RID p_texture, const Color &p_color,
VkImageLayout clear_layout = (src_tex->layout == VK_IMAGE_LAYOUT_GENERAL) ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
- // NOTE: Perhaps the valid stages/accesses for a given owner should be a property of the owner. (Here and places like _get_buffer_from_owner)
+ // NOTE: Perhaps the valid stages/accesses for a given owner should be a property of the owner. (Here and places like _get_buffer_from_owner.)
const VkPipelineStageFlags valid_texture_stages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
constexpr VkAccessFlags read_access = VK_ACCESS_SHADER_READ_BIT;
constexpr VkAccessFlags read_write_access = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
const VkAccessFlags valid_texture_access = (src_tex->usage_flags & TEXTURE_USAGE_STORAGE_BIT) ? read_write_access : read_access;
- { // Barrier from previous access with optional layout change (see clear_layout logic above)
+ { // Barrier from previous access with optional layout change (see clear_layout logic above).
VkImageMemoryBarrier image_memory_barrier;
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
image_memory_barrier.pNext = nullptr;
@@ -3253,7 +3284,7 @@ Error RenderingDeviceVulkan::texture_clear(RID p_texture, const Color &p_color,
vkCmdClearColorImage(command_buffer, src_tex->image, clear_layout, &clear_color, 1, &range);
- { // Barrier to post clear accesses (changing back the layout if needed)
+ { // Barrier to post clear accesses (changing back the layout if needed).
uint32_t barrier_flags = 0;
uint32_t access_flags = 0;
@@ -3309,7 +3340,7 @@ bool RenderingDeviceVulkan::texture_is_format_supported_for_usage(DataFormat p_f
_THREAD_SAFE_METHOD_
- //validate that this image is supported for the intended use
+ // Validate that this image is supported for the intended use.
VkFormatProperties properties;
vkGetPhysicalDeviceFormatProperties(context->get_physical_device(), vulkan_formats[p_format], &properties);
VkFormatFeatureFlags flags;
@@ -3340,6 +3371,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;
}
@@ -3348,22 +3384,29 @@ bool RenderingDeviceVulkan::texture_is_format_supported_for_usage(DataFormat p_f
/********************/
VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentFormat> &p_attachments, const Vector<FramebufferPass> &p_passes, InitialAction p_initial_action, FinalAction p_final_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, uint32_t p_view_count, Vector<TextureSamples> *r_samples) {
- // Set up dependencies from/to external equivalent to the default (implicit) one, and then amend them
+ // Set up dependencies from/to external equivalent to the default (implicit) one, and then amend them.
const VkPipelineStageFlags default_access_mask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT |
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++) {
@@ -3374,10 +3417,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];
@@ -3386,83 +3431,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
}
}
@@ -3472,13 +3529,17 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
int last_pass = p_passes.size() - 1;
if (is_depth) {
- //likely missing depth resolve?
+ // Likely missing depth resolve?
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
+ // If using resolve attachments, check resolve attachments.
for (int j = 0; j < p_passes[last_pass].resolve_attachments.size(); j++) {
if (p_passes[last_pass].resolve_attachments[j] == i) {
used_last = true;
@@ -3517,58 +3578,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.
+ }
}
}
@@ -3577,12 +3649,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());
@@ -3590,20 +3664,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;
@@ -3622,14 +3701,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;
@@ -3641,10 +3723,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()) + ").");
@@ -3652,7 +3735,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;
@@ -3664,13 +3749,16 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
bool multisample = p_attachments[attachment].samples > TEXTURE_SAMPLES_1;
ERR_FAIL_COND_V_MSG(multisample, VK_NULL_HANDLE, "Invalid framebuffer format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), resolve attachments can't be multisample.");
reference.attachment = attachment_remap[attachment];
- reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; // VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+ 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;
@@ -3679,6 +3767,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) {
@@ -3693,6 +3782,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++) {
@@ -3703,15 +3818,23 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
ERR_FAIL_INDEX_V_MSG(attachment, p_attachments.size(), VK_NULL_HANDLE, "Invalid framebuffer format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), preserve attachment (" + itos(j) + ").");
if (attachment_last_pass[attachment] != i) {
- //preserve can still be used to keep depth or color from being discarded after use
+ // Preserve can still be used to keep depth or color from being discarded after use.
attachment_last_pass[attachment] = i;
preserve_references.push_back(attachment);
}
}
- 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();
@@ -3748,7 +3871,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;
@@ -3758,27 +3883,29 @@ 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);
}
/*
- // NOTE: Big Mallet Approach -- any layout transition causes a full barrier
+ // NOTE: Big Mallet Approach -- any layout transition causes a full barrier.
if (reference.layout != description.initialLayout) {
- // NOTE: this should be smarter based on the texture's knowledge of its previous role
+ // NOTE: This should be smarter based on the texture's knowledge of its previous role.
dependency_from_external.srcStageMask |= VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
dependency_from_external.srcAccessMask |= VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
}
if (reference.layout != description.finalLayout) {
- // NOTE: this should be smarter based on the texture's knowledge of its subsequent role
+ // NOTE: This should be smarter based on the texture's knowledge of its subsequent role.
dependency_to_external.dstStageMask |= VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
dependency_to_external.dstAccessMask |= VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
}
*/
}
- 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();
@@ -3795,13 +3922,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!
@@ -3810,7 +3945,7 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
// Make sure we limit this to the number of views we support.
ERR_FAIL_COND_V_MSG(p_view_count > capabilities.max_view_count, VK_NULL_HANDLE, "Hardware does not support requested number of views for Multiview render pass");
- // Set view masks for each subpass
+ // Set view masks for each subpass.
for (uint32_t i = 0; i < subpasses.size(); i++) {
view_masks.push_back(view_mask);
}
@@ -3828,8 +3963,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;
}
@@ -3848,7 +3983,7 @@ RenderingDevice::FramebufferFormatID RenderingDeviceVulkan::framebuffer_format_c
passes.push_back(pass);
return framebuffer_format_create_multipass(p_format, passes, p_view_count);
}
-RenderingDevice::FramebufferFormatID RenderingDeviceVulkan::framebuffer_format_create_multipass(const Vector<AttachmentFormat> &p_attachments, Vector<FramebufferPass> &p_passes, uint32_t p_view_count) {
+RenderingDevice::FramebufferFormatID RenderingDeviceVulkan::framebuffer_format_create_multipass(const Vector<AttachmentFormat> &p_attachments, const Vector<FramebufferPass> &p_passes, uint32_t p_view_count) {
_THREAD_SAFE_METHOD_
FramebufferFormatKey key;
@@ -3858,14 +3993,14 @@ RenderingDevice::FramebufferFormatID RenderingDeviceVulkan::framebuffer_format_c
const RBMap<FramebufferFormatKey, FramebufferFormatID>::Element *E = framebuffer_format_cache.find(key);
if (E) {
- //exists, return
+ // Exists, return.
return E->get();
}
Vector<TextureSamples> samples;
- VkRenderPass render_pass = _render_pass_create(p_attachments, p_passes, INITIAL_ACTION_CLEAR, FINAL_ACTION_READ, INITIAL_ACTION_CLEAR, FINAL_ACTION_READ, p_view_count, &samples); //actions don't matter for this use case
+ VkRenderPass render_pass = _render_pass_create(p_attachments, p_passes, INITIAL_ACTION_CLEAR, FINAL_ACTION_READ, INITIAL_ACTION_CLEAR, FINAL_ACTION_READ, p_view_count, &samples); // Actions don't matter for this use case.
- if (render_pass == VK_NULL_HANDLE) { //was likely invalid
+ if (render_pass == VK_NULL_HANDLE) { // Was likely invalid.
return INVALID_ID;
}
FramebufferFormatID id = FramebufferFormatID(framebuffer_format_cache.size()) | (FramebufferFormatID(ID_TYPE_FRAMEBUFFER_FORMAT) << FramebufferFormatID(ID_BASE_SHIFT));
@@ -3886,14 +4021,17 @@ RenderingDevice::FramebufferFormatID RenderingDeviceVulkan::framebuffer_format_c
const RBMap<FramebufferFormatKey, FramebufferFormatID>::Element *E = framebuffer_format_cache.find(key);
if (E) {
- //exists, return
+ // Exists, return.
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.inputAttachmentCount = 0; //unsupported for now
+ subpass.viewMask = 0;
+ subpass.inputAttachmentCount = 0; // Unsupported for now.
subpass.pInputAttachments = nullptr;
subpass.colorAttachmentCount = 0;
subpass.pColorAttachments = nullptr;
@@ -3902,8 +4040,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;
@@ -3912,13 +4050,15 @@ 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
+ if (render_pass == VK_NULL_HANDLE) { // Was likely invalid.
return INVALID_ID;
}
@@ -3954,7 +4094,11 @@ RID RenderingDeviceVulkan::framebuffer_create_empty(const Size2i &p_size, Textur
framebuffer.size = p_size;
framebuffer.view_count = 1;
- return framebuffer_owner.make_rid(framebuffer);
+ RID id = framebuffer_owner.make_rid(framebuffer);
+#ifdef DEV_ENABLED
+ set_resource_name(id, "RID:" + itos(id.get_id()));
+#endif
+ return id;
}
RID RenderingDeviceVulkan::framebuffer_create(const Vector<RID> &p_texture_attachments, FramebufferFormatID p_format_check, uint32_t p_view_count) {
@@ -3969,6 +4113,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);
}
@@ -3980,7 +4126,7 @@ RID RenderingDeviceVulkan::framebuffer_create(const Vector<RID> &p_texture_attac
return framebuffer_create_multipass(p_texture_attachments, passes, p_format_check, p_view_count);
}
-RID RenderingDeviceVulkan::framebuffer_create_multipass(const Vector<RID> &p_texture_attachments, Vector<FramebufferPass> &p_passes, FramebufferFormatID p_format_check, uint32_t p_view_count) {
+RID RenderingDeviceVulkan::framebuffer_create_multipass(const Vector<RID> &p_texture_attachments, const Vector<FramebufferPass> &p_passes, FramebufferFormatID p_format_check, uint32_t p_view_count) {
_THREAD_SAFE_METHOD_
Vector<AttachmentFormat> attachments;
@@ -3999,6 +4145,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.");
@@ -4028,6 +4178,9 @@ RID RenderingDeviceVulkan::framebuffer_create_multipass(const Vector<RID> &p_tex
framebuffer.view_count = p_view_count;
RID id = framebuffer_owner.make_rid(framebuffer);
+#ifdef DEV_ENABLED
+ set_resource_name(id, "RID:" + itos(id.get_id()));
+#endif
for (int i = 0; i < p_texture_attachments.size(); i++) {
if (p_texture_attachments[i].is_valid()) {
@@ -4047,6 +4200,22 @@ RenderingDevice::FramebufferFormatID RenderingDeviceVulkan::framebuffer_get_form
return framebuffer->format_id;
}
+bool RenderingDeviceVulkan::framebuffer_is_valid(RID p_framebuffer) const {
+ _THREAD_SAFE_METHOD_
+
+ return framebuffer_owner.owns(p_framebuffer);
+}
+
+void RenderingDeviceVulkan::framebuffer_set_invalidation_callback(RID p_framebuffer, InvalidationCallback p_callback, void *p_userdata) {
+ _THREAD_SAFE_METHOD_
+
+ Framebuffer *framebuffer = framebuffer_owner.get_or_null(p_framebuffer);
+ ERR_FAIL_COND(!framebuffer);
+
+ framebuffer->invalidated_callback = p_callback;
+ framebuffer->invalidated_callback_userdata = p_userdata;
+}
+
/*****************/
/**** SAMPLER ****/
/*****************/
@@ -4089,7 +4258,11 @@ RID RenderingDeviceVulkan::sampler_create(const SamplerState &p_state) {
VkResult res = vkCreateSampler(device, &sampler_create_info, nullptr, &sampler);
ERR_FAIL_COND_V_MSG(res, RID(), "vkCreateSampler failed with error " + itos(res) + ".");
- return sampler_owner.make_rid(sampler);
+ RID id = sampler_owner.make_rid(sampler);
+#ifdef DEV_ENABLED
+ set_resource_name(id, "RID:" + itos(id.get_id()));
+#endif
+ return id;
}
/**********************/
@@ -4118,10 +4291,14 @@ RID RenderingDeviceVulkan::vertex_buffer_create(uint32_t p_size_bytes, const Vec
_buffer_memory_barrier(buffer.buffer, 0, data_size, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, false);
}
- return vertex_buffer_owner.make_rid(buffer);
+ RID id = vertex_buffer_owner.make_rid(buffer);
+#ifdef DEV_ENABLED
+ set_resource_name(id, "RID:" + itos(id.get_id()));
+#endif
+ return id;
}
-// Internally reference counted, this ID is warranted to be unique for the same description, but needs to be freed as many times as it was allocated
+// Internally reference counted, this ID is warranted to be unique for the same description, but needs to be freed as many times as it was allocated.
RenderingDevice::VertexFormatID RenderingDeviceVulkan::vertex_format_create(const Vector<VertexAttribute> &p_vertex_formats) {
_THREAD_SAFE_METHOD_
@@ -4133,7 +4310,7 @@ RenderingDevice::VertexFormatID RenderingDeviceVulkan::vertex_format_create(cons
return *idptr;
}
- //does not exist, create one and cache it
+ // Does not exist, create one and cache it.
VertexDescriptionCache vdcache;
vdcache.bindings = memnew_arr(VkVertexInputBindingDescription, p_vertex_formats.size());
vdcache.attributes = memnew_arr(VkVertexInputAttributeDescription, p_vertex_formats.size());
@@ -4189,25 +4366,25 @@ RID RenderingDeviceVulkan::vertex_array_create(uint32_t p_vertex_count, VertexFo
vertex_array.vertex_count = p_vertex_count;
vertex_array.description = p_vertex_format;
- vertex_array.max_instances_allowed = 0xFFFFFFFF; //by default as many as you want
+ vertex_array.max_instances_allowed = 0xFFFFFFFF; // By default as many as you want.
for (int i = 0; i < p_src_buffers.size(); i++) {
Buffer *buffer = vertex_buffer_owner.get_or_null(p_src_buffers[i]);
- //validate with buffer
+ // Validate with buffer.
{
const VertexAttribute &atf = vd.vertex_formats[i];
uint32_t element_size = get_format_vertex_size(atf.format);
- ERR_FAIL_COND_V(element_size == 0, RID()); //should never happens since this was prevalidated
+ ERR_FAIL_COND_V(element_size == 0, RID()); // Should never happens since this was prevalidated.
if (atf.frequency == VERTEX_FREQUENCY_VERTEX) {
- //validate size for regular drawing
+ // Validate size for regular drawing.
uint64_t total_size = uint64_t(atf.stride) * (p_vertex_count - 1) + atf.offset + element_size;
ERR_FAIL_COND_V_MSG(total_size > buffer->size, RID(),
"Attachment (" + itos(i) + ") will read past the end of the buffer.");
} else {
- //validate size for instances drawing
+ // Validate size for instances drawing.
uint64_t available = buffer->size - atf.offset;
ERR_FAIL_COND_V_MSG(available < element_size, RID(),
"Attachment (" + itos(i) + ") uses instancing, but it's just too small.");
@@ -4218,7 +4395,7 @@ RID RenderingDeviceVulkan::vertex_array_create(uint32_t p_vertex_count, VertexFo
}
vertex_array.buffers.push_back(buffer->buffer);
- vertex_array.offsets.push_back(0); //offset unused, but passing anyway
+ vertex_array.offsets.push_back(0); // Offset unused, but passing anyway.
}
RID id = vertex_array_owner.make_rid(vertex_array);
@@ -4253,7 +4430,7 @@ RID RenderingDeviceVulkan::index_buffer_create(uint32_t p_index_count, IndexBuff
const uint16_t *index16 = (const uint16_t *)r;
for (uint32_t i = 0; i < p_index_count; i++) {
if (p_use_restart_indices && index16[i] == 0xFFFF) {
- continue; //restart index, ignore
+ continue; // Restart index, ignore.
}
index_buffer.max_index = MAX(index16[i], index_buffer.max_index);
}
@@ -4261,7 +4438,7 @@ RID RenderingDeviceVulkan::index_buffer_create(uint32_t p_index_count, IndexBuff
const uint32_t *index32 = (const uint32_t *)r;
for (uint32_t i = 0; i < p_index_count; i++) {
if (p_use_restart_indices && index32[i] == 0xFFFFFFFF) {
- continue; //restart index, ignore
+ continue; // Restart index, ignore.
}
index_buffer.max_index = MAX(index32[i], index_buffer.max_index);
}
@@ -4279,7 +4456,11 @@ RID RenderingDeviceVulkan::index_buffer_create(uint32_t p_index_count, IndexBuff
_buffer_update(&index_buffer, 0, r, data_size);
_buffer_memory_barrier(index_buffer.buffer, 0, data_size, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_INDEX_READ_BIT, false);
}
- return index_buffer_owner.make_rid(index_buffer);
+ RID id = index_buffer_owner.make_rid(index_buffer);
+#ifdef DEV_ENABLED
+ set_resource_name(id, "RID:" + itos(id.get_id()));
+#endif
+ return id;
}
RID RenderingDeviceVulkan::index_array_create(RID p_index_buffer, uint32_t p_index_offset, uint32_t p_index_count) {
@@ -4342,7 +4523,7 @@ String RenderingDeviceVulkan::_shader_uniform_debug(RID p_shader, int p_set) {
if (!ret.is_empty()) {
ret += "\n";
}
- ret += "Set: " + itos(i) + " Binding: " + itos(ui.binding) + " Type: " + shader_uniform_names[ui.type] + " Length: " + itos(ui.length);
+ ret += "Set: " + itos(i) + " Binding: " + itos(ui.binding) + " Type: " + shader_uniform_names[ui.type] + " Writable: " + (ui.writable ? "Y" : "N") + " Length: " + itos(ui.length);
}
}
return ret;
@@ -4356,7 +4537,7 @@ bool RenderingDeviceVulkan::_uniform_add_binding(Vector<Vector<VkDescriptorSetLa
case glslang::EbtSampler: {
//print_line("DEBUG: IsSampler");
if (reflection.getType()->getSampler().dim == glslang::EsdBuffer) {
- //texture buffers
+ // Texture buffers.
if (reflection.getType()->getSampler().isCombined()) {
layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
info.type = UNIFORM_TYPE_SAMPLER_WITH_TEXTURE_BUFFER;
@@ -4456,7 +4637,7 @@ bool RenderingDeviceVulkan::_uniform_add_binding(Vector<Vector<VkDescriptorSetLa
} break;*/
default: {
if (reflection.getType()->getQualifier().hasOffset() || reflection.name.find(".") != std::string::npos) {
- //member of uniform block?
+ // Member of uniform block?
return true;
}
@@ -4493,10 +4674,10 @@ bool RenderingDeviceVulkan::_uniform_add_binding(Vector<Vector<VkDescriptorSetLa
uint32_t binding = reflection.getType()->getQualifier().layoutBinding;
if (set < (uint32_t)bindings.size()) {
- //check if this already exists
+ // Check if this already exists.
for (int i = 0; i < bindings[set].size(); i++) {
if (bindings[set][i].binding == binding) {
- //already exists, verify that it's the same type
+ // Already exists, verify that it's the same type.
if (bindings[set][i].descriptorType != layout_binding.descriptorType) {
if (r_error) {
*r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name + "' trying to re-use location for set=" + itos(set) + ", binding=" + itos(binding) + " with different uniform type.";
@@ -4504,7 +4685,7 @@ bool RenderingDeviceVulkan::_uniform_add_binding(Vector<Vector<VkDescriptorSetLa
return false;
}
- //also, verify that it's the same size
+ // Also, verify that it's the same size.
if (bindings[set][i].descriptorCount != layout_binding.descriptorCount || uniform_infos[set][i].length != info.length) {
if (r_error) {
*r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name + "' trying to re-use location for set=" + itos(set) + ", binding=" + itos(binding) + " with different uniform size.";
@@ -4512,7 +4693,7 @@ bool RenderingDeviceVulkan::_uniform_add_binding(Vector<Vector<VkDescriptorSetLa
return false;
}
- //just append stage mask and return
+ // Just append stage mask and return.
bindings.write[set].write[i].stageFlags |= shader_stage_masks[p_stage];
uniform_infos.write[set].write[i].stages |= 1 << p_stage;
return true;
@@ -4521,7 +4702,7 @@ bool RenderingDeviceVulkan::_uniform_add_binding(Vector<Vector<VkDescriptorSetLa
}
layout_binding.binding = binding;
layout_binding.stageFlags = shader_stage_masks[p_stage];
- layout_binding.pImmutableSamplers = nullptr; //no support for this yet
+ layout_binding.pImmutableSamplers = nullptr; // No support for this yet.
info.stages = 1 << p_stage;
info.binding = binding;
@@ -4540,20 +4721,22 @@ bool RenderingDeviceVulkan::_uniform_add_binding(Vector<Vector<VkDescriptorSetLa
}
#endif
-//version 1: initial
-//version 2: Added shader name
+// Version 1: initial.
+// Version 2: Added shader name.
+// Version 3: Added writable.
-#define SHADER_BINARY_VERSION 2
+#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 {
uint32_t type;
uint32_t binding;
uint32_t stages;
- uint32_t length; //size of arrays (in total elements), or ubos (in bytes * total elements)
+ uint32_t length; // Size of arrays (in total elements), or ubos (in bytes * total elements).
+ uint32_t writable;
};
struct RenderingDeviceVulkanShaderBinarySpecializationConstant {
@@ -4593,7 +4776,7 @@ Vector<uint8_t> RenderingDeviceVulkan::shader_compile_binary_from_spirv(const Ve
binary_data.push_constant_size = 0;
binary_data.push_constants_vk_stage = 0;
- Vector<Vector<RenderingDeviceVulkanShaderBinaryDataBinding>> uniform_info; //set bindings
+ Vector<Vector<RenderingDeviceVulkanShaderBinaryDataBinding>> uniform_info; // Set bindings.
Vector<RenderingDeviceVulkanShaderBinarySpecializationConstant> specialization_constants;
uint32_t stages_processed = 0;
@@ -4627,7 +4810,7 @@ Vector<uint8_t> RenderingDeviceVulkan::shader_compile_binary_from_spirv(const Ve
uint32_t stage = p_spirv[i].shader_stage;
if (binding_count > 0) {
- //Parse bindings
+ // Parse bindings.
Vector<SpvReflectDescriptorBinding *> bindings;
bindings.resize(binding_count);
@@ -4643,6 +4826,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: {
@@ -4660,6 +4844,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;
@@ -4668,6 +4853,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;
@@ -4676,6 +4862,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.");
@@ -4714,6 +4901,12 @@ Vector<uint8_t> RenderingDeviceVulkan::shader_compile_binary_from_spirv(const Ve
info.length = 0;
}
+ 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;
+ }
+
info.binding = binding.binding;
uint32_t set = binding.set;
@@ -4724,26 +4917,31 @@ Vector<uint8_t> RenderingDeviceVulkan::shader_compile_binary_from_spirv(const Ve
"On shader stage '" + String(shader_stage_names[stage]) + "', uniform '" + binding.name + "' uses a set (" + itos(set) + ") index larger than what is supported by the hardware (" + itos(limits.maxBoundDescriptorSets) + ").");
if (set < (uint32_t)uniform_info.size()) {
- //check if this already exists
+ // Check if this already exists.
bool exists = false;
for (int k = 0; k < uniform_info[set].size(); k++) {
if (uniform_info[set][k].binding == (uint32_t)info.binding) {
- //already exists, verify that it's the same type
+ // Already exists, verify that it's the same type.
ERR_FAIL_COND_V_MSG(uniform_info[set][k].type != info.type, 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 type.");
- //also, verify that it's the same size
+ // Also, verify that it's the same size.
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.");
- //just append stage mask and return
+ // 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;
+ break;
}
}
if (exists) {
- continue; //merged
+ continue; // Merged.
}
}
@@ -4758,7 +4956,7 @@ Vector<uint8_t> RenderingDeviceVulkan::shader_compile_binary_from_spirv(const Ve
}
{
- //specialization constants
+ // Specialization constants.
uint32_t sc_count = 0;
result = spvReflectEnumerateSpecializationConstants(&module, &sc_count, nullptr);
@@ -4779,7 +4977,7 @@ Vector<uint8_t> RenderingDeviceVulkan::shader_compile_binary_from_spirv(const Ve
SpvReflectSpecializationConstant *spc = spec_constants[j];
sconst.constant_id = spc->constant_id;
- sconst.int_value = 0.0; // clear previous value JIC
+ sconst.int_value = 0.0; // Clear previous value JIC.
switch (spc->constant_type) {
case SPV_REFLECT_SPECIALIZATION_CONSTANT_BOOL: {
sconst.type = PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL;
@@ -4829,7 +5027,7 @@ Vector<uint8_t> RenderingDeviceVulkan::shader_compile_binary_from_spirv(const Ve
"Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "' failed obtaining input variables.");
for (uint32_t j = 0; j < iv_count; j++) {
- if (input_vars[j] && input_vars[j]->decoration_flags == 0) { //regular input
+ if (input_vars[j] && input_vars[j]->decoration_flags == 0) { // Regular input.
binary_data.vertex_input_mask |= (1 << uint32_t(input_vars[j]->location));
}
}
@@ -4898,7 +5096,7 @@ Vector<uint8_t> RenderingDeviceVulkan::shader_compile_binary_from_spirv(const Ve
Vector<Vector<uint8_t>> compressed_stages;
Vector<uint32_t> smolv_size;
- Vector<uint32_t> zstd_size; //if 0, stdno t used
+ Vector<uint32_t> zstd_size; // If 0, zstd not used.
uint32_t stages_binary_size = 0;
@@ -4910,7 +5108,7 @@ Vector<uint8_t> RenderingDeviceVulkan::shader_compile_binary_from_spirv(const Ve
ERR_FAIL_V_MSG(Vector<uint8_t>(), "Error compressing shader stage :" + String(shader_stage_names[p_spirv[i].shader_stage]));
} else {
smolv_size.push_back(smolv.size());
- { //zstd
+ { // zstd.
Vector<uint8_t> zstd;
zstd.resize(Compression::get_max_compressed_buffer_size(smolv.size(), Compression::MODE_ZSTD));
int dst_size = Compression::compress(zstd.ptrw(), &smolv[0], smolv.size(), Compression::MODE_ZSTD);
@@ -4923,7 +5121,7 @@ Vector<uint8_t> RenderingDeviceVulkan::shader_compile_binary_from_spirv(const Ve
Vector<uint8_t> smv;
smv.resize(smolv.size());
memcpy(smv.ptrw(), &smolv[0], smolv.size());
- zstd_size.push_back(0); //not using zstd
+ zstd_size.push_back(0); // Not using zstd.
compressed_stages.push_back(smv);
}
}
@@ -4943,12 +5141,12 @@ Vector<uint8_t> RenderingDeviceVulkan::shader_compile_binary_from_spirv(const Ve
binary_data.shader_name_len = shader_name_utf.length();
- uint32_t total_size = sizeof(uint32_t) * 3; //header + version + main datasize;
+ uint32_t total_size = sizeof(uint32_t) * 3; // Header + version + main datasize;.
total_size += sizeof(RenderingDeviceVulkanShaderBinaryData);
total_size += binary_data.shader_name_len;
- if ((binary_data.shader_name_len % 4) != 0) { //alignment rules are really strange
+ if ((binary_data.shader_name_len % 4) != 0) { // Alignment rules are really strange.
total_size += 4 - (binary_data.shader_name_len % 4);
}
@@ -4959,7 +5157,7 @@ Vector<uint8_t> RenderingDeviceVulkan::shader_compile_binary_from_spirv(const Ve
total_size += sizeof(RenderingDeviceVulkanShaderBinarySpecializationConstant) * specialization_constants.size();
- total_size += compressed_stages.size() * sizeof(uint32_t) * 3; //sizes
+ total_size += compressed_stages.size() * sizeof(uint32_t) * 3; // Sizes.
total_size += stages_binary_size;
Vector<uint8_t> ret;
@@ -4970,7 +5168,7 @@ Vector<uint8_t> RenderingDeviceVulkan::shader_compile_binary_from_spirv(const Ve
binptr[0] = 'G';
binptr[1] = 'V';
binptr[2] = 'B';
- binptr[3] = 'D'; //godot vulkan binary data
+ binptr[3] = 'D'; // Godot vulkan binary data.
offset += 4;
encode_uint32(SHADER_BINARY_VERSION, binptr + offset);
offset += sizeof(uint32_t);
@@ -4981,7 +5179,7 @@ Vector<uint8_t> RenderingDeviceVulkan::shader_compile_binary_from_spirv(const Ve
memcpy(binptr + offset, shader_name_utf.ptr(), binary_data.shader_name_len);
offset += binary_data.shader_name_len;
- if ((binary_data.shader_name_len % 4) != 0) { //alignment rules are really strange
+ if ((binary_data.shader_name_len % 4) != 0) { // Alignment rules are really strange.
offset += 4 - (binary_data.shader_name_len % 4);
}
@@ -5029,12 +5227,12 @@ RID RenderingDeviceVulkan::shader_create_from_bytecode(const Vector<uint8_t> &p_
uint32_t binsize = p_shader_binary.size();
uint32_t read_offset = 0;
- //consistency check
+ // Consistency check.
ERR_FAIL_COND_V(binsize < sizeof(uint32_t) * 3 + sizeof(RenderingDeviceVulkanShaderBinaryData), RID());
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);
@@ -5059,7 +5257,7 @@ RID RenderingDeviceVulkan::shader_create_from_bytecode(const Vector<uint8_t> &p_
if (binary_data.shader_name_len) {
name.parse_utf8((const char *)(binptr + read_offset), binary_data.shader_name_len);
read_offset += binary_data.shader_name_len;
- if ((binary_data.shader_name_len % 4) != 0) { //alignment rules are really strange
+ if ((binary_data.shader_name_len % 4) != 0) { // Alignment rules are really strange.
read_offset += 4 - (binary_data.shader_name_len % 4);
}
}
@@ -5081,6 +5279,7 @@ RID RenderingDeviceVulkan::shader_create_from_bytecode(const Vector<uint8_t> &p_
for (uint32_t j = 0; j < set_count; j++) {
UniformInfo info;
info.type = UniformType(set_ptr[j].type);
+ info.writable = set_ptr[j].writable;
info.length = set_ptr[j].length;
info.binding = set_ptr[j].binding;
info.stages = set_ptr[j].stages;
@@ -5175,7 +5374,7 @@ RID RenderingDeviceVulkan::shader_create_from_bytecode(const Vector<uint8_t> &p_
const uint8_t *src_smolv = nullptr;
if (zstd_size > 0) {
- //decompress to smolv
+ // Decompress to smolv.
smolv.resize(smolv_size);
int dec_smolv_size = Compression::decompress(smolv.ptrw(), smolv.size(), binptr + read_offset, zstd_size, Compression::MODE_ZSTD);
ERR_FAIL_COND_V(dec_smolv_size != (int32_t)smolv_size, RID());
@@ -5204,7 +5403,7 @@ RID RenderingDeviceVulkan::shader_create_from_bytecode(const Vector<uint8_t> &p_
ERR_FAIL_COND_V(read_offset != binsize, RID());
- //all good, let's create modules
+ // All good, let's create modules.
_THREAD_SAFE_METHOD_
@@ -5260,11 +5459,11 @@ RID RenderingDeviceVulkan::shader_create_from_bytecode(const Vector<uint8_t> &p_
shader.pipeline_stages.push_back(shader_stage);
}
- //proceed to create descriptor sets
+ // Proceed to create descriptor sets.
if (success) {
for (int i = 0; i < set_bindings.size(); i++) {
- //empty ones are fine if they were not used according to spec (binding count will be 0)
+ // Empty ones are fine if they were not used according to spec (binding count will be 0).
VkDescriptorSetLayoutCreateInfo layout_create_info;
layout_create_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
layout_create_info.pNext = nullptr;
@@ -5283,13 +5482,13 @@ RID RenderingDeviceVulkan::shader_create_from_bytecode(const Vector<uint8_t> &p_
Shader::Set set;
set.descriptor_set_layout = layout;
set.uniform_info = uniform_info[i];
- //sort and hash
+ // Sort and hash.
set.uniform_info.sort();
- uint32_t format = 0; //no format, default
+ uint32_t format = 0; // No format, default.
if (set.uniform_info.size()) {
- //has data, needs an actual format;
+ // Has data, needs an actual format.
UniformSetFormat usformat;
usformat.uniform_info = set.uniform_info;
RBMap<UniformSetFormat, uint32_t>::Element *E = uniform_set_format_cache.find(usformat);
@@ -5307,7 +5506,7 @@ RID RenderingDeviceVulkan::shader_create_from_bytecode(const Vector<uint8_t> &p_
}
if (success) {
- //create pipeline layout
+ // Create pipeline layout.
VkPipelineLayoutCreateInfo pipeline_layout_create_info;
pipeline_layout_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipeline_layout_create_info.pNext = nullptr;
@@ -5346,7 +5545,7 @@ RID RenderingDeviceVulkan::shader_create_from_bytecode(const Vector<uint8_t> &p_
}
if (!success) {
- //clean up if failed
+ // Clean up if failed.
for (int i = 0; i < shader.pipeline_stages.size(); i++) {
vkDestroyShaderModule(device, shader.pipeline_stages[i].module, nullptr);
}
@@ -5358,7 +5557,11 @@ RID RenderingDeviceVulkan::shader_create_from_bytecode(const Vector<uint8_t> &p_
ERR_FAIL_V_MSG(RID(), error_text);
}
- return shader_owner.make_rid(shader);
+ RID id = shader_owner.make_rid(shader);
+#ifdef DEV_ENABLED
+ set_resource_name(id, "RID:" + itos(id.get_id()));
+#endif
+ return id;
}
uint32_t RenderingDeviceVulkan::shader_get_vertex_input_attribute_mask(RID p_shader) {
@@ -5391,7 +5594,11 @@ RID RenderingDeviceVulkan::uniform_buffer_create(uint32_t p_size_bytes, const Ve
_buffer_update(&buffer, 0, r, data_size);
_buffer_memory_barrier(buffer.buffer, 0, data_size, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_UNIFORM_READ_BIT, false);
}
- return uniform_buffer_owner.make_rid(buffer);
+ RID id = uniform_buffer_owner.make_rid(buffer);
+#ifdef DEV_ENABLED
+ set_resource_name(id, "RID:" + itos(id.get_id()));
+#endif
+ return id;
}
RID RenderingDeviceVulkan::storage_buffer_create(uint32_t p_size_bytes, const Vector<uint8_t> &p_data, uint32_t p_usage) {
@@ -5404,7 +5611,6 @@ RID RenderingDeviceVulkan::storage_buffer_create(uint32_t p_size_bytes, const Ve
ERR_FAIL_COND_V(p_data.size() && (uint32_t)p_data.size() != p_size_bytes, RID());
Buffer buffer;
- buffer.usage = p_usage;
uint32_t flags = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
if (p_usage & STORAGE_BUFFER_USAGE_DISPATCH_INDIRECT) {
flags |= VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT;
@@ -5462,8 +5668,12 @@ RID RenderingDeviceVulkan::texture_buffer_create(uint32_t p_size_elements, DataF
ERR_FAIL_V_MSG(RID(), "Unable to create buffer view, error " + itos(res) + ".");
}
- //allocate the view
- return texture_buffer_owner.make_rid(texture_buffer);
+ // Allocate the view.
+ RID id = texture_buffer_owner.make_rid(texture_buffer);
+#ifdef DEV_ENABLED
+ set_resource_name(id, "RID:" + itos(id.get_id()));
+#endif
+ return id;
}
RenderingDeviceVulkan::DescriptorPool *RenderingDeviceVulkan::_descriptor_pool_allocate(const DescriptorPoolKey &p_key) {
@@ -5481,17 +5691,17 @@ RenderingDeviceVulkan::DescriptorPool *RenderingDeviceVulkan::_descriptor_pool_a
}
if (!pool) {
- //create a new one
+ // Create a new one.
pool = memnew(DescriptorPool);
pool->usage = 0;
VkDescriptorPoolCreateInfo descriptor_pool_create_info;
descriptor_pool_create_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
descriptor_pool_create_info.pNext = nullptr;
- descriptor_pool_create_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; // can't think how somebody may NOT need this flag..
+ descriptor_pool_create_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; // Can't think how somebody may NOT need this flag.
descriptor_pool_create_info.maxSets = max_descriptors_per_pool;
Vector<VkDescriptorPoolSize> sizes;
- //here comes more vulkan API strangeness
+ // Here comes more vulkan API strangeness.
if (p_key.uniform_type[UNIFORM_TYPE_SAMPLER]) {
VkDescriptorPoolSize s;
@@ -5591,7 +5801,7 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
ERR_FAIL_COND_V_MSG(p_shader_set >= (uint32_t)shader->sets.size() || shader->sets[p_shader_set].uniform_info.size() == 0, RID(),
"Desired set (" + itos(p_shader_set) + ") not used by shader.");
- //see that all sets in shader are satisfied
+ // See that all sets in shader are satisfied.
const Shader::Set &set = shader->sets[p_shader_set];
@@ -5604,11 +5814,11 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
Vector<VkWriteDescriptorSet> writes;
DescriptorPoolKey pool_key;
- //to keep them alive until update call
+ // To keep them alive until update call.
List<Vector<VkDescriptorBufferInfo>> buffer_infos;
List<Vector<VkBufferView>> buffer_views;
List<Vector<VkDescriptorImageInfo>> image_infos;
- //used for verification to make sure a uniform set does not use a framebuffer bound texture
+ // Used for verification to make sure a uniform set does not use a framebuffer bound texture.
LocalVector<UniformSet::AttachableTexture> attachable_textures;
Vector<Texture *> mutable_sampled_textures;
Vector<Texture *> mutable_storage_textures;
@@ -5629,14 +5839,14 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
ERR_FAIL_COND_V_MSG(uniform.uniform_type != set_uniform.type, RID(),
"Mismatch uniform type for binding (" + itos(set_uniform.binding) + "), set (" + itos(p_shader_set) + "). Expected '" + shader_uniform_names[set_uniform.type] + "', supplied: '" + shader_uniform_names[uniform.uniform_type] + "'.");
- VkWriteDescriptorSet write; //common header
+ VkWriteDescriptorSet write; // Common header.
write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
write.pNext = nullptr;
- write.dstSet = VK_NULL_HANDLE; //will assign afterwards when everything is valid
+ write.dstSet = VK_NULL_HANDLE; // Will assign afterwards when everything is valid.
write.dstBinding = set_uniform.binding;
write.dstArrayElement = 0;
write.descriptorCount = 0;
- write.descriptorType = VK_DESCRIPTOR_TYPE_MAX_ENUM; //Invalid value.
+ write.descriptorType = VK_DESCRIPTOR_TYPE_MAX_ENUM; // Invalid value.
write.pImageInfo = nullptr;
write.pBufferInfo = nullptr;
write.pTexelBufferView = nullptr;
@@ -5709,12 +5919,12 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
}
if (texture->usage_flags & TEXTURE_USAGE_STORAGE_BIT) {
- //can also be used as storage, add to mutable sampled
+ // Can also be used as storage, add to mutable sampled.
mutable_sampled_textures.push_back(texture);
}
if (texture->owner.is_valid()) {
texture = texture_owner.get_or_null(texture->owner);
- ERR_FAIL_COND_V(!texture, RID()); //bug, should never happen
+ ERR_FAIL_COND_V(!texture, RID()); // Bug, should never happen.
}
img_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
@@ -5762,13 +5972,13 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
}
if (texture->usage_flags & TEXTURE_USAGE_STORAGE_BIT) {
- //can also be used as storage, add to mutable sampled
+ // Can also be used as storage, add to mutable sampled.
mutable_sampled_textures.push_back(texture);
}
if (texture->owner.is_valid()) {
texture = texture_owner.get_or_null(texture->owner);
- ERR_FAIL_COND_V(!texture, RID()); //bug, should never happen
+ ERR_FAIL_COND_V(!texture, RID()); // Bug, should never happen.
}
img_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
@@ -5810,13 +6020,13 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
img_info.imageView = texture->view;
if (texture->usage_flags & TEXTURE_USAGE_SAMPLING_BIT) {
- //can also be used as storage, add to mutable sampled
+ // Can also be used as storage, add to mutable sampled.
mutable_storage_textures.push_back(texture);
}
if (texture->owner.is_valid()) {
texture = texture_owner.get_or_null(texture->owner);
- ERR_FAIL_COND_V(!texture, RID()); //bug, should never happen
+ ERR_FAIL_COND_V(!texture, RID()); // Bug, should never happen.
}
img_info.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
@@ -5906,7 +6116,7 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
type_size = uniform.get_id_count() / 2;
} break;
case UNIFORM_TYPE_IMAGE_BUFFER: {
- //todo
+ // Todo.
} break;
case UNIFORM_TYPE_UNIFORM_BUFFER: {
@@ -5942,7 +6152,7 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
}
ERR_FAIL_COND_V_MSG(!buffer, RID(), "Storage buffer supplied (binding: " + itos(uniform.binding) + ") is invalid.");
- //if 0, then it's sized on link time
+ // If 0, then it's sized on link time.
ERR_FAIL_COND_V_MSG(set_uniform.length > 0 && buffer->size != (uint32_t)set_uniform.length, RID(),
"Storage buffer supplied (binding: " + itos(uniform.binding) + ") size (" + itos(buffer->size) + " does not match size of shader uniform: (" + itos(set_uniform.length) + ").");
@@ -5981,7 +6191,7 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
if (texture->owner.is_valid()) {
texture = texture_owner.get_or_null(texture->owner);
- ERR_FAIL_COND_V(!texture, RID()); //bug, should never happen
+ ERR_FAIL_COND_V(!texture, RID()); // Bug, should never happen.
}
img_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
@@ -6009,7 +6219,7 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
pool_key.uniform_type[set_uniform.type] += type_size;
}
- //need a descriptor pool
+ // Need a descriptor pool.
DescriptorPool *pool = _descriptor_pool_allocate(pool_key);
ERR_FAIL_COND_V(!pool, RID());
@@ -6026,7 +6236,7 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
VkResult res = vkAllocateDescriptorSets(device, &descriptor_set_allocate_info, &descriptor_set);
if (res) {
- _descriptor_pool_free(pool_key, pool); // meh
+ _descriptor_pool_free(pool_key, pool); // Meh.
ERR_FAIL_V_MSG(RID(), "Cannot allocate descriptor sets, error " + itos(res) + ".");
}
@@ -6042,7 +6252,10 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
uniform_set.shader_id = p_shader;
RID id = uniform_set_owner.make_rid(uniform_set);
- //add dependencies
+#ifdef DEV_ENABLED
+ set_resource_name(id, "RID:" + itos(id.get_id()));
+#endif
+ // Add dependencies.
_add_dependency(id, p_shader);
for (uint32_t i = 0; i < uniform_count; i++) {
const Uniform &uniform = uniforms[i];
@@ -6052,7 +6265,7 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
}
}
- //write the contents
+ // Write the contents.
if (writes.size()) {
for (int i = 0; i < writes.size(); i++) {
writes.write[i].dstSet = descriptor_set;
@@ -6067,7 +6280,7 @@ bool RenderingDeviceVulkan::uniform_set_is_valid(RID p_uniform_set) {
return uniform_set_owner.owns(p_uniform_set);
}
-void RenderingDeviceVulkan::uniform_set_set_invalidation_callback(RID p_uniform_set, UniformSetInvalidatedCallback p_callback, void *p_userdata) {
+void RenderingDeviceVulkan::uniform_set_set_invalidation_callback(RID p_uniform_set, InvalidationCallback p_callback, void *p_userdata) {
UniformSet *us = uniform_set_owner.get_or_null(p_uniform_set);
ERR_FAIL_COND(!us);
us->invalidated_callback = p_callback;
@@ -6085,7 +6298,7 @@ Error RenderingDeviceVulkan::buffer_update(RID p_buffer, uint32_t p_offset, uint
VkPipelineStageFlags dst_stage_mask = 0;
VkAccessFlags dst_access = 0;
if (p_post_barrier & BARRIER_MASK_TRANSFER) {
- // Protect subsequent updates...
+ // Protect subsequent updates.
dst_stage_mask = VK_PIPELINE_STAGE_TRANSFER_BIT;
dst_access = VK_ACCESS_TRANSFER_WRITE_BIT;
}
@@ -6097,7 +6310,7 @@ Error RenderingDeviceVulkan::buffer_update(RID p_buffer, uint32_t p_offset, uint
ERR_FAIL_COND_V_MSG(p_offset + p_size > buffer->size, ERR_INVALID_PARAMETER,
"Attempted to write buffer (" + itos((p_offset + p_size) - buffer->size) + " bytes) past the end.");
- // no barrier should be needed here
+ // No barrier should be needed here.
// _buffer_memory_barrier(buffer->buffer, p_offset, p_size, dst_stage_mask, VK_PIPELINE_STAGE_TRANSFER_BIT, dst_access, VK_ACCESS_TRANSFER_WRITE_BIT, true);
Error err = _buffer_update(buffer, p_offset, (uint8_t *)p_data, p_size, p_post_barrier);
@@ -6133,7 +6346,7 @@ Error RenderingDeviceVulkan::buffer_clear(RID p_buffer, uint32_t p_offset, uint3
VkPipelineStageFlags dst_stage_mask = 0;
VkAccessFlags dst_access = 0;
if (p_post_barrier & BARRIER_MASK_TRANSFER) {
- // Protect subsequent updates...
+ // Protect subsequent updates.
dst_stage_mask = VK_PIPELINE_STAGE_TRANSFER_BIT;
dst_access = VK_ACCESS_TRANSFER_WRITE_BIT;
}
@@ -6146,7 +6359,7 @@ Error RenderingDeviceVulkan::buffer_clear(RID p_buffer, uint32_t p_offset, uint3
ERR_FAIL_COND_V_MSG(p_offset + p_size > buffer->size, ERR_INVALID_PARAMETER,
"Attempted to write buffer (" + itos((p_offset + p_size) - buffer->size) + " bytes) past the end.");
- // should not be needed
+ // Should not be needed.
// _buffer_memory_barrier(buffer->buffer, p_offset, p_size, dst_stage_mask, VK_PIPELINE_STAGE_TRANSFER_BIT, dst_access, VK_ACCESS_TRANSFER_WRITE_BIT, p_post_barrier);
vkCmdFillBuffer(frames[frame].draw_command_buffer, buffer->buffer, p_offset, p_size, 0);
@@ -6167,10 +6380,10 @@ Error RenderingDeviceVulkan::buffer_clear(RID p_buffer, uint32_t p_offset, uint3
Vector<uint8_t> RenderingDeviceVulkan::buffer_get_data(RID p_buffer) {
_THREAD_SAFE_METHOD_
- // It could be this buffer was just created
+ // It could be this buffer was just created.
VkPipelineShaderStageCreateFlags src_stage_mask = VK_PIPELINE_STAGE_TRANSFER_BIT;
VkAccessFlags src_access_mask = VK_ACCESS_TRANSFER_WRITE_BIT;
- // Get the vulkan buffer and the potential stage/access possible
+ // Get the vulkan buffer and the potential stage/access possible.
Buffer *buffer = _get_buffer_from_owner(p_buffer, src_stage_mask, src_access_mask, BARRIER_MASK_ALL);
if (!buffer) {
ERR_FAIL_V_MSG(Vector<uint8_t>(), "Buffer is either invalid or this type of buffer can't be retrieved. Only Index and Vertex buffers allow retrieving.");
@@ -6187,8 +6400,8 @@ Vector<uint8_t> RenderingDeviceVulkan::buffer_get_data(RID p_buffer) {
region.srcOffset = 0;
region.dstOffset = 0;
region.size = buffer->size;
- vkCmdCopyBuffer(command_buffer, buffer->buffer, tmp_buffer.buffer, 1, &region); //dst buffer is in CPU, but I wonder if src buffer needs a barrier for this..
- //flush everything so memory can be safely mapped
+ vkCmdCopyBuffer(command_buffer, buffer->buffer, tmp_buffer.buffer, 1, &region); // Dst buffer is in CPU, but I wonder if src buffer needs a barrier for this.
+ // Flush everything so memory can be safely mapped.
_flush(true);
void *buffer_mem;
@@ -6216,7 +6429,7 @@ Vector<uint8_t> RenderingDeviceVulkan::buffer_get_data(RID p_buffer) {
RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const PipelineRasterizationState &p_rasterization_state, const PipelineMultisampleState &p_multisample_state, const PipelineDepthStencilState &p_depth_stencil_state, const PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags, uint32_t p_for_render_pass, const Vector<PipelineSpecializationConstant> &p_specialization_constants) {
_THREAD_SAFE_METHOD_
- //needs a shader
+ // Needs a shader.
Shader *shader = shader_owner.get_or_null(p_shader);
ERR_FAIL_COND_V(!shader, RID());
@@ -6224,13 +6437,13 @@ RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferForma
"Compute shaders can't be used in render pipelines");
if (p_framebuffer_format == INVALID_ID) {
- //if nothing provided, use an empty one (no attachments)
+ // If nothing provided, use an empty one (no attachments).
p_framebuffer_format = framebuffer_format_create(Vector<AttachmentFormat>());
}
ERR_FAIL_COND_V(!framebuffer_formats.has(p_framebuffer_format), RID());
const FramebufferFormat &fb_format = framebuffer_formats[p_framebuffer_format];
- { //validate shader vs framebuffer
+ { // Validate shader vs framebuffer.
ERR_FAIL_COND_V_MSG(p_for_render_pass >= uint32_t(fb_format.E->key().passes.size()), RID(), "Render pass requested for pipeline creation (" + itos(p_for_render_pass) + ") is out of bounds");
const FramebufferPass &pass = fb_format.E->key().passes[p_for_render_pass];
@@ -6243,17 +6456,17 @@ RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferForma
ERR_FAIL_COND_V_MSG(shader->fragment_output_mask != output_mask, RID(),
"Mismatch fragment shader output mask (" + itos(shader->fragment_output_mask) + ") and framebuffer color output mask (" + itos(output_mask) + ") when binding both in render pipeline.");
}
- //vertex
+ // Vertex.
VkPipelineVertexInputStateCreateInfo pipeline_vertex_input_state_create_info;
if (p_vertex_format != INVALID_ID) {
- //uses vertices, else it does not
+ // Uses vertices, else it does not.
ERR_FAIL_COND_V(!vertex_formats.has(p_vertex_format), RID());
const VertexDescriptionCache &vd = vertex_formats[p_vertex_format];
pipeline_vertex_input_state_create_info = vd.create_info;
- //validate with inputs
+ // Validate with inputs.
for (uint32_t i = 0; i < 32; i++) {
if (!(shader->vertex_input_mask & (1UL << i))) {
continue;
@@ -6270,7 +6483,7 @@ RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferForma
}
} else {
- //does not use vertices
+ // Does not use vertices.
pipeline_vertex_input_state_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
pipeline_vertex_input_state_create_info.pNext = nullptr;
pipeline_vertex_input_state_create_info.flags = 0;
@@ -6282,7 +6495,7 @@ RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferForma
ERR_FAIL_COND_V_MSG(shader->vertex_input_mask != 0, RID(),
"Shader contains vertex inputs, but no vertex input description was provided for pipeline creation.");
}
- //input assembly
+ // Input assembly.
ERR_FAIL_INDEX_V(p_render_primitive, RENDER_PRIMITIVE_MAX, RID());
@@ -6308,7 +6521,7 @@ RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferForma
input_assembly_create_info.topology = topology_list[p_render_primitive];
input_assembly_create_info.primitiveRestartEnable = (p_render_primitive == RENDER_PRIMITIVE_TRIANGLE_STRIPS_WITH_RESTART_INDEX);
- //tessellation
+ // Tessellation.
VkPipelineTessellationStateCreateInfo tessellation_create_info;
tessellation_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
tessellation_create_info.pNext = nullptr;
@@ -6320,12 +6533,12 @@ RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferForma
viewport_state_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
viewport_state_create_info.pNext = nullptr;
viewport_state_create_info.flags = 0;
- viewport_state_create_info.viewportCount = 1; //if VR extensions are supported at some point, this will have to be customizable in the framebuffer format
+ viewport_state_create_info.viewportCount = 1; // If VR extensions are supported at some point, this will have to be customizable in the framebuffer format.
viewport_state_create_info.pViewports = nullptr;
viewport_state_create_info.scissorCount = 1;
viewport_state_create_info.pScissors = nullptr;
- //rasterization
+ // Rasterization.
VkPipelineRasterizationStateCreateInfo rasterization_state_create_info;
rasterization_state_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rasterization_state_create_info.pNext = nullptr;
@@ -6348,7 +6561,7 @@ RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferForma
rasterization_state_create_info.depthBiasSlopeFactor = p_rasterization_state.depth_bias_slope_factor;
rasterization_state_create_info.lineWidth = p_rasterization_state.line_width;
- //multisample
+ // Multisample.
VkPipelineMultisampleStateCreateInfo multisample_state_create_info;
multisample_state_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
multisample_state_create_info.pNext = nullptr;
@@ -6359,7 +6572,7 @@ RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferForma
multisample_state_create_info.minSampleShading = p_multisample_state.min_sample_shading;
Vector<VkSampleMask> sample_mask;
if (p_multisample_state.sample_mask.size()) {
- //use sample mask
+ // Use sample mask.
const int rasterization_sample_mask_expected_size[TEXTURE_SAMPLES_MAX] = {
1, 2, 4, 8, 16, 32, 64
};
@@ -6377,7 +6590,7 @@ RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferForma
multisample_state_create_info.alphaToCoverageEnable = p_multisample_state.enable_alpha_to_coverage;
multisample_state_create_info.alphaToOneEnable = p_multisample_state.enable_alpha_to_one;
- //depth stencil
+ // Depth stencil.
VkPipelineDepthStencilStateCreateInfo depth_stencil_state_create_info;
depth_stencil_state_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
@@ -6417,7 +6630,7 @@ RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferForma
depth_stencil_state_create_info.minDepthBounds = p_depth_stencil_state.depth_range_min;
depth_stencil_state_create_info.maxDepthBounds = p_depth_stencil_state.depth_range_max;
- //blend state
+ // Blend state.
VkPipelineColorBlendStateCreateInfo color_blend_state_create_info;
color_blend_state_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
color_blend_state_create_info.pNext = nullptr;
@@ -6488,15 +6701,15 @@ RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferForma
color_blend_state_create_info.blendConstants[2] = p_blend_state.blend_constant.b;
color_blend_state_create_info.blendConstants[3] = p_blend_state.blend_constant.a;
- //dynamic state
+ // Dynamic state.
VkPipelineDynamicStateCreateInfo dynamic_state_create_info;
dynamic_state_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
dynamic_state_create_info.pNext = nullptr;
dynamic_state_create_info.flags = 0;
- Vector<VkDynamicState> dynamic_states; //vulkan is weird..
+ Vector<VkDynamicState> dynamic_states; // Vulkan is weird.
- dynamic_states.push_back(VK_DYNAMIC_STATE_VIEWPORT); //viewport and scissor are always dynamic
+ dynamic_states.push_back(VK_DYNAMIC_STATE_VIEWPORT); // Viewport and scissor are always dynamic.
dynamic_states.push_back(VK_DYNAMIC_STATE_SCISSOR);
if (p_dynamic_state_flags & DYNAMIC_STATE_LINE_WIDTH) {
@@ -6530,11 +6743,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();
- //finally, pipeline create info
+ 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;
@@ -6548,9 +6778,9 @@ RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferForma
specialization_info.resize(pipeline_stages.size());
specialization_map_entries.resize(pipeline_stages.size());
for (int i = 0; i < shader->specialization_constants.size(); i++) {
- //see if overridden
+ // See if overridden.
const Shader::SpecializationConstant &sc = shader->specialization_constants[i];
- data_ptr[i] = sc.constant.int_value; //just copy the 32 bits
+ data_ptr[i] = sc.constant.int_value; // Just copy the 32 bits.
for (int j = 0; j < p_specialization_constants.size(); j++) {
const PipelineSpecializationConstant &psc = p_specialization_constants[j];
@@ -6645,9 +6875,12 @@ RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferForma
};
pipeline.validation.primitive_minimum = primitive_minimum[p_render_primitive];
#endif
- //create ID to associate with this pipeline
+ // Create ID to associate with this pipeline.
RID id = render_pipeline_owner.make_rid(pipeline);
- //now add all the dependencies
+#ifdef DEV_ENABLED
+ set_resource_name(id, "RID:" + itos(id.get_id()));
+#endif
+ // Now add all the dependencies.
_add_dependency(id, p_shader);
return id;
}
@@ -6664,14 +6897,14 @@ bool RenderingDeviceVulkan::render_pipeline_is_valid(RID p_pipeline) {
RID RenderingDeviceVulkan::compute_pipeline_create(RID p_shader, const Vector<PipelineSpecializationConstant> &p_specialization_constants) {
_THREAD_SAFE_METHOD_
- //needs a shader
+ // Needs a shader.
Shader *shader = shader_owner.get_or_null(p_shader);
ERR_FAIL_COND_V(!shader, RID());
ERR_FAIL_COND_V_MSG(!shader->is_compute, RID(),
"Non-compute shaders can't be used in compute pipelines");
- //finally, pipeline create info
+ // Finally, pipeline create info.
VkComputePipelineCreateInfo compute_pipeline_create_info;
compute_pipeline_create_info.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
@@ -6691,15 +6924,15 @@ RID RenderingDeviceVulkan::compute_pipeline_create(RID p_shader, const Vector<Pi
specialization_constant_data.resize(shader->specialization_constants.size());
uint32_t *data_ptr = specialization_constant_data.ptrw();
for (int i = 0; i < shader->specialization_constants.size(); i++) {
- //see if overridden
+ // See if overridden.
const Shader::SpecializationConstant &sc = shader->specialization_constants[i];
- data_ptr[i] = sc.constant.int_value; //just copy the 32 bits
+ data_ptr[i] = sc.constant.int_value; // Just copy the 32 bits.
for (int j = 0; j < p_specialization_constants.size(); j++) {
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;
}
}
@@ -6734,9 +6967,12 @@ RID RenderingDeviceVulkan::compute_pipeline_create(RID p_shader, const Vector<Pi
pipeline.local_group_size[1] = shader->compute_local_size[1];
pipeline.local_group_size[2] = shader->compute_local_size[2];
- //create ID to associate with this pipeline
+ // Create ID to associate with this pipeline.
RID id = compute_pipeline_owner.make_rid(pipeline);
- //now add all the dependencies
+#ifdef DEV_ENABLED
+ set_resource_name(id, "RID:" + itos(id.get_id()));
+#endif
+ // Now add all the dependencies.
_add_dependency(id, p_shader);
return id;
}
@@ -6766,7 +7002,7 @@ RenderingDevice::FramebufferFormatID RenderingDeviceVulkan::screen_get_framebuff
_THREAD_SAFE_METHOD_
ERR_FAIL_COND_V_MSG(local_device.is_valid(), INVALID_ID, "Local devices have no screen");
- //very hacky, but not used often per frame so I guess ok
+ // Very hacky, but not used often per frame so I guess ok.
VkFormat vkformat = context->get_screen_format();
DataFormat format = DATA_FORMAT_MAX;
for (int i = 0; i < DATA_FORMAT_MAX; i++) {
@@ -6868,7 +7104,7 @@ Error RenderingDeviceVulkan::_draw_list_setup_framebuffer(Framebuffer *p_framebu
vk.view_count = p_framebuffer->view_count;
if (!p_framebuffer->framebuffers.has(vk)) {
- //need to create this version
+ // Need to create this version.
Framebuffer::Version version;
version.render_pass = _render_pass_create(framebuffer_formats[p_framebuffer->format_id].E->key().attachments, framebuffer_formats[p_framebuffer->format_id].E->key().passes, p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_framebuffer->view_count);
@@ -6883,8 +7119,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();
@@ -6942,7 +7180,7 @@ Error RenderingDeviceVulkan::_draw_list_render_pass_begin(Framebuffer *framebuff
}
if (color_index < p_clear_colors.size() && texture->usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
- ERR_FAIL_INDEX_V(color_index, p_clear_colors.size(), ERR_BUG); //a bug
+ ERR_FAIL_INDEX_V(color_index, p_clear_colors.size(), ERR_BUG); // A bug.
Color clear_color = p_clear_colors[color_index];
clear_value.color.float32[0] = clear_color.r;
clear_value.color.float32[1] = clear_color.g;
@@ -6973,7 +7211,7 @@ Error RenderingDeviceVulkan::_draw_list_render_pass_begin(Framebuffer *framebuff
ERR_CONTINUE_MSG(!(texture->usage_flags & TEXTURE_USAGE_STORAGE_BIT), "Supplied storage texture " + itos(i) + " for draw list is not set to be used for storage.");
if (texture->usage_flags & TEXTURE_USAGE_SAMPLING_BIT) {
- //must change layout to general
+ // Must change layout to general.
VkImageMemoryBarrier image_memory_barrier;
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
image_memory_barrier.pNext = nullptr;
@@ -7001,7 +7239,7 @@ Error RenderingDeviceVulkan::_draw_list_render_pass_begin(Framebuffer *framebuff
vkCmdBeginRenderPass(command_buffer, &render_pass_begin, subpass_contents);
- //mark textures as bound
+ // Mark textures as bound.
draw_list_bound_textures.clear();
draw_list_unbind_color_textures = p_final_color_action != FINAL_ACTION_CONTINUE;
draw_list_unbind_depth_textures = p_final_depth_action != FINAL_ACTION_CONTINUE;
@@ -7019,7 +7257,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;
@@ -7079,7 +7316,7 @@ RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_begin(RID p_framebu
bool needs_clear_color = false;
bool needs_clear_depth = false;
- if (p_region != Rect2() && p_region != Rect2(Vector2(), viewport_size)) { //check custom region
+ if (p_region != Rect2() && p_region != Rect2(Vector2(), viewport_size)) { // Check custom region.
Rect2i viewport(viewport_offset, viewport_size);
Rect2i regioni = p_region;
if (!(regioni.position.x >= viewport.position.x) && (regioni.position.y >= viewport.position.y) &&
@@ -7108,11 +7345,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++;
}
}
@@ -7169,6 +7409,9 @@ RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_begin(RID p_framebu
Error RenderingDeviceVulkan::draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, DrawListID *r_split_ids, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region, const Vector<RID> &p_storage_textures) {
_THREAD_SAFE_METHOD_
+ ERR_FAIL_COND_V_MSG(draw_list != nullptr, ERR_BUSY, "Only one draw list can be active at the same time.");
+ ERR_FAIL_COND_V_MSG(compute_list != nullptr && !compute_list->state.allow_draw_overlap, ERR_BUSY, "Only one draw/compute list can be active at the same time.");
+
ERR_FAIL_COND_V(p_splits < 1, ERR_INVALID_DECLARATION);
Framebuffer *framebuffer = framebuffer_owner.get_or_null(p_framebuffer);
@@ -7180,7 +7423,7 @@ Error RenderingDeviceVulkan::draw_list_begin_split(RID p_framebuffer, uint32_t p
bool needs_clear_color = false;
bool needs_clear_depth = false;
- if (p_region != Rect2() && p_region != Rect2(Vector2(), viewport_size)) { //check custom region
+ if (p_region != Rect2() && p_region != Rect2(Vector2(), viewport_size)) { // Check custom region.
Rect2i viewport(viewport_offset, viewport_size);
Rect2i regioni = p_region;
if (!(regioni.position.x >= viewport.position.x) && (regioni.position.y >= viewport.position.y) &&
@@ -7202,7 +7445,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++) {
@@ -7288,7 +7531,7 @@ RenderingDeviceVulkan::DrawList *RenderingDeviceVulkan::_get_draw_list_ptr(DrawL
return nullptr;
}
- uint64_t index = p_id & ((DrawListID(1) << DrawListID(ID_BASE_SHIFT)) - 1); //mask
+ uint64_t index = p_id & ((DrawListID(1) << DrawListID(ID_BASE_SHIFT)) - 1); // Mask.
if (index >= draw_list_count) {
return nullptr;
@@ -7314,7 +7557,7 @@ void RenderingDeviceVulkan::draw_list_bind_render_pipeline(DrawListID p_list, RI
#endif
if (p_render_pipeline == dl->state.pipeline) {
- return; //redundant state, return.
+ return; // Redundant state, return.
}
dl->state.pipeline = p_render_pipeline;
@@ -7323,17 +7566,17 @@ void RenderingDeviceVulkan::draw_list_bind_render_pipeline(DrawListID p_list, RI
vkCmdBindPipeline(dl->command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->pipeline);
if (dl->state.pipeline_shader != pipeline->shader) {
- // shader changed, so descriptor sets may become incompatible.
+ // Shader changed, so descriptor sets may become incompatible.
- //go through ALL sets, and unbind them (and all those above) if the format is different
+ // Go through ALL sets, and unbind them (and all those above) if the format is different.
- uint32_t pcount = pipeline->set_formats.size(); //formats count in this pipeline
+ uint32_t pcount = pipeline->set_formats.size(); // Formats count in this pipeline.
dl->state.set_count = MAX(dl->state.set_count, pcount);
- const uint32_t *pformats = pipeline->set_formats.ptr(); //pipeline set formats
+ const uint32_t *pformats = pipeline->set_formats.ptr(); // Pipeline set formats.
- bool sets_valid = true; //once invalid, all above become invalid
+ bool sets_valid = true; // Once invalid, all above become invalid.
for (uint32_t i = 0; i < pcount; i++) {
- //if a part of the format is different, invalidate it (and the rest)
+ // If a part of the format is different, invalidate it (and the rest).
if (!sets_valid || dl->state.sets[i].pipeline_expected_format != pformats[i]) {
dl->state.sets[i].bound = false;
dl->state.sets[i].pipeline_expected_format = pformats[i];
@@ -7342,11 +7585,11 @@ void RenderingDeviceVulkan::draw_list_bind_render_pipeline(DrawListID p_list, RI
}
for (uint32_t i = pcount; i < dl->state.set_count; i++) {
- //unbind the ones above (not used) if exist
+ // Unbind the ones above (not used) if exist.
dl->state.sets[i].bound = false;
}
- dl->state.set_count = pcount; //update set count
+ dl->state.set_count = pcount; // Update set count.
if (pipeline->push_constant_size) {
dl->state.pipeline_push_constant_stages = pipeline->push_constant_stages;
@@ -7359,7 +7602,7 @@ void RenderingDeviceVulkan::draw_list_bind_render_pipeline(DrawListID p_list, RI
}
#ifdef DEBUG_ENABLED
- //update render pass pipeline info
+ // Update render pass pipeline info.
dl->validation.pipeline_active = true;
dl->validation.pipeline_dynamic_state = pipeline->validation.dynamic_state;
dl->validation.pipeline_vertex_format = pipeline->validation.vertex_format;
@@ -7389,8 +7632,8 @@ void RenderingDeviceVulkan::draw_list_bind_uniform_set(DrawListID p_list, RID p_
dl->state.set_count = p_index;
}
- dl->state.sets[p_index].descriptor_set = uniform_set->descriptor_set; //update set pointer
- dl->state.sets[p_index].bound = false; //needs rebind
+ dl->state.sets[p_index].descriptor_set = uniform_set->descriptor_set; // Update set pointer.
+ dl->state.sets[p_index].bound = false; // Needs rebind.
dl->state.sets[p_index].uniform_set_format = uniform_set->format;
dl->state.sets[p_index].uniform_set = p_uniform_set;
@@ -7408,7 +7651,7 @@ void RenderingDeviceVulkan::draw_list_bind_uniform_set(DrawListID p_list, RID p_
}
#ifdef DEBUG_ENABLED
- { //validate that textures bound are not attached as framebuffer bindings
+ { // Validate that textures bound are not attached as framebuffer bindings.
uint32_t attachable_count = uniform_set->attachable_textures.size();
const UniformSet::AttachableTexture *attachable_ptr = uniform_set->attachable_textures.ptr();
uint32_t bound_count = draw_list_bound_textures.size();
@@ -7434,7 +7677,7 @@ void RenderingDeviceVulkan::draw_list_bind_vertex_array(DrawListID p_list, RID p
ERR_FAIL_COND(!vertex_array);
if (dl->state.vertex_array == p_vertex_array) {
- return; //already set
+ return; // Already set.
}
dl->state.vertex_array = p_vertex_array;
@@ -7458,7 +7701,7 @@ void RenderingDeviceVulkan::draw_list_bind_index_array(DrawListID p_list, RID p_
ERR_FAIL_COND(!index_array);
if (dl->state.index_array == p_index_array) {
- return; //already set
+ return; // Already set.
}
dl->state.index_array = p_index_array;
@@ -7510,30 +7753,30 @@ void RenderingDeviceVulkan::draw_list_draw(DrawListID p_list, bool p_use_indices
ERR_FAIL_COND_MSG(!dl->validation.pipeline_active,
"No render pipeline was set before attempting to draw.");
if (dl->validation.pipeline_vertex_format != INVALID_ID) {
- //pipeline uses vertices, validate format
+ // Pipeline uses vertices, validate format.
ERR_FAIL_COND_MSG(dl->validation.vertex_format == INVALID_ID,
"No vertex array was bound, and render pipeline expects vertices.");
- //make sure format is right
+ // Make sure format is right.
ERR_FAIL_COND_MSG(dl->validation.pipeline_vertex_format != dl->validation.vertex_format,
"The vertex format used to create the pipeline does not match the vertex format bound.");
- //make sure number of instances is valid
+ // Make sure number of instances is valid.
ERR_FAIL_COND_MSG(p_instances > dl->validation.vertex_max_instances_allowed,
"Number of instances requested (" + itos(p_instances) + " is larger than the maximum number supported by the bound vertex array (" + itos(dl->validation.vertex_max_instances_allowed) + ").");
}
if (dl->validation.pipeline_push_constant_size > 0) {
- //using push constants, check that they were supplied
+ // Using push constants, check that they were supplied.
ERR_FAIL_COND_MSG(!dl->validation.pipeline_push_constant_supplied,
"The shader in this pipeline requires a push constant to be set before drawing, but it's not present.");
}
#endif
- //Bind descriptor sets
+ // Bind descriptor sets.
for (uint32_t i = 0; i < dl->state.set_count; i++) {
if (dl->state.sets[i].pipeline_expected_format == 0) {
- continue; //nothing expected by this pipeline
+ continue; // Nothing expected by this pipeline.
}
#ifdef DEBUG_ENABLED
if (dl->state.sets[i].pipeline_expected_format != dl->state.sets[i].uniform_set_format) {
@@ -7548,7 +7791,7 @@ void RenderingDeviceVulkan::draw_list_draw(DrawListID p_list, bool p_use_indices
}
#endif
if (!dl->state.sets[i].bound) {
- //All good, see if this requires re-binding
+ // All good, see if this requires re-binding.
vkCmdBindDescriptorSets(dl->command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, dl->state.pipeline_layout, i, 1, &dl->state.sets[i].descriptor_set, 0, nullptr);
dl->state.sets[i].bound = true;
}
@@ -7562,12 +7805,6 @@ void RenderingDeviceVulkan::draw_list_draw(DrawListID p_list, bool p_use_indices
ERR_FAIL_COND_MSG(!dl->validation.index_array_size,
"Draw command requested indices, but no index buffer was set.");
- if (dl->validation.pipeline_vertex_format != INVALID_ID) {
- //uses vertices, do some vertex validations
- ERR_FAIL_COND_MSG(dl->validation.vertex_array_size < dl->validation.index_array_max_index,
- "Index array references (max index: " + itos(dl->validation.index_array_max_index) + ") indices beyond the vertex array size (" + itos(dl->validation.vertex_array_size) + ").");
- }
-
ERR_FAIL_COND_MSG(dl->validation.pipeline_uses_restart_indices != dl->validation.index_buffer_uses_restart_indices,
"The usage of restart indices in index buffer does not match the render primitive in the pipeline.");
#endif
@@ -7689,7 +7926,7 @@ Error RenderingDeviceVulkan::draw_list_switch_to_next_pass_split(uint32_t p_spli
}
Error RenderingDeviceVulkan::_draw_list_allocate(const Rect2i &p_viewport, uint32_t p_splits, uint32_t p_subpass) {
- // Lock while draw_list is active
+ // Lock while draw_list is active.
_THREAD_SAFE_LOCK_
if (p_splits == 0) {
@@ -7716,7 +7953,7 @@ Error RenderingDeviceVulkan::_draw_list_allocate(const Rect2i &p_viewport, uint3
VkCommandBuffer command_buffer;
VkCommandBufferAllocateInfo cmdbuf;
- //no command buffer exists, create it.
+ // No command buffer exists, create it.
cmdbuf.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
cmdbuf.pNext = nullptr;
cmdbuf.commandPool = split_draw_list_allocators[i].command_pool;
@@ -7735,7 +7972,7 @@ Error RenderingDeviceVulkan::_draw_list_allocate(const Rect2i &p_viewport, uint3
draw_list_split = true;
for (uint32_t i = 0; i < p_splits; i++) {
- //take a command buffer and initialize it
+ // Take a command buffer and initialize it.
VkCommandBuffer command_buffer = split_draw_list_allocators[i].command_buffers[frame];
VkCommandBufferInheritanceInfo inheritance_info;
@@ -7745,7 +7982,7 @@ Error RenderingDeviceVulkan::_draw_list_allocate(const Rect2i &p_viewport, uint3
inheritance_info.subpass = p_subpass;
inheritance_info.framebuffer = draw_list_vkframebuffer;
inheritance_info.occlusionQueryEnable = false;
- inheritance_info.queryFlags = 0; //?
+ inheritance_info.queryFlags = 0; // ?
inheritance_info.pipelineStatistics = 0;
VkCommandBufferBeginInfo cmdbuf_begin;
@@ -7778,7 +8015,7 @@ Error RenderingDeviceVulkan::_draw_list_allocate(const Rect2i &p_viewport, uint3
void RenderingDeviceVulkan::_draw_list_free(Rect2i *r_last_viewport) {
if (draw_list_split) {
- //send all command buffers
+ // Send all command buffers.
VkCommandBuffer *command_buffers = (VkCommandBuffer *)alloca(sizeof(VkCommandBuffer) * draw_list_count);
for (uint32_t i = 0; i < draw_list_count; i++) {
vkEndCommandBuffer(draw_list[i].command_buffer);
@@ -7798,12 +8035,12 @@ void RenderingDeviceVulkan::_draw_list_free(Rect2i *r_last_viewport) {
if (r_last_viewport) {
*r_last_viewport = draw_list->viewport;
}
- //just end the list
+ // Just end the list.
memdelete(draw_list);
draw_list = nullptr;
}
- // draw_list is no longer active
+ // Draw_list is no longer active.
_THREAD_SAFE_UNLOCK_
}
@@ -7818,7 +8055,7 @@ void RenderingDeviceVulkan::draw_list_end(uint32_t p_post_barrier) {
for (int i = 0; i < draw_list_bound_textures.size(); i++) {
Texture *texture = texture_owner.get_or_null(draw_list_bound_textures[i]);
- ERR_CONTINUE(!texture); //wtf
+ ERR_CONTINUE(!texture); // Wtf.
if (draw_list_unbind_color_textures && (texture->usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT)) {
texture->bound = false;
}
@@ -7890,12 +8127,8 @@ void RenderingDeviceVulkan::draw_list_end(uint32_t p_post_barrier) {
draw_list_storage_textures.clear();
// To ensure proper synchronization, we must make sure rendering is done before:
- // * Some buffer is copied
- // * Another render pass happens (since we may be done)
-
-#ifdef FORCE_FULL_BARRIER
- _full_barrier(true);
-#else
+ // * Some buffer is copied.
+ // * Another render pass happens (since we may be done).
VkMemoryBarrier mem_barrier;
mem_barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
@@ -7907,6 +8140,8 @@ void RenderingDeviceVulkan::draw_list_end(uint32_t p_post_barrier) {
vkCmdPipelineBarrier(frames[frame].draw_command_buffer, src_stage, barrier_flags, 0, 1, &mem_barrier, 0, nullptr, image_barrier_count, image_barriers);
}
+#ifdef FORCE_FULL_BARRIER
+ _full_barrier(true);
#endif
}
@@ -7918,7 +8153,7 @@ RenderingDevice::ComputeListID RenderingDeviceVulkan::compute_list_begin(bool p_
ERR_FAIL_COND_V_MSG(!p_allow_draw_overlap && draw_list != nullptr, INVALID_ID, "Only one draw list can be active at the same time.");
ERR_FAIL_COND_V_MSG(compute_list != nullptr, INVALID_ID, "Only one draw/compute list can be active at the same time.");
- // Lock while compute_list is active
+ // Lock while compute_list is active.
_THREAD_SAFE_LOCK_
compute_list = memnew(ComputeList);
@@ -7938,7 +8173,7 @@ void RenderingDeviceVulkan::compute_list_bind_compute_pipeline(ComputeListID p_l
ERR_FAIL_COND(!pipeline);
if (p_compute_pipeline == cl->state.pipeline) {
- return; //redundant state, return.
+ return; // Redundant state, return.
}
cl->state.pipeline = p_compute_pipeline;
@@ -7947,17 +8182,17 @@ void RenderingDeviceVulkan::compute_list_bind_compute_pipeline(ComputeListID p_l
vkCmdBindPipeline(cl->command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline->pipeline);
if (cl->state.pipeline_shader != pipeline->shader) {
- // shader changed, so descriptor sets may become incompatible.
+ // Shader changed, so descriptor sets may become incompatible.
- //go through ALL sets, and unbind them (and all those above) if the format is different
+ // Go through ALL sets, and unbind them (and all those above) if the format is different.
- uint32_t pcount = pipeline->set_formats.size(); //formats count in this pipeline
+ uint32_t pcount = pipeline->set_formats.size(); // Formats count in this pipeline.
cl->state.set_count = MAX(cl->state.set_count, pcount);
- const uint32_t *pformats = pipeline->set_formats.ptr(); //pipeline set formats
+ const uint32_t *pformats = pipeline->set_formats.ptr(); // Pipeline set formats.
- bool sets_valid = true; //once invalid, all above become invalid
+ bool sets_valid = true; // Once invalid, all above become invalid.
for (uint32_t i = 0; i < pcount; i++) {
- //if a part of the format is different, invalidate it (and the rest)
+ // If a part of the format is different, invalidate it (and the rest).
if (!sets_valid || cl->state.sets[i].pipeline_expected_format != pformats[i]) {
cl->state.sets[i].bound = false;
cl->state.sets[i].pipeline_expected_format = pformats[i];
@@ -7966,11 +8201,11 @@ void RenderingDeviceVulkan::compute_list_bind_compute_pipeline(ComputeListID p_l
}
for (uint32_t i = pcount; i < cl->state.set_count; i++) {
- //unbind the ones above (not used) if exist
+ // Unbind the ones above (not used) if exist.
cl->state.sets[i].bound = false;
}
- cl->state.set_count = pcount; //update set count
+ cl->state.set_count = pcount; // Update set count.
if (pipeline->push_constant_size) {
cl->state.pipeline_push_constant_stages = pipeline->push_constant_stages;
@@ -7986,7 +8221,7 @@ void RenderingDeviceVulkan::compute_list_bind_compute_pipeline(ComputeListID p_l
}
#ifdef DEBUG_ENABLED
- //update compute pass pipeline info
+ // Update compute pass pipeline info.
cl->validation.pipeline_active = true;
cl->validation.pipeline_push_constant_size = pipeline->push_constant_size;
#endif
@@ -8014,8 +8249,8 @@ void RenderingDeviceVulkan::compute_list_bind_uniform_set(ComputeListID p_list,
cl->state.set_count = p_index;
}
- cl->state.sets[p_index].descriptor_set = uniform_set->descriptor_set; //update set pointer
- cl->state.sets[p_index].bound = false; //needs rebind
+ cl->state.sets[p_index].descriptor_set = uniform_set->descriptor_set; // Update set pointer.
+ cl->state.sets[p_index].bound = false; // Needs rebind.
cl->state.sets[p_index].uniform_set_format = uniform_set->format;
cl->state.sets[p_index].uniform_set = p_uniform_set;
@@ -8118,7 +8353,7 @@ void RenderingDeviceVulkan::compute_list_bind_uniform_set(ComputeListID p_list,
textures_to_storage[i]->layout = VK_IMAGE_LAYOUT_GENERAL;
- cl->state.textures_to_sampled_layout.insert(textures_to_storage[i]); //needs to go back to sampled layout afterwards
+ cl->state.textures_to_sampled_layout.insert(textures_to_storage[i]); // Needs to go back to sampled layout afterwards.
}
}
@@ -8131,7 +8366,7 @@ void RenderingDeviceVulkan::compute_list_bind_uniform_set(ComputeListID p_list,
}
#if 0
- { //validate that textures bound are not attached as framebuffer bindings
+ { // Validate that textures bound are not attached as framebuffer bindings.
uint32_t attachable_count = uniform_set->attachable_textures.size();
const RID *attachable_ptr = uniform_set->attachable_textures.ptr();
uint32_t bound_count = draw_list_bound_textures.size();
@@ -8191,18 +8426,18 @@ void RenderingDeviceVulkan::compute_list_dispatch(ComputeListID p_list, uint32_t
ERR_FAIL_COND_MSG(!cl->validation.pipeline_active, "No compute pipeline was set before attempting to draw.");
if (cl->validation.pipeline_push_constant_size > 0) {
- //using push constants, check that they were supplied
+ // Using push constants, check that they were supplied.
ERR_FAIL_COND_MSG(!cl->validation.pipeline_push_constant_supplied,
"The shader in this pipeline requires a push constant to be set before drawing, but it's not present.");
}
#endif
- //Bind descriptor sets
+ // Bind descriptor sets.
for (uint32_t i = 0; i < cl->state.set_count; i++) {
if (cl->state.sets[i].pipeline_expected_format == 0) {
- continue; //nothing expected by this pipeline
+ continue; // Nothing expected by this pipeline.
}
#ifdef DEBUG_ENABLED
if (cl->state.sets[i].pipeline_expected_format != cl->state.sets[i].uniform_set_format) {
@@ -8217,7 +8452,7 @@ void RenderingDeviceVulkan::compute_list_dispatch(ComputeListID p_list, uint32_t
}
#endif
if (!cl->state.sets[i].bound) {
- //All good, see if this requires re-binding
+ // All good, see if this requires re-binding.
vkCmdBindDescriptorSets(cl->command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, cl->state.pipeline_layout, i, 1, &cl->state.sets[i].descriptor_set, 0, nullptr);
cl->state.sets[i].bound = true;
}
@@ -8243,7 +8478,7 @@ void RenderingDeviceVulkan::compute_list_dispatch_threads(ComputeListID p_list,
ERR_FAIL_COND_MSG(!cl->validation.pipeline_active, "No compute pipeline was set before attempting to draw.");
if (cl->validation.pipeline_push_constant_size > 0) {
- //using push constants, check that they were supplied
+ // Using push constants, check that they were supplied.
ERR_FAIL_COND_MSG(!cl->validation.pipeline_push_constant_supplied,
"The shader in this pipeline requires a push constant to be set before drawing, but it's not present.");
}
@@ -8261,7 +8496,7 @@ void RenderingDeviceVulkan::compute_list_dispatch_indirect(ComputeListID p_list,
Buffer *buffer = storage_buffer_owner.get_or_null(p_buffer);
ERR_FAIL_COND(!buffer);
- ERR_FAIL_COND_MSG(!(buffer->usage & STORAGE_BUFFER_USAGE_DISPATCH_INDIRECT), "Buffer provided was not created to do indirect dispatch.");
+ ERR_FAIL_COND_MSG(!(buffer->usage & VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT), "Buffer provided was not created to do indirect dispatch.");
ERR_FAIL_COND_MSG(p_offset + 12 > buffer->size, "Offset provided (+12) is past the end of buffer.");
@@ -8274,18 +8509,18 @@ void RenderingDeviceVulkan::compute_list_dispatch_indirect(ComputeListID p_list,
ERR_FAIL_COND_MSG(!cl->validation.pipeline_active, "No compute pipeline was set before attempting to draw.");
if (cl->validation.pipeline_push_constant_size > 0) {
- //using push constants, check that they were supplied
+ // Using push constants, check that they were supplied.
ERR_FAIL_COND_MSG(!cl->validation.pipeline_push_constant_supplied,
"The shader in this pipeline requires a push constant to be set before drawing, but it's not present.");
}
#endif
- //Bind descriptor sets
+ // Bind descriptor sets.
for (uint32_t i = 0; i < cl->state.set_count; i++) {
if (cl->state.sets[i].pipeline_expected_format == 0) {
- continue; //nothing expected by this pipeline
+ continue; // Nothing expected by this pipeline.
}
#ifdef DEBUG_ENABLED
if (cl->state.sets[i].pipeline_expected_format != cl->state.sets[i].uniform_set_format) {
@@ -8300,7 +8535,7 @@ void RenderingDeviceVulkan::compute_list_dispatch_indirect(ComputeListID p_list,
}
#endif
if (!cl->state.sets[i].bound) {
- //All good, see if this requires re-binding
+ // All good, see if this requires re-binding.
vkCmdBindDescriptorSets(cl->command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, cl->state.pipeline_layout, i, 1, &cl->state.sets[i].descriptor_set, 0, nullptr);
cl->state.sets[i].bound = true;
}
@@ -8377,9 +8612,6 @@ void RenderingDeviceVulkan::compute_list_end(uint32_t p_post_barrier) {
}
}
-#ifdef FORCE_FULL_BARRIER
- _full_barrier(true);
-#else
VkMemoryBarrier mem_barrier;
mem_barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
mem_barrier.pNext = nullptr;
@@ -8390,12 +8622,14 @@ void RenderingDeviceVulkan::compute_list_end(uint32_t p_post_barrier) {
vkCmdPipelineBarrier(compute_list->command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, barrier_flags, 0, 1, &mem_barrier, 0, nullptr, image_barrier_count, image_barriers);
}
+#ifdef FORCE_FULL_BARRIER
+ _full_barrier(true);
#endif
memdelete(compute_list);
compute_list = nullptr;
- // compute_list is no longer active
+ // Compute_list is no longer active.
_THREAD_SAFE_UNLOCK_
}
@@ -8488,7 +8722,7 @@ void RenderingDeviceVulkan::draw_list_render_secondary_to_framebuffer(ID p_frame
"Draw list index (" + itos(i) + ") is created with a framebuffer format incompatible with this render pass.");
if (dl->validation.active) {
- //needs to be closed, so close it.
+ // Needs to be closed, so close it.
vkEndCommandBuffer(dl->command_buffer);
dl->validation.active = false;
}
@@ -8505,7 +8739,15 @@ void RenderingDeviceVulkan::draw_list_render_secondary_to_framebuffer(ID p_frame
#endif
void RenderingDeviceVulkan::_free_internal(RID p_id) {
- //push everything so it's disposed of next time this frame index is processed (means, it's safe to do it)
+#ifdef DEV_ENABLED
+ String resource_name;
+ if (resource_names.has(p_id)) {
+ resource_name = resource_names[p_id];
+ resource_names.erase(p_id);
+ }
+#endif
+
+ // Push everything so it's disposed of next time this frame index is processed (means, it's safe to do it).
if (texture_owner.owns(p_id)) {
Texture *texture = texture_owner.get_or_null(p_id);
frames[frame].textures_to_dispose_of.push_back(*texture);
@@ -8513,6 +8755,11 @@ void RenderingDeviceVulkan::_free_internal(RID p_id) {
} else if (framebuffer_owner.owns(p_id)) {
Framebuffer *framebuffer = framebuffer_owner.get_or_null(p_id);
frames[frame].framebuffers_to_dispose_of.push_back(*framebuffer);
+
+ if (framebuffer->invalidated_callback != nullptr) {
+ framebuffer->invalidated_callback(framebuffer->invalidated_callback_userdata);
+ }
+
framebuffer_owner.free(p_id);
} else if (sampler_owner.owns(p_id)) {
VkSampler *sampler = sampler_owner.get_or_null(p_id);
@@ -8569,30 +8816,34 @@ void RenderingDeviceVulkan::_free_internal(RID p_id) {
frames[frame].compute_pipelines_to_dispose_of.push_back(*pipeline);
compute_pipeline_owner.free(p_id);
} else {
+#ifdef DEV_ENABLED
+ ERR_PRINT("Attempted to free invalid ID: " + itos(p_id.get_id()) + " " + resource_name);
+#else
ERR_PRINT("Attempted to free invalid ID: " + itos(p_id.get_id()));
+#endif
}
}
void RenderingDeviceVulkan::free(RID p_id) {
_THREAD_SAFE_METHOD_
- _free_dependencies(p_id); //recursively erase dependencies first, to avoid potential API problems
+ _free_dependencies(p_id); // Recursively erase dependencies first, to avoid potential API problems.
_free_internal(p_id);
}
-// The full list of resources that can be named is in the VkObjectType enum
+// The full list of resources that can be named is in the VkObjectType enum.
// We just expose the resources that are owned and can be accessed easily.
void RenderingDeviceVulkan::set_resource_name(RID p_id, const String p_name) {
if (texture_owner.owns(p_id)) {
Texture *texture = texture_owner.get_or_null(p_id);
if (texture->owner.is_null()) {
- // Don't set the source texture's name when calling on a texture view
+ // Don't set the source texture's name when calling on a texture view.
context->set_object_name(VK_OBJECT_TYPE_IMAGE, uint64_t(texture->image), p_name);
}
context->set_object_name(VK_OBJECT_TYPE_IMAGE_VIEW, uint64_t(texture->view), p_name + " View");
} else if (framebuffer_owner.owns(p_id)) {
//Framebuffer *framebuffer = framebuffer_owner.get_or_null(p_id);
- // Not implemented for now as the relationship between Framebuffer and RenderPass is very complex
+ // Not implemented for now as the relationship between Framebuffer and RenderPass is very complex.
} else if (sampler_owner.owns(p_id)) {
VkSampler *sampler = sampler_owner.get_or_null(p_id);
context->set_object_name(VK_OBJECT_TYPE_SAMPLER, uint64_t(*sampler), p_name);
@@ -8631,7 +8882,11 @@ void RenderingDeviceVulkan::set_resource_name(RID p_id, const String p_name) {
context->set_object_name(VK_OBJECT_TYPE_PIPELINE_LAYOUT, uint64_t(pipeline->pipeline_layout), p_name + " Layout");
} else {
ERR_PRINT("Attempted to name invalid ID: " + itos(p_id.get_id()));
+ return;
}
+#ifdef DEV_ENABLED
+ resource_names[p_id] = p_name;
+#endif
}
void RenderingDeviceVulkan::draw_command_begin_label(String p_label_name, const Color p_color) {
@@ -8675,17 +8930,17 @@ void RenderingDeviceVulkan::_finalize_command_bufers() {
ERR_PRINT("Found open compute list at the end of the frame, this should never happen (further compute will likely not work).");
}
- { //complete the setup buffer (that needs to be processed before anything else)
+ { // Complete the setup buffer (that needs to be processed before anything else).
vkEndCommandBuffer(frames[frame].setup_command_buffer);
vkEndCommandBuffer(frames[frame].draw_command_buffer);
}
}
void RenderingDeviceVulkan::_begin_frame() {
- //erase pending resources
+ // Erase pending resources.
_free_pending_resources(frame);
- //create setup command buffer and set as the setup buffer
+ // Create setup command buffer and set as the setup buffer.
{
VkCommandBufferBeginInfo cmdbuf_begin;
@@ -8704,20 +8959,20 @@ void RenderingDeviceVulkan::_begin_frame() {
if (local_device.is_null()) {
context->append_command_buffer(frames[frame].draw_command_buffer);
- context->set_setup_buffer(frames[frame].setup_command_buffer); //append now so it's added before everything else
+ context->set_setup_buffer(frames[frame].setup_command_buffer); // Append now so it's added before everything else.
}
}
- //advance current frame
+ // Advance current frame.
frames_drawn++;
- //advance staging buffer if used
+ // Advance staging buffer if used.
if (staging_buffer_used) {
staging_buffer_current = (staging_buffer_current + 1) % staging_buffer_blocks.size();
staging_buffer_used = false;
}
if (frames[frame].timestamp_count) {
- vkGetQueryPoolResults(device, frames[frame].timestamp_pool, 0, frames[frame].timestamp_count, sizeof(uint64_t) * max_timestamp_query_elements, frames[frame].timestamp_result_values, sizeof(uint64_t), VK_QUERY_RESULT_64_BIT);
+ vkGetQueryPoolResults(device, frames[frame].timestamp_pool, 0, frames[frame].timestamp_count, sizeof(uint64_t) * max_timestamp_query_elements, frames[frame].timestamp_result_values.ptr(), sizeof(uint64_t), VK_QUERY_RESULT_64_BIT);
vkCmdResetQueryPool(frames[frame].setup_command_buffer, frames[frame].timestamp_pool, 0, frames[frame].timestamp_count);
SWAP(frames[frame].timestamp_names, frames[frame].timestamp_result_names);
SWAP(frames[frame].timestamp_cpu_values, frames[frame].timestamp_cpu_result_values);
@@ -8735,7 +8990,7 @@ void RenderingDeviceVulkan::swap_buffers() {
_finalize_command_bufers();
screen_prepared = false;
- //swap buffers
+ // Swap buffers.
context->swap_buffers();
frame = (frame + 1) % frame_count;
@@ -8781,15 +9036,15 @@ VmaPool RenderingDeviceVulkan::_find_or_create_small_allocs_pool(uint32_t p_mem_
pci.pMemoryAllocateNext = nullptr;
VmaPool pool = VK_NULL_HANDLE;
VkResult res = vmaCreatePool(allocator, &pci, &pool);
- small_allocs_pools[p_mem_type_index] = pool; // Don't try to create it again if failed the first time
+ small_allocs_pools[p_mem_type_index] = pool; // Don't try to create it again if failed the first time.
ERR_FAIL_COND_V_MSG(res, pool, "vmaCreatePool failed with error " + itos(res) + ".");
return pool;
}
void RenderingDeviceVulkan::_free_pending_resources(int p_frame) {
- //free in dependency usage order, so nothing weird happens
- //pipelines
+ // Free in dependency usage order, so nothing weird happens.
+ // Pipelines.
while (frames[p_frame].render_pipelines_to_dispose_of.front()) {
RenderPipeline *pipeline = &frames[p_frame].render_pipelines_to_dispose_of.front()->get();
@@ -8806,7 +9061,7 @@ void RenderingDeviceVulkan::_free_pending_resources(int p_frame) {
frames[p_frame].compute_pipelines_to_dispose_of.pop_front();
}
- //uniform sets
+ // Uniform sets.
while (frames[p_frame].uniform_sets_to_dispose_of.front()) {
UniformSet *uniform_set = &frames[p_frame].uniform_sets_to_dispose_of.front()->get();
@@ -8816,7 +9071,7 @@ void RenderingDeviceVulkan::_free_pending_resources(int p_frame) {
frames[p_frame].uniform_sets_to_dispose_of.pop_front();
}
- //buffer views
+ // Buffer views.
while (frames[p_frame].buffer_views_to_dispose_of.front()) {
VkBufferView buffer_view = frames[p_frame].buffer_views_to_dispose_of.front()->get();
@@ -8825,19 +9080,19 @@ void RenderingDeviceVulkan::_free_pending_resources(int p_frame) {
frames[p_frame].buffer_views_to_dispose_of.pop_front();
}
- //shaders
+ // Shaders.
while (frames[p_frame].shaders_to_dispose_of.front()) {
Shader *shader = &frames[p_frame].shaders_to_dispose_of.front()->get();
- //descriptor set layout for each set
+ // Descriptor set layout for each set.
for (int i = 0; i < shader->sets.size(); i++) {
vkDestroyDescriptorSetLayout(device, shader->sets[i].descriptor_set_layout, nullptr);
}
- //pipeline layout
+ // Pipeline layout.
vkDestroyPipelineLayout(device, shader->pipeline_layout, nullptr);
- //shaders themselves
+ // Shaders themselves.
for (int i = 0; i < shader->pipeline_stages.size(); i++) {
vkDestroyShaderModule(device, shader->pipeline_stages[i].module, nullptr);
}
@@ -8845,7 +9100,7 @@ void RenderingDeviceVulkan::_free_pending_resources(int p_frame) {
frames[p_frame].shaders_to_dispose_of.pop_front();
}
- //samplers
+ // Samplers.
while (frames[p_frame].samplers_to_dispose_of.front()) {
VkSampler sampler = frames[p_frame].samplers_to_dispose_of.front()->get();
@@ -8854,12 +9109,12 @@ void RenderingDeviceVulkan::_free_pending_resources(int p_frame) {
frames[p_frame].samplers_to_dispose_of.pop_front();
}
- //framebuffers
+ // Framebuffers.
while (frames[p_frame].framebuffers_to_dispose_of.front()) {
Framebuffer *framebuffer = &frames[p_frame].framebuffers_to_dispose_of.front()->get();
for (const KeyValue<Framebuffer::VersionKey, Framebuffer::Version> &E : framebuffer->framebuffers) {
- //first framebuffer, then render pass because it depends on it
+ // First framebuffer, then render pass because it depends on it.
vkDestroyFramebuffer(device, E.value.framebuffer, nullptr);
vkDestroyRenderPass(device, E.value.render_pass, nullptr);
}
@@ -8867,7 +9122,7 @@ void RenderingDeviceVulkan::_free_pending_resources(int p_frame) {
frames[p_frame].framebuffers_to_dispose_of.pop_front();
}
- //textures
+ // Textures.
while (frames[p_frame].textures_to_dispose_of.front()) {
Texture *texture = &frames[p_frame].textures_to_dispose_of.front()->get();
@@ -8876,14 +9131,14 @@ void RenderingDeviceVulkan::_free_pending_resources(int p_frame) {
}
vkDestroyImageView(device, texture->view, nullptr);
if (texture->owner.is_null()) {
- //actually owns the image and the allocation too
+ // Actually owns the image and the allocation too.
image_memory -= texture->allocation_info.size;
vmaDestroyImage(allocator, texture->image, texture->allocation);
}
frames[p_frame].textures_to_dispose_of.pop_front();
}
- //buffers
+ // Buffers.
while (frames[p_frame].buffers_to_dispose_of.front()) {
_buffer_free(&frames[p_frame].buffers_to_dispose_of.front()->get());
@@ -8915,9 +9170,9 @@ uint64_t RenderingDeviceVulkan::get_memory_usage(MemoryType p_type) const {
void RenderingDeviceVulkan::_flush(bool p_current_frame) {
if (local_device.is_valid() && !p_current_frame) {
- return; //flushing previous frames has no effect with local device
+ return; // Flushing previous frames has no effect with local device.
}
- //not doing this crashes RADV (undefined behavior)
+ // Not doing this crashes RADV (undefined behavior).
if (p_current_frame) {
vkEndCommandBuffer(frames[frame].setup_command_buffer);
vkEndCommandBuffer(frames[frame].draw_command_buffer);
@@ -8941,7 +9196,7 @@ void RenderingDeviceVulkan::_flush(bool p_current_frame) {
} else {
context->flush(p_current_frame, p_current_frame);
- //re-create the setup command
+ // Re-create the setup command.
if (p_current_frame) {
VkCommandBufferBeginInfo cmdbuf_begin;
cmdbuf_begin.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
@@ -8951,7 +9206,7 @@ void RenderingDeviceVulkan::_flush(bool p_current_frame) {
VkResult err = vkBeginCommandBuffer(frames[frame].setup_command_buffer, &cmdbuf_begin);
ERR_FAIL_COND_MSG(err, "vkBeginCommandBuffer failed with error " + itos(err) + ".");
- context->set_setup_buffer(frames[frame].setup_command_buffer); //append now so it's added before everything else
+ context->set_setup_buffer(frames[frame].setup_command_buffer); // Append now so it's added before everything else.
}
if (p_current_frame) {
@@ -8969,21 +9224,10 @@ void RenderingDeviceVulkan::_flush(bool p_current_frame) {
}
void RenderingDeviceVulkan::initialize(VulkanContext *p_context, bool p_local_device) {
- // get our device capabilities
+ // Get our device capabilities.
{
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;
@@ -8993,12 +9237,12 @@ void RenderingDeviceVulkan::initialize(VulkanContext *p_context, bool p_local_de
local_device = p_context->local_device_create();
device = p_context->local_device_get_vk_device(local_device);
} else {
- frame_count = p_context->get_swapchain_image_count() + 1; //always need one extra to ensure it's unused at any time, without having to use a fence for this.
+ frame_count = p_context->get_swapchain_image_count() + 1; // Always need one extra to ensure it's unused at any time, without having to use a fence for this.
}
limits = p_context->get_device_limits();
max_timestamp_query_elements = 256;
- { //initialize allocator
+ { // Initialize allocator.
VmaAllocatorCreateInfo allocatorInfo;
memset(&allocatorInfo, 0, sizeof(VmaAllocatorCreateInfo));
@@ -9008,13 +9252,13 @@ void RenderingDeviceVulkan::initialize(VulkanContext *p_context, bool p_local_de
vmaCreateAllocator(&allocatorInfo, &allocator);
}
- frames = memnew_arr(Frame, frame_count);
+ frames.resize(frame_count);
frame = 0;
- //create setup and frame buffers
+ // Create setup and frame buffers.
for (int i = 0; i < frame_count; i++) {
frames[i].index = 0;
- { //create command pool, one per frame is recommended
+ { // Create command pool, one per frame is recommended.
VkCommandPoolCreateInfo cmd_pool_info;
cmd_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
cmd_pool_info.pNext = nullptr;
@@ -9025,10 +9269,10 @@ void RenderingDeviceVulkan::initialize(VulkanContext *p_context, bool p_local_de
ERR_FAIL_COND_MSG(res, "vkCreateCommandPool failed with error " + itos(res) + ".");
}
- { //create command buffers
+ { // Create command buffers.
VkCommandBufferAllocateInfo cmdbuf;
- //no command buffer exists, create it.
+ // No command buffer exists, create it.
cmdbuf.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
cmdbuf.pNext = nullptr;
cmdbuf.commandPool = frames[i].command_pool;
@@ -9043,7 +9287,7 @@ void RenderingDeviceVulkan::initialize(VulkanContext *p_context, bool p_local_de
}
{
- //create query pool
+ // Create query pool.
VkQueryPoolCreateInfo query_pool_create_info;
query_pool_create_info.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO;
query_pool_create_info.flags = 0;
@@ -9054,19 +9298,19 @@ void RenderingDeviceVulkan::initialize(VulkanContext *p_context, bool p_local_de
vkCreateQueryPool(device, &query_pool_create_info, nullptr, &frames[i].timestamp_pool);
- frames[i].timestamp_names = memnew_arr(String, max_timestamp_query_elements);
- frames[i].timestamp_cpu_values = memnew_arr(uint64_t, max_timestamp_query_elements);
+ frames[i].timestamp_names.resize(max_timestamp_query_elements);
+ frames[i].timestamp_cpu_values.resize(max_timestamp_query_elements);
frames[i].timestamp_count = 0;
- frames[i].timestamp_result_names = memnew_arr(String, max_timestamp_query_elements);
- frames[i].timestamp_cpu_result_values = memnew_arr(uint64_t, max_timestamp_query_elements);
- frames[i].timestamp_result_values = memnew_arr(uint64_t, max_timestamp_query_elements);
+ frames[i].timestamp_result_names.resize(max_timestamp_query_elements);
+ frames[i].timestamp_cpu_result_values.resize(max_timestamp_query_elements);
+ frames[i].timestamp_result_values.resize(max_timestamp_query_elements);
frames[i].timestamp_result_count = 0;
}
}
{
- //begin the first command buffer for the first frame, so
- //setting up things can be done in the meantime until swap_buffers(), which is called before advance.
+ // Begin the first command buffer for the first frame, so
+ // setting up things can be done in the meantime until swap_buffers(), which is called before advance.
VkCommandBufferBeginInfo cmdbuf_begin;
cmdbuf_begin.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
cmdbuf_begin.pNext = nullptr;
@@ -9079,42 +9323,42 @@ void RenderingDeviceVulkan::initialize(VulkanContext *p_context, bool p_local_de
err = vkBeginCommandBuffer(frames[0].draw_command_buffer, &cmdbuf_begin);
ERR_FAIL_COND_MSG(err, "vkBeginCommandBuffer failed with error " + itos(err) + ".");
if (local_device.is_null()) {
- context->set_setup_buffer(frames[0].setup_command_buffer); //append now so it's added before everything else
+ context->set_setup_buffer(frames[0].setup_command_buffer); // Append now so it's added before everything else.
context->append_command_buffer(frames[0].draw_command_buffer);
}
}
- // Note: If adding new project settings here, also duplicate their definition in
+ // NOTE: If adding new project settings here, also duplicate their definition in
// rendering_server.cpp for headless doctool.
staging_buffer_block_size = GLOBAL_DEF("rendering/vulkan/staging_buffer/block_size_kb", 256);
staging_buffer_block_size = MAX(4u, staging_buffer_block_size);
- staging_buffer_block_size *= 1024; //kb -> bytes
+ staging_buffer_block_size *= 1024; // Kb -> bytes.
staging_buffer_max_size = GLOBAL_DEF("rendering/vulkan/staging_buffer/max_size_mb", 128);
staging_buffer_max_size = MAX(1u, staging_buffer_max_size);
staging_buffer_max_size *= 1024 * 1024;
if (staging_buffer_max_size < staging_buffer_block_size * 4) {
- //validate enough blocks
+ // Validate enough blocks.
staging_buffer_max_size = staging_buffer_block_size * 4;
}
texture_upload_region_size_px = GLOBAL_DEF("rendering/vulkan/staging_buffer/texture_upload_region_size_px", 64);
texture_upload_region_size_px = nearest_power_of_2_templated(texture_upload_region_size_px);
- frames_drawn = frame_count; //start from frame count, so everything else is immediately old
+ frames_drawn = frame_count; // Start from frame count, so everything else is immediately old.
- //ensure current staging block is valid and at least one per frame exists
+ // Ensure current staging block is valid and at least one per frame exists.
staging_buffer_current = 0;
staging_buffer_used = false;
for (int i = 0; i < frame_count; i++) {
- //staging was never used, create a block
+ // Staging was never used, create a block.
Error err = _insert_staging_block();
ERR_CONTINUE(err != OK);
}
max_descriptors_per_pool = GLOBAL_DEF("rendering/vulkan/descriptor_pools/max_descriptors_per_pool", 64);
- //check to make sure DescriptorPoolKey is good
+ // Check to make sure DescriptorPoolKey is good.
static_assert(sizeof(uint64_t) * 3 >= UNIFORM_TYPE_MAX * sizeof(uint16_t));
draw_list = nullptr;
@@ -9135,6 +9379,11 @@ void RenderingDeviceVulkan::_free_rids(T &p_owner, const char *p_type) {
WARN_PRINT(vformat("%d RIDs of type \"%s\" were leaked.", owned.size(), p_type));
}
for (const RID &E : owned) {
+#ifdef DEV_ENABLED
+ if (resource_names.has(E)) {
+ print_line(String(" - ") + resource_names[E]);
+ }
+#endif
free(E);
}
}
@@ -9144,7 +9393,7 @@ void RenderingDeviceVulkan::capture_timestamp(const String &p_name) {
ERR_FAIL_COND_MSG(draw_list != nullptr, "Capturing timestamps during draw list creation is not allowed. Offending timestamp was: " + p_name);
ERR_FAIL_COND(frames[frame].timestamp_count >= max_timestamp_query_elements);
- //this should be optional for profiling, else it will slow things down
+ // This should be optional for profiling, else it will slow things down.
{
VkMemoryBarrier memoryBarrier;
@@ -9270,7 +9519,7 @@ uint64_t RenderingDeviceVulkan::get_driver_resource(DriverResource p_resource, R
return uint64_t(render_pipeline->pipeline);
} break;
default: {
- // not supported for this driver
+ // Not supported for this driver.
return 0;
} break;
}
@@ -9307,9 +9556,9 @@ static void mult64to128(uint64_t u, uint64_t v, uint64_t &h, uint64_t &l) {
uint64_t RenderingDeviceVulkan::get_captured_timestamp_gpu_time(uint32_t p_index) const {
ERR_FAIL_UNSIGNED_INDEX_V(p_index, frames[frame].timestamp_result_count, 0);
- // this sucks because timestampPeriod multiplier is a float, while the timestamp is 64 bits nanosecs.
- // so, in cases like nvidia which give you enormous numbers and 1 as multiplier, multiplying is next to impossible
- // need to do 128 bits fixed point multiplication to get the right value
+ // This sucks because timestampPeriod multiplier is a float, while the timestamp is 64 bits nanosecs.
+ // So, in cases like nvidia which give you enormous numbers and 1 as multiplier, multiplying is next to impossible.
+ // Need to do 128 bits fixed point multiplication to get the right value.
uint64_t shift_bits = 16;
@@ -9332,7 +9581,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;
@@ -9402,7 +9651,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);
}
@@ -9411,7 +9671,7 @@ uint64_t RenderingDeviceVulkan::limit_get(Limit p_limit) {
}
void RenderingDeviceVulkan::finalize() {
- //free all resources
+ // Free all resources.
_flush(false);
@@ -9429,7 +9689,7 @@ void RenderingDeviceVulkan::finalize() {
_free_rids(framebuffer_owner, "Framebuffer");
_free_rids(sampler_owner, "Sampler");
{
- //for textures it's a bit more difficult because they may be shared
+ // For textures it's a bit more difficult because they may be shared.
List<RID> owned;
texture_owner.get_owned_list(&owned);
if (owned.size()) {
@@ -9438,40 +9698,45 @@ void RenderingDeviceVulkan::finalize() {
} else {
WARN_PRINT(vformat("%d RIDs of type \"Texture\" were leaked.", owned.size()));
}
- //free shared first
+ // Free shared first.
for (List<RID>::Element *E = owned.front(); E;) {
List<RID>::Element *N = E->next();
if (texture_is_shared(E->get())) {
+#ifdef DEV_ENABLED
+ if (resource_names.has(E->get())) {
+ print_line(String(" - ") + resource_names[E->get()]);
+ }
+#endif
free(E->get());
owned.erase(E);
}
E = N;
}
- //free non shared second, this will avoid an error trying to free unexisting textures due to dependencies.
+ // Free non shared second, this will avoid an error trying to free unexisting textures due to dependencies.
for (const RID &E : owned) {
+#ifdef DEV_ENABLED
+ if (resource_names.has(E)) {
+ print_line(String(" - ") + resource_names[E]);
+ }
+#endif
free(E);
}
}
}
- //free everything pending
+ // Free everything pending.
for (int i = 0; i < frame_count; i++) {
int f = (frame + i) % frame_count;
_free_pending_resources(f);
vkDestroyCommandPool(device, frames[i].command_pool, nullptr);
vkDestroyQueryPool(device, frames[i].timestamp_pool, nullptr);
- memdelete_arr(frames[i].timestamp_names);
- memdelete_arr(frames[i].timestamp_cpu_values);
- memdelete_arr(frames[i].timestamp_result_names);
- memdelete_arr(frames[i].timestamp_result_values);
- memdelete_arr(frames[i].timestamp_cpu_result_values);
}
for (int i = 0; i < split_draw_list_allocators.size(); i++) {
vkDestroyCommandPool(device, split_draw_list_allocators[i].command_pool, nullptr);
}
- memdelete_arr(frames);
+ frames.clear();
for (int i = 0; i < staging_buffer_blocks.size(); i++) {
vmaDestroyBuffer(allocator, staging_buffer_blocks[i].buffer, staging_buffer_blocks[i].allocation);
@@ -9495,7 +9760,7 @@ void RenderingDeviceVulkan::finalize() {
}
framebuffer_formats.clear();
- //all these should be clear at this point
+ // All these should be clear at this point.
ERR_FAIL_COND(descriptor_pools.size());
ERR_FAIL_COND(dependency_map.size());
ERR_FAIL_COND(reverse_dependency_map.size());
@@ -9507,6 +9772,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 903a39b3d0..6572de7c52 100644
--- a/drivers/vulkan/rendering_device_vulkan.h
+++ b/drivers/vulkan/rendering_device_vulkan.h
@@ -96,13 +96,13 @@ class RenderingDeviceVulkan : public RenderingDevice {
ID_TYPE_SPLIT_DRAW_LIST,
ID_TYPE_COMPUTE_LIST,
ID_TYPE_MAX,
- ID_BASE_SHIFT = 58 //5 bits for ID types
+ ID_BASE_SHIFT = 58 // 5 bits for ID types.
};
VkDevice device = VK_NULL_HANDLE;
- HashMap<RID, HashSet<RID>> dependency_map; //IDs to IDs that depend on it
- HashMap<RID, HashSet<RID>> reverse_dependency_map; //same as above, but in reverse
+ HashMap<RID, HashSet<RID>> dependency_map; // IDs to IDs that depend on it.
+ HashMap<RID, HashSet<RID>> reverse_dependency_map; // Same as above, but in reverse.
void _add_dependency(RID p_id, RID p_depends_on);
void _free_dependencies(RID p_id);
@@ -152,7 +152,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
uint32_t read_aspect_mask = 0;
uint32_t barrier_aspect_mask = 0;
- bool bound = false; //bound to framebffer
+ bool bound = false; // Bound to framebffer.
RID owner;
};
@@ -206,7 +206,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
uint64_t staging_buffer_max_size = 0;
bool staging_buffer_used = false;
- Error _staging_buffer_allocate(uint32_t p_amount, uint32_t p_required_align, uint32_t &r_alloc_offset, uint32_t &r_alloc_size, bool p_can_segment = true, bool p_on_draw_command_buffer = false);
+ Error _staging_buffer_allocate(uint32_t p_amount, uint32_t p_required_align, uint32_t &r_alloc_offset, uint32_t &r_alloc_size, bool p_can_segment = true);
Error _insert_staging_block();
struct Buffer {
@@ -214,7 +214,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
uint32_t usage = 0;
VkBuffer buffer = VK_NULL_HANDLE;
VmaAllocation allocation = nullptr;
- VkDescriptorBufferInfo buffer_info; //used for binding
+ VkDescriptorBufferInfo buffer_info; // Used for binding.
Buffer() {
}
};
@@ -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;
@@ -255,7 +256,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
const FramebufferPass *key_pass_ptr = p_key.passes.ptr();
for (uint32_t i = 0; i < pass_size; i++) {
- { //compare color attachments
+ { // Compare color attachments.
uint32_t attachment_size = pass_ptr[i].color_attachments.size();
uint32_t key_attachment_size = key_pass_ptr[i].color_attachments.size();
if (attachment_size != key_attachment_size) {
@@ -270,7 +271,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
}
}
}
- { //compare input attachments
+ { // Compare input attachments.
uint32_t attachment_size = pass_ptr[i].input_attachments.size();
uint32_t key_attachment_size = key_pass_ptr[i].input_attachments.size();
if (attachment_size != key_attachment_size) {
@@ -285,7 +286,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
}
}
}
- { //compare resolve attachments
+ { // Compare resolve attachments.
uint32_t attachment_size = pass_ptr[i].resolve_attachments.size();
uint32_t key_attachment_size = key_pass_ptr[i].resolve_attachments.size();
if (attachment_size != key_attachment_size) {
@@ -300,7 +301,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
}
}
}
- { //compare preserve attachments
+ { // Compare preserve attachments.
uint32_t attachment_size = pass_ptr[i].preserve_attachments.size();
uint32_t key_attachment_size = key_pass_ptr[i].preserve_attachments.size();
if (attachment_size != key_attachment_size) {
@@ -342,7 +343,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
}
}
- return false; //equal
+ return false; // Equal.
}
};
@@ -352,9 +353,9 @@ class RenderingDeviceVulkan : public RenderingDevice {
RBMap<FramebufferFormatKey, FramebufferFormatID> framebuffer_format_cache;
struct FramebufferFormat {
const RBMap<FramebufferFormatKey, FramebufferFormatID>::Element *E;
- VkRenderPass render_pass = VK_NULL_HANDLE; //here for constructing shaders, never used, see section (7.2. Render Pass Compatibility from Vulkan spec)
+ VkRenderPass render_pass = VK_NULL_HANDLE; // Here for constructing shaders, never used, see section (7.2. Render Pass Compatibility from Vulkan spec).
Vector<TextureSamples> pass_samples;
- uint32_t view_count = 1; // number of views
+ uint32_t view_count = 1; // Number of views.
};
HashMap<FramebufferFormatID, FramebufferFormat> framebuffer_formats;
@@ -391,10 +392,12 @@ class RenderingDeviceVulkan : public RenderingDevice {
uint32_t storage_mask = 0;
Vector<RID> texture_ids;
+ InvalidationCallback invalidated_callback = nullptr;
+ void *invalidated_callback_userdata = nullptr;
struct Version {
VkFramebuffer framebuffer = VK_NULL_HANDLE;
- VkRenderPass render_pass = VK_NULL_HANDLE; //this one is owned
+ VkRenderPass render_pass = VK_NULL_HANDLE; // This one is owned.
uint32_t subpass_count = 1;
};
@@ -451,23 +454,23 @@ class RenderingDeviceVulkan : public RenderingDevice {
return false;
}
}
- return true; //they are equal
+ return true; // They are equal.
}
}
uint32_t hash() const {
int vdc = vertex_formats.size();
- uint32_t h = hash_djb2_one_32(vdc);
+ uint32_t h = hash_murmur3_one_32(vdc);
const VertexAttribute *ptr = vertex_formats.ptr();
for (int i = 0; i < vdc; i++) {
const VertexAttribute &vd = ptr[i];
- h = hash_djb2_one_32(vd.location, h);
- h = hash_djb2_one_32(vd.offset, h);
- h = hash_djb2_one_32(vd.format, h);
- h = hash_djb2_one_32(vd.stride, h);
- h = hash_djb2_one_32(vd.frequency, h);
+ h = hash_murmur3_one_32(vd.location, h);
+ h = hash_murmur3_one_32(vd.offset, h);
+ h = hash_murmur3_one_32(vd.format, h);
+ h = hash_murmur3_one_32(vd.stride, h);
+ h = hash_murmur3_one_32(vd.frequency, h);
}
- return h;
+ return hash_fmix32(h);
}
};
@@ -496,14 +499,14 @@ class RenderingDeviceVulkan : public RenderingDevice {
int vertex_count = 0;
uint32_t max_instances_allowed = 0;
- Vector<VkBuffer> buffers; //not owned, just referenced
+ Vector<VkBuffer> buffers; // Not owned, just referenced.
Vector<VkDeviceSize> offsets;
};
RID_Owner<VertexArray, true> vertex_array_owner;
struct IndexBuffer : public Buffer {
- uint32_t max_index = 0; //used for validation
+ uint32_t max_index = 0; // Used for validation.
uint32_t index_count = 0;
VkIndexType index_type = VK_INDEX_TYPE_NONE_NV;
bool supports_restart_indices = false;
@@ -512,8 +515,8 @@ class RenderingDeviceVulkan : public RenderingDevice {
RID_Owner<IndexBuffer, true> index_buffer_owner;
struct IndexArray {
- uint32_t max_index = 0; //remember the maximum index here too, for validation
- VkBuffer buffer; //not owned, inherited from index buffer
+ uint32_t max_index = 0; // Remember the maximum index here too, for validation.
+ VkBuffer buffer; // Not owned, inherited from index buffer.
uint32_t offset = 0;
uint32_t indices = 0;
VkIndexType index_type = VK_INDEX_TYPE_NONE_NV;
@@ -544,12 +547,13 @@ class RenderingDeviceVulkan : public RenderingDevice {
struct UniformInfo {
UniformType type = UniformType::UNIFORM_TYPE_MAX;
+ bool writable = false;
int binding = 0;
uint32_t stages = 0;
- int length = 0; //size of arrays (in total elements), or ubos (in bytes * total elements)
+ int length = 0; // Size of arrays (in total elements), or ubos (in bytes * total elements).
bool operator!=(const UniformInfo &p_info) const {
- return (binding != p_info.binding || type != p_info.type || stages != p_info.stages || length != p_info.length);
+ return (binding != p_info.binding || type != p_info.type || writable != p_info.writable || stages != p_info.stages || length != p_info.length);
}
bool operator<(const UniformInfo &p_info) const {
@@ -559,6 +563,9 @@ class RenderingDeviceVulkan : public RenderingDevice {
if (type != p_info.type) {
return type < p_info.type;
}
+ if (writable != p_info.writable) {
+ return writable < p_info.writable;
+ }
if (stages != p_info.stages) {
return stages < p_info.stages;
}
@@ -615,7 +622,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
VkDescriptorSetLayout descriptor_set_layout = VK_NULL_HANDLE;
};
- uint32_t vertex_input_mask = 0; //inputs used, this is mostly for validation
+ uint32_t vertex_input_mask = 0; // Inputs used, this is mostly for validation.
uint32_t fragment_output_mask = 0;
struct PushConstant {
@@ -633,13 +640,12 @@ class RenderingDeviceVulkan : public RenderingDevice {
};
bool is_compute = false;
- int max_output = 0;
Vector<Set> sets;
Vector<uint32_t> set_formats;
Vector<VkPipelineShaderStageCreateInfo> pipeline_stages;
Vector<SpecializationConstant> specialization_constants;
VkPipelineLayout pipeline_layout = VK_NULL_HANDLE;
- String name; //used for debug
+ String name; // Used for debug.
};
String _shader_uniform_debug(RID p_shader, int p_set = -1);
@@ -711,7 +717,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
RID_Owner<Buffer, true> uniform_buffer_owner;
RID_Owner<Buffer, true> storage_buffer_owner;
- //texture buffer needs a view
+ // Texture buffer needs a view.
struct TextureBuffer {
Buffer buffer;
VkBufferView view = VK_NULL_HANDLE;
@@ -734,16 +740,16 @@ class RenderingDeviceVulkan : public RenderingDevice {
DescriptorPool *pool = nullptr;
DescriptorPoolKey pool_key;
VkDescriptorSet descriptor_set = VK_NULL_HANDLE;
- //VkPipelineLayout pipeline_layout; //not owned, inherited from shader
+ //VkPipelineLayout pipeline_layout; // Not owned, inherited from shader.
struct AttachableTexture {
uint32_t bind;
RID texture;
};
- LocalVector<AttachableTexture> attachable_textures; //used for validation
- Vector<Texture *> mutable_sampled_textures; //used for layout change
- Vector<Texture *> mutable_storage_textures; //used for layout change
- UniformSetInvalidatedCallback invalidated_callback = nullptr;
+ LocalVector<AttachableTexture> attachable_textures; // Used for validation.
+ Vector<Texture *> mutable_sampled_textures; // Used for layout change.
+ Vector<Texture *> mutable_storage_textures; // Used for layout change.
+ InvalidationCallback invalidated_callback = nullptr;
void *invalidated_callback_userdata = nullptr;
};
@@ -765,7 +771,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
// was not supplied as intended.
struct RenderPipeline {
- //Cached values for validation
+ // Cached values for validation.
#ifdef DEBUG_ENABLED
struct Validation {
FramebufferFormatID framebuffer_format = 0;
@@ -777,10 +783,10 @@ class RenderingDeviceVulkan : public RenderingDevice {
uint32_t primitive_divisor = 0;
} validation;
#endif
- //Actual pipeline
+ // Actual pipeline.
RID shader;
Vector<uint32_t> set_formats;
- VkPipelineLayout pipeline_layout = VK_NULL_HANDLE; // not owned, needed for push constants
+ VkPipelineLayout pipeline_layout = VK_NULL_HANDLE; // Not owned, needed for push constants.
VkPipeline pipeline = VK_NULL_HANDLE;
uint32_t push_constant_size = 0;
uint32_t push_constant_stages = 0;
@@ -791,7 +797,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
struct ComputePipeline {
RID shader;
Vector<uint32_t> set_formats;
- VkPipelineLayout pipeline_layout = VK_NULL_HANDLE; // not owned, needed for push constants
+ VkPipelineLayout pipeline_layout = VK_NULL_HANDLE; // Not owned, needed for push constants.
VkPipeline pipeline = VK_NULL_HANDLE;
uint32_t push_constant_size = 0;
uint32_t push_constant_stages = 0;
@@ -817,7 +823,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
struct SplitDrawListAllocator {
VkCommandPool command_pool = VK_NULL_HANDLE;
- Vector<VkCommandBuffer> command_buffers; //one for each frame
+ Vector<VkCommandBuffer> command_buffers; // One for each frame.
};
Vector<SplitDrawListAllocator> split_draw_list_allocators;
@@ -866,11 +872,9 @@ class RenderingDeviceVulkan : public RenderingDevice {
uint32_t pipeline_dynamic_state = 0;
VertexFormatID pipeline_vertex_format = INVALID_ID;
RID pipeline_shader;
- uint32_t invalid_set_from = 0;
bool pipeline_uses_restart_indices = false;
uint32_t pipeline_primitive_divisor = 0;
uint32_t pipeline_primitive_minimum = 0;
- Vector<uint32_t> pipeline_set_formats;
uint32_t pipeline_push_constant_size = 0;
bool pipeline_push_constant_supplied = false;
} validation;
@@ -944,7 +948,6 @@ class RenderingDeviceVulkan : public RenderingDevice {
bool pipeline_active = false;
RID pipeline_shader;
uint32_t invalid_set_from = 0;
- Vector<uint32_t> pipeline_set_formats;
uint32_t pipeline_push_constant_size = 0;
bool pipeline_push_constant_supplied = false;
} validation;
@@ -972,7 +975,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
// when the frame is cycled.
struct Frame {
- //list in usage order, from last to free to first to free
+ // List in usage order, from last to free to first to free.
List<Buffer> buffers_to_dispose_of;
List<Texture> textures_to_dispose_of;
List<Framebuffer> framebuffers_to_dispose_of;
@@ -984,8 +987,8 @@ class RenderingDeviceVulkan : public RenderingDevice {
List<ComputePipeline> compute_pipelines_to_dispose_of;
VkCommandPool command_pool = VK_NULL_HANDLE;
- VkCommandBuffer setup_command_buffer = VK_NULL_HANDLE; //used at the beginning of every frame for set-up
- VkCommandBuffer draw_command_buffer = VK_NULL_HANDLE; //used at the beginning of every frame for set-up
+ VkCommandBuffer setup_command_buffer = VK_NULL_HANDLE; // Used at the beginning of every frame for set-up.
+ VkCommandBuffer draw_command_buffer = VK_NULL_HANDLE; // Used at the beginning of every frame for set-up.
struct Timestamp {
String description;
@@ -994,21 +997,21 @@ class RenderingDeviceVulkan : public RenderingDevice {
VkQueryPool timestamp_pool;
- String *timestamp_names = nullptr;
- uint64_t *timestamp_cpu_values = nullptr;
+ TightLocalVector<String> timestamp_names;
+ TightLocalVector<uint64_t> timestamp_cpu_values;
uint32_t timestamp_count = 0;
- String *timestamp_result_names = nullptr;
- uint64_t *timestamp_cpu_result_values = nullptr;
- uint64_t *timestamp_result_values = nullptr;
+ TightLocalVector<String> timestamp_result_names;
+ TightLocalVector<uint64_t> timestamp_cpu_result_values;
+ TightLocalVector<uint64_t> timestamp_result_values;
uint32_t timestamp_result_count = 0;
uint64_t index = 0;
};
uint32_t max_timestamp_query_elements = 0;
- Frame *frames = nullptr; //frames available, for main device they are cycled (usually 3), for local devices only 1
- int frame = 0; //current frame
- int frame_count = 0; //total amount of frames
+ TightLocalVector<Frame> frames; // Frames available, for main device they are cycled (usually 3), for local devices only 1.
+ int frame = 0; // Current frame.
+ int frame_count = 0; // Total amount of frames.
uint64_t frames_drawn = 0;
RID local_device;
bool local_device_processing = false;
@@ -1035,6 +1038,10 @@ class RenderingDeviceVulkan : public RenderingDevice {
void _finalize_command_bufers();
void _begin_frame();
+#ifdef DEV_ENABLED
+ HashMap<RID, String> resource_names;
+#endif
+
public:
virtual RID texture_create(const TextureFormat &p_format, const TextureView &p_view, const Vector<Vector<uint8_t>> &p_data = Vector<Vector<uint8_t>>());
virtual RID texture_create_shared(const TextureView &p_view, RID p_with_texture);
@@ -1058,13 +1065,15 @@ public:
/*********************/
virtual FramebufferFormatID framebuffer_format_create(const Vector<AttachmentFormat> &p_format, uint32_t p_view_count = 1);
- virtual FramebufferFormatID framebuffer_format_create_multipass(const Vector<AttachmentFormat> &p_attachments, Vector<FramebufferPass> &p_passes, uint32_t p_view_count = 1);
+ virtual FramebufferFormatID framebuffer_format_create_multipass(const Vector<AttachmentFormat> &p_attachments, const Vector<FramebufferPass> &p_passes, uint32_t p_view_count = 1);
virtual FramebufferFormatID framebuffer_format_create_empty(TextureSamples p_samples = TEXTURE_SAMPLES_1);
virtual TextureSamples framebuffer_format_get_texture_samples(FramebufferFormatID p_format, uint32_t p_pass = 0);
virtual RID framebuffer_create(const Vector<RID> &p_texture_attachments, FramebufferFormatID p_format_check = INVALID_ID, uint32_t p_view_count = 1);
- virtual RID framebuffer_create_multipass(const Vector<RID> &p_texture_attachments, Vector<FramebufferPass> &p_passes, FramebufferFormatID p_format_check = INVALID_ID, uint32_t p_view_count = 1);
+ virtual RID framebuffer_create_multipass(const Vector<RID> &p_texture_attachments, const Vector<FramebufferPass> &p_passes, FramebufferFormatID p_format_check = INVALID_ID, uint32_t p_view_count = 1);
virtual RID framebuffer_create_empty(const Size2i &p_size, TextureSamples p_samples = TEXTURE_SAMPLES_1, FramebufferFormatID p_format_check = INVALID_ID);
+ virtual bool framebuffer_is_valid(RID p_framebuffer) const;
+ virtual void framebuffer_set_invalidation_callback(RID p_framebuffer, InvalidationCallback p_callback, void *p_userdata);
virtual FramebufferFormatID framebuffer_get_format(RID p_framebuffer);
@@ -1080,7 +1089,7 @@ public:
virtual RID vertex_buffer_create(uint32_t p_size_bytes, const Vector<uint8_t> &p_data = Vector<uint8_t>(), bool p_use_as_storage = false);
- // Internally reference counted, this ID is warranted to be unique for the same description, but needs to be freed as many times as it was allocated
+ // Internally reference counted, this ID is warranted to be unique for the same description, but needs to be freed as many times as it was allocated.
virtual VertexFormatID vertex_format_create(const Vector<VertexAttribute> &p_vertex_formats);
virtual RID vertex_array_create(uint32_t p_vertex_count, VertexFormatID p_vertex_format, const Vector<RID> &p_src_buffers);
@@ -1109,9 +1118,9 @@ public:
virtual RID uniform_set_create(const Vector<Uniform> &p_uniforms, RID p_shader, uint32_t p_shader_set);
virtual bool uniform_set_is_valid(RID p_uniform_set);
- virtual void uniform_set_set_invalidation_callback(RID p_uniform_set, UniformSetInvalidatedCallback p_callback, void *p_userdata);
+ virtual void uniform_set_set_invalidation_callback(RID p_uniform_set, InvalidationCallback p_callback, void *p_userdata);
- virtual Error buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const void *p_data, uint32_t p_post_barrier = BARRIER_MASK_ALL); //works for any buffer
+ virtual Error buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const void *p_data, uint32_t p_post_barrier = BARRIER_MASK_ALL); // Works for any buffer.
virtual Error buffer_clear(RID p_buffer, uint32_t p_offset, uint32_t p_size, uint32_t p_post_barrier = BARRIER_MASK_ALL);
virtual Vector<uint8_t> buffer_get_data(RID p_buffer);
@@ -1203,16 +1212,16 @@ 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);
void finalize();
- virtual void swap_buffers(); //for main device
+ virtual void swap_buffers(); // For main device.
- virtual void submit(); //for local device
- virtual void sync(); //for local device
+ virtual void submit(); // For local device.
+ virtual void sync(); // For local device.
virtual uint32_t get_frame_delay() const;
@@ -1234,6 +1243,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 7944057041..afc3e78372 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,17 +227,17 @@ 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" }
};
- // Clear out-arguments
+ // Clear out-arguments.
*count = 0;
if (names != nullptr) {
*names = nullptr;
@@ -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,41 +601,72 @@ 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;
subgroup_capabilities.supportedStages = subgroupProperties.supportedStages;
subgroup_capabilities.supportedOperations = subgroupProperties.supportedOperations;
// Note: quadOperationsInAllStages will be true if:
- // - supportedStages has VK_SHADER_STAGE_ALL_GRAPHICS + VK_SHADER_STAGE_COMPUTE_BIT
- // - supportedOperations has VK_SUBGROUP_FEATURE_QUAD_BIT
+ // - supportedStages has VK_SHADER_STAGE_ALL_GRAPHICS + VK_SHADER_STAGE_COMPUTE_BIT.
+ // - 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) {
@@ -673,7 +731,7 @@ Error VulkanContext::_create_instance() {
VkDebugUtilsMessengerCreateInfoEXT dbg_messenger_create_info;
VkDebugReportCallbackCreateInfoEXT dbg_report_callback_create_info{};
if (enabled_debug_utils) {
- // VK_EXT_debug_utils style
+ // VK_EXT_debug_utils style.
dbg_messenger_create_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
dbg_messenger_create_info.pNext = nullptr;
dbg_messenger_create_info.flags = 0;
@@ -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;
@@ -845,8 +902,8 @@ Error VulkanContext::_create_physical_device(VkSurfaceKHR p_surface) {
}
} else {
// TODO: At least on Linux Laptops integrated GPUs fail with Vulkan in many instances.
- // The device should really be a preference, but for now choosing a discrete GPU over the
- // integrated one is better than the default.
+ // The device should really be a preference, but for now choosing a discrete GPU over the
+ // integrated one is better than the default.
int type_selected = -1;
print_verbose("Vulkan devices:");
@@ -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,23 +1605,23 @@ 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
// and to have no tearing. It's a great default present mode to use.
- // There are times when you may wish to use another present mode. The
- // following code shows how to select them, and the comments provide some
- // reasons you may wish to use them.
+ // There are times when you may wish to use another present mode. The
+ // following code shows how to select them, and the comments provide some
+ // reasons you may wish to use them.
//
// It should be noted that Vulkan 1.0 doesn't provide a method for
- // synchronizing rendering with the presentation engine's display. There
+ // synchronizing rendering with the presentation engine's display. There
// is a method provided for throttling rendering with the display, but
// there are some presentation engines for which this method will not work.
// If an application doesn't throttle its rendering, and if it renders much
// faster than the refresh rate of the display, this can waste power on
- // mobile devices. That is because power is being spent rendering images
+ // mobile devices. That is because power is being spent rendering images
// that may never be seen.
// VK_PRESENT_MODE_IMMEDIATE_KHR is for applications that don't care about
@@ -1591,8 +1666,23 @@ Error VulkanContext::_update_swap_chain(Window *window) {
if (present_mode_available) {
window->presentMode = requested_present_mode;
} else {
- WARN_PRINT("Requested VSync mode is not available!");
- window->vsync_mode = DisplayServer::VSYNC_ENABLED; //Set to default
+ String present_mode_string;
+ switch (window->vsync_mode) {
+ case DisplayServer::VSYNC_MAILBOX:
+ present_mode_string = "Mailbox";
+ break;
+ case DisplayServer::VSYNC_ADAPTIVE:
+ present_mode_string = "Adaptive";
+ break;
+ case DisplayServer::VSYNC_ENABLED:
+ present_mode_string = "Enabled";
+ break;
+ case DisplayServer::VSYNC_DISABLED:
+ present_mode_string = "Disabled";
+ break;
+ }
+ WARN_PRINT(vformat("The requested V-Sync mode %s is not available. Falling back to V-Sync mode Enabled.", present_mode_string));
+ window->vsync_mode = DisplayServer::VSYNC_ENABLED; // Set to default.
}
print_verbose("Using present mode: " + String(string_VkPresentModeKHR(window->presentMode)));
@@ -1601,15 +1691,15 @@ 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:
+ // Application must settle for fewer images than desired.
desiredNumOfSwapchainImages = surfCapabilities.maxImageCount;
}
@@ -1620,7 +1710,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 +1757,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 +1815,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 +1829,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 +1852,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 +1863,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 +1940,7 @@ Error VulkanContext::_update_swap_chain(Window *window) {
}
}
- //reset current buffer
+ // Reset current buffer.
window->current_buffer = 0;
return OK;
@@ -1860,27 +1961,30 @@ Error VulkanContext::initialize() {
return OK;
}
-void VulkanContext::set_setup_buffer(const VkCommandBuffer &pCommandBuffer) {
- command_buffer_queue.write[0] = pCommandBuffer;
+void VulkanContext::set_setup_buffer(VkCommandBuffer p_command_buffer) {
+ command_buffer_queue.write[0] = p_command_buffer;
}
-void VulkanContext::append_command_buffer(const VkCommandBuffer &pCommandBuffer) {
+void VulkanContext::append_command_buffer(VkCommandBuffer p_command_buffer) {
if (command_buffer_queue.size() <= command_buffer_count) {
command_buffer_queue.resize(command_buffer_count + 1);
}
- command_buffer_queue.write[command_buffer_count] = pCommandBuffer;
+ command_buffer_queue.write[command_buffer_count] = p_command_buffer;
command_buffer_count++;
}
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.
- if (p_flush_setup && command_buffer_queue[0]) {
- //use a fence to wait for everything done
+ 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.
VkSubmitInfo submit_info;
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submit_info.pNext = nullptr;
@@ -1889,33 +1993,33 @@ void VulkanContext::flush(bool p_flush_setup, bool p_flush_pending) {
submit_info.pWaitSemaphores = nullptr;
submit_info.commandBufferCount = 1;
submit_info.pCommandBuffers = command_buffer_queue.ptr();
- submit_info.signalSemaphoreCount = 0;
- submit_info.pSignalSemaphores = nullptr;
+ submit_info.signalSemaphoreCount = pending_flushable ? 1 : 0;
+ submit_info.pSignalSemaphores = pending_flushable ? &draw_complete_semaphores[frame_index] : nullptr;
VkResult err = vkQueueSubmit(graphics_queue, 1, &submit_info, VK_NULL_HANDLE);
command_buffer_queue.write[0] = nullptr;
ERR_FAIL_COND(err);
- vkDeviceWaitIdle(device);
}
- if (p_flush_pending && command_buffer_count > 1) {
- //use a fence to wait for everything done
+ if (pending_flushable) {
+ // Use a fence to wait for everything to finish.
VkSubmitInfo submit_info;
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submit_info.pNext = nullptr;
- submit_info.pWaitDstStageMask = nullptr;
- submit_info.waitSemaphoreCount = 0;
- submit_info.pWaitSemaphores = nullptr;
+ VkPipelineStageFlags wait_stage_mask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
+ submit_info.pWaitDstStageMask = setup_flushable ? &wait_stage_mask : nullptr;
+ submit_info.waitSemaphoreCount = setup_flushable ? 1 : 0;
+ submit_info.pWaitSemaphores = setup_flushable ? &draw_complete_semaphores[frame_index] : nullptr;
submit_info.commandBufferCount = command_buffer_count - 1;
submit_info.pCommandBuffers = command_buffer_queue.ptr() + 1;
submit_info.signalSemaphoreCount = 0;
submit_info.pSignalSemaphores = nullptr;
VkResult err = vkQueueSubmit(graphics_queue, 1, &submit_info, VK_NULL_HANDLE);
- ERR_FAIL_COND(err);
- vkDeviceWaitIdle(device);
-
command_buffer_count = 1;
+ ERR_FAIL_COND(err);
}
+
+ vkDeviceWaitIdle(device);
}
Error VulkanContext::prepare_buffers() {
@@ -1925,7 +2029,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]);
@@ -1939,19 +2043,19 @@ Error VulkanContext::prepare_buffers() {
}
do {
- // Get the index of the next available swapchain image:
+ // Get the index of the next available swapchain image.
err =
fpAcquireNextImageKHR(device, w->swapchain, UINT64_MAX,
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
- // must be recreated:
+ // 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;
@@ -1979,7 +2083,7 @@ Error VulkanContext::swap_buffers() {
#if 0
if (VK_GOOGLE_display_timing_enabled) {
// Look at what happened to previous presents, and make appropriate
- // adjustments in timing:
+ // adjustments in timing.
DemoUpdateTargetIPD(demo);
// Note: a real application would position its geometry to that it's in
@@ -1998,7 +2102,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;
@@ -2041,7 +2145,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;
@@ -2068,7 +2172,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,
@@ -2142,7 +2246,7 @@ Error VulkanContext::swap_buffers() {
uint64_t curtime = getTimeInNanoseconds();
if (curtime == 0) {
// Since we didn't find out the current time, don't give a
- // desiredPresentTime:
+ // desiredPresentTime.
ptime.desiredPresentTime = 0;
} else {
ptime.desiredPresentTime = curtime + (target_IPD >> 1);
@@ -2173,12 +2277,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
- // must be recreated:
+ // 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 {
@@ -2223,7 +2327,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];
@@ -2244,13 +2348,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);
}
@@ -2312,7 +2416,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;
@@ -2328,7 +2432,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;
@@ -2382,12 +2486,12 @@ String VulkanContext::get_device_pipeline_cache_uuid() const {
}
DisplayServer::VSyncMode VulkanContext::get_vsync_mode(DisplayServer::WindowID p_window) const {
- ERR_FAIL_COND_V_MSG(!windows.has(p_window), DisplayServer::VSYNC_ENABLED, "Could not get VSync mode for window with WindowID " + itos(p_window) + " because it does not exist.");
+ ERR_FAIL_COND_V_MSG(!windows.has(p_window), DisplayServer::VSYNC_ENABLED, "Could not get V-Sync mode for window with WindowID " + itos(p_window) + " because it does not exist.");
return windows[p_window].vsync_mode;
}
void VulkanContext::set_vsync_mode(DisplayServer::WindowID p_window, DisplayServer::VSyncMode p_mode) {
- ERR_FAIL_COND_MSG(!windows.has(p_window), "Could not set VSync mode for window with WindowID " + itos(p_window) + " because it does not exist.");
+ ERR_FAIL_COND_MSG(!windows.has(p_window), "Could not set V-Sync mode for window with WindowID " + itos(p_window) + " because it does not exist.");
windows[p_window].vsync_mode = p_mode;
_update_swap_chain(&windows[p_window]);
}
diff --git a/drivers/vulkan/vulkan_context.h b/drivers/vulkan/vulkan_context.h
index 236e3bf35f..5cc3b515d9 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;
@@ -98,12 +107,13 @@ private:
bool device_initialized = false;
bool inst_initialized = false;
- // Vulkan 1.0 doesn't return version info so we assume this by default until we know otherwise
+ // Vulkan 1.0 doesn't return version info so we assume this by default until we know otherwise.
uint32_t vulkan_major = 1;
uint32_t vulkan_minor = 0;
uint32_t vulkan_patch = 0;
SubgroupCapabilities subgroup_capabilities;
MultiviewCapabilities multiview_capabilities;
+ VRSCapabilities vrs_capabilities;
ShaderCapabilities shader_capabilities;
StorageBufferCapabilities storage_buffer_capabilities;
@@ -117,8 +127,8 @@ private:
// Present queue.
bool queues_initialized = false;
- uint32_t graphics_queue_family_index = 0;
- uint32_t present_queue_family_index = 0;
+ uint32_t graphics_queue_family_index = UINT32_MAX;
+ uint32_t present_queue_family_index = UINT32_MAX;
bool separate_present_queue = false;
VkQueue graphics_queue = VK_NULL_HANDLE;
VkQueue present_queue = VK_NULL_HANDLE;
@@ -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();
@@ -289,8 +304,8 @@ public:
VkFormat get_screen_format() const;
VkPhysicalDeviceLimits get_device_limits() const;
- void set_setup_buffer(const VkCommandBuffer &pCommandBuffer);
- void append_command_buffer(const VkCommandBuffer &pCommandBuffer);
+ void set_setup_buffer(VkCommandBuffer p_command_buffer);
+ void append_command_buffer(VkCommandBuffer p_command_buffer);
void resize_notify();
void flush(bool p_flush_setup = false, bool p_flush_pending = false);
Error prepare_buffers();
@@ -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.cpp b/drivers/wasapi/audio_driver_wasapi.cpp
index 3a62850339..8f5e35b251 100644
--- a/drivers/wasapi/audio_driver_wasapi.cpp
+++ b/drivers/wasapi/audio_driver_wasapi.cpp
@@ -553,8 +553,8 @@ AudioDriver::SpeakerMode AudioDriverWASAPI::get_speaker_mode() const {
return get_speaker_mode_by_total_channels(channels);
}
-Array AudioDriverWASAPI::audio_device_get_list(bool p_capture) {
- Array list;
+PackedStringArray AudioDriverWASAPI::audio_device_get_list(bool p_capture) {
+ PackedStringArray list;
IMMDeviceCollection *devices = nullptr;
IMMDeviceEnumerator *enumerator = nullptr;
@@ -563,14 +563,14 @@ Array AudioDriverWASAPI::audio_device_get_list(bool p_capture) {
CoInitialize(nullptr);
HRESULT hr = CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void **)&enumerator);
- ERR_FAIL_COND_V(hr != S_OK, Array());
+ ERR_FAIL_COND_V(hr != S_OK, PackedStringArray());
hr = enumerator->EnumAudioEndpoints(p_capture ? eCapture : eRender, DEVICE_STATE_ACTIVE, &devices);
- ERR_FAIL_COND_V(hr != S_OK, Array());
+ ERR_FAIL_COND_V(hr != S_OK, PackedStringArray());
UINT count = 0;
hr = devices->GetCount(&count);
- ERR_FAIL_COND_V(hr != S_OK, Array());
+ ERR_FAIL_COND_V(hr != S_OK, PackedStringArray());
for (ULONG i = 0; i < count; i++) {
IMMDevice *device = nullptr;
@@ -600,7 +600,7 @@ Array AudioDriverWASAPI::audio_device_get_list(bool p_capture) {
return list;
}
-Array AudioDriverWASAPI::get_device_list() {
+PackedStringArray AudioDriverWASAPI::get_device_list() {
return audio_device_get_list(false);
}
@@ -950,7 +950,7 @@ void AudioDriverWASAPI::capture_set_device(const String &p_name) {
unlock();
}
-Array AudioDriverWASAPI::capture_get_device_list() {
+PackedStringArray AudioDriverWASAPI::capture_get_device_list() {
return audio_device_get_list(true);
}
diff --git a/drivers/wasapi/audio_driver_wasapi.h b/drivers/wasapi/audio_driver_wasapi.h
index 89ed90e97b..d71e2e914b 100644
--- a/drivers/wasapi/audio_driver_wasapi.h
+++ b/drivers/wasapi/audio_driver_wasapi.h
@@ -91,7 +91,7 @@ class AudioDriverWASAPI : public AudioDriver {
Error audio_device_init(AudioDeviceWASAPI *p_device, bool p_capture, bool reinit);
Error audio_device_finish(AudioDeviceWASAPI *p_device);
- Array audio_device_get_list(bool p_capture);
+ PackedStringArray audio_device_get_list(bool p_capture);
public:
virtual const char *get_name() const {
@@ -103,7 +103,7 @@ public:
virtual int get_mix_rate() const;
virtual float get_latency();
virtual SpeakerMode get_speaker_mode() const;
- virtual Array get_device_list();
+ virtual PackedStringArray get_device_list();
virtual String get_device();
virtual void set_device(String device);
virtual void lock();
@@ -112,7 +112,7 @@ public:
virtual Error capture_start();
virtual Error capture_stop();
- virtual Array capture_get_device_list();
+ virtual PackedStringArray capture_get_device_list();
virtual void capture_set_device(const String &p_name);
virtual String capture_get_device();
@@ -120,4 +120,5 @@ public:
};
#endif // WASAPI_ENABLED
+
#endif // AUDIO_DRIVER_WASAPI_H
diff --git a/drivers/windows/dir_access_windows.cpp b/drivers/windows/dir_access_windows.cpp
index 881575d245..2125709b32 100644
--- a/drivers/windows/dir_access_windows.cpp
+++ b/drivers/windows/dir_access_windows.cpp
@@ -402,6 +402,8 @@ DirAccessWindows::DirAccessWindows() {
}
DirAccessWindows::~DirAccessWindows() {
+ list_dir_end();
+
memdelete(p);
}
diff --git a/drivers/windows/dir_access_windows.h b/drivers/windows/dir_access_windows.h
index fbb07ddef8..c2835b3347 100644
--- a/drivers/windows/dir_access_windows.h
+++ b/drivers/windows/dir_access_windows.h
@@ -54,33 +54,33 @@ class DirAccessWindows : public DirAccess {
bool _cishidden = false;
public:
- virtual Error list_dir_begin(); ///< This starts dir listing
- virtual String get_next();
- virtual bool current_is_dir() const;
- virtual bool current_is_hidden() const;
- virtual void list_dir_end(); ///<
+ virtual Error list_dir_begin() override; ///< This starts dir listing
+ virtual String get_next() override;
+ virtual bool current_is_dir() const override;
+ virtual bool current_is_hidden() const override;
+ virtual void list_dir_end() override; ///<
- virtual int get_drive_count();
- virtual String get_drive(int p_drive);
+ virtual int get_drive_count() override;
+ virtual String get_drive(int p_drive) override;
- virtual Error change_dir(String p_dir); ///< can be relative or absolute, return false on success
- virtual String get_current_dir(bool p_include_drive = true) const; ///< return current dir location
+ virtual Error change_dir(String p_dir) override; ///< can be relative or absolute, return false on success
+ virtual String get_current_dir(bool p_include_drive = true) const override; ///< return current dir location
- virtual bool file_exists(String p_file);
- virtual bool dir_exists(String p_dir);
+ virtual bool file_exists(String p_file) override;
+ virtual bool dir_exists(String p_dir) override;
- virtual Error make_dir(String p_dir);
+ virtual Error make_dir(String p_dir) override;
- virtual Error rename(String p_path, String p_new_path);
- virtual Error remove(String p_path);
+ virtual Error rename(String p_path, String p_new_path) override;
+ virtual Error remove(String p_path) override;
- virtual bool is_link(String p_file) { return false; };
- virtual String read_link(String p_file) { return p_file; };
- virtual Error create_link(String p_source, String p_target) { return FAILED; };
+ virtual bool is_link(String p_file) override { return false; };
+ virtual String read_link(String p_file) override { return p_file; };
+ virtual Error create_link(String p_source, String p_target) override { return FAILED; };
- uint64_t get_space_left();
+ uint64_t get_space_left() override;
- virtual String get_filesystem_type() const;
+ virtual String get_filesystem_type() const override;
DirAccessWindows();
~DirAccessWindows();
diff --git a/drivers/windows/file_access_windows.h b/drivers/windows/file_access_windows.h
index 5d67b6ca4f..8629bb936b 100644
--- a/drivers/windows/file_access_windows.h
+++ b/drivers/windows/file_access_windows.h
@@ -51,33 +51,33 @@ class FileAccessWindows : public FileAccess {
void _close();
public:
- virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file
- virtual bool is_open() const; ///< true when file is open
+ virtual Error _open(const String &p_path, int p_mode_flags) override; ///< open a file
+ virtual bool is_open() const override; ///< true when file is open
- virtual String get_path() const; /// returns the path for the current open file
- virtual String get_path_absolute() const; /// returns the absolute path for the current open file
+ virtual String get_path() const override; /// returns the path for the current open file
+ virtual String get_path_absolute() const override; /// returns the absolute path for the current open file
- virtual void seek(uint64_t p_position); ///< seek to a given position
- virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file
- virtual uint64_t get_position() const; ///< get position in the file
- virtual uint64_t get_length() const; ///< get size of the file
+ virtual void seek(uint64_t p_position) override; ///< seek to a given position
+ virtual void seek_end(int64_t p_position = 0) override; ///< seek from the end of file
+ virtual uint64_t get_position() const override; ///< get position in the file
+ virtual uint64_t get_length() const override; ///< get size of the file
- virtual bool eof_reached() const; ///< reading passed EOF
+ virtual bool eof_reached() const override; ///< reading passed EOF
- virtual uint8_t get_8() const; ///< get a byte
- virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const;
+ virtual uint8_t get_8() const override; ///< get a byte
+ virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override;
- virtual Error get_error() const; ///< get last error
+ virtual Error get_error() const override; ///< get last error
- virtual void flush();
- virtual void store_8(uint8_t p_dest); ///< store a byte
- virtual void store_buffer(const uint8_t *p_src, uint64_t p_length); ///< store an array of bytes
+ virtual void flush() override;
+ virtual void store_8(uint8_t p_dest) override; ///< store a byte
+ virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override; ///< store an array of bytes
- virtual bool file_exists(const String &p_name); ///< return true if a file exists
+ virtual bool file_exists(const String &p_name) override; ///< return true if a file exists
- uint64_t _get_modified_time(const String &p_file);
- virtual uint32_t _get_unix_permissions(const String &p_file);
- virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions);
+ uint64_t _get_modified_time(const String &p_file) override;
+ virtual uint32_t _get_unix_permissions(const String &p_file) override;
+ virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override;
FileAccessWindows() {}
virtual ~FileAccessWindows();
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