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, ©BufRegion);
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 ©ImageRegion);
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, ¶m));
3462 param.toggleInRenderPass();
3463 basicGraphicsTests->addChild(newTestCase<BasicGraphicsTest>(testCtx, ¶m));
3464 // Host Query reset tests
3465 param.toggleHostQueryReset();
3466 basicGraphicsTests->addChild(newTestCase<BasicGraphicsTest>(testCtx, ¶m));
3467 param.toggleInRenderPass();
3468 basicGraphicsTests->addChild(newTestCase<BasicGraphicsTest>(testCtx, ¶m));
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, ¶m));
3485 param.toggleInRenderPass();
3486 basicGraphicsTests->addChild(newTestCase<BasicGraphicsTest>(testCtx, ¶m));
3487 // Host Query reset tests
3488 param.toggleHostQueryReset();
3489 basicGraphicsTests->addChild(newTestCase<BasicGraphicsTest>(testCtx, ¶m));
3490 param.toggleInRenderPass();
3491 basicGraphicsTests->addChild(newTestCase<BasicGraphicsTest>(testCtx, ¶m));
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, ¶m));
3516 param.toggleInRenderPass();
3517 advGraphicsTests->addChild(newTestCase<AdvGraphicsTest>(testCtx, ¶m));
3518 // Host Query reset tests
3519 param.toggleHostQueryReset();
3520 advGraphicsTests->addChild(newTestCase<AdvGraphicsTest>(testCtx, ¶m));
3521 param.toggleInRenderPass();
3522 advGraphicsTests->addChild(newTestCase<AdvGraphicsTest>(testCtx, ¶m));
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, ¶m));
3546 // Host Query reset test
3547 param.toggleHostQueryReset();
3548 basicComputeTests->addChild(newTestCase<BasicComputeTest>(testCtx, ¶m));
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, ¶m));
3592
3593 // Host Query reset test
3594 param.toggleHostQueryReset();
3595 transferTests->addChild(newTestCase<TransferTest>(testCtx, ¶m));
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], ¶m));
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], ¶m));
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