You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
358 lines
14 KiB
358 lines
14 KiB
/*-------------------------------------------------------------------------
|
|
* drawElements Quality Program OpenGL ES 3.0 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 Long-running stress tests.
|
|
*//*--------------------------------------------------------------------*/
|
|
|
|
#include "es3sLongRunningTests.hpp"
|
|
#include "glsLongStressCase.hpp"
|
|
#include "glsLongStressTestUtil.hpp"
|
|
#include "glwEnums.hpp"
|
|
|
|
#include <string>
|
|
|
|
using std::string;
|
|
|
|
namespace deqp
|
|
{
|
|
namespace gles3
|
|
{
|
|
namespace Stress
|
|
{
|
|
|
|
LongRunningTests::LongRunningTests (Context& context)
|
|
: TestCaseGroup(context, "long", "Long-running stress tests")
|
|
{
|
|
}
|
|
|
|
LongRunningTests::~LongRunningTests (void)
|
|
{
|
|
}
|
|
|
|
void LongRunningTests::init (void)
|
|
{
|
|
static const int Mi = 1<<20;
|
|
const gls::LongStressTestUtil::ProgramLibrary progLib (glu::GLSL_VERSION_300_ES);
|
|
|
|
typedef gls::LongStressCase::FeatureProbabilities Probs;
|
|
|
|
// Buffer cases.
|
|
|
|
{
|
|
static const struct MemCase
|
|
{
|
|
const char* const nameSuffix;
|
|
const char* const descSuffix;
|
|
const int limit;
|
|
const int redundantBufferFactor;
|
|
MemCase (const char* n, const char* d, int l, int r) : nameSuffix(n), descSuffix(d), limit(l), redundantBufferFactor(r) {}
|
|
} memoryLimitCases[] =
|
|
{
|
|
MemCase("_low_memory", "; use a low buffer memory usage limit", 8*Mi, 2),
|
|
MemCase("_high_memory", "; use a high buffer memory usage limit", 256*Mi, 64)
|
|
};
|
|
|
|
const std::vector<gls::ProgramContext> contexts(1, progLib.generateBufferContext(4));
|
|
|
|
static const struct Case
|
|
{
|
|
const char* const name;
|
|
const char* const desc;
|
|
const int redundantBufferFactor; //!< If non-positive, taken from memoryLimitCases.
|
|
const Probs probs;
|
|
Case (const char* const name_, const char* const desc_, int bufFact, const Probs& probs_ = Probs()) : name(name_), desc(desc_), redundantBufferFactor(bufFact), probs(probs_) {}
|
|
} cases[] =
|
|
{
|
|
Case("always_reupload",
|
|
"Re-upload buffer data at the beginning of each iteration",
|
|
-1,
|
|
Probs().pReuploadBuffer(1.0f)),
|
|
|
|
Case("always_reupload_bufferdata",
|
|
"Re-upload buffer data at the beginning of each iteration, using glBufferData",
|
|
-1,
|
|
Probs().pReuploadBuffer(1.0f).pReuploadWithBufferData(1.0f)),
|
|
|
|
Case("always_delete",
|
|
"Delete buffers at the end of each iteration, and re-create at the beginning of the next",
|
|
-1,
|
|
Probs().pDeleteBuffer(1.0f)),
|
|
|
|
Case("wasteful",
|
|
"Don't reuse buffers, and only delete them when given memory limit is reached",
|
|
2,
|
|
Probs().pWastefulBufferMemoryUsage(1.0f)),
|
|
|
|
Case("separate_attribute_buffers_wasteful",
|
|
"Give each vertex attribute its own buffer",
|
|
2,
|
|
Probs().pSeparateAttribBuffers(1.0f).pWastefulBufferMemoryUsage(1.0f))
|
|
};
|
|
|
|
TestCaseGroup* const bufferGroup = new TestCaseGroup(m_context, "buffer", "Buffer stress tests");
|
|
addChild(bufferGroup);
|
|
|
|
for (int memoryLimitNdx = 0; memoryLimitNdx < DE_LENGTH_OF_ARRAY(memoryLimitCases); memoryLimitNdx++)
|
|
{
|
|
for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); caseNdx++)
|
|
{
|
|
const int redundantBufferFactor = cases[caseNdx].redundantBufferFactor > 0 ? cases[caseNdx].redundantBufferFactor : memoryLimitCases[memoryLimitNdx].redundantBufferFactor;
|
|
|
|
bufferGroup->addChild(new gls::LongStressCase(m_context.getTestContext(), m_context.getRenderContext(),
|
|
(string() + cases[caseNdx].name + memoryLimitCases[memoryLimitNdx].nameSuffix).c_str(),
|
|
(string() + cases[caseNdx].desc + memoryLimitCases[memoryLimitNdx].descSuffix).c_str(),
|
|
0 /* tex memory */, memoryLimitCases[memoryLimitNdx].limit,
|
|
1 /* draw calls per iteration */, 50000 /* tris per call */,
|
|
contexts, cases[caseNdx].probs,
|
|
GL_DYNAMIC_DRAW, GL_DYNAMIC_DRAW,
|
|
redundantBufferFactor));
|
|
}
|
|
}
|
|
}
|
|
|
|
// Texture cases.
|
|
|
|
{
|
|
static const struct MemCase
|
|
{
|
|
const char* const nameSuffix;
|
|
const char* const descSuffix;
|
|
const int limit;
|
|
const int numTextures;
|
|
MemCase (const char* n, const char* d, int l, int t) : nameSuffix(n), descSuffix(d), limit(l), numTextures(t) {}
|
|
} memoryLimitCases[] =
|
|
{
|
|
MemCase("_low_memory", "; use a low texture memory usage limit", 8*Mi, 6),
|
|
MemCase("_high_memory", "; use a high texture memory usage limit", 256*Mi, 192)
|
|
};
|
|
|
|
static const struct Case
|
|
{
|
|
const char* const name;
|
|
const char* const desc;
|
|
const int numTextures; //!< If non-positive, taken from memoryLimitCases.
|
|
const Probs probs;
|
|
Case (const char* const name_, const char* const desc_, int numTextures_, const Probs& probs_ = Probs()) : name(name_), desc(desc_), numTextures(numTextures_), probs(probs_) {}
|
|
} cases[] =
|
|
{
|
|
Case("always_reupload",
|
|
"Re-upload texture data at the beginning of each iteration",
|
|
-1,
|
|
Probs().pReuploadTexture(1.0f)),
|
|
|
|
Case("always_reupload_teximage",
|
|
"Re-upload texture data at the beginning of each iteration, using glTexImage*",
|
|
-1,
|
|
Probs().pReuploadTexture(1.0f).pReuploadWithTexImage(1.0f)),
|
|
|
|
Case("always_delete",
|
|
"Delete textures at the end of each iteration, and re-create at the beginning of the next",
|
|
-1,
|
|
Probs().pDeleteTexture(1.0f)),
|
|
|
|
Case("wasteful",
|
|
"Don't reuse textures, and only delete them when given memory limit is reached",
|
|
6,
|
|
Probs().pWastefulTextureMemoryUsage(1.0f))
|
|
};
|
|
|
|
TestCaseGroup* const textureGroup = new TestCaseGroup(m_context, "texture", "Texture stress tests");
|
|
addChild(textureGroup);
|
|
|
|
for (int memoryLimitNdx = 0; memoryLimitNdx < DE_LENGTH_OF_ARRAY(memoryLimitCases); memoryLimitNdx++)
|
|
{
|
|
for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); caseNdx++)
|
|
{
|
|
const int numTextures = cases[caseNdx].numTextures > 0 ? cases[caseNdx].numTextures : memoryLimitCases[memoryLimitNdx].numTextures;
|
|
const std::vector<gls::ProgramContext> contexts (1, progLib.generateTextureContext(numTextures, 512, 512, 0.1f));
|
|
|
|
textureGroup->addChild(new gls::LongStressCase(m_context.getTestContext(), m_context.getRenderContext(),
|
|
(string() + cases[caseNdx].name + memoryLimitCases[memoryLimitNdx].nameSuffix).c_str(),
|
|
(string() + cases[caseNdx].desc + memoryLimitCases[memoryLimitNdx].descSuffix).c_str(),
|
|
memoryLimitCases[memoryLimitNdx].limit, 1*Mi /* buf memory */,
|
|
1 /* draw calls per iteration */, 10000 /* tris per call */,
|
|
contexts, cases[caseNdx].probs,
|
|
GL_STATIC_DRAW, GL_STATIC_DRAW));
|
|
}
|
|
}
|
|
}
|
|
|
|
// Draw call cases.
|
|
|
|
{
|
|
const std::vector<gls::ProgramContext> contexts(1, progLib.generateTextureContext(1, 128, 128, 0.5f));
|
|
|
|
static const struct Case
|
|
{
|
|
const char* const name;
|
|
const char* const desc;
|
|
const int drawCallsPerIteration;
|
|
const int numTrisPerDrawCall;
|
|
const Probs probs;
|
|
Case (const char* const name_, const char* const desc_, const int calls, const int tris, const Probs& probs_ = Probs())
|
|
: name(name_), desc(desc_), drawCallsPerIteration(calls), numTrisPerDrawCall(tris), probs(probs_) {}
|
|
} cases[] =
|
|
{
|
|
Case("client_memory_data",
|
|
"Use client-memory for index and attribute data, instead of GL buffers",
|
|
200, 500,
|
|
Probs().pClientMemoryAttributeData(1.0f).pClientMemoryIndexData(1.0f)),
|
|
|
|
Case("vary_draw_function",
|
|
"Choose between glDrawElements and glDrawArrays each iteration, with uniform probability",
|
|
200, 500,
|
|
Probs().pUseDrawArrays(0.5f)),
|
|
|
|
Case("few_big_calls",
|
|
"Per iteration, do a few draw calls with a big number of triangles per call",
|
|
2, 50000),
|
|
|
|
Case("many_small_calls",
|
|
"Per iteration, do many draw calls with a small number of triangles per call",
|
|
2000, 50)
|
|
};
|
|
|
|
TestCaseGroup* const drawCallGroup = new TestCaseGroup(m_context, "draw_call", "Draw call stress tests");
|
|
addChild(drawCallGroup);
|
|
|
|
for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); caseNdx++)
|
|
{
|
|
drawCallGroup->addChild(new gls::LongStressCase(m_context.getTestContext(), m_context.getRenderContext(),
|
|
cases[caseNdx].name, cases[caseNdx].desc,
|
|
1*Mi /* tex memory */, 2*Mi /* buf memory */,
|
|
cases[caseNdx].drawCallsPerIteration, cases[caseNdx].numTrisPerDrawCall,
|
|
contexts, cases[caseNdx].probs,
|
|
GL_STATIC_DRAW, GL_STATIC_DRAW));
|
|
}
|
|
}
|
|
|
|
// Shader cases.
|
|
|
|
{
|
|
std::vector<gls::ProgramContext> contexts;
|
|
contexts.push_back(progLib.generateFragmentPointLightContext(512, 512));
|
|
contexts.push_back(progLib.generateVertexUniformLoopLightContext(512, 512));
|
|
|
|
static const struct Case
|
|
{
|
|
const char* const name;
|
|
const char* const desc;
|
|
const Probs probs;
|
|
Case (const char* const name_, const char* const desc_, const Probs& probs_ = Probs()) : name(name_), desc(desc_), probs(probs_) {}
|
|
} cases[] =
|
|
{
|
|
Case("several_programs",
|
|
"Use several different programs, choosing between them uniformly on each iteration"),
|
|
|
|
Case("several_programs_always_rebuild",
|
|
"Use several different programs, choosing between them uniformly on each iteration, and always rebuild the program",
|
|
Probs().pRebuildProgram(1.0f))
|
|
};
|
|
|
|
TestCaseGroup* const shaderGroup = new TestCaseGroup(m_context, "program", "Shader program stress tests");
|
|
addChild(shaderGroup);
|
|
|
|
for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); caseNdx++)
|
|
{
|
|
shaderGroup->addChild(new gls::LongStressCase(m_context.getTestContext(), m_context.getRenderContext(),
|
|
cases[caseNdx].name, cases[caseNdx].desc,
|
|
3*Mi /* tex memory */, 1*Mi /* buf memory */,
|
|
1 /* draw calls per iteration */, 10000 /* tris per call */,
|
|
contexts, cases[caseNdx].probs,
|
|
GL_STATIC_DRAW, GL_STATIC_DRAW));
|
|
}
|
|
}
|
|
|
|
// Mixed cases.
|
|
|
|
{
|
|
static const struct MemCase
|
|
{
|
|
const char* const nameSuffix;
|
|
const char* const descSuffix;
|
|
const int texLimit;
|
|
const int bufLimit;
|
|
MemCase (const char* n, const char* d, int t, int b) : nameSuffix(n), descSuffix(d), texLimit(t), bufLimit(b) {}
|
|
} memoryLimitCases[] =
|
|
{
|
|
MemCase("_low_memory", "; use a low memory usage limit", 8*Mi, 8*Mi),
|
|
MemCase("_high_memory", "; use a high memory usage limit", 128*Mi, 128*Mi)
|
|
};
|
|
|
|
TestCaseGroup* const mixedGroup = new TestCaseGroup(m_context, "mixed", "Mixed stress tests");
|
|
addChild(mixedGroup);
|
|
|
|
for (int memoryLimitNdx = 0; memoryLimitNdx < DE_LENGTH_OF_ARRAY(memoryLimitCases); memoryLimitNdx++)
|
|
{
|
|
mixedGroup->addChild(new gls::LongStressCase(m_context.getTestContext(), m_context.getRenderContext(),
|
|
(string() + "buffer_texture_wasteful" + memoryLimitCases[memoryLimitNdx].nameSuffix).c_str(),
|
|
(string() + "Use both buffers and textures wastefully" + memoryLimitCases[memoryLimitNdx].descSuffix).c_str(),
|
|
memoryLimitCases[memoryLimitNdx].texLimit, memoryLimitCases[memoryLimitNdx].bufLimit,
|
|
1 /* draw calls per iteration */, 10000 /* tris per call */,
|
|
std::vector<gls::ProgramContext>(1, progLib.generateBufferAndTextureContext(4, 512, 512)),
|
|
Probs()
|
|
.pReuploadTexture (0.3f)
|
|
.pReuploadWithTexImage (0.5f)
|
|
.pReuploadBuffer (0.3f)
|
|
.pReuploadWithBufferData (0.5f)
|
|
.pDeleteTexture (0.2f)
|
|
.pDeleteBuffer (0.2f)
|
|
.pWastefulTextureMemoryUsage (0.5f)
|
|
.pWastefulBufferMemoryUsage (0.5f)
|
|
.pRandomBufferUploadTarget (1.0f)
|
|
.pRandomBufferUsage (1.0f),
|
|
GL_STATIC_DRAW, GL_STATIC_DRAW));
|
|
|
|
{
|
|
std::vector<gls::ProgramContext> contexts;
|
|
contexts.push_back(progLib.generateFragmentPointLightContext(512, 512));
|
|
contexts.push_back(progLib.generateVertexUniformLoopLightContext(512, 512));
|
|
mixedGroup->addChild(new gls::LongStressCase(m_context.getTestContext(), m_context.getRenderContext(),
|
|
(string() + "random" + memoryLimitCases[memoryLimitNdx].nameSuffix).c_str(),
|
|
(string() + "Highly random behavior" + memoryLimitCases[memoryLimitNdx].descSuffix).c_str(),
|
|
memoryLimitCases[memoryLimitNdx].texLimit, memoryLimitCases[memoryLimitNdx].bufLimit,
|
|
1 /* draw calls per iteration */, 10000 /* tris per call */,
|
|
contexts,
|
|
Probs()
|
|
.pRebuildProgram (0.3f)
|
|
.pReuploadTexture (0.3f)
|
|
.pReuploadWithTexImage (0.3f)
|
|
.pReuploadBuffer (0.3f)
|
|
.pReuploadWithBufferData (0.3f)
|
|
.pDeleteTexture (0.2f)
|
|
.pDeleteBuffer (0.2f)
|
|
.pWastefulTextureMemoryUsage (0.3f)
|
|
.pWastefulBufferMemoryUsage (0.3f)
|
|
.pClientMemoryAttributeData (0.2f)
|
|
.pClientMemoryIndexData (0.2f)
|
|
.pSeparateAttribBuffers (0.4f)
|
|
.pUseDrawArrays (0.4f)
|
|
.pRandomBufferUploadTarget (1.0f)
|
|
.pRandomBufferUsage (1.0f),
|
|
GL_STATIC_DRAW, GL_STATIC_DRAW));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
} // Stress
|
|
} // gles3
|
|
} // deqp
|