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 Emit Geometry Shader Tests
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktGeometryEmitGeometryShaderTests.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 de::MovePtr;
52 using std::string;
53 using tcu::TestCaseGroup;
54 using tcu::TestContext;
55 using tcu::TestStatus;
56 using tcu::Vec4;
57
58 typedef enum VertexOutputs
59 {
60 VERTEXT_NO_OP = -1,
61 VERTEXT_ZERO,
62 VERTEXT_ONE
63 } VertexOut;
64 typedef enum GeometryOutputs
65 {
66 GEOMETRY_ZERO,
67 GEOMETRY_ONE,
68 GEOMETRY_TWO
69 } GeometryOut;
70
71 struct EmitTestSpec
72 {
73 VkPrimitiveTopology primitiveTopology;
74 int emitCountA; //!< primitive A emit count
75 int endCountA; //!< primitive A end count
76 int emitCountB; //!<
77 int endCountB; //!<
78 string name;
79 string desc;
80 };
81
82 class GeometryEmitTestInstance : public GeometryExpanderRenderTestInstance
83 {
84 public:
85 GeometryEmitTestInstance(Context &context, const char *name);
86 void genVertexAttribData(void);
87 };
88
GeometryEmitTestInstance(Context & context,const char * name)89 GeometryEmitTestInstance::GeometryEmitTestInstance(Context &context, const char *name)
90 : GeometryExpanderRenderTestInstance(context, VK_PRIMITIVE_TOPOLOGY_POINT_LIST, name)
91 {
92 genVertexAttribData();
93 }
94
genVertexAttribData(void)95 void GeometryEmitTestInstance::genVertexAttribData(void)
96 {
97 m_numDrawVertices = 1;
98 m_vertexPosData.resize(m_numDrawVertices);
99 m_vertexPosData[0] = Vec4(0, 0, 0, 1);
100
101 m_vertexAttrData.resize(m_numDrawVertices);
102 m_vertexAttrData[0] = Vec4(1, 1, 1, 1);
103 }
104
105 class EmitTest : public TestCase
106 {
107 public:
108 EmitTest(TestContext &testCtx, const EmitTestSpec &emitTestSpec);
109
110 void initPrograms(SourceCollections &sourceCollections) const;
111 virtual TestInstance *createInstance(Context &context) const;
112 virtual void checkSupport(Context &context) const;
113
114 protected:
115 string shaderGeometry(bool pointSize) const;
116 const EmitTestSpec m_emitTestSpec;
117 };
118
EmitTest(TestContext & testCtx,const EmitTestSpec & emitTestSpec)119 EmitTest::EmitTest(TestContext &testCtx, const EmitTestSpec &emitTestSpec)
120 : TestCase(testCtx, emitTestSpec.name)
121 , m_emitTestSpec(emitTestSpec)
122
123 {
124 }
125
checkSupport(Context & context) const126 void EmitTest::checkSupport(Context &context) const
127 {
128 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
129 }
130
initPrograms(SourceCollections & sourceCollections) const131 void EmitTest::initPrograms(SourceCollections &sourceCollections) const
132 {
133 {
134 std::ostringstream src;
135 src << "#version 310 es\n"
136 << "layout(location = 0) in highp vec4 a_position;\n"
137 << "layout(location = 1) in highp vec4 a_color;\n"
138 << "layout(location = 0) out highp vec4 v_geom_FragColor;\n"
139 << "void main (void)\n"
140 << "{\n"
141 << " gl_Position = a_position;\n"
142 << " v_geom_FragColor = a_color;\n"
143 << "}\n";
144 sourceCollections.glslSources.add("vertex") << glu::VertexSource(src.str());
145 }
146
147 {
148 sourceCollections.glslSources.add("geometry") << glu::GeometrySource(shaderGeometry(false));
149 if (m_emitTestSpec.primitiveTopology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST)
150 sourceCollections.glslSources.add("geometry_pointsize") << glu::GeometrySource(shaderGeometry(true));
151 }
152
153 {
154 std::ostringstream src;
155 src << "#version 310 es\n"
156 << "layout(location = 0) out mediump vec4 fragColor;\n"
157 << "layout(location = 0) in highp vec4 v_frag_FragColor;\n"
158 << "void main (void)\n"
159 << "{\n"
160 << " fragColor = v_frag_FragColor;\n"
161 << "}\n";
162 sourceCollections.glslSources.add("fragment") << glu::FragmentSource(src.str());
163 }
164 }
165
createInstance(Context & context) const166 TestInstance *EmitTest::createInstance(Context &context) const
167 {
168 return new GeometryEmitTestInstance(context, getName());
169 }
170
shaderGeometry(bool pointSize) const171 string EmitTest::shaderGeometry(bool pointSize) const
172 {
173 std::ostringstream src;
174 src << "#version 310 es\n"
175 << "#extension GL_EXT_geometry_shader : require\n";
176 if (pointSize)
177 src << "#extension GL_EXT_geometry_point_size : require\n";
178 src << "layout(points) in;\n"
179 << "layout(" << outputTypeToGLString(m_emitTestSpec.primitiveTopology)
180 << ", max_vertices = " << (m_emitTestSpec.emitCountA + m_emitTestSpec.emitCountB + 1) << ") out;\n"
181 << "layout(location = 0) in highp vec4 v_geom_FragColor[];\n"
182 << "layout(location = 0) out highp vec4 v_frag_FragColor;\n"
183 << "void main (void)\n"
184 << "{\n"
185 << " const highp vec4 position0 = vec4(-0.5, 0.5, 0.0, 0.0);\n"
186 << " const highp vec4 position1 = vec4( 0.0, 0.1, 0.0, 0.0);\n"
187 << " const highp vec4 position2 = vec4( 0.5, 0.5, 0.0, 0.0);\n"
188 << " const highp vec4 position3 = vec4( 0.7, -0.2, 0.0, 0.0);\n"
189 << " const highp vec4 position4 = vec4( 0.2, 0.2, 0.0, 0.0);\n"
190 << " const highp vec4 position5 = vec4( 0.4, -0.3, 0.0, 0.0);\n";
191 for (int i = 0; i < m_emitTestSpec.emitCountA; ++i)
192 {
193 if (pointSize)
194 src << " gl_PointSize = 1.0;\n";
195 src << " gl_Position = gl_in[0].gl_Position + position" << i
196 << ";\n"
197 " gl_PrimitiveID = gl_PrimitiveIDIn;\n"
198 " v_frag_FragColor = v_geom_FragColor[0];\n"
199 " EmitVertex();\n"
200 "\n";
201 }
202
203 for (int i = 0; i < m_emitTestSpec.endCountA; ++i)
204 src << " EndPrimitive();\n";
205
206 for (int i = 0; i < m_emitTestSpec.emitCountB; ++i)
207 {
208 if (pointSize)
209 src << " gl_PointSize = 1.0;\n";
210 src << " gl_Position = gl_in[0].gl_Position + position" << (m_emitTestSpec.emitCountA + i)
211 << ";\n"
212 " gl_PrimitiveID = gl_PrimitiveIDIn;\n"
213 " v_frag_FragColor = v_geom_FragColor[0];\n"
214 " EmitVertex();\n"
215 "\n";
216 }
217
218 for (int i = 0; i < m_emitTestSpec.endCountB; ++i)
219 src << " EndPrimitive();\n";
220 src << "}\n";
221 return src.str();
222 }
223
224 } // namespace
225
createEmitGeometryShaderTests(TestContext & testCtx)226 TestCaseGroup *createEmitGeometryShaderTests(TestContext &testCtx)
227 {
228 MovePtr<TestCaseGroup> emitGroup(new TestCaseGroup(testCtx, "emit"));
229
230 // emit different amounts
231 {
232 EmitTestSpec emitTests[] = {
233 {VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 0, 0, 0, 0, "points", ""},
234 {VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 0, 1, 0, 0, "points", ""},
235 {VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 1, 1, 0, 0, "points", ""},
236 {VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 0, 2, 0, 0, "points", ""},
237 {VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 1, 2, 0, 0, "points", ""},
238 {VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, 0, 0, 0, 0, "line_strip", ""},
239 {VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, 0, 1, 0, 0, "line_strip", ""},
240 {VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, 1, 1, 0, 0, "line_strip", ""},
241 {VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, 2, 1, 0, 0, "line_strip", ""},
242 {VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, 0, 2, 0, 0, "line_strip", ""},
243 {VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, 1, 2, 0, 0, "line_strip", ""},
244 {VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, 2, 2, 0, 0, "line_strip", ""},
245 {VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, 2, 2, 2, 0, "line_strip", ""},
246 {VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 0, 0, 0, 0, "triangle_strip", ""},
247 {VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 0, 1, 0, 0, "triangle_strip", ""},
248 {VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 1, 1, 0, 0, "triangle_strip", ""},
249 {VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 2, 1, 0, 0, "triangle_strip", ""},
250 {VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 3, 1, 0, 0, "triangle_strip", ""},
251 {VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 0, 2, 0, 0, "triangle_strip", ""},
252 {VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 1, 2, 0, 0, "triangle_strip", ""},
253 {VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 2, 2, 0, 0, "triangle_strip", ""},
254 {VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 3, 2, 0, 0, "triangle_strip", ""},
255 {VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 3, 2, 3, 0, "triangle_strip", ""},
256 };
257
258 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(emitTests); ++ndx)
259 {
260 emitTests[ndx].name = std::string(emitTests[ndx].name) + "_emit_" +
261 de::toString(emitTests[ndx].emitCountA) + "_end_" +
262 de::toString(emitTests[ndx].endCountA);
263 emitTests[ndx].desc = std::string(emitTests[ndx].name) + " output, emit " +
264 de::toString(emitTests[ndx].emitCountA) + " vertices, call EndPrimitive " +
265 de::toString(emitTests[ndx].endCountA) + " times";
266
267 if (emitTests[ndx].emitCountB)
268 {
269 emitTests[ndx].name += "_emit_" + de::toString(emitTests[ndx].emitCountB) + "_end_" +
270 de::toString(emitTests[ndx].endCountB);
271 emitTests[ndx].desc += ", emit " + de::toString(emitTests[ndx].emitCountB) +
272 " vertices, call EndPrimitive " + de::toString(emitTests[ndx].endCountB) +
273 " times";
274 }
275
276 emitGroup->addChild(new EmitTest(testCtx, emitTests[ndx]));
277 }
278 }
279
280 return emitGroup.release();
281 }
282
283 } // namespace geometry
284 } // namespace vkt
285