Merge commit 'b5f003d7a3ece37db45578a8a3140b370036fc64' into vulkan-cts
diff --git a/.appveyor.yml b/.appveyor.yml
index 5765d9e..44d5f04 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -17,6 +17,20 @@
   only:
     - master
 
+# changes to these files don't need to trigger testing
+skip_commits:
+  files:
+    - README.md
+    - README-spirv-remap.txt
+    - LICENSE.txt
+    - CODE_OF_CONDUCT.md
+    - BUILD.*
+    - WORKSPACE
+    - kokoro/*
+    - make-revision
+    - Android.mk
+    - _config.yml
+
 # Travis advances the master-tot tag to current top of the tree after
 # each push into the master branch, because it relies on that tag to
 # upload build artifacts to the master-tot release. This will cause
@@ -32,6 +46,7 @@
 # scripts that run after cloning repository
 install:
   - C:/Python27/python.exe update_glslang_sources.py
+  - set PATH=C:\ninja;C:\Python36;%PATH%
   - git clone https://github.com/google/googletest.git External/googletest
   - cd External/googletest
   - git checkout 440527a61e1c91188195f7de212c63c77e8f0a45
@@ -65,7 +80,6 @@
     bin\glslangValidator.exe
     bin\spirv-remap.exe
     include\glslang\*
-    include\SPIRV\*
     lib\glslang%SUFFIX%.lib
     lib\HLSL%SUFFIX%.lib
     lib\OGLCompiler%SUFFIX%.lib
diff --git a/.clang-format b/.clang-format
index daf8798..8c73a52 100644
--- a/.clang-format
+++ b/.clang-format
@@ -1,7 +1,8 @@
 Language: Cpp
 IndentWidth: 4
+PointerAlignment: Left
 BreakBeforeBraces: Custom
-BraceWrapping: { AfterFunction: true, AfterControlStatement: true }
+BraceWrapping: { AfterFunction: true, AfterControlStatement: false }
 IndentCaseLabels: false
 ReflowComments: false
 ColumnLimit: 120
diff --git a/.travis.yml b/.travis.yml
index 2478912..1fa3fc0 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -99,7 +99,6 @@
       zip ${TARBALL}
         bin/glslangValidator
         include/glslang/*
-        include/SPIRV/*
         lib/libglslang${SUFFIX}.a
         lib/libHLSL${SUFFIX}.a
         lib/libOGLCompiler${SUFFIX}.a
diff --git a/BUILD.bazel b/BUILD.bazel
new file mode 100644
index 0000000..5930608
--- /dev/null
+++ b/BUILD.bazel
@@ -0,0 +1,247 @@
+package(
+    default_visibility = ["//visibility:public"],
+)
+
+# Description:
+#
+# Khronos reference front-end for GLSL and ESSL, and sample SPIR-V generator.
+
+licenses(["notice"])
+
+exports_files(["LICENSE"])
+
+COMMON_COPTS = select({
+    "@bazel_tools//src/conditions:windows": [""],
+    "//conditions:default": [
+        "-Wall",
+        "-Wuninitialized",
+        "-Wunused",
+        "-Wunused-local-typedefs",
+        "-Wunused-parameter",
+        "-Wunused-value",
+        "-Wunused-variable",
+        "-Wno-reorder",
+        "-std=c++11",
+        "-fvisibility=hidden",
+        "-fvisibility-inlines-hidden",
+        "-fno-exceptions",
+        "-fno-rtti",
+    ],
+})
+
+cc_library(
+    name = "glslang",
+    srcs = glob(
+        [
+            "glslang/GenericCodeGen/*.cpp",
+            "glslang/MachineIndependent/*.cpp",
+            "glslang/MachineIndependent/preprocessor/*.cpp",
+            "hlsl/*.cpp",
+        ],
+        exclude = [
+            "glslang/MachineIndependent/pch.cpp",
+            "glslang/MachineIndependent/pch.h",
+            "hlsl/pch.cpp",
+            "hlsl/pch.h",
+        ],
+    ) + [
+        "OGLCompilersDLL/InitializeDll.cpp",
+    ] + select({
+        "@bazel_tools//src/conditions:windows":
+            ["glslang/OSDependent/Windows/ossource.cpp"],
+        "//conditions:default":
+            ["glslang/OSDependent/Unix/ossource.cpp"],
+    }),
+    hdrs = glob([
+        "glslang/Include/*.h",
+        "glslang/MachineIndependent/*.h",
+        "glslang/MachineIndependent/preprocessor/*.h",
+        "hlsl/*.h",
+    ]) + [
+        "OGLCompilersDLL/InitializeDll.h",
+        "StandAlone/DirStackFileIncluder.h",
+        "glslang/OSDependent/osinclude.h",
+        "glslang/Public/ShaderLang.h",
+    ],
+    copts = COMMON_COPTS,
+    defines = [
+        "AMD_EXTENSIONS",
+        "ENABLE_HLSL=0",
+        "ENABLE_OPT=0",
+        "NV_EXTENSIONS",
+    ],
+    linkopts = select({
+        "@bazel_tools//src/conditions:windows": [""],
+        "//conditions:default": ["-lm", "-lpthread"],
+    }),
+    linkstatic = 1,
+)
+
+genrule(
+    name = "export_spirv_headers",
+    srcs = [
+        "SPIRV/GLSL.ext.AMD.h",
+        "SPIRV/GLSL.ext.EXT.h",
+        "SPIRV/GLSL.ext.KHR.h",
+        "SPIRV/GLSL.ext.NV.h",
+        "SPIRV/GLSL.std.450.h",
+        "SPIRV/NonSemanticDebugPrintf.h",
+        "SPIRV/spirv.hpp",
+    ],
+    outs = [
+        "include/SPIRV/GLSL.ext.AMD.h",
+        "include/SPIRV/GLSL.ext.EXT.h",
+        "include/SPIRV/GLSL.ext.KHR.h",
+        "include/SPIRV/GLSL.ext.NV.h",
+        "include/SPIRV/GLSL.std.450.h",
+        "include/SPIRV/NonSemanticDebugPrintf.h",
+        "include/SPIRV/spirv.hpp",
+    ],
+    cmd = "mkdir -p $(@D)/include/SPIRV && cp $(SRCS) $(@D)/include/SPIRV/",
+)
+
+cc_library(
+    name = "SPIRV_headers",
+    hdrs = [":export_spirv_headers"],
+    copts = COMMON_COPTS,
+    includes = [
+        "include",
+        "include/SPIRV",
+    ],
+    linkstatic = 1,
+)
+
+cc_library(
+    name = "SPIRV",
+    srcs = glob(
+        ["SPIRV/*.cpp"],
+        exclude = [
+            "SPIRV/SpvTools.cpp",
+        ],
+    ),
+    hdrs = [
+        "SPIRV/GlslangToSpv.h",
+        "SPIRV/Logger.h",
+        "SPIRV/SPVRemapper.h",
+        "SPIRV/SpvBuilder.h",
+        "SPIRV/SpvTools.h",
+        "SPIRV/bitutils.h",
+        "SPIRV/disassemble.h",
+        "SPIRV/doc.h",
+        "SPIRV/hex_float.h",
+        "SPIRV/spvIR.h",
+    ],
+    copts = COMMON_COPTS,
+    includes = ["SPIRV"],
+    linkopts = select({
+        "@bazel_tools//src/conditions:windows": [""],
+        "//conditions:default": ["-lm"],
+    }),
+    linkstatic = 1,
+    deps = [
+        ":SPIRV_headers",
+        ":glslang",
+    ],
+)
+
+cc_library(
+    name = "glslang-default-resource-limits",
+    srcs = ["StandAlone/ResourceLimits.cpp"],
+    hdrs = ["StandAlone/ResourceLimits.h"],
+    copts = COMMON_COPTS,
+    linkstatic = 1,
+    deps = [":glslang"],
+)
+
+cc_binary(
+    name = "glslangValidator",
+    srcs = [
+        "StandAlone/StandAlone.cpp",
+        "StandAlone/Worklist.h",
+    ],
+    copts = COMMON_COPTS,
+    deps = [
+        ":SPIRV",
+        ":glslang",
+        ":glslang-default-resource-limits",
+    ],
+)
+
+cc_binary(
+    name = "spirv-remap",
+    srcs = ["StandAlone/spirv-remap.cpp"],
+    copts = COMMON_COPTS,
+    deps = [
+        ":SPIRV",
+        ":glslang",
+        ":glslang-default-resource-limits",
+    ],
+)
+
+filegroup(
+    name = "test_files",
+    srcs = glob(
+        ["Test/**"],
+        exclude = [
+            "Test/bump",
+            "Test/glslangValidator",
+            "Test/runtests",
+        ],
+    ),
+)
+
+cc_library(
+    name = "glslang_test_lib",
+    testonly = 1,
+    srcs = [
+        "gtests/HexFloat.cpp",
+        "gtests/Initializer.h",
+        "gtests/Settings.cpp",
+        "gtests/Settings.h",
+        "gtests/TestFixture.cpp",
+        "gtests/TestFixture.h",
+        "gtests/main.cpp",
+    ],
+    copts = COMMON_COPTS,
+    data = [":test_files"],
+    defines = select({
+        # Unfortunately we can't use $(location) in cc_library at the moment.
+        # See https://github.com/bazelbuild/bazel/issues/1023
+        # So we'll specify the path manually.
+        "@bazel_tools//src/conditions:windows":
+            ["GLSLANG_TEST_DIRECTORY='\"../../../../../Test\"'"],
+        "//conditions:default":
+            ["GLSLANG_TEST_DIRECTORY='\"Test\"'"],
+    }),
+    linkstatic = 1,
+    deps = [
+        ":SPIRV",
+        ":glslang",
+        ":glslang-default-resource-limits",
+        "@com_google_googletest//:gtest",
+    ],
+)
+
+GLSLANG_TESTS = glob(
+    ["gtests/*.FromFile.cpp"],
+    # Since we are not building the SPIRV-Tools dependency, the following tests
+    # cannot be performed.
+    exclude = [
+        "gtests/Hlsl.FromFile.cpp",
+        "gtests/Spv.FromFile.cpp",
+    ],
+)
+
+[cc_test(
+    name = test_file.replace("gtests/", "").replace(".FromFile.cpp", "") + "_test",
+    srcs = [test_file],
+    copts = COMMON_COPTS,
+    data = [
+        ":test_files",
+    ],
+    deps = [
+        ":SPIRV",
+        ":glslang",
+        ":glslang_test_lib",
+    ],
+) for test_file in GLSLANG_TESTS]
diff --git a/BUILD.gn b/BUILD.gn
index d8bfe61..49b4b0a 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -33,10 +33,25 @@
 
 import("//build_overrides/glslang.gni")
 
+# Both Chromium and Fuchsia use by default a set of warning errors
+# that is far too strict to compile this project. These are also
+# typically appended after |cflags|, overriding target-specific
+# definitions. To work around this, determine which configs to
+# add and remove in order to succesfully build the project.
+if (defined(is_fuchsia_tree) && is_fuchsia_tree) {
+  _configs_to_remove = [ "//build/config:default_warnings" ]
+  _configs_to_add = []
+} else {
+  _configs_to_remove = [ "//build/config/compiler:chromium_code" ]
+  _configs_to_add = [ "//build/config/compiler:no_chromium_code" ]
+}
+
 spirv_tools_dir = glslang_spirv_tools_dir
 
 config("glslang_public") {
   include_dirs = [ "." ]
+
+  defines = [ "ENABLE_HLSL=1" ]
 }
 
 source_set("glslang_sources") {
@@ -45,19 +60,24 @@
   sources = [
     "OGLCompilersDLL/InitializeDll.cpp",
     "OGLCompilersDLL/InitializeDll.h",
+    "SPIRV/GLSL.ext.AMD.h",
     "SPIRV/GLSL.ext.EXT.h",
     "SPIRV/GLSL.ext.KHR.h",
+    "SPIRV/GLSL.ext.NV.h",
     "SPIRV/GLSL.std.450.h",
     "SPIRV/GlslangToSpv.cpp",
     "SPIRV/GlslangToSpv.h",
     "SPIRV/InReadableOrder.cpp",
     "SPIRV/Logger.cpp",
     "SPIRV/Logger.h",
+    "SPIRV/NonSemanticDebugPrintf.h",
     "SPIRV/SPVRemapper.cpp",
     "SPIRV/SPVRemapper.h",
     "SPIRV/SpvBuilder.cpp",
     "SPIRV/SpvBuilder.h",
     "SPIRV/SpvPostProcess.cpp",
+    "SPIRV/SpvTools.cpp",
+    "SPIRV/SpvTools.h",
     "SPIRV/bitutils.h",
     "SPIRV/disassemble.cpp",
     "SPIRV/disassemble.h",
@@ -104,7 +124,6 @@
     "glslang/MachineIndependent/attribute.cpp",
     "glslang/MachineIndependent/attribute.h",
     "glslang/MachineIndependent/gl_types.h",
-    "glslang/MachineIndependent/glslang.y",
     "glslang/MachineIndependent/glslang_tab.cpp",
     "glslang/MachineIndependent/glslang_tab.cpp.h",
     "glslang/MachineIndependent/intermOut.cpp",
@@ -128,9 +147,25 @@
     "glslang/MachineIndependent/reflection.h",
     "glslang/OSDependent/osinclude.h",
     "glslang/Public/ShaderLang.h",
+    "hlsl/hlslAttributes.cpp",
+    "hlsl/hlslAttributes.h",
+    "hlsl/hlslGrammar.cpp",
+    "hlsl/hlslGrammar.h",
+    "hlsl/hlslOpMap.cpp",
+    "hlsl/hlslOpMap.h",
+    "hlsl/hlslParseHelper.cpp",
+    "hlsl/hlslParseHelper.h",
+    "hlsl/hlslParseables.cpp",
+    "hlsl/hlslParseables.h",
+    "hlsl/hlslScanContext.cpp",
+    "hlsl/hlslScanContext.h",
+    "hlsl/hlslTokenStream.cpp",
+    "hlsl/hlslTokenStream.h",
+    "hlsl/hlslTokens.h",
   ]
 
-  defines = []
+  defines = [ "ENABLE_OPT=1" ]
+
   if (is_win) {
     sources += [ "glslang/OSDependent/Windows/ossource.cpp" ]
     defines += [ "GLSLANG_OSINCLUDE_WIN32" ]
@@ -140,25 +175,31 @@
   }
 
   if (is_clang) {
-    cflags_cc = [
+    cflags = [
       "-Wno-extra-semi",
       "-Wno-ignored-qualifiers",
       "-Wno-implicit-fallthrough",
       "-Wno-inconsistent-missing-override",
       "-Wno-sign-compare",
       "-Wno-unused-variable",
+      "-Wno-missing-field-initializers",
+      "-Wno-newline-eof",
     ]
   }
   if (is_win && !is_clang) {
     cflags = [
-      "/wd4018", # signed/unsigned mismatch
-      "/wd4189", # local variable is initialized but not referenced
+      "/wd4018",  # signed/unsigned mismatch
+      "/wd4189",  # local variable is initialized but not referenced
     ]
   }
 
   deps = [
     "${spirv_tools_dir}:spvtools_opt",
+    "${spirv_tools_dir}:spvtools_val",
   ]
+
+  configs -= _configs_to_remove
+  configs += _configs_to_add
 }
 
 source_set("glslang_default_resource_limits_sources") {
@@ -166,8 +207,13 @@
     "StandAlone/ResourceLimits.cpp",
     "StandAlone/ResourceLimits.h",
   ]
-  deps = [ ":glslang_sources" ]
+  deps = [
+    ":glslang_sources",
+  ]
   public_configs = [ ":glslang_public" ]
+
+  configs -= _configs_to_remove
+  configs += _configs_to_add
 }
 
 executable("glslang_validator") {
@@ -178,9 +224,25 @@
   if (!is_win) {
     cflags = [ "-Woverflow" ]
   }
-  defines = [ "ENABLE_OPT=0" ]
+  defines = [ "ENABLE_OPT=1" ]
   deps = [
     ":glslang_default_resource_limits_sources",
     ":glslang_sources",
   ]
+
+  configs -= _configs_to_remove
+  configs += _configs_to_add
+}
+
+executable("spirv-remap") {
+  sources = [
+    "StandAlone/spirv-remap.cpp",
+  ]
+  defines = [ "ENABLE_OPT=1" ]
+  deps = [
+    ":glslang_sources",
+  ]
+
+  configs -= _configs_to_remove
+  configs += _configs_to_add
 }
diff --git a/CMakeLists.txt b/CMakeLists.txt
index aafa70e..cd9baf8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -6,10 +6,17 @@
 endif()
 set_property(GLOBAL PROPERTY USE_FOLDERS ON)
 
+# Enable compile commands database
+set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
+
 # Adhere to GNU filesystem layout conventions
 include(GNUInstallDirs)
 
+# Needed for CMAKE_DEPENDENT_OPTION macro
+include(CMakeDependentOption)
+
 option(BUILD_SHARED_LIBS "Build Shared Libraries" OFF)
+option(BUILD_EXTERNAL "Build external dependencies in /External" ON)
 
 set(LIB_TYPE STATIC)
 
@@ -23,14 +30,36 @@
 endif()
 option(ENABLE_SPVREMAPPER "Enables building of SPVRemapper" ON)
 
-option(ENABLE_AMD_EXTENSIONS "Enables support of AMD-specific extensions" ON)
 option(ENABLE_GLSLANG_BINARIES "Builds glslangValidator and spirv-remap" ON)
 
-option(ENABLE_NV_EXTENSIONS "Enables support of Nvidia-specific extensions" ON)
+option(ENABLE_GLSLANG_JS
+    "If using Emscripten, build glslang.js. Otherwise, builds a sample executable for binary-size testing." OFF)
+CMAKE_DEPENDENT_OPTION(ENABLE_GLSLANG_WEBMIN
+    "Reduces glslang to minimum needed for web use"
+    OFF "ENABLE_GLSLANG_JS"
+    OFF)
+CMAKE_DEPENDENT_OPTION(ENABLE_GLSLANG_WEBMIN_DEVEL
+    "For ENABLE_GLSLANG_WEBMIN builds, enables compilation error messages"
+    OFF "ENABLE_GLSLANG_WEBMIN"
+    OFF)
+CMAKE_DEPENDENT_OPTION(ENABLE_EMSCRIPTEN_SINGLE_FILE
+    "If using Emscripten, enables SINGLE_FILE build"
+    OFF "ENABLE_GLSLANG_JS AND EMSCRIPTEN"
+    OFF)
+CMAKE_DEPENDENT_OPTION(ENABLE_EMSCRIPTEN_ENVIRONMENT_NODE
+    "If using Emscripten, builds to run on Node instead of Web"
+    OFF "ENABLE_GLSLANG_JS AND EMSCRIPTEN"
+    OFF)
 
-option(ENABLE_HLSL "Enables HLSL input support" ON)
+CMAKE_DEPENDENT_OPTION(ENABLE_HLSL
+    "Enables HLSL input support"
+    ON "NOT ENABLE_GLSLANG_WEBMIN"
+    OFF)
 
+option(ENABLE_RTTI "Enables RTTI" OFF)
 option(ENABLE_OPT "Enables spirv-opt capability if present" ON)
+option(ENABLE_PCH "Enables Precompiled header" ON)
+option(ENABLE_CTEST "Enables testing" ON)
 
 if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT AND WIN32)
     set(CMAKE_INSTALL_PREFIX "install" CACHE STRING "..." FORCE)
@@ -46,7 +75,7 @@
 
 # Precompiled header macro. Parameters are source file list and filename for pch cpp file.
 macro(glslang_pch SRCS PCHCPP)
-  if(MSVC AND CMAKE_GENERATOR MATCHES "^Visual Studio")
+  if(MSVC AND CMAKE_GENERATOR MATCHES "^Visual Studio" AND NOT ${CMAKE_CXX_COMPILER_ID} MATCHES "Clang" AND ENABLE_PCH)
     set(PCH_NAME "$(IntDir)\\pch.pch")
     # make source files use/depend on PCH_NAME
     set_source_files_properties(${${SRCS}} PROPERTIES COMPILE_FLAGS "/Yupch.h /FIpch.h /Fp${PCH_NAME} /Zm300" OBJECT_DEPENDS "${PCH_NAME}")
@@ -57,21 +86,22 @@
 endmacro(glslang_pch)
 
 project(glslang)
-# make testing optional
-include(CTest)
 
-if(ENABLE_AMD_EXTENSIONS)
-    add_definitions(-DAMD_EXTENSIONS)
-endif(ENABLE_AMD_EXTENSIONS)
-
-if(ENABLE_NV_EXTENSIONS)
-    add_definitions(-DNV_EXTENSIONS)
-endif(ENABLE_NV_EXTENSIONS)
+if(ENABLE_CTEST)
+    include(CTest)
+endif()
 
 if(ENABLE_HLSL)
     add_definitions(-DENABLE_HLSL)
 endif(ENABLE_HLSL)
 
+if(ENABLE_GLSLANG_WEBMIN)
+    add_definitions(-DGLSLANG_WEB)
+    if(ENABLE_GLSLANG_WEBMIN_DEVEL)
+        add_definitions(-DGLSLANG_WEB_DEVEL)
+    endif(ENABLE_GLSLANG_WEBMIN_DEVEL)
+endif(ENABLE_GLSLANG_WEBMIN)
+
 if(WIN32)
     set(CMAKE_DEBUG_POSTFIX "d")
     if(MSVC)
@@ -88,17 +118,42 @@
     add_compile_options(-Wall -Wmaybe-uninitialized -Wuninitialized -Wunused -Wunused-local-typedefs
                         -Wunused-parameter -Wunused-value  -Wunused-variable -Wunused-but-set-parameter -Wunused-but-set-variable -fno-exceptions)
     add_compile_options(-Wno-reorder)  # disable this from -Wall, since it happens all over.
-elseif(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")
+    if(NOT ENABLE_RTTI)
+        add_compile_options(-fno-rtti)
+    endif()
+    if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "9.0.0")
+        add_compile_options(-Werror=deprecated-copy)
+    endif()
+elseif(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang" AND NOT MSVC)
     add_compile_options(-Wall -Wuninitialized -Wunused -Wunused-local-typedefs
                         -Wunused-parameter -Wunused-value  -Wunused-variable)
     add_compile_options(-Wno-reorder)  # disable this from -Wall, since it happens all over.
+    if(NOT ENABLE_RTTI)
+        add_compile_options(-fno-rtti)
+    endif()
+elseif(MSVC)
+    if(NOT ENABLE_RTTI)
+        add_compile_options(/GR-) # Disable RTTI
+    endif()
 endif()
 
+if(ENABLE_GLSLANG_JS)
+    if(MSVC)
+        add_compile_options(/Os /GR-)
+    else()
+        add_compile_options(-Os -fno-exceptions)
+        if(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang" AND NOT MSVC)
+            add_compile_options(-Wno-unused-parameter)
+            add_compile_options(-Wno-unused-variable -Wno-unused-const-variable)
+        endif()
+    endif()
+endif(ENABLE_GLSLANG_JS)
+
 # Request C++11
 if(${CMAKE_VERSION} VERSION_LESS 3.1)
     # CMake versions before 3.1 do not understand CMAKE_CXX_STANDARD
     # remove this block once CMake >=3.1 has fixated in the ecosystem
-    add_compile_options(-std=c++11)
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
 else()
     set(CMAKE_CXX_STANDARD 11)
     set(CMAKE_CXX_STANDARD_REQUIRED ON)
@@ -114,8 +169,14 @@
     endif()
 endfunction(glslang_set_link_args)
 
-# We depend on these for later projects, so they should come first.
-add_subdirectory(External)
+# CMake needs to find the right version of python, right from the beginning,
+# otherwise, it will find the wrong version and fail later
+if(BUILD_EXTERNAL AND IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/External)
+    find_package(PythonInterp 3 REQUIRED)
+
+	# We depend on these for later projects, so they should come first.
+	add_subdirectory(External)
+endif()
 
 if(NOT TARGET SPIRV-Tools-opt)
     set(ENABLE_OPT OFF)
@@ -140,4 +201,29 @@
 if(ENABLE_HLSL)
     add_subdirectory(hlsl)
 endif(ENABLE_HLSL)
-add_subdirectory(gtests)
+if(ENABLE_CTEST)
+    add_subdirectory(gtests)
+endif()
+
+if(BUILD_TESTING)
+    # glslang-testsuite runs a bash script on Windows.
+    # Make sure to use '-o igncr' flag to ignore carriage returns (\r).
+    set(IGNORE_CR_FLAG "")
+    if(WIN32)
+        set(IGNORE_CR_FLAG -o igncr)
+    endif()
+
+    if (CMAKE_CONFIGURATION_TYPES)
+        set(RESULTS_PATH ${CMAKE_CURRENT_BINARY_DIR}/$<CONFIGURATION>/localResults)
+        set(VALIDATOR_PATH ${CMAKE_CURRENT_BINARY_DIR}/StandAlone/$<CONFIGURATION>/glslangValidator)
+        set(REMAP_PATH ${CMAKE_CURRENT_BINARY_DIR}/StandAlone/$<CONFIGURATION>/spirv-remap)
+    else(CMAKE_CONFIGURATION_TYPES)
+        set(RESULTS_PATH ${CMAKE_CURRENT_BINARY_DIR}/localResults)
+        set(VALIDATOR_PATH ${CMAKE_CURRENT_BINARY_DIR}/StandAlone/glslangValidator)
+        set(REMAP_PATH ${CMAKE_CURRENT_BINARY_DIR}/StandAlone/spirv-remap)
+    endif(CMAKE_CONFIGURATION_TYPES)
+
+    add_test(NAME glslang-testsuite
+        COMMAND bash ${IGNORE_CR_FLAG} runtests ${RESULTS_PATH} ${VALIDATOR_PATH} ${REMAP_PATH}
+        WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/Test/)
+endif(BUILD_TESTING)
diff --git a/External/CMakeLists.txt b/External/CMakeLists.txt
index 4d96901..6ff4f47 100644
--- a/External/CMakeLists.txt
+++ b/External/CMakeLists.txt
@@ -10,7 +10,8 @@
         if(WIN32)
             set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
         endif(WIN32)
-        add_subdirectory(googletest)
+        # EXCLUDE_FROM_ALL keeps the install target from installing GTEST files.
+        add_subdirectory(googletest EXCLUDE_FROM_ALL)
         set(GTEST_TARGETS
             gtest
             gtest_main
diff --git a/LICENSE.txt b/LICENSE.txt
old mode 100755
new mode 100644
diff --git a/OGLCompilersDLL/CMakeLists.txt b/OGLCompilersDLL/CMakeLists.txt
index 5bb3f0e..e009674 100644
--- a/OGLCompilersDLL/CMakeLists.txt
+++ b/OGLCompilersDLL/CMakeLists.txt
@@ -9,6 +9,7 @@
 endif(WIN32)
 
 if(ENABLE_GLSLANG_INSTALL)
-    install(TARGETS OGLCompiler
+    install(TARGETS OGLCompiler EXPORT OGLCompilerTargets
             ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
+	install(EXPORT OGLCompilerTargets DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake)
 endif(ENABLE_GLSLANG_INSTALL)
diff --git a/README.md b/README.md
index 7d4fe3a..ff844c0 100755
--- a/README.md
+++ b/README.md
@@ -1,35 +1,70 @@
-Also see the Khronos landing page for glslang as a reference front end:
-
-https://www.khronos.org/opengles/sdk/tools/Reference-Compiler/
-
-The above page includes where to get binaries, and is kept up to date
-regarding the feature level of glslang.
-
-glslang
-=======
+# News
 
 [![Build Status](https://travis-ci.org/KhronosGroup/glslang.svg?branch=master)](https://travis-ci.org/KhronosGroup/glslang)
 [![Build status](https://ci.appveyor.com/api/projects/status/q6fi9cb0qnhkla68/branch/master?svg=true)](https://ci.appveyor.com/project/Khronoswebmaster/glslang/branch/master)
 
-An OpenGL and OpenGL ES shader front end and validator.
+## Planned Deprecations/Removals
+
+1. **SPIRV Folder, 1-May, 2020.** Glslang, when installed through CMake,
+will install a `SPIRV` folder into `${CMAKE_INSTALL_INCLUDEDIR}`.
+This `SPIRV` folder is being moved to `glslang/SPIRV`.
+During the transition the `SPIRV` folder will be installed into both locations.
+The old install of `SPIRV/` will be removed as a CMake install target no sooner than May 1, 2020.
+See issue #1964.
+
+2. **Visual Studio 2013, 20-July, 2020.** Keeping code compiling for MS Visual Studio 2013 will no longer be
+a goal as of July 20, 2020, the fifth anniversary of the release of Visual Studio 2015.
+
+# Glslang Components and Status
 
 There are several components:
 
-1. A GLSL/ESSL front-end for reference validation and translation of GLSL/ESSL into an AST.
+### Reference Validator and GLSL/ESSL -> AST Front End
 
-2. An HLSL front-end for translation of a broad generic HLL into the AST. See [issue 362](https://github.com/KhronosGroup/glslang/issues/362) and [issue 701](https://github.com/KhronosGroup/glslang/issues/701) for current status.
+An OpenGL GLSL and OpenGL|ES GLSL (ESSL) front-end for reference validation and translation of GLSL/ESSL into an internal abstract syntax tree (AST).
 
-3. A SPIR-V back end for translating the AST to SPIR-V.
+**Status**: Virtually complete, with results carrying similar weight as the specifications.
 
-4. A standalone wrapper, `glslangValidator`, that can be used as a command-line tool for the above.
+### HLSL -> AST Front End
 
-How to add a feature protected by a version/extension/stage/profile:  See the
-comment in `glslang/MachineIndependent/Versions.cpp`.
+An HLSL front-end for translation of an approximation of HLSL to glslang's AST form.
+
+**Status**: Partially complete. Semantics are not reference quality and input is not validated.
+This is in contrast to the [DXC project](https://github.com/Microsoft/DirectXShaderCompiler), which receives a much larger investment and attempts to have definitive/reference-level semantics.
+
+See [issue 362](https://github.com/KhronosGroup/glslang/issues/362) and [issue 701](https://github.com/KhronosGroup/glslang/issues/701) for current status.
+
+### AST -> SPIR-V Back End
+
+Translates glslang's AST to the Khronos-specified SPIR-V intermediate language.
+
+**Status**: Virtually complete.
+
+### Reflector
+
+An API for getting reflection information from the AST, reflection types/variables/etc. from the HLL source (not the SPIR-V).
+
+**Status**: There is a large amount of functionality present, but no specification/goal to measure completeness against.  It is accurate for the input HLL and AST, but only approximate for what would later be emitted for SPIR-V.
+
+### Standalone Wrapper
+
+`glslangValidator` is command-line tool for accessing the functionality above.
+
+Status: Complete.
 
 Tasks waiting to be done are documented as GitHub issues.
 
-Execution of Standalone Wrapper
--------------------------------
+## Other References
+
+Also see the Khronos landing page for glslang as a reference front end:
+
+https://www.khronos.org/opengles/sdk/tools/Reference-Compiler/
+
+The above page, while not kept up to date, includes additional information regarding glslang as a reference validator.
+
+# How to Use Glslang
+
+## Execution of Standalone Wrapper
 
 To use the standalone binary form, execute `glslangValidator`, and it will print
 a usage statement.  Basic operation is to give it a file containing a shader,
@@ -46,8 +81,7 @@
 There is also a non-shader extension
 * `.conf` for a configuration file of limits, see usage statement for example
 
-Building
---------
+## Building
 
 Instead of building manually, you can also download the binaries for your
 platform directly from the [master-tot release][master-tot-release] on GitHub.
@@ -61,7 +95,7 @@
   (For MSVS: 2015 is recommended, 2013 is fully supported/tested, and 2010 support is attempted, but not tested.)
 * [CMake][cmake]: for generating compilation targets.
 * make: _Linux_, ninja is an alternative, if configured.
-* [Python 2.7][python]: for executing SPIRV-Tools scripts. (Optional if not using SPIRV-Tools.)
+* [Python 3.x][python]: for executing SPIRV-Tools scripts. (Optional if not using SPIRV-Tools and the 'External' subdirectory does not exist.)
 * [bison][bison]: _optional_, but needed when changing the grammar (glslang.y).
 * [googletest][googletest]: _optional_, but should use if making any changes to glslang.
 
@@ -70,7 +104,7 @@
 The following steps assume a Bash shell. On Windows, that could be the Git Bash
 shell or some other shell of your choosing.
 
-#### 1) Check-Out this project 
+#### 1) Check-Out this project
 
 ```bash
 cd <parent of where you want glslang to be>
@@ -94,8 +128,8 @@
 ```
 
 If you wish to assure that SPIR-V generated from HLSL is legal for Vulkan,
-or wish to invoke -Os to reduce SPIR-V size from HLSL or GLSL, install
-spirv-tools with this:
+wish to invoke -Os to reduce SPIR-V size from HLSL or GLSL, or wish to run the
+integrated test suite, install spirv-tools with this:
 
 ```bash
 ./update_glslang_sources.py
@@ -118,6 +152,14 @@
 # "Release" (for CMAKE_BUILD_TYPE) could also be "Debug" or "RelWithDebInfo"
 ```
 
+For building on Android:
+```bash
+cmake $SOURCE_DIR -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX="$(pwd)/install" -DANDROID_ABI=arm64-v8a -DCMAKE_BUILD_TYPE=Release -DANDROID_STL=c++_static -DANDROID_PLATFORM=android-24 -DCMAKE_SYSTEM_NAME=Android -DANDROID_TOOLCHAIN=clang -DANDROID_ARM_MODE=arm -DCMAKE_MAKE_PROGRAM=$ANDROID_NDK_ROOT/prebuilt/linux-x86_64/bin/make -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK_ROOT/build/cmake/android.toolchain.cmake
+# If on Windows will be -DCMAKE_MAKE_PROGRAM=%ANDROID_NDK_ROOT%\prebuilt\windows-x86_64\bin\make.exe
+# -G is needed for building on Windows
+# -DANDROID_ABI can also be armeabi-v7a for 32 bit
+```
+
 For building on Windows:
 
 ```bash
@@ -155,16 +197,57 @@
 The command to rebuild is:
 
 ```bash
+m4 -P MachineIndependent/glslang.m4 > MachineIndependent/glslang.y
 bison --defines=MachineIndependent/glslang_tab.cpp.h
       -t MachineIndependent/glslang.y
       -o MachineIndependent/glslang_tab.cpp
 ```
 
-The above command is also available in the bash script at
-`glslang/updateGrammar`.
+The above commands are also available in the bash script in `updateGrammar`,
+when executed from the glslang subdirectory of the glslang repository.
+With no arguments it builds the full grammar, and with a "web" argument,
+the web grammar subset (see more about the web subset in the next section).
 
-Testing
--------
+### Building to WASM for the Web and Node
+### Building a standalone JS/WASM library for the Web and Node
+
+Use the steps in [Build Steps](#build-steps), with the following notes/exceptions:
+* `emsdk` needs to be present in your executable search path, *PATH* for
+  Bash-like environments:
+  + [Instructions located here](https://emscripten.org/docs/getting_started/downloads.html#sdk-download-and-install)
+* Wrap cmake call: `emcmake cmake`
+* Set `-DBUILD_TESTING=OFF -DENABLE_OPT=OFF -DINSTALL_GTEST=OFF`.
+* Set `-DENABLE_HLSL=OFF` if HLSL is not needed.
+* For a standalone JS/WASM library, turn on `-DENABLE_GLSLANG_JS=ON`.
+* For building a minimum-size web subset of core glslang:
+  + turn on `-DENABLE_GLSLANG_WEBMIN=ON` (disables HLSL)
+  + execute `updateGrammar web` from the glslang subdirectory
+    (or if using your own scripts, `m4` needs a `-DGLSLANG_WEB` argument)
+  + optionally, for GLSL compilation error messages, turn on
+    `-DENABLE_GLSLANG_WEBMIN_DEVEL=ON`
+* To get a fully minimized build, make sure to use `brotli` to compress the .js
+  and .wasm files
+
+Example:
+
+```sh
+emcmake cmake -DCMAKE_BUILD_TYPE=Release -DENABLE_GLSLANG_JS=ON \
+    -DENABLE_HLSL=OFF -DBUILD_TESTING=OFF -DENABLE_OPT=OFF -DINSTALL_GTEST=OFF ..
+```
+
+## Building glslang - Using vcpkg
+
+You can download and install glslang using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager:
+
+    git clone https://github.com/Microsoft/vcpkg.git
+    cd vcpkg
+    ./bootstrap-vcpkg.sh
+    ./vcpkg integrate install
+    ./vcpkg install glslang
+
+The glslang port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
+
+## Testing
 
 Right now, there are two test harnesses existing in glslang: one is [Google
 Test](gtests/), one is the [`runtests` script](Test/runtests). The former
@@ -200,6 +283,11 @@
 cd $SOURCE_DIR/Test && ./runtests
 ```
 
+If some tests fail with validation errors, there may be a mismatch between the
+version of `spirv-val` on the system and the version of glslang.  In this
+case, it is necessary to run `update_glslang_sources.py`.  See "Check-Out
+External Projects" above for more details.
+
 ### Contributing tests
 
 Test results should always be included with a pull request that modifies
@@ -231,8 +319,7 @@
 `localtestlist` to list non-tracked tests.  This is automatically read
 by `runtests` and included in the `diff` and `bump` process.
 
-Programmatic Interfaces
------------------------
+## Programmatic Interfaces
 
 Another piece of software can programmatically translate shaders to an AST
 using one of two different interfaces:
@@ -244,7 +331,8 @@
 ### C++ Class Interface (new, preferred)
 
 This interface is in roughly the last 1/3 of `ShaderLang.h`.  It is in the
-glslang namespace and contains the following.
+glslang namespace and contains the following, here with suggested calls
+for generating SPIR-V:
 
 ```cxx
 const char* GetEsslVersionString();
@@ -267,16 +355,25 @@
     Reflection queries
 ```
 
-See `ShaderLang.h` and the usage of it in `StandAlone/StandAlone.cpp` for more
-details.
+For just validating (not generating code), substitute these calls:
 
-### C Functional Interface (orignal)
+```cxx
+    setEnvInput(EShSourceHlsl or EShSourceGlsl, stage,  EShClientNone, 0);
+    setEnvClient(EShClientNone, 0);
+    setEnvTarget(EShTargetNone, 0);
+```
+
+See `ShaderLang.h` and the usage of it in `StandAlone/StandAlone.cpp` for more
+details. There is a block comment giving more detail above the calls for
+`setEnvInput, setEnvClient, and setEnvTarget`.
+
+### C Functional Interface (original)
 
 This interface is in roughly the first 2/3 of `ShaderLang.h`, and referred to
 as the `Sh*()` interface, as all the entry points start `Sh`.
 
 The `Sh*()` interface takes a "compiler" call-back object, which it calls after
-building call back that is passed the AST and can then execute a backend on it.
+building call back that is passed the AST and can then execute a back end on it.
 
 The following is a simplified resulting run-time call stack:
 
@@ -287,8 +384,7 @@
 In practice, `ShCompile()` takes shader strings, default version, and
 warning/error and other options for controlling compilation.
 
-Basic Internal Operation
-------------------------
+## Basic Internal Operation
 
 * Initial lexical analysis is done by the preprocessor in
   `MachineIndependent/Preprocessor`, and then refined by a GLSL scanner
@@ -303,7 +399,7 @@
 * The intermediate representation is very high-level, and represented
   as an in-memory tree.   This serves to lose no information from the
   original program, and to have efficient transfer of the result from
-  parsing to the back-end.  In the AST, constants are propogated and
+  parsing to the back-end.  In the AST, constants are propagated and
   folded, and a very small amount of dead code is eliminated.
 
   To aid linking and reflection, the last top-level branch in the AST
@@ -335,6 +431,8 @@
   - the object does not come from the pool, and you have to do normal
     C++ memory management of what you `new`
 
+* Features can be protected by version/extension/stage/profile:
+  See the comment in `glslang/MachineIndependent/Versions.cpp`.
 
 [cmake]: https://cmake.org/
 [python]: https://www.python.org/
diff --git a/SPIRV/CMakeLists.txt b/SPIRV/CMakeLists.txt
index 1997e74..9040609 100644
--- a/SPIRV/CMakeLists.txt
+++ b/SPIRV/CMakeLists.txt
@@ -25,28 +25,21 @@
     spvIR.h
     doc.h
     SpvTools.h
-    disassemble.h)
+    disassemble.h
+    GLSL.ext.AMD.h
+    GLSL.ext.NV.h
+    NonSemanticDebugPrintf.h)
 
 set(SPVREMAP_HEADERS
     SPVRemapper.h
     doc.h)
 
-if(ENABLE_AMD_EXTENSIONS)
-    list(APPEND
-         HEADERS
-         GLSL.ext.AMD.h)
-endif(ENABLE_AMD_EXTENSIONS)
-
-if(ENABLE_NV_EXTENSIONS)
-    list(APPEND
-         HEADERS
-         GLSL.ext.NV.h)
-endif(ENABLE_NV_EXTENSIONS)
-
 add_library(SPIRV ${LIB_TYPE} ${SOURCES} ${HEADERS})
 set_property(TARGET SPIRV PROPERTY FOLDER glslang)
 set_property(TARGET SPIRV PROPERTY POSITION_INDEPENDENT_CODE ON)
-target_include_directories(SPIRV PUBLIC ..)
+target_include_directories(SPIRV PUBLIC
+	$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>
+	$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
 
 if (ENABLE_SPVREMAPPER)
     add_library(SPVRemapper ${LIB_TYPE} ${SPVREMAP_SOURCES} ${SPVREMAP_HEADERS})
@@ -67,7 +60,9 @@
         PRIVATE ${spirv-tools_SOURCE_DIR}/source
     )
     target_link_libraries(SPIRV glslang SPIRV-Tools-opt)
-    target_include_directories(SPIRV PUBLIC ../External)
+    target_include_directories(SPIRV PUBLIC
+		$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../External>
+		$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/External>)
 else()
     target_link_libraries(SPIRV glslang)
 endif(ENABLE_OPT)
@@ -80,21 +75,29 @@
 if(ENABLE_GLSLANG_INSTALL)
     if(BUILD_SHARED_LIBS)
         if (ENABLE_SPVREMAPPER)
-            install(TARGETS SPVRemapper
+            install(TARGETS SPVRemapper EXPORT SPVRemapperTargets
                     ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
                     LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
         endif()
-        install(TARGETS SPIRV
+        install(TARGETS SPIRV EXPORT SPIRVTargets
                 ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
-                LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
+                LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+                RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
     else()
         if (ENABLE_SPVREMAPPER)
-            install(TARGETS SPVRemapper
+            install(TARGETS SPVRemapper EXPORT SPVRemapperTargets
                     ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
         endif()
-        install(TARGETS SPIRV
+        install(TARGETS SPIRV EXPORT SPIRVTargets
                 ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
     endif()
 
+    if (ENABLE_SPVREMAPPER)
+        install(EXPORT SPVRemapperTargets DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake)
+    endif()
+
+    install(EXPORT SPIRVTargets DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake)
+
     install(FILES ${HEADERS} ${SPVREMAP_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/SPIRV/)
+    install(FILES ${HEADERS} ${SPVREMAP_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/glslang/SPIRV/)
 endif(ENABLE_GLSLANG_INSTALL)
diff --git a/SPIRV/GLSL.ext.EXT.h b/SPIRV/GLSL.ext.EXT.h
index e29c055..40164b6 100644
--- a/SPIRV/GLSL.ext.EXT.h
+++ b/SPIRV/GLSL.ext.EXT.h
@@ -34,5 +34,6 @@
 static const char* const E_SPV_EXT_shader_viewport_index_layer  = "SPV_EXT_shader_viewport_index_layer";
 static const char* const E_SPV_EXT_fragment_fully_covered = "SPV_EXT_fragment_fully_covered";
 static const char* const E_SPV_EXT_fragment_invocation_density = "SPV_EXT_fragment_invocation_density";
+static const char* const E_SPV_EXT_demote_to_helper_invocation = "SPV_EXT_demote_to_helper_invocation";
 
 #endif  // #ifndef GLSLextEXT_H
diff --git a/SPIRV/GLSL.ext.KHR.h b/SPIRV/GLSL.ext.KHR.h
index 333442b..d783a8f 100644
--- a/SPIRV/GLSL.ext.KHR.h
+++ b/SPIRV/GLSL.ext.KHR.h
@@ -1,5 +1,6 @@
 /*
-** Copyright (c) 2014-2016 The Khronos Group Inc.
+** Copyright (c) 2014-2020 The Khronos Group Inc.
+** Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 **
 ** Permission is hereby granted, free of charge, to any person obtaining a copy
 ** of this software and/or associated documentation files (the "Materials"),
@@ -41,5 +42,10 @@
 static const char* const E_SPV_KHR_post_depth_coverage          = "SPV_KHR_post_depth_coverage";
 static const char* const E_SPV_KHR_vulkan_memory_model          = "SPV_KHR_vulkan_memory_model";
 static const char* const E_SPV_EXT_physical_storage_buffer      = "SPV_EXT_physical_storage_buffer";
-
+static const char* const E_SPV_KHR_physical_storage_buffer      = "SPV_KHR_physical_storage_buffer";
+static const char* const E_SPV_EXT_fragment_shader_interlock    = "SPV_EXT_fragment_shader_interlock";
+static const char* const E_SPV_KHR_shader_clock                 = "SPV_KHR_shader_clock";
+static const char* const E_SPV_KHR_non_semantic_info            = "SPV_KHR_non_semantic_info";
+static const char* const E_SPV_KHR_ray_tracing                  = "SPV_KHR_ray_tracing";
+static const char* const E_SPV_KHR_ray_query                    = "SPV_KHR_ray_query";
 #endif  // #ifndef GLSLextKHR_H
diff --git a/SPIRV/GLSL.ext.NV.h b/SPIRV/GLSL.ext.NV.h
index ede2c57..50146da 100644
--- a/SPIRV/GLSL.ext.NV.h
+++ b/SPIRV/GLSL.ext.NV.h
@@ -75,4 +75,7 @@
 //SPV_NV_cooperative_matrix
 const char* const E_SPV_NV_cooperative_matrix = "SPV_NV_cooperative_matrix";
 
+//SPV_NV_shader_sm_builtins
+const char* const E_SPV_NV_shader_sm_builtins = "SPV_NV_shader_sm_builtins";
+
 #endif  // #ifndef GLSLextNV_H
diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp
index 25ef210..3bed678 100644
--- a/SPIRV/GlslangToSpv.cpp
+++ b/SPIRV/GlslangToSpv.cpp
@@ -1,7 +1,8 @@
 //
 // Copyright (C) 2014-2016 LunarG, Inc.
-// Copyright (C) 2015-2018 Google, Inc.
+// Copyright (C) 2015-2020 Google, Inc.
 // Copyright (C) 2017 ARM Limited.
+// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 //
 // All rights reserved.
 //
@@ -46,10 +47,9 @@
     #include "GLSL.std.450.h"
     #include "GLSL.ext.KHR.h"
     #include "GLSL.ext.EXT.h"
-#ifdef AMD_EXTENSIONS
     #include "GLSL.ext.AMD.h"
-#endif
     #include "GLSL.ext.NV.h"
+    #include "NonSemanticDebugPrintf.h"
 }
 
 // Glslang includes
@@ -89,9 +89,29 @@
 };
 
 struct OpDecorations {
+    public:
+        OpDecorations(spv::Decoration precision, spv::Decoration noContraction, spv::Decoration nonUniform) :
+            precision(precision)
+#ifndef GLSLANG_WEB
+            ,
+            noContraction(noContraction),
+            nonUniform(nonUniform)
+#endif
+        { }
+
     spv::Decoration precision;
-    spv::Decoration noContraction;
-    spv::Decoration nonUniform;
+
+#ifdef GLSLANG_WEB
+        void addNoContraction(spv::Builder&, spv::Id) const { }
+        void addNonUniform(spv::Builder&, spv::Id) const { }
+#else
+        void addNoContraction(spv::Builder& builder, spv::Id t) { builder.addDecoration(t, noContraction); }
+        void addNonUniform(spv::Builder& builder, spv::Id t)  { builder.addDecoration(t, nonUniform); }
+    protected:
+        spv::Decoration noContraction;
+        spv::Decoration nonUniform;
+#endif
+
 };
 
 } // namespace
@@ -135,10 +155,10 @@
     spv::ImageFormat TranslateImageFormat(const glslang::TType& type);
     spv::SelectionControlMask TranslateSelectionControl(const glslang::TIntermSelection&) const;
     spv::SelectionControlMask TranslateSwitchControl(const glslang::TIntermSwitch&) const;
-    spv::LoopControlMask TranslateLoopControl(const glslang::TIntermLoop&, unsigned int& dependencyLength) const;
+    spv::LoopControlMask TranslateLoopControl(const glslang::TIntermLoop&, std::vector<unsigned int>& operands) const;
     spv::StorageClass TranslateStorageClass(const glslang::TType&);
     void addIndirectionIndexCapabilities(const glslang::TType& baseType, const glslang::TType& indexType);
-    spv::Id createSpvVariable(const glslang::TIntermSymbol*);
+    spv::Id createSpvVariable(const glslang::TIntermSymbol*, spv::Id forcedType);
     spv::Id getSampledType(const glslang::TSampler&);
     spv::Id getInvertedSwizzleType(const glslang::TIntermTyped&);
     spv::Id createInvertedSwizzle(spv::Decoration precision, const glslang::TIntermTyped&, spv::Id parentResult);
@@ -169,7 +189,8 @@
     void makeGlobalInitializers(const glslang::TIntermSequence&);
     void visitFunctions(const glslang::TIntermSequence&);
     void handleFunctionEntry(const glslang::TIntermAggregate* node);
-    void translateArguments(const glslang::TIntermAggregate& node, std::vector<spv::Id>& arguments);
+    void translateArguments(const glslang::TIntermAggregate& node, std::vector<spv::Id>& arguments,
+        spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags);
     void translateArguments(glslang::TIntermUnary& node, std::vector<spv::Id>& arguments);
     spv::Id createImageTextureFunctionCall(glslang::TIntermOperator* node);
     spv::Id handleUserFunctionCall(const glslang::TIntermAggregate*);
@@ -178,36 +199,38 @@
                                   glslang::TBasicType typeProxy, bool reduceComparison = true);
     spv::Id createBinaryMatrixOperation(spv::Op, OpDecorations&, spv::Id typeId, spv::Id left, spv::Id right);
     spv::Id createUnaryOperation(glslang::TOperator op, OpDecorations&, spv::Id typeId, spv::Id operand,
-                                 glslang::TBasicType typeProxy);
+                                 glslang::TBasicType typeProxy,
+                                 const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags);
     spv::Id createUnaryMatrixOperation(spv::Op op, OpDecorations&, spv::Id typeId, spv::Id operand,
                                        glslang::TBasicType typeProxy);
     spv::Id createConversion(glslang::TOperator op, OpDecorations&, spv::Id destTypeId, spv::Id operand,
                              glslang::TBasicType typeProxy);
     spv::Id createIntWidthConversion(glslang::TOperator op, spv::Id operand, int vectorSize);
     spv::Id makeSmearedConstant(spv::Id constant, int vectorSize);
-    spv::Id createAtomicOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy);
-    spv::Id createInvocationsOperation(glslang::TOperator op, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy);
-    spv::Id CreateInvocationsVectorOperation(spv::Op op, spv::GroupOperation groupOperation, spv::Id typeId, std::vector<spv::Id>& operands);
-    spv::Id createSubgroupOperation(glslang::TOperator op, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy);
-    spv::Id createMiscOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy);
+    spv::Id createAtomicOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId,
+        std::vector<spv::Id>& operands, glslang::TBasicType typeProxy,
+        const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags);
+    spv::Id createInvocationsOperation(glslang::TOperator op, spv::Id typeId, std::vector<spv::Id>& operands,
+        glslang::TBasicType typeProxy);
+    spv::Id CreateInvocationsVectorOperation(spv::Op op, spv::GroupOperation groupOperation,
+        spv::Id typeId, std::vector<spv::Id>& operands);
+    spv::Id createSubgroupOperation(glslang::TOperator op, spv::Id typeId, std::vector<spv::Id>& operands,
+        glslang::TBasicType typeProxy);
+    spv::Id createMiscOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId,
+        std::vector<spv::Id>& operands, glslang::TBasicType typeProxy);
     spv::Id createNoArgOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId);
     spv::Id getSymbolId(const glslang::TIntermSymbol* node);
-#ifdef NV_EXTENSIONS
     void addMeshNVDecoration(spv::Id id, int member, const glslang::TQualifier & qualifier);
-#endif
     spv::Id createSpvConstant(const glslang::TIntermTyped&);
-    spv::Id createSpvConstantFromConstUnionArray(const glslang::TType& type, const glslang::TConstUnionArray&, int& nextConst, bool specConstant);
+    spv::Id createSpvConstantFromConstUnionArray(const glslang::TType& type, const glslang::TConstUnionArray&,
+        int& nextConst, bool specConstant);
     bool isTrivialLeaf(const glslang::TIntermTyped* node);
     bool isTrivial(const glslang::TIntermTyped* node);
     spv::Id createShortCircuit(glslang::TOperator, glslang::TIntermTyped& left, glslang::TIntermTyped& right);
-#ifdef AMD_EXTENSIONS
     spv::Id getExtBuiltins(const char* name);
-#endif
-    void addPre13Extension(const char* ext)
-    {
-        if (builder.getSpvVersion() < glslang::EShTargetSpv_1_3)
-            builder.addExtension(ext);
-    }
+    std::pair<spv::Id, spv::Id> getForcedType(glslang::TBuiltInVariable builtIn, const glslang::TType&);
+    spv::Id translateForcedType(spv::Id object);
+    spv::Id createCompositeConstruct(spv::Id typeId, std::vector<spv::Id> constituents);
 
     glslang::SpvOptions& options;
     spv::Function* shaderEntry;
@@ -221,22 +244,32 @@
     spv::Builder builder;
     bool inEntryPoint;
     bool entryPointTerminated;
-    bool linkageOnly;                  // true when visiting the set of objects in the AST present only for establishing interface, whether or not they were statically used
+    bool linkageOnly;                  // true when visiting the set of objects in the AST present only for
+                                       // establishing interface, whether or not they were statically used
     std::set<spv::Id> iOSet;           // all input/output variables from either static use or declaration of interface
     const glslang::TIntermediate* glslangIntermediate;
+    bool nanMinMaxClamp;               // true if use NMin/NMax/NClamp instead of FMin/FMax/FClamp
     spv::Id stdBuiltins;
+    spv::Id nonSemanticDebugPrintf;
     std::unordered_map<const char*, spv::Id> extBuiltinMap;
 
     std::unordered_map<int, spv::Id> symbolValues;
-    std::unordered_set<int> rValueParameters;  // set of formal function parameters passed as rValues, rather than a pointer
+    std::unordered_set<int> rValueParameters;  // set of formal function parameters passed as rValues,
+                                               // rather than a pointer
     std::unordered_map<std::string, spv::Function*> functionMap;
     std::unordered_map<const glslang::TTypeList*, spv::Id> structMap[glslang::ElpCount][glslang::ElmCount];
     // for mapping glslang block indices to spv indices (e.g., due to hidden members):
-    std::unordered_map<const glslang::TTypeList*, std::vector<int> > memberRemapper;
+    std::unordered_map<int, std::vector<int>> memberRemapper;
+    // for mapping glslang symbol struct to symbol Id
+    std::unordered_map<const glslang::TTypeList*, int> glslangTypeToIdMap;
     std::stack<bool> breakForLoop;  // false means break for switch
     std::unordered_map<std::string, const glslang::TIntermSymbol*> counterOriginator;
     // Map pointee types for EbtReference to their forward pointers
     std::map<const glslang::TType *, spv::Id> forwardPointers;
+    // Type forcing, for when SPIR-V wants a different type than the AST,
+    // requiring local translation to and from SPIR-V type on every access.
+    // Maps <builtin-variable-id -> AST-required-type-id>
+    std::unordered_map<spv::Id, spv::Id> forceType;
 };
 
 //
@@ -246,6 +279,10 @@
 // Translate glslang profile to SPIR-V source language.
 spv::SourceLanguage TranslateSourceLanguage(glslang::EShSource source, EProfile profile)
 {
+#ifdef GLSLANG_WEB
+    return spv::SourceLanguageESSL;
+#endif
+
     switch (source) {
     case glslang::EShSourceGlsl:
         switch (profile) {
@@ -270,18 +307,18 @@
 {
     switch (stage) {
     case EShLangVertex:           return spv::ExecutionModelVertex;
+    case EShLangFragment:         return spv::ExecutionModelFragment;
+    case EShLangCompute:          return spv::ExecutionModelGLCompute;
+#ifndef GLSLANG_WEB
     case EShLangTessControl:      return spv::ExecutionModelTessellationControl;
     case EShLangTessEvaluation:   return spv::ExecutionModelTessellationEvaluation;
     case EShLangGeometry:         return spv::ExecutionModelGeometry;
-    case EShLangFragment:         return spv::ExecutionModelFragment;
-    case EShLangCompute:          return spv::ExecutionModelGLCompute;
-#ifdef NV_EXTENSIONS
-    case EShLangRayGenNV:         return spv::ExecutionModelRayGenerationNV;
-    case EShLangIntersectNV:      return spv::ExecutionModelIntersectionNV;
-    case EShLangAnyHitNV:         return spv::ExecutionModelAnyHitNV;
-    case EShLangClosestHitNV:     return spv::ExecutionModelClosestHitNV;
-    case EShLangMissNV:           return spv::ExecutionModelMissNV;
-    case EShLangCallableNV:       return spv::ExecutionModelCallableNV;
+    case EShLangRayGen:           return spv::ExecutionModelRayGenerationKHR;
+    case EShLangIntersect:        return spv::ExecutionModelIntersectionKHR;
+    case EShLangAnyHit:           return spv::ExecutionModelAnyHitKHR;
+    case EShLangClosestHit:       return spv::ExecutionModelClosestHitKHR;
+    case EShLangMiss:             return spv::ExecutionModelMissKHR;
+    case EShLangCallable:         return spv::ExecutionModelCallableKHR;
     case EShLangTaskNV:           return spv::ExecutionModelTaskNV;
     case EShLangMeshNV:           return spv::ExecutionModelMeshNV;
 #endif
@@ -334,12 +371,12 @@
         case glslang::EvqBuffer:       return useStorageBuffer ? spv::DecorationBlock : spv::DecorationBufferBlock;
         case glslang::EvqVaryingIn:    return spv::DecorationBlock;
         case glslang::EvqVaryingOut:   return spv::DecorationBlock;
-#ifdef NV_EXTENSIONS
-        case glslang::EvqPayloadNV:    return spv::DecorationBlock;
-        case glslang::EvqPayloadInNV:  return spv::DecorationBlock;
-        case glslang::EvqHitAttrNV:    return spv::DecorationBlock;
-        case glslang::EvqCallableDataNV:   return spv::DecorationBlock;
-        case glslang::EvqCallableDataInNV: return spv::DecorationBlock;
+#ifndef GLSLANG_WEB
+        case glslang::EvqPayload:      return spv::DecorationBlock;
+        case glslang::EvqPayloadIn:    return spv::DecorationBlock;
+        case glslang::EvqHitAttr:      return spv::DecorationBlock;
+        case glslang::EvqCallableData:   return spv::DecorationBlock;
+        case glslang::EvqCallableDataIn: return spv::DecorationBlock;
 #endif
         default:
             assert(0);
@@ -351,21 +388,22 @@
 }
 
 // Translate glslang type to SPIR-V memory decorations.
-void TranslateMemoryDecoration(const glslang::TQualifier& qualifier, std::vector<spv::Decoration>& memory, bool useVulkanMemoryModel)
+void TranslateMemoryDecoration(const glslang::TQualifier& qualifier, std::vector<spv::Decoration>& memory,
+    bool useVulkanMemoryModel)
 {
     if (!useVulkanMemoryModel) {
-        if (qualifier.coherent)
+        if (qualifier.isCoherent())
             memory.push_back(spv::DecorationCoherent);
-        if (qualifier.volatil) {
+        if (qualifier.isVolatile()) {
             memory.push_back(spv::DecorationVolatile);
             memory.push_back(spv::DecorationCoherent);
         }
     }
-    if (qualifier.restrict)
+    if (qualifier.isRestrict())
         memory.push_back(spv::DecorationRestrict);
-    if (qualifier.readonly)
+    if (qualifier.isReadOnly())
         memory.push_back(spv::DecorationNonWritable);
-    if (qualifier.writeonly)
+    if (qualifier.isWriteOnly())
        memory.push_back(spv::DecorationNonReadable);
 }
 
@@ -409,12 +447,12 @@
                     assert(type.getQualifier().layoutPacking == glslang::ElpNone);
                 }
                 return spv::DecorationMax;
-#ifdef NV_EXTENSIONS
-            case glslang::EvqPayloadNV:
-            case glslang::EvqPayloadInNV:
-            case glslang::EvqHitAttrNV:
-            case glslang::EvqCallableDataNV:
-            case glslang::EvqCallableDataInNV:
+#ifndef GLSLANG_WEB
+            case glslang::EvqPayload:
+            case glslang::EvqPayloadIn:
+            case glslang::EvqHitAttr:
+            case glslang::EvqCallableData:
+            case glslang::EvqCallableDataIn:
                 return spv::DecorationMax;
 #endif
             default:
@@ -433,16 +471,14 @@
     if (qualifier.smooth)
         // Smooth decoration doesn't exist in SPIR-V 1.0
         return spv::DecorationMax;
-    else if (qualifier.nopersp)
+    else if (qualifier.isNonPerspective())
         return spv::DecorationNoPerspective;
     else if (qualifier.flat)
         return spv::DecorationFlat;
-#ifdef AMD_EXTENSIONS
-    else if (qualifier.explicitInterp) {
+    else if (qualifier.isExplicitInterpolation()) {
         builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter);
         return spv::DecorationExplicitInterpAMD;
     }
-#endif
     else
         return spv::DecorationMax;
 }
@@ -452,15 +488,18 @@
 // should be applied.
 spv::Decoration TGlslangToSpvTraverser::TranslateAuxiliaryStorageDecoration(const glslang::TQualifier& qualifier)
 {
-    if (qualifier.patch)
-        return spv::DecorationPatch;
-    else if (qualifier.centroid)
+    if (qualifier.centroid)
         return spv::DecorationCentroid;
+#ifndef GLSLANG_WEB
+    else if (qualifier.patch)
+        return spv::DecorationPatch;
     else if (qualifier.sample) {
         builder.addCapability(spv::CapabilitySampleRateShading);
         return spv::DecorationSample;
-    } else
-        return spv::DecorationMax;
+    }
+#endif
+
+    return spv::DecorationMax;
 }
 
 // If glslang type is invariant, return SPIR-V invariant decoration.
@@ -475,38 +514,41 @@
 // If glslang type is noContraction, return SPIR-V NoContraction decoration.
 spv::Decoration TranslateNoContractionDecoration(const glslang::TQualifier& qualifier)
 {
-    if (qualifier.noContraction)
+#ifndef GLSLANG_WEB
+    if (qualifier.isNoContraction())
         return spv::DecorationNoContraction;
     else
+#endif
         return spv::DecorationMax;
 }
 
 // If glslang type is nonUniform, return SPIR-V NonUniform decoration.
 spv::Decoration TGlslangToSpvTraverser::TranslateNonUniformDecoration(const glslang::TQualifier& qualifier)
 {
+#ifndef GLSLANG_WEB
     if (qualifier.isNonUniform()) {
-        builder.addExtension("SPV_EXT_descriptor_indexing");
+        builder.addIncorporatedExtension("SPV_EXT_descriptor_indexing", spv::Spv_1_5);
         builder.addCapability(spv::CapabilityShaderNonUniformEXT);
         return spv::DecorationNonUniformEXT;
     } else
+#endif
         return spv::DecorationMax;
 }
 
-spv::MemoryAccessMask TGlslangToSpvTraverser::TranslateMemoryAccess(const spv::Builder::AccessChain::CoherentFlags &coherentFlags)
+spv::MemoryAccessMask TGlslangToSpvTraverser::TranslateMemoryAccess(
+    const spv::Builder::AccessChain::CoherentFlags &coherentFlags)
 {
-    if (!glslangIntermediate->usingVulkanMemoryModel() || coherentFlags.isImage) {
-        return spv::MemoryAccessMaskNone;
-    }
     spv::MemoryAccessMask mask = spv::MemoryAccessMaskNone;
-    if (coherentFlags.volatil ||
-        coherentFlags.coherent ||
-        coherentFlags.devicecoherent ||
-        coherentFlags.queuefamilycoherent ||
-        coherentFlags.workgroupcoherent ||
-        coherentFlags.subgroupcoherent) {
+
+#ifndef GLSLANG_WEB
+    if (!glslangIntermediate->usingVulkanMemoryModel() || coherentFlags.isImage)
+        return mask;
+
+    if (coherentFlags.isVolatile() || coherentFlags.anyCoherent()) {
         mask = mask | spv::MemoryAccessMakePointerAvailableKHRMask |
                       spv::MemoryAccessMakePointerVisibleKHRMask;
     }
+
     if (coherentFlags.nonprivate) {
         mask = mask | spv::MemoryAccessNonPrivatePointerKHRMask;
     }
@@ -516,21 +558,22 @@
     if (mask != spv::MemoryAccessMaskNone) {
         builder.addCapability(spv::CapabilityVulkanMemoryModelKHR);
     }
+#endif
+
     return mask;
 }
 
-spv::ImageOperandsMask TGlslangToSpvTraverser::TranslateImageOperands(const spv::Builder::AccessChain::CoherentFlags &coherentFlags)
+spv::ImageOperandsMask TGlslangToSpvTraverser::TranslateImageOperands(
+    const spv::Builder::AccessChain::CoherentFlags &coherentFlags)
 {
-    if (!glslangIntermediate->usingVulkanMemoryModel()) {
-        return spv::ImageOperandsMaskNone;
-    }
     spv::ImageOperandsMask mask = spv::ImageOperandsMaskNone;
+
+#ifndef GLSLANG_WEB
+    if (!glslangIntermediate->usingVulkanMemoryModel())
+        return mask;
+
     if (coherentFlags.volatil ||
-        coherentFlags.coherent ||
-        coherentFlags.devicecoherent ||
-        coherentFlags.queuefamilycoherent ||
-        coherentFlags.workgroupcoherent ||
-        coherentFlags.subgroupcoherent) {
+        coherentFlags.anyCoherent()) {
         mask = mask | spv::ImageOperandsMakeTexelAvailableKHRMask |
                       spv::ImageOperandsMakeTexelVisibleKHRMask;
     }
@@ -543,12 +586,15 @@
     if (mask != spv::ImageOperandsMaskNone) {
         builder.addCapability(spv::CapabilityVulkanMemoryModelKHR);
     }
+#endif
+
     return mask;
 }
 
 spv::Builder::AccessChain::CoherentFlags TGlslangToSpvTraverser::TranslateCoherent(const glslang::TType& type)
 {
-    spv::Builder::AccessChain::CoherentFlags flags;
+    spv::Builder::AccessChain::CoherentFlags flags = {};
+#ifndef GLSLANG_WEB
     flags.coherent = type.getQualifier().coherent;
     flags.devicecoherent = type.getQualifier().devicecoherent;
     flags.queuefamilycoherent = type.getQualifier().queuefamilycoherent;
@@ -556,22 +602,23 @@
     flags.workgroupcoherent = type.getQualifier().workgroupcoherent ||
                               type.getQualifier().storage == glslang::EvqShared;
     flags.subgroupcoherent = type.getQualifier().subgroupcoherent;
+    flags.shadercallcoherent = type.getQualifier().shadercallcoherent;
     flags.volatil = type.getQualifier().volatil;
     // *coherent variables are implicitly nonprivate in GLSL
     flags.nonprivate = type.getQualifier().nonprivate ||
-                       flags.subgroupcoherent ||
-                       flags.workgroupcoherent ||
-                       flags.queuefamilycoherent ||
-                       flags.devicecoherent ||
-                       flags.coherent ||
+                       flags.anyCoherent() ||
                        flags.volatil;
     flags.isImage = type.getBasicType() == glslang::EbtSampler;
+#endif
     return flags;
 }
 
-spv::Scope TGlslangToSpvTraverser::TranslateMemoryScope(const spv::Builder::AccessChain::CoherentFlags &coherentFlags)
+spv::Scope TGlslangToSpvTraverser::TranslateMemoryScope(
+    const spv::Builder::AccessChain::CoherentFlags &coherentFlags)
 {
-    spv::Scope scope;
+    spv::Scope scope = spv::ScopeMax;
+
+#ifndef GLSLANG_WEB
     if (coherentFlags.volatil || coherentFlags.coherent) {
         // coherent defaults to Device scope in the old model, QueueFamilyKHR scope in the new model
         scope = glslangIntermediate->usingVulkanMemoryModel() ? spv::ScopeQueueFamilyKHR : spv::ScopeDevice;
@@ -583,12 +630,14 @@
         scope = spv::ScopeWorkgroup;
     } else if (coherentFlags.subgroupcoherent) {
         scope = spv::ScopeSubgroup;
-    } else {
-        scope = spv::ScopeMax;
+    } else if (coherentFlags.shadercallcoherent) {
+        scope = spv::ScopeShaderCallKHR;
     }
     if (glslangIntermediate->usingVulkanMemoryModel() && scope == spv::ScopeDevice) {
         builder.addCapability(spv::CapabilityVulkanMemoryModelDeviceScopeKHR);
     }
+#endif
+
     return scope;
 }
 
@@ -597,10 +646,12 @@
 // is generated only when using the variable in an executable instruction, but not when
 // just declaring a struct member variable with it.  This is true for PointSize,
 // ClipDistance, and CullDistance.
-spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltInVariable builtIn, bool memberDeclaration)
+spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltInVariable builtIn,
+    bool memberDeclaration)
 {
     switch (builtIn) {
     case glslang::EbvPointSize:
+#ifndef GLSLANG_WEB
         // Defer adding the capability until the built-in is actually used.
         if (! memberDeclaration) {
             switch (glslangIntermediate->getStage()) {
@@ -615,8 +666,28 @@
                 break;
             }
         }
+#endif
         return spv::BuiltInPointSize;
 
+    case glslang::EbvPosition:             return spv::BuiltInPosition;
+    case glslang::EbvVertexId:             return spv::BuiltInVertexId;
+    case glslang::EbvInstanceId:           return spv::BuiltInInstanceId;
+    case glslang::EbvVertexIndex:          return spv::BuiltInVertexIndex;
+    case glslang::EbvInstanceIndex:        return spv::BuiltInInstanceIndex;
+
+    case glslang::EbvFragCoord:            return spv::BuiltInFragCoord;
+    case glslang::EbvPointCoord:           return spv::BuiltInPointCoord;
+    case glslang::EbvFace:                 return spv::BuiltInFrontFacing;
+    case glslang::EbvFragDepth:            return spv::BuiltInFragDepth;
+
+    case glslang::EbvNumWorkGroups:        return spv::BuiltInNumWorkgroups;
+    case glslang::EbvWorkGroupSize:        return spv::BuiltInWorkgroupSize;
+    case glslang::EbvWorkGroupId:          return spv::BuiltInWorkgroupId;
+    case glslang::EbvLocalInvocationId:    return spv::BuiltInLocalInvocationId;
+    case glslang::EbvLocalInvocationIndex: return spv::BuiltInLocalInvocationIndex;
+    case glslang::EbvGlobalInvocationId:   return spv::BuiltInGlobalInvocationId;
+
+#ifndef GLSLANG_WEB
     // These *Distance capabilities logically belong here, but if the member is declared and
     // then never used, consumers of SPIR-V prefer the capability not be declared.
     // They are now generated when used, rather than here when declared.
@@ -639,7 +710,7 @@
             glslangIntermediate->getStage() == EShLangTessControl ||
             glslangIntermediate->getStage() == EShLangTessEvaluation) {
 
-            builder.addExtension(spv::E_SPV_EXT_shader_viewport_index_layer);
+            builder.addIncorporatedExtension(spv::E_SPV_EXT_shader_viewport_index_layer, spv::Spv_1_5);
             builder.addCapability(spv::CapabilityShaderViewportIndexLayerEXT);
         }
         return spv::BuiltInViewportIndex;
@@ -656,39 +727,31 @@
         return spv::BuiltInSampleMask;
 
     case glslang::EbvLayer:
-#ifdef NV_EXTENSIONS
         if (glslangIntermediate->getStage() == EShLangMeshNV) {
             return spv::BuiltInLayer;
         }
-#endif
         builder.addCapability(spv::CapabilityGeometry);
         if (glslangIntermediate->getStage() == EShLangVertex ||
             glslangIntermediate->getStage() == EShLangTessControl ||
             glslangIntermediate->getStage() == EShLangTessEvaluation) {
 
-            builder.addExtension(spv::E_SPV_EXT_shader_viewport_index_layer);
+            builder.addIncorporatedExtension(spv::E_SPV_EXT_shader_viewport_index_layer, spv::Spv_1_5);
             builder.addCapability(spv::CapabilityShaderViewportIndexLayerEXT);
         }
         return spv::BuiltInLayer;
 
-    case glslang::EbvPosition:             return spv::BuiltInPosition;
-    case glslang::EbvVertexId:             return spv::BuiltInVertexId;
-    case glslang::EbvInstanceId:           return spv::BuiltInInstanceId;
-    case glslang::EbvVertexIndex:          return spv::BuiltInVertexIndex;
-    case glslang::EbvInstanceIndex:        return spv::BuiltInInstanceIndex;
-
     case glslang::EbvBaseVertex:
-        addPre13Extension(spv::E_SPV_KHR_shader_draw_parameters);
+        builder.addIncorporatedExtension(spv::E_SPV_KHR_shader_draw_parameters, spv::Spv_1_3);
         builder.addCapability(spv::CapabilityDrawParameters);
         return spv::BuiltInBaseVertex;
 
     case glslang::EbvBaseInstance:
-        addPre13Extension(spv::E_SPV_KHR_shader_draw_parameters);
+        builder.addIncorporatedExtension(spv::E_SPV_KHR_shader_draw_parameters, spv::Spv_1_3);
         builder.addCapability(spv::CapabilityDrawParameters);
         return spv::BuiltInBaseInstance;
 
     case glslang::EbvDrawId:
-        addPre13Extension(spv::E_SPV_KHR_shader_draw_parameters);
+        builder.addIncorporatedExtension(spv::E_SPV_KHR_shader_draw_parameters, spv::Spv_1_3);
         builder.addCapability(spv::CapabilityDrawParameters);
         return spv::BuiltInDrawIndex;
 
@@ -707,17 +770,7 @@
     case glslang::EbvTessLevelOuter:       return spv::BuiltInTessLevelOuter;
     case glslang::EbvTessCoord:            return spv::BuiltInTessCoord;
     case glslang::EbvPatchVertices:        return spv::BuiltInPatchVertices;
-    case glslang::EbvFragCoord:            return spv::BuiltInFragCoord;
-    case glslang::EbvPointCoord:           return spv::BuiltInPointCoord;
-    case glslang::EbvFace:                 return spv::BuiltInFrontFacing;
-    case glslang::EbvFragDepth:            return spv::BuiltInFragDepth;
     case glslang::EbvHelperInvocation:     return spv::BuiltInHelperInvocation;
-    case glslang::EbvNumWorkGroups:        return spv::BuiltInNumWorkgroups;
-    case glslang::EbvWorkGroupSize:        return spv::BuiltInWorkgroupSize;
-    case glslang::EbvWorkGroupId:          return spv::BuiltInWorkgroupId;
-    case glslang::EbvLocalInvocationId:    return spv::BuiltInLocalInvocationId;
-    case glslang::EbvLocalInvocationIndex: return spv::BuiltInLocalInvocationIndex;
-    case glslang::EbvGlobalInvocationId:   return spv::BuiltInGlobalInvocationId;
 
     case glslang::EbvSubGroupSize:
         builder.addExtension(spv::E_SPV_KHR_shader_ballot);
@@ -732,27 +785,27 @@
     case glslang::EbvSubGroupEqMask:
         builder.addExtension(spv::E_SPV_KHR_shader_ballot);
         builder.addCapability(spv::CapabilitySubgroupBallotKHR);
-        return spv::BuiltInSubgroupEqMaskKHR;
+        return spv::BuiltInSubgroupEqMask;
 
     case glslang::EbvSubGroupGeMask:
         builder.addExtension(spv::E_SPV_KHR_shader_ballot);
         builder.addCapability(spv::CapabilitySubgroupBallotKHR);
-        return spv::BuiltInSubgroupGeMaskKHR;
+        return spv::BuiltInSubgroupGeMask;
 
     case glslang::EbvSubGroupGtMask:
         builder.addExtension(spv::E_SPV_KHR_shader_ballot);
         builder.addCapability(spv::CapabilitySubgroupBallotKHR);
-        return spv::BuiltInSubgroupGtMaskKHR;
+        return spv::BuiltInSubgroupGtMask;
 
     case glslang::EbvSubGroupLeMask:
         builder.addExtension(spv::E_SPV_KHR_shader_ballot);
         builder.addCapability(spv::CapabilitySubgroupBallotKHR);
-        return spv::BuiltInSubgroupLeMaskKHR;
+        return spv::BuiltInSubgroupLeMask;
 
     case glslang::EbvSubGroupLtMask:
         builder.addExtension(spv::E_SPV_KHR_shader_ballot);
         builder.addCapability(spv::CapabilitySubgroupBallotKHR);
-        return spv::BuiltInSubgroupLtMaskKHR;
+        return spv::BuiltInSubgroupLtMask;
 
     case glslang::EbvNumSubgroups:
         builder.addCapability(spv::CapabilityGroupNonUniform);
@@ -794,7 +847,7 @@
         builder.addCapability(spv::CapabilityGroupNonUniform);
         builder.addCapability(spv::CapabilityGroupNonUniformBallot);
         return spv::BuiltInSubgroupLtMask;
-#ifdef AMD_EXTENSIONS
+
     case glslang::EbvBaryCoordNoPersp:
         builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter);
         return spv::BuiltInBaryCoordNoPerspAMD;
@@ -822,15 +875,14 @@
     case glslang::EbvBaryCoordPullModel:
         builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter);
         return spv::BuiltInBaryCoordPullModelAMD;
-#endif
 
     case glslang::EbvDeviceIndex:
-        addPre13Extension(spv::E_SPV_KHR_device_group);
+        builder.addIncorporatedExtension(spv::E_SPV_KHR_device_group, spv::Spv_1_3);
         builder.addCapability(spv::CapabilityDeviceGroup);
         return spv::BuiltInDeviceIndex;
 
     case glslang::EbvViewIndex:
-        addPre13Extension(spv::E_SPV_KHR_multiview);
+        builder.addIncorporatedExtension(spv::E_SPV_KHR_multiview, spv::Spv_1_3);
         builder.addCapability(spv::CapabilityMultiView);
         return spv::BuiltInViewIndex;
 
@@ -844,7 +896,6 @@
         builder.addCapability(spv::CapabilityFragmentDensityEXT);
         return spv::BuiltInFragInvocationCountEXT;
 
-#ifdef NV_EXTENSIONS
     case glslang::EbvViewportMaskNV:
         if (!memberDeclaration) {
             builder.addExtension(spv::E_SPV_NV_viewport_array2);
@@ -888,35 +939,41 @@
         builder.addCapability(spv::CapabilityShadingRateNV);
         return spv::BuiltInInvocationsPerPixelNV;
 
-    // raytracing
-    case glslang::EbvLaunchIdNV:
-        return spv::BuiltInLaunchIdNV;
-    case glslang::EbvLaunchSizeNV:
-        return spv::BuiltInLaunchSizeNV;
-    case glslang::EbvWorldRayOriginNV:
-        return spv::BuiltInWorldRayOriginNV;
-    case glslang::EbvWorldRayDirectionNV:
-        return spv::BuiltInWorldRayDirectionNV;
-    case glslang::EbvObjectRayOriginNV:
-        return spv::BuiltInObjectRayOriginNV;
-    case glslang::EbvObjectRayDirectionNV:
-        return spv::BuiltInObjectRayDirectionNV;
-    case glslang::EbvRayTminNV:
-        return spv::BuiltInRayTminNV;
-    case glslang::EbvRayTmaxNV:
-        return spv::BuiltInRayTmaxNV;
-    case glslang::EbvInstanceCustomIndexNV:
-        return spv::BuiltInInstanceCustomIndexNV;
-    case glslang::EbvHitTNV:
-        return spv::BuiltInHitTNV;
-    case glslang::EbvHitKindNV:
-        return spv::BuiltInHitKindNV;
-    case glslang::EbvObjectToWorldNV:
-        return spv::BuiltInObjectToWorldNV;
-    case glslang::EbvWorldToObjectNV:
-        return spv::BuiltInWorldToObjectNV;
-    case glslang::EbvIncomingRayFlagsNV:
-        return spv::BuiltInIncomingRayFlagsNV;
+    // ray tracing
+    case glslang::EbvLaunchId:
+        return spv::BuiltInLaunchIdKHR;
+    case glslang::EbvLaunchSize:
+        return spv::BuiltInLaunchSizeKHR;
+    case glslang::EbvWorldRayOrigin:
+        return spv::BuiltInWorldRayOriginKHR;
+    case glslang::EbvWorldRayDirection:
+        return spv::BuiltInWorldRayDirectionKHR;
+    case glslang::EbvObjectRayOrigin:
+        return spv::BuiltInObjectRayOriginKHR;
+    case glslang::EbvObjectRayDirection:
+        return spv::BuiltInObjectRayDirectionKHR;
+    case glslang::EbvRayTmin:
+        return spv::BuiltInRayTminKHR;
+    case glslang::EbvRayTmax:
+        return spv::BuiltInRayTmaxKHR;
+    case glslang::EbvInstanceCustomIndex:
+        return spv::BuiltInInstanceCustomIndexKHR;
+    case glslang::EbvHitT:
+        return spv::BuiltInHitTKHR;
+    case glslang::EbvHitKind:
+        return spv::BuiltInHitKindKHR;
+    case glslang::EbvObjectToWorld:
+    case glslang::EbvObjectToWorld3x4:
+        return spv::BuiltInObjectToWorldKHR;
+    case glslang::EbvWorldToObject:
+    case glslang::EbvWorldToObject3x4:
+        return spv::BuiltInWorldToObjectKHR;
+    case glslang::EbvIncomingRayFlags:
+        return spv::BuiltInIncomingRayFlagsKHR;
+    case glslang::EbvGeometryIndex:
+        return spv::BuiltInRayGeometryIndexKHR;
+
+    // barycentrics
     case glslang::EbvBaryCoordNV:
         builder.addExtension(spv::E_SPV_NV_fragment_shader_barycentric);
         builder.addCapability(spv::CapabilityFragmentBarycentricNV);
@@ -925,23 +982,44 @@
         builder.addExtension(spv::E_SPV_NV_fragment_shader_barycentric);
         builder.addCapability(spv::CapabilityFragmentBarycentricNV);
         return spv::BuiltInBaryCoordNoPerspNV;
-     case glslang::EbvTaskCountNV:
+
+    // mesh shaders
+    case glslang::EbvTaskCountNV:
         return spv::BuiltInTaskCountNV;
-     case glslang::EbvPrimitiveCountNV:
+    case glslang::EbvPrimitiveCountNV:
         return spv::BuiltInPrimitiveCountNV;
-     case glslang::EbvPrimitiveIndicesNV:
+    case glslang::EbvPrimitiveIndicesNV:
         return spv::BuiltInPrimitiveIndicesNV;
-     case glslang::EbvClipDistancePerViewNV:
+    case glslang::EbvClipDistancePerViewNV:
         return spv::BuiltInClipDistancePerViewNV;
-     case glslang::EbvCullDistancePerViewNV:
+    case glslang::EbvCullDistancePerViewNV:
         return spv::BuiltInCullDistancePerViewNV;
-     case glslang::EbvLayerPerViewNV:
+    case glslang::EbvLayerPerViewNV:
         return spv::BuiltInLayerPerViewNV;
-     case glslang::EbvMeshViewCountNV:
+    case glslang::EbvMeshViewCountNV:
         return spv::BuiltInMeshViewCountNV;
-     case glslang::EbvMeshViewIndicesNV:
+    case glslang::EbvMeshViewIndicesNV:
         return spv::BuiltInMeshViewIndicesNV;
-#endif 
+
+    // sm builtins
+    case glslang::EbvWarpsPerSM:
+        builder.addExtension(spv::E_SPV_NV_shader_sm_builtins);
+        builder.addCapability(spv::CapabilityShaderSMBuiltinsNV);
+        return spv::BuiltInWarpsPerSMNV;
+    case glslang::EbvSMCount:
+        builder.addExtension(spv::E_SPV_NV_shader_sm_builtins);
+        builder.addCapability(spv::CapabilityShaderSMBuiltinsNV);
+        return spv::BuiltInSMCountNV;
+    case glslang::EbvWarpID:
+        builder.addExtension(spv::E_SPV_NV_shader_sm_builtins);
+        builder.addCapability(spv::CapabilityShaderSMBuiltinsNV);
+        return spv::BuiltInWarpIDNV;
+    case glslang::EbvSMID:
+        builder.addExtension(spv::E_SPV_NV_shader_sm_builtins);
+        builder.addCapability(spv::CapabilityShaderSMBuiltinsNV);
+        return spv::BuiltInSMIDNV;
+#endif
+
     default:
         return spv::BuiltInMax;
     }
@@ -952,8 +1030,12 @@
 {
     assert(type.getBasicType() == glslang::EbtSampler);
 
+#ifdef GLSLANG_WEB
+    return spv::ImageFormatUnknown;
+#endif
+
     // Check for capabilities
-    switch (type.getQualifier().layoutFormat) {
+    switch (type.getQualifier().getFormat()) {
     case glslang::ElfRg32f:
     case glslang::ElfRg16f:
     case glslang::ElfR11fG11fB10f:
@@ -990,7 +1072,7 @@
     }
 
     // do the translation
-    switch (type.getQualifier().layoutFormat) {
+    switch (type.getQualifier().getFormat()) {
     case glslang::ElfNone:          return spv::ImageFormatUnknown;
     case glslang::ElfRgba32f:       return spv::ImageFormatRgba32f;
     case glslang::ElfRgba16f:       return spv::ImageFormatRgba16f;
@@ -1035,7 +1117,8 @@
     }
 }
 
-spv::SelectionControlMask TGlslangToSpvTraverser::TranslateSelectionControl(const glslang::TIntermSelection& selectionNode) const
+spv::SelectionControlMask TGlslangToSpvTraverser::TranslateSelectionControl(
+    const glslang::TIntermSelection& selectionNode) const
 {
     if (selectionNode.getFlatten())
         return spv::SelectionControlFlattenMask;
@@ -1044,7 +1127,8 @@
     return spv::SelectionControlMaskNone;
 }
 
-spv::SelectionControlMask TGlslangToSpvTraverser::TranslateSwitchControl(const glslang::TIntermSwitch& switchNode) const
+spv::SelectionControlMask TGlslangToSpvTraverser::TranslateSwitchControl(const glslang::TIntermSwitch& switchNode)
+    const
 {
     if (switchNode.getFlatten())
         return spv::SelectionControlFlattenMask;
@@ -1055,7 +1139,7 @@
 
 // return a non-0 dependency if the dependency argument must be set
 spv::LoopControlMask TGlslangToSpvTraverser::TranslateLoopControl(const glslang::TIntermLoop& loopNode,
-    unsigned int& dependencyLength) const
+    std::vector<unsigned int>& operands) const
 {
     spv::LoopControlMask control = spv::LoopControlMaskNone;
 
@@ -1067,7 +1151,29 @@
         control = control | spv::LoopControlDependencyInfiniteMask;
     else if (loopNode.getLoopDependency() > 0) {
         control = control | spv::LoopControlDependencyLengthMask;
-        dependencyLength = loopNode.getLoopDependency();
+        operands.push_back((unsigned int)loopNode.getLoopDependency());
+    }
+    if (glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_4) {
+        if (loopNode.getMinIterations() > 0) {
+            control = control | spv::LoopControlMinIterationsMask;
+            operands.push_back(loopNode.getMinIterations());
+        }
+        if (loopNode.getMaxIterations() < glslang::TIntermLoop::iterationsInfinite) {
+            control = control | spv::LoopControlMaxIterationsMask;
+            operands.push_back(loopNode.getMaxIterations());
+        }
+        if (loopNode.getIterationMultiple() > 1) {
+            control = control | spv::LoopControlIterationMultipleMask;
+            operands.push_back(loopNode.getIterationMultiple());
+        }
+        if (loopNode.getPeelCount() > 0) {
+            control = control | spv::LoopControlPeelCountMask;
+            operands.push_back(loopNode.getPeelCount());
+        }
+        if (loopNode.getPartialCount() > 0) {
+            control = control | spv::LoopControlPartialCountMask;
+            operands.push_back(loopNode.getPartialCount());
+        }
     }
 
     return control;
@@ -1076,33 +1182,33 @@
 // Translate glslang type to SPIR-V storage class.
 spv::StorageClass TGlslangToSpvTraverser::TranslateStorageClass(const glslang::TType& type)
 {
+    if (type.getBasicType() == glslang::EbtRayQuery)
+        return spv::StorageClassFunction;
     if (type.getQualifier().isPipeInput())
         return spv::StorageClassInput;
     if (type.getQualifier().isPipeOutput())
         return spv::StorageClassOutput;
 
     if (glslangIntermediate->getSource() != glslang::EShSourceHlsl ||
-        type.getQualifier().storage == glslang::EvqUniform) {
-        if (type.getBasicType() == glslang::EbtAtomicUint)
+            type.getQualifier().storage == glslang::EvqUniform) {
+        if (type.isAtomic())
             return spv::StorageClassAtomicCounter;
         if (type.containsOpaque())
             return spv::StorageClassUniformConstant;
     }
 
-#ifdef NV_EXTENSIONS
     if (type.getQualifier().isUniformOrBuffer() &&
-        type.getQualifier().layoutShaderRecordNV) {
-        return spv::StorageClassShaderRecordBufferNV;
+        type.getQualifier().isShaderRecord()) {
+        return spv::StorageClassShaderRecordBufferKHR;
     }
-#endif
 
     if (glslangIntermediate->usingStorageBuffer() && type.getQualifier().storage == glslang::EvqBuffer) {
-        addPre13Extension(spv::E_SPV_KHR_storage_buffer_storage_class);
+        builder.addIncorporatedExtension(spv::E_SPV_KHR_storage_buffer_storage_class, spv::Spv_1_3);
         return spv::StorageClassStorageBuffer;
     }
 
     if (type.getQualifier().isUniformOrBuffer()) {
-        if (type.getQualifier().layoutPushConstant)
+        if (type.getQualifier().isPushConstant())
             return spv::StorageClassPushConstant;
         if (type.getBasicType() == glslang::EbtBlock)
             return spv::StorageClassUniform;
@@ -1110,16 +1216,16 @@
     }
 
     switch (type.getQualifier().storage) {
-    case glslang::EvqShared:        return spv::StorageClassWorkgroup;
     case glslang::EvqGlobal:        return spv::StorageClassPrivate;
     case glslang::EvqConstReadOnly: return spv::StorageClassFunction;
     case glslang::EvqTemporary:     return spv::StorageClassFunction;
-#ifdef NV_EXTENSIONS
-    case glslang::EvqPayloadNV:        return spv::StorageClassRayPayloadNV;
-    case glslang::EvqPayloadInNV:      return spv::StorageClassIncomingRayPayloadNV;
-    case glslang::EvqHitAttrNV:        return spv::StorageClassHitAttributeNV;
-    case glslang::EvqCallableDataNV:   return spv::StorageClassCallableDataNV;
-    case glslang::EvqCallableDataInNV: return spv::StorageClassIncomingCallableDataNV;
+    case glslang::EvqShared:           return spv::StorageClassWorkgroup;
+#ifndef GLSLANG_WEB
+    case glslang::EvqPayload:        return spv::StorageClassRayPayloadKHR;
+    case glslang::EvqPayloadIn:      return spv::StorageClassIncomingRayPayloadKHR;
+    case glslang::EvqHitAttr:        return spv::StorageClassHitAttributeKHR;
+    case glslang::EvqCallableData:   return spv::StorageClassCallableDataKHR;
+    case glslang::EvqCallableDataIn: return spv::StorageClassIncomingCallableDataKHR;
 #endif
     default:
         assert(0);
@@ -1133,15 +1239,16 @@
 void TGlslangToSpvTraverser::addIndirectionIndexCapabilities(const glslang::TType& baseType,
                                                              const glslang::TType& indexType)
 {
+#ifndef GLSLANG_WEB
     if (indexType.getQualifier().isNonUniform()) {
         // deal with an asserted non-uniform index
         // SPV_EXT_descriptor_indexing already added in TranslateNonUniformDecoration
         if (baseType.getBasicType() == glslang::EbtSampler) {
             if (baseType.getQualifier().hasAttachment())
                 builder.addCapability(spv::CapabilityInputAttachmentArrayNonUniformIndexingEXT);
-            else if (baseType.isImage() && baseType.getSampler().dim == glslang::EsdBuffer)
+            else if (baseType.isImage() && baseType.getSampler().isBuffer())
                 builder.addCapability(spv::CapabilityStorageTexelBufferArrayNonUniformIndexingEXT);
-            else if (baseType.isTexture() && baseType.getSampler().dim == glslang::EsdBuffer)
+            else if (baseType.isTexture() && baseType.getSampler().isBuffer())
                 builder.addCapability(spv::CapabilityUniformTexelBufferArrayNonUniformIndexingEXT);
             else if (baseType.isImage())
                 builder.addCapability(spv::CapabilityStorageImageArrayNonUniformIndexingEXT);
@@ -1157,17 +1264,18 @@
         // assume a dynamically uniform index
         if (baseType.getBasicType() == glslang::EbtSampler) {
             if (baseType.getQualifier().hasAttachment()) {
-                builder.addExtension("SPV_EXT_descriptor_indexing");
+                builder.addIncorporatedExtension("SPV_EXT_descriptor_indexing", spv::Spv_1_5);
                 builder.addCapability(spv::CapabilityInputAttachmentArrayDynamicIndexingEXT);
-            } else if (baseType.isImage() && baseType.getSampler().dim == glslang::EsdBuffer) {
-                builder.addExtension("SPV_EXT_descriptor_indexing");
+            } else if (baseType.isImage() && baseType.getSampler().isBuffer()) {
+                builder.addIncorporatedExtension("SPV_EXT_descriptor_indexing", spv::Spv_1_5);
                 builder.addCapability(spv::CapabilityStorageTexelBufferArrayDynamicIndexingEXT);
-            } else if (baseType.isTexture() && baseType.getSampler().dim == glslang::EsdBuffer) {
-                builder.addExtension("SPV_EXT_descriptor_indexing");
+            } else if (baseType.isTexture() && baseType.getSampler().isBuffer()) {
+                builder.addIncorporatedExtension("SPV_EXT_descriptor_indexing", spv::Spv_1_5);
                 builder.addCapability(spv::CapabilityUniformTexelBufferArrayDynamicIndexingEXT);
             }
         }
     }
+#endif
 }
 
 // Return whether or not the given type is something that should be tied to a
@@ -1177,10 +1285,8 @@
     // uniform and buffer blocks are included, unless it is a push_constant
     if (type.getBasicType() == glslang::EbtBlock)
         return type.getQualifier().isUniformOrBuffer() &&
-#ifdef NV_EXTENSIONS
-        ! type.getQualifier().layoutShaderRecordNV &&
-#endif
-        ! type.getQualifier().layoutPushConstant;
+        ! type.getQualifier().isShaderRecord() &&
+        ! type.getQualifier().isPushConstant();
 
     // non block...
     // basically samplerXXX/subpass/sampler/texture are all included
@@ -1200,16 +1306,21 @@
 
     if (parent.invariant)
         child.invariant = true;
-    if (parent.nopersp)
-        child.nopersp = true;
-#ifdef AMD_EXTENSIONS
-    if (parent.explicitInterp)
-        child.explicitInterp = true;
-#endif
     if (parent.flat)
         child.flat = true;
     if (parent.centroid)
         child.centroid = true;
+#ifndef GLSLANG_WEB
+    if (parent.nopersp)
+        child.nopersp = true;
+    if (parent.explicitInterp)
+        child.explicitInterp = true;
+    if (parent.perPrimitiveNV)
+        child.perPrimitiveNV = true;
+    if (parent.perViewNV)
+        child.perViewNV = true;
+    if (parent.perTaskNV)
+        child.perTaskNV = true;
     if (parent.patch)
         child.patch = true;
     if (parent.sample)
@@ -1224,6 +1335,8 @@
         child.workgroupcoherent = true;
     if (parent.subgroupcoherent)
         child.subgroupcoherent = true;
+    if (parent.shadercallcoherent)
+        child.shadercallcoherent = true;
     if (parent.nonprivate)
         child.nonprivate = true;
     if (parent.volatil)
@@ -1234,13 +1347,6 @@
         child.readonly = true;
     if (parent.writeonly)
         child.writeonly = true;
-#ifdef NV_EXTENSIONS
-    if (parent.perPrimitiveNV)
-        child.perPrimitiveNV = true;
-    if (parent.perViewNV)
-        child.perViewNV = true;
-    if (parent.perTaskNV)
-        child.perTaskNV = true;
 #endif
 }
 
@@ -1261,15 +1367,18 @@
 // Implement the TGlslangToSpvTraverser class.
 //
 
-TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, const glslang::TIntermediate* glslangIntermediate,
-                                               spv::SpvBuildLogger* buildLogger, glslang::SpvOptions& options)
-    : TIntermTraverser(true, false, true),
-      options(options),
-      shaderEntry(nullptr), currentFunction(nullptr),
-      sequenceDepth(0), logger(buildLogger),
-      builder(spvVersion, (glslang::GetKhronosToolId() << 16) | glslang::GetSpirvGeneratorVersion(), logger),
-      inEntryPoint(false), entryPointTerminated(false), linkageOnly(false),
-      glslangIntermediate(glslangIntermediate)
+TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion,
+    const glslang::TIntermediate* glslangIntermediate,
+    spv::SpvBuildLogger* buildLogger, glslang::SpvOptions& options) :
+        TIntermTraverser(true, false, true),
+        options(options),
+        shaderEntry(nullptr), currentFunction(nullptr),
+        sequenceDepth(0), logger(buildLogger),
+        builder(spvVersion, (glslang::GetKhronosToolId() << 16) | glslang::GetSpirvGeneratorVersion(), logger),
+        inEntryPoint(false), entryPointTerminated(false), linkageOnly(false),
+        glslangIntermediate(glslangIntermediate),
+        nanMinMaxClamp(glslangIntermediate->getNanMinMaxClamp()),
+        nonSemanticDebugPrintf(0)
 {
     spv::ExecutionModel executionModel = TranslateExecutionModel(glslangIntermediate->getStage());
 
@@ -1310,13 +1419,13 @@
 
     if (glslangIntermediate->usingPhysicalStorageBuffer()) {
         addressingModel = spv::AddressingModelPhysicalStorageBuffer64EXT;
-        builder.addExtension(spv::E_SPV_EXT_physical_storage_buffer);
+        builder.addIncorporatedExtension(spv::E_SPV_EXT_physical_storage_buffer, spv::Spv_1_5);
         builder.addCapability(spv::CapabilityPhysicalStorageBufferAddressesEXT);
-    };
+    }
     if (glslangIntermediate->usingVulkanMemoryModel()) {
         memoryModel = spv::MemoryModelVulkanKHR;
         builder.addCapability(spv::CapabilityVulkanMemoryModelKHR);
-        builder.addExtension(spv::E_SPV_KHR_vulkan_memory_model);
+        builder.addIncorporatedExtension(spv::E_SPV_KHR_vulkan_memory_model, spv::Spv_1_5);
     }
     builder.setMemoryModel(addressingModel, memoryModel);
 
@@ -1330,7 +1439,7 @@
     // Add the source extensions
     const auto& sourceExtensions = glslangIntermediate->getRequestedExtensions();
     for (auto it = sourceExtensions.begin(); it != sourceExtensions.end(); ++it)
-        builder.addSourceExtension(it->c_str());
+        builder.addSourceExtension(it->first.c_str());
 
     // Add the top-level modes for this shader.
 
@@ -1339,12 +1448,95 @@
         builder.addExecutionMode(shaderEntry, spv::ExecutionModeXfb);
     }
 
+    if (sourceExtensions.find("GL_EXT_ray_flags_primitive_culling") != sourceExtensions.end()) {
+        builder.addCapability(spv::CapabilityRayTraversalPrimitiveCullingProvisionalKHR);
+    }
+
     unsigned int mode;
     switch (glslangIntermediate->getStage()) {
     case EShLangVertex:
         builder.addCapability(spv::CapabilityShader);
         break;
 
+    case EShLangFragment:
+        builder.addCapability(spv::CapabilityShader);
+        if (glslangIntermediate->getPixelCenterInteger())
+            builder.addExecutionMode(shaderEntry, spv::ExecutionModePixelCenterInteger);
+
+        if (glslangIntermediate->getOriginUpperLeft())
+            builder.addExecutionMode(shaderEntry, spv::ExecutionModeOriginUpperLeft);
+        else
+            builder.addExecutionMode(shaderEntry, spv::ExecutionModeOriginLowerLeft);
+
+        if (glslangIntermediate->getEarlyFragmentTests())
+            builder.addExecutionMode(shaderEntry, spv::ExecutionModeEarlyFragmentTests);
+
+        if (glslangIntermediate->getPostDepthCoverage()) {
+            builder.addCapability(spv::CapabilitySampleMaskPostDepthCoverage);
+            builder.addExecutionMode(shaderEntry, spv::ExecutionModePostDepthCoverage);
+            builder.addExtension(spv::E_SPV_KHR_post_depth_coverage);
+        }
+
+        if (glslangIntermediate->getDepth() != glslang::EldUnchanged && glslangIntermediate->isDepthReplacing())
+            builder.addExecutionMode(shaderEntry, spv::ExecutionModeDepthReplacing);
+
+#ifndef GLSLANG_WEB
+
+        switch(glslangIntermediate->getDepth()) {
+        case glslang::EldGreater:  mode = spv::ExecutionModeDepthGreater; break;
+        case glslang::EldLess:     mode = spv::ExecutionModeDepthLess;    break;
+        default:                   mode = spv::ExecutionModeMax;          break;
+        }
+        if (mode != spv::ExecutionModeMax)
+            builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode);
+        switch (glslangIntermediate->getInterlockOrdering()) {
+        case glslang::EioPixelInterlockOrdered:         mode = spv::ExecutionModePixelInterlockOrderedEXT;
+            break;
+        case glslang::EioPixelInterlockUnordered:       mode = spv::ExecutionModePixelInterlockUnorderedEXT;
+            break;
+        case glslang::EioSampleInterlockOrdered:        mode = spv::ExecutionModeSampleInterlockOrderedEXT;
+            break;
+        case glslang::EioSampleInterlockUnordered:      mode = spv::ExecutionModeSampleInterlockUnorderedEXT;
+            break;
+        case glslang::EioShadingRateInterlockOrdered:   mode = spv::ExecutionModeShadingRateInterlockOrderedEXT;
+            break;
+        case glslang::EioShadingRateInterlockUnordered: mode = spv::ExecutionModeShadingRateInterlockUnorderedEXT;
+            break;
+        default:                                        mode = spv::ExecutionModeMax;
+            break;
+        }
+        if (mode != spv::ExecutionModeMax) {
+            builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode);
+            if (mode == spv::ExecutionModeShadingRateInterlockOrderedEXT ||
+                mode == spv::ExecutionModeShadingRateInterlockUnorderedEXT) {
+                builder.addCapability(spv::CapabilityFragmentShaderShadingRateInterlockEXT);
+            } else if (mode == spv::ExecutionModePixelInterlockOrderedEXT ||
+                       mode == spv::ExecutionModePixelInterlockUnorderedEXT) {
+                builder.addCapability(spv::CapabilityFragmentShaderPixelInterlockEXT);
+            } else {
+                builder.addCapability(spv::CapabilityFragmentShaderSampleInterlockEXT);
+            }
+            builder.addExtension(spv::E_SPV_EXT_fragment_shader_interlock);
+        }
+#endif
+    break;
+
+    case EShLangCompute:
+        builder.addCapability(spv::CapabilityShader);
+        builder.addExecutionMode(shaderEntry, spv::ExecutionModeLocalSize, glslangIntermediate->getLocalSize(0),
+                                                                           glslangIntermediate->getLocalSize(1),
+                                                                           glslangIntermediate->getLocalSize(2));
+        if (glslangIntermediate->getLayoutDerivativeModeNone() == glslang::LayoutDerivativeGroupQuads) {
+            builder.addCapability(spv::CapabilityComputeDerivativeGroupQuadsNV);
+            builder.addExecutionMode(shaderEntry, spv::ExecutionModeDerivativeGroupQuadsNV);
+            builder.addExtension(spv::E_SPV_NV_compute_shader_derivatives);
+        } else if (glslangIntermediate->getLayoutDerivativeModeNone() == glslang::LayoutDerivativeGroupLinear) {
+            builder.addCapability(spv::CapabilityComputeDerivativeGroupLinearNV);
+            builder.addExecutionMode(shaderEntry, spv::ExecutionModeDerivativeGroupLinearNV);
+            builder.addExtension(spv::E_SPV_NV_compute_shader_derivatives);
+        }
+        break;
+#ifndef GLSLANG_WEB
     case EShLangTessEvaluation:
     case EShLangTessControl:
         builder.addCapability(spv::CapabilityTessellation);
@@ -1352,7 +1544,8 @@
         glslang::TLayoutGeometry primitive;
 
         if (glslangIntermediate->getStage() == EShLangTessControl) {
-            builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices, glslangIntermediate->getVertices());
+            builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices,
+                glslangIntermediate->getVertices());
             primitive = glslangIntermediate->getOutputPrimitive();
         } else {
             primitive = glslangIntermediate->getInputPrimitive();
@@ -1414,65 +1607,24 @@
         builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices, glslangIntermediate->getVertices());
         break;
 
-    case EShLangFragment:
-        builder.addCapability(spv::CapabilityShader);
-        if (glslangIntermediate->getPixelCenterInteger())
-            builder.addExecutionMode(shaderEntry, spv::ExecutionModePixelCenterInteger);
-
-        if (glslangIntermediate->getOriginUpperLeft())
-            builder.addExecutionMode(shaderEntry, spv::ExecutionModeOriginUpperLeft);
-        else
-            builder.addExecutionMode(shaderEntry, spv::ExecutionModeOriginLowerLeft);
-
-        if (glslangIntermediate->getEarlyFragmentTests())
-            builder.addExecutionMode(shaderEntry, spv::ExecutionModeEarlyFragmentTests);
-
-        if (glslangIntermediate->getPostDepthCoverage()) {
-            builder.addCapability(spv::CapabilitySampleMaskPostDepthCoverage);
-            builder.addExecutionMode(shaderEntry, spv::ExecutionModePostDepthCoverage);
-            builder.addExtension(spv::E_SPV_KHR_post_depth_coverage);
+    case EShLangRayGen:
+    case EShLangIntersect:
+    case EShLangAnyHit:
+    case EShLangClosestHit:
+    case EShLangMiss:
+    case EShLangCallable: 
+    {
+        auto& extensions = glslangIntermediate->getRequestedExtensions();
+        if (extensions.find("GL_NV_ray_tracing") == extensions.end()) {
+            builder.addCapability(spv::CapabilityRayTracingProvisionalKHR);
+            builder.addExtension("SPV_KHR_ray_tracing");
         }
-
-        switch(glslangIntermediate->getDepth()) {
-        case glslang::EldGreater:  mode = spv::ExecutionModeDepthGreater; break;
-        case glslang::EldLess:     mode = spv::ExecutionModeDepthLess;    break;
-        default:                   mode = spv::ExecutionModeMax;          break;
+        else {
+            builder.addCapability(spv::CapabilityRayTracingNV);
+            builder.addExtension("SPV_NV_ray_tracing");
         }
-        if (mode != spv::ExecutionModeMax)
-            builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode);
-
-        if (glslangIntermediate->getDepth() != glslang::EldUnchanged && glslangIntermediate->isDepthReplacing())
-            builder.addExecutionMode(shaderEntry, spv::ExecutionModeDepthReplacing);
         break;
-
-    case EShLangCompute:
-        builder.addCapability(spv::CapabilityShader);
-        builder.addExecutionMode(shaderEntry, spv::ExecutionModeLocalSize, glslangIntermediate->getLocalSize(0),
-                                                                           glslangIntermediate->getLocalSize(1),
-                                                                           glslangIntermediate->getLocalSize(2));
-#ifdef NV_EXTENSIONS
-        if (glslangIntermediate->getLayoutDerivativeModeNone() == glslang::LayoutDerivativeGroupQuads) {
-            builder.addCapability(spv::CapabilityComputeDerivativeGroupQuadsNV);
-            builder.addExecutionMode(shaderEntry, spv::ExecutionModeDerivativeGroupQuadsNV);
-            builder.addExtension(spv::E_SPV_NV_compute_shader_derivatives);
-        } else if (glslangIntermediate->getLayoutDerivativeModeNone() == glslang::LayoutDerivativeGroupLinear) {
-            builder.addCapability(spv::CapabilityComputeDerivativeGroupLinearNV);
-            builder.addExecutionMode(shaderEntry, spv::ExecutionModeDerivativeGroupLinearNV);
-            builder.addExtension(spv::E_SPV_NV_compute_shader_derivatives);
-        }
-#endif
-        break;
-
-#ifdef NV_EXTENSIONS
-    case EShLangRayGenNV:
-    case EShLangIntersectNV:
-    case EShLangAnyHitNV:
-    case EShLangClosestHitNV:
-    case EShLangMissNV:
-    case EShLangCallableNV:
-        builder.addCapability(spv::CapabilityRayTracingNV);
-        builder.addExtension("SPV_NV_ray_tracing");
-        break;
+    }
     case EShLangTaskNV:
     case EShLangMeshNV:
         builder.addCapability(spv::CapabilityMeshShadingNV);
@@ -1481,8 +1633,10 @@
                                                                            glslangIntermediate->getLocalSize(1),
                                                                            glslangIntermediate->getLocalSize(2));
         if (glslangIntermediate->getStage() == EShLangMeshNV) {
-            builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices, glslangIntermediate->getVertices());
-            builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputPrimitivesNV, glslangIntermediate->getPrimitives());
+            builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices,
+                glslangIntermediate->getVertices());
+            builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputPrimitivesNV,
+                glslangIntermediate->getPrimitives());
 
             switch (glslangIntermediate->getOutputPrimitive()) {
             case glslang::ElgPoints:        mode = spv::ExecutionModeOutputPoints;      break;
@@ -1514,8 +1668,10 @@
     for (auto it = iOSet.cbegin(); it != iOSet.cend(); ++it)
         entryPoint->addIdOperand(*it);
 
-    // Add capabilities, extensions, remove unneeded decorations, etc., 
+    // Add capabilities, extensions, remove unneeded decorations, etc.,
     // based on the resulting SPIR-V.
+    // Note: WebGPU code generation must have the opportunity to aggressively
+    // prune unreachable merge blocks and continue targets.
     builder.postProcess();
 }
 
@@ -1543,6 +1699,9 @@
 void TGlslangToSpvTraverser::visitSymbol(glslang::TIntermSymbol* symbol)
 {
     SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder);
+    if (symbol->getType().isStruct())
+        glslangTypeToIdMap[symbol->getType().getStruct()] = symbol->getId();
+
     if (symbol->getType().getQualifier().isSpecConstant())
         spec_constant_op_mode_setter.turnOnSpecConstantOpMode();
 
@@ -1550,13 +1709,28 @@
     // Formal function parameters were mapped during makeFunctions().
     spv::Id id = getSymbolId(symbol);
 
-    // Include all "static use" and "linkage only" interface variables on the OpEntryPoint instruction
     if (builder.isPointer(id)) {
-        spv::StorageClass sc = builder.getStorageClass(id);
-        if (sc == spv::StorageClassInput || sc == spv::StorageClassOutput) {
-            if (!symbol->getType().isStruct() || symbol->getType().getStruct()->size() > 0)
+        // Include all "static use" and "linkage only" interface variables on the OpEntryPoint instruction
+        // Consider adding to the OpEntryPoint interface list.
+        // Only looking at structures if they have at least one member.
+        if (!symbol->getType().isStruct() || symbol->getType().getStruct()->size() > 0) {
+            spv::StorageClass sc = builder.getStorageClass(id);
+            // Before SPIR-V 1.4, we only want to include Input and Output.
+            // Starting with SPIR-V 1.4, we want all globals.
+            if ((glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_4 && sc != spv::StorageClassFunction) ||
+                (sc == spv::StorageClassInput || sc == spv::StorageClassOutput)) {
                 iOSet.insert(id);
+            }
         }
+
+        // If the SPIR-V type is required to be different than the AST type
+        // (for ex SubgroupMasks or 3x4 ObjectToWorld/WorldToObject matrices),
+        // translate now from the SPIR-V type to the AST type, for the consuming
+        // operation.
+        // Note this turns it from an l-value to an r-value.
+        // Currently, all symbols needing this are inputs; avoid the map lookup when non-input.
+        if (symbol->getType().getQualifier().storage == glslang::EvqVaryingIn)
+            id = translateForcedType(id);
     }
 
     // Only process non-linkage-only nodes for generating actual static uses
@@ -1574,13 +1748,16 @@
         //    See comments in handleUserFunctionCall().
         // B) Specialization constants (normal constants don't even come in as a variable),
         //    These are also pure R-values.
+        // C) R-Values from type translation, see above call to translateForcedType()
         glslang::TQualifier qualifier = symbol->getQualifier();
-        if (qualifier.isSpecConstant() || rValueParameters.find(symbol->getId()) != rValueParameters.end())
+        if (qualifier.isSpecConstant() || rValueParameters.find(symbol->getId()) != rValueParameters.end() ||
+            !builder.isPointerType(builder.getTypeId(id)))
             builder.setAccessChainRValue(id);
         else
             builder.setAccessChainLValue(id);
     }
 
+#ifdef ENABLE_HLSL
     // Process linkage-only nodes for any special additional interface work.
     if (linkageOnly) {
         if (glslangIntermediate->getHlslFunctionality1()) {
@@ -1612,11 +1789,18 @@
             }
         }
     }
+#endif
 }
 
 bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::TIntermBinary* node)
 {
     builder.setLine(node->getLoc().line, node->getLoc().getFilename());
+    if (node->getLeft()->getAsSymbolNode() != nullptr && node->getLeft()->getType().isStruct()) {
+        glslangTypeToIdMap[node->getLeft()->getType().getStruct()] = node->getLeft()->getAsSymbolNode()->getId();
+    }
+    if (node->getRight()->getAsSymbolNode() != nullptr && node->getRight()->getType().isStruct()) {
+        glslangTypeToIdMap[node->getRight()->getType().getStruct()] = node->getRight()->getAsSymbolNode()->getId();
+    }
 
     SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder);
     if (node->getType().getQualifier().isSpecConstant())
@@ -1683,6 +1867,7 @@
     case glslang::EOpIndexDirect:
     case glslang::EOpIndexDirectStruct:
         {
+            // Structure, array, matrix, or vector indirection with statically known index.
             // Get the left part of the access chain.
             node->getLeft()->traverse(this);
 
@@ -1699,13 +1884,14 @@
                 int dummySize;
                 builder.accessChainPushSwizzle(swizzle, convertGlslangToSpvType(node->getLeft()->getType()),
                                                TranslateCoherent(node->getLeft()->getType()),
-                                               glslangIntermediate->getBaseAlignmentScalar(node->getLeft()->getType(), dummySize));
+                                               glslangIntermediate->getBaseAlignmentScalar(
+                                                   node->getLeft()->getType(), dummySize));
             } else {
 
                 // Load through a block reference is performed with a dot operator that
                 // is mapped to EOpIndexDirectStruct. When we get to the actual reference,
                 // do a load and reset the access chain.
-                if (node->getLeft()->getBasicType() == glslang::EbtReference &&
+                if (node->getLeft()->isReference() &&
                     !node->getLeft()->getType().isArray() &&
                     node->getOp() == glslang::EOpIndexDirectStruct)
                 {
@@ -1720,13 +1906,18 @@
                 {
                     // This may be, e.g., an anonymous block-member selection, which generally need
                     // index remapping due to hidden members in anonymous blocks.
-                    std::vector<int>& remapper = memberRemapper[node->getLeft()->getType().getStruct()];
-                    assert(remapper.size() > 0);
-                    spvIndex = remapper[glslangIndex];
+                    int glslangId = glslangTypeToIdMap[node->getLeft()->getType().getStruct()];
+                    if (memberRemapper.find(glslangId) != memberRemapper.end()) {
+                        std::vector<int>& remapper = memberRemapper[glslangId];
+                        assert(remapper.size() > 0);
+                        spvIndex = remapper[glslangIndex];
+                    }
                 }
 
                 // normal case for indexing array or structure or block
-                builder.accessChainPush(builder.makeIntConstant(spvIndex), TranslateCoherent(node->getLeft()->getType()), node->getLeft()->getType().getBufferReferenceAlignment());
+                builder.accessChainPush(builder.makeIntConstant(spvIndex),
+                    TranslateCoherent(node->getLeft()->getType()),
+                        node->getLeft()->getType().getBufferReferenceAlignment());
 
                 // Add capabilities here for accessing PointSize and clip/cull distance.
                 // We have deferred generation of associated capabilities until now.
@@ -1737,8 +1928,8 @@
         return false;
     case glslang::EOpIndexIndirect:
         {
-            // Structure or array or vector indirection.
-            // Will use native SPIR-V access-chain for struct and array indirection;
+            // Array, matrix, or vector indirection with variable index.
+            // Will use native SPIR-V access-chain for and array indirection;
             // matrices are arrays of vectors, so will also work for a matrix.
             // Will use the access chain's 'component' for variable index into a vector.
 
@@ -1763,9 +1954,11 @@
                 int dummySize;
                 builder.accessChainPushComponent(index, convertGlslangToSpvType(node->getLeft()->getType()),
                                                 TranslateCoherent(node->getLeft()->getType()),
-                                                glslangIntermediate->getBaseAlignmentScalar(node->getLeft()->getType(), dummySize));
+                                                glslangIntermediate->getBaseAlignmentScalar(node->getLeft()->getType(),
+                                                dummySize));
             } else
-                builder.accessChainPush(index, TranslateCoherent(node->getLeft()->getType()), node->getLeft()->getType().getBufferReferenceAlignment());
+                builder.accessChainPush(index, TranslateCoherent(node->getLeft()->getType()),
+                    node->getLeft()->getType().getBufferReferenceAlignment());
         }
         return false;
     case glslang::EOpVectorSwizzle:
@@ -1776,7 +1969,8 @@
             int dummySize;
             builder.accessChainPushSwizzle(swizzle, convertGlslangToSpvType(node->getLeft()->getType()),
                                            TranslateCoherent(node->getLeft()->getType()),
-                                           glslangIntermediate->getBaseAlignmentScalar(node->getLeft()->getType(), dummySize));
+                                           glslangIntermediate->getBaseAlignmentScalar(node->getLeft()->getType(),
+                                               dummySize));
         }
         return false;
     case glslang::EOpMatrixSwizzle:
@@ -1792,7 +1986,8 @@
             if (isTrivial(node->getRight()->getAsTyped()))
                 break; // handle below as a normal binary operation
             // otherwise, we need to do dynamic short circuiting on the right operand
-            spv::Id result = createShortCircuit(node->getOp(), *node->getLeft()->getAsTyped(), *node->getRight()->getAsTyped());
+            spv::Id result = createShortCircuit(node->getOp(), *node->getLeft()->getAsTyped(),
+                *node->getRight()->getAsTyped());
             builder.clearAccessChain();
             builder.setAccessChainRValue(result);
         }
@@ -1831,6 +2026,88 @@
     }
 }
 
+// Figure out what, if any, type changes are needed when accessing a specific built-in.
+// Returns <the type SPIR-V requires for declarion, the type to translate to on use>.
+// Also see comment for 'forceType', regarding tracking SPIR-V-required types.
+std::pair<spv::Id, spv::Id> TGlslangToSpvTraverser::getForcedType(glslang::TBuiltInVariable glslangBuiltIn,
+    const glslang::TType& glslangType)
+{
+    switch(glslangBuiltIn)
+    {
+        case glslang::EbvSubGroupEqMask:
+        case glslang::EbvSubGroupGeMask:
+        case glslang::EbvSubGroupGtMask:
+        case glslang::EbvSubGroupLeMask:
+        case glslang::EbvSubGroupLtMask: {
+            // these require changing a 64-bit scaler -> a vector of 32-bit components
+            if (glslangType.isVector())
+                break;
+            std::pair<spv::Id, spv::Id> ret(builder.makeVectorType(builder.makeUintType(32), 4),
+                                            builder.makeUintType(64));
+            return ret;
+        }
+        // There are no SPIR-V builtins defined for these and map onto original non-transposed
+        // builtins. During visitBinary we insert a transpose
+        case glslang::EbvWorldToObject3x4:
+        case glslang::EbvObjectToWorld3x4: {
+            std::pair<spv::Id, spv::Id> ret(builder.makeMatrixType(builder.makeFloatType(32), 4, 3),
+                builder.makeMatrixType(builder.makeFloatType(32), 3, 4)
+            );
+            return ret;
+        }
+        default:
+            break;
+    }
+
+    std::pair<spv::Id, spv::Id> ret(spv::NoType, spv::NoType);
+    return ret;
+}
+
+// For an object previously identified (see getForcedType() and forceType)
+// as needing type translations, do the translation needed for a load, turning
+// an L-value into in R-value.
+spv::Id TGlslangToSpvTraverser::translateForcedType(spv::Id object)
+{
+    const auto forceIt = forceType.find(object);
+    if (forceIt == forceType.end())
+        return object;
+
+    spv::Id desiredTypeId = forceIt->second;
+    spv::Id objectTypeId = builder.getTypeId(object);
+    assert(builder.isPointerType(objectTypeId));
+    objectTypeId = builder.getContainedTypeId(objectTypeId);
+    if (builder.isVectorType(objectTypeId) &&
+        builder.getScalarTypeWidth(builder.getContainedTypeId(objectTypeId)) == 32) {
+        if (builder.getScalarTypeWidth(desiredTypeId) == 64) {
+            // handle 32-bit v.xy* -> 64-bit
+            builder.clearAccessChain();
+            builder.setAccessChainLValue(object);
+            object = builder.accessChainLoad(spv::NoPrecision, spv::DecorationMax, objectTypeId);
+            std::vector<spv::Id> components;
+            components.push_back(builder.createCompositeExtract(object, builder.getContainedTypeId(objectTypeId), 0));
+            components.push_back(builder.createCompositeExtract(object, builder.getContainedTypeId(objectTypeId), 1));
+
+            spv::Id vecType = builder.makeVectorType(builder.getContainedTypeId(objectTypeId), 2);
+            return builder.createUnaryOp(spv::OpBitcast, desiredTypeId,
+                                         builder.createCompositeConstruct(vecType, components));
+        } else {
+            logger->missingFunctionality("forcing 32-bit vector type to non 64-bit scalar");
+        }
+    } else if (builder.isMatrixType(objectTypeId)) {
+            // There are no SPIR-V builtins defined for 3x4 variants of ObjectToWorld/WorldToObject
+            // and we insert a transpose after loading the original non-transposed builtins
+            builder.clearAccessChain();
+            builder.setAccessChainLValue(object);
+            object = builder.accessChainLoad(spv::NoPrecision, spv::DecorationMax, objectTypeId);
+            return builder.createUnaryOp(spv::OpTranspose, desiredTypeId, object);
+
+    } else  {
+        logger->missingFunctionality("forcing non 32-bit vector type");
+    }
+
+    return object;
+}
+
 bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TIntermUnary* node)
 {
     builder.setLine(node->getLoc().line, node->getLoc().getFilename());
@@ -1875,7 +2152,8 @@
         } else {
             glslang::TIntermTyped* block = node->getOperand()->getAsBinaryNode()->getLeft();
             block->traverse(this);
-            unsigned int member = node->getOperand()->getAsBinaryNode()->getRight()->getAsConstantUnion()->getConstArray()[0].getUConst();
+            unsigned int member = node->getOperand()->getAsBinaryNode()->getRight()->getAsConstantUnion()
+                ->getConstArray()[0].getUConst();
             length = builder.createArrayLength(builder.accessChainGetLValue(), member);
         }
 
@@ -1901,25 +2179,45 @@
     // Does it need a swizzle inversion?  If so, evaluation is inverted;
     // operate first on the swizzle base, then apply the swizzle.
     spv::Id invertedType = spv::NoType;
-    auto resultType = [&invertedType, &node, this](){ return invertedType != spv::NoType ? invertedType : convertGlslangToSpvType(node->getType()); };
+    auto resultType = [&invertedType, &node, this](){ return invertedType != spv::NoType ?
+        invertedType : convertGlslangToSpvType(node->getType()); };
     if (node->getOp() == glslang::EOpInterpolateAtCentroid)
         invertedType = getInvertedSwizzleType(*node->getOperand());
 
     builder.clearAccessChain();
+    TIntermNode *operandNode;
     if (invertedType != spv::NoType)
-        node->getOperand()->getAsBinaryNode()->getLeft()->traverse(this);
+        operandNode = node->getOperand()->getAsBinaryNode()->getLeft();
     else
-        node->getOperand()->traverse(this);
+        operandNode = node->getOperand();
+    
+    operandNode->traverse(this);
 
     spv::Id operand = spv::NoResult;
 
+    spv::Builder::AccessChain::CoherentFlags lvalueCoherentFlags;
+
+#ifndef GLSLANG_WEB
     if (node->getOp() == glslang::EOpAtomicCounterIncrement ||
         node->getOp() == glslang::EOpAtomicCounterDecrement ||
         node->getOp() == glslang::EOpAtomicCounter          ||
-        node->getOp() == glslang::EOpInterpolateAtCentroid)
+        node->getOp() == glslang::EOpInterpolateAtCentroid  ||
+        node->getOp() == glslang::EOpRayQueryProceed        ||
+        node->getOp() == glslang::EOpRayQueryGetRayTMin     ||
+        node->getOp() == glslang::EOpRayQueryGetRayFlags    ||
+        node->getOp() == glslang::EOpRayQueryGetWorldRayOrigin ||
+        node->getOp() == glslang::EOpRayQueryGetWorldRayDirection ||
+        node->getOp() == glslang::EOpRayQueryGetIntersectionCandidateAABBOpaque ||
+        node->getOp() == glslang::EOpRayQueryTerminate ||
+        node->getOp() == glslang::EOpRayQueryConfirmIntersection) {
         operand = builder.accessChainGetLValue(); // Special case l-value operands
-    else
+        lvalueCoherentFlags = builder.getAccessChain().coherentFlags;
+        lvalueCoherentFlags |= TranslateCoherent(operandNode->getAsTyped()->getType());
+    } else
+#endif
+    {
         operand = accessChainLoad(node->getOperand()->getType());
+    }
 
     OpDecorations decorations = { TranslatePrecisionDecoration(node->getOperationPrecision()),
                                   TranslateNoContractionDecoration(node->getType().getQualifier()),
@@ -1927,16 +2225,18 @@
 
     // it could be a conversion
     if (! result)
-        result = createConversion(node->getOp(), decorations, resultType(), operand, node->getOperand()->getBasicType());
+        result = createConversion(node->getOp(), decorations, resultType(), operand,
+            node->getOperand()->getBasicType());
 
     // if not, then possibly an operation
     if (! result)
-        result = createUnaryOperation(node->getOp(), decorations, resultType(), operand, node->getOperand()->getBasicType());
+        result = createUnaryOperation(node->getOp(), decorations, resultType(), operand,
+            node->getOperand()->getBasicType(), lvalueCoherentFlags);
 
     if (result) {
         if (invertedType) {
             result = createInvertedSwizzle(decorations.precision, *node->getOperand(), result);
-            builder.addDecoration(result, decorations.nonUniform);
+            decorations.addNonUniform(builder, result);
         }
 
         builder.clearAccessChain();
@@ -1956,6 +2256,7 @@
             spv::Id one = 0;
             if (node->getBasicType() == glslang::EbtFloat)
                 one = builder.makeFloatConstant(1.0F);
+#ifndef GLSLANG_WEB
             else if (node->getBasicType() == glslang::EbtDouble)
                 one = builder.makeDoubleConstant(1.0);
             else if (node->getBasicType() == glslang::EbtFloat16)
@@ -1966,6 +2267,7 @@
                 one = builder.makeInt16Constant(1);
             else if (node->getBasicType() == glslang::EbtInt64 || node->getBasicType() == glslang::EbtUint64)
                 one = builder.makeInt64Constant(1);
+#endif
             else
                 one = builder.makeIntConstant(1);
             glslang::TOperator op;
@@ -1993,12 +2295,20 @@
 
         return false;
 
+#ifndef GLSLANG_WEB
     case glslang::EOpEmitStreamVertex:
         builder.createNoResultOp(spv::OpEmitStreamVertex, operand);
         return false;
     case glslang::EOpEndStreamPrimitive:
         builder.createNoResultOp(spv::OpEndStreamPrimitive, operand);
         return false;
+    case glslang::EOpRayQueryTerminate:
+        builder.createNoResultOp(spv::OpRayQueryTerminateKHR, operand);
+        return false;
+    case glslang::EOpRayQueryConfirmIntersection:
+        builder.createNoResultOp(spv::OpRayQueryConfirmIntersectionKHR, operand);
+        return false;
+#endif
 
     default:
         logger->missingFunctionality("unknown glslang unary");
@@ -2006,6 +2316,40 @@
     }
 }
 
+// Construct a composite object, recursively copying members if their types don't match
+spv::Id TGlslangToSpvTraverser::createCompositeConstruct(spv::Id resultTypeId, std::vector<spv::Id> constituents)
+{
+    for (int c = 0; c < (int)constituents.size(); ++c) {
+        spv::Id& constituent = constituents[c];
+        spv::Id lType = builder.getContainedTypeId(resultTypeId, c);
+        spv::Id rType = builder.getTypeId(constituent);
+        if (lType != rType) {
+            if (glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_4) {
+                constituent = builder.createUnaryOp(spv::OpCopyLogical, lType, constituent);
+            } else if (builder.isStructType(rType)) {
+                std::vector<spv::Id> rTypeConstituents;
+                int numrTypeConstituents = builder.getNumTypeConstituents(rType);
+                for (int i = 0; i < numrTypeConstituents; ++i) {
+                    rTypeConstituents.push_back(builder.createCompositeExtract(constituent,
+                        builder.getContainedTypeId(rType, i), i));
+                }
+                constituents[c] = createCompositeConstruct(lType, rTypeConstituents);
+            } else {
+                assert(builder.isArrayType(rType));
+                std::vector<spv::Id> rTypeConstituents;
+                int numrTypeConstituents = builder.getNumTypeConstituents(rType);
+
+                spv::Id elementRType = builder.getContainedTypeId(rType);
+                for (int i = 0; i < numrTypeConstituents; ++i) {
+                    rTypeConstituents.push_back(builder.createCompositeExtract(constituent, elementRType, i));
+                }
+                constituents[c] = createCompositeConstruct(lType, rTypeConstituents);
+            }
+        }
+    }
+    return builder.createCompositeConstruct(resultTypeId, constituents);
+}
+
 bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TIntermAggregate* node)
 {
     SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder);
@@ -2013,8 +2357,14 @@
         spec_constant_op_mode_setter.turnOnSpecConstantOpMode();
 
     spv::Id result = spv::NoResult;
-    spv::Id invertedType = spv::NoType;  // to use to override the natural type of the node
-    auto resultType = [&invertedType, &node, this](){ return invertedType != spv::NoType ? invertedType : convertGlslangToSpvType(node->getType()); };
+    spv::Id invertedType = spv::NoType;                     // to use to override the natural type of the node
+    std::vector<spv::Builder::AccessChain> complexLvalues;  // for holding swizzling l-values too complex for
+                                                            // SPIR-V, for an out parameter
+    std::vector<spv::Id> temporaryLvalues;                  // temporaries to pass, as proxies for complexLValues
+
+    auto resultType = [&invertedType, &node, this](){ return invertedType != spv::NoType ?
+        invertedType :
+        convertGlslangToSpvType(node->getType()); };
 
     // try texturing
     result = createImageTextureFunctionCall(node);
@@ -2023,14 +2373,15 @@
         builder.setAccessChainRValue(result);
 
         return false;
-    } else if (node->getOp() == glslang::EOpImageStore ||
-#ifdef AMD_EXTENSIONS
+    }
+#ifndef GLSLANG_WEB
+    else if (node->getOp() == glslang::EOpImageStore ||
         node->getOp() == glslang::EOpImageStoreLod ||
-#endif
         node->getOp() == glslang::EOpImageAtomicStore) {
         // "imageStore" is a special case, which has no result
         return false;
     }
+#endif
 
     glslang::TOperator binOp = glslang::EOpNull;
     bool reduceComparison = true;
@@ -2038,6 +2389,8 @@
     bool noReturnValue = false;
     bool atomic = false;
 
+    spv::Builder::AccessChain::CoherentFlags lvalueCoherentFlags;
+
     assert(node->getOp());
 
     spv::Decoration precision = TranslatePrecisionDecoration(node->getOperationPrecision());
@@ -2115,7 +2468,6 @@
         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
         if (result) {
             builder.clearAccessChain();
             builder.setAccessChainRValue(result);
@@ -2235,7 +2587,7 @@
     {
         builder.setLine(node->getLoc().line, node->getLoc().getFilename());
         std::vector<spv::Id> arguments;
-        translateArguments(*node, arguments);
+        translateArguments(*node, arguments, lvalueCoherentFlags);
         spv::Id constructed;
         if (node->getOp() == glslang::EOpConstructTextureSampler)
             constructed = builder.createOp(spv::OpSampledImage, resultType(), arguments);
@@ -2245,7 +2597,7 @@
             std::vector<spv::Id> constituents;
             for (int c = 0; c < (int)arguments.size(); ++c)
                 constituents.push_back(arguments[c]);
-            constructed = builder.createCompositeConstruct(resultType(), constituents);
+            constructed = createCompositeConstruct(resultType(), constituents);
         } else if (isMatrix)
             constructed = builder.createMatrixConstructor(precision, arguments, resultType());
         else
@@ -2298,6 +2650,7 @@
         // which can be emitted by the one in createBinaryOperation()
         binOp = glslang::EOpMod;
         break;
+
     case glslang::EOpEmitVertex:
     case glslang::EOpEndPrimitive:
     case glslang::EOpBarrier:
@@ -2321,10 +2674,6 @@
         // These all have 0 operands and will naturally finish up in the code below for 0 operands
         break;
 
-    case glslang::EOpAtomicStore:
-        noReturnValue = true;
-        // fallthrough
-    case glslang::EOpAtomicLoad:
     case glslang::EOpAtomicAdd:
     case glslang::EOpAtomicMin:
     case glslang::EOpAtomicMax:
@@ -2336,6 +2685,14 @@
         atomic = true;
         break;
 
+#ifndef GLSLANG_WEB
+    case glslang::EOpAtomicStore:
+        noReturnValue = true;
+        // fallthrough
+    case glslang::EOpAtomicLoad:
+        atomic = true;
+        break;
+
     case glslang::EOpAtomicCounterAdd:
     case glslang::EOpAtomicCounterSubtract:
     case glslang::EOpAtomicCounterMin:
@@ -2350,19 +2707,68 @@
         atomic = true;
         break;
 
-#ifdef NV_EXTENSIONS
-    case glslang::EOpIgnoreIntersectionNV:
-    case glslang::EOpTerminateRayNV:
-    case glslang::EOpTraceNV:
-    case glslang::EOpExecuteCallableNV:
+    case glslang::EOpAbsDifference:
+    case glslang::EOpAddSaturate:
+    case glslang::EOpSubSaturate:
+    case glslang::EOpAverage:
+    case glslang::EOpAverageRounded:
+    case glslang::EOpMul32x16:
+        builder.addCapability(spv::CapabilityIntegerFunctions2INTEL);
+        builder.addExtension("SPV_INTEL_shader_integer_functions2");
+        binOp = node->getOp();
+        break;
+
+    case glslang::EOpIgnoreIntersection:
+    case glslang::EOpTerminateRay:
+    case glslang::EOpTrace:
+    case glslang::EOpExecuteCallable:
     case glslang::EOpWritePackedPrimitiveIndices4x8NV:
         noReturnValue = true;
         break;
-#endif
+    case glslang::EOpRayQueryInitialize:
+    case glslang::EOpRayQueryTerminate:
+    case glslang::EOpRayQueryGenerateIntersection:
+    case glslang::EOpRayQueryConfirmIntersection:
+        builder.addExtension("SPV_KHR_ray_query");
+        builder.addCapability(spv::CapabilityRayQueryProvisionalKHR);
+        noReturnValue = true;
+        break;
+    case glslang::EOpRayQueryProceed:
+    case glslang::EOpRayQueryGetIntersectionType:
+    case glslang::EOpRayQueryGetRayTMin:
+    case glslang::EOpRayQueryGetRayFlags:
+    case glslang::EOpRayQueryGetIntersectionT:
+    case glslang::EOpRayQueryGetIntersectionInstanceCustomIndex:
+    case glslang::EOpRayQueryGetIntersectionInstanceId:
+    case glslang::EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset:
+    case glslang::EOpRayQueryGetIntersectionGeometryIndex:
+    case glslang::EOpRayQueryGetIntersectionPrimitiveIndex:
+    case glslang::EOpRayQueryGetIntersectionBarycentrics:
+    case glslang::EOpRayQueryGetIntersectionFrontFace:
+    case glslang::EOpRayQueryGetIntersectionCandidateAABBOpaque:
+    case glslang::EOpRayQueryGetIntersectionObjectRayDirection:
+    case glslang::EOpRayQueryGetIntersectionObjectRayOrigin:
+    case glslang::EOpRayQueryGetWorldRayDirection:
+    case glslang::EOpRayQueryGetWorldRayOrigin:
+    case glslang::EOpRayQueryGetIntersectionObjectToWorld:
+    case glslang::EOpRayQueryGetIntersectionWorldToObject:
+        builder.addExtension("SPV_KHR_ray_query");
+        builder.addCapability(spv::CapabilityRayQueryProvisionalKHR);
+        break;
     case glslang::EOpCooperativeMatrixLoad:
     case glslang::EOpCooperativeMatrixStore:
         noReturnValue = true;
         break;
+    case glslang::EOpBeginInvocationInterlock:
+    case glslang::EOpEndInvocationInterlock:
+        builder.addExtension(spv::E_SPV_EXT_fragment_shader_interlock);
+        noReturnValue = true;
+        break;
+#endif
+
+    case glslang::EOpDebugPrintf:
+        noReturnValue = true;
+        break;
 
     default:
         break;
@@ -2410,26 +2816,33 @@
         // special case l-value operands; there are just a few
         bool lvalue = false;
         switch (node->getOp()) {
-        case glslang::EOpFrexp:
         case glslang::EOpModf:
             if (arg == 1)
                 lvalue = true;
             break;
-        case glslang::EOpInterpolateAtSample:
-        case glslang::EOpInterpolateAtOffset:
-#ifdef AMD_EXTENSIONS
-        case glslang::EOpInterpolateAtVertex:
-#endif
-            if (arg == 0) {
-                lvalue = true;
 
-                // Does it need a swizzle inversion?  If so, evaluation is inverted;
-                // operate first on the swizzle base, then apply the swizzle.
-                if (glslangOperands[0]->getAsOperator() &&
-                    glslangOperands[0]->getAsOperator()->getOp() == glslang::EOpVectorSwizzle)
-                    invertedType = convertGlslangToSpvType(glslangOperands[0]->getAsBinaryNode()->getLeft()->getType());
-            }
+        case glslang::EOpRayQueryInitialize:
+        case glslang::EOpRayQueryTerminate:
+        case glslang::EOpRayQueryConfirmIntersection:
+        case glslang::EOpRayQueryProceed:
+        case glslang::EOpRayQueryGenerateIntersection:
+        case glslang::EOpRayQueryGetIntersectionType:
+        case glslang::EOpRayQueryGetIntersectionT:
+        case glslang::EOpRayQueryGetIntersectionInstanceCustomIndex:
+        case glslang::EOpRayQueryGetIntersectionInstanceId:
+        case glslang::EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset:
+        case glslang::EOpRayQueryGetIntersectionGeometryIndex:
+        case glslang::EOpRayQueryGetIntersectionPrimitiveIndex:
+        case glslang::EOpRayQueryGetIntersectionBarycentrics:
+        case glslang::EOpRayQueryGetIntersectionFrontFace:
+        case glslang::EOpRayQueryGetIntersectionObjectRayDirection:
+        case glslang::EOpRayQueryGetIntersectionObjectRayOrigin:
+        case glslang::EOpRayQueryGetIntersectionObjectToWorld:
+        case glslang::EOpRayQueryGetIntersectionWorldToObject:
+            if (arg == 0)
+                lvalue = true;
             break;
+
         case glslang::EOpAtomicAdd:
         case glslang::EOpAtomicMin:
         case glslang::EOpAtomicMax:
@@ -2438,6 +2851,33 @@
         case glslang::EOpAtomicXor:
         case glslang::EOpAtomicExchange:
         case glslang::EOpAtomicCompSwap:
+            if (arg == 0)
+                lvalue = true;
+            break;
+
+#ifndef GLSLANG_WEB
+        case glslang::EOpFrexp:
+            if (arg == 1)
+                lvalue = true;
+            break;
+        case glslang::EOpInterpolateAtSample:
+        case glslang::EOpInterpolateAtOffset:
+        case glslang::EOpInterpolateAtVertex:
+            if (arg == 0) {
+                lvalue = true;
+
+                // Does it need a swizzle inversion?  If so, evaluation is inverted;
+                // operate first on the swizzle base, then apply the swizzle.
+                // That is, we transform
+                //
+                //    interpolate(v.zy)  ->  interpolate(v).zy
+                //
+                if (glslangOperands[0]->getAsOperator() &&
+                    glslangOperands[0]->getAsOperator()->getOp() == glslang::EOpVectorSwizzle)
+                    invertedType = convertGlslangToSpvType(
+                        glslangOperands[0]->getAsBinaryNode()->getLeft()->getType());
+            }
+            break;
         case glslang::EOpAtomicLoad:
         case glslang::EOpAtomicStore:
         case glslang::EOpAtomicCounterAdd:
@@ -2470,6 +2910,7 @@
             if (arg == 1)
                 lvalue = true;
             break;
+#endif
         default:
             break;
         }
@@ -2479,6 +2920,7 @@
         else
             glslangOperands[arg]->traverse(this);
 
+#ifndef GLSLANG_WEB
         if (node->getOp() == glslang::EOpCooperativeMatrixLoad ||
             node->getOp() == glslang::EOpCooperativeMatrixStore) {
 
@@ -2493,8 +2935,9 @@
                 builder.setAccessChain(save);
 
                 // Point to the first element of the array.
-                builder.accessChainPush(elementId, TranslateCoherent(glslangOperands[arg]->getAsTyped()->getType()),
-                                                   glslangOperands[arg]->getAsTyped()->getType().getBufferReferenceAlignment());
+                builder.accessChainPush(elementId,
+                    TranslateCoherent(glslangOperands[arg]->getAsTyped()->getType()),
+                                      glslangOperands[arg]->getAsTyped()->getType().getBufferReferenceAlignment());
 
                 spv::Builder::AccessChain::CoherentFlags coherentFlags = builder.getAccessChain().coherentFlags;
                 unsigned int alignment = builder.getAccessChain().alignment;
@@ -2504,7 +2947,8 @@
                     memoryAccess &= ~spv::MemoryAccessMakePointerAvailableKHRMask;
                 if (node->getOp() == glslang::EOpCooperativeMatrixStore)
                     memoryAccess &= ~spv::MemoryAccessMakePointerVisibleKHRMask;
-                if (builder.getStorageClass(builder.getAccessChain().base) == spv::StorageClassPhysicalStorageBufferEXT) {
+                if (builder.getStorageClass(builder.getAccessChain().base) ==
+                    spv::StorageClassPhysicalStorageBufferEXT) {
                     memoryAccess = (spv::MemoryAccessMask)(memoryAccess | spv::MemoryAccessAlignedMask);
                 }
 
@@ -2514,23 +2958,63 @@
                     memoryAccessOperands.push_back(spv::IdImmediate(false, alignment));
                 }
 
-                if (memoryAccess & (spv::MemoryAccessMakePointerAvailableKHRMask | spv::MemoryAccessMakePointerVisibleKHRMask)) {
-                    memoryAccessOperands.push_back(spv::IdImmediate(true, builder.makeUintConstant(TranslateMemoryScope(coherentFlags))));
+                if (memoryAccess &
+                    (spv::MemoryAccessMakePointerAvailableKHRMask | spv::MemoryAccessMakePointerVisibleKHRMask)) {
+                    memoryAccessOperands.push_back(spv::IdImmediate(true,
+                        builder.makeUintConstant(TranslateMemoryScope(coherentFlags))));
                 }
             } else if (arg == 2) {
                 continue;
             }
         }
+#endif
 
-        if (lvalue)
-            operands.push_back(builder.accessChainGetLValue());
-        else {
+        // for l-values, pass the address, for r-values, pass the value
+        if (lvalue) {
+            if (invertedType == spv::NoType && !builder.isSpvLvalue()) {
+                // SPIR-V cannot represent an l-value containing a swizzle that doesn't
+                // reduce to a simple access chain.  So, we need a temporary vector to
+                // receive the result, and must later swizzle that into the original
+                // l-value.
+                complexLvalues.push_back(builder.getAccessChain());
+                temporaryLvalues.push_back(builder.createVariable(spv::StorageClassFunction,
+                    builder.accessChainGetInferredType(), "swizzleTemp"));
+                operands.push_back(temporaryLvalues.back());
+            } else {
+                operands.push_back(builder.accessChainGetLValue());
+            }
+            lvalueCoherentFlags = builder.getAccessChain().coherentFlags;
+            lvalueCoherentFlags |= TranslateCoherent(glslangOperands[arg]->getAsTyped()->getType());
+        } else {
             builder.setLine(node->getLoc().line, node->getLoc().getFilename());
-            operands.push_back(accessChainLoad(glslangOperands[arg]->getAsTyped()->getType()));
+             glslang::TOperator glslangOp = node->getOp();
+             if (arg == 1 &&
+                (glslangOp == glslang::EOpRayQueryGetIntersectionType ||
+                 glslangOp == glslang::EOpRayQueryGetIntersectionT ||
+                 glslangOp == glslang::EOpRayQueryGetIntersectionInstanceCustomIndex ||
+                 glslangOp == glslang::EOpRayQueryGetIntersectionInstanceId ||
+                 glslangOp == glslang::EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset ||
+                 glslangOp == glslang::EOpRayQueryGetIntersectionGeometryIndex ||
+                 glslangOp == glslang::EOpRayQueryGetIntersectionPrimitiveIndex ||
+                 glslangOp == glslang::EOpRayQueryGetIntersectionBarycentrics ||
+                 glslangOp == glslang::EOpRayQueryGetIntersectionFrontFace ||
+                 glslangOp == glslang::EOpRayQueryGetIntersectionObjectRayDirection ||
+                 glslangOp == glslang::EOpRayQueryGetIntersectionObjectRayOrigin ||
+                 glslangOp == glslang::EOpRayQueryGetIntersectionObjectToWorld ||
+                 glslangOp == glslang::EOpRayQueryGetIntersectionWorldToObject
+                    )) {
+                bool cond = glslangOperands[arg]->getAsConstantUnion()->getConstArray()[0].getBConst();
+                operands.push_back(builder.makeIntConstant(cond ? 1 : 0));
+            }
+            else {
+                operands.push_back(accessChainLoad(glslangOperands[arg]->getAsTyped()->getType()));
+            }
+
         }
     }
 
     builder.setLine(node->getLoc().line, node->getLoc().getFilename());
+#ifndef GLSLANG_WEB
     if (node->getOp() == glslang::EOpCooperativeMatrixLoad) {
         std::vector<spv::IdImmediate> idImmOps;
 
@@ -2557,9 +3041,18 @@
 
         builder.createNoResultOp(spv::OpCooperativeMatrixStoreNV, idImmOps);
         result = 0;
-    } else if (atomic) {
+    } else
+#endif
+    if (atomic) {
         // Handle all atomics
-        result = createAtomicOperation(node->getOp(), precision, resultType(), operands, node->getBasicType());
+        result = createAtomicOperation(node->getOp(), precision, resultType(), operands, node->getBasicType(),
+            lvalueCoherentFlags);
+    } else if (node->getOp() == glslang::EOpDebugPrintf) {
+        if (!nonSemanticDebugPrintf) {
+            nonSemanticDebugPrintf = builder.import("NonSemantic.DebugPrintf");
+        }
+        result = builder.createBuiltinCall(builder.makeVoidType(), nonSemanticDebugPrintf, spv::NonSemanticDebugPrintfDebugPrintf, operands);
+        builder.addExtension(spv::E_SPV_KHR_non_semantic_info);
     } else {
         // Pass through to generic operations.
         switch (glslangOperands.size()) {
@@ -2574,15 +3067,21 @@
                 result = createUnaryOperation(
                     node->getOp(), decorations,
                     resultType(), operands.front(),
-                    glslangOperands[0]->getAsTyped()->getBasicType());
+                    glslangOperands[0]->getAsTyped()->getBasicType(), lvalueCoherentFlags);
             }
             break;
         default:
             result = createMiscOperation(node->getOp(), precision, resultType(), operands, node->getBasicType());
             break;
         }
-        if (invertedType)
+
+        if (invertedType != spv::NoResult)
             result = createInvertedSwizzle(precision, *glslangOperands[0]->getAsBinaryNode(), result);
+
+        for (unsigned int i = 0; i < temporaryLvalues.size(); ++i) {
+            builder.setAccessChain(complexLvalues[i]);
+            builder.accessChainStore(builder.createLoad(temporaryLvalues[i]));
+        }
     }
 
     if (noReturnValue)
@@ -2609,6 +3108,19 @@
 // next layer copies r-values into memory to use the access-chain mechanism
 bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang::TIntermSelection* node)
 {
+    // see if OpSelect can handle it
+    const auto isOpSelectable = [&]() {
+        if (node->getBasicType() == glslang::EbtVoid)
+            return false;
+        // OpSelect can do all other types starting with SPV 1.4
+        if (glslangIntermediate->getSpv().spv < glslang::EShTargetSpv_1_4) {
+            // pre-1.4, only scalars and vectors can be handled
+            if ((!node->getType().isScalar() && !node->getType().isVector()))
+                return false;
+        }
+        return true;
+    };
+
     // See if it simple and safe, or required, to execute both sides.
     // Crucially, side effects must be either semantically required or avoided,
     // and there are performance trade-offs.
@@ -2627,9 +3139,7 @@
 
         // if not required to execute both, decide based on performance/practicality...
 
-        // see if OpSelect can handle it
-        if ((!node->getType().isScalar() && !node->getType().isVector()) ||
-            node->getBasicType() == glslang::EbtVoid)
+        if (!isOpSelectable())
             return false;
 
         assert(node->getType() == node->getTrueBlock() ->getAsTyped()->getType() &&
@@ -2666,14 +3176,16 @@
         // emit code to select between trueValue and falseValue
 
         // see if OpSelect can handle it
-        if (node->getType().isScalar() || node->getType().isVector()) {
+        if (isOpSelectable()) {
             // Emit OpSelect for this selection.
 
             // smear condition to vector, if necessary (AST is always scalar)
-            if (builder.isVector(trueValue))
+            // Before 1.4, smear like for mix(), starting with 1.4, keep it scalar
+            if (glslangIntermediate->getSpv().spv < glslang::EShTargetSpv_1_4 && builder.isVector(trueValue)) {
                 condition = builder.smearScalar(spv::NoPrecision, condition, 
                                                 builder.makeVectorType(builder.makeBoolType(),
                                                                        builder.getNumComponents(trueValue)));
+            }
 
             // OpSelect
             result = builder.createTriOp(spv::OpSelect,
@@ -2776,7 +3288,8 @@
             defaultSegment = (int)codeSegments.size();
         else if (child->getAsBranchNode() && child->getAsBranchNode()->getFlowOp() == glslang::EOpCase) {
             valueIndexToSegment[caseValues.size()] = (int)codeSegments.size();
-            caseValues.push_back(child->getAsBranchNode()->getExpression()->getAsConstantUnion()->getConstArray()[0].getIConst());
+            caseValues.push_back(child->getAsBranchNode()->getExpression()->getAsConstantUnion()
+                ->getConstArray()[0].getIConst());
         } else
             codeSegments.push_back(child);
     }
@@ -2789,7 +3302,8 @@
 
     // make the switch statement
     std::vector<spv::Block*> segmentBlocks; // returned, as the blocks allocated in the call
-    builder.makeSwitch(selector, control, (int)codeSegments.size(), caseValues, valueIndexToSegment, defaultSegment, segmentBlocks);
+    builder.makeSwitch(selector, control, (int)codeSegments.size(), caseValues, valueIndexToSegment, defaultSegment,
+        segmentBlocks);
 
     // emit all the code in the segments
     breakForLoop.push(false);
@@ -2822,8 +3336,8 @@
     builder.createBranch(&blocks.head);
 
     // Loop control:
-    unsigned int dependencyLength = glslang::TIntermLoop::dependencyInfinite;
-    const spv::LoopControlMask control = TranslateLoopControl(*node, dependencyLength);
+    std::vector<unsigned int> operands;
+    const spv::LoopControlMask control = TranslateLoopControl(*node, operands);
 
     // Spec requires back edges to target header blocks, and every header block
     // must dominate its merge block.  Make a header block first to ensure these
@@ -2833,7 +3347,7 @@
     // including merges of its own.
     builder.setLine(node->getLoc().line, node->getLoc().getFilename());
     builder.setBuildPoint(&blocks.head);
-    builder.createLoopMerge(&blocks.merge, &blocks.continue_target, control, dependencyLength);
+    builder.createLoopMerge(&blocks.merge, &blocks.continue_target, control, operands);
     if (node->testFirst() && node->getTest()) {
         spv::Block& test = builder.makeNewBlock();
         builder.createBranch(&test);
@@ -2923,6 +3437,14 @@
         builder.clearAccessChain();
         break;
 
+#ifndef GLSLANG_WEB
+    case glslang::EOpDemote:
+        builder.createNoResultOp(spv::OpDemoteToHelperInvocationEXT);
+        builder.addExtension(spv::E_SPV_EXT_demote_to_helper_invocation);
+        builder.addCapability(spv::CapabilityDemoteToHelperInvocationEXT);
+        break;
+#endif
+
     default:
         assert(0);
         break;
@@ -2931,7 +3453,7 @@
     return false;
 }
 
-spv::Id TGlslangToSpvTraverser::createSpvVariable(const glslang::TIntermSymbol* node)
+spv::Id TGlslangToSpvTraverser::createSpvVariable(const glslang::TIntermSymbol* node, spv::Id forcedType)
 {
     // First, steer off constants, which are not SPIR-V variables, but
     // can still have a mapping to a SPIR-V Id.
@@ -2944,51 +3466,57 @@
 
     // Now, handle actual variables
     spv::StorageClass storageClass = TranslateStorageClass(node->getType());
-    spv::Id spvType = convertGlslangToSpvType(node->getType());
+    spv::Id spvType = forcedType == spv::NoType ? convertGlslangToSpvType(node->getType())
+                                                : forcedType;
 
-    const bool contains16BitType = node->getType().containsBasicType(glslang::EbtFloat16) ||
-                                   node->getType().containsBasicType(glslang::EbtInt16)   ||
-                                   node->getType().containsBasicType(glslang::EbtUint16);
+    const bool contains16BitType = node->getType().contains16BitFloat() ||
+                                   node->getType().contains16BitInt();
     if (contains16BitType) {
         switch (storageClass) {
         case spv::StorageClassInput:
         case spv::StorageClassOutput:
-            addPre13Extension(spv::E_SPV_KHR_16bit_storage);
+            builder.addIncorporatedExtension(spv::E_SPV_KHR_16bit_storage, spv::Spv_1_3);
             builder.addCapability(spv::CapabilityStorageInputOutput16);
             break;
-        case spv::StorageClassPushConstant:
-            addPre13Extension(spv::E_SPV_KHR_16bit_storage);
-            builder.addCapability(spv::CapabilityStoragePushConstant16);
-            break;
         case spv::StorageClassUniform:
-            addPre13Extension(spv::E_SPV_KHR_16bit_storage);
+            builder.addIncorporatedExtension(spv::E_SPV_KHR_16bit_storage, spv::Spv_1_3);
             if (node->getType().getQualifier().storage == glslang::EvqBuffer)
                 builder.addCapability(spv::CapabilityStorageUniformBufferBlock16);
             else
                 builder.addCapability(spv::CapabilityStorageUniform16);
             break;
+#ifndef GLSLANG_WEB
+        case spv::StorageClassPushConstant:
+            builder.addIncorporatedExtension(spv::E_SPV_KHR_16bit_storage, spv::Spv_1_3);
+            builder.addCapability(spv::CapabilityStoragePushConstant16);
+            break;
         case spv::StorageClassStorageBuffer:
         case spv::StorageClassPhysicalStorageBufferEXT:
-            addPre13Extension(spv::E_SPV_KHR_16bit_storage);
+            builder.addIncorporatedExtension(spv::E_SPV_KHR_16bit_storage, spv::Spv_1_3);
             builder.addCapability(spv::CapabilityStorageUniformBufferBlock16);
             break;
+#endif
         default:
+            if (node->getType().contains16BitFloat())
+                builder.addCapability(spv::CapabilityFloat16);
+            if (node->getType().contains16BitInt())
+                builder.addCapability(spv::CapabilityInt16);
             break;
         }
     }
 
-    const bool contains8BitType = node->getType().containsBasicType(glslang::EbtInt8)   ||
-                                  node->getType().containsBasicType(glslang::EbtUint8);
-    if (contains8BitType) {
+    if (node->getType().contains8BitInt()) {
         if (storageClass == spv::StorageClassPushConstant) {
-            builder.addExtension(spv::E_SPV_KHR_8bit_storage);
+            builder.addIncorporatedExtension(spv::E_SPV_KHR_8bit_storage, spv::Spv_1_5);
             builder.addCapability(spv::CapabilityStoragePushConstant8);
         } else if (storageClass == spv::StorageClassUniform) {
-            builder.addExtension(spv::E_SPV_KHR_8bit_storage);
+            builder.addIncorporatedExtension(spv::E_SPV_KHR_8bit_storage, spv::Spv_1_5);
             builder.addCapability(spv::CapabilityUniformAndStorageBuffer8BitAccess);
         } else if (storageClass == spv::StorageClassStorageBuffer) {
-            builder.addExtension(spv::E_SPV_KHR_8bit_storage);
+            builder.addIncorporatedExtension(spv::E_SPV_KHR_8bit_storage, spv::Spv_1_5);
             builder.addCapability(spv::CapabilityStorageBuffer8BitAccess);
+        } else {
+            builder.addCapability(spv::CapabilityInt8);
         }
     }
 
@@ -3003,15 +3531,15 @@
 spv::Id TGlslangToSpvTraverser::getSampledType(const glslang::TSampler& sampler)
 {
     switch (sampler.type) {
+        case glslang::EbtInt:      return builder.makeIntType(32);
+        case glslang::EbtUint:     return builder.makeUintType(32);
         case glslang::EbtFloat:    return builder.makeFloatType(32);
-#ifdef AMD_EXTENSIONS
+#ifndef GLSLANG_WEB
         case glslang::EbtFloat16:
             builder.addExtension(spv::E_SPV_AMD_gpu_shader_half_float_fetch);
             builder.addCapability(spv::CapabilityFloat16ImageAMD);
             return builder.makeFloatType(16);
 #endif
-        case glslang::EbtInt:      return builder.makeIntType(32);
-        case glslang::EbtUint:     return builder.makeUintType(32);
         default:
             assert(0);
             return builder.makeFloatType(32);
@@ -3032,7 +3560,8 @@
 
 // When inverting a swizzle with a parent op, this function
 // will apply the swizzle operation to a completed parent operation.
-spv::Id TGlslangToSpvTraverser::createInvertedSwizzle(spv::Decoration precision, const glslang::TIntermTyped& node, spv::Id parentResult)
+spv::Id TGlslangToSpvTraverser::createInvertedSwizzle(spv::Decoration precision, const glslang::TIntermTyped& node,
+    spv::Id parentResult)
 {
     std::vector<unsigned> swizzle;
     convertSwizzle(*node.getAsBinaryNode()->getRight()->getAsAggregate(), swizzle);
@@ -3069,15 +3598,6 @@
         spvType = builder.makeVoidType();
         assert (! type.isArray());
         break;
-    case glslang::EbtFloat:
-        spvType = builder.makeFloatType(32);
-        break;
-    case glslang::EbtDouble:
-        spvType = builder.makeFloatType(64);
-        break;
-    case glslang::EbtFloat16:
-        spvType = builder.makeFloatType(16);
-        break;
     case glslang::EbtBool:
         // "transparent" bool doesn't exist in SPIR-V.  The GLSL convention is
         // a 32-bit int where non-0 means true.
@@ -3086,6 +3606,22 @@
         else
             spvType = builder.makeBoolType();
         break;
+    case glslang::EbtInt:
+        spvType = builder.makeIntType(32);
+        break;
+    case glslang::EbtUint:
+        spvType = builder.makeUintType(32);
+        break;
+    case glslang::EbtFloat:
+        spvType = builder.makeFloatType(32);
+        break;
+#ifndef GLSLANG_WEB
+    case glslang::EbtDouble:
+        spvType = builder.makeFloatType(64);
+        break;
+    case glslang::EbtFloat16:
+        spvType = builder.makeFloatType(16);
+        break;
     case glslang::EbtInt8:
         spvType = builder.makeIntType(8);
         break;
@@ -3098,12 +3634,6 @@
     case glslang::EbtUint16:
         spvType = builder.makeUintType(16);
         break;
-    case glslang::EbtInt:
-        spvType = builder.makeIntType(32);
-        break;
-    case glslang::EbtUint:
-        spvType = builder.makeUintType(32);
-        break;
     case glslang::EbtInt64:
         spvType = builder.makeIntType(64);
         break;
@@ -3114,22 +3644,41 @@
         builder.addCapability(spv::CapabilityAtomicStorage);
         spvType = builder.makeUintType(32);
         break;
-#ifdef NV_EXTENSIONS
-    case glslang::EbtAccStructNV:
-        spvType = builder.makeAccelerationStructureNVType();
+    case glslang::EbtAccStruct:
+        spvType = builder.makeAccelerationStructureType();
+        break;
+    case glslang::EbtRayQuery:
+        spvType = builder.makeRayQueryType();
+        break;
+    case glslang::EbtReference:
+        {
+            // Make the forward pointer, then recurse to convert the structure type, then
+            // patch up the forward pointer with a real pointer type.
+            if (forwardPointers.find(type.getReferentType()) == forwardPointers.end()) {
+                spv::Id forwardId = builder.makeForwardPointer(spv::StorageClassPhysicalStorageBufferEXT);
+                forwardPointers[type.getReferentType()] = forwardId;
+            }
+            spvType = forwardPointers[type.getReferentType()];
+            if (!forwardReferenceOnly) {
+                spv::Id referentType = convertGlslangToSpvType(*type.getReferentType());
+                builder.makePointerFromForwardPointer(spv::StorageClassPhysicalStorageBufferEXT,
+                                                      forwardPointers[type.getReferentType()],
+                                                      referentType);
+            }
+        }
         break;
 #endif
     case glslang::EbtSampler:
         {
             const glslang::TSampler& sampler = type.getSampler();
-            if (sampler.sampler) {
-                // pure sampler
+            if (sampler.isPureSampler()) {
                 spvType = builder.makeSamplerType();
             } else {
                 // an image is present, make its type
-                spvType = builder.makeImageType(getSampledType(sampler), TranslateDimensionality(sampler), sampler.shadow, sampler.arrayed, sampler.ms,
-                                                sampler.image ? 2 : 1, TranslateImageFormat(type));
-                if (sampler.combined) {
+                spvType = builder.makeImageType(getSampledType(sampler), TranslateDimensionality(sampler),
+                                                sampler.isShadow(), sampler.isArrayed(), sampler.isMultiSample(),
+                                                sampler.isImageClass() ? 2 : 1, TranslateImageFormat(type));
+                if (sampler.isCombined()) {
                     // already has both image and sampler, make the combined type
                     spvType = builder.makeSampledImageType(spvType);
                 }
@@ -3151,27 +3700,13 @@
 
             // else, we haven't seen it...
             if (type.getBasicType() == glslang::EbtBlock)
-                memberRemapper[glslangMembers].resize(glslangMembers->size());
+                memberRemapper[glslangTypeToIdMap[glslangMembers]].resize(glslangMembers->size());
             spvType = convertGlslangStructToSpvType(type, glslangMembers, explicitLayout, qualifier);
         }
         break;
-    case glslang::EbtReference:
-        {
-            // Make the forward pointer, then recurse to convert the structure type, then
-            // patch up the forward pointer with a real pointer type.
-            if (forwardPointers.find(type.getReferentType()) == forwardPointers.end()) {
-                spv::Id forwardId = builder.makeForwardPointer(spv::StorageClassPhysicalStorageBufferEXT);
-                forwardPointers[type.getReferentType()] = forwardId;
-            }
-            spvType = forwardPointers[type.getReferentType()];
-            if (!forwardReferenceOnly) {
-                spv::Id referentType = convertGlslangToSpvType(*type.getReferentType());
-                builder.makePointerFromForwardPointer(spv::StorageClassPhysicalStorageBufferEXT,
-                                                      forwardPointers[type.getReferentType()],
-                                                      referentType);
-            }
-        }
-        break;
+    case glslang::EbtString:
+        // no type used for OpString
+        return 0;
     default:
         assert(0);
         break;
@@ -3190,6 +3725,10 @@
         builder.addExtension(spv::E_SPV_NV_cooperative_matrix);
         if (type.getBasicType() == glslang::EbtFloat16)
             builder.addCapability(spv::CapabilityFloat16);
+        if (type.getBasicType() == glslang::EbtUint8 ||
+            type.getBasicType() == glslang::EbtInt8) {
+            builder.addCapability(spv::CapabilityInt8);
+        }
 
         spv::Id scope = makeArraySizeId(*type.getTypeParameters(), 1);
         spv::Id rows = makeArraySizeId(*type.getTypeParameters(), 2);
@@ -3236,10 +3775,12 @@
         if (type.isSizedArray())
             spvType = builder.makeArrayType(spvType, makeArraySizeId(*type.getArraySizes(), 0), stride);
         else {
+#ifndef GLSLANG_WEB
             if (!lastBufferBlockMember) {
-                builder.addExtension("SPV_EXT_descriptor_indexing");
+                builder.addIncorporatedExtension("SPV_EXT_descriptor_indexing", spv::Spv_1_5);
                 builder.addCapability(spv::CapabilityRuntimeDescriptorArrayEXT);
             }
+#endif
             spvType = builder.makeRuntimeArray(spvType);
         }
         if (stride > 0)
@@ -3255,7 +3796,7 @@
 //
 bool TGlslangToSpvTraverser::filterMember(const glslang::TType& member)
 {
-#ifdef NV_EXTENSIONS
+#ifndef GLSLANG_WEB
     auto& extensions = glslangIntermediate->getRequestedExtensions();
 
     if (member.getFieldName() == "gl_SecondaryViewportMaskNV" &&
@@ -3291,19 +3832,23 @@
 {
     // Create a vector of struct types for SPIR-V to consume
     std::vector<spv::Id> spvMembers;
-    int memberDelta = 0;  // how much the member's index changes from glslang to SPIR-V, normally 0, except sometimes for blocks
+    int memberDelta = 0;  // how much the member's index changes from glslang to SPIR-V, normally 0,
+                          // except sometimes for blocks
     std::vector<std::pair<glslang::TType*, glslang::TQualifier> > deferredForwardPointers;
     for (int i = 0; i < (int)glslangMembers->size(); i++) {
         glslang::TType& glslangMember = *(*glslangMembers)[i].type;
         if (glslangMember.hiddenMember()) {
             ++memberDelta;
             if (type.getBasicType() == glslang::EbtBlock)
-                memberRemapper[glslangMembers][i] = -1;
+                memberRemapper[glslangTypeToIdMap[glslangMembers]][i] = -1;
         } else {
             if (type.getBasicType() == glslang::EbtBlock) {
-                memberRemapper[glslangMembers][i] = i - memberDelta;
-                if (filterMember(glslangMember))
+                if (filterMember(glslangMember)) {
+                    memberDelta++;
+                    memberRemapper[glslangTypeToIdMap[glslangMembers]][i] = -1;
                     continue;
+                }
+                memberRemapper[glslangTypeToIdMap[glslangMembers]][i] = i - memberDelta;
             }
             // modify just this child's view of the qualifier
             glslang::TQualifier memberQualifier = glslangMember.getQualifier();
@@ -3319,15 +3864,17 @@
 
             // Make forward pointers for any pointer members, and create a list of members to
             // convert to spirv types after creating the struct.
-            if (glslangMember.getBasicType() == glslang::EbtReference) {
+            if (glslangMember.isReference()) {
                 if (forwardPointers.find(glslangMember.getReferentType()) == forwardPointers.end()) {
                     deferredForwardPointers.push_back(std::make_pair(&glslangMember, memberQualifier));
                 }
                 spvMembers.push_back(
-                    convertGlslangToSpvType(glslangMember, explicitLayout, memberQualifier, lastBufferBlockMember, true));
+                    convertGlslangToSpvType(glslangMember, explicitLayout, memberQualifier, lastBufferBlockMember,
+                        true));
             } else {
                 spvMembers.push_back(
-                    convertGlslangToSpvType(glslangMember, explicitLayout, memberQualifier, lastBufferBlockMember, false));
+                    convertGlslangToSpvType(glslangMember, explicitLayout, memberQualifier, lastBufferBlockMember,
+                        false));
             }
         }
     }
@@ -3361,7 +3908,7 @@
         glslang::TType& glslangMember = *(*glslangMembers)[i].type;
         int member = i;
         if (type.getBasicType() == glslang::EbtBlock) {
-            member = memberRemapper[glslangMembers][i];
+            member = memberRemapper[glslangTypeToIdMap[glslangMembers]][i];
             if (filterMember(glslangMember))
                 continue;
         }
@@ -3386,13 +3933,14 @@
                 glslangIntermediate->getSource() == glslang::EShSourceHlsl) {
                 builder.addMemberDecoration(spvType, member, TranslateInterpolationDecoration(memberQualifier));
                 builder.addMemberDecoration(spvType, member, TranslateAuxiliaryStorageDecoration(memberQualifier));
-#ifdef NV_EXTENSIONS
+#ifndef GLSLANG_WEB
                 addMeshNVDecoration(spvType, member, memberQualifier);
 #endif
             }
         }
         builder.addMemberDecoration(spvType, member, TranslateInvariantDecoration(memberQualifier));
 
+#ifndef GLSLANG_WEB
         if (type.getBasicType() == glslang::EbtBlock &&
             qualifier.storage == glslang::EvqBuffer) {
             // Add memory decorations only to top-level members of shader storage block
@@ -3402,6 +3950,8 @@
                 builder.addMemberDecoration(spvType, member, memory[i]);
         }
 
+#endif
+
         // Location assignment was already completed correctly by the front end,
         // just track whether a member needs to be decorated.
         // Ignore member locations if the container is an array, as that's
@@ -3438,6 +3988,7 @@
         if (builtIn != spv::BuiltInMax)
             builder.addMemberDecoration(spvType, member, spv::DecorationBuiltIn, (int)builtIn);
 
+#ifndef GLSLANG_WEB
         // nonuniform
         builder.addMemberDecoration(spvType, member, TranslateNonUniformDecoration(glslangMember.getQualifier()));
 
@@ -3447,7 +3998,6 @@
                                         memberQualifier.semanticName);
         }
 
-#ifdef NV_EXTENSIONS
         if (builtIn == spv::BuiltInLayer) {
             // SPV_NV_viewport_array2 extension
             if (glslangMember.getQualifier().layoutViewportRelative){
@@ -3512,11 +4062,11 @@
     alignment |= type.getBufferReferenceAlignment();
 
     spv::Id loadedId = builder.accessChainLoad(TranslatePrecisionDecoration(type),
-                                               TranslateNonUniformDecoration(type.getQualifier()),
-                                               nominalTypeId,
-                                               spv::MemoryAccessMask(TranslateMemoryAccess(coherentFlags) & ~spv::MemoryAccessMakePointerAvailableKHRMask),
-                                               TranslateMemoryScope(coherentFlags),
-                                               alignment);
+        TranslateNonUniformDecoration(type.getQualifier()),
+        nominalTypeId,
+        spv::MemoryAccessMask(TranslateMemoryAccess(coherentFlags) & ~spv::MemoryAccessMakePointerAvailableKHRMask),
+        TranslateMemoryScope(coherentFlags),
+        alignment);
 
     // Need to convert to abstract types when necessary
     if (type.getBasicType() == glslang::EbtBool) {
@@ -3530,7 +4080,8 @@
             int vecSize = builder.getNumTypeComponents(nominalTypeId);
             spv::Id bvecType = builder.makeVectorType(builder.makeBoolType(), vecSize);
             if (nominalTypeId != bvecType)
-                loadedId = builder.createBinOp(spv::OpINotEqual, bvecType, loadedId, makeSmearedConstant(builder.makeUintConstant(0), vecSize));
+                loadedId = builder.createBinOp(spv::OpINotEqual, bvecType, loadedId,
+                    makeSmearedConstant(builder.makeUintConstant(0), vecSize));
         }
     }
 
@@ -3579,7 +4130,8 @@
     alignment |= type.getBufferReferenceAlignment();
 
     builder.accessChainStore(rvalue,
-                             spv::MemoryAccessMask(TranslateMemoryAccess(coherentFlags) & ~spv::MemoryAccessMakePointerVisibleKHRMask),
+                             spv::MemoryAccessMask(TranslateMemoryAccess(coherentFlags) &
+                                ~spv::MemoryAccessMakePointerVisibleKHRMask),
                              TranslateMemoryScope(coherentFlags), alignment);
 }
 
@@ -3615,6 +4167,20 @@
     // where the two types were the same type in GLSL. This requires member
     // by member copy, recursively.
 
+    // SPIR-V 1.4 added an instruction to do help do this.
+    if (glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_4) {
+        // However, bool in uniform space is changed to int, so
+        // OpCopyLogical does not work for that.
+        // TODO: It would be more robust to do a full recursive verification of the types satisfying SPIR-V rules.
+        bool rBool = builder.containsType(builder.getTypeId(rValue), spv::OpTypeBool, 0);
+        bool lBool = builder.containsType(lType, spv::OpTypeBool, 0);
+        if (lBool == rBool) {
+            spv::Id logicalCopy = builder.createUnaryOp(spv::OpCopyLogical, lType, rValue);
+            accessChainStore(type, logicalCopy);
+            return;
+        }
+    }
+
     // If an array, copy element by element.
     if (type.isArray()) {
         glslang::TType glslangElementType(type, 0);
@@ -3626,7 +4192,8 @@
             // set up the target storage
             builder.clearAccessChain();
             builder.setAccessChainLValue(lValue);
-            builder.accessChainPush(builder.makeIntConstant(index), TranslateCoherent(type), type.getBufferReferenceAlignment());
+            builder.accessChainPush(builder.makeIntConstant(index), TranslateCoherent(type),
+                type.getBufferReferenceAlignment());
 
             // store the member
             multiTypeStore(glslangElementType, elementRValue);
@@ -3646,7 +4213,8 @@
             // set up the target storage
             builder.clearAccessChain();
             builder.setAccessChainLValue(lValue);
-            builder.accessChainPush(builder.makeIntConstant(m), TranslateCoherent(type), type.getBufferReferenceAlignment());
+            builder.accessChainPush(builder.makeIntConstant(m), TranslateCoherent(type),
+                type.getBufferReferenceAlignment());
 
             // store the member
             multiTypeStore(glslangMemberType, memberRValue);
@@ -3681,18 +4249,21 @@
 }
 
 // Given an array type, returns the integer stride required for that array
-int TGlslangToSpvTraverser::getArrayStride(const glslang::TType& arrayType, glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout)
+int TGlslangToSpvTraverser::getArrayStride(const glslang::TType& arrayType, glslang::TLayoutPacking explicitLayout,
+    glslang::TLayoutMatrix matrixLayout)
 {
     int size;
     int stride;
-    glslangIntermediate->getMemberAlignment(arrayType, size, stride, explicitLayout, matrixLayout == glslang::ElmRowMajor);
+    glslangIntermediate->getMemberAlignment(arrayType, size, stride, explicitLayout,
+        matrixLayout == glslang::ElmRowMajor);
 
     return stride;
 }
 
 // Given a matrix type, or array (of array) of matrixes type, returns the integer stride required for that matrix
 // when used as a member of an interface block
-int TGlslangToSpvTraverser::getMatrixStride(const glslang::TType& matrixType, glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout)
+int TGlslangToSpvTraverser::getMatrixStride(const glslang::TType& matrixType, glslang::TLayoutPacking explicitLayout,
+    glslang::TLayoutMatrix matrixLayout)
 {
     glslang::TType elementType;
     elementType.shallowCopy(matrixType);
@@ -3700,7 +4271,8 @@
 
     int size;
     int stride;
-    glslangIntermediate->getMemberAlignment(elementType, size, stride, explicitLayout, matrixLayout == glslang::ElmRowMajor);
+    glslangIntermediate->getMemberAlignment(elementType, size, stride, explicitLayout,
+        matrixLayout == glslang::ElmRowMajor);
 
     return stride;
 }
@@ -3711,8 +4283,8 @@
 // 'currentOffset' should be passed in already initialized, ready to modify, and reflecting
 // the migration of data from nextOffset -> currentOffset.  It should be -1 on the first call.
 // -1 means a non-forced member offset (no decoration needed).
-void TGlslangToSpvTraverser::updateMemberOffset(const glslang::TType& structType, const glslang::TType& memberType, int& currentOffset, int& nextOffset,
-                                                glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout)
+void TGlslangToSpvTraverser::updateMemberOffset(const glslang::TType& structType, const glslang::TType& memberType,
+    int& currentOffset, int& nextOffset, glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout)
 {
     // this will get a positive value when deemed necessary
     nextOffset = -1;
@@ -3742,7 +4314,8 @@
 
     int memberSize;
     int dummyStride;
-    int memberAlignment = glslangIntermediate->getMemberAlignment(memberType, memberSize, dummyStride, explicitLayout, matrixLayout == glslang::ElmRowMajor);
+    int memberAlignment = glslangIntermediate->getMemberAlignment(memberType, memberSize, dummyStride, explicitLayout,
+        matrixLayout == glslang::ElmRowMajor);
 
     // Adjust alignment for HLSL rules
     // TODO: make this consistent in early phases of code:
@@ -3761,7 +4334,8 @@
     glslang::RoundToPow2(currentOffset, memberAlignment);
 
     // Bump up to vec4 if there is a bad straddle
-    if (explicitLayout != glslang::ElpScalar && glslangIntermediate->improperStraddle(memberType, memberSize, currentOffset))
+    if (explicitLayout != glslang::ElpScalar && glslangIntermediate->improperStraddle(memberType, memberSize,
+        currentOffset))
         glslang::RoundToPow2(currentOffset, 16);
 
     nextOffset = currentOffset + memberSize;
@@ -3772,10 +4346,10 @@
     const glslang::TBuiltInVariable glslangBuiltIn = members[glslangMember].type->getQualifier().builtIn;
     switch (glslangBuiltIn)
     {
+    case glslang::EbvPointSize:
+#ifndef GLSLANG_WEB
     case glslang::EbvClipDistance:
     case glslang::EbvCullDistance:
-    case glslang::EbvPointSize:
-#ifdef NV_EXTENSIONS
     case glslang::EbvViewportMaskNV:
     case glslang::EbvSecondaryPositionNV:
     case glslang::EbvSecondaryViewportMaskNV:
@@ -3833,20 +4407,23 @@
 // Make all the functions, skeletally, without actually visiting their bodies.
 void TGlslangToSpvTraverser::makeFunctions(const glslang::TIntermSequence& glslFunctions)
 {
-    const auto getParamDecorations = [&](std::vector<spv::Decoration>& decorations, const glslang::TType& type, bool useVulkanMemoryModel) {
+    const auto getParamDecorations = [&](std::vector<spv::Decoration>& decorations, const glslang::TType& type,
+        bool useVulkanMemoryModel) {
         spv::Decoration paramPrecision = TranslatePrecisionDecoration(type);
         if (paramPrecision != spv::NoPrecision)
             decorations.push_back(paramPrecision);
         TranslateMemoryDecoration(type.getQualifier(), decorations, useVulkanMemoryModel);
-        if (type.getBasicType() == glslang::EbtReference) {
+        if (type.isReference()) {
             // Original and non-writable params pass the pointer directly and
             // use restrict/aliased, others are stored to a pointer in Function
             // memory and use RestrictPointer/AliasedPointer.
             if (originalParam(type.getQualifier().storage, type, false) ||
                 !writableParam(type.getQualifier().storage)) {
-                decorations.push_back(type.getQualifier().restrict ? spv::DecorationRestrict : spv::DecorationAliased);
+                decorations.push_back(type.getQualifier().isRestrict() ? spv::DecorationRestrict :
+                                                                         spv::DecorationAliased);
             } else {
-                decorations.push_back(type.getQualifier().restrict ? spv::DecorationRestrictPointerEXT : spv::DecorationAliasedPointerEXT);
+                decorations.push_back(type.getQualifier().isRestrict() ? spv::DecorationRestrictPointerEXT :
+                                                                         spv::DecorationAliasedPointerEXT);
             }
         }
     };
@@ -3874,8 +4451,12 @@
         std::vector<std::vector<spv::Decoration>> paramDecorations; // list of decorations per parameter
         glslang::TIntermSequence& parameters = glslFunction->getSequence()[0]->getAsAggregate()->getSequence();
 
+#ifdef ENABLE_HLSL
         bool implicitThis = (int)parameters.size() > 0 && parameters[0]->getAsSymbolNode()->getName() ==
                                                           glslangIntermediate->implicitThisName;
+#else
+        bool implicitThis = false;
+#endif
 
         paramDecorations.resize(parameters.size());
         for (int p = 0; p < (int)parameters.size(); ++p) {
@@ -3907,6 +4488,14 @@
             symbolValues[parameters[p]->getAsSymbolNode()->getId()] = function->getParamId(p);
             // give a name too
             builder.addName(function->getParamId(p), parameters[p]->getAsSymbolNode()->getName().c_str());
+
+            const glslang::TType& paramType = parameters[p]->getAsTyped()->getType();
+            if (paramType.contains8BitInt())
+                builder.addCapability(spv::CapabilityInt8);
+            if (paramType.contains16BitInt())
+                builder.addCapability(spv::CapabilityInt16);
+            if (paramType.contains16BitFloat())
+                builder.addCapability(spv::CapabilityFloat16);
         }
     }
 }
@@ -3917,7 +4506,8 @@
     builder.setBuildPoint(shaderEntry->getLastBlock());
     for (int i = 0; i < (int)initializers.size(); ++i) {
         glslang::TIntermAggregate* initializer = initializers[i]->getAsAggregate();
-        if (initializer && initializer->getOp() != glslang::EOpFunction && initializer->getOp() != glslang::EOpLinkerObjects) {
+        if (initializer && initializer->getOp() != glslang::EOpFunction && initializer->getOp() !=
+            glslang::EOpLinkerObjects) {
 
             // We're on a top-level node that's not a function.  Treat as an initializer, whose
             // code goes into the beginning of the entry point.
@@ -3945,20 +4535,22 @@
     builder.setBuildPoint(functionBlock);
 }
 
-void TGlslangToSpvTraverser::translateArguments(const glslang::TIntermAggregate& node, std::vector<spv::Id>& arguments)
+void TGlslangToSpvTraverser::translateArguments(const glslang::TIntermAggregate& node, std::vector<spv::Id>& arguments,
+    spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags)
 {
     const glslang::TIntermSequence& glslangArguments = node.getSequence();
 
     glslang::TSampler sampler = {};
     bool cubeCompare = false;
-#ifdef AMD_EXTENSIONS
+#ifndef GLSLANG_WEB
     bool f16ShadowCompare = false;
 #endif
     if (node.isTexture() || node.isImage()) {
         sampler = glslangArguments[0]->getAsTyped()->getType().getSampler();
         cubeCompare = sampler.dim == glslang::EsdCube && sampler.arrayed && sampler.shadow;
-#ifdef AMD_EXTENSIONS
-        f16ShadowCompare = sampler.shadow && glslangArguments[1]->getAsTyped()->getType().getBasicType() == glslang::EbtFloat16;
+#ifndef GLSLANG_WEB
+        f16ShadowCompare = sampler.shadow &&
+            glslangArguments[1]->getAsTyped()->getType().getBasicType() == glslang::EbtFloat16;
 #endif
     }
 
@@ -3966,6 +4558,7 @@
         builder.clearAccessChain();
         glslangArguments[i]->traverse(this);
 
+#ifndef GLSLANG_WEB
         // Special case l-value operands
         bool lvalue = false;
         switch (node.getOp()) {
@@ -3986,7 +4579,6 @@
             if ((sampler.ms && i == 3) || (! sampler.ms && i == 2))
                 lvalue = true;
             break;
-#ifdef AMD_EXTENSIONS
         case glslang::EOpSparseTexture:
             if (((cubeCompare || f16ShadowCompare) && i == 3) || (! (cubeCompare || f16ShadowCompare) && i == 2))
                 lvalue = true;
@@ -4000,21 +4592,6 @@
             if  ((f16ShadowCompare && i == 4) || (! f16ShadowCompare && i == 3))
                 lvalue = true;
             break;
-#else
-        case glslang::EOpSparseTexture:
-            if ((cubeCompare && i == 3) || (! cubeCompare && i == 2))
-                lvalue = true;
-            break;
-        case glslang::EOpSparseTextureClamp:
-            if ((cubeCompare && i == 4) || (! cubeCompare && i == 3))
-                lvalue = true;
-            break;
-        case glslang::EOpSparseTextureLod:
-        case glslang::EOpSparseTextureOffset:
-            if (i == 3)
-                lvalue = true;
-            break;
-#endif
         case glslang::EOpSparseTextureFetch:
             if ((sampler.dim != glslang::EsdRect && i == 3) || (sampler.dim == glslang::EsdRect && i == 2))
                 lvalue = true;
@@ -4023,7 +4600,6 @@
             if ((sampler.dim != glslang::EsdRect && i == 4) || (sampler.dim == glslang::EsdRect && i == 3))
                 lvalue = true;
             break;
-#ifdef AMD_EXTENSIONS
         case glslang::EOpSparseTextureLodOffset:
         case glslang::EOpSparseTextureGrad:
         case glslang::EOpSparseTextureOffsetClamp:
@@ -4039,23 +4615,6 @@
             if ((f16ShadowCompare && i == 7) || (! f16ShadowCompare && i == 6))
                 lvalue = true;
             break;
-#else
-        case glslang::EOpSparseTextureLodOffset:
-        case glslang::EOpSparseTextureGrad:
-        case glslang::EOpSparseTextureOffsetClamp:
-            if (i == 4)
-                lvalue = true;
-            break;
-        case glslang::EOpSparseTextureGradOffset:
-        case glslang::EOpSparseTextureGradClamp:
-            if (i == 5)
-                lvalue = true;
-            break;
-        case glslang::EOpSparseTextureGradOffsetClamp:
-            if (i == 6)
-                lvalue = true;
-            break;
-#endif
         case glslang::EOpSparseTextureGather:
             if ((sampler.shadow && i == 3) || (! sampler.shadow && i == 2))
                 lvalue = true;
@@ -4065,7 +4624,6 @@
             if ((sampler.shadow && i == 4) || (! sampler.shadow && i == 3))
                 lvalue = true;
             break;
-#ifdef AMD_EXTENSIONS
         case glslang::EOpSparseTextureGatherLod:
             if (i == 3)
                 lvalue = true;
@@ -4079,8 +4637,6 @@
             if (i == 3)
                 lvalue = true;
             break;
-#endif
-#ifdef NV_EXTENSIONS
         case glslang::EOpImageSampleFootprintNV:
             if (i == 4)
                 lvalue = true;
@@ -4098,14 +4654,16 @@
             if (i == 7)
                 lvalue = true;
             break;
-#endif
         default:
             break;
         }
 
-        if (lvalue)
+        if (lvalue) {
             arguments.push_back(builder.accessChainGetLValue());
-        else
+            lvalueCoherentFlags = builder.getAccessChain().coherentFlags;
+            lvalueCoherentFlags |= TranslateCoherent(glslangArguments[i]->getAsTyped()->getType());
+        } else
+#endif
             arguments.push_back(accessChainLoad(glslangArguments[i]->getAsTyped()->getType()));
     }
 }
@@ -4126,18 +4684,33 @@
 
     // Process a GLSL texturing op (will be SPV image)
 
-    const glslang::TType &imageType = node->getAsAggregate() ? node->getAsAggregate()->getSequence()[0]->getAsTyped()->getType()
-                                                             : node->getAsUnaryNode()->getOperand()->getAsTyped()->getType();
+    const glslang::TType &imageType = node->getAsAggregate()
+                                        ? node->getAsAggregate()->getSequence()[0]->getAsTyped()->getType()
+                                        : node->getAsUnaryNode()->getOperand()->getAsTyped()->getType();
     const glslang::TSampler sampler = imageType.getSampler();
-#ifdef AMD_EXTENSIONS
+#ifdef GLSLANG_WEB
+    const bool f16ShadowCompare = false;
+#else
     bool f16ShadowCompare = (sampler.shadow && node->getAsAggregate())
-                                ? node->getAsAggregate()->getSequence()[1]->getAsTyped()->getType().getBasicType() == glslang::EbtFloat16
-                                : false;
+            ? node->getAsAggregate()->getSequence()[1]->getAsTyped()->getType().getBasicType() == glslang::EbtFloat16
+            : false;
 #endif
 
+    const auto signExtensionMask = [&]() {
+        if (builder.getSpvVersion() >= spv::Spv_1_4) {
+            if (sampler.type == glslang::EbtUint)
+                return spv::ImageOperandsZeroExtendMask;
+            else if (sampler.type == glslang::EbtInt)
+                return spv::ImageOperandsSignExtendMask;
+        }
+        return spv::ImageOperandsMaskNone;
+    };
+
+    spv::Builder::AccessChain::CoherentFlags lvalueCoherentFlags;
+
     std::vector<spv::Id> arguments;
     if (node->getAsAggregate())
-        translateArguments(*node->getAsAggregate(), arguments);
+        translateArguments(*node->getAsAggregate(), arguments, lvalueCoherentFlags);
     else
         translateArguments(*node->getAsUnaryNode(), arguments);
     spv::Decoration precision = TranslatePrecisionDecoration(node->getOperationPrecision());
@@ -4164,6 +4737,7 @@
                 return builder.createTextureQueryCall(spv::OpImageQuerySizeLod, params, isUnsignedResult);
             } else
                 return builder.createTextureQueryCall(spv::OpImageQuerySize, params, isUnsignedResult);
+#ifndef GLSLANG_WEB
         case glslang::EOpImageQuerySamples:
         case glslang::EOpTextureQuerySamples:
             return builder.createTextureQueryCall(spv::OpImageQuerySamples, params, isUnsignedResult);
@@ -4174,6 +4748,7 @@
             return builder.createTextureQueryCall(spv::OpImageQueryLevels, params, isUnsignedResult);
         case glslang::EOpSparseTexelsResident:
             return builder.createUnaryOp(spv::OpImageSparseTexelsResident, builder.makeBoolType(), arguments[0]);
+#endif
         default:
             assert(0);
             break;
@@ -4213,11 +4788,17 @@
             spv::IdImmediate coord = { true,
                 builder.makeCompositeConstant(builder.makeVectorType(builder.makeIntType(32), 2), comps) };
             operands.push_back(coord);
-            if (sampler.ms) {
-                spv::IdImmediate imageOperands = { false, spv::ImageOperandsSampleMask };
+            spv::IdImmediate imageOperands = { false, spv::ImageOperandsMaskNone };
+            imageOperands.word = imageOperands.word | signExtensionMask();
+            if (sampler.isMultiSample()) {
+                imageOperands.word = imageOperands.word | spv::ImageOperandsSampleMask;
+            }
+            if (imageOperands.word != spv::ImageOperandsMaskNone) {
                 operands.push_back(imageOperands);
-                spv::IdImmediate imageOperand = { true, *(opIt++) };
-                operands.push_back(imageOperand);
+                if (sampler.isMultiSample()) {
+                    spv::IdImmediate imageOperand = { true, *(opIt++) };
+                    operands.push_back(imageOperand);
+                }
             }
             spv::Id result = builder.createOp(spv::OpImageRead, resultType(), operands);
             builder.setPrecision(result, precision);
@@ -4226,25 +4807,20 @@
 
         spv::IdImmediate coord = { true, *(opIt++) };
         operands.push_back(coord);
-#ifdef AMD_EXTENSIONS
         if (node->getOp() == glslang::EOpImageLoad || node->getOp() == glslang::EOpImageLoadLod) {
-#else
-        if (node->getOp() == glslang::EOpImageLoad) {
-#endif
             spv::ImageOperandsMask mask = spv::ImageOperandsMaskNone;
-            if (sampler.ms) {
+            if (sampler.isMultiSample()) {
                 mask = mask | spv::ImageOperandsSampleMask;
             }
-#ifdef AMD_EXTENSIONS
             if (cracked.lod) {
                 builder.addExtension(spv::E_SPV_AMD_shader_image_load_store_lod);
                 builder.addCapability(spv::CapabilityImageReadWriteLodAMD);
                 mask = mask | spv::ImageOperandsLodMask;
             }
-#endif
             mask = mask | TranslateImageOperands(TranslateCoherent(imageType));
             mask = (spv::ImageOperandsMask)(mask & ~spv::ImageOperandsMakeTexelAvailableKHRMask);
-            if (mask) {
+            mask = mask | signExtensionMask();
+            if (mask != spv::ImageOperandsMaskNone) {
                 spv::IdImmediate imageOperands = { false, (unsigned int)mask };
                 operands.push_back(imageOperands);
             }
@@ -4252,14 +4828,13 @@
                 spv::IdImmediate imageOperand = { true, *opIt++ };
                 operands.push_back(imageOperand);
             }
-#ifdef AMD_EXTENSIONS
             if (mask & spv::ImageOperandsLodMask) {
                 spv::IdImmediate imageOperand = { true, *opIt++ };
                 operands.push_back(imageOperand);
             }
-#endif
             if (mask & spv::ImageOperandsMakeTexelVisibleKHRMask) {
-                spv::IdImmediate imageOperand = { true, builder.makeUintConstant(TranslateMemoryScope(TranslateCoherent(imageType))) };
+                spv::IdImmediate imageOperand = { true,
+                                    builder.makeUintConstant(TranslateMemoryScope(TranslateCoherent(imageType))) };
                 operands.push_back(imageOperand);
             }
 
@@ -4274,18 +4849,10 @@
                 result[0] = builder.createConstructor(precision, result, convertGlslangToSpvType(node->getType()));
 
             return result[0];
-#ifdef AMD_EXTENSIONS
         } else if (node->getOp() == glslang::EOpImageStore || node->getOp() == glslang::EOpImageStoreLod) {
-#else
-        } else if (node->getOp() == glslang::EOpImageStore) {
-#endif
 
             // Push the texel value before the operands
-#ifdef AMD_EXTENSIONS
-            if (sampler.ms || cracked.lod) {
-#else
-            if (sampler.ms) {
-#endif
+            if (sampler.isMultiSample() || cracked.lod) {
                 spv::IdImmediate texel = { true, *(opIt + 1) };
                 operands.push_back(texel);
             } else {
@@ -4294,19 +4861,18 @@
             }
 
             spv::ImageOperandsMask mask = spv::ImageOperandsMaskNone;
-            if (sampler.ms) {
+            if (sampler.isMultiSample()) {
                 mask = mask | spv::ImageOperandsSampleMask;
             }
-#ifdef AMD_EXTENSIONS
             if (cracked.lod) {
                 builder.addExtension(spv::E_SPV_AMD_shader_image_load_store_lod);
                 builder.addCapability(spv::CapabilityImageReadWriteLodAMD);
                 mask = mask | spv::ImageOperandsLodMask;
             }
-#endif
             mask = mask | TranslateImageOperands(TranslateCoherent(imageType));
             mask = (spv::ImageOperandsMask)(mask & ~spv::ImageOperandsMakeTexelVisibleKHRMask);
-            if (mask) {
+            mask = mask | signExtensionMask();
+            if (mask != spv::ImageOperandsMaskNone) {
                 spv::IdImmediate imageOperands = { false, (unsigned int)mask };
                 operands.push_back(imageOperands);
             }
@@ -4314,14 +4880,13 @@
                 spv::IdImmediate imageOperand = { true, *opIt++ };
                 operands.push_back(imageOperand);
             }
-#ifdef AMD_EXTENSIONS
             if (mask & spv::ImageOperandsLodMask) {
                 spv::IdImmediate imageOperand = { true, *opIt++ };
                 operands.push_back(imageOperand);
             }
-#endif
             if (mask & spv::ImageOperandsMakeTexelAvailableKHRMask) {
-                spv::IdImmediate imageOperand = { true, builder.makeUintConstant(TranslateMemoryScope(TranslateCoherent(imageType))) };
+                spv::IdImmediate imageOperand = { true,
+                    builder.makeUintConstant(TranslateMemoryScope(TranslateCoherent(imageType))) };
                 operands.push_back(imageOperand);
             }
 
@@ -4329,30 +4894,26 @@
             if (builder.getImageTypeFormat(builder.getImageType(operands.front().word)) == spv::ImageFormatUnknown)
                 builder.addCapability(spv::CapabilityStorageImageWriteWithoutFormat);
             return spv::NoResult;
-#ifdef AMD_EXTENSIONS
-        } else if (node->getOp() == glslang::EOpSparseImageLoad || node->getOp() == glslang::EOpSparseImageLoadLod) {
-#else
-        } else if (node->getOp() == glslang::EOpSparseImageLoad) {
-#endif
+        } else if (node->getOp() == glslang::EOpSparseImageLoad ||
+                   node->getOp() == glslang::EOpSparseImageLoadLod) {
             builder.addCapability(spv::CapabilitySparseResidency);
             if (builder.getImageTypeFormat(builder.getImageType(operands.front().word)) == spv::ImageFormatUnknown)
                 builder.addCapability(spv::CapabilityStorageImageReadWithoutFormat);
 
             spv::ImageOperandsMask mask = spv::ImageOperandsMaskNone;
-            if (sampler.ms) {
+            if (sampler.isMultiSample()) {
                 mask = mask | spv::ImageOperandsSampleMask;
             }
-#ifdef AMD_EXTENSIONS
             if (cracked.lod) {
                 builder.addExtension(spv::E_SPV_AMD_shader_image_load_store_lod);
                 builder.addCapability(spv::CapabilityImageReadWriteLodAMD);
 
                 mask = mask | spv::ImageOperandsLodMask;
             }
-#endif
             mask = mask | TranslateImageOperands(TranslateCoherent(imageType));
             mask = (spv::ImageOperandsMask)(mask & ~spv::ImageOperandsMakeTexelAvailableKHRMask);
-            if (mask) {
+            mask = mask | signExtensionMask();
+            if (mask != spv::ImageOperandsMaskNone) {
                 spv::IdImmediate imageOperands = { false, (unsigned int)mask };
                 operands.push_back(imageOperands);
             }
@@ -4360,14 +4921,13 @@
                 spv::IdImmediate imageOperand = { true, *opIt++ };
                 operands.push_back(imageOperand);
             }
-#ifdef AMD_EXTENSIONS
             if (mask & spv::ImageOperandsLodMask) {
                 spv::IdImmediate imageOperand = { true, *opIt++ };
                 operands.push_back(imageOperand);
             }
-#endif
             if (mask & spv::ImageOperandsMakeTexelVisibleKHRMask) {
-                spv::IdImmediate imageOperand = { true, builder.makeUintConstant(TranslateMemoryScope(TranslateCoherent(imageType))) };
+                spv::IdImmediate imageOperand = { true, builder.makeUintConstant(TranslateMemoryScope(
+                    TranslateCoherent(imageType))) };
                 operands.push_back(imageOperand);
             }
 
@@ -4388,29 +4948,33 @@
             // GLSL "IMAGE_PARAMS" will involve in constructing an image texel pointer and this pointer,
             // as the first source operand, is required by SPIR-V atomic operations.
             // For non-MS, the sample value should be 0
-            spv::IdImmediate sample = { true, sampler.ms ? *(opIt++) : builder.makeUintConstant(0) };
+            spv::IdImmediate sample = { true, sampler.isMultiSample() ? *(opIt++) : builder.makeUintConstant(0) };
             operands.push_back(sample);
 
             spv::Id resultTypeId;
             // imageAtomicStore has a void return type so base the pointer type on
             // the type of the value operand.
             if (node->getOp() == glslang::EOpImageAtomicStore) {
-                resultTypeId = builder.makePointer(spv::StorageClassImage, builder.getTypeId(operands[2].word));                
+                resultTypeId = builder.makePointer(spv::StorageClassImage, builder.getTypeId(*opIt));
             } else {
                 resultTypeId = builder.makePointer(spv::StorageClassImage, resultType());
             }
             spv::Id pointer = builder.createOp(spv::OpImageTexelPointer, resultTypeId, operands);
+            if (imageType.getQualifier().nonUniform) {
+                builder.addDecoration(pointer, spv::DecorationNonUniformEXT);
+            }
 
             std::vector<spv::Id> operands;
             operands.push_back(pointer);
             for (; opIt != arguments.end(); ++opIt)
                 operands.push_back(*opIt);
 
-            return createAtomicOperation(node->getOp(), precision, resultType(), operands, node->getBasicType());
+            return createAtomicOperation(node->getOp(), precision, resultType(), operands, node->getBasicType(),
+                lvalueCoherentFlags);
         }
     }
 
-#ifdef AMD_EXTENSIONS
+#ifndef GLSLANG_WEB
     // Check for fragment mask functions other than queries
     if (cracked.fragMask) {
         assert(sampler.ms);
@@ -4431,7 +4995,8 @@
             std::vector<spv::Id> comps;
             comps.push_back(zero);
             comps.push_back(zero);
-            operands.push_back(builder.makeCompositeConstant(builder.makeVectorType(builder.makeIntType(32), 2), comps));
+            operands.push_back(builder.makeCompositeConstant(
+                builder.makeVectorType(builder.makeIntType(32), 2), comps));
         }
 
         for (; opIt != arguments.end(); ++opIt)
@@ -4451,45 +5016,32 @@
 
     // Check for texture functions other than queries
     bool sparse = node->isSparseTexture();
-#ifdef NV_EXTENSIONS
     bool imageFootprint = node->isImageFootprint();
-#endif
-
-    bool cubeCompare = sampler.dim == glslang::EsdCube && sampler.arrayed && sampler.shadow;
+    bool cubeCompare = sampler.dim == glslang::EsdCube && sampler.isArrayed() && sampler.isShadow();
 
     // check for bias argument
     bool bias = false;
-#ifdef AMD_EXTENSIONS
     if (! cracked.lod && ! cracked.grad && ! cracked.fetch && ! cubeCompare) {
-#else
-    if (! cracked.lod && ! cracked.gather && ! cracked.grad && ! cracked.fetch && ! cubeCompare) {
-#endif
         int nonBiasArgCount = 2;
-#ifdef AMD_EXTENSIONS
         if (cracked.gather)
             ++nonBiasArgCount; // comp argument should be present when bias argument is present
 
         if (f16ShadowCompare)
             ++nonBiasArgCount;
-#endif
         if (cracked.offset)
             ++nonBiasArgCount;
-#ifdef AMD_EXTENSIONS
         else if (cracked.offsets)
             ++nonBiasArgCount;
-#endif
         if (cracked.grad)
             nonBiasArgCount += 2;
         if (cracked.lodClamp)
             ++nonBiasArgCount;
         if (sparse)
             ++nonBiasArgCount;
-#ifdef NV_EXTENSIONS
         if (imageFootprint)
             //Following three extra arguments
             // int granularity, bool coarse, out gl_TextureFootprint2DNV footprint
             nonBiasArgCount += 3;
-#endif
         if ((int)arguments.size() > nonBiasArgCount)
             bias = true;
     }
@@ -4501,7 +5053,7 @@
             params.sampler = builder.createUnaryOp(spv::OpImage, builder.getImageType(params.sampler), params.sampler);
     }
 
-#ifdef AMD_EXTENSIONS
+#ifndef GLSLANG_WEB
     if (cracked.gather) {
         const auto& sourceExtensions = glslangIntermediate->getRequestedExtensions();
         if (bias || cracked.lod ||
@@ -4519,11 +5071,7 @@
     bool noImplicitLod = false;
 
     // sort out where Dref is coming from
-#ifdef AMD_EXTENSIONS
     if (cubeCompare || f16ShadowCompare) {
-#else
-    if (cubeCompare) {
-#endif
         params.Dref = arguments[2];
         ++extraArgs;
     } else if (sampler.shadow && cracked.gather) {
@@ -4537,26 +5085,23 @@
         else
             dRefComp = builder.getNumComponents(params.coords) - 1;
         indexes.push_back(dRefComp);
-        params.Dref = builder.createCompositeExtract(params.coords, builder.getScalarTypeId(builder.getTypeId(params.coords)), indexes);
+        params.Dref = builder.createCompositeExtract(params.coords,
+            builder.getScalarTypeId(builder.getTypeId(params.coords)), indexes);
     }
 
     // lod
     if (cracked.lod) {
         params.lod = arguments[2 + extraArgs];
         ++extraArgs;
-    } else if (glslangIntermediate->getStage() != EShLangFragment
-#ifdef NV_EXTENSIONS
-        // NV_compute_shader_derivatives layout qualifiers allow for implicit LODs
-           && !(glslangIntermediate->getStage() == EShLangCompute &&
-                (glslangIntermediate->getLayoutDerivativeModeNone() != glslang::LayoutDerivativeNone))
-#endif
-        ) {
+    } else if (glslangIntermediate->getStage() != EShLangFragment &&
+               !(glslangIntermediate->getStage() == EShLangCompute &&
+                 glslangIntermediate->hasLayoutDerivativeModeNone())) {
         // we need to invent the default lod for an explicit lod instruction for a non-fragment stage
         noImplicitLod = true;
     }
 
     // multisample
-    if (sampler.ms) {
+    if (sampler.isMultiSample()) {
         params.sample = arguments[2 + extraArgs]; // For MS, "sample" should be specified
         ++extraArgs;
     }
@@ -4577,6 +5122,7 @@
         ++extraArgs;
     }
 
+#ifndef GLSLANG_WEB
     // lod clamp
     if (cracked.lodClamp) {
         params.lodClamp = arguments[2 + extraArgs];
@@ -4587,7 +5133,6 @@
         params.texelOut = arguments[2 + extraArgs];
         ++extraArgs;
     }
-
     // gather component
     if (cracked.gather && ! sampler.shadow) {
         // default component is 0, if missing, otherwise an argument
@@ -4597,7 +5142,6 @@
         } else
             params.component = builder.makeIntConstant(0);
     }
-#ifdef NV_EXTENSIONS
     spv::Id  resultStruct = spv::NoResult;
     if (imageFootprint) {
         //Following three extra arguments
@@ -4614,7 +5158,7 @@
         ++extraArgs;
     }
 
-#ifdef NV_EXTENSIONS
+#ifndef GLSLANG_WEB
     if (imageFootprint) {
         builder.addExtension(spv::E_SPV_NV_shader_image_footprint);
         builder.addCapability(spv::CapabilityImageFootprintNV);
@@ -4654,7 +5198,8 @@
         spv::Id resType = builder.makeStructType(members, "ResType");
 
         //call ImageFootprintNV
-        spv::Id res = builder.createTextureCall(precision, resType, sparse, cracked.fetch, cracked.proj, cracked.gather, noImplicitLod, params);
+        spv::Id res = builder.createTextureCall(precision, resType, sparse, cracked.fetch, cracked.proj,
+                                                cracked.gather, noImplicitLod, params, signExtensionMask());
         
         //copy resType (SPIR-V type) to resultStructType(OpenGL type)
         for (int i = 0; i < 5; i++) {
@@ -4666,7 +5211,8 @@
             flags.clear();
 
             builder.accessChainPush(builder.makeIntConstant(i), flags, 0);
-            builder.accessChainStore(builder.createCompositeExtract(res, builder.getContainedTypeId(resType, i+1), i+1));
+            builder.accessChainStore(builder.createCompositeExtract(res, builder.getContainedTypeId(resType, i+1),
+                i+1));
         }
         return builder.createCompositeExtract(res, resultType(), 0);
     }
@@ -4689,13 +5235,13 @@
         // copy the projective coordinate if we have to
         if (projTargetComp != projSourceComp) {
             spv::Id projComp = builder.createCompositeExtract(params.coords,
-                                                              builder.getScalarTypeId(builder.getTypeId(params.coords)),
-                                                              projSourceComp);
+                                    builder.getScalarTypeId(builder.getTypeId(params.coords)), projSourceComp);
             params.coords = builder.createCompositeInsert(projComp, params.coords,
-                                                          builder.getTypeId(params.coords), projTargetComp);
+                                    builder.getTypeId(params.coords), projTargetComp);
         }
     }
 
+#ifndef GLSLANG_WEB
     // nonprivate
     if (imageType.getQualifier().nonprivate) {
         params.nonprivate = true;
@@ -4705,9 +5251,11 @@
     if (imageType.getQualifier().volatil) {
         params.volatil = true;
     }
+#endif
 
     std::vector<spv::Id> result( 1, 
-        builder.createTextureCall(precision, resultType(), sparse, cracked.fetch, cracked.proj, cracked.gather, noImplicitLod, params)
+        builder.createTextureCall(precision, resultType(), sparse, cracked.fetch, cracked.proj, cracked.gather,
+                                  noImplicitLod, params, signExtensionMask())
     );
 
     if (components != node->getType().getVectorSize())
@@ -4769,7 +5317,8 @@
             ++lValueCount;
         } else if (writableParam(qualifiers[a])) {
             // need space to hold the copy
-            arg = builder.createVariable(spv::StorageClassFunction, builder.getContainedTypeId(function->getParamType(a)), "param");
+            arg = builder.createVariable(spv::StorageClassFunction,
+                builder.getContainedTypeId(function->getParamType(a)), "param");
             if (qualifiers[a] == glslang::EvqIn || qualifiers[a] == glslang::EvqInOut) {
                 // need to copy the input into output space
                 builder.setAccessChain(lValues[lValueCount]);
@@ -4938,6 +5487,30 @@
         binOp = spv::OpLogicalNotEqual;
         break;
 
+    case glslang::EOpAbsDifference:
+        binOp = isUnsigned ? spv::OpAbsUSubINTEL : spv::OpAbsISubINTEL;
+        break;
+
+    case glslang::EOpAddSaturate:
+        binOp = isUnsigned ? spv::OpUAddSatINTEL : spv::OpIAddSatINTEL;
+        break;
+
+    case glslang::EOpSubSaturate:
+        binOp = isUnsigned ? spv::OpUSubSatINTEL : spv::OpISubSatINTEL;
+        break;
+
+    case glslang::EOpAverage:
+        binOp = isUnsigned ? spv::OpUAverageINTEL : spv::OpIAverageINTEL;
+        break;
+
+    case glslang::EOpAverageRounded:
+        binOp = isUnsigned ? spv::OpUAverageRoundedINTEL : spv::OpIAverageRoundedINTEL;
+        break;
+
+    case glslang::EOpMul32x16:
+        binOp = isUnsigned ? spv::OpUMul32x16INTEL : spv::OpIMul32x16INTEL;
+        break;
+
     case glslang::EOpLessThan:
     case glslang::EOpGreaterThan:
     case glslang::EOpLessThanEqual:
@@ -4964,8 +5537,8 @@
             builder.promoteScalar(decorations.precision, left, right);
 
         spv::Id result = builder.createBinOp(binOp, typeId, left, right);
-        builder.addDecoration(result, decorations.noContraction);
-        builder.addDecoration(result, decorations.nonUniform);
+        decorations.addNoContraction(builder, result);
+        decorations.addNonUniform(builder, result);
         return builder.setPrecision(result, decorations.precision);
     }
 
@@ -4977,7 +5550,7 @@
     if (reduceComparison && (op == glslang::EOpEqual || op == glslang::EOpNotEqual)
                          && (builder.isVector(left) || builder.isMatrix(left) || builder.isAggregate(left))) {
         spv::Id result = builder.createCompositeCompare(decorations.precision, left, right, op == glslang::EOpEqual);
-        builder.addDecoration(result, decorations.nonUniform);
+        decorations.addNonUniform(builder, result);
         return result;
     }
 
@@ -5038,8 +5611,8 @@
 
     if (binOp != spv::OpNop) {
         spv::Id result = builder.createBinOp(binOp, typeId, left, right);
-        builder.addDecoration(result, decorations.noContraction);
-        builder.addDecoration(result, decorations.nonUniform);
+        decorations.addNoContraction(builder, result);
+        decorations.addNonUniform(builder, result);
         return builder.setPrecision(result, decorations.precision);
     }
 
@@ -5103,8 +5676,8 @@
 
     if (firstClass) {
         spv::Id result = builder.createBinOp(op, typeId, left, right);
-        builder.addDecoration(result, decorations.noContraction);
-        builder.addDecoration(result, decorations.nonUniform);
+        decorations.addNoContraction(builder, result);
+        decorations.addNonUniform(builder, result);
         return builder.setPrecision(result, decorations.precision);
     }
 
@@ -5143,14 +5716,14 @@
             spv::Id  leftVec =  leftMat ? builder.createCompositeExtract( left, vecType, indexes) : smearVec;
             spv::Id rightVec = rightMat ? builder.createCompositeExtract(right, vecType, indexes) : smearVec;
             spv::Id result = builder.createBinOp(op, vecType, leftVec, rightVec);
-            builder.addDecoration(result, decorations.noContraction);
-            builder.addDecoration(result, decorations.nonUniform);
+            decorations.addNoContraction(builder, result);
+            decorations.addNonUniform(builder, result);
             results.push_back(builder.setPrecision(result, decorations.precision));
         }
 
         // put the pieces together
         spv::Id result = builder.setPrecision(builder.createCompositeConstruct(typeId, results), decorations.precision);
-        builder.addDecoration(result, decorations.nonUniform);
+        decorations.addNonUniform(builder, result);
         return result;
     }
     default:
@@ -5160,7 +5733,7 @@
 }
 
 spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, OpDecorations& decorations, spv::Id typeId,
-                                                     spv::Id operand, glslang::TBasicType typeProxy)
+    spv::Id operand, glslang::TBasicType typeProxy, const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags)
 {
     spv::Op unaryOp = spv::OpNop;
     int extBuiltins = -1;
@@ -5328,6 +5901,7 @@
     case glslang::EOpUnpackHalf2x16:
         libCall = spv::GLSLstd450UnpackHalf2x16;
         break;
+#ifndef GLSLANG_WEB
     case glslang::EOpPackSnorm4x8:
         libCall = spv::GLSLstd450PackSnorm4x8;
         break;
@@ -5346,6 +5920,7 @@
     case glslang::EOpUnpackDouble2x32:
         libCall = spv::GLSLstd450UnpackDouble2x32;
         break;
+#endif
 
     case glslang::EOpPackInt2x32:
     case glslang::EOpUnpackInt2x32:
@@ -5379,31 +5954,7 @@
     case glslang::EOpFwidth:
         unaryOp = spv::OpFwidth;
         break;
-    case glslang::EOpDPdxFine:
-        unaryOp = spv::OpDPdxFine;
-        break;
-    case glslang::EOpDPdyFine:
-        unaryOp = spv::OpDPdyFine;
-        break;
-    case glslang::EOpFwidthFine:
-        unaryOp = spv::OpFwidthFine;
-        break;
-    case glslang::EOpDPdxCoarse:
-        unaryOp = spv::OpDPdxCoarse;
-        break;
-    case glslang::EOpDPdyCoarse:
-        unaryOp = spv::OpDPdyCoarse;
-        break;
-    case glslang::EOpFwidthCoarse:
-        unaryOp = spv::OpFwidthCoarse;
-        break;
-    case glslang::EOpInterpolateAtCentroid:
-#ifdef AMD_EXTENSIONS
-        if (typeProxy == glslang::EbtFloat16)
-            builder.addExtension(spv::E_SPV_AMD_gpu_shader_half_float);
-#endif
-        libCall = spv::GLSLstd450InterpolateAtCentroid;
-        break;
+
     case glslang::EOpAny:
         unaryOp = spv::OpAny;
         break;
@@ -5424,6 +5975,48 @@
             libCall = spv::GLSLstd450SSign;
         break;
 
+#ifndef GLSLANG_WEB
+    case glslang::EOpDPdxFine:
+        unaryOp = spv::OpDPdxFine;
+        break;
+    case glslang::EOpDPdyFine:
+        unaryOp = spv::OpDPdyFine;
+        break;
+    case glslang::EOpFwidthFine:
+        unaryOp = spv::OpFwidthFine;
+        break;
+    case glslang::EOpDPdxCoarse:
+        unaryOp = spv::OpDPdxCoarse;
+        break;
+    case glslang::EOpDPdyCoarse:
+        unaryOp = spv::OpDPdyCoarse;
+        break;
+    case glslang::EOpFwidthCoarse:
+        unaryOp = spv::OpFwidthCoarse;
+        break;
+    case glslang::EOpRayQueryProceed:
+        unaryOp = spv::OpRayQueryProceedKHR;
+        break;
+    case glslang::EOpRayQueryGetRayTMin:
+        unaryOp = spv::OpRayQueryGetRayTMinKHR;
+        break;
+    case glslang::EOpRayQueryGetRayFlags:
+        unaryOp = spv::OpRayQueryGetRayFlagsKHR;
+        break;
+    case glslang::EOpRayQueryGetWorldRayOrigin:
+        unaryOp = spv::OpRayQueryGetWorldRayOriginKHR;
+        break;
+    case glslang::EOpRayQueryGetWorldRayDirection:
+        unaryOp = spv::OpRayQueryGetWorldRayDirectionKHR;
+        break;
+    case glslang::EOpRayQueryGetIntersectionCandidateAABBOpaque:
+        unaryOp = spv::OpRayQueryGetIntersectionCandidateAABBOpaqueKHR;
+        break;
+    case glslang::EOpInterpolateAtCentroid:
+        if (typeProxy == glslang::EbtFloat16)
+            builder.addExtension(spv::E_SPV_AMD_gpu_shader_half_float);
+        libCall = spv::GLSLstd450InterpolateAtCentroid;
+        break;
     case glslang::EOpAtomicCounterIncrement:
     case glslang::EOpAtomicCounterDecrement:
     case glslang::EOpAtomicCounter:
@@ -5431,7 +6024,7 @@
         // Handle all of the atomics in one place, in createAtomicOperation()
         std::vector<spv::Id> operands;
         operands.push_back(operand);
-        return createAtomicOperation(op, decorations.precision, typeId, operands, typeProxy);
+        return createAtomicOperation(op, decorations.precision, typeId, operands, typeProxy, lvalueCoherentFlags);
     }
 
     case glslang::EOpBitFieldReverse:
@@ -5450,12 +6043,23 @@
             libCall = spv::GLSLstd450FindSMsb;
         break;
 
+    case glslang::EOpCountLeadingZeros:
+        builder.addCapability(spv::CapabilityIntegerFunctions2INTEL);
+        builder.addExtension("SPV_INTEL_shader_integer_functions2");
+        unaryOp = spv::OpUCountLeadingZerosINTEL;
+        break;
+
+    case glslang::EOpCountTrailingZeros:
+        builder.addCapability(spv::CapabilityIntegerFunctions2INTEL);
+        builder.addExtension("SPV_INTEL_shader_integer_functions2");
+        unaryOp = spv::OpUCountTrailingZerosINTEL;
+        break;
+
     case glslang::EOpBallot:
     case glslang::EOpReadFirstInvocation:
     case glslang::EOpAnyInvocation:
     case glslang::EOpAllInvocations:
     case glslang::EOpAllInvocationsEqual:
-#ifdef AMD_EXTENSIONS
     case glslang::EOpMinInvocations:
     case glslang::EOpMaxInvocations:
     case glslang::EOpAddInvocations:
@@ -5474,7 +6078,6 @@
     case glslang::EOpMinInvocationsExclusiveScanNonUniform:
     case glslang::EOpMaxInvocationsExclusiveScanNonUniform:
     case glslang::EOpAddInvocationsExclusiveScanNonUniform:
-#endif
     {
         std::vector<spv::Id> operands;
         operands.push_back(operand);
@@ -5519,7 +6122,6 @@
         operands.push_back(operand);
         return createSubgroupOperation(op, typeId, operands, typeProxy);
     }
-#ifdef AMD_EXTENSIONS
     case glslang::EOpMbcnt:
         extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_ballot);
         libCall = spv::MbcntAMD;
@@ -5534,15 +6136,18 @@
         extBuiltins = getExtBuiltins(spv::E_SPV_AMD_gcn_shader);
         libCall = spv::CubeFaceCoordAMD;
         break;
-#endif
-#ifdef NV_EXTENSIONS
     case glslang::EOpSubgroupPartition:
         unaryOp = spv::OpGroupNonUniformPartitionNV;
         break;
-#endif
     case glslang::EOpConstructReference:
         unaryOp = spv::OpBitcast;
         break;
+#endif
+
+    case glslang::EOpCopyObject:
+        unaryOp = spv::OpCopyObject;
+        break;
+
     default:
         return 0;
     }
@@ -5556,8 +6161,8 @@
         id = builder.createUnaryOp(unaryOp, typeId, operand);
     }
 
-    builder.addDecoration(id, decorations.noContraction);
-    builder.addDecoration(id, decorations.nonUniform);
+    decorations.addNoContraction(builder, id);
+    decorations.addNonUniform(builder, id);
     return builder.setPrecision(id, decorations.precision);
 }
 
@@ -5585,14 +6190,14 @@
         indexes.push_back(c);
         spv::Id srcVec  = builder.createCompositeExtract(operand, srcVecType, indexes);
         spv::Id destVec = builder.createUnaryOp(op, destVecType, srcVec);
-        builder.addDecoration(destVec, decorations.noContraction);
-        builder.addDecoration(destVec, decorations.nonUniform);
+        decorations.addNoContraction(builder, destVec);
+        decorations.addNonUniform(builder, destVec);
         results.push_back(builder.setPrecision(destVec, decorations.precision));
     }
 
     // put the pieces together
     spv::Id result = builder.setPrecision(builder.createCompositeConstruct(typeId, results), decorations.precision);
-    builder.addDecoration(result, decorations.nonUniform);
+    decorations.addNonUniform(builder, result);
     return result;
 }
 
@@ -5684,110 +6289,49 @@
     int vectorSize = builder.isVectorType(destType) ? builder.getNumTypeComponents(destType) : 0;
 
     switch (op) {
-    case glslang::EOpConvInt8ToBool:
-    case glslang::EOpConvUint8ToBool:
-        zero = builder.makeUint8Constant(0);
-        zero = makeSmearedConstant(zero, vectorSize);
-        return builder.createBinOp(spv::OpINotEqual, destType, operand, zero);
-    case glslang::EOpConvInt16ToBool:
-    case glslang::EOpConvUint16ToBool:
-        zero = builder.makeUint16Constant(0);
-        zero = makeSmearedConstant(zero, vectorSize);
-        return builder.createBinOp(spv::OpINotEqual, destType, operand, zero);
     case glslang::EOpConvIntToBool:
     case glslang::EOpConvUintToBool:
         zero = builder.makeUintConstant(0);
         zero = makeSmearedConstant(zero, vectorSize);
         return builder.createBinOp(spv::OpINotEqual, destType, operand, zero);
-    case glslang::EOpConvInt64ToBool:
-    case glslang::EOpConvUint64ToBool:
-        zero = builder.makeUint64Constant(0);
-        zero = makeSmearedConstant(zero, vectorSize);
-        return builder.createBinOp(spv::OpINotEqual, destType, operand, zero);
-
     case glslang::EOpConvFloatToBool:
         zero = builder.makeFloatConstant(0.0F);
         zero = makeSmearedConstant(zero, vectorSize);
         return builder.createBinOp(spv::OpFOrdNotEqual, destType, operand, zero);
-
-    case glslang::EOpConvDoubleToBool:
-        zero = builder.makeDoubleConstant(0.0);
-        zero = makeSmearedConstant(zero, vectorSize);
-        return builder.createBinOp(spv::OpFOrdNotEqual, destType, operand, zero);
-
-    case glslang::EOpConvFloat16ToBool:
-        zero = builder.makeFloat16Constant(0.0F);
-        zero = makeSmearedConstant(zero, vectorSize);
-        return builder.createBinOp(spv::OpFOrdNotEqual, destType, operand, zero);
-
     case glslang::EOpConvBoolToFloat:
         convOp = spv::OpSelect;
         zero = builder.makeFloatConstant(0.0F);
         one  = builder.makeFloatConstant(1.0F);
         break;
 
-    case glslang::EOpConvBoolToDouble:
-        convOp = spv::OpSelect;
-        zero = builder.makeDoubleConstant(0.0);
-        one  = builder.makeDoubleConstant(1.0);
-        break;
-
-    case glslang::EOpConvBoolToFloat16:
-        convOp = spv::OpSelect;
-        zero = builder.makeFloat16Constant(0.0F);
-        one = builder.makeFloat16Constant(1.0F);
-        break;
-
-    case glslang::EOpConvBoolToInt8:
-        zero = builder.makeInt8Constant(0);
-        one  = builder.makeInt8Constant(1);
-        convOp = spv::OpSelect;
-        break;
-
-    case glslang::EOpConvBoolToUint8:
-        zero = builder.makeUint8Constant(0);
-        one  = builder.makeUint8Constant(1);
-        convOp = spv::OpSelect;
-        break;
-
-    case glslang::EOpConvBoolToInt16:
-        zero = builder.makeInt16Constant(0);
-        one  = builder.makeInt16Constant(1);
-        convOp = spv::OpSelect;
-        break;
-
-    case glslang::EOpConvBoolToUint16:
-        zero = builder.makeUint16Constant(0);
-        one  = builder.makeUint16Constant(1);
-        convOp = spv::OpSelect;
-        break;
-
     case glslang::EOpConvBoolToInt:
     case glslang::EOpConvBoolToInt64:
-        if (op == glslang::EOpConvBoolToInt64)
+#ifndef GLSLANG_WEB
+        if (op == glslang::EOpConvBoolToInt64) {
             zero = builder.makeInt64Constant(0);
-        else
-            zero = builder.makeIntConstant(0);
-
-        if (op == glslang::EOpConvBoolToInt64)
             one = builder.makeInt64Constant(1);
-        else
+        } else
+#endif
+        {
+            zero = builder.makeIntConstant(0);
             one = builder.makeIntConstant(1);
+        }
 
         convOp = spv::OpSelect;
         break;
 
     case glslang::EOpConvBoolToUint:
     case glslang::EOpConvBoolToUint64:
-        if (op == glslang::EOpConvBoolToUint64)
+#ifndef GLSLANG_WEB
+        if (op == glslang::EOpConvBoolToUint64) {
             zero = builder.makeUint64Constant(0);
-        else
-            zero = builder.makeUintConstant(0);
-
-        if (op == glslang::EOpConvBoolToUint64)
             one = builder.makeUint64Constant(1);
-        else
+        } else
+#endif
+        {
+            zero = builder.makeUintConstant(0);
             one = builder.makeUintConstant(1);
+        }
 
         convOp = spv::OpSelect;
         break;
@@ -5822,17 +6366,6 @@
         convOp = spv::OpConvertUToF;
         break;
 
-    case glslang::EOpConvDoubleToFloat:
-    case glslang::EOpConvFloatToDouble:
-    case glslang::EOpConvDoubleToFloat16:
-    case glslang::EOpConvFloat16ToDouble:
-    case glslang::EOpConvFloatToFloat16:
-    case glslang::EOpConvFloat16ToFloat:
-        convOp = spv::OpFConvert;
-        if (builder.isMatrixType(destType))
-            return createUnaryMatrixOperation(convOp, decorations, destType, operand, typeProxy);
-        break;
-
     case glslang::EOpConvFloat16ToInt8:
     case glslang::EOpConvFloatToInt8:
     case glslang::EOpConvDoubleToInt8:
@@ -5858,13 +6391,16 @@
     case glslang::EOpConvInt64ToUint64:
         if (builder.isInSpecConstCodeGenMode()) {
             // Build zero scalar or vector for OpIAdd.
+#ifndef GLSLANG_WEB
             if(op == glslang::EOpConvUint8ToInt8 || op == glslang::EOpConvInt8ToUint8) {
                 zero = builder.makeUint8Constant(0);
             } else if (op == glslang::EOpConvUint16ToInt16 || op == glslang::EOpConvInt16ToUint16) {
                 zero = builder.makeUint16Constant(0);
             } else if (op == glslang::EOpConvUint64ToInt64 || op == glslang::EOpConvInt64ToUint64) {
                 zero = builder.makeUint64Constant(0);
-            } else {
+            } else
+#endif
+            {
                 zero = builder.makeUintConstant(0);
             }
             zero = makeSmearedConstant(zero, vectorSize);
@@ -5891,6 +6427,71 @@
         convOp = spv::OpConvertFToU;
         break;
 
+#ifndef GLSLANG_WEB
+    case glslang::EOpConvInt8ToBool:
+    case glslang::EOpConvUint8ToBool:
+        zero = builder.makeUint8Constant(0);
+        zero = makeSmearedConstant(zero, vectorSize);
+        return builder.createBinOp(spv::OpINotEqual, destType, operand, zero);
+    case glslang::EOpConvInt16ToBool:
+    case glslang::EOpConvUint16ToBool:
+        zero = builder.makeUint16Constant(0);
+        zero = makeSmearedConstant(zero, vectorSize);
+        return builder.createBinOp(spv::OpINotEqual, destType, operand, zero);
+    case glslang::EOpConvInt64ToBool:
+    case glslang::EOpConvUint64ToBool:
+        zero = builder.makeUint64Constant(0);
+        zero = makeSmearedConstant(zero, vectorSize);
+        return builder.createBinOp(spv::OpINotEqual, destType, operand, zero);
+    case glslang::EOpConvDoubleToBool:
+        zero = builder.makeDoubleConstant(0.0);
+        zero = makeSmearedConstant(zero, vectorSize);
+        return builder.createBinOp(spv::OpFOrdNotEqual, destType, operand, zero);
+    case glslang::EOpConvFloat16ToBool:
+        zero = builder.makeFloat16Constant(0.0F);
+        zero = makeSmearedConstant(zero, vectorSize);
+        return builder.createBinOp(spv::OpFOrdNotEqual, destType, operand, zero);
+    case glslang::EOpConvBoolToDouble:
+        convOp = spv::OpSelect;
+        zero = builder.makeDoubleConstant(0.0);
+        one  = builder.makeDoubleConstant(1.0);
+        break;
+    case glslang::EOpConvBoolToFloat16:
+        convOp = spv::OpSelect;
+        zero = builder.makeFloat16Constant(0.0F);
+        one = builder.makeFloat16Constant(1.0F);
+        break;
+    case glslang::EOpConvBoolToInt8:
+        zero = builder.makeInt8Constant(0);
+        one  = builder.makeInt8Constant(1);
+        convOp = spv::OpSelect;
+        break;
+    case glslang::EOpConvBoolToUint8:
+        zero = builder.makeUint8Constant(0);
+        one  = builder.makeUint8Constant(1);
+        convOp = spv::OpSelect;
+        break;
+    case glslang::EOpConvBoolToInt16:
+        zero = builder.makeInt16Constant(0);
+        one  = builder.makeInt16Constant(1);
+        convOp = spv::OpSelect;
+        break;
+    case glslang::EOpConvBoolToUint16:
+        zero = builder.makeUint16Constant(0);
+        one  = builder.makeUint16Constant(1);
+        convOp = spv::OpSelect;
+        break;
+    case glslang::EOpConvDoubleToFloat:
+    case glslang::EOpConvFloatToDouble:
+    case glslang::EOpConvDoubleToFloat16:
+    case glslang::EOpConvFloat16ToDouble:
+    case glslang::EOpConvFloatToFloat16:
+    case glslang::EOpConvFloat16ToFloat:
+        convOp = spv::OpFConvert;
+        if (builder.isMatrixType(destType))
+            return createUnaryMatrixOperation(convOp, decorations, destType, operand, typeProxy);
+        break;
+
     case glslang::EOpConvInt8ToInt16:
     case glslang::EOpConvInt8ToInt:
     case glslang::EOpConvInt8ToInt64:
@@ -6001,6 +6602,15 @@
     case glslang::EOpConvPtrToUint64:
         convOp = spv::OpConvertPtrToU;
         break;
+    case glslang::EOpConvPtrToUvec2:
+    case glslang::EOpConvUvec2ToPtr:
+        if (builder.isVector(operand))
+            builder.promoteIncorporatedExtension(spv::E_SPV_EXT_physical_storage_buffer,
+                                                 spv::E_SPV_KHR_physical_storage_buffer, spv::Spv_1_5);
+        convOp = spv::OpBitcast;
+        break;
+#endif
+
     default:
         break;
     }
@@ -6017,7 +6627,7 @@
         result = builder.createUnaryOp(convOp, destType, operand);
 
     result = builder.setPrecision(result, decorations.precision);
-    builder.addDecoration(result, decorations.nonUniform);
+    decorations.addNonUniform(builder, result);
     return result;
 }
 
@@ -6034,7 +6644,9 @@
 }
 
 // For glslang ops that map to SPV atomic opCodes
-spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv::Decoration /*precision*/, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy)
+spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv::Decoration /*precision*/,
+    spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy,
+    const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags)
 {
     spv::Op opCode = spv::OpNop;
 
@@ -6050,12 +6662,14 @@
     case glslang::EOpAtomicMin:
     case glslang::EOpImageAtomicMin:
     case glslang::EOpAtomicCounterMin:
-        opCode = (typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64) ? spv::OpAtomicUMin : spv::OpAtomicSMin;
+        opCode = (typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64) ?
+            spv::OpAtomicUMin : spv::OpAtomicSMin;
         break;
     case glslang::EOpAtomicMax:
     case glslang::EOpImageAtomicMax:
     case glslang::EOpAtomicCounterMax:
-        opCode = (typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64) ? spv::OpAtomicUMax : spv::OpAtomicSMax;
+        opCode = (typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64) ?
+            spv::OpAtomicUMax : spv::OpAtomicSMax;
         break;
     case glslang::EOpAtomicAnd:
     case glslang::EOpImageAtomicAnd:
@@ -6120,7 +6734,10 @@
         scopeId = builder.makeUintConstant(spv::ScopeDevice);
     }
     // semantics default to relaxed 
-    spv::Id semanticsId = builder.makeUintConstant(spv::MemorySemanticsMaskNone);
+    spv::Id semanticsId = builder.makeUintConstant(lvalueCoherentFlags.isVolatile() &&
+        glslangIntermediate->usingVulkanMemoryModel() ?
+                                                    spv::MemorySemanticsVolatileMask :
+                                                    spv::MemorySemanticsMaskNone);
     spv::Id semanticsId2 = semanticsId;
 
     pointerId = operands[0];
@@ -6131,26 +6748,33 @@
         valueId = operands[2];
         if (operands.size() > 3) {
             scopeId = operands[3];
-            semanticsId = builder.makeUintConstant(builder.getConstantScalar(operands[4]) | builder.getConstantScalar(operands[5]));
-            semanticsId2 = builder.makeUintConstant(builder.getConstantScalar(operands[6]) | builder.getConstantScalar(operands[7]));
+            semanticsId = builder.makeUintConstant(
+                builder.getConstantScalar(operands[4]) | builder.getConstantScalar(operands[5]));
+            semanticsId2 = builder.makeUintConstant(
+                builder.getConstantScalar(operands[6]) | builder.getConstantScalar(operands[7]));
         }
     } else if (opCode == spv::OpAtomicLoad) {
         if (operands.size() > 1) {
             scopeId = operands[1];
-            semanticsId = builder.makeUintConstant(builder.getConstantScalar(operands[2]) | builder.getConstantScalar(operands[3]));
+            semanticsId = builder.makeUintConstant(
+                builder.getConstantScalar(operands[2]) | builder.getConstantScalar(operands[3]));
         }
     } else {
         // atomic store or RMW
         valueId = operands[1];
         if (operands.size() > 2) {
             scopeId = operands[2];
-            semanticsId = builder.makeUintConstant(builder.getConstantScalar(operands[3]) | builder.getConstantScalar(operands[4]));
+            semanticsId = builder.makeUintConstant
+                (builder.getConstantScalar(operands[3]) | builder.getConstantScalar(operands[4]));
         }
     }
 
     // Check for capabilities
     unsigned semanticsImmediate = builder.getConstantScalar(semanticsId) | builder.getConstantScalar(semanticsId2);
-    if (semanticsImmediate & (spv::MemorySemanticsMakeAvailableKHRMask | spv::MemorySemanticsMakeVisibleKHRMask | spv::MemorySemanticsOutputMemoryKHRMask)) {
+    if (semanticsImmediate & (spv::MemorySemanticsMakeAvailableKHRMask |
+                              spv::MemorySemanticsMakeVisibleKHRMask |
+                              spv::MemorySemanticsOutputMemoryKHRMask |
+                              spv::MemorySemanticsVolatileMask)) {
         builder.addCapability(spv::CapabilityVulkanMemoryModelKHR);
     }
 
@@ -6186,12 +6810,11 @@
 }
 
 // Create group invocation operations.
-spv::Id TGlslangToSpvTraverser::createInvocationsOperation(glslang::TOperator op, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy)
+spv::Id TGlslangToSpvTraverser::createInvocationsOperation(glslang::TOperator op, spv::Id typeId,
+    std::vector<spv::Id>& operands, glslang::TBasicType typeProxy)
 {
-#ifdef AMD_EXTENSIONS
     bool isUnsigned = isTypeUnsignedInt(typeProxy);
     bool isFloat = isTypeFloat(typeProxy);
-#endif
 
     spv::Op opCode = spv::OpNop;
     std::vector<spv::IdImmediate> spvGroupOperands;
@@ -6208,7 +6831,6 @@
         builder.addCapability(spv::CapabilitySubgroupVoteKHR);
     } else {
         builder.addCapability(spv::CapabilityGroups);
-#ifdef AMD_EXTENSIONS
         if (op == glslang::EOpMinInvocationsNonUniform ||
             op == glslang::EOpMaxInvocationsNonUniform ||
             op == glslang::EOpAddInvocationsNonUniform ||
@@ -6219,9 +6841,7 @@
             op == glslang::EOpMaxInvocationsExclusiveScanNonUniform ||
             op == glslang::EOpAddInvocationsExclusiveScanNonUniform)
             builder.addExtension(spv::E_SPV_AMD_shader_ballot);
-#endif
 
-#ifdef AMD_EXTENSIONS
         switch (op) {
         case glslang::EOpMinInvocations:
         case glslang::EOpMaxInvocations:
@@ -6256,7 +6876,6 @@
             spv::IdImmediate groupOp = { false, (unsigned)groupOperation };
             spvGroupOperands.push_back(groupOp);
         }
-#endif
     }
 
     for (auto opIt = operands.begin(); opIt != operands.end(); ++opIt) {
@@ -6303,7 +6922,6 @@
                                      builder.createCompositeConstruct(uvec2Type, components));
     }
 
-#ifdef AMD_EXTENSIONS
     case glslang::EOpMinInvocations:
     case glslang::EOpMaxInvocations:
     case glslang::EOpAddInvocations:
@@ -6390,7 +7008,6 @@
             return CreateInvocationsVectorOperation(opCode, groupOperation, typeId, operands);
 
         break;
-#endif
     default:
         logger->missingFunctionality("invocation operation");
         return spv::NoResult;
@@ -6404,20 +7021,15 @@
 spv::Id TGlslangToSpvTraverser::CreateInvocationsVectorOperation(spv::Op op, spv::GroupOperation groupOperation,
     spv::Id typeId, std::vector<spv::Id>& operands)
 {
-#ifdef AMD_EXTENSIONS
     assert(op == spv::OpGroupFMin || op == spv::OpGroupUMin || op == spv::OpGroupSMin ||
            op == spv::OpGroupFMax || op == spv::OpGroupUMax || op == spv::OpGroupSMax ||
            op == spv::OpGroupFAdd || op == spv::OpGroupIAdd || op == spv::OpGroupBroadcast ||
            op == spv::OpSubgroupReadInvocationKHR ||
-           op == spv::OpGroupFMinNonUniformAMD || op == spv::OpGroupUMinNonUniformAMD || op == spv::OpGroupSMinNonUniformAMD ||
-           op == spv::OpGroupFMaxNonUniformAMD || op == spv::OpGroupUMaxNonUniformAMD || op == spv::OpGroupSMaxNonUniformAMD ||
+           op == spv::OpGroupFMinNonUniformAMD || op == spv::OpGroupUMinNonUniformAMD ||
+           op == spv::OpGroupSMinNonUniformAMD ||
+           op == spv::OpGroupFMaxNonUniformAMD || op == spv::OpGroupUMaxNonUniformAMD ||
+           op == spv::OpGroupSMaxNonUniformAMD ||
            op == spv::OpGroupFAddNonUniformAMD || op == spv::OpGroupIAddNonUniformAMD);
-#else
-    assert(op == spv::OpGroupFMin || op == spv::OpGroupUMin || op == spv::OpGroupSMin ||
-           op == spv::OpGroupFMax || op == spv::OpGroupUMax || op == spv::OpGroupSMax ||
-           op == spv::OpGroupFAdd || op == spv::OpGroupIAdd || op == spv::OpGroupBroadcast ||
-           op == spv::OpSubgroupReadInvocationKHR);
-#endif
 
     // Handle group invocation operations scalar by scalar.
     // The result type is the same type as the original type.
@@ -6541,7 +7153,6 @@
         builder.addCapability(spv::CapabilityGroupNonUniform);
         builder.addCapability(spv::CapabilityGroupNonUniformQuad);
         break;
-#ifdef NV_EXTENSIONS
     case glslang::EOpSubgroupPartitionedAdd:
     case glslang::EOpSubgroupPartitionedMul:
     case glslang::EOpSubgroupPartitionedMin:
@@ -6566,12 +7177,12 @@
         builder.addExtension(spv::E_SPV_NV_shader_subgroup_partitioned);
         builder.addCapability(spv::CapabilityGroupNonUniformPartitionedNV);
         break;
-#endif
     default: assert(0 && "Unhandled subgroup operation!");
     }
 
-    const bool isUnsigned = typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64;
-    const bool isFloat = typeProxy == glslang::EbtFloat || typeProxy == glslang::EbtDouble;
+
+    const bool isUnsigned = isTypeUnsignedInt(typeProxy);
+    const bool isFloat = isTypeFloat(typeProxy);
     const bool isBool = typeProxy == glslang::EbtBool;
 
     spv::Op opCode = spv::OpNop;
@@ -6600,11 +7211,9 @@
     case glslang::EOpSubgroupInclusiveAdd:
     case glslang::EOpSubgroupExclusiveAdd:
     case glslang::EOpSubgroupClusteredAdd:
-#ifdef NV_EXTENSIONS
     case glslang::EOpSubgroupPartitionedAdd:
     case glslang::EOpSubgroupPartitionedInclusiveAdd:
     case glslang::EOpSubgroupPartitionedExclusiveAdd:
-#endif
         if (isFloat) {
             opCode = spv::OpGroupNonUniformFAdd;
         } else {
@@ -6615,11 +7224,9 @@
     case glslang::EOpSubgroupInclusiveMul:
     case glslang::EOpSubgroupExclusiveMul:
     case glslang::EOpSubgroupClusteredMul:
-#ifdef NV_EXTENSIONS
     case glslang::EOpSubgroupPartitionedMul:
     case glslang::EOpSubgroupPartitionedInclusiveMul:
     case glslang::EOpSubgroupPartitionedExclusiveMul:
-#endif
         if (isFloat) {
             opCode = spv::OpGroupNonUniformFMul;
         } else {
@@ -6630,11 +7237,9 @@
     case glslang::EOpSubgroupInclusiveMin:
     case glslang::EOpSubgroupExclusiveMin:
     case glslang::EOpSubgroupClusteredMin:
-#ifdef NV_EXTENSIONS
     case glslang::EOpSubgroupPartitionedMin:
     case glslang::EOpSubgroupPartitionedInclusiveMin:
     case glslang::EOpSubgroupPartitionedExclusiveMin:
-#endif
         if (isFloat) {
             opCode = spv::OpGroupNonUniformFMin;
         } else if (isUnsigned) {
@@ -6647,11 +7252,9 @@
     case glslang::EOpSubgroupInclusiveMax:
     case glslang::EOpSubgroupExclusiveMax:
     case glslang::EOpSubgroupClusteredMax:
-#ifdef NV_EXTENSIONS
     case glslang::EOpSubgroupPartitionedMax:
     case glslang::EOpSubgroupPartitionedInclusiveMax:
     case glslang::EOpSubgroupPartitionedExclusiveMax:
-#endif
         if (isFloat) {
             opCode = spv::OpGroupNonUniformFMax;
         } else if (isUnsigned) {
@@ -6664,11 +7267,9 @@
     case glslang::EOpSubgroupInclusiveAnd:
     case glslang::EOpSubgroupExclusiveAnd:
     case glslang::EOpSubgroupClusteredAnd:
-#ifdef NV_EXTENSIONS
     case glslang::EOpSubgroupPartitionedAnd:
     case glslang::EOpSubgroupPartitionedInclusiveAnd:
     case glslang::EOpSubgroupPartitionedExclusiveAnd:
-#endif
         if (isBool) {
             opCode = spv::OpGroupNonUniformLogicalAnd;
         } else {
@@ -6679,11 +7280,9 @@
     case glslang::EOpSubgroupInclusiveOr:
     case glslang::EOpSubgroupExclusiveOr:
     case glslang::EOpSubgroupClusteredOr:
-#ifdef NV_EXTENSIONS
     case glslang::EOpSubgroupPartitionedOr:
     case glslang::EOpSubgroupPartitionedInclusiveOr:
     case glslang::EOpSubgroupPartitionedExclusiveOr:
-#endif
         if (isBool) {
             opCode = spv::OpGroupNonUniformLogicalOr;
         } else {
@@ -6694,11 +7293,9 @@
     case glslang::EOpSubgroupInclusiveXor:
     case glslang::EOpSubgroupExclusiveXor:
     case glslang::EOpSubgroupClusteredXor:
-#ifdef NV_EXTENSIONS
     case glslang::EOpSubgroupPartitionedXor:
     case glslang::EOpSubgroupPartitionedInclusiveXor:
     case glslang::EOpSubgroupPartitionedExclusiveXor:
-#endif
         if (isBool) {
             opCode = spv::OpGroupNonUniformLogicalXor;
         } else {
@@ -6756,7 +7353,6 @@
     case glslang::EOpSubgroupClusteredXor:
         groupOperation = spv::GroupOperationClusteredReduce;
         break;
-#ifdef NV_EXTENSIONS
     case glslang::EOpSubgroupPartitionedAdd:
     case glslang::EOpSubgroupPartitionedMul:
     case glslang::EOpSubgroupPartitionedMin:
@@ -6784,7 +7380,6 @@
     case glslang::EOpSubgroupPartitionedExclusiveXor:
         groupOperation = spv::GroupOperationPartitionedExclusiveScanNV;
         break;
-#endif
     }
 
     // build the instruction
@@ -6822,7 +7417,8 @@
     return builder.createOp(opCode, typeId, spvGroupOperands);
 }
 
-spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy)
+spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::Decoration precision,
+    spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy)
 {
     bool isUnsigned = isTypeUnsignedInt(typeProxy);
     bool isFloat = isTypeFloat(typeProxy);
@@ -6842,7 +7438,7 @@
     switch (op) {
     case glslang::EOpMin:
         if (isFloat)
-            libCall = spv::GLSLstd450FMin;
+            libCall = nanMinMaxClamp ? spv::GLSLstd450NMin : spv::GLSLstd450FMin;
         else if (isUnsigned)
             libCall = spv::GLSLstd450UMin;
         else
@@ -6854,7 +7450,7 @@
         break;
     case glslang::EOpMax:
         if (isFloat)
-            libCall = spv::GLSLstd450FMax;
+            libCall = nanMinMaxClamp ? spv::GLSLstd450NMax : spv::GLSLstd450FMax;
         else if (isUnsigned)
             libCall = spv::GLSLstd450UMax;
         else
@@ -6873,7 +7469,7 @@
 
     case glslang::EOpClamp:
         if (isFloat)
-            libCall = spv::GLSLstd450FClamp;
+            libCall = nanMinMaxClamp ? spv::GLSLstd450NClamp : spv::GLSLstd450FClamp;
         else if (isUnsigned)
             libCall = spv::GLSLstd450UClamp;
         else
@@ -6916,18 +7512,59 @@
     case glslang::EOpRefract:
         libCall = spv::GLSLstd450Refract;
         break;
+    case glslang::EOpBarrier:
+        {
+            // This is for the extended controlBarrier function, with four operands.
+            // The unextended barrier() goes through createNoArgOperation.
+            assert(operands.size() == 4);
+            unsigned int executionScope = builder.getConstantScalar(operands[0]);
+            unsigned int memoryScope = builder.getConstantScalar(operands[1]);
+            unsigned int semantics = builder.getConstantScalar(operands[2]) | builder.getConstantScalar(operands[3]);
+            builder.createControlBarrier((spv::Scope)executionScope, (spv::Scope)memoryScope,
+                (spv::MemorySemanticsMask)semantics);
+            if (semantics & (spv::MemorySemanticsMakeAvailableKHRMask |
+                             spv::MemorySemanticsMakeVisibleKHRMask |
+                             spv::MemorySemanticsOutputMemoryKHRMask |
+                             spv::MemorySemanticsVolatileMask)) {
+                builder.addCapability(spv::CapabilityVulkanMemoryModelKHR);
+            }
+            if (glslangIntermediate->usingVulkanMemoryModel() && (executionScope == spv::ScopeDevice ||
+                memoryScope == spv::ScopeDevice)) {
+                builder.addCapability(spv::CapabilityVulkanMemoryModelDeviceScopeKHR);
+            }
+            return 0;
+        }
+        break;
+    case glslang::EOpMemoryBarrier:
+        {
+            // This is for the extended memoryBarrier function, with three operands.
+            // The unextended memoryBarrier() goes through createNoArgOperation.
+            assert(operands.size() == 3);
+            unsigned int memoryScope = builder.getConstantScalar(operands[0]);
+            unsigned int semantics = builder.getConstantScalar(operands[1]) | builder.getConstantScalar(operands[2]);
+            builder.createMemoryBarrier((spv::Scope)memoryScope, (spv::MemorySemanticsMask)semantics);
+            if (semantics & (spv::MemorySemanticsMakeAvailableKHRMask |
+                             spv::MemorySemanticsMakeVisibleKHRMask |
+                             spv::MemorySemanticsOutputMemoryKHRMask |
+                             spv::MemorySemanticsVolatileMask)) {
+                builder.addCapability(spv::CapabilityVulkanMemoryModelKHR);
+            }
+            if (glslangIntermediate->usingVulkanMemoryModel() && memoryScope == spv::ScopeDevice) {
+                builder.addCapability(spv::CapabilityVulkanMemoryModelDeviceScopeKHR);
+            }
+            return 0;
+        }
+        break;
+
+#ifndef GLSLANG_WEB
     case glslang::EOpInterpolateAtSample:
-#ifdef AMD_EXTENSIONS
         if (typeProxy == glslang::EbtFloat16)
             builder.addExtension(spv::E_SPV_AMD_gpu_shader_half_float);
-#endif
         libCall = spv::GLSLstd450InterpolateAtSample;
         break;
     case glslang::EOpInterpolateAtOffset:
-#ifdef AMD_EXTENSIONS
         if (typeProxy == glslang::EbtFloat16)
             builder.addExtension(spv::E_SPV_AMD_gpu_shader_half_float);
-#endif
         libCall = spv::GLSLstd450InterpolateAtOffset;
         break;
     case glslang::EOpAddCarry:
@@ -6969,15 +7606,14 @@
             assert(builder.isPointerType(typeId1));
             typeId1 = builder.getContainedTypeId(typeId1);
             int width = builder.getScalarTypeWidth(typeId1);
-#ifdef AMD_EXTENSIONS
             if (width == 16)
                 // Using 16-bit exp operand, enable extension SPV_AMD_gpu_shader_int16
                 builder.addExtension(spv::E_SPV_AMD_gpu_shader_int16);
-#endif
             if (builder.getNumComponents(operands[0]) == 1)
                 frexpIntType = builder.makeIntegerType(width, true);
             else
-                frexpIntType = builder.makeVectorType(builder.makeIntegerType(width, true), builder.getNumComponents(operands[0]));
+                frexpIntType = builder.makeVectorType(builder.makeIntegerType(width, true),
+                    builder.getNumComponents(operands[0]));
             typeId = builder.makeStructResultType(typeId0, frexpIntType);
             consumedOperands = 1;
         }
@@ -7003,7 +7639,6 @@
     case glslang::EOpSubgroupClusteredOr:
     case glslang::EOpSubgroupClusteredXor:
     case glslang::EOpSubgroupQuadBroadcast:
-#ifdef NV_EXTENSIONS
     case glslang::EOpSubgroupPartitionedAdd:
     case glslang::EOpSubgroupPartitionedMul:
     case glslang::EOpSubgroupPartitionedMin:
@@ -7025,10 +7660,8 @@
     case glslang::EOpSubgroupPartitionedExclusiveAnd:
     case glslang::EOpSubgroupPartitionedExclusiveOr:
     case glslang::EOpSubgroupPartitionedExclusiveXor:
-#endif
         return createSubgroupOperation(op, typeId, operands, typeProxy);
 
-#ifdef AMD_EXTENSIONS
     case glslang::EOpSwizzleInvocations:
         extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_ballot);
         libCall = spv::SwizzleInvocationsAMD;
@@ -7082,70 +7715,113 @@
         extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_explicit_vertex_parameter);
         libCall = spv::InterpolateAtVertexAMD;
         break;
-#endif
-    case glslang::EOpBarrier:
-        {
-            // This is for the extended controlBarrier function, with four operands.
-            // The unextended barrier() goes through createNoArgOperation.
-            assert(operands.size() == 4);
-            unsigned int executionScope = builder.getConstantScalar(operands[0]);
-            unsigned int memoryScope = builder.getConstantScalar(operands[1]);
-            unsigned int semantics = builder.getConstantScalar(operands[2]) | builder.getConstantScalar(operands[3]);
-            builder.createControlBarrier((spv::Scope)executionScope, (spv::Scope)memoryScope, (spv::MemorySemanticsMask)semantics);
-            if (semantics & (spv::MemorySemanticsMakeAvailableKHRMask | spv::MemorySemanticsMakeVisibleKHRMask | spv::MemorySemanticsOutputMemoryKHRMask)) {
-                builder.addCapability(spv::CapabilityVulkanMemoryModelKHR);
-            }
-            if (glslangIntermediate->usingVulkanMemoryModel() && (executionScope == spv::ScopeDevice || memoryScope == spv::ScopeDevice)) {
-                builder.addCapability(spv::CapabilityVulkanMemoryModelDeviceScopeKHR);
-            }
-            return 0;
-        }
-        break;
-    case glslang::EOpMemoryBarrier:
-        {
-            // This is for the extended memoryBarrier function, with three operands.
-            // The unextended memoryBarrier() goes through createNoArgOperation.
-            assert(operands.size() == 3);
-            unsigned int memoryScope = builder.getConstantScalar(operands[0]);
-            unsigned int semantics = builder.getConstantScalar(operands[1]) | builder.getConstantScalar(operands[2]);
-            builder.createMemoryBarrier((spv::Scope)memoryScope, (spv::MemorySemanticsMask)semantics);
-            if (semantics & (spv::MemorySemanticsMakeAvailableKHRMask | spv::MemorySemanticsMakeVisibleKHRMask | spv::MemorySemanticsOutputMemoryKHRMask)) {
-                builder.addCapability(spv::CapabilityVulkanMemoryModelKHR);
-            }
-            if (glslangIntermediate->usingVulkanMemoryModel() && memoryScope == spv::ScopeDevice) {
-                builder.addCapability(spv::CapabilityVulkanMemoryModelDeviceScopeKHR);
-            }
-            return 0;
-        }
-        break;
 
-#ifdef NV_EXTENSIONS
-    case glslang::EOpReportIntersectionNV:
-    {
+    case glslang::EOpReportIntersection:
         typeId = builder.makeBoolType();
-        opCode = spv::OpReportIntersectionNV;
-    }
-    break;
-    case glslang::EOpTraceNV:
-    {
-        builder.createNoResultOp(spv::OpTraceNV, operands);
+        opCode = spv::OpReportIntersectionKHR;
+        break;
+    case glslang::EOpTrace:
+        builder.createNoResultOp(spv::OpTraceRayKHR, operands);
         return 0;
-    }
-    break;
-    case glslang::EOpExecuteCallableNV:
-    {
-        builder.createNoResultOp(spv::OpExecuteCallableNV, operands);
+    case glslang::EOpExecuteCallable:
+        builder.createNoResultOp(spv::OpExecuteCallableKHR, operands);
         return 0;
-    }
-    break;
+
+    case glslang::EOpRayQueryInitialize:
+        builder.createNoResultOp(spv::OpRayQueryInitializeKHR, operands);
+        return 0;
+    case glslang::EOpRayQueryTerminate:
+        builder.createNoResultOp(spv::OpRayQueryTerminateKHR, operands);
+        return 0;
+    case glslang::EOpRayQueryGenerateIntersection:
+        builder.createNoResultOp(spv::OpRayQueryGenerateIntersectionKHR, operands);
+        return 0;
+    case glslang::EOpRayQueryConfirmIntersection:
+        builder.createNoResultOp(spv::OpRayQueryConfirmIntersectionKHR, operands);
+        return 0;
+    case glslang::EOpRayQueryProceed:
+        typeId = builder.makeBoolType();
+        opCode = spv::OpRayQueryProceedKHR;
+        break;
+    case glslang::EOpRayQueryGetIntersectionType:
+        typeId = builder.makeUintType(32);
+        opCode = spv::OpRayQueryGetIntersectionTypeKHR;
+        break;
+    case glslang::EOpRayQueryGetRayTMin:
+        typeId = builder.makeFloatType(32);
+        opCode = spv::OpRayQueryGetRayTMinKHR;
+        break;
+    case glslang::EOpRayQueryGetRayFlags:
+        typeId = builder.makeIntType(32);
+        opCode = spv::OpRayQueryGetRayFlagsKHR;
+        break;
+    case glslang::EOpRayQueryGetIntersectionT:
+        typeId = builder.makeFloatType(32);
+        opCode = spv::OpRayQueryGetIntersectionTKHR;
+        break;
+    case glslang::EOpRayQueryGetIntersectionInstanceCustomIndex:
+        typeId = builder.makeIntType(32);
+        opCode = spv::OpRayQueryGetIntersectionInstanceCustomIndexKHR;
+        break;
+    case glslang::EOpRayQueryGetIntersectionInstanceId:
+        typeId = builder.makeIntType(32);
+        opCode = spv::OpRayQueryGetIntersectionInstanceIdKHR;
+        break;
+    case glslang::EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset:
+        typeId = builder.makeIntType(32);
+        opCode = spv::OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR;
+        break;
+    case glslang::EOpRayQueryGetIntersectionGeometryIndex:
+        typeId = builder.makeIntType(32);
+        opCode = spv::OpRayQueryGetIntersectionGeometryIndexKHR;
+        break;
+    case glslang::EOpRayQueryGetIntersectionPrimitiveIndex:
+        typeId = builder.makeIntType(32);
+        opCode = spv::OpRayQueryGetIntersectionPrimitiveIndexKHR;
+        break;
+    case glslang::EOpRayQueryGetIntersectionBarycentrics:
+        typeId = builder.makeVectorType(builder.makeFloatType(32), 2);
+        opCode = spv::OpRayQueryGetIntersectionBarycentricsKHR;
+        break;
+    case glslang::EOpRayQueryGetIntersectionFrontFace:
+        typeId = builder.makeBoolType();
+        opCode = spv::OpRayQueryGetIntersectionFrontFaceKHR;
+        break;
+    case glslang::EOpRayQueryGetIntersectionCandidateAABBOpaque:
+        typeId = builder.makeBoolType();
+        opCode = spv::OpRayQueryGetIntersectionCandidateAABBOpaqueKHR;
+        break;
+    case glslang::EOpRayQueryGetIntersectionObjectRayDirection:
+        typeId = builder.makeVectorType(builder.makeFloatType(32), 3);
+        opCode = spv::OpRayQueryGetIntersectionObjectRayDirectionKHR;
+        break;
+    case glslang::EOpRayQueryGetIntersectionObjectRayOrigin:
+        typeId = builder.makeVectorType(builder.makeFloatType(32), 3);
+        opCode = spv::OpRayQueryGetIntersectionObjectRayOriginKHR;
+        break;
+    case glslang::EOpRayQueryGetWorldRayDirection:
+        typeId = builder.makeVectorType(builder.makeFloatType(32), 3);
+        opCode = spv::OpRayQueryGetWorldRayDirectionKHR;
+        break;
+    case glslang::EOpRayQueryGetWorldRayOrigin:
+        typeId = builder.makeVectorType(builder.makeFloatType(32), 3);
+        opCode = spv::OpRayQueryGetWorldRayOriginKHR;
+        break;
+    case glslang::EOpRayQueryGetIntersectionObjectToWorld:
+        typeId = builder.makeMatrixType(builder.makeFloatType(32), 4, 3);
+        opCode = spv::OpRayQueryGetIntersectionObjectToWorldKHR;
+        break;
+    case glslang::EOpRayQueryGetIntersectionWorldToObject:
+        typeId = builder.makeMatrixType(builder.makeFloatType(32), 4, 3);
+        opCode = spv::OpRayQueryGetIntersectionWorldToObjectKHR;
+        break;
     case glslang::EOpWritePackedPrimitiveIndices4x8NV:
         builder.createNoResultOp(spv::OpWritePackedPrimitiveIndices4x8NV, operands);
         return 0;
-#endif
     case glslang::EOpCooperativeMatrixMulAdd:
         opCode = spv::OpCooperativeMatrixMulAddNV;
         break;
-
+#endif // GLSLANG_WEB
     default:
         return 0;
     }
@@ -7166,7 +7842,7 @@
         id = builder.createCompositeExtract(mulOp, typeId, 0);
         for (int i = 1; i < componentCount; ++i) {
             builder.setPrecision(id, precision);
-            id = builder.createBinOp(spv::OpIAdd, typeId, id, builder.createCompositeExtract(operands[0], typeId, i));
+            id = builder.createBinOp(spv::OpIAdd, typeId, id, builder.createCompositeExtract(mulOp, typeId, i));
         }
     } else {
         switch (consumedOperands) {
@@ -7189,6 +7865,7 @@
         }
     }
 
+#ifndef GLSLANG_WEB
     // Decode the return types that were structures
     switch (op) {
     case glslang::EOpAddCarry:
@@ -7218,6 +7895,7 @@
     default:
         break;
     }
+#endif
 
     return builder.setPrecision(id, precision);
 }
@@ -7226,15 +7904,10 @@
 spv::Id TGlslangToSpvTraverser::createNoArgOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId)
 {
     // GLSL memory barriers use queuefamily scope in new model, device scope in old model
-    spv::Scope memoryBarrierScope = glslangIntermediate->usingVulkanMemoryModel() ? spv::ScopeQueueFamilyKHR : spv::ScopeDevice;
+    spv::Scope memoryBarrierScope = glslangIntermediate->usingVulkanMemoryModel() ?
+        spv::ScopeQueueFamilyKHR : spv::ScopeDevice;
 
     switch (op) {
-    case glslang::EOpEmitVertex:
-        builder.createNoResultOp(spv::OpEmitVertex);
-        return 0;
-    case glslang::EOpEndPrimitive:
-        builder.createNoResultOp(spv::OpEndPrimitive);
-        return 0;
     case glslang::EOpBarrier:
         if (glslangIntermediate->getStage() == EShLangTessControl) {
             if (glslangIntermediate->usingVulkanMemoryModel()) {
@@ -7255,18 +7928,10 @@
         builder.createMemoryBarrier(memoryBarrierScope, spv::MemorySemanticsAllMemory |
                                                         spv::MemorySemanticsAcquireReleaseMask);
         return 0;
-    case glslang::EOpMemoryBarrierAtomicCounter:
-        builder.createMemoryBarrier(memoryBarrierScope, spv::MemorySemanticsAtomicCounterMemoryMask |
-                                                        spv::MemorySemanticsAcquireReleaseMask);
-        return 0;
     case glslang::EOpMemoryBarrierBuffer:
         builder.createMemoryBarrier(memoryBarrierScope, spv::MemorySemanticsUniformMemoryMask |
                                                         spv::MemorySemanticsAcquireReleaseMask);
         return 0;
-    case glslang::EOpMemoryBarrierImage:
-        builder.createMemoryBarrier(memoryBarrierScope, spv::MemorySemanticsImageMemoryMask |
-                                                        spv::MemorySemanticsAcquireReleaseMask);
-        return 0;
     case glslang::EOpMemoryBarrierShared:
         builder.createMemoryBarrier(memoryBarrierScope, spv::MemorySemanticsWorkgroupMemoryMask |
                                                         spv::MemorySemanticsAcquireReleaseMask);
@@ -7275,6 +7940,15 @@
         builder.createMemoryBarrier(spv::ScopeWorkgroup, spv::MemorySemanticsAllMemory |
                                                          spv::MemorySemanticsAcquireReleaseMask);
         return 0;
+#ifndef GLSLANG_WEB
+    case glslang::EOpMemoryBarrierAtomicCounter:
+        builder.createMemoryBarrier(memoryBarrierScope, spv::MemorySemanticsAtomicCounterMemoryMask |
+                                                        spv::MemorySemanticsAcquireReleaseMask);
+        return 0;
+    case glslang::EOpMemoryBarrierImage:
+        builder.createMemoryBarrier(memoryBarrierScope, spv::MemorySemanticsImageMemoryMask |
+                                                        spv::MemorySemanticsAcquireReleaseMask);
+        return 0;
     case glslang::EOpAllMemoryBarrierWithGroupSync:
         builder.createControlBarrier(spv::ScopeWorkgroup, spv::ScopeDevice,
                                         spv::MemorySemanticsAllMemory |
@@ -7319,30 +7993,80 @@
         builder.createMemoryBarrier(spv::ScopeSubgroup, spv::MemorySemanticsWorkgroupMemoryMask |
                                                         spv::MemorySemanticsAcquireReleaseMask);
         return spv::NoResult;
+
+    case glslang::EOpEmitVertex:
+        builder.createNoResultOp(spv::OpEmitVertex);
+        return 0;
+    case glslang::EOpEndPrimitive:
+        builder.createNoResultOp(spv::OpEndPrimitive);
+        return 0;
+
     case glslang::EOpSubgroupElect: {
         std::vector<spv::Id> operands;
         return createSubgroupOperation(op, typeId, operands, glslang::EbtVoid);
     }
-#ifdef AMD_EXTENSIONS
     case glslang::EOpTime:
     {
         std::vector<spv::Id> args; // Dummy arguments
         spv::Id id = builder.createBuiltinCall(typeId, getExtBuiltins(spv::E_SPV_AMD_gcn_shader), spv::TimeAMD, args);
         return builder.setPrecision(id, precision);
     }
-#endif
-#ifdef NV_EXTENSIONS
-    case glslang::EOpIgnoreIntersectionNV:
-        builder.createNoResultOp(spv::OpIgnoreIntersectionNV);
+    case glslang::EOpIgnoreIntersection:
+        builder.createNoResultOp(spv::OpIgnoreIntersectionKHR);
         return 0;
-    case glslang::EOpTerminateRayNV:
-        builder.createNoResultOp(spv::OpTerminateRayNV);
+    case glslang::EOpTerminateRay:
+        builder.createNoResultOp(spv::OpTerminateRayKHR);
         return 0;
+    case glslang::EOpRayQueryInitialize:
+        builder.createNoResultOp(spv::OpRayQueryInitializeKHR);
+        return 0;
+    case glslang::EOpRayQueryTerminate:
+        builder.createNoResultOp(spv::OpRayQueryTerminateKHR);
+        return 0;
+    case glslang::EOpRayQueryGenerateIntersection:
+        builder.createNoResultOp(spv::OpRayQueryGenerateIntersectionKHR);
+        return 0;
+    case glslang::EOpRayQueryConfirmIntersection:
+        builder.createNoResultOp(spv::OpRayQueryConfirmIntersectionKHR);
+        return 0;
+    case glslang::EOpBeginInvocationInterlock:
+        builder.createNoResultOp(spv::OpBeginInvocationInterlockEXT);
+        return 0;
+    case glslang::EOpEndInvocationInterlock:
+        builder.createNoResultOp(spv::OpEndInvocationInterlockEXT);
+        return 0;
+
+    case glslang::EOpIsHelperInvocation:
+    {
+        std::vector<spv::Id> args; // Dummy arguments
+        builder.addExtension(spv::E_SPV_EXT_demote_to_helper_invocation);
+        builder.addCapability(spv::CapabilityDemoteToHelperInvocationEXT);
+        return builder.createOp(spv::OpIsHelperInvocationEXT, typeId, args);
+    }
+
+    case glslang::EOpReadClockSubgroupKHR: {
+        std::vector<spv::Id> args;
+        args.push_back(builder.makeUintConstant(spv::ScopeSubgroup));
+        builder.addExtension(spv::E_SPV_KHR_shader_clock);
+        builder.addCapability(spv::CapabilityShaderClockKHR);
+        return builder.createOp(spv::OpReadClockKHR, typeId, args);
+    }
+
+    case glslang::EOpReadClockDeviceKHR: {
+        std::vector<spv::Id> args;
+        args.push_back(builder.makeUintConstant(spv::ScopeDevice));
+        builder.addExtension(spv::E_SPV_KHR_shader_clock);
+        builder.addCapability(spv::CapabilityShaderClockKHR);
+        return builder.createOp(spv::OpReadClockKHR, typeId, args);
+    }
 #endif
     default:
-        logger->missingFunctionality("unknown operation with no arguments");
-        return 0;
+        break;
     }
+
+    logger->missingFunctionality("unknown operation with no arguments");
+
+    return 0;
 }
 
 spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol)
@@ -7355,22 +8079,26 @@
     }
 
     // it was not found, create it
-    id = createSpvVariable(symbol);
+    spv::BuiltIn builtIn = TranslateBuiltInDecoration(symbol->getQualifier().builtIn, false);
+    auto forcedType = getForcedType(symbol->getQualifier().builtIn, symbol->getType());
+    id = createSpvVariable(symbol, forcedType.first);
     symbolValues[symbol->getId()] = id;
+    if (forcedType.second != spv::NoType)
+        forceType[id] = forcedType.second;
 
     if (symbol->getBasicType() != glslang::EbtBlock) {
         builder.addDecoration(id, TranslatePrecisionDecoration(symbol->getType()));
         builder.addDecoration(id, TranslateInterpolationDecoration(symbol->getType().getQualifier()));
         builder.addDecoration(id, TranslateAuxiliaryStorageDecoration(symbol->getType().getQualifier()));
-#ifdef NV_EXTENSIONS
+#ifndef GLSLANG_WEB
         addMeshNVDecoration(id, /*member*/ -1, symbol->getType().getQualifier());
+        if (symbol->getQualifier().hasComponent())
+            builder.addDecoration(id, spv::DecorationComponent, symbol->getQualifier().layoutComponent);
+        if (symbol->getQualifier().hasIndex())
+            builder.addDecoration(id, spv::DecorationIndex, symbol->getQualifier().layoutIndex);
 #endif
         if (symbol->getType().getQualifier().hasSpecConstantId())
             builder.addDecoration(id, spv::DecorationSpecId, symbol->getType().getQualifier().layoutSpecConstantId);
-        if (symbol->getQualifier().hasIndex())
-            builder.addDecoration(id, spv::DecorationIndex, symbol->getQualifier().layoutIndex);
-        if (symbol->getQualifier().hasComponent())
-            builder.addDecoration(id, spv::DecorationComponent, symbol->getQualifier().layoutComponent);
         // atomic counters use this:
         if (symbol->getQualifier().hasOffset())
             builder.addDecoration(id, spv::DecorationOffset, symbol->getQualifier().layoutOffset);
@@ -7409,22 +8137,23 @@
             builder.addDecoration(id, spv::DecorationOffset, symbol->getQualifier().layoutXfbOffset);
     }
 
+    // add built-in variable decoration
+    if (builtIn != spv::BuiltInMax) {
+        builder.addDecoration(id, spv::DecorationBuiltIn, (int)builtIn);
+    }
+
+#ifndef GLSLANG_WEB
     if (symbol->getType().isImage()) {
         std::vector<spv::Decoration> memory;
-        TranslateMemoryDecoration(symbol->getType().getQualifier(), memory, glslangIntermediate->usingVulkanMemoryModel());
+        TranslateMemoryDecoration(symbol->getType().getQualifier(), memory,
+            glslangIntermediate->usingVulkanMemoryModel());
         for (unsigned int i = 0; i < memory.size(); ++i)
             builder.addDecoration(id, memory[i]);
     }
 
-    // built-in variable decorations
-    spv::BuiltIn builtIn = TranslateBuiltInDecoration(symbol->getQualifier().builtIn, false);
-    if (builtIn != spv::BuiltInMax)
-        builder.addDecoration(id, spv::DecorationBuiltIn, (int)builtIn);
-
     // nonuniform
     builder.addDecoration(id, TranslateNonUniformDecoration(symbol->getType().getQualifier()));
 
-#ifdef NV_EXTENSIONS
     if (builtIn == spv::BuiltInSampleMask) {
           spv::Decoration decoration;
           // GL_NV_sample_mask_override_coverage extension
@@ -7434,6 +8163,7 @@
               decoration = (spv::Decoration)spv::DecorationMax;
         builder.addDecoration(id, decoration);
         if (decoration != spv::DecorationMax) {
+            builder.addCapability(spv::CapabilitySampleMaskOverrideCoverageNV);
             builder.addExtension(spv::E_SPV_NV_sample_mask_override_coverage);
         }
     }
@@ -7462,7 +8192,6 @@
         builder.addCapability(spv::CapabilityFragmentBarycentricNV);
         builder.addExtension(spv::E_SPV_NV_fragment_shader_barycentric);
     }
-#endif
 
     if (glslangIntermediate->getHlslFunctionality1() && symbol->getType().getQualifier().semanticName != nullptr) {
         builder.addExtension("SPV_GOOGLE_hlsl_functionality1");
@@ -7470,14 +8199,16 @@
                               symbol->getType().getQualifier().semanticName);
     }
 
-    if (symbol->getBasicType() == glslang::EbtReference) {
-        builder.addDecoration(id, symbol->getType().getQualifier().restrict ? spv::DecorationRestrictPointerEXT : spv::DecorationAliasedPointerEXT);
+    if (symbol->isReference()) {
+        builder.addDecoration(id, symbol->getType().getQualifier().restrict ?
+            spv::DecorationRestrictPointerEXT : spv::DecorationAliasedPointerEXT);
     }
+#endif
 
     return id;
 }
 
-#ifdef NV_EXTENSIONS
+#ifndef GLSLANG_WEB
 // add per-primitive, per-view. per-task decorations to a struct member (member >= 0) or an object
 void TGlslangToSpvTraverser::addMeshNVDecoration(spv::Id id, int member, const glslang::TQualifier& qualifier)
 {
@@ -7532,8 +8263,9 @@
         // hand off to the non-spec-constant path
         assert(node.getAsConstantUnion() != nullptr || node.getAsSymbolNode() != nullptr);
         int nextConst = 0;
-        return createSpvConstantFromConstUnionArray(node.getType(), node.getAsConstantUnion() ? node.getAsConstantUnion()->getConstArray() : node.getAsSymbolNode()->getConstArray(),
-                                 nextConst, false);
+        return createSpvConstantFromConstUnionArray(node.getType(), node.getAsConstantUnion() ?
+            node.getAsConstantUnion()->getConstArray() : node.getAsSymbolNode()->getConstArray(),
+            nextConst, false);
     }
 
     // We now know we have a specialization constant to build
@@ -7586,7 +8318,8 @@
 // If there are not enough elements present in 'consts', 0 will be substituted;
 // an empty 'consts' can be used to create a fully zeroed SPIR-V constant.
 //
-spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glslang::TType& glslangType, const glslang::TConstUnionArray& consts, int& nextConst, bool specConstant)
+spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glslang::TType& glslangType,
+    const glslang::TConstUnionArray& consts, int& nextConst, bool specConstant)
 {
     // vector of constants for SPIR-V
     std::vector<spv::Id> spvConsts;
@@ -7613,6 +8346,19 @@
         for (unsigned int i = 0; i < (unsigned int)glslangType.getVectorSize(); ++i) {
             bool zero = nextConst >= consts.size();
             switch (glslangType.getBasicType()) {
+            case glslang::EbtInt:
+                spvConsts.push_back(builder.makeIntConstant(zero ? 0 : consts[nextConst].getIConst()));
+                break;
+            case glslang::EbtUint:
+                spvConsts.push_back(builder.makeUintConstant(zero ? 0 : consts[nextConst].getUConst()));
+                break;
+            case glslang::EbtFloat:
+                spvConsts.push_back(builder.makeFloatConstant(zero ? 0.0F : (float)consts[nextConst].getDConst()));
+                break;
+            case glslang::EbtBool:
+                spvConsts.push_back(builder.makeBoolConstant(zero ? false : consts[nextConst].getBConst()));
+                break;
+#ifndef GLSLANG_WEB
             case glslang::EbtInt8:
                 spvConsts.push_back(builder.makeInt8Constant(zero ? 0 : consts[nextConst].getI8Const()));
                 break;
@@ -7625,30 +8371,19 @@
             case glslang::EbtUint16:
                 spvConsts.push_back(builder.makeUint16Constant(zero ? 0 : consts[nextConst].getU16Const()));
                 break;
-            case glslang::EbtInt:
-                spvConsts.push_back(builder.makeIntConstant(zero ? 0 : consts[nextConst].getIConst()));
-                break;
-            case glslang::EbtUint:
-                spvConsts.push_back(builder.makeUintConstant(zero ? 0 : consts[nextConst].getUConst()));
-                break;
             case glslang::EbtInt64:
                 spvConsts.push_back(builder.makeInt64Constant(zero ? 0 : consts[nextConst].getI64Const()));
                 break;
             case glslang::EbtUint64:
                 spvConsts.push_back(builder.makeUint64Constant(zero ? 0 : consts[nextConst].getU64Const()));
                 break;
-            case glslang::EbtFloat:
-                spvConsts.push_back(builder.makeFloatConstant(zero ? 0.0F : (float)consts[nextConst].getDConst()));
-                break;
             case glslang::EbtDouble:
                 spvConsts.push_back(builder.makeDoubleConstant(zero ? 0.0 : consts[nextConst].getDConst()));
                 break;
             case glslang::EbtFloat16:
                 spvConsts.push_back(builder.makeFloat16Constant(zero ? 0.0F : (float)consts[nextConst].getDConst()));
                 break;
-            case glslang::EbtBool:
-                spvConsts.push_back(builder.makeBoolConstant(zero ? false : consts[nextConst].getBConst()));
-                break;
+#endif
             default:
                 assert(0);
                 break;
@@ -7660,6 +8395,19 @@
         bool zero = nextConst >= consts.size();
         spv::Id scalar = 0;
         switch (glslangType.getBasicType()) {
+        case glslang::EbtInt:
+            scalar = builder.makeIntConstant(zero ? 0 : consts[nextConst].getIConst(), specConstant);
+            break;
+        case glslang::EbtUint:
+            scalar = builder.makeUintConstant(zero ? 0 : consts[nextConst].getUConst(), specConstant);
+            break;
+        case glslang::EbtFloat:
+            scalar = builder.makeFloatConstant(zero ? 0.0F : (float)consts[nextConst].getDConst(), specConstant);
+            break;
+        case glslang::EbtBool:
+            scalar = builder.makeBoolConstant(zero ? false : consts[nextConst].getBConst(), specConstant);
+            break;
+#ifndef GLSLANG_WEB
         case glslang::EbtInt8:
             scalar = builder.makeInt8Constant(zero ? 0 : consts[nextConst].getI8Const(), specConstant);
             break;
@@ -7672,34 +8420,26 @@
         case glslang::EbtUint16:
             scalar = builder.makeUint16Constant(zero ? 0 : consts[nextConst].getU16Const(), specConstant);
             break;
-        case glslang::EbtInt:
-            scalar = builder.makeIntConstant(zero ? 0 : consts[nextConst].getIConst(), specConstant);
-            break;
-        case glslang::EbtUint:
-            scalar = builder.makeUintConstant(zero ? 0 : consts[nextConst].getUConst(), specConstant);
-            break;
         case glslang::EbtInt64:
             scalar = builder.makeInt64Constant(zero ? 0 : consts[nextConst].getI64Const(), specConstant);
             break;
         case glslang::EbtUint64:
             scalar = builder.makeUint64Constant(zero ? 0 : consts[nextConst].getU64Const(), specConstant);
             break;
-        case glslang::EbtFloat:
-            scalar = builder.makeFloatConstant(zero ? 0.0F : (float)consts[nextConst].getDConst(), specConstant);
-            break;
         case glslang::EbtDouble:
             scalar = builder.makeDoubleConstant(zero ? 0.0 : consts[nextConst].getDConst(), specConstant);
             break;
         case glslang::EbtFloat16:
             scalar = builder.makeFloat16Constant(zero ? 0.0F : (float)consts[nextConst].getDConst(), specConstant);
             break;
-        case glslang::EbtBool:
-            scalar = builder.makeBoolConstant(zero ? false : consts[nextConst].getBConst(), specConstant);
-            break;
         case glslang::EbtReference:
             scalar = builder.makeUint64Constant(zero ? 0 : consts[nextConst].getU64Const(), specConstant);
             scalar = builder.createUnaryOp(spv::OpBitcast, typeId, scalar);
             break;
+#endif
+        case glslang::EbtString:
+            scalar = builder.getStringId(consts[nextConst].getSConst()->c_str());
+            break;
         default:
             assert(0);
             break;
@@ -7800,7 +8540,8 @@
 
 // Emit short-circuiting code, where 'right' is never evaluated unless
 // the left side is true (for &&) or false (for ||).
-spv::Id TGlslangToSpvTraverser::createShortCircuit(glslang::TOperator op, glslang::TIntermTyped& left, glslang::TIntermTyped& right)
+spv::Id TGlslangToSpvTraverser::createShortCircuit(glslang::TOperator op, glslang::TIntermTyped& left,
+    glslang::TIntermTyped& right)
 {
     spv::Id boolTypeId = builder.makeBoolType();
 
@@ -7843,7 +8584,7 @@
     return builder.createOp(spv::OpPhi, boolTypeId, phiOperands);
 }
 
-#ifdef AMD_EXTENSIONS
+#ifndef GLSLANG_WEB
 // Return type Id of the imported set of extended instructions corresponds to the name.
 // Import this set if it has not been imported yet.
 spv::Id TGlslangToSpvTraverser::getExtBuiltins(const char* name)
@@ -7883,7 +8624,8 @@
     // return 5; // make OpArrayLength result type be an int with signedness of 0
     // return 6; // revert version 5 change, which makes a different (new) kind of incorrect code,
                  // versions 4 and 6 each generate OpArrayLength as it has long been done
-    return 7; // GLSL volatile keyword maps to both SPIR-V decorations Volatile and Coherent
+    // return 7; // GLSL volatile keyword maps to both SPIR-V decorations Volatile and Coherent
+    return 8; // switch to new dead block eliminator; use OpUnreachable
 }
 
 // Write SPIR-V out to a binary file
@@ -7903,6 +8645,7 @@
 // Write SPIR-V out to a text file with 32-bit hexadecimal words
 void OutputSpvHex(const std::vector<unsigned int>& spirv, const char* baseName, const char* varName)
 {
+#ifndef GLSLANG_WEB
     std::ofstream out;
     out.open(baseName, std::ios::binary | std::ios::out);
     if (out.fail())
@@ -7930,6 +8673,7 @@
         out << "};";
     }
     out.close();
+#endif
 }
 
 //
@@ -7963,11 +8707,14 @@
 #if ENABLE_OPT
     // If from HLSL, run spirv-opt to "legalize" the SPIR-V for Vulkan
     // eg. forward and remove memory writes of opaque types.
-    if ((intermediate.getSource() == EShSourceHlsl || options->optimizeSize) && !options->disableOptimizer)
+    bool prelegalization = intermediate.getSource() == EShSourceHlsl;
+    if ((intermediate.getSource() == EShSourceHlsl || options->optimizeSize) && !options->disableOptimizer) {
         SpirvToolsLegalize(intermediate, spirv, logger, options);
+        prelegalization = false;
+    }
 
     if (options->validate)
-        SpirvToolsValidate(intermediate, spirv, logger);
+        SpirvToolsValidate(intermediate, spirv, logger, prelegalization);
 
     if (options->disassemble)
         SpirvToolsDisassemble(std::cout, spirv);
diff --git a/SPIRV/GlslangToSpv.h b/SPIRV/GlslangToSpv.h
index 86e1c23..3907be4 100755
--- a/SPIRV/GlslangToSpv.h
+++ b/SPIRV/GlslangToSpv.h
@@ -40,7 +40,7 @@
 #endif
 
 #include "SpvTools.h"
-#include "../glslang/Include/intermediate.h"
+#include "glslang/Include/intermediate.h"
 
 #include <string>
 #include <vector>
diff --git a/SPIRV/InReadableOrder.cpp b/SPIRV/InReadableOrder.cpp
index 52b2961..9d9410b 100644
--- a/SPIRV/InReadableOrder.cpp
+++ b/SPIRV/InReadableOrder.cpp
@@ -61,17 +61,22 @@
 // Use by calling visit() on the root block.
 class ReadableOrderTraverser {
 public:
-    explicit ReadableOrderTraverser(std::function<void(Block*)> callback) : callback_(callback) {}
+    ReadableOrderTraverser(std::function<void(Block*, spv::ReachReason, Block*)> callback)
+      : callback_(callback) {}
     // Visits the block if it hasn't been visited already and isn't currently
-    // being delayed.  Invokes callback(block), then descends into its
+    // being delayed.  Invokes callback(block, why, header), then descends into its
     // successors.  Delays merge-block and continue-block processing until all
-    // the branches have been completed.
-    void visit(Block* block)
+    // the branches have been completed.  If |block| is an unreachable merge block or
+    // an unreachable continue target, then |header| is the corresponding header block.
+    void visit(Block* block, spv::ReachReason why, Block* header)
     {
         assert(block);
+        if (why == spv::ReachViaControlFlow) {
+            reachableViaControlFlow_.insert(block);
+        }
         if (visited_.count(block) || delayed_.count(block))
             return;
-        callback_(block);
+        callback_(block, why, header);
         visited_.insert(block);
         Block* mergeBlock = nullptr;
         Block* continueBlock = nullptr;
@@ -87,27 +92,40 @@
                 delayed_.insert(continueBlock);
             }
         }
-        const auto successors = block->getSuccessors();
-        for (auto it = successors.cbegin(); it != successors.cend(); ++it)
-            visit(*it);
+        if (why == spv::ReachViaControlFlow) {
+            const auto& successors = block->getSuccessors();
+            for (auto it = successors.cbegin(); it != successors.cend(); ++it)
+                visit(*it, why, nullptr);
+        }
         if (continueBlock) {
+            const spv::ReachReason continueWhy =
+                (reachableViaControlFlow_.count(continueBlock) > 0)
+                    ? spv::ReachViaControlFlow
+                    : spv::ReachDeadContinue;
             delayed_.erase(continueBlock);
-            visit(continueBlock);
+            visit(continueBlock, continueWhy, block);
         }
         if (mergeBlock) {
+            const spv::ReachReason mergeWhy =
+                (reachableViaControlFlow_.count(mergeBlock) > 0)
+                    ? spv::ReachViaControlFlow
+                    : spv::ReachDeadMerge;
             delayed_.erase(mergeBlock);
-            visit(mergeBlock);
+            visit(mergeBlock, mergeWhy, block);
         }
     }
 
 private:
-    std::function<void(Block*)> callback_;
+    std::function<void(Block*, spv::ReachReason, Block*)> callback_;
     // Whether a block has already been visited or is being delayed.
     std::unordered_set<Block *> visited_, delayed_;
+
+    // The set of blocks that actually are reached via control flow.
+    std::unordered_set<Block *> reachableViaControlFlow_;
 };
 }
 
-void spv::inReadableOrder(Block* root, std::function<void(Block*)> callback)
+void spv::inReadableOrder(Block* root, std::function<void(Block*, spv::ReachReason, Block*)> callback)
 {
-    ReadableOrderTraverser(callback).visit(root);
+    ReadableOrderTraverser(callback).visit(root, spv::ReachViaControlFlow, nullptr);
 }
diff --git a/SPIRV/Logger.cpp b/SPIRV/Logger.cpp
index 48bd4e3..cdc8469 100644
--- a/SPIRV/Logger.cpp
+++ b/SPIRV/Logger.cpp
@@ -32,6 +32,8 @@
 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 // POSSIBILITY OF SUCH DAMAGE.
 
+#ifndef GLSLANG_WEB
+
 #include "Logger.h"
 
 #include <algorithm>
@@ -66,3 +68,5 @@
 }
 
 } // end spv namespace
+
+#endif
diff --git a/SPIRV/Logger.h b/SPIRV/Logger.h
index 2e4ddaf..411367c 100644
--- a/SPIRV/Logger.h
+++ b/SPIRV/Logger.h
@@ -46,6 +46,14 @@
 public:
     SpvBuildLogger() {}
 
+#ifdef GLSLANG_WEB
+    void tbdFunctionality(const std::string& f) { }
+    void missingFunctionality(const std::string& f) { }
+    void warning(const std::string& w) { }
+    void error(const std::string& e) { errors.push_back(e); }
+    std::string getAllMessages() { return ""; }
+#else
+
     // Registers a TBD functionality.
     void tbdFunctionality(const std::string& f);
     // Registers a missing functionality.
@@ -59,6 +67,7 @@
     // Returns all messages accumulated in the order of:
     // TBD functionalities, missing functionalities, warnings, errors.
     std::string getAllMessages() const;
+#endif
 
 private:
     SpvBuildLogger(const SpvBuildLogger&);
diff --git a/SPIRV/NonSemanticDebugPrintf.h b/SPIRV/NonSemanticDebugPrintf.h
new file mode 100644
index 0000000..83796d7
--- /dev/null
+++ b/SPIRV/NonSemanticDebugPrintf.h
@@ -0,0 +1,50 @@
+// Copyright (c) 2020 The Khronos Group Inc.
+// 
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+// 
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+//    https://www.khronos.org/registry/
+// 
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+// 
+
+#ifndef SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_
+#define SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+    NonSemanticDebugPrintfRevision = 1,
+    NonSemanticDebugPrintfRevision_BitWidthPadding = 0x7fffffff
+};
+
+enum NonSemanticDebugPrintfInstructions {
+    NonSemanticDebugPrintfDebugPrintf = 1,
+    NonSemanticDebugPrintfInstructionsMax = 0x7fffffff
+};
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_
diff --git a/SPIRV/SPVRemapper.h b/SPIRV/SPVRemapper.h
index 97e3f31..d6b9c34 100644
--- a/SPIRV/SPVRemapper.h
+++ b/SPIRV/SPVRemapper.h
@@ -45,7 +45,7 @@
 
 // MSVC defines __cplusplus as an older value, even when it supports almost all of 11.
 // We handle that here by making our own symbol.
-#if __cplusplus >= 201103L || _MSC_VER >= 1700
+#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1700)
 #   define use_cpp11 1
 #endif
 
@@ -195,7 +195,7 @@
    // Header access & set methods
    spirword_t  magic()    const       { return spv[0]; } // return magic number
    spirword_t  bound()    const       { return spv[3]; } // return Id bound from header
-   spirword_t  bound(spirword_t b)    { return spv[3] = b; };
+   spirword_t  bound(spirword_t b)    { return spv[3] = b; }
    spirword_t  genmagic() const       { return spv[2]; } // generator magic
    spirword_t  genmagic(spirword_t m) { return spv[2] = m; }
    spirword_t  schemaNum() const      { return spv[4]; } // schema number from header
diff --git a/SPIRV/SpvBuilder.cpp b/SPIRV/SpvBuilder.cpp
index 138c41c..6cf70a1 100644
--- a/SPIRV/SpvBuilder.cpp
+++ b/SPIRV/SpvBuilder.cpp
@@ -1,6 +1,7 @@
 //
 // Copyright (C) 2014-2015 LunarG, Inc.
 // Copyright (C) 2015-2018 Google, Inc.
+// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 //
 // All rights reserved.
 //
@@ -46,7 +47,9 @@
 
 #include "SpvBuilder.h"
 
+#ifndef GLSLANG_WEB
 #include "hex_float.h"
+#endif
 
 #ifndef _WIN32
     #include <cstdio>
@@ -230,6 +233,11 @@
 
 Id Builder::makeIntegerType(int width, bool hasSign)
 {
+#ifdef GLSLANG_WEB
+    assert(width == 32);
+    width = 32;
+#endif
+
     // try to find it
     Instruction* type;
     for (int t = 0; t < (int)groupedTypes[OpTypeInt].size(); ++t) {
@@ -265,6 +273,11 @@
 
 Id Builder::makeFloatType(int width)
 {
+#ifdef GLSLANG_WEB
+    assert(width == 32);
+    width = 32;
+#endif
+
     // try to find it
     Instruction* type;
     for (int t = 0; t < (int)groupedTypes[OpTypeFloat].size(); ++t) {
@@ -484,7 +497,8 @@
     return type->getResultId();
 }
 
-Id Builder::makeImageType(Id sampledType, Dim dim, bool depth, bool arrayed, bool ms, unsigned sampled, ImageFormat format)
+Id Builder::makeImageType(Id sampledType, Dim dim, bool depth, bool arrayed, bool ms, unsigned sampled,
+    ImageFormat format)
 {
     assert(sampled == 1 || sampled == 2);
 
@@ -516,6 +530,7 @@
     constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
     module.mapInstruction(type);
 
+#ifndef GLSLANG_WEB
     // deal with capabilities
     switch (dim) {
     case DimBuffer:
@@ -561,6 +576,7 @@
                 addCapability(CapabilityImageMSArray);
         }
     }
+#endif
 
     return type->getResultId();
 }
@@ -586,22 +602,38 @@
     return type->getResultId();
 }
 
-#ifdef NV_EXTENSIONS
-Id Builder::makeAccelerationStructureNVType()
+#ifndef GLSLANG_WEB
+Id Builder::makeAccelerationStructureType()
 {
     Instruction *type;
-    if (groupedTypes[OpTypeAccelerationStructureNV].size() == 0) {
-        type = new Instruction(getUniqueId(), NoType, OpTypeAccelerationStructureNV);
-        groupedTypes[OpTypeAccelerationStructureNV].push_back(type);
+    if (groupedTypes[OpTypeAccelerationStructureKHR].size() == 0) {
+        type = new Instruction(getUniqueId(), NoType, OpTypeAccelerationStructureKHR);
+        groupedTypes[OpTypeAccelerationStructureKHR].push_back(type);
         constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
         module.mapInstruction(type);
     } else {
-        type = groupedTypes[OpTypeAccelerationStructureNV].back();
+        type = groupedTypes[OpTypeAccelerationStructureKHR].back();
+    }
+
+    return type->getResultId();
+}
+
+Id Builder::makeRayQueryType()
+{
+    Instruction *type;
+    if (groupedTypes[OpTypeRayQueryProvisionalKHR].size() == 0) {
+        type = new Instruction(getUniqueId(), NoType, OpTypeRayQueryProvisionalKHR);
+        groupedTypes[OpTypeRayQueryProvisionalKHR].push_back(type);
+        constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
+        module.mapInstruction(type);
+    } else {
+        type = groupedTypes[OpTypeRayQueryProvisionalKHR].back();
     }
 
     return type->getResultId();
 }
 #endif
+
 Id Builder::getDerefTypeId(Id resultId) const
 {
     Id typeId = getTypeId(resultId);
@@ -939,6 +971,10 @@
 
 Id Builder::makeDoubleConstant(double d, bool specConstant)
 {
+#ifdef GLSLANG_WEB
+    assert(0);
+    return NoResult;
+#else
     Op opcode = specConstant ? OpSpecConstant : OpConstant;
     Id typeId = makeFloatType(64);
     union { double db; unsigned long long ull; } u;
@@ -963,10 +999,15 @@
     module.mapInstruction(c);
 
     return c->getResultId();
+#endif
 }
 
 Id Builder::makeFloat16Constant(float f16, bool specConstant)
 {
+#ifdef GLSLANG_WEB
+    assert(0);
+    return NoResult;
+#else
     Op opcode = specConstant ? OpSpecConstant : OpConstant;
     Id typeId = makeFloatType(16);
 
@@ -991,25 +1032,33 @@
     module.mapInstruction(c);
 
     return c->getResultId();
+#endif
 }
 
 Id Builder::makeFpConstant(Id type, double d, bool specConstant)
 {
-        assert(isFloatType(type));
+#ifdef GLSLANG_WEB
+    const int width = 32;
+    assert(width == getScalarTypeWidth(type));
+#else
+    const int width = getScalarTypeWidth(type);
+#endif
 
-        switch (getScalarTypeWidth(type)) {
-        case 16:
-                return makeFloat16Constant((float)d, specConstant);
-        case 32:
-                return makeFloatConstant((float)d, specConstant);
-        case 64:
-                return makeDoubleConstant(d, specConstant);
-        default:
-                break;
-        }
+    assert(isFloatType(type));
 
-        assert(false);
-        return NoResult;
+    switch (width) {
+    case 16:
+            return makeFloat16Constant((float)d, specConstant);
+    case 32:
+            return makeFloatConstant((float)d, specConstant);
+    case 64:
+            return makeDoubleConstant(d, specConstant);
+    default:
+            break;
+    }
+
+    assert(false);
+    return NoResult;
 }
 
 Id Builder::findCompositeConstant(Op typeClass, Id typeId, const std::vector<Id>& comps)
@@ -1238,7 +1287,8 @@
 
 // Comments in header
 Function* Builder::makeFunctionEntry(Decoration precision, Id returnType, const char* name,
-                                     const std::vector<Id>& paramTypes, const std::vector<std::vector<Decoration>>& decorations, Block **entry)
+                                     const std::vector<Id>& paramTypes,
+                                     const std::vector<std::vector<Decoration>>& decorations, Block **entry)
 {
     // Make the function and initial instructions in it
     Id typeId = makeFunctionType(returnType, paramTypes);
@@ -1306,11 +1356,13 @@
 }
 
 // Comments in header
-Id Builder::createVariable(StorageClass storageClass, Id type, const char* name)
+Id Builder::createVariable(StorageClass storageClass, Id type, const char* name, Id initializer)
 {
     Id pointerType = makePointer(storageClass, type);
     Instruction* inst = new Instruction(getUniqueId(), pointerType, OpVariable);
     inst->addImmediateOperand(storageClass);
+    if (initializer != NoResult)
+        inst->addIdOperand(initializer);
 
     switch (storageClass) {
     case StorageClassFunction:
@@ -1339,7 +1391,8 @@
 }
 
 // av/vis/nonprivate are unnecessary and illegal for some storage classes.
-spv::MemoryAccessMask Builder::sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc) const
+spv::MemoryAccessMask Builder::sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc)
+    const
 {
     switch (sc) {
     case spv::StorageClassUniform:
@@ -1358,7 +1411,8 @@
 }
 
 // Comments in header
-void Builder::createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
+void Builder::createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope scope,
+    unsigned int alignment)
 {
     Instruction* store = new Instruction(OpStore);
     store->addIdOperand(lValue);
@@ -1461,7 +1515,8 @@
     // Generate code for spec constants if in spec constant operation
     // generation mode.
     if (generatingOpCodeForSpecConst) {
-        return createSpecConstantOp(OpCompositeExtract, typeId, std::vector<Id>(1, composite), std::vector<Id>(1, index));
+        return createSpecConstantOp(OpCompositeExtract, typeId, std::vector<Id>(1, composite),
+            std::vector<Id>(1, index));
     }
     Instruction* extract = new Instruction(getUniqueId(), typeId, OpCompositeExtract);
     extract->addIdOperand(composite);
@@ -1663,7 +1718,8 @@
     return op->getResultId();
 }
 
-Id Builder::createSpecConstantOp(Op opCode, Id typeId, const std::vector<Id>& operands, const std::vector<unsigned>& literals)
+Id Builder::createSpecConstantOp(Op opCode, Id typeId, const std::vector<Id>& operands,
+    const std::vector<unsigned>& literals)
 {
     Instruction* op = new Instruction(getUniqueId(), typeId, OpSpecConstantOp);
     op->addImmediateOperand((unsigned) opCode);
@@ -1806,7 +1862,7 @@
 // Accept all parameters needed to create a texture instruction.
 // Create the correct instruction based on the inputs, and make the call.
 Id Builder::createTextureCall(Decoration precision, Id resultType, bool sparse, bool fetch, bool proj, bool gather,
-    bool noImplicitLod, const TextureParameters& parameters)
+    bool noImplicitLod, const TextureParameters& parameters, ImageOperandsMask signExtensionMask)
 {
     static const int maxTextureArgs = 10;
     Id texArgs[maxTextureArgs] = {};
@@ -1823,7 +1879,7 @@
     if (parameters.component != NoResult)
         texArgs[numArgs++] = parameters.component;
 
-#ifdef NV_EXTENSIONS
+#ifndef GLSLANG_WEB
     if (parameters.granularity != NoResult)
         texArgs[numArgs++] = parameters.granularity;
     if (parameters.coarse != NoResult)
@@ -1833,8 +1889,8 @@
     //
     // Set up the optional arguments
     //
-    int optArgNum = numArgs;                        // track which operand, if it exists, is the mask of optional arguments
-    ++numArgs;                                      // speculatively make room for the mask operand
+    int optArgNum = numArgs;    // track which operand, if it exists, is the mask of optional arguments
+    ++numArgs;                  // speculatively make room for the mask operand
     ImageOperandsMask mask = ImageOperandsMaskNone; // the mask operand
     if (parameters.bias) {
         mask = (ImageOperandsMask)(mask | ImageOperandsBiasMask);
@@ -1870,6 +1926,7 @@
         mask = (ImageOperandsMask)(mask | ImageOperandsConstOffsetsMask);
         texArgs[numArgs++] = parameters.offsets;
     }
+#ifndef GLSLANG_WEB
     if (parameters.sample) {
         mask = (ImageOperandsMask)(mask | ImageOperandsSampleMask);
         texArgs[numArgs++] = parameters.sample;
@@ -1887,6 +1944,8 @@
     if (parameters.volatil) {
         mask = mask | ImageOperandsVolatileTexelKHRMask;
     }
+#endif
+    mask = mask | signExtensionMask;
     if (mask == ImageOperandsMaskNone)
         --numArgs;  // undo speculative reservation for the mask argument
     else
@@ -1901,10 +1960,9 @@
             opCode = OpImageSparseFetch;
         else
             opCode = OpImageFetch;
-#ifdef NV_EXTENSIONS
+#ifndef GLSLANG_WEB
     } else if (parameters.granularity && parameters.coarse) {
         opCode = OpImageSampleFootprintNV;
-#endif
     } else if (gather) {
         if (parameters.Dref)
             if (sparse)
@@ -1916,6 +1974,7 @@
                 opCode = OpImageSparseGather;
             else
                 opCode = OpImageGather;
+#endif
     } else if (explicitLod) {
         if (parameters.Dref) {
             if (proj)
@@ -2064,11 +2123,7 @@
         break;
     }
     case OpImageQueryLod:
-#ifdef AMD_EXTENSIONS
         resultType = makeVectorType(getScalarTypeId(getTypeId(parameters.coords)), 2);
-#else
-        resultType = makeVectorType(makeFloatType(32), 2);
-#endif
         break;
     case OpImageQueryLevels:
     case OpImageQuerySamples:
@@ -2086,6 +2141,7 @@
     if (parameters.lod)
         query->addIdOperand(parameters.lod);
     buildPoint->addInstruction(std::unique_ptr<Instruction>(query));
+    addCapability(CapabilityImageQuery);
 
     return query->getResultId();
 }
@@ -2153,7 +2209,8 @@
         if (constituent == 0)
             resultId = subResultId;
         else
-            resultId = setPrecision(createBinOp(equal ? OpLogicalAnd : OpLogicalOr, boolType, resultId, subResultId), precision);
+            resultId = setPrecision(createBinOp(equal ? OpLogicalAnd : OpLogicalOr, boolType, resultId, subResultId),
+                                    precision);
     }
 
     return resultId;
@@ -2162,7 +2219,8 @@
 // OpCompositeConstruct
 Id Builder::createCompositeConstruct(Id typeId, const std::vector<Id>& constituents)
 {
-    assert(isAggregateType(typeId) || (getNumTypeConstituents(typeId) > 1 && getNumTypeConstituents(typeId) == (int)constituents.size()));
+    assert(isAggregateType(typeId) || (getNumTypeConstituents(typeId) > 1 &&
+           getNumTypeConstituents(typeId) == (int)constituents.size()));
 
     if (generatingOpCodeForSpecConst) {
         // Sometime, even in spec-constant-op mode, the constant composite to be
@@ -2279,7 +2337,12 @@
     int numRows = getTypeNumRows(resultTypeId);
 
     Instruction* instr = module.getInstruction(componentTypeId);
-    unsigned bitCount = instr->getImmediateOperand(0);
+#ifdef GLSLANG_WEB
+    const unsigned bitCount = 32;
+    assert(bitCount == instr->getImmediateOperand(0));
+#else
+    const unsigned bitCount = instr->getImmediateOperand(0);
+#endif
 
     // Optimize matrix constructed from a bigger matrix
     if (isMatrix(sources[0]) && getNumColumns(sources[0]) >= numCols && getNumRows(sources[0]) >= numRows) {
@@ -2570,7 +2633,8 @@
 }
 
 // Comments in header
-void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, unsigned int alignment)
+void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType,
+    AccessChain::CoherentFlags coherentFlags, unsigned int alignment)
 {
     accessChain.coherentFlags |= coherentFlags;
     accessChain.alignment |= alignment;
@@ -2624,7 +2688,8 @@
 }
 
 // Comments in header
-Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resultType, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
+Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resultType,
+    spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
 {
     Id id;
 
@@ -2649,12 +2714,19 @@
             if (constant) {
                 id = createCompositeExtract(accessChain.base, swizzleBase, indexes);
             } else {
-                // make a new function variable for this r-value
-                Id lValue = createVariable(StorageClassFunction, getTypeId(accessChain.base), "indexable");
-
-                // store into it
-                createStore(accessChain.base, lValue);
-
+                Id lValue = NoResult;
+                if (spvVersion >= Spv_1_4) {
+                    // make a new function variable for this r-value, using an initializer,
+                    // and mark it as NonWritable so that downstream it can be detected as a lookup
+                    // table
+                    lValue = createVariable(StorageClassFunction, getTypeId(accessChain.base), "indexable",
+                        accessChain.base);
+                    addDecoration(lValue, DecorationNonWritable);
+                } else {
+                    lValue = createVariable(StorageClassFunction, getTypeId(accessChain.base), "indexable");
+                    // store into it
+                    createStore(accessChain.base, lValue);
+                }
                 // move base to the new variable
                 accessChain.base = lValue;
                 accessChain.isRValue = false;
@@ -2675,7 +2747,13 @@
         }
 
         // load through the access chain
-        id = createLoad(collapseAccessChain(), memoryAccess, scope, alignment);
+        id = collapseAccessChain();
+        // Apply nonuniform both to the access chain and the loaded value.
+        // Buffer accesses need the access chain decorated, and this is where
+        // loaded image types get decorated. TODO: This should maybe move to
+        // createImageTextureFunctionCall.
+        addDecoration(id, nonUniform);
+        id = createLoad(id, memoryAccess, scope, alignment);
         setPrecision(id, precision);
         addDecoration(id, nonUniform);
     }
@@ -2956,14 +3034,14 @@
 }
 
 void Builder::createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control,
-                              unsigned int dependencyLength)
+                              const std::vector<unsigned int>& operands)
 {
     Instruction* merge = new Instruction(OpLoopMerge);
     merge->addIdOperand(mergeBlock->getId());
     merge->addIdOperand(continueBlock->getId());
     merge->addImmediateOperand(control);
-    if ((control & LoopControlDependencyLengthMask) != 0)
-        merge->addImmediateOperand(dependencyLength);
+    for (int op = 0; op < (int)operands.size(); ++op)
+        merge->addImmediateOperand(operands[op]);
     buildPoint->addInstruction(std::unique_ptr<Instruction>(merge));
 }
 
@@ -3029,7 +3107,8 @@
         dumpSourceInstructions(iItr->first, *iItr->second, out);
 }
 
-void Builder::dumpInstructions(std::vector<unsigned int>& out, const std::vector<std::unique_ptr<Instruction> >& instructions) const
+void Builder::dumpInstructions(std::vector<unsigned int>& out,
+    const std::vector<std::unique_ptr<Instruction> >& instructions) const
 {
     for (int i = 0; i < (int)instructions.size(); ++i) {
         instructions[i]->dump(out);
diff --git a/SPIRV/SpvBuilder.h b/SPIRV/SpvBuilder.h
index 52f7fba..71b90d6 100644
--- a/SPIRV/SpvBuilder.h
+++ b/SPIRV/SpvBuilder.h
@@ -1,7 +1,8 @@
 //
 // Copyright (C) 2014-2015 LunarG, Inc.
-// Copyright (C) 2015-2018 Google, Inc.
+// Copyright (C) 2015-2020 Google, Inc.
 // Copyright (C) 2017 ARM Limited.
+// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 //
 // All rights reserved.
 //
@@ -61,6 +62,15 @@
 
 namespace spv {
 
+typedef enum {
+    Spv_1_0 = (1 << 16),
+    Spv_1_1 = (1 << 16) | (1 << 8),
+    Spv_1_2 = (1 << 16) | (2 << 8),
+    Spv_1_3 = (1 << 16) | (3 << 8),
+    Spv_1_4 = (1 << 16) | (4 << 8),
+    Spv_1_5 = (1 << 16) | (5 << 8),
+} SpvVersion;
+
 class Builder {
 public:
     Builder(unsigned int spvVersion, unsigned int userNumber, SpvBuildLogger* logger);
@@ -85,6 +95,7 @@
         const char* file_c_str = str.c_str();
         fileString->addStringOperand(file_c_str);
         strings.push_back(std::unique_ptr<Instruction>(fileString));
+        module.mapInstruction(fileString);
         stringIds[file_c_str] = strId;
         return strId;
     }
@@ -97,6 +108,20 @@
     void addModuleProcessed(const std::string& p) { moduleProcesses.push_back(p.c_str()); }
     void setEmitOpLines() { emitOpLines = true; }
     void addExtension(const char* ext) { extensions.insert(ext); }
+    void removeExtension(const char* ext)
+    {
+        extensions.erase(ext);
+    }
+    void addIncorporatedExtension(const char* ext, SpvVersion incorporatedVersion)
+    {
+        if (getSpvVersion() < static_cast<unsigned>(incorporatedVersion))
+            addExtension(ext);
+    }
+    void promoteIncorporatedExtension(const char* baseExt, const char* promoExt, SpvVersion incorporatedVersion)
+    {
+        removeExtension(baseExt);
+        addIncorporatedExtension(promoExt, incorporatedVersion);
+    }
     void addInclude(const std::string& name, const std::string& text)
     {
         spv::Id incId = getStringId(name);
@@ -158,7 +183,9 @@
     Id makeCooperativeMatrixType(Id component, Id scope, Id rows, Id cols);
 
     // accelerationStructureNV type
-    Id makeAccelerationStructureNVType();
+    Id makeAccelerationStructureType();
+    // rayQueryEXT type
+    Id makeRayQueryType();
 
     // For querying about types.
     Id getTypeId(Id resultId) const { return module.getTypeId(resultId); }
@@ -173,7 +200,8 @@
     Id getContainedTypeId(Id typeId) const;
     Id getContainedTypeId(Id typeId, int) const;
     StorageClass getTypeStorageClass(Id typeId) const { return module.getStorageClass(typeId); }
-    ImageFormat getImageTypeFormat(Id typeId) const { return (ImageFormat)module.getInstruction(typeId)->getImmediateOperand(6); }
+    ImageFormat getImageTypeFormat(Id typeId) const
+        { return (ImageFormat)module.getInstruction(typeId)->getImmediateOperand(6); }
 
     bool isPointer(Id resultId)      const { return isPointerType(getTypeId(resultId)); }
     bool isScalar(Id resultId)       const { return isScalarType(getTypeId(resultId)); }
@@ -183,18 +211,28 @@
     bool isAggregate(Id resultId)    const { return isAggregateType(getTypeId(resultId)); }
     bool isSampledImage(Id resultId) const { return isSampledImageType(getTypeId(resultId)); }
 
-    bool isBoolType(Id typeId)               { return groupedTypes[OpTypeBool].size() > 0 && typeId == groupedTypes[OpTypeBool].back()->getResultId(); }
-    bool isIntType(Id typeId)          const { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) != 0; }
-    bool isUintType(Id typeId)         const { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) == 0; }
+    bool isBoolType(Id typeId)
+        { return groupedTypes[OpTypeBool].size() > 0 && typeId == groupedTypes[OpTypeBool].back()->getResultId(); }
+    bool isIntType(Id typeId)          const
+        { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) != 0; }
+    bool isUintType(Id typeId)         const
+        { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) == 0; }
     bool isFloatType(Id typeId)        const { return getTypeClass(typeId) == OpTypeFloat; }
     bool isPointerType(Id typeId)      const { return getTypeClass(typeId) == OpTypePointer; }
-    bool isScalarType(Id typeId)       const { return getTypeClass(typeId) == OpTypeFloat  || getTypeClass(typeId) == OpTypeInt || getTypeClass(typeId) == OpTypeBool; }
+    bool isScalarType(Id typeId)       const
+        { return getTypeClass(typeId) == OpTypeFloat || getTypeClass(typeId) == OpTypeInt ||
+          getTypeClass(typeId) == OpTypeBool; }
     bool isVectorType(Id typeId)       const { return getTypeClass(typeId) == OpTypeVector; }
     bool isMatrixType(Id typeId)       const { return getTypeClass(typeId) == OpTypeMatrix; }
     bool isStructType(Id typeId)       const { return getTypeClass(typeId) == OpTypeStruct; }
     bool isArrayType(Id typeId)        const { return getTypeClass(typeId) == OpTypeArray; }
+#ifdef GLSLANG_WEB
+    bool isCooperativeMatrixType(Id typeId)const { return false; }
+#else
     bool isCooperativeMatrixType(Id typeId)const { return getTypeClass(typeId) == OpTypeCooperativeMatrixNV; }
-    bool isAggregateType(Id typeId)    const { return isArrayType(typeId) || isStructType(typeId) || isCooperativeMatrixType(typeId); }
+#endif
+    bool isAggregateType(Id typeId)    const
+        { return isArrayType(typeId) || isStructType(typeId) || isCooperativeMatrixType(typeId); }
     bool isImageType(Id typeId)        const { return getTypeClass(typeId) == OpTypeImage; }
     bool isSamplerType(Id typeId)      const { return getTypeClass(typeId) == OpTypeSampler; }
     bool isSampledImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampledImage; }
@@ -206,7 +244,8 @@
     bool isConstant(Id resultId) const { return isConstantOpCode(getOpCode(resultId)); }
     bool isConstantScalar(Id resultId) const { return getOpCode(resultId) == OpConstant; }
     bool isSpecConstant(Id resultId) const { return isSpecConstantOpCode(getOpCode(resultId)); }
-    unsigned int getConstantScalar(Id resultId) const { return module.getInstruction(resultId)->getImmediateOperand(0); }
+    unsigned int getConstantScalar(Id resultId) const
+        { return module.getInstruction(resultId)->getImmediateOperand(0); }
     StorageClass getStorageClass(Id resultId) const { return getTypeStorageClass(getTypeId(resultId)); }
 
     int getScalarTypeWidth(Id typeId) const
@@ -248,14 +287,22 @@
 
     // For making new constants (will return old constant if the requested one was already made).
     Id makeBoolConstant(bool b, bool specConstant = false);
-    Id makeInt8Constant(int i, bool specConstant = false)        { return makeIntConstant(makeIntType(8),  (unsigned)i, specConstant); }
-    Id makeUint8Constant(unsigned u, bool specConstant = false)  { return makeIntConstant(makeUintType(8),           u, specConstant); }
-    Id makeInt16Constant(int i, bool specConstant = false)       { return makeIntConstant(makeIntType(16),  (unsigned)i, specConstant); }
-    Id makeUint16Constant(unsigned u, bool specConstant = false) { return makeIntConstant(makeUintType(16),           u, specConstant); }
-    Id makeIntConstant(int i, bool specConstant = false)         { return makeIntConstant(makeIntType(32),  (unsigned)i, specConstant); }
-    Id makeUintConstant(unsigned u, bool specConstant = false)   { return makeIntConstant(makeUintType(32),           u, specConstant); }
-    Id makeInt64Constant(long long i, bool specConstant = false)            { return makeInt64Constant(makeIntType(64),  (unsigned long long)i, specConstant); }
-    Id makeUint64Constant(unsigned long long u, bool specConstant = false)  { return makeInt64Constant(makeUintType(64),                     u, specConstant); }
+    Id makeInt8Constant(int i, bool specConstant = false)
+        { return makeIntConstant(makeIntType(8),  (unsigned)i, specConstant); }
+    Id makeUint8Constant(unsigned u, bool specConstant = false)
+        { return makeIntConstant(makeUintType(8),           u, specConstant); }
+    Id makeInt16Constant(int i, bool specConstant = false)
+        { return makeIntConstant(makeIntType(16),  (unsigned)i, specConstant); }
+    Id makeUint16Constant(unsigned u, bool specConstant = false)
+        { return makeIntConstant(makeUintType(16),           u, specConstant); }
+    Id makeIntConstant(int i, bool specConstant = false)
+        { return makeIntConstant(makeIntType(32),  (unsigned)i, specConstant); }
+    Id makeUintConstant(unsigned u, bool specConstant = false)
+        { return makeIntConstant(makeUintType(32),           u, specConstant); }
+    Id makeInt64Constant(long long i, bool specConstant = false)
+        { return makeInt64Constant(makeIntType(64),  (unsigned long long)i, specConstant); }
+    Id makeUint64Constant(unsigned long long u, bool specConstant = false)
+        { return makeInt64Constant(makeUintType(64),                     u, specConstant); }
     Id makeFloatConstant(float f, bool specConstant = false);
     Id makeDoubleConstant(double d, bool specConstant = false);
     Id makeFloat16Constant(float f16, bool specConstant = false);
@@ -286,8 +333,8 @@
     // Make a shader-style function, and create its entry block if entry is non-zero.
     // Return the function, pass back the entry.
     // The returned pointer is only valid for the lifetime of this builder.
-    Function* makeFunctionEntry(Decoration precision, Id returnType, const char* name, const std::vector<Id>& paramTypes,
-                                const std::vector<std::vector<Decoration>>& precisions, Block **entry = 0);
+    Function* makeFunctionEntry(Decoration precision, Id returnType, const char* name,
+        const std::vector<Id>& paramTypes, const std::vector<std::vector<Decoration>>& precisions, Block **entry = 0);
 
     // Create a return. An 'implicit' return is one not appearing in the source
     // code.  In the case of an implicit return, no post-return block is inserted.
@@ -300,16 +347,18 @@
     void makeDiscard();
 
     // Create a global or function local or IO variable.
-    Id createVariable(StorageClass, Id type, const char* name = 0);
+    Id createVariable(StorageClass, Id type, const char* name = 0, Id initializer = NoResult);
 
     // Create an intermediate with an undefined value.
     Id createUndefined(Id type);
 
     // Store into an Id and return the l-value
-    void createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
+    void createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone,
+        spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
 
     // Load from an Id and return it
-    Id createLoad(Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
+    Id createLoad(Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone,
+        spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
 
     // Create an OpAccessChain instruction
     Id createAccessChain(StorageClass, Id base, const std::vector<Id>& offsets);
@@ -408,7 +457,8 @@
     };
 
     // Select the correct texture operation based on all inputs, and emit the correct instruction
-    Id createTextureCall(Decoration precision, Id resultType, bool sparse, bool fetch, bool proj, bool gather, bool noImplicit, const TextureParameters&);
+    Id createTextureCall(Decoration precision, Id resultType, bool sparse, bool fetch, bool proj, bool gather,
+        bool noImplicit, const TextureParameters&, ImageOperandsMask);
 
     // Emit the OpTextureQuery* instruction that was passed in.
     // Figure out the right return value and type, and return it.
@@ -467,7 +517,7 @@
     // recursion stack can hold the memory for it.
     //
     void makeSwitch(Id condition, unsigned int control, int numSegments, const std::vector<int>& caseValues,
-                    const std::vector<int>& valueToSegment, int defaultSegment, std::vector<Block*>& segmentBB); // return argument
+                    const std::vector<int>& valueToSegment, int defaultSegment, std::vector<Block*>& segmentBB);
 
     // Add a branch to the innermost switch's merge block.
     void addSwitchBreak();
@@ -484,7 +534,7 @@
         Block &head, &body, &merge, &continue_target;
     private:
         LoopBlocks();
-        LoopBlocks& operator=(const LoopBlocks&);
+        LoopBlocks& operator=(const LoopBlocks&) = delete;
     };
 
     // Start a new loop and prepare the builder to generate code for it.  Until
@@ -541,18 +591,34 @@
         std::vector<Id> indexChain;
         Id instr;                      // cache the instruction that generates this access chain
         std::vector<unsigned> swizzle; // each std::vector element selects the next GLSL component number
-        Id component;                  // a dynamic component index, can coexist with a swizzle, done after the swizzle, NoResult if not present
-        Id preSwizzleBaseType;         // dereferenced type, before swizzle or component is applied; NoType unless a swizzle or component is present
+        Id component;                  // a dynamic component index, can coexist with a swizzle,
+                                       // done after the swizzle, NoResult if not present
+        Id preSwizzleBaseType;         // dereferenced type, before swizzle or component is applied;
+                                       // NoType unless a swizzle or component is present
         bool isRValue;                 // true if 'base' is an r-value, otherwise, base is an l-value
-        unsigned int alignment;        // bitwise OR of alignment values passed in. Accumulates worst alignment. Only tracks base and (optional) component selection alignment.
+        unsigned int alignment;        // bitwise OR of alignment values passed in. Accumulates worst alignment.
+                                       // Only tracks base and (optional) component selection alignment.
 
         // Accumulate whether anything in the chain of structures has coherent decorations.
         struct CoherentFlags {
+            CoherentFlags() { clear(); }
+#ifdef GLSLANG_WEB
+            void clear() { }
+            bool isVolatile() const { return false; }
+            CoherentFlags operator |=(const CoherentFlags &other) { return *this; }
+#else
+            bool isVolatile() const { return volatil; }
+            bool anyCoherent() const {
+                return coherent || devicecoherent || queuefamilycoherent || workgroupcoherent ||
+                    subgroupcoherent || shadercallcoherent;
+            }
+
             unsigned coherent : 1;
             unsigned devicecoherent : 1;
             unsigned queuefamilycoherent : 1;
             unsigned workgroupcoherent : 1;
             unsigned subgroupcoherent : 1;
+            unsigned shadercallcoherent : 1;
             unsigned nonprivate : 1;
             unsigned volatil : 1;
             unsigned isImage : 1;
@@ -563,23 +629,25 @@
                 queuefamilycoherent = 0;
                 workgroupcoherent = 0;
                 subgroupcoherent = 0;
+                shadercallcoherent = 0;
                 nonprivate = 0;
                 volatil = 0;
                 isImage = 0;
             }
 
-            CoherentFlags() { clear(); }
             CoherentFlags operator |=(const CoherentFlags &other) {
                 coherent |= other.coherent;
                 devicecoherent |= other.devicecoherent;
                 queuefamilycoherent |= other.queuefamilycoherent;
                 workgroupcoherent |= other.workgroupcoherent;
                 subgroupcoherent |= other.subgroupcoherent;
+                shadercallcoherent |= other.shadercallcoherent;
                 nonprivate |= other.nonprivate;
                 volatil |= other.volatil;
                 isImage |= other.isImage;
                 return *this;
             }
+#endif
         };
         CoherentFlags coherentFlags;
     };
@@ -619,11 +687,13 @@
     }
 
     // push new swizzle onto the end of any existing swizzle, merging into a single swizzle
-    void accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, unsigned int alignment);
+    void accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType,
+        AccessChain::CoherentFlags coherentFlags, unsigned int alignment);
 
     // push a dynamic component selection onto the access chain, only applicable with a
     // non-trivial swizzle or no swizzle
-    void accessChainPushComponent(Id component, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, unsigned int alignment)
+    void accessChainPushComponent(Id component, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags,
+        unsigned int alignment)
     {
         if (accessChain.swizzle.size() != 1) {
             accessChain.component = component;
@@ -635,10 +705,18 @@
     }
 
     // use accessChain and swizzle to store value
-    void accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
+    void accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone,
+        spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
 
     // use accessChain and swizzle to load an r-value
-    Id accessChainLoad(Decoration precision, Decoration nonUniform, Id ResultType, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
+    Id accessChainLoad(Decoration precision, Decoration nonUniform, Id ResultType,
+        spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax,
+            unsigned int alignment = 0);
+
+    // Return whether or not the access chain can be represented in SPIR-V
+    // as an l-value.
+    // E.g., a[3].yx cannot be, while a[3].y and a[3].y[x] can be.
+    bool isSpvLvalue() const { return accessChain.swizzle.size() <= 1; }
 
     // get the direct pointer for an l-value
     Id accessChainGetLValue();
@@ -647,22 +725,28 @@
     // based on the type of the base and the chain of dereferences.
     Id accessChainGetInferredType();
 
-    // Add capabilities, extensions, remove unneeded decorations, etc., 
+    // Add capabilities, extensions, remove unneeded decorations, etc.,
     // based on the resulting SPIR-V.
     void postProcess();
 
+    // Prune unreachable blocks in the CFG and remove unneeded decorations.
+    void postProcessCFG();
+
+#ifndef GLSLANG_WEB
+    // Add capabilities, extensions based on instructions in the module.
+    void postProcessFeatures();
     // Hook to visit each instruction in a block in a function
     void postProcess(Instruction&);
-    // Hook to visit each instruction in a reachable block in a function.
-    void postProcessReachable(const Instruction&);
     // Hook to visit each non-32-bit sized float/int operation in a block.
     void postProcessType(const Instruction&, spv::Id typeId);
+#endif
 
     void dump(std::vector<unsigned int>&) const;
 
     void createBranch(Block* block);
     void createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock);
-    void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control, unsigned int dependencyLength);
+    void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control,
+        const std::vector<unsigned int>& operands);
 
     // Sets to generate opcode for specialization constants.
     void setToSpecConstCodeGenMode() { generatingOpCodeForSpecConst = true; }
@@ -688,7 +772,8 @@
     void dumpSourceInstructions(const spv::Id fileId, const std::string& text, std::vector<unsigned int>&) const;
     void dumpInstructions(std::vector<unsigned int>&, const std::vector<std::unique_ptr<Instruction> >&) const;
     void dumpModuleProcesses(std::vector<unsigned int>&) const;
-    spv::MemoryAccessMask sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc) const;
+    spv::MemoryAccessMask sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc)
+        const;
 
     unsigned int spvVersion;     // the version of SPIR-V to emit in the header
     SourceLanguage source;
@@ -723,10 +808,14 @@
     std::vector<std::unique_ptr<Instruction> > externals;
     std::vector<std::unique_ptr<Function> > functions;
 
-     // not output, internally used for quick & dirty canonical (unique) creation
-    std::unordered_map<unsigned int, std::vector<Instruction*>> groupedConstants;       // map type opcodes to constant inst.
-    std::unordered_map<unsigned int, std::vector<Instruction*>> groupedStructConstants; // map struct-id to constant instructions
-    std::unordered_map<unsigned int, std::vector<Instruction*>> groupedTypes;           // map type opcodes to type instructions
+    // not output, internally used for quick & dirty canonical (unique) creation
+
+    // map type opcodes to constant inst.
+    std::unordered_map<unsigned int, std::vector<Instruction*>> groupedConstants;
+    // map struct-id to constant instructions
+    std::unordered_map<unsigned int, std::vector<Instruction*>> groupedStructConstants;
+    // map type opcodes to type instructions
+    std::unordered_map<unsigned int, std::vector<Instruction*>> groupedTypes;
 
     // stack of switches
     std::stack<Block*> switchMerges;
diff --git a/SPIRV/SpvPostProcess.cpp b/SPIRV/SpvPostProcess.cpp
index 80471ca..d40174d 100644
--- a/SPIRV/SpvPostProcess.cpp
+++ b/SPIRV/SpvPostProcess.cpp
@@ -39,6 +39,7 @@
 #include <cassert>
 #include <cstdlib>
 
+#include <unordered_map>
 #include <unordered_set>
 #include <algorithm>
 
@@ -51,16 +52,13 @@
     #include "GLSL.std.450.h"
     #include "GLSL.ext.KHR.h"
     #include "GLSL.ext.EXT.h"
-#ifdef AMD_EXTENSIONS
     #include "GLSL.ext.AMD.h"
-#endif
-#ifdef NV_EXTENSIONS
     #include "GLSL.ext.NV.h"
-#endif
 }
 
 namespace spv {
 
+#ifndef GLSLANG_WEB
 // Hook to visit each operand type and result type of an instruction.
 // Will be called multiple times for one instruction, once for each typed
 // operand and the result.
@@ -118,12 +116,48 @@
     case OpAccessChain:
     case OpPtrAccessChain:
     case OpCopyObject:
+        break;
     case OpFConvert:
     case OpSConvert:
     case OpUConvert:
+        // Look for any 8/16-bit storage capabilities. If there are none, assume that
+        // the convert instruction requires the Float16/Int8/16 capability.
+        if (containsType(typeId, OpTypeFloat, 16) || containsType(typeId, OpTypeInt, 16)) {
+            bool foundStorage = false;
+            for (auto it = capabilities.begin(); it != capabilities.end(); ++it) {
+                spv::Capability cap = *it;
+                if (cap == spv::CapabilityStorageInputOutput16 ||
+                    cap == spv::CapabilityStoragePushConstant16 ||
+                    cap == spv::CapabilityStorageUniformBufferBlock16 ||
+                    cap == spv::CapabilityStorageUniform16) {
+                    foundStorage = true;
+                    break;
+                }
+            }
+            if (!foundStorage) {
+                if (containsType(typeId, OpTypeFloat, 16))
+                    addCapability(CapabilityFloat16);
+                if (containsType(typeId, OpTypeInt, 16))
+                    addCapability(CapabilityInt16);
+            }
+        }
+        if (containsType(typeId, OpTypeInt, 8)) {
+            bool foundStorage = false;
+            for (auto it = capabilities.begin(); it != capabilities.end(); ++it) {
+                spv::Capability cap = *it;
+                if (cap == spv::CapabilityStoragePushConstant8 ||
+                    cap == spv::CapabilityUniformAndStorageBuffer8BitAccess ||
+                    cap == spv::CapabilityStorageBuffer8BitAccess) {
+                    foundStorage = true;
+                    break;
+                }
+            }
+            if (!foundStorage) {
+                addCapability(CapabilityInt8);
+            }
+        }
         break;
     case OpExtInst:
-#if AMD_EXTENSIONS
         switch (inst.getImmediateOperand(1)) {
         case GLSLstd450Frexp:
         case GLSLstd450FrexpStruct:
@@ -139,7 +173,6 @@
         default:
             break;
         }
-#endif
         break;
     default:
         if (basicTypeOp == OpTypeFloat && width == 16)
@@ -185,12 +218,10 @@
         addCapability(CapabilityImageQuery);
         break;
 
-#ifdef NV_EXTENSIONS
     case OpGroupNonUniformPartitionNV:
         addExtension(E_SPV_NV_shader_subgroup_partitioned);
         addCapability(CapabilityGroupNonUniformPartitionedNV);
         break;
-#endif
 
     case OpLoad:
     case OpStore:
@@ -289,17 +320,16 @@
         }
     }
 }
-
-// Called for each instruction in a reachable block.
-void Builder::postProcessReachable(const Instruction&)
-{
-    // did have code here, but questionable to do so without deleting the instructions
-}
+#endif
 
 // comment in header
-void Builder::postProcess()
+void Builder::postProcessCFG()
 {
+    // reachableBlocks is the set of blockss reached via control flow, or which are
+    // unreachable continue targert or unreachable merge.
     std::unordered_set<const Block*> reachableBlocks;
+    std::unordered_map<Block*, Block*> headerForUnreachableContinue;
+    std::unordered_set<Block*> unreachableMerges;
     std::unordered_set<Id> unreachableDefinitions;
     // Collect IDs defined in unreachable blocks. For each function, label the
     // reachable blocks first. Then for each unreachable block, collect the
@@ -307,16 +337,41 @@
     for (auto fi = module.getFunctions().cbegin(); fi != module.getFunctions().cend(); fi++) {
         Function* f = *fi;
         Block* entry = f->getEntryBlock();
-        inReadableOrder(entry, [&reachableBlocks](const Block* b) { reachableBlocks.insert(b); });
+        inReadableOrder(entry,
+            [&reachableBlocks, &unreachableMerges, &headerForUnreachableContinue]
+            (Block* b, ReachReason why, Block* header) {
+               reachableBlocks.insert(b);
+               if (why == ReachDeadContinue) headerForUnreachableContinue[b] = header;
+               if (why == ReachDeadMerge) unreachableMerges.insert(b);
+            });
         for (auto bi = f->getBlocks().cbegin(); bi != f->getBlocks().cend(); bi++) {
             Block* b = *bi;
-            if (reachableBlocks.count(b) == 0) {
-                for (auto ii = b->getInstructions().cbegin(); ii != b->getInstructions().cend(); ii++)
+            if (unreachableMerges.count(b) != 0 || headerForUnreachableContinue.count(b) != 0) {
+                auto ii = b->getInstructions().cbegin();
+                ++ii; // Keep potential decorations on the label.
+                for (; ii != b->getInstructions().cend(); ++ii)
+                    unreachableDefinitions.insert(ii->get()->getResultId());
+            } else if (reachableBlocks.count(b) == 0) {
+                // The normal case for unreachable code.  All definitions are considered dead.
+                for (auto ii = b->getInstructions().cbegin(); ii != b->getInstructions().cend(); ++ii)
                     unreachableDefinitions.insert(ii->get()->getResultId());
             }
         }
     }
 
+    // Modify unreachable merge blocks and unreachable continue targets.
+    // Delete their contents.
+    for (auto mergeIter = unreachableMerges.begin(); mergeIter != unreachableMerges.end(); ++mergeIter) {
+        (*mergeIter)->rewriteAsCanonicalUnreachableMerge();
+    }
+    for (auto continueIter = headerForUnreachableContinue.begin();
+         continueIter != headerForUnreachableContinue.end();
+         ++continueIter) {
+        Block* continue_target = continueIter->first;
+        Block* header = continueIter->second;
+        continue_target->rewriteAsCanonicalUnreachableContinue(header);
+    }
+
     // Remove unneeded decorations, for unreachable instructions
     decorations.erase(std::remove_if(decorations.begin(), decorations.end(),
         [&unreachableDefinitions](std::unique_ptr<Instruction>& I) -> bool {
@@ -324,14 +379,29 @@
             return unreachableDefinitions.count(decoration_id) != 0;
         }),
         decorations.end());
+}
 
+#ifndef GLSLANG_WEB
+// comment in header
+void Builder::postProcessFeatures() {
     // Add per-instruction capabilities, extensions, etc.,
 
-    // process all reachable instructions...
-    for (auto bi = reachableBlocks.cbegin(); bi != reachableBlocks.cend(); ++bi) {
-        const Block* block = *bi;
-        const auto function = [this](const std::unique_ptr<Instruction>& inst) { postProcessReachable(*inst.get()); };
-        std::for_each(block->getInstructions().begin(), block->getInstructions().end(), function);
+    // Look for any 8/16 bit type in physical storage buffer class, and set the
+    // appropriate capability. This happens in createSpvVariable for other storage
+    // classes, but there isn't always a variable for physical storage buffer.
+    for (int t = 0; t < (int)groupedTypes[OpTypePointer].size(); ++t) {
+        Instruction* type = groupedTypes[OpTypePointer][t];
+        if (type->getImmediateOperand(0) == (unsigned)StorageClassPhysicalStorageBufferEXT) {
+            if (containsType(type->getIdOperand(1), OpTypeInt, 8)) {
+                addIncorporatedExtension(spv::E_SPV_KHR_8bit_storage, spv::Spv_1_5);
+                addCapability(spv::CapabilityStorageBuffer8BitAccess);
+            }
+            if (containsType(type->getIdOperand(1), OpTypeInt, 16) ||
+                containsType(type->getIdOperand(1), OpTypeFloat, 16)) {
+                addIncorporatedExtension(spv::E_SPV_KHR_16bit_storage, spv::Spv_1_3);
+                addCapability(spv::CapabilityStorageBuffer16BitAccess);
+            }
+        }
     }
 
     // process all block-contained instructions
@@ -366,24 +436,15 @@
             }
         }
     }
+}
+#endif
 
-    // Look for any 8/16 bit type in physical storage buffer class, and set the
-    // appropriate capability. This happens in createSpvVariable for other storage
-    // classes, but there isn't always a variable for physical storage buffer.
-    for (int t = 0; t < (int)groupedTypes[OpTypePointer].size(); ++t) {
-        Instruction* type = groupedTypes[OpTypePointer][t];
-        if (type->getImmediateOperand(0) == (unsigned)StorageClassPhysicalStorageBufferEXT) {
-            if (containsType(type->getIdOperand(1), OpTypeInt, 8)) {
-                addExtension(spv::E_SPV_KHR_8bit_storage);
-                addCapability(spv::CapabilityStorageBuffer8BitAccess);
-            }
-            if (containsType(type->getIdOperand(1), OpTypeInt, 16) ||
-                containsType(type->getIdOperand(1), OpTypeFloat, 16)) {
-                addExtension(spv::E_SPV_KHR_16bit_storage);
-                addCapability(spv::CapabilityStorageBuffer16BitAccess);
-            }
-        }
-    }
+// comment in header
+void Builder::postProcess() {
+  postProcessCFG();
+#ifndef GLSLANG_WEB
+  postProcessFeatures();
+#endif
 }
 
 }; // end spv namespace
diff --git a/SPIRV/SpvTools.cpp b/SPIRV/SpvTools.cpp
index cce5fa7..1e968ba 100644
--- a/SPIRV/SpvTools.cpp
+++ b/SPIRV/SpvTools.cpp
@@ -1,6 +1,6 @@
 //
 // Copyright (C) 2014-2016 LunarG, Inc.
-// Copyright (C) 2018 Google, Inc.
+// Copyright (C) 2018-2020 Google, Inc.
 //
 // All rights reserved.
 //
@@ -52,8 +52,23 @@
 spv_target_env MapToSpirvToolsEnv(const SpvVersion& spvVersion, spv::SpvBuildLogger* logger)
 {
     switch (spvVersion.vulkan) {
-    case glslang::EShTargetVulkan_1_0: return spv_target_env::SPV_ENV_VULKAN_1_0;
-    case glslang::EShTargetVulkan_1_1: return spv_target_env::SPV_ENV_VULKAN_1_1;
+    case glslang::EShTargetVulkan_1_0:
+        return spv_target_env::SPV_ENV_VULKAN_1_0;
+    case glslang::EShTargetVulkan_1_1:
+        switch (spvVersion.spv) {
+        case EShTargetSpv_1_0:
+        case EShTargetSpv_1_1:
+        case EShTargetSpv_1_2:
+        case EShTargetSpv_1_3:
+            return spv_target_env::SPV_ENV_VULKAN_1_1;
+        case EShTargetSpv_1_4:
+            return spv_target_env::SPV_ENV_VULKAN_1_1_SPIRV_1_4;
+        default:
+            logger->missingFunctionality("Target version for SPIRV-Tools validator");
+            return spv_target_env::SPV_ENV_VULKAN_1_1;
+        }
+    case glslang::EShTargetVulkan_1_2:
+        return spv_target_env::SPV_ENV_VULKAN_1_2;
     default:
         break;
     }
@@ -90,7 +105,7 @@
 
 // Apply the SPIRV-Tools validator to generated SPIR-V.
 void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
-                        spv::SpvBuildLogger* logger)
+                        spv::SpvBuildLogger* logger, bool prelegalization)
 {
     // validate
     spv_context context = spvContextCreate(MapToSpirvToolsEnv(intermediate.getSpv(), logger));
@@ -98,6 +113,7 @@
     spv_diagnostic diagnostic = nullptr;
     spv_validator_options options = spvValidatorOptionsCreate();
     spvValidatorOptionsSetRelaxBlockLayout(options, intermediate.usingHlslOffsets());
+    spvValidatorOptionsSetBeforeHlslLegalization(options, prelegalization);
     spvValidateWithOptions(context, options, &binary, &diagnostic);
 
     // report
@@ -114,8 +130,8 @@
 
 // Apply the SPIRV-Tools optimizer to generated SPIR-V, for the purpose of
 // legalizing HLSL SPIR-V.
-void SpirvToolsLegalize(const glslang::TIntermediate&, std::vector<unsigned int>& spirv,
-                        spv::SpvBuildLogger*, const SpvOptions* options)
+void SpirvToolsLegalize(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
+                        spv::SpvBuildLogger* logger, const SpvOptions* options)
 {
     spv_target_env target_env = SPV_ENV_UNIVERSAL_1_2;
 
@@ -159,6 +175,7 @@
     if (options->generateDebugInfo) {
         optimizer.RegisterPass(spvtools::CreatePropagateLineInfoPass());
     }
+    optimizer.RegisterPass(spvtools::CreateWrapOpKillPass());
     optimizer.RegisterPass(spvtools::CreateDeadBranchElimPass());
     optimizer.RegisterPass(spvtools::CreateMergeReturnPass());
     optimizer.RegisterPass(spvtools::CreateInlineExhaustivePass());
@@ -182,8 +199,6 @@
     optimizer.RegisterPass(spvtools::CreateDeadInsertElimPass());
     if (options->optimizeSize) {
         optimizer.RegisterPass(spvtools::CreateRedundancyEliminationPass());
-        // TODO(greg-lunarg): Add this when AMD driver issues are resolved
-        // optimizer.RegisterPass(CreateCommonUniformElimPass());
     }
     optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass());
     optimizer.RegisterPass(spvtools::CreateCFGCleanupPass());
@@ -192,7 +207,8 @@
     }
 
     spvtools::OptimizerOptions spvOptOptions;
-    spvOptOptions.set_run_validator(false); // The validator may run as a seperate step later on
+    optimizer.SetTargetEnv(MapToSpirvToolsEnv(intermediate.getSpv(), logger));
+    spvOptOptions.set_run_validator(false); // The validator may run as a separate step later on
     optimizer.Run(spirv.data(), spirv.size(), &spirv, spvOptOptions);
 }
 
diff --git a/SPIRV/SpvTools.h b/SPIRV/SpvTools.h
index 7e49ae0..59c914d 100644
--- a/SPIRV/SpvTools.h
+++ b/SPIRV/SpvTools.h
@@ -41,10 +41,12 @@
 #ifndef GLSLANG_SPV_TOOLS_H
 #define GLSLANG_SPV_TOOLS_H
 
+#ifdef ENABLE_OPT
 #include <vector>
 #include <ostream>
+#endif
 
-#include "../glslang/MachineIndependent/localintermediate.h"
+#include "glslang/MachineIndependent/localintermediate.h"
 #include "Logger.h"
 
 namespace glslang {
@@ -59,14 +61,14 @@
     bool validate;
 };
 
-#if ENABLE_OPT
+#ifdef ENABLE_OPT
 
 // Use the SPIRV-Tools disassembler to print SPIR-V.
 void SpirvToolsDisassemble(std::ostream& out, const std::vector<unsigned int>& spirv);
 
 // Apply the SPIRV-Tools validator to generated SPIR-V.
 void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
-                        spv::SpvBuildLogger*);
+                        spv::SpvBuildLogger*, bool prelegalization);
 
 // Apply the SPIRV-Tools optimizer to generated SPIR-V, for the purpose of
 // legalizing HLSL SPIR-V.
diff --git a/SPIRV/disassemble.cpp b/SPIRV/disassemble.cpp
index 631173c..4faa89e 100644
--- a/SPIRV/disassemble.cpp
+++ b/SPIRV/disassemble.cpp
@@ -52,26 +52,16 @@
     extern "C" {
         // Include C-based headers that don't have a namespace
         #include "GLSL.std.450.h"
-#ifdef AMD_EXTENSIONS
         #include "GLSL.ext.AMD.h"
-#endif
-
-#ifdef NV_EXTENSIONS
         #include "GLSL.ext.NV.h"
-#endif
     }
 }
 const char* GlslStd450DebugNames[spv::GLSLstd450Count];
 
 namespace spv {
 
-#ifdef AMD_EXTENSIONS
 static const char* GLSLextAMDGetDebugNames(const char*, unsigned);
-#endif
-
-#ifdef NV_EXTENSIONS
 static const char* GLSLextNVGetDebugNames(const char*, unsigned);
-#endif
 
 static void Kill(std::ostream& out, const char* message)
 {
@@ -82,16 +72,10 @@
 // used to identify the extended instruction library imported when printing
 enum ExtInstSet {
     GLSL450Inst,
-
-#ifdef AMD_EXTENSIONS
     GLSLextAMDInst,
-#endif
-
-#ifdef NV_EXTENSIONS
     GLSLextNVInst,
-#endif
-
     OpenCLExtInst,
+    NonSemanticDebugPrintfExtInst,
 };
 
 // Container class for a single instance of a SPIR-V stream, with methods for disassembly.
@@ -497,39 +481,37 @@
             if (opCode == OpExtInst) {
                 ExtInstSet extInstSet = GLSL450Inst;
                 const char* name = idDescriptor[stream[word - 2]].c_str();
-                if (0 == memcmp("OpenCL", name, 6)) {
+                if (strcmp("OpenCL.std", name) == 0) {
                     extInstSet = OpenCLExtInst;
-#ifdef AMD_EXTENSIONS
+                } else if (strcmp("OpenCL.DebugInfo.100", name) == 0) {
+                    extInstSet = OpenCLExtInst;
+                } else if (strcmp("NonSemantic.DebugPrintf", name) == 0) {
+                    extInstSet = NonSemanticDebugPrintfExtInst;
                 } else if (strcmp(spv::E_SPV_AMD_shader_ballot, name) == 0 ||
                            strcmp(spv::E_SPV_AMD_shader_trinary_minmax, name) == 0 ||
                            strcmp(spv::E_SPV_AMD_shader_explicit_vertex_parameter, name) == 0 ||
                            strcmp(spv::E_SPV_AMD_gcn_shader, name) == 0) {
                     extInstSet = GLSLextAMDInst;
-#endif
-#ifdef NV_EXTENSIONS
-                }else if (strcmp(spv::E_SPV_NV_sample_mask_override_coverage, name) == 0 ||
+                } else if (strcmp(spv::E_SPV_NV_sample_mask_override_coverage, name) == 0 ||
                           strcmp(spv::E_SPV_NV_geometry_shader_passthrough, name) == 0 ||
                           strcmp(spv::E_SPV_NV_viewport_array2, name) == 0 ||
                           strcmp(spv::E_SPV_NVX_multiview_per_view_attributes, name) == 0 || 
                           strcmp(spv::E_SPV_NV_fragment_shader_barycentric, name) == 0 ||
                           strcmp(spv::E_SPV_NV_mesh_shader, name) == 0) {
                     extInstSet = GLSLextNVInst;
-#endif
                 }
                 unsigned entrypoint = stream[word - 1];
                 if (extInstSet == GLSL450Inst) {
                     if (entrypoint < GLSLstd450Count) {
                         out << "(" << GlslStd450DebugNames[entrypoint] << ")";
                     }
-#ifdef AMD_EXTENSIONS
                 } else if (extInstSet == GLSLextAMDInst) {
                     out << "(" << GLSLextAMDGetDebugNames(name, entrypoint) << ")";
-#endif
-#ifdef NV_EXTENSIONS
                 }
                 else if (extInstSet == GLSLextNVInst) {
                     out << "(" << GLSLextNVGetDebugNames(name, entrypoint) << ")";
-#endif
+                } else if (extInstSet == NonSemanticDebugPrintfExtInst) {
+                    out << "(DebugPrintf)";
                 }
             }
             break;
@@ -648,9 +630,11 @@
     names[GLSLstd450InterpolateAtCentroid]   = "InterpolateAtCentroid";
     names[GLSLstd450InterpolateAtSample]     = "InterpolateAtSample";
     names[GLSLstd450InterpolateAtOffset]     = "InterpolateAtOffset";
+    names[GLSLstd450NMin]                    = "NMin";
+    names[GLSLstd450NMax]                    = "NMax";
+    names[GLSLstd450NClamp]                  = "NClamp";
 }
 
-#ifdef AMD_EXTENSIONS
 static const char* GLSLextAMDGetDebugNames(const char* name, unsigned entrypoint)
 {
     if (strcmp(name, spv::E_SPV_AMD_shader_ballot) == 0) {
@@ -692,18 +676,17 @@
 
     return "Bad";
 }
-#endif
 
-#ifdef NV_EXTENSIONS
 static const char* GLSLextNVGetDebugNames(const char* name, unsigned entrypoint)
 {
     if (strcmp(name, spv::E_SPV_NV_sample_mask_override_coverage) == 0 ||
         strcmp(name, spv::E_SPV_NV_geometry_shader_passthrough) == 0 ||
         strcmp(name, spv::E_ARB_shader_viewport_layer_array) == 0 ||
         strcmp(name, spv::E_SPV_NV_viewport_array2) == 0 ||
-        strcmp(spv::E_SPV_NVX_multiview_per_view_attributes, name) == 0 ||
-        strcmp(spv::E_SPV_NV_fragment_shader_barycentric, name) == 0 ||
-        strcmp(name, spv::E_SPV_NV_mesh_shader) == 0) {
+        strcmp(name, spv::E_SPV_NVX_multiview_per_view_attributes) == 0 ||
+        strcmp(name, spv::E_SPV_NV_fragment_shader_barycentric) == 0 ||
+        strcmp(name, spv::E_SPV_NV_mesh_shader) == 0 ||
+        strcmp(name, spv::E_SPV_NV_shader_image_footprint) == 0) {
         switch (entrypoint) {
         // NV builtins
         case BuiltInViewportMaskNV:                 return "ViewportMaskNV";
@@ -729,6 +712,8 @@
         case CapabilityPerViewAttributesNV:         return "PerViewAttributesNV";
         case CapabilityFragmentBarycentricNV:       return "FragmentBarycentricNV";
         case CapabilityMeshShadingNV:               return "MeshShadingNV";
+        case CapabilityImageFootprintNV:            return "ImageFootprintNV";
+        case CapabilitySampleMaskOverrideCoverageNV:return "SampleMaskOverrideCoverageNV";
 
         // NV Decorations
         case DecorationOverrideCoverageNV:          return "OverrideCoverageNV";
@@ -745,7 +730,6 @@
     }
     return "Bad";
 }
-#endif
 
 void Disassemble(std::ostream& out, const std::vector<unsigned int>& stream)
 {
diff --git a/SPIRV/doc.cpp b/SPIRV/doc.cpp
index 76e1df8..b1f2b82 100644
--- a/SPIRV/doc.cpp
+++ b/SPIRV/doc.cpp
@@ -1,5 +1,6 @@
 //
 // Copyright (C) 2014-2015 LunarG, Inc.
+// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 //
 // All rights reserved.
 //
@@ -50,12 +51,8 @@
         // Include C-based headers that don't have a namespace
         #include "GLSL.ext.KHR.h"
         #include "GLSL.ext.EXT.h"
-#ifdef AMD_EXTENSIONS
         #include "GLSL.ext.AMD.h"
-#endif
-#ifdef NV_EXTENSIONS
         #include "GLSL.ext.NV.h"
-#endif
     }
 }
 
@@ -98,22 +95,17 @@
     case 4:  return "Fragment";
     case 5:  return "GLCompute";
     case 6:  return "Kernel";
-#ifdef NV_EXTENSIONS
     case ExecutionModelTaskNV: return "TaskNV";
     case ExecutionModelMeshNV: return "MeshNV";
-#endif
 
     default: return "Bad";
 
-#ifdef NV_EXTENSIONS
-    case ExecutionModelRayGenerationNV: return "RayGenerationNV";
-    case ExecutionModelIntersectionNV:  return "IntersectionNV";
-    case ExecutionModelAnyHitNV:        return "AnyHitNV";
-    case ExecutionModelClosestHitNV:    return "ClosestHitNV";
-    case ExecutionModelMissNV:          return "MissNV";
-    case ExecutionModelCallableNV:      return "CallableNV";
-#endif
-
+    case ExecutionModelRayGenerationKHR: return "RayGenerationKHR";
+    case ExecutionModelIntersectionKHR:  return "IntersectionKHR";
+    case ExecutionModelAnyHitKHR:        return "AnyHitKHR";
+    case ExecutionModelClosestHitKHR:    return "ClosestHitKHR";
+    case ExecutionModelMissKHR:          return "MissKHR";
+    case ExecutionModelCallableKHR:      return "CallableKHR";
     }
 }
 
@@ -183,13 +175,18 @@
 
     case 4446:  return "PostDepthCoverage";
 
-#ifdef NV_EXTENSIONS
     case ExecutionModeOutputLinesNV:            return "OutputLinesNV";
     case ExecutionModeOutputPrimitivesNV:       return "OutputPrimitivesNV";
     case ExecutionModeOutputTrianglesNV:        return "OutputTrianglesNV";
     case ExecutionModeDerivativeGroupQuadsNV:   return "DerivativeGroupQuadsNV";
     case ExecutionModeDerivativeGroupLinearNV:  return "DerivativeGroupLinearNV";
-#endif
+
+    case ExecutionModePixelInterlockOrderedEXT:         return "PixelInterlockOrderedEXT";
+    case ExecutionModePixelInterlockUnorderedEXT:       return "PixelInterlockUnorderedEXT";
+    case ExecutionModeSampleInterlockOrderedEXT:        return "SampleInterlockOrderedEXT";
+    case ExecutionModeSampleInterlockUnorderedEXT:      return "SampleInterlockUnorderedEXT";
+    case ExecutionModeShadingRateInterlockOrderedEXT:   return "ShadingRateInterlockOrderedEXT";
+    case ExecutionModeShadingRateInterlockUnorderedEXT: return "ShadingRateInterlockUnorderedEXT";
 
     case ExecutionModeCeiling:
     default: return "Bad";
@@ -213,14 +210,12 @@
     case 11: return "Image";
     case 12: return "StorageBuffer";
 
-#ifdef NV_EXTENSIONS
-    case StorageClassRayPayloadNV:            return "RayPayloadNV";
-    case StorageClassHitAttributeNV:          return "HitAttributeNV";
-    case StorageClassIncomingRayPayloadNV:    return "IncomingRayPayloadNV";
-    case StorageClassShaderRecordBufferNV:    return "ShaderRecordBufferNV";
-    case StorageClassCallableDataNV:          return "CallableDataNV";
-    case StorageClassIncomingCallableDataNV:  return "IncomingCallableDataNV";
-#endif
+    case StorageClassRayPayloadKHR:            return "RayPayloadKHR";
+    case StorageClassHitAttributeKHR:          return "HitAttributeKHR";
+    case StorageClassIncomingRayPayloadKHR:    return "IncomingRayPayloadKHR";
+    case StorageClassShaderRecordBufferKHR:    return "ShaderRecordBufferKHR";
+    case StorageClassCallableDataKHR:          return "CallableDataKHR";
+    case StorageClassIncomingCallableDataKHR:  return "IncomingCallableDataKHR";
 
     case StorageClassPhysicalStorageBufferEXT: return "PhysicalStorageBufferEXT";
 
@@ -282,10 +277,7 @@
     case DecorationCeiling:
     default:  return "Bad";
 
-#ifdef AMD_EXTENSIONS
     case DecorationExplicitInterpAMD: return "ExplicitInterpAMD";
-#endif
-#ifdef NV_EXTENSIONS
     case DecorationOverrideCoverageNV:          return "OverrideCoverageNV";
     case DecorationPassthroughNV:               return "PassthroughNV";
     case DecorationViewportRelativeNV:          return "ViewportRelativeNV";
@@ -294,7 +286,6 @@
     case DecorationPerViewNV:                   return "PerViewNV";
     case DecorationPerTaskNV:                   return "PerTaskNV";
     case DecorationPerVertexNV:                 return "PerVertexNV";
-#endif
 
     case DecorationNonUniformEXT:           return "DecorationNonUniformEXT";
     case DecorationHlslCounterBufferGOOGLE: return "DecorationHlslCounterBufferGOOGLE";
@@ -364,7 +355,6 @@
     case 4426: return "DrawIndex";
     case 5014: return "FragStencilRefEXT";
 
-#ifdef AMD_EXTENSIONS
     case 4992: return "BaryCoordNoPerspAMD";
     case 4993: return "BaryCoordNoPerspCentroidAMD";
     case 4994: return "BaryCoordNoPerspSampleAMD";
@@ -372,41 +362,36 @@
     case 4996: return "BaryCoordSmoothCentroidAMD";
     case 4997: return "BaryCoordSmoothSampleAMD";
     case 4998: return "BaryCoordPullModelAMD";
-#endif
-
-#ifdef NV_EXTENSIONS
-    case BuiltInLaunchIdNV:                 return "LaunchIdNV";
-    case BuiltInLaunchSizeNV:               return "LaunchSizeNV";
-    case BuiltInWorldRayOriginNV:           return "WorldRayOriginNV";
-    case BuiltInWorldRayDirectionNV:        return "WorldRayDirectionNV";
-    case BuiltInObjectRayOriginNV:          return "ObjectRayOriginNV";
-    case BuiltInObjectRayDirectionNV:       return "ObjectRayDirectionNV";
-    case BuiltInRayTminNV:                  return "RayTminNV";
-    case BuiltInRayTmaxNV:                  return "RayTmaxNV";
-    case BuiltInInstanceCustomIndexNV:      return "InstanceCustomIndexNV";
-    case BuiltInObjectToWorldNV:            return "ObjectToWorldNV";
-    case BuiltInWorldToObjectNV:            return "WorldToObjectNV";
-    case BuiltInHitTNV:                     return "HitTNV";
-    case BuiltInHitKindNV:                  return "HitKindNV";
-    case BuiltInIncomingRayFlagsNV:         return "IncomingRayFlagsNV";
-    case BuiltInViewportMaskNV:             return "ViewportMaskNV";
-    case BuiltInSecondaryPositionNV:        return "SecondaryPositionNV";
-    case BuiltInSecondaryViewportMaskNV:    return "SecondaryViewportMaskNV";
-    case BuiltInPositionPerViewNV:          return "PositionPerViewNV";
-    case BuiltInViewportMaskPerViewNV:      return "ViewportMaskPerViewNV";
+    case BuiltInLaunchIdKHR:                 return "LaunchIdKHR";
+    case BuiltInLaunchSizeKHR:               return "LaunchSizeKHR";
+    case BuiltInWorldRayOriginKHR:           return "WorldRayOriginKHR";
+    case BuiltInWorldRayDirectionKHR:        return "WorldRayDirectionKHR";
+    case BuiltInObjectRayOriginKHR:          return "ObjectRayOriginKHR";
+    case BuiltInObjectRayDirectionKHR:       return "ObjectRayDirectionKHR";
+    case BuiltInRayTminKHR:                  return "RayTminKHR";
+    case BuiltInRayTmaxKHR:                  return "RayTmaxKHR";
+    case BuiltInInstanceCustomIndexKHR:      return "InstanceCustomIndexKHR";
+    case BuiltInRayGeometryIndexKHR:         return "RayGeometryIndexKHR";
+    case BuiltInObjectToWorldKHR:            return "ObjectToWorldKHR";
+    case BuiltInWorldToObjectKHR:            return "WorldToObjectKHR";
+    case BuiltInHitTKHR:                     return "HitTKHR";
+    case BuiltInHitKindKHR:                  return "HitKindKHR";
+    case BuiltInIncomingRayFlagsKHR:         return "IncomingRayFlagsKHR";
+    case BuiltInViewportMaskNV:              return "ViewportMaskNV";
+    case BuiltInSecondaryPositionNV:         return "SecondaryPositionNV";
+    case BuiltInSecondaryViewportMaskNV:     return "SecondaryViewportMaskNV";
+    case BuiltInPositionPerViewNV:           return "PositionPerViewNV";
+    case BuiltInViewportMaskPerViewNV:       return "ViewportMaskPerViewNV";
 //    case BuiltInFragmentSizeNV:             return "FragmentSizeNV";        // superseded by BuiltInFragSizeEXT
 //    case BuiltInInvocationsPerPixelNV:      return "InvocationsPerPixelNV"; // superseded by BuiltInFragInvocationCountEXT
-    case BuiltInBaryCoordNV:                return "BaryCoordNV";
-    case BuiltInBaryCoordNoPerspNV:         return "BaryCoordNoPerspNV";
-#endif
+    case BuiltInBaryCoordNV:                 return "BaryCoordNV";
+    case BuiltInBaryCoordNoPerspNV:          return "BaryCoordNoPerspNV";
 
-    case BuiltInFragSizeEXT:                return "FragSizeEXT";
-    case BuiltInFragInvocationCountEXT:     return "FragInvocationCountEXT";
+    case BuiltInFragSizeEXT:                 return "FragSizeEXT";
+    case BuiltInFragInvocationCountEXT:      return "FragInvocationCountEXT";
 
     case 5264: return "FullyCoveredEXT";
 
-
-#ifdef NV_EXTENSIONS
     case BuiltInTaskCountNV:           return "TaskCountNV";
     case BuiltInPrimitiveCountNV:      return "PrimitiveCountNV";
     case BuiltInPrimitiveIndicesNV:    return "PrimitiveIndicesNV";
@@ -415,7 +400,10 @@
     case BuiltInLayerPerViewNV:        return "LayerPerViewNV";
     case BuiltInMeshViewCountNV:       return "MeshViewCountNV";
     case BuiltInMeshViewIndicesNV:     return "MeshViewIndicesNV";
-#endif
+    case BuiltInWarpsPerSMNV:           return "WarpsPerSMNV";
+    case BuiltInSMCountNV:              return "SMCountNV";
+    case BuiltInWarpIDNV:               return "WarpIDNV";
+    case BuiltInSMIDNV:                 return "SMIDNV";
 
     default: return "Bad";
     }
@@ -575,7 +563,7 @@
     }
 }
 
-const int ImageOperandsCeiling = 12;
+const int ImageOperandsCeiling = 14;
 
 const char* ImageOperandsString(int format)
 {
@@ -592,6 +580,8 @@
     case ImageOperandsMakeTexelVisibleKHRShift:     return "MakeTexelVisibleKHR";
     case ImageOperandsNonPrivateTexelKHRShift:      return "NonPrivateTexelKHR";
     case ImageOperandsVolatileTexelKHRShift:        return "VolatileTexelKHR";
+    case ImageOperandsSignExtendShift:              return "SignExtend";
+    case ImageOperandsZeroExtendShift:              return "ZeroExtend";
 
     case ImageOperandsCeiling:
     default:
@@ -674,15 +664,20 @@
     }
 }
 
-const int LoopControlCeiling = 4;
+const int LoopControlCeiling = LoopControlPartialCountShift + 1;
 
 const char* LoopControlString(int cont)
 {
     switch (cont) {
-    case 0:  return "Unroll";
-    case 1:  return "DontUnroll";
-    case 2:  return "DependencyInfinite";
-    case 3:  return "DependencyLength";
+    case LoopControlUnrollShift:             return "Unroll";
+    case LoopControlDontUnrollShift:         return "DontUnroll";
+    case LoopControlDependencyInfiniteShift: return "DependencyInfinite";
+    case LoopControlDependencyLengthShift:   return "DependencyLength";
+    case LoopControlMinIterationsShift:      return "MinIterations";
+    case LoopControlMaxIterationsShift:      return "MaxIterations";
+    case LoopControlIterationMultipleShift:  return "IterationMultiple";
+    case LoopControlPeelCountShift:          return "PeelCount";
+    case LoopControlPartialCountShift:       return "PartialCount";
 
     case LoopControlCeiling:
     default: return "Bad";
@@ -763,11 +758,9 @@
     case GroupOperationInclusiveScan:  return "InclusiveScan";
     case GroupOperationExclusiveScan:  return "ExclusiveScan";
     case GroupOperationClusteredReduce:  return "ClusteredReduce";
-#ifdef NV_EXTENSIONS
     case GroupOperationPartitionedReduceNV:  return "PartitionedReduceNV";
     case GroupOperationPartitionedInclusiveScanNV:  return "PartitionedInclusiveScanNV";
     case GroupOperationPartitionedExclusiveScanNV:  return "PartitionedExclusiveScanNV";
-#endif
 
     default: return "Bad";
     }
@@ -875,26 +868,23 @@
     case CapabilityStoragePushConstant16:       return "StoragePushConstant16";
     case CapabilityStorageInputOutput16:        return "StorageInputOutput16";
 
-    case CapabilityStorageBuffer8BitAccess:             return "CapabilityStorageBuffer8BitAccess";
-    case CapabilityUniformAndStorageBuffer8BitAccess:   return "CapabilityUniformAndStorageBuffer8BitAccess";
-    case CapabilityStoragePushConstant8:                return "CapabilityStoragePushConstant8";
+    case CapabilityStorageBuffer8BitAccess:             return "StorageBuffer8BitAccess";
+    case CapabilityUniformAndStorageBuffer8BitAccess:   return "UniformAndStorageBuffer8BitAccess";
+    case CapabilityStoragePushConstant8:                return "StoragePushConstant8";
 
     case CapabilityDeviceGroup: return "DeviceGroup";
     case CapabilityMultiView:   return "MultiView";
 
     case CapabilityStencilExportEXT: return "StencilExportEXT";
 
-#ifdef AMD_EXTENSIONS
     case CapabilityFloat16ImageAMD:       return "Float16ImageAMD";
     case CapabilityImageGatherBiasLodAMD: return "ImageGatherBiasLodAMD";
     case CapabilityFragmentMaskAMD:       return "FragmentMaskAMD";
     case CapabilityImageReadWriteLodAMD:  return "ImageReadWriteLodAMD";
-#endif
 
     case CapabilityAtomicStorageOps:             return "AtomicStorageOps";
 
     case CapabilitySampleMaskPostDepthCoverage:  return "SampleMaskPostDepthCoverage";
-#ifdef NV_EXTENSIONS
     case CapabilityGeometryShaderPassthroughNV:     return "GeometryShaderPassthroughNV";
     case CapabilityShaderViewportIndexLayerNV:      return "ShaderViewportIndexLayerNV";
     case CapabilityShaderViewportMaskNV:            return "ShaderViewportMaskNV";
@@ -902,37 +892,51 @@
     case CapabilityPerViewAttributesNV:             return "PerViewAttributesNV";
     case CapabilityGroupNonUniformPartitionedNV:    return "GroupNonUniformPartitionedNV";
     case CapabilityRayTracingNV:                    return "RayTracingNV";
+    case CapabilityRayTracingProvisionalKHR:        return "RayTracingProvisionalKHR";
+    case CapabilityRayQueryProvisionalKHR:          return "RayQueryProvisionalKHR";
+    case CapabilityRayTraversalPrimitiveCullingProvisionalKHR: return "RayTraversalPrimitiveCullingProvisionalKHR";
     case CapabilityComputeDerivativeGroupQuadsNV:   return "ComputeDerivativeGroupQuadsNV";
     case CapabilityComputeDerivativeGroupLinearNV:  return "ComputeDerivativeGroupLinearNV";
     case CapabilityFragmentBarycentricNV:           return "FragmentBarycentricNV";
     case CapabilityMeshShadingNV:                   return "MeshShadingNV";
-//    case CapabilityShadingRateNV:                   return "ShadingRateNV";  // superseded by CapabilityFragmentDensityEXT
-#endif
+    case CapabilityImageFootprintNV:                return "ImageFootprintNV";
+//    case CapabilityShadingRateNV:                   return "ShadingRateNV";  // superseded by FragmentDensityEXT
+    case CapabilitySampleMaskOverrideCoverageNV:    return "SampleMaskOverrideCoverageNV";
     case CapabilityFragmentDensityEXT:              return "FragmentDensityEXT";
 
     case CapabilityFragmentFullyCoveredEXT: return "FragmentFullyCoveredEXT";
 
-    case CapabilityShaderNonUniformEXT:                          return "CapabilityShaderNonUniformEXT";
-    case CapabilityRuntimeDescriptorArrayEXT:                    return "CapabilityRuntimeDescriptorArrayEXT";
-    case CapabilityInputAttachmentArrayDynamicIndexingEXT:       return "CapabilityInputAttachmentArrayDynamicIndexingEXT";
-    case CapabilityUniformTexelBufferArrayDynamicIndexingEXT:    return "CapabilityUniformTexelBufferArrayDynamicIndexingEXT";
-    case CapabilityStorageTexelBufferArrayDynamicIndexingEXT:    return "CapabilityStorageTexelBufferArrayDynamicIndexingEXT";
-    case CapabilityUniformBufferArrayNonUniformIndexingEXT:      return "CapabilityUniformBufferArrayNonUniformIndexingEXT";
-    case CapabilitySampledImageArrayNonUniformIndexingEXT:       return "CapabilitySampledImageArrayNonUniformIndexingEXT";
-    case CapabilityStorageBufferArrayNonUniformIndexingEXT:      return "CapabilityStorageBufferArrayNonUniformIndexingEXT";
-    case CapabilityStorageImageArrayNonUniformIndexingEXT:       return "CapabilityStorageImageArrayNonUniformIndexingEXT";
-    case CapabilityInputAttachmentArrayNonUniformIndexingEXT:    return "CapabilityInputAttachmentArrayNonUniformIndexingEXT";
-    case CapabilityUniformTexelBufferArrayNonUniformIndexingEXT: return "CapabilityUniformTexelBufferArrayNonUniformIndexingEXT";
-    case CapabilityStorageTexelBufferArrayNonUniformIndexingEXT: return "CapabilityStorageTexelBufferArrayNonUniformIndexingEXT";
+    case CapabilityShaderNonUniformEXT:                          return "ShaderNonUniformEXT";
+    case CapabilityRuntimeDescriptorArrayEXT:                    return "RuntimeDescriptorArrayEXT";
+    case CapabilityInputAttachmentArrayDynamicIndexingEXT:       return "InputAttachmentArrayDynamicIndexingEXT";
+    case CapabilityUniformTexelBufferArrayDynamicIndexingEXT:    return "UniformTexelBufferArrayDynamicIndexingEXT";
+    case CapabilityStorageTexelBufferArrayDynamicIndexingEXT:    return "StorageTexelBufferArrayDynamicIndexingEXT";
+    case CapabilityUniformBufferArrayNonUniformIndexingEXT:      return "UniformBufferArrayNonUniformIndexingEXT";
+    case CapabilitySampledImageArrayNonUniformIndexingEXT:       return "SampledImageArrayNonUniformIndexingEXT";
+    case CapabilityStorageBufferArrayNonUniformIndexingEXT:      return "StorageBufferArrayNonUniformIndexingEXT";
+    case CapabilityStorageImageArrayNonUniformIndexingEXT:       return "StorageImageArrayNonUniformIndexingEXT";
+    case CapabilityInputAttachmentArrayNonUniformIndexingEXT:    return "InputAttachmentArrayNonUniformIndexingEXT";
+    case CapabilityUniformTexelBufferArrayNonUniformIndexingEXT: return "UniformTexelBufferArrayNonUniformIndexingEXT";
+    case CapabilityStorageTexelBufferArrayNonUniformIndexingEXT: return "StorageTexelBufferArrayNonUniformIndexingEXT";
 
-    case CapabilityVulkanMemoryModelKHR:                return "CapabilityVulkanMemoryModelKHR";
-    case CapabilityVulkanMemoryModelDeviceScopeKHR:     return "CapabilityVulkanMemoryModelDeviceScopeKHR";
+    case CapabilityVulkanMemoryModelKHR:                return "VulkanMemoryModelKHR";
+    case CapabilityVulkanMemoryModelDeviceScopeKHR:     return "VulkanMemoryModelDeviceScopeKHR";
 
-    case CapabilityPhysicalStorageBufferAddressesEXT:   return "CapabilityPhysicalStorageBufferAddressesEXT";
+    case CapabilityPhysicalStorageBufferAddressesEXT:   return "PhysicalStorageBufferAddressesEXT";
 
-    case CapabilityVariablePointers:                    return "CapabilityVariablePointers";
+    case CapabilityVariablePointers:                    return "VariablePointers";
 
-    case CapabilityCooperativeMatrixNV:     return "CapabilityCooperativeMatrixNV";
+    case CapabilityCooperativeMatrixNV:     return "CooperativeMatrixNV";
+    case CapabilityShaderSMBuiltinsNV:      return "ShaderSMBuiltinsNV";
+
+    case CapabilityFragmentShaderSampleInterlockEXT:        return "CapabilityFragmentShaderSampleInterlockEXT";
+    case CapabilityFragmentShaderPixelInterlockEXT:         return "CapabilityFragmentShaderPixelInterlockEXT";
+    case CapabilityFragmentShaderShadingRateInterlockEXT:   return "CapabilityFragmentShaderShadingRateInterlockEXT";
+
+    case CapabilityDemoteToHelperInvocationEXT:             return "DemoteToHelperInvocationEXT";
+    case CapabilityShaderClockKHR:                          return "ShaderClockKHR";
+
+    case CapabilityIntegerFunctions2INTEL:              return "CapabilityIntegerFunctions2INTEL";
 
     default: return "Bad";
     }
@@ -1026,6 +1030,7 @@
     case 82:  return "OpCompositeInsert";
     case 83:  return "OpCopyObject";
     case 84:  return "OpTranspose";
+    case OpCopyLogical: return "OpCopyLogical";
     case 85:  return "Bad";
     case 86:  return "OpSampledImage";
     case 87:  return "OpImageSampleImplicitLod";
@@ -1308,7 +1313,6 @@
     case 4430: return "OpSubgroupAllEqualKHR";
     case 4432: return "OpSubgroupReadInvocationKHR";
 
-#ifdef AMD_EXTENSIONS
     case 5000: return "OpGroupIAddNonUniformAMD";
     case 5001: return "OpGroupFAddNonUniformAMD";
     case 5002: return "OpGroupFMinNonUniformAMD";
@@ -1320,28 +1324,57 @@
 
     case 5011: return "OpFragmentMaskFetchAMD";
     case 5012: return "OpFragmentFetchAMD";
-#endif
+
+    case OpReadClockKHR:               return "OpReadClockKHR";
 
     case OpDecorateStringGOOGLE:       return "OpDecorateStringGOOGLE";
     case OpMemberDecorateStringGOOGLE: return "OpMemberDecorateStringGOOGLE";
 
-#ifdef NV_EXTENSIONS
     case OpGroupNonUniformPartitionNV:       return "OpGroupNonUniformPartitionNV";
-    case OpReportIntersectionNV:             return "OpReportIntersectionNV";
-    case OpIgnoreIntersectionNV:             return "OpIgnoreIntersectionNV";
-    case OpTerminateRayNV:                   return "OpTerminateRayNV";
-    case OpTraceNV:                          return "OpTraceNV";
-    case OpTypeAccelerationStructureNV:      return "OpTypeAccelerationStructureNV";
-    case OpExecuteCallableNV:                return "OpExecuteCallableNV";
+    case OpReportIntersectionKHR:            return "OpReportIntersectionKHR";
+    case OpIgnoreIntersectionKHR:            return "OpIgnoreIntersectionKHR";
+    case OpTerminateRayKHR:                  return "OpTerminateRayKHR";
+    case OpTraceRayKHR:                      return "OpTraceRayKHR";
+    case OpTypeAccelerationStructureKHR:     return "OpTypeAccelerationStructureKHR";
+    case OpExecuteCallableKHR:               return "OpExecuteCallableKHR";
     case OpImageSampleFootprintNV:           return "OpImageSampleFootprintNV";
     case OpWritePackedPrimitiveIndices4x8NV: return "OpWritePackedPrimitiveIndices4x8NV";
-#endif
+
+    case OpTypeRayQueryProvisionalKHR:                                        return "OpTypeRayQueryProvisionalKHR";
+    case OpRayQueryInitializeKHR:                                             return "OpRayQueryInitializeKHR";
+    case OpRayQueryTerminateKHR:                                              return "OpRayQueryTerminateKHR";
+    case OpRayQueryGenerateIntersectionKHR:                                   return "OpRayQueryGenerateIntersectionKHR";
+    case OpRayQueryConfirmIntersectionKHR:                                    return "OpRayQueryConfirmIntersectionKHR";
+    case OpRayQueryProceedKHR:                                                return "OpRayQueryProceedKHR";
+    case OpRayQueryGetIntersectionTypeKHR:                                    return "OpRayQueryGetIntersectionTypeKHR";
+    case OpRayQueryGetRayTMinKHR:                                             return "OpRayQueryGetRayTMinKHR";
+    case OpRayQueryGetRayFlagsKHR:                                            return "OpRayQueryGetRayFlagsKHR";
+    case OpRayQueryGetIntersectionTKHR:                                       return "OpRayQueryGetIntersectionTKHR";
+    case OpRayQueryGetIntersectionInstanceCustomIndexKHR:                     return "OpRayQueryGetIntersectionInstanceCustomIndexKHR";
+    case OpRayQueryGetIntersectionInstanceIdKHR:                              return "OpRayQueryGetIntersectionInstanceIdKHR";
+    case OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR:  return "OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR";
+    case OpRayQueryGetIntersectionGeometryIndexKHR:                           return "OpRayQueryGetIntersectionGeometryIndexKHR";
+    case OpRayQueryGetIntersectionPrimitiveIndexKHR:                          return "OpRayQueryGetIntersectionPrimitiveIndexKHR";
+    case OpRayQueryGetIntersectionBarycentricsKHR:                            return "OpRayQueryGetIntersectionBarycentricsKHR";
+    case OpRayQueryGetIntersectionFrontFaceKHR:                               return "OpRayQueryGetIntersectionFrontFaceKHR";
+    case OpRayQueryGetIntersectionCandidateAABBOpaqueKHR:                     return "OpRayQueryGetIntersectionCandidateAABBOpaqueKHR";
+    case OpRayQueryGetIntersectionObjectRayDirectionKHR:                      return "OpRayQueryGetIntersectionObjectRayDirectionKHR";
+    case OpRayQueryGetIntersectionObjectRayOriginKHR:                         return "OpRayQueryGetIntersectionObjectRayOriginKHR";
+    case OpRayQueryGetWorldRayDirectionKHR:                                   return "OpRayQueryGetWorldRayDirectionKHR";
+    case OpRayQueryGetWorldRayOriginKHR:                                      return "OpRayQueryGetWorldRayOriginKHR";
+    case OpRayQueryGetIntersectionObjectToWorldKHR:                           return "OpRayQueryGetIntersectionObjectToWorldKHR";
+    case OpRayQueryGetIntersectionWorldToObjectKHR:                           return "OpRayQueryGetIntersectionWorldToObjectKHR";
 
     case OpTypeCooperativeMatrixNV:         return "OpTypeCooperativeMatrixNV";
     case OpCooperativeMatrixLoadNV:         return "OpCooperativeMatrixLoadNV";
     case OpCooperativeMatrixStoreNV:        return "OpCooperativeMatrixStoreNV";
     case OpCooperativeMatrixMulAddNV:       return "OpCooperativeMatrixMulAddNV";
     case OpCooperativeMatrixLengthNV:       return "OpCooperativeMatrixLengthNV";
+    case OpDemoteToHelperInvocationEXT:     return "OpDemoteToHelperInvocationEXT";
+    case OpIsHelperInvocationEXT:           return "OpIsHelperInvocationEXT";
+
+    case OpBeginInvocationInterlockEXT:     return "OpBeginInvocationInterlockEXT";
+    case OpEndInvocationInterlockEXT:       return "OpEndInvocationInterlockEXT";
 
     default:
         return "Bad";
@@ -1456,6 +1489,8 @@
     InstructionDesc[OpModuleProcessed].setResultAndType(false, false);
     InstructionDesc[OpTypeCooperativeMatrixNV].setResultAndType(true, false);
     InstructionDesc[OpCooperativeMatrixStoreNV].setResultAndType(false, false);
+    InstructionDesc[OpBeginInvocationInterlockEXT].setResultAndType(false, false);
+    InstructionDesc[OpEndInvocationInterlockEXT].setResultAndType(false, false);
 
     // Specific additional context-dependent operands
 
@@ -1933,6 +1968,8 @@
 
     InstructionDesc[OpTranspose].operands.push(OperandId, "'Matrix'");
 
+    InstructionDesc[OpCopyLogical].operands.push(OperandId, "'Operand'");
+
     InstructionDesc[OpIsNan].operands.push(OperandId, "'x'");
 
     InstructionDesc[OpIsInf].operands.push(OperandId, "'x'");
@@ -2646,7 +2683,6 @@
 
     InstructionDesc[OpModuleProcessed].operands.push(OperandLiteralString, "'process'");
 
-#ifdef AMD_EXTENSIONS
     InstructionDesc[OpGroupIAddNonUniformAMD].operands.push(OperandScope, "'Execution'");
     InstructionDesc[OpGroupIAddNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'");
     InstructionDesc[OpGroupIAddNonUniformAMD].operands.push(OperandId, "'X'");
@@ -2685,36 +2721,128 @@
     InstructionDesc[OpFragmentFetchAMD].operands.push(OperandId, "'Image'");
     InstructionDesc[OpFragmentFetchAMD].operands.push(OperandId, "'Coordinate'");
     InstructionDesc[OpFragmentFetchAMD].operands.push(OperandId, "'Fragment Index'");
-#endif
 
-#ifdef NV_EXTENSIONS
     InstructionDesc[OpGroupNonUniformPartitionNV].operands.push(OperandId, "X");
 
-    InstructionDesc[OpTypeAccelerationStructureNV].setResultAndType(true, false);
+    InstructionDesc[OpTypeAccelerationStructureKHR].setResultAndType(true, false);
 
-    InstructionDesc[OpTraceNV].operands.push(OperandId, "'NV Acceleration Structure'");
-    InstructionDesc[OpTraceNV].operands.push(OperandId, "'Ray Flags'");
-    InstructionDesc[OpTraceNV].operands.push(OperandId, "'Cull Mask'");
-    InstructionDesc[OpTraceNV].operands.push(OperandId, "'SBT Record Offset'");
-    InstructionDesc[OpTraceNV].operands.push(OperandId, "'SBT Record Stride'");
-    InstructionDesc[OpTraceNV].operands.push(OperandId, "'Miss Index'");
-    InstructionDesc[OpTraceNV].operands.push(OperandId, "'Ray Origin'");
-    InstructionDesc[OpTraceNV].operands.push(OperandId, "'TMin'");
-    InstructionDesc[OpTraceNV].operands.push(OperandId, "'Ray Direction'");
-    InstructionDesc[OpTraceNV].operands.push(OperandId, "'TMax'");
-    InstructionDesc[OpTraceNV].operands.push(OperandId, "'Payload'");
-    InstructionDesc[OpTraceNV].setResultAndType(false, false);
+    InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'NV Acceleration Structure'");
+    InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Ray Flags'");
+    InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Cull Mask'");
+    InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'SBT Record Offset'");
+    InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'SBT Record Stride'");
+    InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Miss Index'");
+    InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Ray Origin'");
+    InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'TMin'");
+    InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Ray Direction'");
+    InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'TMax'");
+    InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Payload'");
+    InstructionDesc[OpTraceRayKHR].setResultAndType(false, false);
 
-    InstructionDesc[OpReportIntersectionNV].operands.push(OperandId, "'Hit Parameter'");
-    InstructionDesc[OpReportIntersectionNV].operands.push(OperandId, "'Hit Kind'");
+    InstructionDesc[OpReportIntersectionKHR].operands.push(OperandId, "'Hit Parameter'");
+    InstructionDesc[OpReportIntersectionKHR].operands.push(OperandId, "'Hit Kind'");
 
-    InstructionDesc[OpIgnoreIntersectionNV].setResultAndType(false, false);
+    InstructionDesc[OpIgnoreIntersectionKHR].setResultAndType(false, false);
 
-    InstructionDesc[OpTerminateRayNV].setResultAndType(false, false);
+    InstructionDesc[OpTerminateRayKHR].setResultAndType(false, false);
     
-    InstructionDesc[OpExecuteCallableNV].operands.push(OperandId, "SBT Record Index");
-    InstructionDesc[OpExecuteCallableNV].operands.push(OperandId, "CallableData ID");
-    InstructionDesc[OpExecuteCallableNV].setResultAndType(false, false);
+    InstructionDesc[OpExecuteCallableKHR].operands.push(OperandId, "SBT Record Index");
+    InstructionDesc[OpExecuteCallableKHR].operands.push(OperandId, "CallableData ID");
+    InstructionDesc[OpExecuteCallableKHR].setResultAndType(false, false);
+
+    // Ray Query
+    InstructionDesc[OpTypeAccelerationStructureKHR].setResultAndType(true, false);
+    InstructionDesc[OpTypeRayQueryProvisionalKHR].setResultAndType(true, false);
+
+    InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'AccelerationS'");
+    InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'RayFlags'");
+    InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'CullMask'");
+    InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'Origin'");
+    InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'Tmin'");
+    InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'Direction'");
+    InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'Tmax'");
+    InstructionDesc[OpRayQueryInitializeKHR].setResultAndType(false, false);
+
+    InstructionDesc[OpRayQueryTerminateKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryTerminateKHR].setResultAndType(false, false);
+
+    InstructionDesc[OpRayQueryGenerateIntersectionKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGenerateIntersectionKHR].operands.push(OperandId, "'THit'");
+    InstructionDesc[OpRayQueryGenerateIntersectionKHR].setResultAndType(false, false);
+
+    InstructionDesc[OpRayQueryConfirmIntersectionKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryConfirmIntersectionKHR].setResultAndType(false, false);
+
+    InstructionDesc[OpRayQueryProceedKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryProceedKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetIntersectionTypeKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetIntersectionTypeKHR].operands.push(OperandId, "'Committed'");
+    InstructionDesc[OpRayQueryGetIntersectionTypeKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetRayTMinKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetRayTMinKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetRayFlagsKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetRayFlagsKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetIntersectionTKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetIntersectionTKHR].operands.push(OperandId, "'Committed'");
+    InstructionDesc[OpRayQueryGetIntersectionTKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetIntersectionInstanceCustomIndexKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetIntersectionInstanceCustomIndexKHR].operands.push(OperandId, "'Committed'");
+    InstructionDesc[OpRayQueryGetIntersectionInstanceCustomIndexKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetIntersectionInstanceIdKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetIntersectionInstanceIdKHR].operands.push(OperandId, "'Committed'");
+    InstructionDesc[OpRayQueryGetIntersectionInstanceIdKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR].operands.push(OperandId, "'Committed'");
+    InstructionDesc[OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetIntersectionGeometryIndexKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetIntersectionGeometryIndexKHR].operands.push(OperandId, "'Committed'");
+    InstructionDesc[OpRayQueryGetIntersectionGeometryIndexKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetIntersectionPrimitiveIndexKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetIntersectionPrimitiveIndexKHR].operands.push(OperandId, "'Committed'");
+    InstructionDesc[OpRayQueryGetIntersectionPrimitiveIndexKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetIntersectionBarycentricsKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetIntersectionBarycentricsKHR].operands.push(OperandId, "'Committed'");
+    InstructionDesc[OpRayQueryGetIntersectionBarycentricsKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetIntersectionFrontFaceKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetIntersectionFrontFaceKHR].operands.push(OperandId, "'Committed'");
+    InstructionDesc[OpRayQueryGetIntersectionFrontFaceKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetIntersectionCandidateAABBOpaqueKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetIntersectionCandidateAABBOpaqueKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetIntersectionObjectRayDirectionKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetIntersectionObjectRayDirectionKHR].operands.push(OperandId, "'Committed'");
+    InstructionDesc[OpRayQueryGetIntersectionObjectRayDirectionKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetIntersectionObjectRayOriginKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetIntersectionObjectRayOriginKHR].operands.push(OperandId, "'Committed'");
+    InstructionDesc[OpRayQueryGetIntersectionObjectRayOriginKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetWorldRayDirectionKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetWorldRayDirectionKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetWorldRayOriginKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetWorldRayOriginKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetIntersectionObjectToWorldKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetIntersectionObjectToWorldKHR].operands.push(OperandId, "'Committed'");
+    InstructionDesc[OpRayQueryGetIntersectionObjectToWorldKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetIntersectionWorldToObjectKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetIntersectionWorldToObjectKHR].operands.push(OperandId, "'Committed'");
+    InstructionDesc[OpRayQueryGetIntersectionWorldToObjectKHR].setResultAndType(true, true);
 
     InstructionDesc[OpImageSampleFootprintNV].operands.push(OperandId, "'Sampled Image'");
     InstructionDesc[OpImageSampleFootprintNV].operands.push(OperandId, "'Coordinate'");
@@ -2725,7 +2853,6 @@
     
     InstructionDesc[OpWritePackedPrimitiveIndices4x8NV].operands.push(OperandId, "'Index Offset'");
     InstructionDesc[OpWritePackedPrimitiveIndices4x8NV].operands.push(OperandId, "'Packed Indices'");
-#endif
 
     InstructionDesc[OpTypeCooperativeMatrixNV].operands.push(OperandId, "'Component Type'");
     InstructionDesc[OpTypeCooperativeMatrixNV].operands.push(OperandId, "'Scope'");
@@ -2752,6 +2879,10 @@
     InstructionDesc[OpCooperativeMatrixMulAddNV].operands.push(OperandId, "'C'");
 
     InstructionDesc[OpCooperativeMatrixLengthNV].operands.push(OperandId, "'Type'");
+
+    InstructionDesc[OpDemoteToHelperInvocationEXT].setResultAndType(false, false);
+
+    InstructionDesc[OpReadClockKHR].operands.push(OperandScope, "'Scope'");
 }
 
 }; // end spv namespace
diff --git a/SPIRV/hex_float.h b/SPIRV/hex_float.h
index 905b21a..8be8e9f 100644
--- a/SPIRV/hex_float.h
+++ b/SPIRV/hex_float.h
@@ -784,8 +784,8 @@
   if (val.isInfinity()) {
     // Fail the parse.  Emulate standard behaviour by setting the value to
     // the closest normal value, and set the fail bit on the stream.
-    value.set_value((value.isNegative() | negate_value) ? T::lowest()
-                                                        : T::max());
+    value.set_value((value.isNegative() || negate_value) ? T::lowest()
+                                                         : T::max());
     is.setstate(std::ios_base::failbit);
   }
   return is;
diff --git a/SPIRV/spirv.hpp b/SPIRV/spirv.hpp
index 62c2dc9..dae36cf 100644
--- a/SPIRV/spirv.hpp
+++ b/SPIRV/spirv.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2019 The Khronos Group Inc.
+// Copyright (c) 2014-2020 The Khronos Group Inc.
 // 
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and/or associated documentation files (the "Materials"),
@@ -49,12 +49,12 @@
 
 typedef unsigned int Id;
 
-#define SPV_VERSION 0x10300
-#define SPV_REVISION 7
+#define SPV_VERSION 0x10500
+#define SPV_REVISION 3
 
 static const unsigned int MagicNumber = 0x07230203;
-static const unsigned int Version = 0x00010300;
-static const unsigned int Revision = 7;
+static const unsigned int Version = 0x00010500;
+static const unsigned int Revision = 3;
 static const unsigned int OpCodeMask = 0xffff;
 static const unsigned int WordCountShift = 16;
 
@@ -78,11 +78,17 @@
     ExecutionModelKernel = 6,
     ExecutionModelTaskNV = 5267,
     ExecutionModelMeshNV = 5268,
+    ExecutionModelRayGenerationKHR = 5313,
     ExecutionModelRayGenerationNV = 5313,
+    ExecutionModelIntersectionKHR = 5314,
     ExecutionModelIntersectionNV = 5314,
+    ExecutionModelAnyHitKHR = 5315,
     ExecutionModelAnyHitNV = 5315,
+    ExecutionModelClosestHitKHR = 5316,
     ExecutionModelClosestHitNV = 5316,
+    ExecutionModelMissKHR = 5317,
     ExecutionModelMissNV = 5317,
+    ExecutionModelCallableKHR = 5318,
     ExecutionModelCallableNV = 5318,
     ExecutionModelMax = 0x7fffffff,
 };
@@ -91,6 +97,7 @@
     AddressingModelLogical = 0,
     AddressingModelPhysical32 = 1,
     AddressingModelPhysical64 = 2,
+    AddressingModelPhysicalStorageBuffer64 = 5348,
     AddressingModelPhysicalStorageBuffer64EXT = 5348,
     AddressingModelMax = 0x7fffffff,
 };
@@ -99,6 +106,7 @@
     MemoryModelSimple = 0,
     MemoryModelGLSL450 = 1,
     MemoryModelOpenCL = 2,
+    MemoryModelVulkan = 3,
     MemoryModelVulkanKHR = 3,
     MemoryModelMax = 0x7fffffff,
 };
@@ -154,6 +162,12 @@
     ExecutionModeDerivativeGroupQuadsNV = 5289,
     ExecutionModeDerivativeGroupLinearNV = 5290,
     ExecutionModeOutputTrianglesNV = 5298,
+    ExecutionModePixelInterlockOrderedEXT = 5366,
+    ExecutionModePixelInterlockUnorderedEXT = 5367,
+    ExecutionModeSampleInterlockOrderedEXT = 5368,
+    ExecutionModeSampleInterlockUnorderedEXT = 5369,
+    ExecutionModeShadingRateInterlockOrderedEXT = 5370,
+    ExecutionModeShadingRateInterlockUnorderedEXT = 5371,
     ExecutionModeMax = 0x7fffffff,
 };
 
@@ -171,12 +185,19 @@
     StorageClassAtomicCounter = 10,
     StorageClassImage = 11,
     StorageClassStorageBuffer = 12,
+    StorageClassCallableDataKHR = 5328,
     StorageClassCallableDataNV = 5328,
+    StorageClassIncomingCallableDataKHR = 5329,
     StorageClassIncomingCallableDataNV = 5329,
+    StorageClassRayPayloadKHR = 5338,
     StorageClassRayPayloadNV = 5338,
+    StorageClassHitAttributeKHR = 5339,
     StorageClassHitAttributeNV = 5339,
+    StorageClassIncomingRayPayloadKHR = 5342,
     StorageClassIncomingRayPayloadNV = 5342,
+    StorageClassShaderRecordBufferKHR = 5343,
     StorageClassShaderRecordBufferNV = 5343,
+    StorageClassPhysicalStorageBuffer = 5349,
     StorageClassPhysicalStorageBufferEXT = 5349,
     StorageClassMax = 0x7fffffff,
 };
@@ -305,10 +326,16 @@
     ImageOperandsConstOffsetsShift = 5,
     ImageOperandsSampleShift = 6,
     ImageOperandsMinLodShift = 7,
+    ImageOperandsMakeTexelAvailableShift = 8,
     ImageOperandsMakeTexelAvailableKHRShift = 8,
+    ImageOperandsMakeTexelVisibleShift = 9,
     ImageOperandsMakeTexelVisibleKHRShift = 9,
+    ImageOperandsNonPrivateTexelShift = 10,
     ImageOperandsNonPrivateTexelKHRShift = 10,
+    ImageOperandsVolatileTexelShift = 11,
     ImageOperandsVolatileTexelKHRShift = 11,
+    ImageOperandsSignExtendShift = 12,
+    ImageOperandsZeroExtendShift = 13,
     ImageOperandsMax = 0x7fffffff,
 };
 
@@ -322,10 +349,16 @@
     ImageOperandsConstOffsetsMask = 0x00000020,
     ImageOperandsSampleMask = 0x00000040,
     ImageOperandsMinLodMask = 0x00000080,
+    ImageOperandsMakeTexelAvailableMask = 0x00000100,
     ImageOperandsMakeTexelAvailableKHRMask = 0x00000100,
+    ImageOperandsMakeTexelVisibleMask = 0x00000200,
     ImageOperandsMakeTexelVisibleKHRMask = 0x00000200,
+    ImageOperandsNonPrivateTexelMask = 0x00000400,
     ImageOperandsNonPrivateTexelKHRMask = 0x00000400,
+    ImageOperandsVolatileTexelMask = 0x00000800,
     ImageOperandsVolatileTexelKHRMask = 0x00000800,
+    ImageOperandsSignExtendMask = 0x00001000,
+    ImageOperandsZeroExtendMask = 0x00002000,
 };
 
 enum FPFastMathModeShift {
@@ -406,6 +439,7 @@
     DecorationNonWritable = 24,
     DecorationNonReadable = 25,
     DecorationUniform = 26,
+    DecorationUniformId = 27,
     DecorationSaturatedConversion = 28,
     DecorationStream = 29,
     DecorationLocation = 30,
@@ -437,11 +471,17 @@
     DecorationPerViewNV = 5272,
     DecorationPerTaskNV = 5273,
     DecorationPerVertexNV = 5285,
+    DecorationNonUniform = 5300,
     DecorationNonUniformEXT = 5300,
+    DecorationRestrictPointer = 5355,
     DecorationRestrictPointerEXT = 5355,
+    DecorationAliasedPointer = 5356,
     DecorationAliasedPointerEXT = 5356,
+    DecorationCounterBuffer = 5634,
     DecorationHlslCounterBufferGOOGLE = 5634,
     DecorationHlslSemanticGOOGLE = 5635,
+    DecorationUserSemantic = 5635,
+    DecorationUserTypeGOOGLE = 5636,
     DecorationMax = 0x7fffffff,
 };
 
@@ -530,20 +570,39 @@
     BuiltInFragmentSizeNV = 5292,
     BuiltInFragInvocationCountEXT = 5293,
     BuiltInInvocationsPerPixelNV = 5293,
+    BuiltInLaunchIdKHR = 5319,
     BuiltInLaunchIdNV = 5319,
+    BuiltInLaunchSizeKHR = 5320,
     BuiltInLaunchSizeNV = 5320,
+    BuiltInWorldRayOriginKHR = 5321,
     BuiltInWorldRayOriginNV = 5321,
+    BuiltInWorldRayDirectionKHR = 5322,
     BuiltInWorldRayDirectionNV = 5322,
+    BuiltInObjectRayOriginKHR = 5323,
     BuiltInObjectRayOriginNV = 5323,
+    BuiltInObjectRayDirectionKHR = 5324,
     BuiltInObjectRayDirectionNV = 5324,
+    BuiltInRayTminKHR = 5325,
     BuiltInRayTminNV = 5325,
+    BuiltInRayTmaxKHR = 5326,
     BuiltInRayTmaxNV = 5326,
+    BuiltInInstanceCustomIndexKHR = 5327,
     BuiltInInstanceCustomIndexNV = 5327,
+    BuiltInObjectToWorldKHR = 5330,
     BuiltInObjectToWorldNV = 5330,
+    BuiltInWorldToObjectKHR = 5331,
     BuiltInWorldToObjectNV = 5331,
+    BuiltInHitTKHR = 5332,
     BuiltInHitTNV = 5332,
+    BuiltInHitKindKHR = 5333,
     BuiltInHitKindNV = 5333,
+    BuiltInIncomingRayFlagsKHR = 5351,
     BuiltInIncomingRayFlagsNV = 5351,
+    BuiltInRayGeometryIndexKHR = 5352,
+    BuiltInWarpsPerSMNV = 5374,
+    BuiltInSMCountNV = 5375,
+    BuiltInWarpIDNV = 5376,
+    BuiltInSMIDNV = 5377,
     BuiltInMax = 0x7fffffff,
 };
 
@@ -564,6 +623,11 @@
     LoopControlDontUnrollShift = 1,
     LoopControlDependencyInfiniteShift = 2,
     LoopControlDependencyLengthShift = 3,
+    LoopControlMinIterationsShift = 4,
+    LoopControlMaxIterationsShift = 5,
+    LoopControlIterationMultipleShift = 6,
+    LoopControlPeelCountShift = 7,
+    LoopControlPartialCountShift = 8,
     LoopControlMax = 0x7fffffff,
 };
 
@@ -573,6 +637,11 @@
     LoopControlDontUnrollMask = 0x00000002,
     LoopControlDependencyInfiniteMask = 0x00000004,
     LoopControlDependencyLengthMask = 0x00000008,
+    LoopControlMinIterationsMask = 0x00000010,
+    LoopControlMaxIterationsMask = 0x00000020,
+    LoopControlIterationMultipleMask = 0x00000040,
+    LoopControlPeelCountMask = 0x00000080,
+    LoopControlPartialCountMask = 0x00000100,
 };
 
 enum FunctionControlShift {
@@ -602,9 +671,13 @@
     MemorySemanticsCrossWorkgroupMemoryShift = 9,
     MemorySemanticsAtomicCounterMemoryShift = 10,
     MemorySemanticsImageMemoryShift = 11,
+    MemorySemanticsOutputMemoryShift = 12,
     MemorySemanticsOutputMemoryKHRShift = 12,
+    MemorySemanticsMakeAvailableShift = 13,
     MemorySemanticsMakeAvailableKHRShift = 13,
+    MemorySemanticsMakeVisibleShift = 14,
     MemorySemanticsMakeVisibleKHRShift = 14,
+    MemorySemanticsVolatileShift = 15,
     MemorySemanticsMax = 0x7fffffff,
 };
 
@@ -620,17 +693,24 @@
     MemorySemanticsCrossWorkgroupMemoryMask = 0x00000200,
     MemorySemanticsAtomicCounterMemoryMask = 0x00000400,
     MemorySemanticsImageMemoryMask = 0x00000800,
+    MemorySemanticsOutputMemoryMask = 0x00001000,
     MemorySemanticsOutputMemoryKHRMask = 0x00001000,
+    MemorySemanticsMakeAvailableMask = 0x00002000,
     MemorySemanticsMakeAvailableKHRMask = 0x00002000,
+    MemorySemanticsMakeVisibleMask = 0x00004000,
     MemorySemanticsMakeVisibleKHRMask = 0x00004000,
+    MemorySemanticsVolatileMask = 0x00008000,
 };
 
 enum MemoryAccessShift {
     MemoryAccessVolatileShift = 0,
     MemoryAccessAlignedShift = 1,
     MemoryAccessNontemporalShift = 2,
+    MemoryAccessMakePointerAvailableShift = 3,
     MemoryAccessMakePointerAvailableKHRShift = 3,
+    MemoryAccessMakePointerVisibleShift = 4,
     MemoryAccessMakePointerVisibleKHRShift = 4,
+    MemoryAccessNonPrivatePointerShift = 5,
     MemoryAccessNonPrivatePointerKHRShift = 5,
     MemoryAccessMax = 0x7fffffff,
 };
@@ -640,8 +720,11 @@
     MemoryAccessVolatileMask = 0x00000001,
     MemoryAccessAlignedMask = 0x00000002,
     MemoryAccessNontemporalMask = 0x00000004,
+    MemoryAccessMakePointerAvailableMask = 0x00000008,
     MemoryAccessMakePointerAvailableKHRMask = 0x00000008,
+    MemoryAccessMakePointerVisibleMask = 0x00000010,
     MemoryAccessMakePointerVisibleKHRMask = 0x00000010,
+    MemoryAccessNonPrivatePointerMask = 0x00000020,
     MemoryAccessNonPrivatePointerKHRMask = 0x00000020,
 };
 
@@ -651,7 +734,9 @@
     ScopeWorkgroup = 2,
     ScopeSubgroup = 3,
     ScopeInvocation = 4,
+    ScopeQueueFamily = 5,
     ScopeQueueFamilyKHR = 5,
+    ScopeShaderCallKHR = 6,
     ScopeMax = 0x7fffffff,
 };
 
@@ -751,6 +836,8 @@
     CapabilityGroupNonUniformShuffleRelative = 66,
     CapabilityGroupNonUniformClustered = 67,
     CapabilityGroupNonUniformQuad = 68,
+    CapabilityShaderLayer = 69,
+    CapabilityShaderViewportIndex = 70,
     CapabilitySubgroupBallotKHR = 4423,
     CapabilityDrawParameters = 4427,
     CapabilitySubgroupVoteKHR = 4431,
@@ -774,11 +861,14 @@
     CapabilitySignedZeroInfNanPreserve = 4466,
     CapabilityRoundingModeRTE = 4467,
     CapabilityRoundingModeRTZ = 4468,
+    CapabilityRayQueryProvisionalKHR = 4471,
+    CapabilityRayTraversalPrimitiveCullingProvisionalKHR = 4478,
     CapabilityFloat16ImageAMD = 5008,
     CapabilityImageGatherBiasLodAMD = 5009,
     CapabilityFragmentMaskAMD = 5010,
     CapabilityStencilExportEXT = 5013,
     CapabilityImageReadWriteLodAMD = 5015,
+    CapabilityShaderClockKHR = 5055,
     CapabilitySampleMaskOverrideCoverageNV = 5249,
     CapabilityGeometryShaderPassthroughNV = 5251,
     CapabilityShaderViewportIndexLayerEXT = 5254,
@@ -794,34 +884,103 @@
     CapabilityFragmentDensityEXT = 5291,
     CapabilityShadingRateNV = 5291,
     CapabilityGroupNonUniformPartitionedNV = 5297,
+    CapabilityShaderNonUniform = 5301,
     CapabilityShaderNonUniformEXT = 5301,
+    CapabilityRuntimeDescriptorArray = 5302,
     CapabilityRuntimeDescriptorArrayEXT = 5302,
+    CapabilityInputAttachmentArrayDynamicIndexing = 5303,
     CapabilityInputAttachmentArrayDynamicIndexingEXT = 5303,
+    CapabilityUniformTexelBufferArrayDynamicIndexing = 5304,
     CapabilityUniformTexelBufferArrayDynamicIndexingEXT = 5304,
+    CapabilityStorageTexelBufferArrayDynamicIndexing = 5305,
     CapabilityStorageTexelBufferArrayDynamicIndexingEXT = 5305,
+    CapabilityUniformBufferArrayNonUniformIndexing = 5306,
     CapabilityUniformBufferArrayNonUniformIndexingEXT = 5306,
+    CapabilitySampledImageArrayNonUniformIndexing = 5307,
     CapabilitySampledImageArrayNonUniformIndexingEXT = 5307,
+    CapabilityStorageBufferArrayNonUniformIndexing = 5308,
     CapabilityStorageBufferArrayNonUniformIndexingEXT = 5308,
+    CapabilityStorageImageArrayNonUniformIndexing = 5309,
     CapabilityStorageImageArrayNonUniformIndexingEXT = 5309,
+    CapabilityInputAttachmentArrayNonUniformIndexing = 5310,
     CapabilityInputAttachmentArrayNonUniformIndexingEXT = 5310,
+    CapabilityUniformTexelBufferArrayNonUniformIndexing = 5311,
     CapabilityUniformTexelBufferArrayNonUniformIndexingEXT = 5311,
+    CapabilityStorageTexelBufferArrayNonUniformIndexing = 5312,
     CapabilityStorageTexelBufferArrayNonUniformIndexingEXT = 5312,
     CapabilityRayTracingNV = 5340,
+    CapabilityVulkanMemoryModel = 5345,
     CapabilityVulkanMemoryModelKHR = 5345,
+    CapabilityVulkanMemoryModelDeviceScope = 5346,
     CapabilityVulkanMemoryModelDeviceScopeKHR = 5346,
+    CapabilityPhysicalStorageBufferAddresses = 5347,
     CapabilityPhysicalStorageBufferAddressesEXT = 5347,
     CapabilityComputeDerivativeGroupLinearNV = 5350,
+    CapabilityRayTracingProvisionalKHR = 5353,
     CapabilityCooperativeMatrixNV = 5357,
+    CapabilityFragmentShaderSampleInterlockEXT = 5363,
+    CapabilityFragmentShaderShadingRateInterlockEXT = 5372,
+    CapabilityShaderSMBuiltinsNV = 5373,
+    CapabilityFragmentShaderPixelInterlockEXT = 5378,
+    CapabilityDemoteToHelperInvocationEXT = 5379,
     CapabilitySubgroupShuffleINTEL = 5568,
     CapabilitySubgroupBufferBlockIOINTEL = 5569,
     CapabilitySubgroupImageBlockIOINTEL = 5570,
     CapabilitySubgroupImageMediaBlockIOINTEL = 5579,
+    CapabilityIntegerFunctions2INTEL = 5584,
     CapabilitySubgroupAvcMotionEstimationINTEL = 5696,
     CapabilitySubgroupAvcMotionEstimationIntraINTEL = 5697,
     CapabilitySubgroupAvcMotionEstimationChromaINTEL = 5698,
     CapabilityMax = 0x7fffffff,
 };
 
+enum RayFlagsShift {
+    RayFlagsOpaqueKHRShift = 0,
+    RayFlagsNoOpaqueKHRShift = 1,
+    RayFlagsTerminateOnFirstHitKHRShift = 2,
+    RayFlagsSkipClosestHitShaderKHRShift = 3,
+    RayFlagsCullBackFacingTrianglesKHRShift = 4,
+    RayFlagsCullFrontFacingTrianglesKHRShift = 5,
+    RayFlagsCullOpaqueKHRShift = 6,
+    RayFlagsCullNoOpaqueKHRShift = 7,
+    RayFlagsSkipTrianglesKHRShift = 8,
+    RayFlagsSkipAABBsKHRShift = 9,
+    RayFlagsMax = 0x7fffffff,
+};
+
+enum RayFlagsMask {
+    RayFlagsMaskNone = 0,
+    RayFlagsOpaqueKHRMask = 0x00000001,
+    RayFlagsNoOpaqueKHRMask = 0x00000002,
+    RayFlagsTerminateOnFirstHitKHRMask = 0x00000004,
+    RayFlagsSkipClosestHitShaderKHRMask = 0x00000008,
+    RayFlagsCullBackFacingTrianglesKHRMask = 0x00000010,
+    RayFlagsCullFrontFacingTrianglesKHRMask = 0x00000020,
+    RayFlagsCullOpaqueKHRMask = 0x00000040,
+    RayFlagsCullNoOpaqueKHRMask = 0x00000080,
+    RayFlagsSkipTrianglesKHRMask = 0x00000100,
+    RayFlagsSkipAABBsKHRMask = 0x00000200,
+};
+
+enum RayQueryIntersection {
+    RayQueryIntersectionRayQueryCandidateIntersectionKHR = 0,
+    RayQueryIntersectionRayQueryCommittedIntersectionKHR = 1,
+    RayQueryIntersectionMax = 0x7fffffff,
+};
+
+enum RayQueryCommittedIntersectionType {
+    RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionNoneKHR = 0,
+    RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionTriangleKHR = 1,
+    RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionGeneratedKHR = 2,
+    RayQueryCommittedIntersectionTypeMax = 0x7fffffff,
+};
+
+enum RayQueryCandidateIntersectionType {
+    RayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionTriangleKHR = 0,
+    RayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionAABBKHR = 1,
+    RayQueryCandidateIntersectionTypeMax = 0x7fffffff,
+};
+
 enum Op {
     OpNop = 0,
     OpUndef = 1,
@@ -1163,12 +1322,23 @@
     OpGroupNonUniformLogicalXor = 364,
     OpGroupNonUniformQuadBroadcast = 365,
     OpGroupNonUniformQuadSwap = 366,
+    OpCopyLogical = 400,
+    OpPtrEqual = 401,
+    OpPtrNotEqual = 402,
+    OpPtrDiff = 403,
     OpSubgroupBallotKHR = 4421,
     OpSubgroupFirstInvocationKHR = 4422,
     OpSubgroupAllKHR = 4428,
     OpSubgroupAnyKHR = 4429,
     OpSubgroupAllEqualKHR = 4430,
     OpSubgroupReadInvocationKHR = 4432,
+    OpTypeRayQueryProvisionalKHR = 4472,
+    OpRayQueryInitializeKHR = 4473,
+    OpRayQueryTerminateKHR = 4474,
+    OpRayQueryGenerateIntersectionKHR = 4475,
+    OpRayQueryConfirmIntersectionKHR = 4476,
+    OpRayQueryProceedKHR = 4477,
+    OpRayQueryGetIntersectionTypeKHR = 4479,
     OpGroupIAddNonUniformAMD = 5000,
     OpGroupFAddNonUniformAMD = 5001,
     OpGroupFMinNonUniformAMD = 5002,
@@ -1179,20 +1349,31 @@
     OpGroupSMaxNonUniformAMD = 5007,
     OpFragmentMaskFetchAMD = 5011,
     OpFragmentFetchAMD = 5012,
+    OpReadClockKHR = 5056,
     OpImageSampleFootprintNV = 5283,
     OpGroupNonUniformPartitionNV = 5296,
     OpWritePackedPrimitiveIndices4x8NV = 5299,
+    OpReportIntersectionKHR = 5334,
     OpReportIntersectionNV = 5334,
+    OpIgnoreIntersectionKHR = 5335,
     OpIgnoreIntersectionNV = 5335,
+    OpTerminateRayKHR = 5336,
     OpTerminateRayNV = 5336,
     OpTraceNV = 5337,
+    OpTraceRayKHR = 5337,
+    OpTypeAccelerationStructureKHR = 5341,
     OpTypeAccelerationStructureNV = 5341,
+    OpExecuteCallableKHR = 5344,
     OpExecuteCallableNV = 5344,
     OpTypeCooperativeMatrixNV = 5358,
     OpCooperativeMatrixLoadNV = 5359,
     OpCooperativeMatrixStoreNV = 5360,
     OpCooperativeMatrixMulAddNV = 5361,
     OpCooperativeMatrixLengthNV = 5362,
+    OpBeginInvocationInterlockEXT = 5364,
+    OpEndInvocationInterlockEXT = 5365,
+    OpDemoteToHelperInvocationEXT = 5380,
+    OpIsHelperInvocationEXT = 5381,
     OpSubgroupShuffleINTEL = 5571,
     OpSubgroupShuffleDownINTEL = 5572,
     OpSubgroupShuffleUpINTEL = 5573,
@@ -1203,7 +1384,23 @@
     OpSubgroupImageBlockWriteINTEL = 5578,
     OpSubgroupImageMediaBlockReadINTEL = 5580,
     OpSubgroupImageMediaBlockWriteINTEL = 5581,
+    OpUCountLeadingZerosINTEL = 5585,
+    OpUCountTrailingZerosINTEL = 5586,
+    OpAbsISubINTEL = 5587,
+    OpAbsUSubINTEL = 5588,
+    OpIAddSatINTEL = 5589,
+    OpUAddSatINTEL = 5590,
+    OpIAverageINTEL = 5591,
+    OpUAverageINTEL = 5592,
+    OpIAverageRoundedINTEL = 5593,
+    OpUAverageRoundedINTEL = 5594,
+    OpISubSatINTEL = 5595,
+    OpUSubSatINTEL = 5596,
+    OpIMul32x16INTEL = 5597,
+    OpUMul32x16INTEL = 5598,
+    OpDecorateString = 5632,
     OpDecorateStringGOOGLE = 5632,
+    OpMemberDecorateString = 5633,
     OpMemberDecorateStringGOOGLE = 5633,
     OpVmeImageINTEL = 5699,
     OpTypeVmeImageINTEL = 5700,
@@ -1323,9 +1520,582 @@
     OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814,
     OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815,
     OpSubgroupAvcSicGetInterRawSadsINTEL = 5816,
+    OpRayQueryGetRayTMinKHR = 6016,
+    OpRayQueryGetRayFlagsKHR = 6017,
+    OpRayQueryGetIntersectionTKHR = 6018,
+    OpRayQueryGetIntersectionInstanceCustomIndexKHR = 6019,
+    OpRayQueryGetIntersectionInstanceIdKHR = 6020,
+    OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR = 6021,
+    OpRayQueryGetIntersectionGeometryIndexKHR = 6022,
+    OpRayQueryGetIntersectionPrimitiveIndexKHR = 6023,
+    OpRayQueryGetIntersectionBarycentricsKHR = 6024,
+    OpRayQueryGetIntersectionFrontFaceKHR = 6025,
+    OpRayQueryGetIntersectionCandidateAABBOpaqueKHR = 6026,
+    OpRayQueryGetIntersectionObjectRayDirectionKHR = 6027,
+    OpRayQueryGetIntersectionObjectRayOriginKHR = 6028,
+    OpRayQueryGetWorldRayDirectionKHR = 6029,
+    OpRayQueryGetWorldRayOriginKHR = 6030,
+    OpRayQueryGetIntersectionObjectToWorldKHR = 6031,
+    OpRayQueryGetIntersectionWorldToObjectKHR = 6032,
     OpMax = 0x7fffffff,
 };
 
+#ifdef SPV_ENABLE_UTILITY_CODE
+inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) {
+    *hasResult = *hasResultType = false;
+    switch (opcode) {
+    default: /* unknown opcode */ break;
+    case OpNop: *hasResult = false; *hasResultType = false; break;
+    case OpUndef: *hasResult = true; *hasResultType = true; break;
+    case OpSourceContinued: *hasResult = false; *hasResultType = false; break;
+    case OpSource: *hasResult = false; *hasResultType = false; break;
+    case OpSourceExtension: *hasResult = false; *hasResultType = false; break;
+    case OpName: *hasResult = false; *hasResultType = false; break;
+    case OpMemberName: *hasResult = false; *hasResultType = false; break;
+    case OpString: *hasResult = true; *hasResultType = false; break;
+    case OpLine: *hasResult = false; *hasResultType = false; break;
+    case OpExtension: *hasResult = false; *hasResultType = false; break;
+    case OpExtInstImport: *hasResult = true; *hasResultType = false; break;
+    case OpExtInst: *hasResult = true; *hasResultType = true; break;
+    case OpMemoryModel: *hasResult = false; *hasResultType = false; break;
+    case OpEntryPoint: *hasResult = false; *hasResultType = false; break;
+    case OpExecutionMode: *hasResult = false; *hasResultType = false; break;
+    case OpCapability: *hasResult = false; *hasResultType = false; break;
+    case OpTypeVoid: *hasResult = true; *hasResultType = false; break;
+    case OpTypeBool: *hasResult = true; *hasResultType = false; break;
+    case OpTypeInt: *hasResult = true; *hasResultType = false; break;
+    case OpTypeFloat: *hasResult = true; *hasResultType = false; break;
+    case OpTypeVector: *hasResult = true; *hasResultType = false; break;
+    case OpTypeMatrix: *hasResult = true; *hasResultType = false; break;
+    case OpTypeImage: *hasResult = true; *hasResultType = false; break;
+    case OpTypeSampler: *hasResult = true; *hasResultType = false; break;
+    case OpTypeSampledImage: *hasResult = true; *hasResultType = false; break;
+    case OpTypeArray: *hasResult = true; *hasResultType = false; break;
+    case OpTypeRuntimeArray: *hasResult = true; *hasResultType = false; break;
+    case OpTypeStruct: *hasResult = true; *hasResultType = false; break;
+    case OpTypeOpaque: *hasResult = true; *hasResultType = false; break;
+    case OpTypePointer: *hasResult = true; *hasResultType = false; break;
+    case OpTypeFunction: *hasResult = true; *hasResultType = false; break;
+    case OpTypeEvent: *hasResult = true; *hasResultType = false; break;
+    case OpTypeDeviceEvent: *hasResult = true; *hasResultType = false; break;
+    case OpTypeReserveId: *hasResult = true; *hasResultType = false; break;
+    case OpTypeQueue: *hasResult = true; *hasResultType = false; break;
+    case OpTypePipe: *hasResult = true; *hasResultType = false; break;
+    case OpTypeForwardPointer: *hasResult = false; *hasResultType = false; break;
+    case OpConstantTrue: *hasResult = true; *hasResultType = true; break;
+    case OpConstantFalse: *hasResult = true; *hasResultType = true; break;
+    case OpConstant: *hasResult = true; *hasResultType = true; break;
+    case OpConstantComposite: *hasResult = true; *hasResultType = true; break;
+    case OpConstantSampler: *hasResult = true; *hasResultType = true; break;
+    case OpConstantNull: *hasResult = true; *hasResultType = true; break;
+    case OpSpecConstantTrue: *hasResult = true; *hasResultType = true; break;
+    case OpSpecConstantFalse: *hasResult = true; *hasResultType = true; break;
+    case OpSpecConstant: *hasResult = true; *hasResultType = true; break;
+    case OpSpecConstantComposite: *hasResult = true; *hasResultType = true; break;
+    case OpSpecConstantOp: *hasResult = true; *hasResultType = true; break;
+    case OpFunction: *hasResult = true; *hasResultType = true; break;
+    case OpFunctionParameter: *hasResult = true; *hasResultType = true; break;
+    case OpFunctionEnd: *hasResult = false; *hasResultType = false; break;
+    case OpFunctionCall: *hasResult = true; *hasResultType = true; break;
+    case OpVariable: *hasResult = true; *hasResultType = true; break;
+    case OpImageTexelPointer: *hasResult = true; *hasResultType = true; break;
+    case OpLoad: *hasResult = true; *hasResultType = true; break;
+    case OpStore: *hasResult = false; *hasResultType = false; break;
+    case OpCopyMemory: *hasResult = false; *hasResultType = false; break;
+    case OpCopyMemorySized: *hasResult = false; *hasResultType = false; break;
+    case OpAccessChain: *hasResult = true; *hasResultType = true; break;
+    case OpInBoundsAccessChain: *hasResult = true; *hasResultType = true; break;
+    case OpPtrAccessChain: *hasResult = true; *hasResultType = true; break;
+    case OpArrayLength: *hasResult = true; *hasResultType = true; break;
+    case OpGenericPtrMemSemantics: *hasResult = true; *hasResultType = true; break;
+    case OpInBoundsPtrAccessChain: *hasResult = true; *hasResultType = true; break;
+    case OpDecorate: *hasResult = false; *hasResultType = false; break;
+    case OpMemberDecorate: *hasResult = false; *hasResultType = false; break;
+    case OpDecorationGroup: *hasResult = true; *hasResultType = false; break;
+    case OpGroupDecorate: *hasResult = false; *hasResultType = false; break;
+    case OpGroupMemberDecorate: *hasResult = false; *hasResultType = false; break;
+    case OpVectorExtractDynamic: *hasResult = true; *hasResultType = true; break;
+    case OpVectorInsertDynamic: *hasResult = true; *hasResultType = true; break;
+    case OpVectorShuffle: *hasResult = true; *hasResultType = true; break;
+    case OpCompositeConstruct: *hasResult = true; *hasResultType = true; break;
+    case OpCompositeExtract: *hasResult = true; *hasResultType = true; break;
+    case OpCompositeInsert: *hasResult = true; *hasResultType = true; break;
+    case OpCopyObject: *hasResult = true; *hasResultType = true; break;
+    case OpTranspose: *hasResult = true; *hasResultType = true; break;
+    case OpSampledImage: *hasResult = true; *hasResultType = true; break;
+    case OpImageSampleImplicitLod: *hasResult = true; *hasResultType = true; break;
+    case OpImageSampleExplicitLod: *hasResult = true; *hasResultType = true; break;
+    case OpImageSampleDrefImplicitLod: *hasResult = true; *hasResultType = true; break;
+    case OpImageSampleDrefExplicitLod: *hasResult = true; *hasResultType = true; break;
+    case OpImageSampleProjImplicitLod: *hasResult = true; *hasResultType = true; break;
+    case OpImageSampleProjExplicitLod: *hasResult = true; *hasResultType = true; break;
+    case OpImageSampleProjDrefImplicitLod: *hasResult = true; *hasResultType = true; break;
+    case OpImageSampleProjDrefExplicitLod: *hasResult = true; *hasResultType = true; break;
+    case OpImageFetch: *hasResult = true; *hasResultType = true; break;
+    case OpImageGather: *hasResult = true; *hasResultType = true; break;
+    case OpImageDrefGather: *hasResult = true; *hasResultType = true; break;
+    case OpImageRead: *hasResult = true; *hasResultType = true; break;
+    case OpImageWrite: *hasResult = false; *hasResultType = false; break;
+    case OpImage: *hasResult = true; *hasResultType = true; break;
+    case OpImageQueryFormat: *hasResult = true; *hasResultType = true; break;
+    case OpImageQueryOrder: *hasResult = true; *hasResultType = true; break;
+    case OpImageQuerySizeLod: *hasResult = true; *hasResultType = true; break;
+    case OpImageQuerySize: *hasResult = true; *hasResultType = true; break;
+    case OpImageQueryLod: *hasResult = true; *hasResultType = true; break;
+    case OpImageQueryLevels: *hasResult = true; *hasResultType = true; break;
+    case OpImageQuerySamples: *hasResult = true; *hasResultType = true; break;
+    case OpConvertFToU: *hasResult = true; *hasResultType = true; break;
+    case OpConvertFToS: *hasResult = true; *hasResultType = true; break;
+    case OpConvertSToF: *hasResult = true; *hasResultType = true; break;
+    case OpConvertUToF: *hasResult = true; *hasResultType = true; break;
+    case OpUConvert: *hasResult = true; *hasResultType = true; break;
+    case OpSConvert: *hasResult = true; *hasResultType = true; break;
+    case OpFConvert: *hasResult = true; *hasResultType = true; break;
+    case OpQuantizeToF16: *hasResult = true; *hasResultType = true; break;
+    case OpConvertPtrToU: *hasResult = true; *hasResultType = true; break;
+    case OpSatConvertSToU: *hasResult = true; *hasResultType = true; break;
+    case OpSatConvertUToS: *hasResult = true; *hasResultType = true; break;
+    case OpConvertUToPtr: *hasResult = true; *hasResultType = true; break;
+    case OpPtrCastToGeneric: *hasResult = true; *hasResultType = true; break;
+    case OpGenericCastToPtr: *hasResult = true; *hasResultType = true; break;
+    case OpGenericCastToPtrExplicit: *hasResult = true; *hasResultType = true; break;
+    case OpBitcast: *hasResult = true; *hasResultType = true; break;
+    case OpSNegate: *hasResult = true; *hasResultType = true; break;
+    case OpFNegate: *hasResult = true; *hasResultType = true; break;
+    case OpIAdd: *hasResult = true; *hasResultType = true; break;
+    case OpFAdd: *hasResult = true; *hasResultType = true; break;
+    case OpISub: *hasResult = true; *hasResultType = true; break;
+    case OpFSub: *hasResult = true; *hasResultType = true; break;
+    case OpIMul: *hasResult = true; *hasResultType = true; break;
+    case OpFMul: *hasResult = true; *hasResultType = true; break;
+    case OpUDiv: *hasResult = true; *hasResultType = true; break;
+    case OpSDiv: *hasResult = true; *hasResultType = true; break;
+    case OpFDiv: *hasResult = true; *hasResultType = true; break;
+    case OpUMod: *hasResult = true; *hasResultType = true; break;
+    case OpSRem: *hasResult = true; *hasResultType = true; break;
+    case OpSMod: *hasResult = true; *hasResultType = true; break;
+    case OpFRem: *hasResult = true; *hasResultType = true; break;
+    case OpFMod: *hasResult = true; *hasResultType = true; break;
+    case OpVectorTimesScalar: *hasResult = true; *hasResultType = true; break;
+    case OpMatrixTimesScalar: *hasResult = true; *hasResultType = true; break;
+    case OpVectorTimesMatrix: *hasResult = true; *hasResultType = true; break;
+    case OpMatrixTimesVector: *hasResult = true; *hasResultType = true; break;
+    case OpMatrixTimesMatrix: *hasResult = true; *hasResultType = true; break;
+    case OpOuterProduct: *hasResult = true; *hasResultType = true; break;
+    case OpDot: *hasResult = true; *hasResultType = true; break;
+    case OpIAddCarry: *hasResult = true; *hasResultType = true; break;
+    case OpISubBorrow: *hasResult = true; *hasResultType = true; break;
+    case OpUMulExtended: *hasResult = true; *hasResultType = true; break;
+    case OpSMulExtended: *hasResult = true; *hasResultType = true; break;
+    case OpAny: *hasResult = true; *hasResultType = true; break;
+    case OpAll: *hasResult = true; *hasResultType = true; break;
+    case OpIsNan: *hasResult = true; *hasResultType = true; break;
+    case OpIsInf: *hasResult = true; *hasResultType = true; break;
+    case OpIsFinite: *hasResult = true; *hasResultType = true; break;
+    case OpIsNormal: *hasResult = true; *hasResultType = true; break;
+    case OpSignBitSet: *hasResult = true; *hasResultType = true; break;
+    case OpLessOrGreater: *hasResult = true; *hasResultType = true; break;
+    case OpOrdered: *hasResult = true; *hasResultType = true; break;
+    case OpUnordered: *hasResult = true; *hasResultType = true; break;
+    case OpLogicalEqual: *hasResult = true; *hasResultType = true; break;
+    case OpLogicalNotEqual: *hasResult = true; *hasResultType = true; break;
+    case OpLogicalOr: *hasResult = true; *hasResultType = true; break;
+    case OpLogicalAnd: *hasResult = true; *hasResultType = true; break;
+    case OpLogicalNot: *hasResult = true; *hasResultType = true; break;
+    case OpSelect: *hasResult = true; *hasResultType = true; break;
+    case OpIEqual: *hasResult = true; *hasResultType = true; break;
+    case OpINotEqual: *hasResult = true; *hasResultType = true; break;
+    case OpUGreaterThan: *hasResult = true; *hasResultType = true; break;
+    case OpSGreaterThan: *hasResult = true; *hasResultType = true; break;
+    case OpUGreaterThanEqual: *hasResult = true; *hasResultType = true; break;
+    case OpSGreaterThanEqual: *hasResult = true; *hasResultType = true; break;
+    case OpULessThan: *hasResult = true; *hasResultType = true; break;
+    case OpSLessThan: *hasResult = true; *hasResultType = true; break;
+    case OpULessThanEqual: *hasResult = true; *hasResultType = true; break;
+    case OpSLessThanEqual: *hasResult = true; *hasResultType = true; break;
+    case OpFOrdEqual: *hasResult = true; *hasResultType = true; break;
+    case OpFUnordEqual: *hasResult = true; *hasResultType = true; break;
+    case OpFOrdNotEqual: *hasResult = true; *hasResultType = true; break;
+    case OpFUnordNotEqual: *hasResult = true; *hasResultType = true; break;
+    case OpFOrdLessThan: *hasResult = true; *hasResultType = true; break;
+    case OpFUnordLessThan: *hasResult = true; *hasResultType = true; break;
+    case OpFOrdGreaterThan: *hasResult = true; *hasResultType = true; break;
+    case OpFUnordGreaterThan: *hasResult = true; *hasResultType = true; break;
+    case OpFOrdLessThanEqual: *hasResult = true; *hasResultType = true; break;
+    case OpFUnordLessThanEqual: *hasResult = true; *hasResultType = true; break;
+    case OpFOrdGreaterThanEqual: *hasResult = true; *hasResultType = true; break;
+    case OpFUnordGreaterThanEqual: *hasResult = true; *hasResultType = true; break;
+    case OpShiftRightLogical: *hasResult = true; *hasResultType = true; break;
+    case OpShiftRightArithmetic: *hasResult = true; *hasResultType = true; break;
+    case OpShiftLeftLogical: *hasResult = true; *hasResultType = true; break;
+    case OpBitwiseOr: *hasResult = true; *hasResultType = true; break;
+    case OpBitwiseXor: *hasResult = true; *hasResultType = true; break;
+    case OpBitwiseAnd: *hasResult = true; *hasResultType = true; break;
+    case OpNot: *hasResult = true; *hasResultType = true; break;
+    case OpBitFieldInsert: *hasResult = true; *hasResultType = true; break;
+    case OpBitFieldSExtract: *hasResult = true; *hasResultType = true; break;
+    case OpBitFieldUExtract: *hasResult = true; *hasResultType = true; break;
+    case OpBitReverse: *hasResult = true; *hasResultType = true; break;
+    case OpBitCount: *hasResult = true; *hasResultType = true; break;
+    case OpDPdx: *hasResult = true; *hasResultType = true; break;
+    case OpDPdy: *hasResult = true; *hasResultType = true; break;
+    case OpFwidth: *hasResult = true; *hasResultType = true; break;
+    case OpDPdxFine: *hasResult = true; *hasResultType = true; break;
+    case OpDPdyFine: *hasResult = true; *hasResultType = true; break;
+    case OpFwidthFine: *hasResult = true; *hasResultType = true; break;
+    case OpDPdxCoarse: *hasResult = true; *hasResultType = true; break;
+    case OpDPdyCoarse: *hasResult = true; *hasResultType = true; break;
+    case OpFwidthCoarse: *hasResult = true; *hasResultType = true; break;
+    case OpEmitVertex: *hasResult = false; *hasResultType = false; break;
+    case OpEndPrimitive: *hasResult = false; *hasResultType = false; break;
+    case OpEmitStreamVertex: *hasResult = false; *hasResultType = false; break;
+    case OpEndStreamPrimitive: *hasResult = false; *hasResultType = false; break;
+    case OpControlBarrier: *hasResult = false; *hasResultType = false; break;
+    case OpMemoryBarrier: *hasResult = false; *hasResultType = false; break;
+    case OpAtomicLoad: *hasResult = true; *hasResultType = true; break;
+    case OpAtomicStore: *hasResult = false; *hasResultType = false; break;
+    case OpAtomicExchange: *hasResult = true; *hasResultType = true; break;
+    case OpAtomicCompareExchange: *hasResult = true; *hasResultType = true; break;
+    case OpAtomicCompareExchangeWeak: *hasResult = true; *hasResultType = true; break;
+    case OpAtomicIIncrement: *hasResult = true; *hasResultType = true; break;
+    case OpAtomicIDecrement: *hasResult = true; *hasResultType = true; break;
+    case OpAtomicIAdd: *hasResult = true; *hasResultType = true; break;
+    case OpAtomicISub: *hasResult = true; *hasResultType = true; break;
+    case OpAtomicSMin: *hasResult = true; *hasResultType = true; break;
+    case OpAtomicUMin: *hasResult = true; *hasResultType = true; break;
+    case OpAtomicSMax: *hasResult = true; *hasResultType = true; break;
+    case OpAtomicUMax: *hasResult = true; *hasResultType = true; break;
+    case OpAtomicAnd: *hasResult = true; *hasResultType = true; break;
+    case OpAtomicOr: *hasResult = true; *hasResultType = true; break;
+    case OpAtomicXor: *hasResult = true; *hasResultType = true; break;
+    case OpPhi: *hasResult = true; *hasResultType = true; break;
+    case OpLoopMerge: *hasResult = false; *hasResultType = false; break;
+    case OpSelectionMerge: *hasResult = false; *hasResultType = false; break;
+    case OpLabel: *hasResult = true; *hasResultType = false; break;
+    case OpBranch: *hasResult = false; *hasResultType = false; break;
+    case OpBranchConditional: *hasResult = false; *hasResultType = false; break;
+    case OpSwitch: *hasResult = false; *hasResultType = false; break;
+    case OpKill: *hasResult = false; *hasResultType = false; break;
+    case OpReturn: *hasResult = false; *hasResultType = false; break;
+    case OpReturnValue: *hasResult = false; *hasResultType = false; break;
+    case OpUnreachable: *hasResult = false; *hasResultType = false; break;
+    case OpLifetimeStart: *hasResult = false; *hasResultType = false; break;
+    case OpLifetimeStop: *hasResult = false; *hasResultType = false; break;
+    case OpGroupAsyncCopy: *hasResult = true; *hasResultType = true; break;
+    case OpGroupWaitEvents: *hasResult = false; *hasResultType = false; break;
+    case OpGroupAll: *hasResult = true; *hasResultType = true; break;
+    case OpGroupAny: *hasResult = true; *hasResultType = true; break;
+    case OpGroupBroadcast: *hasResult = true; *hasResultType = true; break;
+    case OpGroupIAdd: *hasResult = true; *hasResultType = true; break;
+    case OpGroupFAdd: *hasResult = true; *hasResultType = true; break;
+    case OpGroupFMin: *hasResult = true; *hasResultType = true; break;
+    case OpGroupUMin: *hasResult = true; *hasResultType = true; break;
+    case OpGroupSMin: *hasResult = true; *hasResultType = true; break;
+    case OpGroupFMax: *hasResult = true; *hasResultType = true; break;
+    case OpGroupUMax: *hasResult = true; *hasResultType = true; break;
+    case OpGroupSMax: *hasResult = true; *hasResultType = true; break;
+    case OpReadPipe: *hasResult = true; *hasResultType = true; break;
+    case OpWritePipe: *hasResult = true; *hasResultType = true; break;
+    case OpReservedReadPipe: *hasResult = true; *hasResultType = true; break;
+    case OpReservedWritePipe: *hasResult = true; *hasResultType = true; break;
+    case OpReserveReadPipePackets: *hasResult = true; *hasResultType = true; break;
+    case OpReserveWritePipePackets: *hasResult = true; *hasResultType = true; break;
+    case OpCommitReadPipe: *hasResult = false; *hasResultType = false; break;
+    case OpCommitWritePipe: *hasResult = false; *hasResultType = false; break;
+    case OpIsValidReserveId: *hasResult = true; *hasResultType = true; break;
+    case OpGetNumPipePackets: *hasResult = true; *hasResultType = true; break;
+    case OpGetMaxPipePackets: *hasResult = true; *hasResultType = true; break;
+    case OpGroupReserveReadPipePackets: *hasResult = true; *hasResultType = true; break;
+    case OpGroupReserveWritePipePackets: *hasResult = true; *hasResultType = true; break;
+    case OpGroupCommitReadPipe: *hasResult = false; *hasResultType = false; break;
+    case OpGroupCommitWritePipe: *hasResult = false; *hasResultType = false; break;
+    case OpEnqueueMarker: *hasResult = true; *hasResultType = true; break;
+    case OpEnqueueKernel: *hasResult = true; *hasResultType = true; break;
+    case OpGetKernelNDrangeSubGroupCount: *hasResult = true; *hasResultType = true; break;
+    case OpGetKernelNDrangeMaxSubGroupSize: *hasResult = true; *hasResultType = true; break;
+    case OpGetKernelWorkGroupSize: *hasResult = true; *hasResultType = true; break;
+    case OpGetKernelPreferredWorkGroupSizeMultiple: *hasResult = true; *hasResultType = true; break;
+    case OpRetainEvent: *hasResult = false; *hasResultType = false; break;
+    case OpReleaseEvent: *hasResult = false; *hasResultType = false; break;
+    case OpCreateUserEvent: *hasResult = true; *hasResultType = true; break;
+    case OpIsValidEvent: *hasResult = true; *hasResultType = true; break;
+    case OpSetUserEventStatus: *hasResult = false; *hasResultType = false; break;
+    case OpCaptureEventProfilingInfo: *hasResult = false; *hasResultType = false; break;
+    case OpGetDefaultQueue: *hasResult = true; *hasResultType = true; break;
+    case OpBuildNDRange: *hasResult = true; *hasResultType = true; break;
+    case OpImageSparseSampleImplicitLod: *hasResult = true; *hasResultType = true; break;
+    case OpImageSparseSampleExplicitLod: *hasResult = true; *hasResultType = true; break;
+    case OpImageSparseSampleDrefImplicitLod: *hasResult = true; *hasResultType = true; break;
+    case OpImageSparseSampleDrefExplicitLod: *hasResult = true; *hasResultType = true; break;
+    case OpImageSparseSampleProjImplicitLod: *hasResult = true; *hasResultType = true; break;
+    case OpImageSparseSampleProjExplicitLod: *hasResult = true; *hasResultType = true; break;
+    case OpImageSparseSampleProjDrefImplicitLod: *hasResult = true; *hasResultType = true; break;
+    case OpImageSparseSampleProjDrefExplicitLod: *hasResult = true; *hasResultType = true; break;
+    case OpImageSparseFetch: *hasResult = true; *hasResultType = true; break;
+    case OpImageSparseGather: *hasResult = true; *hasResultType = true; break;
+    case OpImageSparseDrefGather: *hasResult = true; *hasResultType = true; break;
+    case OpImageSparseTexelsResident: *hasResult = true; *hasResultType = true; break;
+    case OpNoLine: *hasResult = false; *hasResultType = false; break;
+    case OpAtomicFlagTestAndSet: *hasResult = true; *hasResultType = true; break;
+    case OpAtomicFlagClear: *hasResult = false; *hasResultType = false; break;
+    case OpImageSparseRead: *hasResult = true; *hasResultType = true; break;
+    case OpSizeOf: *hasResult = true; *hasResultType = true; break;
+    case OpTypePipeStorage: *hasResult = true; *hasResultType = false; break;
+    case OpConstantPipeStorage: *hasResult = true; *hasResultType = true; break;
+    case OpCreatePipeFromPipeStorage: *hasResult = true; *hasResultType = true; break;
+    case OpGetKernelLocalSizeForSubgroupCount: *hasResult = true; *hasResultType = true; break;
+    case OpGetKernelMaxNumSubgroups: *hasResult = true; *hasResultType = true; break;
+    case OpTypeNamedBarrier: *hasResult = true; *hasResultType = false; break;
+    case OpNamedBarrierInitialize: *hasResult = true; *hasResultType = true; break;
+    case OpMemoryNamedBarrier: *hasResult = false; *hasResultType = false; break;
+    case OpModuleProcessed: *hasResult = false; *hasResultType = false; break;
+    case OpExecutionModeId: *hasResult = false; *hasResultType = false; break;
+    case OpDecorateId: *hasResult = false; *hasResultType = false; break;
+    case OpGroupNonUniformElect: *hasResult = true; *hasResultType = true; break;
+    case OpGroupNonUniformAll: *hasResult = true; *hasResultType = true; break;
+    case OpGroupNonUniformAny: *hasResult = true; *hasResultType = true; break;
+    case OpGroupNonUniformAllEqual: *hasResult = true; *hasResultType = true; break;
+    case OpGroupNonUniformBroadcast: *hasResult = true; *hasResultType = true; break;
+    case OpGroupNonUniformBroadcastFirst: *hasResult = true; *hasResultType = true; break;
+    case OpGroupNonUniformBallot: *hasResult = true; *hasResultType = true; break;
+    case OpGroupNonUniformInverseBallot: *hasResult = true; *hasResultType = true; break;
+    case OpGroupNonUniformBallotBitExtract: *hasResult = true; *hasResultType = true; break;
+    case OpGroupNonUniformBallotBitCount: *hasResult = true; *hasResultType = true; break;
+    case OpGroupNonUniformBallotFindLSB: *hasResult = true; *hasResultType = true; break;
+    case OpGroupNonUniformBallotFindMSB: *hasResult = true; *hasResultType = true; break;
+    case OpGroupNonUniformShuffle: *hasResult = true; *hasResultType = true; break;
+    case OpGroupNonUniformShuffleXor: *hasResult = true; *hasResultType = true; break;
+    case OpGroupNonUniformShuffleUp: *hasResult = true; *hasResultType = true; break;
+    case OpGroupNonUniformShuffleDown: *hasResult = true; *hasResultType = true; break;
+    case OpGroupNonUniformIAdd: *hasResult = true; *hasResultType = true; break;
+    case OpGroupNonUniformFAdd: *hasResult = true; *hasResultType = true; break;
+    case OpGroupNonUniformIMul: *hasResult = true; *hasResultType = true; break;
+    case OpGroupNonUniformFMul: *hasResult = true; *hasResultType = true; break;
+    case OpGroupNonUniformSMin: *hasResult = true; *hasResultType = true; break;
+    case OpGroupNonUniformUMin: *hasResult = true; *hasResultType = true; break;
+    case OpGroupNonUniformFMin: *hasResult = true; *hasResultType = true; break;
+    case OpGroupNonUniformSMax: *hasResult = true; *hasResultType = true; break;
+    case OpGroupNonUniformUMax: *hasResult = true; *hasResultType = true; break;
+    case OpGroupNonUniformFMax: *hasResult = true; *hasResultType = true; break;
+    case OpGroupNonUniformBitwiseAnd: *hasResult = true; *hasResultType = true; break;
+    case OpGroupNonUniformBitwiseOr: *hasResult = true; *hasResultType = true; break;
+    case OpGroupNonUniformBitwiseXor: *hasResult = true; *hasResultType = true; break;
+    case OpGroupNonUniformLogicalAnd: *hasResult = true; *hasResultType = true; break;
+    case OpGroupNonUniformLogicalOr: *hasResult = true; *hasResultType = true; break;
+    case OpGroupNonUniformLogicalXor: *hasResult = true; *hasResultType = true; break;
+    case OpGroupNonUniformQuadBroadcast: *hasResult = true; *hasResultType = true; break;
+    case OpGroupNonUniformQuadSwap: *hasResult = true; *hasResultType = true; break;
+    case OpCopyLogical: *hasResult = true; *hasResultType = true; break;
+    case OpPtrEqual: *hasResult = true; *hasResultType = true; break;
+    case OpPtrNotEqual: *hasResult = true; *hasResultType = true; break;
+    case OpPtrDiff: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupBallotKHR: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupFirstInvocationKHR: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAllKHR: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAnyKHR: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAllEqualKHR: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupReadInvocationKHR: *hasResult = true; *hasResultType = true; break;
+    case OpTypeRayQueryProvisionalKHR: *hasResult = true; *hasResultType = false; break;
+    case OpRayQueryInitializeKHR: *hasResult = false; *hasResultType = false; break;
+    case OpRayQueryTerminateKHR: *hasResult = false; *hasResultType = false; break;
+    case OpRayQueryGenerateIntersectionKHR: *hasResult = false; *hasResultType = false; break;
+    case OpRayQueryConfirmIntersectionKHR: *hasResult = false; *hasResultType = false; break;
+    case OpRayQueryProceedKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetIntersectionTypeKHR: *hasResult = true; *hasResultType = true; break;
+    case OpGroupIAddNonUniformAMD: *hasResult = true; *hasResultType = true; break;
+    case OpGroupFAddNonUniformAMD: *hasResult = true; *hasResultType = true; break;
+    case OpGroupFMinNonUniformAMD: *hasResult = true; *hasResultType = true; break;
+    case OpGroupUMinNonUniformAMD: *hasResult = true; *hasResultType = true; break;
+    case OpGroupSMinNonUniformAMD: *hasResult = true; *hasResultType = true; break;
+    case OpGroupFMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break;
+    case OpGroupUMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break;
+    case OpGroupSMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break;
+    case OpFragmentMaskFetchAMD: *hasResult = true; *hasResultType = true; break;
+    case OpFragmentFetchAMD: *hasResult = true; *hasResultType = true; break;
+    case OpReadClockKHR: *hasResult = true; *hasResultType = true; break;
+    case OpImageSampleFootprintNV: *hasResult = true; *hasResultType = true; break;
+    case OpGroupNonUniformPartitionNV: *hasResult = true; *hasResultType = true; break;
+    case OpWritePackedPrimitiveIndices4x8NV: *hasResult = false; *hasResultType = false; break;
+    case OpReportIntersectionNV: *hasResult = true; *hasResultType = true; break;
+    case OpIgnoreIntersectionNV: *hasResult = false; *hasResultType = false; break;
+    case OpTerminateRayNV: *hasResult = false; *hasResultType = false; break;
+    case OpTraceNV: *hasResult = false; *hasResultType = false; break;
+    case OpTypeAccelerationStructureNV: *hasResult = true; *hasResultType = false; break;
+    case OpExecuteCallableNV: *hasResult = false; *hasResultType = false; break;
+    case OpTypeCooperativeMatrixNV: *hasResult = true; *hasResultType = false; break;
+    case OpCooperativeMatrixLoadNV: *hasResult = true; *hasResultType = true; break;
+    case OpCooperativeMatrixStoreNV: *hasResult = false; *hasResultType = false; break;
+    case OpCooperativeMatrixMulAddNV: *hasResult = true; *hasResultType = true; break;
+    case OpCooperativeMatrixLengthNV: *hasResult = true; *hasResultType = true; break;
+    case OpBeginInvocationInterlockEXT: *hasResult = false; *hasResultType = false; break;
+    case OpEndInvocationInterlockEXT: *hasResult = false; *hasResultType = false; break;
+    case OpDemoteToHelperInvocationEXT: *hasResult = false; *hasResultType = false; break;
+    case OpIsHelperInvocationEXT: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupShuffleINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupShuffleDownINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupShuffleUpINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupShuffleXorINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupBlockReadINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupBlockWriteINTEL: *hasResult = false; *hasResultType = false; break;
+    case OpSubgroupImageBlockReadINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupImageBlockWriteINTEL: *hasResult = false; *hasResultType = false; break;
+    case OpSubgroupImageMediaBlockReadINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupImageMediaBlockWriteINTEL: *hasResult = false; *hasResultType = false; break;
+    case OpUCountLeadingZerosINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpUCountTrailingZerosINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpAbsISubINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpAbsUSubINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpIAddSatINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpUAddSatINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpIAverageINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpUAverageINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpIAverageRoundedINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpUAverageRoundedINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpISubSatINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpUSubSatINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpIMul32x16INTEL: *hasResult = true; *hasResultType = true; break;
+    case OpUMul32x16INTEL: *hasResult = true; *hasResultType = true; break;
+    case OpDecorateString: *hasResult = false; *hasResultType = false; break;
+    case OpMemberDecorateString: *hasResult = false; *hasResultType = false; break;
+    case OpVmeImageINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpTypeVmeImageINTEL: *hasResult = true; *hasResultType = false; break;
+    case OpTypeAvcImePayloadINTEL: *hasResult = true; *hasResultType = false; break;
+    case OpTypeAvcRefPayloadINTEL: *hasResult = true; *hasResultType = false; break;
+    case OpTypeAvcSicPayloadINTEL: *hasResult = true; *hasResultType = false; break;
+    case OpTypeAvcMcePayloadINTEL: *hasResult = true; *hasResultType = false; break;
+    case OpTypeAvcMceResultINTEL: *hasResult = true; *hasResultType = false; break;
+    case OpTypeAvcImeResultINTEL: *hasResult = true; *hasResultType = false; break;
+    case OpTypeAvcImeResultSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = false; break;
+    case OpTypeAvcImeResultDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = false; break;
+    case OpTypeAvcImeSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = false; break;
+    case OpTypeAvcImeDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = false; break;
+    case OpTypeAvcRefResultINTEL: *hasResult = true; *hasResultType = false; break;
+    case OpTypeAvcSicResultINTEL: *hasResult = true; *hasResultType = false; break;
+    case OpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcMceSetInterShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcMceSetInterDirectionPenaltyINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcMceSetMotionVectorCostFunctionINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcMceSetAcOnlyHaarINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcMceConvertToImePayloadINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcMceConvertToImeResultINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcMceConvertToRefPayloadINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcMceConvertToRefResultINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcMceConvertToSicPayloadINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcMceConvertToSicResultINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcMceGetMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcMceGetInterDistortionsINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcMceGetBestInterDistortionsINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcMceGetInterMajorShapeINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcMceGetInterMinorShapeINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcMceGetInterDirectionsINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcMceGetInterMotionVectorCountINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcMceGetInterReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcImeInitializeINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcImeSetSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcImeSetDualReferenceINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcImeRefWindowSizeINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcImeAdjustRefOffsetINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcImeConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcImeSetMaxMotionVectorCountINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcImeSetUnidirectionalMixDisableINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcImeSetWeightedSadINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcImeEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcImeEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcImeConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcImeGetSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcImeGetDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcImeStripSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcImeStripDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcImeGetBorderReachedINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcImeGetTruncatedSearchIndicationINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcFmeInitializeINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcBmeInitializeINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcRefConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcRefSetBidirectionalMixDisableINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcRefSetBilinearFilterEnableINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcRefEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcRefEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcRefEvaluateWithMultiReferenceINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcRefConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcSicInitializeINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcSicConfigureSkcINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcSicConfigureIpeLumaINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcSicConfigureIpeLumaChromaINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcSicGetMotionVectorMaskINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcSicConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcSicSetBilinearFilterEnableINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcSicSetSkcForwardTransformEnableINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcSicEvaluateIpeINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcSicEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcSicEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcSicEvaluateWithMultiReferenceINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcSicConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcSicGetIpeLumaShapeINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcSicGetBestIpeLumaDistortionINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcSicGetBestIpeChromaDistortionINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcSicGetPackedIpeLumaModesINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcSicGetIpeChromaModeINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpSubgroupAvcSicGetInterRawSadsINTEL: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetRayTMinKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetRayFlagsKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetIntersectionTKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetIntersectionInstanceCustomIndexKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetIntersectionInstanceIdKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetIntersectionGeometryIndexKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetIntersectionPrimitiveIndexKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetIntersectionBarycentricsKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetIntersectionFrontFaceKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetIntersectionCandidateAABBOpaqueKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetIntersectionObjectRayDirectionKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetIntersectionObjectRayOriginKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetWorldRayDirectionKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetWorldRayOriginKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetIntersectionObjectToWorldKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetIntersectionWorldToObjectKHR: *hasResult = true; *hasResultType = true; break;
+    }
+}
+#endif /* SPV_ENABLE_UTILITY_CODE */
+
 // Overload operator| for mask bit combining
 
 inline ImageOperandsMask operator|(ImageOperandsMask a, ImageOperandsMask b) { return ImageOperandsMask(unsigned(a) | unsigned(b)); }
@@ -1336,6 +2106,7 @@
 inline MemorySemanticsMask operator|(MemorySemanticsMask a, MemorySemanticsMask b) { return MemorySemanticsMask(unsigned(a) | unsigned(b)); }
 inline MemoryAccessMask operator|(MemoryAccessMask a, MemoryAccessMask b) { return MemoryAccessMask(unsigned(a) | unsigned(b)); }
 inline KernelProfilingInfoMask operator|(KernelProfilingInfoMask a, KernelProfilingInfoMask b) { return KernelProfilingInfoMask(unsigned(a) | unsigned(b)); }
+inline RayFlagsMask operator|(RayFlagsMask a, RayFlagsMask b) { return RayFlagsMask(unsigned(a) | unsigned(b)); }
 
 }  // end namespace spv
 
diff --git a/SPIRV/spvIR.h b/SPIRV/spvIR.h
index b3cd0b0..6523035 100755
--- a/SPIRV/spvIR.h
+++ b/SPIRV/spvIR.h
@@ -226,6 +226,35 @@
         return nullptr;
     }
 
+    // Change this block into a canonical dead merge block.  Delete instructions
+    // as necessary.  A canonical dead merge block has only an OpLabel and an
+    // OpUnreachable.
+    void rewriteAsCanonicalUnreachableMerge() {
+        assert(localVariables.empty());
+        // Delete all instructions except for the label.
+        assert(instructions.size() > 0);
+        instructions.resize(1);
+        successors.clear();
+        addInstruction(std::unique_ptr<Instruction>(new Instruction(OpUnreachable)));
+    }
+    // Change this block into a canonical dead continue target branching to the
+    // given header ID.  Delete instructions as necessary.  A canonical dead continue
+    // target has only an OpLabel and an unconditional branch back to the corresponding
+    // header.
+    void rewriteAsCanonicalUnreachableContinue(Block* header) {
+        assert(localVariables.empty());
+        // Delete all instructions except for the label.
+        assert(instructions.size() > 0);
+        instructions.resize(1);
+        successors.clear();
+        // Add OpBranch back to the header.
+        assert(header != nullptr);
+        Instruction* branch = new Instruction(OpBranch);
+        branch->addIdOperand(header->getId());
+        addInstruction(std::unique_ptr<Instruction>(branch));
+        successors.push_back(header);
+    }
+
     bool isTerminated() const
     {
         switch (instructions.back()->getOpCode()) {
@@ -235,6 +264,7 @@
         case OpKill:
         case OpReturn:
         case OpReturnValue:
+        case OpUnreachable:
             return true;
         default:
             return false;
@@ -268,10 +298,24 @@
     bool unreachable;
 };
 
+// The different reasons for reaching a block in the inReadableOrder traversal.
+enum ReachReason {
+    // Reachable from the entry block via transfers of control, i.e. branches.
+    ReachViaControlFlow = 0,
+    // A continue target that is not reachable via control flow.
+    ReachDeadContinue,
+    // A merge block that is not reachable via control flow.
+    ReachDeadMerge
+};
+
 // Traverses the control-flow graph rooted at root in an order suited for
 // readable code generation.  Invokes callback at every node in the traversal
-// order.
-void inReadableOrder(Block* root, std::function<void(Block*)> callback);
+// order.  The callback arguments are:
+// - the block,
+// - the reason we reached the block,
+// - if the reason was that block is an unreachable continue or unreachable merge block
+//   then the last parameter is the corresponding header block.
+void inReadableOrder(Block* root, std::function<void(Block*, ReachReason, Block* header)> callback);
 
 //
 // SPIR-V IR Function.
@@ -321,7 +365,7 @@
             parameterInstructions[p]->dump(out);
 
         // Blocks
-        inReadableOrder(blocks[0], [&out](const Block* b) { b->dump(out); });
+        inReadableOrder(blocks[0], [&out](const Block* b, ReachReason, Block*) { b->dump(out); });
         Instruction end(0, 0, OpFunctionEnd);
         end.dump(out);
     }
@@ -436,6 +480,6 @@
         parent.getParent().mapInstruction(raw_instruction);
 }
 
-};  // end spv namespace
+}  // end spv namespace
 
 #endif // spvIR_H
diff --git a/StandAlone/CMakeLists.txt b/StandAlone/CMakeLists.txt
index 5cea53d..591ac34 100644
--- a/StandAlone/CMakeLists.txt
+++ b/StandAlone/CMakeLists.txt
@@ -1,28 +1,29 @@
 add_library(glslang-default-resource-limits
-            ${CMAKE_CURRENT_SOURCE_DIR}/ResourceLimits.cpp)
+            ${CMAKE_CURRENT_SOURCE_DIR}/ResourceLimits.cpp
+            ${CMAKE_CURRENT_SOURCE_DIR}/resource_limits_c.cpp)
 set_property(TARGET glslang-default-resource-limits PROPERTY FOLDER glslang)
 set_property(TARGET glslang-default-resource-limits PROPERTY POSITION_INDEPENDENT_CODE ON)
 
 target_include_directories(glslang-default-resource-limits
-                           PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}
-                           PUBLIC ${PROJECT_SOURCE_DIR})
+                           PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
+                           PUBLIC $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>)
+
 
 set(SOURCES StandAlone.cpp DirStackFileIncluder.h)
-set(REMAPPER_SOURCES spirv-remap.cpp)
 
 add_executable(glslangValidator ${SOURCES})
-add_executable(spirv-remap ${REMAPPER_SOURCES})
 set_property(TARGET glslangValidator PROPERTY FOLDER tools)
-set_property(TARGET spirv-remap PROPERTY FOLDER tools)
 glslang_set_link_args(glslangValidator)
-glslang_set_link_args(spirv-remap)
 
 set(LIBRARIES
     glslang
     SPIRV
-    SPVRemapper
     glslang-default-resource-limits)
 
+if(ENABLE_SPVREMAPPER)
+    set(LIBRARIES ${LIBRARIES} SPVRemapper)
+endif()
+
 if(WIN32)
     set(LIBRARIES ${LIBRARIES} psapi)
 elseif(UNIX)
@@ -32,22 +33,36 @@
 endif(WIN32)
 
 target_link_libraries(glslangValidator ${LIBRARIES})
-target_link_libraries(spirv-remap ${LIBRARIES})
-target_include_directories(glslangValidator PUBLIC ../External)
+target_include_directories(glslangValidator PUBLIC
+    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../External>
+    $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/External>)
+
+if(ENABLE_SPVREMAPPER)
+    set(REMAPPER_SOURCES spirv-remap.cpp)
+    add_executable(spirv-remap ${REMAPPER_SOURCES})
+    set_property(TARGET spirv-remap PROPERTY FOLDER tools)
+    glslang_set_link_args(spirv-remap)
+    target_link_libraries(spirv-remap ${LIBRARIES})
+endif()
 
 if(WIN32)
     source_group("Source" FILES ${SOURCES})
 endif(WIN32)
 
 if(ENABLE_GLSLANG_INSTALL)
-    install(TARGETS glslangValidator
+    install(TARGETS glslangValidator EXPORT glslangValidatorTargets
             RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
+    install(EXPORT glslangValidatorTargets DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake)
 
-    install(TARGETS spirv-remap
+    if(ENABLE_SPVREMAPPER)
+        install(TARGETS spirv-remap EXPORT spirv-remapTargets
             RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
-            
+        install(EXPORT spirv-remapTargets DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake)
+    endif()
+
     if(BUILD_SHARED_LIBS)
-        install(TARGETS glslang-default-resource-limits
+        install(TARGETS glslang-default-resource-limits EXPORT glslang-default-resource-limitsTargets
                 LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
+        install(EXPORT glslang-default-resource-limitsTargets DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake)
     endif()
 endif(ENABLE_GLSLANG_INSTALL)
diff --git a/StandAlone/ResourceLimits.cpp b/StandAlone/ResourceLimits.cpp
index 66e79af..7c7f4c4 100644
--- a/StandAlone/ResourceLimits.cpp
+++ b/StandAlone/ResourceLimits.cpp
@@ -134,6 +134,7 @@
     /* .maxTaskWorkGroupSizeY_NV = */ 1,
     /* .maxTaskWorkGroupSizeZ_NV = */ 1,
     /* .maxMeshViewCountNV = */ 4,
+    /* .maxDualSourceDrawBuffersEXT = */ 1,
 
     /* .limits = */ {
         /* .nonInductiveForLoops = */ 1,
@@ -234,7 +235,6 @@
             << "MaxCullDistances "                          << DefaultTBuiltInResource.maxCullDistances << "\n"
             << "MaxCombinedClipAndCullDistances "           << DefaultTBuiltInResource.maxCombinedClipAndCullDistances << "\n"
             << "MaxSamples "                                << DefaultTBuiltInResource.maxSamples << "\n"
-#ifdef NV_EXTENSIONS
             << "MaxMeshOutputVerticesNV "                   << DefaultTBuiltInResource.maxMeshOutputVerticesNV << "\n"
             << "MaxMeshOutputPrimitivesNV "                 << DefaultTBuiltInResource.maxMeshOutputPrimitivesNV << "\n"
             << "MaxMeshWorkGroupSizeX_NV "                  << DefaultTBuiltInResource.maxMeshWorkGroupSizeX_NV << "\n"
@@ -244,7 +244,7 @@
             << "MaxTaskWorkGroupSizeY_NV "                  << DefaultTBuiltInResource.maxTaskWorkGroupSizeY_NV << "\n"
             << "MaxTaskWorkGroupSizeZ_NV "                  << DefaultTBuiltInResource.maxTaskWorkGroupSizeZ_NV << "\n"
             << "MaxMeshViewCountNV "                        << DefaultTBuiltInResource.maxMeshViewCountNV << "\n"
-#endif
+            << "MaxDualSourceDrawBuffersEXT "               << DefaultTBuiltInResource.maxDualSourceDrawBuffersEXT << "\n"
             << "nonInductiveForLoops "                      << DefaultTBuiltInResource.limits.nonInductiveForLoops << "\n"
             << "whileLoops "                                << DefaultTBuiltInResource.limits.whileLoops << "\n"
             << "doWhileLoops "                              << DefaultTBuiltInResource.limits.doWhileLoops << "\n"
@@ -451,7 +451,6 @@
             resources->maxCombinedClipAndCullDistances = value;
         else if (tokenStr == "MaxSamples")
             resources->maxSamples = value;
-#ifdef NV_EXTENSIONS
         else if (tokenStr == "MaxMeshOutputVerticesNV")
             resources->maxMeshOutputVerticesNV = value;
         else if (tokenStr == "MaxMeshOutputPrimitivesNV")
@@ -470,7 +469,6 @@
             resources->maxTaskWorkGroupSizeZ_NV = value;
         else if (tokenStr == "MaxMeshViewCountNV")
             resources->maxMeshViewCountNV = value;
-#endif
         else if (tokenStr == "nonInductiveForLoops")
             resources->limits.nonInductiveForLoops = (value != 0);
         else if (tokenStr == "whileLoops")
diff --git a/StandAlone/StandAlone.cpp b/StandAlone/StandAlone.cpp
index bb37a84..a7ce53d 100644
--- a/StandAlone/StandAlone.cpp
+++ b/StandAlone/StandAlone.cpp
@@ -1,6 +1,7 @@
 //
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2013-2016 LunarG, Inc.
+// Copyright (C) 2016-2020 Google, Inc.
 //
 // All rights reserved.
 //
@@ -104,6 +105,7 @@
 bool targetHlslFunctionality1 = false;
 bool SpvToolsDisassembler = false;
 bool SpvToolsValidate = false;
+bool NaNClamp = false;
 
 //
 // Return codes from main/exit().
@@ -145,11 +147,13 @@
 {
     if (ConfigFile.size() == 0)
         Resources = glslang::DefaultTBuiltInResource;
+#ifndef GLSLANG_WEB
     else {
         char* configString = ReadFileData(ConfigFile.c_str());
         glslang::DecodeResourceLimits(&Resources,  configString);
         FreeFileData(configString);
     }
+#endif
 }
 
 int ReflectOptions = EShReflectionDefault;
@@ -162,6 +166,7 @@
 const char* variableName = nullptr;
 bool HlslEnable16BitTypes = false;
 bool HlslDX9compatible = false;
+bool DumpBuiltinSymbols = false;
 std::vector<std::string> IncludeDirectoryList;
 
 // Source environment
@@ -200,7 +205,7 @@
         text.append("#define ");
         fixLine(def);
 
-        Processes.push_back("D");
+        Processes.push_back("define-macro ");
         Processes.back().append(def);
 
         // The first "=" needs to turn into a space
@@ -218,7 +223,7 @@
         text.append("#undef ");
         fixLine(undef);
 
-        Processes.push_back("U");
+        Processes.push_back("undef-macro ");
         Processes.back().append(undef);
 
         text.append(undef);
@@ -237,6 +242,7 @@
     std::string text;  // contents of preamble
 };
 
+// Track the user's #define and #undef from the command line.
 TPreamble UserPreamble;
 
 //
@@ -253,16 +259,14 @@
         case EShLangGeometry:        name = "geom.spv";    break;
         case EShLangFragment:        name = "frag.spv";    break;
         case EShLangCompute:         name = "comp.spv";    break;
-#ifdef NV_EXTENSIONS
-        case EShLangRayGenNV:        name = "rgen.spv";    break;
-        case EShLangIntersectNV:     name = "rint.spv";    break;
-        case EShLangAnyHitNV:        name = "rahit.spv";   break;
-        case EShLangClosestHitNV:    name = "rchit.spv";   break;
-        case EShLangMissNV:          name = "rmiss.spv";   break;
-        case EShLangCallableNV:      name = "rcall.spv";   break;
+        case EShLangRayGen:          name = "rgen.spv";    break;
+        case EShLangIntersect:       name = "rint.spv";    break;
+        case EShLangAnyHit:          name = "rahit.spv";   break;
+        case EShLangClosestHit:      name = "rchit.spv";   break;
+        case EShLangMiss:            name = "rmiss.spv";   break;
+        case EShLangCallable:        name = "rcall.spv";   break;
         case EShLangMeshNV:          name = "mesh.spv";    break;
         case EShLangTaskNV:          name = "task.spv";    break;
-#endif
         default:                     name = "unknown";     break;
         }
     } else
@@ -290,9 +294,12 @@
 //
 // Give error and exit with failure code.
 //
-void Error(const char* message)
+void Error(const char* message, const char* detail = nullptr)
 {
-    fprintf(stderr, "%s: Error %s (use -h for usage)\n", ExecutableName, message);
+    fprintf(stderr, "%s: Error: ", ExecutableName);
+    if (detail != nullptr)
+        fprintf(stderr, "%s: ", detail);
+    fprintf(stderr, "%s (use -h for usage)\n", message);
     exit(EFailUsage);
 }
 
@@ -480,7 +487,7 @@
                         Options |= EOptionAutoMapLocations;
                     } else if (lowerword == "uniform-base") {
                         if (argc <= 1)
-                            Error("no <base> provided for --uniform-base");
+                            Error("no <base> provided", lowerword.c_str());
                         uniformBase = ::strtol(argv[1], NULL, 10);
                         bumpArg();
                         break;
@@ -491,13 +498,23 @@
                             else if (strcmp(argv[1], "opengl100") == 0)
                                 setOpenGlSpv();
                             else
-                                Error("--client expects vulkan100 or opengl100");
-                        }
+                                Error("expects vulkan100 or opengl100", lowerword.c_str());
+                        } else
+                            Error("expects vulkan100 or opengl100", lowerword.c_str());
                         bumpArg();
+                    } else if (lowerword == "define-macro" ||
+                               lowerword == "d") {
+                        if (argc > 1)
+                            UserPreamble.addDef(argv[1]);
+                        else
+                            Error("expects <name[=def]>", argv[0]);
+                        bumpArg();
+                    } else if (lowerword == "dump-builtin-symbols") {
+                        DumpBuiltinSymbols = true;
                     } else if (lowerword == "entry-point") {
                         entryPointName = argv[1];
                         if (argc <= 1)
-                            Error("no <name> provided for --entry-point");
+                            Error("no <name> provided", lowerword.c_str());
                         bumpArg();
                     } else if (lowerword == "flatten-uniform-arrays" || // synonyms
                                lowerword == "flatten-uniform-array"  ||
@@ -519,6 +536,8 @@
                     } else if (lowerword == "keep-uncalled" || // synonyms
                                lowerword == "ku") {
                         Options |= EOptionKeepUncalled;
+                    } else if (lowerword == "nan-clamp") {
+                        NaNClamp = true;
                     } else if (lowerword == "no-storage-format" || // synonyms
                                lowerword == "nsf") {
                         Options |= EOptionNoStorageFormat;
@@ -570,7 +589,7 @@
                     } else if (lowerword == "source-entrypoint" || // synonyms
                                lowerword == "sep") {
                         if (argc <= 1)
-                            Error("no <entry-point> provided for --source-entrypoint");
+                            Error("no <entry-point> provided", lowerword.c_str());
                         sourceEntryPointName = argv[1];
                         bumpArg();
                         break;
@@ -591,6 +610,9 @@
                             } else if (strcmp(argv[1], "vulkan1.1") == 0) {
                                 setVulkanSpv();
                                 ClientVersion = glslang::EShTargetVulkan_1_1;
+                            } else if (strcmp(argv[1], "vulkan1.2") == 0) {
+                                setVulkanSpv();
+                                ClientVersion = glslang::EShTargetVulkan_1_2;
                             } else if (strcmp(argv[1], "opengl") == 0) {
                                 setOpenGlSpv();
                                 ClientVersion = glslang::EShTargetOpenGL_450;
@@ -609,22 +631,36 @@
                             } else if (strcmp(argv[1], "spirv1.4") == 0) {
                                 TargetLanguage = glslang::EShTargetSpv;
                                 TargetVersion = glslang::EShTargetSpv_1_4;
+                            } else if (strcmp(argv[1], "spirv1.5") == 0) {
+                                TargetLanguage = glslang::EShTargetSpv;
+                                TargetVersion = glslang::EShTargetSpv_1_5;
                             } else
-                                Error("--target-env expected one of: vulkan1.0, vulkan1.1, opengl, spirv1.0, spirv1.1, spirv1.2, or spirv1.3");
+                                Error("--target-env expected one of: vulkan1.0, vulkan1.1, vulkan1.2, opengl,\n"
+                                      "spirv1.0, spirv1.1, spirv1.2, spirv1.3, spirv1.4, or spirv1.5");
                         }
                         bumpArg();
+                    } else if (lowerword == "undef-macro" ||
+                               lowerword == "u") {
+                        if (argc > 1)
+                            UserPreamble.addUndef(argv[1]);
+                        else
+                            Error("expects <name>", argv[0]);
+                        bumpArg();
                     } else if (lowerword == "variable-name" || // synonyms
                                lowerword == "vn") {
                         Options |= EOptionOutputHexadecimal;
                         if (argc <= 1)
-                            Error("no <C-variable-name> provided for --variable-name");
+                            Error("no <C-variable-name> provided", lowerword.c_str());
                         variableName = argv[1];
                         bumpArg();
                         break;
                     } else if (lowerword == "version") {
                         Options |= EOptionDumpVersions;
-                    } else {
+                    } else if (lowerword == "help") {
                         usage();
+                        break;
+                    } else {
+                        Error("unrecognized command-line option", argv[0]);
                     }
                 }
                 break;
@@ -635,7 +671,7 @@
                 if (argv[0][2] == 0)
                     Options |= EOptionReadHlsl;
                 else
-                    UserPreamble.addDef(getStringOperand("-D<macro> macro name"));
+                    UserPreamble.addDef(getStringOperand("-D<name[=def]>"));
                 break;
             case 'u':
                 uniformLocationOverrides.push_back(getUniformOverride());
@@ -678,7 +714,7 @@
                 bumpArg();
                 break;
             case 'U':
-                UserPreamble.addUndef(getStringOperand("-U<macro>: macro name"));
+                UserPreamble.addUndef(getStringOperand("-U<name>"));
                 break;
             case 'V':
                 setVulkanSpv();
@@ -750,7 +786,7 @@
                 Options |= EOptionOutputHexadecimal;
                 break;
             default:
-                usage();
+                Error("unrecognized command-line option", argv[0]);
                 break;
             }
         } else {
@@ -766,8 +802,17 @@
         Error("must provide -S when --stdin is given");
 
     // Make sure that -E is not specified alongside linking (which includes SPV generation)
-    if ((Options & EOptionOutputPreprocessed) && (Options & EOptionLinkProgram))
-        Error("can't use -E when linking is selected");
+    // Or things that require linking
+    if (Options & EOptionOutputPreprocessed) {
+        if (Options & EOptionLinkProgram)
+            Error("can't use -E when linking is selected");
+        if (Options & EOptionDumpReflection)
+            Error("reflection requires linking, which can't be used when -E when is selected");
+    }
+
+    // reflection requires linking
+    if ((Options & EOptionDumpReflection) && !(Options & EOptionLinkProgram))
+        Error("reflection requires -l for linking");
 
     // -o or -x makes no sense if there is no target binary
     if (binaryFileName && (Options & EOptionSpv) == 0)
@@ -788,6 +833,10 @@
             TargetLanguage = glslang::EShTargetSpv;
             TargetVersion = glslang::EShTargetSpv_1_3;
             break;
+        case glslang::EShTargetVulkan_1_2:
+            TargetLanguage = glslang::EShTargetSpv;
+            TargetVersion = glslang::EShTargetSpv_1_5;
+            break;
         case glslang::EShTargetOpenGL_450:
             TargetLanguage = glslang::EShTargetSpv;
             TargetVersion = glslang::EShTargetSpv_1_0;
@@ -833,6 +882,8 @@
         messages = (EShMessages)(messages | EShMsgHlslLegalization);
     if (HlslDX9compatible)
         messages = (EShMessages)(messages | EShMsgHlslDX9Compatible);
+    if (DumpBuiltinSymbols)
+        messages = (EShMessages)(messages | EShMsgBuiltinSymbolTable);
 }
 
 //
@@ -960,42 +1011,47 @@
             shader->setPreamble(UserPreamble.get());
         shader->addProcesses(Processes);
 
+#ifndef GLSLANG_WEB
         // Set IO mapper binding shift values
         for (int r = 0; r < glslang::EResCount; ++r) {
             const glslang::TResourceType res = glslang::TResourceType(r);
 
             // Set base bindings
             shader->setShiftBinding(res, baseBinding[res][compUnit.stage]);
-            
+
             // Set bindings for particular resource sets
             // TODO: use a range based for loop here, when available in all environments.
             for (auto i = baseBindingForSet[res][compUnit.stage].begin();
                  i != baseBindingForSet[res][compUnit.stage].end(); ++i)
                 shader->setShiftBindingForSet(res, i->second, i->first);
         }
-
-        shader->setFlattenUniformArrays((Options & EOptionFlattenUniformArrays) != 0);
         shader->setNoStorageFormat((Options & EOptionNoStorageFormat) != 0);
         shader->setResourceSetBinding(baseResourceSetBinding[compUnit.stage]);
 
-        if (Options & EOptionHlslIoMapping)
-            shader->setHlslIoMapping(true);
-
         if (Options & EOptionAutoMapBindings)
             shader->setAutoMapBindings(true);
 
         if (Options & EOptionAutoMapLocations)
             shader->setAutoMapLocations(true);
 
-        if (Options & EOptionInvertY)
-            shader->setInvertY(true);
-
         for (auto& uniOverride : uniformLocationOverrides) {
             shader->addUniformLocationOverride(uniOverride.first.c_str(),
                                                uniOverride.second);
         }
 
         shader->setUniformLocationBase(uniformBase);
+#endif
+
+        shader->setNanMinMaxClamp(NaNClamp);
+
+#ifdef ENABLE_HLSL
+        shader->setFlattenUniformArrays((Options & EOptionFlattenUniformArrays) != 0);
+        if (Options & EOptionHlslIoMapping)
+            shader->setHlslIoMapping(true);
+#endif
+
+        if (Options & EOptionInvertY)
+            shader->setInvertY(true);
 
         // Set up the environment, some subsettings take precedence over earlier
         // ways of setting things.
@@ -1005,8 +1061,10 @@
                                 compUnit.stage, Client, ClientInputSemanticsVersion);
             shader->setEnvClient(Client, ClientVersion);
             shader->setEnvTarget(TargetLanguage, TargetVersion);
+#ifdef ENABLE_HLSL
             if (targetHlslFunctionality1)
                 shader->setEnvTargetHlslFunctionality1();
+#endif
         }
 
         shaders.push_back(shader);
@@ -1016,6 +1074,7 @@
         DirStackFileIncluder includer;
         std::for_each(IncludeDirectoryList.rbegin(), IncludeDirectoryList.rend(), [&includer](const std::string& dir) {
             includer.pushExternalLocalDirectory(dir); });
+#ifndef GLSLANG_WEB
         if (Options & EOptionOutputPreprocessed) {
             std::string str;
             if (shader->preprocess(&Resources, defaultVersion, ENoProfile, false, false, messages, &str, includer)) {
@@ -1027,6 +1086,7 @@
             StderrIfNonEmpty(shader->getInfoDebugLog());
             continue;
         }
+#endif
 
         if (! shader->parse(&Resources, defaultVersion, false, messages, includer))
             CompileFailed = true;
@@ -1049,11 +1109,13 @@
     if (! (Options & EOptionOutputPreprocessed) && ! program.link(messages))
         LinkFailed = true;
 
+#ifndef GLSLANG_WEB
     // Map IO
     if (Options & EOptionSpv) {
         if (!program.mapIO())
             LinkFailed = true;
     }
+#endif
 
     // Report
     if (! (Options & EOptionSuppressInfolog) &&
@@ -1062,11 +1124,13 @@
         PutsIfNonEmpty(program.getInfoDebugLog());
     }
 
+#ifndef GLSLANG_WEB
     // Reflect
     if (Options & EOptionDumpReflection) {
         program.buildReflection(ReflectOptions);
         program.dumpReflection();
     }
+#endif
 
     // Dump SPIR-V
     if (Options & EOptionSpv) {
@@ -1076,7 +1140,6 @@
             for (int stage = 0; stage < EShLangCount; ++stage) {
                 if (program.getIntermediate((EShLanguage)stage)) {
                     std::vector<unsigned int> spirv;
-                    std::string warningsErrors;
                     spv::SpvBuildLogger logger;
                     glslang::SpvOptions spvOptions;
                     if (Options & EOptionDebug)
@@ -1096,8 +1159,10 @@
                         } else {
                             glslang::OutputSpvBin(spirv, GetBinaryName((EShLanguage)stage));
                         }
+#ifndef GLSLANG_WEB
                         if (!SpvToolsDisassembler && (Options & EOptionHumanReadableSpv))
                             spv::Disassemble(std::cout, spirv);
+#endif
                     }
                 }
             }
@@ -1185,11 +1250,13 @@
         workList.add(item.get());
     });
 
+#ifndef GLSLANG_WEB
     if (Options & EOptionDumpConfig) {
         printf("%s", glslang::GetDefaultTBuiltInResourceString().c_str());
         if (workList.empty())
             return ESuccess;
     }
+#endif
 
     if (Options & EOptionDumpBareVersion) {
         printf("%d.%d.%d\n",
@@ -1225,7 +1292,7 @@
     ProcessConfigFile();
 
     if ((Options & EOptionReadHlsl) && !((Options & EOptionOutputPreprocessed) || (Options & EOptionSpv)))
-        Error("ERROR: HLSL requires SPIR-V code generation (or preprocessing only)");
+        Error("HLSL requires SPIR-V code generation (or preprocessing only)");
 
     //
     // Two modes:
@@ -1361,24 +1428,22 @@
         return EShLangFragment;
     else if (stageName == "comp")
         return EShLangCompute;
-#ifdef NV_EXTENSIONS
     else if (stageName == "rgen")
-        return EShLangRayGenNV;
+        return EShLangRayGen;
     else if (stageName == "rint")
-        return EShLangIntersectNV;
+        return EShLangIntersect;
     else if (stageName == "rahit")
-        return EShLangAnyHitNV;
+        return EShLangAnyHit;
     else if (stageName == "rchit")
-        return EShLangClosestHitNV;
+        return EShLangClosestHit;
     else if (stageName == "rmiss")
-        return EShLangMissNV;
+        return EShLangMiss;
     else if (stageName == "rcall")
-        return EShLangCallableNV;
+        return EShLangCallable;
     else if (stageName == "mesh")
         return EShLangMeshNV;
     else if (stageName == "task")
         return EShLangTaskNV;
-#endif
 
     usage();
     return EShLangVertex;
@@ -1448,7 +1513,6 @@
            "    .geom   for a geometry shader\n"
            "    .frag   for a fragment shader\n"
            "    .comp   for a compute shader\n"
-#ifdef NV_EXTENSIONS
            "    .mesh   for a mesh shader\n"
            "    .task   for a task shader\n"
            "    .rgen    for a ray generation shader\n"
@@ -1457,15 +1521,14 @@
            "    .rchit   for a ray closest hit shader\n"
            "    .rmiss   for a ray miss shader\n"
            "    .rcall   for a ray callable shader\n"
-#endif
            "    .glsl   for .vert.glsl, .tesc.glsl, ..., .comp.glsl compound suffixes\n"
            "    .hlsl   for .vert.hlsl, .tesc.hlsl, ..., .comp.hlsl compound suffixes\n"
            "\n"
            "Options:\n"
            "  -C          cascading errors; risk crash from accumulation of error recoveries\n"
            "  -D          input is HLSL (this is the default when any suffix is .hlsl)\n"
-           "  -D<macro=def>\n"
-           "  -D<macro>   define a pre-processor macro\n"
+           "  -D<name[=def]> | --define-macro <name[=def]> | --D <name[=def]>\n"
+           "              define a pre-processor macro\n"
            "  -E          print pre-processed GLSL; cannot be used with -l;\n"
            "              errors will appear on stderr\n"
            "  -G[ver]     create SPIR-V binary, under OpenGL semantics; turns on -l;\n"
@@ -1481,7 +1544,8 @@
            "  -Os         optimizes SPIR-V to minimize size\n"
            "  -S <stage>  uses specified stage rather than parsing the file extension\n"
            "              choices for <stage> are vert, tesc, tese, geom, frag, or comp\n"
-           "  -U<macro>   undefine a pre-processor macro\n"
+           "  -U<name> | --undef-macro <name> | --U <name>\n"
+           "              undefine a pre-processor macro\n"
            "  -V[ver]     create SPIR-V binary, under Vulkan semantics; turns on -l;\n"
            "              default file name is <stage>.spv (-o overrides this)\n"
            "              'ver', when present, is the version of the input semantics,\n"
@@ -1503,7 +1567,7 @@
            "  -l          link all input files together to form a single module\n"
            "  -m          memory leak mode\n"
            "  -o <file>   save binary to <file>, requires a binary option (e.g., -V)\n"
-           "  -q          dump reflection query database\n"
+           "  -q          dump reflection query database; requires -l for linking\n"
            "  -r | --relaxed-errors"
            "              relaxed GLSL semantic error-checking mode\n"
            "  -s          silence syntax and semantic error reporting\n"
@@ -1520,6 +1584,7 @@
            "  --auto-map-locations | --aml      automatically locate input/output lacking\n"
            "                                    'location' (fragile, not cross stage)\n"
            "  --client {vulkan<ver>|opengl<ver>} see -V and -G\n"
+           "  --dump-builtin-symbols            prints builtin symbol table prior each compile\n"
            "  -dumpfullversion | -dumpversion   print bare major.minor.patchlevel\n"
            "  --flatten-uniform-arrays | --fua  flatten uniform texture/sampler arrays to\n"
            "                                    scalars\n"
@@ -1527,9 +1592,11 @@
            "                                    works independently of source language\n"
            "  --hlsl-iomap                      perform IO mapping in HLSL register space\n"
            "  --hlsl-enable-16bit-types         allow 16-bit types in SPIR-V for HLSL\n"
-           "  --hlsl-dx9-compatible             interprets sampler declarations as a texture/sampler combo like DirectX9 would."
+           "  --hlsl-dx9-compatible             interprets sampler declarations as a\n"
+           "                                    texture/sampler combo like DirectX9 would.\n"
            "  --invert-y | --iy                 invert position.Y output in vertex shader\n"
            "  --keep-uncalled | --ku            don't eliminate uncalled functions\n"
+           "  --nan-clamp                       favor non-NaN operand in min, max, and clamp\n"
            "  --no-storage-format | --nsf       use Unknown image format\n"
            "  --reflect-strict-array-suffix     use strict array suffix rules when\n"
            "                                    reflecting\n"
@@ -1584,16 +1651,17 @@
            "  --sep                             synonym for --source-entrypoint\n"
            "  --stdin                           read from stdin instead of from a file;\n"
            "                                    requires providing the shader stage using -S\n"
-           "  --target-env {vulkan1.0 | vulkan1.1 | opengl | \n"
-           "                spirv1.0 | spirv1.1 | spirv1.2 | spirv1.3}\n"
-           "                                    set execution environment that emitted code\n"
-           "                                    will execute in (versus source language\n"
-           "                                    semantics selected by --client) defaults:\n"
-           "                                     * 'vulkan1.0' under '--client vulkan<ver>'\n"
-           "                                     * 'opengl' under '--client opengl<ver>'\n"
-           "                                     * 'spirv1.0' under --target-env vulkan1.0\n"
-           "                                     * 'spirv1.3' under --target-env vulkan1.1\n"
-           "                                    multiple --targen-env can be specified.\n"
+           "  --target-env {vulkan1.0 | vulkan1.1 | vulkan1.2 | opengl | \n"
+           "                spirv1.0 | spirv1.1 | spirv1.2 | spirv1.3 | spirv1.4 | spirv1.5}\n"
+           "                                    Set the execution environment that the\n"
+           "                                    generated code will be executed in.\n"
+           "                                    Defaults to:\n"
+           "                                     * vulkan1.0 under --client vulkan<ver>\n"
+           "                                     * opengl    under --client opengl<ver>\n"
+           "                                     * spirv1.0  under --target-env vulkan1.0\n"
+           "                                     * spirv1.3  under --target-env vulkan1.1\n"
+           "                                     * spirv1.5  under --target-env vulkan1.2\n"
+           "                                    Multiple --target-env can be specified.\n"
            "  --variable-name <name>\n"
            "  --vn <name>                       creates a C header file that contains a\n"
            "                                    uint32_t array named <name>\n"
diff --git a/StandAlone/resource_limits_c.cpp b/StandAlone/resource_limits_c.cpp
new file mode 100644
index 0000000..a1f681c
--- /dev/null
+++ b/StandAlone/resource_limits_c.cpp
@@ -0,0 +1,65 @@
+/**
+BSD 2-Clause License
+
+Copyright (c) 2020, Travis Fort
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+   list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**/
+
+#include "resource_limits_c.h"
+#include "ResourceLimits.h"
+#include <stdlib.h>
+#include <string.h>
+#include <string>
+
+const glslang_resource_t* glslang_default_resource(void)
+{
+    return reinterpret_cast<const glslang_resource_t*>(&glslang::DefaultTBuiltInResource);
+}
+
+#if defined(__clang__) || defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#elif defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable : 4996)
+#endif
+
+const char* glslang_default_resource_string()
+{
+    std::string cpp_str = glslang::GetDefaultTBuiltInResourceString();
+    char* c_str = (char*)malloc(cpp_str.length() + 1);
+    strcpy(c_str, cpp_str.c_str());
+    return c_str;
+}
+
+#if defined(__clang__) || defined(__GNUC__)
+#pragma GCC diagnostic pop
+#elif defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+
+void glslang_decode_resource_limits(glslang_resource_t* resources, char* config)
+{
+    glslang::DecodeResourceLimits(reinterpret_cast<TBuiltInResource*>(resources), config);
+}
diff --git a/StandAlone/resource_limits_c.h b/StandAlone/resource_limits_c.h
new file mode 100644
index 0000000..108fd5e
--- /dev/null
+++ b/StandAlone/resource_limits_c.h
@@ -0,0 +1,54 @@
+/**
+BSD 2-Clause License
+
+Copyright (c) 2020, Travis Fort
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+   list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**/
+
+#ifndef _STAND_ALONE_RESOURCE_LIMITS_C_INCLUDED_
+#define _STAND_ALONE_RESOURCE_LIMITS_C_INCLUDED_
+
+#include "../glslang/Include/glslang_c_interface.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// These are the default resources for TBuiltInResources, used for both
+//  - parsing this string for the case where the user didn't supply one,
+//  - dumping out a template for user construction of a config file.
+const glslang_resource_t* glslang_default_resource(void);
+
+// Returns the DefaultTBuiltInResource as a human-readable string.
+// NOTE: User is responsible for freeing this string.
+const char* glslang_default_resource_string();
+
+// Decodes the resource limits from |config| to |resources|.
+void glslang_decode_resource_limits(glslang_resource_t* resources, char* config);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _STAND_ALONE_RESOURCE_LIMITS_C_INCLUDED_
diff --git a/StandAlone/spirv-remap.cpp b/StandAlone/spirv-remap.cpp
index 998f742..48878c3 100644
--- a/StandAlone/spirv-remap.cpp
+++ b/StandAlone/spirv-remap.cpp
@@ -227,7 +227,7 @@
                 }
             }
             else if (arg == "--version" || arg == "-V") {
-                std::cout << basename(argv[0]) << " version 0.97 " << __DATE__ << " " << __TIME__ << std::endl;
+                std::cout << basename(argv[0]) << " version 0.97" << std::endl;
                 exit(0);
             } else if (arg == "--input" || arg == "-i") {
                 // Collect input files
@@ -334,8 +334,6 @@
     if (outputDir.empty())
         usage(argv[0], "Output directory required");
 
-    std::string errmsg;
-
     // Main operations: read, remap, and write.
     execute(inputFile, outputDir, opts, verbosity);
 
diff --git a/Test/100.frag b/Test/100.frag
index 4f0c69b..439fc6c 100644
--- a/Test/100.frag
+++ b/Test/100.frag
@@ -201,6 +201,19 @@
     return fooinit();

 }

 

+// Test extension GL_EXT_blend_func_extended

+void blendFuncFail() // Error since extension GL_EXT_blend_func_extended is disabled

+{

+    gl_SecondaryFragColorEXT = vec4(1.0);   

+    gl_SecondaryFragDataEXT[gl_MaxDualSourceDrawBuffersEXT - 1] = vec4(0.1);

+}

+#extension GL_EXT_blend_func_extended : enable

+void blendFunc() 

+{

+    gl_SecondaryFragColorEXT = vec4(1.0);

+    gl_SecondaryFragDataEXT[gl_MaxDualSourceDrawBuffersEXT - 1] = vec4(0.1);

+}

+

 // Test extra-function initializers

 const float fi1 = 3.0;

 const float fi2 = 4.0;

@@ -219,6 +232,9 @@
 

 int init2 = gl_FrontFacing ? 1 : 2;

 

+#define A__B // error

+int a__b;    // error

+

 #pragma STDGL invariant(all)

 

 #line 3000

diff --git a/Test/120.vert b/Test/120.vert
index d276557..7b98492 100644
--- a/Test/120.vert
+++ b/Test/120.vert
@@ -201,3 +201,15 @@
 
 #define macr(A,B) A ## B
 int macr(qrs,tuv);
+
+layout(std140) uniform BlockName    // ERROR
+{
+    int test;
+};
+
+#extension GL_ARB_uniform_buffer_object : enable
+
+layout(std140) uniform BlockName
+{
+    int test;
+};
\ No newline at end of file
diff --git a/Test/130.frag b/Test/130.frag
index 3e39411..c352df4 100644
--- a/Test/130.frag
+++ b/Test/130.frag
@@ -62,12 +62,14 @@
     b3 < b3;                   // ERROR
     uv3 > uv3;                 // ERROR
     uvec2(2, 3) >= uvec2(3,3); // ERROR
+    int samples = gl_NumSamples; // ERROR
     int(bl4) <= int(bl4);      // true
     int(bl4.x) > int(bl4.y);   // false
 }
 
 #extension GL_ARB_texture_gather : enable
 #extension GL_ARB_texture_rectangle : enable
+#extension GL_ARB_sample_shading : enable
 
 uniform sampler2D samp2D;
 uniform sampler2DShadow samp2DS;
@@ -83,6 +85,7 @@
     s = textureGatherOffset(samp2DA, vec3(0.3), ivec2(1));
     s = textureGatherOffset(samp2DS, vec2(0.3), 1.3, ivec2(1)); // ERROR
     s = textureGatherOffset(samp2D, vec2(0.3), ivec2(1), 2);    // ERROR
+    int samples = gl_NumSamples;
 }
 
 #extension GL_ARB_gpu_shader5 : enable
@@ -167,3 +170,12 @@
 }
 
 layout(early_fragment_tests) out;         // ERROR
+
+#extension GL_ARB_explicit_uniform_location : enable
+
+layout(location = 3) uniform vec4 ucolor0; // ERROR: explicit attrib location is also required for version < 330
+
+#extension GL_ARB_explicit_attrib_location : enable
+
+layout(location = 4) uniform vec4 ucolor1;
+
diff --git a/Test/140.frag b/Test/140.frag
index 2bc2f59..5efdbed 100644
--- a/Test/140.frag
+++ b/Test/140.frag
@@ -17,6 +17,7 @@
 #error GL_ES is not set
 #endif
 
+
 in struct S { float f; } s; // ERROR
 
 float patch = 3.1;
@@ -51,3 +52,9 @@
 {
     return i1 + i2;
 }
+
+uniform sampler2DMS aaa1; // ERROR
+
+#extension GL_ARB_texture_multisample : enable
+
+uniform sampler2DMS aaa2;
diff --git a/Test/140.vert b/Test/140.vert
index 914e672..8035144 100644
--- a/Test/140.vert
+++ b/Test/140.vert
@@ -68,7 +68,7 @@
 #extension GL_EXT_device_group : enable
 #endif
 
-#ifdef GL_EXT_device_group
+#ifdef GL_EXT_multiview
 #extension GL_EXT_multiview : enable
 #endif
 
diff --git a/Test/150.frag b/Test/150.frag
index 16963af..228e4f0 100644
--- a/Test/150.frag
+++ b/Test/150.frag
@@ -47,4 +47,138 @@
 int primitiveID()

 {

    return gl_PrimitiveID;

+   gl_PerFragment; // ERROR, block name can't get reused

+}

+

+in double type1;    // ERROR

+#extension GL_ARB_gpu_shader_fp64 : enable

+double type2;

+double type3 = 2.0;

+int absTest = sqrt(type3);

+double absTest2 = sqrt(type3);

+double absTest3 = sqrt(2);

+float dk = sqrt(11);

+

+#extension GL_ARB_shader_bit_encoding: enable

+

+float f;

+vec4 v4;

+ivec4 iv4a;

+uvec2 uv2c;

+void bitEncodingPass()

+{

+    int i = floatBitsToInt(f);

+    uvec4 uv11 = floatBitsToUint(v4);

+    vec4 v14 = intBitsToFloat(iv4a);

+    vec2 v15 = uintBitsToFloat(uv2c);

+}

+

+#extension GL_ARB_shader_bit_encoding: disable

+

+void bitEncodingFail()

+{

+    int i = floatBitsToInt(f); // Error, extention GL_ARB_bit_encoding is diabled

+}

+

+#extension GL_ARB_shading_language_packing : enable

+vec2 v2a;

+uint uy;

+

+void packingPass()

+{

+    uint u19 = packSnorm2x16(v2a);

+    vec2 v20 = unpackSnorm2x16(uy);

+    uint u15 = packUnorm2x16(v2a);

+    vec2 v16 = unpackUnorm2x16(uy);

+    uint u17 = packHalf2x16(v2a);

+    vec2 v18 = unpackHalf2x16(uy);

+}

+

+#extension GL_ARB_shading_language_packing : disable

+void packingFail()

+{

+    uint u19 = packSnorm2x16(v2a); // Error, extension GL_ARB_shading_language_packing is disabled

+}

+

+// Testing extension GL_ARB_texture_query_lod

+uniform sampler1D samp1D;

+uniform sampler2DShadow samp2Ds;

+

+void qlodFail()

+{

+    vec2 lod;

+    float pf;

+    vec2 pf2;

+    vec3 pf3;

+

+    lod = textureQueryLod(samp1D, pf);      // ERROR, extension GL_ARB_texture_query_lod needed

+    lod = textureQueryLod(samp2Ds, pf2);    // ERROR, extension GL_ARB_texture_query_lod needed

+}

+

+#extension GL_ARB_texture_query_lod : enable

+

+uniform isampler2D isamp2D;

+uniform usampler3D usamp3D;

+uniform samplerCube sampCube;

+uniform isampler1DArray isamp1DA;

+uniform usampler2DArray usamp2DA;

+

+uniform sampler1DShadow samp1Ds;

+uniform samplerCubeShadow sampCubes;

+uniform sampler1DArrayShadow samp1DAs;

+uniform sampler2DArrayShadow samp2DAs;

+

+uniform samplerBuffer sampBuf;

+uniform sampler2DRect sampRect;

+

+void qlodPass()

+{

+    vec2 lod;

+    float pf;

+    vec2 pf2;

+    vec3 pf3;

+

+    lod = textureQueryLod(samp1D, pf);

+    lod = textureQueryLod(isamp2D, pf2);

+    lod = textureQueryLod(usamp3D, pf3);

+    lod = textureQueryLod(sampCube, pf3);

+    lod = textureQueryLod(isamp1DA, pf);

+    lod = textureQueryLod(usamp2DA, pf2);

+

+    lod = textureQueryLod(samp1Ds, pf);

+    lod = textureQueryLod(samp2Ds, pf2);

+    lod = textureQueryLod(sampCubes, pf3);

+    lod = textureQueryLod(samp1DAs, pf);

+    lod = textureQueryLod(samp2DAs, pf2);

+

+    lod = textureQueryLod(sampBuf, pf);     // ERROR

+    lod = textureQueryLod(sampRect, pf2);   // ERROR

+}

+

+// Test extension GL_EXT_shader_integer_mix

+#extension GL_EXT_shader_integer_mix : enable

+bool b1, b2, b;

+int x,y;

+uint z,w;

+

+void testmix()

+{

+    int ival  = mix(x, y, b);

+    ivec2 iv2 = mix(ivec2(x), ivec2(y), bvec2(b));

+    ivec3 iv3 = mix(ivec3(x), ivec3(y), bvec3(b));

+    ivec4 iv4 = mix(ivec4(x), ivec4(x), bvec4(b));

+    uint  uiv = mix(z, w, b);

+    uvec2 uv2 = mix(uvec2(z), uvec2(z), bvec2(b));

+    uvec3 uv3 = mix(uvec3(z), uvec3(z), bvec3(b));

+    uvec4 uv4 = mix(uvec4(z), uvec4(z), bvec4(b));

+    bool  bv  = mix(b1, b2, b);

+    bvec2 bv2 = mix(bvec2(b1), bvec2(b2), bvec2(b));

+    bvec3 bv3 = mix(bvec3(b1), bvec3(b2), bvec3(b));

+    bvec4 bv4 = mix(bvec4(b1), bvec4(b2), bvec4(b));

+}

+

+#extension GL_EXT_shader_integer_mix : disable

+void testmixFail()

+{

+    int ival  = mix(x, y, b); // Error since extenson GL_EXT_shader_integer_mix is disabled

 }

diff --git a/Test/150.vert b/Test/150.vert
index 4dd9e5c..f9a920c 100644
--- a/Test/150.vert
+++ b/Test/150.vert
@@ -25,5 +25,21 @@
 };

 int a[5]; // ERROR, resizing user-block member

 

+in double dvarerr; // Error since extension GL_ARB_vertex_attrib_64bit is not enabled

+#extension GL_ARB_vertex_attrib_64bit: enable

+in double dvar;

+in dvec2  dv2var;

+in dvec3  dv3var;

+in dvec4  dv4var;

+in dmat2  dmat2var;

+in dmat3  dmat3var;

+in dmat4  dmat4var;

+in dmat2x3 dmat23var;

+in dmat2x4 dmat24var;

+in dmat3x2 dmat32var;

+in dmat3x4 dmat34var;

+in dmat4x2 dmat42var;

+in dmat4x3 dmat43var;

+

 #line 3000

 #error line of this error should be 3001

diff --git a/Test/300.frag b/Test/300.frag
index ca2e2cb..279864a 100644
--- a/Test/300.frag
+++ b/Test/300.frag
@@ -149,6 +149,39 @@
 
 layout(early_fragment_tests) in;  // ERROR
 
+// Test extension GL_EXT_shader_integer_mix
+#extension GL_EXT_shader_integer_mix : enable
+bool b1, b2, b;
+int x,y;
+uint z,w;
+
+void testmix()
+{
+    int ival  = mix(x, y, b);
+    ivec2 iv2 = mix(ivec2(x), ivec2(y), bvec2(b));
+    ivec3 iv3 = mix(ivec3(x), ivec3(y), bvec3(b));
+    ivec4 iv4 = mix(ivec4(x), ivec4(x), bvec4(b));
+    uint  uiv = mix(z, w, b);
+    uvec2 uv2 = mix(uvec2(z), uvec2(z), bvec2(b));
+    uvec3 uv3 = mix(uvec3(z), uvec3(z), bvec3(b));
+    uvec4 uv4 = mix(uvec4(z), uvec4(z), bvec4(b));
+    bool  bv  = mix(b1, b2, b);
+    bvec2 bv2 = mix(bvec2(b1), bvec2(b2), bvec2(b));
+    bvec3 bv3 = mix(bvec3(b1), bvec3(b2), bvec3(b));
+    bvec4 bv4 = mix(bvec4(b1), bvec4(b2), bvec4(b));
+}
+
+#extension GL_EXT_shader_integer_mix : disable
+void testmixFail()
+{
+    int ival  = mix(x, y, b); // Error since extenson GL_EXT_shader_integer_mix is disabled
+}
+
+// Test layout qualifier "index" with extension GL_EXT_blend_func_extended
+layout(location = 0, index = 1) out vec4 outVarFail; // Error Index supported with extension GL_EXT_blend_func_extended enabled
+#extension GL_EXT_blend_func_extended : enable
+layout(location = 0, index = 2) out vec4 outVarPass;
+
 #ifndef GL_FRAGMENT_PRECISION_HIGH
 #error missing GL_FRAGMENT_PRECISION_HIGH
 #endif
diff --git a/Test/310.comp b/Test/310.comp
index 9ca8eaa..33ecbf0 100644
--- a/Test/310.comp
+++ b/Test/310.comp
@@ -106,9 +106,9 @@
 

 void passrc()

 {

-    passr(qualim1);

-    passr(qualim2);   // ERROR, drops restrict

-    passr(iimg2D);

+    passr(qualim1);   // ERROR, changing formats

+    passr(qualim2);   // ERROR, drops restrict, ERROR, changing formats

+    passr(iimg2D);    // ERROR, changing formats

 }

 

 highp layout(rg8i)     uniform readonly uimage2D i1bad; // ERROR, type mismatch

diff --git a/Test/310.frag b/Test/310.frag
old mode 100644
new mode 100755
index 6814e6c..5cdcca7
--- a/Test/310.frag
+++ b/Test/310.frag
@@ -58,8 +58,8 @@
     b1 = mix(b2, b3, b);

     uvec3 um3 = mix(uvec3(i), uvec3(i), bvec3(b));

     ivec4 im4 = mix(ivec4(i), ivec4(i), bvec4(b));

+    1 << mix(1u, 1u, false);  // does not require folding
 }

-

 layout(binding=3) uniform sampler2D s1;

 layout(binding=3) uniform sampler2D s2; // ERROR: overlapping bindings?  Don't see that in the 310 spec.

 highp layout(binding=2) uniform writeonly image2D      i2D;

@@ -440,7 +440,7 @@
 #extension GL_EXT_device_group : enable
 #endif
 
-#ifdef GL_EXT_device_group
+#ifdef GL_EXT_multiview
 #extension GL_EXT_multiview : enable
 #endif
 
@@ -448,4 +448,40 @@
 {
     gl_DeviceIndex;
     gl_ViewIndex;
-}
+}

+

+#extension GL_EXT_shader_implicit_conversions : enable

+

+// Test function overloading

+void func(uint a, uvec4 b)

+{

+

+}

+

+int func(uint a, uvec4 b) // Error function overloading because of same signature and different return type

+{

+    return 0;

+}

+

+int b;

+

+void testimplicit() {

+

+    uint a = b; // int->uint

+    mediump vec4 col = vec4(1, 2, 3, 4); // ivec4 -> vec4

+    int  b = a + 2; // ERROR: cannot convert from ' temp uint' to ' temp int'

+

+    // Test binary ops

+    uint c = b * 3; 

+    uint d = b * 3u;

+    uint e = b%3;

+    uint f = (b > 3)? b : c;     

+    func(b, ivec4(1,2,3,4)); 

+}

+

+#extension GL_EXT_shader_implicit_conversions : disable

+

+void testimplicitFail() {

+    uint a = b; // Error GL_EXT_shader_implicit_conversions is disabled

+}

+

diff --git a/Test/310.inheritMemory.frag b/Test/310.inheritMemory.frag
new file mode 100644
index 0000000..bdf1283
--- /dev/null
+++ b/Test/310.inheritMemory.frag
@@ -0,0 +1,43 @@
+#version 310 es

+precision mediump float;

+

+struct S {

+    float buff[10];

+};

+

+layout(std430, binding=2) readonly buffer RoBuff {

+    float buff_ro[10];

+    S s_ro;

+} ro_buffer;

+

+layout(std430, binding=2) buffer Buff {

+    float buff[10];

+    S s;

+} non_ro_buffer;

+

+void non_ro_fun(float[10] buff) { }

+void non_ro_funf(float el) { }

+void non_ro_funS(S s) { }

+

+out vec4 fragColor;

+

+void main()

+{

+    S s;

+

+    non_ro_fun(s.buff);

+    non_ro_funf(s.buff[3]);

+    non_ro_funS(s);

+

+    non_ro_fun(non_ro_buffer.buff);

+    non_ro_fun(non_ro_buffer.s.buff);

+    non_ro_funf(non_ro_buffer.buff[3]);

+    non_ro_funf(non_ro_buffer.s.buff[3]);

+    non_ro_funS(non_ro_buffer.s);

+

+    non_ro_fun(ro_buffer.buff_ro);

+    non_ro_fun(ro_buffer.s_ro.buff);

+    non_ro_funf(ro_buffer.buff_ro[3]);

+    non_ro_funf(ro_buffer.s_ro.buff[3]);

+    non_ro_funS(ro_buffer.s_ro);

+}

diff --git a/Test/320.comp b/Test/320.comp
index c31b047..5b38995 100644
--- a/Test/320.comp
+++ b/Test/320.comp
@@ -1,5 +1,17 @@
 #version 320 es

+
+float fX;
+float fY;
 

 void main()
 {
+    dFdx(fX);
+    dFdy(fY);
+    fwidth(fX);
+    dFdxCoarse(fX);
+    dFdyCoarse(fY);
+    fwidthCoarse(fX);
+    dFdxFine(fX);
+    dFdyFine(fY);
+    fwidthFine(fX);
 }
diff --git a/Test/330.frag b/Test/330.frag
index 9afa8f8..364fc0a 100644
--- a/Test/330.frag
+++ b/Test/330.frag
@@ -126,27 +126,26 @@
 layout(location=0, index=0) in; // ERROR, not just on in
 layout(location=0, index=0) out; // ERROR, need a variable
 layout(location=26, index=0) out indexBlock { int a; } indexBlockI; // ERROR, not on a block
-

-uniform sampler1D samp1D;

-uniform sampler2DShadow samp2Ds;

-

-void qlod()

-{

-    vec2 lod;

-    float pf;

-    vec2 pf2;

-    vec3 pf3;

-

-    lod = textureQueryLod(samp1D, pf);      // ERROR, not until 400

-    lod = textureQueryLod(samp2Ds, pf2);    // ERROR, not until 400

-}

-

-int precise;                // okay, not a keyword yet

-struct SKeyMem { int precise; } KeyMem; // okay, not a keyword yet

-

-void fooKeyMem()

-{

-    KeyMem.precise;

-}

-

-layout(location=28, index=2) out vec4 outIndex2; // ERROR index out of range
\ No newline at end of file
+
+int precise;                // okay, not a keyword yet
+struct SKeyMem { int precise; } KeyMem; // okay, not a keyword yet
+
+void fooKeyMem()
+{
+    KeyMem.precise;
+}
+
+layout(location=28, index=2) out vec4 outIndex2; // ERROR index out of range
+
+layout(location=4) uniform vec4 ucolor0; // ERROR: extension is not enabled
+
+#extension GL_ARB_explicit_uniform_location : enable
+
+layout(location=5) uniform vec4 ucolor1;
+
+layout(location=6) uniform ColorsBuffer // ERROR: location cannot be applied in uniform buffer block
+{
+    vec4 colors[128];
+} colorsBuffer;
+
+
diff --git a/Test/400.tesc b/Test/400.tesc
index 415d7f7..6d609d5 100644
--- a/Test/400.tesc
+++ b/Test/400.tesc
@@ -114,7 +114,7 @@
 #extension GL_EXT_device_group : enable
 #endif
 
-#ifdef GL_EXT_device_group
+#ifdef GL_EXT_multiview
 #extension GL_EXT_multiview : enable
 #endif
 
diff --git a/Test/400.tese b/Test/400.tese
index c110a1c..a3d30fe 100644
--- a/Test/400.tese
+++ b/Test/400.tese
@@ -114,7 +114,7 @@
 #extension GL_EXT_device_group : enable
 #endif
 
-#ifdef GL_EXT_device_group
+#ifdef GL_EXT_multiview
 #extension GL_EXT_multiview : enable
 #endif
 
diff --git a/Test/410.vert b/Test/410.vert
index 0ecf476..1891a67 100644
--- a/Test/410.vert
+++ b/Test/410.vert
@@ -6,4 +6,5 @@
 
 void main()
 {
+    int test = gl_MaxFragmentUniformVectors;
 }
diff --git a/Test/420.frag b/Test/420.frag
index 1444758..d3020b3 100644
--- a/Test/420.frag
+++ b/Test/420.frag
@@ -12,3 +12,31 @@
 layout(depth_any) out float gl_FragDepth;  // ERROR, done after use
 
 layout(binding=0) uniform atomic_uint a[];
+
+uniform writeonly image2D      i2D;
+ivec2 iv2dim = imageSize(i2D); // ERROR: imageSize called without enabling GL_ARB_shader_image_size extension
+#extension GL_ARB_shader_image_size : enable
+ivec2 iv2dim1 = imageSize(i2D);
+
+#extension GL_ARB_shader_storage_buffer_object : enable
+
+layout(binding = 0,std430) buffer Buffer
+{
+    int atomi;
+    uint atomu;
+};
+
+void atomicOpPass()
+{
+    int origi = atomicAdd(atomi, 3);
+    uint origu = atomicAnd(atomu, 7u);
+    origi = atomicExchange(atomi, 4);
+    origu = atomicCompSwap(atomu, 10u, 8u);
+}
+
+#extension GL_ARB_shader_storage_buffer_object : disable
+
+layout(binding = 1,std430) buffer BufferFail // Error std430 and "buffer" block support disabled 
+{
+    int atom1i;
+};
diff --git a/Test/420.vert b/Test/420.vert
index ab28140..c7ffa90 100644
--- a/Test/420.vert
+++ b/Test/420.vert
@@ -131,9 +131,9 @@
 
 void passrc()
 {
-    passr(qualim1);
-    passr(qualim2);   // ERROR, drops volatile
-    passr(iimg2D);
+    passr(qualim1);   // ERROR, changing formats
+    passr(qualim2);   // ERROR, drops volatile, ERROR, changing formats
+    passr(iimg2D);    // ERROR, changing formats
 }
 
 layout(rg8i) uniform uimage2D i1bad;     // ERROR, type mismatch
diff --git a/Test/430.comp b/Test/430.comp
index 0929432..178b994 100644
--- a/Test/430.comp
+++ b/Test/430.comp
@@ -48,6 +48,9 @@
 layout(location = 2) shared vec4 sl;  // ERROR

 shared float fs = 4.2;                // ERROR

 

+layout(local_size_y = 1) in;

+layout(local_size_y = 2) in;     // ERROR, changing

+layout(local_size_y = 1) in;

 layout(local_size_x = 2, local_size_y = 3, local_size_z = 4) out;  // ERROR

 

 int arrX[gl_WorkGroupSize.x];

diff --git a/Test/450.comp b/Test/450.comp
index fb2b56a..316674d 100644
--- a/Test/450.comp
+++ b/Test/450.comp
@@ -1,5 +1,8 @@
 #version 450 core

 layout(local_size_x = 0) in; // ERROR, 0 not allowed

+

+layout(binding=10000) uniform atomic_uint;     // ERROR

+

 void main()

 {

     shared float f;   // ERROR shared must be global

diff --git a/Test/460.vert b/Test/460.vert
index fd87d8b..cf4f4ad 100644
--- a/Test/460.vert
+++ b/Test/460.vert
@@ -7,6 +7,7 @@
 void main()

 {

     bool b1;

+    float array[int(mod(float (7.1), float (4.0)))];

     b1 = anyInvocation(b1);

     b1 = allInvocations(b1);

     b1 = allInvocationsEqual(b1);

diff --git a/Test/atomic_uint.frag b/Test/atomic_uint.frag
index 9a95a48..4155214 100644
--- a/Test/atomic_uint.frag
+++ b/Test/atomic_uint.frag
@@ -1,6 +1,7 @@
 #version 420 core
 
 layout(binding = 0) uniform atomic_uint counter;
+layout(binding = 0, offset = 9) uniform atomic_uint counter;
 
 uint func(atomic_uint c)
 {
@@ -41,7 +42,7 @@
 layout(binding=0, offset=32) uniform atomic_uint aOffset;

 layout(binding=0, offset=4) uniform atomic_uint;

 layout(binding=0) uniform atomic_uint bar3;           // offset is 4

-layout(binding=0) uniform atomic_uint ac[3];          // offset = 8

+layout(binding=0) uniform atomic_uint ac[2];          // offset = 8

 layout(binding=0) uniform atomic_uint ad;             // offset = 20

 layout(offset=8) uniform atomic_uint bar4;            // ERROR, no binding

 layout(binding = 0, offset = 12) uniform atomic_uint overlap;  // ERROR, overlapping offsets

diff --git a/Test/baseLegalResults/hlsl.aliasOpaque.frag.out b/Test/baseLegalResults/hlsl.aliasOpaque.frag.out
index 2e58bdd..887e4ac 100644
--- a/Test/baseLegalResults/hlsl.aliasOpaque.frag.out
+++ b/Test/baseLegalResults/hlsl.aliasOpaque.frag.out
@@ -1,6 +1,6 @@
 hlsl.aliasOpaque.frag
 // Module Version 10000
-// Generated by (magic number): 80007
+// Generated by (magic number): 80008
 // Id's are bound by 87
 
                               Capability Shader
diff --git a/Test/baseLegalResults/hlsl.flattenOpaque.frag.out b/Test/baseLegalResults/hlsl.flattenOpaque.frag.out
index d334b7e..ad9e6c1 100644
--- a/Test/baseLegalResults/hlsl.flattenOpaque.frag.out
+++ b/Test/baseLegalResults/hlsl.flattenOpaque.frag.out
@@ -1,6 +1,6 @@
 hlsl.flattenOpaque.frag
 // Module Version 10000
-// Generated by (magic number): 80007
+// Generated by (magic number): 80008
 // Id's are bound by 185
 
                               Capability Shader
diff --git a/Test/baseLegalResults/hlsl.flattenOpaqueInit.vert.out b/Test/baseLegalResults/hlsl.flattenOpaqueInit.vert.out
index 921cb96..6ed8da2 100644
--- a/Test/baseLegalResults/hlsl.flattenOpaqueInit.vert.out
+++ b/Test/baseLegalResults/hlsl.flattenOpaqueInit.vert.out
@@ -1,6 +1,6 @@
 hlsl.flattenOpaqueInit.vert
 // Module Version 10000
-// Generated by (magic number): 80007
+// Generated by (magic number): 80008
 // Id's are bound by 134
 
                               Capability Shader
diff --git a/Test/baseLegalResults/hlsl.flattenOpaqueInitMix.vert.out b/Test/baseLegalResults/hlsl.flattenOpaqueInitMix.vert.out
index 39770f4..81ab5e6 100644
--- a/Test/baseLegalResults/hlsl.flattenOpaqueInitMix.vert.out
+++ b/Test/baseLegalResults/hlsl.flattenOpaqueInitMix.vert.out
@@ -1,6 +1,6 @@
 hlsl.flattenOpaqueInitMix.vert
 // Module Version 10000
-// Generated by (magic number): 80007
+// Generated by (magic number): 80008
 // Id's are bound by 97
 
                               Capability Shader
diff --git a/Test/baseLegalResults/hlsl.flattenSubset.frag.out b/Test/baseLegalResults/hlsl.flattenSubset.frag.out
index 4628479..562070d 100644
--- a/Test/baseLegalResults/hlsl.flattenSubset.frag.out
+++ b/Test/baseLegalResults/hlsl.flattenSubset.frag.out
@@ -1,6 +1,6 @@
 hlsl.flattenSubset.frag
 // Module Version 10000
-// Generated by (magic number): 80007
+// Generated by (magic number): 80008
 // Id's are bound by 66
 
                               Capability Shader
diff --git a/Test/baseLegalResults/hlsl.flattenSubset2.frag.out b/Test/baseLegalResults/hlsl.flattenSubset2.frag.out
index 0d7ab56..5cc280b 100644
--- a/Test/baseLegalResults/hlsl.flattenSubset2.frag.out
+++ b/Test/baseLegalResults/hlsl.flattenSubset2.frag.out
@@ -1,6 +1,6 @@
 hlsl.flattenSubset2.frag
 // Module Version 10000
-// Generated by (magic number): 80007
+// Generated by (magic number): 80008
 // Id's are bound by 53
 
                               Capability Shader
diff --git a/Test/baseLegalResults/hlsl.partialFlattenLocal.vert.out b/Test/baseLegalResults/hlsl.partialFlattenLocal.vert.out
index 27482b3..f4c9c5a 100644
--- a/Test/baseLegalResults/hlsl.partialFlattenLocal.vert.out
+++ b/Test/baseLegalResults/hlsl.partialFlattenLocal.vert.out
@@ -1,6 +1,6 @@
 hlsl.partialFlattenLocal.vert
 // Module Version 10000
-// Generated by (magic number): 80007
+// Generated by (magic number): 80008
 // Id's are bound by 158
 
                               Capability Shader
diff --git a/Test/baseLegalResults/hlsl.partialFlattenMixed.vert.out b/Test/baseLegalResults/hlsl.partialFlattenMixed.vert.out
index e54fb7e..7be570b 100644
--- a/Test/baseLegalResults/hlsl.partialFlattenMixed.vert.out
+++ b/Test/baseLegalResults/hlsl.partialFlattenMixed.vert.out
@@ -1,6 +1,6 @@
 hlsl.partialFlattenMixed.vert
 // Module Version 10000
-// Generated by (magic number): 80007
+// Generated by (magic number): 80008
 // Id's are bound by 36
 
                               Capability Shader
diff --git a/Test/baseResults/100.frag.out b/Test/baseResults/100.frag.out
index 5e702e8..2ac6054 100644
--- a/Test/baseResults/100.frag.out
+++ b/Test/baseResults/100.frag.out
@@ -82,13 +82,19 @@
 ERROR: 0:193: '.length' : not supported for this version or the enabled extensions 
 ERROR: 0:194: '.' : cannot apply to an array: method
 ERROR: 0:194: 'a' : can't use function syntax on variable 
-ERROR: 0:214: 'non-constant global initializer (needs GL_EXT_shader_non_constant_global_initializers)' : not supported for this version or the enabled extensions 
+ERROR: 0:207: 'gl_SecondaryFragColorEXT' : required extension not requested: GL_EXT_blend_func_extended
+ERROR: 0:208: 'gl_SecondaryFragDataEXT' : required extension not requested: GL_EXT_blend_func_extended
+ERROR: 0:208: 'gl_MaxDualSourceDrawBuffersEXT' : required extension not requested: GL_EXT_blend_func_extended
+ERROR: 0:227: 'non-constant global initializer (needs GL_EXT_shader_non_constant_global_initializers)' : not supported for this version or the enabled extensions 
+ERROR: 0:235: '#define' : names containing consecutive underscores are reserved, and an error if version < 300: A__B
+ERROR: 0:236: 'a__b' : identifiers containing consecutive underscores ("__") are reserved, and an error if version < 300 
 ERROR: 0:3000: '#error' : line of this error should be 3000  
 ERROR: 0:3002: '' :  syntax error, unexpected IDENTIFIER, expecting LEFT_BRACE or COMMA or SEMICOLON
-ERROR: 77 compilation errors.  No code generated.
+ERROR: 82 compilation errors.  No code generated.
 
 
 Shader version: 100
+Requested GL_EXT_blend_func_extended
 Requested GL_EXT_frag_depth
 Requested GL_EXT_shader_non_constant_global_initializers
 Requested GL_EXT_shader_texture_lod
@@ -359,36 +365,76 @@
 0:201    Sequence
 0:201      Branch: Return with expression
 0:201        Function Call: fooinit( ( global mediump float)
-0:209  Function Definition: fooinit( ( global mediump float)
-0:209    Function Parameters: 
-0:211    Sequence
-0:211      Branch: Return with expression
-0:211        Constant:
-0:211          12.000000
-0:214  Sequence
-0:214    move second child to first child ( temp mediump int)
-0:214      'init1' ( global mediump int)
-0:214      Test condition and select ( temp mediump int)
-0:214        Condition
-0:214        'gl_FrontFacing' ( gl_FrontFacing bool Face)
-0:214        true case
+0:205  Function Definition: blendFuncFail( ( global void)
+0:205    Function Parameters: 
+0:207    Sequence
+0:207      move second child to first child ( temp mediump 4-component vector of float)
+0:207        'gl_SecondaryFragColorEXT' ( out mediump 4-component vector of float SecondaryFragColorEXT)
+0:207        Constant:
+0:207          1.000000
+0:207          1.000000
+0:207          1.000000
+0:207          1.000000
+0:208      move second child to first child ( temp mediump 4-component vector of float)
+0:208        direct index ( temp mediump 4-component vector of float SecondaryFragDataEXT)
+0:208          'gl_SecondaryFragDataEXT' ( out 1-element array of mediump 4-component vector of float SecondaryFragDataEXT)
+0:208          Constant:
+0:208            0 (const int)
+0:208        Constant:
+0:208          0.100000
+0:208          0.100000
+0:208          0.100000
+0:208          0.100000
+0:211  Function Definition: blendFunc( ( global void)
+0:211    Function Parameters: 
+0:213    Sequence
+0:213      move second child to first child ( temp mediump 4-component vector of float)
+0:213        'gl_SecondaryFragColorEXT' ( out mediump 4-component vector of float SecondaryFragColorEXT)
+0:213        Constant:
+0:213          1.000000
+0:213          1.000000
+0:213          1.000000
+0:213          1.000000
+0:214      move second child to first child ( temp mediump 4-component vector of float)
+0:214        direct index ( temp mediump 4-component vector of float SecondaryFragDataEXT)
+0:214          'gl_SecondaryFragDataEXT' ( out 1-element array of mediump 4-component vector of float SecondaryFragDataEXT)
+0:214          Constant:
+0:214            0 (const int)
 0:214        Constant:
-0:214          1 (const int)
-0:214        false case
-0:214        Constant:
-0:214          2 (const int)
-0:220  Sequence
-0:220    move second child to first child ( temp mediump int)
-0:220      'init2' ( global mediump int)
-0:220      Test condition and select ( temp mediump int)
-0:220        Condition
-0:220        'gl_FrontFacing' ( gl_FrontFacing bool Face)
-0:220        true case
-0:220        Constant:
-0:220          1 (const int)
-0:220        false case
-0:220        Constant:
-0:220          2 (const int)
+0:214          0.100000
+0:214          0.100000
+0:214          0.100000
+0:214          0.100000
+0:222  Function Definition: fooinit( ( global mediump float)
+0:222    Function Parameters: 
+0:224    Sequence
+0:224      Branch: Return with expression
+0:224        Constant:
+0:224          12.000000
+0:227  Sequence
+0:227    move second child to first child ( temp mediump int)
+0:227      'init1' ( global mediump int)
+0:227      Test condition and select ( temp mediump int)
+0:227        Condition
+0:227        'gl_FrontFacing' ( gl_FrontFacing bool Face)
+0:227        true case
+0:227        Constant:
+0:227          1 (const int)
+0:227        false case
+0:227        Constant:
+0:227          2 (const int)
+0:233  Sequence
+0:233    move second child to first child ( temp mediump int)
+0:233      'init2' ( global mediump int)
+0:233      Test condition and select ( temp mediump int)
+0:233        Condition
+0:233        'gl_FrontFacing' ( gl_FrontFacing bool Face)
+0:233        true case
+0:233        Constant:
+0:233          1 (const int)
+0:233        false case
+0:233        Constant:
+0:233          2 (const int)
 0:?   Linker Objects
 0:?     'a' ( global 3-element array of mediump int)
 0:?     'uint' ( global mediump int)
@@ -421,12 +467,14 @@
 0:?       5.000000
 0:?     'init1' ( global mediump int)
 0:?     'init2' ( global mediump int)
+0:?     'a__b' ( global mediump int)
 
 
 Linked fragment stage:
 
 
 Shader version: 100
+Requested GL_EXT_blend_func_extended
 Requested GL_EXT_frag_depth
 Requested GL_EXT_shader_non_constant_global_initializers
 Requested GL_EXT_shader_texture_lod
@@ -517,30 +565,30 @@
 0:152      'f124' ( global mediump float)
 0:152      Constant:
 0:152        50000000000.000000
-0:214  Sequence
-0:214    move second child to first child ( temp mediump int)
-0:214      'init1' ( global mediump int)
-0:214      Test condition and select ( temp mediump int)
-0:214        Condition
-0:214        'gl_FrontFacing' ( gl_FrontFacing bool Face)
-0:214        true case
-0:214        Constant:
-0:214          1 (const int)
-0:214        false case
-0:214        Constant:
-0:214          2 (const int)
-0:220  Sequence
-0:220    move second child to first child ( temp mediump int)
-0:220      'init2' ( global mediump int)
-0:220      Test condition and select ( temp mediump int)
-0:220        Condition
-0:220        'gl_FrontFacing' ( gl_FrontFacing bool Face)
-0:220        true case
-0:220        Constant:
-0:220          1 (const int)
-0:220        false case
-0:220        Constant:
-0:220          2 (const int)
+0:227  Sequence
+0:227    move second child to first child ( temp mediump int)
+0:227      'init1' ( global mediump int)
+0:227      Test condition and select ( temp mediump int)
+0:227        Condition
+0:227        'gl_FrontFacing' ( gl_FrontFacing bool Face)
+0:227        true case
+0:227        Constant:
+0:227          1 (const int)
+0:227        false case
+0:227        Constant:
+0:227          2 (const int)
+0:233  Sequence
+0:233    move second child to first child ( temp mediump int)
+0:233      'init2' ( global mediump int)
+0:233      Test condition and select ( temp mediump int)
+0:233        Condition
+0:233        'gl_FrontFacing' ( gl_FrontFacing bool Face)
+0:233        true case
+0:233        Constant:
+0:233          1 (const int)
+0:233        false case
+0:233        Constant:
+0:233          2 (const int)
 0:?   Linker Objects
 0:?     'a' ( global 3-element array of mediump int)
 0:?     'uint' ( global mediump int)
@@ -573,4 +621,5 @@
 0:?       5.000000
 0:?     'init1' ( global mediump int)
 0:?     'init2' ( global mediump int)
+0:?     'a__b' ( global mediump int)
 
diff --git a/Test/baseResults/120.vert.out b/Test/baseResults/120.vert.out
index 5a91ed6..6c42b75 100644
--- a/Test/baseResults/120.vert.out
+++ b/Test/baseResults/120.vert.out
@@ -79,7 +79,8 @@
 ERROR: 0:195: 'gl_ModelViewMatrix' : identifiers starting with "gl_" are reserved 
 ERROR: 0:200: 'token pasting (##)' : not supported for this version or the enabled extensions 
 ERROR: 0:203: 'token pasting (##)' : not supported for this version or the enabled extensions 
-ERROR: 80 compilation errors.  No code generated.
+ERROR: 0:205: '' :  syntax error, unexpected IDENTIFIER
+ERROR: 81 compilation errors.  No code generated.
 
 
 Shader version: 120
diff --git a/Test/baseResults/130.frag.out b/Test/baseResults/130.frag.out
index 81d055b..6115f69 100644
--- a/Test/baseResults/130.frag.out
+++ b/Test/baseResults/130.frag.out
@@ -7,33 +7,38 @@
 ERROR: 0:62: '<' :  wrong operand types: no operation '<' exists that takes a left-hand operand of type ' temp 3-component vector of bool' and a right operand of type ' temp 3-component vector of bool' (or there is no acceptable conversion)
 ERROR: 0:63: '>' :  wrong operand types: no operation '>' exists that takes a left-hand operand of type ' temp 3-component vector of uint' and a right operand of type ' temp 3-component vector of uint' (or there is no acceptable conversion)
 ERROR: 0:64: '>=' :  wrong operand types: no operation '>=' exists that takes a left-hand operand of type ' const 2-component vector of uint' and a right operand of type ' const 2-component vector of uint' (or there is no acceptable conversion)
-ERROR: 0:80: 'textureGatherOffset' : no matching overloaded function found 
-ERROR: 0:80: 'assign' :  cannot convert from ' const float' to ' temp 4-component vector of float'
-ERROR: 0:81: 'textureGatherOffset(...)' : not supported for this version or the enabled extensions 
-ERROR: 0:84: 'textureGatherOffset(...)' : not supported for this version or the enabled extensions 
-ERROR: 0:85: 'textureGatherOffset(...)' : not supported for this version or the enabled extensions 
-WARNING: 0:88: '#extension' : extension is only partially supported: GL_ARB_gpu_shader5
-ERROR: 0:120: 'line continuation' : not supported for this version or the enabled extensions 
-ERROR: 0:126: 'uniform block' : not supported for this version or the enabled extensions 
-ERROR: 0:140: 'length' : does not operate on this type:  temp bool
-ERROR: 0:140: 'boolb' : can't use function syntax on variable 
-ERROR: 0:141: 'length' : does not operate on this type:  temp float
-ERROR: 0:141: '' : function call, method, or subroutine call expected 
-ERROR: 0:141: '' : no matching overloaded function found 
-ERROR: 0:142: 'length' : incomplete method syntax 
-ERROR: 0:143: 'length' : method does not accept any arguments 
-ERROR: 0:146: 'gl_FogFragCoord' : identifiers starting with "gl_" are reserved 
-ERROR: 0:151: 'int' : must be qualified as flat in
-ERROR: 0:151: 'redeclaration' : cannot change the type of gl_FogFragCoord
-ERROR: 0:153: 'early_fragment_tests' : not supported for this version or the enabled extensions 
-ERROR: 0:154: 'image load store' : not supported for this version or the enabled extensions 
-ERROR: 0:154: 'iimage2D' : Reserved word. 
-ERROR: 0:169: 'early_fragment_tests' : can only apply to 'in' 
-ERROR: 28 compilation errors.  No code generated.
+ERROR: 0:65: 'gl_NumSamples' : required extension not requested: GL_ARB_sample_shading
+ERROR: 0:82: 'textureGatherOffset' : no matching overloaded function found 
+ERROR: 0:82: 'assign' :  cannot convert from ' const float' to ' temp 4-component vector of float'
+ERROR: 0:83: 'textureGatherOffset(...)' : not supported for this version or the enabled extensions 
+ERROR: 0:86: 'textureGatherOffset(...)' : not supported for this version or the enabled extensions 
+ERROR: 0:87: 'textureGatherOffset(...)' : not supported for this version or the enabled extensions 
+WARNING: 0:91: '#extension' : extension is only partially supported: GL_ARB_gpu_shader5
+ERROR: 0:123: 'line continuation' : not supported for this version or the enabled extensions 
+ERROR: 0:129: 'uniform block' : not supported for this version or the enabled extensions 
+ERROR: 0:143: 'length' : does not operate on this type:  temp bool
+ERROR: 0:143: 'boolb' : can't use function syntax on variable 
+ERROR: 0:144: 'length' : does not operate on this type:  temp float
+ERROR: 0:144: '' : function call, method, or subroutine call expected 
+ERROR: 0:144: '' : no matching overloaded function found 
+ERROR: 0:145: 'length' : incomplete method syntax 
+ERROR: 0:146: 'length' : method does not accept any arguments 
+ERROR: 0:149: 'gl_FogFragCoord' : identifiers starting with "gl_" are reserved 
+ERROR: 0:154: 'int' : must be qualified as flat in
+ERROR: 0:154: 'redeclaration' : cannot change the type of gl_FogFragCoord
+ERROR: 0:156: 'early_fragment_tests' : not supported for this version or the enabled extensions 
+ERROR: 0:157: 'image load store' : not supported for this version or the enabled extensions 
+ERROR: 0:157: 'iimage2D' : Reserved word. 
+ERROR: 0:172: 'early_fragment_tests' : can only apply to 'in' 
+ERROR: 0:176: 'location qualifier on uniform or buffer' : not supported for this version or the enabled extensions 
+ERROR: 30 compilation errors.  No code generated.
 
 
 Shader version: 130
+Requested GL_ARB_explicit_attrib_location
+Requested GL_ARB_explicit_uniform_location
 Requested GL_ARB_gpu_shader5
+Requested GL_ARB_sample_shading
 Requested GL_ARB_separate_shader_objects
 Requested GL_ARB_shader_image_load_store
 Requested GL_ARB_shading_language_420pack
@@ -119,259 +124,267 @@
 0:63        false (const bool)
 0:64      Constant:
 0:64        false (const bool)
-0:65      Constant:
-0:65        true (const bool)
+0:65      Sequence
+0:65        move second child to first child ( temp int)
+0:65          'samples' ( temp int)
+0:65          'gl_NumSamples' ( uniform int SampleMaskIn)
 0:66      Constant:
-0:66        false (const bool)
-0:77  Function Definition: bar23( ( global void)
-0:77    Function Parameters: 
+0:66        true (const bool)
+0:67      Constant:
+0:67        false (const bool)
+0:79  Function Definition: bar23( ( global void)
+0:79    Function Parameters: 
 0:?     Sequence
-0:80      's' ( temp 4-component vector of float)
-0:81      move second child to first child ( temp 4-component vector of float)
-0:81        's' ( temp 4-component vector of float)
-0:81        textureGatherOffset ( global 4-component vector of float)
-0:81          'samp2DR' ( uniform sampler2DRect)
-0:81          Constant:
-0:81            0.300000
-0:81            0.300000
-0:81          Constant:
-0:81            1 (const int)
-0:81            1 (const int)
-0:82      move second child to first child ( temp 4-component vector of float)
-0:82        's' ( temp 4-component vector of float)
-0:82        textureGatherOffset ( global 4-component vector of float)
-0:82          'samp2D' ( uniform sampler2D)
-0:82          Constant:
-0:82            0.300000
-0:82            0.300000
-0:82          Constant:
-0:82            1 (const int)
-0:82            1 (const int)
+0:82      's' ( temp 4-component vector of float)
 0:83      move second child to first child ( temp 4-component vector of float)
 0:83        's' ( temp 4-component vector of float)
 0:83        textureGatherOffset ( global 4-component vector of float)
-0:83          'samp2DA' ( uniform sampler2DArray)
+0:83          'samp2DR' ( uniform sampler2DRect)
 0:83          Constant:
 0:83            0.300000
 0:83            0.300000
-0:83            0.300000
 0:83          Constant:
 0:83            1 (const int)
 0:83            1 (const int)
 0:84      move second child to first child ( temp 4-component vector of float)
 0:84        's' ( temp 4-component vector of float)
 0:84        textureGatherOffset ( global 4-component vector of float)
-0:84          'samp2DS' ( uniform sampler2DShadow)
+0:84          'samp2D' ( uniform sampler2D)
 0:84          Constant:
 0:84            0.300000
 0:84            0.300000
 0:84          Constant:
-0:84            1.300000
-0:84          Constant:
 0:84            1 (const int)
 0:84            1 (const int)
 0:85      move second child to first child ( temp 4-component vector of float)
 0:85        's' ( temp 4-component vector of float)
 0:85        textureGatherOffset ( global 4-component vector of float)
-0:85          'samp2D' ( uniform sampler2D)
+0:85          'samp2DA' ( uniform sampler2DArray)
 0:85          Constant:
 0:85            0.300000
 0:85            0.300000
+0:85            0.300000
 0:85          Constant:
 0:85            1 (const int)
 0:85            1 (const int)
-0:85          Constant:
-0:85            2 (const int)
-0:90  Function Definition: bar234( ( global void)
-0:90    Function Parameters: 
+0:86      move second child to first child ( temp 4-component vector of float)
+0:86        's' ( temp 4-component vector of float)
+0:86        textureGatherOffset ( global 4-component vector of float)
+0:86          'samp2DS' ( uniform sampler2DShadow)
+0:86          Constant:
+0:86            0.300000
+0:86            0.300000
+0:86          Constant:
+0:86            1.300000
+0:86          Constant:
+0:86            1 (const int)
+0:86            1 (const int)
+0:87      move second child to first child ( temp 4-component vector of float)
+0:87        's' ( temp 4-component vector of float)
+0:87        textureGatherOffset ( global 4-component vector of float)
+0:87          'samp2D' ( uniform sampler2D)
+0:87          Constant:
+0:87            0.300000
+0:87            0.300000
+0:87          Constant:
+0:87            1 (const int)
+0:87            1 (const int)
+0:87          Constant:
+0:87            2 (const int)
+0:88      Sequence
+0:88        move second child to first child ( temp int)
+0:88          'samples' ( temp int)
+0:88          'gl_NumSamples' ( uniform int SampleMaskIn)
+0:93  Function Definition: bar234( ( global void)
+0:93    Function Parameters: 
 0:?     Sequence
-0:93      move second child to first child ( temp 4-component vector of float)
-0:93        's' ( temp 4-component vector of float)
-0:93        textureGatherOffset ( global 4-component vector of float)
-0:93          'samp2D' ( uniform sampler2D)
-0:93          Constant:
-0:93            0.300000
-0:93            0.300000
-0:93          Constant:
-0:93            1 (const int)
-0:93            1 (const int)
-0:94      move second child to first child ( temp 4-component vector of float)
-0:94        's' ( temp 4-component vector of float)
-0:94        textureGatherOffset ( global 4-component vector of float)
-0:94          'samp2DA' ( uniform sampler2DArray)
-0:94          Constant:
-0:94            0.300000
-0:94            0.300000
-0:94            0.300000
-0:94          Constant:
-0:94            1 (const int)
-0:94            1 (const int)
-0:95      move second child to first child ( temp 4-component vector of float)
-0:95        's' ( temp 4-component vector of float)
-0:95        textureGatherOffset ( global 4-component vector of float)
-0:95          'samp2DR' ( uniform sampler2DRect)
-0:95          Constant:
-0:95            0.300000
-0:95            0.300000
-0:95          Constant:
-0:95            1 (const int)
-0:95            1 (const int)
 0:96      move second child to first child ( temp 4-component vector of float)
 0:96        's' ( temp 4-component vector of float)
 0:96        textureGatherOffset ( global 4-component vector of float)
-0:96          'samp2DS' ( uniform sampler2DShadow)
+0:96          'samp2D' ( uniform sampler2D)
 0:96          Constant:
 0:96            0.300000
 0:96            0.300000
 0:96          Constant:
-0:96            1.300000
-0:96          Constant:
 0:96            1 (const int)
 0:96            1 (const int)
 0:97      move second child to first child ( temp 4-component vector of float)
 0:97        's' ( temp 4-component vector of float)
 0:97        textureGatherOffset ( global 4-component vector of float)
-0:97          'samp2D' ( uniform sampler2D)
+0:97          'samp2DA' ( uniform sampler2DArray)
 0:97          Constant:
 0:97            0.300000
 0:97            0.300000
+0:97            0.300000
 0:97          Constant:
 0:97            1 (const int)
 0:97            1 (const int)
-0:97          Constant:
-0:97            2 (const int)
-0:107  Function Definition: bar235( ( global void)
-0:107    Function Parameters: 
-0:109    Sequence
-0:109      Sequence
-0:109        move second child to first child ( temp 3-component vector of int)
-0:109          'a' ( temp 3-component vector of int)
-0:109          textureSize ( global 3-component vector of int)
-0:109            'Sca' ( uniform samplerCubeArray)
-0:109            Constant:
-0:109              3 (const int)
-0:110      Sequence
-0:110        move second child to first child ( temp 4-component vector of float)
-0:110          'b' ( temp 4-component vector of float)
-0:110          texture ( global 4-component vector of float)
-0:110            'Sca' ( uniform samplerCubeArray)
-0:110            'i' ( smooth in 4-component vector of float)
-0:111      Sequence
-0:111        move second child to first child ( temp 4-component vector of int)
-0:111          'c' ( temp 4-component vector of int)
-0:111          texture ( global 4-component vector of int)
-0:111            'Isca' ( uniform isamplerCubeArray)
-0:111            'i' ( smooth in 4-component vector of float)
-0:111            Constant:
-0:111              0.700000
+0:98      move second child to first child ( temp 4-component vector of float)
+0:98        's' ( temp 4-component vector of float)
+0:98        textureGatherOffset ( global 4-component vector of float)
+0:98          'samp2DR' ( uniform sampler2DRect)
+0:98          Constant:
+0:98            0.300000
+0:98            0.300000
+0:98          Constant:
+0:98            1 (const int)
+0:98            1 (const int)
+0:99      move second child to first child ( temp 4-component vector of float)
+0:99        's' ( temp 4-component vector of float)
+0:99        textureGatherOffset ( global 4-component vector of float)
+0:99          'samp2DS' ( uniform sampler2DShadow)
+0:99          Constant:
+0:99            0.300000
+0:99            0.300000
+0:99          Constant:
+0:99            1.300000
+0:99          Constant:
+0:99            1 (const int)
+0:99            1 (const int)
+0:100      move second child to first child ( temp 4-component vector of float)
+0:100        's' ( temp 4-component vector of float)
+0:100        textureGatherOffset ( global 4-component vector of float)
+0:100          'samp2D' ( uniform sampler2D)
+0:100          Constant:
+0:100            0.300000
+0:100            0.300000
+0:100          Constant:
+0:100            1 (const int)
+0:100            1 (const int)
+0:100          Constant:
+0:100            2 (const int)
+0:110  Function Definition: bar235( ( global void)
+0:110    Function Parameters: 
+0:112    Sequence
 0:112      Sequence
-0:112        move second child to first child ( temp 4-component vector of uint)
-0:112          'd' ( temp 4-component vector of uint)
-0:112          texture ( global 4-component vector of uint)
-0:112            'Usca' ( uniform usamplerCubeArray)
-0:112            'i' ( smooth in 4-component vector of float)
-0:114      move second child to first child ( temp 4-component vector of float)
-0:114        'b' ( temp 4-component vector of float)
-0:114        textureLod ( global 4-component vector of float)
-0:114          'Sca' ( uniform samplerCubeArray)
-0:114          'i' ( smooth in 4-component vector of float)
-0:114          Constant:
-0:114            1.700000
-0:115      move second child to first child ( temp 3-component vector of int)
-0:115        'a' ( temp 3-component vector of int)
-0:115        textureSize ( global 3-component vector of int)
-0:115          'Scas' ( uniform samplerCubeArrayShadow)
-0:115          direct index ( temp int)
-0:115            'a' ( temp 3-component vector of int)
-0:115            Constant:
-0:115              0 (const int)
-0:116      Sequence
-0:116        move second child to first child ( temp float)
-0:116          'f' ( temp float)
-0:116          texture ( global float)
-0:116            'Scas' ( uniform samplerCubeArrayShadow)
-0:116            'i' ( smooth in 4-component vector of float)
-0:116            direct index ( temp float)
-0:116              'b' ( temp 4-component vector of float)
-0:116              Constant:
-0:116                1 (const int)
-0:117      move second child to first child ( temp 4-component vector of int)
-0:117        'c' ( temp 4-component vector of int)
-0:117        textureGrad ( global 4-component vector of int)
-0:117          'Isca' ( uniform isamplerCubeArray)
+0:112        move second child to first child ( temp 3-component vector of int)
+0:112          'a' ( temp 3-component vector of int)
+0:112          textureSize ( global 3-component vector of int)
+0:112            'Sca' ( uniform samplerCubeArray)
+0:112            Constant:
+0:112              3 (const int)
+0:113      Sequence
+0:113        move second child to first child ( temp 4-component vector of float)
+0:113          'b' ( temp 4-component vector of float)
+0:113          texture ( global 4-component vector of float)
+0:113            'Sca' ( uniform samplerCubeArray)
+0:113            'i' ( smooth in 4-component vector of float)
+0:114      Sequence
+0:114        move second child to first child ( temp 4-component vector of int)
+0:114          'c' ( temp 4-component vector of int)
+0:114          texture ( global 4-component vector of int)
+0:114            'Isca' ( uniform isamplerCubeArray)
+0:114            'i' ( smooth in 4-component vector of float)
+0:114            Constant:
+0:114              0.700000
+0:115      Sequence
+0:115        move second child to first child ( temp 4-component vector of uint)
+0:115          'd' ( temp 4-component vector of uint)
+0:115          texture ( global 4-component vector of uint)
+0:115            'Usca' ( uniform usamplerCubeArray)
+0:115            'i' ( smooth in 4-component vector of float)
+0:117      move second child to first child ( temp 4-component vector of float)
+0:117        'b' ( temp 4-component vector of float)
+0:117        textureLod ( global 4-component vector of float)
+0:117          'Sca' ( uniform samplerCubeArray)
 0:117          'i' ( smooth in 4-component vector of float)
 0:117          Constant:
-0:117            0.100000
-0:117            0.100000
-0:117            0.100000
-0:117          Constant:
-0:117            0.200000
-0:117            0.200000
-0:117            0.200000
-0:129  Function Definition: bar23444( ( global void)
-0:129    Function Parameters: 
+0:117            1.700000
+0:118      move second child to first child ( temp 3-component vector of int)
+0:118        'a' ( temp 3-component vector of int)
+0:118        textureSize ( global 3-component vector of int)
+0:118          'Scas' ( uniform samplerCubeArrayShadow)
+0:118          direct index ( temp int)
+0:118            'a' ( temp 3-component vector of int)
+0:118            Constant:
+0:118              0 (const int)
+0:119      Sequence
+0:119        move second child to first child ( temp float)
+0:119          'f' ( temp float)
+0:119          texture ( global float)
+0:119            'Scas' ( uniform samplerCubeArrayShadow)
+0:119            'i' ( smooth in 4-component vector of float)
+0:119            direct index ( temp float)
+0:119              'b' ( temp 4-component vector of float)
+0:119              Constant:
+0:119                1 (const int)
+0:120      move second child to first child ( temp 4-component vector of int)
+0:120        'c' ( temp 4-component vector of int)
+0:120        textureGrad ( global 4-component vector of int)
+0:120          'Isca' ( uniform isamplerCubeArray)
+0:120          'i' ( smooth in 4-component vector of float)
+0:120          Constant:
+0:120            0.100000
+0:120            0.100000
+0:120            0.100000
+0:120          Constant:
+0:120            0.200000
+0:120            0.200000
+0:120            0.200000
+0:132  Function Definition: bar23444( ( global void)
+0:132    Function Parameters: 
 0:?     Sequence
-0:132      Sequence
-0:132        move second child to first child ( temp float)
-0:132          'a1' ( temp float)
-0:132          direct index ( temp float)
-0:132            direct index ( temp 3-component vector of float)
-0:132              'm43' ( temp 4X3 matrix of float)
-0:132              Constant:
-0:132                3 (const int)
-0:132            Constant:
-0:132              1 (const int)
-0:134      Sequence
-0:134        move second child to first child ( temp int)
-0:134          'a2' ( temp int)
-0:134          Constant:
-0:134            4 (const int)
-0:135      add second child into first child ( temp int)
-0:135        'a2' ( temp int)
-0:135        Constant:
-0:135          3 (const int)
-0:136      add second child into first child ( temp int)
-0:136        'a2' ( temp int)
-0:136        Constant:
-0:136          3 (const int)
+0:135      Sequence
+0:135        move second child to first child ( temp float)
+0:135          'a1' ( temp float)
+0:135          direct index ( temp float)
+0:135            direct index ( temp 3-component vector of float)
+0:135              'm43' ( temp 4X3 matrix of float)
+0:135              Constant:
+0:135                3 (const int)
+0:135            Constant:
+0:135              1 (const int)
 0:137      Sequence
-0:137        move second child to first child ( temp float)
-0:137          'b' ( const (read only) float)
-0:137          component-wise multiply ( temp float)
-0:137            Constant:
-0:137              2.000000
-0:137            'a1' ( temp float)
-0:138      move second child to first child ( temp float)
-0:138        direct index ( temp float)
-0:138          'a' ( global 3-component vector of float)
-0:138          Constant:
-0:138            0 (const int)
+0:137        move second child to first child ( temp int)
+0:137          'a2' ( temp int)
+0:137          Constant:
+0:137            4 (const int)
+0:138      add second child into first child ( temp int)
+0:138        'a2' ( temp int)
 0:138        Constant:
-0:138          -1.000000
-0:140      Constant:
-0:140        0.000000
-0:141      Constant:
-0:141        0.000000
+0:138          3 (const int)
+0:139      add second child into first child ( temp int)
+0:139        'a2' ( temp int)
+0:139        Constant:
+0:139          3 (const int)
+0:140      Sequence
+0:140        move second child to first child ( temp float)
+0:140          'b' ( const (read only) float)
+0:140          component-wise multiply ( temp float)
+0:140            Constant:
+0:140              2.000000
+0:140            'a1' ( temp float)
+0:141      move second child to first child ( temp float)
+0:141        direct index ( temp float)
+0:141          'a' ( global 3-component vector of float)
+0:141          Constant:
+0:141            0 (const int)
+0:141        Constant:
+0:141          -1.000000
 0:143      Constant:
-0:143        1 (const int)
-0:162  Function Definition: qux2( ( global void)
-0:162    Function Parameters: 
+0:143        0.000000
+0:144      Constant:
+0:144        0.000000
+0:146      Constant:
+0:146        1 (const int)
+0:165  Function Definition: qux2( ( global void)
+0:165    Function Parameters: 
 0:?     Sequence
-0:165      imageAtomicCompSwap ( global int)
-0:165        'iimg2D' (layout( r32i) uniform iimage2D)
-0:165        Construct ivec2 ( temp 2-component vector of int)
-0:165          'i' ( temp int)
-0:165          'i' ( temp int)
-0:165        'i' ( temp int)
-0:165        'i' ( temp int)
-0:166      Sequence
-0:166        move second child to first child ( temp 4-component vector of int)
-0:166          'pos' ( temp 4-component vector of int)
-0:166          imageLoad ( global 4-component vector of int)
-0:166            'iimg2D' (layout( r32i) uniform iimage2D)
-0:166            Construct ivec2 ( temp 2-component vector of int)
-0:166              'i' ( temp int)
-0:166              'i' ( temp int)
+0:168      imageAtomicCompSwap ( global int)
+0:168        'iimg2D' (layout( r32i) uniform iimage2D)
+0:168        Construct ivec2 ( temp 2-component vector of int)
+0:168          'i' ( temp int)
+0:168          'i' ( temp int)
+0:168        'i' ( temp int)
+0:168        'i' ( temp int)
+0:169      Sequence
+0:169        move second child to first child ( temp 4-component vector of int)
+0:169          'pos' ( temp 4-component vector of int)
+0:169          imageLoad ( global 4-component vector of int)
+0:169            'iimg2D' (layout( r32i) uniform iimage2D)
+0:169            Construct ivec2 ( temp 2-component vector of int)
+0:169              'i' ( temp int)
+0:169              'i' ( temp int)
 0:?   Linker Objects
 0:?     'a' ( global 3-component vector of float)
 0:?     'b' ( global float)
@@ -402,13 +415,18 @@
 0:?     'gl_FogFragCoord' ( smooth in float)
 0:?     'iimg2Dbad' (layout( r32i) uniform iimage2D)
 0:?     'iimg2D' (layout( r32i) uniform iimage2D)
+0:?     'ucolor0' (layout( location=3) uniform 4-component vector of float)
+0:?     'ucolor1' (layout( location=4) uniform 4-component vector of float)
 
 
 Linked fragment stage:
 
 
 Shader version: 130
+Requested GL_ARB_explicit_attrib_location
+Requested GL_ARB_explicit_uniform_location
 Requested GL_ARB_gpu_shader5
+Requested GL_ARB_sample_shading
 Requested GL_ARB_separate_shader_objects
 Requested GL_ARB_shader_image_load_store
 Requested GL_ARB_shading_language_420pack
@@ -457,4 +475,6 @@
 0:?     'gl_FogFragCoord' ( smooth in float)
 0:?     'iimg2Dbad' (layout( r32i) uniform iimage2D)
 0:?     'iimg2D' (layout( r32i) uniform iimage2D)
+0:?     'ucolor0' (layout( location=3) uniform 4-component vector of float)
+0:?     'ucolor1' (layout( location=4) uniform 4-component vector of float)
 
diff --git a/Test/baseResults/140.frag.out b/Test/baseResults/140.frag.out
index 7ce2170..702718a 100644
--- a/Test/baseResults/140.frag.out
+++ b/Test/baseResults/140.frag.out
@@ -1,14 +1,15 @@
 140.frag
 WARNING: 0:3: varying deprecated in version 130; may be removed in future release
 ERROR: 0:17: '#error' : GL_ES is not set  
-ERROR: 0:20: 'fragment-shader struct input' : not supported for this version or the enabled extensions 
-ERROR: 0:24: 'location' : not supported for this version or the enabled extensions 
-ERROR: 0:24: 'location qualifier on input' : not supported for this version or the enabled extensions 
-ERROR: 0:26: 'location' : not supported for this version or the enabled extensions 
-ERROR: 0:26: 'location qualifier on output' : not supported for this version or the enabled extensions 
-ERROR: 0:40: 'assign' :  l-value required "v" (can't modify shader input)
-ERROR: 0:40: 'out' : Non-L-value cannot be passed for 'out' or 'inout' parameters. 
-ERROR: 8 compilation errors.  No code generated.
+ERROR: 0:21: 'fragment-shader struct input' : not supported for this version or the enabled extensions 
+ERROR: 0:25: 'location' : not supported for this version or the enabled extensions 
+ERROR: 0:25: 'location qualifier on input' : not supported for this version or the enabled extensions 
+ERROR: 0:27: 'location' : not supported for this version or the enabled extensions 
+ERROR: 0:27: 'location qualifier on output' : not supported for this version or the enabled extensions 
+ERROR: 0:41: 'assign' :  l-value required "v" (can't modify shader input)
+ERROR: 0:41: 'out' : Non-L-value cannot be passed for 'out' or 'inout' parameters. 
+ERROR: 0:56: '' :  syntax error, unexpected IDENTIFIER, expecting LEFT_BRACE or COMMA or SEMICOLON
+ERROR: 9 compilation errors.  No code generated.
 
 
 Shader version: 140
@@ -25,80 +26,80 @@
 0:12            'gl_ClipDistance' ( smooth in 5-element array of float ClipDistance)
 0:12            Constant:
 0:12              2 (const int)
-0:22  Sequence
-0:22    move second child to first child ( temp float)
-0:22      'patch' ( global float)
-0:22      Constant:
-0:22        3.100000
-0:38  Function Definition: foo( ( global void)
-0:38    Function Parameters: 
-0:40    Sequence
-0:40      Sequence
-0:40        move second child to first child ( temp 2-component vector of float)
-0:40          'r1' ( temp 2-component vector of float)
-0:40          modf ( global 2-component vector of float)
-0:40            vector swizzle ( temp 2-component vector of float)
-0:40              'v' ( smooth in 4-component vector of float)
-0:40              Sequence
-0:40                Constant:
-0:40                  0 (const int)
-0:40                Constant:
-0:40                  1 (const int)
-0:40            vector swizzle ( temp 2-component vector of float)
-0:40              'v' ( smooth in 4-component vector of float)
-0:40              Sequence
-0:40                Constant:
-0:40                  2 (const int)
-0:40                Constant:
-0:40                  3 (const int)
+0:23  Sequence
+0:23    move second child to first child ( temp float)
+0:23      'patch' ( global float)
+0:23      Constant:
+0:23        3.100000
+0:39  Function Definition: foo( ( global void)
+0:39    Function Parameters: 
+0:41    Sequence
 0:41      Sequence
 0:41        move second child to first child ( temp 2-component vector of float)
-0:41          'r2' ( temp 2-component vector of float)
+0:41          'r1' ( temp 2-component vector of float)
 0:41          modf ( global 2-component vector of float)
 0:41            vector swizzle ( temp 2-component vector of float)
-0:41              'o' ( out 4-component vector of float)
+0:41              'v' ( smooth in 4-component vector of float)
 0:41              Sequence
 0:41                Constant:
 0:41                  0 (const int)
 0:41                Constant:
 0:41                  1 (const int)
 0:41            vector swizzle ( temp 2-component vector of float)
-0:41              'o' ( out 4-component vector of float)
+0:41              'v' ( smooth in 4-component vector of float)
 0:41              Sequence
 0:41                Constant:
 0:41                  2 (const int)
 0:41                Constant:
 0:41                  3 (const int)
-0:42      move second child to first child ( temp float)
-0:42        direct index ( temp float)
-0:42          'o' ( out 4-component vector of float)
-0:42          Constant:
-0:42            2 (const int)
-0:42        Function Call: fooi( ( global float)
-0:47  Sequence
-0:47    move second child to first child ( temp float)
-0:47      'i1' ( global float)
-0:47      Test condition and select ( temp float)
-0:47        Condition
-0:47        'gl_FrontFacing' ( gl_FrontFacing bool Face)
-0:47        true case
-0:47        Constant:
-0:47          -2.000000
-0:47        false case
-0:47        Constant:
-0:47          2.000000
+0:42      Sequence
+0:42        move second child to first child ( temp 2-component vector of float)
+0:42          'r2' ( temp 2-component vector of float)
+0:42          modf ( global 2-component vector of float)
+0:42            vector swizzle ( temp 2-component vector of float)
+0:42              'o' ( out 4-component vector of float)
+0:42              Sequence
+0:42                Constant:
+0:42                  0 (const int)
+0:42                Constant:
+0:42                  1 (const int)
+0:42            vector swizzle ( temp 2-component vector of float)
+0:42              'o' ( out 4-component vector of float)
+0:42              Sequence
+0:42                Constant:
+0:42                  2 (const int)
+0:42                Constant:
+0:42                  3 (const int)
+0:43      move second child to first child ( temp float)
+0:43        direct index ( temp float)
+0:43          'o' ( out 4-component vector of float)
+0:43          Constant:
+0:43            2 (const int)
+0:43        Function Call: fooi( ( global float)
 0:48  Sequence
 0:48    move second child to first child ( temp float)
-0:48      'i2' ( global float)
-0:48      Constant:
-0:48        102.000000
-0:50  Function Definition: fooi( ( global float)
-0:50    Function Parameters: 
-0:52    Sequence
-0:52      Branch: Return with expression
-0:52        add ( temp float)
-0:52          'i1' ( global float)
-0:52          'i2' ( global float)
+0:48      'i1' ( global float)
+0:48      Test condition and select ( temp float)
+0:48        Condition
+0:48        'gl_FrontFacing' ( gl_FrontFacing bool Face)
+0:48        true case
+0:48        Constant:
+0:48          -2.000000
+0:48        false case
+0:48        Constant:
+0:48          2.000000
+0:49  Sequence
+0:49    move second child to first child ( temp float)
+0:49      'i2' ( global float)
+0:49      Constant:
+0:49        102.000000
+0:51  Function Definition: fooi( ( global float)
+0:51    Function Parameters: 
+0:53    Sequence
+0:53      Branch: Return with expression
+0:53        add ( temp float)
+0:53          'i1' ( global float)
+0:53          'i2' ( global float)
 0:?   Linker Objects
 0:?     'v' ( smooth in 4-component vector of float)
 0:?     'i' ( smooth in 4-component vector of float)
@@ -131,28 +132,28 @@
 0:12            'gl_ClipDistance' ( smooth in 5-element array of float ClipDistance)
 0:12            Constant:
 0:12              2 (const int)
-0:22  Sequence
-0:22    move second child to first child ( temp float)
-0:22      'patch' ( global float)
-0:22      Constant:
-0:22        3.100000
-0:47  Sequence
-0:47    move second child to first child ( temp float)
-0:47      'i1' ( global float)
-0:47      Test condition and select ( temp float)
-0:47        Condition
-0:47        'gl_FrontFacing' ( gl_FrontFacing bool Face)
-0:47        true case
-0:47        Constant:
-0:47          -2.000000
-0:47        false case
-0:47        Constant:
-0:47          2.000000
+0:23  Sequence
+0:23    move second child to first child ( temp float)
+0:23      'patch' ( global float)
+0:23      Constant:
+0:23        3.100000
 0:48  Sequence
 0:48    move second child to first child ( temp float)
-0:48      'i2' ( global float)
-0:48      Constant:
-0:48        102.000000
+0:48      'i1' ( global float)
+0:48      Test condition and select ( temp float)
+0:48        Condition
+0:48        'gl_FrontFacing' ( gl_FrontFacing bool Face)
+0:48        true case
+0:48        Constant:
+0:48          -2.000000
+0:48        false case
+0:48        Constant:
+0:48          2.000000
+0:49  Sequence
+0:49    move second child to first child ( temp float)
+0:49      'i2' ( global float)
+0:49      Constant:
+0:49        102.000000
 0:?   Linker Objects
 0:?     'v' ( smooth in 4-component vector of float)
 0:?     'i' ( smooth in 4-component vector of float)
diff --git a/Test/baseResults/150.frag.out b/Test/baseResults/150.frag.out
index 1454b55..7672b58 100644
--- a/Test/baseResults/150.frag.out
+++ b/Test/baseResults/150.frag.out
@@ -3,10 +3,30 @@
 ERROR: 0:5: 'redeclaration' : cannot redeclare with different qualification: gl_FragCoord
 ERROR: 0:6: 'layout qualifier' : can only apply origin_upper_left and pixel_center_origin to gl_FragCoord 
 ERROR: 0:14: 'gl_FragCoord' : cannot redeclare after use 
-ERROR: 4 compilation errors.  No code generated.
+ERROR: 0:50: 'gl_PerFragment' : cannot be used (maybe an instance name is needed) 
+ERROR: 0:50: 'gl_PerFragment' : undeclared identifier 
+ERROR: 0:53: 'double' : Reserved word. 
+ERROR: 0:53: 'double' : not supported for this version or the enabled extensions 
+ERROR: 0:53: 'double' : must be qualified as flat in
+ERROR: 0:57: '=' :  cannot convert from ' global double' to ' global int'
+ERROR: 0:80: 'floatBitsToInt' : required extension not requested: GL_ARB_shader_bit_encoding
+ERROR: 0:100: 'packSnorm2x16' : required extension not requested: GL_ARB_shading_language_packing
+ERROR: 0:114: 'textureQueryLod' : required extension not requested: GL_ARB_texture_query_lod
+ERROR: 0:115: 'textureQueryLod' : required extension not requested: GL_ARB_texture_query_lod
+ERROR: 0:154: 'textureQueryLod' : no matching overloaded function found 
+ERROR: 0:154: 'assign' :  cannot convert from ' const float' to ' temp 2-component vector of float'
+ERROR: 0:155: 'textureQueryLod' : no matching overloaded function found 
+ERROR: 0:155: 'assign' :  cannot convert from ' const float' to ' temp 2-component vector of float'
+ERROR: 0:183: 'mix' : required extension not requested: GL_EXT_shader_integer_mix
+ERROR: 19 compilation errors.  No code generated.
 
 
 Shader version: 150
+Requested GL_ARB_gpu_shader_fp64
+Requested GL_ARB_shader_bit_encoding
+Requested GL_ARB_shading_language_packing
+Requested GL_ARB_texture_query_lod
+Requested GL_EXT_shader_integer_mix
 gl_FragCoord pixel center is integer
 gl_FragCoord origin is upper left
 ERROR: node is still EOpNull!
@@ -106,6 +126,296 @@
 0:49    Sequence
 0:49      Branch: Return with expression
 0:49        'gl_PrimitiveID' ( flat in int PrimitiveID)
+0:50      'gl_PerFragment' ( temp float)
+0:56  Sequence
+0:56    move second child to first child ( temp double)
+0:56      'type3' ( global double)
+0:56      Constant:
+0:56        2.000000
+0:58  Sequence
+0:58    move second child to first child ( temp double)
+0:58      'absTest2' ( global double)
+0:58      sqrt ( global double)
+0:58        'type3' ( global double)
+0:59  Sequence
+0:59    move second child to first child ( temp double)
+0:59      'absTest3' ( global double)
+0:59      Constant:
+0:59        1.414214
+0:60  Sequence
+0:60    move second child to first child ( temp float)
+0:60      'dk' ( global float)
+0:60      Constant:
+0:60        3.316625
+0:68  Function Definition: bitEncodingPass( ( global void)
+0:68    Function Parameters: 
+0:70    Sequence
+0:70      Sequence
+0:70        move second child to first child ( temp int)
+0:70          'i' ( temp int)
+0:70          floatBitsToInt ( global int)
+0:70            'f' ( global float)
+0:71      Sequence
+0:71        move second child to first child ( temp 4-component vector of uint)
+0:71          'uv11' ( temp 4-component vector of uint)
+0:71          floatBitsToUint ( global 4-component vector of uint)
+0:71            'v4' ( global 4-component vector of float)
+0:72      Sequence
+0:72        move second child to first child ( temp 4-component vector of float)
+0:72          'v14' ( temp 4-component vector of float)
+0:72          intBitsToFloat ( global 4-component vector of float)
+0:72            'iv4a' ( global 4-component vector of int)
+0:73      Sequence
+0:73        move second child to first child ( temp 2-component vector of float)
+0:73          'v15' ( temp 2-component vector of float)
+0:73          uintBitsToFloat ( global 2-component vector of float)
+0:73            'uv2c' ( global 2-component vector of uint)
+0:78  Function Definition: bitEncodingFail( ( global void)
+0:78    Function Parameters: 
+0:80    Sequence
+0:80      Sequence
+0:80        move second child to first child ( temp int)
+0:80          'i' ( temp int)
+0:80          floatBitsToInt ( global int)
+0:80            'f' ( global float)
+0:87  Function Definition: packingPass( ( global void)
+0:87    Function Parameters: 
+0:89    Sequence
+0:89      Sequence
+0:89        move second child to first child ( temp uint)
+0:89          'u19' ( temp uint)
+0:89          packSnorm2x16 ( global uint)
+0:89            'v2a' ( global 2-component vector of float)
+0:90      Sequence
+0:90        move second child to first child ( temp 2-component vector of float)
+0:90          'v20' ( temp 2-component vector of float)
+0:90          unpackSnorm2x16 ( global 2-component vector of float)
+0:90            'uy' ( global uint)
+0:91      Sequence
+0:91        move second child to first child ( temp uint)
+0:91          'u15' ( temp uint)
+0:91          packUnorm2x16 ( global uint)
+0:91            'v2a' ( global 2-component vector of float)
+0:92      Sequence
+0:92        move second child to first child ( temp 2-component vector of float)
+0:92          'v16' ( temp 2-component vector of float)
+0:92          unpackUnorm2x16 ( global 2-component vector of float)
+0:92            'uy' ( global uint)
+0:93      Sequence
+0:93        move second child to first child ( temp uint)
+0:93          'u17' ( temp uint)
+0:93          packHalf2x16 ( global uint)
+0:93            'v2a' ( global 2-component vector of float)
+0:94      Sequence
+0:94        move second child to first child ( temp 2-component vector of float)
+0:94          'v18' ( temp 2-component vector of float)
+0:94          unpackHalf2x16 ( global 2-component vector of float)
+0:94            'uy' ( global uint)
+0:98  Function Definition: packingFail( ( global void)
+0:98    Function Parameters: 
+0:100    Sequence
+0:100      Sequence
+0:100        move second child to first child ( temp uint)
+0:100          'u19' ( temp uint)
+0:100          packSnorm2x16 ( global uint)
+0:100            'v2a' ( global 2-component vector of float)
+0:107  Function Definition: qlodFail( ( global void)
+0:107    Function Parameters: 
+0:?     Sequence
+0:114      move second child to first child ( temp 2-component vector of float)
+0:114        'lod' ( temp 2-component vector of float)
+0:114        textureQueryLod ( global 2-component vector of float)
+0:114          'samp1D' ( uniform sampler1D)
+0:114          'pf' ( temp float)
+0:115      move second child to first child ( temp 2-component vector of float)
+0:115        'lod' ( temp 2-component vector of float)
+0:115        textureQueryLod ( global 2-component vector of float)
+0:115          'samp2Ds' ( uniform sampler2DShadow)
+0:115          'pf2' ( temp 2-component vector of float)
+0:134  Function Definition: qlodPass( ( global void)
+0:134    Function Parameters: 
+0:?     Sequence
+0:141      move second child to first child ( temp 2-component vector of float)
+0:141        'lod' ( temp 2-component vector of float)
+0:141        textureQueryLod ( global 2-component vector of float)
+0:141          'samp1D' ( uniform sampler1D)
+0:141          'pf' ( temp float)
+0:142      move second child to first child ( temp 2-component vector of float)
+0:142        'lod' ( temp 2-component vector of float)
+0:142        textureQueryLod ( global 2-component vector of float)
+0:142          'isamp2D' ( uniform isampler2D)
+0:142          'pf2' ( temp 2-component vector of float)
+0:143      move second child to first child ( temp 2-component vector of float)
+0:143        'lod' ( temp 2-component vector of float)
+0:143        textureQueryLod ( global 2-component vector of float)
+0:143          'usamp3D' ( uniform usampler3D)
+0:143          'pf3' ( temp 3-component vector of float)
+0:144      move second child to first child ( temp 2-component vector of float)
+0:144        'lod' ( temp 2-component vector of float)
+0:144        textureQueryLod ( global 2-component vector of float)
+0:144          'sampCube' ( uniform samplerCube)
+0:144          'pf3' ( temp 3-component vector of float)
+0:145      move second child to first child ( temp 2-component vector of float)
+0:145        'lod' ( temp 2-component vector of float)
+0:145        textureQueryLod ( global 2-component vector of float)
+0:145          'isamp1DA' ( uniform isampler1DArray)
+0:145          'pf' ( temp float)
+0:146      move second child to first child ( temp 2-component vector of float)
+0:146        'lod' ( temp 2-component vector of float)
+0:146        textureQueryLod ( global 2-component vector of float)
+0:146          'usamp2DA' ( uniform usampler2DArray)
+0:146          'pf2' ( temp 2-component vector of float)
+0:148      move second child to first child ( temp 2-component vector of float)
+0:148        'lod' ( temp 2-component vector of float)
+0:148        textureQueryLod ( global 2-component vector of float)
+0:148          'samp1Ds' ( uniform sampler1DShadow)
+0:148          'pf' ( temp float)
+0:149      move second child to first child ( temp 2-component vector of float)
+0:149        'lod' ( temp 2-component vector of float)
+0:149        textureQueryLod ( global 2-component vector of float)
+0:149          'samp2Ds' ( uniform sampler2DShadow)
+0:149          'pf2' ( temp 2-component vector of float)
+0:150      move second child to first child ( temp 2-component vector of float)
+0:150        'lod' ( temp 2-component vector of float)
+0:150        textureQueryLod ( global 2-component vector of float)
+0:150          'sampCubes' ( uniform samplerCubeShadow)
+0:150          'pf3' ( temp 3-component vector of float)
+0:151      move second child to first child ( temp 2-component vector of float)
+0:151        'lod' ( temp 2-component vector of float)
+0:151        textureQueryLod ( global 2-component vector of float)
+0:151          'samp1DAs' ( uniform sampler1DArrayShadow)
+0:151          'pf' ( temp float)
+0:152      move second child to first child ( temp 2-component vector of float)
+0:152        'lod' ( temp 2-component vector of float)
+0:152        textureQueryLod ( global 2-component vector of float)
+0:152          'samp2DAs' ( uniform sampler2DArrayShadow)
+0:152          'pf2' ( temp 2-component vector of float)
+0:154      'lod' ( temp 2-component vector of float)
+0:155      'lod' ( temp 2-component vector of float)
+0:164  Function Definition: testmix( ( global void)
+0:164    Function Parameters: 
+0:166    Sequence
+0:166      Sequence
+0:166        move second child to first child ( temp int)
+0:166          'ival' ( temp int)
+0:166          mix ( global int)
+0:166            'x' ( global int)
+0:166            'y' ( global int)
+0:166            'b' ( global bool)
+0:167      Sequence
+0:167        move second child to first child ( temp 2-component vector of int)
+0:167          'iv2' ( temp 2-component vector of int)
+0:167          mix ( global 2-component vector of int)
+0:167            Construct ivec2 ( temp 2-component vector of int)
+0:167              'x' ( global int)
+0:167            Construct ivec2 ( temp 2-component vector of int)
+0:167              'y' ( global int)
+0:167            Construct bvec2 ( temp 2-component vector of bool)
+0:167              'b' ( global bool)
+0:168      Sequence
+0:168        move second child to first child ( temp 3-component vector of int)
+0:168          'iv3' ( temp 3-component vector of int)
+0:168          mix ( global 3-component vector of int)
+0:168            Construct ivec3 ( temp 3-component vector of int)
+0:168              'x' ( global int)
+0:168            Construct ivec3 ( temp 3-component vector of int)
+0:168              'y' ( global int)
+0:168            Construct bvec3 ( temp 3-component vector of bool)
+0:168              'b' ( global bool)
+0:169      Sequence
+0:169        move second child to first child ( temp 4-component vector of int)
+0:169          'iv4' ( temp 4-component vector of int)
+0:169          mix ( global 4-component vector of int)
+0:169            Construct ivec4 ( temp 4-component vector of int)
+0:169              'x' ( global int)
+0:169            Construct ivec4 ( temp 4-component vector of int)
+0:169              'x' ( global int)
+0:169            Construct bvec4 ( temp 4-component vector of bool)
+0:169              'b' ( global bool)
+0:170      Sequence
+0:170        move second child to first child ( temp uint)
+0:170          'uiv' ( temp uint)
+0:170          mix ( global uint)
+0:170            'z' ( global uint)
+0:170            'w' ( global uint)
+0:170            'b' ( global bool)
+0:171      Sequence
+0:171        move second child to first child ( temp 2-component vector of uint)
+0:171          'uv2' ( temp 2-component vector of uint)
+0:171          mix ( global 2-component vector of uint)
+0:171            Construct uvec2 ( temp 2-component vector of uint)
+0:171              'z' ( global uint)
+0:171            Construct uvec2 ( temp 2-component vector of uint)
+0:171              'z' ( global uint)
+0:171            Construct bvec2 ( temp 2-component vector of bool)
+0:171              'b' ( global bool)
+0:172      Sequence
+0:172        move second child to first child ( temp 3-component vector of uint)
+0:172          'uv3' ( temp 3-component vector of uint)
+0:172          mix ( global 3-component vector of uint)
+0:172            Construct uvec3 ( temp 3-component vector of uint)
+0:172              'z' ( global uint)
+0:172            Construct uvec3 ( temp 3-component vector of uint)
+0:172              'z' ( global uint)
+0:172            Construct bvec3 ( temp 3-component vector of bool)
+0:172              'b' ( global bool)
+0:173      Sequence
+0:173        move second child to first child ( temp 4-component vector of uint)
+0:173          'uv4' ( temp 4-component vector of uint)
+0:173          mix ( global 4-component vector of uint)
+0:173            Construct uvec4 ( temp 4-component vector of uint)
+0:173              'z' ( global uint)
+0:173            Construct uvec4 ( temp 4-component vector of uint)
+0:173              'z' ( global uint)
+0:173            Construct bvec4 ( temp 4-component vector of bool)
+0:173              'b' ( global bool)
+0:174      Sequence
+0:174        move second child to first child ( temp bool)
+0:174          'bv' ( temp bool)
+0:174          mix ( global bool)
+0:174            'b1' ( global bool)
+0:174            'b2' ( global bool)
+0:174            'b' ( global bool)
+0:175      Sequence
+0:175        move second child to first child ( temp 2-component vector of bool)
+0:175          'bv2' ( temp 2-component vector of bool)
+0:175          mix ( global 2-component vector of bool)
+0:175            Construct bvec2 ( temp 2-component vector of bool)
+0:175              'b1' ( global bool)
+0:175            Construct bvec2 ( temp 2-component vector of bool)
+0:175              'b2' ( global bool)
+0:175            Construct bvec2 ( temp 2-component vector of bool)
+0:175              'b' ( global bool)
+0:176      Sequence
+0:176        move second child to first child ( temp 3-component vector of bool)
+0:176          'bv3' ( temp 3-component vector of bool)
+0:176          mix ( global 3-component vector of bool)
+0:176            Construct bvec3 ( temp 3-component vector of bool)
+0:176              'b1' ( global bool)
+0:176            Construct bvec3 ( temp 3-component vector of bool)
+0:176              'b2' ( global bool)
+0:176            Construct bvec3 ( temp 3-component vector of bool)
+0:176              'b' ( global bool)
+0:177      Sequence
+0:177        move second child to first child ( temp 4-component vector of bool)
+0:177          'bv4' ( temp 4-component vector of bool)
+0:177          mix ( global 4-component vector of bool)
+0:177            Construct bvec4 ( temp 4-component vector of bool)
+0:177              'b1' ( global bool)
+0:177            Construct bvec4 ( temp 4-component vector of bool)
+0:177              'b2' ( global bool)
+0:177            Construct bvec4 ( temp 4-component vector of bool)
+0:177              'b' ( global bool)
+0:181  Function Definition: testmixFail( ( global void)
+0:181    Function Parameters: 
+0:183    Sequence
+0:183      Sequence
+0:183        move second child to first child ( temp int)
+0:183          'ival' ( temp int)
+0:183          mix ( global int)
+0:183            'x' ( global int)
+0:183            'y' ( global int)
+0:183            'b' ( global bool)
 0:?   Linker Objects
 0:?     'gl_FragCoord' ( gl_FragCoord 4-component vector of float FragCoord)
 0:?     'foo' ( smooth in 4-component vector of float)
@@ -120,12 +430,50 @@
 0:?     'p2' ( flat in 2-component vector of int)
 0:?     'p3' ( flat in 3-component vector of int)
 0:?     'samp' ( flat in int)
+0:?     'type1' ( smooth in double)
+0:?     'type2' ( global double)
+0:?     'type3' ( global double)
+0:?     'absTest' ( global int)
+0:?     'absTest2' ( global double)
+0:?     'absTest3' ( global double)
+0:?     'dk' ( global float)
+0:?     'f' ( global float)
+0:?     'v4' ( global 4-component vector of float)
+0:?     'iv4a' ( global 4-component vector of int)
+0:?     'uv2c' ( global 2-component vector of uint)
+0:?     'v2a' ( global 2-component vector of float)
+0:?     'uy' ( global uint)
+0:?     'samp1D' ( uniform sampler1D)
+0:?     'samp2Ds' ( uniform sampler2DShadow)
+0:?     'isamp2D' ( uniform isampler2D)
+0:?     'usamp3D' ( uniform usampler3D)
+0:?     'sampCube' ( uniform samplerCube)
+0:?     'isamp1DA' ( uniform isampler1DArray)
+0:?     'usamp2DA' ( uniform usampler2DArray)
+0:?     'samp1Ds' ( uniform sampler1DShadow)
+0:?     'sampCubes' ( uniform samplerCubeShadow)
+0:?     'samp1DAs' ( uniform sampler1DArrayShadow)
+0:?     'samp2DAs' ( uniform sampler2DArrayShadow)
+0:?     'sampBuf' ( uniform samplerBuffer)
+0:?     'sampRect' ( uniform sampler2DRect)
+0:?     'b1' ( global bool)
+0:?     'b2' ( global bool)
+0:?     'b' ( global bool)
+0:?     'x' ( global int)
+0:?     'y' ( global int)
+0:?     'z' ( global uint)
+0:?     'w' ( global uint)
 
 
 Linked fragment stage:
 
 
 Shader version: 150
+Requested GL_ARB_gpu_shader_fp64
+Requested GL_ARB_shader_bit_encoding
+Requested GL_ARB_shading_language_packing
+Requested GL_ARB_texture_query_lod
+Requested GL_EXT_shader_integer_mix
 gl_FragCoord pixel center is integer
 gl_FragCoord origin is upper left
 ERROR: node is still EOpNull!
@@ -141,6 +489,26 @@
 0:18      'patch' ( global float)
 0:18      Constant:
 0:18        3.100000
+0:56  Sequence
+0:56    move second child to first child ( temp double)
+0:56      'type3' ( global double)
+0:56      Constant:
+0:56        2.000000
+0:58  Sequence
+0:58    move second child to first child ( temp double)
+0:58      'absTest2' ( global double)
+0:58      sqrt ( global double)
+0:58        'type3' ( global double)
+0:59  Sequence
+0:59    move second child to first child ( temp double)
+0:59      'absTest3' ( global double)
+0:59      Constant:
+0:59        1.414214
+0:60  Sequence
+0:60    move second child to first child ( temp float)
+0:60      'dk' ( global float)
+0:60      Constant:
+0:60        3.316625
 0:?   Linker Objects
 0:?     'gl_FragCoord' ( gl_FragCoord 4-component vector of float FragCoord)
 0:?     'foo' ( smooth in 4-component vector of float)
@@ -155,4 +523,37 @@
 0:?     'p2' ( flat in 2-component vector of int)
 0:?     'p3' ( flat in 3-component vector of int)
 0:?     'samp' ( flat in int)
+0:?     'type1' ( smooth in double)
+0:?     'type2' ( global double)
+0:?     'type3' ( global double)
+0:?     'absTest' ( global int)
+0:?     'absTest2' ( global double)
+0:?     'absTest3' ( global double)
+0:?     'dk' ( global float)
+0:?     'f' ( global float)
+0:?     'v4' ( global 4-component vector of float)
+0:?     'iv4a' ( global 4-component vector of int)
+0:?     'uv2c' ( global 2-component vector of uint)
+0:?     'v2a' ( global 2-component vector of float)
+0:?     'uy' ( global uint)
+0:?     'samp1D' ( uniform sampler1D)
+0:?     'samp2Ds' ( uniform sampler2DShadow)
+0:?     'isamp2D' ( uniform isampler2D)
+0:?     'usamp3D' ( uniform usampler3D)
+0:?     'sampCube' ( uniform samplerCube)
+0:?     'isamp1DA' ( uniform isampler1DArray)
+0:?     'usamp2DA' ( uniform usampler2DArray)
+0:?     'samp1Ds' ( uniform sampler1DShadow)
+0:?     'sampCubes' ( uniform samplerCubeShadow)
+0:?     'samp1DAs' ( uniform sampler1DArrayShadow)
+0:?     'samp2DAs' ( uniform sampler2DArrayShadow)
+0:?     'sampBuf' ( uniform samplerBuffer)
+0:?     'sampRect' ( uniform sampler2DRect)
+0:?     'b1' ( global bool)
+0:?     'b2' ( global bool)
+0:?     'b' ( global bool)
+0:?     'x' ( global int)
+0:?     'y' ( global int)
+0:?     'z' ( global uint)
+0:?     'w' ( global uint)
 
diff --git a/Test/baseResults/150.vert.out b/Test/baseResults/150.vert.out
index 504160d..05a1db9 100644
--- a/Test/baseResults/150.vert.out
+++ b/Test/baseResults/150.vert.out
@@ -1,10 +1,14 @@
 150.vert
 ERROR: 0:26: 'a' : cannot redeclare a user-block member array 
+ERROR: 0:28: 'double' : Reserved word. 
+ERROR: 0:28: 'double' : not supported for this version or the enabled extensions 
+ERROR: 0:28: 'vertex-shader `double` type input' : not supported for this version or the enabled extensions 
 ERROR: 0:3001: '#error' : line of this error should be 3001  
-ERROR: 2 compilation errors.  No code generated.
+ERROR: 5 compilation errors.  No code generated.
 
 
 Shader version: 150
+Requested GL_ARB_vertex_attrib_64bit
 ERROR: node is still EOpNull!
 0:13  Function Definition: main( ( global void)
 0:13    Function Parameters: 
@@ -43,6 +47,20 @@
 0:?     'iv4' ( in 4-component vector of float)
 0:?     'ps' ( uniform float)
 0:?     'anon@1' (layout( column_major shared) uniform block{layout( column_major shared) uniform unsized 1-element array of int a})
+0:?     'dvarerr' ( in double)
+0:?     'dvar' ( in double)
+0:?     'dv2var' ( in 2-component vector of double)
+0:?     'dv3var' ( in 3-component vector of double)
+0:?     'dv4var' ( in 4-component vector of double)
+0:?     'dmat2var' ( in 2X2 matrix of double)
+0:?     'dmat3var' ( in 3X3 matrix of double)
+0:?     'dmat4var' ( in 4X4 matrix of double)
+0:?     'dmat23var' ( in 2X3 matrix of double)
+0:?     'dmat24var' ( in 2X4 matrix of double)
+0:?     'dmat32var' ( in 3X2 matrix of double)
+0:?     'dmat34var' ( in 3X4 matrix of double)
+0:?     'dmat42var' ( in 4X2 matrix of double)
+0:?     'dmat43var' ( in 4X3 matrix of double)
 0:?     'gl_VertexID' ( gl_VertexId int VertexId)
 0:?     'gl_InstanceID' ( gl_InstanceId int InstanceId)
 
@@ -52,6 +70,7 @@
 ERROR: Linking vertex stage: Can only use one of gl_ClipDistance or gl_ClipVertex (gl_ClipDistance is preferred)
 
 Shader version: 150
+Requested GL_ARB_vertex_attrib_64bit
 ERROR: node is still EOpNull!
 0:13  Function Definition: main( ( global void)
 0:13    Function Parameters: 
@@ -90,6 +109,20 @@
 0:?     'iv4' ( in 4-component vector of float)
 0:?     'ps' ( uniform float)
 0:?     'anon@1' (layout( column_major shared) uniform block{layout( column_major shared) uniform 1-element array of int a})
+0:?     'dvarerr' ( in double)
+0:?     'dvar' ( in double)
+0:?     'dv2var' ( in 2-component vector of double)
+0:?     'dv3var' ( in 3-component vector of double)
+0:?     'dv4var' ( in 4-component vector of double)
+0:?     'dmat2var' ( in 2X2 matrix of double)
+0:?     'dmat3var' ( in 3X3 matrix of double)
+0:?     'dmat4var' ( in 4X4 matrix of double)
+0:?     'dmat23var' ( in 2X3 matrix of double)
+0:?     'dmat24var' ( in 2X4 matrix of double)
+0:?     'dmat32var' ( in 3X2 matrix of double)
+0:?     'dmat34var' ( in 3X4 matrix of double)
+0:?     'dmat42var' ( in 4X2 matrix of double)
+0:?     'dmat43var' ( in 4X3 matrix of double)
 0:?     'gl_VertexID' ( gl_VertexId int VertexId)
 0:?     'gl_InstanceID' ( gl_InstanceId int InstanceId)
 
diff --git a/Test/baseResults/300.frag.out b/Test/baseResults/300.frag.out
index ee1b8a5..50a6b07 100644
--- a/Test/baseResults/300.frag.out
+++ b/Test/baseResults/300.frag.out
@@ -40,15 +40,20 @@
 ERROR: 0:129: 'texel offset' : value is out of range: [gl_MinProgramTexelOffset, gl_MaxProgramTexelOffset]
 ERROR: 0:148: 'qualifier' : cannot use auxiliary, memory, interpolation, or precision qualifier in a default qualifier declaration (declaration with no type) 
 ERROR: 0:150: 'early_fragment_tests' : not supported for this version or the enabled extensions 
-ERROR: 0:156: 'invariant' : can only apply to an output 
-ERROR: 0:157: 'invariant' : can only apply to an output 
-ERROR: 0:158: 'invariant' : can only apply to an output 
-ERROR: 0:160: 'imageBuffer' : Reserved word. 
-ERROR: 0:160: '' :  syntax error, unexpected IMAGEBUFFER, expecting COMMA or SEMICOLON
-ERROR: 46 compilation errors.  No code generated.
+ERROR: 0:177: 'specific signature of builtin mix' : required extension not requested: GL_EXT_shader_integer_mix
+ERROR: 0:181: 'index layout qualifier on fragment output' : not supported for this version or the enabled extensions 
+ERROR: 0:183: 'index' : value must be 0 or 1 
+ERROR: 0:189: 'invariant' : can only apply to an output 
+ERROR: 0:190: 'invariant' : can only apply to an output 
+ERROR: 0:191: 'invariant' : can only apply to an output 
+ERROR: 0:193: 'imageBuffer' : Reserved word. 
+ERROR: 0:193: '' :  syntax error, unexpected IMAGEBUFFER, expecting COMMA or SEMICOLON
+ERROR: 49 compilation errors.  No code generated.
 
 
 Shader version: 300
+Requested GL_EXT_blend_func_extended
+Requested GL_EXT_shader_integer_mix
 using early_fragment_tests
 ERROR: node is still EOpNull!
 0:53  Function Definition: main( ( global void)
@@ -362,6 +367,130 @@
 0:145            21.000000
 0:145            22.000000
 0:145            33.000000
+0:158  Function Definition: testmix( ( global void)
+0:158    Function Parameters: 
+0:160    Sequence
+0:160      Sequence
+0:160        move second child to first child ( temp mediump int)
+0:160          'ival' ( temp mediump int)
+0:160          mix ( global mediump int)
+0:160            'x' ( global mediump int)
+0:160            'y' ( global mediump int)
+0:160            'b' ( global bool)
+0:161      Sequence
+0:161        move second child to first child ( temp mediump 2-component vector of int)
+0:161          'iv2' ( temp mediump 2-component vector of int)
+0:161          mix ( global mediump 2-component vector of int)
+0:161            Construct ivec2 ( temp mediump 2-component vector of int)
+0:161              'x' ( global mediump int)
+0:161            Construct ivec2 ( temp mediump 2-component vector of int)
+0:161              'y' ( global mediump int)
+0:161            Construct bvec2 ( temp 2-component vector of bool)
+0:161              'b' ( global bool)
+0:162      Sequence
+0:162        move second child to first child ( temp mediump 3-component vector of int)
+0:162          'iv3' ( temp mediump 3-component vector of int)
+0:162          mix ( global mediump 3-component vector of int)
+0:162            Construct ivec3 ( temp mediump 3-component vector of int)
+0:162              'x' ( global mediump int)
+0:162            Construct ivec3 ( temp mediump 3-component vector of int)
+0:162              'y' ( global mediump int)
+0:162            Construct bvec3 ( temp 3-component vector of bool)
+0:162              'b' ( global bool)
+0:163      Sequence
+0:163        move second child to first child ( temp mediump 4-component vector of int)
+0:163          'iv4' ( temp mediump 4-component vector of int)
+0:163          mix ( global mediump 4-component vector of int)
+0:163            Construct ivec4 ( temp mediump 4-component vector of int)
+0:163              'x' ( global mediump int)
+0:163            Construct ivec4 ( temp mediump 4-component vector of int)
+0:163              'x' ( global mediump int)
+0:163            Construct bvec4 ( temp 4-component vector of bool)
+0:163              'b' ( global bool)
+0:164      Sequence
+0:164        move second child to first child ( temp mediump uint)
+0:164          'uiv' ( temp mediump uint)
+0:164          mix ( global mediump uint)
+0:164            'z' ( global mediump uint)
+0:164            'w' ( global mediump uint)
+0:164            'b' ( global bool)
+0:165      Sequence
+0:165        move second child to first child ( temp mediump 2-component vector of uint)
+0:165          'uv2' ( temp mediump 2-component vector of uint)
+0:165          mix ( global mediump 2-component vector of uint)
+0:165            Construct uvec2 ( temp mediump 2-component vector of uint)
+0:165              'z' ( global mediump uint)
+0:165            Construct uvec2 ( temp mediump 2-component vector of uint)
+0:165              'z' ( global mediump uint)
+0:165            Construct bvec2 ( temp 2-component vector of bool)
+0:165              'b' ( global bool)
+0:166      Sequence
+0:166        move second child to first child ( temp mediump 3-component vector of uint)
+0:166          'uv3' ( temp mediump 3-component vector of uint)
+0:166          mix ( global mediump 3-component vector of uint)
+0:166            Construct uvec3 ( temp mediump 3-component vector of uint)
+0:166              'z' ( global mediump uint)
+0:166            Construct uvec3 ( temp mediump 3-component vector of uint)
+0:166              'z' ( global mediump uint)
+0:166            Construct bvec3 ( temp 3-component vector of bool)
+0:166              'b' ( global bool)
+0:167      Sequence
+0:167        move second child to first child ( temp mediump 4-component vector of uint)
+0:167          'uv4' ( temp mediump 4-component vector of uint)
+0:167          mix ( global mediump 4-component vector of uint)
+0:167            Construct uvec4 ( temp mediump 4-component vector of uint)
+0:167              'z' ( global mediump uint)
+0:167            Construct uvec4 ( temp mediump 4-component vector of uint)
+0:167              'z' ( global mediump uint)
+0:167            Construct bvec4 ( temp 4-component vector of bool)
+0:167              'b' ( global bool)
+0:168      Sequence
+0:168        move second child to first child ( temp bool)
+0:168          'bv' ( temp bool)
+0:168          mix ( global bool)
+0:168            'b1' ( global bool)
+0:168            'b2' ( global bool)
+0:168            'b' ( global bool)
+0:169      Sequence
+0:169        move second child to first child ( temp 2-component vector of bool)
+0:169          'bv2' ( temp 2-component vector of bool)
+0:169          mix ( global 2-component vector of bool)
+0:169            Construct bvec2 ( temp 2-component vector of bool)
+0:169              'b1' ( global bool)
+0:169            Construct bvec2 ( temp 2-component vector of bool)
+0:169              'b2' ( global bool)
+0:169            Construct bvec2 ( temp 2-component vector of bool)
+0:169              'b' ( global bool)
+0:170      Sequence
+0:170        move second child to first child ( temp 3-component vector of bool)
+0:170          'bv3' ( temp 3-component vector of bool)
+0:170          mix ( global 3-component vector of bool)
+0:170            Construct bvec3 ( temp 3-component vector of bool)
+0:170              'b1' ( global bool)
+0:170            Construct bvec3 ( temp 3-component vector of bool)
+0:170              'b2' ( global bool)
+0:170            Construct bvec3 ( temp 3-component vector of bool)
+0:170              'b' ( global bool)
+0:171      Sequence
+0:171        move second child to first child ( temp 4-component vector of bool)
+0:171          'bv4' ( temp 4-component vector of bool)
+0:171          mix ( global 4-component vector of bool)
+0:171            Construct bvec4 ( temp 4-component vector of bool)
+0:171              'b1' ( global bool)
+0:171            Construct bvec4 ( temp 4-component vector of bool)
+0:171              'b2' ( global bool)
+0:171            Construct bvec4 ( temp 4-component vector of bool)
+0:171              'b' ( global bool)
+0:175  Function Definition: testmixFail( ( global void)
+0:175    Function Parameters: 
+0:177    Sequence
+0:177      Sequence
+0:177        move second child to first child ( temp mediump int)
+0:177          'ival' ( temp mediump int)
+0:177          mix ( global mediump int)
+0:177            'x' ( global mediump int)
+0:177            'y' ( global mediump int)
+0:177            'b' ( global bool)
 0:?   Linker Objects
 0:?     's2D' ( uniform lowp sampler2D)
 0:?     's3D' ( uniform lowp sampler3D)
@@ -397,6 +526,15 @@
 0:?     'colors' ( out 4-element array of lowp 4-component vector of float)
 0:?     'st1' ( uniform structure{ global mediump int i,  global lowp sampler2D s})
 0:?     'st2' ( uniform structure{ global mediump int i,  global lowp sampler2D s})
+0:?     'b1' ( global bool)
+0:?     'b2' ( global bool)
+0:?     'b' ( global bool)
+0:?     'x' ( global mediump int)
+0:?     'y' ( global mediump int)
+0:?     'z' ( global mediump uint)
+0:?     'w' ( global mediump uint)
+0:?     'outVarFail' (layout( location=0 index=1) out lowp 4-component vector of float)
+0:?     'outVarPass' (layout( location=0 index=0) out lowp 4-component vector of float)
 0:?     'fooinv' ( invariant smooth in lowp 4-component vector of float)
 
 
@@ -405,6 +543,8 @@
 ERROR: Linking fragment stage: when more than one fragment shader output, all must have location qualifiers
 
 Shader version: 300
+Requested GL_EXT_blend_func_extended
+Requested GL_EXT_shader_integer_mix
 using early_fragment_tests
 ERROR: node is still EOpNull!
 0:53  Function Definition: main( ( global void)
@@ -628,5 +768,14 @@
 0:?     'colors' ( out 4-element array of lowp 4-component vector of float)
 0:?     'st1' ( uniform structure{ global mediump int i,  global lowp sampler2D s})
 0:?     'st2' ( uniform structure{ global mediump int i,  global lowp sampler2D s})
+0:?     'b1' ( global bool)
+0:?     'b2' ( global bool)
+0:?     'b' ( global bool)
+0:?     'x' ( global mediump int)
+0:?     'y' ( global mediump int)
+0:?     'z' ( global mediump uint)
+0:?     'w' ( global mediump uint)
+0:?     'outVarFail' (layout( location=0 index=1) out lowp 4-component vector of float)
+0:?     'outVarPass' (layout( location=0 index=0) out lowp 4-component vector of float)
 0:?     'fooinv' ( invariant smooth in lowp 4-component vector of float)
 
diff --git a/Test/baseResults/300BuiltIns.frag.out b/Test/baseResults/300