Merge pull request #65227 from BastiaanOlij/complete_render_target_api
Implementing override functionality for XR
This commit is contained in:
commit
58a112183c
30 changed files with 803 additions and 330 deletions
doc/classes
drivers/gles3
modules/openxr
SCsub
extensions
openxr_composition_layer_depth_extension.cppopenxr_composition_layer_depth_extension.hopenxr_composition_layer_provider.hopenxr_extension_wrapper.hopenxr_vulkan_extension.cppopenxr_vulkan_extension.h
openxr_api.cppopenxr_api.hopenxr_interface.cppopenxr_interface.hservers
rendering
dummy/storage
renderer_rd
renderer_viewport.cppstorage
xr
|
@ -39,6 +39,18 @@
|
|||
Returns the capabilities of this interface.
|
||||
</description>
|
||||
</method>
|
||||
<method name="_get_color_texture" qualifiers="virtual">
|
||||
<return type="RID" />
|
||||
<description>
|
||||
Return color texture into which to render (if applicable).
|
||||
</description>
|
||||
</method>
|
||||
<method name="_get_depth_texture" qualifiers="virtual">
|
||||
<return type="RID" />
|
||||
<description>
|
||||
Return depth texture into which to render (if applicable).
|
||||
</description>
|
||||
</method>
|
||||
<method name="_get_name" qualifiers="virtual const">
|
||||
<return type="StringName" />
|
||||
<description>
|
||||
|
@ -100,6 +112,12 @@
|
|||
Returns a [Transform3D] for a given view.
|
||||
</description>
|
||||
</method>
|
||||
<method name="_get_velocity_texture" qualifiers="virtual">
|
||||
<return type="RID" />
|
||||
<description>
|
||||
Return velocity texture into which to render (if applicable).
|
||||
</description>
|
||||
</method>
|
||||
<method name="_get_view_count" qualifiers="virtual">
|
||||
<return type="int" />
|
||||
<description>
|
||||
|
@ -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].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_color_texture">
|
||||
<return type="RID" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_depth_texture">
|
||||
<return type="RID" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_render_target_texture">
|
||||
<return type="RID" />
|
||||
<param index="0" name="render_target" type="RID" />
|
||||
|
@ -220,5 +248,10 @@
|
|||
Returns a valid [RID] for a texture to which we should render the current frame if supported by the interface.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_velocity_texture">
|
||||
<return type="RID" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
</class>
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -31,6 +31,7 @@
|
|||
#ifndef OPENXR_COMPOSITION_LAYER_PROVIDER_H
|
||||
#define OPENXR_COMPOSITION_LAYER_PROVIDER_H
|
||||
|
||||
#include "openxr_extension_wrapper.h"
|
||||
#include <openxr/openxr.h>
|
||||
|
||||
// Interface for OpenXR extensions that provide a composition layer.
|
||||
|
|
|
@ -100,11 +100,12 @@ public:
|
|||
class OpenXRGraphicsExtensionWrapper : public OpenXRExtensionWrapper {
|
||||
public:
|
||||
virtual void get_usable_swapchain_formats(Vector<int64_t> &p_usable_swap_chains) = 0;
|
||||
virtual void get_usable_depth_formats(Vector<int64_t> &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){};
|
||||
|
|
|
@ -228,6 +228,12 @@ void OpenXRVulkanExtension::get_usable_swapchain_formats(Vector<int64_t> &p_usab
|
|||
p_usable_swap_chains.push_back(VK_FORMAT_B8G8R8A8_UINT);
|
||||
}
|
||||
|
||||
void OpenXRVulkanExtension::get_usable_depth_formats(Vector<int64_t> &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<RID> image_rids;
|
||||
Vector<RID> framebuffers;
|
||||
Vector<RID> 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<RID> 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;
|
||||
|
|
|
@ -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<int64_t> &p_usable_swap_chains) override;
|
||||
virtual void get_usable_depth_formats(Vector<int64_t> &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<RID> image_rids;
|
||||
Vector<RID> framebuffers;
|
||||
Vector<RID> texture_rids;
|
||||
};
|
||||
|
||||
bool check_graphics_api_support(XrVersion p_desired_version);
|
||||
|
|
|
@ -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<int64_t> 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<int64_t> 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<int64_t> 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)));
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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<BlitToScreen> OpenXRInterface::post_draw_viewport(RID p_render_target, const Rect2 &p_screen_rect) {
|
||||
Vector<BlitToScreen> 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<BlitToScreen> 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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -2095,17 +2095,17 @@ void RenderForwardClustered::_render_buffers_debug_draw(Ref<RenderSceneBuffersRD
|
|||
RID render_target = p_render_buffers->get_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);
|
||||
|
|
|
@ -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<RD::Uniform> uniforms;
|
||||
RD::Uniform u;
|
||||
|
|
|
@ -828,7 +828,7 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(Ref<RenderSceneBuffersRD>
|
|||
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<RenderSceneBuffersRD>
|
|||
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<RenderSceneBuffersRD>
|
|||
|
||||
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<RenderSceneBuffersRD>
|
|||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<RenderBufferCustomDataRD> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<RID> &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<RID> 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<Color> 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());
|
||||
|
|
|
@ -301,7 +301,6 @@ private:
|
|||
struct RenderTarget {
|
||||
Size2i size;
|
||||
uint32_t view_count;
|
||||
RID framebuffer;
|
||||
RID color;
|
||||
Vector<RID> 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<SliceKey, RID, SliceKey> 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<RenderTarget> 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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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(){};
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue