xref: /aosp_15_r20/external/deqp/framework/common/tcuTestLog.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program Tester Core
3  * ----------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Test Log C++ Wrapper.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "deCommandLine.h"
25 #include "tcuTestLog.hpp"
26 #include "tcuTextureUtil.hpp"
27 #include "tcuSurface.hpp"
28 #include "deMath.h"
29 
30 #include <limits>
31 
32 namespace tcu
33 {
34 
35 class LogWriteFailedError : public ResourceError
36 {
37 public:
LogWriteFailedError(void)38     LogWriteFailedError(void) : ResourceError("Writing to test log failed")
39     {
40     }
41 };
42 
43 enum
44 {
45     MAX_IMAGE_SIZE_2D = 4096,
46     MAX_IMAGE_SIZE_3D = 128
47 };
48 
49 // LogImage
50 
LogImage(const std::string & name,const std::string & description,const Surface & surface,qpImageCompressionMode compression)51 LogImage::LogImage(const std::string &name, const std::string &description, const Surface &surface,
52                    qpImageCompressionMode compression)
53     : m_name(name)
54     , m_description(description)
55     , m_access(surface.getAccess())
56     , m_scale(1.0f, 1.0f, 1.0f, 1.0f)
57     , m_bias(0.0f, 0.0f, 0.0f, 0.0f)
58     , m_compression(compression)
59 {
60 }
61 
LogImage(const std::string & name,const std::string & description,const ConstPixelBufferAccess & access,qpImageCompressionMode compression)62 LogImage::LogImage(const std::string &name, const std::string &description, const ConstPixelBufferAccess &access,
63                    qpImageCompressionMode compression)
64     : m_name(name)
65     , m_description(description)
66     , m_access(access)
67     , m_scale(1.0f, 1.0f, 1.0f, 1.0f)
68     , m_bias(0.0f, 0.0f, 0.0f, 0.0f)
69     , m_compression(compression)
70 {
71     // Simplify combined formats that only use a single channel
72     if (tcu::isCombinedDepthStencilType(m_access.getFormat().type))
73     {
74         if (m_access.getFormat().order == tcu::TextureFormat::D)
75             m_access = tcu::getEffectiveDepthStencilAccess(m_access, tcu::Sampler::MODE_DEPTH);
76         else if (m_access.getFormat().order == tcu::TextureFormat::S)
77             m_access = tcu::getEffectiveDepthStencilAccess(m_access, tcu::Sampler::MODE_STENCIL);
78     }
79 
80     // Implicit scale and bias
81     if (m_access.getFormat().order != tcu::TextureFormat::DS)
82         computePixelScaleBias(m_access, m_scale, m_bias);
83     else
84     {
85         // Pack D and S bias and scale to R and G
86         const ConstPixelBufferAccess depthAccess =
87             tcu::getEffectiveDepthStencilAccess(m_access, tcu::Sampler::MODE_DEPTH);
88         const ConstPixelBufferAccess stencilAccess =
89             tcu::getEffectiveDepthStencilAccess(m_access, tcu::Sampler::MODE_STENCIL);
90         tcu::Vec4 depthScale;
91         tcu::Vec4 depthBias;
92         tcu::Vec4 stencilScale;
93         tcu::Vec4 stencilBias;
94 
95         computePixelScaleBias(depthAccess, depthScale, depthBias);
96         computePixelScaleBias(stencilAccess, stencilScale, stencilBias);
97 
98         m_scale = tcu::Vec4(depthScale.x(), stencilScale.x(), 0.0f, 0.0f);
99         m_bias  = tcu::Vec4(depthBias.x(), stencilBias.x(), 0.0f, 0.0f);
100     }
101 }
102 
LogImage(const std::string & name,const std::string & description,const ConstPixelBufferAccess & access,const Vec4 & scale,const Vec4 & bias,qpImageCompressionMode compression)103 LogImage::LogImage(const std::string &name, const std::string &description, const ConstPixelBufferAccess &access,
104                    const Vec4 &scale, const Vec4 &bias, qpImageCompressionMode compression)
105     : m_name(name)
106     , m_description(description)
107     , m_access(access)
108     , m_scale(scale)
109     , m_bias(bias)
110     , m_compression(compression)
111 {
112     // Cannot set scale and bias of combined formats
113     DE_ASSERT(access.getFormat().order != tcu::TextureFormat::DS);
114 
115     // Simplify access
116     if (tcu::isCombinedDepthStencilType(access.getFormat().type))
117     {
118         if (access.getFormat().order == tcu::TextureFormat::D)
119             m_access = tcu::getEffectiveDepthStencilAccess(access, tcu::Sampler::MODE_DEPTH);
120         if (access.getFormat().order == tcu::TextureFormat::S)
121             m_access = tcu::getEffectiveDepthStencilAccess(access, tcu::Sampler::MODE_STENCIL);
122         else
123         {
124             // Cannot log a DS format
125             DE_ASSERT(false);
126             return;
127         }
128     }
129 }
130 
write(TestLog & log) const131 void LogImage::write(TestLog &log) const
132 {
133     if (m_access.getFormat().order != tcu::TextureFormat::DS)
134         log.writeImage(m_name.c_str(), m_description.c_str(), m_access, m_scale, m_bias, m_compression);
135     else
136     {
137         const ConstPixelBufferAccess depthAccess =
138             tcu::getEffectiveDepthStencilAccess(m_access, tcu::Sampler::MODE_DEPTH);
139         const ConstPixelBufferAccess stencilAccess =
140             tcu::getEffectiveDepthStencilAccess(m_access, tcu::Sampler::MODE_STENCIL);
141 
142         log.startImageSet(m_name.c_str(), m_description.c_str());
143         log.writeImage("Depth", "Depth channel", depthAccess, m_scale.swizzle(0, 0, 0, 0), m_bias.swizzle(0, 0, 0, 0),
144                        m_compression);
145         log.writeImage("Stencil", "Stencil channel", stencilAccess, m_scale.swizzle(1, 1, 1, 1),
146                        m_bias.swizzle(1, 1, 1, 1), m_compression);
147         log.endImageSet();
148     }
149 }
150 
151 // MessageBuilder
152 
MessageBuilder(const MessageBuilder & other)153 MessageBuilder::MessageBuilder(const MessageBuilder &other) : m_log(other.m_log)
154 {
155     m_str.str(other.m_str.str());
156 }
157 
operator =(const MessageBuilder & other)158 MessageBuilder &MessageBuilder::operator=(const MessageBuilder &other)
159 {
160     m_log = other.m_log;
161     m_str.str(other.m_str.str());
162     return *this;
163 }
164 
operator <<(const TestLog::EndMessageToken &)165 TestLog &MessageBuilder::operator<<(const TestLog::EndMessageToken &)
166 {
167     m_log->writeMessage(m_str.str().c_str());
168     return *m_log;
169 }
170 
171 // SampleBuilder
172 
operator <<(const TestLog::EndSampleToken &)173 TestLog &SampleBuilder::operator<<(const TestLog::EndSampleToken &)
174 {
175     m_log->startSample();
176 
177     for (std::vector<Value>::const_iterator val = m_values.begin(); val != m_values.end(); ++val)
178     {
179         if (val->type == Value::TYPE_FLOAT64)
180             m_log->writeSampleValue(val->value.float64);
181         else if (val->type == Value::TYPE_INT64)
182             m_log->writeSampleValue(val->value.int64);
183         else
184             DE_ASSERT(false);
185     }
186 
187     m_log->endSample();
188 
189     return *m_log;
190 }
191 
192 // TestLog
193 
TestLog(const char * fileName,uint32_t flags)194 TestLog::TestLog(const char *fileName, uint32_t flags)
195     : m_log(qpTestLog_createFileLog(fileName, flags))
196     , m_logSupressed(false)
197 {
198     if (!m_log)
199         throw ResourceError(std::string("Failed to open test log file '") + fileName + "'");
200 }
201 
writeSessionInfo(std::string additionalInfo)202 void TestLog::writeSessionInfo(std::string additionalInfo)
203 {
204     qpTestLog_beginSession(m_log, additionalInfo.c_str());
205 }
206 
~TestLog(void)207 TestLog::~TestLog(void)
208 {
209     qpTestLog_destroy(m_log);
210 }
211 
writeMessage(const char * msgStr)212 void TestLog::writeMessage(const char *msgStr)
213 {
214     if (m_logSupressed)
215         return;
216     if (m_skipAdditionalDataInLog)
217         return;
218     if (qpTestLog_writeText(m_log, DE_NULL, DE_NULL, QP_KEY_TAG_NONE, msgStr) == false)
219         throw LogWriteFailedError();
220 }
221 
startImageSet(const char * name,const char * description)222 void TestLog::startImageSet(const char *name, const char *description)
223 {
224     if (m_logSupressed)
225         return;
226     if (m_skipAdditionalDataInLog)
227         return;
228     if (qpTestLog_startImageSet(m_log, name, description) == false)
229         throw LogWriteFailedError();
230 }
231 
endImageSet(void)232 void TestLog::endImageSet(void)
233 {
234     if (m_logSupressed)
235         return;
236     if (m_skipAdditionalDataInLog)
237         return;
238     if (qpTestLog_endImageSet(m_log) == false)
239         throw LogWriteFailedError();
240 }
241 
242 template <int Size>
computeScaledSize(const Vector<int,Size> & imageSize,int maxSize)243 static Vector<int, Size> computeScaledSize(const Vector<int, Size> &imageSize, int maxSize)
244 {
245     bool allInRange = true;
246     for (int i = 0; i < Size; i++)
247         allInRange = allInRange && (imageSize[i] <= maxSize);
248 
249     if (allInRange)
250         return imageSize;
251     else
252     {
253         float d = 1.0f;
254         for (int i = 0; i < Size; i++)
255             d = de::max(d, (float)imageSize[i] / (float)maxSize);
256 
257         Vector<int, Size> res;
258         for (int i = 0; i < Size; i++)
259             res[i] = de::max(1, deRoundFloatToInt32((float)imageSize[i] / d));
260 
261         return res;
262     }
263 }
264 
writeImage(const char * name,const char * description,const ConstPixelBufferAccess & access,const Vec4 & pixelScale,const Vec4 & pixelBias,qpImageCompressionMode compressionMode)265 void TestLog::writeImage(const char *name, const char *description, const ConstPixelBufferAccess &access,
266                          const Vec4 &pixelScale, const Vec4 &pixelBias, qpImageCompressionMode compressionMode)
267 {
268     if (m_logSupressed)
269         return;
270     if (m_skipAdditionalDataInLog)
271         return;
272     const TextureFormat &format = access.getFormat();
273     int width                   = access.getWidth();
274     int height                  = access.getHeight();
275     int depth                   = access.getDepth();
276 
277     // Writing a combined image does not make sense
278     DE_ASSERT(!tcu::isCombinedDepthStencilType(access.getFormat().type));
279 
280     // Do not bother with preprocessing if images are not stored
281     if ((qpTestLog_getLogFlags(m_log) & QP_TEST_LOG_EXCLUDE_IMAGES) != 0)
282         return;
283 
284     if (depth == 1 && (format.type == TextureFormat::UNORM_INT8 || format.type == TextureFormat::UNSIGNED_INT8) &&
285         width <= MAX_IMAGE_SIZE_2D && height <= MAX_IMAGE_SIZE_2D &&
286         (format.order == TextureFormat::RGB || format.order == TextureFormat::RGBA) &&
287         access.getPixelPitch() == access.getFormat().getPixelSize() && pixelBias[0] == 0.0f && pixelBias[1] == 0.0f &&
288         pixelBias[2] == 0.0f && pixelBias[3] == 0.0f && pixelScale[0] == 1.0f && pixelScale[1] == 1.0f &&
289         pixelScale[2] == 1.0f && pixelScale[3] == 1.0f)
290     {
291         // Fast-path.
292         bool isRGBA = format.order == TextureFormat::RGBA;
293 
294         writeImage(name, description, compressionMode, isRGBA ? QP_IMAGE_FORMAT_RGBA8888 : QP_IMAGE_FORMAT_RGB888,
295                    width, height, access.getRowPitch(), access.getDataPtr());
296     }
297     else if (depth == 1)
298     {
299         Sampler sampler(Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::LINEAR,
300                         Sampler::NEAREST);
301         IVec2 logImageSize = computeScaledSize(IVec2(width, height), MAX_IMAGE_SIZE_2D);
302         tcu::TextureLevel logImage(TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8), logImageSize.x(),
303                                    logImageSize.y(), 1);
304         PixelBufferAccess logImageAccess = logImage.getAccess();
305         std::ostringstream longDesc;
306 
307         longDesc << description << " (p' = p * " << pixelScale << " + " << pixelBias << ")";
308 
309         for (int y = 0; y < logImage.getHeight(); y++)
310         {
311             for (int x = 0; x < logImage.getWidth(); x++)
312             {
313                 float yf = ((float)y + 0.5f) / (float)logImage.getHeight();
314                 float xf = ((float)x + 0.5f) / (float)logImage.getWidth();
315                 Vec4 s   = access.sample2D(sampler, sampler.minFilter, xf, yf, 0) * pixelScale + pixelBias;
316 
317                 logImageAccess.setPixel(s, x, y);
318             }
319         }
320 
321         writeImage(name, longDesc.str().c_str(), compressionMode, QP_IMAGE_FORMAT_RGBA8888, logImageAccess.getWidth(),
322                    logImageAccess.getHeight(), logImageAccess.getRowPitch(), logImageAccess.getDataPtr());
323     }
324     else
325     {
326         // Isometric splat volume rendering.
327         const float blendFactor = 0.85f;
328         IVec3 scaledSize        = computeScaledSize(IVec3(width, height, depth), MAX_IMAGE_SIZE_3D);
329         int w                   = scaledSize.x();
330         int h                   = scaledSize.y();
331         int d                   = scaledSize.z();
332         int logImageW           = w + d - 1;
333         int logImageH           = w + d + h;
334         std::vector<float> blendImage(logImageW * logImageH * 4, 0.0f);
335         PixelBufferAccess blendImageAccess(TextureFormat(TextureFormat::RGBA, TextureFormat::FLOAT), logImageW,
336                                            logImageH, 1, &blendImage[0]);
337         tcu::TextureLevel logImage(TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8), logImageW, logImageH,
338                                    1);
339         PixelBufferAccess logImageAccess = logImage.getAccess();
340         Sampler sampler(Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::NEAREST,
341                         Sampler::NEAREST);
342         std::ostringstream longDesc;
343 
344         // \note Back-to-front.
345         for (int z = d - 1; z >= 0; z--)
346         {
347             for (int y = 0; y < h; y++)
348             {
349                 for (int x = 0; x < w; x++)
350                 {
351                     int px = w - (x + 1) + z;
352                     int py = (w + d + h) - (x + y + z + 1);
353 
354                     float xf = ((float)x + 0.5f) / (float)w;
355                     float yf = ((float)y + 0.5f) / (float)h;
356                     float zf = ((float)z + 0.5f) / (float)d;
357 
358                     Vec4 p = blendImageAccess.getPixel(px, py);
359                     Vec4 s = access.sample3D(sampler, sampler.minFilter, xf, yf, zf);
360                     Vec4 b = s + p * blendFactor;
361 
362                     blendImageAccess.setPixel(b, px, py);
363                 }
364             }
365         }
366 
367         // Scale blend image nicely.
368         longDesc << description << " (p' = p * " << pixelScale << " + " << pixelBias << ")";
369 
370         // Write to final image.
371         tcu::clear(logImageAccess, tcu::IVec4(0x33, 0x66, 0x99, 0xff));
372 
373         for (int z = 0; z < d; z++)
374         {
375             for (int y = 0; y < h; y++)
376             {
377                 for (int x = 0; x < w; x++)
378                 {
379                     if (z != 0 && !(x == 0 || y == h - 1 || y == h - 2))
380                         continue;
381 
382                     int px = w - (x + 1) + z;
383                     int py = (w + d + h) - (x + y + z + 1);
384                     Vec4 s = blendImageAccess.getPixel(px, py) * pixelScale + pixelBias;
385 
386                     logImageAccess.setPixel(s, px, py);
387                 }
388             }
389         }
390 
391         writeImage(name, longDesc.str().c_str(), compressionMode, QP_IMAGE_FORMAT_RGBA8888, logImageAccess.getWidth(),
392                    logImageAccess.getHeight(), logImageAccess.getRowPitch(), logImageAccess.getDataPtr());
393     }
394 }
395 
writeImage(const char * name,const char * description,qpImageCompressionMode compressionMode,qpImageFormat format,int width,int height,int stride,const void * data)396 void TestLog::writeImage(const char *name, const char *description, qpImageCompressionMode compressionMode,
397                          qpImageFormat format, int width, int height, int stride, const void *data)
398 {
399     if (m_logSupressed)
400         return;
401     if (m_skipAdditionalDataInLog)
402         return;
403     if (qpTestLog_writeImage(m_log, name, description, compressionMode, format, width, height, stride, data) == false)
404         throw LogWriteFailedError();
405 }
406 
startSection(const char * name,const char * description)407 void TestLog::startSection(const char *name, const char *description)
408 {
409     if (m_logSupressed)
410         return;
411     if (m_skipAdditionalDataInLog)
412         return;
413     if (qpTestLog_startSection(m_log, name, description) == false)
414         throw LogWriteFailedError();
415 }
416 
endSection(void)417 void TestLog::endSection(void)
418 {
419     if (m_logSupressed)
420         return;
421     if (m_skipAdditionalDataInLog)
422         return;
423     if (qpTestLog_endSection(m_log) == false)
424         throw LogWriteFailedError();
425 }
426 
startShaderProgram(bool linkOk,const char * linkInfoLog)427 void TestLog::startShaderProgram(bool linkOk, const char *linkInfoLog)
428 {
429     if (m_logSupressed)
430         return;
431     if (m_skipAdditionalDataInLog)
432         return;
433     if (qpTestLog_startShaderProgram(m_log, linkOk ? true : false, linkInfoLog) == false)
434         throw LogWriteFailedError();
435 }
436 
endShaderProgram(void)437 void TestLog::endShaderProgram(void)
438 {
439     if (m_logSupressed)
440         return;
441     if (m_skipAdditionalDataInLog)
442         return;
443     if (qpTestLog_endShaderProgram(m_log) == false)
444         throw LogWriteFailedError();
445 }
446 
writeShader(qpShaderType type,const char * source,bool compileOk,const char * infoLog)447 void TestLog::writeShader(qpShaderType type, const char *source, bool compileOk, const char *infoLog)
448 {
449     if (m_logSupressed)
450         return;
451     if (m_skipAdditionalDataInLog)
452         return;
453     if (qpTestLog_writeShader(m_log, type, source, compileOk ? true : false, infoLog) == false)
454         throw LogWriteFailedError();
455 }
456 
writeSpirVAssemblySource(const char * source)457 void TestLog::writeSpirVAssemblySource(const char *source)
458 {
459     if (m_logSupressed)
460         return;
461     if (m_skipAdditionalDataInLog)
462         return;
463     if (qpTestLog_writeSpirVAssemblySource(m_log, source) == false)
464         throw LogWriteFailedError();
465 }
466 
writeKernelSource(const char * source)467 void TestLog::writeKernelSource(const char *source)
468 {
469     if (m_logSupressed)
470         return;
471     if (m_skipAdditionalDataInLog)
472         return;
473     if (qpTestLog_writeKernelSource(m_log, source) == false)
474         throw LogWriteFailedError();
475 }
476 
writeCompileInfo(const char * name,const char * description,bool compileOk,const char * infoLog)477 void TestLog::writeCompileInfo(const char *name, const char *description, bool compileOk, const char *infoLog)
478 {
479     if (m_logSupressed)
480         return;
481     if (m_skipAdditionalDataInLog)
482         return;
483     if (qpTestLog_writeCompileInfo(m_log, name, description, compileOk ? true : false, infoLog) == false)
484         throw LogWriteFailedError();
485 }
486 
writeFloat(const char * name,const char * description,const char * unit,qpKeyValueTag tag,float value)487 void TestLog::writeFloat(const char *name, const char *description, const char *unit, qpKeyValueTag tag, float value)
488 {
489     if (m_logSupressed)
490         return;
491     if (m_skipAdditionalDataInLog)
492         return;
493     if (qpTestLog_writeFloat(m_log, name, description, unit, tag, value) == false)
494         throw LogWriteFailedError();
495 }
496 
writeInteger(const char * name,const char * description,const char * unit,qpKeyValueTag tag,int64_t value)497 void TestLog::writeInteger(const char *name, const char *description, const char *unit, qpKeyValueTag tag,
498                            int64_t value)
499 {
500     if (m_logSupressed)
501         return;
502     if (m_skipAdditionalDataInLog)
503         return;
504     if (qpTestLog_writeInteger(m_log, name, description, unit, tag, value) == false)
505         throw LogWriteFailedError();
506 }
507 
startEglConfigSet(const char * name,const char * description)508 void TestLog::startEglConfigSet(const char *name, const char *description)
509 {
510     if (m_logSupressed)
511         return;
512     if (qpTestLog_startEglConfigSet(m_log, name, description) == false)
513         throw LogWriteFailedError();
514 }
515 
writeEglConfig(const qpEglConfigInfo * config)516 void TestLog::writeEglConfig(const qpEglConfigInfo *config)
517 {
518     if (m_logSupressed)
519         return;
520     if (qpTestLog_writeEglConfig(m_log, config) == false)
521         throw LogWriteFailedError();
522 }
523 
endEglConfigSet(void)524 void TestLog::endEglConfigSet(void)
525 {
526     if (m_logSupressed)
527         return;
528     if (qpTestLog_endEglConfigSet(m_log) == false)
529         throw LogWriteFailedError();
530 }
531 
startCase(const char * testCasePath,qpTestCaseType testCaseType)532 void TestLog::startCase(const char *testCasePath, qpTestCaseType testCaseType)
533 {
534     if (m_logSupressed)
535         return;
536     if (qpTestLog_startCase(m_log, testCasePath, testCaseType) == false)
537         throw LogWriteFailedError();
538     // Check if the test is one of those we want to print fully in the log
539     m_skipAdditionalDataInLog = false;
540     if (qpTestLog_isCompact(m_log))
541     {
542         const std::string testCasePathStr = testCasePath;
543         if (testCasePathStr.rfind("dEQP-VK.info.") != 0 && testCasePathStr.rfind("dEQP-VK.api.info.") != 0 &&
544             testCasePathStr.rfind("dEQP-VK.api.version_check.") != 0)
545         {
546             // We can skip writing text, numbers, imagesets, etc.
547             m_skipAdditionalDataInLog = true;
548         }
549     }
550 }
551 
endCase(qpTestResult result,const char * description)552 void TestLog::endCase(qpTestResult result, const char *description)
553 {
554     if (m_logSupressed)
555         return;
556     if (qpTestLog_endCase(m_log, result, description) == false)
557         throw LogWriteFailedError();
558 }
559 
terminateCase(qpTestResult result)560 void TestLog::terminateCase(qpTestResult result)
561 {
562     if (m_logSupressed)
563         return;
564     if (qpTestLog_terminateCase(m_log, result) == false)
565         throw LogWriteFailedError();
566 }
567 
startTestsCasesTime(void)568 void TestLog::startTestsCasesTime(void)
569 {
570     if (m_logSupressed)
571         return;
572     if (qpTestLog_startTestsCasesTime(m_log) == false)
573         throw LogWriteFailedError();
574 }
575 
endTestsCasesTime(void)576 void TestLog::endTestsCasesTime(void)
577 {
578     if (m_logSupressed)
579         return;
580     if (qpTestLog_endTestsCasesTime(m_log) == false)
581         throw LogWriteFailedError();
582 }
583 
startSampleList(const std::string & name,const std::string & description)584 void TestLog::startSampleList(const std::string &name, const std::string &description)
585 {
586     if (m_logSupressed)
587         return;
588     if (qpTestLog_startSampleList(m_log, name.c_str(), description.c_str()) == false)
589         throw LogWriteFailedError();
590 }
591 
startSampleInfo(void)592 void TestLog::startSampleInfo(void)
593 {
594     if (m_logSupressed)
595         return;
596     if (qpTestLog_startSampleInfo(m_log) == false)
597         throw LogWriteFailedError();
598 }
599 
writeValueInfo(const std::string & name,const std::string & description,const std::string & unit,qpSampleValueTag tag)600 void TestLog::writeValueInfo(const std::string &name, const std::string &description, const std::string &unit,
601                              qpSampleValueTag tag)
602 {
603     if (m_logSupressed)
604         return;
605     if (qpTestLog_writeValueInfo(m_log, name.c_str(), description.c_str(), unit.empty() ? DE_NULL : unit.c_str(),
606                                  tag) == false)
607         throw LogWriteFailedError();
608 }
609 
endSampleInfo(void)610 void TestLog::endSampleInfo(void)
611 {
612     if (m_logSupressed)
613         return;
614     if (qpTestLog_endSampleInfo(m_log) == false)
615         throw LogWriteFailedError();
616 }
617 
startSample(void)618 void TestLog::startSample(void)
619 {
620     if (m_logSupressed)
621         return;
622     if (qpTestLog_startSample(m_log) == false)
623         throw LogWriteFailedError();
624 }
625 
writeSampleValue(double value)626 void TestLog::writeSampleValue(double value)
627 {
628     if (m_logSupressed)
629         return;
630     if (qpTestLog_writeValueFloat(m_log, value) == false)
631         throw LogWriteFailedError();
632 }
633 
writeSampleValue(int64_t value)634 void TestLog::writeSampleValue(int64_t value)
635 {
636     if (m_logSupressed)
637         return;
638     if (qpTestLog_writeValueInteger(m_log, value) == false)
639         throw LogWriteFailedError();
640 }
641 
endSample(void)642 void TestLog::endSample(void)
643 {
644     if (m_logSupressed)
645         return;
646     if (qpTestLog_endSample(m_log) == false)
647         throw LogWriteFailedError();
648 }
649 
endSampleList(void)650 void TestLog::endSampleList(void)
651 {
652     if (m_logSupressed)
653         return;
654     if (qpTestLog_endSampleList(m_log) == false)
655         throw LogWriteFailedError();
656 }
657 
writeRaw(const char * rawContents)658 void TestLog::writeRaw(const char *rawContents)
659 {
660     if (m_logSupressed)
661         return;
662     qpTestLog_writeRaw(m_log, rawContents);
663 }
664 
isShaderLoggingEnabled(void)665 bool TestLog::isShaderLoggingEnabled(void)
666 {
667     return (qpTestLog_getLogFlags(m_log) & QP_TEST_LOG_EXCLUDE_SHADER_SOURCES) == 0;
668 }
669 
supressLogging(bool value)670 void TestLog::supressLogging(bool value)
671 {
672     m_logSupressed = value;
673 }
674 
isSupressLogging(void)675 bool TestLog::isSupressLogging(void)
676 {
677     return m_logSupressed;
678 }
679 
680 const TestLog::BeginMessageToken TestLog::Message              = TestLog::BeginMessageToken();
681 const TestLog::EndMessageToken TestLog::EndMessage             = TestLog::EndMessageToken();
682 const TestLog::EndImageSetToken TestLog::EndImageSet           = TestLog::EndImageSetToken();
683 const TestLog::EndSectionToken TestLog::EndSection             = TestLog::EndSectionToken();
684 const TestLog::EndShaderProgramToken TestLog::EndShaderProgram = TestLog::EndShaderProgramToken();
685 const TestLog::SampleInfoToken TestLog::SampleInfo             = TestLog::SampleInfoToken();
686 const TestLog::EndSampleInfoToken TestLog::EndSampleInfo       = TestLog::EndSampleInfoToken();
687 const TestLog::BeginSampleToken TestLog::Sample                = TestLog::BeginSampleToken();
688 const TestLog::EndSampleToken TestLog::EndSample               = TestLog::EndSampleToken();
689 const TestLog::EndSampleListToken TestLog::EndSampleList       = TestLog::EndSampleListToken();
690 
691 } // namespace tcu
692