/*------------------------------------------------------------------------ * Vulkan Conformance Tests * ------------------------ * * Copyright (c) 2016 The Khronos Group Inc. * Copyright (c) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *//*! * \file * \brief Emit Geometry Shader Tests *//*--------------------------------------------------------------------*/ #include "vktGeometryEmitGeometryShaderTests.hpp" #include "vktGeometryBasicClass.hpp" #include "vktGeometryTestsUtil.hpp" #include "vkDefs.hpp" #include "vktTestCase.hpp" #include "vktTestCaseUtil.hpp" #include "vkImageUtil.hpp" #include "vkTypeUtil.hpp" #include "vkPrograms.hpp" #include "vkBuilderUtil.hpp" #include "vkRefUtil.hpp" #include "vkQueryUtil.hpp" #include "vkMemUtil.hpp" #include using namespace vk; namespace vkt { namespace geometry { namespace { using std::string; using de::MovePtr; using tcu::Vec4; using tcu::TestStatus; using tcu::TestContext; using tcu::TestCaseGroup; typedef enum VertexOutputs {VERTEXT_NO_OP = -1,VERTEXT_ZERO, VERTEXT_ONE} VertexOut; typedef enum GeometryOutputs {GEOMETRY_ZERO, GEOMETRY_ONE, GEOMETRY_TWO} GeometryOut; struct EmitTestSpec { VkPrimitiveTopology primitiveTopology; int emitCountA; //!< primitive A emit count int endCountA; //!< primitive A end count int emitCountB; //!< int endCountB; //!< string name; string desc; }; class GeometryEmitTestInstance : public GeometryExpanderRenderTestInstance { public: GeometryEmitTestInstance (Context& context, const char* name); void genVertexAttribData (void); }; GeometryEmitTestInstance::GeometryEmitTestInstance (Context& context, const char* name) : GeometryExpanderRenderTestInstance (context, VK_PRIMITIVE_TOPOLOGY_POINT_LIST, name) { genVertexAttribData(); } void GeometryEmitTestInstance::genVertexAttribData (void) { m_numDrawVertices = 1; m_vertexPosData.resize(m_numDrawVertices); m_vertexPosData[0] = Vec4(0, 0, 0, 1); m_vertexAttrData.resize(m_numDrawVertices); m_vertexAttrData[0] = Vec4(1, 1, 1, 1); } class EmitTest : public TestCase { public: EmitTest (TestContext& testCtx, const EmitTestSpec& emitTestSpec); void initPrograms (SourceCollections& sourceCollections) const; virtual TestInstance* createInstance (Context& context) const; virtual void checkSupport (Context& context) const; protected: string shaderGeometry (bool pointSize) const; const EmitTestSpec m_emitTestSpec; }; EmitTest::EmitTest (TestContext& testCtx, const EmitTestSpec& emitTestSpec) : TestCase (testCtx, emitTestSpec.name, emitTestSpec.desc) , m_emitTestSpec (emitTestSpec) { } void EmitTest::checkSupport (Context& context) const { context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER); } void EmitTest::initPrograms (SourceCollections& sourceCollections) const { { std::ostringstream src; src << "#version 310 es\n" << "layout(location = 0) in highp vec4 a_position;\n" << "layout(location = 1) in highp vec4 a_color;\n" << "layout(location = 0) out highp vec4 v_geom_FragColor;\n" << "void main (void)\n" << "{\n" << " gl_Position = a_position;\n" << " v_geom_FragColor = a_color;\n" << "}\n"; sourceCollections.glslSources.add("vertex") << glu::VertexSource(src.str()); } { sourceCollections.glslSources.add("geometry") << glu::GeometrySource(shaderGeometry(false)); if(m_emitTestSpec.primitiveTopology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST) sourceCollections.glslSources.add("geometry_pointsize") << glu::GeometrySource(shaderGeometry(true)); } { std::ostringstream src; src << "#version 310 es\n" << "layout(location = 0) out mediump vec4 fragColor;\n" << "layout(location = 0) in highp vec4 v_frag_FragColor;\n" << "void main (void)\n" << "{\n" << " fragColor = v_frag_FragColor;\n" <<"}\n"; sourceCollections.glslSources.add("fragment") << glu::FragmentSource(src.str()); } } TestInstance* EmitTest::createInstance (Context& context) const { return new GeometryEmitTestInstance(context, getName()); } string EmitTest::shaderGeometry (bool pointSize) const { std::ostringstream src; src << "#version 310 es\n" << "#extension GL_EXT_geometry_shader : require\n"; if (pointSize) src <<"#extension GL_EXT_geometry_point_size : require\n"; src << "layout(points) in;\n" << "layout(" << outputTypeToGLString(m_emitTestSpec.primitiveTopology) << ", max_vertices = " << (m_emitTestSpec.emitCountA + m_emitTestSpec.emitCountB +1) << ") out;\n" << "layout(location = 0) in highp vec4 v_geom_FragColor[];\n" << "layout(location = 0) out highp vec4 v_frag_FragColor;\n" << "void main (void)\n" << "{\n" << " const highp vec4 position0 = vec4(-0.5, 0.5, 0.0, 0.0);\n" << " const highp vec4 position1 = vec4( 0.0, 0.1, 0.0, 0.0);\n" << " const highp vec4 position2 = vec4( 0.5, 0.5, 0.0, 0.0);\n" << " const highp vec4 position3 = vec4( 0.7, -0.2, 0.0, 0.0);\n" << " const highp vec4 position4 = vec4( 0.2, 0.2, 0.0, 0.0);\n" << " const highp vec4 position5 = vec4( 0.4, -0.3, 0.0, 0.0);\n"; for (int i = 0; i < m_emitTestSpec.emitCountA; ++i) { if (pointSize) src << " gl_PointSize = 1.0;\n"; src << " gl_Position = gl_in[0].gl_Position + position" << i << ";\n" " gl_PrimitiveID = gl_PrimitiveIDIn;\n" " v_frag_FragColor = v_geom_FragColor[0];\n" " EmitVertex();\n" "\n"; } for (int i = 0; i < m_emitTestSpec.endCountA; ++i) src << " EndPrimitive();\n"; for (int i = 0; i < m_emitTestSpec.emitCountB; ++i) { if (pointSize) src << " gl_PointSize = 1.0;\n"; src << " gl_Position = gl_in[0].gl_Position + position" << (m_emitTestSpec.emitCountA + i) << ";\n" " gl_PrimitiveID = gl_PrimitiveIDIn;\n" " v_frag_FragColor = v_geom_FragColor[0];\n" " EmitVertex();\n" "\n"; } for (int i = 0; i < m_emitTestSpec.endCountB; ++i) src << " EndPrimitive();\n"; src << "}\n"; return src.str(); } } // anonymous TestCaseGroup* createEmitGeometryShaderTests (TestContext& testCtx) { MovePtr emitGroup (new TestCaseGroup(testCtx, "emit", "Different emit counts.")); // emit different amounts { EmitTestSpec emitTests[] = { { VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 0, 0, 0, 0, "points" , ""}, { VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 0, 1, 0, 0, "points" , ""}, { VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 1, 1, 0, 0, "points" , ""}, { VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 0, 2, 0, 0, "points" , ""}, { VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 1, 2, 0, 0, "points" , ""}, { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, 0, 0, 0, 0, "line_strip" , ""}, { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, 0, 1, 0, 0, "line_strip" , ""}, { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, 1, 1, 0, 0, "line_strip" , ""}, { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, 2, 1, 0, 0, "line_strip" , ""}, { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, 0, 2, 0, 0, "line_strip" , ""}, { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, 1, 2, 0, 0, "line_strip" , ""}, { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, 2, 2, 0, 0, "line_strip" , ""}, { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, 2, 2, 2, 0, "line_strip" , ""}, { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 0, 0, 0, 0, "triangle_strip", ""}, { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 0, 1, 0, 0, "triangle_strip", ""}, { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 1, 1, 0, 0, "triangle_strip", ""}, { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 2, 1, 0, 0, "triangle_strip", ""}, { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 3, 1, 0, 0, "triangle_strip", ""}, { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 0, 2, 0, 0, "triangle_strip", ""}, { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 1, 2, 0, 0, "triangle_strip", ""}, { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 2, 2, 0, 0, "triangle_strip", ""}, { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 3, 2, 0, 0, "triangle_strip", ""}, { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 3, 2, 3, 0, "triangle_strip", ""}, }; for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(emitTests); ++ndx) { emitTests[ndx].name = std::string(emitTests[ndx].name) + "_emit_" + de::toString(emitTests[ndx].emitCountA) + "_end_" + de::toString(emitTests[ndx].endCountA); emitTests[ndx].desc = std::string(emitTests[ndx].name) + " output, emit " + de::toString(emitTests[ndx].emitCountA) + " vertices, call EndPrimitive " + de::toString(emitTests[ndx].endCountA) + " times"; if (emitTests[ndx].emitCountB) { emitTests[ndx].name += "_emit_" + de::toString(emitTests[ndx].emitCountB) + "_end_" + de::toString(emitTests[ndx].endCountB); emitTests[ndx].desc += ", emit " + de::toString(emitTests[ndx].emitCountB) + " vertices, call EndPrimitive " + de::toString(emitTests[ndx].endCountB) + " times"; } emitGroup->addChild(new EmitTest(testCtx, emitTests[ndx])); } } return emitGroup.release(); } } // geometry } // vkt