diff options
Diffstat (limited to 'drivers/gles3')
-rw-r--r-- | drivers/gles3/rasterizer_canvas_gles3.cpp | 7 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_gles3.cpp | 12 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_scene_gles3.cpp | 37 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_scene_gles3.h | 9 | ||||
-rw-r--r-- | drivers/gles3/shader_gles3.cpp | 7 | ||||
-rw-r--r-- | drivers/gles3/shaders/canvas.glsl | 14 | ||||
-rw-r--r-- | drivers/gles3/shaders/scene.glsl | 25 | ||||
-rw-r--r-- | drivers/gles3/shaders/stdlib_inc.glsl | 19 | ||||
-rw-r--r-- | drivers/gles3/storage/material_storage.cpp | 1 | ||||
-rw-r--r-- | drivers/gles3/storage/texture_storage.cpp | 69 | ||||
-rw-r--r-- | drivers/gles3/storage/texture_storage.h | 3 |
11 files changed, 133 insertions, 70 deletions
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index 83c20e6fa7..e5d4077393 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -312,9 +312,14 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_ Size2i ssize = texture_storage->render_target_get_size(p_to_render_target); + // If we've overridden the render target's color texture, then we need + // to invert the Y axis, so 2D texture appear right side up. + // We're probably rendering directly to an XR device. + float y_scale = texture_storage->render_target_get_override_color(p_to_render_target).is_valid() ? -2.0f : 2.0f; + Transform3D screen_transform; screen_transform.translate_local(-(ssize.width / 2.0f), -(ssize.height / 2.0f), 0.0f); - screen_transform.scale(Vector3(2.0f / ssize.width, 2.0f / ssize.height, 1.0f)); + screen_transform.scale(Vector3(2.0f / ssize.width, y_scale / ssize.height, 1.0f)); _update_transform_to_mat4(screen_transform, state_buffer.screen_transform); _update_transform_2d_to_mat4(p_canvas_transform, state_buffer.canvas_transform); diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp index 1b42b55425..7b4131b3a3 100644 --- a/drivers/gles3/rasterizer_gles3.cpp +++ b/drivers/gles3/rasterizer_gles3.cpp @@ -285,6 +285,15 @@ void RasterizerGLES3::_blit_render_target_to_screen(RID p_render_target, Display ERR_FAIL_COND(!rt); + // We normally render to the render target upside down, so flip Y when blitting to the screen. + bool flip_y = true; + if (rt->overridden.color.is_valid()) { + // If we've overridden the render target's color texture, that means we + // didn't render upside down, so we don't need to flip it. + // We're probably rendering directly to an XR device. + flip_y = false; + } + GLuint read_fbo = 0; if (rt->view_count > 1) { glGenFramebuffers(1, &read_fbo); @@ -296,10 +305,9 @@ void RasterizerGLES3::_blit_render_target_to_screen(RID p_render_target, Display glReadBuffer(GL_COLOR_ATTACHMENT0); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, GLES3::TextureStorage::system_fbo); - // Flip content upside down to correct for coordinates. Vector2i screen_rect_end = p_screen_rect.get_end(); glBlitFramebuffer(0, 0, rt->size.x, rt->size.y, - p_screen_rect.position.x, screen_rect_end.y, screen_rect_end.x, p_screen_rect.position.y, + p_screen_rect.position.x, flip_y ? screen_rect_end.y : p_screen_rect.position.y, screen_rect_end.x, flip_y ? p_screen_rect.position.y : screen_rect_end.y, GL_COLOR_BUFFER_BIT, GL_NEAREST); if (read_fbo != 0) { diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 8250140c3f..66c02f5566 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -1321,6 +1321,7 @@ void RasterizerSceneGLES3::_setup_environment(const RenderDataGLES3 *p_render_da GLES3::MaterialStorage::store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix); GLES3::MaterialStorage::store_transform(p_render_data->cam_transform, scene_state.ubo.inv_view_matrix); GLES3::MaterialStorage::store_transform(p_render_data->inv_cam_transform, scene_state.ubo.view_matrix); + scene_state.ubo.camera_visible_layers = p_render_data->camera_visible_layers; if (p_render_data->view_count > 1) { for (uint32_t v = 0; v < p_render_data->view_count; v++) { @@ -1705,6 +1706,7 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_ render_data.inv_cam_transform = render_data.cam_transform.affine_inverse(); render_data.cam_projection = p_camera_data->main_projection; render_data.cam_orthogonal = p_camera_data->is_orthogonal; + render_data.camera_visible_layers = p_camera_data->visible_layers; render_data.view_count = p_camera_data->view_count; for (uint32_t v = 0; v < p_camera_data->view_count; v++) { @@ -1900,7 +1902,7 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_ glColorMask(0, 0, 0, 0); glClearDepth(1.0f); glClear(GL_DEPTH_BUFFER_BIT); - uint32_t spec_constant = SceneShaderGLES3::DISABLE_FOG | SceneShaderGLES3::DISABLE_LIGHT_DIRECTIONAL | + uint64_t spec_constant = SceneShaderGLES3::DISABLE_FOG | SceneShaderGLES3::DISABLE_LIGHT_DIRECTIONAL | SceneShaderGLES3::DISABLE_LIGHTMAP | SceneShaderGLES3::DISABLE_LIGHT_OMNI | SceneShaderGLES3::DISABLE_LIGHT_SPOT; @@ -1941,7 +1943,7 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_ glClearBufferfv(GL_COLOR, 0, clear_color.components); } RENDER_TIMESTAMP("Render Opaque Pass"); - uint32_t spec_constant_base_flags = 0; + uint64_t spec_constant_base_flags = 0; { // Specialization Constants that apply for entire rendering pass. @@ -2012,8 +2014,10 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params, GeometryInstanceGLES3 *prev_inst = nullptr; SceneShaderGLES3::ShaderVariant prev_variant = SceneShaderGLES3::ShaderVariant::MODE_COLOR; SceneShaderGLES3::ShaderVariant shader_variant = SceneShaderGLES3::MODE_COLOR; // Assigned to silence wrong -Wmaybe-initialized + uint64_t prev_spec_constants = 0; - uint32_t base_spec_constants = p_params->spec_constant_base_flags; + // Specializations constants used by all instances in the scene. + uint64_t base_spec_constants = p_params->spec_constant_base_flags; if (p_render_data->view_count > 1) { base_spec_constants |= SceneShaderGLES3::USE_MULTIVIEW; @@ -2233,8 +2237,18 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params, instance_variant = SceneShaderGLES3::ShaderVariant(1 + int(shader_variant)); } - if (prev_shader != shader || prev_variant != instance_variant) { - bool success = material_storage->shaders.scene_shader.version_bind_shader(shader->version, instance_variant, base_spec_constants); + uint64_t spec_constants = base_spec_constants; + + if (inst->omni_light_count == 0) { + spec_constants |= SceneShaderGLES3::DISABLE_LIGHT_OMNI; + } + + if (inst->spot_light_count == 0) { + spec_constants |= SceneShaderGLES3::DISABLE_LIGHT_SPOT; + } + + if (prev_shader != shader || prev_variant != instance_variant || spec_constants != prev_spec_constants) { + bool success = material_storage->shaders.scene_shader.version_bind_shader(shader->version, instance_variant, spec_constants); if (!success) { continue; } @@ -2246,29 +2260,30 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params, opaque_prepass_threshold = 0.1; } - material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::OPAQUE_PREPASS_THRESHOLD, opaque_prepass_threshold, shader->version, instance_variant, base_spec_constants); + material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::OPAQUE_PREPASS_THRESHOLD, opaque_prepass_threshold, shader->version, instance_variant, spec_constants); prev_shader = shader; prev_variant = instance_variant; + prev_spec_constants = spec_constants; } if (prev_inst != inst || prev_shader != shader || prev_variant != instance_variant) { // Rebind the light indices. - material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::OMNI_LIGHT_COUNT, inst->omni_light_count, shader->version, instance_variant, base_spec_constants); - material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::SPOT_LIGHT_COUNT, inst->spot_light_count, shader->version, instance_variant, base_spec_constants); + material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::OMNI_LIGHT_COUNT, inst->omni_light_count, shader->version, instance_variant, spec_constants); + material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::SPOT_LIGHT_COUNT, inst->spot_light_count, shader->version, instance_variant, spec_constants); if (inst->omni_light_count) { - glUniform1uiv(material_storage->shaders.scene_shader.version_get_uniform(SceneShaderGLES3::OMNI_LIGHT_INDICES, shader->version, instance_variant, base_spec_constants), inst->omni_light_count, inst->omni_light_gl_cache.ptr()); + glUniform1uiv(material_storage->shaders.scene_shader.version_get_uniform(SceneShaderGLES3::OMNI_LIGHT_INDICES, shader->version, instance_variant, spec_constants), inst->omni_light_count, inst->omni_light_gl_cache.ptr()); } if (inst->spot_light_count) { - glUniform1uiv(material_storage->shaders.scene_shader.version_get_uniform(SceneShaderGLES3::SPOT_LIGHT_INDICES, shader->version, instance_variant, base_spec_constants), inst->spot_light_count, inst->spot_light_gl_cache.ptr()); + glUniform1uiv(material_storage->shaders.scene_shader.version_get_uniform(SceneShaderGLES3::SPOT_LIGHT_INDICES, shader->version, instance_variant, spec_constants), inst->spot_light_count, inst->spot_light_gl_cache.ptr()); } prev_inst = inst; } - material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::WORLD_TRANSFORM, world_transform, shader->version, instance_variant, base_spec_constants); + material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::WORLD_TRANSFORM, world_transform, shader->version, instance_variant, spec_constants); if (inst->instance_count > 0) { // Using MultiMesh or Particles. // Bind instance buffers. diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index 6e1f1babf8..255e62fc33 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -93,6 +93,7 @@ struct RenderDataGLES3 { Transform3D inv_cam_transform; Projection cam_projection; bool cam_orthogonal = false; + uint32_t camera_visible_layers = 0xFFFFFFFF; // For stereo rendering uint32_t view_count = 1; @@ -333,6 +334,10 @@ private: float fog_light_color[3]; float fog_sun_scatter; + uint32_t camera_visible_layers; + uint32_t pad1; + uint32_t pad2; + uint32_t pad3; }; static_assert(sizeof(UBO) % 16 == 0, "Scene UBO size must be a multiple of 16 bytes"); @@ -387,10 +392,10 @@ private: GeometryInstanceSurface **elements = nullptr; int element_count = 0; bool reverse_cull = false; - uint32_t spec_constant_base_flags = 0; + uint64_t spec_constant_base_flags = 0; bool force_wireframe = false; - RenderListParameters(GeometryInstanceSurface **p_elements, int p_element_count, bool p_reverse_cull, uint32_t p_spec_constant_base_flags, bool p_force_wireframe = false) { + RenderListParameters(GeometryInstanceSurface **p_elements, int p_element_count, bool p_reverse_cull, uint64_t p_spec_constant_base_flags, bool p_force_wireframe = false) { elements = p_elements; element_count = p_element_count; reverse_cull = p_reverse_cull; diff --git a/drivers/gles3/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp index 1dcd17ea0e..69c3ff7c8e 100644 --- a/drivers/gles3/shader_gles3.cpp +++ b/drivers/gles3/shader_gles3.cpp @@ -36,6 +36,11 @@ #include "core/io/dir_access.h" #include "core/io/file_access.h" +static String _mkid(const String &p_id) { + String id = "m_" + p_id.replace("__", "_dus_"); + return id.replace("__", "_dus_"); //doubleunderscore is reserved in glsl +} + void ShaderGLES3::_add_stage(const char *p_code, StageType p_stage_type) { Vector<String> lines = String(p_code).split("\n"); @@ -425,7 +430,7 @@ void ShaderGLES3::_compile_specialization(Version::Specialization &spec, uint32_ } // textures for (int i = 0; i < p_version->texture_uniforms.size(); i++) { - String native_uniform_name = p_version->texture_uniforms[i]; + String native_uniform_name = _mkid(p_version->texture_uniforms[i]); GLint location = glGetUniformLocation(spec.id, (native_uniform_name).ascii().get_data()); glUniform1i(location, i + base_texture_index); } diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl index 60139de472..c1c26ed963 100644 --- a/drivers/gles3/shaders/canvas.glsl +++ b/drivers/gles3/shaders/canvas.glsl @@ -41,8 +41,6 @@ layout(std140) uniform MaterialUniforms{ //ubo:4 #include "canvas_uniforms_inc.glsl" #include "stdlib_inc.glsl" -uniform sampler2D transforms_texture; //texunit:-1 - out vec2 uv_interp; out vec4 color_interp; out vec2 vertex_interp; @@ -288,11 +286,9 @@ vec3 light_normal_compute(vec3 light_vec, vec3 normal, vec3 base_color, vec3 lig #endif -#define SHADOW_TEST(m_uv) \ - { \ - highp float sd = SHADOW_DEPTH(m_uv); \ - shadow += step(sd, shadow_uv.z / shadow_uv.w); \ - } +/* clang-format off */ +#define SHADOW_TEST(m_uv) { highp float sd = SHADOW_DEPTH(m_uv); shadow += step(sd, shadow_uv.z / shadow_uv.w); } +/* clang-format on */ //float distance = length(shadow_pos); vec4 light_shadow_compute(uint light_base, vec4 light_color, vec4 shadow_uv @@ -332,7 +328,7 @@ vec4 light_shadow_compute(uint light_base, vec4 light_color, vec4 shadow_uv shadow /= 13.0; } - vec4 shadow_color = unpackUnorm4x8(light_array[light_base].shadow_color); + vec4 shadow_color = godot_unpackUnorm4x8(light_array[light_base].shadow_color); #ifdef LIGHT_CODE_USED shadow_color.rgb *= shadow_modulate; #endif @@ -499,7 +495,7 @@ void main() { if (specular_shininess_used || (using_light && normal_used && bool(draw_data[draw_data_instance].flags & FLAGS_DEFAULT_SPECULAR_MAP_USED))) { specular_shininess = texture(specular_texture, uv); - specular_shininess *= unpackUnorm4x8(draw_data[draw_data_instance].specular_shininess); + specular_shininess *= godot_unpackUnorm4x8(draw_data[draw_data_instance].specular_shininess); specular_shininess_used = true; } else { specular_shininess = vec4(1.0); diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index 04dba602dd..fa68f0063f 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -129,7 +129,7 @@ layout(std140) uniform SceneData { // ubo:2 mediump float ambient_color_sky_mix; bool material_uv2_mode; - float pad2; + float emissive_exposure_normalization; bool use_ambient_light; bool use_ambient_cubemap; bool use_reflection_cubemap; @@ -142,7 +142,7 @@ layout(std140) uniform SceneData { // ubo:2 uint directional_light_count; float z_far; float z_near; - float pad; + float IBL_exposure_normalization; bool fog_enabled; float fog_density; @@ -151,6 +151,10 @@ layout(std140) uniform SceneData { // ubo:2 vec3 fog_light_color; float fog_sun_scatter; + uint camera_visible_layers; + uint pad3; + uint pad4; + uint pad5; } scene_data; @@ -455,7 +459,7 @@ layout(std140) uniform SceneData { // ubo:2 mediump float ambient_color_sky_mix; bool material_uv2_mode; - float pad2; + float emissive_exposure_normalization; bool use_ambient_light; bool use_ambient_cubemap; bool use_reflection_cubemap; @@ -468,7 +472,7 @@ layout(std140) uniform SceneData { // ubo:2 uint directional_light_count; float z_far; float z_near; - float pad; + float IBL_exposure_normalization; bool fog_enabled; float fog_density; @@ -477,6 +481,10 @@ layout(std140) uniform SceneData { // ubo:2 vec3 fog_light_color; float fog_sun_scatter; + uint camera_visible_layers; + uint pad3; + uint pad4; + uint pad5; } scene_data; @@ -771,7 +779,7 @@ float get_omni_attenuation(float distance, float inv_range, float decay) { nd *= nd; // nd^2 return nd * pow(max(distance, 0.0001), -decay); } - +#ifndef DISABLE_LIGHT_OMNI void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 f0, float roughness, float metallic, float shadow, vec3 albedo, inout float alpha, #ifdef LIGHT_BACKLIGHT_USED vec3 backlight, @@ -813,7 +821,9 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 f diffuse_light, specular_light); } +#endif // !DISABLE_LIGHT_OMNI +#ifndef DISABLE_LIGHT_SPOT void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 f0, float roughness, float metallic, float shadow, vec3 albedo, inout float alpha, #ifdef LIGHT_BACKLIGHT_USED vec3 backlight, @@ -861,6 +871,7 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 f #endif diffuse_light, specular_light); } +#endif // !DISABLE_LIGHT_SPOT #endif // !defined(DISABLE_LIGHT_DIRECTIONAL) || !defined(DISABLE_LIGHT_OMNI) && !defined(DISABLE_LIGHT_SPOT) #ifndef MODE_RENDER_DEPTH @@ -1100,7 +1111,7 @@ void main() { ref_vec = mix(ref_vec, normal, roughness * roughness); float horizon = min(1.0 + dot(ref_vec, normal), 1.0); ref_vec = scene_data.radiance_inverse_xform * ref_vec; - specular_light = textureLod(radiance_map, ref_vec, roughness * RADIANCE_MAX_LOD).rgb; + specular_light = textureLod(radiance_map, ref_vec, sqrt(roughness) * RADIANCE_MAX_LOD).rgb; specular_light = srgb_to_linear(specular_light); specular_light *= horizon * horizon; specular_light *= scene_data.ambient_light_color_energy.a; @@ -1162,7 +1173,7 @@ void main() { float a004 = min(r.x * r.x, exp2(-9.28 * ndotv)) * r.x + r.y; vec2 env = vec2(-1.04, 1.04) * a004 + r.zw; - specular_light *= env.x * f0 + env.y * clamp(50.0 * f0.g, 0.0, 1.0); + specular_light *= env.x * f0 + env.y * clamp(50.0 * f0.g, metallic, 1.0); #endif } diff --git a/drivers/gles3/shaders/stdlib_inc.glsl b/drivers/gles3/shaders/stdlib_inc.glsl index d819940b1d..8d4a24cc1f 100644 --- a/drivers/gles3/shaders/stdlib_inc.glsl +++ b/drivers/gles3/shaders/stdlib_inc.glsl @@ -39,23 +39,32 @@ vec2 unpackSnorm2x16(uint p) { return clamp((v - 32767.0) * vec2(0.00003051851), vec2(-1.0), vec2(1.0)); } -uint packUnorm4x8(vec4 v) { +#endif + +// Compatibility renames. These are exposed with the "godot_" prefix +// to work around an Adreno bug which was exposing these ES310 functions +// in ES300 shaders. Internally, we must use the "godot_" prefix, but user shaders +// will be mapped automatically. +uint godot_packUnorm4x8(vec4 v) { uvec4 uv = uvec4(round(clamp(v, vec4(0.0), vec4(1.0)) * 255.0)); return uv.x | (uv.y << uint(8)) | (uv.z << uint(16)) | (uv.w << uint(24)); } -vec4 unpackUnorm4x8(uint p) { +vec4 godot_unpackUnorm4x8(uint p) { return vec4(float(p & uint(0xff)), float((p >> uint(8)) & uint(0xff)), float((p >> uint(16)) & uint(0xff)), float(p >> uint(24))) * 0.00392156862; // 1.0 / 255.0 } -uint packSnorm4x8(vec4 v) { +uint godot_packSnorm4x8(vec4 v) { uvec4 uv = uvec4(round(clamp(v, vec4(-1.0), vec4(1.0)) * 127.0) + 127.0); return uv.x | uv.y << uint(8) | uv.z << uint(16) | uv.w << uint(24); } -vec4 unpackSnorm4x8(uint p) { +vec4 godot_unpackSnorm4x8(uint p) { vec4 v = vec4(float(p & uint(0xff)), float((p >> uint(8)) & uint(0xff)), float((p >> uint(16)) & uint(0xff)), float(p >> uint(24))); return clamp((v - vec4(127.0)) * vec4(0.00787401574), vec4(-1.0), vec4(1.0)); } -#endif +#define packUnorm4x8 godot_packUnorm4x8 +#define unpackUnorm4x8 godot_unpackUnorm4x8 +#define packSnorm4x8 godot_packSnorm4x8 +#define unpackSnorm4x8 godot_unpackSnorm4x8 diff --git a/drivers/gles3/storage/material_storage.cpp b/drivers/gles3/storage/material_storage.cpp index d413c2b00e..19e841f466 100644 --- a/drivers/gles3/storage/material_storage.cpp +++ b/drivers/gles3/storage/material_storage.cpp @@ -1522,6 +1522,7 @@ MaterialStorage::MaterialStorage() { actions.renames["NODE_POSITION_WORLD"] = "model_matrix[3].xyz"; actions.renames["CAMERA_POSITION_WORLD"] = "scene_data.inv_view_matrix[3].xyz"; actions.renames["CAMERA_DIRECTION_WORLD"] = "scene_data.view_matrix[3].xyz"; + actions.renames["CAMERA_VISIBLE_LAYERS"] = "scene_data.camera_visible_layers"; actions.renames["NODE_POSITION_VIEW"] = "(model_matrix * scene_data.view_matrix)[3].xyz"; actions.renames["VIEW_INDEX"] = "ViewIndex"; diff --git a/drivers/gles3/storage/texture_storage.cpp b/drivers/gles3/storage/texture_storage.cpp index 15743c2d78..99908d197a 100644 --- a/drivers/gles3/storage/texture_storage.cpp +++ b/drivers/gles3/storage/texture_storage.cpp @@ -1694,34 +1694,51 @@ void TextureStorage::_clear_render_target(RenderTarget *rt) { return; } + // Dispose of the cached fbo's and the allocated textures + for (KeyValue<uint32_t, RenderTarget::RTOverridden::FBOCacheEntry> &E : rt->overridden.fbo_cache) { + glDeleteTextures(E.value.allocated_textures.size(), E.value.allocated_textures.ptr()); + // Don't delete the current FBO, we'll do that a couple lines down. + if (E.value.fbo != rt->fbo) { + glDeleteFramebuffers(1, &E.value.fbo); + } + } + rt->overridden.fbo_cache.clear(); + if (rt->fbo) { glDeleteFramebuffers(1, &rt->fbo); rt->fbo = 0; } if (rt->overridden.color.is_null()) { - glDeleteTextures(1, &rt->color); - rt->color = 0; + if (rt->texture.is_valid()) { + Texture *tex = get_texture(rt->texture); + tex->alloc_height = 0; + tex->alloc_width = 0; + tex->width = 0; + tex->height = 0; + tex->active = false; + } + } else { + Texture *tex = get_texture(rt->overridden.color); + tex->is_render_target = false; } - if (rt->overridden.depth.is_null()) { - glDeleteTextures(1, &rt->depth); - rt->depth = 0; + if (rt->overridden.color.is_valid()) { + rt->overridden.color = RID(); + } else if (rt->color) { + glDeleteTextures(1, &rt->color); } + rt->color = 0; - if (rt->texture.is_valid()) { - Texture *tex = get_texture(rt->texture); - tex->alloc_height = 0; - tex->alloc_width = 0; - tex->width = 0; - tex->height = 0; - tex->active = false; + if (rt->overridden.depth.is_valid()) { + rt->overridden.depth = RID(); + } else if (rt->depth) { + glDeleteTextures(1, &rt->depth); } + rt->depth = 0; - if (rt->overridden.color.is_valid()) { - Texture *tex = get_texture(rt->overridden.color); - tex->is_render_target = false; - } + rt->overridden.velocity = RID(); + rt->overridden.is_overridden = false; if (rt->backbuffer_fbo != 0) { glDeleteFramebuffers(1, &rt->backbuffer_fbo); @@ -1732,15 +1749,6 @@ void TextureStorage::_clear_render_target(RenderTarget *rt) { _render_target_clear_sdf(rt); } -void TextureStorage::_clear_render_target_overridden_fbo_cache(RenderTarget *rt) { - // Dispose of the cached fbo's and the allocated textures - for (KeyValue<uint32_t, RenderTarget::RTOverridden::FBOCacheEntry> &E : rt->overridden.fbo_cache) { - glDeleteTextures(E.value.allocated_textures.size(), E.value.allocated_textures.ptr()); - glDeleteFramebuffers(1, &E.value.fbo); - } - rt->overridden.fbo_cache.clear(); -} - RID TextureStorage::render_target_create() { RenderTarget render_target; //render_target.was_used = false; @@ -1759,7 +1767,6 @@ RID TextureStorage::render_target_create() { void TextureStorage::render_target_free(RID p_rid) { RenderTarget *rt = render_target_owner.get_or_null(p_rid); _clear_render_target(rt); - _clear_render_target_overridden_fbo_cache(rt); Texture *t = get_texture(rt->texture); if (t) { @@ -1826,11 +1833,7 @@ void TextureStorage::render_target_set_override(RID p_render_target, RID p_color if (p_color_texture.is_null() && p_depth_texture.is_null()) { _clear_render_target(rt); - rt->overridden.is_overridden = false; - rt->overridden.color = RID(); - rt->overridden.depth = RID(); - rt->size = Size2i(); - _clear_render_target_overridden_fbo_cache(rt); + _update_render_target(rt); return; } @@ -1849,6 +1852,8 @@ void TextureStorage::render_target_set_override(RID p_render_target, RID p_color RBMap<uint32_t, RenderTarget::RTOverridden::FBOCacheEntry>::Element *cache; if ((cache = rt->overridden.fbo_cache.find(hash_key)) != nullptr) { rt->fbo = cache->get().fbo; + rt->color = cache->get().color; + rt->depth = cache->get().depth; rt->size = cache->get().size; rt->texture = p_color_texture; return; @@ -1858,6 +1863,8 @@ void TextureStorage::render_target_set_override(RID p_render_target, RID p_color RenderTarget::RTOverridden::FBOCacheEntry new_entry; new_entry.fbo = rt->fbo; + new_entry.color = rt->color; + new_entry.depth = rt->depth; new_entry.size = rt->size; // Keep track of any textures we had to allocate because they weren't overridden. if (p_color_texture.is_null()) { diff --git a/drivers/gles3/storage/texture_storage.h b/drivers/gles3/storage/texture_storage.h index c465576347..169c50638d 100644 --- a/drivers/gles3/storage/texture_storage.h +++ b/drivers/gles3/storage/texture_storage.h @@ -344,6 +344,8 @@ struct RenderTarget { struct FBOCacheEntry { GLuint fbo; + GLuint color; + GLuint depth; Size2i size; Vector<GLuint> allocated_textures; }; @@ -412,7 +414,6 @@ private: mutable RID_Owner<RenderTarget> render_target_owner; void _clear_render_target(RenderTarget *rt); - void _clear_render_target_overridden_fbo_cache(RenderTarget *rt); void _update_render_target(RenderTarget *rt); void _create_render_target_backbuffer(RenderTarget *rt); void _render_target_allocate_sdf(RenderTarget *rt); |