1e5c31af7Sopenharmony_ci/*------------------------------------------------------------------------- 2e5c31af7Sopenharmony_ci * drawElements Quality Program OpenGL ES 3.0 Module 3e5c31af7Sopenharmony_ci * ------------------------------------------------- 4e5c31af7Sopenharmony_ci * 5e5c31af7Sopenharmony_ci * Copyright 2014 The Android Open Source Project 6e5c31af7Sopenharmony_ci * 7e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 8e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License. 9e5c31af7Sopenharmony_ci * You may obtain a copy of the License at 10e5c31af7Sopenharmony_ci * 11e5c31af7Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 12e5c31af7Sopenharmony_ci * 13e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 14e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 15e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and 17e5c31af7Sopenharmony_ci * limitations under the License. 18e5c31af7Sopenharmony_ci * 19e5c31af7Sopenharmony_ci *//*! 20e5c31af7Sopenharmony_ci * \file 21e5c31af7Sopenharmony_ci * \brief Occlusion query stress tests 22e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 23e5c31af7Sopenharmony_ci 24e5c31af7Sopenharmony_ci#include "es3sOcclusionQueryTests.hpp" 25e5c31af7Sopenharmony_ci 26e5c31af7Sopenharmony_ci#include "deRandom.hpp" 27e5c31af7Sopenharmony_ci#include "deStringUtil.hpp" 28e5c31af7Sopenharmony_ci#include "deString.h" 29e5c31af7Sopenharmony_ci#include "tcuTestLog.hpp" 30e5c31af7Sopenharmony_ci#include "tcuVector.hpp" 31e5c31af7Sopenharmony_ci#include "tcuSurface.hpp" 32e5c31af7Sopenharmony_ci#include "gluShaderProgram.hpp" 33e5c31af7Sopenharmony_ci#include "deClock.h" 34e5c31af7Sopenharmony_ci 35e5c31af7Sopenharmony_ci#include "glw.h" 36e5c31af7Sopenharmony_ci 37e5c31af7Sopenharmony_ci#include <vector> 38e5c31af7Sopenharmony_ci 39e5c31af7Sopenharmony_ciusing std::vector; 40e5c31af7Sopenharmony_ciusing tcu::TestLog; 41e5c31af7Sopenharmony_ci 42e5c31af7Sopenharmony_cinamespace deqp 43e5c31af7Sopenharmony_ci{ 44e5c31af7Sopenharmony_cinamespace gles3 45e5c31af7Sopenharmony_ci{ 46e5c31af7Sopenharmony_cinamespace Stress 47e5c31af7Sopenharmony_ci{ 48e5c31af7Sopenharmony_ci 49e5c31af7Sopenharmony_cistatic const tcu::Vec4 OCCLUDER_COLOR = tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f); 50e5c31af7Sopenharmony_cistatic const tcu::Vec4 TARGET_COLOR = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f); 51e5c31af7Sopenharmony_cistatic const int NUM_CASE_ITERATIONS = 3; 52e5c31af7Sopenharmony_cistatic const int NUM_GENERATED_VERTICES = 100; 53e5c31af7Sopenharmony_cistatic const int WATCHDOG_INTERVAL = 50; // Touch watchdog every N iterations. 54e5c31af7Sopenharmony_ci 55e5c31af7Sopenharmony_ciclass OcclusionQueryStressCase : public TestCase 56e5c31af7Sopenharmony_ci{ 57e5c31af7Sopenharmony_cipublic: 58e5c31af7Sopenharmony_ci OcclusionQueryStressCase (Context& ctx, const char* name, const char* desc, int m_numOccluderDraws, int m_numOccludersPerDraw, int m_numTargetDraws, int m_numTargetsPerDraw, int m_numQueries, deUint32 m_queryMode); 59e5c31af7Sopenharmony_ci ~OcclusionQueryStressCase (void); 60e5c31af7Sopenharmony_ci 61e5c31af7Sopenharmony_ci void init (void); 62e5c31af7Sopenharmony_ci void deinit (void); 63e5c31af7Sopenharmony_ci IterateResult iterate (void); 64e5c31af7Sopenharmony_ci 65e5c31af7Sopenharmony_ciprivate: 66e5c31af7Sopenharmony_ci OcclusionQueryStressCase (const OcclusionQueryStressCase&); 67e5c31af7Sopenharmony_ci OcclusionQueryStressCase& operator= (const OcclusionQueryStressCase&); 68e5c31af7Sopenharmony_ci 69e5c31af7Sopenharmony_ci int m_numOccluderDraws; 70e5c31af7Sopenharmony_ci int m_numOccludersPerDraw; 71e5c31af7Sopenharmony_ci int m_numTargetDraws; 72e5c31af7Sopenharmony_ci int m_numTargetsPerDraw; 73e5c31af7Sopenharmony_ci int m_numQueries; 74e5c31af7Sopenharmony_ci deUint32 m_queryMode; 75e5c31af7Sopenharmony_ci 76e5c31af7Sopenharmony_ci glu::RenderContext& m_renderCtx; 77e5c31af7Sopenharmony_ci glu::ShaderProgram* m_program; 78e5c31af7Sopenharmony_ci int m_iterNdx; 79e5c31af7Sopenharmony_ci de::Random m_rnd; 80e5c31af7Sopenharmony_ci 81e5c31af7Sopenharmony_ci}; 82e5c31af7Sopenharmony_ci 83e5c31af7Sopenharmony_ciOcclusionQueryStressCase::OcclusionQueryStressCase (Context& ctx, const char* name, const char* desc, int numOccluderDraws, int numOccludersPerDraw, int numTargetDraws, int numTargetsPerDraw, int numQueries, deUint32 queryMode) 84e5c31af7Sopenharmony_ci : TestCase (ctx, name, desc) 85e5c31af7Sopenharmony_ci , m_numOccluderDraws (numOccluderDraws) 86e5c31af7Sopenharmony_ci , m_numOccludersPerDraw (numOccludersPerDraw) 87e5c31af7Sopenharmony_ci , m_numTargetDraws (numTargetDraws) 88e5c31af7Sopenharmony_ci , m_numTargetsPerDraw (numTargetsPerDraw) 89e5c31af7Sopenharmony_ci , m_numQueries (numQueries) 90e5c31af7Sopenharmony_ci , m_queryMode (queryMode) 91e5c31af7Sopenharmony_ci , m_renderCtx (ctx.getRenderContext()) 92e5c31af7Sopenharmony_ci , m_program (DE_NULL) 93e5c31af7Sopenharmony_ci , m_iterNdx (0) 94e5c31af7Sopenharmony_ci , m_rnd (deStringHash(name)) 95e5c31af7Sopenharmony_ci{ 96e5c31af7Sopenharmony_ci} 97e5c31af7Sopenharmony_ci 98e5c31af7Sopenharmony_ciOcclusionQueryStressCase::~OcclusionQueryStressCase (void) 99e5c31af7Sopenharmony_ci{ 100e5c31af7Sopenharmony_ci OcclusionQueryStressCase::deinit(); 101e5c31af7Sopenharmony_ci} 102e5c31af7Sopenharmony_ci 103e5c31af7Sopenharmony_civoid OcclusionQueryStressCase::init (void) 104e5c31af7Sopenharmony_ci{ 105e5c31af7Sopenharmony_ci const char* vertShaderSource = 106e5c31af7Sopenharmony_ci "#version 300 es\n" 107e5c31af7Sopenharmony_ci "layout(location = 0) in mediump vec4 a_position;\n" 108e5c31af7Sopenharmony_ci "\n" 109e5c31af7Sopenharmony_ci "void main (void)\n" 110e5c31af7Sopenharmony_ci "{\n" 111e5c31af7Sopenharmony_ci " gl_Position = a_position;\n" 112e5c31af7Sopenharmony_ci "}\n"; 113e5c31af7Sopenharmony_ci 114e5c31af7Sopenharmony_ci const char* fragShaderSource = 115e5c31af7Sopenharmony_ci "#version 300 es\n" 116e5c31af7Sopenharmony_ci "layout(location = 0) out mediump vec4 dEQP_FragColor;\n" 117e5c31af7Sopenharmony_ci "uniform mediump vec4 u_color;\n" 118e5c31af7Sopenharmony_ci "\n" 119e5c31af7Sopenharmony_ci "void main (void)\n" 120e5c31af7Sopenharmony_ci "{\n" 121e5c31af7Sopenharmony_ci " mediump float depth_gradient = gl_FragCoord.z;\n" 122e5c31af7Sopenharmony_ci " mediump float bias = 0.1;\n" 123e5c31af7Sopenharmony_ci " dEQP_FragColor = vec4(u_color.xyz * (depth_gradient + bias), 1.0);\n" 124e5c31af7Sopenharmony_ci "}\n"; 125e5c31af7Sopenharmony_ci 126e5c31af7Sopenharmony_ci DE_ASSERT(!m_program); 127e5c31af7Sopenharmony_ci m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(vertShaderSource, fragShaderSource)); 128e5c31af7Sopenharmony_ci 129e5c31af7Sopenharmony_ci if (!m_program->isOk()) 130e5c31af7Sopenharmony_ci { 131e5c31af7Sopenharmony_ci m_testCtx.getLog() << *m_program; 132e5c31af7Sopenharmony_ci TCU_FAIL("Failed to compile shader program"); 133e5c31af7Sopenharmony_ci } 134e5c31af7Sopenharmony_ci 135e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); // Initialize test result to pass. 136e5c31af7Sopenharmony_ci GLU_CHECK_MSG ("Case initialization finished"); 137e5c31af7Sopenharmony_ci} 138e5c31af7Sopenharmony_ci 139e5c31af7Sopenharmony_civoid OcclusionQueryStressCase::deinit (void) 140e5c31af7Sopenharmony_ci{ 141e5c31af7Sopenharmony_ci delete m_program; 142e5c31af7Sopenharmony_ci m_program = DE_NULL; 143e5c31af7Sopenharmony_ci} 144e5c31af7Sopenharmony_ci 145e5c31af7Sopenharmony_ci 146e5c31af7Sopenharmony_ciOcclusionQueryStressCase::IterateResult OcclusionQueryStressCase::iterate (void) 147e5c31af7Sopenharmony_ci{ 148e5c31af7Sopenharmony_ci tcu::TestLog& log = m_testCtx.getLog(); 149e5c31af7Sopenharmony_ci deUint32 colorUnif = glGetUniformLocation(m_program->getProgram(), "u_color"); 150e5c31af7Sopenharmony_ci 151e5c31af7Sopenharmony_ci std::vector<float> vertices; 152e5c31af7Sopenharmony_ci std::vector<float> occluderVertices; 153e5c31af7Sopenharmony_ci std::vector<float> targetVertices; 154e5c31af7Sopenharmony_ci std::vector<deUint32> queryIds (m_numQueries, 0); 155e5c31af7Sopenharmony_ci std::vector<deUint32> queryResultReady (m_numQueries, 0); 156e5c31af7Sopenharmony_ci std::vector<deUint32> queryResult (m_numQueries, 0); 157e5c31af7Sopenharmony_ci 158e5c31af7Sopenharmony_ci std::string sectionName ("Case iteration " + de::toString(m_iterNdx+1) + "/" + de::toString(NUM_CASE_ITERATIONS)); 159e5c31af7Sopenharmony_ci tcu::ScopedLogSection section (log, sectionName.c_str(), sectionName.c_str()); 160e5c31af7Sopenharmony_ci 161e5c31af7Sopenharmony_ci log << tcu::TestLog::Message << "Parameters:\n" 162e5c31af7Sopenharmony_ci << "- Number of occlusion queries: " << m_numQueries << ".\n" 163e5c31af7Sopenharmony_ci << "- Number of occluder draws per query: " << m_numOccluderDraws << ", primitives per draw: " << m_numOccludersPerDraw << ".\n" 164e5c31af7Sopenharmony_ci << "- Number of target draws per query: " << m_numTargetDraws << ", primitives per draw: " << m_numTargetsPerDraw << ".\n" 165e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 166e5c31af7Sopenharmony_ci 167e5c31af7Sopenharmony_ci int numOccluderIndicesPerDraw = 3*m_numOccludersPerDraw; 168e5c31af7Sopenharmony_ci int numTargetIndicesPerDraw = 3*m_numTargetsPerDraw; 169e5c31af7Sopenharmony_ci 170e5c31af7Sopenharmony_ci // Generate vertex data 171e5c31af7Sopenharmony_ci 172e5c31af7Sopenharmony_ci vertices.resize(4*NUM_GENERATED_VERTICES); 173e5c31af7Sopenharmony_ci 174e5c31af7Sopenharmony_ci for (int i = 0; i < NUM_GENERATED_VERTICES; i++) 175e5c31af7Sopenharmony_ci { 176e5c31af7Sopenharmony_ci vertices[4*i ] = m_rnd.getFloat(-1.0f, 1.0f); 177e5c31af7Sopenharmony_ci vertices[4*i + 1] = m_rnd.getFloat(-1.0f, 1.0f); 178e5c31af7Sopenharmony_ci vertices[4*i + 2] = m_rnd.getFloat(0.0f, 1.0f); 179e5c31af7Sopenharmony_ci vertices[4*i + 3] = 1.0f; 180e5c31af7Sopenharmony_ci } 181e5c31af7Sopenharmony_ci 182e5c31af7Sopenharmony_ci // Generate primitives 183e5c31af7Sopenharmony_ci 184e5c31af7Sopenharmony_ci occluderVertices.resize(4*numOccluderIndicesPerDraw * m_numOccluderDraws); 185e5c31af7Sopenharmony_ci 186e5c31af7Sopenharmony_ci for (int i = 0; i < numOccluderIndicesPerDraw * m_numOccluderDraws; i++) 187e5c31af7Sopenharmony_ci { 188e5c31af7Sopenharmony_ci int vtxNdx = m_rnd.getInt(0, NUM_GENERATED_VERTICES-1); 189e5c31af7Sopenharmony_ci occluderVertices[4*i ] = vertices[4*vtxNdx]; 190e5c31af7Sopenharmony_ci occluderVertices[4*i + 1] = vertices[4*vtxNdx + 1]; 191e5c31af7Sopenharmony_ci occluderVertices[4*i + 2] = vertices[4*vtxNdx + 2]; 192e5c31af7Sopenharmony_ci occluderVertices[4*i + 3] = vertices[4*vtxNdx + 3]; 193e5c31af7Sopenharmony_ci } 194e5c31af7Sopenharmony_ci 195e5c31af7Sopenharmony_ci targetVertices.resize(4*numTargetIndicesPerDraw * m_numTargetDraws); 196e5c31af7Sopenharmony_ci 197e5c31af7Sopenharmony_ci for (int i = 0; i < numTargetIndicesPerDraw * m_numTargetDraws; i++) 198e5c31af7Sopenharmony_ci { 199e5c31af7Sopenharmony_ci int vtxNdx = m_rnd.getInt(0, NUM_GENERATED_VERTICES-1); 200e5c31af7Sopenharmony_ci targetVertices[4*i ] = vertices[4*vtxNdx]; 201e5c31af7Sopenharmony_ci targetVertices[4*i + 1] = vertices[4*vtxNdx + 1]; 202e5c31af7Sopenharmony_ci targetVertices[4*i + 2] = vertices[4*vtxNdx + 2]; 203e5c31af7Sopenharmony_ci targetVertices[4*i + 3] = vertices[4*vtxNdx + 3]; 204e5c31af7Sopenharmony_ci } 205e5c31af7Sopenharmony_ci 206e5c31af7Sopenharmony_ci TCU_CHECK(m_program); 207e5c31af7Sopenharmony_ci 208e5c31af7Sopenharmony_ci glClearColor (0.0f, 0.0f, 0.0f, 1.0f); 209e5c31af7Sopenharmony_ci glClearDepthf (1.0f); 210e5c31af7Sopenharmony_ci glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 211e5c31af7Sopenharmony_ci glEnable (GL_DEPTH_TEST); 212e5c31af7Sopenharmony_ci glUseProgram (m_program->getProgram()); 213e5c31af7Sopenharmony_ci glEnableVertexAttribArray (0); 214e5c31af7Sopenharmony_ci 215e5c31af7Sopenharmony_ci deUint64 time = deGetMicroseconds(); 216e5c31af7Sopenharmony_ci 217e5c31af7Sopenharmony_ci for (int queryIter = 0; queryIter < m_numQueries; queryIter++) 218e5c31af7Sopenharmony_ci { 219e5c31af7Sopenharmony_ci // Draw occluders 220e5c31af7Sopenharmony_ci 221e5c31af7Sopenharmony_ci glUniform4f (colorUnif, OCCLUDER_COLOR.x(), OCCLUDER_COLOR.y(), OCCLUDER_COLOR.z(), OCCLUDER_COLOR.w()); 222e5c31af7Sopenharmony_ci 223e5c31af7Sopenharmony_ci for (int drawIter = 0; drawIter < m_numOccluderDraws; drawIter++) 224e5c31af7Sopenharmony_ci { 225e5c31af7Sopenharmony_ci glVertexAttribPointer (0, 4, GL_FLOAT, GL_FALSE, 0, &occluderVertices[drawIter * numOccluderIndicesPerDraw]); 226e5c31af7Sopenharmony_ci glDrawArrays (GL_TRIANGLES, 0, numOccluderIndicesPerDraw); 227e5c31af7Sopenharmony_ci } 228e5c31af7Sopenharmony_ci 229e5c31af7Sopenharmony_ci // Begin occlusion query 230e5c31af7Sopenharmony_ci 231e5c31af7Sopenharmony_ci glGenQueries (1, &queryIds[queryIter]); 232e5c31af7Sopenharmony_ci glBeginQuery (m_queryMode, queryIds[queryIter]); 233e5c31af7Sopenharmony_ci 234e5c31af7Sopenharmony_ci // Draw targets 235e5c31af7Sopenharmony_ci 236e5c31af7Sopenharmony_ci glUniform4f (colorUnif, TARGET_COLOR.x(), TARGET_COLOR.y(), TARGET_COLOR.z(), TARGET_COLOR.w()); 237e5c31af7Sopenharmony_ci 238e5c31af7Sopenharmony_ci for (int drawIter = 0; drawIter < m_numTargetDraws; drawIter++) 239e5c31af7Sopenharmony_ci { 240e5c31af7Sopenharmony_ci glVertexAttribPointer (0, 4, GL_FLOAT, GL_FALSE, 0, &targetVertices[drawIter * numTargetIndicesPerDraw]); 241e5c31af7Sopenharmony_ci glDrawArrays (GL_TRIANGLES, 0, numTargetIndicesPerDraw); 242e5c31af7Sopenharmony_ci } 243e5c31af7Sopenharmony_ci 244e5c31af7Sopenharmony_ci // End occlusion query 245e5c31af7Sopenharmony_ci 246e5c31af7Sopenharmony_ci glEndQuery (m_queryMode); 247e5c31af7Sopenharmony_ci 248e5c31af7Sopenharmony_ci if ((queryIter % WATCHDOG_INTERVAL) == 0 && m_testCtx.getWatchDog()) 249e5c31af7Sopenharmony_ci qpWatchDog_touch(m_testCtx.getWatchDog()); 250e5c31af7Sopenharmony_ci } 251e5c31af7Sopenharmony_ci 252e5c31af7Sopenharmony_ci glFinish(); 253e5c31af7Sopenharmony_ci glDisable(GL_DEPTH_TEST); 254e5c31af7Sopenharmony_ci 255e5c31af7Sopenharmony_ci deUint64 dTime = deGetMicroseconds() - time; 256e5c31af7Sopenharmony_ci log << tcu::TestLog::Message << "Total duration: " << dTime/1000 << " ms" << tcu::TestLog::EndMessage; 257e5c31af7Sopenharmony_ci 258e5c31af7Sopenharmony_ci // Get results 259e5c31af7Sopenharmony_ci 260e5c31af7Sopenharmony_ci for (int queryIter = 0; queryIter < m_numQueries; queryIter++) 261e5c31af7Sopenharmony_ci { 262e5c31af7Sopenharmony_ci glGetQueryObjectuiv(queryIds[queryIter], GL_QUERY_RESULT_AVAILABLE, &queryResultReady[queryIter]); 263e5c31af7Sopenharmony_ci 264e5c31af7Sopenharmony_ci if (queryResultReady[queryIter] == GL_TRUE) 265e5c31af7Sopenharmony_ci { 266e5c31af7Sopenharmony_ci glGetQueryObjectuiv(queryIds[queryIter], GL_QUERY_RESULT, &queryResult[queryIter]); 267e5c31af7Sopenharmony_ci } 268e5c31af7Sopenharmony_ci else 269e5c31af7Sopenharmony_ci TCU_FAIL("Occlusion query failed to return a result after glFinish()"); 270e5c31af7Sopenharmony_ci 271e5c31af7Sopenharmony_ci if ((queryIter % WATCHDOG_INTERVAL) == 0 && m_testCtx.getWatchDog()) 272e5c31af7Sopenharmony_ci qpWatchDog_touch(m_testCtx.getWatchDog()); 273e5c31af7Sopenharmony_ci } 274e5c31af7Sopenharmony_ci 275e5c31af7Sopenharmony_ci glDeleteQueries (m_numQueries, &queryIds[0]); 276e5c31af7Sopenharmony_ci GLU_CHECK_MSG ("Occlusion queries finished"); 277e5c31af7Sopenharmony_ci 278e5c31af7Sopenharmony_ci log << tcu::TestLog::Message << "Case passed!" << tcu::TestLog::EndMessage; 279e5c31af7Sopenharmony_ci 280e5c31af7Sopenharmony_ci return (++m_iterNdx < NUM_CASE_ITERATIONS) ? CONTINUE : STOP; 281e5c31af7Sopenharmony_ci} 282e5c31af7Sopenharmony_ci 283e5c31af7Sopenharmony_ci 284e5c31af7Sopenharmony_ciOcclusionQueryTests::OcclusionQueryTests (Context& testCtx) 285e5c31af7Sopenharmony_ci : TestCaseGroup(testCtx, "occlusion_query", "Occlusion query stress tests") 286e5c31af7Sopenharmony_ci{ 287e5c31af7Sopenharmony_ci} 288e5c31af7Sopenharmony_ci 289e5c31af7Sopenharmony_ciOcclusionQueryTests::~OcclusionQueryTests(void) 290e5c31af7Sopenharmony_ci{ 291e5c31af7Sopenharmony_ci} 292e5c31af7Sopenharmony_ci 293e5c31af7Sopenharmony_civoid OcclusionQueryTests::init (void) 294e5c31af7Sopenharmony_ci{ 295e5c31af7Sopenharmony_ci addChild(new OcclusionQueryStressCase(m_context, "10_queries_2500_triangles_per_query", "10_queries_2500_triangles_per_query", 49, 50, 1, 50, 10, GL_ANY_SAMPLES_PASSED)); 296e5c31af7Sopenharmony_ci addChild(new OcclusionQueryStressCase(m_context, "100_queries_2500_triangles_per_query", "100_queries_2500_triangles_per_query", 49, 50, 1, 50, 100, GL_ANY_SAMPLES_PASSED)); 297e5c31af7Sopenharmony_ci addChild(new OcclusionQueryStressCase(m_context, "1000_queries_500_triangles_per_query", "1000_queries_500_triangles_per_query", 49, 10, 1, 10, 1000, GL_ANY_SAMPLES_PASSED)); 298e5c31af7Sopenharmony_ci addChild(new OcclusionQueryStressCase(m_context, "10000_queries_20_triangles_per_query", "10000_queries_20_triangles_per_query", 1, 19, 1, 1, 10000, GL_ANY_SAMPLES_PASSED)); 299e5c31af7Sopenharmony_ci} 300e5c31af7Sopenharmony_ci 301e5c31af7Sopenharmony_ci} // Stress 302e5c31af7Sopenharmony_ci} // gles3 303e5c31af7Sopenharmony_ci} // deqp 304