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