mirror of https://gitlab.freedesktop.org/mesa/mesa
383 lines
16 KiB
Diff
383 lines
16 KiB
Diff
From 8ea5db3fc0fab7f60472dcd0db7e5e40571549cb Mon Sep 17 00:00:00 2001
|
|
From: Joe Withers <joe.withers@imgtec.com>
|
|
Date: Wed, 15 Nov 2023 17:46:25 +0000
|
|
Subject: [PATCH] Fix for render_to_image exceeding maxResourceSize
|
|
|
|
Fixes an issue seen in render_to_image tests, where image creation may
|
|
fail due to exceeding the maxResourceSize for the corresponding
|
|
VkImageFormatProperties.
|
|
|
|
Affects:
|
|
dEQP-VK.pipeline.*.render_to_image.*.huge.*
|
|
|
|
Components: Vulkan
|
|
|
|
VK-GL-CTS issue: 4793
|
|
|
|
Change-Id: Idb5ec9fd5bb778d437a1e96b34c5cdc423490920
|
|
---
|
|
.../vktPipelineRenderToImageTests.cpp | 283 ++++++++++++------
|
|
1 file changed, 199 insertions(+), 84 deletions(-)
|
|
|
|
diff --git a/external/vulkancts/modules/vulkan/pipeline/vktPipelineRenderToImageTests.cpp b/external/vulkancts/modules/vulkan/pipeline/vktPipelineRenderToImageTests.cpp
|
|
index a8bc15b66685dda2f4af..c9ce129a0a0e8334f1ad 100644
|
|
--- a/external/vulkancts/modules/vulkan/pipeline/vktPipelineRenderToImageTests.cpp
|
|
+++ b/external/vulkancts/modules/vulkan/pipeline/vktPipelineRenderToImageTests.cpp
|
|
@@ -645,38 +645,6 @@ IVec4 getMaxImageSize (const VkImageViewType viewType, const IVec4& sizeHint)
|
|
return size;
|
|
}
|
|
|
|
-deUint32 getMemoryTypeNdx (Context& context, const CaseDef& caseDef)
|
|
-{
|
|
- const DeviceInterface& vk = context.getDeviceInterface();
|
|
- const InstanceInterface& vki = context.getInstanceInterface();
|
|
- const VkDevice device = context.getDevice();
|
|
- const VkPhysicalDevice physDevice = context.getPhysicalDevice();
|
|
-
|
|
- const VkPhysicalDeviceMemoryProperties memoryProperties = getPhysicalDeviceMemoryProperties(vki, physDevice);
|
|
- Move<VkImage> colorImage;
|
|
- VkMemoryRequirements memReqs;
|
|
-
|
|
- const VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
|
- const IVec4 imageSize = getMaxImageSize(caseDef.viewType, caseDef.imageSizeHint);
|
|
-
|
|
- //create image, don't bind any memory to it
|
|
- colorImage = makeImage(vk, device, getImageCreateFlags(caseDef.viewType), getImageType(caseDef.viewType), caseDef.colorFormat,
|
|
- imageSize.swizzle(0, 1, 2), 1u, imageSize.w(), imageUsage);
|
|
-
|
|
- vk.getImageMemoryRequirements(device, *colorImage, &memReqs);
|
|
- return selectMatchingMemoryType(memoryProperties, memReqs.memoryTypeBits, MemoryRequirement::Any);
|
|
-}
|
|
-
|
|
-VkDeviceSize getMaxDeviceHeapSize (Context& context, const CaseDef& caseDef)
|
|
-{
|
|
- const InstanceInterface& vki = context.getInstanceInterface();
|
|
- const VkPhysicalDevice physDevice = context.getPhysicalDevice();
|
|
- const VkPhysicalDeviceMemoryProperties memoryProperties = getPhysicalDeviceMemoryProperties(vki, physDevice);
|
|
- const deUint32 memoryTypeNdx = getMemoryTypeNdx (context, caseDef);
|
|
-
|
|
- return memoryProperties.memoryHeaps[memoryProperties.memoryTypes[memoryTypeNdx].heapIndex].size;
|
|
-}
|
|
-
|
|
//! Get a smaller image size. Returns a vector of zeroes, if it can't reduce more.
|
|
IVec4 getReducedImageSize (const CaseDef& caseDef, IVec4 size)
|
|
{
|
|
@@ -706,6 +674,41 @@ IVec4 getReducedImageSize (const CaseDef& caseDef, IVec4 size)
|
|
return size;
|
|
}
|
|
|
|
+//! Get the image memory requirements for the image size under test, expecting potential image
|
|
+//! creation failure if the required size is larger than the device's maxResourceSize, returning
|
|
+//! false if creation failed.
|
|
+bool getSupportedImageMemoryRequirements(Context& context, const CaseDef& caseDef, const VkFormat format, const IVec4 size, const VkImageUsageFlags usage, VkMemoryRequirements& imageMemoryRequiements)
|
|
+{
|
|
+ const DeviceInterface& vk = context.getDeviceInterface();
|
|
+ const VkDevice device = context.getDevice();
|
|
+ bool imageCreationPossible = true;
|
|
+
|
|
+ try
|
|
+ {
|
|
+ Move<VkImage> image = makeImage(
|
|
+ vk,
|
|
+ device,
|
|
+ getImageCreateFlags(caseDef.viewType),
|
|
+ getImageType(caseDef.viewType),
|
|
+ format,
|
|
+ size.swizzle(0, 1, 2),
|
|
+ 1u,
|
|
+ size.w(),
|
|
+ usage
|
|
+ );
|
|
+
|
|
+ vk.getImageMemoryRequirements(device, *image, &imageMemoryRequiements);
|
|
+ }
|
|
+ // vkCreateImage is allowed to return VK_ERROR_OUT_OF_HOST_MEMORY if the image's
|
|
+ // memory requirements will exceed maxResourceSize.
|
|
+ catch (const vk::OutOfMemoryError& e)
|
|
+ {
|
|
+ imageCreationPossible = false;
|
|
+ }
|
|
+
|
|
+ return imageCreationPossible;
|
|
+}
|
|
+
|
|
bool isDepthStencilFormatSupported (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const VkFormat format)
|
|
{
|
|
const VkFormatProperties properties = getPhysicalDeviceFormatProperties(vki, physDevice, format);
|
|
@@ -794,72 +797,150 @@ tcu::TestStatus testWithSizeReduction (Context& context, const CaseDef& caseDef)
|
|
const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
|
|
Allocator& allocator = context.getDefaultAllocator();
|
|
|
|
- // The memory might be too small to allocate a largest possible attachment, so try to account for that.
|
|
- const bool useDepthStencil = (caseDef.depthStencilFormat != VK_FORMAT_UNDEFINED);
|
|
-
|
|
IVec4 imageSize = getMaxImageSize(caseDef.viewType, caseDef.imageSizeHint);
|
|
- VkDeviceSize colorSize = product(imageSize) * tcu::getPixelSize(mapVkFormat(caseDef.colorFormat));
|
|
- VkDeviceSize depthStencilSize = (useDepthStencil ? product(imageSize) * tcu::getPixelSize(mapVkFormat(caseDef.depthStencilFormat)) : 0ull);
|
|
|
|
- const VkDeviceSize reserveForChecking = 500ull * 1024ull; //left 512KB
|
|
- const float additionalMemory = 1.15f; //left some free memory on device (15%)
|
|
- VkDeviceSize neededMemory = static_cast<VkDeviceSize>(static_cast<float>(colorSize + depthStencilSize) * additionalMemory) + reserveForChecking;
|
|
- VkDeviceSize maxMemory = getMaxDeviceHeapSize(context, caseDef) >> 2;
|
|
+ const VkImageUsageFlags colorImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
|
+ const VkImageUsageFlags depthStencilImageUsage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
|
+ const bool useDepthStencil = (caseDef.depthStencilFormat != VK_FORMAT_UNDEFINED);
|
|
|
|
- tcu::PlatformMemoryLimits memoryLimits;
|
|
- context.getTestContext().getPlatform().getMemoryLimits(memoryLimits);
|
|
- maxMemory = std::min(maxMemory, VkDeviceSize(memoryLimits.totalSystemMemory));
|
|
+ {
|
|
+ VkImageFormatProperties colorImageFormatProperties;
|
|
+ const auto result = vki.getPhysicalDeviceImageFormatProperties(
|
|
+ physDevice,
|
|
+ caseDef.colorFormat,
|
|
+ getImageType(caseDef.viewType),
|
|
+ VK_IMAGE_TILING_OPTIMAL,
|
|
+ colorImageUsage,
|
|
+ getImageCreateFlags(caseDef.viewType),
|
|
+ &colorImageFormatProperties
|
|
+ );
|
|
+
|
|
+ VK_CHECK(result);
|
|
|
|
- const VkDeviceSize deviceMemoryBudget = std::min(neededMemory, maxMemory);
|
|
- bool allocationPossible = false;
|
|
+ imageSize.x() = std::min(static_cast<deUint32>(imageSize.x()), colorImageFormatProperties.maxExtent.width);
|
|
+ imageSize.y() = std::min(static_cast<deUint32>(imageSize.y()), colorImageFormatProperties.maxExtent.height);
|
|
+ imageSize.z() = std::min(static_cast<deUint32>(imageSize.z()), colorImageFormatProperties.maxExtent.depth);
|
|
+ imageSize.w() = std::min(static_cast<deUint32>(imageSize.w()), colorImageFormatProperties.maxArrayLayers);
|
|
+ }
|
|
|
|
- // Keep reducing the size, if image size is too big
|
|
- while (neededMemory > deviceMemoryBudget)
|
|
+ if (useDepthStencil)
|
|
{
|
|
- imageSize = getReducedImageSize(caseDef, imageSize);
|
|
+ VkImageFormatProperties depthStencilImageFormatProperties;
|
|
+ const auto result = vki.getPhysicalDeviceImageFormatProperties(
|
|
+ physDevice,
|
|
+ caseDef.depthStencilFormat,
|
|
+ getImageType(caseDef.viewType),
|
|
+ VK_IMAGE_TILING_OPTIMAL,
|
|
+ depthStencilImageUsage,
|
|
+ getImageCreateFlags(caseDef.viewType),
|
|
+ &depthStencilImageFormatProperties
|
|
+ );
|
|
|
|
- if (imageSize == IVec4())
|
|
- return tcu::TestStatus::fail("Couldn't create an image with required size");
|
|
+ VK_CHECK(result);
|
|
|
|
- colorSize = product(imageSize) * tcu::getPixelSize(mapVkFormat(caseDef.colorFormat));
|
|
- depthStencilSize = (useDepthStencil ? product(imageSize) * tcu::getPixelSize(mapVkFormat(caseDef.depthStencilFormat)) : 0ull);
|
|
- neededMemory = static_cast<VkDeviceSize>(static_cast<double>(colorSize + depthStencilSize) * additionalMemory);
|
|
+ imageSize.x() = std::min(static_cast<deUint32>(imageSize.x()), depthStencilImageFormatProperties.maxExtent.width);
|
|
+ imageSize.y() = std::min(static_cast<deUint32>(imageSize.y()), depthStencilImageFormatProperties.maxExtent.height);
|
|
+ imageSize.z() = std::min(static_cast<deUint32>(imageSize.z()), depthStencilImageFormatProperties.maxExtent.depth);
|
|
+ imageSize.w() = std::min(static_cast<deUint32>(imageSize.w()), depthStencilImageFormatProperties.maxArrayLayers);
|
|
}
|
|
|
|
- // Keep reducing the size, if allocation return out of any memory
|
|
+ bool allocationPossible = false;
|
|
while (!allocationPossible)
|
|
{
|
|
- VkDeviceMemory object = 0;
|
|
- const VkMemoryAllocateInfo allocateInfo =
|
|
- {
|
|
- VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, //VkStructureType sType;
|
|
- DE_NULL, //const void* pNext;
|
|
- neededMemory, //VkDeviceSize allocationSize;
|
|
- getMemoryTypeNdx(context, caseDef) //deUint32 memoryTypeIndex;
|
|
- };
|
|
-
|
|
- const VkResult result = vk.allocateMemory(device, &allocateInfo, DE_NULL, &object);
|
|
+ // Get the image memory requirements
|
|
+ VkMemoryRequirements colorImageMemReqs;
|
|
+ VkDeviceSize neededMemory = 0;
|
|
+ deUint32 memoryTypeNdx = 0;
|
|
|
|
- if (VK_ERROR_OUT_OF_DEVICE_MEMORY == result || VK_ERROR_OUT_OF_HOST_MEMORY == result)
|
|
+ if (!getSupportedImageMemoryRequirements(context, caseDef, caseDef.colorFormat, imageSize, colorImageUsage, colorImageMemReqs))
|
|
{
|
|
+ // Try again with reduced image size
|
|
imageSize = getReducedImageSize(caseDef, imageSize);
|
|
-
|
|
if (imageSize == IVec4())
|
|
return tcu::TestStatus::fail("Couldn't create an image with required size");
|
|
+ else
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ neededMemory = colorImageMemReqs.size;
|
|
+
|
|
+ if (useDepthStencil)
|
|
+ {
|
|
+ VkMemoryRequirements depthStencilImageMemReqs;
|
|
|
|
- colorSize = product(imageSize) * tcu::getPixelSize(mapVkFormat(caseDef.colorFormat));
|
|
- depthStencilSize = (useDepthStencil ? product(imageSize) * tcu::getPixelSize(mapVkFormat(caseDef.depthStencilFormat)) : 0ull);
|
|
- neededMemory = static_cast<VkDeviceSize>(static_cast<double>(colorSize + depthStencilSize) * additionalMemory) + reserveForChecking;
|
|
+ if (!getSupportedImageMemoryRequirements(context, caseDef, caseDef.depthStencilFormat, imageSize, depthStencilImageUsage, depthStencilImageMemReqs))
|
|
+ {
|
|
+ // Try again with reduced image size
|
|
+ imageSize = getReducedImageSize(caseDef, imageSize);
|
|
+ if (imageSize == IVec4())
|
|
+ return tcu::TestStatus::fail("Couldn't create an image with required size");
|
|
+ else
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ neededMemory += depthStencilImageMemReqs.size;
|
|
}
|
|
- else if (VK_SUCCESS != result)
|
|
+
|
|
+ // Reserve an additional 15% device memory, plus the 512KB for checking results
|
|
{
|
|
- return tcu::TestStatus::fail("Couldn't allocate memory");
|
|
+ const VkDeviceSize reserveForChecking = 500ull * 1024ull;
|
|
+ const float additionalMemory = 1.15f;
|
|
+ neededMemory = static_cast<VkDeviceSize>(static_cast<float>(neededMemory) * additionalMemory) + reserveForChecking;
|
|
}
|
|
- else
|
|
+
|
|
+ // Query the available memory in the corresponding memory heap
|
|
{
|
|
- //free memory using Move pointer
|
|
- Move<VkDeviceMemory> memoryAllocated (check<VkDeviceMemory>(object), Deleter<VkDeviceMemory>(vk, device, DE_NULL));
|
|
- allocationPossible = true;
|
|
+ const VkPhysicalDeviceMemoryProperties memoryProperties = getPhysicalDeviceMemoryProperties(vki, physDevice);
|
|
+ // Use the color image memory requirements, assume depth stencil uses the same memory type
|
|
+ memoryTypeNdx = selectMatchingMemoryType(memoryProperties, colorImageMemReqs.memoryTypeBits, MemoryRequirement::Any);
|
|
+ tcu::PlatformMemoryLimits memoryLimits;
|
|
+ context.getTestContext().getPlatform().getMemoryLimits(memoryLimits);
|
|
+ VkDeviceSize maxMemory = std::min(
|
|
+ memoryProperties.memoryHeaps[memoryProperties.memoryTypes[memoryTypeNdx].heapIndex].size,
|
|
+ VkDeviceSize(memoryLimits.totalSystemMemory)
|
|
+ );
|
|
+
|
|
+ if (neededMemory > maxMemory)
|
|
+ {
|
|
+ // Try again with reduced image size
|
|
+ imageSize = getReducedImageSize(caseDef, imageSize);
|
|
+ if (imageSize == IVec4())
|
|
+ return tcu::TestStatus::fail("Couldn't create an image with required size");
|
|
+ else
|
|
+ continue;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // Attempt a memory allocation
|
|
+ {
|
|
+ VkDeviceMemory object = 0;
|
|
+ const VkMemoryAllocateInfo allocateInfo =
|
|
+ {
|
|
+ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, //VkStructureType sType;
|
|
+ DE_NULL, //const void* pNext;
|
|
+ neededMemory, //VkDeviceSize allocationSize;
|
|
+ memoryTypeNdx //deUint32 memoryTypeIndex;
|
|
+ };
|
|
+
|
|
+ const VkResult result = vk.allocateMemory(device, &allocateInfo, DE_NULL, &object);
|
|
+
|
|
+ if (VK_ERROR_OUT_OF_DEVICE_MEMORY == result || VK_ERROR_OUT_OF_HOST_MEMORY == result)
|
|
+ {
|
|
+ // Try again with reduced image size
|
|
+ imageSize = getReducedImageSize(caseDef, imageSize);
|
|
+ if (imageSize == IVec4())
|
|
+ return tcu::TestStatus::fail("Couldn't create an image with required size");
|
|
+ }
|
|
+ else if (VK_SUCCESS != result)
|
|
+ {
|
|
+ return tcu::TestStatus::fail("Couldn't allocate memory");
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ //free memory using Move pointer
|
|
+ Move<VkDeviceMemory> memoryAllocated (check<VkDeviceMemory>(object), Deleter<VkDeviceMemory>(vk, device, DE_NULL));
|
|
+ allocationPossible = true;
|
|
+ }
|
|
}
|
|
}
|
|
|
|
@@ -907,20 +988,16 @@ tcu::TestStatus testWithSizeReduction (Context& context, const CaseDef& caseDef)
|
|
|
|
// Create a color image
|
|
{
|
|
- const VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
|
-
|
|
colorImage = makeImage(vk, device, getImageCreateFlags(caseDef.viewType), getImageType(caseDef.viewType), caseDef.colorFormat,
|
|
- imageSize.swizzle(0, 1, 2), 1u, imageSize.w(), imageUsage);
|
|
+ imageSize.swizzle(0, 1, 2), 1u, imageSize.w(), colorImageUsage);
|
|
colorImageAlloc = bindImage(vki, vk, physDevice, device, *colorImage, MemoryRequirement::Any, allocator, caseDef.allocationKind);
|
|
}
|
|
|
|
// Create a depth/stencil image (always a 2D image, optionally layered)
|
|
if (useDepthStencil)
|
|
{
|
|
- const VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
|
-
|
|
depthStencilImage = makeImage(vk, device, (VkImageCreateFlags)0, VK_IMAGE_TYPE_2D, caseDef.depthStencilFormat,
|
|
- IVec3(imageSize.x(), imageSize.y(), 1), 1u, numSlices, imageUsage);
|
|
+ IVec3(imageSize.x(), imageSize.y(), 1), 1u, numSlices, depthStencilImageUsage);
|
|
depthStencilImageAlloc = bindImage(vki, vk, physDevice, device, *depthStencilImage, MemoryRequirement::Any, allocator, caseDef.allocationKind);
|
|
}
|
|
|
|
@@ -1153,13 +1230,51 @@ void checkImageViewTypeRequirements (Context& context, const VkImageViewType vie
|
|
|
|
void checkSupportAttachmentSize (Context& context, const CaseDef caseDef)
|
|
{
|
|
+ const InstanceInterface& vki = context.getInstanceInterface();
|
|
+ const VkPhysicalDevice physDevice = context.getPhysicalDevice();
|
|
+
|
|
checkImageViewTypeRequirements(context, caseDef.viewType);
|
|
|
|
if (caseDef.allocationKind == ALLOCATION_KIND_DEDICATED)
|
|
context.requireDeviceFunctionality("VK_KHR_dedicated_allocation");
|
|
|
|
- if (caseDef.depthStencilFormat != VK_FORMAT_UNDEFINED && !isDepthStencilFormatSupported(context.getInstanceInterface(), context.getPhysicalDevice(), caseDef.depthStencilFormat))
|
|
- TCU_THROW(NotSupportedError, "Unsupported depth/stencil format");
|
|
+ {
|
|
+ VkImageFormatProperties colorImageFormatProperties;
|
|
+ const auto result = vki.getPhysicalDeviceImageFormatProperties(
|
|
+ physDevice,
|
|
+ caseDef.colorFormat,
|
|
+ getImageType(caseDef.viewType),
|
|
+ VK_IMAGE_TILING_OPTIMAL,
|
|
+ (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT),
|
|
+ getImageCreateFlags(caseDef.viewType),
|
|
+ &colorImageFormatProperties
|
|
+ );
|
|
+
|
|
+ if (result != VK_SUCCESS)
|
|
+ {
|
|
+ TCU_THROW(NotSupportedError, "Unsupported color attachment format");
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (caseDef.depthStencilFormat != VK_FORMAT_UNDEFINED)
|
|
+ {
|
|
+
|
|
+ VkImageFormatProperties depthStencilImageFormatProperties;
|
|
+ const auto result = vki.getPhysicalDeviceImageFormatProperties(
|
|
+ physDevice,
|
|
+ caseDef.depthStencilFormat,
|
|
+ getImageType(caseDef.viewType),
|
|
+ VK_IMAGE_TILING_OPTIMAL,
|
|
+ VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
|
|
+ getImageCreateFlags(caseDef.viewType),
|
|
+ &depthStencilImageFormatProperties
|
|
+ );
|
|
+
|
|
+ if (result != VK_SUCCESS)
|
|
+ {
|
|
+ TCU_THROW(NotSupportedError, "Unsupported depth/stencil attachment format");
|
|
+ }
|
|
+ }
|
|
|
|
checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), caseDef.pipelineConstructionType);
|
|
}
|
|
--
|
|
Cheers,
|
|
Eric
|
|
|