summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.cpp45
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.h2
-rw-r--r--drivers/gles3/rasterizer_gles3.cpp25
-rw-r--r--drivers/gles3/rasterizer_gles3.h2
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp50
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.h12
-rw-r--r--drivers/gles3/shader_gles3.cpp33
-rw-r--r--drivers/gles3/shader_gles3.h2
-rw-r--r--drivers/gles3/shaders/scene.glsl51
-rw-r--r--drivers/gles3/shaders/tonemap.glsl20
-rw-r--r--drivers/gles3/storage/config.cpp20
-rw-r--r--drivers/gles3/storage/config.h10
-rw-r--r--drivers/gles3/storage/mesh_storage.cpp36
-rw-r--r--drivers/gles3/storage/mesh_storage.h11
-rw-r--r--drivers/gles3/storage/render_scene_buffers_gles3.cpp48
-rw-r--r--drivers/gles3/storage/render_scene_buffers_gles3.h2
-rw-r--r--drivers/gles3/storage/texture_storage.cpp61
-rw-r--r--drivers/gles3/storage/texture_storage.h1
-rw-r--r--drivers/gles3/storage/utilities.cpp9
-rw-r--r--drivers/gles3/storage/utilities.h2
-rw-r--r--drivers/vulkan/rendering_device_vulkan.cpp4
-rw-r--r--drivers/vulkan/vulkan_context.cpp9
22 files changed, 379 insertions, 76 deletions
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp
index b407670098..5d0edda6c5 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.cpp
+++ b/drivers/gles3/rasterizer_canvas_gles3.cpp
@@ -436,10 +436,12 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, starting_index, false);
item_count = 0;
- Rect2i group_rect = ci->canvas_group_owner->global_rect_cache;
-
- if (ci->canvas_group_owner->canvas_group->mode == RS::CANVAS_GROUP_MODE_OPAQUE) {
+ if (ci->canvas_group_owner->canvas_group->mode != RS::CANVAS_GROUP_MODE_TRANSPARENT) {
+ Rect2i group_rect = ci->canvas_group_owner->global_rect_cache;
texture_storage->render_target_copy_to_back_buffer(p_to_render_target, group_rect, false);
+ if (ci->canvas_group_owner->canvas_group->mode == RS::CANVAS_GROUP_MODE_CLIP_AND_DRAW) {
+ items[item_count++] = ci->canvas_group_owner;
+ }
} else if (!backbuffer_cleared) {
texture_storage->render_target_clear_back_buffer(p_to_render_target, Rect2i(), Color(0, 0, 0, 0));
backbuffer_cleared = true;
@@ -547,9 +549,18 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou
}
RID material = ci->material_owner == nullptr ? ci->material : ci->material_owner->material;
-
- if (material.is_null() && ci->canvas_group != nullptr) {
- material = default_canvas_group_material;
+ if (ci->canvas_group != nullptr) {
+ if (ci->canvas_group->mode == RS::CANVAS_GROUP_MODE_CLIP_AND_DRAW) {
+ if (!p_to_backbuffer) {
+ material = default_clip_children_material;
+ }
+ } else {
+ if (ci->canvas_group->mode == RS::CANVAS_GROUP_MODE_CLIP_ONLY) {
+ material = default_clip_children_material;
+ } else {
+ material = default_canvas_group_material;
+ }
+ }
}
GLES3::CanvasShaderData *shader_data_cache = nullptr;
@@ -2078,6 +2089,26 @@ void fragment() {
material_storage->material_set_shader(default_canvas_group_material, default_canvas_group_shader);
}
+ {
+ default_clip_children_shader = material_storage->shader_allocate();
+ material_storage->shader_initialize(default_clip_children_shader);
+
+ material_storage->shader_set_code(default_clip_children_shader, R"(
+// Default clip children shader.
+
+shader_type canvas_item;
+
+void fragment() {
+ vec4 c = textureLod(SCREEN_TEXTURE, SCREEN_UV, 0.0);
+ COLOR.rgb = c.rgb;
+}
+)");
+ default_clip_children_material = material_storage->material_allocate();
+ material_storage->material_initialize(default_clip_children_material);
+
+ material_storage->material_set_shader(default_clip_children_material, default_clip_children_shader);
+ }
+
default_canvas_texture = texture_storage->canvas_texture_allocate();
texture_storage->canvas_texture_initialize(default_canvas_texture);
@@ -2090,6 +2121,8 @@ RasterizerCanvasGLES3::~RasterizerCanvasGLES3() {
material_storage->shaders.canvas_shader.version_free(data.canvas_shader_default_version);
material_storage->material_free(default_canvas_group_material);
material_storage->shader_free(default_canvas_group_shader);
+ material_storage->material_free(default_clip_children_material);
+ material_storage->shader_free(default_clip_children_shader);
singleton = nullptr;
glDeleteBuffers(1, &data.canvas_quad_vertices);
diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h
index 65e5f14838..aee2782b62 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.h
+++ b/drivers/gles3/rasterizer_canvas_gles3.h
@@ -284,6 +284,8 @@ public:
RID default_canvas_texture;
RID default_canvas_group_material;
RID default_canvas_group_shader;
+ RID default_clip_children_material;
+ RID default_clip_children_shader;
typedef void Texture;
diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp
index 0836a21254..ea97dff522 100644
--- a/drivers/gles3/rasterizer_gles3.cpp
+++ b/drivers/gles3/rasterizer_gles3.cpp
@@ -274,15 +274,32 @@ RasterizerGLES3::~RasterizerGLES3() {
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) {
+void RasterizerGLES3::_blit_render_target_to_screen(RID p_render_target, DisplayServer::WindowID p_screen, const Rect2 &p_screen_rect, uint32_t p_layer) {
GLES3::RenderTarget *rt = GLES3::TextureStorage::get_singleton()->get_render_target(p_render_target);
+
ERR_FAIL_COND(!rt);
- glBindFramebuffer(GL_READ_FRAMEBUFFER, rt->fbo);
+ GLuint read_fbo = 0;
+ if (rt->view_count > 1) {
+ glGenFramebuffers(1, &read_fbo);
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, read_fbo);
+ glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, rt->color, 0, p_layer);
+ } else {
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, rt->fbo);
+ }
+
glReadBuffer(GL_COLOR_ATTACHMENT0);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);
// Flip content upside down to correct for coordinates.
- glBlitFramebuffer(0, 0, rt->size.x, rt->size.y, 0, p_screen_rect.size.y, p_screen_rect.size.x, 0, GL_COLOR_BUFFER_BIT, GL_NEAREST);
+ 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,
+ GL_COLOR_BUFFER_BIT, GL_NEAREST);
+
+ if (read_fbo != 0) {
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
+ glDeleteFramebuffers(1, &read_fbo);
+ }
}
// is this p_screen useless in a multi window environment?
@@ -293,7 +310,7 @@ void RasterizerGLES3::blit_render_targets_to_screen(DisplayServer::WindowID p_sc
RID rid_rt = blit.render_target;
Rect2 dst_rect = blit.dst_rect;
- _blit_render_target_to_screen(rid_rt, p_screen, dst_rect);
+ _blit_render_target_to_screen(rid_rt, p_screen, dst_rect, blit.multi_view.use_layer ? blit.multi_view.layer : 0);
}
}
diff --git a/drivers/gles3/rasterizer_gles3.h b/drivers/gles3/rasterizer_gles3.h
index 431515fd0d..d7d26685b4 100644
--- a/drivers/gles3/rasterizer_gles3.h
+++ b/drivers/gles3/rasterizer_gles3.h
@@ -68,7 +68,7 @@ protected:
RasterizerCanvasGLES3 *canvas = nullptr;
RasterizerSceneGLES3 *scene = nullptr;
- void _blit_render_target_to_screen(RID p_render_target, DisplayServer::WindowID p_screen, const Rect2 &p_screen_rect);
+ void _blit_render_target_to_screen(RID p_render_target, DisplayServer::WindowID p_screen, const Rect2 &p_screen_rect, uint32_t p_layer);
public:
RendererUtilities *get_utilities() { return utilities; }
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index d6486801e7..6e9d4e5963 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -1189,8 +1189,8 @@ void RasterizerSceneGLES3::_fill_render_list(RenderListType p_render_list, const
distance = 1.0;
}
- uint32_t indices;
- surf->lod_index = mesh_storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, &indices);
+ uint32_t indices = 0;
+ surf->lod_index = mesh_storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, indices);
/*
if (p_render_data->render_info) {
indices = _indices_to_primitives(surf->primitive, indices);
@@ -1273,6 +1273,19 @@ void RasterizerSceneGLES3::_setup_environment(const RenderDataGLES3 *p_render_da
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);
+ if (p_render_data->view_count > 1) {
+ for (uint32_t v = 0; v < p_render_data->view_count; v++) {
+ projection = correction * p_render_data->view_projection[v];
+ GLES3::MaterialStorage::store_camera(projection, scene_state.multiview_ubo.projection_matrix_view[v]);
+ GLES3::MaterialStorage::store_camera(projection.inverse(), scene_state.multiview_ubo.inv_projection_matrix_view[v]);
+
+ scene_state.multiview_ubo.eye_offset[v][0] = p_render_data->view_eye_offset[v].x;
+ scene_state.multiview_ubo.eye_offset[v][1] = p_render_data->view_eye_offset[v].y;
+ scene_state.multiview_ubo.eye_offset[v][2] = p_render_data->view_eye_offset[v].z;
+ scene_state.multiview_ubo.eye_offset[v][3] = 0.0;
+ }
+ }
+
scene_state.ubo.directional_light_count = p_render_data->directional_light_count;
scene_state.ubo.z_far = p_render_data->z_far;
@@ -1374,6 +1387,15 @@ void RasterizerSceneGLES3::_setup_environment(const RenderDataGLES3 *p_render_da
glBindBufferBase(GL_UNIFORM_BUFFER, SCENE_DATA_UNIFORM_LOCATION, scene_state.ubo_buffer);
glBufferData(GL_UNIFORM_BUFFER, sizeof(SceneState::UBO), &scene_state.ubo, GL_STREAM_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
+
+ if (p_render_data->view_count > 1) {
+ if (scene_state.multiview_buffer == 0) {
+ glGenBuffers(1, &scene_state.multiview_buffer);
+ }
+ glBindBufferBase(GL_UNIFORM_BUFFER, SCENE_MULTIVIEW_UNIFORM_LOCATION, scene_state.multiview_buffer);
+ glBufferData(GL_UNIFORM_BUFFER, sizeof(SceneState::MultiviewUBO), &scene_state.multiview_ubo, GL_STREAM_DRAW);
+ glBindBuffer(GL_UNIFORM_BUFFER, 0);
+ }
}
// Puts lights into Uniform Buffers. Needs to be called before _fill_list as this caches the index of each light in the Uniform Buffer
@@ -1916,8 +1938,14 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
GLES3::SceneShaderData *prev_shader = nullptr;
GeometryInstanceGLES3 *prev_inst = nullptr;
SceneShaderGLES3::ShaderVariant prev_variant = SceneShaderGLES3::ShaderVariant::MODE_COLOR;
+ SceneShaderGLES3::ShaderVariant shader_variant = SceneShaderGLES3::MODE_COLOR; // Assigned to silence wrong -Wmaybe-initialized
- SceneShaderGLES3::ShaderVariant shader_variant = SceneShaderGLES3::MODE_COLOR; // Assigned to silence wrong -Wmaybe-initialized.
+ // @todo Get this from p_params->spec_constant_base_flags instead of hardcoding it.
+ uint32_t base_spec_constants = 0;
+
+ if (p_render_data->view_count > 1) {
+ base_spec_constants |= 1 << SPEC_CONSTANT_USE_MULTIVIEW;
+ }
switch (p_pass_mode) {
case PASS_MODE_COLOR:
@@ -1957,8 +1985,6 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
continue;
}
- //uint32_t base_spec_constants = p_params->spec_constant_base_flags;
-
GLES3::SceneShaderData *shader;
GLES3::SceneMaterialData *material_data;
void *mesh_surface;
@@ -2128,7 +2154,7 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
}
if (prev_shader != shader || prev_variant != instance_variant) {
- material_storage->shaders.scene_shader.version_bind_shader(shader->version, instance_variant);
+ material_storage->shaders.scene_shader.version_bind_shader(shader->version, instance_variant, base_spec_constants);
float opaque_prepass_threshold = 0.0;
if constexpr (p_pass_mode == PASS_MODE_DEPTH) {
opaque_prepass_threshold = 0.99;
@@ -2136,7 +2162,7 @@ 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);
+ material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::OPAQUE_PREPASS_THRESHOLD, opaque_prepass_threshold, shader->version, instance_variant, base_spec_constants);
prev_shader = shader;
prev_variant = instance_variant;
@@ -2144,21 +2170,21 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
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);
- material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::SPOT_LIGHT_COUNT, inst->spot_light_count, shader->version, instance_variant);
+ 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);
if (inst->omni_light_count) {
- glUniform1uiv(material_storage->shaders.scene_shader.version_get_uniform(SceneShaderGLES3::OMNI_LIGHT_INDICES, shader->version, instance_variant), inst->omni_light_count, inst->omni_light_gl_cache.ptr());
+ 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());
}
if (inst->spot_light_count) {
- glUniform1uiv(material_storage->shaders.scene_shader.version_get_uniform(SceneShaderGLES3::SPOT_LIGHT_INDICES, shader->version, instance_variant), inst->spot_light_count, inst->spot_light_gl_cache.ptr());
+ 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());
}
prev_inst = inst;
}
- material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::WORLD_TRANSFORM, world_transform, shader->version, instance_variant);
+ material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::WORLD_TRANSFORM, world_transform, shader->version, instance_variant, base_spec_constants);
if (inst->instance_count > 0) {
// Using MultiMesh.
// Bind instance buffers.
diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h
index 3895620228..3a759425e2 100644
--- a/drivers/gles3/rasterizer_scene_gles3.h
+++ b/drivers/gles3/rasterizer_scene_gles3.h
@@ -74,6 +74,7 @@ enum SceneUniformLocation {
SCENE_OMNILIGHT_UNIFORM_LOCATION,
SCENE_SPOTLIGHT_UNIFORM_LOCATION,
SCENE_DIRECTIONAL_LIGHT_UNIFORM_LOCATION,
+ SCENE_MULTIVIEW_UNIFORM_LOCATION,
};
enum SkyUniformLocation {
@@ -90,6 +91,8 @@ enum {
SPEC_CONSTANT_DISABLE_OMNI_LIGHTS = 2,
SPEC_CONSTANT_DISABLE_SPOT_LIGHTS = 3,
SPEC_CONSTANT_DISABLE_FOG = 4,
+ SPEC_CONSTANT_USE_RADIANCE_MAP = 5,
+ SPEC_CONSTANT_USE_MULTIVIEW = 6,
};
struct RenderDataGLES3 {
@@ -343,6 +346,13 @@ private:
};
static_assert(sizeof(UBO) % 16 == 0, "Scene UBO size must be a multiple of 16 bytes");
+ struct MultiviewUBO {
+ float projection_matrix_view[RendererSceneRender::MAX_RENDER_VIEWS][16];
+ float inv_projection_matrix_view[RendererSceneRender::MAX_RENDER_VIEWS][16];
+ float eye_offset[RendererSceneRender::MAX_RENDER_VIEWS][4];
+ };
+ static_assert(sizeof(MultiviewUBO) % 16 == 0, "Multiview UBO size must be a multiple of 16 bytes");
+
struct TonemapUBO {
float exposure = 1.0;
float white = 1.0;
@@ -353,6 +363,8 @@ private:
UBO ubo;
GLuint ubo_buffer = 0;
+ MultiviewUBO multiview_ubo;
+ GLuint multiview_buffer = 0;
GLuint tonemap_buffer = 0;
bool used_depth_prepass = false;
diff --git a/drivers/gles3/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp
index 033f10dbc5..2ff7f72180 100644
--- a/drivers/gles3/shader_gles3.cpp
+++ b/drivers/gles3/shader_gles3.cpp
@@ -142,7 +142,7 @@ RID ShaderGLES3::version_create() {
return version_owner.make_rid(version);
}
-void ShaderGLES3::_build_variant_code(StringBuilder &builder, uint32_t p_variant, const Version *p_version, const StageTemplate &p_template, uint64_t p_specialization) {
+void ShaderGLES3::_build_variant_code(StringBuilder &builder, uint32_t p_variant, const Version *p_version, StageType p_stage_type, uint64_t p_specialization) {
#ifdef GLES_OVER_GL
builder.append("#version 330\n");
builder.append("#define USE_GLES_OVER_GL\n");
@@ -171,6 +171,24 @@ void ShaderGLES3::_build_variant_code(StringBuilder &builder, uint32_t p_variant
}
builder.append("\n"); //make sure defines begin at newline
+ // Insert multiview extension loading, because it needs to appear before
+ // any non-preprocessor code (like the "precision highp..." lines below).
+ builder.append("#ifdef USE_MULTIVIEW\n");
+ builder.append("#if defined(GL_OVR_multiview2)\n");
+ builder.append("#extension GL_OVR_multiview2 : require\n");
+ builder.append("#elif defined(GL_OVR_multiview)\n");
+ builder.append("#extension GL_OVR_multiview : require\n");
+ builder.append("#endif\n");
+ if (p_stage_type == StageType::STAGE_TYPE_VERTEX) {
+ builder.append("layout(num_views=2) in;\n");
+ }
+ builder.append("#define ViewIndex gl_ViewID_OVR\n");
+ builder.append("#define MAX_VIEWS 2\n");
+ builder.append("#else\n");
+ builder.append("#define ViewIndex 0\n");
+ builder.append("#define MAX_VIEWS 1\n");
+ builder.append("#endif\n");
+
// Default to highp precision unless specified otherwise.
builder.append("precision highp float;\n");
builder.append("precision highp int;\n");
@@ -180,8 +198,9 @@ void ShaderGLES3::_build_variant_code(StringBuilder &builder, uint32_t p_variant
builder.append("precision highp sampler2DArray;\n");
#endif
- for (uint32_t i = 0; i < p_template.chunks.size(); i++) {
- const StageTemplate::Chunk &chunk = p_template.chunks[i];
+ const StageTemplate &stage_template = stage_templates[p_stage_type];
+ for (uint32_t i = 0; i < stage_template.chunks.size(); i++) {
+ const StageTemplate::Chunk &chunk = stage_template.chunks[i];
switch (chunk.type) {
case StageTemplate::Chunk::TYPE_MATERIAL_UNIFORMS: {
builder.append(p_version->uniforms.get_data()); //uniforms (same for vertex and fragment)
@@ -224,7 +243,7 @@ void ShaderGLES3::_compile_specialization(Version::Specialization &spec, uint32_
//vertex stage
{
StringBuilder builder;
- _build_variant_code(builder, p_variant, p_version, stage_templates[STAGE_TYPE_VERTEX], p_specialization);
+ _build_variant_code(builder, p_variant, p_version, STAGE_TYPE_VERTEX, p_specialization);
spec.vert_id = glCreateShader(GL_VERTEX_SHADER);
String builder_string = builder.as_string();
@@ -272,7 +291,7 @@ void ShaderGLES3::_compile_specialization(Version::Specialization &spec, uint32_
//fragment stage
{
StringBuilder builder;
- _build_variant_code(builder, p_variant, p_version, stage_templates[STAGE_TYPE_FRAGMENT], p_specialization);
+ _build_variant_code(builder, p_variant, p_version, STAGE_TYPE_FRAGMENT, p_specialization);
spec.frag_id = glCreateShader(GL_FRAGMENT_SHADER);
String builder_string = builder.as_string();
@@ -413,7 +432,7 @@ RS::ShaderNativeSourceCode ShaderGLES3::version_get_native_source_code(RID p_ver
{
StringBuilder builder;
- _build_variant_code(builder, i, version, stage_templates[STAGE_TYPE_VERTEX], specialization_default_mask);
+ _build_variant_code(builder, i, version, STAGE_TYPE_VERTEX, specialization_default_mask);
RS::ShaderNativeSourceCode::Version::Stage stage;
stage.name = "vertex";
@@ -425,7 +444,7 @@ RS::ShaderNativeSourceCode ShaderGLES3::version_get_native_source_code(RID p_ver
//fragment stage
{
StringBuilder builder;
- _build_variant_code(builder, i, version, stage_templates[STAGE_TYPE_FRAGMENT], specialization_default_mask);
+ _build_variant_code(builder, i, version, STAGE_TYPE_FRAGMENT, specialization_default_mask);
RS::ShaderNativeSourceCode::Version::Stage stage;
stage.name = "fragment";
diff --git a/drivers/gles3/shader_gles3.h b/drivers/gles3/shader_gles3.h
index 2b72549b5b..760b5e5ddb 100644
--- a/drivers/gles3/shader_gles3.h
+++ b/drivers/gles3/shader_gles3.h
@@ -153,7 +153,7 @@ private:
StageTemplate stage_templates[STAGE_TYPE_MAX];
- void _build_variant_code(StringBuilder &p_builder, uint32_t p_variant, const Version *p_version, const StageTemplate &p_template, uint64_t p_specialization);
+ void _build_variant_code(StringBuilder &p_builder, uint32_t p_variant, const Version *p_version, StageType p_stage_type, uint64_t p_specialization);
void _add_stage(const char *p_code, StageType p_stage_type);
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl
index efd6036ba9..ed176c7829 100644
--- a/drivers/gles3/shaders/scene.glsl
+++ b/drivers/gles3/shaders/scene.glsl
@@ -16,6 +16,7 @@ DISABLE_LIGHT_OMNI = false
DISABLE_LIGHT_SPOT = false
DISABLE_FOG = false
USE_RADIANCE_MAP = true
+USE_MULTIVIEW = false
#[vertex]
@@ -153,6 +154,15 @@ layout(std140) uniform SceneData { // ubo:2
}
scene_data;
+#ifdef USE_MULTIVIEW
+layout(std140) uniform MultiviewData { // ubo:8
+ highp mat4 projection_matrix_view[MAX_VIEWS];
+ highp mat4 inv_projection_matrix_view[MAX_VIEWS];
+ highp vec4 eye_offset[MAX_VIEWS];
+}
+multiview_data;
+#endif
+
uniform highp mat4 world_transform;
#ifdef USE_LIGHTMAP
@@ -250,8 +260,14 @@ void main() {
#if defined(OVERRIDE_POSITION)
highp vec4 position;
#endif
- highp mat4 projection_matrix = scene_data.projection_matrix;
- highp mat4 inv_projection_matrix = scene_data.inv_projection_matrix;
+
+#ifdef USE_MULTIVIEW
+ mat4 projection_matrix = multiview_data.projection_matrix_view[ViewIndex];
+ mat4 inv_projection_matrix = multiview_data.inv_projection_matrix_view[ViewIndex];
+#else
+ mat4 projection_matrix = scene_data.projection_matrix;
+ mat4 inv_projection_matrix = scene_data.inv_projection_matrix;
+#endif //USE_MULTIVIEW
#ifdef USE_INSTANCING
vec4 instance_custom = vec4(unpackHalf2x16(instance_color_custom_data.z), unpackHalf2x16(instance_color_custom_data.w));
@@ -339,7 +355,6 @@ void main() {
/* clang-format off */
#[fragment]
-
// Default to SPECULAR_SCHLICK_GGX.
#if !defined(SPECULAR_DISABLED) && !defined(SPECULAR_SCHLICK_GGX) && !defined(SPECULAR_TOON)
#define SPECULAR_SCHLICK_GGX
@@ -463,6 +478,15 @@ layout(std140) uniform SceneData { // ubo:2
}
scene_data;
+#ifdef USE_MULTIVIEW
+layout(std140) uniform MultiviewData { // ubo:8
+ highp mat4 projection_matrix_view[MAX_VIEWS];
+ highp mat4 inv_projection_matrix_view[MAX_VIEWS];
+ highp vec4 eye_offset[MAX_VIEWS];
+}
+multiview_data;
+#endif
+
/* clang-format off */
#GLOBALS
@@ -530,8 +554,13 @@ uniform highp samplerCubeShadow positional_shadow; // texunit:-4
#endif // !defined(DISABLE_LIGHT_OMNI) && !defined(DISABLE_LIGHT_SPOT)
-uniform highp sampler2D screen_texture; // texunit:-5
+#ifdef USE_MULTIVIEW
+uniform highp sampler2DArray depth_buffer; // texunit:-6
+uniform highp sampler2DArray screen_texture; // texunit:-5
+#else
uniform highp sampler2D depth_buffer; // texunit:-6
+uniform highp sampler2D screen_texture; // texunit:-5
+#endif
uniform highp mat4 world_transform;
uniform mediump float opaque_prepass_threshold;
@@ -884,7 +913,11 @@ vec4 fog_process(vec3 vertex) {
void main() {
//lay out everything, whatever is unused is optimized away anyway
vec3 vertex = vertex_interp;
+#ifdef USE_MULTIVIEW
+ vec3 view = -normalize(vertex_interp - multiview_data.eye_offset[ViewIndex].xyz);
+#else
vec3 view = -normalize(vertex_interp);
+#endif
vec3 albedo = vec3(1.0);
vec3 backlight = vec3(0.0);
vec4 transmittance_color = vec4(0.0, 0.0, 0.0, 1.0);
@@ -1096,9 +1129,15 @@ void main() {
#if defined(CUSTOM_IRRADIANCE_USED)
ambient_light = mix(ambient_light, custom_irradiance.rgb, custom_irradiance.a);
#endif // CUSTOM_IRRADIANCE_USED
- ambient_light *= albedo.rgb;
- ambient_light *= ao;
+ {
+#if defined(AMBIENT_LIGHT_DISABLED)
+ ambient_light = vec3(0.0, 0.0, 0.0);
+#else
+ ambient_light *= albedo.rgb;
+ ambient_light *= ao;
+#endif // AMBIENT_LIGHT_DISABLED
+ }
// convert ao to direct light ao
ao = mix(1.0, ao, ao_light_affect);
diff --git a/drivers/gles3/shaders/tonemap.glsl b/drivers/gles3/shaders/tonemap.glsl
index a478cf9170..0b769e77f2 100644
--- a/drivers/gles3/shaders/tonemap.glsl
+++ b/drivers/gles3/shaders/tonemap.glsl
@@ -44,7 +44,11 @@ in vec2 uv_interp;
layout(location = 0) out vec4 frag_color;
+#ifdef USE_MULTIVIEW
+uniform highp sampler2DArray source; //texunit:0
+#else
uniform highp sampler2D source; //texunit:0
+#endif
#if defined(USE_GLOW_LEVEL1) || defined(USE_GLOW_LEVEL2) || defined(USE_GLOW_LEVEL3) || defined(USE_GLOW_LEVEL4) || defined(USE_GLOW_LEVEL5) || defined(USE_GLOW_LEVEL6) || defined(USE_GLOW_LEVEL7)
#define USING_GLOW // only use glow when at least one glow level is selected
@@ -191,10 +195,17 @@ vec3 apply_fxaa(vec3 color, vec2 uv_interp, vec2 pixel_size) {
const float FXAA_REDUCE_MUL = (1.0 / 8.0);
const float FXAA_SPAN_MAX = 8.0;
+#ifdef USE_MULTIVIEW
+ vec3 rgbNW = textureLod(source, vec3(uv_interp + vec2(-1.0, -1.0) * pixel_size, ViewIndex), 0.0).xyz;
+ vec3 rgbNE = textureLod(source, vec3(uv_interp + vec2(1.0, -1.0) * pixel_size, ViewIndex), 0.0).xyz;
+ vec3 rgbSW = textureLod(source, vec3(uv_interp + vec2(-1.0, 1.0) * pixel_size, ViewIndex), 0.0).xyz;
+ vec3 rgbSE = textureLod(source, vec3(uv_interp + vec2(1.0, 1.0) * pixel_size, ViewIndex), 0.0).xyz;
+#else
vec3 rgbNW = textureLod(source, uv_interp + vec2(-1.0, -1.0) * pixel_size, 0.0).xyz;
vec3 rgbNE = textureLod(source, uv_interp + vec2(1.0, -1.0) * pixel_size, 0.0).xyz;
vec3 rgbSW = textureLod(source, uv_interp + vec2(-1.0, 1.0) * pixel_size, 0.0).xyz;
vec3 rgbSE = textureLod(source, uv_interp + vec2(1.0, 1.0) * pixel_size, 0.0).xyz;
+#endif
vec3 rgbM = color;
vec3 luma = vec3(0.299, 0.587, 0.114);
float lumaNW = dot(rgbNW, luma);
@@ -219,8 +230,13 @@ vec3 apply_fxaa(vec3 color, vec2 uv_interp, vec2 pixel_size) {
dir * rcpDirMin)) *
pixel_size;
+#ifdef USE_MULTIVIEW
+ vec3 rgbA = 0.5 * (textureLod(source, vec3(uv_interp + dir * (1.0 / 3.0 - 0.5), ViewIndex), 0.0).xyz + textureLod(source, vec3(uv_interp + dir * (2.0 / 3.0 - 0.5), ViewIndex), 0.0).xyz);
+ vec3 rgbB = rgbA * 0.5 + 0.25 * (textureLod(source, vec3(uv_interp + dir * -0.5, ViewIndex), 0.0).xyz + textureLod(source, vec3(uv_interp + dir * 0.5, ViewIndex), 0.0).xyz);
+#else
vec3 rgbA = 0.5 * (textureLod(source, uv_interp + dir * (1.0 / 3.0 - 0.5), 0.0).xyz + textureLod(source, uv_interp + dir * (2.0 / 3.0 - 0.5), 0.0).xyz);
vec3 rgbB = rgbA * 0.5 + 0.25 * (textureLod(source, uv_interp + dir * -0.5, 0.0).xyz + textureLod(source, uv_interp + dir * 0.5, 0.0).xyz);
+#endif
float lumaB = dot(rgbB, luma);
if ((lumaB < lumaMin) || (lumaB > lumaMax)) {
@@ -231,7 +247,11 @@ vec3 apply_fxaa(vec3 color, vec2 uv_interp, vec2 pixel_size) {
}
void main() {
+#ifdef USE_MULTIVIEW
+ vec4 color = textureLod(source, vec3(uv_interp, ViewIndex), 0.0);
+#else
vec4 color = textureLod(source, uv_interp, 0.0);
+#endif
#ifdef USE_FXAA
color.rgb = apply_fxaa(color.rgb, uv_interp, pixel_size);
diff --git a/drivers/gles3/storage/config.cpp b/drivers/gles3/storage/config.cpp
index 242c1ce0a9..943df3b156 100644
--- a/drivers/gles3/storage/config.cpp
+++ b/drivers/gles3/storage/config.cpp
@@ -34,6 +34,15 @@
#include "core/config/project_settings.h"
#include "core/templates/vector.h"
+#ifdef ANDROID_ENABLED
+#include <GLES3/gl3.h>
+#include <GLES3/gl3ext.h>
+#include <GLES3/gl3platform.h>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#endif
+
using namespace GLES3;
#define _GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
@@ -85,6 +94,7 @@ Config::Config() {
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &max_texture_image_units);
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &max_uniform_buffer_size);
+ glGetIntegerv(GL_MAX_VIEWPORT_DIMS, &max_viewport_size);
glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &uniform_buffer_offset_alignment);
@@ -98,6 +108,16 @@ Config::Config() {
anisotropic_level = MIN(float(1 << int(ProjectSettings::get_singleton()->get("rendering/textures/default_filters/anisotropic_filtering_level"))), anisotropic_level);
}
+ multiview_supported = extensions.has("GL_OVR_multiview2") || extensions.has("GL_OVR_multiview");
+#ifdef ANDROID_ENABLED
+ if (multiview_supported) {
+ eglFramebufferTextureMultiviewOVR = (PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC)eglGetProcAddress("glFramebufferTextureMultiviewOVR");
+ if (eglFramebufferTextureMultiviewOVR == nullptr) {
+ multiview_supported = false;
+ }
+ }
+#endif
+
force_vertex_shading = false; //GLOBAL_GET("rendering/quality/shading/force_vertex_shading");
use_nearest_mip_filter = GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter");
diff --git a/drivers/gles3/storage/config.h b/drivers/gles3/storage/config.h
index fe18345775..d4b38acd18 100644
--- a/drivers/gles3/storage/config.h
+++ b/drivers/gles3/storage/config.h
@@ -44,6 +44,10 @@
#include OPENGL_INCLUDE_H
#endif
+#ifdef ANDROID_ENABLED
+typedef void (*PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC)(GLenum, GLenum, GLuint, GLint, GLint, GLsizei);
+#endif
+
namespace GLES3 {
class Config {
@@ -60,6 +64,7 @@ public:
int max_texture_image_units = 0;
int max_texture_size = 0;
int max_uniform_buffer_size = 0;
+ int max_viewport_size = 0;
int max_renderable_elements = 0;
int max_renderable_lights = 0;
int max_lights_per_object = 0;
@@ -82,6 +87,11 @@ public:
bool support_anisotropic_filter = false;
float anisotropic_level = 0.0f;
+ bool multiview_supported = false;
+#ifdef ANDROID_ENABLED
+ PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC eglFramebufferTextureMultiviewOVR = nullptr;
+#endif
+
static Config *get_singleton() { return singleton; };
Config();
diff --git a/drivers/gles3/storage/mesh_storage.cpp b/drivers/gles3/storage/mesh_storage.cpp
index 22d84eba93..11ce31856d 100644
--- a/drivers/gles3/storage/mesh_storage.cpp
+++ b/drivers/gles3/storage/mesh_storage.cpp
@@ -309,12 +309,48 @@ RS::BlendShapeMode MeshStorage::mesh_get_blend_shape_mode(RID p_mesh) const {
}
void MeshStorage::mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND(!mesh);
+ ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count);
+ ERR_FAIL_COND(p_data.size() == 0);
+
+ uint64_t data_size = p_data.size();
+ ERR_FAIL_COND(p_offset + data_size > mesh->surfaces[p_surface]->vertex_buffer_size);
+ const uint8_t *r = p_data.ptr();
+
+ glBindBuffer(GL_ARRAY_BUFFER, mesh->surfaces[p_surface]->vertex_buffer);
+ glBufferSubData(GL_ARRAY_BUFFER, p_offset, data_size, r);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void MeshStorage::mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND(!mesh);
+ ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count);
+ ERR_FAIL_COND(p_data.size() == 0);
+
+ uint64_t data_size = p_data.size();
+ ERR_FAIL_COND(p_offset + data_size > mesh->surfaces[p_surface]->attribute_buffer_size);
+ const uint8_t *r = p_data.ptr();
+
+ glBindBuffer(GL_ARRAY_BUFFER, mesh->surfaces[p_surface]->attribute_buffer);
+ glBufferSubData(GL_ARRAY_BUFFER, p_offset, data_size, r);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void MeshStorage::mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND(!mesh);
+ ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count);
+ ERR_FAIL_COND(p_data.size() == 0);
+
+ uint64_t data_size = p_data.size();
+ ERR_FAIL_COND(p_offset + data_size > mesh->surfaces[p_surface]->skin_buffer_size);
+ const uint8_t *r = p_data.ptr();
+
+ glBindBuffer(GL_ARRAY_BUFFER, mesh->surfaces[p_surface]->skin_buffer);
+ glBufferSubData(GL_ARRAY_BUFFER, p_offset, data_size, r);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void MeshStorage::mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) {
diff --git a/drivers/gles3/storage/mesh_storage.h b/drivers/gles3/storage/mesh_storage.h
index 74f5800795..a31db24f2d 100644
--- a/drivers/gles3/storage/mesh_storage.h
+++ b/drivers/gles3/storage/mesh_storage.h
@@ -325,13 +325,12 @@ public:
return s->index_count ? s->index_count : s->vertex_count;
}
- _FORCE_INLINE_ uint32_t mesh_surface_get_lod(void *p_surface, float p_model_scale, float p_distance_threshold, float p_mesh_lod_threshold, uint32_t *r_index_count = nullptr) const {
+ _FORCE_INLINE_ uint32_t mesh_surface_get_lod(void *p_surface, float p_model_scale, float p_distance_threshold, float p_mesh_lod_threshold, uint32_t &r_index_count) const {
Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
int32_t current_lod = -1;
- if (r_index_count) {
- *r_index_count = s->index_count;
- }
+ r_index_count = s->index_count;
+
for (uint32_t i = 0; i < s->lod_count; i++) {
float screen_size = s->lods[i].edge_length * p_model_scale / p_distance_threshold;
if (screen_size > p_mesh_lod_threshold) {
@@ -342,9 +341,7 @@ public:
if (current_lod == -1) {
return 0;
} else {
- if (r_index_count) {
- *r_index_count = s->lods[current_lod].index_count;
- }
+ r_index_count = s->lods[current_lod].index_count;
return current_lod + 1;
}
}
diff --git a/drivers/gles3/storage/render_scene_buffers_gles3.cpp b/drivers/gles3/storage/render_scene_buffers_gles3.cpp
index 9123984dc7..b8e4530f56 100644
--- a/drivers/gles3/storage/render_scene_buffers_gles3.cpp
+++ b/drivers/gles3/storage/render_scene_buffers_gles3.cpp
@@ -33,12 +33,17 @@
#include "render_scene_buffers_gles3.h"
#include "texture_storage.h"
+#ifdef ANDROID_ENABLED
+#define glFramebufferTextureMultiviewOVR GLES3::Config::get_singleton()->eglFramebufferTextureMultiviewOVR
+#endif
+
RenderSceneBuffersGLES3::~RenderSceneBuffersGLES3() {
free_render_buffer_data();
}
void RenderSceneBuffersGLES3::configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) {
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
+ GLES3::Config *config = GLES3::Config::get_singleton();
//internal_size.x = p_internal_size.x; // ignore for now
//internal_size.y = p_internal_size.y;
@@ -50,7 +55,7 @@ void RenderSceneBuffersGLES3::configure(RID p_render_target, const Size2i p_inte
//msaa = p_msaa;
//screen_space_aa = p_screen_space_aa;
//use_debanding = p_use_debanding;
- //view_count = p_view_count;
+ view_count = p_view_count;
free_render_buffer_data();
@@ -62,24 +67,43 @@ void RenderSceneBuffersGLES3::configure(RID p_render_target, const Size2i p_inte
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
- glBindTexture(GL_TEXTURE_2D, rt->color);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color, 0);
+ if (view_count > 1 && config->multiview_supported) {
+ glBindTexture(GL_TEXTURE_2D_ARRAY, rt->color);
+ glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, rt->color, 0, 0, view_count);
+ } else {
+ glBindTexture(GL_TEXTURE_2D, rt->color);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color, 0);
+ }
glGenTextures(1, &depth_texture);
- glBindTexture(GL_TEXTURE_2D, depth_texture);
-
- glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, rt->size.x, rt->size.y, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ if (view_count > 1 && config->multiview_supported) {
+ glBindTexture(GL_TEXTURE_2D_ARRAY, depth_texture);
+ glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_DEPTH_COMPONENT24, rt->size.x, rt->size.y, view_count, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
+
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ } else {
+ glBindTexture(GL_TEXTURE_2D, depth_texture);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, rt->size.x, rt->size.y, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ }
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth_texture, 0);
+ if (view_count > 1 && config->multiview_supported) {
+ glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depth_texture, 0, 0, view_count);
+ } else {
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth_texture, 0);
+ }
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
glBindTexture(GL_TEXTURE_2D, 0);
+ glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
glBindFramebuffer(GL_FRAMEBUFFER, texture_storage->system_fbo);
if (status != GL_FRAMEBUFFER_COMPLETE) {
diff --git a/drivers/gles3/storage/render_scene_buffers_gles3.h b/drivers/gles3/storage/render_scene_buffers_gles3.h
index ad0d2032b0..dbedbd22c3 100644
--- a/drivers/gles3/storage/render_scene_buffers_gles3.h
+++ b/drivers/gles3/storage/render_scene_buffers_gles3.h
@@ -56,7 +56,7 @@ public:
RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED;
//RS::ViewportScreenSpaceAA screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED;
//bool use_debanding = false;
- //uint32_t view_count = 1;
+ uint32_t view_count = 1;
bool is_transparent = false;
diff --git a/drivers/gles3/storage/texture_storage.cpp b/drivers/gles3/storage/texture_storage.cpp
index 554b4165fa..524ff14cc9 100644
--- a/drivers/gles3/storage/texture_storage.cpp
+++ b/drivers/gles3/storage/texture_storage.cpp
@@ -34,6 +34,10 @@
#include "config.h"
#include "drivers/gles3/effects/copy_effects.h"
+#ifdef ANDROID_ENABLED
+#define glFramebufferTextureMultiviewOVR GLES3::Config::get_singleton()->eglFramebufferTextureMultiviewOVR
+#endif
+
using namespace GLES3;
TextureStorage *TextureStorage::singleton = nullptr;
@@ -720,8 +724,7 @@ void TextureStorage::texture_proxy_initialize(RID p_texture, RID p_base) {
}
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);
+ texture_set_data(p_texture, p_image, p_layer);
#ifdef TOOLS_ENABLED
Texture *tex = texture_owner.get_or_null(p_texture);
@@ -1012,7 +1015,7 @@ void TextureStorage::texture_set_data(RID p_texture, const Ref<Image> &p_image,
img->resize_to_po2(false);
}
- GLenum blit_target = (texture->target == GL_TEXTURE_CUBE_MAP) ? _cube_side_enum[p_layer] : GL_TEXTURE_2D;
+ GLenum blit_target = (texture->target == GL_TEXTURE_CUBE_MAP) ? _cube_side_enum[p_layer] : texture->target;
Vector<uint8_t> read = img->get_data();
@@ -1069,7 +1072,11 @@ void TextureStorage::texture_set_data(RID p_texture, const Ref<Image> &p_image,
glCompressedTexImage2D(blit_target, i, internal_format, bw, bh, 0, size, &read[ofs]);
} else {
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- glTexImage2D(blit_target, i, internal_format, w, h, 0, format, type, &read[ofs]);
+ if (texture->target == GL_TEXTURE_2D_ARRAY) {
+ glTexSubImage3D(GL_TEXTURE_2D_ARRAY, i, 0, 0, p_layer, w, h, 0, format, type, &read[ofs]);
+ } else {
+ glTexImage2D(blit_target, i, internal_format, w, h, 0, format, type, &read[ofs]);
+ }
}
tsize += size;
@@ -1425,6 +1432,8 @@ void TextureStorage::_update_render_target(RenderTarget *rt) {
return;
}
+ Config *config = Config::get_singleton();
+
rt->color_internal_format = rt->is_transparent ? GL_RGBA8 : GL_RGB10_A2;
rt->color_format = GL_RGBA;
rt->color_type = rt->is_transparent ? GL_UNSIGNED_BYTE : GL_UNSIGNED_INT_2_10_10_10_REV;
@@ -1446,17 +1455,29 @@ void TextureStorage::_update_render_target(RenderTarget *rt) {
// color
glGenTextures(1, &rt->color);
- glBindTexture(GL_TEXTURE_2D, rt->color);
-
- glTexImage2D(GL_TEXTURE_2D, 0, rt->color_internal_format, rt->size.x, rt->size.y, 0, rt->color_format, rt->color_type, nullptr);
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ if (rt->view_count > 1 && config->multiview_supported) {
+ glBindTexture(GL_TEXTURE_2D_ARRAY, rt->color);
+ glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, rt->color_internal_format, rt->size.x, rt->size.y, rt->view_count, 0, rt->color_format, rt->color_type, nullptr);
+
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ } else {
+ glBindTexture(GL_TEXTURE_2D, rt->color);
+ glTexImage2D(GL_TEXTURE_2D, 0, rt->color_internal_format, rt->size.x, rt->size.y, 0, rt->color_format, rt->color_type, nullptr);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ }
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color, 0);
+ if (rt->view_count > 1 && config->multiview_supported) {
+ glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, rt->color, 0, 0, rt->view_count);
+ } else {
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color, 0);
+ }
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
@@ -1475,8 +1496,15 @@ void TextureStorage::_update_render_target(RenderTarget *rt) {
texture->format = rt->image_format;
texture->real_format = rt->image_format;
- texture->type = Texture::TYPE_2D;
- texture->target = GL_TEXTURE_2D;
+ if (rt->view_count > 1 && config->multiview_supported) {
+ texture->type = Texture::TYPE_LAYERED;
+ texture->target = GL_TEXTURE_2D_ARRAY;
+ texture->layers = rt->view_count;
+ } else {
+ texture->type = Texture::TYPE_2D;
+ texture->target = GL_TEXTURE_2D;
+ texture->layers = 1;
+ }
texture->gl_format_cache = rt->color_format;
texture->gl_type_cache = GL_UNSIGNED_BYTE;
texture->gl_internal_format_cache = rt->color_internal_format;
@@ -1619,13 +1647,14 @@ void TextureStorage::render_target_set_size(RID p_render_target, int p_width, in
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND(!rt);
- if (p_width == rt->size.x && p_height == rt->size.y) {
+ if (p_width == rt->size.x && p_height == rt->size.y && p_view_count == rt->view_count) {
return;
}
_clear_render_target(rt);
rt->size = Size2i(p_width, p_height);
+ rt->view_count = p_view_count;
_update_render_target(rt);
}
diff --git a/drivers/gles3/storage/texture_storage.h b/drivers/gles3/storage/texture_storage.h
index 39a74236e5..dbe39428ac 100644
--- a/drivers/gles3/storage/texture_storage.h
+++ b/drivers/gles3/storage/texture_storage.h
@@ -324,6 +324,7 @@ private:
struct RenderTarget {
Point2i position = Point2i(0, 0);
Size2i size = Size2i(0, 0);
+ uint32_t view_count = 1;
int mipmap_count = 1;
RID self;
GLuint fbo = 0;
diff --git a/drivers/gles3/storage/utilities.cpp b/drivers/gles3/storage/utilities.cpp
index 6e91f38050..0a04f0d4d0 100644
--- a/drivers/gles3/storage/utilities.cpp
+++ b/drivers/gles3/storage/utilities.cpp
@@ -356,4 +356,13 @@ String Utilities::get_video_adapter_api_version() const {
return (const char *)glGetString(GL_VERSION);
}
+Size2i Utilities::get_maximum_viewport_size() const {
+ Config *config = Config::get_singleton();
+ if (!config) {
+ return Size2i();
+ }
+
+ return Size2i(config->max_viewport_size, config->max_viewport_size);
+}
+
#endif // GLES3_ENABLED
diff --git a/drivers/gles3/storage/utilities.h b/drivers/gles3/storage/utilities.h
index e054f2f816..936ac35cc9 100644
--- a/drivers/gles3/storage/utilities.h
+++ b/drivers/gles3/storage/utilities.h
@@ -150,6 +150,8 @@ public:
virtual String get_video_adapter_vendor() const override;
virtual RenderingDevice::DeviceType get_video_adapter_type() const override;
virtual String get_video_adapter_api_version() const override;
+
+ virtual Size2i get_maximum_viewport_size() const override;
};
} // namespace GLES3
diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp
index 72c9a80a94..de29363556 100644
--- a/drivers/vulkan/rendering_device_vulkan.cpp
+++ b/drivers/vulkan/rendering_device_vulkan.cpp
@@ -9686,6 +9686,10 @@ uint64_t RenderingDeviceVulkan::limit_get(Limit p_limit) const {
return limits.maxComputeWorkGroupSize[1];
case LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_Z:
return limits.maxComputeWorkGroupSize[2];
+ case LIMIT_MAX_VIEWPORT_DIMENSIONS_X:
+ return limits.maxViewportDimensions[0];
+ case LIMIT_MAX_VIEWPORT_DIMENSIONS_Y:
+ return limits.maxViewportDimensions[1];
case LIMIT_SUBGROUP_SIZE: {
VulkanContext::SubgroupCapabilities subgroup_capabilities = context->get_subgroup_capabilities();
return subgroup_capabilities.size;
diff --git a/drivers/vulkan/vulkan_context.cpp b/drivers/vulkan/vulkan_context.cpp
index 688efa42e1..9ee5a67471 100644
--- a/drivers/vulkan/vulkan_context.cpp
+++ b/drivers/vulkan/vulkan_context.cpp
@@ -717,9 +717,12 @@ Error VulkanContext::_check_capabilities() {
VkPhysicalDeviceProperties2 physicalDeviceProperties{};
void *nextptr = nullptr;
- subgroupProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES;
- subgroupProperties.pNext = nextptr;
- nextptr = &subgroupProperties;
+ if (!(vulkan_major == 1 && vulkan_minor == 0)) {
+ subgroupProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES;
+ subgroupProperties.pNext = nextptr;
+
+ nextptr = &subgroupProperties;
+ }
if (multiview_capabilities.is_supported) {
multiviewProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES;