1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2020 The Khronos Group Inc.
6 * Copyright (c) 2020 Valve Corporation
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 Vulkan Concurrent Query Tests
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktQueryPoolConcurrentTests.hpp"
26
27 #include "vktTestCase.hpp"
28
29 #include "vktDrawImageObjectUtil.hpp"
30 #include "vktDrawBufferObjectUtil.hpp"
31 #include "vktDrawCreateInfoUtil.hpp"
32 #include "vkBuilderUtil.hpp"
33 #include "vkRef.hpp"
34 #include "vkRefUtil.hpp"
35 #include "vkTypeUtil.hpp"
36 #include "vkCmdUtil.hpp"
37 #include "vkQueryUtil.hpp"
38
39 #include "tcuTestLog.hpp"
40 #include "tcuImageCompare.hpp"
41
42 #include <memory>
43
44 namespace vkt
45 {
46
47 namespace QueryPool
48 {
49
50 using namespace Draw;
51
52 namespace
53 {
54
55 enum QueryType
56 {
57 QUERY_TYPE_OCCLUSION = vk::VK_QUERY_TYPE_OCCLUSION,
58 QUERY_TYPE_PIPELINE_STATISTICS = vk::VK_QUERY_TYPE_PIPELINE_STATISTICS,
59 QUERY_TYPE_TIMESTAMP = vk::VK_QUERY_TYPE_TIMESTAMP,
60 NUM_QUERY_POOLS = 3
61 };
62
63 struct StateObjects
64 {
65 StateObjects(const vk::DeviceInterface &vk, vkt::Context &context, const int numVertices,
66 vk::VkPrimitiveTopology primitive);
67 void setVertices(const vk::DeviceInterface &vk, std::vector<tcu::Vec4> vertices);
68
69 enum
70 {
71 WIDTH = 128,
72 HEIGHT = 128
73 };
74
75 vkt::Context &m_context;
76
77 vk::Move<vk::VkPipeline> m_pipeline;
78 vk::Move<vk::VkPipelineLayout> m_pipelineLayout;
79
80 de::SharedPtr<Image> m_colorAttachmentImage, m_DepthImage;
81 vk::Move<vk::VkImageView> m_attachmentView;
82 vk::Move<vk::VkImageView> m_depthiew;
83
84 vk::Move<vk::VkRenderPass> m_renderPass;
85 vk::Move<vk::VkFramebuffer> m_framebuffer;
86
87 de::SharedPtr<Buffer> m_vertexBuffer;
88
89 vk::VkFormat m_colorAttachmentFormat;
90 };
91
StateObjects(const vk::DeviceInterface & vk,vkt::Context & context,const int numVertices,vk::VkPrimitiveTopology primitive)92 StateObjects::StateObjects(const vk::DeviceInterface &vk, vkt::Context &context, const int numVertices,
93 vk::VkPrimitiveTopology primitive)
94 : m_context(context)
95 , m_colorAttachmentFormat(vk::VK_FORMAT_R8G8B8A8_UNORM)
96
97 {
98 vk::VkFormat depthFormat = vk::VK_FORMAT_D16_UNORM;
99 const vk::VkDevice device = m_context.getDevice();
100
101 //attachment images and views
102 {
103 vk::VkExtent3D imageExtent = {
104 WIDTH, // width;
105 HEIGHT, // height;
106 1 // depth;
107 };
108
109 const ImageCreateInfo colorImageCreateInfo(
110 vk::VK_IMAGE_TYPE_2D, m_colorAttachmentFormat, imageExtent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT,
111 vk::VK_IMAGE_TILING_OPTIMAL, vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
112
113 m_colorAttachmentImage =
114 Image::createAndAlloc(vk, device, colorImageCreateInfo, m_context.getDefaultAllocator(),
115 m_context.getUniversalQueueFamilyIndex());
116
117 const ImageViewCreateInfo attachmentViewInfo(m_colorAttachmentImage->object(), vk::VK_IMAGE_VIEW_TYPE_2D,
118 m_colorAttachmentFormat);
119 m_attachmentView = vk::createImageView(vk, device, &attachmentViewInfo);
120
121 ImageCreateInfo depthImageCreateInfo(vk::VK_IMAGE_TYPE_2D, depthFormat, imageExtent, 1, 1,
122 vk::VK_SAMPLE_COUNT_1_BIT, vk::VK_IMAGE_TILING_OPTIMAL,
123 vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
124
125 m_DepthImage = Image::createAndAlloc(vk, device, depthImageCreateInfo, m_context.getDefaultAllocator(),
126 m_context.getUniversalQueueFamilyIndex());
127
128 // Construct a depth view from depth image
129 const ImageViewCreateInfo depthViewInfo(m_DepthImage->object(), vk::VK_IMAGE_VIEW_TYPE_2D, depthFormat);
130 m_depthiew = vk::createImageView(vk, device, &depthViewInfo);
131 }
132
133 {
134 // Renderpass and Framebuffer
135
136 RenderPassCreateInfo renderPassCreateInfo;
137 renderPassCreateInfo.addAttachment(AttachmentDescription(m_colorAttachmentFormat, // format
138 vk::VK_SAMPLE_COUNT_1_BIT, // samples
139 vk::VK_ATTACHMENT_LOAD_OP_CLEAR, // loadOp
140 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE, // storeOp
141 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE, // stencilLoadOp
142 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE, // stencilLoadOp
143 vk::VK_IMAGE_LAYOUT_GENERAL, // initialLauout
144 vk::VK_IMAGE_LAYOUT_GENERAL)); // finalLayout
145
146 renderPassCreateInfo.addAttachment(
147 AttachmentDescription(depthFormat, // format
148 vk::VK_SAMPLE_COUNT_1_BIT, // samples
149 vk::VK_ATTACHMENT_LOAD_OP_CLEAR, // loadOp
150 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE, // storeOp
151 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE, // stencilLoadOp
152 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE, // stencilLoadOp
153 vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // initialLauout
154 vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)); // finalLayout
155
156 const vk::VkAttachmentReference colorAttachmentReference = {
157 0, // attachment
158 vk::VK_IMAGE_LAYOUT_GENERAL // layout
159 };
160
161 const vk::VkAttachmentReference depthAttachmentReference = {
162 1, // attachment
163 vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL // layout
164 };
165
166 renderPassCreateInfo.addSubpass(SubpassDescription(vk::VK_PIPELINE_BIND_POINT_GRAPHICS, // pipelineBindPoint
167 0, // flags
168 0, // inputCount
169 DE_NULL, // pInputAttachments
170 1, // colorCount
171 &colorAttachmentReference, // pColorAttachments
172 DE_NULL, // pResolveAttachments
173 depthAttachmentReference, // depthStencilAttachment
174 0, // preserveCount
175 DE_NULL)); // preserveAttachments
176
177 m_renderPass = vk::createRenderPass(vk, device, &renderPassCreateInfo);
178
179 std::vector<vk::VkImageView> attachments(2);
180 attachments[0] = *m_attachmentView;
181 attachments[1] = *m_depthiew;
182
183 FramebufferCreateInfo framebufferCreateInfo(*m_renderPass, attachments, WIDTH, HEIGHT, 1);
184 m_framebuffer = vk::createFramebuffer(vk, device, &framebufferCreateInfo);
185 }
186
187 {
188 // Pipeline
189
190 vk::Unique<vk::VkShaderModule> vs(
191 vk::createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0));
192 vk::Unique<vk::VkShaderModule> fs(
193 vk::createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0));
194
195 const PipelineCreateInfo::ColorBlendState::Attachment attachmentState;
196
197 const PipelineLayoutCreateInfo pipelineLayoutCreateInfo;
198 m_pipelineLayout = vk::createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
199
200 const vk::VkVertexInputBindingDescription vf_binding_desc = {
201 0, // binding;
202 4 * (uint32_t)sizeof(float), // stride;
203 vk::VK_VERTEX_INPUT_RATE_VERTEX // inputRate
204 };
205
206 const vk::VkVertexInputAttributeDescription vf_attribute_desc = {
207 0, // location;
208 0, // binding;
209 vk::VK_FORMAT_R32G32B32A32_SFLOAT, // format;
210 0 // offset;
211 };
212
213 const vk::VkPipelineVertexInputStateCreateInfo vf_info = {
214 // sType;
215 vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // pNext;
216 NULL, // flags;
217 0u, // vertexBindingDescriptionCount;
218 1, // pVertexBindingDescriptions;
219 &vf_binding_desc, // vertexAttributeDescriptionCount;
220 1, // pVertexAttributeDescriptions;
221 &vf_attribute_desc};
222
223 PipelineCreateInfo pipelineCreateInfo(*m_pipelineLayout, *m_renderPass, 0, 0);
224 pipelineCreateInfo.addShader(
225 PipelineCreateInfo::PipelineShaderStage(*vs, "main", vk::VK_SHADER_STAGE_VERTEX_BIT));
226 pipelineCreateInfo.addShader(
227 PipelineCreateInfo::PipelineShaderStage(*fs, "main", vk::VK_SHADER_STAGE_FRAGMENT_BIT));
228 pipelineCreateInfo.addState(PipelineCreateInfo::InputAssemblerState(primitive));
229 pipelineCreateInfo.addState(PipelineCreateInfo::ColorBlendState(1, &attachmentState));
230 const vk::VkViewport viewport = vk::makeViewport(WIDTH, HEIGHT);
231 const vk::VkRect2D scissor = vk::makeRect2D(WIDTH, HEIGHT);
232 pipelineCreateInfo.addState(PipelineCreateInfo::ViewportState(1, std::vector<vk::VkViewport>(1, viewport),
233 std::vector<vk::VkRect2D>(1, scissor)));
234 pipelineCreateInfo.addState(
235 PipelineCreateInfo::DepthStencilState(true, true, vk::VK_COMPARE_OP_GREATER_OR_EQUAL));
236 pipelineCreateInfo.addState(PipelineCreateInfo::RasterizerState());
237 pipelineCreateInfo.addState(PipelineCreateInfo::MultiSampleState());
238 pipelineCreateInfo.addState(vf_info);
239 m_pipeline = vk::createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo);
240 }
241
242 {
243 // Vertex buffer
244 const size_t kBufferSize = numVertices * sizeof(tcu::Vec4);
245 m_vertexBuffer =
246 Buffer::createAndAlloc(vk, device, BufferCreateInfo(kBufferSize, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT),
247 m_context.getDefaultAllocator(), vk::MemoryRequirement::HostVisible);
248 }
249 }
250
setVertices(const vk::DeviceInterface & vk,std::vector<tcu::Vec4> vertices)251 void StateObjects::setVertices(const vk::DeviceInterface &vk, std::vector<tcu::Vec4> vertices)
252 {
253 const vk::VkDevice device = m_context.getDevice();
254
255 tcu::Vec4 *ptr = reinterpret_cast<tcu::Vec4 *>(m_vertexBuffer->getBoundMemory().getHostPtr());
256 std::copy(vertices.begin(), vertices.end(), ptr);
257
258 vk::flushAlloc(vk, device, m_vertexBuffer->getBoundMemory());
259 }
260
261 class PrimaryCommandBufferConcurrentTestInstance : public vkt::TestInstance
262 {
263 public:
264 PrimaryCommandBufferConcurrentTestInstance(vkt::Context &context);
265 ~PrimaryCommandBufferConcurrentTestInstance(void);
266
267 private:
268 tcu::TestStatus iterate(void);
269
270 enum
271 {
272 NUM_QUERIES_IN_POOL = 2,
273 QUERY_INDEX_CAPTURE_EMPTY = 0,
274 QUERY_INDEX_CAPTURE_DRAWCALL = 1,
275 NUM_VERTICES_IN_DRAWCALL = 3
276 };
277
278 std::unique_ptr<StateObjects> m_stateObjects;
279 vk::Move<vk::VkQueryPool> m_queryPools[NUM_QUERY_POOLS];
280 bool m_supportedQueryType[NUM_QUERY_POOLS];
281 };
282
PrimaryCommandBufferConcurrentTestInstance(vkt::Context & context)283 PrimaryCommandBufferConcurrentTestInstance::PrimaryCommandBufferConcurrentTestInstance(vkt::Context &context)
284 : TestInstance(context)
285 {
286 // Check support for multiple query types
287 {
288 for (uint32_t poolNdx = 0; poolNdx < NUM_QUERY_POOLS; poolNdx++)
289 m_supportedQueryType[poolNdx] = false;
290
291 uint32_t numSupportedQueryTypes = 0;
292 m_supportedQueryType[QUERY_TYPE_OCCLUSION] = true;
293 numSupportedQueryTypes++;
294
295 if (context.getDeviceFeatures().pipelineStatisticsQuery)
296 {
297 m_supportedQueryType[QUERY_TYPE_PIPELINE_STATISTICS] = true;
298 numSupportedQueryTypes++;
299 }
300
301 // Check support for timestamp queries
302 {
303 const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
304 const std::vector<vk::VkQueueFamilyProperties> queueProperties =
305 vk::getPhysicalDeviceQueueFamilyProperties(context.getInstanceInterface(), context.getPhysicalDevice());
306
307 DE_ASSERT(queueFamilyIndex < (uint32_t)queueProperties.size());
308
309 if (queueProperties[queueFamilyIndex].timestampValidBits)
310 {
311 m_supportedQueryType[QUERY_TYPE_TIMESTAMP] = true;
312 numSupportedQueryTypes++;
313 }
314 }
315 if (numSupportedQueryTypes < 2)
316 throw tcu::NotSupportedError("Device does not support multiple query types");
317 }
318
319 m_stateObjects = std::unique_ptr<StateObjects>(new StateObjects(
320 m_context.getDeviceInterface(), m_context, NUM_VERTICES_IN_DRAWCALL, vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST));
321
322 const vk::VkDevice device = m_context.getDevice();
323 const vk::DeviceInterface &vk = m_context.getDeviceInterface();
324
325 for (uint32_t poolNdx = 0; poolNdx < NUM_QUERY_POOLS; poolNdx++)
326 {
327 if (!m_supportedQueryType[poolNdx])
328 continue;
329
330 vk::VkQueryPoolCreateInfo queryPoolCreateInfo = {
331 vk::VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,
332 DE_NULL,
333 0u,
334 static_cast<vk::VkQueryType>(poolNdx),
335 NUM_QUERIES_IN_POOL,
336 0u,
337 };
338 if (poolNdx == QUERY_TYPE_PIPELINE_STATISTICS)
339 queryPoolCreateInfo.pipelineStatistics = vk::VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT;
340
341 m_queryPools[poolNdx] = createQueryPool(vk, device, &queryPoolCreateInfo, /*pAllocator*/ DE_NULL);
342 }
343
344 std::vector<tcu::Vec4> vertices(NUM_VERTICES_IN_DRAWCALL);
345 vertices[0] = tcu::Vec4(0.5, 0.5, 0.0, 1.0);
346 vertices[1] = tcu::Vec4(0.5, 0.0, 0.0, 1.0);
347 vertices[2] = tcu::Vec4(0.0, 0.5, 0.0, 1.0);
348 m_stateObjects->setVertices(vk, vertices);
349 }
350
~PrimaryCommandBufferConcurrentTestInstance(void)351 PrimaryCommandBufferConcurrentTestInstance::~PrimaryCommandBufferConcurrentTestInstance(void)
352 {
353 }
354
iterate(void)355 tcu::TestStatus PrimaryCommandBufferConcurrentTestInstance::iterate(void)
356 {
357 tcu::TestLog &log = m_context.getTestContext().getLog();
358 const vk::VkDevice device = m_context.getDevice();
359 const vk::VkQueue queue = m_context.getUniversalQueue();
360 const vk::DeviceInterface &vk = m_context.getDeviceInterface();
361
362 const CmdPoolCreateInfo cmdPoolCreateInfo(m_context.getUniversalQueueFamilyIndex());
363 vk::Move<vk::VkCommandPool> cmdPool = vk::createCommandPool(vk, device, &cmdPoolCreateInfo);
364
365 vk::Unique<vk::VkCommandBuffer> cmdBuffer(
366 vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
367
368 beginCommandBuffer(vk, *cmdBuffer);
369
370 initialTransitionColor2DImage(vk, *cmdBuffer, m_stateObjects->m_colorAttachmentImage->object(),
371 vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
372 vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
373 initialTransitionDepth2DImage(
374 vk, *cmdBuffer, m_stateObjects->m_DepthImage->object(), vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
375 vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
376 vk::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | vk::VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
377
378 std::vector<vk::VkClearValue> renderPassClearValues(2);
379 deMemset(&renderPassClearValues[0], 0, static_cast<int>(renderPassClearValues.size()) * sizeof(vk::VkClearValue));
380
381 for (uint32_t poolNdx = 0u; poolNdx < NUM_QUERY_POOLS; poolNdx++)
382 {
383 if (m_supportedQueryType[poolNdx])
384 vk.cmdResetQueryPool(*cmdBuffer, *m_queryPools[poolNdx], 0u, NUM_QUERIES_IN_POOL);
385 }
386
387 beginRenderPass(vk, *cmdBuffer, *m_stateObjects->m_renderPass, *m_stateObjects->m_framebuffer,
388 vk::makeRect2D(0, 0, StateObjects::WIDTH, StateObjects::HEIGHT),
389 (uint32_t)renderPassClearValues.size(), &renderPassClearValues[0]);
390
391 vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_stateObjects->m_pipeline);
392
393 vk::VkBuffer vertexBuffer = m_stateObjects->m_vertexBuffer->object();
394 const vk::VkDeviceSize vertexBufferOffset = 0;
395 vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
396
397 // Begin all queries
398 for (uint32_t poolNdx = 0u; poolNdx < QUERY_TYPE_TIMESTAMP; poolNdx++)
399 {
400 if (m_supportedQueryType[poolNdx])
401 vk.cmdBeginQuery(*cmdBuffer, *m_queryPools[poolNdx], QUERY_INDEX_CAPTURE_EMPTY, 0u);
402 }
403
404 // End first capture (should not have any result). Start the second one.
405 for (uint32_t poolNdx = 0u; poolNdx < QUERY_TYPE_TIMESTAMP; poolNdx++)
406 {
407 if (m_supportedQueryType[poolNdx])
408 {
409 vk.cmdEndQuery(*cmdBuffer, *m_queryPools[poolNdx], QUERY_INDEX_CAPTURE_EMPTY);
410 vk.cmdBeginQuery(*cmdBuffer, *m_queryPools[poolNdx], QUERY_INDEX_CAPTURE_DRAWCALL, 0u);
411 }
412 }
413
414 vk.cmdDraw(*cmdBuffer, NUM_VERTICES_IN_DRAWCALL, 1, 0, 0);
415
416 if (m_supportedQueryType[QUERY_TYPE_TIMESTAMP])
417 vk.cmdWriteTimestamp(*cmdBuffer, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
418 *m_queryPools[QUERY_TYPE_TIMESTAMP], QUERY_INDEX_CAPTURE_DRAWCALL);
419
420 for (uint32_t poolNdx = 0u; poolNdx < QUERY_TYPE_TIMESTAMP; poolNdx++)
421 {
422 if (m_supportedQueryType[poolNdx])
423 vk.cmdEndQuery(*cmdBuffer, *m_queryPools[poolNdx], QUERY_INDEX_CAPTURE_DRAWCALL);
424 }
425
426 endRenderPass(vk, *cmdBuffer);
427
428 transition2DImage(vk, *cmdBuffer, m_stateObjects->m_colorAttachmentImage->object(), vk::VK_IMAGE_ASPECT_COLOR_BIT,
429 vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
430 vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT,
431 vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT);
432
433 endCommandBuffer(vk, *cmdBuffer);
434
435 submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
436
437 uint64_t queryResults[NUM_QUERIES_IN_POOL] = {0};
438 size_t queryResultsSize = sizeof(queryResults);
439 bool passed = true;
440
441 // Occlusion and pipeline statistics queries verification
442 for (uint32_t poolNdx = 0; poolNdx < QUERY_TYPE_TIMESTAMP; poolNdx++)
443 {
444 if (m_supportedQueryType[poolNdx] == false)
445 continue;
446 vk::VkResult queryResult =
447 vk.getQueryPoolResults(device, *m_queryPools[poolNdx], 0, NUM_QUERIES_IN_POOL, queryResultsSize,
448 queryResults, sizeof(queryResults[0]), vk::VK_QUERY_RESULT_64_BIT);
449
450 if (queryResult == vk::VK_NOT_READY)
451 {
452 TCU_FAIL("Query result not available, but vkWaitIdle() was called.");
453 }
454
455 VK_CHECK(queryResult);
456 std::string name =
457 (poolNdx == QUERY_TYPE_OCCLUSION) ? "OcclusionQueryResults" : "PipelineStatisticsQueryResults";
458 std::string desc =
459 (poolNdx == QUERY_TYPE_OCCLUSION) ? "Occlusion query results" : "PipelineStatistics query results";
460 log << tcu::TestLog::Section(name, desc);
461 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(queryResults); ++ndx)
462 {
463 log << tcu::TestLog::Message << "query[slot == " << ndx << "] result == " << queryResults[ndx]
464 << tcu::TestLog::EndMessage;
465 }
466
467 for (uint32_t queryNdx = 0; queryNdx < DE_LENGTH_OF_ARRAY(queryResults); ++queryNdx)
468 {
469 if (queryNdx == QUERY_INDEX_CAPTURE_EMPTY && queryResults[queryNdx] != 0u)
470 {
471 log << tcu::TestLog::Message
472 << "vkGetQueryPoolResults returned "
473 "wrong value of query for index "
474 << queryNdx << ", expected any zero value, got " << queryResults[0] << "."
475 << tcu::TestLog::EndMessage;
476 passed = false;
477 }
478
479 if (queryNdx != QUERY_INDEX_CAPTURE_EMPTY && queryResults[queryNdx] == 0)
480 {
481 log << tcu::TestLog::Message
482 << "vkGetQueryPoolResults returned "
483 "wrong value of query for index "
484 << queryNdx << ", expected any non-zero value, got " << queryResults[0] << "."
485 << tcu::TestLog::EndMessage;
486 passed = false;
487 }
488 }
489 log << tcu::TestLog::EndSection;
490 }
491
492 // Timestamp query verification
493 if (m_supportedQueryType[QUERY_TYPE_TIMESTAMP])
494 {
495 std::pair<uint64_t, uint64_t> queryResultsWithAvailabilityBit[NUM_QUERIES_IN_POOL];
496 size_t queryResultsWithAvailabilityBitSize = sizeof(queryResultsWithAvailabilityBit);
497 vk::VkResult queryResult = vk.getQueryPoolResults(
498 device, *m_queryPools[QUERY_TYPE_TIMESTAMP], 0, NUM_QUERIES_IN_POOL, queryResultsWithAvailabilityBitSize,
499 &queryResultsWithAvailabilityBit[0], sizeof(queryResultsWithAvailabilityBit[0]),
500 vk::VK_QUERY_RESULT_64_BIT | vk::VK_QUERY_RESULT_WITH_AVAILABILITY_BIT);
501
502 if (queryResult != vk::VK_NOT_READY)
503 {
504 TCU_FAIL("We don't have available one query, it should return VK_NOT_READY");
505 }
506
507 log << tcu::TestLog::Section("TimestampQueryResults", "Timestamp query results");
508 for (int ndx = 0; ndx < NUM_QUERIES_IN_POOL; ++ndx)
509 {
510 log << tcu::TestLog::Message << "query[slot == " << ndx
511 << "] result == " << queryResultsWithAvailabilityBit[ndx].first << tcu::TestLog::EndMessage;
512 }
513
514 for (uint32_t queryNdx = 0; queryNdx < NUM_QUERIES_IN_POOL; ++queryNdx)
515 {
516 if (queryNdx == QUERY_INDEX_CAPTURE_EMPTY && (queryResultsWithAvailabilityBit[queryNdx].first != 0u ||
517 queryResultsWithAvailabilityBit[queryNdx].second != 0u))
518 {
519 log << tcu::TestLog::Message
520 << "vkGetQueryPoolResults returned "
521 "either wrong value of query for index "
522 << queryNdx << " (expected any zero value, got " << queryResultsWithAvailabilityBit[queryNdx].first
523 << ") or the result is available (" << queryResultsWithAvailabilityBit[queryNdx].second << ")"
524 << tcu::TestLog::EndMessage;
525 passed = false;
526 }
527
528 if (queryNdx != QUERY_INDEX_CAPTURE_EMPTY && (queryResultsWithAvailabilityBit[queryNdx].first == 0u ||
529 queryResultsWithAvailabilityBit[queryNdx].second == 0u))
530 {
531 log << tcu::TestLog::Message
532 << "vkGetQueryPoolResults returned "
533 "either wrong value of query for index "
534 << queryNdx << " (expected any non-zero value, got " << queryResults[0]
535 << ") or result is unavailable." << tcu::TestLog::EndMessage;
536 passed = false;
537 }
538 }
539 log << tcu::TestLog::EndSection;
540 }
541
542 if (passed)
543 {
544 return tcu::TestStatus(QP_TEST_RESULT_PASS, "Query result verification passed");
545 }
546 return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Query result verification failed");
547 }
548
549 class SecondaryCommandBufferConcurrentTestInstance : public vkt::TestInstance
550 {
551 public:
552 SecondaryCommandBufferConcurrentTestInstance(vkt::Context &context);
553 ~SecondaryCommandBufferConcurrentTestInstance(void);
554
555 private:
556 tcu::TestStatus iterate(void);
557
558 enum
559 {
560 NUM_QUERIES_IN_POOL = 2,
561 QUERY_INDEX_CAPTURE_EMPTY = 0,
562 QUERY_INDEX_CAPTURE_DRAWCALL = 1,
563 NUM_VERTICES_IN_DRAWCALL = 3
564 };
565
566 std::unique_ptr<StateObjects> m_stateObjects;
567 vk::Move<vk::VkQueryPool> m_queryPools[NUM_QUERY_POOLS];
568 bool m_supportedQueryType[NUM_QUERY_POOLS];
569 };
570
SecondaryCommandBufferConcurrentTestInstance(vkt::Context & context)571 SecondaryCommandBufferConcurrentTestInstance::SecondaryCommandBufferConcurrentTestInstance(vkt::Context &context)
572 : TestInstance(context)
573 {
574 // Check support for multiple query types
575 {
576 for (uint32_t poolNdx = 0; poolNdx < NUM_QUERY_POOLS; poolNdx++)
577 m_supportedQueryType[poolNdx] = false;
578
579 uint32_t numSupportedQueryTypes = 0;
580 m_supportedQueryType[QUERY_TYPE_OCCLUSION] = true;
581 numSupportedQueryTypes++;
582
583 if (context.getDeviceFeatures().pipelineStatisticsQuery)
584 {
585 m_supportedQueryType[QUERY_TYPE_PIPELINE_STATISTICS] = true;
586 numSupportedQueryTypes++;
587 }
588
589 // Check support for timestamp queries
590 {
591 const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
592 const std::vector<vk::VkQueueFamilyProperties> queueProperties =
593 vk::getPhysicalDeviceQueueFamilyProperties(context.getInstanceInterface(), context.getPhysicalDevice());
594
595 DE_ASSERT(queueFamilyIndex < (uint32_t)queueProperties.size());
596
597 if (queueProperties[queueFamilyIndex].timestampValidBits)
598 {
599 m_supportedQueryType[QUERY_TYPE_TIMESTAMP] = true;
600 numSupportedQueryTypes++;
601 }
602 }
603 if (numSupportedQueryTypes < 2)
604 throw tcu::NotSupportedError("Device does not support multiple query types");
605 }
606
607 m_stateObjects = std::unique_ptr<StateObjects>(new StateObjects(
608 m_context.getDeviceInterface(), m_context, NUM_VERTICES_IN_DRAWCALL, vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST));
609
610 const vk::VkDevice device = m_context.getDevice();
611 const vk::DeviceInterface &vk = m_context.getDeviceInterface();
612
613 for (uint32_t poolNdx = 0; poolNdx < NUM_QUERY_POOLS; poolNdx++)
614 {
615 if (!m_supportedQueryType[poolNdx])
616 continue;
617
618 vk::VkQueryPoolCreateInfo queryPoolCreateInfo = {
619 vk::VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,
620 DE_NULL,
621 0u,
622 static_cast<vk::VkQueryType>(poolNdx),
623 NUM_QUERIES_IN_POOL,
624 0u,
625 };
626 if (poolNdx == QUERY_TYPE_PIPELINE_STATISTICS)
627 queryPoolCreateInfo.pipelineStatistics = vk::VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT;
628
629 m_queryPools[poolNdx] = createQueryPool(vk, device, &queryPoolCreateInfo, /*pAllocator*/ DE_NULL);
630 }
631
632 std::vector<tcu::Vec4> vertices(NUM_VERTICES_IN_DRAWCALL);
633 vertices[0] = tcu::Vec4(0.5, 0.5, 0.0, 1.0);
634 vertices[1] = tcu::Vec4(0.5, 0.0, 0.0, 1.0);
635 vertices[2] = tcu::Vec4(0.0, 0.5, 0.0, 1.0);
636 m_stateObjects->setVertices(vk, vertices);
637 }
638
~SecondaryCommandBufferConcurrentTestInstance(void)639 SecondaryCommandBufferConcurrentTestInstance::~SecondaryCommandBufferConcurrentTestInstance(void)
640 {
641 }
642
beginSecondaryCommandBuffer(const vk::DeviceInterface & vk,const vk::VkCommandBuffer secondaryCmdBuffer,const vk::VkCommandBufferInheritanceInfo bufferInheritanceInfo)643 void beginSecondaryCommandBuffer(const vk::DeviceInterface &vk, const vk::VkCommandBuffer secondaryCmdBuffer,
644 const vk::VkCommandBufferInheritanceInfo bufferInheritanceInfo)
645 {
646 const vk::VkCommandBufferUsageFlags flags =
647 bufferInheritanceInfo.renderPass != DE_NULL ?
648 (vk::VkCommandBufferUsageFlags)vk::VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT :
649 (vk::VkCommandBufferUsageFlags)0u;
650 const vk::VkCommandBufferBeginInfo beginInfo = {
651 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
652 DE_NULL, // pNext
653 flags, // flags
654 &bufferInheritanceInfo, // pInheritanceInfo
655 };
656 VK_CHECK(vk.beginCommandBuffer(secondaryCmdBuffer, &beginInfo));
657 }
658
iterate(void)659 tcu::TestStatus SecondaryCommandBufferConcurrentTestInstance::iterate(void)
660 {
661 tcu::TestLog &log = m_context.getTestContext().getLog();
662 const vk::VkDevice device = m_context.getDevice();
663 const vk::VkQueue queue = m_context.getUniversalQueue();
664 const vk::DeviceInterface &vk = m_context.getDeviceInterface();
665 const bool inheritedQueries = m_context.getDeviceFeatures().inheritedQueries;
666
667 const CmdPoolCreateInfo cmdPoolCreateInfo(m_context.getUniversalQueueFamilyIndex());
668 vk::Move<vk::VkCommandPool> cmdPool = vk::createCommandPool(vk, device, &cmdPoolCreateInfo);
669
670 vk::Unique<vk::VkCommandBuffer> cmdBufferPrimary(
671 vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
672 vk::Unique<vk::VkCommandBuffer> cmdBufferSecondary(
673 vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY));
674
675 // Secondary command buffer recording.
676 {
677 // Begin secondary command buffer
678 const vk::VkCommandBufferInheritanceInfo secCmdBufInheritInfo = {
679 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
680 DE_NULL,
681 *m_stateObjects->m_renderPass, // renderPass
682 0u, // subpass
683 *m_stateObjects->m_framebuffer, // framebuffer
684 inheritedQueries ? VK_TRUE : VK_FALSE, // occlusionQueryEnable
685 (vk::VkQueryControlFlags)0u, // queryFlags
686 (vk::VkQueryPipelineStatisticFlags)0u, // pipelineStatistics
687 };
688 beginSecondaryCommandBuffer(vk, *cmdBufferSecondary, secCmdBufInheritInfo);
689
690 vk.cmdBindPipeline(*cmdBufferSecondary, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_stateObjects->m_pipeline);
691 vk::VkBuffer vertexBuffer = m_stateObjects->m_vertexBuffer->object();
692 const vk::VkDeviceSize vertexBufferOffset = 0;
693 vk.cmdBindVertexBuffers(*cmdBufferSecondary, 0, 1, &vertexBuffer, &vertexBufferOffset);
694
695 if (!inheritedQueries && m_supportedQueryType[QUERY_TYPE_OCCLUSION])
696 vk.cmdBeginQuery(*cmdBufferSecondary, *m_queryPools[QUERY_TYPE_OCCLUSION], QUERY_INDEX_CAPTURE_DRAWCALL,
697 0u);
698
699 // Run pipeline statistics queries capture in the second command buffer
700 if (m_supportedQueryType[QUERY_TYPE_PIPELINE_STATISTICS])
701 vk.cmdBeginQuery(*cmdBufferSecondary, *m_queryPools[QUERY_TYPE_PIPELINE_STATISTICS],
702 QUERY_INDEX_CAPTURE_DRAWCALL, 0u);
703
704 // Timestamp query happening in the secondary command buffer
705 if (m_supportedQueryType[QUERY_TYPE_TIMESTAMP])
706 vk.cmdWriteTimestamp(*cmdBufferSecondary, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
707 *m_queryPools[QUERY_TYPE_TIMESTAMP], QUERY_INDEX_CAPTURE_DRAWCALL);
708
709 vk.cmdDraw(*cmdBufferSecondary, NUM_VERTICES_IN_DRAWCALL, 1, 0, 0);
710
711 if (m_supportedQueryType[QUERY_TYPE_PIPELINE_STATISTICS])
712 vk.cmdEndQuery(*cmdBufferSecondary, *m_queryPools[QUERY_TYPE_PIPELINE_STATISTICS],
713 QUERY_INDEX_CAPTURE_DRAWCALL);
714
715 if (!inheritedQueries && m_supportedQueryType[QUERY_TYPE_OCCLUSION])
716 vk.cmdEndQuery(*cmdBufferSecondary, *m_queryPools[QUERY_TYPE_OCCLUSION], QUERY_INDEX_CAPTURE_DRAWCALL);
717
718 endCommandBuffer(vk, *cmdBufferSecondary);
719 }
720
721 // Primary command buffer recording
722 {
723 beginCommandBuffer(vk, *cmdBufferPrimary);
724
725 initialTransitionColor2DImage(vk, *cmdBufferPrimary, m_stateObjects->m_colorAttachmentImage->object(),
726 vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
727 vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
728 initialTransitionDepth2DImage(
729 vk, *cmdBufferPrimary, m_stateObjects->m_DepthImage->object(),
730 vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
731 vk::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | vk::VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
732
733 std::vector<vk::VkClearValue> renderPassClearValues(2);
734 deMemset(&renderPassClearValues[0], 0,
735 static_cast<int>(renderPassClearValues.size()) * sizeof(vk::VkClearValue));
736
737 for (uint32_t poolNdx = 0u; poolNdx < NUM_QUERY_POOLS; poolNdx++)
738 {
739 if (m_supportedQueryType[poolNdx])
740 vk.cmdResetQueryPool(*cmdBufferPrimary, *m_queryPools[poolNdx], 0u, NUM_QUERIES_IN_POOL);
741 }
742
743 for (uint32_t poolNdx = 0u; poolNdx < QUERY_TYPE_TIMESTAMP; poolNdx++)
744 {
745 if (m_supportedQueryType[poolNdx])
746 vk.cmdBeginQuery(*cmdBufferPrimary, *m_queryPools[poolNdx], QUERY_INDEX_CAPTURE_EMPTY, 0u);
747 }
748
749 for (uint32_t poolNdx = 0u; poolNdx < QUERY_TYPE_TIMESTAMP; poolNdx++)
750 {
751 if (m_supportedQueryType[poolNdx])
752 vk.cmdEndQuery(*cmdBufferPrimary, *m_queryPools[poolNdx], QUERY_INDEX_CAPTURE_EMPTY);
753 }
754
755 // Run oclussion queries capture in the primary command buffer, inherit the counters for the secondary command buffer
756 if (inheritedQueries && m_supportedQueryType[QUERY_TYPE_OCCLUSION])
757 vk.cmdBeginQuery(*cmdBufferPrimary, *m_queryPools[QUERY_TYPE_OCCLUSION], QUERY_INDEX_CAPTURE_DRAWCALL, 0u);
758
759 beginRenderPass(vk, *cmdBufferPrimary, *m_stateObjects->m_renderPass, *m_stateObjects->m_framebuffer,
760 vk::makeRect2D(0, 0, StateObjects::WIDTH, StateObjects::HEIGHT),
761 (uint32_t)renderPassClearValues.size(), &renderPassClearValues[0],
762 vk::VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
763
764 vk.cmdExecuteCommands(*cmdBufferPrimary, 1u, &cmdBufferSecondary.get());
765
766 endRenderPass(vk, *cmdBufferPrimary);
767
768 if (inheritedQueries && m_supportedQueryType[QUERY_TYPE_OCCLUSION])
769 vk.cmdEndQuery(*cmdBufferPrimary, *m_queryPools[QUERY_TYPE_OCCLUSION], QUERY_INDEX_CAPTURE_DRAWCALL);
770
771 transition2DImage(vk, *cmdBufferPrimary, m_stateObjects->m_colorAttachmentImage->object(),
772 vk::VK_IMAGE_ASPECT_COLOR_BIT, vk::VK_IMAGE_LAYOUT_GENERAL,
773 vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
774 vk::VK_ACCESS_TRANSFER_READ_BIT, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
775 vk::VK_PIPELINE_STAGE_TRANSFER_BIT);
776
777 endCommandBuffer(vk, *cmdBufferPrimary);
778 }
779
780 submitCommandsAndWait(vk, device, queue, cmdBufferPrimary.get());
781
782 uint64_t queryResults[NUM_QUERIES_IN_POOL] = {0};
783 size_t queryResultsSize = sizeof(queryResults);
784 bool passed = true;
785
786 // Occlusion and pipeline statistics queries verification
787 for (uint32_t poolNdx = 0; poolNdx < QUERY_TYPE_TIMESTAMP; poolNdx++)
788 {
789 if (!m_supportedQueryType[poolNdx])
790 continue;
791 vk::VkResult queryResult =
792 vk.getQueryPoolResults(device, *m_queryPools[poolNdx], 0, NUM_QUERIES_IN_POOL, queryResultsSize,
793 queryResults, sizeof(queryResults[0]), vk::VK_QUERY_RESULT_64_BIT);
794
795 if (queryResult == vk::VK_NOT_READY)
796 {
797 TCU_FAIL("Query result not available, but vkWaitIdle() was called.");
798 }
799
800 VK_CHECK(queryResult);
801 std::string name =
802 (poolNdx == QUERY_TYPE_OCCLUSION) ? "OcclusionQueryResults" : "PipelineStatisticsQueryResults";
803 std::string desc =
804 (poolNdx == QUERY_TYPE_OCCLUSION) ? "Occlusion query results" : "PipelineStatistics query results";
805 log << tcu::TestLog::Section(name, desc);
806 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(queryResults); ++ndx)
807 {
808 log << tcu::TestLog::Message << "query[slot == " << ndx << "] result == " << queryResults[ndx]
809 << tcu::TestLog::EndMessage;
810 }
811
812 for (uint32_t queryNdx = 0; queryNdx < DE_LENGTH_OF_ARRAY(queryResults); ++queryNdx)
813 {
814 if (queryNdx == QUERY_INDEX_CAPTURE_EMPTY && queryResults[queryNdx] != 0u)
815 {
816 log << tcu::TestLog::Message
817 << "vkGetQueryPoolResults returned "
818 "wrong value of query for index "
819 << queryNdx << ", expected any zero value, got " << queryResults[0] << "."
820 << tcu::TestLog::EndMessage;
821 passed = false;
822 }
823
824 if (queryNdx != QUERY_INDEX_CAPTURE_EMPTY && queryResults[queryNdx] == 0)
825 {
826 log << tcu::TestLog::Message
827 << "vkGetQueryPoolResults returned "
828 "wrong value of query for index "
829 << queryNdx << ", expected any non-zero value, got " << queryResults[0] << "."
830 << tcu::TestLog::EndMessage;
831 passed = false;
832 }
833 }
834 log << tcu::TestLog::EndSection;
835 }
836
837 // Timestamp query verification
838 if (m_supportedQueryType[QUERY_TYPE_TIMESTAMP])
839 {
840 std::pair<uint64_t, uint64_t> queryResultsWithAvailabilityBit[NUM_QUERIES_IN_POOL];
841 size_t queryResultsWithAvailabilityBitSize = sizeof(queryResultsWithAvailabilityBit);
842 vk::VkResult queryResult = vk.getQueryPoolResults(
843 device, *m_queryPools[QUERY_TYPE_TIMESTAMP], 0, NUM_QUERIES_IN_POOL, queryResultsWithAvailabilityBitSize,
844 &queryResultsWithAvailabilityBit[0], sizeof(queryResultsWithAvailabilityBit[0]),
845 vk::VK_QUERY_RESULT_64_BIT | vk::VK_QUERY_RESULT_WITH_AVAILABILITY_BIT);
846
847 if (queryResult != vk::VK_NOT_READY)
848 {
849 TCU_FAIL("We don't have available one query, it should return VK_NOT_READY");
850 }
851
852 log << tcu::TestLog::Section("TimestampQueryResults", "Timestamp query results");
853 for (int ndx = 0; ndx < NUM_QUERIES_IN_POOL; ++ndx)
854 {
855 log << tcu::TestLog::Message << "query[slot == " << ndx
856 << "] result == " << queryResultsWithAvailabilityBit[ndx].first << tcu::TestLog::EndMessage;
857 }
858
859 for (uint32_t queryNdx = 0; queryNdx < NUM_QUERIES_IN_POOL; ++queryNdx)
860 {
861 if (queryNdx == QUERY_INDEX_CAPTURE_EMPTY && (queryResultsWithAvailabilityBit[queryNdx].first != 0u ||
862 queryResultsWithAvailabilityBit[queryNdx].second != 0u))
863 {
864 log << tcu::TestLog::Message
865 << "vkGetQueryPoolResults returned "
866 "either wrong value of query for index "
867 << queryNdx << " (expected any zero value, got " << queryResultsWithAvailabilityBit[queryNdx].first
868 << ") or the result is available (" << queryResultsWithAvailabilityBit[queryNdx].second << ")"
869 << tcu::TestLog::EndMessage;
870 passed = false;
871 }
872
873 if (queryNdx != QUERY_INDEX_CAPTURE_EMPTY && (queryResultsWithAvailabilityBit[queryNdx].first == 0u ||
874 queryResultsWithAvailabilityBit[queryNdx].second == 0u))
875 {
876 log << tcu::TestLog::Message
877 << "vkGetQueryPoolResults returned "
878 "either wrong value of query for index "
879 << queryNdx << " (expected any non-zero value, got " << queryResults[0]
880 << ") or result is unavailable." << tcu::TestLog::EndMessage;
881 passed = false;
882 }
883 }
884 log << tcu::TestLog::EndSection;
885 }
886
887 if (passed)
888 {
889 return tcu::TestStatus(QP_TEST_RESULT_PASS, "Query result verification passed");
890 }
891 return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Query result verification failed");
892 }
893
894 template <class Instance>
895 class QueryPoolConcurrentTest : public vkt::TestCase
896 {
897 public:
QueryPoolConcurrentTest(tcu::TestContext & context,const char * name)898 QueryPoolConcurrentTest(tcu::TestContext &context, const char *name) : TestCase(context, name)
899 {
900 }
901
902 private:
createInstance(vkt::Context & context) const903 vkt::TestInstance *createInstance(vkt::Context &context) const
904 {
905 return new Instance(context);
906 }
907
initPrograms(vk::SourceCollections & programCollection) const908 void initPrograms(vk::SourceCollections &programCollection) const
909 {
910 const std::string fragSrc = std::string("#version 400\n"
911 "layout(location = 0) out vec4 out_FragColor;\n"
912 "void main()\n"
913 "{\n"
914 " out_FragColor = vec4(0.07, 0.48, 0.75, 1.0);\n"
915 " if ((int(gl_FragCoord.x) % 2) == (int(gl_FragCoord.y) % 2))\n"
916 " discard;\n"
917 "}");
918
919 programCollection.glslSources.add("frag") << glu::FragmentSource(fragSrc.c_str());
920
921 programCollection.glslSources.add("vert")
922 << glu::VertexSource("#version 430\n"
923 "layout(location = 0) in vec4 in_Position;\n"
924 "out gl_PerVertex { vec4 gl_Position; float gl_PointSize; };\n"
925 "void main() {\n"
926 " gl_Position = in_Position;\n"
927 " gl_PointSize = 1.0;\n"
928 "}\n");
929 }
930 };
931
932 } // namespace
933
QueryPoolConcurrentTests(tcu::TestContext & testCtx)934 QueryPoolConcurrentTests::QueryPoolConcurrentTests(tcu::TestContext &testCtx)
935 : TestCaseGroup(testCtx, "concurrent_queries")
936 {
937 /* Left blank on purpose */
938 }
939
~QueryPoolConcurrentTests(void)940 QueryPoolConcurrentTests::~QueryPoolConcurrentTests(void)
941 {
942 /* Left blank on purpose */
943 }
944
init(void)945 void QueryPoolConcurrentTests::init(void)
946 {
947 addChild(
948 new QueryPoolConcurrentTest<PrimaryCommandBufferConcurrentTestInstance>(m_testCtx, "primary_command_buffer"));
949 addChild(new QueryPoolConcurrentTest<SecondaryCommandBufferConcurrentTestInstance>(m_testCtx,
950 "secondary_command_buffer"));
951 }
952
953 } // namespace QueryPool
954 } // namespace vkt
955