Improving communication of scaling settings to renderer implementation

This commit is contained in:
Bastiaan Olij 2023-01-13 12:54:15 +11:00
parent 1f171ff18b
commit 478c37deb8
10 changed files with 62 additions and 59 deletions

View File

@ -37,13 +37,14 @@ RenderSceneBuffersGLES3::~RenderSceneBuffersGLES3() {
free_render_buffer_data(); free_render_buffer_data();
} }
void RenderSceneBuffersGLES3::configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) { void RenderSceneBuffersGLES3::configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, RS::ViewportScaling3DMode p_scaling_3d_mode, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) {
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton(); GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
//internal_size.x = p_internal_size.x; // ignore for now //internal_size.x = p_internal_size.x; // ignore for now
//internal_size.y = p_internal_size.y; //internal_size.y = p_internal_size.y;
width = p_target_size.x; width = p_target_size.x;
height = p_target_size.y; height = p_target_size.y;
//scaling_3d_mode = p_scaling_3d_mode
//fsr_sharpness = p_fsr_sharpness; //fsr_sharpness = p_fsr_sharpness;
//texture_mipmap_bias = p_texture_mipmap_bias; //texture_mipmap_bias = p_texture_mipmap_bias;
render_target = p_render_target; render_target = p_render_target;

View File

@ -81,7 +81,7 @@ public:
private: private:
public: public:
virtual ~RenderSceneBuffersGLES3(); virtual ~RenderSceneBuffersGLES3();
virtual void configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override; virtual void configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, RS::ViewportScaling3DMode p_scaling_3d_mode, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override;
virtual void set_fsr_sharpness(float p_fsr_sharpness) override{}; virtual void set_fsr_sharpness(float p_fsr_sharpness) override{};
virtual void set_texture_mipmap_bias(float p_texture_mipmap_bias) override{}; virtual void set_texture_mipmap_bias(float p_texture_mipmap_bias) override{};

View File

@ -251,7 +251,7 @@ RID RenderForwardMobile::RenderBufferDataForwardMobile::get_color_fbs(Framebuffe
Size2i target_size = render_buffers->get_target_size(); Size2i target_size = render_buffers->get_target_size();
Size2i internal_size = render_buffers->get_internal_size(); Size2i internal_size = render_buffers->get_internal_size();
// can't do our blit pass if resolutions don't match // can't do our blit pass if resolutions don't match, this should already have been checked.
ERR_FAIL_COND_V(target_size != internal_size, RID()); ERR_FAIL_COND_V(target_size != internal_size, RID());
// - opaque pass // - opaque pass
@ -715,20 +715,26 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
// setup rendering to render buffer // setup rendering to render buffer
screen_size = p_render_data->render_buffers->get_internal_size(); screen_size = p_render_data->render_buffers->get_internal_size();
if (rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_FOUR_SUBPASSES).is_null()) { if (rb->get_scaling_3d_mode() != RS::VIEWPORT_SCALING_3D_MODE_OFF) {
// can't do blit subpass // can't do blit subpass because we're scaling
using_subpass_post_process = false; using_subpass_post_process = false;
} else if (p_render_data->environment.is_valid() && (environment_get_glow_enabled(p_render_data->environment) || RSG::camera_attributes->camera_attributes_uses_auto_exposure(p_render_data->camera_attributes) || RSG::camera_attributes->camera_attributes_uses_dof(p_render_data->camera_attributes))) { } else if (p_render_data->environment.is_valid() && (environment_get_glow_enabled(p_render_data->environment) || RSG::camera_attributes->camera_attributes_uses_auto_exposure(p_render_data->camera_attributes) || RSG::camera_attributes->camera_attributes_uses_dof(p_render_data->camera_attributes))) {
// can't do blit subpass // can't do blit subpass because we're using post processes
using_subpass_post_process = false; using_subpass_post_process = false;
} }
if (scene_state.used_screen_texture || scene_state.used_depth_texture) { if (scene_state.used_screen_texture || scene_state.used_depth_texture) {
// can't use our last two subpasses // can't use our last two subpasses because we're reading from screen texture or depth texture
using_subpass_transparent = false; using_subpass_transparent = false;
using_subpass_post_process = false; using_subpass_post_process = false;
} }
// We do this last because our get_color_fbs creates and caches the framebuffer if we need it.
if (using_subpass_post_process && rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_FOUR_SUBPASSES).is_null()) {
// can't do blit subpass because we don't have all subpasses
using_subpass_post_process = false;
}
if (using_subpass_post_process) { if (using_subpass_post_process) {
// all as subpasses // all as subpasses
framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_FOUR_SUBPASSES); framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_FOUR_SUBPASSES);

