Merge remote-tracking branch 'aosp/upstream-master'

Pulls in the following:
4213a47 Fixed Android.mk for Windows.
c902a06 Enable test for failure of Vulkan shader targeting OpenGL
cdfb5ac Support Glslang with its new HLSL parser library
65d92e8 Test Vulkan-specific shaders
a18ea5b Enable dependency info dumping tests for abspath
aab7744 Remove revision from SPV_ENV_*.
d3bdf59 Add -I to the glslc synopsis.
afb959a Improve the #include behaviour description.
533ba9b Reflect ExtInstSet generation steps of SPIRV-Tools in Android.mk.
7c9ed1d Add new files appearing in SPIRV-Tools to Android.mk.
8468206 libspirv.h in SPIRV-Tools removed macros for version and revision.
9ede710 Add rules to build grammar tables in Android.mk for SPIRV-Tools.
e0d3d95 Enabled relative includes in glslc.
c15f6f3 Give spvContextCreate() a target environment.
d63c5e0 Update the interface to handle the new Glslang includer.

Change-Id: Id80cb4eb345ad51b4d4e1c80312f88063afb812c
diff --git a/Android.mk b/Android.mk
index 9a988b9..6d94a00 100644
--- a/Android.mk
+++ b/Android.mk
@@ -10,6 +10,7 @@
 	libshaderc.a \
 	libshaderc_util.a \
 	libSPIRV.a \
+	libHLSL.a \
 	libSPIRV-Tools.a
 
 define gen_libshaderc
@@ -23,14 +24,14 @@
 
 $(1)/libshaderc_combined.a: $(addprefix $(1)/, $(ALL_LIBS)) $(1)/combine.ar
 	@echo "[$(TARGET_ARCH_ABI)] Combine: libshaderc_combined.a <= $(ALL_LIBS)"
-	@cd $(1) && $(2)ar -M < combine.ar && cd -
+	@cd $(1) && $(2)ar -M < combine.ar && cd $(ROOT_SHADERC_PATH)
 	@$(2)objcopy --strip-debug $(1)/libshaderc_combined.a
 
 $(NDK_APP_LIBS_OUT)/$(APP_STL)/$(TARGET_ARCH_ABI)/libshaderc.a: \
 		$(1)/libshaderc_combined.a
 	$(call host-mkdir,$(NDK_APP_LIBS_OUT)/$(APP_STL)/$(TARGET_ARCH_ABI))
 	$(call host-cp,$(1)/libshaderc_combined.a \
-		$(NDK_APP_LIBS_OUT)/$(APP_STL)/$(TARGET_ARCH_ABI)/libshaderc.a)
+		,$(NDK_APP_LIBS_OUT)/$(APP_STL)/$(TARGET_ARCH_ABI)/libshaderc.a)
 
 ifndef HEADER_TARGET
 HEADER_TARGET=1
@@ -38,13 +39,13 @@
 		$(ROOT_SHADERC_PATH)/libshaderc/include/shaderc/shaderc.hpp
 	$(call host-mkdir,$(NDK_APP_LIBS_OUT)/../include/shaderc)
 	$(call host-cp,$(ROOT_SHADERC_PATH)/libshaderc/include/shaderc/shaderc.hpp \
-		$(NDK_APP_LIBS_OUT)/../include/shaderc/shaderc.hpp)
+		,$(NDK_APP_LIBS_OUT)/../include/shaderc/shaderc.hpp)
 
 $(NDK_APP_LIBS_OUT)/../include/shaderc/shaderc.h: \
 	$(ROOT_SHADERC_PATH)/libshaderc/include/shaderc/shaderc.h
 	$(call host-mkdir,$(NDK_APP_LIBS_OUT)/../include/shaderc)
 	$(call host-cp,$(ROOT_SHADERC_PATH)/libshaderc/include/shaderc/shaderc.h \
-		$(NDK_APP_LIBS_OUT)/../include/shaderc/shaderc.h)
+		,$(NDK_APP_LIBS_OUT)/../include/shaderc/shaderc.h)
 endif
 
 libshaderc_combined: \
@@ -55,4 +56,3 @@
 	$(NDK_APP_LIBS_OUT)/../include/shaderc/shaderc.h
 
 $(eval $(call gen_libshaderc,$(TARGET_OUT),$(TOOLCHAIN_PREFIX)))
-
diff --git a/glslc/CMakeLists.txt b/glslc/CMakeLists.txt
index f0a53fb..ba4d4c5 100644
--- a/glslc/CMakeLists.txt
+++ b/glslc/CMakeLists.txt
@@ -16,7 +16,7 @@
 shaderc_default_compile_options(glslc)
 target_include_directories(glslc PUBLIC ${glslang_SOURCE_DIR})
 target_link_libraries(glslc PRIVATE glslang OSDependent OGLCompiler
-  glslang SPIRV ${CMAKE_THREAD_LIBS_INIT})
+  HLSL glslang SPIRV ${CMAKE_THREAD_LIBS_INIT})
 target_link_libraries(glslc PRIVATE shaderc_util shaderc)
 
 add_executable(glslc_exe src/main.cc)
diff --git a/glslc/README.asciidoc b/glslc/README.asciidoc
index 5ed1f91..1c4021b 100644
--- a/glslc/README.asciidoc
+++ b/glslc/README.asciidoc
@@ -12,6 +12,7 @@
 ----
 glslc [-c|-S|-E]
       [-Dmacroname[=value]...]
+      [-Idirectory...]
       [-std=standard] [-x glsl]
       [-fshader-stage=...]
       [--target-env=...]
@@ -208,9 +209,9 @@
 
 ==== `-I`
 
-`-I` adds the specified directory to the search path for include files.
-
-WARNING: Implementation is not complete yet.
+`-Idirectory' or `-I directory` adds the specified directory to the search path
+for include files.  The directory may be an absolute path or a relative path to
+the current working directory.
 
 === Code Generation Options
 
@@ -378,11 +379,26 @@
 
 WARNING: This section is still evolving. Expect changes.
 
-TODO: Expected behaviors of the `#include` directive.
-
 If `#include` directives are used in a shader, there will be an `#extension
 GL_GOOGLE_include_directive : enable` line generated into the preprocessed
 output.
 
 The `GL_GOOGLE_cpp_style_line_directive` extension is implicitly turned on by
 the `GL_GOOGLE_include_directive` extension.
+
+The file argument to `#include` must be enclosed in double quotes.  It must be a
+relative path, using whatever path separator the OS supports.  However, the last
+path element -- the name of the file itself -- must not contain either '/' or
+'\', regardless of which path separator is used.  This will not be flagged as an
+error but will instead trigger undefined behavior.  For example, let's say there
+is a file named `f\ilename.vert` on a Unix OS.  It is not possible to craft a
+`#include` that includes that file.
+
+Furthermore, it is not possible to escape any characters in a `#include`
+directive, so the file argument cannot contain any special characters that need
+escaping in C.
+
+The file argument is a relative path that is matched first against the including
+file's own directory and then against all `-I` arguments in order of their
+appearance on the command line.  If the file cannot be found, `glslc` aborts
+with an error.
diff --git a/glslc/src/file_includer.cc b/glslc/src/file_includer.cc
index 9fbbeaa..ea42e81 100644
--- a/glslc/src/file_includer.cc
+++ b/glslc/src/file_includer.cc
@@ -14,35 +14,51 @@
 
 #include "file_includer.h"
 
