420082815eaa9b11c3bc14e9b5f9002f15d4cfb5
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / geometry / vktGeometryBasicGeometryShaderTests.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 The Khronos Group Inc.
6  * Copyright (c) 2016 The Android Open Source Project
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief Basic Geometry Shader Tests
23  *//*--------------------------------------------------------------------*/
24
25 #include "vktGeometryBasicGeometryShaderTests.hpp"
26 #include "vktGeometryBasicClass.hpp"
27 #include "vktGeometryTestsUtil.hpp"
28
29 #include "gluTextureUtil.hpp"
30 #include "glwEnums.hpp"
31 #include "vkDefs.hpp"
32 #include "vktTestCase.hpp"
33 #include "vktTestCaseUtil.hpp"
34 #include "vkImageUtil.hpp"
35 #include "vkTypeUtil.hpp"
36 #include "vkPrograms.hpp"
37 #include "vkBuilderUtil.hpp"
38 #include "vkRefUtil.hpp"
39 #include "vkQueryUtil.hpp"
40 #include "vkMemUtil.hpp"
41 #include "tcuTextureUtil.hpp"
42
43 #include <string>
44
45 using namespace vk;
46
47 namespace vkt
48 {
49 namespace geometry
50 {
51 namespace
52 {
53 using tcu::TestStatus;
54 using tcu::TestContext;
55 using tcu::TestCaseGroup;
56 using de::MovePtr;
57 using std::string;
58 using std::vector;
59
60 enum VaryingSource
61 {
62         READ_ATTRIBUTE = 0,
63         READ_UNIFORM,
64         READ_TEXTURE,
65
66         READ_LAST
67 };
68 enum ShaderInstancingMode
69 {
70         MODE_WITHOUT_INSTANCING = 0,
71         MODE_WITH_INSTANCING,
72
73         MODE_LAST
74 };
75 enum
76 {
77         EMIT_COUNT_VERTEX_0 = 6,
78         EMIT_COUNT_VERTEX_1 = 0,
79         EMIT_COUNT_VERTEX_2 = -1,
80         EMIT_COUNT_VERTEX_3 = 10,
81 };
82 enum VariableTest
83 {
84         TEST_POINT_SIZE = 0,
85         TEST_PRIMITIVE_ID_IN,
86         TEST_PRIMITIVE_ID,
87         TEST_LAST
88 };
89
90 void uploadImage (Context&                                                              context,
91                                   const tcu::ConstPixelBufferAccess&    access,
92                                   VkImage                                                               destImage)
93 {
94         const DeviceInterface&                  vk                                      = context.getDeviceInterface();
95         const VkDevice                                  device                          = context.getDevice();
96         const deUint32                                  queueFamilyIndex        = context.getUniversalQueueFamilyIndex();
97         const VkQueue                                   queue                           = context.getUniversalQueue();
98         Allocator&                                              memAlloc                        = context.getDefaultAllocator();
99         const VkImageAspectFlags                aspectMask                      = VK_IMAGE_ASPECT_COLOR_BIT;
100         const deUint32                                  bufferSize                      = access.getWidth() * access.getHeight() * access.getDepth() * access.getFormat().getPixelSize();
101         Move<VkBuffer>                                  buffer;
102         de::MovePtr<Allocation>                 bufferAlloc;
103         Move<VkCommandPool>                             cmdPool;
104         Move<VkCommandBuffer>                   cmdBuffer;
105         Move<VkFence>                                   fence;
106
107         // Create source buffer
108         {
109                 const VkBufferCreateInfo bufferParams =
110                 {
111                         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,           // VkStructureType              sType;
112                         DE_NULL,                                                                        // const void*                  pNext;
113                         0u,                                                                                     // VkBufferCreateFlags  flags;
114                         bufferSize,                                                                     // VkDeviceSize                 size;
115                         VK_BUFFER_USAGE_TRANSFER_SRC_BIT,                       // VkBufferUsageFlags   usage;
116                         VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode                sharingMode;
117                         0u,                                                                                     // deUint32                             queueFamilyIndexCount;
118                         DE_NULL,                                                                        // const deUint32*              pQueueFamilyIndices;
119                 };
120                 buffer          = createBuffer(vk, device, &bufferParams);
121                 bufferAlloc     = memAlloc.allocate(getBufferMemoryRequirements(vk, device, *buffer), MemoryRequirement::HostVisible);
122                 VK_CHECK(vk.bindBufferMemory(device, *buffer, bufferAlloc->getMemory(), bufferAlloc->getOffset()));
123         }
124
125         // Create command pool and buffer
126         {
127                 const VkCommandPoolCreateInfo cmdPoolParams =
128                 {
129                         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,             // VkStructureType                      sType;
130                         DE_NULL,                                                                                // const void*                          pNext;
131                         VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,                   // VkCommandPoolCreateFlags     flags;
132                         queueFamilyIndex,                                                               // deUint32                                     queueFamilyIndex;
133                 };
134                 cmdPool = createCommandPool(vk, device, &cmdPoolParams);
135
136                 const VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
137                 {
138                         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType                      sType;
139                         DE_NULL,                                                                                // const void*                          pNext;
140                         *cmdPool,                                                                               // VkCommandPool                        commandPool;
141                         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                                // VkCommandBufferLevel         level;
142                         1u,                                                                                             // deUint32                                     bufferCount;
143                 };
144                 cmdBuffer = allocateCommandBuffer(vk, device, &cmdBufferAllocateInfo);
145         }
146
147         // Create fence
148         {
149                 const VkFenceCreateInfo fenceParams =
150                 {
151                         VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,    // VkStructureType              sType;
152                         DE_NULL,                                                                // const void*                  pNext;
153                         0u                                                                              // VkFenceCreateFlags   flags;
154                 };
155
156                 fence = createFence(vk, device, &fenceParams);
157         }
158
159         // Barriers for copying buffer to image
160         const VkBufferMemoryBarrier preBufferBarrier =
161         {
162                 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,        // VkStructureType      sType;
163                 DE_NULL,                                                                        // const void*          pNext;
164                 VK_ACCESS_HOST_WRITE_BIT,                                       // VkAccessFlags        srcAccessMask;
165                 VK_ACCESS_TRANSFER_READ_BIT,                            // VkAccessFlags        dstAccessMask;
166                 VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                     srcQueueFamilyIndex;
167                 VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                     dstQueueFamilyIndex;
168                 *buffer,                                                                        // VkBuffer                     buffer;
169                 0u,                                                                                     // VkDeviceSize         offset;
170                 bufferSize                                                                      // VkDeviceSize         size;
171         };
172
173         const VkImageMemoryBarrier preImageBarrier =
174         {
175                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,         // VkStructureType                      sType;
176                 DE_NULL,                                                                        // const void*                          pNext;
177                 0u,                                                                                     // VkAccessFlags                        srcAccessMask;
178                 VK_ACCESS_TRANSFER_WRITE_BIT,                           // VkAccessFlags                        dstAccessMask;
179                 VK_IMAGE_LAYOUT_UNDEFINED,                                      // VkImageLayout                        oldLayout;
180                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,           // VkImageLayout                        newLayout;
181                 VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                                     srcQueueFamilyIndex;
182                 VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                                     dstQueueFamilyIndex;
183                 destImage,                                                                      // VkImage                                      image;
184                 {                                                                                       // VkImageSubresourceRange      subresourceRange;
185                         aspectMask,                                                             // VkImageAspect        aspect;
186                         0u,                                                                             // deUint32                     baseMipLevel;
187                         1u,                                                                             // deUint32                     mipLevels;
188                         0u,                                                                             // deUint32                     baseArraySlice;
189                         1u                                                                              // deUint32                     arraySize;
190                 }
191         };
192
193         const VkImageMemoryBarrier postImageBarrier =
194         {
195                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,         // VkStructureType                      sType;
196                 DE_NULL,                                                                        // const void*                          pNext;
197                 VK_ACCESS_TRANSFER_WRITE_BIT,                           // VkAccessFlags                        srcAccessMask;
198                 VK_ACCESS_SHADER_READ_BIT,                                      // VkAccessFlags                        dstAccessMask;
199                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,           // VkImageLayout                        oldLayout;
200                 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,       // VkImageLayout                        newLayout;
201                 VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                                     srcQueueFamilyIndex;
202                 VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                                     dstQueueFamilyIndex;
203                 destImage,                                                                      // VkImage                                      image;
204                 {                                                                                       // VkImageSubresourceRange      subresourceRange;
205                         aspectMask,                                                             // VkImageAspect        aspect;
206                         0u,                                                                             // deUint32                     baseMipLevel;
207                         1u,                                                                             // deUint32                     mipLevels;
208                         0u,                                                                             // deUint32                     baseArraySlice;
209                         1u                                                                              // deUint32                     arraySize;
210                 }
211         };
212
213         const VkCommandBufferBeginInfo cmdBufferBeginInfo =
214         {
215                 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,    // VkStructureType                                      sType;
216                 DE_NULL,                                                                                // const void*                                          pNext;
217                 VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,    // VkCommandBufferUsageFlags            flags;
218                 (const VkCommandBufferInheritanceInfo*)DE_NULL,
219         };
220
221         // Get copy regions and write buffer data
222         const VkBufferImageCopy                 copyRegions     =
223         {
224                 0u,                                                             // VkDeviceSize                         bufferOffset;
225                 (deUint32)access.getWidth(),    // deUint32                                     bufferRowLength;
226                 (deUint32)access.getHeight(),   // deUint32                                     bufferImageHeight;
227                 {                                                               // VkImageSubresourceLayers     imageSubresource;
228                                 aspectMask,                             // VkImageAspectFlags           aspectMask;
229                                 (deUint32)0u,                   // uint32_t                                     mipLevel;
230                                 (deUint32)0u,                   // uint32_t                                     baseArrayLayer;
231                                 1u                                              // uint32_t                                     layerCount;
232                 },
233                 { 0u, 0u, 0u },                                 // VkOffset3D                   imageOffset;
234                 {                                                               // VkExtent3D                   imageExtent;
235                         (deUint32)access.getWidth(),
236                         (deUint32)access.getHeight(),
237                         (deUint32)access.getDepth()
238                 }
239         };
240
241         {
242                 const tcu::PixelBufferAccess    destAccess      (access.getFormat(), access.getSize(), bufferAlloc->getHostPtr());
243                 tcu::copy(destAccess, access);
244                 flushMappedMemoryRange(vk, device, bufferAlloc->getMemory(), bufferAlloc->getOffset(), bufferSize);
245         }
246
247         // Copy buffer to image
248         VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
249         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &preBufferBarrier, 1, &preImageBarrier);
250         vk.cmdCopyBufferToImage(*cmdBuffer, *buffer, destImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &copyRegions);
251         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &postImageBarrier);
252         VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
253
254         const VkSubmitInfo submitInfo =
255         {
256                 VK_STRUCTURE_TYPE_SUBMIT_INFO,  // VkStructureType                              sType;
257                 DE_NULL,                                                // const void*                                  pNext;
258                 0u,                                                             // deUint32                                             waitSemaphoreCount;
259                 DE_NULL,                                                // const VkSemaphore*                   pWaitSemaphores;
260                 DE_NULL,                                                // const VkPipelineStageFlags*  pWaitDstStageMask;
261                 1u,                                                             // deUint32                                             commandBufferCount;
262                 &cmdBuffer.get(),                               // const VkCommandBuffer*               pCommandBuffers;
263                 0u,                                                             // deUint32                                             signalSemaphoreCount;
264                 DE_NULL                                                 // const VkSemaphore*                   pSignalSemaphores;
265         };
266
267         VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence));
268         VK_CHECK(vk.waitForFences(device, 1, &fence.get(), true, ~(0ull) /* infinity */));
269 }
270
271 class GeometryOutputCountTestInstance : public GeometryExpanderRenderTestInstance
272 {
273 public:
274                                                                 GeometryOutputCountTestInstance (Context&                                       context,
275                                                                                                                                  const VkPrimitiveTopology      primitiveType,
276                                                                                                                                  const int                                      primitiveCount,
277                                                                                                                                  const char*                            name);
278         void                                            genVertexAttribData                             (void);
279 private:
280         const int                                       m_primitiveCount;
281 };
282
283 GeometryOutputCountTestInstance::GeometryOutputCountTestInstance (Context&                                      context,
284                                                                                                                                   const VkPrimitiveTopology     primitiveType,
285                                                                                                                                   const int                                     primitiveCount,
286                                                                                                                                   const char*                           name)
287         : GeometryExpanderRenderTestInstance    (context, primitiveType, name)
288         , m_primitiveCount                                              (primitiveCount)
289
290 {
291         genVertexAttribData();
292 }
293
294 void GeometryOutputCountTestInstance::genVertexAttribData (void)
295 {
296         m_vertexPosData.resize(m_primitiveCount);
297         m_vertexAttrData.resize(m_primitiveCount);
298
299         for (int ndx = 0; ndx < m_primitiveCount; ++ndx)
300         {
301                 m_vertexPosData[ndx] = tcu::Vec4(-1.0f, ((float)ndx) / (float)m_primitiveCount * 2.0f - 1.0f, 0.0f, 1.0f);
302                 m_vertexAttrData[ndx] = (ndx % 2 == 0) ? tcu::Vec4(1, 1, 1, 1) : tcu::Vec4(1, 0, 0, 1);
303         }
304         m_numDrawVertices = m_primitiveCount;
305 }
306
307 class VaryingOutputCountTestInstance : public GeometryExpanderRenderTestInstance
308 {
309 public:
310                                                                 VaryingOutputCountTestInstance  (Context&                                       context,
311                                                                                                                                  const char*                            name,
312                                                                                                                                  const VkPrimitiveTopology      primitiveType,
313                                                                                                                                  const VaryingSource            test,
314                                                                                                                                  const ShaderInstancingMode     mode);
315         void                                            genVertexAttribData                             (void);
316 protected:
317         Move<VkPipelineLayout>          createPipelineLayout                    (const DeviceInterface& vk, const VkDevice device);
318         void                                            bindDescriptorSets                              (const DeviceInterface&         vk,
319                                                                                                                                  const VkDevice                         device,
320                                                                                                                                  Allocator&                                     memAlloc,
321                                                                                                                                  const VkCommandBuffer&         cmdBuffer,
322                                                                                                                                  const VkPipelineLayout&        pipelineLayout);
323 private:
324         void                                            genVertexDataWithoutInstancing  (void);
325         void                                            genVertexDataWithInstancing             (void);
326
327         const VaryingSource                     m_test;
328         const ShaderInstancingMode      m_mode;
329         const deInt32                           m_maxEmitCount;
330         Move<VkDescriptorPool>          m_descriptorPool;
331         Move<VkDescriptorSetLayout>     m_descriptorSetLayout;
332         Move<VkDescriptorSet>           m_descriptorSet;
333         Move<VkBuffer>                          m_buffer;
334         Move<VkImage>                           m_texture;
335         Move<VkImageView>                       m_imageView;
336         Move<VkSampler>                         m_sampler;
337         de::MovePtr<Allocation>         m_allocation;
338 };
339
340 VaryingOutputCountTestInstance::VaryingOutputCountTestInstance (Context&                                        context,
341                                                                                                                                 const char*                                     name,
342                                                                                                                                 const VkPrimitiveTopology       primitiveType,
343                                                                                                                                 const VaryingSource                     test,
344                                                                                                                                 const ShaderInstancingMode      mode)
345         : GeometryExpanderRenderTestInstance    (context, primitiveType, name)
346         , m_test                                                                (test)
347         , m_mode                                                                (mode)
348         , m_maxEmitCount                                                (128)
349 {
350         genVertexAttribData ();
351 }
352
353 void VaryingOutputCountTestInstance::genVertexAttribData (void)
354 {
355         if (m_mode == MODE_WITHOUT_INSTANCING)
356                 genVertexDataWithoutInstancing();
357         else if (m_mode == MODE_WITH_INSTANCING)
358                 genVertexDataWithInstancing();
359         else
360                 DE_ASSERT(false);
361 }
362
363 Move<VkPipelineLayout> VaryingOutputCountTestInstance::createPipelineLayout (const DeviceInterface& vk, const VkDevice device)
364 {
365         if (m_test == READ_UNIFORM)
366         {
367                 m_descriptorSetLayout   =       DescriptorSetLayoutBuilder()
368                                                                         .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_GEOMETRY_BIT)
369                                                                         .build(vk, device);
370                 m_descriptorPool                =       DescriptorPoolBuilder()
371                                                                         .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER)
372                                                                         .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
373                 m_descriptorSet                 =       makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
374
375                 return makePipelineLayout(vk, device, *m_descriptorSetLayout);
376         }
377         else if (m_test == READ_TEXTURE)
378         {
379                 const tcu::Vec4                         data[4]                         =
380                                                                                                                 {
381                                                                                                                         tcu::Vec4(255, 0, 0, 0),
382                                                                                                                         tcu::Vec4(0, 255, 0, 0),
383                                                                                                                         tcu::Vec4(0, 0, 255, 0),
384                                                                                                                         tcu::Vec4(0, 0, 0, 255)
385                                                                                                                 };
386                 const tcu::UVec2                        viewportSize            (4, 1);
387                 const tcu::TextureFormat        texFormat                       = glu::mapGLInternalFormat(GL_RGBA8);
388                 const VkFormat                          format                          = mapTextureFormat(texFormat);
389                 const VkImageUsageFlags         imageUsageFlags         = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
390                 Allocator&                                      memAlloc                        = m_context.getDefaultAllocator();
391                 tcu::TextureLevel                       texture                         (texFormat, static_cast<int>(viewportSize.x()), static_cast<int>(viewportSize.y()));
392
393                 // Fill with data
394                 {
395                         tcu::PixelBufferAccess access = texture.getAccess();
396                         for (int x = 0; x < texture.getWidth(); ++x)
397                                 access.setPixel(data[x], x, 0);
398                 }
399                 // Create image
400                 const VkImageCreateInfo                 imageParams =
401                 {
402                         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,    // VkStructureType                      sType;
403                         DE_NULL,                                                                // const void*                          pNext;
404                         0,                                                                              // VkImageCreateFlags           flags;
405                         VK_IMAGE_TYPE_2D,                                               // VkImageType                          imageType;
406                         format,                                                                 // VkFormat                                     format;
407                         {                                                                               // VkExtent3D                           extent;
408                                         viewportSize.x(),
409                                         viewportSize.y(),
410                                         1u,
411                         },
412                         1u,                                                     // deUint32                                     mipLevels;
413                         1u,                                                     // deUint32                                     arrayLayers;
414                         VK_SAMPLE_COUNT_1_BIT,          // VkSampleCountFlagBits        samples;
415                         VK_IMAGE_TILING_OPTIMAL,        // VkImageTiling                        tiling;
416                         imageUsageFlags,                        // VkImageUsageFlags            usage;
417                         VK_SHARING_MODE_EXCLUSIVE,      // VkSharingMode                        sharingMode;
418                         0u,                                                     // deUint32                                     queueFamilyIndexCount;
419                         DE_NULL,                                        // const deUint32*                      pQueueFamilyIndices;
420                         VK_IMAGE_LAYOUT_UNDEFINED       // VkImageLayout                        initialLayout;
421                 };
422
423                 m_texture               = createImage(vk, device, &imageParams);
424                 m_allocation    = memAlloc.allocate(getImageMemoryRequirements(vk, device, *m_texture), MemoryRequirement::Any);
425                 VK_CHECK(vk.bindImageMemory(device, *m_texture, m_allocation->getMemory(), m_allocation->getOffset()));
426                 uploadImage(m_context, texture.getAccess(), *m_texture);
427
428                 m_descriptorSetLayout   =       DescriptorSetLayoutBuilder()
429                                                                         .addSingleBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_GEOMETRY_BIT)
430                                                                         .build(vk, device);
431                 m_descriptorPool                =       DescriptorPoolBuilder()
432                                                                         .addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
433                                                                         .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
434                 m_descriptorSet                 =       makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
435
436                 return makePipelineLayout(vk, device, *m_descriptorSetLayout);
437         }
438         else
439                 return makePipelineLayout(vk, device);
440 }
441
442 void VaryingOutputCountTestInstance::bindDescriptorSets (const DeviceInterface& vk, const VkDevice device, Allocator& memAlloc,
443                                                                                                                  const VkCommandBuffer& cmdBuffer, const VkPipelineLayout& pipelineLayout)
444 {
445         if (m_test == READ_UNIFORM)
446         {
447                 const deInt32                           emitCount[4]            = { 6, 0, m_maxEmitCount, 10 };
448                 const VkBufferCreateInfo        bufferCreateInfo        = makeBufferCreateInfo(sizeof(emitCount), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
449                 m_buffer                                                                                = createBuffer(vk, device, &bufferCreateInfo);
450                 m_allocation                                                                    = memAlloc.allocate(getBufferMemoryRequirements(vk, device, *m_buffer), MemoryRequirement::HostVisible);
451
452                 VK_CHECK(vk.bindBufferMemory(device, *m_buffer, m_allocation->getMemory(), m_allocation->getOffset()));
453                 {
454                         deMemcpy(m_allocation->getHostPtr(), &emitCount[0], sizeof(emitCount));
455                         flushMappedMemoryRange(vk, device, m_allocation->getMemory(), m_allocation->getOffset(), sizeof(emitCount));
456
457                         const VkDescriptorBufferInfo bufferDescriptorInfo = makeDescriptorBufferInfo(*m_buffer, 0ull, sizeof(emitCount));
458
459                         DescriptorSetUpdateBuilder()
460                                 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &bufferDescriptorInfo)
461                                 .update(vk, device);
462                         vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0u, 1u, &*m_descriptorSet, 0u, DE_NULL);
463                 }
464         }
465         else if (m_test == READ_TEXTURE)
466         {
467                 const tcu::TextureFormat        texFormat                       = glu::mapGLInternalFormat(GL_RGBA8);
468                 const VkFormat                          format                          = mapTextureFormat(texFormat);
469                 const VkSamplerCreateInfo       samplerParams           =
470                                                                                                                 {
471                                                                                                                         VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,          // VkStructureType                      sType;
472                                                                                                                         DE_NULL,                                                                        // const void*                          pNext;
473                                                                                                                         0u,                                                                                     // VkSamplerCreateFlags         flags;
474                                                                                                                         VK_FILTER_NEAREST,                                                      // VkFilter                                     magFilter;
475                                                                                                                         VK_FILTER_NEAREST,                                                      // VkFilter                                     minFilter;
476                                                                                                                         VK_SAMPLER_MIPMAP_MODE_NEAREST,                         // VkSamplerMipmapMode          mipmapMode;
477                                                                                                                         VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,          // VkSamplerAddressMode         addressModeU;
478                                                                                                                         VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,          // VkSamplerAddressMode         addressModeV;
479                                                                                                                         VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,          // VkSamplerAddressMode         addressModeW;
480                                                                                                                         0.0f,                                                                           // float                                        mipLodBias;
481                                                                                                                         VK_FALSE,                                                                       // VkBool32                                     anisotropyEnable;
482                                                                                                                         1.0f,                                                                           // float                                        maxAnisotropy;
483                                                                                                                         false,                                                                          // VkBool32                                     compareEnable;
484                                                                                                                         VK_COMPARE_OP_NEVER,                                            // VkCompareOp                          compareOp;
485                                                                                                                         0.0f,                                                                           // float                                        minLod;
486                                                                                                                         0.0f,                                                                           // float                                        maxLod;
487                                                                                                                         VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,        // VkBorderColor                        borderColor;
488                                                                                                                         false                                                                           // VkBool32                                     unnormalizedCoordinates;
489                                                                                                                 };
490                 m_sampler                                                                               = createSampler(vk, device, &samplerParams);
491                 const VkImageViewCreateInfo     viewParams                      =
492                                                                                                                 {
493                                                                                                                         VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,       // VkStructureType                      sType;
494                                                                                                                         NULL,                                                                           // const voide*                         pNext;
495                                                                                                                         0u,                                                                                     // VkImageViewCreateFlags       flags;
496                                                                                                                         *m_texture,                                                                     // VkImage                                      image;
497                                                                                                                         VK_IMAGE_VIEW_TYPE_2D,                                          // VkImageViewType                      viewType;
498                                                                                                                         format,                                                                         // VkFormat                                     format;
499                                                                                                                         makeComponentMappingRGBA(),                                     // VkChannelMapping                     channels;
500                                                                                                                         {
501                                                                                                                                 VK_IMAGE_ASPECT_COLOR_BIT,                              // VkImageAspectFlags   aspectMask;
502                                                                                                                                 0u,                                                                             // deUint32                             baseMipLevel;
503                                                                                                                                 1u,                                                                             // deUint32                             mipLevels;
504                                                                                                                                 0,                                                                              // deUint32                             baseArraySlice;
505                                                                                                                                 1u                                                                              // deUint32                             arraySize;
506                                                                                                                         },                                                                                      // VkImageSubresourceRange      subresourceRange;
507                                                                                                                 };
508                 m_imageView                                                                             = createImageView(vk, device, &viewParams);
509                 const VkDescriptorImageInfo descriptorImageInfo = makeDescriptorImageInfo (*m_sampler, *m_imageView, VK_IMAGE_LAYOUT_GENERAL);
510                 DescriptorSetUpdateBuilder()
511                         .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &descriptorImageInfo)
512                         .update(vk, device);
513                 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0u, 1u, &*m_descriptorSet, 0u, DE_NULL);
514         }
515 }
516
517 void VaryingOutputCountTestInstance::genVertexDataWithoutInstancing (void)
518 {
519         m_numDrawVertices = 4;
520         m_vertexPosData.resize(m_numDrawVertices);
521         m_vertexAttrData.resize(m_numDrawVertices);
522
523         m_vertexPosData[0] = tcu::Vec4( 0.5f,  0.0f, 0.0f, 1.0f);
524         m_vertexPosData[1] = tcu::Vec4( 0.0f,  0.5f, 0.0f, 1.0f);
525         m_vertexPosData[2] = tcu::Vec4(-0.7f, -0.1f, 0.0f, 1.0f);
526         m_vertexPosData[3] = tcu::Vec4(-0.1f, -0.7f, 0.0f, 1.0f);
527
528         if (m_test == READ_ATTRIBUTE)
529         {
530                 m_vertexAttrData[0] = tcu::Vec4(((EMIT_COUNT_VERTEX_0 == -1) ? ((float)m_maxEmitCount) : ((float)EMIT_COUNT_VERTEX_0)), 0.0f, 0.0f, 0.0f);
531                 m_vertexAttrData[1] = tcu::Vec4(((EMIT_COUNT_VERTEX_1 == -1) ? ((float)m_maxEmitCount) : ((float)EMIT_COUNT_VERTEX_1)), 0.0f, 0.0f, 0.0f);
532                 m_vertexAttrData[2] = tcu::Vec4(((EMIT_COUNT_VERTEX_2 == -1) ? ((float)m_maxEmitCount) : ((float)EMIT_COUNT_VERTEX_2)), 0.0f, 0.0f, 0.0f);
533                 m_vertexAttrData[3] = tcu::Vec4(((EMIT_COUNT_VERTEX_3 == -1) ? ((float)m_maxEmitCount) : ((float)EMIT_COUNT_VERTEX_3)), 0.0f, 0.0f, 0.0f);
534         }
535         else
536         {
537                 m_vertexAttrData[0] = tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f);
538                 m_vertexAttrData[1] = tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f);
539                 m_vertexAttrData[2] = tcu::Vec4(2.0f, 0.0f, 0.0f, 0.0f);
540                 m_vertexAttrData[3] = tcu::Vec4(3.0f, 0.0f, 0.0f, 0.0f);
541         }
542 }
543
544 void VaryingOutputCountTestInstance::genVertexDataWithInstancing (void)
545 {
546         m_numDrawVertices = 1;
547         m_vertexPosData.resize(m_numDrawVertices);
548         m_vertexAttrData.resize(m_numDrawVertices);
549
550         m_vertexPosData[0] = tcu::Vec4(0.0f,  0.0f, 0.0f, 1.0f);
551
552         if (m_test == READ_ATTRIBUTE)
553         {
554                 const int emitCounts[] =
555                 {
556                         (EMIT_COUNT_VERTEX_0 == -1) ? (m_maxEmitCount) : (EMIT_COUNT_VERTEX_0),
557                         (EMIT_COUNT_VERTEX_1 == -1) ? (m_maxEmitCount) : (EMIT_COUNT_VERTEX_1),
558                         (EMIT_COUNT_VERTEX_2 == -1) ? (m_maxEmitCount) : (EMIT_COUNT_VERTEX_2),
559                         (EMIT_COUNT_VERTEX_3 == -1) ? (m_maxEmitCount) : (EMIT_COUNT_VERTEX_3),
560                 };
561
562                 m_vertexAttrData[0] = tcu::Vec4((float)emitCounts[0], (float)emitCounts[1], (float)emitCounts[2], (float)emitCounts[3]);
563         }
564         else
565         {
566                 // not used
567                 m_vertexAttrData[0] = tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f);
568         }
569 }
570
571 class BuiltinVariableRenderTestInstance: public GeometryExpanderRenderTestInstance
572 {
573 public:
574                         BuiltinVariableRenderTestInstance       (Context&                               context,
575                                                                                                  const char*                    name,
576                                                                                                  const VariableTest             test,
577                                                                                                  const bool                             indicesTest);
578         void    genVertexAttribData                                     (void);
579         void    createIndicesBuffer                                     (void);
580
581 protected:
582         void    drawCommand                                                     (const VkCommandBuffer& cmdBuffer);
583
584 private:
585         const bool                              m_indicesTest;
586         std::vector<deUint16>   m_indices;
587         Move<vk::VkBuffer>              m_indicesBuffer;
588         MovePtr<Allocation>             m_allocation;
589 };
590
591 BuiltinVariableRenderTestInstance::BuiltinVariableRenderTestInstance (Context& context, const char* name, const VariableTest test, const bool indicesTest)
592         : GeometryExpanderRenderTestInstance    (context, (test == TEST_PRIMITIVE_ID_IN) ? VK_PRIMITIVE_TOPOLOGY_LINE_STRIP : VK_PRIMITIVE_TOPOLOGY_POINT_LIST, name)
593         , m_indicesTest                                                 (indicesTest)
594 {
595         genVertexAttribData();
596 }
597
598 void BuiltinVariableRenderTestInstance::genVertexAttribData (void)
599 {
600         m_numDrawVertices = 5;
601
602         m_vertexPosData.resize(m_numDrawVertices);
603         m_vertexPosData[0] = tcu::Vec4( 0.5f,  0.0f, 0.0f, 1.0f);
604         m_vertexPosData[1] = tcu::Vec4( 0.0f,  0.5f, 0.0f, 1.0f);
605         m_vertexPosData[2] = tcu::Vec4(-0.7f, -0.1f, 0.0f, 1.0f);
606         m_vertexPosData[3] = tcu::Vec4(-0.1f, -0.7f, 0.0f, 1.0f);
607         m_vertexPosData[4] = tcu::Vec4( 0.5f,  0.0f, 0.0f, 1.0f);
608
609         m_vertexAttrData.resize(m_numDrawVertices);
610         m_vertexAttrData[0] = tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f);
611         m_vertexAttrData[1] = tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f);
612         m_vertexAttrData[2] = tcu::Vec4(2.0f, 0.0f, 0.0f, 0.0f);
613         m_vertexAttrData[3] = tcu::Vec4(3.0f, 0.0f, 0.0f, 0.0f);
614         m_vertexAttrData[4] = tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f);
615
616         if (m_indicesTest)
617         {
618                 // Only used by primitive ID restart test
619                 m_indices.resize(m_numDrawVertices);
620                 m_indices[0] = 1;
621                 m_indices[1] = 4;
622                 m_indices[2] = 0xFFFF; // restart
623                 m_indices[3] = 2;
624                 m_indices[4] = 1;
625                 createIndicesBuffer();
626         }
627 }
628
629 void BuiltinVariableRenderTestInstance::createIndicesBuffer (void)
630 {
631         // Create vertex indices buffer
632         const DeviceInterface&                  vk                                      = m_context.getDeviceInterface();
633         const VkDevice                                  device                          = m_context.getDevice();
634         Allocator&                                              memAlloc                        = m_context.getDefaultAllocator();
635         const VkDeviceSize                              indexBufferSize         = m_indices.size() * sizeof(deUint16);
636         const VkBufferCreateInfo                indexBufferParams       =
637                                                                                                                 {
638                                                                                                                         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,   // VkStructureType              sType;
639                                                                                                                         DE_NULL,                                                                // const void*                  pNext;
640                                                                                                                         0u,                                                                             // VkBufferCreateFlags  flags;
641                                                                                                                         indexBufferSize,                                                // VkDeviceSize                 size;
642                                                                                                                         VK_BUFFER_USAGE_INDEX_BUFFER_BIT,               // VkBufferUsageFlags   usage;
643                                                                                                                         VK_SHARING_MODE_EXCLUSIVE,                              // VkSharingMode                sharingMode;
644                                                                                                                         0u,                                                                             // deUint32                             queueFamilyCount;
645                                                                                                                         DE_NULL                                                                 // const deUint32*              pQueueFamilyIndices;
646                                                                                                                 };
647
648         m_indicesBuffer = createBuffer(vk, device, &indexBufferParams);
649         m_allocation = memAlloc.allocate(getBufferMemoryRequirements(vk, device, *m_indicesBuffer), MemoryRequirement::HostVisible);
650         VK_CHECK(vk.bindBufferMemory(device, *m_indicesBuffer, m_allocation->getMemory(), m_allocation->getOffset()));
651         // Load indices into buffer
652         deMemcpy(m_allocation->getHostPtr(), &m_indices[0], (size_t)indexBufferSize);
653         flushMappedMemoryRange(vk, device, m_allocation->getMemory(), m_allocation->getOffset(), indexBufferSize);
654 }
655
656 void BuiltinVariableRenderTestInstance::drawCommand (const VkCommandBuffer&     cmdBuffer)
657 {
658         const DeviceInterface&  vk = m_context.getDeviceInterface();
659         if (m_indicesTest)
660         {
661                 vk.cmdBindIndexBuffer(cmdBuffer, *m_indicesBuffer, 0, VK_INDEX_TYPE_UINT16);
662                 vk.cmdDrawIndexed(cmdBuffer, static_cast<deUint32>(m_indices.size()), 1, 0, 0, 0);
663         }
664         else
665                 vk.cmdDraw(cmdBuffer, static_cast<deUint32>(m_numDrawVertices), 1u, 0u, 0u);
666 }
667
668 class GeometryOutputCountTest : public TestCase
669 {
670 public:
671                                                         GeometryOutputCountTest (TestContext&           testCtx,
672                                                                                                          const char*            name,
673                                                                                                          const char*            description,
674                                                                                                          const vector<int>      pattern);
675
676         void                                    initPrograms                    (SourceCollections&                     sourceCollections) const;
677         virtual TestInstance*   createInstance                  (Context&                                       context) const;
678
679 protected:
680         const vector<int> m_pattern;
681 };
682
683 GeometryOutputCountTest::GeometryOutputCountTest (TestContext& testCtx, const char* name, const char* description, const vector<int> pattern)
684         : TestCase      (testCtx, name, description)
685         , m_pattern     (pattern)
686 {
687
688 }
689
690 void GeometryOutputCountTest::initPrograms (SourceCollections& sourceCollections) const
691 {
692         {
693                 std::ostringstream src;
694                 src     << "#version 310 es\n"
695                         <<"layout(location = 0) in highp vec4 a_position;\n"
696                         <<"layout(location = 1) in highp vec4 a_color;\n"
697                         <<"layout(location = 0) out highp vec4 v_geom_FragColor;\n"
698                         <<"void main (void)\n"
699                         <<"{\n"
700                         <<"     gl_Position = a_position;\n"
701                         <<"     v_geom_FragColor = a_color;\n"
702                         <<"}\n";
703                 sourceCollections.glslSources.add("vertex") << glu::VertexSource(src.str());
704         }
705
706         {
707                 const int max_vertices = m_pattern.size() == 2 ? std::max(m_pattern[0], m_pattern[1]) : m_pattern[0];
708
709                 std::ostringstream src;
710                 src     << "#version 310 es\n"
711                         << "#extension GL_EXT_geometry_shader : require\n"
712                         << "#extension GL_OES_texture_storage_multisample_2d_array : require\n"
713                         << "layout(points) in;\n"
714                         << "layout(triangle_strip, max_vertices = " << max_vertices << ") out;\n"
715                         << "layout(location = 0) in highp vec4 v_geom_FragColor[];\n"
716                         << "layout(location = 0) out highp vec4 v_frag_FragColor;\n"
717                         << "void main (void)\n"
718                         << "{\n"
719                         << "    const highp float rowHeight = 2.0 / float(" << m_pattern.size() << ");\n"
720                         << "    const highp float colWidth = 2.0 / float(" << max_vertices << ");\n";
721
722                 if (m_pattern.size() == 2)
723                         src     << "    highp int emitCount = (gl_PrimitiveIDIn == 0) ? (" << m_pattern[0] << ") : (" << m_pattern[1] << ");\n";
724                 else
725                         src     << "    highp int emitCount = " << m_pattern[0] << ";\n";
726                 src     << "    for (highp int ndx = 0; ndx < emitCount / 2; ndx++)\n"
727                         << "    {\n"
728                         << "            gl_Position = gl_in[0].gl_Position + vec4(float(ndx) * 2.0 * colWidth, 0.0, 0.0, 0.0);\n"
729                         << "            v_frag_FragColor = v_geom_FragColor[0];\n"
730                         << "            EmitVertex();\n"
731
732                         << "            gl_Position = gl_in[0].gl_Position + vec4(float(ndx) * 2.0 * colWidth, rowHeight, 0.0, 0.0);\n"
733                         << "            v_frag_FragColor = v_geom_FragColor[0];\n"
734                         << "            EmitVertex();\n"
735
736                         << "    }\n"
737                         << "}\n";
738                 sourceCollections.glslSources.add("geometry") << glu::GeometrySource(src.str());
739         }
740
741         {
742                 std::ostringstream src;
743                 src     << "#version 310 es\n"
744                         <<"layout(location = 0) out mediump vec4 fragColor;\n"
745                         <<"layout(location = 0) in highp vec4 v_frag_FragColor;\n"
746                         <<"void main (void)\n"
747                         <<"{\n"
748                         <<"     fragColor = v_frag_FragColor;\n"
749                         <<"}\n";
750                 sourceCollections.glslSources.add("fragment") << glu::FragmentSource(src.str());
751         }
752 }
753
754 TestInstance* GeometryOutputCountTest::createInstance (Context& context) const
755 {
756         return new GeometryOutputCountTestInstance (context, VK_PRIMITIVE_TOPOLOGY_POINT_LIST, static_cast<int>(m_pattern.size()), getName());
757 }
758
759 class VaryingOutputCountCase : public TestCase
760 {
761 public:
762                                                         VaryingOutputCountCase  (TestContext&                           testCtx,
763                                                                                                          const char*                            name,
764                                                                                                          const char*                            description,
765                                                                                                          const VaryingSource            test,
766                                                                                                          const ShaderInstancingMode     mode);
767         void                                    initPrograms                    (SourceCollections&                     sourceCollections) const;
768         virtual TestInstance*   createInstance                  (Context&                                       context) const;
769 protected:
770         const VaryingSource                     m_test;
771         const ShaderInstancingMode      m_mode;
772 };
773
774 VaryingOutputCountCase::VaryingOutputCountCase (TestContext& testCtx, const char* name, const char* description, const VaryingSource test, const ShaderInstancingMode mode)
775         : TestCase      (testCtx, name, description)
776         , m_test        (test)
777         , m_mode        (mode)
778 {
779 }
780
781 void VaryingOutputCountCase::initPrograms (SourceCollections& sourceCollections) const
782 {
783         {
784                 std::ostringstream src;
785                 switch(m_test)
786                 {
787                         case READ_ATTRIBUTE:
788                         case READ_TEXTURE:
789                                 src     << "#version 310 es\n"
790                                         << "layout(location = 0) in highp vec4 a_position;\n"
791                                         << "layout(location = 1) in highp vec4 a_emitCount;\n"
792                                         << "layout(location = 0) out highp vec4 v_geom_emitCount;\n"
793                                         << "void main (void)\n"
794                                         << "{\n"
795                                         << "    gl_Position = a_position;\n"
796                                         << "    v_geom_emitCount = a_emitCount;\n"
797                                         << "}\n";
798                                 break;
799                         case READ_UNIFORM:
800                                 src     << "#version 310 es\n"
801                                         << "layout(location = 0) in highp vec4 a_position;\n"
802                                         << "layout(location = 1) in highp vec4 a_vertexNdx;\n"
803                                         << "layout(location = 0) out highp vec4 v_geom_vertexNdx;\n"
804                                         << "void main (void)\n"
805                                         << "{\n"
806                                         << "    gl_Position = a_position;\n"
807                                         << "    v_geom_vertexNdx = a_vertexNdx;\n"
808                                         << "}\n";
809                                 break;
810                         default:
811                                 DE_ASSERT(0);
812                                 break;
813                 }
814                 sourceCollections.glslSources.add("vertex") << glu::VertexSource(src.str());
815         }
816
817         {
818                 const bool instanced = MODE_WITH_INSTANCING == m_mode;
819                 std::ostringstream src;
820                 src     << "#version 310 es\n"
821                         << "#extension GL_EXT_geometry_shader : require\n"
822                         << "#extension GL_OES_texture_storage_multisample_2d_array : require\n";
823                 if (instanced)
824                         src     << "layout(points, invocations=4) in;\n";
825                 else
826                         src     << "layout(points) in;\n";
827
828                 switch(m_test)
829                 {
830                         case READ_ATTRIBUTE:
831                                 src     << "layout(triangle_strip, max_vertices = 128) out;\n"
832                                         << "layout(location = 0) in highp vec4 v_geom_emitCount[];\n"
833                                         << "layout(location = 0) out highp vec4 v_frag_FragColor;\n"
834                                         << "void main (void)\n"
835                                         << "{\n"
836                                         << "    highp vec4 attrEmitCounts = v_geom_emitCount[0];\n"
837                                         << "    mediump int emitCount = int(attrEmitCounts[" << ((instanced) ? ("gl_InvocationID") : ("0")) << "]);\n"
838                                         << "    highp vec4 color = vec4((emitCount < 10) ? (0.0) : (1.0), (emitCount > 10) ? (0.0) : (1.0), 1.0, 1.0);\n"
839                                         << "    highp vec4 basePos = " << ((instanced) ? ("gl_in[0].gl_Position + 0.5 * vec4(cos(float(gl_InvocationID)), sin(float(gl_InvocationID)), 0.0, 0.0)") : ("gl_in[0].gl_Position")) << ";\n"
840                                         << "    for (mediump int i = 0; i < emitCount / 2; i++)\n"
841                                         << "    {\n"
842                                         << "            highp float angle = (float(i) + 0.5) / float(emitCount / 2) * 3.142;\n"
843                                         << "            gl_Position = basePos + vec4(cos(angle),  sin(angle), 0.0, 0.0) * 0.15;\n"
844                                         << "            v_frag_FragColor = color;\n"
845                                         << "            EmitVertex();\n"
846                                         << "            gl_Position = basePos + vec4(cos(angle), -sin(angle), 0.0, 0.0) * 0.15;\n"
847                                         << "            v_frag_FragColor = color;\n"
848                                         << "            EmitVertex();\n"
849                                         << "    }\n"
850                                         <<"}\n";
851                                 break;
852                         case READ_UNIFORM:
853                                 src     << "layout(triangle_strip, max_vertices = 128) out;\n"
854                                         << "layout(location = 0) in highp vec4 v_geom_vertexNdx[];\n"
855                                         << "layout(binding = 0) readonly uniform Input {\n"
856                                         << "    ivec4 u_emitCount;\n"
857                                         << "} emit;\n"
858                                         << "layout(location = 0) out highp vec4 v_frag_FragColor;\n"
859                                         << "void main (void)\n"
860                                         << "{\n"
861                                         << "    mediump int primitiveNdx = " << ((instanced) ? ("gl_InvocationID") : ("int(v_geom_vertexNdx[0].x)")) << ";\n"
862                                         << "    mediump int emitCount = emit.u_emitCount[primitiveNdx];\n"
863                                         << "\n"
864                                         << "    const highp vec4 red = vec4(1.0, 0.0, 0.0, 1.0);\n"
865                                         << "    const highp vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n"
866                                         << "    const highp vec4 blue = vec4(0.0, 0.0, 1.0, 1.0);\n"
867                                         << "    const highp vec4 yellow = vec4(1.0, 1.0, 0.0, 1.0);\n"
868                                         << "    const highp vec4 colors[4] = vec4[4](red, green, blue, yellow);\n"
869                                         << "    highp vec4 color = colors[int(primitiveNdx)];\n"
870                                         << "\n"
871                                         << "    highp vec4 basePos = " << ((instanced) ? ("gl_in[0].gl_Position + 0.5 * vec4(cos(float(gl_InvocationID)), sin(float(gl_InvocationID)), 0.0, 0.0)") : ("gl_in[0].gl_Position")) << ";\n"
872                                         << "    for (mediump int i = 0; i < emitCount / 2; i++)\n"
873                                         << "    {\n"
874                                         << "            highp float angle = (float(i) + 0.5) / float(emitCount / 2) * 3.142;\n"
875                                         << "            gl_Position = basePos + vec4(cos(angle),  sin(angle), 0.0, 0.0) * 0.15;\n"
876                                         << "            v_frag_FragColor = color;\n"
877                                         << "            EmitVertex();\n"
878                                         << "            gl_Position = basePos + vec4(cos(angle), -sin(angle), 0.0, 0.0) * 0.15;\n"
879                                         << "            v_frag_FragColor = color;\n"
880                                         << "            EmitVertex();\n"
881                                         << "    }\n"
882                                         <<"}\n";
883                                 break;
884                         case READ_TEXTURE:
885                                 src     << "layout(triangle_strip, max_vertices = 128) out;\n"
886                                         << "layout(location = 0) in highp vec4 v_geom_vertexNdx[];\n"
887                                         << "layout(binding = 0) uniform highp sampler2D u_sampler;\n"
888                                         << "layout(location = 0) out highp vec4 v_frag_FragColor;\n"
889                                         << "void main (void)\n"
890                                         << "{\n"
891                                         << "    highp float primitiveNdx = " << ((instanced) ? ("float(gl_InvocationID)") : ("v_geom_vertexNdx[0].x")) << ";\n"
892                                         << "    highp vec2 texCoord = vec2(1.0 / 8.0 + primitiveNdx / 4.0, 0.5);\n"
893                                         << "    highp vec4 texColor = texture(u_sampler, texCoord);\n"
894                                         << "    mediump int emitCount = 0;\n"
895                                         << "    if (texColor.x > 0.0)\n"
896                                         << "            emitCount += 6;\n"
897                                         << "    if (texColor.y > 0.0)\n"
898                                         << "            emitCount += 0;\n"
899                                         << "    if (texColor.z > 0.0)\n"
900                                         << "            emitCount += 128;\n"
901                                         << "    if (texColor.w > 0.0)\n"
902                                         << "            emitCount += 10;\n"
903                                         << "    const highp vec4 red = vec4(1.0, 0.0, 0.0, 1.0);\n"
904                                         << "    const highp vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n"
905                                         << "    const highp vec4 blue = vec4(0.0, 0.0, 1.0, 1.0);\n"
906                                         << "    const highp vec4 yellow = vec4(1.0, 1.0, 0.0, 1.0);\n"
907                                         << "    const highp vec4 colors[4] = vec4[4](red, green, blue, yellow);\n"
908                                         << "    highp vec4 color = colors[int(primitiveNdx)];\n"
909                                         << "    highp vec4 basePos = "<< ((instanced) ? ("gl_in[0].gl_Position + 0.5 * vec4(cos(float(gl_InvocationID)), sin(float(gl_InvocationID)), 0.0, 0.0)") : ("gl_in[0].gl_Position")) << ";\n"
910                                         << "    for (mediump int i = 0; i < emitCount / 2; i++)\n"
911                                         << "    {\n"
912                                         << "            highp float angle = (float(i) + 0.5) / float(emitCount / 2) * 3.142;\n"
913                                         << "            gl_Position = basePos + vec4(cos(angle),  sin(angle), 0.0, 0.0) * 0.15;\n"
914                                         << "            v_frag_FragColor = color;\n"
915                                         << "            EmitVertex();\n"
916                                         << "            gl_Position = basePos + vec4(cos(angle), -sin(angle), 0.0, 0.0) * 0.15;\n"
917                                         << "            v_frag_FragColor = color;\n"
918                                         << "            EmitVertex();\n"
919                                         << "    }\n"
920                                         <<"}\n";
921                                 break;
922                         default:
923                                 DE_ASSERT(0);
924                                 break;
925                 }
926                 sourceCollections.glslSources.add("geometry") << glu::GeometrySource(src.str());
927         }
928
929         {
930                 std::ostringstream src;
931                 src     << "#version 310 es\n"
932                         << "layout(location = 0) out mediump vec4 fragColor;\n"
933                         << "layout(location = 0) in highp vec4 v_frag_FragColor;\n"
934                         << "void main (void)\n"
935                         << "{\n"
936                         << "    fragColor = v_frag_FragColor;\n"
937                         << "}\n";
938                 sourceCollections.glslSources.add("fragment") << glu::FragmentSource(src.str());
939         }
940 }
941
942 TestInstance* VaryingOutputCountCase::createInstance (Context& context) const
943 {
944         return new VaryingOutputCountTestInstance (context, getName(), VK_PRIMITIVE_TOPOLOGY_POINT_LIST, m_test, m_mode);
945 }
946
947 class BuiltinVariableRenderTest : public TestCase
948 {
949 public:
950                                                         BuiltinVariableRenderTest       (TestContext&           testCtx,
951                                                                                                                 const char*                     name,
952                                                                                                                 const char*                     desc,
953                                                                                                                 const VariableTest      test,
954                                                                                                                 const bool                      flag = false);
955         void                                    initPrograms                            (SourceCollections&     sourceCollections) const;
956         virtual TestInstance*   createInstance                          (Context&                       context) const;
957 protected:
958         const VariableTest      m_test;
959         const bool                      m_flag;
960 };
961
962 BuiltinVariableRenderTest::BuiltinVariableRenderTest (TestContext& testCtx, const char* name, const char* description, const VariableTest test, const bool flag)
963         : TestCase      (testCtx, name, description)
964         , m_test        (test)
965         , m_flag        (flag)
966 {
967 }
968
969 void BuiltinVariableRenderTest::initPrograms (SourceCollections& sourceCollections) const
970 {
971         {
972                 std::ostringstream src;
973                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
974                         << "out gl_PerVertex\n"
975                         <<" {\n"
976                         << "    vec4 gl_Position;\n"
977                         << "    float gl_PointSize;\n"
978                         << "};\n"
979                         << "layout(location = 0) in vec4 a_position;\n";
980                 switch(m_test)
981                 {
982                         case TEST_POINT_SIZE:
983                                 src     << "layout(location = 1) in vec4 a_pointSize;\n"
984                                         << "layout(location = 0) out vec4 v_geom_pointSize;\n"
985                                         << "void main (void)\n"
986                                         << "{\n"
987                                         << "    gl_Position = a_position;\n"
988                                         << "    gl_PointSize = 1.0;\n"
989                                         << "    v_geom_pointSize = a_pointSize;\n"
990                                         << "}\n";
991                                 break;
992                         case TEST_PRIMITIVE_ID_IN:
993                                 src     << "void main (void)\n"
994                                         << "{\n"
995                                         << "    gl_Position = a_position;\n"
996                                         << "}\n";
997                                 break;
998                         case TEST_PRIMITIVE_ID:
999                                 src     << "layout(location = 1) in vec4 a_primitiveID;\n"
1000                                         << "layout(location = 0) out vec4 v_geom_primitiveID;\n"
1001                                         << "void main (void)\n"
1002                                         << "{\n"
1003                                         << "    gl_Position = a_position;\n"
1004                                         << "    v_geom_primitiveID = a_primitiveID;\n"
1005                                         << "}\n";
1006                                 break;
1007                         default:
1008                                 DE_ASSERT(0);
1009                                 break;
1010                 }
1011                 sourceCollections.glslSources.add("vertex") << glu::VertexSource(src.str());
1012         }
1013
1014         {
1015                 std::ostringstream src;
1016                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1017                         << "in gl_PerVertex\n"
1018                         <<"{\n"
1019                         << "    vec4 gl_Position;\n"
1020                         << "    float gl_PointSize;\n"
1021                         << "} gl_in[];\n"
1022                         << "out gl_PerVertex\n"
1023                         <<"{\n"
1024                         << "    vec4 gl_Position;\n"
1025                         << "    float gl_PointSize;\n"
1026                         << "};\n";
1027                 switch(m_test)
1028                 {
1029                         case TEST_POINT_SIZE:
1030                                 src     << "#extension GL_EXT_geometry_point_size : require\n"
1031                                         << "layout(points) in;\n"
1032                                         << "layout(points, max_vertices = 1) out;\n"
1033                                         << "layout(location = 0) in vec4 v_geom_pointSize[];\n"
1034                                         << "layout(location = 0) out vec4 v_frag_FragColor;\n"
1035                                         << "void main (void)\n"
1036                                         << "{\n"
1037                                         << "    gl_Position = gl_in[0].gl_Position;\n"
1038                                         << "    gl_PointSize = v_geom_pointSize[0].x + 1.0;\n"
1039                                         << "    v_frag_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
1040                                         << "    EmitVertex();\n"
1041                                         << "}\n";
1042                                 break;
1043                         case TEST_PRIMITIVE_ID_IN:
1044                                 src     << "layout(lines) in;\n"
1045                                         << "layout(triangle_strip, max_vertices = 10) out;\n"
1046                                         << "layout(location = 0) out vec4 v_frag_FragColor;\n"
1047                                         << "void main (void)\n"
1048                                         << "{\n"
1049                                         << "    const vec4 red = vec4(1.0, 0.0, 0.0, 1.0);\n"
1050                                         << "    const vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n"
1051                                         << "    const vec4 blue = vec4(0.0, 0.0, 1.0, 1.0);\n"
1052                                         << "    const vec4 yellow = vec4(1.0, 1.0, 0.0, 1.0);\n"
1053                                         << "    const vec4 colors[4] = vec4[4](red, green, blue, yellow);\n"
1054                                         << "    for (float percent=0.00; percent < 0.30; percent+=0.10)\n"
1055                                                         "{\n"
1056                                         << "            gl_Position = gl_in[0].gl_Position * vec4(1.0+percent, 1.0+percent, 1.0, 1.0);\n"
1057                                         << "            v_frag_FragColor = colors[gl_PrimitiveIDIn % 4];\n"
1058                                         << "            EmitVertex();\n"
1059                                         << "            gl_Position = gl_in[1].gl_Position * vec4(1.0+percent, 1.0+percent, 1.0, 1.0);\n"
1060                                         << "            v_frag_FragColor = colors[gl_PrimitiveIDIn % 4];\n"
1061                                         << "            EmitVertex();\n"
1062                                         << "    }\n"
1063                                         << "}\n";
1064                                 break;
1065                         case TEST_PRIMITIVE_ID:
1066                                 src     << "layout(points, invocations=1) in;\n"
1067                                         << "layout(triangle_strip, max_vertices = 3) out;\n"
1068                                         << "layout(location = 0) in vec4 v_geom_primitiveID[];\n"
1069                                         << "void main (void)\n"
1070                                         << "{\n"
1071                                         << "    gl_Position = gl_in[0].gl_Position + vec4(0.05, 0.0, 0.0, 0.0);\n"
1072                                         << "    gl_PrimitiveID = int(floor(v_geom_primitiveID[0].x)) + 3;\n"
1073                                         << "    EmitVertex();\n"
1074                                         << "    gl_Position = gl_in[0].gl_Position - vec4(0.05, 0.0, 0.0, 0.0);\n"
1075                                         << "    gl_PrimitiveID = int(floor(v_geom_primitiveID[0].x)) + 3;\n"
1076                                         << "    EmitVertex();\n"
1077                                         << "    gl_Position = gl_in[0].gl_Position + vec4(0.0, 0.05, 0.0, 0.0);\n"
1078                                         << "    gl_PrimitiveID = int(floor(v_geom_primitiveID[0].x)) + 3;\n"
1079                                         << "    EmitVertex();\n"
1080                                         << "}\n";
1081                                 break;
1082                         default:
1083                                 DE_ASSERT(0);
1084                                 break;
1085                 }
1086                 sourceCollections.glslSources.add("geometry") << glu::GeometrySource(src.str());
1087         }
1088
1089         {
1090                 std::ostringstream src;
1091                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n";
1092                 switch(m_test)
1093                 {
1094                         case TEST_POINT_SIZE:
1095                                 src     << "layout(location = 0) out vec4 fragColor;\n"
1096                                         << "layout(location = 0) in vec4 v_frag_FragColor;\n"
1097                                         << "void main (void)\n"
1098                                         << "{\n"
1099                                         << "    fragColor = v_frag_FragColor;\n"
1100                                         << "}\n";
1101                                 break;
1102                         case TEST_PRIMITIVE_ID_IN:
1103                                 src     << "layout(location = 0) out vec4 fragColor;\n"
1104                                         << "layout(location = 0) in vec4 v_frag_FragColor;\n"
1105                                         << "void main (void)\n"
1106                                         << "{\n"
1107                                         << "    fragColor = v_frag_FragColor;\n"
1108                                         << "}\n";
1109                                 break;
1110                         case TEST_PRIMITIVE_ID:
1111                                 src     << "layout(location = 0) out vec4 fragColor;\n"
1112                                         << "void main (void)\n"
1113                                         << "{\n"
1114                                         << "    const vec4 red                  = vec4(1.0, 0.0, 0.0, 1.0);\n"
1115                                         << "    const vec4 green                = vec4(0.0, 1.0, 0.0, 1.0);\n"
1116                                         << "    const vec4 blue                 = vec4(0.0, 0.0, 1.0, 1.0);\n"
1117                                         << "    const vec4 yellow               = vec4(1.0, 1.0, 0.0, 1.0);\n"
1118                                         << "    const vec4 colors[4]    = vec4[4](yellow, red, green, blue);\n"
1119                                         << "    fragColor = colors[gl_PrimitiveID % 4];\n"
1120                                         << "}\n";
1121                                 break;
1122                         default:
1123                                 DE_ASSERT(0);
1124                                 break;
1125                 }
1126                 sourceCollections.glslSources.add("fragment") << glu::FragmentSource(src.str());
1127         }
1128 }
1129
1130 TestInstance* BuiltinVariableRenderTest::createInstance (Context& context) const
1131 {
1132         if (m_test == TEST_POINT_SIZE && !checkPointSize(context.getInstanceInterface(), context.getPhysicalDevice()))
1133                         TCU_THROW(NotSupportedError, "Missing feature: pointSize");
1134         return new BuiltinVariableRenderTestInstance(context, getName(), m_test, m_flag);
1135 }
1136
1137 inline vector<int> createPattern (int count)
1138 {
1139         vector<int>     pattern;
1140         pattern.push_back(count);
1141         return pattern;
1142 }
1143
1144 inline vector<int> createPattern (int count0, int count1)
1145 {
1146         vector<int>     pattern;
1147         pattern.push_back(count0);
1148         pattern.push_back(count1);
1149         return pattern;
1150 }
1151
1152 } // anonymous
1153
1154 TestCaseGroup* createBasicGeometryShaderTests (TestContext& testCtx)
1155 {
1156         MovePtr<TestCaseGroup> basicGroup       (new tcu::TestCaseGroup(testCtx, "basic", "Basic tests."));
1157
1158         basicGroup->addChild(new GeometryOutputCountTest        (testCtx,       "output_10",                            "Output 10 vertices",                                                           createPattern(10)));
1159         basicGroup->addChild(new GeometryOutputCountTest        (testCtx,       "output_128",                           "Output 128 vertices",                                                          createPattern(128)));
1160         basicGroup->addChild(new GeometryOutputCountTest        (testCtx,       "output_10_and_100",            "Output 10 and 100 vertices in two invocations",        createPattern(10, 100)));
1161         basicGroup->addChild(new GeometryOutputCountTest        (testCtx,       "output_100_and_10",            "Output 100 and 10 vertices in two invocations",        createPattern(100, 10)));
1162         basicGroup->addChild(new GeometryOutputCountTest        (testCtx,       "output_0_and_128",                     "Output 0 and 128 vertices in two invocations",         createPattern(0, 128)));
1163         basicGroup->addChild(new GeometryOutputCountTest        (testCtx,       "output_128_and_0",                     "Output 128 and 0 vertices in two invocations",         createPattern(128, 0)));
1164
1165         basicGroup->addChild(new VaryingOutputCountCase         (testCtx,       "output_vary_by_attribute",                             "Output varying number of vertices",    READ_ATTRIBUTE, MODE_WITHOUT_INSTANCING));
1166         basicGroup->addChild(new VaryingOutputCountCase         (testCtx,       "output_vary_by_uniform",                               "Output varying number of vertices",    READ_UNIFORM,   MODE_WITHOUT_INSTANCING));
1167         basicGroup->addChild(new VaryingOutputCountCase         (testCtx,       "output_vary_by_texture",                               "Output varying number of vertices",    READ_TEXTURE,   MODE_WITHOUT_INSTANCING));
1168         basicGroup->addChild(new VaryingOutputCountCase         (testCtx,       "output_vary_by_attribute_instancing",  "Output varying number of vertices",    READ_ATTRIBUTE, MODE_WITH_INSTANCING));
1169         basicGroup->addChild(new VaryingOutputCountCase         (testCtx,       "output_vary_by_uniform_instancing",    "Output varying number of vertices",    READ_UNIFORM,   MODE_WITH_INSTANCING));
1170         basicGroup->addChild(new VaryingOutputCountCase         (testCtx,       "output_vary_by_texture_instancing",    "Output varying number of vertices",    READ_TEXTURE,   MODE_WITH_INSTANCING));
1171
1172         basicGroup->addChild(new BuiltinVariableRenderTest      (testCtx,       "point_size",                                   "test gl_PointSize",                                                            TEST_POINT_SIZE));
1173         basicGroup->addChild(new BuiltinVariableRenderTest      (testCtx,       "primitive_id_in",                              "test gl_PrimitiveIDIn",                                                        TEST_PRIMITIVE_ID_IN));
1174         basicGroup->addChild(new BuiltinVariableRenderTest      (testCtx,       "primitive_id_in_restarted",    "test gl_PrimitiveIDIn with primitive restart",         TEST_PRIMITIVE_ID_IN, true));
1175         basicGroup->addChild(new BuiltinVariableRenderTest      (testCtx,       "primitive_id",                                 "test gl_PrimitiveID",                                                          TEST_PRIMITIVE_ID));
1176
1177         return basicGroup.release();
1178 }
1179
1180 } // geometry
1181 } // vkt