Browse Source

Merge pull request #46781 from BastiaanOlij/gdn_set_interface

Add set_interface for access by GDNative
Rémi Verschelde 4 years ago
parent
commit
acbd1e8b02

+ 2 - 1
drivers/dummy/rasterizer_dummy.h

@@ -705,7 +705,8 @@ public:
 	void render_target_set_position(RID p_render_target, int p_x, int p_y) {}
 	void render_target_set_size(RID p_render_target, int p_width, int p_height) {}
 	RID render_target_get_texture(RID p_render_target) const { return RID(); }
-	void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) {}
+	uint32_t render_target_get_depth_texture_id(RID p_render_target) const { return 0; }
+	void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id, unsigned int p_depth_id) {}
 	void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) {}
 	bool render_target_was_used(RID p_render_target) { return false; }
 	void render_target_clear_used(RID p_render_target) {}

+ 47 - 3
drivers/gles2/rasterizer_storage_gles2.cpp

@@ -5173,7 +5173,14 @@ void RasterizerStorageGLES2::_render_target_clear(RenderTarget *rt) {
 		texture_owner.free(rt->external.texture);
 		memdelete(t);
 
+		if (rt->external.depth != 0 && rt->external.depth_owned) {
+			glDeleteRenderbuffers(1, &rt->external.depth);
+		}
+
 		rt->external.fbo = 0;
+		rt->external.color = 0;
+		rt->external.depth = 0;
+		rt->external.depth_owned = false;
 	}
 
 	if (rt->depth) {
@@ -5298,7 +5305,19 @@ RID RasterizerStorageGLES2::render_target_get_texture(RID p_render_target) const
 	}
 }
 
-void RasterizerStorageGLES2::render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) {
+uint32_t RasterizerStorageGLES2::render_target_get_depth_texture_id(RID p_render_target) const {
+
+	RenderTarget *rt = render_target_owner.getornull(p_render_target);
+	ERR_FAIL_COND_V(!rt, 0);
+
+	if (rt->external.depth == 0) {
+		return rt->depth;
+	} else {
+		return rt->external.depth;
+	}
+}
+
+void RasterizerStorageGLES2::render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id, unsigned int p_depth_id) {
 	RenderTarget *rt = render_target_owner.getornull(p_render_target);
 	ERR_FAIL_COND(!rt);
 
@@ -5308,7 +5327,7 @@ void RasterizerStorageGLES2::render_target_set_external_texture(RID p_render_tar
 			glDeleteFramebuffers(1, &rt->external.fbo);
 
 			// and this
-			if (rt->external.depth != 0) {
+			if (rt->external.depth != 0 && rt->external.depth_owned) {
 				glDeleteRenderbuffers(1, &rt->external.depth);
 			}
 
@@ -5388,15 +5407,31 @@ void RasterizerStorageGLES2::render_target_set_external_texture(RID p_render_tar
 			// On any other hardware these two modes are ignored and we do not have any MSAA,
 			// the normal MSAA modes need to be used to enable our two pass approach
 
+			// If we created a depth buffer before and we're now passed one, we need to clear it out
+			if (rt->external.depth != 0 && rt->external.depth_owned && p_depth_id != 0) {
+				glDeleteRenderbuffers(1, &rt->external.depth);
+				rt->external.depth_owned = false;
+				rt->external.depth = 0;
+			}
+
+			if (!rt->external.depth_owned) {
+				rt->external.depth = p_depth_id;
+			}
+
 			static const int msaa_value[] = { 2, 4 };
 			int msaa = msaa_value[rt->msaa - VS::VIEWPORT_MSAA_EXT_2X];
 
 			if (rt->external.depth == 0) {
+				rt->external.depth_owned = true;
+
 				// create a multisample depth buffer, we're not reusing Godots because Godot's didn't get created..
 				glGenRenderbuffers(1, &rt->external.depth);
 				glBindRenderbuffer(GL_RENDERBUFFER, rt->external.depth);
 				glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, config.depth_buffer_internalformat, rt->width, rt->height);
 				glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->external.depth);
+			} else if (!rt->external.depth_owned) {
+				// we make an exception here, external plugin MUST make sure this is a proper multisample render buffer!
+				glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->external.depth);
 			}
 
 			// and set our external texture as the texture...
@@ -5405,11 +5440,20 @@ void RasterizerStorageGLES2::render_target_set_external_texture(RID p_render_tar
 		} else
 #endif
 		{
+			// if MSAA as on before, clear our render buffer
+			if (rt->external.depth != 0 && rt->external.depth_owned) {
+				glDeleteRenderbuffers(1, &rt->external.depth);
+			}
+			rt->external.depth_owned = false;
+			rt->external.depth = p_depth_id;
+
 			// set our texture as the destination for our framebuffer
 			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, p_texture_id, 0);
 
 			// seeing we're rendering into this directly, better also use our depth buffer, just use our existing one :)
-			if (config.support_depth_texture) {
+			if (rt->external.depth != 0) {
+				glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rt->external.depth, 0);
+			} else if (config.support_depth_texture) {
 				glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rt->depth, 0);
 			} else {
 				glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth);

