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