Create a new logger class for all messages w.r.t. SPIR-V build.

This commit is contained in:
Lei Zhang 2016-05-04 15:55:59 -04:00
parent 09caf12bec
commit 17535f7d55
10 changed files with 184 additions and 61 deletions

View File

@ -1,6 +1,7 @@
set(SOURCES
GlslangToSpv.cpp
InReadableOrder.cpp
Logger.cpp
SpvBuilder.cpp
SPVRemapper.cpp
doc.cpp
@ -10,6 +11,7 @@ set(HEADERS
spirv.hpp
GLSL.std.450.h
GlslangToSpv.h
Logger.h
SpvBuilder.h
SPVRemapper.h
spvIR.h

View File

@ -52,12 +52,12 @@ namespace spv {
#include "../glslang/MachineIndependent/SymbolTable.h"
#include "../glslang/Include/Common.h"
#include <string>
#include <map>
#include <list>
#include <vector>
#include <stack>
#include <fstream>
#include <list>
#include <map>
#include <stack>
#include <string>
#include <vector>
namespace {
@ -94,7 +94,7 @@ private:
//
class TGlslangToSpvTraverser : public glslang::TIntermTraverser {
public:
TGlslangToSpvTraverser(const glslang::TIntermediate*);
TGlslangToSpvTraverser(const glslang::TIntermediate*, spv::SpvBuildLogger* logger);
virtual ~TGlslangToSpvTraverser();
bool visitAggregate(glslang::TVisit, glslang::TIntermAggregate*);
@ -109,8 +109,6 @@ public:
void dumpSpv(std::vector<unsigned int>& out);
std::string getWarningsAndErrors() const { return warningsErrors.str(); }
protected:
spv::Decoration TranslateInterpolationDecoration(const glslang::TQualifier& qualifier);
spv::BuiltIn TranslateBuiltInDecoration(glslang::TBuiltInVariable);
@ -161,7 +159,7 @@ protected:
spv::Instruction* entryPoint;
int sequenceDepth;
std::ostringstream warningsErrors;
spv::SpvBuildLogger* logger;
// There is a 1:1 mapping between a spv builder and a module; this is thread safe
spv::Builder builder;
@ -437,7 +435,7 @@ spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltI
case glslang::EbvBaseInstance:
case glslang::EbvDrawId:
// TODO: Add SPIR-V builtin ID.
spv::MissingFunctionality(warningsErrors, "Draw parameters");
logger->missingFunctionality("Draw parameters");
return (spv::BuiltIn)spv::BadValue;
case glslang::EbvPrimitiveId: return spv::BuiltInPrimitiveId;
case glslang::EbvInvocationId: return spv::BuiltInInvocationId;
@ -610,9 +608,9 @@ bool HasNonLayoutQualifiers(const glslang::TQualifier& qualifier)
// Implement the TGlslangToSpvTraverser class.
//
TGlslangToSpvTraverser::TGlslangToSpvTraverser(const glslang::TIntermediate* glslangIntermediate)
: TIntermTraverser(true, false, true), shaderEntry(0), sequenceDepth(0),
builder((glslang::GetKhronosToolId() << 16) | GeneratorVersion, warningsErrors),
TGlslangToSpvTraverser::TGlslangToSpvTraverser(const glslang::TIntermediate* glslangIntermediate, spv::SpvBuildLogger* buildLogger)
: TIntermTraverser(true, false, true), shaderEntry(0), sequenceDepth(0), logger(buildLogger),
builder((glslang::GetKhronosToolId() << 16) | GeneratorVersion, logger),
inMain(false), mainTerminated(false), linkageOnly(false),
glslangIntermediate(glslangIntermediate)
{
@ -988,7 +986,7 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
builder.clearAccessChain();
if (! result) {
spv::MissingFunctionality(warningsErrors, "unknown glslang binary operation");
logger->missingFunctionality("unknown glslang binary operation");
return true; // pick up a child as the place-holder result
} else {
builder.setAccessChainRValue(result);
@ -1113,7 +1111,7 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI
return false;
default:
spv::MissingFunctionality(warningsErrors, "unknown glslang unary");
logger->missingFunctionality("unknown glslang unary");
return true; // pick up operand as placeholder result
}
}
@ -1224,7 +1222,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
builder.clearAccessChain();
builder.setAccessChainRValue(result);
} else
spv::MissingFunctionality(warningsErrors, "missing user function; linker needs to catch that");
logger->missingFunctionality("missing user function; linker needs to catch that");
return false;
}
@ -1472,7 +1470,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
return false;
if (! result) {
spv::MissingFunctionality(warningsErrors, "unknown glslang aggregate");
logger->missingFunctionality("unknown glslang aggregate");
return true; // pick up a child as a placeholder operand
} else {
builder.clearAccessChain();
@ -1765,7 +1763,7 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
spvType = builder.makeUintType(64);
break;
case glslang::EbtAtomicUint:
spv::TbdFunctionality(warningsErrors, "Is atomic_uint an opaque handle in the uniform storage class, or an addresses in the atomic storage class?");
logger->tbdFunctionality("Is atomic_uint an opaque handle in the uniform storage class, or an addresses in the atomic storage class?");
spvType = builder.makeUintType(32);
break;
case glslang::EbtSampler:
@ -3151,7 +3149,7 @@ spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, spv:
case glslang::EOpUnpackInt2x32:
case glslang::EOpPackUint2x32:
case glslang::EOpUnpackUint2x32:
spv::MissingFunctionality(warningsErrors, "shader int64");
logger->missingFunctionality("shader int64");
libCall = spv::GLSLstd450Bad; // TODO: This is a placeholder.
break;
@ -3782,7 +3780,7 @@ spv::Id TGlslangToSpvTraverser::createNoArgOperation(glslang::TOperator op)
builder.createMemoryBarrier(spv::ScopeDevice, spv::MemorySemanticsCrossWorkgroupMemoryMask);
return 0;
default:
spv::MissingFunctionality(warningsErrors, "unknown operation with no arguments");
logger->missingFunctionality("unknown operation with no arguments");
return 0;
}
}
@ -3943,7 +3941,7 @@ spv::Id TGlslangToSpvTraverser::createSpvConstant(const glslang::TIntermTyped& n
// Neither a front-end constant node, nor a specialization constant node with constant union array or
// constant sub tree as initializer.
spv::MissingFunctionality(warningsErrors, "Neither a front-end constant nor a spec constant.");
logger->missingFunctionality("Neither a front-end constant nor a spec constant.");
exit(1);
return spv::NoResult;
}
@ -4198,10 +4196,11 @@ void OutputSpv(const std::vector<unsigned int>& spirv, const char* baseName)
//
void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv)
{
GlslangToSpv(intermediate, spirv, nullptr);
spv::SpvBuildLogger logger;
GlslangToSpv(intermediate, spirv, &logger);
}
void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv, std::string* messages)
void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv, spv::SpvBuildLogger* logger)
{
TIntermNode* root = intermediate.getTreeRoot();
@ -4210,14 +4209,12 @@ void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsign
glslang::GetThreadPoolAllocator().push();
TGlslangToSpvTraverser it(&intermediate);
TGlslangToSpvTraverser it(&intermediate, logger);
root->traverse(&it);
it.dumpSpv(spirv);
if (messages != nullptr) *messages = it.getWarningsAndErrors();
glslang::GetThreadPoolAllocator().pop();
}

