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