You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-12-02 16:48:55 +00:00
OpenXR: Fix Vulkan validation errors and get XR_META_foveation_eye_tracked working on Meta Quest devices
This commit is contained in:
@@ -750,6 +750,11 @@ Error RenderingDeviceDriverVulkan::_check_device_capabilities() {
|
|||||||
// Cache extension availability we query often.
|
// Cache extension availability we query often.
|
||||||
framebuffer_depth_resolve = enabled_device_extension_names.has(VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME);
|
framebuffer_depth_resolve = enabled_device_extension_names.has(VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME);
|
||||||
|
|
||||||
|
bool use_fdm_offsets = false;
|
||||||
|
if (VulkanHooks::get_singleton() != nullptr) {
|
||||||
|
use_fdm_offsets = VulkanHooks::get_singleton()->use_fragment_density_offsets();
|
||||||
|
}
|
||||||
|
|
||||||
// References:
|
// References:
|
||||||
// https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VK_KHR_multiview.html
|
// https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VK_KHR_multiview.html
|
||||||
// https://www.khronos.org/blog/vulkan-subgroup-tutorial
|
// https://www.khronos.org/blog/vulkan-subgroup-tutorial
|
||||||
@@ -805,7 +810,7 @@ Error RenderingDeviceDriverVulkan::_check_device_capabilities() {
|
|||||||
next_features = &fdm_features;
|
next_features = &fdm_features;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enabled_device_extension_names.has(VK_QCOM_FRAGMENT_DENSITY_MAP_OFFSET_EXTENSION_NAME)) {
|
if (use_fdm_offsets && enabled_device_extension_names.has(VK_QCOM_FRAGMENT_DENSITY_MAP_OFFSET_EXTENSION_NAME)) {
|
||||||
fdmo_features_qcom.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_FEATURES_QCOM;
|
fdmo_features_qcom.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_FEATURES_QCOM;
|
||||||
fdmo_features_qcom.pNext = next_features;
|
fdmo_features_qcom.pNext = next_features;
|
||||||
next_features = &fdmo_features_qcom;
|
next_features = &fdmo_features_qcom;
|
||||||
@@ -1006,14 +1011,16 @@ Error RenderingDeviceDriverVulkan::_check_device_capabilities() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (fdm_capabilities.attachment_supported || fdm_capabilities.dynamic_attachment_supported || fdm_capabilities.non_subsampled_images_supported) {
|
if (fdm_capabilities.attachment_supported || fdm_capabilities.dynamic_attachment_supported || fdm_capabilities.non_subsampled_images_supported) {
|
||||||
print_verbose("- Vulkan Fragment Density Map supported");
|
|
||||||
|
|
||||||
fdm_capabilities.min_texel_size.x = fdm_properties.minFragmentDensityTexelSize.width;
|
fdm_capabilities.min_texel_size.x = fdm_properties.minFragmentDensityTexelSize.width;
|
||||||
fdm_capabilities.min_texel_size.y = fdm_properties.minFragmentDensityTexelSize.height;
|
fdm_capabilities.min_texel_size.y = fdm_properties.minFragmentDensityTexelSize.height;
|
||||||
fdm_capabilities.max_texel_size.x = fdm_properties.maxFragmentDensityTexelSize.width;
|
fdm_capabilities.max_texel_size.x = fdm_properties.maxFragmentDensityTexelSize.width;
|
||||||
fdm_capabilities.max_texel_size.y = fdm_properties.maxFragmentDensityTexelSize.height;
|
fdm_capabilities.max_texel_size.y = fdm_properties.maxFragmentDensityTexelSize.height;
|
||||||
fdm_capabilities.invocations_supported = fdm_properties.fragmentDensityInvocations;
|
fdm_capabilities.invocations_supported = fdm_properties.fragmentDensityInvocations;
|
||||||
|
|
||||||
|
print_verbose(String("- Vulkan Fragment Density Map supported") +
|
||||||
|
String(", min texel size: (") + itos(fdm_capabilities.min_texel_size.x) + String(", ") + itos(fdm_capabilities.min_texel_size.y) + String(")") +
|
||||||
|
String(", max texel size: (") + itos(fdm_capabilities.max_texel_size.x) + String(", ") + itos(fdm_capabilities.max_texel_size.y) + String(")"));
|
||||||
|
|
||||||
if (fdm_capabilities.dynamic_attachment_supported) {
|
if (fdm_capabilities.dynamic_attachment_supported) {
|
||||||
print_verbose(" - dynamic fragment density map supported");
|
print_verbose(" - dynamic fragment density map supported");
|
||||||
}
|
}
|
||||||
@@ -1032,7 +1039,7 @@ Error RenderingDeviceDriverVulkan::_check_device_capabilities() {
|
|||||||
fdm_capabilities.offset_granularity.y = fdmo_properties.fragmentDensityOffsetGranularity.height;
|
fdm_capabilities.offset_granularity.y = fdmo_properties.fragmentDensityOffsetGranularity.height;
|
||||||
|
|
||||||
print_verbose(vformat(" Offset granularity: (%d, %d)", fdm_capabilities.offset_granularity.x, fdm_capabilities.offset_granularity.y));
|
print_verbose(vformat(" Offset granularity: (%d, %d)", fdm_capabilities.offset_granularity.x, fdm_capabilities.offset_granularity.y));
|
||||||
} else {
|
} else if (use_fdm_offsets) {
|
||||||
print_verbose("- Vulkan Fragment Density Map Offset not supported");
|
print_verbose("- Vulkan Fragment Density Map Offset not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1156,6 +1163,14 @@ Error RenderingDeviceDriverVulkan::_initialize_device(const LocalVector<VkDevice
|
|||||||
create_info_next = &fdm_features;
|
create_info_next = &fdm_features;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VkPhysicalDeviceFragmentDensityMapOffsetFeaturesQCOM fdm_offset_features = {};
|
||||||
|
if (fdm_capabilities.offset_supported) {
|
||||||
|
fdm_offset_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_FEATURES_QCOM;
|
||||||
|
fdm_offset_features.pNext = create_info_next;
|
||||||
|
fdm_offset_features.fragmentDensityMapOffset = VK_TRUE;
|
||||||
|
create_info_next = &fdm_offset_features;
|
||||||
|
}
|
||||||
|
|
||||||
VkPhysicalDevicePipelineCreationCacheControlFeatures pipeline_cache_control_features = {};
|
VkPhysicalDevicePipelineCreationCacheControlFeatures pipeline_cache_control_features = {};
|
||||||
if (pipeline_cache_control_support) {
|
if (pipeline_cache_control_support) {
|
||||||
pipeline_cache_control_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES;
|
pipeline_cache_control_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES;
|
||||||
@@ -1992,6 +2007,10 @@ RDD::TextureID RenderingDeviceDriverVulkan::texture_create(const TextureFormat &
|
|||||||
create_info.flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT;
|
create_info.flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT;
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
create_info.imageType = RD_TEX_TYPE_TO_VK_IMG_TYPE[p_format.texture_type];
|
create_info.imageType = RD_TEX_TYPE_TO_VK_IMG_TYPE[p_format.texture_type];
|
||||||
|
|
||||||
create_info.format = RD_TO_VK_FORMAT[p_format.format];
|
create_info.format = RD_TO_VK_FORMAT[p_format.format];
|
||||||
@@ -5036,12 +5055,12 @@ void RenderingDeviceDriverVulkan::command_end_render_pass(CommandBufferID p_cmd_
|
|||||||
if (device_functions.EndRenderPass2KHR != nullptr && fdm_capabilities.offset_supported && command_buffer->active_render_pass->uses_fragment_density_map) {
|
if (device_functions.EndRenderPass2KHR != nullptr && fdm_capabilities.offset_supported && command_buffer->active_render_pass->uses_fragment_density_map) {
|
||||||
LocalVector<VkOffset2D> fragment_density_offsets;
|
LocalVector<VkOffset2D> fragment_density_offsets;
|
||||||
if (VulkanHooks::get_singleton() != nullptr) {
|
if (VulkanHooks::get_singleton() != nullptr) {
|
||||||
fragment_density_offsets = VulkanHooks::get_singleton()->get_fragment_density_offsets();
|
VulkanHooks::get_singleton()->get_fragment_density_offsets(fragment_density_offsets, fdm_capabilities.offset_granularity);
|
||||||
}
|
}
|
||||||
|
if (fragment_density_offsets.size() > 0) {
|
||||||
VkSubpassFragmentDensityMapOffsetEndInfoQCOM offset_info = {};
|
VkSubpassFragmentDensityMapOffsetEndInfoQCOM offset_info = {};
|
||||||
offset_info.sType = VK_STRUCTURE_TYPE_SUBPASS_FRAGMENT_DENSITY_MAP_OFFSET_END_INFO_QCOM;
|
offset_info.sType = VK_STRUCTURE_TYPE_SUBPASS_FRAGMENT_DENSITY_MAP_OFFSET_END_INFO_QCOM;
|
||||||
offset_info.pFragmentDensityOffsets = fragment_density_offsets.is_empty() ? nullptr : fragment_density_offsets.ptr();
|
offset_info.pFragmentDensityOffsets = fragment_density_offsets.ptr();
|
||||||
offset_info.fragmentDensityOffsetCount = fragment_density_offsets.size();
|
offset_info.fragmentDensityOffsetCount = fragment_density_offsets.size();
|
||||||
|
|
||||||
VkSubpassEndInfo subpass_end_info = {};
|
VkSubpassEndInfo subpass_end_info = {};
|
||||||
@@ -5052,6 +5071,9 @@ void RenderingDeviceDriverVulkan::command_end_render_pass(CommandBufferID p_cmd_
|
|||||||
} else {
|
} else {
|
||||||
vkCmdEndRenderPass(command_buffer->vk_command_buffer);
|
vkCmdEndRenderPass(command_buffer->vk_command_buffer);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
vkCmdEndRenderPass(command_buffer->vk_command_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
command_buffer->active_render_pass = nullptr;
|
command_buffer->active_render_pass = nullptr;
|
||||||
command_buffer->active_framebuffer = nullptr;
|
command_buffer->active_framebuffer = nullptr;
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/math/vector2i.h"
|
||||||
#include "core/templates/local_vector.h"
|
#include "core/templates/local_vector.h"
|
||||||
#include "drivers/vulkan/godot_vulkan.h"
|
#include "drivers/vulkan/godot_vulkan.h"
|
||||||
|
|
||||||
@@ -44,6 +45,7 @@ public:
|
|||||||
virtual bool get_physical_device(VkPhysicalDevice *r_device) = 0;
|
virtual bool get_physical_device(VkPhysicalDevice *r_device) = 0;
|
||||||
virtual bool create_vulkan_device(const VkDeviceCreateInfo *p_device_create_info, VkDevice *r_device) = 0;
|
virtual bool create_vulkan_device(const VkDeviceCreateInfo *p_device_create_info, VkDevice *r_device) = 0;
|
||||||
virtual void set_direct_queue_family_and_index(uint32_t p_queue_family_index, uint32_t p_queue_index) = 0;
|
virtual void set_direct_queue_family_and_index(uint32_t p_queue_family_index, uint32_t p_queue_index) = 0;
|
||||||
virtual LocalVector<VkOffset2D> get_fragment_density_offsets() = 0;
|
virtual bool use_fragment_density_offsets() = 0;
|
||||||
|
virtual void get_fragment_density_offsets(LocalVector<VkOffset2D> &r_offsets, const Vector2i &p_granularity) = 0;
|
||||||
static VulkanHooks *get_singleton() { return singleton; }
|
static VulkanHooks *get_singleton() { return singleton; }
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -63,6 +63,11 @@ OpenXRFBFoveationExtension::OpenXRFBFoveationExtension(const String &p_rendering
|
|||||||
meta_foveation_eye_tracked_properties.next = nullptr;
|
meta_foveation_eye_tracked_properties.next = nullptr;
|
||||||
meta_foveation_eye_tracked_properties.supportsFoveationEyeTracked = XR_FALSE;
|
meta_foveation_eye_tracked_properties.supportsFoveationEyeTracked = XR_FALSE;
|
||||||
|
|
||||||
|
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.additionalUsageFlags = 0;
|
||||||
|
|
||||||
if (rendering_driver == "opengl3") {
|
if (rendering_driver == "opengl3") {
|
||||||
swapchain_create_info_foveation_fb.flags = XR_SWAPCHAIN_CREATE_FOVEATION_SCALED_BIN_BIT_FB;
|
swapchain_create_info_foveation_fb.flags = XR_SWAPCHAIN_CREATE_FOVEATION_SCALED_BIN_BIT_FB;
|
||||||
} else if (rendering_driver == "vulkan") {
|
} else if (rendering_driver == "vulkan") {
|
||||||
@@ -84,7 +89,8 @@ HashMap<String, bool *> OpenXRFBFoveationExtension::get_requested_extensions() {
|
|||||||
#ifdef XR_USE_GRAPHICS_API_VULKAN
|
#ifdef XR_USE_GRAPHICS_API_VULKAN
|
||||||
if (rendering_driver == "vulkan") {
|
if (rendering_driver == "vulkan") {
|
||||||
request_extensions[XR_FB_FOVEATION_VULKAN_EXTENSION_NAME] = &fb_foveation_vulkan_ext;
|
request_extensions[XR_FB_FOVEATION_VULKAN_EXTENSION_NAME] = &fb_foveation_vulkan_ext;
|
||||||
request_extensions[XR_META_FOVEATION_EYE_TRACKED_EXTENSION_NAME] = &meta_foveation_eye_tracked;
|
request_extensions[XR_META_FOVEATION_EYE_TRACKED_EXTENSION_NAME] = &meta_foveation_eye_tracked_ext;
|
||||||
|
request_extensions[XR_META_VULKAN_SWAPCHAIN_CREATE_INFO_EXTENSION_NAME] = &meta_vulkan_swapchain_create_info_ext;
|
||||||
}
|
}
|
||||||
#endif // XR_USE_GRAPHICS_API_VULKAN
|
#endif // XR_USE_GRAPHICS_API_VULKAN
|
||||||
|
|
||||||
@@ -101,7 +107,7 @@ void OpenXRFBFoveationExtension::on_instance_created(const XrInstance p_instance
|
|||||||
// nothing to register here...
|
// nothing to register here...
|
||||||
}
|
}
|
||||||
|
|
||||||
if (meta_foveation_eye_tracked) {
|
if (meta_foveation_eye_tracked_ext) {
|
||||||
EXT_INIT_XR_FUNC(xrGetFoveationEyeTrackedStateMETA);
|
EXT_INIT_XR_FUNC(xrGetFoveationEyeTrackedStateMETA);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -109,7 +115,7 @@ void OpenXRFBFoveationExtension::on_instance_created(const XrInstance p_instance
|
|||||||
void OpenXRFBFoveationExtension::on_instance_destroyed() {
|
void OpenXRFBFoveationExtension::on_instance_destroyed() {
|
||||||
fb_foveation_ext = false;
|
fb_foveation_ext = false;
|
||||||
fb_foveation_configuration_ext = false;
|
fb_foveation_configuration_ext = false;
|
||||||
meta_foveation_eye_tracked = false;
|
meta_foveation_eye_tracked_ext = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OpenXRFBFoveationExtension::is_enabled() const {
|
bool OpenXRFBFoveationExtension::is_enabled() const {
|
||||||
@@ -133,14 +139,20 @@ void *OpenXRFBFoveationExtension::set_system_properties_and_get_next_pointer(voi
|
|||||||
}
|
}
|
||||||
|
|
||||||
void *OpenXRFBFoveationExtension::set_swapchain_create_info_and_get_next_pointer(void *p_next_pointer) {
|
void *OpenXRFBFoveationExtension::set_swapchain_create_info_and_get_next_pointer(void *p_next_pointer) {
|
||||||
|
void *next = p_next_pointer;
|
||||||
if (is_enabled()) {
|
if (is_enabled()) {
|
||||||
swapchain_create_info_foveation_fb.next = p_next_pointer;
|
swapchain_create_info_foveation_fb.next = next;
|
||||||
return &swapchain_create_info_foveation_fb;
|
next = &swapchain_create_info_foveation_fb;
|
||||||
} else {
|
|
||||||
return p_next_pointer;
|
if (meta_foveation_eye_tracked_ext && meta_vulkan_swapchain_create_info_ext && meta_foveation_eye_tracked_properties.supportsFoveationEyeTracked) {
|
||||||
|
meta_vulkan_swapchain_create_info.next = next;
|
||||||
|
next = &meta_vulkan_swapchain_create_info;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
void OpenXRFBFoveationExtension::on_main_swapchains_created() {
|
void OpenXRFBFoveationExtension::on_main_swapchains_created() {
|
||||||
update_profile();
|
update_profile();
|
||||||
}
|
}
|
||||||
@@ -167,14 +179,22 @@ void OpenXRFBFoveationExtension::set_foveation_dynamic(XrFoveationDynamicFB p_fo
|
|||||||
update_profile();
|
update_profile();
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalVector<Vector2i> OpenXRFBFoveationExtension::get_fragment_density_offsets() {
|
bool OpenXRFBFoveationExtension::is_foveation_eye_tracked_enabled() const {
|
||||||
LocalVector<Vector2i> ret;
|
return is_enabled() && meta_foveation_eye_tracked_ext && meta_vulkan_swapchain_create_info_ext && meta_foveation_eye_tracked_properties.supportsFoveationEyeTracked;
|
||||||
if (!is_enabled() || !meta_foveation_eye_tracked || !meta_foveation_eye_tracked_properties.supportsFoveationEyeTracked || !OpenXREyeGazeInteractionExtension::get_singleton()->is_available()) {
|
}
|
||||||
return ret;
|
|
||||||
|
void OpenXRFBFoveationExtension::get_fragment_density_offsets(LocalVector<Vector2i> &r_offsets) {
|
||||||
|
// Must be called from rendering thread!
|
||||||
|
ERR_NOT_ON_RENDER_THREAD;
|
||||||
|
|
||||||
|
if (!is_foveation_eye_tracked_enabled() || !OpenXREyeGazeInteractionExtension::get_singleton()->is_available()) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
OpenXRAPI *openxr_api = OpenXRAPI::get_singleton();
|
OpenXRAPI *openxr_api = OpenXRAPI::get_singleton();
|
||||||
ERR_FAIL_NULL_V(openxr_api, ret);
|
ERR_FAIL_NULL(openxr_api);
|
||||||
|
|
||||||
|
_update_profile_rt();
|
||||||
|
|
||||||
XrFoveationEyeTrackedStateMETA state = {
|
XrFoveationEyeTrackedStateMETA state = {
|
||||||
XR_TYPE_FOVEATION_EYE_TRACKED_STATE_META, // type
|
XR_TYPE_FOVEATION_EYE_TRACKED_STATE_META, // type
|
||||||
@@ -185,27 +205,25 @@ LocalVector<Vector2i> OpenXRFBFoveationExtension::get_fragment_density_offsets()
|
|||||||
XrResult result = xrGetFoveationEyeTrackedStateMETA(openxr_api->get_session(), &state);
|
XrResult result = xrGetFoveationEyeTrackedStateMETA(openxr_api->get_session(), &state);
|
||||||
if (XR_FAILED(result)) {
|
if (XR_FAILED(result)) {
|
||||||
print_line("OpenXR: Unable to get foveation offsets [", openxr_api->get_error_string(result), "]");
|
print_line("OpenXR: Unable to get foveation offsets [", openxr_api->get_error_string(result), "]");
|
||||||
return ret;
|
return;
|
||||||
|
}
|
||||||
|
if (!(state.flags & XR_FOVEATION_EYE_TRACKED_STATE_VALID_BIT_META)) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret.reserve(XR_FOVEATION_CENTER_SIZE_META);
|
r_offsets.reserve(XR_FOVEATION_CENTER_SIZE_META);
|
||||||
Size2 dims = openxr_api->get_recommended_target_size() * 0.5 / openxr_api->get_render_target_size_multiplier();
|
Size2 dims = openxr_api->get_recommended_target_size() * 0.5;
|
||||||
for (uint32_t i = 0; i < XR_FOVEATION_CENTER_SIZE_META; ++i) {
|
for (uint32_t i = 0; i < XR_FOVEATION_CENTER_SIZE_META; ++i) {
|
||||||
const XrVector2f &xr_offset = state.foveationCenter[i];
|
const XrVector2f &xr_center = state.foveationCenter[i];
|
||||||
ret.push_back(Vector2i((int)(xr_offset.x * dims.x), (int)(xr_offset.y * dims.y)));
|
r_offsets.push_back(Vector2i((int)(xr_center.x * dims.x), (int)(xr_center.y * dims.y)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
void OpenXRFBFoveationExtension::_update_profile_rt() {
|
||||||
}
|
|
||||||
|
|
||||||
void OpenXRFBFoveationExtension::_update_profile() {
|
|
||||||
// Must be called from rendering thread!
|
// Must be called from rendering thread!
|
||||||
ERR_NOT_ON_RENDER_THREAD;
|
ERR_NOT_ON_RENDER_THREAD;
|
||||||
|
|
||||||
OpenXRFBFoveationExtension *fov_ext = OpenXRFBFoveationExtension::get_singleton();
|
if (!is_enabled()) {
|
||||||
ERR_FAIL_NULL(fov_ext);
|
|
||||||
|
|
||||||
if (!fov_ext->is_enabled()) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,24 +237,24 @@ void OpenXRFBFoveationExtension::_update_profile() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void *next = nullptr;
|
void *next = nullptr;
|
||||||
if (fov_ext->meta_foveation_eye_tracked && fov_ext->meta_foveation_eye_tracked_properties.supportsFoveationEyeTracked) {
|
if (meta_foveation_eye_tracked_ext && meta_vulkan_swapchain_create_info_ext && meta_foveation_eye_tracked_properties.supportsFoveationEyeTracked) {
|
||||||
fov_ext->meta_foveation_eye_tracked_create_info.next = next;
|
meta_foveation_eye_tracked_create_info.next = next;
|
||||||
next = &fov_ext->meta_foveation_eye_tracked_create_info;
|
next = &meta_foveation_eye_tracked_create_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
XrFoveationLevelProfileCreateInfoFB level_profile_create_info;
|
XrFoveationLevelProfileCreateInfoFB level_profile_create_info;
|
||||||
level_profile_create_info.type = XR_TYPE_FOVEATION_LEVEL_PROFILE_CREATE_INFO_FB;
|
level_profile_create_info.type = XR_TYPE_FOVEATION_LEVEL_PROFILE_CREATE_INFO_FB;
|
||||||
level_profile_create_info.next = next;
|
level_profile_create_info.next = next;
|
||||||
level_profile_create_info.level = fov_ext->foveation_level;
|
level_profile_create_info.level = foveation_level;
|
||||||
level_profile_create_info.verticalOffset = 0.0f;
|
level_profile_create_info.verticalOffset = 0.0f;
|
||||||
level_profile_create_info.dynamic = fov_ext->foveation_dynamic;
|
level_profile_create_info.dynamic = foveation_dynamic;
|
||||||
|
|
||||||
XrFoveationProfileCreateInfoFB profile_create_info;
|
XrFoveationProfileCreateInfoFB profile_create_info;
|
||||||
profile_create_info.type = XR_TYPE_FOVEATION_PROFILE_CREATE_INFO_FB;
|
profile_create_info.type = XR_TYPE_FOVEATION_PROFILE_CREATE_INFO_FB;
|
||||||
profile_create_info.next = &level_profile_create_info;
|
profile_create_info.next = &level_profile_create_info;
|
||||||
|
|
||||||
XrFoveationProfileFB foveation_profile;
|
XrFoveationProfileFB foveation_profile;
|
||||||
XrResult result = fov_ext->xrCreateFoveationProfileFB(openxr_api->get_session(), &profile_create_info, &foveation_profile);
|
XrResult result = xrCreateFoveationProfileFB(openxr_api->get_session(), &profile_create_info, &foveation_profile);
|
||||||
if (XR_FAILED(result)) {
|
if (XR_FAILED(result)) {
|
||||||
print_line("OpenXR: Unable to create the foveation profile [", openxr_api->get_error_string(result), "]");
|
print_line("OpenXR: Unable to create the foveation profile [", openxr_api->get_error_string(result), "]");
|
||||||
return;
|
return;
|
||||||
@@ -248,14 +266,14 @@ void OpenXRFBFoveationExtension::_update_profile() {
|
|||||||
foveation_update_state.flags = 0;
|
foveation_update_state.flags = 0;
|
||||||
foveation_update_state.profile = foveation_profile;
|
foveation_update_state.profile = foveation_profile;
|
||||||
|
|
||||||
result = fov_ext->swapchain_update_state_ext->xrUpdateSwapchainFB(main_color_swapchain, (XrSwapchainStateBaseHeaderFB *)&foveation_update_state);
|
result = swapchain_update_state_ext->xrUpdateSwapchainFB(main_color_swapchain, (XrSwapchainStateBaseHeaderFB *)&foveation_update_state);
|
||||||
if (XR_FAILED(result)) {
|
if (XR_FAILED(result)) {
|
||||||
print_line("OpenXR: Unable to update the swapchain [", openxr_api->get_error_string(result), "]");
|
print_line("OpenXR: Unable to update the swapchain [", openxr_api->get_error_string(result), "]");
|
||||||
|
|
||||||
// We still want to destroy our profile so keep going...
|
// We still want to destroy our profile so keep going...
|
||||||
}
|
}
|
||||||
|
|
||||||
result = fov_ext->xrDestroyFoveationProfileFB(foveation_profile);
|
result = xrDestroyFoveationProfileFB(foveation_profile);
|
||||||
if (XR_FAILED(result)) {
|
if (XR_FAILED(result)) {
|
||||||
print_line("OpenXR: Unable to destroy the foveation profile [", openxr_api->get_error_string(result), "]");
|
print_line("OpenXR: Unable to destroy the foveation profile [", openxr_api->get_error_string(result), "]");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,6 +40,8 @@
|
|||||||
#include "openxr_extension_wrapper.h"
|
#include "openxr_extension_wrapper.h"
|
||||||
#include "openxr_fb_update_swapchain_extension.h"
|
#include "openxr_fb_update_swapchain_extension.h"
|
||||||
|
|
||||||
|
#include "../openxr_platform_inc.h"
|
||||||
|
|
||||||
class OpenXRFBFoveationExtension : public OpenXRExtensionWrapper {
|
class OpenXRFBFoveationExtension : public OpenXRExtensionWrapper {
|
||||||
GDCLASS(OpenXRFBFoveationExtension, OpenXRExtensionWrapper);
|
GDCLASS(OpenXRFBFoveationExtension, OpenXRExtensionWrapper);
|
||||||
|
|
||||||
@@ -70,7 +72,8 @@ public:
|
|||||||
XrFoveationDynamicFB get_foveation_dynamic() const;
|
XrFoveationDynamicFB get_foveation_dynamic() const;
|
||||||
void set_foveation_dynamic(XrFoveationDynamicFB p_foveation_dynamic);
|
void set_foveation_dynamic(XrFoveationDynamicFB p_foveation_dynamic);
|
||||||
|
|
||||||
LocalVector<Vector2i> get_fragment_density_offsets();
|
bool is_foveation_eye_tracked_enabled() const;
|
||||||
|
void get_fragment_density_offsets(LocalVector<Vector2i> &r_offsets);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static OpenXRFBFoveationExtension *singleton;
|
static OpenXRFBFoveationExtension *singleton;
|
||||||
@@ -80,20 +83,21 @@ private:
|
|||||||
bool fb_foveation_ext = false;
|
bool fb_foveation_ext = false;
|
||||||
bool fb_foveation_configuration_ext = false;
|
bool fb_foveation_configuration_ext = false;
|
||||||
bool fb_foveation_vulkan_ext = false;
|
bool fb_foveation_vulkan_ext = false;
|
||||||
bool meta_foveation_eye_tracked = false;
|
bool meta_foveation_eye_tracked_ext = false;
|
||||||
|
bool meta_vulkan_swapchain_create_info_ext = false;
|
||||||
|
|
||||||
// Configuration
|
// Configuration
|
||||||
XrFoveationLevelFB foveation_level = XR_FOVEATION_LEVEL_NONE_FB;
|
XrFoveationLevelFB foveation_level = XR_FOVEATION_LEVEL_NONE_FB;
|
||||||
XrFoveationDynamicFB foveation_dynamic = XR_FOVEATION_DYNAMIC_DISABLED_FB;
|
XrFoveationDynamicFB foveation_dynamic = XR_FOVEATION_DYNAMIC_DISABLED_FB;
|
||||||
|
|
||||||
static void _update_profile();
|
void _update_profile_rt();
|
||||||
|
|
||||||
void update_profile() {
|
void update_profile() {
|
||||||
// If we're rendering on a separate thread, we may still be processing the last frame, don't communicate this till we're ready...
|
// If we're rendering on a separate thread, we may still be processing the last frame, don't communicate this till we're ready...
|
||||||
RenderingServer *rendering_server = RenderingServer::get_singleton();
|
RenderingServer *rendering_server = RenderingServer::get_singleton();
|
||||||
ERR_FAIL_NULL(rendering_server);
|
ERR_FAIL_NULL(rendering_server);
|
||||||
|
|
||||||
rendering_server->call_on_render_thread(callable_mp_static(&OpenXRFBFoveationExtension::_update_profile));
|
rendering_server->call_on_render_thread(callable_mp(this, &OpenXRFBFoveationExtension::_update_profile_rt));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable foveation on this swapchain
|
// Enable foveation on this swapchain
|
||||||
@@ -103,6 +107,7 @@ private:
|
|||||||
// Enable eye tracked foveation
|
// Enable eye tracked foveation
|
||||||
XrSystemFoveationEyeTrackedPropertiesMETA meta_foveation_eye_tracked_properties;
|
XrSystemFoveationEyeTrackedPropertiesMETA meta_foveation_eye_tracked_properties;
|
||||||
XrFoveationEyeTrackedProfileCreateInfoMETA meta_foveation_eye_tracked_create_info;
|
XrFoveationEyeTrackedProfileCreateInfoMETA meta_foveation_eye_tracked_create_info;
|
||||||
|
XrVulkanSwapchainCreateInfoMETA meta_vulkan_swapchain_create_info;
|
||||||
|
|
||||||
// OpenXR API call wrappers
|
// OpenXR API call wrappers
|
||||||
EXT_PROTO_XRRESULT_FUNC3(xrCreateFoveationProfileFB, (XrSession), session, (const XrFoveationProfileCreateInfoFB *), create_info, (XrFoveationProfileFB *), profile);
|
EXT_PROTO_XRRESULT_FUNC3(xrCreateFoveationProfileFB, (XrSession), session, (const XrFoveationProfileCreateInfoFB *), create_info, (XrFoveationProfileFB *), profile);
|
||||||
|
|||||||
@@ -203,21 +203,30 @@ void OpenXRVulkanExtension::set_direct_queue_family_and_index(uint32_t p_queue_f
|
|||||||
vulkan_queue_index = p_queue_index;
|
vulkan_queue_index = p_queue_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalVector<VkOffset2D> OpenXRVulkanExtension::get_fragment_density_offsets() {
|
bool OpenXRVulkanExtension::use_fragment_density_offsets() {
|
||||||
LocalVector<VkOffset2D> ret;
|
|
||||||
OpenXRFBFoveationExtension *fb_foveation = OpenXRFBFoveationExtension::get_singleton();
|
OpenXRFBFoveationExtension *fb_foveation = OpenXRFBFoveationExtension::get_singleton();
|
||||||
if (fb_foveation == nullptr) {
|
if (fb_foveation == nullptr) {
|
||||||
return ret;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalVector<Vector2i> offsets = fb_foveation->get_fragment_density_offsets();
|
return fb_foveation->is_foveation_eye_tracked_enabled();
|
||||||
|
|
||||||
ret.reserve(offsets.size());
|
|
||||||
for (const Vector2i &offset : offsets) {
|
|
||||||
ret.push_back(VkOffset2D{ offset.x, offset.y });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
void OpenXRVulkanExtension::get_fragment_density_offsets(LocalVector<VkOffset2D> &r_vk_offsets, const Vector2i &p_granularity) {
|
||||||
|
OpenXRFBFoveationExtension *fb_foveation = OpenXRFBFoveationExtension::get_singleton();
|
||||||
|
if (fb_foveation == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalVector<Vector2i> offsets;
|
||||||
|
fb_foveation->get_fragment_density_offsets(offsets);
|
||||||
|
|
||||||
|
r_vk_offsets.reserve(offsets.size());
|
||||||
|
for (Vector2i offset : offsets) {
|
||||||
|
offset = ((offset + p_granularity / 2) / p_granularity) * p_granularity;
|
||||||
|
|
||||||
|
r_vk_offsets.push_back(VkOffset2D{ offset.x, offset.y });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
XrGraphicsBindingVulkanKHR OpenXRVulkanExtension::graphics_binding_vulkan;
|
XrGraphicsBindingVulkanKHR OpenXRVulkanExtension::graphics_binding_vulkan;
|
||||||
|
|||||||
@@ -54,7 +54,8 @@ public:
|
|||||||
virtual bool get_physical_device(VkPhysicalDevice *r_device) override final;
|
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 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 void set_direct_queue_family_and_index(uint32_t p_queue_family_index, uint32_t p_queue_index) override final;
|
||||||
virtual LocalVector<VkOffset2D> get_fragment_density_offsets() 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;
|
||||||
|
|
||||||
virtual void get_usable_swapchain_formats(Vector<int64_t> &p_usable_swap_chains) 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 void get_usable_depth_formats(Vector<int64_t> &p_usable_swap_chains) override;
|
||||||
|
|||||||
Reference in New Issue
Block a user