From 48dc81ac5d5d9df39787d7726e394e18d84009a8 Mon Sep 17 00:00:00 2001 From: Pyry Haulos Date: Fri, 11 Dec 2015 14:25:55 -0800 Subject: [PATCH] Add basic coverage for allocation callbacks to obj mgmt tests * Allocation callbacks that always succeed * Failure after increasing number of callbacks until object creation succeeds Change-Id: I26742ebe910505b91a78bae4549a484fa6cd77ae --- .../api/vktApiObjectManagementTests.cpp | 266 +++++++++++++++--- 1 file changed, 229 insertions(+), 37 deletions(-) diff --git a/external/vulkancts/modules/vulkan/api/vktApiObjectManagementTests.cpp b/external/vulkancts/modules/vulkan/api/vktApiObjectManagementTests.cpp index 8ef11216d..d992a3785 100644 --- a/external/vulkancts/modules/vulkan/api/vktApiObjectManagementTests.cpp +++ b/external/vulkancts/modules/vulkan/api/vktApiObjectManagementTests.cpp @@ -44,6 +44,7 @@ #include "vkTypeUtil.hpp" #include "vkPlatform.hpp" #include "vkStrUtil.hpp" +#include "vkAllocationCallbackUtil.hpp" #include "tcuVector.hpp" #include "tcuResultCollector.hpp" @@ -232,12 +233,13 @@ deUint32 getDefaultTestThreadCount (void) struct Environment { - const PlatformInterface& vkp; - const DeviceInterface& vkd; - VkDevice device; - deUint32 queueFamilyIndex; - const BinaryCollection& programBinaries; - deUint32 maxResourceConsumers; // Maximum number of objects using same Object::Resources concurrently + const PlatformInterface& vkp; + const DeviceInterface& vkd; + VkDevice device; + deUint32 queueFamilyIndex; + const BinaryCollection& programBinaries; + const VkAllocationCallbacks* allocationCallbacks; + deUint32 maxResourceConsumers; // Maximum number of objects using same Object::Resources concurrently Environment (Context& context, deUint32 maxResourceConsumers_) : vkp (context.getPlatformInterface()) @@ -245,21 +247,24 @@ struct Environment , device (context.getDevice()) , queueFamilyIndex (context.getUniversalQueueFamilyIndex()) , programBinaries (context.getBinaryCollection()) + , allocationCallbacks (DE_NULL) , maxResourceConsumers (maxResourceConsumers_) { } - Environment (const PlatformInterface& vkp_, - const DeviceInterface& vkd_, - VkDevice device_, - deUint32 queueFamilyIndex_, - const BinaryCollection& programBinaries_, - deUint32 maxResourceConsumers_) + Environment (const PlatformInterface& vkp_, + const DeviceInterface& vkd_, + VkDevice device_, + deUint32 queueFamilyIndex_, + const BinaryCollection& programBinaries_, + const VkAllocationCallbacks* allocationCallbacks_, + deUint32 maxResourceConsumers_) : vkp (vkp_) , vkd (vkd_) , device (device_) , queueFamilyIndex (queueFamilyIndex_) , programBinaries (programBinaries_) + , allocationCallbacks (allocationCallbacks_) , maxResourceConsumers (maxResourceConsumers_) { } @@ -324,7 +329,7 @@ struct Instance DE_NULL, // ppEnabledExtensionNames }; - return createInstance(env.vkp, &instanceInfo); + return createInstance(env.vkp, &instanceInfo, env.allocationCallbacks); } }; @@ -386,7 +391,7 @@ struct Device } }; - static Move create (const Environment&, const Resources& res, const Parameters&) + static Move create (const Environment& env, const Resources& res, const Parameters&) { const float queuePriority = 1.0; @@ -415,7 +420,7 @@ struct Device DE_NULL, // pEnabledFeatures }; - return createDevice(res.vki, res.physicalDevice, &deviceInfo); + return createDevice(res.vki, res.physicalDevice, &deviceInfo, env.allocationCallbacks); } }; @@ -453,7 +458,7 @@ struct DeviceMemory params.memoryTypeIndex }; - return allocateMemory(env.vkd, env.device, &allocInfo); + return allocateMemory(env.vkd, env.device, &allocInfo, env.allocationCallbacks); } }; @@ -509,7 +514,7 @@ struct Buffer &env.queueFamilyIndex }; - return createBuffer(env.vkd, env.device, &bufferInfo); + return createBuffer(env.vkd, env.device, &bufferInfo, env.allocationCallbacks); } }; @@ -563,7 +568,7 @@ struct BufferView params.range }; - return createBufferView(env.vkd, env.device, &bufferViewInfo); + return createBufferView(env.vkd, env.device, &bufferViewInfo, env.allocationCallbacks); } }; @@ -635,7 +640,7 @@ struct Image params.initialLayout }; - return createImage(env.vkd, env.device, &imageInfo); + return createImage(env.vkd, env.device, &imageInfo, env.allocationCallbacks); } }; @@ -693,7 +698,7 @@ struct ImageView params.subresourceRange, }; - return createImageView(env.vkd, env.device, &imageViewInfo); + return createImageView(env.vkd, env.device, &imageViewInfo, env.allocationCallbacks); } }; @@ -726,7 +731,7 @@ struct Semaphore params.flags }; - return createSemaphore(env.vkd, env.device, &semaphoreInfo); + return createSemaphore(env.vkd, env.device, &semaphoreInfo, env.allocationCallbacks); } }; @@ -759,7 +764,7 @@ struct Fence params.flags }; - return createFence(env.vkd, env.device, &fenceInfo); + return createFence(env.vkd, env.device, &fenceInfo, env.allocationCallbacks); } }; @@ -792,7 +797,7 @@ struct Event params.flags }; - return createEvent(env.vkd, env.device, &eventInfo); + return createEvent(env.vkd, env.device, &eventInfo, env.allocationCallbacks); } }; @@ -834,7 +839,7 @@ struct QueryPool params.pipelineStatistics }; - return createQueryPool(env.vkd, env.device, &queryPoolInfo); + return createQueryPool(env.vkd, env.device, &queryPoolInfo, env.allocationCallbacks); } }; @@ -915,7 +920,7 @@ struct ShaderModule (const deUint32*)res.binary.getBinary(), }; - return createShaderModule(env.vkd, env.device, &shaderModuleInfo); + return createShaderModule(env.vkd, env.device, &shaderModuleInfo, env.allocationCallbacks); } }; @@ -946,7 +951,7 @@ struct PipelineCache DE_NULL, // pInitialData }; - return createPipelineCache(env.vkd, env.device, &pipelineCacheInfo); + return createPipelineCache(env.vkd, env.device, &pipelineCacheInfo, env.allocationCallbacks); } }; @@ -1020,7 +1025,7 @@ struct Sampler params.unnormalizedCoordinates }; - return createSampler(env.vkd, env.device, &samplerInfo); + return createSampler(env.vkd, env.device, &samplerInfo, env.allocationCallbacks); } }; @@ -1125,7 +1130,7 @@ struct DescriptorSetLayout (res.bindings.empty() ? DE_NULL : &res.bindings[0]) }; - return createDescriptorSetLayout(env.vkd, env.device, &descriptorSetLayoutInfo); + return createDescriptorSetLayout(env.vkd, env.device, &descriptorSetLayoutInfo, env.allocationCallbacks); } }; @@ -1188,7 +1193,7 @@ struct PipelineLayout (params.pushConstantRanges.empty() ? DE_NULL : ¶ms.pushConstantRanges[0]), }; - return createPipelineLayout(env.vkd, env.device, &pipelineLayoutInfo); + return createPipelineLayout(env.vkd, env.device, &pipelineLayoutInfo, env.allocationCallbacks); } }; @@ -1276,7 +1281,7 @@ struct RenderPass DE_NULL // pDependencies }; - return createRenderPass(env.vkd, env.device, &renderPassInfo); + return createRenderPass(env.vkd, env.device, &renderPassInfo, env.allocationCallbacks); } }; @@ -1490,7 +1495,7 @@ struct GraphicsPipeline 0, // basePipelineIndex }; - return createGraphicsPipeline(env.vkd, env.device, *res.pipelineCache.object, &pipelineInfo); + return createGraphicsPipeline(env.vkd, env.device, *res.pipelineCache.object, &pipelineInfo, env.allocationCallbacks); } }; @@ -1557,7 +1562,7 @@ struct ComputePipeline 0u, // basePipelineIndex }; - return createComputePipeline(env.vkd, env.device, *res.pipelineCache.object, &pipelineInfo); + return createComputePipeline(env.vkd, env.device, *res.pipelineCache.object, &pipelineInfo, env.allocationCallbacks); } }; @@ -1609,7 +1614,7 @@ struct DescriptorPool (params.poolSizes.empty() ? DE_NULL : ¶ms.poolSizes[0]) }; - return createDescriptorPool(env.vkd, env.device, &descriptorPoolInfo); + return createDescriptorPool(env.vkd, env.device, &descriptorPoolInfo, env.allocationCallbacks); } }; @@ -1742,7 +1747,7 @@ struct Framebuffer 1u // layers }; - return createFramebuffer(env.vkd, env.device, &framebufferInfo); + return createFramebuffer(env.vkd, env.device, &framebufferInfo, env.allocationCallbacks); } }; @@ -1776,7 +1781,7 @@ struct CommandPool env.queueFamilyIndex, }; - return createCommandPool(env.vkd, env.device, &cmdPoolInfo); + return createCommandPool(env.vkd, env.device, &cmdPoolInfo, env.allocationCallbacks); } }; @@ -1971,11 +1976,17 @@ struct EnvClone : deviceRes (parent, deviceParams) , device (Device::create(parent, deviceRes, deviceParams)) , vkd (deviceRes.vki, *device) - , env (parent.vkp, vkd, *device, deviceRes.queueFamilyIndex, parent.programBinaries, maxResourceConsumers) + , env (parent.vkp, vkd, *device, deviceRes.queueFamilyIndex, parent.programBinaries, parent.allocationCallbacks, maxResourceConsumers) { } }; +Device::Parameters getDefaulDeviceParameters (Context& context) +{ + return Device::Parameters(context.getTestContext().getCommandLine().getVKDeviceId()-1u, + VK_QUEUE_GRAPHICS_BIT|VK_QUEUE_COMPUTE_BIT); +} + template tcu::TestStatus multithreadedCreatePerThreadDeviceTest (Context& context, typename Object::Parameters params) { @@ -1983,7 +1994,7 @@ tcu::TestStatus multithreadedCreatePerThreadDeviceTest (Context& context, typena typedef SharedPtr ResPtr; const deUint32 numThreads = getDefaultTestThreadCount(); - const Device::Parameters deviceParams (context.getTestContext().getCommandLine().getVKDeviceId()-1u, VK_QUEUE_GRAPHICS_BIT|VK_QUEUE_COMPUTE_BIT); + const Device::Parameters deviceParams = getDefaulDeviceParameters(context); const Environment sharedEnv (context, numThreads); // For creating Device's vector perThreadEnv (numThreads); vector resources (numThreads); @@ -2000,6 +2011,129 @@ tcu::TestStatus multithreadedCreatePerThreadDeviceTest (Context& context, typena return threads.run(); } +template +tcu::TestStatus createSingleAllocCallbacksTest (Context& context, typename Object::Parameters params) +{ + const deUint32 noCmdScope = VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE + | VK_SYSTEM_ALLOCATION_SCOPE_DEVICE + | VK_SYSTEM_ALLOCATION_SCOPE_CACHE + | VK_SYSTEM_ALLOCATION_SCOPE_OBJECT; + + // Callbacks used by resources + AllocationCallbackRecorder resCallbacks (getSystemAllocator(), 128); + + // Root environment still uses default instance and device, created without callbacks + const Environment rootEnv (context.getPlatformInterface(), + context.getDeviceInterface(), + context.getDevice(), + context.getUniversalQueueFamilyIndex(), + context.getBinaryCollection(), + resCallbacks.getCallbacks(), + 1u); + + { + // Test env has instance & device created with callbacks + const EnvClone resEnv (rootEnv, getDefaulDeviceParameters(context), 1u); + const typename Object::Resources res (resEnv.env, params); + + // Supply a separate callback recorder just for object construction + AllocationCallbackRecorder objCallbacks(getSystemAllocator(), 128); + const Environment objEnv (resEnv.env.vkp, + resEnv.env.vkd, + resEnv.env.device, + resEnv.env.queueFamilyIndex, + resEnv.env.programBinaries, + objCallbacks.getCallbacks(), + resEnv.env.maxResourceConsumers); + + { + Unique obj (Object::create(objEnv, res, params)); + + // Validate that no command-level allocations are live + if (!validateAndLog(context.getTestContext().getLog(), objCallbacks, noCmdScope)) + return tcu::TestStatus::fail("Invalid allocation callback"); + } + + // At this point all allocations made against object callbacks must have been freed + if (!validateAndLog(context.getTestContext().getLog(), objCallbacks, 0u)) + return tcu::TestStatus::fail("Invalid allocation callback"); + } + + if (!validateAndLog(context.getTestContext().getLog(), resCallbacks, 0u)) + return tcu::TestStatus::fail("Invalid allocation callback"); + + return tcu::TestStatus::pass("Ok"); +} + +template +tcu::TestStatus allocCallbackFailTest (Context& context, typename Object::Parameters params) +{ + AllocationCallbackRecorder resCallbacks (getSystemAllocator(), 128); + const Environment rootEnv (context.getPlatformInterface(), + context.getDeviceInterface(), + context.getDevice(), + context.getUniversalQueueFamilyIndex(), + context.getBinaryCollection(), + resCallbacks.getCallbacks(), + 1u); + + { + const EnvClone resEnv (rootEnv, getDefaulDeviceParameters(context), 1u); + const typename Object::Resources res (resEnv.env, params); + deUint32 numPassingAllocs = 0; + const deUint32 maxTries = 1u<<10; + + // Iterate over test until object allocation succeeds + for (; numPassingAllocs < maxTries; ++numPassingAllocs) + { + DeterministicFailAllocator objAllocator(getSystemAllocator(), numPassingAllocs); + AllocationCallbackRecorder recorder (objAllocator.getCallbacks(), 128); + const Environment objEnv (resEnv.env.vkp, + resEnv.env.vkd, + resEnv.env.device, + resEnv.env.queueFamilyIndex, + resEnv.env.programBinaries, + recorder.getCallbacks(), + resEnv.env.maxResourceConsumers); + bool createOk = false; + + context.getTestContext().getLog() + << TestLog::Message + << "Trying to create object with " << numPassingAllocs << " allocation" << (numPassingAllocs != 1 ? "s" : "") << " passing" + << TestLog::EndMessage; + + try + { + Unique obj (Object::create(objEnv, res, params)); + createOk = true; + } + catch (const vk::OutOfMemoryError& e) + { + if (e.getError() != VK_ERROR_OUT_OF_HOST_MEMORY) + { + context.getTestContext().getLog() << e; + return tcu::TestStatus::fail("Got invalid error code"); + } + } + + if (!validateAndLog(context.getTestContext().getLog(), recorder, 0u)) + return tcu::TestStatus::fail("Invalid allocation callback"); + + if (createOk) + { + context.getTestContext().getLog() + << TestLog::Message << "Object construction succeeded! " << TestLog::EndMessage; + break; + } + } + } + + if (!validateAndLog(context.getTestContext().getLog(), resCallbacks, 0u)) + return tcu::TestStatus::fail("Invalid allocation callback"); + + return tcu::TestStatus::pass("Ok"); +} + // Utilities for creating groups template @@ -2436,6 +2570,64 @@ tcu::TestCaseGroup* createObjectManagementTests (tcu::TestContext& testCtx) }; objectMgmtTests->addChild(createGroup(testCtx, "multithreaded_shared_resources", "Multithreaded object construction with shared resources", s_multithreadedCreateSharedResourcesGroup)); + static const CaseDescriptions s_createSingleAllocCallbacksGroup = + { + CASE_DESC(createSingleAllocCallbacksTest , s_instanceCases), + CASE_DESC(createSingleAllocCallbacksTest , s_deviceCases), + CASE_DESC(createSingleAllocCallbacksTest , s_deviceMemCases), + CASE_DESC(createSingleAllocCallbacksTest , s_bufferCases), + CASE_DESC(createSingleAllocCallbacksTest , s_bufferViewCases), + CASE_DESC(createSingleAllocCallbacksTest , s_imageCases), + CASE_DESC(createSingleAllocCallbacksTest , s_imageViewCases), + CASE_DESC(createSingleAllocCallbacksTest , s_semaphoreCases), + CASE_DESC(createSingleAllocCallbacksTest , s_eventCases), + CASE_DESC(createSingleAllocCallbacksTest , s_fenceCases), + CASE_DESC(createSingleAllocCallbacksTest , s_queryPoolCases), + CASE_DESC(createSingleAllocCallbacksTest , s_shaderModuleCases), + CASE_DESC(createSingleAllocCallbacksTest , s_pipelineCacheCases), + CASE_DESC(createSingleAllocCallbacksTest , s_pipelineLayoutCases), + CASE_DESC(createSingleAllocCallbacksTest , s_renderPassCases), + CASE_DESC(createSingleAllocCallbacksTest , s_graphicsPipelineCases), + CASE_DESC(createSingleAllocCallbacksTest , s_computePipelineCases), + CASE_DESC(createSingleAllocCallbacksTest , s_descriptorSetLayoutCases), + CASE_DESC(createSingleAllocCallbacksTest , s_samplerCases), + CASE_DESC(createSingleAllocCallbacksTest , s_descriptorPoolCases), + CASE_DESC(createSingleAllocCallbacksTest , s_descriptorSetCases), + CASE_DESC(createSingleAllocCallbacksTest , s_framebufferCases), + CASE_DESC(createSingleAllocCallbacksTest , s_commandPoolCases), + CASE_DESC(createSingleAllocCallbacksTest , s_commandBufferCases), + }; + objectMgmtTests->addChild(createGroup(testCtx, "single_alloc_callbacks", "Create single object", s_createSingleAllocCallbacksGroup)); + + static const CaseDescriptions s_allocCallbackFailGroup = + { + CASE_DESC(allocCallbackFailTest , s_instanceCases), + CASE_DESC(allocCallbackFailTest , s_deviceCases), + CASE_DESC(allocCallbackFailTest , s_deviceMemCases), + CASE_DESC(allocCallbackFailTest , s_bufferCases), + CASE_DESC(allocCallbackFailTest , s_bufferViewCases), + CASE_DESC(allocCallbackFailTest , s_imageCases), + CASE_DESC(allocCallbackFailTest , s_imageViewCases), + CASE_DESC(allocCallbackFailTest , s_semaphoreCases), + CASE_DESC(allocCallbackFailTest , s_eventCases), + CASE_DESC(allocCallbackFailTest , s_fenceCases), + CASE_DESC(allocCallbackFailTest , s_queryPoolCases), + CASE_DESC(allocCallbackFailTest , s_shaderModuleCases), + CASE_DESC(allocCallbackFailTest , s_pipelineCacheCases), + CASE_DESC(allocCallbackFailTest , s_pipelineLayoutCases), + CASE_DESC(allocCallbackFailTest , s_renderPassCases), + CASE_DESC(allocCallbackFailTest , s_graphicsPipelineCases), + CASE_DESC(allocCallbackFailTest , s_computePipelineCases), + CASE_DESC(allocCallbackFailTest , s_descriptorSetLayoutCases), + CASE_DESC(allocCallbackFailTest , s_samplerCases), + CASE_DESC(allocCallbackFailTest , s_descriptorPoolCases), + CASE_DESC(allocCallbackFailTest , s_descriptorSetCases), + CASE_DESC(allocCallbackFailTest , s_framebufferCases), + CASE_DESC(allocCallbackFailTest , s_commandPoolCases), + CASE_DESC(allocCallbackFailTest , s_commandBufferCases), + }; + objectMgmtTests->addChild(createGroup(testCtx, "alloc_callback_fail", "Allocation callback failure", s_allocCallbackFailGroup)); + return objectMgmtTests.release(); } -- 2.34.1