diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp index a2bd8484f8..e175bfc651 100755 --- a/SPIRV/GlslangToSpv.cpp +++ b/SPIRV/GlslangToSpv.cpp @@ -869,6 +869,7 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(const glslang::TIntermediate* gls 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); @@ -1077,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(); @@ -1264,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(); @@ -1507,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 @@ -1613,6 +1619,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt case glslang::EOpConstructStruct: case glslang::EOpConstructTextureSampler: { + builder.setLine(node->getLoc().line); std::vector arguments; translateArguments(*node, arguments); spv::Id constructed; @@ -1723,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); @@ -1795,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()); @@ -1880,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, @@ -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 // 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()) { @@ -2030,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); @@ -2046,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); @@ -2080,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(); @@ -3057,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) diff --git a/SPIRV/SpvBuilder.cpp b/SPIRV/SpvBuilder.cpp index 37c4cb5b1d..ffd17af1b7 100644 --- a/SPIRV/SpvBuilder.cpp +++ b/SPIRV/SpvBuilder.cpp @@ -60,6 +60,8 @@ Builder::Builder(unsigned int magicNumber, SpvBuildLogger* buildLogger) : source(SourceLanguageUnknown), sourceVersion(0), sourceFileStringId(NoResult), + currentLine(0), + emitOpLines(false), addressModel(AddressingModelLogical), memoryModel(MemoryModelGLSL450), builderNumber(magicNumber), @@ -85,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(line)); +} + // For creating new groupedTypes (will return old type if the requested one was already made). Id Builder::makeVoidType() { @@ -929,17 +951,6 @@ void Builder::addMemberName(Id id, int memberNumber, const char* string) names.push_back(std::unique_ptr(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(line)); -} - void Builder::addDecoration(Id id, Decoration decoration, int num) { if (decoration == spv::DecorationMax) diff --git a/SPIRV/SpvBuilder.h b/SPIRV/SpvBuilder.h index 42c18b7d86..60d97e9c81 100755 --- a/SPIRV/SpvBuilder.h +++ b/SPIRV/SpvBuilder.h @@ -79,6 +79,7 @@ class Builder { } 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) @@ -100,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(); @@ -221,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); @@ -576,6 +582,8 @@ class Builder { int sourceVersion; spv::Id sourceFileStringId; std::string sourceText; + int currentLine; + bool emitOpLines; std::set extensions; std::vector sourceExtensions; AddressingModel addressModel; diff --git a/Test/baseResults/spv.debugInfo.frag.out b/Test/baseResults/spv.debugInfo.frag.out index 6e9e208211..16f605bfa2 100644 --- a/Test/baseResults/spv.debugInfo.frag.out +++ b/Test/baseResults/spv.debugInfo.frag.out @@ -3,12 +3,12 @@ Warning, version 450 is not yet complete; most version-specific features are pre // Module Version 10000 // Generated by (magic number): 80001 -// Id's are bound by 40 +// Id's are bound by 126 Capability Shader 2: ExtInstImport "GLSL.std.450" MemoryModel Logical GLSL450 - EntryPoint Fragment 5 "main" 17 24 + EntryPoint Fragment 5 "main" 24 52 ExecutionMode 5 OriginUpperLeft 1: String "spv.debugInfo.frag" Source GLSL 450 1 "#version 450 @@ -21,79 +21,252 @@ uniform ubuf { S s; }; +uniform sampler2D s2d; + layout(location = 0) in vec4 inv; 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() { - 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); }" Name 5 "main" Name 8 "S" MemberName 8(S) 0 "a" - Name 12 "foo(struct-S-i11;" - Name 11 "s" - Name 17 "outv" + Name 14 "foo(struct-S-i11;" + Name 13 "s" + Name 17 "r" Name 24 "inv" - Name 27 "S" - MemberName 27(S) 0 "a" - Name 28 "ubuf" - MemberName 28(ubuf) 0 "s" - Name 30 "" - Name 31 "S" - MemberName 31(S) 0 "a" - Name 33 "param" - Decorate 17(outv) Location 0 + Name 52 "outv" + Name 53 "S" + MemberName 53(S) 0 "a" + Name 54 "ubuf" + MemberName 54(ubuf) 0 "s" + Name 56 "" + Name 57 "S" + MemberName 57(S) 0 "a" + Name 59 "param" + Name 69 "s2d" + Name 99 "i" Decorate 24(inv) Location 0 - MemberDecorate 27(S) 0 Offset 0 - MemberDecorate 28(ubuf) 0 Offset 0 - Decorate 28(ubuf) Block - Decorate 30 DescriptorSet 0 + Decorate 52(outv) Location 0 + MemberDecorate 53(S) 0 Offset 0 + MemberDecorate 54(ubuf) 0 Offset 0 + Decorate 54(ubuf) Block + Decorate 56 DescriptorSet 0 + Decorate 69(s2d) DescriptorSet 0 3: TypeVoid 4: TypeFunction 3 7: TypeInt 32 1 8(S): TypeStruct 7(int) 9: TypePointer Function 8(S) - 10: TypeFunction 3 9(ptr) - 14: TypeFloat 32 - 15: TypeVector 14(float) 4 - 16: TypePointer Output 15(fvec4) - 17(outv): 16(ptr) Variable Output + 10: TypeFloat 32 + 11: TypeVector 10(float) 4 + 12: TypeFunction 11(fvec4) 9(ptr) + 16: TypePointer Function 11(fvec4) 18: 7(int) Constant 0 19: TypePointer Function 7(int) - 23: TypePointer Input 15(fvec4) + 23: TypePointer Input 11(fvec4) 24(inv): 23(ptr) Variable Input - 27(S): TypeStruct 7(int) - 28(ubuf): TypeStruct 27(S) - 29: TypePointer Uniform 28(ubuf) - 30: 29(ptr) Variable Uniform - 31(S): TypeStruct 7(int) - 32: TypePointer Function 31(S) - 34: TypePointer Uniform 27(S) + 28: 10(float) Constant 1065353216 + 31: TypeInt 32 0 + 32: 31(int) Constant 0 + 33: TypePointer Function 10(float) + 36: 10(float) Constant 1077936128 + 37: TypeBool + 45: 10(float) Constant 1073741824 + 51: TypePointer Output 11(fvec4) + 52(outv): 51(ptr) Variable Output + 53(S): TypeStruct 7(int) + 54(ubuf): TypeStruct 53(S) + 55: TypePointer Uniform 54(ubuf) + 56: 55(ptr) Variable Uniform + 57(S): TypeStruct 7(int) + 58: TypePointer Function 57(S) + 60: TypePointer Uniform 53(S) + 66: TypeImage 10(float) 2D sampled format:Unknown + 67: TypeSampledImage 66 + 68: TypePointer UniformConstant 67 + 69(s2d): 68(ptr) Variable UniformConstant + 71: TypeVector 10(float) 2 + 72: 10(float) Constant 1056964608 + 73: 71(fvec2) ConstantComposite 72 72 + 77: TypePointer Uniform 7(int) + 106: 7(int) Constant 10 + 111: 7(int) Constant 1 + 114: TypePointer Output 10(float) + 117: 10(float) Constant 1092616192 5(main): 3 Function None 4 6: Label - 33(param): 32(ptr) Variable Function - 35: 34(ptr) AccessChain 30 18 - 36: 27(S) Load 35 - 37: 7(int) CompositeExtract 36 0 - 38: 19(ptr) AccessChain 33(param) 18 - Store 38 37 - 39: 3 FunctionCall 12(foo(struct-S-i11;) 33(param) + 59(param): 58(ptr) Variable Function + 99(i): 19(ptr) Variable Function + 113: 16(ptr) Variable Function + Line 1 30 0 + 61: 60(ptr) AccessChain 56 18 + 62: 53(S) Load 61 + 63: 7(int) CompositeExtract 62 0 + 64: 19(ptr) AccessChain 59(param) 18 + Store 64 63 + 65: 11(fvec4) FunctionCall 14(foo(struct-S-i11;) 59(param) + Store 52(outv) 65 + Line 1 31 0 + 70: 67 Load 69(s2d) + 74: 11(fvec4) ImageSampleImplicitLod 70 73 + 75: 11(fvec4) Load 52(outv) + 76: 11(fvec4) FAdd 75 74 + Store 52(outv) 76 + Line 1 33 0 + 78: 77(ptr) AccessChain 56 18 18 + 79: 7(int) Load 78 + SelectionMerge 83 None + Switch 79 82 + case 10: 80 + case 20: 81 + 82: Label + Line 1 42 0 + 94: 11(fvec4) Load 52(outv) + 95: 11(fvec4) CompositeConstruct 28 28 28 28 + 96: 11(fvec4) FSub 94 95 + Store 52(outv) 96 + Line 1 43 0 + Branch 83 + 80: Label + Line 1 35 0 + 84: 11(fvec4) Load 52(outv) + 85: 11(fvec4) CompositeConstruct 28 28 28 28 + 86: 11(fvec4) FAdd 84 85 + Store 52(outv) 86 + Line 1 36 0 + Branch 83 + 81: Label + Line 1 38 0 + 88: 11(fvec4) Load 52(outv) + 89: 11(fvec4) VectorTimesScalar 88 45 + Store 52(outv) 89 + Line 1 39 0 + 90: 11(fvec4) Load 52(outv) + 91: 11(fvec4) CompositeConstruct 28 28 28 28 + 92: 11(fvec4) FAdd 90 91 + Store 52(outv) 92 + Line 1 40 0 + Branch 83 + 83: Label + Line 1 46 0 + Store 99(i) 18 + Branch 100 + 100: Label + LoopMerge 102 103 None + Branch 104 + 104: Label + 105: 7(int) Load 99(i) + 107: 37(bool) SLessThan 105 106 + BranchConditional 107 101 102 + 101: Label + Line 1 47 0 + 108: 11(fvec4) Load 52(outv) + 109: 11(fvec4) VectorTimesScalar 108 36 + Store 52(outv) 109 + Branch 103 + 103: Label + Line 1 46 0 + 110: 7(int) Load 99(i) + 112: 7(int) IAdd 110 111 + Store 99(i) 112 + Branch 100 + 102: Label + Line 1 49 0 + 115: 114(ptr) AccessChain 52(outv) 32 + 116: 10(float) Load 115 + 118: 37(bool) FOrdLessThan 116 117 + SelectionMerge 120 None + BranchConditional 118 119 123 + 119: Label + Line 1 50 0 + 121: 11(fvec4) Load 52(outv) + 122: 11(fvec4) ExtInst 2(GLSL.std.450) 13(Sin) 121 + Store 52(outv) 122 + Store 113 122 + Branch 120 + 123: Label + Line 1 51 0 + 124: 11(fvec4) Load 52(outv) + 125: 11(fvec4) ExtInst 2(GLSL.std.450) 14(Cos) 124 + Store 52(outv) 125 + Store 113 125 + Branch 120 + 120: Label Return FunctionEnd -12(foo(struct-S-i11;): 3 Function None 10 - 11(s): 9(ptr) FunctionParameter - 13: Label - 20: 19(ptr) AccessChain 11(s) 18 +14(foo(struct-S-i11;): 11(fvec4) Function None 12 + 13(s): 9(ptr) FunctionParameter + 15: Label + 17(r): 16(ptr) Variable Function + Line 1 18 0 + 20: 19(ptr) AccessChain 13(s) 18 21: 7(int) Load 20 - 22: 14(float) ConvertSToF 21 - 25: 15(fvec4) Load 24(inv) - 26: 15(fvec4) VectorTimesScalar 25 22 - Store 17(outv) 26 - Return + 22: 10(float) ConvertSToF 21 + 25: 11(fvec4) Load 24(inv) + 26: 11(fvec4) VectorTimesScalar 25 22 + Store 17(r) 26 + Line 1 19 0 + 27: 11(fvec4) Load 17(r) + 29: 11(fvec4) CompositeConstruct 28 28 28 28 + 30: 11(fvec4) FAdd 27 29 + Store 17(r) 30 + Line 1 20 0 + 34: 33(ptr) AccessChain 17(r) 32 + 35: 10(float) Load 34 + 38: 37(bool) FOrdGreaterThan 35 36 + SelectionMerge 40 None + BranchConditional 38 39 44 + 39: Label + Line 1 21 0 + 41: 11(fvec4) Load 17(r) + 42: 11(fvec4) CompositeConstruct 28 28 28 28 + 43: 11(fvec4) FSub 41 42 + Store 17(r) 43 + Branch 40 + 44: Label + Line 1 23 0 + 46: 11(fvec4) Load 17(r) + 47: 11(fvec4) VectorTimesScalar 46 45 + Store 17(r) 47 + Branch 40 + 40: Label + Line 1 25 0 + 48: 11(fvec4) Load 17(r) + ReturnValue 48 FunctionEnd diff --git a/Test/spv.debugInfo.frag b/Test/spv.debugInfo.frag index e2fc257f40..3b6cd27fea 100644 --- a/Test/spv.debugInfo.frag +++ b/Test/spv.debugInfo.frag @@ -8,15 +8,45 @@ uniform ubuf { S s; }; +uniform sampler2D s2d; + layout(location = 0) in vec4 inv; 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() { - 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