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