+ 5 - 2
drivers/gles2/rasterizer_storage_gles2.h

@@ -1231,12 +1231,14 @@ public:
 			GLuint fbo;
 			GLuint color;
 			GLuint depth;
+			bool depth_owned;
 			RID texture;
 
 			External() :
 					fbo(0),
 					color(0),
-					depth(0) {
+					depth(0),
+					depth_owned(false) {
 			}
 		} external;
 
@@ -1289,7 +1291,8 @@ public:
 	virtual void render_target_set_position(RID p_render_target, int p_x, int p_y);
 	virtual void render_target_set_size(RID p_render_target, int p_width, int p_height);
 	virtual RID render_target_get_texture(RID p_render_target) const;
-	virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id);
+	virtual uint32_t render_target_get_depth_texture_id(RID p_render_target) const;
+	virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id, unsigned int p_depth_id);
 
 	virtual void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value);
 	virtual bool render_target_was_used(RID p_render_target);

+ 54 - 6
drivers/gles3/rasterizer_storage_gles3.cpp

@@ -7197,6 +7197,8 @@ void RasterizerStorageGLES3::_render_target_clear(RenderTarget *rt) {
 		memdelete(t);
 
 		rt->external.fbo = 0;
+		rt->external.color = 0;
+		rt->external.depth = 0;
 	}
 
 	Texture *tex = texture_owner.get(rt->texture);
@@ -7282,8 +7284,14 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) {
 		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
 		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 
-		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
-				GL_TEXTURE_2D, rt->depth, 0);
+		if (rt->external.depth == 0) {
+			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+					GL_TEXTURE_2D, rt->depth, 0);
+		} else {
+			// Use our external depth texture instead.
+			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+					GL_TEXTURE_2D, rt->external.depth, 0);
+		}
 
 		glGenTextures(1, &rt->color);
 		glBindTexture(GL_TEXTURE_2D, rt->color);
@@ -7665,12 +7673,31 @@ RID RasterizerStorageGLES3::render_target_get_texture(RID p_render_target) const
 	}
 }
 
