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