77#include < cstring>
88#include < new>
99
10- #define LOG_TAG " osu_native "
10+ #define LOG_TAG " osu!native "
1111#define LOGI (...) __android_log_print(ANDROID_LOG_INFO , LOG_TAG , __VA_ARGS__)
1212#define LOGE (...) __android_log_print(ANDROID_LOG_ERROR , LOG_TAG , __VA_ARGS__)
1313
@@ -26,7 +26,8 @@ VulkanProbe::VulkanProbe() {
2626 available_ = true ;
2727
2828 LOGI (" Vulkan available: %s (Vendor: 0x%x, API %u.%u.%u, driver %u, VRAM %u MB, "
29- " qCount %u, mailbox %d, vk1.3 %d, sync2 %d, pWait %d, gpl %d, sObj %d, gPrio %d)" ,
29+ " qCount %u, vk1.3 %d, vk1.4 %d, sync2 %d, pWait %d, gpl %d, sObj %d, gPrio %d, "
30+ " hostCopy %d, pushDesc %d)" ,
3031 deviceInfo_.deviceName .c_str (),
3132 deviceInfo_.vendorId ,
3233 VK_VERSION_MAJOR (deviceInfo_.apiVersion ),
@@ -35,13 +36,15 @@ VulkanProbe::VulkanProbe() {
3536 deviceInfo_.driverVersion ,
3637 deviceInfo_.deviceLocalMemoryMB ,
3738 deviceInfo_.queueFamilyCount ,
38- deviceInfo_.supportsMailboxPresentMode ? 1 : 0 ,
3939 deviceInfo_.meetsVulkan13 ? 1 : 0 ,
40+ deviceInfo_.meetsVulkan14 ? 1 : 0 ,
4041 deviceInfo_.supportsSynchronization2 ? 1 : 0 ,
4142 deviceInfo_.supportsPresentWait ? 1 : 0 ,
4243 deviceInfo_.supportsGraphicsPipelineLibrary ? 1 : 0 ,
4344 deviceInfo_.supportsShaderObject ? 1 : 0 ,
44- deviceInfo_.supportsGlobalPriority ? 1 : 0 );
45+ deviceInfo_.supportsGlobalPriority ? 1 : 0 ,
46+ deviceInfo_.supportsHostImageCopy ? 1 : 0 ,
47+ deviceInfo_.supportsPushDescriptors ? 1 : 0 );
4548}
4649
4750VulkanProbe::~VulkanProbe () {
@@ -99,8 +102,15 @@ bool VulkanProbe::queryDevice() {
99102
100103 queryMemory (selected);
101104 queryQueueFamilies (selected);
102- queryVulkan13Features (selected);
105+ // Query extensions first (sets extension-based feature flags for pre-1.3 devices).
103106 queryModernExtensions (selected);
107+ // Feature queries for 1.3+ override extension-based values with actual feature support.
108+ queryVulkan13Features (selected);
109+
110+ // MAILBOX present mode cannot be queried without a VkSurfaceKHR (we have none in
111+ // this lightweight probe). The actual present mode is selected by the renderer
112+ // (Veldrid) at swapchain creation time via vkGetPhysicalDeviceSurfacePresentModesKHR.
113+ // We leave supportsMailboxPresentMode = false (default) to avoid false positives.
104114
105115 return true ;
106116}
@@ -137,26 +147,40 @@ void VulkanProbe::queryModernExtensions(VkPhysicalDevice device) {
137147 std::vector<VkExtensionProperties> exts (count);
138148 vkEnumerateDeviceExtensionProperties (device, nullptr , &count, exts.data ());
139149 for (const auto & ext : exts) {
140- if (strcmp (ext.extensionName , VK_KHR_SWAPCHAIN_EXTENSION_NAME ) == 0 ) { deviceInfo_.supportsSwapchain = true ; deviceInfo_. supportsMailboxPresentMode = true ; }
150+ if (strcmp (ext.extensionName , VK_KHR_SWAPCHAIN_EXTENSION_NAME ) == 0 ) deviceInfo_.supportsSwapchain = true ;
141151 if (strcmp (ext.extensionName , VK_KHR_PRESENT_ID_EXTENSION_NAME ) == 0 ) deviceInfo_.supportsPresentId = true ;
142152 if (strcmp (ext.extensionName , VK_KHR_PRESENT_WAIT_EXTENSION_NAME ) == 0 ) deviceInfo_.supportsPresentWait = true ;
143153 if (strcmp (ext.extensionName , VK_EXT_GRAPHICS_PIPELINE_LIBRARY_EXTENSION_NAME ) == 0 ) deviceInfo_.supportsGraphicsPipelineLibrary = true ;
144154 if (strcmp (ext.extensionName , VK_EXT_SHADER_OBJECT_EXTENSION_NAME ) == 0 ) deviceInfo_.supportsShaderObject = true ;
145155 if (strcmp (ext.extensionName , VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME ) == 0 || strcmp (ext.extensionName , VK_KHR_GLOBAL_PRIORITY_EXTENSION_NAME ) == 0 ) deviceInfo_.supportsGlobalPriority = true ;
146156 if (strcmp (ext.extensionName , VK_EXT_MEMORY_BUDGET_EXTENSION_NAME ) == 0 ) deviceInfo_.supportsMemoryBudget = true ;
147157 if (strcmp (ext.extensionName , " VK_EXT_surface_maintenance1" ) == 0 ) deviceInfo_.supportsSurfaceMaintenance1 = true ;
158+
159+ // Extension-based fallback for pre-1.3 devices (overridden by queryVulkan13Features on 1.3+).
160+ if (strcmp (ext.extensionName , " VK_KHR_dynamic_rendering" ) == 0 ) deviceInfo_.supportsDynamicRendering = true ;
161+ if (strcmp (ext.extensionName , " VK_KHR_synchronization2" ) == 0 ) deviceInfo_.supportsSynchronization2 = true ;
162+
163+ // Vulkan 1.4+ / Android 16+ extensions — used by string literals since NDK r29
164+ // headers may not define these macros.
165+ if (strcmp (ext.extensionName , " VK_EXT_host_image_copy" ) == 0 ) deviceInfo_.supportsHostImageCopy = true ;
166+ if (strcmp (ext.extensionName , " VK_KHR_push_descriptor" ) == 0 ) deviceInfo_.supportsPushDescriptors = true ;
148167 }
149168
150169 // ── Vendor-specific GPU quirks ──────────────────────────────────────
151170 // Qualcomm Adreno 7xx series: known flickering with PresentId/PresentWait
152171 // and broken Graphics Pipeline Library compilation on some driver versions.
153- if (deviceInfo_.vendorId == 0x5143 && (deviceInfo_.deviceName .find (" 740" ) != std::string::npos ||
154- deviceInfo_.deviceName .find (" 750" ) != std::string::npos ||
155- deviceInfo_.deviceName .find (" Adreno" ) != std::string::npos)) {
156- LOGI (" Adreno 7xx GPU detected: applying performance and flickering overrides" );
157- deviceInfo_.disablePresentId = true ;
158- deviceInfo_.disablePresentWait = true ;
159- deviceInfo_.disableGraphicsPipelineLibrary = true ;
172+ // Only target 7xx (730/740/750) — other Adreno generations are unaffected.
173+ if (deviceInfo_.vendorId == 0x5143 ) {
174+ const auto & name = deviceInfo_.deviceName ;
175+ bool isAdreno7xx = name.find (" 730" ) != std::string::npos ||
176+ name.find (" 740" ) != std::string::npos ||
177+ name.find (" 750" ) != std::string::npos;
178+ if (isAdreno7xx) {
179+ LOGI (" Adreno 7xx GPU detected: applying performance and flickering overrides" );
180+ deviceInfo_.disablePresentId = true ;
181+ deviceInfo_.disablePresentWait = true ;
182+ deviceInfo_.disableGraphicsPipelineLibrary = true ;
183+ }
160184 }
161185
162186 // ARM Mali (Samsung Exynos, MediaTek Dimensity, Google Tensor):
@@ -184,12 +208,18 @@ void VulkanProbe::queryModernExtensions(VkPhysicalDevice device) {
184208void VulkanProbe::queryVulkan13Features (VkPhysicalDevice device) {
185209 if (VK_VERSION_MAJOR (deviceInfo_.apiVersion ) < 1 || (VK_VERSION_MAJOR (deviceInfo_.apiVersion ) == 1 && VK_VERSION_MINOR (deviceInfo_.apiVersion ) < 3 )) return ;
186210 deviceInfo_.meetsVulkan13 = true ;
211+
212+ // Vulkan 1.4 is just a version check — no NDK header support needed.
213+ if (VK_VERSION_MINOR (deviceInfo_.apiVersion ) >= 4 )
214+ deviceInfo_.meetsVulkan14 = true ;
215+
187216 VkPhysicalDeviceVulkan13Features f13{};
188217 f13.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES ;
189218 VkPhysicalDeviceFeatures2 f2{};
190219 f2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2 ;
191220 f2.pNext = &f13;
192221 vkGetPhysicalDeviceFeatures2 (device, &f2);
222+ // Override extension-based flags with accurate feature queries for 1.3+ devices.
193223 deviceInfo_.supportsDynamicRendering = f13.dynamicRendering == VK_TRUE ;
194224 deviceInfo_.supportsSynchronization2 = f13.synchronization2 == VK_TRUE ;
195225}
@@ -227,4 +257,7 @@ OSU_EXPORT byte nVulkanSupportsSurfaceMaintenance1(intptr_t ptr) { return (ptr &
227257OSU_EXPORT byte nVulkanDisablePresentId (intptr_t ptr) { return (ptr && reinterpret_cast <VulkanProbe*>(ptr)->getDeviceInfo ().disablePresentId ) ? 1 : 0 ; }
228258OSU_EXPORT byte nVulkanDisablePresentWait (intptr_t ptr) { return (ptr && reinterpret_cast <VulkanProbe*>(ptr)->getDeviceInfo ().disablePresentWait ) ? 1 : 0 ; }
229259OSU_EXPORT byte nVulkanDisableGraphicsPipelineLibrary (intptr_t ptr) { return (ptr && reinterpret_cast <VulkanProbe*>(ptr)->getDeviceInfo ().disableGraphicsPipelineLibrary ) ? 1 : 0 ; }
260+ OSU_EXPORT byte nVulkanMeetsVulkan14 (intptr_t ptr) { return (ptr && reinterpret_cast <VulkanProbe*>(ptr)->getDeviceInfo ().meetsVulkan14 ) ? 1 : 0 ; }
261+ OSU_EXPORT byte nVulkanSupportsHostImageCopy (intptr_t ptr) { return (ptr && reinterpret_cast <VulkanProbe*>(ptr)->getDeviceInfo ().supportsHostImageCopy ) ? 1 : 0 ; }
262+ OSU_EXPORT byte nVulkanSupportsPushDescriptors (intptr_t ptr) { return (ptr && reinterpret_cast <VulkanProbe*>(ptr)->getDeviceInfo ().supportsPushDescriptors ) ? 1 : 0 ; }
230263}
0 commit comments