From: baldurk <baldurk@baldurk.org>
Date: Wed, 30 Jan 2019 17:18:14 +0000
Subject: Cherry-pick portion of upstream
 2ea6174c83c3c55f504c107303991d9bb2aa9af3

This commit updated renderdoc to use a newer glslang. We need to
cherry-pick it to build with a newer version of the glslang debian
package.
---
 renderdoc/driver/shaders/spirv/spirv_compile.cpp   |   9 ++
 .../driver/shaders/spirv/spirv_disassemble.cpp     |   8 +
 renderdoc/driver/shaders/spirv/spirv_editor.cpp    | 180 +++++++++++++++++++++
 3 files changed, 197 insertions(+)

diff --git a/renderdoc/driver/shaders/spirv/spirv_compile.cpp b/renderdoc/driver/shaders/spirv/spirv_compile.cpp
index c6b7136..c737d3c 100644
--- a/renderdoc/driver/shaders/spirv/spirv_compile.cpp
+++ b/renderdoc/driver/shaders/spirv/spirv_compile.cpp
@@ -115,6 +115,15 @@ TBuiltInResource DefaultResources = {
     /*.maxCullDistances =*/8,
     /*.maxCombinedClipAndCullDistances =*/8,
     /*.maxSamples =*/4,
+    /*.maxMeshOutputVerticesNV =*/256,
+    /*.maxMeshOutputPrimitivesNV =*/512,
+    /*.maxMeshWorkGroupSizeX_NV =*/32,
+    /*.maxMeshWorkGroupSizeY_NV =*/1,
+    /*.maxMeshWorkGroupSizeZ_NV =*/1,
+    /*.maxTaskWorkGroupSizeX_NV =*/32,
+    /*.maxTaskWorkGroupSizeY_NV =*/1,
+    /*.maxTaskWorkGroupSizeZ_NV =*/1,
+    /*.maxMeshViewCountNV =*/4,
 
     /*.limits*/
     {
diff --git a/renderdoc/driver/shaders/spirv/spirv_disassemble.cpp b/renderdoc/driver/shaders/spirv/spirv_disassemble.cpp
index 8b1413e..037e51c 100644
--- a/renderdoc/driver/shaders/spirv/spirv_disassemble.cpp
+++ b/renderdoc/driver/shaders/spirv/spirv_disassemble.cpp
@@ -3988,6 +3988,14 @@ ShaderStage SPVModule::StageForEntry(const string &entryPoint) const
         case spv::ExecutionModelFragment: return ShaderStage::Fragment;
         case spv::ExecutionModelGLCompute: return ShaderStage::Compute;
         case spv::ExecutionModelKernel:
+        case spv::ExecutionModelTaskNV:
+        case spv::ExecutionModelMeshNV:
+        case spv::ExecutionModelRayGenerationNV:
+        case spv::ExecutionModelIntersectionNV:
+        case spv::ExecutionModelAnyHitNV:
+        case spv::ExecutionModelClosestHitNV:
+        case spv::ExecutionModelMissNV:
+        case spv::ExecutionModelCallableNV:
         case spv::ExecutionModelMax: return ShaderStage::Count;
       }
     }
diff --git a/renderdoc/driver/shaders/spirv/spirv_editor.cpp b/renderdoc/driver/shaders/spirv/spirv_editor.cpp
index 57385eb..b1a1e85 100644
--- a/renderdoc/driver/shaders/spirv/spirv_editor.cpp
+++ b/renderdoc/driver/shaders/spirv/spirv_editor.cpp
@@ -892,3 +892,183 @@ std::map<SPIRVFunction, SPIRVId> &SPIRVEditor::GetTable<SPIRVFunction>()
 {
   return functionTypes;
 }
