diff --git a/StandAlone/DirStackFileIncluder.h b/StandAlone/DirStackFileIncluder.h index 5a33c78fa2..a66e0ae441 100644 --- a/StandAlone/DirStackFileIncluder.h +++ b/StandAlone/DirStackFileIncluder.h @@ -49,19 +49,21 @@ // Can be overridden to customize. class DirStackFileIncluder : public glslang::TShader::Includer { public: - DirStackFileIncluder() : externalLocalDirectoryCount(0) { } + DirStackFileIncluder() { } virtual IncludeResult* includeLocal(const char* headerName, const char* includerName, size_t inclusionDepth) override { - return readLocalPath(headerName, includerName, (int)inclusionDepth); + recordLocalPath(includerName, inclusionDepth); + return readLocalPath(headerName); } virtual IncludeResult* includeSystem(const char* headerName, - const char* /*includerName*/, - size_t /*inclusionDepth*/) override + const char* includerName, + size_t inclusionDepth) override { + recordLocalPath(includerName, inclusionDepth); return readSystemPath(headerName); } @@ -69,12 +71,13 @@ class DirStackFileIncluder : public glslang::TShader::Includer { // - Most-recently pushed are checked first. // - All these are checked after the parse-time stack of local directories // is checked. - // - This only applies to the "local" form of #include. // - Makes its own copy of the path. - virtual void pushExternalLocalDirectory(const std::string& dir) + // - Search paths are processed similar to GCC: "local" inclusions will + // search in the current directory and external directories, while + // inclusions will search external directories only. + virtual void pushExternalDirectory(const std::string& dir) { - directoryStack.push_back(dir); - externalLocalDirectoryCount = (int)directoryStack.size(); + externalDirectoryList.push_back(dir); } virtual void releaseInclude(IncludeResult* result) override @@ -94,27 +97,31 @@ class DirStackFileIncluder : public glslang::TShader::Includer { protected: typedef char tUserDataElement; - std::vector directoryStack; - int externalLocalDirectoryCount; + std::vector localDirectoryStack; + std::vector externalDirectoryList; std::set includedFiles; - // Search for a valid "local" path based on combining the stack of include - // directories and the nominal name of the header. - virtual IncludeResult* readLocalPath(const char* headerName, const char* includerName, int depth) + // Record local path for future local inclusion. + // Discard popped include directories, and + // initialize when at parse-time first level. + void recordLocalPath(const char * includerName, size_t depth) { - // Discard popped include directories, and - // initialize when at parse-time first level. - directoryStack.resize(depth + externalLocalDirectoryCount); + localDirectoryStack.resize(depth); if (depth == 1) - directoryStack.back() = getDirectory(includerName); + localDirectoryStack.back() = getDirectory(includerName); + } + // Search for a valid "local" path based on combining the stack of include + // directories and the nominal name of the header. + virtual IncludeResult* readLocalPath(const char* headerName) + { // Find a directory that works, using a reverse search of the include stack. - for (auto it = directoryStack.rbegin(); it != directoryStack.rend(); ++it) { + for (auto it = localDirectoryStack.rbegin(); it != localDirectoryStack.rend(); ++it) { std::string path = *it + '/' + headerName; std::replace(path.begin(), path.end(), '\\', '/'); std::ifstream file(path, std::ios_base::binary | std::ios_base::ate); if (file) { - directoryStack.push_back(getDirectory(path)); + localDirectoryStack.push_back(getDirectory(path)); includedFiles.insert(path); return newIncludeResult(path, file, (int)file.tellg()); } @@ -124,9 +131,19 @@ class DirStackFileIncluder : public glslang::TShader::Includer { } // Search for a valid path. - // Not implemented yet; returning nullptr signals failure to find. - virtual IncludeResult* readSystemPath(const char* /*headerName*/) const + virtual IncludeResult* readSystemPath(const char* headerName) { + // Search for external directories only. + for (auto it = externalDirectoryList.begin(); it != externalDirectoryList.end(); ++it) { + std::string path = *it + '/' + headerName; + std::replace(path.begin(), path.end(), '\\', '/'); + std::ifstream file(path, std::ios_base::binary | std::ios_base::ate); + if (file) { + localDirectoryStack.push_back(getDirectory(path)); + includedFiles.insert(path); + return newIncludeResult(path, file, (int)file.tellg()); + } + } return nullptr; } diff --git a/StandAlone/StandAlone.cpp b/StandAlone/StandAlone.cpp index be7f442123..e35403a740 100644 --- a/StandAlone/StandAlone.cpp +++ b/StandAlone/StandAlone.cpp @@ -1351,8 +1351,8 @@ void CompileAndLinkShaderUnits(std::vector compUnits) SetMessageOptions(messages); DirStackFileIncluder includer; - std::for_each(IncludeDirectoryList.rbegin(), IncludeDirectoryList.rend(), [&includer](const std::string& dir) { - includer.pushExternalLocalDirectory(dir); }); + std::for_each(IncludeDirectoryList.begin(), IncludeDirectoryList.end(), [&includer](const std::string& dir) { + includer.pushExternalDirectory(dir); }); std::vector sources; diff --git a/Test/baseResults/hlsl.include.system.unresolved.vert.out b/Test/baseResults/hlsl.include.system.unresolved.vert.out new file mode 100644 index 0000000000..e5acdbc59c --- /dev/null +++ b/Test/baseResults/hlsl.include.system.unresolved.vert.out @@ -0,0 +1,8 @@ +hlsl.include.system.unresolved.vert +ERROR: hlsl.include.system.unresolved.vert:2: '#include' : Could not process include directive for header name: foo.h +ERROR: 1 compilation errors. No code generated. + + +WARNING: Linking vertex stage: Entry point not found + +SPIR-V is not generated for failed compile or link diff --git a/Test/baseResults/hlsl.include.system.vert.out b/Test/baseResults/hlsl.include.system.vert.out new file mode 100644 index 0000000000..aa116a85a4 --- /dev/null +++ b/Test/baseResults/hlsl.include.system.vert.out @@ -0,0 +1,76 @@ +hlsl.include.system.vert +// Module Version 10000 +// Generated by (magic number): 8000b +// Id's are bound by 44 + + Capability Shader + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint Vertex 4 "main" 42 + Source HLSL 500 + Name 4 "main" + Name 9 "@main(" + Name 11 "$Global" + MemberName 11($Global) 0 "i2" + MemberName 11($Global) 1 "i4" + MemberName 11($Global) 2 "i3" + MemberName 11($Global) 3 "p1" + MemberName 11($Global) 4 "p2" + MemberName 11($Global) 5 "p3" + Name 13 "" + Name 42 "@entryPointOutput" + Decorate 11($Global) Block + MemberDecorate 11($Global) 0 Offset 0 + MemberDecorate 11($Global) 1 Offset 16 + MemberDecorate 11($Global) 2 Offset 32 + MemberDecorate 11($Global) 3 Offset 48 + MemberDecorate 11($Global) 4 Offset 64 + MemberDecorate 11($Global) 5 Offset 80 + Decorate 13 Binding 0 + Decorate 13 DescriptorSet 0 + Decorate 42(@entryPointOutput) BuiltIn Position + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeFloat 32 + 7: TypeVector 6(float) 4 + 8: TypeFunction 7(fvec4) + 11($Global): TypeStruct 7(fvec4) 7(fvec4) 7(fvec4) 7(fvec4) 7(fvec4) 7(fvec4) + 12: TypePointer Uniform 11($Global) + 13: 12(ptr) Variable Uniform + 14: TypeInt 32 1 + 15: 14(int) Constant 0 + 16: TypePointer Uniform 7(fvec4) + 19: 14(int) Constant 2 + 23: 14(int) Constant 1 + 27: 14(int) Constant 3 + 31: 14(int) Constant 4 + 35: 14(int) Constant 5 + 41: TypePointer Output 7(fvec4) +42(@entryPointOutput): 41(ptr) Variable Output + 4(main): 2 Function None 3 + 5: Label + 43: 7(fvec4) FunctionCall 9(@main() + Store 42(@entryPointOutput) 43 + Return + FunctionEnd + 9(@main(): 7(fvec4) Function None 8 + 10: Label + 17: 16(ptr) AccessChain 13 15 + 18: 7(fvec4) Load 17 + 20: 16(ptr) AccessChain 13 19 + 21: 7(fvec4) Load 20 + 22: 7(fvec4) FAdd 18 21 + 24: 16(ptr) AccessChain 13 23 + 25: 7(fvec4) Load 24 + 26: 7(fvec4) FAdd 22 25 + 28: 16(ptr) AccessChain 13 27 + 29: 7(fvec4) Load 28 + 30: 7(fvec4) FAdd 26 29 + 32: 16(ptr) AccessChain 13 31 + 33: 7(fvec4) Load 32 + 34: 7(fvec4) FAdd 30 33 + 36: 16(ptr) AccessChain 13 35 + 37: 7(fvec4) Load 36 + 38: 7(fvec4) FAdd 34 37 + ReturnValue 38 + FunctionEnd diff --git a/Test/baseResults/include.system.vert.out b/Test/baseResults/include.system.vert.out new file mode 100644 index 0000000000..8864244300 --- /dev/null +++ b/Test/baseResults/include.system.vert.out @@ -0,0 +1,49 @@ +include.system.vert +Shader version: 450 +Requested GL_GOOGLE_cpp_style_line_directive +Requested GL_GOOGLE_include_directive +0:? Sequence +0:15 Function Definition: main( ( global void) +0:15 Function Parameters: +0:17 Sequence +0:17 move second child to first child ( temp 4-component vector of float) +0:17 'color' ( smooth out 4-component vector of float) +0:17 add ( temp 4-component vector of float) +0:17 add ( temp 4-component vector of float) +0:17 'i1' ( global 4-component vector of float) +0:17 'i5' ( global 4-component vector of float) +0:17 'i6' ( global 4-component vector of float) +0:? Linker Objects +0:? 'i1' ( global 4-component vector of float) +0:? 'i6' ( global 4-component vector of float) +0:? 'i5' ( global 4-component vector of float) +0:? 'color' ( smooth out 4-component vector of float) +0:? 'gl_VertexID' ( gl_VertexId int VertexId) +0:? 'gl_InstanceID' ( gl_InstanceId int InstanceId) + + +Linked vertex stage: + + +Shader version: 450 +Requested GL_GOOGLE_cpp_style_line_directive +Requested GL_GOOGLE_include_directive +0:? Sequence +0:15 Function Definition: main( ( global void) +0:15 Function Parameters: +0:17 Sequence +0:17 move second child to first child ( temp 4-component vector of float) +0:17 'color' ( smooth out 4-component vector of float) +0:17 add ( temp 4-component vector of float) +0:17 add ( temp 4-component vector of float) +0:17 'i1' ( global 4-component vector of float) +0:17 'i5' ( global 4-component vector of float) +0:17 'i6' ( global 4-component vector of float) +0:? Linker Objects +0:? 'i1' ( global 4-component vector of float) +0:? 'i6' ( global 4-component vector of float) +0:? 'i5' ( global 4-component vector of float) +0:? 'color' ( smooth out 4-component vector of float) +0:? 'gl_VertexID' ( gl_VertexId int VertexId) +0:? 'gl_InstanceID' ( gl_InstanceId int InstanceId) + diff --git a/Test/hlsl.include.system.unresolved.vert b/Test/hlsl.include.system.unresolved.vert new file mode 100644 index 0000000000..ffbee05e1a --- /dev/null +++ b/Test/hlsl.include.system.unresolved.vert @@ -0,0 +1,6 @@ +// Should fail even though "./foo.h" exists +#include + +int main() { +#error in main +} diff --git a/Test/hlsl.include.system.vert b/Test/hlsl.include.system.vert new file mode 100644 index 0000000000..c5646c06c3 --- /dev/null +++ b/Test/hlsl.include.system.vert @@ -0,0 +1,10 @@ +// For -Iinc1 -Iinc1/path1 -Iinc1/path2 +// Should include ./inc1/bar, ./inc1/foo, and ./parent +#include +// Should include ./inc1/path1/notHere.h +#include + +float4 main() : SV_Position +{ + return i2 + i3 + i4 + p1 + p2 + p3; +} diff --git a/Test/include.system.vert b/Test/include.system.vert new file mode 100644 index 0000000000..89c9bab45c --- /dev/null +++ b/Test/include.system.vert @@ -0,0 +1,18 @@ +#version 450 + +#extension GL_GOOGLE_include_directive : enable + +#define float4 vec4 + +// For -Iinc2 +// Should include "./bar.h" +#include "bar.h" +// Should include "./inc2/bar.h" and "./inc2/foo.h" +#include + +out vec4 color; + +void main() +{ + color = i1 + i5 + i6; +} diff --git a/Test/runtests b/Test/runtests index f797c9eb79..a65a0331f0 100755 --- a/Test/runtests +++ b/Test/runtests @@ -187,6 +187,12 @@ run -D -Od -e main -H -Od ../Test/hlsl.include.vert > "$TARGETDIR/hlsl.include.v diff -b $BASEDIR/hlsl.include.vert.out "$TARGETDIR/hlsl.include.vert.out" || HASERROR=1 run -D -Od -e main -H -Od hlsl.includeNegative.vert > "$TARGETDIR/hlsl.includeNegative.vert.out" diff -b $BASEDIR/hlsl.includeNegative.vert.out "$TARGETDIR/hlsl.includeNegative.vert.out" || HASERROR=1 +run -D -Od -e main -H -Od hlsl.include.system.vert -Iinc1 -Iinc1/path1 -Iinc1/path2 > "$TARGETDIR/hlsl.include.system.vert.out" +diff -b $BASEDIR/hlsl.include.system.vert.out "$TARGETDIR/hlsl.include.system.vert.out" || HASERROR=1 +run -D -Od -e main -H -Od hlsl.include.system.unresolved.vert > "$TARGETDIR/hlsl.include.system.unresolved.vert.out" +diff -b $BASEDIR/hlsl.include.system.unresolved.vert.out "$TARGETDIR/hlsl.include.system.unresolved.vert.out" || HASERROR=1 +run -l -i include.system.vert -Iinc2 > "$TARGETDIR/include.system.vert.out" +diff -b $BASEDIR/include.system.vert.out "$TARGETDIR/include.system.vert.out" || HASERROR=1 run -l -i include.vert > "$TARGETDIR/include.vert.out" diff -b $BASEDIR/include.vert.out "$TARGETDIR/include.vert.out" || HASERROR=1 run -D -Od -e main -H -Od -Iinc1/path1 -Iinc1/path2 hlsl.dashI.vert > "$TARGETDIR/hlsl.dashI.vert.out"