| /*------------------------------------------------------------------------ |
| * 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 Input Geometry Shader Tests |
| *//*--------------------------------------------------------------------*/ |
| |
| #include "vktGeometryInputGeometryShaderTests.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 <string> |
| |
| using namespace vk; |
| |
| namespace vkt |
| { |
| namespace geometry |
| { |
| namespace |
| { |
| using de::MovePtr; |
| using std::string; |
| using std::vector; |
| using tcu::TestCaseGroup; |
| using tcu::TestContext; |
| using tcu::TestStatus; |
| using tcu::Vec4; |
| |
| class GeometryInputTestInstance : public GeometryExpanderRenderTestInstance |
| { |
| public: |
| GeometryInputTestInstance(Context &context, const VkPrimitiveTopology primitiveType, const char *name); |
| |
| GeometryInputTestInstance(Context &context, const VkPrimitiveTopology primitiveType, const char *name, |
| const int numDrawVertices); |
| |
| void genVertexAttribData(void); |
| }; |
| |
| GeometryInputTestInstance::GeometryInputTestInstance(Context &context, const VkPrimitiveTopology primitiveType, |
| const char *name) |
| : GeometryExpanderRenderTestInstance(context, primitiveType, name) |
| { |
| genVertexAttribData(); |
| } |
| |
| GeometryInputTestInstance::GeometryInputTestInstance(Context &context, const VkPrimitiveTopology primitiveType, |
| const char *name, const int numDrawVertices) |
| : GeometryExpanderRenderTestInstance(context, primitiveType, name) |
| { |
| genVertexAttribData(); |
| m_numDrawVertices = numDrawVertices; |
| } |
| |
| void GeometryInputTestInstance::genVertexAttribData(void) |
| { |
| // Create 1 X 2 grid in triangle strip adjacent - order |
| const float scale = 0.3f; |
| const Vec4 offset(-0.5f, -0.2f, 0.0f, 1.0f); |
| m_numDrawVertices = 12; |
| |
| m_vertexPosData.resize(m_numDrawVertices); |
| m_vertexPosData[0] = Vec4(0, 0, 0.0f, 0.0f) * scale + offset; |
| m_vertexPosData[1] = Vec4(-1, -1, 0.0f, 0.0f) * scale + offset; |
| m_vertexPosData[2] = Vec4(0, -1, 0.0f, 0.0f) * scale + offset; |
| m_vertexPosData[3] = Vec4(1, 1, 0.0f, 0.0f) * scale + offset; |
| m_vertexPosData[4] = Vec4(1, 0, 0.0f, 0.0f) * scale + offset; |
| m_vertexPosData[5] = Vec4(0, -2, 0.0f, 0.0f) * scale + offset; |
| m_vertexPosData[6] = Vec4(1, -1, 0.0f, 0.0f) * scale + offset; |
| m_vertexPosData[7] = Vec4(2, 1, 0.0f, 0.0f) * scale + offset; |
| m_vertexPosData[8] = Vec4(2, 0, 0.0f, 0.0f) * scale + offset; |
| m_vertexPosData[9] = Vec4(1, -2, 0.0f, 0.0f) * scale + offset; |
| m_vertexPosData[10] = Vec4(2, -1, 0.0f, 0.0f) * scale + offset; |
| m_vertexPosData[11] = Vec4(3, 0, 0.0f, 0.0f) * scale + offset; |
| |
| // Red and white |
| m_vertexAttrData.resize(m_numDrawVertices); |
| for (int i = 0; i < m_numDrawVertices; ++i) |
| m_vertexAttrData[i] = (i % 2 == 0) ? Vec4(1, 1, 1, 1) : Vec4(1, 0, 0, 1); |
| } |
| |
| class GeometryExpanderRenderTest : public TestCase |
| { |
| public: |
| GeometryExpanderRenderTest(TestContext &testCtx, const PrimitiveTestSpec &inputPrimitives); |
| |
| void initPrograms(SourceCollections &sourceCollections) const; |
| virtual TestInstance *createInstance(Context &context) const; |
| virtual void checkSupport(Context &context) const; |
| |
| protected: |
| string shaderGeometry(bool pointSize) const; |
| const VkPrimitiveTopology m_primitiveType; |
| const VkPrimitiveTopology m_outputType; |
| }; |
| |
| GeometryExpanderRenderTest::GeometryExpanderRenderTest(TestContext &testCtx, const PrimitiveTestSpec &inputPrimitives) |
| : TestCase(testCtx, inputPrimitives.name) |
| , m_primitiveType(inputPrimitives.primitiveType) |
| , m_outputType(inputPrimitives.outputType) |
| { |
| } |
| |
| void GeometryExpanderRenderTest::checkSupport(Context &context) const |
| { |
| context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER); |
| |
| #ifndef CTS_USES_VULKANSC |
| if (m_primitiveType == vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN && |
| context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") && |
| !context.getPortabilitySubsetFeatures().triangleFans) |
| { |
| TCU_THROW(NotSupportedError, |
| "VK_KHR_portability_subset: Triangle fans are not supported by this implementation"); |
| } |
| #endif // CTS_USES_VULKANSC |
| } |
| |
| void GeometryExpanderRenderTest::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_outputType == 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 highp 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 *GeometryExpanderRenderTest::createInstance(Context &context) const |
| { |
| return new GeometryInputTestInstance(context, m_primitiveType, getName()); |
| } |
| |
| string GeometryExpanderRenderTest::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(" << inputTypeToGLString(m_primitiveType) << ") in;\n" |
| << "layout(" << outputTypeToGLString(m_outputType) << ", max_vertices = " << calcOutputVertices(m_primitiveType) |
| << ") out;\n" |
| << "layout(location = 0) in highp vec4 v_geom_FragColor[];\n" |
| << "layout(location = 0) out highp vec4 v_frag_FragColor;\n" |
| << "\n" |
| << "void main (void)\n" |
| << "{\n" |
| << " const highp vec4 offset0 = vec4(-0.07, -0.01, 0.0, 0.0);\n" |
| << " const highp vec4 offset1 = vec4( 0.03, -0.03, 0.0, 0.0);\n" |
| << " const highp vec4 offset2 = vec4(-0.01, 0.08, 0.0, 0.0);\n" |
| << " highp vec4 yoffset = float(gl_PrimitiveIDIn) * vec4(0.02, 0.1, 0.0, 0.0);\n" |
| << "\n" |
| << " for (highp int ndx = 0; ndx < gl_in.length(); ndx++)\n" |
| << " {\n"; |
| if (pointSize) |
| src << " gl_PointSize = 1.0;\n"; |
| src << " gl_Position = gl_in[ndx].gl_Position + offset0 + yoffset;\n" |
| << " v_frag_FragColor = v_geom_FragColor[ndx];\n" |
| << " EmitVertex();\n" |
| << "\n"; |
| if (pointSize) |
| src << " gl_PointSize = 1.0;\n"; |
| src << " gl_Position = gl_in[ndx].gl_Position + offset1 + yoffset;\n" |
| << " v_frag_FragColor = v_geom_FragColor[ndx];\n" |
| << " EmitVertex();\n" |
| << "\n"; |
| if (pointSize) |
| src << " gl_PointSize = 1.0;\n"; |
| src << " gl_Position = gl_in[ndx].gl_Position + offset2 + yoffset;\n" |
| << " v_frag_FragColor = v_geom_FragColor[ndx];\n" |
| << " EmitVertex();\n" |
| << " EndPrimitive();\n" |
| << " }\n" |
| << "}\n"; |
| return src.str(); |
| } |
| |
| class TriangleStripAdjacencyVertexCountTest : public GeometryExpanderRenderTest |
| { |
| public: |
| TriangleStripAdjacencyVertexCountTest(TestContext &testCtx, const PrimitiveTestSpec &inputPrimitives, |
| const int numInputVertices); |
| virtual TestInstance *createInstance(Context &context) const; |
| |
| private: |
| const int m_numInputVertices; |
| }; |
| |
| TriangleStripAdjacencyVertexCountTest::TriangleStripAdjacencyVertexCountTest(TestContext &testCtx, |
| const PrimitiveTestSpec &inputPrimitives, |
| const int numInputVertices) |
| : GeometryExpanderRenderTest(testCtx, inputPrimitives) |
| , m_numInputVertices(numInputVertices) |
| { |
| } |
| |
| TestInstance *TriangleStripAdjacencyVertexCountTest::createInstance(Context &context) const |
| { |
| return new GeometryInputTestInstance(context, m_primitiveType, getName(), m_numInputVertices); |
| } |
| |
| } // namespace |
| |
| TestCaseGroup *createInputGeometryShaderTests(TestContext &testCtx) |
| { |
| MovePtr<TestCaseGroup> inputPrimitiveGroup(new TestCaseGroup(testCtx, "input")); |
| MovePtr<TestCaseGroup> basicPrimitiveGroup(new TestCaseGroup(testCtx, "basic_primitive")); |
| MovePtr<TestCaseGroup> triStripAdjacencyGroup(new TestCaseGroup(testCtx, "triangle_strip_adjacency")); |
| MovePtr<TestCaseGroup> conversionPrimitiveGroup(new TestCaseGroup(testCtx, "conversion")); |
| |
| const PrimitiveTestSpec inputPrimitives[] = { |
| {VK_PRIMITIVE_TOPOLOGY_POINT_LIST, "points", VK_PRIMITIVE_TOPOLOGY_POINT_LIST}, |
| {VK_PRIMITIVE_TOPOLOGY_LINE_LIST, "lines", VK_PRIMITIVE_TOPOLOGY_LINE_STRIP}, |
| {VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, "line_strip", VK_PRIMITIVE_TOPOLOGY_LINE_STRIP}, |
| {VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, "triangles", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP}, |
| {VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, "triangle_strip", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP}, |
| {VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, "triangle_fan", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP}, |
| {VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY, "lines_adjacency", VK_PRIMITIVE_TOPOLOGY_LINE_STRIP}, |
| {VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY, "line_strip_adjacency", VK_PRIMITIVE_TOPOLOGY_LINE_STRIP}, |
| {VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY, "triangles_adjacency", |
| VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP}}; |
| |
| // more basic types |
| for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(inputPrimitives); ++ndx) |
| basicPrimitiveGroup->addChild(new GeometryExpanderRenderTest(testCtx, inputPrimitives[ndx])); |
| |
| // triangle strip adjacency with different vertex counts |
| for (int vertexCount = 0; vertexCount <= 12; ++vertexCount) |
| { |
| const string name = "vertex_count_" + de::toString(vertexCount); |
| const PrimitiveTestSpec primitives = {VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY, name.c_str(), |
| VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP}; |
| |
| triStripAdjacencyGroup->addChild(new TriangleStripAdjacencyVertexCountTest(testCtx, primitives, vertexCount)); |
| } |
| |
| // different type conversions |
| { |
| static const PrimitiveTestSpec conversionPrimitives[] = { |
| {VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, "triangles_to_points", VK_PRIMITIVE_TOPOLOGY_POINT_LIST}, |
| {VK_PRIMITIVE_TOPOLOGY_LINE_LIST, "lines_to_points", VK_PRIMITIVE_TOPOLOGY_POINT_LIST}, |
| {VK_PRIMITIVE_TOPOLOGY_POINT_LIST, "points_to_lines", VK_PRIMITIVE_TOPOLOGY_LINE_STRIP}, |
| {VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, "triangles_to_lines", VK_PRIMITIVE_TOPOLOGY_LINE_STRIP}, |
| {VK_PRIMITIVE_TOPOLOGY_POINT_LIST, "points_to_triangles", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP}, |
| {VK_PRIMITIVE_TOPOLOGY_LINE_LIST, "lines_to_triangles", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP}}; |
| |
| for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(conversionPrimitives); ++ndx) |
| conversionPrimitiveGroup->addChild(new GeometryExpanderRenderTest(testCtx, conversionPrimitives[ndx])); |
| } |
| |
| inputPrimitiveGroup->addChild(basicPrimitiveGroup.release()); |
| inputPrimitiveGroup->addChild(triStripAdjacencyGroup.release()); |
| inputPrimitiveGroup->addChild(conversionPrimitiveGroup.release()); |
| return inputPrimitiveGroup.release(); |
| } |
| |
| } // namespace geometry |
| } // namespace vkt |