SPV: Fix #1575, fix #1593: Support HLSL #line

SPIR-V OpLines now contain filenames from HLSL-style #lines.
This commit is contained in:
greg-lunarg 2018-12-07 17:36:33 -07:00 committed by John Kessenich
parent 127cea5c9a
commit 5d43c4aac7
18 changed files with 754 additions and 39 deletions

View File

@ -1594,7 +1594,7 @@ void TGlslangToSpvTraverser::visitSymbol(glslang::TIntermSymbol* symbol)
bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::TIntermBinary* node)
{
builder.setLine(node->getLoc().line);
builder.setLine(node->getLoc().line, node->getLoc().getFilename());
SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder);
if (node->getType().getQualifier().isSpecConstant())
@ -1789,7 +1789,7 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TIntermUnary* node)
{
builder.setLine(node->getLoc().line);
builder.setLine(node->getLoc().line, node->getLoc().getFilename());
SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder);
if (node->getType().getQualifier().isSpecConstant())
@ -2053,7 +2053,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
return false;
case glslang::EOpFunctionCall:
{
builder.setLine(node->getLoc().line);
builder.setLine(node->getLoc().line, node->getLoc().getFilename());
if (node->isUserDefined())
result = handleUserFunctionCall(node);
// assert(result); // this can happen for bad shaders because the call graph completeness checking is not yet done
@ -2172,7 +2172,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
case glslang::EOpConstructStruct:
case glslang::EOpConstructTextureSampler:
{
builder.setLine(node->getLoc().line);
builder.setLine(node->getLoc().line, node->getLoc().getFilename());
std::vector<spv::Id> arguments;
translateArguments(*node, arguments);
spv::Id constructed;
@ -2317,7 +2317,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
right->traverse(this);
spv::Id rightId = accessChainLoad(right->getType());
builder.setLine(node->getLoc().line);
builder.setLine(node->getLoc().line, node->getLoc().getFilename());
OpDecorations decorations = { precision,
TranslateNoContractionDecoration(node->getType().getQualifier()),
TranslateNonUniformDecoration(node->getType().getQualifier()) };
@ -2405,12 +2405,12 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
if (lvalue)
operands.push_back(builder.accessChainGetLValue());
else {
builder.setLine(node->getLoc().line);
builder.setLine(node->getLoc().line, node->getLoc().getFilename());
operands.push_back(accessChainLoad(glslangOperands[arg]->getAsTyped()->getType()));
}
}
builder.setLine(node->getLoc().line);
builder.setLine(node->getLoc().line, node->getLoc().getFilename());
if (atomic) {
// Handle all atomics
result = createAtomicOperation(node->getOp(), precision, resultType(), operands, node->getBasicType());
@ -2511,7 +2511,7 @@ bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang
node->getFalseBlock()->traverse(this);
spv::Id falseValue = accessChainLoad(node->getTrueBlock()->getAsTyped()->getType());
builder.setLine(node->getLoc().line);
builder.setLine(node->getLoc().line, node->getLoc().getFilename());
// done if void
if (node->getBasicType() == glslang::EbtVoid)
@ -2685,7 +2685,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.setLine(node->getLoc().line, node->getLoc().getFilename());
builder.setBuildPoint(&blocks.head);
builder.createLoopMerge(&blocks.merge, &blocks.continue_target, control, dependencyLength);
if (node->testFirst() && node->getTest()) {
@ -2709,7 +2709,7 @@ bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIn
node->getTerminal()->traverse(this);
builder.createBranch(&blocks.head);
} else {
builder.setLine(node->getLoc().line);
builder.setLine(node->getLoc().line, node->getLoc().getFilename());
builder.createBranch(&blocks.body);
breakForLoop.push(true);
@ -2744,7 +2744,7 @@ bool TGlslangToSpvTraverser::visitBranch(glslang::TVisit /* visit */, glslang::T
if (node->getExpression())
node->getExpression()->traverse(this);
builder.setLine(node->getLoc().line);
builder.setLine(node->getLoc().line, node->getLoc().getFilename());
switch (node->getFlowOp()) {
case glslang::EOpKill:
@ -3913,7 +3913,7 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
if (! node->isImage() && ! node->isTexture())
return spv::NoResult;
builder.setLine(node->getLoc().line);
builder.setLine(node->getLoc().line, node->getLoc().getFilename());
// Process a GLSL texturing op (will be SPV image)

View File

@ -60,6 +60,7 @@ Builder::Builder(unsigned int spvVersion, unsigned int magicNumber, SpvBuildLogg
sourceVersion(0),
sourceFileStringId(NoResult),
currentLine(0),
currentFile(nullptr),
emitOpLines(false),
addressModel(AddressingModelLogical),
memoryModel(MemoryModelGLSL450),
@ -87,8 +88,9 @@ 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.
// Emit instruction for non-filename-based #line directives (ie. no filename
// seen yet): 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) {
@ -98,6 +100,38 @@ void Builder::setLine(int lineNum)
}
}
// If no filename, do non-filename-based #line emit. Else do filename-based emit.
// Emit OpLine if we've been asked to emit OpLines and the line number or filename
// has changed since the last time, and line number is valid.
void Builder::setLine(int lineNum, const char* filename)
{
if (filename == nullptr) {
setLine(lineNum);
return;
}
if ((lineNum != 0 && lineNum != currentLine) || currentFile == nullptr ||
strncmp(filename, currentFile, strlen(currentFile) + 1) != 0) {
currentLine = lineNum;
currentFile = filename;
if (emitOpLines) {
// If filename previously seen, use its id, else create a string
// and put it in the map.
auto sItr = stringIds.find(filename);
if (sItr != stringIds.end()) {
addLine(sItr->second, currentLine, 0);
} else {
Instruction* fileString =
new Instruction(getUniqueId(), NoType, OpString);
fileString->addStringOperand(filename);
spv::Id stringId = fileString->getResultId();
strings.push_back(std::unique_ptr<Instruction>(fileString));
addLine(stringId, currentLine, 0);
stringIds[filename] = stringId;
}
}
}
}
void Builder::addLine(Id fileName, int lineNum, int column)
{
Instruction* line = new Instruction(OpLine);

View File

@ -77,9 +77,11 @@ public:
void setSourceFile(const std::string& file)
{
Instruction* fileString = new Instruction(getUniqueId(), NoType, OpString);
fileString->addStringOperand(file.c_str());
const char* file_c_str = file.c_str();
fileString->addStringOperand(file_c_str);
sourceFileStringId = fileString->getResultId();
strings.push_back(std::unique_ptr<Instruction>(fileString));
stringIds[file_c_str] = sourceFileStringId;
}
void setSourceText(const std::string& text) { sourceText = text; }
void addSourceExtension(const char* ext) { sourceExtensions.push_back(ext); }
@ -106,9 +108,16 @@ public:
return id;
}
// Log the current line, and if different than the last one,
// issue a new OpLine, using the current file name.
// Generate OpLine for non-filename-based #line directives (ie no filename
// seen yet): Log the current line, and if different than the last one,
// issue a new OpLine using the new line and current source file name.
void setLine(int line);
// If filename null, generate OpLine for non-filename-based line directives,
// else do filename-based: Log the current line and file, and if different
// than the last one, issue a new OpLine using the new line and file
// name.
void setLine(int line, const char* filename);
// Low-level OpLine. See setLine() for a layered helper.
void addLine(Id fileName, int line, int column);
@ -658,6 +667,7 @@ public:
spv::Id sourceFileStringId;
std::string sourceText;
int currentLine;
const char* currentFile;
bool emitOpLines;
std::set<std::string> extensions;
std::vector<const char*> sourceExtensions;
@ -695,6 +705,9 @@ public:
// Our loop stack.
std::stack<LoopBlocks> loops;
// map from strings to their string ids
std::unordered_map<std::string, spv::Id> stringIds;
// The stream for outputting warnings and errors.
SpvBuildLogger* logger;
}; // end Builder class

View File

@ -0,0 +1,183 @@
hlsl.pp.line2.frag
// Module Version 10000
// Generated by (magic number): 80007
// Id's are bound by 80
Capability Shader
2: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450
EntryPoint Fragment 5 "MainPs" 71 75
ExecutionMode 5 OriginUpperLeft
1: String "hlsl.pp.line2.frag"
17: String "foo.frag"
32: String "foo.h"
42: String "foo2.h"
Source HLSL 500 1 "// OpModuleProcessed auto-map-locations
// OpModuleProcessed auto-map-bindings
// OpModuleProcessed entry-point MainPs
// OpModuleProcessed client vulkan100
// OpModuleProcessed target-env vulkan1.0
// OpModuleProcessed keep-uncalled
// OpModuleProcessed hlsl-offsets
#line 1
#line 1 "foo.frag"
Texture2D g_tColor[ 128 ] ;
layout (push_constant) cbuffer PerViewConstantBuffer_t
{
uint g_nDataIdx;
uint g_nDataIdx2;
bool g_B;
} ;
SamplerState g_sAniso;
struct PS_INPUT
{
float2 vTextureCoords : TEXCOORD2 ;
} ;
struct PS_OUTPUT
{
float4 vColor : SV_Target0 ;
} ;
PS_OUTPUT MainPs ( PS_INPUT i )
{
PS_OUTPUT ps_output ;
uint u;
#line 47
if (g_B)
#line 3 "foo.h"
u = g_nDataIdx;
else
#line 67
u = g_nDataIdx2;
#line 7 "foo2.h"
ps_output . vColor = g_tColor [ u ] . Sample ( g_sAniso , i . vTextureCoords . xy );
#line 105
return ps_output ;
}
"
Name 5 "MainPs"
Name 9 "PS_INPUT"
MemberName 9(PS_INPUT) 0 "vTextureCoords"
Name 12 "PS_OUTPUT"
MemberName 12(PS_OUTPUT) 0 "vColor"
Name 15 "@MainPs(struct-PS_INPUT-vf21;"
Name 14 "i"
Name 19 "PerViewConstantBuffer_t"
MemberName 19(PerViewConstantBuffer_t) 0 "g_nDataIdx"
MemberName 19(PerViewConstantBuffer_t) 1 "g_nDataIdx2"
MemberName 19(PerViewConstantBuffer_t) 2 "g_B"
Name 21 ""
Name 34 "u"
Name 44 "ps_output"
Name 49 "g_tColor"
Name 56 "g_sAniso"
Name 69 "i"
Name 71 "i.vTextureCoords"
Name 75 "@entryPointOutput.vColor"
Name 76 "param"
MemberDecorate 19(PerViewConstantBuffer_t) 0 Offset 0
MemberDecorate 19(PerViewConstantBuffer_t) 1 Offset 4
MemberDecorate 19(PerViewConstantBuffer_t) 2 Offset 8
Decorate 19(PerViewConstantBuffer_t) Block
Decorate 49(g_tColor) DescriptorSet 0
Decorate 56(g_sAniso) DescriptorSet 0
Decorate 71(i.vTextureCoords) Location 0
Decorate 75(@entryPointOutput.vColor) Location 0
3: TypeVoid
4: TypeFunction 3
7: TypeFloat 32
8: TypeVector 7(float) 2
9(PS_INPUT): TypeStruct 8(fvec2)
10: TypePointer Function 9(PS_INPUT)
11: TypeVector 7(float) 4
12(PS_OUTPUT): TypeStruct 11(fvec4)
13: TypeFunction 12(PS_OUTPUT) 10(ptr)
18: TypeInt 32 0
19(PerViewConstantBuffer_t): TypeStruct 18(int) 18(int) 18(int)
20: TypePointer PushConstant 19(PerViewConstantBuffer_t)
21: 20(ptr) Variable PushConstant
22: TypeInt 32 1
23: 22(int) Constant 2
24: TypePointer PushConstant 18(int)
27: TypeBool
28: 18(int) Constant 0
33: TypePointer Function 18(int)
35: 22(int) Constant 0
39: 22(int) Constant 1
43: TypePointer Function 12(PS_OUTPUT)
45: TypeImage 7(float) 2D sampled format:Unknown
46: 18(int) Constant 128
47: TypeArray 45 46
48: TypePointer UniformConstant 47
49(g_tColor): 48(ptr) Variable UniformConstant
51: TypePointer UniformConstant 45
54: TypeSampler
55: TypePointer UniformConstant 54
56(g_sAniso): 55(ptr) Variable UniformConstant
58: TypeSampledImage 45
60: TypePointer Function 8(fvec2)
64: TypePointer Function 11(fvec4)
70: TypePointer Input 8(fvec2)
71(i.vTextureCoords): 70(ptr) Variable Input
74: TypePointer Output 11(fvec4)
75(@entryPointOutput.vColor): 74(ptr) Variable Output
5(MainPs): 3 Function None 4
6: Label
69(i): 10(ptr) Variable Function
76(param): 10(ptr) Variable Function
Line 17 23 0
72: 8(fvec2) Load 71(i.vTextureCoords)
73: 60(ptr) AccessChain 69(i) 35
Store 73 72
77: 9(PS_INPUT) Load 69(i)
Store 76(param) 77
78:12(PS_OUTPUT) FunctionCall 15(@MainPs(struct-PS_INPUT-vf21;) 76(param)
79: 11(fvec4) CompositeExtract 78 0
Store 75(@entryPointOutput.vColor) 79
Return
FunctionEnd
15(@MainPs(struct-PS_INPUT-vf21;):12(PS_OUTPUT) Function None 13
14(i): 10(ptr) FunctionParameter
16: Label
34(u): 33(ptr) Variable Function
44(ps_output): 43(ptr) Variable Function
Line 17 47 0
25: 24(ptr) AccessChain 21 23
26: 18(int) Load 25
29: 27(bool) INotEqual 26 28
SelectionMerge 31 None
BranchConditional 29 30 38
30: Label
Line 32 3 0
36: 24(ptr) AccessChain 21 35
37: 18(int) Load 36
Store 34(u) 37
Branch 31
38: Label
Line 32 67 0
40: 24(ptr) AccessChain 21 39
41: 18(int) Load 40
Store 34(u) 41
Branch 31
31: Label
Line 42 7 0
50: 18(int) Load 34(u)
52: 51(ptr) AccessChain 49(g_tColor) 50
53: 45 Load 52
57: 54 Load 56(g_sAniso)
59: 58 SampledImage 53 57
61: 60(ptr) AccessChain 14(i) 35
62: 8(fvec2) Load 61
63: 11(fvec4) ImageSampleImplicitLod 59 62
65: 64(ptr) AccessChain 44(ps_output) 35
Store 65 63
Line 42 105 0
66:12(PS_OUTPUT) Load 44(ps_output)
ReturnValue 66
FunctionEnd

View File

@ -0,0 +1,172 @@
hlsl.pp.line3.frag
// Module Version 10000
// Generated by (magic number): 80007
// Id's are bound by 78
Capability Shader
2: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450
EntryPoint Fragment 5 "MainPs" 69 73
ExecutionMode 5 OriginUpperLeft
1: String "hlsl.pp.line3.frag"
31: String "./i1.h"
Source HLSL 500 1 "// OpModuleProcessed entry-point MainPs
// OpModuleProcessed client vulkan100
// OpModuleProcessed target-env vulkan1.0
// OpModuleProcessed hlsl-offsets
#line 1
Texture2D g_tColor[ 128 ] ;
layout (push_constant) cbuffer PerViewConstantBuffer_t
{
uint g_nDataIdx;
uint g_nDataIdx2;
bool g_B;
} ;
SamplerState g_sAniso;
struct PS_INPUT
{
float2 vTextureCoords : TEXCOORD2 ;
} ;
struct PS_OUTPUT
{
float4 vColor : SV_Target0 ;
} ;
PS_OUTPUT MainPs ( PS_INPUT i )
{
PS_OUTPUT ps_output ;
uint u;
if (g_B)
#include "i1.h"
else
u = g_nDataIdx2;
ps_output . vColor = g_tColor [ u ] . Sample ( g_sAniso , i . vTextureCoords . xy );
return ps_output ;
}
"
Name 5 "MainPs"
Name 9 "PS_INPUT"
MemberName 9(PS_INPUT) 0 "vTextureCoords"
Name 12 "PS_OUTPUT"
MemberName 12(PS_OUTPUT) 0 "vColor"
Name 15 "@MainPs(struct-PS_INPUT-vf21;"
Name 14 "i"
Name 18 "PerViewConstantBuffer_t"
MemberName 18(PerViewConstantBuffer_t) 0 "g_nDataIdx"
MemberName 18(PerViewConstantBuffer_t) 1 "g_nDataIdx2"
MemberName 18(PerViewConstantBuffer_t) 2 "g_B"
Name 20 ""
Name 33 "u"
Name 42 "ps_output"
Name 47 "g_tColor"
Name 54 "g_sAniso"
Name 67 "i"
Name 69 "i.vTextureCoords"
Name 73 "@entryPointOutput.vColor"
Name 74 "param"
MemberDecorate 18(PerViewConstantBuffer_t) 0 Offset 0
MemberDecorate 18(PerViewConstantBuffer_t) 1 Offset 4
MemberDecorate 18(PerViewConstantBuffer_t) 2 Offset 8
Decorate 18(PerViewConstantBuffer_t) Block
Decorate 47(g_tColor) DescriptorSet 0
Decorate 54(g_sAniso) DescriptorSet 0
Decorate 69(i.vTextureCoords) Location 0
Decorate 73(@entryPointOutput.vColor) Location 0
3: TypeVoid
4: TypeFunction 3
7: TypeFloat 32
8: TypeVector 7(float) 2
9(PS_INPUT): TypeStruct 8(fvec2)
10: TypePointer Function 9(PS_INPUT)
11: TypeVector 7(float) 4
12(PS_OUTPUT): TypeStruct 11(fvec4)
13: TypeFunction 12(PS_OUTPUT) 10(ptr)
17: TypeInt 32 0
18(PerViewConstantBuffer_t): TypeStruct 17(int) 17(int) 17(int)
19: TypePointer PushConstant 18(PerViewConstantBuffer_t)
20: 19(ptr) Variable PushConstant
21: TypeInt 32 1
22: 21(int) Constant 2
23: TypePointer PushConstant 17(int)
26: TypeBool
27: 17(int) Constant 0
32: TypePointer Function 17(int)
34: 21(int) Constant 0
38: 21(int) Constant 1
41: TypePointer Function 12(PS_OUTPUT)
43: TypeImage 7(float) 2D sampled format:Unknown
44: 17(int) Constant 128
45: TypeArray 43 44
46: TypePointer UniformConstant 45
47(g_tColor): 46(ptr) Variable UniformConstant
49: TypePointer UniformConstant 43
52: TypeSampler
53: TypePointer UniformConstant 52
54(g_sAniso): 53(ptr) Variable UniformConstant
56: TypeSampledImage 43
58: TypePointer Function 8(fvec2)
62: TypePointer Function 11(fvec4)
68: TypePointer Input 8(fvec2)
69(i.vTextureCoords): 68(ptr) Variable Input
72: TypePointer Output 11(fvec4)
73(@entryPointOutput.vColor): 72(ptr) Variable Output
5(MainPs): 3 Function None 4
6: Label
67(i): 10(ptr) Variable Function
74(param): 10(ptr) Variable Function
Line 1 23 0
70: 8(fvec2) Load 69(i.vTextureCoords)
71: 58(ptr) AccessChain 67(i) 34
Store 71 70
75: 9(PS_INPUT) Load 67(i)
Store 74(param) 75
76:12(PS_OUTPUT) FunctionCall 15(@MainPs(struct-PS_INPUT-vf21;) 74(param)
77: 11(fvec4) CompositeExtract 76 0
Store 73(@entryPointOutput.vColor) 77
Return
FunctionEnd
15(@MainPs(struct-PS_INPUT-vf21;):12(PS_OUTPUT) Function None 13
14(i): 10(ptr) FunctionParameter
16: Label
33(u): 32(ptr) Variable Function
42(ps_output): 41(ptr) Variable Function
Line 1 27 0
24: 23(ptr) AccessChain 20 22
25: 17(int) Load 24
28: 26(bool) INotEqual 25 27
SelectionMerge 30 None
BranchConditional 28 29 37
29: Label
Line 31 1 0
35: 23(ptr) AccessChain 20 34
36: 17(int) Load 35
Store 33(u) 36
Branch 30
37: Label
Line 1 30 0
39: 23(ptr) AccessChain 20 38
40: 17(int) Load 39
Store 33(u) 40
Branch 30
30: Label
Line 1 31 0
48: 17(int) Load 33(u)
50: 49(ptr) AccessChain 47(g_tColor) 48
51: 43 Load 50
55: 52 Load 54(g_sAniso)
57: 56 SampledImage 51 55
59: 58(ptr) AccessChain 14(i) 34
60: 8(fvec2) Load 59
61: 11(fvec4) ImageSampleImplicitLod 57 60
63: 62(ptr) AccessChain 42(ps_output) 34
Store 63 61
Line 1 32 0
64:12(PS_OUTPUT) Load 42(ps_output)
ReturnValue 64
FunctionEnd

View File

@ -0,0 +1,144 @@
spv.pp.line.frag
WARNING: spv.pp.line.frag:6: varying deprecated in version 130; may be removed in future release
WARNING: spv.pp.line.frag:7: varying deprecated in version 130; may be removed in future release
// Module Version 10000
// Generated by (magic number): 80007
// Id's are bound by 65
Capability Shader
Capability Sampled1D
2: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450
EntryPoint Fragment 5 "main" 41 53 56 59
ExecutionMode 5 OriginUpperLeft
1: String "spv.pp.line.frag"
Source GLSL 140 1 "// OpModuleProcessed auto-map-locations
// OpModuleProcessed auto-map-bindings
// OpModuleProcessed client vulkan100
// OpModuleProcessed target-env vulkan1.0
// OpModuleProcessed keep-uncalled
// OpModuleProcessed entry-point main
#line 1
#version 140
uniform sampler1D texSampler1D;
uniform sampler2D texSampler2D;
varying float blend;
varying vec4 u;
in vec2 coords2D;
void main()
{
float blendscale = 1.789;
float bias = 2.0;
float coords1D = 1.789;
vec4 color = vec4(0.0, 0.0, 0.0, 0.0);
#line 53
color += texture (texSampler1D, coords1D);
color += texture (texSampler1D, coords1D, bias);
#line 102
color += texture (texSampler2D, coords2D);
color += texture (texSampler2D, coords2D, bias);
gl_FragColor = mix(color, u, blend * blendscale);
}
"
Name 5 "main"
Name 9 "blendscale"
Name 11 "bias"
Name 13 "coords1D"
Name 16 "color"
Name 22 "texSampler1D"
Name 37 "texSampler2D"
Name 41 "coords2D"
Name 53 "gl_FragColor"
Name 56 "u"
Name 59 "blend"
Decorate 22(texSampler1D) DescriptorSet 0
Decorate 37(texSampler2D) DescriptorSet 0
Decorate 53(gl_FragColor) Location 0
3: TypeVoid
4: TypeFunction 3
7: TypeFloat 32
8: TypePointer Function 7(float)
10: 7(float) Constant 1071971828
12: 7(float) Constant 1073741824
14: TypeVector 7(float) 4
15: TypePointer Function 14(fvec4)
17: 7(float) Constant 0
18: 14(fvec4) ConstantComposite 17 17 17 17
19: TypeImage 7(float) 1D sampled format:Unknown
20: TypeSampledImage 19
21: TypePointer UniformConstant 20
22(texSampler1D): 21(ptr) Variable UniformConstant
34: TypeImage 7(float) 2D sampled format:Unknown
35: TypeSampledImage 34
36: TypePointer UniformConstant 35
37(texSampler2D): 36(ptr) Variable UniformConstant
39: TypeVector 7(float) 2
40: TypePointer Input 39(fvec2)
41(coords2D): 40(ptr) Variable Input
52: TypePointer Output 14(fvec4)
53(gl_FragColor): 52(ptr) Variable Output
55: TypePointer Input 14(fvec4)
56(u): 55(ptr) Variable Input
58: TypePointer Input 7(float)
59(blend): 58(ptr) Variable Input
5(main): 3 Function None 4
6: Label
9(blendscale): 8(ptr) Variable Function
11(bias): 8(ptr) Variable Function
13(coords1D): 8(ptr) Variable Function
16(color): 15(ptr) Variable Function
Line 1 13 0
Store 9(blendscale) 10
Line 1 14 0
Store 11(bias) 12
Line 1 15 0
Store 13(coords1D) 10
Line 1 16 0
Store 16(color) 18
Line 1 54 0
23: 20 Load 22(texSampler1D)
24: 7(float) Load 13(coords1D)
25: 14(fvec4) ImageSampleImplicitLod 23 24
26: 14(fvec4) Load 16(color)
27: 14(fvec4) FAdd 26 25
Store 16(color) 27
Line 1 55 0
28: 20 Load 22(texSampler1D)
29: 7(float) Load 13(coords1D)
30: 7(float) Load 11(bias)
31: 14(fvec4) ImageSampleImplicitLod 28 29 Bias 30
32: 14(fvec4) Load 16(color)
33: 14(fvec4) FAdd 32 31
Store 16(color) 33
Line 1 103 0
38: 35 Load 37(texSampler2D)
42: 39(fvec2) Load 41(coords2D)
43: 14(fvec4) ImageSampleImplicitLod 38 42
44: 14(fvec4) Load 16(color)
45: 14(fvec4) FAdd 44 43
Store 16(color) 45
Line 1 104 0
46: 35 Load 37(texSampler2D)
47: 39(fvec2) Load 41(coords2D)
48: 7(float) Load 11(bias)
49: 14(fvec4) ImageSampleImplicitLod 46 47 Bias 48
50: 14(fvec4) Load 16(color)
51: 14(fvec4) FAdd 50 49
Store 16(color) 51
Line 1 106 0
54: 14(fvec4) Load 16(color)
57: 14(fvec4) Load 56(u)
60: 7(float) Load 59(blend)
61: 7(float) Load 9(blendscale)
62: 7(float) FMul 60 61
63: 14(fvec4) CompositeConstruct 62 62 62 62
64: 14(fvec4) ExtInst 2(GLSL.std.450) 46(FMix) 54 57 63
Store 53(gl_FragColor) 64
Return
FunctionEnd

40
Test/hlsl.pp.line2.frag Normal file
View File

@ -0,0 +1,40 @@
#line 1 "foo.frag"
Texture2D g_tColor[ 128 ] ;
layout (push_constant) cbuffer PerViewConstantBuffer_t
{
uint g_nDataIdx;
uint g_nDataIdx2;
bool g_B;
} ;
SamplerState g_sAniso;
struct PS_INPUT
{
float2 vTextureCoords : TEXCOORD2 ;
} ;
struct PS_OUTPUT
{
float4 vColor : SV_Target0 ;
} ;
PS_OUTPUT MainPs ( PS_INPUT i )
{
PS_OUTPUT ps_output ;
uint u;
#line 47
if (g_B)
#line 3 "foo.h"
u = g_nDataIdx;
else
#line 67
u = g_nDataIdx2;
#line 7 "foo2.h"
ps_output . vColor = g_tColor [ u ] . Sample ( g_sAniso , i . vTextureCoords . xy );
#line 105
return ps_output ;
}

34
Test/hlsl.pp.line3.frag Normal file
View File

@ -0,0 +1,34 @@
Texture2D g_tColor[ 128 ] ;
layout (push_constant) cbuffer PerViewConstantBuffer_t
{
uint g_nDataIdx;
uint g_nDataIdx2;
bool g_B;
} ;
SamplerState g_sAniso;
struct PS_INPUT
{
float2 vTextureCoords : TEXCOORD2 ;
} ;
struct PS_OUTPUT
{
float4 vColor : SV_Target0 ;
} ;
PS_OUTPUT MainPs ( PS_INPUT i )
{
PS_OUTPUT ps_output ;
uint u;
if (g_B)
#include "i1.h"
else
u = g_nDataIdx2;
ps_output . vColor = g_tColor [ u ] . Sample ( g_sAniso , i . vTextureCoords . xy );
return ps_output ;
}

1
Test/i1.h Normal file
View File

@ -0,0 +1 @@
u = g_nDataIdx;

View File

@ -152,6 +152,8 @@ $EXE -l -i include.vert > $TARGETDIR/include.vert.out
diff -b $BASEDIR/include.vert.out $TARGETDIR/include.vert.out || HASERROR=1
$EXE -D -Od -e main -H -Od -Iinc1/path1 -Iinc1/path2 hlsl.dashI.vert > $TARGETDIR/hlsl.dashI.vert.out
diff -b $BASEDIR/hlsl.dashI.vert.out $TARGETDIR/hlsl.dashI.vert.out || HASERROR=1
$EXE -D -Od -e MainPs -H -Od -g hlsl.pp.line3.frag > $TARGETDIR/hlsl.pp.line3.frag.out
diff -b $BASEDIR/hlsl.pp.line3.frag.out $TARGETDIR/hlsl.pp.line3.frag.out || HASERROR=1
#
# Testing -D and -U

25
Test/spv.pp.line.frag Normal file
View File

@ -0,0 +1,25 @@
#version 140
uniform sampler1D texSampler1D;
uniform sampler2D texSampler2D;
varying float blend;
varying vec4 u;
in vec2 coords2D;
void main()
{
float blendscale = 1.789;
float bias = 2.0;
float coords1D = 1.789;
vec4 color = vec4(0.0, 0.0, 0.0, 0.0);
#line 53
color += texture (texSampler1D, coords1D);
color += texture (texSampler1D, coords1D, bias);
#line 102
color += texture (texSampler2D, coords2D);
color += texture (texSampler2D, coords2D, bias);
gl_FragColor = mix(color, u, blend * blendscale);
}

View File

@ -229,16 +229,28 @@ inline const TString String(const int i, const int /*base*/ = 10)
#endif
struct TSourceLoc {
void init() { name = nullptr; string = 0; line = 0; column = 0; }
void init()
{
name = nullptr; string = 0; line = 0; column = 0;
}
void init(int stringNum) { init(); string = stringNum; }
// Returns the name if it exists. Otherwise, returns the string number.
std::string getStringNameOrNum(bool quoteStringName = true) const
{
if (name != nullptr)
return quoteStringName ? ("\"" + std::string(name) + "\"") : name;
if (name != nullptr) {
TString qstr = quoteStringName ? ("\"" + *name + "\"") : *name;
std::string ret_str(qstr.c_str());
return ret_str;
}
return std::to_string((long long)string);
}
const char* name; // descriptive name for this string
const char* getFilename() const
{
if (name == nullptr)
return nullptr;
return name->c_str();
}
TString* name; // descriptive name for this string
int string;
int line;
int column;

View File

@ -65,7 +65,7 @@ public:
}
if (names != nullptr) {
for (int i = 0; i < numSources; ++i)
loc[i].name = names[i];
loc[i].name = names[i] != nullptr ? NewPoolTString(names[i]) : nullptr;
}
loc[currentSource].line = 1;
logicalSourceLoc.init(1);
@ -170,16 +170,18 @@ public:
// for #line override in filename based parsing
void setFile(const char* filename)
{
logicalSourceLoc.name = filename;
loc[getLastValidSourceIndex()].name = filename;
TString* fn_tstr = NewPoolTString(filename);
logicalSourceLoc.name = fn_tstr;
loc[getLastValidSourceIndex()].name = fn_tstr;
}
void setFile(const char* filename, int i)
{
TString* fn_tstr = NewPoolTString(filename);
if (i == getLastValidSourceIndex()) {
logicalSourceLoc.name = filename;
logicalSourceLoc.name = fn_tstr;
}
loc[i].name = filename;
loc[i].name = fn_tstr;
}
void setString(int newString)

View File

@ -533,7 +533,7 @@ protected:
prologue_(prologue),
epilogue_(epilogue),
includedFile_(includedFile),
scanner(3, strings, lengths, names, 0, 0, true),
scanner(3, strings, lengths, nullptr, 0, 0, true),
prevScanner(nullptr),
stringInput(pp, scanner)
{
@ -548,9 +548,9 @@ protected:
scanner.setLine(startLoc.line);
scanner.setString(startLoc.string);
scanner.setFile(startLoc.name, 0);
scanner.setFile(startLoc.name, 1);
scanner.setFile(startLoc.name, 2);
scanner.setFile(startLoc.name->c_str(), 0);
scanner.setFile(startLoc.name->c_str(), 1);
scanner.setFile(startLoc.name->c_str(), 2);
}
// tInput methods:
@ -590,8 +590,6 @@ protected:
const char* strings[3];
// Length of str_, passed to scanner constructor.
size_t lengths[3];
// String names
const char* names[3];
// Scans over str_.
TInputScanner scanner;
// The previous effective scanner before the scanner in this instance

View File

@ -61,6 +61,7 @@ using HlslCompileTest = GlslangTest<::testing::TestWithParam<FileNameEntryPointP
using HlslVulkan1_1CompileTest = GlslangTest<::testing::TestWithParam<FileNameEntryPointPair>>;
using HlslCompileAndFlattenTest = GlslangTest<::testing::TestWithParam<FileNameEntryPointPair>>;
using HlslLegalizeTest = GlslangTest<::testing::TestWithParam<FileNameEntryPointPair>>;
using HlslDebugTest = GlslangTest<::testing::TestWithParam<FileNameEntryPointPair>>;
// Compiling HLSL to pre-legalized SPIR-V under Vulkan semantics. Expected
// to successfully generate both AST and SPIR-V.
@ -95,6 +96,16 @@ TEST_P(HlslLegalizeTest, FromFile)
"/baseLegalResults/", true);
}
// Compiling HLSL to pre-legalized SPIR-V. Expected to successfully generate
// SPIR-V with debug instructions, particularly line info.
TEST_P(HlslDebugTest, FromFile)
{
loadFileCompileAndCheck(GlobalTestSettings.testRoot, GetParam().fileName,
Source::HLSL, Semantics::Vulkan, glslang::EShTargetVulkan_1_0,
Target::Spv, true, GetParam().entryPoint,
"/baseResults/", false, true);
}
// clang-format off
INSTANTIATE_TEST_CASE_P(
ToSpirv, HlslCompileTest,
@ -437,5 +448,15 @@ INSTANTIATE_TEST_CASE_P(
// clang-format on
#endif
// clang-format off
INSTANTIATE_TEST_CASE_P(
ToSpirv, HlslDebugTest,
::testing::ValuesIn(std::vector<FileNameEntryPointPair>{
{"hlsl.pp.line2.frag", "MainPs"}
}),
FileNameAsCustomTestSuffix
);
// clang-format on
} // anonymous namespace
} // namespace glslangtest

View File

@ -63,6 +63,7 @@ std::string FileNameAsCustomTestSuffixIoMap(
}
using CompileVulkanToSpirvTest = GlslangTest<::testing::TestWithParam<std::string>>;
using CompileVulkanToDebugSpirvTest = GlslangTest<::testing::TestWithParam<std::string>>;
using CompileVulkan1_1ToSpirvTest = GlslangTest<::testing::TestWithParam<std::string>>;
using CompileOpenGLToSpirvTest = GlslangTest<::testing::TestWithParam<std::string>>;
using VulkanSemantics = GlslangTest<::testing::TestWithParam<std::string>>;
@ -87,6 +88,17 @@ TEST_P(CompileVulkanToSpirvTest, FromFile)
Target::Spv);
}
// Compiling GLSL to SPIR-V with debug info under Vulkan semantics. Expected
// to successfully generate SPIR-V.
TEST_P(CompileVulkanToDebugSpirvTest, FromFile)
{
loadFileCompileAndCheck(GlobalTestSettings.testRoot, GetParam(),
Source::GLSL, Semantics::Vulkan,
glslang::EShTargetVulkan_1_0,
Target::Spv, true, "",
"/baseResults/", false, true);
}
TEST_P(CompileVulkan1_1ToSpirvTest, FromFile)
{
loadFileCompileAndCheck(GlobalTestSettings.testRoot, GetParam(),
@ -369,6 +381,15 @@ INSTANTIATE_TEST_CASE_P(
FileNameAsCustomTestSuffix
);
// clang-format off
INSTANTIATE_TEST_CASE_P(
Glsl, CompileVulkanToDebugSpirvTest,
::testing::ValuesIn(std::vector<std::string>({
"spv.pp.line.frag",
})),
FileNameAsCustomTestSuffix
);
// clang-format off
INSTANTIATE_TEST_CASE_P(
Glsl, CompileVulkan1_1ToSpirvTest,

View File

@ -184,12 +184,19 @@ public:
// and modifies |shader| on success.
bool compile(glslang::TShader* shader, const std::string& code,
const std::string& entryPointName, EShMessages controls,
const TBuiltInResource* resources=nullptr)
const TBuiltInResource* resources=nullptr,
const std::string* shaderName=nullptr)
{
const char* shaderStrings = code.data();
const int shaderLengths = static_cast<int>(code.size());
const char* shaderNames = nullptr;
shader->setStringsWithLengths(&shaderStrings, &shaderLengths, 1);
if ((controls & EShMsgDebugInfo) && shaderName != nullptr) {
shaderNames = shaderName->data();
shader->setStringsWithLengthsAndNames(
&shaderStrings, &shaderLengths, &shaderNames, 1);
} else
shader->setStringsWithLengths(&shaderStrings, &shaderLengths, 1);
if (!entryPointName.empty()) shader->setEntryPoint(entryPointName.c_str());
return shader->parse(
(resources ? resources : &glslang::DefaultTBuiltInResource),
@ -202,12 +209,13 @@ public:
// during the process. If the target includes SPIR-V, also disassembles
// the result and returns disassembly text.
GlslangResult compileAndLink(
const std::string shaderName, const std::string& code,
const std::string& shaderName, const std::string& code,
const std::string& entryPointName, EShMessages controls,
glslang::EShTargetClientVersion clientTargetVersion,
bool flattenUniformArrays = false,
EShTextureSamplerTransformMode texSampTransMode = EShTexSampTransKeep,
bool enableOptimizer = false,
bool enableDebug = false,
bool automap = true)
{
const EShLanguage stage = GetShaderStage(GetSuffix(shaderName));
@ -238,7 +246,8 @@ public:
}
}
bool success = compile(&shader, code, entryPointName, controls);
bool success = compile(
&shader, code, entryPointName, controls, nullptr, &shaderName);
glslang::TProgram program;
program.addShader(&shader);
@ -249,6 +258,7 @@ public:
if (success && (controls & EShMsgSpvRules)) {
std::vector<uint32_t> spirv_binary;
options().disableOptimizer = !enableOptimizer;
options().generateDebugInfo = enableDebug;
glslang::GlslangToSpv(*program.getIntermediate(stage),
spirv_binary, &logger, &options());
@ -423,7 +433,8 @@ public:
bool automap = true,
const std::string& entryPointName="",
const std::string& baseDir="/baseResults/",
const bool enableOptimizer = false)
const bool enableOptimizer = false,
const bool enableDebug = false)
{
const std::string inputFname = testDir + "/" + testName;
const std::string expectedOutputFname =
@ -436,8 +447,10 @@ public:
EShMessages controls = DeriveOptions(source, semantics, target);
if (enableOptimizer)
controls = static_cast<EShMessages>(controls & ~EShMsgHlslLegalization);
if (enableDebug)
controls = static_cast<EShMessages>(controls | EShMsgDebugInfo);
GlslangResult result = compileAndLink(testName, input, entryPointName, controls, clientTargetVersion, false,
EShTexSampTransKeep, enableOptimizer, automap);
EShTexSampTransKeep, enableOptimizer, enableDebug, automap);
// Generate the hybrid output in the way of glslangValidator.
std::ostringstream stream;

View File

@ -133,7 +133,7 @@ bool HlslParseContext::parseShaderStrings(TPpContext& ppContext, TInputScanner&
// Print a message formated such that if you click on the message it will take you right to
// the line through most UIs.
const glslang::TSourceLoc& sourceLoc = input.getSourceLoc();
infoSink.info << sourceLoc.name << "(" << sourceLoc.line << "): error at column " << sourceLoc.column
infoSink.info << sourceLoc.name->c_str() << "(" << sourceLoc.line << "): error at column " << sourceLoc.column
<< ", HLSL parsing failed.\n";
++numErrors;
return false;