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 Varying Geometry Shader Tests
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktGeometryVaryingGeometryShaderTests.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
57 typedef enum VertexOutputs
58 {
59 VERTEXT_NO_OP = -1,
60 VERTEXT_ZERO,
61 VERTEXT_ONE
62 } VertexOut;
63 typedef enum GeometryOutputs
64 {
65 GEOMETRY_ZERO,
66 GEOMETRY_ONE,
67 GEOMETRY_TWO
68 } GeometryOut;
69
70 struct VaryingTestSpec
71 {
72 VertexOutputs vertexOutputs;
73 GeometryOutputs geometryOutputs;
74 const string name;
75 };
76
77 class GeometryVaryingTestInstance : public GeometryExpanderRenderTestInstance
78 {
79 public:
80 GeometryVaryingTestInstance(Context &context, const char *name);
81
82 void genVertexAttribData(void);
83 };
84
GeometryVaryingTestInstance(Context & context,const char * name)85 GeometryVaryingTestInstance::GeometryVaryingTestInstance(Context &context, const char *name)
86 : GeometryExpanderRenderTestInstance(context, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, name)
87 {
88 genVertexAttribData();
89 }
90
genVertexAttribData(void)91 void GeometryVaryingTestInstance::genVertexAttribData(void)
92 {
93 m_numDrawVertices = 3;
94 m_vertexPosData.resize(m_numDrawVertices);
95 m_vertexPosData[0] = tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f);
96 m_vertexPosData[1] = tcu::Vec4(0.0f, 0.5f, 0.0f, 1.0f);
97 m_vertexPosData[2] = tcu::Vec4(0.1f, 0.0f, 0.0f, 1.0f);
98
99 m_vertexAttrData.resize(m_numDrawVertices);
100 m_vertexAttrData[0] = tcu::Vec4(0.7f, 0.4f, 0.6f, 1.0f);
101 m_vertexAttrData[1] = tcu::Vec4(0.9f, 0.2f, 0.5f, 1.0f);
102 m_vertexAttrData[2] = tcu::Vec4(0.1f, 0.8f, 0.3f, 1.0f);
103 }
104
105 class VaryingTest : public TestCase
106 {
107 public:
108 VaryingTest(TestContext &testCtx, const VaryingTestSpec &varyingTestSpec);
109
110 void checkSupport(Context &context) const;
111 void initPrograms(SourceCollections &sourceCollections) const;
112 virtual TestInstance *createInstance(Context &context) const;
113
114 protected:
115 const VaryingTestSpec m_varyingTestSpec;
116 };
117
VaryingTest(TestContext & testCtx,const VaryingTestSpec & varyingTestSpec)118 VaryingTest::VaryingTest(TestContext &testCtx, const VaryingTestSpec &varyingTestSpec)
119 : TestCase(testCtx, varyingTestSpec.name)
120 , m_varyingTestSpec(varyingTestSpec)
121
122 {
123 }
124
checkSupport(Context & context) const125 void VaryingTest::checkSupport(Context &context) const
126 {
127 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
128 }
129
initPrograms(SourceCollections & sourceCollections) const130 void VaryingTest::initPrograms(SourceCollections &sourceCollections) const
131 {
132 {
133 std::ostringstream src;
134 src << "#version 310 es\n"
135 << "layout(location = 0) in highp vec4 a_position;\n"
136 << "layout(location = 1) in highp vec4 a_color;\n";
137 switch (m_varyingTestSpec.vertexOutputs)
138 {
139 case VERTEXT_NO_OP:
140 src << "void main (void)\n"
141 << "{\n"
142 << "}\n";
143 break;
144 case VERTEXT_ZERO:
145 src << "void main (void)\n"
146 << "{\n"
147 << " gl_Position = a_position;\n"
148 << "}\n";
149 break;
150 case VERTEXT_ONE:
151 src << "layout(location = 0) out highp vec4 v_geom_0;\n"
152 << "void main (void)\n"
153 << "{\n"
154 << " gl_Position = a_position;\n"
155 << " v_geom_0 = a_color;\n"
156 << "}\n";
157 break;
158 default:
159 DE_ASSERT(0);
160 }
161 sourceCollections.glslSources.add("vertex") << glu::VertexSource(src.str());
162 }
163
164 {
165 std::ostringstream src;
166 src << "#version 310 es\n"
167 << "#extension GL_EXT_geometry_shader : require\n"
168 << "layout(triangles) in;\n"
169 << "layout(triangle_strip, max_vertices = 3) out;\n";
170
171 if (m_varyingTestSpec.vertexOutputs == VERTEXT_ONE)
172 src << "layout(location = 0) in highp vec4 v_geom_0[];\n";
173
174 if (m_varyingTestSpec.geometryOutputs >= GEOMETRY_ONE)
175 src << "layout(location = 0) out highp vec4 v_frag_0;\n";
176 if (m_varyingTestSpec.geometryOutputs == GEOMETRY_TWO)
177 src << "layout(location = 1) out highp vec4 v_frag_1;\n";
178
179 src << "void main (void)\n"
180 << "{\n"
181 << " highp vec4 offset = vec4(-0.2, -0.2, 0.0, 0.0);\n"
182 << " highp vec4 inputColor;\n"
183 << "\n";
184 if (m_varyingTestSpec.vertexOutputs == VERTEXT_ONE)
185 src << " inputColor = v_geom_0[0];\n";
186 else
187 src << " inputColor = vec4(1.0, 0.0, 0.0, 1.0);\n";
188
189 if (m_varyingTestSpec.vertexOutputs == VERTEXT_NO_OP)
190 src << " gl_Position = vec4(0.0, 0.0, 0.0, 1.0) + offset;\n";
191 if (m_varyingTestSpec.vertexOutputs >= VERTEXT_ZERO)
192 src << " gl_Position = gl_in[0].gl_Position + offset;\n";
193
194 if (m_varyingTestSpec.geometryOutputs == GEOMETRY_ONE)
195 src << " v_frag_0 = inputColor;\n";
196 if (m_varyingTestSpec.geometryOutputs == GEOMETRY_TWO)
197 src << " v_frag_0 = inputColor * 0.5;\n"
198 << " v_frag_1 = inputColor.yxzw * 0.5;\n";
199
200 src << " EmitVertex();\n"
201 << "\n";
202 if (m_varyingTestSpec.vertexOutputs == VERTEXT_ONE)
203 src << " inputColor = v_geom_0[1];\n";
204 else
205 src << " inputColor = vec4(1.0, 0.0, 0.0, 1.0);\n";
206
207 if (m_varyingTestSpec.vertexOutputs == VERTEXT_NO_OP)
208 src << " gl_Position = vec4(1.0, 0.0, 0.0, 1.0) + offset;\n";
209 if (m_varyingTestSpec.vertexOutputs >= VERTEXT_ZERO)
210 src << " gl_Position = gl_in[1].gl_Position + offset;\n";
211
212 if (m_varyingTestSpec.geometryOutputs == GEOMETRY_ONE)
213 src << " v_frag_0 = inputColor;\n";
214 if (m_varyingTestSpec.geometryOutputs == GEOMETRY_TWO)
215 src << " v_frag_0 = inputColor * 0.5;\n"
216 << " v_frag_1 = inputColor.yxzw * 0.5;\n";
217
218 src << " EmitVertex();\n"
219 << "\n";
220
221 if (m_varyingTestSpec.vertexOutputs == VERTEXT_ONE)
222 src << " inputColor = v_geom_0[2];\n";
223 else
224 src << " inputColor = vec4(1.0, 0.0, 0.0, 1.0);\n";
225
226 if (m_varyingTestSpec.vertexOutputs == VERTEXT_NO_OP)
227 src << " gl_Position = vec4(1.0, 1.0, 0.0, 1.0) + offset;\n";
228 if (m_varyingTestSpec.vertexOutputs >= VERTEXT_ZERO)
229 src << " gl_Position = gl_in[2].gl_Position + offset;\n";
230
231 if (m_varyingTestSpec.geometryOutputs == GEOMETRY_ONE)
232 src << " v_frag_0 = inputColor;\n";
233 if (m_varyingTestSpec.geometryOutputs == GEOMETRY_TWO)
234 src << " v_frag_0 = inputColor * 0.5;\n"
235 << " v_frag_1 = inputColor.yxzw * 0.5;\n";
236
237 src << " EmitVertex();\n"
238 << "\n"
239 << " EndPrimitive();\n"
240 << "}\n";
241 sourceCollections.glslSources.add("geometry") << glu::GeometrySource(src.str());
242 }
243
244 {
245 std::ostringstream src;
246 src << "#version 310 es\n"
247 << "layout(location = 0) out highp vec4 fragColor;\n";
248 if (m_varyingTestSpec.geometryOutputs >= GEOMETRY_ONE)
249 src << "layout(location = 0) in highp vec4 v_frag_0;\n";
250 if (m_varyingTestSpec.geometryOutputs == GEOMETRY_TWO)
251 src << "layout(location = 1) in highp vec4 v_frag_1;\n";
252
253 src << "void main (void)\n"
254 << "{\n";
255 if (m_varyingTestSpec.geometryOutputs == GEOMETRY_ZERO)
256 src << "fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n";
257 if (m_varyingTestSpec.geometryOutputs == GEOMETRY_ONE)
258 src << " fragColor = v_frag_0;\n";
259 if (m_varyingTestSpec.geometryOutputs == GEOMETRY_TWO)
260 src << " fragColor = v_frag_0 + v_frag_1.yxzw;\n";
261 src << "}\n";
262 sourceCollections.glslSources.add("fragment") << glu::FragmentSource(src.str());
263 }
264 }
265
createInstance(Context & context) const266 TestInstance *VaryingTest::createInstance(Context &context) const
267 {
268 return new GeometryVaryingTestInstance(context, getName());
269 }
270
271 } // namespace
272
createVaryingGeometryShaderTests(TestContext & testCtx)273 TestCaseGroup *createVaryingGeometryShaderTests(TestContext &testCtx)
274 {
275 MovePtr<TestCaseGroup> varyingGroup(new TestCaseGroup(testCtx, "varying"));
276
277 // varying
278 {
279 static const VaryingTestSpec varyingTests[] = {
280 {VERTEXT_NO_OP, GEOMETRY_ONE, "vertex_no_op_geometry_out_1"},
281 {VERTEXT_ZERO, GEOMETRY_ONE, "vertex_out_0_geometry_out_1"},
282 {VERTEXT_ZERO, GEOMETRY_TWO, "vertex_out_0_geometry_out_2"},
283 {VERTEXT_ONE, GEOMETRY_ZERO, "vertex_out_1_geometry_out_0"},
284 {VERTEXT_ONE, GEOMETRY_TWO, "vertex_out_1_geometry_out_2"},
285 };
286
287 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(varyingTests); ++ndx)
288 varyingGroup->addChild(new VaryingTest(testCtx, varyingTests[ndx]));
289 }
290
291 return varyingGroup.release();
292 }
293
294 } // namespace geometry
295 } // namespace vkt
296