You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
551 lines
17 KiB
551 lines
17 KiB
/*-------------------------------------------------------------------------
|
|
* drawElements Quality Program Tester Core
|
|
* ----------------------------------------
|
|
*
|
|
* Copyright 2014 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
*//*!
|
|
* \file
|
|
* \brief Test Log C++ Wrapper.
|
|
*//*--------------------------------------------------------------------*/
|
|
|
|
#include "deCommandLine.h"
|
|
#include "tcuTestLog.hpp"
|
|
#include "tcuTextureUtil.hpp"
|
|
#include "tcuSurface.hpp"
|
|
#include "deMath.h"
|
|
|
|
#include <limits>
|
|
|
|
namespace tcu
|
|
{
|
|
|
|
class LogWriteFailedError : public ResourceError
|
|
{
|
|
public:
|
|
LogWriteFailedError (void) : ResourceError("Writing to test log failed") {}
|
|
};
|
|
|
|
enum
|
|
{
|
|
MAX_IMAGE_SIZE_2D = 4096,
|
|
MAX_IMAGE_SIZE_3D = 128
|
|
};
|
|
|
|
// LogImage
|
|
|
|
LogImage::LogImage (const std::string& name, const std::string& description, const Surface& surface, qpImageCompressionMode compression)
|
|
: m_name (name)
|
|
, m_description (description)
|
|
, m_access (surface.getAccess())
|
|
, m_scale (1.0f, 1.0f, 1.0f, 1.0f)
|
|
, m_bias (0.0f, 0.0f, 0.0f, 0.0f)
|
|
, m_compression (compression)
|
|
{
|
|
}
|
|
|
|
LogImage::LogImage (const std::string& name, const std::string& description, const ConstPixelBufferAccess& access, qpImageCompressionMode compression)
|
|
: m_name (name)
|
|
, m_description (description)
|
|
, m_access (access)
|
|
, m_scale (1.0f, 1.0f, 1.0f, 1.0f)
|
|
, m_bias (0.0f, 0.0f, 0.0f, 0.0f)
|
|
, m_compression (compression)
|
|
{
|
|
// Simplify combined formats that only use a single channel
|
|
if (tcu::isCombinedDepthStencilType(m_access.getFormat().type))
|
|
{
|
|
if (m_access.getFormat().order == tcu::TextureFormat::D)
|
|
m_access = tcu::getEffectiveDepthStencilAccess(m_access, tcu::Sampler::MODE_DEPTH);
|
|
else if (m_access.getFormat().order == tcu::TextureFormat::S)
|
|
m_access = tcu::getEffectiveDepthStencilAccess(m_access, tcu::Sampler::MODE_STENCIL);
|
|
}
|
|
|
|
// Implicit scale and bias
|
|
if (m_access.getFormat().order != tcu::TextureFormat::DS)
|
|
computePixelScaleBias(m_access, m_scale, m_bias);
|
|
else
|
|
{
|
|
// Pack D and S bias and scale to R and G
|
|
const ConstPixelBufferAccess depthAccess = tcu::getEffectiveDepthStencilAccess(m_access, tcu::Sampler::MODE_DEPTH);
|
|
const ConstPixelBufferAccess stencilAccess = tcu::getEffectiveDepthStencilAccess(m_access, tcu::Sampler::MODE_STENCIL);
|
|
tcu::Vec4 depthScale;
|
|
tcu::Vec4 depthBias;
|
|
tcu::Vec4 stencilScale;
|
|
tcu::Vec4 stencilBias;
|
|
|
|
computePixelScaleBias(depthAccess, depthScale, depthBias);
|
|
computePixelScaleBias(stencilAccess, stencilScale, stencilBias);
|
|
|
|
m_scale = tcu::Vec4(depthScale.x(), stencilScale.x(), 0.0f, 0.0f);
|
|
m_bias = tcu::Vec4(depthBias.x(), stencilBias.x(), 0.0f, 0.0f);
|
|
}
|
|
}
|
|
|
|
LogImage::LogImage (const std::string& name, const std::string& description, const ConstPixelBufferAccess& access, const Vec4& scale, const Vec4& bias, qpImageCompressionMode compression)
|
|
: m_name (name)
|
|
, m_description (description)
|
|
, m_access (access)
|
|
, m_scale (scale)
|
|
, m_bias (bias)
|
|
, m_compression (compression)
|
|
{
|
|
// Cannot set scale and bias of combined formats
|
|
DE_ASSERT(access.getFormat().order != tcu::TextureFormat::DS);
|
|
|
|
// Simplify access
|
|
if (tcu::isCombinedDepthStencilType(access.getFormat().type))
|
|
{
|
|
if (access.getFormat().order == tcu::TextureFormat::D)
|
|
m_access = tcu::getEffectiveDepthStencilAccess(access, tcu::Sampler::MODE_DEPTH);
|
|
if (access.getFormat().order == tcu::TextureFormat::S)
|
|
m_access = tcu::getEffectiveDepthStencilAccess(access, tcu::Sampler::MODE_STENCIL);
|
|
else
|
|
{
|
|
// Cannot log a DS format
|
|
DE_ASSERT(false);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void LogImage::write (TestLog& log) const
|
|
{
|
|
if (m_access.getFormat().order != tcu::TextureFormat::DS)
|
|
log.writeImage(m_name.c_str(), m_description.c_str(), m_access, m_scale, m_bias, m_compression);
|
|
else
|
|
{
|
|
const ConstPixelBufferAccess depthAccess = tcu::getEffectiveDepthStencilAccess(m_access, tcu::Sampler::MODE_DEPTH);
|
|
const ConstPixelBufferAccess stencilAccess = tcu::getEffectiveDepthStencilAccess(m_access, tcu::Sampler::MODE_STENCIL);
|
|
|
|
log.startImageSet(m_name.c_str(), m_description.c_str());
|
|
log.writeImage("Depth", "Depth channel", depthAccess, m_scale.swizzle(0, 0, 0, 0), m_bias.swizzle(0, 0, 0, 0), m_compression);
|
|
log.writeImage("Stencil", "Stencil channel", stencilAccess, m_scale.swizzle(1, 1, 1, 1), m_bias.swizzle(1, 1, 1, 1), m_compression);
|
|
log.endImageSet();
|
|
}
|
|
}
|
|
|
|
// MessageBuilder
|
|
|
|
MessageBuilder::MessageBuilder (const MessageBuilder& other)
|
|
: m_log(other.m_log)
|
|
{
|
|
m_str.str(other.m_str.str());
|
|
}
|
|
|
|
MessageBuilder& MessageBuilder::operator= (const MessageBuilder& other)
|
|
{
|
|
m_log = other.m_log;
|
|
m_str.str(other.m_str.str());
|
|
return *this;
|
|
}
|
|
|
|
TestLog& MessageBuilder::operator<< (const TestLog::EndMessageToken&)
|
|
{
|
|
m_log->writeMessage(m_str.str().c_str());
|
|
return *m_log;
|
|
}
|
|
|
|
// SampleBuilder
|
|
|
|
TestLog& SampleBuilder::operator<< (const TestLog::EndSampleToken&)
|
|
{
|
|
m_log->startSample();
|
|
|
|
for (std::vector<Value>::const_iterator val = m_values.begin(); val != m_values.end(); ++val)
|
|
{
|
|
if (val->type == Value::TYPE_FLOAT64)
|
|
m_log->writeSampleValue(val->value.float64);
|
|
else if (val->type == Value::TYPE_INT64)
|
|
m_log->writeSampleValue(val->value.int64);
|
|
else
|
|
DE_ASSERT(false);
|
|
}
|
|
|
|
m_log->endSample();
|
|
|
|
return *m_log;
|
|
}
|
|
|
|
// TestLog
|
|
|
|
TestLog::TestLog (const char* fileName, deUint32 flags)
|
|
: m_log(qpTestLog_createFileLog(fileName, flags))
|
|
{
|
|
if (!m_log)
|
|
throw ResourceError(std::string("Failed to open test log file '") + fileName + "'");
|
|
}
|
|
|
|
void TestLog::writeSessionInfo(std::string additionalInfo)
|
|
{
|
|
qpTestLog_beginSession(m_log, additionalInfo.c_str());
|
|
}
|
|
|
|
TestLog::~TestLog (void)
|
|
{
|
|
qpTestLog_destroy(m_log);
|
|
}
|
|
|
|
void TestLog::writeMessage (const char* msgStr)
|
|
{
|
|
if (qpTestLog_writeText(m_log, DE_NULL, DE_NULL, QP_KEY_TAG_NONE, msgStr) == DE_FALSE)
|
|
throw LogWriteFailedError();
|
|
}
|
|
|
|
void TestLog::startImageSet (const char* name, const char* description)
|
|
{
|
|
if (qpTestLog_startImageSet(m_log, name, description) == DE_FALSE)
|
|
throw LogWriteFailedError();
|
|
}
|
|
|
|
void TestLog::endImageSet (void)
|
|
{
|
|
if (qpTestLog_endImageSet(m_log) == DE_FALSE)
|
|
throw LogWriteFailedError();
|
|
}
|
|
|
|
template <int Size>
|
|
static Vector<int, Size> computeScaledSize (const Vector<int, Size>& imageSize, int maxSize)
|
|
{
|
|
bool allInRange = true;
|
|
for (int i = 0; i < Size; i++)
|
|
allInRange = allInRange && (imageSize[i] <= maxSize);
|
|
|
|
if (allInRange)
|
|
return imageSize;
|
|
else
|
|
{
|
|
float d = 1.0f;
|
|
for (int i = 0; i < Size; i++)
|
|
d = de::max(d, (float)imageSize[i] / (float)maxSize);
|
|
|
|
Vector<int, Size> res;
|
|
for (int i = 0; i < Size; i++)
|
|
res[i] = de::max(1, deRoundFloatToInt32((float)imageSize[i] / d));
|
|
|
|
return res;
|
|
}
|
|
}
|
|
|
|
void TestLog::writeImage (const char* name, const char* description, const ConstPixelBufferAccess& access, const Vec4& pixelScale, const Vec4& pixelBias, qpImageCompressionMode compressionMode)
|
|
{
|
|
const TextureFormat& format = access.getFormat();
|
|
int width = access.getWidth();
|
|
int height = access.getHeight();
|
|
int depth = access.getDepth();
|
|
|
|
// Writing a combined image does not make sense
|
|
DE_ASSERT(!tcu::isCombinedDepthStencilType(access.getFormat().type));
|
|
|
|
// Do not bother with preprocessing if images are not stored
|
|
if ((qpTestLog_getLogFlags(m_log) & QP_TEST_LOG_EXCLUDE_IMAGES) != 0)
|
|
return;
|
|
|
|
if (depth == 1 && format.type == TextureFormat::UNORM_INT8
|
|
&& width <= MAX_IMAGE_SIZE_2D && height <= MAX_IMAGE_SIZE_2D
|
|
&& (format.order == TextureFormat::RGB || format.order == TextureFormat::RGBA)
|
|
&& access.getPixelPitch() == access.getFormat().getPixelSize()
|
|
&& pixelBias[0] == 0.0f && pixelBias[1] == 0.0f && pixelBias[2] == 0.0f && pixelBias[3] == 0.0f
|
|
&& pixelScale[0] == 1.0f && pixelScale[1] == 1.0f && pixelScale[2] == 1.0f && pixelScale[3] == 1.0f)
|
|
{
|
|
// Fast-path.
|
|
bool isRGBA = format.order == TextureFormat::RGBA;
|
|
|
|
writeImage(name, description, compressionMode,
|
|
isRGBA ? QP_IMAGE_FORMAT_RGBA8888 : QP_IMAGE_FORMAT_RGB888,
|
|
width, height, access.getRowPitch(), access.getDataPtr());
|
|
}
|
|
else if (depth == 1)
|
|
{
|
|
Sampler sampler (Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::LINEAR, Sampler::NEAREST);
|
|
IVec2 logImageSize = computeScaledSize(IVec2(width, height), MAX_IMAGE_SIZE_2D);
|
|
tcu::TextureLevel logImage (TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8), logImageSize.x(), logImageSize.y(), 1);
|
|
PixelBufferAccess logImageAccess = logImage.getAccess();
|
|
std::ostringstream longDesc;
|
|
|
|
longDesc << description << " (p' = p * " << pixelScale << " + " << pixelBias << ")";
|
|
|
|
for (int y = 0; y < logImage.getHeight(); y++)
|
|
{
|
|
for (int x = 0; x < logImage.getWidth(); x++)
|
|
{
|
|
float yf = ((float)y + 0.5f) / (float)logImage.getHeight();
|
|
float xf = ((float)x + 0.5f) / (float)logImage.getWidth();
|
|
Vec4 s = access.sample2D(sampler, sampler.minFilter, xf, yf, 0)*pixelScale + pixelBias;
|
|
|
|
logImageAccess.setPixel(s, x, y);
|
|
}
|
|
}
|
|
|
|
writeImage(name, longDesc.str().c_str(), compressionMode, QP_IMAGE_FORMAT_RGBA8888,
|
|
logImageAccess.getWidth(), logImageAccess.getHeight(), logImageAccess.getRowPitch(),
|
|
logImageAccess.getDataPtr());
|
|
}
|
|
else
|
|
{
|
|
// Isometric splat volume rendering.
|
|
const float blendFactor = 0.85f;
|
|
IVec3 scaledSize = computeScaledSize(IVec3(width, height, depth), MAX_IMAGE_SIZE_3D);
|
|
int w = scaledSize.x();
|
|
int h = scaledSize.y();
|
|
int d = scaledSize.z();
|
|
int logImageW = w+d - 1;
|
|
int logImageH = w+d+h;
|
|
std::vector<float> blendImage (logImageW*logImageH*4, 0.0f);
|
|
PixelBufferAccess blendImageAccess (TextureFormat(TextureFormat::RGBA, TextureFormat::FLOAT), logImageW, logImageH, 1, &blendImage[0]);
|
|
tcu::TextureLevel logImage (TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8), logImageW, logImageH, 1);
|
|
PixelBufferAccess logImageAccess = logImage.getAccess();
|
|
Sampler sampler (Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::NEAREST, Sampler::NEAREST);
|
|
std::ostringstream longDesc;
|
|
|
|
// \note Back-to-front.
|
|
for (int z = d-1; z >= 0; z--)
|
|
{
|
|
for (int y = 0; y < h; y++)
|
|
{
|
|
for (int x = 0; x < w; x++)
|
|
{
|
|
int px = w - (x + 1) + z;
|
|
int py = (w + d + h) - (x + y + z + 1);
|
|
|
|
float xf = ((float)x + 0.5f) / (float)w;
|
|
float yf = ((float)y + 0.5f) / (float)h;
|
|
float zf = ((float)z + 0.5f) / (float)d;
|
|
|
|
Vec4 p = blendImageAccess.getPixel(px, py);
|
|
Vec4 s = access.sample3D(sampler, sampler.minFilter, xf, yf, zf);
|
|
Vec4 b = s + p*blendFactor;
|
|
|
|
blendImageAccess.setPixel(b, px, py);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Scale blend image nicely.
|
|
longDesc << description << " (p' = p * " << pixelScale << " + " << pixelBias << ")";
|
|
|
|
// Write to final image.
|
|
tcu::clear(logImageAccess, tcu::IVec4(0x33, 0x66, 0x99, 0xff));
|
|
|
|
for (int z = 0; z < d; z++)
|
|
{
|
|
for (int y = 0; y < h; y++)
|
|
{
|
|
for (int x = 0; x < w; x++)
|
|
{
|
|
if (z != 0 && !(x == 0 || y == h-1 || y == h-2))
|
|
continue;
|
|
|
|
int px = w - (x + 1) + z;
|
|
int py = (w + d + h) - (x + y + z + 1);
|
|
Vec4 s = blendImageAccess.getPixel(px, py)*pixelScale + pixelBias;
|
|
|
|
logImageAccess.setPixel(s, px, py);
|
|
}
|
|
}
|
|
}
|
|
|
|
writeImage(name, longDesc.str().c_str(), compressionMode, QP_IMAGE_FORMAT_RGBA8888,
|
|
logImageAccess.getWidth(), logImageAccess.getHeight(), logImageAccess.getRowPitch(),
|
|
logImageAccess.getDataPtr());
|
|
}
|
|
}
|
|
|
|
void TestLog::writeImage (const char* name, const char* description, qpImageCompressionMode compressionMode, qpImageFormat format, int width, int height, int stride, const void* data)
|
|
{
|
|
if (qpTestLog_writeImage(m_log, name, description, compressionMode, format, width, height, stride, data) == DE_FALSE)
|
|
throw LogWriteFailedError();
|
|
}
|
|
|
|
void TestLog::startSection (const char* name, const char* description)
|
|
{
|
|
if (qpTestLog_startSection(m_log, name, description) == DE_FALSE)
|
|
throw LogWriteFailedError();
|
|
}
|
|
|
|
void TestLog::endSection (void)
|
|
{
|
|
if (qpTestLog_endSection(m_log) == DE_FALSE)
|
|
throw LogWriteFailedError();
|
|
}
|
|
|
|
void TestLog::startShaderProgram (bool linkOk, const char* linkInfoLog)
|
|
{
|
|
if (qpTestLog_startShaderProgram(m_log, linkOk?DE_TRUE:DE_FALSE, linkInfoLog) == DE_FALSE)
|
|
throw LogWriteFailedError();
|
|
}
|
|
|
|
void TestLog::endShaderProgram (void)
|
|
{
|
|
if (qpTestLog_endShaderProgram(m_log) == DE_FALSE)
|
|
throw LogWriteFailedError();
|
|
}
|
|
|
|
void TestLog::writeShader (qpShaderType type, const char* source, bool compileOk, const char* infoLog)
|
|
{
|
|
if (qpTestLog_writeShader(m_log, type, source, compileOk?DE_TRUE:DE_FALSE, infoLog) == DE_FALSE)
|
|
throw LogWriteFailedError();
|
|
}
|
|
|
|
void TestLog::writeSpirVAssemblySource (const char* source)
|
|
{
|
|
if (qpTestLog_writeSpirVAssemblySource(m_log, source) == DE_FALSE)
|
|
throw LogWriteFailedError();
|
|
}
|
|
|
|
void TestLog::writeKernelSource (const char* source)
|
|
{
|
|
if (qpTestLog_writeKernelSource(m_log, source) == DE_FALSE)
|
|
throw LogWriteFailedError();
|
|
}
|
|
|
|
void TestLog::writeCompileInfo (const char* name, const char* description, bool compileOk, const char* infoLog)
|
|
{
|
|
if (qpTestLog_writeCompileInfo(m_log, name, description, compileOk ? DE_TRUE : DE_FALSE, infoLog) == DE_FALSE)
|
|
throw LogWriteFailedError();
|
|
}
|
|
|
|
void TestLog::writeFloat (const char* name, const char* description, const char* unit, qpKeyValueTag tag, float value)
|
|
{
|
|
if (qpTestLog_writeFloat(m_log, name, description, unit, tag, value) == DE_FALSE)
|
|
throw LogWriteFailedError();
|
|
}
|
|
|
|
void TestLog::writeInteger (const char* name, const char* description, const char* unit, qpKeyValueTag tag, deInt64 value)
|
|
{
|
|
if (qpTestLog_writeInteger(m_log, name, description, unit, tag, value) == DE_FALSE)
|
|
throw LogWriteFailedError();
|
|
}
|
|
|
|
void TestLog::startEglConfigSet (const char* name, const char* description)
|
|
{
|
|
if (qpTestLog_startEglConfigSet(m_log, name, description) == DE_FALSE)
|
|
throw LogWriteFailedError();
|
|
}
|
|
|
|
void TestLog::writeEglConfig (const qpEglConfigInfo* config)
|
|
{
|
|
if (qpTestLog_writeEglConfig(m_log, config) == DE_FALSE)
|
|
throw LogWriteFailedError();
|
|
}
|
|
|
|
void TestLog::endEglConfigSet (void)
|
|
{
|
|
if (qpTestLog_endEglConfigSet(m_log) == DE_FALSE)
|
|
throw LogWriteFailedError();
|
|
}
|
|
|
|
void TestLog::startCase (const char* testCasePath, qpTestCaseType testCaseType)
|
|
{
|
|
if (qpTestLog_startCase(m_log, testCasePath, testCaseType) == DE_FALSE)
|
|
throw LogWriteFailedError();
|
|
}
|
|
|
|
void TestLog::endCase (qpTestResult result, const char* description)
|
|
{
|
|
if (qpTestLog_endCase(m_log, result, description) == DE_FALSE)
|
|
throw LogWriteFailedError();
|
|
}
|
|
|
|
void TestLog::terminateCase (qpTestResult result)
|
|
{
|
|
if (qpTestLog_terminateCase(m_log, result) == DE_FALSE)
|
|
throw LogWriteFailedError();
|
|
}
|
|
|
|
void TestLog::startTestsCasesTime (void)
|
|
{
|
|
if (qpTestLog_startTestsCasesTime(m_log) == DE_FALSE)
|
|
throw LogWriteFailedError();
|
|
}
|
|
|
|
void TestLog::endTestsCasesTime (void)
|
|
{
|
|
if (qpTestLog_endTestsCasesTime(m_log) == DE_FALSE)
|
|
throw LogWriteFailedError();
|
|
}
|
|
|
|
void TestLog::startSampleList (const std::string& name, const std::string& description)
|
|
{
|
|
if (qpTestLog_startSampleList(m_log, name.c_str(), description.c_str()) == DE_FALSE)
|
|
throw LogWriteFailedError();
|
|
}
|
|
|
|
void TestLog::startSampleInfo (void)
|
|
{
|
|
if (qpTestLog_startSampleInfo(m_log) == DE_FALSE)
|
|
throw LogWriteFailedError();
|
|
}
|
|
|
|
void TestLog::writeValueInfo (const std::string& name, const std::string& description, const std::string& unit, qpSampleValueTag tag)
|
|
{
|
|
if (qpTestLog_writeValueInfo(m_log, name.c_str(), description.c_str(), unit.empty() ? DE_NULL : unit.c_str(), tag) == DE_FALSE)
|
|
throw LogWriteFailedError();
|
|
}
|
|
|
|
void TestLog::endSampleInfo (void)
|
|
{
|
|
if (qpTestLog_endSampleInfo(m_log) == DE_FALSE)
|
|
throw LogWriteFailedError();
|
|
}
|
|
|
|
void TestLog::startSample (void)
|
|
{
|
|
if (qpTestLog_startSample(m_log) == DE_FALSE)
|
|
throw LogWriteFailedError();
|
|
}
|
|
|
|
void TestLog::writeSampleValue (double value)
|
|
{
|
|
if (qpTestLog_writeValueFloat(m_log, value) == DE_FALSE)
|
|
throw LogWriteFailedError();
|
|
}
|
|
|
|
void TestLog::writeSampleValue (deInt64 value)
|
|
{
|
|
if (qpTestLog_writeValueInteger(m_log, value) == DE_FALSE)
|
|
throw LogWriteFailedError();
|
|
}
|
|
|
|
void TestLog::endSample (void)
|
|
{
|
|
if (qpTestLog_endSample(m_log) == DE_FALSE)
|
|
throw LogWriteFailedError();
|
|
}
|
|
|
|
void TestLog::endSampleList (void)
|
|
{
|
|
if (qpTestLog_endSampleList(m_log) == DE_FALSE)
|
|
throw LogWriteFailedError();
|
|
}
|
|
|
|
bool TestLog::isShaderLoggingEnabled (void)
|
|
{
|
|
return (qpTestLog_getLogFlags(m_log) & QP_TEST_LOG_EXCLUDE_SHADER_SOURCES) == 0;
|
|
}
|
|
|
|
const TestLog::BeginMessageToken TestLog::Message = TestLog::BeginMessageToken();
|
|
const TestLog::EndMessageToken TestLog::EndMessage = TestLog::EndMessageToken();
|
|
const TestLog::EndImageSetToken TestLog::EndImageSet = TestLog::EndImageSetToken();
|
|
const TestLog::EndSectionToken TestLog::EndSection = TestLog::EndSectionToken();
|
|
const TestLog::EndShaderProgramToken TestLog::EndShaderProgram = TestLog::EndShaderProgramToken();
|
|
const TestLog::SampleInfoToken TestLog::SampleInfo = TestLog::SampleInfoToken();
|
|
const TestLog::EndSampleInfoToken TestLog::EndSampleInfo = TestLog::EndSampleInfoToken();
|
|
const TestLog::BeginSampleToken TestLog::Sample = TestLog::BeginSampleToken();
|
|
const TestLog::EndSampleToken TestLog::EndSample = TestLog::EndSampleToken();
|
|
const TestLog::EndSampleListToken TestLog::EndSampleList = TestLog::EndSampleListToken();
|
|
|
|
} // tcu
|