e8043036970ad58089f5cebdc343fc804d8f9d8d
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / transform_feedback / vktPrimitivesGeneratedQueryTests.cpp
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
36 #include "tcuTestLog.hpp"
37
38 #include <functional>
39 #include <map>
40
41 namespace vkt
42 {
43 namespace TransformFeedback
44 {
45 namespace
46 {
47 using namespace vk;
48
49 enum
50 {
51         IMAGE_WIDTH             = 64,
52         IMAGE_HEIGHT    = IMAGE_WIDTH,
53 };
54
55 enum QueryReadType
56 {
57         QUERY_READ_TYPE_GET,
58         QUERY_READ_TYPE_COPY,
59
60         QUERY_READ_TYPE_LAST
61 };
62
63 enum QueryResetType
64 {
65         QUERY_RESET_TYPE_QUEUE,
66         QUERY_RESET_TYPE_HOST,
67
68         QUERY_RESET_TYPE_LAST
69 };
70
71 enum QueryResultType
72 {
73         QUERY_RESULT_TYPE_32_BIT,
74         QUERY_RESULT_TYPE_64_BIT,
75         QUERY_RESULT_TYPE_PGQ_32_XFB_64,
76         QUERY_RESULT_TYPE_PGQ_64_XFB_32,
77
78         QUERY_RESULT_TYPE_LAST
79 };
80
81 enum ShaderStage
82 {
83         SHADER_STAGE_VERTEX,
84         SHADER_STAGE_TESSELLATION_EVALUATION,
85         SHADER_STAGE_GEOMETRY,
86
87         SHADER_STAGE_LAST
88 };
89
90 enum RasterizationCase
91 {
92         RAST_CASE_DEFAULT,
93         RAST_CASE_DISCARD,
94         RAST_CASE_EMPTY_FRAG,
95         RAST_CASE_NO_ATTACHMENT,
96         RAST_CASE_COLOR_WRITE_DISABLE_STATIC,
97         RAST_CASE_COLOR_WRITE_DISABLE_DYNAMIC,
98
99         RAST_CASE_LAST
100 };
101
102 enum VertexStream
103 {
104         VERTEX_STREAM_DEFAULT   = -1,
105         VERTEX_STREAM_0                 = 0,
106         VERTEX_STREAM_1                 = 1,
107 };
108
109 enum CommandBufferCase
110 {
111         CMD_BUF_CASE_SINGLE_DRAW,
112
113         CMD_BUF_CASE_LAST
114 };
115
116 struct TestParameters
117 {
118         QueryReadType           queryReadType;
119         QueryResetType          queryResetType;
120         QueryResultType         queryResultType;
121         ShaderStage                     shaderStage;
122         deBool                          transformFeedback;
123         RasterizationCase       rastCase;
124         deBool                          depthStencilAttachment;
125         VkPrimitiveTopology     primitiveTopology;
126         VertexStream            pgqStream;
127         VertexStream            xfbStream;
128         CommandBufferCase       cmdBufCase;
129
130         bool            pgqDefault                                      (void)  const   { return pgqStream == VERTEX_STREAM_DEFAULT;                                            }
131         bool            xfbDefault                                      (void)  const   { return xfbStream == VERTEX_STREAM_DEFAULT;                                            }
132         deUint32        pgqStreamIndex                          (void)  const   { return pgqDefault() ? 0 : static_cast<deUint32>(pgqStream);           }
133         deUint32        xfbStreamIndex                          (void)  const   { return xfbDefault() ? 0 : static_cast<deUint32>(xfbStream);           }
134         bool            multipleStreams                         (void)  const   { return pgqStreamIndex() != xfbStreamIndex();                                          }
135         bool            nonZeroStreams                          (void)  const   { return (pgqStreamIndex() != 0) || (xfbStreamIndex() != 0);            }
136         bool            rastDiscard                                     (void)  const   { return rastCase == RAST_CASE_DISCARD;                                                         }
137         bool            colorAttachment                         (void)  const   { return !rastDiscard() && rastCase != RAST_CASE_NO_ATTACHMENT;         }
138         bool            staticColorWriteDisable         (void)  const   { return rastCase == RAST_CASE_COLOR_WRITE_DISABLE_STATIC;                      }
139         bool            dynamicColorWriteDisable        (void)  const   { return rastCase == RAST_CASE_COLOR_WRITE_DISABLE_DYNAMIC;                     }
140         bool            colorWriteDisable                       (void)  const   { return staticColorWriteDisable() || dynamicColorWriteDisable();       }
141 };
142
143 struct TopologyInfo
144 {
145         deUint32                                                        primitiveSize;          // Size of the primitive.
146         deBool                                                          hasAdjacency;           // True if topology has adjacency.
147         const char*                                                     inputString;            // Layout qualifier identifier for geometry shader input.
148         const char*                                                     outputString;           // Layout qualifier identifier for geometry shader output.
149         std::function<deUint64(deUint64)>       getNumPrimitives;       // Number of primitives generated.
150         std::function<deUint64(deUint64)>       getNumVertices;         // Number of vertices generated.
151 };
152
153 const std::map<VkPrimitiveTopology, TopologyInfo> topologyData =
154 {
155         { VK_PRIMITIVE_TOPOLOGY_POINT_LIST,                                             { 1, DE_FALSE,  "points",                               "points",                       [](deUint64 vtxCount) { return vtxCount;                                }, [](deUint64 primCount) {     return primCount;                       } } },
156         { VK_PRIMITIVE_TOPOLOGY_LINE_LIST,                                              { 2, DE_FALSE,  "lines",                                "line_strip",           [](deUint64 vtxCount) { return vtxCount / 2u;                   }, [](deUint64 primCount) {     return primCount * 2u;          } } },
157         { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,                                             { 2, DE_FALSE,  "lines",                                "line_strip",           [](deUint64 vtxCount) { return vtxCount - 1u;                   }, [](deUint64 primCount) {     return primCount + 1u;          } } },
158         { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,                                  { 3, DE_FALSE,  "triangles",                    "triangle_strip",       [](deUint64 vtxCount) { return vtxCount / 3u;                   }, [](deUint64 primCount) {     return primCount * 3u;          } } },
159         { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,                                 { 3, DE_FALSE,  "triangles",                    "triangle_strip",       [](deUint64 vtxCount) { return vtxCount - 2u;                   }, [](deUint64 primCount) {     return primCount + 2u;          } } },
160         { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,                                   { 3, DE_FALSE,  "triangles",                    "triangle_strip",       [](deUint64 vtxCount) { return vtxCount - 2u;                   }, [](deUint64 primCount) {     return primCount + 2u;          } } },
161         { VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY,               { 2, DE_TRUE,   "lines_adjacency",              "line_strip",           [](deUint64 vtxCount) { return vtxCount / 4u;                   }, [](deUint64 primCount) {     return primCount * 4u;          } } },
162         { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY,              { 2, DE_TRUE,   "lines_adjacency",              "line_strip",           [](deUint64 vtxCount) { return vtxCount - 3u;                   }, [](deUint64 primCount) {     return primCount + 3u;          } } },
163         { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY,   { 3, DE_TRUE,   "triangles_adjacency",  "triangle_strip",       [](deUint64 vtxCount) { return vtxCount / 6u;                   }, [](deUint64 primCount) {     return primCount * 6u;          } } },
164         { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY,  { 3, DE_TRUE,   "triangles_adjacency",  "triangle_strip",       [](deUint64 vtxCount) { return (vtxCount - 4u) / 2u;    }, [](deUint64 primCount) {     return primCount * 2u + 4;      } } },
165         { VK_PRIMITIVE_TOPOLOGY_PATCH_LIST,                                             { 3, DE_FALSE,  "ERROR",                                "ERROR",                        [](deUint64 vtxCount) { return vtxCount / 3u;                   }, [](deUint64 primCount) {     return primCount * 3u;          } } },
166 };
167
168 class PrimitivesGeneratedQueryTestInstance : public vkt::TestInstance
169 {
170 public:
171                                                         PrimitivesGeneratedQueryTestInstance    (vkt::Context &context, const TestParameters& parameters)
172                                                                 : vkt::TestInstance     (context)
173                                                                 , m_parameters          (parameters)
174                                                         {
175                                                         }
176
177 private:
178         tcu::TestStatus                 iterate                                                                 (void);
179         VkFormat                                selectDepthStencilFormat                                (void);
180         Move<VkPipeline>                makeGraphicsPipeline                                    (const DeviceInterface& vk,
181                                                                                                                                          const VkDevice device,
182                                                                                                                                          const VkRenderPass renderPass);
183         void                                    fillVertexBuffer                                                (tcu::Vec2* vertices,
184                                                                                                                                          const deUint64 primitivesGenerated);
185         const TestParameters    m_parameters;
186 };
187
188 tcu::TestStatus PrimitivesGeneratedQueryTestInstance::iterate (void)
189 {
190         const DeviceInterface&                  vk                                      = m_context.getDeviceInterface();
191         const VkDevice                                  device                          = m_context.getDevice();
192         const deUint32                                  queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
193         const VkQueue                                   queue                           = m_context.getUniversalQueue();
194         Allocator&                                              allocator                       = m_context.getDefaultAllocator();
195
196         const VkFormat                                  colorFormat                     = m_parameters.colorAttachment() ? VK_FORMAT_R8G8B8A8_UNORM : VK_FORMAT_UNDEFINED;
197         Move<VkImage>                                   colorImage;
198         de::MovePtr<Allocation>                 colorImageAllocation;
199
200         if (m_parameters.colorAttachment())
201         {
202                 const VkImageCreateInfo colorImageCreateInfo =
203                 {
204                         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,            // VkStructureType                      sType
205                         DE_NULL,                                                                        // const void*                          pNext
206                         0u,                                                                                     // VkImageCreateFlags           flags
207                         VK_IMAGE_TYPE_2D,                                                       // VkImageType                          imageType
208                         colorFormat,                                                            // VkFormat                                     format
209                         makeExtent3D(IMAGE_WIDTH, IMAGE_HEIGHT, 1),     // VkExtent3D                           extent
210                         1u,                                                                                     // deUint32                                     mipLevels
211                         1u,                                                                                     // deUint32                                     arrayLayers
212                         VK_SAMPLE_COUNT_1_BIT,                                          // VkSampleCountFlagBits        samples
213                         VK_IMAGE_TILING_OPTIMAL,                                        // VkImageTiling                        tiling
214                         VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,            // VkImageUsageFlags            usage
215                         VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode                        sharingMode
216                         0u,                                                                                     // deUint32                                     queueFamilyIndexCount
217                         DE_NULL,                                                                        // const deUint32*                      pQueueFamilyIndices
218                         VK_IMAGE_LAYOUT_UNDEFINED,                                      // VkImageLayout                        initialLayout
219                 };
220
221                 colorImage                              = makeImage(vk, device, colorImageCreateInfo);
222                 colorImageAllocation    = bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any);
223         }
224
225         const VkFormat                                  dsFormat                        = m_parameters.depthStencilAttachment ? PrimitivesGeneratedQueryTestInstance::selectDepthStencilFormat() : VK_FORMAT_UNDEFINED;
226
227         if (m_parameters.depthStencilAttachment && dsFormat == VK_FORMAT_UNDEFINED)
228                 return tcu::TestStatus::fail("VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT feature must be supported for at least one of VK_FORMAT_D24_UNORM_S8_UINT and VK_FORMAT_D32_SFLOAT_S8_UINT.");
229
230         Move<VkImage>                                   dsImage;
231         de::MovePtr<Allocation>                 dsImageAllocation;
232
233         if (m_parameters.depthStencilAttachment)
234         {
235                 const VkImageCreateInfo dsImageCreateInfo =
236                 {
237                         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                    // VkStructureType                      sType
238                         DE_NULL,                                                                                // const void*                          pNext
239                         0u,                                                                                             // VkImageCreateFlags           flags
240                         VK_IMAGE_TYPE_2D,                                                               // VkImageType                          imageType
241                         dsFormat,                                                                               // VkFormat                                     format
242                         makeExtent3D(IMAGE_WIDTH, IMAGE_HEIGHT, 1),             // VkExtent3D                           extent
243                         1u,                                                                                             // deUint32                                     mipLevels
244                         1u,                                                                                             // deUint32                                     arrayLayers
245                         VK_SAMPLE_COUNT_1_BIT,                                                  // VkSampleCountFlagBits        samples
246                         VK_IMAGE_TILING_OPTIMAL,                                                // VkImageTiling                        tiling
247                         VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,    // VkImageUsageFlags            usage
248                         VK_SHARING_MODE_EXCLUSIVE,                                              // VkSharingMode                        sharingMode
249                         0u,                                                                                             // deUint32                                     queueFamilyIndexCount
250                         DE_NULL,                                                                                // const deUint32*                      pQueueFamilyIndices
251                         VK_IMAGE_LAYOUT_UNDEFINED,                                              // VkImageLayout                        initialLayout
252                 };
253
254                 dsImage                         = makeImage(vk, device, dsImageCreateInfo);
255                 dsImageAllocation       = bindImage(vk, device, allocator, *dsImage, MemoryRequirement::Any);
256         }
257
258         const VkDeviceSize                              primitivesGenerated = 32;
259         const deUint32                                  baseMipLevel            = 0;
260         const deUint32                                  levelCount                      = 1;
261         const deUint32                                  baseArrayLayer          = 0;
262         const deUint32                                  layerCount                      = 1;
263
264         Move<VkImageView>                               colorImageView;
265         Move<VkImageView>                               dsImageView;
266         std::vector<VkImageView>                imageViews;
267
268         if (m_parameters.colorAttachment())
269         {
270                 const VkImageSubresourceRange colorSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, baseMipLevel, levelCount, baseArrayLayer, layerCount);
271                 colorImageView = makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange);
272                 imageViews.push_back(*colorImageView);
273         }
274
275         if (m_parameters.depthStencilAttachment)
276         {
277                 const VkImageSubresourceRange dsSubresourceRange = makeImageSubresourceRange((VK_IMAGE_ASPECT_DEPTH_BIT | vk::VK_IMAGE_ASPECT_STENCIL_BIT), baseMipLevel, levelCount, baseArrayLayer, layerCount);
278                 dsImageView = makeImageView(vk, device, *dsImage, VK_IMAGE_VIEW_TYPE_2D, dsFormat, dsSubresourceRange);
279                 imageViews.push_back(*dsImageView);
280         }
281
282         const Unique<VkRenderPass>              renderPass                      (makeRenderPass(vk, device, colorFormat, dsFormat, VK_ATTACHMENT_LOAD_OP_DONT_CARE));
283         const Unique<VkFramebuffer>             framebuffer                     (makeFramebuffer(vk, device, *renderPass, (deUint32)imageViews.size(), imageViews.data(), IMAGE_WIDTH, IMAGE_HEIGHT));
284         const Unique<VkPipeline>                pipeline                        (PrimitivesGeneratedQueryTestInstance::makeGraphicsPipeline(vk, device, *renderPass));
285         Move<VkBuffer>                                  vtxBuffer;
286         de::MovePtr<Allocation>                 vtxBufferAlloc;
287
288         {
289                 const VkBufferUsageFlags                usage                           = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
290                 const std::vector<deUint32>             queueFamilyIndices      (1, queueFamilyIndex);
291                 const VkDeviceSize                              vtxBufferSize           = topologyData.at(m_parameters.primitiveTopology).getNumVertices(primitivesGenerated) * sizeof(tcu::Vec2);
292                 const VkBufferCreateInfo                createInfo                      = makeBufferCreateInfo(vtxBufferSize, usage, queueFamilyIndices);
293
294                 vtxBuffer                       = createBuffer(vk, device, &createInfo);
295                 vtxBufferAlloc          = allocator.allocate(getBufferMemoryRequirements(vk, device, *vtxBuffer), MemoryRequirement::HostVisible);
296         }
297
298         const VkCommandPoolCreateFlags  cmdPoolCreateFlags      = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
299         const VkCommandBufferLevel              cmdBufferLevel          = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
300         const Unique<VkCommandPool>             cmdPool                         (createCommandPool(vk, device, cmdPoolCreateFlags, queueFamilyIndex));
301         const Unique<VkCommandBuffer>   cmdBuffer                       (allocateCommandBuffer(vk, device, *cmdPool, cmdBufferLevel));
302
303         const bool                                              pgq64                           = (m_parameters.queryResultType == QUERY_RESULT_TYPE_64_BIT ||
304                                                                                                                    m_parameters.queryResultType == QUERY_RESULT_TYPE_PGQ_64_XFB_32);
305         const bool                                              xfb64                           = (m_parameters.queryResultType == QUERY_RESULT_TYPE_64_BIT ||
306                                                                                                                    m_parameters.queryResultType == QUERY_RESULT_TYPE_PGQ_32_XFB_64);
307         const size_t                                    pgqResultSize           = pgq64 ? sizeof(deUint64) : sizeof(deUint32);
308         const size_t                                    xfbResultSize           = xfb64 ? sizeof(deUint64) * 2 : sizeof(deUint32) * 2;
309         const VkQueryResultFlags                pgqResultWidthBit       = pgq64 ? VK_QUERY_RESULT_64_BIT : 0;
310         const VkQueryResultFlags                xfbResultWidthBit       = xfb64 ? VK_QUERY_RESULT_64_BIT : 0;
311         const VkQueryResultFlags                pgqResultFlags          = VK_QUERY_RESULT_WAIT_BIT | pgqResultWidthBit;
312         const VkQueryResultFlags                xfbResultFlags          = VK_QUERY_RESULT_WAIT_BIT | xfbResultWidthBit;
313
314         const deUint32                                  queryIndex                      = 0;
315         const deUint32                                  queryCount                      = 1;
316
317         std::vector<deUint8>                    pgqResults                      (pgqResultSize, 255u);
318         std::vector<deUint8>                    xfbResults                      (xfbResultSize, 255u);
319
320         const VkQueryPoolCreateInfo             pgqCreateInfo           =
321         {
322                 VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,       // VkStructureType                                      sType
323                 DE_NULL,                                                                        // const void*                                          pNext
324                 0u,                                                                                     // VkQueryPoolCreateFlags                       flags
325                 VK_QUERY_TYPE_PRIMITIVES_GENERATED_EXT,         // VkQueryType                                          queryType
326                 queryCount,                                                                     // deUint32                                                     queryCount
327                 0u,                                                                                     // VkQueryPipelineStatisticFlags        pipelineStatistics
328         };
329
330         const Unique<VkQueryPool>               pgqPool                         (createQueryPool(vk, device, &pgqCreateInfo));
331         Move<VkQueryPool>                               xfbPool;
332
333         if (m_parameters.transformFeedback)
334         {
335                 const VkQueryPoolCreateInfo xfbCreateInfo =
336                 {
337                         VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,               // VkStructureType                                      sType
338                         DE_NULL,                                                                                // const void*                                          pNext
339                         0u,                                                                                             // VkQueryPoolCreateFlags                       flags
340                         VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT,    // VkQueryType                                          queryType
341                         queryCount,                                                                             // deUint32                                                     queryCount
342                         0u,                                                                                             // VkQueryPipelineStatisticFlags        pipelineStatistics
343                 };
344
345                 xfbPool = createQueryPool(vk, device, &xfbCreateInfo);
346         }
347
348         Move<VkBuffer>                                  pgqResultsBuffer;
349         Move<VkBuffer>                                  xfbResultsBuffer;
350         de::MovePtr<Allocation>                 pgqResultsBufferAlloc;
351         de::MovePtr<Allocation>                 xfbResultsBufferAlloc;
352
353         if (m_parameters.queryReadType == QUERY_READ_TYPE_COPY)
354         {
355                 const VkBufferUsageFlags        usage                           = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
356                 const std::vector<deUint32>     queueFamilyIndices      (1, queueFamilyIndex);
357                 const VkBufferCreateInfo        pgqBufferCreateInfo     = makeBufferCreateInfo(pgqResultSize, usage, queueFamilyIndices);
358
359                 pgqResultsBuffer                = createBuffer(vk, device, &pgqBufferCreateInfo);
360                 pgqResultsBufferAlloc   = allocator.allocate(getBufferMemoryRequirements(vk, device, *pgqResultsBuffer), MemoryRequirement::HostVisible);
361
362                 VK_CHECK(vk.bindBufferMemory(device, *pgqResultsBuffer, pgqResultsBufferAlloc->getMemory(), pgqResultsBufferAlloc->getOffset()));
363
364                 if (m_parameters.transformFeedback)
365                 {
366                         const VkBufferCreateInfo xfbBufferCreateInfo = makeBufferCreateInfo(xfbResultSize, usage, queueFamilyIndices);
367
368                         xfbResultsBuffer                = createBuffer(vk, device, &xfbBufferCreateInfo);
369                         xfbResultsBufferAlloc   = allocator.allocate(getBufferMemoryRequirements(vk, device, *xfbResultsBuffer), MemoryRequirement::HostVisible);
370
371                         VK_CHECK(vk.bindBufferMemory(device, *xfbResultsBuffer, xfbResultsBufferAlloc->getMemory(), xfbResultsBufferAlloc->getOffset()));
372                 }
373         }
374
375         const VkDeviceSize                              primitivesWritten       = primitivesGenerated - 3;
376         const VkDeviceSize                              verticesWritten         = topologyData.at(m_parameters.primitiveTopology).getNumVertices(primitivesWritten);
377         const VkDeviceSize                              primitiveSize           = m_parameters.nonZeroStreams() ? 1 : topologyData.at(m_parameters.primitiveTopology).primitiveSize;
378         const VkDeviceSize                              bytesPerVertex          = 4 * sizeof(float);
379         const VkDeviceSize                              xfbBufferSize           = primitivesWritten * primitiveSize * bytesPerVertex;
380         Move<VkBuffer>                                  xfbBuffer;
381         de::MovePtr<Allocation>                 xfbBufferAlloc;
382
383         if (m_parameters.transformFeedback)
384         {
385                 const VkBufferUsageFlags        usage                           = VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT;
386                 const std::vector<deUint32>     queueFamilyIndices      (1, queueFamilyIndex);
387                 const VkBufferCreateInfo        createInfo                      = makeBufferCreateInfo(xfbBufferSize, usage, queueFamilyIndices);
388
389                 xfbBuffer               = createBuffer(vk, device, &createInfo);
390                 xfbBufferAlloc  = allocator.allocate(getBufferMemoryRequirements(vk, device, *xfbBuffer), MemoryRequirement::HostVisible);
391
392                 VK_CHECK(vk.bindBufferMemory(device, *xfbBuffer, xfbBufferAlloc->getMemory(), xfbBufferAlloc->getOffset()));
393         }
394
395         fillVertexBuffer(static_cast<tcu::Vec2*>(vtxBufferAlloc.get()->getHostPtr()), primitivesGenerated);
396
397         VK_CHECK(vk.bindBufferMemory(device, *vtxBuffer, vtxBufferAlloc->getMemory(), vtxBufferAlloc->getOffset()));
398
399         beginCommandBuffer(vk, *cmdBuffer);
400         {
401                 const VkDeviceSize      vertexBufferOffset      = static_cast<VkDeviceSize>(0);
402
403                 // After query pool creation, each query must be reset before it is used.
404                 if (m_parameters.queryResetType == QUERY_RESET_TYPE_QUEUE)
405                 {
406                         vk.cmdResetQueryPool(*cmdBuffer, *pgqPool, queryIndex, queryCount);
407
408                         if (m_parameters.transformFeedback)
409                                 vk.cmdResetQueryPool(*cmdBuffer, *xfbPool, queryIndex, queryCount);
410                 }
411
412                 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
413
414                 vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &vtxBuffer.get(), &vertexBufferOffset);
415
416                 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(makeExtent2D(IMAGE_WIDTH, IMAGE_HEIGHT)));
417                 {
418                         const VkQueryControlFlags       queryControlFlags               = 0;
419
420                         if (m_parameters.pgqDefault())
421                                 vk.cmdBeginQuery(*cmdBuffer, *pgqPool, queryIndex, queryControlFlags);
422                         else
423                                 vk.cmdBeginQueryIndexedEXT(*cmdBuffer, *pgqPool, queryIndex, queryControlFlags, m_parameters.pgqStreamIndex());
424
425                         const deUint32                          firstCounterBuffer              = 0;
426                         const deUint32                          counterBufferCount              = 0;
427                         const VkBuffer*                         counterBuffers                  = DE_NULL;
428                         const VkDeviceSize*                     counterBufferOffsets    = DE_NULL;
429
430                         if (m_parameters.transformFeedback)
431                         {
432                                 const deUint32          firstBinding    = 0;
433                                 const deUint32          bindingCount    = 1;
434                                 const VkDeviceSize      offset                  = 0;
435
436                                 vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, firstBinding, bindingCount, &*xfbBuffer, &offset, &xfbBufferSize);
437
438                                 if (m_parameters.xfbDefault())
439                                         vk.cmdBeginQuery(*cmdBuffer, *xfbPool, queryIndex, queryControlFlags);
440                                 else
441                                         vk.cmdBeginQueryIndexedEXT(*cmdBuffer, *xfbPool, queryIndex, queryControlFlags, m_parameters.xfbStreamIndex());
442
443                                 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, firstCounterBuffer, counterBufferCount, counterBuffers, counterBufferOffsets);
444                         }
445
446                         if (m_parameters.dynamicColorWriteDisable())
447                         {
448                                 const deUint32  attachmentCount         = 1;
449                                 const VkBool32  colorWriteEnables       = VK_FALSE;
450
451                                 vk.cmdSetColorWriteEnableEXT(*cmdBuffer, attachmentCount, &colorWriteEnables);
452                         }
453
454                         const deUint32                          vertexCount                             = static_cast<deUint32>(topologyData.at(m_parameters.primitiveTopology).getNumVertices(primitivesGenerated));
455                         const deUint32                          instanceCount                   = 1u;
456                         const deUint32                          firstVertex                             = 0u;
457                         const deUint32                          firstInstance                   = 0u;
458
459                         vk.cmdDraw(*cmdBuffer, vertexCount, instanceCount, firstVertex, firstInstance);
460
461                         if (m_parameters.pgqDefault())
462                                 vk.cmdEndQuery(*cmdBuffer, *pgqPool, queryIndex);
463                         else
464                                 vk.cmdEndQueryIndexedEXT(*cmdBuffer, *pgqPool, queryIndex, m_parameters.pgqStreamIndex());
465
466                         if (m_parameters.transformFeedback)
467                         {
468                                 if (m_parameters.xfbDefault())
469                                         vk.cmdEndQuery(*cmdBuffer, *xfbPool, queryIndex);
470                                 else
471                                         vk.cmdEndQueryIndexedEXT(*cmdBuffer, *xfbPool, queryIndex, m_parameters.xfbStreamIndex());
472
473                                 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, firstCounterBuffer, counterBufferCount, counterBuffers, counterBufferOffsets);
474                         }
475                 }
476                 endRenderPass(vk, *cmdBuffer);
477
478                 if (m_parameters.queryReadType == QUERY_READ_TYPE_COPY)
479                 {
480                         VkBufferMemoryBarrier bufferBarrier =
481                         {
482                                 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,        // VkStructureType      sType
483                                 DE_NULL,                                                                        // const void*          pNext
484                                 VK_ACCESS_TRANSFER_WRITE_BIT,                           // VkAccessFlags        srcAccessMask
485                                 VK_ACCESS_HOST_READ_BIT,                                        // VkAccessFlags        dstAccessMask
486                                 VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                     srcQueueFamilyIndex
487                                 VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                     dstQueueFamilyIndex
488                                 *pgqResultsBuffer,                                                      // VkBuffer                     buffer
489                                 0u,                                                                                     // VkDeviceSize         offset
490                                 VK_WHOLE_SIZE                                                           // VkDeviceSize         size
491                         };
492
493                         vk.cmdCopyQueryPoolResults(*cmdBuffer, *pgqPool, queryIndex, queryCount, *pgqResultsBuffer, 0u, pgqResultSize, pgqResultFlags);
494                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
495
496                         if (m_parameters.transformFeedback)
497                         {
498                                 bufferBarrier.buffer = *xfbResultsBuffer;
499                                 vk.cmdCopyQueryPoolResults(*cmdBuffer, *xfbPool, queryIndex, queryCount, *xfbResultsBuffer, 0u, xfbResultSize, xfbResultFlags);
500                                 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
501                         }
502                 }
503         }
504         endCommandBuffer(vk, *cmdBuffer);
505
506         // After query pool creation, each query must be reset before it is used.
507         if (m_parameters.queryResetType == QUERY_RESET_TYPE_HOST)
508         {
509                 vk.resetQueryPool(device, *pgqPool, queryIndex, queryCount);
510
511                 if (m_parameters.transformFeedback)
512                         vk.resetQueryPool(device, *xfbPool, queryIndex, queryCount);
513         }
514
515         submitCommandsAndWait(vk, device, queue, *cmdBuffer);
516
517         if (m_parameters.queryReadType == QUERY_READ_TYPE_COPY)
518         {
519                 invalidateAlloc(vk, device, *pgqResultsBufferAlloc);
520                 deMemcpy(pgqResults.data(), pgqResultsBufferAlloc->getHostPtr(), pgqResults.size());
521
522                 if (m_parameters.transformFeedback)
523                 {
524                         invalidateAlloc(vk, device, *xfbResultsBufferAlloc);
525                         deMemcpy(xfbResults.data(), xfbResultsBufferAlloc->getHostPtr(), xfbResults.size());
526                 }
527         }
528         else
529         {
530                 vk.getQueryPoolResults(device, *pgqPool, queryIndex, queryCount, pgqResults.size(), pgqResults.data(), pgqResults.size(), pgqResultFlags);
531
532                 if (m_parameters.transformFeedback)
533                         vk.getQueryPoolResults(device, *xfbPool, queryIndex, queryCount, xfbResults.size(), xfbResults.data(), xfbResults.size(), xfbResultFlags);
534         }
535
536         // Validate counters.
537         {
538                 union QueryResults
539                 {
540                         deUint32        elements32[2];
541                         deUint64        elements64[2];
542                 };
543
544                 const QueryResults*     pgqCounters             = reinterpret_cast<QueryResults*>(pgqResults.data());
545                 const QueryResults*     xfbCounters             = reinterpret_cast<QueryResults*>(xfbResults.data());
546                 const deUint64          pgqGenerated    = pgq64 ? pgqCounters->elements64[0] : static_cast<deUint64>(pgqCounters->elements32[0]);
547                 const deUint64          xfbWritten              = xfb64 ? xfbCounters->elements64[0] : static_cast<deUint64>(xfbCounters->elements32[0]);
548                 const deUint64          xfbGenerated    = xfb64 ? xfbCounters->elements64[1] : static_cast<deUint64>(xfbCounters->elements32[1]);
549                 tcu::TestLog&           log                             = m_context.getTestContext().getLog();
550
551                 log     <<      tcu::TestLog::Message
552                         <<      "primitivesGenerated: " << primitivesGenerated << "\n"
553                         <<      "primitivesWritten: " << primitivesWritten << "\n"
554                         <<      "verticesWritten: " << verticesWritten << "\n"
555                         <<      "xfbBufferSize: " << xfbBufferSize << "\n"
556                         <<      tcu::TestLog::EndMessage;
557
558                 log << tcu::TestLog::Message << "PGQ: Generated " << pgqGenerated << tcu::TestLog::EndMessage;
559
560                 if (m_parameters.transformFeedback)
561                         log << tcu::TestLog::Message << "XFB: Written " << xfbWritten << ", generated " << xfbGenerated << tcu::TestLog::EndMessage;
562
563                 if (pgqGenerated != primitivesGenerated)
564                 {
565                         const std::string message = std::string("pgqGenerated == ") + de::toString(pgqGenerated) + ", expected " + de::toString(primitivesGenerated);
566                         return tcu::TestStatus::fail(message);
567                 }
568
569                 if (m_parameters.transformFeedback)
570                 {
571                         if (xfbGenerated != primitivesGenerated)
572                         {
573                                 const std::string message = std::string("xfbGenerated == ") + de::toString(xfbGenerated) + ", expected " + de::toString(primitivesGenerated);
574                                 return tcu::TestStatus::fail(message);
575                         }
576
577                         if (xfbWritten != primitivesWritten)
578                         {
579                                 const std::string message = std::string("xfbWritten == ") + de::toString(xfbWritten) + ", expected " + de::toString(primitivesWritten);
580                                 return tcu::TestStatus::fail(message);
581                         }
582                 }
583         }
584
585         return tcu::TestStatus::pass("Counters OK");
586 }
587
588 VkFormat PrimitivesGeneratedQueryTestInstance::selectDepthStencilFormat (void)
589 {
590         constexpr VkFormat                      formats[]               =
591         {
592                 VK_FORMAT_D32_SFLOAT_S8_UINT,
593                 VK_FORMAT_D24_UNORM_S8_UINT
594         };
595
596         const InstanceInterface&        vki                             = m_context.getInstanceInterface();
597         const VkPhysicalDevice          physicalDevice  = m_context.getPhysicalDevice();
598
599         for (VkFormat format : formats)
600         {
601                 const VkFormatFeatureFlags features = getPhysicalDeviceFormatProperties(vki, physicalDevice, format).optimalTilingFeatures;
602
603                 if (features & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)
604                         return format;
605         }
606
607         return VK_FORMAT_UNDEFINED;
608 }
609
610 Move<VkPipeline> PrimitivesGeneratedQueryTestInstance::makeGraphicsPipeline (const DeviceInterface&     vk, const VkDevice device, const VkRenderPass renderPass)
611 {
612         const VkDescriptorSetLayout                                             descriptorSetLayout                             = DE_NULL;
613         const Unique<VkPipelineLayout>                                  pipelineLayout                                  (makePipelineLayout(vk, device, descriptorSetLayout));
614         const std::vector<VkViewport>                                   viewports                                               (1, makeViewport(makeExtent2D(IMAGE_WIDTH, IMAGE_HEIGHT)));
615         const std::vector<VkRect2D>                                             scissors                                                (1, makeRect2D(makeExtent2D(IMAGE_WIDTH, IMAGE_HEIGHT)));
616         const deUint32                                                                  subpass                                                 = 0u;
617         const deUint32                                                                  patchControlPoints                              = topologyData.at(VK_PRIMITIVE_TOPOLOGY_PATCH_LIST).primitiveSize;
618         const Unique<VkShaderModule>                                    vertModule                                              (createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
619         Move<VkShaderModule>                                                    tescModule;
620         Move<VkShaderModule>                                                    teseModule;
621         Move<VkShaderModule>                                                    geomModule;
622         Move<VkShaderModule>                                                    fragModule;
623         VkVertexInputBindingDescription                                 bindingDescription;
624         VkVertexInputAttributeDescription                               attributeDescription;
625
626         if (m_parameters.shaderStage == SHADER_STAGE_TESSELLATION_EVALUATION)
627         {
628                 tescModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("tesc"), 0u);
629                 teseModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("tese"), 0u);
630         }
631
632         if (m_parameters.shaderStage == SHADER_STAGE_GEOMETRY)
633                 geomModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("geom"), 0u);
634
635         if (!m_parameters.rastDiscard())
636                 fragModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u);
637
638         bindingDescription.binding              = 0;
639         bindingDescription.stride               = sizeof(tcu::Vec2);
640         bindingDescription.inputRate    = VK_VERTEX_INPUT_RATE_VERTEX;
641
642         attributeDescription.binding    = 0;
643         attributeDescription.location   = 0;
644         attributeDescription.format             = VK_FORMAT_R32G32_SFLOAT;
645         attributeDescription.offset             = 0;
646
647         const VkPipelineVertexInputStateCreateInfo              vertexInputStateCreateInfo              =
648         {
649                 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,      // VkStructureType                                                      sType
650                 DE_NULL,                                                                                                        // const void*                                                          pNext
651                 0u,                                                                                                                     // VkPipelineVertexInputStateCreateFlags        flags
652                 1u,                                                                                                                     // deUint32                                                                     vertexBindingDescriptionCount
653                 &bindingDescription,                                                                            // const VkVertexInputBindingDescription*       pVertexBindingDescriptions
654                 1u,                                                                                                                     // deUint32                                                                     vertexAttributeDescriptionCount
655                 &attributeDescription,                                                                          // const VkVertexInputAttributeDescription*     pVertexAttributeDescriptions
656         };
657
658         const VkPipelineRasterizationStateCreateInfo    rasterizationStateCreateInfo    =
659         {
660                 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,     // VkStructureType                                                      sType
661                 DE_NULL,                                                                                                        // const void*                                                          pNext
662                 0,                                                                                                                      // VkPipelineRasterizationStateCreateFlags      flags
663                 VK_FALSE,                                                                                                       // VkBool32                                                                     depthClampEnable
664                 (m_parameters.rastDiscard() ? VK_TRUE : VK_FALSE),                      // VkBool32                                                                     rasterizerDiscardEnable
665                 VK_POLYGON_MODE_FILL,                                                                           // VkPolygonMode                                                        polygonMode
666                 VK_CULL_MODE_NONE,                                                                                      // VkCullModeFlags                                                      cullMode
667                 VK_FRONT_FACE_COUNTER_CLOCKWISE,                                                        // VkFrontFace                                                          frontFace
668                 VK_FALSE,                                                                                                       // VkBool32                                                                     depthBiasEnable
669                 0.0f,                                                                                                           // float                                                                        depthBiasConstantFactor
670                 0.0f,                                                                                                           // float                                                                        depthBiasClamp
671                 0.0f,                                                                                                           // float                                                                        depthBiasSlopeFactor
672                 1.0f                                                                                                            // float                                                                        lineWidth
673         };
674
675         const VkStencilOpState                                                  stencilOpState                                  =
676         {
677                 VK_STENCIL_OP_KEEP,             // VkStencilOp  failOp
678                 VK_STENCIL_OP_KEEP,             // VkStencilOp  passOp
679                 VK_STENCIL_OP_KEEP,             // VkStencilOp  depthFailOp
680                 VK_COMPARE_OP_ALWAYS,   // VkCompareOp  compareOp
681                 0xFFu,                                  // deUint32             compareMask
682                 0xFFu,                                  // deUint32             writeMask
683                 0,                                              // deUint32             reference
684         };
685
686         const VkPipelineDepthStencilStateCreateInfo             depthStencilStateCreateInfo             =
687         {
688                 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,     //      VkStructureType                                                 sType
689                 DE_NULL,                                                                                                        //      const void*                                                             pNext
690                 0,                                                                                                                      //      VkPipelineDepthStencilStateCreateFlags  flags
691                 VK_TRUE,                                                                                                        //      VkBool32                                                                depthTestEnable
692                 VK_TRUE,                                                                                                        //      VkBool32                                                                depthWriteEnable
693                 VK_COMPARE_OP_LESS,                                                                                     //      VkCompareOp                                                             depthCompareOp
694                 VK_FALSE,                                                                                                       //      VkBool32                                                                depthBoundsTestEnable
695                 VK_FALSE,                                                                                                       //      VkBool32                                                                stencilTestEnable
696                 stencilOpState,                                                                                         //      VkStencilOpState                                                front
697                 stencilOpState,                                                                                         //      VkStencilOpState                                                back
698                 0.0f,                                                                                                           //      float                                                                   minDepthBounds
699                 1.0f,                                                                                                           //      float                                                                   maxDepthBounds
700         };
701
702         const VkBool32                                                                  colorWriteEnables                               = VK_FALSE;
703
704         const VkPipelineColorWriteCreateInfoEXT                 colorWriteCreateInfo                    =
705         {
706                 VK_STRUCTURE_TYPE_PIPELINE_COLOR_WRITE_CREATE_INFO_EXT, // VkStructureType      sType;
707                 DE_NULL,                                                                                                // const void*          pNext;
708                 1,                                                                                                              // deUint32                     attachmentCount;
709                 &colorWriteEnables                                                                              // const VkBool32*      pColorWriteEnables;
710         };
711
712         const VkPipelineColorBlendAttachmentState               colorBlendAttachmentState               =
713         {
714                 VK_FALSE,                                       // VkBool32                                     blendEnable
715                 VK_BLEND_FACTOR_ZERO,           // VkBlendFactor                        srcColorBlendFactor
716                 VK_BLEND_FACTOR_ZERO,           // VkBlendFactor                        dstColorBlendFactor
717                 VK_BLEND_OP_ADD,                        // VkBlendOp                            colorBlendOp
718                 VK_BLEND_FACTOR_ZERO,           // VkBlendFactor                        srcAlphaBlendFactor
719                 VK_BLEND_FACTOR_ZERO,           // VkBlendFactor                        dstAlphaBlendFactor
720                 VK_BLEND_OP_ADD,                        // VkBlendOp                            alphaBlendOp
721                 VK_COLOR_COMPONENT_R_BIT        // VkColorComponentFlags        colorWriteMask
722                 | VK_COLOR_COMPONENT_G_BIT
723                 | VK_COLOR_COMPONENT_B_BIT
724                 | VK_COLOR_COMPONENT_A_BIT
725         };
726
727         const VkPipelineColorBlendStateCreateInfo               colorBlendStateCreateInfo               =
728         {
729                 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,       // VkStructureType                                                              sType
730                 &colorWriteCreateInfo,                                                                          // const void*                                                                  pNext
731                 0,                                                                                                                      // VkPipelineColorBlendStateCreateFlags                 flags
732                 VK_FALSE,                                                                                                       // VkBool32                                                                             logicOpEnable
733                 VK_LOGIC_OP_NO_OP,                                                                                      // VkLogicOp                                                                    logicOp
734                 1,                                                                                                                      // deUint32                                                                             attachmentCount
735                 &colorBlendAttachmentState,                                                                     // const VkPipelineColorBlendAttachmentState*   pAttachments
736                 { 0.0f, 0.0f, 0.0f, 0.0f }                                                                      // float                                                                                blendConstants[4]
737         };
738
739         const VkDynamicState                                                    dynamicStates                                   = VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT;
740
741         const VkPipelineDynamicStateCreateInfo                  pipelineDynamicStateCreateInfo  =
742         {
743                 VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,   // VkStructureType                                              sType
744                 DE_NULL,                                                                                                // const void*                                                  pNext
745                 0u,                                                                                                             // VkPipelineDynamicStateCreateFlags    flags
746                 1u,                                                                                                             // deUint32                                                             dynamicStateCount
747                 &dynamicStates                                                                                  // const VkDynamicState*                                pDynamicStates
748         };
749
750         return vk::makeGraphicsPipeline(vk,
751                                                                         device,
752                                                                         *pipelineLayout,
753                                                                         *vertModule,
754                                                                         *tescModule,
755                                                                         *teseModule,
756                                                                         *geomModule,
757                                                                         *fragModule,
758                                                                         renderPass,
759                                                                         viewports,
760                                                                         scissors,
761                                                                         m_parameters.primitiveTopology,
762                                                                         subpass,
763                                                                         patchControlPoints,
764                                                                         &vertexInputStateCreateInfo,
765                                                                         &rasterizationStateCreateInfo,
766                                                                         DE_NULL,        // multisampleStateCreateInfo
767                                                                         m_parameters.depthStencilAttachment ? &depthStencilStateCreateInfo : DE_NULL,
768                                                                         m_parameters.staticColorWriteDisable() ? &colorBlendStateCreateInfo : DE_NULL,
769                                                                         m_parameters.dynamicColorWriteDisable() ? &pipelineDynamicStateCreateInfo : DE_NULL);
770 }
771
772 void PrimitivesGeneratedQueryTestInstance::fillVertexBuffer(tcu::Vec2* vertices, const deUint64 primitivesGenerated)
773 {
774         const float step = 1.0f / static_cast<float>(primitivesGenerated);
775
776         switch (m_parameters.primitiveTopology)
777         {
778                 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
779                 {
780                         for (deUint32 prim = 0; prim < primitivesGenerated; ++prim)
781                         {
782                                 vertices[prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 0.0f);
783                         }
784                         break;
785                 }
786                 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
787                 {
788                         for (deUint32 prim = 0; prim < primitivesGenerated; ++prim)
789                         {
790                                 vertices[2* prim + 0] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step,  1.0f);
791                                 vertices[2* prim + 1] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
792                         }
793                         break;
794                 }
795                 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
796                 {
797                         vertices[0] = tcu::Vec2(-1.0f,-1.0f);
798                         vertices[1] = tcu::Vec2(-1.0f, 1.0f);
799
800                         for (deUint32 prim = 1; prim < primitivesGenerated; ++prim)
801                         {
802                                 if (prim % 2 == 0)
803                                 {
804                                         vertices[2 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step,  1.0f);
805                                 }
806                                 else
807                                 {
808                                         vertices[2 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
809                                 }
810                         }
811                         break;
812                 }
813                 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
814                 {
815                         vertices[0] = tcu::Vec2(-1.0f,                           1.0f);
816                         vertices[1] = tcu::Vec2(-1.0f,                          -1.0f);
817                         vertices[2] = tcu::Vec2(-1.0f + 2.0f * step, 1.0f);
818
819                         for (deUint32 prim = 1; prim < primitivesGenerated; ++prim)
820                         {
821                                 if (prim % 2 == 0)
822                                 {
823                                         vertices[3 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 1.0f);
824                                 }
825                                 else
826                                 {
827                                         vertices[3 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
828                                 }
829                         }
830                         break;
831                 }
832                 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
833                 {
834                         vertices[0] = tcu::Vec2(0.0f, -1.0f);
835
836                         for (deUint32 prim = 0; prim < primitivesGenerated+1; ++prim)
837                         {
838                                 vertices[1 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f + 2.0f * (float)prim * step);
839                         }
840                         break;
841                 }
842                 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
843                 {
844                         for (deUint32 prim = 0; prim < primitivesGenerated; ++prim)
845                         {
846                                 vertices[4 * prim + 0] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step,  1.0f);
847                                 vertices[4 * prim + 1] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step,  0.5f);
848                                 vertices[4 * prim + 2] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -0.5f);
849                                 vertices[4 * prim + 3] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
850                         }
851                         break;
852                 }
853                 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
854                 {
855                         vertices[0] = tcu::Vec2(-1.0f,  0.0f);
856                         vertices[1] = tcu::Vec2(-1.0f, -1.0f);
857                         vertices[2] = tcu::Vec2(-1.0f,  1.0f);
858
859                         for (deUint32 prim = 1; prim < primitivesGenerated; ++prim)
860                         {
861                                 if (prim % 2 == 0)
862                                 {
863                                         vertices[3 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step,  1.0f);
864                                 }
865                                 else
866                                 {
867                                         vertices[3 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
868                                 }
869                         }
870
871                         vertices[3 + primitivesGenerated] = tcu::Vec2(1.0f, 0.0f);
872
873                         break;
874                 }
875                 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
876                 case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
877                 {
878                         for (deUint32 prim = 0; prim < primitivesGenerated; ++prim)
879                         {
880                                 if (prim % 2 == 0)
881                                 {
882                                         vertices[3 * prim + 0] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step,  1.0f);
883                                         vertices[3 * prim + 1] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, -1.0f);
884                                         vertices[3 * prim + 2] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, -1.0f);
885                                 }
886                                 else
887                                 {
888                                         vertices[3 * prim + 0] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, -1.0f);
889                                         vertices[3 * prim + 1] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step,  1.0f);
890                                         vertices[3 * prim + 2] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step,  1.0f);
891                                 }
892                         }
893                         break;
894                 }
895                 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
896                 {
897                         for (deUint32 prim = 0; prim < primitivesGenerated; ++prim)
898                         {
899                                 if (prim % 2 == 0)
900                                 {
901                                         vertices[6 * prim + 0] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step,  1.0f);
902                                         vertices[6 * prim + 1] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step,  1.0f);
903                                         vertices[6 * prim + 2] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, -1.0f);
904                                         vertices[6 * prim + 3] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, -1.0f);
905                                         vertices[6 * prim + 4] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, -1.0f);
906                                         vertices[6 * prim + 5] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, -1.0f);
907                                 }
908                                 else
909                                 {
910                                         vertices[6 * prim + 0] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, -1.0f);
911                                         vertices[6 * prim + 1] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, -1.0f);
912                                         vertices[6 * prim + 2] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step,  1.0f);
913                                         vertices[6 * prim + 3] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step,  1.0f);
914                                         vertices[6 * prim + 4] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step,  1.0f);
915                                         vertices[6 * prim + 5] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step,  1.0f);
916                                 }
917                         }
918                         break;
919                 }
920                 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
921                 {
922                         vertices[0] = tcu::Vec2(-1.0f,  1.0f);
923                         vertices[1] = tcu::Vec2(-1.0f,  1.0f);
924                         vertices[2] = tcu::Vec2(-1.0f, -1.0f);
925                         vertices[3] = tcu::Vec2(-1.0f, -1.0f);
926                         vertices[4] = tcu::Vec2(-1.0f + 2.0f * step, 1.0f);
927                         vertices[5] = tcu::Vec2(-1.0f + 2.0f * step, 1.0f);
928
929                         for (deUint32 prim = 1; prim < primitivesGenerated; ++prim)
930                         {
931                                 if (prim % 2 == 0)
932                                 {
933                                         vertices[6 + prim + 0] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 1.0f);
934                                         vertices[6 + prim + 1] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 1.0f);
935                                 }
936                                 else
937                                 {
938                                         vertices[6 + prim + 0] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
939                                         vertices[6 + prim + 1] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
940                                 }
941                         }
942                         break;
943                 }
944                 default:
945                         TCU_THROW(InternalError, "Unrecognized primitive topology");
946         }
947 }
948
949 class PrimitivesGeneratedQueryTestCase : public vkt::TestCase
950 {
951 public:
952                                                         PrimitivesGeneratedQueryTestCase        (tcu::TestContext &context, const char *name, const char *description, const TestParameters& parameters)
953                                                                 : TestCase              (context, name, description)
954                                                                 , m_parameters  (parameters)
955                                                         {
956                                                         }
957
958 private:
959         void                                    checkSupport                                            (vkt::Context& context) const;
960         void                                    initPrograms                                            (vk::SourceCollections& programCollection) const;
961         vkt::TestInstance*              createInstance                                          (vkt::Context& context) const { return new PrimitivesGeneratedQueryTestInstance(context, m_parameters); }
962
963         const TestParameters    m_parameters;
964 };
965
966 void PrimitivesGeneratedQueryTestCase::checkSupport (vkt::Context& context) const
967 {
968         context.requireDeviceFunctionality("VK_EXT_primitives_generated_query");
969         context.requireDeviceFunctionality("VK_EXT_transform_feedback");
970
971         const VkPhysicalDevicePrimitivesGeneratedQueryFeaturesEXT&      pgqFeatures             = context.getPrimitivesGeneratedQueryFeaturesEXT();
972         const VkPhysicalDeviceTransformFeedbackFeaturesEXT&                     xfbFeatures             = context.getTransformFeedbackFeaturesEXT();
973         const VkPhysicalDeviceTransformFeedbackPropertiesEXT&           xfbProperties   = context.getTransformFeedbackPropertiesEXT();
974
975         if (pgqFeatures.primitivesGeneratedQuery != VK_TRUE)
976                 TCU_THROW(NotSupportedError, "VK_QUERY_TYPE_PRIMITIVES_GENERATED_EXT not supported");
977
978         if (m_parameters.rastDiscard() && (pgqFeatures.primitivesGeneratedQueryWithRasterizerDiscard != VK_TRUE))
979                 TCU_THROW(NotSupportedError, "primitivesGeneratedQueryWithRasterizerDiscard not supported");
980
981         if (m_parameters.queryResetType == QUERY_RESET_TYPE_HOST)
982                 context.requireDeviceFunctionality("VK_EXT_host_query_reset");
983
984         if (m_parameters.shaderStage == SHADER_STAGE_GEOMETRY || topologyData.at(m_parameters.primitiveTopology).hasAdjacency)
985                 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
986
987         if (m_parameters.shaderStage == SHADER_STAGE_TESSELLATION_EVALUATION)
988                 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
989
990         if (m_parameters.nonZeroStreams())
991         {
992                 const deUint32 requiredStreams  = de::max(m_parameters.pgqStreamIndex(), m_parameters.xfbStreamIndex());
993
994                 if (m_parameters.pgqStreamIndex() > 0 && pgqFeatures.primitivesGeneratedQueryWithNonZeroStreams != VK_TRUE)
995                         TCU_THROW(NotSupportedError, "primitivesGeneratedQueryWithNonZeroStreams not supported");
996
997                 if (xfbProperties.maxTransformFeedbackStreams <= requiredStreams)
998                         TCU_THROW(NotSupportedError, "Required amount of XFB streams not supported");
999         }
1000
1001         if (m_parameters.transformFeedback)
1002         {
1003                 if (xfbFeatures.transformFeedback != VK_TRUE)
1004                         TCU_THROW(NotSupportedError, "transformFeedback not supported");
1005
1006                 if (xfbProperties.transformFeedbackQueries != VK_TRUE)
1007                         TCU_THROW(NotSupportedError, "transformFeedbackQueries not supported");
1008         }
1009
1010         if (m_parameters.colorWriteDisable())
1011         {
1012                 context.requireDeviceFunctionality("VK_EXT_color_write_enable");
1013
1014                 if (context.getColorWriteEnableFeaturesEXT().colorWriteEnable != VK_TRUE)
1015                         TCU_THROW(NotSupportedError, "colorWriteEnable not supported");
1016         }
1017 }
1018
1019 void PrimitivesGeneratedQueryTestCase::initPrograms (vk::SourceCollections& programCollection) const
1020 {
1021         // Vertex shader.
1022         {
1023                 const bool                      vertXfb = (m_parameters.transformFeedback && m_parameters.shaderStage == SHADER_STAGE_VERTEX);
1024                 std::ostringstream      src;
1025
1026                 src     <<      "#version 450\n";
1027                 src << "layout(location=0) in vec2 inPosition;\n";
1028
1029                 if (vertXfb)
1030                         src     <<      "layout(xfb_buffer = 0, xfb_offset = 0, xfb_stride = 16, location = 0) out vec4 out0;\n";
1031
1032                 src     <<      "void main (void)\n"
1033                                 "{\n";
1034
1035                 if (m_parameters.primitiveTopology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST && m_parameters.shaderStage == SHADER_STAGE_VERTEX)
1036                         src     <<      "    gl_PointSize = 1.0;\n";
1037
1038                 src << "         gl_Position = vec4(inPosition, 0, 1);\n";
1039
1040                 if (vertXfb)
1041                         src     <<      "    out0 = vec4(42);\n";
1042
1043                 src << "    gl_Position = vec4(1.0f);\n";
1044                 src     <<      "}\n";
1045
1046                 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
1047         }
1048
1049         // Tessellation shaders.
1050         if (m_parameters.shaderStage == SHADER_STAGE_TESSELLATION_EVALUATION)
1051         {
1052                 std::stringstream       tescSrc;
1053                 std::stringstream       teseSrc;
1054
1055                 tescSrc <<      "#version 450\n"
1056                                         "#extension GL_EXT_tessellation_shader : require\n"
1057                                         "layout(vertices = "<< topologyData.at(VK_PRIMITIVE_TOPOLOGY_PATCH_LIST).primitiveSize << ") out;\n"
1058                                         "void main (void)\n"
1059                                         "{\n"
1060                                         "    gl_TessLevelInner[0] = 1.0;\n"
1061                                         "    gl_TessLevelInner[1] = 1.0;\n"
1062                                         "    gl_TessLevelOuter[0] = 1.0;\n"
1063                                         "    gl_TessLevelOuter[1] = 1.0;\n"
1064                                         "    gl_TessLevelOuter[2] = 1.0;\n"
1065                                         "    gl_TessLevelOuter[3] = 1.0;\n"
1066                                         "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1067                                         "}\n";
1068
1069                 teseSrc <<      "#version 450\n"
1070                                         "#extension GL_EXT_tessellation_shader : require\n"
1071                                         "layout(triangles) in;\n";
1072
1073                 if (m_parameters.transformFeedback)
1074                         teseSrc <<      "layout(xfb_buffer = 0, xfb_offset = 0, location = 0) out vec4 out0;\n";
1075
1076                 teseSrc <<      "void main (void)\n"
1077                                         "{\n";
1078
1079                 if (m_parameters.transformFeedback)
1080                         teseSrc <<      "    out0 = vec4(42);\n";
1081
1082                 teseSrc <<      "    vec4 p0 = gl_TessCoord.x * gl_in[0].gl_Position;\n"
1083                                         "    vec4 p1 = gl_TessCoord.y * gl_in[1].gl_Position;\n"
1084                                         "    vec4 p2 = gl_TessCoord.z * gl_in[2].gl_Position;\n"
1085                                         "    gl_Position = p0 + p1 + p2;\n"
1086                                         "}\n";
1087
1088                 programCollection.glslSources.add("tesc") << glu::TessellationControlSource(tescSrc.str());
1089                 programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(teseSrc.str());
1090         }
1091
1092         // Geometry shader.
1093         if (m_parameters.shaderStage == SHADER_STAGE_GEOMETRY)
1094         {
1095                 const bool                      outputPoints    = m_parameters.nonZeroStreams() || m_parameters.primitiveTopology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
1096                 const char* const       inputTopology   = topologyData.at(m_parameters.primitiveTopology).inputString;
1097                 const char* const       outputTopology  = outputPoints ? "points" : topologyData.at(m_parameters.primitiveTopology).outputString;
1098                 const VkDeviceSize      outputPrimSize  = outputPoints ? 1 : topologyData.at(m_parameters.primitiveTopology).primitiveSize;
1099                 const VkDeviceSize      maxVertices             = m_parameters.multipleStreams() ? outputPrimSize * 2 : outputPrimSize;
1100                 const std::string       pgqEmitCommand  = m_parameters.nonZeroStreams() ? std::string("EmitStreamVertex(") + de::toString(m_parameters.pgqStreamIndex()) + ")" : "EmitVertex()";
1101                 const std::string       xfbEmitCommand  = m_parameters.nonZeroStreams() ? std::string("EmitStreamVertex(") + de::toString(m_parameters.xfbStreamIndex()) + ")" : "EmitVertex()";
1102                 const std::string       pgqEndCommand   = m_parameters.nonZeroStreams() ? std::string("EndStreamPrimitive(") + de::toString(m_parameters.pgqStreamIndex()) + ")" : "EndPrimitive()";
1103                 const std::string       xfbEndCommand   = m_parameters.nonZeroStreams() ? std::string("EndStreamPrimitive(") + de::toString(m_parameters.xfbStreamIndex()) + ")" : "EndPrimitive()";
1104                 std::ostringstream      src;
1105
1106                 src     <<      "#version 450\n"
1107                                 "layout(" << inputTopology << ") in;\n"
1108                                 "layout(" << outputTopology << ", max_vertices = " << maxVertices << ") out;\n";
1109
1110                 if (m_parameters.transformFeedback)
1111                         src     <<      "layout(xfb_buffer = 0, xfb_offset = 0, xfb_stride = 16, location = 0, stream = " << m_parameters.xfbStreamIndex() << ") out vec4 xfb;\n";
1112
1113                 src     <<      "void main (void)\n"
1114                                 "{\n";
1115
1116                 if (outputPoints)
1117                         src     <<      "    gl_PointSize = 1.0;\n";
1118
1119                 if (m_parameters.transformFeedback)
1120                         src     <<      "    xfb = vec4(42);\n";
1121
1122                 for (VkDeviceSize i = 0; i < outputPrimSize; i++)
1123                         src     <<      "    " << pgqEmitCommand << ";\n";
1124
1125                 src     <<      "    " << pgqEndCommand << ";\n";
1126
1127                 if (m_parameters.transformFeedback && m_parameters.multipleStreams())
1128                 {
1129                         for (VkDeviceSize i = 0; i < outputPrimSize; i++)
1130                                 src     <<      "    " << xfbEmitCommand << ";\n";
1131
1132                         src     <<      "    " << xfbEndCommand << ";\n";
1133                 }
1134
1135                 src     <<      "}\n";
1136
1137                 programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
1138         }
1139
1140         // Fragment shader.
1141         if (!m_parameters.rastDiscard())
1142         {
1143                 std::ostringstream src;
1144
1145                 if (m_parameters.rastCase == RAST_CASE_EMPTY_FRAG)
1146                 {
1147                         src     <<      "#version 450\n"
1148                                         "void main (void) {}\n";
1149                 }
1150                 else
1151                 {
1152                         src     <<      "#version 450\n"
1153                                         "layout(location = 0) out vec4 out0;\n"
1154                                         "void main (void)\n"
1155                                         "{\n"
1156                                         "    out0 = vec4(0.0, 1.0, 0.0, 1.0);\n"
1157                                         "}\n";
1158                 }
1159
1160                 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1161         }
1162 }
1163
1164 void testGenerator (tcu::TestCaseGroup* pgqGroup)
1165 {
1166         constexpr struct ReadType
1167         {
1168                 QueryReadType   type;
1169                 const char*             name;
1170                 const char*             desc;
1171         } readTypes[] =
1172         {
1173                 { QUERY_READ_TYPE_GET,  "get",  "Tests for vkGetQueryPoolResults"               },
1174                 { QUERY_READ_TYPE_COPY, "copy", "Tests for vkCmdCopyQueryPoolResults"   },
1175         };
1176         DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(readTypes) == QUERY_READ_TYPE_LAST);
1177
1178         constexpr struct ResetType
1179         {
1180                 QueryResetType  type;
1181                 const char*             name;
1182                 const char*             desc;
1183         } resetTypes[] =
1184         {
1185                 { QUERY_RESET_TYPE_QUEUE,       "queue_reset",  "Tests for vkCmdResetQueryPool" },
1186                 { QUERY_RESET_TYPE_HOST,        "host_reset",   "Tests for vkResetQueryPool"    },
1187         };
1188         DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(resetTypes) == QUERY_RESET_TYPE_LAST);
1189
1190         constexpr struct ResultTypes
1191         {
1192                 QueryResultType type;
1193                 const char*             name;
1194                 const char*             desc;
1195         } resultTypes[] =
1196         {
1197                 { QUERY_RESULT_TYPE_32_BIT,                     "32bit",                                "Tests for default query result size"                                                   },
1198                 { QUERY_RESULT_TYPE_64_BIT,                     "64bit",                                "Tests for VK_QUERY_RESULT_64_BIT"                                                              },
1199                 { QUERY_RESULT_TYPE_PGQ_32_XFB_64,      "pgq_32bit_xfb_64bit",  "Tests for PGQ without and XFBQ with VK_QUERY_RESULT_64_BIT"    },
1200                 { QUERY_RESULT_TYPE_PGQ_64_XFB_32,      "pgq_64bit_xfb_32bit",  "Tests for PGQ with and XFBQ without VK_QUERY_RESULT_64_BIT"    },
1201         };
1202         DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(resultTypes) == QUERY_RESULT_TYPE_LAST);
1203
1204         constexpr struct Shader
1205         {
1206                 ShaderStage     stage;
1207                 const char*     name;
1208                 const char*     desc;
1209         } shaderStages[] =
1210         {
1211                 { SHADER_STAGE_VERTEX,                                  "vert", "Vertex shader tests"                                   },
1212                 { SHADER_STAGE_TESSELLATION_EVALUATION, "tese", "Tessellation evaluation shader tests"  },
1213                 { SHADER_STAGE_GEOMETRY,                                "geom", "Geometry shader tests"                                 },
1214         };
1215         DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(shaderStages) == SHADER_STAGE_LAST);
1216
1217         constexpr struct TransformFeedbackState
1218         {
1219                 deBool          enable;
1220                 const char*     name;
1221                 const char*     desc;
1222         } transformFeedbackStates[] =
1223         {
1224                 { DE_FALSE,     "no_xfb",       "Tests without transform feedback"                                                                                      },
1225                 { DE_TRUE,      "xfb",          "Tests for comparing PGQ results against transform feedback query results"      },
1226         };
1227
1228         constexpr struct RastCase
1229         {
1230                 RasterizationCase       type;
1231                 deBool                          dsAttachment;
1232                 const char*                     name;
1233                 const char*                     desc;
1234         } rastCases[] =
1235         {
1236                 { RAST_CASE_DISCARD,                                            DE_FALSE,       "no_rast",                                                      "Tests with rasterizer discard"                                                                                                                                                 },
1237                 { RAST_CASE_DEFAULT,                                            DE_FALSE,       "rast",                                                         "Tests without rasterizer discard"                                                                                                                                              },
1238                 { RAST_CASE_EMPTY_FRAG,                                         DE_FALSE,       "empty_frag",                                           "Tests with an empty fragment shader"                                                                                                                                   },
1239                 { RAST_CASE_NO_ATTACHMENT,                                      DE_FALSE,       "no_attachment",                                        "Tests with an attachmentless render pass"                                                                                                                              },
1240                 { RAST_CASE_COLOR_WRITE_DISABLE_STATIC,         DE_FALSE,       "color_write_disable_static",           "Tests disabling color output using VkPipelineColorWriteCreateInfoEXT"                                                                  },
1241                 { RAST_CASE_COLOR_WRITE_DISABLE_STATIC,         DE_TRUE,        "color_write_disable_static_ds",        "Tests disabling color output using VkPipelineColorWriteCreateInfoEXT with a depth stencil attachment"  },
1242                 { RAST_CASE_COLOR_WRITE_DISABLE_DYNAMIC,        DE_FALSE,       "color_write_disable_dynamic",          "Tests disabling color output using vkCmdSetColorWriteEnableEXT"                                                                                },
1243                 { RAST_CASE_COLOR_WRITE_DISABLE_DYNAMIC,        DE_TRUE,        "color_write_disable_dynamic_ds",       "Tests disabling color output using vkCmdSetColorWriteEnableEXT with a depth stencil attachment"                },
1244         };
1245
1246         constexpr struct Topology
1247         {
1248                 VkPrimitiveTopology     type;
1249                 const char*                     name;
1250                 const char*                     desc;
1251         } topologies[] =
1252         {
1253                 { VK_PRIMITIVE_TOPOLOGY_POINT_LIST,                                             "point_list",                                           "Tests for separate point primitives"                                                                                                                                           },
1254                 { VK_PRIMITIVE_TOPOLOGY_LINE_LIST,                                              "line_list",                                            "Tests for separate line primitives"                                                                                                                                            },
1255                 { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,                                             "line_strip",                                           "Tests for connected line primitives with consecutive lines sharing a vertex"                                                           },
1256                 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,                                  "triangle_list",                                        "Tests for separate triangle primitives"                                                                                                                                        },
1257                 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,                                 "triangle_strip",                                       "Tests for connected triangle primitives with consecutive triangles sharing an edge"                                            },
1258                 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,                                   "triangle_fan",                                         "Tests for connected triangle primitives with all triangles sharing a common vertex"                                            },
1259                 { VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY,               "line_list_with_adjacency",                     "Tests for separate line primitives with adjacency"                                                                                                                     },
1260                 { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY,              "line_strip_with_adjacency",            "Tests for connected line primitives with adjacency, with consecutive primitives sharing three vertices"        },
1261                 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY,   "triangle_list_with_adjacency",         "Tests for separate triangle primitives with adjacency"                                                                                                         },
1262                 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY,  "triangle_strip_with_adjacency",        "Tests for connected triangle primitives with adjacency, with consecutive triangles sharing an edge"            },
1263                 { VK_PRIMITIVE_TOPOLOGY_PATCH_LIST,                                             "patch_list",                                           "Tests for separate patch primitives"                                                                                                                                           },
1264         };
1265
1266         // Tests for vkCmdBeginQueryIndexedEXT and vkCmdEndQueryIndexedEXT.
1267         constexpr struct StreamIndex
1268         {
1269                 VertexStream    index;
1270                 const char*             name;
1271         } streamIndices[] =
1272         {
1273                 { VERTEX_STREAM_DEFAULT,        "default"       },
1274                 { VERTEX_STREAM_0,                      "0"                     },
1275                 { VERTEX_STREAM_1,                      "1"                     },
1276         };
1277
1278         constexpr struct CmdBufCase
1279         {
1280                 CommandBufferCase       type;
1281                 const char*                     name;
1282                 const char*                     desc;
1283         } cmdBufCases[] =
1284         {
1285                 { CMD_BUF_CASE_SINGLE_DRAW,     "single_draw",  "Test single draw call" },
1286         };
1287         DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(cmdBufCases) == CMD_BUF_CASE_LAST);
1288
1289         tcu::TestContext& testCtx = pgqGroup->getTestContext();
1290
1291         for (const ReadType& read : readTypes)
1292         {
1293                 tcu::TestCaseGroup* const readGroup = new tcu::TestCaseGroup(testCtx, read.name, read.desc);
1294
1295                 for (const ResetType& reset : resetTypes)
1296                 {
1297                         tcu::TestCaseGroup* const resetGroup = new tcu::TestCaseGroup(testCtx, reset.name, reset.desc);
1298
1299                         for (const ResultTypes& result : resultTypes)
1300                         {
1301                                 tcu::TestCaseGroup* const resultGroup = new tcu::TestCaseGroup(testCtx, result.name, result.desc);
1302
1303                                 for (const Shader& shader : shaderStages)
1304                                 {
1305                                         tcu::TestCaseGroup* const shaderGroup = new tcu::TestCaseGroup(testCtx, shader.name, shader.desc);
1306
1307                                         for (const TransformFeedbackState& xfbState : transformFeedbackStates)
1308                                         {
1309                                                 tcu::TestCaseGroup* const xfbGroup = new tcu::TestCaseGroup(testCtx, xfbState.name, xfbState.desc);
1310
1311                                                 // Only test multiple result types with XFB enabled.
1312                                                 if ((result.type == QUERY_RESULT_TYPE_PGQ_32_XFB_64 || result.type == QUERY_RESULT_TYPE_PGQ_64_XFB_32) && !xfbState.enable)
1313                                                         continue;
1314
1315                                                 for (const RastCase& rastCase : rastCases)
1316                                                 {
1317                                                         tcu::TestCaseGroup* const rastGroup = new tcu::TestCaseGroup(testCtx, rastCase.name, rastCase.desc);
1318
1319                                                         // Skip uninteresting cases
1320                                                         if ((rastCase.type > RAST_CASE_DISCARD)
1321                                                                 && ((read.type != QUERY_READ_TYPE_GET)
1322                                                                 || (reset.type != QUERY_RESET_TYPE_QUEUE)
1323                                                                 || (result.type != QUERY_RESULT_TYPE_32_BIT)))
1324                                                         {
1325                                                                 continue;
1326                                                         }
1327
1328                                                         for (const Topology& topology : topologies)
1329                                                         {
1330                                                                 tcu::TestCaseGroup* const topologyGroup = new tcu::TestCaseGroup(testCtx, topology.name, topology.desc);
1331
1332                                                                 // Only test patch lists with tessellation shaders.
1333                                                                 if ((topology.type == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST && shader.stage != SHADER_STAGE_TESSELLATION_EVALUATION) ||
1334                                                                    ((topology.type != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST && shader.stage == SHADER_STAGE_TESSELLATION_EVALUATION)))
1335                                                                 {
1336                                                                         continue;
1337                                                                 }
1338
1339                                                                 // Only test adjacency topologies with geometry shaders.
1340                                                                 if (shader.stage != SHADER_STAGE_GEOMETRY && topologyData.at(topology.type).hasAdjacency)
1341                                                                         continue;
1342
1343                                                                 for (const StreamIndex& pgqStream : streamIndices)
1344                                                                 {
1345                                                                         for (const StreamIndex& xfbStream : streamIndices)
1346                                                                         {
1347                                                                                 const std::string                       streamGroupName = std::string("pgq_") + pgqStream.name + (xfbState.enable ? std::string("_xfb_") + xfbStream.name : "");
1348                                                                                 const bool                                      pgqDefault              = (pgqStream.index == VERTEX_STREAM_DEFAULT);
1349                                                                                 const bool                                      xfbDefault              = (xfbStream.index == VERTEX_STREAM_DEFAULT);
1350                                                                                 const std::string                       pgqDescStr              = std::string("PGQ on ") + (pgqDefault ? "default " : "") + std::string("vertex stream ") + (pgqDefault ? "" : pgqStream.name);
1351                                                                                 const std::string                       xfbDescStr              = std::string("XFB on ") + (xfbDefault ? "default " : "") + std::string("vertex stream ") + (xfbDefault ? "" : xfbStream.name);
1352                                                                                 const std::string                       streamGroupDesc = std::string("Tests for ") + pgqDescStr + (xfbState.enable ? (std::string(" and ") + xfbDescStr) : "");
1353                                                                                 tcu::TestCaseGroup* const       streamGroup             = new tcu::TestCaseGroup(testCtx, streamGroupName.c_str(), streamGroupDesc.c_str());
1354
1355                                                                                 // Only test nondefault vertex streams with geometry shaders.
1356                                                                                 if ((pgqStream.index != VERTEX_STREAM_DEFAULT || xfbStream.index != VERTEX_STREAM_DEFAULT) && shader.stage != SHADER_STAGE_GEOMETRY)
1357                                                                                         continue;
1358
1359                                                                                 // Skip nondefault vertex streams for XFB when not enabled.
1360                                                                                 if (!xfbState.enable && xfbStream.index != VERTEX_STREAM_DEFAULT)
1361                                                                                         continue;
1362
1363                                                                                 for (const CmdBufCase& cmdBufCase : cmdBufCases)
1364                                                                                 {
1365                                                                                         const TestParameters    parameters      =
1366                                                                                         {
1367                                                                                                 read.type,                              // QueryReadType                queryReadType
1368                                                                                                 reset.type,                             // QueryResetType               queryResetType
1369                                                                                                 result.type,                    // QueryResultType              queryResultType
1370                                                                                                 shader.stage,                   // ShaderStage                  shaderStage
1371                                                                                                 xfbState.enable,                // deBool                               transformFeedback
1372                                                                                                 rastCase.type,                  // RasterizationCase    rastCase
1373                                                                                                 rastCase.dsAttachment,  // deBool                               depthStencilAttachment
1374                                                                                                 topology.type,                  // VkPrimitiveTopology  primitiveTopology
1375                                                                                                 pgqStream.index,                // VertexStreamIndex    pgqStreamIndex
1376                                                                                                 xfbStream.index,                // VertexStreamIndex    xfbStreamIndex
1377                                                                                                 cmdBufCase.type,                // CommandBufferCase    cmdBufCase
1378                                                                                         };
1379
1380                                                                                         streamGroup->addChild(new PrimitivesGeneratedQueryTestCase(testCtx, cmdBufCase.name, cmdBufCase.desc, parameters));
1381                                                                                 }
1382
1383                                                                                 topologyGroup->addChild(streamGroup);
1384                                                                         }
1385                                                                 }
1386
1387                                                                 rastGroup->addChild(topologyGroup);
1388                                                         }
1389
1390                                                         xfbGroup->addChild(rastGroup);
1391                                                 }
1392
1393                                                 shaderGroup->addChild(xfbGroup);
1394                                         }
1395
1396                                         resultGroup->addChild(shaderGroup);
1397                                 }
1398
1399                                 resetGroup->addChild(resultGroup);
1400                         }
1401
1402                         readGroup->addChild(resetGroup);
1403                 }
1404
1405                 pgqGroup->addChild(readGroup);
1406         }
1407 }
1408
1409 } // anonymous
1410
1411 tcu::TestCaseGroup* createPrimitivesGeneratedQueryTests (tcu::TestContext& testCtx)
1412 {
1413         return createTestGroup(testCtx, "primitives_generated_query", "Primitives Generated Query Tests", testGenerator);
1414 }
1415
1416 } // TransformFeedback
1417 } // vkt