From: Maciej Jesionowski Date: Mon, 17 Oct 2016 15:32:50 +0000 (+0200) Subject: Add test: queue bind sparse api X-Git-Tag: upstream/0.1.0~9^2~200 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=4ade6487c461bf7674120c0008562dc9e75266aa;p=platform%2Fupstream%2FVK-GL-CTS.git Add test: queue bind sparse api Test vkQueueBindSparse with wait and signal semaphores, zero bindInfos, etc. New test: - dEQP-VK.sparse_resources.queue_bind.* See issue #401 Change-Id: If2201095cb9508bf9fa79f3c57e7de5a7dd03616 --- diff --git a/android/cts/master/vk-master.txt b/android/cts/master/vk-master.txt index 0940044..ab007d6 100644 --- a/android/cts/master/vk-master.txt +++ b/android/cts/master/vk-master.txt @@ -117758,6 +117758,24 @@ dEQP-VK.sparse_resources.shader_intrinsics.2d_array_sparse_gather.rgba8ui.512_25 dEQP-VK.sparse_resources.shader_intrinsics.2d_array_sparse_gather.rgba8ui.128_128_8 dEQP-VK.sparse_resources.shader_intrinsics.2d_array_sparse_gather.rgba8ui.503_137_3 dEQP-VK.sparse_resources.shader_intrinsics.2d_array_sparse_gather.rgba8ui.11_37_3 +dEQP-VK.sparse_resources.queue_bind.no_dependency +dEQP-VK.sparse_resources.queue_bind.no_dependency_fence +dEQP-VK.sparse_resources.queue_bind.single_queue_wait_one +dEQP-VK.sparse_resources.queue_bind.single_queue_wait_many +dEQP-VK.sparse_resources.queue_bind.single_queue_signal_one +dEQP-VK.sparse_resources.queue_bind.single_queue_signal_many +dEQP-VK.sparse_resources.queue_bind.single_queue_wait_one_signal_one +dEQP-VK.sparse_resources.queue_bind.single_queue_wait_many_signal_many +dEQP-VK.sparse_resources.queue_bind.multi_queue_wait_one +dEQP-VK.sparse_resources.queue_bind.multi_queue_wait_many +dEQP-VK.sparse_resources.queue_bind.multi_queue_signal_one +dEQP-VK.sparse_resources.queue_bind.multi_queue_signal_many +dEQP-VK.sparse_resources.queue_bind.multi_queue_wait_one_signal_one +dEQP-VK.sparse_resources.queue_bind.multi_queue_wait_many_signal_many +dEQP-VK.sparse_resources.queue_bind.multi_queue_wait_one_signal_one_other +dEQP-VK.sparse_resources.queue_bind.multi_queue_wait_many_signal_many_other +dEQP-VK.sparse_resources.queue_bind.empty +dEQP-VK.sparse_resources.queue_bind.empty_fence dEQP-VK.tessellation.limits.max_tessellation_generation_level dEQP-VK.tessellation.limits.max_tessellation_patch_size dEQP-VK.tessellation.limits.max_tessellation_control_per_vertex_input_components diff --git a/external/vulkancts/modules/vulkan/sparse_resources/CMakeLists.txt b/external/vulkancts/modules/vulkan/sparse_resources/CMakeLists.txt index 80a79d2..4da15e5 100644 --- a/external/vulkancts/modules/vulkan/sparse_resources/CMakeLists.txt +++ b/external/vulkancts/modules/vulkan/sparse_resources/CMakeLists.txt @@ -17,6 +17,8 @@ set(DEQP_VK_SPARSE_RESOURCES_SRCS vktSparseResourcesImageSparseResidency.hpp vktSparseResourcesMipmapSparseResidency.cpp vktSparseResourcesMipmapSparseResidency.hpp + vktSparseResourcesQueueBindSparseTests.cpp + vktSparseResourcesQueueBindSparseTests.hpp vktSparseResourcesShaderIntrinsics.cpp vktSparseResourcesShaderIntrinsics.hpp vktSparseResourcesShaderIntrinsicsBase.cpp diff --git a/external/vulkancts/modules/vulkan/sparse_resources/vktSparseResourcesQueueBindSparseTests.cpp b/external/vulkancts/modules/vulkan/sparse_resources/vktSparseResourcesQueueBindSparseTests.cpp new file mode 100644 index 0000000..1aa3b7c --- /dev/null +++ b/external/vulkancts/modules/vulkan/sparse_resources/vktSparseResourcesQueueBindSparseTests.cpp @@ -0,0 +1,379 @@ +/*------------------------------------------------------------------------ + * Vulkan Conformance Tests + * ------------------------ + * + * Copyright (c) 2016 The Khronos Group Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *//*! + * \file + * \brief Queue bind sparse tests + *//*--------------------------------------------------------------------*/ + +#include "vktSparseResourcesQueueBindSparseTests.hpp" +#include "vktSparseResourcesTestsUtil.hpp" +#include "vktSparseResourcesBase.hpp" +#include "vktTestGroupUtil.hpp" + +#include "vkDefs.hpp" +#include "vkRefUtil.hpp" +#include "vkMemUtil.hpp" +#include "vkTypeUtil.hpp" +#include "vkQueryUtil.hpp" + +#include "deUniquePtr.hpp" +#include "deSharedPtr.hpp" + +#include +#include + +using namespace vk; +using de::MovePtr; + +namespace vkt +{ +namespace sparse +{ +namespace +{ + +typedef de::SharedPtr > SemaphoreSp; +typedef de::SharedPtr > FenceSp; + +struct TestParams +{ + deUint32 numQueues; //! use 2 or more to sync between different queues + deUint32 numWaitSemaphores; + deUint32 numSignalSemaphores; + bool emptySubmission; //! will make an empty bind sparse submission + bool bindSparseUseFence; +}; + +struct QueueSubmission +{ + union InfoUnion + { + VkSubmitInfo regular; + VkBindSparseInfo sparse; + }; + + const Queue* queue; + bool isSparseBinding; + InfoUnion info; +}; + +QueueSubmission makeSubmissionRegular (const Queue* queue, + const deUint32 numWaitSemaphores, + const VkSemaphore* pWaitSemaphore, + const VkPipelineStageFlags* pWaitDstStageMask, + const deUint32 numSignalSemaphores, + const VkSemaphore* pSignalSemaphore) +{ + const VkSubmitInfo submitInfo = + { + VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + numWaitSemaphores, // uint32_t waitSemaphoreCount; + pWaitSemaphore, // const VkSemaphore* pWaitSemaphores; + pWaitDstStageMask, // const VkPipelineStageFlags* pWaitDstStageMask; + 0u, // uint32_t commandBufferCount; + DE_NULL, // const VkCommandBuffer* pCommandBuffers; + numSignalSemaphores, // uint32_t signalSemaphoreCount; + pSignalSemaphore, // const VkSemaphore* pSignalSemaphores; + }; + + QueueSubmission submission; + submission.isSparseBinding = false; + submission.queue = queue; + submission.info.regular = submitInfo; + + return submission; +} + +QueueSubmission makeSubmissionSparse (const Queue* queue, + const deUint32 numWaitSemaphores, + const VkSemaphore* pWaitSemaphore, + const deUint32 numSignalSemaphores, + const VkSemaphore* pSignalSemaphore) +{ + const VkBindSparseInfo bindInfo = + { + VK_STRUCTURE_TYPE_BIND_SPARSE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + numWaitSemaphores, // uint32_t waitSemaphoreCount; + pWaitSemaphore, // const VkSemaphore* pWaitSemaphores; + 0u, // uint32_t bufferBindCount; + DE_NULL, // const VkSparseBufferMemoryBindInfo* pBufferBinds; + 0u, // uint32_t imageOpaqueBindCount; + DE_NULL, // const VkSparseImageOpaqueMemoryBindInfo* pImageOpaqueBinds; + 0u, // uint32_t imageBindCount; + DE_NULL, // const VkSparseImageMemoryBindInfo* pImageBinds; + numSignalSemaphores, // uint32_t signalSemaphoreCount; + pSignalSemaphore, // const VkSemaphore* pSignalSemaphores; + }; + + QueueSubmission submission; + submission.isSparseBinding = true; + submission.queue = queue; + submission.info.sparse = bindInfo; + + return submission; +} + +bool waitForFences (const DeviceInterface& vk, const VkDevice device, const std::vector& fences) +{ + for (std::vector::const_iterator fenceSpIter = fences.begin(); fenceSpIter != fences.end(); ++fenceSpIter) + { + if (vk.waitForFences(device, 1u, &(***fenceSpIter), VK_TRUE, ~0ull) != VK_SUCCESS) + return false; + } + return true; +} + +class SparseQueueBindTestInstance : public SparseResourcesBaseInstance +{ +public: + SparseQueueBindTestInstance (Context &context, const TestParams& params) + : SparseResourcesBaseInstance (context) + , m_params (params) + { + DE_ASSERT(m_params.numQueues > 0u); // must use at least one queue + DE_ASSERT(!m_params.emptySubmission || (m_params.numWaitSemaphores == 0u && m_params.numSignalSemaphores == 0u)); // can't use semaphores if we don't submit + } + + tcu::TestStatus iterate (void) + { + const DeviceInterface& vk = m_context.getDeviceInterface(); + const InstanceInterface& vki = m_context.getInstanceInterface(); + const VkPhysicalDevice physDevice = m_context.getPhysicalDevice(); + const Queue* sparseQueue = DE_NULL; + std::vector otherQueues; + + if (!getPhysicalDeviceFeatures(vki, physDevice).sparseBinding) + TCU_THROW(NotSupportedError, "Sparse binding not supported"); + + // Determine required queues and create a device that supports them + { + QueueRequirementsVec requirements; + requirements.push_back(QueueRequirements(VK_QUEUE_SPARSE_BINDING_BIT, 1u)); + requirements.push_back(QueueRequirements((VkQueueFlags)0, m_params.numQueues)); // any queue flags + + createDeviceSupportingQueues(requirements); + + sparseQueue = &getQueue(VK_QUEUE_SPARSE_BINDING_BIT, 0u); + + // We probably have picked the sparse queue again, so filter it out + for (deUint32 queueNdx = 0u; queueNdx < m_params.numQueues; ++queueNdx) + { + const Queue* queue = &getQueue((VkQueueFlags)0, queueNdx); + if (queue->queueHandle != sparseQueue->queueHandle) + otherQueues.push_back(queue); + } + } + + std::vector allSemaphores; + std::vector waitSemaphores; + std::vector signalSemaphores; + std::vector signalSemaphoresWaitDstStageMask; + std::vector queueSubmissions; + + for (deUint32 i = 0; i < m_params.numWaitSemaphores; ++i) + { + allSemaphores.push_back(makeVkSharedPtr(makeSemaphore(vk, getDevice()))); + waitSemaphores.push_back(**allSemaphores.back()); + } + + for (deUint32 i = 0; i < m_params.numSignalSemaphores; ++i) + { + allSemaphores.push_back(makeVkSharedPtr(makeSemaphore(vk, getDevice()))); + signalSemaphores.push_back(**allSemaphores.back()); + signalSemaphoresWaitDstStageMask.push_back(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT); + } + + // Prepare submissions: signal semaphores for the sparse bind operation + { + deUint32 numQueues = 1u + static_cast(otherQueues.size()); + deUint32 numSemaphores = m_params.numWaitSemaphores; + + while (numSemaphores > 0u && numQueues > 0u) + { + if (numQueues == 1u) // sparse queue is assigned last + { + // sparse queue can handle regular submissions as well + queueSubmissions.push_back(makeSubmissionRegular( + sparseQueue, 0u, DE_NULL, DE_NULL, numSemaphores, getDataOrNullptr(waitSemaphores))); + numSemaphores = 0u; + numQueues = 0u; + } + else + { + queueSubmissions.push_back(makeSubmissionRegular( + otherQueues[numQueues - 2], 0u, DE_NULL, DE_NULL, 1u, getDataOrNullptr(waitSemaphores, numSemaphores - 1))); + --numQueues; + --numSemaphores; + } + } + } + + // Prepare submission: bind sparse + if (!m_params.emptySubmission) + { + queueSubmissions.push_back(makeSubmissionSparse( + sparseQueue, m_params.numWaitSemaphores, getDataOrNullptr(waitSemaphores), m_params.numSignalSemaphores, getDataOrNullptr(signalSemaphores))); + } + else + { + // a dummy submission, won't be used in a call to vkQueueBindSparse + queueSubmissions.push_back(makeSubmissionSparse(sparseQueue, 0u, DE_NULL, 0u, DE_NULL)); + } + + // Prepare submissions: wait on semaphores signaled by the sparse bind operation + if (!m_params.emptySubmission) + { + deUint32 numQueues = 1u + static_cast(otherQueues.size()); + deUint32 numSemaphores = m_params.numSignalSemaphores; + + while (numSemaphores > 0u && numQueues > 0u) + { + if (numQueues == 1u) + { + queueSubmissions.push_back(makeSubmissionRegular( + sparseQueue, numSemaphores, getDataOrNullptr(signalSemaphores), getDataOrNullptr(signalSemaphoresWaitDstStageMask), 0u, DE_NULL)); + numSemaphores = 0u; + numQueues = 0u; + } + else + { + queueSubmissions.push_back(makeSubmissionRegular( + otherQueues[numQueues - 2], 1u, getDataOrNullptr(signalSemaphores, numSemaphores - 1), getDataOrNullptr(signalSemaphoresWaitDstStageMask, numSemaphores - 1), 0u, DE_NULL)); + --numQueues; + --numSemaphores; + } + } + } + + // Submit to queues + { + std::vector regularFences; + std::vector bindSparseFences; + + for (std::vector::const_iterator submissionIter = queueSubmissions.begin(); submissionIter != queueSubmissions.end(); ++submissionIter) + { + if (submissionIter->isSparseBinding) + { + VkFence fence = DE_NULL; + + if (m_params.bindSparseUseFence) + { + bindSparseFences.push_back(makeVkSharedPtr(makeFence(vk, getDevice()))); + fence = **bindSparseFences.back(); + } + + if (m_params.emptySubmission) + VK_CHECK(vk.queueBindSparse(submissionIter->queue->queueHandle, 0u, DE_NULL, fence)); + else + VK_CHECK(vk.queueBindSparse(submissionIter->queue->queueHandle, 1u, &submissionIter->info.sparse, fence)); + } + else + { + regularFences.push_back(makeVkSharedPtr(makeFence(vk, getDevice()))); + VK_CHECK(vk.queueSubmit(submissionIter->queue->queueHandle, 1u, &submissionIter->info.regular, **regularFences.back())); + } + } + + if (!waitForFences(vk, getDevice(), bindSparseFences)) + return tcu::TestStatus::fail("vkQueueBindSparse didn't signal the fence"); + + if (!waitForFences(vk, getDevice(), regularFences)) + return tcu::TestStatus::fail("Some fences weren't signaled (vkQueueBindSparse didn't signal semaphores?)"); + } + + // May return an error if some waitSemaphores didn't get signaled + VK_CHECK(vk.deviceWaitIdle(getDevice())); + + return tcu::TestStatus::pass("Pass"); + } + +private: + const TestParams m_params; +}; + +class SparseQueueBindTest : public TestCase +{ +public: + SparseQueueBindTest (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const TestParams& params) + : TestCase (testCtx, name, description) + , m_params (params) + { + DE_ASSERT(params.numQueues > 0u); + DE_ASSERT(params.numQueues == 1u || m_params.numWaitSemaphores > 0u || m_params.numSignalSemaphores > 0u); // without any semaphores, only sparse queue will be used + } + + TestInstance* createInstance (Context& context) const + { + return new SparseQueueBindTestInstance(context, m_params); + } + +private: + const TestParams m_params; +}; + +void populateTestGroup(tcu::TestCaseGroup* group) +{ + const struct + { + std::string name; + TestParams params; + std::string description; + } cases[] = + { + // case name // numQueues, numWaitSems, numSignalSems, emptySubmission, checkFence + { "no_dependency", { 1u, 0u, 0u, false, false, }, "submit without any semaphores", }, + { "no_dependency_fence", { 1u, 0u, 0u, false, true, }, "submit without any semaphores, signal a fence", }, + + { "single_queue_wait_one", { 1u, 1u, 0u, false, true, }, "only sparse queue, wait for semaphore(s)", }, + { "single_queue_wait_many", { 1u, 3u, 0u, false, true, }, "only sparse queue, wait for semaphore(s)", }, + { "single_queue_signal_one", { 1u, 0u, 1u, false, true, }, "only sparse queue, signal semaphore(s)", }, + { "single_queue_signal_many", { 1u, 0u, 3u, false, true, }, "only sparse queue, signal semaphore(s)", }, + { "single_queue_wait_one_signal_one", { 1u, 1u, 1u, false, true, }, "only sparse queue, wait for and signal semaphore(s)", }, + { "single_queue_wait_many_signal_many", { 1u, 2u, 3u, false, true, }, "only sparse queue, wait for and signal semaphore(s)", }, + + { "multi_queue_wait_one", { 2u, 1u, 0u, false, true, }, "sparse and other queues, wait for semaphore(s)", }, + { "multi_queue_wait_many", { 2u, 2u, 0u, false, true, }, "sparse and other queues, wait for semaphore(s)", }, + { "multi_queue_signal_one", { 2u, 0u, 1u, false, true, }, "sparse and other queues, signal semaphore(s)", }, + { "multi_queue_signal_many", { 2u, 0u, 2u, false, true, }, "sparse and other queues, signal semaphore(s)", }, + { "multi_queue_wait_one_signal_one", { 2u, 1u, 1u, false, true, }, "sparse and other queues, wait for and signal semaphore(s)", }, + { "multi_queue_wait_many_signal_many", { 2u, 2u, 2u, false, true, }, "sparse and other queues, wait for and signal semaphore(s)", }, + { "multi_queue_wait_one_signal_one_other", { 2u, 1u, 1u, false, true, }, "sparse and other queues, wait for and signal semaphore(s) on other queues", }, + { "multi_queue_wait_many_signal_many_other", { 3u, 2u, 2u, false, true, }, "sparse and other queues, wait for and signal semaphore(s) on other queues", }, + + { "empty", { 1u, 0u, 0u, true, false, }, "call vkQueueBindSparse with zero bindInfos", }, + { "empty_fence", { 1u, 0u, 0u, true, true, }, "call vkQueueBindSparse with zero bindInfos, signal a fence", }, + }; + + for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); ++caseNdx) + group->addChild(new SparseQueueBindTest(group->getTestContext(), cases[caseNdx].name, cases[caseNdx].description, cases[caseNdx].params)); +} + +} // anonymous ns + +//! Sparse queue binding edge cases and synchronization with semaphores/fences. +//! Actual binding and usage is tested by other test groups. +tcu::TestCaseGroup* createQueueBindSparseTests (tcu::TestContext& testCtx) +{ + return createTestGroup(testCtx, "queue_bind", "Queue bind sparse tests", populateTestGroup); +} + +} // sparse +} // vkt diff --git a/external/vulkancts/modules/vulkan/sparse_resources/vktSparseResourcesQueueBindSparseTests.hpp b/external/vulkancts/modules/vulkan/sparse_resources/vktSparseResourcesQueueBindSparseTests.hpp new file mode 100644 index 0000000..e0f0b94 --- /dev/null +++ b/external/vulkancts/modules/vulkan/sparse_resources/vktSparseResourcesQueueBindSparseTests.hpp @@ -0,0 +1,39 @@ +#ifndef _VKTSPARSERESOURCESQUEUEBINDSPARSETESTS_HPP +#define _VKTSPARSERESOURCESQUEUEBINDSPARSETESTS_HPP +/*------------------------------------------------------------------------ + * Vulkan Conformance Tests + * ------------------------ + * + * Copyright (c) 2016 The Khronos Group Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *//*! + * \file + * \brief Queue bind sparse tests + *//*--------------------------------------------------------------------*/ + +#include "tcuDefs.hpp" +#include "vktTestCase.hpp" + +namespace vkt +{ +namespace sparse +{ + +tcu::TestCaseGroup* createQueueBindSparseTests (tcu::TestContext& testCtx); + +} // sparse +} // vkt + +#endif // _VKTSPARSERESOURCESQUEUEBINDSPARSETESTS_HPP diff --git a/external/vulkancts/modules/vulkan/sparse_resources/vktSparseResourcesTests.cpp b/external/vulkancts/modules/vulkan/sparse_resources/vktSparseResourcesTests.cpp index c9f26ce..44b8f68 100644 --- a/external/vulkancts/modules/vulkan/sparse_resources/vktSparseResourcesTests.cpp +++ b/external/vulkancts/modules/vulkan/sparse_resources/vktSparseResourcesTests.cpp @@ -30,6 +30,7 @@ #include "vktSparseResourcesBufferMemoryAliasing.hpp" #include "vktSparseResourcesImageMemoryAliasing.hpp" #include "vktSparseResourcesShaderIntrinsics.hpp" +#include "vktSparseResourcesQueueBindSparseTests.hpp" #include "deUniquePtr.hpp" namespace vkt @@ -49,6 +50,7 @@ tcu::TestCaseGroup* createTests (tcu::TestContext& testCtx) sparseTests->addChild(createBufferSparseMemoryAliasingTests (testCtx)); sparseTests->addChild(createImageSparseMemoryAliasingTests (testCtx)); sparseTests->addChild(createSparseResourcesShaderIntrinsicsTests(testCtx)); + sparseTests->addChild(createQueueBindSparseTests (testCtx)); return sparseTests.release(); } diff --git a/external/vulkancts/mustpass/1.0.2/vk-default.txt b/external/vulkancts/mustpass/1.0.2/vk-default.txt index e9e3d16..c8e1f95 100644 --- a/external/vulkancts/mustpass/1.0.2/vk-default.txt +++ b/external/vulkancts/mustpass/1.0.2/vk-default.txt @@ -111538,6 +111538,24 @@ dEQP-VK.sparse_resources.shader_intrinsics.2d_array_sparse_gather.rgba8ui.512_25 dEQP-VK.sparse_resources.shader_intrinsics.2d_array_sparse_gather.rgba8ui.128_128_8 dEQP-VK.sparse_resources.shader_intrinsics.2d_array_sparse_gather.rgba8ui.503_137_3 dEQP-VK.sparse_resources.shader_intrinsics.2d_array_sparse_gather.rgba8ui.11_37_3 +dEQP-VK.sparse_resources.queue_bind.no_dependency +dEQP-VK.sparse_resources.queue_bind.no_dependency_fence +dEQP-VK.sparse_resources.queue_bind.single_queue_wait_one +dEQP-VK.sparse_resources.queue_bind.single_queue_wait_many +dEQP-VK.sparse_resources.queue_bind.single_queue_signal_one +dEQP-VK.sparse_resources.queue_bind.single_queue_signal_many +dEQP-VK.sparse_resources.queue_bind.single_queue_wait_one_signal_one +dEQP-VK.sparse_resources.queue_bind.single_queue_wait_many_signal_many +dEQP-VK.sparse_resources.queue_bind.multi_queue_wait_one +dEQP-VK.sparse_resources.queue_bind.multi_queue_wait_many +dEQP-VK.sparse_resources.queue_bind.multi_queue_signal_one +dEQP-VK.sparse_resources.queue_bind.multi_queue_signal_many +dEQP-VK.sparse_resources.queue_bind.multi_queue_wait_one_signal_one +dEQP-VK.sparse_resources.queue_bind.multi_queue_wait_many_signal_many +dEQP-VK.sparse_resources.queue_bind.multi_queue_wait_one_signal_one_other +dEQP-VK.sparse_resources.queue_bind.multi_queue_wait_many_signal_many_other +dEQP-VK.sparse_resources.queue_bind.empty +dEQP-VK.sparse_resources.queue_bind.empty_fence dEQP-VK.tessellation.limits.max_tessellation_generation_level dEQP-VK.tessellation.limits.max_tessellation_patch_size dEQP-VK.tessellation.limits.max_tessellation_control_per_vertex_input_components