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