Просмотр исходного кода

Merge pull request #39340 from JFonS/upgrade_oidn

Upgrade OpenImageDenoise to v1.1.0
Rémi Verschelde 5 лет назад
Родитель
Сommit
d838a44735

+ 22 - 2
thirdparty/README.md

@@ -446,12 +446,32 @@ Files extracted from the upstream source:
 ## oidn
 ## oidn
 
 
 - Upstream: https://github.com/OpenImageDenoise/oidn
 - Upstream: https://github.com/OpenImageDenoise/oidn
-- Version: TBD
+- Version: 1.1.0 (c58c5216db05ceef4cde5a096862f2eeffd14c06)
 - License: Apache 2.0
 - License: Apache 2.0
 
 
 Files extracted from upstream source:
 Files extracted from upstream source:
 
 
-- TBD
+common/* (except tasking.* and CMakeLists.txt)
+core/*
+include/OpenImageDenoise/* (except version.h.in)
+LICENSE.txt
+mkl-dnn/include/*
+mkl-dnn/src/* (except CMakeLists.txt)
+weights/rtlightmap_hdr.tza
+scripts/resource_to_cpp.py
+
+Modified files:
+Modifications are marked with `// -- GODOT start --` and `// -- GODOT end --`
+A patch file is provided in `oidn/godot-changes-c58c5216.patch`
+
+core/autoencoder.cpp
+core/autoencoder.h
+core/common.h
+core/device.cpp
+core/device.h
+core/transfer_function.cpp
+
+scripts/resource_to_cpp.py (used in modules/denoise/resource_to_cpp.py)
 
 
 
 
 ## opus
 ## opus

+ 0 - 13
thirdparty/oidn/0001-window.h-case-sensitive.patch

@@ -1,13 +0,0 @@
-diff --git a/thirdparty/oidn/common/platform.h b/thirdparty/oidn/common/platform.h
-index 205ac8981d..9373b617b5 100644
---- a/thirdparty/oidn/common/platform.h
-+++ b/thirdparty/oidn/common/platform.h
-@@ -19,7 +19,7 @@
- #if defined(_WIN32)
-   #define WIN32_LEAN_AND_MEAN
-   #define NOMINMAX
--  #include <Windows.h>
-+  #include <windows.h>
- #elif defined(__APPLE__)
-   #include <sys/sysctl.h>
- #endif

+ 21 - 5
thirdparty/oidn/core/autoencoder.cpp

@@ -90,12 +90,19 @@ namespace oidn {
     if (!dirty)
     if (!dirty)
       return;
       return;
 
 
-    {
+    // -- GODOT start --
+    //device->executeTask([&]()
+    //{
+    // GODOT end --
+
       if (mayiuse(avx512_common))
       if (mayiuse(avx512_common))
         net = buildNet<16>();
         net = buildNet<16>();
       else
       else
         net = buildNet<8>();
         net = buildNet<8>();
-    }
+
+    // GODOT start --    
+    //});
+    // GODOT end --
 
 
     dirty = false;
     dirty = false;
   }
   }
@@ -107,8 +114,10 @@ namespace oidn {
 
 
     if (!net)
     if (!net)
       return;
       return;
-
-    {
+    // -- GODOT start --
+    //device->executeTask([&]()
+    //{
+    // -- GODOT end --
       Progress progress;
       Progress progress;
       progress.func = progressFunc;
       progress.func = progressFunc;
       progress.userPtr = progressUserPtr;
       progress.userPtr = progressUserPtr;
@@ -154,7 +163,9 @@ namespace oidn {
           tileIndex++;
           tileIndex++;
         }
         }
       }
       }
-    }
+    // -- GODOT start --
+    //});
+    // -- GODOT end --
   }
   }
 
 
   void AutoencoderFilter::computeTileSize()
   void AutoencoderFilter::computeTileSize()
@@ -462,8 +473,11 @@ namespace oidn {
       return std::make_shared<GammaTransferFunction>();
       return std::make_shared<GammaTransferFunction>();
   }
   }
 
 
+// -- GODOT start --
 // Godot doesn't need Raytracing filters. Removing them saves space in the weights files.
 // Godot doesn't need Raytracing filters. Removing them saves space in the weights files.
 #if 0
 #if 0
+// -- GODOT end --
+
   // --------------------------------------------------------------------------
   // --------------------------------------------------------------------------
   // RTFilter
   // RTFilter
   // --------------------------------------------------------------------------
   // --------------------------------------------------------------------------
@@ -491,7 +505,9 @@ namespace oidn {
     weightData.hdr_alb     = weights::rt_hdr_alb;
     weightData.hdr_alb     = weights::rt_hdr_alb;
     weightData.hdr_alb_nrm = weights::rt_hdr_alb_nrm;
     weightData.hdr_alb_nrm = weights::rt_hdr_alb_nrm;
   }
   }
+// -- GODOT start --
 #endif
 #endif
+// -- GODOT end --
 
 
   // --------------------------------------------------------------------------
   // --------------------------------------------------------------------------
   // RTLightmapFilter
   // RTLightmapFilter

+ 4 - 0
thirdparty/oidn/core/autoencoder.h

@@ -93,14 +93,18 @@ namespace oidn {
   // RTFilter - Generic ray tracing denoiser
   // RTFilter - Generic ray tracing denoiser
   // --------------------------------------------------------------------------
   // --------------------------------------------------------------------------
 
 
+// -- GODOT start --
 // Godot doesn't need Raytracing filters. Removing them saves space in the weights files.
 // Godot doesn't need Raytracing filters. Removing them saves space in the weights files.
 #if 0
 #if 0
+// -- GODOT end --
   class RTFilter : public AutoencoderFilter
   class RTFilter : public AutoencoderFilter
   {
   {
   public:
   public:
     explicit RTFilter(const Ref<Device>& device);
     explicit RTFilter(const Ref<Device>& device);
   };
   };
+// -- GODOT start --
 #endif
 #endif
+// -- GODOT end --
 
 
   // --------------------------------------------------------------------------
   // --------------------------------------------------------------------------
   // RTLightmapFilter - Ray traced lightmap denoiser
   // RTLightmapFilter - Ray traced lightmap denoiser

+ 3 - 0
thirdparty/oidn/core/common.h

@@ -27,6 +27,9 @@
 #include "common/ref.h"
 #include "common/ref.h"
 #include "common/exception.h"
 #include "common/exception.h"
 #include "common/thread.h"
 #include "common/thread.h"
+// -- GODOT start --
+//#include "common/tasking.h"
+// -- GODOT end --
 #include "math.h"
 #include "math.h"
 
 
 namespace oidn {
 namespace oidn {

+ 36 - 3
thirdparty/oidn/core/device.cpp

@@ -29,6 +29,9 @@ namespace oidn {
 
 
   Device::~Device()
   Device::~Device()
   {
   {
+    // -- GODOT start --
+    //observer.reset();
+    // -- GODOT end --
   }
   }
 
 
   void Device::setError(Device* device, Error code, const std::string& message)
   void Device::setError(Device* device, Error code, const std::string& message)
@@ -140,10 +143,29 @@ namespace oidn {
     if (isCommitted())
     if (isCommitted())
       throw Exception(Error::InvalidOperation, "device can be committed only once");
       throw Exception(Error::InvalidOperation, "device can be committed only once");
 
 
+    // -- GODOT start --
+    #if 0
+    // -- GODOT end --
+    // Get the optimal thread affinities
+    if (setAffinity)
+    {
+      affinity = std::make_shared<ThreadAffinity>(1, verbose); // one thread per core
+      if (affinity->getNumThreads() == 0)
+        affinity.reset();
+    }
+
     // Create the task arena
     // Create the task arena
-    const int maxNumThreads = 1; //affinity ? affinity->getNumThreads() : tbb::this_task_arena::max_concurrency();
+    const int maxNumThreads = affinity ? affinity->getNumThreads() : tbb::this_task_arena::max_concurrency();
     numThreads = (numThreads > 0) ? min(numThreads, maxNumThreads) : maxNumThreads;
     numThreads = (numThreads > 0) ? min(numThreads, maxNumThreads) : maxNumThreads;
-
+    arena = std::make_shared<tbb::task_arena>(numThreads);
+
+    // Automatically set the thread affinities
+    if (affinity)
+      observer = std::make_shared<PinningObserver>(affinity, *arena);
+    // -- GODOT start --
+    #endif
+    numThreads = 1;
+    // -- GODOT end --
     dirty = false;
     dirty = false;
 
 
     if (isVerbose())
     if (isVerbose())
@@ -177,12 +199,17 @@ namespace oidn {
 
 
     Ref<Filter> filter;
     Ref<Filter> filter;
 
 
+// -- GODOT start --
 // Godot doesn't need Raytracing filters. Removing them saves space in the weights files.
 // Godot doesn't need Raytracing filters. Removing them saves space in the weights files.
 #if 0
 #if 0
+// -- GODOT end --
     if (type == "RT")
     if (type == "RT")
       filter = makeRef<RTFilter>(Ref<Device>(this));
       filter = makeRef<RTFilter>(Ref<Device>(this));
+// -- GODOT start --
+// Godot doesn't need Raytracing filters. Removing them saves space in the weights files.
 #endif
 #endif
-	if (type == "RTLightmap")
+    if (type == "RTLightmap")
+// -- GODOT end --
       filter = makeRef<RTLightmapFilter>(Ref<Device>(this));
       filter = makeRef<RTLightmapFilter>(Ref<Device>(this));
     else
     else
       throw Exception(Error::InvalidArgument, "unknown filter type");
       throw Exception(Error::InvalidArgument, "unknown filter type");
@@ -199,6 +226,12 @@ namespace oidn {
     std::cout << "  Build   : " << getBuildName() << std::endl;
     std::cout << "  Build   : " << getBuildName() << std::endl;
     std::cout << "  Platform: " << getPlatformName() << std::endl;
     std::cout << "  Platform: " << getPlatformName() << std::endl;
 
 
+// -- GODOT start --
+//    std::cout << "  Tasking :";
+//    std::cout << " TBB" << TBB_VERSION_MAJOR << "." << TBB_VERSION_MINOR;
+//    std::cout << " TBB_header_interface_" << TBB_INTERFACE_VERSION << " TBB_lib_interface_" << tbb::TBB_runtime_interface_version();
+//    std::cout << std::endl;
+// -- GODOT end --
     std::cout << std::endl;
     std::cout << std::endl;
   }
   }
 
 

+ 25 - 1
thirdparty/oidn/core/device.h

@@ -41,6 +41,13 @@ namespace oidn {
     ErrorFunction errorFunc = nullptr;
     ErrorFunction errorFunc = nullptr;
     void* errorUserPtr = nullptr;
     void* errorUserPtr = nullptr;
 
 
+// -- GODOT start --
+//    // Tasking
+//    std::shared_ptr<tbb::task_arena> arena;
+//    std::shared_ptr<PinningObserver> observer;
+//    std::shared_ptr<ThreadAffinity> affinity;
+// -- GODOT end --
+
     // Parameters
     // Parameters
     int numThreads = 0; // autodetect by default
     int numThreads = 0; // autodetect by default
     bool setAffinity = true;
     bool setAffinity = true;
@@ -61,6 +68,20 @@ namespace oidn {
 
 
     void commit();
     void commit();
 
 
+// -- GODOT start --
+//    template<typename F>
+//    void executeTask(F& f)
+//    {
+//      arena->execute(f);
+//    }
+
+//    template<typename F>
+//    void executeTask(const F& f)
+//    {
+//      arena->execute(f);
+//    }
+// -- GODOT end --
+
     Ref<Buffer> newBuffer(size_t byteSize);
     Ref<Buffer> newBuffer(size_t byteSize);
     Ref<Buffer> newBuffer(void* ptr, size_t byteSize);
     Ref<Buffer> newBuffer(void* ptr, size_t byteSize);
     Ref<Filter> newFilter(const std::string& type);
     Ref<Filter> newFilter(const std::string& type);
@@ -69,7 +90,10 @@ namespace oidn {
     __forceinline std::mutex& getMutex() { return mutex; }
     __forceinline std::mutex& getMutex() { return mutex; }
 
 
   private:
   private:
-    bool isCommitted() const { return false; }
+// -- GODOT start --
+  //bool isCommitted() const { return bool(arena); }
+  bool isCommitted() const { return false; }
+// -- GODOT end --
     void checkCommitted();
     void checkCommitted();
 
 
     void print();
     void print();

+ 3 - 1
thirdparty/oidn/core/network.cpp

@@ -14,10 +14,12 @@
 // limitations under the License.                                           //
 // limitations under the License.                                           //
 // ======================================================================== //
 // ======================================================================== //
 
 
-#include "network.h"
 #include "upsample.h"
 #include "upsample.h"
 #include "weights_reorder.h"
 #include "weights_reorder.h"
+#include "network.h"
+// -- GODOT start -- 
 #include <cstring>
 #include <cstring>
+// -- GODOT end --
 
 
 namespace oidn {
 namespace oidn {
 
 

+ 10 - 3
thirdparty/oidn/core/transfer_function.cpp

@@ -24,9 +24,12 @@ namespace oidn {
   float AutoexposureNode::autoexposure(const Image& color)
   float AutoexposureNode::autoexposure(const Image& color)
   {
   {
     assert(color.format == Format::Float3);
     assert(color.format == Format::Float3);
-    return 1.0f;
+// -- GODOT start --
+// We don't want to mess with TTB and we don't use autoexposure, so we disable this code
+#if 0
+// -- GODOT end --
 
 
-    /*constexpr float key = 0.18f;
+    constexpr float key = 0.18f;
     constexpr float eps = 1e-8f;
     constexpr float eps = 1e-8f;
     constexpr int K = 16; // downsampling amount
     constexpr int K = 16; // downsampling amount
 
 
@@ -89,7 +92,11 @@ namespace oidn {
         tbb::static_partitioner()
         tbb::static_partitioner()
       );
       );
 
 
-    return (sum.second > 0) ? (key / exp2(sum.first / float(sum.second))) : 1.f;*/
+    return (sum.second > 0) ? (key / exp2(sum.first / float(sum.second))) : 1.f;
+// -- GODOT start --
+#endif
+    return 1.0;
+// -- GODOT end --
   }
   }
 
 
 } // namespace oidn
 } // namespace oidn

