blob: 0291dcaba9b57fb08386a20897e7160618990f9f [file] [log] [blame]
#ifndef _GLSLONGSTRESSCASE_HPP
#define _GLSLONGSTRESSCASE_HPP
/*-------------------------------------------------------------------------
* drawElements Quality Program OpenGL (ES) 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 Parametrized, long-running stress case.
*//*--------------------------------------------------------------------*/
#include "tcuDefs.hpp"
#include "tcuTestCase.hpp"
#include "tcuTexture.hpp"
#include "tcuMatrix.hpp"
#include "gluRenderContext.hpp"
#include "gluShaderUtil.hpp"
#include "glsTextureTestUtil.hpp"
#include "deRandom.hpp"
#include "deSharedPtr.hpp"
#include <string>
#include <vector>
#include <map>
namespace deqp
{
namespace gls
{
namespace LongStressCaseInternal
{
template <typename T> class GLObjectManager;
class Program;
class Buffer;
class Texture;
class DebugInfoRenderer;
}
struct VarSpec
{
union Value
{
float f[4*4]; // \note Matrices are stored in column major order.
int i[4];
};
std::string name;
glu::DataType type;
Value minValue;
Value maxValue;
template <typename T>
VarSpec (const std::string& name_, const T& minValue_, const T& maxValue_) : name(name_) { set(minValue_, maxValue_); }
template <typename T>
VarSpec (const std::string& name_, const T& value) : name(name_) { set(value, value); }
void set (float minValue_, float maxValue_)
{
type = glu::TYPE_FLOAT;
minValue.f[0] = minValue_;
maxValue.f[0] = maxValue_;
}
template <int ValSize>
void set (const tcu::Vector<float, ValSize>& minValue_, const tcu::Vector<float, ValSize>& maxValue_)
{
type = glu::getDataTypeFloatVec(ValSize);
vecToArr(minValue_, minValue.f);
vecToArr(maxValue_, maxValue.f);
}
template <int ValRows, int ValCols>
void set (const tcu::Matrix<float, ValRows, ValCols>& minValue_, const tcu::Matrix<float, ValRows, ValCols>& maxValue_)
{
type = glu::getDataTypeMatrix(ValCols, ValRows);
matToArr(minValue_, minValue.f);
matToArr(maxValue_, maxValue.f);
}
void set (int minValue_, int maxValue_)
{
type = glu::TYPE_INT;
minValue.i[0] = minValue_;
maxValue.i[0] = maxValue_;
}
template <int ValSize>
void set (const tcu::Vector<int, ValSize>& minValue_, const tcu::Vector<int, ValSize>& maxValue_)
{
type = glu::getDataTypeVector(glu::TYPE_INT, ValSize);
vecToArr(minValue_, minValue.i);
vecToArr(maxValue_, maxValue.i);
}
private:
template <typename T, int SrcSize, int DstSize>
static inline void vecToArr (const tcu::Vector<T, SrcSize>& src, T (&dst)[DstSize])
{
DE_STATIC_ASSERT(DstSize >= SrcSize);
for (int i = 0; i < SrcSize; i++)
dst[i] = src[i];
}
template <int ValRows, int ValCols, int DstSize>
static inline void matToArr (const tcu::Matrix<float, ValRows, ValCols>& src, float (&dst)[DstSize])
{
DE_STATIC_ASSERT(DstSize >= ValRows*ValCols);
tcu::Array<float, ValRows*ValCols> data = src.getColumnMajorData();
for (int i = 0; i < ValRows*ValCols; i++)
dst[i] = data[i];
}
};
struct TextureSpec
{
glu::TextureTestUtil::TextureType textureType;
deUint32 textureUnit;
int width;
int height;
deUint32 format;
deUint32 dataType;
deUint32 internalFormat;
bool useMipmap;
deUint32 minFilter;
deUint32 magFilter;
deUint32 sWrap;
deUint32 tWrap;
tcu::Vec4 minValue;
tcu::Vec4 maxValue;
TextureSpec (const glu::TextureTestUtil::TextureType texType,
const deUint32 unit,
const int width_,
const int height_,
const deUint32 format_,
const deUint32 dataType_,
const deUint32 internalFormat_,
const bool useMipmap_,
const deUint32 minFilter_,
const deUint32 magFilter_,
const deUint32 sWrap_,
const deUint32 tWrap_,
const tcu::Vec4& minValue_,
const tcu::Vec4& maxValue_)
: textureType (texType)
, textureUnit (unit)
, width (width_)
, height (height_)
, format (format_)
, dataType (dataType_)
, internalFormat (internalFormat_)
, useMipmap (useMipmap_)
, minFilter (minFilter_)
, magFilter (magFilter_)
, sWrap (sWrap_)
, tWrap (tWrap_)
, minValue (minValue_)
, maxValue (maxValue_)
{
}
};
/*--------------------------------------------------------------------*//*!
* \brief Struct for a shader program sources and related data
*
* A ProgramContext holds a program's vertex and fragment shader sources
* as well as specifications of its attributes, uniforms, and textures.
* When given to a StressCase, the string ${NS} is replaced by a magic
* number that varies between different compilations of the same program;
* the same replacement is done in attributes' and uniforms' names. This
* can be used to avoid shader caching by the GL, by e.g. suffixing each
* attribute, uniform and varying name with ${NS} in the shader source.
*//*--------------------------------------------------------------------*/
struct ProgramContext
{
std::string vertexSource;
std::string fragmentSource;
std::vector<VarSpec> attributes;
std::vector<VarSpec> uniforms;
std::vector<TextureSpec> textureSpecs; //!< \note If multiple textures have same unit, one of them is picked randomly.
std::string positionAttrName; //!< \note Position attribute may get a bit more careful handling than just complete random.
ProgramContext (const char* const vtxShaderSource_,
const char* const fragShaderSource_,
const char* const positionAttrName_)
: vertexSource (vtxShaderSource_)
, fragmentSource (fragShaderSource_)
, positionAttrName (positionAttrName_)
{
}
};
class LongStressCase : public tcu::TestCase
{
public:
//! Probabilities for actions that may be taken on each iteration. \note The texture and buffer specific actions are randomized per texture or buffer.
struct FeatureProbabilities
{
float rebuildProgram; //!< Rebuild program, with variable name-mangling.
float reuploadTexture; //!< Reupload texture, even if it already exists and has been uploaded.
float reuploadBuffer; //!< Reupload buffer, even if it already exists and has been uploaded.
float reuploadWithTexImage; //!< Use glTexImage*() when re-uploading texture, not glTexSubImage*().
float reuploadWithBufferData; //!< Use glBufferData() when re-uploading buffer, not glBufferSubData().
float deleteTexture; //!< Delete texture at end of iteration, even if we could re-use it.
float deleteBuffer; //!< Delete buffer at end of iteration, even if we could re-use it.
float wastefulTextureMemoryUsage; //!< Don't re-use a texture, and don't delete it until given memory limit is hit.
float wastefulBufferMemoryUsage; //!< Don't re-use a buffer, and don't delete it until given memory limit is hit.
float clientMemoryAttributeData; //!< Use client memory for vertex attribute data when drawing (instead of GL buffers).
float clientMemoryIndexData; //!< Use client memory for vertex indices when drawing (instead of GL buffers).
float randomBufferUploadTarget; //!< Use a random target when setting buffer data (i.e. not necessarily the one it'll be ultimately bound to).
float randomBufferUsage; //!< Use a random buffer usage parameter with glBufferData(), instead of the ones specified as params for the case.
float useDrawArrays; //!< Use glDrawArrays() instead of glDrawElements().
float separateAttributeBuffers; //!< Give each vertex attribute its own buffer.
// Named parameter idiom: helpers that can be used when making temporaries, e.g. FeatureProbabilities().pReuploadTexture(1.0f).pReuploadWithTexImage(1.0f)
FeatureProbabilities& pRebuildProgram (const float prob) { rebuildProgram = prob; return *this; }
FeatureProbabilities& pReuploadTexture (const float prob) { reuploadTexture = prob; return *this; }
FeatureProbabilities& pReuploadBuffer (const float prob) { reuploadBuffer = prob; return *this; }
FeatureProbabilities& pReuploadWithTexImage (const float prob) { reuploadWithTexImage = prob; return *this; }
FeatureProbabilities& pReuploadWithBufferData (const float prob) { reuploadWithBufferData = prob; return *this; }
FeatureProbabilities& pDeleteTexture (const float prob) { deleteTexture = prob; return *this; }
FeatureProbabilities& pDeleteBuffer (const float prob) { deleteBuffer = prob; return *this; }
FeatureProbabilities& pWastefulTextureMemoryUsage (const float prob) { wastefulTextureMemoryUsage = prob; return *this; }
FeatureProbabilities& pWastefulBufferMemoryUsage (const float prob) { wastefulBufferMemoryUsage = prob; return *this; }
FeatureProbabilities& pClientMemoryAttributeData (const float prob) { clientMemoryAttributeData = prob; return *this; }
FeatureProbabilities& pClientMemoryIndexData (const float prob) { clientMemoryIndexData = prob; return *this; }
FeatureProbabilities& pRandomBufferUploadTarget (const float prob) { randomBufferUploadTarget = prob; return *this; }
FeatureProbabilities& pRandomBufferUsage (const float prob) { randomBufferUsage = prob; return *this; }
FeatureProbabilities& pUseDrawArrays (const float prob) { useDrawArrays = prob; return *this; }
FeatureProbabilities& pSeparateAttribBuffers (const float prob) { separateAttributeBuffers = prob; return *this; }
FeatureProbabilities (void)
: rebuildProgram (0.0f)
, reuploadTexture (0.0f)
, reuploadBuffer (0.0f)
, reuploadWithTexImage (0.0f)
, reuploadWithBufferData (0.0f)
, deleteTexture (0.0f)
, deleteBuffer (0.0f)
, wastefulTextureMemoryUsage (0.0f)
, wastefulBufferMemoryUsage (0.0f)
, clientMemoryAttributeData (0.0f)
, clientMemoryIndexData (0.0f)
, randomBufferUploadTarget (0.0f)
, randomBufferUsage (0.0f)
, useDrawArrays (0.0f)
, separateAttributeBuffers (0.0f)
{
}
};
LongStressCase (tcu::TestContext& testCtx,
const glu::RenderContext& renderCtx,
const char* name,
const char* desc,
int maxTexMemoryUsageBytes, //!< Approximate upper bound on GL texture memory usage.
int maxBufMemoryUsageBytes, //!< Approximate upper bound on GL buffer memory usage.
int numDrawCallsPerIteration,
int numTrianglesPerDrawCall,
const std::vector<ProgramContext>& programContexts,
const FeatureProbabilities& probabilities,
deUint32 indexBufferUsage,
deUint32 attrBufferUsage,
int redundantBufferFactor = 1,
bool showDebugInfo = false);
~LongStressCase (void);
void init (void);
void deinit (void);
IterateResult iterate (void);
private:
LongStressCase (const LongStressCase&);
LongStressCase& operator= (const LongStressCase&);
const glu::RenderContext& m_renderCtx;
const int m_maxTexMemoryUsageBytes;
const int m_maxBufMemoryUsageBytes;
const int m_numDrawCallsPerIteration;
const int m_numTrianglesPerDrawCall;
const int m_numVerticesPerDrawCall;
const std::vector<ProgramContext> m_programContexts;
const FeatureProbabilities m_probabilities;
const deUint32 m_indexBufferUsage;
const deUint32 m_attrBufferUsage;
const int m_redundantBufferFactor; //!< By what factor we allocate redundant buffers. Default is 1, i.e. no redundancy.
const bool m_showDebugInfo;
const int m_numIterations;
const bool m_isGLES3;
int m_currentIteration;
deUint64 m_startTimeSeconds; //!< Set at beginning of first iteration.
deUint64 m_lastLogTime;
int m_lastLogIteration;
int m_currentLogEntryNdx;
de::Random m_rnd;
LongStressCaseInternal::GLObjectManager<
LongStressCaseInternal::Program>* m_programs;
LongStressCaseInternal::GLObjectManager<
LongStressCaseInternal::Buffer>* m_buffers;
LongStressCaseInternal::GLObjectManager<
LongStressCaseInternal::Texture>* m_textures;
std::vector<deUint16> m_vertexIndices;
struct ProgramResources
{
std::vector<deUint8> attrDataBuf;
std::vector<int> attrDataOffsets;
std::vector<int> attrDataSizes;
std::vector<de::SharedPtr<tcu::TextureLevel> > dummyTextures;
std::string shaderNameManglingSuffix;
};
std::vector<ProgramResources> m_programResources;
LongStressCaseInternal::DebugInfoRenderer* m_debugInfoRenderer;
};
} // gls
} // deqp
#endif // _GLSLONGSTRESSCASE_HPP