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