/*------------------------------------------------------------------------ * Vulkan Conformance Tests * ------------------------ * * Copyright (c) 2018 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 Vulkan Performance Query Tests *//*--------------------------------------------------------------------*/ #include "vktQueryPoolPerformanceTests.hpp" #include "vktTestCase.hpp" #include "vktDrawImageObjectUtil.hpp" #include "vktDrawBufferObjectUtil.hpp" #include "vktDrawCreateInfoUtil.hpp" #include "vkBuilderUtil.hpp" #include "vkRefUtil.hpp" #include "vkPrograms.hpp" #include "vkTypeUtil.hpp" #include "vkCmdUtil.hpp" #include "vkQueryUtil.hpp" #include "deMath.h" #include "tcuTestLog.hpp" #include "tcuResource.hpp" #include "tcuImageCompare.hpp" #include "vkImageUtil.hpp" #include "tcuCommandLine.hpp" #include "tcuRGBA.hpp" namespace vkt { namespace QueryPool { namespace { using namespace vk; using namespace Draw; std::string uuidToHex(const deUint8 uuid[]) { const size_t bytesPerPart[] = {4, 2, 2, 2, 6}; const deUint8* ptr = &uuid[0]; const size_t stringSize = VK_UUID_SIZE * 2 + DE_LENGTH_OF_ARRAY(bytesPerPart) - 1; std::string result; result.reserve(stringSize); for (size_t partNdx = 0; partNdx < DE_LENGTH_OF_ARRAY(bytesPerPart); ++partNdx) { const size_t bytesInPart = bytesPerPart[partNdx]; const size_t symbolsInPart = 2 * bytesInPart; deUint64 part = 0; std::string partString; for (size_t byteInPartNdx = 0; byteInPartNdx < bytesInPart; ++byteInPartNdx) { part = (part << 8) | *ptr; ++ptr; } partString = tcu::toHex(part).toString(); DE_ASSERT(partString.size() > symbolsInPart); result += (symbolsInPart >= partString.size()) ? partString : partString.substr(partString.size() - symbolsInPart); if (partNdx + 1 != DE_LENGTH_OF_ARRAY(bytesPerPart)) result += '-'; } DE_ASSERT(ptr == &uuid[VK_UUID_SIZE]); DE_ASSERT(result.size() == stringSize); return result; } class EnumerateAndValidateTest : public TestInstance { public: EnumerateAndValidateTest (vkt::Context& context, VkQueueFlagBits queueFlagBits); tcu::TestStatus iterate (void); protected: void basicValidateCounter (const deUint32 familyIndex); private: VkQueueFlagBits m_queueFlagBits; bool m_requiredExtensionsPresent; }; EnumerateAndValidateTest::EnumerateAndValidateTest (vkt::Context& context, VkQueueFlagBits queueFlagBits) : TestInstance(context) , m_queueFlagBits(queueFlagBits) , m_requiredExtensionsPresent(context.requireDeviceFunctionality("VK_KHR_performance_query")) { } tcu::TestStatus EnumerateAndValidateTest::iterate (void) { const InstanceInterface& vki = m_context.getInstanceInterface(); const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice(); const std::vector queueProperties = getPhysicalDeviceQueueFamilyProperties(vki, physicalDevice); for (deUint32 queueNdx = 0; queueNdx < queueProperties.size(); queueNdx++) { if ((queueProperties[queueNdx].queueFlags & m_queueFlagBits) == 0) continue; deUint32 counterCount = 0; VK_CHECK(vki.enumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR(physicalDevice, queueNdx, &counterCount, DE_NULL, DE_NULL)); if (counterCount == 0) continue; { std::vector counters (counterCount); for (deUint32 i = 0; i < counterCount; ++i) counters[i] = vk::initVulkanStructure(); deUint32 counterCountRead = counterCount; std::map uuidValidator; if (counterCount > 1) { deUint32 incompleteCounterCount = counterCount - 1; VkResult result; result = vki.enumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR(physicalDevice, queueNdx, &incompleteCounterCount, &counters[0], DE_NULL); if (result != VK_INCOMPLETE) TCU_FAIL("VK_INCOMPLETE not returned"); } VK_CHECK(vki.enumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR(physicalDevice, queueNdx, &counterCountRead, &counters[0], DE_NULL)); if (counterCountRead != counterCount) TCU_FAIL("Number of counters read (" + de::toString(counterCountRead) + ") is not equal to number of counters reported (" + de::toString(counterCount) + ")"); for (size_t counterNdx = 0; counterNdx < counters.size(); ++counterNdx) { const VkPerformanceCounterKHR& counter = counters[counterNdx]; const std::string uuidStr = uuidToHex(counter.uuid); if (uuidValidator.find(uuidStr) != uuidValidator.end()) TCU_FAIL("Duplicate counter UUID detected " + uuidStr); else uuidValidator[uuidStr] = counterNdx; if (counter.scope >= VK_PERFORMANCE_COUNTER_SCOPE_KHR_LAST) TCU_FAIL("Counter scope is invalid " + de::toString(static_cast(counter.scope))); if (counter.storage >= VK_PERFORMANCE_COUNTER_STORAGE_KHR_LAST) TCU_FAIL("Counter storage is invalid " + de::toString(static_cast(counter.storage))); if (counter.unit >= VK_PERFORMANCE_COUNTER_UNIT_KHR_LAST) TCU_FAIL("Counter unit is invalid " + de::toString(static_cast(counter.unit))); } } { std::vector counterDescriptors (counterCount); for (deUint32 i = 0; i < counterCount; ++i) counterDescriptors[i] = vk::initVulkanStructure(); deUint32 counterCountRead = counterCount; VK_CHECK(vki.enumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR(physicalDevice, queueNdx, &counterCountRead, DE_NULL, &counterDescriptors[0])); if (counterCountRead != counterCount) TCU_FAIL("Number of counters read (" + de::toString(counterCountRead) + ") is not equal to number of counters reported (" + de::toString(counterCount) + ")"); for (size_t counterNdx = 0; counterNdx < counterDescriptors.size(); ++counterNdx) { const VkPerformanceCounterDescriptionKHR& counterDescriptor = counterDescriptors[counterNdx]; const VkPerformanceCounterDescriptionFlagsKHR allowedFlags = VK_PERFORMANCE_COUNTER_DESCRIPTION_PERFORMANCE_IMPACTING_KHR | VK_PERFORMANCE_COUNTER_DESCRIPTION_CONCURRENTLY_IMPACTED_KHR; if ((counterDescriptor.flags & ~allowedFlags) != 0) TCU_FAIL("Invalid flags present in VkPerformanceCounterDescriptionFlagsKHR"); } } } return tcu::TestStatus::pass("Pass"); } class QueryTestBase : public TestInstance { public: QueryTestBase (vkt::Context& context); protected: void setupCounters (void); Move createQueryPool (deUint32 enabledCounterOffset, deUint32 enabledCounterStride); bool acquireProfilingLock (void); void releaseProfilingLock (void); bool verifyQueryResults (VkQueryPool queryPool); deUint32 getRequiredNumerOfPasses(void); private: bool m_requiredExtensionsPresent; deUint32 m_requiredNumerOfPasses; std::map m_enabledCountersCountMap; // number of counters that were enabled per query pool std::vector m_counters; // counters provided by the device }; QueryTestBase::QueryTestBase(vkt::Context& context) : TestInstance (context) , m_requiredExtensionsPresent(context.requireDeviceFunctionality("VK_KHR_performance_query")) , m_requiredNumerOfPasses(0) { } void QueryTestBase::setupCounters() { const InstanceInterface& vki = m_context.getInstanceInterface(); const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice(); const CmdPoolCreateInfo cmdPoolCreateInfo = m_context.getUniversalQueueFamilyIndex(); deUint32 queueFamilyIndex = cmdPoolCreateInfo.queueFamilyIndex; deUint32 counterCount; if (!m_context.getPerformanceQueryFeatures().performanceCounterQueryPools) TCU_THROW(NotSupportedError, "Performance counter query pools feature not supported"); // get the number of supported counters VK_CHECK(vki.enumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR(physicalDevice, queueFamilyIndex, &counterCount, NULL, NULL)); if (!counterCount) TCU_THROW(NotSupportedError, "QualityWarning: there are no performance counters"); // get supported counters m_counters.resize(counterCount, vk::initVulkanStructure()); VK_CHECK(vki.enumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR(physicalDevice, queueFamilyIndex, &counterCount, &m_counters[0], DE_NULL)); } Move QueryTestBase::createQueryPool(deUint32 enabledCounterOffset, deUint32 enabledCounterStride) { const InstanceInterface& vki = m_context.getInstanceInterface(); const DeviceInterface& vkd = m_context.getDeviceInterface(); const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice(); const VkDevice device = m_context.getDevice(); const CmdPoolCreateInfo cmdPoolCreateInfo = m_context.getUniversalQueueFamilyIndex(); const deUint32 counterCount = (deUint32)m_counters.size(); deUint32 enabledIndex = enabledCounterOffset ? 0 : enabledCounterStride; std::vector enabledCounters; // enable every counter that has command or render pass scope for (deUint32 i = 0; i < counterCount; i++) { // handle offset if (enabledCounterOffset) { if (enabledCounterOffset == enabledIndex) { // disable handling offset enabledCounterOffset = 0; // eneble next index in stride condition enabledIndex = enabledCounterStride; } else { ++enabledIndex; continue; } } // handle stride if (enabledIndex == enabledCounterStride) { enabledCounters.push_back(i); enabledIndex = 0; } else ++enabledIndex; } // get number of counters that were enabled for this query pool deUint32 enabledCountersCount = static_cast(enabledCounters.size()); if (!enabledCountersCount) TCU_THROW(NotSupportedError, "QualityWarning: no performance counters"); // define performance query VkQueryPoolPerformanceCreateInfoKHR performanceQueryCreateInfo = { VK_STRUCTURE_TYPE_QUERY_POOL_PERFORMANCE_CREATE_INFO_KHR, NULL, cmdPoolCreateInfo.queueFamilyIndex, // queue family that this performance query is performed on enabledCountersCount, // number of counters to enable &enabledCounters[0] // array of indices of counters to enable }; // get the number of passes counters will require vki.getPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR(physicalDevice, &performanceQueryCreateInfo, &m_requiredNumerOfPasses); // create query pool VkQueryPoolCreateInfo queryPoolCreateInfo = { VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, &performanceQueryCreateInfo, 0, // flags VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR, // new query type 1, // queryCount 0 }; Move queryPool = vk::createQueryPool(vkd, device, &queryPoolCreateInfo); // memorize number of enabled counters for this query pool m_enabledCountersCountMap[queryPool.get().getInternal()] = enabledCountersCount; return queryPool; } bool QueryTestBase::acquireProfilingLock() { const DeviceInterface& vkd = m_context.getDeviceInterface(); const VkDevice device = m_context.getDevice(); // acquire profiling lock before we record command buffers VkAcquireProfilingLockInfoKHR lockInfo = { VK_STRUCTURE_TYPE_ACQUIRE_PROFILING_LOCK_INFO_KHR, NULL, 0, 2000000000ull // wait 2s for the lock }; VkResult result = vkd.acquireProfilingLockKHR(device, &lockInfo); if (result == VK_TIMEOUT) { m_context.getTestContext().getLog() << tcu::TestLog::Message << "Timeout reached, profiling lock wasn't acquired - test had to end earlier" << tcu::TestLog::EndMessage; return false; } if (result != VK_SUCCESS) TCU_FAIL("Profiling lock wasn't acquired"); return true; } void QueryTestBase::releaseProfilingLock() { const DeviceInterface& vkd = m_context.getDeviceInterface(); const VkDevice device = m_context.getDevice(); // release the profiling lock after the command buffer is no longer in the pending state vkd.releaseProfilingLockKHR(device); } bool QueryTestBase::verifyQueryResults(VkQueryPool queryPool) { const DeviceInterface& vkd = m_context.getDeviceInterface(); const VkDevice device = m_context.getDevice(); // create an array to hold the results of all counters deUint32 enabledCounterCount = m_enabledCountersCountMap[queryPool.getInternal()]; std::vector recordedCounters(enabledCounterCount); // verify that query result can be retrieved VkResult result = vkd.getQueryPoolResults(device, queryPool, 0, 1, sizeof(VkPerformanceCounterResultKHR) * enabledCounterCount, &recordedCounters[0], sizeof(VkPerformanceCounterResultKHR), VK_QUERY_RESULT_WAIT_BIT); if (result == VK_NOT_READY) { m_context.getTestContext().getLog() << tcu::TestLog::Message << "Pass but result is not ready" << tcu::TestLog::EndMessage; return true; } return (result == VK_SUCCESS); } deUint32 QueryTestBase::getRequiredNumerOfPasses() { return m_requiredNumerOfPasses; } // Base class for all graphic tests class GraphicQueryTestBase : public QueryTestBase { public: GraphicQueryTestBase(vkt::Context& context); protected: void initStateObjects(void); protected: Move m_pipeline; Move m_pipelineLayout; de::SharedPtr m_colorAttachmentImage; Move m_attachmentView; Move m_renderPass; Move m_framebuffer; de::SharedPtr m_vertexBuffer; VkFormat m_colorAttachmentFormat; deUint32 m_size; }; GraphicQueryTestBase::GraphicQueryTestBase(vkt::Context& context) : QueryTestBase(context) , m_colorAttachmentFormat(VK_FORMAT_R8G8B8A8_UNORM) , m_size(32) { } void GraphicQueryTestBase::initStateObjects(void) { const VkDevice device = m_context.getDevice(); const DeviceInterface& vkd = m_context.getDeviceInterface(); //attachment images and views { VkExtent3D imageExtent = { m_size, // width m_size, // height 1 // depth }; const ImageCreateInfo colorImageCreateInfo(VK_IMAGE_TYPE_2D, m_colorAttachmentFormat, imageExtent, 1, 1, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT); m_colorAttachmentImage = Image::createAndAlloc(vkd, device, colorImageCreateInfo, m_context.getDefaultAllocator(), m_context.getUniversalQueueFamilyIndex()); const ImageViewCreateInfo attachmentViewInfo(m_colorAttachmentImage->object(), VK_IMAGE_VIEW_TYPE_2D, m_colorAttachmentFormat); m_attachmentView = createImageView(vkd, device, &attachmentViewInfo); } // renderpass and framebuffer { RenderPassCreateInfo renderPassCreateInfo; renderPassCreateInfo.addAttachment(AttachmentDescription(m_colorAttachmentFormat, // format VK_SAMPLE_COUNT_1_BIT, // samples VK_ATTACHMENT_LOAD_OP_CLEAR, // loadOp VK_ATTACHMENT_STORE_OP_DONT_CARE, // storeOp VK_ATTACHMENT_LOAD_OP_DONT_CARE, // stencilLoadOp VK_ATTACHMENT_STORE_OP_DONT_CARE, // stencilLoadOp VK_IMAGE_LAYOUT_GENERAL, // initialLauout VK_IMAGE_LAYOUT_GENERAL)); // finalLayout const VkAttachmentReference colorAttachmentReference = { 0, // attachment VK_IMAGE_LAYOUT_GENERAL // layout }; renderPassCreateInfo.addSubpass(SubpassDescription(VK_PIPELINE_BIND_POINT_GRAPHICS, // pipelineBindPoint 0, // flags 0, // inputCount DE_NULL, // pInputAttachments 1, // colorCount &colorAttachmentReference, // pColorAttachments DE_NULL, // pResolveAttachments AttachmentReference(), // depthStencilAttachment 0, // preserveCount DE_NULL)); // preserveAttachments m_renderPass = createRenderPass(vkd, device, &renderPassCreateInfo); std::vector attachments(1); attachments[0] = *m_attachmentView; FramebufferCreateInfo framebufferCreateInfo(*m_renderPass, attachments, m_size, m_size, 1); m_framebuffer = createFramebuffer(vkd, device, &framebufferCreateInfo); } // pipeline { Unique vs(createShaderModule(vkd, device, m_context.getBinaryCollection().get("vert"), 0)); Unique fs(createShaderModule(vkd, device, m_context.getBinaryCollection().get("frag"), 0)); const PipelineCreateInfo::ColorBlendState::Attachment attachmentState; const PipelineLayoutCreateInfo pipelineLayoutCreateInfo; m_pipelineLayout = createPipelineLayout(vkd, device, &pipelineLayoutCreateInfo); const VkVertexInputBindingDescription vf_binding_desc = { 0, // binding 4 * (deUint32)sizeof(float), // stride VK_VERTEX_INPUT_RATE_VERTEX // inputRate }; const VkVertexInputAttributeDescription vf_attribute_desc = { 0, // location 0, // binding VK_FORMAT_R32G32B32A32_SFLOAT, // format 0 // offset }; const VkPipelineVertexInputStateCreateInfo vf_info = { VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // sType NULL, // pNext 0u, // flags 1, // vertexBindingDescriptionCount &vf_binding_desc, // pVertexBindingDescriptions 1, // vertexAttributeDescriptionCount &vf_attribute_desc // pVertexAttributeDescriptions }; PipelineCreateInfo pipelineCreateInfo(*m_pipelineLayout, *m_renderPass, 0, 0); pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vs, "main", VK_SHADER_STAGE_VERTEX_BIT)); pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fs, "main", VK_SHADER_STAGE_FRAGMENT_BIT)); pipelineCreateInfo.addState(PipelineCreateInfo::InputAssemblerState(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)); pipelineCreateInfo.addState(PipelineCreateInfo::ColorBlendState(1, &attachmentState)); const VkViewport viewport = makeViewport(m_size, m_size); const VkRect2D scissor = makeRect2D(m_size, m_size); pipelineCreateInfo.addState(PipelineCreateInfo::ViewportState(1, std::vector(1, viewport), std::vector(1, scissor))); pipelineCreateInfo.addState(PipelineCreateInfo::DepthStencilState(false, false, VK_COMPARE_OP_GREATER_OR_EQUAL)); pipelineCreateInfo.addState(PipelineCreateInfo::RasterizerState()); pipelineCreateInfo.addState(PipelineCreateInfo::MultiSampleState()); pipelineCreateInfo.addState(vf_info); m_pipeline = createGraphicsPipeline(vkd, device, DE_NULL, &pipelineCreateInfo); } // vertex buffer { std::vector vertices(3); vertices[0] = tcu::Vec4(0.5, 0.5, 0.0, 1.0); vertices[1] = tcu::Vec4(0.5, 0.0, 0.0, 1.0); vertices[2] = tcu::Vec4(0.0, 0.5, 0.0, 1.0); const size_t kBufferSize = vertices.size() * sizeof(tcu::Vec4); m_vertexBuffer = Buffer::createAndAlloc(vkd, device, BufferCreateInfo(kBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), m_context.getDefaultAllocator(), MemoryRequirement::HostVisible); tcu::Vec4 *ptr = reinterpret_cast(m_vertexBuffer->getBoundMemory().getHostPtr()); deMemcpy(ptr, &vertices[0], kBufferSize); flushAlloc(vkd, device, m_vertexBuffer->getBoundMemory()); } } class GraphicQueryTest : public GraphicQueryTestBase { public: GraphicQueryTest (vkt::Context& context); tcu::TestStatus iterate (void); }; GraphicQueryTest::GraphicQueryTest(vkt::Context& context) : GraphicQueryTestBase(context) { } tcu::TestStatus GraphicQueryTest::iterate(void) { const DeviceInterface& vkd = m_context.getDeviceInterface(); const VkDevice device = m_context.getDevice(); const VkQueue queue = m_context.getUniversalQueue(); const CmdPoolCreateInfo cmdPoolCreateInfo = m_context.getUniversalQueueFamilyIndex(); Unique cmdPool (createCommandPool(vkd, device, &cmdPoolCreateInfo)); Unique cmdBuffer (allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY)); initStateObjects(); setupCounters(); vk::Unique queryPool(createQueryPool(0, 1)); if (!acquireProfilingLock()) { // lock was not acquired in given time, we can't fail the test return tcu::TestStatus::pass("Pass"); } // reset query pool { Unique resetCmdBuffer (allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY)); const Unique fence (createFence(vkd, device)); const VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO, // sType DE_NULL, // pNext 0u, // waitSemaphoreCount DE_NULL, // pWaitSemaphores (const VkPipelineStageFlags*)DE_NULL, // pWaitDstStageMask 1u, // commandBufferCount &resetCmdBuffer.get(), // pCommandBuffers 0u, // signalSemaphoreCount DE_NULL, // pSignalSemaphores }; beginCommandBuffer(vkd, *resetCmdBuffer); vkd.cmdResetQueryPool(*resetCmdBuffer, *queryPool, 0u, 1u); endCommandBuffer(vkd, *resetCmdBuffer); VK_CHECK(vkd.queueSubmit(queue, 1u, &submitInfo, *fence)); VK_CHECK(vkd.waitForFences(device, 1u, &fence.get(), DE_TRUE, ~0ull)); } // begin command buffer beginCommandBuffer(vkd, *cmdBuffer, 0u); initialTransitionColor2DImage(vkd, *cmdBuffer, m_colorAttachmentImage->object(), VK_IMAGE_LAYOUT_GENERAL, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT); // begin render pass VkClearValue renderPassClearValue; deMemset(&renderPassClearValue, 0, sizeof(VkClearValue)); // perform query during triangle draw vkd.cmdBeginQuery(*cmdBuffer, *queryPool, 0, VK_QUERY_CONTROL_PRECISE_BIT); beginRenderPass(vkd, *cmdBuffer, *m_renderPass, *m_framebuffer, makeRect2D(0, 0, m_size, m_size), 1, &renderPassClearValue); // bind pipeline vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline); // bind vertex buffer VkBuffer vertexBuffer = m_vertexBuffer->object(); const VkDeviceSize vertexBufferOffset = 0; vkd.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset); vkd.cmdDraw(*cmdBuffer, 3, 1, 0, 0); endRenderPass(vkd, *cmdBuffer); vkd.cmdEndQuery(*cmdBuffer, *queryPool, 0); transition2DImage(vkd, *cmdBuffer, m_colorAttachmentImage->object(), VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); endCommandBuffer(vkd, *cmdBuffer); // submit command buffer for each pass and wait for its completion for (deUint32 passIndex = 0; passIndex < getRequiredNumerOfPasses(); passIndex++) { const Unique fence(createFence(vkd, device)); VkPerformanceQuerySubmitInfoKHR performanceQuerySubmitInfo = { VK_STRUCTURE_TYPE_PERFORMANCE_QUERY_SUBMIT_INFO_KHR, NULL, passIndex }; const VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO, // sType &performanceQuerySubmitInfo, // pNext 0u, // waitSemaphoreCount DE_NULL, // pWaitSemaphores (const VkPipelineStageFlags*)DE_NULL, // pWaitDstStageMask 1u, // commandBufferCount &cmdBuffer.get(), // pCommandBuffers 0u, // signalSemaphoreCount DE_NULL, // pSignalSemaphores }; VK_CHECK(vkd.queueSubmit(queue, 1u, &submitInfo, *fence)); VK_CHECK(vkd.waitForFences(device, 1u, &fence.get(), DE_TRUE, ~0ull)); } releaseProfilingLock(); VK_CHECK(vkd.resetCommandBuffer(*cmdBuffer, 0)); if (verifyQueryResults(*queryPool)) return tcu::TestStatus::pass("Pass"); return tcu::TestStatus::fail("Fail"); } class GraphicMultiplePoolsTest : public GraphicQueryTestBase { public: GraphicMultiplePoolsTest (vkt::Context& context); tcu::TestStatus iterate (void); }; GraphicMultiplePoolsTest::GraphicMultiplePoolsTest(vkt::Context& context) : GraphicQueryTestBase(context) { } tcu::TestStatus GraphicMultiplePoolsTest::iterate(void) { if (!m_context.getPerformanceQueryFeatures().performanceCounterMultipleQueryPools) throw tcu::NotSupportedError("MultipleQueryPools not supported"); const DeviceInterface& vkd = m_context.getDeviceInterface(); const VkDevice device = m_context.getDevice(); const VkQueue queue = m_context.getUniversalQueue(); const CmdPoolCreateInfo cmdPoolCreateInfo = m_context.getUniversalQueueFamilyIndex(); Unique cmdPool (createCommandPool(vkd, device, &cmdPoolCreateInfo)); Unique cmdBuffer (allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY)); initStateObjects(); setupCounters(); vk::Unique queryPool1(createQueryPool(0, 2)), queryPool2(createQueryPool(1, 2)); if (!acquireProfilingLock()) { // lock was not acquired in given time, we can't fail the test return tcu::TestStatus::pass("Pass"); } // reset query pools { Unique resetCmdBuffer (allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY)); const Unique fence (createFence(vkd, device)); const VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO, // sType DE_NULL, // pNext 0u, // waitSemaphoreCount DE_NULL, // pWaitSemaphores (const VkPipelineStageFlags*)DE_NULL, // pWaitDstStageMask 1u, // commandBufferCount &resetCmdBuffer.get(), // pCommandBuffers 0u, // signalSemaphoreCount DE_NULL, // pSignalSemaphores }; beginCommandBuffer(vkd, *resetCmdBuffer); vkd.cmdResetQueryPool(*resetCmdBuffer, *queryPool1, 0u, 1u); vkd.cmdResetQueryPool(*resetCmdBuffer, *queryPool2, 0u, 1u); endCommandBuffer(vkd, *resetCmdBuffer); VK_CHECK(vkd.queueSubmit(queue, 1u, &submitInfo, *fence)); VK_CHECK(vkd.waitForFences(device, 1u, &fence.get(), DE_TRUE, ~0ull)); } // begin command buffer beginCommandBuffer(vkd, *cmdBuffer, 0u); initialTransitionColor2DImage(vkd, *cmdBuffer, m_colorAttachmentImage->object(), VK_IMAGE_LAYOUT_GENERAL, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT); // begin render pass VkClearValue renderPassClearValue; deMemset(&renderPassClearValue, 0, sizeof(VkClearValue)); VkBuffer vertexBuffer = m_vertexBuffer->object(); const VkDeviceSize vertexBufferOffset = 0; const VkQueryPool queryPools[] = { *queryPool1, *queryPool2 }; // perform two queries during triangle draw for (deUint32 loop = 0; loop < DE_LENGTH_OF_ARRAY(queryPools); ++loop) { const VkQueryPool queryPool = queryPools[loop]; vkd.cmdBeginQuery(*cmdBuffer, queryPool, 0u, (VkQueryControlFlags)0u); beginRenderPass(vkd, *cmdBuffer, *m_renderPass, *m_framebuffer, makeRect2D(0, 0, m_size, m_size), 1, &renderPassClearValue); vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline); vkd.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset); vkd.cmdDraw(*cmdBuffer, 3, 1, 0, 0); endRenderPass(vkd, *cmdBuffer); vkd.cmdEndQuery(*cmdBuffer, queryPool, 0u); } transition2DImage(vkd, *cmdBuffer, m_colorAttachmentImage->object(), VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); endCommandBuffer(vkd, *cmdBuffer); // submit command buffer for each pass and wait for its completion for (deUint32 passIndex = 0; passIndex < getRequiredNumerOfPasses(); passIndex++) { const Unique fence(createFence(vkd, device)); VkPerformanceQuerySubmitInfoKHR performanceQuerySubmitInfo = { VK_STRUCTURE_TYPE_PERFORMANCE_QUERY_SUBMIT_INFO_KHR, NULL, passIndex }; const VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO, // sType &performanceQuerySubmitInfo, // pNext 0u, // waitSemaphoreCount DE_NULL, // pWaitSemaphores (const VkPipelineStageFlags*)DE_NULL, // pWaitDstStageMask 1u, // commandBufferCount &cmdBuffer.get(), // pCommandBuffers 0u, // signalSemaphoreCount DE_NULL, // pSignalSemaphores }; VK_CHECK(vkd.queueSubmit(queue, 1u, &submitInfo, *fence)); VK_CHECK(vkd.waitForFences(device, 1u, &fence.get(), DE_TRUE, ~0ull)); } releaseProfilingLock(); VK_CHECK(vkd.resetCommandBuffer(*cmdBuffer, 0)); if (verifyQueryResults(*queryPool1) && verifyQueryResults(*queryPool2)) return tcu::TestStatus::pass("Pass"); return tcu::TestStatus::fail("Fail"); } // Base class for all compute tests class ComputeQueryTestBase : public QueryTestBase { public: ComputeQueryTestBase(vkt::Context& context); protected: void initStateObjects(void); protected: Move m_pipeline; Move m_pipelineLayout; de::SharedPtr m_buffer; Move m_descriptorPool; Move m_descriptorSet; VkDescriptorBufferInfo m_descriptorBufferInfo; VkBufferMemoryBarrier m_computeFinishBarrier; }; ComputeQueryTestBase::ComputeQueryTestBase(vkt::Context& context) : QueryTestBase(context) { } void ComputeQueryTestBase::initStateObjects(void) { const DeviceInterface& vkd = m_context.getDeviceInterface(); const VkDevice device = m_context.getDevice(); const VkDeviceSize bufferSize = 32 * sizeof(deUint32); const CmdPoolCreateInfo cmdPoolCreateInfo(m_context.getUniversalQueueFamilyIndex()); const Unique cmdPool(createCommandPool(vkd, device, &cmdPoolCreateInfo)); const Unique cmdBuffer(allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY)); const Unique descriptorSetLayout(DescriptorSetLayoutBuilder() .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT) .build(vkd, device)); // create pipeline layout { const VkPipelineLayoutCreateInfo pipelineLayoutParams = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // sType DE_NULL, // pNext 0u, // flags 1u, // setLayoutCount &(*descriptorSetLayout), // pSetLayouts 0u, // pushConstantRangeCount DE_NULL, // pPushConstantRanges }; m_pipelineLayout = createPipelineLayout(vkd, device, &pipelineLayoutParams); } // create compute pipeline { const Unique cs(createShaderModule(vkd, device, m_context.getBinaryCollection().get("comp"), 0u)); const VkPipelineShaderStageCreateInfo pipelineShaderStageParams = { VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // sType DE_NULL, // pNext (VkPipelineShaderStageCreateFlags)0u, // flags VK_SHADER_STAGE_COMPUTE_BIT, // stage *cs, // module "main", // pName DE_NULL, // pSpecializationInfo }; const VkComputePipelineCreateInfo pipelineCreateInfo = { VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // sType DE_NULL, // pNext (VkPipelineCreateFlags)0u, // flags pipelineShaderStageParams, // stage *m_pipelineLayout, // layout DE_NULL, // basePipelineHandle 0, // basePipelineIndex }; m_pipeline = createComputePipeline(vkd, device, DE_NULL, &pipelineCreateInfo); } m_buffer = Buffer::createAndAlloc(vkd, device, BufferCreateInfo(bufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), m_context.getDefaultAllocator(), MemoryRequirement::HostVisible); m_descriptorPool = DescriptorPoolBuilder() .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) .build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u); const VkDescriptorSetAllocateInfo allocateParams = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // sType DE_NULL, // pNext *m_descriptorPool, // descriptorPool 1u, // setLayoutCount &(*descriptorSetLayout), // pSetLayouts }; m_descriptorSet = allocateDescriptorSet(vkd, device, &allocateParams); const VkDescriptorBufferInfo descriptorInfo = { m_buffer->object(), // buffer 0ull, // offset bufferSize, // range }; DescriptorSetUpdateBuilder() .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorInfo) .update(vkd, device); // clear buffer const std::vector data((size_t)bufferSize, 0u); const Allocation& allocation = m_buffer->getBoundMemory(); void* allocationData = allocation.getHostPtr(); invalidateAlloc(vkd, device, allocation); deMemcpy(allocationData, &data[0], (size_t)bufferSize); const VkBufferMemoryBarrier barrier = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // sType DE_NULL, // pNext VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, // srcAccessMask VK_ACCESS_HOST_READ_BIT, // dstAccessMask VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex m_buffer->object(), // buffer 0ull, // offset bufferSize, // size }; m_computeFinishBarrier = barrier; } class ComputeQueryTest : public ComputeQueryTestBase { public: ComputeQueryTest (vkt::Context& context); tcu::TestStatus iterate (void); }; ComputeQueryTest::ComputeQueryTest(vkt::Context& context) : ComputeQueryTestBase(context) { } tcu::TestStatus ComputeQueryTest::iterate(void) { const DeviceInterface& vkd = m_context.getDeviceInterface(); const VkDevice device = m_context.getDevice(); const VkQueue queue = m_context.getUniversalQueue(); const CmdPoolCreateInfo cmdPoolCreateInfo (m_context.getUniversalQueueFamilyIndex()); const Unique cmdPool (createCommandPool(vkd, device, &cmdPoolCreateInfo)); const Unique resetCmdBuffer (allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY)); const Unique cmdBuffer (allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY)); initStateObjects(); setupCounters(); vk::Unique queryPool(createQueryPool(0, 1)); if (!acquireProfilingLock()) { // lock was not acquired in given time, we can't fail the test return tcu::TestStatus::pass("Pass"); } beginCommandBuffer(vkd, *resetCmdBuffer); vkd.cmdResetQueryPool(*resetCmdBuffer, *queryPool, 0u, 1u); endCommandBuffer(vkd, *resetCmdBuffer); beginCommandBuffer(vkd, *cmdBuffer, 0u); vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipeline); vkd.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipelineLayout, 0u, 1u, &(m_descriptorSet.get()), 0u, DE_NULL); vkd.cmdBeginQuery(*cmdBuffer, *queryPool, 0u, (VkQueryControlFlags)0u); vkd.cmdDispatch(*cmdBuffer, 2, 2, 2); vkd.cmdEndQuery(*cmdBuffer, *queryPool, 0u); vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0u, 0u, (const VkMemoryBarrier*)DE_NULL, 1u, &m_computeFinishBarrier, 0u, (const VkImageMemoryBarrier*)DE_NULL); endCommandBuffer(vkd, *cmdBuffer); // submit reset of queries only once { const VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO, // sType DE_NULL, // pNext 0u, // waitSemaphoreCount DE_NULL, // pWaitSemaphores (const VkPipelineStageFlags*)DE_NULL, // pWaitDstStageMask 1u, // commandBufferCount &resetCmdBuffer.get(), // pCommandBuffers 0u, // signalSemaphoreCount DE_NULL, // pSignalSemaphores }; VK_CHECK(vkd.queueSubmit(queue, 1u, &submitInfo, DE_NULL)); } // submit command buffer for each pass and wait for its completion for (deUint32 passIndex = 0; passIndex < getRequiredNumerOfPasses(); passIndex++) { const Unique fence(createFence(vkd, device)); VkPerformanceQuerySubmitInfoKHR performanceQuerySubmitInfo = { VK_STRUCTURE_TYPE_PERFORMANCE_QUERY_SUBMIT_INFO_KHR, NULL, passIndex }; const VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO, // sType &performanceQuerySubmitInfo, // pNext 0u, // waitSemaphoreCount DE_NULL, // pWaitSemaphores (const VkPipelineStageFlags*)DE_NULL, // pWaitDstStageMask 1u, // commandBufferCount &cmdBuffer.get(), // pCommandBuffers 0u, // signalSemaphoreCount DE_NULL, // pSignalSemaphores }; VK_CHECK(vkd.queueSubmit(queue, 1u, &submitInfo, *fence)); VK_CHECK(vkd.waitForFences(device, 1u, &fence.get(), DE_TRUE, ~0ull)); } releaseProfilingLock(); VK_CHECK(vkd.resetCommandBuffer(*cmdBuffer, 0)); if (verifyQueryResults(*queryPool)) return tcu::TestStatus::pass("Pass"); return tcu::TestStatus::fail("Fail"); } class ComputeMultiplePoolsTest : public ComputeQueryTestBase { public: ComputeMultiplePoolsTest (vkt::Context& context); tcu::TestStatus iterate (void); }; ComputeMultiplePoolsTest::ComputeMultiplePoolsTest(vkt::Context& context) : ComputeQueryTestBase(context) { } tcu::TestStatus ComputeMultiplePoolsTest::iterate(void) { if (!m_context.getPerformanceQueryFeatures().performanceCounterMultipleQueryPools) throw tcu::NotSupportedError("MultipleQueryPools not supported"); const DeviceInterface& vkd = m_context.getDeviceInterface(); const VkDevice device = m_context.getDevice(); const VkQueue queue = m_context.getUniversalQueue(); const CmdPoolCreateInfo cmdPoolCreateInfo(m_context.getUniversalQueueFamilyIndex()); const Unique cmdPool(createCommandPool(vkd, device, &cmdPoolCreateInfo)); const Unique resetCmdBuffer(allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY)); const Unique cmdBuffer(allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY)); initStateObjects(); setupCounters(); vk::Unique queryPool1(createQueryPool(0, 2)), queryPool2(createQueryPool(1, 2)); if (!acquireProfilingLock()) { // lock was not acquired in given time, we can't fail the test return tcu::TestStatus::pass("Pass"); } const VkQueryPool queryPools[] = { *queryPool1, *queryPool2 }; beginCommandBuffer(vkd, *resetCmdBuffer); vkd.cmdResetQueryPool(*resetCmdBuffer, queryPools[0], 0u, 1u); vkd.cmdResetQueryPool(*resetCmdBuffer, queryPools[1], 0u, 1u); endCommandBuffer(vkd, *resetCmdBuffer); beginCommandBuffer(vkd, *cmdBuffer, 0u); vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipeline); vkd.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipelineLayout, 0u, 1u, &(m_descriptorSet.get()), 0u, DE_NULL); // perform two queries for (deUint32 loop = 0; loop < DE_LENGTH_OF_ARRAY(queryPools); ++loop) { const VkQueryPool queryPool = queryPools[loop]; vkd.cmdBeginQuery(*cmdBuffer, queryPool, 0u, (VkQueryControlFlags)0u); vkd.cmdDispatch(*cmdBuffer, 2, 2, 2); vkd.cmdEndQuery(*cmdBuffer, queryPool, 0u); } vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0u, 0u, (const VkMemoryBarrier*)DE_NULL, 1u, &m_computeFinishBarrier, 0u, (const VkImageMemoryBarrier*)DE_NULL); endCommandBuffer(vkd, *cmdBuffer); // submit reset of queries only once { const VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO, // sType DE_NULL, // pNext 0u, // waitSemaphoreCount DE_NULL, // pWaitSemaphores (const VkPipelineStageFlags*)DE_NULL, // pWaitDstStageMask 1u, // commandBufferCount &resetCmdBuffer.get(), // pCommandBuffers 0u, // signalSemaphoreCount DE_NULL, // pSignalSemaphores }; VK_CHECK(vkd.queueSubmit(queue, 1u, &submitInfo, DE_NULL)); } // submit command buffer for each pass and wait for its completion for (deUint32 passIndex = 0; passIndex < getRequiredNumerOfPasses(); passIndex++) { const Unique fence(createFence(vkd, device)); VkPerformanceQuerySubmitInfoKHR performanceQuerySubmitInfo = { VK_STRUCTURE_TYPE_PERFORMANCE_QUERY_SUBMIT_INFO_KHR, NULL, passIndex }; const VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO, // sType &performanceQuerySubmitInfo, // pNext 0u, // waitSemaphoreCount DE_NULL, // pWaitSemaphores (const VkPipelineStageFlags*)DE_NULL, // pWaitDstStageMask 1u, // commandBufferCount &cmdBuffer.get(), // pCommandBuffers 0u, // signalSemaphoreCount DE_NULL, // pSignalSemaphores }; VK_CHECK(vkd.queueSubmit(queue, 1u, &submitInfo, *fence)); VK_CHECK(vkd.waitForFences(device, 1u, &fence.get(), DE_TRUE, ~0ull)); } releaseProfilingLock(); VK_CHECK(vkd.resetCommandBuffer(*cmdBuffer, 0)); if (verifyQueryResults(*queryPool1) && verifyQueryResults(*queryPool2)) return tcu::TestStatus::pass("Pass"); return tcu::TestStatus::fail("Fail"); } enum TestType { TT_ENUMERATE_AND_VALIDATE = 0, TT_QUERY, TT_MULTIPLE_POOLS }; class QueryPoolPerformanceTest : public TestCase { public: QueryPoolPerformanceTest (tcu::TestContext &context, TestType testType, VkQueueFlagBits queueFlagBits, const char *name) : TestCase (context, name) , m_testType (testType) , m_queueFlagBits (queueFlagBits) { } vkt::TestInstance* createInstance (vkt::Context& context) const { if (m_testType == TT_ENUMERATE_AND_VALIDATE) return new EnumerateAndValidateTest(context, m_queueFlagBits); if (m_queueFlagBits == VK_QUEUE_GRAPHICS_BIT) { if (m_testType == TT_QUERY) return new GraphicQueryTest(context); return new GraphicMultiplePoolsTest(context); } // tests for VK_QUEUE_COMPUTE_BIT if (m_testType == TT_QUERY) return new ComputeQueryTest(context); return new ComputeMultiplePoolsTest(context); } void initPrograms (SourceCollections& programCollection) const { // validation test do not need programs if (m_testType == TT_ENUMERATE_AND_VALIDATE) return; if (m_queueFlagBits == VK_QUEUE_COMPUTE_BIT) { programCollection.glslSources.add("comp") << glu::ComputeSource("#version 430\n" "layout (local_size_x = 1) in;\n" "layout(binding = 0) writeonly buffer Output {\n" " uint values[];\n" "} sb_out;\n\n" "void main (void) {\n" " uint index = uint(gl_GlobalInvocationID.x);\n" " sb_out.values[index] += gl_GlobalInvocationID.y*2;\n" "}\n"); return; } programCollection.glslSources.add("frag") << glu::FragmentSource("#version 430\n" "layout(location = 0) out vec4 out_FragColor;\n" "void main()\n" "{\n" " out_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n" "}\n"); programCollection.glslSources.add("vert") << glu::VertexSource("#version 430\n" "layout(location = 0) in vec4 in_Position;\n" "out gl_PerVertex { vec4 gl_Position; float gl_PointSize; };\n" "void main() {\n" " gl_Position = in_Position;\n" " gl_PointSize = 1.0;\n" "}\n"); } private: TestType m_testType; VkQueueFlagBits m_queueFlagBits; }; } //anonymous QueryPoolPerformanceTests::QueryPoolPerformanceTests (tcu::TestContext &testCtx) : TestCaseGroup(testCtx, "performance_query") { } void QueryPoolPerformanceTests::init (void) { addChild(new QueryPoolPerformanceTest(m_testCtx, TT_ENUMERATE_AND_VALIDATE, VK_QUEUE_GRAPHICS_BIT, "enumerate_and_validate_graphic")); addChild(new QueryPoolPerformanceTest(m_testCtx, TT_ENUMERATE_AND_VALIDATE, VK_QUEUE_COMPUTE_BIT, "enumerate_and_validate_compute")); addChild(new QueryPoolPerformanceTest(m_testCtx, TT_QUERY, VK_QUEUE_GRAPHICS_BIT, "query_graphic")); addChild(new QueryPoolPerformanceTest(m_testCtx, TT_QUERY, VK_QUEUE_COMPUTE_BIT, "query_compute")); addChild(new QueryPoolPerformanceTest(m_testCtx, TT_MULTIPLE_POOLS, VK_QUEUE_GRAPHICS_BIT, "multiple_pools_graphic")); addChild(new QueryPoolPerformanceTest(m_testCtx, TT_MULTIPLE_POOLS, VK_QUEUE_COMPUTE_BIT, "multiple_pools_compute")); } } //QueryPool } //vkt