Browse Source

Make screen texture and depth texture work in Multiview

Bastiaan Olij 2 years ago
parent
commit
85c478e170

+ 1 - 1
drivers/gles3/shader_gles3.cpp

@@ -192,7 +192,7 @@ void ShaderGLES3::_build_variant_code(StringBuilder &builder, uint32_t p_variant
 	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 ViewIndex uint(0)\n");
 	builder.append("#define MAX_VIEWS 1\n");
 	builder.append("#endif\n");
 

+ 10 - 0
drivers/gles3/shaders/scene.glsl

@@ -565,9 +565,15 @@ uniform highp samplerCubeShadow positional_shadow; // texunit:-4
 #ifdef USE_MULTIVIEW
 uniform highp sampler2DArray depth_buffer; // texunit:-6
 uniform highp sampler2DArray color_buffer; // texunit:-5
+vec3 multiview_uv(vec2 uv) {
+	return vec3(uv, ViewIndex);
+}
 #else
 uniform highp sampler2D depth_buffer; // texunit:-6
 uniform highp sampler2D color_buffer; // texunit:-5
+vec2 multiview_uv(vec2 uv) {
+	return uv;
+}
 #endif
 
 uniform highp mat4 world_transform;
@@ -924,8 +930,12 @@ void main() {
 	vec3 vertex = vertex_interp;
 #ifdef USE_MULTIVIEW
 	vec3 view = -normalize(vertex_interp - multiview_data.eye_offset[ViewIndex].xyz);
+	mat4 projection_matrix = multiview_data.projection_matrix_view[ViewIndex];
+	mat4 inv_projection_matrix = multiview_data.inv_projection_matrix_view[ViewIndex];
 #else
 	vec3 view = -normalize(vertex_interp);
+	mat4 projection_matrix = scene_data.projection_matrix;
+	mat4 inv_projection_matrix = scene_data.inv_projection_matrix;
 #endif
 	highp mat4 model_matrix = world_transform;
 	vec3 albedo = vec3(1.0);

+ 4 - 2
drivers/gles3/storage/material_storage.cpp

@@ -1635,8 +1635,8 @@ MaterialStorage::MaterialStorage() {
 		actions.renames["NODE_POSITION_VIEW"] = "(model_matrix * scene_data.view_matrix)[3].xyz";
 
 		actions.renames["VIEW_INDEX"] = "ViewIndex";
-		actions.renames["VIEW_MONO_LEFT"] = "0";
-		actions.renames["VIEW_RIGHT"] = "1";
+		actions.renames["VIEW_MONO_LEFT"] = "uint(0)";
+		actions.renames["VIEW_RIGHT"] = "uint(1)";
 
 		//for light
 		actions.renames["VIEW"] = "view";
@@ -1718,6 +1718,8 @@ MaterialStorage::MaterialStorage() {
 		actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
 		actions.default_repeat = ShaderLanguage::REPEAT_ENABLE;
 
+		actions.check_multiview_samplers = true;
+
 		shaders.compiler_scene.initialize(actions);
 	}
 

+ 2 - 0
servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp

@@ -717,6 +717,8 @@ void SceneShaderForwardClustered::init(const String p_defines) {
 		actions.global_buffer_array_variable = "global_shader_uniforms.data";
 		actions.instance_uniform_index_variable = "instances.data[instance_index_interp].instance_uniforms_ofs";
 
+		actions.check_multiview_samplers = true; // make sure we check sampling multiview textures
+
 		compiler.initialize(actions);
 	}
 

+ 1 - 0
servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp

@@ -609,6 +609,7 @@ void SceneShaderForwardMobile::init(const String p_defines) {
 		actions.instance_uniform_index_variable = "draw_call.instance_uniforms_ofs";
 
 		actions.apply_luminance_multiplier = true; // apply luminance multiplier to screen texture
+		actions.check_multiview_samplers = true; // make sure we check sampling multiview textures
 
 		compiler.initialize(actions);
 	}

+ 10 - 0
servers/rendering/renderer_rd/renderer_scene_render_rd.cpp

@@ -253,6 +253,11 @@ void RendererSceneRenderRD::_render_buffers_copy_screen_texture(const RenderData
 	Ref<RenderSceneBuffersRD> rb = p_render_data->render_buffers;
 	ERR_FAIL_COND(rb.is_null());
 
+	if (!rb->has_internal_texture()) {
+		// We're likely rendering reflection probes where we can't use our backbuffers.
+		return;
+	}
+
 	RD::get_singleton()->draw_command_begin_label("Copy screen texture");
 
 	rb->allocate_blur_textures();
@@ -292,6 +297,11 @@ void RendererSceneRenderRD::_render_buffers_copy_depth_texture(const RenderDataR
 	Ref<RenderSceneBuffersRD> rb = p_render_data->render_buffers;
 	ERR_FAIL_COND(rb.is_null());
 
+	if (!rb->has_depth_texture()) {
+		// We're likely rendering reflection probes where we can't use our backbuffers.
+		return;
+	}
+
 	RD::get_singleton()->draw_command_begin_label("Copy depth texture");
 
 	// note, this only creates our back depth texture if we haven't already created it.

+ 4 - 4
servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl

@@ -118,13 +118,13 @@ layout(location = 10) out flat uint instance_index_interp;
 // !BAS! This needs to become an input once we implement our fallback!
 #define ViewIndex 0
 #endif // has_VK_KHR_multiview
-vec3 normal_roughness_uv(vec2 uv) {
+vec3 multiview_uv(vec2 uv) {
 	return vec3(uv, ViewIndex);
 }
 #else // USE_MULTIVIEW
 // Set to zero, not supported in non stereo
 #define ViewIndex 0
-vec2 normal_roughness_uv(vec2 uv) {
+vec2 multiview_uv(vec2 uv) {
 	return uv;
 }
 #endif //USE_MULTIVIEW
@@ -550,13 +550,13 @@ layout(location = 10) in flat uint instance_index_interp;
 // !BAS! This needs to become an input once we implement our fallback!
 #define ViewIndex 0
 #endif // has_VK_KHR_multiview
-vec3 normal_roughness_uv(vec2 uv) {
+vec3 multiview_uv(vec2 uv) {
 	return vec3(uv, ViewIndex);
 }
 #else // USE_MULTIVIEW
 // Set to zero, not supported in non stereo
 #define ViewIndex 0
-vec2 normal_roughness_uv(vec2 uv) {
+vec2 multiview_uv(vec2 uv) {
 	return uv;
 }
 #endif //USE_MULTIVIEW

+ 4 - 3
servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl

@@ -271,15 +271,16 @@ layout(r32ui, set = 1, binding = 13) uniform restrict uimage3D geom_facing_grid;
 #define multiviewSampler sampler2D
 #else
 
-layout(set = 1, binding = 10) uniform texture2D depth_buffer;
-layout(set = 1, binding = 11) uniform texture2D color_buffer;
-
 #ifdef USE_MULTIVIEW
+layout(set = 1, binding = 10) uniform texture2DArray depth_buffer;
+layout(set = 1, binding = 11) uniform texture2DArray color_buffer;
 layout(set = 1, binding = 12) uniform texture2DArray normal_roughness_buffer;
 layout(set = 1, binding = 14) uniform texture2DArray ambient_buffer;
 layout(set = 1, binding = 15) uniform texture2DArray reflection_buffer;
 #define multiviewSampler sampler2DArray
 #else // USE_MULTIVIEW
+layout(set = 1, binding = 10) uniform texture2D depth_buffer;
+layout(set = 1, binding = 11) uniform texture2D color_buffer;
 layout(set = 1, binding = 12) uniform texture2D normal_roughness_buffer;
 layout(set = 1, binding = 14) uniform texture2D ambient_buffer;
 layout(set = 1, binding = 15) uniform texture2D reflection_buffer;

+ 12 - 0
servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl

@@ -112,9 +112,15 @@ layout(location = 9) out highp float dp_clip;
 // !BAS! This needs to become an input once we implement our fallback!
 #define ViewIndex 0
 #endif
+vec3 multiview_uv(vec2 uv) {
+	return vec3(uv, ViewIndex);
+}
 #else
 // Set to zero, not supported in non stereo
 #define ViewIndex 0
+vec2 multiview_uv(vec2 uv) {
+	return uv;
+}
 #endif //USE_MULTIVIEW
 
 invariant gl_Position;
@@ -523,9 +529,15 @@ layout(location = 9) highp in float dp_clip;
 // !BAS! This needs to become an input once we implement our fallback!
 #define ViewIndex 0
 #endif
+vec3 multiview_uv(vec2 uv) {
+	return vec3(uv, ViewIndex);
+}
 #else
 // Set to zero, not supported in non stereo
 #define ViewIndex 0
+vec2 multiview_uv(vec2 uv) {
+	return uv;
+}
 #endif //USE_MULTIVIEW
 
 //defines to keep compatibility with vertex

+ 7 - 0
servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl

@@ -154,8 +154,15 @@ layout(set = 1, binding = 5) uniform highp texture2D directional_shadow_atlas;
 // this needs to change to providing just the lightmap we're using..
 layout(set = 1, binding = 6) uniform texture2DArray lightmap_textures[MAX_LIGHTMAP_TEXTURES];
 
+#ifdef USE_MULTIVIEW
+layout(set = 1, binding = 9) uniform highp texture2DArray depth_buffer;
+layout(set = 1, binding = 10) uniform mediump texture2DArray color_buffer;
+#define multiviewSampler sampler2DArray
+#else
 layout(set = 1, binding = 9) uniform highp texture2D depth_buffer;
 layout(set = 1, binding = 10) uniform mediump texture2D color_buffer;
+#define multiviewSampler sampler2D
+#endif // USE_MULTIVIEW
 
 /* Set 2 Skeleton & Instancing (can change per item) */
 

+ 0 - 1
servers/rendering/renderer_rd/storage_rd/light_storage.cpp

@@ -1464,7 +1464,6 @@ bool LightStorage::reflection_probe_instance_begin_render(RID p_instance, RID p_
 		fb.push_back(atlas->depth_buffer);
 		atlas->depth_fb = RD::get_singleton()->framebuffer_create(fb);
 
-		atlas->render_buffers->cleanup();
 		atlas->render_buffers->configure_for_reflections(Size2i(atlas->size, atlas->size));
 	}
 

+ 10 - 0
servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp

@@ -490,6 +490,16 @@ Ref<RenderBufferCustomDataRD> RenderSceneBuffersRD::get_custom_data(const String
 
 // Depth texture
 
+bool RenderSceneBuffersRD::has_depth_texture() {
+	RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+	RID depth = texture_storage->render_target_get_override_depth(render_target);
+	if (depth.is_valid()) {
+		return true;
+	} else {
+		return has_texture(RB_SCOPE_BUFFERS, RB_TEX_DEPTH);
+	}
+}
+
 RID RenderSceneBuffersRD::get_depth_texture() {
 	RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
 	RID depth = texture_storage->render_target_get_override_depth(render_target);

+ 4 - 0
servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h

@@ -185,6 +185,9 @@ public:
 
 	// For our internal textures we provide some easy access methods.
 
+	_FORCE_INLINE_ bool has_internal_texture() const {
+		return has_texture(RB_SCOPE_BUFFERS, RB_TEX_COLOR);
+	}
 	_FORCE_INLINE_ RID get_internal_texture() const {
 		return get_texture(RB_SCOPE_BUFFERS, RB_TEX_COLOR);
 	}
@@ -192,6 +195,7 @@ public:
 		return get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_COLOR, p_layer, 0);
 	}
 
+	bool has_depth_texture();
 	RID get_depth_texture();
 	RID get_depth_texture(const uint32_t p_layer);
 

+ 33 - 12
servers/rendering/shader_compiler.cpp

@@ -1173,9 +1173,10 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
 
 					code += "(";
 
-					// if normal roughness texture is used, we will add logic to automatically switch between
+					// if color backbuffer, depth backbuffer or normal roughness texture is used,
+					// we will add logic to automatically switch between
 					// sampler2D and sampler2D array and vec2 UV and vec3 UV.
-					bool normal_roughness_texture_used = false;
+					bool multiview_uv_needed = false;
 
 					for (int i = 1; i < onode->arguments.size(); i++) {
 						if (i > 1) {
@@ -1220,8 +1221,8 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
 						}
 
 						String node_code = _dump_node_code(onode->arguments[i], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
-						if (!RS::get_singleton()->is_low_end() && is_texture_func && i == 1) {
-							//need to map from texture to sampler in order to sample when using Vulkan GLSL
+						if (is_texture_func && i == 1) {
+							// If we're doing a texture lookup we need to check our texture argument
 							StringName texture_uniform;
 							bool correct_texture_uniform = false;
 
@@ -1240,8 +1241,10 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
 									break;
 							}
 
-							if (correct_texture_uniform) {
+							if (correct_texture_uniform && !RS::get_singleton()->is_low_end()) {
+								// Need to map from texture to sampler in order to sample when using Vulkan GLSL.
 								String sampler_name;
+								bool is_depth_texture = false;
 								bool is_normal_roughness_texture = false;
 
 								if (actions.custom_samplers.has(texture_uniform)) {
@@ -1251,6 +1254,8 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
 										const ShaderLanguage::ShaderNode::Uniform &u = shader->uniforms[texture_uniform];
 										if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE) {
 											is_screen_texture = true;
+										} else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
+											is_depth_texture = true;
 										} else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE) {
 											is_normal_roughness_texture = true;
 										}
@@ -1281,23 +1286,39 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
 								}
 
 								String data_type_name = "";
-								if (is_normal_roughness_texture) {
+								if (actions.check_multiview_samplers && (is_screen_texture || is_depth_texture || is_normal_roughness_texture)) {
 									data_type_name = "multiviewSampler";
-									normal_roughness_texture_used = true;
+									multiview_uv_needed = true;
 								} else {
 									data_type_name = ShaderLanguage::get_datatype_name(onode->arguments[i]->get_datatype());
 								}
 
 								code += data_type_name + "(" + node_code + ", " + sampler_name + ")";
+							} else if (actions.check_multiview_samplers && correct_texture_uniform && RS::get_singleton()->is_low_end()) {
+								// Texture function on low end hardware (i.e. OpenGL).
+								// We just need to know if the texture supports multiview.
+
+								if (shader->uniforms.has(texture_uniform)) {
+									const ShaderLanguage::ShaderNode::Uniform &u = shader->uniforms[texture_uniform];
+									if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE) {
+										multiview_uv_needed = true;
+									} else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
+										multiview_uv_needed = true;
+									} else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE) {
+										multiview_uv_needed = true;
+									}
+								}
+
+								code += node_code;
 							} else {
 								code += node_code;
 							}
-						} else {
-							if (normal_roughness_texture_used && i == 2) {
-								// UV coordinate after using normal roughness texture.
-								node_code = "normal_roughness_uv(" + node_code + ".xy)";
-							}
+						} else if (multiview_uv_needed && i == 2) {
+							// UV coordinate after using color, depth or normal roughness texture.
+							node_code = "multiview_uv(" + node_code + ".xy)";
 
+							code += node_code;
+						} else {
 							code += node_code;
 						}
 					}

+ 1 - 0
servers/rendering/shader_compiler.h

@@ -101,6 +101,7 @@ public:
 		String instance_uniform_index_variable;
 		uint32_t base_varying_index = 0;
 		bool apply_luminance_multiplier = false;
+		bool check_multiview_samplers = false;
 	};
 
 private: