@@ -523,6 +523,7 @@ Error RenderingDeviceDriverVulkan::_initialize_device_extensions() {
523523 _register_requested_device_extension (VK_KHR_MULTIVIEW_EXTENSION_NAME, false );
524524 _register_requested_device_extension (VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME, false );
525525 _register_requested_device_extension (VK_EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME, false );
526+ _register_requested_device_extension (VK_QCOM_FRAGMENT_DENSITY_MAP_OFFSET_EXTENSION_NAME, false );
526527 _register_requested_device_extension (VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME, false );
527528 _register_requested_device_extension (VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME, false );
528529 _register_requested_device_extension (VK_KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME, false );
@@ -760,6 +761,7 @@ Error RenderingDeviceDriverVulkan::_check_device_capabilities() {
760761 VkPhysicalDeviceVulkanMemoryModelFeaturesKHR vulkan_memory_model_features = {};
761762 VkPhysicalDeviceFragmentShadingRateFeaturesKHR fsr_features = {};
762763 VkPhysicalDeviceFragmentDensityMapFeaturesEXT fdm_features = {};
764+ VkPhysicalDeviceFragmentDensityMapOffsetFeaturesQCOM fdmo_features_qcom = {};
763765 VkPhysicalDevice16BitStorageFeaturesKHR storage_feature = {};
764766 VkPhysicalDeviceMultiviewFeatures multiview_features = {};
765767 VkPhysicalDevicePipelineCreationCacheControlFeatures pipeline_cache_control_features = {};
@@ -799,6 +801,12 @@ Error RenderingDeviceDriverVulkan::_check_device_capabilities() {
799801 next_features = &fdm_features;
800802 }
801803
804+ if (enabled_device_extension_names.has (VK_QCOM_FRAGMENT_DENSITY_MAP_OFFSET_EXTENSION_NAME)) {
805+ fdmo_features_qcom.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_FEATURES_QCOM;
806+ fdmo_features_qcom.pNext = next_features;
807+ next_features = &fdmo_features_qcom;
808+ }
809+
802810 if (enabled_device_extension_names.has (VK_KHR_16BIT_STORAGE_EXTENSION_NAME)) {
803811 storage_feature.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR;
804812 storage_feature.pNext = next_features;
@@ -863,6 +871,10 @@ Error RenderingDeviceDriverVulkan::_check_device_capabilities() {
863871 fdm_capabilities.non_subsampled_images_supported = fdm_features.fragmentDensityMapNonSubsampledImages ;
864872 }
865873
874+ if (enabled_device_extension_names.has (VK_QCOM_FRAGMENT_DENSITY_MAP_OFFSET_EXTENSION_NAME)) {
875+ fdm_capabilities.offset_supported = fdmo_features_qcom.fragmentDensityMapOffset ;
876+ }
877+
866878 // Multiple VRS techniques can't co-exist during the existence of one device, so we must
867879 // choose one at creation time and only report one of them as available.
868880 _choose_vrs_capabilities ();
@@ -898,6 +910,7 @@ Error RenderingDeviceDriverVulkan::_check_device_capabilities() {
898910 void *next_properties = nullptr ;
899911 VkPhysicalDeviceFragmentShadingRatePropertiesKHR fsr_properties = {};
900912 VkPhysicalDeviceFragmentDensityMapPropertiesEXT fdm_properties = {};
913+ VkPhysicalDeviceFragmentDensityMapOffsetPropertiesQCOM fdmo_properties = {};
901914 VkPhysicalDeviceMultiviewProperties multiview_properties = {};
902915 VkPhysicalDeviceSubgroupProperties subgroup_properties = {};
903916 VkPhysicalDeviceSubgroupSizeControlProperties subgroup_size_control_properties = {};
@@ -935,6 +948,12 @@ Error RenderingDeviceDriverVulkan::_check_device_capabilities() {
935948 next_properties = &fdm_properties;
936949 }
937950
951+ if (fdm_capabilities.offset_supported ) {
952+ fdmo_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_PROPERTIES_QCOM;
953+ fdmo_properties.pNext = next_properties;
954+ next_properties = &fdmo_properties;
955+ }
956+
938957 physical_device_properties_2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
939958 physical_device_properties_2.pNext = next_properties;
940959 functions.GetPhysicalDeviceProperties2 (physical_device, &physical_device_properties_2);
@@ -1002,6 +1021,17 @@ Error RenderingDeviceDriverVulkan::_check_device_capabilities() {
10021021 print_verbose (" - Vulkan Fragment Density Map not supported" );
10031022 }
10041023
1024+ if (fdm_capabilities.offset_supported ) {
1025+ print_verbose (" - Vulkan Fragment Density Map Offset supported" );
1026+
1027+ fdm_capabilities.offset_granularity .x = fdmo_properties.fragmentDensityOffsetGranularity .width ;
1028+ fdm_capabilities.offset_granularity .y = fdmo_properties.fragmentDensityOffsetGranularity .height ;
1029+
1030+ print_verbose (vformat (" Offset granularity: (%d, %d)" , fdm_capabilities.offset_granularity .x , fdm_capabilities.offset_granularity .y ));
1031+ } else {
1032+ print_verbose (" - Vulkan Fragment Density Map Offset not supported" );
1033+ }
1034+
10051035 if (multiview_capabilities.is_supported ) {
10061036 multiview_capabilities.max_view_count = multiview_properties.maxMultiviewViewCount ;
10071037 multiview_capabilities.max_instance_count = multiview_properties.maxMultiviewInstanceIndex ;
@@ -3708,11 +3738,6 @@ RDD::FramebufferID RenderingDeviceDriverVulkan::framebuffer_create(RenderPassID
37083738 for (uint32_t i = 0 ; i < p_attachments.size (); i++) {
37093739 const TextureInfo *texture = (const TextureInfo *)p_attachments[i].id ;
37103740 vk_img_views[i] = texture->vk_view ;
3711-
3712- if (render_pass->uses_fragment_density_map_offsets && (texture->vk_create_info .usage & VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT)) {
3713- // If the render pass uses the FDM and the usage fits, we store the amount of layers to use it later on the render pass's end.
3714- fragment_density_map_offsets_layers = texture->vk_create_info .arrayLayers ;
3715- }
37163741 }
37173742
37183743 VkFramebufferCreateInfo framebuffer_create_info = {};
@@ -4921,6 +4946,7 @@ RDD::RenderPassID RenderingDeviceDriverVulkan::render_pass_create(VectorView<Att
49214946
49224947 RenderPassInfo *render_pass = VersatileResource::allocate<RenderPassInfo>(resources_allocator);
49234948 render_pass->vk_render_pass = vk_render_pass;
4949+ render_pass->uses_fragment_density_map = uses_fragment_density_map;
49244950 return RenderPassID (render_pass);
49254951}
49264952
@@ -4982,7 +5008,25 @@ void RenderingDeviceDriverVulkan::command_end_render_pass(CommandBufferID p_cmd_
49825008 DEV_ASSERT (command_buffer->active_framebuffer != nullptr && " A framebuffer must be active." );
49835009 DEV_ASSERT (command_buffer->active_render_pass != nullptr && " A render pass must be active." );
49845010
4985- vkCmdEndRenderPass (command_buffer->vk_command_buffer );
5011+ if (device_functions.EndRenderPass2KHR != nullptr && fdm_capabilities.offset_supported && command_buffer->active_render_pass ->uses_fragment_density_map ) {
5012+ LocalVector<VkOffset2D> fragment_density_offsets;
5013+ if (VulkanHooks::get_singleton () != nullptr ) {
5014+ fragment_density_offsets = VulkanHooks::get_singleton ()->get_fragment_density_offsets ();
5015+ }
5016+
5017+ VkSubpassFragmentDensityMapOffsetEndInfoQCOM offset_info = {};
5018+ offset_info.sType = VK_STRUCTURE_TYPE_SUBPASS_FRAGMENT_DENSITY_MAP_OFFSET_END_INFO_QCOM;
5019+ offset_info.pFragmentDensityOffsets = fragment_density_offsets.is_empty () ? nullptr : fragment_density_offsets.ptr ();
5020+ offset_info.fragmentDensityOffsetCount = fragment_density_offsets.size ();
5021+
5022+ VkSubpassEndInfo subpass_end_info = {};
5023+ subpass_end_info.sType = VK_STRUCTURE_TYPE_SUBPASS_END_INFO;
5024+ subpass_end_info.pNext = &offset_info;
5025+
5026+ device_functions.EndRenderPass2KHR (command_buffer->vk_command_buffer , &subpass_end_info);
5027+ } else {
5028+ vkCmdEndRenderPass (command_buffer->vk_command_buffer );
5029+ }
49865030
49875031 command_buffer->active_render_pass = nullptr ;
49885032 command_buffer->active_framebuffer = nullptr ;
0 commit comments