Commit e485c7af by John Kessenich

SPV: Debug output: Include OpLine information for execution path.

Note that declaratives are not handled, only procedurals.
parent 121853f4
...@@ -869,6 +869,7 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(const glslang::TIntermediate* gls ...@@ -869,6 +869,7 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(const glslang::TIntermediate* gls
if (options.generateDebugInfo) { if (options.generateDebugInfo) {
builder.setSourceFile(glslangIntermediate->getSourceFile()); builder.setSourceFile(glslangIntermediate->getSourceFile());
builder.setSourceText(glslangIntermediate->getSourceText()); builder.setSourceText(glslangIntermediate->getSourceText());
builder.setEmitOpLines();
} }
stdBuiltins = builder.import("GLSL.std.450"); stdBuiltins = builder.import("GLSL.std.450");
builder.setMemoryModel(spv::AddressingModelLogical, spv::MemoryModelGLSL450); builder.setMemoryModel(spv::AddressingModelLogical, spv::MemoryModelGLSL450);
...@@ -1077,6 +1078,8 @@ void TGlslangToSpvTraverser::visitSymbol(glslang::TIntermSymbol* symbol) ...@@ -1077,6 +1078,8 @@ void TGlslangToSpvTraverser::visitSymbol(glslang::TIntermSymbol* symbol)
bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::TIntermBinary* node) bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::TIntermBinary* node)
{ {
builder.setLine(node->getLoc().line);
SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder); SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder);
if (node->getType().getQualifier().isSpecConstant()) if (node->getType().getQualifier().isSpecConstant())
spec_constant_op_mode_setter.turnOnSpecConstantOpMode(); spec_constant_op_mode_setter.turnOnSpecConstantOpMode();
...@@ -1264,6 +1267,8 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T ...@@ -1264,6 +1267,8 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TIntermUnary* node) bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TIntermUnary* node)
{ {
builder.setLine(node->getLoc().line);
SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder); SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder);
if (node->getType().getQualifier().isSpecConstant()) if (node->getType().getQualifier().isSpecConstant())
spec_constant_op_mode_setter.turnOnSpecConstantOpMode(); spec_constant_op_mode_setter.turnOnSpecConstantOpMode();
...@@ -1507,6 +1512,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt ...@@ -1507,6 +1512,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
return false; return false;
case glslang::EOpFunctionCall: case glslang::EOpFunctionCall:
{ {
builder.setLine(node->getLoc().line);
if (node->isUserDefined()) if (node->isUserDefined())
result = handleUserFunctionCall(node); result = handleUserFunctionCall(node);
// assert(result); // this can happen for bad shaders because the call graph completeness checking is not yet done // assert(result); // this can happen for bad shaders because the call graph completeness checking is not yet done
...@@ -1613,6 +1619,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt ...@@ -1613,6 +1619,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
case glslang::EOpConstructStruct: case glslang::EOpConstructStruct:
case glslang::EOpConstructTextureSampler: case glslang::EOpConstructTextureSampler:
{ {
builder.setLine(node->getLoc().line);
std::vector<spv::Id> arguments; std::vector<spv::Id> arguments;
translateArguments(*node, arguments); translateArguments(*node, arguments);
spv::Id constructed; spv::Id constructed;
...@@ -1723,6 +1730,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt ...@@ -1723,6 +1730,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
right->traverse(this); right->traverse(this);
spv::Id rightId = accessChainLoad(right->getType()); spv::Id rightId = accessChainLoad(right->getType());
builder.setLine(node->getLoc().line);
result = createBinaryOperation(binOp, precision, TranslateNoContractionDecoration(node->getType().getQualifier()), result = createBinaryOperation(binOp, precision, TranslateNoContractionDecoration(node->getType().getQualifier()),
resultType(), leftId, rightId, resultType(), leftId, rightId,
left->getType().getBasicType(), reduceComparison); left->getType().getBasicType(), reduceComparison);
...@@ -1795,10 +1803,13 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt ...@@ -1795,10 +1803,13 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
glslangOperands[arg]->traverse(this); glslangOperands[arg]->traverse(this);
if (lvalue) if (lvalue)
operands.push_back(builder.accessChainGetLValue()); operands.push_back(builder.accessChainGetLValue());
else else {
builder.setLine(node->getLoc().line);
operands.push_back(accessChainLoad(glslangOperands[arg]->getAsTyped()->getType())); operands.push_back(accessChainLoad(glslangOperands[arg]->getAsTyped()->getType()));
}
} }
builder.setLine(node->getLoc().line);
if (atomic) { if (atomic) {
// Handle all atomics // Handle all atomics
result = createAtomicOperation(node->getOp(), precision, resultType(), operands, node->getBasicType()); result = createAtomicOperation(node->getOp(), precision, resultType(), operands, node->getBasicType());
...@@ -1880,6 +1891,8 @@ bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang ...@@ -1880,6 +1891,8 @@ bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang
node->getFalseBlock()->traverse(this); node->getFalseBlock()->traverse(this);
spv::Id falseValue = accessChainLoad(node->getTrueBlock()->getAsTyped()->getType()); spv::Id falseValue = accessChainLoad(node->getTrueBlock()->getAsTyped()->getType());
builder.setLine(node->getLoc().line);
// smear condition to vector, if necessary (AST is always scalar) // smear condition to vector, if necessary (AST is always scalar)
if (builder.isVector(trueValue)) if (builder.isVector(trueValue))
condition = builder.smearScalar(spv::NoPrecision, condition, condition = builder.smearScalar(spv::NoPrecision, condition,
...@@ -2022,6 +2035,7 @@ bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIn ...@@ -2022,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 // 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, // instructions in it, since the body/test may have arbitrary instructions,
// including merges of its own. // including merges of its own.
builder.setLine(node->getLoc().line);
builder.setBuildPoint(&blocks.head); builder.setBuildPoint(&blocks.head);
builder.createLoopMerge(&blocks.merge, &blocks.continue_target, control); builder.createLoopMerge(&blocks.merge, &blocks.continue_target, control);
if (node->testFirst() && node->getTest()) { if (node->testFirst() && node->getTest()) {
...@@ -2030,8 +2044,7 @@ bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIn ...@@ -2030,8 +2044,7 @@ bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIn
builder.setBuildPoint(&test); builder.setBuildPoint(&test);
node->getTest()->traverse(this); node->getTest()->traverse(this);
spv::Id condition = spv::Id condition = accessChainLoad(node->getTest()->getType());
accessChainLoad(node->getTest()->getType());
builder.createConditionalBranch(condition, &blocks.body, &blocks.merge); builder.createConditionalBranch(condition, &blocks.body, &blocks.merge);
builder.setBuildPoint(&blocks.body); builder.setBuildPoint(&blocks.body);
...@@ -2046,6 +2059,7 @@ bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIn ...@@ -2046,6 +2059,7 @@ bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIn
node->getTerminal()->traverse(this); node->getTerminal()->traverse(this);
builder.createBranch(&blocks.head); builder.createBranch(&blocks.head);
} else { } else {
builder.setLine(node->getLoc().line);
builder.createBranch(&blocks.body); builder.createBranch(&blocks.body);
breakForLoop.push(true); breakForLoop.push(true);
...@@ -2080,6 +2094,8 @@ bool TGlslangToSpvTraverser::visitBranch(glslang::TVisit /* visit */, glslang::T ...@@ -2080,6 +2094,8 @@ bool TGlslangToSpvTraverser::visitBranch(glslang::TVisit /* visit */, glslang::T
if (node->getExpression()) if (node->getExpression())
node->getExpression()->traverse(this); node->getExpression()->traverse(this);
builder.setLine(node->getLoc().line);
switch (node->getFlowOp()) { switch (node->getFlowOp()) {
case glslang::EOpKill: case glslang::EOpKill:
builder.makeDiscard(); builder.makeDiscard();
...@@ -3057,9 +3073,11 @@ void TGlslangToSpvTraverser::translateArguments(glslang::TIntermUnary& node, std ...@@ -3057,9 +3073,11 @@ void TGlslangToSpvTraverser::translateArguments(glslang::TIntermUnary& node, std
spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermOperator* node) spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermOperator* node)
{ {
if (! node->isImage() && ! node->isTexture()) { if (! node->isImage() && ! node->isTexture())
return spv::NoResult; return spv::NoResult;
}
builder.setLine(node->getLoc().line);
auto resultType = [&node,this]{ return convertGlslangToSpvType(node->getType()); }; auto resultType = [&node,this]{ return convertGlslangToSpvType(node->getType()); };
// Process a GLSL texturing op (will be SPV image) // Process a GLSL texturing op (will be SPV image)
......
...@@ -60,6 +60,8 @@ Builder::Builder(unsigned int magicNumber, SpvBuildLogger* buildLogger) : ...@@ -60,6 +60,8 @@ Builder::Builder(unsigned int magicNumber, SpvBuildLogger* buildLogger) :
source(SourceLanguageUnknown), source(SourceLanguageUnknown),
sourceVersion(0), sourceVersion(0),
sourceFileStringId(NoResult), sourceFileStringId(NoResult),
currentLine(0),
emitOpLines(false),
addressModel(AddressingModelLogical), addressModel(AddressingModelLogical),
memoryModel(MemoryModelGLSL450), memoryModel(MemoryModelGLSL450),
builderNumber(magicNumber), builderNumber(magicNumber),
...@@ -85,6 +87,26 @@ Id Builder::import(const char* name) ...@@ -85,6 +87,26 @@ Id Builder::import(const char* name)
return import->getResultId(); 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). // For creating new groupedTypes (will return old type if the requested one was already made).
Id Builder::makeVoidType() Id Builder::makeVoidType()
{ {
...@@ -929,17 +951,6 @@ void Builder::addMemberName(Id id, int memberNumber, const char* string) ...@@ -929,17 +951,6 @@ void Builder::addMemberName(Id id, int memberNumber, const char* string)
names.push_back(std::unique_ptr<Instruction>(name)); 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) void Builder::addDecoration(Id id, Decoration decoration, int num)
{ {
if (decoration == spv::DecorationMax) if (decoration == spv::DecorationMax)
......
...@@ -79,6 +79,7 @@ public: ...@@ -79,6 +79,7 @@ public:
} }
void setSourceText(const std::string& text) { sourceText = text; } void setSourceText(const std::string& text) { sourceText = text; }
void addSourceExtension(const char* ext) { sourceExtensions.push_back(ext); } void addSourceExtension(const char* ext) { sourceExtensions.push_back(ext); }
void setEmitOpLines() { emitOpLines = true; }
void addExtension(const char* ext) { extensions.insert(ext); } void addExtension(const char* ext) { extensions.insert(ext); }
Id import(const char*); Id import(const char*);
void setMemoryModel(spv::AddressingModel addr, spv::MemoryModel mem) void setMemoryModel(spv::AddressingModel addr, spv::MemoryModel mem)
...@@ -100,6 +101,12 @@ public: ...@@ -100,6 +101,12 @@ public:
return id; 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). // For creating new types (will return old type if the requested one was already made).
Id makeVoidType(); Id makeVoidType();
Id makeBoolType(); Id makeBoolType();
...@@ -221,7 +228,6 @@ public: ...@@ -221,7 +228,6 @@ public:
void addExecutionMode(Function*, ExecutionMode mode, int value1 = -1, int value2 = -1, int value3 = -1); void addExecutionMode(Function*, ExecutionMode mode, int value1 = -1, int value2 = -1, int value3 = -1);
void addName(Id, const char* name); void addName(Id, const char* name);
void addMemberName(Id, int member, 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 addDecoration(Id, Decoration, int num = -1);
void addMemberDecoration(Id, unsigned int member, Decoration, int num = -1); void addMemberDecoration(Id, unsigned int member, Decoration, int num = -1);
...@@ -576,6 +582,8 @@ public: ...@@ -576,6 +582,8 @@ public:
int sourceVersion; int sourceVersion;
spv::Id sourceFileStringId; spv::Id sourceFileStringId;
std::string sourceText; std::string sourceText;
int currentLine;
bool emitOpLines;
std::set<std::string> extensions; std::set<std::string> extensions;
std::vector<const char*> sourceExtensions; std::vector<const char*> sourceExtensions;
AddressingModel addressModel; AddressingModel addressModel;
......
...@@ -8,15 +8,45 @@ uniform ubuf { ...@@ -8,15 +8,45 @@ uniform ubuf {
S s; S s;
}; };
uniform sampler2D s2d;
layout(location = 0) in vec4 inv; layout(location = 0) in vec4 inv;
layout(location = 0) out vec4 outv; layout(location = 0) out vec4 outv;
void foo(S s) vec4 foo(S s)
{ {
outv = s.a * inv; vec4 r = s.a * inv;
++r;
if (r.x > 3.0)
--r;
else
r *= 2;
return r;
} }
void main() void main()
{ {
foo(s); outv = foo(s);
outv += texture(s2d, vec2(0.5));
switch (s.a) {
case 10:
++outv;
break;
case 20:
outv = 2 * outv;
++outv;
break;
default:
--outv;
break;
}
for (int i = 0; i < 10; ++i)
outv *= 3.0;
outv.x < 10.0 ?
outv = sin(outv) :
outv = cos(outv);
} }
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment