diff --git a/src/video_core/renderer_vulkan/vk_render_pass_cache.cpp b/src/video_core/renderer_vulkan/vk_render_pass_cache.cpp index b64aab8be0..40a7aad298 100644 --- a/src/video_core/renderer_vulkan/vk_render_pass_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_render_pass_cache.cpp @@ -64,7 +64,8 @@ using VideoCore::Surface::SurfaceType; VkAttachmentDescription AttachmentDescription(const Device& device, PixelFormat format, VkSampleCountFlagBits samples, bool tbdr_will_clear, - bool tbdr_discard_after) { + bool tbdr_discard_after, + bool tbdr_read_only = false) { using MaxwellToVK::SurfaceFormat; const SurfaceType surface_type = GetSurfaceType(format); @@ -84,15 +85,20 @@ using VideoCore::Surface::SurfaceType; // On TBDR: Use DONT_CARE if content won't be read (avoids storing to main memory) // On Desktop: Always STORE (safer default) + // VK_QCOM_render_pass_store_ops: Use NONE_QCOM for read-only attachments (preserves outside render area) VkAttachmentStoreOp store_op = VK_ATTACHMENT_STORE_OP_STORE; if (is_tbdr && tbdr_discard_after) { store_op = VK_ATTACHMENT_STORE_OP_DONT_CARE; + } else if (is_tbdr && tbdr_read_only && device.IsQcomRenderPassStoreOpsSupported()) { + store_op = static_cast(1000301000); // VK_ATTACHMENT_STORE_OP_NONE_QCOM } // Stencil operations follow same logic VkAttachmentLoadOp stencil_load_op = VK_ATTACHMENT_LOAD_OP_DONT_CARE; VkAttachmentStoreOp stencil_store_op = VK_ATTACHMENT_STORE_OP_DONT_CARE; - if (has_stencil) { + if (has_stencil && tbdr_read_only && device.IsQcomRenderPassStoreOpsSupported()) { + stencil_store_op = static_cast(1000301000); // VK_ATTACHMENT_STORE_OP_NONE_QCOM + } else if (has_stencil) { stencil_load_op = (is_tbdr && tbdr_will_clear) ? VK_ATTACHMENT_LOAD_OP_DONT_CARE : VK_ATTACHMENT_LOAD_OP_LOAD; stencil_store_op = (is_tbdr && tbdr_discard_after) ? VK_ATTACHMENT_STORE_OP_DONT_CARE @@ -154,7 +160,7 @@ VkRenderPass RenderPassCache::Get(const RenderPassKey& key) { .layout = VK_IMAGE_LAYOUT_GENERAL, }; descriptions.push_back(AttachmentDescription(*device, key.depth_format, key.samples, - key.tbdr_will_clear, key.tbdr_discard_after)); + key.tbdr_will_clear, key.tbdr_discard_after, key.tbdr_read_only)); } VkSubpassDescriptionFlags subpass_flags = 0; if (key.qcom_shader_resolve) { diff --git a/src/video_core/renderer_vulkan/vk_render_pass_cache.h b/src/video_core/renderer_vulkan/vk_render_pass_cache.h index c375b1996b..06bd8901a7 100644 --- a/src/video_core/renderer_vulkan/vk_render_pass_cache.h +++ b/src/video_core/renderer_vulkan/vk_render_pass_cache.h @@ -25,6 +25,7 @@ struct RenderPassKey { // These flags indicate the expected usage pattern to optimize load/store operations bool tbdr_will_clear{false}; // Attachment will be cleared with vkCmdClearAttachments bool tbdr_discard_after{false}; // Attachment won't be read after render pass + bool tbdr_read_only{false}; // Attachment is read-only (input attachment, depth test without writes) // VK_QCOM_render_pass_shader_resolve support bool qcom_shader_resolve{false}; // Use shader resolve instead of fixed-function (last subpass) diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index 5d48db5103..708dd6b087 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp @@ -539,6 +539,17 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR "Qualcomm drivers have a slow VK_KHR_push_descriptor implementation"); //RemoveExtension(extensions.push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); + // Log Qualcomm-specific optimizations + if (extensions.render_pass_store_ops) { + LOG_INFO(Render_Vulkan, "VK_QCOM_render_pass_store_ops: ENABLED (TBDR store optimization)"); + } + if (extensions.tile_properties) { + LOG_INFO(Render_Vulkan, "VK_QCOM_tile_properties: ENABLED (tile size queries available)"); + } + if (extensions.render_pass_shader_resolve) { + LOG_INFO(Render_Vulkan, "VK_QCOM_render_pass_shader_resolve: ENABLED (HDR+MSAA shader resolve)"); + } + #ifdef ANDROID // Shader Float Controls handling for Qualcomm Adreno // Default: DISABLED due to historical issues with binning precision causing visual glitches diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index 3e319724e8..ba516efd9c 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h @@ -63,7 +63,8 @@ VK_DEFINE_HANDLE(VmaAllocator) FEATURE(KHR, PipelineExecutableProperties, PIPELINE_EXECUTABLE_PROPERTIES, \ pipeline_executable_properties) \ FEATURE(KHR, WorkgroupMemoryExplicitLayout, WORKGROUP_MEMORY_EXPLICIT_LAYOUT, \ - workgroup_memory_explicit_layout) + workgroup_memory_explicit_layout) \ + FEATURE(QCOM, TileProperties, TILE_PROPERTIES, tile_properties_qcom) // Define miscellaneous extensions which may be used by the implementation here. #define FOR_EACH_VK_EXTENSION(EXTENSION) \ @@ -96,6 +97,8 @@ VK_DEFINE_HANDLE(VmaAllocator) EXTENSION(EXT, FILTER_CUBIC, filter_cubic) \ EXTENSION(QCOM, FILTER_CUBIC_WEIGHTS, filter_cubic_weights) \ EXTENSION(QCOM, RENDER_PASS_SHADER_RESOLVE, render_pass_shader_resolve) \ + EXTENSION(QCOM, RENDER_PASS_STORE_OPS, render_pass_store_ops) \ + EXTENSION(QCOM, TILE_PROPERTIES, tile_properties) \ EXTENSION(KHR, MAINTENANCE_1, maintenance1) \ EXTENSION(KHR, MAINTENANCE_2, maintenance2) \ EXTENSION(KHR, MAINTENANCE_3, maintenance3) \ @@ -588,6 +591,26 @@ public: return extensions.render_pass_shader_resolve; } + /// Returns true if the device supports VK_QCOM_render_pass_store_ops + bool IsQcomRenderPassStoreOpsSupported() const { + return extensions.render_pass_store_ops; + } + + /// Returns true if the device supports VK_QCOM_tile_properties + bool IsQcomTilePropertiesSupported() const { + return extensions.tile_properties; + } + + /// Returns Qualcomm tile size (width, height, depth). Returns {0,0,0} if not queried or unsupported + VkExtent3D GetQcomTileSize() const { + return properties.qcom_tile_size; + } + + /// Returns Qualcomm tile apron size. Returns {0,0} if not queried or unsupported + VkExtent2D GetQcomApronSize() const { + return properties.qcom_apron_size; + } + /// Returns true if MSAA copy operations are supported via compute shader (upload/download) /// Qualcomm uses render pass shader resolve instead, so this returns false for Qualcomm bool CanUploadMSAA() const { @@ -857,6 +880,8 @@ private: VkPhysicalDeviceSubgroupSizeControlProperties subgroup_size_control{}; VkPhysicalDeviceTransformFeedbackPropertiesEXT transform_feedback{}; VkPhysicalDeviceProperties properties{}; + VkExtent3D qcom_tile_size{}; // Qualcomm tile dimensions (0 if not queried) + VkExtent2D qcom_apron_size{}; // Qualcomm tile apron size }; Extensions extensions{};