1e5c31af7Sopenharmony_ci/*------------------------------------------------------------------------ 2e5c31af7Sopenharmony_ci * Vulkan Conformance Tests 3e5c31af7Sopenharmony_ci * ------------------------ 4e5c31af7Sopenharmony_ci * 5e5c31af7Sopenharmony_ci * Copyright (c) 2014 The Android Open Source Project 6e5c31af7Sopenharmony_ci * Copyright (c) 2016 The Khronos Group Inc. 7e5c31af7Sopenharmony_ci * 8e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 9e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License. 10e5c31af7Sopenharmony_ci * You may obtain a copy of the License at 11e5c31af7Sopenharmony_ci * 12e5c31af7Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 13e5c31af7Sopenharmony_ci * 14e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 15e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 16e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and 18e5c31af7Sopenharmony_ci * limitations under the License. 19e5c31af7Sopenharmony_ci * 20e5c31af7Sopenharmony_ci *//*! 21e5c31af7Sopenharmony_ci * \file 22e5c31af7Sopenharmony_ci * \brief Tessellation Winding Tests 23e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 24e5c31af7Sopenharmony_ci 25e5c31af7Sopenharmony_ci#include "vktTessellationWindingTests.hpp" 26e5c31af7Sopenharmony_ci#include "vktTestCaseUtil.hpp" 27e5c31af7Sopenharmony_ci#include "vktTessellationUtil.hpp" 28e5c31af7Sopenharmony_ci#include "vktTestGroupUtil.hpp" 29e5c31af7Sopenharmony_ci 30e5c31af7Sopenharmony_ci#include "tcuTestLog.hpp" 31e5c31af7Sopenharmony_ci#include "tcuRGBA.hpp" 32e5c31af7Sopenharmony_ci#include "tcuMaybe.hpp" 33e5c31af7Sopenharmony_ci 34e5c31af7Sopenharmony_ci#include "vkDefs.hpp" 35e5c31af7Sopenharmony_ci#include "vkBarrierUtil.hpp" 36e5c31af7Sopenharmony_ci#include "vkQueryUtil.hpp" 37e5c31af7Sopenharmony_ci#include "vkBuilderUtil.hpp" 38e5c31af7Sopenharmony_ci#include "vkImageUtil.hpp" 39e5c31af7Sopenharmony_ci#include "vkTypeUtil.hpp" 40e5c31af7Sopenharmony_ci#include "vkStrUtil.hpp" 41e5c31af7Sopenharmony_ci#include "vkCmdUtil.hpp" 42e5c31af7Sopenharmony_ci#include "vkObjUtil.hpp" 43e5c31af7Sopenharmony_ci#include "vkBufferWithMemory.hpp" 44e5c31af7Sopenharmony_ci#include "vkImageWithMemory.hpp" 45e5c31af7Sopenharmony_ci 46e5c31af7Sopenharmony_ci#include "deUniquePtr.hpp" 47e5c31af7Sopenharmony_ci 48e5c31af7Sopenharmony_cinamespace vkt 49e5c31af7Sopenharmony_ci{ 50e5c31af7Sopenharmony_cinamespace tessellation 51e5c31af7Sopenharmony_ci{ 52e5c31af7Sopenharmony_ci 53e5c31af7Sopenharmony_ciusing namespace vk; 54e5c31af7Sopenharmony_ci 55e5c31af7Sopenharmony_cinamespace 56e5c31af7Sopenharmony_ci{ 57e5c31af7Sopenharmony_ci 58e5c31af7Sopenharmony_cistd::string getCaseName (const TessPrimitiveType primitiveType, const ShaderLanguage shaderLanguage, const Winding winding, bool yFlip) 59e5c31af7Sopenharmony_ci{ 60e5c31af7Sopenharmony_ci std::ostringstream str; 61e5c31af7Sopenharmony_ci str << getShaderLanguageName(shaderLanguage) << "_" << getTessPrimitiveTypeShaderName(primitiveType) << "_" << getWindingShaderName(winding); 62e5c31af7Sopenharmony_ci if (yFlip) 63e5c31af7Sopenharmony_ci str << "_yflip"; 64e5c31af7Sopenharmony_ci return str.str(); 65e5c31af7Sopenharmony_ci} 66e5c31af7Sopenharmony_ci 67e5c31af7Sopenharmony_ciinline VkFrontFace mapFrontFace (const Winding winding) 68e5c31af7Sopenharmony_ci{ 69e5c31af7Sopenharmony_ci switch (winding) 70e5c31af7Sopenharmony_ci { 71e5c31af7Sopenharmony_ci case WINDING_CCW: return VK_FRONT_FACE_COUNTER_CLOCKWISE; 72e5c31af7Sopenharmony_ci case WINDING_CW: return VK_FRONT_FACE_CLOCKWISE; 73e5c31af7Sopenharmony_ci default: 74e5c31af7Sopenharmony_ci DE_ASSERT(false); 75e5c31af7Sopenharmony_ci return VK_FRONT_FACE_LAST; 76e5c31af7Sopenharmony_ci } 77e5c31af7Sopenharmony_ci} 78e5c31af7Sopenharmony_ci 79e5c31af7Sopenharmony_ci//! Returns true when the image passes the verification. 80e5c31af7Sopenharmony_cibool verifyResultImage (tcu::TestLog& log, 81e5c31af7Sopenharmony_ci const tcu::ConstPixelBufferAccess image, 82e5c31af7Sopenharmony_ci const TessPrimitiveType primitiveType, 83e5c31af7Sopenharmony_ci const VkTessellationDomainOrigin domainOrigin, 84e5c31af7Sopenharmony_ci const Winding winding, 85e5c31af7Sopenharmony_ci bool yFlip, 86e5c31af7Sopenharmony_ci const Winding frontFaceWinding) 87e5c31af7Sopenharmony_ci{ 88e5c31af7Sopenharmony_ci const bool expectVisiblePrimitive = ((frontFaceWinding == winding) == (domainOrigin == VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT)) != yFlip; 89e5c31af7Sopenharmony_ci 90e5c31af7Sopenharmony_ci const int totalNumPixels = image.getWidth()*image.getHeight(); 91e5c31af7Sopenharmony_ci 92e5c31af7Sopenharmony_ci const tcu::Vec4 white = tcu::RGBA::white().toVec(); 93e5c31af7Sopenharmony_ci const tcu::Vec4 red = tcu::RGBA::red().toVec(); 94e5c31af7Sopenharmony_ci 95e5c31af7Sopenharmony_ci int numWhitePixels = 0; 96e5c31af7Sopenharmony_ci int numRedPixels = 0; 97e5c31af7Sopenharmony_ci 98e5c31af7Sopenharmony_ci // Count red and white pixels 99e5c31af7Sopenharmony_ci for (int y = 0; y < image.getHeight(); y++) 100e5c31af7Sopenharmony_ci for (int x = 0; x < image.getWidth(); x++) 101e5c31af7Sopenharmony_ci { 102e5c31af7Sopenharmony_ci numWhitePixels += image.getPixel(x, y) == white ? 1 : 0; 103e5c31af7Sopenharmony_ci numRedPixels += image.getPixel(x, y) == red ? 1 : 0; 104e5c31af7Sopenharmony_ci } 105e5c31af7Sopenharmony_ci 106e5c31af7Sopenharmony_ci DE_ASSERT(numWhitePixels + numRedPixels <= totalNumPixels); 107e5c31af7Sopenharmony_ci 108e5c31af7Sopenharmony_ci log << tcu::TestLog::Message << "Note: got " << numWhitePixels << " white and " << numRedPixels << " red pixels" << tcu::TestLog::EndMessage; 109e5c31af7Sopenharmony_ci 110e5c31af7Sopenharmony_ci { 111e5c31af7Sopenharmony_ci const int otherPixels = totalNumPixels - numWhitePixels - numRedPixels; 112e5c31af7Sopenharmony_ci if (otherPixels > 0) 113e5c31af7Sopenharmony_ci { 114e5c31af7Sopenharmony_ci log << tcu::TestLog::Message 115e5c31af7Sopenharmony_ci << "Failure: Got " << otherPixels << " other than white or red pixels" 116e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 117e5c31af7Sopenharmony_ci return false; 118e5c31af7Sopenharmony_ci } 119e5c31af7Sopenharmony_ci } 120e5c31af7Sopenharmony_ci 121e5c31af7Sopenharmony_ci if (expectVisiblePrimitive) 122e5c31af7Sopenharmony_ci { 123e5c31af7Sopenharmony_ci if (primitiveType == TESSPRIMITIVETYPE_TRIANGLES) 124e5c31af7Sopenharmony_ci { 125e5c31af7Sopenharmony_ci const int badPixelTolerance = (primitiveType == TESSPRIMITIVETYPE_TRIANGLES ? 5*de::max(image.getWidth(), image.getHeight()) : 0); 126e5c31af7Sopenharmony_ci 127e5c31af7Sopenharmony_ci if (de::abs(numWhitePixels - totalNumPixels/2) > badPixelTolerance) 128e5c31af7Sopenharmony_ci { 129e5c31af7Sopenharmony_ci log << tcu::TestLog::Message << "Failure: wrong number of white pixels; expected approximately " << totalNumPixels/2 << tcu::TestLog::EndMessage; 130e5c31af7Sopenharmony_ci return false; 131e5c31af7Sopenharmony_ci } 132e5c31af7Sopenharmony_ci 133e5c31af7Sopenharmony_ci // Check number of filled pixels (from left) in top and bottom rows to 134e5c31af7Sopenharmony_ci // determine if triangle is in right orientation. 135e5c31af7Sopenharmony_ci { 136e5c31af7Sopenharmony_ci const tcu::IVec2 expectedStart (0, 1); 137e5c31af7Sopenharmony_ci const tcu::IVec2 expectedEnd (image.getWidth()-1, image.getWidth()); 138e5c31af7Sopenharmony_ci const tcu::IVec2 expectedTop = yFlip ? expectedStart : expectedEnd; 139e5c31af7Sopenharmony_ci const tcu::IVec2 expectedBottom = yFlip ? expectedEnd : expectedStart; 140e5c31af7Sopenharmony_ci int numTopFilled = 0; 141e5c31af7Sopenharmony_ci int numBottomFilled = 0; 142e5c31af7Sopenharmony_ci 143e5c31af7Sopenharmony_ci for (int x = 0; x < image.getWidth(); ++x) 144e5c31af7Sopenharmony_ci { 145e5c31af7Sopenharmony_ci if (image.getPixel(x, 0) == white) 146e5c31af7Sopenharmony_ci numTopFilled += 1; 147e5c31af7Sopenharmony_ci else 148e5c31af7Sopenharmony_ci break; 149e5c31af7Sopenharmony_ci } 150e5c31af7Sopenharmony_ci 151e5c31af7Sopenharmony_ci for (int x = 0; x < image.getWidth(); ++x) 152e5c31af7Sopenharmony_ci { 153e5c31af7Sopenharmony_ci if (image.getPixel(x, image.getHeight()-1) == white) 154e5c31af7Sopenharmony_ci numBottomFilled += 1; 155e5c31af7Sopenharmony_ci else 156e5c31af7Sopenharmony_ci break; 157e5c31af7Sopenharmony_ci } 158e5c31af7Sopenharmony_ci 159e5c31af7Sopenharmony_ci if (!de::inBounds(numTopFilled, expectedTop[0], expectedTop[1]) || 160e5c31af7Sopenharmony_ci !de::inBounds(numBottomFilled, expectedBottom[0], expectedBottom[1])) 161e5c31af7Sopenharmony_ci { 162e5c31af7Sopenharmony_ci log << tcu::TestLog::Message << "Failure: triangle orientation is incorrect" << tcu::TestLog::EndMessage; 163e5c31af7Sopenharmony_ci return false; 164e5c31af7Sopenharmony_ci } 165e5c31af7Sopenharmony_ci } 166e5c31af7Sopenharmony_ci 167e5c31af7Sopenharmony_ci } 168e5c31af7Sopenharmony_ci else if (primitiveType == TESSPRIMITIVETYPE_QUADS) 169e5c31af7Sopenharmony_ci { 170e5c31af7Sopenharmony_ci if (numWhitePixels != totalNumPixels) 171e5c31af7Sopenharmony_ci { 172e5c31af7Sopenharmony_ci log << tcu::TestLog::Message << "Failure: expected only white pixels (full-viewport quad)" << tcu::TestLog::EndMessage; 173e5c31af7Sopenharmony_ci return false; 174e5c31af7Sopenharmony_ci } 175e5c31af7Sopenharmony_ci } 176e5c31af7Sopenharmony_ci else 177e5c31af7Sopenharmony_ci DE_ASSERT(false); 178e5c31af7Sopenharmony_ci } 179e5c31af7Sopenharmony_ci else 180e5c31af7Sopenharmony_ci { 181e5c31af7Sopenharmony_ci if (numWhitePixels != 0) 182e5c31af7Sopenharmony_ci { 183e5c31af7Sopenharmony_ci log << tcu::TestLog::Message << "Failure: expected only red pixels (everything culled)" << tcu::TestLog::EndMessage; 184e5c31af7Sopenharmony_ci return false; 185e5c31af7Sopenharmony_ci } 186e5c31af7Sopenharmony_ci } 187e5c31af7Sopenharmony_ci 188e5c31af7Sopenharmony_ci return true; 189e5c31af7Sopenharmony_ci} 190e5c31af7Sopenharmony_ci 191e5c31af7Sopenharmony_citypedef tcu::Maybe<VkTessellationDomainOrigin> MaybeDomainOrigin; 192e5c31af7Sopenharmony_ci 193e5c31af7Sopenharmony_ciclass WindingTest : public TestCase 194e5c31af7Sopenharmony_ci{ 195e5c31af7Sopenharmony_cipublic: 196e5c31af7Sopenharmony_ci WindingTest (tcu::TestContext& testCtx, 197e5c31af7Sopenharmony_ci const TessPrimitiveType primitiveType, 198e5c31af7Sopenharmony_ci const MaybeDomainOrigin& domainOrigin, 199e5c31af7Sopenharmony_ci const ShaderLanguage shaderLanguage, 200e5c31af7Sopenharmony_ci const Winding winding, 201e5c31af7Sopenharmony_ci bool yFlip); 202e5c31af7Sopenharmony_ci 203e5c31af7Sopenharmony_ci void initPrograms (SourceCollections& programCollection) const; 204e5c31af7Sopenharmony_ci TestInstance* createInstance (Context& context) const; 205e5c31af7Sopenharmony_ci 206e5c31af7Sopenharmony_ciprivate: 207e5c31af7Sopenharmony_ci const TessPrimitiveType m_primitiveType; 208e5c31af7Sopenharmony_ci const MaybeDomainOrigin m_domainOrigin; 209e5c31af7Sopenharmony_ci const ShaderLanguage m_shaderLanguage; 210e5c31af7Sopenharmony_ci const Winding m_winding; 211e5c31af7Sopenharmony_ci const bool m_yFlip; 212e5c31af7Sopenharmony_ci}; 213e5c31af7Sopenharmony_ci 214e5c31af7Sopenharmony_ciWindingTest::WindingTest (tcu::TestContext& testCtx, 215e5c31af7Sopenharmony_ci const TessPrimitiveType primitiveType, 216e5c31af7Sopenharmony_ci const MaybeDomainOrigin& domainOrigin, 217e5c31af7Sopenharmony_ci const ShaderLanguage shaderLanguage, 218e5c31af7Sopenharmony_ci const Winding winding, 219e5c31af7Sopenharmony_ci bool yFlip) 220e5c31af7Sopenharmony_ci : TestCase (testCtx, getCaseName(primitiveType, shaderLanguage, winding, yFlip)) 221e5c31af7Sopenharmony_ci , m_primitiveType (primitiveType) 222e5c31af7Sopenharmony_ci , m_domainOrigin (domainOrigin) 223e5c31af7Sopenharmony_ci , m_shaderLanguage (shaderLanguage) 224e5c31af7Sopenharmony_ci , m_winding (winding) 225e5c31af7Sopenharmony_ci , m_yFlip (yFlip) 226e5c31af7Sopenharmony_ci{ 227e5c31af7Sopenharmony_ci} 228e5c31af7Sopenharmony_ci 229e5c31af7Sopenharmony_civoid WindingTest::initPrograms (SourceCollections& programCollection) const 230e5c31af7Sopenharmony_ci{ 231e5c31af7Sopenharmony_ci if (m_shaderLanguage == SHADER_LANGUAGE_GLSL) 232e5c31af7Sopenharmony_ci { 233e5c31af7Sopenharmony_ci // Vertex shader - no inputs 234e5c31af7Sopenharmony_ci { 235e5c31af7Sopenharmony_ci std::ostringstream src; 236e5c31af7Sopenharmony_ci src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n" 237e5c31af7Sopenharmony_ci << "\n" 238e5c31af7Sopenharmony_ci << "void main (void)\n" 239e5c31af7Sopenharmony_ci << "{\n" 240e5c31af7Sopenharmony_ci << "}\n"; 241e5c31af7Sopenharmony_ci 242e5c31af7Sopenharmony_ci programCollection.glslSources.add("vert") << glu::VertexSource(src.str()); 243e5c31af7Sopenharmony_ci } 244e5c31af7Sopenharmony_ci 245e5c31af7Sopenharmony_ci // Tessellation control shader 246e5c31af7Sopenharmony_ci { 247e5c31af7Sopenharmony_ci std::ostringstream src; 248e5c31af7Sopenharmony_ci src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n" 249e5c31af7Sopenharmony_ci << "#extension GL_EXT_tessellation_shader : require\n" 250e5c31af7Sopenharmony_ci << "\n" 251e5c31af7Sopenharmony_ci << "layout(vertices = 1) out;\n" 252e5c31af7Sopenharmony_ci << "\n" 253e5c31af7Sopenharmony_ci << "void main (void)\n" 254e5c31af7Sopenharmony_ci << "{\n" 255e5c31af7Sopenharmony_ci << " gl_TessLevelInner[0] = 5.0;\n" 256e5c31af7Sopenharmony_ci << " gl_TessLevelInner[1] = 5.0;\n" 257e5c31af7Sopenharmony_ci << "\n" 258e5c31af7Sopenharmony_ci << " gl_TessLevelOuter[0] = 5.0;\n" 259e5c31af7Sopenharmony_ci << " gl_TessLevelOuter[1] = 5.0;\n" 260e5c31af7Sopenharmony_ci << " gl_TessLevelOuter[2] = 5.0;\n" 261e5c31af7Sopenharmony_ci << " gl_TessLevelOuter[3] = 5.0;\n" 262e5c31af7Sopenharmony_ci << "}\n"; 263e5c31af7Sopenharmony_ci 264e5c31af7Sopenharmony_ci programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str()); 265e5c31af7Sopenharmony_ci } 266e5c31af7Sopenharmony_ci 267e5c31af7Sopenharmony_ci // Tessellation evaluation shader 268e5c31af7Sopenharmony_ci { 269e5c31af7Sopenharmony_ci std::ostringstream src; 270e5c31af7Sopenharmony_ci src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n" 271e5c31af7Sopenharmony_ci << "#extension GL_EXT_tessellation_shader : require\n" 272e5c31af7Sopenharmony_ci << "\n" 273e5c31af7Sopenharmony_ci << "layout(" << getTessPrimitiveTypeShaderName(m_primitiveType) << ", " 274e5c31af7Sopenharmony_ci << getWindingShaderName(m_winding) << ") in;\n" 275e5c31af7Sopenharmony_ci << "\n" 276e5c31af7Sopenharmony_ci << "void main (void)\n" 277e5c31af7Sopenharmony_ci << "{\n" 278e5c31af7Sopenharmony_ci << " gl_Position = vec4(gl_TessCoord.xy*2.0 - 1.0, 0.0, 1.0);\n" 279e5c31af7Sopenharmony_ci << "}\n"; 280e5c31af7Sopenharmony_ci 281e5c31af7Sopenharmony_ci programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str()); 282e5c31af7Sopenharmony_ci } 283e5c31af7Sopenharmony_ci 284e5c31af7Sopenharmony_ci // Fragment shader 285e5c31af7Sopenharmony_ci { 286e5c31af7Sopenharmony_ci std::ostringstream src; 287e5c31af7Sopenharmony_ci src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n" 288e5c31af7Sopenharmony_ci << "\n" 289e5c31af7Sopenharmony_ci << "layout(location = 0) out mediump vec4 o_color;\n" 290e5c31af7Sopenharmony_ci << "\n" 291e5c31af7Sopenharmony_ci << "void main (void)\n" 292e5c31af7Sopenharmony_ci << "{\n" 293e5c31af7Sopenharmony_ci << " o_color = vec4(1.0);\n" 294e5c31af7Sopenharmony_ci << "}\n"; 295e5c31af7Sopenharmony_ci 296e5c31af7Sopenharmony_ci programCollection.glslSources.add("frag") << glu::FragmentSource(src.str()); 297e5c31af7Sopenharmony_ci } 298e5c31af7Sopenharmony_ci } 299e5c31af7Sopenharmony_ci else 300e5c31af7Sopenharmony_ci { 301e5c31af7Sopenharmony_ci // Vertex shader - no inputs 302e5c31af7Sopenharmony_ci { 303e5c31af7Sopenharmony_ci std::ostringstream src; 304e5c31af7Sopenharmony_ci src << "void main (void)\n" 305e5c31af7Sopenharmony_ci << "{\n" 306e5c31af7Sopenharmony_ci << "}\n"; 307e5c31af7Sopenharmony_ci 308e5c31af7Sopenharmony_ci programCollection.hlslSources.add("vert") << glu::VertexSource(src.str()); 309e5c31af7Sopenharmony_ci } 310e5c31af7Sopenharmony_ci 311e5c31af7Sopenharmony_ci // Tessellation control shader 312e5c31af7Sopenharmony_ci { 313e5c31af7Sopenharmony_ci std::ostringstream src; 314e5c31af7Sopenharmony_ci src << "struct HS_CONSTANT_OUT\n" 315e5c31af7Sopenharmony_ci << "{\n" 316e5c31af7Sopenharmony_ci << " float tessLevelsOuter[4] : SV_TessFactor;\n" 317e5c31af7Sopenharmony_ci << " float tessLevelsInner[2] : SV_InsideTessFactor;\n" 318e5c31af7Sopenharmony_ci << "};\n" 319e5c31af7Sopenharmony_ci << "\n" 320e5c31af7Sopenharmony_ci << "[domain(\"" << getDomainName(m_primitiveType) << "\")]\n" 321e5c31af7Sopenharmony_ci << "[partitioning(\"integer\")]\n" 322e5c31af7Sopenharmony_ci << "[outputtopology(\"" << getOutputTopologyName (m_primitiveType, m_winding, false) << "\")]\n" 323e5c31af7Sopenharmony_ci << "[outputcontrolpoints(1)]\n" 324e5c31af7Sopenharmony_ci << "[patchconstantfunc(\"PCF\")]\n" 325e5c31af7Sopenharmony_ci << "void main()\n" 326e5c31af7Sopenharmony_ci << "{\n" 327e5c31af7Sopenharmony_ci << "}\n" 328e5c31af7Sopenharmony_ci << "\n" 329e5c31af7Sopenharmony_ci << "HS_CONSTANT_OUT PCF()\n" 330e5c31af7Sopenharmony_ci << "{\n" 331e5c31af7Sopenharmony_ci << " HS_CONSTANT_OUT output;\n" 332e5c31af7Sopenharmony_ci << " output.tessLevelsInner[0] = 5.0;\n" 333e5c31af7Sopenharmony_ci << " output.tessLevelsInner[1] = 5.0;\n" 334e5c31af7Sopenharmony_ci << " output.tessLevelsOuter[0] = 5.0;\n" 335e5c31af7Sopenharmony_ci << " output.tessLevelsOuter[1] = 5.0;\n" 336e5c31af7Sopenharmony_ci << " output.tessLevelsOuter[2] = 5.0;\n" 337e5c31af7Sopenharmony_ci << " output.tessLevelsOuter[3] = 5.0;\n" 338e5c31af7Sopenharmony_ci << " return output;\n" 339e5c31af7Sopenharmony_ci << "}\n"; 340e5c31af7Sopenharmony_ci 341e5c31af7Sopenharmony_ci programCollection.hlslSources.add("tesc") << glu::TessellationControlSource(src.str()); 342e5c31af7Sopenharmony_ci } 343e5c31af7Sopenharmony_ci 344e5c31af7Sopenharmony_ci // Tessellation evaluation shader 345e5c31af7Sopenharmony_ci { 346e5c31af7Sopenharmony_ci std::ostringstream src; 347e5c31af7Sopenharmony_ci 348e5c31af7Sopenharmony_ci src << "float4 main(" << (m_primitiveType == TESSPRIMITIVETYPE_TRIANGLES ? "float3" : "float2") << " tessCoords : SV_DOMAINLOCATION) : SV_POSITION\n" 349e5c31af7Sopenharmony_ci << "{\n" 350e5c31af7Sopenharmony_ci << " return float4(tessCoords.xy*2.0 - 1, 0.0, 1.0);\n" 351e5c31af7Sopenharmony_ci << "}\n"; 352e5c31af7Sopenharmony_ci 353e5c31af7Sopenharmony_ci programCollection.hlslSources.add("tese") << glu::TessellationEvaluationSource(src.str()); 354e5c31af7Sopenharmony_ci } 355e5c31af7Sopenharmony_ci 356e5c31af7Sopenharmony_ci // Fragment shader 357e5c31af7Sopenharmony_ci { 358e5c31af7Sopenharmony_ci std::ostringstream src; 359e5c31af7Sopenharmony_ci src << "float4 main (void) : COLOR0\n" 360e5c31af7Sopenharmony_ci << "{\n" 361e5c31af7Sopenharmony_ci << " return float4(1.0);\n" 362e5c31af7Sopenharmony_ci << "}\n"; 363e5c31af7Sopenharmony_ci 364e5c31af7Sopenharmony_ci programCollection.hlslSources.add("frag") << glu::FragmentSource(src.str()); 365e5c31af7Sopenharmony_ci } 366e5c31af7Sopenharmony_ci } 367e5c31af7Sopenharmony_ci} 368e5c31af7Sopenharmony_ci 369e5c31af7Sopenharmony_ciclass WindingTestInstance : public TestInstance 370e5c31af7Sopenharmony_ci{ 371e5c31af7Sopenharmony_cipublic: 372e5c31af7Sopenharmony_ci WindingTestInstance (Context& context, 373e5c31af7Sopenharmony_ci const TessPrimitiveType primitiveType, 374e5c31af7Sopenharmony_ci const MaybeDomainOrigin& domainOrigin, 375e5c31af7Sopenharmony_ci const Winding winding, 376e5c31af7Sopenharmony_ci bool yFlip); 377e5c31af7Sopenharmony_ci 378e5c31af7Sopenharmony_ci tcu::TestStatus iterate (void); 379e5c31af7Sopenharmony_ci 380e5c31af7Sopenharmony_ciprivate: 381e5c31af7Sopenharmony_ci void requireExtension (const char* name) const; 382e5c31af7Sopenharmony_ci 383e5c31af7Sopenharmony_ci const TessPrimitiveType m_primitiveType; 384e5c31af7Sopenharmony_ci const MaybeDomainOrigin m_domainOrigin; 385e5c31af7Sopenharmony_ci const Winding m_winding; 386e5c31af7Sopenharmony_ci const bool m_yFlip; 387e5c31af7Sopenharmony_ci}; 388e5c31af7Sopenharmony_ci 389e5c31af7Sopenharmony_ciWindingTestInstance::WindingTestInstance (Context& context, 390e5c31af7Sopenharmony_ci const TessPrimitiveType primitiveType, 391e5c31af7Sopenharmony_ci const MaybeDomainOrigin& domainOrigin, 392e5c31af7Sopenharmony_ci const Winding winding, 393e5c31af7Sopenharmony_ci bool yFlip) 394e5c31af7Sopenharmony_ci : TestInstance (context) 395e5c31af7Sopenharmony_ci , m_primitiveType (primitiveType) 396e5c31af7Sopenharmony_ci , m_domainOrigin (domainOrigin) 397e5c31af7Sopenharmony_ci , m_winding (winding) 398e5c31af7Sopenharmony_ci , m_yFlip (yFlip) 399e5c31af7Sopenharmony_ci{ 400e5c31af7Sopenharmony_ci if (m_yFlip) 401e5c31af7Sopenharmony_ci requireExtension("VK_KHR_maintenance1"); 402e5c31af7Sopenharmony_ci 403e5c31af7Sopenharmony_ci if ((bool)m_domainOrigin) 404e5c31af7Sopenharmony_ci requireExtension("VK_KHR_maintenance2"); 405e5c31af7Sopenharmony_ci} 406e5c31af7Sopenharmony_ci 407e5c31af7Sopenharmony_civoid WindingTestInstance::requireExtension (const char* name) const 408e5c31af7Sopenharmony_ci{ 409e5c31af7Sopenharmony_ci if(!m_context.isDeviceFunctionalitySupported(name)) 410e5c31af7Sopenharmony_ci TCU_THROW(NotSupportedError, (std::string(name) + " is not supported").c_str()); 411e5c31af7Sopenharmony_ci} 412e5c31af7Sopenharmony_ci 413e5c31af7Sopenharmony_citcu::TestStatus WindingTestInstance::iterate (void) 414e5c31af7Sopenharmony_ci{ 415e5c31af7Sopenharmony_ci const DeviceInterface& vk = m_context.getDeviceInterface(); 416e5c31af7Sopenharmony_ci const VkDevice device = m_context.getDevice(); 417e5c31af7Sopenharmony_ci const VkQueue queue = m_context.getUniversalQueue(); 418e5c31af7Sopenharmony_ci const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); 419e5c31af7Sopenharmony_ci Allocator& allocator = m_context.getDefaultAllocator(); 420e5c31af7Sopenharmony_ci 421e5c31af7Sopenharmony_ci // Color attachment 422e5c31af7Sopenharmony_ci 423e5c31af7Sopenharmony_ci const tcu::IVec2 renderSize = tcu::IVec2(64, 64); 424e5c31af7Sopenharmony_ci const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM; 425e5c31af7Sopenharmony_ci const VkImageSubresourceRange colorImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u); 426e5c31af7Sopenharmony_ci const ImageWithMemory colorAttachmentImage (vk, device, allocator, 427e5c31af7Sopenharmony_ci makeImageCreateInfo(renderSize, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 1u), 428e5c31af7Sopenharmony_ci MemoryRequirement::Any); 429e5c31af7Sopenharmony_ci 430e5c31af7Sopenharmony_ci // Color output buffer: image will be copied here for verification 431e5c31af7Sopenharmony_ci 432e5c31af7Sopenharmony_ci const VkDeviceSize colorBufferSizeBytes = renderSize.x()*renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat)); 433e5c31af7Sopenharmony_ci const BufferWithMemory colorBuffer (vk, device, allocator, makeBufferCreateInfo(colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT), MemoryRequirement::HostVisible); 434e5c31af7Sopenharmony_ci 435e5c31af7Sopenharmony_ci // Pipeline 436e5c31af7Sopenharmony_ci 437e5c31af7Sopenharmony_ci const Unique<VkImageView> colorAttachmentView (makeImageView (vk, device, *colorAttachmentImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorImageSubresourceRange)); 438e5c31af7Sopenharmony_ci const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, colorFormat)); 439e5c31af7Sopenharmony_ci const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, *colorAttachmentView, renderSize.x(), renderSize.y())); 440e5c31af7Sopenharmony_ci const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout (vk, device)); 441e5c31af7Sopenharmony_ci 442e5c31af7Sopenharmony_ci const VkCullModeFlags cullMode = VK_CULL_MODE_BACK_BIT; 443e5c31af7Sopenharmony_ci 444e5c31af7Sopenharmony_ci // Front face is static state, so we have to create two pipelines. 445e5c31af7Sopenharmony_ci 446e5c31af7Sopenharmony_ci const Unique<VkPipeline> pipelineCounterClockwise(GraphicsPipelineBuilder() 447e5c31af7Sopenharmony_ci .setCullModeFlags (cullMode) 448e5c31af7Sopenharmony_ci .setFrontFace (VK_FRONT_FACE_COUNTER_CLOCKWISE) 449e5c31af7Sopenharmony_ci .setShader (vk, device, VK_SHADER_STAGE_VERTEX_BIT, m_context.getBinaryCollection().get("vert"), DE_NULL) 450e5c31af7Sopenharmony_ci .setShader (vk, device, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, m_context.getBinaryCollection().get("tesc"), DE_NULL) 451e5c31af7Sopenharmony_ci .setShader (vk, device, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, m_context.getBinaryCollection().get("tese"), DE_NULL) 452e5c31af7Sopenharmony_ci .setShader (vk, device, VK_SHADER_STAGE_FRAGMENT_BIT, m_context.getBinaryCollection().get("frag"), DE_NULL) 453e5c31af7Sopenharmony_ci .setTessellationDomainOrigin (m_domainOrigin) 454e5c31af7Sopenharmony_ci .build (vk, device, *pipelineLayout, *renderPass)); 455e5c31af7Sopenharmony_ci 456e5c31af7Sopenharmony_ci const Unique<VkPipeline> pipelineClockwise(GraphicsPipelineBuilder() 457e5c31af7Sopenharmony_ci .setCullModeFlags (cullMode) 458e5c31af7Sopenharmony_ci .setFrontFace (VK_FRONT_FACE_CLOCKWISE) 459e5c31af7Sopenharmony_ci .setShader (vk, device, VK_SHADER_STAGE_VERTEX_BIT, m_context.getBinaryCollection().get("vert"), DE_NULL) 460e5c31af7Sopenharmony_ci .setShader (vk, device, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, m_context.getBinaryCollection().get("tesc"), DE_NULL) 461e5c31af7Sopenharmony_ci .setShader (vk, device, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, m_context.getBinaryCollection().get("tese"), DE_NULL) 462e5c31af7Sopenharmony_ci .setShader (vk, device, VK_SHADER_STAGE_FRAGMENT_BIT, m_context.getBinaryCollection().get("frag"), DE_NULL) 463e5c31af7Sopenharmony_ci .setTessellationDomainOrigin (m_domainOrigin) 464e5c31af7Sopenharmony_ci .build (vk, device, *pipelineLayout, *renderPass)); 465e5c31af7Sopenharmony_ci 466e5c31af7Sopenharmony_ci const struct // not static 467e5c31af7Sopenharmony_ci { 468e5c31af7Sopenharmony_ci Winding frontFaceWinding; 469e5c31af7Sopenharmony_ci VkPipeline pipeline; 470e5c31af7Sopenharmony_ci } testCases[] = 471e5c31af7Sopenharmony_ci { 472e5c31af7Sopenharmony_ci { WINDING_CCW, *pipelineCounterClockwise }, 473e5c31af7Sopenharmony_ci { WINDING_CW, *pipelineClockwise }, 474e5c31af7Sopenharmony_ci }; 475e5c31af7Sopenharmony_ci 476e5c31af7Sopenharmony_ci tcu::TestLog& log = m_context.getTestContext().getLog(); 477e5c31af7Sopenharmony_ci log << tcu::TestLog::Message << "Pipeline uses " << getCullModeFlagsStr(cullMode) << tcu::TestLog::EndMessage; 478e5c31af7Sopenharmony_ci 479e5c31af7Sopenharmony_ci bool success = true; 480e5c31af7Sopenharmony_ci 481e5c31af7Sopenharmony_ci // Draw commands 482e5c31af7Sopenharmony_ci 483e5c31af7Sopenharmony_ci const Unique<VkCommandPool> cmdPool (makeCommandPool (vk, device, queueFamilyIndex)); 484e5c31af7Sopenharmony_ci const Unique<VkCommandBuffer> cmdBuffer(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY)); 485e5c31af7Sopenharmony_ci 486e5c31af7Sopenharmony_ci for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(testCases); ++caseNdx) 487e5c31af7Sopenharmony_ci { 488e5c31af7Sopenharmony_ci const Winding frontFaceWinding = testCases[caseNdx].frontFaceWinding; 489e5c31af7Sopenharmony_ci 490e5c31af7Sopenharmony_ci log << tcu::TestLog::Message << "Setting " << getFrontFaceName(mapFrontFace(frontFaceWinding)) << tcu::TestLog::EndMessage; 491e5c31af7Sopenharmony_ci 492e5c31af7Sopenharmony_ci // Reset the command buffer and begin. 493e5c31af7Sopenharmony_ci beginCommandBuffer(vk, *cmdBuffer); 494e5c31af7Sopenharmony_ci 495e5c31af7Sopenharmony_ci // Change color attachment image layout 496e5c31af7Sopenharmony_ci { 497e5c31af7Sopenharmony_ci // State is slightly different on the first iteration. 498e5c31af7Sopenharmony_ci const VkImageLayout currentLayout = (caseNdx == 0 ? VK_IMAGE_LAYOUT_UNDEFINED : VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); 499e5c31af7Sopenharmony_ci const VkAccessFlags srcFlags = (caseNdx == 0 ? (VkAccessFlags)0 : (VkAccessFlags)VK_ACCESS_TRANSFER_READ_BIT); 500e5c31af7Sopenharmony_ci 501e5c31af7Sopenharmony_ci const VkImageMemoryBarrier colorAttachmentLayoutBarrier = makeImageMemoryBarrier( 502e5c31af7Sopenharmony_ci srcFlags, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, 503e5c31af7Sopenharmony_ci currentLayout, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 504e5c31af7Sopenharmony_ci *colorAttachmentImage, colorImageSubresourceRange); 505e5c31af7Sopenharmony_ci 506e5c31af7Sopenharmony_ci vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 507e5c31af7Sopenharmony_ci 0u, DE_NULL, 0u, DE_NULL, 1u, &colorAttachmentLayoutBarrier); 508e5c31af7Sopenharmony_ci } 509e5c31af7Sopenharmony_ci 510e5c31af7Sopenharmony_ci // Begin render pass 511e5c31af7Sopenharmony_ci { 512e5c31af7Sopenharmony_ci const VkRect2D renderArea = makeRect2D(renderSize); 513e5c31af7Sopenharmony_ci const tcu::Vec4 clearColor = tcu::RGBA::red().toVec(); 514e5c31af7Sopenharmony_ci 515e5c31af7Sopenharmony_ci beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, clearColor); 516e5c31af7Sopenharmony_ci } 517e5c31af7Sopenharmony_ci 518e5c31af7Sopenharmony_ci const VkViewport viewport = 519e5c31af7Sopenharmony_ci { 520e5c31af7Sopenharmony_ci 0.0f, // float x; 521e5c31af7Sopenharmony_ci m_yFlip ? static_cast<float>(renderSize.y()) : 0.0f, // float y; 522e5c31af7Sopenharmony_ci static_cast<float>(renderSize.x()), // float width; 523e5c31af7Sopenharmony_ci static_cast<float>(m_yFlip ? -renderSize.y() : renderSize.y()), // float height; 524e5c31af7Sopenharmony_ci 0.0f, // float minDepth; 525e5c31af7Sopenharmony_ci 1.0f, // float maxDepth; 526e5c31af7Sopenharmony_ci }; 527e5c31af7Sopenharmony_ci vk.cmdSetViewport(*cmdBuffer, 0, 1, &viewport); 528e5c31af7Sopenharmony_ci 529e5c31af7Sopenharmony_ci const VkRect2D scissor = makeRect2D(renderSize); 530e5c31af7Sopenharmony_ci vk.cmdSetScissor(*cmdBuffer, 0, 1, &scissor); 531e5c31af7Sopenharmony_ci 532e5c31af7Sopenharmony_ci vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, testCases[caseNdx].pipeline); 533e5c31af7Sopenharmony_ci 534e5c31af7Sopenharmony_ci // Process a single abstract vertex. 535e5c31af7Sopenharmony_ci vk.cmdDraw(*cmdBuffer, 1u, 1u, 0u, 0u); 536e5c31af7Sopenharmony_ci endRenderPass(vk, *cmdBuffer); 537e5c31af7Sopenharmony_ci 538e5c31af7Sopenharmony_ci // Copy render result to a host-visible buffer 539e5c31af7Sopenharmony_ci copyImageToBuffer(vk, *cmdBuffer, *colorAttachmentImage, *colorBuffer, renderSize); 540e5c31af7Sopenharmony_ci 541e5c31af7Sopenharmony_ci endCommandBuffer(vk, *cmdBuffer); 542e5c31af7Sopenharmony_ci submitCommandsAndWait(vk, device, queue, *cmdBuffer); 543e5c31af7Sopenharmony_ci 544e5c31af7Sopenharmony_ci { 545e5c31af7Sopenharmony_ci // Log rendered image 546e5c31af7Sopenharmony_ci const Allocation& colorBufferAlloc = colorBuffer.getAllocation(); 547e5c31af7Sopenharmony_ci 548e5c31af7Sopenharmony_ci invalidateAlloc(vk, device, colorBufferAlloc); 549e5c31af7Sopenharmony_ci 550e5c31af7Sopenharmony_ci const tcu::ConstPixelBufferAccess imagePixelAccess (mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1, colorBufferAlloc.getHostPtr()); 551e5c31af7Sopenharmony_ci 552e5c31af7Sopenharmony_ci log << tcu::TestLog::Image("color0", "Rendered image", imagePixelAccess); 553e5c31af7Sopenharmony_ci 554e5c31af7Sopenharmony_ci // Verify case result 555e5c31af7Sopenharmony_ci success = verifyResultImage(log, 556e5c31af7Sopenharmony_ci imagePixelAccess, 557e5c31af7Sopenharmony_ci m_primitiveType, 558e5c31af7Sopenharmony_ci !m_domainOrigin ? VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT : *m_domainOrigin, 559e5c31af7Sopenharmony_ci m_winding, 560e5c31af7Sopenharmony_ci m_yFlip, 561e5c31af7Sopenharmony_ci frontFaceWinding) && success; 562e5c31af7Sopenharmony_ci } 563e5c31af7Sopenharmony_ci } // for windingNdx 564e5c31af7Sopenharmony_ci 565e5c31af7Sopenharmony_ci return (success ? tcu::TestStatus::pass("OK") : tcu::TestStatus::fail("Failure")); 566e5c31af7Sopenharmony_ci} 567e5c31af7Sopenharmony_ci 568e5c31af7Sopenharmony_ciTestInstance* WindingTest::createInstance (Context& context) const 569e5c31af7Sopenharmony_ci{ 570e5c31af7Sopenharmony_ci requireFeatures(context.getInstanceInterface(), context.getPhysicalDevice(), FEATURE_TESSELLATION_SHADER); 571e5c31af7Sopenharmony_ci 572e5c31af7Sopenharmony_ci return new WindingTestInstance(context, m_primitiveType, m_domainOrigin, m_winding, m_yFlip); 573e5c31af7Sopenharmony_ci} 574e5c31af7Sopenharmony_ci 575e5c31af7Sopenharmony_civoid populateWindingGroup (tcu::TestCaseGroup* group, tcu::Maybe<VkTessellationDomainOrigin> domainOrigin) 576e5c31af7Sopenharmony_ci{ 577e5c31af7Sopenharmony_ci static const TessPrimitiveType primitivesNoIsolines[] = 578e5c31af7Sopenharmony_ci { 579e5c31af7Sopenharmony_ci TESSPRIMITIVETYPE_TRIANGLES, 580e5c31af7Sopenharmony_ci TESSPRIMITIVETYPE_QUADS, 581e5c31af7Sopenharmony_ci }; 582e5c31af7Sopenharmony_ci 583e5c31af7Sopenharmony_ci static const ShaderLanguage shaderLanguage[] = 584e5c31af7Sopenharmony_ci { 585e5c31af7Sopenharmony_ci SHADER_LANGUAGE_GLSL, 586e5c31af7Sopenharmony_ci SHADER_LANGUAGE_HLSL, 587e5c31af7Sopenharmony_ci }; 588e5c31af7Sopenharmony_ci 589e5c31af7Sopenharmony_ci for (int primitiveTypeNdx = 0; primitiveTypeNdx < DE_LENGTH_OF_ARRAY(primitivesNoIsolines); ++primitiveTypeNdx) 590e5c31af7Sopenharmony_ci for (int shaderLanguageNdx = 0; shaderLanguageNdx < DE_LENGTH_OF_ARRAY(shaderLanguage); ++shaderLanguageNdx) 591e5c31af7Sopenharmony_ci for (int windingNdx = 0; windingNdx < WINDING_LAST; ++windingNdx) 592e5c31af7Sopenharmony_ci { 593e5c31af7Sopenharmony_ci group->addChild(new WindingTest(group->getTestContext(), primitivesNoIsolines[primitiveTypeNdx], domainOrigin, shaderLanguage[shaderLanguageNdx], (Winding)windingNdx, false)); 594e5c31af7Sopenharmony_ci group->addChild(new WindingTest(group->getTestContext(), primitivesNoIsolines[primitiveTypeNdx], domainOrigin, shaderLanguage[shaderLanguageNdx], (Winding)windingNdx, true)); 595e5c31af7Sopenharmony_ci } 596e5c31af7Sopenharmony_ci} 597e5c31af7Sopenharmony_ci 598e5c31af7Sopenharmony_ci} // anonymous 599e5c31af7Sopenharmony_ci 600e5c31af7Sopenharmony_ci//! These tests correspond to dEQP-GLES31.functional.tessellation.winding.* 601e5c31af7Sopenharmony_citcu::TestCaseGroup* createWindingTests (tcu::TestContext& testCtx) 602e5c31af7Sopenharmony_ci{ 603e5c31af7Sopenharmony_ci // Test the cw and ccw input layout qualifiers 604e5c31af7Sopenharmony_ci de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "winding")); 605e5c31af7Sopenharmony_ci 606e5c31af7Sopenharmony_ci // No tessellation domain specified 607e5c31af7Sopenharmony_ci addTestGroup(group.get(), "default_domain", populateWindingGroup, tcu::nothing<VkTessellationDomainOrigin>()); 608e5c31af7Sopenharmony_ci // Lower left tessellation domain 609e5c31af7Sopenharmony_ci addTestGroup(group.get(), "lower_left_domain", populateWindingGroup, tcu::just(VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT)); 610e5c31af7Sopenharmony_ci // Upper left tessellation domain 611e5c31af7Sopenharmony_ci addTestGroup(group.get(), "upper_left_domain", populateWindingGroup, tcu::just(VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT)); 612e5c31af7Sopenharmony_ci 613e5c31af7Sopenharmony_ci return group.release(); 614e5c31af7Sopenharmony_ci} 615e5c31af7Sopenharmony_ci 616e5c31af7Sopenharmony_ci} // tessellation 617e5c31af7Sopenharmony_ci} // vkt 618