diff --git a/doc/classes/XRInterfaceExtension.xml b/doc/classes/XRInterfaceExtension.xml
index 06ef18b534b..5958999037c 100644
--- a/doc/classes/XRInterfaceExtension.xml
+++ b/doc/classes/XRInterfaceExtension.xml
@@ -39,6 +39,18 @@
Returns the capabilities of this interface.
+
+
+
+ Return color texture into which to render (if applicable).
+
+
+
+
+
+ Return depth texture into which to render (if applicable).
+
+
@@ -100,6 +112,12 @@
Returns a [Transform3D] for a given view.
+
+
+
+ Return velocity texture into which to render (if applicable).
+
+
@@ -213,6 +231,16 @@
Blits our render results to screen optionally applying lens distortion. This can only be called while processing [code]_commit_views[/code].
+
+
+
+
+
+
+
+
+
+
@@ -220,5 +248,10 @@
Returns a valid [RID] for a texture to which we should render the current frame if supported by the interface.
+
+
+
+
+
diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp
index 35758377940..3ac923d33c7 100644
--- a/drivers/gles3/rasterizer_gles3.cpp
+++ b/drivers/gles3/rasterizer_gles3.cpp
@@ -280,11 +280,7 @@ void RasterizerGLES3::_blit_render_target_to_screen(RID p_render_target, Display
GLES3::RenderTarget *rt = texture_storage->get_render_target(p_render_target);
ERR_FAIL_COND(!rt);
- if (rt->external.fbo != 0) {
- glBindFramebuffer(GL_READ_FRAMEBUFFER, rt->external.fbo);
- } else {
- glBindFramebuffer(GL_READ_FRAMEBUFFER, rt->fbo);
- }
+ 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.
diff --git a/drivers/gles3/storage/texture_storage.cpp b/drivers/gles3/storage/texture_storage.cpp
index 8ea10539ecd..5950997f9b7 100644
--- a/drivers/gles3/storage/texture_storage.cpp
+++ b/drivers/gles3/storage/texture_storage.cpp
@@ -1343,24 +1343,6 @@ void TextureStorage::_clear_render_target(RenderTarget *rt) {
rt->fbo = 0;
rt->color = 0;
}
- /*
- if (rt->external.fbo != 0) {
- // free this
- glDeleteFramebuffers(1, &rt->external.fbo);
-
- // clean up our texture
- Texture *t = get_texture(rt->external.texture);
- t->alloc_height = 0;
- t->alloc_width = 0;
- t->width = 0;
- t->height = 0;
- t->active = false;
- texture_free(rt->external.texture);
- memdelete(t);
-
- rt->external.fbo = 0;
- }
- */
Texture *tex = get_texture(rt->texture);
tex->alloc_height = 0;
@@ -1412,6 +1394,13 @@ void TextureStorage::render_target_set_position(RID p_render_target, int p_x, in
rt->position = Point2i(p_x, p_y);
}
+Point2i TextureStorage::render_target_get_position(RID p_render_target) const {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, Point2i());
+
+ return rt->position;
+};
+
void TextureStorage::render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) {
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND(!rt);
@@ -1428,9 +1417,9 @@ void TextureStorage::render_target_set_size(RID p_render_target, int p_width, in
}
// TODO: convert to Size2i internally
-Size2i TextureStorage::render_target_get_size(RID p_render_target) {
+Size2i TextureStorage::render_target_get_size(RID p_render_target) const {
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND_V(!rt, Size2());
+ ERR_FAIL_COND_V(!rt, Size2i());
return rt->size;
}
@@ -1439,105 +1428,7 @@ RID TextureStorage::render_target_get_texture(RID p_render_target) {
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND_V(!rt, RID());
- if (rt->external.fbo == 0) {
- return rt->texture;
- } else {
- return rt->external.texture;
- }
-}
-
-void TextureStorage::render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND(!rt);
-
- if (p_texture_id == 0) {
- if (rt->external.fbo != 0) {
- // free this
- glDeleteFramebuffers(1, &rt->external.fbo);
-
- // and this
- if (rt->external.depth != 0) {
- glDeleteRenderbuffers(1, &rt->external.depth);
- }
-
- // clean up our texture
- Texture *t = get_texture(rt->external.texture);
- t->alloc_height = 0;
- t->alloc_width = 0;
- t->width = 0;
- t->height = 0;
- t->active = false;
- texture_free(rt->external.texture);
- //memdelete(t);
-
- rt->external.fbo = 0;
- rt->external.color = 0;
- rt->external.depth = 0;
- }
- } else {
- Texture *t;
-
- if (rt->external.fbo == 0) {
- // create our fbo
- glGenFramebuffers(1, &rt->external.fbo);
- glBindFramebuffer(GL_FRAMEBUFFER, rt->external.fbo);
-
- // allocate a texture
- t = memnew(Texture);
-
- t->type = Texture::TYPE_2D;
- t->width = 0;
- t->height = 0;
- t->alloc_height = 0;
- t->alloc_width = 0;
- t->format = Image::FORMAT_RGBA8;
- t->target = GL_TEXTURE_2D;
- t->gl_format_cache = 0;
- t->gl_internal_format_cache = 0;
- t->gl_type_cache = 0;
- t->total_data_size = 0;
- t->mipmaps = 1;
- t->active = true;
- t->tex_id = 0;
- t->render_target = rt;
- t->is_render_target = true;
-
- //rt->external.texture = make_rid(t);
-
- } else {
- // bind our frame buffer
- glBindFramebuffer(GL_FRAMEBUFFER, rt->external.fbo);
-
- // find our texture
- t = get_texture(rt->external.texture);
- }
-
- // set our texture
- t->tex_id = p_texture_id;
- rt->external.color = p_texture_id;
-
- // size shouldn't be different
- t->width = rt->size.x;
- t->height = rt->size.y;
- t->alloc_height = rt->size.x;
- t->alloc_width = rt->size.y;
-
- // Switch our texture on our frame buffer
- {
- // 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
- GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
- glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);
-
- if (status != GL_FRAMEBUFFER_COMPLETE) {
- WARN_PRINT("framebuffer fail, status: " + get_framebuffer_error(status));
- }
-
- ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE);
- }
+ return rt->texture;
}
void TextureStorage::render_target_set_transparent(RID p_render_target, bool p_transparent) {
@@ -1550,6 +1441,13 @@ void TextureStorage::render_target_set_transparent(RID p_render_target, bool p_t
_update_render_target(rt);
}
+bool TextureStorage::render_target_get_transparent(RID p_render_target) const {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, false);
+
+ return rt->is_transparent;
+}
+
void TextureStorage::render_target_set_direct_to_screen(RID p_render_target, bool p_direct_to_screen) {
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND(!rt);
@@ -1564,7 +1462,14 @@ void TextureStorage::render_target_set_direct_to_screen(RID p_render_target, boo
_update_render_target(rt);
}
-bool TextureStorage::render_target_was_used(RID p_render_target) {
+bool TextureStorage::render_target_get_direct_to_screen(RID p_render_target) const {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, false);
+
+ return rt->direct_to_screen;
+}
+
+bool TextureStorage::render_target_was_used(RID p_render_target) const {
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND_V(!rt, false);
@@ -1591,6 +1496,13 @@ void TextureStorage::render_target_set_msaa(RID p_render_target, RS::ViewportMSA
_update_render_target(rt);
}
+RS::ViewportMSAA TextureStorage::render_target_get_msaa(RID p_render_target) const {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, RS::VIEWPORT_MSAA_DISABLED);
+
+ return rt->msaa;
+}
+
void TextureStorage::render_target_request_clear(RID p_render_target, const Color &p_clear_color) {
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND(!rt);
diff --git a/drivers/gles3/storage/texture_storage.h b/drivers/gles3/storage/texture_storage.h
index 16bf4068459..0d4cd9c7e3e 100644
--- a/drivers/gles3/storage/texture_storage.h
+++ b/drivers/gles3/storage/texture_storage.h
@@ -327,16 +327,6 @@ private:
};
struct RenderTarget {
- struct External {
- GLuint fbo = 0;
- GLuint color = 0;
- GLuint depth = 0;
- RID texture;
-
- External() {
- }
- } external;
-
Point2i position = Point2i(0, 0);
Size2i size = Size2i(0, 0);
int mipmap_count = 1;
@@ -524,17 +514,19 @@ public:
virtual RID render_target_create() override;
virtual void render_target_free(RID p_rid) override;
- virtual void render_target_set_position(RID p_render_target, int p_x, int p_y) override;
- virtual void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) override;
- Size2i render_target_get_size(RID p_render_target);
- virtual RID render_target_get_texture(RID p_render_target) override;
- virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) override;
+ virtual void render_target_set_position(RID p_render_target, int p_x, int p_y) override;
+ virtual Point2i render_target_get_position(RID p_render_target) const override;
+ virtual void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) override;
+ virtual Size2i render_target_get_size(RID p_render_target) const override;
virtual void render_target_set_transparent(RID p_render_target, bool p_is_transparent) override;
+ virtual bool render_target_get_transparent(RID p_render_target) const override;
virtual void render_target_set_direct_to_screen(RID p_render_target, bool p_direct_to_screen) override;
- virtual bool render_target_was_used(RID p_render_target) override;
+ virtual bool render_target_get_direct_to_screen(RID p_render_target) const override;
+ virtual bool render_target_was_used(RID p_render_target) const override;
void render_target_clear_used(RID p_render_target);
virtual void render_target_set_msaa(RID p_render_target, RS::ViewportMSAA p_msaa) override;
+ virtual RS::ViewportMSAA render_target_get_msaa(RID p_render_target) const override;
// new
void render_target_set_as_unused(RID p_render_target) override {
@@ -554,8 +546,20 @@ public:
void render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region, bool p_gen_mipmaps);
void render_target_clear_back_buffer(RID p_render_target, const Rect2i &p_region, const Color &p_color);
void render_target_gen_back_buffer_mipmaps(RID p_render_target, const Rect2i &p_region);
- virtual void render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) override{};
- virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) override{};
+
+ virtual void render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) override {}
+ virtual RS::ViewportVRSMode render_target_get_vrs_mode(RID p_render_target) const override { return RS::VIEWPORT_VRS_DISABLED; }
+ virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) override {}
+ virtual RID render_target_get_vrs_texture(RID p_render_target) const override { return RID(); }
+
+ virtual void render_target_set_override_color(RID p_render_target, RID p_texture) override {}
+ virtual RID render_target_get_override_color(RID p_render_target) const override { return RID(); }
+ virtual void render_target_set_override_depth(RID p_render_target, RID p_texture) override {}
+ virtual RID render_target_get_override_depth(RID p_render_target) const override { return RID(); }
+ virtual void render_target_set_override_velocity(RID p_render_target, RID p_texture) override {}
+ virtual RID render_target_get_override_velocity(RID p_render_target) const override { return RID(); }
+
+ virtual RID render_target_get_texture(RID p_render_target) override;
void bind_framebuffer(GLuint framebuffer) {
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
diff --git a/modules/openxr/SCsub b/modules/openxr/SCsub
index d4469b110b2..5ac167ad98a 100644
--- a/modules/openxr/SCsub
+++ b/modules/openxr/SCsub
@@ -92,6 +92,7 @@ if env["vulkan"]:
env_openxr.add_source_files(module_obj, "extensions/openxr_vulkan_extension.cpp")
env_openxr.add_source_files(module_obj, "extensions/openxr_palm_pose_extension.cpp")
+env_openxr.add_source_files(module_obj, "extensions/openxr_composition_layer_depth_extension.cpp")
env_openxr.add_source_files(module_obj, "extensions/openxr_htc_vive_tracker_extension.cpp")
env_openxr.add_source_files(module_obj, "extensions/openxr_hand_tracking_extension.cpp")
env_openxr.add_source_files(module_obj, "extensions/openxr_fb_passthrough_extension_wrapper.cpp")
diff --git a/modules/openxr/extensions/openxr_composition_layer_depth_extension.cpp b/modules/openxr/extensions/openxr_composition_layer_depth_extension.cpp
new file mode 100644
index 00000000000..0f6aaf8afb9
--- /dev/null
+++ b/modules/openxr/extensions/openxr_composition_layer_depth_extension.cpp
@@ -0,0 +1,58 @@
+/*************************************************************************/
+/* openxr_composition_layer_depth_extension.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "openxr_composition_layer_depth_extension.h"
+
+OpenXRCompositionLayerDepthExtension *OpenXRCompositionLayerDepthExtension::singleton = nullptr;
+
+OpenXRCompositionLayerDepthExtension *OpenXRCompositionLayerDepthExtension::get_singleton() {
+ return singleton;
+}
+
+OpenXRCompositionLayerDepthExtension::OpenXRCompositionLayerDepthExtension(OpenXRAPI *p_openxr_api) :
+ OpenXRExtensionWrapper(p_openxr_api) {
+ singleton = this;
+
+ request_extensions[XR_KHR_COMPOSITION_LAYER_DEPTH_EXTENSION_NAME] = &available;
+}
+
+OpenXRCompositionLayerDepthExtension::~OpenXRCompositionLayerDepthExtension() {
+ singleton = nullptr;
+}
+
+bool OpenXRCompositionLayerDepthExtension::is_available() {
+ return available;
+}
+
+XrCompositionLayerBaseHeader *OpenXRCompositionLayerDepthExtension::get_composition_layer() {
+ // Seems this is all done in our base layer... Just in case this changes...
+
+ return nullptr;
+}
diff --git a/modules/openxr/extensions/openxr_composition_layer_depth_extension.h b/modules/openxr/extensions/openxr_composition_layer_depth_extension.h
new file mode 100644
index 00000000000..9533783d83a
--- /dev/null
+++ b/modules/openxr/extensions/openxr_composition_layer_depth_extension.h
@@ -0,0 +1,53 @@
+/*************************************************************************/
+/* openxr_composition_layer_depth_extension.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef OPENXR_COMPOSITION_LAYER_DEPTH_EXTENSION_H
+#define OPENXR_COMPOSITION_LAYER_DEPTH_EXTENSION_H
+
+#include "openxr_composition_layer_provider.h"
+#include "openxr_extension_wrapper.h"
+
+class OpenXRCompositionLayerDepthExtension : public OpenXRExtensionWrapper, public OpenXRCompositionLayerProvider {
+public:
+ static OpenXRCompositionLayerDepthExtension *get_singleton();
+
+ OpenXRCompositionLayerDepthExtension(OpenXRAPI *p_openxr_api);
+ virtual ~OpenXRCompositionLayerDepthExtension() override;
+
+ bool is_available();
+ virtual XrCompositionLayerBaseHeader *get_composition_layer() override;
+
+private:
+ static OpenXRCompositionLayerDepthExtension *singleton;
+
+ bool available = false;
+};
+
+#endif // OPENXR_COMPOSITION_LAYER_DEPTH_EXTENSION_H
diff --git a/modules/openxr/extensions/openxr_composition_layer_provider.h b/modules/openxr/extensions/openxr_composition_layer_provider.h
index ba51389f7de..a4c4cbe0c60 100644
--- a/modules/openxr/extensions/openxr_composition_layer_provider.h
+++ b/modules/openxr/extensions/openxr_composition_layer_provider.h
@@ -31,6 +31,7 @@
#ifndef OPENXR_COMPOSITION_LAYER_PROVIDER_H
#define OPENXR_COMPOSITION_LAYER_PROVIDER_H
+#include "openxr_extension_wrapper.h"
#include
// Interface for OpenXR extensions that provide a composition layer.
diff --git a/modules/openxr/extensions/openxr_extension_wrapper.h b/modules/openxr/extensions/openxr_extension_wrapper.h
index 623c264e6ed..c417c90d110 100644
--- a/modules/openxr/extensions/openxr_extension_wrapper.h
+++ b/modules/openxr/extensions/openxr_extension_wrapper.h
@@ -100,11 +100,12 @@ public:
class OpenXRGraphicsExtensionWrapper : public OpenXRExtensionWrapper {
public:
virtual void get_usable_swapchain_formats(Vector &p_usable_swap_chains) = 0;
+ virtual void get_usable_depth_formats(Vector &p_usable_swap_chains) = 0;
virtual String get_swapchain_format_name(int64_t p_swapchain_format) const = 0;
virtual bool get_swapchain_image_data(XrSwapchain p_swapchain, int64_t p_swapchain_format, uint32_t p_width, uint32_t p_height, uint32_t p_sample_count, uint32_t p_array_size, void **r_swapchain_graphics_data) = 0;
virtual void cleanup_swapchain_graphics_data(void **p_swapchain_graphics_data) = 0;
virtual bool create_projection_fov(const XrFovf p_fov, double p_z_near, double p_z_far, Projection &r_camera_matrix) = 0;
- virtual bool copy_render_target_to_image(RID p_from_render_target, void *p_swapchain_graphics_data, int p_image_index) = 0;
+ virtual RID get_texture(void *p_swapchain_graphics_data, int p_image_index) = 0;
OpenXRGraphicsExtensionWrapper(OpenXRAPI *p_openxr_api) :
OpenXRExtensionWrapper(p_openxr_api){};
diff --git a/modules/openxr/extensions/openxr_vulkan_extension.cpp b/modules/openxr/extensions/openxr_vulkan_extension.cpp
index f9e771c9342..cc171cc42a6 100644
--- a/modules/openxr/extensions/openxr_vulkan_extension.cpp
+++ b/modules/openxr/extensions/openxr_vulkan_extension.cpp
@@ -228,6 +228,12 @@ void OpenXRVulkanExtension::get_usable_swapchain_formats(Vector &p_usab
p_usable_swap_chains.push_back(VK_FORMAT_B8G8R8A8_UINT);
}
+void OpenXRVulkanExtension::get_usable_depth_formats(Vector &p_usable_swap_chains) {
+ p_usable_swap_chains.push_back(VK_FORMAT_R32_SFLOAT);
+ p_usable_swap_chains.push_back(VK_FORMAT_D24_UNORM_S8_UINT);
+ p_usable_swap_chains.push_back(VK_FORMAT_D32_SFLOAT_S8_UINT);
+}
+
bool OpenXRVulkanExtension::get_swapchain_image_data(XrSwapchain p_swapchain, int64_t p_swapchain_format, uint32_t p_width, uint32_t p_height, uint32_t p_sample_count, uint32_t p_array_size, void **r_swapchain_graphics_data) {
XrSwapchainImageVulkanKHR *images = nullptr;
@@ -271,7 +277,7 @@ bool OpenXRVulkanExtension::get_swapchain_image_data(XrSwapchain p_swapchain, in
RenderingDevice::DataFormat format = RenderingDevice::DATA_FORMAT_R8G8B8A8_SRGB;
RenderingDevice::TextureSamples samples = RenderingDevice::TEXTURE_SAMPLES_1;
- uint64_t usage_flags = RenderingDevice::TEXTURE_USAGE_SAMPLING_BIT | RenderingDevice::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+ uint64_t usage_flags = RenderingDevice::TEXTURE_USAGE_SAMPLING_BIT;
switch (p_swapchain_format) {
case VK_FORMAT_R8G8B8A8_SRGB:
@@ -283,16 +289,32 @@ bool OpenXRVulkanExtension::get_swapchain_image_data(XrSwapchain p_swapchain, in
// will thus do an sRGB -> Linear conversion as expected.
// format = RenderingDevice::DATA_FORMAT_R8G8B8A8_SRGB;
format = RenderingDevice::DATA_FORMAT_R8G8B8A8_UNORM;
+ usage_flags |= RenderingDevice::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
break;
case VK_FORMAT_B8G8R8A8_SRGB:
// format = RenderingDevice::DATA_FORMAT_B8G8R8A8_SRGB;
format = RenderingDevice::DATA_FORMAT_B8G8R8A8_UNORM;
+ usage_flags |= RenderingDevice::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
break;
case VK_FORMAT_R8G8B8A8_UINT:
format = RenderingDevice::DATA_FORMAT_R8G8B8A8_UINT;
+ usage_flags |= RenderingDevice::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
break;
case VK_FORMAT_B8G8R8A8_UINT:
format = RenderingDevice::DATA_FORMAT_B8G8R8A8_UINT;
+ usage_flags |= RenderingDevice::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+ break;
+ case VK_FORMAT_R32_SFLOAT:
+ format = RenderingDevice::DATA_FORMAT_R32_SFLOAT;
+ usage_flags |= RenderingDevice::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
+ break;
+ case VK_FORMAT_D24_UNORM_S8_UINT:
+ format = RenderingDevice::DATA_FORMAT_D24_UNORM_S8_UINT;
+ usage_flags |= RenderingDevice::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
+ break;
+ case VK_FORMAT_D32_SFLOAT_S8_UINT:
+ format = RenderingDevice::DATA_FORMAT_D32_SFLOAT_S8_UINT;
+ usage_flags |= RenderingDevice::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
break;
default:
// continue with our default value
@@ -328,8 +350,7 @@ bool OpenXRVulkanExtension::get_swapchain_image_data(XrSwapchain p_swapchain, in
break;
}
- Vector image_rids;
- Vector framebuffers;
+ Vector texture_rids;
// create Godot texture objects for each entry in our swapchain
for (uint64_t i = 0; i < swapchain_length; i++) {
@@ -344,19 +365,10 @@ bool OpenXRVulkanExtension::get_swapchain_image_data(XrSwapchain p_swapchain, in
1,
p_array_size);
- image_rids.push_back(image_rid);
-
- {
- Vector fb;
- fb.push_back(image_rid);
-
- RID fb_rid = rendering_device->framebuffer_create(fb, RenderingDevice::INVALID_ID, p_array_size);
- framebuffers.push_back(fb_rid);
- }
+ texture_rids.push_back(image_rid);
}
- data->image_rids = image_rids;
- data->framebuffers = framebuffers;
+ data->texture_rids = texture_rids;
memfree(images);
@@ -377,26 +389,12 @@ bool OpenXRVulkanExtension::create_projection_fov(const XrFovf p_fov, double p_z
return true;
}
-bool OpenXRVulkanExtension::copy_render_target_to_image(RID p_from_render_target, void *p_swapchain_graphics_data, int p_image_index) {
+RID OpenXRVulkanExtension::get_texture(void *p_swapchain_graphics_data, int p_image_index) {
SwapchainGraphicsData *data = (SwapchainGraphicsData *)p_swapchain_graphics_data;
- ERR_FAIL_NULL_V(data, false);
- ERR_FAIL_COND_V(p_from_render_target.is_null(), false);
+ ERR_FAIL_NULL_V(data, RID());
- RID source_image = RendererRD::TextureStorage::get_singleton()->render_target_get_rd_texture(p_from_render_target);
- ERR_FAIL_COND_V(source_image.is_null(), false);
-
- RID depth_image; // TODO implement
-
- ERR_FAIL_INDEX_V(p_image_index, data->framebuffers.size(), false);
- RID fb = data->framebuffers[p_image_index];
- ERR_FAIL_COND_V(fb.is_null(), false);
-
- // Our vulkan extension can only be used in conjunction with our vulkan renderer.
- RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton();
- ERR_FAIL_NULL_V(copy_effects, false);
- copy_effects->copy_to_fb_rect(source_image, fb, Rect2i(), false, false, false, false, depth_image, data->is_multiview);
-
- return true;
+ ERR_FAIL_INDEX_V(p_image_index, data->texture_rids.size(), RID());
+ return data->texture_rids[p_image_index];
}
void OpenXRVulkanExtension::cleanup_swapchain_graphics_data(void **p_swapchain_graphics_data) {
@@ -411,17 +409,11 @@ void OpenXRVulkanExtension::cleanup_swapchain_graphics_data(void **p_swapchain_g
RenderingDevice *rendering_device = rendering_server->get_rendering_device();
ERR_FAIL_NULL(rendering_device);
- for (int i = 0; i < data->image_rids.size(); i++) {
+ for (int i = 0; i < data->texture_rids.size(); i++) {
// This should clean up our RIDs and associated texture objects but shouldn't destroy the images, they are owned by our XrSwapchain
- rendering_device->free(data->image_rids[i]);
+ rendering_device->free(data->texture_rids[i]);
}
- data->image_rids.clear();
-
- for (int i = 0; i < data->framebuffers.size(); i++) {
- // This should clean up our RIDs and associated texture objects but shouldn't destroy the images, they are owned by our XrSwapchain
- rendering_device->free(data->framebuffers[i]);
- }
- data->framebuffers.clear();
+ data->texture_rids.clear();
memdelete(data);
*p_swapchain_graphics_data = nullptr;
diff --git a/modules/openxr/extensions/openxr_vulkan_extension.h b/modules/openxr/extensions/openxr_vulkan_extension.h
index d6e9917900e..71abe3b1668 100644
--- a/modules/openxr/extensions/openxr_vulkan_extension.h
+++ b/modules/openxr/extensions/openxr_vulkan_extension.h
@@ -69,11 +69,12 @@ public:
virtual bool create_vulkan_device(const VkDeviceCreateInfo *p_device_create_info, VkDevice *r_device) override;
virtual void get_usable_swapchain_formats(Vector &p_usable_swap_chains) override;
+ virtual void get_usable_depth_formats(Vector &p_usable_swap_chains) override;
virtual String get_swapchain_format_name(int64_t p_swapchain_format) const override;
virtual bool get_swapchain_image_data(XrSwapchain p_swapchain, int64_t p_swapchain_format, uint32_t p_width, uint32_t p_height, uint32_t p_sample_count, uint32_t p_array_size, void **r_swapchain_graphics_data) override;
virtual void cleanup_swapchain_graphics_data(void **p_swapchain_graphics_data) override;
virtual bool create_projection_fov(const XrFovf p_fov, double p_z_near, double p_z_far, Projection &r_camera_matrix) override;
- virtual bool copy_render_target_to_image(RID p_from_render_target, void *p_swapchain_graphics_data, int p_image_index) override;
+ virtual RID get_texture(void *p_swapchain_graphics_data, int p_image_index) override;
private:
static OpenXRVulkanExtension *singleton;
@@ -81,8 +82,7 @@ private:
struct SwapchainGraphicsData {
bool is_multiview;
- Vector image_rids;
- Vector framebuffers;
+ Vector texture_rids;
};
bool check_graphics_api_support(XrVersion p_desired_version);
diff --git a/modules/openxr/openxr_api.cpp b/modules/openxr/openxr_api.cpp
index 16879ac4e5a..8a690727931 100644
--- a/modules/openxr/openxr_api.cpp
+++ b/modules/openxr/openxr_api.cpp
@@ -49,6 +49,7 @@
#include "extensions/openxr_vulkan_extension.h"
#endif
+#include "extensions/openxr_composition_layer_depth_extension.h"
#include "extensions/openxr_fb_passthrough_extension_wrapper.h"
#include "extensions/openxr_hand_tracking_extension.h"
#include "extensions/openxr_htc_vive_tracker_extension.h"
@@ -663,7 +664,7 @@ bool OpenXRAPI::is_swapchain_format_supported(int64_t p_swapchain_format) {
return false;
}
-bool OpenXRAPI::create_main_swapchain() {
+bool OpenXRAPI::create_swapchains() {
ERR_FAIL_NULL_V(graphics_extension, false);
ERR_FAIL_COND_V(session == XR_NULL_HANDLE, false);
@@ -681,34 +682,36 @@ bool OpenXRAPI::create_main_swapchain() {
already rendering the next frame.
Finally an area we need to expand upon is that Foveated rendering is only enabled for the swap chain we create,
- as we render 3D content into internal buffers that are copied into the swapchain, we don't get any of the performance gains
- until such time as we implement VRS.
+ as we render 3D content into internal buffers that are copied into the swapchain, we do now have (basic) VRS support
*/
- // Build a vector with swapchain formats we want to use, from best fit to worst
- Vector usable_swapchain_formats;
- int64_t swapchain_format_to_use = 0;
-
- graphics_extension->get_usable_swapchain_formats(usable_swapchain_formats);
-
- // now find out which one is supported
- for (int i = 0; i < usable_swapchain_formats.size() && swapchain_format_to_use == 0; i++) {
- if (is_swapchain_format_supported(usable_swapchain_formats[i])) {
- swapchain_format_to_use = usable_swapchain_formats[i];
- }
- }
-
- if (swapchain_format_to_use == 0) {
- swapchain_format_to_use = usable_swapchain_formats[0]; // just use the first one and hope for the best...
- print_line("Couldn't find usable swap chain format, using", get_swapchain_format_name(swapchain_format_to_use), "instead.");
- } else {
- print_line("Using swap chain format:", get_swapchain_format_name(swapchain_format_to_use));
- }
-
Size2 recommended_size = get_recommended_target_size();
- if (!create_swapchain(swapchain_format_to_use, recommended_size.width, recommended_size.height, view_configuration_views[0].recommendedSwapchainSampleCount, view_count, swapchain, &swapchain_graphics_data)) {
- return false;
+ // We start with our color swapchain...
+ {
+ // Build a vector with swapchain formats we want to use, from best fit to worst
+ Vector usable_swapchain_formats;
+ int64_t swapchain_format_to_use = 0;
+
+ graphics_extension->get_usable_swapchain_formats(usable_swapchain_formats);
+
+ // now find out which one is supported
+ for (int i = 0; i < usable_swapchain_formats.size() && swapchain_format_to_use == 0; i++) {
+ if (is_swapchain_format_supported(usable_swapchain_formats[i])) {
+ swapchain_format_to_use = usable_swapchain_formats[i];
+ }
+ }
+
+ if (swapchain_format_to_use == 0) {
+ swapchain_format_to_use = usable_swapchain_formats[0]; // just use the first one and hope for the best...
+ print_line("Couldn't find usable color swap chain format, using", get_swapchain_format_name(swapchain_format_to_use), "instead.");
+ } else {
+ print_line("Using color swap chain format:", get_swapchain_format_name(swapchain_format_to_use));
+ }
+
+ if (!create_swapchain(XR_SWAPCHAIN_USAGE_SAMPLED_BIT | XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT, swapchain_format_to_use, recommended_size.width, recommended_size.height, view_configuration_views[0].recommendedSwapchainSampleCount, view_count, swapchains[OPENXR_SWAPCHAIN_COLOR].swapchain, &swapchains[OPENXR_SWAPCHAIN_COLOR].swapchain_graphics_data)) {
+ return false;
+ }
}
views = (XrView *)memalloc(sizeof(XrView) * view_count);
@@ -717,18 +720,73 @@ bool OpenXRAPI::create_main_swapchain() {
projection_views = (XrCompositionLayerProjectionView *)memalloc(sizeof(XrCompositionLayerProjectionView) * view_count);
ERR_FAIL_NULL_V_MSG(projection_views, false, "OpenXR Couldn't allocate memory for projection views");
+ // We create our depth swapchain if:
+ // - we support our depth layer extension
+ // - we have our spacewarp extension (not yet implemented)
+ if (OpenXRCompositionLayerDepthExtension::get_singleton()->is_available()) {
+ // Build a vector with swapchain formats we want to use, from best fit to worst
+ Vector usable_swapchain_formats;
+ int64_t swapchain_format_to_use = 0;
+
+ graphics_extension->get_usable_depth_formats(usable_swapchain_formats);
+
+ // now find out which one is supported
+ for (int i = 0; i < usable_swapchain_formats.size() && swapchain_format_to_use == 0; i++) {
+ if (is_swapchain_format_supported(usable_swapchain_formats[i])) {
+ swapchain_format_to_use = usable_swapchain_formats[i];
+ }
+ }
+
+ if (swapchain_format_to_use == 0) {
+ swapchain_format_to_use = usable_swapchain_formats[0]; // just use the first one and hope for the best...
+ print_line("Couldn't find usable depth swap chain format, using", get_swapchain_format_name(swapchain_format_to_use), "instead.");
+ } else {
+ print_line("Using depth swap chain format:", get_swapchain_format_name(swapchain_format_to_use));
+ }
+
+ if (!create_swapchain(XR_SWAPCHAIN_USAGE_SAMPLED_BIT | XR_SWAPCHAIN_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, swapchain_format_to_use, recommended_size.width, recommended_size.height, view_configuration_views[0].recommendedSwapchainSampleCount, view_count, swapchains[OPENXR_SWAPCHAIN_DEPTH].swapchain, &swapchains[OPENXR_SWAPCHAIN_DEPTH].swapchain_graphics_data)) {
+ return false;
+ }
+
+ depth_views = (XrCompositionLayerDepthInfoKHR *)memalloc(sizeof(XrCompositionLayerDepthInfoKHR) * view_count);
+ ERR_FAIL_NULL_V_MSG(depth_views, false, "OpenXR Couldn't allocate memory for depth views");
+ }
+
+ // We create our velocity swapchain if:
+ // - we have our spacewarp extension (not yet implemented)
+ {
+ // TBD
+ }
+
for (uint32_t i = 0; i < view_count; i++) {
views[i].type = XR_TYPE_VIEW;
views[i].next = nullptr;
projection_views[i].type = XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW;
projection_views[i].next = nullptr;
- projection_views[i].subImage.swapchain = swapchain;
+ projection_views[i].subImage.swapchain = swapchains[OPENXR_SWAPCHAIN_COLOR].swapchain;
projection_views[i].subImage.imageArrayIndex = i;
projection_views[i].subImage.imageRect.offset.x = 0;
projection_views[i].subImage.imageRect.offset.y = 0;
projection_views[i].subImage.imageRect.extent.width = recommended_size.width;
projection_views[i].subImage.imageRect.extent.height = recommended_size.height;
+
+ if (OpenXRCompositionLayerDepthExtension::get_singleton()->is_available() && depth_views) {
+ projection_views[i].next = &depth_views[i];
+
+ depth_views[i].type = XR_TYPE_COMPOSITION_LAYER_DEPTH_INFO_KHR;
+ depth_views[i].next = nullptr;
+ depth_views[i].subImage.swapchain = swapchains[OPENXR_SWAPCHAIN_DEPTH].swapchain;
+ depth_views[i].subImage.imageArrayIndex = 0;
+ depth_views[i].subImage.imageRect.offset.x = 0;
+ depth_views[i].subImage.imageRect.offset.y = 0;
+ depth_views[i].subImage.imageRect.extent.width = recommended_size.width;
+ depth_views[i].subImage.imageRect.extent.height = recommended_size.height;
+ depth_views[i].minDepth = 0.0;
+ depth_views[i].maxDepth = 1.0;
+ depth_views[i].nearZ = 0.01; // Near and far Z will be set to the correct values in fill_projection_matrix
+ depth_views[i].farZ = 100.0;
+ }
};
return true;
@@ -740,7 +798,7 @@ void OpenXRAPI::destroy_session() {
}
if (graphics_extension) {
- graphics_extension->cleanup_swapchain_graphics_data(&swapchain_graphics_data);
+ graphics_extension->cleanup_swapchain_graphics_data(&swapchains[OPENXR_SWAPCHAIN_COLOR].swapchain_graphics_data);
}
if (views != nullptr) {
@@ -753,9 +811,16 @@ void OpenXRAPI::destroy_session() {
projection_views = nullptr;
}
- if (swapchain != XR_NULL_HANDLE) {
- xrDestroySwapchain(swapchain);
- swapchain = XR_NULL_HANDLE;
+ if (depth_views != nullptr) {
+ memfree(depth_views);
+ depth_views = nullptr;
+ }
+
+ for (int i = 0; i < OPENXR_SWAPCHAIN_MAX; i++) {
+ if (swapchains[i].swapchain != XR_NULL_HANDLE) {
+ xrDestroySwapchain(swapchains[i].swapchain);
+ swapchains[i].swapchain = XR_NULL_HANDLE;
+ }
}
if (supported_swapchain_formats != nullptr) {
@@ -789,7 +854,7 @@ void OpenXRAPI::destroy_session() {
}
}
-bool OpenXRAPI::create_swapchain(int64_t p_swapchain_format, uint32_t p_width, uint32_t p_height, uint32_t p_sample_count, uint32_t p_array_size, XrSwapchain &r_swapchain, void **r_swapchain_graphics_data) {
+bool OpenXRAPI::create_swapchain(XrSwapchainUsageFlags p_usage_flags, int64_t p_swapchain_format, uint32_t p_width, uint32_t p_height, uint32_t p_sample_count, uint32_t p_array_size, XrSwapchain &r_swapchain, void **r_swapchain_graphics_data) {
ERR_FAIL_COND_V(session == XR_NULL_HANDLE, false);
ERR_FAIL_NULL_V(graphics_extension, false);
@@ -807,7 +872,7 @@ bool OpenXRAPI::create_swapchain(int64_t p_swapchain_format, uint32_t p_width, u
XR_TYPE_SWAPCHAIN_CREATE_INFO, // type
next_pointer, // next
0, // createFlags
- XR_SWAPCHAIN_USAGE_SAMPLED_BIT | XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT, // usageFlags
+ p_usage_flags, // usageFlags
p_swapchain_format, // format
p_sample_count, // sampleCount
p_width, // width
@@ -871,7 +936,7 @@ bool OpenXRAPI::on_state_ready() {
// That will be very very ugly
// The other possibility is to create a separate OpenXRViewport type specifically for this goal as part of our OpenXR module
- if (!create_main_swapchain()) {
+ if (!create_swapchains()) {
return false;
}
@@ -1304,6 +1369,15 @@ bool OpenXRAPI::get_view_projection(uint32_t p_view, double p_z_near, double p_z
return false;
}
+ // if we're using depth views, make sure we update our near and far there...
+ if (depth_views != nullptr) {
+ for (uint32_t i = 0; i < view_count; i++) {
+ depth_views[i].nearZ = p_z_near;
+ depth_views[i].farZ = p_z_far;
+ }
+ }
+
+ // now update our projection
return graphics_extension->create_projection_fov(views[p_view].fov, p_z_near, p_z_far, p_camera_matrix);
}
@@ -1442,15 +1516,15 @@ bool OpenXRAPI::process() {
return true;
}
-bool OpenXRAPI::acquire_image(XrSwapchain p_swapchain, uint32_t &r_image_index) {
- ERR_FAIL_COND_V(image_acquired, true); // this was not released when it should be, error out and re-use...
+bool OpenXRAPI::acquire_image(OpenXRSwapChainInfo &p_swapchain) {
+ ERR_FAIL_COND_V(p_swapchain.image_acquired, true); // this was not released when it should be, error out and re-use...
XrResult result;
XrSwapchainImageAcquireInfo swapchain_image_acquire_info = {
XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO, // type
nullptr // next
};
- result = xrAcquireSwapchainImage(p_swapchain, &swapchain_image_acquire_info, &r_image_index);
+ result = xrAcquireSwapchainImage(p_swapchain.swapchain, &swapchain_image_acquire_info, &p_swapchain.image_index);
if (XR_FAILED(result)) {
print_line("OpenXR: failed to acquire swapchain image [", get_error_string(result), "]");
return false;
@@ -1462,7 +1536,7 @@ bool OpenXRAPI::acquire_image(XrSwapchain p_swapchain, uint32_t &r_image_index)
17000000 // timeout in nanoseconds
};
- result = xrWaitSwapchainImage(p_swapchain, &swapchain_image_wait_info);
+ result = xrWaitSwapchainImage(p_swapchain.swapchain, &swapchain_image_wait_info);
if (XR_FAILED(result)) {
print_line("OpenXR: failed to wait for swapchain image [", get_error_string(result), "]");
return false;
@@ -1471,12 +1545,12 @@ bool OpenXRAPI::acquire_image(XrSwapchain p_swapchain, uint32_t &r_image_index)
return true;
}
-bool OpenXRAPI::release_image(XrSwapchain p_swapchain) {
+bool OpenXRAPI::release_image(OpenXRSwapChainInfo &p_swapchain) {
XrSwapchainImageReleaseInfo swapchain_image_release_info = {
XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO, // type
nullptr // next
};
- XrResult result = xrReleaseSwapchainImage(swapchain, &swapchain_image_release_info);
+ XrResult result = xrReleaseSwapchainImage(p_swapchain.swapchain, &swapchain_image_release_info);
if (XR_FAILED(result)) {
print_line("OpenXR: failed to release swapchain image! [", get_error_string(result), "]");
return false;
@@ -1590,28 +1664,41 @@ bool OpenXRAPI::pre_draw_viewport(RID p_render_target) {
// TODO: at some point in time we may support multiple viewports in which case we need to handle that...
+ // Acquire our images
+ for (int i = 0; i < OPENXR_SWAPCHAIN_MAX; i++) {
+ if (!swapchains[i].image_acquired && swapchains[i].swapchain != XR_NULL_HANDLE) {
+ if (!acquire_image(swapchains[i])) {
+ return false;
+ }
+ swapchains[i].image_acquired = true;
+ }
+ }
+
return true;
}
+RID OpenXRAPI::get_color_texture() {
+ if (swapchains[OPENXR_SWAPCHAIN_COLOR].image_acquired) {
+ return graphics_extension->get_texture(swapchains[OPENXR_SWAPCHAIN_COLOR].swapchain_graphics_data, swapchains[OPENXR_SWAPCHAIN_COLOR].image_index);
+ } else {
+ return RID();
+ }
+}
+
+RID OpenXRAPI::get_depth_texture() {
+ if (swapchains[OPENXR_SWAPCHAIN_DEPTH].image_acquired) {
+ return graphics_extension->get_texture(swapchains[OPENXR_SWAPCHAIN_DEPTH].swapchain_graphics_data, swapchains[OPENXR_SWAPCHAIN_DEPTH].image_index);
+ } else {
+ return RID();
+ }
+}
+
void OpenXRAPI::post_draw_viewport(RID p_render_target) {
if (!can_render()) {
return;
}
- // TODO: at some point in time we may support multiple viewports in which case we need to handle that...
-
- // TODO: if we can get PR 51179 to work properly we can change away from this approach and move this into get_external_texture or something
- if (!image_acquired) {
- if (!acquire_image(swapchain, image_index)) {
- return;
- }
- image_acquired = true;
-
- // print_line("OpenXR: acquired image " + itos(image_index) + ", copying...");
-
- // Copy our buffer into our swap chain (remove once PR 51179 is done)
- graphics_extension->copy_render_target_to_image(p_render_target, swapchain_graphics_data, image_index);
- }
+ // Nothing to do here at this point in time...
};
void OpenXRAPI::end_frame() {
@@ -1623,7 +1710,7 @@ void OpenXRAPI::end_frame() {
return;
}
- if (frame_state.shouldRender && view_pose_valid && !image_acquired) {
+ if (frame_state.shouldRender && view_pose_valid && !swapchains[OPENXR_SWAPCHAIN_COLOR].image_acquired) {
print_line("OpenXR: No viewport was marked with use_xr, there is no rendered output!");
}
@@ -1631,7 +1718,7 @@ void OpenXRAPI::end_frame() {
// - shouldRender set to true
// - a valid view pose for projection_views[eye].pose to submit layer
// - an image to render
- if (!frame_state.shouldRender || !view_pose_valid || !image_acquired) {
+ if (!frame_state.shouldRender || !view_pose_valid || !swapchains[OPENXR_SWAPCHAIN_COLOR].image_acquired) {
// submit 0 layers when we shouldn't render
XrFrameEndInfo frame_end_info = {
XR_TYPE_FRAME_END_INFO, // type
@@ -1652,10 +1739,12 @@ void OpenXRAPI::end_frame() {
}
// release our swapchain image if we acquired it
- if (image_acquired) {
- image_acquired = false; // whether we succeed or not, consider this released.
+ for (int i = 0; i < OPENXR_SWAPCHAIN_MAX; i++) {
+ if (swapchains[i].image_acquired) {
+ swapchains[i].image_acquired = false; // whether we succeed or not, consider this released.
- release_image(swapchain);
+ release_image(swapchains[i]);
+ }
}
for (uint32_t eye = 0; eye < view_count; eye++) {
@@ -1763,6 +1852,7 @@ OpenXRAPI::OpenXRAPI() {
// register our other extensions
register_extension_wrapper(memnew(OpenXRPalmPoseExtension(this)));
+ register_extension_wrapper(memnew(OpenXRCompositionLayerDepthExtension(this)));
register_extension_wrapper(memnew(OpenXRHTCViveTrackerExtension(this)));
register_extension_wrapper(memnew(OpenXRHandTrackingExtension(this)));
register_extension_wrapper(memnew(OpenXRFbPassthroughExtensionWrapper(this)));
diff --git a/modules/openxr/openxr_api.h b/modules/openxr/openxr_api.h
index 316886239ed..bd69432dcba 100644
--- a/modules/openxr/openxr_api.h
+++ b/modules/openxr/openxr_api.h
@@ -120,15 +120,28 @@ private:
OpenXRGraphicsExtensionWrapper *graphics_extension = nullptr;
XrSystemGraphicsProperties graphics_properties;
- void *swapchain_graphics_data = nullptr;
- uint32_t image_index = 0;
- bool image_acquired = false;
uint32_t view_count = 0;
XrViewConfigurationView *view_configuration_views = nullptr;
XrView *views = nullptr;
XrCompositionLayerProjectionView *projection_views = nullptr;
- XrSwapchain swapchain = XR_NULL_HANDLE;
+ XrCompositionLayerDepthInfoKHR *depth_views = nullptr; // Only used by Composition Layer Depth Extension if available
+
+ enum OpenXRSwapChainTypes {
+ OPENXR_SWAPCHAIN_COLOR,
+ OPENXR_SWAPCHAIN_DEPTH,
+ // OPENXR_SWAPCHAIN_VELOCITY,
+ OPENXR_SWAPCHAIN_MAX
+ };
+
+ struct OpenXRSwapChainInfo {
+ XrSwapchain swapchain = XR_NULL_HANDLE;
+ void *swapchain_graphics_data = nullptr;
+ uint32_t image_index = 0;
+ bool image_acquired = false;
+ };
+
+ OpenXRSwapChainInfo swapchains[OPENXR_SWAPCHAIN_MAX];
XrSpace play_space = XR_NULL_HANDLE;
XrSpace view_space = XR_NULL_HANDLE;
@@ -212,13 +225,13 @@ private:
bool setup_spaces();
bool load_supported_swapchain_formats();
bool is_swapchain_format_supported(int64_t p_swapchain_format);
- bool create_main_swapchain();
+ bool create_swapchains();
void destroy_session();
// swapchains
- bool create_swapchain(int64_t p_swapchain_format, uint32_t p_width, uint32_t p_height, uint32_t p_sample_count, uint32_t p_array_size, XrSwapchain &r_swapchain, void **r_swapchain_graphics_data);
- bool acquire_image(XrSwapchain p_swapchain, uint32_t &r_image_index);
- bool release_image(XrSwapchain p_swapchain);
+ bool create_swapchain(XrSwapchainUsageFlags p_usage_flags, int64_t p_swapchain_format, uint32_t p_width, uint32_t p_height, uint32_t p_sample_count, uint32_t p_array_size, XrSwapchain &r_swapchain, void **r_swapchain_graphics_data);
+ bool acquire_image(OpenXRSwapChainInfo &p_swapchain);
+ bool release_image(OpenXRSwapChainInfo &p_swapchain);
// action map
struct Tracker { // Trackers represent tracked physical objects such as controllers, pucks, etc.
@@ -318,6 +331,8 @@ public:
void pre_render();
bool pre_draw_viewport(RID p_render_target);
+ RID get_color_texture();
+ RID get_depth_texture();
void post_draw_viewport(RID p_render_target);
void end_frame();
diff --git a/modules/openxr/openxr_interface.cpp b/modules/openxr/openxr_interface.cpp
index 01e148e00f6..31dc2bbf430 100644
--- a/modules/openxr/openxr_interface.cpp
+++ b/modules/openxr/openxr_interface.cpp
@@ -648,6 +648,22 @@ Projection OpenXRInterface::get_projection_for_view(uint32_t p_view, double p_as
return cm;
}
+RID OpenXRInterface::get_color_texture() {
+ if (openxr_api) {
+ return openxr_api->get_color_texture();
+ } else {
+ return RID();
+ }
+}
+
+RID OpenXRInterface::get_depth_texture() {
+ if (openxr_api) {
+ return openxr_api->get_depth_texture();
+ } else {
+ return RID();
+ }
+}
+
void OpenXRInterface::process() {
if (openxr_api) {
// do our normal process
@@ -707,6 +723,7 @@ bool OpenXRInterface::pre_draw_viewport(RID p_render_target) {
Vector OpenXRInterface::post_draw_viewport(RID p_render_target, const Rect2 &p_screen_rect) {
Vector blit_to_screen;
+#ifndef ANDROID_ENABLED
// If separate HMD we should output one eye to screen
if (p_screen_rect != Rect2()) {
BlitToScreen blit;
@@ -732,6 +749,7 @@ Vector OpenXRInterface::post_draw_viewport(RID p_render_target, co
blit.dst_rect = dst_rect;
blit_to_screen.push_back(blit);
}
+#endif
if (openxr_api) {
openxr_api->post_draw_viewport(p_render_target);
diff --git a/modules/openxr/openxr_interface.h b/modules/openxr/openxr_interface.h
index 3765f186375..72935b039cf 100644
--- a/modules/openxr/openxr_interface.h
+++ b/modules/openxr/openxr_interface.h
@@ -126,6 +126,9 @@ public:
virtual Transform3D get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) override;
virtual Projection get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) override;
+ virtual RID get_color_texture() override;
+ virtual RID get_depth_texture() override;
+
virtual void process() override;
virtual void pre_render() override;
bool pre_draw_viewport(RID p_render_target) override;
diff --git a/servers/rendering/dummy/storage/texture_storage.h b/servers/rendering/dummy/storage/texture_storage.h
index f5bdccca68d..98acd5ad741 100644
--- a/servers/rendering/dummy/storage/texture_storage.h
+++ b/servers/rendering/dummy/storage/texture_storage.h
@@ -157,14 +157,17 @@ public:
virtual RID render_target_create() override { return RID(); }
virtual void render_target_free(RID p_rid) override {}
virtual void render_target_set_position(RID p_render_target, int p_x, int p_y) override {}
+ virtual Point2i render_target_get_position(RID p_render_target) const override { return Point2i(); }
virtual void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) override {}
- virtual RID render_target_get_texture(RID p_render_target) override { return RID(); }
- virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) override {}
+ virtual Size2i render_target_get_size(RID p_render_target) const override { return Size2i(); }
virtual void render_target_set_transparent(RID p_render_target, bool p_is_transparent) override {}
+ virtual bool render_target_get_transparent(RID p_render_target) const override { return false; }
virtual void render_target_set_direct_to_screen(RID p_render_target, bool p_direct_to_screen) override {}
- virtual bool render_target_was_used(RID p_render_target) override { return false; }
+ virtual bool render_target_get_direct_to_screen(RID p_render_target) const override { return false; }
+ virtual bool render_target_was_used(RID p_render_target) const override { return false; }
virtual void render_target_set_as_unused(RID p_render_target) override {}
virtual void render_target_set_msaa(RID p_render_target, RS::ViewportMSAA p_msaa) override {}
+ virtual RS::ViewportMSAA render_target_get_msaa(RID p_render_target) const override { return RS::VIEWPORT_MSAA_DISABLED; }
virtual void render_target_request_clear(RID p_render_target, const Color &p_clear_color) override {}
virtual bool render_target_is_clear_requested(RID p_render_target) override { return false; }
@@ -176,8 +179,19 @@ public:
virtual Rect2i render_target_get_sdf_rect(RID p_render_target) const override { return Rect2i(); }
virtual void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) override {}
- virtual void render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) override{};
- virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) override{};
+ virtual void render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) override {}
+ virtual RS::ViewportVRSMode render_target_get_vrs_mode(RID p_render_target) const override { return RS::VIEWPORT_VRS_DISABLED; }
+ virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) override {}
+ virtual RID render_target_get_vrs_texture(RID p_render_target) const override { return RID(); }
+
+ virtual void render_target_set_override_color(RID p_render_target, RID p_texture) override {}
+ virtual RID render_target_get_override_color(RID p_render_target) const override { return RID(); }
+ virtual void render_target_set_override_depth(RID p_render_target, RID p_texture) override {}
+ virtual RID render_target_get_override_depth(RID p_render_target) const override { return RID(); }
+ virtual void render_target_set_override_velocity(RID p_render_target, RID p_texture) override {}
+ virtual RID render_target_get_override_velocity(RID p_render_target) const override { return RID(); }
+
+ virtual RID render_target_get_texture(RID p_render_target) override { return RID(); }
};
} // namespace RendererDummy
diff --git a/servers/rendering/renderer_rd/environment/gi.cpp b/servers/rendering/renderer_rd/environment/gi.cpp
index 08534608618..ee6e5c27f26 100644
--- a/servers/rendering/renderer_rd/environment/gi.cpp
+++ b/servers/rendering/renderer_rd/environment/gi.cpp
@@ -1644,8 +1644,8 @@ void GI::SDFGI::debug_draw(uint32_t p_view_count, const Projection *p_projection
RD::get_singleton()->compute_list_end();
}
- Size2 rtsize = texture_storage->render_target_get_size(p_render_target);
- copy_effects->copy_to_fb_rect(p_texture, texture_storage->render_target_get_rd_framebuffer(p_render_target), Rect2(Vector2(), rtsize), true, false, false, false, RID(), p_view_count > 1);
+ Size2i rtsize = texture_storage->render_target_get_size(p_render_target);
+ copy_effects->copy_to_fb_rect(p_texture, texture_storage->render_target_get_rd_framebuffer(p_render_target), Rect2i(Point2i(), rtsize), true, false, false, false, RID(), p_view_count > 1);
}
void GI::SDFGI::debug_probes(RID p_framebuffer, const uint32_t p_view_count, const Projection *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth) {
diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
index c1a78189219..cf08949d998 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
@@ -2095,17 +2095,17 @@ void RenderForwardClustered::_render_buffers_debug_draw(Refget_render_target();
if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_SSAO && rb_data->ss_effects_data.ssao.ao_final.is_valid()) {
- Size2 rtsize = texture_storage->render_target_get_size(render_target);
+ Size2i rtsize = texture_storage->render_target_get_size(render_target);
copy_effects->copy_to_fb_rect(rb_data->ss_effects_data.ssao.ao_final, texture_storage->render_target_get_rd_framebuffer(render_target), Rect2(Vector2(), rtsize), false, true);
}
if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_SSIL && rb_data->ss_effects_data.ssil.ssil_final.is_valid()) {
- Size2 rtsize = texture_storage->render_target_get_size(render_target);
+ Size2i rtsize = texture_storage->render_target_get_size(render_target);
copy_effects->copy_to_fb_rect(rb_data->ss_effects_data.ssil.ssil_final, texture_storage->render_target_get_rd_framebuffer(render_target), Rect2(Vector2(), rtsize), false, false);
}
if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_BUFFER && p_render_buffers->has_texture(RB_SCOPE_GI, RB_TEX_AMBIENT)) {
- Size2 rtsize = texture_storage->render_target_get_size(render_target);
+ Size2i rtsize = texture_storage->render_target_get_size(render_target);
RID ambient_texture = p_render_buffers->get_texture(RB_SCOPE_GI, RB_TEX_AMBIENT);
RID reflection_texture = p_render_buffers->get_texture(RB_SCOPE_GI, RB_TEX_REFLECTION);
copy_effects->copy_to_fb_rect(ambient_texture, texture_storage->render_target_get_rd_framebuffer(render_target), Rect2(Vector2(), rtsize), false, false, false, true, reflection_texture, p_render_buffers->get_view_count() > 1);
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
index a50742f91a4..dd3f62e509f 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
@@ -44,13 +44,9 @@ void RendererCompositorRD::blit_render_targets_to_screen(DisplayServer::WindowID
}
for (int i = 0; i < p_amount; i++) {
- RID texture = texture_storage->render_target_get_texture(p_render_targets[i].render_target);
- ERR_CONTINUE(texture.is_null());
- RID rd_texture = texture_storage->texture_get_rd_texture(texture);
+ RID rd_texture = texture_storage->render_target_get_rd_texture(p_render_targets[i].render_target);
ERR_CONTINUE(rd_texture.is_null());
- // TODO if keep_3d_linear was set when rendering to this render target we need to add a linear->sRGB conversion in.
-
if (!render_target_descriptors.has(rd_texture) || !RD::get_singleton()->uniform_set_is_valid(render_target_descriptors[rd_texture])) {
Vector uniforms;
RD::Uniform u;
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index acc964b3f3f..6157d7d840e 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
@@ -828,7 +828,7 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(Ref
if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS) {
if (RendererRD::LightStorage::get_singleton()->directional_shadow_get_texture().is_valid()) {
RID shadow_atlas_texture = RendererRD::LightStorage::get_singleton()->directional_shadow_get_texture();
- Size2 rtsize = texture_storage->render_target_get_size(render_target);
+ Size2i rtsize = texture_storage->render_target_get_size(render_target);
copy_effects->copy_to_fb_rect(shadow_atlas_texture, texture_storage->render_target_get_rd_framebuffer(render_target), Rect2i(Vector2(), rtsize / 2), false, true);
}
@@ -838,7 +838,7 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(Ref
RID decal_atlas = RendererRD::TextureStorage::get_singleton()->decal_atlas_get_texture();
if (decal_atlas.is_valid()) {
- Size2 rtsize = texture_storage->render_target_get_size(render_target);
+ Size2i rtsize = texture_storage->render_target_get_size(render_target);
copy_effects->copy_to_fb_rect(decal_atlas, texture_storage->render_target_get_rd_framebuffer(render_target), Rect2i(Vector2(), rtsize / 2), false, false, true);
}
@@ -846,7 +846,7 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(Ref
if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SCENE_LUMINANCE) {
if (p_render_buffers->luminance.current.is_valid()) {
- Size2 rtsize = texture_storage->render_target_get_size(render_target);
+ Size2i rtsize = texture_storage->render_target_get_size(render_target);
copy_effects->copy_to_fb_rect(p_render_buffers->luminance.current, texture_storage->render_target_get_rd_framebuffer(render_target), Rect2(Vector2(), rtsize / 8), false, true);
}
@@ -859,13 +859,13 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(Ref
if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_OCCLUDERS) {
if (p_occlusion_buffer.is_valid()) {
- Size2 rtsize = texture_storage->render_target_get_size(render_target);
+ Size2i rtsize = texture_storage->render_target_get_size(render_target);
copy_effects->copy_to_fb_rect(texture_storage->texture_get_rd_texture(p_occlusion_buffer), texture_storage->render_target_get_rd_framebuffer(render_target), Rect2i(Vector2(), rtsize), true, false);
}
}
if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_MOTION_VECTORS && _render_buffers_get_velocity_texture(p_render_buffers).is_valid()) {
- Size2 rtsize = texture_storage->render_target_get_size(render_target);
+ Size2i rtsize = texture_storage->render_target_get_size(render_target);
copy_effects->copy_to_fb_rect(_render_buffers_get_velocity_texture(p_render_buffers), texture_storage->render_target_get_rd_framebuffer(render_target), Rect2(Vector2(), rtsize), false, false);
}
}
diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp
index 1b2237b5058..0c2092f03e1 100644
--- a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp
@@ -178,7 +178,7 @@ void RenderSceneBuffersRD::configure(RID p_render_target, const Size2i p_interna
// Create our depth buffer
{
- // TODO If we have depth buffer supplied externally, pick this up
+ // TODO Lazy create this in case we've got an external depth buffer
RD::DataFormat format;
uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT;
@@ -490,6 +490,28 @@ Ref RenderSceneBuffersRD::get_custom_data(const String
return ret;
}
+// Depth texture
+
+RID RenderSceneBuffersRD::get_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 depth;
+ } else {
+ return get_texture(RB_SCOPE_BUFFERS, RB_TEX_DEPTH);
+ }
+}
+
+RID RenderSceneBuffersRD::get_depth_texture(const uint32_t p_layer) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ RID depth_slice = texture_storage->render_target_get_override_depth_slice(render_target, p_layer);
+ if (depth_slice.is_valid()) {
+ return depth_slice;
+ } else {
+ return get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_DEPTH, p_layer, 0);
+ }
+}
+
// Velocity texture.
void RenderSceneBuffersRD::ensure_velocity() {
@@ -516,6 +538,20 @@ void RenderSceneBuffersRD::ensure_velocity() {
}
}
+bool RenderSceneBuffersRD::has_velocity_buffer(bool p_has_msaa) {
+ if (p_has_msaa) {
+ return has_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY_MSAA);
+ } else {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ RID velocity = texture_storage->render_target_get_override_velocity(render_target);
+ if (velocity.is_valid()) {
+ return true;
+ } else {
+ return has_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY);
+ }
+ }
+}
+
RID RenderSceneBuffersRD::get_velocity_buffer(bool p_get_msaa) {
if (p_get_msaa) {
if (!has_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY_MSAA)) {
@@ -524,10 +560,28 @@ RID RenderSceneBuffersRD::get_velocity_buffer(bool p_get_msaa) {
return get_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY_MSAA);
}
} else {
- if (!has_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY)) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ RID velocity = texture_storage->render_target_get_override_velocity(render_target);
+ if (velocity.is_valid()) {
+ return velocity;
+ } else if (!has_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY)) {
return RID();
} else {
return get_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY);
}
}
}
+
+RID RenderSceneBuffersRD::get_velocity_buffer(bool p_get_msaa, uint32_t p_layer) {
+ if (p_get_msaa) {
+ return get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY_MSAA, p_layer, 0);
+ } else {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ RID velocity_slice = texture_storage->render_target_get_override_velocity_slice(render_target, p_layer);
+ if (velocity_slice.is_valid()) {
+ return velocity_slice;
+ } else {
+ return get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY, p_layer, 0);
+ }
+ }
+}
diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h
index 169ee2e2b15..6907f69b933 100644
--- a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h
+++ b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h
@@ -189,12 +189,8 @@ public:
return get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_COLOR, p_layer, 0);
}
- _FORCE_INLINE_ RID get_depth_texture() const {
- return get_texture(RB_SCOPE_BUFFERS, RB_TEX_DEPTH);
- }
- _FORCE_INLINE_ RID get_depth_texture(const uint32_t p_layer) {
- return get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_DEPTH, p_layer, 0);
- }
+ RID get_depth_texture();
+ RID get_depth_texture(const uint32_t p_layer);
// back buffer (color)
RID get_back_buffer_texture() const { return has_texture(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0) ? get_texture(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0) : RID(); } // We (re)use our blur texture here.
@@ -202,9 +198,9 @@ public:
// Velocity, currently only used by TAA (Clustered) but we'll be using this in other places soon too.
void ensure_velocity();
- bool has_velocity_buffer(bool p_has_msaa) { return has_texture(RB_SCOPE_BUFFERS, p_has_msaa ? RB_TEX_VELOCITY_MSAA : RB_TEX_VELOCITY); }
+ bool has_velocity_buffer(bool p_has_msaa);
RID get_velocity_buffer(bool p_get_msaa);
- RID get_velocity_buffer(bool p_get_msaa, uint32_t p_layer) { return get_texture_slice(RB_SCOPE_BUFFERS, p_get_msaa ? RB_TEX_VELOCITY_MSAA : RB_TEX_VELOCITY, p_layer, 0); }
+ RID get_velocity_buffer(bool p_get_msaa, uint32_t p_layer);
////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Everything after this needs to be re-evaluated, this is all old implementation
diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
index 14e41a0d6b3..b3a7e05ff53 100644
--- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
@@ -30,6 +30,7 @@
#include "texture_storage.h"
#include "../effects/copy_effects.h"
+#include "../framebuffer_cache_rd.h"
#include "material_storage.h"
#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
@@ -2359,10 +2360,26 @@ void TextureStorage::update_decal_buffer(const PagedArray &p_decals, const
/* RENDER TARGET API */
+RID TextureStorage::RenderTarget::get_framebuffer() {
+ // Note that if we're using an overridden color buffer, we're likely cycling through a texture chain.
+ // this is where our framebuffer cache comes in clutch..
+
+ if (msaa != RS::VIEWPORT_MSAA_DISABLED) {
+ return FramebufferCacheRD::get_singleton()->get_cache_multiview(view_count, color_multisample, overridden.color.is_valid() ? overridden.color : color);
+ } else {
+ return FramebufferCacheRD::get_singleton()->get_cache_multiview(view_count, overridden.color.is_valid() ? overridden.color : color);
+ }
+}
+
void TextureStorage::_clear_render_target(RenderTarget *rt) {
- //free in reverse dependency order
- if (rt->framebuffer.is_valid()) {
- RD::get_singleton()->free(rt->framebuffer);
+ // clear overrides, we assume these are freed by the object that created them
+ rt->overridden.color = RID();
+ rt->overridden.depth = RID();
+ rt->overridden.velocity = RID();
+ rt->overridden.cached_slices.clear(); // these are automatically freed when their parent textures are freed so just clear
+
+ // free in reverse dependency order
+ if (rt->framebuffer_uniform_set.is_valid()) {
rt->framebuffer_uniform_set = RID(); //chain deleted
}
@@ -2384,7 +2401,6 @@ void TextureStorage::_clear_render_target(RenderTarget *rt) {
_render_target_clear_sdf(rt);
- rt->framebuffer = RID();
rt->color = RID();
rt->color_multisample = RID();
}
@@ -2432,11 +2448,10 @@ void TextureStorage::_update_render_target(RenderTarget *rt) {
}
}
+ // TODO see if we can lazy create this once we actually use it as we may not need to create this if we have an overridden color buffer...
rt->color = RD::get_singleton()->texture_create(rd_color_attachment_format, rd_view);
ERR_FAIL_COND(rt->color.is_null());
- Vector fb_textures;
-
if (rt->msaa != RS::VIEWPORT_MSAA_DISABLED) {
// Use the texture format of the color attachment for the multisample color attachment.
RD::TextureFormat rd_color_multisample_format = rd_color_attachment_format;
@@ -2450,15 +2465,8 @@ void TextureStorage::_update_render_target(RenderTarget *rt) {
RD::TextureView rd_view_multisample;
rd_color_multisample_format.is_resolve_buffer = false;
rt->color_multisample = RD::get_singleton()->texture_create(rd_color_multisample_format, rd_view_multisample);
- fb_textures.push_back(rt->color_multisample);
ERR_FAIL_COND(rt->color_multisample.is_null());
}
- fb_textures.push_back(rt->color);
- rt->framebuffer = RD::get_singleton()->framebuffer_create(fb_textures, RenderingDevice::INVALID_ID, rt->view_count);
- if (rt->framebuffer.is_null()) {
- _clear_render_target(rt);
- ERR_FAIL_COND(rt->framebuffer.is_null());
- }
{ //update texture
@@ -2568,6 +2576,11 @@ void TextureStorage::render_target_set_position(RID p_render_target, int p_x, in
//unused for this render target
}
+Point2i TextureStorage::render_target_get_position(RID p_render_target) const {
+ //unused for this render target
+ return Point2i();
+}
+
void TextureStorage::render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) {
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND(!rt);
@@ -2579,6 +2592,13 @@ void TextureStorage::render_target_set_size(RID p_render_target, int p_width, in
}
}
+Size2i TextureStorage::render_target_get_size(RID p_render_target) const {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, Size2i());
+
+ return rt->size;
+}
+
RID TextureStorage::render_target_get_texture(RID p_render_target) {
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND_V(!rt, RID());
@@ -2586,7 +2606,84 @@ RID TextureStorage::render_target_get_texture(RID p_render_target) {
return rt->texture;
}
-void TextureStorage::render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) {
+void TextureStorage::render_target_set_override_color(RID p_render_target, RID p_texture) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+
+ rt->overridden.color = p_texture;
+}
+
+RID TextureStorage::render_target_get_override_color(RID p_render_target) const {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, RID());
+
+ return rt->overridden.color;
+}
+
+void TextureStorage::render_target_set_override_depth(RID p_render_target, RID p_texture) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+
+ rt->overridden.depth = p_texture;
+}
+
+RID TextureStorage::render_target_get_override_depth(RID p_render_target) const {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, RID());
+
+ return rt->overridden.depth;
+}
+
+RID TextureStorage::render_target_get_override_depth_slice(RID p_render_target, const uint32_t p_layer) const {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, RID());
+
+ if (rt->overridden.depth.is_null()) {
+ return RID();
+ } else if (rt->view_count == 1) {
+ return rt->overridden.depth;
+ } else {
+ RenderTarget::RTOverridden::SliceKey key(rt->overridden.depth, p_layer);
+
+ if (!rt->overridden.cached_slices.has(key)) {
+ rt->overridden.cached_slices[key] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rt->overridden.depth, p_layer, 0);
+ }
+
+ return rt->overridden.cached_slices[key];
+ }
+}
+
+void TextureStorage::render_target_set_override_velocity(RID p_render_target, RID p_texture) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+
+ rt->overridden.velocity = p_texture;
+}
+
+RID TextureStorage::render_target_get_override_velocity(RID p_render_target) const {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, RID());
+
+ return rt->overridden.velocity;
+}
+
+RID TextureStorage::render_target_get_override_velocity_slice(RID p_render_target, const uint32_t p_layer) const {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, RID());
+
+ if (rt->overridden.velocity.is_null()) {
+ return RID();
+ } else if (rt->view_count == 1) {
+ return rt->overridden.velocity;
+ } else {
+ RenderTarget::RTOverridden::SliceKey key(rt->overridden.velocity, p_layer);
+
+ if (!rt->overridden.cached_slices.has(key)) {
+ rt->overridden.cached_slices[key] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rt->overridden.velocity, p_layer, 0);
+ }
+
+ return rt->overridden.cached_slices[key];
+ }
}
void TextureStorage::render_target_set_transparent(RID p_render_target, bool p_is_transparent) {
@@ -2596,10 +2693,21 @@ void TextureStorage::render_target_set_transparent(RID p_render_target, bool p_i
_update_render_target(rt);
}
+bool TextureStorage::render_target_get_transparent(RID p_render_target) const {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, false);
+
+ return rt->is_transparent;
+}
+
void TextureStorage::render_target_set_direct_to_screen(RID p_render_target, bool p_value) {
}
-bool TextureStorage::render_target_was_used(RID p_render_target) {
+bool TextureStorage::render_target_get_direct_to_screen(RID p_render_target) const {
+ return false;
+}
+
+bool TextureStorage::render_target_was_used(RID p_render_target) const {
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND_V(!rt, false);
return rt->was_used;
@@ -2622,25 +2730,29 @@ void TextureStorage::render_target_set_msaa(RID p_render_target, RS::ViewportMSA
_update_render_target(rt);
}
-Size2 TextureStorage::render_target_get_size(RID p_render_target) {
+RS::ViewportMSAA TextureStorage::render_target_get_msaa(RID p_render_target) const {
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND_V(!rt, Size2());
+ ERR_FAIL_COND_V(!rt, RS::VIEWPORT_MSAA_DISABLED);
- return rt->size;
+ return rt->msaa;
}
RID TextureStorage::render_target_get_rd_framebuffer(RID p_render_target) {
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND_V(!rt, RID());
- return rt->framebuffer;
+ return rt->get_framebuffer();
}
RID TextureStorage::render_target_get_rd_texture(RID p_render_target) {
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND_V(!rt, RID());
- return rt->color;
+ if (rt->overridden.color.is_valid()) {
+ return rt->overridden.color;
+ } else {
+ return rt->color;
+ }
}
RID TextureStorage::render_target_get_rd_texture_slice(RID p_render_target, uint32_t p_layer) {
@@ -2711,7 +2823,7 @@ void TextureStorage::render_target_do_clear_request(RID p_render_target) {
}
Vector clear_colors;
clear_colors.push_back(rt->clear_color);
- RD::get_singleton()->draw_list_begin(rt->framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, clear_colors);
+ RD::get_singleton()->draw_list_begin(rt->get_framebuffer(), RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, clear_colors);
RD::get_singleton()->draw_list_end();
rt->clear_requested = false;
}
@@ -3140,13 +3252,6 @@ void TextureStorage::render_target_set_vrs_mode(RID p_render_target, RS::Viewpor
rt->vrs_mode = p_mode;
}
-void TextureStorage::render_target_set_vrs_texture(RID p_render_target, RID p_texture) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND(!rt);
-
- rt->vrs_texture = p_texture;
-}
-
RS::ViewportVRSMode TextureStorage::render_target_get_vrs_mode(RID p_render_target) const {
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND_V(!rt, RS::VIEWPORT_VRS_DISABLED);
@@ -3154,6 +3259,13 @@ RS::ViewportVRSMode TextureStorage::render_target_get_vrs_mode(RID p_render_targ
return rt->vrs_mode;
}
+void TextureStorage::render_target_set_vrs_texture(RID p_render_target, RID p_texture) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+
+ rt->vrs_texture = p_texture;
+}
+
RID TextureStorage::render_target_get_vrs_texture(RID p_render_target) const {
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND_V(!rt, RID());
diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.h b/servers/rendering/renderer_rd/storage_rd/texture_storage.h
index 327a21a1fc2..00b4e507372 100644
--- a/servers/rendering/renderer_rd/storage_rd/texture_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.h
@@ -301,7 +301,6 @@ private:
struct RenderTarget {
Size2i size;
uint32_t view_count;
- RID framebuffer;
RID color;
Vector color_slices;
RID color_multisample; // Needed when MSAA is enabled.
@@ -339,6 +338,43 @@ private:
RS::ViewportVRSMode vrs_mode = RS::VIEWPORT_VRS_DISABLED;
RID vrs_texture;
+ // overridden textures
+ struct RTOverridden {
+ RID color;
+ RID depth;
+ RID velocity;
+
+ // In a multiview scenario, which is the most likely where we
+ // override our destination textures, we need to obtain slices
+ // for each layer of these textures.
+ // These are likely changing every frame as we loop through
+ // texture chains hence we add a cache to manage these slices.
+ // For this we define a key using the RID of the texture and
+ // the layer for which we create a slice.
+ struct SliceKey {
+ RID rid;
+ uint32_t layer = 0;
+
+ bool operator==(const SliceKey &p_val) const {
+ return (rid == p_val.rid) && (layer == p_val.layer);
+ }
+
+ static uint32_t hash(const SliceKey &p_val) {
+ uint32_t h = hash_one_uint64(p_val.rid.get_id());
+ h = hash_murmur3_one_32(p_val.layer, h);
+ return hash_fmix32(h);
+ }
+
+ SliceKey() {}
+ SliceKey(RID p_rid, uint32_t p_layer) {
+ rid = p_rid;
+ layer = p_layer;
+ }
+ };
+
+ mutable HashMap cached_slices;
+ } overridden;
+
//texture generated for this owner (nor RD).
RID texture;
bool was_used;
@@ -346,6 +382,8 @@ private:
//clear request
bool clear_requested;
Color clear_color;
+
+ RID get_framebuffer();
};
mutable RID_Owner render_target_owner;
@@ -644,14 +682,17 @@ public:
virtual void render_target_free(RID p_rid) override;
virtual void render_target_set_position(RID p_render_target, int p_x, int p_y) override;
+ virtual Point2i render_target_get_position(RID p_render_target) const override;
virtual void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) override;
- virtual RID render_target_get_texture(RID p_render_target) override;
- virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) override;
+ virtual Size2i render_target_get_size(RID p_render_target) const override;
virtual void render_target_set_transparent(RID p_render_target, bool p_is_transparent) override;
+ virtual bool render_target_get_transparent(RID p_render_target) const override;
virtual void render_target_set_direct_to_screen(RID p_render_target, bool p_direct_to_screen) override;
- virtual bool render_target_was_used(RID p_render_target) override;
+ virtual bool render_target_get_direct_to_screen(RID p_render_target) const override;
+ virtual bool render_target_was_used(RID p_render_target) const override;
virtual void render_target_set_as_unused(RID p_render_target) override;
virtual void render_target_set_msaa(RID p_render_target, RS::ViewportMSAA p_msaa) override;
+ virtual RS::ViewportMSAA render_target_get_msaa(RID p_render_target) const override;
void render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region, bool p_gen_mipmaps);
void render_target_clear_back_buffer(RID p_render_target, const Rect2i &p_region, const Color &p_color);
@@ -673,12 +714,21 @@ public:
bool render_target_is_sdf_enabled(RID p_render_target) const;
virtual void render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) override;
+ virtual RS::ViewportVRSMode render_target_get_vrs_mode(RID p_render_target) const override;
virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) override;
+ virtual RID render_target_get_vrs_texture(RID p_render_target) const override;
- RS::ViewportVRSMode render_target_get_vrs_mode(RID p_render_target) const;
- RID render_target_get_vrs_texture(RID p_render_target) const;
+ virtual void render_target_set_override_color(RID p_render_target, RID p_texture) override;
+ virtual RID render_target_get_override_color(RID p_render_target) const override;
+ virtual void render_target_set_override_depth(RID p_render_target, RID p_texture) override;
+ virtual RID render_target_get_override_depth(RID p_render_target) const override;
+ RID render_target_get_override_depth_slice(RID p_render_target, const uint32_t p_layer) const;
+ virtual void render_target_set_override_velocity(RID p_render_target, RID p_texture) override;
+ virtual RID render_target_get_override_velocity(RID p_render_target) const override;
+ RID render_target_get_override_velocity_slice(RID p_render_target, const uint32_t p_layer) const;
+
+ virtual RID render_target_get_texture(RID p_render_target) override;
- Size2 render_target_get_size(RID p_render_target);
RID render_target_get_rd_framebuffer(RID p_render_target);
RID render_target_get_rd_texture(RID p_render_target);
RID render_target_get_rd_texture_slice(RID p_render_target, uint32_t p_layer);
diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp
index 1db018b6476..4f7683493b4 100644
--- a/servers/rendering/renderer_viewport.cpp
+++ b/servers/rendering/renderer_viewport.cpp
@@ -664,9 +664,9 @@ void RendererViewport::draw_viewports() {
RSG::texture_storage->render_target_set_as_unused(vp->render_target);
if (vp->use_xr && xr_interface.is_valid()) {
- // check for an external texture destination (disabled for now, not yet supported)
- // RSG::texture_storage->render_target_set_external_texture(vp->render_target, xr_interface->get_external_texture_for_eye(leftOrMono));
- RSG::texture_storage->render_target_set_external_texture(vp->render_target, 0);
+ RSG::texture_storage->render_target_set_override_color(vp->render_target, xr_interface->get_color_texture());
+ RSG::texture_storage->render_target_set_override_depth(vp->render_target, xr_interface->get_depth_texture());
+ RSG::texture_storage->render_target_set_override_velocity(vp->render_target, xr_interface->get_velocity_texture());
// render...
RSG::scene->set_debug_draw_mode(vp->debug_draw);
@@ -695,7 +695,9 @@ void RendererViewport::draw_viewports() {
}
}
} else {
- RSG::texture_storage->render_target_set_external_texture(vp->render_target, 0);
+ RSG::texture_storage->render_target_set_override_color(vp->render_target, RID()); // TODO if fullscreen output, we can set this to our texture chain
+ RSG::texture_storage->render_target_set_override_depth(vp->render_target, RID());
+ RSG::texture_storage->render_target_set_override_velocity(vp->render_target, RID());
RSG::scene->set_debug_draw_mode(vp->debug_draw);
diff --git a/servers/rendering/storage/texture_storage.h b/servers/rendering/storage/texture_storage.h
index 5024a76c098..635f44786c8 100644
--- a/servers/rendering/storage/texture_storage.h
+++ b/servers/rendering/storage/texture_storage.h
@@ -131,15 +131,18 @@ public:
virtual RID render_target_create() = 0;
virtual void render_target_free(RID p_rid) = 0;
- 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, uint32_t p_view_count) = 0;
- virtual RID render_target_get_texture(RID p_render_target) = 0;
- virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) = 0;
+ virtual void render_target_set_position(RID p_render_target, int p_x, int p_y) = 0; // Q change input to const Point2i &p_position ?
+ virtual Point2i render_target_get_position(RID p_render_target) const = 0;
+ virtual void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) = 0; // Q change input to const Size2i &p_size ?
+ virtual Size2i render_target_get_size(RID p_render_target) const = 0;
virtual void render_target_set_transparent(RID p_render_target, bool p_is_transparent) = 0;
+ virtual bool render_target_get_transparent(RID p_render_target) const = 0;
virtual void render_target_set_direct_to_screen(RID p_render_target, bool p_direct_to_screen) = 0;
- virtual bool render_target_was_used(RID p_render_target) = 0;
+ virtual bool render_target_get_direct_to_screen(RID p_render_target) const = 0;
+ virtual bool render_target_was_used(RID p_render_target) const = 0;
virtual void render_target_set_as_unused(RID p_render_target) = 0;
virtual void render_target_set_msaa(RID p_render_target, RS::ViewportMSAA p_msaa) = 0;
+ virtual RS::ViewportMSAA render_target_get_msaa(RID p_render_target) const = 0;
virtual void render_target_request_clear(RID p_render_target, const Color &p_clear_color) = 0;
virtual bool render_target_is_clear_requested(RID p_render_target) = 0;
@@ -152,7 +155,20 @@ public:
virtual void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) = 0;
virtual void render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) = 0;
+ virtual RS::ViewportVRSMode render_target_get_vrs_mode(RID p_render_target) const = 0;
virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) = 0;
+ virtual RID render_target_get_vrs_texture(RID p_render_target) const = 0;
+
+ // override color, depth and velocity buffers (depth and velocity only for 3D)
+ virtual void render_target_set_override_color(RID p_render_target, RID p_texture) = 0;
+ virtual RID render_target_get_override_color(RID p_render_target) const = 0;
+ virtual void render_target_set_override_depth(RID p_render_target, RID p_texture) = 0;
+ virtual RID render_target_get_override_depth(RID p_render_target) const = 0;
+ virtual void render_target_set_override_velocity(RID p_render_target, RID p_texture) = 0;
+ virtual RID render_target_get_override_velocity(RID p_render_target) const = 0;
+
+ // get textures
+ virtual RID render_target_get_texture(RID p_render_target) = 0;
};
#endif // TEXTURE_STORAGE_H
diff --git a/servers/xr/xr_interface.cpp b/servers/xr/xr_interface.cpp
index 430a5bfd169..430e2042d92 100644
--- a/servers/xr/xr_interface.cpp
+++ b/servers/xr/xr_interface.cpp
@@ -241,6 +241,19 @@ RID XRInterface::get_vrs_texture() {
}
/** these are optional, so we want dummies **/
+
+RID XRInterface::get_color_texture() {
+ return RID();
+}
+
+RID XRInterface::get_depth_texture() {
+ return RID();
+}
+
+RID XRInterface::get_velocity_texture() {
+ return RID();
+}
+
PackedStringArray XRInterface::get_suggested_tracker_names() const {
PackedStringArray arr;
diff --git a/servers/xr/xr_interface.h b/servers/xr/xr_interface.h
index 17ff5f8add4..86d328d41c8 100644
--- a/servers/xr/xr_interface.h
+++ b/servers/xr/xr_interface.h
@@ -121,8 +121,9 @@ public:
virtual Transform3D get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) = 0; /* get each views transform */
virtual Projection get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) = 0; /* get each view projection matrix */
virtual RID get_vrs_texture(); /* obtain VRS texture */
-
- // note, external color/depth/vrs texture support will be added here soon.
+ virtual RID get_color_texture(); /* obtain color output texture (if applicable) */
+ virtual RID get_depth_texture(); /* obtain depth output texture (if applicable, used for reprojection) */
+ virtual RID get_velocity_texture(); /* obtain velocity output texture (if applicable, used for spacewarp) */
virtual void process() = 0;
virtual void pre_render(){};
diff --git a/servers/xr/xr_interface_extension.cpp b/servers/xr/xr_interface_extension.cpp
index 7024a255289..f828c569e9c 100644
--- a/servers/xr/xr_interface_extension.cpp
+++ b/servers/xr/xr_interface_extension.cpp
@@ -74,6 +74,15 @@ void XRInterfaceExtension::_bind_methods() {
GDVIRTUAL_BIND(_set_anchor_detection_is_enabled, "enabled");
GDVIRTUAL_BIND(_get_camera_feed_id);
+ // override output methods
+ GDVIRTUAL_BIND(_get_color_texture);
+ GDVIRTUAL_BIND(_get_depth_texture);
+ GDVIRTUAL_BIND(_get_velocity_texture);
+
+ ClassDB::bind_method(D_METHOD("get_color_texture"), &XRInterfaceExtension::get_color_texture);
+ ClassDB::bind_method(D_METHOD("get_depth_texture"), &XRInterfaceExtension::get_depth_texture);
+ ClassDB::bind_method(D_METHOD("get_velocity_texture"), &XRInterfaceExtension::get_velocity_texture);
+
// helper methods
ClassDB::bind_method(D_METHOD("add_blit", "render_target", "src_rect", "dst_rect", "use_layer", "layer", "apply_lens_distortion", "eye_center", "k1", "k2", "upscale", "aspect_ratio"), &XRInterfaceExtension::add_blit);
ClassDB::bind_method(D_METHOD("get_render_target_texture", "render_target"), &XRInterfaceExtension::get_render_target_texture);
@@ -283,6 +292,33 @@ RID XRInterfaceExtension::get_vrs_texture() {
}
}
+RID XRInterfaceExtension::get_color_texture() {
+ RID texture;
+ if (GDVIRTUAL_CALL(_get_color_texture, texture)) {
+ return texture;
+ } else {
+ return RID();
+ }
+}
+
+RID XRInterfaceExtension::get_depth_texture() {
+ RID texture;
+ if (GDVIRTUAL_CALL(_get_depth_texture, texture)) {
+ return texture;
+ } else {
+ return RID();
+ }
+}
+
+RID XRInterfaceExtension::get_velocity_texture() {
+ RID texture;
+ if (GDVIRTUAL_CALL(_get_velocity_texture, texture)) {
+ return texture;
+ } else {
+ return RID();
+ }
+}
+
void XRInterfaceExtension::add_blit(RID p_render_target, Rect2 p_src_rect, Rect2i p_dst_rect, bool p_use_layer, uint32_t p_layer, bool p_apply_lens_distortion, Vector2 p_eye_center, double p_k1, double p_k2, double p_upscale, double p_aspect_ratio) {
BlitToScreen blit;
diff --git a/servers/xr/xr_interface_extension.h b/servers/xr/xr_interface_extension.h
index 65b474425e0..2235b57cb38 100644
--- a/servers/xr/xr_interface_extension.h
+++ b/servers/xr/xr_interface_extension.h
@@ -102,6 +102,9 @@ public:
virtual Transform3D get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) override;
virtual Projection get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) override;
virtual RID get_vrs_texture() override;
+ virtual RID get_color_texture() override;
+ virtual RID get_depth_texture() override;
+ virtual RID get_velocity_texture() override;
GDVIRTUAL0R(Size2, _get_render_target_size);
GDVIRTUAL0R(uint32_t, _get_view_count);
@@ -109,6 +112,9 @@ public:
GDVIRTUAL2R(Transform3D, _get_transform_for_view, uint32_t, const Transform3D &);
GDVIRTUAL4R(PackedFloat64Array, _get_projection_for_view, uint32_t, double, double, double);
GDVIRTUAL0R(RID, _get_vrs_texture);
+ GDVIRTUAL0R(RID, _get_color_texture);
+ GDVIRTUAL0R(RID, _get_depth_texture);
+ GDVIRTUAL0R(RID, _get_velocity_texture);
void add_blit(RID p_render_target, Rect2 p_src_rect, Rect2i p_dst_rect, bool p_use_layer = false, uint32_t p_layer = 0, bool p_apply_lens_distortion = false, Vector2 p_eye_center = Vector2(), double p_k1 = 0.0, double p_k2 = 0.0, double p_upscale = 1.0, double p_aspect_ratio = 1.0);