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