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 &parameters)
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 &parameters)
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 &parameters)
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 &parameters)
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