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