OpenXR: Allow using Vulkan subsampled images with foveated rendered
This commit is contained in:
1 parent
bfbe95e510
commit
4d218bdeb7
25 files changed
+291
-15
No files matched your search
@@ -3617,6 +3617,10 @@
|
||||
Applied foveation level if supported.
|
||||
[b]Note:[/b] On platforms other than Android, if [member rendering/anti_aliasing/quality/msaa_3d] is enabled, this feature will be disabled.
|
||||
</member>
|
||||
<member name="xr/openxr/foveation_with_subsampled_images" type="bool" setter="" getter="" default="false">
|
||||
If [code]true[/code] and foveation is also enabled, subsampled images will be used on Vulkan. This can improve the performance gain from foveated rendering, especially when using high foveation levels.
|
||||
[b]Note:[/b]: Using subsampled images is incompatible with many screen-space rendering features or post-processing effects like FXAA or glow. If any such effects are enabled, subsampled images will automatically be disabled and a warning shown in the log.
|
||||
</member>
|
||||
<member name="xr/openxr/reference_space" type="int" setter="" getter="" default=""1"">
|
||||
Specify the default reference space.
|
||||
</member>
|
||||
|
||||
@@ -740,6 +740,12 @@ public:
|
||||
virtual void render_target_set_render_region(RID p_render_target, const Rect2i &p_render_region) override;
|
||||
virtual Rect2i render_target_get_render_region(RID p_render_target) const override;
|
||||
|
||||
virtual void render_target_set_subsampled_enabled(RID p_render_target, bool p_enabled) override {}
|
||||
virtual bool render_target_is_subsampled_enabled(RID p_render_target) const override { return false; }
|
||||
|
||||
virtual void render_target_set_subsampled_allowed(RID p_render_target, bool p_allowed) override {}
|
||||
virtual bool render_target_is_subsampled_allowed(RID p_render_target) const override { return false; }
|
||||
|
||||
virtual RID render_target_get_texture(RID p_render_target) override;
|
||||
|
||||
virtual void render_target_set_velocity_target_size(RID p_render_target, const Size2i &p_target_size) override;
|
||||
|
||||
@@ -569,6 +569,7 @@ Error RenderingDeviceDriverVulkan::_initialize_device_extensions() {
|
||||
_register_requested_device_extension(VK_KHR_MULTIVIEW_EXTENSION_NAME, false);
|
||||
_register_requested_device_extension(VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME, false);
|
||||
_register_requested_device_extension(VK_EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME, false);
|
||||
_register_requested_device_extension(VK_EXT_FRAGMENT_DENSITY_MAP_2_EXTENSION_NAME, false);
|
||||
_register_requested_device_extension(VK_QCOM_FRAGMENT_DENSITY_MAP_OFFSET_EXTENSION_NAME, false);
|
||||
_register_requested_device_extension(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME, false);
|
||||
_register_requested_device_extension(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME, false);
|
||||
@@ -2194,6 +2195,11 @@ RDD::TextureID RenderingDeviceDriverVulkan::texture_create(const TextureFormat &
|
||||
create_info.flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT;
|
||||
}*/
|
||||
|
||||
bool use_subsampled_images = VulkanHooks::get_singleton() && VulkanHooks::get_singleton()->use_subsampled_images();
|
||||
if (fdm_capabilities.attachment_supported && use_subsampled_images && p_format.is_subsampled && (p_format.usage_bits & (TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | TEXTURE_USAGE_INPUT_ATTACHMENT_BIT | TEXTURE_USAGE_DEPTH_RESOLVE_ATTACHMENT_BIT))) {
|
||||
create_info.flags |= VK_IMAGE_CREATE_SUBSAMPLED_BIT_EXT;
|
||||
}
|
||||
|
||||
if (fdm_capabilities.offset_supported && (p_format.usage_bits & (TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | TEXTURE_USAGE_INPUT_ATTACHMENT_BIT | TEXTURE_USAGE_DEPTH_RESOLVE_ATTACHMENT_BIT | TEXTURE_USAGE_VRS_ATTACHMENT_BIT))) {
|
||||
create_info.flags |= VK_IMAGE_CREATE_FRAGMENT_DENSITY_MAP_OFFSET_BIT_QCOM;
|
||||
}
|
||||
@@ -2353,6 +2359,7 @@ RDD::TextureID RenderingDeviceDriverVulkan::texture_create(const TextureFormat &
|
||||
tex_info->vk_create_info = create_info;
|
||||
tex_info->vk_view_create_info = image_view_create_info;
|
||||
tex_info->allocation.handle = allocation;
|
||||
tex_info->is_subsampled = (create_info.flags & VK_IMAGE_CREATE_SUBSAMPLED_BIT_EXT) != 0;
|
||||
#ifdef DEBUG_ENABLED
|
||||
tex_info->transient = (p_format.usage_bits & TEXTURE_USAGE_TRANSIENT_BIT) != 0;
|
||||
#endif
|
||||
@@ -5108,6 +5115,11 @@ void RenderingDeviceDriverVulkan::command_clear_depth_stencil_texture(CommandBuf
|
||||
void RenderingDeviceDriverVulkan::command_copy_buffer_to_texture(CommandBufferID p_cmd_buffer, BufferID p_src_buffer, TextureID p_dst_texture, TextureLayout p_dst_texture_layout, VectorView<BufferTextureCopyRegion> p_regions) {
|
||||
const TextureInfo *tex_info = (const TextureInfo *)p_dst_texture.id;
|
||||
|
||||
if (tex_info->is_subsampled) {
|
||||
// Subsampled images can't be copied into, only used as attachments to a framebuffer.
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t pixel_size = get_image_format_pixel_size(tex_info->rd_format);
|
||||
uint32_t block_size = get_compressed_image_format_block_byte_size(tex_info->rd_format);
|
||||
uint32_t block_w, block_h;
|
||||
|
||||
@@ -275,6 +275,7 @@ public:
|
||||
VmaAllocation handle = nullptr;
|
||||
VmaAllocationInfo info = {};
|
||||
} allocation; // All 0/null if just a view.
|
||||
bool is_subsampled = false;
|
||||
#ifdef DEBUG_ENABLED
|
||||
bool created_from_extension = false;
|
||||
bool transient = false;
|
||||
|
||||
@@ -47,5 +47,6 @@ public:
|
||||
virtual void set_direct_queue_family_and_index(uint32_t p_queue_family_index, uint32_t p_queue_index) = 0;
|
||||
virtual bool use_fragment_density_offsets() = 0;
|
||||
virtual void get_fragment_density_offsets(LocalVector<VkOffset2D> &r_offsets, const Vector2i &p_granularity) = 0;
|
||||
virtual bool use_subsampled_images() = 0;
|
||||
static VulkanHooks *get_singleton() { return singleton; }
|
||||
};
|
||||
@@ -2827,6 +2827,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
|
||||
GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "xr/openxr/environment_blend_mode", PROPERTY_HINT_ENUM, "Opaque,Additive,Alpha"), "0");
|
||||
GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "xr/openxr/foveation_level", PROPERTY_HINT_ENUM, "Off,Low,Medium,High"), "0");
|
||||
GLOBAL_DEF_BASIC("xr/openxr/foveation_dynamic", false);
|
||||
GLOBAL_DEF_BASIC("xr/openxr/foveation_with_subsampled_images", false);
|
||||
|
||||
GLOBAL_DEF_BASIC("xr/openxr/submit_depth_buffer", false);
|
||||
GLOBAL_DEF_BASIC("xr/openxr/startup_alert", true);
|
||||
|
||||
@@ -176,11 +176,12 @@
|
||||
</member>
|
||||
<member name="foveation_dynamic" type="bool" setter="set_foveation_dynamic" getter="get_foveation_dynamic" default="false">
|
||||
If [code]true[/code], enables dynamic foveation adjustment. The interface must be initialized before this is accessible. If enabled, foveation will automatically be adjusted between low and [member foveation_level].
|
||||
[b]Note:[/b] Only works on the Compatibility renderer.
|
||||
</member>
|
||||
<member name="foveation_level" type="int" setter="set_foveation_level" getter="get_foveation_level" default="0">
|
||||
The foveation level, from [code]0[/code] (off) to [code]3[/code] (high). The interface must be initialized before this is accessible.
|
||||
[b]Note:[/b] Only works on the Compatibility renderer.
|
||||
</member>
|
||||
<member name="foveation_with_subsampled_images" type="bool" setter="set_foveation_with_subsampled_images" getter="get_foveation_with_subsampled_images" default="false">
|
||||
If [code]true[/code], enables subsampled images with foveation, which can provide a performance boost on Vulkan.
|
||||
</member>
|
||||
<member name="render_target_size_multiplier" type="float" setter="set_render_target_size_multiplier" getter="get_render_target_size_multiplier" default="1.0">
|
||||
The render size multiplier for the current HMD. Must be set before the interface has been initialized.
|
||||
|
||||
@@ -51,9 +51,13 @@ OpenXRFBFoveationExtension::OpenXRFBFoveationExtension(const String &p_rendering
|
||||
if (fov_level >= 0 && fov_level < 4) {
|
||||
foveation_level = XrFoveationLevelFB(fov_level);
|
||||
}
|
||||
|
||||
bool fov_dyn = GLOBAL_GET("xr/openxr/foveation_dynamic");
|
||||
foveation_dynamic = fov_dyn ? XR_FOVEATION_DYNAMIC_LEVEL_ENABLED_FB : XR_FOVEATION_DYNAMIC_DISABLED_FB;
|
||||
|
||||
foveation_with_subsampled_images_enabled = GLOBAL_GET("xr/openxr/foveation_with_subsampled_images");
|
||||
foveation_with_subsampled_images_active = foveation_with_subsampled_images_enabled;
|
||||
|
||||
swapchain_create_info_foveation_fb.type = XR_TYPE_SWAPCHAIN_CREATE_INFO_FOVEATION_FB;
|
||||
swapchain_create_info_foveation_fb.next = nullptr;
|
||||
swapchain_create_info_foveation_fb.flags = 0;
|
||||
@@ -69,7 +73,7 @@ OpenXRFBFoveationExtension::OpenXRFBFoveationExtension(const String &p_rendering
|
||||
#ifdef VULKAN_ENABLED
|
||||
meta_vulkan_swapchain_create_info.type = XR_TYPE_VULKAN_SWAPCHAIN_CREATE_INFO_META;
|
||||
meta_vulkan_swapchain_create_info.next = nullptr;
|
||||
meta_vulkan_swapchain_create_info.additionalCreateFlags = VK_IMAGE_CREATE_FRAGMENT_DENSITY_MAP_OFFSET_BIT_QCOM;
|
||||
meta_vulkan_swapchain_create_info.additionalCreateFlags = 0;
|
||||
meta_vulkan_swapchain_create_info.additionalUsageFlags = 0;
|
||||
#endif
|
||||
|
||||
@@ -150,7 +154,15 @@ void *OpenXRFBFoveationExtension::set_swapchain_create_info_and_get_next_pointer
|
||||
next = &swapchain_create_info_foveation_fb;
|
||||
|
||||
#ifdef VULKAN_ENABLED
|
||||
if (meta_foveation_eye_tracked_ext && meta_vulkan_swapchain_create_info_ext && meta_foveation_eye_tracked_properties.supportsFoveationEyeTracked) {
|
||||
if (meta_vulkan_swapchain_create_info_ext) {
|
||||
meta_vulkan_swapchain_create_info.additionalCreateFlags = 0;
|
||||
if (meta_foveation_eye_tracked_ext && meta_foveation_eye_tracked_properties.supportsFoveationEyeTracked) {
|
||||
meta_vulkan_swapchain_create_info.additionalCreateFlags |= VK_IMAGE_CREATE_FRAGMENT_DENSITY_MAP_OFFSET_BIT_QCOM;
|
||||
}
|
||||
if (foveation_with_subsampled_images_enabled && foveation_with_subsampled_images_active) {
|
||||
meta_vulkan_swapchain_create_info.additionalCreateFlags |= VK_IMAGE_CREATE_SUBSAMPLED_BIT_EXT;
|
||||
}
|
||||
|
||||
meta_vulkan_swapchain_create_info.next = next;
|
||||
next = &meta_vulkan_swapchain_create_info;
|
||||
}
|
||||
@@ -226,6 +238,18 @@ void OpenXRFBFoveationExtension::get_fragment_density_offsets(LocalVector<Vector
|
||||
}
|
||||
}
|
||||
|
||||
void OpenXRFBFoveationExtension::set_foveation_with_subsampled_images_enabled(bool p_enabled) {
|
||||
foveation_with_subsampled_images_enabled = p_enabled;
|
||||
}
|
||||
|
||||
bool OpenXRFBFoveationExtension::is_foveation_with_subsampled_images_enabled() const {
|
||||
return is_enabled() && meta_vulkan_swapchain_create_info_ext && foveation_with_subsampled_images_enabled;
|
||||
}
|
||||
|
||||
void OpenXRFBFoveationExtension::set_foveation_with_subsampled_images_active(bool p_active) {
|
||||
foveation_with_subsampled_images_active = p_active;
|
||||
}
|
||||
|
||||
void OpenXRFBFoveationExtension::_update_profile_rt() {
|
||||
// Must be called from rendering thread!
|
||||
ERR_NOT_ON_RENDER_THREAD;
|
||||
|
||||
@@ -75,6 +75,11 @@ public:
|
||||
bool is_foveation_eye_tracked_enabled() const;
|
||||
void get_fragment_density_offsets(LocalVector<Vector2i> &r_offsets);
|
||||
|
||||
void set_foveation_with_subsampled_images_enabled(bool p_enabled);
|
||||
bool is_foveation_with_subsampled_images_enabled() const;
|
||||
|
||||
void set_foveation_with_subsampled_images_active(bool p_active);
|
||||
|
||||
private:
|
||||
static OpenXRFBFoveationExtension *singleton;
|
||||
|
||||
@@ -89,6 +94,8 @@ private:
|
||||
// Configuration
|
||||
XrFoveationLevelFB foveation_level = XR_FOVEATION_LEVEL_NONE_FB;
|
||||
XrFoveationDynamicFB foveation_dynamic = XR_FOVEATION_DYNAMIC_DISABLED_FB;
|
||||
bool foveation_with_subsampled_images_enabled = false;
|
||||
bool foveation_with_subsampled_images_active = false;
|
||||
|
||||
void _update_profile_rt();
|
||||
|
||||
|
||||
@@ -229,6 +229,15 @@ void OpenXRVulkanExtension::get_fragment_density_offsets(LocalVector<VkOffset2D>
|
||||
}
|
||||
}
|
||||
|
||||
bool OpenXRVulkanExtension::use_subsampled_images() {
|
||||
OpenXRFBFoveationExtension *fb_foveation = OpenXRFBFoveationExtension::get_singleton();
|
||||
if (fb_foveation == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return fb_foveation->is_foveation_with_subsampled_images_enabled();
|
||||
}
|
||||
|
||||
XrGraphicsBindingVulkanKHR OpenXRVulkanExtension::graphics_binding_vulkan;
|
||||
|
||||
void *OpenXRVulkanExtension::set_session_create_and_get_next_pointer(void *p_next_pointer) {
|
||||
|
||||
@@ -54,6 +54,7 @@ public:
|
||||
virtual bool get_physical_device(VkPhysicalDevice *r_device) override final;
|
||||
virtual bool create_vulkan_device(const VkDeviceCreateInfo *p_device_create_info, VkDevice *r_device) override final;
|
||||
virtual void set_direct_queue_family_and_index(uint32_t p_queue_family_index, uint32_t p_queue_index) override final;
|
||||
virtual bool use_subsampled_images() override final;
|
||||
virtual bool use_fragment_density_offsets() override final;
|
||||
virtual void get_fragment_density_offsets(LocalVector<VkOffset2D> &r_offets, const Vector2i &p_granularity) override final;
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#include "core/profiling/profiling.h"
|
||||
#include "core/version.h"
|
||||
#include "servers/rendering/rendering_server.h"
|
||||
#include "servers/rendering/rendering_server_globals.h"
|
||||
|
||||
#include "openxr_platform_inc.h"
|
||||
|
||||
@@ -2430,15 +2431,6 @@ void OpenXRAPI::pre_render() {
|
||||
// Process any swapchains that were queued to be freed
|
||||
OpenXRSwapChainInfo::free_queued();
|
||||
|
||||
Size2i swapchain_size = get_recommended_target_size();
|
||||
if (swapchain_size != render_state.main_swapchain_size) {
|
||||
// Out with the old.
|
||||
free_main_swapchains();
|
||||
|
||||
// In with the new.
|
||||
create_main_swapchains(swapchain_size);
|
||||
}
|
||||
|
||||
void *view_locate_info_next_pointer = nullptr;
|
||||
for (OpenXRExtensionWrapper *extension : frame_info_extensions) {
|
||||
void *np = extension->set_view_locate_info_and_get_next_pointer(view_locate_info_next_pointer);
|
||||
@@ -2526,6 +2518,39 @@ bool OpenXRAPI::pre_draw_viewport(RID p_render_target) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Size2i swapchain_size = get_recommended_target_size();
|
||||
bool should_recreate_swapchain = (swapchain_size != render_state.main_swapchain_size);
|
||||
|
||||
OpenXRFBFoveationExtension *fov_ext = OpenXRFBFoveationExtension::get_singleton();
|
||||
if (fov_ext) {
|
||||
bool subsampled_images_enabled = fov_ext->is_foveation_with_subsampled_images_enabled();
|
||||
|
||||
// Mark subsampled images as enabled on the render target (so we try to use them).
|
||||
RSG::texture_storage->render_target_set_subsampled_enabled(p_render_target, subsampled_images_enabled);
|
||||
|
||||
// But check if they are "allowed", because they may not work if we are using
|
||||
// any incompatible rendering features.
|
||||
bool subsampled_images_allowed = RSG::texture_storage->render_target_is_subsampled_allowed(p_render_target);
|
||||
fov_ext->set_foveation_with_subsampled_images_active(subsampled_images_allowed);
|
||||
|
||||
bool use_subsampled_images = subsampled_images_enabled && subsampled_images_allowed;
|
||||
if (render_state.use_subsampled_images != use_subsampled_images) {
|
||||
render_state.use_subsampled_images = use_subsampled_images;
|
||||
if (!subsampled_images_allowed) {
|
||||
WARN_PRINT("Foveation with subsampled images was enabled, but rendering features are in use that have forced it to be disabled.");
|
||||
}
|
||||
should_recreate_swapchain = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (should_recreate_swapchain) {
|
||||
// Out with the old.
|
||||
free_main_swapchains();
|
||||
|
||||
// In with the new.
|
||||
create_main_swapchains(swapchain_size);
|
||||
}
|
||||
|
||||
// Acquire our images
|
||||
for (int i = 0; i < OPENXR_SWAPCHAIN_MAX; i++) {
|
||||
if (!render_state.main_swapchains[i].is_image_acquired() && render_state.main_swapchains[i].get_swapchain() != XR_NULL_HANDLE) {
|
||||
@@ -2879,6 +2904,21 @@ void OpenXRAPI::set_foveation_dynamic(bool p_foveation_dynamic) {
|
||||
}
|
||||
}
|
||||
|
||||
bool OpenXRAPI::get_foveation_with_subsampled_images() const {
|
||||
OpenXRFBFoveationExtension *fov_ext = OpenXRFBFoveationExtension::get_singleton();
|
||||
if (fov_ext != nullptr) {
|
||||
return fov_ext->is_foveation_with_subsampled_images_enabled();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void OpenXRAPI::set_foveation_with_subsampled_images(bool p_enabled) {
|
||||
OpenXRFBFoveationExtension *fov_ext = OpenXRFBFoveationExtension::get_singleton();
|
||||
if (fov_ext != nullptr) {
|
||||
fov_ext->set_foveation_with_subsampled_images_enabled(p_enabled);
|
||||
}
|
||||
}
|
||||
|
||||
Size2 OpenXRAPI::get_play_space_bounds() const {
|
||||
Size2 ret;
|
||||
|
||||
|
||||
@@ -364,6 +364,7 @@ private:
|
||||
LocalVector<XrCompositionLayerProjectionView> projection_views;
|
||||
LocalVector<XrCompositionLayerDepthInfoKHR> depth_views; // Only used by Composition Layer Depth Extension if available
|
||||
bool submit_depth_buffer = false; // if set to true we submit depth buffers to OpenXR if a suitable extension is enabled.
|
||||
bool use_subsampled_images = true; // We need to default to true for the warning to be shown if we fallback immediately at startup.
|
||||
bool view_pose_valid = false;
|
||||
|
||||
double z_near = 0.0;
|
||||
@@ -524,6 +525,9 @@ public:
|
||||
bool get_foveation_dynamic() const;
|
||||
void set_foveation_dynamic(bool p_foveation_dynamic);
|
||||
|
||||
bool get_foveation_with_subsampled_images() const;
|
||||
void set_foveation_with_subsampled_images(bool p_enabled);
|
||||
|
||||
// Play space.
|
||||
Size2 get_play_space_bounds() const;
|
||||
|
||||
|
||||
@@ -89,6 +89,10 @@ void OpenXRInterface::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_foveation_dynamic", "foveation_dynamic"), &OpenXRInterface::set_foveation_dynamic);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "foveation_dynamic"), "set_foveation_dynamic", "get_foveation_dynamic");
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_foveation_with_subsampled_images"), &OpenXRInterface::get_foveation_with_subsampled_images);
|
||||
ClassDB::bind_method(D_METHOD("set_foveation_with_subsampled_images", "enabled"), &OpenXRInterface::set_foveation_with_subsampled_images);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "foveation_with_subsampled_images"), "set_foveation_with_subsampled_images", "get_foveation_with_subsampled_images");
|
||||
|
||||
// Action sets
|
||||
ClassDB::bind_method(D_METHOD("is_action_set_active", "name"), &OpenXRInterface::is_action_set_active);
|
||||
ClassDB::bind_method(D_METHOD("set_action_set_active", "name", "active"), &OpenXRInterface::set_action_set_active);
|
||||
@@ -1025,6 +1029,22 @@ void OpenXRInterface::set_foveation_dynamic(bool p_foveation_dynamic) {
|
||||
}
|
||||
}
|
||||
|
||||
bool OpenXRInterface::get_foveation_with_subsampled_images() const {
|
||||
if (openxr_api == nullptr) {
|
||||
return false;
|
||||
} else {
|
||||
return openxr_api->get_foveation_with_subsampled_images();
|
||||
}
|
||||
}
|
||||
|
||||
void OpenXRInterface::set_foveation_with_subsampled_images(bool p_enabled) {
|
||||
if (openxr_api == nullptr) {
|
||||
return;
|
||||
} else {
|
||||
openxr_api->set_foveation_with_subsampled_images(p_enabled);
|
||||
}
|
||||
}
|
||||
|
||||
Size2 OpenXRInterface::get_render_target_size() {
|
||||
if (openxr_api == nullptr) {
|
||||
return Size2();
|
||||
|
||||
@@ -171,6 +171,9 @@ public:
|
||||
bool get_foveation_dynamic() const;
|
||||
void set_foveation_dynamic(bool p_foveation_dynamic);
|
||||
|
||||
bool get_foveation_with_subsampled_images() const;
|
||||
void set_foveation_with_subsampled_images(bool p_enabled);
|
||||
|
||||
float get_vrs_min_radius() const;
|
||||
void set_vrs_min_radius(float p_vrs_min_radius);
|
||||
|
||||
|
||||
@@ -215,6 +215,12 @@ public:
|
||||
virtual void render_target_set_render_region(RID p_render_target, const Rect2i &p_render_region) override {}
|
||||
virtual Rect2i render_target_get_render_region(RID p_render_target) const override { return Rect2i(); }
|
||||
|
||||
virtual void render_target_set_subsampled_enabled(RID p_render_target, bool p_enabled) override {}
|
||||
virtual bool render_target_is_subsampled_enabled(RID p_render_target) const override { return false; }
|
||||
|
||||
virtual void render_target_set_subsampled_allowed(RID p_render_target, bool p_allowed) override {}
|
||||
virtual bool render_target_is_subsampled_allowed(RID p_render_target) const override { return false; }
|
||||
|
||||
virtual RID render_target_get_texture(RID p_render_target) override { return RID(); }
|
||||
|
||||
virtual void render_target_set_velocity_target_size(RID p_render_target, const Size2i &p_target_size) override {}
|
||||
|
||||
@@ -232,8 +232,13 @@ RID RenderForwardMobile::RenderBufferDataForwardMobile::get_color_fbs(Framebuffe
|
||||
Vector<RID> textures;
|
||||
int color_buffer_id = 0;
|
||||
int depth_buffer_id = 1;
|
||||
textures.push_back(use_msaa ? render_buffers->get_color_msaa() : render_buffers->get_internal_texture()); // 0 - color buffer.
|
||||
textures.push_back(use_msaa ? render_buffers->get_depth_msaa() : render_buffers->get_depth_texture()); // 1 - depth buffer.
|
||||
if (p_config_type == FB_CONFIG_RENDER_AND_POST_PASS && vrs_texture.is_valid() && texture_storage->render_target_is_subsampled_enabled(render_buffers->get_render_target())) {
|
||||
textures.push_back(use_msaa ? render_buffers->get_color_msaa_subsampled() : render_buffers->get_color_subsampled()); // 0 - color buffer.
|
||||
textures.push_back(use_msaa ? render_buffers->get_depth_msaa_subsampled() : render_buffers->get_depth_subsampled()); // 1 - depth buffer.
|
||||
} else {
|
||||
textures.push_back(use_msaa ? render_buffers->get_color_msaa() : render_buffers->get_internal_texture()); // 0 - color buffer.
|
||||
textures.push_back(use_msaa ? render_buffers->get_depth_msaa() : render_buffers->get_depth_texture()); // 1 - depth buffer.
|
||||
}
|
||||
if (vrs_texture.is_valid()) {
|
||||
textures.push_back(vrs_texture); // 2 - vrs texture.
|
||||
}
|
||||
@@ -997,6 +1002,9 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
|
||||
ERR_FAIL(); //bug?
|
||||
}
|
||||
|
||||
// Set subsampled images as not allowed on this render target, if we are using incompatible rendering features.
|
||||
texture_storage->render_target_set_subsampled_allowed(render_target, using_subpass_post_process);
|
||||
|
||||
if (p_render_data->scene_data->view_count > 1) {
|
||||
global_pipeline_data_required.use_multiview = true;
|
||||
}
|
||||
|
||||
@@ -641,6 +641,80 @@ RID RenderSceneBuffersRD::get_depth_texture(const uint32_t p_layer) {
|
||||
}
|
||||
}
|
||||
|
||||
// Subsampled textures.
|
||||
|
||||
RID RenderSceneBuffersRD::get_color_subsampled() {
|
||||
const bool use_msaa = (msaa_3d != RSE::VIEWPORT_MSAA_DISABLED);
|
||||
|
||||
RD::TextureFormat tf;
|
||||
tf.format = get_base_data_format();
|
||||
if (view_count > 1) {
|
||||
tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
|
||||
}
|
||||
tf.width = internal_size.x;
|
||||
tf.height = internal_size.y;
|
||||
tf.array_layers = view_count;
|
||||
tf.usage_bits = get_color_usage_bits(use_msaa, false, can_be_storage);
|
||||
tf.is_subsampled = true;
|
||||
|
||||
return create_texture_from_format(RB_SCOPE_BUFFERS, RB_TEX_COLOR_SUBSAMPLED, tf);
|
||||
}
|
||||
|
||||
RID RenderSceneBuffersRD::get_color_msaa_subsampled() {
|
||||
ERR_FAIL_COND_V(msaa_3d == RSE::VIEWPORT_MSAA_DISABLED, RID());
|
||||
|
||||
RD::TextureFormat tf;
|
||||
tf.format = get_base_data_format();
|
||||
if (view_count > 1) {
|
||||
tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
|
||||
}
|
||||
tf.width = internal_size.x;
|
||||
tf.height = internal_size.y;
|
||||
tf.array_layers = view_count;
|
||||
tf.samples = msaa_to_samples(msaa_3d);
|
||||
tf.usage_bits = get_color_usage_bits(false, true, can_be_storage);
|
||||
tf.is_discardable = true;
|
||||
tf.is_subsampled = true;
|
||||
|
||||
return create_texture_from_format(RB_SCOPE_BUFFERS, RB_TEX_COLOR_MSAA_SUBSAMPLED, tf);
|
||||
}
|
||||
|
||||
RID RenderSceneBuffersRD::get_depth_subsampled() {
|
||||
const bool use_msaa = (msaa_3d != RSE::VIEWPORT_MSAA_DISABLED);
|
||||
|
||||
RD::TextureFormat tf;
|
||||
tf.format = get_depth_format(use_msaa, false, can_be_storage);
|
||||
if (view_count > 1) {
|
||||
tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
|
||||
}
|
||||
tf.width = internal_size.x;
|
||||
tf.height = internal_size.y;
|
||||
tf.array_layers = view_count;
|
||||
tf.usage_bits = get_depth_usage_bits(use_msaa, false, can_be_storage);
|
||||
tf.is_subsampled = true;
|
||||
|
||||
return create_texture_from_format(RB_SCOPE_BUFFERS, RB_TEX_DEPTH_SUBSAMPLED, tf);
|
||||
}
|
||||
|
||||
RID RenderSceneBuffersRD::get_depth_msaa_subsampled() {
|
||||
ERR_FAIL_COND_V(msaa_3d == RSE::VIEWPORT_MSAA_DISABLED, RID());
|
||||
|
||||
RD::TextureFormat tf;
|
||||
tf.format = get_depth_format(false, true, can_be_storage);
|
||||
if (view_count > 1) {
|
||||
tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
|
||||
}
|
||||
tf.width = internal_size.x;
|
||||
tf.height = internal_size.y;
|
||||
tf.array_layers = view_count;
|
||||
tf.samples = msaa_to_samples(msaa_3d);
|
||||
tf.usage_bits = get_depth_usage_bits(false, true, can_be_storage);
|
||||
tf.is_discardable = true;
|
||||
tf.is_subsampled = true;
|
||||
|
||||
return create_texture_from_format(RB_SCOPE_BUFFERS, RB_TEX_DEPTH_MSAA_SUBSAMPLED, tf);
|
||||
}
|
||||
|
||||
// Upscaled texture.
|
||||
|
||||
void RenderSceneBuffersRD::ensure_upscaled() {
|
||||
|
||||
@@ -48,8 +48,12 @@
|
||||
#define RB_TEX_COLOR SNAME("color")
|
||||
#define RB_TEX_COLOR_MSAA SNAME("color_msaa")
|
||||
#define RB_TEX_COLOR_UPSCALED SNAME("color_upscaled")
|
||||
#define RB_TEX_COLOR_SUBSAMPLED SNAME("color_subsampled")
|
||||
#define RB_TEX_COLOR_MSAA_SUBSAMPLED SNAME("color_msaa_subsampled")
|
||||
#define RB_TEX_DEPTH SNAME("depth")
|
||||
#define RB_TEX_DEPTH_MSAA SNAME("depth_msaa")
|
||||
#define RB_TEX_DEPTH_SUBSAMPLED SNAME("depth_subsampled")
|
||||
#define RB_TEX_DEPTH_MSAA_SUBSAMPLED SNAME("depth_msaa_subsampled")
|
||||
#define RB_TEX_VELOCITY SNAME("velocity")
|
||||
#define RB_TEX_VELOCITY_MSAA SNAME("velocity_msaa")
|
||||
|
||||
@@ -282,6 +286,11 @@ public:
|
||||
return get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_DEPTH_MSAA, p_layer, 0);
|
||||
}
|
||||
|
||||
RID get_color_subsampled();
|
||||
RID get_color_msaa_subsampled();
|
||||
RID get_depth_subsampled();
|
||||
RID get_depth_msaa_subsampled();
|
||||
|
||||
// back buffer (color)
|
||||
RID get_back_buffer_texture() const {
|
||||
// Prefer returning the dedicated backbuffer color texture if it was created. Return the reused blur texture otherwise.
|
||||
|
||||
@@ -4220,6 +4220,34 @@ Rect2i RendererRD::TextureStorage::render_target_get_render_region(RID p_render_
|
||||
return rt->render_region;
|
||||
}
|
||||
|
||||
void RendererRD::TextureStorage::render_target_set_subsampled_enabled(RID p_render_target, bool p_enabled) {
|
||||
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
|
||||
ERR_FAIL_NULL(rt);
|
||||
|
||||
rt->subsampled_enabled = p_enabled;
|
||||
}
|
||||
|
||||
bool RendererRD::TextureStorage::render_target_is_subsampled_enabled(RID p_render_target) const {
|
||||
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
|
||||
ERR_FAIL_NULL_V(rt, false);
|
||||
|
||||
return rt->subsampled_enabled;
|
||||
}
|
||||
|
||||
void RendererRD::TextureStorage::render_target_set_subsampled_allowed(RID p_render_target, bool p_allowed) {
|
||||
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
|
||||
ERR_FAIL_NULL(rt);
|
||||
|
||||
rt->subsampled_allowed = p_allowed;
|
||||
}
|
||||
|
||||
bool RendererRD::TextureStorage::render_target_is_subsampled_allowed(RID p_render_target) const {
|
||||
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
|
||||
ERR_FAIL_NULL_V(rt, false);
|
||||
|
||||
return rt->subsampled_allowed;
|
||||
}
|
||||
|
||||
void TextureStorage::render_target_set_transparent(RID p_render_target, bool p_is_transparent) {
|
||||
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
|
||||
ERR_FAIL_NULL(rt);
|
||||
|
||||
@@ -404,6 +404,8 @@ private:
|
||||
RID vrs_texture;
|
||||
|
||||
Rect2i render_region;
|
||||
bool subsampled_enabled = false;
|
||||
bool subsampled_allowed = true;
|
||||
|
||||
// overridden textures
|
||||
struct RTOverridden {
|
||||
@@ -839,6 +841,12 @@ public:
|
||||
virtual void render_target_set_render_region(RID p_render_target, const Rect2i &p_render_region) override;
|
||||
virtual Rect2i render_target_get_render_region(RID p_render_target) const override;
|
||||
|
||||
virtual void render_target_set_subsampled_enabled(RID p_render_target, bool p_enabled) override;
|
||||
virtual bool render_target_is_subsampled_enabled(RID p_render_target) const override;
|
||||
|
||||
virtual void render_target_set_subsampled_allowed(RID p_render_target, bool p_allowed) override;
|
||||
virtual bool render_target_is_subsampled_allowed(RID p_render_target) const override;
|
||||
|
||||
virtual RID render_target_get_texture(RID p_render_target) override;
|
||||
|
||||
virtual void render_target_set_velocity_target_size(RID p_render_target, const Size2i &p_target_size) override {}
|
||||
|
||||
@@ -1332,6 +1332,7 @@ RID RenderingDevice::texture_create(const TextureFormat &p_format, const Texture
|
||||
texture.base_layer = 0;
|
||||
texture.is_resolve_buffer = format.is_resolve_buffer;
|
||||
texture.is_discardable = format.is_discardable;
|
||||
texture.is_subsampled = format.is_subsampled;
|
||||
texture.usage_flags = format.usage_bits & ~forced_usage_bits;
|
||||
texture.samples = format.samples;
|
||||
texture.allowed_shared_formats = format.shareable_formats;
|
||||
|
||||
@@ -356,6 +356,7 @@ public:
|
||||
|
||||
bool is_resolve_buffer = false;
|
||||
bool is_discardable = false;
|
||||
bool is_subsampled = false;
|
||||
bool has_initial_data = false;
|
||||
bool pending_clear = false;
|
||||
|
||||
|
||||
@@ -444,6 +444,7 @@ public:
|
||||
Vector<DataFormat> shareable_formats;
|
||||
bool is_resolve_buffer = false;
|
||||
bool is_discardable = false;
|
||||
bool is_subsampled = false;
|
||||
|
||||
bool operator==(const TextureFormat &b) const {
|
||||
if (format != b.format) {
|
||||
|
||||
@@ -195,6 +195,12 @@ public:
|
||||
virtual void render_target_set_render_region(RID p_render_target, const Rect2i &p_render_region) = 0;
|
||||
virtual Rect2i render_target_get_render_region(RID p_render_target) const = 0;
|
||||
|
||||
virtual void render_target_set_subsampled_enabled(RID p_render_target, bool p_enabled) = 0;
|
||||
virtual bool render_target_is_subsampled_enabled(RID p_render_target) const = 0;
|
||||
|
||||
virtual void render_target_set_subsampled_allowed(RID p_render_target, bool p_allowed) = 0;
|
||||
virtual bool render_target_is_subsampled_allowed(RID p_render_target) const = 0;
|
||||
|
||||
// get textures
|
||||
virtual RID render_target_get_texture(RID p_render_target) = 0;
|
||||
|
||||
|
||||
Reference in new issue
Block a user