1 #ifndef _GLSLONGSTRESSCASE_HPP 2 #define _GLSLONGSTRESSCASE_HPP 3 /*------------------------------------------------------------------------- 4 * drawElements Quality Program OpenGL (ES) Module 5 * ----------------------------------------------- 6 * 7 * Copyright 2014 The Android Open Source Project 8 * 9 * Licensed under the Apache License, Version 2.0 (the "License"); 10 * you may not use this file except in compliance with the License. 11 * You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 * 21 *//*! 22 * \file 23 * \brief Parametrized, long-running stress case. 24 *//*--------------------------------------------------------------------*/ 25 26 #include "tcuDefs.hpp" 27 #include "tcuTestCase.hpp" 28 #include "tcuTexture.hpp" 29 #include "tcuMatrix.hpp" 30 #include "gluRenderContext.hpp" 31 #include "gluShaderUtil.hpp" 32 #include "glsTextureTestUtil.hpp" 33 #include "deRandom.hpp" 34 #include "deSharedPtr.hpp" 35 36 #include <string> 37 #include <vector> 38 #include <map> 39 40 namespace deqp 41 { 42 namespace gls 43 { 44 45 namespace LongStressCaseInternal 46 { 47 48 template <typename T> 49 class GLObjectManager; 50 class Program; 51 class Buffer; 52 class Texture; 53 class DebugInfoRenderer; 54 55 } // namespace LongStressCaseInternal 56 57 struct VarSpec 58 { 59 union Value 60 { 61 float f[4 * 4]; // \note Matrices are stored in column major order. 62 int i[4]; 63 }; 64 65 std::string name; 66 glu::DataType type; 67 Value minValue; 68 Value maxValue; 69 70 template <typename T> VarSpecdeqp::gls::VarSpec71 VarSpec(const std::string &name_, const T &minValue_, const T &maxValue_) : name(name_) 72 { 73 set(minValue_, maxValue_); 74 } 75 76 template <typename T> VarSpecdeqp::gls::VarSpec77 VarSpec(const std::string &name_, const T &value) : name(name_) 78 { 79 set(value, value); 80 } 81 setdeqp::gls::VarSpec82 void set(float minValue_, float maxValue_) 83 { 84 type = glu::TYPE_FLOAT; 85 minValue.f[0] = minValue_; 86 maxValue.f[0] = maxValue_; 87 } 88 89 template <int ValSize> setdeqp::gls::VarSpec90 void set(const tcu::Vector<float, ValSize> &minValue_, const tcu::Vector<float, ValSize> &maxValue_) 91 { 92 type = glu::getDataTypeFloatVec(ValSize); 93 vecToArr(minValue_, minValue.f); 94 vecToArr(maxValue_, maxValue.f); 95 } 96 97 template <int ValRows, int ValCols> setdeqp::gls::VarSpec98 void set(const tcu::Matrix<float, ValRows, ValCols> &minValue_, 99 const tcu::Matrix<float, ValRows, ValCols> &maxValue_) 100 { 101 type = glu::getDataTypeMatrix(ValCols, ValRows); 102 matToArr(minValue_, minValue.f); 103 matToArr(maxValue_, maxValue.f); 104 } 105 setdeqp::gls::VarSpec106 void set(int minValue_, int maxValue_) 107 { 108 type = glu::TYPE_INT; 109 minValue.i[0] = minValue_; 110 maxValue.i[0] = maxValue_; 111 } 112 113 template <int ValSize> setdeqp::gls::VarSpec114 void set(const tcu::Vector<int, ValSize> &minValue_, const tcu::Vector<int, ValSize> &maxValue_) 115 { 116 type = glu::getDataTypeVector(glu::TYPE_INT, ValSize); 117 vecToArr(minValue_, minValue.i); 118 vecToArr(maxValue_, maxValue.i); 119 } 120 121 private: 122 template <typename T, int SrcSize, int DstSize> vecToArrdeqp::gls::VarSpec123 static inline void vecToArr(const tcu::Vector<T, SrcSize> &src, T (&dst)[DstSize]) 124 { 125 DE_STATIC_ASSERT(DstSize >= SrcSize); 126 for (int i = 0; i < SrcSize; i++) 127 dst[i] = src[i]; 128 } 129 130 template <int ValRows, int ValCols, int DstSize> matToArrdeqp::gls::VarSpec131 static inline void matToArr(const tcu::Matrix<float, ValRows, ValCols> &src, float (&dst)[DstSize]) 132 { 133 DE_STATIC_ASSERT(DstSize >= ValRows * ValCols); 134 tcu::Array<float, ValRows *ValCols> data = src.getColumnMajorData(); 135 for (int i = 0; i < ValRows * ValCols; i++) 136 dst[i] = data[i]; 137 } 138 }; 139 140 struct TextureSpec 141 { 142 glu::TextureTestUtil::TextureType textureType; 143 uint32_t textureUnit; 144 int width; 145 int height; 146 uint32_t format; 147 uint32_t dataType; 148 uint32_t internalFormat; 149 bool useMipmap; 150 uint32_t minFilter; 151 uint32_t magFilter; 152 uint32_t sWrap; 153 uint32_t tWrap; 154 tcu::Vec4 minValue; 155 tcu::Vec4 maxValue; 156 TextureSpecdeqp::gls::TextureSpec157 TextureSpec(const glu::TextureTestUtil::TextureType texType, const uint32_t unit, const int width_, 158 const int height_, const uint32_t format_, const uint32_t dataType_, const uint32_t internalFormat_, 159 const bool useMipmap_, const uint32_t minFilter_, const uint32_t magFilter_, const uint32_t sWrap_, 160 const uint32_t tWrap_, const tcu::Vec4 &minValue_, const tcu::Vec4 &maxValue_) 161 : textureType(texType) 162 , textureUnit(unit) 163 , width(width_) 164 , height(height_) 165 , format(format_) 166 , dataType(dataType_) 167 , internalFormat(internalFormat_) 168 , useMipmap(useMipmap_) 169 , minFilter(minFilter_) 170 , magFilter(magFilter_) 171 , sWrap(sWrap_) 172 , tWrap(tWrap_) 173 , minValue(minValue_) 174 , maxValue(maxValue_) 175 { 176 } 177 }; 178 179 /*--------------------------------------------------------------------*//*! 180 * \brief Struct for a shader program sources and related data 181 * 182 * A ProgramContext holds a program's vertex and fragment shader sources 183 * as well as specifications of its attributes, uniforms, and textures. 184 * When given to a StressCase, the string ${NS} is replaced by a magic 185 * number that varies between different compilations of the same program; 186 * the same replacement is done in attributes' and uniforms' names. This 187 * can be used to avoid shader caching by the GL, by e.g. suffixing each 188 * attribute, uniform and varying name with ${NS} in the shader source. 189 *//*--------------------------------------------------------------------*/ 190 struct ProgramContext 191 { 192 std::string vertexSource; 193 std::string fragmentSource; 194 std::vector<VarSpec> attributes; 195 std::vector<VarSpec> uniforms; 196 197 std::vector<TextureSpec> 198 textureSpecs; //!< \note If multiple textures have same unit, one of them is picked randomly. 199 200 std::string 201 positionAttrName; //!< \note Position attribute may get a bit more careful handling than just complete random. 202 ProgramContextdeqp::gls::ProgramContext203 ProgramContext(const char *const vtxShaderSource_, const char *const fragShaderSource_, 204 const char *const positionAttrName_) 205 : vertexSource(vtxShaderSource_) 206 , fragmentSource(fragShaderSource_) 207 , positionAttrName(positionAttrName_) 208 { 209 } 210 }; 211 212 class LongStressCase : public tcu::TestCase 213 { 214 public: 215 //! Probabilities for actions that may be taken on each iteration. \note The texture and buffer specific actions are randomized per texture or buffer. 216 struct FeatureProbabilities 217 { 218 float rebuildProgram; //!< Rebuild program, with variable name-mangling. 219 float reuploadTexture; //!< Reupload texture, even if it already exists and has been uploaded. 220 float reuploadBuffer; //!< Reupload buffer, even if it already exists and has been uploaded. 221 float reuploadWithTexImage; //!< Use glTexImage*() when re-uploading texture, not glTexSubImage*(). 222 float reuploadWithBufferData; //!< Use glBufferData() when re-uploading buffer, not glBufferSubData(). 223 float deleteTexture; //!< Delete texture at end of iteration, even if we could re-use it. 224 float deleteBuffer; //!< Delete buffer at end of iteration, even if we could re-use it. 225 float 226 wastefulTextureMemoryUsage; //!< Don't re-use a texture, and don't delete it until given memory limit is hit. 227 float 228 wastefulBufferMemoryUsage; //!< Don't re-use a buffer, and don't delete it until given memory limit is hit. 229 float 230 clientMemoryAttributeData; //!< Use client memory for vertex attribute data when drawing (instead of GL buffers). 231 float clientMemoryIndexData; //!< Use client memory for vertex indices when drawing (instead of GL buffers). 232 float 233 randomBufferUploadTarget; //!< Use a random target when setting buffer data (i.e. not necessarily the one it'll be ultimately bound to). 234 float 235 randomBufferUsage; //!< Use a random buffer usage parameter with glBufferData(), instead of the ones specified as params for the case. 236 float useDrawArrays; //!< Use glDrawArrays() instead of glDrawElements(). 237 float separateAttributeBuffers; //!< Give each vertex attribute its own buffer. 238 239 // Named parameter idiom: helpers that can be used when making temporaries, e.g. FeatureProbabilities().pReuploadTexture(1.0f).pReuploadWithTexImage(1.0f) pRebuildProgramdeqp::gls::LongStressCase::FeatureProbabilities240 FeatureProbabilities &pRebuildProgram(const float prob) 241 { 242 rebuildProgram = prob; 243 return *this; 244 } pReuploadTexturedeqp::gls::LongStressCase::FeatureProbabilities245 FeatureProbabilities &pReuploadTexture(const float prob) 246 { 247 reuploadTexture = prob; 248 return *this; 249 } pReuploadBufferdeqp::gls::LongStressCase::FeatureProbabilities250 FeatureProbabilities &pReuploadBuffer(const float prob) 251 { 252 reuploadBuffer = prob; 253 return *this; 254 } pReuploadWithTexImagedeqp::gls::LongStressCase::FeatureProbabilities255 FeatureProbabilities &pReuploadWithTexImage(const float prob) 256 { 257 reuploadWithTexImage = prob; 258 return *this; 259 } pReuploadWithBufferDatadeqp::gls::LongStressCase::FeatureProbabilities260 FeatureProbabilities &pReuploadWithBufferData(const float prob) 261 { 262 reuploadWithBufferData = prob; 263 return *this; 264 } pDeleteTexturedeqp::gls::LongStressCase::FeatureProbabilities265 FeatureProbabilities &pDeleteTexture(const float prob) 266 { 267 deleteTexture = prob; 268 return *this; 269 } pDeleteBufferdeqp::gls::LongStressCase::FeatureProbabilities270 FeatureProbabilities &pDeleteBuffer(const float prob) 271 { 272 deleteBuffer = prob; 273 return *this; 274 } pWastefulTextureMemoryUsagedeqp::gls::LongStressCase::FeatureProbabilities275 FeatureProbabilities &pWastefulTextureMemoryUsage(const float prob) 276 { 277 wastefulTextureMemoryUsage = prob; 278 return *this; 279 } pWastefulBufferMemoryUsagedeqp::gls::LongStressCase::FeatureProbabilities280 FeatureProbabilities &pWastefulBufferMemoryUsage(const float prob) 281 { 282 wastefulBufferMemoryUsage = prob; 283 return *this; 284 } pClientMemoryAttributeDatadeqp::gls::LongStressCase::FeatureProbabilities285 FeatureProbabilities &pClientMemoryAttributeData(const float prob) 286 { 287 clientMemoryAttributeData = prob; 288 return *this; 289 } pClientMemoryIndexDatadeqp::gls::LongStressCase::FeatureProbabilities290 FeatureProbabilities &pClientMemoryIndexData(const float prob) 291 { 292 clientMemoryIndexData = prob; 293 return *this; 294 } pRandomBufferUploadTargetdeqp::gls::LongStressCase::FeatureProbabilities295 FeatureProbabilities &pRandomBufferUploadTarget(const float prob) 296 { 297 randomBufferUploadTarget = prob; 298 return *this; 299 } pRandomBufferUsagedeqp::gls::LongStressCase::FeatureProbabilities300 FeatureProbabilities &pRandomBufferUsage(const float prob) 301 { 302 randomBufferUsage = prob; 303 return *this; 304 } pUseDrawArraysdeqp::gls::LongStressCase::FeatureProbabilities305 FeatureProbabilities &pUseDrawArrays(const float prob) 306 { 307 useDrawArrays = prob; 308 return *this; 309 } pSeparateAttribBuffersdeqp::gls::LongStressCase::FeatureProbabilities310 FeatureProbabilities &pSeparateAttribBuffers(const float prob) 311 { 312 separateAttributeBuffers = prob; 313 return *this; 314 } 315 FeatureProbabilitiesdeqp::gls::LongStressCase::FeatureProbabilities316 FeatureProbabilities(void) 317 : rebuildProgram(0.0f) 318 , reuploadTexture(0.0f) 319 , reuploadBuffer(0.0f) 320 , reuploadWithTexImage(0.0f) 321 , reuploadWithBufferData(0.0f) 322 , deleteTexture(0.0f) 323 , deleteBuffer(0.0f) 324 , wastefulTextureMemoryUsage(0.0f) 325 , wastefulBufferMemoryUsage(0.0f) 326 , clientMemoryAttributeData(0.0f) 327 , clientMemoryIndexData(0.0f) 328 , randomBufferUploadTarget(0.0f) 329 , randomBufferUsage(0.0f) 330 , useDrawArrays(0.0f) 331 , separateAttributeBuffers(0.0f) 332 { 333 } 334 }; 335 336 LongStressCase(tcu::TestContext &testCtx, const glu::RenderContext &renderCtx, const char *name, const char *desc, 337 int maxTexMemoryUsageBytes, //!< Approximate upper bound on GL texture memory usage. 338 int maxBufMemoryUsageBytes, //!< Approximate upper bound on GL buffer memory usage. 339 int numDrawCallsPerIteration, int numTrianglesPerDrawCall, 340 const std::vector<ProgramContext> &programContexts, const FeatureProbabilities &probabilities, 341 uint32_t indexBufferUsage, uint32_t attrBufferUsage, int redundantBufferFactor = 1, 342 bool showDebugInfo = false); 343 344 ~LongStressCase(void); 345 346 void init(void); 347 void deinit(void); 348 349 IterateResult iterate(void); 350 351 private: 352 LongStressCase(const LongStressCase &); 353 LongStressCase &operator=(const LongStressCase &); 354 355 const glu::RenderContext &m_renderCtx; 356 const int m_maxTexMemoryUsageBytes; 357 const int m_maxBufMemoryUsageBytes; 358 const int m_numDrawCallsPerIteration; 359 const int m_numTrianglesPerDrawCall; 360 const int m_numVerticesPerDrawCall; 361 const std::vector<ProgramContext> m_programContexts; 362 const FeatureProbabilities m_probabilities; 363 const uint32_t m_indexBufferUsage; 364 const uint32_t m_attrBufferUsage; 365 const int 366 m_redundantBufferFactor; //!< By what factor we allocate redundant buffers. Default is 1, i.e. no redundancy. 367 const bool m_showDebugInfo; 368 369 const int m_numIterations; 370 const bool m_isGLES3; 371 372 int m_currentIteration; 373 uint64_t m_startTimeSeconds; //!< Set at beginning of first iteration. 374 uint64_t m_lastLogTime; 375 int m_lastLogIteration; 376 int m_currentLogEntryNdx; 377 378 de::Random m_rnd; 379 LongStressCaseInternal::GLObjectManager<LongStressCaseInternal::Program> *m_programs; 380 LongStressCaseInternal::GLObjectManager<LongStressCaseInternal::Buffer> *m_buffers; 381 LongStressCaseInternal::GLObjectManager<LongStressCaseInternal::Texture> *m_textures; 382 std::vector<uint16_t> m_vertexIndices; 383 384 struct ProgramResources 385 { 386 std::vector<uint8_t> attrDataBuf; 387 std::vector<int> attrDataOffsets; 388 std::vector<int> attrDataSizes; 389 std::vector<de::SharedPtr<tcu::TextureLevel>> unusedTextures; 390 std::string shaderNameManglingSuffix; 391 }; 392 393 std::vector<ProgramResources> m_programResources; 394 395 LongStressCaseInternal::DebugInfoRenderer *m_debugInfoRenderer; 396 }; 397 398 } // namespace gls 399 } // namespace deqp 400 401 #endif // _GLSLONGSTRESSCASE_HPP 402