+
+#if ENABLED(ENABLE_UNIT_TESTS)
+
+#include "3rdparty/catch/catch.hpp"
+#include "core/core.h"
+#include "spirv_common.h"
+
+static void RemoveSection(std::vector<uint32_t> &spirv, size_t offsets[SPIRVSection::Count][2],
+                          SPIRVSection::Type section)
+{
+  SPIRVEditor ed(spirv);
+
+  for(SPIRVIterator it = ed.Begin(section), end = ed.End(section); it < end; it++)
+    ed.Remove(it);
+
+  size_t oldLength = offsets[section][1] - offsets[section][0];
+
+  // section will still contain a nop
+  offsets[section][1] = offsets[section][0] + 4;
+
+  // subsequent sections will be shorter by the length - 4, because a nop will still be inserted
+  // as padding to ensure no section is truly empty.
+  size_t delta = oldLength - 4;
+
+  for(uint32_t s = section + 1; s < SPIRVSection::Count; s++)
+  {
+    offsets[s][0] -= delta;
+    offsets[s][1] -= delta;
+  }
+}
+
+TEST_CASE("Test SPIR-V editor section handling", "[spirv]")
+{
+  InitSPIRVCompiler();
+  RenderDoc::Inst().RegisterShutdownFunction(&ShutdownSPIRVCompiler);
+
+  SPIRVCompilationSettings settings;
+  settings.entryPoint = "main";
+  settings.lang = SPIRVSourceLanguage::VulkanGLSL;
+  settings.stage = SPIRVShaderStage::Fragment;
+
+  // simple shader that has at least something in every section
+  std::vector<std::string> sources = {
+      R"(#version 450 core
+
+#extension GL_EXT_shader_16bit_storage : require
+
+layout(binding = 0) uniform block {
+	float16_t val;
+};
+
+layout(location = 0) out vec4 col;
+
+void main() {
+  col = vec4(sin(gl_FragCoord.x)*float(val), 0, 0, 1);
+}
+)",
+  };
+
+  std::vector<uint32_t> spirv;
+  std::string errors = CompileSPIRV(settings, sources, spirv);
+
+  INFO("SPIR-V compilation - " << errors);
+
+  // ensure that compilation succeeded
+  REQUIRE(spirv.size() > 0);
+
+  // these offsets may change if the compiler changes above. Verify manually with spirv-dis that
+  // they should be updated.
+  // For convenience the offsets are in bytes (which spirv-dis uses) and are converted in the loops
+  // below.
+  size_t offsets[SPIRVSection::Count][2] = {
+      // Capabilities
+      {0x14, 0x24},
+      // Extensions
+      {0x24, 0x40},
+      // ExtInst
+      {0x40, 0x58},
+      // MemoryModel
+      {0x58, 0x64},
+      // EntryPoints
+      {0x64, 0x80},
+      // ExecutionMode
+      {0x80, 0x8c},
+      // Debug
+      {0x8c, 0x118},
+      // Annotations
+      {0x118, 0x178},
+      // TypesVariables
+      {0x178, 0x2a0},
+      // Functions
+      {0x2a0, 0x370},
+  };
+
+  SECTION("Check that SPIR-V is correct with no changes")
+  {
+    SPIRVEditor ed(spirv);
+
+    for(uint32_t s = SPIRVSection::First; s < SPIRVSection::Count; s++)
+    {
+      INFO("Section " << s);
+      CHECK(ed.Begin((SPIRVSection::Type)s).offs() == offsets[s][0] / sizeof(uint32_t));
+      CHECK(ed.End((SPIRVSection::Type)s).offs() == offsets[s][1] / sizeof(uint32_t));
+    }
+  }
+
+  // we remove all sections we consider optional in arbitrary order. We don't care about keeping the
+  // SPIR-V valid all we're testing is the section offsets are correct.
+  RemoveSection(spirv, offsets, SPIRVSection::Extensions);
+
+  SECTION("Check with extensions removed")
+  {
+    SPIRVEditor ed(spirv);
+
+    for(uint32_t s = SPIRVSection::First; s < SPIRVSection::Count; s++)
+    {
+      INFO("Section " << s);
+      CHECK(ed.Begin((SPIRVSection::Type)s).offs() == offsets[s][0] / sizeof(uint32_t));
+      CHECK(ed.End((SPIRVSection::Type)s).offs() == offsets[s][1] / sizeof(uint32_t));
+    }
+  }
+
+  RemoveSection(spirv, offsets, SPIRVSection::Debug);
+
+  SECTION("Check with debug removed")
+  {
+    SPIRVEditor ed(spirv);
+
+    for(uint32_t s = SPIRVSection::First; s < SPIRVSection::Count; s++)
+    {
+      INFO("Section " << s);
+      CHECK(ed.Begin((SPIRVSection::Type)s).offs() == offsets[s][0] / sizeof(uint32_t));
+      CHECK(ed.End((SPIRVSection::Type)s).offs() == offsets[s][1] / sizeof(uint32_t));
+    }
+  }
+
+  RemoveSection(spirv, offsets, SPIRVSection::ExtInst);
+
+  SECTION("Check with extension imports removed")
+  {
+    SPIRVEditor ed(spirv);
+
+    for(uint32_t s = SPIRVSection::First; s < SPIRVSection::Count; s++)
+    {
+      INFO("Section " << s);
+      CHECK(ed.Begin((SPIRVSection::Type)s).offs() == offsets[s][0] / sizeof(uint32_t));
+      CHECK(ed.End((SPIRVSection::Type)s).offs() == offsets[s][1] / sizeof(uint32_t));
+    }
+  }
+
+  RemoveSection(spirv, offsets, SPIRVSection::ExecutionMode);
+
+  SECTION("Check with execution mode removed")
+  {
+    SPIRVEditor ed(spirv);
+
+    for(uint32_t s = SPIRVSection::First; s < SPIRVSection::Count; s++)
+    {
+      INFO("Section " << s);
+      CHECK(ed.Begin((SPIRVSection::Type)s).offs() == offsets[s][0] / sizeof(uint32_t));
+      CHECK(ed.End((SPIRVSection::Type)s).offs() == offsets[s][1] / sizeof(uint32_t));
+    }
+  }
+
+  RemoveSection(spirv, offsets, SPIRVSection::Annotations);
+
+  SECTION("Check with annotations removed")
+  {
+    SPIRVEditor ed(spirv);
+
+    for(uint32_t s = SPIRVSection::First; s < SPIRVSection::Count; s++)
+    {
+      INFO("Section " << s);
+      CHECK(ed.Begin((SPIRVSection::Type)s).offs() == offsets[s][0] / sizeof(uint32_t));
+      CHECK(ed.End((SPIRVSection::Type)s).offs() == offsets[s][1] / sizeof(uint32_t));
+    }
+  }
+}
+
+#endif