+#include <mutex>
+#include <utility>
+
 #include "libshaderc_util/io.h"
 
 namespace glslc {
 
-shaderc_includer_response* FileIncluder::GetInclude(const char* filename) {
-  file_full_path_ = file_finder_.FindReadableFilepath(filename);
-  source_files_used_.insert(file_full_path_);
-  if (!file_full_path_.empty() &&
-      shaderc_util::ReadFile(file_full_path_, &file_content_)) {
-    response_ = {
-        file_full_path_.c_str(), file_full_path_.length(), file_content_.data(),
-        file_content_.size(),
-    };
-  } else {
-    const char error_msg[] = "Cannot find or open include file.";
-    file_content_.assign(std::begin(error_msg), std::end(error_msg));
-    response_ = {
-        "", 0u, file_content_.data(), file_content_.size(),
-    };
-  }
-  return &response_;
+shaderc_include_result* MakeErrorIncludeResult(const char* message) {
+  return new shaderc_include_result{"", 0, message, strlen(message)};
 }
 
-void FileIncluder::ReleaseInclude(shaderc_includer_response*) {
-  response_ = {
-      nullptr, 0u, nullptr, 0u,
-  };
-  file_content_.clear();
-  file_full_path_.clear();
+shaderc_include_result* FileIncluder::GetInclude(
+    const char* requested_source, shaderc_include_type include_type,
+    const char* requesting_source, size_t) {
+
+  const std::string full_path =
+      (include_type == shaderc_include_type_relative)
+          ? file_finder_.FindRelativeReadableFilepath(requesting_source,
+                                                      requested_source)
+          : file_finder_.FindReadableFilepath(requested_source);
+
+  if (full_path.empty())
+    return MakeErrorIncludeResult("Cannot find or open include file.");
+
+  // In principle, several threads could be resolving includes at the same
+  // time.  Protect the included_files.
+
+  // Read the file and save its full path and contents into stable addresses.
+  FileInfo* new_file_info = new FileInfo{full_path, {}};
+  if (!shaderc_util::ReadFile(full_path, &(new_file_info->contents))) {
+    return MakeErrorIncludeResult("Cannot read file");
+  }
+
+  included_files_.insert(full_path);
+
+  return new shaderc_include_result{
+      new_file_info->full_path.data(), new_file_info->full_path.length(),
+      new_file_info->contents.data(), new_file_info->contents.size(),
+      new_file_info};
+}
+
+void FileIncluder::ReleaseInclude(shaderc_include_result* include_result) {
+  FileInfo* info = static_cast<FileInfo*>(include_result->user_data);
+  delete info;
+  delete include_result;
 }
 
 }  // namespace glslc
diff --git a/glslc/src/file_includer.h b/glslc/src/file_includer.h
index 08cb8db..ae42730 100644
--- a/glslc/src/file_includer.h
+++ b/glslc/src/file_includer.h
@@ -15,10 +15,13 @@
 #ifndef GLSLC_FILE_INCLUDER_H_
 #define GLSLC_FILE_INCLUDER_H_
 
+#include <mutex>
 #include <string>
+#include <unordered_map>
 #include <unordered_set>
 #include <utility>
 #include <vector>
+#include <unordered_set>
 
 #include "libshaderc_util/file_finder.h"
 #include "shaderc/shaderc.hpp"
@@ -30,26 +33,37 @@
 // of the file to be included. In the case that the file is not found or cannot
 // be opened, the full path field of in the response will point to an empty
 // string, and error message will be passed to the content field.
+// This class provides the basic thread-safety guarantee.
 class FileIncluder : public shaderc::CompileOptions::IncluderInterface {
  public:
   explicit FileIncluder(const shaderc_util::FileFinder* file_finder)
       : file_finder_(*file_finder) {}
-  shaderc_includer_response* GetInclude(const char* filename) override;
-  void ReleaseInclude(shaderc_includer_response* data) override;
+  // Resolves a requested source file of a given type from a requesting
+  // source into a shaderc_include_result whose contents will remain valid
+  // until it's released.
+  shaderc_include_result* GetInclude(const char* requested_source,
+                                     shaderc_include_type type,
+                                     const char* requesting_source,
+                                     size_t include_depth) override;
+  // Releases an include result.
+  void ReleaseInclude(shaderc_include_result* include_result) override;
+
+  // Returns a reference to the member storing the set of included files.
   const std::unordered_set<std::string>& file_path_trace() const {
-    return source_files_used_;
+    return included_files_;
   };
 
  private:
   // Used by GetInclude() to get the full filepath.
   const shaderc_util::FileFinder& file_finder_;
-  // Only one response needs to be kept alive due to the implementation of
-  // libshaderc's InternalFileIncluder::include_delegate, which make copies for
-  // the full path and content.
-  shaderc_includer_response response_;
-  std::vector<char> file_content_;
-  std::string file_full_path_;
-  std::unordered_set<std::string> source_files_used_;
+  // The full path and content of a source file.
+  struct FileInfo {
+    const std::string full_path;
+    std::vector<char> contents;
+  };
+
+  // The set of full paths of included files.
+  std::unordered_set<std::string> included_files_;
 };
 
 }  // namespace glslc
diff --git a/glslc/src/main.cc b/glslc/src/main.cc
index 5f84c87..38a85b2 100644
--- a/glslc/src/main.cc
+++ b/glslc/src/main.cc
@@ -112,8 +112,6 @@
   bool success = true;
   bool has_stdin_input = false;
 
-  compiler.AddIncludeDirectory("");
-
   for (int i = 1; i < argc; ++i) {
     const string_piece arg = argv[i];
     if (arg == "--help") {
@@ -121,9 +119,8 @@
       return 0;
     } else if (arg == "--version") {
       std::cout << kBuildVersion << std::endl;
-      std::cout << "Target: SPIR-V " << SPV_SPIRV_VERSION_MAJOR << "."
-                << SPV_SPIRV_VERSION_MINOR << " rev "
-                << SPV_SPIRV_VERSION_REVISION << std::endl;
+      std::cout << "Target: " << spvTargetEnvDescription(SPV_ENV_UNIVERSAL_1_0)
+                << std::endl;
       return 0;
     } else if (arg.starts_with("-o")) {
       string_piece file_name;
diff --git a/glslc/test/glslc_test_framework.py b/glslc/test/glslc_test_framework.py
index e6f2f52..6a2a3b9 100755
--- a/glslc/test/glslc_test_framework.py
+++ b/glslc/test/glslc_test_framework.py
@@ -269,6 +269,10 @@
                 setattr(
                     self.test, expectation_name,
                     ''.join(expanded_expections))
+            elif isinstance(expectation, PlaceHolder):
+                setattr(self.test, expectation_name,
+                        expectation.instantiate_for_expectation(self))
+
 
     def tearDown(self):
         """Removes the directory if we were not instructed to do otherwise."""
diff --git a/glslc/test/include.py b/glslc/test/include.py
index dfb1aa0..a965032 100644
--- a/glslc/test/include.py
+++ b/glslc/test/include.py
@@ -14,6 +14,7 @@
 
 import expect
 from glslc_test_framework import inside_glslc_testsuite
+from placeholder import SpecializedString
 from environment import File, Directory
 
 
@@ -306,3 +307,255 @@
         "b.glsl:1: error: '#version' : must occur first in shader\n",
         '1 error generated.\n'
     ]
+
+
+@inside_glslc_testsuite('Include')
+class VerifyRelativeInclude(expect.StdoutMatch):
+    """Tests #including a relative sibling."""
+
+    environment = Directory('.', [
+        File('a.vert', '#version 140\ncontent a\n#include "foo/b.glsl"\n'),
+        Directory('foo', [
+            File('b.glsl', '#include "c.glsl"\ncontent b\n'),
+            File('c.glsl', 'content c\n')
+        ])])
+
+    glslc_args = ['-E', 'a.vert']
+
+    expected_stdout = \
+"""#version 140
+#extension GL_GOOGLE_include_directive : enable
+#line 0 "a.vert"
+
+content a
+#line 0 "foo/b.glsl"
+#line 0 "foo/c.glsl"
+ content c
+#line 1 "foo/b.glsl"
+ content b
+#line 3 "a.vert"
+
+"""
+
+@inside_glslc_testsuite('Include')
+class VerifyNestedRelativeInclude(expect.StdoutMatch):
+    """Tests #including a relative child file."""
+
+    environment = Directory('.', [
+        File('a.vert', '#version 140\ncontent a\n#include "foo/b.glsl"\n'),
+        Directory('foo', [
+            File('b.glsl', '#include "bar/c.glsl"\ncontent b\n'),
+            Directory('bar', [
+                File('c.glsl', 'content c\n')
+            ])
+        ])
+    ])
+
+    glslc_args = ['-E', 'a.vert']
+
+    expected_stdout = \
+"""#version 140
+#extension GL_GOOGLE_include_directive : enable
+#line 0 "a.vert"
+
+content a
+#line 0 "foo/b.glsl"
+#line 0 "foo/bar/c.glsl"
+ content c
+#line 1 "foo/b.glsl"
+ content b
+#line 3 "a.vert"
+
+"""
+
+
+@inside_glslc_testsuite('Include')
+class VerifyRelativeIncludeWithDashI(expect.StdoutMatch):
+    """Tests #including a relative file from a -I directory."""
+
+    environment = Directory('.', [
+        File('a.vert', '#version 140\ncontent a\n#include "bar/b.glsl"\n'),
+        Directory('foo', [
+            Directory('bar', [
+                File('b.glsl', '#include "c.glsl"\ncontent b\n'),
+            ]),
+            File('c.glsl', 'content c\n')
+        ])
+    ])
+
+    glslc_args = ['-E', 'a.vert', '-Ifoo']
+
+    expected_stdout = \
+"""#version 140
+#extension GL_GOOGLE_include_directive : enable
+#line 0 "a.vert"
+
+content a
+#line 0 "foo/bar/b.glsl"
+#line 0 "foo/c.glsl"
+ content c
+#line 1 "foo/bar/b.glsl"
+ content b
+#line 3 "a.vert"
+
+"""
+
+
+@inside_glslc_testsuite('Include')
+class VerifyRelativeOverridesDashI(expect.StdoutMatch):
+    """Tests that relative includes override -I parameters."""
+
+    environment = Directory('.', [
+        File('a.vert', '#version 140\ncontent a\n#include "b.glsl"\n'),
+        File('b.glsl', 'content base_b\n'),
+        Directory('foo', [
+            File('b.glsl', '#include "c.glsl"\ncontent b\n'),
+            File('c.glsl', 'content c\n')
+        ])
+    ])
+
+    glslc_args = ['-E', 'a.vert', '-Ifoo']
+
+    expected_stdout = \
+"""#version 140
+#extension GL_GOOGLE_include_directive : enable
+#line 0 "a.vert"
+
+content a
+#line 0 "b.glsl"
+ content base_b
+#line 3 "a.vert"
+
+"""
+
+
+@inside_glslc_testsuite('Include')
+class VerifyRelativeParent(expect.StdoutMatch):
+    """Tests #including a parent file."""
+
+    environment = Directory('.', [
+        File('a.vert', '#version 140\ncontent a\n#include "b.glsl"\n'),
+        File('c.glsl', 'content c\n'),
+        Directory('foo', [
+            File('b.glsl', '#include "../c.glsl"\ncontent b\n')
+        ])
+    ])
+
+    glslc_args = ['-E', 'a.vert', '-Ifoo']
+
+    expected_stdout = \
+"""#version 140
+#extension GL_GOOGLE_include_directive : enable
+#line 0 "a.vert"
+
+content a
+#line 0 "foo/b.glsl"
+#line 0 "foo/../c.glsl"
+ content c
+#line 1 "foo/b.glsl"
+ content b
+#line 3 "a.vert"
+
+"""
+
+
+@inside_glslc_testsuite('Include')
+class VerifyRelativeNeighbourDirectory(expect.StdoutMatch):
+    """Tests #including a relative file in a neighbour directory."""
+
+    environment = Directory('.', [
+        File('a.vert', '#version 140\ncontent a\n#include "foo/b.glsl"\n'),
+        Directory('foo', [
+            File('b.glsl', '#include "../bar/c.glsl"\ncontent b\n')
+        ]),
+        Directory('bar', [
+            File('c.glsl', 'content c\n')
+        ])
+    ])
+
+    glslc_args = ['-E', 'a.vert']
+
+    expected_stdout = \
+"""#version 140
+#extension GL_GOOGLE_include_directive : enable
+#line 0 "a.vert"
+
+content a
+#line 0 "foo/b.glsl"
+#line 0 "foo/../bar/c.glsl"
+ content c
+#line 1 "foo/b.glsl"
+ content b
+#line 3 "a.vert"
+
+"""
+
+
+@inside_glslc_testsuite('Include')
+class VerifyRelativeOnlyToSelf(expect.ErrorMessage):
+    """Tests that a relative includes are only relative to yourself."""
+
+    environment = Directory('.', [
+        File('a.vert', '#version 140\ncontent a\n#include "foo/b.glsl"\n'),
+        File('c.glsl', 'content c\n'),
+        Directory('foo', [
+            File('b.glsl', '#include "c.glsl"\ncontent b\n')
+        ]),
+    ])
+
+    glslc_args = ['-E', 'a.vert']
+
+    expected_error = [
+        "foo/b.glsl:1: error: '#include' : Cannot find or open include file.\n",
+        '1 error generated.\n'
+    ]
+
+
+@inside_glslc_testsuite('Include')
+class VerifyRelativeFromAbsolutePath(expect.StdoutMatch):
+    """Tests that absolute files can relatively include."""
+
+    environment = Directory('.', [
+        File('a.vert', '#version 140\ncontent a\n#include "b.glsl"\n'),
+        File('b.glsl', 'content b\n')
+    ])
+
+    glslc_args = ['-E', SpecializedString('$directory/a.vert')]
+
+    expected_stdout = SpecializedString(
+"""#version 140
+#extension GL_GOOGLE_include_directive : enable
+#line 0 "$directory/a.vert"
+
+content a
+#line 0 "$directory/b.glsl"
+ content b
+#line 3 "$directory/a.vert"
+
+""")
+
+
+@inside_glslc_testsuite('Include')
+class VerifyDashIAbsolutePath(expect.StdoutMatch):
+    """Tests that -I parameters can be absolute paths."""
+
+    environment = Directory('.', [
+        File('a.vert', '#version 140\ncontent a\n#include "b.glsl"\n'),
+        Directory('foo', {
+            File('b.glsl', 'content b\n')
+        })
+    ])
+
+    glslc_args = ['-E', 'a.vert', '-I', SpecializedString('$directory/foo')]
+
+    expected_stdout = SpecializedString(
+"""#version 140
+#extension GL_GOOGLE_include_directive : enable
+#line 0 "a.vert"
+
+content a
+#line 0 "$directory/foo/b.glsl"
+ content b
+#line 3 "a.vert"
+
+""")
diff --git a/glslc/test/option_dash_M.py b/glslc/test/option_dash_M.py
index f797f1c..b7d77ba 100644
--- a/glslc/test/option_dash_M.py
+++ b/glslc/test/option_dash_M.py
@@ -268,14 +268,8 @@
     dependency_rules_expected = [{'target': 'target',
                                   'dependency': {'shader.vert'}}]
 
-# TODO:(qining) Add tests for absolute input path with #include directives, the
-# dependent file should also be represented in absolute path.
-# e.g. glslc -M /usr/local/a.vert
-#   => a.vert.spv: /usr/local/a.vert /usr/local/b.vert /usr/local/subdir/c.vert
-# These tests needs to be enabled after we have full-fledged includer.
 
-
-# @inside_glslc_testsuite('OptionsCapM')
+@inside_glslc_testsuite('OptionsCapM')
 class TestDashCapMInputAbsolutePathWithInclude(DependencyInfoStdoutMatch):
     """Tests -M have included files represented in absolute paths when the input
     file is represented in absolute path.
@@ -283,17 +277,28 @@
          glslc -M /usr/local/a.vert
       => a.vert.spv: /usr/local/a.vert /usr/local/b.vert
     """
-    shader_a = FileShader('#version 140\n#include "b.vert"\nvoid main(){}\n',
-                          '.vert')
-    shader_b = FileShader('void foo(){}\n', '.vert')
+    environment = Directory('.', [File('b.vert', 'void foo(){}\n')])
+    shader_main = FileShader(
+        '#version 140\n#include "b.vert"\nvoid main(){}\n', '.vert')
 
-    glslc_args = ['-M', shader_a]
-    dependency_rules_expected = [{'target': shader_a,
-                                  'target_extension': '.spv',
-                                  'dependency': {shader_a, shader_b}}]
+    glslc_args = ['-M', shader_main]
+    dependency_rules_expected = [{
+        'target': shader_main,
+        'target_extension': '.spv',
+        'dependency': {shader_main}
+        # The dependency here is not complete.  we can not get the absolute path
+        # of b.vert here. It will be added in check_stdout_dependency_info()
+    }]
+
+    def check_stdout_dependency_info(self, status):
+        # Add the absolute path of b.vert to the dependency set
+        self.dependency_rules_expected[0]['dependency'].add(os.path.dirname(
+            self.shader_main.filename) + '/b.vert')
+        return DependencyInfoStdoutMatch.check_stdout_dependency_info(self,
+                                                                      status)
 
 
-# @inside_glslc_testsuite('OptionsCapM')
+@inside_glslc_testsuite('OptionsCapM')
 class TestDashCapMSingleInputAbsolutePathWithIncludeSubdir(
         DependencyInfoStdoutMatch):
     """Tests -M with single input file which does #include another file in a
diff --git a/glslc/test/option_dashdash_version.py b/glslc/test/option_dashdash_version.py
index c275f47..65ba0bd 100644
--- a/glslc/test/option_dashdash_version.py
+++ b/glslc/test/option_dashdash_version.py
@@ -41,4 +41,4 @@
 class TestVersionContainsTarget(expect.StdoutMatch, expect.ReturnCodeIsZero):
     """Tests --version output contains 'Target:'."""
     glslc_args = ['--version']
-    expected_stdout = re.compile('\nTarget: SPIR-V \d+\.\d+ rev \d+')
+    expected_stdout = re.compile('\nTarget: SPIR-V \d+\.\d+')
diff --git a/glslc/test/option_target_env.py b/glslc/test/option_target_env.py
index 5979111..93b7be0 100644
--- a/glslc/test/option_target_env.py
+++ b/glslc/test/option_target_env.py
@@ -30,6 +30,11 @@
 void main() { int t = gl_VertexID; }"""
 
 
+def vulkan_vertex_shader():
+    return """#version 310 es
+void main() { int t = gl_VertexIndex; }"""
+
+
 @inside_glslc_testsuite('OptionTargetEnv')
 class TestTargetEnvEqOpenglCompatWithOpenGlCompatShader(expect.ValidObjectFile):
     """Tests that compiling OpenGL Compatibility Fragment shader with
@@ -66,6 +71,28 @@
 
 
 @inside_glslc_testsuite('OptionTargetEnv')
+class TestDefaultTargetEnvWithVulkanShader(expect.ValidObjectFile):
+    """Tests that compiling a Vulkan-specific shader with a default
+    target environment succeeds"""
+    shader = FileShader(vulkan_vertex_shader(), '.vert')
+    glslc_args = ['-c', shader]
+
+
+@inside_glslc_testsuite('OptionTargetEnv')
+class TestTargetEnvEqVulkanWithVulkanShader(expect.ValidObjectFile):
+    """Tests that compiling a Vulkan-specific shader succeeds with
+    --target-env=vulkan"""
+    shader = FileShader(vulkan_vertex_shader(), '.vert')
+    glslc_args = ['--target-env=vulkan', '-c', shader]
+
+
+# Note: Negative tests are covered in the libshaderc_util unit tests.
+# For example, that an OpenGL-specific shader should fail to compile
+# for Vulkan, or a Vulkan-specific shader should fail to compile for
+# OpenGL.
+
+
+@inside_glslc_testsuite('OptionTargetEnv')
 class TestTargetEnvEqNoArg(expect.ErrorMessage):
     """Tests the error message of assigning empty string to --target-env"""
     shader = FileShader(opengl_vertex_shader(), '.vert')
diff --git a/glslc/test/placeholder.py b/glslc/test/placeholder.py
index 2cb8e50..9c5bcfc 100644
--- a/glslc/test/placeholder.py
+++ b/glslc/test/placeholder.py
@@ -22,6 +22,7 @@
 """
 import os
 import tempfile
+from string import Template
 
 
 class PlaceHolderException(Exception):
@@ -115,3 +116,24 @@
 
     def instantiate_for_expectation(self, testcase):
         return os.path.join(testcase.directory, self.filename)
+
+
+class SpecializedString(PlaceHolder):
+    """Returns a string that has been specialized based on TestCase.
+
+    The string is specialized by expanding it as a string.Template
+    with all of the specialization being done with each $param replaced
+    by the associated member on TestCase.
+    """
+
+    def __init__(self, filename):
+        assert isinstance(filename, str)
+        assert filename != ''
+        self.filename = filename
+
+    def instantiate_for_glslc_args(self, testcase):
+        return Template(self.filename).substitute(vars(testcase))
+
+    def instantiate_for_expectation(self, testcase):
+        return Template(self.filename).substitute(vars(testcase))
+
diff --git a/libshaderc/include/shaderc/shaderc.h b/libshaderc/include/shaderc/shaderc.h
index b31a5f0..7823671 100644
--- a/libshaderc/include/shaderc/shaderc.h
+++ b/libshaderc/include/shaderc/shaderc.h
@@ -154,6 +154,7 @@
 void shaderc_compile_options_set_generate_debug_info(
     shaderc_compile_options_t options);
 
+
 // Forces the GLSL language version and profile to a given pair. The version
 // number is the same as would appear in the #version annotation in the source.
 // Version and profile specified here overrides the #version annotation in the
@@ -162,44 +163,57 @@
 void shaderc_compile_options_set_forced_version_profile(
     shaderc_compile_options_t options, int version, shaderc_profile profile);
 
-// Response to a request for #include content.  "Includer" is client code that
-// resolves #include arguments into objects of this type.
-//
-// TODO: File inclusion needs to be context-aware.
-// e.g.
-//  In file: /path/to/main_shader.vert:
-//  #include "include/a"
-//  In file: /path/to/include/a":
-//  #include "b"
-//  When compiling /path/to/main_shader.vert, the compiler should be able to
-//  go to /path/to/include/b to find the file b.
-//  This needs context info from compiler to client includer, and may needs
-//  interface changes.
-typedef struct {
-  const char* path;
-  size_t path_length;
+// Source text inclusion via #include is supported with a pair of callbacks
+// to an "includer" on the client side.  The first callback processes an
+// inclusion request, and returns an include result.  The includer owns
+// the contents of the result, and those contents must remain valid until the
+// second callback is invoked to release the result.  Both callbacks take a
+// user_data argument to specify the client context.
+
+// An include result.
+typedef struct shaderc_include_result {
+  // The name of the source file.  The name should be fully resolved
+  // in the sense that it should be a unique name in the context of the
+  // includer.  For example, if the includer maps source names to files in
+  // a filesystem, then this name should be the absolute path of the file.
+  const char* source_name;
+  size_t source_name_length;
+  // The text contents of the source file.
   const char* content;
   size_t content_length;
-} shaderc_includer_response;
+  // User data to be passed along with this request.
+  void* user_data;
+} shaderc_include_result;
 
-// A function mapping a #include argument to its includer response.  The
-// includer retains memory ownership of the response object.
-typedef shaderc_includer_response* (*shaderc_includer_response_get_fn)(
-    void* user_data, const char* filename);
+// The kinds of include requests.
+enum shaderc_include_type {
+  shaderc_include_type_relative,  // E.g. #include "source"
+  shaderc_include_type_standard   // E.g. #include <source>
+};
 
-// A function to destroy an includer response when it's no longer needed.
-typedef void (*shaderc_includer_response_release_fn)(
-    void* user_data, shaderc_includer_response* data);
+// An includer callback type for mapping an #include request to an include
+// result.  The user_data parameter specifies the client context.  The
+// requested_source parameter specifies the name of the source being requested.
+// The type parameter specifies the kind of inclusion request being made.
+// The requesting_source parameter specifies the name of the source containing
+// the #include request.  The includer owns the result object and its contents,
+// and both must remain valid until the release callback is called on the result object.
+typedef shaderc_include_result* (*shaderc_include_resolve_fn)(
+    void* user_data,
+    const char* requested_source,
+    int type,
+    const char* requesting_source,
+    size_t include_depth);
 
-// Sets includer callback functions. When a compiler encounters a #include in
-// the source, it will query the includer by invoking getter on user_data and
-// the #include argument.  The includer must respond with a
-// shaderc_includer_response object that remains valid until releaser is invoked
-// on it.  When the compiler is done processing the response, it will invoke
-// releaser on user_data and the response pointer.
-void shaderc_compile_options_set_includer_callbacks(
-    shaderc_compile_options_t options, shaderc_includer_response_get_fn getter,
-    shaderc_includer_response_release_fn releaser, void* user_data);
+// An includer callback type for destroying an include result.
+typedef void (*shaderc_include_result_release_fn)(
+    void* user_data, shaderc_include_result* include_result);
+
+// Sets includer callback functions.
+void shaderc_compile_options_set_include_callbacks(
+    shaderc_compile_options_t options, shaderc_include_resolve_fn resolver,
+    shaderc_include_result_release_fn result_releaser, void* user_data);
+
 
 // Sets the compiler mode to suppress warnings, overriding warnings-as-errors
 // mode. When both suppress-warnings and warnings-as-errors modes are
@@ -267,7 +281,6 @@
     size_t source_text_size, shaderc_shader_kind shader_kind,
     const char* input_file_name, const char* entry_point_name,
     const shaderc_compile_options_t additional_options);
-
 // The following functions, operating on shaderc_compilation_result_t objects,
 // offer only the basic thread-safety guarantee.
 
diff --git a/libshaderc/include/shaderc/shaderc.hpp b/libshaderc/include/shaderc/shaderc.hpp
index 116a100..5131995 100644
--- a/libshaderc/include/shaderc/shaderc.hpp
+++ b/libshaderc/include/shaderc/shaderc.hpp
@@ -166,27 +166,34 @@
   // A C++ version of the libshaderc includer interface.
   class IncluderInterface {
    public:
-    // Handles shaderc_includer_response_get_fn callbacks.
-    virtual shaderc_includer_response* GetInclude(const char* filename) = 0;
+    // Handles shaderc_include_resolver_fn callbacks.
+    virtual shaderc_include_result* GetInclude(
+        const char* requested_source, shaderc_include_type type,
+        const char* requesting_source,
+        size_t include_depth) = 0;
 
-    // Handles shaderc_includer_response_release_fn callbacks.
-    virtual void ReleaseInclude(shaderc_includer_response* data) = 0;
+    // Handles shaderc_include_result_release_fn callbacks.
+    virtual void ReleaseInclude(shaderc_include_result* data) = 0;
   };
 
-  // Sets the includer instance for libshaderc to call on during compilation, as
-  // described in shaderc_compile_options_set_includer_callbacks().  Callbacks
+  // Sets the includer instance for libshaderc to call during compilation, as
+  // described in shaderc_compile_options_set_include_callbacks().  Callbacks
   // are routed to this includer's methods.
   void SetIncluder(std::unique_ptr<IncluderInterface>&& includer) {
     includer_ = std::move(includer);
-    shaderc_compile_options_set_includer_callbacks(
+    shaderc_compile_options_set_include_callbacks(
         options_,
-        [](void* user_data, const char* filename) {
+        [](void* user_data, const char* requested_source,
+           int type, const char* requesting_source,
+           size_t include_depth) {
           auto* includer = static_cast<IncluderInterface*>(user_data);
-          return includer->GetInclude(filename);
+          return includer->GetInclude(requested_source,
+                                      (shaderc_include_type)type,
+                                      requesting_source, include_depth);
         },
-        [](void* user_data, shaderc_includer_response* data) {
+        [](void* user_data, shaderc_include_result* include_result) {
           auto* includer = static_cast<IncluderInterface*>(user_data);
-          return includer->ReleaseInclude(data);
+          return includer->ReleaseInclude(include_result);
         },
         includer_.get());
   }
diff --git a/libshaderc/src/shaderc.cc b/libshaderc/src/shaderc.cc
index 73cd6b6..4d83b45 100644
--- a/libshaderc/src/shaderc.cc
+++ b/libshaderc/src/shaderc.cc
@@ -23,6 +23,7 @@
 #include "SPIRV/spirv.hpp"
 
 #include "libshaderc_util/compiler.h"
+#include "libshaderc_util/counting_includer.h"
 #include "libshaderc_util/resources.h"
 #include "libshaderc_util/version_profile.h"
 
@@ -160,54 +161,92 @@
 // A bridge between the libshaderc includer and libshaderc_util includer.
 class InternalFileIncluder : public shaderc_util::CountingIncluder {
  public:
-  InternalFileIncluder(
-      const shaderc_includer_response_get_fn get_includer_response,
-      const shaderc_includer_response_release_fn release_includer_response,
-      void* user_data)
-      : get_includer_response_(get_includer_response),
-        release_includer_response_(release_includer_response),
+  InternalFileIncluder(const shaderc_include_resolve_fn resolver,
+                       const shaderc_include_result_release_fn result_releaser,
+                       void* user_data)
+      : resolver_(resolver),
+        result_releaser_(result_releaser),
         user_data_(user_data){};
   InternalFileIncluder()
-      : get_includer_response_(nullptr),
-        release_includer_response_(nullptr),
-        user_data_(nullptr){};
+      : resolver_(nullptr), result_releaser_(nullptr), user_data_(nullptr){};
 
  private:
   // Check the validity of the callbacks.
   bool AreValidCallbacks() const {
-    return get_includer_response_ != nullptr &&
-           release_includer_response_ != nullptr;
+    return resolver_ != nullptr &&
+           result_releaser_ != nullptr;
   }
 
-  // Find filename in search path and returns its contents.
-  std::pair<std::string, std::string> include_delegate(
-      const char* filename) const override {
-    if (!AreValidCallbacks())
-      return std::make_pair<std::string, std::string>(
-          "", "unexpected include directive");
-    shaderc_includer_response* data =
-        get_includer_response_(user_data_, filename);
-    std::pair<std::string, std::string> entry =
-        std::make_pair(std::string(data->path, data->path_length),
-                       std::string(data->content, data->content_length));
-    release_includer_response_(user_data_, data);
-    return entry;
+  // Maps a shaderc_include_type to the correpsonding Glslang include type.
+  shaderc_include_type GetIncludeType(
+      glslang::TShader::Includer::IncludeType type) {
+    switch (type) {
+      case glslang::TShader::Includer::EIncludeRelative:
+        return shaderc_include_type_relative;
+      case glslang::TShader::Includer::EIncludeStandard:
+        return shaderc_include_type_standard;
+      default:
+        break;
+    }
+    assert(0 && "Unhandled shaderc_include_type");
+    return shaderc_include_type_relative;
   }
 
-  const shaderc_includer_response_get_fn get_includer_response_;
-  const shaderc_includer_response_release_fn release_includer_response_;
+  // Resolves an include request for the requested source of the given
+  // type in the context of the specified requesting source.  On success,
+  // returns a newly allocated IncludeResponse containing the fully resolved
+  // name of the requested source and the contents of that source.
+  // On failure, returns a newly allocated IncludeResponse where the
+  // resolved name member is an empty string, and the contents members
+  // contains error details.
+  virtual glslang::TShader::Includer::IncludeResult* include_delegate(
+      const char* requested_source,
+      glslang::TShader::Includer::IncludeType type,
+      const char* requesting_source,
+      size_t include_depth) override {
+    if (!AreValidCallbacks()) {
+      const char kUnexpectedIncludeError[] =
+          "#error unexpected include directive";
+      return new glslang::TShader::Includer::IncludeResult{
+          "", kUnexpectedIncludeError, strlen(kUnexpectedIncludeError),
+          nullptr};
+    }
+    shaderc_include_result* include_result =
+        resolver_(user_data_, requested_source, GetIncludeType(type),
+                  requesting_source, include_depth);
+    // Make a glslang IncludeResult from a shaderc_include_result.  The
+    // user_data member of the IncludeResult is a pointer to the
+    // shaderc_include_result object, so we can later release the latter.
+    return new glslang::TShader::Includer::IncludeResult{
+        std::string(include_result->source_name,
+                    include_result->source_name_length),
+        include_result->content, include_result->content_length,
+        include_result};
+  }
+
+  // Releases the given IncludeResult.
+  virtual void release_delegate(
+      glslang::TShader::Includer::IncludeResult* result) override {
+    if (result && result_releaser_) {
+      result_releaser_(user_data_,
+                       static_cast<shaderc_include_result*>(result->user_data));
+    }
+    delete result;
+  }
+
+  const shaderc_include_resolve_fn resolver_;
+  const shaderc_include_result_release_fn result_releaser_;
   void* user_data_;
 };
 
 }  // anonymous namespace
 
 struct shaderc_compile_options {
-  shaderc_compile_options() : includer_user_data(nullptr) {}
-
+  shaderc_compile_options() : include_user_data(nullptr) {}
   shaderc_util::Compiler compiler;
-  shaderc_includer_response_get_fn get_includer_response;
-  shaderc_includer_response_release_fn release_includer_response;
-  void* includer_user_data;
+  shaderc_include_resolve_fn include_resolver;
+  shaderc_include_result_release_fn include_result_releaser;
+  void* include_user_data;
 };
 
 shaderc_compile_options_t shaderc_compile_options_initialize() {
@@ -237,6 +276,7 @@
   options->compiler.SetGenerateDebugInfo();
 }
 
+
 void shaderc_compile_options_set_forced_version_profile(
     shaderc_compile_options_t options, int version, shaderc_profile profile) {
   // Transfer the profile parameter from public enum type to glslang internal
@@ -258,16 +298,17 @@
   }
 }
 
-void shaderc_compile_options_set_includer_callbacks(
+void shaderc_compile_options_set_include_callbacks(
     shaderc_compile_options_t options,
-    shaderc_includer_response_get_fn get_includer_response,
-    shaderc_includer_response_release_fn release_includer_response,
+    shaderc_include_resolve_fn resolver,
+    shaderc_include_result_release_fn result_releaser,
     void* user_data) {
-  options->get_includer_response = get_includer_response;
-  options->release_includer_response = release_includer_response;
-  options->includer_user_data = user_data;
+  options->include_resolver = resolver;
+  options->include_result_releaser = result_releaser;
+  options->include_user_data = user_data;
 }
 
+
 void shaderc_compile_options_set_suppress_warnings(
     shaderc_compile_options_t options) {
   options->compiler.SetSuppressWarnings();
@@ -323,6 +364,10 @@
         shaderc_util::string_piece(source_text, source_text + source_text_size);
     StageDeducer stage_deducer(shader_kind);
     if (additional_options) {
+      InternalFileIncluder includer(
+                  additional_options->include_resolver,
+                  additional_options->include_result_releaser,
+                  additional_options->include_user_data);
       // Depends on return value optimization to avoid extra copy.
       std::tie(compilation_succeeded, compilation_output_data,
                compilation_output_data_size_in_bytes) =
@@ -332,19 +377,17 @@
               // We need to make this a reference wrapper, so that std::function
               // won't make a copy for this callable object.
               std::ref(stage_deducer),
-              InternalFileIncluder(
-                  additional_options->get_includer_response,
-                  additional_options->release_includer_response,
-                  additional_options->includer_user_data),
+              includer,
               output_type, &errors, &total_warnings, &total_errors,
               compiler->initializer);
     } else {
       // Compile with default options.
+      InternalFileIncluder includer;
       std::tie(compilation_succeeded, compilation_output_data,
                compilation_output_data_size_in_bytes) =
           shaderc_util::Compiler().Compile(
               source_string, forced_stage, input_file_name_str,
-              std::ref(stage_deducer), InternalFileIncluder(), output_type,
+              std::ref(stage_deducer), includer, output_type,
               &errors, &total_warnings, &total_errors, compiler->initializer);
     }
 
diff --git a/libshaderc/src/shaderc_cpp_test.cc b/libshaderc/src/shaderc_cpp_test.cc
index 9e3595f..cd5bcad 100644
--- a/libshaderc/src/shaderc_cpp_test.cc
+++ b/libshaderc/src/shaderc_cpp_test.cc
@@ -642,19 +642,23 @@
       : fake_fs_(fake_fs), responses_({}) {}
 
   // Get path and content from the fake file system.
-  shaderc_includer_response* GetInclude(const char* filename) override {
-    responses_.emplace_back(shaderc_includer_response{
-        filename, strlen(filename), fake_fs_.at(std::string(filename)).c_str(),
-        fake_fs_.at(std::string(filename)).size()});
+  shaderc_include_result* GetInclude(const char* requested_source,
+                                     shaderc_include_type type,
+                                     const char* requesting_source,
+                                     size_t include_depth) override {
+    responses_.emplace_back(shaderc_include_result{
+        requested_source, strlen(requested_source),
+        fake_fs_.at(std::string(requested_source)).c_str(),
+        fake_fs_.at(std::string(requested_source)).size()});
     return &responses_.back();
   }
 
   // Response data is owned as private property, no need to release explicitly.
-  void ReleaseInclude(shaderc_includer_response*) override {}
+  void ReleaseInclude(shaderc_include_result*) override {}
 
  private:
   const FakeFS& fake_fs_;
-  std::vector<shaderc_includer_response> responses_;
+  std::vector<shaderc_include_result> responses_;
 };
 
 using IncluderTests = testing::TestWithParam<IncluderTestCase>;
diff --git a/libshaderc/src/shaderc_test.cc b/libshaderc/src/shaderc_test.cc
index ee5115a..50afe8e 100644
--- a/libshaderc/src/shaderc_test.cc
+++ b/libshaderc/src/shaderc_test.cc
@@ -99,7 +99,6 @@
   return shaderc_compile_into_spv(compiler, shader.c_str(), shader.size(), kind,
                                   input_file_name, "", options);
 }
-
 // RAII class for shaderc_compilation_result.
 class Compilation {
  public:
@@ -405,6 +404,7 @@
                         options_.get(), OutputType::SpirvAssemblyText);
   EXPECT_THAT(disassembly_text, HasSubstr("Capability Shader"));
   EXPECT_THAT(disassembly_text, HasSubstr("MemoryModel"));
+
 }
 
 TEST_F(CompileStringWithOptionsTest, DisassembleMinimalShader) {
@@ -668,32 +668,33 @@
       : fake_fs_(fake_fs), responses_({}) {}
 
   // Get path and content from the fake file system.
-  shaderc_includer_response* GetInclude(const char* filename) {
-    responses_.emplace_back(shaderc_includer_response{
+  shaderc_include_result* GetInclude(const char* filename) {
+    responses_.emplace_back(shaderc_include_result{
         filename, strlen(filename), fake_fs_.at(std::string(filename)).c_str(),
         fake_fs_.at(std::string(filename)).size()});
     return &responses_.back();
   }
 
   // Response data is owned as private property, no need to release explicitly.
-  void ReleaseInclude(shaderc_includer_response*) {}
+  void ReleaseInclude(shaderc_include_result*) {}
 
   // Wrapper for the corresponding member function.
-  static shaderc_includer_response* GetIncluderResponseWrapper(
-      void* user_data, const char* filename) {
+  static shaderc_include_result* GetIncluderResponseWrapper(
+      void* user_data, const char* filename, int,
+      const char* includer, size_t include_depth) {
     return static_cast<TestIncluder*>(user_data)->GetInclude(filename);
   }
 
   // Wrapper for the corresponding member function.
   static void ReleaseIncluderResponseWrapper(void* user_data,
-                                             shaderc_includer_response* data) {
+                                             shaderc_include_result* data) {
     return static_cast<TestIncluder*>(user_data)->ReleaseInclude(data);
   }
 
  private:
   // Includer response data is stored as private property.
   const FakeFS& fake_fs_;
-  std::vector<shaderc_includer_response> responses_;
+  std::vector<shaderc_include_result> responses_;
 };
 
 using IncluderTests = testing::TestWithParam<IncluderTestCase>;
@@ -706,7 +707,7 @@
   TestIncluder includer(fs);
   Compiler compiler;
   compile_options_ptr options(shaderc_compile_options_initialize());
-  shaderc_compile_options_set_includer_callbacks(
+  shaderc_compile_options_set_include_callbacks(
       options.get(), TestIncluder::GetIncluderResponseWrapper,
       TestIncluder::ReleaseIncluderResponseWrapper, &includer);
 
@@ -725,7 +726,7 @@
   TestIncluder includer(fs);
   Compiler compiler;
   compile_options_ptr options(shaderc_compile_options_initialize());
-  shaderc_compile_options_set_includer_callbacks(
+  shaderc_compile_options_set_include_callbacks(
       options.get(), TestIncluder::GetIncluderResponseWrapper,
       TestIncluder::ReleaseIncluderResponseWrapper, &includer);
 
diff --git a/libshaderc_util/CMakeLists.txt b/libshaderc_util/CMakeLists.txt
index c94dd1b..bb32520 100644
--- a/libshaderc_util/CMakeLists.txt
+++ b/libshaderc_util/CMakeLists.txt
@@ -25,7 +25,7 @@
   PUBLIC include PRIVATE ${glslang_SOURCE_DIR})
 find_package(Threads)
 target_link_libraries(shaderc_util PRIVATE
-  glslang OSDependent OGLCompiler glslang SPIRV
+  glslang OSDependent OGLCompiler HLSL glslang SPIRV
   SPIRV-Tools ${CMAKE_THREAD_LIBS_INIT})
 
 shaderc_add_tests(
diff --git a/libshaderc_util/include/libshaderc_util/compiler.h b/libshaderc_util/include/libshaderc_util/compiler.h
index cb7c320..0c19be3 100644
--- a/libshaderc_util/include/libshaderc_util/compiler.h
+++ b/libshaderc_util/include/libshaderc_util/compiler.h
@@ -111,6 +111,7 @@
         generate_debug_info_(false),
         message_rules_(GetDefaultRules()) {}
 
+
   // Requests that the compiler place debug information into the object code,
   // such as identifier names and line numbers.
   void SetGenerateDebugInfo();
@@ -143,7 +144,6 @@
     SpirvAssemblyText,  // Assembly syntax defined by the SPIRV-Tools project.
     PreprocessedText,   // Preprocessed source code.
   };
-
   // Compiles the shader source in the input_source_string parameter.
   //
   // If the forced_shader stage parameter is not EShLangCount then
@@ -179,7 +179,7 @@
       const std::function<EShLanguage(
           std::ostream* error_stream,
           const shaderc_util::string_piece& error_tag)>& stage_callback,
-      const CountingIncluder& includer, OutputType output_type,
+      CountingIncluder& includer, OutputType output_type,
       std::ostream* error_stream, size_t* total_warnings, size_t* total_errors,
       GlslInitializer* initializer) const;
 
@@ -208,7 +208,7 @@
       const std::string& error_tag,
       const shaderc_util::string_piece& shader_source,
       const shaderc_util::string_piece& shader_preamble,
-      const CountingIncluder& includer) const;
+      CountingIncluder& includer) const;
 
   // Cleans up the preamble in a given preprocessed shader.
   //
@@ -264,6 +264,7 @@
   // When true, use the default version and profile from eponymous data members.
   bool force_version_profile_;
 
+
   // Macro definitions that must be available to reference in the shader source.
   MacroDictionary predefined_macros_;
 
diff --git a/libshaderc_util/include/libshaderc_util/counting_includer.h b/libshaderc_util/include/libshaderc_util/counting_includer.h
index 7a4ae1e..d341ad1 100644
--- a/libshaderc_util/include/libshaderc_util/counting_includer.h
+++ b/libshaderc_util/include/libshaderc_util/counting_includer.h
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef LIBSHADERC_UTIL_INCLUDER_H
-#define LIBSHADERC_UTIL_INCLUDER_H
+#ifndef LIBSHADERC_UTIL_COUNTING_INCLUDER_H
+#define LIBSHADERC_UTIL_COUNTING_INCLUDER_H
 
 #include <atomic>
 
@@ -33,26 +33,41 @@
     num_include_directives_.store(0);
   }
 
-  // Bumps num_include_directives and returns the results of
+  // Resolves an include request for a source by name, type, and name of the
+  // requesting source.  For the semantics of the result, see the base class.
+  // Also increments num_include_directives and returns the results of
   // include_delegate(filename).  Subclasses should override include_delegate()
-  // instead of this one.  Also see the base-class version.
-  std::pair<std::string, std::string> include(
-      const char* filename) const final {
+  // instead of this method.
+  glslang::TShader::Includer::IncludeResult* include(
+      const char* requested_source, glslang::TShader::Includer::IncludeType type,
+      const char* requesting_source,
+      size_t include_depth) final {
     ++num_include_directives_;
-    return include_delegate(filename);
+    return include_delegate(requested_source, type, requesting_source,
+                            include_depth);
+  }
+
+  // Releases the given IncludeResult.
+  void releaseInclude(glslang::TShader::Includer::IncludeResult* result) final {
+    release_delegate(result);
   }
 
   int num_include_directives() const { return num_include_directives_.load(); }
 
  private:
   // Invoked by this class to provide results to
-  // TShader::Includer::include(filename).
-  virtual std::pair<std::string, std::string> include_delegate(
-      const char* filename) const = 0;
+  // glslang::TShader::Includer::include.
+  virtual glslang::TShader::Includer::IncludeResult* include_delegate(
+      const char* requested_source, glslang::TShader::Includer::IncludeType type,
+      const char* requesting_source, size_t include_depth) = 0;
+
+  // Release the given IncludeResult.
+  virtual void release_delegate(
+      glslang::TShader::Includer::IncludeResult* result) = 0;
 
   // The number of #include directive encountered.
-  mutable std::atomic_int num_include_directives_;
+  std::atomic_int num_include_directives_;
 };
 }
 
-#endif  // LIBSHADERC_UTIL_INCLUDER_H
+#endif  // LIBSHADERC_UTIL_COUNTING_INCLUDER_H
diff --git a/libshaderc_util/include/libshaderc_util/file_finder.h b/libshaderc_util/include/libshaderc_util/file_finder.h
index 8aec788..2c1c9d1 100644
--- a/libshaderc_util/include/libshaderc_util/file_finder.h
+++ b/libshaderc_util/include/libshaderc_util/file_finder.h
@@ -33,14 +33,18 @@
   // If a search_path() element is non-empty and not ending in a slash, then a
   // slash is inserted between it and filename before its search attempt. An
   // empty string in search_path() means that the filename is tried as-is.
-  //
-  // Usage advice: when searching #include files, you almost certainly want ""
-  // to be the first element in search_path().  That way both relative and
-  // absolute filenames will work as expected.  Note that a "." entry on the
-  // search path may be prepended to an absolute filename (eg, "/a/b/c") to
-  // create a relative result (eg, ".//a/b/c").
   std::string FindReadableFilepath(const std::string& filename) const;
 
+  // Searches for a read-openable file based on filename, which must be
+  // non-empty. The search is first attempted as a path relative to
+  // the requesting_file parameter. If no file is found relative to the
+  // requesting_file then this acts as FindReadableFilepath does. If
+  // requesting_file does not contain a '/' or a '\' character then it is
+  // assumed to be a filename and the request will be relative to the
+  // current directory.
+  std::string FindRelativeReadableFilepath(const std::string& requesting_file,
+                                           const std::string& filename) const;
+
   // Search path for Find().  Users may add/remove elements as desired.
   std::vector<std::string>& search_path() { return search_path_; }
 
diff --git a/libshaderc_util/src/compiler.cc b/libshaderc_util/src/compiler.cc
index 35c216b..7f24aa5 100644
--- a/libshaderc_util/src/compiler.cc
+++ b/libshaderc_util/src/compiler.cc
@@ -83,7 +83,7 @@
 // error message to *text_or_error.
 spv_result_t DisassembleBinary(const std::vector<uint32_t>& binary,
                                std::string* text_or_error) {
-  auto spvtools_context = spvContextCreate();
+  auto spvtools_context = spvContextCreate(SPV_ENV_UNIVERSAL_1_0);
   spv_text disassembled_text = nullptr;
   spv_diagnostic spvtools_diagnostic = nullptr;
 
@@ -107,14 +107,13 @@
 }  // anonymous namespace
 
 namespace shaderc_util {
-
 std::tuple<bool, std::vector<uint32_t>, size_t> Compiler::Compile(
     const string_piece& input_source_string, EShLanguage forced_shader_stage,
     const std::string& error_tag,
     const std::function<EShLanguage(std::ostream* error_stream,
                                     const string_piece& error_tag)>&
         stage_callback,
-    const CountingIncluder& includer, Compiler::OutputType output_type,
+    CountingIncluder& includer, OutputType output_type,
     std::ostream* error_stream, size_t* total_warnings, size_t* total_errors,
     GlslInitializer* initializer) const {
   // Compilation results to be returned:
@@ -155,7 +154,8 @@
     if (!success) return result_tuple;
     // Because of the behavior change of the #line directive, the #line
     // directive introducing each file's content must use the syntax for the
-    // specified version. So we need to probe this shader's version and profile.
+    // specified version. So we need to probe this shader's version and
+    // profile.
     int version;
     EProfile profile;
     std::tie(version, profile) = DeduceVersionProfile(preprocessed_shader);
@@ -216,7 +216,8 @@
                                  total_warnings, total_errors);
   if (!success) return result_tuple;
 
-  // 'spirv' is an alias for the compilation_output_data. This alias is added to
+  // 'spirv' is an alias for the compilation_output_data. This alias is added
+  // to
   // serve as an input for the call to DissassemblyBinary.
   std::vector<uint32_t>& spirv = compilation_output_data;
   // Note the call to GlslangToSpv also populates compilation_output_data.
@@ -266,8 +267,7 @@
 
 std::tuple<bool, std::string, std::string> Compiler::PreprocessShader(
     const std::string& error_tag, const string_piece& shader_source,
-    const string_piece& shader_preamble,
-    const CountingIncluder& includer) const {
+    const string_piece& shader_preamble, CountingIncluder& includer) const {
   // The stage does not matter for preprocessing.
   glslang::TShader shader(EShLangVertex);
   const char* shader_strings = shader_source.data();
diff --git a/libshaderc_util/src/compiler_test.cc b/libshaderc_util/src/compiler_test.cc
index 8957a7b..9614f5d 100644
--- a/libshaderc_util/src/compiler_test.cc
+++ b/libshaderc_util/src/compiler_test.cc
@@ -68,6 +68,12 @@
        #pragma shader_stage(vertex)
        void main() { int t = gl_VertexID; })";
 
+// A shader that compiles under Vulkan rules.
+// See the GL_KHR_vuklan_glsl extension to GLSL.
+const char kVulkanVertexShader[] =
+    R"(#version 310 es
+       void main() { int t = gl_VertexIndex; })";
+
 // A shader that needs valueless macro predefinition E, to be compiled
 // successfully.
 const std::string kValuelessPredefinitionShader =
@@ -83,10 +89,14 @@
 class DummyCountingIncluder : public shaderc_util::CountingIncluder {
  private:
   // Returns a pair of empty strings.
-  virtual std::pair<std::string, std::string> include_delegate(
-      const char*) const override {
-    return std::make_pair(std::string(), std::string());
+  virtual glslang::TShader::Includer::IncludeResult* include_delegate(
+      const char*, glslang::TShader::Includer::IncludeType,
+      const char*,
+      size_t) override {
+    return nullptr;
   }
+  virtual void release_delegate(
+      glslang::TShader::Includer::IncludeResult*) override {}
 };
 
 // A test fixture for compiling GLSL shaders.
@@ -107,9 +117,11 @@
     size_t total_errors = 0;
     shaderc_util::GlslInitializer initializer;
     bool result = false;
+    DummyCountingIncluder dummy_includer;
     std::tie(result, std::ignore, std::ignore) = compiler_.Compile(
-        source, stage, "shader", stage_callback, DummyCountingIncluder(),
-        output_type, &errors, &total_warnings, &total_errors, &initializer);
+        source, stage, "shader", stage_callback, dummy_includer,
+        Compiler::OutputType::SpirvBinary, &errors, &total_warnings,
+        &total_errors, &initializer);
     errors_ = errors.str();
     return result;
   }
@@ -120,7 +132,6 @@
     return SimpleCompilationSucceedsForOutputType(
         source, stage, Compiler::OutputType::SpirvBinary);
   }
