Merge vk-gl-cts/vulkan-cts-1.2.7 into vk-gl-cts/vulkan-cts-1.2.8
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / geometry / vktGeometryInputGeometryShaderTests.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 Input Geometry Shader Tests
23  *//*--------------------------------------------------------------------*/
24
25 #include "vktGeometryInputGeometryShaderTests.hpp"
26 #include "vktGeometryBasicClass.hpp"
27 #include "vktGeometryTestsUtil.hpp"
28
29 #include "vkDefs.hpp"
30 #include "vktTestCase.hpp"
31 #include "vktTestCaseUtil.hpp"
32 #include "vkImageUtil.hpp"
33 #include "vkTypeUtil.hpp"
34 #include "vkPrograms.hpp"
35 #include "vkBuilderUtil.hpp"
36
37 #include "vkRefUtil.hpp"
38 #include "vkQueryUtil.hpp"
39 #include "vkMemUtil.hpp"
40
41 #include <string>
42
43 using namespace vk;
44
45 namespace vkt
46 {
47 namespace geometry
48 {
49 namespace
50 {
51 using tcu::Vec4;
52 using tcu::TestStatus;
53 using tcu::TestContext;
54 using tcu::TestCaseGroup;
55 using de::MovePtr;
56 using std::string;
57 using std::vector;
58
59 class GeometryInputTestInstance : public GeometryExpanderRenderTestInstance
60 {
61 public:
62                         GeometryInputTestInstance       (Context&                                       context,
63                                                                                  const VkPrimitiveTopology      primitiveType,
64                                                                                  const char*                            name);
65
66                         GeometryInputTestInstance       (Context&                                       context,
67                                                                                  const VkPrimitiveTopology      primitiveType,
68                                                                                  const char*                            name,
69                                                                                  const int                                      numDrawVertices);
70
71         void    genVertexAttribData                     (void);
72 };
73
74 GeometryInputTestInstance::GeometryInputTestInstance    (Context&                                               context,
75                                                                                                                  const VkPrimitiveTopology              primitiveType,
76                                                                                                                  const char*                                    name)
77         : GeometryExpanderRenderTestInstance    (context, primitiveType, name)
78 {
79         genVertexAttribData();
80 }
81
82 GeometryInputTestInstance::GeometryInputTestInstance    (Context&                                       context,
83                                                                                                                  const VkPrimitiveTopology      primitiveType,
84                                                                                                                  const char*                            name,
85                                                                                                                  const int                                      numDrawVertices)
86         : GeometryExpanderRenderTestInstance    (context, primitiveType, name)
87 {
88         genVertexAttribData();
89         m_numDrawVertices = numDrawVertices;
90 }
91
92 void GeometryInputTestInstance::genVertexAttribData (void)
93 {
94         // Create 1 X 2 grid in triangle strip adjacent - order
95         const float     scale   = 0.3f;
96         const Vec4      offset  (-0.5f, -0.2f, 0.0f, 1.0f);
97         m_numDrawVertices       = 12;
98
99         m_vertexPosData.resize(m_numDrawVertices);
100         m_vertexPosData[ 0] = Vec4( 0,  0, 0.0f, 0.0f) * scale + offset;
101         m_vertexPosData[ 1] = Vec4(-1, -1, 0.0f, 0.0f) * scale + offset;
102         m_vertexPosData[ 2] = Vec4( 0, -1, 0.0f, 0.0f) * scale + offset;
103         m_vertexPosData[ 3] = Vec4( 1,  1, 0.0f, 0.0f) * scale + offset;
104         m_vertexPosData[ 4] = Vec4( 1,  0, 0.0f, 0.0f) * scale + offset;
105         m_vertexPosData[ 5] = Vec4( 0, -2, 0.0f, 0.0f) * scale + offset;
106         m_vertexPosData[ 6] = Vec4( 1, -1, 0.0f, 0.0f) * scale + offset;
107         m_vertexPosData[ 7] = Vec4( 2,  1, 0.0f, 0.0f) * scale + offset;
108         m_vertexPosData[ 8] = Vec4( 2,  0, 0.0f, 0.0f) * scale + offset;
109         m_vertexPosData[ 9] = Vec4( 1, -2, 0.0f, 0.0f) * scale + offset;
110         m_vertexPosData[10] = Vec4( 2, -1, 0.0f, 0.0f) * scale + offset;
111         m_vertexPosData[11] = Vec4( 3,  0, 0.0f, 0.0f) * scale + offset;
112
113         // Red and white
114         m_vertexAttrData.resize(m_numDrawVertices);
115         for (int i = 0; i < m_numDrawVertices; ++i)
116                 m_vertexAttrData[i] = (i % 2 == 0) ? Vec4(1, 1, 1, 1) : Vec4(1, 0, 0, 1);
117 }
118
119 class GeometryExpanderRenderTest : public TestCase
120 {
121 public:
122                                                                 GeometryExpanderRenderTest      (TestContext&                           testCtx,
123                                                                                                                          const PrimitiveTestSpec&       inputPrimitives);
124
125         void                                            initPrograms                            (SourceCollections&                     sourceCollections) const;
126         virtual TestInstance*           createInstance                          (Context&                                       context) const;
127         virtual void                            checkSupport                            (Context&                                       context) const;
128
129 protected:
130         string                                          shaderGeometry                          (bool                                           pointSize) const;
131         const VkPrimitiveTopology       m_primitiveType;
132         const VkPrimitiveTopology       m_outputType;
133 };
134
135 GeometryExpanderRenderTest::GeometryExpanderRenderTest (TestContext& testCtx, const PrimitiveTestSpec& inputPrimitives)
136         : TestCase                      (testCtx, inputPrimitives.name, inputPrimitives.name)
137         , m_primitiveType       (inputPrimitives.primitiveType)
138         , m_outputType          (inputPrimitives.outputType)
139 {
140
141 }
142
143 void GeometryExpanderRenderTest::checkSupport (Context& context) const
144 {
145         context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
146
147         if (m_primitiveType == vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN &&
148                 context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
149                 !context.getPortabilitySubsetFeatures().triangleFans)
150         {
151                 TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Triangle fans are not supported by this implementation");
152         }
153 }
154
155 void GeometryExpanderRenderTest::initPrograms (SourceCollections& sourceCollections) const
156 {
157         {
158                 std::ostringstream src;
159                 src     << "#version 310 es\n"
160                         <<"layout(location = 0) in highp vec4 a_position;\n"
161                         <<"layout(location = 1) in highp vec4 a_color;\n"
162                         <<"layout(location = 0) out highp vec4 v_geom_FragColor;\n"
163                         <<"void main (void)\n"
164                         <<"{\n"
165                         <<"     gl_Position = a_position;\n"
166                         <<"     v_geom_FragColor = a_color;\n"
167                         <<"}\n";
168                 sourceCollections.glslSources.add("vertex") << glu::VertexSource(src.str());
169         }
170
171         {
172                 sourceCollections.glslSources.add("geometry") << glu::GeometrySource(shaderGeometry(false));
173                 if (m_outputType == VK_PRIMITIVE_TOPOLOGY_POINT_LIST)
174                         sourceCollections.glslSources.add("geometry_pointsize") << glu::GeometrySource(shaderGeometry(true));
175         }
176
177         {
178                 std::ostringstream src;
179                 src     << "#version 310 es\n"
180                         <<"layout(location = 0) out highp vec4 fragColor;\n"
181                         <<"layout(location = 0) in highp vec4 v_frag_FragColor;\n"
182                         <<"void main (void)\n"
183                         <<"{\n"
184                         <<"     fragColor = v_frag_FragColor;\n"
185                         <<"}\n";
186                 sourceCollections.glslSources.add("fragment") << glu::FragmentSource(src.str());
187         }
188 }
189
190 TestInstance* GeometryExpanderRenderTest::createInstance (Context& context) const
191 {
192         return new GeometryInputTestInstance(context, m_primitiveType, getName());
193 }
194
195 string GeometryExpanderRenderTest::shaderGeometry (bool pointSize) const
196 {
197         std::ostringstream src;
198         src     << "#version 310 es\n"
199                 << "#extension GL_EXT_geometry_shader : require\n";
200         if (pointSize)
201                 src     <<"#extension GL_EXT_geometry_point_size : require\n";
202         src     << "layout(" << inputTypeToGLString(m_primitiveType) << ") in;\n"
203                 << "layout(" << outputTypeToGLString(m_outputType) << ", max_vertices = " << calcOutputVertices(m_primitiveType) << ") out;\n"
204                 << "layout(location = 0) in highp vec4 v_geom_FragColor[];\n"
205                 << "layout(location = 0) out highp vec4 v_frag_FragColor;\n"
206                 << "\n"
207                 << "void main (void)\n"
208                 << "{\n"
209                 << "    const highp vec4 offset0 = vec4(-0.07, -0.01, 0.0, 0.0);\n"
210                 << "    const highp vec4 offset1 = vec4( 0.03, -0.03, 0.0, 0.0);\n"
211                 << "    const highp vec4 offset2 = vec4(-0.01,  0.08, 0.0, 0.0);\n"
212                 << "    highp vec4 yoffset = float(gl_PrimitiveIDIn) * vec4(0.02, 0.1, 0.0, 0.0);\n"
213                 << "\n"
214                 << "    for (highp int ndx = 0; ndx < gl_in.length(); ndx++)\n"
215                 << "    {\n";
216                 if (pointSize)
217                         src     << "            gl_PointSize = 1.0;\n";
218         src     << "            gl_Position = gl_in[ndx].gl_Position + offset0 + yoffset;\n"
219                 << "            v_frag_FragColor = v_geom_FragColor[ndx];\n"
220                 << "            EmitVertex();\n"
221                 << "\n";
222                 if (pointSize)
223                         src     << "            gl_PointSize = 1.0;\n";
224         src     << "            gl_Position = gl_in[ndx].gl_Position + offset1 + yoffset;\n"
225                 << "            v_frag_FragColor = v_geom_FragColor[ndx];\n"
226                 << "            EmitVertex();\n"
227                 << "\n";
228                 if (pointSize)
229                         src     << "            gl_PointSize = 1.0;\n";
230         src     << "            gl_Position = gl_in[ndx].gl_Position + offset2 + yoffset;\n"
231                 << "            v_frag_FragColor = v_geom_FragColor[ndx];\n"
232                 << "            EmitVertex();\n"
233                 << "            EndPrimitive();\n"
234                 << "    }\n"
235                 << "}\n";
236         return src.str();
237 }
238
239 class TriangleStripAdjacencyVertexCountTest : public GeometryExpanderRenderTest
240 {
241 public:
242                                                         TriangleStripAdjacencyVertexCountTest   (TestContext& testCtx, const PrimitiveTestSpec& inputPrimitives, const int numInputVertices);
243         virtual TestInstance*   createInstance                                                  (Context& context) const;
244 private:
245         const int       m_numInputVertices;
246 };
247
248 TriangleStripAdjacencyVertexCountTest::TriangleStripAdjacencyVertexCountTest (TestContext& testCtx, const PrimitiveTestSpec& inputPrimitives, const int numInputVertices)
249         : GeometryExpanderRenderTest    (testCtx, inputPrimitives)
250         , m_numInputVertices                    (numInputVertices)
251 {
252 }
253
254 TestInstance* TriangleStripAdjacencyVertexCountTest::createInstance (Context& context) const
255 {
256         return new GeometryInputTestInstance(context, m_primitiveType, getName(), m_numInputVertices);
257 }
258
259 } // anonymous
260
261 TestCaseGroup* createInputGeometryShaderTests (TestContext& testCtx)
262 {
263         MovePtr<TestCaseGroup> inputPrimitiveGroup              (new TestCaseGroup(testCtx, "input", "Different input primitives."));
264         MovePtr<TestCaseGroup> basicPrimitiveGroup              (new TestCaseGroup(testCtx, "basic_primitive", "Basic Primitive geometry tests"));
265         MovePtr<TestCaseGroup> triStripAdjacencyGroup   (new TestCaseGroup(testCtx, "triangle_strip_adjacency", "Different triangle_strip_adjacency vertex counts."));
266         MovePtr<TestCaseGroup> conversionPrimitiveGroup (new TestCaseGroup(testCtx, "conversion", "Different input and output primitives."));
267
268         const PrimitiveTestSpec inputPrimitives[] =
269         {
270                 { VK_PRIMITIVE_TOPOLOGY_POINT_LIST,                                             "points",                                       VK_PRIMITIVE_TOPOLOGY_POINT_LIST                },
271                 { VK_PRIMITIVE_TOPOLOGY_LINE_LIST,                                              "lines",                                        VK_PRIMITIVE_TOPOLOGY_LINE_STRIP                },
272                 { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,                                             "line_strip",                           VK_PRIMITIVE_TOPOLOGY_LINE_STRIP                },
273                 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,                                  "triangles",                            VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP    },
274                 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,                                 "triangle_strip",                       VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP    },
275                 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,                                   "triangle_fan",                         VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP    },
276                 { VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY,               "lines_adjacency",                      VK_PRIMITIVE_TOPOLOGY_LINE_STRIP                },
277                 { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY,              "line_strip_adjacency",         VK_PRIMITIVE_TOPOLOGY_LINE_STRIP                },
278                 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY,   "triangles_adjacency",          VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP    }
279         };
280
281                 // more basic types
282                 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(inputPrimitives); ++ndx)
283                         basicPrimitiveGroup->addChild(new GeometryExpanderRenderTest(testCtx, inputPrimitives[ndx]));
284
285                 // triangle strip adjacency with different vertex counts
286                 for (int vertexCount = 0; vertexCount <= 12; ++vertexCount)
287                 {
288                         const string name = "vertex_count_" + de::toString(vertexCount);
289                         const PrimitiveTestSpec primitives = { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY, name.c_str(), VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP };
290
291                         triStripAdjacencyGroup->addChild(new TriangleStripAdjacencyVertexCountTest(testCtx, primitives, vertexCount));
292                 }
293
294                 // different type conversions
295                 {
296                         static const PrimitiveTestSpec conversionPrimitives[] =
297                         {
298                                 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,  "triangles_to_points",  VK_PRIMITIVE_TOPOLOGY_POINT_LIST        },
299                                 { VK_PRIMITIVE_TOPOLOGY_LINE_LIST,              "lines_to_points",              VK_PRIMITIVE_TOPOLOGY_POINT_LIST        },
300                                 { VK_PRIMITIVE_TOPOLOGY_POINT_LIST,             "points_to_lines",              VK_PRIMITIVE_TOPOLOGY_LINE_STRIP        },
301                                 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,  "triangles_to_lines",   VK_PRIMITIVE_TOPOLOGY_LINE_STRIP        },
302                                 { VK_PRIMITIVE_TOPOLOGY_POINT_LIST,             "points_to_triangles",  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP},
303                                 { VK_PRIMITIVE_TOPOLOGY_LINE_LIST,              "lines_to_triangles",   VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP}
304                         };
305
306                         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(conversionPrimitives); ++ndx)
307                                 conversionPrimitiveGroup->addChild(new GeometryExpanderRenderTest(testCtx, conversionPrimitives[ndx]));
308                 }
309
310         inputPrimitiveGroup->addChild(basicPrimitiveGroup.release());
311         inputPrimitiveGroup->addChild(triStripAdjacencyGroup.release());
312         inputPrimitiveGroup->addChild(conversionPrimitiveGroup.release());
313         return inputPrimitiveGroup.release();
314 }
315
316 } // geometry
317 } // vkt