View File

@ -34,11 +34,16 @@
#include "../glslang/Include/intermediate.h"
#include <string>
#include <vector>
#include "Logger.h"
namespace glslang {
void GetSpirvVersion(std::string&);
void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv);
void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv, std::string* messages);
void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv, spv::SpvBuildLogger* logger);
void OutputSpv(const std::vector<unsigned int>& spirv, const char* baseName);
}

68
SPIRV/Logger.cpp Normal file
View File

@ -0,0 +1,68 @@
//
// Copyright (C) 2016 Google, Inc.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
//
// Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#include "Logger.h"
#include <algorithm>
#include <iterator>
#include <sstream>
namespace spv {
void SpvBuildLogger::tbdFunctionality(const char* f)
{
if (std::find(std::begin(tbdFeatures), std::end(tbdFeatures), f) == std::end(tbdFeatures))
tbdFeatures.push_back(f);
}
void SpvBuildLogger::missingFunctionality(const char* f)
{
if (std::find(std::begin(missingFeatures), std::end(missingFeatures), f) == std::end(missingFeatures))
missingFeatures.push_back(f);
}
std::string SpvBuildLogger::getAllMessages() const {
std::ostringstream messages;
for (const auto& f : tbdFeatures)
messages << "TBD functionality: " << f << "\n";
for (const auto& f : missingFeatures)
messages << "Missing functionality: " << f << "\n";
for (const auto& w : warnings)
messages << "warning: " << w << "\n";
for (const auto& e : errors)
messages << "error: " << e << "\n";
return messages.str();
}
} // end spv namespace

73
SPIRV/Logger.h Normal file
View File

@ -0,0 +1,73 @@
//
// Copyright (C) 2016 Google, Inc.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
//
// Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#ifndef GLSLANG_SPIRV_LOGGER_H
#define GLSLANG_SPIRV_LOGGER_H
#include <string>
#include <vector>
namespace spv {
// A class for holding all SPIR-V build status messages, including
// missing/TBD functionalities, warnings, and errors.
class SpvBuildLogger {
public:
SpvBuildLogger() = default;
SpvBuildLogger(const SpvBuildLogger&) = delete;
// Registers a TBD functionality.
void tbdFunctionality(const char* f);
// Registers a missing functionality.
void missingFunctionality(const char* f);
// Logs a warning.
void warning(const std::string& w) { warnings.push_back(w); }
// Logs an error.
void error(const std::string& e) { errors.push_back(e); }
// Returns all messages accumulated in the order of:
// TBD functionalities, missing functionalities, warnings, errors.
std::string getAllMessages() const;
private:
std::vector<const char*> tbdFeatures;
std::vector<const char*> missingFeatures;
std::vector<std::string> warnings;
std::vector<std::string> errors;
};
} // end spv namespace
#endif // GLSLANG_SPIRV_LOGGER_H

