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