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 
GeometryInputTestInstance(Context & context,const VkPrimitiveTopology primitiveType,const char * name)74 GeometryInputTestInstance::GeometryInputTestInstance	(Context&						context,
75 														 const VkPrimitiveTopology		primitiveType,
76 														 const char*					name)
77 	: GeometryExpanderRenderTestInstance	(context, primitiveType, name)
78 {
79 	genVertexAttribData();
80 }
81 
GeometryInputTestInstance(Context & context,const VkPrimitiveTopology primitiveType,const char * name,const int numDrawVertices)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 
genVertexAttribData(void)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 
128 protected:
129 	string					shaderGeometry				(bool						pointSize) const;
130 	const VkPrimitiveTopology	m_primitiveType;
131 	const VkPrimitiveTopology	m_outputType;
132 };
133 
GeometryExpanderRenderTest(TestContext & testCtx,const PrimitiveTestSpec & inputPrimitives)134 GeometryExpanderRenderTest::GeometryExpanderRenderTest (TestContext& testCtx, const PrimitiveTestSpec& inputPrimitives)
135 	: TestCase			(testCtx, inputPrimitives.name, inputPrimitives.name)
136 	, m_primitiveType	(inputPrimitives.primitiveType)
137 	, m_outputType		(inputPrimitives.outputType)
138 {
139 
140 }
141 
initPrograms(SourceCollections & sourceCollections) const142 void GeometryExpanderRenderTest::initPrograms (SourceCollections& sourceCollections) const
143 {
144 	{
145 		std::ostringstream src;
146 		src	<< "#version 310 es\n"
147 			<<"layout(location = 0) in highp vec4 a_position;\n"
148 			<<"layout(location = 1) in highp vec4 a_color;\n"
149 			<<"layout(location = 0) out highp vec4 v_geom_FragColor;\n"
150 			<<"void main (void)\n"
151 			<<"{\n"
152 			<<"	gl_Position = a_position;\n"
153 			<<"	v_geom_FragColor = a_color;\n"
154 			<<"}\n";
155 		sourceCollections.glslSources.add("vertex") << glu::VertexSource(src.str());
156 	}
157 
158 	{
159 		sourceCollections.glslSources.add("geometry") << glu::GeometrySource(shaderGeometry(false));
160 		if (m_outputType == VK_PRIMITIVE_TOPOLOGY_POINT_LIST)
161 			sourceCollections.glslSources.add("geometry_pointsize") << glu::GeometrySource(shaderGeometry(true));
162 	}
163 
164 	{
165 		std::ostringstream src;
166 		src	<< "#version 310 es\n"
167 			<<"layout(location = 0) out highp vec4 fragColor;\n"
168 			<<"layout(location = 0) in highp vec4 v_frag_FragColor;\n"
169 			<<"void main (void)\n"
170 			<<"{\n"
171 			<<"	fragColor = v_frag_FragColor;\n"
172 			<<"}\n";
173 		sourceCollections.glslSources.add("fragment") << glu::FragmentSource(src.str());
174 	}
175 }
176 
createInstance(Context & context) const177 TestInstance* GeometryExpanderRenderTest::createInstance (Context& context) const
178 {
179 	return new GeometryInputTestInstance(context, m_primitiveType, getName());
180 }
181 
shaderGeometry(bool pointSize) const182 string GeometryExpanderRenderTest::shaderGeometry (bool pointSize) const
183 {
184 	std::ostringstream src;
185 	src	<< "#version 310 es\n"
186 		<< "#extension GL_EXT_geometry_shader : require\n";
187 	if (pointSize)
188 		src	<<"#extension GL_EXT_geometry_point_size : require\n";
189 	src	<< "layout(" << inputTypeToGLString(m_primitiveType) << ") in;\n"
190 		<< "layout(" << outputTypeToGLString(m_outputType) << ", max_vertices = " << calcOutputVertices(m_primitiveType) << ") out;\n"
191 		<< "layout(location = 0) in highp vec4 v_geom_FragColor[];\n"
192 		<< "layout(location = 0) out highp vec4 v_frag_FragColor;\n"
193 		<< "\n"
194 		<< "void main (void)\n"
195 		<< "{\n"
196 		<< "	const highp vec4 offset0 = vec4(-0.07, -0.01, 0.0, 0.0);\n"
197 		<< "	const highp vec4 offset1 = vec4( 0.03, -0.03, 0.0, 0.0);\n"
198 		<< "	const highp vec4 offset2 = vec4(-0.01,  0.08, 0.0, 0.0);\n"
199 		<< "	highp vec4 yoffset = float(gl_PrimitiveIDIn) * vec4(0.02, 0.1, 0.0, 0.0);\n"
200 		<< "\n"
201 		<< "	for (highp int ndx = 0; ndx < gl_in.length(); ndx++)\n"
202 		<< "	{\n";
203 		if (pointSize)
204 			src	<< "		gl_PointSize = 1.0;\n";
205 	src	<< "		gl_Position = gl_in[ndx].gl_Position + offset0 + yoffset;\n"
206 		<< "		v_frag_FragColor = v_geom_FragColor[ndx];\n"
207 		<< "		EmitVertex();\n"
208 		<< "\n";
209 		if (pointSize)
210 			src	<< "		gl_PointSize = 1.0;\n";
211 	src	<< "		gl_Position = gl_in[ndx].gl_Position + offset1 + yoffset;\n"
212 		<< "		v_frag_FragColor = v_geom_FragColor[ndx];\n"
213 		<< "		EmitVertex();\n"
214 		<< "\n";
215 		if (pointSize)
216 			src	<< "		gl_PointSize = 1.0;\n";
217 	src	<< "		gl_Position = gl_in[ndx].gl_Position + offset2 + yoffset;\n"
218 		<< "		v_frag_FragColor = v_geom_FragColor[ndx];\n"
219 		<< "		EmitVertex();\n"
220 		<< "		EndPrimitive();\n"
221 		<< "	}\n"
222 		<< "}\n";
223 	return src.str();
224 }
225 
226 class TriangleStripAdjacencyVertexCountTest : public GeometryExpanderRenderTest
227 {
228 public:
229 							TriangleStripAdjacencyVertexCountTest	(TestContext& testCtx, const PrimitiveTestSpec& inputPrimitives, const int numInputVertices);
230 	virtual TestInstance*	createInstance							(Context& context) const;
231 private:
232 	const int	m_numInputVertices;
233 };
234 
TriangleStripAdjacencyVertexCountTest(TestContext & testCtx,const PrimitiveTestSpec & inputPrimitives,const int numInputVertices)235 TriangleStripAdjacencyVertexCountTest::TriangleStripAdjacencyVertexCountTest (TestContext& testCtx, const PrimitiveTestSpec& inputPrimitives, const int numInputVertices)
236 	: GeometryExpanderRenderTest	(testCtx, inputPrimitives)
237 	, m_numInputVertices			(numInputVertices)
238 {
239 }
240 
createInstance(Context & context) const241 TestInstance* TriangleStripAdjacencyVertexCountTest::createInstance (Context& context) const
242 {
243 	return new GeometryInputTestInstance(context, m_primitiveType, getName(), m_numInputVertices);
244 }
245 
246 } // anonymous
247 
createInputGeometryShaderTests(TestContext & testCtx)248 TestCaseGroup* createInputGeometryShaderTests (TestContext& testCtx)
249 {
250 	MovePtr<TestCaseGroup> inputPrimitiveGroup		(new TestCaseGroup(testCtx, "input", "Different input primitives."));
251 	MovePtr<TestCaseGroup> basicPrimitiveGroup		(new TestCaseGroup(testCtx, "basic_primitive", "Basic Primitive geometry tests"));
252 	MovePtr<TestCaseGroup> triStripAdjacencyGroup	(new TestCaseGroup(testCtx, "triangle_strip_adjacency",	"Different triangle_strip_adjacency vertex counts."));
253 	MovePtr<TestCaseGroup> conversionPrimitiveGroup	(new TestCaseGroup(testCtx, "conversion", "Different input and output primitives."));
254 
255 	const PrimitiveTestSpec inputPrimitives[] =
256 	{
257 		{ VK_PRIMITIVE_TOPOLOGY_POINT_LIST,						"points",					VK_PRIMITIVE_TOPOLOGY_POINT_LIST		},
258 		{ VK_PRIMITIVE_TOPOLOGY_LINE_LIST,						"lines",					VK_PRIMITIVE_TOPOLOGY_LINE_STRIP		},
259 		{ VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,						"line_strip",				VK_PRIMITIVE_TOPOLOGY_LINE_STRIP		},
260 		{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,					"triangles",				VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP	},
261 		{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,					"triangle_strip",			VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP	},
262 		{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,					"triangle_fan",				VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP	},
263 		{ VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY,		"lines_adjacency",			VK_PRIMITIVE_TOPOLOGY_LINE_STRIP		},
264 		{ VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY,		"line_strip_adjacency",		VK_PRIMITIVE_TOPOLOGY_LINE_STRIP		},
265 		{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY,	"triangles_adjacency",		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP	}
266 	};
267 
268 		// more basic types
269 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(inputPrimitives); ++ndx)
270 			basicPrimitiveGroup->addChild(new GeometryExpanderRenderTest(testCtx, inputPrimitives[ndx]));
271 
272 		// triangle strip adjacency with different vertex counts
273 		for (int vertexCount = 0; vertexCount <= 12; ++vertexCount)
274 		{
275 			const string name = "vertex_count_" + de::toString(vertexCount);
276 			const PrimitiveTestSpec primitives = { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY, name.c_str(), VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP };
277 
278 			triStripAdjacencyGroup->addChild(new TriangleStripAdjacencyVertexCountTest(testCtx, primitives, vertexCount));
279 		}
280 
281 		// different type conversions
282 		{
283 			static const PrimitiveTestSpec conversionPrimitives[] =
284 			{
285 				{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	"triangles_to_points",	VK_PRIMITIVE_TOPOLOGY_POINT_LIST	},
286 				{ VK_PRIMITIVE_TOPOLOGY_LINE_LIST,		"lines_to_points",		VK_PRIMITIVE_TOPOLOGY_POINT_LIST	},
287 				{ VK_PRIMITIVE_TOPOLOGY_POINT_LIST,		"points_to_lines",		VK_PRIMITIVE_TOPOLOGY_LINE_STRIP	},
288 				{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	"triangles_to_lines",	VK_PRIMITIVE_TOPOLOGY_LINE_STRIP	},
289 				{ VK_PRIMITIVE_TOPOLOGY_POINT_LIST,		"points_to_triangles",	VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP},
290 				{ VK_PRIMITIVE_TOPOLOGY_LINE_LIST,		"lines_to_triangles",	VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP}
291 			};
292 
293 			for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(conversionPrimitives); ++ndx)
294 				conversionPrimitiveGroup->addChild(new GeometryExpanderRenderTest(testCtx, conversionPrimitives[ndx]));
295 		}
296 
297 	inputPrimitiveGroup->addChild(basicPrimitiveGroup.release());
298 	inputPrimitiveGroup->addChild(triStripAdjacencyGroup.release());
299 	inputPrimitiveGroup->addChild(conversionPrimitiveGroup.release());
300 	return inputPrimitiveGroup.release();
301 }
302 
303 } // geometry
304 } // vkt
305