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