summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/coreaudio/audio_driver_coreaudio.cpp26
-rw-r--r--drivers/gles3/SCsub1
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.cpp40
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.h6
-rw-r--r--drivers/gles3/rasterizer_gles3.cpp18
-rw-r--r--drivers/gles3/rasterizer_gles3.h9
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp1
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.h4
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.cpp1505
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.h489
-rw-r--r--drivers/gles3/shader_gles3.cpp1
-rw-r--r--drivers/gles3/shaders/scene.glsl8
-rw-r--r--drivers/gles3/storage/SCsub5
-rw-r--r--drivers/gles3/storage/canvas_texture_storage.cpp96
-rw-r--r--drivers/gles3/storage/canvas_texture_storage.h87
-rw-r--r--drivers/gles3/storage/config.cpp156
-rw-r--r--drivers/gles3/storage/config.h113
-rw-r--r--drivers/gles3/storage/render_target_storage.h132
-rw-r--r--drivers/gles3/storage/texture_storage.cpp1211
-rw-r--r--drivers/gles3/storage/texture_storage.h389
-rw-r--r--drivers/gles3/texture_loader_gles3.cpp1
-rw-r--r--drivers/png/resource_saver_png.cpp4
-rw-r--r--drivers/unix/dir_access_unix.cpp12
-rw-r--r--drivers/unix/file_access_unix.cpp9
-rw-r--r--drivers/unix/ip_unix.cpp29
-rw-r--r--drivers/unix/net_socket_posix.cpp16
-rw-r--r--drivers/unix/os_unix.cpp53
-rw-r--r--drivers/unix/os_unix.h11
-rw-r--r--drivers/unix/syslog_logger.cpp2
-rw-r--r--drivers/vulkan/SCsub3
-rw-r--r--drivers/vulkan/rendering_device_vulkan.cpp382
-rw-r--r--drivers/vulkan/rendering_device_vulkan.h5
-rw-r--r--drivers/vulkan/vulkan_context.cpp388
-rw-r--r--drivers/vulkan/vulkan_context.h10
-rw-r--r--drivers/vulkan/vulkan_hooks.h48
-rw-r--r--drivers/wasapi/audio_driver_wasapi.cpp6
-rw-r--r--drivers/windows/file_access_windows.cpp7
37 files changed, 3041 insertions, 2242 deletions
diff --git a/drivers/coreaudio/audio_driver_coreaudio.cpp b/drivers/coreaudio/audio_driver_coreaudio.cpp
index e37a53fede..e2b195350f 100644
--- a/drivers/coreaudio/audio_driver_coreaudio.cpp
+++ b/drivers/coreaudio/audio_driver_coreaudio.cpp
@@ -174,9 +174,9 @@ OSStatus AudioDriverCoreAudio::output_callback(void *inRefCon,
for (unsigned int i = 0; i < ioData->mNumberBuffers; i++) {
AudioBuffer *abuf = &ioData->mBuffers[i];
memset(abuf->mData, 0, abuf->mDataByteSize);
- };
+ }
return 0;
- };
+ }
ad->start_counting_ticks();
@@ -195,14 +195,14 @@ OSStatus AudioDriverCoreAudio::output_callback(void *inRefCon,
frames_left -= frames;
out += frames * ad->channels;
- };
- };
+ }
+ }
ad->stop_counting_ticks();
ad->unlock();
return 0;
-};
+}
OSStatus AudioDriverCoreAudio::input_callback(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
@@ -251,7 +251,7 @@ void AudioDriverCoreAudio::start() {
active = true;
}
}
-};
+}
void AudioDriverCoreAudio::stop() {
if (active) {
@@ -266,19 +266,19 @@ void AudioDriverCoreAudio::stop() {
int AudioDriverCoreAudio::get_mix_rate() const {
return mix_rate;
-};
+}
AudioDriver::SpeakerMode AudioDriverCoreAudio::get_speaker_mode() const {
return get_speaker_mode_by_total_channels(channels);
-};
+}
void AudioDriverCoreAudio::lock() {
mutex.lock();
-};
+}
void AudioDriverCoreAudio::unlock() {
mutex.unlock();
-};
+}
bool AudioDriverCoreAudio::try_lock() {
return mutex.try_lock() == OK;
@@ -521,8 +521,9 @@ Array AudioDriverCoreAudio::_get_device_list(bool capture) {
AudioObjectGetPropertyData(audioDevices[i], &prop, 0, nullptr, &size, bufferList);
UInt32 channelCount = 0;
- for (UInt32 j = 0; j < bufferList->mNumberBuffers; j++)
+ for (UInt32 j = 0; j < bufferList->mNumberBuffers; j++) {
channelCount += bufferList->mBuffers[j].mNumberChannels;
+ }
memfree(bufferList);
@@ -579,8 +580,9 @@ void AudioDriverCoreAudio::_set_device(const String &device, bool capture) {
AudioObjectGetPropertyData(audioDevices[i], &prop, 0, nullptr, &size, bufferList);
UInt32 channelCount = 0;
- for (UInt32 j = 0; j < bufferList->mNumberBuffers; j++)
+ for (UInt32 j = 0; j < bufferList->mNumberBuffers; j++) {
channelCount += bufferList->mBuffers[j].mNumberChannels;
+ }
memfree(bufferList);
diff --git a/drivers/gles3/SCsub b/drivers/gles3/SCsub
index 987ddcd16e..fcb05a988d 100644
--- a/drivers/gles3/SCsub
+++ b/drivers/gles3/SCsub
@@ -5,3 +5,4 @@ Import("env")
env.add_source_files(env.drivers_sources, "*.cpp")
SConscript("shaders/SCsub")
+SConscript("storage/SCsub")
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp
index 451960d772..b47d2e08f1 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.cpp
+++ b/drivers/gles3/rasterizer_canvas_gles3.cpp
@@ -38,6 +38,8 @@
#include "core/config/project_settings.h"
#include "servers/rendering/rendering_server_default.h"
+#include "storage/canvas_texture_storage.h"
+#include "storage/config.h"
#ifndef GLES_OVER_GL
#define glClearDepth glClearDepthf
@@ -260,7 +262,7 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou
for (int ti = 0; ti < tc; i++) {
glActiveTexture(GL_TEXTURE0 + ti);
- RasterizerStorageGLES3::Texture *t = storage->texture_owner.get_or_null(textures[ti].second);
+ GLES3::Texture *t = texture_storage->get_texture(textures[ti].second);
if (!t) {
switch (texture_uniforms[i].hint) {
@@ -605,7 +607,7 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
_bind_canvas_texture(RID(), current_filter, current_repeat, r_index, last_texture, texpixel_size);
state.canvas_shader.version_bind_shader(state.current_shader_version, CanvasShaderGLES3::MODE_PRIMITIVE);
- for (uint32_t j = 0; j < MIN(3, primitive->point_count); j++) {
+ for (uint32_t j = 0; j < MIN(3u, primitive->point_count); j++) {
state.instance_data_array[r_index].points[j * 2 + 0] = primitive->points[j].x;
state.instance_data_array[r_index].points[j * 2 + 1] = primitive->points[j].y;
state.instance_data_array[r_index].uvs[j * 2 + 0] = primitive->uvs[j].x;
@@ -915,20 +917,20 @@ void RasterizerCanvasGLES3::_bind_canvas_texture(RID p_texture, RS::CanvasItemTe
state.end_batch = true;
_render_batch(r_index);
- RasterizerStorageGLES3::CanvasTexture *ct = nullptr;
+ GLES3::CanvasTexture *ct = nullptr;
- RasterizerStorageGLES3::Texture *t = storage->texture_owner.get_or_null(p_texture);
+ GLES3::Texture *t = texture_storage->get_texture(p_texture);
if (t) {
//regular texture
if (!t->canvas_texture) {
- t->canvas_texture = memnew(RasterizerStorageGLES3::CanvasTexture);
+ t->canvas_texture = memnew(GLES3::CanvasTexture);
t->canvas_texture->diffuse = p_texture;
}
ct = t->canvas_texture;
} else {
- ct = storage->canvas_texture_owner.get_or_null(p_texture);
+ ct = GLES3::CanvasTextureStorage::get_singleton()->get_canvas_texture(p_texture);
}
if (!ct) {
@@ -943,7 +945,7 @@ void RasterizerCanvasGLES3::_bind_canvas_texture(RID p_texture, RS::CanvasItemTe
RS::CanvasItemTextureRepeat repeat = ct->texture_repeat != RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT ? ct->texture_repeat : p_base_repeat;
ERR_FAIL_COND(repeat == RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT);
- RasterizerStorageGLES3::Texture *texture = storage->texture_owner.get_or_null(ct->diffuse);
+ GLES3::Texture *texture = texture_storage->get_texture(ct->diffuse);
if (!texture) {
state.current_tex = RID();
@@ -967,18 +969,18 @@ void RasterizerCanvasGLES3::_bind_canvas_texture(RID p_texture, RS::CanvasItemTe
texture->GLSetRepeat(GL_TEXTURE_2D, repeat);
}
- RasterizerStorageGLES3::Texture *normal_map = storage->texture_owner.get_or_null(ct->normal_map);
+ GLES3::Texture *normal_map = texture_storage->get_texture(ct->normal_map);
if (!normal_map) {
state.current_normal = RID();
ct->use_normal_cache = false;
- glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 6);
+ glActiveTexture(GL_TEXTURE0 + GLES3::Config::get_singleton()->max_texture_image_units - 6);
glBindTexture(GL_TEXTURE_2D, storage->resources.normal_tex);
} else {
normal_map = normal_map->get_ptr();
- glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 6);
+ glActiveTexture(GL_TEXTURE0 + storage->config->max_texture_image_units - 6);
glBindTexture(GL_TEXTURE_2D, normal_map->tex_id);
state.current_normal = ct->normal_map;
ct->use_normal_cache = true;
@@ -986,18 +988,18 @@ void RasterizerCanvasGLES3::_bind_canvas_texture(RID p_texture, RS::CanvasItemTe
texture->GLSetRepeat(GL_TEXTURE_2D, repeat);
}
- RasterizerStorageGLES3::Texture *specular_map = storage->texture_owner.get_or_null(ct->specular);
+ GLES3::Texture *specular_map = texture_storage->get_texture(ct->specular);
if (!specular_map) {
state.current_specular = RID();
ct->use_specular_cache = false;
- glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 7);
+ glActiveTexture(GL_TEXTURE0 + storage->config->max_texture_image_units - 7);
glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex);
} else {
specular_map = specular_map->get_ptr();
- glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 7);
+ glActiveTexture(GL_TEXTURE0 + storage->config->max_texture_image_units - 7);
glBindTexture(GL_TEXTURE_2D, specular_map->tex_id);
state.current_specular = ct->specular;
ct->use_specular_cache = true;
@@ -1249,6 +1251,10 @@ void RasterizerCanvasGLES3::_allocate_instance_data_buffer() {
}
void RasterizerCanvasGLES3::initialize() {
+ // !BAS! shouldn't we be obtaining storage here as well?
+ canvas_texture_storage = GLES3::CanvasTextureStorage::get_singleton();
+ texture_storage = GLES3::TextureStorage::get_singleton();
+
// quad buffer
{
glGenBuffers(1, &data.canvas_quad_vertices);
@@ -1408,7 +1414,7 @@ void RasterizerCanvasGLES3::initialize() {
state.canvas_shader_default_version = state.canvas_shader.version_create();
state.canvas_shader.version_bind_shader(state.canvas_shader_default_version, CanvasShaderGLES3::MODE_QUAD);
- //state.canvas_shader.set_conditional(CanvasOldShaderGLES3::USE_RGBA_SHADOWS, storage->config.use_rgba_2d_shadows);
+ //state.canvas_shader.set_conditional(CanvasOldShaderGLES3::USE_RGBA_SHADOWS, storage->config->use_rgba_2d_shadows);
//state.canvas_shader.bind();
@@ -1441,8 +1447,8 @@ void fragment() {
storage->material_set_shader(default_canvas_group_material, default_canvas_group_shader);
}
- default_canvas_texture = storage->canvas_texture_allocate();
- storage->canvas_texture_initialize(default_canvas_texture);
+ default_canvas_texture = canvas_texture_storage->canvas_texture_allocate();
+ canvas_texture_storage->canvas_texture_initialize(default_canvas_texture);
state.using_light = nullptr;
state.using_transparent_rt = false;
@@ -1456,7 +1462,7 @@ RasterizerCanvasGLES3::~RasterizerCanvasGLES3() {
state.canvas_shader.version_free(state.canvas_shader_default_version);
storage->free(default_canvas_group_material);
storage->free(default_canvas_group_shader);
- storage->free(default_canvas_texture);
+ canvas_texture_storage->canvas_texture_free(default_canvas_texture);
}
void RasterizerCanvasGLES3::finalize() {
diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h
index 908d79f9f8..1f57c2b5ea 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.h
+++ b/drivers/gles3/rasterizer_canvas_gles3.h
@@ -37,6 +37,8 @@
#include "rasterizer_storage_gles3.h"
#include "servers/rendering/renderer_canvas_render.h"
#include "servers/rendering/renderer_compositor.h"
+#include "storage/canvas_texture_storage.h"
+#include "storage/texture_storage.h"
#include "shaders/canvas.glsl.gen.h"
@@ -184,7 +186,7 @@ public:
RID current_tex = RID();
RID current_normal = RID();
RID current_specular = RID();
- RasterizerStorageGLES3::Texture *current_tex_ptr;
+ GLES3::Texture *current_tex_ptr;
RID current_shader_version = RID();
RS::PrimitiveType current_primitive = RS::PRIMITIVE_MAX;
uint32_t current_primitive_points = 0;
@@ -217,6 +219,8 @@ public:
RasterizerSceneGLES3 *scene_render;
+ GLES3::CanvasTextureStorage *canvas_texture_storage;
+ GLES3::TextureStorage *texture_storage;
RasterizerStorageGLES3 *storage;
void _set_uniforms();
diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp
index 087bf36473..faadb2a4ed 100644
--- a/drivers/gles3/rasterizer_gles3.cpp
+++ b/drivers/gles3/rasterizer_gles3.cpp
@@ -195,7 +195,7 @@ typedef void (*DebugMessageCallbackARB)(DEBUGPROCARB callback, const void *userP
void RasterizerGLES3::initialize() {
print_verbose("Using OpenGL video driver");
- storage._main_thread_id = Thread::get_caller_id();
+ texture_storage.set_main_thread_id(Thread::get_caller_id());
#ifdef GLAD_ENABLED
if (!gladLoadGL()) {
@@ -271,7 +271,7 @@ void RasterizerGLES3::prepare_for_blitting_render_targets() {
void RasterizerGLES3::_blit_render_target_to_screen(RID p_render_target, DisplayServer::WindowID p_screen, const Rect2 &p_screen_rect) {
ERR_FAIL_COND(storage.frame.current_rt);
- RasterizerStorageGLES3::RenderTarget *rt = storage.render_target_owner.get_or_null(p_render_target);
+ GLES3::RenderTarget *rt = storage.render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND(!rt);
// TODO: do we need a keep 3d linear option?
@@ -324,10 +324,10 @@ void RasterizerGLES3::set_boot_image(const Ref<Image> &p_image, const Color &p_c
canvas.canvas_begin();
- RID texture = storage.texture_create();
- //storage.texture_allocate(texture, p_image->get_width(), p_image->get_height(), 0, p_image->get_format(), VS::TEXTURE_TYPE_2D, p_use_filter ? VS::TEXTURE_FLAG_FILTER : 0);
- storage._texture_allocate_internal(texture, p_image->get_width(), p_image->get_height(), 0, p_image->get_format(), RenderingDevice::TEXTURE_TYPE_2D);
- storage.texture_set_data(texture, p_image);
+ RID texture = texture_storage.texture_create();
+ //texture_storage.texture_allocate(texture, p_image->get_width(), p_image->get_height(), 0, p_image->get_format(), VS::TEXTURE_TYPE_2D, p_use_filter ? VS::TEXTURE_FLAG_FILTER : 0);
+ texture_storage._texture_allocate_internal(texture, p_image->get_width(), p_image->get_height(), 0, p_image->get_format(), RenderingDevice::TEXTURE_TYPE_2D);
+ texture_storage.texture_set_data(texture, p_image);
Rect2 imgrect(0, 0, p_image->get_width(), p_image->get_height());
Rect2 screenrect;
@@ -349,13 +349,13 @@ void RasterizerGLES3::set_boot_image(const Ref<Image> &p_image, const Color &p_c
screenrect.position += ((Size2(win_size.width, win_size.height) - screenrect.size) / 2.0).floor();
}
- RasterizerStorageGLES3::Texture *t = storage.texture_owner.get_or_null(texture);
- glActiveTexture(GL_TEXTURE0 + storage.config.max_texture_image_units - 1);
+ GLES3::Texture *t = texture_storage.get_texture(texture);
+ glActiveTexture(GL_TEXTURE0 + config.max_texture_image_units - 1);
glBindTexture(GL_TEXTURE_2D, t->tex_id);
glBindTexture(GL_TEXTURE_2D, 0);
canvas.canvas_end();
- storage.free(texture);
+ texture_storage.texture_free(texture);
end_frame(true);
}
diff --git a/drivers/gles3/rasterizer_gles3.h b/drivers/gles3/rasterizer_gles3.h
index a641e189c5..93c58a8d9d 100644
--- a/drivers/gles3/rasterizer_gles3.h
+++ b/drivers/gles3/rasterizer_gles3.h
@@ -37,6 +37,10 @@
#include "rasterizer_scene_gles3.h"
#include "rasterizer_storage_gles3.h"
#include "servers/rendering/renderer_compositor.h"
+#include "storage/canvas_texture_storage.h"
+#include "storage/config.h"
+#include "storage/render_target_storage.h"
+#include "storage/texture_storage.h"
class RasterizerGLES3 : public RendererCompositor {
private:
@@ -46,6 +50,9 @@ private:
double time_total = 0.0;
protected:
+ GLES3::Config config;
+ GLES3::CanvasTextureStorage canvas_texture_storage;
+ GLES3::TextureStorage texture_storage;
RasterizerStorageGLES3 storage;
RasterizerCanvasGLES3 canvas;
RasterizerSceneGLES3 scene;
@@ -53,6 +60,8 @@ protected:
void _blit_render_target_to_screen(RID p_render_target, DisplayServer::WindowID p_screen, const Rect2 &p_screen_rect);
public:
+ RendererCanvasTextureStorage *get_canvas_texture_storage() { return &canvas_texture_storage; }
+ RendererTextureStorage *get_texture_storage() { return &texture_storage; }
RendererStorage *get_storage() { return &storage; }
RendererCanvasRender *get_canvas() { return &canvas; }
RendererSceneRender *get_scene() { return &scene; }
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index 121dc86fb2..1382573461 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "rasterizer_scene_gles3.h"
+
#ifdef GLES3_ENABLED
// TODO: 3D support not implemented yet.
diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h
index 246b908c14..12bb21a5a0 100644
--- a/drivers/gles3/rasterizer_scene_gles3.h
+++ b/drivers/gles3/rasterizer_scene_gles3.h
@@ -78,11 +78,11 @@ public:
/* SHADOW ATLAS API */
RID shadow_atlas_create() override;
- void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits = false) override;
+ void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits = true) override;
void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) override;
bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) override;
- void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = false) override;
+ void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = true) override;
int get_directional_light_shadow_size(RID p_light_intance) override;
void set_directional_shadow_count(int p_count) override;
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp
index fda208b812..e28a40ba9b 100644
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ b/drivers/gles3/rasterizer_storage_gles3.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "rasterizer_storage_gles3.h"
+
#ifdef GLES3_ENABLED
#include "core/config/project_settings.h"
@@ -39,45 +40,6 @@
GLuint RasterizerStorageGLES3::system_fbo = 0;
-/* TEXTURE API */
-
-#define _EXT_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
-#define _EXT_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
-#define _EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
-
-#define _EXT_COMPRESSED_RED_RGTC1_EXT 0x8DBB
-#define _EXT_COMPRESSED_RED_RGTC1 0x8DBB
-#define _EXT_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC
-#define _EXT_COMPRESSED_RG_RGTC2 0x8DBD
-#define _EXT_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE
-#define _EXT_COMPRESSED_SIGNED_RED_RGTC1_EXT 0x8DBC
-#define _EXT_COMPRESSED_RED_GREEN_RGTC2_EXT 0x8DBD
-#define _EXT_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT 0x8DBE
-#define _EXT_ETC1_RGB8_OES 0x8D64
-
-#define _EXT_COMPRESSED_RGBA_BPTC_UNORM 0x8E8C
-#define _EXT_COMPRESSED_SRGB_ALPHA_BPTC_UNORM 0x8E8D
-#define _EXT_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E
-#define _EXT_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F
-
-#define _GL_TEXTURE_EXTERNAL_OES 0x8D65
-
-#ifdef GLES_OVER_GL
-#define _GL_HALF_FLOAT_OES 0x140B
-#else
-#define _GL_HALF_FLOAT_OES 0x8D61
-#endif
-
-#define _EXT_TEXTURE_CUBE_MAP_SEAMLESS 0x884F
-
-#define _RED_OES 0x1903
-
-#define _DEPTH_COMPONENT24_OES 0x81A6
-
-#ifndef GLES_OVER_GL
-#define glClearDepth glClearDepthf
-#endif //!GLES_OVER_GL
-
void RasterizerStorageGLES3::bind_quad_array() const {
//glBindBuffer(GL_ARRAY_BUFFER, resources.quadie);
//glVertexAttribPointer(RS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, 0);
@@ -87,1180 +49,6 @@ void RasterizerStorageGLES3::bind_quad_array() const {
//glEnableVertexAttribArray(RS::ARRAY_TEX_UV);
}
-bool RasterizerStorageGLES3::can_create_resources_async() const {
- return false;
-}
-
-Ref<Image> RasterizerStorageGLES3::_get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, 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 {
- r_gl_format = 0;
- Ref<Image> image = p_image;
- r_compressed = false;
- r_real_format = p_format;
-
- bool need_decompress = false;
-
- switch (p_format) {
- case Image::FORMAT_L8: {
-#ifdef GLES_OVER_GL
- r_gl_internal_format = GL_R8;
- r_gl_format = GL_RED;
- r_gl_type = GL_UNSIGNED_BYTE;
-#else
- r_gl_internal_format = GL_LUMINANCE;
- r_gl_format = GL_LUMINANCE;
- r_gl_type = GL_UNSIGNED_BYTE;
-#endif
- } break;
- case Image::FORMAT_LA8: {
-#ifdef GLES_OVER_GL
- r_gl_internal_format = GL_RG8;
- r_gl_format = GL_RG;
- r_gl_type = GL_UNSIGNED_BYTE;
-#else
- r_gl_internal_format = GL_LUMINANCE_ALPHA;
- r_gl_format = GL_LUMINANCE_ALPHA;
- r_gl_type = GL_UNSIGNED_BYTE;
-#endif
- } break;
- case Image::FORMAT_R8: {
- r_gl_internal_format = GL_R8;
- r_gl_format = GL_RED;
- r_gl_type = GL_UNSIGNED_BYTE;
-
- } break;
- case Image::FORMAT_RG8: {
- r_gl_internal_format = GL_RG8;
- r_gl_format = GL_RG;
- r_gl_type = GL_UNSIGNED_BYTE;
-
- } break;
- case Image::FORMAT_RGB8: {
- r_gl_internal_format = GL_RGB8;
- r_gl_format = GL_RGB;
- r_gl_type = GL_UNSIGNED_BYTE;
- //r_srgb = true;
-
- } break;
- case Image::FORMAT_RGBA8: {
- r_gl_format = GL_RGBA;
- r_gl_internal_format = GL_RGBA8;
- r_gl_type = GL_UNSIGNED_BYTE;
- //r_srgb = true;
-
- } break;
- case Image::FORMAT_RGBA4444: {
- r_gl_internal_format = GL_RGBA4;
- r_gl_format = GL_RGBA;
- r_gl_type = GL_UNSIGNED_SHORT_4_4_4_4;
-
- } break;
- //case Image::FORMAT_RGBA5551: {
- // r_gl_internal_format = GL_RGB5_A1;
- // r_gl_format = GL_RGBA;
- // r_gl_type = GL_UNSIGNED_SHORT_5_5_5_1;
- //
- //} break;
- case Image::FORMAT_RF: {
- r_gl_internal_format = GL_R32F;
- r_gl_format = GL_RED;
- r_gl_type = GL_FLOAT;
-
- } break;
- case Image::FORMAT_RGF: {
- r_gl_internal_format = GL_RG32F;
- r_gl_format = GL_RG;
- r_gl_type = GL_FLOAT;
-
- } break;
- case Image::FORMAT_RGBF: {
- r_gl_internal_format = GL_RGB32F;
- r_gl_format = GL_RGB;
- r_gl_type = GL_FLOAT;
-
- } break;
- case Image::FORMAT_RGBAF: {
- r_gl_internal_format = GL_RGBA32F;
- r_gl_format = GL_RGBA;
- r_gl_type = GL_FLOAT;
-
- } break;
- case Image::FORMAT_RH: {
- r_gl_internal_format = GL_R16F;
- r_gl_format = GL_RED;
- r_gl_type = GL_HALF_FLOAT;
- } break;
- case Image::FORMAT_RGH: {
- r_gl_internal_format = GL_RG16F;
- r_gl_format = GL_RG;
- r_gl_type = GL_HALF_FLOAT;
-
- } break;
- case Image::FORMAT_RGBH: {
- r_gl_internal_format = GL_RGB16F;
- r_gl_format = GL_RGB;
- r_gl_type = GL_HALF_FLOAT;
-
- } break;
- case Image::FORMAT_RGBAH: {
- r_gl_internal_format = GL_RGBA16F;
- r_gl_format = GL_RGBA;
- r_gl_type = GL_HALF_FLOAT;
-
- } break;
- case Image::FORMAT_RGBE9995: {
- r_gl_internal_format = GL_RGB9_E5;
- r_gl_format = GL_RGB;
- r_gl_type = GL_UNSIGNED_INT_5_9_9_9_REV;
-
- } break;
- case Image::FORMAT_DXT1: {
- if (config.s3tc_supported) {
- r_gl_internal_format = _EXT_COMPRESSED_RGBA_S3TC_DXT1_EXT;
- r_gl_format = GL_RGBA;
- r_gl_type = GL_UNSIGNED_BYTE;
- r_compressed = true;
- //r_srgb = true;
-
- } else {
- need_decompress = true;
- }
- } break;
- case Image::FORMAT_DXT3: {
- if (config.s3tc_supported) {
- r_gl_internal_format = _EXT_COMPRESSED_RGBA_S3TC_DXT3_EXT;
- r_gl_format = GL_RGBA;
- r_gl_type = GL_UNSIGNED_BYTE;
- r_compressed = true;
- //r_srgb = true;
-
- } else {
- need_decompress = true;
- }
- } break;
- case Image::FORMAT_DXT5: {
- if (config.s3tc_supported) {
- r_gl_internal_format = _EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT;
- r_gl_format = GL_RGBA;
- r_gl_type = GL_UNSIGNED_BYTE;
- r_compressed = true;
- //r_srgb = true;
-
- } else {
- need_decompress = true;
- }
- } break;
- case Image::FORMAT_RGTC_R: {
- if (config.rgtc_supported) {
- r_gl_internal_format = _EXT_COMPRESSED_RED_RGTC1_EXT;
- r_gl_format = GL_RGBA;
- r_gl_type = GL_UNSIGNED_BYTE;
- r_compressed = true;
-
- } else {
- need_decompress = true;
- }
- } break;
- case Image::FORMAT_RGTC_RG: {
- if (config.rgtc_supported) {
- r_gl_internal_format = _EXT_COMPRESSED_RED_GREEN_RGTC2_EXT;
- r_gl_format = GL_RGBA;
- r_gl_type = GL_UNSIGNED_BYTE;
- r_compressed = true;
- } else {
- need_decompress = true;
- }
- } break;
- case Image::FORMAT_BPTC_RGBA: {
- if (config.bptc_supported) {
- r_gl_internal_format = _EXT_COMPRESSED_RGBA_BPTC_UNORM;
- r_gl_format = GL_RGBA;
- r_gl_type = GL_UNSIGNED_BYTE;
- r_compressed = true;
- //r_srgb = true;
-
- } else {
- need_decompress = true;
- }
- } break;
- case Image::FORMAT_BPTC_RGBF: {
- if (config.bptc_supported) {
- r_gl_internal_format = _EXT_COMPRESSED_RGB_BPTC_SIGNED_FLOAT;
- r_gl_format = GL_RGB;
- r_gl_type = GL_FLOAT;
- r_compressed = true;
- } else {
- need_decompress = true;
- }
- } break;
- case Image::FORMAT_BPTC_RGBFU: {
- if (config.bptc_supported) {
- r_gl_internal_format = _EXT_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT;
- r_gl_format = GL_RGB;
- r_gl_type = GL_FLOAT;
- r_compressed = true;
- } else {
- need_decompress = true;
- }
- } break;
- case Image::FORMAT_ETC: {
- if (config.etc_supported) {
- r_gl_internal_format = _EXT_ETC1_RGB8_OES;
- r_gl_format = GL_RGBA;
- r_gl_type = GL_UNSIGNED_BYTE;
- r_compressed = true;
-
- } else {
- need_decompress = true;
- }
-
- } break;
- /*
- case Image::FORMAT_ETC2_R11: {
- if (config.etc2_supported) {
- r_gl_internal_format = _EXT_COMPRESSED_R11_EAC;
- r_gl_format = GL_RED;
- r_gl_type = GL_UNSIGNED_BYTE;
- r_compressed = true;
-
- } else {
- need_decompress = true;
- }
- } break;
- case Image::FORMAT_ETC2_R11S: {
- if (config.etc2_supported) {
- r_gl_internal_format = _EXT_COMPRESSED_SIGNED_R11_EAC;
- r_gl_format = GL_RED;
- r_gl_type = GL_UNSIGNED_BYTE;
- r_compressed = true;
-
- } else {
- need_decompress = true;
- }
- } break;
- case Image::FORMAT_ETC2_RG11: {
- if (config.etc2_supported) {
- r_gl_internal_format = _EXT_COMPRESSED_RG11_EAC;
- r_gl_format = GL_RG;
- r_gl_type = GL_UNSIGNED_BYTE;
- r_compressed = true;
-
- } else {
- need_decompress = true;
- }
- } break;
- case Image::FORMAT_ETC2_RG11S: {
- if (config.etc2_supported) {
- r_gl_internal_format = _EXT_COMPRESSED_SIGNED_RG11_EAC;
- r_gl_format = GL_RG;
- r_gl_type = GL_UNSIGNED_BYTE;
- r_compressed = true;
-
- } else {
- need_decompress = true;
- }
- } break;
- case Image::FORMAT_ETC2_RGB8: {
- if (config.etc2_supported) {
- r_gl_internal_format = _EXT_COMPRESSED_RGB8_ETC2;
- r_gl_format = GL_RGB;
- r_gl_type = GL_UNSIGNED_BYTE;
- r_compressed = true;
- //r_srgb = true;
-
- } else {
- need_decompress = true;
- }
- } break;
- case Image::FORMAT_ETC2_RGBA8: {
- if (config.etc2_supported) {
- r_gl_internal_format = _EXT_COMPRESSED_RGBA8_ETC2_EAC;
- r_gl_format = GL_RGBA;
- r_gl_type = GL_UNSIGNED_BYTE;
- r_compressed = true;
- //r_srgb = true;
-
- } else {
- need_decompress = true;
- }
- } break;
- case Image::FORMAT_ETC2_RGB8A1: {
- if (config.etc2_supported) {
- r_gl_internal_format = _EXT_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2;
- r_gl_format = GL_RGBA;
- r_gl_type = GL_UNSIGNED_BYTE;
- r_compressed = true;
- //r_srgb = true;
-
- } else {
- need_decompress = true;
- }
- } break;
- */
- default: {
- ERR_FAIL_V(Ref<Image>());
- }
- }
-
- if (need_decompress || p_force_decompress) {
- if (!image.is_null()) {
- image = image->duplicate();
- image->decompress();
- ERR_FAIL_COND_V(image->is_compressed(), image);
- switch (image->get_format()) {
- case Image::FORMAT_RGB8: {
- r_gl_format = GL_RGB;
- r_gl_internal_format = GL_RGB;
- r_gl_type = GL_UNSIGNED_BYTE;
- r_real_format = Image::FORMAT_RGB8;
- r_compressed = false;
- } break;
- case Image::FORMAT_RGBA8: {
- r_gl_format = GL_RGBA;
- r_gl_internal_format = GL_RGBA;
- r_gl_type = GL_UNSIGNED_BYTE;
- r_real_format = Image::FORMAT_RGBA8;
- r_compressed = false;
- } break;
- default: {
- image->convert(Image::FORMAT_RGBA8);
- r_gl_format = GL_RGBA;
- r_gl_internal_format = GL_RGBA;
- r_gl_type = GL_UNSIGNED_BYTE;
- r_real_format = Image::FORMAT_RGBA8;
- r_compressed = false;
-
- } break;
- }
- }
-
- return image;
- }
-
- return p_image;
-}
-
-static const GLenum _cube_side_enum[6] = {
- GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
- GL_TEXTURE_CUBE_MAP_POSITIVE_X,
- GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
- GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
- GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
- GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
-};
-
-RID RasterizerStorageGLES3::texture_allocate() {
- RID id = texture_create();
- ERR_FAIL_COND_V(id == RID(), id);
- return id;
-}
-
-void RasterizerStorageGLES3::texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) {
- Texture *tex = texture_owner.get_or_null(p_texture);
- ERR_FAIL_COND(!tex);
-
- int w = p_image->get_width();
- int h = p_image->get_height();
-
- _texture_allocate_internal(p_texture, w, h, 1, p_image->get_format(), RenderingDevice::TEXTURE_TYPE_2D, 0);
- texture_set_data(p_texture, p_image);
-}
-
-void RasterizerStorageGLES3::texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) {
-}
-
-void RasterizerStorageGLES3::texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) {
-}
-
-void RasterizerStorageGLES3::texture_proxy_initialize(RID p_texture, RID p_base) {
- texture_set_proxy(p_texture, p_base);
-}
-
-//RID RasterizerStorageGLES3::texture_2d_create(const Ref<Image> &p_image) {
-// RID id = texture_create();
-// ERR_FAIL_COND_V(id == RID(), id);
-
-// int w = p_image->get_width();
-// int h = p_image->get_height();
-
-// texture_allocate(id, w, h, 1, p_image->get_format(), RenderingDevice::TEXTURE_TYPE_2D, 0);
-
-// texture_set_data(id, p_image);
-
-// return id;
-//}
-
-//RID RasterizerStorageGLES3::texture_2d_layered_create(const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) {
-// return RID();
-//}
-
-//void RasterizerStorageGLES3::texture_2d_update_immediate(RID p_texture, const Ref<Image> &p_image, int p_layer) {
-// // only 1 layer so far
-// texture_set_data(p_texture, p_image);
-//}
-void RasterizerStorageGLES3::texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer) {
- // only 1 layer so far
- texture_set_data(p_texture, p_image);
-}
-
-void RasterizerStorageGLES3::texture_2d_placeholder_initialize(RID p_texture) {
-}
-
-void RasterizerStorageGLES3::texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) {
-}
-
-void RasterizerStorageGLES3::texture_3d_placeholder_initialize(RID p_texture) {
-}
-
-Ref<Image> RasterizerStorageGLES3::texture_2d_get(RID p_texture) const {
- Texture *tex = texture_owner.get_or_null(p_texture);
- ERR_FAIL_COND_V(!tex, Ref<Image>());
-
- /*
-#ifdef TOOLS_ENABLED
- if (tex->image_cache_2d.is_valid()) {
- return tex->image_cache_2d;
- }
-#endif
- Vector<uint8_t> data = RD::get_singleton()->texture_get_data(tex->rd_texture, 0);
- ERR_FAIL_COND_V(data.size() == 0, Ref<Image>());
- Ref<Image> image;
- image.instance();
- image->create(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data);
- ERR_FAIL_COND_V(image->empty(), Ref<Image>());
- if (tex->format != tex->validated_format) {
- image->convert(tex->format);
- }
-
-#ifdef TOOLS_ENABLED
- if (Engine::get_singleton()->is_editor_hint()) {
- tex->image_cache_2d = image;
- }
-#endif
-*/
- ERR_FAIL_COND_V(!tex->images.size(), Ref<Image>());
-
- return tex->images[0];
-
- // return image;
-
- // return Ref<Image>();
-}
-
-void RasterizerStorageGLES3::texture_replace(RID p_texture, RID p_by_texture) {
- Texture *tex_to = texture_owner.get_or_null(p_texture);
- ERR_FAIL_COND(!tex_to);
- Texture *tex_from = texture_owner.get_or_null(p_by_texture);
- ERR_FAIL_COND(!tex_from);
-
- tex_to->destroy();
- tex_to->copy_from(*tex_from);
-
- // copy image data and upload to GL
- tex_to->images.resize(tex_from->images.size());
-
- for (int n = 0; n < tex_from->images.size(); n++) {
- texture_set_data(p_texture, tex_from->images[n], n);
- }
-
- free(p_by_texture);
-}
-
-bool RasterizerStorageGLES3::_is_main_thread() {
- //#if defined DEBUG_ENABLED && defined TOOLS_ENABLED
- // must be called from main thread in OpenGL
- bool is_main_thread = _main_thread_id == Thread::get_caller_id();
- //#endif
- return is_main_thread;
-}
-
-RID RasterizerStorageGLES3::texture_create() {
- ERR_FAIL_COND_V(!_is_main_thread(), RID());
-
- Texture *texture = memnew(Texture);
- ERR_FAIL_COND_V(!texture, RID());
- glGenTextures(1, &texture->tex_id);
- texture->active = false;
- texture->total_data_size = 0;
-
- return texture_owner.make_rid(texture);
-}
-
-void RasterizerStorageGLES3::_texture_allocate_internal(RID p_texture, int p_width, int p_height, int p_depth_3d, Image::Format p_format, RenderingDevice::TextureType p_type, uint32_t p_flags) {
- // GLenum format;
- // GLenum internal_format;
- // GLenum type;
-
- // bool compressed = false;
-
- if (p_flags & TEXTURE_FLAG_USED_FOR_STREAMING) {
- p_flags &= ~TEXTURE_FLAG_MIPMAPS; // no mipies for video
- }
-
- Texture *texture = texture_owner.get_or_null(p_texture);
- ERR_FAIL_COND(!texture);
- texture->width = p_width;
- texture->height = p_height;
- texture->format = p_format;
- texture->flags = p_flags;
- texture->stored_cube_sides = 0;
- texture->type = p_type;
-
- switch (p_type) {
- case RenderingDevice::TEXTURE_TYPE_2D: {
- texture->target = GL_TEXTURE_2D;
- texture->images.resize(1);
- } break;
- // case RenderingDevice::TEXTURE_TYPE_EXTERNAL: {
- //#ifdef ANDROID_ENABLED
- // texture->target = _GL_TEXTURE_EXTERNAL_OES;
- //#else
- // texture->target = GL_TEXTURE_2D;
- //#endif
- // texture->images.resize(0);
- // } break;
- case RenderingDevice::TEXTURE_TYPE_CUBE: {
- texture->target = GL_TEXTURE_CUBE_MAP;
- texture->images.resize(6);
- } break;
- case RenderingDevice::TEXTURE_TYPE_2D_ARRAY:
- case RenderingDevice::TEXTURE_TYPE_3D: {
- texture->target = GL_TEXTURE_3D;
- ERR_PRINT("3D textures and Texture Arrays are not supported in OpenGL. Please switch to the Vulkan backend.");
- return;
- } break;
- default: {
- ERR_PRINT("Unknown texture type!");
- return;
- }
- }
-
-#if 0
- // if (p_type != RS::TEXTURE_TYPE_EXTERNAL) {
- if (p_type == RenderingDevice::TEXTURE_TYPE_2D) {
- texture->alloc_width = texture->width;
- texture->alloc_height = texture->height;
- texture->resize_to_po2 = false;
- if (!config.support_npot_repeat_mipmap) {
- int po2_width = next_power_of_2(p_width);
- int po2_height = next_power_of_2(p_height);
-
- bool is_po2 = p_width == po2_width && p_height == po2_height;
-
- if (!is_po2 && (p_flags & TEXTURE_FLAG_REPEAT || p_flags & TEXTURE_FLAG_MIPMAPS)) {
- if (p_flags & TEXTURE_FLAG_USED_FOR_STREAMING) {
- //not supported
- ERR_PRINT("Streaming texture for non power of 2 or has mipmaps on this hardware: " + texture->path + "'. Mipmaps and repeat disabled.");
- texture->flags &= ~(TEXTURE_FLAG_REPEAT | TEXTURE_FLAG_MIPMAPS);
- } else {
- texture->alloc_height = po2_height;
- texture->alloc_width = po2_width;
- texture->resize_to_po2 = true;
- }
- }
- }
-
- GLenum format;
- GLenum internal_format;
- GLenum type;
- bool compressed = false;
-
- Image::Format real_format;
- _get_gl_image_and_format(Ref<Image>(),
- texture->format,
- texture->flags,
- real_format,
- format,
- internal_format,
- type,
- compressed,
- texture->resize_to_po2);
-
- texture->gl_format_cache = format;
- texture->gl_type_cache = type;
- texture->gl_internal_format_cache = internal_format;
- texture->data_size = 0;
- texture->mipmaps = 1;
-
- texture->compressed = compressed;
- }
-#endif
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(texture->target, texture->tex_id);
-
- // if (p_type == RS::TEXTURE_TYPE_EXTERNAL) {
- // glTexParameteri(texture->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- // glTexParameteri(texture->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- // glTexParameteri(texture->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- // glTexParameteri(texture->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- // } else if (p_flags & TEXTURE_FLAG_USED_FOR_STREAMING) {
- // //prealloc if video
- // glTexImage2D(texture->target, 0, internal_format, texture->alloc_width, texture->alloc_height, 0, format, type, NULL);
- // }
-
- texture->active = true;
-}
-
-void RasterizerStorageGLES3::texture_set_data(RID p_texture, const Ref<Image> &p_image, int p_layer) {
- Texture *texture = texture_owner.get_or_null(p_texture);
-
- ERR_FAIL_COND(!_is_main_thread());
-
- ERR_FAIL_COND(!texture);
- if (texture->target == GL_TEXTURE_3D) {
- // Target is set to a 3D texture or array texture, exit early to avoid spamming errors
- return;
- }
- ERR_FAIL_COND(!texture->active);
- ERR_FAIL_COND(texture->render_target);
- ERR_FAIL_COND(p_image.is_null());
- ERR_FAIL_COND(texture->format != p_image->get_format());
-
- ERR_FAIL_COND(!p_image->get_width());
- ERR_FAIL_COND(!p_image->get_height());
-
- // ERR_FAIL_COND(texture->type == RS::TEXTURE_TYPE_EXTERNAL);
-
- GLenum type;
- GLenum format;
- GLenum internal_format;
- bool compressed = false;
-
- if (config.keep_original_textures && !(texture->flags & TEXTURE_FLAG_USED_FOR_STREAMING)) {
- texture->images.write[p_layer] = p_image;
- }
-
- // print_line("texture_set_data width " + itos (p_image->get_width()) + " height " + itos(p_image->get_height()));
-
- Image::Format real_format;
- Ref<Image> img = _get_gl_image_and_format(p_image, p_image->get_format(), texture->flags, real_format, format, internal_format, type, compressed, texture->resize_to_po2);
-
- if (texture->resize_to_po2) {
- if (p_image->is_compressed()) {
- ERR_PRINT("Texture '" + texture->path + "' is required to be a power of 2 because it uses either mipmaps or repeat, so it was decompressed. This will hurt performance and memory usage.");
- }
-
- if (img == p_image) {
- img = img->duplicate();
- }
- img->resize_to_po2(false);
- }
-
- if (config.shrink_textures_x2 && (p_image->has_mipmaps() || !p_image->is_compressed()) && !(texture->flags & TEXTURE_FLAG_USED_FOR_STREAMING)) {
- texture->alloc_height = MAX(1, texture->alloc_height / 2);
- texture->alloc_width = MAX(1, texture->alloc_width / 2);
-
- if (texture->alloc_width == img->get_width() / 2 && texture->alloc_height == img->get_height() / 2) {
- img->shrink_x2();
- } else if (img->get_format() <= Image::FORMAT_RGBA8) {
- img->resize(texture->alloc_width, texture->alloc_height, Image::INTERPOLATE_BILINEAR);
- }
- }
-
- GLenum blit_target = (texture->target == GL_TEXTURE_CUBE_MAP) ? _cube_side_enum[p_layer] : GL_TEXTURE_2D;
-
- texture->data_size = img->get_data().size();
- Vector<uint8_t> read = img->get_data();
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(texture->target, texture->tex_id);
-
- texture->ignore_mipmaps = compressed && !img->has_mipmaps();
-
- // set filtering and repeat state
- _texture_set_state_from_flags(texture);
-
- //set swizle for older format compatibility
-#ifdef GLES_OVER_GL
- switch (texture->format) {
- case Image::FORMAT_L8: {
- glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_R, GL_RED);
- glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_G, GL_RED);
- glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_B, GL_RED);
- glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_A, GL_ONE);
-
- } break;
- case Image::FORMAT_LA8: {
- glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_R, GL_RED);
- glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_G, GL_RED);
- glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_B, GL_RED);
- glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_A, GL_GREEN);
- } break;
- default: {
- glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_R, GL_RED);
- glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_G, GL_GREEN);
- glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_B, GL_BLUE);
- glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_A, GL_ALPHA);
-
- } break;
- }
-#endif
-
- int mipmaps = ((texture->flags & TEXTURE_FLAG_MIPMAPS) && img->has_mipmaps()) ? img->get_mipmap_count() + 1 : 1;
-
- int w = img->get_width();
- int h = img->get_height();
-
- int tsize = 0;
-
- for (int i = 0; i < mipmaps; i++) {
- int size, ofs;
- img->get_mipmap_offset_and_size(i, ofs, size);
-
- if (compressed) {
- glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
-
- int bw = w;
- int bh = h;
-
- glCompressedTexImage2D(blit_target, i, internal_format, bw, bh, 0, size, &read[ofs]);
- } else {
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- if (texture->flags & TEXTURE_FLAG_USED_FOR_STREAMING) {
- glTexSubImage2D(blit_target, i, 0, 0, w, h, format, type, &read[ofs]);
- } else {
- glTexImage2D(blit_target, i, internal_format, w, h, 0, format, type, &read[ofs]);
- }
- }
-
- tsize += size;
-
- w = MAX(1, w >> 1);
- h = MAX(1, h >> 1);
- }
-
- info.texture_mem -= texture->total_data_size;
- texture->total_data_size = tsize;
- info.texture_mem += texture->total_data_size;
-
- // printf("texture: %i x %i - size: %i - total: %i\n", texture->width, texture->height, tsize, info.texture_mem);
-
- texture->stored_cube_sides |= (1 << p_layer);
-
- if ((texture->flags & TEXTURE_FLAG_MIPMAPS) && mipmaps == 1 && !texture->ignore_mipmaps && (texture->type != RenderingDevice::TEXTURE_TYPE_CUBE || texture->stored_cube_sides == (1 << 6) - 1)) {
- //generate mipmaps if they were requested and the image does not contain them
- glGenerateMipmap(texture->target);
- }
-
- texture->mipmaps = mipmaps;
-}
-
-void RasterizerStorageGLES3::texture_set_data_partial(RID p_texture, const Ref<Image> &p_image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int p_dst_mip, int p_layer) {
- // TODO
- ERR_PRINT("Not implemented (ask Karroffel to do it :p)");
-}
-
-/*
-Ref<Image> RasterizerStorageGLES3::texture_get_data(RID p_texture, int p_layer) const {
- Texture *texture = texture_owner.get_or_null(p_texture);
-
- ERR_FAIL_COND_V(!texture, Ref<Image>());
- ERR_FAIL_COND_V(!texture->active, Ref<Image>());
- ERR_FAIL_COND_V(texture->data_size == 0 && !texture->render_target, Ref<Image>());
-
- if (texture->type == RS::TEXTURE_TYPE_CUBEMAP && p_layer < 6 && p_layer >= 0 && !texture->images[p_layer].is_null()) {
- return texture->images[p_layer];
- }
-
-#ifdef GLES_OVER_GL
-
- Image::Format real_format;
- GLenum gl_format;
- GLenum gl_internal_format;
- GLenum gl_type;
- bool compressed;
- _get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, real_format, gl_format, gl_internal_format, gl_type, compressed, false);
-
- PoolVector<uint8_t> data;
-
- int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, real_format, texture->mipmaps > 1);
-
- data.resize(data_size * 2); //add some memory at the end, just in case for buggy drivers
- PoolVector<uint8_t>::Write wb = data.write();
-
- glActiveTexture(GL_TEXTURE0);
-
- glBindTexture(texture->target, texture->tex_id);
-
- glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
-
- for (int i = 0; i < texture->mipmaps; i++) {
- int ofs = Image::get_image_mipmap_offset(texture->alloc_width, texture->alloc_height, real_format, i);
-
- if (texture->compressed) {
- glPixelStorei(GL_PACK_ALIGNMENT, 4);
- glGetCompressedTexImage(texture->target, i, &wb[ofs]);
- } else {
- glPixelStorei(GL_PACK_ALIGNMENT, 1);
- glGetTexImage(texture->target, i, texture->gl_format_cache, texture->gl_type_cache, &wb[ofs]);
- }
- }
-
- wb.release();
-
- data.resize(data_size);
-
- Image *img = memnew(Image(texture->alloc_width, texture->alloc_height, texture->mipmaps > 1, real_format, data));
-
- return Ref<Image>(img);
-#else
-
- Image::Format real_format;
- GLenum gl_format;
- GLenum gl_internal_format;
- GLenum gl_type;
- bool compressed;
- _get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, real_format, gl_format, gl_internal_format, gl_type, compressed, texture->resize_to_po2);
-
- PoolVector<uint8_t> data;
-
- int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, Image::FORMAT_RGBA8, false);
-
- data.resize(data_size * 2); //add some memory at the end, just in case for buggy drivers
- PoolVector<uint8_t>::Write wb = data.write();
-
- GLuint temp_framebuffer;
- glGenFramebuffers(1, &temp_framebuffer);
-
- GLuint temp_color_texture;
- glGenTextures(1, &temp_color_texture);
-
- glBindFramebuffer(GL_FRAMEBUFFER, temp_framebuffer);
-
- glBindTexture(GL_TEXTURE_2D, temp_color_texture);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->alloc_width, texture->alloc_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, temp_color_texture, 0);
-
- glDepthMask(GL_FALSE);
- glDisable(GL_DEPTH_TEST);
- glDisable(GL_CULL_FACE);
- glDisable(GL_BLEND);
- glDepthFunc(GL_LEQUAL);
- glColorMask(1, 1, 1, 1);
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, texture->tex_id);
-
- glViewport(0, 0, texture->alloc_width, texture->alloc_height);
-
- shaders.copy.bind();
-
- glClearColor(0.0, 0.0, 0.0, 0.0);
- glClear(GL_COLOR_BUFFER_BIT);
- bind_quad_array();
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
-
- glReadPixels(0, 0, texture->alloc_width, texture->alloc_height, GL_RGBA, GL_UNSIGNED_BYTE, &wb[0]);
-
- glDeleteTextures(1, &temp_color_texture);
-
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
- glDeleteFramebuffers(1, &temp_framebuffer);
-
- wb.release();
-
- data.resize(data_size);
-
- Image *img = memnew(Image(texture->alloc_width, texture->alloc_height, false, Image::FORMAT_RGBA8, data));
- if (!texture->compressed) {
- img->convert(real_format);
- }
-
- return Ref<Image>(img);
-
-#endif
-}
-*/
-
-void RasterizerStorageGLES3::_texture_set_state_from_flags(Texture *p_tex) {
- if ((p_tex->flags & TEXTURE_FLAG_MIPMAPS) && !p_tex->ignore_mipmaps) {
- if (p_tex->flags & TEXTURE_FLAG_FILTER) {
- // these do not exactly correspond ...
- p_tex->GLSetFilter(p_tex->target, RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS);
- //texture->glTexParam_MinFilter(texture->target, config.use_fast_texture_filter ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR_MIPMAP_LINEAR);
- } else {
- p_tex->GLSetFilter(p_tex->target, RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS);
- //texture->glTexParam_MinFilter(texture->target, config.use_fast_texture_filter ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST_MIPMAP_LINEAR);
- }
- } else {
- if (p_tex->flags & TEXTURE_FLAG_FILTER) {
- p_tex->GLSetFilter(p_tex->target, RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR);
- //texture->glTexParam_MinFilter(texture->target, GL_LINEAR);
- } else {
- p_tex->GLSetFilter(p_tex->target, RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST);
- // texture->glTexParam_MinFilter(texture->target, GL_NEAREST);
- }
- }
-
- if (((p_tex->flags & TEXTURE_FLAG_REPEAT) || (p_tex->flags & TEXTURE_FLAG_MIRRORED_REPEAT)) && p_tex->target != GL_TEXTURE_CUBE_MAP) {
- if (p_tex->flags & TEXTURE_FLAG_MIRRORED_REPEAT) {
- p_tex->GLSetRepeat(p_tex->target, RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR);
- } else {
- p_tex->GLSetRepeat(p_tex->target, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- }
- } else {
- p_tex->GLSetRepeat(p_tex->target, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- }
-}
-
-void RasterizerStorageGLES3::texture_set_flags(RID p_texture, uint32_t p_flags) {
- Texture *texture = texture_owner.get_or_null(p_texture);
- ERR_FAIL_COND(!texture);
-
- bool had_mipmaps = texture->flags & TEXTURE_FLAG_MIPMAPS;
-
- texture->flags = p_flags;
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(texture->target, texture->tex_id);
-
- // set filtering and repeat state
- _texture_set_state_from_flags(texture);
-
- if ((texture->flags & TEXTURE_FLAG_MIPMAPS) && !texture->ignore_mipmaps) {
- if (!had_mipmaps && texture->mipmaps == 1) {
- glGenerateMipmap(texture->target);
- }
- }
-}
-
-uint32_t RasterizerStorageGLES3::texture_get_flags(RID p_texture) const {
- Texture *texture = texture_owner.get_or_null(p_texture);
-
- ERR_FAIL_COND_V(!texture, 0);
-
- return texture->flags;
-}
-
-Image::Format RasterizerStorageGLES3::texture_get_format(RID p_texture) const {
- Texture *texture = texture_owner.get_or_null(p_texture);
-
- ERR_FAIL_COND_V(!texture, Image::FORMAT_L8);
-
- return texture->format;
-}
-
-RenderingDevice::TextureType RasterizerStorageGLES3::texture_get_type(RID p_texture) const {
- Texture *texture = texture_owner.get_or_null(p_texture);
-
- ERR_FAIL_COND_V(!texture, RenderingDevice::TEXTURE_TYPE_2D);
-
- return texture->type;
-}
-
-uint32_t RasterizerStorageGLES3::texture_get_texid(RID p_texture) const {
- Texture *texture = texture_owner.get_or_null(p_texture);
-
- ERR_FAIL_COND_V(!texture, 0);
-
- return texture->tex_id;
-}
-
-void RasterizerStorageGLES3::texture_bind(RID p_texture, uint32_t p_texture_no) {
- Texture *texture = texture_owner.get_or_null(p_texture);
-
- ERR_FAIL_COND(!texture);
-
- glActiveTexture(GL_TEXTURE0 + p_texture_no);
- glBindTexture(texture->target, texture->tex_id);
-}
-
-uint32_t RasterizerStorageGLES3::texture_get_width(RID p_texture) const {
- Texture *texture = texture_owner.get_or_null(p_texture);
-
- ERR_FAIL_COND_V(!texture, 0);
-
- return texture->width;
-}
-
-uint32_t RasterizerStorageGLES3::texture_get_height(RID p_texture) const {
- Texture *texture = texture_owner.get_or_null(p_texture);
-
- ERR_FAIL_COND_V(!texture, 0);
-
- return texture->height;
-}
-
-uint32_t RasterizerStorageGLES3::texture_get_depth(RID p_texture) const {
- Texture *texture = texture_owner.get_or_null(p_texture);
-
- ERR_FAIL_COND_V(!texture, 0);
-
- return texture->depth;
-}
-
-void RasterizerStorageGLES3::texture_set_size_override(RID p_texture, int p_width, int p_height) {
- Texture *texture = texture_owner.get_or_null(p_texture);
-
- ERR_FAIL_COND(!texture);
- ERR_FAIL_COND(texture->render_target);
-
- ERR_FAIL_COND(p_width <= 0 || p_width > 16384);
- ERR_FAIL_COND(p_height <= 0 || p_height > 16384);
- //real texture size is in alloc width and height
- texture->width = p_width;
- texture->height = p_height;
-}
-
-void RasterizerStorageGLES3::texture_set_path(RID p_texture, const String &p_path) {
- Texture *texture = texture_owner.get_or_null(p_texture);
- ERR_FAIL_COND(!texture);
-
- texture->path = p_path;
-}
-
-String RasterizerStorageGLES3::texture_get_path(RID p_texture) const {
- Texture *texture = texture_owner.get_or_null(p_texture);
- ERR_FAIL_COND_V(!texture, "");
-
- return texture->path;
-}
-
-void RasterizerStorageGLES3::texture_debug_usage(List<RS::TextureInfo> *r_info) {
- List<RID> textures;
- texture_owner.get_owned_list(&textures);
-
- for (List<RID>::Element *E = textures.front(); E; E = E->next()) {
- Texture *t = texture_owner.get_or_null(E->get());
- if (!t) {
- continue;
- }
- RS::TextureInfo tinfo;
- tinfo.path = t->path;
- tinfo.format = t->format;
- tinfo.width = t->alloc_width;
- tinfo.height = t->alloc_height;
- tinfo.depth = 0;
- tinfo.bytes = t->total_data_size;
- r_info->push_back(tinfo);
- }
-}
-
-void RasterizerStorageGLES3::texture_set_shrink_all_x2_on_set_data(bool p_enable) {
- config.shrink_textures_x2 = p_enable;
-}
-
-void RasterizerStorageGLES3::textures_keep_original(bool p_enable) {
- config.keep_original_textures = p_enable;
-}
-
-Size2 RasterizerStorageGLES3::texture_size_with_proxy(RID p_texture) {
- const Texture *texture = texture_owner.get_or_null(p_texture);
- ERR_FAIL_COND_V(!texture, Size2());
- if (texture->proxy) {
- return Size2(texture->proxy->width, texture->proxy->height);
- } else {
- return Size2(texture->width, texture->height);
- }
-}
-
-// example use in 3.2
-// VS::get_singleton()->texture_set_proxy(default_texture->proxy, texture_rid);
-
-// p_proxy is the source (pre-existing) texture?
-// and p_texture is the one that is being made into a proxy?
-//This naming is confusing. Comments!!!
-
-// The naming of the parameters seemed to be reversed?
-// The p_proxy is the source texture
-// and p_texture is actually the proxy????
-
-void RasterizerStorageGLES3::texture_set_proxy(RID p_texture, RID p_proxy) {
- Texture *texture = texture_owner.get_or_null(p_texture);
- ERR_FAIL_COND(!texture);
-
- if (texture->proxy) {
- texture->proxy->proxy_owners.erase(texture);
- texture->proxy = nullptr;
- }
-
- if (p_proxy.is_valid()) {
- Texture *proxy = texture_owner.get_or_null(p_proxy);
- ERR_FAIL_COND(!proxy);
- ERR_FAIL_COND(proxy == texture);
- proxy->proxy_owners.insert(texture);
- texture->proxy = proxy;
- }
-}
-
-void RasterizerStorageGLES3::texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) {
- Texture *texture = texture_owner.get_or_null(p_texture);
- ERR_FAIL_COND(!texture);
-
- texture->redraw_if_visible = p_enable;
-}
-
-void RasterizerStorageGLES3::texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) {
- Texture *texture = texture_owner.get_or_null(p_texture);
- ERR_FAIL_COND(!texture);
-
- texture->detect_3d = p_callback;
- texture->detect_3d_ud = p_userdata;
-}
-
-void RasterizerStorageGLES3::texture_set_detect_srgb_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) {
- Texture *texture = texture_owner.get_or_null(p_texture);
- ERR_FAIL_COND(!texture);
-
- texture->detect_srgb = p_callback;
- texture->detect_srgb_ud = p_userdata;
-}
-
-void RasterizerStorageGLES3::texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) {
- Texture *texture = texture_owner.get_or_null(p_texture);
- ERR_FAIL_COND(!texture);
-
- texture->detect_normal = p_callback;
- texture->detect_normal_ud = p_userdata;
-}
-
-RID RasterizerStorageGLES3::texture_create_radiance_cubemap(RID p_source, int p_resolution) const {
- return RID();
-}
-
-RID RasterizerStorageGLES3::canvas_texture_allocate() {
- return canvas_texture_owner.allocate_rid();
-}
-
-void RasterizerStorageGLES3::canvas_texture_initialize(RID p_rid) {
- canvas_texture_owner.initialize_rid(p_rid);
-}
-
-void RasterizerStorageGLES3::canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) {
- CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
- switch (p_channel) {
- case RS::CANVAS_TEXTURE_CHANNEL_DIFFUSE: {
- ct->diffuse = p_texture;
- } break;
- case RS::CANVAS_TEXTURE_CHANNEL_NORMAL: {
- ct->normal_map = p_texture;
- } break;
- case RS::CANVAS_TEXTURE_CHANNEL_SPECULAR: {
- ct->specular = p_texture;
- } break;
- }
-}
-
-void RasterizerStorageGLES3::canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_specular_color, float p_shininess) {
- CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
- ct->specular_color.r = p_specular_color.r;
- ct->specular_color.g = p_specular_color.g;
- ct->specular_color.b = p_specular_color.b;
- ct->specular_color.a = p_shininess;
-}
-
-void RasterizerStorageGLES3::canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter) {
- CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
- ct->texture_filter = p_filter;
-}
-void RasterizerStorageGLES3::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat) {
- CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
- ct->texture_repeat = p_repeat;
-}
-
RID RasterizerStorageGLES3::sky_create() {
Sky *sky = memnew(Sky);
sky->radiance = 0;
@@ -1665,7 +453,7 @@ void RasterizerStorageGLES3::shader_get_param_list(RID p_shader, List<PropertyIn
void RasterizerStorageGLES3::shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) {
Shader *shader = shader_owner.get_or_null(p_shader);
ERR_FAIL_COND(!shader);
- ERR_FAIL_COND(p_texture.is_valid() && !texture_owner.owns(p_texture));
+ ERR_FAIL_COND(p_texture.is_valid() && !GLES3::TextureStorage::get_singleton()->owns_texture(p_texture));
if (!p_texture.is_valid()) {
if (shader->default_textures.has(p_name) && shader->default_textures[p_name].has(p_index)) {
@@ -2254,9 +1042,6 @@ void RasterizerStorageGLES3::light_set_param(RID p_light, RS::LightParam p_param
void RasterizerStorageGLES3::light_set_shadow(RID p_light, bool p_enabled) {
}
-void RasterizerStorageGLES3::light_set_shadow_color(RID p_light, const Color &p_color) {
-}
-
void RasterizerStorageGLES3::light_set_projector(RID p_light, RID p_texture) {
}
@@ -2266,6 +1051,9 @@ void RasterizerStorageGLES3::light_set_negative(RID p_light, bool p_enable) {
void RasterizerStorageGLES3::light_set_cull_mask(RID p_light, uint32_t p_mask) {
}
+void RasterizerStorageGLES3::light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) {
+}
+
void RasterizerStorageGLES3::light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) {
}
@@ -2288,11 +1076,11 @@ bool RasterizerStorageGLES3::light_directional_get_blend_splits(RID p_light) con
return false;
}
-void RasterizerStorageGLES3::light_directional_set_sky_only(RID p_light, bool p_sky_only) {
+void RasterizerStorageGLES3::light_directional_set_sky_mode(RID p_light, RS::LightDirectionalSkyMode p_mode) {
}
-bool RasterizerStorageGLES3::light_directional_is_sky_only(RID p_light) const {
- return false;
+RS::LightDirectionalSkyMode RasterizerStorageGLES3::light_directional_get_sky_mode(RID p_light) const {
+ return RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_AND_SKY;
}
RS::LightDirectionalShadowMode RasterizerStorageGLES3::light_directional_get_shadow_mode(RID p_light) {
@@ -2660,6 +1448,9 @@ void RasterizerStorageGLES3::particles_set_use_local_coordinates(RID p_particles
void RasterizerStorageGLES3::particles_set_process_material(RID p_particles, RID p_material) {
}
+RID RasterizerStorageGLES3::particles_get_process_material(RID p_particles) const {
+ return RID();
+}
void RasterizerStorageGLES3::particles_set_fixed_fps(RID p_particles, int p_fps) {
}
@@ -2893,7 +1684,7 @@ bool RasterizerStorageGLES3::particles_is_inactive(RID p_particles) const {
/* RENDER TARGET */
void RasterizerStorageGLES3::_set_current_render_target(RID p_render_target) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
if (rt) {
if (rt->allocate_is_dirty) {
@@ -2919,7 +1710,7 @@ void RasterizerStorageGLES3::_set_current_render_target(RID p_render_target) {
}
}
-void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) {
+void RasterizerStorageGLES3::_render_target_allocate(GLES3::RenderTarget *rt) {
// do not allocate a render target with no size
if (rt->width <= 0 || rt->height <= 0) {
return;
@@ -2960,7 +1751,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) {
{
/* Front FBO */
- Texture *texture = texture_owner.get_or_null(rt->texture);
+ GLES3::Texture *texture = GLES3::TextureStorage::get_singleton()->get_texture(rt->texture);
ERR_FAIL_COND(!texture);
// framebuffer
@@ -2973,7 +1764,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) {
glTexImage2D(GL_TEXTURE_2D, 0, color_internal_format, rt->width, rt->height, 0, color_format, color_type, nullptr);
- if (texture->flags & TEXTURE_FLAG_FILTER) {
+ if (texture->flags & GLES3::TEXTURE_FLAG_FILTER) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
} else {
@@ -2988,10 +1779,10 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) {
// depth
- if (config.support_depth_texture) {
+ if (config->support_depth_texture) {
glGenTextures(1, &rt->depth);
glBindTexture(GL_TEXTURE_2D, rt->depth);
- glTexImage2D(GL_TEXTURE_2D, 0, config.depth_internalformat, rt->width, rt->height, 0, GL_DEPTH_COMPONENT, config.depth_type, nullptr);
+ glTexImage2D(GL_TEXTURE_2D, 0, config->depth_internalformat, rt->width, rt->height, 0, GL_DEPTH_COMPONENT, config->depth_type, nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
@@ -3003,7 +1794,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) {
glGenRenderbuffers(1, &rt->depth);
glBindRenderbuffer(GL_RENDERBUFFER, rt->depth);
- glRenderbufferStorage(GL_RENDERBUFFER, config.depth_buffer_internalformat, rt->width, rt->height);
+ glRenderbufferStorage(GL_RENDERBUFFER, config->depth_buffer_internalformat, rt->width, rt->height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth);
}
@@ -3012,7 +1803,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) {
if (status != GL_FRAMEBUFFER_COMPLETE) {
glDeleteFramebuffers(1, &rt->fbo);
- if (config.support_depth_texture) {
+ if (config->support_depth_texture) {
glDeleteTextures(1, &rt->depth);
} else {
glDeleteRenderbuffers(1, &rt->depth);
@@ -3041,7 +1832,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) {
texture->alloc_height = rt->height;
texture->active = true;
- texture_set_flags(rt->texture, texture->flags);
+ GLES3::TextureStorage::get_singleton()->texture_set_flags(rt->texture, texture->flags);
}
/* BACK FBO */
@@ -3067,7 +1858,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) {
glGenRenderbuffers(1, &rt->multisample_depth);
glBindRenderbuffer(GL_RENDERBUFFER, rt->multisample_depth);
- glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, config.depth_buffer_internalformat, rt->width, rt->height);
+ glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, config->depth_buffer_internalformat, rt->width, rt->height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->multisample_depth);
@@ -3156,7 +1947,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) {
int fb_h = h;
while (true) {
- RenderTarget::MipMaps::Size mm;
+ GLES3::RenderTarget::MipMaps::Size mm;
mm.width = w;
mm.height = h;
rt->mip_maps[i].sizes.push_back(mm);
@@ -3174,7 +1965,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) {
GLsizei width = fb_w;
GLsizei height = fb_h;
- if (config.render_to_mipmap_supported) {
+ if (config->render_to_mipmap_supported) {
glGenTextures(1, &rt->mip_maps[i].color);
glBindTexture(GL_TEXTURE_2D, rt->mip_maps[i].color);
@@ -3207,12 +1998,12 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) {
glDepthMask(GL_TRUE);
for (int j = 0; j < rt->mip_maps[i].sizes.size(); j++) {
- RenderTarget::MipMaps::Size &mm = rt->mip_maps[i].sizes.write[j];
+ GLES3::RenderTarget::MipMaps::Size &mm = rt->mip_maps[i].sizes.write[j];
glGenFramebuffers(1, &mm.fbo);
bind_framebuffer(mm.fbo);
- if (config.render_to_mipmap_supported) {
+ if (config->render_to_mipmap_supported) {
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->mip_maps[i].color, j);
} else {
glBindTexture(GL_TEXTURE_2D, rt->mip_maps[i].sizes[j].color);
@@ -3221,7 +2012,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) {
bool used_depth = false;
if (j == 0 && i == 0) { //use always
- if (config.support_depth_texture) {
+ if (config->support_depth_texture) {
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rt->depth, 0);
} else {
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth);
@@ -3246,7 +2037,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) {
rt->mip_maps[i].levels = level;
- if (config.render_to_mipmap_supported) {
+ if (config->render_to_mipmap_supported) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
@@ -3259,7 +2050,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) {
bind_framebuffer_system();
}
-void RasterizerStorageGLES3::_render_target_clear(RenderTarget *rt) {
+void RasterizerStorageGLES3::_render_target_clear(GLES3::RenderTarget *rt) {
// there is nothing to clear when DIRECT_TO_SCREEN is used
if (rt->flags[RENDER_TARGET_DIRECT_TO_SCREEN]) {
return;
@@ -3276,20 +2067,20 @@ void RasterizerStorageGLES3::_render_target_clear(RenderTarget *rt) {
glDeleteFramebuffers(1, &rt->external.fbo);
// clean up our texture
- Texture *t = texture_owner.get_or_null(rt->external.texture);
+ GLES3::Texture *t = GLES3::TextureStorage::get_singleton()->get_texture(rt->external.texture);
t->alloc_height = 0;
t->alloc_width = 0;
t->width = 0;
t->height = 0;
t->active = false;
- texture_owner.free(rt->external.texture);
+ GLES3::TextureStorage::get_singleton()->texture_free(rt->external.texture);
memdelete(t);
rt->external.fbo = 0;
}
if (rt->depth) {
- if (config.support_depth_texture) {
+ if (config->support_depth_texture) {
glDeleteTextures(1, &rt->depth);
} else {
glDeleteRenderbuffers(1, &rt->depth);
@@ -3298,7 +2089,7 @@ void RasterizerStorageGLES3::_render_target_clear(RenderTarget *rt) {
rt->depth = 0;
}
- Texture *tex = texture_owner.get_or_null(rt->texture);
+ GLES3::Texture *tex = GLES3::TextureStorage::get_singleton()->get_texture(rt->texture);
tex->alloc_height = 0;
tex->alloc_width = 0;
tex->width = 0;
@@ -3341,8 +2132,8 @@ void RasterizerStorageGLES3::_render_target_clear(RenderTarget *rt) {
}
RID RasterizerStorageGLES3::render_target_create() {
- RenderTarget *rt = memnew(RenderTarget);
- Texture *t = memnew(Texture);
+ GLES3::RenderTarget *rt = memnew(GLES3::RenderTarget);
+ GLES3::Texture *t = memnew(GLES3::Texture);
t->type = RenderingDevice::TEXTURE_TYPE_2D;
t->flags = 0;
@@ -3364,12 +2155,12 @@ RID RasterizerStorageGLES3::render_target_create() {
t->tex_id = 0;
t->render_target = rt;
- rt->texture = texture_owner.make_rid(t);
+ rt->texture = GLES3::TextureStorage::get_singleton()->make_rid(t);
return render_target_owner.make_rid(rt);
}
void RasterizerStorageGLES3::render_target_set_position(RID p_render_target, int p_x, int p_y) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND(!rt);
rt->x = p_x;
@@ -3377,7 +2168,7 @@ void RasterizerStorageGLES3::render_target_set_position(RID p_render_target, int
}
void RasterizerStorageGLES3::render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND(!rt);
if (p_width == rt->width && p_height == rt->height) {
@@ -3397,14 +2188,14 @@ void RasterizerStorageGLES3::render_target_set_size(RID p_render_target, int p_w
// TODO: convert to Size2i internally
Size2i RasterizerStorageGLES3::render_target_get_size(RID p_render_target) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND_V(!rt, Size2());
return Size2i(rt->width, rt->height);
}
RID RasterizerStorageGLES3::render_target_get_texture(RID p_render_target) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND_V(!rt, RID());
if (rt->external.fbo == 0) {
@@ -3415,7 +2206,7 @@ RID RasterizerStorageGLES3::render_target_get_texture(RID p_render_target) {
}
void RasterizerStorageGLES3::render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND(!rt);
if (p_texture_id == 0) {
@@ -3429,13 +2220,13 @@ void RasterizerStorageGLES3::render_target_set_external_texture(RID p_render_tar
}
// clean up our texture
- Texture *t = texture_owner.get_or_null(rt->external.texture);
+ GLES3::Texture *t = GLES3::TextureStorage::get_singleton()->get_texture(rt->external.texture);
t->alloc_height = 0;
t->alloc_width = 0;
t->width = 0;
t->height = 0;
t->active = false;
- texture_owner.free(rt->external.texture);
+ GLES3::TextureStorage::get_singleton()->texture_free(rt->external.texture);
memdelete(t);
rt->external.fbo = 0;
@@ -3443,7 +2234,7 @@ void RasterizerStorageGLES3::render_target_set_external_texture(RID p_render_tar
rt->external.depth = 0;
}
} else {
- Texture *t;
+ GLES3::Texture *t;
if (rt->external.fbo == 0) {
// create our fbo
@@ -3451,7 +2242,7 @@ void RasterizerStorageGLES3::render_target_set_external_texture(RID p_render_tar
bind_framebuffer(rt->external.fbo);
// allocate a texture
- t = memnew(Texture);
+ t = memnew(GLES3::Texture);
t->type = RenderingDevice::TEXTURE_TYPE_2D;
t->flags = 0;
@@ -3474,14 +2265,14 @@ void RasterizerStorageGLES3::render_target_set_external_texture(RID p_render_tar
t->tex_id = 0;
t->render_target = rt;
- rt->external.texture = texture_owner.make_rid(t);
+ rt->external.texture = GLES3::TextureStorage::get_singleton()->make_rid(t);
} else {
// bind our frame buffer
bind_framebuffer(rt->external.fbo);
// find our texture
- t = texture_owner.get_or_null(rt->external.texture);
+ t = GLES3::TextureStorage::get_singleton()->get_texture(rt->external.texture);
}
// set our texture
@@ -3500,7 +2291,7 @@ void RasterizerStorageGLES3::render_target_set_external_texture(RID p_render_tar
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, p_texture_id, 0);
// seeing we're rendering into this directly, better also use our depth buffer, just use our existing one :)
- if (config.support_depth_texture) {
+ if (config->support_depth_texture) {
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rt->depth, 0);
} else {
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth);
@@ -3520,7 +2311,7 @@ void RasterizerStorageGLES3::render_target_set_external_texture(RID p_render_tar
}
void RasterizerStorageGLES3::render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND(!rt);
// When setting DIRECT_TO_SCREEN, you need to clear before the value is set, but allocate after as
@@ -3552,21 +2343,21 @@ void RasterizerStorageGLES3::render_target_set_flag(RID p_render_target, RenderT
}
bool RasterizerStorageGLES3::render_target_was_used(RID p_render_target) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND_V(!rt, false);
return rt->used_in_frame;
}
void RasterizerStorageGLES3::render_target_clear_used(RID p_render_target) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND(!rt);
rt->used_in_frame = false;
}
void RasterizerStorageGLES3::render_target_set_msaa(RID p_render_target, RS::ViewportMSAA p_msaa) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND(!rt);
if (rt->msaa == p_msaa) {
@@ -3578,20 +2369,20 @@ void RasterizerStorageGLES3::render_target_set_msaa(RID p_render_target, RS::Vie
_render_target_allocate(rt);
}
-//RasterizerStorageGLES3::RenderTarget * RasterizerStorageGLES3::render_target_get(RID p_render_target)
+//RasterizerStorageGLES3::GLES3::RenderTarget * RasterizerStorageGLES3::render_target_get(RID p_render_target)
//{
// return render_target_owner.get_or_null(p_render_target);
//}
void RasterizerStorageGLES3::render_target_set_use_fxaa(RID p_render_target, bool p_fxaa) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND(!rt);
rt->use_fxaa = p_fxaa;
}
void RasterizerStorageGLES3::render_target_set_use_debanding(RID p_render_target, bool p_debanding) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND(!rt);
if (p_debanding) {
@@ -3602,7 +2393,7 @@ void RasterizerStorageGLES3::render_target_set_use_debanding(RID p_render_target
}
void RasterizerStorageGLES3::render_target_request_clear(RID p_render_target, const Color &p_clear_color) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND(!rt);
rt->clear_requested = true;
rt->clear_color = p_clear_color;
@@ -3613,18 +2404,18 @@ void RasterizerStorageGLES3::render_target_request_clear(RID p_render_target, co
}
bool RasterizerStorageGLES3::render_target_is_clear_requested(RID p_render_target) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND_V(!rt, false);
return rt->clear_requested;
}
Color RasterizerStorageGLES3::render_target_get_clear_request_color(RID p_render_target) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND_V(!rt, Color());
return rt->clear_color;
}
void RasterizerStorageGLES3::render_target_disable_clear_request(RID p_render_target) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND(!rt);
rt->clear_requested = false;
}
@@ -3647,8 +2438,8 @@ void RasterizerStorageGLES3::render_target_mark_sdf_enabled(RID p_render_target,
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;
+ if (p_width > config->max_texture_size) {
+ p_width = config->max_texture_size;
}
cls->size = p_width;
@@ -3661,12 +2452,12 @@ RID RasterizerStorageGLES3::canvas_light_shadow_buffer_create(int p_width) {
glGenRenderbuffers(1, &cls->depth);
glBindRenderbuffer(GL_RENDERBUFFER, cls->depth);
- glRenderbufferStorage(GL_RENDERBUFFER, config.depth_buffer_internalformat, cls->size, cls->height);
+ glRenderbufferStorage(GL_RENDERBUFFER, config->depth_buffer_internalformat, 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) {
+ if (config->use_rgba_2d_shadows) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, cls->size, cls->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
} else {
#ifdef GLES_OVER_GL
@@ -3713,10 +2504,11 @@ void RasterizerStorageGLES3::canvas_light_occluder_set_polylines(RID p_occluder,
co->lines = p_lines;
if (p_lines.size() != co->len) {
- if (co->index_id)
+ if (co->index_id) {
glDeleteBuffers(1, &co->index_id);
- if (co->vertex_id)
+ } if (co->vertex_id) {
glDeleteBuffers(1, &co->vertex_id);
+ }
co->index_id = 0;
co->vertex_id = 0;
@@ -3817,33 +2609,23 @@ RS::InstanceType RasterizerStorageGLES3::get_base_type(RID p_rid) const {
bool RasterizerStorageGLES3::free(RID p_rid) {
if (render_target_owner.owns(p_rid)) {
- RenderTarget *rt = render_target_owner.get_or_null(p_rid);
+ GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_rid);
_render_target_clear(rt);
- Texture *t = texture_owner.get_or_null(rt->texture);
+ GLES3::Texture *t = GLES3::TextureStorage::get_singleton()->get_texture(rt->texture);
if (t) {
- texture_owner.free(rt->texture);
+ GLES3::TextureStorage::get_singleton()->texture_free(rt->texture);
memdelete(t);
}
render_target_owner.free(p_rid);
memdelete(rt);
return true;
- } else if (texture_owner.owns(p_rid)) {
- Texture *t = texture_owner.get_or_null(p_rid);
- // can't free a render target texture
- ERR_FAIL_COND_V(t->render_target, true);
- if (t->canvas_texture) {
- memdelete(t->canvas_texture);
- }
-
- info.texture_mem -= t->total_data_size;
- texture_owner.free(p_rid);
- memdelete(t);
-
+ } else if (GLES3::TextureStorage::get_singleton()->owns_texture(p_rid)) {
+ GLES3::TextureStorage::get_singleton()->texture_free(p_rid);
return true;
- } else if (canvas_texture_owner.owns(p_rid)) {
- canvas_texture_owner.free(p_rid);
+ } else if (GLES3::CanvasTextureStorage::get_singleton()->owns_canvas_texture(p_rid)) {
+ GLES3::CanvasTextureStorage::get_singleton()->canvas_texture_free(p_rid);
return true;
} else if (sky_owner.owns(p_rid)) {
Sky *sky = sky_owner.get_or_null(p_rid);
@@ -4011,10 +2793,12 @@ bool RasterizerStorageGLES3::free(RID p_rid) {
} else if (canvas_occluder_owner.owns(p_rid)) {
CanvasOccluder *co = canvas_occluder_owner.get_or_null(p_rid);
- if (co->index_id)
+ if (co->index_id) {
glDeleteBuffers(1, &co->index_id);
- if (co->vertex_id)
+ }
+ if (co->vertex_id) {
glDeleteBuffers(1, &co->vertex_id);
+ }
canvas_occluder_owner.free(p_rid);
memdelete(co);
@@ -4035,15 +2819,15 @@ bool RasterizerStorageGLES3::free(RID p_rid) {
bool RasterizerStorageGLES3::has_os_feature(const String &p_feature) const {
if (p_feature == "s3tc") {
- return config.s3tc_supported;
+ return config->s3tc_supported;
}
if (p_feature == "etc") {
- return config.etc_supported;
+ return config->etc_supported;
}
if (p_feature == "skinning_fallback") {
- return config.use_skeleton_software;
+ return config->use_skeleton_software;
}
return false;
@@ -4150,105 +2934,11 @@ RenderingDevice::DeviceType RasterizerStorageGLES3::get_video_adapter_type() con
void RasterizerStorageGLES3::initialize() {
RasterizerStorageGLES3::system_fbo = 0;
+ config = GLES3::Config::get_singleton();
+ config->initialize();
- {
- const GLubyte *extension_string = glGetString(GL_EXTENSIONS);
-
- Vector<String> extensions = String((const char *)extension_string).split(" ");
-
- for (int i = 0; i < extensions.size(); i++) {
- config.extensions.insert(extensions[i]);
- }
- }
-
- config.keep_original_textures = true; // false
- config.shrink_textures_x2 = false;
- config.depth_internalformat = GL_DEPTH_COMPONENT;
- config.depth_type = GL_UNSIGNED_INT;
-
-#ifdef GLES_OVER_GL
- config.float_texture_supported = true;
- config.s3tc_supported = true;
- config.etc_supported = false;
- config.support_npot_repeat_mipmap = true;
- config.depth_buffer_internalformat = GL_DEPTH_COMPONENT24;
-#else
- config.float_texture_supported = config.extensions.has("GL_ARB_texture_float") || config.extensions.has("GL_OES_texture_float");
- config.s3tc_supported = config.extensions.has("GL_EXT_texture_compression_s3tc") || config.extensions.has("WEBGL_compressed_texture_s3tc");
- config.etc_supported = config.extensions.has("GL_OES_compressed_ETC1_RGB8_texture") || config.extensions.has("WEBGL_compressed_texture_etc1");
- config.support_npot_repeat_mipmap = config.extensions.has("GL_OES_texture_npot");
-
-#ifdef JAVASCRIPT_ENABLED
- // RenderBuffer internal format must be 16 bits in WebGL,
- // but depth_texture should default to 32 always
- // if the implementation doesn't support 32, it should just quietly use 16 instead
- // https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/
- config.depth_buffer_internalformat = GL_DEPTH_COMPONENT16;
- config.depth_type = GL_UNSIGNED_INT;
-#else
- // on mobile check for 24 bit depth support for RenderBufferStorage
- if (config.extensions.has("GL_OES_depth24")) {
- config.depth_buffer_internalformat = _DEPTH_COMPONENT24_OES;
- config.depth_type = GL_UNSIGNED_INT;
- } else {
- config.depth_buffer_internalformat = GL_DEPTH_COMPONENT16;
- config.depth_type = GL_UNSIGNED_SHORT;
- }
-#endif
-#endif
-
-#ifdef GLES_OVER_GL
- //TODO: causes huge problems with desktop video drivers. Making false for now, needs to be true to render SCREEN_TEXTURE mipmaps
- config.render_to_mipmap_supported = false;
-#else
- //check if mipmaps can be used for SCREEN_TEXTURE and Glow on Mobile and web platforms
- config.render_to_mipmap_supported = config.extensions.has("GL_OES_fbo_render_mipmap") && config.extensions.has("GL_EXT_texture_lod");
-#endif
-
-#ifdef GLES_OVER_GL
- config.use_rgba_2d_shadows = false;
- config.support_depth_texture = true;
- config.use_rgba_3d_shadows = false;
- config.support_depth_cubemaps = true;
-#else
- config.use_rgba_2d_shadows = !(config.float_texture_supported && config.extensions.has("GL_EXT_texture_rg"));
- config.support_depth_texture = config.extensions.has("GL_OES_depth_texture") || config.extensions.has("WEBGL_depth_texture");
- config.use_rgba_3d_shadows = !config.support_depth_texture;
- config.support_depth_cubemaps = config.extensions.has("GL_OES_depth_texture_cube_map");
-#endif
-
-#ifdef GLES_OVER_GL
- config.support_32_bits_indices = true;
-#else
- config.support_32_bits_indices = config.extensions.has("GL_OES_element_index_uint");
-#endif
-
-#ifdef GLES_OVER_GL
- config.support_write_depth = true;
-#elif defined(JAVASCRIPT_ENABLED)
- config.support_write_depth = false;
-#else
- config.support_write_depth = config.extensions.has("GL_EXT_frag_depth");
-#endif
-
- config.support_half_float_vertices = true;
-//every platform should support this except web, iOS has issues with their support, so add option to disable
-#ifdef JAVASCRIPT_ENABLED
- config.support_half_float_vertices = false;
-#endif
- bool disable_half_float = false; //GLOBAL_GET("rendering/opengl/compatibility/disable_half_float");
- if (disable_half_float) {
- config.support_half_float_vertices = false;
- }
-
- config.etc_supported = config.extensions.has("GL_OES_compressed_ETC1_RGB8_texture");
- config.latc_supported = config.extensions.has("GL_EXT_texture_compression_latc");
- config.bptc_supported = config.extensions.has("GL_ARB_texture_compression_bptc");
- config.rgtc_supported = config.extensions.has("GL_EXT_texture_compression_rgtc") || config.extensions.has("GL_ARB_texture_compression_rgtc") || config.extensions.has("EXT_texture_compression_rgtc");
- config.bptc_supported = config.extensions.has("GL_ARB_texture_compression_bptc") || config.extensions.has("EXT_texture_compression_bptc");
- config.srgb_decode_supported = config.extensions.has("GL_EXT_texture_sRGB_decode");
//determine formats for depth textures (or renderbuffers)
- if (config.support_depth_texture) {
+ if (config->support_depth_texture) {
// Will use texture for depth
// have to manually see if we can create a valid framebuffer texture using UNSIGNED_INT,
// as there is no extension to test for this.
@@ -4258,7 +2948,7 @@ void RasterizerStorageGLES3::initialize() {
GLuint depth;
glGenTextures(1, &depth);
glBindTexture(GL_TEXTURE_2D, depth);
- glTexImage2D(GL_TEXTURE_2D, 0, config.depth_internalformat, 32, 32, 0, GL_DEPTH_COMPONENT, config.depth_type, nullptr);
+ glTexImage2D(GL_TEXTURE_2D, 0, config->depth_internalformat, 32, 32, 0, GL_DEPTH_COMPONENT, config->depth_type, nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
@@ -4278,19 +2968,19 @@ void RasterizerStorageGLES3::initialize() {
// If it fails, test to see if it supports a framebuffer texture using UNSIGNED_SHORT
// This is needed because many OSX devices don't support either UNSIGNED_INT or UNSIGNED_SHORT
#ifdef GLES_OVER_GL
- config.depth_internalformat = GL_DEPTH_COMPONENT16;
+ config->depth_internalformat = GL_DEPTH_COMPONENT16;
#else
// OES_depth_texture extension only specifies GL_DEPTH_COMPONENT.
- config.depth_internalformat = GL_DEPTH_COMPONENT;
+ config->depth_internalformat = GL_DEPTH_COMPONENT;
#endif
- config.depth_type = GL_UNSIGNED_SHORT;
+ config->depth_type = GL_UNSIGNED_SHORT;
glGenFramebuffers(1, &fbo);
bind_framebuffer(fbo);
glGenTextures(1, &depth);
glBindTexture(GL_TEXTURE_2D, depth);
- glTexImage2D(GL_TEXTURE_2D, 0, config.depth_internalformat, 32, 32, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, nullptr);
+ glTexImage2D(GL_TEXTURE_2D, 0, config->depth_internalformat, 32, 32, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
@@ -4302,8 +2992,8 @@ void RasterizerStorageGLES3::initialize() {
status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
//if it fails again depth textures aren't supported, use rgba shadows and renderbuffer for depth
- config.support_depth_texture = false;
- config.use_rgba_3d_shadows = true;
+ config->support_depth_texture = false;
+ config->use_rgba_3d_shadows = true;
}
bind_framebuffer_system();
@@ -4314,20 +3004,16 @@ void RasterizerStorageGLES3::initialize() {
}
//picky requirements for these
- config.support_shadow_cubemaps = config.support_depth_texture && config.support_write_depth && config.support_depth_cubemaps;
+ config->support_shadow_cubemaps = config->support_depth_texture && config->support_write_depth && config->support_depth_cubemaps;
frame.count = 0;
frame.delta = 0;
frame.current_rt = nullptr;
frame.clear_request = false;
- glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &config.max_vertex_texture_image_units);
- glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &config.max_texture_image_units);
- glGetIntegerv(GL_MAX_TEXTURE_SIZE, &config.max_texture_size);
-
// the use skeleton software path should be used if either float texture is not supported,
// OR max_vertex_texture_image_units is zero
- config.use_skeleton_software = (config.float_texture_supported == false) || (config.max_vertex_texture_image_units == 0);
+ config->use_skeleton_software = (config->float_texture_supported == false) || (config->max_vertex_texture_image_units == 0);
shaders.copy.initialize();
shaders.copy_version = shaders.copy.version_create(); //TODO
@@ -4431,7 +3117,7 @@ void RasterizerStorageGLES3::initialize() {
// radical inverse vdc cache texture
// used for cubemap filtering
- if (true /*||config.float_texture_supported*/) { //uint8 is similar and works everywhere
+ if (true /*||config->float_texture_supported*/) { //uint8 is similar and works everywhere
glGenTextures(1, &resources.radical_inverse_vdc_cache_tex);
glActiveTexture(GL_TEXTURE0);
@@ -4469,16 +3155,12 @@ void RasterizerStorageGLES3::initialize() {
#ifdef GLES_OVER_GL
//this needs to be enabled manually in OpenGL 2.1
- if (config.extensions.has("GL_ARB_seamless_cube_map")) {
+ if (config->extensions.has("GL_ARB_seamless_cube_map")) {
glEnable(_EXT_TEXTURE_CUBE_MAP_SEAMLESS);
}
glEnable(GL_POINT_SPRITE);
glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
#endif
-
- config.force_vertex_shading = false; //GLOBAL_GET("rendering/quality/shading/force_vertex_shading");
- config.use_fast_texture_filter = false; //GLOBAL_GET("rendering/quality/filters/use_nearest_mipmap_filter");
- //config.should_orphan = GLOBAL_GET("rendering/options/api_usage_legacy/orphan_buffers");
}
void RasterizerStorageGLES3::finalize() {
@@ -4505,7 +3187,6 @@ void RasterizerStorageGLES3::update_dirty_resources() {
RasterizerStorageGLES3::RasterizerStorageGLES3() {
RasterizerStorageGLES3::system_fbo = 0;
- config.should_orphan = true;
}
RasterizerStorageGLES3::~RasterizerStorageGLES3() {
diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h
index 0dfc909777..96daed581b 100644
--- a/drivers/gles3/rasterizer_storage_gles3.h
+++ b/drivers/gles3/rasterizer_storage_gles3.h
@@ -40,6 +40,10 @@
#include "servers/rendering/renderer_storage.h"
#include "servers/rendering/shader_compiler.h"
#include "servers/rendering/shader_language.h"
+#include "storage/canvas_texture_storage.h"
+#include "storage/config.h"
+#include "storage/render_target_storage.h"
+#include "storage/texture_storage.h"
#include "shaders/copy.glsl.gen.h"
@@ -47,66 +51,13 @@ class RasterizerCanvasGLES3;
class RasterizerSceneGLES3;
class RasterizerStorageGLES3 : public RendererStorage {
- friend class RasterizerGLES3;
-
- Thread::ID _main_thread_id = 0;
- bool _is_main_thread();
-
public:
RasterizerCanvasGLES3 *canvas;
RasterizerSceneGLES3 *scene;
static GLuint system_fbo;
- struct Config {
- bool shrink_textures_x2;
- bool use_fast_texture_filter;
- bool use_skeleton_software;
-
- int max_vertex_texture_image_units;
- int max_texture_image_units;
- int max_texture_size;
-
- // TODO implement wireframe in OpenGL
- // bool generate_wireframes;
-
- Set<String> extensions;
-
- bool float_texture_supported;
- bool s3tc_supported;
- bool latc_supported;
- bool rgtc_supported;
- bool bptc_supported;
- bool etc_supported;
- bool etc2_supported;
- bool srgb_decode_supported;
-
- bool keep_original_textures;
-
- bool force_vertex_shading;
-
- bool use_rgba_2d_shadows;
- bool use_rgba_3d_shadows;
-
- bool support_32_bits_indices;
- bool support_write_depth;
- bool support_half_float_vertices;
- bool support_npot_repeat_mipmap;
- bool support_depth_texture;
- bool support_depth_cubemaps;
-
- bool support_shadow_cubemaps;
-
- bool render_to_mipmap_supported;
-
- GLuint depth_internalformat;
- GLuint depth_type;
- GLuint depth_buffer_internalformat;
-
- // in some cases the legacy render didn't orphan. We will mark these
- // so the user can switch orphaning off for them.
- bool should_orphan;
- } config;
+ GLES3::Config *config;
struct Resources {
GLuint white_tex;
@@ -180,334 +131,7 @@ public:
//////////////////////////////////API////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
- bool can_create_resources_async() const override;
-
- // TEXTURE API
-
- enum OpenGLTextureFlags {
- TEXTURE_FLAG_MIPMAPS = 1, /// Enable automatic mipmap generation - when available
- TEXTURE_FLAG_REPEAT = 2, /// Repeat texture (Tiling), otherwise Clamping
- TEXTURE_FLAG_FILTER = 4, /// Create texture with linear (or available) filter
- TEXTURE_FLAG_ANISOTROPIC_FILTER = 8,
- TEXTURE_FLAG_CONVERT_TO_LINEAR = 16,
- TEXTURE_FLAG_MIRRORED_REPEAT = 32, /// Repeat texture, with alternate sections mirrored
- TEXTURE_FLAG_USED_FOR_STREAMING = 2048,
- TEXTURE_FLAGS_DEFAULT = TEXTURE_FLAG_REPEAT | TEXTURE_FLAG_MIPMAPS | TEXTURE_FLAG_FILTER
- };
-
- /* CANVAS TEXTURE API (2D) */
-
- struct CanvasTexture {
- RID diffuse;
- RID normal_map;
- RID specular;
- Color specular_color = Color(1, 1, 1, 1);
- float shininess = 1.0;
-
- RS::CanvasItemTextureFilter texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT;
- RS::CanvasItemTextureRepeat texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT;
-
- Size2i size_cache = Size2i(1, 1);
- bool use_normal_cache = false;
- bool use_specular_cache = false;
- bool cleared_cache = true;
- };
-
- RID_Owner<CanvasTexture, true> canvas_texture_owner;
-
- struct RenderTarget;
-
- struct Texture {
- RID self;
-
- Texture *proxy;
- Set<Texture *> proxy_owners;
-
- String path;
- uint32_t flags;
- int width, height, depth;
- int alloc_width, alloc_height;
- Image::Format format;
- RenderingDevice::TextureType type;
-
- GLenum target;
- GLenum gl_format_cache;
- GLenum gl_internal_format_cache;
- GLenum gl_type_cache;
-
- int data_size;
- int total_data_size;
- bool ignore_mipmaps;
-
- bool compressed;
-
- bool srgb;
-
- int mipmaps;
-
- bool resize_to_po2;
-
- bool active;
- GLenum tex_id;
-
- uint16_t stored_cube_sides;
-
- RenderTarget *render_target;
-
- Vector<Ref<Image>> images;
-
- bool redraw_if_visible;
-
- RS::TextureDetectCallback detect_3d;
- void *detect_3d_ud;
-
- RS::TextureDetectCallback detect_srgb;
- void *detect_srgb_ud;
-
- RS::TextureDetectCallback detect_normal;
- void *detect_normal_ud;
-
- CanvasTexture *canvas_texture = nullptr;
-
- // some silly opengl shenanigans where
- // texture coords start from bottom left, means we need to draw render target textures upside down
- // to be compatible with vulkan etc.
- bool is_upside_down() const {
- if (proxy) {
- return proxy->is_upside_down();
- }
-
- return render_target != nullptr;
- }
-
- Texture() {
- create();
- }
-
- _ALWAYS_INLINE_ Texture *get_ptr() {
- if (proxy) {
- return proxy; //->get_ptr(); only one level of indirection, else not inlining possible.
- } else {
- return this;
- }
- }
-
- ~Texture() {
- destroy();
-
- if (tex_id != 0) {
- glDeleteTextures(1, &tex_id);
- }
- }
-
- void copy_from(const Texture &o) {
- proxy = o.proxy;
- flags = o.flags;
- width = o.width;
- height = o.height;
- alloc_width = o.alloc_width;
- alloc_height = o.alloc_height;
- format = o.format;
- type = o.type;
- target = o.target;
- data_size = o.data_size;
- total_data_size = o.total_data_size;
- ignore_mipmaps = o.ignore_mipmaps;
- compressed = o.compressed;
- mipmaps = o.mipmaps;
- resize_to_po2 = o.resize_to_po2;
- active = o.active;
- tex_id = o.tex_id;
- stored_cube_sides = o.stored_cube_sides;
- render_target = o.render_target;
- redraw_if_visible = o.redraw_if_visible;
- detect_3d = o.detect_3d;
- detect_3d_ud = o.detect_3d_ud;
- detect_srgb = o.detect_srgb;
- detect_srgb_ud = o.detect_srgb_ud;
- detect_normal = o.detect_normal;
- detect_normal_ud = o.detect_normal_ud;
-
- images.clear();
- }
-
- void create() {
- proxy = nullptr;
- flags = 0;
- width = 0;
- height = 0;
- alloc_width = 0;
- alloc_height = 0;
- format = Image::FORMAT_L8;
- type = RenderingDevice::TEXTURE_TYPE_2D;
- target = 0;
- data_size = 0;
- total_data_size = 0;
- ignore_mipmaps = false;
- compressed = false;
- mipmaps = 0;
- resize_to_po2 = false;
- active = false;
- tex_id = 0;
- stored_cube_sides = 0;
- render_target = nullptr;
- redraw_if_visible = false;
- detect_3d = nullptr;
- detect_3d_ud = nullptr;
- detect_srgb = nullptr;
- detect_srgb_ud = nullptr;
- detect_normal = nullptr;
- detect_normal_ud = nullptr;
- }
- void destroy() {
- images.clear();
-
- for (Set<Texture *>::Element *E = proxy_owners.front(); E; E = E->next()) {
- E->get()->proxy = nullptr;
- }
-
- if (proxy) {
- proxy->proxy_owners.erase(this);
- }
- }
-
- // texture state
- void GLSetFilter(GLenum p_target, RS::CanvasItemTextureFilter p_filter) {
- if (p_filter == state_filter) {
- return;
- }
- state_filter = p_filter;
- GLint pmin = GL_LINEAR; // param min
- GLint pmag = GL_LINEAR; // param mag
- switch (state_filter) {
- default: {
- } break;
- case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: {
- pmin = GL_LINEAR_MIPMAP_LINEAR;
- pmag = GL_LINEAR;
- } break;
- case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST: {
- pmin = GL_NEAREST;
- pmag = GL_NEAREST;
- } break;
- case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: {
- pmin = GL_NEAREST_MIPMAP_NEAREST;
- pmag = GL_NEAREST;
- } break;
- }
- glTexParameteri(p_target, GL_TEXTURE_MIN_FILTER, pmin);
- glTexParameteri(p_target, GL_TEXTURE_MAG_FILTER, pmag);
- }
- void GLSetRepeat(GLenum p_target, RS::CanvasItemTextureRepeat p_repeat) {
- if (p_repeat == state_repeat) {
- return;
- }
- state_repeat = p_repeat;
- GLint prep = GL_CLAMP_TO_EDGE; // parameter repeat
- switch (state_repeat) {
- default: {
- } break;
- case RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED: {
- prep = GL_REPEAT;
- } break;
- case RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR: {
- prep = GL_MIRRORED_REPEAT;
- } break;
- }
- glTexParameteri(p_target, GL_TEXTURE_WRAP_S, prep);
- glTexParameteri(p_target, GL_TEXTURE_WRAP_T, prep);
- }
-
- private:
- RS::CanvasItemTextureFilter state_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR;
- RS::CanvasItemTextureRepeat state_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED;
- };
-
- mutable RID_PtrOwner<Texture> texture_owner;
-
- Ref<Image> _get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, 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;
-
- void _texture_set_state_from_flags(Texture *p_tex);
-
- // new
- RID texture_allocate() override;
- void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) override;
- void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) override;
- void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) override;
- void texture_proxy_initialize(RID p_texture, RID p_base) override; //all slices, then all the mipmaps, must be coherent
-
- void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override;
- void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) override {}
- void texture_proxy_update(RID p_proxy, RID p_base) override {}
-
- void texture_2d_placeholder_initialize(RID p_texture) override;
- void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) override;
- void texture_3d_placeholder_initialize(RID p_texture) override;
-
- Ref<Image> texture_2d_get(RID p_texture) const override;
- Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const override { return Ref<Image>(); }
- Vector<Ref<Image>> texture_3d_get(RID p_texture) const override { return Vector<Ref<Image>>(); }
-
- void texture_replace(RID p_texture, RID p_by_texture) override;
- //void texture_set_size_override(RID p_texture, int p_width, int p_height) override {}
-
- void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {}
- void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {}
-
- // old
- uint32_t texture_get_width(RID p_texture) const;
- uint32_t texture_get_height(RID p_texture) const;
-
-private:
- RID texture_create();
-
- //void texture_allocate(RID p_texture, int p_width, int p_height, int p_depth_3d, Image::Format p_format, RenderingDevice::TextureType p_type, uint32_t p_flags = TEXTURE_FLAGS_DEFAULT);
- void _texture_allocate_internal(RID p_texture, int p_width, int p_height, int p_depth_3d, Image::Format p_format, RenderingDevice::TextureType p_type, uint32_t p_flags = TEXTURE_FLAGS_DEFAULT);
-
- void texture_set_data(RID p_texture, const Ref<Image> &p_image, int p_layer = 0);
- void texture_set_data_partial(RID p_texture, const Ref<Image> &p_image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int p_dst_mip, int p_layer = 0);
- //Ref<Image> texture_get_data(RID p_texture, int p_layer = 0) const;
- void texture_set_flags(RID p_texture, uint32_t p_flags);
- uint32_t texture_get_flags(RID p_texture) const;
- Image::Format texture_get_format(RID p_texture) const;
- RenderingDevice::TextureType texture_get_type(RID p_texture) const;
- uint32_t texture_get_texid(RID p_texture) const;
- uint32_t texture_get_depth(RID p_texture) const;
- void texture_set_size_override(RID p_texture, int p_width, int p_height) override;
-
- void texture_bind(RID p_texture, uint32_t p_texture_no);
-
- void texture_set_path(RID p_texture, const String &p_path) override;
- String texture_get_path(RID p_texture) const override;
-
- void texture_set_shrink_all_x2_on_set_data(bool p_enable);
-
- void texture_debug_usage(List<RS::TextureInfo> *r_info) override;
-
- RID texture_create_radiance_cubemap(RID p_source, int p_resolution = -1) const;
-
- void textures_keep_original(bool p_enable);
-
- void texture_set_proxy(RID p_texture, RID p_proxy);
- Size2 texture_size_with_proxy(RID p_texture) override;
-
- void texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override;
- void texture_set_detect_srgb_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata);
- void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override;
- void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) override {}
-
- void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) override;
-
public:
- RID canvas_texture_allocate() override;
- void canvas_texture_initialize(RID p_rid) override;
-
- void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) override;
- void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_specular_color, float p_shininess) override;
-
- void canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter) override;
- void canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat) override;
-
/* SKY API */
// not sure if used in godot 4?
struct Sky {
@@ -898,10 +522,10 @@ public:
void light_set_color(RID p_light, const Color &p_color) override;
void light_set_param(RID p_light, RS::LightParam p_param, float p_value) override;
void light_set_shadow(RID p_light, bool p_enabled) override;
- void light_set_shadow_color(RID p_light, const Color &p_color) override;
void light_set_projector(RID p_light, RID p_texture) override;
void light_set_negative(RID p_light, bool p_enable) override;
void light_set_cull_mask(RID p_light, uint32_t p_mask) override;
+ void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) override;
void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) override;
void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) override;
void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) override;
@@ -911,8 +535,8 @@ public:
void light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) override;
void light_directional_set_blend_splits(RID p_light, bool p_enable) override;
bool light_directional_get_blend_splits(RID p_light) const override;
- void light_directional_set_sky_only(RID p_light, bool p_sky_only) override;
- bool light_directional_is_sky_only(RID p_light) const override;
+ void light_directional_set_sky_mode(RID p_light, RS::LightDirectionalSkyMode p_mode) override;
+ RS::LightDirectionalSkyMode light_directional_get_sky_mode(RID p_light) const override;
RS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) override;
RS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) override;
@@ -971,6 +595,9 @@ public:
AABB decal_get_aabb(RID p_decal) const override;
+ void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {}
+ void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {}
+
/* VOXEL GI API */
RID voxel_gi_allocate() override;
@@ -1050,6 +677,7 @@ public:
void particles_set_speed_scale(RID p_particles, double p_scale) override;
void particles_set_use_local_coordinates(RID p_particles, bool p_enable) override;
void particles_set_process_material(RID p_particles, RID p_material) override;
+ RID particles_get_process_material(RID p_particles) const override;
void particles_set_fixed_fps(RID p_particles, int p_fps) override;
void particles_set_interpolate(RID p_particles, bool p_enable) override;
void particles_set_fractional_delta(RID p_particles, bool p_enable) override;
@@ -1150,91 +778,10 @@ public:
// RENDER TARGET
- struct RenderTarget {
- RID self;
- GLuint fbo = 0;
- GLuint color = 0;
- GLuint depth = 0;
-
- GLuint multisample_fbo = 0;
- GLuint multisample_color = 0;
- GLuint multisample_depth = 0;
- bool multisample_active = false;
-
- struct Effect {
- GLuint fbo = 0;
- int width = 0;
- int height = 0;
-
- GLuint color = 0;
-
- Effect() {
- }
- };
-
- Effect copy_screen_effect;
-
- struct MipMaps {
- struct Size {
- GLuint fbo;
- GLuint color;
- int width;
- int height;
- };
-
- Vector<Size> sizes;
- GLuint color = 0;
- int levels = 0;
-
- MipMaps() {
- }
- };
-
- MipMaps mip_maps[2];
-
- struct External {
- GLuint fbo = 0;
- GLuint color = 0;
- GLuint depth = 0;
- RID texture;
-
- External() {
- }
- } external;
-
- int x = 0, y = 0, width = 0, height = 0;
-
- bool flags[RENDER_TARGET_FLAG_MAX];
-
- // instead of allocating sized render targets immediately,
- // defer this for faster startup
- bool allocate_is_dirty = false;
- bool used_in_frame = false;
- RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED;
-
- bool use_fxaa = false;
- bool use_debanding = false;
-
- RID texture;
-
- bool used_dof_blur_near = false;
- bool mip_maps_allocated = false;
-
- Color clear_color = Color(1, 1, 1, 1);
- bool clear_requested = false;
-
- RenderTarget() {
- for (int i = 0; i < RENDER_TARGET_FLAG_MAX; ++i) {
- flags[i] = false;
- }
- external.fbo = 0;
- }
- };
-
- mutable RID_PtrOwner<RenderTarget> render_target_owner;
+ mutable RID_PtrOwner<GLES3::RenderTarget> render_target_owner;
- void _render_target_clear(RenderTarget *rt);
- void _render_target_allocate(RenderTarget *rt);
+ void _render_target_clear(GLES3::RenderTarget *rt);
+ void _render_target_allocate(GLES3::RenderTarget *rt);
void _set_current_render_target(RID p_render_target);
RID render_target_create() override;
@@ -1267,7 +814,7 @@ public:
void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) override;
// access from canvas
- // RenderTarget * render_target_get(RID p_render_target);
+ // GLES3::RenderTarget * render_target_get(RID p_render_target);
/* CANVAS SHADOW */
@@ -1306,7 +853,7 @@ public:
bool free(RID p_rid) override;
struct Frame {
- RenderTarget *current_rt;
+ GLES3::RenderTarget *current_rt;
// these 2 may have been superseded by the equivalents in the render target.
// these may be able to be removed.
@@ -1413,7 +960,7 @@ inline bool RasterizerStorageGLES3::safe_buffer_sub_data(unsigned int p_total_bu
inline void RasterizerStorageGLES3::buffer_orphan_and_upload(unsigned int p_buffer_size, unsigned int p_offset, unsigned int p_data_size, const void *p_data, GLenum p_target, GLenum p_usage, bool p_optional_orphan) const {
// Orphan the buffer to avoid CPU/GPU sync points caused by glBufferSubData
// Was previously #ifndef GLES_OVER_GL however this causes stalls on desktop mac also (and possibly other)
- if (!p_optional_orphan || (config.should_orphan)) {
+ if (!p_optional_orphan || (config->should_orphan)) {
glBufferData(p_target, p_buffer_size, nullptr, p_usage);
#ifdef RASTERIZER_EXTRA_CHECKS
// fill with garbage off the end of the array
diff --git a/drivers/gles3/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp
index 7ae8b4e3bf..9349722625 100644
--- a/drivers/gles3/shader_gles3.cpp
+++ b/drivers/gles3/shader_gles3.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "shader_gles3.h"
+
#ifdef GLES3_ENABLED
#include "core/io/compression.h"
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl
index 98c92a1d99..2d504cd052 100644
--- a/drivers/gles3/shaders/scene.glsl
+++ b/drivers/gles3/shaders/scene.glsl
@@ -1107,7 +1107,7 @@ void light_compute(
float rim,
float rim_tint,
float clearcoat,
- float clearcoat_gloss,
+ float clearcoat_roughness,
float anisotropy,
inout vec3 diffuse_light,
inout vec3 specular_light,
@@ -1298,7 +1298,7 @@ LIGHT_SHADER_CODE
#if !defined(SPECULAR_SCHLICK_GGX)
float cLdotH5 = SchlickFresnel(cLdotH);
#endif
- float Dr = GTR1(cNdotH, mix(.1, .001, clearcoat_gloss));
+ float Dr = GTR1(cNdotH, mix(.1, .001, clearcoat_roughness));
float Fr = mix(.04, 1.0, cLdotH5);
//float Gr = G_GGX_2cos(cNdotL, .25) * G_GGX_2cos(cNdotV, .25);
float Gr = V_GGX(cNdotL, cNdotV, 0.25);
@@ -1427,7 +1427,7 @@ void main() {
float rim = 0.0;
float rim_tint = 0.0;
float clearcoat = 0.0;
- float clearcoat_gloss = 0.0;
+ float clearcoat_roughness = 0.0;
float anisotropy = 0.0;
vec2 anisotropy_flow = vec2(1.0, 0.0);
float sss_strength = 0.0; //unused
@@ -2028,7 +2028,7 @@ FRAGMENT_SHADER_CODE
rim,
rim_tint,
clearcoat,
- clearcoat_gloss,
+ clearcoat_roughness,
anisotropy,
diffuse_light,
specular_light,
diff --git a/drivers/gles3/storage/SCsub b/drivers/gles3/storage/SCsub
new file mode 100644
index 0000000000..91e1140b75
--- /dev/null
+++ b/drivers/gles3/storage/SCsub
@@ -0,0 +1,5 @@
+#!/usr/bin/env python
+
+Import("env")
+
+env.add_source_files(env.drivers_sources, "*.cpp")
diff --git a/drivers/gles3/storage/canvas_texture_storage.cpp b/drivers/gles3/storage/canvas_texture_storage.cpp
new file mode 100644
index 0000000000..fe12700c21
--- /dev/null
+++ b/drivers/gles3/storage/canvas_texture_storage.cpp
@@ -0,0 +1,96 @@
+/*************************************************************************/
+/* canvas_texture_storage.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 "canvas_texture_storage.h"
+
+using namespace GLES3;
+
+CanvasTextureStorage *CanvasTextureStorage::singleton = nullptr;
+
+CanvasTextureStorage *CanvasTextureStorage::get_singleton() {
+ return singleton;
+}
+
+CanvasTextureStorage::CanvasTextureStorage() {
+ singleton = this;
+}
+
+CanvasTextureStorage::~CanvasTextureStorage() {
+ singleton = nullptr;
+}
+
+RID CanvasTextureStorage::canvas_texture_allocate() {
+ return canvas_texture_owner.allocate_rid();
+}
+
+void CanvasTextureStorage::canvas_texture_initialize(RID p_rid) {
+ canvas_texture_owner.initialize_rid(p_rid);
+}
+
+void CanvasTextureStorage::canvas_texture_free(RID p_rid) {
+ canvas_texture_owner.free(p_rid);
+}
+
+void CanvasTextureStorage::canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) {
+ CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
+ switch (p_channel) {
+ case RS::CANVAS_TEXTURE_CHANNEL_DIFFUSE: {
+ ct->diffuse = p_texture;
+ } break;
+ case RS::CANVAS_TEXTURE_CHANNEL_NORMAL: {
+ ct->normal_map = p_texture;
+ } break;
+ case RS::CANVAS_TEXTURE_CHANNEL_SPECULAR: {
+ ct->specular = p_texture;
+ } break;
+ }
+}
+
+void CanvasTextureStorage::canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_specular_color, float p_shininess) {
+ CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
+ ct->specular_color.r = p_specular_color.r;
+ ct->specular_color.g = p_specular_color.g;
+ ct->specular_color.b = p_specular_color.b;
+ ct->specular_color.a = p_shininess;
+}
+
+void CanvasTextureStorage::canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter) {
+ CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
+ ct->texture_filter = p_filter;
+}
+
+void CanvasTextureStorage::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat) {
+ CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
+ ct->texture_repeat = p_repeat;
+}
+
+#endif // !GLES3_ENABLED
diff --git a/drivers/gles3/storage/canvas_texture_storage.h b/drivers/gles3/storage/canvas_texture_storage.h
new file mode 100644
index 0000000000..5930e927fe
--- /dev/null
+++ b/drivers/gles3/storage/canvas_texture_storage.h
@@ -0,0 +1,87 @@
+/*************************************************************************/
+/* canvas_texture_storage.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 CANVAS_TEXTURE_STORAGE_GLES3_H
+#define CANVAS_TEXTURE_STORAGE_GLES3_H
+
+#ifdef GLES3_ENABLED
+
+#include "core/templates/rid_owner.h"
+#include "servers/rendering/storage/canvas_texture_storage.h"
+
+namespace GLES3 {
+
+struct CanvasTexture {
+ RID diffuse;
+ RID normal_map;
+ RID specular;
+ Color specular_color = Color(1, 1, 1, 1);
+ float shininess = 1.0;
+
+ RS::CanvasItemTextureFilter texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT;
+ RS::CanvasItemTextureRepeat texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT;
+
+ Size2i size_cache = Size2i(1, 1);
+ bool use_normal_cache = false;
+ bool use_specular_cache = false;
+ bool cleared_cache = true;
+};
+
+class CanvasTextureStorage : public RendererCanvasTextureStorage {
+private:
+ static CanvasTextureStorage *singleton;
+
+ RID_Owner<CanvasTexture, true> canvas_texture_owner;
+
+public:
+ static CanvasTextureStorage *get_singleton();
+
+ CanvasTextureStorage();
+ virtual ~CanvasTextureStorage();
+
+ CanvasTexture *get_canvas_texture(RID p_rid) { return canvas_texture_owner.get_or_null(p_rid); };
+ bool owns_canvas_texture(RID p_rid) { return canvas_texture_owner.owns(p_rid); };
+
+ virtual RID canvas_texture_allocate() override;
+ virtual void canvas_texture_initialize(RID p_rid) override;
+ virtual void canvas_texture_free(RID p_rid) override;
+
+ virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) override;
+ virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) override;
+
+ 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;
+};
+
+} // namespace GLES3
+
+#endif // !GLES3_ENABLED
+
+#endif // !CANVAS_TEXTURE_STORAGE_GLES3_H
diff --git a/drivers/gles3/storage/config.cpp b/drivers/gles3/storage/config.cpp
new file mode 100644
index 0000000000..1f66401427
--- /dev/null
+++ b/drivers/gles3/storage/config.cpp
@@ -0,0 +1,156 @@
+/*************************************************************************/
+/* config.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 "config.h"
+#include "core/templates/vector.h"
+
+using namespace GLES3;
+
+Config *Config::singleton = nullptr;
+
+Config::Config() {
+ singleton = this;
+ should_orphan = true;
+}
+
+Config::~Config() {
+ singleton = nullptr;
+}
+
+void Config::initialize() {
+ {
+ const GLubyte *extension_string = glGetString(GL_EXTENSIONS);
+
+ Vector<String> exts = String((const char *)extension_string).split(" ");
+
+ for (int i = 0; i < exts.size(); i++) {
+ extensions.insert(exts[i]);
+ }
+ }
+
+ keep_original_textures = true; // false
+ shrink_textures_x2 = false;
+ depth_internalformat = GL_DEPTH_COMPONENT;
+ depth_type = GL_UNSIGNED_INT;
+
+#ifdef GLES_OVER_GL
+ float_texture_supported = true;
+ s3tc_supported = true;
+ etc_supported = false;
+ support_npot_repeat_mipmap = true;
+ depth_buffer_internalformat = GL_DEPTH_COMPONENT24;
+#else
+ float_texture_supported = extensions.has("GL_ARB_texture_float") || extensions.has("GL_OES_texture_float");
+ s3tc_supported = extensions.has("GL_EXT_texture_compression_s3tc") || extensions.has("WEBGL_compressed_texture_s3tc");
+ etc_supported = extensions.has("GL_OES_compressed_ETC1_RGB8_texture") || extensions.has("WEBGL_compressed_texture_etc1");
+ support_npot_repeat_mipmap = extensions.has("GL_OES_texture_npot");
+
+#ifdef JAVASCRIPT_ENABLED
+ // RenderBuffer internal format must be 16 bits in WebGL,
+ // but depth_texture should default to 32 always
+ // if the implementation doesn't support 32, it should just quietly use 16 instead
+ // https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/
+ depth_buffer_internalformat = GL_DEPTH_COMPONENT16;
+ depth_type = GL_UNSIGNED_INT;
+#else
+ // on mobile check for 24 bit depth support for RenderBufferStorage
+ if (extensions.has("GL_OES_depth24")) {
+ depth_buffer_internalformat = _DEPTH_COMPONENT24_OES;
+ depth_type = GL_UNSIGNED_INT;
+ } else {
+ depth_buffer_internalformat = GL_DEPTH_COMPONENT16;
+ depth_type = GL_UNSIGNED_SHORT;
+ }
+#endif
+#endif
+
+#ifdef GLES_OVER_GL
+ //TODO: causes huge problems with desktop video drivers. Making false for now, needs to be true to render SCREEN_TEXTURE mipmaps
+ render_to_mipmap_supported = false;
+#else
+ //check if mipmaps can be used for SCREEN_TEXTURE and Glow on Mobile and web platforms
+ render_to_mipmap_supported = extensions.has("GL_OES_fbo_render_mipmap") && extensions.has("GL_EXT_texture_lod");
+#endif
+
+#ifdef GLES_OVER_GL
+ use_rgba_2d_shadows = false;
+ support_depth_texture = true;
+ use_rgba_3d_shadows = false;
+ support_depth_cubemaps = true;
+#else
+ use_rgba_2d_shadows = !(float_texture_supported && extensions.has("GL_EXT_texture_rg"));
+ support_depth_texture = extensions.has("GL_OES_depth_texture") || extensions.has("WEBGL_depth_texture");
+ use_rgba_3d_shadows = !support_depth_texture;
+ support_depth_cubemaps = extensions.has("GL_OES_depth_texture_cube_map");
+#endif
+
+#ifdef GLES_OVER_GL
+ support_32_bits_indices = true;
+#else
+ support_32_bits_indices = extensions.has("GL_OES_element_index_uint");
+#endif
+
+#ifdef GLES_OVER_GL
+ support_write_depth = true;
+#elif defined(JAVASCRIPT_ENABLED)
+ support_write_depth = false;
+#else
+ support_write_depth = extensions.has("GL_EXT_frag_depth");
+#endif
+
+ support_half_float_vertices = true;
+//every platform should support this except web, iOS has issues with their support, so add option to disable
+#ifdef JAVASCRIPT_ENABLED
+ support_half_float_vertices = false;
+#endif
+ bool disable_half_float = false; //GLOBAL_GET("rendering/opengl/compatibility/disable_half_float");
+ if (disable_half_float) {
+ support_half_float_vertices = false;
+ }
+
+ etc_supported = extensions.has("GL_OES_compressed_ETC1_RGB8_texture");
+ latc_supported = extensions.has("GL_EXT_texture_compression_latc");
+ bptc_supported = extensions.has("GL_ARB_texture_compression_bptc");
+ rgtc_supported = extensions.has("GL_EXT_texture_compression_rgtc") || extensions.has("GL_ARB_texture_compression_rgtc") || extensions.has("EXT_texture_compression_rgtc");
+ bptc_supported = extensions.has("GL_ARB_texture_compression_bptc") || extensions.has("EXT_texture_compression_bptc");
+ srgb_decode_supported = extensions.has("GL_EXT_texture_sRGB_decode");
+
+ glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &max_vertex_texture_image_units);
+ glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_texture_image_units);
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
+
+ force_vertex_shading = false; //GLOBAL_GET("rendering/quality/shading/force_vertex_shading");
+ use_fast_texture_filter = false; //GLOBAL_GET("rendering/quality/filters/use_nearest_mipmap_filter");
+ // should_orphan = GLOBAL_GET("rendering/options/api_usage_legacy/orphan_buffers");
+}
+
+#endif // GLES3_ENABLED
diff --git a/drivers/gles3/storage/config.h b/drivers/gles3/storage/config.h
new file mode 100644
index 0000000000..25bd3fd9a1
--- /dev/null
+++ b/drivers/gles3/storage/config.h
@@ -0,0 +1,113 @@
+/*************************************************************************/
+/* config.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 CONFIG_GLES3_H
+#define CONFIG_GLES3_H
+
+#ifdef GLES3_ENABLED
+
+#include "core/string/ustring.h"
+#include "core/templates/set.h"
+
+// This must come first to avoid windows.h mess
+#include "platform_config.h"
+#ifndef OPENGL_INCLUDE_H
+#include <GLES3/gl3.h>
+#else
+#include OPENGL_INCLUDE_H
+#endif
+
+namespace GLES3 {
+
+class Config {
+private:
+ static Config *singleton;
+
+public:
+ bool shrink_textures_x2;
+ bool use_fast_texture_filter;
+ bool use_skeleton_software;
+
+ int max_vertex_texture_image_units;
+ int max_texture_image_units;
+ int max_texture_size;
+
+ // TODO implement wireframe in OpenGL
+ // bool generate_wireframes;
+
+ Set<String> extensions;
+
+ bool float_texture_supported;
+ bool s3tc_supported;
+ bool latc_supported;
+ bool rgtc_supported;
+ bool bptc_supported;
+ bool etc_supported;
+ bool etc2_supported;
+ bool srgb_decode_supported;
+
+ bool keep_original_textures;
+
+ bool force_vertex_shading;
+
+ bool use_rgba_2d_shadows;
+ bool use_rgba_3d_shadows;
+
+ bool support_32_bits_indices;
+ bool support_write_depth;
+ bool support_half_float_vertices;
+ bool support_npot_repeat_mipmap;
+ bool support_depth_texture;
+ bool support_depth_cubemaps;
+
+ bool support_shadow_cubemaps;
+
+ bool render_to_mipmap_supported;
+
+ GLuint depth_internalformat;
+ GLuint depth_type;
+ GLuint depth_buffer_internalformat;
+
+ // in some cases the legacy render didn't orphan. We will mark these
+ // so the user can switch orphaning off for them.
+ bool should_orphan = true;
+
+ static Config *get_singleton() { return singleton; };
+
+ Config();
+ ~Config();
+ void initialize();
+};
+
+} // namespace GLES3
+
+#endif // GLES3_ENABLED
+
+#endif // !CONFIG_GLES3_H
diff --git a/drivers/gles3/storage/render_target_storage.h b/drivers/gles3/storage/render_target_storage.h
new file mode 100644
index 0000000000..816cc76e40
--- /dev/null
+++ b/drivers/gles3/storage/render_target_storage.h
@@ -0,0 +1,132 @@
+/*************************************************************************/
+/* render_target_storage.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 RENDER_TARGET_STORAGE_GLES3_H
+#define RENDER_TARGET_STORAGE_GLES3_H
+
+#ifdef GLES3_ENABLED
+
+#include "core/templates/rid_owner.h"
+#include "servers/rendering/renderer_compositor.h"
+#include "servers/rendering/renderer_storage.h" // included until we move stuff into storage/render_target_storage.h
+// #include "servers/rendering/storage/render_target_storage.h"
+
+// This must come first to avoid windows.h mess
+#include "platform_config.h"
+#ifndef OPENGL_INCLUDE_H
+#include <GLES3/gl3.h>
+#else
+#include OPENGL_INCLUDE_H
+#endif
+
+namespace GLES3 {
+
+// NOTE, this class currently is just a container for the the RenderTarget struct and is not yet implemented further, we'll do that next after we finish with TextureStorage
+
+struct RenderTarget {
+ RID self;
+ GLuint fbo = 0;
+ GLuint color = 0;
+ GLuint depth = 0;
+
+ GLuint multisample_fbo = 0;
+ GLuint multisample_color = 0;
+ GLuint multisample_depth = 0;
+ bool multisample_active = false;
+
+ struct Effect {
+ GLuint fbo = 0;
+ int width = 0;
+ int height = 0;
+
+ GLuint color = 0;
+ };
+
+ Effect copy_screen_effect;
+
+ struct MipMaps {
+ struct Size {
+ GLuint fbo = 0;
+ GLuint color = 0;
+ int width = 0;
+ int height = 0;
+ };
+
+ Vector<Size> sizes;
+ GLuint color = 0;
+ int levels = 0;
+ };
+
+ MipMaps mip_maps[2];
+
+ struct External {
+ GLuint fbo = 0;
+ GLuint color = 0;
+ GLuint depth = 0;
+ RID texture;
+ } external;
+
+ int x = 0;
+ int y = 0;
+ int width = 0;
+ int height = 0;
+
+ bool flags[RendererStorage::RENDER_TARGET_FLAG_MAX] = {};
+
+ // instead of allocating sized render targets immediately,
+ // defer this for faster startup
+ bool allocate_is_dirty = false;
+ bool used_in_frame = false;
+ RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED;
+
+ bool use_fxaa = false;
+ bool use_debanding = false;
+
+ RID texture;
+
+ bool used_dof_blur_near = false;
+ bool mip_maps_allocated = false;
+
+ Color clear_color = Color(1, 1, 1, 1);
+ bool clear_requested = false;
+
+ RenderTarget() {
+ for (int i = 0; i < RendererStorage::RENDER_TARGET_FLAG_MAX; ++i) {
+ flags[i] = false;
+ }
+ external.fbo = 0;
+ }
+};
+
+} // namespace GLES3
+
+#endif // !GLES3_ENABLED
+
+#endif // !RENDER_TARGET_STORAGE_GLES3_H
diff --git a/drivers/gles3/storage/texture_storage.cpp b/drivers/gles3/storage/texture_storage.cpp
new file mode 100644
index 0000000000..d199b1032e
--- /dev/null
+++ b/drivers/gles3/storage/texture_storage.cpp
@@ -0,0 +1,1211 @@
+/*************************************************************************/
+/* texture_storage.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 "texture_storage.h"
+#include "config.h"
+
+using namespace GLES3;
+
+TextureStorage *TextureStorage::singleton = nullptr;
+
+TextureStorage *TextureStorage::get_singleton() {
+ return singleton;
+}
+
+TextureStorage::TextureStorage() {
+ singleton = this;
+}
+
+TextureStorage::~TextureStorage() {
+ singleton = nullptr;
+}
+
+void TextureStorage::set_main_thread_id(Thread::ID p_id) {
+ _main_thread_id = p_id;
+}
+
+bool TextureStorage::_is_main_thread() {
+ //#if defined DEBUG_ENABLED && defined TOOLS_ENABLED
+ // must be called from main thread in OpenGL
+ bool is_main_thread = _main_thread_id == Thread::get_caller_id();
+ //#endif
+ return is_main_thread;
+}
+
+bool TextureStorage::can_create_resources_async() const {
+ return false;
+}
+
+static const GLenum _cube_side_enum[6] = {
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
+ GL_TEXTURE_CUBE_MAP_POSITIVE_X,
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
+ GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
+ GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
+};
+
+Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, 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 {
+ Config *config = Config::get_singleton();
+ r_gl_format = 0;
+ Ref<Image> image = p_image;
+ r_compressed = false;
+ r_real_format = p_format;
+
+ bool need_decompress = false;
+
+ switch (p_format) {
+ case Image::FORMAT_L8: {
+#ifdef GLES_OVER_GL
+ r_gl_internal_format = GL_R8;
+ r_gl_format = GL_RED;
+ r_gl_type = GL_UNSIGNED_BYTE;
+#else
+ r_gl_internal_format = GL_LUMINANCE;
+ r_gl_format = GL_LUMINANCE;
+ r_gl_type = GL_UNSIGNED_BYTE;
+#endif
+ } break;
+ case Image::FORMAT_LA8: {
+#ifdef GLES_OVER_GL
+ r_gl_internal_format = GL_RG8;
+ r_gl_format = GL_RG;
+ r_gl_type = GL_UNSIGNED_BYTE;
+#else
+ r_gl_internal_format = GL_LUMINANCE_ALPHA;
+ r_gl_format = GL_LUMINANCE_ALPHA;
+ r_gl_type = GL_UNSIGNED_BYTE;
+#endif
+ } break;
+ case Image::FORMAT_R8: {
+ r_gl_internal_format = GL_R8;
+ r_gl_format = GL_RED;
+ r_gl_type = GL_UNSIGNED_BYTE;
+
+ } break;
+ case Image::FORMAT_RG8: {
+ r_gl_internal_format = GL_RG8;
+ r_gl_format = GL_RG;
+ r_gl_type = GL_UNSIGNED_BYTE;
+
+ } break;
+ case Image::FORMAT_RGB8: {
+ r_gl_internal_format = GL_RGB8;
+ r_gl_format = GL_RGB;
+ r_gl_type = GL_UNSIGNED_BYTE;
+ //r_srgb = true;
+
+ } break;
+ case Image::FORMAT_RGBA8: {
+ r_gl_format = GL_RGBA;
+ r_gl_internal_format = GL_RGBA8;
+ r_gl_type = GL_UNSIGNED_BYTE;
+ //r_srgb = true;
+
+ } break;
+ case Image::FORMAT_RGBA4444: {
+ r_gl_internal_format = GL_RGBA4;
+ r_gl_format = GL_RGBA;
+ r_gl_type = GL_UNSIGNED_SHORT_4_4_4_4;
+
+ } break;
+ //case Image::FORMAT_RGBA5551: {
+ // r_gl_internal_format = GL_RGB5_A1;
+ // r_gl_format = GL_RGBA;
+ // r_gl_type = GL_UNSIGNED_SHORT_5_5_5_1;
+ //
+ //} break;
+ case Image::FORMAT_RF: {
+ r_gl_internal_format = GL_R32F;
+ r_gl_format = GL_RED;
+ r_gl_type = GL_FLOAT;
+
+ } break;
+ case Image::FORMAT_RGF: {
+ r_gl_internal_format = GL_RG32F;
+ r_gl_format = GL_RG;
+ r_gl_type = GL_FLOAT;
+
+ } break;
+ case Image::FORMAT_RGBF: {
+ r_gl_internal_format = GL_RGB32F;
+ r_gl_format = GL_RGB;
+ r_gl_type = GL_FLOAT;
+
+ } break;
+ case Image::FORMAT_RGBAF: {
+ r_gl_internal_format = GL_RGBA32F;
+ r_gl_format = GL_RGBA;
+ r_gl_type = GL_FLOAT;
+
+ } break;
+ case Image::FORMAT_RH: {
+ r_gl_internal_format = GL_R16F;
+ r_gl_format = GL_RED;
+ r_gl_type = GL_HALF_FLOAT;
+ } break;
+ case Image::FORMAT_RGH: {
+ r_gl_internal_format = GL_RG16F;
+ r_gl_format = GL_RG;
+ r_gl_type = GL_HALF_FLOAT;
+
+ } break;
+ case Image::FORMAT_RGBH: {
+ r_gl_internal_format = GL_RGB16F;
+ r_gl_format = GL_RGB;
+ r_gl_type = GL_HALF_FLOAT;
+
+ } break;
+ case Image::FORMAT_RGBAH: {
+ r_gl_internal_format = GL_RGBA16F;
+ r_gl_format = GL_RGBA;
+ r_gl_type = GL_HALF_FLOAT;
+
+ } break;
+ case Image::FORMAT_RGBE9995: {
+ r_gl_internal_format = GL_RGB9_E5;
+ r_gl_format = GL_RGB;
+ r_gl_type = GL_UNSIGNED_INT_5_9_9_9_REV;
+
+ } break;
+ case Image::FORMAT_DXT1: {
+ if (config->s3tc_supported) {
+ r_gl_internal_format = _EXT_COMPRESSED_RGBA_S3TC_DXT1_EXT;
+ r_gl_format = GL_RGBA;
+ r_gl_type = GL_UNSIGNED_BYTE;
+ r_compressed = true;
+ //r_srgb = true;
+
+ } else {
+ need_decompress = true;
+ }
+ } break;
+ case Image::FORMAT_DXT3: {
+ if (config->s3tc_supported) {
+ r_gl_internal_format = _EXT_COMPRESSED_RGBA_S3TC_DXT3_EXT;
+ r_gl_format = GL_RGBA;
+ r_gl_type = GL_UNSIGNED_BYTE;
+ r_compressed = true;
+ //r_srgb = true;
+
+ } else {
+ need_decompress = true;
+ }
+ } break;
+ case Image::FORMAT_DXT5: {
+ if (config->s3tc_supported) {
+ r_gl_internal_format = _EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+ r_gl_format = GL_RGBA;
+ r_gl_type = GL_UNSIGNED_BYTE;
+ r_compressed = true;
+ //r_srgb = true;
+
+ } else {
+ need_decompress = true;
+ }
+ } break;
+ case Image::FORMAT_RGTC_R: {
+ if (config->rgtc_supported) {
+ r_gl_internal_format = _EXT_COMPRESSED_RED_RGTC1_EXT;
+ r_gl_format = GL_RGBA;
+ r_gl_type = GL_UNSIGNED_BYTE;
+ r_compressed = true;
+
+ } else {
+ need_decompress = true;
+ }
+ } break;
+ case Image::FORMAT_RGTC_RG: {
+ if (config->rgtc_supported) {
+ r_gl_internal_format = _EXT_COMPRESSED_RED_GREEN_RGTC2_EXT;
+ r_gl_format = GL_RGBA;
+ r_gl_type = GL_UNSIGNED_BYTE;
+ r_compressed = true;
+ } else {
+ need_decompress = true;
+ }
+ } break;
+ case Image::FORMAT_BPTC_RGBA: {
+ if (config->bptc_supported) {
+ r_gl_internal_format = _EXT_COMPRESSED_RGBA_BPTC_UNORM;
+ r_gl_format = GL_RGBA;
+ r_gl_type = GL_UNSIGNED_BYTE;
+ r_compressed = true;
+ //r_srgb = true;
+
+ } else {
+ need_decompress = true;
+ }
+ } break;
+ case Image::FORMAT_BPTC_RGBF: {
+ if (config->bptc_supported) {
+ r_gl_internal_format = _EXT_COMPRESSED_RGB_BPTC_SIGNED_FLOAT;
+ r_gl_format = GL_RGB;
+ r_gl_type = GL_FLOAT;
+ r_compressed = true;
+ } else {
+ need_decompress = true;
+ }
+ } break;
+ case Image::FORMAT_BPTC_RGBFU: {
+ if (config->bptc_supported) {
+ r_gl_internal_format = _EXT_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT;
+ r_gl_format = GL_RGB;
+ r_gl_type = GL_FLOAT;
+ r_compressed = true;
+ } else {
+ need_decompress = true;
+ }
+ } break;
+ case Image::FORMAT_ETC: {
+ if (config->etc_supported) {
+ r_gl_internal_format = _EXT_ETC1_RGB8_OES;
+ r_gl_format = GL_RGBA;
+ r_gl_type = GL_UNSIGNED_BYTE;
+ r_compressed = true;
+
+ } else {
+ need_decompress = true;
+ }
+
+ } break;
+ /*
+ case Image::FORMAT_ETC2_R11: {
+ if (config->etc2_supported) {
+ r_gl_internal_format = _EXT_COMPRESSED_R11_EAC;
+ r_gl_format = GL_RED;
+ r_gl_type = GL_UNSIGNED_BYTE;
+ r_compressed = true;
+
+ } else {
+ need_decompress = true;
+ }
+ } break;
+ case Image::FORMAT_ETC2_R11S: {
+ if (config->etc2_supported) {
+ r_gl_internal_format = _EXT_COMPRESSED_SIGNED_R11_EAC;
+ r_gl_format = GL_RED;
+ r_gl_type = GL_UNSIGNED_BYTE;
+ r_compressed = true;
+
+ } else {
+ need_decompress = true;
+ }
+ } break;
+ case Image::FORMAT_ETC2_RG11: {
+ if (config->etc2_supported) {
+ r_gl_internal_format = _EXT_COMPRESSED_RG11_EAC;
+ r_gl_format = GL_RG;
+ r_gl_type = GL_UNSIGNED_BYTE;
+ r_compressed = true;
+
+ } else {
+ need_decompress = true;
+ }
+ } break;
+ case Image::FORMAT_ETC2_RG11S: {
+ if (config->etc2_supported) {
+ r_gl_internal_format = _EXT_COMPRESSED_SIGNED_RG11_EAC;
+ r_gl_format = GL_RG;
+ r_gl_type = GL_UNSIGNED_BYTE;
+ r_compressed = true;
+
+ } else {
+ need_decompress = true;
+ }
+ } break;
+ case Image::FORMAT_ETC2_RGB8: {
+ if (config->etc2_supported) {
+ r_gl_internal_format = _EXT_COMPRESSED_RGB8_ETC2;
+ r_gl_format = GL_RGB;
+ r_gl_type = GL_UNSIGNED_BYTE;
+ r_compressed = true;
+ //r_srgb = true;
+
+ } else {
+ need_decompress = true;
+ }
+ } break;
+ case Image::FORMAT_ETC2_RGBA8: {
+ if (config->etc2_supported) {
+ r_gl_internal_format = _EXT_COMPRESSED_RGBA8_ETC2_EAC;
+ r_gl_format = GL_RGBA;
+ r_gl_type = GL_UNSIGNED_BYTE;
+ r_compressed = true;
+ //r_srgb = true;
+
+ } else {
+ need_decompress = true;
+ }
+ } break;
+ case Image::FORMAT_ETC2_RGB8A1: {
+ if (config->etc2_supported) {
+ r_gl_internal_format = _EXT_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2;
+ r_gl_format = GL_RGBA;
+ r_gl_type = GL_UNSIGNED_BYTE;
+ r_compressed = true;
+ //r_srgb = true;
+
+ } else {
+ need_decompress = true;
+ }
+ } break;
+ */
+ default: {
+ ERR_FAIL_V(Ref<Image>());
+ }
+ }
+
+ if (need_decompress || p_force_decompress) {
+ if (!image.is_null()) {
+ image = image->duplicate();
+ image->decompress();
+ ERR_FAIL_COND_V(image->is_compressed(), image);
+ switch (image->get_format()) {
+ case Image::FORMAT_RGB8: {
+ r_gl_format = GL_RGB;
+ r_gl_internal_format = GL_RGB;
+ r_gl_type = GL_UNSIGNED_BYTE;
+ r_real_format = Image::FORMAT_RGB8;
+ r_compressed = false;
+ } break;
+ case Image::FORMAT_RGBA8: {
+ r_gl_format = GL_RGBA;
+ r_gl_internal_format = GL_RGBA;
+ r_gl_type = GL_UNSIGNED_BYTE;
+ r_real_format = Image::FORMAT_RGBA8;
+ r_compressed = false;
+ } break;
+ default: {
+ image->convert(Image::FORMAT_RGBA8);
+ r_gl_format = GL_RGBA;
+ r_gl_internal_format = GL_RGBA;
+ r_gl_type = GL_UNSIGNED_BYTE;
+ r_real_format = Image::FORMAT_RGBA8;
+ r_compressed = false;
+
+ } break;
+ }
+ }
+
+ return image;
+ }
+
+ return p_image;
+}
+
+void TextureStorage::_texture_set_state_from_flags(Texture *p_tex) {
+ // Config *config = Config::get_singleton();
+
+ if ((p_tex->flags & TEXTURE_FLAG_MIPMAPS) && !p_tex->ignore_mipmaps) {
+ if (p_tex->flags & TEXTURE_FLAG_FILTER) {
+ // these do not exactly correspond ...
+ p_tex->GLSetFilter(p_tex->target, RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS);
+ //texture->glTexParam_MinFilter(texture->target, config->use_fast_texture_filter ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR_MIPMAP_LINEAR);
+ } else {
+ p_tex->GLSetFilter(p_tex->target, RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS);
+ //texture->glTexParam_MinFilter(texture->target, config->use_fast_texture_filter ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST_MIPMAP_LINEAR);
+ }
+ } else {
+ if (p_tex->flags & TEXTURE_FLAG_FILTER) {
+ p_tex->GLSetFilter(p_tex->target, RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR);
+ //texture->glTexParam_MinFilter(texture->target, GL_LINEAR);
+ } else {
+ p_tex->GLSetFilter(p_tex->target, RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST);
+ //texture->glTexParam_MinFilter(texture->target, GL_NEAREST);
+ }
+ }
+
+ if (((p_tex->flags & TEXTURE_FLAG_REPEAT) || (p_tex->flags & TEXTURE_FLAG_MIRRORED_REPEAT)) && p_tex->target != GL_TEXTURE_CUBE_MAP) {
+ if (p_tex->flags & TEXTURE_FLAG_MIRRORED_REPEAT) {
+ p_tex->GLSetRepeat(p_tex->target, RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR);
+ } else {
+ p_tex->GLSetRepeat(p_tex->target, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ }
+ } else {
+ p_tex->GLSetRepeat(p_tex->target, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ }
+}
+
+void TextureStorage::_texture_allocate_internal(RID p_texture, int p_width, int p_height, int p_depth_3d, Image::Format p_format, RenderingDevice::TextureType p_type, uint32_t p_flags) {
+ // GLenum format;
+ // GLenum internal_format;
+ // GLenum type;
+
+ // bool compressed = false;
+
+ // Config *config = Config::get_singleton();
+
+ if (p_flags & TEXTURE_FLAG_USED_FOR_STREAMING) {
+ p_flags &= ~TEXTURE_FLAG_MIPMAPS; // no mipies for video
+ }
+
+ Texture *texture = texture_owner.get_or_null(p_texture);
+ ERR_FAIL_COND(!texture);
+ texture->width = p_width;
+ texture->height = p_height;
+ texture->format = p_format;
+ texture->flags = p_flags;
+ texture->stored_cube_sides = 0;
+ texture->type = p_type;
+
+ switch (p_type) {
+ case RenderingDevice::TEXTURE_TYPE_2D: {
+ texture->target = GL_TEXTURE_2D;
+ texture->images.resize(1);
+ } break;
+ // case RenderingDevice::TEXTURE_TYPE_EXTERNAL: {
+ //#ifdef ANDROID_ENABLED
+ // texture->target = _GL_TEXTURE_EXTERNAL_OES;
+ //#else
+ // texture->target = GL_TEXTURE_2D;
+ //#endif
+ // texture->images.resize(0);
+ // } break;
+ case RenderingDevice::TEXTURE_TYPE_CUBE: {
+ texture->target = GL_TEXTURE_CUBE_MAP;
+ texture->images.resize(6);
+ } break;
+ case RenderingDevice::TEXTURE_TYPE_2D_ARRAY:
+ case RenderingDevice::TEXTURE_TYPE_3D: {
+ texture->target = GL_TEXTURE_3D;
+ ERR_PRINT("3D textures and Texture Arrays are not supported in OpenGL. Please switch to the Vulkan backend.");
+ return;
+ } break;
+ default: {
+ ERR_PRINT("Unknown texture type!");
+ return;
+ }
+ }
+
+#if 0
+ // if (p_type != RS::TEXTURE_TYPE_EXTERNAL) {
+ if (p_type == RenderingDevice::TEXTURE_TYPE_2D) {
+ texture->alloc_width = texture->width;
+ texture->alloc_height = texture->height;
+ texture->resize_to_po2 = false;
+ if (!config->support_npot_repeat_mipmap) {
+ int po2_width = next_power_of_2(p_width);
+ int po2_height = next_power_of_2(p_height);
+
+ bool is_po2 = p_width == po2_width && p_height == po2_height;
+
+ if (!is_po2 && (p_flags & TEXTURE_FLAG_REPEAT || p_flags & TEXTURE_FLAG_MIPMAPS)) {
+ if (p_flags & TEXTURE_FLAG_USED_FOR_STREAMING) {
+ //not supported
+ ERR_PRINT("Streaming texture for non power of 2 or has mipmaps on this hardware: " + texture->path + "'. Mipmaps and repeat disabled.");
+ texture->flags &= ~(TEXTURE_FLAG_REPEAT | TEXTURE_FLAG_MIPMAPS);
+ } else {
+ texture->alloc_height = po2_height;
+ texture->alloc_width = po2_width;
+ texture->resize_to_po2 = true;
+ }
+ }
+ }
+
+ GLenum format;
+ GLenum internal_format;
+ GLenum type;
+ bool compressed = false;
+
+ Image::Format real_format;
+ _get_gl_image_and_format(Ref<Image>(),
+ texture->format,
+ texture->flags,
+ real_format,
+ format,
+ internal_format,
+ type,
+ compressed,
+ texture->resize_to_po2);
+
+ texture->gl_format_cache = format;
+ texture->gl_type_cache = type;
+ texture->gl_internal_format_cache = internal_format;
+ texture->data_size = 0;
+ texture->mipmaps = 1;
+
+ texture->compressed = compressed;
+ }
+#endif
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(texture->target, texture->tex_id);
+
+ // if (p_type == RS::TEXTURE_TYPE_EXTERNAL) {
+ // glTexParameteri(texture->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ // glTexParameteri(texture->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ // glTexParameteri(texture->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ // glTexParameteri(texture->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ // } else if (p_flags & TEXTURE_FLAG_USED_FOR_STREAMING) {
+ // //prealloc if video
+ // glTexImage2D(texture->target, 0, internal_format, texture->alloc_width, texture->alloc_height, 0, format, type, NULL);
+ // }
+
+ texture->active = true;
+}
+
+RID TextureStorage::texture_create() {
+ ERR_FAIL_COND_V(!_is_main_thread(), RID());
+
+ Texture *texture = memnew(Texture);
+ ERR_FAIL_COND_V(!texture, RID());
+ glGenTextures(1, &texture->tex_id);
+ texture->active = false;
+ texture->total_data_size = 0;
+
+ return texture_owner.make_rid(texture);
+}
+
+RID TextureStorage::texture_allocate() {
+ RID id = texture_create();
+ ERR_FAIL_COND_V(id == RID(), id);
+ return id;
+}
+
+void TextureStorage::texture_free(RID p_rid) {
+ Texture *t = texture_owner.get_or_null(p_rid);
+
+ // can't free a render target texture
+ ERR_FAIL_COND(t->render_target);
+ if (t->canvas_texture) {
+ memdelete(t->canvas_texture);
+ }
+
+ // info.texture_mem -= t->total_data_size; // TODO make this work again!!
+ texture_owner.free(p_rid);
+ memdelete(t);
+}
+
+void TextureStorage::texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) {
+ Texture *tex = texture_owner.get_or_null(p_texture);
+ ERR_FAIL_COND(!tex);
+
+ int w = p_image->get_width();
+ int h = p_image->get_height();
+
+ _texture_allocate_internal(p_texture, w, h, 1, p_image->get_format(), RenderingDevice::TEXTURE_TYPE_2D, 0);
+ texture_set_data(p_texture, p_image);
+}
+
+void TextureStorage::texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) {
+}
+
+void TextureStorage::texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) {
+}
+
+void TextureStorage::texture_proxy_initialize(RID p_texture, RID p_base) {
+ texture_set_proxy(p_texture, p_base);
+}
+
+//RID TextureStorage::texture_2d_create(const Ref<Image> &p_image) {
+// RID id = texture_create();
+// ERR_FAIL_COND_V(id == RID(), id);
+
+// int w = p_image->get_width();
+// int h = p_image->get_height();
+
+// texture_allocate(id, w, h, 1, p_image->get_format(), RenderingDevice::TEXTURE_TYPE_2D, 0);
+
+// texture_set_data(id, p_image);
+
+// return id;
+//}
+
+//RID TextureStorage::texture_2d_layered_create(const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) {
+// return RID();
+//}
+
+//void TextureStorage::texture_2d_update_immediate(RID p_texture, const Ref<Image> &p_image, int p_layer) {
+// // only 1 layer so far
+// texture_set_data(p_texture, p_image);
+//}
+
+void TextureStorage::texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer) {
+ // only 1 layer so far
+ texture_set_data(p_texture, p_image);
+}
+
+void TextureStorage::texture_2d_placeholder_initialize(RID p_texture) {
+}
+
+void TextureStorage::texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) {
+}
+
+void TextureStorage::texture_3d_placeholder_initialize(RID p_texture) {
+}
+
+Ref<Image> TextureStorage::texture_2d_get(RID p_texture) const {
+ Texture *tex = texture_owner.get_or_null(p_texture);
+ ERR_FAIL_COND_V(!tex, Ref<Image>());
+
+ /*
+#ifdef TOOLS_ENABLED
+ if (tex->image_cache_2d.is_valid()) {
+ return tex->image_cache_2d;
+ }
+#endif
+ Vector<uint8_t> data = RD::get_singleton()->texture_get_data(tex->rd_texture, 0);
+ ERR_FAIL_COND_V(data.size() == 0, Ref<Image>());
+ Ref<Image> image;
+ image.instance();
+ image->create(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data);
+ ERR_FAIL_COND_V(image->empty(), Ref<Image>());
+ if (tex->format != tex->validated_format) {
+ image->convert(tex->format);
+ }
+
+#ifdef TOOLS_ENABLED
+ if (Engine::get_singleton()->is_editor_hint()) {
+ tex->image_cache_2d = image;
+ }
+#endif
+*/
+ ERR_FAIL_COND_V(!tex->images.size(), Ref<Image>());
+
+ return tex->images[0];
+
+ // return image;
+
+ // return Ref<Image>();
+}
+
+void TextureStorage::texture_replace(RID p_texture, RID p_by_texture) {
+ Texture *tex_to = texture_owner.get_or_null(p_texture);
+ ERR_FAIL_COND(!tex_to);
+ Texture *tex_from = texture_owner.get_or_null(p_by_texture);
+ ERR_FAIL_COND(!tex_from);
+
+ tex_to->destroy();
+ tex_to->copy_from(*tex_from);
+
+ // copy image data and upload to GL
+ tex_to->images.resize(tex_from->images.size());
+
+ for (int n = 0; n < tex_from->images.size(); n++) {
+ texture_set_data(p_texture, tex_from->images[n], n);
+ }
+
+ texture_free(p_by_texture);
+}
+
+void TextureStorage::texture_set_size_override(RID p_texture, int p_width, int p_height) {
+ Texture *texture = texture_owner.get_or_null(p_texture);
+
+ ERR_FAIL_COND(!texture);
+ ERR_FAIL_COND(texture->render_target);
+
+ ERR_FAIL_COND(p_width <= 0 || p_width > 16384);
+ ERR_FAIL_COND(p_height <= 0 || p_height > 16384);
+ //real texture size is in alloc width and height
+ texture->width = p_width;
+ texture->height = p_height;
+}
+
+void TextureStorage::texture_set_path(RID p_texture, const String &p_path) {
+ Texture *texture = texture_owner.get_or_null(p_texture);
+ ERR_FAIL_COND(!texture);
+
+ texture->path = p_path;
+}
+
+String TextureStorage::texture_get_path(RID p_texture) const {
+ Texture *texture = texture_owner.get_or_null(p_texture);
+ ERR_FAIL_COND_V(!texture, "");
+
+ return texture->path;
+}
+
+void TextureStorage::texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) {
+ Texture *texture = texture_owner.get_or_null(p_texture);
+ ERR_FAIL_COND(!texture);
+
+ texture->detect_3d = p_callback;
+ texture->detect_3d_ud = p_userdata;
+}
+
+void TextureStorage::texture_set_detect_srgb_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) {
+ Texture *texture = texture_owner.get_or_null(p_texture);
+ ERR_FAIL_COND(!texture);
+
+ texture->detect_srgb = p_callback;
+ texture->detect_srgb_ud = p_userdata;
+}
+
+void TextureStorage::texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) {
+ Texture *texture = texture_owner.get_or_null(p_texture);
+ ERR_FAIL_COND(!texture);
+
+ texture->detect_normal = p_callback;
+ texture->detect_normal_ud = p_userdata;
+}
+
+void TextureStorage::texture_debug_usage(List<RS::TextureInfo> *r_info) {
+ List<RID> textures;
+ texture_owner.get_owned_list(&textures);
+
+ for (List<RID>::Element *E = textures.front(); E; E = E->next()) {
+ Texture *t = texture_owner.get_or_null(E->get());
+ if (!t) {
+ continue;
+ }
+ RS::TextureInfo tinfo;
+ tinfo.path = t->path;
+ tinfo.format = t->format;
+ tinfo.width = t->alloc_width;
+ tinfo.height = t->alloc_height;
+ tinfo.depth = 0;
+ tinfo.bytes = t->total_data_size;
+ r_info->push_back(tinfo);
+ }
+}
+
+void TextureStorage::texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) {
+ Texture *texture = texture_owner.get_or_null(p_texture);
+ ERR_FAIL_COND(!texture);
+
+ texture->redraw_if_visible = p_enable;
+}
+
+Size2 TextureStorage::texture_size_with_proxy(RID p_texture) {
+ const Texture *texture = texture_owner.get_or_null(p_texture);
+ ERR_FAIL_COND_V(!texture, Size2());
+ if (texture->proxy) {
+ return Size2(texture->proxy->width, texture->proxy->height);
+ } else {
+ return Size2(texture->width, texture->height);
+ }
+}
+
+// example use in 3.2
+// VS::get_singleton()->texture_set_proxy(default_texture->proxy, texture_rid);
+
+// p_proxy is the source (pre-existing) texture?
+// and p_texture is the one that is being made into a proxy?
+//This naming is confusing. Comments!!!
+
+// The naming of the parameters seemed to be reversed?
+// The p_proxy is the source texture
+// and p_texture is actually the proxy????
+
+void TextureStorage::texture_set_proxy(RID p_texture, RID p_proxy) {
+ Texture *texture = texture_owner.get_or_null(p_texture);
+ ERR_FAIL_COND(!texture);
+
+ if (texture->proxy) {
+ texture->proxy->proxy_owners.erase(texture);
+ texture->proxy = nullptr;
+ }
+
+ if (p_proxy.is_valid()) {
+ Texture *proxy = texture_owner.get_or_null(p_proxy);
+ ERR_FAIL_COND(!proxy);
+ ERR_FAIL_COND(proxy == texture);
+ proxy->proxy_owners.insert(texture);
+ texture->proxy = proxy;
+ }
+}
+
+void TextureStorage::texture_set_data(RID p_texture, const Ref<Image> &p_image, int p_layer) {
+ Config *config = Config::get_singleton();
+ Texture *texture = texture_owner.get_or_null(p_texture);
+
+ ERR_FAIL_COND(!_is_main_thread());
+
+ ERR_FAIL_COND(!texture);
+ if (texture->target == GL_TEXTURE_3D) {
+ // Target is set to a 3D texture or array texture, exit early to avoid spamming errors
+ return;
+ }
+ ERR_FAIL_COND(!texture->active);
+ ERR_FAIL_COND(texture->render_target);
+ ERR_FAIL_COND(p_image.is_null());
+ ERR_FAIL_COND(texture->format != p_image->get_format());
+
+ ERR_FAIL_COND(!p_image->get_width());
+ ERR_FAIL_COND(!p_image->get_height());
+
+ // ERR_FAIL_COND(texture->type == RS::TEXTURE_TYPE_EXTERNAL);
+
+ GLenum type;
+ GLenum format;
+ GLenum internal_format;
+ bool compressed = false;
+
+ if (config->keep_original_textures && !(texture->flags & TEXTURE_FLAG_USED_FOR_STREAMING)) {
+ texture->images.write[p_layer] = p_image;
+ }
+
+ // print_line("texture_set_data width " + itos (p_image->get_width()) + " height " + itos(p_image->get_height()));
+
+ Image::Format real_format;
+ Ref<Image> img = _get_gl_image_and_format(p_image, p_image->get_format(), texture->flags, real_format, format, internal_format, type, compressed, texture->resize_to_po2);
+
+ if (texture->resize_to_po2) {
+ if (p_image->is_compressed()) {
+ ERR_PRINT("Texture '" + texture->path + "' is required to be a power of 2 because it uses either mipmaps or repeat, so it was decompressed. This will hurt performance and memory usage.");
+ }
+
+ if (img == p_image) {
+ img = img->duplicate();
+ }
+ img->resize_to_po2(false);
+ }
+
+ if (config->shrink_textures_x2 && (p_image->has_mipmaps() || !p_image->is_compressed()) && !(texture->flags & TEXTURE_FLAG_USED_FOR_STREAMING)) {
+ texture->alloc_height = MAX(1, texture->alloc_height / 2);
+ texture->alloc_width = MAX(1, texture->alloc_width / 2);
+
+ if (texture->alloc_width == img->get_width() / 2 && texture->alloc_height == img->get_height() / 2) {
+ img->shrink_x2();
+ } else if (img->get_format() <= Image::FORMAT_RGBA8) {
+ img->resize(texture->alloc_width, texture->alloc_height, Image::INTERPOLATE_BILINEAR);
+ }
+ }
+
+ GLenum blit_target = (texture->target == GL_TEXTURE_CUBE_MAP) ? _cube_side_enum[p_layer] : GL_TEXTURE_2D;
+
+ texture->data_size = img->get_data().size();
+ Vector<uint8_t> read = img->get_data();
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(texture->target, texture->tex_id);
+
+ texture->ignore_mipmaps = compressed && !img->has_mipmaps();
+
+ // set filtering and repeat state
+ _texture_set_state_from_flags(texture);
+
+ //set swizle for older format compatibility
+#ifdef GLES_OVER_GL
+ switch (texture->format) {
+ case Image::FORMAT_L8: {
+ glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_R, GL_RED);
+ glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_G, GL_RED);
+ glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_B, GL_RED);
+ glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_A, GL_ONE);
+
+ } break;
+ case Image::FORMAT_LA8: {
+ glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_R, GL_RED);
+ glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_G, GL_RED);
+ glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_B, GL_RED);
+ glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_A, GL_GREEN);
+ } break;
+ default: {
+ glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_R, GL_RED);
+ glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_G, GL_GREEN);
+ glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_B, GL_BLUE);
+ glTexParameteri(texture->target, GL_TEXTURE_SWIZZLE_A, GL_ALPHA);
+
+ } break;
+ }
+#endif
+
+ int mipmaps = ((texture->flags & TEXTURE_FLAG_MIPMAPS) && img->has_mipmaps()) ? img->get_mipmap_count() + 1 : 1;
+
+ int w = img->get_width();
+ int h = img->get_height();
+
+ int tsize = 0;
+
+ for (int i = 0; i < mipmaps; i++) {
+ int size, ofs;
+ img->get_mipmap_offset_and_size(i, ofs, size);
+
+ if (compressed) {
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+
+ int bw = w;
+ int bh = h;
+
+ glCompressedTexImage2D(blit_target, i, internal_format, bw, bh, 0, size, &read[ofs]);
+ } else {
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ if (texture->flags & TEXTURE_FLAG_USED_FOR_STREAMING) {
+ glTexSubImage2D(blit_target, i, 0, 0, w, h, format, type, &read[ofs]);
+ } else {
+ glTexImage2D(blit_target, i, internal_format, w, h, 0, format, type, &read[ofs]);
+ }
+ }
+
+ tsize += size;
+
+ w = MAX(1, w >> 1);
+ h = MAX(1, h >> 1);
+ }
+
+ // info.texture_mem -= texture->total_data_size; // TODO make this work again!!
+ texture->total_data_size = tsize;
+ // info.texture_mem += texture->total_data_size; // TODO make this work again!!
+
+ // printf("texture: %i x %i - size: %i - total: %i\n", texture->width, texture->height, tsize, info.texture_mem);
+
+ texture->stored_cube_sides |= (1 << p_layer);
+
+ if ((texture->flags & TEXTURE_FLAG_MIPMAPS) && mipmaps == 1 && !texture->ignore_mipmaps && (texture->type != RenderingDevice::TEXTURE_TYPE_CUBE || texture->stored_cube_sides == (1 << 6) - 1)) {
+ //generate mipmaps if they were requested and the image does not contain them
+ glGenerateMipmap(texture->target);
+ }
+
+ texture->mipmaps = mipmaps;
+}
+
+void TextureStorage::texture_set_data_partial(RID p_texture, const Ref<Image> &p_image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int p_dst_mip, int p_layer) {
+ // TODO
+ ERR_PRINT("Not implemented (ask Karroffel to do it :p)");
+}
+
+/*
+Ref<Image> TextureStorage::texture_get_data(RID p_texture, int p_layer) const {
+ Texture *texture = texture_owner.get_or_null(p_texture);
+
+ ERR_FAIL_COND_V(!texture, Ref<Image>());
+ ERR_FAIL_COND_V(!texture->active, Ref<Image>());
+ ERR_FAIL_COND_V(texture->data_size == 0 && !texture->render_target, Ref<Image>());
+
+ if (texture->type == RS::TEXTURE_TYPE_CUBEMAP && p_layer < 6 && p_layer >= 0 && !texture->images[p_layer].is_null()) {
+ return texture->images[p_layer];
+ }
+
+#ifdef GLES_OVER_GL
+
+ Image::Format real_format;
+ GLenum gl_format;
+ GLenum gl_internal_format;
+ GLenum gl_type;
+ bool compressed;
+ _get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, real_format, gl_format, gl_internal_format, gl_type, compressed, false);
+
+ PoolVector<uint8_t> data;
+
+ int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, real_format, texture->mipmaps > 1);
+
+ data.resize(data_size * 2); //add some memory at the end, just in case for buggy drivers
+ PoolVector<uint8_t>::Write wb = data.write();
+
+ glActiveTexture(GL_TEXTURE0);
+
+ glBindTexture(texture->target, texture->tex_id);
+
+ glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
+
+ for (int i = 0; i < texture->mipmaps; i++) {
+ int ofs = Image::get_image_mipmap_offset(texture->alloc_width, texture->alloc_height, real_format, i);
+
+ if (texture->compressed) {
+ glPixelStorei(GL_PACK_ALIGNMENT, 4);
+ glGetCompressedTexImage(texture->target, i, &wb[ofs]);
+ } else {
+ glPixelStorei(GL_PACK_ALIGNMENT, 1);
+ glGetTexImage(texture->target, i, texture->gl_format_cache, texture->gl_type_cache, &wb[ofs]);
+ }
+ }
+
+ wb.release();
+
+ data.resize(data_size);
+
+ Image *img = memnew(Image(texture->alloc_width, texture->alloc_height, texture->mipmaps > 1, real_format, data));
+
+ return Ref<Image>(img);
+#else
+
+ Image::Format real_format;
+ GLenum gl_format;
+ GLenum gl_internal_format;
+ GLenum gl_type;
+ bool compressed;
+ _get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, real_format, gl_format, gl_internal_format, gl_type, compressed, texture->resize_to_po2);
+
+ PoolVector<uint8_t> data;
+
+ int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, Image::FORMAT_RGBA8, false);
+
+ data.resize(data_size * 2); //add some memory at the end, just in case for buggy drivers
+ PoolVector<uint8_t>::Write wb = data.write();
+
+ GLuint temp_framebuffer;
+ glGenFramebuffers(1, &temp_framebuffer);
+
+ GLuint temp_color_texture;
+ glGenTextures(1, &temp_color_texture);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, temp_framebuffer);
+
+ glBindTexture(GL_TEXTURE_2D, temp_color_texture);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->alloc_width, texture->alloc_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, temp_color_texture, 0);
+
+ glDepthMask(GL_FALSE);
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_BLEND);
+ glDepthFunc(GL_LEQUAL);
+ glColorMask(1, 1, 1, 1);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, texture->tex_id);
+
+ glViewport(0, 0, texture->alloc_width, texture->alloc_height);
+
+ shaders.copy.bind();
+
+ glClearColor(0.0, 0.0, 0.0, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+ bind_quad_array();
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ glReadPixels(0, 0, texture->alloc_width, texture->alloc_height, GL_RGBA, GL_UNSIGNED_BYTE, &wb[0]);
+
+ glDeleteTextures(1, &temp_color_texture);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ glDeleteFramebuffers(1, &temp_framebuffer);
+
+ wb.release();
+
+ data.resize(data_size);
+
+ Image *img = memnew(Image(texture->alloc_width, texture->alloc_height, false, Image::FORMAT_RGBA8, data));
+ if (!texture->compressed) {
+ img->convert(real_format);
+ }
+
+ return Ref<Image>(img);
+
+#endif
+}
+*/
+
+void TextureStorage::texture_set_flags(RID p_texture, uint32_t p_flags) {
+ Texture *texture = texture_owner.get_or_null(p_texture);
+ ERR_FAIL_COND(!texture);
+
+ bool had_mipmaps = texture->flags & TEXTURE_FLAG_MIPMAPS;
+
+ texture->flags = p_flags;
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(texture->target, texture->tex_id);
+
+ // set filtering and repeat state
+ _texture_set_state_from_flags(texture);
+
+ if ((texture->flags & TEXTURE_FLAG_MIPMAPS) && !texture->ignore_mipmaps) {
+ if (!had_mipmaps && texture->mipmaps == 1) {
+ glGenerateMipmap(texture->target);
+ }
+ }
+}
+
+uint32_t TextureStorage::texture_get_flags(RID p_texture) const {
+ Texture *texture = texture_owner.get_or_null(p_texture);
+
+ ERR_FAIL_COND_V(!texture, 0);
+
+ return texture->flags;
+}
+
+Image::Format TextureStorage::texture_get_format(RID p_texture) const {
+ Texture *texture = texture_owner.get_or_null(p_texture);
+
+ ERR_FAIL_COND_V(!texture, Image::FORMAT_L8);
+
+ return texture->format;
+}
+
+RenderingDevice::TextureType TextureStorage::texture_get_type(RID p_texture) const {
+ Texture *texture = texture_owner.get_or_null(p_texture);
+
+ ERR_FAIL_COND_V(!texture, RenderingDevice::TEXTURE_TYPE_2D);
+
+ return texture->type;
+}
+
+uint32_t TextureStorage::texture_get_texid(RID p_texture) const {
+ Texture *texture = texture_owner.get_or_null(p_texture);
+
+ ERR_FAIL_COND_V(!texture, 0);
+
+ return texture->tex_id;
+}
+
+uint32_t TextureStorage::texture_get_width(RID p_texture) const {
+ Texture *texture = texture_owner.get_or_null(p_texture);
+
+ ERR_FAIL_COND_V(!texture, 0);
+
+ return texture->width;
+}
+
+uint32_t TextureStorage::texture_get_height(RID p_texture) const {
+ Texture *texture = texture_owner.get_or_null(p_texture);
+
+ ERR_FAIL_COND_V(!texture, 0);
+
+ return texture->height;
+}
+
+uint32_t TextureStorage::texture_get_depth(RID p_texture) const {
+ Texture *texture = texture_owner.get_or_null(p_texture);
+
+ ERR_FAIL_COND_V(!texture, 0);
+
+ return texture->depth;
+}
+
+void TextureStorage::texture_bind(RID p_texture, uint32_t p_texture_no) {
+ Texture *texture = texture_owner.get_or_null(p_texture);
+
+ ERR_FAIL_COND(!texture);
+
+ glActiveTexture(GL_TEXTURE0 + p_texture_no);
+ glBindTexture(texture->target, texture->tex_id);
+}
+
+void TextureStorage::texture_set_shrink_all_x2_on_set_data(bool p_enable) {
+ Config::get_singleton()->shrink_textures_x2 = p_enable;
+}
+
+RID TextureStorage::texture_create_radiance_cubemap(RID p_source, int p_resolution) const {
+ return RID();
+}
+
+void TextureStorage::textures_keep_original(bool p_enable) {
+ Config::get_singleton()->keep_original_textures = p_enable;
+}
+
+#endif // GLES3_ENABLED
diff --git a/drivers/gles3/storage/texture_storage.h b/drivers/gles3/storage/texture_storage.h
new file mode 100644
index 0000000000..8a921fbe10
--- /dev/null
+++ b/drivers/gles3/storage/texture_storage.h
@@ -0,0 +1,389 @@
+/*************************************************************************/
+/* texture_storage.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 TEXTURE_STORAGE_GLES3_H
+#define TEXTURE_STORAGE_GLES3_H
+
+#ifdef GLES3_ENABLED
+
+#include "canvas_texture_storage.h"
+#include "config.h"
+#include "core/os/os.h"
+#include "core/templates/rid_owner.h"
+#include "render_target_storage.h"
+#include "servers/rendering/storage/texture_storage.h"
+
+namespace GLES3 {
+
+#define _EXT_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
+#define _EXT_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
+#define _EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
+
+#define _EXT_COMPRESSED_RED_RGTC1_EXT 0x8DBB
+#define _EXT_COMPRESSED_RED_RGTC1 0x8DBB
+#define _EXT_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC
+#define _EXT_COMPRESSED_RG_RGTC2 0x8DBD
+#define _EXT_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE
+#define _EXT_COMPRESSED_SIGNED_RED_RGTC1_EXT 0x8DBC
+#define _EXT_COMPRESSED_RED_GREEN_RGTC2_EXT 0x8DBD
+#define _EXT_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT 0x8DBE
+#define _EXT_ETC1_RGB8_OES 0x8D64
+
+#define _EXT_COMPRESSED_RGBA_BPTC_UNORM 0x8E8C
+#define _EXT_COMPRESSED_SRGB_ALPHA_BPTC_UNORM 0x8E8D
+#define _EXT_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E
+#define _EXT_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F
+
+#define _GL_TEXTURE_EXTERNAL_OES 0x8D65
+
+#ifdef GLES_OVER_GL
+#define _GL_HALF_FLOAT_OES 0x140B
+#else
+#define _GL_HALF_FLOAT_OES 0x8D61
+#endif
+
+#define _EXT_TEXTURE_CUBE_MAP_SEAMLESS 0x884F
+
+#define _RED_OES 0x1903
+
+#define _DEPTH_COMPONENT24_OES 0x81A6
+
+#ifndef GLES_OVER_GL
+#define glClearDepth glClearDepthf
+#endif //!GLES_OVER_GL
+
+enum OpenGLTextureFlags {
+ TEXTURE_FLAG_MIPMAPS = 1, /// Enable automatic mipmap generation - when available
+ TEXTURE_FLAG_REPEAT = 2, /// Repeat texture (Tiling), otherwise Clamping
+ TEXTURE_FLAG_FILTER = 4, /// Create texture with linear (or available) filter
+ TEXTURE_FLAG_ANISOTROPIC_FILTER = 8,
+ TEXTURE_FLAG_CONVERT_TO_LINEAR = 16,
+ TEXTURE_FLAG_MIRRORED_REPEAT = 32, /// Repeat texture, with alternate sections mirrored
+ TEXTURE_FLAG_USED_FOR_STREAMING = 2048,
+ TEXTURE_FLAGS_DEFAULT = TEXTURE_FLAG_REPEAT | TEXTURE_FLAG_MIPMAPS | TEXTURE_FLAG_FILTER
+};
+
+struct Texture {
+ RID self;
+
+ Texture *proxy;
+ Set<Texture *> proxy_owners;
+
+ String path;
+ uint32_t flags;
+ int width, height, depth;
+ int alloc_width, alloc_height;
+ Image::Format format;
+ RenderingDevice::TextureType type;
+
+ GLenum target;
+ GLenum gl_format_cache;
+ GLenum gl_internal_format_cache;
+ GLenum gl_type_cache;
+
+ int data_size;
+ int total_data_size;
+ bool ignore_mipmaps;
+
+ bool compressed;
+
+ bool srgb;
+
+ int mipmaps;
+
+ bool resize_to_po2;
+
+ bool active;
+ GLenum tex_id;
+
+ uint16_t stored_cube_sides;
+
+ RenderTarget *render_target;
+
+ Vector<Ref<Image>> images;
+
+ bool redraw_if_visible;
+
+ RS::TextureDetectCallback detect_3d;
+ void *detect_3d_ud;
+
+ RS::TextureDetectCallback detect_srgb;
+ void *detect_srgb_ud;
+
+ RS::TextureDetectCallback detect_normal;
+ void *detect_normal_ud;
+
+ CanvasTexture *canvas_texture = nullptr;
+
+ // some silly opengl shenanigans where
+ // texture coords start from bottom left, means we need to draw render target textures upside down
+ // to be compatible with vulkan etc.
+ bool is_upside_down() const {
+ if (proxy) {
+ return proxy->is_upside_down();
+ }
+
+ return render_target != nullptr;
+ }
+
+ Texture() {
+ create();
+ }
+
+ _ALWAYS_INLINE_ Texture *get_ptr() {
+ if (proxy) {
+ return proxy; //->get_ptr(); only one level of indirection, else not inlining possible.
+ } else {
+ return this;
+ }
+ }
+
+ ~Texture() {
+ destroy();
+
+ if (tex_id != 0) {
+ glDeleteTextures(1, &tex_id);
+ }
+ }
+
+ void copy_from(const Texture &o) {
+ proxy = o.proxy;
+ flags = o.flags;
+ width = o.width;
+ height = o.height;
+ alloc_width = o.alloc_width;
+ alloc_height = o.alloc_height;
+ format = o.format;
+ type = o.type;
+ target = o.target;
+ data_size = o.data_size;
+ total_data_size = o.total_data_size;
+ ignore_mipmaps = o.ignore_mipmaps;
+ compressed = o.compressed;
+ mipmaps = o.mipmaps;
+ resize_to_po2 = o.resize_to_po2;
+ active = o.active;
+ tex_id = o.tex_id;
+ stored_cube_sides = o.stored_cube_sides;
+ render_target = o.render_target;
+ redraw_if_visible = o.redraw_if_visible;
+ detect_3d = o.detect_3d;
+ detect_3d_ud = o.detect_3d_ud;
+ detect_srgb = o.detect_srgb;
+ detect_srgb_ud = o.detect_srgb_ud;
+ detect_normal = o.detect_normal;
+ detect_normal_ud = o.detect_normal_ud;
+
+ images.clear();
+ }
+
+ void create() {
+ proxy = nullptr;
+ flags = 0;
+ width = 0;
+ height = 0;
+ alloc_width = 0;
+ alloc_height = 0;
+ format = Image::FORMAT_L8;
+ type = RenderingDevice::TEXTURE_TYPE_2D;
+ target = 0;
+ data_size = 0;
+ total_data_size = 0;
+ ignore_mipmaps = false;
+ compressed = false;
+ mipmaps = 0;
+ resize_to_po2 = false;
+ active = false;
+ tex_id = 0;
+ stored_cube_sides = 0;
+ render_target = nullptr;
+ redraw_if_visible = false;
+ detect_3d = nullptr;
+ detect_3d_ud = nullptr;
+ detect_srgb = nullptr;
+ detect_srgb_ud = nullptr;
+ detect_normal = nullptr;
+ detect_normal_ud = nullptr;
+ }
+ void destroy() {
+ images.clear();
+
+ for (Set<Texture *>::Element *E = proxy_owners.front(); E; E = E->next()) {
+ E->get()->proxy = nullptr;
+ }
+
+ if (proxy) {
+ proxy->proxy_owners.erase(this);
+ }
+ }
+
+ // texture state
+ void GLSetFilter(GLenum p_target, RS::CanvasItemTextureFilter p_filter) {
+ if (p_filter == state_filter) {
+ return;
+ }
+ state_filter = p_filter;
+ GLint pmin = GL_LINEAR; // param min
+ GLint pmag = GL_LINEAR; // param mag
+ switch (state_filter) {
+ default: {
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: {
+ pmin = GL_LINEAR_MIPMAP_LINEAR;
+ pmag = GL_LINEAR;
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST: {
+ pmin = GL_NEAREST;
+ pmag = GL_NEAREST;
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: {
+ pmin = GL_NEAREST_MIPMAP_NEAREST;
+ pmag = GL_NEAREST;
+ } break;
+ }
+ glTexParameteri(p_target, GL_TEXTURE_MIN_FILTER, pmin);
+ glTexParameteri(p_target, GL_TEXTURE_MAG_FILTER, pmag);
+ }
+ void GLSetRepeat(GLenum p_target, RS::CanvasItemTextureRepeat p_repeat) {
+ if (p_repeat == state_repeat) {
+ return;
+ }
+ state_repeat = p_repeat;
+ GLint prep = GL_CLAMP_TO_EDGE; // parameter repeat
+ switch (state_repeat) {
+ default: {
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED: {
+ prep = GL_REPEAT;
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR: {
+ prep = GL_MIRRORED_REPEAT;
+ } break;
+ }
+ glTexParameteri(p_target, GL_TEXTURE_WRAP_S, prep);
+ glTexParameteri(p_target, GL_TEXTURE_WRAP_T, prep);
+ }
+
+private:
+ RS::CanvasItemTextureFilter state_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR;
+ RS::CanvasItemTextureRepeat state_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED;
+};
+
+class TextureStorage : public RendererTextureStorage {
+private:
+ static TextureStorage *singleton;
+
+ Thread::ID _main_thread_id = 0;
+ bool _is_main_thread();
+
+ mutable RID_PtrOwner<Texture> texture_owner;
+
+ Ref<Image> _get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, 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;
+ void _texture_set_state_from_flags(Texture *p_tex);
+
+ void texture_set_proxy(RID p_texture, RID p_proxy);
+
+public:
+ static TextureStorage *get_singleton();
+
+ TextureStorage();
+ virtual ~TextureStorage();
+
+ Texture *get_texture(RID p_rid) { return texture_owner.get_or_null(p_rid); };
+ bool owns_texture(RID p_rid) { return texture_owner.owns(p_rid); };
+ RID make_rid(Texture *p_texture) { return texture_owner.make_rid(p_texture); };
+
+ void set_main_thread_id(Thread::ID p_id);
+
+ virtual bool can_create_resources_async() const override;
+
+ RID texture_create();
+ void _texture_allocate_internal(RID p_texture, int p_width, int p_height, int p_depth_3d, Image::Format p_format, RenderingDevice::TextureType p_type, uint32_t p_flags = TEXTURE_FLAGS_DEFAULT);
+
+ virtual RID texture_allocate() override;
+ virtual void texture_free(RID p_rid) override;
+
+ virtual void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) override;
+ virtual void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) override;
+ virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) override;
+ virtual void texture_proxy_initialize(RID p_texture, RID p_base) override; //all slices, then all the mipmaps, must be coherent
+
+ virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override;
+ virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) override{};
+ virtual void texture_proxy_update(RID p_proxy, RID p_base) override{};
+
+ //these two APIs can be used together or in combination with the others.
+ virtual void texture_2d_placeholder_initialize(RID p_texture) override;
+ virtual void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) override;
+ virtual void texture_3d_placeholder_initialize(RID p_texture) override;
+
+ virtual Ref<Image> texture_2d_get(RID p_texture) const override;
+ virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const override { return Ref<Image>(); };
+ virtual Vector<Ref<Image>> texture_3d_get(RID p_texture) const override { return Vector<Ref<Image>>(); };
+
+ virtual void texture_replace(RID p_texture, RID p_by_texture) override;
+ virtual void texture_set_size_override(RID p_texture, int p_width, int p_height) override;
+
+ virtual void texture_set_path(RID p_texture, const String &p_path) override;
+ virtual String texture_get_path(RID p_texture) const override;
+
+ virtual void texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override;
+ void texture_set_detect_srgb_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata);
+ virtual void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override;
+ virtual void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) override{};
+
+ virtual void texture_debug_usage(List<RS::TextureInfo> *r_info) override;
+
+ virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) override;
+
+ virtual Size2 texture_size_with_proxy(RID p_proxy) override;
+
+ void texture_set_data(RID p_texture, const Ref<Image> &p_image, int p_layer = 0);
+ void texture_set_data_partial(RID p_texture, const Ref<Image> &p_image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int p_dst_mip, int p_layer = 0);
+ //Ref<Image> texture_get_data(RID p_texture, int p_layer = 0) const;
+ void texture_set_flags(RID p_texture, uint32_t p_flags);
+ uint32_t texture_get_flags(RID p_texture) const;
+ Image::Format texture_get_format(RID p_texture) const;
+ RenderingDevice::TextureType texture_get_type(RID p_texture) const;
+ uint32_t texture_get_texid(RID p_texture) const;
+ uint32_t texture_get_width(RID p_texture) const;
+ uint32_t texture_get_height(RID p_texture) const;
+ uint32_t texture_get_depth(RID p_texture) const;
+ void texture_bind(RID p_texture, uint32_t p_texture_no);
+ void texture_set_shrink_all_x2_on_set_data(bool p_enable);
+ RID texture_create_radiance_cubemap(RID p_source, int p_resolution = -1) const;
+ void textures_keep_original(bool p_enable);
+};
+
+} // namespace GLES3
+
+#endif // !GLES3_ENABLED
+
+#endif // !TEXTURE_STORAGE_GLES3_H
diff --git a/drivers/gles3/texture_loader_gles3.cpp b/drivers/gles3/texture_loader_gles3.cpp
index 1cbda02121..f8d4cfdc61 100644
--- a/drivers/gles3/texture_loader_gles3.cpp
+++ b/drivers/gles3/texture_loader_gles3.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "texture_loader_gles3.h"
+
#ifdef GLES3_ENABLED
#include "core/io/file_access.h"
diff --git a/drivers/png/resource_saver_png.cpp b/drivers/png/resource_saver_png.cpp
index 77390a5915..ca84fb6be9 100644
--- a/drivers/png/resource_saver_png.cpp
+++ b/drivers/png/resource_saver_png.cpp
@@ -46,7 +46,7 @@ Error ResourceSaverPNG::save(const String &p_path, const RES &p_resource, uint32
Error err = save_image(p_path, img);
return err;
-};
+}
Error ResourceSaverPNG::save_image(const String &p_path, const Ref<Image> &p_img) {
Vector<uint8_t> buffer;
@@ -89,4 +89,4 @@ void ResourceSaverPNG::get_recognized_extensions(const RES &p_resource, List<Str
ResourceSaverPNG::ResourceSaverPNG() {
Image::save_png_func = &save_image;
Image::save_png_buffer_func = &save_image_to_buffer;
-};
+}
diff --git a/drivers/unix/dir_access_unix.cpp b/drivers/unix/dir_access_unix.cpp
index 5fdfde4913..af47173b41 100644
--- a/drivers/unix/dir_access_unix.cpp
+++ b/drivers/unix/dir_access_unix.cpp
@@ -138,9 +138,9 @@ uint64_t DirAccessUnix::get_modified_time(String p_file) {
return flags.st_mtime;
} else {
ERR_FAIL_V(0);
- };
+ }
return 0;
-};
+}
String DirAccessUnix::get_next() {
if (!dir_stream) {
@@ -320,11 +320,11 @@ Error DirAccessUnix::make_dir(String p_dir) {
if (success) {
return OK;
- };
+ }
if (err == EEXIST) {
return ERR_ALREADY_EXISTS;
- };
+ }
return ERR_CANT_CREATE;
}
@@ -474,14 +474,14 @@ uint64_t DirAccessUnix::get_space_left() {
struct statvfs vfs;
if (statvfs(current_dir.utf8().get_data(), &vfs) != 0) {
return 0;
- };
+ }
return (uint64_t)vfs.f_bavail * (uint64_t)vfs.f_frsize;
#else
// FIXME: Implement this.
return 0;
#endif
-};
+}
String DirAccessUnix::get_filesystem_type() const {
return ""; //TODO this should be implemented
diff --git a/drivers/unix/file_access_unix.cpp b/drivers/unix/file_access_unix.cpp
index 80ae999ac9..ea442ad8bf 100644
--- a/drivers/unix/file_access_unix.cpp
+++ b/drivers/unix/file_access_unix.cpp
@@ -246,7 +246,7 @@ uint64_t FileAccessUnix::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
uint64_t read = fread(p_dst, 1, p_length, f);
check_errors();
return read;
-};
+}
Error FileAccessUnix::get_error() const {
return last_error;
@@ -285,8 +285,9 @@ bool FileAccessUnix::file_exists(const String &p_path) {
return false;
}
#else
- if (_access(filename.utf8().get_data(), 4) == -1)
+ if (_access(filename.utf8().get_data(), 4) == -1) {
return false;
+ }
#endif
// See if this is a regular file
@@ -309,7 +310,7 @@ uint64_t FileAccessUnix::_get_modified_time(const String &p_file) {
} else {
print_verbose("Failed to get modified time for: " + p_file + "");
return 0;
- };
+ }
}
uint32_t FileAccessUnix::_get_unix_permissions(const String &p_file) {
@@ -321,7 +322,7 @@ uint32_t FileAccessUnix::_get_unix_permissions(const String &p_file) {
return flags.st_mode & 0x7FF; //only permissions
} else {
ERR_FAIL_V_MSG(0, "Failed to get unix permissions for: " + p_file + ".");
- };
+ }
}
Error FileAccessUnix::_set_unix_permissions(const String &p_file, uint32_t p_permissions) {
diff --git a/drivers/unix/ip_unix.cpp b/drivers/unix/ip_unix.cpp
index d82dcb8a8d..d442e521bf 100644
--- a/drivers/unix/ip_unix.cpp
+++ b/drivers/unix/ip_unix.cpp
@@ -72,10 +72,10 @@ static IPAddress _sockaddr2ip(struct sockaddr *p_addr) {
} else if (p_addr->sa_family == AF_INET6) {
struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)p_addr;
ip.set_ipv6(addr6->sin6_addr.s6_addr);
- };
+ }
return ip;
-};
+}
void IPUnix::_resolve_hostname(List<IPAddress> &r_addresses, const String &p_hostname, Type p_type) const {
struct addrinfo hints;
@@ -90,14 +90,14 @@ void IPUnix::_resolve_hostname(List<IPAddress> &r_addresses, const String &p_hos
} else {
hints.ai_family = AF_UNSPEC;
hints.ai_flags = AI_ADDRCONFIG;
- };
+ }
hints.ai_flags &= ~AI_NUMERICHOST;
int s = getaddrinfo(p_hostname.utf8().get_data(), nullptr, &hints, &result);
if (s != 0) {
ERR_PRINT("getaddrinfo failed! Cannot resolve hostname.");
return;
- };
+ }
if (result == nullptr || result->ai_addr == nullptr) {
ERR_PRINT("Invalid response from getaddrinfo");
@@ -105,7 +105,7 @@ void IPUnix::_resolve_hostname(List<IPAddress> &r_addresses, const String &p_hos
freeaddrinfo(result);
}
return;
- };
+ }
struct addrinfo *next = result;
@@ -138,8 +138,9 @@ void IPUnix::get_local_interfaces(Map<String, Interface_Info> *r_interfaces) con
for (int i = 0; i < hostnames->Size; i++) {
auto hostname = hostnames->GetAt(i);
- if (hostname->Type != HostNameType::Ipv4 && hostname->Type != HostNameType::Ipv6)
+ if (hostname->Type != HostNameType::Ipv4 && hostname->Type != HostNameType::Ipv6) {
continue;
+ }
String name = hostname->RawName->Data();
Map<String, Interface_Info>::Element *E = r_interfaces->find(name);
@@ -171,14 +172,14 @@ void IPUnix::get_local_interfaces(Map<String, Interface_Info> *r_interfaces) con
nullptr, addrs, &buf_size);
if (err == NO_ERROR) {
break;
- };
+ }
memfree(addrs);
if (err == ERROR_BUFFER_OVERFLOW) {
continue; // will go back and alloc the right size
- };
+ }
ERR_FAIL_MSG("Call to GetAdaptersAddresses failed with error " + itos(err) + ".");
- };
+ }
IP_ADAPTER_ADDRESSES *adapter = addrs;
@@ -191,19 +192,21 @@ void IPUnix::get_local_interfaces(Map<String, Interface_Info> *r_interfaces) con
IP_ADAPTER_UNICAST_ADDRESS *address = adapter->FirstUnicastAddress;
while (address != nullptr) {
int family = address->Address.lpSockaddr->sa_family;
- if (family != AF_INET && family != AF_INET6)
+ if (family != AF_INET && family != AF_INET6) {
continue;
+ }
info.ip_addresses.push_front(_sockaddr2ip(address->Address.lpSockaddr));
address = address->Next;
}
adapter = adapter->Next;
// Only add interface if it has at least one IP
- if (info.ip_addresses.size() > 0)
+ if (info.ip_addresses.size() > 0) {
r_interfaces->insert(info.name, info);
- };
+ }
+ }
memfree(addrs);
-};
+}
#endif
diff --git a/drivers/unix/net_socket_posix.cpp b/drivers/unix/net_socket_posix.cpp
index bdfd264a0c..3130d5cae2 100644
--- a/drivers/unix/net_socket_posix.cpp
+++ b/drivers/unix/net_socket_posix.cpp
@@ -147,7 +147,7 @@ void NetSocketPosix::_set_ip_port(struct sockaddr_storage *p_addr, IPAddress *r_
if (r_port) {
*r_port = ntohs(addr6->sin6_port);
}
- };
+ }
}
NetSocket *NetSocketPosix::_create_func() {
@@ -325,8 +325,9 @@ Error NetSocketPosix::open(Type p_sock_type, IP::Type &ip_type) {
#if defined(__OpenBSD__)
// OpenBSD does not support dual stacking, fallback to IPv4 only.
- if (ip_type == IP::TYPE_ANY)
+ if (ip_type == IP::TYPE_ANY) {
ip_type = IP::TYPE_IPV4;
+ }
#endif
int family = ip_type == IP::TYPE_IPV4 ? AF_INET : AF_INET6;
@@ -420,7 +421,7 @@ Error NetSocketPosix::listen(int p_max_pending) {
print_verbose("Failed to listen from socket.");
close();
return FAILED;
- };
+ }
return OK;
}
@@ -494,8 +495,9 @@ Error NetSocketPosix::poll(PollType p_type, int p_timeout) const {
return FAILED;
}
- if (ret == 0)
+ if (ret == 0) {
return ERR_BUSY;
+ }
if (FD_ISSET(_sock, &ex)) {
_get_socket_error();
@@ -503,10 +505,12 @@ Error NetSocketPosix::poll(PollType p_type, int p_timeout) const {
return FAILED;
}
- if (rdp && FD_ISSET(_sock, rdp))
+ if (rdp && FD_ISSET(_sock, rdp)) {
ready = true;
- if (wrp && FD_ISSET(_sock, wrp))
+ }
+ if (wrp && FD_ISSET(_sock, wrp)) {
ready = true;
+ }
return ready ? OK : ERR_BUSY;
#else
diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp
index 00f84eba8c..3b5e1bf91d 100644
--- a/drivers/unix/os_unix.cpp
+++ b/drivers/unix/os_unix.cpp
@@ -65,6 +65,21 @@
#include <time.h>
#include <unistd.h>
+#if defined(OSX_ENABLED) || (defined(__ANDROID_API__) && __ANDROID_API__ >= 28)
+// Random location for getentropy. Fitting.
+#include <sys/random.h>
+#define UNIX_GET_ENTROPY
+#elif defined(__FreeBSD__) || defined(__OpenBSD__) || (defined(__GLIBC_MINOR__) && (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 26))
+// In <unistd.h>.
+// One day... (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 700)
+// https://publications.opengroup.org/standards/unix/c211
+#define UNIX_GET_ENTROPY
+#endif
+
+#if !defined(UNIX_GET_ENTROPY) && !defined(NO_URANDOM)
+#include <fcntl.h>
+#endif
+
/// Clock Setup function (used by get_ticks_usec)
static uint64_t _clock_start = 0;
#if defined(__APPLE__)
@@ -91,7 +106,7 @@ static void _setup_clock() {
void OS_Unix::debug_break() {
assert(false);
-};
+}
static void handle_interrupt(int sig) {
if (!EngineDebugger::is_active()) {
@@ -150,6 +165,31 @@ String OS_Unix::get_stdin_string(bool p_block) {
return "";
}
+Error OS_Unix::get_entropy(uint8_t *r_buffer, int p_bytes) {
+#if defined(UNIX_GET_ENTROPY)
+ int left = p_bytes;
+ int ofs = 0;
+ do {
+ int chunk = MIN(left, 256);
+ ERR_FAIL_COND_V(getentropy(r_buffer + ofs, chunk), FAILED);
+ left -= chunk;
+ ofs += chunk;
+ } while (left > 0);
+#elif !defined(NO_URANDOM)
+ int r = open("/dev/urandom", O_RDONLY);
+ ERR_FAIL_COND_V(r < 0, FAILED);
+ int left = p_bytes;
+ do {
+ ssize_t ret = read(r, r_buffer, p_bytes);
+ ERR_FAIL_COND_V(ret <= 0, FAILED);
+ left -= ret;
+ } while (left > 0);
+#else
+ return ERR_UNAVAILABLE;
+#endif
+ return OK;
+}
+
String OS_Unix::get_name() const {
return "Unix";
}
@@ -158,7 +198,7 @@ double OS_Unix::get_unix_time() const {
struct timeval tv_now;
gettimeofday(&tv_now, nullptr);
return (double)tv_now.tv_sec + double(tv_now.tv_usec) / 1000000;
-};
+}
OS::Date OS_Unix::get_date(bool p_utc) const {
time_t t = time(nullptr);
@@ -370,7 +410,7 @@ Error OS_Unix::kill(const ProcessID &p_pid) {
int OS_Unix::get_process_id() const {
return getpid();
-};
+}
bool OS_Unix::has_environment(const String &p_var) const {
return getenv(p_var.utf8().get_data()) != nullptr;
@@ -399,12 +439,12 @@ Error OS_Unix::open_dynamic_library(const String p_path, void *&p_library_handle
}
if (!FileAccess::exists(path)) {
- //this code exists so gdnative can load .so files from within the executable path
+ // This code exists so GDExtension can load .so files from within the executable path.
path = get_executable_path().get_base_dir().plus_file(p_path.get_file());
}
if (!FileAccess::exists(path)) {
- //this code exists so gdnative can load .so files from a standard unix location
+ // This code exists so GDExtension can load .so files from a standard unix location.
path = get_executable_path().get_base_dir().plus_file("../lib").plus_file(p_path.get_file());
}
@@ -515,8 +555,9 @@ String OS_Unix::get_executable_path() const {
char *resolved_path = new char[buff_size + 1];
- if (_NSGetExecutablePath(resolved_path, &buff_size) == 1)
+ if (_NSGetExecutablePath(resolved_path, &buff_size) == 1) {
WARN_PRINT("MAXPATHLEN is too small");
+ }
String path(resolved_path);
delete[] resolved_path;
diff --git a/drivers/unix/os_unix.h b/drivers/unix/os_unix.h
index 3f0e8a171c..460ba4b9e1 100644
--- a/drivers/unix/os_unix.h
+++ b/drivers/unix/os_unix.h
@@ -43,7 +43,6 @@ protected:
virtual void initialize_core();
virtual int unix_initialize_audio(int p_audio_driver);
- //virtual Error initialize(int p_video_driver,int p_audio_driver);
virtual void finalize_core() override;
@@ -54,15 +53,7 @@ public:
virtual String get_stdin_string(bool p_block) override;
- //virtual void set_mouse_show(bool p_show);
- //virtual void set_mouse_grab(bool p_grab);
- //virtual bool is_mouse_grab_enabled() const = 0;
- //virtual void get_mouse_position(int &x, int &y) const;
- //virtual void set_window_title(const String& p_title);
-
- //virtual void set_video_mode(const VideoMode& p_video_mode);
- //virtual VideoMode get_video_mode() const;
- //virtual void get_fullscreen_mode_list(List<VideoMode> *p_list) const;
+ virtual Error get_entropy(uint8_t *r_buffer, int p_bytes) override; // Should return cryptographycally-safe random bytes.
virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false) override;
virtual Error close_dynamic_library(void *p_library_handle) override;
diff --git a/drivers/unix/syslog_logger.cpp b/drivers/unix/syslog_logger.cpp
index 0e1a1a89a3..6189d645c6 100644
--- a/drivers/unix/syslog_logger.cpp
+++ b/drivers/unix/syslog_logger.cpp
@@ -31,7 +31,9 @@
#ifdef UNIX_ENABLED
#include "syslog_logger.h"
+
#include "core/string/print_string.h"
+
#include <syslog.h>
void SyslogLogger::logv(const char *p_format, va_list p_list, bool p_err) {
diff --git a/drivers/vulkan/SCsub b/drivers/vulkan/SCsub
index 8fe75367a8..b6ceb1cdea 100644
--- a/drivers/vulkan/SCsub
+++ b/drivers/vulkan/SCsub
@@ -40,6 +40,9 @@ 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":
+ # MoltenVK supports only Vulkan 1.1 API, limit VMA to the same version.
+ env_thirdparty_vma.AppendUnique(CPPDEFINES=["VMA_VULKAN_VERSION=1001000"])
env_thirdparty_vma.add_source_files(thirdparty_obj, thirdparty_sources_vma)
diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp
index ba623eb298..62de01e8bb 100644
--- a/drivers/vulkan/rendering_device_vulkan.cpp
+++ b/drivers/vulkan/rendering_device_vulkan.cpp
@@ -43,6 +43,8 @@
//#define FORCE_FULL_BARRIER
+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)
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;
@@ -1174,7 +1176,7 @@ uint32_t RenderingDeviceVulkan::get_image_format_required_size(DataFormat p_form
}
w = MAX(blockw, w >> 1);
h = MAX(blockh, h >> 1);
- d = MAX(1, d >> 1);
+ d = MAX(1u, d >> 1);
}
return size;
@@ -1182,23 +1184,23 @@ 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)
- int w = p_width;
- int h = p_height;
- int d = p_depth;
+ uint32_t w = p_width;
+ uint32_t h = p_height;
+ uint32_t d = p_depth;
- int mipmaps = 1;
+ uint32_t mipmaps = 1;
while (true) {
if (w == 1 && h == 1 && d == 1) {
break;
}
- w = MAX(1, w >> 1);
- h = MAX(1, h >> 1);
- d = MAX(1, d >> 1);
+ w = MAX(1u, w >> 1);
+ h = MAX(1u, h >> 1);
+ d = MAX(1u, d >> 1);
mipmaps++;
- };
+ }
return mipmaps;
}
@@ -1335,6 +1337,11 @@ Error RenderingDeviceVulkan::_buffer_allocate(Buffer *p_buffer, uint32_t p_size,
allocInfo.memoryTypeBits = 0;
allocInfo.pool = nullptr;
allocInfo.pUserData = nullptr;
+ if (p_size <= SMALL_ALLOCATION_MAX_SIZE) {
+ uint32_t mem_type_index = 0;
+ vmaFindMemoryTypeIndexForBufferInfo(allocator, &bufferInfo, &allocInfo, &mem_type_index);
+ allocInfo.pool = _find_or_create_small_allocs_pool(mem_type_index);
+ }
VkResult err = vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &p_buffer->buffer, &p_buffer->allocation, nullptr);
ERR_FAIL_COND_V_MSG(err, ERR_CANT_CREATE, "Can't create buffer of size: " + itos(p_size) + ", error " + itos(err) + ".");
@@ -1836,14 +1843,22 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T
//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);
+
VmaAllocationCreateInfo allocInfo;
allocInfo.flags = 0;
+ allocInfo.pool = nullptr;
allocInfo.usage = p_format.usage_bits & TEXTURE_USAGE_CPU_READ_BIT ? VMA_MEMORY_USAGE_CPU_ONLY : VMA_MEMORY_USAGE_GPU_ONLY;
allocInfo.requiredFlags = 0;
allocInfo.preferredFlags = 0;
allocInfo.memoryTypeBits = 0;
- allocInfo.pool = nullptr;
allocInfo.pUserData = nullptr;
+ if (image_size <= SMALL_ALLOCATION_MAX_SIZE) {
+ uint32_t mem_type_index = 0;
+ vmaFindMemoryTypeIndexForImageInfo(allocator, &image_create_info, &allocInfo, &mem_type_index);
+ allocInfo.pool = _find_or_create_small_allocs_pool(mem_type_index);
+ }
Texture texture;
@@ -2113,6 +2128,124 @@ RID RenderingDeviceVulkan::texture_create_shared(const TextureView &p_view, RID
return id;
}
+RID RenderingDeviceVulkan::texture_create_from_extension(TextureType p_type, DataFormat p_format, TextureSamples p_samples, uint64_t p_flags, uint64_t p_image, uint64_t p_width, uint64_t p_height, uint64_t p_depth, uint64_t p_layers) {
+ _THREAD_SAFE_METHOD_
+ // This method creates a texture object using a VkImage created by an extension, module or other external source (OpenXR uses this).
+ VkImage image = (VkImage)p_image;
+
+ 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
+ texture.type = p_type;
+ texture.format = p_format;
+ texture.samples = p_samples;
+ texture.width = p_width;
+ texture.height = p_height;
+ texture.depth = p_depth;
+ texture.layers = p_layers;
+ 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 ?
+
+ if (texture.usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
+ texture.read_aspect_mask = VK_IMAGE_ASPECT_DEPTH_BIT;
+ texture.barrier_aspect_mask = VK_IMAGE_ASPECT_DEPTH_BIT;
+
+ // if (format_has_stencil(p_format.format)) {
+ // texture.barrier_aspect_mask |= VK_IMAGE_ASPECT_STENCIL_BIT;
+ // }
+ } else {
+ texture.read_aspect_mask = VK_IMAGE_ASPECT_COLOR_BIT;
+ texture.barrier_aspect_mask = VK_IMAGE_ASPECT_COLOR_BIT;
+ }
+
+ // Create a view for us to use
+
+ VkImageViewCreateInfo image_view_create_info;
+ image_view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
+ image_view_create_info.pNext = nullptr;
+ image_view_create_info.flags = 0;
+ image_view_create_info.image = texture.image;
+
+ static const VkImageViewType view_types[TEXTURE_TYPE_MAX] = {
+ VK_IMAGE_VIEW_TYPE_1D,
+ VK_IMAGE_VIEW_TYPE_2D,
+ VK_IMAGE_VIEW_TYPE_3D,
+ VK_IMAGE_VIEW_TYPE_CUBE,
+ VK_IMAGE_VIEW_TYPE_1D_ARRAY,
+ VK_IMAGE_VIEW_TYPE_2D_ARRAY,
+ VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,
+ };
+
+ image_view_create_info.viewType = view_types[texture.type];
+ image_view_create_info.format = vulkan_formats[texture.format];
+
+ static const VkComponentSwizzle component_swizzles[TEXTURE_SWIZZLE_MAX] = {
+ VK_COMPONENT_SWIZZLE_IDENTITY,
+ VK_COMPONENT_SWIZZLE_ZERO,
+ VK_COMPONENT_SWIZZLE_ONE,
+ VK_COMPONENT_SWIZZLE_R,
+ VK_COMPONENT_SWIZZLE_G,
+ VK_COMPONENT_SWIZZLE_B,
+ VK_COMPONENT_SWIZZLE_A
+ };
+
+ // 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];
+ image_view_create_info.components.a = component_swizzles[TEXTURE_SWIZZLE_A];
+
+ image_view_create_info.subresourceRange.baseMipLevel = 0;
+ image_view_create_info.subresourceRange.levelCount = texture.mipmaps;
+ image_view_create_info.subresourceRange.baseArrayLayer = 0;
+ image_view_create_info.subresourceRange.layerCount = texture.layers;
+ if (texture.usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
+ image_view_create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
+ } else {
+ image_view_create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ }
+
+ VkResult err = vkCreateImageView(device, &image_view_create_info, nullptr, &texture.view);
+
+ if (err) {
+ // vmaDestroyImage(allocator, texture.image, texture.allocation);
+ ERR_FAIL_V_MSG(RID(), "vkCreateImageView failed with error " + itos(err) + ".");
+ }
+
+ //barrier to set layout
+ {
+ VkImageMemoryBarrier image_memory_barrier;
+ image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+ image_memory_barrier.pNext = nullptr;
+ image_memory_barrier.srcAccessMask = 0;
+ image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
+ image_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ image_memory_barrier.newLayout = texture.layout;
+ image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ image_memory_barrier.image = texture.image;
+ image_memory_barrier.subresourceRange.aspectMask = texture.barrier_aspect_mask;
+ image_memory_barrier.subresourceRange.baseMipLevel = 0;
+ image_memory_barrier.subresourceRange.levelCount = texture.mipmaps;
+ image_memory_barrier.subresourceRange.baseArrayLayer = 0;
+ image_memory_barrier.subresourceRange.layerCount = texture.layers;
+
+ vkCmdPipelineBarrier(frames[frame].setup_command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
+ }
+
+ RID id = texture_owner.make_rid(texture);
+
+ return id;
+}
+
RID RenderingDeviceVulkan::texture_create_shared_from_slice(const TextureView &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap, uint32_t p_mipmaps, TextureSliceType p_slice_type) {
_THREAD_SAFE_METHOD_
@@ -2423,8 +2556,8 @@ Error RenderingDeviceVulkan::_texture_update(RID p_texture, uint32_t p_layer, co
}
mipmap_offset = image_total;
- logic_width = MAX(1, logic_width >> 1);
- logic_height = MAX(1, logic_height >> 1);
+ logic_width = MAX(1u, logic_width >> 1);
+ logic_height = MAX(1u, logic_height >> 1);
}
//barrier to restore layout
@@ -2622,9 +2755,9 @@ Vector<uint8_t> RenderingDeviceVulkan::texture_get_data(RID p_texture, uint32_t
vkCmdCopyImageToBuffer(command_buffer, tex->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, tmp_buffer.buffer, 1, &buffer_image_copy);
- computed_w = MAX(1, computed_w >> 1);
- computed_h = MAX(1, computed_h >> 1);
- computed_d = MAX(1, computed_d >> 1);
+ computed_w = MAX(1u, computed_w >> 1);
+ computed_h = MAX(1u, computed_h >> 1);
+ computed_d = MAX(1u, computed_d >> 1);
offset += size;
}
@@ -3674,7 +3807,7 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
// Set view masks for each subpass
for (uint32_t i = 0; i < subpasses.size(); i++) {
view_masks.push_back(view_mask);
- };
+ }
render_pass_multiview_create_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO;
render_pass_multiview_create_info.pNext = nullptr;
@@ -4630,19 +4763,22 @@ Vector<uint8_t> RenderingDeviceVulkan::shader_compile_binary_from_spirv(const Ve
for (uint32_t j = 0; j < sc_count; j++) {
int32_t existing = -1;
RenderingDeviceVulkanShaderBinarySpecializationConstant sconst;
- sconst.constant_id = spec_constants[j]->constant_id;
- switch (spec_constants[j]->constant_type) {
+ SpvReflectSpecializationConstant *spc = spec_constants[j];
+
+ sconst.constant_id = spc->constant_id;
+ 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;
- sconst.bool_value = spec_constants[j]->default_value.int_bool_value != 0;
+ sconst.bool_value = spc->default_value.int_bool_value != 0;
} break;
case SPV_REFLECT_SPECIALIZATION_CONSTANT_INT: {
sconst.type = PIPELINE_SPECIALIZATION_CONSTANT_TYPE_INT;
- sconst.int_value = spec_constants[j]->default_value.int_bool_value;
+ sconst.int_value = spc->default_value.int_bool_value;
} break;
case SPV_REFLECT_SPECIALIZATION_CONSTANT_FLOAT: {
sconst.type = PIPELINE_SPECIALIZATION_CONSTANT_TYPE_FLOAT;
- sconst.float_value = spec_constants[j]->default_value.float_value;
+ sconst.float_value = spc->default_value.float_value;
} break;
}
sconst.stage_flags = 1 << p_spirv[i].shader_stage;
@@ -5496,18 +5632,18 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
switch (uniform.uniform_type) {
case UNIFORM_TYPE_SAMPLER: {
- if (uniform.ids.size() != set_uniform.length) {
+ if (uniform.get_id_count() != (uint32_t)set_uniform.length) {
if (set_uniform.length > 1) {
- ERR_FAIL_V_MSG(RID(), "Sampler (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") sampler elements, so it should be provided equal number of sampler IDs to satisfy it (IDs provided: " + itos(uniform.ids.size()) + ").");
+ ERR_FAIL_V_MSG(RID(), "Sampler (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") sampler elements, so it should be provided equal number of sampler IDs to satisfy it (IDs provided: " + itos(uniform.get_id_count()) + ").");
} else {
- ERR_FAIL_V_MSG(RID(), "Sampler (binding: " + itos(uniform.binding) + ") should provide one ID referencing a sampler (IDs provided: " + itos(uniform.ids.size()) + ").");
+ ERR_FAIL_V_MSG(RID(), "Sampler (binding: " + itos(uniform.binding) + ") should provide one ID referencing a sampler (IDs provided: " + itos(uniform.get_id_count()) + ").");
}
}
Vector<VkDescriptorImageInfo> image_info;
- for (int j = 0; j < uniform.ids.size(); j++) {
- VkSampler *sampler = sampler_owner.get_or_null(uniform.ids[j]);
+ for (uint32_t j = 0; j < uniform.get_id_count(); j++) {
+ VkSampler *sampler = sampler_owner.get_or_null(uniform.get_id(j));
ERR_FAIL_COND_V_MSG(!sampler, RID(), "Sampler (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") is not a valid sampler.");
VkDescriptorImageInfo img_info;
@@ -5519,31 +5655,31 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
}
write.dstArrayElement = 0;
- write.descriptorCount = uniform.ids.size();
+ write.descriptorCount = uniform.get_id_count();
write.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
write.pImageInfo = image_infos.push_back(image_info)->get().ptr();
write.pBufferInfo = nullptr;
write.pTexelBufferView = nullptr;
- type_size = uniform.ids.size();
+ type_size = uniform.get_id_count();
} break;
case UNIFORM_TYPE_SAMPLER_WITH_TEXTURE: {
- if (uniform.ids.size() != set_uniform.length * 2) {
+ if (uniform.get_id_count() != (uint32_t)set_uniform.length * 2) {
if (set_uniform.length > 1) {
- ERR_FAIL_V_MSG(RID(), "SamplerTexture (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") sampler&texture elements, so it should provided twice the amount of IDs (sampler,texture pairs) to satisfy it (IDs provided: " + itos(uniform.ids.size()) + ").");
+ ERR_FAIL_V_MSG(RID(), "SamplerTexture (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") sampler&texture elements, so it should provided twice the amount of IDs (sampler,texture pairs) to satisfy it (IDs provided: " + itos(uniform.get_id_count()) + ").");
} else {
- ERR_FAIL_V_MSG(RID(), "SamplerTexture (binding: " + itos(uniform.binding) + ") should provide two IDs referencing a sampler and then a texture (IDs provided: " + itos(uniform.ids.size()) + ").");
+ ERR_FAIL_V_MSG(RID(), "SamplerTexture (binding: " + itos(uniform.binding) + ") should provide two IDs referencing a sampler and then a texture (IDs provided: " + itos(uniform.get_id_count()) + ").");
}
}
Vector<VkDescriptorImageInfo> image_info;
- for (int j = 0; j < uniform.ids.size(); j += 2) {
- VkSampler *sampler = sampler_owner.get_or_null(uniform.ids[j + 0]);
+ for (uint32_t j = 0; j < uniform.get_id_count(); j += 2) {
+ VkSampler *sampler = sampler_owner.get_or_null(uniform.get_id(j + 0));
ERR_FAIL_COND_V_MSG(!sampler, RID(), "SamplerBuffer (binding: " + itos(uniform.binding) + ", index " + itos(j + 1) + ") is not a valid sampler.");
- Texture *texture = texture_owner.get_or_null(uniform.ids[j + 1]);
+ Texture *texture = texture_owner.get_or_null(uniform.get_id(j + 1));
ERR_FAIL_COND_V_MSG(!texture, RID(), "Texture (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") is not a valid texture.");
ERR_FAIL_COND_V_MSG(!(texture->usage_flags & TEXTURE_USAGE_SAMPLING_BIT), RID(),
@@ -5556,7 +5692,7 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
if (texture->usage_flags & (TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | TEXTURE_USAGE_INPUT_ATTACHMENT_BIT)) {
UniformSet::AttachableTexture attachable_texture;
attachable_texture.bind = set_uniform.binding;
- attachable_texture.texture = texture->owner.is_valid() ? texture->owner : uniform.ids[j + 1];
+ attachable_texture.texture = texture->owner.is_valid() ? texture->owner : uniform.get_id(j + 1);
attachable_textures.push_back(attachable_texture);
}
@@ -5575,28 +5711,28 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
}
write.dstArrayElement = 0;
- write.descriptorCount = uniform.ids.size() / 2;
+ write.descriptorCount = uniform.get_id_count() / 2;
write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
write.pImageInfo = image_infos.push_back(image_info)->get().ptr();
write.pBufferInfo = nullptr;
write.pTexelBufferView = nullptr;
- type_size = uniform.ids.size() / 2;
+ type_size = uniform.get_id_count() / 2;
} break;
case UNIFORM_TYPE_TEXTURE: {
- if (uniform.ids.size() != set_uniform.length) {
+ if (uniform.get_id_count() != (uint32_t)set_uniform.length) {
if (set_uniform.length > 1) {
- ERR_FAIL_V_MSG(RID(), "Texture (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") textures, so it should be provided equal number of texture IDs to satisfy it (IDs provided: " + itos(uniform.ids.size()) + ").");
+ ERR_FAIL_V_MSG(RID(), "Texture (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") textures, so it should be provided equal number of texture IDs to satisfy it (IDs provided: " + itos(uniform.get_id_count()) + ").");
} else {
- ERR_FAIL_V_MSG(RID(), "Texture (binding: " + itos(uniform.binding) + ") should provide one ID referencing a texture (IDs provided: " + itos(uniform.ids.size()) + ").");
+ ERR_FAIL_V_MSG(RID(), "Texture (binding: " + itos(uniform.binding) + ") should provide one ID referencing a texture (IDs provided: " + itos(uniform.get_id_count()) + ").");
}
}
Vector<VkDescriptorImageInfo> image_info;
- for (int j = 0; j < uniform.ids.size(); j++) {
- Texture *texture = texture_owner.get_or_null(uniform.ids[j]);
+ for (uint32_t j = 0; j < uniform.get_id_count(); j++) {
+ Texture *texture = texture_owner.get_or_null(uniform.get_id(j));
ERR_FAIL_COND_V_MSG(!texture, RID(), "Texture (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") is not a valid texture.");
ERR_FAIL_COND_V_MSG(!(texture->usage_flags & TEXTURE_USAGE_SAMPLING_BIT), RID(),
@@ -5609,7 +5745,7 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
if (texture->usage_flags & (TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | TEXTURE_USAGE_INPUT_ATTACHMENT_BIT)) {
UniformSet::AttachableTexture attachable_texture;
attachable_texture.bind = set_uniform.binding;
- attachable_texture.texture = texture->owner.is_valid() ? texture->owner : uniform.ids[j];
+ attachable_texture.texture = texture->owner.is_valid() ? texture->owner : uniform.get_id(j);
attachable_textures.push_back(attachable_texture);
}
@@ -5629,27 +5765,27 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
}
write.dstArrayElement = 0;
- write.descriptorCount = uniform.ids.size();
+ write.descriptorCount = uniform.get_id_count();
write.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
write.pImageInfo = image_infos.push_back(image_info)->get().ptr();
write.pBufferInfo = nullptr;
write.pTexelBufferView = nullptr;
- type_size = uniform.ids.size();
+ type_size = uniform.get_id_count();
} break;
case UNIFORM_TYPE_IMAGE: {
- if (uniform.ids.size() != set_uniform.length) {
+ if (uniform.get_id_count() != (uint32_t)set_uniform.length) {
if (set_uniform.length > 1) {
- ERR_FAIL_V_MSG(RID(), "Image (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") textures, so it should be provided equal number of texture IDs to satisfy it (IDs provided: " + itos(uniform.ids.size()) + ").");
+ ERR_FAIL_V_MSG(RID(), "Image (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") textures, so it should be provided equal number of texture IDs to satisfy it (IDs provided: " + itos(uniform.get_id_count()) + ").");
} else {
- ERR_FAIL_V_MSG(RID(), "Image (binding: " + itos(uniform.binding) + ") should provide one ID referencing a texture (IDs provided: " + itos(uniform.ids.size()) + ").");
+ ERR_FAIL_V_MSG(RID(), "Image (binding: " + itos(uniform.binding) + ") should provide one ID referencing a texture (IDs provided: " + itos(uniform.get_id_count()) + ").");
}
}
Vector<VkDescriptorImageInfo> image_info;
- for (int j = 0; j < uniform.ids.size(); j++) {
- Texture *texture = texture_owner.get_or_null(uniform.ids[j]);
+ for (uint32_t j = 0; j < uniform.get_id_count(); j++) {
+ Texture *texture = texture_owner.get_or_null(uniform.get_id(j));
ERR_FAIL_COND_V_MSG(!texture, RID(),
"Image (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") is not a valid texture.");
@@ -5677,29 +5813,29 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
}
write.dstArrayElement = 0;
- write.descriptorCount = uniform.ids.size();
+ write.descriptorCount = uniform.get_id_count();
write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
write.pImageInfo = image_infos.push_back(image_info)->get().ptr();
write.pBufferInfo = nullptr;
write.pTexelBufferView = nullptr;
- type_size = uniform.ids.size();
+ type_size = uniform.get_id_count();
} break;
case UNIFORM_TYPE_TEXTURE_BUFFER: {
- if (uniform.ids.size() != set_uniform.length) {
+ if (uniform.get_id_count() != (uint32_t)set_uniform.length) {
if (set_uniform.length > 1) {
- ERR_FAIL_V_MSG(RID(), "Buffer (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") texture buffer elements, so it should be provided equal number of texture buffer IDs to satisfy it (IDs provided: " + itos(uniform.ids.size()) + ").");
+ ERR_FAIL_V_MSG(RID(), "Buffer (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") texture buffer elements, so it should be provided equal number of texture buffer IDs to satisfy it (IDs provided: " + itos(uniform.get_id_count()) + ").");
} else {
- ERR_FAIL_V_MSG(RID(), "Buffer (binding: " + itos(uniform.binding) + ") should provide one ID referencing a texture buffer (IDs provided: " + itos(uniform.ids.size()) + ").");
+ ERR_FAIL_V_MSG(RID(), "Buffer (binding: " + itos(uniform.binding) + ") should provide one ID referencing a texture buffer (IDs provided: " + itos(uniform.get_id_count()) + ").");
}
}
Vector<VkDescriptorBufferInfo> buffer_info;
Vector<VkBufferView> buffer_view;
- for (int j = 0; j < uniform.ids.size(); j++) {
- TextureBuffer *buffer = texture_buffer_owner.get_or_null(uniform.ids[j]);
+ for (uint32_t j = 0; j < uniform.get_id_count(); j++) {
+ TextureBuffer *buffer = texture_buffer_owner.get_or_null(uniform.get_id(j));
ERR_FAIL_COND_V_MSG(!buffer, RID(), "Texture Buffer (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") is not a valid texture buffer.");
buffer_info.push_back(buffer->buffer.buffer_info);
@@ -5707,21 +5843,21 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
}
write.dstArrayElement = 0;
- write.descriptorCount = uniform.ids.size();
+ write.descriptorCount = uniform.get_id_count();
write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
write.pImageInfo = nullptr;
write.pBufferInfo = buffer_infos.push_back(buffer_info)->get().ptr();
write.pTexelBufferView = buffer_views.push_back(buffer_view)->get().ptr();
- type_size = uniform.ids.size();
+ type_size = uniform.get_id_count();
} break;
case UNIFORM_TYPE_SAMPLER_WITH_TEXTURE_BUFFER: {
- if (uniform.ids.size() != set_uniform.length * 2) {
+ if (uniform.get_id_count() != (uint32_t)set_uniform.length * 2) {
if (set_uniform.length > 1) {
- ERR_FAIL_V_MSG(RID(), "SamplerBuffer (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") sampler buffer elements, so it should provided twice the amount of IDs (sampler,buffer pairs) to satisfy it (IDs provided: " + itos(uniform.ids.size()) + ").");
+ ERR_FAIL_V_MSG(RID(), "SamplerBuffer (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") sampler buffer elements, so it should provided twice the amount of IDs (sampler,buffer pairs) to satisfy it (IDs provided: " + itos(uniform.get_id_count()) + ").");
} else {
- ERR_FAIL_V_MSG(RID(), "SamplerBuffer (binding: " + itos(uniform.binding) + ") should provide two IDs referencing a sampler and then a texture buffer (IDs provided: " + itos(uniform.ids.size()) + ").");
+ ERR_FAIL_V_MSG(RID(), "SamplerBuffer (binding: " + itos(uniform.binding) + ") should provide two IDs referencing a sampler and then a texture buffer (IDs provided: " + itos(uniform.get_id_count()) + ").");
}
}
@@ -5729,11 +5865,11 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
Vector<VkDescriptorBufferInfo> buffer_info;
Vector<VkBufferView> buffer_view;
- for (int j = 0; j < uniform.ids.size(); j += 2) {
- VkSampler *sampler = sampler_owner.get_or_null(uniform.ids[j + 0]);
+ for (uint32_t j = 0; j < uniform.get_id_count(); j += 2) {
+ VkSampler *sampler = sampler_owner.get_or_null(uniform.get_id(j + 0));
ERR_FAIL_COND_V_MSG(!sampler, RID(), "SamplerBuffer (binding: " + itos(uniform.binding) + ", index " + itos(j + 1) + ") is not a valid sampler.");
- TextureBuffer *buffer = texture_buffer_owner.get_or_null(uniform.ids[j + 1]);
+ TextureBuffer *buffer = texture_buffer_owner.get_or_null(uniform.get_id(j + 1));
VkDescriptorImageInfo img_info;
img_info.sampler = *sampler;
@@ -5749,23 +5885,23 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
}
write.dstArrayElement = 0;
- write.descriptorCount = uniform.ids.size() / 2;
+ write.descriptorCount = uniform.get_id_count() / 2;
write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
write.pImageInfo = image_infos.push_back(image_info)->get().ptr();
write.pBufferInfo = buffer_infos.push_back(buffer_info)->get().ptr();
write.pTexelBufferView = buffer_views.push_back(buffer_view)->get().ptr();
- type_size = uniform.ids.size() / 2;
+ type_size = uniform.get_id_count() / 2;
} break;
case UNIFORM_TYPE_IMAGE_BUFFER: {
//todo
} break;
case UNIFORM_TYPE_UNIFORM_BUFFER: {
- ERR_FAIL_COND_V_MSG(uniform.ids.size() != 1, RID(),
- "Uniform buffer supplied (binding: " + itos(uniform.binding) + ") must provide one ID (" + itos(uniform.ids.size()) + " provided).");
+ ERR_FAIL_COND_V_MSG(uniform.get_id_count() != 1, RID(),
+ "Uniform buffer supplied (binding: " + itos(uniform.binding) + ") must provide one ID (" + itos(uniform.get_id_count()) + " provided).");
- Buffer *buffer = uniform_buffer_owner.get_or_null(uniform.ids[0]);
+ Buffer *buffer = uniform_buffer_owner.get_or_null(uniform.get_id(0));
ERR_FAIL_COND_V_MSG(!buffer, RID(), "Uniform buffer supplied (binding: " + itos(uniform.binding) + ") is invalid.");
ERR_FAIL_COND_V_MSG(buffer->size != (uint32_t)set_uniform.length, RID(),
@@ -5780,15 +5916,15 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
} break;
case UNIFORM_TYPE_STORAGE_BUFFER: {
- ERR_FAIL_COND_V_MSG(uniform.ids.size() != 1, RID(),
- "Storage buffer supplied (binding: " + itos(uniform.binding) + ") must provide one ID (" + itos(uniform.ids.size()) + " provided).");
+ ERR_FAIL_COND_V_MSG(uniform.get_id_count() != 1, RID(),
+ "Storage buffer supplied (binding: " + itos(uniform.binding) + ") must provide one ID (" + itos(uniform.get_id_count()) + " provided).");
Buffer *buffer = nullptr;
- if (storage_buffer_owner.owns(uniform.ids[0])) {
- buffer = storage_buffer_owner.get_or_null(uniform.ids[0]);
- } else if (vertex_buffer_owner.owns(uniform.ids[0])) {
- buffer = vertex_buffer_owner.get_or_null(uniform.ids[0]);
+ if (storage_buffer_owner.owns(uniform.get_id(0))) {
+ buffer = storage_buffer_owner.get_or_null(uniform.get_id(0));
+ } else if (vertex_buffer_owner.owns(uniform.get_id(0))) {
+ buffer = vertex_buffer_owner.get_or_null(uniform.get_id(0));
ERR_FAIL_COND_V_MSG(!(buffer->usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), RID(), "Vertex buffer supplied (binding: " + itos(uniform.binding) + ") was not created with storage flag.");
}
@@ -5808,18 +5944,18 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
case UNIFORM_TYPE_INPUT_ATTACHMENT: {
ERR_FAIL_COND_V_MSG(shader->is_compute, RID(), "InputAttachment (binding: " + itos(uniform.binding) + ") supplied for compute shader (this is not allowed).");
- if (uniform.ids.size() != set_uniform.length) {
+ if (uniform.get_id_count() != (uint32_t)set_uniform.length) {
if (set_uniform.length > 1) {
- ERR_FAIL_V_MSG(RID(), "InputAttachment (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") textures, so it should be provided equal number of texture IDs to satisfy it (IDs provided: " + itos(uniform.ids.size()) + ").");
+ ERR_FAIL_V_MSG(RID(), "InputAttachment (binding: " + itos(uniform.binding) + ") is an array of (" + itos(set_uniform.length) + ") textures, so it should be provided equal number of texture IDs to satisfy it (IDs provided: " + itos(uniform.get_id_count()) + ").");
} else {
- ERR_FAIL_V_MSG(RID(), "InputAttachment (binding: " + itos(uniform.binding) + ") should provide one ID referencing a texture (IDs provided: " + itos(uniform.ids.size()) + ").");
+ ERR_FAIL_V_MSG(RID(), "InputAttachment (binding: " + itos(uniform.binding) + ") should provide one ID referencing a texture (IDs provided: " + itos(uniform.get_id_count()) + ").");
}
}
Vector<VkDescriptorImageInfo> image_info;
- for (int j = 0; j < uniform.ids.size(); j++) {
- Texture *texture = texture_owner.get_or_null(uniform.ids[j]);
+ for (uint32_t j = 0; j < uniform.get_id_count(); j++) {
+ Texture *texture = texture_owner.get_or_null(uniform.get_id(j));
ERR_FAIL_COND_V_MSG(!texture, RID(),
"InputAttachment (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") is not a valid texture.");
@@ -5842,13 +5978,13 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
}
write.dstArrayElement = 0;
- write.descriptorCount = uniform.ids.size();
+ write.descriptorCount = uniform.get_id_count();
write.descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
write.pImageInfo = image_infos.push_back(image_info)->get().ptr();
write.pBufferInfo = nullptr;
write.pTexelBufferView = nullptr;
- type_size = uniform.ids.size();
+ type_size = uniform.get_id_count();
} break;
default: {
}
@@ -5898,10 +6034,9 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
_add_dependency(id, p_shader);
for (uint32_t i = 0; i < uniform_count; i++) {
const Uniform &uniform = uniforms[i];
- int id_count = uniform.ids.size();
- const RID *ids = uniform.ids.ptr();
+ int id_count = uniform.get_id_count();
for (int j = 0; j < id_count; j++) {
- _add_dependency(id, ids[j]);
+ _add_dependency(id, uniform.get_id(j));
}
}
@@ -6321,7 +6456,7 @@ RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferForma
attachment_states.push_back(state);
idx++;
- };
+ }
}
ERR_FAIL_COND_V(attachment_states.size() != p_blend_state.attachments.size(), RID());
@@ -6647,6 +6782,10 @@ RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_begin_for_screen(Di
VkCommandBuffer command_buffer = frames[frame].draw_command_buffer;
+ if (!context->window_is_valid_swapchain(p_screen)) {
+ return INVALID_ID;
+ }
+
Size2i size = Size2i(context->window_get_width(p_screen), context->window_get_height(p_screen));
_draw_list_allocate(Rect2i(Vector2i(), size), 0, 0);
@@ -8587,6 +8726,30 @@ void RenderingDeviceVulkan::sync() {
local_device_processing = false;
}
+VmaPool RenderingDeviceVulkan::_find_or_create_small_allocs_pool(uint32_t p_mem_type_index) {
+ if (small_allocs_pools.has(p_mem_type_index)) {
+ return small_allocs_pools[p_mem_type_index];
+ }
+
+ print_verbose("Creating VMA small objects pool for memory type index " + itos(p_mem_type_index));
+
+ VmaPoolCreateInfo pci;
+ pci.memoryTypeIndex = p_mem_type_index;
+ pci.flags = 0;
+ pci.blockSize = 0;
+ pci.minBlockCount = 0;
+ pci.maxBlockCount = SIZE_MAX;
+ pci.priority = 0.5f;
+ pci.minAllocationAlignment = 0;
+ 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
+ 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
@@ -8707,9 +8870,9 @@ uint64_t RenderingDeviceVulkan::get_memory_usage(MemoryType p_type) const {
} else if (p_type == MEMORY_TEXTURES) {
return image_memory;
} else {
- VmaStats stats;
- vmaCalculateStats(allocator, &stats);
- return stats.total.usedBytes;
+ VmaTotalStatistics stats;
+ vmaCalculateStatistics(allocator, &stats);
+ return stats.total.statistics.allocationBytes;
}
}
@@ -8887,10 +9050,10 @@ void RenderingDeviceVulkan::initialize(VulkanContext *p_context, bool p_local_de
// 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(4, staging_buffer_block_size);
+ staging_buffer_block_size = MAX(4u, staging_buffer_block_size);
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(1, staging_buffer_max_size);
+ 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) {
@@ -8996,49 +9159,49 @@ uint64_t RenderingDeviceVulkan::get_driver_resource(DriverResource p_resource, R
switch (p_resource) {
case DRIVER_RESOURCE_VULKAN_DEVICE: {
return (uint64_t)context->get_device();
- }; break;
+ } break;
case DRIVER_RESOURCE_VULKAN_PHYSICAL_DEVICE: {
return (uint64_t)context->get_physical_device();
- }; break;
+ } break;
case DRIVER_RESOURCE_VULKAN_INSTANCE: {
return (uint64_t)context->get_instance();
- }; break;
+ } break;
case DRIVER_RESOURCE_VULKAN_QUEUE: {
return (uint64_t)context->get_graphics_queue();
- }; break;
+ } break;
case DRIVER_RESOURCE_VULKAN_QUEUE_FAMILY_INDEX: {
return context->get_graphics_queue_family_index();
- }; break;
+ } break;
case DRIVER_RESOURCE_VULKAN_IMAGE: {
Texture *tex = texture_owner.get_or_null(p_rid);
ERR_FAIL_NULL_V(tex, 0);
return (uint64_t)tex->image;
- }; break;
+ } break;
case DRIVER_RESOURCE_VULKAN_IMAGE_VIEW: {
Texture *tex = texture_owner.get_or_null(p_rid);
ERR_FAIL_NULL_V(tex, 0);
return (uint64_t)tex->view;
- }; break;
+ } break;
case DRIVER_RESOURCE_VULKAN_IMAGE_NATIVE_TEXTURE_FORMAT: {
Texture *tex = texture_owner.get_or_null(p_rid);
ERR_FAIL_NULL_V(tex, 0);
return vulkan_formats[tex->format];
- }; break;
+ } break;
case DRIVER_RESOURCE_VULKAN_SAMPLER: {
VkSampler *sampler = sampler_owner.get_or_null(p_rid);
ERR_FAIL_NULL_V(sampler, 0);
return uint64_t(*sampler);
- }; break;
+ } break;
case DRIVER_RESOURCE_VULKAN_DESCRIPTOR_SET: {
UniformSet *uniform_set = uniform_set_owner.get_or_null(p_rid);
ERR_FAIL_NULL_V(uniform_set, 0);
return uint64_t(uniform_set->descriptor_set);
- }; break;
+ } break;
case DRIVER_RESOURCE_VULKAN_BUFFER: {
Buffer *buffer = nullptr;
if (vertex_buffer_owner.owns(p_rid)) {
@@ -9056,23 +9219,23 @@ uint64_t RenderingDeviceVulkan::get_driver_resource(DriverResource p_resource, R
ERR_FAIL_NULL_V(buffer, 0);
return uint64_t(buffer->buffer);
- }; break;
+ } break;
case DRIVER_RESOURCE_VULKAN_COMPUTE_PIPELINE: {
ComputePipeline *compute_pipeline = compute_pipeline_owner.get_or_null(p_rid);
ERR_FAIL_NULL_V(compute_pipeline, 0);
return uint64_t(compute_pipeline->pipeline);
- }; break;
+ } break;
case DRIVER_RESOURCE_VULKAN_RENDER_PIPELINE: {
RenderPipeline *render_pipeline = render_pipeline_owner.get_or_null(p_rid);
ERR_FAIL_NULL_V(render_pipeline, 0);
return uint64_t(render_pipeline->pipeline);
- }; break;
+ } break;
default: {
// not supported for this driver
return 0;
- }; break;
+ } break;
}
}
@@ -9132,7 +9295,7 @@ String RenderingDeviceVulkan::get_captured_timestamp_name(uint32_t p_index) cons
return frames[frame].timestamp_result_names[p_index];
}
-int RenderingDeviceVulkan::limit_get(Limit p_limit) {
+uint64_t RenderingDeviceVulkan::limit_get(Limit p_limit) {
switch (p_limit) {
case LIMIT_MAX_BOUND_UNIFORM_SETS:
return limits.maxBoundDescriptorSets;
@@ -9276,6 +9439,11 @@ void RenderingDeviceVulkan::finalize() {
for (int i = 0; i < staging_buffer_blocks.size(); i++) {
vmaDestroyBuffer(allocator, staging_buffer_blocks[i].buffer, staging_buffer_blocks[i].allocation);
}
+ while (small_allocs_pools.size()) {
+ Map<uint32_t, VmaPool>::Element *E = small_allocs_pools.front();
+ vmaDestroyPool(allocator, E->get());
+ small_allocs_pools.erase(E);
+ }
vmaDestroyAllocator(allocator);
while (vertex_formats.size()) {
diff --git a/drivers/vulkan/rendering_device_vulkan.h b/drivers/vulkan/rendering_device_vulkan.h
index f42929ffa4..a4d5af91a4 100644
--- a/drivers/vulkan/rendering_device_vulkan.h
+++ b/drivers/vulkan/rendering_device_vulkan.h
@@ -1016,6 +1016,8 @@ class RenderingDeviceVulkan : public RenderingDevice {
void _free_pending_resources(int p_frame);
VmaAllocator allocator = nullptr;
+ Map<uint32_t, VmaPool> small_allocs_pools;
+ VmaPool _find_or_create_small_allocs_pool(uint32_t p_mem_type_index);
VulkanContext *context = nullptr;
@@ -1036,6 +1038,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
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);
+ virtual RID texture_create_from_extension(TextureType p_type, DataFormat p_format, TextureSamples p_samples, uint64_t p_flags, uint64_t p_image, uint64_t p_width, uint64_t p_height, uint64_t p_depth, uint64_t p_layers);
virtual RID texture_create_shared_from_slice(const TextureView &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap, uint32_t p_mipmaps = 1, TextureSliceType p_slice_type = TEXTURE_SLICE_2D);
virtual Error texture_update(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data, uint32_t p_post_barrier = BARRIER_MASK_ALL);
@@ -1200,7 +1203,7 @@ public:
/**** Limits ****/
/****************/
- virtual int limit_get(Limit p_limit);
+ virtual uint64_t limit_get(Limit p_limit);
virtual void prepare_screen_for_drawing();
void initialize(VulkanContext *p_context, bool p_local_device = false);
diff --git a/drivers/vulkan/vulkan_context.cpp b/drivers/vulkan/vulkan_context.cpp
index 689d76ba26..3551b5d6c4 100644
--- a/drivers/vulkan/vulkan_context.cpp
+++ b/drivers/vulkan/vulkan_context.cpp
@@ -46,6 +46,8 @@
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
#define APP_SHORT_NAME "GodotEngine"
+VulkanHooks *VulkanContext::vulkan_hooks = nullptr;
+
VKAPI_ATTR VkBool32 VKAPI_CALL VulkanContext::_debug_messenger_callback(
VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
VkDebugUtilsMessageTypeFlagsEXT messageType,
@@ -514,45 +516,62 @@ Error VulkanContext::_check_capabilities() {
subgroup_capabilities.supportedStages = 0;
subgroup_capabilities.supportedOperations = 0;
subgroup_capabilities.quadOperationsInAllStages = false;
+ shader_capabilities.shader_float16_is_supported = false;
+ shader_capabilities.shader_int8_is_supported = false;
+ storage_buffer_capabilities.storage_buffer_16_bit_access_is_supported = false;
+ storage_buffer_capabilities.uniform_and_storage_buffer_16_bit_access_is_supported = false;
+ storage_buffer_capabilities.storage_push_constant_16_is_supported = false;
+ storage_buffer_capabilities.storage_input_output_16 = false;
// check for extended features
- PFN_vkGetPhysicalDeviceFeatures2 device_features_func = (PFN_vkGetPhysicalDeviceFeatures2)vkGetInstanceProcAddr(inst, "vkGetPhysicalDeviceFeatures2");
- if (device_features_func == nullptr) {
+ 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
- device_features_func = (PFN_vkGetPhysicalDeviceFeatures2)vkGetInstanceProcAddr(inst, "vkGetPhysicalDeviceFeatures2KHR");
+ vkGetPhysicalDeviceFeatures2_func = (PFN_vkGetPhysicalDeviceFeatures2)vkGetInstanceProcAddr(inst, "vkGetPhysicalDeviceFeatures2KHR");
}
- if (device_features_func != nullptr) {
+ if (vkGetPhysicalDeviceFeatures2_func != nullptr) {
// check our extended features
- VkPhysicalDeviceMultiviewFeatures multiview_features;
- multiview_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES;
- multiview_features.pNext = nullptr;
+ VkPhysicalDeviceShaderFloat16Int8FeaturesKHR shader_features = {
+ /*sType*/ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES_KHR,
+ /*pNext*/ nullptr,
+ /*shaderFloat16*/ false,
+ /*shaderInt8*/ false,
+ };
+
+ VkPhysicalDevice16BitStorageFeaturesKHR storage_feature = {
+ /*sType*/ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR,
+ /*pNext*/ &shader_features,
+ /*storageBuffer16BitAccess*/ false,
+ /*uniformAndStorageBuffer16BitAccess*/ false,
+ /*storagePushConstant16*/ false,
+ /*storageInputOutput16*/ false,
+ };
+
+ VkPhysicalDeviceMultiviewFeatures multiview_features = {
+ /*sType*/ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES,
+ /*pNext*/ &storage_feature,
+ /*multiview*/ false,
+ /*multiviewGeometryShader*/ false,
+ /*multiviewTessellationShader*/ false,
+ };
VkPhysicalDeviceFeatures2 device_features;
device_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
device_features.pNext = &multiview_features;
- device_features_func(gpu, &device_features);
+ vkGetPhysicalDeviceFeatures2_func(gpu, &device_features);
+
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;
- VkPhysicalDeviceShaderFloat16Int8FeaturesKHR shader_features;
- shader_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES_KHR;
- shader_features.pNext = nullptr;
-
- device_features.pNext = &shader_features;
-
- device_features_func(gpu, &device_features);
shader_capabilities.shader_float16_is_supported = shader_features.shaderFloat16;
+ shader_capabilities.shader_int8_is_supported = shader_features.shaderInt8;
- VkPhysicalDevice16BitStorageFeaturesKHR storage_feature;
- storage_feature.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR;
- storage_feature.pNext = nullptr;
-
- device_features.pNext = &storage_feature;
-
- device_features_func(gpu, &device_features);
storage_buffer_capabilities.storage_buffer_16_bit_access_is_supported = storage_feature.storageBuffer16BitAccess;
+ storage_buffer_capabilities.uniform_and_storage_buffer_16_bit_access_is_supported = storage_feature.uniformAndStorageBuffer16BitAccess;
+ storage_buffer_capabilities.storage_push_constant_16_is_supported = storage_feature.storagePushConstant16;
+ storage_buffer_capabilities.storage_input_output_16 = storage_feature.storageInputOutput16;
}
// check extended properties
@@ -678,19 +697,27 @@ Error VulkanContext::_create_instance() {
inst_info.pNext = &dbg_report_callback_create_info;
}
- VkResult err = vkCreateInstance(&inst_info, nullptr, &inst);
- ERR_FAIL_COND_V_MSG(err == VK_ERROR_INCOMPATIBLE_DRIVER, ERR_CANT_CREATE,
- "Cannot find a compatible Vulkan installable client driver (ICD).\n\n"
- "vkCreateInstance Failure");
- ERR_FAIL_COND_V_MSG(err == VK_ERROR_EXTENSION_NOT_PRESENT, ERR_CANT_CREATE,
- "Cannot find a specified extension library.\n"
- "Make sure your layers path is set appropriately.\n"
- "vkCreateInstance Failure");
- ERR_FAIL_COND_V_MSG(err, ERR_CANT_CREATE,
- "vkCreateInstance failed.\n\n"
- "Do you have a compatible Vulkan installable client driver (ICD) installed?\n"
- "Please look at the Getting Started guide for additional information.\n"
- "vkCreateInstance Failure");
+ VkResult err;
+
+ if (vulkan_hooks) {
+ if (!vulkan_hooks->create_vulkan_instance(&inst_info, &inst)) {
+ return ERR_CANT_CREATE;
+ }
+ } else {
+ err = vkCreateInstance(&inst_info, nullptr, &inst);
+ ERR_FAIL_COND_V_MSG(err == VK_ERROR_INCOMPATIBLE_DRIVER, ERR_CANT_CREATE,
+ "Cannot find a compatible Vulkan installable client driver (ICD).\n\n"
+ "vkCreateInstance Failure");
+ ERR_FAIL_COND_V_MSG(err == VK_ERROR_EXTENSION_NOT_PRESENT, ERR_CANT_CREATE,
+ "Cannot find a specified extension library.\n"
+ "Make sure your layers path is set appropriately.\n"
+ "vkCreateInstance Failure");
+ ERR_FAIL_COND_V_MSG(err, ERR_CANT_CREATE,
+ "vkCreateInstance failed.\n\n"
+ "Do you have a compatible Vulkan installable client driver (ICD) installed?\n"
+ "Please look at the Getting Started guide for additional information.\n"
+ "vkCreateInstance Failure");
+ }
inst_initialized = true;
@@ -803,107 +830,122 @@ Error VulkanContext::_create_physical_device(VkSurfaceKHR p_surface) {
{ 0, nullptr },
};
- // 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.
-
int32_t device_index = -1;
- int type_selected = -1;
- print_verbose("Vulkan devices:");
- for (uint32_t i = 0; i < gpu_count; ++i) {
- VkPhysicalDeviceProperties props;
- vkGetPhysicalDeviceProperties(physical_devices[i], &props);
-
- bool present_supported = false;
-
- uint32_t device_queue_family_count = 0;
- vkGetPhysicalDeviceQueueFamilyProperties(physical_devices[i], &device_queue_family_count, nullptr);
- VkQueueFamilyProperties *device_queue_props = (VkQueueFamilyProperties *)malloc(device_queue_family_count * sizeof(VkQueueFamilyProperties));
- vkGetPhysicalDeviceQueueFamilyProperties(physical_devices[i], &device_queue_family_count, device_queue_props);
- for (uint32_t j = 0; j < device_queue_family_count; j++) {
- VkBool32 supports;
- vkGetPhysicalDeviceSurfaceSupportKHR(physical_devices[i], j, p_surface, &supports);
- if (supports && ((device_queue_props[j].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0)) {
- present_supported = true;
- } else {
- continue;
- }
+ if (vulkan_hooks) {
+ if (!vulkan_hooks->get_physical_device(&gpu)) {
+ return ERR_CANT_CREATE;
}
- String name = props.deviceName;
- String vendor = "Unknown";
- String dev_type;
- switch (props.deviceType) {
- case VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: {
- dev_type = "Discrete";
- } break;
- case VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: {
- dev_type = "Integrated";
- } break;
- case VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: {
- dev_type = "Virtual";
- } break;
- case VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_CPU: {
- dev_type = "CPU";
- } break;
- default: {
- dev_type = "Other";
- } break;
- }
- uint32_t vendor_idx = 0;
- while (vendor_names[vendor_idx].name != nullptr) {
- if (props.vendorID == vendor_names[vendor_idx].id) {
- vendor = vendor_names[vendor_idx].name;
+
+ // 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;
break;
}
- vendor_idx++;
}
- free(device_queue_props);
- print_verbose(" #" + itos(i) + ": " + vendor + " " + name + " - " + (present_supported ? "Supported" : "Unsupported") + ", " + dev_type);
-
- if (present_supported) { // Select first supported device of preffered type: Discrete > Integrated > Virtual > CPU > Other.
+ } 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.
+
+ int type_selected = -1;
+ print_verbose("Vulkan devices:");
+ for (uint32_t i = 0; i < gpu_count; ++i) {
+ VkPhysicalDeviceProperties props;
+ vkGetPhysicalDeviceProperties(physical_devices[i], &props);
+
+ bool present_supported = false;
+
+ uint32_t device_queue_family_count = 0;
+ vkGetPhysicalDeviceQueueFamilyProperties(physical_devices[i], &device_queue_family_count, nullptr);
+ VkQueueFamilyProperties *device_queue_props = (VkQueueFamilyProperties *)malloc(device_queue_family_count * sizeof(VkQueueFamilyProperties));
+ vkGetPhysicalDeviceQueueFamilyProperties(physical_devices[i], &device_queue_family_count, device_queue_props);
+ for (uint32_t j = 0; j < device_queue_family_count; j++) {
+ VkBool32 supports;
+ vkGetPhysicalDeviceSurfaceSupportKHR(physical_devices[i], j, p_surface, &supports);
+ if (supports && ((device_queue_props[j].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0)) {
+ present_supported = true;
+ } else {
+ continue;
+ }
+ }
+ String name = props.deviceName;
+ String vendor = "Unknown";
+ String dev_type;
switch (props.deviceType) {
case VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: {
- if (type_selected < 4) {
- type_selected = 4;
- device_index = i;
- }
+ dev_type = "Discrete";
} break;
case VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: {
- if (type_selected < 3) {
- type_selected = 3;
- device_index = i;
- }
+ dev_type = "Integrated";
} break;
case VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: {
- if (type_selected < 2) {
- type_selected = 2;
- device_index = i;
- }
+ dev_type = "Virtual";
} break;
case VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_CPU: {
- if (type_selected < 1) {
- type_selected = 1;
- device_index = i;
- }
+ dev_type = "CPU";
} break;
default: {
- if (type_selected < 0) {
- type_selected = 0;
- device_index = i;
- }
+ dev_type = "Other";
} break;
}
+ uint32_t vendor_idx = 0;
+ while (vendor_names[vendor_idx].name != nullptr) {
+ if (props.vendorID == vendor_names[vendor_idx].id) {
+ vendor = vendor_names[vendor_idx].name;
+ break;
+ }
+ vendor_idx++;
+ }
+ free(device_queue_props);
+ print_verbose(" #" + itos(i) + ": " + vendor + " " + name + " - " + (present_supported ? "Supported" : "Unsupported") + ", " + dev_type);
+
+ if (present_supported) { // Select first supported device of preffered type: Discrete > Integrated > Virtual > CPU > Other.
+ switch (props.deviceType) {
+ case VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: {
+ if (type_selected < 4) {
+ type_selected = 4;
+ device_index = i;
+ }
+ } break;
+ case VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: {
+ if (type_selected < 3) {
+ type_selected = 3;
+ device_index = i;
+ }
+ } break;
+ case VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: {
+ if (type_selected < 2) {
+ type_selected = 2;
+ device_index = i;
+ }
+ } break;
+ case VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_CPU: {
+ if (type_selected < 1) {
+ type_selected = 1;
+ device_index = i;
+ }
+ } break;
+ default: {
+ if (type_selected < 0) {
+ type_selected = 0;
+ device_index = i;
+ }
+ } break;
+ }
+ }
}
- }
- int32_t user_device_index = Engine::get_singleton()->get_gpu_index(); // Force user selected GPU.
- if (user_device_index >= 0 && user_device_index < (int32_t)gpu_count) {
- device_index = user_device_index;
- }
+ int32_t user_device_index = Engine::get_singleton()->get_gpu_index(); // Force user selected GPU.
+ if (user_device_index >= 0 && user_device_index < (int32_t)gpu_count) {
+ device_index = user_device_index;
+ }
+
+ ERR_FAIL_COND_V_MSG(device_index == -1, ERR_CANT_CREATE, "None of Vulkan devices supports both graphics and present queues.");
- ERR_FAIL_COND_V_MSG(device_index == -1, ERR_CANT_CREATE, "None of Vulkan devices supports both graphics and present queues.");
+ gpu = physical_devices[device_index];
+ }
- gpu = physical_devices[device_index];
free(physical_devices);
/* Look for device extensions */
@@ -1057,9 +1099,61 @@ Error VulkanContext::_create_device() {
queues[0].pQueuePriorities = queue_priorities;
queues[0].flags = 0;
+ // Before we retrieved what is supported, here we tell Vulkan we want to enable these features using the same structs.
+ void *nextptr = nullptr;
+
+ VkPhysicalDeviceShaderFloat16Int8FeaturesKHR shader_features = {
+ /*sType*/ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES_KHR,
+ /*pNext*/ nextptr,
+ /*shaderFloat16*/ shader_capabilities.shader_float16_is_supported,
+ /*shaderInt8*/ shader_capabilities.shader_int8_is_supported,
+ };
+ nextptr = &shader_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
+
+ vulkan11features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES;
+ vulkan11features.pNext = nextptr;
+ vulkan11features.storageBuffer16BitAccess = storage_buffer_capabilities.storage_buffer_16_bit_access_is_supported;
+ vulkan11features.uniformAndStorageBuffer16BitAccess = storage_buffer_capabilities.uniform_and_storage_buffer_16_bit_access_is_supported;
+ vulkan11features.storagePushConstant16 = storage_buffer_capabilities.storage_push_constant_16_is_supported;
+ vulkan11features.storageInputOutput16 = storage_buffer_capabilities.storage_input_output_16;
+ vulkan11features.multiview = multiview_capabilities.is_supported;
+ vulkan11features.multiviewGeometryShader = multiview_capabilities.geometry_shader_is_supported;
+ vulkan11features.multiviewTessellationShader = multiview_capabilities.tessellation_shader_is_supported;
+ vulkan11features.variablePointersStorageBuffer = 0;
+ vulkan11features.variablePointers = 0;
+ vulkan11features.protectedMemory = 0;
+ vulkan11features.samplerYcbcrConversion = 0;
+ vulkan11features.shaderDrawParameters = 0;
+ nextptr = &vulkan11features;
+ } else {
+ // 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;
+ storage_feature.uniformAndStorageBuffer16BitAccess = storage_buffer_capabilities.uniform_and_storage_buffer_16_bit_access_is_supported;
+ storage_feature.storagePushConstant16 = storage_buffer_capabilities.storage_push_constant_16_is_supported;
+ storage_feature.storageInputOutput16 = storage_buffer_capabilities.storage_input_output_16;
+ nextptr = &storage_feature;
+
+ if (vulkan_major == 1 && vulkan_minor == 1) {
+ multiview_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES;
+ multiview_features.pNext = nextptr;
+ multiview_features.multiview = multiview_capabilities.is_supported;
+ multiview_features.multiviewGeometryShader = multiview_capabilities.geometry_shader_is_supported;
+ multiview_features.multiviewTessellationShader = multiview_capabilities.tessellation_shader_is_supported;
+ nextptr = &multiview_features;
+ }
+ }
+
VkDeviceCreateInfo sdevice = {
/*sType*/ VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
- /*pNext*/ nullptr,
+ /*pNext*/ nextptr,
/*flags*/ 0,
/*queueCreateInfoCount*/ 1,
/*pQueueCreateInfos*/ queues,
@@ -1068,7 +1162,6 @@ Error VulkanContext::_create_device() {
/*enabledExtensionCount*/ enabled_extension_count,
/*ppEnabledExtensionNames*/ (const char *const *)extension_names,
/*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;
@@ -1080,39 +1173,15 @@ Error VulkanContext::_create_device() {
sdevice.queueCreateInfoCount = 2;
}
- VkPhysicalDeviceVulkan11Features vulkan11features;
- VkPhysicalDeviceMultiviewFeatures multiview_features;
- if (vulkan_major > 1 || vulkan_minor >= 2) {
- vulkan11features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES;
- vulkan11features.pNext = nullptr;
- // !BAS! Need to figure out which ones of these we want enabled...
- vulkan11features.storageBuffer16BitAccess = 0;
- vulkan11features.uniformAndStorageBuffer16BitAccess = 0;
- vulkan11features.storagePushConstant16 = 0;
- vulkan11features.storageInputOutput16 = 0;
- vulkan11features.multiview = multiview_capabilities.is_supported;
- vulkan11features.multiviewGeometryShader = multiview_capabilities.geometry_shader_is_supported;
- vulkan11features.multiviewTessellationShader = multiview_capabilities.tessellation_shader_is_supported;
- vulkan11features.variablePointersStorageBuffer = 0;
- vulkan11features.variablePointers = 0;
- vulkan11features.protectedMemory = 0;
- vulkan11features.samplerYcbcrConversion = 0;
- vulkan11features.shaderDrawParameters = 0;
-
- sdevice.pNext = &vulkan11features;
- } else if (vulkan_major == 1 && vulkan_minor == 1) {
- multiview_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES;
- multiview_features.pNext = nullptr;
- multiview_features.multiview = multiview_capabilities.is_supported;
- multiview_features.multiviewGeometryShader = multiview_capabilities.geometry_shader_is_supported;
- multiview_features.multiviewTessellationShader = multiview_capabilities.tessellation_shader_is_supported;
-
- sdevice.pNext = &multiview_features;
+ if (vulkan_hooks) {
+ if (!vulkan_hooks->create_vulkan_device(&sdevice, &device)) {
+ return ERR_CANT_CREATE;
+ }
+ } else {
+ err = vkCreateDevice(gpu, &sdevice, nullptr, &device);
+ ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
}
- err = vkCreateDevice(gpu, &sdevice, nullptr, &device);
- ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
-
return OK;
}
@@ -1348,6 +1417,12 @@ int VulkanContext::window_get_height(DisplayServer::WindowID p_window) {
return windows[p_window].height;
}
+bool VulkanContext::window_is_valid_swapchain(DisplayServer::WindowID p_window) {
+ ERR_FAIL_COND_V(!windows.has(p_window), false);
+ Window *w = &windows[p_window];
+ return w->swapchain_image_resources != VK_NULL_HANDLE;
+}
+
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];
@@ -1360,7 +1435,11 @@ VkFramebuffer VulkanContext::window_get_framebuffer(DisplayServer::WindowID p_wi
ERR_FAIL_COND_V(!buffers_prepared, VK_NULL_HANDLE);
Window *w = &windows[p_window];
//vulkan use of currentbuffer
- return w->swapchain_image_resources[w->current_buffer].framebuffer;
+ if (w->swapchain_image_resources != VK_NULL_HANDLE) {
+ return w->swapchain_image_resources[w->current_buffer].framebuffer;
+ } else {
+ return VK_NULL_HANDLE;
+ }
}
void VulkanContext::window_destroy(DisplayServer::WindowID p_window_id) {
@@ -1930,24 +2009,25 @@ Error VulkanContext::swap_buffers() {
}
VkSemaphore *semaphores_to_acquire = (VkSemaphore *)alloca(windows.size() * sizeof(VkSemaphore));
+ VkPipelineStageFlags *pipe_stage_flags = (VkPipelineStageFlags *)alloca(windows.size() * sizeof(VkPipelineStageFlags));
uint32_t semaphores_to_acquire_count = 0;
for (KeyValue<int, Window> &E : windows) {
Window *w = &E.value;
if (w->semaphore_acquired) {
- semaphores_to_acquire[semaphores_to_acquire_count++] = w->image_acquired_semaphores[frame_index];
+ semaphores_to_acquire[semaphores_to_acquire_count] = w->image_acquired_semaphores[frame_index];
+ pipe_stage_flags[semaphores_to_acquire_count] = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ semaphores_to_acquire_count++;
}
}
- VkPipelineStageFlags pipe_stage_flags;
VkSubmitInfo submit_info;
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submit_info.pNext = nullptr;
- submit_info.pWaitDstStageMask = &pipe_stage_flags;
- pipe_stage_flags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
submit_info.waitSemaphoreCount = semaphores_to_acquire_count;
submit_info.pWaitSemaphores = semaphores_to_acquire;
+ submit_info.pWaitDstStageMask = pipe_stage_flags;
submit_info.commandBufferCount = commands_to_submit;
submit_info.pCommandBuffers = commands_ptr;
submit_info.signalSemaphoreCount = 1;
@@ -1963,7 +2043,7 @@ Error VulkanContext::swap_buffers() {
// present queue before presenting, waiting for the draw complete
// semaphore and signalling the ownership released semaphore when finished
VkFence nullFence = VK_NULL_HANDLE;
- pipe_stage_flags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ pipe_stage_flags[0] = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
submit_info.waitSemaphoreCount = 1;
submit_info.pWaitSemaphores = &draw_complete_semaphores[frame_index];
submit_info.commandBufferCount = 0;
diff --git a/drivers/vulkan/vulkan_context.h b/drivers/vulkan/vulkan_context.h
index 67a675f6c6..8c0111714c 100644
--- a/drivers/vulkan/vulkan_context.h
+++ b/drivers/vulkan/vulkan_context.h
@@ -45,6 +45,8 @@
#include <vulkan/vulkan.h>
#endif
+#include "vulkan_hooks.h"
+
class VulkanContext {
public:
struct SubgroupCapabilities {
@@ -69,10 +71,14 @@ public:
struct ShaderCapabilities {
bool shader_float16_is_supported;
+ bool shader_int8_is_supported;
};
struct StorageBufferCapabilities {
bool storage_buffer_16_bit_access_is_supported;
+ bool uniform_and_storage_buffer_16_bit_access_is_supported;
+ bool storage_push_constant_16_is_supported;
+ bool storage_input_output_16;
};
private:
@@ -82,6 +88,7 @@ private:
FRAME_LAG = 2
};
+ static VulkanHooks *vulkan_hooks;
VkInstance inst = VK_NULL_HANDLE;
VkPhysicalDevice gpu = VK_NULL_HANDLE;
VkPhysicalDeviceProperties gpu_props;
@@ -263,9 +270,12 @@ public:
VkQueue get_graphics_queue() const;
uint32_t get_graphics_queue_family_index() const;
+ static void set_vulkan_hooks(VulkanHooks *p_vulkan_hooks) { vulkan_hooks = p_vulkan_hooks; };
+
void window_resize(DisplayServer::WindowID p_window_id, int p_width, int p_height);
int window_get_width(DisplayServer::WindowID p_window = 0);
int window_get_height(DisplayServer::WindowID p_window = 0);
+ bool window_is_valid_swapchain(DisplayServer::WindowID p_window = 0);
void window_destroy(DisplayServer::WindowID p_window_id);
VkFramebuffer window_get_framebuffer(DisplayServer::WindowID p_window = 0);
VkRenderPass window_get_render_pass(DisplayServer::WindowID p_window = 0);
diff --git a/drivers/vulkan/vulkan_hooks.h b/drivers/vulkan/vulkan_hooks.h
new file mode 100644
index 0000000000..3f244b4d45
--- /dev/null
+++ b/drivers/vulkan/vulkan_hooks.h
@@ -0,0 +1,48 @@
+/*************************************************************************/
+/* vulkan_hooks.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 VULKAN_HOOKS_H
+#define VULKAN_HOOKS_H
+
+#ifdef USE_VOLK
+#include <volk.h>
+#else
+#include <vulkan/vulkan.h>
+#endif
+
+class VulkanHooks {
+public:
+ virtual bool create_vulkan_instance(const VkInstanceCreateInfo *p_vulkan_create_info, VkInstance *r_instance) { return false; };
+ virtual bool get_physical_device(VkPhysicalDevice *r_device) { return false; };
+ virtual bool create_vulkan_device(const VkDeviceCreateInfo *p_device_create_info, VkDevice *r_device) { return false; };
+ virtual ~VulkanHooks(){};
+};
+
+#endif
diff --git a/drivers/wasapi/audio_driver_wasapi.cpp b/drivers/wasapi/audio_driver_wasapi.cpp
index c7a2d04436..c9609b469a 100644
--- a/drivers/wasapi/audio_driver_wasapi.cpp
+++ b/drivers/wasapi/audio_driver_wasapi.cpp
@@ -454,8 +454,9 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_c
Error AudioDriverWASAPI::init_render_device(bool reinit) {
Error err = audio_device_init(&audio_output, false, reinit);
- if (err != OK)
+ if (err != OK) {
return err;
+ }
switch (audio_output.channels) {
case 2: // Stereo
@@ -485,8 +486,9 @@ Error AudioDriverWASAPI::init_render_device(bool reinit) {
Error AudioDriverWASAPI::init_capture_device(bool reinit) {
Error err = audio_device_init(&audio_input, true, reinit);
- if (err != OK)
+ if (err != OK) {
return err;
+ }
// Get the max frames
UINT32 max_frames;
diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp
index cfd5d65f60..59dc1d8e77 100644
--- a/drivers/windows/file_access_windows.cpp
+++ b/drivers/windows/file_access_windows.cpp
@@ -87,7 +87,7 @@ Error FileAccessWindows::_open(const String &p_path, int p_mode_flags) {
if (!S_ISREG(st.st_mode)) {
return ERR_FILE_CANT_OPEN;
}
- };
+ }
#ifdef TOOLS_ENABLED
// Windows is case insensitive, but all other platforms are sensitive to it
@@ -269,7 +269,7 @@ uint64_t FileAccessWindows::get_buffer(uint8_t *p_dst, uint64_t p_length) const
uint64_t read = fread(p_dst, 1, p_length, f);
check_errors();
return read;
-};
+}
Error FileAccessWindows::get_error() const {
return last_error;
@@ -326,8 +326,9 @@ bool FileAccessWindows::file_exists(const String &p_name) {
uint64_t FileAccessWindows::_get_modified_time(const String &p_file) {
String file = fix_path(p_file);
- if (file.ends_with("/") && file != "/")
+ if (file.ends_with("/") && file != "/") {
file = file.substr(0, file.length() - 1);
+ }
struct _stat st;
int rv = _wstat((LPCWSTR)(file.utf16().get_data()), &st);