• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 The Khronos Group Inc.
6  * Copyright (c) 2015 ARM Ltd.
7  * Copyright (c) 2023 LunarG, Inc.
8  * Copyright (c) 2023 Nintendo
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  *      http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  *
22  *//*!
23  * \file
24  * \brief Timestamp Tests
25  *//*--------------------------------------------------------------------*/
26 
27 #include "vktPipelineTimestampTests.hpp"
28 #include "vktPipelineClearUtil.hpp"
29 #include "vktPipelineImageUtil.hpp"
30 #include "vktPipelineVertexUtil.hpp"
31 #include "vktPipelineReferenceRenderer.hpp"
32 #include "vktCustomInstancesDevices.hpp"
33 #include "vktTestCaseUtil.hpp"
34 #include "vkSafetyCriticalUtil.hpp"
35 #include "vkImageUtil.hpp"
36 #include "vkMemUtil.hpp"
37 #include "vkPrograms.hpp"
38 #include "vkBuilderUtil.hpp"
39 #include "vkQueryUtil.hpp"
40 #include "vkRef.hpp"
41 #include "vkRefUtil.hpp"
42 #include "vkTypeUtil.hpp"
43 #include "vkCmdUtil.hpp"
44 #include "vkObjUtil.hpp"
45 #include "vkDeviceUtil.hpp"
46 #include "tcuImageCompare.hpp"
47 #include "tcuCommandLine.hpp"
48 #include "deUniquePtr.hpp"
49 #include "deStringUtil.hpp"
50 #include "deMemory.h"
51 
52 #include <sstream>
53 #include <vector>
54 #include <set>
55 #include <cctype>
56 #include <locale>
57 #include <limits>
58 #include <thread>
59 #include <chrono>
60 #include <time.h>
61 #include <algorithm>
62 
63 #ifdef CTS_USES_VULKANSC
64 // VulkanSC supports VK_EXT_calibrated_timestamps but not VK_KHR_calibrated_timestamps
65 #define VkCalibratedTimestampInfoKHR VkCalibratedTimestampInfoEXT
66 #define VkTimeDomainKHR VkTimeDomainEXT
67 #endif // CTS_USES_VULKANSC
68 
69 #if (DE_OS == DE_OS_WIN32)
70 #define VC_EXTRALEAN
71 #define WIN32_LEAN_AND_MEAN
72 #define NOMINMAX
73 #include <windows.h>
74 #endif
75 
76 namespace vkt
77 {
78 namespace pipeline
79 {
80 
81 using namespace vk;
82 
83 namespace
84 {
85 typedef std::vector<VkPipelineStageFlagBits> StageFlagVector;
86 
87 // helper functions
88 #define GEN_DESC_STRING(name, postfix)                                   \
89     do                                                                   \
90     {                                                                    \
91         for (std::string::size_type ndx = 0; ndx < strlen(#name); ++ndx) \
92             if (isDescription && #name[ndx] == '_')                      \
93                 desc << " ";                                             \
94             else                                                         \
95                 desc << std::tolower(#name[ndx], loc);                   \
96         if (isDescription)                                               \
97             desc << " " << #postfix;                                     \
98         else                                                             \
99             desc << "_" << #postfix;                                     \
100     } while (false)
101 
getPipelineStageFlagStr(const VkPipelineStageFlagBits stage,bool isDescription)102 std::string getPipelineStageFlagStr(const VkPipelineStageFlagBits stage, bool isDescription)
103 {
104     std::ostringstream desc;
105     std::locale loc;
106     switch (stage)
107     {
108 #define STAGE_CASE(p)                 \
109     case VK_PIPELINE_STAGE_##p##_BIT: \
110     {                                 \
111         GEN_DESC_STRING(p, stage);    \
112         break;                        \
113     }
114         STAGE_CASE(TOP_OF_PIPE)
115         STAGE_CASE(DRAW_INDIRECT)
116         STAGE_CASE(VERTEX_INPUT)
117         STAGE_CASE(VERTEX_SHADER)
118         STAGE_CASE(TESSELLATION_CONTROL_SHADER)
119         STAGE_CASE(TESSELLATION_EVALUATION_SHADER)
120         STAGE_CASE(GEOMETRY_SHADER)
121         STAGE_CASE(FRAGMENT_SHADER)
122         STAGE_CASE(EARLY_FRAGMENT_TESTS)
123         STAGE_CASE(LATE_FRAGMENT_TESTS)
124         STAGE_CASE(COLOR_ATTACHMENT_OUTPUT)
125         STAGE_CASE(COMPUTE_SHADER)
126         STAGE_CASE(TRANSFER)
127         STAGE_CASE(HOST)
128         STAGE_CASE(ALL_GRAPHICS)
129         STAGE_CASE(ALL_COMMANDS)
130 #undef STAGE_CASE
131     default:
132         desc << "unknown stage!";
133         DE_FATAL("Unknown Stage!");
134         break;
135     }
136 
137     return desc.str();
138 }
139 
140 enum TransferMethod
141 {
142     TRANSFER_METHOD_COPY_BUFFER = 0,
143     TRANSFER_METHOD_COPY_IMAGE,
144     TRANSFER_METHOD_BLIT_IMAGE,
145     TRANSFER_METHOD_COPY_BUFFER_TO_IMAGE,
146     TRANSFER_METHOD_COPY_IMAGE_TO_BUFFER,
147     TRANSFER_METHOD_UPDATE_BUFFER,
148     TRANSFER_METHOD_FILL_BUFFER,
149     TRANSFER_METHOD_CLEAR_COLOR_IMAGE,
150     TRANSFER_METHOD_CLEAR_DEPTH_STENCIL_IMAGE,
151     TRANSFER_METHOD_RESOLVE_IMAGE,
152     TRANSFER_METHOD_COPY_QUERY_POOL_RESULTS,
153     TRANSFER_METHOD_COPY_QUERY_POOL_RESULTS_STRIDE_ZERO,
154     TRANSFER_METHOD_LAST
155 };
156 
getTransferMethodStr(const TransferMethod method,bool isDescription)157 std::string getTransferMethodStr(const TransferMethod method, bool isDescription)
158 {
159     std::ostringstream desc;
160     std::locale loc;
161 
162     switch (method)
163     {
164 #define METHOD_CASE(p)              \
165     case TRANSFER_METHOD_##p:       \
166     {                               \
167         GEN_DESC_STRING(p, method); \
168         break;                      \
169     }
170         METHOD_CASE(COPY_BUFFER)
171         METHOD_CASE(COPY_IMAGE)
172         METHOD_CASE(BLIT_IMAGE)
173         METHOD_CASE(COPY_BUFFER_TO_IMAGE)
174         METHOD_CASE(COPY_IMAGE_TO_BUFFER)
175         METHOD_CASE(UPDATE_BUFFER)
176         METHOD_CASE(FILL_BUFFER)
177         METHOD_CASE(CLEAR_COLOR_IMAGE)
178         METHOD_CASE(CLEAR_DEPTH_STENCIL_IMAGE)
179         METHOD_CASE(RESOLVE_IMAGE)
180         METHOD_CASE(COPY_QUERY_POOL_RESULTS)
181         METHOD_CASE(COPY_QUERY_POOL_RESULTS_STRIDE_ZERO)
182 #undef METHOD_CASE
183     default:
184         desc << "unknown method!";
185         DE_FATAL("Unknown method!");
186         break;
187     }
188 
189     return desc.str();
190 }
191 
192 constexpr uint32_t MIN_TIMESTAMP_VALID_BITS = 36;
193 constexpr uint32_t MAX_TIMESTAMP_VALID_BITS = 64;
194 
195 // Checks the number of valid bits for the given queue meets the spec requirements.
checkValidBits(uint32_t validBits,uint32_t queueFamilyIndex)196 void checkValidBits(uint32_t validBits, uint32_t queueFamilyIndex)
197 {
198     if (validBits < MIN_TIMESTAMP_VALID_BITS || validBits > MAX_TIMESTAMP_VALID_BITS)
199     {
200         std::ostringstream msg;
201         msg << "Invalid value for timestampValidBits (" << validBits << ") in queue index " << queueFamilyIndex;
202         TCU_FAIL(msg.str());
203     }
204 }
205 
206 // Returns the timestamp mask given the number of valid timestamp bits.
timestampMaskFromValidBits(uint32_t validBits)207 uint64_t timestampMaskFromValidBits(uint32_t validBits)
208 {
209     return ((validBits == MAX_TIMESTAMP_VALID_BITS) ? std::numeric_limits<uint64_t>::max() : ((1ULL << validBits) - 1));
210 }
211 
212 // Checks support for timestamps and returns the timestamp mask.
checkTimestampsSupported(const InstanceInterface & vki,const VkPhysicalDevice physDevice,const uint32_t queueFamilyIndex)213 uint64_t checkTimestampsSupported(const InstanceInterface &vki, const VkPhysicalDevice physDevice,
214                                   const uint32_t queueFamilyIndex)
215 {
216     const std::vector<VkQueueFamilyProperties> queueProperties =
217         vk::getPhysicalDeviceQueueFamilyProperties(vki, physDevice);
218     DE_ASSERT(queueFamilyIndex < queueProperties.size());
219     const uint32_t &validBits = queueProperties[queueFamilyIndex].timestampValidBits;
220 
221     if (validBits == 0)
222         throw tcu::NotSupportedError("Queue does not support timestamps");
223 
224     checkValidBits(validBits, queueFamilyIndex);
225     return timestampMaskFromValidBits(validBits);
226 }
227 
checkTimestampBits(uint64_t timestamp,uint64_t mask)228 void checkTimestampBits(uint64_t timestamp, uint64_t mask)
229 {
230     // The spec says:
231     // timestampValidBits is the unsigned integer count of meaningful bits in
232     // the timestamps written via vkCmdWriteTimestamp. The valid range for the
233     // count is 36..64 bits, or a value of 0, indicating no support for
234     // timestamps. Bits outside the valid range are guaranteed to be zeros.
235     if (timestamp > mask)
236     {
237         std::ostringstream msg;
238         msg << std::hex << "Invalid device timestamp value 0x" << timestamp << " according to device timestamp mask 0x"
239             << mask;
240         TCU_FAIL(msg.str());
241     }
242 }
243 
244 // helper classes
245 class TimestampTestParam
246 {
247 public:
248     TimestampTestParam(const PipelineConstructionType pipelineConstructionType, const VkPipelineStageFlagBits *stages,
249                        const uint32_t stageCount, const bool inRenderPass, const bool hostQueryReset,
250                        const bool transferOnlyQueue, const VkQueryResultFlags queryResultFlags);
251     virtual ~TimestampTestParam(void);
252     virtual const std::string generateTestName(void) const;
getPipelineConstructionType(void) const253     PipelineConstructionType getPipelineConstructionType(void) const
254     {
255         return m_pipelineConstructionType;
256     }
getStageVector(void) const257     StageFlagVector getStageVector(void) const
258     {
259         return m_stageVec;
260     }
getInRenderPass(void) const261     bool getInRenderPass(void) const
262     {
263         return m_inRenderPass;
264     }
getHostQueryReset(void) const265     bool getHostQueryReset(void) const
266     {
267         return m_hostQueryReset;
268     }
getTransferOnlyQueue(void) const269     bool getTransferOnlyQueue(void) const
270     {
271         return m_transferOnlyQueue;
272     }
getQueryResultFlags(void) const273     VkQueryResultFlags getQueryResultFlags(void) const
274     {
275         return m_queryResultFlags;
276     }
toggleInRenderPass(void)277     void toggleInRenderPass(void)
278     {
279         m_inRenderPass = !m_inRenderPass;
280     }
toggleHostQueryReset(void)281     void toggleHostQueryReset(void)
282     {
283         m_hostQueryReset = !m_hostQueryReset;
284     }
285 
setQueryResultFlags(VkQueryResultFlags flags)286     void setQueryResultFlags(VkQueryResultFlags flags)
287     {
288         m_queryResultFlags = flags;
289     }
290 
291 protected:
292     const PipelineConstructionType m_pipelineConstructionType;
293     StageFlagVector m_stageVec;
294     bool m_inRenderPass;
295     bool m_hostQueryReset;
296     bool m_transferOnlyQueue;
297     VkQueryResultFlags m_queryResultFlags;
298 };
299 
TimestampTestParam(const PipelineConstructionType pipelineConstructionType,const VkPipelineStageFlagBits * stages,const uint32_t stageCount,const bool inRenderPass,const bool hostQueryReset,const bool transferOnlyQueue,const VkQueryResultFlags queryResultFlags)300 TimestampTestParam::TimestampTestParam(const PipelineConstructionType pipelineConstructionType,
301                                        const VkPipelineStageFlagBits *stages, const uint32_t stageCount,
302                                        const bool inRenderPass, const bool hostQueryReset, const bool transferOnlyQueue,
303                                        const VkQueryResultFlags queryResultFlags)
304     : m_pipelineConstructionType(pipelineConstructionType)
305     , m_inRenderPass(inRenderPass)
306     , m_hostQueryReset(hostQueryReset)
307     , m_transferOnlyQueue(transferOnlyQueue)
308     , m_queryResultFlags(queryResultFlags)
309 {
310     for (uint32_t ndx = 0; ndx < stageCount; ndx++)
311     {
312         m_stageVec.push_back(stages[ndx]);
313     }
314 }
315 
~TimestampTestParam(void)316 TimestampTestParam::~TimestampTestParam(void)
317 {
318 }
319 
generateTestName(void) const320 const std::string TimestampTestParam::generateTestName(void) const
321 {
322     std::string result("");
323 
324     for (StageFlagVector::const_iterator it = m_stageVec.begin(); it != m_stageVec.end(); it++)
325     {
326         if (*it != VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT)
327         {
328             result += getPipelineStageFlagStr(*it, false) + '_';
329         }
330     }
331     if (m_inRenderPass)
332         result += "in_render_pass";
333     else
334         result += "out_of_render_pass";
335 
336     if (m_hostQueryReset)
337         result += "_host_query_reset";
338 
339     if (m_transferOnlyQueue)
340         result += "_transfer_queue";
341 
342     if (m_queryResultFlags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT)
343         result += "_with_availability_bit";
344 
345     return result;
346 }
347 
348 class TransferTimestampTestParam : public TimestampTestParam
349 {
350 public:
351     TransferTimestampTestParam(const PipelineConstructionType pipelineConstructionType,
352                                const VkPipelineStageFlagBits *stages, const uint32_t stageCount,
353                                const bool inRenderPass, const bool hostQueryReset, const bool transferOnlyQueue,
354                                const uint32_t methodNdx, const VkQueryResultFlags flags);
~TransferTimestampTestParam(void)355     ~TransferTimestampTestParam(void)
356     {
357     }
358     const std::string generateTestName(void) const;
359     const std::string generateTestDescription(void) const;
getMethod(void) const360     TransferMethod getMethod(void) const
361     {
362         return m_method;
363     }
364 
365 protected:
366     TransferMethod m_method;
367 };
368 
TransferTimestampTestParam(const PipelineConstructionType pipelineConstructionType,const VkPipelineStageFlagBits * stages,const uint32_t stageCount,const bool inRenderPass,const bool hostQueryReset,const bool transferOnlyQueue,const uint32_t methodNdx,const VkQueryResultFlags flags)369 TransferTimestampTestParam::TransferTimestampTestParam(const PipelineConstructionType pipelineConstructionType,
370                                                        const VkPipelineStageFlagBits *stages, const uint32_t stageCount,
371                                                        const bool inRenderPass, const bool hostQueryReset,
372                                                        const bool transferOnlyQueue, const uint32_t methodNdx,
373                                                        const VkQueryResultFlags flags)
374     : TimestampTestParam(pipelineConstructionType, stages, stageCount, inRenderPass, hostQueryReset, transferOnlyQueue,
375                          flags)
376 {
377     DE_ASSERT(methodNdx < (uint32_t)TRANSFER_METHOD_LAST);
378 
379     m_method = (TransferMethod)methodNdx;
380 }
381 
generateTestName(void) const382 const std::string TransferTimestampTestParam::generateTestName(void) const
383 {
384     std::string result("");
385 
386     for (StageFlagVector::const_iterator it = m_stageVec.begin(); it != m_stageVec.end(); it++)
387     {
388         if (*it != VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT)
389         {
390             result += getPipelineStageFlagStr(*it, false) + '_';
391         }
392     }
393 
394     result += "with_" + getTransferMethodStr(m_method, false);
395 
396     if (m_hostQueryReset)
397         result += "_host_query_reset";
398 
399     if (m_transferOnlyQueue)
400         result += "_transfer_queue";
401 
402     if (m_queryResultFlags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT)
403         result += "_with_availability_bit";
404 
405     return result;
406 }
407 
408 class TwoCmdBuffersTestParam : public TimestampTestParam
409 {
410 public:
411     TwoCmdBuffersTestParam(const PipelineConstructionType pipelineConstructionType,
412                            const VkPipelineStageFlagBits *stages, const uint32_t stageCount, const bool inRenderPass,
413                            const bool hostQueryReset, const bool transferOnlyQueue,
414                            const VkCommandBufferLevel cmdBufferLevel, const VkQueryResultFlags queryPoolResultFlags);
~TwoCmdBuffersTestParam(void)415     ~TwoCmdBuffersTestParam(void)
416     {
417     }
getCmdBufferLevel(void) const418     VkCommandBufferLevel getCmdBufferLevel(void) const
419     {
420         return m_cmdBufferLevel;
421     }
422 
423 protected:
424     VkCommandBufferLevel m_cmdBufferLevel;
425 };
426 
TwoCmdBuffersTestParam(const PipelineConstructionType pipelineConstructionType,const VkPipelineStageFlagBits * stages,const uint32_t stageCount,const bool inRenderPass,const bool hostQueryReset,const bool transferOnlyQueue,const VkCommandBufferLevel cmdBufferLevel,const VkQueryResultFlags queryPoolResultFlags)427 TwoCmdBuffersTestParam::TwoCmdBuffersTestParam(const PipelineConstructionType pipelineConstructionType,
428                                                const VkPipelineStageFlagBits *stages, const uint32_t stageCount,
429                                                const bool inRenderPass, const bool hostQueryReset,
430                                                const bool transferOnlyQueue, const VkCommandBufferLevel cmdBufferLevel,
431                                                const VkQueryResultFlags queryPoolResultFlags)
432     : TimestampTestParam(pipelineConstructionType, stages, stageCount, inRenderPass, hostQueryReset, transferOnlyQueue,
433                          queryPoolResultFlags)
434     , m_cmdBufferLevel(cmdBufferLevel)
435 {
436 }
437 
438 template <class Test>
newTestCase(tcu::TestContext & testContext,TimestampTestParam * testParam)439 vkt::TestCase *newTestCase(tcu::TestContext &testContext, TimestampTestParam *testParam)
440 {
441     return new Test(testContext, testParam->generateTestName().c_str(), testParam);
442 }
443 
444 // Test Classes
445 class TimestampTest : public vkt::TestCase
446 {
447 public:
448     enum
449     {
450         ENTRY_COUNT = 8
451     };
452 
TimestampTest(tcu::TestContext & testContext,const std::string & name,const TimestampTestParam * param)453     TimestampTest(tcu::TestContext &testContext, const std::string &name, const TimestampTestParam *param)
454         : vkt::TestCase(testContext, name)
455         , m_pipelineConstructionType(param->getPipelineConstructionType())
456         , m_stages(param->getStageVector())
457         , m_inRenderPass(param->getInRenderPass())
458         , m_hostQueryReset(param->getHostQueryReset())
459         , m_transferOnlyQueue(param->getTransferOnlyQueue())
460         , m_queryResultFlags(param->getQueryResultFlags())
461     {
462     }
~TimestampTest(void)463     virtual ~TimestampTest(void)
464     {
465     }
466     virtual void initPrograms(SourceCollections &programCollection) const;
467     virtual TestInstance *createInstance(Context &context) const;
468     virtual void checkSupport(Context &context) const;
469 
470 protected:
471     const PipelineConstructionType m_pipelineConstructionType;
472     const StageFlagVector m_stages;
473     const bool m_inRenderPass;
474     const bool m_hostQueryReset;
475     const bool m_transferOnlyQueue;
476     const VkQueryResultFlags m_queryResultFlags;
477 };
478 
479 class TimestampTestInstance : public vkt::TestInstance
480 {
481 public:
482     TimestampTestInstance(Context &context, const StageFlagVector &stages, const bool inRenderPass,
483                           const bool hostQueryReset, const bool transferOnlyQueue,
484                           const VkQueryResultFlags queryResultFlags);
485 
486     virtual ~TimestampTestInstance(void);
487     virtual tcu::TestStatus iterate(void);
488 
489 protected:
490     virtual tcu::TestStatus verifyTimestamp(void);
491     virtual void buildPipeline(void);
492     virtual void configCommandBuffer(void);
493 
494     Move<VkBuffer> createBufferAndBindMemory(VkDeviceSize size, VkBufferUsageFlags usage,
495                                              de::MovePtr<Allocation> *pAlloc);
496 
497     Move<VkImage> createImage2DAndBindMemory(VkFormat format, uint32_t width, uint32_t height, VkImageUsageFlags usage,
498                                              VkSampleCountFlagBits sampleCount, de::MovePtr<Allocation> *pAlloc);
499 
500     // Creates a device that has transfer only operations
501     void createCustomDeviceWithTransferOnlyQueue(void);
502 
503 protected:
504     Move<VkDevice> m_customDevice;
505     de::MovePtr<Allocator> m_customAllocator;
506 
507     VkDevice m_device;
508 #ifdef CTS_USES_VULKANSC
509     const CustomInstance m_customInstance;
510 #endif // CTS_USES_VULKANSC
511     Allocator *m_allocator;
512     uint32_t m_queueFamilyIndex;
513 
514     const StageFlagVector m_stages;
515     bool m_inRenderPass;
516     bool m_hostQueryReset;
517     bool m_transferOnlyQueue;
518     VkQueryResultFlags m_queryResultFlags;
519 
520     Move<VkCommandPool> m_cmdPool;
521     Move<VkCommandBuffer> m_cmdBuffer;
522     Move<VkQueryPool> m_queryPool;
523     uint64_t *m_timestampValues;
524     uint64_t *m_timestampValuesHostQueryReset;
525     uint64_t m_timestampMask;
526 };
527 
initPrograms(SourceCollections & programCollection) const528 void TimestampTest::initPrograms(SourceCollections &programCollection) const
529 {
530     vkt::TestCase::initPrograms(programCollection);
531 }
532 
checkSupport(Context & context) const533 void TimestampTest::checkSupport(Context &context) const
534 {
535     const InstanceInterface &vki          = context.getInstanceInterface();
536     const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
537     uint32_t queueFamilyIndex             = context.getUniversalQueueFamilyIndex();
538 
539     if (m_transferOnlyQueue)
540         queueFamilyIndex = findQueueFamilyIndexWithCaps(vki, physicalDevice, VK_QUEUE_TRANSFER_BIT,
541                                                         VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT);
542 
543     // Check support for timestamp queries
544     const std::vector<VkQueueFamilyProperties> queueProperties =
545         vk::getPhysicalDeviceQueueFamilyProperties(context.getInstanceInterface(), context.getPhysicalDevice());
546     DE_ASSERT(queueFamilyIndex < (uint32_t)queueProperties.size());
547     if (!queueProperties[queueFamilyIndex].timestampValidBits)
548         throw tcu::NotSupportedError("Universal queue does not support timestamps");
549 
550     if (m_hostQueryReset)
551     {
552         // Check VK_EXT_host_query_reset is supported
553         context.requireDeviceFunctionality("VK_EXT_host_query_reset");
554 
555         if (context.getHostQueryResetFeatures().hostQueryReset == VK_FALSE)
556             throw tcu::NotSupportedError("Implementation doesn't support resetting queries from the host");
557     }
558     checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(),
559                                           m_pipelineConstructionType);
560 }
561 
createInstance(Context & context) const562 TestInstance *TimestampTest::createInstance(Context &context) const
563 {
564     return new TimestampTestInstance(context, m_stages, m_inRenderPass, m_hostQueryReset, false, m_queryResultFlags);
565 }
566 
TimestampTestInstance(Context & context,const StageFlagVector & stages,const bool inRenderPass,const bool hostQueryReset,const bool transferOnlyQueue,const VkQueryResultFlags queryResultFlags)567 TimestampTestInstance::TimestampTestInstance(Context &context, const StageFlagVector &stages, const bool inRenderPass,
568                                              const bool hostQueryReset, const bool transferOnlyQueue,
569                                              const VkQueryResultFlags queryResultFlags)
570     : TestInstance(context)
571 #ifdef CTS_USES_VULKANSC
572     , m_customInstance(createCustomInstanceFromContext(context))
573 #endif // CTS_USES_VULKANSC
574     , m_stages(stages)
575     , m_inRenderPass(inRenderPass)
576     , m_hostQueryReset(hostQueryReset)
577     , m_transferOnlyQueue(transferOnlyQueue)
578     , m_queryResultFlags(queryResultFlags)
579 {
580     const DeviceInterface &vk = context.getDeviceInterface();
581 
582     m_device           = context.getDevice();
583     m_allocator        = &context.getDefaultAllocator();
584     m_queueFamilyIndex = context.getUniversalQueueFamilyIndex();
585 
586     // when needed create custom device and overwrite m_device, m_allocator and m_queueFamilyIndex
587     if (m_transferOnlyQueue)
588         createCustomDeviceWithTransferOnlyQueue();
589 
590     m_timestampMask =
591         checkTimestampsSupported(context.getInstanceInterface(), context.getPhysicalDevice(), m_queueFamilyIndex);
592 
593     // Create Query Pool
594     {
595         const VkQueryPoolCreateInfo queryPoolParams = {
596             VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, // VkStructureType               sType;
597             nullptr,                                  // const void*                   pNext;
598             0u,                                       // VkQueryPoolCreateFlags        flags;
599             VK_QUERY_TYPE_TIMESTAMP,                  // VkQueryType                   queryType;
600             TimestampTest::ENTRY_COUNT,               // uint32_t                      entryCount;
601             0u,                                       // VkQueryPipelineStatisticFlags pipelineStatistics;
602         };
603 
604         m_queryPool = createQueryPool(vk, m_device, &queryPoolParams);
605     }
606 
607     // Create command pool
608     m_cmdPool = createCommandPool(vk, m_device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, m_queueFamilyIndex);
609 
610     // Create command buffer
611     m_cmdBuffer = allocateCommandBuffer(vk, m_device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
612 
613     // alloc timestamp values
614     m_timestampValues =
615         new uint64_t[m_stages.size() * ((m_queryResultFlags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT) ? 2u : 1u)];
616 
617     if (m_hostQueryReset)
618         m_timestampValuesHostQueryReset = new uint64_t[m_stages.size() * 2];
619     else
620         m_timestampValuesHostQueryReset = nullptr;
621 }
622 
~TimestampTestInstance(void)623 TimestampTestInstance::~TimestampTestInstance(void)
624 {
625     delete[] m_timestampValues;
626     m_timestampValues = NULL;
627 
628     delete[] m_timestampValuesHostQueryReset;
629     m_timestampValuesHostQueryReset = NULL;
630 }
631 
buildPipeline(void)632 void TimestampTestInstance::buildPipeline(void)
633 {
634 }
635 
configCommandBuffer(void)636 void TimestampTestInstance::configCommandBuffer(void)
637 {
638     const DeviceInterface &vk = m_context.getDeviceInterface();
639 
640     beginCommandBuffer(vk, *m_cmdBuffer, 0u);
641 
642     if (!m_hostQueryReset)
643         vk.cmdResetQueryPool(*m_cmdBuffer, *m_queryPool, 0u, TimestampTest::ENTRY_COUNT);
644 
645     uint32_t timestampEntry = 0;
646     for (const auto &stage : m_stages)
647     {
648         vk.cmdWriteTimestamp(*m_cmdBuffer, stage, *m_queryPool, timestampEntry++);
649     }
650 
651     endCommandBuffer(vk, *m_cmdBuffer);
652 }
653 
iterate(void)654 tcu::TestStatus TimestampTestInstance::iterate(void)
655 {
656     const DeviceInterface &vk    = m_context.getDeviceInterface();
657     const VkQueue queue          = getDeviceQueue(vk, m_device, m_queueFamilyIndex, 0);
658     const bool availabilityBit   = m_queryResultFlags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT;
659     const uint32_t stageSize     = (uint32_t)m_stages.size();
660     const uint32_t queryDataSize = uint32_t(sizeof(uint64_t) * (availabilityBit ? 2u : 1u));
661 
662     buildPipeline();
663     configCommandBuffer();
664     if (m_hostQueryReset)
665     {
666         vk.resetQueryPool(m_device, *m_queryPool, 0u, TimestampTest::ENTRY_COUNT);
667     }
668     submitCommandsAndWait(vk, m_device, queue, m_cmdBuffer.get());
669 
670     // Get timestamp value from query pool
671     VK_CHECK(vk.getQueryPoolResults(m_device, *m_queryPool, 0u, stageSize, queryDataSize * stageSize,
672                                     (void *)m_timestampValues, queryDataSize, m_queryResultFlags));
673 
674     for (uint32_t ndx = 0; ndx < stageSize; ndx++)
675     {
676         m_timestampValues[ndx] &= m_timestampMask;
677         if (availabilityBit)
678             ndx++;
679     }
680 
681     if (m_hostQueryReset)
682     {
683         // Initialize timestampValuesHostQueryReset values
684         deMemset(m_timestampValuesHostQueryReset, 0, sizeof(uint64_t) * stageSize * 2);
685 
686         for (uint32_t ndx = 0; ndx < stageSize; ndx++)
687         {
688             const uint32_t ndxTimestampValue         = ndx * (availabilityBit ? 2u : 1u);
689             m_timestampValuesHostQueryReset[2 * ndx] = m_timestampValues[ndxTimestampValue];
690         }
691 
692         // Host resets the query pool
693         vk.resetQueryPool(m_device, *m_queryPool, 0u, stageSize);
694         // Get timestamp value from query pool
695         vk::VkResult res =
696             vk.getQueryPoolResults(m_device, *m_queryPool, 0u, stageSize, sizeof(uint64_t) * stageSize * 2,
697                                    (void *)m_timestampValuesHostQueryReset, sizeof(uint64_t) * 2,
698                                    VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WITH_AVAILABILITY_BIT);
699 
700         /* From Vulkan spec:
701          *
702          * If VK_QUERY_RESULT_WAIT_BIT and VK_QUERY_RESULT_PARTIAL_BIT are both not set then no result values are written to pData
703          * for queries that are in the unavailable state at the time of the call, and vkGetQueryPoolResults returns VK_NOT_READY.
704          * However, availability state is still written to pData for those queries if VK_QUERY_RESULT_WITH_AVAILABILITY_BIT is set.
705          */
706         if (res != vk::VK_NOT_READY)
707             return tcu::TestStatus::fail("QueryPoolResults incorrect reset");
708 
709         for (uint32_t ndx = 0; ndx < stageSize; ndx++)
710         {
711             const uint32_t ndxTimestampValue = ndx * (availabilityBit ? 2u : 1u);
712             if ((m_timestampValuesHostQueryReset[2 * ndx] & m_timestampMask) != m_timestampValues[ndxTimestampValue])
713                 return tcu::TestStatus::fail("QueryPoolResults returned value was modified");
714             if (m_timestampValuesHostQueryReset[2 * ndx + 1] != 0u)
715                 return tcu::TestStatus::fail("QueryPoolResults availability status is not zero");
716         }
717     }
718 
719     return verifyTimestamp();
720 }
721 
verifyTimestamp(void)722 tcu::TestStatus TimestampTestInstance::verifyTimestamp(void)
723 {
724     bool availabilityBit = m_queryResultFlags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT;
725     uint32_t increment   = availabilityBit ? 2u : 1u;
726     for (uint32_t first = 0u; first < m_stages.size(); first += increment)
727     {
728         for (uint32_t second = 0u; second < first; second += increment)
729         {
730             if (availabilityBit && (m_timestampValues[first + 1u] == 0u || m_timestampValues[second + 1u] == 0u))
731             {
732                 return tcu::TestStatus::fail("Timestamp query not available");
733             }
734 
735             if (m_timestampValues[first] < m_timestampValues[second])
736             {
737                 return tcu::TestStatus::fail("Latter stage timestamp is smaller than the former stage timestamp.");
738             }
739         }
740     }
741 
742     return tcu::TestStatus::pass("Timestamp increases steadily.");
743 }
744 
createBufferAndBindMemory(VkDeviceSize size,VkBufferUsageFlags usage,de::MovePtr<Allocation> * pAlloc)745 Move<VkBuffer> TimestampTestInstance::createBufferAndBindMemory(VkDeviceSize size, VkBufferUsageFlags usage,
746                                                                 de::MovePtr<Allocation> *pAlloc)
747 {
748     const DeviceInterface &vk                   = m_context.getDeviceInterface();
749     const VkBufferCreateInfo vertexBufferParams = {
750         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType      sType;
751         nullptr,                              // const void*          pNext;
752         0u,                                   // VkBufferCreateFlags  flags;
753         size,                                 // VkDeviceSize         size;
754         usage,                                // VkBufferUsageFlags   usage;
755         VK_SHARING_MODE_EXCLUSIVE,            // VkSharingMode        sharingMode;
756         1u,                                   // uint32_t             queueFamilyCount;
757         &m_queueFamilyIndex                   // const uint32_t*      pQueueFamilyIndices;
758     };
759 
760     Move<VkBuffer> vertexBuffer = createBuffer(vk, m_device, &vertexBufferParams);
761     de::MovePtr<Allocation> vertexBufferAlloc =
762         m_allocator->allocate(getBufferMemoryRequirements(vk, m_device, *vertexBuffer), MemoryRequirement::HostVisible);
763 
764     VK_CHECK(
765         vk.bindBufferMemory(m_device, *vertexBuffer, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset()));
766 
767     DE_ASSERT(pAlloc);
768     *pAlloc = vertexBufferAlloc;
769 
770     return vertexBuffer;
771 }
772 
createImage2DAndBindMemory(VkFormat format,uint32_t width,uint32_t height,VkImageUsageFlags usage,VkSampleCountFlagBits sampleCount,de::details::MovePtr<Allocation> * pAlloc)773 Move<VkImage> TimestampTestInstance::createImage2DAndBindMemory(VkFormat format, uint32_t width, uint32_t height,
774                                                                 VkImageUsageFlags usage,
775                                                                 VkSampleCountFlagBits sampleCount,
776                                                                 de::details::MovePtr<Allocation> *pAlloc)
777 {
778     const DeviceInterface &vk = m_context.getDeviceInterface();
779 
780     // Optimal tiling feature check
781     VkFormatProperties formatProperty;
782 
783     m_context.getInstanceInterface().getPhysicalDeviceFormatProperties(m_context.getPhysicalDevice(), format,
784                                                                        &formatProperty);
785 
786     if ((usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) &&
787         !(formatProperty.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT))
788     {
789         // Remove color attachment usage if the optimal tiling feature does not support it
790         usage &= ~VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
791     }
792     if ((usage & VK_IMAGE_USAGE_STORAGE_BIT) &&
793         !(formatProperty.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT))
794     {
795         // Remove storage usage if the optimal tiling feature does not support it
796         usage &= ~VK_IMAGE_USAGE_STORAGE_BIT;
797     }
798 
799     const VkImageCreateInfo colorImageParams = {
800         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType      sType;
801         nullptr,                             // const void*          pNext;
802         0u,                                  // VkImageCreateFlags   flags;
803         VK_IMAGE_TYPE_2D,                    // VkImageType          imageType;
804         format,                              // VkFormat             format;
805         {width, height, 1u},                 // VkExtent3D           extent;
806         1u,                                  // uint32_t             mipLevels;
807         1u,                                  // uint32_t             arraySize;
808         sampleCount,                         // uint32_t             samples;
809         VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling        tiling;
810         usage,                               // VkImageUsageFlags    usage;
811         VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode        sharingMode;
812         1u,                                  // uint32_t             queueFamilyCount;
813         &m_queueFamilyIndex,                 // const uint32_t*      pQueueFamilyIndices;
814         VK_IMAGE_LAYOUT_UNDEFINED,           // VkImageLayout        initialLayout;
815     };
816 
817     Move<VkImage> image = createImage(vk, m_device, &colorImageParams);
818 
819     // Allocate and bind image memory
820     de::MovePtr<Allocation> colorImageAlloc =
821         m_allocator->allocate(getImageMemoryRequirements(vk, m_device, *image), MemoryRequirement::Any);
822     VK_CHECK(vk.bindImageMemory(m_device, *image, colorImageAlloc->getMemory(), colorImageAlloc->getOffset()));
823 
824     DE_ASSERT(pAlloc);
825     *pAlloc = colorImageAlloc;
826 
827     return image;
828 }
829 
createCustomDeviceWithTransferOnlyQueue(void)830 void TimestampTestInstance::createCustomDeviceWithTransferOnlyQueue(void)
831 {
832 #ifdef CTS_USES_VULKANSC
833     vk::VkInstance instance          = m_customInstance;
834     const vk::InstanceInterface &vki = m_customInstance.getDriver();
835     const VkPhysicalDevice physicalDevice =
836         chooseDevice(vki, m_customInstance, m_context.getTestContext().getCommandLine());
837 #else
838     vk::VkInstance instance               = m_context.getInstance();
839     const vk::InstanceInterface &vki      = m_context.getInstanceInterface();
840     const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
841 #endif // CTS_USES_VULKANSC
842 
843     const DeviceInterface &vk = m_context.getDeviceInterface();
844 
845     m_queueFamilyIndex = findQueueFamilyIndexWithCaps(vki, physicalDevice, VK_QUEUE_TRANSFER_BIT,
846                                                       VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT);
847 
848     const std::vector<VkQueueFamilyProperties> queueFamilies =
849         getPhysicalDeviceQueueFamilyProperties(vki, physicalDevice);
850 
851     // This must be found, findQueueFamilyIndexWithCaps would have
852     // thrown a NotSupported exception if the requested queue type did
853     // not exist. Similarly, this was written with the assumption the
854     // "alternative" queue would be different to the universal queue.
855     DE_ASSERT(m_queueFamilyIndex < queueFamilies.size() &&
856               m_queueFamilyIndex != m_context.getUniversalQueueFamilyIndex());
857     const float queuePriority = 1.0f;
858     const VkDeviceQueueCreateInfo deviceQueueCreateInfos{
859         VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType;
860         nullptr,                                    // const void* pNext;
861         (VkDeviceQueueCreateFlags)0u,               // VkDeviceQueueCreateFlags flags;
862         m_queueFamilyIndex,                         // uint32_t queueFamilyIndex;
863         1u,                                         // uint32_t queueCount;
864         &queuePriority,                             // const float* pQueuePriorities;
865     };
866 
867     // Replicate default device extension list.
868     const auto extensionNames = m_context.getDeviceCreationExtensions();
869     auto queryResetFeatures   = m_context.getHostQueryResetFeatures();
870     auto deviceFeatures2      = m_context.getDeviceFeatures2();
871 
872     const void *pNext = &deviceFeatures2;
873     if (m_context.getUsedApiVersion() < VK_API_VERSION_1_2)
874     {
875         queryResetFeatures.pNext = &deviceFeatures2;
876         pNext                    = &queryResetFeatures;
877     }
878 
879 #ifdef CTS_USES_VULKANSC
880     VkDeviceObjectReservationCreateInfo memReservationInfo =
881         m_context.getTestContext().getCommandLine().isSubProcess() ? m_context.getResourceInterface()->getStatMax() :
882                                                                      resetDeviceObjectReservationCreateInfo();
883     memReservationInfo.pNext = pNext;
884     pNext                    = &memReservationInfo;
885 
886     VkPipelineCacheCreateInfo pcCI;
887     std::vector<VkPipelinePoolSize> poolSizes;
888     if (m_context.getTestContext().getCommandLine().isSubProcess())
889     {
890         if (m_context.getResourceInterface()->getCacheDataSize() > 0)
891         {
892             pcCI = {
893                 VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO, // VkStructureType sType;
894                 nullptr,                                      // const void* pNext;
895                 VK_PIPELINE_CACHE_CREATE_READ_ONLY_BIT |
896                     VK_PIPELINE_CACHE_CREATE_USE_APPLICATION_STORAGE_BIT, // VkPipelineCacheCreateFlags flags;
897                 m_context.getResourceInterface()->getCacheDataSize(),     // uintptr_t initialDataSize;
898                 m_context.getResourceInterface()->getCacheData()          // const void* pInitialData;
899             };
900             memReservationInfo.pipelineCacheCreateInfoCount = 1;
901             memReservationInfo.pPipelineCacheCreateInfos    = &pcCI;
902         }
903         poolSizes = m_context.getResourceInterface()->getPipelinePoolSizes();
904         if (!poolSizes.empty())
905         {
906             memReservationInfo.pipelinePoolSizeCount = uint32_t(poolSizes.size());
907             memReservationInfo.pPipelinePoolSizes    = poolSizes.data();
908         }
909     }
910 #endif // CTS_USES_VULKANSC
911 
912     const VkDeviceCreateInfo deviceCreateInfo{
913         VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,         // VkStructureType sType;
914         pNext,                                        // const void* pNext;
915         (VkDeviceCreateFlags)0u,                      // VkDeviceCreateFlags flags;
916         1u,                                           // uint32_t queueCreateInfoCount;
917         &deviceQueueCreateInfos,                      // const VkDeviceQueueCreateInfo* pQueueCreateInfos;
918         0u,                                           // uint32_t enabledLayerCount;
919         nullptr,                                      // const char* const* ppEnabledLayerNames;
920         static_cast<uint32_t>(extensionNames.size()), // uint32_t enabledExtensionCount;
921         extensionNames.data(),                        // const char* const* ppEnabledExtensionNames;
922         nullptr,                                      // const VkPhysicalDeviceFeatures* pEnabledFeatures;
923     };
924 
925     m_customDevice =
926         vkt::createCustomDevice(m_context.getTestContext().getCommandLine().isValidationEnabled(),
927                                 m_context.getPlatformInterface(), instance, vki, physicalDevice, &deviceCreateInfo);
928     m_customAllocator = de::MovePtr<Allocator>(
929         new SimpleAllocator(vk, *m_customDevice, getPhysicalDeviceMemoryProperties(vki, physicalDevice)));
930 
931     m_device    = *m_customDevice;
932     m_allocator = &(*m_customAllocator);
933 }
934 
935 template <class T>
936 class CalibratedTimestampTest : public vkt::TestCase
937 {
938 public:
CalibratedTimestampTest(tcu::TestContext & testContext,const std::string & name)939     CalibratedTimestampTest(tcu::TestContext &testContext, const std::string &name) : vkt::TestCase{testContext, name}
940     {
941     }
942 
~CalibratedTimestampTest(void)943     virtual ~CalibratedTimestampTest(void) override
944     {
945     }
946     virtual void initPrograms(SourceCollections &programCollection) const override;
947     virtual void checkSupport(Context &context) const override;
948     virtual vkt::TestInstance *createInstance(Context &context) const override;
949 };
950 
951 class CalibratedTimestampTestInstance : public vkt::TestInstance
952 {
953 public:
954     CalibratedTimestampTestInstance(Context &context);
~CalibratedTimestampTestInstance(void)955     virtual ~CalibratedTimestampTestInstance(void) override
956     {
957     }
958     virtual tcu::TestStatus iterate(void) override;
959     virtual tcu::TestStatus runTest(void) = 0;
960 
961 protected:
962     struct CalibratedTimestamp
963     {
CalibratedTimestampvkt::pipeline::__anon5e35836c0111::CalibratedTimestampTestInstance::CalibratedTimestamp964         CalibratedTimestamp(uint64_t timestamp_, uint64_t deviation_) : timestamp{timestamp_}, deviation(deviation_)
965         {
966         }
CalibratedTimestampvkt::pipeline::__anon5e35836c0111::CalibratedTimestampTestInstance::CalibratedTimestamp967         CalibratedTimestamp() : timestamp{}, deviation{}
968         {
969         }
970         uint64_t timestamp;
971         uint64_t deviation;
972     };
973 
974     std::vector<VkTimeDomainKHR> getDomainSubset(const std::vector<VkTimeDomainKHR> &available,
975                                                  const std::vector<VkTimeDomainKHR> &interesting) const;
976     std::string domainName(VkTimeDomainKHR domain) const;
977     uint64_t getHostNativeTimestamp(VkTimeDomainKHR hostDomain) const;
978     uint64_t getHostNanoseconds(uint64_t hostTimestamp) const;
979     uint64_t getDeviceNanoseconds(uint64_t devTicksDelta) const;
980     std::vector<CalibratedTimestamp> getCalibratedTimestamps(const std::vector<VkTimeDomainKHR> &domains);
981     CalibratedTimestamp getCalibratedTimestamp(VkTimeDomainKHR domain);
982     void appendQualityMessage(const std::string &message);
983 
984     void verifyDevTimestampMask(uint64_t value) const;
985     uint64_t absDiffWithOverflow(uint64_t a, uint64_t b, uint64_t mask = std::numeric_limits<uint64_t>::max()) const;
986     uint64_t positiveDiffWithOverflow(uint64_t before, uint64_t after,
987                                       uint64_t mask = std::numeric_limits<uint64_t>::max()) const;
988     bool outOfRange(uint64_t begin, uint64_t middle, uint64_t end) const;
989 
990     static constexpr uint64_t kBatchTimeLimitNanos        = 1000000000u; // 1 sec.
991     static constexpr uint64_t kDeviationErrorLimitNanos   = 100000000u;  // 100 ms.
992     static constexpr uint64_t kDeviationWarningLimitNanos = 50000000u;   // 50 ms.
993     static constexpr uint64_t kDefaultToleranceNanos      = 100000000u;  // 100 ms.
994 
995 #if (DE_OS == DE_OS_WIN32)
996     // Preprocessor used to avoid warning about unused variable.
997     static constexpr uint64_t kNanosecondsPerSecond = 1000000000u;
998 #endif
999     static constexpr uint64_t kNanosecondsPerMillisecond = 1000000u;
1000 
1001     std::string m_qualityMessage;
1002     float m_timestampPeriod;
1003     std::vector<VkTimeDomainKHR> m_devDomains;
1004     std::vector<VkTimeDomainKHR> m_hostDomains;
1005 #if (DE_OS == DE_OS_WIN32)
1006     uint64_t m_frequency;
1007 #endif
1008 
1009     Move<VkCommandPool> m_cmdPool;
1010     Move<VkCommandBuffer> m_cmdBuffer;
1011     Move<VkQueryPool> m_queryPool;
1012     uint64_t m_devTimestampMask;
1013 };
1014 
1015 class CalibratedTimestampDevDomainTestInstance : public CalibratedTimestampTestInstance
1016 {
1017 public:
CalibratedTimestampDevDomainTestInstance(Context & context)1018     CalibratedTimestampDevDomainTestInstance(Context &context) : CalibratedTimestampTestInstance{context}
1019     {
1020     }
1021 
~CalibratedTimestampDevDomainTestInstance(void)1022     virtual ~CalibratedTimestampDevDomainTestInstance(void)
1023     {
1024     }
1025     virtual tcu::TestStatus runTest(void) override;
1026 };
1027 
1028 class CalibratedTimestampHostDomainTestInstance : public CalibratedTimestampTestInstance
1029 {
1030 public:
CalibratedTimestampHostDomainTestInstance(Context & context)1031     CalibratedTimestampHostDomainTestInstance(Context &context) : CalibratedTimestampTestInstance{context}
1032     {
1033     }
1034 
~CalibratedTimestampHostDomainTestInstance(void)1035     virtual ~CalibratedTimestampHostDomainTestInstance(void)
1036     {
1037     }
1038     virtual tcu::TestStatus runTest(void) override;
1039 };
1040 
1041 class CalibratedTimestampCalibrationTestInstance : public CalibratedTimestampTestInstance
1042 {
1043 public:
CalibratedTimestampCalibrationTestInstance(Context & context)1044     CalibratedTimestampCalibrationTestInstance(Context &context) : CalibratedTimestampTestInstance{context}
1045     {
1046     }
1047 
~CalibratedTimestampCalibrationTestInstance(void)1048     virtual ~CalibratedTimestampCalibrationTestInstance(void)
1049     {
1050     }
1051     virtual tcu::TestStatus runTest(void) override;
1052 };
1053 
1054 template <class T>
initPrograms(SourceCollections & programCollection) const1055 void CalibratedTimestampTest<T>::initPrograms(SourceCollections &programCollection) const
1056 {
1057     vkt::TestCase::initPrograms(programCollection);
1058 }
1059 
1060 template <class T>
createInstance(Context & context) const1061 vkt::TestInstance *CalibratedTimestampTest<T>::createInstance(Context &context) const
1062 {
1063     return new T{context};
1064 }
1065 
1066 template <class T>
checkSupport(Context & context) const1067 void CalibratedTimestampTest<T>::checkSupport(Context &context) const
1068 {
1069 #ifdef CTS_USES_VULKANSC
1070     context.requireDeviceFunctionality("VK_EXT_calibrated_timestamps");
1071 #else
1072     if (!context.isDeviceFunctionalitySupported("VK_KHR_calibrated_timestamps") &&
1073         !context.isDeviceFunctionalitySupported("VK_EXT_calibrated_timestamps"))
1074         TCU_THROW(NotSupportedError, "VK_KHR_calibrated_timestamps and VK_EXT_calibrated_timestamps are not supported");
1075 #endif
1076 }
1077 
CalibratedTimestampTestInstance(Context & context)1078 CalibratedTimestampTestInstance::CalibratedTimestampTestInstance(Context &context) : TestInstance{context}
1079 {
1080 #if (DE_OS == DE_OS_WIN32)
1081     LARGE_INTEGER freq;
1082     if (!QueryPerformanceFrequency(&freq))
1083     {
1084         throw tcu::ResourceError("Unable to get clock frequency with QueryPerformanceFrequency");
1085     }
1086     if (freq.QuadPart <= 0)
1087     {
1088         throw tcu::ResourceError("QueryPerformanceFrequency did not return a positive number");
1089     }
1090     m_frequency = static_cast<uint64_t>(freq.QuadPart);
1091 #endif
1092 
1093     const InstanceInterface &vki      = context.getInstanceInterface();
1094     const VkPhysicalDevice physDevice = context.getPhysicalDevice();
1095     const uint32_t queueFamilyIndex   = context.getUniversalQueueFamilyIndex();
1096 
1097     // Get timestamp mask.
1098     m_devTimestampMask = checkTimestampsSupported(vki, physDevice, queueFamilyIndex);
1099 
1100     // Get calibreatable time domains.
1101     m_timestampPeriod = getPhysicalDeviceProperties(vki, physDevice).limits.timestampPeriod;
1102 
1103     uint32_t domainCount;
1104     VK_CHECK(vki.getPhysicalDeviceCalibrateableTimeDomainsKHR(physDevice, &domainCount, nullptr));
1105     if (domainCount == 0)
1106     {
1107         throw tcu::NotSupportedError("No calibrateable time domains found");
1108     }
1109 
1110     std::vector<VkTimeDomainKHR> domains;
1111     domains.resize(domainCount);
1112     VK_CHECK(vki.getPhysicalDeviceCalibrateableTimeDomainsKHR(physDevice, &domainCount, domains.data()));
1113 
1114     // Find the dev domain.
1115     std::vector<VkTimeDomainKHR> preferredDevDomains;
1116     preferredDevDomains.push_back(VK_TIME_DOMAIN_DEVICE_KHR);
1117     m_devDomains = getDomainSubset(domains, preferredDevDomains);
1118 
1119     // Find the host domain.
1120     std::vector<VkTimeDomainKHR> preferredHostDomains;
1121 #if (DE_OS == DE_OS_WIN32)
1122     preferredHostDomains.push_back(VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_KHR);
1123 #else
1124     preferredHostDomains.push_back(VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_KHR);
1125     preferredHostDomains.push_back(VK_TIME_DOMAIN_CLOCK_MONOTONIC_KHR);
1126 #endif
1127     m_hostDomains = getDomainSubset(domains, preferredHostDomains);
1128 
1129     // Initialize command buffers and queries.
1130     const DeviceInterface &vk = context.getDeviceInterface();
1131     const VkDevice vkDevice   = context.getDevice();
1132 
1133     const VkQueryPoolCreateInfo queryPoolParams = {
1134         VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, // VkStructureType               sType;
1135         nullptr,                                  // const void*                   pNext;
1136         0u,                                       // VkQueryPoolCreateFlags        flags;
1137         VK_QUERY_TYPE_TIMESTAMP,                  // VkQueryType                   queryType;
1138         1u,                                       // uint32_t                      entryCount;
1139         0u,                                       // VkQueryPipelineStatisticFlags pipelineStatistics;
1140     };
1141 
1142     m_queryPool = createQueryPool(vk, vkDevice, &queryPoolParams);
1143     m_cmdPool   = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
1144     m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1145 
1146     beginCommandBuffer(vk, *m_cmdBuffer, 0u);
1147     vk.cmdResetQueryPool(*m_cmdBuffer, *m_queryPool, 0u, 1u);
1148     vk.cmdWriteTimestamp(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, *m_queryPool, 0u);
1149     endCommandBuffer(vk, *m_cmdBuffer);
1150 }
1151 
getDomainSubset(const std::vector<VkTimeDomainKHR> & available,const std::vector<VkTimeDomainKHR> & interesting) const1152 std::vector<VkTimeDomainKHR> CalibratedTimestampTestInstance::getDomainSubset(
1153     const std::vector<VkTimeDomainKHR> &available, const std::vector<VkTimeDomainKHR> &interesting) const
1154 {
1155     const std::set<VkTimeDomainKHR> availableSet(begin(available), end(available));
1156     const std::set<VkTimeDomainKHR> interestingSet(begin(interesting), end(interesting));
1157 
1158     std::vector<VkTimeDomainKHR> subset;
1159     std::set_intersection(begin(availableSet), end(availableSet), begin(interestingSet), end(interestingSet),
1160                           std::back_inserter(subset));
1161     return subset;
1162 }
1163 
domainName(VkTimeDomainKHR domain) const1164 std::string CalibratedTimestampTestInstance::domainName(VkTimeDomainKHR domain) const
1165 {
1166     switch (domain)
1167     {
1168     case VK_TIME_DOMAIN_DEVICE_KHR:
1169         return "Device Domain";
1170     case VK_TIME_DOMAIN_CLOCK_MONOTONIC_KHR:
1171         return "Monotonic Clock";
1172     case VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_KHR:
1173         return "Raw Monotonic Clock";
1174     case VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_KHR:
1175         return "Query Performance Counter";
1176     default:
1177         DE_ASSERT(false);
1178         return "Unknown Time Domain";
1179     }
1180 }
1181 
getHostNativeTimestamp(VkTimeDomainKHR hostDomain) const1182 uint64_t CalibratedTimestampTestInstance::getHostNativeTimestamp(VkTimeDomainKHR hostDomain) const
1183 {
1184 #if (DE_OS == DE_OS_WIN32)
1185     DE_ASSERT(hostDomain == VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_KHR);
1186     LARGE_INTEGER result;
1187     if (!QueryPerformanceCounter(&result))
1188     {
1189         throw tcu::ResourceError("Unable to obtain host native timestamp for Win32");
1190     }
1191     if (result.QuadPart < 0)
1192     {
1193         throw tcu::ResourceError("Host-native timestamp for Win32 less than zero");
1194     }
1195     return static_cast<uint64_t>(result.QuadPart);
1196 #else
1197     DE_ASSERT(hostDomain == VK_TIME_DOMAIN_CLOCK_MONOTONIC_KHR || hostDomain == VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_KHR);
1198 
1199 #if defined(CLOCK_MONOTONIC_RAW)
1200     clockid_t id = ((hostDomain == VK_TIME_DOMAIN_CLOCK_MONOTONIC_KHR) ? CLOCK_MONOTONIC : CLOCK_MONOTONIC_RAW);
1201 #else
1202     clockid_t id = CLOCK_MONOTONIC;
1203 #endif
1204     struct timespec ts;
1205     if (clock_gettime(id, &ts) != 0)
1206     {
1207         throw tcu::ResourceError("Unable to obtain host native timestamp for POSIX");
1208     }
1209     return (static_cast<uint64_t>(ts.tv_sec) * 1000000000ULL + ts.tv_nsec);
1210 #endif
1211 }
1212 
getHostNanoseconds(uint64_t hostTimestamp) const1213 uint64_t CalibratedTimestampTestInstance::getHostNanoseconds(uint64_t hostTimestamp) const
1214 {
1215 #if (DE_OS == DE_OS_WIN32)
1216     uint64_t secs  = hostTimestamp / m_frequency;
1217     uint64_t nanos = ((hostTimestamp % m_frequency) * kNanosecondsPerSecond) / m_frequency;
1218 
1219     return ((secs * kNanosecondsPerSecond) + nanos);
1220 #else
1221     return hostTimestamp;
1222 #endif
1223 }
1224 
1225 // This method will be used when devTicksDelta is (supposedly) a small amount of ticks between two events. We will check
1226 // devTicksDelta is reasonably small for the calculation below to succeed without losing precision.
getDeviceNanoseconds(uint64_t devTicksDelta) const1227 uint64_t CalibratedTimestampTestInstance::getDeviceNanoseconds(uint64_t devTicksDelta) const
1228 {
1229     if (devTicksDelta > static_cast<uint64_t>(std::numeric_limits<uint32_t>::max()))
1230     {
1231         std::ostringstream msg;
1232         msg << "Number of device ticks too big for conversion to nanoseconds: " << devTicksDelta;
1233         throw tcu::InternalError(msg.str());
1234     }
1235     return static_cast<uint64_t>(static_cast<double>(devTicksDelta) * m_timestampPeriod);
1236 }
1237 
iterate(void)1238 tcu::TestStatus CalibratedTimestampTestInstance::iterate(void)
1239 {
1240     // Notes:
1241     //    1) Clocks may overflow.
1242     //    2) Because m_timestampPeriod is a floating point value, there may be less than one nano per tick.
1243 
1244     const tcu::TestStatus result = runTest();
1245     if (result.getCode() != QP_TEST_RESULT_PASS)
1246         return result;
1247 
1248     if (!m_qualityMessage.empty())
1249     {
1250         const std::string msg = "Warnings found: " + m_qualityMessage;
1251         return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, msg);
1252     }
1253     return tcu::TestStatus::pass("Pass");
1254 }
1255 
1256 // Verify all invalid timestamp bits are zero.
verifyDevTimestampMask(uint64_t value) const1257 void CalibratedTimestampTestInstance::verifyDevTimestampMask(uint64_t value) const
1258 {
1259     checkTimestampBits(value, m_devTimestampMask);
1260 }
1261 
1262 // Absolute difference between two timestamps A and B taking overflow into account. Pick the smallest difference between the two
1263 // possibilities. We don't know beforehand if B > A or vice versa. Take the valid bit mask into account.
absDiffWithOverflow(uint64_t a,uint64_t b,uint64_t mask) const1264 uint64_t CalibratedTimestampTestInstance::absDiffWithOverflow(uint64_t a, uint64_t b, uint64_t mask) const
1265 {
1266     //    <---------+ range +-------->
1267     //
1268     //    +--------------------------+
1269     //    |         uint64_t         |
1270     //    +------^-----------^-------+
1271     //           +           +
1272     //           a           b
1273     //           +----------->
1274     //           ccccccccccccc
1275     //    ------>             +-------
1276     //    ddddddd             dddddddd
1277 
1278     DE_ASSERT(a <= mask);
1279     DE_ASSERT(b <= mask);
1280 
1281     const uint64_t c = ((a >= b) ? (a - b) : (b - a));
1282 
1283     if (c == 0u)
1284         return c;
1285 
1286     const uint64_t d = (mask - c) + 1;
1287 
1288     return ((c < d) ? c : d);
1289 }
1290 
1291 // Positive difference between both marks, advancing from before to after, taking overflow and the valid bit mask into account.
positiveDiffWithOverflow(uint64_t before,uint64_t after,uint64_t mask) const1292 uint64_t CalibratedTimestampTestInstance::positiveDiffWithOverflow(uint64_t before, uint64_t after, uint64_t mask) const
1293 {
1294     DE_ASSERT(before <= mask);
1295     DE_ASSERT(after <= mask);
1296 
1297     return ((before <= after) ? (after - before) : ((mask - (before - after)) + 1));
1298 }
1299 
1300 // Return true if middle is not between begin and end, taking overflow into account.
outOfRange(uint64_t begin,uint64_t middle,uint64_t end) const1301 bool CalibratedTimestampTestInstance::outOfRange(uint64_t begin, uint64_t middle, uint64_t end) const
1302 {
1303     return (((begin <= end) && (middle < begin || middle > end)) ||
1304             ((begin > end) && (middle > end && middle < begin)));
1305 }
1306 
1307 std::vector<CalibratedTimestampTestInstance::CalibratedTimestamp> CalibratedTimestampTestInstance::
getCalibratedTimestamps(const std::vector<VkTimeDomainKHR> & domains)1308     getCalibratedTimestamps(const std::vector<VkTimeDomainKHR> &domains)
1309 {
1310     std::vector<VkCalibratedTimestampInfoKHR> infos;
1311 
1312     for (auto domain : domains)
1313     {
1314         VkCalibratedTimestampInfoKHR info;
1315         info.sType      = getStructureType<VkCalibratedTimestampInfoKHR>();
1316         info.pNext      = nullptr;
1317         info.timeDomain = domain;
1318         infos.push_back(info);
1319     }
1320 
1321     std::vector<uint64_t> timestamps(domains.size());
1322     uint64_t deviation;
1323 
1324     const DeviceInterface &vk = m_context.getDeviceInterface();
1325     const VkDevice vkDevice   = m_context.getDevice();
1326 
1327     VK_CHECK(vk.getCalibratedTimestampsKHR(vkDevice, static_cast<uint32_t>(domains.size()), infos.data(),
1328                                            timestamps.data(), &deviation));
1329 
1330     if (deviation > kDeviationErrorLimitNanos)
1331     {
1332         throw tcu::InternalError("Calibrated maximum deviation too big");
1333     }
1334     else if (deviation > kDeviationWarningLimitNanos)
1335     {
1336         appendQualityMessage("Calibrated maximum deviation beyond desirable limits");
1337     }
1338     else if (deviation == 0 && domains.size() > 1)
1339     {
1340         appendQualityMessage("Calibrated maximum deviation reported as zero");
1341     }
1342 
1343     // Pack results.
1344     std::vector<CalibratedTimestamp> results;
1345 
1346     for (size_t i = 0; i < domains.size(); ++i)
1347     {
1348         if (domains[i] == VK_TIME_DOMAIN_DEVICE_KHR)
1349             verifyDevTimestampMask(timestamps[i]);
1350         results.emplace_back(timestamps[i], deviation);
1351     }
1352 
1353     return results;
1354 }
1355 
getCalibratedTimestamp(VkTimeDomainKHR domain)1356 CalibratedTimestampTestInstance::CalibratedTimestamp CalibratedTimestampTestInstance::getCalibratedTimestamp(
1357     VkTimeDomainKHR domain)
1358 {
1359     // Single domain, single result.
1360     return getCalibratedTimestamps(std::vector<VkTimeDomainKHR>(1, domain))[0];
1361 }
1362 
appendQualityMessage(const std::string & message)1363 void CalibratedTimestampTestInstance::appendQualityMessage(const std::string &message)
1364 {
1365     if (!m_qualityMessage.empty())
1366         m_qualityMessage += "; ";
1367 
1368     m_qualityMessage += message;
1369 }
1370 
1371 // Test device domain makes sense and is consistent with vkCmdWriteTimestamp().
runTest(void)1372 tcu::TestStatus CalibratedTimestampDevDomainTestInstance::runTest(void)
1373 {
1374     if (m_devDomains.empty())
1375         throw tcu::NotSupportedError("No suitable device time domains found");
1376 
1377     const DeviceInterface &vk = m_context.getDeviceInterface();
1378     const VkDevice vkDevice   = m_context.getDevice();
1379     const VkQueue queue       = m_context.getUniversalQueue();
1380 
1381     for (const auto devDomain : m_devDomains)
1382     {
1383         const CalibratedTimestamp before = getCalibratedTimestamp(devDomain);
1384         submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
1385         const CalibratedTimestamp after = getCalibratedTimestamp(devDomain);
1386         const uint64_t diffNanos =
1387             getDeviceNanoseconds(positiveDiffWithOverflow(before.timestamp, after.timestamp, m_devTimestampMask));
1388         uint64_t written;
1389         VK_CHECK(vk.getQueryPoolResults(vkDevice, *m_queryPool, 0u, 1u, sizeof(written), &written, sizeof(written),
1390                                         (VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT)));
1391         verifyDevTimestampMask(written);
1392 
1393         if (diffNanos > kBatchTimeLimitNanos)
1394         {
1395             return tcu::TestStatus::fail(domainName(devDomain) + ": Batch of work took too long to execute");
1396         }
1397 
1398         if (outOfRange(before.timestamp, written, after.timestamp))
1399         {
1400             return tcu::TestStatus::fail(domainName(devDomain) +
1401                                          ": vkCmdWriteTimestamp() inconsistent with vkGetCalibratedTimestampsKHR()");
1402         }
1403     }
1404 
1405     return tcu::TestStatus::pass("Pass");
1406 }
1407 
1408 // Test host domain makes sense and is consistent with native host values.
runTest(void)1409 tcu::TestStatus CalibratedTimestampHostDomainTestInstance::runTest(void)
1410 {
1411     if (m_hostDomains.empty())
1412         throw tcu::NotSupportedError("No suitable host time domains found");
1413 
1414     for (const auto hostDomain : m_hostDomains)
1415     {
1416         const uint64_t before          = getHostNativeTimestamp(hostDomain);
1417         const CalibratedTimestamp vkTS = getCalibratedTimestamp(hostDomain);
1418         const uint64_t after           = getHostNativeTimestamp(hostDomain);
1419         const uint64_t diffNanos       = getHostNanoseconds(positiveDiffWithOverflow(before, after));
1420 
1421         if (diffNanos > kBatchTimeLimitNanos)
1422         {
1423             return tcu::TestStatus::fail(domainName(hostDomain) + ": Querying host domain took too long to execute");
1424         }
1425 
1426         if (outOfRange(before, vkTS.timestamp, after))
1427         {
1428             return tcu::TestStatus::fail(domainName(hostDomain) +
1429                                          ": vkGetCalibratedTimestampsKHR() inconsistent with native host API");
1430         }
1431     }
1432 
1433     return tcu::TestStatus::pass("Pass");
1434 }
1435 
1436 // Verify predictable timestamps and calibration possible.
runTest(void)1437 tcu::TestStatus CalibratedTimestampCalibrationTestInstance::runTest(void)
1438 {
1439     if (m_devDomains.empty())
1440         throw tcu::NotSupportedError("No suitable device time domains found");
1441     if (m_hostDomains.empty())
1442         throw tcu::NotSupportedError("No suitable host time domains found");
1443 
1444     // Sleep time.
1445     constexpr uint32_t kSleepMilliseconds = 200;
1446     constexpr uint32_t kSleepNanoseconds  = kSleepMilliseconds * kNanosecondsPerMillisecond;
1447 
1448     for (const auto devDomain : m_devDomains)
1449         for (const auto hostDomain : m_hostDomains)
1450         {
1451             std::vector<VkTimeDomainKHR> domains;
1452             domains.push_back(devDomain);  // Device results at index 0.
1453             domains.push_back(hostDomain); // Host results at index 1.
1454 
1455             // Measure time.
1456             const std::vector<CalibratedTimestamp> before = getCalibratedTimestamps(domains);
1457             std::this_thread::sleep_for(std::chrono::nanoseconds(kSleepNanoseconds));
1458             const std::vector<CalibratedTimestamp> after = getCalibratedTimestamps(domains);
1459 
1460             // Check device timestamp is as expected.
1461             const uint64_t devBeforeTicks = before[0].timestamp;
1462             const uint64_t devAfterTicks  = after[0].timestamp;
1463             const uint64_t devExpectedTicks =
1464                 ((devBeforeTicks + static_cast<uint64_t>(static_cast<double>(kSleepNanoseconds) / m_timestampPeriod)) &
1465                  m_devTimestampMask);
1466             const uint64_t devDiffNanos =
1467                 getDeviceNanoseconds(absDiffWithOverflow(devAfterTicks, devExpectedTicks, m_devTimestampMask));
1468             const uint64_t maxDevDiffNanos =
1469                 std::max({kDefaultToleranceNanos, before[0].deviation + after[0].deviation});
1470 
1471             if (devDiffNanos > maxDevDiffNanos)
1472             {
1473                 std::ostringstream msg;
1474                 msg << "[" << domainName(devDomain) << "] Device expected timestamp differs " << devDiffNanos
1475                     << " nanoseconds (expect value <= " << maxDevDiffNanos << ")";
1476                 return tcu::TestStatus::fail(msg.str());
1477             }
1478 
1479             // Check host timestamp is as expected.
1480             const uint64_t hostBefore   = getHostNanoseconds(before[1].timestamp);
1481             const uint64_t hostAfter    = getHostNanoseconds(after[1].timestamp);
1482             const uint64_t hostExpected = hostBefore + kSleepNanoseconds;
1483             const uint64_t hostDiff     = absDiffWithOverflow(hostAfter, hostExpected);
1484             const uint64_t maxHostDiff  = std::max({kDefaultToleranceNanos, before[1].deviation + after[1].deviation});
1485 
1486             if (hostDiff > maxHostDiff)
1487             {
1488                 std::ostringstream msg;
1489                 msg << "[" << domainName(hostDomain) << "] Host expected timestamp differs " << hostDiff
1490                     << " nanoseconds (expected value <= " << maxHostDiff << ")";
1491                 return tcu::TestStatus::fail(msg.str());
1492             }
1493         }
1494 
1495     return tcu::TestStatus::pass("Pass");
1496 }
1497 
1498 class BasicGraphicsTest : public TimestampTest
1499 {
1500 public:
BasicGraphicsTest(tcu::TestContext & testContext,const std::string & name,const TimestampTestParam * param)1501     BasicGraphicsTest(tcu::TestContext &testContext, const std::string &name, const TimestampTestParam *param)
1502         : TimestampTest(testContext, name, param)
1503     {
1504     }
~BasicGraphicsTest(void)1505     virtual ~BasicGraphicsTest(void)
1506     {
1507     }
1508     virtual void initPrograms(SourceCollections &programCollection) const;
1509     virtual TestInstance *createInstance(Context &context) const;
1510 };
1511 
1512 class BasicGraphicsTestInstance : public TimestampTestInstance
1513 {
1514 public:
1515     enum
1516     {
1517         VK_MAX_SHADER_STAGES = 6,
1518     };
1519     BasicGraphicsTestInstance(Context &context, const PipelineConstructionType pipelineConstructionType,
1520                               const StageFlagVector stages, const bool inRenderPass, const bool hostQueryReset,
1521                               const VkQueryResultFlags queryResultFlags);
1522 
1523     virtual ~BasicGraphicsTestInstance(void);
1524 
1525 protected:
1526     virtual void buildPipeline(void);
1527     virtual void configCommandBuffer(void);
1528     virtual void buildVertexBuffer(void);
1529     virtual void buildRenderPass(VkFormat colorFormat, VkFormat depthFormat);
1530 
1531     virtual void buildFrameBuffer(tcu::UVec2 renderSize, VkFormat colorFormat, VkFormat depthFormat);
1532 
1533 protected:
1534     const PipelineConstructionType m_pipelineConstructionType;
1535     const tcu::UVec2 m_renderSize;
1536     const VkFormat m_colorFormat;
1537     const VkFormat m_depthFormat;
1538 
1539     Move<VkImage> m_colorImage;
1540     de::MovePtr<Allocation> m_colorImageAlloc;
1541     Move<VkImage> m_depthImage;
1542     de::MovePtr<Allocation> m_depthImageAlloc;
1543     Move<VkImageView> m_colorAttachmentView;
1544     Move<VkImageView> m_depthAttachmentView;
1545     RenderPassWrapper m_renderPass;
1546     Move<VkFramebuffer> m_framebuffer;
1547     VkImageMemoryBarrier m_imageLayoutBarriers[2];
1548 
1549     de::MovePtr<Allocation> m_vertexBufferAlloc;
1550     Move<VkBuffer> m_vertexBuffer;
1551     std::vector<Vertex4RGBA> m_vertices;
1552 
1553     PipelineLayoutWrapper m_pipelineLayout;
1554     GraphicsPipelineWrapper m_graphicsPipeline;
1555 };
1556 
initPrograms(SourceCollections & programCollection) const1557 void BasicGraphicsTest::initPrograms(SourceCollections &programCollection) const
1558 {
1559     programCollection.glslSources.add("color_vert")
1560         << glu::VertexSource("#version 310 es\n"
1561                              "layout(location = 0) in vec4 position;\n"
1562                              "layout(location = 1) in vec4 color;\n"
1563                              "layout(location = 0) out highp vec4 vtxColor;\n"
1564                              "void main (void)\n"
1565                              "{\n"
1566                              "  gl_Position = position;\n"
1567                              "  vtxColor = color;\n"
1568                              "}\n");
1569 
1570     programCollection.glslSources.add("color_frag")
1571         << glu::FragmentSource("#version 310 es\n"
1572                                "layout(location = 0) in highp vec4 vtxColor;\n"
1573                                "layout(location = 0) out highp vec4 fragColor;\n"
1574                                "void main (void)\n"
1575                                "{\n"
1576                                "  fragColor = vtxColor;\n"
1577                                "}\n");
1578 }
1579 
createInstance(Context & context) const1580 TestInstance *BasicGraphicsTest::createInstance(Context &context) const
1581 {
1582     return new BasicGraphicsTestInstance(context, m_pipelineConstructionType, m_stages, m_inRenderPass,
1583                                          m_hostQueryReset, m_queryResultFlags);
1584 }
1585 
buildVertexBuffer(void)1586 void BasicGraphicsTestInstance::buildVertexBuffer(void)
1587 {
1588     const DeviceInterface &vk = m_context.getDeviceInterface();
1589 
1590     // Create vertex buffer
1591     {
1592         m_vertexBuffer = createBufferAndBindMemory(1024u, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, &m_vertexBufferAlloc);
1593         m_vertices     = createOverlappingQuads();
1594 
1595         // Load vertices into vertex buffer
1596         deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
1597         flushAlloc(vk, m_device, *m_vertexBufferAlloc);
1598     }
1599 }
1600 
buildRenderPass(VkFormat colorFormat,VkFormat depthFormat)1601 void BasicGraphicsTestInstance::buildRenderPass(VkFormat colorFormat, VkFormat depthFormat)
1602 {
1603     const DeviceInterface &vk = m_context.getDeviceInterface();
1604 
1605     // Create render pass
1606     m_renderPass = RenderPassWrapper(m_pipelineConstructionType, vk, m_device, colorFormat, depthFormat);
1607 }
1608 
buildFrameBuffer(tcu::UVec2 renderSize,VkFormat colorFormat,VkFormat depthFormat)1609 void BasicGraphicsTestInstance::buildFrameBuffer(tcu::UVec2 renderSize, VkFormat colorFormat, VkFormat depthFormat)
1610 {
1611     const DeviceInterface &vk                     = m_context.getDeviceInterface();
1612     const VkComponentMapping ComponentMappingRGBA = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G,
1613                                                      VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
1614 
1615     // Create color image
1616     {
1617         m_colorImage = createImage2DAndBindMemory(colorFormat, renderSize.x(), renderSize.y(),
1618                                                   VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
1619                                                   VK_SAMPLE_COUNT_1_BIT, &m_colorImageAlloc);
1620     }
1621 
1622     // Create depth image
1623     {
1624         m_depthImage = createImage2DAndBindMemory(depthFormat, renderSize.x(), renderSize.y(),
1625                                                   VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_SAMPLE_COUNT_1_BIT,
1626                                                   &m_depthImageAlloc);
1627     }
1628 
1629     // Set up image layout transition barriers
1630     {
1631         const VkImageMemoryBarrier colorImageBarrier = {
1632             VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,      // VkStructureType sType;
1633             nullptr,                                     // const void* pNext;
1634             0u,                                          // VkAccessFlags srcAccessMask;
1635             VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,        // VkAccessFlags dstAccessMask;
1636             VK_IMAGE_LAYOUT_UNDEFINED,                   // VkImageLayout oldLayout;
1637             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,    // VkImageLayout newLayout;
1638             VK_QUEUE_FAMILY_IGNORED,                     // uint32_t srcQueueFamilyIndex;
1639             VK_QUEUE_FAMILY_IGNORED,                     // uint32_t dstQueueFamilyIndex;
1640             *m_colorImage,                               // VkImage image;
1641             {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u}, // VkImageSubresourceRange subresourceRange;
1642         };
1643         const VkImageMemoryBarrier depthImageBarrier = {
1644             VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,           // VkStructureType sType;
1645             nullptr,                                          // const void* pNext;
1646             0u,                                               // VkAccessFlags srcAccessMask;
1647             VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,     // VkAccessFlags dstAccessMask;
1648             VK_IMAGE_LAYOUT_UNDEFINED,                        // VkImageLayout oldLayout;
1649             VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout;
1650             VK_QUEUE_FAMILY_IGNORED,                          // uint32_t srcQueueFamilyIndex;
1651             VK_QUEUE_FAMILY_IGNORED,                          // uint32_t dstQueueFamilyIndex;
1652             *m_depthImage,                                    // VkImage image;
1653             {VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 1u, 0u, 1u},      // VkImageSubresourceRange subresourceRange;
1654         };
1655 
1656         m_imageLayoutBarriers[0] = colorImageBarrier;
1657         m_imageLayoutBarriers[1] = depthImageBarrier;
1658     }
1659 
1660     // Create color attachment view
1661     {
1662         const VkImageViewCreateInfo colorAttachmentViewParams = {
1663             VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,    // VkStructureType          sType;
1664             nullptr,                                     // const void*              pNext;
1665             0u,                                          // VkImageViewCreateFlags   flags;
1666             *m_colorImage,                               // VkImage                  image;
1667             VK_IMAGE_VIEW_TYPE_2D,                       // VkImageViewType          viewType;
1668             colorFormat,                                 // VkFormat                 format;
1669             ComponentMappingRGBA,                        // VkComponentMapping       components;
1670             {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u}, // VkImageSubresourceRange  subresourceRange;
1671         };
1672 
1673         m_colorAttachmentView = createImageView(vk, m_device, &colorAttachmentViewParams);
1674     }
1675 
1676     // Create depth attachment view
1677     {
1678         const VkImageViewCreateInfo depthAttachmentViewParams = {
1679             VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,    // VkStructureType          sType;
1680             nullptr,                                     // const void*              pNext;
1681             0u,                                          // VkImageViewCreateFlags   flags;
1682             *m_depthImage,                               // VkImage                  image;
1683             VK_IMAGE_VIEW_TYPE_2D,                       // VkImageViewType          viewType;
1684             depthFormat,                                 // VkFormat                 format;
1685             ComponentMappingRGBA,                        // VkComponentMapping       components;
1686             {VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 1u, 0u, 1u}, // VkImageSubresourceRange  subresourceRange;
1687         };
1688 
1689         m_depthAttachmentView = createImageView(vk, m_device, &depthAttachmentViewParams);
1690     }
1691 
1692     // Create framebuffer
1693     {
1694         const std::vector<VkImage> images = {
1695             *m_colorImage,
1696             *m_depthImage,
1697         };
1698         const VkImageView attachmentBindInfos[2] = {
1699             *m_colorAttachmentView,
1700             *m_depthAttachmentView,
1701         };
1702 
1703         const VkFramebufferCreateInfo framebufferParams = {
1704             VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType              sType;
1705             nullptr,                                   // const void*                  pNext;
1706             0u,                                        // VkFramebufferCreateFlags     flags;
1707             *m_renderPass,                             // VkRenderPass                 renderPass;
1708             2u,                                        // uint32_t                     attachmentCount;
1709             attachmentBindInfos,                       // const VkImageView*           pAttachments;
1710             (uint32_t)renderSize.x(),                  // uint32_t                     width;
1711             (uint32_t)renderSize.y(),                  // uint32_t                     height;
1712             1u,                                        // uint32_t                     layers;
1713         };
1714 
1715         m_renderPass.createFramebuffer(vk, m_device, &framebufferParams, images);
1716     }
1717 }
1718 
BasicGraphicsTestInstance(Context & context,const PipelineConstructionType pipelineConstructionType,const StageFlagVector stages,const bool inRenderPass,const bool hostQueryReset,const VkQueryResultFlags queryResultFlags)1719 BasicGraphicsTestInstance::BasicGraphicsTestInstance(Context &context,
1720                                                      const PipelineConstructionType pipelineConstructionType,
1721                                                      const StageFlagVector stages, const bool inRenderPass,
1722                                                      const bool hostQueryReset,
1723                                                      const VkQueryResultFlags queryResultFlags)
1724     : TimestampTestInstance(context, stages, inRenderPass, hostQueryReset, false, queryResultFlags)
1725     , m_pipelineConstructionType(pipelineConstructionType)
1726     , m_renderSize(32, 32)
1727     , m_colorFormat(VK_FORMAT_R8G8B8A8_UNORM)
1728     , m_depthFormat(VK_FORMAT_D16_UNORM)
1729     , m_graphicsPipeline(context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(),
1730                          context.getDevice(), context.getDeviceExtensions(), pipelineConstructionType)
1731 {
1732     buildVertexBuffer();
1733 
1734     buildRenderPass(m_colorFormat, m_depthFormat);
1735 
1736     buildFrameBuffer(m_renderSize, m_colorFormat, m_depthFormat);
1737 
1738     // Create pipeline layout
1739     const DeviceInterface &vk                             = m_context.getDeviceInterface();
1740     const VkPipelineLayoutCreateInfo pipelineLayoutParams = initVulkanStructure();
1741     m_pipelineLayout = PipelineLayoutWrapper(pipelineConstructionType, vk, m_device, &pipelineLayoutParams);
1742 }
1743 
~BasicGraphicsTestInstance(void)1744 BasicGraphicsTestInstance::~BasicGraphicsTestInstance(void)
1745 {
1746 }
1747 
1748 static const VkVertexInputBindingDescription defaultVertexInputBindingDescription{
1749     0u,                          // uint32_t binding;
1750     sizeof(Vertex4RGBA),         // uint32_t strideInBytes;
1751     VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate;
1752 };
1753 
1754 static const VkVertexInputAttributeDescription defaultVertexInputAttributeDescriptions[2]{
1755     {
1756         0u,                            // uint32_t location;
1757         0u,                            // uint32_t binding;
1758         VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
1759         0u                             // uint32_t offsetInBytes;
1760     },
1761     {
1762         1u,                            // uint32_t location;
1763         0u,                            // uint32_t binding;
1764         VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
1765         offsetof(Vertex4RGBA, color),  // uint32_t offsetInBytes;
1766     }};
1767 
1768 static const VkPipelineVertexInputStateCreateInfo defaultVertexInputStateParams{
1769     VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
1770     nullptr,                                                   // const void* pNext;
1771     0u,                                                        // VkPipelineVertexInputStateCreateFlags flags;
1772     1u,                                                        // uint32_t vertexBindingDescriptionCount;
1773     &defaultVertexInputBindingDescription,   // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
1774     2u,                                      // uint32_t vertexAttributeDescriptionCount;
1775     defaultVertexInputAttributeDescriptions, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
1776 };
1777 
1778 static const VkPipelineDepthStencilStateCreateInfo defaultDepthStencilStateParams{
1779     VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
1780     nullptr,                                                    // const void* pNext;
1781     0u,                                                         // VkPipelineDepthStencilStateCreateFlags flags;
1782     VK_TRUE,                                                    // VkBool32 depthTestEnable;
1783     VK_TRUE,                                                    // VkBool32 depthWriteEnable;
1784     VK_COMPARE_OP_LESS_OR_EQUAL,                                // VkCompareOp depthCompareOp;
1785     VK_FALSE,                                                   // VkBool32 depthBoundsTestEnable;
1786     VK_FALSE,                                                   // VkBool32 stencilTestEnable;
1787     {
1788         // VkStencilOpState front;
1789         VK_STENCIL_OP_KEEP,  // VkStencilOp                                failOp
1790         VK_STENCIL_OP_KEEP,  // VkStencilOp                                passOp
1791         VK_STENCIL_OP_KEEP,  // VkStencilOp                                depthFailOp
1792         VK_COMPARE_OP_NEVER, // VkCompareOp                                compareOp
1793         0u,                  // uint32_t                                    compareMask
1794         0u,                  // uint32_t                                    writeMask
1795         0u                   // uint32_t                                    reference
1796     },
1797     {
1798         // VkStencilOpState back;
1799         VK_STENCIL_OP_KEEP,  // VkStencilOp                                failOp
1800         VK_STENCIL_OP_KEEP,  // VkStencilOp                                passOp
1801         VK_STENCIL_OP_KEEP,  // VkStencilOp                                depthFailOp
1802         VK_COMPARE_OP_NEVER, // VkCompareOp                                compareOp
1803         0u,                  // uint32_t                                    compareMask
1804         0u,                  // uint32_t                                    writeMask
1805         0u                   // uint32_t                                    reference
1806     },
1807     0.0f, // float minDepthBounds;
1808     1.0f, // float maxDepthBounds;
1809 };
1810 
buildPipeline(void)1811 void BasicGraphicsTestInstance::buildPipeline(void)
1812 {
1813     const DeviceInterface &vk = m_context.getDeviceInterface();
1814 
1815     auto vertexShaderModule   = ShaderWrapper(vk, m_device, m_context.getBinaryCollection().get("color_vert"), 0);
1816     auto fragmentShaderModule = ShaderWrapper(vk, m_device, m_context.getBinaryCollection().get("color_frag"), 0);
1817 
1818     const std::vector<VkViewport> viewports{makeViewport(m_renderSize)};
1819     const std::vector<VkRect2D> scissors{makeRect2D(m_renderSize)};
1820 
1821     // Create pipeline
1822     m_graphicsPipeline.setDefaultRasterizationState()
1823         .setDefaultColorBlendState()
1824         .setDefaultMultisampleState()
1825         .setupVertexInputState(&defaultVertexInputStateParams)
1826         .setupPreRasterizationShaderState(viewports, scissors, m_pipelineLayout, *m_renderPass, 0u, vertexShaderModule)
1827         .setupFragmentShaderState(m_pipelineLayout, *m_renderPass, 0u, fragmentShaderModule,
1828                                   &defaultDepthStencilStateParams)
1829         .setupFragmentOutputState(*m_renderPass)
1830         .setMonolithicPipelineLayout(m_pipelineLayout)
1831         .buildPipeline();
1832 }
1833 
configCommandBuffer(void)1834 void BasicGraphicsTestInstance::configCommandBuffer(void)
1835 {
1836     const DeviceInterface &vk = m_context.getDeviceInterface();
1837 
1838     const VkClearValue attachmentClearValues[2] = {
1839         defaultClearValue(m_colorFormat),
1840         defaultClearValue(m_depthFormat),
1841     };
1842 
1843     beginCommandBuffer(vk, *m_cmdBuffer, 0u);
1844 
1845     vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
1846                           VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,
1847                           (VkDependencyFlags)0, 0u, nullptr, 0u, nullptr, DE_LENGTH_OF_ARRAY(m_imageLayoutBarriers),
1848                           m_imageLayoutBarriers);
1849 
1850     if (!m_hostQueryReset)
1851         vk.cmdResetQueryPool(*m_cmdBuffer, *m_queryPool, 0u, TimestampTest::ENTRY_COUNT);
1852 
1853     m_renderPass.begin(vk, *m_cmdBuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), 2u,
1854                        attachmentClearValues);
1855 
1856     m_graphicsPipeline.bind(*m_cmdBuffer);
1857     VkDeviceSize offsets = 0u;
1858     vk.cmdBindVertexBuffers(*m_cmdBuffer, 0u, 1u, &m_vertexBuffer.get(), &offsets);
1859     vk.cmdDraw(*m_cmdBuffer, (uint32_t)m_vertices.size(), 1u, 0u, 0u);
1860 
1861     if (m_inRenderPass)
1862     {
1863         uint32_t timestampEntry = 0u;
1864 
1865         for (StageFlagVector::const_iterator it = m_stages.begin(); it != m_stages.end(); it++)
1866         {
1867             vk.cmdWriteTimestamp(*m_cmdBuffer, *it, *m_queryPool, timestampEntry++);
1868         }
1869     }
1870 
1871     m_renderPass.end(vk, *m_cmdBuffer);
1872 
1873     if (!m_inRenderPass)
1874     {
1875         uint32_t timestampEntry = 0u;
1876 
1877         for (StageFlagVector::const_iterator it = m_stages.begin(); it != m_stages.end(); it++)
1878         {
1879             vk.cmdWriteTimestamp(*m_cmdBuffer, *it, *m_queryPool, timestampEntry++);
1880         }
1881     }
1882 
1883     endCommandBuffer(vk, *m_cmdBuffer);
1884 }
1885 
1886 class AdvGraphicsTest : public BasicGraphicsTest
1887 {
1888 public:
AdvGraphicsTest(tcu::TestContext & testContext,const std::string & name,const TimestampTestParam * param)1889     AdvGraphicsTest(tcu::TestContext &testContext, const std::string &name, const TimestampTestParam *param)
1890         : BasicGraphicsTest(testContext, name, param)
1891     {
1892     }
1893 
~AdvGraphicsTest(void)1894     virtual ~AdvGraphicsTest(void)
1895     {
1896     }
1897     virtual void initPrograms(SourceCollections &programCollection) const;
1898     virtual TestInstance *createInstance(Context &context) const;
1899 };
1900 
1901 class AdvGraphicsTestInstance : public BasicGraphicsTestInstance
1902 {
1903 public:
1904     AdvGraphicsTestInstance(Context &context, const PipelineConstructionType pipelineConstructionType,
1905                             const StageFlagVector stages, const bool inRenderPass, const bool hostQueryReset,
1906                             const VkQueryResultFlags queryResultFlags);
1907 
1908     virtual ~AdvGraphicsTestInstance(void);
1909     virtual void buildPipeline(void);
1910     virtual void configCommandBuffer(void);
1911 
1912 protected:
1913     virtual void featureSupportCheck(void);
1914 
1915 protected:
1916     VkPhysicalDeviceFeatures m_features;
1917     uint32_t m_draw_count;
1918     de::MovePtr<Allocation> m_indirectBufferAlloc;
1919     Move<VkBuffer> m_indirectBuffer;
1920 };
1921 
initPrograms(SourceCollections & programCollection) const1922 void AdvGraphicsTest::initPrograms(SourceCollections &programCollection) const
1923 {
1924     BasicGraphicsTest::initPrograms(programCollection);
1925 
1926     programCollection.glslSources.add("unused_geo")
1927         << glu::GeometrySource("#version 310 es\n"
1928                                "#extension GL_EXT_geometry_shader : enable\n"
1929                                "layout(triangles) in;\n"
1930                                "layout(triangle_strip, max_vertices = 3) out;\n"
1931                                "layout(location = 0) in highp vec4 in_vtxColor[];\n"
1932                                "layout(location = 0) out highp vec4 vtxColor;\n"
1933                                "void main (void)\n"
1934                                "{\n"
1935                                "  for(int ndx=0; ndx<3; ndx++)\n"
1936                                "  {\n"
1937                                "    gl_Position = gl_in[ndx].gl_Position;\n"
1938                                "    vtxColor    = in_vtxColor[ndx];\n"
1939                                "    EmitVertex();\n"
1940                                "  }\n"
1941                                "  EndPrimitive();\n"
1942                                "}\n");
1943 
1944     programCollection.glslSources.add("basic_tcs") << glu::TessellationControlSource(
1945         "#version 310 es\n"
1946         "#extension GL_EXT_tessellation_shader : enable\n"
1947         "layout(vertices = 3) out;\n"
1948         "layout(location = 0) in highp vec4 color[];\n"
1949         "layout(location = 0) out highp vec4 vtxColor[];\n"
1950         "void main()\n"
1951         "{\n"
1952         "  gl_TessLevelOuter[0] = 4.0;\n"
1953         "  gl_TessLevelOuter[1] = 4.0;\n"
1954         "  gl_TessLevelOuter[2] = 4.0;\n"
1955         "  gl_TessLevelInner[0] = 4.0;\n"
1956         "  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1957         "  vtxColor[gl_InvocationID] = color[gl_InvocationID];\n"
1958         "}\n");
1959 
1960     programCollection.glslSources.add("basic_tes")
1961         << glu::TessellationEvaluationSource("#version 310 es\n"
1962                                              "#extension GL_EXT_tessellation_shader : enable\n"
1963                                              "layout(triangles, fractional_even_spacing, ccw) in;\n"
1964                                              "layout(location = 0) in highp vec4 colors[];\n"
1965                                              "layout(location = 0) out highp vec4 vtxColor;\n"
1966                                              "void main() \n"
1967                                              "{\n"
1968                                              "  float u = gl_TessCoord.x;\n"
1969                                              "  float v = gl_TessCoord.y;\n"
1970                                              "  float w = gl_TessCoord.z;\n"
1971                                              "  vec4 pos = vec4(0);\n"
1972                                              "  vec4 color = vec4(0);\n"
1973                                              "  pos.xyz += u * gl_in[0].gl_Position.xyz;\n"
1974                                              "  color.xyz += u * colors[0].xyz;\n"
1975                                              "  pos.xyz += v * gl_in[1].gl_Position.xyz;\n"
1976                                              "  color.xyz += v * colors[1].xyz;\n"
1977                                              "  pos.xyz += w * gl_in[2].gl_Position.xyz;\n"
1978                                              "  color.xyz += w * colors[2].xyz;\n"
1979                                              "  pos.w = 1.0;\n"
1980                                              "  color.w = 1.0;\n"
1981                                              "  gl_Position = pos;\n"
1982                                              "  vtxColor = color;\n"
1983                                              "}\n");
1984 }
1985 
createInstance(Context & context) const1986 TestInstance *AdvGraphicsTest::createInstance(Context &context) const
1987 {
1988     return new AdvGraphicsTestInstance(context, m_pipelineConstructionType, m_stages, m_inRenderPass, m_hostQueryReset,
1989                                        m_queryResultFlags);
1990 }
1991 
featureSupportCheck(void)1992 void AdvGraphicsTestInstance::featureSupportCheck(void)
1993 {
1994     for (StageFlagVector::const_iterator it = m_stages.begin(); it != m_stages.end(); it++)
1995     {
1996         switch (*it)
1997         {
1998         case VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT:
1999             if (m_features.geometryShader == VK_FALSE)
2000             {
2001                 TCU_THROW(NotSupportedError, "Geometry Shader Not Supported");
2002             }
2003             break;
2004         case VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT:
2005         case VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT:
2006             if (m_features.tessellationShader == VK_FALSE)
2007             {
2008                 TCU_THROW(NotSupportedError, "Tessellation Not Supported");
2009             }
2010             break;
2011         case VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT:
2012         default:
2013             break;
2014         }
2015     }
2016 }
2017 
AdvGraphicsTestInstance(Context & context,const PipelineConstructionType pipelineConstructionType,const StageFlagVector stages,const bool inRenderPass,const bool hostQueryReset,const VkQueryResultFlags queryResultFlags)2018 AdvGraphicsTestInstance::AdvGraphicsTestInstance(Context &context,
2019                                                  const PipelineConstructionType pipelineConstructionType,
2020                                                  const StageFlagVector stages, const bool inRenderPass,
2021                                                  const bool hostQueryReset, const VkQueryResultFlags queryResultFlags)
2022     : BasicGraphicsTestInstance(context, pipelineConstructionType, stages, inRenderPass, hostQueryReset,
2023                                 queryResultFlags)
2024     , m_features(context.getDeviceFeatures())
2025 {
2026 
2027     const DeviceInterface &vk = m_context.getDeviceInterface();
2028 
2029     // If necessary feature is not supported, throw error and fail current test
2030     featureSupportCheck();
2031 
2032     // Prepare the indirect draw buffer
2033     if (m_features.multiDrawIndirect == VK_TRUE)
2034     {
2035         m_draw_count = 2;
2036     }
2037     else
2038     {
2039         m_draw_count = 1;
2040     }
2041 
2042     m_indirectBuffer = createBufferAndBindMemory(32u, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, &m_indirectBufferAlloc);
2043 
2044     const VkDrawIndirectCommand indirectCmds[] = {
2045         {
2046             12u, // uint32_t    vertexCount;
2047             1u,  // uint32_t    instanceCount;
2048             0u,  // uint32_t    firstVertex;
2049             0u,  // uint32_t    firstInstance;
2050         },
2051         {
2052             12u, // uint32_t    vertexCount;
2053             1u,  // uint32_t    instanceCount;
2054             11u, // uint32_t    firstVertex;
2055             0u,  // uint32_t    firstInstance;
2056         },
2057     };
2058 
2059     // Load data into indirect draw buffer
2060     deMemcpy(m_indirectBufferAlloc->getHostPtr(), indirectCmds, m_draw_count * sizeof(VkDrawIndirectCommand));
2061     flushAlloc(vk, m_device, *m_indirectBufferAlloc);
2062 }
2063 
~AdvGraphicsTestInstance(void)2064 AdvGraphicsTestInstance::~AdvGraphicsTestInstance(void)
2065 {
2066 }
2067 
buildPipeline(void)2068 void AdvGraphicsTestInstance::buildPipeline(void)
2069 {
2070     const DeviceInterface &vk = m_context.getDeviceInterface();
2071 
2072     const std::vector<VkViewport> viewports{makeViewport(m_renderSize)};
2073     const std::vector<VkRect2D> scissors{makeRect2D(m_renderSize)};
2074 
2075     ShaderWrapper vertShaderModule = ShaderWrapper(vk, m_device, m_context.getBinaryCollection().get("color_vert"), 0);
2076     ShaderWrapper fragShaderModule = ShaderWrapper(vk, m_device, m_context.getBinaryCollection().get("color_frag"), 0);
2077     ShaderWrapper tescShaderModule;
2078     ShaderWrapper teseShaderModule;
2079     ShaderWrapper geomShaderModule;
2080 
2081     if (m_features.tessellationShader)
2082     {
2083         tescShaderModule = ShaderWrapper(vk, m_device, m_context.getBinaryCollection().get("basic_tcs"), 0);
2084         teseShaderModule = ShaderWrapper(vk, m_device, m_context.getBinaryCollection().get("basic_tes"), 0);
2085     }
2086 
2087     if (m_features.geometryShader)
2088         geomShaderModule = ShaderWrapper(vk, m_device, m_context.getBinaryCollection().get("unused_geo"), 0);
2089 
2090     // Create pipeline
2091     m_graphicsPipeline
2092         .setDefaultTopology(m_features.tessellationShader ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST :
2093                                                             VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
2094         .setDefaultRasterizationState()
2095         .setDefaultColorBlendState()
2096         .setDefaultMultisampleState()
2097         .setupVertexInputState(&defaultVertexInputStateParams)
2098         .setupPreRasterizationShaderState(viewports, scissors, m_pipelineLayout, *m_renderPass, 0u, vertShaderModule,
2099                                           nullptr, tescShaderModule, teseShaderModule, geomShaderModule)
2100         .setupFragmentShaderState(m_pipelineLayout, *m_renderPass, 0u, fragShaderModule,
2101                                   &defaultDepthStencilStateParams)
2102         .setupFragmentOutputState(*m_renderPass)
2103         .setMonolithicPipelineLayout(m_pipelineLayout)
2104         .buildPipeline();
2105 }
2106 
configCommandBuffer(void)2107 void AdvGraphicsTestInstance::configCommandBuffer(void)
2108 {
2109     const DeviceInterface &vk = m_context.getDeviceInterface();
2110 
2111     const VkClearValue attachmentClearValues[2] = {
2112         defaultClearValue(m_colorFormat),
2113         defaultClearValue(m_depthFormat),
2114     };
2115 
2116     beginCommandBuffer(vk, *m_cmdBuffer, 0u);
2117 
2118     vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
2119                           VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,
2120                           (VkDependencyFlags)0, 0u, nullptr, 0u, nullptr, DE_LENGTH_OF_ARRAY(m_imageLayoutBarriers),
2121                           m_imageLayoutBarriers);
2122 
2123     if (!m_hostQueryReset)
2124         vk.cmdResetQueryPool(*m_cmdBuffer, *m_queryPool, 0u, TimestampTest::ENTRY_COUNT);
2125 
2126     m_renderPass.begin(vk, *m_cmdBuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), 2u,
2127                        attachmentClearValues);
2128 
2129     m_graphicsPipeline.bind(*m_cmdBuffer);
2130 
2131     VkDeviceSize offsets = 0u;
2132     vk.cmdBindVertexBuffers(*m_cmdBuffer, 0u, 1u, &m_vertexBuffer.get(), &offsets);
2133 
2134     vk.cmdDrawIndirect(*m_cmdBuffer, *m_indirectBuffer, 0u, m_draw_count, sizeof(VkDrawIndirectCommand));
2135 
2136     if (m_inRenderPass)
2137     {
2138         uint32_t timestampEntry = 0u;
2139         for (StageFlagVector::const_iterator it = m_stages.begin(); it != m_stages.end(); it++)
2140         {
2141             vk.cmdWriteTimestamp(*m_cmdBuffer, *it, *m_queryPool, timestampEntry++);
2142         }
2143     }
2144 
2145     m_renderPass.end(vk, *m_cmdBuffer);
2146 
2147     if (!m_inRenderPass)
2148     {
2149         uint32_t timestampEntry = 0u;
2150         for (StageFlagVector::const_iterator it = m_stages.begin(); it != m_stages.end(); it++)
2151         {
2152             vk.cmdWriteTimestamp(*m_cmdBuffer, *it, *m_queryPool, timestampEntry++);
2153         }
2154     }
2155 
2156     endCommandBuffer(vk, *m_cmdBuffer);
2157 }
2158 
2159 class BasicComputeTest : public TimestampTest
2160 {
2161 public:
BasicComputeTest(tcu::TestContext & testContext,const std::string & name,const TimestampTestParam * param)2162     BasicComputeTest(tcu::TestContext &testContext, const std::string &name, const TimestampTestParam *param)
2163         : TimestampTest(testContext, name, param)
2164     {
2165     }
2166 
~BasicComputeTest(void)2167     virtual ~BasicComputeTest(void)
2168     {
2169     }
2170     virtual void initPrograms(SourceCollections &programCollection) const;
2171     virtual TestInstance *createInstance(Context &context) const;
2172 };
2173 
2174 class BasicComputeTestInstance : public TimestampTestInstance
2175 {
2176 public:
2177     BasicComputeTestInstance(Context &context, const StageFlagVector stages, const bool inRenderPass,
2178                              const bool hostQueryReset, VkQueryResultFlags VkQueryResultFlags);
2179 
2180     virtual ~BasicComputeTestInstance(void);
2181     virtual void configCommandBuffer(void);
2182 
2183 protected:
2184     de::MovePtr<Allocation> m_inputBufAlloc;
2185     Move<VkBuffer> m_inputBuf;
2186     de::MovePtr<Allocation> m_outputBufAlloc;
2187     Move<VkBuffer> m_outputBuf;
2188 
2189     Move<VkDescriptorPool> m_descriptorPool;
2190     Move<VkDescriptorSet> m_descriptorSet;
2191     Move<VkDescriptorSetLayout> m_descriptorSetLayout;
2192 
2193     Move<VkPipelineLayout> m_pipelineLayout;
2194     Move<VkShaderModule> m_computeShaderModule;
2195     Move<VkPipeline> m_computePipelines;
2196 };
2197 
initPrograms(SourceCollections & programCollection) const2198 void BasicComputeTest::initPrograms(SourceCollections &programCollection) const
2199 {
2200     TimestampTest::initPrograms(programCollection);
2201 
2202     programCollection.glslSources.add("basic_compute") << glu::ComputeSource(
2203         "#version 310 es\n"
2204         "layout(local_size_x = 128) in;\n"
2205         "layout(std430) buffer;\n"
2206         "layout(binding = 0) readonly buffer Input0\n"
2207         "{\n"
2208         "  vec4 elements[];\n"
2209         "} input_data0;\n"
2210         "layout(binding = 1) writeonly buffer Output\n"
2211         "{\n"
2212         "  vec4 elements[];\n"
2213         "} output_data;\n"
2214         "void main()\n"
2215         "{\n"
2216         "  uint ident = gl_GlobalInvocationID.x;\n"
2217         "  output_data.elements[ident] = input_data0.elements[ident] * input_data0.elements[ident];\n"
2218         "}");
2219 }
2220 
createInstance(Context & context) const2221 TestInstance *BasicComputeTest::createInstance(Context &context) const
2222 {
2223     return new BasicComputeTestInstance(context, m_stages, m_inRenderPass, m_hostQueryReset, m_queryResultFlags);
2224 }
2225 
BasicComputeTestInstance(Context & context,const StageFlagVector stages,const bool inRenderPass,const bool hostQueryReset,VkQueryResultFlags VkQueryResultFlags)2226 BasicComputeTestInstance::BasicComputeTestInstance(Context &context, const StageFlagVector stages,
2227                                                    const bool inRenderPass, const bool hostQueryReset,
2228                                                    VkQueryResultFlags VkQueryResultFlags)
2229     : TimestampTestInstance(context, stages, inRenderPass, hostQueryReset, false, VkQueryResultFlags)
2230 {
2231     const DeviceInterface &vk = context.getDeviceInterface();
2232     const VkDevice vkDevice   = context.getDevice();
2233 
2234     // Create buffer object, allocate storage, and generate input data
2235     const VkDeviceSize size = sizeof(tcu::Vec4) * 128u * 128u;
2236 
2237     m_inputBuf = createBufferAndBindMemory(size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, &m_inputBufAlloc);
2238 
2239     // Load vertices into buffer
2240     tcu::Vec4 *pVec = reinterpret_cast<tcu::Vec4 *>(m_inputBufAlloc->getHostPtr());
2241 
2242     for (uint32_t ndx = 0u; ndx < (128u * 128u); ndx++)
2243     {
2244         for (uint32_t component = 0u; component < 4u; component++)
2245         {
2246             pVec[ndx][component] = (float)(ndx * (component + 1u));
2247         }
2248     }
2249 
2250     flushAlloc(vk, vkDevice, *m_inputBufAlloc);
2251 
2252     m_outputBuf = createBufferAndBindMemory(size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, &m_outputBufAlloc);
2253 
2254     std::vector<VkDescriptorBufferInfo> descriptorInfos;
2255 
2256     descriptorInfos.push_back(makeDescriptorBufferInfo(*m_inputBuf, 0u, size));
2257     descriptorInfos.push_back(makeDescriptorBufferInfo(*m_outputBuf, 0u, size));
2258 
2259     // Create descriptor set layout
2260     DescriptorSetLayoutBuilder descLayoutBuilder;
2261 
2262     for (uint32_t bindingNdx = 0u; bindingNdx < 2u; bindingNdx++)
2263     {
2264         descLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT);
2265     }
2266 
2267     m_descriptorSetLayout = descLayoutBuilder.build(vk, vkDevice);
2268 
2269     // Create descriptor pool
2270     m_descriptorPool = DescriptorPoolBuilder()
2271                            .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 2)
2272                            .build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
2273 
2274     // Create descriptor set
2275     const VkDescriptorSetAllocateInfo descriptorSetAllocInfo = {
2276         VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType                 sType;
2277         nullptr,                                        // const void*                     pNext;
2278         *m_descriptorPool,                              // VkDescriptorPool                descriptorPool;
2279         1u,                                             // uint32_t                        setLayoutCount;
2280         &m_descriptorSetLayout.get(),                   // const VkDescriptorSetLayout*    pSetLayouts;
2281     };
2282     m_descriptorSet = allocateDescriptorSet(vk, vkDevice, &descriptorSetAllocInfo);
2283 
2284     DescriptorSetUpdateBuilder builder;
2285     for (uint32_t descriptorNdx = 0u; descriptorNdx < 2u; descriptorNdx++)
2286     {
2287         builder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(descriptorNdx),
2288                             VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorInfos[descriptorNdx]);
2289     }
2290     builder.update(vk, vkDevice);
2291 
2292     // Create compute pipeline layout
2293     const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
2294         VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType                 sType;
2295         nullptr,                                       // const void*                     pNext;
2296         0u,                                            // VkPipelineLayoutCreateFlags     flags;
2297         1u,                                            // uint32_t                        setLayoutCount;
2298         &m_descriptorSetLayout.get(),                  // const VkDescriptorSetLayout*    pSetLayouts;
2299         0u,                                            // uint32_t                        pushConstantRangeCount;
2300         nullptr,                                       // const VkPushConstantRange*      pPushConstantRanges;
2301     };
2302 
2303     m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutCreateInfo);
2304 
2305     // Create compute shader
2306     VkShaderModuleCreateInfo shaderModuleCreateInfo = {
2307         VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,                    // VkStructureType             sType;
2308         nullptr,                                                        // const void*                 pNext;
2309         0u,                                                             // VkShaderModuleCreateFlags   flags;
2310         m_context.getBinaryCollection().get("basic_compute").getSize(), // uintptr_t                   codeSize;
2311         (uint32_t *)m_context.getBinaryCollection()
2312             .get("basic_compute")
2313             .getBinary(), // const uint32_t*             pCode;
2314 
2315     };
2316 
2317     m_computeShaderModule = createShaderModule(vk, vkDevice, &shaderModuleCreateInfo);
2318 
2319     // Create compute pipeline
2320     const VkPipelineShaderStageCreateInfo stageCreateInfo = {
2321         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType                     sType;
2322         nullptr,                                             // const void*                         pNext;
2323         0u,                                                  // VkPipelineShaderStageCreateFlags    flags;
2324         VK_SHADER_STAGE_COMPUTE_BIT,                         // VkShaderStageFlagBits               stage;
2325         *m_computeShaderModule,                              // VkShaderModule                      module;
2326         "main",                                              // const char*                         pName;
2327         nullptr,                                             // const VkSpecializationInfo*         pSpecializationInfo;
2328     };
2329 
2330     const VkComputePipelineCreateInfo pipelineCreateInfo = {
2331         VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType                 sType;
2332         nullptr,                                        // const void*                     pNext;
2333         0u,                                             // VkPipelineCreateFlags           flags;
2334         stageCreateInfo,                                // VkPipelineShaderStageCreateInfo stage;
2335         *m_pipelineLayout,                              // VkPipelineLayout                layout;
2336         VK_NULL_HANDLE,                                 // VkPipeline                      basePipelineHandle;
2337         0u,                                             // int32_t                         basePipelineIndex;
2338     };
2339 
2340     m_computePipelines = createComputePipeline(vk, vkDevice, VK_NULL_HANDLE, &pipelineCreateInfo);
2341 }
2342 
~BasicComputeTestInstance(void)2343 BasicComputeTestInstance::~BasicComputeTestInstance(void)
2344 {
2345 }
2346 
configCommandBuffer(void)2347 void BasicComputeTestInstance::configCommandBuffer(void)
2348 {
2349     const DeviceInterface &vk = m_context.getDeviceInterface();
2350 
2351     beginCommandBuffer(vk, *m_cmdBuffer, 0u);
2352 
2353     if (!m_hostQueryReset)
2354         vk.cmdResetQueryPool(*m_cmdBuffer, *m_queryPool, 0u, TimestampTest::ENTRY_COUNT);
2355 
2356     vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_computePipelines);
2357     vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipelineLayout, 0u, 1u,
2358                              &m_descriptorSet.get(), 0u, nullptr);
2359     vk.cmdDispatch(*m_cmdBuffer, 128u, 1u, 1u);
2360 
2361     uint32_t timestampEntry = 0u;
2362     for (StageFlagVector::const_iterator it = m_stages.begin(); it != m_stages.end(); it++)
2363     {
2364         vk.cmdWriteTimestamp(*m_cmdBuffer, *it, *m_queryPool, timestampEntry++);
2365     }
2366 
2367     endCommandBuffer(vk, *m_cmdBuffer);
2368 }
2369 
2370 class TransferTest : public TimestampTest
2371 {
2372 public:
2373     TransferTest(tcu::TestContext &testContext, const std::string &name, const TimestampTestParam *param);
2374 
~TransferTest(void)2375     virtual ~TransferTest(void)
2376     {
2377     }
2378     virtual void initPrograms(SourceCollections &programCollection) const;
2379     virtual TestInstance *createInstance(Context &context) const;
2380 
2381 protected:
2382     TransferMethod m_method;
2383 };
2384 
2385 class TransferTestInstance : public TimestampTestInstance
2386 {
2387 public:
2388     TransferTestInstance(Context &context, const StageFlagVector stages, const bool inRenderPass,
2389                          const bool hostQueryReset, const bool transferOnlyQueue, const TransferMethod method,
2390                          const VkQueryResultFlags queryResultFlags);
2391 
2392     virtual ~TransferTestInstance(void);
2393     virtual void configCommandBuffer(void);
2394     virtual void initialImageTransition(VkCommandBuffer cmdBuffer, VkImage image, VkImageSubresourceRange subRange,
2395                                         VkImageLayout layout);
2396 
2397 protected:
2398     TransferMethod m_method;
2399 
2400     VkDeviceSize m_bufSize;
2401     Move<VkBuffer> m_srcBuffer;
2402     Move<VkBuffer> m_dstBuffer;
2403     de::MovePtr<Allocation> m_srcBufferAlloc;
2404     de::MovePtr<Allocation> m_dstBufferAlloc;
2405 
2406     VkFormat m_imageFormat;
2407     int32_t m_imageWidth;
2408     int32_t m_imageHeight;
2409     VkDeviceSize m_imageSize;
2410     Move<VkImage> m_srcImage;
2411     Move<VkImage> m_dstImage;
2412     Move<VkImage> m_depthImage;
2413     Move<VkImage> m_msImage;
2414     de::MovePtr<Allocation> m_srcImageAlloc;
2415     de::MovePtr<Allocation> m_dstImageAlloc;
2416     de::MovePtr<Allocation> m_depthImageAlloc;
2417     de::MovePtr<Allocation> m_msImageAlloc;
2418 };
2419 
TransferTest(tcu::TestContext & testContext,const std::string & name,const TimestampTestParam * param)2420 TransferTest::TransferTest(tcu::TestContext &testContext, const std::string &name, const TimestampTestParam *param)
2421     : TimestampTest(testContext, name, param)
2422 {
2423     const TransferTimestampTestParam *transferParam = dynamic_cast<const TransferTimestampTestParam *>(param);
2424     m_method                                        = transferParam->getMethod();
2425 }
2426 
initPrograms(SourceCollections & programCollection) const2427 void TransferTest::initPrograms(SourceCollections &programCollection) const
2428 {
2429     TimestampTest::initPrograms(programCollection);
2430 }
2431 
createInstance(Context & context) const2432 TestInstance *TransferTest::createInstance(Context &context) const
2433 {
2434     return new TransferTestInstance(context, m_stages, m_inRenderPass, m_hostQueryReset, m_transferOnlyQueue, m_method,
2435                                     m_queryResultFlags);
2436 }
2437 
TransferTestInstance(Context & context,const StageFlagVector stages,const bool inRenderPass,const bool hostQueryReset,const bool transferOnlyQueue,const TransferMethod method,const VkQueryResultFlags queryResultFlags)2438 TransferTestInstance::TransferTestInstance(Context &context, const StageFlagVector stages, const bool inRenderPass,
2439                                            const bool hostQueryReset, const bool transferOnlyQueue,
2440                                            const TransferMethod method, const VkQueryResultFlags queryResultFlags)
2441     : TimestampTestInstance(context, stages, inRenderPass, hostQueryReset, transferOnlyQueue, queryResultFlags)
2442     , m_method(method)
2443     , m_bufSize((queryResultFlags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT) ? 512u : 256u)
2444     , m_imageFormat(VK_FORMAT_R8G8B8A8_UNORM)
2445     , m_imageWidth(4u)
2446     , m_imageHeight(4u)
2447     , m_imageSize(256u)
2448 {
2449     const DeviceInterface &vk = context.getDeviceInterface();
2450 
2451     // Create src buffer
2452     m_srcBuffer = createBufferAndBindMemory(
2453         m_bufSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT, &m_srcBufferAlloc);
2454 
2455     // Init the source buffer memory
2456     char *pBuf = reinterpret_cast<char *>(m_srcBufferAlloc->getHostPtr());
2457     deMemset(pBuf, 0xFF, sizeof(char) * (size_t)m_bufSize);
2458     flushAlloc(vk, m_device, *m_srcBufferAlloc);
2459 
2460     // Create dst buffer
2461     m_dstBuffer = createBufferAndBindMemory(
2462         m_bufSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, &m_dstBufferAlloc);
2463 
2464     // Create src/dst/depth image
2465     m_srcImage = createImage2DAndBindMemory(m_imageFormat, m_imageWidth, m_imageHeight,
2466                                             VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
2467                                             VK_SAMPLE_COUNT_1_BIT, &m_srcImageAlloc);
2468     m_dstImage = createImage2DAndBindMemory(m_imageFormat, m_imageWidth, m_imageHeight,
2469                                             VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
2470                                             VK_SAMPLE_COUNT_1_BIT, &m_dstImageAlloc);
2471     m_depthImage =
2472         createImage2DAndBindMemory(VK_FORMAT_D16_UNORM, m_imageWidth, m_imageHeight, VK_IMAGE_USAGE_TRANSFER_DST_BIT,
2473                                    VK_SAMPLE_COUNT_1_BIT, &m_depthImageAlloc);
2474     m_msImage = createImage2DAndBindMemory(m_imageFormat, m_imageWidth, m_imageHeight,
2475                                            VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
2476                                                VK_IMAGE_USAGE_TRANSFER_DST_BIT,
2477                                            VK_SAMPLE_COUNT_4_BIT, &m_msImageAlloc);
2478 }
2479 
~TransferTestInstance(void)2480 TransferTestInstance::~TransferTestInstance(void)
2481 {
2482 }
2483 
configCommandBuffer(void)2484 void TransferTestInstance::configCommandBuffer(void)
2485 {
2486     const DeviceInterface &vk = m_context.getDeviceInterface();
2487 
2488     beginCommandBuffer(vk, *m_cmdBuffer, 0u);
2489 
2490     // Initialize buffer/image
2491     vk.cmdFillBuffer(*m_cmdBuffer, *m_dstBuffer, 0u, m_bufSize, 0x0);
2492 
2493     const VkClearColorValue srcClearValue              = {{1.0f, 1.0f, 1.0f, 1.0f}};
2494     const VkClearColorValue dstClearValue              = {{0.0f, 0.0f, 0.0f, 0.0f}};
2495     const struct VkImageSubresourceRange subRangeColor = {
2496         VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags  aspectMask;
2497         0u,                        // uint32_t            baseMipLevel;
2498         1u,                        // uint32_t            mipLevels;
2499         0u,                        // uint32_t            baseArrayLayer;
2500         1u,                        // uint32_t            arraySize;
2501     };
2502     const struct VkImageSubresourceRange subRangeDepth = {
2503         VK_IMAGE_ASPECT_DEPTH_BIT, // VkImageAspectFlags  aspectMask;
2504         0u,                        // uint32_t            baseMipLevel;
2505         1u,                        // uint32_t            mipLevels;
2506         0u,                        // uint32_t            baseArrayLayer;
2507         1u,                        // uint32_t            arraySize;
2508     };
2509 
2510     initialImageTransition(*m_cmdBuffer, *m_srcImage, subRangeColor, VK_IMAGE_LAYOUT_GENERAL);
2511     initialImageTransition(*m_cmdBuffer, *m_dstImage, subRangeColor, VK_IMAGE_LAYOUT_GENERAL);
2512 
2513     if (!m_transferOnlyQueue)
2514     {
2515         vk.cmdClearColorImage(*m_cmdBuffer, *m_srcImage, VK_IMAGE_LAYOUT_GENERAL, &srcClearValue, 1u, &subRangeColor);
2516         vk.cmdClearColorImage(*m_cmdBuffer, *m_dstImage, VK_IMAGE_LAYOUT_GENERAL, &dstClearValue, 1u, &subRangeColor);
2517     }
2518 
2519     // synchronize the Clear commands before starting any copy
2520     const vk::VkMemoryBarrier barrier = {
2521         vk::VK_STRUCTURE_TYPE_MEMORY_BARRIER,                           // VkStructureType sType;
2522         nullptr,                                                        // const void* pNext;
2523         vk::VK_ACCESS_TRANSFER_WRITE_BIT,                               // VkAccessFlags srcAccessMask;
2524         vk::VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask;
2525     };
2526     vk.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 1u,
2527                           &barrier, 0u, nullptr, 0u, nullptr);
2528 
2529     if (!m_hostQueryReset)
2530         vk.cmdResetQueryPool(*m_cmdBuffer, *m_queryPool, 0u, TimestampTest::ENTRY_COUNT);
2531 
2532     // Copy Operations
2533     const VkImageSubresourceLayers imgSubResCopy = {
2534         VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags  aspectMask;
2535         0u,                        // uint32_t            mipLevel;
2536         0u,                        // uint32_t            baseArrayLayer;
2537         1u,                        // uint32_t            layerCount;
2538     };
2539 
2540     const VkOffset3D nullOffset  = {0u, 0u, 0u};
2541     const VkExtent3D imageExtent = {(uint32_t)m_imageWidth, (uint32_t)m_imageHeight, 1u};
2542     const VkOffset3D imageOffset = {(int)m_imageWidth, (int)m_imageHeight, 1};
2543 
2544     switch (m_method)
2545     {
2546     case TRANSFER_METHOD_COPY_BUFFER:
2547     {
2548         const VkBufferCopy copyBufRegion = {
2549             0u,        // VkDeviceSize    srcOffset;
2550             0u,        // VkDeviceSize    destOffset;
2551             m_bufSize, // VkDeviceSize    copySize;
2552         };
2553 
2554         vk.cmdCopyBuffer(*m_cmdBuffer, *m_srcBuffer, *m_dstBuffer, 1u, &copyBufRegion);
2555         break;
2556     }
2557     case TRANSFER_METHOD_COPY_IMAGE:
2558     {
2559         const VkImageCopy copyImageRegion = {
2560             imgSubResCopy, // VkImageSubresourceCopy  srcSubresource;
2561             nullOffset,    // VkOffset3D              srcOffset;
2562             imgSubResCopy, // VkImageSubresourceCopy  destSubresource;
2563             nullOffset,    // VkOffset3D              destOffset;
2564             imageExtent,   // VkExtent3D              extent;
2565 
2566         };
2567 
2568         vk.cmdCopyImage(*m_cmdBuffer, *m_srcImage, VK_IMAGE_LAYOUT_GENERAL, *m_dstImage, VK_IMAGE_LAYOUT_GENERAL, 1u,
2569                         &copyImageRegion);
2570         break;
2571     }
2572     case TRANSFER_METHOD_COPY_BUFFER_TO_IMAGE:
2573     {
2574         const VkBufferImageCopy bufImageCopy = {
2575             0u,                      // VkDeviceSize            bufferOffset;
2576             (uint32_t)m_imageWidth,  // uint32_t                bufferRowLength;
2577             (uint32_t)m_imageHeight, // uint32_t                bufferImageHeight;
2578             imgSubResCopy,           // VkImageSubresourceCopy  imageSubresource;
2579             nullOffset,              // VkOffset3D              imageOffset;
2580             imageExtent,             // VkExtent3D              imageExtent;
2581         };
2582 
2583         vk.cmdCopyBufferToImage(*m_cmdBuffer, *m_srcBuffer, *m_dstImage, VK_IMAGE_LAYOUT_GENERAL, 1u, &bufImageCopy);
2584         break;
2585     }
2586     case TRANSFER_METHOD_COPY_IMAGE_TO_BUFFER:
2587     {
2588         const VkBufferImageCopy imgBufferCopy = {
2589             0u,                      // VkDeviceSize            bufferOffset;
2590             (uint32_t)m_imageWidth,  // uint32_t                bufferRowLength;
2591             (uint32_t)m_imageHeight, // uint32_t                bufferImageHeight;
2592             imgSubResCopy,           // VkImageSubresourceCopy  imageSubresource;
2593             nullOffset,              // VkOffset3D              imageOffset;
2594             imageExtent,             // VkExtent3D              imageExtent;
2595         };
2596 
2597         vk.cmdCopyImageToBuffer(*m_cmdBuffer, *m_srcImage, VK_IMAGE_LAYOUT_GENERAL, *m_dstBuffer, 1u, &imgBufferCopy);
2598         break;
2599     }
2600     case TRANSFER_METHOD_BLIT_IMAGE:
2601     {
2602         const VkImageBlit imageBlt = {imgSubResCopy, // VkImageSubresourceCopy  srcSubresource;
2603                                       {
2604                                           nullOffset,
2605                                           imageOffset,
2606                                       },
2607                                       imgSubResCopy, // VkImageSubresourceCopy  destSubresource;
2608                                       {
2609                                           nullOffset,
2610                                           imageOffset,
2611                                       }};
2612 
2613         vk.cmdBlitImage(*m_cmdBuffer, *m_srcImage, VK_IMAGE_LAYOUT_GENERAL, *m_dstImage, VK_IMAGE_LAYOUT_GENERAL, 1u,
2614                         &imageBlt, VK_FILTER_NEAREST);
2615         break;
2616     }
2617     case TRANSFER_METHOD_CLEAR_COLOR_IMAGE:
2618     {
2619         vk.cmdClearColorImage(*m_cmdBuffer, *m_dstImage, VK_IMAGE_LAYOUT_GENERAL, &srcClearValue, 1u, &subRangeColor);
2620         break;
2621     }
2622     case TRANSFER_METHOD_CLEAR_DEPTH_STENCIL_IMAGE:
2623     {
2624         initialImageTransition(*m_cmdBuffer, *m_depthImage, subRangeDepth, VK_IMAGE_LAYOUT_GENERAL);
2625 
2626         const VkClearDepthStencilValue clearDSValue = {
2627             1.0f, // float       depth;
2628             0u,   // uint32_t    stencil;
2629         };
2630 
2631         vk.cmdClearDepthStencilImage(*m_cmdBuffer, *m_depthImage, VK_IMAGE_LAYOUT_GENERAL, &clearDSValue, 1u,
2632                                      &subRangeDepth);
2633         break;
2634     }
2635     case TRANSFER_METHOD_FILL_BUFFER:
2636     {
2637         vk.cmdFillBuffer(*m_cmdBuffer, *m_dstBuffer, 0u, m_bufSize, 0x0);
2638         break;
2639     }
2640     case TRANSFER_METHOD_UPDATE_BUFFER:
2641     {
2642         const uint32_t data[] = {0xdeadbeef, 0xabcdef00, 0x12345678};
2643 
2644         vk.cmdUpdateBuffer(*m_cmdBuffer, *m_dstBuffer, 0x10, sizeof(data), data);
2645         break;
2646     }
2647     case TRANSFER_METHOD_COPY_QUERY_POOL_RESULTS:
2648     case TRANSFER_METHOD_COPY_QUERY_POOL_RESULTS_STRIDE_ZERO:
2649     {
2650         vk.cmdWriteTimestamp(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, *m_queryPool, 0u);
2651         VkDeviceSize copyStride = m_method == TRANSFER_METHOD_COPY_QUERY_POOL_RESULTS_STRIDE_ZERO ? 0u : 8u;
2652         vk.cmdCopyQueryPoolResults(*m_cmdBuffer, *m_queryPool, 0u, 1u, *m_dstBuffer, 0u, copyStride,
2653                                    VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT);
2654 
2655         const vk::VkBufferMemoryBarrier bufferBarrier = {
2656             vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
2657             nullptr,                                     // const void* pNext;
2658             vk::VK_ACCESS_TRANSFER_WRITE_BIT,            // VkAccessFlags srcAccessMask;
2659             vk::VK_ACCESS_HOST_READ_BIT,                 // VkAccessFlags dstAccessMask;
2660             VK_QUEUE_FAMILY_IGNORED,                     // uint32_t srcQueueFamilyIndex;
2661             VK_QUEUE_FAMILY_IGNORED,                     // uint32_t dstQueueFamilyIndex;
2662             *m_dstBuffer,                                // VkBuffer buffer;
2663             0ull,                                        // VkDeviceSize offset;
2664             VK_WHOLE_SIZE                                // VkDeviceSize size;
2665         };
2666 
2667         vk.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u,
2668                               nullptr, 1u, &bufferBarrier, 0u, nullptr);
2669 
2670         vk.cmdResetQueryPool(*m_cmdBuffer, *m_queryPool, 0u, 1u);
2671         break;
2672     }
2673     case TRANSFER_METHOD_RESOLVE_IMAGE:
2674     {
2675         const VkImageResolve imageResolve = {
2676             imgSubResCopy, // VkImageSubresourceLayers  srcSubresource;
2677             nullOffset,    // VkOffset3D                srcOffset;
2678             imgSubResCopy, // VkImageSubresourceLayers  destSubresource;
2679             nullOffset,    // VkOffset3D                destOffset;
2680             imageExtent,   // VkExtent3D                extent;
2681         };
2682 
2683         initialImageTransition(*m_cmdBuffer, *m_msImage, subRangeColor, VK_IMAGE_LAYOUT_GENERAL);
2684         vk.cmdClearColorImage(*m_cmdBuffer, *m_msImage, VK_IMAGE_LAYOUT_GENERAL, &srcClearValue, 1u, &subRangeColor);
2685         vk.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
2686                               1u, &barrier, 0u, nullptr, 0u, nullptr);
2687         vk.cmdResolveImage(*m_cmdBuffer, *m_msImage, VK_IMAGE_LAYOUT_GENERAL, *m_dstImage, VK_IMAGE_LAYOUT_GENERAL, 1u,
2688                            &imageResolve);
2689         break;
2690     }
2691     default:
2692         DE_FATAL("Unknown Transfer Method!");
2693         break;
2694     }
2695 
2696     uint32_t timestampEntry = 0u;
2697 
2698     for (StageFlagVector::const_iterator it = m_stages.begin(); it != m_stages.end(); it++)
2699     {
2700         vk.cmdWriteTimestamp(*m_cmdBuffer, *it, *m_queryPool, timestampEntry++);
2701     }
2702 
2703     endCommandBuffer(vk, *m_cmdBuffer);
2704 }
2705 
initialImageTransition(VkCommandBuffer cmdBuffer,VkImage image,VkImageSubresourceRange subRange,VkImageLayout layout)2706 void TransferTestInstance::initialImageTransition(VkCommandBuffer cmdBuffer, VkImage image,
2707                                                   VkImageSubresourceRange subRange, VkImageLayout layout)
2708 {
2709     const DeviceInterface &vk = m_context.getDeviceInterface();
2710 
2711     const VkImageMemoryBarrier imageMemBarrier = {
2712         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType          sType;
2713         nullptr,                                // const void*              pNext;
2714         0u,                                     // VkAccessFlags            srcAccessMask;
2715         VK_ACCESS_TRANSFER_WRITE_BIT,           // VkAccessFlags            dstAccessMask;
2716         VK_IMAGE_LAYOUT_UNDEFINED,              // VkImageLayout            oldLayout;
2717         layout,                                 // VkImageLayout            newLayout;
2718         VK_QUEUE_FAMILY_IGNORED,                // uint32_t                 srcQueueFamilyIndex;
2719         VK_QUEUE_FAMILY_IGNORED,                // uint32_t                 dstQueueFamilyIndex;
2720         image,                                  // VkImage                  image;
2721         subRange                                // VkImageSubresourceRange  subresourceRange;
2722     };
2723 
2724     vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0,
2725                           nullptr, 1, &imageMemBarrier);
2726 }
2727 
2728 class FillBufferBeforeCopyTest : public vkt::TestCase
2729 {
2730 public:
FillBufferBeforeCopyTest(tcu::TestContext & testContext,const std::string & name)2731     FillBufferBeforeCopyTest(tcu::TestContext &testContext, const std::string &name) : vkt::TestCase(testContext, name)
2732     {
2733     }
~FillBufferBeforeCopyTest(void)2734     virtual ~FillBufferBeforeCopyTest(void)
2735     {
2736     }
2737     virtual void initPrograms(SourceCollections &programCollection) const;
2738     virtual TestInstance *createInstance(Context &context) const;
2739 };
2740 
2741 class FillBufferBeforeCopyTestInstance : public vkt::TestInstance
2742 {
2743 public:
2744     FillBufferBeforeCopyTestInstance(Context &context);
~FillBufferBeforeCopyTestInstance(void)2745     virtual ~FillBufferBeforeCopyTestInstance(void)
2746     {
2747     }
2748     virtual tcu::TestStatus iterate(void);
2749 
2750 protected:
2751     struct TimestampWithAvailability
2752     {
2753         uint64_t timestamp;
2754         uint64_t availability;
2755     };
2756 
2757     Move<VkCommandPool> m_cmdPool;
2758     Move<VkCommandBuffer> m_cmdBuffer;
2759     Move<VkQueryPool> m_queryPool;
2760 
2761     Move<VkBuffer> m_resultBuffer;
2762     de::MovePtr<Allocation> m_resultBufferMemory;
2763 };
2764 
initPrograms(SourceCollections & programCollection) const2765 void FillBufferBeforeCopyTest::initPrograms(SourceCollections &programCollection) const
2766 {
2767     vkt::TestCase::initPrograms(programCollection);
2768 }
2769 
createInstance(Context & context) const2770 TestInstance *FillBufferBeforeCopyTest::createInstance(Context &context) const
2771 {
2772     return new FillBufferBeforeCopyTestInstance(context);
2773 }
2774 
FillBufferBeforeCopyTestInstance(Context & context)2775 FillBufferBeforeCopyTestInstance::FillBufferBeforeCopyTestInstance(Context &context) : vkt::TestInstance(context)
2776 {
2777     const DeviceInterface &vk       = context.getDeviceInterface();
2778     const VkDevice vkDevice         = context.getDevice();
2779     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
2780     Allocator &allocator            = m_context.getDefaultAllocator();
2781 
2782     // Check support for timestamp queries
2783     checkTimestampsSupported(context.getInstanceInterface(), context.getPhysicalDevice(), queueFamilyIndex);
2784 
2785     const VkQueryPoolCreateInfo queryPoolParams = {
2786         VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, // VkStructureType               sType;
2787         nullptr,                                  // const void*                   pNext;
2788         0u,                                       // VkQueryPoolCreateFlags        flags;
2789         VK_QUERY_TYPE_TIMESTAMP,                  // VkQueryType                   queryType;
2790         1u,                                       // uint32_t                      entryCount;
2791         0u,                                       // VkQueryPipelineStatisticFlags pipelineStatistics;
2792     };
2793 
2794     m_queryPool = createQueryPool(vk, vkDevice, &queryPoolParams);
2795     m_cmdPool   = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
2796     m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2797 
2798     // Create results buffer.
2799     const VkBufferCreateInfo bufferCreateInfo = {
2800         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
2801         nullptr,                              // const void* pNext;
2802         0u,                                   // VkBufferCreateFlags flags;
2803         sizeof(TimestampWithAvailability),    // VkDeviceSize size;
2804         VK_BUFFER_USAGE_TRANSFER_DST_BIT,     // VkBufferUsageFlags usage;
2805         VK_SHARING_MODE_EXCLUSIVE,            // VkSharingMode sharingMode;
2806         1u,                                   // uint32_t queueFamilyIndexCount;
2807         &queueFamilyIndex                     // const uint32_t* pQueueFamilyIndices;
2808     };
2809 
2810     m_resultBuffer = createBuffer(vk, vkDevice, &bufferCreateInfo);
2811     m_resultBufferMemory =
2812         allocator.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_resultBuffer), MemoryRequirement::HostVisible);
2813     VK_CHECK(vk.bindBufferMemory(vkDevice, *m_resultBuffer, m_resultBufferMemory->getMemory(),
2814                                  m_resultBufferMemory->getOffset()));
2815 
2816     const vk::VkBufferMemoryBarrier fillBufferBarrier = {
2817         vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
2818         nullptr,                                     // const void* pNext;
2819         vk::VK_ACCESS_TRANSFER_WRITE_BIT,            // VkAccessFlags srcAccessMask;
2820         vk::VK_ACCESS_TRANSFER_WRITE_BIT,            // VkAccessFlags dstAccessMask;
2821         VK_QUEUE_FAMILY_IGNORED,                     // uint32_t srcQueueFamilyIndex;
2822         VK_QUEUE_FAMILY_IGNORED,                     // uint32_t dstQueueFamilyIndex;
2823         *m_resultBuffer,                             // VkBuffer buffer;
2824         0ull,                                        // VkDeviceSize offset;
2825         VK_WHOLE_SIZE                                // VkDeviceSize size;
2826     };
2827 
2828     const vk::VkBufferMemoryBarrier bufferBarrier = {
2829         vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
2830         nullptr,                                     // const void* pNext;
2831         vk::VK_ACCESS_TRANSFER_WRITE_BIT,            // VkAccessFlags srcAccessMask;
2832         vk::VK_ACCESS_HOST_READ_BIT,                 // VkAccessFlags dstAccessMask;
2833         VK_QUEUE_FAMILY_IGNORED,                     // uint32_t srcQueueFamilyIndex;
2834         VK_QUEUE_FAMILY_IGNORED,                     // uint32_t dstQueueFamilyIndex;
2835         *m_resultBuffer,                             // VkBuffer buffer;
2836         0ull,                                        // VkDeviceSize offset;
2837         VK_WHOLE_SIZE                                // VkDeviceSize size;
2838     };
2839 
2840     // Prepare command buffer.
2841     beginCommandBuffer(vk, *m_cmdBuffer, 0u);
2842     vk.cmdResetQueryPool(*m_cmdBuffer, *m_queryPool, 0u, 1u);
2843     vk.cmdFillBuffer(*m_cmdBuffer, *m_resultBuffer, 0u, bufferCreateInfo.size, 0u);
2844     vk.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u,
2845                           nullptr, 1u, &fillBufferBarrier, 0u, nullptr);
2846     vk.cmdWriteTimestamp(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, *m_queryPool, 0u);
2847     vk.cmdCopyQueryPoolResults(*m_cmdBuffer, *m_queryPool, 0u, 1u, *m_resultBuffer, 0u,
2848                                sizeof(TimestampWithAvailability),
2849                                (VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WITH_AVAILABILITY_BIT));
2850     vk.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u,
2851                           nullptr, 1u, &bufferBarrier, 0u, nullptr);
2852     endCommandBuffer(vk, *m_cmdBuffer);
2853 }
2854 
iterate(void)2855 tcu::TestStatus FillBufferBeforeCopyTestInstance::iterate(void)
2856 {
2857     const DeviceInterface &vk = m_context.getDeviceInterface();
2858     const VkDevice vkDevice   = m_context.getDevice();
2859     const VkQueue queue       = m_context.getUniversalQueue();
2860     TimestampWithAvailability ta;
2861 
2862     submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
2863     invalidateAlloc(vk, vkDevice, *m_resultBufferMemory);
2864     deMemcpy(&ta, m_resultBufferMemory->getHostPtr(), sizeof(ta));
2865     if (ta.availability)
2866     {
2867         if (ta.timestamp == 0)
2868         {
2869             return tcu::TestStatus::fail("Timestamp not written");
2870         }
2871     }
2872     return tcu::TestStatus::pass("Pass");
2873 }
2874 
2875 class ResetTimestampQueryBeforeCopyTest : public vkt::TestCase
2876 {
2877 public:
ResetTimestampQueryBeforeCopyTest(tcu::TestContext & testContext,const std::string & name)2878     ResetTimestampQueryBeforeCopyTest(tcu::TestContext &testContext, const std::string &name)
2879         : vkt::TestCase(testContext, name)
2880     {
2881     }
~ResetTimestampQueryBeforeCopyTest(void)2882     virtual ~ResetTimestampQueryBeforeCopyTest(void)
2883     {
2884     }
2885     virtual void initPrograms(SourceCollections &programCollection) const;
2886     virtual TestInstance *createInstance(Context &context) const;
2887 };
2888 
2889 class ResetTimestampQueryBeforeCopyTestInstance : public vkt::TestInstance
2890 {
2891 public:
2892     ResetTimestampQueryBeforeCopyTestInstance(Context &context);
~ResetTimestampQueryBeforeCopyTestInstance(void)2893     virtual ~ResetTimestampQueryBeforeCopyTestInstance(void)
2894     {
2895     }
2896     virtual tcu::TestStatus iterate(void);
2897 
2898 protected:
2899     struct TimestampWithAvailability
2900     {
2901         uint64_t timestamp;
2902         uint64_t availability;
2903     };
2904 
2905     Move<VkCommandPool> m_cmdPool;
2906     Move<VkCommandBuffer> m_cmdBuffer;
2907     Move<VkQueryPool> m_queryPool;
2908 
2909     Move<VkBuffer> m_resultBuffer;
2910     de::MovePtr<Allocation> m_resultBufferMemory;
2911 };
2912 
initPrograms(SourceCollections & programCollection) const2913 void ResetTimestampQueryBeforeCopyTest::initPrograms(SourceCollections &programCollection) const
2914 {
2915     vkt::TestCase::initPrograms(programCollection);
2916 }
2917 
createInstance(Context & context) const2918 TestInstance *ResetTimestampQueryBeforeCopyTest::createInstance(Context &context) const
2919 {
2920     return new ResetTimestampQueryBeforeCopyTestInstance(context);
2921 }
2922 
ResetTimestampQueryBeforeCopyTestInstance(Context & context)2923 ResetTimestampQueryBeforeCopyTestInstance::ResetTimestampQueryBeforeCopyTestInstance(Context &context)
2924     : vkt::TestInstance(context)
2925 {
2926     const DeviceInterface &vk       = context.getDeviceInterface();
2927     const VkDevice vkDevice         = context.getDevice();
2928     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
2929     Allocator &allocator            = m_context.getDefaultAllocator();
2930 
2931     // Check support for timestamp queries
2932     checkTimestampsSupported(context.getInstanceInterface(), context.getPhysicalDevice(), queueFamilyIndex);
2933 
2934     const VkQueryPoolCreateInfo queryPoolParams = {
2935         VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, // VkStructureType               sType;
2936         nullptr,                                  // const void*                   pNext;
2937         0u,                                       // VkQueryPoolCreateFlags        flags;
2938         VK_QUERY_TYPE_TIMESTAMP,                  // VkQueryType                   queryType;
2939         1u,                                       // uint32_t                      entryCount;
2940         0u,                                       // VkQueryPipelineStatisticFlags pipelineStatistics;
2941     };
2942 
2943     m_queryPool = createQueryPool(vk, vkDevice, &queryPoolParams);
2944     m_cmdPool   = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
2945     m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2946 
2947     // Create results buffer.
2948     const VkBufferCreateInfo bufferCreateInfo = {
2949         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
2950         nullptr,                              // const void* pNext;
2951         0u,                                   // VkBufferCreateFlags flags;
2952         sizeof(TimestampWithAvailability),    // VkDeviceSize size;
2953         VK_BUFFER_USAGE_TRANSFER_DST_BIT,     // VkBufferUsageFlags usage;
2954         VK_SHARING_MODE_EXCLUSIVE,            // VkSharingMode sharingMode;
2955         1u,                                   // uint32_t queueFamilyIndexCount;
2956         &queueFamilyIndex                     // const uint32_t* pQueueFamilyIndices;
2957     };
2958 
2959     m_resultBuffer = createBuffer(vk, vkDevice, &bufferCreateInfo);
2960     m_resultBufferMemory =
2961         allocator.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_resultBuffer), MemoryRequirement::HostVisible);
2962     VK_CHECK(vk.bindBufferMemory(vkDevice, *m_resultBuffer, m_resultBufferMemory->getMemory(),
2963                                  m_resultBufferMemory->getOffset()));
2964 
2965     const vk::VkBufferMemoryBarrier bufferBarrier = {
2966         vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
2967         nullptr,                                     // const void* pNext;
2968         vk::VK_ACCESS_TRANSFER_WRITE_BIT,            // VkAccessFlags srcAccessMask;
2969         vk::VK_ACCESS_HOST_READ_BIT,                 // VkAccessFlags dstAccessMask;
2970         VK_QUEUE_FAMILY_IGNORED,                     // uint32_t srcQueueFamilyIndex;
2971         VK_QUEUE_FAMILY_IGNORED,                     // uint32_t dstQueueFamilyIndex;
2972         *m_resultBuffer,                             // VkBuffer buffer;
2973         0ull,                                        // VkDeviceSize offset;
2974         VK_WHOLE_SIZE                                // VkDeviceSize size;
2975     };
2976 
2977     // Prepare command buffer.
2978     beginCommandBuffer(vk, *m_cmdBuffer, 0u);
2979     vk.cmdResetQueryPool(*m_cmdBuffer, *m_queryPool, 0u, 1u);
2980     vk.cmdWriteTimestamp(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, *m_queryPool, 0u);
2981     vk.cmdResetQueryPool(*m_cmdBuffer, *m_queryPool, 0u, 1u);
2982     vk.cmdCopyQueryPoolResults(*m_cmdBuffer, *m_queryPool, 0u, 1u, *m_resultBuffer, 0u,
2983                                sizeof(TimestampWithAvailability),
2984                                (VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WITH_AVAILABILITY_BIT));
2985     vk.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u,
2986                           nullptr, 1u, &bufferBarrier, 0u, nullptr);
2987     endCommandBuffer(vk, *m_cmdBuffer);
2988 }
2989 
iterate(void)2990 tcu::TestStatus ResetTimestampQueryBeforeCopyTestInstance::iterate(void)
2991 {
2992     const DeviceInterface &vk = m_context.getDeviceInterface();
2993     const VkDevice vkDevice   = m_context.getDevice();
2994     const VkQueue queue       = m_context.getUniversalQueue();
2995     TimestampWithAvailability ta;
2996 
2997     submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
2998     invalidateAlloc(vk, vkDevice, *m_resultBufferMemory);
2999     deMemcpy(&ta, m_resultBufferMemory->getHostPtr(), sizeof(ta));
3000     return ((ta.availability != 0) ? tcu::TestStatus::fail("Availability bit nonzero after resetting query") :
3001                                      tcu::TestStatus::pass("Pass"));
3002 }
3003 
3004 class TwoCmdBuffersTest : public TimestampTest
3005 {
3006 public:
TwoCmdBuffersTest(tcu::TestContext & testContext,const std::string & name,const TwoCmdBuffersTestParam * param)3007     TwoCmdBuffersTest(tcu::TestContext &testContext, const std::string &name, const TwoCmdBuffersTestParam *param)
3008         : TimestampTest(testContext, name, param)
3009         , m_cmdBufferLevel(param->getCmdBufferLevel())
3010     {
3011     }
~TwoCmdBuffersTest(void)3012     virtual ~TwoCmdBuffersTest(void)
3013     {
3014     }
3015     virtual TestInstance *createInstance(Context &context) const;
3016     virtual void checkSupport(Context &context) const;
3017 
3018 protected:
3019     VkCommandBufferLevel m_cmdBufferLevel;
3020 };
3021 
3022 class TwoCmdBuffersTestInstance : public TimestampTestInstance
3023 {
3024 public:
3025     TwoCmdBuffersTestInstance(Context &context, const StageFlagVector stages, const bool inRenderPass,
3026                               const bool hostQueryReset, const bool transferOnlyQueue,
3027                               VkCommandBufferLevel cmdBufferLevel, VkQueryResultFlags queryResultFlags);
3028     virtual ~TwoCmdBuffersTestInstance(void);
3029     virtual tcu::TestStatus iterate(void);
3030 
3031 protected:
3032     virtual void configCommandBuffer(void);
3033 
3034 protected:
3035     Move<VkCommandBuffer> m_secondCmdBuffer;
3036     Move<VkBuffer> m_dstBuffer;
3037     de::MovePtr<Allocation> m_dstBufferAlloc;
3038     VkCommandBufferLevel m_cmdBufferLevel;
3039 };
3040 
createInstance(Context & context) const3041 TestInstance *TwoCmdBuffersTest::createInstance(Context &context) const
3042 {
3043     return new TwoCmdBuffersTestInstance(context, m_stages, m_inRenderPass, m_hostQueryReset, m_transferOnlyQueue,
3044                                          m_cmdBufferLevel, m_queryResultFlags);
3045 }
3046 
checkSupport(Context & context) const3047 void TwoCmdBuffersTest::checkSupport(Context &context) const
3048 {
3049     TimestampTest::checkSupport(context);
3050 #ifdef CTS_USES_VULKANSC
3051     if (m_cmdBufferLevel == VK_COMMAND_BUFFER_LEVEL_SECONDARY &&
3052         context.getDeviceVulkanSC10Properties().secondaryCommandBufferNullOrImagelessFramebuffer == VK_FALSE)
3053         TCU_THROW(NotSupportedError, "secondaryCommandBufferNullFramebuffer is not supported");
3054 #endif
3055 }
3056 
TwoCmdBuffersTestInstance(Context & context,const StageFlagVector stages,const bool inRenderPass,const bool hostQueryReset,const bool transferOnlyQueue,VkCommandBufferLevel cmdBufferLevel,VkQueryResultFlags queryResultFlags)3057 TwoCmdBuffersTestInstance::TwoCmdBuffersTestInstance(Context &context, const StageFlagVector stages,
3058                                                      const bool inRenderPass, const bool hostQueryReset,
3059                                                      const bool transferOnlyQueue, VkCommandBufferLevel cmdBufferLevel,
3060                                                      VkQueryResultFlags queryResultFlags)
3061     : TimestampTestInstance(context, stages, inRenderPass, hostQueryReset, transferOnlyQueue, queryResultFlags)
3062     , m_cmdBufferLevel(cmdBufferLevel)
3063 {
3064     const DeviceInterface &vk = context.getDeviceInterface();
3065 
3066     m_secondCmdBuffer = allocateCommandBuffer(vk, m_device, *m_cmdPool, cmdBufferLevel);
3067     m_dstBuffer = createBufferAndBindMemory(1024, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
3068                                             &m_dstBufferAlloc);
3069 }
3070 
~TwoCmdBuffersTestInstance(void)3071 TwoCmdBuffersTestInstance::~TwoCmdBuffersTestInstance(void)
3072 {
3073 }
3074 
configCommandBuffer(void)3075 void TwoCmdBuffersTestInstance::configCommandBuffer(void)
3076 {
3077     const DeviceInterface &vk = m_context.getDeviceInterface();
3078 
3079     const VkCommandBufferBeginInfo cmdBufferBeginInfo = {
3080         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType                          sType;
3081         nullptr,                                     // const void*                              pNext;
3082         0u,                                          // VkCommandBufferUsageFlags                flags;
3083         nullptr                                      // const VkCommandBufferInheritanceInfo*    pInheritanceInfo;
3084     };
3085 
3086     const vk::VkBufferMemoryBarrier bufferBarrier = {
3087         vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
3088         nullptr,                                     // const void* pNext;
3089         vk::VK_ACCESS_TRANSFER_WRITE_BIT,            // VkAccessFlags srcAccessMask;
3090         vk::VK_ACCESS_HOST_READ_BIT,                 // VkAccessFlags dstAccessMask;
3091         VK_QUEUE_FAMILY_IGNORED,                     // uint32_t srcQueueFamilyIndex;
3092         VK_QUEUE_FAMILY_IGNORED,                     // uint32_t dstQueueFamilyIndex;
3093         *m_dstBuffer,                                // VkBuffer buffer;
3094         0ull,                                        // VkDeviceSize offset;
3095         VK_WHOLE_SIZE                                // VkDeviceSize size;
3096     };
3097 
3098     if (m_cmdBufferLevel == VK_COMMAND_BUFFER_LEVEL_PRIMARY)
3099     {
3100         VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
3101         if (!m_hostQueryReset)
3102             vk.cmdResetQueryPool(*m_cmdBuffer, *m_queryPool, 0u, TimestampTest::ENTRY_COUNT);
3103         vk.cmdWriteTimestamp(*m_cmdBuffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, *m_queryPool, 0);
3104         VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
3105         VK_CHECK(vk.beginCommandBuffer(*m_secondCmdBuffer, &cmdBufferBeginInfo));
3106         vk.cmdCopyQueryPoolResults(*m_secondCmdBuffer, *m_queryPool, 0u, 1u, *m_dstBuffer, 0u, 0u, m_queryResultFlags);
3107         vk.cmdPipelineBarrier(*m_secondCmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT,
3108                               0u, 0u, nullptr, 1u, &bufferBarrier, 0u, nullptr);
3109         VK_CHECK(vk.endCommandBuffer(*m_secondCmdBuffer));
3110     }
3111     else
3112     {
3113         const VkCommandBufferInheritanceInfo inheritanceInfo = {
3114             VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, // VkStructureType                  sType;
3115             nullptr,                                           // const void*                      pNext;
3116             VK_NULL_HANDLE,                                    // VkRenderPass                     renderPass;
3117             0u,                                                // uint32_t                         subpass;
3118             VK_NULL_HANDLE,                                    // VkFramebuffer                    framebuffer;
3119             VK_FALSE,                                          // VkBool32                         occlusionQueryEnable;
3120             0u,                                                // VkQueryControlFlags              queryFlags;
3121             0u                                                 // VkQueryPipelineStatisticFlags    pipelineStatistics;
3122         };
3123 
3124         const VkCommandBufferBeginInfo cmdBufferBeginInfoSecondary = {
3125             VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType                          sType;
3126             nullptr,                                     // const void*                              pNext;
3127             0u,                                          // VkCommandBufferUsageFlags                flags;
3128             &inheritanceInfo                             // const VkCommandBufferInheritanceInfo*    pInheritanceInfo;
3129         };
3130 
3131         VK_CHECK(vk.beginCommandBuffer(*m_secondCmdBuffer, &cmdBufferBeginInfoSecondary));
3132         if (!m_hostQueryReset)
3133             vk.cmdResetQueryPool(*m_secondCmdBuffer, *m_queryPool, 0u, TimestampTest::ENTRY_COUNT);
3134         vk::VkPipelineStageFlagBits pipelineStage =
3135             m_transferOnlyQueue ? VK_PIPELINE_STAGE_TRANSFER_BIT : VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT;
3136         vk.cmdWriteTimestamp(*m_secondCmdBuffer, pipelineStage, *m_queryPool, 0);
3137         VK_CHECK(vk.endCommandBuffer(*m_secondCmdBuffer));
3138         VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
3139         vk.cmdExecuteCommands(m_cmdBuffer.get(), 1u, &m_secondCmdBuffer.get());
3140         if (!m_transferOnlyQueue)
3141             vk.cmdCopyQueryPoolResults(*m_cmdBuffer, *m_queryPool, 0u, 1u, *m_dstBuffer, 0u, 0u, m_queryResultFlags);
3142         vk.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u,
3143                               nullptr, 1u, &bufferBarrier, 0u, nullptr);
3144         VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
3145     }
3146 }
3147 
iterate(void)3148 tcu::TestStatus TwoCmdBuffersTestInstance::iterate(void)
3149 {
3150     const DeviceInterface &vk = m_context.getDeviceInterface();
3151     const VkQueue queue       = getDeviceQueue(vk, m_device, m_queueFamilyIndex, 0);
3152 
3153     configCommandBuffer();
3154 
3155     const VkCommandBuffer cmdBuffers[] = {m_cmdBuffer.get(), m_secondCmdBuffer.get()};
3156 
3157     const VkSubmitInfo submitInfo = {
3158         VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType                sType;
3159         nullptr,                       // const void*                    pNext;
3160         0u,                            // uint32_t                       waitSemaphoreCount;
3161         nullptr,                       // const VkSemaphore*             pWaitSemaphores;
3162         nullptr,                       // const VkPipelineStageFlags*    pWaitDstStageMask;
3163         m_cmdBufferLevel == VK_COMMAND_BUFFER_LEVEL_PRIMARY ? 2u :
3164                                                               1u, // uint32_t                       commandBufferCount;
3165         cmdBuffers,                                               // const VkCommandBuffer*         pCommandBuffers;
3166         0u,      // uint32_t                       signalSemaphoreCount;
3167         nullptr, // const VkSemaphore*             pSignalSemaphores;
3168     };
3169 
3170     if (m_hostQueryReset)
3171     {
3172         // Only reset the pool for the primary command buffer, the secondary command buffer will reset the pool by itself.
3173         vk.resetQueryPool(m_device, *m_queryPool, 0u, TimestampTest::ENTRY_COUNT);
3174     }
3175 
3176     VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, VK_NULL_HANDLE));
3177     VK_CHECK(vk.queueWaitIdle(queue));
3178 
3179     // Always pass in case no crash occurred.
3180     return tcu::TestStatus::pass("Pass");
3181 }
3182 
3183 class ConsistentQueryResultsTest : public vkt::TestCase
3184 {
3185 public:
ConsistentQueryResultsTest(tcu::TestContext & testContext,const std::string & name)3186     ConsistentQueryResultsTest(tcu::TestContext &testContext, const std::string &name)
3187         : vkt::TestCase(testContext, name)
3188     {
3189     }
~ConsistentQueryResultsTest(void)3190     virtual ~ConsistentQueryResultsTest(void)
3191     {
3192     }
3193     virtual void initPrograms(SourceCollections &programCollection) const;
3194     virtual TestInstance *createInstance(Context &context) const;
3195 };
3196 
3197 class ConsistentQueryResultsTestInstance : public vkt::TestInstance
3198 {
3199 public:
3200     ConsistentQueryResultsTestInstance(Context &context);
~ConsistentQueryResultsTestInstance(void)3201     virtual ~ConsistentQueryResultsTestInstance(void)
3202     {
3203     }
3204     virtual tcu::TestStatus iterate(void);
3205 
3206 protected:
3207     Move<VkCommandPool> m_cmdPool;
3208     Move<VkCommandBuffer> m_cmdBuffer;
3209     Move<VkQueryPool> m_queryPool;
3210 
3211     uint64_t m_timestampMask;
3212     Move<VkBuffer> m_resultBuffer32Bits;
3213     Move<VkBuffer> m_resultBuffer64Bits;
3214     de::MovePtr<Allocation> m_resultBufferMemory32Bits;
3215     de::MovePtr<Allocation> m_resultBufferMemory64Bits;
3216 };
3217 
initPrograms(SourceCollections & programCollection) const3218 void ConsistentQueryResultsTest::initPrograms(SourceCollections &programCollection) const
3219 {
3220     vkt::TestCase::initPrograms(programCollection);
3221 }
3222 
createInstance(Context & context) const3223 TestInstance *ConsistentQueryResultsTest::createInstance(Context &context) const
3224 {
3225     return new ConsistentQueryResultsTestInstance(context);
3226 }
3227 
ConsistentQueryResultsTestInstance(Context & context)3228 ConsistentQueryResultsTestInstance::ConsistentQueryResultsTestInstance(Context &context) : vkt::TestInstance(context)
3229 {
3230     const DeviceInterface &vk       = context.getDeviceInterface();
3231     const VkDevice vkDevice         = context.getDevice();
3232     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
3233     Allocator &allocator            = m_context.getDefaultAllocator();
3234 
3235     // Check support for timestamp queries
3236     m_timestampMask =
3237         checkTimestampsSupported(context.getInstanceInterface(), context.getPhysicalDevice(), queueFamilyIndex);
3238 
3239     const VkQueryPoolCreateInfo queryPoolParams = {
3240         VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, // VkStructureType               sType;
3241         nullptr,                                  // const void*                   pNext;
3242         0u,                                       // VkQueryPoolCreateFlags        flags;
3243         VK_QUERY_TYPE_TIMESTAMP,                  // VkQueryType                   queryType;
3244         1u,                                       // uint32_t                      entryCount;
3245         0u,                                       // VkQueryPipelineStatisticFlags pipelineStatistics;
3246     };
3247 
3248     m_queryPool = createQueryPool(vk, vkDevice, &queryPoolParams);
3249     m_cmdPool   = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
3250     m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
3251 
3252     // Create results buffer.
3253     VkBufferCreateInfo bufferCreateInfo = {
3254         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
3255         nullptr,                              // const void* pNext;
3256         0u,                                   // VkBufferCreateFlags flags;
3257         0u,                                   // VkDeviceSize size;
3258         VK_BUFFER_USAGE_TRANSFER_DST_BIT,     // VkBufferUsageFlags usage;
3259         VK_SHARING_MODE_EXCLUSIVE,            // VkSharingMode sharingMode;
3260         1u,                                   // uint32_t queueFamilyIndexCount;
3261         &queueFamilyIndex                     // const uint32_t* pQueueFamilyIndices;
3262     };
3263 
3264     // 32 bits.
3265     bufferCreateInfo.size      = sizeof(uint32_t);
3266     m_resultBuffer32Bits       = createBuffer(vk, vkDevice, &bufferCreateInfo);
3267     m_resultBufferMemory32Bits = allocator.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_resultBuffer32Bits),
3268                                                     MemoryRequirement::HostVisible);
3269     VK_CHECK(vk.bindBufferMemory(vkDevice, *m_resultBuffer32Bits, m_resultBufferMemory32Bits->getMemory(),
3270                                  m_resultBufferMemory32Bits->getOffset()));
3271 
3272     // 64 bits.
3273     bufferCreateInfo.size      = sizeof(uint64_t);
3274     m_resultBuffer64Bits       = createBuffer(vk, vkDevice, &bufferCreateInfo);
3275     m_resultBufferMemory64Bits = allocator.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_resultBuffer64Bits),
3276                                                     MemoryRequirement::HostVisible);
3277     VK_CHECK(vk.bindBufferMemory(vkDevice, *m_resultBuffer64Bits, m_resultBufferMemory64Bits->getMemory(),
3278                                  m_resultBufferMemory64Bits->getOffset()));
3279 
3280     vk::VkBufferMemoryBarrier bufferBarrier = {
3281         vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
3282         nullptr,                                     // const void* pNext;
3283         vk::VK_ACCESS_TRANSFER_WRITE_BIT,            // VkAccessFlags srcAccessMask;
3284         vk::VK_ACCESS_HOST_READ_BIT,                 // VkAccessFlags dstAccessMask;
3285         VK_QUEUE_FAMILY_IGNORED,                     // uint32_t srcQueueFamilyIndex;
3286         VK_QUEUE_FAMILY_IGNORED,                     // uint32_t dstQueueFamilyIndex;
3287         VK_NULL_HANDLE,                              // VkBuffer buffer;
3288         0ull,                                        // VkDeviceSize offset;
3289         VK_WHOLE_SIZE                                // VkDeviceSize size;
3290     };
3291 
3292     // Prepare command buffer.
3293     beginCommandBuffer(vk, *m_cmdBuffer, 0u);
3294     vk.cmdResetQueryPool(*m_cmdBuffer, *m_queryPool, 0u, 1u);
3295     vk.cmdWriteTimestamp(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, *m_queryPool, 0u);
3296 
3297     // 32 bits.
3298     bufferBarrier.buffer = *m_resultBuffer32Bits;
3299     vk.cmdCopyQueryPoolResults(*m_cmdBuffer, *m_queryPool, 0u, 1u, *m_resultBuffer32Bits, 0u, sizeof(uint32_t),
3300                                VK_QUERY_RESULT_WAIT_BIT);
3301     vk.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u,
3302                           nullptr, 1u, &bufferBarrier, 0u, nullptr);
3303 
3304     // 64 bits.
3305     bufferBarrier.buffer = *m_resultBuffer64Bits;
3306     vk.cmdCopyQueryPoolResults(*m_cmdBuffer, *m_queryPool, 0u, 1u, *m_resultBuffer64Bits, 0u, sizeof(uint64_t),
3307                                (VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
3308     vk.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u,
3309                           nullptr, 1u, &bufferBarrier, 0u, nullptr);
3310 
3311     endCommandBuffer(vk, *m_cmdBuffer);
3312 }
3313 
iterate(void)3314 tcu::TestStatus ConsistentQueryResultsTestInstance::iterate(void)
3315 {
3316     const DeviceInterface &vk = m_context.getDeviceInterface();
3317     const VkDevice vkDevice   = m_context.getDevice();
3318     const VkQueue queue       = m_context.getUniversalQueue();
3319 
3320     uint32_t tsBuffer32Bits;
3321     uint64_t tsBuffer64Bits;
3322     uint32_t tsGet32Bits;
3323     uint64_t tsGet64Bits;
3324 
3325     constexpr uint32_t maxDeUint32Value = std::numeric_limits<uint32_t>::max();
3326 
3327     submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
3328 
3329     // Get results from buffers.
3330     invalidateAlloc(vk, vkDevice, *m_resultBufferMemory32Bits);
3331     invalidateAlloc(vk, vkDevice, *m_resultBufferMemory64Bits);
3332     deMemcpy(&tsBuffer32Bits, m_resultBufferMemory32Bits->getHostPtr(), sizeof(tsBuffer32Bits));
3333     deMemcpy(&tsBuffer64Bits, m_resultBufferMemory64Bits->getHostPtr(), sizeof(tsBuffer64Bits));
3334 
3335     // Get results with vkGetQueryPoolResults().
3336     VK_CHECK(vk.getQueryPoolResults(vkDevice, *m_queryPool, 0u, 1u, sizeof(tsGet32Bits), &tsGet32Bits,
3337                                     sizeof(tsGet32Bits), VK_QUERY_RESULT_WAIT_BIT));
3338     VK_CHECK(vk.getQueryPoolResults(vkDevice, *m_queryPool, 0u, 1u, sizeof(tsGet64Bits), &tsGet64Bits,
3339                                     sizeof(tsGet64Bits), (VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT)));
3340 
3341     // Check timestamp mask for both 64-bit results.
3342     checkTimestampBits(tsBuffer64Bits, m_timestampMask);
3343     checkTimestampBits(tsGet64Bits, m_timestampMask);
3344 
3345 #ifndef CTS_USES_VULKANSC
3346     const bool hasMaint7 = m_context.getMaintenance7Features().maintenance7;
3347 #else
3348     const bool hasMaint7 = false;
3349 #endif
3350 
3351     // Check results are consistent.
3352     if (hasMaint7)
3353     {
3354         // If maintenance7 is supported, 32 bit queries _must_ be equivalent to the lower 32 bits of the 64 bit query
3355         if (tsBuffer32Bits == tsGet32Bits && tsBuffer64Bits == tsGet64Bits &&
3356             (((tsGet64Bits & maxDeUint32Value) == tsGet32Bits)))
3357         {
3358             return tcu::TestStatus::pass("Pass");
3359         }
3360     }
3361     else
3362     {
3363         if (tsBuffer32Bits == tsGet32Bits && tsBuffer64Bits == tsGet64Bits &&
3364             (((tsGet64Bits & maxDeUint32Value) == tsGet32Bits) ||
3365              ((tsGet64Bits > maxDeUint32Value) && (maxDeUint32Value == tsGet32Bits))))
3366         {
3367             return tcu::TestStatus::pass("Pass");
3368         }
3369     }
3370 
3371     std::ostringstream msg;
3372     msg << std::hex << "Results are inconsistent:"
3373         << " B32=0x" << tsBuffer32Bits << " B64=0x" << tsBuffer64Bits << " G32=0x" << tsGet32Bits << " G64=0x"
3374         << tsGet64Bits;
3375     return tcu::TestStatus::fail(msg.str());
3376 }
3377 
3378 class CheckTimestampComputeAndGraphicsTest : public vkt::TestCase
3379 {
3380 public:
CheckTimestampComputeAndGraphicsTest(tcu::TestContext & testContext,const std::string & name)3381     CheckTimestampComputeAndGraphicsTest(tcu::TestContext &testContext, const std::string &name)
3382         : vkt::TestCase(testContext, name)
3383     {
3384     }
3385     virtual ~CheckTimestampComputeAndGraphicsTest(void) = default;
3386     void checkSupport(Context &context) const;
3387     TestInstance *createInstance(Context &context) const;
3388 };
3389 
3390 class CheckTimestampComputeAndGraphicsTestInstance : public vkt::TestInstance
3391 {
3392 public:
CheckTimestampComputeAndGraphicsTestInstance(Context & context)3393     CheckTimestampComputeAndGraphicsTestInstance(Context &context) : vkt::TestInstance(context)
3394     {
3395     }
3396     virtual ~CheckTimestampComputeAndGraphicsTestInstance(void) = default;
3397     virtual tcu::TestStatus iterate(void);
3398 };
3399 
checkSupport(Context & context) const3400 void CheckTimestampComputeAndGraphicsTest::checkSupport(Context &context) const
3401 {
3402     if (!context.getDeviceProperties().limits.timestampComputeAndGraphics)
3403         TCU_THROW(NotSupportedError, "timestampComputeAndGraphics is not supported");
3404 }
3405 
createInstance(Context & context) const3406 TestInstance *CheckTimestampComputeAndGraphicsTest::createInstance(Context &context) const
3407 {
3408     return new CheckTimestampComputeAndGraphicsTestInstance(context);
3409 }
3410 
iterate(void)3411 tcu::TestStatus CheckTimestampComputeAndGraphicsTestInstance::iterate(void)
3412 {
3413     const InstanceInterface &vki          = m_context.getInstanceInterface();
3414     const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
3415     const VkQueueFlags gcQueueFlags       = VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT;
3416 
3417     // When timestampComputeAndGraphics is true then all queues that advertise
3418     // the VK_QUEUE_GRAPHICS_BIT or VK_QUEUE_COMPUTE_BIT in the queueFlags support
3419     // VkQueueFamilyProperties::timestampValidBits of at least 36.
3420 
3421     const auto queueProps = getPhysicalDeviceQueueFamilyProperties(vki, physicalDevice);
3422     for (const auto &qp : queueProps)
3423     {
3424         if ((qp.queueFlags & gcQueueFlags) && (qp.timestampValidBits < 36))
3425             return tcu::TestStatus::fail("Fail");
3426     }
3427 
3428     return tcu::TestStatus::pass("Pass");
3429 }
3430 
3431 } // namespace
3432 
createTimestampTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType)3433 tcu::TestCaseGroup *createTimestampTests(tcu::TestContext &testCtx, PipelineConstructionType pipelineConstructionType)
3434 {
3435     de::MovePtr<tcu::TestCaseGroup> timestampTests(new tcu::TestCaseGroup(testCtx, "timestamp"));
3436     const VkQueryResultFlags queryResultFlagsTimestampTest[] = {
3437         VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT,
3438         VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT | VK_QUERY_RESULT_WITH_AVAILABILITY_BIT,
3439     };
3440 
3441     // Basic Graphics Tests
3442     {
3443         de::MovePtr<tcu::TestCaseGroup> basicGraphicsTests(new tcu::TestCaseGroup(testCtx, "basic_graphics_tests"));
3444 
3445         const VkPipelineStageFlagBits basicGraphicsStages0[][2] = {
3446             {VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT},
3447             {VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT},
3448             {VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT},
3449             {VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT},
3450             {VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT},
3451             {VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT},
3452             {VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT},
3453             {VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT},
3454         };
3455         for (uint32_t stageNdx = 0u; stageNdx < DE_LENGTH_OF_ARRAY(basicGraphicsStages0); stageNdx++)
3456         {
3457             for (uint32_t flagsIdx = 0u; flagsIdx < DE_LENGTH_OF_ARRAY(queryResultFlagsTimestampTest); flagsIdx++)
3458             {
3459                 TimestampTestParam param(pipelineConstructionType, basicGraphicsStages0[stageNdx], 2u, true, false,
3460                                          false, queryResultFlagsTimestampTest[flagsIdx]);
3461                 basicGraphicsTests->addChild(newTestCase<BasicGraphicsTest>(testCtx, &param));
3462                 param.toggleInRenderPass();
3463                 basicGraphicsTests->addChild(newTestCase<BasicGraphicsTest>(testCtx, &param));
3464                 // Host Query reset tests
3465                 param.toggleHostQueryReset();
3466                 basicGraphicsTests->addChild(newTestCase<BasicGraphicsTest>(testCtx, &param));
3467                 param.toggleInRenderPass();
3468                 basicGraphicsTests->addChild(newTestCase<BasicGraphicsTest>(testCtx, &param));
3469             }
3470         }
3471 
3472         const VkPipelineStageFlagBits basicGraphicsStages1[][3] = {
3473             {VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
3474              VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT},
3475             {VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,
3476              VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT},
3477         };
3478         for (uint32_t stageNdx = 0u; stageNdx < DE_LENGTH_OF_ARRAY(basicGraphicsStages1); stageNdx++)
3479         {
3480             for (uint32_t flagsIdx = 0u; flagsIdx < DE_LENGTH_OF_ARRAY(queryResultFlagsTimestampTest); flagsIdx++)
3481             {
3482                 TimestampTestParam param(pipelineConstructionType, basicGraphicsStages1[stageNdx], 3u, true, false,
3483                                          false, queryResultFlagsTimestampTest[flagsIdx]);
3484                 basicGraphicsTests->addChild(newTestCase<BasicGraphicsTest>(testCtx, &param));
3485                 param.toggleInRenderPass();
3486                 basicGraphicsTests->addChild(newTestCase<BasicGraphicsTest>(testCtx, &param));
3487                 // Host Query reset tests
3488                 param.toggleHostQueryReset();
3489                 basicGraphicsTests->addChild(newTestCase<BasicGraphicsTest>(testCtx, &param));
3490                 param.toggleInRenderPass();
3491                 basicGraphicsTests->addChild(newTestCase<BasicGraphicsTest>(testCtx, &param));
3492             }
3493         }
3494 
3495         timestampTests->addChild(basicGraphicsTests.release());
3496     }
3497 
3498     // Advanced Graphics Tests
3499     {
3500         // Record timestamp in different pipeline stages of advanced graphics tests
3501         de::MovePtr<tcu::TestCaseGroup> advGraphicsTests(new tcu::TestCaseGroup(testCtx, "advanced_graphics_tests"));
3502 
3503         const VkPipelineStageFlagBits advGraphicsStages[][2] = {
3504             {VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT},
3505             {VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT},
3506             {VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT},
3507             {VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT},
3508         };
3509         for (uint32_t stageNdx = 0u; stageNdx < DE_LENGTH_OF_ARRAY(advGraphicsStages); stageNdx++)
3510         {
3511             for (uint32_t flagsIdx = 0u; flagsIdx < DE_LENGTH_OF_ARRAY(queryResultFlagsTimestampTest); flagsIdx++)
3512             {
3513                 TimestampTestParam param(pipelineConstructionType, advGraphicsStages[stageNdx], 2u, true, false, false,
3514                                          queryResultFlagsTimestampTest[flagsIdx]);
3515                 advGraphicsTests->addChild(newTestCase<AdvGraphicsTest>(testCtx, &param));
3516                 param.toggleInRenderPass();
3517                 advGraphicsTests->addChild(newTestCase<AdvGraphicsTest>(testCtx, &param));
3518                 // Host Query reset tests
3519                 param.toggleHostQueryReset();
3520                 advGraphicsTests->addChild(newTestCase<AdvGraphicsTest>(testCtx, &param));
3521                 param.toggleInRenderPass();
3522                 advGraphicsTests->addChild(newTestCase<AdvGraphicsTest>(testCtx, &param));
3523             }
3524         }
3525 
3526         timestampTests->addChild(advGraphicsTests.release());
3527     }
3528 
3529     // Basic Compute Tests - don't repeat those tests for graphics pipeline library
3530     if (pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
3531     {
3532         // Record timestamp for compute stages
3533         de::MovePtr<tcu::TestCaseGroup> basicComputeTests(new tcu::TestCaseGroup(testCtx, "basic_compute_tests"));
3534 
3535         const VkPipelineStageFlagBits basicComputeStages[][2] = {
3536             {VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT},
3537             {VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT},
3538         };
3539         for (uint32_t stageNdx = 0u; stageNdx < DE_LENGTH_OF_ARRAY(basicComputeStages); stageNdx++)
3540         {
3541             for (uint32_t flagsIdx = 0u; flagsIdx < DE_LENGTH_OF_ARRAY(queryResultFlagsTimestampTest); flagsIdx++)
3542             {
3543                 TimestampTestParam param(pipelineConstructionType, basicComputeStages[stageNdx], 2u, false, false,
3544                                          false, queryResultFlagsTimestampTest[flagsIdx]);
3545                 basicComputeTests->addChild(newTestCase<BasicComputeTest>(testCtx, &param));
3546                 // Host Query reset test
3547                 param.toggleHostQueryReset();
3548                 basicComputeTests->addChild(newTestCase<BasicComputeTest>(testCtx, &param));
3549             }
3550         }
3551 
3552         timestampTests->addChild(basicComputeTests.release());
3553     }
3554 
3555     // Transfer Tests - don't repeat those tests for graphics pipeline library
3556     if (pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
3557     {
3558         de::MovePtr<tcu::TestCaseGroup> transferTests(new tcu::TestCaseGroup(testCtx, "transfer_tests"));
3559 
3560         const VkPipelineStageFlagBits transferStages[][2] = {
3561             {VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT},
3562             {VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_HOST_BIT},
3563         };
3564 
3565         for (uint32_t transferOnlyQueue = 0u; transferOnlyQueue < 2; transferOnlyQueue++)
3566         {
3567             for (uint32_t stageNdx = 0u; stageNdx < DE_LENGTH_OF_ARRAY(transferStages); stageNdx++)
3568             {
3569                 for (uint32_t method = 0u; method < TRANSFER_METHOD_LAST; method++)
3570                 {
3571                     if (transferOnlyQueue)
3572                     {
3573                         // skip tests that use commands not supported on transfer only queue
3574                         if (method == TRANSFER_METHOD_BLIT_IMAGE || method == TRANSFER_METHOD_CLEAR_COLOR_IMAGE ||
3575                             method == TRANSFER_METHOD_CLEAR_DEPTH_STENCIL_IMAGE ||
3576                             method == TRANSFER_METHOD_RESOLVE_IMAGE ||
3577                             method == TRANSFER_METHOD_COPY_QUERY_POOL_RESULTS ||
3578                             method == TRANSFER_METHOD_COPY_QUERY_POOL_RESULTS_STRIDE_ZERO)
3579                             continue;
3580                     }
3581 
3582                     for (uint32_t flagsIdx = 0u; flagsIdx < DE_LENGTH_OF_ARRAY(queryResultFlagsTimestampTest);
3583                          flagsIdx++)
3584                     {
3585                         TransferTimestampTestParam param(pipelineConstructionType, transferStages[stageNdx], 2u, false,
3586                                                          false, transferOnlyQueue, method,
3587                                                          queryResultFlagsTimestampTest[flagsIdx]);
3588 
3589                         // execute tests that use cmdResetQueryPool only on default device
3590                         if (!transferOnlyQueue)
3591                             transferTests->addChild(newTestCase<TransferTest>(testCtx, &param));
3592 
3593                         // Host Query reset test
3594                         param.toggleHostQueryReset();
3595                         transferTests->addChild(newTestCase<TransferTest>(testCtx, &param));
3596                     }
3597                 }
3598             }
3599         }
3600 
3601         timestampTests->addChild(transferTests.release());
3602     }
3603 
3604     // Calibrated Timestamp Tests - don't repeat those tests for graphics pipeline library
3605     if (pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
3606     {
3607         de::MovePtr<tcu::TestCaseGroup> calibratedTimestampTests(new tcu::TestCaseGroup(testCtx, "calibrated"));
3608 
3609         calibratedTimestampTests->addChild(
3610             new CalibratedTimestampTest<CalibratedTimestampDevDomainTestInstance>(testCtx, "dev_domain_test"));
3611         calibratedTimestampTests->addChild(
3612             new CalibratedTimestampTest<CalibratedTimestampHostDomainTestInstance>(testCtx, "host_domain_test"));
3613         // Test calibration using device and host domains
3614         calibratedTimestampTests->addChild(
3615             new CalibratedTimestampTest<CalibratedTimestampCalibrationTestInstance>(testCtx, "calibration_test"));
3616 
3617         timestampTests->addChild(calibratedTimestampTests.release());
3618     }
3619 
3620     // Misc Tests - don't repeat those tests for graphics pipeline library
3621     if (pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
3622     {
3623         const VkQueryResultFlags queryResultFlagsMiscTests[] = {
3624             VK_QUERY_RESULT_WAIT_BIT,
3625             VK_QUERY_RESULT_WAIT_BIT | VK_QUERY_RESULT_WITH_AVAILABILITY_BIT,
3626         };
3627 
3628         const std::string queryResultsFlagsMiscTestsStr[] = {"", "_with_availability_bit"};
3629 
3630         de::MovePtr<tcu::TestCaseGroup> miscTests(new tcu::TestCaseGroup(testCtx, "misc_tests"));
3631 
3632         for (uint32_t flagsIdx = 0u; flagsIdx < DE_LENGTH_OF_ARRAY(queryResultFlagsMiscTests); flagsIdx++)
3633         {
3634             const VkPipelineStageFlagBits miscStages[] = {VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT};
3635             TimestampTestParam param(pipelineConstructionType, miscStages, 1u, false, false, false,
3636                                      queryResultFlagsTimestampTest[flagsIdx]);
3637             // Only write timestamp command in the commmand buffer
3638             miscTests->addChild(
3639                 new TimestampTest(testCtx, "timestamp_only" + queryResultsFlagsMiscTestsStr[flagsIdx], &param));
3640 
3641             TwoCmdBuffersTestParam twoCmdBuffersParamPrimary(pipelineConstructionType, miscStages, 1u, false, false,
3642                                                              false, VK_COMMAND_BUFFER_LEVEL_PRIMARY,
3643                                                              queryResultFlagsMiscTests[flagsIdx]);
3644             // Issue query in a command buffer and copy it on another primary command buffer
3645             miscTests->addChild(
3646                 new TwoCmdBuffersTest(testCtx, "two_cmd_buffers_primary" + queryResultsFlagsMiscTestsStr[flagsIdx],
3647                                       &twoCmdBuffersParamPrimary));
3648 
3649             TwoCmdBuffersTestParam twoCmdBuffersParamSecondary(pipelineConstructionType, miscStages, 1u, false, false,
3650                                                                false, VK_COMMAND_BUFFER_LEVEL_SECONDARY,
3651                                                                queryResultFlagsMiscTests[flagsIdx]);
3652             // Issue query in a secondary command buffer and copy it on a primary command buffer
3653             miscTests->addChild(
3654                 new TwoCmdBuffersTest(testCtx, "two_cmd_buffers_secondary" + queryResultsFlagsMiscTestsStr[flagsIdx],
3655                                       &twoCmdBuffersParamSecondary));
3656             // Misc: Host Query Reset tests
3657             param.toggleHostQueryReset();
3658             // Only write timestamp command in the commmand buffer
3659             miscTests->addChild(new TimestampTest(
3660                 testCtx, "timestamp_only_host_query_reset" + queryResultsFlagsMiscTestsStr[flagsIdx], &param));
3661             TwoCmdBuffersTestParam twoCmdBuffersParamPrimaryHostQueryReset(
3662                 pipelineConstructionType, miscStages, 1u, false, true, false, VK_COMMAND_BUFFER_LEVEL_PRIMARY,
3663                 queryResultFlagsMiscTests[flagsIdx]);
3664             // Issue query in a command buffer and copy it on another primary command buffer
3665             miscTests->addChild(new TwoCmdBuffersTest(
3666                 testCtx, "two_cmd_buffers_primary_host_query_reset" + queryResultsFlagsMiscTestsStr[flagsIdx],
3667                 &twoCmdBuffersParamPrimaryHostQueryReset));
3668 
3669             TwoCmdBuffersTestParam twoCmdBuffersParamSecondaryHostQueryReset(
3670                 pipelineConstructionType, miscStages, 1u, false, true, false, VK_COMMAND_BUFFER_LEVEL_SECONDARY,
3671                 queryResultFlagsMiscTests[flagsIdx]);
3672             // Issue query in a secondary command buffer and copy it on a primary command buffer
3673             miscTests->addChild(new TwoCmdBuffersTest(
3674                 testCtx, "two_cmd_buffers_secondary_host_query_reset" + queryResultsFlagsMiscTestsStr[flagsIdx],
3675                 &twoCmdBuffersParamSecondaryHostQueryReset));
3676             TwoCmdBuffersTestParam twoCmdBuffersParamSecondaryTransferQueue(
3677                 pipelineConstructionType, miscStages, 1u, false, true, true, VK_COMMAND_BUFFER_LEVEL_SECONDARY,
3678                 queryResultFlagsMiscTests[flagsIdx]);
3679             // Issue query in a secondary command buffer and copy it on a primary command buffer
3680             miscTests->addChild(new TwoCmdBuffersTest(
3681                 testCtx, "two_cmd_buffers_secondary_transfer_queue" + queryResultsFlagsMiscTestsStr[flagsIdx],
3682                 &twoCmdBuffersParamSecondaryTransferQueue));
3683         }
3684         // Reset timestamp query before copying results.
3685         miscTests->addChild(new ResetTimestampQueryBeforeCopyTest(testCtx, "reset_query_before_copy"));
3686 
3687         // Fill buffer with 0s before copying results.
3688         miscTests->addChild(new FillBufferBeforeCopyTest(testCtx, "fill_buffer_before_copy"));
3689 
3690         // Check consistency between 32 and 64 bits.
3691         miscTests->addChild(new ConsistentQueryResultsTest(testCtx, "consistent_results"));
3692 
3693         // Check if timestamps are supported by every queue family that supports either graphics or compute operations
3694         if (pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
3695             miscTests->addChild(
3696                 new CheckTimestampComputeAndGraphicsTest(testCtx, "check_timestamp_compute_and_graphics"));
3697 
3698         timestampTests->addChild(miscTests.release());
3699     }
3700 
3701     return timestampTests.release();
3702 }
3703 
3704 } // namespace pipeline
3705 
3706 } // namespace vkt
3707