-
  protected:
   Compiler compiler_;
   // The error string from the most recent compilation.
@@ -145,6 +156,10 @@
   EXPECT_FALSE(SimpleCompilationSucceeds(" bogus ", EShLangVertex));
 }
 
+TEST_F(CompilerTest, SimpleVulkanShaderCompilesWithDefaultCompilerSettings) {
+  EXPECT_TRUE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
+}
+
 TEST_F(CompilerTest, RespectTargetEnvOnOpenGLCompatibilityShader) {
   const EShLanguage stage = EShLangFragment;
 
@@ -193,8 +208,6 @@
 
   compiler_.SetMessageRules(kOpenGLRules);
   EXPECT_TRUE(SimpleCompilationSucceeds(kOpenGLVertexShader, stage));
-
-  // TODO(dneto): Check Vulkan rules.
 }
 
 TEST_F(CompilerTest, RespectTargetEnvOnOpenGLShaderWhenDeducingStage) {
@@ -207,12 +220,41 @@
   compiler_.SetMessageRules(kOpenGLRules);
   EXPECT_TRUE(
       SimpleCompilationSucceeds(kOpenGLVertexShaderDeducibleStage, stage));
-
-  // TODO(dneto): Check Vulkan rules.
 }
 
-TEST_F(CompilerTest, DISABLED_RespectTargetEnvOnVulkanShader) {
-  // TODO(dneto): Add test for a shader that should only compile for Vulkan.
+TEST_F(CompilerTest, RespectTargetEnvOnVulkanShader) {
+  compiler_.SetMessageRules(kVulkanRules);
+  EXPECT_TRUE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
+}
+
+TEST_F(CompilerTest, VulkanSpecificShaderFailsUnderOpenGLCompatibilityRules) {
+  compiler_.SetMessageRules(kOpenGLCompatibilityRules);
+  EXPECT_FALSE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
+}
+
+TEST_F(CompilerTest, VulkanSpecificShaderFailsUnderOpenGLRules) {
+  compiler_.SetMessageRules(kOpenGLRules);
+  EXPECT_FALSE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
+}
+
+TEST_F(CompilerTest, OpenGLCompatibilitySpecificShaderFailsUnderDefaultRules) {
+  EXPECT_FALSE(SimpleCompilationSucceeds(kOpenGLCompatibilityFragShader,
+                                         EShLangFragment));
+}
+
+TEST_F(CompilerTest, OpenGLSpecificShaderFailsUnderDefaultRules) {
+  EXPECT_FALSE(SimpleCompilationSucceeds(kOpenGLVertexShader, EShLangVertex));
+}
+
+TEST_F(CompilerTest, OpenGLCompatibilitySpecificShaderFailsUnderVulkanRules) {
+  compiler_.SetMessageRules(kVulkanRules);
+  EXPECT_FALSE(SimpleCompilationSucceeds(kOpenGLCompatibilityFragShader,
+                                         EShLangFragment));
+}
+
+TEST_F(CompilerTest, OpenGLSpecificShaderFailsUnderVulkanRules) {
+  compiler_.SetMessageRules(kVulkanRules);
+  EXPECT_FALSE(SimpleCompilationSucceeds(kOpenGLVertexShader, EShLangVertex));
 }
 
 TEST_F(CompilerTest, AddMacroDefinition) {
diff --git a/libshaderc_util/src/counting_includer_test.cc b/libshaderc_util/src/counting_includer_test.cc
index 1f452e4..0400ae3 100644
--- a/libshaderc_util/src/counting_includer_test.cc
+++ b/libshaderc_util/src/counting_includer_test.cc
@@ -19,13 +19,24 @@
 
 namespace {
 
+const auto kRelative = glslang::TShader::Includer::EIncludeRelative;
+const auto kStandard = glslang::TShader::Includer::EIncludeStandard;
+
 // A trivial implementation of CountingIncluder's virtual methods, so tests can
 // instantiate.
 class ConcreteCountingIncluder : public shaderc_util::CountingIncluder {
  public:
-  std::pair<std::string, std::string> include_delegate(
-      const char* filename) const override {
-    return std::make_pair<std::string, std::string>("", "Unexpected #include");
+  virtual glslang::TShader::Includer::IncludeResult* include_delegate(
+      const char* requested, glslang::TShader::Includer::IncludeType,
+      const char* requestor,
+      size_t) override {
+    const char kError[] = "Unexpected #include";
+    return new glslang::TShader::Includer::IncludeResult{
+        "", kError, strlen(kError), nullptr};
+  }
+  virtual void release_delegate(
+      glslang::TShader::Includer::IncludeResult* include_result) override {
+    delete include_result;
   }
 };
 
@@ -35,21 +46,21 @@
 
 TEST(CountingIncluderTest, OneInclude) {
   ConcreteCountingIncluder includer;
-  includer.include("random file name");
+  includer.include("random file name", kRelative, "from me", 0);
   EXPECT_EQ(1, includer.num_include_directives());
 }
 
-TEST(CountingIncluderTest, TwoIncludes) {
+TEST(CountingIncluderTest, TwoIncludesAnyIncludeType) {
   ConcreteCountingIncluder includer;
-  includer.include("name1");
-  includer.include("name2");
+  includer.include("name1", kRelative, "from me", 0);
+  includer.include("name2", kStandard, "me", 0);
   EXPECT_EQ(2, includer.num_include_directives());
 }
 
 TEST(CountingIncluderTest, ManyIncludes) {
   ConcreteCountingIncluder includer;
   for (int i = 0; i < 100; ++i) {
-    includer.include("filename");
+    includer.include("filename", kRelative, "from me", i);
   }
   EXPECT_EQ(100, includer.num_include_directives());
 }
@@ -57,9 +68,12 @@
 #ifndef SHADERC_DISABLE_THREADED_TESTS
 TEST(CountingIncluderTest, ThreadedIncludes) {
   ConcreteCountingIncluder includer;
-  std::thread t1([&includer]() { includer.include("name1"); });
-  std::thread t2([&includer]() { includer.include("name2"); });
-  std::thread t3([&includer]() { includer.include("name3"); });
+  std::thread t1(
+      [&includer]() { includer.include("name1", kRelative, "me", 0); });
+  std::thread t2(
+      [&includer]() { includer.include("name2", kRelative, "me", 1); });
+  std::thread t3(
+      [&includer]() { includer.include("name3", kRelative, "me", 2); });
   t1.join();
   t2.join();
   t3.join();
diff --git a/libshaderc_util/src/file_finder.cc b/libshaderc_util/src/file_finder.cc
index df926b6..d25c611 100644
--- a/libshaderc_util/src/file_finder.cc
+++ b/libshaderc_util/src/file_finder.cc
@@ -13,6 +13,7 @@
 // limitations under the License.
 
 #include "libshaderc_util/file_finder.h"
+#include "libshaderc_util/string_piece.h"
 
 #include <cassert>
 #include <fstream>
@@ -21,7 +22,7 @@
 namespace {
 
 // Returns "" if path is empty or ends in '/'.  Otherwise, returns "/".
-std::string MaybeSlash(const std::string& path) {
+std::string MaybeSlash(const shaderc_util::string_piece& path) {
   return (path.empty() || path.back() == '/') ? "" : "/";
 }
 
@@ -42,4 +43,29 @@
   return "";
 }
 
+std::string FileFinder::FindRelativeReadableFilepath(
+    const std::string& requesting_file, const std::string& filename) const {
+  assert(!filename.empty());
+
+  string_piece dir_name(requesting_file);
+
+  size_t last_slash = requesting_file.find_last_of("/\\");
+  if (last_slash != std::string::npos) {
+    dir_name = string_piece(requesting_file.c_str(),
+                            requesting_file.c_str() + last_slash);
+  }
+
+  if (dir_name.size() == requesting_file.size()) {
+    dir_name.clear();
+  }
+
+  static const auto for_reading = std::ios_base::in;
+  std::filebuf opener;
+  const std::string relative_filename =
+      dir_name.str() + MaybeSlash(dir_name) + filename;
+  if (opener.open(relative_filename, for_reading)) return relative_filename;
+
+  return FindReadableFilepath(filename);
+}
+
 }  // namespace shaderc_util
diff --git a/third_party/Android.mk b/third_party/Android.mk
index f192173..ed07147 100644
--- a/third_party/Android.mk
+++ b/third_party/Android.mk
@@ -39,6 +39,20 @@
 LOCAL_STATIC_LIBRARIES:=OSDependent
 include $(BUILD_STATIC_LIBRARY)
 
+
+# Build Glslang's HLSL parser library.
+include $(CLEAR_VARS)
+LOCAL_MODULE:=HLSL
+LOCAL_CXXFLAGS:=-std=c++11 -fno-exceptions -fno-rtti
+LOCAL_SRC_FILES:= \
+		hlsl/hlslGrammar.cpp \
+		hlsl/hlslParseHelper.cpp \
+		hlsl/hlslScanContext.cpp
+LOCAL_C_INCLUDES:=$(GLSLANG_LOCAL_PATH) \
+	$(GLSLANG_LOCAL_PATH)/hlsl
+include $(BUILD_STATIC_LIBRARY)
+
+
 include $(CLEAR_VARS)
 
 GLSLANG_OUT_PATH=$(abspath $(TARGET_OUT))
@@ -79,22 +93,44 @@
 LOCAL_C_INCLUDES:=$(GLSLANG_LOCAL_PATH) \
 	$(GLSLANG_LOCAL_PATH)/glslang/MachineIndependent \
 	$(GLSLANG_OUT_PATH)
-LOCAL_STATIC_LIBRARIES:=OSDependent OGLCompiler SPIRV
+LOCAL_STATIC_LIBRARIES:=OSDependent OGLCompiler SPIRV HLSL
 include $(BUILD_STATIC_LIBRARY)
 
 
 SPVTOOLS_LOCAL_PATH := $(THIRD_PARTY_PATH)/spirv-tools
 LOCAL_PATH := $(SPVTOOLS_LOCAL_PATH)
+SPVTOOLS_OUT_PATH=$(abspath $(TARGET_OUT))
+
+define gen_spvtools_grammar_tables
+$(call generate-file-dir,$(1)/core.insts.inc)
+$(1)/core.insts.inc $(1)/operand.kinds.inc $(1)/glsl.std.450.insts.inc $(1)/opencl.std.insts.inc: \
+        $(SPVTOOLS_LOCAL_PATH)/utils/generate_grammar_tables.py \
+        $(SPVTOOLS_LOCAL_PATH)/source/spirv.core.grammar.json \
+        $(SPVTOOLS_LOCAL_PATH)/source/extinst.glsl.std.450.grammar.json \
+        $(SPVTOOLS_LOCAL_PATH)/source/extinst.opencl.std.grammar.json
+		@$(HOST_PYTHON) $(SPVTOOLS_LOCAL_PATH)/utils/generate_grammar_tables.py \
+		                --spirv-core-grammar=$(SPVTOOLS_LOCAL_PATH)/source/spirv.core.grammar.json \
+		                --extinst-glsl-grammar=$(SPVTOOLS_LOCAL_PATH)/source/extinst.glsl.std.450.grammar.json \
+		                --extinst-opencl-grammar=$(SPVTOOLS_LOCAL_PATH)/source/extinst.opencl.std.grammar.json \
+		                --core-insts-output=$(1)/core.insts.inc \
+		                --glsl-insts-output=$(1)/glsl.std.450.insts.inc \
+		                --opencl-insts-output=$(1)/opencl.std.insts.inc \
+		                --operand-kinds-output=$(1)/operand.kinds.inc
+		@echo "[$(TARGET_ARCH_ABI)] Grammar        : instructions & operands <= grammar JSON files"
+$(SPVTOOLS_LOCAL_PATH)/source/opcode.cpp: $(1)/core.insts.inc
+$(SPVTOOLS_LOCAL_PATH)/source/operand.cpp: $(1)/operand.kinds.inc
+$(SPVTOOLS_LOCAL_PATH)/source/ext_inst.cpp: $(1)/glsl.std.450.insts.inc $(1)/opencl.std.insts.inc
+endef
+$(eval $(call gen_spvtools_grammar_tables,$(SPVTOOLS_OUT_PATH)))
 
 include $(CLEAR_VARS)
 LOCAL_MODULE := SPIRV-Tools
 LOCAL_C_INCLUDES := \
 		$(SPVTOOLS_LOCAL_PATH)/include \
-		$(SPVTOOLS_LOCAL_PATH)/external/include \
-		$(SPVTOOLS_LOCAL_PATH)/source
+		$(SPVTOOLS_LOCAL_PATH)/source \
+		$(SPVTOOLS_OUT_PATH)
 LOCAL_EXPORT_C_INCLUDES := \
-		$(SPVTOOLS_LOCAL_PATH)/include \
-		$(SPVTOOLS_LOCAL_PATH)/external/include
+		$(SPVTOOLS_LOCAL_PATH)/include
 LOCAL_CXXFLAGS:=-std=c++11 -fno-exceptions -fno-rtti
 LOCAL_SRC_FILES:= \
 		source/assembly_grammar.cpp \
@@ -107,11 +143,12 @@
 		source/operand.cpp \
 		source/print.cpp \
 		source/spirv_endian.cpp \
+		source/spirv_target_env.cpp \
 		source/table.cpp \
 		source/text.cpp \
 		source/text_handler.cpp \
-		source/validate_cfg.cpp \
 		source/validate.cpp \
+		source/validate_cfg.cpp \
 		source/validate_id.cpp \
 		source/validate_instruction.cpp \
 		source/validate_layout.cpp \