View File

@ -539,7 +539,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
tonemap.view_count = rb->get_view_count(); tonemap.view_count = rb->get_view_count();
RID dest_fb; RID dest_fb;
if (fsr && can_use_effects && (internal_size.x != target_size.x || internal_size.y != target_size.y)) { if (fsr && can_use_effects && rb->get_scaling_3d_mode() == RS::VIEWPORT_SCALING_3D_MODE_FSR) {
// If we use FSR to upscale we need to write our result into an intermediate buffer. // If we use FSR to upscale we need to write our result into an intermediate buffer.
// Note that this is cached so we only create the texture the first time. // Note that this is cached so we only create the texture the first time.
RID dest_texture = rb->create_texture(SNAME("Tonemapper"), SNAME("destination"), _render_buffers_get_color_format(), RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT); RID dest_texture = rb->create_texture(SNAME("Tonemapper"), SNAME("destination"), _render_buffers_get_color_format(), RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT);
@ -556,10 +556,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
RD::get_singleton()->draw_command_end_label(); RD::get_singleton()->draw_command_end_label();
} }
if (fsr && can_use_effects && (internal_size.x != target_size.x || internal_size.y != target_size.y)) { if (fsr && can_use_effects && rb->get_scaling_3d_mode() == RS::VIEWPORT_SCALING_3D_MODE_FSR) {
// TODO Investigate? Does this work? We never write into our render target and we've already done so up above in our tonemapper.
// I think FSR should either work before our tonemapper or as an alternative of our tonemapper.
RD::get_singleton()->draw_command_begin_label("FSR 1.0 Upscale"); RD::get_singleton()->draw_command_begin_label("FSR 1.0 Upscale");
for (uint32_t v = 0; v < rb->get_view_count(); v++) { for (uint32_t v = 0; v < rb->get_view_count(); v++) {

View File

@ -96,7 +96,7 @@ void RenderSceneBuffersRD::cleanup() {
named_textures.clear(); named_textures.clear();
} }
void RenderSceneBuffersRD::configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa_3d, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) { void RenderSceneBuffersRD::configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, RS::ViewportScaling3DMode p_scaling_3d_mode, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa_3d, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
@ -104,12 +104,7 @@ void RenderSceneBuffersRD::configure(RID p_render_target, const Size2i p_interna
target_size = p_target_size; target_size = p_target_size;
internal_size = p_internal_size; internal_size = p_internal_size;
scaling_3d_mode = p_scaling_3d_mode;
// FIXME, right now we do this because only our clustered renderer supports FSR upscale
// this does mean that with linear upscale if we use subpasses, we could get into trouble.
if (!can_be_storage) {
internal_size = target_size;
}
if (p_use_taa) { if (p_use_taa) {
// Use negative mipmap LOD bias when TAA is enabled to compensate for loss of sharpness. // Use negative mipmap LOD bias when TAA is enabled to compensate for loss of sharpness.
@ -193,6 +188,7 @@ void RenderSceneBuffersRD::configure_for_reflections(const Size2i p_reflection_s
target_size = p_reflection_size; target_size = p_reflection_size;
internal_size = p_reflection_size; internal_size = p_reflection_size;
render_target = RID(); render_target = RID();
scaling_3d_mode = RS::VIEWPORT_SCALING_3D_MODE_OFF;
fsr_sharpness = 0.0; fsr_sharpness = 0.0;
msaa_3d = RS::VIEWPORT_MSAA_DISABLED; msaa_3d = RS::VIEWPORT_MSAA_DISABLED;
screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED; screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED;

View File

@ -73,6 +73,7 @@ private:
// The internal size of the textures we render 3D to in case we render at a lower resolution and upscale // The internal size of the textures we render 3D to in case we render at a lower resolution and upscale
Size2i internal_size = Size2i(0, 0); Size2i internal_size = Size2i(0, 0);
RS::ViewportScaling3DMode scaling_3d_mode = RS::VIEWPORT_SCALING_3D_MODE_OFF;
float fsr_sharpness = 0.2f; float fsr_sharpness = 0.2f;
// Aliassing settings // Aliassing settings
@ -139,7 +140,7 @@ public:
void set_vrs(RendererRD::VRS *p_vrs) { vrs = p_vrs; } void set_vrs(RendererRD::VRS *p_vrs) { vrs = p_vrs; }
void cleanup(); void cleanup();
virtual void configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa_3d, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override; virtual void configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, RS::ViewportScaling3DMode p_scaling_3d_mode, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa_3d, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override;
void configure_for_reflections(const Size2i p_reflection_size); void configure_for_reflections(const Size2i p_reflection_size);
virtual void set_fsr_sharpness(float p_fsr_sharpness) override; virtual void set_fsr_sharpness(float p_fsr_sharpness) override;
virtual void set_texture_mipmap_bias(float p_texture_mipmap_bias) override; virtual void set_texture_mipmap_bias(float p_texture_mipmap_bias) override;
@ -172,6 +173,7 @@ public:
_FORCE_INLINE_ uint32_t get_view_count() const { return view_count; } _FORCE_INLINE_ uint32_t get_view_count() const { return view_count; }
_FORCE_INLINE_ Size2i get_internal_size() const { return internal_size; } _FORCE_INLINE_ Size2i get_internal_size() const { return internal_size; }
_FORCE_INLINE_ Size2i get_target_size() const { return target_size; } _FORCE_INLINE_ Size2i get_target_size() const { return target_size; }
_FORCE_INLINE_ RS::ViewportScaling3DMode get_scaling_3d_mode() const { return scaling_3d_mode; }
_FORCE_INLINE_ float get_fsr_sharpness() const { return fsr_sharpness; } _FORCE_INLINE_ float get_fsr_sharpness() const { return fsr_sharpness; }
_FORCE_INLINE_ RS::ViewportMSAA get_msaa_3d() const { return msaa_3d; } _FORCE_INLINE_ RS::ViewportMSAA get_msaa_3d() const { return msaa_3d; }
_FORCE_INLINE_ RS::ViewportScreenSpaceAA get_screen_space_aa() const { return screen_space_aa; } _FORCE_INLINE_ RS::ViewportScreenSpaceAA get_screen_space_aa() const { return screen_space_aa; }

View File

@ -115,9 +115,8 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) {
if (p_viewport->size.width == 0 || p_viewport->size.height == 0) { if (p_viewport->size.width == 0 || p_viewport->size.height == 0) {
p_viewport->render_buffers.unref(); p_viewport->render_buffers.unref();
} else { } else {
const float scaling_3d_scale = p_viewport->scaling_3d_scale; float scaling_3d_scale = p_viewport->scaling_3d_scale;
RS::ViewportScaling3DMode scaling_3d_mode = p_viewport->scaling_3d_mode; RS::ViewportScaling3DMode scaling_3d_mode = p_viewport->scaling_3d_mode;
bool scaling_enabled = true;
if ((scaling_3d_mode == RS::VIEWPORT_SCALING_3D_MODE_FSR) && (scaling_3d_scale > 1.0)) { if ((scaling_3d_mode == RS::VIEWPORT_SCALING_3D_MODE_FSR) && (scaling_3d_scale > 1.0)) {
// FSR is not designed for downsampling. // FSR is not designed for downsampling.
@ -133,7 +132,7 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) {
} }
if (scaling_3d_scale == 1.0) { if (scaling_3d_scale == 1.0) {
scaling_enabled = false; scaling_3d_mode = RS::VIEWPORT_SCALING_3D_MODE_OFF;
} }
int width; int width;
@ -141,36 +140,37 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) {
int render_width; int render_width;
int render_height; int render_height;
if (scaling_enabled) { switch (scaling_3d_mode) {
switch (scaling_3d_mode) { case RS::VIEWPORT_SCALING_3D_MODE_BILINEAR:
case RS::VIEWPORT_SCALING_3D_MODE_BILINEAR: // Clamp 3D rendering resolution to reasonable values supported on most hardware.
// Clamp 3D rendering resolution to reasonable values supported on most hardware. // This prevents freezing the engine or outright crashing on lower-end GPUs.
// This prevents freezing the engine or outright crashing on lower-end GPUs. width = CLAMP(p_viewport->size.width * scaling_3d_scale, 1, 16384);
width = CLAMP(p_viewport->size.width * scaling_3d_scale, 1, 16384); height = CLAMP(p_viewport->size.height * scaling_3d_scale, 1, 16384);
height = CLAMP(p_viewport->size.height * scaling_3d_scale, 1, 16384); render_width = width;
render_width = width; render_height = height;
render_height = height; break;
break; case RS::VIEWPORT_SCALING_3D_MODE_FSR:
case RS::VIEWPORT_SCALING_3D_MODE_FSR: width = p_viewport->size.width;
width = p_viewport->size.width; height = p_viewport->size.height;
height = p_viewport->size.height; render_width = MAX(width * scaling_3d_scale, 1.0); // width / (width * scaling)
render_width = MAX(width * scaling_3d_scale, 1.0); // width / (width * scaling) render_height = MAX(height * scaling_3d_scale, 1.0);
render_height = MAX(height * scaling_3d_scale, 1.0); break;
break; case RS::VIEWPORT_SCALING_3D_MODE_OFF:
default: width = p_viewport->size.width;
// This is an unknown mode. height = p_viewport->size.height;
WARN_PRINT_ONCE(vformat("Unknown scaling mode: %d. Disabling 3D resolution scaling.", scaling_3d_mode)); render_width = width;
width = p_viewport->size.width; render_height = height;
height = p_viewport->size.height; break;
render_width = width; default:
render_height = height; // This is an unknown mode.
break; WARN_PRINT_ONCE(vformat("Unknown scaling mode: %d. Disabling 3D resolution scaling.", scaling_3d_mode));
} scaling_3d_mode = RS::VIEWPORT_SCALING_3D_MODE_OFF;
} else { scaling_3d_scale = 1.0;
width = p_viewport->size.width; width = p_viewport->size.width;
height = p_viewport->size.height; height = p_viewport->size.height;
render_width = width; render_width = width;
render_height = height; render_height = height;
break;
} }
p_viewport->internal_size = Size2(render_width, render_height); p_viewport->internal_size = Size2(render_width, render_height);
@ -179,7 +179,7 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) {
// to compensate for the loss of sharpness. // to compensate for the loss of sharpness.
const float texture_mipmap_bias = log2f(MIN(scaling_3d_scale, 1.0)) + p_viewport->texture_mipmap_bias; const float texture_mipmap_bias = log2f(MIN(scaling_3d_scale, 1.0)) + p_viewport->texture_mipmap_bias;
p_viewport->render_buffers->configure(p_viewport->render_target, Size2i(render_width, render_height), Size2(width, height), p_viewport->fsr_sharpness, texture_mipmap_bias, p_viewport->msaa_3d, p_viewport->screen_space_aa, p_viewport->use_taa, p_viewport->use_debanding, p_viewport->view_count); p_viewport->render_buffers->configure(p_viewport->render_target, Size2i(render_width, render_height), Size2(width, height), scaling_3d_mode, p_viewport->fsr_sharpness, texture_mipmap_bias, p_viewport->msaa_3d, p_viewport->screen_space_aa, p_viewport->use_taa, p_viewport->use_debanding, p_viewport->view_count);
} }
} }
} }

View File

@ -34,8 +34,8 @@ void RenderSceneBuffers::_bind_methods() {
ClassDB::bind_method(D_METHOD("configure", "render_target", "internal_size", "target_size", "fsr_sharpness", "texture_mipmap_bias", "msaa", "screen_space_aa", "use_taa", "use_debanding", "view_count"), &RenderSceneBuffers::configure); ClassDB::bind_method(D_METHOD("configure", "render_target", "internal_size", "target_size", "fsr_sharpness", "texture_mipmap_bias", "msaa", "screen_space_aa", "use_taa", "use_debanding", "view_count"), &RenderSceneBuffers::configure);
} }
void RenderSceneBuffers::configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) { void RenderSceneBuffers::configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, RS::ViewportScaling3DMode p_scaling_3d_mode, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) {
GDVIRTUAL_CALL(_configure, p_render_target, p_internal_size, p_target_size, p_fsr_sharpness, p_texture_mipmap_bias, p_msaa, p_screen_space_aa, p_use_taa, p_use_debanding, p_view_count); GDVIRTUAL_CALL(_configure, p_render_target, p_internal_size, p_target_size, p_scaling_3d_mode, p_fsr_sharpness, p_texture_mipmap_bias, p_msaa, p_screen_space_aa, p_use_taa, p_use_debanding, p_view_count);
}; };
void RenderSceneBuffers::set_fsr_sharpness(float p_fsr_sharpness) { void RenderSceneBuffers::set_fsr_sharpness(float p_fsr_sharpness) {

View File

@ -40,7 +40,7 @@ class RenderSceneBuffers : public RefCounted {
protected: protected:
static void _bind_methods(); static void _bind_methods();
GDVIRTUAL10(_configure, RID, Size2i, Size2i, float, float, RS::ViewportMSAA, RenderingServer::ViewportScreenSpaceAA, bool, bool, uint32_t) GDVIRTUAL11(_configure, RID, Size2i, Size2i, RS::ViewportScaling3DMode, float, float, RS::ViewportMSAA, RenderingServer::ViewportScreenSpaceAA, bool, bool, uint32_t)
GDVIRTUAL1(_set_fsr_sharpness, float) GDVIRTUAL1(_set_fsr_sharpness, float)
GDVIRTUAL1(_set_texture_mipmap_bias, float) GDVIRTUAL1(_set_texture_mipmap_bias, float)
GDVIRTUAL1(_set_use_debanding, bool) GDVIRTUAL1(_set_use_debanding, bool)
@ -49,7 +49,7 @@ public:
RenderSceneBuffers(){}; RenderSceneBuffers(){};
virtual ~RenderSceneBuffers(){}; virtual ~RenderSceneBuffers(){};
virtual void configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa_3d, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count); virtual void configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, RS::ViewportScaling3DMode p_scaling_3d_mode, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa_3d, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count);
// for those settings that are unlikely to require buffers to be recreated, we'll add setters // for those settings that are unlikely to require buffers to be recreated, we'll add setters
virtual void set_fsr_sharpness(float p_fsr_sharpness); virtual void set_fsr_sharpness(float p_fsr_sharpness);

View File

@ -802,7 +802,8 @@ public:
enum ViewportScaling3DMode { enum ViewportScaling3DMode {
VIEWPORT_SCALING_3D_MODE_BILINEAR, VIEWPORT_SCALING_3D_MODE_BILINEAR,
VIEWPORT_SCALING_3D_MODE_FSR, VIEWPORT_SCALING_3D_MODE_FSR,
VIEWPORT_SCALING_3D_MODE_MAX VIEWPORT_SCALING_3D_MODE_MAX,
VIEWPORT_SCALING_3D_MODE_OFF = 255, // for internal use only
}; };
virtual void viewport_set_use_xr(RID p_viewport, bool p_use_xr) = 0; virtual void viewport_set_use_xr(RID p_viewport, bool p_use_xr) = 0;