1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2021 Google LLC
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief VK_EXT_primitives_generated_query Tests
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktPrimitivesGeneratedQueryTests.hpp"
25
26 #include "vktTestCase.hpp"
27 #include "vktTestGroupUtil.hpp"
28
29 #include "vkCmdUtil.hpp"
30 #include "vkImageUtil.hpp"
31 #include "vkMemUtil.hpp"
32 #include "vkObjUtil.hpp"
33 #include "vkQueryUtil.hpp"
34 #include "vkTypeUtil.hpp"
35 #include "vkBarrierUtil.hpp"
36
37 #include "tcuTestLog.hpp"
38 #include "tcuTextureUtil.hpp"
39 #include "tcuImageCompare.hpp"
40
41 #include <functional>
42 #include <map>
43 #include <set>
44
45 namespace vkt
46 {
47 namespace TransformFeedback
48 {
49 namespace
50 {
51 using namespace vk;
52
53 enum
54 {
55 IMAGE_WIDTH = 64,
56 IMAGE_HEIGHT = IMAGE_WIDTH,
57 };
58
59 enum QueryReadType
60 {
61 QUERY_READ_TYPE_GET,
62 QUERY_READ_TYPE_COPY,
63
64 QUERY_READ_TYPE_LAST
65 };
66
67 enum QueryResetType
68 {
69 QUERY_RESET_TYPE_QUEUE,
70 QUERY_RESET_TYPE_HOST,
71
72 QUERY_RESET_TYPE_LAST
73 };
74
75 enum QueryResultType
76 {
77 QUERY_RESULT_TYPE_32_BIT,
78 QUERY_RESULT_TYPE_64_BIT,
79 QUERY_RESULT_TYPE_PGQ_32_XFB_64,
80 QUERY_RESULT_TYPE_PGQ_64_XFB_32,
81
82 QUERY_RESULT_TYPE_LAST
83 };
84
85 enum ShaderStage
86 {
87 SHADER_STAGE_VERTEX,
88 SHADER_STAGE_TESSELLATION_EVALUATION,
89 SHADER_STAGE_GEOMETRY,
90
91 SHADER_STAGE_LAST
92 };
93
94 enum RasterizationCase
95 {
96 RAST_CASE_DEFAULT,
97 RAST_CASE_DISCARD,
98 RAST_CASE_EMPTY_FRAG,
99 RAST_CASE_NO_ATTACHMENT,
100 RAST_CASE_COLOR_WRITE_DISABLE_STATIC,
101 RAST_CASE_COLOR_WRITE_DISABLE_DYNAMIC,
102
103 RAST_CASE_LAST
104 };
105
106 enum VertexStream
107 {
108 VERTEX_STREAM_DEFAULT = -1,
109 VERTEX_STREAM_0 = 0,
110 VERTEX_STREAM_1 = 1,
111 VERTEX_STREAM_NONE = 2,
112 };
113
114 enum CommandBufferCase
115 {
116 CMD_BUF_CASE_SINGLE_DRAW,
117 CMD_BUF_CASE_TWO_DRAWS,
118
119 CMD_BUF_CASE_LAST
120 };
121
122 enum QueryOrder
123 {
124 QUERY_ORDER_PGQ_FIRST,
125 QUERY_ORDER_XFBQ_FIRST,
126
127 QUERY_ORDER_LAST
128 };
129
130 enum OutsideDraw
131 {
132 OUTSIDE_DRAW_NONE,
133 OUTSIDE_DRAW_BEFORE,
134 OUTSIDE_DRAW_AFTER,
135
136 OUTSIDE_DRAW_LAST
137 };
138
139 struct TestParameters
140 {
141 QueryReadType queryReadType;
142 QueryResetType queryResetType;
143 QueryResultType queryResultType;
144 ShaderStage shaderStage;
145 bool transformFeedback;
146 RasterizationCase rastCase;
147 bool depthStencilAttachment;
148 VkPrimitiveTopology primitiveTopology;
149 VertexStream pgqStream;
150 VertexStream xfbStream;
151 CommandBufferCase cmdBufCase;
152 const uint32_t queryCount;
153 QueryOrder queryOrder;
154 OutsideDraw outsideDraw;
155 const bool availabilityBit;
156
pgqDefaultvkt::TransformFeedback::__anon1ebbc75d0111::TestParameters157 bool pgqDefault(void) const
158 {
159 return pgqStream == VERTEX_STREAM_DEFAULT;
160 }
xfbDefaultvkt::TransformFeedback::__anon1ebbc75d0111::TestParameters161 bool xfbDefault(void) const
162 {
163 return xfbStream == VERTEX_STREAM_DEFAULT;
164 }
pgqStreamIndexvkt::TransformFeedback::__anon1ebbc75d0111::TestParameters165 uint32_t pgqStreamIndex(void) const
166 {
167 return pgqDefault() ? 0 : static_cast<uint32_t>(pgqStream);
168 }
xfbStreamIndexvkt::TransformFeedback::__anon1ebbc75d0111::TestParameters169 uint32_t xfbStreamIndex(void) const
170 {
171 return xfbDefault() ? 0 : static_cast<uint32_t>(xfbStream);
172 }
multipleStreamsvkt::TransformFeedback::__anon1ebbc75d0111::TestParameters173 bool multipleStreams(void) const
174 {
175 return pgqStreamIndex() != xfbStreamIndex();
176 }
nonZeroStreamsvkt::TransformFeedback::__anon1ebbc75d0111::TestParameters177 bool nonZeroStreams(void) const
178 {
179 return (pgqStreamIndex() != 0) || (xfbStreamIndex() != 0);
180 }
rastDiscardvkt::TransformFeedback::__anon1ebbc75d0111::TestParameters181 bool rastDiscard(void) const
182 {
183 return rastCase == RAST_CASE_DISCARD;
184 }
colorAttachmentvkt::TransformFeedback::__anon1ebbc75d0111::TestParameters185 bool colorAttachment(void) const
186 {
187 return !rastDiscard() && rastCase != RAST_CASE_NO_ATTACHMENT;
188 }
staticColorWriteDisablevkt::TransformFeedback::__anon1ebbc75d0111::TestParameters189 bool staticColorWriteDisable(void) const
190 {
191 return rastCase == RAST_CASE_COLOR_WRITE_DISABLE_STATIC;
192 }
dynamicColorWriteDisablevkt::TransformFeedback::__anon1ebbc75d0111::TestParameters193 bool dynamicColorWriteDisable(void) const
194 {
195 return rastCase == RAST_CASE_COLOR_WRITE_DISABLE_DYNAMIC;
196 }
colorWriteDisablevkt::TransformFeedback::__anon1ebbc75d0111::TestParameters197 bool colorWriteDisable(void) const
198 {
199 return staticColorWriteDisable() || dynamicColorWriteDisable();
200 }
201 };
202
203 enum ConcurrentTestType
204 {
205 CONCURRENT_TEST_TYPE_TWO_XFB_INSIDE_PGQ,
206 CONCURRENT_TEST_TYPE_PGQ_SECONDARY_CMD_BUFFER,
207 CONCURRENT_TEST_TYPE_PIPELINE_STATISTICS_1,
208 CONCURRENT_TEST_TYPE_PIPELINE_STATISTICS_2,
209 CONCURRENT_TEST_TYPE_PIPELINE_STATISTICS_3,
210
211 CONCURRENT_TEST_TYPE_LAST
212 };
213
214 struct ConcurrentTestParameters
215 {
216 ConcurrentTestType concurrentTestType;
217 QueryResultType queryResultType;
218 ShaderStage shaderStage;
219 VkPrimitiveTopology primitiveTopology;
220 VertexStream pgqStream;
221 VertexStream xfbStream;
222 bool indirect;
223
pgqDefaultvkt::TransformFeedback::__anon1ebbc75d0111::ConcurrentTestParameters224 bool pgqDefault(void) const
225 {
226 return pgqStream == VERTEX_STREAM_DEFAULT;
227 }
xfbDefaultvkt::TransformFeedback::__anon1ebbc75d0111::ConcurrentTestParameters228 bool xfbDefault(void) const
229 {
230 return xfbStream == VERTEX_STREAM_DEFAULT;
231 }
pgqStreamIndexvkt::TransformFeedback::__anon1ebbc75d0111::ConcurrentTestParameters232 uint32_t pgqStreamIndex(void) const
233 {
234 return pgqDefault() ? 0 : static_cast<uint32_t>(pgqStream);
235 }
xfbStreamIndexvkt::TransformFeedback::__anon1ebbc75d0111::ConcurrentTestParameters236 uint32_t xfbStreamIndex(void) const
237 {
238 return xfbDefault() ? 0 : static_cast<uint32_t>(xfbStream);
239 }
multipleStreamsvkt::TransformFeedback::__anon1ebbc75d0111::ConcurrentTestParameters240 bool multipleStreams(void) const
241 {
242 return pgqStreamIndex() != xfbStreamIndex();
243 }
nonZeroStreamsvkt::TransformFeedback::__anon1ebbc75d0111::ConcurrentTestParameters244 bool nonZeroStreams(void) const
245 {
246 return (pgqStreamIndex() != 0) || (xfbStreamIndex() != 0);
247 }
248 };
249
250 struct TopologyInfo
251 {
252 uint32_t primitiveSize; // Size of the primitive.
253 bool hasAdjacency; // True if topology has adjacency.
254 const char *inputString; // Layout qualifier identifier for geometry shader input.
255 const char *outputString; // Layout qualifier identifier for geometry shader output.
256 std::function<uint64_t(uint64_t)> getNumPrimitives; // Number of primitives generated.
257 std::function<uint64_t(uint64_t)> getNumVertices; // Number of vertices generated.
258 };
259
260 const std::map<VkPrimitiveTopology, TopologyInfo> topologyData = {
261 {VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
__anon1ebbc75d0302() 262 {1, false, "points", "points", [](uint64_t vtxCount) { return vtxCount; },
263 [](uint64_t primCount) { return primCount; }}},
264 {VK_PRIMITIVE_TOPOLOGY_LINE_LIST,
__anon1ebbc75d0502() 265 {2, false, "lines", "line_strip", [](uint64_t vtxCount) { return vtxCount / 2u; },
266 [](uint64_t primCount) { return primCount * 2u; }}},
267 {VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,
__anon1ebbc75d0702() 268 {2, false, "lines", "line_strip", [](uint64_t vtxCount) { return vtxCount - 1u; },
269 [](uint64_t primCount) { return primCount + 1u; }}},
270 {VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
__anon1ebbc75d0902() 271 {3, false, "triangles", "triangle_strip", [](uint64_t vtxCount) { return vtxCount / 3u; },
272 [](uint64_t primCount) { return primCount * 3u; }}},
273 {VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
__anon1ebbc75d0b02() 274 {3, false, "triangles", "triangle_strip", [](uint64_t vtxCount) { return vtxCount - 2u; },
275 [](uint64_t primCount) { return primCount + 2u; }}},
276 {VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,
__anon1ebbc75d0d02() 277 {3, false, "triangles", "triangle_strip", [](uint64_t vtxCount) { return vtxCount - 2u; },
278 [](uint64_t primCount) { return primCount + 2u; }}},
279 {VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY,
__anon1ebbc75d0f02() 280 {2, true, "lines_adjacency", "line_strip", [](uint64_t vtxCount) { return vtxCount / 4u; },
281 [](uint64_t primCount) { return primCount * 4u; }}},
282 {VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY,
__anon1ebbc75d1102() 283 {2, true, "lines_adjacency", "line_strip", [](uint64_t vtxCount) { return vtxCount - 3u; },
284 [](uint64_t primCount) { return primCount + 3u; }}},
285 {VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY,
__anon1ebbc75d1302() 286 {3, true, "triangles_adjacency", "triangle_strip", [](uint64_t vtxCount) { return vtxCount / 6u; },
287 [](uint64_t primCount) { return primCount * 6u; }}},
288 {VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY,
__anon1ebbc75d1502() 289 {3, true, "triangles_adjacency", "triangle_strip", [](uint64_t vtxCount) { return (vtxCount - 4u) / 2u; },
290 [](uint64_t primCount) { return primCount * 2u + 4; }}},
291 {VK_PRIMITIVE_TOPOLOGY_PATCH_LIST,
__anon1ebbc75d1702() 292 {3, false, "ERROR", "ERROR", [](uint64_t vtxCount) { return vtxCount / 3u; },
293 [](uint64_t primCount) { return primCount * 3u; }}},
294 };
295
296 class PrimitivesGeneratedQueryTestInstance : public vkt::TestInstance
297 {
298 public:
PrimitivesGeneratedQueryTestInstance(vkt::Context & context,const TestParameters & parameters)299 PrimitivesGeneratedQueryTestInstance(vkt::Context &context, const TestParameters ¶meters)
300 : vkt::TestInstance(context)
301 , m_parameters(parameters)
302 {
303 }
304
305 private:
306 tcu::TestStatus iterate(void);
307 VkFormat selectDepthStencilFormat(void);
308 Move<VkPipeline> makeGraphicsPipeline(const DeviceInterface &vk, const VkDevice device,
309 const VkRenderPass renderPass);
310 void fillVertexBuffer(tcu::Vec2 *vertices, const uint64_t primitivesGenerated);
311 const TestParameters m_parameters;
312 };
313
iterate(void)314 tcu::TestStatus PrimitivesGeneratedQueryTestInstance::iterate(void)
315 {
316 const DeviceInterface &vk = m_context.getDeviceInterface();
317 const VkDevice device = m_context.getDevice();
318 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
319 const VkQueue queue = m_context.getUniversalQueue();
320 Allocator &allocator = m_context.getDefaultAllocator();
321
322 using ImageVec = std::vector<Move<VkImage>>;
323 using AllocVec = std::vector<de::MovePtr<Allocation>>;
324
325 const VkFormat colorFormat = m_parameters.colorAttachment() ? VK_FORMAT_R8G8B8A8_UNORM : VK_FORMAT_UNDEFINED;
326 ImageVec colorImages;
327 AllocVec colorImageAllocations;
328
329 if (m_parameters.colorAttachment())
330 {
331 const VkImageCreateInfo colorImageCreateInfo = {
332 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType
333 DE_NULL, // const void* pNext
334 0u, // VkImageCreateFlags flags
335 VK_IMAGE_TYPE_2D, // VkImageType imageType
336 colorFormat, // VkFormat format
337 makeExtent3D(IMAGE_WIDTH, IMAGE_HEIGHT, 1), // VkExtent3D extent
338 1u, // uint32_t mipLevels
339 1u, // uint32_t arrayLayers
340 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
341 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling
342 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, // VkImageUsageFlags usage
343 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode
344 0u, // uint32_t queueFamilyIndexCount
345 DE_NULL, // const uint32_t* pQueueFamilyIndices
346 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout
347 };
348
349 for (uint32_t queryIdx = 0u; queryIdx < m_parameters.queryCount; ++queryIdx)
350 {
351 auto colorImage = makeImage(vk, device, colorImageCreateInfo);
352 auto colorImageAllocation = bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any);
353
354 colorImages.emplace_back(colorImage);
355 colorImageAllocations.emplace_back(colorImageAllocation);
356 }
357 }
358
359 const VkFormat dsFormat = m_parameters.depthStencilAttachment ?
360 PrimitivesGeneratedQueryTestInstance::selectDepthStencilFormat() :
361 VK_FORMAT_UNDEFINED;
362
363 if (m_parameters.depthStencilAttachment && dsFormat == VK_FORMAT_UNDEFINED)
364 return tcu::TestStatus::fail("VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT feature must be supported for at "
365 "least one of VK_FORMAT_D24_UNORM_S8_UINT and VK_FORMAT_D32_SFLOAT_S8_UINT.");
366
367 ImageVec dsImages;
368 AllocVec dsImageAllocations;
369
370 if (m_parameters.depthStencilAttachment)
371 {
372 const VkImageCreateInfo dsImageCreateInfo = {
373 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType
374 DE_NULL, // const void* pNext
375 0u, // VkImageCreateFlags flags
376 VK_IMAGE_TYPE_2D, // VkImageType imageType
377 dsFormat, // VkFormat format
378 makeExtent3D(IMAGE_WIDTH, IMAGE_HEIGHT, 1), // VkExtent3D extent
379 1u, // uint32_t mipLevels
380 1u, // uint32_t arrayLayers
381 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
382 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling
383 VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, // VkImageUsageFlags usage
384 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode
385 0u, // uint32_t queueFamilyIndexCount
386 DE_NULL, // const uint32_t* pQueueFamilyIndices
387 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout
388 };
389
390 for (uint32_t queryIdx = 0u; queryIdx < m_parameters.queryCount; ++queryIdx)
391 {
392 auto dsImage = makeImage(vk, device, dsImageCreateInfo);
393 auto dsImageAllocation = bindImage(vk, device, allocator, *dsImage, MemoryRequirement::Any);
394
395 dsImages.emplace_back(dsImage);
396 dsImageAllocations.emplace_back(dsImageAllocation);
397 }
398 }
399
400 const VkDeviceSize primitivesGenerated = 32;
401 const uint32_t baseMipLevel = 0;
402 const uint32_t levelCount = 1;
403 const uint32_t baseArrayLayer = 0;
404 const uint32_t layerCount = 1;
405
406 using ImageViewVec = std::vector<Move<VkImageView>>;
407
408 ImageViewVec colorImageViews;
409 ImageViewVec dsImageViews;
410
411 for (uint32_t queryIdx = 0u; queryIdx < m_parameters.queryCount; ++queryIdx)
412 {
413 if (m_parameters.colorAttachment())
414 {
415 const VkImageSubresourceRange colorSubresourceRange = makeImageSubresourceRange(
416 VK_IMAGE_ASPECT_COLOR_BIT, baseMipLevel, levelCount, baseArrayLayer, layerCount);
417 auto colorImageView = makeImageView(vk, device, *colorImages.at(queryIdx), VK_IMAGE_VIEW_TYPE_2D,
418 colorFormat, colorSubresourceRange);
419 colorImageViews.emplace_back(colorImageView);
420 }
421
422 if (m_parameters.depthStencilAttachment)
423 {
424 const VkImageSubresourceRange dsSubresourceRange =
425 makeImageSubresourceRange((VK_IMAGE_ASPECT_DEPTH_BIT | vk::VK_IMAGE_ASPECT_STENCIL_BIT), baseMipLevel,
426 levelCount, baseArrayLayer, layerCount);
427 auto dsImageView =
428 makeImageView(vk, device, *dsImages.at(queryIdx), VK_IMAGE_VIEW_TYPE_2D, dsFormat, dsSubresourceRange);
429 dsImageViews.emplace_back(dsImageView);
430 }
431 }
432
433 using FramebufferVec = std::vector<Move<VkFramebuffer>>;
434
435 const Unique<VkRenderPass> renderPass(
436 makeRenderPass(vk, device, colorFormat, dsFormat, VK_ATTACHMENT_LOAD_OP_DONT_CARE));
437 const Unique<VkPipeline> pipeline(
438 PrimitivesGeneratedQueryTestInstance::makeGraphicsPipeline(vk, device, *renderPass));
439 FramebufferVec framebuffers;
440
441 for (uint32_t queryIdx = 0u; queryIdx < m_parameters.queryCount; ++queryIdx)
442 {
443 std::vector<VkImageView> imageViews;
444
445 if (m_parameters.colorAttachment())
446 imageViews.push_back(*colorImageViews.at(queryIdx));
447
448 if (m_parameters.depthStencilAttachment)
449 imageViews.push_back(*dsImageViews.at(queryIdx));
450
451 auto framebuffer = makeFramebuffer(vk, device, *renderPass, (uint32_t)imageViews.size(), imageViews.data(),
452 IMAGE_WIDTH, IMAGE_HEIGHT);
453 framebuffers.emplace_back(framebuffer);
454 }
455
456 Move<VkBuffer> vtxBuffer;
457 de::MovePtr<Allocation> vtxBufferAlloc;
458
459 {
460 const VkBufferUsageFlags usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
461 const std::vector<uint32_t> queueFamilyIndices(1, queueFamilyIndex);
462 const VkDeviceSize vtxBufferSize =
463 topologyData.at(m_parameters.primitiveTopology).getNumVertices(primitivesGenerated) * sizeof(tcu::Vec2);
464 const VkBufferCreateInfo createInfo = makeBufferCreateInfo(vtxBufferSize, usage, queueFamilyIndices);
465
466 vtxBuffer = createBuffer(vk, device, &createInfo);
467 vtxBufferAlloc =
468 allocator.allocate(getBufferMemoryRequirements(vk, device, *vtxBuffer), MemoryRequirement::HostVisible);
469 }
470
471 const VkCommandPoolCreateFlags cmdPoolCreateFlags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
472 const VkCommandBufferLevel cmdBufferLevel = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
473 const Unique<VkCommandPool> cmdPool(createCommandPool(vk, device, cmdPoolCreateFlags, queueFamilyIndex));
474 const Unique<VkCommandBuffer> cmdBuffer(allocateCommandBuffer(vk, device, *cmdPool, cmdBufferLevel));
475 const auto resetCmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, cmdBufferLevel);
476
477 const bool pgq64 = (m_parameters.queryResultType == QUERY_RESULT_TYPE_64_BIT ||
478 m_parameters.queryResultType == QUERY_RESULT_TYPE_PGQ_64_XFB_32);
479 const bool xfb64 = (m_parameters.queryResultType == QUERY_RESULT_TYPE_64_BIT ||
480 m_parameters.queryResultType == QUERY_RESULT_TYPE_PGQ_32_XFB_64);
481 const VkQueryResultFlags availabilityFlags =
482 (m_parameters.availabilityBit ? VK_QUERY_RESULT_WITH_AVAILABILITY_BIT : 0);
483 const size_t pgqValuesPerQuery = (m_parameters.availabilityBit ? 2 : 1);
484 const size_t xfbValuesPerQuery = (m_parameters.availabilityBit ? 3 : 2);
485 const size_t pgqResultSize = (pgq64 ? sizeof(uint64_t) : sizeof(uint32_t)) * pgqValuesPerQuery;
486 const size_t xfbResultSize = (xfb64 ? sizeof(uint64_t) : sizeof(uint32_t)) * xfbValuesPerQuery;
487 const size_t pgqResultBufferSize = pgqResultSize * m_parameters.queryCount;
488 const size_t xfbResultBufferSize = xfbResultSize * m_parameters.queryCount;
489 const VkQueryResultFlags pgqResultWidthBit = pgq64 ? VK_QUERY_RESULT_64_BIT : 0;
490 const VkQueryResultFlags xfbResultWidthBit = xfb64 ? VK_QUERY_RESULT_64_BIT : 0;
491 const VkQueryResultFlags pgqResultFlags = VK_QUERY_RESULT_WAIT_BIT | pgqResultWidthBit | availabilityFlags;
492 const VkQueryResultFlags xfbResultFlags = VK_QUERY_RESULT_WAIT_BIT | xfbResultWidthBit | availabilityFlags;
493
494 std::vector<uint8_t> pgqResults(pgqResultBufferSize, 255u);
495 std::vector<uint8_t> xfbResults(xfbResultBufferSize, 255u);
496
497 const VkQueryPoolCreateInfo pgqCreateInfo = {
498 VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, // VkStructureType sType
499 DE_NULL, // const void* pNext
500 0u, // VkQueryPoolCreateFlags flags
501 VK_QUERY_TYPE_PRIMITIVES_GENERATED_EXT, // VkQueryType queryType
502 m_parameters.queryCount, // uint32_t queryCount
503 0u, // VkQueryPipelineStatisticFlags pipelineStatistics
504 };
505
506 const Unique<VkQueryPool> pgqPool(createQueryPool(vk, device, &pgqCreateInfo));
507 Move<VkQueryPool> xfbPool;
508
509 if (m_parameters.transformFeedback)
510 {
511 const VkQueryPoolCreateInfo xfbCreateInfo = {
512 VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, // VkStructureType sType
513 DE_NULL, // const void* pNext
514 0u, // VkQueryPoolCreateFlags flags
515 VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT, // VkQueryType queryType
516 m_parameters.queryCount, // uint32_t queryCount
517 0u, // VkQueryPipelineStatisticFlags pipelineStatistics
518 };
519
520 xfbPool = createQueryPool(vk, device, &xfbCreateInfo);
521 }
522
523 Move<VkBuffer> pgqResultsBuffer;
524 Move<VkBuffer> xfbResultsBuffer;
525 de::MovePtr<Allocation> pgqResultsBufferAlloc;
526 de::MovePtr<Allocation> xfbResultsBufferAlloc;
527
528 if (m_parameters.queryReadType == QUERY_READ_TYPE_COPY)
529 {
530 const VkBufferUsageFlags usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
531 const std::vector<uint32_t> queueFamilyIndices(1, queueFamilyIndex);
532 const VkBufferCreateInfo pgqBufferCreateInfo =
533 makeBufferCreateInfo(pgqResultBufferSize, usage, queueFamilyIndices);
534
535 pgqResultsBuffer = createBuffer(vk, device, &pgqBufferCreateInfo);
536 pgqResultsBufferAlloc = allocator.allocate(getBufferMemoryRequirements(vk, device, *pgqResultsBuffer),
537 MemoryRequirement::HostVisible);
538
539 VK_CHECK(vk.bindBufferMemory(device, *pgqResultsBuffer, pgqResultsBufferAlloc->getMemory(),
540 pgqResultsBufferAlloc->getOffset()));
541
542 if (m_parameters.transformFeedback)
543 {
544 const VkBufferCreateInfo xfbBufferCreateInfo =
545 makeBufferCreateInfo(xfbResultBufferSize, usage, queueFamilyIndices);
546
547 xfbResultsBuffer = createBuffer(vk, device, &xfbBufferCreateInfo);
548 xfbResultsBufferAlloc = allocator.allocate(getBufferMemoryRequirements(vk, device, *xfbResultsBuffer),
549 MemoryRequirement::HostVisible);
550
551 VK_CHECK(vk.bindBufferMemory(device, *xfbResultsBuffer, xfbResultsBufferAlloc->getMemory(),
552 xfbResultsBufferAlloc->getOffset()));
553 }
554 }
555
556 const VkDeviceSize primitivesWritten = primitivesGenerated - 3;
557 const VkDeviceSize verticesWritten =
558 topologyData.at(m_parameters.primitiveTopology).getNumVertices(primitivesWritten);
559 const VkDeviceSize primitiveSize =
560 m_parameters.nonZeroStreams() ? 1 : topologyData.at(m_parameters.primitiveTopology).primitiveSize;
561 const VkDeviceSize bytesPerVertex = 4 * sizeof(float);
562 const VkDeviceSize xfbBufferSize = primitivesWritten * primitiveSize * bytesPerVertex;
563
564 using BufferVec = std::vector<Move<VkBuffer>>;
565
566 BufferVec xfbBuffers;
567 AllocVec xfbBufferAllocs;
568
569 if (m_parameters.transformFeedback)
570 {
571 const VkBufferUsageFlags usage = VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT;
572 const std::vector<uint32_t> queueFamilyIndices(1, queueFamilyIndex);
573 const VkBufferCreateInfo createInfo = makeBufferCreateInfo(xfbBufferSize, usage, queueFamilyIndices);
574
575 for (uint32_t queryIdx = 0u; queryIdx < m_parameters.queryCount; ++queryIdx)
576 {
577 auto xfbBuffer = createBuffer(vk, device, &createInfo);
578 auto xfbBufferAlloc =
579 allocator.allocate(getBufferMemoryRequirements(vk, device, *xfbBuffer), MemoryRequirement::HostVisible);
580
581 VK_CHECK(vk.bindBufferMemory(device, *xfbBuffer, xfbBufferAlloc->getMemory(), xfbBufferAlloc->getOffset()));
582
583 xfbBuffers.emplace_back(xfbBuffer);
584 xfbBufferAllocs.emplace_back(xfbBufferAlloc);
585 }
586 }
587
588 fillVertexBuffer(static_cast<tcu::Vec2 *>(vtxBufferAlloc.get()->getHostPtr()), primitivesGenerated);
589
590 VK_CHECK(vk.bindBufferMemory(device, *vtxBuffer, vtxBufferAlloc->getMemory(), vtxBufferAlloc->getOffset()));
591
592 // After query pool creation, each query must be reset before it is used.
593 //
594 // When resetting them using a queue, we will submit a separate command buffer with the reset operation and wait for it to
595 // complete. This will make sure queries are properly reset before we attempt to get results from them. This is needed because
596 // we're not going to wait for any fence when using vkGetQueryPoolResults, so there's a potential race condition with
597 // vkGetQueryPoolResults attempting to get results before queries are properly reset, which is against the spec.
598 if (m_parameters.queryResetType == QUERY_RESET_TYPE_QUEUE)
599 {
600 beginCommandBuffer(vk, *resetCmdBuffer);
601 vk.cmdResetQueryPool(*resetCmdBuffer, *pgqPool, 0u, m_parameters.queryCount);
602 if (m_parameters.transformFeedback)
603 vk.cmdResetQueryPool(*resetCmdBuffer, *xfbPool, 0u, m_parameters.queryCount);
604 endCommandBuffer(vk, *resetCmdBuffer);
605 submitCommandsAndWait(vk, device, queue, *resetCmdBuffer);
606 }
607
608 beginCommandBuffer(vk, *cmdBuffer);
609 {
610 const VkDeviceSize vertexBufferOffset = static_cast<VkDeviceSize>(0);
611
612 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
613
614 vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &vtxBuffer.get(), &vertexBufferOffset);
615
616 for (uint32_t queryIdx = 0u; queryIdx < m_parameters.queryCount; ++queryIdx)
617 {
618 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffers.at(queryIdx),
619 makeRect2D(makeExtent2D(IMAGE_WIDTH, IMAGE_HEIGHT)));
620 {
621 const VkQueryControlFlags queryControlFlags = 0;
622
623 const uint32_t firstCounterBuffer = 0;
624 const uint32_t counterBufferCount = 0;
625 const VkBuffer *counterBuffers = DE_NULL;
626 const VkDeviceSize *counterBufferOffsets = DE_NULL;
627
628 const uint32_t vertexCount = static_cast<uint32_t>(
629 topologyData.at(m_parameters.primitiveTopology).getNumVertices(primitivesGenerated));
630 const uint32_t instanceCount = 1u;
631 const uint32_t firstVertex = 0u;
632 const uint32_t firstInstance = 0u;
633
634 if (m_parameters.dynamicColorWriteDisable())
635 {
636 const uint32_t attachmentCount = 1;
637 const VkBool32 colorWriteEnables = VK_FALSE;
638
639 vk.cmdSetColorWriteEnableEXT(*cmdBuffer, attachmentCount, &colorWriteEnables);
640 }
641
642 if (m_parameters.outsideDraw == OUTSIDE_DRAW_BEFORE)
643 vk.cmdDraw(*cmdBuffer, vertexCount, instanceCount, firstVertex, firstInstance);
644
645 if (m_parameters.queryOrder == QUERY_ORDER_PGQ_FIRST)
646 {
647 if (m_parameters.pgqDefault())
648 vk.cmdBeginQuery(*cmdBuffer, *pgqPool, queryIdx, queryControlFlags);
649 else
650 vk.cmdBeginQueryIndexedEXT(*cmdBuffer, *pgqPool, queryIdx, queryControlFlags,
651 m_parameters.pgqStreamIndex());
652 }
653
654 if (m_parameters.transformFeedback)
655 {
656 const uint32_t firstBinding = 0;
657 const uint32_t bindingCount = 1;
658 const VkDeviceSize offset = 0;
659
660 vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, firstBinding, bindingCount,
661 &*xfbBuffers.at(queryIdx), &offset, &xfbBufferSize);
662
663 if (m_parameters.xfbDefault())
664 vk.cmdBeginQuery(*cmdBuffer, *xfbPool, queryIdx, queryControlFlags);
665 else
666 vk.cmdBeginQueryIndexedEXT(*cmdBuffer, *xfbPool, queryIdx, queryControlFlags,
667 m_parameters.xfbStreamIndex());
668
669 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, firstCounterBuffer, counterBufferCount, counterBuffers,
670 counterBufferOffsets);
671 }
672
673 if (m_parameters.queryOrder != QUERY_ORDER_PGQ_FIRST)
674 {
675 if (m_parameters.pgqDefault())
676 vk.cmdBeginQuery(*cmdBuffer, *pgqPool, queryIdx, queryControlFlags);
677 else
678 vk.cmdBeginQueryIndexedEXT(*cmdBuffer, *pgqPool, queryIdx, queryControlFlags,
679 m_parameters.pgqStreamIndex());
680 }
681
682 vk.cmdDraw(*cmdBuffer, vertexCount, instanceCount, firstVertex, firstInstance);
683
684 if (m_parameters.cmdBufCase == CMD_BUF_CASE_TWO_DRAWS)
685 vk.cmdDraw(*cmdBuffer, vertexCount, instanceCount, firstVertex, firstInstance);
686
687 if (m_parameters.pgqDefault())
688 vk.cmdEndQuery(*cmdBuffer, *pgqPool, queryIdx);
689 else
690 vk.cmdEndQueryIndexedEXT(*cmdBuffer, *pgqPool, queryIdx, m_parameters.pgqStreamIndex());
691
692 if (m_parameters.transformFeedback)
693 {
694 if (m_parameters.xfbDefault())
695 vk.cmdEndQuery(*cmdBuffer, *xfbPool, queryIdx);
696 else
697 vk.cmdEndQueryIndexedEXT(*cmdBuffer, *xfbPool, queryIdx, m_parameters.xfbStreamIndex());
698
699 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, firstCounterBuffer, counterBufferCount, counterBuffers,
700 counterBufferOffsets);
701 }
702
703 if (m_parameters.outsideDraw == OUTSIDE_DRAW_AFTER)
704 vk.cmdDraw(*cmdBuffer, vertexCount, instanceCount, firstVertex, firstInstance);
705 }
706 endRenderPass(vk, *cmdBuffer);
707 }
708
709 if (m_parameters.queryReadType == QUERY_READ_TYPE_COPY)
710 {
711 VkBufferMemoryBarrier bufferBarrier = {
712 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType
713 DE_NULL, // const void* pNext
714 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask
715 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask
716 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex
717 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex
718 *pgqResultsBuffer, // VkBuffer buffer
719 0u, // VkDeviceSize offset
720 VK_WHOLE_SIZE // VkDeviceSize size
721 };
722
723 vk.cmdCopyQueryPoolResults(*cmdBuffer, *pgqPool, 0u, m_parameters.queryCount, *pgqResultsBuffer, 0u,
724 pgqResultSize, pgqResultFlags);
725 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u,
726 DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
727
728 if (m_parameters.transformFeedback)
729 {
730 bufferBarrier.buffer = *xfbResultsBuffer;
731 vk.cmdCopyQueryPoolResults(*cmdBuffer, *xfbPool, 0u, m_parameters.queryCount, *xfbResultsBuffer, 0u,
732 xfbResultSize, xfbResultFlags);
733 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u,
734 DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
735 }
736 }
737 }
738 vk::endCommandBuffer(vk, *cmdBuffer);
739
740 // After query pool creation, each query must be reset before it is used.
741 if (m_parameters.queryResetType == QUERY_RESET_TYPE_HOST)
742 {
743 vk.resetQueryPool(device, *pgqPool, 0u, m_parameters.queryCount);
744
745 if (m_parameters.transformFeedback)
746 vk.resetQueryPool(device, *xfbPool, 0u, m_parameters.queryCount);
747 }
748
749 const auto fence = submitCommands(vk, device, queue, *cmdBuffer);
750
751 // To make it more interesting, attempt to get results with WAIT before waiting for the fence.
752 if (m_parameters.queryReadType == QUERY_READ_TYPE_GET)
753 {
754 vk.getQueryPoolResults(device, *pgqPool, 0u, m_parameters.queryCount, pgqResults.size(), pgqResults.data(),
755 pgqResultSize, pgqResultFlags);
756
757 if (m_parameters.transformFeedback)
758 vk.getQueryPoolResults(device, *xfbPool, 0u, m_parameters.queryCount, xfbResults.size(), xfbResults.data(),
759 xfbResultSize, xfbResultFlags);
760 }
761
762 waitForFence(vk, device, *fence);
763
764 if (m_parameters.queryReadType == QUERY_READ_TYPE_COPY)
765 {
766 invalidateAlloc(vk, device, *pgqResultsBufferAlloc);
767 deMemcpy(pgqResults.data(), pgqResultsBufferAlloc->getHostPtr(), pgqResults.size());
768
769 if (m_parameters.transformFeedback)
770 {
771 invalidateAlloc(vk, device, *xfbResultsBufferAlloc);
772 deMemcpy(xfbResults.data(), xfbResultsBufferAlloc->getHostPtr(), xfbResults.size());
773 }
774 }
775
776 // Validate counters.
777 for (uint32_t queryIdx = 0u; queryIdx < m_parameters.queryCount; ++queryIdx)
778 {
779 union QueryResults
780 {
781 uint32_t elements32[3];
782 uint64_t elements64[3];
783 };
784
785 const QueryResults *pgqCounters =
786 reinterpret_cast<QueryResults *>(pgqResults.data() + queryIdx * pgqResultSize);
787 const QueryResults *xfbCounters =
788 reinterpret_cast<QueryResults *>(xfbResults.data() + queryIdx * xfbResultSize);
789 const uint64_t pgqGenerated =
790 pgq64 ? pgqCounters->elements64[0] : static_cast<uint64_t>(pgqCounters->elements32[0]);
791 const uint64_t xfbWritten =
792 xfb64 ? xfbCounters->elements64[0] : static_cast<uint64_t>(xfbCounters->elements32[0]);
793 const uint64_t xfbGenerated =
794 xfb64 ? xfbCounters->elements64[1] : static_cast<uint64_t>(xfbCounters->elements32[1]);
795 const uint32_t drawCount = (m_parameters.cmdBufCase == CMD_BUF_CASE_TWO_DRAWS) ? 2u : 1u;
796 const uint64_t pgqAvailability =
797 (m_parameters.availabilityBit ?
798 (pgq64 ? pgqCounters->elements64[1] : static_cast<uint64_t>(pgqCounters->elements32[1])) :
799 1);
800 const uint64_t xfbAvailability =
801 (m_parameters.availabilityBit ?
802 (xfb64 ? xfbCounters->elements64[2] : static_cast<uint64_t>(xfbCounters->elements32[2])) :
803 1);
804 tcu::TestLog &log = m_context.getTestContext().getLog();
805
806 if (queryIdx == 0u)
807 {
808 log << tcu::TestLog::Message << "primitivesGenerated: " << primitivesGenerated << "\n"
809 << "primitivesWritten: " << primitivesWritten << "\n"
810 << "verticesWritten: " << verticesWritten << "\n"
811 << "xfbBufferSize: " << xfbBufferSize << "\n"
812 << tcu::TestLog::EndMessage;
813 }
814
815 const std::string logPrefix = std::string("[Query ") + std::to_string(queryIdx) + "] ";
816
817 log << tcu::TestLog::Message << logPrefix << "PGQ: Generated " << pgqGenerated << tcu::TestLog::EndMessage;
818
819 if (m_parameters.transformFeedback)
820 log << tcu::TestLog::Message << logPrefix << "XFB: Written " << xfbWritten << ", generated " << xfbGenerated
821 << tcu::TestLog::EndMessage;
822
823 if (pgqGenerated != primitivesGenerated * drawCount)
824 {
825 const std::string message = logPrefix + "pgqGenerated == " + de::toString(pgqGenerated) + ", expected " +
826 de::toString(primitivesGenerated * drawCount);
827 return tcu::TestStatus::fail(message);
828 }
829
830 if (pgqAvailability != 1)
831 {
832 const std::string message =
833 logPrefix + "pgqAvailability == " + de::toString(pgqAvailability) + ", expected 1";
834 return tcu::TestStatus::fail(message);
835 }
836
837 if (m_parameters.transformFeedback)
838 {
839 if (xfbGenerated != primitivesGenerated * drawCount)
840 {
841 const std::string message = logPrefix + "xfbGenerated == " + de::toString(xfbGenerated) +
842 ", expected " + de::toString(primitivesGenerated * drawCount);
843 return tcu::TestStatus::fail(message);
844 }
845
846 if (xfbWritten != primitivesWritten)
847 {
848 const std::string message = logPrefix + "xfbWritten == " + de::toString(xfbWritten) + ", expected " +
849 de::toString(primitivesWritten);
850 return tcu::TestStatus::fail(message);
851 }
852
853 if (xfbWritten != (primitivesGenerated - 3))
854 {
855 const std::string message = logPrefix + "xfbWritten == " + de::toString(xfbWritten) + ", expected " +
856 de::toString(primitivesGenerated - 3);
857 return tcu::TestStatus::fail(message);
858 }
859
860 if (xfbAvailability != 1)
861 {
862 const std::string message =
863 logPrefix + "xfbAvailability == " + de::toString(xfbAvailability) + ", expected 1";
864 return tcu::TestStatus::fail(message);
865 }
866 }
867 }
868
869 return tcu::TestStatus::pass("Counters OK");
870 }
871
selectDepthStencilFormat(void)872 VkFormat PrimitivesGeneratedQueryTestInstance::selectDepthStencilFormat(void)
873 {
874 constexpr VkFormat formats[] = {VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT};
875
876 const InstanceInterface &vki = m_context.getInstanceInterface();
877 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
878
879 for (VkFormat format : formats)
880 {
881 const VkFormatFeatureFlags features =
882 getPhysicalDeviceFormatProperties(vki, physicalDevice, format).optimalTilingFeatures;
883
884 if (features & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)
885 return format;
886 }
887
888 return VK_FORMAT_UNDEFINED;
889 }
890
makeGraphicsPipeline(const DeviceInterface & vk,const VkDevice device,const VkRenderPass renderPass)891 Move<VkPipeline> PrimitivesGeneratedQueryTestInstance::makeGraphicsPipeline(const DeviceInterface &vk,
892 const VkDevice device,
893 const VkRenderPass renderPass)
894 {
895 const VkDescriptorSetLayout descriptorSetLayout = DE_NULL;
896 const Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, descriptorSetLayout));
897 const std::vector<VkViewport> viewports(1, makeViewport(makeExtent2D(IMAGE_WIDTH, IMAGE_HEIGHT)));
898 const std::vector<VkRect2D> scissors(1, makeRect2D(makeExtent2D(IMAGE_WIDTH, IMAGE_HEIGHT)));
899 const uint32_t subpass = 0u;
900 const uint32_t patchControlPoints = topologyData.at(VK_PRIMITIVE_TOPOLOGY_PATCH_LIST).primitiveSize;
901 const Unique<VkShaderModule> vertModule(
902 createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
903 Move<VkShaderModule> tescModule;
904 Move<VkShaderModule> teseModule;
905 Move<VkShaderModule> geomModule;
906 Move<VkShaderModule> fragModule;
907 VkVertexInputBindingDescription bindingDescription;
908 VkVertexInputAttributeDescription attributeDescription;
909
910 if (m_parameters.shaderStage == SHADER_STAGE_TESSELLATION_EVALUATION)
911 {
912 tescModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("tesc"), 0u);
913 teseModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("tese"), 0u);
914 }
915
916 if (m_parameters.shaderStage == SHADER_STAGE_GEOMETRY)
917 geomModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("geom"), 0u);
918
919 if (!m_parameters.rastDiscard())
920 fragModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u);
921
922 bindingDescription.binding = 0;
923 bindingDescription.stride = sizeof(tcu::Vec2);
924 bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
925
926 attributeDescription.binding = 0;
927 attributeDescription.location = 0;
928 attributeDescription.format = VK_FORMAT_R32G32_SFLOAT;
929 attributeDescription.offset = 0;
930
931 const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo = {
932 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType
933 DE_NULL, // const void* pNext
934 0u, // VkPipelineVertexInputStateCreateFlags flags
935 1u, // uint32_t vertexBindingDescriptionCount
936 &bindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions
937 1u, // uint32_t vertexAttributeDescriptionCount
938 &attributeDescription, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions
939 };
940
941 const VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo = {
942 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType
943 DE_NULL, // const void* pNext
944 0, // VkPipelineRasterizationStateCreateFlags flags
945 VK_FALSE, // VkBool32 depthClampEnable
946 (m_parameters.rastDiscard() ? VK_TRUE :
947 VK_FALSE), // VkBool32 rasterizerDiscardEnable
948 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode
949 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode
950 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace
951 VK_FALSE, // VkBool32 depthBiasEnable
952 0.0f, // float depthBiasConstantFactor
953 0.0f, // float depthBiasClamp
954 0.0f, // float depthBiasSlopeFactor
955 1.0f // float lineWidth
956 };
957
958 const VkStencilOpState stencilOpState = {
959 VK_STENCIL_OP_KEEP, // VkStencilOp failOp
960 VK_STENCIL_OP_KEEP, // VkStencilOp passOp
961 VK_STENCIL_OP_KEEP, // VkStencilOp depthFailOp
962 VK_COMPARE_OP_ALWAYS, // VkCompareOp compareOp
963 0xFFu, // uint32_t compareMask
964 0xFFu, // uint32_t writeMask
965 0, // uint32_t reference
966 };
967
968 const VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo = {
969 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType
970 DE_NULL, // const void* pNext
971 0, // VkPipelineDepthStencilStateCreateFlags flags
972 VK_TRUE, // VkBool32 depthTestEnable
973 VK_TRUE, // VkBool32 depthWriteEnable
974 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp
975 VK_FALSE, // VkBool32 depthBoundsTestEnable
976 VK_FALSE, // VkBool32 stencilTestEnable
977 stencilOpState, // VkStencilOpState front
978 stencilOpState, // VkStencilOpState back
979 0.0f, // float minDepthBounds
980 1.0f, // float maxDepthBounds
981 };
982
983 const VkBool32 colorWriteEnables = VK_FALSE;
984
985 const VkPipelineColorWriteCreateInfoEXT colorWriteCreateInfo = {
986 VK_STRUCTURE_TYPE_PIPELINE_COLOR_WRITE_CREATE_INFO_EXT, // VkStructureType sType;
987 DE_NULL, // const void* pNext;
988 1, // uint32_t attachmentCount;
989 &colorWriteEnables // const VkBool32* pColorWriteEnables;
990 };
991
992 const VkPipelineColorBlendAttachmentState colorBlendAttachmentState = {
993 VK_FALSE, // VkBool32 blendEnable
994 VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcColorBlendFactor
995 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor
996 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp
997 VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcAlphaBlendFactor
998 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor
999 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp
1000 VK_COLOR_COMPONENT_R_BIT // VkColorComponentFlags colorWriteMask
1001 | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT};
1002
1003 const VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfo = {
1004 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType
1005 &colorWriteCreateInfo, // const void* pNext
1006 0, // VkPipelineColorBlendStateCreateFlags flags
1007 VK_FALSE, // VkBool32 logicOpEnable
1008 VK_LOGIC_OP_NO_OP, // VkLogicOp logicOp
1009 1, // uint32_t attachmentCount
1010 &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments
1011 {0.0f, 0.0f, 0.0f, 0.0f} // float blendConstants[4]
1012 };
1013
1014 const VkDynamicState dynamicStates = VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT;
1015
1016 const VkPipelineDynamicStateCreateInfo pipelineDynamicStateCreateInfo = {
1017 VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType
1018 DE_NULL, // const void* pNext
1019 0u, // VkPipelineDynamicStateCreateFlags flags
1020 1u, // uint32_t dynamicStateCount
1021 &dynamicStates // const VkDynamicState* pDynamicStates
1022 };
1023
1024 const VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo = {
1025 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
1026 nullptr, // const void* pNext;
1027 0u, // VkPipelineMultisampleStateCreateFlags flags;
1028 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
1029 VK_FALSE, // VkBool32 sampleShadingEnable;
1030 1.0f, // float minSampleShading;
1031 nullptr, // const VkSampleMask* pSampleMask;
1032 VK_FALSE, // VkBool32 alphaToCoverageEnable;
1033 VK_FALSE, // VkBool32 alphaToOneEnable;
1034 };
1035
1036 return vk::makeGraphicsPipeline(
1037 vk, device, *pipelineLayout, *vertModule, *tescModule, *teseModule, *geomModule, *fragModule, renderPass,
1038 viewports, scissors, m_parameters.primitiveTopology, subpass, patchControlPoints, &vertexInputStateCreateInfo,
1039 &rasterizationStateCreateInfo, &multisampleStateCreateInfo,
1040 m_parameters.depthStencilAttachment ? &depthStencilStateCreateInfo : DE_NULL,
1041 m_parameters.staticColorWriteDisable() ? &colorBlendStateCreateInfo : DE_NULL,
1042 m_parameters.dynamicColorWriteDisable() ? &pipelineDynamicStateCreateInfo : DE_NULL);
1043 }
1044
fillVertexBuffer(tcu::Vec2 * vertices,const uint64_t primitivesGenerated)1045 void PrimitivesGeneratedQueryTestInstance::fillVertexBuffer(tcu::Vec2 *vertices, const uint64_t primitivesGenerated)
1046 {
1047 const float step = 1.0f / static_cast<float>(primitivesGenerated);
1048
1049 switch (m_parameters.primitiveTopology)
1050 {
1051 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
1052 {
1053 for (uint32_t prim = 0; prim < primitivesGenerated; ++prim)
1054 {
1055 vertices[prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 0.0f);
1056 }
1057 break;
1058 }
1059 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
1060 {
1061 for (uint32_t prim = 0; prim < primitivesGenerated; ++prim)
1062 {
1063 vertices[2 * prim + 0] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 1.0f);
1064 vertices[2 * prim + 1] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
1065 }
1066 break;
1067 }
1068 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
1069 {
1070 vertices[0] = tcu::Vec2(-1.0f, -1.0f);
1071 vertices[1] = tcu::Vec2(-1.0f, 1.0f);
1072
1073 for (uint32_t prim = 1; prim < primitivesGenerated; ++prim)
1074 {
1075 if (prim % 2 == 0)
1076 {
1077 vertices[1 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 1.0f);
1078 }
1079 else
1080 {
1081 vertices[1 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
1082 }
1083 }
1084 break;
1085 }
1086 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
1087 {
1088 vertices[0] = tcu::Vec2(-1.0f, 1.0f);
1089 vertices[1] = tcu::Vec2(-1.0f, -1.0f);
1090 vertices[2] = tcu::Vec2(-1.0f + 2.0f * step, 1.0f);
1091
1092 for (uint32_t prim = 1; prim < primitivesGenerated; ++prim)
1093 {
1094 if (prim % 2 == 0)
1095 {
1096 vertices[2 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 1.0f);
1097 }
1098 else
1099 {
1100 vertices[2 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
1101 }
1102 }
1103 break;
1104 }
1105 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
1106 {
1107 vertices[0] = tcu::Vec2(0.0f, -1.0f);
1108
1109 for (uint32_t prim = 0; prim < primitivesGenerated + 1; ++prim)
1110 {
1111 vertices[1 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f + 2.0f * (float)prim * step);
1112 }
1113 break;
1114 }
1115 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
1116 {
1117 for (uint32_t prim = 0; prim < primitivesGenerated; ++prim)
1118 {
1119 vertices[4 * prim + 0] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 1.0f);
1120 vertices[4 * prim + 1] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 0.5f);
1121 vertices[4 * prim + 2] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -0.5f);
1122 vertices[4 * prim + 3] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
1123 }
1124 break;
1125 }
1126 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
1127 {
1128 vertices[0] = tcu::Vec2(-1.0f, 0.0f);
1129 vertices[1] = tcu::Vec2(-1.0f, -1.0f);
1130 vertices[2] = tcu::Vec2(-1.0f, 1.0f);
1131
1132 for (uint32_t prim = 1; prim < primitivesGenerated; ++prim)
1133 {
1134 if (prim % 2 == 0)
1135 {
1136 vertices[2 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 1.0f);
1137 }
1138 else
1139 {
1140 vertices[2 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
1141 }
1142 }
1143
1144 vertices[2 + primitivesGenerated] = tcu::Vec2(1.0f, 0.0f);
1145
1146 break;
1147 }
1148 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
1149 case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
1150 {
1151 for (uint32_t prim = 0; prim < primitivesGenerated; ++prim)
1152 {
1153 if (prim % 2 == 0)
1154 {
1155 vertices[3 * prim + 0] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, 1.0f);
1156 vertices[3 * prim + 1] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, -1.0f);
1157 vertices[3 * prim + 2] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, -1.0f);
1158 }
1159 else
1160 {
1161 vertices[3 * prim + 0] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, -1.0f);
1162 vertices[3 * prim + 1] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, 1.0f);
1163 vertices[3 * prim + 2] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, 1.0f);
1164 }
1165 }
1166 break;
1167 }
1168 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
1169 {
1170 for (uint32_t prim = 0; prim < primitivesGenerated; ++prim)
1171 {
1172 if (prim % 2 == 0)
1173 {
1174 vertices[6 * prim + 0] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, 1.0f);
1175 vertices[6 * prim + 1] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, 1.0f);
1176 vertices[6 * prim + 2] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, -1.0f);
1177 vertices[6 * prim + 3] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, -1.0f);
1178 vertices[6 * prim + 4] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, -1.0f);
1179 vertices[6 * prim + 5] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, -1.0f);
1180 }
1181 else
1182 {
1183 vertices[6 * prim + 0] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, -1.0f);
1184 vertices[6 * prim + 1] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, -1.0f);
1185 vertices[6 * prim + 2] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, 1.0f);
1186 vertices[6 * prim + 3] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, 1.0f);
1187 vertices[6 * prim + 4] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, 1.0f);
1188 vertices[6 * prim + 5] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, 1.0f);
1189 }
1190 }
1191 break;
1192 }
1193 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
1194 {
1195 vertices[0] = tcu::Vec2(-1.0f, 1.0f);
1196 vertices[1] = tcu::Vec2(-1.0f, 1.0f);
1197 vertices[2] = tcu::Vec2(-1.0f, -1.0f);
1198 vertices[3] = tcu::Vec2(-1.0f, -1.0f);
1199 vertices[4] = tcu::Vec2(-1.0f + 2.0f * step, 1.0f);
1200 vertices[5] = tcu::Vec2(-1.0f + 2.0f * step, 1.0f);
1201
1202 for (uint32_t prim = 1; prim < primitivesGenerated; ++prim)
1203 {
1204 if (prim % 2 == 0)
1205 {
1206 vertices[5 + prim + 0] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 1.0f);
1207 vertices[5 + prim + 1] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 1.0f);
1208 }
1209 else
1210 {
1211 vertices[5 + prim + 0] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
1212 vertices[5 + prim + 1] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
1213 }
1214 }
1215 break;
1216 }
1217 default:
1218 TCU_THROW(InternalError, "Unrecognized primitive topology");
1219 }
1220 }
1221
1222 class PrimitivesGeneratedQueryTestCase : public vkt::TestCase
1223 {
1224 public:
PrimitivesGeneratedQueryTestCase(tcu::TestContext & context,const char * name,const TestParameters & parameters)1225 PrimitivesGeneratedQueryTestCase(tcu::TestContext &context, const char *name, const TestParameters ¶meters)
1226 : TestCase(context, name)
1227 , m_parameters(parameters)
1228 {
1229 }
1230
1231 private:
1232 void checkSupport(vkt::Context &context) const;
1233 void initPrograms(vk::SourceCollections &programCollection) const;
createInstance(vkt::Context & context) const1234 vkt::TestInstance *createInstance(vkt::Context &context) const
1235 {
1236 return new PrimitivesGeneratedQueryTestInstance(context, m_parameters);
1237 }
1238
1239 const TestParameters m_parameters;
1240 };
1241
checkSupport(vkt::Context & context) const1242 void PrimitivesGeneratedQueryTestCase::checkSupport(vkt::Context &context) const
1243 {
1244 context.requireDeviceFunctionality("VK_EXT_primitives_generated_query");
1245 context.requireDeviceFunctionality("VK_EXT_transform_feedback");
1246
1247 const VkPhysicalDevicePrimitivesGeneratedQueryFeaturesEXT &pgqFeatures =
1248 context.getPrimitivesGeneratedQueryFeaturesEXT();
1249 const VkPhysicalDeviceTransformFeedbackFeaturesEXT &xfbFeatures = context.getTransformFeedbackFeaturesEXT();
1250 const VkPhysicalDeviceTransformFeedbackPropertiesEXT &xfbProperties = context.getTransformFeedbackPropertiesEXT();
1251
1252 if (pgqFeatures.primitivesGeneratedQuery != VK_TRUE)
1253 TCU_THROW(NotSupportedError, "VK_QUERY_TYPE_PRIMITIVES_GENERATED_EXT not supported");
1254
1255 if (m_parameters.rastDiscard() && (pgqFeatures.primitivesGeneratedQueryWithRasterizerDiscard != VK_TRUE))
1256 TCU_THROW(NotSupportedError, "primitivesGeneratedQueryWithRasterizerDiscard not supported");
1257
1258 if (m_parameters.queryResetType == QUERY_RESET_TYPE_HOST)
1259 context.requireDeviceFunctionality("VK_EXT_host_query_reset");
1260
1261 if (m_parameters.shaderStage == SHADER_STAGE_GEOMETRY ||
1262 topologyData.at(m_parameters.primitiveTopology).hasAdjacency)
1263 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
1264
1265 if (m_parameters.shaderStage == SHADER_STAGE_TESSELLATION_EVALUATION)
1266 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
1267
1268 if (m_parameters.nonZeroStreams())
1269 {
1270 const uint32_t requiredStreams = de::max(m_parameters.pgqStreamIndex(), m_parameters.xfbStreamIndex());
1271
1272 if (m_parameters.pgqStreamIndex() > 0 && pgqFeatures.primitivesGeneratedQueryWithNonZeroStreams != VK_TRUE)
1273 TCU_THROW(NotSupportedError, "primitivesGeneratedQueryWithNonZeroStreams not supported");
1274
1275 if (xfbProperties.maxTransformFeedbackStreams <= requiredStreams)
1276 TCU_THROW(NotSupportedError, "Required amount of XFB streams not supported");
1277 }
1278
1279 if (m_parameters.transformFeedback)
1280 {
1281 if (xfbFeatures.transformFeedback != VK_TRUE)
1282 TCU_THROW(NotSupportedError, "transformFeedback not supported");
1283
1284 if (xfbProperties.transformFeedbackQueries != VK_TRUE)
1285 TCU_THROW(NotSupportedError, "transformFeedbackQueries not supported");
1286 }
1287
1288 if (m_parameters.colorWriteDisable())
1289 {
1290 context.requireDeviceFunctionality("VK_EXT_color_write_enable");
1291
1292 if (context.getColorWriteEnableFeaturesEXT().colorWriteEnable != VK_TRUE)
1293 TCU_THROW(NotSupportedError, "colorWriteEnable not supported");
1294 }
1295 }
1296
initPrograms(vk::SourceCollections & programCollection) const1297 void PrimitivesGeneratedQueryTestCase::initPrograms(vk::SourceCollections &programCollection) const
1298 {
1299 // Vertex shader.
1300 {
1301 const bool vertXfb = (m_parameters.transformFeedback && m_parameters.shaderStage == SHADER_STAGE_VERTEX);
1302 std::ostringstream src;
1303
1304 src << "#version 450\n";
1305 src << "layout(location=0) in vec2 inPosition;\n";
1306
1307 if (vertXfb)
1308 src << "layout(xfb_buffer = 0, xfb_offset = 0, xfb_stride = 16, location = 0) out vec4 out0;\n";
1309
1310 src << "void main (void)\n"
1311 "{\n";
1312
1313 if (m_parameters.primitiveTopology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST &&
1314 m_parameters.shaderStage == SHADER_STAGE_VERTEX)
1315 src << " gl_PointSize = 1.0;\n";
1316
1317 src << " gl_Position = vec4(inPosition, 0, 1);\n";
1318
1319 if (vertXfb)
1320 src << " out0 = vec4(42);\n";
1321
1322 src << "}\n";
1323
1324 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
1325 }
1326
1327 // Tessellation shaders.
1328 if (m_parameters.shaderStage == SHADER_STAGE_TESSELLATION_EVALUATION)
1329 {
1330 std::stringstream tescSrc;
1331 std::stringstream teseSrc;
1332
1333 tescSrc << "#version 450\n"
1334 "#extension GL_EXT_tessellation_shader : require\n"
1335 "layout(vertices = "
1336 << topologyData.at(VK_PRIMITIVE_TOPOLOGY_PATCH_LIST).primitiveSize
1337 << ") out;\n"
1338 "void main (void)\n"
1339 "{\n"
1340 " gl_TessLevelInner[0] = 1.0;\n"
1341 " gl_TessLevelInner[1] = 1.0;\n"
1342 " gl_TessLevelOuter[0] = 1.0;\n"
1343 " gl_TessLevelOuter[1] = 1.0;\n"
1344 " gl_TessLevelOuter[2] = 1.0;\n"
1345 " gl_TessLevelOuter[3] = 1.0;\n"
1346 " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1347 "}\n";
1348
1349 teseSrc << "#version 450\n"
1350 "#extension GL_EXT_tessellation_shader : require\n"
1351 "layout(triangles) in;\n";
1352
1353 if (m_parameters.transformFeedback)
1354 teseSrc << "layout(xfb_buffer = 0, xfb_offset = 0, location = 0) out vec4 out0;\n";
1355
1356 teseSrc << "void main (void)\n"
1357 "{\n";
1358
1359 if (m_parameters.transformFeedback)
1360 teseSrc << " out0 = vec4(42);\n";
1361
1362 teseSrc << " vec4 p0 = gl_TessCoord.x * gl_in[0].gl_Position;\n"
1363 " vec4 p1 = gl_TessCoord.y * gl_in[1].gl_Position;\n"
1364 " vec4 p2 = gl_TessCoord.z * gl_in[2].gl_Position;\n"
1365 " gl_Position = p0 + p1 + p2;\n"
1366 "}\n";
1367
1368 programCollection.glslSources.add("tesc") << glu::TessellationControlSource(tescSrc.str());
1369 programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(teseSrc.str());
1370 }
1371
1372 // Geometry shader.
1373 if (m_parameters.shaderStage == SHADER_STAGE_GEOMETRY)
1374 {
1375 const bool outputPoints =
1376 m_parameters.nonZeroStreams() || m_parameters.primitiveTopology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
1377 const char *const inputTopology = topologyData.at(m_parameters.primitiveTopology).inputString;
1378 const char *const outputTopology =
1379 outputPoints ? "points" : topologyData.at(m_parameters.primitiveTopology).outputString;
1380 const VkDeviceSize outputPrimSize =
1381 outputPoints ? 1 : topologyData.at(m_parameters.primitiveTopology).primitiveSize;
1382 const VkDeviceSize maxVertices = m_parameters.multipleStreams() ? outputPrimSize * 2 : outputPrimSize;
1383 const std::string pgqEmitCommand =
1384 m_parameters.nonZeroStreams() ?
1385 std::string("EmitStreamVertex(") + de::toString(m_parameters.pgqStreamIndex()) + ")" :
1386 "EmitVertex()";
1387 const std::string xfbEmitCommand =
1388 m_parameters.nonZeroStreams() ?
1389 std::string("EmitStreamVertex(") + de::toString(m_parameters.xfbStreamIndex()) + ")" :
1390 "EmitVertex()";
1391 const std::string pgqEndCommand =
1392 m_parameters.nonZeroStreams() ?
1393 std::string("EndStreamPrimitive(") + de::toString(m_parameters.pgqStreamIndex()) + ")" :
1394 "EndPrimitive()";
1395 const std::string xfbEndCommand =
1396 m_parameters.nonZeroStreams() ?
1397 std::string("EndStreamPrimitive(") + de::toString(m_parameters.xfbStreamIndex()) + ")" :
1398 "EndPrimitive()";
1399 std::ostringstream src;
1400
1401 src << "#version 450\n"
1402 "layout("
1403 << inputTopology
1404 << ") in;\n"
1405 "layout("
1406 << outputTopology << ", max_vertices = " << maxVertices << ") out;\n";
1407
1408 if (m_parameters.transformFeedback)
1409 src << "layout(xfb_buffer = 0, xfb_offset = 0, xfb_stride = 16, location = 0, stream = "
1410 << m_parameters.xfbStreamIndex() << ") out vec4 xfb;\n";
1411
1412 src << "void main (void)\n"
1413 "{\n";
1414
1415 if (outputPoints)
1416 src << " gl_PointSize = 1.0;\n";
1417
1418 if (m_parameters.transformFeedback)
1419 src << " xfb = vec4(42);\n";
1420
1421 for (VkDeviceSize i = 0; i < outputPrimSize; i++)
1422 src << " " << pgqEmitCommand << ";\n";
1423
1424 src << " " << pgqEndCommand << ";\n";
1425
1426 if (m_parameters.transformFeedback && m_parameters.multipleStreams())
1427 {
1428 for (VkDeviceSize i = 0; i < outputPrimSize; i++)
1429 src << " " << xfbEmitCommand << ";\n";
1430
1431 src << " " << xfbEndCommand << ";\n";
1432 }
1433
1434 src << "}\n";
1435
1436 programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
1437 }
1438
1439 // Fragment shader.
1440 if (!m_parameters.rastDiscard())
1441 {
1442 std::ostringstream src;
1443
1444 if (m_parameters.rastCase == RAST_CASE_EMPTY_FRAG)
1445 {
1446 src << "#version 450\n"
1447 "void main (void) {}\n";
1448 }
1449 else
1450 {
1451 src << "#version 450\n"
1452 "layout(location = 0) out vec4 out0;\n"
1453 "void main (void)\n"
1454 "{\n"
1455 " out0 = vec4(0.0, 1.0, 0.0, 1.0);\n"
1456 "}\n";
1457 }
1458
1459 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1460 }
1461 }
1462 class ConcurrentPrimitivesGeneratedQueryTestInstance : public vkt::TestInstance
1463 {
1464 public:
ConcurrentPrimitivesGeneratedQueryTestInstance(vkt::Context & context,const ConcurrentTestParameters & parameters)1465 ConcurrentPrimitivesGeneratedQueryTestInstance(vkt::Context &context, const ConcurrentTestParameters ¶meters)
1466 : vkt::TestInstance(context)
1467 , m_parameters(parameters)
1468 {
1469 }
1470
1471 private:
1472 tcu::TestStatus iterate(void);
1473 void draw(const DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer, uint32_t vertexCount,
1474 vk::VkBuffer indirectBuffer);
1475 Move<VkPipeline> makeGraphicsPipeline(const DeviceInterface &vk, const VkDevice device,
1476 const VkRenderPass renderPass);
1477 void fillVertexBuffer(tcu::Vec2 *vertices, const uint64_t primitivesGenerated);
1478 void copyColorImageToBuffer(const DeviceInterface &vk, VkCommandBuffer cmdBuffer, VkImage image, VkBuffer buffer);
1479
1480 const ConcurrentTestParameters m_parameters;
1481 const uint32_t m_imageWidth = 16;
1482 const uint32_t m_imageHeight = 16;
1483 const uint32_t instanceCount = 1u;
1484 const uint32_t firstVertex = 0u;
1485 const uint32_t firstInstance = 0u;
1486 };
1487
1488 // Create a render pass with an initial and final layout of VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL.
1489 // The load operation will clear the attachment.
makeConstantLayoutRenderPass(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat)1490 Move<VkRenderPass> makeConstantLayoutRenderPass(const DeviceInterface &vk, const VkDevice device,
1491 const VkFormat colorFormat)
1492 {
1493 const auto constantLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
1494
1495 const VkAttachmentDescription colorAttachmentDescription = {
1496 0u, // VkAttachmentDescriptionFlags flags
1497 colorFormat, // VkFormat format
1498 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
1499 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp
1500 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp
1501 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp
1502 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp
1503 constantLayout, // VkImageLayout initialLayout
1504 constantLayout // VkImageLayout finalLayout
1505 };
1506
1507 const VkAttachmentReference colorAttachmentRef = makeAttachmentReference(0u, constantLayout);
1508
1509 const VkSubpassDescription subpassDescription = {
1510 0u, // VkSubpassDescriptionFlags flags
1511 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint
1512 0u, // uint32_t inputAttachmentCount
1513 nullptr, // const VkAttachmentReference* pInputAttachments
1514 1u, // uint32_t colorAttachmentCount
1515 &colorAttachmentRef, // const VkAttachmentReference* pColorAttachments
1516 nullptr, // const VkAttachmentReference* pResolveAttachments
1517 nullptr, // const VkAttachmentReference* pDepthStencilAttachment
1518 0u, // uint32_t preserveAttachmentCount
1519 nullptr // const uint32_t* pPreserveAttachments
1520 };
1521
1522 const VkRenderPassCreateInfo renderPassInfo = {
1523 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType
1524 nullptr, // const void* pNext
1525 0u, // VkRenderPassCreateFlags flags
1526 1u, // uint32_t attachmentCount
1527 &colorAttachmentDescription, // const VkAttachmentDescription* pAttachments
1528 1u, // uint32_t subpassCount
1529 &subpassDescription, // const VkSubpassDescription* pSubpasses
1530 0u, // uint32_t dependencyCount
1531 nullptr // const VkSubpassDependency* pDependencies
1532 };
1533
1534 return createRenderPass(vk, device, &renderPassInfo);
1535 }
1536
1537 // Transitions the selected subresource range to color attachment optimal.
prepareColorAttachment(const DeviceInterface & vkd,const VkCommandBuffer cmdBuffer,const VkImage image,const VkImageSubresourceRange imageSRR)1538 void prepareColorAttachment(const DeviceInterface &vkd, const VkCommandBuffer cmdBuffer, const VkImage image,
1539 const VkImageSubresourceRange imageSRR)
1540 {
1541 const auto barrier = makeImageMemoryBarrier(0u, 0u, VK_IMAGE_LAYOUT_UNDEFINED,
1542 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, image, imageSRR);
1543 cmdPipelineImageMemoryBarrier(vkd, cmdBuffer, 0u, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, &barrier);
1544 }
1545
iterate(void)1546 tcu::TestStatus ConcurrentPrimitivesGeneratedQueryTestInstance::iterate(void)
1547 {
1548 const DeviceInterface &vk = m_context.getDeviceInterface();
1549 const VkDevice device = m_context.getDevice();
1550 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1551 const VkQueue queue = m_context.getUniversalQueue();
1552 Allocator &allocator = m_context.getDefaultAllocator();
1553 tcu::TestLog &log = m_context.getTestContext().getLog();
1554
1555 const VkDeviceSize primitivesGenerated = 32;
1556 const uint32_t baseMipLevel = 0;
1557 const uint32_t levelCount = 1;
1558 const uint32_t baseArrayLayer = 0;
1559 const uint32_t layerCount = 1;
1560
1561 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
1562
1563 const VkImageCreateInfo colorImageCreateInfo = {
1564 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType
1565 DE_NULL, // const void* pNext
1566 0u, // VkImageCreateFlags flags
1567 VK_IMAGE_TYPE_2D, // VkImageType imageType
1568 colorFormat, // VkFormat format
1569 makeExtent3D(m_imageWidth, m_imageHeight, 1), // VkExtent3D extent
1570 1u, // uint32_t mipLevels
1571 1u, // uint32_t arrayLayers
1572 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
1573 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling
1574 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage
1575 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode
1576 0u, // uint32_t queueFamilyIndexCount
1577 DE_NULL, // const uint32_t* pQueueFamilyIndices
1578 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout
1579 };
1580
1581 const VkImageSubresourceRange colorSubresourceRange =
1582 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, baseMipLevel, levelCount, baseArrayLayer, layerCount);
1583
1584 Move<VkImage> colorImage = makeImage(vk, device, colorImageCreateInfo);
1585 de::MovePtr<Allocation> colorImageAllocation =
1586 bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any);
1587 Move<VkImageView> colorImageView =
1588 makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange);
1589
1590 // By using a constant-layout render pass, we can begin and end the render pass multiple times without layout transition hazards.
1591 const Unique<VkRenderPass> renderPass(makeConstantLayoutRenderPass(vk, device, colorFormat));
1592 const vk::VkClearValue clearColor = {{{0.0f, 0.0f, 0.0f, 0.0f}}};
1593 const Unique<VkFramebuffer> framebuffer(
1594 makeFramebuffer(vk, device, *renderPass, *colorImageView, m_imageWidth, m_imageHeight));
1595 const Unique<VkPipeline> pipeline(
1596 ConcurrentPrimitivesGeneratedQueryTestInstance::makeGraphicsPipeline(vk, device, *renderPass));
1597
1598 const VkBufferUsageFlags usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
1599 const std::vector<uint32_t> queueFamilyIndices(1, queueFamilyIndex);
1600 const VkDeviceSize vtxBufferSize =
1601 topologyData.at(m_parameters.primitiveTopology).getNumVertices(primitivesGenerated) * sizeof(tcu::Vec2);
1602 const VkBufferCreateInfo createInfo = makeBufferCreateInfo(vtxBufferSize, usage, queueFamilyIndices);
1603
1604 Move<VkBuffer> vtxBuffer = createBuffer(vk, device, &createInfo);
1605 de::MovePtr<Allocation> vtxBufferAlloc =
1606 allocator.allocate(getBufferMemoryRequirements(vk, device, *vtxBuffer), MemoryRequirement::HostVisible);
1607
1608 const Unique<VkCommandPool> cmdPool(
1609 createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1610 const Unique<VkCommandBuffer> primaryCmdBuffer(
1611 allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1612 const Unique<VkCommandBuffer> secondaryCmdBuffer(
1613 allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY));
1614
1615 const bool pgq64 = (m_parameters.queryResultType == QUERY_RESULT_TYPE_64_BIT ||
1616 m_parameters.queryResultType == QUERY_RESULT_TYPE_PGQ_64_XFB_32);
1617 const bool xfb64 = (m_parameters.queryResultType == QUERY_RESULT_TYPE_64_BIT ||
1618 m_parameters.queryResultType == QUERY_RESULT_TYPE_PGQ_32_XFB_64);
1619 const size_t pgqResultSize = pgq64 ? sizeof(uint64_t) : sizeof(uint32_t);
1620 const size_t xfbResultSize = xfb64 ? sizeof(uint64_t) * 2 : sizeof(uint32_t) * 2;
1621 const size_t psResultsSize = sizeof(uint64_t);
1622 const VkQueryResultFlags pgqResultWidthBit = pgq64 ? VK_QUERY_RESULT_64_BIT : 0;
1623 const VkQueryResultFlags xfbResultWidthBit = xfb64 ? VK_QUERY_RESULT_64_BIT : 0;
1624 const VkQueryResultFlags psResultWidthBit = 0;
1625 const VkQueryResultFlags pgqResultFlags = VK_QUERY_RESULT_WAIT_BIT | pgqResultWidthBit;
1626 const VkQueryResultFlags xfbResultFlags = VK_QUERY_RESULT_WAIT_BIT | xfbResultWidthBit;
1627 const VkQueryResultFlags psResultFlags = VK_QUERY_RESULT_WAIT_BIT | psResultWidthBit;
1628
1629 const uint32_t pgqQueryCount = 1;
1630 const uint32_t xfbQueryCount = (m_parameters.concurrentTestType == CONCURRENT_TEST_TYPE_TWO_XFB_INSIDE_PGQ) ? 2 : 0;
1631 const uint32_t psQueryCount =
1632 (m_parameters.concurrentTestType >= CONCURRENT_TEST_TYPE_PIPELINE_STATISTICS_1) ? 1 : 0;
1633
1634 std::vector<uint8_t> pgqResults(pgqResultSize, 255u);
1635 std::vector<std::vector<uint8_t>> xfbResults;
1636 std::vector<std::vector<uint8_t>> psqResults;
1637 if (xfbQueryCount > 0)
1638 {
1639 xfbResults.resize(xfbQueryCount);
1640 for (uint32_t i = 0; i < xfbQueryCount; ++i)
1641 xfbResults[i] = std::vector<uint8_t>(xfbResultSize, 255u);
1642 }
1643 if (psQueryCount > 0)
1644 {
1645 psqResults.resize(psQueryCount);
1646 for (uint32_t i = 0; i < psQueryCount; ++i)
1647 psqResults[i] = std::vector<uint8_t>(psResultsSize, 255u);
1648 }
1649
1650 const VkQueryPoolCreateInfo pgqCreateInfo = {
1651 VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, // VkStructureType sType
1652 DE_NULL, // const void* pNext
1653 0u, // VkQueryPoolCreateFlags flags
1654 VK_QUERY_TYPE_PRIMITIVES_GENERATED_EXT, // VkQueryType queryType
1655 pgqQueryCount, // uint32_t queryCount
1656 0u, // VkQueryPipelineStatisticFlags pipelineStatistics
1657 };
1658
1659 const VkQueryPoolCreateInfo xfbCreateInfo = {
1660 VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, // VkStructureType sType
1661 DE_NULL, // const void* pNext
1662 0u, // VkQueryPoolCreateFlags flags
1663 VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT, // VkQueryType queryType
1664 xfbQueryCount, // uint32_t queryCount
1665 0u, // VkQueryPipelineStatisticFlags pipelineStatistics
1666 };
1667
1668 const VkQueryPoolCreateInfo psCreateInfo = {
1669 VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, // VkStructureType sType
1670 DE_NULL, // const void* pNext
1671 0u, // VkQueryPoolCreateFlags flags
1672 VK_QUERY_TYPE_PIPELINE_STATISTICS, // VkQueryType queryType
1673 psQueryCount, // uint32_t queryCount
1674 VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_PRIMITIVES_BIT
1675 // VkQueryPipelineStatisticFlags pipelineStatistics
1676 };
1677
1678 const Move<VkQueryPool> pgqPool(createQueryPool(vk, device, &pgqCreateInfo));
1679 Move<VkQueryPool> xfbPool;
1680 Move<VkQueryPool> psqPool;
1681 if (xfbQueryCount > 0)
1682 xfbPool = createQueryPool(vk, device, &xfbCreateInfo);
1683 if (psQueryCount > 0)
1684 psqPool = createQueryPool(vk, device, &psCreateInfo);
1685
1686 const VkDeviceSize primitivesWritten = primitivesGenerated - 3;
1687 const VkDeviceSize verticesWritten =
1688 topologyData.at(m_parameters.primitiveTopology).getNumVertices(primitivesWritten);
1689 const VkDeviceSize primitiveSize =
1690 m_parameters.nonZeroStreams() ? 1 : topologyData.at(m_parameters.primitiveTopology).primitiveSize;
1691 const VkDeviceSize bytesPerVertex = 4 * sizeof(float);
1692 const VkDeviceSize xfbBufferSize = primitivesWritten * primitiveSize * bytesPerVertex;
1693 Move<VkBuffer> xfbBuffer;
1694 de::MovePtr<Allocation> xfbBufferAlloc;
1695
1696 {
1697 const VkBufferUsageFlags xfbUsage = VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT;
1698 const VkBufferCreateInfo xfbBufferCreateInfo = makeBufferCreateInfo(xfbBufferSize, xfbUsage);
1699
1700 xfbBuffer = createBuffer(vk, device, &xfbBufferCreateInfo);
1701 xfbBufferAlloc =
1702 allocator.allocate(getBufferMemoryRequirements(vk, device, *xfbBuffer), MemoryRequirement::HostVisible);
1703
1704 VK_CHECK(vk.bindBufferMemory(device, *xfbBuffer, xfbBufferAlloc->getMemory(), xfbBufferAlloc->getOffset()));
1705 }
1706
1707 fillVertexBuffer(static_cast<tcu::Vec2 *>(vtxBufferAlloc.get()->getHostPtr()), primitivesGenerated);
1708
1709 VK_CHECK(vk.bindBufferMemory(device, *vtxBuffer, vtxBufferAlloc->getMemory(), vtxBufferAlloc->getOffset()));
1710
1711 const vk::VkDeviceSize colorOutputBufferSize =
1712 m_imageWidth * m_imageHeight * tcu::getPixelSize(vk::mapVkFormat(colorFormat));
1713 de::MovePtr<vk::BufferWithMemory> colorOutputBuffer = de::MovePtr<vk::BufferWithMemory>(new vk::BufferWithMemory(
1714 vk, device, allocator, makeBufferCreateInfo(colorOutputBufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT),
1715 vk::MemoryRequirement::HostVisible));
1716
1717 de::MovePtr<vk::BufferWithMemory> indirectBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(
1718 vk, device, allocator,
1719 vk::makeBufferCreateInfo(sizeof(vk::VkDrawIndirectCommand), vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT),
1720 vk::MemoryRequirement::HostVisible));
1721 ;
1722
1723 const uint32_t vertexCount =
1724 static_cast<uint32_t>(topologyData.at(m_parameters.primitiveTopology).getNumVertices(primitivesGenerated));
1725
1726 if (m_parameters.indirect)
1727 {
1728 const vk::Allocation &indirectAlloc = (*indirectBuffer).getAllocation();
1729 vk::VkDrawIndirectCommand *indirectDataPtr =
1730 reinterpret_cast<vk::VkDrawIndirectCommand *>(indirectAlloc.getHostPtr());
1731
1732 indirectDataPtr->vertexCount = vertexCount;
1733 indirectDataPtr->instanceCount = instanceCount;
1734 indirectDataPtr->firstVertex = firstVertex;
1735 indirectDataPtr->firstInstance = firstInstance;
1736
1737 flushAlloc(vk, device, indirectAlloc);
1738 }
1739
1740 const bool secondaryCmdBufferUsed =
1741 m_parameters.concurrentTestType == CONCURRENT_TEST_TYPE_PGQ_SECONDARY_CMD_BUFFER;
1742 const VkQueryControlFlags queryControlFlags = 0;
1743 const VkDeviceSize vertexBufferOffset = static_cast<VkDeviceSize>(0);
1744
1745 VkCommandBuffer cmdBuffer;
1746
1747 if (secondaryCmdBufferUsed)
1748 {
1749 cmdBuffer = *secondaryCmdBuffer;
1750 beginSecondaryCommandBuffer(vk, cmdBuffer, *renderPass, *framebuffer);
1751 }
1752 else
1753 {
1754 cmdBuffer = *primaryCmdBuffer;
1755 beginCommandBuffer(vk, cmdBuffer);
1756 prepareColorAttachment(vk, cmdBuffer, *colorImage, colorSubresourceRange);
1757 }
1758
1759 if (m_parameters.concurrentTestType == CONCURRENT_TEST_TYPE_PIPELINE_STATISTICS_3)
1760 {
1761 const VkCommandBufferInheritanceInfo inheritanceInfo = {
1762 VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, // VkStructureType sType;
1763 nullptr, // const void* pNext;
1764 *renderPass, // VkRenderPass renderPass;
1765 0u, // uint32_t subpass;
1766 *framebuffer, // VkFramebuffer framebuffer;
1767 VK_FALSE, // VkBool32 occlusionQueryEnable;
1768 queryControlFlags, // VkQueryControlFlags queryFlags;
1769 psCreateInfo.pipelineStatistics, // VkQueryPipelineStatisticFlags pipelineStatistics;
1770 };
1771
1772 const VkCommandBufferBeginInfo beginInfo = {
1773 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
1774 nullptr, // const void* pNext;
1775 VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, // VkCommandBufferUsageFlags flags;
1776 &inheritanceInfo, // const VkCommandBufferInheritanceInfo* pInheritanceInfo;
1777 };
1778
1779 vk.beginCommandBuffer(*secondaryCmdBuffer, &beginInfo);
1780 vk.cmdBeginQueryIndexedEXT(*secondaryCmdBuffer, *pgqPool, 0, queryControlFlags, m_parameters.pgqStreamIndex());
1781 vk.cmdBindPipeline(*secondaryCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1782 vk.cmdBindVertexBuffers(*secondaryCmdBuffer, 0, 1, &vtxBuffer.get(), &vertexBufferOffset);
1783 draw(vk, *secondaryCmdBuffer, vertexCount, indirectBuffer->get());
1784 vk.cmdEndQueryIndexedEXT(*secondaryCmdBuffer, *pgqPool, 0, m_parameters.pgqStreamIndex());
1785 vk.endCommandBuffer(*secondaryCmdBuffer);
1786 }
1787
1788 {
1789 // After query pool creation, each query must be reset before it is used.
1790 if (!secondaryCmdBufferUsed)
1791 {
1792 vk.cmdResetQueryPool(cmdBuffer, *pgqPool, 0, pgqQueryCount);
1793 if (xfbQueryCount > 0)
1794 vk.cmdResetQueryPool(cmdBuffer, *xfbPool, 0, xfbQueryCount);
1795 if (psQueryCount > 0)
1796 vk.cmdResetQueryPool(cmdBuffer, *psqPool, 0, psQueryCount);
1797 }
1798
1799 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1800 vk.cmdBindVertexBuffers(cmdBuffer, 0, 1, &vtxBuffer.get(), &vertexBufferOffset);
1801
1802 {
1803 const uint32_t firstCounterBuffer = 0;
1804 const uint32_t counterBufferCount = 0;
1805 const VkBuffer *counterBuffers = DE_NULL;
1806 const VkDeviceSize *counterBufferOffsets = DE_NULL;
1807
1808 if (m_parameters.concurrentTestType == CONCURRENT_TEST_TYPE_TWO_XFB_INSIDE_PGQ)
1809 {
1810 beginRenderPass(vk, cmdBuffer, *renderPass, *framebuffer,
1811 makeRect2D(makeExtent2D(m_imageWidth, m_imageHeight)), clearColor);
1812
1813 // Begin PGQ
1814 vk.cmdBeginQueryIndexedEXT(cmdBuffer, *pgqPool, 0, queryControlFlags, m_parameters.pgqStreamIndex());
1815
1816 draw(vk, cmdBuffer, vertexCount, indirectBuffer->get());
1817
1818 // Begin XFBQ 1
1819 {
1820 const uint32_t firstBinding = m_parameters.xfbStreamIndex();
1821 const uint32_t bindingCount = 1;
1822 const VkDeviceSize offset = 0;
1823
1824 vk.cmdBindTransformFeedbackBuffersEXT(cmdBuffer, firstBinding, bindingCount, &*xfbBuffer, &offset,
1825 &xfbBufferSize);
1826 vk.cmdBeginQueryIndexedEXT(cmdBuffer, *xfbPool, 0, queryControlFlags,
1827 m_parameters.xfbStreamIndex());
1828 vk.cmdBeginTransformFeedbackEXT(cmdBuffer, firstCounterBuffer, counterBufferCount, counterBuffers,
1829 counterBufferOffsets);
1830 }
1831
1832 draw(vk, cmdBuffer, vertexCount, indirectBuffer->get());
1833
1834 // End XFBQ 1
1835 {
1836 vk.cmdEndQueryIndexedEXT(cmdBuffer, *xfbPool, 0, m_parameters.xfbStreamIndex());
1837 vk.cmdEndTransformFeedbackEXT(cmdBuffer, firstCounterBuffer, counterBufferCount, counterBuffers,
1838 counterBufferOffsets);
1839 }
1840
1841 draw(vk, cmdBuffer, vertexCount, indirectBuffer->get());
1842
1843 // Begin XFBQ 1
1844 {
1845 const uint32_t firstBinding = m_parameters.xfbStreamIndex();
1846 const uint32_t bindingCount = 1;
1847 const VkDeviceSize offset = 0;
1848
1849 vk.cmdBindTransformFeedbackBuffersEXT(cmdBuffer, firstBinding, bindingCount, &*xfbBuffer, &offset,
1850 &xfbBufferSize);
1851 vk.cmdBeginQueryIndexedEXT(cmdBuffer, *xfbPool, 1, queryControlFlags,
1852 m_parameters.xfbStreamIndex());
1853 vk.cmdBeginTransformFeedbackEXT(cmdBuffer, firstCounterBuffer, counterBufferCount, counterBuffers,
1854 counterBufferOffsets);
1855 }
1856
1857 draw(vk, cmdBuffer, vertexCount, indirectBuffer->get());
1858
1859 // End XFBQ 1
1860 {
1861 vk.cmdEndQueryIndexedEXT(cmdBuffer, *xfbPool, 1, m_parameters.xfbStreamIndex());
1862 vk.cmdEndTransformFeedbackEXT(cmdBuffer, firstCounterBuffer, counterBufferCount, counterBuffers,
1863 counterBufferOffsets);
1864 }
1865
1866 draw(vk, cmdBuffer, vertexCount, indirectBuffer->get());
1867
1868 // End PGQ
1869 vk.cmdEndQueryIndexedEXT(cmdBuffer, *pgqPool, 0, m_parameters.pgqStreamIndex());
1870
1871 endRenderPass(vk, cmdBuffer);
1872 }
1873 else if (m_parameters.concurrentTestType == CONCURRENT_TEST_TYPE_PGQ_SECONDARY_CMD_BUFFER)
1874 {
1875
1876 vk.cmdBeginQueryIndexedEXT(cmdBuffer, *pgqPool, 0, queryControlFlags, m_parameters.pgqStreamIndex());
1877 draw(vk, cmdBuffer, vertexCount, indirectBuffer->get());
1878 vk.cmdEndQueryIndexedEXT(cmdBuffer, *pgqPool, 0, m_parameters.pgqStreamIndex());
1879 }
1880 else if (m_parameters.concurrentTestType == CONCURRENT_TEST_TYPE_PIPELINE_STATISTICS_1)
1881 {
1882 vk.cmdBeginQueryIndexedEXT(cmdBuffer, *pgqPool, 0, queryControlFlags, m_parameters.pgqStreamIndex());
1883 vk.cmdBeginQuery(cmdBuffer, *psqPool, 0, queryControlFlags);
1884
1885 beginRenderPass(vk, cmdBuffer, *renderPass, *framebuffer,
1886 makeRect2D(makeExtent2D(m_imageWidth, m_imageHeight)), clearColor);
1887 draw(vk, cmdBuffer, vertexCount, indirectBuffer->get());
1888 endRenderPass(vk, cmdBuffer);
1889
1890 vk.cmdEndQueryIndexedEXT(cmdBuffer, *pgqPool, 0, m_parameters.pgqStreamIndex());
1891
1892 beginRenderPass(vk, cmdBuffer, *renderPass, *framebuffer,
1893 makeRect2D(makeExtent2D(m_imageWidth, m_imageHeight)), clearColor);
1894 draw(vk, cmdBuffer, vertexCount, indirectBuffer->get());
1895 endRenderPass(vk, cmdBuffer);
1896
1897 vk.cmdEndQuery(cmdBuffer, *psqPool, 0);
1898 }
1899 else if (m_parameters.concurrentTestType == CONCURRENT_TEST_TYPE_PIPELINE_STATISTICS_2)
1900 {
1901 vk.cmdBeginQueryIndexedEXT(cmdBuffer, *pgqPool, 0, queryControlFlags, m_parameters.pgqStreamIndex());
1902
1903 beginRenderPass(vk, cmdBuffer, *renderPass, *framebuffer,
1904 makeRect2D(makeExtent2D(m_imageWidth, m_imageHeight)), clearColor);
1905 vk.cmdBeginQuery(cmdBuffer, *psqPool, 0, queryControlFlags);
1906 draw(vk, cmdBuffer, vertexCount, indirectBuffer->get());
1907 vk.cmdEndQuery(cmdBuffer, *psqPool, 0);
1908 endRenderPass(vk, cmdBuffer);
1909
1910 beginRenderPass(vk, cmdBuffer, *renderPass, *framebuffer,
1911 makeRect2D(makeExtent2D(m_imageWidth, m_imageHeight)), clearColor);
1912 draw(vk, cmdBuffer, vertexCount, indirectBuffer->get());
1913 endRenderPass(vk, cmdBuffer);
1914
1915 vk.cmdEndQueryIndexedEXT(cmdBuffer, *pgqPool, 0, m_parameters.pgqStreamIndex());
1916 }
1917 else if (m_parameters.concurrentTestType == CONCURRENT_TEST_TYPE_PIPELINE_STATISTICS_3)
1918 {
1919 vk.cmdBeginQuery(cmdBuffer, *psqPool, 0, queryControlFlags);
1920
1921 beginRenderPass(vk, cmdBuffer, *renderPass, *framebuffer,
1922 makeRect2D(makeExtent2D(m_imageWidth, m_imageHeight)), clearColor,
1923 vk::VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
1924 vk.cmdExecuteCommands(cmdBuffer, 1u, &*secondaryCmdBuffer);
1925 endRenderPass(vk, cmdBuffer);
1926
1927 beginRenderPass(vk, cmdBuffer, *renderPass, *framebuffer,
1928 makeRect2D(makeExtent2D(m_imageWidth, m_imageHeight)), clearColor);
1929 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1930 vk.cmdBindVertexBuffers(cmdBuffer, 0, 1, &vtxBuffer.get(), &vertexBufferOffset);
1931 draw(vk, cmdBuffer, vertexCount, indirectBuffer->get());
1932 endRenderPass(vk, cmdBuffer);
1933
1934 vk.cmdEndQuery(cmdBuffer, *psqPool, 0);
1935 }
1936 }
1937 }
1938
1939 if (!secondaryCmdBufferUsed)
1940 copyColorImageToBuffer(vk, cmdBuffer, *colorImage, **colorOutputBuffer);
1941
1942 vk::endCommandBuffer(vk, cmdBuffer);
1943
1944 if (secondaryCmdBufferUsed)
1945 {
1946 vk::beginCommandBuffer(vk, *primaryCmdBuffer);
1947 prepareColorAttachment(vk, *primaryCmdBuffer, *colorImage, colorSubresourceRange);
1948 vk.cmdResetQueryPool(*primaryCmdBuffer, *pgqPool, 0, pgqQueryCount);
1949 if (xfbQueryCount > 0)
1950 vk.cmdResetQueryPool(*primaryCmdBuffer, *xfbPool, 0, xfbQueryCount);
1951 if (psQueryCount > 0)
1952 vk.cmdResetQueryPool(cmdBuffer, *psqPool, 0, psQueryCount);
1953 beginRenderPass(vk, *primaryCmdBuffer, *renderPass, *framebuffer,
1954 makeRect2D(makeExtent2D(m_imageWidth, m_imageHeight)), clearColor,
1955 vk::VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
1956 vk.cmdExecuteCommands(*primaryCmdBuffer, 1u, &*secondaryCmdBuffer);
1957 endRenderPass(vk, *primaryCmdBuffer);
1958 copyColorImageToBuffer(vk, *primaryCmdBuffer, *colorImage, **colorOutputBuffer);
1959 vk::endCommandBuffer(vk, *primaryCmdBuffer);
1960 }
1961
1962 vk::submitCommandsAndWait(vk, device, queue, *primaryCmdBuffer);
1963
1964 vk.getQueryPoolResults(device, *pgqPool, 0, pgqQueryCount, pgqResults.size(), pgqResults.data(), pgqResults.size(),
1965 pgqResultFlags);
1966 for (uint32_t i = 0; i < xfbQueryCount; ++i)
1967 vk.getQueryPoolResults(device, *xfbPool, i, 1, xfbResults[i].size(), xfbResults[i].data(), xfbResults[i].size(),
1968 xfbResultFlags);
1969 for (uint32_t i = 0; i < psQueryCount; ++i)
1970 vk.getQueryPoolResults(device, *psqPool, i, 1, psqResults[i].size(), psqResults[i].data(), psqResults[i].size(),
1971 psResultFlags);
1972
1973 // Validate counters.
1974 {
1975 uint32_t pgqDrawCount = 1;
1976 if (m_parameters.concurrentTestType == CONCURRENT_TEST_TYPE_TWO_XFB_INSIDE_PGQ)
1977 pgqDrawCount = 5;
1978 else if (m_parameters.concurrentTestType == CONCURRENT_TEST_TYPE_PIPELINE_STATISTICS_2)
1979 pgqDrawCount = 2;
1980 const uint32_t totalPrimitivesGenerated = static_cast<uint32_t>(primitivesGenerated * pgqDrawCount);
1981
1982 union QueryResults
1983 {
1984 uint32_t elements32[2];
1985 uint64_t elements64[2];
1986 };
1987
1988 const QueryResults *pgqCounters = reinterpret_cast<QueryResults *>(pgqResults.data());
1989 const uint64_t pgqGenerated =
1990 pgq64 ? pgqCounters->elements64[0] : static_cast<uint64_t>(pgqCounters->elements32[0]);
1991 std::vector<QueryResults *> xfbCounters(xfbResults.size());
1992 std::vector<uint64_t> xfbWritten(xfbResults.size());
1993 std::vector<uint64_t> xfbGenerated(xfbResults.size());
1994
1995 for (uint32_t i = 0; i < xfbQueryCount; ++i)
1996 {
1997 xfbCounters[i] = reinterpret_cast<QueryResults *>(xfbResults[i].data());
1998 xfbWritten[i] =
1999 xfb64 ? xfbCounters[i]->elements64[0] : static_cast<uint64_t>(xfbCounters[i]->elements32[0]);
2000 xfbGenerated[i] =
2001 xfb64 ? xfbCounters[i]->elements64[1] : static_cast<uint64_t>(xfbCounters[i]->elements32[1]);
2002 }
2003
2004 log << tcu::TestLog::Message << "primitivesGenerated: " << totalPrimitivesGenerated << "\n"
2005 << "primitivesWritten: " << primitivesWritten << "\n"
2006 << "verticesWritten: " << verticesWritten << "\n"
2007 << "xfbBufferSize: " << xfbBufferSize << "\n"
2008 << tcu::TestLog::EndMessage;
2009
2010 log << tcu::TestLog::Message << "PGQ: Generated " << pgqGenerated << tcu::TestLog::EndMessage;
2011 for (uint32_t i = 0; i < (uint32_t)xfbCounters.size(); ++i)
2012 log << tcu::TestLog::Message << "XFB " << i << ": Written " << xfbWritten[i] << ", generated "
2013 << xfbGenerated[i] << tcu::TestLog::EndMessage;
2014
2015 if (pgqGenerated != totalPrimitivesGenerated)
2016 {
2017 const std::string message = std::string("Total pgqGenerated == ") + de::toString(pgqGenerated) +
2018 ", expected " + de::toString(totalPrimitivesGenerated);
2019 return tcu::TestStatus::fail(message);
2020 }
2021
2022 for (uint32_t i = 0; i < (uint32_t)xfbCounters.size(); ++i)
2023 {
2024 if (xfbGenerated[i] != primitivesGenerated)
2025 {
2026 const std::string message = std::string("xfbGenerated == ") + de::toString(xfbGenerated[i]) +
2027 ", expected " + de::toString(primitivesGenerated);
2028 return tcu::TestStatus::fail(message);
2029 }
2030
2031 if (xfbWritten[i] != primitivesWritten)
2032 {
2033 const std::string message = std::string("xfbWritten == ") + de::toString(xfbWritten[i]) +
2034 ", expected " + de::toString(primitivesWritten);
2035 return tcu::TestStatus::fail(message);
2036 }
2037
2038 if (xfbWritten[i] != (primitivesGenerated - 3))
2039 {
2040 const std::string message = std::string("xfbWritten == ") + de::toString(xfbWritten[i]) +
2041 ", expected " + de::toString(primitivesGenerated - 3);
2042 return tcu::TestStatus::fail(message);
2043 }
2044 }
2045
2046 if (psQueryCount > 0)
2047 {
2048
2049 const QueryResults *psqCounters = reinterpret_cast<QueryResults *>(psqResults[0].data());
2050 const uint64_t inputAssemblyPrimitives = psqCounters->elements32[0];
2051
2052 uint32_t drawCount = (m_parameters.concurrentTestType == CONCURRENT_TEST_TYPE_PIPELINE_STATISTICS_1 ||
2053 m_parameters.concurrentTestType == CONCURRENT_TEST_TYPE_PIPELINE_STATISTICS_3) ?
2054 2 :
2055 1;
2056
2057 if (inputAssemblyPrimitives != primitivesGenerated * drawCount)
2058 {
2059 const std::string message = std::string("input assembly primitives == ") +
2060 de::toString(inputAssemblyPrimitives) + ", expected " +
2061 de::toString(primitivesGenerated * drawCount);
2062 return tcu::TestStatus::fail(message);
2063 }
2064 }
2065 }
2066
2067 const auto tcuFormat = vk::mapVkFormat(colorFormat);
2068 const auto iWidth = static_cast<int>(m_imageWidth);
2069 const auto iHeight = static_cast<int>(m_imageHeight);
2070
2071 tcu::ConstPixelBufferAccess resultBuffer =
2072 tcu::ConstPixelBufferAccess(tcuFormat, iWidth, iHeight, 1, colorOutputBuffer->getAllocation().getHostPtr());
2073 tcu::TextureLevel referenceLevel(tcuFormat, iWidth, iHeight);
2074 const auto referenceAccess = referenceLevel.getAccess();
2075 const tcu::Vec4 bgColor(0.0f, 0.0f, 0.0f, 0.0f);
2076 const tcu::Vec4 geomColor(0.0f, 1.0f, 0.0f, 1.0f);
2077 const tcu::Vec4 threshold(0.0f, 0.0f, 0.0f, 0.0f);
2078 const int colorRow = 7;
2079
2080 tcu::clear(referenceAccess, bgColor);
2081 const auto subregion = tcu::getSubregion(referenceAccess, 0, colorRow, iWidth, 1);
2082 tcu::clear(subregion, geomColor);
2083
2084 if (!tcu::floatThresholdCompare(log, "Result", "", referenceAccess, resultBuffer, threshold,
2085 tcu::COMPARE_LOG_ON_ERROR))
2086 return tcu::TestStatus::fail("Color buffer contains unexpected results; check log for details");
2087 return tcu::TestStatus::pass("Pass");
2088 }
2089
draw(const DeviceInterface & vk,vk::VkCommandBuffer cmdBuffer,uint32_t vertexCount,vk::VkBuffer indirectBuffer)2090 void ConcurrentPrimitivesGeneratedQueryTestInstance::draw(const DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer,
2091 uint32_t vertexCount, vk::VkBuffer indirectBuffer)
2092 {
2093 if (m_parameters.indirect)
2094 vk.cmdDrawIndirect(cmdBuffer, indirectBuffer, 0u, 1u, sizeof(vk::VkDrawIndirectCommand));
2095 else
2096 vk.cmdDraw(cmdBuffer, vertexCount, instanceCount, firstVertex, firstInstance);
2097 }
2098
makeGraphicsPipeline(const DeviceInterface & vk,const VkDevice device,const VkRenderPass renderPass)2099 Move<VkPipeline> ConcurrentPrimitivesGeneratedQueryTestInstance::makeGraphicsPipeline(const DeviceInterface &vk,
2100 const VkDevice device,
2101 const VkRenderPass renderPass)
2102 {
2103 const VkDescriptorSetLayout descriptorSetLayout = DE_NULL;
2104 const Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, descriptorSetLayout));
2105 const std::vector<VkViewport> viewports(1, makeViewport(makeExtent2D(m_imageWidth, m_imageHeight)));
2106 const std::vector<VkRect2D> scissors(1, makeRect2D(makeExtent2D(m_imageWidth, m_imageHeight)));
2107 const uint32_t subpass = 0u;
2108 const uint32_t patchControlPoints = topologyData.at(VK_PRIMITIVE_TOPOLOGY_PATCH_LIST).primitiveSize;
2109 const Unique<VkShaderModule> vertModule(
2110 createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
2111 Move<VkShaderModule> tescModule;
2112 Move<VkShaderModule> teseModule;
2113 Move<VkShaderModule> geomModule;
2114 Move<VkShaderModule> fragModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u);
2115 VkVertexInputBindingDescription bindingDescription;
2116 VkVertexInputAttributeDescription attributeDescription;
2117
2118 if (m_parameters.shaderStage == SHADER_STAGE_TESSELLATION_EVALUATION)
2119 {
2120 tescModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("tesc"), 0u);
2121 teseModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("tese"), 0u);
2122 }
2123
2124 if (m_parameters.shaderStage == SHADER_STAGE_GEOMETRY)
2125 geomModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("geom"), 0u);
2126
2127 bindingDescription.binding = 0;
2128 bindingDescription.stride = sizeof(tcu::Vec2);
2129 bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
2130
2131 attributeDescription.binding = 0;
2132 attributeDescription.location = 0;
2133 attributeDescription.format = VK_FORMAT_R32G32_SFLOAT;
2134 attributeDescription.offset = 0;
2135
2136 const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo = {
2137 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType
2138 DE_NULL, // const void* pNext
2139 0u, // VkPipelineVertexInputStateCreateFlags flags
2140 1u, // uint32_t vertexBindingDescriptionCount
2141 &bindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions
2142 1u, // uint32_t vertexAttributeDescriptionCount
2143 &attributeDescription, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions
2144 };
2145
2146 const VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo = {
2147 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType
2148 DE_NULL, // const void* pNext
2149 0, // VkPipelineRasterizationStateCreateFlags flags
2150 VK_FALSE, // VkBool32 depthClampEnable
2151 VK_FALSE, // VkBool32 rasterizerDiscardEnable
2152 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode
2153 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode
2154 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace
2155 VK_FALSE, // VkBool32 depthBiasEnable
2156 0.0f, // float depthBiasConstantFactor
2157 0.0f, // float depthBiasClamp
2158 0.0f, // float depthBiasSlopeFactor
2159 1.0f // float lineWidth
2160 };
2161
2162 const VkPipelineColorBlendAttachmentState colorBlendAttachmentState = {
2163 VK_TRUE, // VkBool32 blendEnable
2164 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor
2165 VK_BLEND_FACTOR_ONE, // VkBlendFactor dstColorBlendFactor
2166 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp
2167 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor
2168 VK_BLEND_FACTOR_ONE, // VkBlendFactor dstAlphaBlendFactor
2169 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp
2170 VK_COLOR_COMPONENT_R_BIT // VkColorComponentFlags colorWriteMask
2171 | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT};
2172
2173 const VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfo = {
2174 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType
2175 DE_NULL, // const void* pNext
2176 0, // VkPipelineColorBlendStateCreateFlags flags
2177 VK_FALSE, // VkBool32 logicOpEnable
2178 VK_LOGIC_OP_NO_OP, // VkLogicOp logicOp
2179 1, // uint32_t attachmentCount
2180 &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments
2181 {0.0f, 0.0f, 0.0f, 0.0f} // float blendConstants[4]
2182 };
2183
2184 const VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo = {
2185 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
2186 nullptr, // const void* pNext;
2187 0u, // VkPipelineMultisampleStateCreateFlags flags;
2188 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
2189 VK_FALSE, // VkBool32 sampleShadingEnable;
2190 1.0f, // float minSampleShading;
2191 nullptr, // const VkSampleMask* pSampleMask;
2192 VK_FALSE, // VkBool32 alphaToCoverageEnable;
2193 VK_FALSE, // VkBool32 alphaToOneEnable;
2194 };
2195
2196 return vk::makeGraphicsPipeline(
2197 vk, device, *pipelineLayout, *vertModule, *tescModule, *teseModule, *geomModule, *fragModule, renderPass,
2198 viewports, scissors, m_parameters.primitiveTopology, subpass, patchControlPoints, &vertexInputStateCreateInfo,
2199 &rasterizationStateCreateInfo, &multisampleStateCreateInfo, DE_NULL, &colorBlendStateCreateInfo);
2200 }
2201
fillVertexBuffer(tcu::Vec2 * vertices,const uint64_t primitivesGenerated)2202 void ConcurrentPrimitivesGeneratedQueryTestInstance::fillVertexBuffer(tcu::Vec2 *vertices,
2203 const uint64_t primitivesGenerated)
2204 {
2205 const float step = 1.0f / static_cast<float>(primitivesGenerated - 1);
2206
2207 switch (m_parameters.primitiveTopology)
2208 {
2209 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
2210 {
2211 for (uint32_t prim = 0; prim < primitivesGenerated; ++prim)
2212 {
2213 vertices[prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 0.0f);
2214 }
2215 break;
2216 }
2217 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
2218 {
2219 for (uint32_t prim = 0; prim < primitivesGenerated; ++prim)
2220 {
2221 vertices[2 * prim + 0] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 0.0f);
2222 vertices[2 * prim + 1] = tcu::Vec2(-1.0f + 2.0f * (float)(prim + 1) * step, 0.0f);
2223 }
2224 break;
2225 }
2226 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
2227 {
2228 vertices[0] = tcu::Vec2(-1.0f, 0.0f);
2229 vertices[1] = tcu::Vec2(-1.0f, 0.0f);
2230
2231 for (uint32_t prim = 1; prim < primitivesGenerated; ++prim)
2232 vertices[1 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 0.0f);
2233 break;
2234 }
2235 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
2236 {
2237 vertices[0] = tcu::Vec2(-1.0f, -0.001f);
2238 vertices[1] = tcu::Vec2(-1.0f, -0.002f);
2239 vertices[2] = tcu::Vec2(-1.0f + 2.0f * step, -0.002f);
2240
2241 for (uint32_t prim = 1; prim < primitivesGenerated; ++prim)
2242 {
2243 vertices[2 + prim] =
2244 tcu::Vec2(-1.0f + 2.0f * (float)(prim + 1) * step, (prim % 2 == 0) ? -0.002f : -0.001f);
2245 }
2246 break;
2247 }
2248 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
2249 {
2250 vertices[0] = tcu::Vec2(0.0f, -0.1f);
2251 for (uint32_t prim = 0; prim < primitivesGenerated + 1; ++prim)
2252 {
2253 vertices[1 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 0.0f);
2254 }
2255 break;
2256 }
2257 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
2258 {
2259 for (uint32_t prim = 0; prim < primitivesGenerated; ++prim)
2260 {
2261 vertices[4 * prim + 0] = tcu::Vec2(-1.0f + 2.0f * (float)(prim - 1) * step, 0.0f);
2262 vertices[4 * prim + 1] = tcu::Vec2(-1.0f + 2.0f * (float)(prim + 0) * step, 0.0f);
2263 vertices[4 * prim + 2] = tcu::Vec2(-1.0f + 2.0f * (float)(prim + 1) * step, 0.0f);
2264 vertices[4 * prim + 3] = tcu::Vec2(-1.0f + 2.0f * (float)(prim + 2) * step, 0.0f);
2265 }
2266 break;
2267 }
2268 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
2269 {
2270 vertices[0] = tcu::Vec2(-1.0f, 0.0f);
2271 vertices[1] = tcu::Vec2(-1.0f, 0.0f);
2272
2273 for (uint32_t prim = 0; prim < primitivesGenerated; ++prim)
2274 {
2275 vertices[2 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)(prim + 1) * step, 0.0f);
2276 }
2277
2278 vertices[2 + primitivesGenerated] = tcu::Vec2(1.0f, 0.0f);
2279
2280 break;
2281 }
2282 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
2283 case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
2284 {
2285 for (uint32_t prim = 0; prim < primitivesGenerated; ++prim)
2286 {
2287 vertices[3 * prim + 0] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, -0.01f);
2288 vertices[3 * prim + 1] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, 0.01f);
2289 vertices[3 * prim + 2] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, 0.0f);
2290 }
2291 break;
2292 }
2293 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
2294 {
2295 for (uint32_t prim = 0; prim < primitivesGenerated; ++prim)
2296 {
2297 vertices[6 * prim + 0] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, -0.01f);
2298 vertices[6 * prim + 1] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, -0.01f);
2299 vertices[6 * prim + 2] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, -0.02f);
2300 vertices[6 * prim + 3] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, -0.02f);
2301 vertices[6 * prim + 4] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, -0.02f);
2302 vertices[6 * prim + 5] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, -0.02f);
2303 }
2304 break;
2305 }
2306 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
2307 {
2308 // A strip of triangles, each pair of them forming a quad, crossing the image from left to right.
2309 const auto quarterRow = 2.0f / (static_cast<float>(m_imageHeight) * 4.0f); // In height.
2310 const auto threeQRow = 3.0f * quarterRow; // In height.
2311 const auto quadStep = 2.0f / (static_cast<float>(primitivesGenerated) / 2.0f); // In width.
2312 const float yCoords[2] = {-threeQRow, -quarterRow};
2313
2314 // The first two points on the left edge of the image.
2315 vertices[0] = tcu::Vec2(-1.0f, yCoords[0]);
2316 vertices[1] = tcu::Vec2(-1.0f, yCoords[0]);
2317 vertices[2] = tcu::Vec2(-1.0f, yCoords[1]);
2318 vertices[3] = tcu::Vec2(-1.0f, yCoords[1]);
2319
2320 for (uint32_t primIdx = 0u; primIdx < static_cast<uint32_t>(primitivesGenerated); ++primIdx)
2321 {
2322 const auto edgeIdx = primIdx / 2u;
2323 const auto yIDx = primIdx % 2u;
2324 const auto xCoord = -1.0f + (static_cast<float>(edgeIdx) + 1.0f) * quadStep;
2325 const auto yCoord = yCoords[yIDx];
2326 const auto vertIdx = primIdx + 2u;
2327
2328 vertices[vertIdx * 2u + 0u] = tcu::Vec2(xCoord, yCoord); // Vertex.
2329 vertices[vertIdx * 2u + 1u] = tcu::Vec2(xCoord, yCoord); // Adjacency point.
2330 }
2331 break;
2332 }
2333 default:
2334 TCU_THROW(InternalError, "Unrecognized primitive topology");
2335 }
2336 }
2337
copyColorImageToBuffer(const DeviceInterface & vk,VkCommandBuffer cmdBuffer,VkImage image,VkBuffer buffer)2338 void ConcurrentPrimitivesGeneratedQueryTestInstance::copyColorImageToBuffer(const DeviceInterface &vk,
2339 VkCommandBuffer cmdBuffer, VkImage image,
2340 VkBuffer buffer)
2341 {
2342 const VkImageSubresourceRange colorSubresourceRange =
2343 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1);
2344 vk::VkImageMemoryBarrier postImageBarrier = vk::makeImageMemoryBarrier(
2345 vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT,
2346 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, vk::VK_IMAGE_LAYOUT_GENERAL, image, colorSubresourceRange);
2347 vk.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
2348 vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0u, 0u,
2349 (const vk::VkMemoryBarrier *)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier *)DE_NULL, 1u,
2350 &postImageBarrier);
2351 vk::VkExtent3D extent = {m_imageWidth, m_imageHeight, 1};
2352 const auto colorSubresourceLayers = vk::makeImageSubresourceLayers(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
2353 const vk::VkBufferImageCopy colorCopyRegion = vk::makeBufferImageCopy(extent, colorSubresourceLayers);
2354 vk.cmdCopyImageToBuffer(cmdBuffer, image, vk::VK_IMAGE_LAYOUT_GENERAL, buffer, 1u, &colorCopyRegion);
2355 }
2356
2357 class ConcurrentPrimitivesGeneratedQueryTestCase : public vkt::TestCase
2358 {
2359 public:
ConcurrentPrimitivesGeneratedQueryTestCase(tcu::TestContext & context,const char * name,const ConcurrentTestParameters & parameters)2360 ConcurrentPrimitivesGeneratedQueryTestCase(tcu::TestContext &context, const char *name,
2361 const ConcurrentTestParameters ¶meters)
2362 : TestCase(context, name)
2363 , m_parameters(parameters)
2364 {
2365 }
2366
2367 private:
2368 void checkSupport(vkt::Context &context) const;
2369 void initPrograms(vk::SourceCollections &programCollection) const;
createInstance(vkt::Context & context) const2370 vkt::TestInstance *createInstance(vkt::Context &context) const
2371 {
2372 return new ConcurrentPrimitivesGeneratedQueryTestInstance(context, m_parameters);
2373 }
2374
2375 const ConcurrentTestParameters m_parameters;
2376 };
2377
checkSupport(vkt::Context & context) const2378 void ConcurrentPrimitivesGeneratedQueryTestCase::checkSupport(vkt::Context &context) const
2379 {
2380 context.requireDeviceFunctionality("VK_EXT_primitives_generated_query");
2381 context.requireDeviceFunctionality("VK_EXT_transform_feedback");
2382
2383 const VkPhysicalDevicePrimitivesGeneratedQueryFeaturesEXT &pgqFeatures =
2384 context.getPrimitivesGeneratedQueryFeaturesEXT();
2385 const VkPhysicalDeviceTransformFeedbackFeaturesEXT &xfbFeatures = context.getTransformFeedbackFeaturesEXT();
2386 const VkPhysicalDeviceTransformFeedbackPropertiesEXT &xfbProperties = context.getTransformFeedbackPropertiesEXT();
2387
2388 if (pgqFeatures.primitivesGeneratedQuery != VK_TRUE)
2389 TCU_THROW(NotSupportedError, "VK_QUERY_TYPE_PRIMITIVES_GENERATED_EXT not supported");
2390
2391 if (m_parameters.shaderStage == SHADER_STAGE_GEOMETRY ||
2392 topologyData.at(m_parameters.primitiveTopology).hasAdjacency)
2393 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
2394
2395 if (m_parameters.shaderStage == SHADER_STAGE_TESSELLATION_EVALUATION)
2396 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
2397
2398 if (m_parameters.nonZeroStreams())
2399 {
2400 const uint32_t requiredStreams = de::max(m_parameters.pgqStreamIndex(), m_parameters.xfbStreamIndex());
2401
2402 if (m_parameters.pgqStreamIndex() > 0 && pgqFeatures.primitivesGeneratedQueryWithNonZeroStreams != VK_TRUE)
2403 TCU_THROW(NotSupportedError, "primitivesGeneratedQueryWithNonZeroStreams not supported");
2404
2405 if (xfbProperties.maxTransformFeedbackStreams <= requiredStreams)
2406 TCU_THROW(NotSupportedError, "Required amount of XFB streams not supported");
2407 }
2408
2409 if (xfbFeatures.transformFeedback != VK_TRUE)
2410 TCU_THROW(NotSupportedError, "transformFeedback not supported");
2411
2412 if (xfbProperties.transformFeedbackQueries != VK_TRUE)
2413 TCU_THROW(NotSupportedError, "transformFeedbackQueries not supported");
2414
2415 if (m_parameters.concurrentTestType == CONCURRENT_TEST_TYPE_PIPELINE_STATISTICS_1 ||
2416 m_parameters.concurrentTestType == CONCURRENT_TEST_TYPE_PIPELINE_STATISTICS_2 ||
2417 m_parameters.concurrentTestType == CONCURRENT_TEST_TYPE_PIPELINE_STATISTICS_3)
2418 {
2419 if (!context.getDeviceFeatures().pipelineStatisticsQuery)
2420 TCU_THROW(NotSupportedError, "pipelineStatisticsQuery not supported");
2421 }
2422 }
2423
initPrograms(vk::SourceCollections & programCollection) const2424 void ConcurrentPrimitivesGeneratedQueryTestCase::initPrograms(vk::SourceCollections &programCollection) const
2425 {
2426 bool transformFeedback = m_parameters.xfbStreamIndex() != VERTEX_STREAM_NONE;
2427 // Vertex shader.
2428 {
2429 const bool vertXfb = (transformFeedback && m_parameters.shaderStage == SHADER_STAGE_VERTEX);
2430 std::ostringstream src;
2431
2432 src << "#version 450\n";
2433 src << "layout(location=0) in vec2 inPosition;\n";
2434
2435 if (vertXfb)
2436 src << "layout(xfb_buffer = " << m_parameters.xfbStreamIndex()
2437 << ", xfb_offset = 0, xfb_stride = 16, location = 0) out vec4 out0;\n";
2438
2439 src << "void main (void)\n"
2440 "{\n";
2441
2442 if (m_parameters.primitiveTopology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST &&
2443 m_parameters.shaderStage == SHADER_STAGE_VERTEX)
2444 src << " gl_PointSize = 1.0;\n";
2445
2446 src << " gl_Position = vec4(inPosition, 0, 1);\n";
2447
2448 if (vertXfb)
2449 src << " out0 = vec4(42);\n";
2450
2451 src << "}\n";
2452
2453 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
2454 }
2455
2456 // Geometry shader.
2457 if (m_parameters.shaderStage == SHADER_STAGE_GEOMETRY)
2458 {
2459 const bool outputPoints =
2460 m_parameters.nonZeroStreams() || m_parameters.primitiveTopology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
2461 const char *const inputTopology = topologyData.at(m_parameters.primitiveTopology).inputString;
2462 const char *const outputTopology =
2463 outputPoints ? "points" : topologyData.at(m_parameters.primitiveTopology).outputString;
2464 const VkDeviceSize outputPrimSize =
2465 outputPoints ? 1 : topologyData.at(m_parameters.primitiveTopology).primitiveSize;
2466 VkDeviceSize maxVertices =
2467 (transformFeedback && m_parameters.multipleStreams()) ? outputPrimSize * 2 : outputPrimSize;
2468 const bool outputZero = m_parameters.pgqStreamIndex() != 0 &&
2469 (!transformFeedback || (transformFeedback && m_parameters.xfbStreamIndex() != 0));
2470 if (outputZero)
2471 maxVertices *= 2;
2472 const std::string pgqEmitCommand =
2473 m_parameters.nonZeroStreams() ?
2474 std::string("EmitStreamVertex(") + de::toString(m_parameters.pgqStreamIndex()) + ")" :
2475 "EmitVertex()";
2476 const std::string xfbEmitCommand =
2477 m_parameters.nonZeroStreams() ?
2478 std::string("EmitStreamVertex(") + de::toString(m_parameters.xfbStreamIndex()) + ")" :
2479 "EmitVertex()";
2480 const std::string pgqEndCommand =
2481 m_parameters.nonZeroStreams() ?
2482 std::string("EndStreamPrimitive(") + de::toString(m_parameters.pgqStreamIndex()) + ")" :
2483 "EndPrimitive()";
2484 const std::string xfbEndCommand =
2485 m_parameters.nonZeroStreams() ?
2486 std::string("EndStreamPrimitive(") + de::toString(m_parameters.xfbStreamIndex()) + ")" :
2487 "EndPrimitive()";
2488 std::string output;
2489
2490 if (m_parameters.primitiveTopology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY)
2491 {
2492 output =
2493 // Each point will be in the middle X and Y coordinates of each triangle.
2494 " const vec3 xCoords = vec3(gl_in[0].gl_Position.x, gl_in[2].gl_Position.x, "
2495 "gl_in[4].gl_Position.x);\n"
2496 " const vec3 yCoords = vec3(gl_in[0].gl_Position.y, gl_in[2].gl_Position.y, "
2497 "gl_in[4].gl_Position.y);\n"
2498 " const float maxX = max(max(xCoords.x, xCoords.y), xCoords.z);\n"
2499 " const float minX = min(min(xCoords.x, xCoords.y), xCoords.z);\n"
2500 " const float maxY = max(max(yCoords.x, yCoords.y), yCoords.z);\n"
2501 " const float minY = min(min(yCoords.x, yCoords.y), yCoords.z);\n"
2502 " gl_Position = vec4((maxX + minX) / 2.0, (maxY + minY) / 2.0, gl_in[0].gl_Position.z, "
2503 "gl_in[0].gl_Position.w);\n";
2504 }
2505 else if (m_parameters.primitiveTopology != VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN)
2506 output = " gl_Position = gl_in[0].gl_Position;\n";
2507 else
2508 output = " gl_Position = abs(gl_in[0].gl_Position.y) < abs(gl_in[1].gl_Position.y) ? "
2509 "gl_in[0].gl_Position : gl_in[1].gl_Position;\n";
2510
2511 if (outputPoints)
2512 output += " gl_PointSize = 1.0;\n";
2513
2514 std::ostringstream src;
2515
2516 src << "#version 450\n"
2517 "layout("
2518 << inputTopology
2519 << ") in;\n"
2520 "layout("
2521 << outputTopology << ", max_vertices = " << maxVertices << ") out;\n";
2522
2523 if (transformFeedback)
2524 src << "layout(xfb_buffer = " << m_parameters.xfbStreamIndex()
2525 << ", xfb_offset = 0, xfb_stride = 16, location = 0, stream = " << m_parameters.xfbStreamIndex()
2526 << ") out vec4 xfb;\n";
2527
2528 src << "void main (void)\n"
2529 "{\n";
2530
2531 if (outputZero)
2532 {
2533 src << output;
2534 src << " EmitVertex();\n";
2535 src << " EndPrimitive();\n";
2536 }
2537
2538 if (transformFeedback)
2539 src << " xfb = vec4(42);\n";
2540
2541 for (VkDeviceSize i = 0; i < outputPrimSize; i++)
2542 {
2543 if (m_parameters.pgqStreamIndex() == 0)
2544 src << output;
2545 src << " " << pgqEmitCommand << ";\n";
2546 }
2547
2548 src << " " << pgqEndCommand << ";\n";
2549
2550 if (transformFeedback && m_parameters.multipleStreams())
2551 {
2552 for (VkDeviceSize i = 0; i < outputPrimSize; i++)
2553 {
2554 if (m_parameters.xfbStreamIndex() == 0)
2555 src << output;
2556 src << " " << xfbEmitCommand << ";\n";
2557 }
2558
2559 src << " " << xfbEndCommand << ";\n";
2560 }
2561
2562 src << "}\n";
2563
2564 programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
2565 }
2566
2567 // Fragment shader.
2568 {
2569 std::ostringstream src;
2570
2571 src << "#version 450\n"
2572 "layout(location = 0) out vec4 out0;\n"
2573 "void main (void)\n"
2574 "{\n"
2575 " out0 = vec4(0.0, 1.0, 0.0, 1.0);\n"
2576 "}\n";
2577
2578 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
2579 }
2580 }
2581
testGenerator(tcu::TestCaseGroup * pgqGroup)2582 void testGenerator(tcu::TestCaseGroup *pgqGroup)
2583 {
2584 constexpr struct ReadType
2585 {
2586 QueryReadType type;
2587 const char *name;
2588 } readTypes[] = {
2589 // Tests for vkGetQueryPoolResults
2590 {QUERY_READ_TYPE_GET, "get"},
2591 // Tests for vkCmdCopyQueryPoolResults
2592 {QUERY_READ_TYPE_COPY, "copy"},
2593 };
2594 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(readTypes) == QUERY_READ_TYPE_LAST);
2595
2596 constexpr struct ResetType
2597 {
2598 QueryResetType type;
2599 const char *name;
2600 } resetTypes[] = {
2601 // Tests for vkCmdResetQueryPool
2602 {QUERY_RESET_TYPE_QUEUE, "queue_reset"},
2603 // Tests for vkResetQueryPool
2604 {QUERY_RESET_TYPE_HOST, "host_reset"},
2605 };
2606 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(resetTypes) == QUERY_RESET_TYPE_LAST);
2607
2608 constexpr struct ResultTypes
2609 {
2610 QueryResultType type;
2611 const char *name;
2612 } resultTypes[] = {
2613 // Tests for default query result size
2614 {QUERY_RESULT_TYPE_32_BIT, "32bit"},
2615 // Tests for VK_QUERY_RESULT_64_BIT
2616 {QUERY_RESULT_TYPE_64_BIT, "64bit"},
2617 // Tests for PGQ without and XFBQ with VK_QUERY_RESULT_64_BIT
2618 {QUERY_RESULT_TYPE_PGQ_32_XFB_64, "pgq_32bit_xfb_64bit"},
2619 // Tests for PGQ with and XFBQ without VK_QUERY_RESULT_64_BIT
2620 {QUERY_RESULT_TYPE_PGQ_64_XFB_32, "pgq_64bit_xfb_32bit"},
2621 };
2622 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(resultTypes) == QUERY_RESULT_TYPE_LAST);
2623
2624 constexpr struct Shader
2625 {
2626 ShaderStage stage;
2627 const char *name;
2628 } shaderStages[] = {
2629 // Vertex shader tests
2630 {SHADER_STAGE_VERTEX, "vert"},
2631 // Tessellation evaluation shader tests
2632 {SHADER_STAGE_TESSELLATION_EVALUATION, "tese"},
2633 // Geometry shader tests
2634 {SHADER_STAGE_GEOMETRY, "geom"},
2635 };
2636 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(shaderStages) == SHADER_STAGE_LAST);
2637
2638 constexpr struct TransformFeedbackState
2639 {
2640 bool enable;
2641 const char *name;
2642 } transformFeedbackStates[] = {
2643 // Tests without transform feedback
2644 {false, "no_xfb"},
2645 // Tests for comparing PGQ results against transform feedback query results
2646 {true, "xfb"},
2647 };
2648
2649 constexpr struct RastCase
2650 {
2651 RasterizationCase type;
2652 bool dsAttachment;
2653 const char *name;
2654 } rastCases[] = {
2655 // Tests with rasterizer discard
2656 {RAST_CASE_DISCARD, false, "no_rast"},
2657 // Tests without rasterizer discard
2658 {RAST_CASE_DEFAULT, false, "rast"},
2659 // Tests with an empty fragment shader
2660 {RAST_CASE_EMPTY_FRAG, false, "empty_frag"},
2661 // Tests with an attachmentless render pass
2662 {RAST_CASE_NO_ATTACHMENT, false, "no_attachment"},
2663 // Tests disabling color output using VkPipelineColorWriteCreateInfoEXT
2664 {RAST_CASE_COLOR_WRITE_DISABLE_STATIC, false, "color_write_disable_static"},
2665 // Tests disabling color output using VkPipelineColorWriteCreateInfoEXT with a depth stencil attachment
2666 {RAST_CASE_COLOR_WRITE_DISABLE_STATIC, true, "color_write_disable_static_ds"},
2667 // Tests disabling color output using vkCmdSetColorWriteEnableEXT
2668 {RAST_CASE_COLOR_WRITE_DISABLE_DYNAMIC, false, "color_write_disable_dynamic"},
2669 // Tests disabling color output using vkCmdSetColorWriteEnableEXT with a depth stencil attachment
2670 {RAST_CASE_COLOR_WRITE_DISABLE_DYNAMIC, true, "color_write_disable_dynamic_ds"},
2671 };
2672
2673 static const std::set<RasterizationCase> rasterizationCasesWithAvailability{
2674 RAST_CASE_DISCARD,
2675 RAST_CASE_DEFAULT,
2676 RAST_CASE_NO_ATTACHMENT,
2677 };
2678
2679 constexpr struct Topology
2680 {
2681 VkPrimitiveTopology type;
2682 const char *name;
2683 } topologies[] = {
2684 // Tests for separate point primitives
2685 {VK_PRIMITIVE_TOPOLOGY_POINT_LIST, "point_list"},
2686 // Tests for separate line primitives
2687 {VK_PRIMITIVE_TOPOLOGY_LINE_LIST, "line_list"},
2688 // Tests for connected line primitives with consecutive lines sharing a vertex
2689 {VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, "line_strip"},
2690 // Tests for separate triangle primitives
2691 {VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, "triangle_list"},
2692 // Tests for connected triangle primitives with consecutive triangles sharing an edge
2693 {VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, "triangle_strip"},
2694 // Tests for connected triangle primitives with all triangles sharing a common vertex
2695 {VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, "triangle_fan"},
2696 // Tests for separate line primitives with adjacency
2697 {VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY, "line_list_with_adjacency"},
2698 // Tests for connected line primitives with adjacency, with consecutive primitives sharing three vertices
2699 {VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY, "line_strip_with_adjacency"},
2700 // Tests for separate triangle primitives with adjacency
2701 {VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY, "triangle_list_with_adjacency"},
2702 // Tests for connected triangle primitives with adjacency, with consecutive triangles sharing an edge
2703 {VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY, "triangle_strip_with_adjacency"},
2704 // Tests for separate patch primitives
2705 {VK_PRIMITIVE_TOPOLOGY_PATCH_LIST, "patch_list"},
2706 };
2707
2708 static const std::set<VkPrimitiveTopology> topologiesWithAvailability{
2709 VK_PRIMITIVE_TOPOLOGY_LINE_LIST,
2710 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
2711 VK_PRIMITIVE_TOPOLOGY_PATCH_LIST,
2712 };
2713
2714 // Tests for vkCmdBeginQueryIndexedEXT and vkCmdEndQueryIndexedEXT.
2715 constexpr struct StreamIndex
2716 {
2717 VertexStream index;
2718 const char *name;
2719 } streamIndices[] = {
2720 {VERTEX_STREAM_DEFAULT, "default"},
2721 {VERTEX_STREAM_0, "0"},
2722 {VERTEX_STREAM_1, "1"},
2723 };
2724
2725 constexpr struct CmdBufCase
2726 {
2727 CommandBufferCase type;
2728 const char *name;
2729 } cmdBufCases[] = {
2730 // Test single draw call
2731 {CMD_BUF_CASE_SINGLE_DRAW, "single_draw"},
2732 // Test two draw calls
2733 {CMD_BUF_CASE_TWO_DRAWS, "two_draws"},
2734 };
2735 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(cmdBufCases) == CMD_BUF_CASE_LAST);
2736
2737 constexpr struct
2738 {
2739 uint32_t queryCount;
2740 const char *nameSuffix;
2741 } queryCountCases[] = {
2742 {1u, ""},
2743 // using 2 queries
2744 {2u, "_2_queries"},
2745 };
2746
2747 constexpr struct QueryOrderCase
2748 {
2749 QueryOrder order;
2750 const char *name;
2751 } queryOrderCases[] = {
2752 // Test starting primitives generated query first
2753 {QUERY_ORDER_PGQ_FIRST, "pqg_first"},
2754 // Test starting transform feedback query first
2755 {QUERY_ORDER_XFBQ_FIRST, "xfbq_first"},
2756 };
2757 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(queryOrderCases) == QUERY_ORDER_LAST);
2758
2759 constexpr struct OutsideDrawCase
2760 {
2761 OutsideDraw outsideDraw;
2762 const char *name;
2763 } outsideDrawCases[] = {
2764 // Test without draws outside of active queries
2765 {OUTSIDE_DRAW_NONE, "none"},
2766 // Test with draws before active queries
2767 {OUTSIDE_DRAW_BEFORE, "before"},
2768 // Test with draw after active queries
2769 {OUTSIDE_DRAW_AFTER, "after"},
2770 };
2771 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(outsideDrawCases) == OUTSIDE_DRAW_LAST);
2772
2773 tcu::TestContext &testCtx = pgqGroup->getTestContext();
2774
2775 for (const ReadType &read : readTypes)
2776 {
2777 de::MovePtr<tcu::TestCaseGroup> readGroup(new tcu::TestCaseGroup(testCtx, read.name));
2778
2779 for (const ResetType &reset : resetTypes)
2780 {
2781 de::MovePtr<tcu::TestCaseGroup> resetGroup(new tcu::TestCaseGroup(testCtx, reset.name));
2782
2783 for (const ResultTypes &result : resultTypes)
2784 {
2785 de::MovePtr<tcu::TestCaseGroup> resultGroup(new tcu::TestCaseGroup(testCtx, result.name));
2786
2787 for (const Shader &shader : shaderStages)
2788 {
2789 de::MovePtr<tcu::TestCaseGroup> shaderGroup(new tcu::TestCaseGroup(testCtx, shader.name));
2790
2791 for (const TransformFeedbackState &xfbState : transformFeedbackStates)
2792 {
2793 de::MovePtr<tcu::TestCaseGroup> xfbGroup(new tcu::TestCaseGroup(testCtx, xfbState.name));
2794
2795 // Only test multiple result types with XFB enabled.
2796 if ((result.type == QUERY_RESULT_TYPE_PGQ_32_XFB_64 ||
2797 result.type == QUERY_RESULT_TYPE_PGQ_64_XFB_32) &&
2798 !xfbState.enable)
2799 continue;
2800
2801 for (const RastCase &rastCase : rastCases)
2802 {
2803 de::MovePtr<tcu::TestCaseGroup> rastGroup(new tcu::TestCaseGroup(testCtx, rastCase.name));
2804
2805 // Skip uninteresting cases
2806 if ((rastCase.type > RAST_CASE_DISCARD) &&
2807 ((read.type != QUERY_READ_TYPE_GET) || (reset.type != QUERY_RESET_TYPE_QUEUE) ||
2808 (result.type != QUERY_RESULT_TYPE_32_BIT)))
2809 {
2810 continue;
2811 }
2812
2813 for (const Topology &topology : topologies)
2814 {
2815 de::MovePtr<tcu::TestCaseGroup> topologyGroup(
2816 new tcu::TestCaseGroup(testCtx, topology.name));
2817
2818 // Only test patch lists with tessellation shaders.
2819 if ((topology.type == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST &&
2820 shader.stage != SHADER_STAGE_TESSELLATION_EVALUATION) ||
2821 ((topology.type != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST &&
2822 shader.stage == SHADER_STAGE_TESSELLATION_EVALUATION)))
2823 {
2824 continue;
2825 }
2826
2827 // Only test adjacency topologies with geometry shaders.
2828 if (shader.stage != SHADER_STAGE_GEOMETRY &&
2829 topologyData.at(topology.type).hasAdjacency)
2830 continue;
2831
2832 for (const StreamIndex &pgqStream : streamIndices)
2833 {
2834 for (const StreamIndex &xfbStream : streamIndices)
2835 {
2836 const std::string streamGroupName =
2837 std::string("pgq_") + pgqStream.name +
2838 (xfbState.enable ? std::string("_xfb_") + xfbStream.name : "");
2839 const bool pgqDefault = (pgqStream.index == VERTEX_STREAM_DEFAULT);
2840 const bool xfbDefault = (xfbStream.index == VERTEX_STREAM_DEFAULT);
2841 const std::string pgqDescStr =
2842 std::string("PGQ on ") + (pgqDefault ? "default " : "") +
2843 std::string("vertex stream ") + (pgqDefault ? "" : pgqStream.name);
2844 const std::string xfbDescStr =
2845 std::string("XFB on ") + (xfbDefault ? "default " : "") +
2846 std::string("vertex stream ") + (xfbDefault ? "" : xfbStream.name);
2847 const std::string streamGroupDesc =
2848 std::string("Tests for ") + pgqDescStr +
2849 (xfbState.enable ? (std::string(" and ") + xfbDescStr) : "");
2850 de::MovePtr<tcu::TestCaseGroup> streamGroup(
2851 new tcu::TestCaseGroup(testCtx, streamGroupName.c_str()));
2852
2853 // Only test nondefault vertex streams with geometry shaders.
2854 if ((pgqStream.index != VERTEX_STREAM_DEFAULT ||
2855 xfbStream.index != VERTEX_STREAM_DEFAULT) &&
2856 shader.stage != SHADER_STAGE_GEOMETRY)
2857 continue;
2858
2859 // Skip nondefault vertex streams for XFB when not enabled.
2860 if (!xfbState.enable && xfbStream.index != VERTEX_STREAM_DEFAULT)
2861 continue;
2862
2863 for (const CmdBufCase &cmdBufCase : cmdBufCases)
2864 {
2865 de::MovePtr<tcu::TestCaseGroup> cmdBufGroup(
2866 new tcu::TestCaseGroup(testCtx, cmdBufCase.name));
2867
2868 for (const QueryOrderCase &queryOrderCase : queryOrderCases)
2869 {
2870 if (queryOrderCase.order == QUERY_ORDER_XFBQ_FIRST &&
2871 xfbState.enable == false)
2872 continue;
2873
2874 de::MovePtr<tcu::TestCaseGroup> queryOrderGroup(
2875 new tcu::TestCaseGroup(testCtx, queryOrderCase.name));
2876 for (const OutsideDrawCase &outSideDrawCase : outsideDrawCases)
2877 {
2878 for (const auto &countCase : queryCountCases)
2879 {
2880 for (const auto availabilityBit : {false, true})
2881 {
2882 if (availabilityBit &&
2883 topologiesWithAvailability.count(topology.type) == 0)
2884 continue;
2885
2886 if (availabilityBit &&
2887 rasterizationCasesWithAvailability.count(
2888 rastCase.type) == 0)
2889 continue;
2890
2891 if (availabilityBit &&
2892 cmdBufCase.type != CMD_BUF_CASE_SINGLE_DRAW)
2893 continue;
2894
2895 const TestParameters parameters = {
2896 read.type, // QueryReadType queryReadType
2897 reset.type, // QueryResetType queryResetType
2898 result.type, // QueryResultType queryResultType
2899 shader.stage, // ShaderStage shaderStage
2900 xfbState
2901 .enable, // bool transformFeedback
2902 rastCase.type, // RasterizationCase rastCase
2903 rastCase
2904 .dsAttachment, // bool depthStencilAttachment
2905 topology
2906 .type, // VkPrimitiveTopology primitiveTopology
2907 pgqStream.index, // VertexStreamIndex pgqStreamIndex
2908 xfbStream.index, // VertexStreamIndex xfbStreamIndex
2909 cmdBufCase.type, // CommandBufferCase cmdBufCase
2910 countCase
2911 .queryCount, // const uint32_t queryCount
2912 queryOrderCase
2913 .order, // QueryOrder queryOrder
2914 outSideDrawCase
2915 .outsideDraw, // OutsideDraw outsideDraw
2916 availabilityBit, // const bool availabilityBit
2917 };
2918
2919 const auto availabilityNameSuffix =
2920 (availabilityBit ? "_with_availability" : "");
2921 const auto name = std::string(outSideDrawCase.name) +
2922 countCase.nameSuffix +
2923 availabilityNameSuffix;
2924
2925 queryOrderGroup->addChild(
2926 new PrimitivesGeneratedQueryTestCase(
2927 testCtx, name.c_str(), parameters));
2928 }
2929 }
2930 }
2931
2932 cmdBufGroup->addChild(queryOrderGroup.release());
2933 }
2934
2935 streamGroup->addChild(cmdBufGroup.release());
2936 }
2937
2938 topologyGroup->addChild(streamGroup.release());
2939 }
2940 }
2941
2942 rastGroup->addChild(topologyGroup.release());
2943 }
2944
2945 xfbGroup->addChild(rastGroup.release());
2946 }
2947
2948 shaderGroup->addChild(xfbGroup.release());
2949 }
2950
2951 resultGroup->addChild(shaderGroup.release());
2952 }
2953
2954 resetGroup->addChild(resultGroup.release());
2955 }
2956
2957 readGroup->addChild(resetGroup.release());
2958 }
2959
2960 pgqGroup->addChild(readGroup.release());
2961 }
2962
2963 constexpr struct ConcurrentTestTypeCase
2964 {
2965 ConcurrentTestType type;
2966 const char *name;
2967 } concurrentTestTypeCases[] = {
2968 {CONCURRENT_TEST_TYPE_TWO_XFB_INSIDE_PGQ, "two_xfbq_inside_pgq"},
2969 {CONCURRENT_TEST_TYPE_PGQ_SECONDARY_CMD_BUFFER, "pgq_secondary_cmd_buffers"},
2970 {CONCURRENT_TEST_TYPE_PIPELINE_STATISTICS_1, "pipeline_statistics_1"},
2971 {CONCURRENT_TEST_TYPE_PIPELINE_STATISTICS_2, "pipeline_statistics_2"},
2972 {CONCURRENT_TEST_TYPE_PIPELINE_STATISTICS_3, "pipeline_statistics_3"},
2973 };
2974 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(concurrentTestTypeCases) == CONCURRENT_TEST_TYPE_LAST);
2975
2976 constexpr struct DrawTypeCase
2977 {
2978 bool indirect;
2979 const char *name;
2980 } drawTypeCases[] = {
2981 {false, "draw"},
2982 {true, "indirect"},
2983 };
2984
2985 de::MovePtr<tcu::TestCaseGroup> concurrentGroup(new tcu::TestCaseGroup(testCtx, "concurrent"));
2986
2987 for (const ConcurrentTestTypeCase &concurrentTestType : concurrentTestTypeCases)
2988 {
2989 de::MovePtr<tcu::TestCaseGroup> concurrentTypeGroup(new tcu::TestCaseGroup(testCtx, concurrentTestType.name));
2990 for (const ResultTypes &result : resultTypes)
2991 {
2992 de::MovePtr<tcu::TestCaseGroup> resultGroup(new tcu::TestCaseGroup(testCtx, result.name));
2993
2994 for (const Topology &topology : topologies)
2995 {
2996 // Testing only with geometry shaders, skip patch list
2997 if (topology.type == vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST)
2998 continue;
2999
3000 de::MovePtr<tcu::TestCaseGroup> topologyGroup(new tcu::TestCaseGroup(testCtx, topology.name));
3001
3002 for (const DrawTypeCase &draw : drawTypeCases)
3003 {
3004 VertexStream pgqStreamIndex = VERTEX_STREAM_DEFAULT;
3005 VertexStream xfbStreamIndex = VERTEX_STREAM_NONE;
3006 if (concurrentTestType.type == CONCURRENT_TEST_TYPE_TWO_XFB_INSIDE_PGQ)
3007 xfbStreamIndex = VERTEX_STREAM_1;
3008
3009 const ConcurrentTestParameters parameters = {
3010 concurrentTestType.type, // ConcurrentTestType concurrentTestType;
3011 result.type, // QueryResultType queryResultType
3012 SHADER_STAGE_GEOMETRY, // ShaderStage shaderStage
3013 topology.type, // VkPrimitiveTopology primitiveTopology
3014 pgqStreamIndex, // VertexStreamIndex pgqStreamIndex
3015 xfbStreamIndex, // VertexStreamIndex xfbStreamIndex
3016 draw.indirect, // bool indirect
3017 };
3018
3019 topologyGroup->addChild(
3020 new ConcurrentPrimitivesGeneratedQueryTestCase(testCtx, draw.name, parameters));
3021 }
3022
3023 resultGroup->addChild(topologyGroup.release());
3024 }
3025
3026 concurrentTypeGroup->addChild(resultGroup.release());
3027 }
3028
3029 concurrentGroup->addChild(concurrentTypeGroup.release());
3030 }
3031 pgqGroup->addChild(concurrentGroup.release());
3032 }
3033
3034 } // namespace
3035
createPrimitivesGeneratedQueryTests(tcu::TestContext & testCtx)3036 tcu::TestCaseGroup *createPrimitivesGeneratedQueryTests(tcu::TestContext &testCtx)
3037 {
3038 return createTestGroup(testCtx, "primitives_generated_query", testGenerator);
3039 }
3040
3041 } // namespace TransformFeedback
3042 } // namespace vkt
3043