Test behaviour of color write enable with colorWriteMask
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / transform_feedback / vktTransformFeedbackSimpleTests.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2018 The Khronos Group Inc.
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 Vulkan Transform Feedback Simple Tests
22  *//*--------------------------------------------------------------------*/
23
24 #include "vktTransformFeedbackSimpleTests.hpp"
25 #include "vktTestGroupUtil.hpp"
26 #include "vktTestCase.hpp"
27
28 #include "vkBuilderUtil.hpp"
29 #include "vkCmdUtil.hpp"
30 #include "vkImageUtil.hpp"
31 #include "vkObjUtil.hpp"
32 #include "vkQueryUtil.hpp"
33 #include "vkRefUtil.hpp"
34 #include "vkTypeUtil.hpp"
35
36 #include "deUniquePtr.hpp"
37 #include "deRandom.hpp"
38
39 #include "tcuTextureUtil.hpp"
40 #include "tcuVectorUtil.hpp"
41 #include "tcuImageCompare.hpp"
42 #include "tcuRGBA.hpp"
43 #include "tcuTestLog.hpp"
44
45 #include <iostream>
46 #include <functional>
47 #include <set>
48 #include <algorithm>
49
50 namespace vkt
51 {
52 namespace TransformFeedback
53 {
54 namespace
55 {
56 using namespace vk;
57 using de::MovePtr;
58 using de::UniquePtr;
59 using de::SharedPtr;
60
61 #define VALIDATE_MINIMUM(A,B) if ((A) < (B)) TCU_FAIL(#A "==" + de::toString(A) + " which is less than required by specification (" + de::toString(B) + ")")
62 #define VALIDATE_BOOL(A) if (! ( (A) == VK_TRUE || (A) == VK_FALSE) ) TCU_FAIL(#A " expected to be VK_TRUE or VK_FALSE. Received " + de::toString((deUint64)(A)))
63
64 enum TestType
65 {
66         TEST_TYPE_BASIC,
67         TEST_TYPE_RESUME,
68         TEST_TYPE_STREAMS,
69         TEST_TYPE_XFB_POINTSIZE,
70         TEST_TYPE_XFB_CLIPDISTANCE,
71         TEST_TYPE_XFB_CULLDISTANCE,
72         TEST_TYPE_XFB_CLIP_AND_CULL,
73         TEST_TYPE_WINDING,
74         TEST_TYPE_STREAMS_POINTSIZE,
75         TEST_TYPE_STREAMS_CLIPDISTANCE,
76         TEST_TYPE_STREAMS_CULLDISTANCE,
77         TEST_TYPE_MULTISTREAMS,
78         TEST_TYPE_DRAW_INDIRECT,
79         TEST_TYPE_BACKWARD_DEPENDENCY,
80         TEST_TYPE_QUERY_GET,
81         TEST_TYPE_QUERY_COPY,
82         TEST_TYPE_QUERY_RESET,
83         TEST_TYPE_MULTIQUERY,
84         TEST_TYPE_LAST
85 };
86
87 enum StreamId0Mode
88 {
89         STREAM_ID_0_NORMAL                                      = 0,
90         STREAM_ID_0_BEGIN_QUERY_INDEXED         = 1,
91         STREAM_ID_0_END_QUERY_INDEXED           = 2,
92 };
93
94 struct TestParameters
95 {
96         TestType                        testType;
97         deUint32                        bufferSize;
98         deUint32                        partCount;
99         deUint32                        streamId;
100         deUint32                        pointSize;
101         deUint32                        vertexStride;
102         StreamId0Mode           streamId0Mode;
103         bool                            query64bits;
104         bool                            noOffsetArray;
105         VkPrimitiveTopology     primTopology;
106 };
107
108 struct TopologyInfo
109 {
110         deUint32                                                        primSize;                       // The size of the on primitive.
111         std::string                                                     topologyName;           // The suffix for the name of test.
112         std::function<deUint64(deUint64)>       getNumPrimitives;       // The number of primitives generated.
113         std::function<deUint64(deUint64)>       getNumVertices;         // The number of vertices generated.
114 };
115
116 const std::map<VkPrimitiveTopology, TopologyInfo> topologyData =
117 {
118         { VK_PRIMITIVE_TOPOLOGY_POINT_LIST                                              , { 1, ""                                                               ,[](deUint64 vertexCount)       {       return vertexCount;                             }       ,[](deUint64 primCount) {       return primCount;                       }, } },
119         { VK_PRIMITIVE_TOPOLOGY_LINE_LIST                                               , { 2, "line_list_"                                             ,[](deUint64 vertexCount)       {       return vertexCount / 2u;                }       ,[](deUint64 primCount) {       return primCount * 2u;          }, } },
120         { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP                                              , { 2, "line_strip_"                                    ,[](deUint64 vertexCount)       {       return vertexCount - 1u;                }       ,[](deUint64 primCount) {       return primCount + 1u;          }, } },
121         { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST                                   , { 3, "triangle_list_"                                 ,[](deUint64 vertexCount)       {       return vertexCount / 3u;                }       ,[](deUint64 primCount) {       return primCount * 3u;          }, } },
122         { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP                                  , { 3, "triangle_strip_"                                ,[](deUint64 vertexCount)       {       return vertexCount - 2u;                }       ,[](deUint64 primCount) {       return primCount + 2u;          }, } },
123         { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN                                    , { 3, "triangle_fan_"                                  ,[](deUint64 vertexCount)       {       return vertexCount - 2u;                }       ,[](deUint64 primCount) {       return primCount + 2u;          }, } },
124         { VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY                , { 2, "line_list_with_adjacency_"              ,[](deUint64 vertexCount)       {       return vertexCount / 4u;                }       ,[](deUint64 primCount) {       return primCount * 4u;          }, } },
125         { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY               , { 2, "line_strip_with_adjacency_"             ,[](deUint64 vertexCount)       {       return vertexCount - 3u;                }       ,[](deUint64 primCount) {       return primCount + 3u;          }, } },
126         { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY    , { 3, "triangle_list_with_adjacency_"  ,[](deUint64 vertexCount)       {       return vertexCount / 6u;                }       ,[](deUint64 primCount) {       return primCount * 6u;          }, } },
127         { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY   , { 3, "triangle_strip_with_adjacency_" ,[](deUint64 vertexCount)       {       return (vertexCount - 4u) / 2u; }       ,[](deUint64 primCount) {       return primCount * 2u + 4u;     }, } },
128         { VK_PRIMITIVE_TOPOLOGY_PATCH_LIST                                              , { 3, "patch_list_"                                    ,[](deUint64 vertexCount)       {       return vertexCount / 3u;                }       ,[](deUint64 primCount) {       return primCount * 3u;          }, } },
129 };
130
131 struct TransformFeedbackQuery
132 {
133         deUint32        written;
134         deUint32        attempts;
135 };
136
137 const deUint32 MINIMUM_TF_BUFFER_SIZE   = (1<<27);
138 const deUint32 IMAGE_SIZE                               = 64u;
139
140 template<typename T>
141 inline SharedPtr<Unique<T> > makeSharedPtr(Move<T> move)
142 {
143         return SharedPtr<Unique<T> >(new Unique<T>(move));
144 }
145
146 Move<VkPipelineLayout> makePipelineLayout (const DeviceInterface&               vk,
147                                                                                    const VkDevice                               device)
148 {
149         const VkPushConstantRange                       pushConstantRanges                      =
150         {
151                 VK_SHADER_STAGE_VERTEX_BIT,                                             //  VkShaderStageFlags                          stageFlags;
152                 0u,                                                                                             //  deUint32                                            offset;
153                 sizeof(deUint32)                                                                //  deUint32                                            size;
154         };
155         const VkPipelineLayoutCreateInfo        pipelineLayoutCreateInfo        =
156         {
157                 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,  //  VkStructureType                                     sType;
158                 DE_NULL,                                                                                //  const void*                                         pNext;
159                 (VkPipelineLayoutCreateFlags)0,                                 //  VkPipelineLayoutCreateFlags         flags;
160                 0u,                                                                                             //  deUint32                                            setLayoutCount;
161                 DE_NULL,                                                                                //  const VkDescriptorSetLayout*        pSetLayouts;
162                 1u,                                                                                             //  deUint32                                            pushConstantRangeCount;
163                 &pushConstantRanges,                                                    //  const VkPushConstantRange*          pPushConstantRanges;
164         };
165         return createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
166 }
167
168 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface&           vk,
169                                                                            const VkDevice                               device,
170                                                                            const VkPipelineLayout               pipelineLayout,
171                                                                            const VkRenderPass                   renderPass,
172                                                                            const VkShaderModule                 vertexModule,
173                                                                            const VkShaderModule                 tessellationControlModule,
174                                                                            const VkShaderModule                 tessellationEvalModule,
175                                                                            const VkShaderModule                 geometryModule,
176                                                                            const VkShaderModule                 fragmendModule,
177                                                                            const VkExtent2D                             renderSize,
178                                                                            const deUint32                               subpass,
179                                                                            const deUint32*                              rasterizationStreamPtr  = DE_NULL,
180                                                                            const VkPrimitiveTopology    topology                                = VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
181                                                                            const bool                                   inputVertices                   = false)
182 {
183         const std::vector<VkViewport>                                                   viewports                                                               (1, makeViewport(renderSize));
184         const std::vector<VkRect2D>                                                             scissors                                                                (1, makeRect2D(renderSize));
185         const VkPipelineVertexInputStateCreateInfo                              vertexInputStateCreateInfo                      =
186         {
187                 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,                                                                      //  VkStructureType                                                                     sType
188                 DE_NULL,                                                                                                                                                                        //  const void*                                                                         pNext
189                 (VkPipelineVertexInputStateCreateFlags)0,                                                                                                       //  VkPipelineVertexInputStateCreateFlags                       flags
190                 0u,                                                                                                                                                                                     //  deUint32                                                                            vertexBindingDescriptionCount
191                 DE_NULL,                                                                                                                                                                        //  const VkVertexInputBindingDescription*                      pVertexBindingDescriptions
192                 0u,                                                                                                                                                                                     //  deUint32                                                                            vertexAttributeDescriptionCount
193                 DE_NULL,                                                                                                                                                                        //  const VkVertexInputAttributeDescription*            pVertexAttributeDescriptions
194         };
195         const VkPipelineVertexInputStateCreateInfo*                             vertexInputStateCreateInfoPtr           = (inputVertices) ? DE_NULL : &vertexInputStateCreateInfo;
196         const VkBool32                                                                                  disableRasterization                            = (fragmendModule == DE_NULL);
197         const deUint32                                                                                  rasterizationStream                                     = (rasterizationStreamPtr == DE_NULL) ? 0 : *rasterizationStreamPtr;
198         const VkPipelineRasterizationStateStreamCreateInfoEXT   rasterizationStateStreamCreateInfo      =
199         {
200                 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_STREAM_CREATE_INFO_EXT,                                          //  VkStructureType                                                                             sType;
201                 DE_NULL,                                                                                                                                                                        //  const void*                                                                                 pNext;
202                 0,                                                                                                                                                                                      //  VkPipelineRasterizationStateStreamCreateFlagsEXT    flags;
203                 rasterizationStream                                                                                                                                                     //  deUint32                                                                                    rasterizationStream;
204         };
205         const VkPipelineRasterizationStateCreateInfo                    rasterizationStateCreateInfo            =
206         {
207                 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,                                                                     //  VkStructureType                                                     sType;
208                 &rasterizationStateStreamCreateInfo,                                                                                                            //  const void*                                                         pNext;
209                 0u,                                                                                                                                                                                     //  VkPipelineRasterizationStateCreateFlags     flags;
210                 VK_FALSE,                                                                                                                                                                       //  VkBool32                                                            depthClampEnable;
211                 disableRasterization,                                                                                                                                           //  VkBool32                                                            rasterizerDiscardEnable;
212                 VK_POLYGON_MODE_FILL,                                                                                                                                           //  VkPolygonMode                                                       polygonMode;
213                 VK_CULL_MODE_NONE,                                                                                                                                                      //  VkCullModeFlags                                                     cullMode;
214                 VK_FRONT_FACE_COUNTER_CLOCKWISE,                                                                                                                        //  VkFrontFace                                                         frontFace;
215                 VK_FALSE,                                                                                                                                                                       //  VkBool32                                                            depthBiasEnable;
216                 0.0f,                                                                                                                                                                           //  float                                                                       depthBiasConstantFactor;
217                 0.0f,                                                                                                                                                                           //  float                                                                       depthBiasClamp;
218                 0.0f,                                                                                                                                                                           //  float                                                                       depthBiasSlopeFactor;
219                 1.0f                                                                                                                                                                            //  float                                                                       lineWidth;
220         };
221         const VkPipelineRasterizationStateCreateInfo*                   rasterizationStateCreateInfoPtr         = (rasterizationStreamPtr == DE_NULL) ? DE_NULL : &rasterizationStateCreateInfo;
222
223         return makeGraphicsPipeline(vk,                                                                                 // const DeviceInterface&                                                       vk
224                                                                 device,                                                                         // const VkDevice                                                                       device
225                                                                 pipelineLayout,                                                         // const VkPipelineLayout                                                       pipelineLayout
226                                                                 vertexModule,                                                           // const VkShaderModule                                                         vertexShaderModule
227                                                                 tessellationControlModule,                                      // const VkShaderModule                                                         tessellationControlModule
228                                                                 tessellationEvalModule,                                         // const VkShaderModule                                                         tessellationEvalModule
229                                                                 geometryModule,                                                         // const VkShaderModule                                                         geometryShaderModule
230                                                                 fragmendModule,                                                         // const VkShaderModule                                                         fragmentShaderModule
231                                                                 renderPass,                                                                     // const VkRenderPass                                                           renderPass
232                                                                 viewports,                                                                      // const std::vector<VkViewport>&                                       viewports
233                                                                 scissors,                                                                       // const std::vector<VkRect2D>&                                         scissors
234                                                                 topology,                                                                       // const VkPrimitiveTopology                                            topology
235                                                                 subpass,                                                                        // const deUint32                                                                       subpass
236                                                                 (tessellationEvalModule != DE_NULL) * 3u,       // const deUint32                                                                       patchControlPoints
237                                                                 vertexInputStateCreateInfoPtr,                          // const VkPipelineVertexInputStateCreateInfo*          vertexInputStateCreateInfo
238                                                                 rasterizationStateCreateInfoPtr);                       // const VkPipelineRasterizationStateCreateInfo*        rasterizationStateCreateInfo
239 }
240
241 VkImageCreateInfo makeImageCreateInfo (const VkImageCreateFlags flags, const VkImageType type, const VkFormat format, const VkExtent2D size, const deUint32 numLayers, const VkImageUsageFlags usage)
242 {
243         const VkExtent3D                extent          = { size.width, size.height, 1u };
244         const VkImageCreateInfo imageParams =
245         {
246                 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                    // VkStructureType                      sType;
247                 DE_NULL,                                                                                // const void*                          pNext;
248                 flags,                                                                                  // VkImageCreateFlags           flags;
249                 type,                                                                                   // VkImageType                          imageType;
250                 format,                                                                                 // VkFormat                                     format;
251                 extent,                                                                                 // VkExtent3D                           extent;
252                 1u,                                                                                             // deUint32                                     mipLevels;
253                 numLayers,                                                                              // deUint32                                     arrayLayers;
254                 VK_SAMPLE_COUNT_1_BIT,                                                  // VkSampleCountFlagBits        samples;
255                 VK_IMAGE_TILING_OPTIMAL,                                                // VkImageTiling                        tiling;
256                 usage,                                                                                  // VkImageUsageFlags            usage;
257                 VK_SHARING_MODE_EXCLUSIVE,                                              // VkSharingMode                        sharingMode;
258                 0u,                                                                                             // deUint32                                     queueFamilyIndexCount;
259                 DE_NULL,                                                                                // const deUint32*                      pQueueFamilyIndices;
260                 VK_IMAGE_LAYOUT_UNDEFINED,                                              // VkImageLayout                        initialLayout;
261         };
262         return imageParams;
263 }
264
265 Move<VkRenderPass> makeRenderPass (const DeviceInterface&               vk,
266                                                                    const VkDevice                               device)
267 {
268         std::vector<VkSubpassDescription>       subpassDescriptions;
269         std::vector<VkSubpassDependency>        subpassDependencies;
270
271         const VkSubpassDescription      description     =
272         {
273                 (VkSubpassDescriptionFlags)0,           //  VkSubpassDescriptionFlags           flags;
274                 VK_PIPELINE_BIND_POINT_GRAPHICS,        //  VkPipelineBindPoint                         pipelineBindPoint;
275                 0u,                                                                     //  deUint32                                            inputAttachmentCount;
276                 DE_NULL,                                                        //  const VkAttachmentReference*        pInputAttachments;
277                 0u,                                                                     //  deUint32                                            colorAttachmentCount;
278                 DE_NULL,                                                        //  const VkAttachmentReference*        pColorAttachments;
279                 DE_NULL,                                                        //  const VkAttachmentReference*        pResolveAttachments;
280                 DE_NULL,                                                        //  const VkAttachmentReference*        pDepthStencilAttachment;
281                 0,                                                                      //  deUint32                                            preserveAttachmentCount;
282                 DE_NULL                                                         //  const deUint32*                                     pPreserveAttachments;
283         };
284         subpassDescriptions.push_back(description);
285
286         const VkSubpassDependency       dependency      =
287         {
288                 0u,                                                                                                     //  deUint32                            srcSubpass;
289                 0u,                                                                                                     //  deUint32                            dstSubpass;
290                 VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT,           //  VkPipelineStageFlags        srcStageMask;
291                 VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT,                            //  VkPipelineStageFlags        dstStageMask;
292                 VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT,     //  VkAccessFlags                       srcAccessMask;
293                 VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT,      //  VkAccessFlags                       dstAccessMask;
294                 0u                                                                                                      //  VkDependencyFlags           dependencyFlags;
295         };
296         subpassDependencies.push_back(dependency);
297
298         const VkRenderPassCreateInfo renderPassInfo =
299         {
300                 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,                                                      //  VkStructureType                                     sType;
301                 DE_NULL,                                                                                                                        //  const void*                                         pNext;
302                 static_cast<VkRenderPassCreateFlags>(0u),                                                       //  VkRenderPassCreateFlags                     flags;
303                 0u,                                                                                                                                     //  deUint32                                            attachmentCount;
304                 DE_NULL,                                                                                                                        //  const VkAttachmentDescription*      pAttachments;
305                 static_cast<deUint32>(subpassDescriptions.size()),                                      //  deUint32                                            subpassCount;
306                 &subpassDescriptions[0],                                                                                        //  const VkSubpassDescription*         pSubpasses;
307                 static_cast<deUint32>(subpassDependencies.size()),                                      //  deUint32                                            dependencyCount;
308                 subpassDependencies.size() > 0 ? &subpassDependencies[0] : DE_NULL      //  const VkSubpassDependency*          pDependencies;
309         };
310
311         return createRenderPass(vk, device, &renderPassInfo);
312 }
313
314 VkImageMemoryBarrier makeImageMemoryBarrier     (const VkAccessFlags                    srcAccessMask,
315                                                                                          const VkAccessFlags                    dstAccessMask,
316                                                                                          const VkImageLayout                    oldLayout,
317                                                                                          const VkImageLayout                    newLayout,
318                                                                                          const VkImage                                  image,
319                                                                                          const VkImageSubresourceRange  subresourceRange)
320 {
321         const VkImageMemoryBarrier barrier =
322         {
323                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                 // VkStructureType                      sType;
324                 DE_NULL,                                                                                // const void*                          pNext;
325                 srcAccessMask,                                                                  // VkAccessFlags                        outputMask;
326                 dstAccessMask,                                                                  // VkAccessFlags                        inputMask;
327                 oldLayout,                                                                              // VkImageLayout                        oldLayout;
328                 newLayout,                                                                              // VkImageLayout                        newLayout;
329                 VK_QUEUE_FAMILY_IGNORED,                                                // deUint32                                     srcQueueFamilyIndex;
330                 VK_QUEUE_FAMILY_IGNORED,                                                // deUint32                                     destQueueFamilyIndex;
331                 image,                                                                                  // VkImage                                      image;
332                 subresourceRange,                                                               // VkImageSubresourceRange      subresourceRange;
333         };
334         return barrier;
335 }
336
337 VkBufferMemoryBarrier makeBufferMemoryBarrier (const VkAccessFlags      srcAccessMask,
338                                                                                            const VkAccessFlags  dstAccessMask,
339                                                                                            const VkBuffer               buffer,
340                                                                                            const VkDeviceSize   offset,
341                                                                                            const VkDeviceSize   bufferSizeBytes)
342 {
343         const VkBufferMemoryBarrier barrier =
344         {
345                 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,        //  VkStructureType     sType;
346                 DE_NULL,                                                                        //  const void*         pNext;
347                 srcAccessMask,                                                          //  VkAccessFlags       srcAccessMask;
348                 dstAccessMask,                                                          //  VkAccessFlags       dstAccessMask;
349                 VK_QUEUE_FAMILY_IGNORED,                                        //  deUint32            srcQueueFamilyIndex;
350                 VK_QUEUE_FAMILY_IGNORED,                                        //  deUint32            destQueueFamilyIndex;
351                 buffer,                                                                         //  VkBuffer            buffer;
352                 offset,                                                                         //  VkDeviceSize        offset;
353                 bufferSizeBytes,                                                        //  VkDeviceSize        size;
354         };
355         return barrier;
356 }
357
358 VkMemoryBarrier makeMemoryBarrier (const VkAccessFlags  srcAccessMask,
359                                                                    const VkAccessFlags  dstAccessMask)
360 {
361         const VkMemoryBarrier barrier =
362         {
363                 VK_STRUCTURE_TYPE_MEMORY_BARRIER,       // VkStructureType                      sType;
364                 DE_NULL,                                                        // const void*                          pNext;
365                 srcAccessMask,                                          // VkAccessFlags                        outputMask;
366                 dstAccessMask,                                          // VkAccessFlags                        inputMask;
367         };
368         return barrier;
369 }
370
371 VkQueryPoolCreateInfo makeQueryPoolCreateInfo (const deUint32 queryCountersNumber)
372 {
373         const VkQueryPoolCreateInfo                     queryPoolCreateInfo             =
374         {
375                 VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,               //  VkStructureType                                     sType;
376                 DE_NULL,                                                                                //  const void*                                         pNext;
377                 (VkQueryPoolCreateFlags)0,                                              //  VkQueryPoolCreateFlags                      flags;
378                 VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT,    //  VkQueryType                                         queryType;
379                 queryCountersNumber,                                                    //  deUint32                                            queryCount;
380                 0u,                                                                                             //  VkQueryPipelineStatisticFlags       pipelineStatistics;
381         };
382
383         return queryPoolCreateInfo;
384 }
385
386 void fillBuffer (const DeviceInterface& vk, const VkDevice device, Allocation& bufferAlloc, VkDeviceSize bufferSize, const void* data, const VkDeviceSize dataSize)
387 {
388         const VkMappedMemoryRange       memRange                =
389         {
390                 VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,  //  VkStructureType     sType;
391                 DE_NULL,                                                                //  const void*         pNext;
392                 bufferAlloc.getMemory(),                                //  VkDeviceMemory      memory;
393                 bufferAlloc.getOffset(),                                //  VkDeviceSize        offset;
394                 VK_WHOLE_SIZE                                                   //  VkDeviceSize        size;
395         };
396         std::vector<deUint8>            dataVec                 (static_cast<deUint32>(bufferSize), 0u);
397
398         DE_ASSERT(bufferSize >= dataSize);
399
400         deMemcpy(&dataVec[0], data, static_cast<deUint32>(dataSize));
401
402         deMemcpy(bufferAlloc.getHostPtr(), &dataVec[0], dataVec.size());
403         VK_CHECK(vk.flushMappedMemoryRanges(device, 1u, &memRange));
404 }
405
406 class TransformFeedbackTestInstance : public TestInstance
407 {
408 public:
409                                                                                                         TransformFeedbackTestInstance   (Context& context, const TestParameters& parameters);
410 protected:
411         void                                                                                    validateLimits                                  ();
412         std::vector<VkDeviceSize>                                               generateSizesList                               (const size_t bufBytes, const size_t chunkCount);
413         std::vector<VkDeviceSize>                                               generateOffsetsList                             (const std::vector<VkDeviceSize>& sizesList);
414         void                                                                                    verifyTransformFeedbackBuffer   (const MovePtr<Allocation>& bufAlloc,
415                                                                                                                                                                          const deUint32 bufBytes);
416
417         const bool                                                                              m_extensions;
418         const VkExtent2D                                                                m_imageExtent2D;
419         const TestParameters                                                    m_parameters;
420         VkPhysicalDeviceTransformFeedbackPropertiesEXT  m_transformFeedbackProperties;
421         de::Random                                                                              m_rnd;
422 };
423
424 TransformFeedbackTestInstance::TransformFeedbackTestInstance (Context& context, const TestParameters& parameters)
425         : TestInstance          (context)
426         , m_extensions          (context.requireDeviceFunctionality("VK_EXT_transform_feedback"))
427         , m_imageExtent2D       (makeExtent2D(IMAGE_SIZE, IMAGE_SIZE))
428         , m_parameters          (parameters)
429         , m_rnd                         (0)
430 {
431         const VkPhysicalDeviceTransformFeedbackFeaturesEXT&             transformFeedbackFeatures       = m_context.getTransformFeedbackFeaturesEXT();
432         VkPhysicalDeviceProperties2                                                             deviceProperties2;
433
434         if (transformFeedbackFeatures.transformFeedback == DE_FALSE)
435                 TCU_THROW(NotSupportedError, "transformFeedback feature is not supported");
436
437         deMemset(&deviceProperties2, 0, sizeof(deviceProperties2));
438         deMemset(&m_transformFeedbackProperties, 0, sizeof(m_transformFeedbackProperties));
439
440         deviceProperties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
441         deviceProperties2.pNext = &m_transformFeedbackProperties;
442
443         m_transformFeedbackProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT;
444         m_transformFeedbackProperties.pNext = DE_NULL;
445
446         context.getInstanceInterface().getPhysicalDeviceProperties2(context.getPhysicalDevice(), &deviceProperties2);
447
448         validateLimits();
449
450         if (m_parameters.streamId > 0 && (m_transformFeedbackProperties.transformFeedbackRasterizationStreamSelect == VK_FALSE))
451                 TCU_THROW(NotSupportedError, "Implementation doesn't support streamId > 0");
452 }
453
454 void TransformFeedbackTestInstance::validateLimits ()
455 {
456         VALIDATE_MINIMUM(m_transformFeedbackProperties.maxTransformFeedbackBuffers, 1);
457         VALIDATE_MINIMUM(m_transformFeedbackProperties.maxTransformFeedbackBufferSize, MINIMUM_TF_BUFFER_SIZE);
458         VALIDATE_MINIMUM(m_transformFeedbackProperties.maxTransformFeedbackStreamDataSize, 512);
459         VALIDATE_MINIMUM(m_transformFeedbackProperties.maxTransformFeedbackBufferDataSize, 512);
460         VALIDATE_MINIMUM(m_transformFeedbackProperties.maxTransformFeedbackBufferDataStride, 512);
461
462         VALIDATE_BOOL(m_transformFeedbackProperties.transformFeedbackQueries);
463         VALIDATE_BOOL(m_transformFeedbackProperties.transformFeedbackStreamsLinesTriangles);
464         VALIDATE_BOOL(m_transformFeedbackProperties.transformFeedbackRasterizationStreamSelect);
465         VALIDATE_BOOL(m_transformFeedbackProperties.transformFeedbackDraw);
466 }
467
468 std::vector<VkDeviceSize> TransformFeedbackTestInstance::generateSizesList (const size_t bufBytes, const size_t chunkCount)
469 {
470         const int                                       minChunkSlot    = static_cast<int>(1);
471         const int                                       maxChunkSlot    = static_cast<int>(bufBytes / sizeof(deUint32));
472         int                                                     prevOffsetSlot  = 0;
473         std::map<int, bool>                     offsetsSet;
474         std::vector<VkDeviceSize>       result;
475
476         DE_ASSERT(bufBytes <= MINIMUM_TF_BUFFER_SIZE);
477         DE_ASSERT(bufBytes % sizeof(deUint32) == 0);
478         DE_ASSERT(minChunkSlot <= maxChunkSlot);
479         DE_ASSERT(chunkCount > 0);
480         // To be effective this algorithm requires that chunkCount is much less than amount of chunks possible
481         DE_ASSERT(8 * chunkCount <= static_cast<size_t>(maxChunkSlot));
482
483         offsetsSet[0] = true;
484
485         // Create a list of unique offsets first
486         for (size_t chunkNdx = 1; chunkNdx < chunkCount; ++chunkNdx)
487         {
488                 int chunkSlot;
489
490                 do
491                 {
492                         chunkSlot = m_rnd.getInt(minChunkSlot, maxChunkSlot - 1);
493                 } while (offsetsSet.find(chunkSlot) != offsetsSet.end());
494
495                 offsetsSet[chunkSlot] = true;
496         }
497         offsetsSet[maxChunkSlot] = true;
498
499         // Calculate sizes of offsets list
500         result.reserve(chunkCount);
501         for (std::map<int, bool>::iterator mapIt = offsetsSet.begin(); mapIt != offsetsSet.end(); ++mapIt)
502         {
503                 const int offsetSlot = mapIt->first;
504
505                 if (offsetSlot == 0)
506                         continue;
507
508                 DE_ASSERT(prevOffsetSlot < offsetSlot && offsetSlot > 0);
509
510                 result.push_back(static_cast<VkDeviceSize>(static_cast<size_t>(offsetSlot - prevOffsetSlot) * sizeof(deUint32)));
511
512                 prevOffsetSlot = offsetSlot;
513         }
514
515         DE_ASSERT(result.size() == chunkCount);
516
517         return result;
518 }
519
520 std::vector<VkDeviceSize> TransformFeedbackTestInstance::generateOffsetsList (const std::vector<VkDeviceSize>& sizesList)
521 {
522         VkDeviceSize                            offset  = 0ull;
523         std::vector<VkDeviceSize>       result;
524
525         result.reserve(sizesList.size());
526
527         for (size_t chunkNdx = 0; chunkNdx < sizesList.size(); ++chunkNdx)
528         {
529                 result.push_back(offset);
530
531                 offset += sizesList[chunkNdx];
532         }
533
534         DE_ASSERT(sizesList.size() == result.size());
535
536         return result;
537 }
538
539 void TransformFeedbackTestInstance::verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc,
540                                                                                                                                    const deUint32 bufBytes)
541 {
542         const DeviceInterface&  vk                      = m_context.getDeviceInterface();
543         const VkDevice                  device          = m_context.getDevice();
544
545         invalidateAlloc(vk, device, *bufAlloc);
546
547         const deUint32                  numPoints       = static_cast<deUint32>(bufBytes / sizeof(deUint32));
548         const deUint32*                 tfData          = (deUint32*)bufAlloc->getHostPtr();
549
550         for (deUint32 i = 0; i < numPoints; ++i)
551                 if (tfData[i] != i)
552                         TCU_FAIL(std::string("Failed at item ") + de::toString(i) + " received:" + de::toString(tfData[i]) + " expected:" + de::toString(i));
553 }
554
555 class TransformFeedbackBasicTestInstance : public TransformFeedbackTestInstance
556 {
557 public:
558                                                 TransformFeedbackBasicTestInstance      (Context& context, const TestParameters& parameters);
559
560 protected:
561         tcu::TestStatus         iterate                                                         (void);
562 };
563
564 TransformFeedbackBasicTestInstance::TransformFeedbackBasicTestInstance (Context& context, const TestParameters& parameters)
565         : TransformFeedbackTestInstance (context, parameters)
566 {
567 }
568
569 tcu::TestStatus TransformFeedbackBasicTestInstance::iterate (void)
570 {
571         const DeviceInterface&                          vk                                              = m_context.getDeviceInterface();
572         const VkDevice                                          device                                  = m_context.getDevice();
573         const deUint32                                          queueFamilyIndex                = m_context.getUniversalQueueFamilyIndex();
574         const VkQueue                                           queue                                   = m_context.getUniversalQueue();
575         Allocator&                                                      allocator                               = m_context.getDefaultAllocator();
576
577         const Unique<VkShaderModule>            vertexModule                    (createShaderModule                                             (vk, device, m_context.getBinaryCollection().get("vert"), 0u));
578         const Unique<VkRenderPass>                      renderPass                              (makeRenderPass                                                 (vk, device, VK_FORMAT_UNDEFINED));
579         const Unique<VkFramebuffer>                     framebuffer                             (makeFramebuffer                                                (vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
580         const Unique<VkPipelineLayout>          pipelineLayout                  (TransformFeedback::makePipelineLayout  (vk, device));
581         const Unique<VkPipeline>                        pipeline                                (makeGraphicsPipeline                                   (vk, device, *pipelineLayout, *renderPass, *vertexModule, DE_NULL, DE_NULL, DE_NULL, DE_NULL, m_imageExtent2D, 0u, &m_parameters.streamId));
582         const Unique<VkCommandPool>                     cmdPool                                 (createCommandPool                                              (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
583         const Unique<VkCommandBuffer>           cmdBuffer                               (allocateCommandBuffer                                  (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
584
585         const VkBufferCreateInfo                        tfBufCreateInfo                 = makeBufferCreateInfo(m_parameters.bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
586         const Move<VkBuffer>                            tfBuf                                   = createBuffer(vk, device, &tfBufCreateInfo);
587         const MovePtr<Allocation>                       tfBufAllocation                 = allocator.allocate(getBufferMemoryRequirements(vk, device, *tfBuf), MemoryRequirement::HostVisible);
588         const VkMemoryBarrier                           tfMemoryBarrier                 = makeMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, VK_ACCESS_HOST_READ_BIT);
589         const std::vector<VkDeviceSize>         tfBufBindingSizes               = generateSizesList(m_parameters.bufferSize, m_parameters.partCount);
590         const std::vector<VkDeviceSize>         tfBufBindingOffsets             = generateOffsetsList(tfBufBindingSizes);
591
592         VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
593
594         beginCommandBuffer(vk, *cmdBuffer);
595         {
596                 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
597                 {
598                         vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
599
600                         for (deUint32 drawNdx = 0; drawNdx < m_parameters.partCount; ++drawNdx)
601                         {
602                                 const deUint32  startValue      = static_cast<deUint32>(tfBufBindingOffsets[drawNdx] / sizeof(deUint32));
603                                 const deUint32  numPoints       = static_cast<deUint32>(tfBufBindingSizes[drawNdx] / sizeof(deUint32));
604
605                                 vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0, 1, &*tfBuf, &tfBufBindingOffsets[drawNdx], &tfBufBindingSizes[drawNdx]);
606
607                                 vk.cmdPushConstants(*cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0u, sizeof(startValue), &startValue);
608
609                                 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
610                                 {
611                                         vk.cmdDraw(*cmdBuffer, numPoints, 1u, 0u, 0u);
612                                 }
613                                 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
614                         }
615                 }
616                 endRenderPass(vk, *cmdBuffer);
617
618                 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &tfMemoryBarrier, 0u, DE_NULL, 0u, DE_NULL);
619         }
620         endCommandBuffer(vk, *cmdBuffer);
621         submitCommandsAndWait(vk, device, queue, *cmdBuffer);
622
623         verifyTransformFeedbackBuffer(tfBufAllocation, m_parameters.bufferSize);
624
625         return tcu::TestStatus::pass("Pass");
626 }
627
628 class TransformFeedbackResumeTestInstance : public TransformFeedbackTestInstance
629 {
630 public:
631                                                 TransformFeedbackResumeTestInstance     (Context& context, const TestParameters& parameters);
632
633 protected:
634         tcu::TestStatus         iterate                                                         (void);
635 };
636
637 TransformFeedbackResumeTestInstance::TransformFeedbackResumeTestInstance (Context& context, const TestParameters& parameters)
638         : TransformFeedbackTestInstance (context, parameters)
639 {
640 }
641
642 tcu::TestStatus TransformFeedbackResumeTestInstance::iterate (void)
643 {
644         const DeviceInterface&                                  vk                                              = m_context.getDeviceInterface();
645         const VkDevice                                                  device                                  = m_context.getDevice();
646         const deUint32                                                  queueFamilyIndex                = m_context.getUniversalQueueFamilyIndex();
647         const VkQueue                                                   queue                                   = m_context.getUniversalQueue();
648         Allocator&                                                              allocator                               = m_context.getDefaultAllocator();
649
650         const Unique<VkShaderModule>                    vertexModule                    (createShaderModule                                             (vk, device, m_context.getBinaryCollection().get("vert"), 0u));
651         const Unique<VkRenderPass>                              renderPass                              (makeRenderPass                                                 (vk, device, VK_FORMAT_UNDEFINED));
652         const Unique<VkFramebuffer>                             framebuffer                             (makeFramebuffer                                                (vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
653         const Unique<VkPipelineLayout>                  pipelineLayout                  (TransformFeedback::makePipelineLayout  (vk, device));
654         const Unique<VkPipeline>                                pipeline                                (makeGraphicsPipeline                                   (vk, device, *pipelineLayout, *renderPass, *vertexModule, DE_NULL, DE_NULL, DE_NULL, DE_NULL, m_imageExtent2D, 0u, &m_parameters.streamId));
655
656         const Unique<VkCommandPool>                             cmdPool                                 (createCommandPool                                              (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
657         const Unique<VkCommandBuffer>                   cmdBuffer                               (allocateCommandBuffer                                  (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
658
659         const VkBufferCreateInfo                                tfBufCreateInfo                 = makeBufferCreateInfo(m_parameters.bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
660         const Move<VkBuffer>                                    tfBuf                                   = createBuffer(vk, device, &tfBufCreateInfo);
661         const MovePtr<Allocation>                               tfBufAllocation                 = allocator.allocate(getBufferMemoryRequirements(vk, device, *tfBuf), MemoryRequirement::HostVisible);
662         const VkMemoryBarrier                                   tfMemoryBarrier                 = makeMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, VK_ACCESS_HOST_READ_BIT);
663         const std::vector<VkDeviceSize>                 tfBufBindingSizes               = std::vector<VkDeviceSize>(1, m_parameters.bufferSize);
664         const std::vector<VkDeviceSize>                 tfBufBindingOffsets             = std::vector<VkDeviceSize>(1, 0ull);
665
666         const size_t                                                    tfcBufSize                              = 16 * sizeof(deUint32) * m_parameters.partCount;
667         const VkBufferCreateInfo                                tfcBufCreateInfo                = makeBufferCreateInfo(tfcBufSize, VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT);
668         const Move<VkBuffer>                                    tfcBuf                                  = createBuffer(vk, device, &tfcBufCreateInfo);
669         const MovePtr<Allocation>                               tfcBufAllocation                = allocator.allocate(getBufferMemoryRequirements(vk, device, *tfcBuf), MemoryRequirement::Any);
670         const std::vector<VkDeviceSize>                 tfcBufBindingOffsets    = generateOffsetsList(generateSizesList(tfcBufSize, m_parameters.partCount));
671         const VkBufferMemoryBarrier                             tfcBufBarrier                   = makeBufferMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT, VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT, *tfcBuf, 0ull, VK_WHOLE_SIZE);
672
673         const std::vector<VkDeviceSize>                 chunkSizesList                  = generateSizesList(m_parameters.bufferSize, m_parameters.partCount);
674         const std::vector<VkDeviceSize>                 chunkOffsetsList                = generateOffsetsList(chunkSizesList);
675
676         DE_ASSERT(tfBufBindingSizes.size() == 1);
677         DE_ASSERT(tfBufBindingOffsets.size() == 1);
678
679         VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
680         VK_CHECK(vk.bindBufferMemory(device, *tfcBuf, tfcBufAllocation->getMemory(), tfcBufAllocation->getOffset()));
681
682         beginCommandBuffer(vk, *cmdBuffer);
683         {
684                 for (size_t drawNdx = 0; drawNdx < m_parameters.partCount; ++drawNdx)
685                 {
686                         const deUint32  startValue = static_cast<deUint32>(chunkOffsetsList[drawNdx] / sizeof(deUint32));
687                         const deUint32  numPoints = static_cast<deUint32>(chunkSizesList[drawNdx] / sizeof(deUint32));
688                         const deUint32  countBuffersCount = (drawNdx == 0) ? 0 : 1;
689
690                         beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
691                         {
692
693                                 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
694
695                                 vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0, 1, &*tfBuf, &tfBufBindingOffsets[0], &tfBufBindingSizes[0]);
696
697                                 vk.cmdPushConstants(*cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0u, sizeof(startValue), &startValue);
698
699                                 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, countBuffersCount, (drawNdx == 0) ? DE_NULL : &*tfcBuf, (drawNdx == 0) ? DE_NULL : &tfcBufBindingOffsets[drawNdx - 1]);
700                                 {
701                                         vk.cmdDraw(*cmdBuffer, numPoints, 1u, 0u, 0u);
702                                 }
703                                 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 1, &*tfcBuf, &tfcBufBindingOffsets[drawNdx]);
704                         }
705                         endRenderPass(vk, *cmdBuffer);
706
707                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, 0u, 0u, DE_NULL, 1u, &tfcBufBarrier, 0u, DE_NULL);
708                 }
709
710                 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &tfMemoryBarrier, 0u, DE_NULL, 0u, DE_NULL);
711         }
712         endCommandBuffer(vk, *cmdBuffer);
713         submitCommandsAndWait(vk, device, queue, *cmdBuffer);
714
715         verifyTransformFeedbackBuffer(tfBufAllocation, m_parameters.bufferSize);
716
717         return tcu::TestStatus::pass("Pass");
718 }
719
720 class TransformFeedbackWindingOrderTestInstance : public TransformFeedbackTestInstance
721 {
722 public:
723         TransformFeedbackWindingOrderTestInstance(Context& context, const TestParameters& parameters);
724
725 protected:
726         struct TopologyParameters
727         {
728                 // number of vertex in primitive; 2 for line, 3 for triangle
729                 deUint32 vertexPerPrimitive;
730
731                 // pointer to function calculating number of points that
732                 // will be generated for given part count
733                 std::function<deUint32(deUint32)> getNumGeneratedPoints;
734
735                 // pointer to function generating expected values; parameter is
736                 // primitive index, result array with expected data for primitive vertex
737                 std::function<std::vector<deUint32>(deUint32)> getExpectedValuesForPrimitive;
738         };
739         typedef const std::map<VkPrimitiveTopology, TopologyParameters> TopologyParametersMap;
740
741 protected:
742         const TopologyParametersMap&    getTopologyParametersMap                                        (void);
743         tcu::TestStatus                                 iterate                                                                         (void);
744         void                                                    verifyTransformFeedbackBuffer                           (const MovePtr<Allocation>& bufAlloc,
745                                                                                                                                                                  const deUint32 bufBytes);
746
747 private:
748         TopologyParameters                              m_tParameters;
749         const bool                                              m_requiresTesselationStage;
750 };
751
752 TransformFeedbackWindingOrderTestInstance::TransformFeedbackWindingOrderTestInstance(Context& context, const TestParameters& parameters)
753         : TransformFeedbackTestInstance (context, parameters)
754         , m_requiresTesselationStage(parameters.primTopology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST)
755 {
756         if (m_requiresTesselationStage && !context.getDeviceFeatures().tessellationShader)
757                 throw tcu::NotSupportedError("Tessellation shader not supported");
758
759         TopologyParametersMap topologyParametersMap = getTopologyParametersMap();
760         DE_ASSERT(topologyParametersMap.find(parameters.primTopology) != topologyParametersMap.end());
761         m_tParameters = topologyParametersMap.at(parameters.primTopology);
762 }
763
764 const TransformFeedbackWindingOrderTestInstance::TopologyParametersMap& TransformFeedbackWindingOrderTestInstance::getTopologyParametersMap(void)
765 {
766         static const TopologyParametersMap topologyParametersMap =
767         {
768                 {
769                         VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
770                         {
771                                 1u,
772                                 [](deUint32 partCount)  {       return partCount;       },
773                                 [](deUint32 i)                  {       return std::vector<deUint32>{ i, i + 1u };      }
774                         }
775                 },
776                 {
777                         VK_PRIMITIVE_TOPOLOGY_LINE_LIST,
778                         {
779                                 2u,
780                                 [](deUint32 partCount)  {       return partCount;       },
781                                 [](deUint32 i)                  {       return std::vector<deUint32>{ 2 * i, 2 * i + 1u };      }
782                         }
783                 },
784                 {
785                         VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,
786                         {
787                                 2u,
788                                 [](deUint32 partCount)  {       return 2u * (partCount - 1);    },
789                                 [](deUint32 i)                  {       return std::vector<deUint32>{ i, i + 1u };      }
790                         }
791                 },
792                 {
793                         VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
794                         {
795                                 3u,
796                                 [](deUint32 partCount)  {       return partCount;       },
797                                 [](deUint32 i)                  {       return std::vector<deUint32>{ 3 * i, 3 * i + 1u, 3 * i + 2u };  }
798                         }
799                 },
800                 {
801                         VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
802                         {
803                                 3u,
804                                 [](deUint32 partCount)  {       return 3u * (partCount - 2);    },
805                                 [](deUint32 i)
806                                 {
807                                         const deUint32  iMod2 = i % 2;
808                                         return std::vector<deUint32>{ i, i + 1 + iMod2, i + 2 - iMod2 };
809                                 }
810                         }
811                 },
812                 {
813                         VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,
814                         {
815                                 3u,
816                                 [](deUint32 partCount)  {       return partCount;       },
817                                 [](deUint32 i)                  {       return std::vector<deUint32>{ i + 1, i + 2, 0 };        }
818                         }
819                 },
820                 {
821                         VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY,
822                         {
823                                 2u,
824                                 [](deUint32 partCount)  {       return partCount / 4u;  },              // note: this cant be replaced with partCount / 2 as for partCount=6 we will get 3 instead of 2
825                                 [](deUint32 i)                  {       return std::vector<deUint32>{ i + 1u, i + 2u }; }
826                         }
827                 },
828                 {
829                         VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY,
830                         {
831                                 2u,
832                                 [](deUint32 partCount)  {       return 2u * (partCount - 3u);   },
833                                 [](deUint32 i)                  {       return std::vector<deUint32>{ i + 1u, i + 2u }; }
834                         }
835                 },
836                 {
837                         VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY,
838                         {
839                                 3u,
840                                 [](deUint32 partCount)  {       return partCount / 2u;  },
841                                 [](deUint32 i)                  {       return std::vector<deUint32>{ 6 * i, 6 * i + 2u, 6 * i + 4u     };      }
842                         }
843                 },
844                 {
845                         VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY,
846                         {
847                                 3u,
848                                 [](deUint32 partCount)  {       return 3u * (partCount / 2u - 2u);      },
849                                 [](deUint32 i)
850                                 {
851                                         const bool even = (0 == i % 2);
852                                         if (even)
853                                                 return std::vector<deUint32>{ 2 * i + 0, 2 * i + 2, 2 * i + 4 };
854                                         return std::vector<deUint32>{ 2 * i + 0, 2 * i + 4, 2 * i + 2 };
855                                 }
856                         }
857                 },
858                 {
859                         VK_PRIMITIVE_TOPOLOGY_PATCH_LIST,
860                         {
861                                 9u,
862                                 [](deUint32 partCount)  {       return partCount * 3u;  },
863                                 [](deUint32 i)
864                                 {
865                                         // we cant generate vertex numbers in tesselation evaluation shader;
866                                         // check if patch index is correct for every 9 generated vertex
867                                         return std::vector<deUint32>(9, i);
868                                 }
869                         }
870                 }
871         };
872
873         return topologyParametersMap;
874 }
875
876 tcu::TestStatus TransformFeedbackWindingOrderTestInstance::iterate (void)
877 {
878         DE_ASSERT(m_parameters.partCount >= 6);
879
880         const DeviceInterface&                  vk                                      = m_context.getDeviceInterface();
881         const VkDevice                                  device                          = m_context.getDevice();
882         const deUint32                                  queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
883         const VkQueue                                   queue                           = m_context.getUniversalQueue();
884         Allocator&                                              allocator                       = m_context.getDefaultAllocator();
885
886         const Move<VkShaderModule>              vertexModule(createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
887         Move<VkShaderModule>                    tescModule;
888         Move<VkShaderModule>                    teseModule;
889         if (m_requiresTesselationStage)
890         {
891                 tescModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("tesc"), 0u);
892                 teseModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("tese"), 0u);
893         }
894
895         const Unique<VkRenderPass>              renderPass                      (makeRenderPass                                                 (vk, device, VK_FORMAT_UNDEFINED));
896         const Unique<VkFramebuffer>             framebuffer                     (makeFramebuffer                                                (vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
897         const Unique<VkPipelineLayout>  pipelineLayout          (TransformFeedback::makePipelineLayout  (vk, device));
898         const Unique<VkPipeline>                pipeline                        (makeGraphicsPipeline                                   (vk, device, *pipelineLayout, *renderPass,
899                                                                                                                                                                                                  *vertexModule,
900                                                                                                                                                                                                  m_requiresTesselationStage ? *tescModule : DE_NULL,
901                                                                                                                                                                                                  m_requiresTesselationStage ? *teseModule : DE_NULL,
902                                                                                                                                                                                                  DE_NULL,
903                                                                                                                                                                                                  DE_NULL,
904                                                                                                                                                                                                  m_imageExtent2D, 0u, DE_NULL, m_parameters.primTopology));
905         const Unique<VkCommandPool>             cmdPool                         (createCommandPool                                              (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
906         const Unique<VkCommandBuffer>   cmdBuffer                       (allocateCommandBuffer                                  (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
907         const VkDeviceSize                              bufferSize                      = m_tParameters.getNumGeneratedPoints   (m_parameters.partCount) * sizeof(deUint32);
908         const VkBufferCreateInfo                tfBufCreateInfo         = makeBufferCreateInfo                                  (bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
909         const Move<VkBuffer>                    tfBuf                           = createBuffer                                                  (vk, device, &tfBufCreateInfo);
910         const MovePtr<Allocation>               tfBufAllocation         = allocator.allocate                                    (getBufferMemoryRequirements(vk, device, *tfBuf), MemoryRequirement::HostVisible);
911         const VkMemoryBarrier                   tfMemoryBarrier         = makeMemoryBarrier                                             (VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, VK_ACCESS_HOST_READ_BIT);
912         const VkDeviceSize                              tfBufBindingSize        = bufferSize;
913         const VkDeviceSize                              tfBufBindingOffset      = 0u;
914         const deUint32                                  startValue                      = 0u;
915
916         VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
917
918         beginCommandBuffer(vk, *cmdBuffer);
919         {
920                 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
921                 {
922                         vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
923
924                         vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0, 1, &*tfBuf, &tfBufBindingOffset, &tfBufBindingSize);
925
926                         vk.cmdPushConstants(*cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0u, sizeof(startValue), &startValue);
927
928                         vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
929                         {
930                                 vk.cmdDraw(*cmdBuffer, m_parameters.partCount, 1u, 0u, 0u);
931                         }
932                         vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
933                 }
934                 endRenderPass(vk, *cmdBuffer);
935
936                 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &tfMemoryBarrier, 0u, DE_NULL, 0u, DE_NULL);
937         }
938         endCommandBuffer(vk, *cmdBuffer);
939         submitCommandsAndWait(vk, device, queue, *cmdBuffer);
940
941         verifyTransformFeedbackBuffer(tfBufAllocation, static_cast<deUint32>(bufferSize));
942
943         return tcu::TestStatus::pass("Pass");
944 }
945
946 void TransformFeedbackWindingOrderTestInstance::verifyTransformFeedbackBuffer(const MovePtr<Allocation>& bufAlloc,
947                                                                                                                                                           const deUint32 bufBytes)
948 {
949         const DeviceInterface&  vk              = m_context.getDeviceInterface();
950         const VkDevice                  device  = m_context.getDevice();
951
952         invalidateAlloc(vk, device, *bufAlloc);
953
954         const deUint32  numPoints                       = static_cast<deUint32>(bufBytes / sizeof(deUint32));
955         const deUint32  vertexPerPrimitive      = m_tParameters.vertexPerPrimitive;
956         const deUint32  numPrimitives           = numPoints / vertexPerPrimitive;
957         const deUint32* tfData                          = (deUint32*)bufAlloc->getHostPtr();
958
959         for (deUint32 primitiveIndex = 0; primitiveIndex < numPrimitives; ++primitiveIndex)
960         {
961                 const deUint32*                 tfDataForPrimitive                      = &tfData[primitiveIndex * vertexPerPrimitive];
962                 std::vector<deUint32>   expectedDataForPrimitive        = m_tParameters.getExpectedValuesForPrimitive(primitiveIndex);
963
964                 // For multi - vertex primitives, all values for a given vertex are written before writing values for any other vertex.
965                 // Implementations may write out any vertex within the primitive first, but all subsequent vertices for that primitive
966                 // must be written out in a consistent winding order
967                 bool correctWinding = true;
968                 for (deUint32 combinationIndex = 0; combinationIndex < vertexPerPrimitive; combinationIndex++)
969                 {
970                         correctWinding = true;
971                         for (deUint32 vertexIndex = 0; vertexIndex < vertexPerPrimitive; vertexIndex++)
972                         {
973                                 correctWinding &= (tfDataForPrimitive[vertexIndex] == expectedDataForPrimitive[(combinationIndex + vertexIndex) % vertexPerPrimitive]);
974
975                                 // if data for this vertex is not correct then there
976                                 // is no need to check other, go to next combination
977                                 if (!correctWinding)
978                                         break;
979                         }
980
981                         // no need to check other combinations, we found correct one
982                         if (correctWinding)
983                                 break;
984                 }
985
986                 if (!correctWinding)
987                 {
988                         std::stringstream message;
989                         message << "Failed at primitive " << primitiveIndex << " received: [";
990                         for (deUint32 vertexIndex = 0; vertexIndex < vertexPerPrimitive; vertexIndex++)
991                                 message << de::toString(tfDataForPrimitive[vertexIndex]) << " ";
992                         message << "] expected: [";
993                         for (deUint32 vertexIndex = 0; vertexIndex < vertexPerPrimitive; vertexIndex++)
994                                 message << de::toString(expectedDataForPrimitive[vertexIndex]) << " ";
995                         message << "]";
996                         TCU_FAIL(message.str());
997                 }
998         }
999 }
1000
1001 class TransformFeedbackBuiltinTestInstance : public TransformFeedbackTestInstance
1002 {
1003 public:
1004                                                 TransformFeedbackBuiltinTestInstance    (Context& context, const TestParameters& parameters);
1005
1006 protected:
1007         tcu::TestStatus         iterate                                                                 (void);
1008         void                            verifyTransformFeedbackBuffer                   (const MovePtr<Allocation>& bufAlloc, const VkDeviceSize offset, const deUint32 bufBytes);
1009 };
1010
1011 TransformFeedbackBuiltinTestInstance::TransformFeedbackBuiltinTestInstance (Context& context, const TestParameters& parameters)
1012         : TransformFeedbackTestInstance (context, parameters)
1013 {
1014         const InstanceInterface&                vki                     = m_context.getInstanceInterface();
1015         const VkPhysicalDevice                  physDevice      = m_context.getPhysicalDevice();
1016         const VkPhysicalDeviceFeatures  features        = getPhysicalDeviceFeatures(vki, physDevice);
1017
1018         const deUint32 tfBuffersSupported       = m_transformFeedbackProperties.maxTransformFeedbackBuffers;
1019         const deUint32 tfBuffersRequired        = m_parameters.partCount;
1020
1021         if ((m_parameters.testType == TEST_TYPE_XFB_CLIPDISTANCE || m_parameters.testType == TEST_TYPE_XFB_CLIP_AND_CULL) && !features.shaderClipDistance)
1022                 TCU_THROW(NotSupportedError, std::string("shaderClipDistance feature is not supported"));
1023         if ((m_parameters.testType == TEST_TYPE_XFB_CULLDISTANCE || m_parameters.testType == TEST_TYPE_XFB_CLIP_AND_CULL) && !features.shaderCullDistance)
1024                 TCU_THROW(NotSupportedError, std::string("shaderCullDistance feature is not supported"));
1025         if (tfBuffersSupported < tfBuffersRequired)
1026                 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBuffers=" + de::toString(tfBuffersSupported) + ", while test requires " + de::toString(tfBuffersRequired)).c_str());
1027 }
1028
1029 void TransformFeedbackBuiltinTestInstance::verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc, const VkDeviceSize offset, const deUint32 bufBytes)
1030 {
1031         const DeviceInterface&  vk                      = m_context.getDeviceInterface();
1032         const VkDevice                  device          = m_context.getDevice();
1033
1034         invalidateAlloc(vk, device, *bufAlloc);
1035
1036         const deUint32                  numPoints       = bufBytes / static_cast<deUint32>(sizeof(float));
1037         const deUint8*                  tfDataBytes     = (deUint8*)bufAlloc->getHostPtr();
1038         const float*                    tfData          = (float*)&tfDataBytes[offset];
1039
1040         for (deUint32 i = 0; i < numPoints; ++i)
1041         {
1042                 const deUint32  divisor         = 32768u;
1043                 const float             epsilon         = 1.0f / float(divisor);
1044                 const float             expected        = float(i) / float(divisor);
1045
1046                 if (deAbs(tfData[i] - expected) > epsilon)
1047                         TCU_FAIL(std::string("Failed at item ") + de::toString(i) + " received:" + de::toString(tfData[i]) + " expected:" + de::toString(expected));
1048         }
1049 }
1050
1051 tcu::TestStatus TransformFeedbackBuiltinTestInstance::iterate (void)
1052 {
1053         const DeviceInterface&                          vk                                              = m_context.getDeviceInterface();
1054         const VkDevice                                          device                                  = m_context.getDevice();
1055         const deUint32                                          queueFamilyIndex                = m_context.getUniversalQueueFamilyIndex();
1056         const VkQueue                                           queue                                   = m_context.getUniversalQueue();
1057         Allocator&                                                      allocator                               = m_context.getDefaultAllocator();
1058
1059         const Unique<VkShaderModule>            vertexModule                    (createShaderModule                                             (vk, device, m_context.getBinaryCollection().get("vert"), 0u));
1060         const Unique<VkRenderPass>                      renderPass                              (makeRenderPass                                                 (vk, device, VK_FORMAT_UNDEFINED));
1061         const Unique<VkFramebuffer>                     framebuffer                             (makeFramebuffer                                                (vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
1062         const Unique<VkPipelineLayout>          pipelineLayout                  (TransformFeedback::makePipelineLayout  (vk, device));
1063         const Unique<VkPipeline>                        pipeline                                (makeGraphicsPipeline                                   (vk, device, *pipelineLayout, *renderPass, *vertexModule, DE_NULL, DE_NULL, DE_NULL, DE_NULL, m_imageExtent2D, 0u, &m_parameters.streamId));
1064         const Unique<VkCommandPool>                     cmdPool                                 (createCommandPool                                              (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1065         const Unique<VkCommandBuffer>           cmdBuffer                               (allocateCommandBuffer                                  (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1066
1067         const VkDeviceSize                                      tfBufSize                               = m_parameters.bufferSize * m_parameters.partCount;
1068         const VkBufferCreateInfo                        tfBufCreateInfo                 = makeBufferCreateInfo(tfBufSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
1069         const Move<VkBuffer>                            tfBuf                                   = createBuffer(vk, device, &tfBufCreateInfo);
1070         const std::vector<VkBuffer>                     tfBufArray                              = std::vector<VkBuffer>(m_parameters.partCount, *tfBuf);
1071         const MovePtr<Allocation>                       tfBufAllocation                 = allocator.allocate(getBufferMemoryRequirements(vk, device, *tfBuf), MemoryRequirement::HostVisible);
1072         const VkMemoryBarrier                           tfMemoryBarrier                 = makeMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, VK_ACCESS_HOST_READ_BIT);
1073         const std::vector<VkDeviceSize>         tfBufBindingSizes               = std::vector<VkDeviceSize>(m_parameters.partCount, m_parameters.bufferSize);
1074         const std::vector<VkDeviceSize>         tfBufBindingOffsets             = generateOffsetsList(tfBufBindingSizes);
1075         const deUint32                                          perVertexDataSize               = (m_parameters.testType == TEST_TYPE_XFB_POINTSIZE)    ? static_cast<deUint32>(sizeof(float))
1076                                                                                                                                 : (m_parameters.testType == TEST_TYPE_XFB_CLIPDISTANCE) ? static_cast<deUint32>(8u * sizeof(float))
1077                                                                                                                                 : (m_parameters.testType == TEST_TYPE_XFB_CULLDISTANCE) ? static_cast<deUint32>(8u * sizeof(float))
1078                                                                                                                                 : (m_parameters.testType == TEST_TYPE_XFB_CLIP_AND_CULL) ? static_cast<deUint32>(6u * sizeof(float))
1079                                                                                                                                 : 0u;
1080         const deUint32                                          numPoints                               = m_parameters.bufferSize / perVertexDataSize;
1081
1082         VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
1083
1084         beginCommandBuffer(vk, *cmdBuffer);
1085         {
1086                 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
1087                 {
1088                         vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1089
1090                         vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0, m_parameters.partCount, &tfBufArray[0], &tfBufBindingOffsets[0], &tfBufBindingSizes[0]);
1091
1092                         vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1093                         {
1094                                 vk.cmdDraw(*cmdBuffer, numPoints, 1u, 0u, 0u);
1095                         }
1096                         vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1097                 }
1098                 endRenderPass(vk, *cmdBuffer);
1099
1100                 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &tfMemoryBarrier, 0u, DE_NULL, 0u, DE_NULL);
1101         }
1102         endCommandBuffer(vk, *cmdBuffer);
1103         submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1104
1105         verifyTransformFeedbackBuffer(tfBufAllocation, tfBufBindingOffsets[m_parameters.partCount - 1], numPoints * perVertexDataSize);
1106
1107         return tcu::TestStatus::pass("Pass");
1108 }
1109
1110 class TransformFeedbackMultistreamTestInstance : public TransformFeedbackTestInstance
1111 {
1112 public:
1113                                                                 TransformFeedbackMultistreamTestInstance        (Context& context, const TestParameters& parameters);
1114
1115 protected:
1116         std::vector<VkDeviceSize>       generateSizesList                                                       (const size_t bufBytes, const size_t chunkCount);
1117         void                                            verifyTransformFeedbackBuffer                           (const MovePtr<Allocation>& bufAlloc, const deUint32 bufBytes);
1118         tcu::TestStatus                         iterate                                                                         (void);
1119 };
1120
1121 TransformFeedbackMultistreamTestInstance::TransformFeedbackMultistreamTestInstance (Context& context, const TestParameters& parameters)
1122         : TransformFeedbackTestInstance (context, parameters)
1123 {
1124         const InstanceInterface&                                                                vki                                                     = m_context.getInstanceInterface();
1125         const VkPhysicalDevice                                                                  physDevice                                      = m_context.getPhysicalDevice();
1126         const VkPhysicalDeviceFeatures                                                  features                                        = getPhysicalDeviceFeatures(vki, physDevice);
1127         const VkPhysicalDeviceTransformFeedbackFeaturesEXT&             transformFeedbackFeatures       = m_context.getTransformFeedbackFeaturesEXT();
1128         const deUint32                                                                                  streamsSupported                        = m_transformFeedbackProperties.maxTransformFeedbackStreams;
1129         const deUint32                                                                                  streamsRequired                         = m_parameters.streamId + 1;
1130         const deUint32                                                                                  tfBuffersSupported                      = m_transformFeedbackProperties.maxTransformFeedbackBuffers;
1131         const deUint32                                                                                  tfBuffersRequired                       = m_parameters.partCount;
1132         const deUint32                                                                                  bytesPerVertex                          = m_parameters.bufferSize / m_parameters.partCount;
1133         const deUint32                                                                                  tfStreamDataSizeSupported       = m_transformFeedbackProperties.maxTransformFeedbackStreamDataSize;
1134         const deUint32                                                                                  tfBufferDataSizeSupported       = m_transformFeedbackProperties.maxTransformFeedbackBufferDataSize;
1135         const deUint32                                                                                  tfBufferDataStrideSupported     = m_transformFeedbackProperties.maxTransformFeedbackBufferDataStride;
1136
1137         DE_ASSERT(m_parameters.partCount == 2u);
1138
1139         if (!features.geometryShader)
1140                 TCU_THROW(NotSupportedError, "Missing feature: geometryShader");
1141
1142         if (transformFeedbackFeatures.geometryStreams == DE_FALSE)
1143                 TCU_THROW(NotSupportedError, "geometryStreams feature is not supported");
1144
1145         if (streamsSupported < streamsRequired)
1146                 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackStreams=" + de::toString(streamsSupported) + ", while test requires " + de::toString(streamsRequired)).c_str());
1147
1148         if (tfBuffersSupported < tfBuffersRequired)
1149                 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBuffers=" + de::toString(tfBuffersSupported) + ", while test requires " + de::toString(tfBuffersRequired)).c_str());
1150
1151         if (tfStreamDataSizeSupported < bytesPerVertex)
1152                 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackStreamDataSize=" + de::toString(tfStreamDataSizeSupported) + ", while test requires " + de::toString(bytesPerVertex)).c_str());
1153
1154         if (tfBufferDataSizeSupported < bytesPerVertex)
1155                 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBufferDataSize=" + de::toString(tfBufferDataSizeSupported) + ", while test requires " + de::toString(bytesPerVertex)).c_str());
1156
1157         if (tfBufferDataStrideSupported < bytesPerVertex)
1158                 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBufferDataStride=" + de::toString(tfBufferDataStrideSupported) + ", while test requires " + de::toString(bytesPerVertex)).c_str());
1159 }
1160
1161 std::vector<VkDeviceSize> TransformFeedbackMultistreamTestInstance::generateSizesList (const size_t bufBytes, const size_t chunkCount)
1162 {
1163         const VkDeviceSize                      chunkSize       = bufBytes / chunkCount;
1164         std::vector<VkDeviceSize>       result          (chunkCount, chunkSize);
1165
1166         DE_ASSERT(chunkSize * chunkCount == bufBytes);
1167         DE_ASSERT(bufBytes <= MINIMUM_TF_BUFFER_SIZE);
1168         DE_ASSERT(bufBytes % sizeof(deUint32) == 0);
1169         DE_ASSERT(chunkCount > 0);
1170         DE_ASSERT(result.size() == chunkCount);
1171
1172         return result;
1173 }
1174
1175 void TransformFeedbackMultistreamTestInstance::verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc, const deUint32 bufBytes)
1176 {
1177         const DeviceInterface&  vk                      = m_context.getDeviceInterface();
1178         const VkDevice                  device          = m_context.getDevice();
1179
1180         invalidateAlloc(vk, device, *bufAlloc);
1181
1182         const deUint32                  numPoints       = static_cast<deUint32>(bufBytes / sizeof(deUint32));
1183         const float*                    tfData          = (float*)bufAlloc->getHostPtr();
1184
1185         for (deUint32 i = 0; i < numPoints; ++i)
1186                 if (tfData[i] != float(i))
1187                         TCU_FAIL(std::string("Failed at item ") + de::toString(float(i)) + " received:" + de::toString(tfData[i]) + " expected:" + de::toString(i));
1188 }
1189
1190 tcu::TestStatus TransformFeedbackMultistreamTestInstance::iterate (void)
1191 {
1192         const DeviceInterface&                          vk                                              = m_context.getDeviceInterface();
1193         const VkDevice                                          device                                  = m_context.getDevice();
1194         const deUint32                                          queueFamilyIndex                = m_context.getUniversalQueueFamilyIndex();
1195         const VkQueue                                           queue                                   = m_context.getUniversalQueue();
1196         Allocator&                                                      allocator                               = m_context.getDefaultAllocator();
1197
1198         const Unique<VkRenderPass>                      renderPass                              (makeRenderPass                                                 (vk, device, VK_FORMAT_UNDEFINED));
1199
1200         const Unique<VkShaderModule>            vertexModule                    (createShaderModule                                             (vk, device, m_context.getBinaryCollection().get("vert"), 0u));
1201         const Unique<VkShaderModule>            geomModule                              (createShaderModule                                             (vk, device, m_context.getBinaryCollection().get("geom"), 0u));
1202
1203         const Unique<VkFramebuffer>                     framebuffer                             (makeFramebuffer                                                (vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
1204         const Unique<VkPipelineLayout>          pipelineLayout                  (TransformFeedback::makePipelineLayout  (vk, device));
1205         const Unique<VkPipeline>                        pipeline                                (makeGraphicsPipeline                                   (vk, device, *pipelineLayout, *renderPass, *vertexModule, DE_NULL, DE_NULL, *geomModule, DE_NULL, m_imageExtent2D, 0u, &m_parameters.streamId));
1206         const Unique<VkCommandPool>                     cmdPool                                 (createCommandPool                                              (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1207         const Unique<VkCommandBuffer>           cmdBuffer                               (allocateCommandBuffer                                  (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1208
1209         const VkBufferCreateInfo                        tfBufCreateInfo                 = makeBufferCreateInfo(m_parameters.bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
1210         const Move<VkBuffer>                            tfBuf                                   = createBuffer(vk, device, &tfBufCreateInfo);
1211         const std::vector<VkBuffer>                     tfBufArray                              = std::vector<VkBuffer>(m_parameters.partCount, *tfBuf);
1212         const MovePtr<Allocation>                       tfBufAllocation                 = allocator.allocate(getBufferMemoryRequirements(vk, device, *tfBuf), MemoryRequirement::HostVisible);
1213         const VkMemoryBarrier                           tfMemoryBarrier                 = makeMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, VK_ACCESS_HOST_READ_BIT);
1214         const std::vector<VkDeviceSize>         tfBufBindingSizes               = generateSizesList(m_parameters.bufferSize, m_parameters.partCount);
1215         const std::vector<VkDeviceSize>         tfBufBindingOffsets             = generateOffsetsList(tfBufBindingSizes);
1216
1217         VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
1218
1219         beginCommandBuffer(vk, *cmdBuffer);
1220         {
1221                 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
1222                 {
1223                         vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1224
1225                         vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0u, m_parameters.partCount, &tfBufArray[0], &tfBufBindingOffsets[0], &tfBufBindingSizes[0]);
1226
1227                         vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1228                         {
1229                                 vk.cmdDraw(*cmdBuffer, 1u, 1u, 0u, 0u);
1230                         }
1231                         vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1232                 }
1233                 endRenderPass(vk, *cmdBuffer);
1234
1235                 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &tfMemoryBarrier, 0u, DE_NULL, 0u, DE_NULL);
1236         }
1237         endCommandBuffer(vk, *cmdBuffer);
1238         submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1239
1240         verifyTransformFeedbackBuffer(tfBufAllocation, m_parameters.bufferSize);
1241
1242         return tcu::TestStatus::pass("Pass");
1243 }
1244
1245 class TransformFeedbackStreamsTestInstance : public TransformFeedbackTestInstance
1246 {
1247 public:
1248                                                 TransformFeedbackStreamsTestInstance    (Context& context, const TestParameters& parameters);
1249
1250 protected:
1251         tcu::TestStatus         iterate                                                                 (void);
1252         bool                            verifyImage                                                             (const VkFormat imageFormat, const VkExtent2D& size, const void* resultData);
1253 };
1254
1255 TransformFeedbackStreamsTestInstance::TransformFeedbackStreamsTestInstance (Context& context, const TestParameters& parameters)
1256         : TransformFeedbackTestInstance (context, parameters)
1257 {
1258         const InstanceInterface&                                                                vki                                                     = m_context.getInstanceInterface();
1259         const VkPhysicalDevice                                                                  physDevice                                      = m_context.getPhysicalDevice();
1260         const VkPhysicalDeviceFeatures                                                  features                                        = getPhysicalDeviceFeatures(vki, physDevice);
1261         const VkPhysicalDeviceTransformFeedbackFeaturesEXT&             transformFeedbackFeatures       = m_context.getTransformFeedbackFeaturesEXT();
1262         const deUint32                                                                                  streamsSupported                        = m_transformFeedbackProperties.maxTransformFeedbackStreams;
1263         const deUint32                                                                                  streamsRequired                         = m_parameters.streamId + 1;
1264         const bool                                                                                              geomPointSizeRequired           = m_parameters.testType == TEST_TYPE_STREAMS_POINTSIZE;
1265
1266         if (!features.geometryShader)
1267                 TCU_THROW(NotSupportedError, "Missing feature: geometryShader");
1268
1269         if (transformFeedbackFeatures.geometryStreams == DE_FALSE)
1270                 TCU_THROW(NotSupportedError, "geometryStreams feature is not supported");
1271
1272         if (m_transformFeedbackProperties.transformFeedbackRasterizationStreamSelect == DE_FALSE)
1273                 TCU_THROW(NotSupportedError, "transformFeedbackRasterizationStreamSelect feature is not supported");
1274
1275         if (streamsSupported < streamsRequired)
1276                 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackStreams=" + de::toString(streamsSupported) + ", while test requires " + de::toString(streamsRequired)).c_str());
1277
1278         if (geomPointSizeRequired && !features.shaderTessellationAndGeometryPointSize)
1279                 TCU_THROW(NotSupportedError, "shaderTessellationAndGeometryPointSize feature is not supported");
1280 }
1281
1282 bool TransformFeedbackStreamsTestInstance::verifyImage (const VkFormat imageFormat, const VkExtent2D& size, const void* resultData)
1283 {
1284         const tcu::RGBA                         magentaRGBA             (tcu::RGBA(0xFF, 0x00, 0xFF, 0xFF));
1285         const tcu::Vec4                         magenta                 (magentaRGBA.toVec());
1286         const tcu::Vec4                         black                   (tcu::RGBA::black().toVec());
1287         const tcu::TextureFormat        textureFormat   (mapVkFormat(imageFormat));
1288         const int                                       dataSize                (size.width * size.height * textureFormat.getPixelSize());
1289         tcu::TextureLevel                       referenceImage  (textureFormat, size.width, size.height);
1290         tcu::PixelBufferAccess          referenceAccess (referenceImage.getAccess());
1291
1292         // Generate reference image
1293         if (m_parameters.testType == TEST_TYPE_STREAMS)
1294         {
1295                 for (int y = 0; y < referenceImage.getHeight(); ++y)
1296                 {
1297                         const tcu::Vec4&        validColor = y < referenceImage.getHeight() / 2 ? black : magenta;
1298
1299                         for (int x = 0; x < referenceImage.getWidth(); ++x)
1300                                 referenceAccess.setPixel(validColor, x, y);
1301                 }
1302         }
1303
1304         if (m_parameters.testType == TEST_TYPE_STREAMS_CLIPDISTANCE || m_parameters.testType == TEST_TYPE_STREAMS_CULLDISTANCE)
1305         {
1306                 for (int y = 0; y < referenceImage.getHeight(); ++y)
1307                         for (int x = 0; x < referenceImage.getWidth(); ++x)
1308                         {
1309                                 const tcu::Vec4&        validColor      = (y >= referenceImage.getHeight() / 2) && (x >= referenceImage.getWidth() / 2) ? magenta : black;
1310
1311                                 referenceAccess.setPixel(validColor, x, y);
1312                         }
1313         }
1314
1315         if (m_parameters.testType == TEST_TYPE_STREAMS_POINTSIZE)
1316         {
1317                 const int                       pointSize       = static_cast<int>(m_parameters.pointSize);
1318                 const tcu::Vec4&        validColor      = black;
1319
1320                 for (int y = 0; y < referenceImage.getHeight(); ++y)
1321                         for (int x = 0; x < referenceImage.getWidth(); ++x)
1322                                 referenceAccess.setPixel(validColor, x, y);
1323
1324                 referenceAccess.setPixel(magenta, (1 + referenceImage.getWidth()) / 4 - 1, (referenceImage.getHeight() * 3) / 4 - 1);
1325
1326                 for (int y = 0; y < pointSize; ++y)
1327                         for (int x = 0; x < pointSize; ++x)
1328                                 referenceAccess.setPixel(magenta, x + (referenceImage.getWidth() * 3) / 4 - 1, y + (referenceImage.getHeight() * 3) / 4 - 1);
1329         }
1330
1331         if (deMemCmp(resultData, referenceAccess.getDataPtr(), dataSize) != 0)
1332         {
1333                 const tcu::ConstPixelBufferAccess       resultImage     (textureFormat, size.width, size.height, 1, resultData);
1334                 bool                                                            ok;
1335
1336                 ok = tcu::intThresholdCompare(m_context.getTestContext().getLog(), "Image comparison", "", referenceAccess, resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT);
1337
1338                 return ok;
1339         }
1340
1341         return true;
1342 }
1343
1344 tcu::TestStatus TransformFeedbackStreamsTestInstance::iterate (void)
1345 {
1346         const DeviceInterface&                          vk                                      = m_context.getDeviceInterface();
1347         const VkDevice                                          device                          = m_context.getDevice();
1348         const deUint32                                          queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
1349         const VkQueue                                           queue                           = m_context.getUniversalQueue();
1350         Allocator&                                                      allocator                       = m_context.getDefaultAllocator();
1351
1352         const Unique<VkRenderPass>                      renderPass                      (makeRenderPass                 (vk, device, VK_FORMAT_R8G8B8A8_UNORM));
1353
1354         const Unique<VkShaderModule>            vertModule                      (createShaderModule             (vk, device, m_context.getBinaryCollection().get("vert"), 0u));
1355         const Unique<VkShaderModule>            geomModule                      (createShaderModule             (vk, device, m_context.getBinaryCollection().get("geom"), 0u));
1356         const Unique<VkShaderModule>            fragModule                      (createShaderModule             (vk, device, m_context.getBinaryCollection().get("frag"), 0u));
1357
1358         const VkFormat                                          colorFormat                     = VK_FORMAT_R8G8B8A8_UNORM;
1359         const VkImageUsageFlags                         imageUsageFlags         = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1360         const tcu::RGBA                                         clearColor                      (tcu::RGBA::black());
1361         const VkImageSubresourceRange           colorSubresRange        (makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u));
1362         const VkDeviceSize                                      colorBufferSize         (m_imageExtent2D.width * m_imageExtent2D.height * tcu::getPixelSize(mapVkFormat(colorFormat)));
1363         const Unique<VkImage>                           colorImage                      (makeImage                                                              (vk, device, makeImageCreateInfo(0u, VK_IMAGE_TYPE_2D, colorFormat, m_imageExtent2D, 1u, imageUsageFlags)));
1364         const UniquePtr<Allocation>                     colorImageAlloc         (bindImage                                                              (vk, device, allocator, *colorImage, MemoryRequirement::Any));
1365         const Unique<VkImageView>                       colorAttachment         (makeImageView                                                  (vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresRange));
1366         const Unique<VkBuffer>                          colorBuffer                     (makeBuffer                                                             (vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1367         const UniquePtr<Allocation>                     colorBufferAlloc        (bindBuffer                                                             (vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
1368
1369         const Unique<VkFramebuffer>                     framebuffer                     (makeFramebuffer                                                (vk, device, *renderPass, *colorAttachment, m_imageExtent2D.width, m_imageExtent2D.height));
1370         const Unique<VkPipelineLayout>          pipelineLayout          (TransformFeedback::makePipelineLayout  (vk, device));
1371         const Unique<VkPipeline>                        pipeline                        (makeGraphicsPipeline                                   (vk, device, *pipelineLayout, *renderPass, *vertModule, DE_NULL, DE_NULL, *geomModule, *fragModule, m_imageExtent2D, 0u, &m_parameters.streamId));
1372         const Unique<VkCommandPool>                     cmdPool                         (createCommandPool                                              (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1373         const Unique<VkCommandBuffer>           cmdBuffer                       (allocateCommandBuffer                                  (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1374
1375         const VkImageMemoryBarrier                      preCopyBarrier          = makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1376                                                                                                                                                                          VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1377                                                                                                                                                                          *colorImage, colorSubresRange);
1378         const VkBufferImageCopy                         region                          = makeBufferImageCopy(makeExtent3D(m_imageExtent2D.width, m_imageExtent2D.height, 1u),
1379                                                                                                                                                                   makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u));
1380         const VkBufferMemoryBarrier                     postCopyBarrier         = makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *colorBuffer, 0ull, VK_WHOLE_SIZE);
1381
1382         beginCommandBuffer(vk, *cmdBuffer);
1383         {
1384                 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D), clearColor.toVec());
1385                 {
1386                         vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1387
1388                         vk.cmdDraw(*cmdBuffer, 2u, 1u, 0u, 0u);
1389                 }
1390                 endRenderPass(vk, *cmdBuffer);
1391
1392                 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &preCopyBarrier);
1393                 vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, &region);
1394                 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &postCopyBarrier, DE_NULL, 0u);
1395         }
1396         endCommandBuffer(vk, *cmdBuffer);
1397         submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1398
1399         if (!verifyImage(colorFormat, m_imageExtent2D, colorBufferAlloc->getHostPtr()))
1400                 return tcu::TestStatus::fail("Fail");
1401
1402         return tcu::TestStatus::pass("Pass");
1403 }
1404
1405 class TransformFeedbackIndirectDrawTestInstance : public TransformFeedbackTestInstance
1406 {
1407 public:
1408                                                 TransformFeedbackIndirectDrawTestInstance       (Context& context, const TestParameters& parameters);
1409
1410 protected:
1411         tcu::TestStatus         iterate                                                                         (void);
1412         bool                            verifyImage                                                                     (const VkFormat imageFormat, const VkExtent2D& size, const void* resultData);
1413 };
1414
1415 TransformFeedbackIndirectDrawTestInstance::TransformFeedbackIndirectDrawTestInstance (Context& context, const TestParameters& parameters)
1416         : TransformFeedbackTestInstance (context, parameters)
1417 {
1418         const InstanceInterface&                vki                                                     = m_context.getInstanceInterface();
1419         const VkPhysicalDevice                  physDevice                                      = m_context.getPhysicalDevice();
1420         const VkPhysicalDeviceLimits    limits                                          = getPhysicalDeviceProperties(vki, physDevice).limits;
1421         const deUint32                                  tfBufferDataSizeSupported       = m_transformFeedbackProperties.maxTransformFeedbackBufferDataSize;
1422         const deUint32                                  tfBufferDataStrideSupported     = m_transformFeedbackProperties.maxTransformFeedbackBufferDataStride;
1423
1424         if (m_transformFeedbackProperties.transformFeedbackDraw == DE_FALSE)
1425                 TCU_THROW(NotSupportedError, "transformFeedbackDraw feature is not supported");
1426
1427         if (limits.maxVertexInputBindingStride < m_parameters.vertexStride)
1428                 TCU_THROW(NotSupportedError, std::string("maxVertexInputBindingStride=" + de::toString(limits.maxVertexInputBindingStride) + ", while test requires " + de::toString(m_parameters.vertexStride)).c_str());
1429
1430         if (tfBufferDataSizeSupported < m_parameters.vertexStride)
1431                 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBufferDataSize=" + de::toString(tfBufferDataSizeSupported) + ", while test requires " + de::toString(m_parameters.vertexStride)).c_str());
1432
1433         if (tfBufferDataStrideSupported < m_parameters.vertexStride)
1434                 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBufferDataStride=" + de::toString(tfBufferDataStrideSupported) + ", while test requires " + de::toString(m_parameters.vertexStride)).c_str());
1435 }
1436
1437 bool TransformFeedbackIndirectDrawTestInstance::verifyImage (const VkFormat imageFormat, const VkExtent2D& size, const void* resultData)
1438 {
1439         const tcu::Vec4                         white                   (tcu::RGBA::white().toVec());
1440         const tcu::TextureFormat        textureFormat   (mapVkFormat(imageFormat));
1441         const int                                       dataSize                (size.width * size.height * textureFormat.getPixelSize());
1442         tcu::TextureLevel                       referenceImage  (textureFormat, size.width, size.height);
1443         tcu::PixelBufferAccess          referenceAccess (referenceImage.getAccess());
1444
1445         // Generate reference image
1446         for (int y = 0; y < referenceImage.getHeight(); ++y)
1447                 for (int x = 0; x < referenceImage.getWidth(); ++x)
1448                         referenceAccess.setPixel(white, x, y);
1449
1450         if (deMemCmp(resultData, referenceAccess.getDataPtr(), dataSize) != 0)
1451         {
1452                 const tcu::ConstPixelBufferAccess       resultImage     (textureFormat, size.width, size.height, 1, resultData);
1453                 bool                                                            ok;
1454
1455                 ok = tcu::intThresholdCompare(m_context.getTestContext().getLog(), "Image comparison", "", referenceAccess, resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT);
1456
1457                 return ok;
1458         }
1459
1460         return true;
1461 }
1462
1463 tcu::TestStatus TransformFeedbackIndirectDrawTestInstance::iterate (void)
1464 {
1465         const DeviceInterface&                          vk                                      = m_context.getDeviceInterface();
1466         const VkDevice                                          device                          = m_context.getDevice();
1467         const deUint32                                          queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
1468         const VkQueue                                           queue                           = m_context.getUniversalQueue();
1469         Allocator&                                                      allocator                       = m_context.getDefaultAllocator();
1470
1471         const Unique<VkRenderPass>                      renderPass                      (makeRenderPass                 (vk, device, VK_FORMAT_R8G8B8A8_UNORM));
1472
1473         const Unique<VkShaderModule>            vertModule                      (createShaderModule             (vk, device, m_context.getBinaryCollection().get("vert"), 0u));
1474         const Unique<VkShaderModule>            fragModule                      (createShaderModule             (vk, device, m_context.getBinaryCollection().get("frag"), 0u));
1475
1476         const VkFormat                                          colorFormat                     = VK_FORMAT_R8G8B8A8_UNORM;
1477         const VkImageUsageFlags                         imageUsageFlags         = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1478         const tcu::RGBA                                         clearColor                      (tcu::RGBA::black());
1479         const VkImageSubresourceRange           colorSubresRange        (makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u));
1480         const VkDeviceSize                                      colorBufferSize         (m_imageExtent2D.width * m_imageExtent2D.height * tcu::getPixelSize(mapVkFormat(colorFormat)));
1481         const Unique<VkImage>                           colorImage                      (makeImage                              (vk, device, makeImageCreateInfo(0u, VK_IMAGE_TYPE_2D, colorFormat, m_imageExtent2D, 1u, imageUsageFlags)));
1482         const UniquePtr<Allocation>                     colorImageAlloc         (bindImage                              (vk, device, allocator, *colorImage, MemoryRequirement::Any));
1483         const Unique<VkImageView>                       colorAttachment         (makeImageView                  (vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresRange));
1484         const Unique<VkBuffer>                          colorBuffer                     (makeBuffer                             (vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1485         const UniquePtr<Allocation>                     colorBufferAlloc        (bindBuffer                             (vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
1486
1487         const deUint32                                          vertexCount                     = 6u;
1488         const VkDeviceSize                                      vertexBufferSize        = vertexCount * m_parameters.vertexStride;
1489         const VkBufferUsageFlags                        vertexBufferUsage       = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
1490         const Unique<VkBuffer>                          vertexBuffer            (makeBuffer                             (vk, device, vertexBufferSize, vertexBufferUsage));
1491         const UniquePtr<Allocation>                     vertexBufferAlloc       (bindBuffer                             (vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
1492         const VkDeviceSize                                      vertexBufferOffset      (0u);
1493         const float                                                     vertexBufferVals[]      =
1494                                                                                                                                 {
1495                                                                                                                                         -1.0f, -1.0f, 0.0f, 1.0f,
1496                                                                                                                                         -1.0f, +1.0f, 0.0f, 1.0f,
1497                                                                                                                                         +1.0f, -1.0f, 0.0f, 1.0f,
1498                                                                                                                                         -1.0f, +1.0f, 0.0f, 1.0f,
1499                                                                                                                                         +1.0f, -1.0f, 0.0f, 1.0f,
1500                                                                                                                                         +1.0f, +1.0f, 0.0f, 1.0f,
1501                                                                                                                                 };
1502
1503         const deUint32                                          counterBufferValue      = m_parameters.vertexStride * vertexCount;
1504         const VkDeviceSize                                      counterBufferSize       = sizeof(counterBufferValue);
1505         const VkBufferUsageFlags                        counterBufferUsage      = VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
1506         const Unique<VkBuffer>                          counterBuffer           (makeBuffer                                                             (vk, device, counterBufferSize, counterBufferUsage));
1507         const UniquePtr<Allocation>                     counterBufferAlloc      (bindBuffer                                                             (vk, device, allocator, *counterBuffer, MemoryRequirement::HostVisible));
1508
1509         const Unique<VkFramebuffer>                     framebuffer                     (makeFramebuffer                                                (vk, device, *renderPass, *colorAttachment, m_imageExtent2D.width, m_imageExtent2D.height));
1510         const Unique<VkPipelineLayout>          pipelineLayout          (TransformFeedback::makePipelineLayout  (vk, device));
1511         const Unique<VkPipeline>                        pipeline                        (makeGraphicsPipeline                                   (vk, device, *pipelineLayout, *renderPass, *vertModule, DE_NULL, DE_NULL, DE_NULL, *fragModule, m_imageExtent2D, 0u, DE_NULL, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, true));
1512         const Unique<VkCommandPool>                     cmdPool                         (createCommandPool                                              (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1513         const Unique<VkCommandBuffer>           cmdBuffer                       (allocateCommandBuffer                                  (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1514
1515         const VkImageMemoryBarrier                      preCopyBarrier          = makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1516                                                                                                                                                                          VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1517                                                                                                                                                                          *colorImage, colorSubresRange);
1518         const VkBufferImageCopy                         region                          = makeBufferImageCopy(makeExtent3D(m_imageExtent2D.width, m_imageExtent2D.height, 1u),
1519                                                                                                                                                                   makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u));
1520         const VkBufferMemoryBarrier                     postCopyBarrier         = makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *colorBuffer, 0ull, VK_WHOLE_SIZE);
1521
1522         fillBuffer(vk, device, *counterBufferAlloc, counterBufferSize, &counterBufferValue, counterBufferSize);
1523         fillBuffer(vk, device, *vertexBufferAlloc, vertexBufferSize, vertexBufferVals, sizeof(vertexBufferVals));
1524
1525         beginCommandBuffer(vk, *cmdBuffer);
1526         {
1527                 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D), clearColor.toVec());
1528                 {
1529                         vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &*vertexBuffer, &vertexBufferOffset);
1530
1531                         vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1532
1533                         vk.cmdDrawIndirectByteCountEXT(*cmdBuffer, 1u, 0u, *counterBuffer, 0u, 0u, m_parameters.vertexStride);
1534                 }
1535                 endRenderPass(vk, *cmdBuffer);
1536
1537                 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &preCopyBarrier);
1538                 vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, &region);
1539                 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &postCopyBarrier, DE_NULL, 0u);
1540         }
1541         endCommandBuffer(vk, *cmdBuffer);
1542         submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1543
1544         if (!verifyImage(colorFormat, m_imageExtent2D, colorBufferAlloc->getHostPtr()))
1545                 return tcu::TestStatus::fail("Fail");
1546
1547         return tcu::TestStatus::pass("Pass");
1548 }
1549
1550 class TransformFeedbackBackwardDependencyTestInstance : public TransformFeedbackTestInstance
1551 {
1552 public:
1553                                                                 TransformFeedbackBackwardDependencyTestInstance (Context& context, const TestParameters& parameters);
1554
1555 protected:
1556         tcu::TestStatus                         iterate                                                                                 (void);
1557         std::vector<VkDeviceSize>       generateSizesList                                                               (const size_t bufBytes, const size_t chunkCount);
1558 };
1559
1560 TransformFeedbackBackwardDependencyTestInstance::TransformFeedbackBackwardDependencyTestInstance (Context& context, const TestParameters& parameters)
1561         : TransformFeedbackTestInstance (context, parameters)
1562 {
1563         if (m_transformFeedbackProperties.transformFeedbackDraw == DE_FALSE)
1564                 TCU_THROW(NotSupportedError, "transformFeedbackDraw feature is not supported");
1565 }
1566
1567 std::vector<VkDeviceSize> TransformFeedbackBackwardDependencyTestInstance::generateSizesList (const size_t bufBytes, const size_t chunkCount)
1568 {
1569         const VkDeviceSize                      chunkSize       = bufBytes / chunkCount;
1570         std::vector<VkDeviceSize>       result          (chunkCount, chunkSize);
1571
1572         DE_ASSERT(chunkSize * chunkCount == bufBytes);
1573         DE_ASSERT(bufBytes <= MINIMUM_TF_BUFFER_SIZE);
1574         DE_ASSERT(bufBytes % sizeof(deUint32) == 0);
1575         DE_ASSERT(chunkCount > 0);
1576         DE_ASSERT(result.size() == chunkCount);
1577
1578         return result;
1579 }
1580
1581 tcu::TestStatus TransformFeedbackBackwardDependencyTestInstance::iterate (void)
1582 {
1583         const DeviceInterface&                          vk                                      = m_context.getDeviceInterface();
1584         const VkDevice                                          device                          = m_context.getDevice();
1585         const deUint32                                          queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
1586         const VkQueue                                           queue                           = m_context.getUniversalQueue();
1587         Allocator&                                                      allocator                       = m_context.getDefaultAllocator();
1588
1589         const Unique<VkShaderModule>            vertexModule            (createShaderModule                                             (vk, device, m_context.getBinaryCollection().get("vert"), 0u));
1590         const Unique<VkRenderPass>                      renderPass                      (TransformFeedback::makeRenderPass              (vk, device));
1591         const Unique<VkFramebuffer>                     framebuffer                     (makeFramebuffer                                                (vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
1592         const Unique<VkPipelineLayout>          pipelineLayout          (TransformFeedback::makePipelineLayout  (vk, device));
1593         const Unique<VkPipeline>                        pipeline                        (makeGraphicsPipeline                                   (vk, device, *pipelineLayout, *renderPass, *vertexModule, DE_NULL, DE_NULL, DE_NULL, DE_NULL, m_imageExtent2D, 0u));
1594         const Unique<VkCommandPool>                     cmdPool                         (createCommandPool                                              (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1595         const Unique<VkCommandBuffer>           cmdBuffer                       (allocateCommandBuffer                                  (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1596
1597         const VkBufferCreateInfo                        tfBufCreateInfo         = makeBufferCreateInfo(m_parameters.bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
1598         const Move<VkBuffer>                            tfBuf                           = createBuffer(vk, device, &tfBufCreateInfo);
1599         const MovePtr<Allocation>                       tfBufAllocation         = allocator.allocate(getBufferMemoryRequirements(vk, device, *tfBuf), MemoryRequirement::HostVisible);
1600         const VkMemoryBarrier                           tfMemoryBarrier         = makeMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, VK_ACCESS_HOST_READ_BIT);
1601         const VkDeviceSize                                      tfBufBindingSize        = m_parameters.bufferSize;
1602         const VkDeviceSize                                      tfBufBindingOffset      = 0ull;
1603
1604         const size_t                                            tfcBufSize                      = sizeof(deUint32);
1605         const VkBufferCreateInfo                        tfcBufCreateInfo        = makeBufferCreateInfo(tfcBufSize, VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT | VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT);
1606         const Move<VkBuffer>                            tfcBuf                          = createBuffer(vk, device, &tfcBufCreateInfo);
1607         const MovePtr<Allocation>                       tfcBufAllocation        = allocator.allocate(getBufferMemoryRequirements(vk, device, *tfcBuf), MemoryRequirement::Any);
1608         const VkDeviceSize                                      tfcBufBindingOffset     = 0ull;
1609         const VkMemoryBarrier                           tfcMemoryBarrier        = makeMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT, VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT);
1610
1611         const std::vector<VkDeviceSize>         chunkSizesList          = generateSizesList(m_parameters.bufferSize, m_parameters.partCount);
1612         const std::vector<VkDeviceSize>         chunkOffsetsList        = generateOffsetsList(chunkSizesList);
1613
1614         VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
1615         VK_CHECK(vk.bindBufferMemory(device, *tfcBuf, tfcBufAllocation->getMemory(), tfcBufAllocation->getOffset()));
1616
1617         DE_ASSERT(m_parameters.partCount == 2u);
1618
1619         beginCommandBuffer(vk, *cmdBuffer);
1620         {
1621                 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
1622                 {
1623                         vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1624
1625                         vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0, 1, &*tfBuf, &tfBufBindingOffset, &tfBufBindingSize);
1626
1627                         {
1628                                 const deUint32  startValue      = static_cast<deUint32>(chunkOffsetsList[0] / sizeof(deUint32));
1629                                 const deUint32  numPoints       = static_cast<deUint32>(chunkSizesList[0] / sizeof(deUint32));
1630
1631                                 vk.cmdPushConstants(*cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0u, sizeof(startValue), &startValue);
1632
1633                                 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1634                                 {
1635                                         vk.cmdDraw(*cmdBuffer, numPoints, 1u, 0u, 0u);
1636                                 }
1637                                 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 1, &*tfcBuf, m_parameters.noOffsetArray ? DE_NULL : &tfcBufBindingOffset);
1638                         }
1639
1640                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, 0u, 1u, &tfcMemoryBarrier, 0u, DE_NULL, DE_NULL, 0u);
1641
1642                         {
1643                                 const deUint32  startValue      = static_cast<deUint32>(chunkOffsetsList[1] / sizeof(deUint32));
1644
1645                                 vk.cmdPushConstants(*cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0u, sizeof(startValue), &startValue);
1646
1647                                 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 1, &*tfcBuf, m_parameters.noOffsetArray ? DE_NULL : &tfcBufBindingOffset);
1648                                 {
1649                                         vk.cmdDrawIndirectByteCountEXT(*cmdBuffer, 1u, 0u, *tfcBuf, 0u, 0u, 4u);
1650                                 }
1651                                 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1652                         }
1653
1654                 }
1655                 endRenderPass(vk, *cmdBuffer);
1656
1657                 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &tfMemoryBarrier, 0u, DE_NULL, 0u, DE_NULL);
1658         }
1659         endCommandBuffer(vk, *cmdBuffer);
1660         submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1661
1662         verifyTransformFeedbackBuffer(tfBufAllocation, m_parameters.bufferSize);
1663
1664         return tcu::TestStatus::pass("Pass");
1665 }
1666
1667
1668 class TransformFeedbackQueryTestInstance : public TransformFeedbackTestInstance
1669 {
1670 public:
1671                                                 TransformFeedbackQueryTestInstance      (Context& context, const TestParameters& parameters);
1672
1673 protected:
1674         tcu::TestStatus         iterate                                                         (void);
1675 };
1676
1677 TransformFeedbackQueryTestInstance::TransformFeedbackQueryTestInstance (Context& context, const TestParameters& parameters)
1678         : TransformFeedbackTestInstance (context, parameters)
1679 {
1680         const InstanceInterface&                                                                vki                                                     = m_context.getInstanceInterface();
1681         const VkPhysicalDevice                                                                  physDevice                                      = m_context.getPhysicalDevice();
1682         const VkPhysicalDeviceFeatures                                                  features                                        = getPhysicalDeviceFeatures(vki, physDevice);
1683         const VkPhysicalDeviceTransformFeedbackFeaturesEXT&             transformFeedbackFeatures       = m_context.getTransformFeedbackFeaturesEXT();
1684         const deUint32                                                                                  streamsSupported                        = m_transformFeedbackProperties.maxTransformFeedbackStreams;
1685         const deUint32                                                                                  streamsRequired                         = m_parameters.streamId + 1;
1686
1687         if (!features.geometryShader)
1688                 TCU_THROW(NotSupportedError, "Missing feature: geometryShader");
1689
1690         if (streamsRequired > 1 && transformFeedbackFeatures.geometryStreams == DE_FALSE)
1691                 TCU_THROW(NotSupportedError, "geometryStreams feature is not supported");
1692
1693         if (streamsSupported < streamsRequired)
1694                 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackStreams=" + de::toString(streamsSupported) + ", while test requires " + de::toString(streamsRequired)).c_str());
1695
1696         if (m_transformFeedbackProperties.transformFeedbackQueries == DE_FALSE)
1697                 TCU_THROW(NotSupportedError, "transformFeedbackQueries feature is not supported");
1698
1699         if (m_parameters.testType == TEST_TYPE_QUERY_RESET)
1700         {
1701                 // Check VK_EXT_host_query_reset is supported
1702                 m_context.requireDeviceFunctionality("VK_EXT_host_query_reset");
1703                 if(m_context.getHostQueryResetFeatures().hostQueryReset == VK_FALSE)
1704                         throw tcu::NotSupportedError(std::string("Implementation doesn't support resetting queries from the host").c_str());
1705         }
1706 }
1707
1708 tcu::TestStatus TransformFeedbackQueryTestInstance::iterate (void)
1709 {
1710         const DeviceInterface&                          vk                                              = m_context.getDeviceInterface();
1711         const VkDevice                                          device                                  = m_context.getDevice();
1712         const deUint32                                          queueFamilyIndex                = m_context.getUniversalQueueFamilyIndex();
1713         const VkQueue                                           queue                                   = m_context.getUniversalQueue();
1714         Allocator&                                                      allocator                               = m_context.getDefaultAllocator();
1715
1716         const deUint64                                          overflowVertices                = 3u;
1717         const deUint32                                          bytesPerVertex                  = static_cast<deUint32>(4 * sizeof(float));
1718         const deUint64                                          numVerticesInBuffer             = m_parameters.bufferSize / bytesPerVertex;
1719         const deUint64                                          numVerticesToWrite              = numVerticesInBuffer + overflowVertices;
1720         const Unique<VkRenderPass>                      renderPass                              (makeRenderPass                                                 (vk, device, VK_FORMAT_UNDEFINED));
1721
1722         const Unique<VkShaderModule>            vertModule                              (createShaderModule                                             (vk, device, m_context.getBinaryCollection().get("vert"), 0u));
1723         const Unique<VkShaderModule>            geomModule                              (createShaderModule                                             (vk, device, m_context.getBinaryCollection().get("geom"), 0u));
1724
1725         const Unique<VkFramebuffer>                     framebuffer                             (makeFramebuffer                                                (vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
1726         const Unique<VkPipelineLayout>          pipelineLayout                  (TransformFeedback::makePipelineLayout  (vk, device));
1727         const Unique<VkPipeline>                        pipeline                                (makeGraphicsPipeline                                   (vk, device, *pipelineLayout, *renderPass, *vertModule, DE_NULL, DE_NULL, *geomModule, DE_NULL, m_imageExtent2D, 0u, &m_parameters.streamId, m_parameters.primTopology));
1728         const Unique<VkCommandPool>                     cmdPool                                 (createCommandPool                                              (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1729         const Unique<VkCommandBuffer>           cmdBuffer                               (allocateCommandBuffer                                  (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1730
1731         const deUint32                                          tfBufferSize                    = (deUint32)topologyData.at(m_parameters.primTopology).getNumPrimitives(numVerticesInBuffer) * (deUint32)topologyData.at(m_parameters.primTopology).primSize * bytesPerVertex;
1732         const VkBufferCreateInfo                        tfBufCreateInfo                 = makeBufferCreateInfo(tfBufferSize, VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
1733         const Move<VkBuffer>                            tfBuf                                   = createBuffer(vk, device, &tfBufCreateInfo);
1734         const MovePtr<Allocation>                       tfBufAllocation                 = bindBuffer(vk, device, allocator, *tfBuf, MemoryRequirement::HostVisible);
1735         const VkDeviceSize                                      tfBufBindingSize                = tfBufferSize;
1736         const VkDeviceSize                                      tfBufBindingOffset              = 0ull;
1737
1738         const size_t                                            queryResultWidth                = (m_parameters.query64bits ? sizeof(deUint64) : sizeof(deUint32));
1739         const vk::VkQueryControlFlags           queryExtraFlags                 = (m_parameters.query64bits ? vk::VK_QUERY_RESULT_64_BIT : 0);
1740         const deUint32                                          queryCountersNumber             = 1u;
1741         const deUint32                                          queryIndex                              = 0u;
1742         constexpr deUint32                                      queryResultElements             = 2u;
1743         const deUint32                                          queryDataSize                   = static_cast<deUint32>(queryResultElements * queryResultWidth);
1744         const VkQueryPoolCreateInfo                     queryPoolCreateInfo             = makeQueryPoolCreateInfo(queryCountersNumber);
1745         const Unique<VkQueryPool>                       queryPool                               (createQueryPool(vk, device, &queryPoolCreateInfo));
1746
1747         Move<VkBuffer>                                          queryPoolResultsBuffer;
1748         de::MovePtr<Allocation>                         queryPoolResultsBufferAlloc;
1749
1750         tcu::TestLog&                                           log                                             = m_context.getTestContext().getLog();
1751
1752         DE_ASSERT(numVerticesInBuffer * bytesPerVertex == m_parameters.bufferSize);
1753
1754         if (m_parameters.testType == TEST_TYPE_QUERY_COPY)
1755         {
1756                 const VkBufferCreateInfo bufferParams =
1757                 {
1758                         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,       // VkStructureType      sType;
1759                         DE_NULL,                                    // const void*          pNext;
1760                         0u,                                         // VkBufferCreateFlags  flags;
1761                         queryDataSize,                              // VkDeviceSize         size;
1762                         VK_BUFFER_USAGE_TRANSFER_DST_BIT,           // VkBufferUsageFlags   usage;
1763                         VK_SHARING_MODE_EXCLUSIVE,                  // VkSharingMode        sharingMode;
1764                         1u,                                         // deUint32             queueFamilyCount;
1765                         &queueFamilyIndex                           // const deUint32*      pQueueFamilyIndices;
1766                 };
1767
1768                 queryPoolResultsBuffer = createBuffer(vk, device, &bufferParams);
1769                 queryPoolResultsBufferAlloc = allocator.allocate(getBufferMemoryRequirements(vk, device, *queryPoolResultsBuffer), MemoryRequirement::HostVisible);
1770
1771                 VK_CHECK(vk.bindBufferMemory(device, *queryPoolResultsBuffer, queryPoolResultsBufferAlloc->getMemory(), queryPoolResultsBufferAlloc->getOffset()));
1772         }
1773
1774         beginCommandBuffer(vk, *cmdBuffer);
1775         {
1776                 if (m_parameters.testType != TEST_TYPE_QUERY_RESET)
1777                         vk.cmdResetQueryPool(*cmdBuffer, *queryPool, queryIndex, queryCountersNumber);
1778
1779                 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
1780                 {
1781                         vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1782
1783                         vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0u, 1u, &*tfBuf, &tfBufBindingOffset, &tfBufBindingSize);
1784
1785                         if (m_parameters.streamId == 0 && m_parameters.streamId0Mode != STREAM_ID_0_BEGIN_QUERY_INDEXED)
1786                                 vk.cmdBeginQuery(*cmdBuffer, *queryPool, queryIndex, 0u);
1787                         else
1788                                 vk.cmdBeginQueryIndexedEXT(*cmdBuffer, *queryPool, queryIndex, 0u, m_parameters.streamId);
1789                         {
1790                                 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1791                                 {
1792                                         vk.cmdDraw(*cmdBuffer, static_cast<deUint32>(numVerticesToWrite), 1u, 0u, 0u);
1793                                 }
1794                                 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1795                         }
1796                         if (m_parameters.streamId == 0 && m_parameters.streamId0Mode != STREAM_ID_0_END_QUERY_INDEXED)
1797                                 vk.cmdEndQuery(*cmdBuffer, *queryPool, queryIndex);
1798                         else
1799                                 vk.cmdEndQueryIndexedEXT(*cmdBuffer, *queryPool, queryIndex, m_parameters.streamId);
1800                 }
1801                 endRenderPass(vk, *cmdBuffer);
1802
1803                 if (m_parameters.testType == TEST_TYPE_QUERY_COPY)
1804                 {
1805                         vk.cmdCopyQueryPoolResults(*cmdBuffer, *queryPool, queryIndex, queryCountersNumber, *queryPoolResultsBuffer, 0u, queryDataSize, (vk::VK_QUERY_RESULT_WAIT_BIT | queryExtraFlags));
1806
1807                         const VkBufferMemoryBarrier bufferBarrier =
1808                         {
1809                                 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,        // VkStructureType      sType;
1810                                 DE_NULL,                                                                        // const void*          pNext;
1811                                 VK_ACCESS_TRANSFER_WRITE_BIT,                           // VkAccessFlags        srcAccessMask;
1812                                 VK_ACCESS_HOST_READ_BIT,                                        // VkAccessFlags        dstAccessMask;
1813                                 VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                     srcQueueFamilyIndex;
1814                                 VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                     dstQueueFamilyIndex;
1815                                 *queryPoolResultsBuffer,                                        // VkBuffer                     buffer;
1816                                 0ull,                                                                           // VkDeviceSize         offset;
1817                                 VK_WHOLE_SIZE                                                           // VkDeviceSize         size;
1818                         };
1819                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
1820                 }
1821
1822         }
1823         endCommandBuffer(vk, *cmdBuffer);
1824
1825         if (m_parameters.testType == TEST_TYPE_QUERY_RESET)
1826                 vk.resetQueryPool(device, *queryPool, queryIndex, queryCountersNumber);
1827         submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1828
1829         {
1830                 union Results
1831                 {
1832                         deUint32        elements32[queryResultElements];
1833                         deUint64        elements64[queryResultElements];
1834                 };
1835
1836                 std::vector<deUint8>    queryData               (queryDataSize, 0u);
1837                 const Results*                  queryResults    = reinterpret_cast<Results*>(queryData.data());
1838
1839                 if (m_parameters.testType != TEST_TYPE_QUERY_COPY)
1840                 {
1841                         vk.getQueryPoolResults(device, *queryPool, queryIndex, queryCountersNumber, queryDataSize, queryData.data(), queryDataSize, (vk::VK_QUERY_RESULT_WAIT_BIT | queryExtraFlags));
1842                 }
1843                 else
1844                 {
1845                         invalidateAlloc(vk, device, *queryPoolResultsBufferAlloc);
1846                         deMemcpy(queryData.data(), queryPoolResultsBufferAlloc->getHostPtr(), queryData.size());
1847                 }
1848
1849                 // The number of primitives successfully written to the corresponding transform feedback buffer.
1850                 const deUint64  numPrimitivesWritten    = (m_parameters.query64bits ? queryResults->elements64[0] : queryResults->elements32[0]);
1851
1852                 // The number of primitives output to the vertex stream.
1853                 const deUint64  numPrimitivesNeeded             = (m_parameters.query64bits ? queryResults->elements64[1] : queryResults->elements32[1]);
1854
1855                 // Count how many primitives we should get by using selected topology.
1856                 const auto              primitivesInBuffer              = topologyData.at(m_parameters.primTopology).getNumPrimitives(numVerticesInBuffer);
1857                 const auto              primitivesToWrite               = topologyData.at(m_parameters.primTopology).getNumPrimitives(numVerticesToWrite);
1858
1859                 log << tcu::TestLog::Message << "Primitives Written / Expected :  " << de::toString(numPrimitivesWritten) << " / " << de::toString(primitivesInBuffer) << tcu::TestLog::EndMessage;
1860                 log << tcu::TestLog::Message << "Primitives  Needed / Expected :  " << de::toString(numPrimitivesNeeded) << " / " << de::toString(primitivesToWrite) << tcu::TestLog::EndMessage;
1861
1862                 if (numPrimitivesWritten != primitivesInBuffer)
1863                         return tcu::TestStatus::fail("numPrimitivesWritten=" + de::toString(numPrimitivesWritten) + " while expected " + de::toString(primitivesInBuffer));
1864
1865                 if (numPrimitivesNeeded != primitivesToWrite)
1866                         return tcu::TestStatus::fail("numPrimitivesNeeded=" + de::toString(numPrimitivesNeeded) + " while expected " + de::toString(primitivesToWrite));
1867         }
1868
1869         if (m_parameters.testType == TEST_TYPE_QUERY_RESET)
1870         {
1871                 constexpr deUint32              queryResetElements              = queryResultElements + 1; // For the availability bit.
1872
1873                 union Results
1874                 {
1875                         deUint32        elements32[queryResetElements];
1876                         deUint64        elements64[queryResetElements];
1877                 };
1878
1879                 const deUint32                  queryDataAvailSize              (static_cast<deUint32>(queryResetElements * queryResultWidth));
1880                 std::vector<deUint8>    queryData                               (queryDataAvailSize, 0u);
1881                 Results*                                queryResults                    = reinterpret_cast<Results*>(queryData.data());
1882
1883                 // Initialize values
1884                 if (m_parameters.query64bits)
1885                 {
1886                         queryResults->elements64[0] = 1u;       // numPrimitivesWritten
1887                         queryResults->elements64[1] = 1u;       // numPrimitivesNeeded
1888                         queryResults->elements64[2] = 1u;       // Availability bit
1889                 }
1890                 else
1891                 {
1892                         queryResults->elements32[0] = 1u;       // numPrimitivesWritten
1893                         queryResults->elements32[1] = 1u;       // numPrimitivesNeeded
1894                         queryResults->elements32[2] = 1u;       // Availability bit
1895                 }
1896
1897                 vk.resetQueryPool(device, *queryPool, queryIndex, queryCountersNumber);
1898
1899                 vk::VkResult    res                                             = vk.getQueryPoolResults(device, *queryPool, queryIndex, queryCountersNumber, queryDataAvailSize, queryData.data(), queryDataAvailSize, (vk::VK_QUERY_RESULT_WITH_AVAILABILITY_BIT | queryExtraFlags));
1900                 const deUint64  numPrimitivesWritten    = (m_parameters.query64bits ? queryResults->elements64[0] : queryResults->elements32[0]);
1901                 const deUint64  numPrimitivesNeeded             = (m_parameters.query64bits ? queryResults->elements64[1] : queryResults->elements32[1]);
1902                 const deUint64  availabilityState               = (m_parameters.query64bits ? queryResults->elements64[2] : queryResults->elements32[2]);
1903
1904                 /* From the Vulkan spec:
1905                         *
1906                         * If VK_QUERY_RESULT_WAIT_BIT and VK_QUERY_RESULT_PARTIAL_BIT are both not set then no result values are written to pData
1907                         * for queries that are in the unavailable state at the time of the call, and vkGetQueryPoolResults returns VK_NOT_READY.
1908                         * However, availability state is still written to pData for those queries if VK_QUERY_RESULT_WITH_AVAILABILITY_BIT is set.
1909                         */
1910                 if (res != vk::VK_NOT_READY || availabilityState != 0u)
1911                         return tcu::TestStatus::fail("QueryPoolResults incorrect reset");
1912             if (numPrimitivesWritten != 1u || numPrimitivesNeeded != 1u)
1913                         return tcu::TestStatus::fail("QueryPoolResults data was modified");
1914
1915         }
1916
1917         return tcu::TestStatus::pass("Pass");
1918 }
1919
1920 class TransformFeedbackMultiQueryTestInstance : public TransformFeedbackTestInstance
1921 {
1922 public:
1923                                                                 TransformFeedbackMultiQueryTestInstance (Context& context, const TestParameters& parameters);
1924
1925 protected:
1926         std::vector<VkDeviceSize>       generateSizesList                                                       (const size_t bufBytes, const size_t chunkCount);
1927         void                                            verifyTransformFeedbackBuffer                           (const MovePtr<Allocation>& bufAlloc, const deUint32 bufBytes, const deUint32 bufOffset, const float expected);
1928         tcu::TestStatus                         iterate                                                                         (void);
1929 };
1930
1931 TransformFeedbackMultiQueryTestInstance::TransformFeedbackMultiQueryTestInstance (Context& context, const TestParameters& parameters)
1932         : TransformFeedbackTestInstance (context, parameters)
1933 {
1934         const InstanceInterface&                                                                vki                                                     = m_context.getInstanceInterface();
1935         const VkPhysicalDevice                                                                  physDevice                                      = m_context.getPhysicalDevice();
1936         const VkPhysicalDeviceFeatures                                                  features                                        = getPhysicalDeviceFeatures(vki, physDevice);
1937         const VkPhysicalDeviceTransformFeedbackFeaturesEXT&             transformFeedbackFeatures       = m_context.getTransformFeedbackFeaturesEXT();
1938         const deUint32                                                                                  streamsSupported                        = m_transformFeedbackProperties.maxTransformFeedbackStreams;
1939         const deUint32                                                                                  streamsRequired                         = m_parameters.streamId + 1;
1940         const deUint32                                                                                  tfBuffersSupported                      = m_transformFeedbackProperties.maxTransformFeedbackBuffers;
1941         const deUint32                                                                                  tfBuffersRequired                       = m_parameters.partCount;
1942         const deUint32                                                                                  bytesPerVertex                          = m_parameters.bufferSize / m_parameters.partCount;
1943         const deUint32                                                                                  tfStreamDataSizeSupported       = m_transformFeedbackProperties.maxTransformFeedbackStreamDataSize;
1944         const deUint32                                                                                  tfBufferDataSizeSupported       = m_transformFeedbackProperties.maxTransformFeedbackBufferDataSize;
1945         const deUint32                                                                                  tfBufferDataStrideSupported     = m_transformFeedbackProperties.maxTransformFeedbackBufferDataStride;
1946
1947         DE_ASSERT(m_parameters.partCount == 2u);
1948
1949         if (!features.geometryShader)
1950                 TCU_THROW(NotSupportedError, "Missing feature: geometryShader");
1951
1952         if (transformFeedbackFeatures.geometryStreams == DE_FALSE)
1953                 TCU_THROW(NotSupportedError, "geometryStreams feature is not supported");
1954
1955         if (streamsSupported < streamsRequired)
1956                 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackStreams=" + de::toString(streamsSupported) + ", while test requires " + de::toString(streamsRequired)).c_str());
1957
1958         if (tfBuffersSupported < tfBuffersRequired)
1959                 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBuffers=" + de::toString(tfBuffersSupported) + ", while test requires " + de::toString(tfBuffersRequired)).c_str());
1960
1961         if (tfStreamDataSizeSupported < bytesPerVertex)
1962                 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackStreamDataSize=" + de::toString(tfStreamDataSizeSupported) + ", while test requires " + de::toString(bytesPerVertex)).c_str());
1963
1964         if (tfBufferDataSizeSupported < bytesPerVertex)
1965                 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBufferDataSize=" + de::toString(tfBufferDataSizeSupported) + ", while test requires " + de::toString(bytesPerVertex)).c_str());
1966
1967         if (tfBufferDataStrideSupported < bytesPerVertex)
1968                 TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBufferDataStride=" + de::toString(tfBufferDataStrideSupported) + ", while test requires " + de::toString(bytesPerVertex)).c_str());
1969
1970         if (m_transformFeedbackProperties.transformFeedbackQueries == DE_FALSE)
1971                 TCU_THROW(NotSupportedError, "transformFeedbackQueries feature is not supported");
1972 }
1973
1974 std::vector<VkDeviceSize> TransformFeedbackMultiQueryTestInstance::generateSizesList (const size_t bufBytes, const size_t chunkCount)
1975 {
1976         const VkDeviceSize                      chunkSize       = bufBytes / chunkCount;
1977         std::vector<VkDeviceSize>       result          (chunkCount, chunkSize);
1978
1979         DE_ASSERT(chunkSize * chunkCount == bufBytes);
1980         DE_ASSERT(bufBytes <= MINIMUM_TF_BUFFER_SIZE);
1981         DE_ASSERT(bufBytes % sizeof(deUint32) == 0);
1982         DE_ASSERT(chunkCount > 0);
1983         DE_ASSERT(result.size() == chunkCount);
1984
1985         return result;
1986 }
1987
1988 void TransformFeedbackMultiQueryTestInstance::verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc, const deUint32 bufBytes, const deUint32 bufOffset, const float expected)
1989 {
1990         const DeviceInterface&  vk                      = m_context.getDeviceInterface();
1991         const VkDevice                  device          = m_context.getDevice();
1992
1993         invalidateAlloc(vk, device, *bufAlloc);
1994
1995         const deUint32                  numPoints       = bufBytes / static_cast<deUint32>(sizeof(float));
1996         const deUint8*                  tfDataRaw       = reinterpret_cast<const deUint8*>(bufAlloc->getHostPtr());
1997         const float*                    tfData          = reinterpret_cast<const float*>(&tfDataRaw[bufOffset]);
1998
1999         for (deUint32 i = 0; i < numPoints; ++i)
2000                 if (tfData[i] != expected)
2001                         TCU_FAIL(std::string("Failed at item ") + de::toString(i) + " received:" + de::toString(tfData[i]) + " expected:" + de::toString(expected));
2002 }
2003
2004 tcu::TestStatus TransformFeedbackMultiQueryTestInstance::iterate (void)
2005 {
2006         const DeviceInterface&                                          vk                                                      = m_context.getDeviceInterface();
2007         const VkDevice                                                          device                                          = m_context.getDevice();
2008         const deUint32                                                          queueFamilyIndex                        = m_context.getUniversalQueueFamilyIndex();
2009         const std::vector<deUint32>                                     queueFamilyIndices                      = { queueFamilyIndex };
2010         const VkQueue                                                           queue                                           = m_context.getUniversalQueue();
2011         Allocator&                                                                      allocator                                       = m_context.getDefaultAllocator();
2012
2013         const Unique<VkRenderPass>                                      renderPass                                      (makeRenderPass                                                 (vk, device, VK_FORMAT_UNDEFINED));
2014
2015         const Unique<VkShaderModule>                            vertModule                                      (createShaderModule                                             (vk, device, m_context.getBinaryCollection().get("vert"), 0u));
2016         const Unique<VkShaderModule>                            geomModule                                      (createShaderModule                                             (vk, device, m_context.getBinaryCollection().get("geom"), 0u));
2017
2018         const Unique<VkFramebuffer>                                     framebuffer                                     (makeFramebuffer                                                (vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
2019         const Unique<VkPipelineLayout>                          pipelineLayout                          (TransformFeedback::makePipelineLayout  (vk, device));
2020         const Unique<VkPipeline>                                        pipeline                                        (makeGraphicsPipeline                                   (vk, device, *pipelineLayout, *renderPass, *vertModule, DE_NULL, DE_NULL, *geomModule, DE_NULL, m_imageExtent2D, 0u));
2021         const Unique<VkCommandPool>                                     cmdPool                                         (createCommandPool                                              (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
2022         const Unique<VkCommandBuffer>                           cmdBuffer                                       (allocateCommandBuffer                                  (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
2023
2024         const VkBufferCreateInfo                                        tfBufCreateInfo                         = makeBufferCreateInfo(m_parameters.bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
2025         const Move<VkBuffer>                                            tfBuf                                           = createBuffer(vk, device, &tfBufCreateInfo);
2026         const std::vector<VkBuffer>                                     tfBufArray                                      = std::vector<VkBuffer>(m_parameters.partCount, *tfBuf);
2027         const MovePtr<Allocation>                                       tfBufAllocation                         = allocator.allocate(getBufferMemoryRequirements(vk, device, *tfBuf), MemoryRequirement::HostVisible);
2028         const VkMemoryBarrier                                           tfMemoryBarrier                         = makeMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, VK_ACCESS_HOST_READ_BIT);
2029         const std::vector<VkDeviceSize>                         tfBufBindingSizes                       = generateSizesList(m_parameters.bufferSize, m_parameters.partCount);
2030         const std::vector<VkDeviceSize>                         tfBufBindingOffsets                     = generateOffsetsList(tfBufBindingSizes);
2031         const std::vector<float>                                        tfBufExpectedValues                     = { 0.5f, 0.5f + float(m_parameters.streamId) };
2032         const deUint32                                                          maxBufferSizeBytes                      = static_cast<deUint32>(*std::max_element(tfBufBindingSizes.begin(), tfBufBindingSizes.end()));
2033         const deUint32                                                          bytesPerVertex                          = static_cast<deUint32>(4 * sizeof(float));
2034         const deUint32                                                          numVerticesInBuffer                     = maxBufferSizeBytes / bytesPerVertex;
2035         const deUint32                                                          numDrawVertices                         = numVerticesInBuffer / 2;
2036
2037         const deUint32                                                          queryIndex                                      = 0u;
2038         const deUint32                                                          queryCountersNumber                     = 2u;
2039         const deUint32                                                          queryStride                                     = sizeof(TransformFeedbackQuery);
2040         const deUint32                                                          queryDataSize                           = queryCountersNumber * queryStride;
2041         const VkQueryPoolCreateInfo                                     queryPoolCreateInfo                     = makeQueryPoolCreateInfo(queryCountersNumber);
2042         const Unique<VkQueryPool>                                       queryPool                                       (createQueryPool(vk, device, &queryPoolCreateInfo));
2043         const deUint32                                                          queryInvalidCounterValue        = 999999u;
2044         std::vector<TransformFeedbackQuery>                     queryResultData                         (queryCountersNumber, TransformFeedbackQuery{ queryInvalidCounterValue, queryInvalidCounterValue });
2045         const std::vector<TransformFeedbackQuery>       queryExpectedData                       ({ TransformFeedbackQuery{ numVerticesInBuffer, 3 * numDrawVertices }, TransformFeedbackQuery{ numDrawVertices, numDrawVertices } });
2046
2047         const VkBufferCreateInfo                                        queryBufferCreateInfo           = makeBufferCreateInfo(queryDataSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT, queueFamilyIndices);
2048         const Move<VkBuffer>                                            queryPoolResultsBuffer          = createBuffer(vk, device, &queryBufferCreateInfo);
2049         const MovePtr<Allocation>                                       queryPoolResultsBufferAlloc     = allocator.allocate(getBufferMemoryRequirements(vk, device, *queryPoolResultsBuffer), MemoryRequirement::HostVisible);
2050
2051     vk.resetQueryPool(device, *queryPool, queryIndex, queryCountersNumber);
2052
2053         DE_ASSERT(queryCountersNumber == queryExpectedData.size());
2054
2055         VK_CHECK(vk.bindBufferMemory(device, *queryPoolResultsBuffer, queryPoolResultsBufferAlloc->getMemory(), queryPoolResultsBufferAlloc->getOffset()));
2056
2057         VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
2058
2059         beginCommandBuffer(vk, *cmdBuffer);
2060         {
2061                 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
2062                 {
2063                         vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
2064
2065                         vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0u, m_parameters.partCount, &tfBufArray[0], &tfBufBindingOffsets[0], &tfBufBindingSizes[0]);
2066
2067                         vk.cmdBeginQueryIndexedEXT(*cmdBuffer, *queryPool, queryIndex + 0, 0u, 0u);
2068                         vk.cmdBeginQueryIndexedEXT(*cmdBuffer, *queryPool, queryIndex + 1, 0u, m_parameters.streamId);
2069                         {
2070                                 vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
2071                                 {
2072                                         vk.cmdDraw(*cmdBuffer, numDrawVertices, 1u, 0u, 0u);
2073                                 }
2074                                 vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
2075                         }
2076                         vk.cmdEndQueryIndexedEXT(*cmdBuffer, *queryPool, queryIndex + 1, m_parameters.streamId);
2077                         vk.cmdEndQueryIndexedEXT(*cmdBuffer, *queryPool, queryIndex + 0, 0);
2078                 }
2079                 endRenderPass(vk, *cmdBuffer);
2080
2081                 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &tfMemoryBarrier, 0u, DE_NULL, 0u, DE_NULL);
2082         }
2083         endCommandBuffer(vk, *cmdBuffer);
2084         submitCommandsAndWait(vk, device, queue, *cmdBuffer);
2085
2086         vk.getQueryPoolResults(device, *queryPool, queryIndex, queryCountersNumber, queryDataSize, queryResultData.data(), queryStride, (vk::VK_QUERY_RESULT_WAIT_BIT));
2087
2088         DE_ASSERT(queryResultData.size() == queryCountersNumber && queryExpectedData.size() == queryCountersNumber);
2089         DE_ASSERT(queryCountersNumber > 0);
2090
2091         for (size_t counterNdx = 0; counterNdx < queryCountersNumber; ++counterNdx)
2092         {
2093                 const TransformFeedbackQuery&   result          = queryResultData[counterNdx];
2094                 const TransformFeedbackQuery&   expected        = queryExpectedData[counterNdx];
2095
2096                 DE_ASSERT(expected.written != queryInvalidCounterValue);
2097                 DE_ASSERT(expected.attempts != queryInvalidCounterValue);
2098
2099                 if (result.written == queryInvalidCounterValue || result.attempts == queryInvalidCounterValue)
2100                         return tcu::TestStatus::fail("Query counters read failed");
2101
2102                 if (result.written != expected.written)
2103                 {
2104                         const std::string       comment = "At counter " + de::toString(counterNdx) + " vertices written " + de::toString(result.written) + ", while expected " + de::toString(expected.written);
2105
2106                         return tcu::TestStatus::fail(comment.c_str());
2107                 }
2108
2109
2110                 if (result.attempts != expected.attempts)
2111                 {
2112                         const std::string       comment = "At counter " + de::toString(counterNdx) + " attempts committed " + de::toString(result.attempts) + ", while expected " + de::toString(expected.attempts);
2113
2114                         return tcu::TestStatus::fail(comment.c_str());
2115                 }
2116
2117                 verifyTransformFeedbackBuffer(tfBufAllocation, bytesPerVertex * expected.written, static_cast<deUint32>(tfBufBindingOffsets[counterNdx]), tfBufExpectedValues[counterNdx]);
2118         }
2119
2120         return tcu::TestStatus::pass("Pass");
2121 }
2122
2123
2124 class TransformFeedbackTestCase : public vkt::TestCase
2125 {
2126 public:
2127                                                 TransformFeedbackTestCase       (tcu::TestContext &context, const char *name, const char *description, const TestParameters& parameters);
2128
2129 protected:
2130         vkt::TestInstance*      createInstance                          (vkt::Context& context) const;
2131         void                            initPrograms                            (SourceCollections& programCollection) const;
2132
2133         TestParameters          m_parameters;
2134 };
2135
2136 TransformFeedbackTestCase::TransformFeedbackTestCase (tcu::TestContext &context, const char *name, const char *description, const TestParameters& parameters)
2137         : TestCase              (context, name, description)
2138         , m_parameters  (parameters)
2139 {
2140 }
2141
2142 vkt::TestInstance*      TransformFeedbackTestCase::createInstance (vkt::Context& context) const
2143 {
2144         if (m_parameters.testType == TEST_TYPE_BASIC)
2145                 return new TransformFeedbackBasicTestInstance(context, m_parameters);
2146
2147         if (m_parameters.testType == TEST_TYPE_RESUME)
2148                 return new TransformFeedbackResumeTestInstance(context, m_parameters);
2149
2150         if (m_parameters.testType == TEST_TYPE_XFB_POINTSIZE)
2151                 return new TransformFeedbackBuiltinTestInstance(context, m_parameters);
2152
2153         if (m_parameters.testType == TEST_TYPE_XFB_CLIPDISTANCE)
2154                 return new TransformFeedbackBuiltinTestInstance(context, m_parameters);
2155
2156         if (m_parameters.testType == TEST_TYPE_XFB_CULLDISTANCE)
2157                 return new TransformFeedbackBuiltinTestInstance(context, m_parameters);
2158
2159         if (m_parameters.testType == TEST_TYPE_XFB_CLIP_AND_CULL)
2160                 return new TransformFeedbackBuiltinTestInstance(context, m_parameters);
2161
2162         if (m_parameters.testType == TEST_TYPE_WINDING)
2163                 return new TransformFeedbackWindingOrderTestInstance(context, m_parameters);
2164
2165         if (m_parameters.testType == TEST_TYPE_STREAMS)
2166                 return new TransformFeedbackStreamsTestInstance(context, m_parameters);
2167
2168         if (m_parameters.testType == TEST_TYPE_STREAMS_POINTSIZE)
2169                 return new TransformFeedbackStreamsTestInstance(context, m_parameters);
2170
2171         if (m_parameters.testType == TEST_TYPE_STREAMS_CLIPDISTANCE)
2172                 return new TransformFeedbackStreamsTestInstance(context, m_parameters);
2173
2174         if (m_parameters.testType == TEST_TYPE_STREAMS_CULLDISTANCE)
2175                 return new TransformFeedbackStreamsTestInstance(context, m_parameters);
2176
2177         if (m_parameters.testType == TEST_TYPE_MULTISTREAMS)
2178                 return new TransformFeedbackMultistreamTestInstance(context, m_parameters);
2179
2180         if (m_parameters.testType == TEST_TYPE_DRAW_INDIRECT)
2181                 return new TransformFeedbackIndirectDrawTestInstance(context, m_parameters);
2182
2183         if (m_parameters.testType == TEST_TYPE_BACKWARD_DEPENDENCY)
2184                 return new TransformFeedbackBackwardDependencyTestInstance(context, m_parameters);
2185
2186         if (m_parameters.testType == TEST_TYPE_QUERY_GET        ||
2187                 m_parameters.testType == TEST_TYPE_QUERY_COPY   ||
2188             m_parameters.testType == TEST_TYPE_QUERY_RESET)
2189                 return new TransformFeedbackQueryTestInstance(context, m_parameters);
2190
2191         if (m_parameters.testType == TEST_TYPE_MULTIQUERY)
2192                 return new TransformFeedbackMultiQueryTestInstance(context, m_parameters);
2193
2194         TCU_THROW(InternalError, "Specified test type not found");
2195 }
2196
2197 void TransformFeedbackTestCase::initPrograms (SourceCollections& programCollection) const
2198 {
2199         const bool vertexShaderOnly             =  m_parameters.testType == TEST_TYPE_BASIC
2200                                                                         || m_parameters.testType == TEST_TYPE_RESUME
2201                                                                         || m_parameters.testType == TEST_TYPE_BACKWARD_DEPENDENCY
2202                                                                         || (m_parameters.testType == TEST_TYPE_WINDING && m_parameters.primTopology != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST);
2203         const bool requiresFullPipeline =  m_parameters.testType == TEST_TYPE_STREAMS
2204                                                                         || m_parameters.testType == TEST_TYPE_STREAMS_POINTSIZE
2205                                                                         || m_parameters.testType == TEST_TYPE_STREAMS_CULLDISTANCE
2206                                                                         || m_parameters.testType == TEST_TYPE_STREAMS_CLIPDISTANCE
2207                                                                         || (m_parameters.testType == TEST_TYPE_WINDING && m_parameters.primTopology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST);
2208         const bool xfbBuiltinPipeline   =  m_parameters.testType == TEST_TYPE_XFB_POINTSIZE
2209                                                                         || m_parameters.testType == TEST_TYPE_XFB_CLIPDISTANCE
2210                                                                         || m_parameters.testType == TEST_TYPE_XFB_CULLDISTANCE
2211                                                                         || m_parameters.testType == TEST_TYPE_XFB_CLIP_AND_CULL;
2212
2213         if (vertexShaderOnly)
2214         {
2215                 // Vertex shader
2216                 {
2217                         std::ostringstream src;
2218                         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2219                                 << "\n"
2220                                 << "layout(push_constant) uniform pushConstants\n"
2221                                 << "{\n"
2222                                 << "    uint start;\n"
2223                                 << "} uInput;\n"
2224                                 << "\n"
2225                                 << "layout(xfb_buffer = 0, xfb_offset = 0, xfb_stride = 4, location = 0) out uint idx_out;\n"
2226                                 << "\n"
2227                                 << "void main(void)\n"
2228                                 << "{\n"
2229                                 << "    idx_out = uInput.start + gl_VertexIndex;\n"
2230                                 << "}\n";
2231
2232                         programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
2233                 }
2234
2235                 return;
2236         }
2237
2238         if (m_parameters.primTopology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST)
2239         {
2240                 // Vertex shader
2241                 {
2242                         std::ostringstream src;
2243                         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2244                                 << "layout(push_constant) uniform pushConstants\n"
2245                                 << "{\n"
2246                                 << "    uint start;\n"
2247                                 << "} uInput;\n"
2248                                 << "void main(void)\n"
2249                                 << "{\n"
2250                                 << "}\n";
2251                         programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
2252                 }
2253
2254                 // Tesselation control shader
2255                 {
2256                         std::ostringstream src;
2257                         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2258                                 << "layout(vertices = 3) out;\n"
2259                                 << "void main (void)\n"
2260                                 << "{\n"
2261                                 << "    gl_TessLevelInner[0] = 2.0;\n" // generate three triangles out of each patch
2262                                 << "    gl_TessLevelOuter[0] = 1.0;\n"
2263                                 << "    gl_TessLevelOuter[1] = 1.0;\n"
2264                                 << "    gl_TessLevelOuter[2] = 1.0;\n"
2265                                 << "}\n";
2266                         programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
2267                 }
2268
2269                 // Tessellation evaluation shader
2270                 {
2271                         std::ostringstream src;
2272                         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2273                                 << "layout(triangles, ccw) in;\n"
2274                                 << "layout(xfb_buffer = 0, xfb_offset = 0, xfb_stride = 4, location = 0) out uint idx_out;\n"
2275                                 << "\n"
2276                                 << "void main (void)\n"
2277                                 << "{\n"
2278                                 << "    idx_out = gl_PrimitiveID;\n" // all vertex generated from patch will have its id
2279                                 << "}\n";
2280                         programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
2281                 }
2282
2283                 return;
2284         }
2285
2286         if (xfbBuiltinPipeline)
2287         {
2288                 const std::string       outputBuiltIn           = (m_parameters.testType == TEST_TYPE_XFB_POINTSIZE)     ? "float gl_PointSize;\n"
2289                                                                                                 : (m_parameters.testType == TEST_TYPE_XFB_CLIPDISTANCE)  ? "float gl_ClipDistance[8];\n"
2290                                                                                                 : (m_parameters.testType == TEST_TYPE_XFB_CULLDISTANCE)  ? "float gl_CullDistance[8];\n"
2291                                                                                                 : (m_parameters.testType == TEST_TYPE_XFB_CLIP_AND_CULL) ? "float gl_CullDistance[5];\nfloat gl_ClipDistance[1];\n"
2292                                                                                                 : "";
2293                 const std::string       operationBuiltIn        = (m_parameters.testType == TEST_TYPE_XFB_POINTSIZE)     ? "gl_PointSize = float(gl_VertexIndex) / 32768.0f;"
2294                                                                                                 : (m_parameters.testType == TEST_TYPE_XFB_CLIPDISTANCE)  ? "for (int i=0; i<8; i++) gl_ClipDistance[i] = float(8 * gl_VertexIndex + i) / 32768.0f;"
2295                                                                                                 : (m_parameters.testType == TEST_TYPE_XFB_CULLDISTANCE)  ? "for (int i=0; i<8; i++) gl_CullDistance[i] = float(8 * gl_VertexIndex + i) / 32768.0f;"
2296                                                                                                 : (m_parameters.testType == TEST_TYPE_XFB_CLIP_AND_CULL) ? "for (int i=0; i<5; i++) gl_CullDistance[i] = float(6 * gl_VertexIndex + i) / 32768.0f;\n"
2297                                                                                                                                                                                                                    "gl_ClipDistance[0] = float(6 * gl_VertexIndex + 5) / 32768.0f;\n"
2298                                                                                                 : "";
2299
2300                 // Vertex shader
2301                 {
2302                         std::ostringstream src;
2303                         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2304                                 << "\n"
2305                                 << "layout(xfb_buffer = " << m_parameters.partCount - 1 << ", xfb_offset = 0) out gl_PerVertex\n"
2306                                 << "{\n"
2307                                 << outputBuiltIn
2308                                 << "};\n"
2309                                 << "\n"
2310                                 << "void main(void)\n"
2311                                 << "{\n"
2312                                 << operationBuiltIn
2313                                 << "}\n";
2314
2315                         programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
2316                 }
2317
2318                 return;
2319         }
2320
2321         if (m_parameters.testType == TEST_TYPE_MULTISTREAMS)
2322         {
2323                 // vertex shader
2324                 {
2325                         std::ostringstream src;
2326                         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2327                                 << "\n"
2328                                 << "void main(void)\n"
2329                                 << "{\n"
2330                                 << "}\n";
2331
2332                         programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
2333                 }
2334
2335                 // geometry shader
2336                 {
2337                         const deUint32          s       = m_parameters.streamId;
2338                         std::ostringstream      src;
2339
2340                         DE_ASSERT(s != 0);
2341
2342                         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2343                                 << "\n"
2344                                 << "layout(points) in;\n"
2345                                 << "\n"
2346                                 << "layout(points, max_vertices = 32) out;\n"
2347                                 << "layout(stream = " << 0 << ", xfb_buffer = 0, xfb_offset = 0, xfb_stride = 16, location = 0) out vec4 out0;\n"
2348                                 << "layout(stream = " << s << ", xfb_buffer = 1, xfb_offset = 0, xfb_stride = 16, location = 1) out vec4 out1;\n"
2349                                 << "\n"
2350                                 << "const int counts[] = int[](1, 1, 2, 4, 8);\n"
2351                                 << "\n"
2352                                 << "void main(void)\n"
2353                                 << "{\n"
2354                                 << "    int c0 = 0;\n"
2355                                 << "    int c1 = 0;\n"
2356                                 << "\n"
2357                                 << "    // Start 1st buffer from point where 0th buffer ended\n"
2358                                 << "    for (int i = 0; i < counts.length(); i++)\n"
2359                                 << "        c1 = c1 + 4 * counts[i];\n"
2360                                 << "\n"
2361                                 << "    for (int i = 0; i < counts.length(); i++)\n"
2362                                 << "    {\n"
2363                                 << "        const int n0 = counts[i];\n"
2364                                 << "        const int n1 = counts[counts.length() - 1 - i];\n"
2365                                 << "\n"
2366                                 << "        for (int j = 0; j < n0; j++)\n"
2367                                 << "        {\n"
2368                                 << "            out0 = vec4(ivec4(c0, c0 + 1, c0 + 2, c0 + 3));\n"
2369                                 << "            c0 = c0 + 4;\n"
2370                                 << "            EmitStreamVertex(0);\n"
2371                                 << "            EndStreamPrimitive(0);\n"
2372                                 << "        }\n"
2373                                 << "\n"
2374                                 << "        for (int j = 0; j < n1; j++)\n"
2375                                 << "        {\n"
2376                                 << "            out1 = vec4(ivec4(c1, c1 + 1, c1 + 2, c1 + 3));\n"
2377                                 << "            c1 = c1 + 4;\n"
2378                                 << "            EmitStreamVertex(" << s << ");\n"
2379                                 << "            EndStreamPrimitive(" << s << ");\n"
2380                                 << "        }\n"
2381                                 << "    }\n"
2382                                 << "}\n";
2383
2384                         programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
2385                 }
2386
2387                 return;
2388         }
2389
2390         if (requiresFullPipeline)
2391         {
2392                 // vertex shader
2393                 {
2394                         std::ostringstream src;
2395                         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2396                                 << "\n"
2397                                 << "void main(void)\n"
2398                                 << "{\n"
2399                                 << "}\n";
2400
2401                         programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
2402                 }
2403
2404                 // geometry shader
2405                 {
2406                         const deUint32          s                                       = m_parameters.streamId;
2407                         const bool                      requirePoints           = (m_parameters.testType == TEST_TYPE_STREAMS_POINTSIZE || m_parameters.testType == TEST_TYPE_MULTISTREAMS);
2408                         const std::string       outputPrimitiveType     = requirePoints ? "points" : "triangle_strip";
2409                         const std::string       outputBuiltIn           = (m_parameters.testType == TEST_TYPE_STREAMS_POINTSIZE)    ? "    float gl_PointSize;\n"
2410                                                                                                         : (m_parameters.testType == TEST_TYPE_STREAMS_CLIPDISTANCE) ? "    float gl_ClipDistance[];\n"
2411                                                                                                         : (m_parameters.testType == TEST_TYPE_STREAMS_CULLDISTANCE) ? "    float gl_CullDistance[];\n"
2412                                                                                                         : "";
2413                         std::ostringstream      src;
2414
2415                         DE_ASSERT(s != 0);
2416
2417                         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2418                                 << "\n"
2419                                 << "layout(points) in;\n"
2420                                 << "layout(" << outputPrimitiveType << ", max_vertices = 16) out;\n"
2421                                 << "layout(stream = " << s << ") out;\n"
2422                                 << "layout(location = 0) out vec4 color;\n"
2423                                 << "\n"
2424                                 << "layout(stream = " << s << ") out gl_PerVertex\n"
2425                                 << "{\n"
2426                                 << "    vec4 gl_Position;\n"
2427                                 << outputBuiltIn
2428                                 << "};\n"
2429                                 << "\n"
2430                                 << "void main(void)\n"
2431                                 << "{\n"
2432                                 << "    // Color constants\n"
2433                                 << "    vec4 g = vec4(0.0, 1.0, 0.0, 1.0);\n"
2434                                 << "    vec4 m = vec4(1.0, 0.0, 1.0, 1.0);\n"
2435                                 << "    // Coordinate constants: leftmost column\n"
2436                                 << "    vec4 a = vec4(-1.0,-1.0, 0.0, 1.0);\n"
2437                                 << "    vec4 b = vec4(-1.0, 0.0, 0.0, 1.0);\n"
2438                                 << "    vec4 c = vec4(-1.0, 1.0, 0.0, 1.0);\n"
2439                                 << "    // Coordinate constants: middle column\n"
2440                                 << "    vec4 i = vec4( 0.0,-1.0, 0.0, 1.0);\n"
2441                                 << "    vec4 j = vec4( 0.0, 0.0, 0.0, 1.0);\n"
2442                                 << "    vec4 k = vec4( 0.0, 1.0, 0.0, 1.0);\n"
2443                                 << "    // Coordinate constants: rightmost column\n"
2444                                 << "    vec4 x = vec4( 1.0,-1.0, 0.0, 1.0);\n"
2445                                 << "    vec4 y = vec4( 1.0, 0.0, 0.0, 1.0);\n"
2446                                 << "    vec4 z = vec4( 1.0, 1.0, 0.0, 1.0);\n"
2447                                 << "\n";
2448
2449                         if (m_parameters.testType == TEST_TYPE_STREAMS)
2450                         {
2451                                 src << "    if (gl_PrimitiveIDIn == 0)\n"
2452                                         << "    {\n"
2453                                         << "        color = m; gl_Position = b; EmitStreamVertex(" << s << ");\n"
2454                                         << "        color = m; gl_Position = y; EmitStreamVertex(" << s << ");\n"
2455                                         << "        color = m; gl_Position = c; EmitStreamVertex(" << s << ");\n"
2456                                         << "        EndStreamPrimitive(" << s << ");\n"
2457                                         << "    }\n"
2458                                         << "    else\n"
2459                                         << "    {\n"
2460                                         << "        color = m; gl_Position = y; EmitStreamVertex(" << s << ");\n"
2461                                         << "        color = m; gl_Position = c; EmitStreamVertex(" << s << ");\n"
2462                                         << "        color = m; gl_Position = z; EmitStreamVertex(" << s << ");\n"
2463                                         << "        EndStreamPrimitive(" << s << ");\n"
2464                                         << "    }\n";
2465                         }
2466
2467                         if (m_parameters.testType == TEST_TYPE_STREAMS_POINTSIZE)
2468                         {
2469                                 const std::string       pointSize       = "gl_PointSize = " + de::toString(m_parameters.pointSize) + ".0f";
2470
2471                                 src << "    if (gl_PrimitiveIDIn == 0)\n"
2472                                         << "    {\n"
2473                                         << "        color = g; gl_Position = (a + j) / 2.0f; gl_PointSize = 1.0f; EmitStreamVertex(0);\n"
2474                                         << "        EndStreamPrimitive(0);\n"
2475                                         << "        color = m; gl_Position = (b + k) / 2.0f; gl_PointSize = 1.0f; EmitStreamVertex(" << s << ");\n"
2476                                         << "        EndStreamPrimitive(" << s << ");\n"
2477                                         << "    }\n"
2478                                         << "    else\n"
2479                                         << "    {\n"
2480                                         << "        color = g; gl_Position = (j + x) / 2.0f; " << pointSize << "; EmitStreamVertex(0);\n"
2481                                         << "        EndStreamPrimitive(0);\n"
2482                                         << "        color = m; gl_Position = (k + y) / 2.0f; " << pointSize << "; EmitStreamVertex(" << s << ");\n"
2483                                         << "        EndStreamPrimitive(" << s << ");\n"
2484                                         << "    }\n";
2485                         }
2486
2487                         if (m_parameters.testType == TEST_TYPE_STREAMS_CLIPDISTANCE)
2488                         {
2489                                 src << "    if (gl_PrimitiveIDIn == 0)\n"
2490                                         << "    {\n"
2491                                         << "        color = m; gl_Position = b; gl_ClipDistance[0] = -1.0; EmitStreamVertex(" << s << ");\n"
2492                                         << "        color = m; gl_Position = c; gl_ClipDistance[0] = -1.0; EmitStreamVertex(" << s << ");\n"
2493                                         << "        color = m; gl_Position = y; gl_ClipDistance[0] =  1.0; EmitStreamVertex(" << s << ");\n"
2494                                         << "        EndStreamPrimitive(" << s << ");\n"
2495                                         << "    }\n"
2496                                         << "    else\n"
2497                                         << "    {\n"
2498                                         << "        color = m; gl_Position = y; gl_ClipDistance[0] =  1.0; EmitStreamVertex(" << s << ");\n"
2499                                         << "        color = m; gl_Position = c; gl_ClipDistance[0] = -1.0; EmitStreamVertex(" << s << ");\n"
2500                                         << "        color = m; gl_Position = z; gl_ClipDistance[0] =  1.0; EmitStreamVertex(" << s << ");\n"
2501                                         << "        EndStreamPrimitive(" << s << ");\n"
2502                                         << "    }\n";
2503                         }
2504
2505                         if (m_parameters.testType == TEST_TYPE_STREAMS_CULLDISTANCE)
2506                         {
2507                                 src << "    if (gl_PrimitiveIDIn == 0)\n"
2508                                         << "    {\n"
2509                                         << "        color = m; gl_Position = b; gl_CullDistance[0] = -1.0; EmitStreamVertex(" << s << ");\n"
2510                                         << "        color = m; gl_Position = c; gl_CullDistance[0] = -1.0; EmitStreamVertex(" << s << ");\n"
2511                                         << "        color = m; gl_Position = j; gl_CullDistance[0] = -1.0; EmitStreamVertex(" << s << ");\n"
2512                                         << "        EndStreamPrimitive(" << s << ");\n"
2513                                         << "        color = m; gl_Position = j; gl_CullDistance[0] = -1.0; EmitStreamVertex(" << s << ");\n"
2514                                         << "        color = m; gl_Position = c; gl_CullDistance[0] = -1.0; EmitStreamVertex(" << s << ");\n"
2515                                         << "        color = m; gl_Position = k; gl_CullDistance[0] = -1.0; EmitStreamVertex(" << s << ");\n"
2516                                         << "        EndStreamPrimitive(" << s << ");\n"
2517                                         << "    }\n"
2518                                         << "    else\n"
2519                                         << "    {\n"
2520                                         << "        color = m; gl_Position = j; gl_CullDistance[0] =  1.0; EmitStreamVertex(" << s << ");\n"
2521                                         << "        color = m; gl_Position = k; gl_CullDistance[0] =  1.0; EmitStreamVertex(" << s << ");\n"
2522                                         << "        color = m; gl_Position = y; gl_CullDistance[0] =  1.0; EmitStreamVertex(" << s << ");\n"
2523                                         << "        EndStreamPrimitive(" << s << ");\n"
2524                                         << "        color = m; gl_Position = y; gl_CullDistance[0] =  1.0; EmitStreamVertex(" << s << ");\n"
2525                                         << "        color = m; gl_Position = k; gl_CullDistance[0] =  1.0; EmitStreamVertex(" << s << ");\n"
2526                                         << "        color = m; gl_Position = z; gl_CullDistance[0] =  1.0; EmitStreamVertex(" << s << ");\n"
2527                                         << "        EndStreamPrimitive(" << s << ");\n"
2528                                         << "    }\n";
2529                         }
2530
2531                         src << "}\n";
2532
2533                         programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
2534                 }
2535
2536                 // Fragment shader
2537                 {
2538                         std::ostringstream src;
2539                         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2540                                 << "\n"
2541                                 << "layout(location = 0) in  vec4 i_color;\n"
2542                                 << "layout(location = 0) out vec4 o_color;\n"
2543                                 << "\n"
2544                                 << "void main(void)\n"
2545                                 << "{\n"
2546                                 << "    o_color = i_color;\n"
2547                                 << "}\n";
2548
2549                         programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
2550                 }
2551
2552                 return;
2553         }
2554
2555         if (m_parameters.testType == TEST_TYPE_DRAW_INDIRECT)
2556         {
2557                 // vertex shader
2558                 {
2559                         std::ostringstream src;
2560                         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2561                                 << "\n"
2562                                 << "layout(location = 0) in vec4 in_position;\n"
2563                                 << "\n"
2564                                 << "void main(void)\n"
2565                                 << "{\n"
2566                                 << "    gl_Position = in_position;\n"
2567                                 << "}\n";
2568
2569                         programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
2570                 }
2571
2572                 // Fragment shader
2573                 {
2574                         std::ostringstream src;
2575                         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2576                                 << "\n"
2577                                 << "layout(location = 0) out vec4 o_color;\n"
2578                                 << "\n"
2579                                 << "void main(void)\n"
2580                                 << "{\n"
2581                                 << "    o_color = vec4(1.0, 1.0, 1.0, 1.0);\n"
2582                                 << "}\n";
2583
2584                         programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
2585                 }
2586
2587                 return;
2588         }
2589
2590         if (m_parameters.testType == TEST_TYPE_QUERY_GET        ||
2591                 m_parameters.testType == TEST_TYPE_QUERY_COPY   ||
2592                 m_parameters.testType == TEST_TYPE_QUERY_RESET)
2593         {
2594                 struct TopologyShaderInfo
2595                 {
2596                         std::string glslIn;
2597                         std::string glslOut;
2598                         std::string spirvIn;
2599                         std::string spirvOut;
2600                 };
2601
2602                 const std::map<VkPrimitiveTopology, TopologyShaderInfo> primitiveNames  =
2603                 {
2604                         { VK_PRIMITIVE_TOPOLOGY_POINT_LIST                                              , { "points"                            , "points"                      , "InputPoints"                         , "OutputPoints"                } },
2605                         { VK_PRIMITIVE_TOPOLOGY_LINE_LIST                                               , { "lines"                                     , "line_strip"          , "InputLines"                          , "OutputLineStrip"             } },
2606                         { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP                                              , { "lines"                                     , "line_strip"          , "InputLines"                          , "OutputLineStrip"             } },
2607                         { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST                                   , { "triangles"                         , "triangle_strip"      , "Triangles"                           , "OutputTriangleStrip" } },
2608                         { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP                                  , { "triangles"                         , "triangle_strip"      , "Triangles"                           , "OutputTriangleStrip" } },
2609                         { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN                                    , { "triangles"                         , "triangle_strip"      , "Triangles"                           , "OutputTriangleStrip" } },
2610                         { VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY                , { "lines_adjacency"           , "line_strip"          , "InputLinesAdjacency"         , "OutputLineStrip"             } },
2611                         { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY               , { "lines_adjacency"           , "line_strip"          , "InputLinesAdjacency"         , "OutputLineStrip"             } },
2612                         { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY    , { "triangles_adjacency"       , "triangle_strip"      , "InputTrianglesAdjacency"     , "OutputTriangleStrip" } },
2613                         { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY   , { "triangles_adjacency"       , "triangle_strip"      , "InputTrianglesAdjacency"     , "OutputTriangleStrip" } }
2614                 };
2615
2616                 // Vertex shader
2617                 {
2618                         std::ostringstream src;
2619                         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2620                                 << "\n"
2621                                 << "layout(location = 0) out vec4 out0;\n"
2622                                 << "\n"
2623                                 << "void main(void)\n"
2624                                 << "{\n"
2625                                 << "    float n = 4.0 * float(gl_VertexIndex);\n"
2626                                 << "    out0 = vec4(n + 0.0, n + 1.0, n + 2.0, n + 3.0);\n"
2627                                 << "}\n";
2628
2629                         programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
2630                 }
2631
2632                 // geometry shader
2633                 if (m_parameters.streamId == 0)
2634                 {
2635                         std::ostringstream      src;
2636
2637                         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2638                                 << "\n"
2639                                 << "layout(" << primitiveNames.at(m_parameters.primTopology).glslIn << ") in;\n"
2640                                 << "layout(location = 0) in vec4 in0[];\n"
2641                                 << "\n"
2642                                 << "layout(" << primitiveNames.at(m_parameters.primTopology).glslOut << ", max_vertices = " << topologyData.at(m_parameters.primTopology).primSize<< ") out;\n"
2643                                 << "layout(xfb_buffer = 0, xfb_offset = 0, xfb_stride = 16, location = 0) out vec4 out0;\n"
2644                                 << "\n"
2645                                 << "void main(void)\n"
2646                                 << "{\n";
2647
2648                                 for (deUint32 i = 0; i < topologyData.at(m_parameters.primTopology).primSize; i++)
2649                                 {
2650                                         src << "    out0 = in0[" << i << "];\n"
2651                                                 << "    EmitVertex();\n";
2652                                 }
2653
2654                         src << "    EndPrimitive();\n"
2655                                 << "}\n";
2656
2657                         programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
2658                 }
2659                 else
2660                 {
2661                         const deUint32          s       = m_parameters.streamId;
2662                         std::ostringstream      src;
2663
2664                         if (m_parameters.testType == TEST_TYPE_QUERY_GET)
2665                         {
2666                                 // The SPIR-V program below is roughly equivalent to the following GLSL code:
2667                                 //
2668                                 // #version 450
2669                                 // #extension GL_ARB_enhanced_layouts : require
2670                                 //
2671                                 // layout(points) in;
2672                                 // layout(location = 0) in vec4 in0[];
2673                                 //
2674                                 // layout(points, max_vertices = 1) out;
2675                                 // layout(location=0, stream=1, xfb_buffer=0, xfb_stride=16) out OutBlock {
2676                                 //     layout(xfb_offset=0, location=0) vec4 out0;
2677                                 // } outBlock;
2678                                 //
2679                                 // void main(void)
2680                                 // {
2681                                 //     outBlock.out0 = in0[0];
2682                                 //     EmitStreamVertex(1);
2683                                 //     EndStreamPrimitive(1);
2684                                 // }
2685                                 //
2686                                 // However, the stream number has been parametrized and the code generated by glslang has been tuned to move the
2687                                 // Stream, XfbBuffer and XfbStride decorations to the structure member instead of the block. This allows us to test
2688                                 // transform feedback decorations on structure members as part of these basic tests.
2689                                 src     << "; SPIR-V\n"
2690                                         << "; Version: 1.0\n"
2691                                         << "; Generator: Khronos Glslang Reference Front End; 10\n"
2692                                         << "; Bound: 64\n"
2693                                         << "; Schema: 0\n"
2694                                         << "               OpCapability Geometry\n"
2695                                         << "               OpCapability TransformFeedback\n"
2696                                         << "               OpCapability GeometryStreams\n"
2697                                         << "          %1 = OpExtInstImport \"GLSL.std.450\"\n"
2698                                         << "               OpMemoryModel Logical GLSL450\n"
2699                                         << "               OpEntryPoint Geometry %main \"main\" %outBlock %in0\n"
2700                                         << "               OpExecutionMode %main Xfb\n"
2701                                         << "               OpExecutionMode %main " << primitiveNames.at(m_parameters.primTopology).spirvIn << "\n"
2702                                         << "               OpExecutionMode %main Invocations 1\n"
2703                                         << "               OpExecutionMode %main  " << primitiveNames.at(m_parameters.primTopology).spirvOut << "\n"
2704                                         << "               OpExecutionMode %main OutputVertices " << topologyData.at(m_parameters.primTopology).primSize << "\n"
2705                                         << "               OpSource GLSL 450\n"
2706                                         << "               OpSourceExtension \"GL_ARB_enhanced_layouts\"\n"
2707                                         << "               OpName %main \"main\"\n"
2708                                         << "               OpName %OutBlock \"OutBlock\"\n"
2709                                         << "               OpMemberName %OutBlock 0 \"out0\"\n"
2710                                         << "               OpName %outBlock \"outBlock\"\n"
2711                                         << "               OpName %in0 \"in0\"\n"
2712                                         << "               OpMemberDecorate %OutBlock 0 Location 0\n"
2713                                         << "               OpMemberDecorate %OutBlock 0 Offset 0\n"
2714                                         // These Stream, XfbBuffer and XfbStride decorations have been moved to the struct member.
2715                                         << "               OpMemberDecorate %OutBlock 0 Stream " << s << "\n"
2716                                         << "               OpMemberDecorate %OutBlock 0 XfbBuffer 0\n"
2717                                         << "               OpMemberDecorate %OutBlock 0 XfbStride 16\n"
2718                                         << "               OpDecorate %OutBlock Block\n"
2719                                         // The decorations mentioned above were using OpDecorate and assigned to %outBlock itself here.
2720                                         << "               OpDecorate %in0 Location 0\n"
2721                                         << "       %void = OpTypeVoid\n"
2722                                         << "          %3 = OpTypeFunction %void\n"
2723                                         << "      %float = OpTypeFloat 32\n"
2724                                         << "    %v4float = OpTypeVector %float 4\n"
2725                                         << "   %OutBlock = OpTypeStruct %v4float\n"
2726                                         << "%_ptr_Output_OutBlock = OpTypePointer Output %OutBlock\n"
2727                                         << "   %outBlock = OpVariable %_ptr_Output_OutBlock Output\n"
2728                                         << "        %int = OpTypeInt 32 1\n"
2729                                         << "      %int_0 = OpConstant %int 0\n";
2730
2731                                 for (deUint32 i = 1; i < topologyData.at(m_parameters.primTopology).primSize + 1; i++)
2732                                 {
2733                                         src << "%int_" << i << " = OpConstant %int " << i << "\n";
2734                                 }
2735
2736                                 src << "       %uint = OpTypeInt 32 0\n"
2737                                         << "     %uint_0 = OpConstant %uint " << topologyData.at(m_parameters.primTopology).primSize << "\n"
2738                                         << "%_arr_v4float_uint_0 = OpTypeArray %v4float %uint_0\n"
2739                                         << "%_ptr_Input__arr_v4float_uint_0 = OpTypePointer Input %_arr_v4float_uint_0\n"
2740                                         << "        %in0 = OpVariable %_ptr_Input__arr_v4float_uint_0 Input\n"
2741                                         << "%_ptr_Input_v4float = OpTypePointer Input %v4float\n"
2742                                         << "%_ptr_Output_v4float = OpTypePointer Output %v4float\n"
2743                                         << "  %streamNum = OpConstant %int " << s << "\n"
2744                                         << "       %main = OpFunction %void None %3\n"
2745                                         << "          %5 = OpLabel\n";
2746
2747                                 for (deUint32 i = 1; i < topologyData.at(m_parameters.primTopology).primSize + 1; i++)
2748                                 {
2749                                         src << "%" << i << "1 = OpAccessChain %_ptr_Input_v4float %in0 %int_" << i << "\n"
2750                                                 << "          %" << i << "2 = OpLoad %v4float %" << i << "1\n"
2751                                                 << "          %" << i << "3 = OpAccessChain %_ptr_Output_v4float %outBlock %int_0\n"
2752                                                 << "               OpStore %" << i << "3 %" << i << "2\n"
2753                                                 << "               OpEmitStreamVertex %streamNum\n";
2754                                 }
2755
2756                                 src << "               OpEndStreamPrimitive %streamNum\n"
2757                                         << "               OpReturn\n"
2758                                         << "               OpFunctionEnd\n"
2759                                         ;
2760
2761                                 programCollection.spirvAsmSources.add("geom") << src.str();
2762                         }
2763                         else
2764                         {
2765                                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2766                                         << "\n"
2767                                         << "layout(" << primitiveNames.at(m_parameters.primTopology).glslIn << ") in;\n"
2768                                         << "layout(location = 0) in vec4 in0[];\n"
2769                                         << "\n"
2770                                         << "layout(" << primitiveNames.at(m_parameters.primTopology).glslOut << ", max_vertices = " << topologyData.at(m_parameters.primTopology).primSize << ") out;\n"
2771                                         << "layout(stream = " << s << ", xfb_buffer = 0, xfb_offset = 0, xfb_stride = 16, location = 0) out vec4 out0;\n"
2772                                         << "\n"
2773                                         << "void main(void)\n"
2774                                         << "{\n";
2775
2776                                 for (deUint32 i = 0; i < topologyData.at(m_parameters.primTopology).primSize; i++)
2777                                 {
2778                                         src << "    out0 = in0[" << i << "];\n"
2779                                                 << "    EmitStreamVertex(" << s << ");\n";
2780                                 }
2781
2782                                 src << "    EndStreamPrimitive(" << s << ");\n"
2783                                         << "}\n";
2784
2785                                 programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
2786                         }
2787                 }
2788
2789                 return;
2790         }
2791
2792         if (m_parameters.testType == TEST_TYPE_MULTIQUERY)
2793         {
2794                 // vertex shader
2795                 {
2796                         std::ostringstream src;
2797                         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2798                                 << "\n"
2799                                 << "layout(location = 0) out ivec4 out0;\n"
2800                                 << "\n"
2801                                 << "void main(void)\n"
2802                                 << "{\n"
2803                                 << "    out0 = ivec4(gl_VertexIndex);\n"
2804                                 << "}\n";
2805
2806                         programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
2807                 }
2808
2809                 // geometry shader
2810                 {
2811                         const deUint32          s       = m_parameters.streamId;
2812                         std::ostringstream      src;
2813
2814                         DE_ASSERT(s != 0);
2815
2816                         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2817                                 << "\n"
2818                                 << "layout(points) in;\n"
2819                                 << "\n"
2820                                 << "layout(points, max_vertices = 4) out;\n"
2821                                 << "\n"
2822                                 << "layout(stream = " << 0 << ", xfb_buffer = 0, xfb_offset = 0, xfb_stride = 16, location = 0) out vec4 out0;\n"
2823                                 << "layout(stream = " << s << ", xfb_buffer = 1, xfb_offset = 0, xfb_stride = 16, location = 1) out vec4 out1;\n"
2824                                 << "\n"
2825                                 << "void main(void)\n"
2826                                 << "{\n"
2827                                 << "    const int   n0 = 3;\n"
2828                                 << "    const int   n1 = 1;\n"
2829                                 << "    const float c0 = 0.5f;\n"
2830                                 << "    const float c1 = 0.5f + float(" << s << ");\n"
2831                                 << "\n"
2832                                 << "    for (int j = 0; j < n0; j++)\n"
2833                                 << "    {\n"
2834                                 << "        out0 = vec4(c0);\n"
2835                                 << "        EmitStreamVertex(0);\n"
2836                                 << "        EndStreamPrimitive(0);\n"
2837                                 << "    }\n"
2838                                 << "\n"
2839                                 << "    for (int j = 0; j < n1; j++)\n"
2840                                 << "    {\n"
2841                                 << "        out1 = vec4(c1);\n"
2842                                 << "        EmitStreamVertex(" << s << ");\n"
2843                                 << "        EndStreamPrimitive(" << s << ");\n"
2844                                 << "    }\n"
2845                                 << "}\n";
2846
2847                         programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
2848                 }
2849
2850                 return;
2851         }
2852
2853         DE_ASSERT(0 && "Unknown test");
2854 }
2855
2856 void createTransformFeedbackSimpleTests(tcu::TestCaseGroup* group)
2857 {
2858         {
2859                 const deUint32          bufferCounts[]  = { 1u, 2u, 4u, 8u };
2860                 const deUint32          bufferSizes[]   = { 256u, 512u, 128u * 1024u };
2861                 const TestType          testTypes[]             = { TEST_TYPE_BASIC, TEST_TYPE_RESUME, TEST_TYPE_XFB_POINTSIZE, TEST_TYPE_XFB_CLIPDISTANCE, TEST_TYPE_XFB_CULLDISTANCE, TEST_TYPE_XFB_CLIP_AND_CULL };
2862                 const std::string       testTypeNames[] = { "basic", "resume", "xfb_pointsize", "xfb_clipdistance", "xfb_culldistance", "xfb_clip_and_cull" };
2863
2864                 for (deUint32 testTypesNdx = 0; testTypesNdx < DE_LENGTH_OF_ARRAY(testTypes); ++testTypesNdx)
2865                 {
2866                         const TestType          testType        = testTypes[testTypesNdx];
2867                         const std::string       testName        = testTypeNames[testTypesNdx];
2868
2869                         for (deUint32 bufferCountsNdx = 0; bufferCountsNdx < DE_LENGTH_OF_ARRAY(bufferCounts); ++bufferCountsNdx)
2870                         {
2871                                 const deUint32  partCount       = bufferCounts[bufferCountsNdx];
2872
2873                                 for (deUint32 bufferSizesNdx = 0; bufferSizesNdx < DE_LENGTH_OF_ARRAY(bufferSizes); ++bufferSizesNdx)
2874                                 {
2875                                         const deUint32  bufferSize      = bufferSizes[bufferSizesNdx];
2876                                         TestParameters  parameters      = { testType, bufferSize, partCount, 0u, 0u, 0u, STREAM_ID_0_NORMAL, false, false, VK_PRIMITIVE_TOPOLOGY_POINT_LIST };
2877
2878                                         group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_" + de::toString(partCount) + "_" + de::toString(bufferSize)).c_str(), "Simple Transform Feedback test", parameters));
2879                                         parameters.streamId0Mode = STREAM_ID_0_BEGIN_QUERY_INDEXED;
2880                                         group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_beginqueryindexed_streamid_0_" + de::toString(partCount) + "_" + de::toString(bufferSize)).c_str(), "Simple Transform Feedback test", parameters));
2881                                         parameters.streamId0Mode = STREAM_ID_0_END_QUERY_INDEXED;
2882                                         group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_endqueryindexed_streamid_0_" + de::toString(partCount) + "_" + de::toString(bufferSize)).c_str(), "Simple Transform Feedback test", parameters));
2883                                 }
2884                         }
2885                 }
2886         }
2887
2888         {
2889                 const deUint32          bufferCounts[]  = { 6u, 8u, 10u, 12u };
2890                 const TestType          testType                = TEST_TYPE_WINDING;
2891                 const std::string       testName                = "winding";
2892
2893                 for (const auto& topology : topologyData)
2894                 {
2895                         // Note: no need to test POINT_LIST as is tested in many tests.
2896                         if (topology.first == VK_PRIMITIVE_TOPOLOGY_POINT_LIST)
2897                                 continue;
2898
2899                         for (deUint32 bufferCountsNdx = 0; bufferCountsNdx < DE_LENGTH_OF_ARRAY(bufferCounts); ++bufferCountsNdx)
2900                         {
2901                                 const deUint32  vertexCount     = bufferCounts[bufferCountsNdx];
2902
2903                                 TestParameters  parameters      = { testType, 0u, vertexCount, 0u, 0u, 0u, STREAM_ID_0_NORMAL, false, false, topology.first };
2904
2905                                 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_" + topology.second.topologyName + de::toString(vertexCount)).c_str(), "Topology winding test", parameters));
2906                         }
2907                 }
2908         }
2909
2910         {
2911                 const deUint32          vertexStrides[] = { 4u, 61u, 127u, 251u, 509u };
2912                 const TestType          testType                = TEST_TYPE_DRAW_INDIRECT;
2913                 const std::string       testName                = "draw_indirect";
2914
2915                 for (deUint32 vertexStridesNdx = 0; vertexStridesNdx < DE_LENGTH_OF_ARRAY(vertexStrides); ++vertexStridesNdx)
2916                 {
2917                         const deUint32  vertexStrideBytes       = static_cast<deUint32>(sizeof(deUint32) * vertexStrides[vertexStridesNdx]);
2918                         TestParameters  parameters                      = { testType, 0u, 0u, 0u, 0u, vertexStrideBytes, STREAM_ID_0_NORMAL, false, false, VK_PRIMITIVE_TOPOLOGY_POINT_LIST };
2919
2920                         group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_" + de::toString(vertexStrideBytes)).c_str(), "Rendering tests with various strides", parameters));
2921                         parameters.streamId0Mode = STREAM_ID_0_BEGIN_QUERY_INDEXED;
2922                         group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_beginqueryindexed_streamid_0_" + de::toString(vertexStrideBytes)).c_str(), "Rendering tests with various strides", parameters));
2923                         parameters.streamId0Mode = STREAM_ID_0_END_QUERY_INDEXED;
2924                         group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_endqueryindexed_streamid_0_" + de::toString(vertexStrideBytes)).c_str(), "Rendering tests with various strides", parameters));
2925                 }
2926         }
2927
2928         {
2929                 const TestType          testType        = TEST_TYPE_BACKWARD_DEPENDENCY;
2930                 const std::string       testName        = "backward_dependency";
2931                 TestParameters          parameters      = { testType, 512u, 2u, 0u, 0u, 0u, STREAM_ID_0_NORMAL, false, false, VK_PRIMITIVE_TOPOLOGY_POINT_LIST };
2932
2933                 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), testName.c_str(), "Rendering test checks backward pipeline dependency", parameters));
2934                 parameters.streamId0Mode = STREAM_ID_0_BEGIN_QUERY_INDEXED;
2935                 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_beginqueryindexed_streamid_0").c_str(), "Rendering test checks backward pipeline dependency", parameters));
2936                 parameters.streamId0Mode = STREAM_ID_0_END_QUERY_INDEXED;
2937                 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_endqueryindexed_streamid_0").c_str(), "Rendering test checks backward pipeline dependency", parameters));
2938
2939                 parameters.noOffsetArray = true;
2940                 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_no_offset_array").c_str(), "Rendering test checks backward pipeline dependency (using NULL for offset array)", parameters));
2941         }
2942
2943         {
2944                 const deUint32          usedStreamId[]                  = { 0u, 1u, 3u, 6u, 14u };
2945                 const deUint32          vertexCounts[]                  = { 6u, 61u, 127u, 251u, 509u }; // Lowest value has to be at least 6. Otherwise the triangles with adjacency can't be generated.
2946                 const TestType          testType                                = TEST_TYPE_QUERY_GET;
2947                 const std::string       testName                                = "query";
2948                 const TestType          testTypeCopy                    = TEST_TYPE_QUERY_COPY;
2949                 const std::string       testNameCopy                    = "query_copy";
2950                 const TestType          testTypeHostQueryReset  = TEST_TYPE_QUERY_RESET;
2951                 const std::string       testNameHostQueryReset  = "host_query_reset";
2952
2953                 for (const auto& topology : topologyData)
2954                 {
2955                         // Currently, we don't test tessellation here.
2956                         if (topology.first == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST)
2957                                 continue;
2958
2959                         for (const auto& streamCounts : usedStreamId)
2960                         {
2961                                 const deUint32  streamId        = streamCounts;
2962
2963                                 for (const auto& numVertices : vertexCounts)
2964                                 {
2965                                         for (deUint32 i = 0; i < 2; ++i)
2966                                         {
2967                                                 const bool                              query64Bits             = (i == 1);
2968                                                 const std::string               widthStr                = (query64Bits ? "_64bits" : "_32bits");
2969
2970                                                 deUint32                                vertCount               = numVertices;
2971
2972                                                 // The number of vertices in original test was 4.
2973                                                 if (topology.first == VK_PRIMITIVE_TOPOLOGY_POINT_LIST && vertCount == 6) vertCount -= 2;
2974
2975                                                 // Round the number of vertices to match the used primitive topology - if necessary.
2976                                                 const deUint32                  primitiveCount  = (deUint32)topology.second.getNumPrimitives(vertCount);
2977                                                 const deUint32                  vertexCount             = (deUint32)topology.second.getNumVertices(primitiveCount);
2978
2979                                                 DE_ASSERT(vertexCount > 0);
2980
2981                                                 const deUint32                  bytesPerVertex  = static_cast<deUint32>(4 * sizeof(float));
2982                                                 const deUint32                  bufferSize              = bytesPerVertex * vertexCount;
2983                                                 TestParameters                  parameters              = { testType, bufferSize, 0u, streamId, 0u, 0u, STREAM_ID_0_NORMAL, query64Bits, false, topology.first };
2984                                                 const std::string               fullTestName    = testName + "_" + topology.second.topologyName + de::toString(streamId) + "_" + de::toString(vertexCount) + widthStr;
2985                                                 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), fullTestName.c_str(), "Written primitives query test", parameters));
2986
2987                                                 const TestParameters    parametersCopy          = { testTypeCopy, bufferSize, 0u, streamId, 0u, 0u, STREAM_ID_0_NORMAL, query64Bits, false, topology.first };
2988                                                 const std::string               fullTestNameCopy        = testNameCopy + "_" + topology.second.topologyName + de::toString(streamId) + "_" + de::toString(vertexCount) + widthStr;
2989                                                 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), fullTestNameCopy.c_str(), "Written primitives query test", parametersCopy));
2990
2991                                                 const TestParameters    parametersHostQueryReset        = { testTypeHostQueryReset, bufferSize, 0u, streamId, 0u, 0u, STREAM_ID_0_NORMAL, query64Bits, false, topology.first };
2992                                                 const std::string               fullTestNameHostQueryReset      = testNameHostQueryReset + "_" + topology.second.topologyName + de::toString(streamId) + "_" + de::toString(vertexCount) + widthStr;
2993                                                 group->addChild(new TransformFeedbackTestCase(group->getTestContext(), fullTestNameHostQueryReset.c_str(), "Written primitives query test", parametersHostQueryReset));
2994
2995                                                 if (streamId == 0)
2996                                                 {
2997                                                         std::string     testNameStream0 = fullTestName;
2998                                                         testNameStream0 += "_beginqueryindexed_streamid_0";
2999                                                         parameters.streamId0Mode = STREAM_ID_0_BEGIN_QUERY_INDEXED;
3000                                                         group->addChild(new TransformFeedbackTestCase(group->getTestContext(), testNameStream0.c_str(), "Written primitives query test", parameters));
3001                                                         testNameStream0 = fullTestName;
3002                                                         testNameStream0 += "_endqueryindexed_streamid_0";
3003                                                         parameters.streamId0Mode = STREAM_ID_0_END_QUERY_INDEXED;
3004                                                         group->addChild(new TransformFeedbackTestCase(group->getTestContext(), testNameStream0.c_str(), "Written primitives query test", parameters));
3005                                                 }
3006                                         }
3007                                 }
3008                         }
3009                 }
3010         }
3011 }
3012
3013 void createTransformFeedbackStreamsSimpleTests (tcu::TestCaseGroup* group)
3014 {
3015         const deUint32          usedStreamId[]          = { 1u, 3u, 6u, 14u };
3016         const TestType          testTypes[]                     = { TEST_TYPE_STREAMS, TEST_TYPE_STREAMS_POINTSIZE, TEST_TYPE_STREAMS_CLIPDISTANCE, TEST_TYPE_STREAMS_CULLDISTANCE };
3017         const std::string       testTypeNames[]         = { "streams", "streams_pointsize", "streams_clipdistance", "streams_culldistance" };
3018
3019         for (deUint32 testTypesNdx = 0; testTypesNdx < DE_LENGTH_OF_ARRAY(testTypes); ++testTypesNdx)
3020         {
3021                 const TestType          testType        = testTypes[testTypesNdx];
3022                 const std::string       testName        = testTypeNames[testTypesNdx];
3023                 const deUint32          pointSize       = (testType == TEST_TYPE_STREAMS_POINTSIZE) ? 2u : 0u;
3024
3025                 for (deUint32 streamCountsNdx = 0; streamCountsNdx < DE_LENGTH_OF_ARRAY(usedStreamId); ++streamCountsNdx)
3026                 {
3027                         const deUint32  streamId        = usedStreamId[streamCountsNdx];
3028                         TestParameters  parameters      = { testType, 0u, 0u, streamId, pointSize, 0u, STREAM_ID_0_NORMAL, false, false, VK_PRIMITIVE_TOPOLOGY_POINT_LIST };
3029
3030                         group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_" + de::toString(streamId)).c_str(), "Streams usage test", parameters));
3031                 }
3032         }
3033
3034         {
3035                 const TestType          testType        = TEST_TYPE_MULTISTREAMS;
3036                 const std::string       testName        = "multistreams";
3037
3038                 for (deUint32 bufferCountsNdx = 0; bufferCountsNdx < DE_LENGTH_OF_ARRAY(usedStreamId); ++bufferCountsNdx)
3039                 {
3040                         const deUint32                  streamId                        = usedStreamId[bufferCountsNdx];
3041                         const deUint32                  streamsUsed                     = 2u;
3042                         const deUint32                  maxBytesPerVertex       = 256u;
3043                         const TestParameters    parameters                      = { testType, maxBytesPerVertex * streamsUsed, streamsUsed, streamId, 0u, 0u, STREAM_ID_0_NORMAL, false, false, VK_PRIMITIVE_TOPOLOGY_POINT_LIST };
3044
3045                         group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_" + de::toString(streamId)).c_str(), "Simultaneous multiple streams usage test", parameters));
3046                 }
3047         }
3048
3049         {
3050                 const TestType          testType        = TEST_TYPE_MULTIQUERY;
3051                 const std::string       testName        = "multiquery";
3052
3053                 for (deUint32 bufferCountsNdx = 0; bufferCountsNdx < DE_LENGTH_OF_ARRAY(usedStreamId); ++bufferCountsNdx)
3054                 {
3055                         const deUint32                  streamId                        = usedStreamId[bufferCountsNdx];
3056                         const deUint32                  streamsUsed                     = 2u;
3057                         const deUint32                  maxBytesPerVertex       = 256u;
3058                         const TestParameters    parameters                      = { testType, maxBytesPerVertex * streamsUsed, streamsUsed, streamId, 0u, 0u, STREAM_ID_0_NORMAL, false, false, VK_PRIMITIVE_TOPOLOGY_POINT_LIST };
3059
3060                         group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_" + de::toString(streamId)).c_str(), "Simultaneous multiple queries usage test", parameters));
3061                 }
3062         }
3063 }
3064
3065 void createTransformFeedbackAndStreamsSimpleTests (tcu::TestCaseGroup* group)
3066 {
3067         createTransformFeedbackSimpleTests(group);
3068         createTransformFeedbackStreamsSimpleTests(group);
3069 }
3070 } // anonymous
3071
3072 tcu::TestCaseGroup* createTransformFeedbackSimpleTests (tcu::TestContext& testCtx)
3073 {
3074         return createTestGroup(testCtx, "simple", "Transform Feedback Simple tests", createTransformFeedbackAndStreamsSimpleTests);
3075 }
3076
3077 } // TransformFeedback
3078 } // vkt