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