View File

@ -56,7 +56,7 @@
namespace spv {
Builder::Builder(unsigned int magicNumber, std::ostringstream& warnError) :
Builder::Builder(unsigned int magicNumber, SpvBuildLogger* buildLogger) :
source(SourceLanguageUnknown),
sourceVersion(0),
addressModel(AddressingModelLogical),
@ -66,7 +66,7 @@ Builder::Builder(unsigned int magicNumber, std::ostringstream& warnError) :
uniqueId(0),
mainFunction(0),
generatingOpCodeForSpecConst(false),
warningsErrors(warnError)
logger(buildLogger)
{
clearAccessChain();
}
@ -2111,7 +2111,7 @@ void Builder::accessChainStore(Id rvalue)
Id base = collapseAccessChain();
if (accessChain.swizzle.size() && accessChain.component != NoResult)
MissingFunctionality(warningsErrors, "simultaneous l-value swizzle and dynamic component selection");
logger->missingFunctionality("simultaneous l-value swizzle and dynamic component selection");
// If swizzle still exists, it is out-of-order or not full, we must load the target vector,
// extract and insert elements to perform writeMask and/or swizzle.
@ -2487,19 +2487,4 @@ void Builder::dumpInstructions(std::vector<unsigned int>& out, const std::vector
}
}
void TbdFunctionality(std::ostringstream& stream, const char* tbd)
{
static std::unordered_set<const char*> issued;
if (issued.find(tbd) == issued.end()) {
stream << "TBD functionality: " << tbd << "\n";
issued.insert(tbd);
}
}
void MissingFunctionality(std::ostringstream& stream, const char* fun)
{
stream << "Missing functionality: " << fun << "\n";
}
}; // end spv namespace

View File

@ -49,6 +49,7 @@
#ifndef SpvBuilder_H
#define SpvBuilder_H
#include "Logger.h"
#include "spirv.hpp"
#include "spvIR.h"
@ -63,7 +64,7 @@ namespace spv {
class Builder {
public:
Builder(unsigned int userNumber, std::ostringstream& warnError);
Builder(unsigned int userNumber, SpvBuildLogger* logger);
virtual ~Builder();
static const int maxMatrixSize = 4;
@ -583,15 +584,9 @@ public:
std::stack<LoopBlocks> loops;
// The stream for outputing warnings and errors.
std::ostringstream& warningsErrors;
SpvBuildLogger* logger;
}; // end Builder class
// Use for non-fatal notes about what's not complete
void TbdFunctionality(std::ostringstream&, const char*);
// Use for fatal missing functionality
void MissingFunctionality(std::ostringstream&, const char*);
}; // end spv namespace
#endif // SpvBuilder_H

View File

@ -672,12 +672,13 @@ void CompileAndLinkShaderUnits(std::vector<ShaderCompUnit> compUnits)
if (program.getIntermediate((EShLanguage)stage)) {
std::vector<unsigned int> spirv;
std::string warningsErrors;
glslang::GlslangToSpv(*program.getIntermediate((EShLanguage)stage), spirv, &warningsErrors);
spv::SpvBuildLogger logger;
glslang::GlslangToSpv(*program.getIntermediate((EShLanguage)stage), spirv, &logger);
// Dump the spv to a file or stdout, etc., but only if not doing
// memory/perf testing, as it's not internal to programmatic use.
if (! (Options & EOptionMemoryLeakMode)) {
printf("%s", warningsErrors.c_str());
printf("%s", logger.getAllMessages().c_str());
glslang::OutputSpv(spirv, GetBinaryName((EShLanguage)stage));
if (Options & EOptionHumanReadableSpv) {
spv::Disassemble(std::cout, spirv);

View File

@ -5,9 +5,6 @@ Warning, version 450 is not yet complete; most version-specific features are pre
Linked fragment stage:
Missing functionality: shader int64
Missing functionality: shader int64
Missing functionality: shader int64
Missing functionality: shader int64
// Module Version 10000
// Generated by (magic number): 80001

View File

@ -188,19 +188,19 @@ public:
program.addShader(&shader);
success &= program.link(messages);
std::string spirvWarningsErrors;
spv::SpvBuildLogger logger;
if (success && target == Target::Spirv) {
std::vector<uint32_t> spirv_binary;
glslang::GlslangToSpv(*program.getIntermediate(language),
spirv_binary, &spirvWarningsErrors);
spirv_binary, &logger);
std::ostringstream disassembly_stream;
spv::Parameterize();
spv::Disassemble(disassembly_stream, spirv_binary);
return {shader.getInfoLog(), shader.getInfoDebugLog(),
program.getInfoLog(), program.getInfoDebugLog(),
spirvWarningsErrors, disassembly_stream.str()};
logger.getAllMessages(), disassembly_stream.str()};
} else {
return {shader.getInfoLog(), shader.getInfoDebugLog(),
program.getInfoLog(), program.getInfoDebugLog(),