-void RasterizerStorageGLES3::render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) {
+uint32_t RasterizerStorageGLES3::render_target_get_depth_texture_id(RID p_render_target) const {
+
+	RenderTarget *rt = render_target_owner.getornull(p_render_target);
+	ERR_FAIL_COND_V(!rt, 0);
+
+	if (rt->external.depth == 0) {
+		return rt->depth;
+	} else {
+		return rt->external.depth;
+	}
+}
+
+void RasterizerStorageGLES3::render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id, unsigned int p_depth_id) {
 	RenderTarget *rt = render_target_owner.getornull(p_render_target);
 	ERR_FAIL_COND(!rt);
 
 	if (p_texture_id == 0) {
 		if (rt->external.fbo != 0) {
+			// return to our original depth buffer
+			if (rt->external.depth != 0 && rt->fbo != 0) {
+				glBindFramebuffer(GL_FRAMEBUFFER, rt->fbo);
+				glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rt->depth, 0);
+				glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo);
+			}
+
 			// free this
 			glDeleteFramebuffers(1, &rt->external.fbo);
 
@@ -7685,6 +7712,8 @@ void RasterizerStorageGLES3::render_target_set_external_texture(RID p_render_tar
 			memdelete(t);
 
 			rt->external.fbo = 0;
+			rt->external.color = 0;
+			rt->external.depth = 0;
 		}
 	} else {
 		Texture *t;
@@ -7729,6 +7758,7 @@ void RasterizerStorageGLES3::render_target_set_external_texture(RID p_render_tar
 
 		// set our texture
 		t->tex_id = p_texture_id;
+		rt->external.color = p_texture_id;
 
 		// size shouldn't be different
 		t->width = rt->width;
@@ -7741,14 +7771,32 @@ void RasterizerStorageGLES3::render_target_set_external_texture(RID p_render_tar
 		// set our texture as the destination for our framebuffer
 		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, p_texture_id, 0);
 
-		// check status and unbind
+		// check status
 		GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
-		glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo);
-
 		if (status != GL_FRAMEBUFFER_COMPLETE) {
 			printf("framebuffer fail, status: %x\n", status);
 		}
 
+		// Copy our depth texture id,
+		// if it's 0 then we don't use it,
+		// else we use it instead of our normal depth buffer
+		rt->external.depth = p_depth_id;
+
+		if (rt->external.depth != 0 && rt->fbo != 0) {
+			// Use our external depth texture instead.
+			glBindFramebuffer(GL_FRAMEBUFFER, rt->fbo);
+			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rt->external.depth, 0);
+
+			// check status
+			GLenum status2 = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+			if (status2 != GL_FRAMEBUFFER_COMPLETE) {
+				printf("framebuffer fail, status: %x\n", status2);
+			}
+		}
+
+		// and unbind
+		glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo);
+
 		ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE);
 	}
 }

+ 8 - 2
drivers/gles3/rasterizer_storage_gles3.h

@@ -1401,10 +1401,15 @@ public:
 		// External FBO to render our final result to (mostly used for ARVR)
 		struct External {
 			GLuint fbo;
+			GLuint color;
+			GLuint depth;
 			RID texture;
 
 			External() :
-					fbo(0) {}
+					fbo(0),
+					color(0),
+					depth(0) {
+			}
 		} external;
 
 		uint64_t last_exposure_tick;
@@ -1451,7 +1456,8 @@ public:
 	virtual void render_target_set_position(RID p_render_target, int p_x, int p_y);
 	virtual void render_target_set_size(RID p_render_target, int p_width, int p_height);
 	virtual RID render_target_get_texture(RID p_render_target) const;
-	virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id);
+	virtual uint32_t render_target_get_depth_texture_id(RID p_render_target) const;
+	virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id, unsigned int p_depth_id);
 
 	virtual void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value);
 	virtual bool render_target_was_used(RID p_render_target);

+ 28 - 0
modules/gdnative/arvr/arvr_interface_gdnative.cpp

@@ -216,6 +216,17 @@ unsigned int ARVRInterfaceGDNative::get_external_texture_for_eye(ARVRInterface::
 	}
 }
 
+unsigned int ARVRInterfaceGDNative::get_external_depth_for_eye(ARVRInterface::Eyes p_eye) {
+
+	ERR_FAIL_COND_V(interface == NULL, 0);
+
+	if ((interface->version.major > 1) || ((interface->version.major) == 1 && (interface->version.minor >= 2))) {
+		return (unsigned int)interface->get_external_depth_for_eye(data, (godot_int)p_eye);
+	} else {
+		return 0;
+	}
+}
+
 void ARVRInterfaceGDNative::commit_for_eye(ARVRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect) {
 
 	ERR_FAIL_COND(interface == NULL);
@@ -425,4 +436,21 @@ godot_real GDAPI godot_arvr_get_controller_rumble(godot_int p_controller_id) {
 
 	return 0.0;
 }
+
+void GDAPI godot_arvr_set_interface(godot_object *p_arvr_interface, const godot_arvr_interface_gdnative *p_gdn_interface) {
+	// If our major version is 0 or bigger then 10, we're likely looking at our constructor pointer from an older plugin
+	ERR_FAIL_COND_MSG((p_gdn_interface->version.major == 0) || (p_gdn_interface->version.major > 10), "GDNative ARVR interfaces build for Godot 3.0 are not supported.");
+
+	ARVRInterfaceGDNative *interface = (ARVRInterfaceGDNative *)p_arvr_interface;
+	interface->set_interface((const godot_arvr_interface_gdnative *)p_gdn_interface);
+}
+
+godot_int GDAPI godot_arvr_get_depthid(godot_rid *p_render_target) {
+	// We also need to access our depth texture for reprojection.
+	RID *render_target = (RID *)p_render_target;
+
+	uint32_t texid = VSG::storage->render_target_get_depth_texture_id(*render_target);
+
+	return texid;
+}
 }