+ 307 - 0
thirdparty/oidn/godot-changes-c58c5216.patch

@@ -0,0 +1,307 @@
+diff --git a/common/platform.h b/common/platform.h
+index be14bc7..9373b61 100644
+--- a/common/platform.h
++++ b/common/platform.h
+@@ -19,7 +19,7 @@
+ #if defined(_WIN32)
+   #define WIN32_LEAN_AND_MEAN
+   #define NOMINMAX
+-  #include <Windows.h>
++  #include <windows.h>
+ #elif defined(__APPLE__)
+   #include <sys/sysctl.h>
+ #endif
+@@ -129,4 +129,3 @@ namespace oidn {
+   std::string getBuildName();
+ 
+ } // namespace oidn
+-
+diff --git a/core/autoencoder.cpp b/core/autoencoder.cpp
+index d6915e6..d8da684 100644
+--- a/core/autoencoder.cpp
++++ b/core/autoencoder.cpp
+@@ -90,13 +90,19 @@ namespace oidn {
+     if (!dirty)
+       return;
+ 
+-    device->executeTask([&]()
+-    {
++    // -- GODOT start --
++    //device->executeTask([&]()
++    //{
++    // GODOT end --
++
+       if (mayiuse(avx512_common))
+         net = buildNet<16>();
+       else
+         net = buildNet<8>();
+-    });
++
++    // GODOT start --    
++    //});
++    // GODOT end --
+ 
+     dirty = false;
+   }
+@@ -108,9 +114,10 @@ namespace oidn {
+ 
+     if (!net)
+       return;
+-
+-    device->executeTask([&]()
+-    {
++    // -- GODOT start --
++    //device->executeTask([&]()
++    //{
++    // -- GODOT end --
+       Progress progress;
+       progress.func = progressFunc;
+       progress.userPtr = progressUserPtr;
+@@ -156,7 +163,9 @@ namespace oidn {
+           tileIndex++;
+         }
+       }
+-    });
++    // -- GODOT start --
++    //});
++    // -- GODOT end --
+   }
+ 
+   void AutoencoderFilter::computeTileSize()
+@@ -464,6 +473,11 @@ namespace oidn {
+       return std::make_shared<GammaTransferFunction>();
+   }
+ 
++// -- GODOT start --
++// Godot doesn't need Raytracing filters. Removing them saves space in the weights files.
++#if 0
++// -- GODOT end --
++
+   // --------------------------------------------------------------------------
+   // RTFilter
+   // --------------------------------------------------------------------------
+@@ -491,6 +505,9 @@ namespace oidn {
+     weightData.hdr_alb     = weights::rt_hdr_alb;
+     weightData.hdr_alb_nrm = weights::rt_hdr_alb_nrm;
+   }
++// -- GODOT start --
++#endif
++// -- GODOT end --
+ 
+   // --------------------------------------------------------------------------
+   // RTLightmapFilter
+diff --git a/core/autoencoder.h b/core/autoencoder.h
+index c199052..98b6108 100644
+--- a/core/autoencoder.h
++++ b/core/autoencoder.h
+@@ -93,11 +93,18 @@ namespace oidn {
+   // RTFilter - Generic ray tracing denoiser
+   // --------------------------------------------------------------------------
+ 
++// -- GODOT start --
++// Godot doesn't need Raytracing filters. Removing them saves space in the weights files.
++#if 0
++// -- GODOT end --
+   class RTFilter : public AutoencoderFilter
+   {
+   public:
+     explicit RTFilter(const Ref<Device>& device);
+   };
++// -- GODOT start --
++#endif
++// -- GODOT end --
+ 
+   // --------------------------------------------------------------------------
+   // RTLightmapFilter - Ray traced lightmap denoiser
+diff --git a/core/common.h b/core/common.h
+index a3a7e8a..a35dd90 100644
+--- a/core/common.h
++++ b/core/common.h
+@@ -27,7 +27,9 @@
+ #include "common/ref.h"
+ #include "common/exception.h"
+ #include "common/thread.h"
+-#include "common/tasking.h"
++// -- GODOT start --
++//#include "common/tasking.h"
++// -- GODOT end --
+ #include "math.h"
+ 
+ namespace oidn {
+diff --git a/core/device.cpp b/core/device.cpp
+index c455695..3cd658b 100644
+--- a/core/device.cpp
++++ b/core/device.cpp
+@@ -29,7 +29,9 @@ namespace oidn {
+ 
+   Device::~Device()
+   {
+-    observer.reset();
++    // -- GODOT start --
++    //observer.reset();
++    // -- GODOT end --
+   }
+ 
+   void Device::setError(Device* device, Error code, const std::string& message)
+@@ -141,6 +143,9 @@ namespace oidn {
+     if (isCommitted())
+       throw Exception(Error::InvalidOperation, "device can be committed only once");
+ 
++    // -- GODOT start --
++    #if 0
++    // -- GODOT end --
+     // Get the optimal thread affinities
+     if (setAffinity)
+     {
+@@ -157,7 +162,10 @@ namespace oidn {
+     // Automatically set the thread affinities
+     if (affinity)
+       observer = std::make_shared<PinningObserver>(affinity, *arena);
+-
++    // -- GODOT start --
++    #endif
++    numThreads = 1;
++    // -- GODOT end --
+     dirty = false;
+ 
+     if (isVerbose())
+@@ -191,9 +199,17 @@ namespace oidn {
+ 
+     Ref<Filter> filter;
+ 
++// -- GODOT start --
++// Godot doesn't need Raytracing filters. Removing them saves space in the weights files.
++#if 0
++// -- GODOT end --
+     if (type == "RT")
+       filter = makeRef<RTFilter>(Ref<Device>(this));
+-    else if (type == "RTLightmap")
++// -- GODOT start --
++// Godot doesn't need Raytracing filters. Removing them saves space in the weights files.
++#endif
++    if (type == "RTLightmap")
++// -- GODOT end --
+       filter = makeRef<RTLightmapFilter>(Ref<Device>(this));
+     else
+       throw Exception(Error::InvalidArgument, "unknown filter type");
+@@ -210,11 +226,12 @@ namespace oidn {
+     std::cout << "  Build   : " << getBuildName() << std::endl;
+     std::cout << "  Platform: " << getPlatformName() << std::endl;
+ 
+-    std::cout << "  Tasking :";
+-    std::cout << " TBB" << TBB_VERSION_MAJOR << "." << TBB_VERSION_MINOR;
+-    std::cout << " TBB_header_interface_" << TBB_INTERFACE_VERSION << " TBB_lib_interface_" << tbb::TBB_runtime_interface_version();
+-    std::cout << std::endl;
+-
++// -- GODOT start --
++//    std::cout << "  Tasking :";
++//    std::cout << " TBB" << TBB_VERSION_MAJOR << "." << TBB_VERSION_MINOR;
++//    std::cout << " TBB_header_interface_" << TBB_INTERFACE_VERSION << " TBB_lib_interface_" << tbb::TBB_runtime_interface_version();
++//    std::cout << std::endl;
++// -- GODOT end --
+     std::cout << std::endl;
+   }
+ 
+diff --git a/core/device.h b/core/device.h
+index c2df714..d9cfd85 100644
+--- a/core/device.h
++++ b/core/device.h
+@@ -41,10 +41,12 @@ namespace oidn {
+     ErrorFunction errorFunc = nullptr;
+     void* errorUserPtr = nullptr;
+ 
+-    // Tasking
+-    std::shared_ptr<tbb::task_arena> arena;
+-    std::shared_ptr<PinningObserver> observer;
+-    std::shared_ptr<ThreadAffinity> affinity;
++// -- GODOT start --
++//    // Tasking
++//    std::shared_ptr<tbb::task_arena> arena;
++//    std::shared_ptr<PinningObserver> observer;
++//    std::shared_ptr<ThreadAffinity> affinity;
++// -- GODOT end --
+ 
+     // Parameters
+     int numThreads = 0; // autodetect by default
+@@ -66,17 +68,19 @@ namespace oidn {
+ 
+     void commit();
+ 
+-    template<typename F>
+-    void executeTask(F& f)
+-    {
+-      arena->execute(f);
+-    }
++// -- GODOT start --
++//    template<typename F>
++//    void executeTask(F& f)
++//    {
++//      arena->execute(f);
++//    }
+ 
+-    template<typename F>
+-    void executeTask(const F& f)
+-    {
+-      arena->execute(f);
+-    }
++//    template<typename F>
++//    void executeTask(const F& f)
++//    {
++//      arena->execute(f);
++//    }
++// -- GODOT end --
+ 
+     Ref<Buffer> newBuffer(size_t byteSize);
+     Ref<Buffer> newBuffer(void* ptr, size_t byteSize);
+@@ -86,7 +90,10 @@ namespace oidn {
+     __forceinline std::mutex& getMutex() { return mutex; }
+ 
+   private:
+-    bool isCommitted() const { return bool(arena); }
++// -- GODOT start --
++  //bool isCommitted() const { return bool(arena); }
++  bool isCommitted() const { return false; }
++// -- GODOT end --
+     void checkCommitted();
+ 
+     void print();
+diff --git a/core/network.cpp b/core/network.cpp
+index 8c2de09..ed8328c 100644
+--- a/core/network.cpp
++++ b/core/network.cpp
+@@ -17,6 +17,9 @@
+ #include "upsample.h"
+ #include "weights_reorder.h"
+ #include "network.h"
++// -- GODOT start -- 
++#include <cstring>
++// -- GODOT end --
+ 
+ namespace oidn {
+ 
+diff --git a/core/transfer_function.cpp b/core/transfer_function.cpp
+index 601f814..487f0a9 100644
+--- a/core/transfer_function.cpp
++++ b/core/transfer_function.cpp
+@@ -24,6 +24,10 @@ namespace oidn {
+   float AutoexposureNode::autoexposure(const Image& color)
+   {
+     assert(color.format == Format::Float3);
++// -- GODOT start --
++// We don't want to mess with TTB and we don't use autoexposure, so we disable this code
++#if 0
++// -- GODOT end --
+ 
+     constexpr float key = 0.18f;
+     constexpr float eps = 1e-8f;
+@@ -89,6 +93,10 @@ namespace oidn {
+       );
+ 
+     return (sum.second > 0) ? (key / exp2(sum.first / float(sum.second))) : 1.f;
++// -- GODOT start --
++#endif
++    return 1.0;
++// -- GODOT end --
+   }
+ 
+ } // namespace oidn

+ 202 - 0
thirdparty/oidn/weights/LICENSE.txt

@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.