diff options
-rw-r--r-- | vulkan/libvulkan/driver.cpp | 56 | ||||
-rw-r--r-- | vulkan/libvulkan/driver_gen.cpp | 20 | ||||
-rw-r--r-- | vulkan/libvulkan/driver_gen.h | 4 | ||||
-rw-r--r-- | vulkan/libvulkan/swapchain.cpp | 624 | ||||
-rw-r--r-- | vulkan/libvulkan/swapchain.h | 1 | ||||
-rw-r--r-- | vulkan/scripts/driver_generator.py | 6 |
6 files changed, 183 insertions, 528 deletions
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp index b7e19d4296..9ed992b230 100644 --- a/vulkan/libvulkan/driver.cpp +++ b/vulkan/libvulkan/driver.cpp @@ -636,7 +636,6 @@ void CreateInfoWrapper::FilterExtension(const char* name) { case ProcHook::EXT_swapchain_colorspace: case ProcHook::KHR_get_surface_capabilities2: case ProcHook::GOOGLE_surfaceless_query: - case ProcHook::EXT_surface_maintenance1: hook_extensions_.set(ext_bit); // return now as these extensions do not require HAL support return; @@ -658,11 +657,9 @@ void CreateInfoWrapper::FilterExtension(const char* name) { case ProcHook::KHR_shared_presentable_image: case ProcHook::KHR_swapchain: case ProcHook::EXT_hdr_metadata: - case ProcHook::EXT_swapchain_maintenance1: case ProcHook::ANDROID_external_memory_android_hardware_buffer: case ProcHook::ANDROID_native_buffer: case ProcHook::GOOGLE_display_timing: - case ProcHook::KHR_external_fence_fd: case ProcHook::EXTENSION_CORE_1_0: case ProcHook::EXTENSION_CORE_1_1: case ProcHook::EXTENSION_CORE_1_2: @@ -693,22 +690,16 @@ void CreateInfoWrapper::FilterExtension(const char* name) { ext_bit = ProcHook::ANDROID_native_buffer; break; case ProcHook::KHR_incremental_present: - case ProcHook::KHR_shared_presentable_image: case ProcHook::GOOGLE_display_timing: + case ProcHook::KHR_shared_presentable_image: hook_extensions_.set(ext_bit); // return now as these extensions do not require HAL support return; - case ProcHook::EXT_swapchain_maintenance1: - // map VK_KHR_swapchain_maintenance1 to KHR_external_fence_fd - name = VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME; - ext_bit = ProcHook::KHR_external_fence_fd; - break; case ProcHook::EXT_hdr_metadata: case ProcHook::KHR_bind_memory2: hook_extensions_.set(ext_bit); break; case ProcHook::ANDROID_external_memory_android_hardware_buffer: - case ProcHook::KHR_external_fence_fd: case ProcHook::EXTENSION_UNKNOWN: // Extensions we don't need to do anything about at this level break; @@ -724,7 +715,6 @@ void CreateInfoWrapper::FilterExtension(const char* name) { case ProcHook::KHR_surface_protected_capabilities: case ProcHook::EXT_debug_report: case ProcHook::EXT_swapchain_colorspace: - case ProcHook::EXT_surface_maintenance1: case ProcHook::GOOGLE_surfaceless_query: case ProcHook::ANDROID_native_buffer: case ProcHook::EXTENSION_CORE_1_0: @@ -761,8 +751,6 @@ void CreateInfoWrapper::FilterExtension(const char* name) { if (ext_bit != ProcHook::EXTENSION_UNKNOWN) { if (ext_bit == ProcHook::ANDROID_native_buffer) hook_extensions_.set(ProcHook::KHR_swapchain); - if (ext_bit == ProcHook::KHR_external_fence_fd) - hook_extensions_.set(ProcHook::EXT_swapchain_maintenance1); hal_extensions_.set(ext_bit); } @@ -952,9 +940,6 @@ VkResult EnumerateInstanceExtensionProperties( VK_KHR_GET_SURFACE_CAPABILITIES_2_SPEC_VERSION}); loader_extensions.push_back({VK_GOOGLE_SURFACELESS_QUERY_EXTENSION_NAME, VK_GOOGLE_SURFACELESS_QUERY_SPEC_VERSION}); - loader_extensions.push_back({ - VK_EXT_SURFACE_MAINTENANCE_1_EXTENSION_NAME, - VK_EXT_SURFACE_MAINTENANCE_1_SPEC_VERSION}); static const VkExtensionProperties loader_debug_report_extension = { VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION, @@ -1087,33 +1072,6 @@ VkResult GetAndroidNativeBufferSpecVersion9Support( return result; } -bool CanSupportSwapchainMaintenance1Extension(VkPhysicalDevice physicalDevice) { - const auto& driver = GetData(physicalDevice).driver; - if (!driver.GetPhysicalDeviceExternalFenceProperties) - return false; - - // Requires support for external fences imported from sync fds. - // This is _almost_ universal on Android, but may be missing on - // some extremely old drivers, or on strange implementations like - // cuttlefish. - VkPhysicalDeviceExternalFenceInfo fenceInfo = { - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO, - nullptr, - VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT - }; - VkExternalFenceProperties fenceProperties = { - VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES, - nullptr, - 0, 0, 0 - }; - - GetPhysicalDeviceExternalFenceProperties(physicalDevice, &fenceInfo, &fenceProperties); - if (fenceProperties.externalFenceFeatures & VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT) - return true; - - return false; -} - VkResult EnumerateDeviceExtensionProperties( VkPhysicalDevice physicalDevice, const char* pLayerName, @@ -1191,12 +1149,6 @@ VkResult EnumerateDeviceExtensionProperties( VK_EXT_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN_SPEC_VERSION}); } - if (CanSupportSwapchainMaintenance1Extension(physicalDevice)) { - loader_extensions.push_back({ - VK_EXT_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME, - VK_EXT_SWAPCHAIN_MAINTENANCE_1_SPEC_VERSION}); - } - // enumerate our extensions first if (!pLayerName && pProperties) { uint32_t count = std::min( @@ -1692,12 +1644,6 @@ void GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice, imageCompressionControlSwapchainInChain = true; } break; - case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SWAPCHAIN_MAINTENANCE_1_FEATURES_EXT: { - auto smf = reinterpret_cast<VkPhysicalDeviceSwapchainMaintenance1FeaturesEXT *>( - pFeats); - smf->swapchainMaintenance1 = true; - } break; - default: break; } diff --git a/vulkan/libvulkan/driver_gen.cpp b/vulkan/libvulkan/driver_gen.cpp index 798af5c6a6..de98aa7e61 100644 --- a/vulkan/libvulkan/driver_gen.cpp +++ b/vulkan/libvulkan/driver_gen.cpp @@ -162,15 +162,6 @@ VKAPI_ATTR void checkedGetDeviceQueue2(VkDevice device, const VkDeviceQueueInfo2 } } -VKAPI_ATTR VkResult checkedReleaseSwapchainImagesEXT(VkDevice device, const VkReleaseSwapchainImagesInfoEXT* pReleaseInfo) { - if (GetData(device).hook_extensions[ProcHook::EXT_swapchain_maintenance1]) { - return ReleaseSwapchainImagesEXT(device, pReleaseInfo); - } else { - Logger(device).Err(device, "VK_EXT_swapchain_maintenance1 not enabled. vkReleaseSwapchainImagesEXT not executed."); - return VK_SUCCESS; - } -} - // clang-format on const ProcHook g_proc_hooks[] = { @@ -554,13 +545,6 @@ const ProcHook g_proc_hooks[] = { nullptr, }, { - "vkReleaseSwapchainImagesEXT", - ProcHook::DEVICE, - ProcHook::EXT_swapchain_maintenance1, - reinterpret_cast<PFN_vkVoidFunction>(ReleaseSwapchainImagesEXT), - reinterpret_cast<PFN_vkVoidFunction>(checkedReleaseSwapchainImagesEXT), - }, - { "vkSetHdrMetadataEXT", ProcHook::DEVICE, ProcHook::EXT_hdr_metadata, @@ -596,8 +580,6 @@ ProcHook::Extension GetProcHookExtension(const char* name) { if (strcmp(name, "VK_KHR_surface") == 0) return ProcHook::KHR_surface; if (strcmp(name, "VK_KHR_surface_protected_capabilities") == 0) return ProcHook::KHR_surface_protected_capabilities; if (strcmp(name, "VK_KHR_swapchain") == 0) return ProcHook::KHR_swapchain; - if (strcmp(name, "VK_EXT_swapchain_maintenance1") == 0) return ProcHook::EXT_swapchain_maintenance1; - if (strcmp(name, "VK_EXT_surface_maintenance1") == 0) return ProcHook::EXT_surface_maintenance1; if (strcmp(name, "VK_ANDROID_external_memory_android_hardware_buffer") == 0) return ProcHook::ANDROID_external_memory_android_hardware_buffer; if (strcmp(name, "VK_KHR_bind_memory2") == 0) return ProcHook::KHR_bind_memory2; if (strcmp(name, "VK_KHR_get_physical_device_properties2") == 0) return ProcHook::KHR_get_physical_device_properties2; @@ -605,7 +587,6 @@ ProcHook::Extension GetProcHookExtension(const char* name) { if (strcmp(name, "VK_KHR_external_memory_capabilities") == 0) return ProcHook::KHR_external_memory_capabilities; if (strcmp(name, "VK_KHR_external_semaphore_capabilities") == 0) return ProcHook::KHR_external_semaphore_capabilities; if (strcmp(name, "VK_KHR_external_fence_capabilities") == 0) return ProcHook::KHR_external_fence_capabilities; - if (strcmp(name, "VK_KHR_external_fence_fd") == 0) return ProcHook::KHR_external_fence_fd; // clang-format on return ProcHook::EXTENSION_UNKNOWN; } @@ -685,7 +666,6 @@ bool InitDriverTable(VkDevice dev, INIT_PROC(true, dev, CreateImage); INIT_PROC(true, dev, DestroyImage); INIT_PROC(true, dev, AllocateCommandBuffers); - INIT_PROC_EXT(KHR_external_fence_fd, true, dev, ImportFenceFdKHR); INIT_PROC(false, dev, BindImageMemory2); INIT_PROC_EXT(KHR_bind_memory2, true, dev, BindImageMemory2KHR); INIT_PROC(false, dev, GetDeviceQueue2); diff --git a/vulkan/libvulkan/driver_gen.h b/vulkan/libvulkan/driver_gen.h index 31ba04ba1f..2f60086a27 100644 --- a/vulkan/libvulkan/driver_gen.h +++ b/vulkan/libvulkan/driver_gen.h @@ -49,8 +49,6 @@ struct ProcHook { KHR_surface, KHR_surface_protected_capabilities, KHR_swapchain, - EXT_swapchain_maintenance1, - EXT_surface_maintenance1, ANDROID_external_memory_android_hardware_buffer, KHR_bind_memory2, KHR_get_physical_device_properties2, @@ -58,7 +56,6 @@ struct ProcHook { KHR_external_memory_capabilities, KHR_external_semaphore_capabilities, KHR_external_fence_capabilities, - KHR_external_fence_fd, EXTENSION_CORE_1_0, EXTENSION_CORE_1_1, @@ -121,7 +118,6 @@ struct DeviceDriverTable { PFN_vkCreateImage CreateImage; PFN_vkDestroyImage DestroyImage; PFN_vkAllocateCommandBuffers AllocateCommandBuffers; - PFN_vkImportFenceFdKHR ImportFenceFdKHR; PFN_vkBindImageMemory2 BindImageMemory2; PFN_vkBindImageMemory2KHR BindImageMemory2KHR; PFN_vkGetDeviceQueue2 GetDeviceQueue2; diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp index 1bff50dd7f..b03200e4a7 100644 --- a/vulkan/libvulkan/swapchain.cpp +++ b/vulkan/libvulkan/swapchain.cpp @@ -291,9 +291,6 @@ struct Swapchain { release_fence(-1), dequeued(false) {} VkImage image; - // If the image is bound to memory, an sp to the underlying gralloc buffer. - // Otherwise, nullptr; the image will be bound to memory as part of - // AcquireNextImage. android::sp<ANativeWindowBuffer> buffer; // The fence is only valid when the buffer is dequeued, and should be // -1 any other time. When valid, we own the fd, and must ensure it is @@ -659,40 +656,100 @@ VkResult GetPhysicalDeviceSurfaceCapabilitiesKHR( VkSurfaceCapabilitiesKHR* capabilities) { ATRACE_CALL(); - // Implement in terms of GetPhysicalDeviceSurfaceCapabilities2KHR + int err; + int width, height; + int transform_hint; + int max_buffer_count; + if (surface == VK_NULL_HANDLE) { + const InstanceData& instance_data = GetData(pdev); + ProcHook::Extension surfaceless = ProcHook::GOOGLE_surfaceless_query; + bool surfaceless_enabled = + instance_data.hook_extensions.test(surfaceless); + if (!surfaceless_enabled) { + // It is an error to pass a surface==VK_NULL_HANDLE unless the + // VK_GOOGLE_surfaceless_query extension is enabled + return VK_ERROR_SURFACE_LOST_KHR; + } + // Support for VK_GOOGLE_surfaceless_query. The primary purpose of this + // extension for this function is for + // VkSurfaceProtectedCapabilitiesKHR::supportsProtected. The following + // four values cannot be known without a surface. Default values will + // be supplied anyway, but cannot be relied upon. + width = 0xFFFFFFFF; + height = 0xFFFFFFFF; + transform_hint = VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR; + capabilities->minImageCount = 0xFFFFFFFF; + capabilities->maxImageCount = 0xFFFFFFFF; + } else { + ANativeWindow* window = SurfaceFromHandle(surface)->window.get(); - VkPhysicalDeviceSurfaceInfo2KHR info2 = { - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR, - nullptr, - surface - }; + err = window->query(window, NATIVE_WINDOW_DEFAULT_WIDTH, &width); + if (err != android::OK) { + ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)", + strerror(-err), err); + return VK_ERROR_SURFACE_LOST_KHR; + } + err = window->query(window, NATIVE_WINDOW_DEFAULT_HEIGHT, &height); + if (err != android::OK) { + ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)", + strerror(-err), err); + return VK_ERROR_SURFACE_LOST_KHR; + } - VkSurfaceCapabilities2KHR caps2 = { - VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR, - nullptr, - {}, - }; + err = window->query(window, NATIVE_WINDOW_TRANSFORM_HINT, + &transform_hint); + if (err != android::OK) { + ALOGE("NATIVE_WINDOW_TRANSFORM_HINT query failed: %s (%d)", + strerror(-err), err); + return VK_ERROR_SURFACE_LOST_KHR; + } - VkResult result = GetPhysicalDeviceSurfaceCapabilities2KHR(pdev, &info2, &caps2); - *capabilities = caps2.surfaceCapabilities; - return result; -} + err = window->query(window, NATIVE_WINDOW_MAX_BUFFER_COUNT, + &max_buffer_count); + if (err != android::OK) { + ALOGE("NATIVE_WINDOW_MAX_BUFFER_COUNT query failed: %s (%d)", + strerror(-err), err); + return VK_ERROR_SURFACE_LOST_KHR; + } + capabilities->minImageCount = std::min(max_buffer_count, 3); + capabilities->maxImageCount = static_cast<uint32_t>(max_buffer_count); + } -// Does the call-twice and VK_INCOMPLETE handling for querying lists -// of things, where we already have the full set built in a vector. -template <typename T> -VkResult CopyWithIncomplete(std::vector<T> const& things, - T* callerPtr, uint32_t* callerCount) { - VkResult result = VK_SUCCESS; - if (callerPtr) { - if (things.size() > *callerCount) - result = VK_INCOMPLETE; - *callerCount = std::min(uint32_t(things.size()), *callerCount); - std::copy(things.begin(), things.begin() + *callerCount, callerPtr); - } else { - *callerCount = things.size(); + capabilities->currentExtent = + VkExtent2D{static_cast<uint32_t>(width), static_cast<uint32_t>(height)}; + + // TODO(http://b/134182502): Figure out what the max extent should be. + capabilities->minImageExtent = VkExtent2D{1, 1}; + capabilities->maxImageExtent = VkExtent2D{4096, 4096}; + + if (capabilities->maxImageExtent.height < + capabilities->currentExtent.height) { + capabilities->maxImageExtent.height = + capabilities->currentExtent.height; } - return result; + + if (capabilities->maxImageExtent.width < + capabilities->currentExtent.width) { + capabilities->maxImageExtent.width = capabilities->currentExtent.width; + } + + capabilities->maxImageArrayLayers = 1; + + capabilities->supportedTransforms = kSupportedTransforms; + capabilities->currentTransform = + TranslateNativeToVulkanTransform(transform_hint); + + // On Android, window composition is a WindowManager property, not something + // associated with the bufferqueue. It can't be changed from here. + capabilities->supportedCompositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR; + + capabilities->supportedUsageFlags = + VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | + VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT | + VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | + VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; + + return VK_SUCCESS; } VKAPI_ATTR @@ -825,7 +882,21 @@ VkResult GetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice pdev, // Android users. This includes the ANGLE team (a layered implementation of // OpenGL-ES). - return CopyWithIncomplete(all_formats, formats, count); + VkResult result = VK_SUCCESS; + if (formats) { + uint32_t transfer_count = all_formats.size(); + if (transfer_count > *count) { + transfer_count = *count; + result = VK_INCOMPLETE; + } + std::copy(all_formats.begin(), all_formats.begin() + transfer_count, + formats); + *count = transfer_count; + } else { + *count = all_formats.size(); + } + + return result; } VKAPI_ATTR @@ -835,134 +906,19 @@ VkResult GetPhysicalDeviceSurfaceCapabilities2KHR( VkSurfaceCapabilities2KHR* pSurfaceCapabilities) { ATRACE_CALL(); - auto surface = pSurfaceInfo->surface; - auto capabilities = &pSurfaceCapabilities->surfaceCapabilities; - - VkSurfacePresentModeEXT const *pPresentMode = nullptr; - for (auto pNext = reinterpret_cast<VkBaseInStructure const *>(pSurfaceInfo->pNext); - pNext; pNext = reinterpret_cast<VkBaseInStructure const *>(pNext->pNext)) { - switch (pNext->sType) { - case VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_EXT: - pPresentMode = reinterpret_cast<VkSurfacePresentModeEXT const *>(pNext); - break; - - default: - break; - } - } + VkResult result = GetPhysicalDeviceSurfaceCapabilitiesKHR( + physicalDevice, pSurfaceInfo->surface, + &pSurfaceCapabilities->surfaceCapabilities); - int err; - int width, height; - int transform_hint; - int max_buffer_count; - if (surface == VK_NULL_HANDLE) { - const InstanceData& instance_data = GetData(physicalDevice); - ProcHook::Extension surfaceless = ProcHook::GOOGLE_surfaceless_query; - bool surfaceless_enabled = - instance_data.hook_extensions.test(surfaceless); - if (!surfaceless_enabled) { - // It is an error to pass a surface==VK_NULL_HANDLE unless the - // VK_GOOGLE_surfaceless_query extension is enabled - return VK_ERROR_SURFACE_LOST_KHR; - } - // Support for VK_GOOGLE_surfaceless_query. The primary purpose of this - // extension for this function is for - // VkSurfaceProtectedCapabilitiesKHR::supportsProtected. The following - // four values cannot be known without a surface. Default values will - // be supplied anyway, but cannot be relied upon. - width = 0xFFFFFFFF; - height = 0xFFFFFFFF; - transform_hint = VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR; - capabilities->minImageCount = 0xFFFFFFFF; - capabilities->maxImageCount = 0xFFFFFFFF; - } else { - ANativeWindow* window = SurfaceFromHandle(surface)->window.get(); + VkSurfaceCapabilities2KHR* caps = pSurfaceCapabilities; + while (caps->pNext) { + caps = reinterpret_cast<VkSurfaceCapabilities2KHR*>(caps->pNext); - err = window->query(window, NATIVE_WINDOW_DEFAULT_WIDTH, &width); - if (err != android::OK) { - ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)", - strerror(-err), err); - return VK_ERROR_SURFACE_LOST_KHR; - } - err = window->query(window, NATIVE_WINDOW_DEFAULT_HEIGHT, &height); - if (err != android::OK) { - ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)", - strerror(-err), err); - return VK_ERROR_SURFACE_LOST_KHR; - } - - err = window->query(window, NATIVE_WINDOW_TRANSFORM_HINT, - &transform_hint); - if (err != android::OK) { - ALOGE("NATIVE_WINDOW_TRANSFORM_HINT query failed: %s (%d)", - strerror(-err), err); - return VK_ERROR_SURFACE_LOST_KHR; - } - - err = window->query(window, NATIVE_WINDOW_MAX_BUFFER_COUNT, - &max_buffer_count); - if (err != android::OK) { - ALOGE("NATIVE_WINDOW_MAX_BUFFER_COUNT query failed: %s (%d)", - strerror(-err), err); - return VK_ERROR_SURFACE_LOST_KHR; - } - - if (pPresentMode && IsSharedPresentMode(pPresentMode->presentMode)) { - capabilities->minImageCount = 1; - capabilities->maxImageCount = 1; - } else if (pPresentMode && pPresentMode->presentMode == VK_PRESENT_MODE_MAILBOX_KHR) { - // TODO: use undequeued buffer requirement for more precise bound - capabilities->minImageCount = std::min(max_buffer_count, 4); - capabilities->maxImageCount = static_cast<uint32_t>(max_buffer_count); - } else { - // TODO: if we're able to, provide better bounds on the number of buffers - // for other modes as well. - capabilities->minImageCount = std::min(max_buffer_count, 3); - capabilities->maxImageCount = static_cast<uint32_t>(max_buffer_count); - } - } - - capabilities->currentExtent = - VkExtent2D{static_cast<uint32_t>(width), static_cast<uint32_t>(height)}; - - // TODO(http://b/134182502): Figure out what the max extent should be. - capabilities->minImageExtent = VkExtent2D{1, 1}; - capabilities->maxImageExtent = VkExtent2D{4096, 4096}; - - if (capabilities->maxImageExtent.height < - capabilities->currentExtent.height) { - capabilities->maxImageExtent.height = - capabilities->currentExtent.height; - } - - if (capabilities->maxImageExtent.width < - capabilities->currentExtent.width) { - capabilities->maxImageExtent.width = capabilities->currentExtent.width; - } - - capabilities->maxImageArrayLayers = 1; - - capabilities->supportedTransforms = kSupportedTransforms; - capabilities->currentTransform = - TranslateNativeToVulkanTransform(transform_hint); - - // On Android, window composition is a WindowManager property, not something - // associated with the bufferqueue. It can't be changed from here. - capabilities->supportedCompositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR; - - capabilities->supportedUsageFlags = - VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | - VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT | - VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | - VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; - - for (auto pNext = reinterpret_cast<VkBaseOutStructure*>(pSurfaceCapabilities->pNext); - pNext; pNext = reinterpret_cast<VkBaseOutStructure*>(pNext->pNext)) { - - switch (pNext->sType) { + switch (caps->sType) { case VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR: { VkSharedPresentSurfaceCapabilitiesKHR* shared_caps = - reinterpret_cast<VkSharedPresentSurfaceCapabilitiesKHR*>(pNext); + reinterpret_cast<VkSharedPresentSurfaceCapabilitiesKHR*>( + caps); // Claim same set of usage flags are supported for // shared present modes as for other modes. shared_caps->sharedPresentSupportedUsageFlags = @@ -972,64 +928,17 @@ VkResult GetPhysicalDeviceSurfaceCapabilities2KHR( case VK_STRUCTURE_TYPE_SURFACE_PROTECTED_CAPABILITIES_KHR: { VkSurfaceProtectedCapabilitiesKHR* protected_caps = - reinterpret_cast<VkSurfaceProtectedCapabilitiesKHR*>(pNext); + reinterpret_cast<VkSurfaceProtectedCapabilitiesKHR*>(caps); protected_caps->supportsProtected = VK_TRUE; } break; - case VK_STRUCTURE_TYPE_SURFACE_PRESENT_SCALING_CAPABILITIES_EXT: { - VkSurfacePresentScalingCapabilitiesEXT* scaling_caps = - reinterpret_cast<VkSurfacePresentScalingCapabilitiesEXT*>(pNext); - // By default, Android stretches the buffer to fit the window, - // without preserving aspect ratio. Other modes are technically possible - // but consult with CoGS team before exposing them here! - scaling_caps->supportedPresentScaling = VK_PRESENT_SCALING_STRETCH_BIT_EXT; - - // Since we always scale, we don't support any gravity. - scaling_caps->supportedPresentGravityX = 0; - scaling_caps->supportedPresentGravityY = 0; - - // Scaled image limits are just the basic image limits - scaling_caps->minScaledImageExtent = capabilities->minImageExtent; - scaling_caps->maxScaledImageExtent = capabilities->maxImageExtent; - } break; - - case VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_COMPATIBILITY_EXT: { - VkSurfacePresentModeCompatibilityEXT* mode_caps = - reinterpret_cast<VkSurfacePresentModeCompatibilityEXT*>(pNext); - - ALOG_ASSERT(pPresentMode, - "querying VkSurfacePresentModeCompatibilityEXT " - "requires VkSurfacePresentModeEXT to be provided"); - std::vector<VkPresentModeKHR> compatibleModes; - compatibleModes.push_back(pPresentMode->presentMode); - - switch (pPresentMode->presentMode) { - // Shared modes are both compatible with each other. - case VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR: - compatibleModes.push_back(VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR); - break; - case VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR: - compatibleModes.push_back(VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR); - break; - default: - // Other modes are only compatible with themselves. - // TODO: consider whether switching between FIFO and MAILBOX is reasonable - break; - } - - // Note: this does not generate VK_INCOMPLETE since we're nested inside - // a larger query and there would be no way to determine exactly where it came from. - CopyWithIncomplete(compatibleModes, mode_caps->pPresentModes, - &mode_caps->presentModeCount); - } break; - default: // Ignore all other extension structs break; } } - return VK_SUCCESS; + return result; } VKAPI_ATTR @@ -1188,7 +1097,18 @@ VkResult GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice pdev, present_modes.push_back(VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR); } - return CopyWithIncomplete(present_modes, modes, count); + uint32_t num_modes = uint32_t(present_modes.size()); + + VkResult result = VK_SUCCESS; + if (modes) { + if (*count < num_modes) + result = VK_INCOMPLETE; + *count = std::min(*count, num_modes); + std::copy_n(present_modes.data(), *count, modes); + } else { + *count = num_modes; + } + return result; } VKAPI_ATTR @@ -1474,7 +1394,8 @@ VkResult CreateSwapchainKHR(VkDevice device, } VkSwapchainImageUsageFlagsANDROID swapchain_image_usage = 0; - if (IsSharedPresentMode(create_info->presentMode)) { + if (create_info->presentMode == VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR || + create_info->presentMode == VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR) { swapchain_image_usage |= VK_SWAPCHAIN_IMAGE_USAGE_SHARED_BIT_ANDROID; err = native_window_set_shared_buffer_mode(window, true); if (err != android::OK) { @@ -1624,6 +1545,8 @@ VkResult CreateSwapchainKHR(VkDevice device, Swapchain* swapchain = new (mem) Swapchain(surface, num_images, create_info->presentMode, TranslateVulkanToNativeTransform(create_info->preTransform)); + // -- Dequeue all buffers and create a VkImage for each -- + // Any failures during or after this must cancel the dequeued buffers. VkSwapchainImageCreateInfoANDROID swapchain_image_create = { #pragma clang diagnostic push @@ -1640,18 +1563,13 @@ VkResult CreateSwapchainKHR(VkDevice device, #pragma clang diagnostic pop .pNext = &swapchain_image_create, }; - VkImageCreateInfo image_create = { .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, - .pNext = nullptr, + .pNext = &image_native_buffer, .flags = createProtectedSwapchain ? VK_IMAGE_CREATE_PROTECTED_BIT : 0u, .imageType = VK_IMAGE_TYPE_2D, .format = create_info->imageFormat, - .extent = { - create_info->imageExtent.width, - create_info->imageExtent.height, - 1 - }, + .extent = {0, 0, 1}, .mipLevels = 1, .arrayLayers = 1, .samples = VK_SAMPLE_COUNT_1_BIT, @@ -1662,87 +1580,60 @@ VkResult CreateSwapchainKHR(VkDevice device, .pQueueFamilyIndices = create_info->pQueueFamilyIndices, }; - // Note: don't do deferred allocation for shared present modes. There's only one buffer - // involved so very little benefit. - if ((create_info->flags & VK_SWAPCHAIN_CREATE_DEFERRED_MEMORY_ALLOCATION_BIT_EXT) && - !IsSharedPresentMode(create_info->presentMode)) { - // Don't want to touch the underlying gralloc buffers yet; - // instead just create unbound VkImages which will later be bound to memory inside - // AcquireNextImage. - VkImageSwapchainCreateInfoKHR image_swapchain_create = { - .sType = VK_STRUCTURE_TYPE_IMAGE_SWAPCHAIN_CREATE_INFO_KHR, - .pNext = nullptr, - .swapchain = HandleFromSwapchain(swapchain), - }; - image_create.pNext = &image_swapchain_create; - - for (uint32_t i = 0; i < num_images; i++) { - Swapchain::Image& img = swapchain->images[i]; - img.buffer = nullptr; - img.dequeued = false; + for (uint32_t i = 0; i < num_images; i++) { + Swapchain::Image& img = swapchain->images[i]; - result = dispatch.CreateImage(device, &image_create, nullptr, &img.image); - if (result != VK_SUCCESS) { - ALOGD("vkCreateImage w/ for deferred swapchain image failed: %u", result); - break; + ANativeWindowBuffer* buffer; + err = window->dequeueBuffer(window, &buffer, &img.dequeue_fence); + if (err != android::OK) { + ALOGE("dequeueBuffer[%u] failed: %s (%d)", i, strerror(-err), err); + switch (-err) { + case ENOMEM: + result = VK_ERROR_OUT_OF_DEVICE_MEMORY; + break; + default: + result = VK_ERROR_SURFACE_LOST_KHR; + break; } + break; } - } else { - // -- Dequeue all buffers and create a VkImage for each -- - // Any failures during or after this must cancel the dequeued buffers. - - for (uint32_t i = 0; i < num_images; i++) { - Swapchain::Image& img = swapchain->images[i]; - - ANativeWindowBuffer* buffer; - err = window->dequeueBuffer(window, &buffer, &img.dequeue_fence); - if (err != android::OK) { - ALOGE("dequeueBuffer[%u] failed: %s (%d)", i, strerror(-err), err); - switch (-err) { - case ENOMEM: - result = VK_ERROR_OUT_OF_DEVICE_MEMORY; - break; - default: - result = VK_ERROR_SURFACE_LOST_KHR; - break; - } - break; - } - img.buffer = buffer; - img.dequeued = true; - - image_native_buffer.handle = img.buffer->handle; - image_native_buffer.stride = img.buffer->stride; - image_native_buffer.format = img.buffer->format; - image_native_buffer.usage = int(img.buffer->usage); - android_convertGralloc0To1Usage(int(img.buffer->usage), - &image_native_buffer.usage2.producer, - &image_native_buffer.usage2.consumer); - image_native_buffer.usage3 = img.buffer->usage; - image_create.pNext = &image_native_buffer; - - ATRACE_BEGIN("CreateImage"); - result = - dispatch.CreateImage(device, &image_create, nullptr, &img.image); - ATRACE_END(); - if (result != VK_SUCCESS) { - ALOGD("vkCreateImage w/ native buffer failed: %u", result); - break; - } + img.buffer = buffer; + img.dequeued = true; + + image_create.extent = + VkExtent3D{static_cast<uint32_t>(img.buffer->width), + static_cast<uint32_t>(img.buffer->height), + 1}; + image_native_buffer.handle = img.buffer->handle; + image_native_buffer.stride = img.buffer->stride; + image_native_buffer.format = img.buffer->format; + image_native_buffer.usage = int(img.buffer->usage); + android_convertGralloc0To1Usage(int(img.buffer->usage), + &image_native_buffer.usage2.producer, + &image_native_buffer.usage2.consumer); + image_native_buffer.usage3 = img.buffer->usage; + + ATRACE_BEGIN("CreateImage"); + result = + dispatch.CreateImage(device, &image_create, nullptr, &img.image); + ATRACE_END(); + if (result != VK_SUCCESS) { + ALOGD("vkCreateImage w/ native buffer failed: %u", result); + break; } + } - // -- Cancel all buffers, returning them to the queue -- - // If an error occurred before, also destroy the VkImage and release the - // buffer reference. Otherwise, we retain a strong reference to the buffer. - for (uint32_t i = 0; i < num_images; i++) { - Swapchain::Image& img = swapchain->images[i]; - if (img.dequeued) { - if (!swapchain->shared) { - window->cancelBuffer(window, img.buffer.get(), - img.dequeue_fence); - img.dequeue_fence = -1; - img.dequeued = false; - } + // -- Cancel all buffers, returning them to the queue -- + // If an error occurred before, also destroy the VkImage and release the + // buffer reference. Otherwise, we retain a strong reference to the buffer. + for (uint32_t i = 0; i < num_images; i++) { + Swapchain::Image& img = swapchain->images[i]; + if (img.dequeued) { + if (!swapchain->shared) { + window->cancelBuffer(window, img.buffer.get(), + img.dequeue_fence); + img.dequeue_fence = -1; + img.dequeued = false; } } } @@ -1865,64 +1756,6 @@ VkResult AcquireNextImageKHR(VkDevice device, break; } } - - // If this is a deferred alloc swapchain, this may be the first time we've - // seen a particular buffer. If so, there should be an empty slot. Find it, - // and bind the gralloc buffer to the VkImage for that slot. If there is no - // empty slot, then we dequeued an unexpected buffer. Non-deferred swapchains - // will also take this path, but will never have an empty slot since we - // populated them all upfront. - if (idx == swapchain.num_images) { - for (idx = 0; idx < swapchain.num_images; idx++) { - if (!swapchain.images[idx].buffer) { - // Note: this structure is technically required for - // Vulkan correctness, even though the driver is probably going - // to use everything from the VkNativeBufferANDROID below. - // This is kindof silly, but it's how we did the ANB - // side of VK_KHR_swapchain v69, so we're stuck with it unless - // we want to go tinkering with the ANB spec some more. - VkBindImageMemorySwapchainInfoKHR bimsi = { - .sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR, - .pNext = nullptr, - .swapchain = swapchain_handle, - .imageIndex = idx, - }; - VkNativeBufferANDROID nb = { - .sType = VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID, - .pNext = &bimsi, - .handle = buffer->handle, - .stride = buffer->stride, - .format = buffer->format, - .usage = int(buffer->usage), - }; - VkBindImageMemoryInfo bimi = { - .sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO, - .pNext = &nb, - .image = swapchain.images[idx].image, - .memory = VK_NULL_HANDLE, - .memoryOffset = 0, - }; - result = GetData(device).driver.BindImageMemory2(device, 1, &bimi); - if (result != VK_SUCCESS) { - // This shouldn't really happen. If it does, something is probably - // unrecoverably wrong with the swapchain and its images. Cancel - // the buffer and declare the swapchain broken. - ALOGE("failed to do deferred gralloc buffer bind"); - window->cancelBuffer(window, buffer, fence_fd); - return VK_ERROR_OUT_OF_DATE_KHR; - } - - swapchain.images[idx].dequeued = true; - swapchain.images[idx].dequeue_fence = fence_fd; - swapchain.images[idx].buffer = buffer; - break; - } - } - } - - // The buffer doesn't match any slot. This shouldn't normally happen, but is - // possible if the bufferqueue is reconfigured behind libvulkan's back. If this - // happens, just declare the swapchain to be broken and the app will recreate it. if (idx == swapchain.num_images) { ALOGE("dequeueBuffer returned unrecognized buffer"); window->cancelBuffer(window, buffer, fence_fd); @@ -2048,32 +1881,12 @@ static void SetSwapchainFrameTimestamp(Swapchain &swapchain, const VkPresentTime } } -// EXT_swapchain_maintenance1 present mode change -static bool SetSwapchainPresentMode(ANativeWindow *window, VkPresentModeKHR mode) { - // There is no dynamic switching between non-shared present modes. - // All we support is switching between demand and continuous refresh. - if (!IsSharedPresentMode(mode)) - return true; - - int err = native_window_set_auto_refresh(window, - mode == VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR); - if (err != android::OK) { - ALOGE("native_window_set_auto_refresh() failed: %s (%d)", - strerror(-err), err); - return false; - } - - return true; -} - static VkResult PresentOneSwapchain( VkQueue queue, Swapchain& swapchain, uint32_t imageIndex, const VkPresentRegionKHR *pRegion, const VkPresentTimeGOOGLE *pTime, - VkFence presentFence, - const VkPresentModeKHR *pPresentMode, uint32_t waitSemaphoreCount, const VkSemaphore *pWaitSemaphores) { @@ -2104,33 +1917,12 @@ static VkResult PresentOneSwapchain( ANativeWindow* window = swapchain.surface.window.get(); if (swapchain_result == VK_SUCCESS) { - if (presentFence != VK_NULL_HANDLE) { - int fence_copy = fence < 0 ? -1 : dup(fence); - VkImportFenceFdInfoKHR iffi = { - VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR, - nullptr, - presentFence, - VK_FENCE_IMPORT_TEMPORARY_BIT, - VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT, - fence_copy, - }; - if (VK_SUCCESS != dispatch.ImportFenceFdKHR(device, &iffi) && fence_copy >= 0) { - // ImportFenceFdKHR takes ownership only if it succeeds - close(fence_copy); - } - } - if (pRegion) { SetSwapchainSurfaceDamage(window, pRegion); } if (pTime) { SetSwapchainFrameTimestamp(swapchain, pTime); } - if (pPresentMode) { - if (!SetSwapchainPresentMode(window, *pPresentMode)) - swapchain_result = WorstPresentResult(swapchain_result, - VK_ERROR_SURFACE_LOST_KHR); - } err = window->queueBuffer(window, img.buffer.get(), fence); // queueBuffer always closes fence, even on error @@ -2211,9 +2003,6 @@ VkResult QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* present_info) { // Look at the pNext chain for supported extension structs: const VkPresentRegionsKHR* present_regions = nullptr; const VkPresentTimesInfoGOOGLE* present_times = nullptr; - const VkSwapchainPresentFenceInfoEXT* present_fences = nullptr; - const VkSwapchainPresentModeInfoEXT* present_modes = nullptr; - const VkPresentRegionsKHR* next = reinterpret_cast<const VkPresentRegionsKHR*>(present_info->pNext); while (next) { @@ -2225,14 +2014,6 @@ VkResult QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* present_info) { present_times = reinterpret_cast<const VkPresentTimesInfoGOOGLE*>(next); break; - case VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_FENCE_INFO_EXT: - present_fences = - reinterpret_cast<const VkSwapchainPresentFenceInfoEXT*>(next); - break; - case VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_MODE_INFO_EXT: - present_modes = - reinterpret_cast<const VkSwapchainPresentModeInfoEXT*>(next); - break; default: ALOGV("QueuePresentKHR ignoring unrecognized pNext->sType = %x", next->sType); @@ -2248,15 +2029,6 @@ VkResult QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* present_info) { present_times->swapchainCount != present_info->swapchainCount, "VkPresentTimesInfoGOOGLE::swapchainCount != " "VkPresentInfo::swapchainCount"); - ALOGV_IF(present_fences && - present_fences->swapchainCount != present_info->swapchainCount, - "VkSwapchainPresentFenceInfoEXT::swapchainCount != " - "VkPresentInfo::swapchainCount"); - ALOGV_IF(present_modes && - present_modes->swapchainCount != present_info->swapchainCount, - "VkSwapchainPresentModeInfoEXT::swapchainCount != " - "VkPresentInfo::swapchainCount"); - const VkPresentRegionKHR* regions = (present_regions) ? present_regions->pRegions : nullptr; const VkPresentTimeGOOGLE* times = @@ -2272,8 +2044,6 @@ VkResult QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* present_info) { present_info->pImageIndices[sc], (regions && !swapchain.mailbox_mode) ? ®ions[sc] : nullptr, times ? ×[sc] : nullptr, - present_fences ? present_fences->pFences[sc] : VK_NULL_HANDLE, - present_modes ? &present_modes->pPresentModes[sc] : nullptr, present_info->waitSemaphoreCount, present_info->pWaitSemaphores); @@ -2498,35 +2268,5 @@ VkResult BindImageMemory2KHR(VkDevice device, out_bind_infos.empty() ? pBindInfos : out_bind_infos.data()); } -VKAPI_ATTR -VkResult ReleaseSwapchainImagesEXT(VkDevice /*device*/, - const VkReleaseSwapchainImagesInfoEXT* pReleaseInfo) { - ATRACE_CALL(); - - Swapchain& swapchain = *SwapchainFromHandle(pReleaseInfo->swapchain); - ANativeWindow* window = swapchain.surface.window.get(); - - // If in shared present mode, don't actually release the image back to the BQ. - // Both sides share it forever. - if (swapchain.shared) - return VK_SUCCESS; - - for (uint32_t i = 0; i < pReleaseInfo->imageIndexCount; i++) { - Swapchain::Image& img = swapchain.images[pReleaseInfo->pImageIndices[i]]; - window->cancelBuffer(window, img.buffer.get(), img.dequeue_fence); - - // cancelBuffer has taken ownership of the dequeue fence - img.dequeue_fence = -1; - // if we're still holding a release fence, get rid of it now - if (img.release_fence >= 0) { - close(img.release_fence); - img.release_fence = -1; - } - img.dequeued = false; - } - - return VK_SUCCESS; -} - } // namespace driver } // namespace vulkan diff --git a/vulkan/libvulkan/swapchain.h b/vulkan/libvulkan/swapchain.h index 280fe9b5a3..4912ef1a33 100644 --- a/vulkan/libvulkan/swapchain.h +++ b/vulkan/libvulkan/swapchain.h @@ -46,7 +46,6 @@ VKAPI_ATTR VkResult GetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice ph VKAPI_ATTR VkResult GetPhysicalDeviceSurfaceFormats2KHR(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, uint32_t* pSurfaceFormatCount, VkSurfaceFormat2KHR* pSurfaceFormats); VKAPI_ATTR VkResult BindImageMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos); VKAPI_ATTR VkResult BindImageMemory2KHR(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos); -VKAPI_ATTR VkResult ReleaseSwapchainImagesEXT(VkDevice device, const VkReleaseSwapchainImagesInfoEXT* pReleaseInfo); // clang-format on } // namespace driver diff --git a/vulkan/scripts/driver_generator.py b/vulkan/scripts/driver_generator.py index 78b550c202..af56764a21 100644 --- a/vulkan/scripts/driver_generator.py +++ b/vulkan/scripts/driver_generator.py @@ -35,8 +35,6 @@ _INTERCEPTED_EXTENSIONS = [ 'VK_KHR_surface', 'VK_KHR_surface_protected_capabilities', 'VK_KHR_swapchain', - 'VK_EXT_swapchain_maintenance1', - 'VK_EXT_surface_maintenance1', ] # Extensions known to vulkan::driver level. @@ -48,7 +46,6 @@ _KNOWN_EXTENSIONS = _INTERCEPTED_EXTENSIONS + [ 'VK_KHR_external_memory_capabilities', 'VK_KHR_external_semaphore_capabilities', 'VK_KHR_external_fence_capabilities', - 'VK_KHR_external_fence_fd', ] # Functions needed at vulkan::driver level. @@ -115,9 +112,6 @@ _NEEDED_COMMANDS = [ # For promoted VK_KHR_external_fence_capabilities 'vkGetPhysicalDeviceExternalFenceProperties', 'vkGetPhysicalDeviceExternalFencePropertiesKHR', - - # VK_KHR_swapchain_maintenance1 requirement - 'vkImportFenceFdKHR', ] # Functions intercepted at vulkan::driver level. |