+ 1 - 0
modules/gdnative/arvr/arvr_interface_gdnative.h

@@ -82,6 +82,7 @@ public:
 	virtual CameraMatrix get_projection_for_eye(ARVRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far);
 
 	virtual unsigned int get_external_texture_for_eye(ARVRInterface::Eyes p_eye);
+	virtual unsigned int get_external_depth_for_eye(ARVRInterface::Eyes p_eye);
 	virtual void commit_for_eye(ARVRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect);
 
 	virtual void process();

+ 26 - 1
modules/gdnative/gdnative_api.json

@@ -6459,7 +6459,32 @@
         "major": 1,
         "minor": 1
       },
-      "next": null,
+      "next": {
+        "name": "arvr",
+        "type": "ARVR",
+        "version": {
+          "major": 1,
+          "minor": 2
+        },
+        "next": null,
+        "api": [
+          {
+            "name": "godot_arvr_set_interface",
+            "return_type": "void",
+            "arguments": [
+              ["godot_object *", "p_arvr_interface"],
+              ["const godot_arvr_interface_gdnative *", "p_gdn_interface"]
+            ]
+          },
+          {
+            "name": "godot_arvr_get_depthid",
+            "return_type": "godot_int",
+            "arguments": [
+              ["godot_rid *", "p_render_target"]
+            ]
+          }
+        ]
+      },
       "api": [
         {
           "name": "godot_arvr_register_interface",

+ 7 - 1
modules/gdnative/include/arvr/godot_arvr.h

@@ -42,7 +42,7 @@ extern "C" {
 
 // Use these to populate version in your plugin
 #define GODOTVR_API_MAJOR 1
-#define GODOTVR_API_MINOR 1
+#define GODOTVR_API_MINOR 2
 
 typedef struct {
 	godot_gdnative_api_version version; /* version of our API */
@@ -65,6 +65,8 @@ typedef struct {
 	godot_int (*get_external_texture_for_eye)(void *, godot_int);
 	void (*notification)(void *, godot_int);
 	godot_int (*get_camera_feed_id)(void *);
+	// only in 1.2 onwards
+	godot_int (*get_external_depth_for_eye)(void *, godot_int);
 } godot_arvr_interface_gdnative;
 
 void GDAPI godot_arvr_register_interface(const godot_arvr_interface_gdnative *p_interface);
@@ -85,6 +87,10 @@ void GDAPI godot_arvr_set_controller_button(godot_int p_controller_id, godot_int
 void GDAPI godot_arvr_set_controller_axis(godot_int p_controller_id, godot_int p_axis, godot_real p_value, godot_bool p_can_be_negative);
 godot_real GDAPI godot_arvr_get_controller_rumble(godot_int p_controller_id);
 
+// ARVR 1.2 functions
+void GDAPI godot_arvr_set_interface(godot_object *p_arvr_interface, const godot_arvr_interface_gdnative *p_gdn_interface);
+godot_int GDAPI godot_arvr_get_depthid(godot_rid *p_render_target);
+
 #ifdef __cplusplus
 }
 #endif

+ 5 - 0
servers/arvr/arvr_interface.cpp

@@ -129,6 +129,11 @@ unsigned int ARVRInterface::get_external_texture_for_eye(ARVRInterface::Eyes p_e
 	return 0;
 };
 
+// optional render to external depth texture which enhances performance on those platforms that require us to submit our end result into special textures.
+unsigned int ARVRInterface::get_external_depth_for_eye(ARVRInterface::Eyes p_eye) {
+	return 0;
+};
+
 /** these will only be implemented on AR interfaces, so we want dummies for VR **/
 bool ARVRInterface::get_anchor_detection_is_enabled() const {
 	return false;

+ 1 - 0
servers/arvr/arvr_interface.h

@@ -110,6 +110,7 @@ public:
 	virtual Transform get_transform_for_eye(ARVRInterface::Eyes p_eye, const Transform &p_cam_transform) = 0; /* get each eyes camera transform, also implement EYE_MONO */
 	virtual CameraMatrix get_projection_for_eye(ARVRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far) = 0; /* get each eyes projection matrix */
 	virtual unsigned int get_external_texture_for_eye(ARVRInterface::Eyes p_eye); /* if applicable return external texture to render to */
+	virtual unsigned int get_external_depth_for_eye(ARVRInterface::Eyes p_eye); /* if applicable return external depth texture to render to */
 	virtual void commit_for_eye(ARVRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect) = 0; /* output the left or right eye */
 
 	virtual void process() = 0;

+ 2 - 1
servers/visual/rasterizer.h

@@ -573,7 +573,8 @@ public:
 	virtual void render_target_set_position(RID p_render_target, int p_x, int p_y) = 0;
 	virtual void render_target_set_size(RID p_render_target, int p_width, int p_height) = 0;
 	virtual RID render_target_get_texture(RID p_render_target) const = 0;
-	virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) = 0;
+	virtual uint32_t render_target_get_depth_texture_id(RID p_render_target) const = 0;
+	virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id, unsigned int p_depth_id) = 0;
 	virtual void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) = 0;
 	virtual bool render_target_was_used(RID p_render_target) = 0;
 	virtual void render_target_clear_used(RID p_render_target) = 0;

+ 3 - 3
servers/visual/visual_server_viewport.cpp

@@ -314,7 +314,7 @@ void VisualServerViewport::draw_viewports() {
 			ARVRInterface::Eyes leftOrMono = arvr_interface->is_stereo() ? ARVRInterface::EYE_LEFT : ARVRInterface::EYE_MONO;
 
 			// check for an external texture destination for our left eye/mono
-			VSG::storage->render_target_set_external_texture(vp->render_target, arvr_interface->get_external_texture_for_eye(leftOrMono));
+			VSG::storage->render_target_set_external_texture(vp->render_target, arvr_interface->get_external_texture_for_eye(leftOrMono), arvr_interface->get_external_depth_for_eye(leftOrMono));
 
 			// set our render target as current
 			VSG::rasterizer->set_current_render_target(vp->render_target);
@@ -326,7 +326,7 @@ void VisualServerViewport::draw_viewports() {
 			// render right eye
 			if (leftOrMono == ARVRInterface::EYE_LEFT) {
 				// check for an external texture destination for our right eye
-				VSG::storage->render_target_set_external_texture(vp->render_target, arvr_interface->get_external_texture_for_eye(ARVRInterface::EYE_RIGHT));
+				VSG::storage->render_target_set_external_texture(vp->render_target, arvr_interface->get_external_texture_for_eye(ARVRInterface::EYE_RIGHT), arvr_interface->get_external_depth_for_eye(ARVRInterface::EYE_RIGHT));
 
 				// commit for eye may have changed the render target
 				VSG::rasterizer->set_current_render_target(vp->render_target);
@@ -338,7 +338,7 @@ void VisualServerViewport::draw_viewports() {
 			// and for our frame timing, mark when we've finished committing our eyes
 			ARVRServer::get_singleton()->_mark_commit();
 		} else {
-			VSG::storage->render_target_set_external_texture(vp->render_target, 0);
+			VSG::storage->render_target_set_external_texture(vp->render_target, 0, 0);
 			VSG::rasterizer->set_current_render_target(vp->render_target);
 
 			VSG::scene_render->set_debug_draw_mode(vp->debug_draw);