Merge pull request from BastiaanOlij/complete_render_target_api

Implementing override functionality for XR
This commit is contained in:
Rémi Verschelde 2022-10-05 08:31:40 +02:00
commit 58a112183c
30 changed files with 803 additions and 330 deletions

View file

@ -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>

View file

@ -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.

View file

@ -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);

View file

@ -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);

View file

@ -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")

View file

@ -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;
}

View file

@ -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

View file

@ -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.

View file

@ -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){};

View file

@ -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;

View file

@ -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);

View file

@ -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)));

View file

@ -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();

View file

@ -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);

View file

@ -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;

View file

@ -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

View file

@ -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) {

View file

@ -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);

View file

@ -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;

View file

@ -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);
}
}

View file

@ -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);
}
}
}

View file

@ -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

View file

@ -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());

View file

@ -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);

View file

@ -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);

View file

@ -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

View file

@ -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;

View file

@ -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(){};

View file

@ -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;

View file

@ -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);