xref: /aosp_15_r20/external/deqp/modules/glshared/glsLongStressCase.hpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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