From 2af2465cd272e315df2c7d4c2930a5b790add042 Mon Sep 17 00:00:00 2001 From: Jesse Hall Date: Wed, 16 May 2018 16:56:54 -0700 Subject: [PATCH] Limit protected swapchain images based on memory A surface's maxImageCount isn't based on the swapchain image extents or format, so it's valid for swapchain creation to fail for out-of-memory reasons even when the image count is within the supported range. This is particularly problematic for protected swapchains, since many implementations have a limit on the total amount of protected memory that can be allocated which is much smaller than total device memory. This change estimates how much memory is used by protected swapchain images, compares that to the size of heaps that support protected memory types, and doesn't try to create swapchains that would have more images than would fit within that size. Components: Vulkan VK-GL-CTS Issue: 1167 Affects: dEQP-VK.protected_memory.interaction.wsi.*.swapchain.create.min_image_count Bug: 77319653 Test: dEQP-VK.protected_memory.interaction.wsi.android.swapchain.create.min_image_count Change-Id: I6cc3bd25f7f22de8424f9e3375ade35fac26a884 --- .../vktProtectedMemWsiSwapchainTests.cpp | 71 +++++++++++++++++++--- 1 file changed, 63 insertions(+), 8 deletions(-) diff --git a/external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemWsiSwapchainTests.cpp b/external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemWsiSwapchainTests.cpp index 2ac1510..229ad73 100644 --- a/external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemWsiSwapchainTests.cpp +++ b/external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemWsiSwapchainTests.cpp @@ -204,6 +204,7 @@ struct TestParameters std::vector generateSwapchainParameterCases (vk::wsi::Type wsiType, TestDimension dimension, + const ProtectedContext& context, const vk::VkSurfaceCapabilitiesKHR& capabilities, const std::vector& formats, const std::vector& presentModes) @@ -239,8 +240,62 @@ std::vector generateSwapchainParameterCases (vk::w { case TEST_DIMENSION_MIN_IMAGE_COUNT: { - const deUint32 maxImageCountToTest = de::clamp(16u, capabilities.minImageCount, (capabilities.maxImageCount > 0) ? capabilities.maxImageCount : capabilities.minImageCount + 16u); + // Estimate how much memory each swapchain image consumes. This isn't perfect, since + // swapchain images may have additional constraints that equivalent non-swapchain + // images don't have. But it's the best we can do. + const vk::DeviceInterface& vkd = context.getDeviceInterface(); + vk::VkDevice device = context.getDevice(); + vk::VkMemoryRequirements memoryRequirements; + { + const vk::VkImageCreateInfo imageInfo = + { + vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, + DE_NULL, + vk::VK_IMAGE_CREATE_PROTECTED_BIT, + vk::VK_IMAGE_TYPE_2D, + baseParameters.imageFormat, + { + baseParameters.imageExtent.width, + baseParameters.imageExtent.height, + 1, + }, + 1, // mipLevels + baseParameters.imageArrayLayers, + vk::VK_SAMPLE_COUNT_1_BIT, + vk::VK_IMAGE_TILING_OPTIMAL, + baseParameters.imageUsage, + baseParameters.imageSharingMode, + baseParameters.queueFamilyIndexCount, + baseParameters.pQueueFamilyIndices, + vk::VK_IMAGE_LAYOUT_UNDEFINED + }; + vk::Move image = vk::createImage(vkd, device, &imageInfo); + + memoryRequirements = vk::getImageMemoryRequirements(vkd, device, *image); + } + + // Determine the maximum memory heap space available for protected images + vk::VkPhysicalDeviceMemoryProperties memoryProperties = vk::getPhysicalDeviceMemoryProperties(context.getInstanceDriver(), context.getPhysicalDevice()); + vk::VkDeviceSize protectedHeapSize = 0; + deUint32 protectedHeapMask = 0; + for (deUint32 memType = 0; memType < memoryProperties.memoryTypeCount; memType++) + { + deUint32 heapIndex = memoryProperties.memoryTypes[memType].heapIndex; + if ((memoryRequirements.memoryTypeBits & (1u << memType)) != 0 && + (memoryProperties.memoryTypes[memType].propertyFlags & vk::VK_MEMORY_PROPERTY_PROTECTED_BIT) != 0 && + (protectedHeapMask & (1u << heapIndex)) == 0) + { + protectedHeapSize = de::max(protectedHeapSize, memoryProperties.memoryHeaps[heapIndex].size); + protectedHeapMask |= 1u << heapIndex; + } + } + // If the implementation doesn't have a max image count, min+16 means we won't clamp. + // Limit it to how many protected images we estimate can be allocated, with one image + // worth of slack for alignment, swapchain-specific constraints, etc. + const deUint32 maxImageCount = de::min((capabilities.maxImageCount > 0) ? capabilities.maxImageCount : capabilities.minImageCount + 16u, + deUint32(protectedHeapSize / memoryRequirements.size) - 1); + const deUint32 maxImageCountToTest = de::clamp(16u, capabilities.minImageCount, maxImageCount); for (deUint32 imageCount = capabilities.minImageCount; imageCount <= maxImageCountToTest; ++imageCount) { cases.push_back(baseParameters); @@ -404,10 +459,11 @@ std::vector generateSwapchainParameterCases (vk::w std::vector generateSwapchainParameterCases (vk::wsi::Type wsiType, TestDimension dimension, - const vk::InstanceInterface& vki, - vk::VkPhysicalDevice physicalDevice, + const ProtectedContext& context, vk::VkSurfaceKHR surface) { + const vk::InstanceInterface& vki = context.getInstanceDriver(); + vk::VkPhysicalDevice physicalDevice = context.getPhysicalDevice(); const vk::VkSurfaceCapabilitiesKHR capabilities = vk::wsi::getPhysicalDeviceSurfaceCapabilities(vki, physicalDevice, surface); @@ -418,7 +474,7 @@ std::vector generateSwapchainParameterCases (vk::w physicalDevice, surface); - return generateSwapchainParameterCases(wsiType, dimension, capabilities, formats, presentModes); + return generateSwapchainParameterCases(wsiType, dimension, context, capabilities, formats, presentModes); } tcu::TestStatus createSwapchainTest (Context& baseCtx, TestParameters params) @@ -432,10 +488,9 @@ tcu::TestStatus createSwapchainTest (Context& baseCtx, TestParameters params) ProtectedContext context (baseCtx, params.wsiType, *native.display, *native.window, instExts, devExts); vk::VkSurfaceKHR surface = context.getSurface(); const std::vector cases (generateSwapchainParameterCases(params.wsiType, - params.dimension, - context.getInstanceDriver(), - context.getPhysicalDevice(), - surface)); + params.dimension, + context, + surface)); deUint32 queueIdx = context.getQueueFamilyIndex(); for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx) { -- 2.7.4