blob: 1dd5609a53cdea39cbf7b2581674ec413c431352 [file] [log] [blame] [edit]
/*-------------------------------------------------------------------------
* 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 eglMakeCurrent performance tests.
*//*--------------------------------------------------------------------*/
#include "teglMakeCurrentPerfTests.hpp"
#include "egluNativeWindow.hpp"
#include "egluNativePixmap.hpp"
#include "egluUtil.hpp"
#include "eglwLibrary.hpp"
#include "eglwEnums.hpp"
#include "tcuTestLog.hpp"
#include "deRandom.hpp"
#include "deStringUtil.hpp"
#include "deClock.h"
#include "deString.h"
#include <algorithm>
#include <cmath>
#include <limits>
#include <sstream>
#include <string>
#include <vector>
using std::ostringstream;
using std::string;
using std::vector;
using tcu::TestLog;
using namespace eglw;
namespace deqp
{
namespace egl
{
class MakeCurrentPerfCase : public TestCase
{
public:
enum SurfaceType
{
SURFACETYPE_PBUFFER = (1 << 0),
SURFACETYPE_WINDOW = (1 << 1),
SURFACETYPE_PIXMAP = (1 << 2)
};
struct Spec
{
SurfaceType surfaceTypes;
int contextCount;
int surfaceCount;
bool release;
int iterationCount;
int sampleCount;
string toName(void) const;
string toDescription(void) const;
};
MakeCurrentPerfCase(EglTestContext &eglTestCtx, const Spec &spec, const char *name, const char *description);
~MakeCurrentPerfCase(void);
void init(void);
void deinit(void);
IterateResult iterate(void);
private:
Spec m_spec;
de::Random m_rnd;
EGLDisplay m_display;
EGLConfig m_config;
vector<EGLContext> m_contexts;
vector<EGLSurface> m_surfaces;
vector<eglu::NativeWindow *> m_windows;
vector<eglu::NativePixmap *> m_pixmaps;
vector<uint64_t> m_samples;
void chooseConfig(void);
void createSurfaces(void);
void createContexts(void);
void destroySurfaces(void);
void destroyContexts(void);
void createPBuffer(void);
void createWindow(void);
void createPixmap(void);
void logTestInfo(void);
void logResults(void);
// Disabled
MakeCurrentPerfCase(const MakeCurrentPerfCase &);
MakeCurrentPerfCase &operator=(const MakeCurrentPerfCase &);
};
string MakeCurrentPerfCase::Spec::toName(void) const
{
ostringstream name;
name << "context";
if (contextCount > 1)
name << "s_" << contextCount;
if ((surfaceTypes & SURFACETYPE_WINDOW) != 0)
name << "_window" << (surfaceCount > 1 ? "s" : "");
if ((surfaceTypes & SURFACETYPE_PIXMAP) != 0)
name << "_pixmap" << (surfaceCount > 1 ? "s" : "");
if ((surfaceTypes & SURFACETYPE_PBUFFER) != 0)
name << "_pbuffer" << (surfaceCount > 1 ? "s" : "");
if (surfaceCount > 1)
name << "_" << surfaceCount;
if (release)
name << "_release";
return name.str();
}
string MakeCurrentPerfCase::Spec::toDescription(void) const
{
// \todo [mika] Generate descrpition
return toName();
}
MakeCurrentPerfCase::MakeCurrentPerfCase(EglTestContext &eglTestCtx, const Spec &spec, const char *name,
const char *description)
: TestCase(eglTestCtx, tcu::NODETYPE_PERFORMANCE, name, description)
, m_spec(spec)
, m_rnd(deStringHash(name))
, m_display(EGL_NO_DISPLAY)
, m_config(nullptr)
{
}
MakeCurrentPerfCase::~MakeCurrentPerfCase(void)
{
deinit();
}
void MakeCurrentPerfCase::init(void)
{
m_display = eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay());
chooseConfig();
createContexts();
createSurfaces();
}
void MakeCurrentPerfCase::deinit(void)
{
destroyContexts();
destroySurfaces();
if (m_display != EGL_NO_DISPLAY)
{
m_eglTestCtx.getLibrary().terminate(m_display);
m_display = EGL_NO_DISPLAY;
}
}
void MakeCurrentPerfCase::chooseConfig(void)
{
const EGLint surfaceBits = ((m_spec.surfaceTypes & SURFACETYPE_WINDOW) != 0 ? EGL_WINDOW_BIT : 0) |
((m_spec.surfaceTypes & SURFACETYPE_PIXMAP) != 0 ? EGL_PIXMAP_BIT : 0) |
((m_spec.surfaceTypes & SURFACETYPE_PBUFFER) != 0 ? EGL_PBUFFER_BIT : 0);
const EGLint attribList[] = {EGL_SURFACE_TYPE, surfaceBits, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_NONE};
const Library &egl = m_eglTestCtx.getLibrary();
EGLint configCount = 0;
EGLU_CHECK_CALL(egl, chooseConfig(m_display, attribList, &m_config, 1, &configCount));
if (configCount <= 0)
throw tcu::NotSupportedError("No compatible configs found");
}
void MakeCurrentPerfCase::createSurfaces(void)
{
vector<SurfaceType> types;
if ((m_spec.surfaceTypes & SURFACETYPE_WINDOW) != 0)
types.push_back(SURFACETYPE_WINDOW);
if ((m_spec.surfaceTypes & SURFACETYPE_PIXMAP) != 0)
types.push_back(SURFACETYPE_PIXMAP);
if ((m_spec.surfaceTypes & SURFACETYPE_PBUFFER) != 0)
types.push_back(SURFACETYPE_PBUFFER);
DE_ASSERT((int)types.size() <= m_spec.surfaceCount);
// Create surfaces
for (int surfaceNdx = 0; surfaceNdx < m_spec.surfaceCount; surfaceNdx++)
{
SurfaceType type = types[surfaceNdx % types.size()];
switch (type)
{
case SURFACETYPE_PBUFFER:
createPBuffer();
break;
case SURFACETYPE_WINDOW:
createWindow();
break;
case SURFACETYPE_PIXMAP:
createPixmap();
break;
default:
DE_ASSERT(false);
}
}
}
void MakeCurrentPerfCase::createPBuffer(void)
{
const Library &egl = m_eglTestCtx.getLibrary();
const EGLint width = 256;
const EGLint height = 256;
const EGLint attribList[] = {EGL_WIDTH, width, EGL_HEIGHT, height, EGL_NONE};
EGLSurface surface = egl.createPbufferSurface(m_display, m_config, attribList);
EGLU_CHECK_MSG(egl, "eglCreatePbufferSurface()");
m_surfaces.push_back(surface);
}
void MakeCurrentPerfCase::createWindow(void)
{
const Library &egl = m_eglTestCtx.getLibrary();
const EGLint width = 256;
const EGLint height = 256;
const eglu::NativeWindowFactory &windowFactory =
eglu::selectNativeWindowFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine());
eglu::NativeWindow *window = nullptr;
EGLSurface surface = EGL_NO_SURFACE;
try
{
window = windowFactory.createWindow(
&m_eglTestCtx.getNativeDisplay(), m_display, m_config, nullptr,
eglu::WindowParams(width, height,
eglu::parseWindowVisibility(m_eglTestCtx.getTestContext().getCommandLine())));
surface = eglu::createWindowSurface(m_eglTestCtx.getNativeDisplay(), *window, m_display, m_config, nullptr);
}
catch (...)
{
if (surface != EGL_NO_SURFACE)
egl.destroySurface(m_display, surface);
delete window;
throw;
}
m_windows.push_back(window);
m_surfaces.push_back(surface);
}
void MakeCurrentPerfCase::createPixmap(void)
{
const Library &egl = m_eglTestCtx.getLibrary();
const EGLint width = 256;
const EGLint height = 256;
const eglu::NativePixmapFactory &pixmapFactory =
eglu::selectNativePixmapFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine());
eglu::NativePixmap *pixmap = nullptr;
EGLSurface surface = EGL_NO_SURFACE;
try
{
pixmap =
pixmapFactory.createPixmap(&m_eglTestCtx.getNativeDisplay(), m_display, m_config, nullptr, width, height);
surface = eglu::createPixmapSurface(m_eglTestCtx.getNativeDisplay(), *pixmap, m_display, m_config, nullptr);
}
catch (...)
{
if (surface != EGL_NO_SURFACE)
egl.destroySurface(m_display, surface);
delete pixmap;
throw;
}
m_pixmaps.push_back(pixmap);
m_surfaces.push_back(surface);
}
void MakeCurrentPerfCase::destroySurfaces(void)
{
const Library &egl = m_eglTestCtx.getLibrary();
if (m_surfaces.size() > 0)
{
EGLDisplay display = m_display;
// Destroy surfaces
for (vector<EGLSurface>::iterator iter = m_surfaces.begin(); iter != m_surfaces.end(); ++iter)
{
if (*iter != EGL_NO_SURFACE)
EGLU_CHECK_CALL(egl, destroySurface(display, *iter));
*iter = EGL_NO_SURFACE;
}
m_surfaces.clear();
// Destroy pixmaps
for (vector<eglu::NativePixmap *>::iterator iter = m_pixmaps.begin(); iter != m_pixmaps.end(); ++iter)
{
delete *iter;
*iter = NULL;
}
m_pixmaps.clear();
// Destroy windows
for (vector<eglu::NativeWindow *>::iterator iter = m_windows.begin(); iter != m_windows.end(); ++iter)
{
delete *iter;
*iter = NULL;
}
m_windows.clear();
// Clear all surface handles
m_surfaces.clear();
}
}
void MakeCurrentPerfCase::createContexts(void)
{
const Library &egl = m_eglTestCtx.getLibrary();
for (int contextNdx = 0; contextNdx < m_spec.contextCount; contextNdx++)
{
const EGLint attribList[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
EGLU_CHECK_CALL(egl, bindAPI(EGL_OPENGL_ES_API));
EGLContext context = egl.createContext(m_display, m_config, EGL_NO_CONTEXT, attribList);
EGLU_CHECK_MSG(egl, "eglCreateContext()");
m_contexts.push_back(context);
}
}
void MakeCurrentPerfCase::destroyContexts(void)
{
const Library &egl = m_eglTestCtx.getLibrary();
if (m_contexts.size() > 0)
{
EGLDisplay display = m_display;
for (vector<EGLContext>::iterator iter = m_contexts.begin(); iter != m_contexts.end(); ++iter)
{
if (*iter != EGL_NO_CONTEXT)
EGLU_CHECK_CALL(egl, destroyContext(display, *iter));
*iter = EGL_NO_CONTEXT;
}
m_contexts.clear();
}
}
void MakeCurrentPerfCase::logTestInfo(void)
{
TestLog &log = m_testCtx.getLog();
{
tcu::ScopedLogSection section(log, "Test Info", "Test case information.");
log << TestLog::Message << "Context count: " << m_contexts.size() << TestLog::EndMessage;
log << TestLog::Message << "Surfaces count: " << m_surfaces.size() << TestLog::EndMessage;
log << TestLog::Message << "Sample count: " << m_spec.sampleCount << TestLog::EndMessage;
log << TestLog::Message << "Iteration count: " << m_spec.iterationCount << TestLog::EndMessage;
log << TestLog::Message << "Window count: " << m_windows.size() << TestLog::EndMessage;
log << TestLog::Message << "Pixmap count: " << m_pixmaps.size() << TestLog::EndMessage;
log << TestLog::Message << "PBuffer count: " << (m_surfaces.size() - m_windows.size() - m_pixmaps.size())
<< TestLog::EndMessage;
if (m_spec.release)
log << TestLog::Message
<< "Context is released after each use. Both binding and releasing context are included in result time."
<< TestLog::EndMessage;
}
}
void MakeCurrentPerfCase::logResults(void)
{
TestLog &log = m_testCtx.getLog();
log << TestLog::SampleList("Result", "Result") << TestLog::SampleInfo
<< TestLog::ValueInfo("Time", "Time", "us", QP_SAMPLE_VALUE_TAG_RESPONSE) << TestLog::EndSampleInfo;
for (int sampleNdx = 0; sampleNdx < (int)m_samples.size(); sampleNdx++)
log << TestLog::Sample << int64_t(m_samples[sampleNdx]) << TestLog::EndSample;
log << TestLog::EndSampleList;
// Log stats
{
uint64_t totalTimeUs = 0;
uint64_t totalIterationCount = 0;
float iterationTimeMeanUs = 0.0f;
float iterationTimeMedianUs = 0.0f;
float iterationTimeVarianceUs = 0.0f;
float iterationTimeSkewnessUs = 0.0f;
float iterationTimeMinUs = std::numeric_limits<float>::max();
float iterationTimeMaxUs = 0.0f;
std::sort(m_samples.begin(), m_samples.end());
// Calculate totals
for (int sampleNdx = 0; sampleNdx < (int)m_samples.size(); sampleNdx++)
{
totalTimeUs += m_samples[sampleNdx];
totalIterationCount += m_spec.iterationCount;
}
// Calculate mean and median
iterationTimeMeanUs = ((float)(((double)totalTimeUs) / (double)totalIterationCount));
iterationTimeMedianUs = ((float)(((double)m_samples[m_samples.size() / 2]) / (double)m_spec.iterationCount));
// Calculate variance
for (int sampleNdx = 0; sampleNdx < (int)m_samples.size(); sampleNdx++)
{
float iterationTimeUs = (float)(((double)m_samples[sampleNdx]) / m_spec.iterationCount);
iterationTimeVarianceUs += std::pow(iterationTimeUs - iterationTimeMedianUs, 2.0f);
}
// Calculate min and max
for (int sampleNdx = 0; sampleNdx < (int)m_samples.size(); sampleNdx++)
{
float iterationTimeUs = (float)(((double)m_samples[sampleNdx]) / m_spec.iterationCount);
iterationTimeMinUs = std::min<float>(iterationTimeMinUs, iterationTimeUs);
iterationTimeMaxUs = std::max<float>(iterationTimeMaxUs, iterationTimeUs);
}
iterationTimeVarianceUs /= (float)m_samples.size();
// Calculate skewness
for (int sampleNdx = 0; sampleNdx < (int)m_samples.size(); sampleNdx++)
{
float iterationTimeUs = (float)(((double)m_samples[sampleNdx]) / m_spec.iterationCount);
iterationTimeSkewnessUs =
std::pow((iterationTimeUs - iterationTimeMedianUs) / iterationTimeVarianceUs, 2.0f);
}
iterationTimeSkewnessUs /= (float)m_samples.size();
{
tcu::ScopedLogSection section(log, "Result", "Statistics from results.");
log << TestLog::Message << "Total time: " << totalTimeUs << "us" << TestLog::EndMessage;
log << TestLog::Message << "Mean: " << iterationTimeMeanUs << "us" << TestLog::EndMessage;
log << TestLog::Message << "Median: " << iterationTimeMedianUs << "us" << TestLog::EndMessage;
log << TestLog::Message << "Variance: " << iterationTimeVarianceUs << "us" << TestLog::EndMessage;
log << TestLog::Message << "Skewness: " << iterationTimeSkewnessUs << "us" << TestLog::EndMessage;
log << TestLog::Message << "Min: " << iterationTimeMinUs << "us" << TestLog::EndMessage;
log << TestLog::Message << "Max: " << iterationTimeMaxUs << "us" << TestLog::EndMessage;
}
m_testCtx.setTestResult(
QP_TEST_RESULT_PASS,
de::floatToString((float)(((double)totalTimeUs) / (double)totalIterationCount), 2).c_str());
}
}
TestCase::IterateResult MakeCurrentPerfCase::iterate(void)
{
const Library &egl = m_eglTestCtx.getLibrary();
if (m_samples.size() == 0)
logTestInfo();
{
EGLDisplay display = m_display;
uint64_t beginTimeUs = deGetMicroseconds();
for (int iteration = 0; iteration < m_spec.iterationCount; iteration++)
{
EGLContext context = m_contexts[m_rnd.getUint32() % m_contexts.size()];
EGLSurface surface = m_surfaces[m_rnd.getUint32() % m_surfaces.size()];
egl.makeCurrent(display, surface, surface, context);
if (m_spec.release)
egl.makeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
}
m_samples.push_back(deGetMicroseconds() - beginTimeUs);
egl.makeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
EGLU_CHECK_MSG(egl, "eglMakeCurrent()");
}
if ((int)m_samples.size() == m_spec.sampleCount)
{
logResults();
return STOP;
}
else
return CONTINUE;
}
MakeCurrentPerfTests::MakeCurrentPerfTests(EglTestContext &eglTestCtx)
: TestCaseGroup(eglTestCtx, "make_current", "eglMakeCurrent performance tests")
{
}
void MakeCurrentPerfTests::init(void)
{
const int iterationCount = 100;
const int sampleCount = 100;
// Add simple test group
{
TestCaseGroup *simple = new TestCaseGroup(
m_eglTestCtx, "simple", "Simple eglMakeCurrent performance tests using single context and surface");
const MakeCurrentPerfCase::SurfaceType types[] = {MakeCurrentPerfCase::SURFACETYPE_PBUFFER,
MakeCurrentPerfCase::SURFACETYPE_PIXMAP,
MakeCurrentPerfCase::SURFACETYPE_WINDOW};
for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(types); typeNdx++)
{
for (int releaseNdx = 0; releaseNdx < 2; releaseNdx++)
{
MakeCurrentPerfCase::Spec spec;
spec.surfaceTypes = types[typeNdx];
spec.contextCount = 1;
spec.surfaceCount = 1;
spec.release = (releaseNdx == 1);
spec.iterationCount = iterationCount;
spec.sampleCount = sampleCount;
simple->addChild(
new MakeCurrentPerfCase(m_eglTestCtx, spec, spec.toName().c_str(), spec.toDescription().c_str()));
}
}
addChild(simple);
}
// Add multi context test group
{
TestCaseGroup *multiContext =
new TestCaseGroup(m_eglTestCtx, "multi_context",
"eglMakeCurrent performance tests using multiple contexts and single surface");
const MakeCurrentPerfCase::SurfaceType types[] = {MakeCurrentPerfCase::SURFACETYPE_PBUFFER,
MakeCurrentPerfCase::SURFACETYPE_PIXMAP,
MakeCurrentPerfCase::SURFACETYPE_WINDOW};
const int contextCounts[] = {10, 100};
for (int contextCountNdx = 0; contextCountNdx < DE_LENGTH_OF_ARRAY(contextCounts); contextCountNdx++)
{
for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(types); typeNdx++)
{
for (int releaseNdx = 0; releaseNdx < 2; releaseNdx++)
{
MakeCurrentPerfCase::Spec spec;
spec.surfaceTypes = types[typeNdx];
spec.contextCount = contextCounts[contextCountNdx];
spec.surfaceCount = 1;
spec.release = (releaseNdx == 1);
spec.iterationCount = iterationCount;
spec.sampleCount = sampleCount;
multiContext->addChild(new MakeCurrentPerfCase(m_eglTestCtx, spec, spec.toName().c_str(),
spec.toDescription().c_str()));
}
}
}
addChild(multiContext);
}
// Add multi surface test group
{
TestCaseGroup *multiSurface =
new TestCaseGroup(m_eglTestCtx, "multi_surface",
"eglMakeCurrent performance tests using single context and multiple surfaces");
const MakeCurrentPerfCase::SurfaceType types[] = {
MakeCurrentPerfCase::SURFACETYPE_PBUFFER,
MakeCurrentPerfCase::SURFACETYPE_PIXMAP,
MakeCurrentPerfCase::SURFACETYPE_WINDOW,
(MakeCurrentPerfCase::SurfaceType)(MakeCurrentPerfCase::SURFACETYPE_PBUFFER |
MakeCurrentPerfCase::SURFACETYPE_PIXMAP),
(MakeCurrentPerfCase::SurfaceType)(MakeCurrentPerfCase::SURFACETYPE_PBUFFER |
MakeCurrentPerfCase::SURFACETYPE_WINDOW),
(MakeCurrentPerfCase::SurfaceType)(MakeCurrentPerfCase::SURFACETYPE_PIXMAP |
MakeCurrentPerfCase::SURFACETYPE_WINDOW),
(MakeCurrentPerfCase::SurfaceType)(MakeCurrentPerfCase::SURFACETYPE_PBUFFER |
MakeCurrentPerfCase::SURFACETYPE_PIXMAP |
MakeCurrentPerfCase::SURFACETYPE_WINDOW)};
const int surfaceCounts[] = {10, 100};
for (int surfaceCountNdx = 0; surfaceCountNdx < DE_LENGTH_OF_ARRAY(surfaceCounts); surfaceCountNdx++)
{
for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(types); typeNdx++)
{
for (int releaseNdx = 0; releaseNdx < 2; releaseNdx++)
{
MakeCurrentPerfCase::Spec spec;
spec.surfaceTypes = types[typeNdx];
spec.surfaceCount = surfaceCounts[surfaceCountNdx];
spec.contextCount = 1;
spec.release = (releaseNdx == 1);
spec.iterationCount = iterationCount;
spec.sampleCount = sampleCount;
multiSurface->addChild(new MakeCurrentPerfCase(m_eglTestCtx, spec, spec.toName().c_str(),
spec.toDescription().c_str()));
}
}
}
addChild(multiSurface);
}
// Add Complex? test group
{
TestCaseGroup *multi = new TestCaseGroup(
m_eglTestCtx, "complex", "eglMakeCurrent performance tests using multiple contexts and multiple surfaces");
const MakeCurrentPerfCase::SurfaceType types[] = {
MakeCurrentPerfCase::SURFACETYPE_PBUFFER,
MakeCurrentPerfCase::SURFACETYPE_PIXMAP,
MakeCurrentPerfCase::SURFACETYPE_WINDOW,
(MakeCurrentPerfCase::SurfaceType)(MakeCurrentPerfCase::SURFACETYPE_PBUFFER |
MakeCurrentPerfCase::SURFACETYPE_PIXMAP),
(MakeCurrentPerfCase::SurfaceType)(MakeCurrentPerfCase::SURFACETYPE_PBUFFER |
MakeCurrentPerfCase::SURFACETYPE_WINDOW),
(MakeCurrentPerfCase::SurfaceType)(MakeCurrentPerfCase::SURFACETYPE_PIXMAP |
MakeCurrentPerfCase::SURFACETYPE_WINDOW),
(MakeCurrentPerfCase::SurfaceType)(MakeCurrentPerfCase::SURFACETYPE_PBUFFER |
MakeCurrentPerfCase::SURFACETYPE_PIXMAP |
MakeCurrentPerfCase::SURFACETYPE_WINDOW)};
const int surfaceCounts[] = {10, 100};
const int contextCounts[] = {10, 100};
for (int surfaceCountNdx = 0; surfaceCountNdx < DE_LENGTH_OF_ARRAY(surfaceCounts); surfaceCountNdx++)
{
for (int contextCountNdx = 0; contextCountNdx < DE_LENGTH_OF_ARRAY(contextCounts); contextCountNdx++)
{
for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(types); typeNdx++)
{
for (int releaseNdx = 0; releaseNdx < 2; releaseNdx++)
{
MakeCurrentPerfCase::Spec spec;
spec.surfaceTypes = types[typeNdx];
spec.contextCount = contextCounts[contextCountNdx];
spec.surfaceCount = surfaceCounts[surfaceCountNdx];
spec.release = (releaseNdx == 1);
spec.iterationCount = iterationCount;
spec.sampleCount = sampleCount;
multi->addChild(new MakeCurrentPerfCase(m_eglTestCtx, spec, spec.toName().c_str(),
spec.toDescription().c_str()));
}
}
}
}
addChild(multi);
}
}
} // namespace egl
} // namespace deqp