summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gles2/rasterizer_canvas_gles2.cpp74
-rw-r--r--drivers/gles2/rasterizer_scene_gles2.cpp16
-rw-r--r--drivers/gles2/rasterizer_scene_gles2.h1
-rw-r--r--drivers/gles2/rasterizer_storage_gles2.cpp239
-rw-r--r--drivers/gles2/rasterizer_storage_gles2.h2
-rw-r--r--drivers/gles2/shader_gles2.cpp35
-rw-r--r--drivers/gles2/shader_gles2.h3
-rw-r--r--drivers/gles2/shaders/canvas.glsl47
-rw-r--r--drivers/gles2/shaders/copy.glsl11
-rw-r--r--drivers/gles2/shaders/cubemap_filter.glsl38
-rw-r--r--drivers/gles2/shaders/scene.glsl29
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp31
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.h13
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.cpp125
-rw-r--r--drivers/gles3/shader_gles3.cpp28
-rw-r--r--drivers/gles3/shader_gles3.h1
-rw-r--r--drivers/gles3/shaders/copy.glsl23
-rw-r--r--drivers/gles3/shaders/scene.glsl4
-rw-r--r--drivers/unix/dir_access_unix.cpp4
-rw-r--r--drivers/unix/dir_access_unix.h3
-rw-r--r--drivers/windows/dir_access_windows.cpp29
-rw-r--r--drivers/windows/dir_access_windows.h3
-rw-r--r--drivers/windows/thread_windows.cpp11
23 files changed, 700 insertions, 70 deletions
diff --git a/drivers/gles2/rasterizer_canvas_gles2.cpp b/drivers/gles2/rasterizer_canvas_gles2.cpp
index 047eaaf0ac..6f686690bf 100644
--- a/drivers/gles2/rasterizer_canvas_gles2.cpp
+++ b/drivers/gles2/rasterizer_canvas_gles2.cpp
@@ -1162,7 +1162,65 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
void RasterizerCanvasGLES2::_copy_texscreen(const Rect2 &p_rect) {
- // This isn't really working yet, so disabling for now.
+ if (storage->frame.current_rt->copy_screen_effect.color == 0) {
+ ERR_EXPLAIN("Can't use screen texture copying in a render target configured without copy buffers");
+ ERR_FAIL();
+ }
+
+ glDisable(GL_BLEND);
+
+ state.canvas_texscreen_used = true;
+
+ Vector2 wh(storage->frame.current_rt->width, storage->frame.current_rt->height);
+
+ Color copy_section(p_rect.position.x / wh.x, p_rect.position.y / wh.y, p_rect.size.x / wh.x, p_rect.size.y / wh.y);
+
+ if (p_rect != Rect2()) {
+ storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_COPY_SECTION, true);
+ }
+
+ glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->copy_screen_effect.fbo);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color);
+
+ glClearColor(1, 0, 1, 1);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ storage->shaders.copy.bind();
+ storage->shaders.copy.set_uniform(CopyShaderGLES2::COPY_SECTION, copy_section);
+
+ const Vector2 vertpos[4] = {
+ Vector2(-1, -1),
+ Vector2(-1, 1),
+ Vector2(1, 1),
+ Vector2(1, -1),
+ };
+
+ const Vector2 uvpos[4] = {
+ Vector2(0, 0),
+ Vector2(0, 1),
+ Vector2(1, 1),
+ Vector2(1, 0)
+ };
+
+ const int indexpos[6] = {
+ 0, 1, 2,
+ 2, 3, 0
+ };
+
+ _draw_polygon(indexpos, 6, 4, vertpos, uvpos, NULL, false);
+
+ storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_COPY_SECTION, false);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo); //back to front
+
+ // back to canvas, force rebind
+ state.using_texture_rect = false;
+ state.canvas_shader.bind();
+ _bind_canvas_texture(state.current_tex, state.current_normal);
+ _set_uniforms();
+
+ glEnable(GL_BLEND);
}
void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, const Color &p_modulate, Light *p_light, const Transform2D &p_base_transform) {
@@ -1178,6 +1236,7 @@ void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, cons
state.current_tex = RID();
state.current_tex_ptr = NULL;
state.current_normal = RID();
+ state.canvas_texscreen_used = false;
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex);
@@ -1265,7 +1324,18 @@ void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, cons
if (shader_ptr) {
if (shader_ptr->canvas_item.uses_screen_texture) {
- _copy_texscreen(Rect2());
+ if (!state.canvas_texscreen_used) {
+ //copy if not copied before
+ _copy_texscreen(Rect2());
+
+ // blend mode will have been enabled so make sure we disable it again later on
+ //last_blend_mode = last_blend_mode != RasterizerStorageGLES2::Shader::CanvasItem::BLEND_MODE_DISABLED ? last_blend_mode : -1;
+ }
+
+ if (storage->frame.current_rt->copy_screen_effect.color) {
+ glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4);
+ glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->copy_screen_effect.color);
+ }
}
if (shader_ptr != shader_cache) {
diff --git a/drivers/gles2/rasterizer_scene_gles2.cpp b/drivers/gles2/rasterizer_scene_gles2.cpp
index e4783e907b..ae677b606d 100644
--- a/drivers/gles2/rasterizer_scene_gles2.cpp
+++ b/drivers/gles2/rasterizer_scene_gles2.cpp
@@ -524,7 +524,11 @@ bool RasterizerSceneGLES2::reflection_probe_instance_begin_render(RID p_instance
glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
glBindRenderbuffer(GL_RENDERBUFFER, rpi->depth); //resize depth buffer
+#ifdef JAVASCRIPT_ENABLED
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, size, size);
+#else
glRenderbufferStorage(GL_RENDERBUFFER, _DEPTH_COMPONENT24_OES, size, size);
+#endif
for (int i = 0; i < 6; i++) {
glBindFramebuffer(GL_FRAMEBUFFER, rpi->fbo[i]);
@@ -990,6 +994,12 @@ void RasterizerSceneGLES2::_add_geometry_with_material(RasterizerStorageGLES2::G
e->depth_layer = e->instance->depth_layer;
e->priority = p_material->render_priority;
+ if (has_alpha && p_material->shader->spatial.depth_draw_mode == RasterizerStorageGLES2::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) {
+ //add element to opaque
+ RenderList::Element *eo = render_list.add_element();
+ *eo = *e;
+ }
+
int rpsize = e->instance->reflection_probe_instances.size();
if (rpsize > 0) {
bool first = true;
@@ -2873,7 +2883,7 @@ void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_
if (light->type == VS::LIGHT_OMNI) {
// cubemap only
- if (light->omni_shadow_mode == VS::LIGHT_OMNI_SHADOW_CUBE) {
+ if (light->omni_shadow_mode == VS::LIGHT_OMNI_SHADOW_CUBE && storage->config.support_write_depth) {
int cubemap_index = shadow_cubemaps.size() - 1;
// find an appropriate cubemap to render to
@@ -2969,7 +2979,7 @@ void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_
state.scene_shader.set_conditional(SceneShaderGLES2::RENDER_DEPTH_DUAL_PARABOLOID, false);
// convert cubemap to dual paraboloid if needed
- if (light->type == VS::LIGHT_OMNI && light->omni_shadow_mode == VS::LIGHT_OMNI_SHADOW_CUBE && p_pass == 5) {
+ if (light->type == VS::LIGHT_OMNI && (light->omni_shadow_mode == VS::LIGHT_OMNI_SHADOW_CUBE && storage->config.support_write_depth) && p_pass == 5) {
ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas);
glBindFramebuffer(GL_FRAMEBUFFER, shadow_atlas->fbo);
@@ -3131,7 +3141,7 @@ void RasterizerSceneGLES2::initialize() {
}
// cubemaps for shadows
- {
+ if (storage->config.support_write_depth) { //not going to be used
int max_shadow_cubemap_sampler_size = 512;
int cube_size = max_shadow_cubemap_sampler_size;
diff --git a/drivers/gles2/rasterizer_scene_gles2.h b/drivers/gles2/rasterizer_scene_gles2.h
index 42ac621e45..0d917f4da2 100644
--- a/drivers/gles2/rasterizer_scene_gles2.h
+++ b/drivers/gles2/rasterizer_scene_gles2.h
@@ -473,6 +473,7 @@ public:
virtual void light_instance_set_transform(RID p_light_instance, const Transform &p_transform);
virtual void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_bias_scale = 1.0);
virtual void light_instance_mark_visible(RID p_light_instance);
+ virtual bool light_instances_can_render_shadow_cube() const { return storage->config.support_write_depth; }
LightInstance **render_light_instances;
int render_directional_lights;
diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp
index 0622a353df..f0deff4791 100644
--- a/drivers/gles2/rasterizer_storage_gles2.cpp
+++ b/drivers/gles2/rasterizer_storage_gles2.cpp
@@ -1715,8 +1715,196 @@ RID RasterizerStorageGLES2::mesh_create() {
return mesh_owner.make_rid(mesh);
}
+static PoolVector<uint8_t> _unpack_half_floats(const PoolVector<uint8_t> &array, uint32_t &format, int p_vertices) {
+
+ uint32_t p_format = format;
+
+ static int src_size[VS::ARRAY_MAX];
+ static int dst_size[VS::ARRAY_MAX];
+ static int to_convert[VS::ARRAY_MAX];
+
+ int src_stride = 0;
+ int dst_stride = 0;
+
+ for (int i = 0; i < VS::ARRAY_MAX; i++) {
+
+ to_convert[i] = 0;
+ if (!(p_format & (1 << i))) {
+ src_size[i] = 0;
+ dst_size[i] = 0;
+ continue;
+ }
+
+ switch (i) {
+
+ case VS::ARRAY_VERTEX: {
+
+ if (p_format & VS::ARRAY_COMPRESS_VERTEX) {
+
+ if (p_format & VS::ARRAY_FLAG_USE_2D_VERTICES) {
+ src_size[i] = 4;
+ dst_size[i] = 8;
+ to_convert[i] = 2;
+ } else {
+ src_size[i] = 8;
+ dst_size[i] = 12;
+ to_convert[i] = 3;
+ }
+
+ format &= ~VS::ARRAY_COMPRESS_VERTEX;
+ } else {
+
+ if (p_format & VS::ARRAY_FLAG_USE_2D_VERTICES) {
+ src_size[i] = 8;
+ dst_size[i] = 8;
+ } else {
+ src_size[i] = 12;
+ dst_size[i] = 12;
+ }
+ }
+
+ } break;
+ case VS::ARRAY_NORMAL: {
+
+ if (p_format & VS::ARRAY_COMPRESS_NORMAL) {
+ src_size[i] = 4;
+ dst_size[i] = 4;
+ } else {
+ src_size[i] = 12;
+ dst_size[i] = 12;
+ }
+
+ } break;
+ case VS::ARRAY_TANGENT: {
+
+ if (p_format & VS::ARRAY_COMPRESS_TANGENT) {
+ src_size[i] = 4;
+ dst_size[i] = 4;
+ } else {
+ src_size[i] = 16;
+ dst_size[i] = 16;
+ }
+
+ } break;
+ case VS::ARRAY_COLOR: {
+
+ if (p_format & VS::ARRAY_COMPRESS_COLOR) {
+ src_size[i] = 4;
+ dst_size[i] = 4;
+ } else {
+ src_size[i] = 16;
+ dst_size[i] = 16;
+ }
+
+ } break;
+ case VS::ARRAY_TEX_UV: {
+
+ if (p_format & VS::ARRAY_COMPRESS_TEX_UV) {
+ src_size[i] = 4;
+ to_convert[i] = 2;
+ format &= ~VS::ARRAY_COMPRESS_TEX_UV;
+ } else {
+ src_size[i] = 8;
+ }
+
+ dst_size[i] = 8;
+
+ } break;
+ case VS::ARRAY_TEX_UV2: {
+
+ if (p_format & VS::ARRAY_COMPRESS_TEX_UV2) {
+ src_size[i] = 4;
+ to_convert[i] = 2;
+ format &= ~VS::ARRAY_COMPRESS_TEX_UV2;
+ } else {
+ src_size[i] = 8;
+ }
+
+ dst_size[i] = 8;
+
+ } break;
+ case VS::ARRAY_BONES: {
+
+ if (p_format & VS::ARRAY_FLAG_USE_16_BIT_BONES) {
+ src_size[i] = 8;
+ dst_size[i] = 8;
+ } else {
+ src_size[i] = 4;
+ dst_size[i] = 4;
+ }
+
+ } break;
+ case VS::ARRAY_WEIGHTS: {
+
+ if (p_format & VS::ARRAY_COMPRESS_WEIGHTS) {
+ src_size[i] = 8;
+ dst_size[i] = 8;
+ } else {
+ src_size[i] = 16;
+ dst_size[i] = 16;
+ }
+
+ } break;
+ case VS::ARRAY_INDEX: {
+
+ src_size[i] = 0;
+ dst_size[i] = 0;
+
+ } break;
+ }
+
+ src_stride += src_size[i];
+ dst_stride += dst_size[i];
+ }
+
+ PoolVector<uint8_t> ret;
+ ret.resize(p_vertices * dst_stride);
+
+ PoolVector<uint8_t>::Read r = array.read();
+ PoolVector<uint8_t>::Write w = ret.write();
+
+ int src_offset = 0;
+ int dst_offset = 0;
+
+ for (int i = 0; i < VS::ARRAY_MAX; i++) {
+
+ if (src_size[i] == 0) {
+ continue; //no go
+ }
+ const uint8_t *rptr = r.ptr();
+ uint8_t *wptr = w.ptr();
+ if (to_convert[i]) { //converting
+
+ for (int j = 0; j < p_vertices; j++) {
+ const uint16_t *src = (const uint16_t *)&rptr[src_stride * j + src_offset];
+ float *dst = (float *)&wptr[dst_stride * j + dst_offset];
+
+ for (int k = 0; k < to_convert[i]; k++) {
+
+ dst[k] = Math::half_to_float(src[k]);
+ }
+ }
+
+ } else {
+ //just copy
+ for (int j = 0; j < p_vertices; j++) {
+ for (int k = 0; k < src_size[i]; k++) {
+ wptr[dst_stride * j + dst_offset + k] = rptr[src_stride * j + src_offset + k];
+ }
+ }
+ }
+
+ src_offset += src_size[i];
+ dst_offset += dst_size[i];
+ }
+
+ r = PoolVector<uint8_t>::Read();
+ w = PoolVector<uint8_t>::Write();
+
+ return ret;
+}
+
void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS::PrimitiveType p_primitive, const PoolVector<uint8_t> &p_array, int p_vertex_count, const PoolVector<uint8_t> &p_index_array, int p_index_count, const AABB &p_aabb, const Vector<PoolVector<uint8_t> > &p_blend_shapes, const Vector<AABB> &p_bone_aabbs) {
- PoolVector<uint8_t> array = p_array;
Mesh *mesh = mesh_owner.getornull(p_mesh);
ERR_FAIL_COND(!mesh);
@@ -1735,6 +1923,7 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
Surface::Attrib attribs[VS::ARRAY_MAX];
int stride = 0;
+ bool uses_half_float = false;
for (int i = 0; i < VS::ARRAY_MAX; i++) {
@@ -1763,6 +1952,7 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
if (p_format & VS::ARRAY_COMPRESS_VERTEX) {
attribs[i].type = _GL_HALF_FLOAT_OES;
stride += attribs[i].size * 2;
+ uses_half_float = true;
} else {
attribs[i].type = GL_FLOAT;
stride += attribs[i].size * 4;
@@ -1823,6 +2013,7 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
if (p_format & VS::ARRAY_COMPRESS_TEX_UV) {
attribs[i].type = _GL_HALF_FLOAT_OES;
stride += 4;
+ uses_half_float = true;
} else {
attribs[i].type = GL_FLOAT;
stride += 8;
@@ -1838,6 +2029,7 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
if (p_format & VS::ARRAY_COMPRESS_TEX_UV2) {
attribs[i].type = _GL_HALF_FLOAT_OES;
stride += 4;
+ uses_half_float = true;
} else {
attribs[i].type = GL_FLOAT;
stride += 8;
@@ -1900,6 +2092,7 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
}
//validate sizes
+ PoolVector<uint8_t> array = p_array;
int array_size = stride * p_vertex_count;
int index_array_size = 0;
@@ -1931,6 +2124,15 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
ERR_FAIL_COND(array.size() != array_size);
+ if (!config.support_half_float_vertices && uses_half_float) {
+
+ uint32_t new_format = p_format;
+ PoolVector<uint8_t> unpacked_array = _unpack_half_floats(array, new_format, p_vertex_count);
+
+ mesh_add_surface(p_mesh, new_format, p_primitive, unpacked_array, p_vertex_count, p_index_array, p_index_count, p_aabb, p_blend_shapes, p_bone_aabbs);
+ return; //do not go any further, above function used unpacked stuff will be used instead.
+ }
+
if (p_format & VS::ARRAY_FORMAT_INDEX) {
index_array_size = attribs[VS::ARRAY_INDEX].stride * p_index_count;
@@ -4007,7 +4209,11 @@ void RasterizerStorageGLES2::_render_target_allocate(RenderTarget *rt) {
glGenRenderbuffers(1, &rt->depth);
glBindRenderbuffer(GL_RENDERBUFFER, rt->depth);
+#ifdef JAVASCRIPT_ENABLED
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, rt->width, rt->height);
+#else
glRenderbufferStorage(GL_RENDERBUFFER, _DEPTH_COMPONENT24_OES, rt->width, rt->height);
+#endif
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
@@ -4045,7 +4251,8 @@ void RasterizerStorageGLES2::_render_target_allocate(RenderTarget *rt) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// copy texscreen buffers
- {
+ if (!(rt->flags[RasterizerStorage::RENDER_TARGET_NO_SAMPLING])) {
+
int w = rt->width;
int h = rt->height;
@@ -4053,10 +4260,17 @@ void RasterizerStorageGLES2::_render_target_allocate(RenderTarget *rt) {
glBindTexture(GL_TEXTURE_2D, rt->copy_screen_effect.color);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glGenFramebuffers(1, &rt->copy_screen_effect.fbo);
glBindFramebuffer(GL_FRAMEBUFFER, rt->copy_screen_effect.fbo);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color, 0);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->copy_screen_effect.color, 0);
+
+ glClearColor(0, 0, 0, 0);
+ glClear(GL_COLOR_BUFFER_BIT);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
@@ -4218,7 +4432,11 @@ RID RasterizerStorageGLES2::canvas_light_shadow_buffer_create(int p_width) {
glGenRenderbuffers(1, &cls->depth);
glBindRenderbuffer(GL_RENDERBUFFER, cls->depth);
- glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, cls->size, cls->height);
+#ifdef JAVASCRIPT_ENABLED
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, cls->size, cls->height);
+#else
+ glRenderbufferStorage(GL_RENDERBUFFER, _DEPTH_COMPONENT24_OES, cls->size, cls->height);
+#endif
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, cls->depth);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
@@ -4665,6 +4883,19 @@ void RasterizerStorageGLES2::initialize() {
config.support_32_bits_indices = config.extensions.has("GL_OES_element_index_uint");
#endif
+#ifdef GLES_OVER_GL
+ config.support_write_depth = true;
+#else
+ config.support_write_depth = config.extensions.has("GL_EXT_frag_depth");
+#endif
+
+#ifdef JAVASCRIPT_ENABLED
+ config.support_half_float_vertices = false;
+#else
+ //every other platform, be it mobile or desktop, supports this (even if not in the GLES2 spec).
+ config.support_half_float_vertices = true;
+#endif
+
frame.count = 0;
frame.delta = 0;
frame.current_rt = NULL;
diff --git a/drivers/gles2/rasterizer_storage_gles2.h b/drivers/gles2/rasterizer_storage_gles2.h
index ae14aaa9c0..ed21238db6 100644
--- a/drivers/gles2/rasterizer_storage_gles2.h
+++ b/drivers/gles2/rasterizer_storage_gles2.h
@@ -80,6 +80,8 @@ public:
bool use_rgba_2d_shadows;
bool support_32_bits_indices;
+ bool support_write_depth;
+ bool support_half_float_vertices;
} config;
struct Resources {
diff --git a/drivers/gles2/shader_gles2.cpp b/drivers/gles2/shader_gles2.cpp
index 65d4b63bb9..3bf5baec14 100644
--- a/drivers/gles2/shader_gles2.cpp
+++ b/drivers/gles2/shader_gles2.cpp
@@ -229,6 +229,7 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() {
glDeleteShader(v.vert_id);
glDeleteShader(v.frag_id);
glDeleteProgram(v.id);
+ memdelete_arr(v.uniform_location);
v.id = 0;
}
}
@@ -242,6 +243,11 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() {
strings.push_back("#define USE_GLES_OVER_GL\n");
#else
strings.push_back("#version 100\n");
+//angle does not like
+#ifdef JAVASCRIPT_ENABLED
+ strings.push_back("#define USE_HIGHP_PRECISION\n");
+#endif
+
#endif
int define_line_ofs = 1;
@@ -323,6 +329,7 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() {
if (iloglen < 0) {
glDeleteShader(v.vert_id);
glDeleteProgram(v.id);
+ memdelete_arr(v.uniform_location);
v.id = 0;
ERR_PRINT("No OpenGL vertex shader compiler log. What the frick?");
@@ -344,6 +351,7 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() {
Memory::free_static(ilogmem);
glDeleteShader(v.vert_id);
glDeleteProgram(v.id);
+ memdelete_arr(v.uniform_location);
v.id = 0;
}
@@ -398,6 +406,7 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() {
glDeleteShader(v.frag_id);
glDeleteShader(v.vert_id);
glDeleteProgram(v.id);
+ memdelete_arr(v.uniform_location);
v.id = 0;
ERR_PRINT("No OpenGL fragment shader compiler log. What the frick?");
@@ -420,6 +429,7 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() {
glDeleteShader(v.frag_id);
glDeleteShader(v.vert_id);
glDeleteProgram(v.id);
+ memdelete_arr(v.uniform_location);
v.id = 0;
}
@@ -447,6 +457,7 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() {
glDeleteShader(v.frag_id);
glDeleteShader(v.vert_id);
glDeleteProgram(v.id);
+ memdelete_arr(v.uniform_location);
v.id = 0;
ERR_PRINT("No OpenGL program link log. What the frick?");
@@ -471,6 +482,7 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() {
glDeleteShader(v.frag_id);
glDeleteShader(v.vert_id);
glDeleteProgram(v.id);
+ memdelete_arr(v.uniform_location);
v.id = 0;
ERR_FAIL_V(NULL);
@@ -514,6 +526,10 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() {
glUseProgram(0);
v.ok = true;
+ if (cc) {
+ cc->versions.insert(conditional_version.version);
+ }
+
return &v;
}
@@ -678,9 +694,26 @@ void ShaderGLES2::set_custom_shader(uint32_t p_code_id) {
}
void ShaderGLES2::free_custom_shader(uint32_t p_code_id) {
+
ERR_FAIL_COND(!custom_code_map.has(p_code_id));
if (conditional_version.code_version == p_code_id)
- conditional_version.code_version = 0;
+ conditional_version.code_version = 0; //do not keep using a version that is going away
+
+ VersionKey key;
+ key.code_version = p_code_id;
+ for (Set<uint32_t>::Element *E = custom_code_map[p_code_id].versions.front(); E; E = E->next()) {
+ key.version = E->get();
+ ERR_CONTINUE(!version_map.has(key));
+ Version &v = version_map[key];
+
+ glDeleteShader(v.vert_id);
+ glDeleteShader(v.frag_id);
+ glDeleteProgram(v.id);
+ memdelete_arr(v.uniform_location);
+ v.id = 0;
+
+ version_map.erase(key);
+ }
custom_code_map.erase(p_code_id);
}
diff --git a/drivers/gles2/shader_gles2.h b/drivers/gles2/shader_gles2.h
index 468971471c..d493880d0b 100644
--- a/drivers/gles2/shader_gles2.h
+++ b/drivers/gles2/shader_gles2.h
@@ -104,6 +104,7 @@ private:
Vector<StringName> texture_uniforms;
Vector<StringName> custom_uniforms;
Vector<CharString> custom_defines;
+ Set<uint32_t> versions;
};
struct Version {
@@ -465,6 +466,8 @@ public:
void set_custom_shader(uint32_t p_code_id);
void free_custom_shader(uint32_t p_code_id);
+ uint32_t get_version_key() const { return conditional_version.version; }
+
void set_uniform_default(int p_idx, const Variant &p_value) {
if (p_value.get_type() == Variant::NIL) {
diff --git a/drivers/gles2/shaders/canvas.glsl b/drivers/gles2/shaders/canvas.glsl
index 0de60d7421..c4a8c8b990 100644
--- a/drivers/gles2/shaders/canvas.glsl
+++ b/drivers/gles2/shaders/canvas.glsl
@@ -6,8 +6,8 @@
#define mediump
#define highp
#else
-precision mediump float;
-precision mediump int;
+precision highp float;
+precision highp int;
#endif
uniform highp mat4 projection_matrix;
@@ -215,14 +215,42 @@ VERTEX_SHADER_CODE
/* clang-format off */
[fragment]
+#ifndef USE_GLES_OVER_GL
+
+#ifdef GL_EXT_shader_texture_lod
+#extension GL_EXT_shader_texture_lod : enable
+#define texture2DLod(img, coord, lod) texture2DLodEXT(img, coord, lod)
+#define textureCubeLod(img, coord, lod) textureCubeLodEXT(img, coord, lod)
+#endif
+
+#endif
+
+#ifdef GL_ARB_shader_texture_lod
+#extension GL_ARB_shader_texture_lod : enable
+#endif
+
+
+#if !defined(GL_EXT_shader_texture_lod) && !defined(GL_ARB_shader_texture_lod)
+#define texture2DLod(img, coord, lod) texture2D(img, coord, lod)
+#define textureCubeLod(img, coord, lod) textureCube(img, coord, lod)
+#endif
+
+
+
+
#ifdef USE_GLES_OVER_GL
#define lowp
#define mediump
#define highp
#else
+#if defined(USE_HIGHP_PRECISION)
+precision highp float;
+precision highp int;
+#else
precision mediump float;
precision mediump int;
#endif
+#endif
uniform sampler2D color_texture; // texunit:-1
/* clang-format on */
@@ -433,19 +461,14 @@ FRAGMENT_SHADER_CODE
#ifdef SHADOW_USE_GRADIENT
-#define SHADOW_TEST(m_ofs) \
- { \
- highp float sd = SHADOW_DEPTH(shadow_texture, vec2(m_ofs, sh)); \
- shadow_attenuation += 1.0 - smoothstep(sd, sd + shadow_gradient, sz); \
- }
+ /* clang-format off */
+ /* GLSL es 100 doesn't support line continuation characters(backslashes) */
+#define SHADOW_TEST(m_ofs) { highp float sd = SHADOW_DEPTH(shadow_texture, vec2(m_ofs, sh)); shadow_attenuation += 1.0 - smoothstep(sd, sd + shadow_gradient, sz); }
#else
-#define SHADOW_TEST(m_ofs) \
- { \
- highp float sd = SHADOW_DEPTH(shadow_texture, vec2(m_ofs, sh)); \
- shadow_attenuation += step(sz, sd); \
- }
+#define SHADOW_TEST(m_ofs) { highp float sd = SHADOW_DEPTH(shadow_texture, vec2(m_ofs, sh)); shadow_attenuation += step(sz, sd); }
+ /* clang-format on */
#endif
diff --git a/drivers/gles2/shaders/copy.glsl b/drivers/gles2/shaders/copy.glsl
index f3c2a7eec4..931b3f3708 100644
--- a/drivers/gles2/shaders/copy.glsl
+++ b/drivers/gles2/shaders/copy.glsl
@@ -6,8 +6,8 @@
#define mediump
#define highp
#else
-precision mediump float;
-precision mediump int;
+precision highp float;
+precision highp int;
#endif
attribute highp vec4 vertex_attrib; // attrib:0
@@ -29,7 +29,7 @@ varying vec2 uv_interp;
varying vec2 uv2_interp;
#ifdef USE_COPY_SECTION
-uniform vec4 copy_section;
+uniform highp vec4 copy_section;
#endif
void main() {
@@ -61,9 +61,14 @@ void main() {
#define mediump
#define highp
#else
+#if defined(USE_HIGHP_PRECISION)
+precision highp float;
+precision highp int;
+#else
precision mediump float;
precision mediump int;
#endif
+#endif
#if defined(USE_CUBEMAP) || defined(USE_PANORAMA)
varying vec3 cube_interp;
diff --git a/drivers/gles2/shaders/cubemap_filter.glsl b/drivers/gles2/shaders/cubemap_filter.glsl
index 06274a7698..7643297a14 100644
--- a/drivers/gles2/shaders/cubemap_filter.glsl
+++ b/drivers/gles2/shaders/cubemap_filter.glsl
@@ -6,8 +6,8 @@
#define mediump
#define highp
#else
-precision mediump float;
-precision mediump int;
+precision highp float;
+precision highp int;
#endif
attribute highp vec2 vertex; // attrib:0
@@ -25,22 +25,42 @@ void main() {
/* clang-format off */
[fragment]
+#ifndef USE_GLES_OVER_GL
+
+#ifdef GL_EXT_shader_texture_lod
+#extension GL_EXT_shader_texture_lod : enable
+#define texture2DLod(img, coord, lod) texture2DLodEXT(img, coord, lod)
+#define textureCubeLod(img, coord, lod) textureCubeLodEXT(img, coord, lod)
+#endif
+
+#endif
+
+#ifdef GL_ARB_shader_texture_lod
#extension GL_ARB_shader_texture_lod : enable
+#endif
-#ifndef GL_ARB_shader_texture_lod
-#define texture2DLod(img, coord, lod) texture2D(img, coord)
-#define textureCubeLod(img, coord, lod) textureCube(img, coord)
+#if !defined(GL_EXT_shader_texture_lod) && !defined(GL_ARB_shader_texture_lod)
+#define texture2DLod(img, coord, lod) texture2D(img, coord, lod)
+#define textureCubeLod(img, coord, lod) textureCube(img, coord, lod)
#endif
+
+
#ifdef USE_GLES_OVER_GL
#define lowp
#define mediump
#define highp
#else
+#if defined(USE_HIGHP_PRECISION)
+precision highp float;
+precision highp int;
+#else
precision mediump float;
precision mediump int;
#endif
+#endif
+
#ifdef USE_SOURCE_PANORAMA
uniform sampler2D source_panorama; //texunit:0
#else
@@ -118,7 +138,13 @@ vec3 texelCoordToVec(vec2 uv, int faceID) {
faceUvVectors[5][2] = vec3(0.0, 0.0, 1.0); // +z face
// out = u * s_faceUv[0] + v * s_faceUv[1] + s_faceUv[2].
- vec3 result = (faceUvVectors[faceID][0] * uv.x) + (faceUvVectors[faceID][1] * uv.y) + faceUvVectors[faceID][2];
+ vec3 result;
+ for (int i = 0; i < 6; i++) {
+ if (i == faceID) {
+ result = (faceUvVectors[i][0] * uv.x) + (faceUvVectors[i][1] * uv.y) + faceUvVectors[i][2];
+ break;
+ }
+ }
return normalize(result);
}
diff --git a/drivers/gles2/shaders/scene.glsl b/drivers/gles2/shaders/scene.glsl
index b2b9458ed2..c7f5c97133 100644
--- a/drivers/gles2/shaders/scene.glsl
+++ b/drivers/gles2/shaders/scene.glsl
@@ -655,20 +655,41 @@ VERTEX_SHADER_CODE
/* clang-format off */
[fragment]
+
+#ifndef USE_GLES_OVER_GL
+
+#ifdef GL_EXT_shader_texture_lod
+#extension GL_EXT_shader_texture_lod : enable
+#define texture2DLod(img, coord, lod) texture2DLodEXT(img, coord, lod)
+#define textureCubeLod(img, coord, lod) textureCubeLodEXT(img, coord, lod)
+#endif
+
+#endif
+
+#ifdef GL_ARB_shader_texture_lod
#extension GL_ARB_shader_texture_lod : enable
+#endif
-#ifndef GL_ARB_shader_texture_lod
-#define texture2DLod(img, coord, lod) texture2D(img, coord)
-#define textureCubeLod(img, coord, lod) textureCube(img, coord)
+#if !defined(GL_EXT_shader_texture_lod) && !defined(GL_ARB_shader_texture_lod)
+#define texture2DLod(img, coord, lod) texture2D(img, coord, lod)
+#define textureCubeLod(img, coord, lod) textureCube(img, coord, lod)
#endif
+
+
+
#ifdef USE_GLES_OVER_GL
#define lowp
#define mediump
#define highp
#else
-precision mediump float;
+#if defined(USE_HIGHP_PRECISION)
+precision highp float;
precision highp int;
+#else
+precision mediump float;
+precision mediump int;
+#endif
#endif
#include "stdlib.glsl"
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index d53b27eb88..966466d9bc 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -1832,6 +1832,7 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) {
storage->info.render.vertices_count += s->index_array_len * amount;
} else
#endif
+
if (s->index_array_len > 0) {
glDrawElementsInstanced(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0, amount);
@@ -2677,13 +2678,6 @@ void RasterizerSceneGLES3::_setup_environment(Environment *env, const CameraMatr
glBindBuffer(GL_UNIFORM_BUFFER, 0);
}
-// Drop -O3 for this function as it triggers a GCC bug up until at least GCC 8.2.1.
-// This refers to GH issue #19633.
-// The bug has been reported to the GCC project.
-#if defined(__GNUC__) && !defined(__clang__)
-#pragma GCC push_options
-#pragma GCC optimize("-O2")
-#endif
void RasterizerSceneGLES3::_setup_directional_light(int p_index, const Transform &p_camera_inverse_transform, bool p_use_shadows) {
LightInstance *li = directional_lights[p_index];
@@ -2784,7 +2778,7 @@ void RasterizerSceneGLES3::_setup_directional_light(int p_index, const Transform
CameraMatrix shadow_mtx = rectm * bias * li->shadow_transform[j].camera * modelview;
- store_camera(shadow_mtx, &ubo_data.shadow_matrix1[16 * j]);
+ store_camera(shadow_mtx, &ubo_data.shadow.matrix[16 * j]);
ubo_data.light_clamp[0] = atlas_rect.position.x;
ubo_data.light_clamp[1] = atlas_rect.position.y;
@@ -2801,9 +2795,6 @@ void RasterizerSceneGLES3::_setup_directional_light(int p_index, const Transform
glBindBufferBase(GL_UNIFORM_BUFFER, 3, state.directional_ubo);
}
-#if defined(__GNUC__) && !defined(__clang__)
-#pragma GCC pop_options
-#endif
void RasterizerSceneGLES3::_setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, const CameraMatrix &p_camera_projection, RID p_shadow_atlas) {
@@ -2898,7 +2889,7 @@ void RasterizerSceneGLES3::_setup_lights(RID *p_light_cull_result, int p_light_c
Transform proj = (p_camera_inverse_transform * li->transform).inverse();
- store_transform(proj, ubo_data.shadow_matrix1);
+ store_transform(proj, ubo_data.shadow.matrix1);
ubo_data.light_params[3] = 1.0; //means it has shadow
ubo_data.light_clamp[0] = float(x) / atlas_size;
@@ -2987,7 +2978,7 @@ void RasterizerSceneGLES3::_setup_lights(RID *p_light_cull_result, int p_light_c
CameraMatrix shadow_mtx = rectm * bias * li->shadow_transform[0].camera * modelview;
- store_camera(shadow_mtx, ubo_data.shadow_matrix1);
+ store_camera(shadow_mtx, ubo_data.shadow.matrix1);
}
li->light_index = state.spot_light_count;
@@ -4141,9 +4132,19 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
glDepthFunc(GL_LEQUAL);
- state.used_contact_shadows = true;
+ state.used_contact_shadows = false;
+
+ for (int i = 0; i < p_light_cull_count; i++) {
+
+ ERR_BREAK(i >= RenderList::MAX_LIGHTS);
+
+ LightInstance *li = light_instance_owner.getptr(p_light_cull_result[i]);
+ if (li->light_ptr->param[VS::LIGHT_PARAM_CONTACT_SHADOW_SIZE] > CMP_EPSILON) {
+ state.used_contact_shadows = true;
+ }
+ }
- if (!storage->config.no_depth_prepass && storage->frame.current_rt && state.debug_draw != VS::VIEWPORT_DEBUG_DRAW_OVERDRAW) { //detect with state.used_contact_shadows too
+ if (!storage->config.no_depth_prepass && storage->frame.current_rt && state.debug_draw != VS::VIEWPORT_DEBUG_DRAW_OVERDRAW && !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_NO_3D_EFFECTS]) { //detect with state.used_contact_shadows too
//pre z pass
glDisable(GL_BLEND);
diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h
index 9772b5dd23..325617745a 100644
--- a/drivers/gles3/rasterizer_scene_gles3.h
+++ b/drivers/gles3/rasterizer_scene_gles3.h
@@ -569,10 +569,15 @@ public:
float light_params[4]; //spot attenuation, spot angle, specular, shadow enabled
float light_clamp[4];
float light_shadow_color_contact[4];
- float shadow_matrix1[16]; //up to here for spot and omni, rest is for directional
- float shadow_matrix2[16];
- float shadow_matrix3[16];
- float shadow_matrix4[16];
+ union {
+ struct {
+ float matrix1[16]; //up to here for spot and omni, rest is for directional
+ float matrix2[16];
+ float matrix3[16];
+ float matrix4[16];
+ };
+ float matrix[4 * 16];
+ } shadow;
float shadow_split_offsets[4];
};
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp
index 24673c8755..8b3f1a1b77 100644
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ b/drivers/gles3/rasterizer_storage_gles3.cpp
@@ -1056,6 +1056,128 @@ Ref<Image> RasterizerStorageGLES3::texture_get_data(RID p_texture, int p_layer)
return texture->images[p_layer];
}
+ // 3D textures and 2D texture arrays need special treatment, as the glGetTexImage reads **the whole**
+ // texture to host-memory. 3D textures and 2D texture arrays are potentially very big, so reading
+ // everything just to throw everything but one layer away is A Bad Idea.
+ //
+ // Unfortunately, to solve this, the copy shader has to read the data out via a shader and store it
+ // in a temporary framebuffer. The data from the framebuffer can then be read using glReadPixels.
+ if (texture->type == VS::TEXTURE_TYPE_2D_ARRAY || texture->type == VS::TEXTURE_TYPE_3D) {
+ // can't read a layer that doesn't exist
+ ERR_FAIL_INDEX_V(p_layer, texture->alloc_depth, Ref<Image>());
+
+ // get some information about the texture
+ Image::Format real_format;
+ GLenum gl_format;
+ GLenum gl_internal_format;
+ GLenum gl_type;
+
+ bool compressed;
+ bool srgb;
+
+ _get_gl_image_and_format(
+ Ref<Image>(),
+ texture->format,
+ texture->flags,
+ real_format,
+ gl_format,
+ gl_internal_format,
+ gl_type,
+ compressed,
+ srgb);
+
+ PoolVector<uint8_t> data;
+
+ // TODO need to decide between RgbaUnorm and RgbaFloat32 for output
+ 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 more memory at the end, just in case for buggy drivers
+ PoolVector<uint8_t>::Write wb = data.write();
+
+ // generate temporary resources
+ GLuint tmp_fbo;
+ glGenFramebuffers(1, &tmp_fbo);
+
+ GLuint tmp_color_attachment;
+ glGenTextures(1, &tmp_color_attachment);
+
+ // now bring the OpenGL context into the correct state
+ {
+ glBindFramebuffer(GL_FRAMEBUFFER, tmp_fbo);
+
+ // back color attachment with memory, then set properties
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, tmp_color_attachment);
+ // TODO support HDR properly
+ 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);
+
+ // use the color texture as color attachment for this render pass
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tmp_color_attachment, 0);
+
+ // more GL state, wheeeey
+ glDepthMask(GL_FALSE);
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_BLEND);
+ glDepthFunc(GL_LEQUAL);
+ glColorMask(1, 1, 1, 1);
+
+ // use volume tex for reading
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(texture->target, texture->tex_id);
+
+ glViewport(0, 0, texture->alloc_width, texture->alloc_height);
+
+ // set up copy shader for proper use
+ shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB, !srgb);
+ shaders.copy.set_conditional(CopyShaderGLES3::USE_TEXTURE3D, texture->type == VS::TEXTURE_TYPE_3D);
+ shaders.copy.set_conditional(CopyShaderGLES3::USE_TEXTURE2DARRAY, texture->type == VS::TEXTURE_TYPE_2D_ARRAY);
+ shaders.copy.bind();
+
+ // calculate the normalized z coordinate for the layer
+ float layer = (float)p_layer / (float)texture->alloc_depth;
+
+ shaders.copy.set_uniform(CopyShaderGLES3::LAYER, layer);
+
+ glBindVertexArray(resources.quadie_array);
+ }
+
+ // clear color attachment, then perform copy
+ glClearColor(0.0, 0.0, 0.0, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+ // read the image into the host buffer
+ glReadPixels(0, 0, texture->alloc_width, texture->alloc_height, GL_RGBA, GL_UNSIGNED_BYTE, &wb[0]);
+
+ // remove temp resources and unset some GL state
+ {
+ shaders.copy.set_conditional(CopyShaderGLES3::USE_TEXTURE3D, false);
+ shaders.copy.set_conditional(CopyShaderGLES3::USE_TEXTURE2DARRAY, false);
+ shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB, false);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ glDeleteTextures(1, &tmp_color_attachment);
+ glDeleteFramebuffers(1, &tmp_fbo);
+ }
+
+ wb = PoolVector<uint8_t>::Write();
+
+ 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);
+ }
+
#ifdef GLES_OVER_GL
Image::Format real_format;
@@ -1172,9 +1294,8 @@ Ref<Image> RasterizerStorageGLES3::texture_get_data(RID p_texture, int p_layer)
glViewport(0, 0, texture->alloc_width, texture->alloc_height);
- shaders.copy.bind();
-
shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB, !srgb);
+ shaders.copy.bind();
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
diff --git a/drivers/gles3/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp
index edc2a6c054..64396cadd1 100644
--- a/drivers/gles3/shader_gles3.cpp
+++ b/drivers/gles3/shader_gles3.cpp
@@ -204,6 +204,7 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() {
glDeleteShader(v.vert_id);
glDeleteShader(v.frag_id);
glDeleteProgram(v.id);
+ memdelete_arr(v.uniform_location);
v.id = 0;
}
}
@@ -324,6 +325,7 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() {
glDeleteShader(v.vert_id);
glDeleteProgram(v.id);
+ memdelete_arr(v.uniform_location);
v.id = 0;
ERR_PRINT("Vertex shader compilation failed with empty log");
@@ -345,6 +347,7 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() {
memfree(ilogmem);
glDeleteShader(v.vert_id);
glDeleteProgram(v.id);
+ memdelete_arr(v.uniform_location);
v.id = 0;
}
@@ -418,6 +421,7 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() {
glDeleteShader(v.frag_id);
glDeleteShader(v.vert_id);
glDeleteProgram(v.id);
+ memdelete_arr(v.uniform_location);
v.id = 0;
ERR_PRINT("Fragment shader compilation failed with empty log");
} else {
@@ -440,6 +444,7 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() {
glDeleteShader(v.frag_id);
glDeleteShader(v.vert_id);
glDeleteProgram(v.id);
+ memdelete_arr(v.uniform_location);
v.id = 0;
}
@@ -486,6 +491,7 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() {
glDeleteShader(v.frag_id);
glDeleteShader(v.vert_id);
glDeleteProgram(v.id);
+ memdelete_arr(v.uniform_location);
v.id = 0;
ERR_FAIL_COND_V(iloglen <= 0, NULL);
}
@@ -508,6 +514,7 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() {
glDeleteShader(v.frag_id);
glDeleteShader(v.vert_id);
glDeleteProgram(v.id);
+ memdelete_arr(v.uniform_location);
v.id = 0;
ERR_FAIL_V(NULL);
@@ -559,6 +566,9 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() {
glUseProgram(0);
v.ok = true;
+ if (cc) {
+ cc->versions.insert(conditional_version.version);
+ }
return &v;
}
@@ -742,7 +752,23 @@ void ShaderGLES3::free_custom_shader(uint32_t p_code_id) {
ERR_FAIL_COND(!custom_code_map.has(p_code_id));
if (conditional_version.code_version == p_code_id)
- conditional_version.code_version = 0; //bye
+ conditional_version.code_version = 0; //do not keep using a version that is going away
+
+ VersionKey key;
+ key.code_version = p_code_id;
+ for (Set<uint32_t>::Element *E = custom_code_map[p_code_id].versions.front(); E; E = E->next()) {
+ key.version = E->get();
+ ERR_CONTINUE(!version_map.has(key));
+ Version &v = version_map[key];
+
+ glDeleteShader(v.vert_id);
+ glDeleteShader(v.frag_id);
+ glDeleteProgram(v.id);
+ memdelete_arr(v.uniform_location);
+ v.id = 0;
+
+ version_map.erase(key);
+ }
custom_code_map.erase(p_code_id);
}
diff --git a/drivers/gles3/shader_gles3.h b/drivers/gles3/shader_gles3.h
index 1f98f4883d..1ed30986bf 100644
--- a/drivers/gles3/shader_gles3.h
+++ b/drivers/gles3/shader_gles3.h
@@ -117,6 +117,7 @@ private:
uint32_t version;
Vector<StringName> texture_uniforms;
Vector<CharString> custom_defines;
+ Set<uint32_t> versions;
};
struct Version {
diff --git a/drivers/gles3/shaders/copy.glsl b/drivers/gles3/shaders/copy.glsl
index 3b36bc7cc1..e1a0813efc 100644
--- a/drivers/gles3/shaders/copy.glsl
+++ b/drivers/gles3/shaders/copy.glsl
@@ -61,19 +61,35 @@ in vec3 cube_interp;
#else
in vec2 uv_interp;
#endif
-/* clang-format on */
#ifdef USE_ASYM_PANO
uniform highp mat4 pano_transform;
uniform highp vec4 asym_proj;
#endif
+// These definitions are here because the shader-wrapper builder does
+// not understand `#elif defined()`
+#ifdef USE_TEXTURE3D
+#endif
+#ifdef USE_TEXTURE2DARRAY
+#endif
+
#ifdef USE_CUBEMAP
uniform samplerCube source_cube; //texunit:0
+#elif defined(USE_TEXTURE3D)
+uniform sampler3D source_3d; //texunit:0
+#elif defined(USE_TEXTURE2DARRAY)
+uniform sampler2DArray source_2d_array; //texunit:0
#else
uniform sampler2D source; //texunit:0
#endif
+/* clang-format on */
+
+#if defined(USE_TEXTURE3D) || defined(USE_TEXTURE2DARRAY)
+uniform float layer;
+#endif
+
#ifdef USE_MULTIPLIER
uniform float multiplier;
#endif
@@ -97,7 +113,6 @@ vec4 texturePanorama(vec3 normal, sampler2D pano) {
#endif
-uniform float stuff;
uniform vec2 pixel_size;
in vec2 uv2_interp;
@@ -147,6 +162,10 @@ void main() {
#elif defined(USE_CUBEMAP)
vec4 color = texture(source_cube, normalize(cube_interp));
+#elif defined(USE_TEXTURE3D)
+ vec4 color = textureLod(source_3d, vec3(uv_interp, layer), 0.0);
+#elif defined(USE_TEXTURE2DARRAY)
+ vec4 color = textureLod(source_2d_array, vec3(uv_interp, layer), 0.0);
#else
vec4 color = textureLod(source, uv_interp, 0.0);
#endif
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl
index 86aac2801a..1a8ad5e1ef 100644
--- a/drivers/gles3/shaders/scene.glsl
+++ b/drivers/gles3/shaders/scene.glsl
@@ -165,10 +165,8 @@ uniform int spot_light_count;
out vec4 diffuse_light_interp;
out vec4 specular_light_interp;
-
void light_compute(vec3 N, vec3 L, vec3 V, vec3 light_color, float roughness, inout vec3 diffuse, inout vec3 specular) {
-
float NdotL = dot(N, L);
float cNdotL = max(NdotL, 0.0); // clamped NdotL
float NdotV = dot(N, V);
@@ -225,8 +223,6 @@ void light_compute(vec3 N, vec3 L, vec3 V, vec3 light_color, float roughness, in
specular += specular_brdf_NL * light_color * (1.0 / M_PI);
}
-
-
}
void light_process_omni(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, float roughness, inout vec3 diffuse, inout vec3 specular) {
diff --git a/drivers/unix/dir_access_unix.cpp b/drivers/unix/dir_access_unix.cpp
index 7284226ae7..e011176806 100644
--- a/drivers/unix/dir_access_unix.cpp
+++ b/drivers/unix/dir_access_unix.cpp
@@ -407,6 +407,10 @@ size_t DirAccessUnix::get_space_left() {
#endif
};
+String DirAccessUnix::get_filesystem_type() const {
+ return ""; //TODO this should be implemented
+}
+
DirAccessUnix::DirAccessUnix() {
dir_stream = 0;
diff --git a/drivers/unix/dir_access_unix.h b/drivers/unix/dir_access_unix.h
index 4da7e42b64..b85ae719ff 100644
--- a/drivers/unix/dir_access_unix.h
+++ b/drivers/unix/dir_access_unix.h
@@ -82,6 +82,9 @@ public:
virtual size_t get_space_left();
+ virtual String get_filesystem_type() const;
+
+
DirAccessUnix();
~DirAccessUnix();
};
diff --git a/drivers/windows/dir_access_windows.cpp b/drivers/windows/dir_access_windows.cpp
index c20f707684..c32e063736 100644
--- a/drivers/windows/dir_access_windows.cpp
+++ b/drivers/windows/dir_access_windows.cpp
@@ -346,6 +346,35 @@ size_t DirAccessWindows::get_space_left() {
return (size_t)bytes;
}
+String DirAccessWindows::get_filesystem_type() const {
+ String path = fix_path(const_cast<DirAccessWindows*>(this)->get_current_dir());
+ print_line("fixed path: "+path);
+ int unit_end = path.find(":");
+ ERR_FAIL_COND_V(unit_end==-1,String());
+ String unit = path.substr(0,unit_end+1) + "\\";
+ print_line("unit: "+unit);
+
+ TCHAR szVolumeName[100] = "";
+ TCHAR szFileSystemName[10] = "";
+ DWORD dwSerialNumber = 0;
+ DWORD dwMaxFileNameLength = 0;
+ DWORD dwFileSystemFlags = 0;
+
+ if(::GetVolumeInformation(unit.utf8().get_data(),
+ szVolumeName,
+ sizeof(szVolumeName),
+ &dwSerialNumber,
+ &dwMaxFileNameLength,
+ &dwFileSystemFlags,
+ szFileSystemName,
+ sizeof(szFileSystemName)) == TRUE) {
+
+ return String(szFileSystemName);
+ }
+
+ ERR_FAIL_V("");
+}
+
DirAccessWindows::DirAccessWindows() {
p = memnew(DirAccessWindowsPrivate);
diff --git a/drivers/windows/dir_access_windows.h b/drivers/windows/dir_access_windows.h
index 2e2d23f4e2..b8599d5c26 100644
--- a/drivers/windows/dir_access_windows.h
+++ b/drivers/windows/dir_access_windows.h
@@ -82,6 +82,9 @@ public:
//virtual FileType get_file_type() const;
size_t get_space_left();
+ virtual String get_filesystem_type() const;
+
+
DirAccessWindows();
~DirAccessWindows();
};
diff --git a/drivers/windows/thread_windows.cpp b/drivers/windows/thread_windows.cpp
index 1bcd5a10d4..8a2992e0c2 100644
--- a/drivers/windows/thread_windows.cpp
+++ b/drivers/windows/thread_windows.cpp
@@ -52,6 +52,7 @@ DWORD ThreadWindows::thread_callback(LPVOID userdata) {
t->id = (ID)GetCurrentThreadId(); // must implement
t->callback(t->user);
+ SetEvent(t->handle);
ScriptServer::thread_exit();
@@ -63,13 +64,9 @@ Thread *ThreadWindows::create_func_windows(ThreadCreateCallback p_callback, void
ThreadWindows *tr = memnew(ThreadWindows);
tr->callback = p_callback;
tr->user = p_user;
- tr->handle = CreateThread(
- NULL, // default security attributes
- 0, // use default stack size
- thread_callback, // thread function name
- tr, // argument to thread function
- 0, // use default creation flags
- NULL); // returns the thread identifier
+ tr->handle = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+ QueueUserWorkItem(thread_callback, tr, WT_EXECUTELONGFUNCTION);
return tr;
}