1
0
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:
David Snopek
2025-11-19 15:06:55 -06:00
parent 9dd6c4dbac
commit fce47ac456
6 changed files with 117 additions and 60 deletions

View File

@@ -750,6 +750,11 @@ Error RenderingDeviceDriverVulkan::_check_device_capabilities() {
// Cache extension availability we query often.
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:
// https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VK_KHR_multiview.html
// https://www.khronos.org/blog/vulkan-subgroup-tutorial
@@ -805,7 +810,7 @@ Error RenderingDeviceDriverVulkan::_check_device_capabilities() {
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.pNext = next_features;
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) {
print_verbose("- Vulkan Fragment Density Map supported");
fdm_capabilities.min_texel_size.x = fdm_properties.minFragmentDensityTexelSize.width;
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.y = fdm_properties.maxFragmentDensityTexelSize.height;
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) {
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;
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");
}
@@ -1156,6 +1163,14 @@ Error RenderingDeviceDriverVulkan::_initialize_device(const LocalVector<VkDevice
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 = {};
if (pipeline_cache_control_support) {
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;
}*/
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.format = RD_TO_VK_FORMAT[p_format.format];
@@ -5036,19 +5055,22 @@ 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) {
LocalVector<VkOffset2D> fragment_density_offsets;
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 = {};
offset_info.sType = VK_STRUCTURE_TYPE_SUBPASS_FRAGMENT_DENSITY_MAP_OFFSET_END_INFO_QCOM;
offset_info.pFragmentDensityOffsets = fragment_density_offsets.ptr();
offset_info.fragmentDensityOffsetCount = fragment_density_offsets.size();
VkSubpassFragmentDensityMapOffsetEndInfoQCOM offset_info = {};
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.fragmentDensityOffsetCount = fragment_density_offsets.size();
VkSubpassEndInfo subpass_end_info = {};
subpass_end_info.sType = VK_STRUCTURE_TYPE_SUBPASS_END_INFO;
subpass_end_info.pNext = &offset_info;
VkSubpassEndInfo subpass_end_info = {};
subpass_end_info.sType = VK_STRUCTURE_TYPE_SUBPASS_END_INFO;
subpass_end_info.pNext = &offset_info;
device_functions.EndRenderPass2KHR(command_buffer->vk_command_buffer, &subpass_end_info);
device_functions.EndRenderPass2KHR(command_buffer->vk_command_buffer, &subpass_end_info);
} else {
vkCmdEndRenderPass(command_buffer->vk_command_buffer);
}
} else {
vkCmdEndRenderPass(command_buffer->vk_command_buffer);
}