/*-------------------------------------------------------------------------
* 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);
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::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