Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SPV: Add OpSource shader source code and file name. #911

Merged
merged 2 commits into from
Jun 1, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
55 changes: 43 additions & 12 deletions SPIRV/GlslangToSpv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ class SpecConstantOpModeGuard {
//
class TGlslangToSpvTraverser : public glslang::TIntermTraverser {
public:
TGlslangToSpvTraverser(const glslang::TIntermediate*, spv::SpvBuildLogger* logger);
TGlslangToSpvTraverser(const glslang::TIntermediate*, spv::SpvBuildLogger* logger, glslang::SpvOptions& options);
virtual ~TGlslangToSpvTraverser() { }

bool visitAggregate(glslang::TVisit, glslang::TIntermAggregate*);
Expand Down Expand Up @@ -179,6 +179,7 @@ class TGlslangToSpvTraverser : public glslang::TIntermTraverser {
spv::Id createShortCircuit(glslang::TOperator, glslang::TIntermTyped& left, glslang::TIntermTyped& right);
spv::Id getExtBuiltins(const char* name);

glslang::SpvOptions& options;
spv::Function* shaderEntry;
spv::Function* currentFunction;
spv::Instruction* entryPoint;
Expand Down Expand Up @@ -851,8 +852,11 @@ bool HasNonLayoutQualifiers(const glslang::TType& type, const glslang::TQualifie
// Implement the TGlslangToSpvTraverser class.
//

TGlslangToSpvTraverser::TGlslangToSpvTraverser(const glslang::TIntermediate* glslangIntermediate, spv::SpvBuildLogger* buildLogger)
: TIntermTraverser(true, false, true), shaderEntry(nullptr), currentFunction(nullptr),
TGlslangToSpvTraverser::TGlslangToSpvTraverser(const glslang::TIntermediate* glslangIntermediate,
spv::SpvBuildLogger* buildLogger, glslang::SpvOptions& options)
: TIntermTraverser(true, false, true),
options(options),
shaderEntry(nullptr), currentFunction(nullptr),
sequenceDepth(0), logger(buildLogger),
builder((glslang::GetKhronosToolId() << 16) | GeneratorVersion, logger),
inEntryPoint(false), entryPointTerminated(false), linkageOnly(false),
Expand All @@ -862,6 +866,11 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(const glslang::TIntermediate* gls

builder.clearAccessChain();
builder.setSource(TranslateSourceLanguage(glslangIntermediate->getSource(), glslangIntermediate->getProfile()), glslangIntermediate->getVersion());
if (options.generateDebugInfo) {
builder.setSourceFile(glslangIntermediate->getSourceFile());
builder.setSourceText(glslangIntermediate->getSourceText());
builder.setEmitOpLines();
}
stdBuiltins = builder.import("GLSL.std.450");
builder.setMemoryModel(spv::AddressingModelLogical, spv::MemoryModelGLSL450);
shaderEntry = builder.makeEntryPoint(glslangIntermediate->getEntryPointName().c_str());
Expand Down Expand Up @@ -1069,6 +1078,8 @@ void TGlslangToSpvTraverser::visitSymbol(glslang::TIntermSymbol* symbol)

bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::TIntermBinary* node)
{
builder.setLine(node->getLoc().line);

SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder);
if (node->getType().getQualifier().isSpecConstant())
spec_constant_op_mode_setter.turnOnSpecConstantOpMode();
Expand Down Expand Up @@ -1256,6 +1267,8 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T

bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TIntermUnary* node)
{
builder.setLine(node->getLoc().line);

SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder);
if (node->getType().getQualifier().isSpecConstant())
spec_constant_op_mode_setter.turnOnSpecConstantOpMode();
Expand Down Expand Up @@ -1499,6 +1512,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
return false;
case glslang::EOpFunctionCall:
{
builder.setLine(node->getLoc().line);
if (node->isUserDefined())
result = handleUserFunctionCall(node);
// assert(result); // this can happen for bad shaders because the call graph completeness checking is not yet done
Expand Down Expand Up @@ -1605,6 +1619,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
case glslang::EOpConstructStruct:
case glslang::EOpConstructTextureSampler:
{
builder.setLine(node->getLoc().line);
std::vector<spv::Id> arguments;
translateArguments(*node, arguments);
spv::Id constructed;
Expand Down Expand Up @@ -1715,6 +1730,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
right->traverse(this);
spv::Id rightId = accessChainLoad(right->getType());

builder.setLine(node->getLoc().line);
result = createBinaryOperation(binOp, precision, TranslateNoContractionDecoration(node->getType().getQualifier()),
resultType(), leftId, rightId,
left->getType().getBasicType(), reduceComparison);
Expand Down Expand Up @@ -1787,10 +1803,13 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
glslangOperands[arg]->traverse(this);
if (lvalue)
operands.push_back(builder.accessChainGetLValue());
else
else {
builder.setLine(node->getLoc().line);
operands.push_back(accessChainLoad(glslangOperands[arg]->getAsTyped()->getType()));
}
}

builder.setLine(node->getLoc().line);
if (atomic) {
// Handle all atomics
result = createAtomicOperation(node->getOp(), precision, resultType(), operands, node->getBasicType());
Expand Down Expand Up @@ -1872,6 +1891,8 @@ bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang
node->getFalseBlock()->traverse(this);
spv::Id falseValue = accessChainLoad(node->getTrueBlock()->getAsTyped()->getType());

builder.setLine(node->getLoc().line);

// smear condition to vector, if necessary (AST is always scalar)
if (builder.isVector(trueValue))
condition = builder.smearScalar(spv::NoPrecision, condition,
Expand Down Expand Up @@ -2014,6 +2035,7 @@ bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIn
// by a block-ending branch. But we don't want to put any other body/test
// instructions in it, since the body/test may have arbitrary instructions,
// including merges of its own.
builder.setLine(node->getLoc().line);
builder.setBuildPoint(&blocks.head);
builder.createLoopMerge(&blocks.merge, &blocks.continue_target, control);
if (node->testFirst() && node->getTest()) {
Expand All @@ -2022,8 +2044,7 @@ bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIn

builder.setBuildPoint(&test);
node->getTest()->traverse(this);
spv::Id condition =
accessChainLoad(node->getTest()->getType());
spv::Id condition = accessChainLoad(node->getTest()->getType());
builder.createConditionalBranch(condition, &blocks.body, &blocks.merge);

builder.setBuildPoint(&blocks.body);
Expand All @@ -2038,6 +2059,7 @@ bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIn
node->getTerminal()->traverse(this);
builder.createBranch(&blocks.head);
} else {
builder.setLine(node->getLoc().line);
builder.createBranch(&blocks.body);

breakForLoop.push(true);
Expand Down Expand Up @@ -2072,6 +2094,8 @@ bool TGlslangToSpvTraverser::visitBranch(glslang::TVisit /* visit */, glslang::T
if (node->getExpression())
node->getExpression()->traverse(this);

builder.setLine(node->getLoc().line);

switch (node->getFlowOp()) {
case glslang::EOpKill:
builder.makeDiscard();
Expand Down Expand Up @@ -3049,9 +3073,11 @@ void TGlslangToSpvTraverser::translateArguments(glslang::TIntermUnary& node, std

spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermOperator* node)
{
if (! node->isImage() && ! node->isTexture()) {
if (! node->isImage() && ! node->isTexture())
return spv::NoResult;
}

builder.setLine(node->getLoc().line);

auto resultType = [&node,this]{ return convertGlslangToSpvType(node->getType()); };

// Process a GLSL texturing op (will be SPV image)
Expand Down Expand Up @@ -5561,22 +5587,27 @@ void OutputSpvHex(const std::vector<unsigned int>& spirv, const char* baseName,
//
// Set up the glslang traversal
//
void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv)
void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv, SpvOptions* options)
{
spv::SpvBuildLogger logger;
GlslangToSpv(intermediate, spirv, &logger);
GlslangToSpv(intermediate, spirv, &logger, options);
}

void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv, spv::SpvBuildLogger* logger)
void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
spv::SpvBuildLogger* logger, SpvOptions* options)
{
TIntermNode* root = intermediate.getTreeRoot();

if (root == 0)
return;

glslang::SpvOptions defaultOptions;
if (options == nullptr)
options = &defaultOptions;

glslang::GetThreadPoolAllocator().push();

TGlslangToSpvTraverser it(&intermediate, logger);
TGlslangToSpvTraverser it(&intermediate, logger, *options);
root->traverse(&it);
it.finishSpv();
it.dumpSpv(spirv);
Expand Down
11 changes: 9 additions & 2 deletions SPIRV/GlslangToSpv.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,16 @@

namespace glslang {

struct SpvOptions {
SpvOptions() : generateDebugInfo(false) { }
bool generateDebugInfo;
};

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, spv::SpvBuildLogger* logger);
void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
SpvOptions* options = nullptr);
void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
spv::SpvBuildLogger* logger, SpvOptions* options = nullptr);
void OutputSpvBin(const std::vector<unsigned int>& spirv, const char* baseName);
void OutputSpvHex(const std::vector<unsigned int>& spirv, const char* baseName, const char* varName);

Expand Down
84 changes: 67 additions & 17 deletions SPIRV/SpvBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ namespace spv {
Builder::Builder(unsigned int magicNumber, SpvBuildLogger* buildLogger) :
source(SourceLanguageUnknown),
sourceVersion(0),
sourceFileStringId(NoResult),
currentLine(0),
emitOpLines(false),
addressModel(AddressingModelLogical),
memoryModel(MemoryModelGLSL450),
builderNumber(magicNumber),
Expand All @@ -84,6 +87,26 @@ Id Builder::import(const char* name)
return import->getResultId();
}

// Emit an OpLine if we've been asked to emit OpLines and the line number
// has changed since the last time, and is a valid line number.
void Builder::setLine(int lineNum)
{
if (lineNum != 0 && lineNum != currentLine) {
currentLine = lineNum;
if (emitOpLines)
addLine(sourceFileStringId, currentLine, 0);
}
}

void Builder::addLine(Id fileName, int lineNum, int column)
{
Instruction* line = new Instruction(OpLine);
line->addIdOperand(fileName);
line->addImmediateOperand(lineNum);
line->addImmediateOperand(column);
buildPoint->addInstruction(std::unique_ptr<Instruction>(line));
}

// For creating new groupedTypes (will return old type if the requested one was already made).
Id Builder::makeVoidType()
{
Expand Down Expand Up @@ -928,17 +951,6 @@ void Builder::addMemberName(Id id, int memberNumber, const char* string)
names.push_back(std::unique_ptr<Instruction>(name));
}

void Builder::addLine(Id target, Id fileName, int lineNum, int column)
{
Instruction* line = new Instruction(OpLine);
line->addIdOperand(target);
line->addIdOperand(fileName);
line->addImmediateOperand(lineNum);
line->addImmediateOperand(column);

lines.push_back(std::unique_ptr<Instruction>(line));
}

void Builder::addDecoration(Id id, Decoration decoration, int num)
{
if (decoration == spv::DecorationMax)
Expand Down Expand Up @@ -2411,12 +2423,8 @@ void Builder::dump(std::vector<unsigned int>& out) const
dumpInstructions(out, executionModes);

// Debug instructions
if (source != SourceLanguageUnknown) {
Instruction sourceInst(0, 0, OpSource);
sourceInst.addImmediateOperand(source);
sourceInst.addImmediateOperand(sourceVersion);
sourceInst.dump(out);
}
dumpInstructions(out, strings);
dumpSourceInstructions(out);
for (int e = 0; e < (int)sourceExtensions.size(); ++e) {
Instruction sourceExtInst(0, 0, OpSourceExtension);
sourceExtInst.addStringOperand(sourceExtensions[e]);
Expand Down Expand Up @@ -2574,6 +2582,48 @@ void Builder::createConditionalBranch(Id condition, Block* thenBlock, Block* els
elseBlock->addPredecessor(buildPoint);
}

// OpSource
// [OpSourceContinued]
// ...
void Builder::dumpSourceInstructions(std::vector<unsigned int>& out) const
{
const int maxWordCount = 0xFFFF;
const int opSourceWordCount = 4;
const int nonNullBytesPerInstruction = 4 * (maxWordCount - opSourceWordCount) - 1;

if (source != SourceLanguageUnknown) {
// OpSource Language Version File Source
Instruction sourceInst(NoResult, NoType, OpSource);
sourceInst.addImmediateOperand(source);
sourceInst.addImmediateOperand(sourceVersion);
// File operand
if (sourceFileStringId != NoResult) {
sourceInst.addIdOperand(sourceFileStringId);
// Source operand
if (sourceText.size() > 0) {
int nextByte = 0;
std::string subString;
while ((int)sourceText.size() - nextByte > 0) {
subString = sourceText.substr(nextByte, nonNullBytesPerInstruction);
if (nextByte == 0) {
// OpSource
sourceInst.addStringOperand(subString.c_str());
sourceInst.dump(out);
} else {
// OpSourcContinued
Instruction sourceContinuedInst(OpSourceContinued);
sourceContinuedInst.addStringOperand(subString.c_str());
sourceContinuedInst.dump(out);
}
nextByte += nonNullBytesPerInstruction;
}
} else
sourceInst.dump(out);
} else
sourceInst.dump(out);
}
}

void Builder::dumpInstructions(std::vector<unsigned int>& out, const std::vector<std::unique_ptr<Instruction> >& instructions) const
{
for (int i = 0; i < (int)instructions.size(); ++i) {
Expand Down
24 changes: 22 additions & 2 deletions SPIRV/SpvBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,16 @@ class Builder {
source = lang;
sourceVersion = version;
}
void setSourceFile(const std::string& file)
{
Instruction* fileString = new Instruction(getUniqueId(), NoType, OpString);
fileString->addStringOperand(file.c_str());
sourceFileStringId = fileString->getResultId();
strings.push_back(std::unique_ptr<Instruction>(fileString));
}
void setSourceText(const std::string& text) { sourceText = text; }
void addSourceExtension(const char* ext) { sourceExtensions.push_back(ext); }
void setEmitOpLines() { emitOpLines = true; }
void addExtension(const char* ext) { extensions.insert(ext); }
Id import(const char*);
void setMemoryModel(spv::AddressingModel addr, spv::MemoryModel mem)
Expand All @@ -92,6 +101,12 @@ class Builder {
return id;
}

// Log the current line, and if different than the last one,
// issue a new OpLine, using the current file name.
void setLine(int line);
// Low-level OpLine. See setLine() for a layered helper.
void addLine(Id fileName, int line, int column);

// For creating new types (will return old type if the requested one was already made).
Id makeVoidType();
Id makeBoolType();
Expand Down Expand Up @@ -213,7 +228,6 @@ class Builder {
void addExecutionMode(Function*, ExecutionMode mode, int value1 = -1, int value2 = -1, int value3 = -1);
void addName(Id, const char* name);
void addMemberName(Id, int member, const char* name);
void addLine(Id target, Id fileName, int line, int column);
void addDecoration(Id, Decoration, int num = -1);
void addMemberDecoration(Id, unsigned int member, Decoration, int num = -1);

Expand Down Expand Up @@ -561,10 +575,15 @@ class Builder {
void simplifyAccessChainSwizzle();
void createAndSetNoPredecessorBlock(const char*);
void createSelectionMerge(Block* mergeBlock, unsigned int control);
void dumpSourceInstructions(std::vector<unsigned int>&) const;
void dumpInstructions(std::vector<unsigned int>&, const std::vector<std::unique_ptr<Instruction> >&) const;

SourceLanguage source;
int sourceVersion;
spv::Id sourceFileStringId;
std::string sourceText;
int currentLine;
bool emitOpLines;
std::set<std::string> extensions;
std::vector<const char*> sourceExtensions;
AddressingModel addressModel;
Expand All @@ -579,6 +598,7 @@ class Builder {
AccessChain accessChain;

// special blocks of instructions for output
std::vector<std::unique_ptr<Instruction> > strings;
std::vector<std::unique_ptr<Instruction> > imports;
std::vector<std::unique_ptr<Instruction> > entryPoints;
std::vector<std::unique_ptr<Instruction> > executionModes;
Expand All @@ -599,7 +619,7 @@ class Builder {
// Our loop stack.
std::stack<LoopBlocks> loops;

// The stream for outputing warnings and errors.
// The stream for outputting warnings and errors.
SpvBuildLogger* logger;
}; // end Builder class

Expand Down