| /*------------------------------------------------------------------------- |
| * 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 std::string; |
| using std::vector; |
| using tcu::TestLog; |
| |
| 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<uint16_t> 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<uint16_t> &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<uint16_t> 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(uint16_t)), &(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<uint8_t> &data, const TestConfig &config) |
| { |
| for (int x = 0; x < config.textureWidth; x++) |
| { |
| for (int y = 0; y < config.textureHeight; y++) |
| { |
| data.push_back((uint8_t)((255 * x) / 255)); |
| data.push_back((uint8_t)((255 * y) / 255)); |
| data.push_back((uint8_t)((255 * x * y) / (255 * 255))); |
| data.push_back(255); |
| } |
| } |
| } |
| |
| GLuint createTexture(const glw::Functions &gl, const TestConfig &config) |
| { |
| GLuint texture; |
| vector<uint8_t> 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, nullptr); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource()"); |
| gl.shaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr); |
| 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, nullptr); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource()"); |
| gl.shaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr); |
| 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, nullptr); |
| 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; |
| } |
| |
| } // namespace |
| |
| 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)(uintptr_t)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 == nullptr && 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, const Library &egl); |
| ~TestThread(void); |
| |
| void start(void); |
| void join(void); |
| |
| bool resultOk(void) |
| { |
| return m_isOk; |
| } |
| |
| private: |
| vector<TestContext *> m_contexts; |
| const Library &m_egl; |
| bool m_isOk; |
| string m_errorString; |
| |
| uint64_t m_beginTimeUs; |
| uint64_t m_endTimeUs; |
| |
| uint64_t m_joinBeginUs; |
| uint64_t m_joinEndUs; |
| |
| uint64_t m_startBeginUs; |
| uint64_t m_startEndUs; |
| |
| virtual void run(void); |
| |
| TestThread &operator=(const TestThread &); |
| TestThread(const TestThread &); |
| }; |
| |
| TestThread::TestThread(const vector<TestContext *> contexts, const Library &egl) |
| : m_contexts(contexts) |
| , m_egl(egl) |
| , 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::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"; |
| } |
| |
| m_egl.releaseThread(); |
| } |
| |
| 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<uint64_t> 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 ? nullptr : 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] = nullptr; |
| } |
| |
| 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, const Library &egl) |
| { |
| 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, egl)); |
| |
| threadContexts.clear(); |
| } |
| } |
| |
| void destroyThreads(vector<TestThread *> &threads) |
| { |
| for (int threadNdx = 0; threadNdx < (int)threads.size(); threadNdx++) |
| { |
| delete threads[threadNdx]; |
| threads[threadNdx] = nullptr; |
| } |
| |
| 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<uint64_t> &r) |
| { |
| TestLog &log = testCtx.getLog(); |
| vector<uint64_t> resultsUs = r; |
| uint64_t sum = 0; |
| uint64_t average; |
| uint64_t 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 << int64_t(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; |
| } |
| |
| } // namespace |
| |
| TestCase::IterateResult SharedRenderingPerfCase::iterate(void) |
| { |
| uint64_t beginTimeUs; |
| uint64_t endTimeUs; |
| vector<TestThread *> threads; |
| |
| if (m_results.empty()) |
| logTestConfig(m_testCtx.getLog(), m_config); |
| |
| createThreads(threads, m_config.threadCount, m_config.perThreadContextCount, m_contexts, m_eglTestCtx.getLibrary()); |
| |
| 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(); |
| } |
| |
| } // namespace |
| |
| 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); |
| } |
| } |
| |
| } // namespace egl |
| } // namespace deqp |