/*------------------------------------------------------------------------- * drawElements Quality Program EGL Module * --------------------------------------- * * Copyright 2014 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 GLES2 resource sharing performnace tests. *//*--------------------------------------------------------------------*/ #include "teglGLES2SharedRenderingPerfTests.hpp" #include "tcuTestLog.hpp" #include "egluUtil.hpp" #include "eglwLibrary.hpp" #include "eglwEnums.hpp" #include "gluDefs.hpp" #include "glwDefs.hpp" #include "glwEnums.hpp" #include "glwFunctions.hpp" #include "deThread.hpp" #include "deClock.h" #include "deStringUtil.hpp" #include "deSTLUtil.hpp" #include <vector> #include <string> #include <algorithm> #include <cmath> namespace deqp { namespace egl { using tcu::TestLog; using std::vector; using std::string; using namespace glw; using namespace eglw; namespace { struct TestConfig { enum TextureType { TEXTURETYPE_TEXTURE = 0, TEXTURETYPE_SHARED_TEXTURE, TEXTURETYPE_IMAGE, TEXTURETYPE_SHARED_IMAGE, TEXTURETYPE_SHARED_IMAGE_TEXTURE }; int threadCount; int perThreadContextCount; int frameCount; int drawCallCount; int triangleCount; bool sharedContexts; bool useCoordBuffer; bool sharedCoordBuffer; bool useIndices; bool useIndexBuffer; bool sharedIndexBuffer; bool useTexture; TextureType textureType; bool sharedProgram; int textureWidth; int textureHeight; int surfaceWidth; int surfaceHeight; }; class TestContext { public: TestContext (EglTestContext& eglTestCtx, EGLDisplay display, EGLConfig eglConfig, const TestConfig& config, bool share, TestContext* parent); ~TestContext (void); void render (void); EGLContext getEGLContext (void) { return m_eglContext; } GLuint getCoordBuffer (void) const { return m_coordBuffer; } GLuint getIndexBuffer (void) const { return m_indexBuffer; } GLuint getTexture (void) const { return m_texture; } GLuint getProgram (void) const { return m_program; } EGLImageKHR getEGLImage (void) const { return m_eglImage; } private: TestContext* m_parent; EglTestContext& m_testCtx; TestConfig m_config; EGLDisplay m_eglDisplay; EGLContext m_eglContext; EGLSurface m_eglSurface; glw::Functions m_gl; GLuint m_coordBuffer; GLuint m_indexBuffer; GLuint m_texture; GLuint m_program; EGLImageKHR m_eglImage; GLuint m_coordLoc; GLuint m_textureLoc; vector<float> m_coordData; vector<deUint16> m_indexData; EGLImageKHR createEGLImage (void); GLuint createTextureFromImage (EGLImageKHR image); // Not supported TestContext& operator= (const TestContext&); TestContext (const TestContext&); }; namespace { void createCoordData (vector<float>& data, const TestConfig& config) { if (config.useIndices) { for (int triangleNdx = 0; triangleNdx < 2; triangleNdx++) { const float x1 = -1.0f; const float y1 = -1.0f; const float x2 = 1.0f; const float y2 = 1.0f; const float side = ((triangleNdx % 2) == 0 ? 1.0f : -1.0f); data.push_back(side * x1); data.push_back(side * y1); data.push_back(side * x2); data.push_back(side * y1); data.push_back(side * x2); data.push_back(side * y2); } } else { data.reserve(config.triangleCount * 3 * 2); for (int triangleNdx = 0; triangleNdx < config.triangleCount; triangleNdx++) { const float x1 = -1.0f; const float y1 = -1.0f; const float x2 = 1.0f; const float y2 = 1.0f; const float side = ((triangleNdx % 2) == 0 ? 1.0f : -1.0f); data.push_back(side * x1); data.push_back(side * y1); data.push_back(side * x2); data.push_back(side * y1); data.push_back(side * x2); data.push_back(side * y2); } } } GLuint createCoordBuffer (const glw::Functions& gl, const TestConfig& config) { GLuint buffer; vector<float> data; createCoordData(data, config); gl.genBuffers(1, &buffer); GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers()"); gl.bindBuffer(GL_ARRAY_BUFFER, buffer); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer()"); gl.bufferData(GL_ARRAY_BUFFER, (GLsizei)(data.size() * sizeof(float)), &(data[0]), GL_STATIC_DRAW); GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData()"); gl.bindBuffer(GL_ARRAY_BUFFER, 0); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer()"); return buffer; } void createIndexData (vector<deUint16>& data, const TestConfig& config) { for (int triangleNdx = 0; triangleNdx < config.triangleCount; triangleNdx++) { if ((triangleNdx % 2) == 0) { data.push_back(0); data.push_back(1); data.push_back(2); } else { data.push_back(2); data.push_back(3); data.push_back(0); } } } GLuint createIndexBuffer (const glw::Functions& gl, const TestConfig& config) { GLuint buffer; vector<deUint16> data; createIndexData(data, config); gl.genBuffers(1, &buffer); GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers()"); gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer()"); gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizei)(data.size() * sizeof(deUint16)), &(data[0]), GL_STATIC_DRAW); GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData()"); gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer()"); return buffer; } void createTextureData (vector<deUint8>& data, const TestConfig& config) { for (int x = 0; x < config.textureWidth; x++) { for (int y = 0; y < config.textureHeight; y++) { data.push_back((deUint8)((255*x)/255)); data.push_back((deUint8)((255*y)/255)); data.push_back((deUint8)((255*x*y)/(255*255))); data.push_back(255); } } } GLuint createTexture (const glw::Functions& gl, const TestConfig& config) { GLuint texture; vector<deUint8> data; createTextureData(data, config); gl.genTextures(1, &texture); GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures()"); gl.bindTexture(GL_TEXTURE_2D, texture); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture()"); gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri"); gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri"); gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri"); gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri"); gl.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, config.textureWidth, config.textureWidth, 0, GL_RGBA, GL_UNSIGNED_BYTE, &(data[0])); GLU_EXPECT_NO_ERROR(gl.getError(), "glTexImage2D()"); gl.bindTexture(GL_TEXTURE_2D, 0); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture()"); return texture; } GLuint createProgram (const glw::Functions& gl, const TestConfig& config) { GLuint vertexShader = gl.createShader(GL_VERTEX_SHADER); GLuint fragmentShader = gl.createShader(GL_FRAGMENT_SHADER); if (config.useTexture) { const char* vertexShaderSource = "attribute mediump vec2 a_coord;\n" "varying mediump vec2 v_texCoord;\n" "void main(void)\n" "{\n" "\tv_texCoord = 0.5 * a_coord + vec2(0.5);\n" "\tgl_Position = vec4(a_coord, 0.0, 1.0);\n" "}\n"; const char* fragmentShaderSource = "uniform sampler2D u_sampler;\n" "varying mediump vec2 v_texCoord;\n" "void main(void)\n" "{\n" "\tgl_FragColor = texture2D(u_sampler, v_texCoord);\n" "}\n"; gl.shaderSource(vertexShader, 1, &vertexShaderSource, DE_NULL); GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource()"); gl.shaderSource(fragmentShader, 1, &fragmentShaderSource, DE_NULL); GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource()"); } else { const char* vertexShaderSource = "attribute mediump vec2 a_coord;\n" "varying mediump vec4 v_color;\n" "void main(void)\n" "{\n" "\tv_color = vec4(0.5 * a_coord + vec2(0.5), 0.5, 1.0);\n" "\tgl_Position = vec4(a_coord, 0.0, 1.0);\n" "}\n"; const char* fragmentShaderSource = "varying mediump vec4 v_color;\n" "void main(void)\n" "{\n" "\tgl_FragColor = v_color;\n" "}\n"; gl.shaderSource(vertexShader, 1, &vertexShaderSource, DE_NULL); GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource()"); gl.shaderSource(fragmentShader, 1, &fragmentShaderSource, DE_NULL); GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource()"); } gl.compileShader(vertexShader); GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader()"); gl.compileShader(fragmentShader); GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader()"); { GLint status; gl.getShaderiv(vertexShader, GL_COMPILE_STATUS, &status); GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv()"); if (!status) { string log; GLint length; gl.getShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &length); GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv()"); log.resize(length, 0); gl.getShaderInfoLog(vertexShader, (GLsizei)log.size(), &length, &(log[0])); GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderInfoLog()"); throw std::runtime_error(log.c_str()); } } { GLint status; gl.getShaderiv(fragmentShader, GL_COMPILE_STATUS, &status); GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv()"); if (!status) { string log; GLint length; gl.getShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &length); GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv()"); log.resize(length, 0); gl.getShaderInfoLog(fragmentShader, (GLsizei)log.size(), &length, &(log[0])); GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderInfoLog()"); throw std::runtime_error(log.c_str()); } } { GLuint program = gl.createProgram(); gl.attachShader(program, vertexShader); GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader()"); gl.attachShader(program, fragmentShader); GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader()"); gl.linkProgram(program); GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram()"); { GLint status; gl.getProgramiv(program, GL_LINK_STATUS, &status); GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv()"); if (!status) { string log; GLsizei length; gl.getProgramInfoLog(program, 0, &length, DE_NULL); GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInfoLog()"); log.resize(length, 0); gl.getProgramInfoLog(program, (GLsizei)log.size(), &length, &(log[0])); GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInfoLog()"); throw std::runtime_error(log.c_str()); } } gl.deleteShader(vertexShader); GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteShader()"); gl.deleteShader(fragmentShader); GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteShader()"); return program; } } EGLContext createEGLContext (EglTestContext& testCtx, EGLDisplay eglDisplay, EGLConfig eglConfig, EGLContext share) { const Library& egl = testCtx.getLibrary(); const EGLint attribList[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; EGLU_CHECK_CALL(egl, bindAPI(EGL_OPENGL_ES_API)); EGLContext context = egl.createContext(eglDisplay, eglConfig, share, attribList); EGLU_CHECK_MSG(egl, "eglCreateContext()"); return context; } EGLSurface createEGLSurface (EglTestContext& testCtx, EGLDisplay display, EGLConfig eglConfig, const TestConfig& config) { const Library& egl = testCtx.getLibrary(); const EGLint attribList[] = { EGL_WIDTH, config.surfaceWidth, EGL_HEIGHT, config.surfaceHeight, EGL_NONE }; EGLSurface surface = egl.createPbufferSurface(display, eglConfig, attribList); EGLU_CHECK_MSG(egl, "eglCreatePbufferSurface()"); return surface; } } // anonymous TestContext::TestContext (EglTestContext& testCtx, EGLDisplay eglDisplay, EGLConfig eglConfig, const TestConfig& config, bool share, TestContext* parent) : m_parent (parent) , m_testCtx (testCtx) , m_config (config) , m_eglDisplay (eglDisplay) , m_eglContext (EGL_NO_CONTEXT) , m_eglSurface (EGL_NO_SURFACE) , m_coordBuffer (0) , m_indexBuffer (0) , m_texture (0) , m_program (0) , m_eglImage (EGL_NO_IMAGE_KHR) { const Library& egl = m_testCtx.getLibrary(); if (m_config.textureType == TestConfig::TEXTURETYPE_IMAGE || m_config.textureType == TestConfig::TEXTURETYPE_SHARED_IMAGE || m_config.textureType == TestConfig::TEXTURETYPE_SHARED_IMAGE_TEXTURE) { const vector<string> extensions = eglu::getDisplayExtensions(egl, m_eglDisplay); if (!de::contains(extensions.begin(), extensions.end(), "EGL_KHR_image_base") || !de::contains(extensions.begin(), extensions.end(), "EGL_KHR_gl_texture_2D_image")) TCU_THROW(NotSupportedError, "EGL_KHR_image_base extensions not supported"); } m_eglContext = createEGLContext(m_testCtx, m_eglDisplay, eglConfig, (share && parent ? parent->getEGLContext() : EGL_NO_CONTEXT)); m_eglSurface = createEGLSurface(m_testCtx, m_eglDisplay, eglConfig, config); EGLU_CHECK_CALL(egl, makeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext)); { const char* reqExts[] = { "GL_OES_EGL_image" }; m_testCtx.initGLFunctions(&m_gl, glu::ApiType::es(2,0), DE_LENGTH_OF_ARRAY(reqExts), reqExts); } if (m_config.textureType == TestConfig::TEXTURETYPE_IMAGE || m_config.textureType == TestConfig::TEXTURETYPE_SHARED_IMAGE || m_config.textureType == TestConfig::TEXTURETYPE_SHARED_IMAGE_TEXTURE) { vector<string> glExts = de::splitString((const char*)m_gl.getString(GL_EXTENSIONS), ' '); if (!de::contains(glExts.begin(), glExts.end(), "GL_OES_EGL_image")) TCU_THROW(NotSupportedError, "GL_OES_EGL_image extensions not supported"); TCU_CHECK(m_gl.eglImageTargetTexture2DOES); } if (m_config.useCoordBuffer && (!m_config.sharedCoordBuffer || !parent)) m_coordBuffer = createCoordBuffer(m_gl, m_config); else if (m_config.useCoordBuffer && m_config.sharedCoordBuffer) m_coordBuffer = parent->getCoordBuffer(); else createCoordData(m_coordData, m_config); if (m_config.useIndexBuffer && (!m_config.sharedIndexBuffer || !parent)) m_indexBuffer = createIndexBuffer(m_gl, m_config); else if (m_config.useIndexBuffer && m_config.sharedIndexBuffer) m_indexBuffer = parent->getIndexBuffer(); else if (m_config.useIndices) createIndexData(m_indexData, m_config); if (m_config.useTexture) { if (m_config.textureType == TestConfig::TEXTURETYPE_TEXTURE) m_texture = createTexture(m_gl, m_config); else if (m_config.textureType == TestConfig::TEXTURETYPE_SHARED_TEXTURE) { if (parent) m_texture = parent->getTexture(); else m_texture = createTexture(m_gl, m_config); } else if (m_config.textureType == TestConfig::TEXTURETYPE_IMAGE) { m_eglImage = createEGLImage(); m_texture = createTextureFromImage(m_eglImage); } else if (m_config.textureType == TestConfig::TEXTURETYPE_SHARED_IMAGE) { if (parent) m_eglImage = parent->getEGLImage(); else m_eglImage = createEGLImage(); m_texture = createTextureFromImage(m_eglImage); } else if (m_config.textureType == TestConfig::TEXTURETYPE_SHARED_IMAGE_TEXTURE) { if (parent) m_texture = parent->getTexture(); else { m_eglImage = createEGLImage(); m_texture = createTextureFromImage(m_eglImage); } } } if (!m_config.sharedProgram || !parent) m_program = createProgram(m_gl, m_config); else if (m_config.sharedProgram) m_program = parent->getProgram(); m_coordLoc = m_gl.getAttribLocation(m_program, "a_coord"); if (m_config.useTexture) m_textureLoc = m_gl.getUniformLocation(m_program, "u_sampler"); EGLU_CHECK_CALL(egl, makeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)); } EGLImageKHR TestContext::createEGLImage (void) { GLuint sourceTexture = createTexture(m_gl, m_config); try { const Library& egl = m_testCtx.getLibrary(); const EGLint attribList[] = { EGL_GL_TEXTURE_LEVEL_KHR, 0, EGL_NONE }; EGLImageKHR image = egl.createImageKHR(m_eglDisplay, m_eglContext, EGL_GL_TEXTURE_2D_KHR, (EGLClientBuffer)(deUintptr)sourceTexture, attribList); EGLU_CHECK_MSG(egl, "eglCreateImageKHR()"); m_gl.deleteTextures(1, &sourceTexture); GLU_EXPECT_NO_ERROR(m_gl.getError(), "eglCreateImageKHR()"); return image; } catch (...) { m_gl.deleteTextures(1, &sourceTexture); throw; } } GLuint TestContext::createTextureFromImage (EGLImageKHR image) { GLuint texture = 0; try { m_gl.genTextures(1, &texture); m_gl.bindTexture(GL_TEXTURE_2D, texture); m_gl.eglImageTargetTexture2DOES(GL_TEXTURE_2D, image); m_gl.bindTexture(GL_TEXTURE_2D, 0); GLU_EXPECT_NO_ERROR(m_gl.getError(), "Creating texture from image"); return texture; } catch (...) { m_gl.deleteTextures(1, &texture); throw; } } TestContext::~TestContext (void) { const Library& egl = m_testCtx.getLibrary(); EGLU_CHECK_CALL(egl, makeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext)); if (m_parent == DE_NULL && m_eglImage) EGLU_CHECK_CALL(egl, destroyImageKHR(m_eglDisplay, m_eglImage)); EGLU_CHECK_CALL(egl, makeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)); EGLU_CHECK_CALL(egl, destroyContext(m_eglDisplay, m_eglContext)); EGLU_CHECK_CALL(egl, destroySurface(m_eglDisplay, m_eglSurface)); } void TestContext::render (void) { const Library& egl = m_testCtx.getLibrary(); egl.makeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext); for (int frameNdx = 0; frameNdx < m_config.frameCount; frameNdx++) { m_gl.clearColor(0.75f, 0.6f, 0.5f, 1.0f); m_gl.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); for (int callNdx = 0; callNdx < m_config.drawCallCount; callNdx++) { m_gl.useProgram(m_program); m_gl.enableVertexAttribArray(m_coordLoc); if (m_config.useCoordBuffer) { m_gl.bindBuffer(GL_ARRAY_BUFFER, m_coordBuffer); m_gl.vertexAttribPointer(m_coordLoc, 2, GL_FLOAT, GL_FALSE, 0, 0); m_gl.bindBuffer(GL_ARRAY_BUFFER, 0); } else m_gl.vertexAttribPointer(m_coordLoc, 2, GL_FLOAT, GL_FALSE, 0, &(m_coordData[0])); if (m_config.useTexture) { m_gl.bindTexture(GL_TEXTURE_2D, m_texture); m_gl.uniform1i(m_textureLoc, 0); } if (m_config.useIndices) { if (m_config.useIndexBuffer) { m_gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_indexBuffer); m_gl.drawElements(GL_TRIANGLES, m_config.triangleCount, GL_UNSIGNED_SHORT, 0); } else m_gl.drawElements(GL_TRIANGLES, m_config.triangleCount, GL_UNSIGNED_SHORT, &(m_indexData[0])); } else m_gl.drawArrays(GL_TRIANGLES, 0, m_config.triangleCount); if (m_config.useTexture) m_gl.bindTexture(GL_TEXTURE_2D, 0); m_gl.disableVertexAttribArray(m_coordLoc); m_gl.useProgram(0); } egl.swapBuffers(m_eglDisplay, m_eglSurface); } m_gl.finish(); GLU_EXPECT_NO_ERROR(m_gl.getError(), "glFinish()"); EGLU_CHECK_CALL(egl, makeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)); } class TestThread : de::Thread { public: TestThread (const vector<TestContext*> contexts); ~TestThread (void); void start (void); void join (void); void log (TestLog& log); bool resultOk (void) { return m_isOk; } private: vector<TestContext*> m_contexts; bool m_isOk; string m_errorString; deUint64 m_beginTimeUs; deUint64 m_endTimeUs; deUint64 m_joinBeginUs; deUint64 m_joinEndUs; deUint64 m_startBeginUs; deUint64 m_startEndUs; virtual void run (void); TestThread& operator= (const TestThread&); TestThread (const TestThread&); }; TestThread::TestThread (const vector<TestContext*> contexts) : m_contexts (contexts) , m_isOk (false) , m_errorString ("") , m_beginTimeUs (0) , m_endTimeUs (0) , m_joinBeginUs (0) , m_joinEndUs (0) , m_startBeginUs (0) , m_startEndUs (0) { } TestThread::~TestThread (void) { m_contexts.clear(); } void TestThread::log (TestLog& testLog) { if (!m_isOk) testLog << TestLog::Message << "Thread failed: " << m_errorString << TestLog::EndMessage; } void TestThread::start (void) { m_startBeginUs = deGetMicroseconds(); de::Thread::start(); m_startEndUs = deGetMicroseconds(); } void TestThread::join (void) { m_joinBeginUs = deGetMicroseconds(); de::Thread::join(); m_joinEndUs = deGetMicroseconds(); } void TestThread::run (void) { try { m_beginTimeUs = deGetMicroseconds(); for (int contextNdx = 0; contextNdx < (int)m_contexts.size(); contextNdx++) m_contexts[contextNdx]->render(); m_isOk = true; m_endTimeUs = deGetMicroseconds(); } catch (const std::runtime_error& error) { m_isOk = false; m_errorString = error.what(); } catch (...) { m_isOk = false; m_errorString = "Got unknown exception"; } } class SharedRenderingPerfCase : public TestCase { public: SharedRenderingPerfCase (EglTestContext& eglTestCtx, const TestConfig& config, const char* name, const char* description); ~SharedRenderingPerfCase (void); void init (void); void deinit (void); IterateResult iterate (void); private: TestConfig m_config; const int m_iterationCount; EGLDisplay m_display; vector<TestContext*> m_contexts; vector<deUint64> m_results; SharedRenderingPerfCase& operator= (const SharedRenderingPerfCase&); SharedRenderingPerfCase (const SharedRenderingPerfCase&); }; SharedRenderingPerfCase::SharedRenderingPerfCase (EglTestContext& eglTestCtx, const TestConfig& config, const char* name, const char* description) : TestCase (eglTestCtx, tcu::NODETYPE_PERFORMANCE, name, description) , m_config (config) , m_iterationCount (30) , m_display (EGL_NO_DISPLAY) { } SharedRenderingPerfCase::~SharedRenderingPerfCase (void) { deinit(); } void SharedRenderingPerfCase::init (void) { m_display = eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay()); { const Library& egl = m_eglTestCtx.getLibrary(); const EGLint attribList[] = { EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_NONE }; EGLConfig eglConfig = eglu::chooseSingleConfig(egl, m_display, attribList); // Create contexts and resources for (int threadNdx = 0; threadNdx < m_config.threadCount * m_config.perThreadContextCount; threadNdx++) m_contexts.push_back(new TestContext(m_eglTestCtx, m_display, eglConfig, m_config, m_config.sharedContexts, (threadNdx == 0 ? DE_NULL : m_contexts[threadNdx-1]))); } } void SharedRenderingPerfCase::deinit (void) { // Destroy resources and contexts for (int threadNdx = 0; threadNdx < (int)m_contexts.size(); threadNdx++) { delete m_contexts[threadNdx]; m_contexts[threadNdx] = DE_NULL; } m_contexts.clear(); m_results.clear(); if (m_display != EGL_NO_DISPLAY) { m_eglTestCtx.getLibrary().terminate(m_display); m_display = EGL_NO_DISPLAY; } } namespace { void createThreads (vector<TestThread*>& threads, int threadCount, int perThreadContextCount, vector<TestContext*>& contexts) { DE_ASSERT(threadCount * perThreadContextCount == (int)contexts.size()); DE_ASSERT(threads.empty()); vector<TestContext*> threadContexts; for (int threadNdx = 0; threadNdx < threadCount; threadNdx++) { for (int contextNdx = 0; contextNdx < perThreadContextCount; contextNdx++) threadContexts.push_back(contexts[threadNdx * perThreadContextCount + contextNdx]); threads.push_back(new TestThread(threadContexts)); threadContexts.clear(); } } void destroyThreads (vector<TestThread*>& threads) { for (int threadNdx = 0; threadNdx < (int)threads.size(); threadNdx++) { delete threads[threadNdx]; threads[threadNdx] = DE_NULL; } threads.clear(); } void startThreads (vector<TestThread*>& threads) { for (int threadNdx = 0; threadNdx < (int)threads.size(); threadNdx++) threads[threadNdx]->start(); } void joinThreads (vector<TestThread*>& threads) { for (int threadNdx = 0; threadNdx < (int)threads.size(); threadNdx++) threads[threadNdx]->join(); } bool threadResultsOk (const vector<TestThread*>& threads) { for (int threadNdx = 0; threadNdx < (int)threads.size(); threadNdx++) { if (!threads[threadNdx]->resultOk()) return false; } return true; } void logAndSetResults (tcu::TestContext& testCtx, const vector<deUint64>& r) { TestLog& log = testCtx.getLog(); vector<deUint64> resultsUs = r; deUint64 sum = 0; deUint64 average; deUint64 median; double deviation; log << TestLog::SampleList("Result", "Result") << TestLog::SampleInfo << TestLog::ValueInfo("Time", "Time", "us", QP_SAMPLE_VALUE_TAG_RESPONSE) << TestLog::EndSampleInfo; for (int resultNdx = 0; resultNdx < (int)resultsUs.size(); resultNdx++) log << TestLog::Sample << deInt64(resultsUs[resultNdx]) << TestLog::EndSample; log << TestLog::EndSampleList; std::sort(resultsUs.begin(), resultsUs.end()); for (int resultNdx = 0; resultNdx < (int)resultsUs.size(); resultNdx++) sum += resultsUs[resultNdx]; average = sum / resultsUs.size(); median = resultsUs[resultsUs.size() / 2]; deviation = 0.0; for (int resultNdx = 0; resultNdx < (int)resultsUs.size(); resultNdx++) deviation += (double)((resultsUs[resultNdx] - average) * (resultsUs[resultNdx] - average)); deviation = std::sqrt(deviation/(double)resultsUs.size()); { tcu::ScopedLogSection section(log, "Statistics from results", "Statistics from results"); log << TestLog::Message << "Average: " << ((double)average/1000.0) << "ms\n" << "Standard deviation: " << ((double)deviation/1000.0) << "ms\n" << "Standard error of mean: " << (((double)deviation/std::sqrt((double)resultsUs.size()))/1000.0) << "ms\n" << "Median: " << ((double)median/1000.0) << "ms\n" << TestLog::EndMessage; } testCtx.setTestResult(QP_TEST_RESULT_PASS, de::floatToString((float)((double)average/1000.0), 2).c_str()); } void logTestConfig (TestLog& log, const TestConfig& config) { tcu::ScopedLogSection threadSection(log, "Test info", "Test information"); log << TestLog::Message << "Total triangles rendered: : " << config.triangleCount * config.drawCallCount * config.frameCount * config.perThreadContextCount * config.threadCount << TestLog::EndMessage; log << TestLog::Message << "Number of threads: " << config.threadCount << TestLog::EndMessage; log << TestLog::Message << "Number of contexts used to render with each thread: " << config.perThreadContextCount << TestLog::EndMessage; log << TestLog::Message << "Number of frames rendered with each context: " << config.frameCount << TestLog::EndMessage; log << TestLog::Message << "Number of draw calls performed by each frame: " << config.drawCallCount << TestLog::EndMessage; log << TestLog::Message << "Number of triangles rendered by each draw call: " << config.triangleCount << TestLog::EndMessage; if (config.sharedContexts) log << TestLog::Message << "Shared contexts." << TestLog::EndMessage; else log << TestLog::Message << "No shared contexts." << TestLog::EndMessage; if (config.useCoordBuffer) log << TestLog::Message << (config.sharedCoordBuffer ? "Shared " : "") << "Coordinate buffer" << TestLog::EndMessage; else log << TestLog::Message << "Coordinates from pointer" << TestLog::EndMessage; if (config.useIndices) log << TestLog::Message << "Using glDrawElements with indices from " << (config.sharedIndexBuffer ? "shared " : "") << (config.useIndexBuffer ? "buffer." : "pointer.") << TestLog::EndMessage; if (config.useTexture) { if (config.textureType == TestConfig::TEXTURETYPE_TEXTURE) log << TestLog::Message << "Use texture." << TestLog::EndMessage; else if (config.textureType == TestConfig::TEXTURETYPE_SHARED_TEXTURE) log << TestLog::Message << "Use shared texture." << TestLog::EndMessage; else if (config.textureType == TestConfig::TEXTURETYPE_IMAGE) log << TestLog::Message << "Use texture created from EGLImage." << TestLog::EndMessage; else if (config.textureType == TestConfig::TEXTURETYPE_SHARED_IMAGE) log << TestLog::Message << "Use texture created from shared EGLImage." << TestLog::EndMessage; else if (config.textureType == TestConfig::TEXTURETYPE_SHARED_IMAGE_TEXTURE) log << TestLog::Message << "Use shared texture created from EGLImage." << TestLog::EndMessage; else DE_ASSERT(false); log << TestLog::Message << "Texture size: " << config.textureWidth << "x" << config.textureHeight << TestLog::EndMessage; } if (config.sharedProgram) log << TestLog::Message << "Shared program." << TestLog::EndMessage; log << TestLog::Message << "Surface size: " << config.surfaceWidth << "x" << config.surfaceHeight << TestLog::EndMessage; } } // anonymous TestCase::IterateResult SharedRenderingPerfCase::iterate (void) { deUint64 beginTimeUs; deUint64 endTimeUs; vector<TestThread*> threads; if (m_results.empty()) logTestConfig(m_testCtx.getLog(), m_config); createThreads(threads, m_config.threadCount, m_config.perThreadContextCount, m_contexts); beginTimeUs = deGetMicroseconds(); startThreads(threads); joinThreads(threads); endTimeUs = deGetMicroseconds(); if (!threadResultsOk(threads)) { m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); return STOP; } destroyThreads(threads); m_results.push_back(endTimeUs - beginTimeUs); if ((int)m_results.size() == m_iterationCount) { logAndSetResults(m_testCtx, m_results); return STOP; } else return CONTINUE; } string createTestName(int threads, int perThreadContextCount) { std::ostringstream stream; stream << threads << (threads == 1 ? "_thread_" : "_threads_") << perThreadContextCount << (perThreadContextCount == 1 ? "_context" : "_contexts"); return stream.str(); } } // anonymous GLES2SharedRenderingPerfTests::GLES2SharedRenderingPerfTests (EglTestContext& eglTestCtx) : TestCaseGroup(eglTestCtx, "gles2_shared_render", "") { } void GLES2SharedRenderingPerfTests::init (void) { TestConfig basicConfig; basicConfig.threadCount = 1; basicConfig.perThreadContextCount = 1; basicConfig.sharedContexts = true; basicConfig.frameCount = 10; basicConfig.drawCallCount = 10; basicConfig.triangleCount = 100; basicConfig.useCoordBuffer = true; basicConfig.sharedCoordBuffer = false; basicConfig.useIndices = true; basicConfig.useIndexBuffer = true; basicConfig.sharedIndexBuffer = false; basicConfig.useTexture = true; basicConfig.textureType = TestConfig::TEXTURETYPE_TEXTURE; basicConfig.sharedProgram = false; basicConfig.textureWidth = 128; basicConfig.textureHeight = 128; basicConfig.surfaceWidth = 256; basicConfig.surfaceHeight = 256; const int threadCounts[] = { 1, 2, 4 }; const int perThreadContextCounts[] = { 1, 2, 4 }; // Add no sharing tests { TestCaseGroup* sharedNoneGroup = new TestCaseGroup(m_eglTestCtx, "no_shared_context", "Tests without sharing contexts."); for (int threadCountNdx = 0; threadCountNdx < DE_LENGTH_OF_ARRAY(threadCounts); threadCountNdx++) { int threadCount = threadCounts[threadCountNdx]; for (int contextCountNdx = 0; contextCountNdx < DE_LENGTH_OF_ARRAY(perThreadContextCounts); contextCountNdx++) { int contextCount = perThreadContextCounts[contextCountNdx]; if (threadCount * contextCount != 4 && threadCount * contextCount != 1) continue; TestConfig config = basicConfig; config.threadCount = threadCount; config.perThreadContextCount = contextCount; config.sharedContexts = false; { TestConfig smallConfig = config; smallConfig.triangleCount = 1; smallConfig.drawCallCount = 1000; smallConfig.frameCount = 10; if (threadCount * contextCount == 1) smallConfig.frameCount *= 4; sharedNoneGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, smallConfig, (createTestName(threadCount, contextCount) + "_small_call").c_str(), "")); } { TestConfig bigConfig = config; bigConfig.triangleCount = 1000; bigConfig.drawCallCount = 1; bigConfig.frameCount = 10; if (threadCount * contextCount == 1) bigConfig.frameCount *= 4; sharedNoneGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, bigConfig, (createTestName(threadCount, contextCount) + "_big_call").c_str(), "")); } } } addChild(sharedNoneGroup); } // Add no resource sharing tests { TestCaseGroup* sharedNoneGroup = new TestCaseGroup(m_eglTestCtx, "no_shared_resource", "Tests without shared resources."); for (int threadCountNdx = 0; threadCountNdx < DE_LENGTH_OF_ARRAY(threadCounts); threadCountNdx++) { int threadCount = threadCounts[threadCountNdx]; for (int contextCountNdx = 0; contextCountNdx < DE_LENGTH_OF_ARRAY(perThreadContextCounts); contextCountNdx++) { int contextCount = perThreadContextCounts[contextCountNdx]; if (threadCount * contextCount != 4 && threadCount * contextCount != 1) continue; TestConfig config = basicConfig; config.threadCount = threadCount; config.perThreadContextCount = contextCount; { TestConfig smallConfig = config; smallConfig.triangleCount = 1; smallConfig.drawCallCount = 1000; smallConfig.frameCount = 10; if (threadCount * contextCount == 1) smallConfig.frameCount *= 4; sharedNoneGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, smallConfig, (createTestName(threadCount, contextCount) + "_small_call").c_str(), "")); } { TestConfig bigConfig = config; bigConfig.triangleCount = 1000; bigConfig.drawCallCount = 1; bigConfig.frameCount = 10; if (threadCount * contextCount == 1) bigConfig.frameCount *= 4; sharedNoneGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, bigConfig, (createTestName(threadCount, contextCount) + "_big_call").c_str(), "")); } } } addChild(sharedNoneGroup); } // Add shared coord buffer tests { TestCaseGroup* sharedCoordBufferGroup = new TestCaseGroup(m_eglTestCtx, "shared_coord_buffer", "Shared coordinate bufffer"); for (int threadCountNdx = 0; threadCountNdx < DE_LENGTH_OF_ARRAY(threadCounts); threadCountNdx++) { int threadCount = threadCounts[threadCountNdx]; for (int contextCountNdx = 0; contextCountNdx < DE_LENGTH_OF_ARRAY(perThreadContextCounts); contextCountNdx++) { int contextCount = perThreadContextCounts[contextCountNdx]; if (threadCount * contextCount != 4 && threadCount * contextCount != 1) continue; TestConfig config = basicConfig; config.sharedCoordBuffer = true; config.threadCount = threadCount; config.perThreadContextCount = contextCount; { TestConfig smallConfig = config; smallConfig.triangleCount = 1; smallConfig.drawCallCount = 1000; smallConfig.frameCount = 10; if (threadCount * contextCount == 1) smallConfig.frameCount *= 4; sharedCoordBufferGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, smallConfig, (createTestName(threadCount, contextCount) + "_small_call").c_str(), "")); } { TestConfig bigConfig = config; bigConfig.triangleCount = 1000; bigConfig.drawCallCount = 1; bigConfig.frameCount = 10; if (threadCount * contextCount == 1) bigConfig.frameCount *= 4; sharedCoordBufferGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, bigConfig, (createTestName(threadCount, contextCount) + "_big_call").c_str(), "")); } } } addChild(sharedCoordBufferGroup); } // Add shared index buffer tests { TestCaseGroup* sharedIndexBufferGroup = new TestCaseGroup(m_eglTestCtx, "shared_index_buffer", "Shared index bufffer"); for (int threadCountNdx = 0; threadCountNdx < DE_LENGTH_OF_ARRAY(threadCounts); threadCountNdx++) { int threadCount = threadCounts[threadCountNdx]; for (int contextCountNdx = 0; contextCountNdx < DE_LENGTH_OF_ARRAY(perThreadContextCounts); contextCountNdx++) { int contextCount = perThreadContextCounts[contextCountNdx]; if (threadCount * contextCount != 4 && threadCount * contextCount != 1) continue; TestConfig config = basicConfig; config.sharedIndexBuffer = true; config.threadCount = threadCount; config.perThreadContextCount = contextCount; { TestConfig smallConfig = config; smallConfig.triangleCount = 1; smallConfig.drawCallCount = 1000; smallConfig.frameCount = 10; if (threadCount * contextCount == 1) smallConfig.frameCount *= 4; sharedIndexBufferGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, smallConfig, (createTestName(threadCount, contextCount) + "_small_call").c_str(), "")); } { TestConfig bigConfig = config; bigConfig.triangleCount = 1000; bigConfig.drawCallCount = 1; bigConfig.frameCount = 10; if (threadCount * contextCount == 1) bigConfig.frameCount *= 4; sharedIndexBufferGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, bigConfig, (createTestName(threadCount, contextCount) + "_big_call").c_str(), "")); } } } addChild(sharedIndexBufferGroup); } // Add shared texture tests { TestCaseGroup* sharedTextureGroup = new TestCaseGroup(m_eglTestCtx, "shared_texture", "Shared texture tests."); for (int threadCountNdx = 0; threadCountNdx < DE_LENGTH_OF_ARRAY(threadCounts); threadCountNdx++) { int threadCount = threadCounts[threadCountNdx]; for (int contextCountNdx = 0; contextCountNdx < DE_LENGTH_OF_ARRAY(perThreadContextCounts); contextCountNdx++) { int contextCount = perThreadContextCounts[contextCountNdx]; if (threadCount * contextCount != 4 && threadCount * contextCount != 1) continue; TestConfig config = basicConfig; config.textureType = TestConfig::TEXTURETYPE_SHARED_TEXTURE; config.threadCount = threadCount; config.perThreadContextCount = contextCount; { TestConfig smallConfig = config; smallConfig.triangleCount = 1; smallConfig.drawCallCount = 1000; smallConfig.frameCount = 10; if (threadCount * contextCount == 1) smallConfig.frameCount *= 4; sharedTextureGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, smallConfig, (createTestName(threadCount, contextCount) + "_small_call").c_str(), "")); } { TestConfig bigConfig = config; bigConfig.triangleCount = 1000; bigConfig.drawCallCount = 1; bigConfig.frameCount = 10; if (threadCount * contextCount == 1) bigConfig.frameCount *= 4; sharedTextureGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, bigConfig, (createTestName(threadCount, contextCount) + "_big_call").c_str(), "")); } } } addChild(sharedTextureGroup); } // Add shared program tests { TestCaseGroup* sharedProgramGroup = new TestCaseGroup(m_eglTestCtx, "shared_program", "Shared program tests."); for (int threadCountNdx = 0; threadCountNdx < DE_LENGTH_OF_ARRAY(threadCounts); threadCountNdx++) { int threadCount = threadCounts[threadCountNdx]; for (int contextCountNdx = 0; contextCountNdx < DE_LENGTH_OF_ARRAY(perThreadContextCounts); contextCountNdx++) { int contextCount = perThreadContextCounts[contextCountNdx]; if (threadCount * contextCount != 4 && threadCount * contextCount != 1) continue; TestConfig config = basicConfig; config.sharedProgram = true; config.threadCount = threadCount; config.perThreadContextCount = contextCount; { TestConfig smallConfig = config; smallConfig.triangleCount = 1; smallConfig.drawCallCount = 1000; smallConfig.frameCount = 10; if (threadCount * contextCount == 1) smallConfig.frameCount *= 4; sharedProgramGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, smallConfig, (createTestName(threadCount, contextCount) + "_small_call").c_str(), "")); } { TestConfig bigConfig = config; bigConfig.triangleCount = 1000; bigConfig.drawCallCount = 1; bigConfig.frameCount = 10; if (threadCount * contextCount == 1) bigConfig.frameCount *= 4; sharedProgramGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, bigConfig, (createTestName(threadCount, contextCount) + "_big_call").c_str(), "")); } } } addChild(sharedProgramGroup); } // Add shared all tests { TestCaseGroup* sharedallGroup = new TestCaseGroup(m_eglTestCtx, "shared_all", "Share all possible resources."); for (int threadCountNdx = 0; threadCountNdx < DE_LENGTH_OF_ARRAY(threadCounts); threadCountNdx++) { int threadCount = threadCounts[threadCountNdx]; for (int contextCountNdx = 0; contextCountNdx < DE_LENGTH_OF_ARRAY(perThreadContextCounts); contextCountNdx++) { int contextCount = perThreadContextCounts[contextCountNdx]; if (threadCount * contextCount != 4 && threadCount * contextCount != 1) continue; TestConfig config = basicConfig; config.sharedCoordBuffer = true; config.sharedIndexBuffer = true; config.sharedProgram = true; config.textureType = TestConfig::TEXTURETYPE_SHARED_TEXTURE; config.threadCount = threadCount; config.perThreadContextCount = contextCount; { TestConfig smallConfig = config; smallConfig.triangleCount = 1; smallConfig.drawCallCount = 1000; smallConfig.frameCount = 10; if (threadCount * contextCount == 1) smallConfig.frameCount *= 4; sharedallGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, smallConfig, (createTestName(threadCount, contextCount) + "_small_call").c_str(), "")); } { TestConfig bigConfig = config; bigConfig.triangleCount = 1000; bigConfig.drawCallCount = 1; bigConfig.frameCount = 10; if (threadCount * contextCount == 1) bigConfig.frameCount *= 4; sharedallGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, bigConfig, (createTestName(threadCount, contextCount) + "_big_call").c_str(), "")); } } } addChild(sharedallGroup); } // Add EGLImage tests { TestCaseGroup* sharedTextureGroup = new TestCaseGroup(m_eglTestCtx, "egl_image", "EGL image tests."); for (int threadCountNdx = 0; threadCountNdx < DE_LENGTH_OF_ARRAY(threadCounts); threadCountNdx++) { int threadCount = threadCounts[threadCountNdx]; for (int contextCountNdx = 0; contextCountNdx < DE_LENGTH_OF_ARRAY(perThreadContextCounts); contextCountNdx++) { int contextCount = perThreadContextCounts[contextCountNdx]; if (threadCount * contextCount != 4 && threadCount * contextCount != 1) continue; TestConfig config = basicConfig; config.textureType = TestConfig::TEXTURETYPE_IMAGE; config.threadCount = threadCount; config.perThreadContextCount = contextCount; config.sharedContexts = false; { TestConfig smallConfig = config; smallConfig.triangleCount = 1; smallConfig.drawCallCount = 1000; smallConfig.frameCount = 10; if (threadCount * contextCount == 1) smallConfig.frameCount *= 4; sharedTextureGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, smallConfig, (createTestName(threadCount, contextCount) + "_small_call").c_str(), "")); } { TestConfig bigConfig = config; bigConfig.triangleCount = 1000; bigConfig.drawCallCount = 1; bigConfig.frameCount = 10; if (threadCount * contextCount == 1) bigConfig.frameCount *= 4; sharedTextureGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, bigConfig, (createTestName(threadCount, contextCount) + "_big_call").c_str(), "")); } } } addChild(sharedTextureGroup); } // Add shared EGLImage tests { TestCaseGroup* sharedTextureGroup = new TestCaseGroup(m_eglTestCtx, "shared_egl_image", "Shared EGLImage tests."); for (int threadCountNdx = 0; threadCountNdx < DE_LENGTH_OF_ARRAY(threadCounts); threadCountNdx++) { int threadCount = threadCounts[threadCountNdx]; for (int contextCountNdx = 0; contextCountNdx < DE_LENGTH_OF_ARRAY(perThreadContextCounts); contextCountNdx++) { int contextCount = perThreadContextCounts[contextCountNdx]; if (threadCount * contextCount != 4 && threadCount * contextCount != 1) continue; TestConfig config = basicConfig; config.textureType = TestConfig::TEXTURETYPE_SHARED_IMAGE; config.threadCount = threadCount; config.perThreadContextCount = contextCount; config.sharedContexts = false; { TestConfig smallConfig = config; smallConfig.triangleCount = 1; smallConfig.drawCallCount = 1000; smallConfig.frameCount = 10; if (threadCount * contextCount == 1) smallConfig.frameCount *= 4; sharedTextureGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, smallConfig, (createTestName(threadCount, contextCount) + "_small_call").c_str(), "")); } { TestConfig bigConfig = config; bigConfig.triangleCount = 1000; bigConfig.drawCallCount = 1; bigConfig.frameCount = 10; if (threadCount * contextCount == 1) bigConfig.frameCount *= 4; sharedTextureGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, bigConfig, (createTestName(threadCount, contextCount) + "_big_call").c_str(), "")); } } } addChild(sharedTextureGroup); } // Shared EGLImage texture test { TestCaseGroup* sharedTextureGroup = new TestCaseGroup(m_eglTestCtx, "shared_egl_image_texture", "Shared EGLImage texture tests."); for (int threadCountNdx = 0; threadCountNdx < DE_LENGTH_OF_ARRAY(threadCounts); threadCountNdx++) { int threadCount = threadCounts[threadCountNdx]; for (int contextCountNdx = 0; contextCountNdx < DE_LENGTH_OF_ARRAY(perThreadContextCounts); contextCountNdx++) { int contextCount = perThreadContextCounts[contextCountNdx]; if (threadCount * contextCount != 4 && threadCount * contextCount != 1) continue; TestConfig config = basicConfig; config.textureType = TestConfig::TEXTURETYPE_SHARED_IMAGE_TEXTURE; config.threadCount = threadCount; config.perThreadContextCount = contextCount; { TestConfig smallConfig = config; smallConfig.triangleCount = 1; smallConfig.drawCallCount = 1000; smallConfig.frameCount = 10; if (threadCount * contextCount == 1) smallConfig.frameCount *= 4; sharedTextureGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, smallConfig, (createTestName(threadCount, contextCount) + "_small_call").c_str(), "")); } { TestConfig bigConfig = config; bigConfig.triangleCount = 1000; bigConfig.drawCallCount = 1; bigConfig.frameCount = 10; if (threadCount * contextCount == 1) bigConfig.frameCount *= 4; sharedTextureGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, bigConfig, (createTestName(threadCount, contextCount) + "_big_call").c_str(), "")); } } } addChild(sharedTextureGroup); } } } // egl } // deqp