ソースを参照

NVIDIA Image Scaling SDK v1.0

Initial public commit
Ariel Bernal 2 年 前
コミット
76ffb04381
100 ファイル変更58589 行追加1 行削除
  1. 47 0
      .gitignore
  2. 391 0
      NIS/NIS_Config.h
  3. 102 0
      NIS/NIS_Main.hlsl
  4. 972 0
      NIS/NIS_Scaler.h
  5. 381 1
      README.md
  6. BIN
      docs/NIS_SDK_Programming_Guide.pdf
  7. BIN
      docs/RTX UI Developer Guidelines Chinese Version.pdf
  8. BIN
      docs/RTX UI Developer Guidelines.pdf
  9. 20 0
      licence.txt
  10. 8 0
      samples/CMakeLists.txt
  11. 72 0
      samples/DX11/CMakeLists.txt
  12. 70 0
      samples/DX11/include/AppRenderer.h
  13. 75 0
      samples/DX11/include/BilinearUpscale.h
  14. 165 0
      samples/DX11/include/DXUtilities.h
  15. 86 0
      samples/DX11/include/DeviceResources.h
  16. 55 0
      samples/DX11/include/NVScaler.h
  17. 50 0
      samples/DX11/include/NVSharpen.h
  18. 76 0
      samples/DX11/include/UIRenderer.h
  19. 137 0
      samples/DX11/src/AppRenderer.cpp
  20. 152 0
      samples/DX11/src/BilinearUpscale.cpp
  21. 218 0
      samples/DX11/src/DeviceResources.cpp
  22. 98 0
      samples/DX11/src/NVScaler.cpp
  23. 88 0
      samples/DX11/src/NVSharpen.cpp
  24. 159 0
      samples/DX11/src/Sample.cpp
  25. 196 0
      samples/DX11/src/UIRenderer.cpp
  26. 9 0
      samples/DX11/src/dpi.manifest
  27. 67 0
      samples/common/Image.cpp
  28. 53 0
      samples/common/Image.h
  29. 213 0
      samples/common/Utilities.h
  30. BIN
      samples/media/images/1080.png
  31. BIN
      samples/media/images/1440.png
  32. 47 0
      samples/third_party/glfw/.appveyor.yml
  33. 5 0
      samples/third_party/glfw/.gitattributes
  34. 104 0
      samples/third_party/glfw/.gitignore
  35. 10 0
      samples/third_party/glfw/.mailmap
  36. 48 0
      samples/third_party/glfw/CMake/GenerateMappings.cmake
  37. 38 0
      samples/third_party/glfw/CMake/MacOSXBundleInfo.plist.in
  38. 13 0
      samples/third_party/glfw/CMake/i686-w64-mingw32-clang.cmake
  39. 13 0
      samples/third_party/glfw/CMake/i686-w64-mingw32.cmake
  40. 17 0
      samples/third_party/glfw/CMake/modules/FindEpollShim.cmake
  41. 18 0
      samples/third_party/glfw/CMake/modules/FindOSMesa.cmake
  42. 26 0
      samples/third_party/glfw/CMake/modules/FindWaylandProtocols.cmake
  43. 34 0
      samples/third_party/glfw/CMake/modules/FindXKBCommon.cmake
  44. 13 0
      samples/third_party/glfw/CMake/x86_64-w64-mingw32-clang.cmake
  45. 13 0
      samples/third_party/glfw/CMake/x86_64-w64-mingw32.cmake
  46. 386 0
      samples/third_party/glfw/CMakeLists.txt
  47. 220 0
      samples/third_party/glfw/CONTRIBUTORS.md
  48. 23 0
      samples/third_party/glfw/LICENSE.md
  49. 163 0
      samples/third_party/glfw/README.md
  50. 29 0
      samples/third_party/glfw/cmake_uninstall.cmake.in
  51. 230 0
      samples/third_party/glfw/deps/getopt.c
  52. 57 0
      samples/third_party/glfw/deps/getopt.h
  53. 3840 0
      samples/third_party/glfw/deps/glad/gl.h
  54. 282 0
      samples/third_party/glfw/deps/glad/khrplatform.h
  55. 92 0
      samples/third_party/glfw/deps/glad/vk_platform.h
  56. 3480 0
      samples/third_party/glfw/deps/glad/vulkan.h
  57. 1791 0
      samples/third_party/glfw/deps/glad_gl.c
  58. 593 0
      samples/third_party/glfw/deps/glad_vulkan.c
  59. 574 0
      samples/third_party/glfw/deps/linmath.h
  60. 117 0
      samples/third_party/glfw/deps/mingw/_mingw_dxhelper.h
  61. 2467 0
      samples/third_party/glfw/deps/mingw/dinput.h
  62. 239 0
      samples/third_party/glfw/deps/mingw/xinput.h
  63. 25539 0
      samples/third_party/glfw/deps/nuklear.h
  64. 381 0
      samples/third_party/glfw/deps/nuklear_glfw_gl2.h
  65. 1048 0
      samples/third_party/glfw/deps/stb_image_write.h
  66. 594 0
      samples/third_party/glfw/deps/tinycthread.c
  67. 443 0
      samples/third_party/glfw/deps/tinycthread.h
  68. 247 0
      samples/third_party/glfw/deps/vs2008/stdint.h
  69. 34 0
      samples/third_party/glfw/docs/CMakeLists.txt
  70. 10 0
      samples/third_party/glfw/docs/CODEOWNERS
  71. 391 0
      samples/third_party/glfw/docs/CONTRIBUTING.md
  72. 1828 0
      samples/third_party/glfw/docs/Doxyfile.in
  73. 71 0
      samples/third_party/glfw/docs/DoxygenLayout.xml
  74. 14 0
      samples/third_party/glfw/docs/SUPPORT.md
  75. 348 0
      samples/third_party/glfw/docs/build.dox
  76. 285 0
      samples/third_party/glfw/docs/compat.dox
  77. 365 0
      samples/third_party/glfw/docs/compile.dox
  78. 346 0
      samples/third_party/glfw/docs/context.dox
  79. 1 0
      samples/third_party/glfw/docs/extra.css
  80. 1 0
      samples/third_party/glfw/docs/extra.css.map
  81. 430 0
      samples/third_party/glfw/docs/extra.scss
  82. 7 0
      samples/third_party/glfw/docs/footer.html
  83. 34 0
      samples/third_party/glfw/docs/header.html
  84. 950 0
      samples/third_party/glfw/docs/input.dox
  85. 115 0
      samples/third_party/glfw/docs/internal.dox
  86. 454 0
      samples/third_party/glfw/docs/intro.dox
  87. 46 0
      samples/third_party/glfw/docs/main.dox
  88. 268 0
      samples/third_party/glfw/docs/monitor.dox
  89. 513 0
      samples/third_party/glfw/docs/moving.dox
  90. 863 0
      samples/third_party/glfw/docs/news.dox
  91. 365 0
      samples/third_party/glfw/docs/quick.dox
  92. 877 0
      samples/third_party/glfw/docs/spaces.svg
  93. 235 0
      samples/third_party/glfw/docs/vulkan.dox
  94. 1412 0
      samples/third_party/glfw/docs/window.dox
  95. 93 0
      samples/third_party/glfw/examples/CMakeLists.txt
  96. 679 0
      samples/third_party/glfw/examples/boing.c
  97. 360 0
      samples/third_party/glfw/examples/gears.c
  98. BIN
      samples/third_party/glfw/examples/glfw.icns
  99. BIN
      samples/third_party/glfw/examples/glfw.ico
  100. 0 0
      samples/third_party/glfw/examples/glfw.rc

+ 47 - 0
.gitignore

@@ -0,0 +1,47 @@
+# cmake
+CMakeFiles/
+.cmake/
+*.dir/
+*.tlog/
+CMakeCache.txt
+cmake_install.cmake
+*.recipe
+
+# make
+Makefile
+
+# VS
+*.vcxproj*
+*.sln
+.vs/
+
+# VS Code
+.vscode/
+
+# Shaders
+*.dxbc
+*.dxil
+*.spirv
+*.dxbc.h
+*.dxil.h
+*.spirv.h
+
+# Library
+*.lib
+*.exp
+*.dll
+*.pdb
+*.so
+*.so.*
+*.a
+
+# ninja
+.ninja_deps
+.ninja_log
+build.ninja
+compile_commands.json
+*.log
+
+# packaged SDK
+samples/build
+samples/bin

+ 391 - 0
NIS/NIS_Config.h

@@ -0,0 +1,391 @@
+// The MIT License(MIT)
+//
+// Copyright(c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files(the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of
+// the Software, and to permit persons to whom the Software is 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 Software.
+//
+// THE SOFTWARE IS 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 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+#pragma once
+
+#include <algorithm>
+#include <cmath>
+#include <cstdint>
+
+#if defined(_MSC_VER)
+#define NIS_ALIGNED(x) __declspec(align(x))
+#else
+#if defined(__GNUC__)
+#define NIS_ALIGNED(x) __attribute__ ((aligned(x)))
+#endif
+#endif
+
+
+struct NIS_ALIGNED(256) NISConfig
+{
+    float kDetectRatio;
+    float kDetectThres;
+    float kMinContrastRatio;
+    float kRatioNorm;
+
+    float kContrastBoost;
+    float kEps;
+    float kSharpStartY;
+    float kSharpScaleY;
+
+    float kSharpStrengthMin;
+    float kSharpStrengthScale;
+    float kSharpLimitMin;
+    float kSharpLimitScale;
+
+    float kScaleX;
+    float kScaleY;
+    float kDstNormX;
+    float kDstNormY;
+
+    float kSrcNormX;
+    float kSrcNormY;
+
+    uint32_t kInputViewportOriginX;
+    uint32_t kInputViewportOriginY;
+    uint32_t kInputViewportWidth;
+    uint32_t kInputViewportHeight;
+
+    uint32_t kOutputViewportOriginX;
+    uint32_t kOutputViewportOriginY;
+    uint32_t kOutputViewportWidth;
+    uint32_t kOutputViewportHeight;
+
+    float reserved0;
+    float reserved1;
+};
+
+enum class NISHDRMode : uint32_t
+{
+    None = 0,
+    Linear = 1,
+    PQ = 2
+};
+
+enum class NISGPUArchitecture : uint32_t
+{
+    NVIDIA_Generic = 0,
+    AMD_Generic = 1,
+    Intel_Generic = 2
+};
+
+struct NISOptimizer
+{
+    bool isUpscaling;
+    NISGPUArchitecture gpuArch;
+
+    constexpr NISOptimizer(bool isUpscaling = true, NISGPUArchitecture gpuArch = NISGPUArchitecture::NVIDIA_Generic)
+        : isUpscaling(isUpscaling)
+        , gpuArch(gpuArch)
+    {}
+
+    constexpr uint32_t GetOptimalBlockWidth()
+    {
+        switch (gpuArch) {
+        case NISGPUArchitecture::NVIDIA_Generic:
+            return 32;
+        case NISGPUArchitecture::AMD_Generic:
+            return 32;
+        case NISGPUArchitecture::Intel_Generic:
+            return 32;
+        }
+        return 32;
+    }
+
+    constexpr uint32_t GetOptimalBlockHeight()
+    {
+        switch (gpuArch) {
+        case NISGPUArchitecture::NVIDIA_Generic:
+            return isUpscaling ? 24 : 32;
+        case NISGPUArchitecture::AMD_Generic:
+            return isUpscaling ? 24 : 32;
+        case NISGPUArchitecture::Intel_Generic:
+            return isUpscaling ? 24 : 32;
+        }
+        return isUpscaling ? 24 : 32;
+    }
+
+    constexpr uint32_t GetOptimalThreadGroupSize()
+    {
+        switch (gpuArch) {
+        case NISGPUArchitecture::NVIDIA_Generic:
+            return 256;
+        case NISGPUArchitecture::AMD_Generic:
+            return 256;
+        case NISGPUArchitecture::Intel_Generic:
+            return 256;
+        }
+        return 256;
+    }
+};
+
+
+inline bool NVScalerUpdateConfig(NISConfig& config, float sharpness,
+    uint32_t inputViewportOriginX, uint32_t inputViewportOriginY,
+    uint32_t inputViewportWidth, uint32_t inputViewportHeight,
+    uint32_t inputTextureWidth, uint32_t inputTextureHeight,
+    uint32_t outputViewportOriginX, uint32_t outputViewportOriginY,
+    uint32_t outputViewportWidth, uint32_t outputViewportHeight,
+    uint32_t outputTextureWidth, uint32_t outputTextureHeight,
+    NISHDRMode hdrMode = NISHDRMode::None)
+{
+    // adjust params based on value from sharpness slider
+    sharpness = std::max<float>(std::min<float>(1.f, sharpness), 0.f);
+    float sharpen_slider = sharpness - 0.5f;   // Map 0 to 1 to -0.5 to +0.5
+
+    // Different range for 0 to 50% vs 50% to 100%
+    // The idea is to make sure sharpness of 0% map to no-sharpening,
+    // while also ensuring that sharpness of 100% doesn't cause too much over-sharpening.
+    const float MaxScale = (sharpen_slider >= 0.0f) ? 1.25f : 1.75f;
+    const float MinScale = (sharpen_slider >= 0.0f) ? 1.25f : 1.0f;
+    const float LimitScale = (sharpen_slider >= 0.0f) ? 1.25f : 1.0f;
+
+    float kDetectRatio = 1127.f / 1024.f;
+
+    // Params for SDR
+    float kDetectThres = 64.0f / 1024.0f;
+    float kMinContrastRatio = 2.0f;
+    float kMaxContrastRatio = 10.0f;
+
+    float kSharpStartY = 0.45f;
+    float kSharpEndY = 0.9f;
+    float kSharpStrengthMin = std::max<float>(0.0f, 0.4f + sharpen_slider * MinScale * 1.2f);
+    float kSharpStrengthMax = 1.6f + sharpen_slider * 1.8f;
+    float kSharpLimitMin = std::max<float>(0.1f, 0.14f + sharpen_slider * LimitScale * 0.32f);
+    float kSharpLimitMax = 0.5f + sharpen_slider * LimitScale * 0.6f;
+
+    if (hdrMode == NISHDRMode::Linear || hdrMode == NISHDRMode::PQ)
+    {
+        kDetectThres = 32.0f / 1024.0f;
+
+        kMinContrastRatio = 1.5f;
+        kMaxContrastRatio = 5.0f;
+
+        kSharpStrengthMin = std::max<float>(0.0f, 0.4f + sharpen_slider * MinScale * 1.1f);
+        kSharpStrengthMax = 2.2f + sharpen_slider * MaxScale * 1.8f;
+        kSharpLimitMin = std::max<float>(0.06f, 0.10f + sharpen_slider * LimitScale * 0.28f);
+        kSharpLimitMax = 0.6f + sharpen_slider * LimitScale * 0.6f;
+
+        if (hdrMode == NISHDRMode::PQ)
+        {
+            kSharpStartY = 0.35f;
+            kSharpEndY = 0.55f;
+        }
+        else
+        {
+            kSharpStartY = 0.3f;
+            kSharpEndY = 0.5f;
+        }
+    }
+
+    float kRatioNorm = 1.0f / (kMaxContrastRatio - kMinContrastRatio);
+    float kSharpScaleY = 1.0f / (kSharpEndY - kSharpStartY);
+    float kSharpStrengthScale = kSharpStrengthMax - kSharpStrengthMin;
+    float kSharpLimitScale = kSharpLimitMax - kSharpLimitMin;
+
+    config.kInputViewportWidth = inputViewportWidth == 0 ? inputTextureWidth : inputViewportWidth;
+    config.kInputViewportHeight = inputViewportHeight == 0 ? inputTextureHeight : inputViewportHeight;
+    config.kOutputViewportWidth = outputViewportWidth == 0 ? outputTextureWidth : outputViewportWidth;
+    config.kOutputViewportHeight = outputViewportHeight == 0 ? outputTextureHeight : outputViewportHeight;
+    if (config.kInputViewportWidth == 0 || config.kInputViewportHeight == 0 ||
+        config.kOutputViewportWidth == 0 || config.kOutputViewportHeight == 0)
+        return false;
+
+    config.kInputViewportOriginX = inputViewportOriginX;
+    config.kInputViewportOriginY = inputViewportOriginY;
+    config.kOutputViewportOriginX = outputViewportOriginX;
+    config.kOutputViewportOriginY = outputViewportOriginY;
+
+    config.kSrcNormX = 1.f / inputTextureWidth;
+    config.kSrcNormY = 1.f / inputTextureHeight;
+    config.kDstNormX = 1.f / outputTextureWidth;
+    config.kDstNormY = 1.f / outputTextureHeight;
+    config.kScaleX = config.kInputViewportWidth / float(config.kOutputViewportWidth);
+    config.kScaleY = config.kInputViewportHeight / float(config.kOutputViewportHeight);
+    if (config.kScaleX < 0.5f || config.kScaleX > 1.f || config.kScaleY < 0.5f || config.kScaleY > 1.f)
+        return false;
+    config.kDetectRatio = kDetectRatio;
+    config.kDetectThres = kDetectThres;
+    config.kMinContrastRatio = kMinContrastRatio;
+    config.kRatioNorm = kRatioNorm;
+    config.kContrastBoost = 1.0f;
+    config.kEps = 1.0f;
+    config.kSharpStartY = kSharpStartY;
+    config.kSharpScaleY = kSharpScaleY;
+    config.kSharpStrengthMin = kSharpStrengthMin;
+    config.kSharpStrengthScale = kSharpStrengthScale;
+    config.kSharpLimitMin = kSharpLimitMin;
+    config.kSharpLimitScale = kSharpLimitScale;
+    return true;
+}
+
+
+inline bool NVSharpenUpdateConfig(NISConfig& config, float sharpness,
+    uint32_t inputViewportOriginX, uint32_t inputViewportOriginY,
+    uint32_t inputViewportWidth, uint32_t inputViewportHeight,
+    uint32_t inputTextureWidth, uint32_t inputTextureHeight,
+    uint32_t outputViewportOriginX, uint32_t outputViewportOriginY,
+    NISHDRMode hdrMode = NISHDRMode::None)
+{
+    return NVScalerUpdateConfig(config, sharpness,
+            inputViewportOriginX, inputViewportOriginY, inputViewportWidth, inputViewportHeight, inputTextureWidth, inputTextureHeight,
+            outputViewportOriginX, outputViewportOriginY, inputViewportWidth, inputViewportHeight, inputTextureWidth, inputTextureHeight,
+            hdrMode);
+}
+
+namespace {
+    constexpr size_t kPhaseCount = 64;
+    constexpr size_t kFilterSize = 8;
+
+    constexpr float coef_scale[kPhaseCount][kFilterSize] = {
+        {0.0,     0.0,    1.0000, 0.0,     0.0,    0.0, 0.0, 0.0},
+        {0.0029, -0.0127, 1.0000, 0.0132, -0.0034, 0.0, 0.0, 0.0},
+        {0.0063, -0.0249, 0.9985, 0.0269, -0.0068, 0.0, 0.0, 0.0},
+        {0.0088, -0.0361, 0.9956, 0.0415, -0.0103, 0.0005, 0.0, 0.0},
+        {0.0117, -0.0474, 0.9932, 0.0562, -0.0142, 0.0005, 0.0, 0.0},
+        {0.0142, -0.0576, 0.9897, 0.0713, -0.0181, 0.0005, 0.0, 0.0},
+        {0.0166, -0.0674, 0.9844, 0.0874, -0.0220, 0.0010, 0.0, 0.0},
+        {0.0186, -0.0762, 0.9785, 0.1040, -0.0264, 0.0015, 0.0, 0.0},
+        {0.0205, -0.0850, 0.9727, 0.1206, -0.0308, 0.0020, 0.0, 0.0},
+        {0.0225, -0.0928, 0.9648, 0.1382, -0.0352, 0.0024, 0.0, 0.0},
+        {0.0239, -0.1006, 0.9575, 0.1558, -0.0396, 0.0029, 0.0, 0.0},
+        {0.0254, -0.1074, 0.9487, 0.1738, -0.0439, 0.0034, 0.0, 0.0},
+        {0.0264, -0.1138, 0.9390, 0.1929, -0.0488, 0.0044, 0.0, 0.0},
+        {0.0278, -0.1191, 0.9282, 0.2119, -0.0537, 0.0049, 0.0, 0.0},
+        {0.0288, -0.1245, 0.9170, 0.2310, -0.0581, 0.0059, 0.0, 0.0},
+        {0.0293, -0.1294, 0.9058, 0.2510, -0.0630, 0.0063, 0.0, 0.0},
+        {0.0303, -0.1333, 0.8926, 0.2710, -0.0679, 0.0073, 0.0, 0.0},
+        {0.0308, -0.1367, 0.8789, 0.2915, -0.0728, 0.0083, 0.0, 0.0},
+        {0.0308, -0.1401, 0.8657, 0.3120, -0.0776, 0.0093, 0.0, 0.0},
+        {0.0313, -0.1426, 0.8506, 0.3330, -0.0825, 0.0103, 0.0, 0.0},
+        {0.0313, -0.1445, 0.8354, 0.3540, -0.0874, 0.0112, 0.0, 0.0},
+        {0.0313, -0.1460, 0.8193, 0.3755, -0.0923, 0.0122, 0.0, 0.0},
+        {0.0313, -0.1470, 0.8022, 0.3965, -0.0967, 0.0137, 0.0, 0.0},
+        {0.0308, -0.1479, 0.7856, 0.4185, -0.1016, 0.0146, 0.0, 0.0},
+        {0.0303, -0.1479, 0.7681, 0.4399, -0.1060, 0.0156, 0.0, 0.0},
+        {0.0298, -0.1479, 0.7505, 0.4614, -0.1104, 0.0166, 0.0, 0.0},
+        {0.0293, -0.1470, 0.7314, 0.4829, -0.1147, 0.0181, 0.0, 0.0},
+        {0.0288, -0.1460, 0.7119, 0.5049, -0.1187, 0.0190, 0.0, 0.0},
+        {0.0278, -0.1445, 0.6929, 0.5264, -0.1226, 0.0200, 0.0, 0.0},
+        {0.0273, -0.1431, 0.6724, 0.5479, -0.1260, 0.0215, 0.0, 0.0},
+        {0.0264, -0.1411, 0.6528, 0.5693, -0.1299, 0.0225, 0.0, 0.0},
+        {0.0254, -0.1387, 0.6323, 0.5903, -0.1328, 0.0234, 0.0, 0.0},
+        {0.0244, -0.1357, 0.6113, 0.6113, -0.1357, 0.0244, 0.0, 0.0},
+        {0.0234, -0.1328, 0.5903, 0.6323, -0.1387, 0.0254, 0.0, 0.0},
+        {0.0225, -0.1299, 0.5693, 0.6528, -0.1411, 0.0264, 0.0, 0.0},
+        {0.0215, -0.1260, 0.5479, 0.6724, -0.1431, 0.0273, 0.0, 0.0},
+        {0.0200, -0.1226, 0.5264, 0.6929, -0.1445, 0.0278, 0.0, 0.0},
+        {0.0190, -0.1187, 0.5049, 0.7119, -0.1460, 0.0288, 0.0, 0.0},
+        {0.0181, -0.1147, 0.4829, 0.7314, -0.1470, 0.0293, 0.0, 0.0},
+        {0.0166, -0.1104, 0.4614, 0.7505, -0.1479, 0.0298, 0.0, 0.0},
+        {0.0156, -0.1060, 0.4399, 0.7681, -0.1479, 0.0303, 0.0, 0.0},
+        {0.0146, -0.1016, 0.4185, 0.7856, -0.1479, 0.0308, 0.0, 0.0},
+        {0.0137, -0.0967, 0.3965, 0.8022, -0.1470, 0.0313, 0.0, 0.0},
+        {0.0122, -0.0923, 0.3755, 0.8193, -0.1460, 0.0313, 0.0, 0.0},
+        {0.0112, -0.0874, 0.3540, 0.8354, -0.1445, 0.0313, 0.0, 0.0},
+        {0.0103, -0.0825, 0.3330, 0.8506, -0.1426, 0.0313, 0.0, 0.0},
+        {0.0093, -0.0776, 0.3120, 0.8657, -0.1401, 0.0308, 0.0, 0.0},
+        {0.0083, -0.0728, 0.2915, 0.8789, -0.1367, 0.0308, 0.0, 0.0},
+        {0.0073, -0.0679, 0.2710, 0.8926, -0.1333, 0.0303, 0.0, 0.0},
+        {0.0063, -0.0630, 0.2510, 0.9058, -0.1294, 0.0293, 0.0, 0.0},
+        {0.0059, -0.0581, 0.2310, 0.9170, -0.1245, 0.0288, 0.0, 0.0},
+        {0.0049, -0.0537, 0.2119, 0.9282, -0.1191, 0.0278, 0.0, 0.0},
+        {0.0044, -0.0488, 0.1929, 0.9390, -0.1138, 0.0264, 0.0, 0.0},
+        {0.0034, -0.0439, 0.1738, 0.9487, -0.1074, 0.0254, 0.0, 0.0},
+        {0.0029, -0.0396, 0.1558, 0.9575, -0.1006, 0.0239, 0.0, 0.0},
+        {0.0024, -0.0352, 0.1382, 0.9648, -0.0928, 0.0225, 0.0, 0.0},
+        {0.0020, -0.0308, 0.1206, 0.9727, -0.0850, 0.0205, 0.0, 0.0},
+        {0.0015, -0.0264, 0.1040, 0.9785, -0.0762, 0.0186, 0.0, 0.0},
+        {0.0010, -0.0220, 0.0874, 0.9844, -0.0674, 0.0166, 0.0, 0.0},
+        {0.0005, -0.0181, 0.0713, 0.9897, -0.0576, 0.0142, 0.0, 0.0},
+        {0.0005, -0.0142, 0.0562, 0.9932, -0.0474, 0.0117, 0.0, 0.0},
+        {0.0005, -0.0103, 0.0415, 0.9956, -0.0361, 0.0088, 0.0, 0.0},
+        {0.0, -0.0068, 0.0269, 0.9985, -0.0249, 0.0063, 0.0, 0.0},
+        {0.0, -0.0034, 0.0132, 1.0000, -0.0127, 0.0029, 0.0, 0.0}
+    };
+
+    constexpr float coef_usm[kPhaseCount][kFilterSize] = {
+        {0,      -0.6001, 1.2002, -0.6001,  0,      0, 0, 0},
+        {0.0029, -0.6084, 1.1987, -0.5903, -0.0029, 0, 0, 0},
+        {0.0049, -0.6147, 1.1958, -0.5791, -0.0068, 0.0005, 0, 0},
+        {0.0073, -0.6196, 1.1890, -0.5659, -0.0103, 0, 0, 0},
+        {0.0093, -0.6235, 1.1802, -0.5513, -0.0151, 0, 0, 0},
+        {0.0112, -0.6265, 1.1699, -0.5352, -0.0195, 0.0005, 0, 0},
+        {0.0122, -0.6270, 1.1582, -0.5181, -0.0259, 0.0005, 0, 0},
+        {0.0142, -0.6284, 1.1455, -0.5005, -0.0317, 0.0005, 0, 0},
+        {0.0156, -0.6265, 1.1274, -0.4790, -0.0386, 0.0005, 0, 0},
+        {0.0166, -0.6235, 1.1089, -0.4570, -0.0454, 0.0010, 0, 0},
+        {0.0176, -0.6187, 1.0879, -0.4346, -0.0532, 0.0010, 0, 0},
+        {0.0181, -0.6138, 1.0659, -0.4102, -0.0615, 0.0015, 0, 0},
+        {0.0190, -0.6069, 1.0405, -0.3843, -0.0698, 0.0015, 0, 0},
+        {0.0195, -0.6006, 1.0161, -0.3574, -0.0796, 0.0020, 0, 0},
+        {0.0200, -0.5928, 0.9893, -0.3286, -0.0898, 0.0024, 0, 0},
+        {0.0200, -0.5820, 0.9580, -0.2988, -0.1001, 0.0029, 0, 0},
+        {0.0200, -0.5728, 0.9292, -0.2690, -0.1104, 0.0034, 0, 0},
+        {0.0200, -0.5620, 0.8975, -0.2368, -0.1226, 0.0039, 0, 0},
+        {0.0205, -0.5498, 0.8643, -0.2046, -0.1343, 0.0044, 0, 0},
+        {0.0200, -0.5371, 0.8301, -0.1709, -0.1465, 0.0049, 0, 0},
+        {0.0195, -0.5239, 0.7944, -0.1367, -0.1587, 0.0054, 0, 0},
+        {0.0195, -0.5107, 0.7598, -0.1021, -0.1724, 0.0059, 0, 0},
+        {0.0190, -0.4966, 0.7231, -0.0649, -0.1865, 0.0063, 0, 0},
+        {0.0186, -0.4819, 0.6846, -0.0288, -0.1997, 0.0068, 0, 0},
+        {0.0186, -0.4668, 0.6460, 0.0093, -0.2144, 0.0073, 0, 0},
+        {0.0176, -0.4507, 0.6055, 0.0479, -0.2290, 0.0083, 0, 0},
+        {0.0171, -0.4370, 0.5693, 0.0859, -0.2446, 0.0088, 0, 0},
+        {0.0161, -0.4199, 0.5283, 0.1255, -0.2598, 0.0098, 0, 0},
+        {0.0161, -0.4048, 0.4883, 0.1655, -0.2754, 0.0103, 0, 0},
+        {0.0151, -0.3887, 0.4497, 0.2041, -0.2910, 0.0107, 0, 0},
+        {0.0142, -0.3711, 0.4072, 0.2446, -0.3066, 0.0117, 0, 0},
+        {0.0137, -0.3555, 0.3672, 0.2852, -0.3228, 0.0122, 0, 0},
+        {0.0132, -0.3394, 0.3262, 0.3262, -0.3394, 0.0132, 0, 0},
+        {0.0122, -0.3228, 0.2852, 0.3672, -0.3555, 0.0137, 0, 0},
+        {0.0117, -0.3066, 0.2446, 0.4072, -0.3711, 0.0142, 0, 0},
+        {0.0107, -0.2910, 0.2041, 0.4497, -0.3887, 0.0151, 0, 0},
+        {0.0103, -0.2754, 0.1655, 0.4883, -0.4048, 0.0161, 0, 0},
+        {0.0098, -0.2598, 0.1255, 0.5283, -0.4199, 0.0161, 0, 0},
+        {0.0088, -0.2446, 0.0859, 0.5693, -0.4370, 0.0171, 0, 0},
+        {0.0083, -0.2290, 0.0479, 0.6055, -0.4507, 0.0176, 0, 0},
+        {0.0073, -0.2144, 0.0093, 0.6460, -0.4668, 0.0186, 0, 0},
+        {0.0068, -0.1997, -0.0288, 0.6846, -0.4819, 0.0186, 0, 0},
+        {0.0063, -0.1865, -0.0649, 0.7231, -0.4966, 0.0190, 0, 0},
+        {0.0059, -0.1724, -0.1021, 0.7598, -0.5107, 0.0195, 0, 0},
+        {0.0054, -0.1587, -0.1367, 0.7944, -0.5239, 0.0195, 0, 0},
+        {0.0049, -0.1465, -0.1709, 0.8301, -0.5371, 0.0200, 0, 0},
+        {0.0044, -0.1343, -0.2046, 0.8643, -0.5498, 0.0205, 0, 0},
+        {0.0039, -0.1226, -0.2368, 0.8975, -0.5620, 0.0200, 0, 0},
+        {0.0034, -0.1104, -0.2690, 0.9292, -0.5728, 0.0200, 0, 0},
+        {0.0029, -0.1001, -0.2988, 0.9580, -0.5820, 0.0200, 0, 0},
+        {0.0024, -0.0898, -0.3286, 0.9893, -0.5928, 0.0200, 0, 0},
+        {0.0020, -0.0796, -0.3574, 1.0161, -0.6006, 0.0195, 0, 0},
+        {0.0015, -0.0698, -0.3843, 1.0405, -0.6069, 0.0190, 0, 0},
+        {0.0015, -0.0615, -0.4102, 1.0659, -0.6138, 0.0181, 0, 0},
+        {0.0010, -0.0532, -0.4346, 1.0879, -0.6187, 0.0176, 0, 0},
+        {0.0010, -0.0454, -0.4570, 1.1089, -0.6235, 0.0166, 0, 0},
+        {0.0005, -0.0386, -0.4790, 1.1274, -0.6265, 0.0156, 0, 0},
+        {0.0005, -0.0317, -0.5005, 1.1455, -0.6284, 0.0142, 0, 0},
+        {0.0005, -0.0259, -0.5181, 1.1582, -0.6270, 0.0122, 0, 0},
+        {0.0005, -0.0195, -0.5352, 1.1699, -0.6265, 0.0112, 0, 0},
+        {0, -0.0151, -0.5513, 1.1802, -0.6235, 0.0093, 0, 0},
+        {0, -0.0103, -0.5659, 1.1890, -0.6196, 0.0073, 0, 0},
+        {0.0005, -0.0068, -0.5791, 1.1958, -0.6147, 0.0049, 0, 0},
+        {0, -0.0029, -0.5903, 1.1987, -0.6084, 0.0029, 0, 0}
+    };
+}

+ 102 - 0
NIS/NIS_Main.hlsl

@@ -0,0 +1,102 @@
+// The MIT License(MIT)
+// 
+// Copyright(c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+// 
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files(the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of
+// the Software, and to permit persons to whom the Software is 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 Software.
+// 
+// THE SOFTWARE IS 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 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+#ifndef NIS_SCALER
+#define NIS_SCALER 1
+#endif
+
+#ifndef NIS_DXC
+#define NIS_DXC 0
+#endif
+
+#if NIS_DXC
+#define NIS_PUSH_CONSTANT    [[vk::push_constant]]
+#define NIS_BINDING(bindingIndex) [[vk::binding(bindingIndex, 0)]]
+#define NIS_CONSTANT_BUFFER(structName, variableName, bufferRegister) \
+        ConstantBuffer<structName> variableName : register(bufferRegister);
+#else
+#define NIS_PUSH_CONSTANT
+#define NIS_BINDING(bindingIndex)
+#define NIS_CONSTANT_BUFFER(structName, variableName, bufferRegister) \
+        cbuffer cbufferType : register(bufferRegister) { structName variableName; };
+#endif
+
+
+NIS_BINDING(0) cbuffer cb : register(b0)
+{
+    float kDetectRatio;
+    float kDetectThres;
+    float kMinContrastRatio;
+    float kRatioNorm;
+
+    float kContrastBoost;
+    float kEps;
+    float kSharpStartY;
+    float kSharpScaleY;
+
+    float kSharpStrengthMin;
+    float kSharpStrengthScale;
+    float kSharpLimitMin;
+    float kSharpLimitScale;
+
+    float kScaleX;
+    float kScaleY;
+
+    float kDstNormX;
+    float kDstNormY;
+    float kSrcNormX;
+    float kSrcNormY;
+    
+    uint kInputViewportOriginX;
+    uint kInputViewportOriginY;
+    uint kInputViewportWidth;
+    uint kInputViewportHeight;
+
+    uint kOutputViewportOriginX;
+    uint kOutputViewportOriginY;
+    uint kOutputViewportWidth;
+    uint kOutputViewportHeight;
+
+    float reserved0;
+    float reserved1;
+};
+
+NIS_BINDING(1) SamplerState samplerLinearClamp : register(s0);
+NIS_BINDING(2) Texture2D in_texture            : register(t0);
+NIS_BINDING(3) RWTexture2D<unorm float4> out_texture : register(u0);
+#if NIS_SCALER
+NIS_BINDING(4) Texture2D coef_scaler           : register(t1);
+NIS_BINDING(5) Texture2D coef_usm              : register(t2);
+#endif
+
+
+
+#include "NIS_Scaler.h"
+
+[numthreads(NIS_THREAD_GROUP_SIZE, 1, 1)]
+void main(uint3 blockIdx : SV_GroupID, uint3 threadIdx : SV_GroupThreadID)
+{
+#if NIS_SCALER
+    NVScaler(blockIdx.xy, threadIdx.x);
+#else
+    NVSharpen(blockIdx.xy, threadIdx.x);
+#endif
+}

+ 972 - 0
NIS/NIS_Scaler.h

@@ -0,0 +1,972 @@
+// The MIT License(MIT)
+//
+// Copyright(c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files(the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of
+// the Software, and to permit persons to whom the Software is 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 Software.
+//
+// THE SOFTWARE IS 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 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+//---------------------------------------------------------------------------------
+// NVIDIA Image Scaling SDK  - v1.0
+//---------------------------------------------------------------------------------
+// The NVIDIA Image Scaling SDK provides a single spatial scaling and sharpening algorithm 
+// for cross-platform support. The scaling algorithm uses a 6-tap scaling filter combined 
+// with 4 directional scaling and adaptive sharpening filters, which creates nice smooth images
+// and sharp edges. In addition, the SDK provides a state-of-the-art adaptive directional sharpening algorithm
+// for use in applications where no scaling is required. 
+//
+// The directional scaling and sharpening algorithm is named NVScaler while the adaptive-directional-sharpening-only 
+// algorithm is named NVSharpen. Both algorithms are provided as compute shaders and 
+// developers are free to integrate them in their applications. Note that if you integrate NVScaler, you 
+// should NOT integrate NVSharpen, as NVScaler already includes a sharpening pass
+// 
+// Pipeline Placement
+// ------------------
+// The call into the NVIDIA Image Scaling shaders must occur during the post-processing phase after tone-mapping. 
+// Applying the scaling in linear HDR in-game color-space may result in a sharpening effect that is
+// either not visible or too strong. Since sharpening algorithms can enhance noisy or grainy regions, it is recommended
+// that certain effects such as film grain should occur after NVScaler or NVSharpen. Low-pass filters such as motion blur or 
+// light bloom are recommended to be applied before NVScaler or NVSharpen to avoid sharpening attenuation.
+//
+// Color Space and Ranges 
+// ----------------------
+// NVIDIA Image Scaling shaders can process color textures stored as either LDR or HDR with the following 
+// restrictions:
+// 1) LDR
+//    - The range of color values must be in the [0, 1] range
+//    - The input color texture must be in display-referred color-space after tone mapping and OETF (gamma-correction)
+//      has been applied
+// 2) HDR PQ
+//    - The range of color values must be in the [0, 1] range
+//    - The input color texture must be in display-referred color-space after tone mapping with Rec.2020 PQ OETF applied
+// 3) HDR Linear
+//    - The recommended range of color values is [0, 12.5], where luminance value (as per BT. 709) of 
+//      1.0 maps to brightness value of 80nits (sRGB peak) and 12.5 maps to 1000nits
+//    - The input color texture may have luminance values that are either linear and scene-referred or 
+//      linear and display-referred (after tone mapping)
+//
+// If the input color texture sent to NVScaler/NVSharpen is in HDR format set NIS_HDR_MODE define to either 
+// NIS_HDR_MODE_LINEAR (1) or NIS_HDR_MODE_PQ (2).
+//
+// Supported Texture Formats
+// -------------------------
+// Input and output formats:
+// Input and output formats are expected to be in the rages defined in previous section and should be 
+// specified using non-integer data types such as DXGI_FORMAT_R8G8B8A8_UNORM.
+//
+// Coefficients formats: 
+// The scaler coefficients and USM coefficients format should be specified using float4 type such as
+// DXGI_FORMAT_R32G32B32A32_FLOAT or DXGI_FORMAT_R16G16B16A16_FLOAT.
+//
+// Resource States, Buffers, and Sampler:
+// The game or application calling NVIDIA Image Scaling SDK shaders must ensure that the textures are in 
+// the correct state.
+// - Input color textures must be in pixel shader read state. Shader Resource View (SRV) in DirectX
+// - The output texture must be in read/write state. Unordered Access View (UAV) in DirectX
+// - The coefficients texture for NVScaler must be in read state. Shader Resource View (SRV) in DirectX
+// - The configuration variables must be passed as constant buffer. Constant Buffer View (CBV) in DirectX
+// - The sampler for texture pixel sampling. Linear clamp SamplerState in Direct
+//
+// Adding NVIDIA Image Scaling SDK to a Project
+// --------------------------------------------
+// Include NIS_Scaler.h directly in your application or alternative use the provided NIS_Main.hlsl shader file.
+// Use NIS_Config.h to get the ideal shader dispatch values for your platform, to configure the algorithm constant 
+// values (NVScalerUpdateConfig, and NVSharpenUpdateConfig), and to access the algorithm coefficients (coef_scale and coef_USM).
+//
+// Defines:
+// NIS_SCALER: default (1) NVScaler, (0) fast NVSharpen only, no upscaling
+// NIS_HDR_MODE: default(0) disabled, (1) Linear, (2) PQ
+// NIS_BLOCK_WIDTH: pixels per block width. Use GetOptimalBlockWidth query for your platform
+// NIS_BLOCK_HEIGHT: pixels per block height. Use GetOptimalBlockHeight query for your platform
+// NIS_THREAD_GROUP_SIZE: number of threads per group. Use GetOptimalThreadGroupSize query for your platform
+// NIS_USE_HALF_PRECISION: default(0) disabled, (1) enable half pression computation
+// NIS_HLSL_6_2: default (0) HLSL v5, (1) HLSL v6.2 
+// NIS_VIEWPORT_SUPPORT: default(0) disabled, (1) enable input/output viewport support
+// 
+// Default NVScaler shader constants:
+// [NIS_BLOCK_WIDTH, NIS_BLOCK_HEIGHT, NIS_THREAD_GROUP_SIZE] = [32, 24, 256]
+//
+// Default NVSharpen shader constants:
+// [NIS_BLOCK_WIDTH, NIS_BLOCK_HEIGHT, NIS_THREAD_GROUP_SIZE] = [32, 32, 256]
+//---------------------------------------------------------------------------------
+
+// NVScaler enable by default. Set to 0 for NVSharpen only
+#ifndef NIS_SCALER
+#define NIS_SCALER 1
+#endif
+
+// HDR Modes
+#define NIS_HDR_MODE_NONE  0 
+#define NIS_HDR_MODE_LINEAR  1
+#define NIS_HDR_MODE_PQ  2
+#ifndef NIS_HDR_MODE
+#define NIS_HDR_MODE NIS_HDR_MODE_NONE
+#endif
+#define kHDRCompressionFactor  0.282842712f
+
+// Viewport support
+#ifndef NIS_VIEWPORT_SUPPORT
+#define NIS_VIEWPORT_SUPPORT 0
+#endif
+
+// Half precision
+#ifndef NIS_USE_HALF_PRECISION
+#define NIS_USE_HALF_PRECISION 0
+#endif
+#ifndef NIS_HLSL_6_2
+#define NIS_HLSL_6_2 0
+#endif
+
+#if NIS_USE_HALF_PRECISION
+#if NIS_HLSL_6_2
+typedef float16_t4 NVF4;
+typedef float16_t NVF;
+#else
+typedef min16float4 NVF4;
+typedef min16float NVF;
+#endif // NIS_HLSL_6_2
+#define NIS_SCALE_INT 1
+#define NIS_SCALE_FLOAT 1.0
+#else
+typedef float4 NVF4;
+typedef float NVF;
+#define NIS_SCALE_INT 255
+#define NIS_SCALE_FLOAT 255.0
+#endif // NIS_USE_HALF_PRECISION
+
+// Loop unrolling
+#ifndef NIS_UNROLL
+#define NIS_UNROLL [unroll]
+#endif 
+
+// Texture gather
+#ifndef NIS_TEXTURE_GATHER
+#define NIS_TEXTURE_GATHER 0
+#endif
+
+float getY(float3 rgba)
+{
+#if NIS_HDR_MODE == NIS_HDR_MODE_PQ
+    return 0.262f * rgba.x + 0.678f * rgba.y + 0.0593f * rgba.z;
+#elif NIS_HDR_MODE == NIS_HDR_MODE_LINEAR    
+    return sqrt(0.2126f * rgba.x + 0.7152f * rgba.y + 0.0722f * rgba.z) * kHDRCompressionFactor;
+#else
+    return 0.2126f * rgba.x + 0.7152f * rgba.y + 0.0722f * rgba.z;
+#endif
+}
+
+float getYLinear(float3 rgba)
+{
+    return 0.2126f * rgba.x + 0.7152f * rgba.y + 0.0722f * rgba.z;
+};
+
+#if NIS_SCALER
+float4 GetEdgeMap(float p[4][4], int i, int j)
+#else
+float4 GetEdgeMap(float p[5][5], int i, int j)
+#endif
+{
+    const float g_0 = abs(p[0 + i][0 + j] + p[0 + i][1 + j] + p[0 + i][2 + j] - p[2 + i][0 + j] - p[2 + i][1 + j] - p[2 + i][2 + j]);
+    const float g_45 = abs(p[1 + i][0 + j] + p[0 + i][0 + j] + p[0 + i][1 + j] - p[2 + i][1 + j] - p[2 + i][2 + j] - p[1 + i][2 + j]);
+    const float g_90 = abs(p[0 + i][0 + j] + p[1 + i][0 + j] + p[2 + i][0 + j] - p[0 + i][2 + j] - p[1 + i][2 + j] - p[2 + i][2 + j]);
+    const float g_135 = abs(p[1 + i][0 + j] + p[2 + i][0 + j] + p[2 + i][1 + j] - p[0 + i][1 + j] - p[0 + i][2 + j] - p[1 + i][2 + j]);
+
+    const float g_0_90_max = max(g_0, g_90);
+    const float g_0_90_min = min(g_0, g_90);
+    const float g_45_135_max = max(g_45, g_135);
+    const float g_45_135_min = min(g_45, g_135);
+
+    float e_0_90 = 0;
+    float e_45_135 = 0;
+
+    float edge_0 = 0;
+    float edge_45 = 0;
+    float edge_90 = 0;
+    float edge_135 = 0;
+
+    if ((g_0_90_max + g_45_135_max) == 0)
+    {
+        e_0_90 = 0;
+        e_45_135 = 0;
+    }
+    else
+    {
+        e_0_90 = g_0_90_max / (g_0_90_max + g_45_135_max);
+        e_0_90 = min(e_0_90, 1.0f);
+        e_45_135 = 1.0f - e_0_90;
+    }
+
+    if ((g_0_90_max > (g_0_90_min * kDetectRatio)) && (g_0_90_max > kDetectThres) && (g_0_90_max > g_45_135_min))
+    {
+        if (g_0_90_max == g_0)
+        {
+            edge_0 = 1.0f;
+            edge_90 = 0;
+        }
+        else
+        {
+            edge_0 = 0;
+            edge_90 = 1.0f;
+        }
+    }
+    else
+    {
+        edge_0 = 0;
+        edge_90 = 0;
+    }
+
+    if ((g_45_135_max > (g_45_135_min * kDetectRatio)) && (g_45_135_max > kDetectThres) &&
+        (g_45_135_max > g_0_90_min))
+    {
+
+        if (g_45_135_max == g_45)
+        {
+            edge_45 = 1.0f;
+            edge_135 = 0;
+        }
+        else
+        {
+            edge_45 = 0;
+            edge_135 = 1.0f;
+        }
+    }
+    else
+    {
+        edge_45 = 0;
+        edge_135 = 0;
+    }
+
+    float weight_0, weight_90, weight_45, weight_135;
+    if ((edge_0 + edge_90 + edge_45 + edge_135) >= 2.0f)
+    {
+        if (edge_0 == 1.0f)
+        {
+            weight_0 = e_0_90;
+            weight_90 = 0;
+        }
+        else
+        {
+            weight_0 = 0;
+            weight_90 = e_0_90;
+        }
+
+        if (edge_45 == 1.0f)
+        {
+            weight_45 = e_45_135;
+            weight_135 = 0;
+        }
+        else
+        {
+            weight_45 = 0;
+            weight_135 = e_45_135;
+        }
+    }
+    else if ((edge_0 + edge_90 + edge_45 + edge_135) >= 1.0f)
+    {
+        weight_0 = edge_0;
+        weight_90 = edge_90;
+        weight_45 = edge_45;
+        weight_135 = edge_135;
+    }
+    else
+    {
+        weight_0 = 0;
+        weight_90 = 0;
+        weight_45 = 0;
+        weight_135 = 0;
+    }
+
+    return float4(weight_0, weight_90, weight_45, weight_135);
+}
+
+#if NIS_SCALER
+
+#ifndef NIS_BLOCK_WIDTH
+#define NIS_BLOCK_WIDTH 32
+#endif 
+#ifndef NIS_BLOCK_HEIGHT
+#define NIS_BLOCK_HEIGHT 24
+#endif
+#ifndef NIS_THREAD_GROUP_SIZE
+#define NIS_THREAD_GROUP_SIZE 256
+#endif
+#define kPhaseCount  64
+#define kFilterSize  8
+#define kSupportSize 6
+#define kPadSize     kSupportSize
+#define kTileSize    (NIS_BLOCK_WIDTH + kPadSize) * (NIS_BLOCK_HEIGHT + kPadSize)
+#define blockDim     NIS_THREAD_GROUP_SIZE
+
+groupshared NVF shPixelsY[kTileSize];
+groupshared NVF shCoefScaler[kPhaseCount][kFilterSize];
+groupshared NVF shCoefUSM[kPhaseCount][kFilterSize];
+groupshared NVF4 shEdgeMap[kTileSize];
+
+void LoadFilterBanksSh(int i0, int di)
+{
+    // load up filter banks to shared memory
+    for (int i = i0; i < kFilterSize * kPhaseCount / 4 / 2; i += di)
+    {
+        NVF4 v0 = coef_scaler[int2(0, i)];
+        NVF4 v1 = coef_scaler[int2(1, i)];
+        shCoefScaler[i][0] = (NVF)v0.x;
+        shCoefScaler[i][1] = (NVF)v0.y;
+        shCoefScaler[i][2] = (NVF)v0.z;
+        shCoefScaler[i][3] = (NVF)v0.w;
+        shCoefScaler[i][4] = (NVF)v1.x;
+        shCoefScaler[i][5] = (NVF)v1.y;
+
+        v0 = coef_usm[int2(0, i)];
+        v1 = coef_usm[int2(1, i)];
+        shCoefUSM[i][0] = (NVF)v0.x;
+        shCoefUSM[i][1] = (NVF)v0.y;
+        shCoefUSM[i][2] = (NVF)v0.z;
+        shCoefUSM[i][3] = (NVF)v0.w;
+        shCoefUSM[i][4] = (NVF)v1.x;
+        shCoefUSM[i][5] = (NVF)v1.y;
+    }
+}
+
+float CalcLTI(float p0, float p1, float p2, float p3, float p4, float p5, int phase_index)
+{
+    float y0, y1, y2, y3, y4;
+
+    if (phase_index <= kPhaseCount / 2)
+    {
+        y0 = p0;
+        y1 = p1;
+        y2 = p2;
+        y3 = p3;
+        y4 = p4;
+    }
+    else
+    {
+        y0 = p1;
+        y1 = p2;
+        y2 = p3;
+        y3 = p4;
+        y4 = p5;
+    }
+
+    const float a_min = min(min(y0, y1), y2);
+    const float a_max = max(max(y0, y1), y2);
+
+    const float b_min = min(min(y2, y3), y4);
+    const float b_max = max(max(y2, y3), y4);
+
+    const float a_cont = a_max - a_min;
+    const float b_cont = b_max - b_min;
+
+    const float cont_ratio = max(a_cont, b_cont) / (min(a_cont, b_cont) + kEps);
+    return (1.0f - saturate((cont_ratio - kMinContrastRatio) * kRatioNorm)) * kContrastBoost;
+}
+
+float4 GetInterpEdgeMap(const float4 edge[2][2], float phase_frac_x, float phase_frac_y)
+{
+    float4 h0, h1, f;
+
+    h0.x = lerp(edge[0][0].x, edge[0][1].x, phase_frac_x);
+    h0.y = lerp(edge[0][0].y, edge[0][1].y, phase_frac_x);
+    h0.z = lerp(edge[0][0].z, edge[0][1].z, phase_frac_x);
+    h0.w = lerp(edge[0][0].w, edge[0][1].w, phase_frac_x);
+
+    h1.x = lerp(edge[1][0].x, edge[1][1].x, phase_frac_x);
+    h1.y = lerp(edge[1][0].y, edge[1][1].y, phase_frac_x);
+    h1.z = lerp(edge[1][0].z, edge[1][1].z, phase_frac_x);
+    h1.w = lerp(edge[1][0].w, edge[1][1].w, phase_frac_x);
+
+    f.x = lerp(h0.x, h1.x, phase_frac_y);
+    f.y = lerp(h0.y, h1.y, phase_frac_y);
+    f.z = lerp(h0.z, h1.z, phase_frac_y);
+    f.w = lerp(h0.w, h1.w, phase_frac_y);
+
+    return f;
+}
+
+float EvalPoly6(const float pxl[6], int phase_int)
+{
+    float y = 0.f;
+    {
+        NIS_UNROLL
+        for (int i = 0; i < 6; ++i)
+        {
+            y += shCoefScaler[phase_int][i] * pxl[i];
+        }
+    }
+    float y_usm = 0.f;
+    {
+        NIS_UNROLL
+        for (int i = 0; i < 6; ++i)
+        {
+            y_usm += shCoefUSM[phase_int][i] * pxl[i];
+        }
+    }
+
+    // let's compute a piece-wise ramp based on luma
+    const float y_scale = 1.0f - saturate((y * (1.0f / 255) - kSharpStartY) * kSharpScaleY);
+
+    // scale the ramp to sharpen as a function of luma
+    const float y_sharpness = y_scale * kSharpStrengthScale + kSharpStrengthMin;
+
+    y_usm *= y_sharpness;
+
+    // scale the ramp to limit USM as a function of luma
+    const float y_sharpness_limit = (y_scale * kSharpLimitScale + kSharpLimitMin) * y;
+
+    y_usm = min(y_sharpness_limit, max(-y_sharpness_limit, y_usm));
+    // reduce ringing
+    y_usm *= CalcLTI(pxl[0], pxl[1], pxl[2], pxl[3], pxl[4], pxl[5], phase_int);
+
+    return y + y_usm;
+}
+
+float FilterNormal(const float p[6][6], int phase_x_frac_int, int phase_y_frac_int)
+{
+    float h_acc = 0.0f;
+    NIS_UNROLL
+    for (int j = 0; j < 6; ++j)
+    {
+        float v_acc = 0.0f;
+        NIS_UNROLL
+        for (int i = 0; i < 6; ++i)
+        {
+            v_acc += p[i][j] * shCoefScaler[phase_y_frac_int][i];
+        }
+        h_acc += v_acc * shCoefScaler[phase_x_frac_int][j];
+    }
+
+    // let's return the sum unpacked -> we can accumulate it later
+    return h_acc;
+}
+
+float4 GetDirFilters(float p[6][6], float phase_x_frac, float phase_y_frac, int phase_x_frac_int, int phase_y_frac_int)
+{
+    float4 f;
+    // 0 deg filter
+    float interp0Deg[6];
+    {
+        NIS_UNROLL
+        for (int i = 0; i < 6; ++i)
+        {
+            interp0Deg[i] = lerp(p[i][2], p[i][3], phase_x_frac);
+        }
+    }
+
+    f.x = EvalPoly6(interp0Deg, phase_y_frac_int);
+
+    // 90 deg filter
+    float interp90Deg[6];
+    {
+        NIS_UNROLL
+        for (int i = 0; i < 6; ++i)
+        {
+            interp90Deg[i] = lerp(p[2][i], p[3][i], phase_y_frac);
+        }
+    }
+
+    f.y = EvalPoly6(interp90Deg, phase_x_frac_int);
+
+    //45 deg filter
+    float pphase_b45;
+    pphase_b45 = 0.5f + 0.5f * (phase_x_frac - phase_y_frac);
+
+    float temp_interp45Deg[7];
+    temp_interp45Deg[1] = lerp(p[2][1], p[1][2], pphase_b45);
+    temp_interp45Deg[3] = lerp(p[3][2], p[2][3], pphase_b45);
+    temp_interp45Deg[5] = lerp(p[4][3], p[3][4], pphase_b45);
+
+    if (pphase_b45 >= 0.5f)
+    {
+        pphase_b45 = pphase_b45 - 0.5f;
+
+        temp_interp45Deg[0] = lerp(p[1][1], p[0][2], pphase_b45);
+        temp_interp45Deg[2] = lerp(p[2][2], p[1][3], pphase_b45);
+        temp_interp45Deg[4] = lerp(p[3][3], p[2][4], pphase_b45);
+        temp_interp45Deg[6] = lerp(p[4][4], p[3][5], pphase_b45);
+    }
+    else
+    {
+        pphase_b45 = 0.5f - pphase_b45;
+
+        temp_interp45Deg[0] = lerp(p[1][1], p[2][0], pphase_b45);
+        temp_interp45Deg[2] = lerp(p[2][2], p[3][1], pphase_b45);
+        temp_interp45Deg[4] = lerp(p[3][3], p[4][2], pphase_b45);
+        temp_interp45Deg[6] = lerp(p[4][4], p[5][3], pphase_b45);
+    }
+
+    float interp45Deg[6];
+    float pphase_p45 = phase_x_frac + phase_y_frac;
+    if (pphase_p45 >= 1)
+    {
+        NIS_UNROLL
+        for (int i = 0; i < 6; i++)
+        {
+            interp45Deg[i] = temp_interp45Deg[i + 1];
+        }
+        pphase_p45 = pphase_p45 - 1;
+    }
+    else
+    {
+        NIS_UNROLL
+        for (int i = 0; i < 6; i++)
+        {
+            interp45Deg[i] = temp_interp45Deg[i];
+        }
+    }
+
+    f.z = EvalPoly6(interp45Deg, (int)(pphase_p45 * 64));
+
+    //135 deg filter
+    float pphase_b135;
+    pphase_b135 = 0.5f * (phase_x_frac + phase_y_frac);
+
+    float temp_interp135Deg[7];
+
+    temp_interp135Deg[1] = lerp(p[3][1], p[4][2], pphase_b135);
+    temp_interp135Deg[3] = lerp(p[2][2], p[3][3], pphase_b135);
+    temp_interp135Deg[5] = lerp(p[1][3], p[2][4], pphase_b135);
+
+    if (pphase_b135 >= 0.5f)
+    {
+        pphase_b135 = pphase_b135 - 0.5f;
+
+        temp_interp135Deg[0] = lerp(p[4][1], p[5][2], pphase_b135);
+        temp_interp135Deg[2] = lerp(p[3][2], p[4][3], pphase_b135);
+        temp_interp135Deg[4] = lerp(p[2][3], p[3][4], pphase_b135);
+        temp_interp135Deg[6] = lerp(p[1][4], p[2][5], pphase_b135);
+    }
+    else
+    {
+        pphase_b135 = 0.5f - pphase_b135;
+
+        temp_interp135Deg[0] = lerp(p[4][1], p[3][0], pphase_b135);
+        temp_interp135Deg[2] = lerp(p[3][2], p[2][1], pphase_b135);
+        temp_interp135Deg[4] = lerp(p[2][3], p[1][2], pphase_b135);
+        temp_interp135Deg[6] = lerp(p[1][4], p[0][3], pphase_b135);
+    }
+
+    float interp135Deg[6];
+    float pphase_p135 = 1 + (phase_x_frac - phase_y_frac);
+    if (pphase_p135 >= 1)
+    {
+        NIS_UNROLL
+        for (int i = 0; i < 6; ++i)
+        {
+            interp135Deg[i] = temp_interp135Deg[i + 1];
+        }
+        pphase_p135 = pphase_p135 - 1;
+    }
+    else
+    {
+        NIS_UNROLL
+        for (int i = 0; i < 6; ++i)
+        {
+            interp135Deg[i] = temp_interp135Deg[i];
+        }
+    }
+
+    f.w = EvalPoly6(interp135Deg, (int)(pphase_p135 * 64));
+    return f;
+}
+
+
+//-----------------------------------------------------------------------------------------------
+// NVScaler
+//-----------------------------------------------------------------------------------------------
+void NVScaler(uint2 blockIdx, uint threadIdx)
+{
+    // Figure out the range of pixels from input image that would be needed to be loaded for this thread-block
+    const int dstBlockX = NIS_BLOCK_WIDTH * blockIdx.x;
+    const int dstBlockY = NIS_BLOCK_HEIGHT * blockIdx.y;
+
+    const int srcBlockStartX = floor((dstBlockX + 0.5f) * kScaleX - 0.5f);
+    const int srcBlockStartY = floor((dstBlockY + 0.5f) * kScaleY - 0.5f);
+    const int srcBlockEndX = ceil((dstBlockX + NIS_BLOCK_WIDTH + 0.5f) * kScaleX - 0.5f);
+    const int srcBlockEndY = ceil((dstBlockY + NIS_BLOCK_HEIGHT + 0.5f) * kScaleY - 0.5f);
+            
+    int numPixelsX = srcBlockEndX - srcBlockStartX + kSupportSize - 1;
+    int numPixelsY = srcBlockEndY - srcBlockStartY + kSupportSize - 1;
+
+    // round-up load region to even size since we're loading in 2x2 batches
+    numPixelsX += numPixelsX & 0x1;
+    numPixelsY += numPixelsY & 0x1;
+
+    const float invNumPixelX = 1.0f / numPixelsX;
+    const uint numPixels = numPixelsX * numPixelsY;
+
+    // fill in input luma tile in batches of 2x2 pixels
+    // we use texture gather to get extra support necessary
+    // to compute 2x2 edge map outputs too
+    for (uint i = threadIdx * 2; i < numPixels / 2; i += blockDim * 2)
+    {
+        float py = floor(i * invNumPixelX);
+        const float px = i - py * numPixelsX;
+        py *= 2.0f;
+
+        // 0.5 to be in the center of texel
+        // -1.0 to sample top-left corner of 3x3 halo necessary
+        // -kSupportSize/2 to shift by the kernel support size
+        float kShift = 0.5f - 1.0f - (kSupportSize - 1) / 2;
+#if NIS_VIEWPORT_SUPPORT
+        const float tx = (srcBlockStartX + px + kInputViewportOriginX + kShift) * kSrcNormX;
+        const float ty = (srcBlockStartY + py + kInputViewportOriginY + kShift) * kSrcNormY;
+#else
+        const float tx = (srcBlockStartX + px + kShift) * kSrcNormX;
+        const float ty = (srcBlockStartY + py + kShift) * kSrcNormY;
+#endif
+        float p[4][4];
+#if NIS_TEXTURE_GATHER
+        NIS_UNROLL for (int j = 0; j < 4; j += 2)
+        {
+            NIS_UNROLL for (int k = 0; k < 4; k += 2)
+            {
+                const float4 sr = in_texture.GatherRed(samplerLinearClamp, float2(tx + k * kSrcNormX, ty + j * kSrcNormY), int2(0, 0));
+                const float4 sg = in_texture.GatherGreen(samplerLinearClamp, float2(tx + k * kSrcNormX, ty + j * kSrcNormY), int2(0, 0));
+                const float4 sb = in_texture.GatherBlue(samplerLinearClamp, float2(tx + k * kSrcNormX, ty + j * kSrcNormY), int2(0, 0));
+
+                p[j + 0][k + 0] = getY(float3(sr.w, sg.w, sb.w));
+                p[j + 0][k + 1] = getY(float3(sr.z, sg.z, sb.z));
+                p[j + 1][k + 0] = getY(float3(sr.x, sg.x, sb.x));
+                p[j + 1][k + 1] = getY(float3(sr.y, sg.y, sb.y));
+            }
+        }
+#else
+        NIS_UNROLL
+        for (int j = 0; j < 4; j++)
+        {
+            NIS_UNROLL
+            for (int k = 0; k < 4; k++)
+            {
+                const float3 px = in_texture.SampleLevel(samplerLinearClamp, float2(tx + k * kSrcNormX, ty + j * kSrcNormY), 0).xyz;
+                p[j][k] = getY(px);
+            }
+        }
+#endif
+        const int idx = py * numPixelsX + px;
+        shEdgeMap[idx] = (NVF4)GetEdgeMap(p, 0, 0);
+        shEdgeMap[idx + 1] = (NVF4)GetEdgeMap(p, 0, 1);
+        shEdgeMap[idx + numPixelsX] = (NVF4)GetEdgeMap(p, 1, 0);
+        shEdgeMap[idx + numPixelsX + 1] = (NVF4)GetEdgeMap(p, 1, 1);
+
+        // normalize luma to 255.0f and write out to shmem
+        shPixelsY[idx] = (NVF)(p[1][1] * NIS_SCALE_FLOAT);
+        shPixelsY[idx + 1] = (NVF)(p[1][2] * NIS_SCALE_FLOAT);
+        shPixelsY[idx + numPixelsX] = (NVF)(p[2][1] * NIS_SCALE_FLOAT);
+        shPixelsY[idx + numPixelsX + 1] = (NVF)(p[2][2] * NIS_SCALE_FLOAT);
+    }
+
+    LoadFilterBanksSh(threadIdx, blockDim);
+
+    GroupMemoryBarrierWithGroupSync();
+
+    for (uint k = threadIdx; k < NIS_BLOCK_WIDTH * NIS_BLOCK_HEIGHT; k += blockDim)
+    {
+        const int2 pos = int2(k % NIS_BLOCK_WIDTH, k / NIS_BLOCK_WIDTH);
+
+        const int dstX = dstBlockX + pos.x;
+        const int dstY = dstBlockY + pos.y;
+
+        const float srcX = (0.5f + dstX) * kScaleX - 0.5f;
+        const float srcY = (0.5f + dstY) * kScaleY - 0.5f;
+#if NIS_VIEWPORT_SUPPORT
+        if (srcX > kInputViewportWidth || srcY > kInputViewportHeight || 
+            dstX > kOutputViewportWidth || dstY > kOutputViewportHeight)
+        {
+            return;
+        }
+#endif
+
+        const int px = floor(srcX) - srcBlockStartX;
+        const int py = floor(srcY) - srcBlockStartY;
+
+        const int start_idx = py * numPixelsX + px;
+
+        // load 6x6 support to regs
+        float p[6][6];
+        {
+            NIS_UNROLL
+            for (int i = 0; i < 6; ++i)
+            {
+                NIS_UNROLL
+                for (int j = 0; j < 6; ++j)
+                {
+                    p[i][j] = shPixelsY[start_idx + i * numPixelsX + j];
+                }
+            }
+        }
+
+        // compute discretized filter phase
+        const float fx = srcX - floor(srcX);
+        const float fy = srcY - floor(srcY);
+        const int fx_int = (int)(fx * kPhaseCount);
+        const int fy_int = (int)(fy * kPhaseCount);
+
+        // get traditional scaler filter output
+        const float pixel_n = FilterNormal(p, fx_int, fy_int);
+
+        // get directional filter bank output
+        float4 opDirYU = GetDirFilters(p, fx, fy, fx_int, fy_int);
+
+        // final luma is a weighted product of directional & normal filters
+
+        // generate weights for directional filters
+        const int kShift = (kSupportSize - 2) / 2;
+        float4 edge[2][2];
+        NIS_UNROLL
+        for (int i = 0; i < 2; i++)
+        {
+            NIS_UNROLL
+            for (int j = 0; j < 2; j++)
+            {
+                // need to shift edge map sampling since it's a 2x2 centered inside 6x6 grid                
+                edge[i][j] = shEdgeMap[start_idx + (i + kShift) * numPixelsX + (j + kShift)];
+            }
+        }
+        const float4 w = GetInterpEdgeMap(edge, fx, fy) * NIS_SCALE_INT;
+
+        // final pixel is a weighted sum filter outputs
+        const float opY = (opDirYU.x * w.x + opDirYU.y * w.y + opDirYU.z * w.z + opDirYU.w * w.w +
+            pixel_n * (NIS_SCALE_FLOAT - w.x - w.y - w.z - w.w)) * (1.0f / NIS_SCALE_FLOAT);
+        // do bilinear tap for chroma upscaling
+#if NIS_VIEWPORT_SUPPORT
+        float4 op = in_texture.SampleLevel(samplerLinearClamp, float2((srcX + kInputViewportOriginX) * kSrcNormX, (srcY + kInputViewportOriginY) * kSrcNormY), 0);
+#else
+        float4 op = in_texture.SampleLevel(samplerLinearClamp, float2((dstX + 0.5f) * kDstNormX, (dstY + 0.5f) * kDstNormY), 0);
+#endif 
+#if NIS_HDR_MODE == NIS_HDR_MODE_LINEAR
+        const float kEps = 1e-4f;
+        const float kNorm = 1.0f / (NIS_SCALE_FLOAT * kHDRCompressionFactor);
+        const float opYN = max(opY, 0.0f) * kNorm;
+        const float corr = (opYN * opYN + kEps) / (max(getYLinear(float3(op.x, op.y, op.z)), 0.0f) + kEps);
+        op.x *= corr;
+        op.y *= corr;
+        op.z *= corr;
+#else
+        const float corr = opY * (1.0f / NIS_SCALE_FLOAT) - getY(float3(op.x, op.y, op.z));
+        op.x += corr;
+        op.y += corr;
+        op.z += corr;
+#endif
+
+#if NIS_VIEWPORT_SUPPORT
+        out_texture[uint2(dstX + kOutputViewportOriginX, dstY + kOutputViewportOriginY)] = op;
+#else
+        out_texture[uint2(dstX, dstY)] = op;
+#endif
+    }
+}
+#else
+
+#ifndef NIS_BLOCK_WIDTH
+#define NIS_BLOCK_WIDTH 32
+#endif 
+#ifndef NIS_BLOCK_HEIGHT
+#define NIS_BLOCK_HEIGHT 32
+#endif
+#ifndef NIS_THREAD_GROUP_SIZE
+#define NIS_THREAD_GROUP_SIZE 256
+#endif
+
+#define kSupportSize 5
+#define kNumPixelsX  (NIS_BLOCK_WIDTH + kSupportSize + 1)
+#define kNumPixelsY  (NIS_BLOCK_HEIGHT + kSupportSize + 1)
+#define blockDim     NIS_THREAD_GROUP_SIZE
+
+groupshared float shPixelsY[kNumPixelsY][kNumPixelsX];
+
+float CalcLTIFast(const float y[5])
+{
+    const float a_min = min(min(y[0], y[1]), y[2]);
+    const float a_max = max(max(y[0], y[1]), y[2]);
+
+    const float b_min = min(min(y[2], y[3]), y[4]);
+    const float b_max = max(max(y[2], y[3]), y[4]);
+
+    const float a_cont = a_max - a_min;
+    const float b_cont = b_max - b_min;
+
+    const float cont_ratio = max(a_cont, b_cont) / (min(a_cont, b_cont) + kEps * (1.0f / 255.0f));
+    return (1.0f - saturate((cont_ratio - kMinContrastRatio) * kRatioNorm)) * kContrastBoost;
+}
+
+float EvalUSM(const float pxl[5], const float sharpnessStrength, const float sharpnessLimit)
+{
+    // USM profile
+    float y_usm = -0.6001f * pxl[1] + 1.2002f * pxl[2] - 0.6001f * pxl[3];
+    // boost USM profile
+    y_usm *= sharpnessStrength;
+    // clamp to the limit
+    y_usm = min(sharpnessLimit, max(-sharpnessLimit, y_usm));
+    // reduce ringing
+    y_usm *= CalcLTIFast(pxl);
+
+    return y_usm;
+}
+
+float4 GetDirUSM(const float p[5][5])
+{
+    // sharpness boost & limit are the same for all directions
+    const float scaleY = 1.0f - saturate((p[2][2] - kSharpStartY) * kSharpScaleY);
+    // scale the ramp to sharpen as a function of luma
+    const float sharpnessStrength = scaleY * kSharpStrengthScale + kSharpStrengthMin;
+    // scale the ramp to limit USM as a function of luma
+    const float sharpnessLimit = (scaleY * kSharpLimitScale + kSharpLimitMin) * p[2][2];
+
+    float4 rval;
+    // 0 deg filter
+    float interp0Deg[5];
+    {
+        for (int i = 0; i < 5; ++i)
+        {
+            interp0Deg[i] = p[i][2];
+        }
+    }
+
+    rval.x = EvalUSM(interp0Deg, sharpnessStrength, sharpnessLimit);
+
+    // 90 deg filter
+    float interp90Deg[5];
+    {
+        for (int i = 0; i < 5; ++i)
+        {
+            interp90Deg[i] = p[2][i];
+        }
+    }
+
+    rval.y = EvalUSM(interp90Deg, sharpnessStrength, sharpnessLimit);
+
+    //45 deg filter
+    float interp45Deg[5];
+    interp45Deg[0] = p[1][1];
+    interp45Deg[1] = lerp(p[2][1], p[1][2], 0.5f);
+    interp45Deg[2] = p[2][2];
+    interp45Deg[3] = lerp(p[3][2], p[2][3], 0.5f);
+    interp45Deg[4] = p[3][3];
+
+    rval.z = EvalUSM(interp45Deg, sharpnessStrength, sharpnessLimit);
+
+    //135 deg filter
+    float interp135Deg[5];
+    interp135Deg[0] = p[3][1];
+    interp135Deg[1] = lerp(p[3][2], p[2][1], 0.5f);
+    interp135Deg[2] = p[2][2];
+    interp135Deg[3] = lerp(p[2][3], p[1][2], 0.5f);
+    interp135Deg[4] = p[1][3];
+
+    rval.w = EvalUSM(interp135Deg, sharpnessStrength, sharpnessLimit);
+    return rval;
+}
+
+//-----------------------------------------------------------------------------------------------
+// NVSharpen
+//-----------------------------------------------------------------------------------------------
+void NVSharpen(uint2 blockIdx, uint threadIdx)
+{
+    const int dstBlockX = NIS_BLOCK_WIDTH * blockIdx.x;
+    const int dstBlockY = NIS_BLOCK_HEIGHT * blockIdx.y;
+
+    // fill in input luma tile in batches of 2x2 pixels
+    // we use texture gather to get extra support necessary
+    // to compute 2x2 edge map outputs too
+    const float kShift = 0.5f - kSupportSize / 2;
+   
+    for (uint i = threadIdx * 2; i < kNumPixelsX * kNumPixelsY / 2; i += blockDim * 2)
+    {
+        uint2 pos = uint2(i % kNumPixelsX, i / kNumPixelsX * 2);
+        NIS_UNROLL
+        for (int dy = 0; dy < 2; dy++)
+        {
+            NIS_UNROLL
+            for (int dx = 0; dx < 2; dx++)
+            {
+#if NIS_VIEWPORT_SUPPORT
+                const float tx = (dstBlockX + pos.x + kInputViewportOriginX + dx + kShift) * kSrcNormX;
+                const float ty = (dstBlockY + pos.y + kInputViewportOriginY + dy + kShift) * kSrcNormY;
+#else
+                const float tx = (dstBlockX + pos.x + dx + kShift) * kSrcNormX;
+                const float ty = (dstBlockY + pos.y + dy + kShift) * kSrcNormY;
+#endif
+                const float3 px = in_texture.SampleLevel(samplerLinearClamp, float2(tx, ty), 0).xyz;
+                shPixelsY[pos.y + dy][pos.x + dx] = getY(px);                
+            }
+        }
+    }
+
+    GroupMemoryBarrierWithGroupSync();
+
+    for (int k = threadIdx; k < NIS_BLOCK_WIDTH * NIS_BLOCK_HEIGHT; k += blockDim)
+    {
+        const int2 pos = int2(k % NIS_BLOCK_WIDTH, k / NIS_BLOCK_WIDTH);
+
+        // load 5x5 support to regs
+        float p[5][5];
+        NIS_UNROLL
+        for (int i = 0; i < 5; ++i)
+        {
+            NIS_UNROLL
+            for (int j = 0; j < 5; ++j)
+            {
+                p[i][j] = shPixelsY[pos.y + i][pos.x + j];
+            }
+        }
+
+        // get directional filter bank output
+        const float4 dirUSM = GetDirUSM(p);
+
+        // generate weights for directional filters
+        float4 w = GetEdgeMap(p, kSupportSize / 2 - 1, kSupportSize / 2 - 1);
+
+        // final USM is a weighted sum filter outputs
+        const float usmY = (dirUSM.x * w.x + dirUSM.y * w.y + dirUSM.z * w.z + dirUSM.w * w.w);
+
+        // do bilinear tap and correct rgb texel so it produces new sharpened luma
+        const int dstX = dstBlockX + pos.x;
+        const int dstY = dstBlockY + pos.y;
+
+#if NIS_VIEWPORT_SUPPORT
+        if (dstX > kOutputViewportWidth || dstY > kOutputViewportHeight)
+        {
+            return;
+        }
+#endif
+
+#if NIS_VIEWPORT_SUPPORT
+        float4 op = in_texture.SampleLevel(samplerLinearClamp, float2((dstX + kInputViewportOriginX) * kSrcNormX, (dstY + kInputViewportOriginY) * kSrcNormY), 0);
+#else
+        float4 op = in_texture.SampleLevel(samplerLinearClamp, float2((dstX + 0.5f) * kDstNormX, (dstY + 0.5f) * kDstNormY), 0);
+#endif 
+#if NIS_HDR_MODE == NIS_HDR_MODE_LINEAR
+        const float kEps = 1e-4f * kHDRCompressionFactor * kHDRCompressionFactor;
+        float newY = p[2][2] + usmY;
+        newY = max(newY, 0.0f);
+        const float oldY = p[2][2];
+        const float corr = (newY * newY + kEps) / (oldY * oldY + kEps);
+        op.x *= corr;
+        op.y *= corr;
+        op.z *= corr;
+#else
+        op.x += usmY;
+        op.y += usmY;
+        op.z += usmY;
+#endif
+#if NIS_VIEWPORT_SUPPORT
+        out_texture[uint2(dstX + kOutputViewportOriginX, dstY + kOutputViewportOriginY)] = op;
+#else
+        out_texture[uint2(dstX, dstY)] = op;
+#endif
+    }
+}
+#endif

+ 381 - 1
README.md

@@ -1 +1,381 @@
-# NVIDIA Image Scaling
+# NVIDIA Image Scaling SDK v1.0
+
+The MIT License(MIT)
+
+Copyright(c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files(the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of
+the Software, and to permit persons to whom the Software is 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 Software.
+
+THE SOFTWARE IS 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 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+
+## Introduction
+
+The NVIDIA Image Scaling SDK provides a single spatial scaling and sharpening algorithm
+for cross-platform support. The scaling algorithm uses a 6-tap scaling filter combined
+with 4 directional scaling and adaptive sharpening filters, which creates nice smooth images
+and sharp edges. In addition, the SDK provides a state-of-the-art adaptive directional sharpening algorithm for use in
+applications where no scaling is required.\
+The directional scaling and sharpening algorithm is named NVScaler while the adaptive-directional-sharpening-only
+algorithm is named NVSharpen. Both algorithms are provided as compute shaders and
+developers are free to integrate them in their applications. Note that if you integrate NVScaler, you
+should NOT integrate NVSharpen, as NVScaler already includes a sharpening pass
+
+
+
+## Pipeline Placement
+
+The call into the NVIDIA Image Scaling shaders must occur during the post-processing phase after tone-mapping.
+Applying the scaling in linear HDR in-game color-space may result in a sharpening effect that is
+either not visible or too strong. Since sharpening algorithms can enhance noisy or grainy regions, it is recommended
+that certain effects such as film grain should occur after NVScaler or NVSharpen. Low-pass filters such as motion blur or
+light bloom are recommended to be applied before NVScaler or NVSharpen to avoid sharpening attenuation.
+
+
+
+## Color Space and Ranges
+
+NVIDIA Image Scaling shaders can process color textures stored as either LDR or HDR with the following
+restrictions:
+
+1) LDR
+   - The range of color values must be in the [0, 1] range
+   - The input color texture must be in display-referred color-space after tone mapping and OETF (gamma-correction)
+     has been applied
+2) HDR PQ
+   - The range of color values must be in the [0, 1] range
+   - The input color texture must be in display-referred color-space after tone mapping with Rec.2020 PQ OETF applied
+3) HDR Linear
+   - The recommended range of color values is [0, 12.5], where luminance value (as per BT. 709) of
+     1.0 maps to brightness value of 80nits (sRGB peak) and 12.5 maps to 1000nits
+   - The input color texture may have luminance values that are either linear and scene-referred or
+     linear and display-referred (after tone mapping)
+
+If the input color texture sent to NVScaler/NVSharpen is in HDR format set NIS_HDR_MODE define to either NIS_HDR_MODE_LINEAR (1) or NIS_HDR_MODE_PQ (2).
+
+
+
+## Supported Texture Formats
+
+### Input and output formats:
+
+Input and output formats are expected to be in the rages defined in previous section and should be
+specified using non-integer data types such as DXGI_FORMAT_R8G8B8A8_UNORM.
+
+### Coefficients formats:
+
+The scaler coefficients and USM coefficients format should be specified using float4 type such as
+DXGI_FORMAT_R32G32B32A32_FLOAT or DXGI_FORMAT_R16G16B16A16_FLOAT.
+
+### Resource States, Buffers, and Sampler:
+
+The game or application calling NVIDIA Image Scaling SDK shaders must ensure that the textures are in
+the correct state.
+
+- Input color textures must be in pixel shader read state. Shader Resource View (SRV) in DirectX
+- The output texture must be in read/write state. Unordered Access View (UAV) in DirectX
+- The coefficients texture for NVScaler must be in read state. Shader Resource View (SRV) in DirectX
+- The configuration variables must be passed as constant buffer. Constant Buffer View (CBV) in DirectX
+- The sampler for texture pixel sampling. Linear clamp SamplerState in Direct
+
+
+
+## Adding NVIDIA Image Scaling SDK to a Project
+
+Include NIS_Scaler.h directly in your application or alternative use the provided NIS_Main.hlsl shader file.
+Use NIS_Config.h to get the ideal shader dispatch values for your platform, to configure the algorithm constant
+values (NVScalerUpdateConfig, and NVSharpenUpdateConfig), and to access the algorithm coefficients (coef_scale and coef_USM).
+
+- Device\
+  NIS_Scaler.h    : HLSL shader file\
+  NIS_Main.hlsl   : Main HLSL shader example (can be replaced by your own)
+
+- Host Configuration\
+  NIS_Config.h    : Configuration structure
+
+
+### Defines:
+
+**NIS_SCALER**: default (**1**) NVScaler, (0) fast NVSharpen only, no upscaling\
+**NIS_HDR_MODE**: default(**0**) disabled, (1) Linear, (2) PQ\
+**NIS_BLOCK_WIDTH**: pixels per block width. Use GetOptimalBlockWidth query for your platform\
+**NIS_BLOCK_HEIGHT**: pixels per block height. Use GetOptimalBlockHeight query for your platform\
+**NIS_THREAD_GROUP_SIZE**: number of threads per group. Use GetOptimalThreadGroupSize query for your platform\
+**NIS_USE_HALF_PRECISION**: default(**0**) disabled, (1) enable half pression computation\
+**NIS_HLSL_6_2**: default (**0**) HLSL v5, (1) HLSL v6.2\
+**NIS_VIEWPORT_SUPPORT**: default(**0**) disabled, (1) enable input/output viewport support\
+
+
+*Default NVScaler shader constants:*
+
+[**NIS_BLOCK_WIDTH**, **NIS_BLOCK_HEIGHT**, **NIS_THREAD_GROUP_SIZE**] = [32, 24, 256]
+
+*Default NVSharpen shader constants:*
+
+[**NIS_BLOCK_WIDTH**, **NIS_BLOCK_HEIGHT**, **NIS_THREAD_GROUP_SIZE**] = [32, 32, 256]
+
+
+## Optimal shader settings
+
+To get optimal performance of NvScaler and NvSharpen for current and future hardware, it is recommended that the following API is used to obtain the values for NIS_BLOCK_WIDTH, NIS_BLOCK_HEIGHT, and NIS_THREAD_GROUP_SIZE.
+
+```
+enum class NISGPUArchitecture : uint32_t
+{
+    NVIDIA_Generic = 0,
+    AMD_Generic = 1,
+    Intel_Generic = 2
+};
+```
+
+```
+struct NISOptimizer
+{
+    bool isUpscaling;
+    NISGPUArchitecture gpuArch;
+
+    NISOptimizer(bool isUpscaling = true,
+                 NISGPUArchitecture gpuArch = NISGPUArchitecture::NVIDIA_Generic);
+    uint32_t GetOptimalBlockWidth();
+    uint32_t GetOptimalBlockHeight();
+    uint32_t GetOptimalThreadGroupSize();
+};
+```
+
+
+
+## HDR shader settings
+
+Use the following enum values for setting NIS_HDR_MODE
+
+```
+enum class NISHDRMode : uint32_t
+{
+    None = 0,
+    Linear = 1,
+    PQ = 2
+};
+```
+
+
+
+## Integration of NVScaler
+
+### Compile the NIS_Main.hlsl shader
+
+NIS_SCALER should be set to 1, and isUscaling should be pass as true.
+
+```
+NISOptimizer opt(true, NISGPUArchitecture::NVIDIA_Generic);
+uint32_t blockWidth = opt.GetOptimalBlockWidth();
+uint32_t blockHeight = opt.GetOptimalBlockHeight();
+uint32_t threadGroupSize = opt.GetOptimalThreadGroupSize();
+
+Defines defines;
+defines.add("NIS_SCALER", true);
+defines.add("NIS_HDR_MODE", hdrMode);
+defines.add("NIS_BLOCK_WIDTH", blockWidth);
+defines.add("NIS_BLOCK_HEIGHT", blockHeight);
+defines.add("NIS_THREAD_GROUP_SIZE", threadGroupSize);
+NVScalerCS = CompileComputeShader(device, "NIS_Main.hlsl”, &defines);
+```
+
+### Create NVIDIA Image Scaling SDK configuration constant buffer
+
+```
+struct NISConfig
+{
+    float kDetectRatio;
+    float kDetectThres;
+    float kMinContrastRatio;
+    float kRatioNorm;
+    ...
+};
+
+NISConfig config;
+createConstBuffer(&config, &csBuffer);
+```
+
+### Create SRV textures for the scaler and USM phase coefficients
+
+```
+const int rowPitch = kFilterSize * 4;
+const int imageSize = rowPitch * kPhaseCount;
+
+createTexture2D(kFilterSize / 4, kPhaseCount, DXGI_FORMAT_R32G32B32A32_FLOAT, D3D11_USAGE_DEFAULT, coef_scaler, rowPitch, imageSize, &scalerTex);
+
+createTexture2D(kFilterSize / 4, kPhaseCount, DXGI_FORMAT_R32G32B32A32_FLOAT, D3D11_USAGE_DEFAULT, coef_usm, rowPitch, imageSize, &usmTex);
+
+createSRV(scalerTex.Get(), DXGI_FORMAT_R32G32B32A32_FLOAT, &scalerSRV);
+createSRV(usmTex.Get(), DXGI_FORMAT_R32G32B32A32_FLOAT, &usmSRV);
+```
+
+### Create Sampler
+
+```
+createLinearClampSampler(&linearClampSampler);
+```
+
+### Update NVIDIA Image Scaling SDK NVScaler configuration and constant buffer
+
+Use the following API call to update the NVIDIA Image Scaling SDK configuration
+
+```
+void NVScalerUpdateConfig(NISConfig& config,
+    float sharpness,
+    uint32_t inputViewportOriginX, uint32_t inputViewportOriginY,
+    uint32_t inputViewportWidth, uint32_t inputViewportHeight,
+    uint32_t inputTextureWidth, uint32_t inputTextureHeight,
+    uint32_t outputViewportOriginX, uint32_t outputViewportOriginY,
+    uint32_t outputViewportWidth, uint32_t outputViewportHeight,
+    uint32_t outputTextureWidth, uint32_t outputTextureHeight,
+    NISHDRMode hdrMode = NISHDRMode::None
+);
+```
+
+Update the constant buffer whenever the input size, sharpness, or scale changes
+
+```
+NVScalerUpdateConfig(m_config, sharpness,
+                0, 0, inputWidth, inputHeight, inputWidth, inputHeight,
+                0, 0, outputWidth, outputHeight, outputWidth, outputHeight,
+                NISHDRMode::None);
+
+updateConstBuffer(&config, csBuffer.Get());
+```
+
+### A simple DX11 NVScaler dispatch example
+
+```
+context->CSSetShaderResources(0, 1, input); // SRV
+context->CSSetShaderResource (1, 1, scalerSRV.GetAddressOf());
+context->CSSetShaderResource (2, 1, usmSRV.GetAddressOf());
+context->CSSetUnorderedAccessViews(0, 1, output, nullptr);
+context->CSSetSamplers(0, 1, linearClampSampler.GetAddressOf());
+context->CSSetConstantBuffers(0, 1, csBuffer.GetAddressOf());
+context->CSSetShader(NVScalerCS.Get(), nullptr, 0);
+
+context->Dispatch(UINT(std::ceil(outputWidth / float(blockWidth))),
+                  UINT(std::ceil(outputHeight / float(blockHeight))), 1);
+```
+
+
+
+## Integration of NVSharpen
+
+If your application requires upscaling and sharpening do not use NVSharpen use NVScaler instead. Since NVScaler performs both operations, upscaling and sharpening, in one step, it performs faster and produces better image quality.
+
+### Compile the NIS_Main.hlsl shader
+
+NIS_SCALER should be set to 0 and the optimizer isUscaling argument should be set as false.
+
+```
+bool isUpscaling = false;
+NISOptimizer opt(isUpscaling, NISGPUArchitecture::NVIDIA_Generic);
+uint32_t blockWidth = opt.GetOptimalBlockWidth();
+uint32_t blockHeight = opt.GetOptimalBlockHeight();
+uint32_t threadGroupSize = opt.GetOptimalThreadGroupSize();
+
+Defines defines;
+defines.add("NIS_DIRSCALER", isUpscaling);
+defines.add("NIS_HDR_MODE", hdrMode);
+defines.add("NIS_BLOCK_WIDTH", blockWidth);
+defines.add("NIS_BLOCK_HEIGHT", blockHeight);
+defines.add("NIS_THREAD_GROUP_SIZE", threadGroupSize);
+NVSharpenCS = CompileComputeShader(device, "NIS_Main.hlsl”, &defines);
+```
+
+### Create NVIDIA Image Scaling SDK NVSharpen configuration constant buffer
+
+```
+struct NISConfig
+{
+    float kDetectRatio;
+    float kDetectThres;
+    float kMinContrastRatio;
+    float kRatioNorm;
+    ...
+};
+
+NISConfig config;
+createConstBuffer(&config, &csBuffer);
+```
+
+### Create Sampler
+
+```
+createLinearClampSampler(&linearClampSampler);
+```
+
+### Update NVIDIA Image Scaling SDK NVSharpen configuration and constant buffer
+
+Use the following API call to update the NVIDIA Image Scaling SDK configuration. Since NVSharpen is a sharpening algorithm only the sharpness and input size are required. For upscaling with sharpening use NVScaler since it performs both operations at the same time.
+
+```
+void NVSharpenUpdateConfig(NISConfig& config, float sharpness,
+    uint32_t inputViewportOriginX, uint32_t inputViewportOriginY,
+    uint32_t inputViewportWidth, uint32_t inputViewportHeight,
+    uint32_t inputTextureWidth, uint32_t inputTextureHeight,
+    uint32_t outputViewportOriginX, uint32_t outputViewportOriginY,
+    NISHDRMode hdrMode = NISHDRMode::None
+);
+
+```
+
+Update the constant buffer whenever the input size or sharpness changes.
+
+```
+NVSharpenUpdateConfig(m_config, sharpness,
+                      0, 0, inputWidth, inputHeight, inputWidth, inputHeight,
+                      0, 0, NISHDRMode::None);
+
+updateConstBuffer(&config, csBuffer.Get());
+```
+
+### A simple DX11 NVSharpen dispatch example
+
+```
+context->CSSetShaderResources(0, 1, input);
+context->CSSetUnorderedAccessViews(0, 1, output, nullptr);
+context->CSSetSamplers(0, 1, linearClampSampler.GetAddressOf());
+context->CSSetConstantBuffers(0, 1, csBuffer.GetAddressOf());
+context->CSSetShader(NVSharpenCS.Get(), nullptr, 0);
+
+context->Dispatch(UINT(std::ceil(outputWidth / float(blockWidth))),
+                  UINT(std::ceil(outputHeight / float(blockHeight))), 1);
+```
+
+
+
+## Samples
+
+### Dependencies
+
+- Visual Studio 2019 : https://visualstudio.microsoft.com/downloads/
+- Windows 10 SDK : https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk
+- CMake 3.16 : https://cmake.org/download/
+
+### Build
+
+```
+$> cd samples
+$> mkdir build
+$> cd build
+$> cmake ..
+```
+
+Open the solution with Visual Studio 2019. Right-click the sample project and select "Set as Startup Project" before building the project

BIN
docs/NIS_SDK_Programming_Guide.pdf


BIN
docs/RTX UI Developer Guidelines Chinese Version.pdf


BIN
docs/RTX UI Developer Guidelines.pdf


+ 20 - 0
licence.txt

@@ -0,0 +1,20 @@
+// The MIT License(MIT)
+// 
+// Copyright(c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+// 
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files(the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of
+// the Software, and to permit persons to whom the Software is 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 Software.
+// 
+// THE SOFTWARE IS 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 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ 8 - 0
samples/CMakeLists.txt

@@ -0,0 +1,8 @@
+cmake_minimum_required(VERSION 3.12)
+project(NIS_SDK)
+
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+set(CMAKE_CXX_EXTENSIONS ON)
+
+add_subdirectory (DX11)

+ 72 - 0
samples/DX11/CMakeLists.txt

@@ -0,0 +1,72 @@
+project(dx11_sample)
+set_property(GLOBAL PROPERTY USE_FOLDERS ON)
+
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /UMBCS /D_UNICODE /DUNICODE")
+set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_HOME_DIRECTORY}/bin/DX11/)
+
+set(IMGUI_PATH    "${CMAKE_SOURCE_DIR}/third_party/imgui/")
+set(IMGUI_INCLUDE "${IMGUI_PATH}" "${IMGUI_PATH}/backends/")
+set(IMGUI_SRC     "${IMGUI_PATH}/backends/imgui_impl_dx11.cpp"
+                  "${IMGUI_PATH}/backends/imgui_impl_win32.cpp"
+                  "${IMGUI_PATH}/imgui.cpp"
+                  "${IMGUI_PATH}/imgui_demo.cpp"
+                  "${IMGUI_PATH}/imgui_draw.cpp"
+                  "${IMGUI_PATH}/imgui_tables.cpp"
+                  "${IMGUI_PATH}/imgui_widgets.cpp"
+)
+
+set(NIS_PATH "${CMAKE_SOURCE_DIR}/../NIS")
+
+set(SAMPLES_PATH "${CMAKE_SOURCE_DIR}")
+
+set(DX_SAMPLE_SRC "src/Sample.cpp"
+                  "src/AppRenderer.cpp"
+                  "src/UIRenderer.cpp"
+                  "src/DeviceResources.cpp"
+                  "src/NVScaler.cpp"
+                  "src/NVSharpen.cpp"
+                  "src/BilinearUpscale.cpp"
+                  "${SAMPLES_PATH}/common/Image.cpp"
+                  "src/dpi.manifest"
+)
+
+set(DX_SAMPLE_HEADERS "include/AppRenderer.h"
+                      "include/DeviceResources.h"
+                      "include/NVScaler.h"
+                      "include/NVSharpen.h"
+                      "include/UIRenderer.h"
+                      "include/BilinearUpscale.h"
+                      "include/DXUtilities.h"
+                      "${NIS_PATH}/NIS_Config.h"
+                      "${SAMPLES_PATH}/common/Image.h"
+                      "${SAMPLES_PATH}/common/Utilities.h"
+)
+
+set(DX_SAMPLE_SHADERS "${NIS_PATH}/NIS_Scaler.h"
+                      "${NIS_PATH}/NIS_Main.hlsl"
+)
+
+set(DX_SAMPLE_MEDIA "${SAMPLES_PATH}/media/images/1080.png"
+                    "${SAMPLES_PATH}/media/images/1440.png"
+                    "${SAMPLES_PATH}/media/images/1660.png"
+)
+
+set_source_files_properties(${DX_SAMPLE_SHADERS} PROPERTIES VS_COPY_TO_OUT_DIR TRUE)
+
+source_group("ui" FILES ${IMGUI_SRC})
+source_group("shaders" FILES ${DX_SAMPLE_SHADERS})
+add_executable(${PROJECT_NAME} ${DX_SAMPLE_SRC} ${IMGUI_SRC} ${DX_SAMPLE_HEADERS} ${DX_SAMPLE_SHADERS})
+target_include_directories (${PROJECT_NAME} PUBLIC include ${IMGUI_INCLUDE} ${NIS_PATH} ${SAMPLES_PATH}/common)
+
+add_custom_command(
+  TARGET ${PROJECT_NAME} POST_BUILD
+  COMMAND ${CMAKE_COMMAND} -E make_directory $<TARGET_FILE_DIR:${PROJECT_NAME}>/NIS
+  COMMAND ${CMAKE_COMMAND} -E copy_directory ${NIS_PATH} $<TARGET_FILE_DIR:${PROJECT_NAME}>/NIS
+)
+
+add_custom_command(
+  TARGET ${PROJECT_NAME} POST_BUILD
+  COMMAND ${CMAKE_COMMAND} -E make_directory $<TARGET_FILE_DIR:${PROJECT_NAME}>/media/images
+  COMMAND ${CMAKE_COMMAND} -E copy_directory ${SAMPLES_PATH}/media/images $<TARGET_FILE_DIR:${PROJECT_NAME}>/media/images
+)
+

+ 70 - 0
samples/DX11/include/AppRenderer.h

@@ -0,0 +1,70 @@
+// The MIT License(MIT)
+// 
+// Copyright(c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+// 
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files(the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of
+// the Software, and to permit persons to whom the Software is 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 Software.
+// 
+// THE SOFTWARE IS 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 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+#pragma once
+
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+#include <d3d11.h>
+#include <wrl.h>
+
+#include "DeviceResources.h"
+#include "NVScaler.h"
+#include "NVSharpen.h"
+#include "UIRenderer.h"
+#include "BilinearUpscale.h"
+#include "Image.h"
+
+using namespace Microsoft::WRL;
+
+class AppRenderer
+{
+public:
+    AppRenderer(DeviceResources& deviceResources, UIData& ui, const std::string& shadersFolder);
+    bool update();
+    void render();
+    uint32_t width() { return m_outputWidth; }
+    uint32_t height() { return m_outputHeight; }
+private:
+    UIData& m_ui;
+    DeviceResources& m_deviceResources;
+    NVSharpen							m_NVSharpen;
+    NVScaler							m_NVScaler;
+    BilinearUpscale						m_upscale;
+    uint32_t							m_inputWidth = 0;
+    uint32_t							m_inputHeight = 0;
+    uint32_t							m_outputWidth = 0;
+    uint32_t							m_outputHeight = 0;
+    ComPtr<ID3D11Texture2D>				m_input;
+    ComPtr<ID3D11Texture2D>				m_output;
+    ComPtr<ID3D11ShaderResourceView>	m_inputSRV;
+    ComPtr<ID3D11UnorderedAccessView>	m_outputUAV;
+
+    Image								m_image;
+    std::filesystem::path				m_currentFilePath;
+    float							    m_currentScale = 100.f;
+    float    							m_currentSharpness = 0.f;
+
+    ComPtr<ID3D11Query>                 m_timeStampDis;
+    ComPtr<ID3D11Query>                 m_timeStampStart;
+    ComPtr<ID3D11Query>                 m_timeStampEnd;
+};

+ 75 - 0
samples/DX11/include/BilinearUpscale.h

@@ -0,0 +1,75 @@
+// The MIT License(MIT)
+// 
+// Copyright(c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+// 
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files(the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of
+// the Software, and to permit persons to whom the Software is 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 Software.
+// 
+// THE SOFTWARE IS 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 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+#pragma once
+
+#include <dxgi1_4.h>
+#include <d3d11_3.h>
+
+#include "DeviceResources.h"
+
+__declspec(align(16))
+struct BilinearUpscaleConfig
+{
+    uint32_t kInputViewportOriginX;
+    uint32_t kInputViewportOriginY;
+    uint32_t kInputViewportWidth;
+    uint32_t kInputViewportHeight;
+    uint32_t kOutputViewportOriginX;
+    uint32_t kOutputViewportOriginY;
+    uint32_t kOutputViewportWidth;
+    uint32_t kOutputViewportHeight;
+    float    kScaleX;
+    float    kScaleY;
+    float    kDstNormX;
+    float    kDstNormY;
+    float    kSrcNormX;
+    float    kSrcNormY;
+};
+
+void BilinearUpdateConfig(BilinearUpscaleConfig& config,
+    uint32_t inputViewportOriginX, uint32_t inputViewportOriginY,
+    uint32_t inputViewportWidth, uint32_t inputViewportHeight,
+    uint32_t inputTextureWidth, uint32_t inputTextureHeight,
+    uint32_t outputViewportOriginX, uint32_t outputViewportOriginY,
+    uint32_t outputViewportWidth, uint32_t outputViewportHeight,
+    uint32_t outputTextureWidth, uint32_t outputTextureHeight);
+
+class BilinearUpscale {
+public:
+    const uint32_t kBlockWidth = 16;
+    const uint32_t kBlockHeight = 16;
+
+    BilinearUpscale(DeviceResources& deviceResources);
+
+    void update(uint32_t inputWidth, uint32_t inputHeight, uint32_t outputWidth, uint32_t outputHeight);
+
+    void dispatch(ID3D11ShaderResourceView*const* input, ID3D11UnorderedAccessView*const* output);
+private:
+    DeviceResources&            m_deviceResources;
+    BilinearUpscaleConfig               m_config;
+    ComPtr<ID3D11ComputeShader> m_computeShader;
+    ComPtr<ID3D11Buffer>        m_csBuffer;
+    ComPtr<ID3D11SamplerState>	m_LinearClampSampler;
+
+    uint32_t m_outputWidth;
+    uint32_t m_outputHeight;
+};

+ 165 - 0
samples/DX11/include/DXUtilities.h

@@ -0,0 +1,165 @@
+// The MIT License(MIT)
+// 
+// Copyright(c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+// 
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files(the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of
+// the Software, and to permit persons to whom the Software is 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 Software.
+// 
+// THE SOFTWARE IS 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 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+#pragma once
+
+#include <stdio.h>
+#include <tchar.h>
+#include <dxgi1_4.h>
+#include <d3d11.h>
+#include <d3dcompiler.h>
+#include <wrl.h>
+#include <algorithm>
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <vector>
+
+namespace DX
+{
+    using namespace Microsoft::WRL;
+
+    inline LPTSTR GetErrorDescription(HRESULT hr, WCHAR* buffer, size_t size)
+    {
+        if (FACILITY_WINDOWS == HRESULT_FACILITY(hr))
+            hr = HRESULT_CODE(hr);
+
+        FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
+            nullptr, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buffer, DWORD(size), nullptr);
+        return buffer;
+    }
+
+    inline void ThrowIfFailed(HRESULT hr)
+    {
+        if (FAILED(hr))
+        {
+            // Set a breakpoint on this line to catch Win32 API errors.
+            const size_t size = 1024;
+            WCHAR buffer[size];
+            GetErrorDescription(hr, buffer, size);
+            char str[size];
+            size_t i = 0;
+            wcstombs_s(&i, str, 1024, buffer, 1024);
+            throw std::runtime_error(str);
+        }
+    }
+
+    inline void CompileComputeShader(ID3D11Device* device,
+        LPCWSTR pFileName,
+        LPCSTR pEntryPoint,
+        ID3D11ComputeShader** csShader,
+        const D3D_SHADER_MACRO* pDefines = nullptr,
+        ID3DInclude* pInclude = nullptr,
+        LPCSTR pTarget = "cs_5_0")
+    {
+        ComPtr<ID3DBlob> csBlob;
+        ComPtr<ID3DBlob> cdErrorBlob = nullptr;
+        HRESULT hr = D3DCompileFromFile(pFileName, pDefines, pInclude, pEntryPoint, pTarget, 0, 0, &csBlob, &cdErrorBlob);
+        if (FAILED(hr)) {
+            if (cdErrorBlob) {
+                OutputDebugStringA((char*)cdErrorBlob->GetBufferPointer());
+            }
+            DX::ThrowIfFailed(hr);
+        }
+        DX::ThrowIfFailed(device->CreateComputeShader(csBlob->GetBufferPointer(), csBlob->GetBufferSize(), nullptr, csShader));
+    }
+
+    inline void CompileComputeShader(ID3D11Device* device,
+        LPCVOID pSrcData,
+        size_t SrcDataSize,
+        LPCSTR pEntrypoint,
+        ID3D11ComputeShader** csShader,
+        const D3D_SHADER_MACRO* pDefines = nullptr,
+        LPCSTR pTarget = "cs_5_0")
+    {
+        ComPtr<ID3DBlob> csBlob;
+        ComPtr<ID3DBlob> cdErrorBlob = nullptr;
+
+        HRESULT hr = D3DCompile(pSrcData, SrcDataSize, nullptr, pDefines, nullptr, pEntrypoint, pTarget, 0, 0, &csBlob, &cdErrorBlob);
+        if (FAILED(hr)) {
+            if (cdErrorBlob) {
+                OutputDebugStringA((char*)cdErrorBlob->GetBufferPointer());
+            }
+            DX::ThrowIfFailed(hr);
+        }
+        DX::ThrowIfFailed(device->CreateComputeShader(csBlob->GetBufferPointer(), csBlob->GetBufferSize(), nullptr, csShader));
+    }
+
+    struct IncludeHeader : ID3DInclude {
+        IncludeHeader(const std::vector<std::string>& includePath) 
+            : m_includePath(includePath)
+            , m_idx(0) {}
+
+        HRESULT Open(
+            D3D_INCLUDE_TYPE IncludeType,
+            LPCSTR           pFileName,
+            LPCVOID          pParentData,
+            LPCVOID* ppData,
+            UINT* pBytes
+        ) {
+            m_data.push_back("");
+            std::ifstream t;
+            size_t i = 0;
+            while (!t.is_open() && i < m_includePath.size()) {
+                t.open(m_includePath[i] + "/" + pFileName);
+                i++;
+            }
+            if (!t.is_open())
+                throw std::runtime_error("Error opening D3DCompileFromFile include header");
+            t.seekg(0, std::ios::end);
+            size_t size = t.tellg();
+            m_data[m_idx].resize(size);
+            t.seekg(0, std::ios::beg);
+            t.read(m_data[m_idx].data(), size);
+            m_data[m_idx].erase(std::remove(m_data[m_idx].begin(), m_data[m_idx].end(), '\0'), m_data[m_idx].end());
+            *ppData = m_data[m_idx].data();
+            *pBytes = UINT(m_data[m_idx].size());
+            m_idx++;
+            return S_OK;
+        }
+
+        HRESULT Close(LPCVOID pData) {
+            return S_OK;
+        }
+
+        std::vector<std::string> m_data;
+        std::vector<std::string> m_includePath;
+        size_t m_idx;
+    };
+
+    class Defines {
+    public:
+        template<typename T>
+        void add(const std::string& define, const T& val) {
+            m_definesVector.push_back({ define, toStr(val) });
+        }
+        D3D_SHADER_MACRO* get() {
+            m_defines = std::make_unique<D3D_SHADER_MACRO[]>(m_definesVector.size() + 1);
+            for (size_t i = 0; i < m_definesVector.size(); ++i)
+                m_defines[i] = { m_definesVector[i].first.c_str(), m_definesVector[i].second.c_str() };
+            m_defines[m_definesVector.size()] = { nullptr, nullptr };
+            return m_defines.get();
+        }
+    private:
+        std::vector<std::pair<std::string, std::string>> m_definesVector;        
+        std::unique_ptr<D3D_SHADER_MACRO[]> m_defines;
+    };
+}

+ 86 - 0
samples/DX11/include/DeviceResources.h

@@ -0,0 +1,86 @@
+// The MIT License(MIT)
+// 
+// Copyright(c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+// 
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files(the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of
+// the Software, and to permit persons to whom the Software is 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 Software.
+// 
+// THE SOFTWARE IS 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 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ 
+#pragma once
+ 
+#include <dxgi1_4.h>
+#include <d3d11.h>
+#include <wrl.h>
+#include <iostream>
+#include <vector>
+ 
+using namespace Microsoft::WRL;
+ 
+struct Adapter
+{
+    std::string Description;
+    uint32_t VendorId;
+    uint32_t DeviceId;
+    uint32_t SubSysId;
+    uint32_t Revision;
+    size_t DedicatedVideoMemory;
+    size_t DedicatedSystemMemory;
+    size_t SharedSystemMemory;
+};
+ 
+class DeviceResources
+{
+public:
+    void create(HWND hWnd, uint32_t adapterIdx = 0);
+    void initRenderTarget();
+    void resizeRenderTarget(uint32_t Width, uint32_t Height, DXGI_FORMAT format);
+    void clearRenderTargetView(const float color[4]);
+    void present(uint32_t SyncInterval, uint32_t Flags) { m_swapChain->Present(SyncInterval, Flags); }
+    ID3D11Device* device() { return m_d3dDevice.Get(); }
+    ID3D11DeviceContext* context() { return m_d3dContext.Get(); }
+    bool initialized() { return m_initialized; }
+ 
+    IDXGISwapChain* swapChain() { return m_swapChain.Get();  }
+    ID3D11Texture2D* renderTarget() { return m_d3dRenderTarget.Get(); }
+    void DeviceResources::setRenderTarget() {
+        m_d3dContext->OMSetRenderTargets(1, m_d3dRenderTargetView.GetAddressOf(), NULL);
+    }
+    ID3D11RenderTargetView* targetView() { return m_d3dRenderTargetView.Get(); }
+    ID3D11RenderTargetView* const* targetViewAddress() { return m_d3dRenderTargetView.GetAddressOf(); }
+    ID3D11UnorderedAccessView* const* targetUAVAddress() { return m_d3dRenderTargetUAV.GetAddressOf(); }
+    void createTexture2D(int w, int h, DXGI_FORMAT format, D3D11_USAGE heapType, const void* data, uint32_t rowPitch, uint32_t imageSize, ID3D11Texture2D** ppTexture2D);
+    void createUAV(ID3D11Resource* pResource, DXGI_FORMAT format, ID3D11UnorderedAccessView** ppUAView);
+    void createSRV(ID3D11Resource* pResource, DXGI_FORMAT format, ID3D11ShaderResourceView** ppSRView);
+    void createLinearClampSampler(ID3D11SamplerState** ppSampleState);
+    void createConstBuffer(void* initialData, uint32_t size, ID3D11Buffer** ppBuffer);
+    void updateConstBuffer(void* data, uint32_t size, ID3D11Buffer* ppBuffer);
+    void getTextureData(ID3D11Texture2D* texture, uint8_t* data);
+ 
+    uint32_t width() { return m_width; }
+    uint32_t height() { return m_height; }
+    Adapter getAdapter() { return m_adapter; }
+private:
+    ComPtr<ID3D11Device>               m_d3dDevice;
+    ComPtr<ID3D11DeviceContext>        m_d3dContext;
+    ComPtr<IDXGISwapChain>             m_swapChain;
+    ComPtr<ID3D11Texture2D>            m_d3dRenderTarget;
+    ComPtr<ID3D11RenderTargetView>	   m_d3dRenderTargetView;
+    ComPtr<ID3D11UnorderedAccessView>  m_d3dRenderTargetUAV;
+    uint32_t                           m_width;
+    uint32_t                           m_height;
+    bool                               m_initialized = false;
+    Adapter                            m_adapter;
+};

+ 55 - 0
samples/DX11/include/NVScaler.h

@@ -0,0 +1,55 @@
+// The MIT License(MIT)
+// 
+// Copyright(c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+// 
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files(the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of
+// the Software, and to permit persons to whom the Software is 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 Software.
+// 
+// THE SOFTWARE IS 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 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+#pragma once
+
+#include <dxgi1_4.h>
+#include <d3d11_3.h>
+#include <d3dcompiler.h>
+#include <iostream>
+
+#include "DXUtilities.h"
+#include "DeviceResources.h"
+#include "Utilities.h"
+#include "NIS_Config.h"
+
+class NVScaler {
+public:
+    NVScaler(DeviceResources& deviceResources, const std::string& shaderFolder);
+
+    void update(float sharpness, uint32_t inputWidth, uint32_t inputHeight, uint32_t outputWidth, uint32_t outputHeight);
+
+    void dispatch(ID3D11ShaderResourceView* const* input, ID3D11UnorderedAccessView* const* output);
+private:
+    DeviceResources& m_deviceResources;
+    NISConfig                           m_config;
+    ComPtr<ID3D11ComputeShader>         m_computeShader;
+    ComPtr<ID3D11Buffer>                m_csBuffer;
+    ComPtr<ID3D11Texture2D>				m_coef_scale;
+    ComPtr<ID3D11Texture2D>				m_coef_usm;
+    ComPtr<ID3D11ShaderResourceView>    m_coef_scaleSRV;
+    ComPtr<ID3D11ShaderResourceView>    m_coef_usmSRV;
+    ComPtr<ID3D11SamplerState>			m_LinearClampSampler;
+    uint32_t                            m_outputWidth;
+    uint32_t                            m_outputHeight;
+    uint32_t                            m_blockWidth;
+    uint32_t                            m_blockHeight;
+};

+ 50 - 0
samples/DX11/include/NVSharpen.h

@@ -0,0 +1,50 @@
+// The MIT License(MIT)
+// 
+// Copyright(c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+// 
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files(the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of
+// the Software, and to permit persons to whom the Software is 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 Software.
+// 
+// THE SOFTWARE IS 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 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+#pragma once
+
+#include <dxgi1_4.h>
+#include <d3d11_3.h>
+#include <d3dcompiler.h>
+#include <iostream>
+
+#include "DXUtilities.h"
+#include "DeviceResources.h"
+#include "Utilities.h"
+#include "NIS_Config.h"
+
+class NVSharpen {
+public:
+    NVSharpen(DeviceResources& deviceResources, const std::string& shaderFolder);
+
+    void update(float sharpness, uint32_t inputWidth, uint32_t inputHeight);
+    void dispatch(ID3D11ShaderResourceView* const* input, ID3D11UnorderedAccessView* const* output);
+private:
+    DeviceResources&                    m_deviceResources;
+    NISConfig                           m_config;
+    ComPtr<ID3D11ComputeShader>         m_computeShader;
+    ComPtr<ID3D11Buffer>                m_csBuffer;
+    ComPtr<ID3D11SamplerState>			m_LinearClampSampler;
+    uint32_t                            m_outputWidth;
+    uint32_t                            m_outputHeight;
+    uint32_t                            m_blockWidth;
+    uint32_t                            m_blockHeight;
+};

+ 76 - 0
samples/DX11/include/UIRenderer.h

@@ -0,0 +1,76 @@
+// The MIT License(MIT)
+// 
+// Copyright(c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+// 
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files(the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of
+// the Software, and to permit persons to whom the Software is 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 Software.
+// 
+// THE SOFTWARE IS 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 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ 
+#pragma once
+ 
+#include <iomanip>
+#include <iostream>
+#include <filesystem>
+#include <sstream>
+#include <string>
+#include <vector>
+#include <imgui.h>
+#include <imgui_impl_win32.h>
+#include <imgui_impl_dx11.h>
+#include "DeviceResources.h"
+#include "Utilities.h"
+ 
+enum class OutputSizeMode : uint32_t
+{
+	VARIABLE,
+	P1080,
+	P1440,
+	P2160
+};
+ 
+ 
+struct UIData
+{
+	std::vector<std::filesystem::path> Files;
+	std::filesystem::path FilePath;
+	std::string FileName;
+	float Scale = 75.f;
+	bool EnableNVScaler = true;
+	int FilterMode = 0;
+	float Sharpness = 50.f;
+	bool EnableVsync = false;
+	OutputSizeMode OutputMode;
+	uint32_t InputWidth;
+	uint32_t InputHeight;
+	uint32_t OutputWidth;
+	uint32_t OutputHeight;
+	double FilterTime;
+	bool ShowSettings = true;
+	int32_t UnitMicroseconds = true;
+};
+ 
+class UIRenderer
+{
+public:
+	UIRenderer(HWND hwnd, DeviceResources& deviceResources, UIData& ui);
+	void cleanUp();
+	void update(double fps);
+	void render();
+private:
+	UIData& m_ui;
+	DeviceResources& m_deviceResources;
+	ElapsedTimer m_elapsedTimer;
+};

+ 137 - 0
samples/DX11/src/AppRenderer.cpp

@@ -0,0 +1,137 @@
+// The MIT License(MIT)
+//
+// Copyright(c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files(the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of
+// the Software, and to permit persons to whom the Software is 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 Software.
+//
+// THE SOFTWARE IS 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 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ 
+#pragma once
+ 
+#include "AppRenderer.h"
+ 
+using namespace Microsoft::WRL;
+ 
+AppRenderer::AppRenderer(DeviceResources& deviceResources, UIData& ui, const std::string& shadersFolder)
+    : m_ui(ui)
+    , m_deviceResources(deviceResources)
+    , m_NVSharpen(deviceResources, shadersFolder)
+    , m_NVScaler(deviceResources, shadersFolder)
+    , m_upscale(deviceResources)
+{}
+ 
+bool AppRenderer::update()
+{
+    bool updateWindowSize = m_currentFilePath != m_ui.FilePath || m_currentScale != m_ui.Scale;
+    bool updateSharpeness = m_ui.Sharpness != m_currentSharpness;
+    if (updateWindowSize)
+    {
+        if (m_currentFilePath != m_ui.FilePath)
+        {
+            m_image.load(m_ui.FilePath);
+            m_inputWidth = m_image.width();
+            m_inputHeight = m_image.height();
+            m_deviceResources.createTexture2D(m_inputWidth, m_inputHeight, DXGI_FORMAT_R8G8B8A8_UNORM, D3D11_USAGE_DEFAULT, m_image.data(), m_image.rowPitch(), m_image.imageSize(), &m_input);
+            m_deviceResources.createSRV(m_input.Get(), DXGI_FORMAT_R8G8B8A8_UNORM, &m_inputSRV);
+            m_currentFilePath = m_ui.FilePath;
+        }
+        if (m_ui.Scale == 100)
+        {
+            m_outputWidth = m_inputWidth;
+            m_outputHeight = m_inputHeight;
+        }
+        else
+        {
+            m_outputWidth = uint32_t(std::ceil(m_inputWidth * 100.f / m_ui.Scale));
+            m_outputHeight = uint32_t(std::ceil(m_inputHeight * 100.f / m_ui.Scale));
+        }
+        m_deviceResources.createTexture2D(m_outputWidth, m_outputHeight, DXGI_FORMAT_R8G8B8A8_UNORM, D3D11_USAGE_DEFAULT, nullptr , 0, 0, &m_output);
+        m_deviceResources.createUAV(m_output.Get(), DXGI_FORMAT_R8G8B8A8_UNORM, &m_outputUAV);
+        m_currentScale = m_ui.Scale;
+        m_ui.InputWidth = m_inputWidth;
+        m_ui.InputHeight = m_inputHeight;
+        m_ui.OutputWidth = m_outputWidth;
+        m_ui.OutputHeight = m_outputHeight;
+    }
+    if (updateSharpeness)
+    {
+        m_currentSharpness = m_ui.Sharpness;
+    }
+    if (updateSharpeness || updateWindowSize)
+    {
+        m_upscale.update(m_inputWidth, m_inputHeight, m_outputWidth, m_outputHeight);
+        m_NVScaler.update(m_currentSharpness / 100.f, m_inputWidth, m_inputHeight, m_outputWidth, m_outputHeight);
+        m_NVSharpen.update(m_currentSharpness / 100.f, m_inputWidth, m_inputHeight);
+    }
+    return updateWindowSize;
+}
+ 
+void AppRenderer::render()
+{
+    auto context = m_deviceResources.context();
+    D3D11_QUERY_DESC desc;
+    ZeroMemory(&desc, sizeof(D3D11_QUERY_DESC));
+    desc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
+    m_deviceResources.device()->CreateQuery(&desc, &m_timeStampDis);
+    desc.Query = D3D11_QUERY_TIMESTAMP;
+    m_deviceResources.device()->CreateQuery(&desc, &m_timeStampStart);
+    m_deviceResources.device()->CreateQuery(&desc, &m_timeStampEnd);
+    context->Begin(m_timeStampDis.Get());
+    context->End(m_timeStampStart.Get());
+    if (!m_ui.EnableNVScaler)
+    {
+        if (m_ui.Scale == 100)
+        {
+            context->CopyResource(m_output.Get(), m_input.Get());
+        }
+        else
+        {
+            m_upscale.dispatch(m_inputSRV.GetAddressOf(), m_outputUAV.GetAddressOf());
+        }
+    }
+    else {
+        if (m_ui.Scale == 100)
+        {
+            m_NVSharpen.dispatch(m_inputSRV.GetAddressOf(), m_outputUAV.GetAddressOf());
+        }
+        else
+        {
+            m_NVScaler.dispatch(m_inputSRV.GetAddressOf(), m_outputUAV.GetAddressOf());
+        }
+    }
+ 
+    context->End(m_timeStampEnd.Get());
+    context->End(m_timeStampDis.Get());
+    D3D11_QUERY_DATA_TIMESTAMP_DISJOINT disData;
+    while (context->GetData(m_timeStampDis.Get(), &disData, sizeof(D3D11_QUERY_DATA_TIMESTAMP_DISJOINT), 0) != S_OK);
+    UINT64 startime;
+    UINT64 endtime;
+    while (context->GetData(m_timeStampStart.Get(), &startime, sizeof(UINT64), 0) != S_OK);
+    while (context->GetData(m_timeStampEnd.Get(), &endtime, sizeof(UINT64), 0) != S_OK);
+    if (!disData.Disjoint)
+    {
+        m_ui.FilterTime = (endtime - startime) / double(disData.Frequency) * 1E6;
+    }
+    D3D11_BOX sourceRegion;
+    sourceRegion.left = 0;
+    sourceRegion.right = m_deviceResources.width();
+    sourceRegion.top = 0;
+    sourceRegion.bottom = m_deviceResources.height();
+    sourceRegion.front = 0;
+    sourceRegion.back = 1;
+    context->CopySubresourceRegion(m_deviceResources.renderTarget(), 0, 0, 0, 0, m_output.Get(), 0, &sourceRegion);
+    context->OMSetRenderTargets(1, m_deviceResources.targetViewAddress(), nullptr);
+}

+ 152 - 0
samples/DX11/src/BilinearUpscale.cpp

@@ -0,0 +1,152 @@
+// The MIT License(MIT)
+//
+// Copyright(c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files(the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of
+// the Software, and to permit persons to whom the Software is 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 Software.
+//
+// THE SOFTWARE IS 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 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+#include "BilinearUpscale.h"
+#include "DXUtilities.h"
+#include "Utilities.h"
+
+#include <iostream>
+#include <d3dcompiler.h>
+
+void BilinearUpdateConfig(BilinearUpscaleConfig& config,
+    uint32_t inputViewportOriginX, uint32_t inputViewportOriginY,
+    uint32_t inputViewportWidth, uint32_t inputViewportHeight,
+    uint32_t inputTextureWidth, uint32_t inputTextureHeight,
+    uint32_t outputViewportOriginX, uint32_t outputViewportOriginY,
+    uint32_t outputViewportWidth, uint32_t outputViewportHeight,
+    uint32_t outputTextureWidth, uint32_t outputTextureHeight)
+{
+    config.kInputViewportHeight = inputViewportHeight;
+    config.kInputViewportWidth = inputViewportWidth;
+    config.kOutputViewportHeight = outputViewportHeight;
+    config.kOutputViewportWidth = outputViewportWidth;
+
+    config.kInputViewportOriginX = inputViewportOriginX;
+    config.kInputViewportOriginY = inputViewportOriginY;
+    config.kOutputViewportOriginX = outputViewportOriginX;
+    config.kOutputViewportOriginY = outputViewportOriginY;
+
+    config.kScaleX = inputTextureWidth / float(outputTextureWidth);
+    config.kScaleY = inputTextureWidth / float(outputTextureWidth);
+    config.kDstNormX = 1.f / outputTextureWidth;
+    config.kDstNormY = 1.f / outputTextureHeight;
+    config.kSrcNormX = 1.f / inputTextureWidth;
+    config.kSrcNormY = 1.f / inputTextureHeight;
+}
+
+BilinearUpscale::BilinearUpscale(DeviceResources& deviceResources)
+        : m_deviceResources(deviceResources)
+        , m_outputWidth(0)
+        , m_outputHeight(0)
+{
+    std::string skBlockWidth = std::to_string(kBlockWidth);
+    std::string skBlockHeight = std::to_string(kBlockHeight);
+    const D3D_SHADER_MACRO shaderMacros[] = { {"kBlockWidth", skBlockWidth.c_str() },
+                                              {"kBlockHeight", skBlockHeight.c_str() },
+                                              { nullptr, nullptr } };
+
+    static const char* upscaleShader =
+    R"(
+        Texture2D                 in_texture   : register(t0); // image srv
+        RWTexture2D<unorm float4> out_texture  : register(u1); // working uav
+        cbuffer cb : register(b0) {
+            uint     kInputViewportOriginX;
+            uint     kInputViewportOriginY;
+            uint     kInputViewportWidth;
+            uint     kInputViewportHeight;
+            uint     kOutputViewportOriginX;
+            uint     kOutputViewportOriginY;
+            uint     kOutputViewportWidth;
+            uint     kOutputViewportHeight;
+            float    kScaleX;
+            float    kScaleY;
+            float    kDstNormX;
+            float    kDstNormY;
+            float    kSrcNormX;
+            float    kSrcNormY;
+        }
+        SamplerState  samplerLinearClamp : register(s0);
+        [numthreads(kBlockWidth, kBlockHeight, 1)]
+        void Bilinear(uint3 id : SV_DispatchThreadID) {
+            float dX = (id.x + 0.5f) * kScaleX;
+            float dY = (id.y + 0.5f) * kScaleY;
+            if (id.x < kOutputViewportWidth && id.y < kOutputViewportHeight && dX < kInputViewportWidth && dY < kInputViewportHeight) {
+              float uvX = (dX + kInputViewportOriginX) * kSrcNormX;
+              float uvY = (dY + kInputViewportOriginY) * kSrcNormY;
+              uint dstX = id.x + kOutputViewportOriginX;
+              uint dstY = id.y + kOutputViewportOriginY;
+              out_texture[uint2(dstX, dstY)] = in_texture.SampleLevel(samplerLinearClamp, float2(uvX, uvY), 0);
+            }
+        }
+    )";
+
+    DX::CompileComputeShader(m_deviceResources.device(), upscaleShader, strlen(upscaleShader), "Bilinear", &m_computeShader, shaderMacros);
+
+    BilinearUpdateConfig(m_config, 0, 0, 100, 100, 100, 100, 0, 0, 100, 100, 100, 100);
+
+    D3D11_SAMPLER_DESC samplerDesc;
+    samplerDesc.Filter = D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT;
+    samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
+    samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
+    samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
+    samplerDesc.MipLODBias = 0.0f;
+    samplerDesc.MaxAnisotropy = 1;
+    samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
+    samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
+    DX::ThrowIfFailed(m_deviceResources.device()->CreateSamplerState(&samplerDesc, &m_LinearClampSampler));
+
+    D3D11_BUFFER_DESC bDesc;
+    bDesc.ByteWidth = sizeof(BilinearUpscaleConfig);
+    bDesc.Usage = D3D11_USAGE_DYNAMIC;
+    bDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
+    bDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+    bDesc.MiscFlags = 0;
+    bDesc.StructureByteStride = 0;
+
+    D3D11_SUBRESOURCE_DATA srData;
+    srData.pSysMem = &m_config;
+    srData.SysMemPitch = sizeof(BilinearUpscaleConfig);
+    srData.SysMemSlicePitch = 1;
+    DX::ThrowIfFailed(m_deviceResources.device()->CreateBuffer(&bDesc, &srData, &m_csBuffer));
+}
+
+void BilinearUpscale::update(uint32_t inputWidth, uint32_t inputHeight, uint32_t outputWidth, uint32_t outputHeight)
+{
+    BilinearUpdateConfig(m_config, 0, 0, inputWidth, inputHeight, inputWidth, inputHeight, 0, 0, outputWidth, outputHeight, outputWidth, outputHeight);
+    D3D11_MAPPED_SUBRESOURCE mappedResource;
+    m_deviceResources.context()->Map(m_csBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+    BilinearUpscaleConfig* dataPtr = (BilinearUpscaleConfig*)mappedResource.pData;
+    memcpy(dataPtr, &m_config, sizeof(BilinearUpscaleConfig));
+    m_deviceResources.context()->Unmap(m_csBuffer.Get(), 0);
+    m_outputWidth = outputWidth;
+    m_outputHeight = outputHeight;
+}
+
+void BilinearUpscale::dispatch(ID3D11ShaderResourceView* const* input, ID3D11UnorderedAccessView* const* output)
+{
+    auto context = m_deviceResources.context();
+    context->CSSetShader(m_computeShader.Get(), nullptr, 0);
+    context->CSSetShaderResources(0, 1, input);
+    context->CSSetUnorderedAccessViews(1, 1, output, nullptr);
+    context->CSSetSamplers(0, 1, m_LinearClampSampler.GetAddressOf());
+    context->CSSetConstantBuffers(0, 1, m_csBuffer.GetAddressOf());
+    context->Dispatch(UINT(std::ceil(m_outputWidth / float(kBlockWidth))), UINT(std::ceil(m_outputHeight / float(kBlockHeight))), 1);
+}

+ 218 - 0
samples/DX11/src/DeviceResources.cpp

@@ -0,0 +1,218 @@
+// The MIT License(MIT)
+//
+// Copyright(c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files(the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of
+// the Software, and to permit persons to whom the Software is 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 Software.
+//
+// THE SOFTWARE IS 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 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ 
+#include "DeviceResources.h"
+#include "DXUtilities.h"
+ 
+ 
+void DeviceResources::create(HWND hWnd, uint32_t adapterIdx)
+{
+    DXGI_SWAP_CHAIN_DESC desc;
+    ZeroMemory(&desc, sizeof(desc));
+    desc.BufferCount = 2;
+    desc.BufferDesc.Width = 320;
+    desc.BufferDesc.Height = 200;
+    desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+    desc.BufferDesc.RefreshRate.Numerator = 0;
+    desc.BufferDesc.RefreshRate.Denominator = 0;
+    desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
+    desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+    desc.OutputWindow = hWnd;
+    desc.SampleDesc.Count = 1;
+    desc.SampleDesc.Quality = 0;
+    desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
+    desc.Windowed = TRUE;
+ 
+    ComPtr<IDXGIFactory> pFactory;
+    CreateDXGIFactory(__uuidof(IDXGIFactory) ,(void**)&pFactory);
+    ComPtr<IDXGIAdapter> pAdapter;
+    if(pFactory->EnumAdapters(adapterIdx, &pAdapter) != DXGI_ERROR_NOT_FOUND)
+    {
+        DXGI_ADAPTER_DESC desc;
+        pAdapter->GetDesc(&desc);
+        char description[256]{};
+        snprintf(description, sizeof(description), "%ls", desc.Description);
+        m_adapter.Description = description;
+        m_adapter.DeviceId = desc.DeviceId;
+        m_adapter.VendorId = desc.VendorId;
+        m_adapter.DedicatedSystemMemory = desc.DedicatedSystemMemory;
+        m_adapter.DedicatedVideoMemory = desc.DedicatedVideoMemory;
+        m_adapter.SharedSystemMemory = desc.SharedSystemMemory;
+    }
+    else 
+    {
+        throw std::runtime_error("Adapter not found");
+    }
+ 
+    uint32_t createDeviceFlags = 0;
+    createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
+ 
+    D3D_FEATURE_LEVEL featureLevel;
+    const D3D_FEATURE_LEVEL featureLevelArray[2] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_0 };
+ 
+    HRESULT hr = D3D11CreateDeviceAndSwapChain(pAdapter.Get(), D3D_DRIVER_TYPE_UNKNOWN, nullptr,
+            createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &desc,
+            &m_swapChain, &m_d3dDevice, &featureLevel, &m_d3dContext);
+    DX::ThrowIfFailed(hr);
+ 
+    initRenderTarget();
+    m_initialized = true;
+}
+ 
+void DeviceResources::initRenderTarget()
+{
+    D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc;
+    ZeroMemory(&uavDesc, sizeof(D3D11_UNORDERED_ACCESS_VIEW_DESC));
+    uavDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+    uavDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D;
+ 
+    DX::ThrowIfFailed(m_swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), &m_d3dRenderTarget));
+    DX::ThrowIfFailed(m_d3dDevice->CreateRenderTargetView(m_d3dRenderTarget.Get(), NULL, &m_d3dRenderTargetView));
+}
+ 
+void DeviceResources::resizeRenderTarget(uint32_t Width, uint32_t Height, DXGI_FORMAT format)
+{
+    m_width = Width;
+    m_height = Height;
+    m_d3dRenderTargetUAV = nullptr;
+    m_d3dRenderTargetView = nullptr;
+    m_d3dRenderTarget = nullptr;
+    DX::ThrowIfFailed(m_swapChain->ResizeBuffers(0, Width, Height, format, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH));
+    initRenderTarget();
+}
+ 
+void DeviceResources::clearRenderTargetView(const float color[4])
+{
+    m_d3dContext->ClearRenderTargetView(m_d3dRenderTargetView.Get(), color);
+}
+ 
+void DeviceResources::createUAV(ID3D11Resource* pResource, DXGI_FORMAT format, ID3D11UnorderedAccessView** ppUAView)
+{
+    D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc;
+    ZeroMemory(&uavDesc, sizeof(D3D11_UNORDERED_ACCESS_VIEW_DESC));
+    uavDesc.Format = format;
+    uavDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D;
+    DX::ThrowIfFailed(m_d3dDevice->CreateUnorderedAccessView(pResource, &uavDesc, ppUAView));
+}
+ 
+void DeviceResources::createSRV(ID3D11Resource* pResource, DXGI_FORMAT format, ID3D11ShaderResourceView** ppSRView)
+{
+    D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+    ZeroMemory(&srvDesc, sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC));
+    srvDesc.Format = format;
+    srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+    srvDesc.Texture2D.MostDetailedMip = 0;
+    srvDesc.Texture2D.MipLevels = 1;
+    DX::ThrowIfFailed(m_d3dDevice->CreateShaderResourceView(pResource, &srvDesc, ppSRView));
+}
+ 
+void DeviceResources::createLinearClampSampler(ID3D11SamplerState** ppSampleState)
+{
+    D3D11_SAMPLER_DESC samplerDesc;
+    samplerDesc.Filter = D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT;
+    samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
+    samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
+    samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
+    samplerDesc.MipLODBias = 0.0f;
+    samplerDesc.MaxAnisotropy = 1;
+    samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
+    samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
+    DX::ThrowIfFailed(m_d3dDevice->CreateSamplerState(&samplerDesc, ppSampleState));
+}
+ 
+void DeviceResources::createTexture2D(int w, int h, DXGI_FORMAT format, D3D11_USAGE heapType, const void* data, uint32_t rowPitch, uint32_t imageSize, ID3D11Texture2D** ppTexture2D)
+{
+    D3D11_TEXTURE2D_DESC desc;
+    desc.Width = w;
+    desc.Height = h;
+    desc.MipLevels = 1;
+    desc.ArraySize = 1;
+    desc.Format = format;
+    desc.SampleDesc.Count = 1;
+    desc.SampleDesc.Quality = 0;
+ 
+    desc.MiscFlags = 0;
+    desc.Usage = heapType;
+    if (heapType == D3D11_USAGE_STAGING)
+    {
+        desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
+        desc.BindFlags = 0;
+    }
+    else
+    {
+        desc.CPUAccessFlags = 0;
+        desc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
+        desc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS;
+    }
+ 
+    D3D11_SUBRESOURCE_DATA* pInitialData = nullptr;
+    D3D11_SUBRESOURCE_DATA initData;
+    if (data)
+    {
+        initData.pSysMem = data;
+        initData.SysMemPitch = static_cast<uint32_t>(rowPitch);
+        initData.SysMemSlicePitch = static_cast<uint32_t>(imageSize);
+        pInitialData = &initData;
+    }
+ 
+    DX::ThrowIfFailed(m_d3dDevice->CreateTexture2D(&desc, pInitialData, ppTexture2D));
+}
+ 
+void DeviceResources::getTextureData(ID3D11Texture2D* texture, uint8_t* data)
+{
+    D3D11_TEXTURE2D_DESC desc;
+    texture->GetDesc(&desc);
+    desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
+    desc.BindFlags = 0;
+    desc.Usage = D3D11_USAGE_STAGING;
+    ComPtr<ID3D11Texture2D> stage;
+    m_d3dDevice->CreateTexture2D(&desc, nullptr, &stage);
+    m_d3dContext->CopyResource(stage.Get(), texture);
+    D3D11_MAPPED_SUBRESOURCE mappedResource;
+    DX::ThrowIfFailed(m_d3dContext->Map(stage.Get(), 0, D3D11_MAP_READ, 0, &mappedResource));
+    uint8_t* mappData = (uint8_t*)mappedResource.pData;
+    memcpy(data, mappData, mappedResource.DepthPitch);
+    m_d3dContext->Unmap(stage.Get(), 0);
+}
+ 
+void DeviceResources::updateConstBuffer(void* data, uint32_t size, ID3D11Buffer* ppBuffer)
+{
+    D3D11_MAPPED_SUBRESOURCE mappedResource;
+    m_d3dContext->Map(ppBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+    uint8_t* mappData = (uint8_t*)mappedResource.pData;
+    memcpy(mappData, data, size);
+    m_d3dContext->Unmap(ppBuffer, 0);
+}
+ 
+void DeviceResources::createConstBuffer(void* initialData, uint32_t size, ID3D11Buffer** ppBuffer)
+{
+    D3D11_BUFFER_DESC bDesc;
+    bDesc.ByteWidth = size;
+    bDesc.Usage = D3D11_USAGE_DYNAMIC;
+    bDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
+    bDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+    bDesc.MiscFlags = 0;
+    bDesc.StructureByteStride = 0;
+ 
+    D3D11_SUBRESOURCE_DATA srData;
+    srData.pSysMem = initialData;
+    DX::ThrowIfFailed(m_d3dDevice->CreateBuffer(&bDesc, &srData, ppBuffer));
+}

+ 98 - 0
samples/DX11/src/NVScaler.cpp

@@ -0,0 +1,98 @@
+// The MIT License(MIT)
+//
+// Copyright(c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files(the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of
+// the Software, and to permit persons to whom the Software is 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 Software.
+//
+// THE SOFTWARE IS 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 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ 
+#include "NVScaler.h"
+ 
+#pragma once
+#pragma once
+ 
+#include <dxgi1_4.h>
+#include <d3d11_3.h>
+#include <d3dcompiler.h>
+#include <iostream>
+ 
+#include "DXUtilities.h"
+#include "DeviceResources.h"
+#include "Utilities.h"
+ 
+ 
+NVScaler::NVScaler(DeviceResources& deviceResources, const std::string& shaderFolder)
+    : m_deviceResources(deviceResources)
+    , m_outputWidth(1)
+    , m_outputHeight(1)
+{
+    NISOptimizer opt(true, NISGPUArchitecture::NVIDIA_Generic);
+    m_blockWidth = opt.GetOptimalBlockWidth();
+    m_blockHeight = opt.GetOptimalBlockHeight();
+    uint32_t threadGroupSize = opt.GetOptimalThreadGroupSize();
+ 
+    DX::Defines defines;
+    defines.add("NIS_SCALER", true);
+    defines.add("NIS_HDR_MODE", uint32_t(NISHDRMode::None));
+    defines.add("NIS_BLOCK_WIDTH", m_blockWidth);
+    defines.add("NIS_BLOCK_HEIGHT", m_blockHeight);
+    defines.add("NIS_THREAD_GROUP_SIZE", threadGroupSize);
+ 
+    std::wstring wShaderFilename = widen(shaderFolder + "/" + "NIS_Main.hlsl");
+    DX::IncludeHeader includeHeader({ shaderFolder });
+    DX::CompileComputeShader(m_deviceResources.device(),
+        wShaderFilename.c_str(),
+        "main",
+        &m_computeShader,
+        defines.get(),
+        &includeHeader);
+ 
+    const int rowPitch = kFilterSize * 4;
+    const int imageSize = rowPitch * kPhaseCount;
+    m_deviceResources.createTexture2D(kFilterSize / 4, kPhaseCount, DXGI_FORMAT_R32G32B32A32_FLOAT, D3D11_USAGE_DEFAULT,
+        coef_scale, rowPitch, imageSize, &m_coef_scale);
+    m_deviceResources.createTexture2D(kFilterSize / 4, kPhaseCount, DXGI_FORMAT_R32G32B32A32_FLOAT, D3D11_USAGE_DEFAULT,
+        coef_usm, rowPitch, imageSize, &m_coef_usm);
+    m_deviceResources.createSRV(m_coef_scale.Get(), DXGI_FORMAT_R32G32B32A32_FLOAT, &m_coef_scaleSRV);
+    m_deviceResources.createSRV(m_coef_usm.Get(), DXGI_FORMAT_R32G32B32A32_FLOAT, &m_coef_usmSRV);
+    m_deviceResources.createLinearClampSampler(&m_LinearClampSampler);
+    m_deviceResources.createConstBuffer(&m_config, sizeof(NISConfig), &m_csBuffer);
+}
+ 
+void NVScaler::update(float sharpness, uint32_t inputWidth, uint32_t inputHeight, uint32_t outputWidth, uint32_t outputHeight)
+{
+    NVScalerUpdateConfig(m_config, sharpness,
+        0, 0, inputWidth, inputHeight, inputWidth, inputHeight,
+        0, 0, outputWidth, outputHeight, outputWidth, outputHeight,
+        NISHDRMode::None);
+ 
+    m_deviceResources.updateConstBuffer(&m_config, sizeof(NISConfig), m_csBuffer.Get());
+    m_outputWidth = outputWidth;
+    m_outputHeight = outputHeight;
+}
+ 
+void NVScaler::dispatch(ID3D11ShaderResourceView* const* input, ID3D11UnorderedAccessView* const* output)
+{
+    auto context = m_deviceResources.context();
+    context->CSSetShaderResources(0, 1, input);
+    context->CSSetUnorderedAccessViews(0, 1, output, nullptr);
+    context->CSSetShaderResources(1, 1, m_coef_scaleSRV.GetAddressOf());
+    context->CSSetShaderResources(2, 1, m_coef_usmSRV.GetAddressOf());
+    context->CSSetSamplers(0, 1, m_LinearClampSampler.GetAddressOf());
+    context->CSSetConstantBuffers(0, 1, m_csBuffer.GetAddressOf());
+    context->CSSetShader(m_computeShader.Get(), nullptr, 0);
+    context->Dispatch(UINT(std::ceil(m_outputWidth / float(m_blockWidth))), UINT(std::ceil(m_outputHeight / float(m_blockHeight))), 1);
+}

+ 88 - 0
samples/DX11/src/NVSharpen.cpp

@@ -0,0 +1,88 @@
+// The MIT License(MIT)
+//
+// Copyright(c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files(the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of
+// the Software, and to permit persons to whom the Software is 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 Software.
+//
+// THE SOFTWARE IS 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 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+#include "NVSharpen.h"
+
+#pragma once
+#pragma once
+
+#include <dxgi1_4.h>
+#include <d3d11_3.h>
+#include <d3dcompiler.h>
+#include <iostream>
+
+#include "DXUtilities.h"
+#include "DeviceResources.h"
+#include "Utilities.h"
+
+
+NVSharpen::NVSharpen(DeviceResources& deviceResources, const std::string& shaderFolder)
+    : m_deviceResources(deviceResources)
+    , m_outputWidth(1)
+    , m_outputHeight(1)
+{
+    NISOptimizer opt(false, NISGPUArchitecture::NVIDIA_Generic);
+    m_blockWidth = opt.GetOptimalBlockWidth();
+    m_blockHeight = opt.GetOptimalBlockHeight();
+    uint32_t threadGroupSize = opt.GetOptimalThreadGroupSize();
+
+    DX::Defines defines;
+    defines.add("NIS_SCALER", false);
+    defines.add("NIS_HDR_MODE", uint32_t(NISHDRMode::None));
+    defines.add("NIS_BLOCK_WIDTH", m_blockWidth);
+    defines.add("NIS_BLOCK_HEIGHT", m_blockHeight);
+    defines.add("NIS_THREAD_GROUP_SIZE", threadGroupSize);
+
+    std::wstring wShaderFilename = widen(shaderFolder + "/" + "NIS_Main.hlsl");
+    DX::IncludeHeader includeHeader({ shaderFolder });
+    DX::CompileComputeShader(m_deviceResources.device(),
+        wShaderFilename.c_str(),
+        "main",
+        &m_computeShader,
+        defines.get(),
+        &includeHeader);
+
+    const int rowPitch = kFilterSize * 4;
+    const int imageSize = rowPitch * kPhaseCount;
+    m_deviceResources.createLinearClampSampler(&m_LinearClampSampler);
+    m_deviceResources.createConstBuffer(&m_config, sizeof(NISConfig), &m_csBuffer);
+}
+
+void NVSharpen::update(float sharpness, uint32_t inputWidth, uint32_t inputHeight)
+{
+    NVSharpenUpdateConfig(m_config, sharpness,
+        0, 0, inputWidth, inputHeight, inputWidth, inputHeight,
+        0, 0, NISHDRMode::None);
+    m_deviceResources.updateConstBuffer(&m_config, sizeof(NISConfig), m_csBuffer.Get());
+    m_outputWidth = inputWidth;
+    m_outputHeight = inputHeight;
+}
+
+void NVSharpen::dispatch(ID3D11ShaderResourceView* const* input, ID3D11UnorderedAccessView* const* output)
+{
+    auto context = m_deviceResources.context();
+    context->CSSetShaderResources(0, 1, input);
+    context->CSSetUnorderedAccessViews(0, 1, output, nullptr);
+    context->CSSetSamplers(0, 1, m_LinearClampSampler.GetAddressOf());
+    context->CSSetConstantBuffers(0, 1, m_csBuffer.GetAddressOf());
+    context->CSSetShader(m_computeShader.Get(), nullptr, 0);
+    context->Dispatch(UINT(std::ceil(m_outputWidth / float(m_blockWidth))), UINT(std::ceil(m_outputHeight / float(m_blockHeight))), 1);
+}

+ 159 - 0
samples/DX11/src/Sample.cpp

@@ -0,0 +1,159 @@
+// The MIT License(MIT)
+//
+// Copyright(c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files(the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of
+// the Software, and to permit persons to whom the Software is 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 Software.
+//
+// THE SOFTWARE IS 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 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#pragma comment(lib, "user32")
+#pragma comment(lib, "d3d11")
+#pragma comment(lib, "dxgi")
+#pragma comment(lib, "d3dcompiler")
+#pragma comment(lib, "windowscodecs")
+ 
+ 
+#include <d3d11.h>
+#include <filesystem>
+#include <iostream>
+#include <tchar.h>
+#include <wincodec.h>
+ 
+#include "AppRenderer.h"
+#include "DeviceResources.h"
+#include "UIRenderer.h"
+#include "Utilities.h"
+ 
+DeviceResources deviceResources;
+UIData uiData;
+ 
+LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+ 
+int main(int argc, char* argv[])
+{
+    // Resources
+    std::string mediaFolder = "media/images/";
+    std::string shadersFolder = "NIS/";
+ 
+    if (!std::filesystem::exists(mediaFolder))
+        mediaFolder = "media/images/";
+    if (!std::filesystem::exists(mediaFolder))
+        mediaFolder = "../../media/images/";
+    if (!std::filesystem::exists(mediaFolder))
+        return -1;
+    if (!std::filesystem::exists(shadersFolder))
+        shadersFolder = "NIS/";
+    if (!std::filesystem::exists(shadersFolder))
+        shadersFolder = "../../../NIS/";
+    if (!std::filesystem::exists(shadersFolder))
+        return -1;
+ 
+    // Create Window
+    WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(nullptr),
+                    nullptr, nullptr, nullptr, nullptr, L"NVIDIA Image Scaling Demo", nullptr };
+    ::RegisterClassEx(&wc);
+    RECT wr = { 0, 0, 1280, 1080 };
+    AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
+    HWND hwnd = ::CreateWindow(wc.lpszClassName, L"NVIDIA Image Scaling DX11 Demo", WS_OVERLAPPEDWINDOW,
+                    100, 100, wr.right - wr.left, wr.bottom - wr.top, nullptr, nullptr, wc.hInstance, nullptr);
+    ::SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_SIZEBOX);
+    SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
+ 
+    // Initialize DX11
+    deviceResources.create(hwnd, 0);
+ 
+    // Show the window
+    ::ShowWindow(hwnd, SW_SHOWDEFAULT);
+    ::UpdateWindow(hwnd);
+ 
+    // UI settings
+    uiData.Files = getFiles(mediaFolder);
+    if (uiData.Files.size() == 0)
+        throw std::runtime_error("No media files");
+    uiData.FileName = uiData.Files[0].filename().string();
+    uiData.FilePath = uiData.Files[0];
+ 
+    // Renderers
+    AppRenderer appRenderer(deviceResources, uiData, shadersFolder);
+    UIRenderer uiRenderer(hwnd, deviceResources, uiData);
+    FPS m_fps;
+ 
+    MSG msg{};
+    while (msg.message != WM_QUIT)
+    {
+        if (::PeekMessage(&msg, nullptr, 0U, 0U, PM_REMOVE))
+        {
+            ::TranslateMessage(&msg);
+            ::DispatchMessage(&msg);
+        }
+ 
+        // Update
+        m_fps.update();
+        if (appRenderer.update())
+        {
+            RECT wr = { 0, 0, LONG(appRenderer.width()), LONG(appRenderer.height()) };
+            AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
+            SetWindowPos(hwnd, nullptr, 0, 0, wr.right - wr.left, wr.bottom - wr.top, SWP_NOMOVE);
+        }
+        uiRenderer.update(m_fps.fps());
+ 
+        // Render
+        appRenderer.render();
+        uiRenderer.render(); // render UI at the end
+ 
+        deviceResources.present(uiData.EnableVsync, 0);
+    }
+ 
+    uiRenderer.cleanUp();
+ 
+    ::DestroyWindow(hwnd);
+    ::UnregisterClass(wc.lpszClassName, wc.hInstance);
+ 
+    return 0;
+}
+ 
+// Forward declare message handler from imgui_impl_win32.cpp
+extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+ 
+// Win32 message handler
+LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+    if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
+        return true;
+ 
+    switch (msg)
+    {
+    case WM_SIZE:
+        if (deviceResources.initialized() && wParam != SIZE_MINIMIZED)
+        {
+            deviceResources.resizeRenderTarget((UINT)LOWORD(lParam), (UINT)HIWORD(lParam), DXGI_FORMAT_R8G8B8A8_UNORM);
+        }
+        return 0;
+    case WM_SYSCOMMAND:
+        if ((wParam & 0xfff0) == SC_KEYMENU) // Disable ALT application menu
+            return 0;
+        break;
+    case WM_KEYUP:
+    case WM_SYSKEYUP:
+        if (wParam == VK_F1)
+            uiData.ShowSettings = !uiData.ShowSettings;
+        break;
+    case WM_CLOSE:
+    case WM_DESTROY:
+        ::PostQuitMessage(0);
+        return 0;
+    }
+    return ::DefWindowProc(hWnd, msg, wParam, lParam);
+}

+ 196 - 0
samples/DX11/src/UIRenderer.cpp

@@ -0,0 +1,196 @@
+// The MIT License(MIT)
+// 
+// Copyright(c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+// 
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files(the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of
+// the Software, and to permit persons to whom the Software is 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 Software.
+// 
+// THE SOFTWARE IS 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 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ 
+#include <UIRenderer.h>
+ 
+UIRenderer::UIRenderer(HWND hwnd, DeviceResources& deviceResources, UIData& ui)
+: m_ui(ui)
+, m_deviceResources(deviceResources)
+{
+    // Setup Dear ImGui context
+    IMGUI_CHECKVERSION();
+    ImGui::CreateContext();
+    ImGuiIO& io = ImGui::GetIO(); (void)io;
+ 
+    ImGui::StyleColorsDark();
+    ImGui::GetStyle().WindowRounding = 6;
+    ImGui::GetStyle().FrameBorderSize = 1;
+ 
+    ImGui_ImplWin32_Init(hwnd);
+    ImGui_ImplDX11_Init(m_deviceResources.device(), m_deviceResources.context());
+}
+ 
+void UIRenderer::cleanUp()
+{
+    // Cleanup
+    ImGui_ImplDX11_Shutdown();
+    ImGui_ImplWin32_Shutdown();
+    ImGui::DestroyContext();
+}
+ 
+void UIRenderer::update(double fps)
+{
+    m_elapsedTimer.start();
+    ImGui_ImplDX11_NewFrame();
+    ImGui_ImplWin32_NewFrame();
+    ImGui::NewFrame();
+    if (m_ui.ShowSettings)
+    {
+        ImGui::Begin("Settings", 0, ImGuiWindowFlags_AlwaysAutoResize);
+        if (ImGui::CollapsingHeader("GPU Info", ImGuiTreeNodeFlags_DefaultOpen))
+        {
+            Adapter adapter = m_deviceResources.getAdapter();
+            ImGui::Text("Description: %s", adapter.Description.c_str());
+            ImGui::Text("VendorID: 0x%x DeviceID: 0x%x", adapter.VendorId, adapter.DeviceId);
+            ImGui::Text("DedicatedSystemMemory: %d [MB]", adapter.DedicatedVideoMemory / 1024 / 1024);
+            ImGui::Text("SharedSystemMemory   : %d [MB]", adapter.SharedSystemMemory / 1024 / 1024);
+        }
+        if (ImGui::CollapsingHeader("Images", ImGuiTreeNodeFlags_DefaultOpen))
+        {
+            if (ImGui::BeginCombo("Filename", m_ui.FileName.c_str()))
+            {
+                for (auto& e : m_ui.Files)
+                {
+                    bool is_selected = (m_ui.FileName == e.filename().string());
+                    if (ImGui::Selectable(e.filename().string().c_str(), is_selected))
+                    {
+                        m_ui.FileName = e.filename().string();
+                        m_ui.FilePath = e;
+                    }
+                    if (is_selected)
+                    {
+                        ImGui::SetItemDefaultFocus();
+                    }
+                }
+                ImGui::EndCombo();
+            }
+        }
+        if (ImGui::CollapsingHeader("Filter", ImGuiTreeNodeFlags_DefaultOpen))
+        {
+            ImGui::RadioButton("NVScaler", &m_ui.FilterMode, 0); ImGui::SameLine();
+            ImGui::RadioButton("Bilinear", &m_ui.FilterMode, 2); ImGui::SameLine();
+            ImGui::RadioButton("NVSharpen", &m_ui.FilterMode, 1);
+            ;
+            ImGui::Separator();
+            if (m_ui.FilterMode == 0 || m_ui.FilterMode == 1)
+            {
+                m_ui.EnableNVScaler = true;
+                ImGui::SliderFloat("Sharpness (0% - 100%)", &m_ui.Sharpness, 0, 100, "%2.1f%%");
+            }
+            else
+            {
+                m_ui.EnableNVScaler = false;
+            }
+            if (m_ui.FilterMode == 0 || m_ui.FilterMode == 2)
+            {
+                ImGui::Separator();
+                std::vector<const char*> outputSizes = { "Variable", "1920x1080", "2560x1440", "3840x2160" };
+                ImGui::Combo("Height Size", (int*)&m_ui.OutputMode, outputSizes.data(), int(outputSizes.size()));
+                float fixScaleSize = 0;
+                switch (m_ui.OutputMode) {
+                case OutputSizeMode::VARIABLE:
+                    ImGui::SliderFloat("Scale (50% - 100%)", &m_ui.Scale, 50, 100, "%2.1f%%");
+                    break;
+                case OutputSizeMode::P1080:
+                    fixScaleSize = 1080.f;
+                    break;
+                case OutputSizeMode::P1440:
+                    fixScaleSize = 1440.f;
+                    break;
+                case OutputSizeMode::P2160:
+                    fixScaleSize = 2160.f;
+                    break;
+                }
+                if (fixScaleSize > 0)
+                {
+                    m_ui.Scale = std::min<float>(100.f, std::max<float>(50.f, m_ui.InputHeight / fixScaleSize * 100.f));
+                    ImGui::Text("Fix Scale : %2.1f%%", m_ui.Scale);
+                }
+            }
+            else
+            {
+                m_ui.Scale = 100;
+            }
+            ImGui::Separator();
+            if (m_ui.Scale == 100)
+            {
+                if (m_ui.EnableNVScaler)
+                {
+                    ImGui::Text("Using NVSharpen shader:");
+                    ImGui::Text("Scale 100 %% performs only sharpening");
+                }
+                else
+                {
+                    ImGui::Text("Using CopyResource");
+                }
+            }
+            else
+            {
+                if (m_ui.EnableNVScaler)
+                {
+                    ImGui::Text("Using NVScaler shader:");
+                    ImGui::Text("Performs scaling and sharpening");
+                }
+                else
+                {
+                    ImGui::Text("Using bilinear upscale shader");
+                }
+            }
+            ImGui::Separator();
+            ImGui::Text("Input Size  : %d x %d", m_ui.InputWidth, m_ui.InputHeight);
+            ImGui::Text("Output Size : %d x %d", m_ui.OutputWidth, m_ui.OutputHeight);
+        }
+        if (ImGui::CollapsingHeader("Display", ImGuiTreeNodeFlags_DefaultOpen))
+        {
+            ImGui::Checkbox("VSync", &m_ui.EnableVsync);
+        }
+        if (ImGui::CollapsingHeader("Profiling", ImGuiTreeNodeFlags_DefaultOpen))
+        {
+            ImGui::RadioButton("microseconds", &m_ui.UnitMicroseconds, 1); ImGui::SameLine();
+            ImGui::RadioButton("milliseconds", &m_ui.UnitMicroseconds, 0);
+            ImGui::Separator();
+            double unitConst = 1E6;
+            std::string unitStr = "us";
+            if (!m_ui.UnitMicroseconds)
+            {
+                unitConst = 1E3;
+                unitStr = "ms";
+            }
+            double filterTime = m_ui.FilterTime / 1E6 * unitConst;
+            double totalTime = 1. / fps * unitConst;
+            double uiTime = m_elapsedTimer.averageTime_us() / 1E6 * unitConst;
+            ImGui::Text("FPS         : %9.2f", fps);
+            ImGui::Text("Filter Time : %9.2f %s", filterTime, unitStr.c_str());
+            ImGui::Text("UI Time     : %9.2f %s", uiTime, unitStr.c_str());
+            ImGui::Text("Presnt Time : %9.2f %s", totalTime - filterTime - uiTime, unitStr.c_str());
+            ImGui::Text("Total Time  : %9.2f %s", totalTime, unitStr.c_str());
+        }
+ 
+        ImGui::End();
+    }
+    ImGui::Render();
+    m_elapsedTimer.end();
+}
+ 
+void UIRenderer::render()
+{
+    ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
+}

+ 9 - 0
samples/DX11/src/dpi.manifest

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
+  <asmv3:application>
+    <asmv3:windowsSettings>
+      <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
+      <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
+    </asmv3:windowsSettings>
+  </asmv3:application>
+</assembly>

+ 67 - 0
samples/common/Image.cpp

@@ -0,0 +1,67 @@
+// The MIT License(MIT)
+// 
+// Copyright(c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+// 
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files(the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of
+// the Software, and to permit persons to whom the Software is 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 Software.
+// 
+// THE SOFTWARE IS 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 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+#include "Image.h"
+#include "DXUtilities.h"
+
+Image::Image() 
+{
+    DX::ThrowIfFailed(CoInitialize(nullptr));
+    DX::ThrowIfFailed(CoCreateInstance(CLSID_WICImagingFactory, nullptr, CLSCTX_INPROC_SERVER, __uuidof(IWICImagingFactory), (LPVOID*)&m_WICFactory));
+}
+
+void Image::load(const std::filesystem::path& FilePath)
+{
+    if (FilePath.extension() == ".png")
+        LoadWIC(FilePath.wstring());
+}
+
+void Image::LoadWIC(const std::wstring& filename)
+{
+    wchar_t* wfilename = _wcsdup(filename.c_str());
+    ComPtr<IWICBitmapDecoder> decoder;
+    DX::ThrowIfFailed(m_WICFactory->CreateDecoderFromFilename(wfilename, 0, GENERIC_READ, WICDecodeMetadataCacheOnDemand, &decoder));
+    ComPtr<IWICBitmapFrameDecode> frame;
+    DX::ThrowIfFailed(decoder->GetFrame(0, &frame));
+    DX::ThrowIfFailed(frame->GetSize(&m_width, &m_height));
+    // get bpp
+    WICPixelFormatGUID pixelFormat;
+    DX::ThrowIfFailed(frame->GetPixelFormat(&pixelFormat));
+    ComPtr<IWICBitmapSource> pConvertedFrame;
+    if (pixelFormat != GUID_WICPixelFormat32bppRGBA)
+    {
+        DX::ThrowIfFailed(WICConvertBitmapSource(GUID_WICPixelFormat32bppRGBA, frame.Get(), &pConvertedFrame));
+    }
+    else
+    {
+        pConvertedFrame = frame;
+    }
+    DX::ThrowIfFailed(pConvertedFrame->GetPixelFormat(&pixelFormat));
+    ComPtr<IWICComponentInfo> cinfo;
+    DX::ThrowIfFailed(m_WICFactory->CreateComponentInfo(pixelFormat, &cinfo));
+    ComPtr<IWICPixelFormatInfo> pfinfo;
+    DX::ThrowIfFailed(cinfo->QueryInterface(__uuidof(IWICPixelFormatInfo), &pfinfo));
+    DX::ThrowIfFailed(pfinfo->GetBitsPerPixel(&m_bpp));
+    m_rowPitch = (m_width * m_bpp + 7) / 8;
+    m_imageSize = m_rowPitch * m_height;
+    m_data.resize(m_imageSize);
+    DX::ThrowIfFailed(pConvertedFrame->CopyPixels(0, m_rowPitch, m_imageSize, m_data.data()));
+}

+ 53 - 0
samples/common/Image.h

@@ -0,0 +1,53 @@
+// The MIT License(MIT)
+// 
+// Copyright(c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+// 
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files(the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of
+// the Software, and to permit persons to whom the Software is 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 Software.
+// 
+// THE SOFTWARE IS 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 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+#pragma once
+
+#include <filesystem>
+#include <iostream>
+#include <string>
+#include <vector>
+#include <wincodec.h>
+#include <wrl.h>
+
+using namespace Microsoft::WRL;
+
+class Image
+{
+public:
+    Image();
+    void load(const std::filesystem::path& FilePath);
+    uint32_t width() { return m_width; }
+    uint32_t height() { return m_height; }
+    uint32_t bpp() { return m_bpp; }
+    uint32_t rowPitch() { return m_rowPitch; }
+    uint32_t imageSize() { return m_imageSize; }
+    uint8_t* data() { return m_data.data(); }
+protected:
+    void LoadWIC(const std::wstring& filename);
+private:    
+    uint32_t m_width, m_height;
+    uint32_t m_bpp;
+    std::vector<uint8_t> m_data;
+    uint32_t m_rowPitch;
+    uint32_t m_imageSize;
+    ComPtr<IWICImagingFactory> m_WICFactory;
+};

+ 213 - 0
samples/common/Utilities.h

@@ -0,0 +1,213 @@
+// The MIT License(MIT)
+// 
+// Copyright(c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+// 
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files(the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of
+// the Software, and to permit persons to whom the Software is 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 Software.
+// 
+// THE SOFTWARE IS 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 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+#pragma once
+
+#include <chrono>
+#include <filesystem>
+#include <iomanip>
+#include <iostream>
+#include <map>
+#include <sstream>
+#include <unordered_map>
+#include <vector>
+
+inline std::vector<std::filesystem::path> getFiles(const std::string& path, const std::string& ext = "")
+{
+    namespace fs = std::filesystem;
+    std::vector<fs::path> ret;
+    for (const auto& e : fs::directory_iterator(path)) {
+        if (ext == "" || e.path().extension() == ext)
+            ret.push_back(e.path());
+    }
+    return ret;
+}
+
+
+class FPS {
+public:
+    FPS(double maxTime = 100000) : m_maxTime(maxTime), m_totalTime(0), m_averageTime(0), m_numFrames(0) {
+        m_t0 = std::chrono::high_resolution_clock::now();
+    }
+    void update() {
+        m_t1 = std::chrono::high_resolution_clock::now();
+        m_totalTime += std::chrono::duration_cast<std::chrono::microseconds>(m_t1 - m_t0).count();
+        m_t0 = m_t1;
+        m_numFrames++;
+        // update only when time is up
+        if (m_totalTime > m_maxTime) 
+        {
+            m_averageTime = m_totalTime / m_numFrames;
+            m_totalTime = 0.0;
+            m_numFrames = 0;
+        }
+    }
+    void setMaxTime(double maxTime) { 
+        m_maxTime = maxTime; 
+    }
+    double averageTime_us() {
+        return m_averageTime;
+    }
+    double averageTime_ms() {
+        return m_averageTime / 1E3;
+    }
+    double fps() {
+        return 1 / m_averageTime * 1E6;
+    }
+private:
+    double m_maxTime;
+    double m_totalTime;
+    double m_averageTime;
+    size_t m_numFrames;
+    std::chrono::steady_clock::time_point m_t0, m_t1;
+};
+
+class ElapsedTimer {
+public:
+    ElapsedTimer(uint32_t maxIterations = 500) : m_maxIterations(maxIterations), m_totalTime(0), m_averageTime(0) {
+        m_t0 = std::chrono::high_resolution_clock::now();
+    }
+    void start() {
+        m_t0 = std::chrono::high_resolution_clock::now();
+    }
+    void end() {
+        m_t1 = std::chrono::high_resolution_clock::now();
+        m_totalTime += std::chrono::duration_cast<std::chrono::microseconds>(m_t1 - m_t0).count();
+        m_numIterations++;
+        if (m_numIterations > m_maxIterations)
+        {
+            m_averageTime = m_totalTime / m_maxIterations;
+            m_totalTime = 0.0;
+            m_numIterations = 0;
+        }
+    }
+    void setMaxTime(uint32_t maxTime) {
+        m_maxIterations = maxTime;
+    }
+    double averageTime_us() {
+        return m_averageTime;
+    }
+    double averageTime_ms() {
+        return m_averageTime / 1E3;
+    }
+private:
+    uint32_t m_maxIterations;
+    double m_totalTime;
+    double m_averageTime;
+    size_t m_numIterations;
+    std::chrono::steady_clock::time_point m_t0, m_t1;
+};
+
+
+
+class ArgParser {
+public:
+    ArgParser(int argc, char* argv[]) {
+        programName = argv[0];
+        addOption("-h", "Print this help");
+        for (size_t i = 1; i < argc; ++i)
+            arguments.push_back(argv[i]);
+    }
+    void addOption(const std::string& opt, const std::string& description) {
+        options[opt] = description;
+    }
+    void printHelp() {
+        std::cout << "Usage: " << programName << " " << std::endl;
+        std::cout << "----------------------------------------" << std::endl;
+        for (auto& e : options) {
+            std::cout << e.first << " " << e.second << std::endl;;
+        }
+    }
+    bool parse(bool requiredArgs = false) {
+        if (arguments.size() > 0 && arguments[0] == "-h") {
+            printHelp();
+            return false;
+        }
+        if (arguments.size() < 1) {
+            return !requiredArgs;
+        }
+        bool lastOpt = false;
+        size_t i = 0;
+        while (i < arguments.size()) {
+            if (options.find(arguments[i]) != options.end() && i < arguments.size() - 1) {
+                argMap[arguments[i]] = arguments[i + 1];
+                i += 2;
+            }
+            else {
+                std::cout << "Argument not found : " << arguments[i] << std::endl;
+                printHelp();
+                return false;
+            }
+        }
+        return true;
+    }
+    template<typename T>
+    T get(const std::string& opt, T defaultVal = T()) {
+        T val;
+        auto sval = argMap.find(opt);
+        if (sval == argMap.end())
+            return defaultVal;
+        std::stringstream ss;
+        ss << sval->second;
+        ss >> val;
+        return val;
+    }
+private:
+    std::map<std::string, std::string> options;
+    std::vector<std::string> arguments;
+    std::unordered_map<std::string, std::string> argMap;
+    std::string programName;
+};
+
+
+inline std::wstring widen(const std::string& str)
+{
+    int size = MultiByteToWideChar(CP_ACP, 0, str.c_str(), int(str.size()) + 1, 0, 0);
+    std::vector<wchar_t> temp(size);
+    MultiByteToWideChar(CP_ACP, 0, str.c_str(), int(str.size()) + 1, &temp[0], int(temp.size()));
+    return std::wstring(&temp[0]);
+}
+
+template <typename T>
+inline std::string toStr(T value)
+{
+    return std::to_string(value);
+}
+
+template <>
+inline std::string toStr<bool>(bool value)
+{
+    return value ? "1" : "0";
+}
+
+template <>
+inline std::string toStr<std::string>(std::string value)
+{
+    return value;
+}
+
+template <>
+inline std::string toStr<const char*>(const char* value)
+{
+    return value;
+}
+
+

BIN
samples/media/images/1080.png


BIN
samples/media/images/1440.png


+ 47 - 0
samples/third_party/glfw/.appveyor.yml

@@ -0,0 +1,47 @@
+image:
+    - Visual Studio 2015
+branches:
+    only:
+        - ci
+        - master
+        - latest
+        - 3.3-stable
+skip_tags: true
+environment:
+    matrix:
+        - GENERATOR: MinGW Makefiles
+          BUILD_SHARED_LIBS: ON
+          CFLAGS: -Werror
+        - GENERATOR: MinGW Makefiles
+          BUILD_SHARED_LIBS: OFF
+          CFLAGS: -Werror
+        - GENERATOR: Visual Studio 10 2010
+          BUILD_SHARED_LIBS: ON
+          CFLAGS: /WX
+        - GENERATOR: Visual Studio 10 2010
+          BUILD_SHARED_LIBS: OFF
+          CFLAGS: /WX
+matrix:
+    fast_finish: true
+for:
+-
+    matrix:
+        only:
+            - GENERATOR: MinGW Makefiles
+    build_script:
+        - set PATH=%PATH:C:\Program Files\Git\usr\bin=C:\MinGW\bin%
+        - cmake -S . -B build -G "%GENERATOR%" -DBUILD_SHARED_LIBS=%BUILD_SHARED_LIBS%
+        - cmake --build build
+-
+    matrix:
+        only:
+            - GENERATOR: Visual Studio 10 2010
+    build_script:
+        - cmake -S . -B build -G "%GENERATOR%" -DBUILD_SHARED_LIBS=%BUILD_SHARED_LIBS%
+        - cmake --build build --target glfw
+notifications:
+    - provider: Email
+      to:
+        - ci@glfw.org
+      on_build_failure: true
+      on_build_success: false

+ 5 - 0
samples/third_party/glfw/.gitattributes

@@ -0,0 +1,5 @@
+*.m linguist-language=Objective-C
+.gitignore export-ignore
+.gitattributes export-ignore
+.travis.yml export-ignore
+.appveyor.yml export-ignore

+ 104 - 0
samples/third_party/glfw/.gitignore

@@ -0,0 +1,104 @@
+# The canonical out-of-tree build subdirectory
+build
+
+# Visual Studio clutter
+_ReSharper*
+*.sdf
+*.suo
+*.dir
+*.vcxproj*
+*.sln
+.vs
+CMakeSettings.json
+Win32
+x64
+Debug
+Release
+MinSizeRel
+RelWithDebInfo
+*.opensdf
+
+# Xcode clutter
+GLFW.build
+GLFW.xcodeproj
+
+# macOS clutter
+.DS_Store
+
+# Makefile generator clutter
+Makefile
+
+# Ninja generator clutter
+build.ninja
+rules.ninja
+.ninja_deps
+.ninja_log
+
+# CMake clutter
+CMakeCache.txt
+CMakeFiles
+CMakeScripts
+CMakeDoxyfile.in
+CMakeDoxygenDefaults.cmake
+cmake_install.cmake
+cmake_uninstall.cmake
+
+# Generated files
+docs/Doxyfile
+docs/html
+docs/warnings.txt
+docs/doxygen_sqlite3.db
+src/glfw_config.h
+src/glfw3.pc
+src/glfw3Config.cmake
+src/glfw3ConfigVersion.cmake
+src/wayland-pointer-constraints-unstable-v1-client-protocol.h
+src/wayland-pointer-constraints-unstable-v1-protocol.c
+src/wayland-relative-pointer-unstable-v1-client-protocol.h
+src/wayland-relative-pointer-unstable-v1-protocol.c
+
+# Compiled binaries
+src/libglfw.so
+src/libglfw.so.3
+src/libglfw.so.3.3
+src/libglfw.dylib
+src/libglfw.dylib
+src/libglfw.3.dylib
+src/libglfw.3.3.dylib
+src/libglfw3.a
+src/glfw3.lib
+src/glfw3.dll
+src/glfw3dll.lib
+src/libglfw3dll.a
+examples/*.app
+examples/*.exe
+examples/boing
+examples/gears
+examples/heightmap
+examples/offscreen
+examples/particles
+examples/splitview
+examples/sharing
+examples/simple
+examples/wave
+tests/*.app
+tests/*.exe
+tests/clipboard
+tests/cursor
+tests/empty
+tests/events
+tests/gamma
+tests/glfwinfo
+tests/icon
+tests/iconify
+tests/joysticks
+tests/monitors
+tests/msaa
+tests/reopen
+tests/tearing
+tests/threads
+tests/timeout
+tests/title
+tests/triangle-vulkan
+tests/windows
+

+ 10 - 0
samples/third_party/glfw/.mailmap

@@ -0,0 +1,10 @@
+Camilla Löwy <elmindreda@glfw.org> <elmindreda@users.sourceforge.net>
+Camilla Löwy <elmindreda@glfw.org> <elmindreda@elmindreda.org>
+Camilla Löwy <elmindreda@glfw.org>
+
+Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
+
+Marcus Geelnard <m@bitsnbites.eu> <marcus256@users.sourceforge.net>
+Marcus Geelnard <m@bitsnbites.eu> <marcus@geelnards-pc.(none)>
+Marcus Geelnard <m@bitsnbites.eu>
+

+ 48 - 0
samples/third_party/glfw/CMake/GenerateMappings.cmake

@@ -0,0 +1,48 @@
+# Usage:
+# cmake -P GenerateMappings.cmake <path/to/mappings.h.in> <path/to/mappings.h>
+
+set(source_url "https://raw.githubusercontent.com/gabomdq/SDL_GameControllerDB/master/gamecontrollerdb.txt")
+set(source_path "${CMAKE_CURRENT_BINARY_DIR}/gamecontrollerdb.txt")
+set(template_path "${CMAKE_ARGV3}")
+set(target_path "${CMAKE_ARGV4}")
+
+if (NOT EXISTS "${template_path}")
+    message(FATAL_ERROR "Failed to find template file ${template_path}")
+endif()
+
+file(DOWNLOAD "${source_url}" "${source_path}"
+     STATUS download_status
+     TLS_VERIFY on)
+
+list(GET download_status 0 status_code)
+list(GET download_status 1 status_message)
+
+if (status_code)
+    message(FATAL_ERROR "Failed to download ${source_url}: ${status_message}")
+endif()
+
+file(STRINGS "${source_path}" lines)
+foreach(line ${lines})
+    if (line MATCHES "^[0-9a-fA-F]")
+        if (line MATCHES "platform:Windows")
+            if (GLFW_WIN32_MAPPINGS)
+                set(GLFW_WIN32_MAPPINGS "${GLFW_WIN32_MAPPINGS}\n")
+            endif()
+            set(GLFW_WIN32_MAPPINGS "${GLFW_WIN32_MAPPINGS}\"${line}\",")
+        elseif (line MATCHES "platform:Mac OS X")
+            if (GLFW_COCOA_MAPPINGS)
+                set(GLFW_COCOA_MAPPINGS "${GLFW_COCOA_MAPPINGS}\n")
+            endif()
+            set(GLFW_COCOA_MAPPINGS "${GLFW_COCOA_MAPPINGS}\"${line}\",")
+        elseif (line MATCHES "platform:Linux")
+            if (GLFW_LINUX_MAPPINGS)
+                set(GLFW_LINUX_MAPPINGS "${GLFW_LINUX_MAPPINGS}\n")
+            endif()
+            set(GLFW_LINUX_MAPPINGS "${GLFW_LINUX_MAPPINGS}\"${line}\",")
+        endif()
+    endif()
+endforeach()
+
+configure_file("${template_path}" "${target_path}" @ONLY NEWLINE_STYLE UNIX)
+file(REMOVE "${source_path}")
+

+ 38 - 0
samples/third_party/glfw/CMake/MacOSXBundleInfo.plist.in

@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>English</string>
+	<key>CFBundleExecutable</key>
+	<string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
+	<key>CFBundleGetInfoString</key>
+	<string>${MACOSX_BUNDLE_INFO_STRING}</string>
+	<key>CFBundleIconFile</key>
+	<string>${MACOSX_BUNDLE_ICON_FILE}</string>
+	<key>CFBundleIdentifier</key>
+	<string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleLongVersionString</key>
+	<string>${MACOSX_BUNDLE_LONG_VERSION_STRING}</string>
+	<key>CFBundleName</key>
+	<string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
+	<key>CFBundlePackageType</key>
+	<string>APPL</string>
+	<key>CFBundleShortVersionString</key>
+	<string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
+	<key>CSResourcesFileMapped</key>
+	<true/>
+	<key>LSRequiresCarbon</key>
+	<true/>
+	<key>NSHumanReadableCopyright</key>
+	<string>${MACOSX_BUNDLE_COPYRIGHT}</string>
+	<key>NSHighResolutionCapable</key>
+	<true/>
+</dict>
+</plist>

+ 13 - 0
samples/third_party/glfw/CMake/i686-w64-mingw32-clang.cmake

@@ -0,0 +1,13 @@
+# Define the environment for cross-compiling with 32-bit MinGW-w64 Clang
+SET(CMAKE_SYSTEM_NAME    Windows) # Target system name
+SET(CMAKE_SYSTEM_VERSION 1)
+SET(CMAKE_C_COMPILER     "i686-w64-mingw32-clang")
+SET(CMAKE_CXX_COMPILER   "i686-w64-mingw32-clang++")
+SET(CMAKE_RC_COMPILER    "i686-w64-mingw32-windres")
+SET(CMAKE_RANLIB         "i686-w64-mingw32-ranlib")
+
+# Configure the behaviour of the find commands
+SET(CMAKE_FIND_ROOT_PATH "/usr/i686-w64-mingw32")
+SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

+ 13 - 0
samples/third_party/glfw/CMake/i686-w64-mingw32.cmake

@@ -0,0 +1,13 @@
+# Define the environment for cross-compiling with 32-bit MinGW-w64 GCC
+SET(CMAKE_SYSTEM_NAME    Windows) # Target system name
+SET(CMAKE_SYSTEM_VERSION 1)
+SET(CMAKE_C_COMPILER     "i686-w64-mingw32-gcc")
+SET(CMAKE_CXX_COMPILER   "i686-w64-mingw32-g++")
+SET(CMAKE_RC_COMPILER    "i686-w64-mingw32-windres")
+SET(CMAKE_RANLIB         "i686-w64-mingw32-ranlib")
+
+# Configure the behaviour of the find commands
+SET(CMAKE_FIND_ROOT_PATH "/usr/i686-w64-mingw32")
+SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

+ 17 - 0
samples/third_party/glfw/CMake/modules/FindEpollShim.cmake

@@ -0,0 +1,17 @@
+# Find EpollShim
+# Once done, this will define
+#
+#   EPOLLSHIM_FOUND - System has EpollShim
+#   EPOLLSHIM_INCLUDE_DIRS - The EpollShim include directories
+#   EPOLLSHIM_LIBRARIES - The libraries needed to use EpollShim
+
+find_path(EPOLLSHIM_INCLUDE_DIRS NAMES sys/epoll.h sys/timerfd.h HINTS /usr/local/include/libepoll-shim)
+find_library(EPOLLSHIM_LIBRARIES NAMES epoll-shim libepoll-shim HINTS /usr/local/lib)
+
+if (EPOLLSHIM_INCLUDE_DIRS AND EPOLLSHIM_LIBRARIES)
+	set(EPOLLSHIM_FOUND TRUE)
+endif (EPOLLSHIM_INCLUDE_DIRS AND EPOLLSHIM_LIBRARIES)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(EpollShim DEFAULT_MSG EPOLLSHIM_LIBRARIES EPOLLSHIM_INCLUDE_DIRS)
+mark_as_advanced(EPOLLSHIM_INCLUDE_DIRS EPOLLSHIM_LIBRARIES)

+ 18 - 0
samples/third_party/glfw/CMake/modules/FindOSMesa.cmake

@@ -0,0 +1,18 @@
+# Try to find OSMesa on a Unix system
+#
+# This will define:
+#
+#   OSMESA_LIBRARIES   - Link these to use OSMesa
+#   OSMESA_INCLUDE_DIR - Include directory for OSMesa
+#
+# Copyright (c) 2014 Brandon Schaefer <brandon.schaefer@canonical.com>
+
+if (NOT WIN32)
+
+  find_package (PkgConfig)
+  pkg_check_modules (PKG_OSMESA QUIET osmesa)
+
+  set (OSMESA_INCLUDE_DIR ${PKG_OSMESA_INCLUDE_DIRS})
+  set (OSMESA_LIBRARIES   ${PKG_OSMESA_LIBRARIES})
+
+endif ()

+ 26 - 0
samples/third_party/glfw/CMake/modules/FindWaylandProtocols.cmake

@@ -0,0 +1,26 @@
+find_package(PkgConfig)
+
+pkg_check_modules(WaylandProtocols QUIET wayland-protocols>=${WaylandProtocols_FIND_VERSION})
+
+execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE} --variable=pkgdatadir wayland-protocols
+                OUTPUT_VARIABLE WaylandProtocols_PKGDATADIR
+                RESULT_VARIABLE _pkgconfig_failed)
+if (_pkgconfig_failed)
+    message(FATAL_ERROR "Missing wayland-protocols pkgdatadir")
+endif()
+
+string(REGEX REPLACE "[\r\n]" "" WaylandProtocols_PKGDATADIR "${WaylandProtocols_PKGDATADIR}")
+
+find_package_handle_standard_args(WaylandProtocols
+    FOUND_VAR
+        WaylandProtocols_FOUND
+    REQUIRED_VARS
+        WaylandProtocols_PKGDATADIR
+    VERSION_VAR
+        WaylandProtocols_VERSION
+    HANDLE_COMPONENTS
+)
+
+set(WAYLAND_PROTOCOLS_FOUND ${WaylandProtocols_FOUND})
+set(WAYLAND_PROTOCOLS_PKGDATADIR ${WaylandProtocols_PKGDATADIR})
+set(WAYLAND_PROTOCOLS_VERSION ${WaylandProtocols_VERSION})

+ 34 - 0
samples/third_party/glfw/CMake/modules/FindXKBCommon.cmake

@@ -0,0 +1,34 @@
+# - Try to find XKBCommon
+# Once done, this will define
+#
+#   XKBCOMMON_FOUND - System has XKBCommon
+#   XKBCOMMON_INCLUDE_DIRS - The XKBCommon include directories
+#   XKBCOMMON_LIBRARIES - The libraries needed to use XKBCommon
+#   XKBCOMMON_DEFINITIONS - Compiler switches required for using XKBCommon
+
+find_package(PkgConfig)
+pkg_check_modules(PC_XKBCOMMON QUIET xkbcommon)
+set(XKBCOMMON_DEFINITIONS ${PC_XKBCOMMON_CFLAGS_OTHER})
+
+find_path(XKBCOMMON_INCLUDE_DIR
+    NAMES xkbcommon/xkbcommon.h
+    HINTS ${PC_XKBCOMMON_INCLUDE_DIR} ${PC_XKBCOMMON_INCLUDE_DIRS}
+)
+
+find_library(XKBCOMMON_LIBRARY
+    NAMES xkbcommon
+    HINTS ${PC_XKBCOMMON_LIBRARY} ${PC_XKBCOMMON_LIBRARY_DIRS}
+)
+
+set(XKBCOMMON_LIBRARIES ${XKBCOMMON_LIBRARY})
+set(XKBCOMMON_LIBRARY_DIRS ${XKBCOMMON_LIBRARY_DIRS})
+set(XKBCOMMON_INCLUDE_DIRS ${XKBCOMMON_INCLUDE_DIR})
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(XKBCommon DEFAULT_MSG
+    XKBCOMMON_LIBRARY
+    XKBCOMMON_INCLUDE_DIR
+)
+
+mark_as_advanced(XKBCOMMON_LIBRARY XKBCOMMON_INCLUDE_DIR)
+

+ 13 - 0
samples/third_party/glfw/CMake/x86_64-w64-mingw32-clang.cmake

@@ -0,0 +1,13 @@
+# Define the environment for cross-compiling with 64-bit MinGW-w64 Clang
+SET(CMAKE_SYSTEM_NAME    Windows) # Target system name
+SET(CMAKE_SYSTEM_VERSION 1)
+SET(CMAKE_C_COMPILER     "x86_64-w64-mingw32-clang")
+SET(CMAKE_CXX_COMPILER   "x86_64-w64-mingw32-clang++")
+SET(CMAKE_RC_COMPILER    "x86_64-w64-mingw32-windres")
+SET(CMAKE_RANLIB         "x86_64-w64-mingw32-ranlib")
+
+# Configure the behaviour of the find commands
+SET(CMAKE_FIND_ROOT_PATH "/usr/x86_64-w64-mingw32")
+SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

+ 13 - 0
samples/third_party/glfw/CMake/x86_64-w64-mingw32.cmake

@@ -0,0 +1,13 @@
+# Define the environment for cross-compiling with 64-bit MinGW-w64 GCC
+SET(CMAKE_SYSTEM_NAME    Windows) # Target system name
+SET(CMAKE_SYSTEM_VERSION 1)
+SET(CMAKE_C_COMPILER     "x86_64-w64-mingw32-gcc")
+SET(CMAKE_CXX_COMPILER   "x86_64-w64-mingw32-g++")
+SET(CMAKE_RC_COMPILER    "x86_64-w64-mingw32-windres")
+SET(CMAKE_RANLIB         "x86_64-w64-mingw32-ranlib")
+
+# Configure the behaviour of the find commands
+SET(CMAKE_FIND_ROOT_PATH "/usr/x86_64-w64-mingw32")
+SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

+ 386 - 0
samples/third_party/glfw/CMakeLists.txt

@@ -0,0 +1,386 @@
+cmake_minimum_required(VERSION 3.0...3.20 FATAL_ERROR)
+
+project(GLFW VERSION 3.3.5 LANGUAGES C)
+
+set(CMAKE_LEGACY_CYGWIN_WIN32 OFF)
+
+if (POLICY CMP0054)
+    cmake_policy(SET CMP0054 NEW)
+endif()
+
+if (POLICY CMP0069)
+    cmake_policy(SET CMP0069 NEW)
+endif()
+
+if (POLICY CMP0077)
+    cmake_policy(SET CMP0077 NEW)
+endif()
+
+set_property(GLOBAL PROPERTY USE_FOLDERS ON)
+
+option(BUILD_SHARED_LIBS "Build shared libraries" OFF)
+option(GLFW_BUILD_EXAMPLES "Build the GLFW example programs" ON)
+option(GLFW_BUILD_TESTS "Build the GLFW test programs" ON)
+option(GLFW_BUILD_DOCS "Build the GLFW documentation" ON)
+option(GLFW_INSTALL "Generate installation target" ON)
+option(GLFW_VULKAN_STATIC "Assume the Vulkan loader is linked with the application" OFF)
+
+include(GNUInstallDirs)
+include(CMakeDependentOption)
+
+cmake_dependent_option(GLFW_USE_OSMESA "Use OSMesa for offscreen context creation" OFF
+                       "UNIX" OFF)
+cmake_dependent_option(GLFW_USE_HYBRID_HPG "Force use of high-performance GPU on hybrid systems" OFF
+                       "WIN32" OFF)
+cmake_dependent_option(GLFW_USE_WAYLAND "Use Wayland for window creation" OFF
+                       "UNIX;NOT APPLE" OFF)
+cmake_dependent_option(USE_MSVC_RUNTIME_LIBRARY_DLL "Use MSVC runtime library DLL" ON
+                       "MSVC" OFF)
+
+if (BUILD_SHARED_LIBS)
+    set(_GLFW_BUILD_DLL 1)
+endif()
+
+if (BUILD_SHARED_LIBS AND UNIX)
+    # On Unix-like systems, shared libraries can use the soname system.
+    set(GLFW_LIB_NAME glfw)
+else()
+    set(GLFW_LIB_NAME glfw3)
+endif()
+
+if (GLFW_VULKAN_STATIC)
+    if (BUILD_SHARED_LIBS)
+        # If you absolutely must do this, remove this line and add the Vulkan
+        # loader static library via the CMAKE_SHARED_LINKER_FLAGS
+        message(FATAL_ERROR "You are trying to link the Vulkan loader static library into the GLFW shared library")
+    endif()
+    set(_GLFW_VULKAN_STATIC 1)
+endif()
+
+list(APPEND CMAKE_MODULE_PATH "${GLFW_SOURCE_DIR}/CMake/modules")
+
+find_package(Threads REQUIRED)
+
+if (GLFW_BUILD_DOCS)
+    set(DOXYGEN_SKIP_DOT TRUE)
+    find_package(Doxygen)
+endif()
+
+#--------------------------------------------------------------------
+# Apply Microsoft C runtime library option
+# This is here because it also applies to tests and examples
+#--------------------------------------------------------------------
+if (MSVC)
+    if (MSVC90)
+        # Workaround for VS 2008 not shipping with the DirectX 9 SDK
+        include(CheckIncludeFile)
+        check_include_file(dinput.h DINPUT_H_FOUND)
+        if (NOT DINPUT_H_FOUND)
+            message(FATAL_ERROR "DirectX 9 headers not found; install DirectX 9 SDK")
+        endif()
+        # Workaround for VS 2008 not shipping with stdint.h
+        list(APPEND glfw_INCLUDE_DIRS "${GLFW_SOURCE_DIR}/deps/vs2008")
+    endif()
+endif()
+
+if (MSVC AND NOT USE_MSVC_RUNTIME_LIBRARY_DLL)
+    if (CMAKE_VERSION VERSION_LESS 3.15)
+        foreach (flag CMAKE_C_FLAGS
+                      CMAKE_C_FLAGS_DEBUG
+                      CMAKE_C_FLAGS_RELEASE
+                      CMAKE_C_FLAGS_MINSIZEREL
+                      CMAKE_C_FLAGS_RELWITHDEBINFO)
+
+            if (flag MATCHES "/MD")
+                string(REGEX REPLACE "/MD" "/MT" ${flag} "${${flag}}")
+            endif()
+            if (flag MATCHES "/MDd")
+                string(REGEX REPLACE "/MDd" "/MTd" ${flag} "${${flag}}")
+            endif()
+
+        endforeach()
+    else()
+        set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
+    endif()
+endif()
+
+if (MINGW)
+    # Workaround for legacy MinGW not providing XInput and DirectInput
+    include(CheckIncludeFile)
+
+    check_include_file(dinput.h DINPUT_H_FOUND)
+    check_include_file(xinput.h XINPUT_H_FOUND)
+    if (NOT DINPUT_H_FOUND OR NOT XINPUT_H_FOUND)
+        list(APPEND glfw_INCLUDE_DIRS "${GLFW_SOURCE_DIR}/deps/mingw")
+    endif()
+
+    # Enable link-time exploit mitigation features enabled by default on MSVC
+    include(CheckCCompilerFlag)
+
+    # Compatibility with data execution prevention (DEP)
+    set(CMAKE_REQUIRED_FLAGS "-Wl,--nxcompat")
+    check_c_compiler_flag("" _GLFW_HAS_DEP)
+    if (_GLFW_HAS_DEP)
+        set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--nxcompat ${CMAKE_SHARED_LINKER_FLAGS}")
+    endif()
+
+    # Compatibility with address space layout randomization (ASLR)
+    set(CMAKE_REQUIRED_FLAGS "-Wl,--dynamicbase")
+    check_c_compiler_flag("" _GLFW_HAS_ASLR)
+    if (_GLFW_HAS_ASLR)
+        set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--dynamicbase ${CMAKE_SHARED_LINKER_FLAGS}")
+    endif()
+
+    # Compatibility with 64-bit address space layout randomization (ASLR)
+    set(CMAKE_REQUIRED_FLAGS "-Wl,--high-entropy-va")
+    check_c_compiler_flag("" _GLFW_HAS_64ASLR)
+    if (_GLFW_HAS_64ASLR)
+        set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--high-entropy-va ${CMAKE_SHARED_LINKER_FLAGS}")
+    endif()
+
+    # Clear flags again to avoid breaking later tests
+    set(CMAKE_REQUIRED_FLAGS)
+endif()
+
+#--------------------------------------------------------------------
+# Detect and select backend APIs
+#--------------------------------------------------------------------
+if (GLFW_USE_WAYLAND)
+    set(_GLFW_WAYLAND 1)
+    message(STATUS "Using Wayland for window creation")
+elseif (GLFW_USE_OSMESA)
+    set(_GLFW_OSMESA 1)
+    message(STATUS "Using OSMesa for headless context creation")
+elseif (WIN32)
+    set(_GLFW_WIN32 1)
+    message(STATUS "Using Win32 for window creation")
+elseif (APPLE)
+    set(_GLFW_COCOA 1)
+    message(STATUS "Using Cocoa for window creation")
+elseif (UNIX)
+    set(_GLFW_X11 1)
+    message(STATUS "Using X11 for window creation")
+else()
+    message(FATAL_ERROR "No supported platform was detected")
+endif()
+
+#--------------------------------------------------------------------
+# Find and add Unix math and time libraries
+#--------------------------------------------------------------------
+if (UNIX AND NOT APPLE)
+    find_library(RT_LIBRARY rt)
+    mark_as_advanced(RT_LIBRARY)
+    if (RT_LIBRARY)
+        list(APPEND glfw_LIBRARIES "${RT_LIBRARY}")
+        list(APPEND glfw_PKG_LIBS "-lrt")
+    endif()
+
+    find_library(MATH_LIBRARY m)
+    mark_as_advanced(MATH_LIBRARY)
+    if (MATH_LIBRARY)
+        list(APPEND glfw_LIBRARIES "${MATH_LIBRARY}")
+        list(APPEND glfw_PKG_LIBS "-lm")
+    endif()
+
+    if (CMAKE_DL_LIBS)
+        list(APPEND glfw_LIBRARIES "${CMAKE_DL_LIBS}")
+        list(APPEND glfw_PKG_LIBS "-l${CMAKE_DL_LIBS}")
+    endif()
+endif()
+
+#--------------------------------------------------------------------
+# Use Win32 for window creation
+#--------------------------------------------------------------------
+if (_GLFW_WIN32)
+
+    list(APPEND glfw_PKG_LIBS "-lgdi32")
+
+    if (GLFW_USE_HYBRID_HPG)
+        set(_GLFW_USE_HYBRID_HPG 1)
+    endif()
+endif()
+
+#--------------------------------------------------------------------
+# Use X11 for window creation
+#--------------------------------------------------------------------
+if (_GLFW_X11)
+
+    find_package(X11 REQUIRED)
+
+    list(APPEND glfw_PKG_DEPS "x11")
+
+    # Set up library and include paths
+    list(APPEND glfw_INCLUDE_DIRS "${X11_X11_INCLUDE_PATH}")
+    list(APPEND glfw_LIBRARIES "${X11_X11_LIB}" "${CMAKE_THREAD_LIBS_INIT}")
+
+    # Check for XRandR (modern resolution switching and gamma control)
+    if (NOT X11_Xrandr_INCLUDE_PATH)
+        message(FATAL_ERROR "RandR headers not found; install libxrandr development package")
+    endif()
+
+    # Check for Xinerama (legacy multi-monitor support)
+    if (NOT X11_Xinerama_INCLUDE_PATH)
+        message(FATAL_ERROR "Xinerama headers not found; install libxinerama development package")
+    endif()
+
+    # Check for Xkb (X keyboard extension)
+    if (NOT X11_Xkb_INCLUDE_PATH)
+        message(FATAL_ERROR "XKB headers not found; install X11 development package")
+    endif()
+
+    # Check for Xcursor (cursor creation from RGBA images)
+    if (NOT X11_Xcursor_INCLUDE_PATH)
+        message(FATAL_ERROR "Xcursor headers not found; install libxcursor development package")
+    endif()
+
+    # Check for XInput (modern HID input)
+    if (NOT X11_Xi_INCLUDE_PATH)
+        message(FATAL_ERROR "XInput headers not found; install libxi development package")
+    endif()
+
+    list(APPEND glfw_INCLUDE_DIRS "${X11_Xrandr_INCLUDE_PATH}"
+                                  "${X11_Xinerama_INCLUDE_PATH}"
+                                  "${X11_Xkb_INCLUDE_PATH}"
+                                  "${X11_Xcursor_INCLUDE_PATH}"
+                                  "${X11_Xi_INCLUDE_PATH}")
+endif()
+
+#--------------------------------------------------------------------
+# Use Wayland for window creation
+#--------------------------------------------------------------------
+if (_GLFW_WAYLAND)
+    find_package(ECM REQUIRED NO_MODULE)
+    list(APPEND CMAKE_MODULE_PATH "${ECM_MODULE_PATH}")
+
+    find_package(Wayland REQUIRED Client Cursor Egl)
+    find_package(WaylandScanner REQUIRED)
+    find_package(WaylandProtocols 1.15 REQUIRED)
+
+    list(APPEND glfw_PKG_DEPS "wayland-client")
+
+    list(APPEND glfw_INCLUDE_DIRS "${Wayland_INCLUDE_DIRS}")
+    list(APPEND glfw_LIBRARIES "${Wayland_LIBRARIES}" "${CMAKE_THREAD_LIBS_INIT}")
+
+    find_package(XKBCommon REQUIRED)
+    list(APPEND glfw_INCLUDE_DIRS "${XKBCOMMON_INCLUDE_DIRS}")
+
+    include(CheckIncludeFiles)
+    include(CheckFunctionExists)
+    check_include_files(xkbcommon/xkbcommon-compose.h HAVE_XKBCOMMON_COMPOSE_H)
+    check_function_exists(memfd_create HAVE_MEMFD_CREATE)
+
+    if (NOT CMAKE_SYSTEM_NAME STREQUAL "Linux")
+        find_package(EpollShim)
+        if (EPOLLSHIM_FOUND)
+            list(APPEND glfw_INCLUDE_DIRS "${EPOLLSHIM_INCLUDE_DIRS}")
+            list(APPEND glfw_LIBRARIES "${EPOLLSHIM_LIBRARIES}")
+        endif()
+    endif()
+endif()
+
+#--------------------------------------------------------------------
+# Use OSMesa for offscreen context creation
+#--------------------------------------------------------------------
+if (_GLFW_OSMESA)
+    find_package(OSMesa REQUIRED)
+    list(APPEND glfw_LIBRARIES "${CMAKE_THREAD_LIBS_INIT}")
+endif()
+
+#--------------------------------------------------------------------
+# Use Cocoa for window creation and NSOpenGL for context creation
+#--------------------------------------------------------------------
+if (_GLFW_COCOA)
+
+    list(APPEND glfw_LIBRARIES
+        "-framework Cocoa"
+        "-framework IOKit"
+        "-framework CoreFoundation")
+
+    set(glfw_PKG_DEPS "")
+    set(glfw_PKG_LIBS "-framework Cocoa -framework IOKit -framework CoreFoundation")
+endif()
+
+#--------------------------------------------------------------------
+# Add the Vulkan loader as a dependency if necessary
+#--------------------------------------------------------------------
+if (GLFW_VULKAN_STATIC)
+    list(APPEND glfw_PKG_DEPS "vulkan")
+endif()
+
+#--------------------------------------------------------------------
+# Export GLFW library dependencies
+#--------------------------------------------------------------------
+foreach(arg ${glfw_PKG_DEPS})
+    set(GLFW_PKG_DEPS "${GLFW_PKG_DEPS} ${arg}")
+endforeach()
+foreach(arg ${glfw_PKG_LIBS})
+    set(GLFW_PKG_LIBS "${GLFW_PKG_LIBS} ${arg}")
+endforeach()
+
+#--------------------------------------------------------------------
+# Create generated files
+#--------------------------------------------------------------------
+include(CMakePackageConfigHelpers)
+
+set(GLFW_CONFIG_PATH "${CMAKE_INSTALL_LIBDIR}/cmake/glfw3")
+
+configure_package_config_file(src/glfw3Config.cmake.in
+                              src/glfw3Config.cmake
+                              INSTALL_DESTINATION "${GLFW_CONFIG_PATH}"
+                              NO_CHECK_REQUIRED_COMPONENTS_MACRO)
+
+write_basic_package_version_file(src/glfw3ConfigVersion.cmake
+                                 VERSION ${GLFW_VERSION}
+                                 COMPATIBILITY SameMajorVersion)
+
+configure_file(src/glfw_config.h.in src/glfw_config.h @ONLY)
+
+configure_file(src/glfw3.pc.in src/glfw3.pc @ONLY)
+
+#--------------------------------------------------------------------
+# Add subdirectories
+#--------------------------------------------------------------------
+add_subdirectory(src)
+
+if (GLFW_BUILD_EXAMPLES)
+    add_subdirectory(examples)
+endif()
+
+if (GLFW_BUILD_TESTS)
+    add_subdirectory(tests)
+endif()
+
+if (DOXYGEN_FOUND AND GLFW_BUILD_DOCS)
+    add_subdirectory(docs)
+endif()
+
+#--------------------------------------------------------------------
+# Install files other than the library
+# The library is installed by src/CMakeLists.txt
+#--------------------------------------------------------------------
+if (GLFW_INSTALL)
+    install(DIRECTORY include/GLFW DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
+            FILES_MATCHING PATTERN glfw3.h PATTERN glfw3native.h)
+
+    install(FILES "${GLFW_BINARY_DIR}/src/glfw3Config.cmake"
+                  "${GLFW_BINARY_DIR}/src/glfw3ConfigVersion.cmake"
+            DESTINATION "${GLFW_CONFIG_PATH}")
+
+    install(EXPORT glfwTargets FILE glfw3Targets.cmake
+            EXPORT_LINK_INTERFACE_LIBRARIES
+            DESTINATION "${GLFW_CONFIG_PATH}")
+    install(FILES "${GLFW_BINARY_DIR}/src/glfw3.pc"
+            DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
+
+    # Only generate this target if no higher-level project already has
+    if (NOT TARGET uninstall)
+        configure_file(cmake_uninstall.cmake.in
+                       cmake_uninstall.cmake IMMEDIATE @ONLY)
+
+        add_custom_target(uninstall
+                          "${CMAKE_COMMAND}" -P
+                          "${GLFW_BINARY_DIR}/cmake_uninstall.cmake")
+        set_target_properties(uninstall PROPERTIES FOLDER "GLFW3")
+    endif()
+endif()
+

+ 220 - 0
samples/third_party/glfw/CONTRIBUTORS.md

@@ -0,0 +1,220 @@
+# Acknowledgements
+
+GLFW exists because people around the world donated their time and lent their
+skills.  This list only includes contributions to the main repository and
+excludes other invaluable contributions like language bindings and text and
+video tutorials.
+
+ - Bobyshev Alexander
+ - Laurent Aphecetche
+ - Matt Arsenault
+ - ashishgamedev
+ - David Avedissian
+ - Keith Bauer
+ - John Bartholomew
+ - Coşku Baş
+ - Niklas Behrens
+ - Andrew Belt
+ - Nevyn Bengtsson
+ - Niklas Bergström
+ - Denis Bernard
+ - Doug Binks
+ - blanco
+ - Waris Boonyasiriwat
+ - Kyle Brenneman
+ - Rok Breulj
+ - Kai Burjack
+ - Martin Capitanio
+ - Nicolas Caramelli
+ - David Carlier
+ - Arturo Castro
+ - Chi-kwan Chan
+ - Joseph Chua
+ - Ian Clarkson
+ - Michał Cichoń
+ - Lambert Clara
+ - Anna Clarke
+ - Josh Codd
+ - Yaron Cohen-Tal
+ - Omar Cornut
+ - Andrew Corrigan
+ - Bailey Cosier
+ - Noel Cower
+ - CuriouserThing
+ - Jason Daly
+ - Jarrod Davis
+ - Olivier Delannoy
+ - Paul R. Deppe
+ - Michael Dickens
+ - Роман Донченко
+ - Mario Dorn
+ - Wolfgang Draxinger
+ - Jonathan Dummer
+ - Ralph Eastwood
+ - Fredrik Ehnbom
+ - Robin Eklind
+ - Siavash Eliasi
+ - TheExileFox
+ - Felipe Ferreira
+ - Michael Fogleman
+ - Gerald Franz
+ - Mário Freitas
+ - GeO4d
+ - Marcus Geelnard
+ - Charles Giessen
+ - Ryan C. Gordon
+ - Stephen Gowen
+ - Kovid Goyal
+ - Eloi Marín Gratacós
+ - Stefan Gustavson
+ - Jonathan Hale
+ - hdf89shfdfs
+ - Sylvain Hellegouarch
+ - Matthew Henry
+ - heromyth
+ - Lucas Hinderberger
+ - Paul Holden
+ - Warren Hu
+ - Charles Huber
+ - IntellectualKitty
+ - Aaron Jacobs
+ - Erik S. V. Jansson
+ - Toni Jovanoski
+ - Arseny Kapoulkine
+ - Cem Karan
+ - Osman Keskin
+ - Koray Kilinc
+ - Josh Kilmer
+ - Byunghoon Kim
+ - Cameron King
+ - Peter Knut
+ - Christoph Kubisch
+ - Yuri Kunde Schlesner
+ - Rokas Kupstys
+ - Konstantin Käfer
+ - Eric Larson
+ - Francis Lecavalier
+ - Jong Won Lee
+ - Robin Leffmann
+ - Glenn Lewis
+ - Shane Liesegang
+ - Anders Lindqvist
+ - Leon Linhart
+ - Marco Lizza
+ - Eyal Lotem
+ - Aaron Loucks
+ - Luflosi
+ - lukect
+ - Tristam MacDonald
+ - Hans Mackowiak
+ - Дмитри Малышев
+ - Zbigniew Mandziejewicz
+ - Adam Marcus
+ - Célestin Marot
+ - Kyle McDonald
+ - David V. McKay
+ - David Medlock
+ - Bryce Mehring
+ - Jonathan Mercier
+ - Marcel Metz
+ - Liam Middlebrook
+ - Ave Milia
+ - Jonathan Miller
+ - Kenneth Miller
+ - Bruce Mitchener
+ - Jack Moffitt
+ - Jeff Molofee
+ - Alexander Monakov
+ - Pierre Morel
+ - Jon Morton
+ - Pierre Moulon
+ - Martins Mozeiko
+ - Julian Møller
+ - ndogxj
+ - Kristian Nielsen
+ - Kamil Nowakowski
+ - onox
+ - Denis Ovod
+ - Ozzy
+ - Andri Pálsson
+ - Peoro
+ - Braden Pellett
+ - Christopher Pelloux
+ - Arturo J. Pérez
+ - Vladimir Perminov
+ - Anthony Pesch
+ - Orson Peters
+ - Emmanuel Gil Peyrot
+ - Cyril Pichard
+ - Keith Pitt
+ - Stanislav Podgorskiy
+ - Konstantin Podsvirov
+ - Nathan Poirier
+ - Alexandre Pretyman
+ - Pablo Prietz
+ - przemekmirek
+ - pthom
+ - Guillaume Racicot
+ - Philip Rideout
+ - Eddie Ringle
+ - Max Risuhin
+ - Jorge Rodriguez
+ - Luca Rood
+ - Ed Ropple
+ - Aleksey Rybalkin
+ - Mikko Rytkönen
+ - Riku Salminen
+ - Brandon Schaefer
+ - Sebastian Schuberth
+ - Christian Sdunek
+ - Matt Sealey
+ - Steve Sexton
+ - Arkady Shapkin
+ - Ali Sherief
+ - Yoshiki Shibukawa
+ - Dmitri Shuralyov
+ - Daniel Skorupski
+ - Bradley Smith
+ - Cliff Smolinsky
+ - Patrick Snape
+ - Erlend Sogge Heggen
+ - Julian Squires
+ - Johannes Stein
+ - Pontus Stenetorp
+ - Michael Stocker
+ - Justin Stoecker
+ - Elviss Strazdins
+ - Paul Sultana
+ - Nathan Sweet
+ - TTK-Bandit
+ - Sergey Tikhomirov
+ - Arthur Tombs
+ - Ioannis Tsakpinis
+ - Samuli Tuomola
+ - Matthew Turner
+ - urraka
+ - Elias Vanderstuyft
+ - Stef Velzel
+ - Jari Vetoniemi
+ - Ricardo Vieira
+ - Nicholas Vitovitch
+ - Simon Voordouw
+ - Corentin Wallez
+ - Torsten Walluhn
+ - Patrick Walton
+ - Xo Wang
+ - Jay Weisskopf
+ - Frank Wille
+ - Richard A. Wilkes
+ - Tatsuya Yatagawa
+ - Ryogo Yoshimura
+ - Lukas Zanner
+ - Andrey Zholos
+ - Aihui Zhu
+ - Santi Zupancic
+ - Jonas Ådahl
+ - Lasse Öörni
+ - Leonard König
+ - All the unmentioned and anonymous contributors in the GLFW community, for bug
+   reports, patches, feedback, testing and encouragement
+

+ 23 - 0
samples/third_party/glfw/LICENSE.md

@@ -0,0 +1,23 @@
+Copyright (c) 2002-2006 Marcus Geelnard
+
+Copyright (c) 2006-2019 Camilla Löwy
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+   claim that you wrote the original software. If you use this software
+   in a product, an acknowledgment in the product documentation would
+   be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and must not
+   be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+   distribution.
+

+ 163 - 0
samples/third_party/glfw/README.md

@@ -0,0 +1,163 @@
+# GLFW
+
+[![Build status](https://github.com/glfw/glfw/actions/workflows/build.yml/badge.svg)](https://github.com/glfw/glfw/actions)
+[![Build status](https://ci.appveyor.com/api/projects/status/0kf0ct9831i5l6sp/branch/master?svg=true)](https://ci.appveyor.com/project/elmindreda/glfw)
+[![Coverity Scan](https://scan.coverity.com/projects/4884/badge.svg)](https://scan.coverity.com/projects/glfw-glfw)
+
+## Introduction
+
+GLFW is an Open Source, multi-platform library for OpenGL, OpenGL ES and Vulkan
+application development.  It provides a simple, platform-independent API for
+creating windows, contexts and surfaces, reading input, handling events, etc.
+
+GLFW natively supports Windows, macOS and Linux and other Unix-like systems.  On
+Linux both X11 and Wayland are supported.
+
+GLFW is licensed under the [zlib/libpng
+license](https://www.glfw.org/license.html).
+
+You can [download](https://www.glfw.org/download.html) the latest stable release
+as source or Windows binaries, or fetch the `latest` branch from GitHub.  Each
+release starting with 3.0 also has a corresponding [annotated
+tag](https://github.com/glfw/glfw/releases) with source and binary archives.
+
+The [documentation](https://www.glfw.org/docs/latest/) is available online and is
+included in all source and binary archives.  See the [release
+notes](https://www.glfw.org/docs/latest/news.html) for new features, caveats and
+deprecations in the latest release.  For more details see the [version
+history](https://www.glfw.org/changelog.html).
+
+The `master` branch is the stable integration branch and _should_ always compile
+and run on all supported platforms, although details of newly added features may
+change until they have been included in a release.  New features and many bug
+fixes live in [other branches](https://github.com/glfw/glfw/branches/all) until
+they are stable enough to merge.
+
+If you are new to GLFW, you may find the
+[tutorial](https://www.glfw.org/docs/latest/quick.html) for GLFW 3 useful.  If
+you have used GLFW 2 in the past, there is a [transition
+guide](https://www.glfw.org/docs/latest/moving.html) for moving to the GLFW
+3 API.
+
+GLFW exists because of the contributions of [many people](CONTRIBUTORS.md)
+around the world, whether by reporting bugs, providing community support, adding
+features, reviewing or testing code, debugging, proofreading docs, suggesting
+features or fixing bugs.
+
+
+## Compiling GLFW
+
+GLFW itself requires only the headers and libraries for your OS and window
+system.  It does not need the headers for any context creation API (WGL, GLX,
+EGL, NSGL, OSMesa) or rendering API (OpenGL, OpenGL ES, Vulkan) to enable
+support for them.
+
+GLFW supports compilation on Windows with Visual C++ 2010 and later, MinGW and
+MinGW-w64, on macOS with Clang and on Linux and other Unix-like systems with GCC
+and Clang.  It will likely compile in other environments as well, but this is
+not regularly tested.
+
+There are [pre-compiled Windows binaries](https://www.glfw.org/download.html)
+available for all supported compilers.
+
+See the [compilation guide](https://www.glfw.org/docs/latest/compile.html) for
+more information about how to compile GLFW yourself.
+
+
+## Using GLFW
+
+See the [documentation](https://www.glfw.org/docs/latest/) for tutorials, guides
+and the API reference.
+
+
+## Contributing to GLFW
+
+See the [contribution
+guide](https://github.com/glfw/glfw/blob/master/docs/CONTRIBUTING.md) for
+more information.
+
+
+## System requirements
+
+GLFW supports Windows XP and later and macOS 10.8 and later.  Linux and other
+Unix-like systems running the X Window System are supported even without
+a desktop environment or modern extensions, although some features require
+a running window or clipboard manager.  The OSMesa backend requires Mesa 6.3.
+
+See the [compatibility guide](https://www.glfw.org/docs/latest/compat.html)
+in the documentation for more information.
+
+
+## Dependencies
+
+GLFW itself depends only on the headers and libraries for your window system.
+
+The (experimental) Wayland backend also depends on the `extra-cmake-modules`
+package, which is used to generate Wayland protocol headers.
+
+The examples and test programs depend on a number of tiny libraries.  These are
+located in the `deps/` directory.
+
+ - [getopt\_port](https://github.com/kimgr/getopt_port/) for examples
+   with command-line options
+ - [TinyCThread](https://github.com/tinycthread/tinycthread) for threaded
+   examples
+ - [glad2](https://github.com/Dav1dde/glad) for loading OpenGL and Vulkan
+   functions
+ - [linmath.h](https://github.com/datenwolf/linmath.h) for linear algebra in
+   examples
+ - [Nuklear](https://github.com/Immediate-Mode-UI/Nuklear) for test and example UI
+ - [stb\_image\_write](https://github.com/nothings/stb) for writing images to disk
+
+The documentation is generated with [Doxygen](https://doxygen.org/) if CMake can
+find that tool.
+
+
+## Reporting bugs
+
+Bugs are reported to our [issue tracker](https://github.com/glfw/glfw/issues).
+Please check the [contribution
+guide](https://github.com/glfw/glfw/blob/master/docs/CONTRIBUTING.md) for
+information on what to include when reporting a bug.
+
+
+## Changelog
+
+ - Updated gamepad mappings from upstream
+ - Bugfix: Buffers were swapped at creation on single-buffered windows (#1873)
+ - Bugfix: Gamepad mapping updates could spam `GLFW_INVALID_VALUE` due to
+   incompatible controllers sharing hardware ID (#1763)
+ - Bugfix: Native access functions for context handles did not check that the API matched
+ - [Win32] Bugfix: `USE_MSVC_RUNTIME_LIBRARY_DLL` had no effect on CMake 3.15 or
+   later (#1783,#1796)
+ - [Win32] Bugfix: Compilation with LLVM for Windows failed (#1807,#1824,#1874)
+ - [Cocoa] Bugfix: The MoltenVK layer contents scale was updated only after
+   related events were emitted
+ - [Cocoa] Bugfix: Moving the cursor programmatically would freeze it for
+   a fraction of a second (#1962)
+ - [Cocoa] Bugfix: `kIOMasterPortDefault` was deprecated in macOS 12.0 (#1980)
+ - [X11] Bugfix: Changing `GLFW_FLOATING` could leak memory
+ - [Wayland] Bugfix: Some keys were not repeating in Wayland (#1908)
+ - [Wayland] Bugfix: Non-arrow cursors are offset from the hotspot (#1706,#1899)
+ - [Wayland] Bugfix: The `O_CLOEXEC` flag was not defined on FreeBSD
+ - [NSGL] Bugfix: Defining `GL_SILENCE_DEPRECATION` externally caused
+   a duplicate definition warning (#1840)
+ - [EGL] Bugfix: The `GLFW_DOUBLEBUFFER` context attribute was ignored (#1843)
+
+
+## Contact
+
+On [glfw.org](https://www.glfw.org/) you can find the latest version of GLFW, as
+well as news, documentation and other information about the project.
+
+If you have questions related to the use of GLFW, we have a
+[forum](https://discourse.glfw.org/), and the `#glfw` IRC channel on
+[Libera.Chat](https://libera.chat/).
+
+If you have a bug to report, a patch to submit or a feature you'd like to
+request, please file it in the
+[issue tracker](https://github.com/glfw/glfw/issues) on GitHub.
+
+Finally, if you're interested in helping out with the development of GLFW or
+porting it to your favorite platform, join us on the forum, GitHub or IRC.
+

+ 29 - 0
samples/third_party/glfw/cmake_uninstall.cmake.in

@@ -0,0 +1,29 @@
+
+if (NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
+  message(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"")
+endif()
+
+file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
+string(REGEX REPLACE "\n" ";" files "${files}")
+
+foreach (file ${files})
+  message(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"")
+  if (EXISTS "$ENV{DESTDIR}${file}")
+    exec_program("@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
+                 OUTPUT_VARIABLE rm_out
+                 RETURN_VALUE rm_retval)
+    if (NOT "${rm_retval}" STREQUAL 0)
+      MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"")
+    endif()
+  elseif (IS_SYMLINK "$ENV{DESTDIR}${file}")
+    EXEC_PROGRAM("@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
+                 OUTPUT_VARIABLE rm_out
+                 RETURN_VALUE rm_retval)
+    if (NOT "${rm_retval}" STREQUAL 0)
+      message(FATAL_ERROR "Problem when removing symlink \"$ENV{DESTDIR}${file}\"")
+    endif()
+  else()
+    message(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.")
+  endif()
+endforeach()
+

+ 230 - 0
samples/third_party/glfw/deps/getopt.c

@@ -0,0 +1,230 @@
+/* Copyright (c) 2012, Kim Gräsman
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * 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.
+ *  * Neither the name of Kim Gräsman nor the names of contributors may be used
+ *    to endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * 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 KIM GRÄSMAN 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 "getopt.h"
+
+#include <stddef.h>
+#include <string.h>
+
+const int no_argument = 0;
+const int required_argument = 1;
+const int optional_argument = 2;
+
+char* optarg;
+int optopt;
+/* The variable optind [...] shall be initialized to 1 by the system. */
+int optind = 1;
+int opterr;
+
+static char* optcursor = NULL;
+
+/* Implemented based on [1] and [2] for optional arguments.
+   optopt is handled FreeBSD-style, per [3].
+   Other GNU and FreeBSD extensions are purely accidental.
+
+[1] http://pubs.opengroup.org/onlinepubs/000095399/functions/getopt.html
+[2] http://www.kernel.org/doc/man-pages/online/pages/man3/getopt.3.html
+[3] http://www.freebsd.org/cgi/man.cgi?query=getopt&sektion=3&manpath=FreeBSD+9.0-RELEASE
+*/
+int getopt(int argc, char* const argv[], const char* optstring) {
+  int optchar = -1;
+  const char* optdecl = NULL;
+
+  optarg = NULL;
+  opterr = 0;
+  optopt = 0;
+
+  /* Unspecified, but we need it to avoid overrunning the argv bounds. */
+  if (optind >= argc)
+    goto no_more_optchars;
+
+  /* If, when getopt() is called argv[optind] is a null pointer, getopt()
+     shall return -1 without changing optind. */
+  if (argv[optind] == NULL)
+    goto no_more_optchars;
+
+  /* If, when getopt() is called *argv[optind]  is not the character '-',
+     getopt() shall return -1 without changing optind. */
+  if (*argv[optind] != '-')
+    goto no_more_optchars;
+
+  /* If, when getopt() is called argv[optind] points to the string "-",
+     getopt() shall return -1 without changing optind. */
+  if (strcmp(argv[optind], "-") == 0)
+    goto no_more_optchars;
+
+  /* If, when getopt() is called argv[optind] points to the string "--",
+     getopt() shall return -1 after incrementing optind. */
+  if (strcmp(argv[optind], "--") == 0) {
+    ++optind;
+    goto no_more_optchars;
+  }
+
+  if (optcursor == NULL || *optcursor == '\0')
+    optcursor = argv[optind] + 1;
+
+  optchar = *optcursor;
+
+  /* FreeBSD: The variable optopt saves the last known option character
+     returned by getopt(). */
+  optopt = optchar;
+
+  /* The getopt() function shall return the next option character (if one is
+     found) from argv that matches a character in optstring, if there is
+     one that matches. */
+  optdecl = strchr(optstring, optchar);
+  if (optdecl) {
+    /* [I]f a character is followed by a colon, the option takes an
+       argument. */
+    if (optdecl[1] == ':') {
+      optarg = ++optcursor;
+      if (*optarg == '\0') {
+        /* GNU extension: Two colons mean an option takes an
+           optional arg; if there is text in the current argv-element
+           (i.e., in the same word as the option name itself, for example,
+           "-oarg"), then it is returned in optarg, otherwise optarg is set
+           to zero. */
+        if (optdecl[2] != ':') {
+          /* If the option was the last character in the string pointed to by
+             an element of argv, then optarg shall contain the next element
+             of argv, and optind shall be incremented by 2. If the resulting
+             value of optind is greater than argc, this indicates a missing
+             option-argument, and getopt() shall return an error indication.
+
+             Otherwise, optarg shall point to the string following the
+             option character in that element of argv, and optind shall be
+             incremented by 1.
+          */
+          if (++optind < argc) {
+            optarg = argv[optind];
+          } else {
+            /* If it detects a missing option-argument, it shall return the
+               colon character ( ':' ) if the first character of optstring
+               was a colon, or a question-mark character ( '?' ) otherwise.
+            */
+            optarg = NULL;
+            optchar = (optstring[0] == ':') ? ':' : '?';
+          }
+        } else {
+          optarg = NULL;
+        }
+      }
+
+      optcursor = NULL;
+    }
+  } else {
+    /* If getopt() encounters an option character that is not contained in
+       optstring, it shall return the question-mark ( '?' ) character. */
+    optchar = '?';
+  }
+
+  if (optcursor == NULL || *++optcursor == '\0')
+    ++optind;
+
+  return optchar;
+
+no_more_optchars:
+  optcursor = NULL;
+  return -1;
+}
+
+/* Implementation based on [1].
+
+[1] http://www.kernel.org/doc/man-pages/online/pages/man3/getopt.3.html
+*/
+int getopt_long(int argc, char* const argv[], const char* optstring,
+  const struct option* longopts, int* longindex) {
+  const struct option* o = longopts;
+  const struct option* match = NULL;
+  int num_matches = 0;
+  size_t argument_name_length = 0;
+  const char* current_argument = NULL;
+  int retval = -1;
+
+  optarg = NULL;
+  optopt = 0;
+
+  if (optind >= argc)
+    return -1;
+
+  if (strlen(argv[optind]) < 3 || strncmp(argv[optind], "--", 2) != 0)
+    return getopt(argc, argv, optstring);
+
+  /* It's an option; starts with -- and is longer than two chars. */
+  current_argument = argv[optind] + 2;
+  argument_name_length = strcspn(current_argument, "=");
+  for (; o->name; ++o) {
+    if (strncmp(o->name, current_argument, argument_name_length) == 0) {
+      match = o;
+      ++num_matches;
+    }
+  }
+
+  if (num_matches == 1) {
+    /* If longindex is not NULL, it points to a variable which is set to the
+       index of the long option relative to longopts. */
+    if (longindex)
+      *longindex = (int) (match - longopts);
+
+    /* If flag is NULL, then getopt_long() shall return val.
+       Otherwise, getopt_long() returns 0, and flag shall point to a variable
+       which shall be set to val if the option is found, but left unchanged if
+       the option is not found. */
+    if (match->flag)
+      *(match->flag) = match->val;
+
+    retval = match->flag ? 0 : match->val;
+
+    if (match->has_arg != no_argument) {
+      optarg = strchr(argv[optind], '=');
+      if (optarg != NULL)
+        ++optarg;
+
+      if (match->has_arg == required_argument) {
+        /* Only scan the next argv for required arguments. Behavior is not
+           specified, but has been observed with Ubuntu and Mac OSX. */
+        if (optarg == NULL && ++optind < argc) {
+          optarg = argv[optind];
+        }
+
+        if (optarg == NULL)
+          retval = ':';
+      }
+    } else if (strchr(argv[optind], '=')) {
+      /* An argument was provided to a non-argument option.
+         I haven't seen this specified explicitly, but both GNU and BSD-based
+         implementations show this behavior.
+      */
+      retval = '?';
+    }
+  } else {
+    /* Unknown option or ambiguous match. */
+    retval = '?';
+  }
+
+  ++optind;
+  return retval;
+}

+ 57 - 0
samples/third_party/glfw/deps/getopt.h

@@ -0,0 +1,57 @@
+/* Copyright (c) 2012, Kim Gräsman
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * 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.
+ *  * Neither the name of Kim Gräsman nor the names of contributors may be used
+ *    to endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * 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 KIM GRÄSMAN 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 INCLUDED_GETOPT_PORT_H
+#define INCLUDED_GETOPT_PORT_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+extern const int no_argument;
+extern const int required_argument;
+extern const int optional_argument;
+
+extern char* optarg;
+extern int optind, opterr, optopt;
+
+struct option {
+  const char* name;
+  int has_arg;
+  int* flag;
+  int val;
+};
+
+int getopt(int argc, char* const argv[], const char* optstring);
+
+int getopt_long(int argc, char* const argv[],
+  const char* optstring, const struct option* longopts, int* longindex);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif // INCLUDED_GETOPT_PORT_H

ファイルの差分が大きいため隠しています
+ 3840 - 0
samples/third_party/glfw/deps/glad/gl.h


+ 282 - 0
samples/third_party/glfw/deps/glad/khrplatform.h

@@ -0,0 +1,282 @@
+#ifndef __khrplatform_h_
+#define __khrplatform_h_
+
+/*
+** Copyright (c) 2008-2018 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.
+**
+** 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.
+*/
+
+/* Khronos platform-specific types and definitions.
+ *
+ * The master copy of khrplatform.h is maintained in the Khronos EGL
+ * Registry repository at https://github.com/KhronosGroup/EGL-Registry
+ * The last semantic modification to khrplatform.h was at commit ID:
+ *      67a3e0864c2d75ea5287b9f3d2eb74a745936692
+ *
+ * Adopters may modify this file to suit their platform. Adopters are
+ * encouraged to submit platform specific modifications to the Khronos
+ * group so that they can be included in future versions of this file.
+ * Please submit changes by filing pull requests or issues on
+ * the EGL Registry repository linked above.
+ *
+ *
+ * See the Implementer's Guidelines for information about where this file
+ * should be located on your system and for more details of its use:
+ *    http://www.khronos.org/registry/implementers_guide.pdf
+ *
+ * This file should be included as
+ *        #include <KHR/khrplatform.h>
+ * by Khronos client API header files that use its types and defines.
+ *
+ * The types in khrplatform.h should only be used to define API-specific types.
+ *
+ * Types defined in khrplatform.h:
+ *    khronos_int8_t              signed   8  bit
+ *    khronos_uint8_t             unsigned 8  bit
+ *    khronos_int16_t             signed   16 bit
+ *    khronos_uint16_t            unsigned 16 bit
+ *    khronos_int32_t             signed   32 bit
+ *    khronos_uint32_t            unsigned 32 bit
+ *    khronos_int64_t             signed   64 bit
+ *    khronos_uint64_t            unsigned 64 bit
+ *    khronos_intptr_t            signed   same number of bits as a pointer
+ *    khronos_uintptr_t           unsigned same number of bits as a pointer
+ *    khronos_ssize_t             signed   size
+ *    khronos_usize_t             unsigned size
+ *    khronos_float_t             signed   32 bit floating point
+ *    khronos_time_ns_t           unsigned 64 bit time in nanoseconds
+ *    khronos_utime_nanoseconds_t unsigned time interval or absolute time in
+ *                                         nanoseconds
+ *    khronos_stime_nanoseconds_t signed time interval in nanoseconds
+ *    khronos_boolean_enum_t      enumerated boolean type. This should
+ *      only be used as a base type when a client API's boolean type is
+ *      an enum. Client APIs which use an integer or other type for
+ *      booleans cannot use this as the base type for their boolean.
+ *
+ * Tokens defined in khrplatform.h:
+ *
+ *    KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values.
+ *
+ *    KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0.
+ *    KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0.
+ *
+ * Calling convention macros defined in this file:
+ *    KHRONOS_APICALL
+ *    KHRONOS_APIENTRY
+ *    KHRONOS_APIATTRIBUTES
+ *
+ * These may be used in function prototypes as:
+ *
+ *      KHRONOS_APICALL void KHRONOS_APIENTRY funcname(
+ *                                  int arg1,
+ *                                  int arg2) KHRONOS_APIATTRIBUTES;
+ */
+
+/*-------------------------------------------------------------------------
+ * Definition of KHRONOS_APICALL
+ *-------------------------------------------------------------------------
+ * This precedes the return type of the function in the function prototype.
+ */
+#if defined(_WIN32) && !defined(__SCITECH_SNAP__)
+#   define KHRONOS_APICALL __declspec(dllimport)
+#elif defined (__SYMBIAN32__)
+#   define KHRONOS_APICALL IMPORT_C
+#elif defined(__ANDROID__)
+#   define KHRONOS_APICALL __attribute__((visibility("default")))
+#else
+#   define KHRONOS_APICALL
+#endif
+
+/*-------------------------------------------------------------------------
+ * Definition of KHRONOS_APIENTRY
+ *-------------------------------------------------------------------------
+ * This follows the return type of the function  and precedes the function
+ * name in the function prototype.
+ */
+#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__)
+    /* Win32 but not WinCE */
+#   define KHRONOS_APIENTRY __stdcall
+#else
+#   define KHRONOS_APIENTRY
+#endif
+
+/*-------------------------------------------------------------------------
+ * Definition of KHRONOS_APIATTRIBUTES
+ *-------------------------------------------------------------------------
+ * This follows the closing parenthesis of the function prototype arguments.
+ */
+#if defined (__ARMCC_2__)
+#define KHRONOS_APIATTRIBUTES __softfp
+#else
+#define KHRONOS_APIATTRIBUTES
+#endif
+
+/*-------------------------------------------------------------------------
+ * basic type definitions
+ *-----------------------------------------------------------------------*/
+#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__)
+
+
+/*
+ * Using <stdint.h>
+ */
+#include <stdint.h>
+typedef int32_t                 khronos_int32_t;
+typedef uint32_t                khronos_uint32_t;
+typedef int64_t                 khronos_int64_t;
+typedef uint64_t                khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64   1
+#define KHRONOS_SUPPORT_FLOAT   1
+
+#elif defined(__VMS ) || defined(__sgi)
+
+/*
+ * Using <inttypes.h>
+ */
+#include <inttypes.h>
+typedef int32_t                 khronos_int32_t;
+typedef uint32_t                khronos_uint32_t;
+typedef int64_t                 khronos_int64_t;
+typedef uint64_t                khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64   1
+#define KHRONOS_SUPPORT_FLOAT   1
+
+#elif defined(_WIN32) && !defined(__SCITECH_SNAP__)
+
+/*
+ * Win32
+ */
+typedef __int32                 khronos_int32_t;
+typedef unsigned __int32        khronos_uint32_t;
+typedef __int64                 khronos_int64_t;
+typedef unsigned __int64        khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64   1
+#define KHRONOS_SUPPORT_FLOAT   1
+
+#elif defined(__sun__) || defined(__digital__)
+
+/*
+ * Sun or Digital
+ */
+typedef int                     khronos_int32_t;
+typedef unsigned int            khronos_uint32_t;
+#if defined(__arch64__) || defined(_LP64)
+typedef long int                khronos_int64_t;
+typedef unsigned long int       khronos_uint64_t;
+#else
+typedef long long int           khronos_int64_t;
+typedef unsigned long long int  khronos_uint64_t;
+#endif /* __arch64__ */
+#define KHRONOS_SUPPORT_INT64   1
+#define KHRONOS_SUPPORT_FLOAT   1
+
+#elif 0
+
+/*
+ * Hypothetical platform with no float or int64 support
+ */
+typedef int                     khronos_int32_t;
+typedef unsigned int            khronos_uint32_t;
+#define KHRONOS_SUPPORT_INT64   0
+#define KHRONOS_SUPPORT_FLOAT   0
+
+#else
+
+/*
+ * Generic fallback
+ */
+#include <stdint.h>
+typedef int32_t                 khronos_int32_t;
+typedef uint32_t                khronos_uint32_t;
+typedef int64_t                 khronos_int64_t;
+typedef uint64_t                khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64   1
+#define KHRONOS_SUPPORT_FLOAT   1
+
+#endif
+
+
+/*
+ * Types that are (so far) the same on all platforms
+ */
+typedef signed   char          khronos_int8_t;
+typedef unsigned char          khronos_uint8_t;
+typedef signed   short int     khronos_int16_t;
+typedef unsigned short int     khronos_uint16_t;
+
+/*
+ * Types that differ between LLP64 and LP64 architectures - in LLP64,
+ * pointers are 64 bits, but 'long' is still 32 bits. Win64 appears
+ * to be the only LLP64 architecture in current use.
+ */
+#ifdef _WIN64
+typedef signed   long long int khronos_intptr_t;
+typedef unsigned long long int khronos_uintptr_t;
+typedef signed   long long int khronos_ssize_t;
+typedef unsigned long long int khronos_usize_t;
+#else
+typedef signed   long  int     khronos_intptr_t;
+typedef unsigned long  int     khronos_uintptr_t;
+typedef signed   long  int     khronos_ssize_t;
+typedef unsigned long  int     khronos_usize_t;
+#endif
+
+#if KHRONOS_SUPPORT_FLOAT
+/*
+ * Float type
+ */
+typedef          float         khronos_float_t;
+#endif
+
+#if KHRONOS_SUPPORT_INT64
+/* Time types
+ *
+ * These types can be used to represent a time interval in nanoseconds or
+ * an absolute Unadjusted System Time.  Unadjusted System Time is the number
+ * of nanoseconds since some arbitrary system event (e.g. since the last
+ * time the system booted).  The Unadjusted System Time is an unsigned
+ * 64 bit value that wraps back to 0 every 584 years.  Time intervals
+ * may be either signed or unsigned.
+ */
+typedef khronos_uint64_t       khronos_utime_nanoseconds_t;
+typedef khronos_int64_t        khronos_stime_nanoseconds_t;
+#endif
+
+/*
+ * Dummy value used to pad enum types to 32 bits.
+ */
+#ifndef KHRONOS_MAX_ENUM
+#define KHRONOS_MAX_ENUM 0x7FFFFFFF
+#endif
+
+/*
+ * Enumerated boolean type
+ *
+ * Values other than zero should be considered to be true.  Therefore
+ * comparisons should not be made against KHRONOS_TRUE.
+ */
+typedef enum {
+    KHRONOS_FALSE = 0,
+    KHRONOS_TRUE  = 1,
+    KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
+} khronos_boolean_enum_t;
+
+#endif /* __khrplatform_h_ */

+ 92 - 0
samples/third_party/glfw/deps/glad/vk_platform.h

@@ -0,0 +1,92 @@
+/* */
+/* File: vk_platform.h */
+/* */
+/*
+** Copyright (c) 2014-2017 The Khronos Group Inc.
+**
+** 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.
+*/
+
+
+#ifndef VK_PLATFORM_H_
+#define VK_PLATFORM_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+/*
+***************************************************************************************************
+*   Platform-specific directives and type declarations
+***************************************************************************************************
+*/
+
+/* Platform-specific calling convention macros.
+ *
+ * Platforms should define these so that Vulkan clients call Vulkan commands
+ * with the same calling conventions that the Vulkan implementation expects.
+ *
+ * VKAPI_ATTR - Placed before the return type in function declarations.
+ *              Useful for C++11 and GCC/Clang-style function attribute syntax.
+ * VKAPI_CALL - Placed after the return type in function declarations.
+ *              Useful for MSVC-style calling convention syntax.
+ * VKAPI_PTR  - Placed between the '(' and '*' in function pointer types.
+ *
+ * Function declaration:  VKAPI_ATTR void VKAPI_CALL vkCommand(void);
+ * Function pointer type: typedef void (VKAPI_PTR *PFN_vkCommand)(void);
+ */
+#if defined(_WIN32)
+    /* On Windows, Vulkan commands use the stdcall convention */
+    #define VKAPI_ATTR
+    #define VKAPI_CALL __stdcall
+    #define VKAPI_PTR  VKAPI_CALL
+#elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH < 7
+    #error "Vulkan isn't supported for the 'armeabi' NDK ABI"
+#elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH >= 7 && defined(__ARM_32BIT_STATE)
+    /* On Android 32-bit ARM targets, Vulkan functions use the "hardfloat" */
+    /* calling convention, i.e. float parameters are passed in registers. This */
+    /* is true even if the rest of the application passes floats on the stack, */
+    /* as it does by default when compiling for the armeabi-v7a NDK ABI. */
+    #define VKAPI_ATTR __attribute__((pcs("aapcs-vfp")))
+    #define VKAPI_CALL
+    #define VKAPI_PTR  VKAPI_ATTR
+#else
+    /* On other platforms, use the default calling convention */
+    #define VKAPI_ATTR
+    #define VKAPI_CALL
+    #define VKAPI_PTR
+#endif
+
+#include <stddef.h>
+
+#if !defined(VK_NO_STDINT_H)
+    #if defined(_MSC_VER) && (_MSC_VER < 1600)
+        typedef signed   __int8  int8_t;
+        typedef unsigned __int8  uint8_t;
+        typedef signed   __int16 int16_t;
+        typedef unsigned __int16 uint16_t;
+        typedef signed   __int32 int32_t;
+        typedef unsigned __int32 uint32_t;
+        typedef signed   __int64 int64_t;
+        typedef unsigned __int64 uint64_t;
+    #else
+        #include <stdint.h>
+    #endif
+#endif /* !defined(VK_NO_STDINT_H) */
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+#endif

ファイルの差分が大きいため隠しています
+ 3480 - 0
samples/third_party/glfw/deps/glad/vulkan.h


ファイルの差分が大きいため隠しています
+ 1791 - 0
samples/third_party/glfw/deps/glad_gl.c


+ 593 - 0
samples/third_party/glfw/deps/glad_vulkan.c

@@ -0,0 +1,593 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <glad/vulkan.h>
+
+#ifndef GLAD_IMPL_UTIL_C_
+#define GLAD_IMPL_UTIL_C_
+
+#ifdef _MSC_VER
+#define GLAD_IMPL_UTIL_SSCANF sscanf_s
+#else
+#define GLAD_IMPL_UTIL_SSCANF sscanf
+#endif
+
+#endif /* GLAD_IMPL_UTIL_C_ */
+
+
+int GLAD_VK_VERSION_1_0 = 0;
+int GLAD_VK_VERSION_1_1 = 0;
+int GLAD_VK_EXT_debug_report = 0;
+int GLAD_VK_KHR_surface = 0;
+int GLAD_VK_KHR_swapchain = 0;
+
+
+
+PFN_vkAcquireNextImage2KHR glad_vkAcquireNextImage2KHR = NULL;
+PFN_vkAcquireNextImageKHR glad_vkAcquireNextImageKHR = NULL;
+PFN_vkAllocateCommandBuffers glad_vkAllocateCommandBuffers = NULL;
+PFN_vkAllocateDescriptorSets glad_vkAllocateDescriptorSets = NULL;
+PFN_vkAllocateMemory glad_vkAllocateMemory = NULL;
+PFN_vkBeginCommandBuffer glad_vkBeginCommandBuffer = NULL;
+PFN_vkBindBufferMemory glad_vkBindBufferMemory = NULL;
+PFN_vkBindBufferMemory2 glad_vkBindBufferMemory2 = NULL;
+PFN_vkBindImageMemory glad_vkBindImageMemory = NULL;
+PFN_vkBindImageMemory2 glad_vkBindImageMemory2 = NULL;
+PFN_vkCmdBeginQuery glad_vkCmdBeginQuery = NULL;
+PFN_vkCmdBeginRenderPass glad_vkCmdBeginRenderPass = NULL;
+PFN_vkCmdBindDescriptorSets glad_vkCmdBindDescriptorSets = NULL;
+PFN_vkCmdBindIndexBuffer glad_vkCmdBindIndexBuffer = NULL;
+PFN_vkCmdBindPipeline glad_vkCmdBindPipeline = NULL;
+PFN_vkCmdBindVertexBuffers glad_vkCmdBindVertexBuffers = NULL;
+PFN_vkCmdBlitImage glad_vkCmdBlitImage = NULL;
+PFN_vkCmdClearAttachments glad_vkCmdClearAttachments = NULL;
+PFN_vkCmdClearColorImage glad_vkCmdClearColorImage = NULL;
+PFN_vkCmdClearDepthStencilImage glad_vkCmdClearDepthStencilImage = NULL;
+PFN_vkCmdCopyBuffer glad_vkCmdCopyBuffer = NULL;
+PFN_vkCmdCopyBufferToImage glad_vkCmdCopyBufferToImage = NULL;
+PFN_vkCmdCopyImage glad_vkCmdCopyImage = NULL;
+PFN_vkCmdCopyImageToBuffer glad_vkCmdCopyImageToBuffer = NULL;
+PFN_vkCmdCopyQueryPoolResults glad_vkCmdCopyQueryPoolResults = NULL;
+PFN_vkCmdDispatch glad_vkCmdDispatch = NULL;
+PFN_vkCmdDispatchBase glad_vkCmdDispatchBase = NULL;
+PFN_vkCmdDispatchIndirect glad_vkCmdDispatchIndirect = NULL;
+PFN_vkCmdDraw glad_vkCmdDraw = NULL;
+PFN_vkCmdDrawIndexed glad_vkCmdDrawIndexed = NULL;
+PFN_vkCmdDrawIndexedIndirect glad_vkCmdDrawIndexedIndirect = NULL;
+PFN_vkCmdDrawIndirect glad_vkCmdDrawIndirect = NULL;
+PFN_vkCmdEndQuery glad_vkCmdEndQuery = NULL;
+PFN_vkCmdEndRenderPass glad_vkCmdEndRenderPass = NULL;
+PFN_vkCmdExecuteCommands glad_vkCmdExecuteCommands = NULL;
+PFN_vkCmdFillBuffer glad_vkCmdFillBuffer = NULL;
+PFN_vkCmdNextSubpass glad_vkCmdNextSubpass = NULL;
+PFN_vkCmdPipelineBarrier glad_vkCmdPipelineBarrier = NULL;
+PFN_vkCmdPushConstants glad_vkCmdPushConstants = NULL;
+PFN_vkCmdResetEvent glad_vkCmdResetEvent = NULL;
+PFN_vkCmdResetQueryPool glad_vkCmdResetQueryPool = NULL;
+PFN_vkCmdResolveImage glad_vkCmdResolveImage = NULL;
+PFN_vkCmdSetBlendConstants glad_vkCmdSetBlendConstants = NULL;
+PFN_vkCmdSetDepthBias glad_vkCmdSetDepthBias = NULL;
+PFN_vkCmdSetDepthBounds glad_vkCmdSetDepthBounds = NULL;
+PFN_vkCmdSetDeviceMask glad_vkCmdSetDeviceMask = NULL;
+PFN_vkCmdSetEvent glad_vkCmdSetEvent = NULL;
+PFN_vkCmdSetLineWidth glad_vkCmdSetLineWidth = NULL;
+PFN_vkCmdSetScissor glad_vkCmdSetScissor = NULL;
+PFN_vkCmdSetStencilCompareMask glad_vkCmdSetStencilCompareMask = NULL;
+PFN_vkCmdSetStencilReference glad_vkCmdSetStencilReference = NULL;
+PFN_vkCmdSetStencilWriteMask glad_vkCmdSetStencilWriteMask = NULL;
+PFN_vkCmdSetViewport glad_vkCmdSetViewport = NULL;
+PFN_vkCmdUpdateBuffer glad_vkCmdUpdateBuffer = NULL;
+PFN_vkCmdWaitEvents glad_vkCmdWaitEvents = NULL;
+PFN_vkCmdWriteTimestamp glad_vkCmdWriteTimestamp = NULL;
+PFN_vkCreateBuffer glad_vkCreateBuffer = NULL;
+PFN_vkCreateBufferView glad_vkCreateBufferView = NULL;
+PFN_vkCreateCommandPool glad_vkCreateCommandPool = NULL;
+PFN_vkCreateComputePipelines glad_vkCreateComputePipelines = NULL;
+PFN_vkCreateDebugReportCallbackEXT glad_vkCreateDebugReportCallbackEXT = NULL;
+PFN_vkCreateDescriptorPool glad_vkCreateDescriptorPool = NULL;
+PFN_vkCreateDescriptorSetLayout glad_vkCreateDescriptorSetLayout = NULL;
+PFN_vkCreateDescriptorUpdateTemplate glad_vkCreateDescriptorUpdateTemplate = NULL;
+PFN_vkCreateDevice glad_vkCreateDevice = NULL;
+PFN_vkCreateEvent glad_vkCreateEvent = NULL;
+PFN_vkCreateFence glad_vkCreateFence = NULL;
+PFN_vkCreateFramebuffer glad_vkCreateFramebuffer = NULL;
+PFN_vkCreateGraphicsPipelines glad_vkCreateGraphicsPipelines = NULL;
+PFN_vkCreateImage glad_vkCreateImage = NULL;
+PFN_vkCreateImageView glad_vkCreateImageView = NULL;
+PFN_vkCreateInstance glad_vkCreateInstance = NULL;
+PFN_vkCreatePipelineCache glad_vkCreatePipelineCache = NULL;
+PFN_vkCreatePipelineLayout glad_vkCreatePipelineLayout = NULL;
+PFN_vkCreateQueryPool glad_vkCreateQueryPool = NULL;
+PFN_vkCreateRenderPass glad_vkCreateRenderPass = NULL;
+PFN_vkCreateSampler glad_vkCreateSampler = NULL;
+PFN_vkCreateSamplerYcbcrConversion glad_vkCreateSamplerYcbcrConversion = NULL;
+PFN_vkCreateSemaphore glad_vkCreateSemaphore = NULL;
+PFN_vkCreateShaderModule glad_vkCreateShaderModule = NULL;
+PFN_vkCreateSwapchainKHR glad_vkCreateSwapchainKHR = NULL;
+PFN_vkDebugReportMessageEXT glad_vkDebugReportMessageEXT = NULL;
+PFN_vkDestroyBuffer glad_vkDestroyBuffer = NULL;
+PFN_vkDestroyBufferView glad_vkDestroyBufferView = NULL;
+PFN_vkDestroyCommandPool glad_vkDestroyCommandPool = NULL;
+PFN_vkDestroyDebugReportCallbackEXT glad_vkDestroyDebugReportCallbackEXT = NULL;
+PFN_vkDestroyDescriptorPool glad_vkDestroyDescriptorPool = NULL;
+PFN_vkDestroyDescriptorSetLayout glad_vkDestroyDescriptorSetLayout = NULL;
+PFN_vkDestroyDescriptorUpdateTemplate glad_vkDestroyDescriptorUpdateTemplate = NULL;
+PFN_vkDestroyDevice glad_vkDestroyDevice = NULL;
+PFN_vkDestroyEvent glad_vkDestroyEvent = NULL;
+PFN_vkDestroyFence glad_vkDestroyFence = NULL;
+PFN_vkDestroyFramebuffer glad_vkDestroyFramebuffer = NULL;
+PFN_vkDestroyImage glad_vkDestroyImage = NULL;
+PFN_vkDestroyImageView glad_vkDestroyImageView = NULL;
+PFN_vkDestroyInstance glad_vkDestroyInstance = NULL;
+PFN_vkDestroyPipeline glad_vkDestroyPipeline = NULL;
+PFN_vkDestroyPipelineCache glad_vkDestroyPipelineCache = NULL;
+PFN_vkDestroyPipelineLayout glad_vkDestroyPipelineLayout = NULL;
+PFN_vkDestroyQueryPool glad_vkDestroyQueryPool = NULL;
+PFN_vkDestroyRenderPass glad_vkDestroyRenderPass = NULL;
+PFN_vkDestroySampler glad_vkDestroySampler = NULL;
+PFN_vkDestroySamplerYcbcrConversion glad_vkDestroySamplerYcbcrConversion = NULL;
+PFN_vkDestroySemaphore glad_vkDestroySemaphore = NULL;
+PFN_vkDestroyShaderModule glad_vkDestroyShaderModule = NULL;
+PFN_vkDestroySurfaceKHR glad_vkDestroySurfaceKHR = NULL;
+PFN_vkDestroySwapchainKHR glad_vkDestroySwapchainKHR = NULL;
+PFN_vkDeviceWaitIdle glad_vkDeviceWaitIdle = NULL;
+PFN_vkEndCommandBuffer glad_vkEndCommandBuffer = NULL;
+PFN_vkEnumerateDeviceExtensionProperties glad_vkEnumerateDeviceExtensionProperties = NULL;
+PFN_vkEnumerateDeviceLayerProperties glad_vkEnumerateDeviceLayerProperties = NULL;
+PFN_vkEnumerateInstanceExtensionProperties glad_vkEnumerateInstanceExtensionProperties = NULL;
+PFN_vkEnumerateInstanceLayerProperties glad_vkEnumerateInstanceLayerProperties = NULL;
+PFN_vkEnumerateInstanceVersion glad_vkEnumerateInstanceVersion = NULL;
+PFN_vkEnumeratePhysicalDeviceGroups glad_vkEnumeratePhysicalDeviceGroups = NULL;
+PFN_vkEnumeratePhysicalDevices glad_vkEnumeratePhysicalDevices = NULL;
+PFN_vkFlushMappedMemoryRanges glad_vkFlushMappedMemoryRanges = NULL;
+PFN_vkFreeCommandBuffers glad_vkFreeCommandBuffers = NULL;
+PFN_vkFreeDescriptorSets glad_vkFreeDescriptorSets = NULL;
+PFN_vkFreeMemory glad_vkFreeMemory = NULL;
+PFN_vkGetBufferMemoryRequirements glad_vkGetBufferMemoryRequirements = NULL;
+PFN_vkGetBufferMemoryRequirements2 glad_vkGetBufferMemoryRequirements2 = NULL;
+PFN_vkGetDescriptorSetLayoutSupport glad_vkGetDescriptorSetLayoutSupport = NULL;
+PFN_vkGetDeviceGroupPeerMemoryFeatures glad_vkGetDeviceGroupPeerMemoryFeatures = NULL;
+PFN_vkGetDeviceGroupPresentCapabilitiesKHR glad_vkGetDeviceGroupPresentCapabilitiesKHR = NULL;
+PFN_vkGetDeviceGroupSurfacePresentModesKHR glad_vkGetDeviceGroupSurfacePresentModesKHR = NULL;
+PFN_vkGetDeviceMemoryCommitment glad_vkGetDeviceMemoryCommitment = NULL;
+PFN_vkGetDeviceProcAddr glad_vkGetDeviceProcAddr = NULL;
+PFN_vkGetDeviceQueue glad_vkGetDeviceQueue = NULL;
+PFN_vkGetDeviceQueue2 glad_vkGetDeviceQueue2 = NULL;
+PFN_vkGetEventStatus glad_vkGetEventStatus = NULL;
+PFN_vkGetFenceStatus glad_vkGetFenceStatus = NULL;
+PFN_vkGetImageMemoryRequirements glad_vkGetImageMemoryRequirements = NULL;
+PFN_vkGetImageMemoryRequirements2 glad_vkGetImageMemoryRequirements2 = NULL;
+PFN_vkGetImageSparseMemoryRequirements glad_vkGetImageSparseMemoryRequirements = NULL;
+PFN_vkGetImageSparseMemoryRequirements2 glad_vkGetImageSparseMemoryRequirements2 = NULL;
+PFN_vkGetImageSubresourceLayout glad_vkGetImageSubresourceLayout = NULL;
+PFN_vkGetInstanceProcAddr glad_vkGetInstanceProcAddr = NULL;
+PFN_vkGetPhysicalDeviceExternalBufferProperties glad_vkGetPhysicalDeviceExternalBufferProperties = NULL;
+PFN_vkGetPhysicalDeviceExternalFenceProperties glad_vkGetPhysicalDeviceExternalFenceProperties = NULL;
+PFN_vkGetPhysicalDeviceExternalSemaphoreProperties glad_vkGetPhysicalDeviceExternalSemaphoreProperties = NULL;
+PFN_vkGetPhysicalDeviceFeatures glad_vkGetPhysicalDeviceFeatures = NULL;
+PFN_vkGetPhysicalDeviceFeatures2 glad_vkGetPhysicalDeviceFeatures2 = NULL;
+PFN_vkGetPhysicalDeviceFormatProperties glad_vkGetPhysicalDeviceFormatProperties = NULL;
+PFN_vkGetPhysicalDeviceFormatProperties2 glad_vkGetPhysicalDeviceFormatProperties2 = NULL;
+PFN_vkGetPhysicalDeviceImageFormatProperties glad_vkGetPhysicalDeviceImageFormatProperties = NULL;
+PFN_vkGetPhysicalDeviceImageFormatProperties2 glad_vkGetPhysicalDeviceImageFormatProperties2 = NULL;
+PFN_vkGetPhysicalDeviceMemoryProperties glad_vkGetPhysicalDeviceMemoryProperties = NULL;
+PFN_vkGetPhysicalDeviceMemoryProperties2 glad_vkGetPhysicalDeviceMemoryProperties2 = NULL;
+PFN_vkGetPhysicalDevicePresentRectanglesKHR glad_vkGetPhysicalDevicePresentRectanglesKHR = NULL;
+PFN_vkGetPhysicalDeviceProperties glad_vkGetPhysicalDeviceProperties = NULL;
+PFN_vkGetPhysicalDeviceProperties2 glad_vkGetPhysicalDeviceProperties2 = NULL;
+PFN_vkGetPhysicalDeviceQueueFamilyProperties glad_vkGetPhysicalDeviceQueueFamilyProperties = NULL;
+PFN_vkGetPhysicalDeviceQueueFamilyProperties2 glad_vkGetPhysicalDeviceQueueFamilyProperties2 = NULL;
+PFN_vkGetPhysicalDeviceSparseImageFormatProperties glad_vkGetPhysicalDeviceSparseImageFormatProperties = NULL;
+PFN_vkGetPhysicalDeviceSparseImageFormatProperties2 glad_vkGetPhysicalDeviceSparseImageFormatProperties2 = NULL;
+PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR glad_vkGetPhysicalDeviceSurfaceCapabilitiesKHR = NULL;
+PFN_vkGetPhysicalDeviceSurfaceFormatsKHR glad_vkGetPhysicalDeviceSurfaceFormatsKHR = NULL;
+PFN_vkGetPhysicalDeviceSurfacePresentModesKHR glad_vkGetPhysicalDeviceSurfacePresentModesKHR = NULL;
+PFN_vkGetPhysicalDeviceSurfaceSupportKHR glad_vkGetPhysicalDeviceSurfaceSupportKHR = NULL;
+PFN_vkGetPipelineCacheData glad_vkGetPipelineCacheData = NULL;
+PFN_vkGetQueryPoolResults glad_vkGetQueryPoolResults = NULL;
+PFN_vkGetRenderAreaGranularity glad_vkGetRenderAreaGranularity = NULL;
+PFN_vkGetSwapchainImagesKHR glad_vkGetSwapchainImagesKHR = NULL;
+PFN_vkInvalidateMappedMemoryRanges glad_vkInvalidateMappedMemoryRanges = NULL;
+PFN_vkMapMemory glad_vkMapMemory = NULL;
+PFN_vkMergePipelineCaches glad_vkMergePipelineCaches = NULL;
+PFN_vkQueueBindSparse glad_vkQueueBindSparse = NULL;
+PFN_vkQueuePresentKHR glad_vkQueuePresentKHR = NULL;
+PFN_vkQueueSubmit glad_vkQueueSubmit = NULL;
+PFN_vkQueueWaitIdle glad_vkQueueWaitIdle = NULL;
+PFN_vkResetCommandBuffer glad_vkResetCommandBuffer = NULL;
+PFN_vkResetCommandPool glad_vkResetCommandPool = NULL;
+PFN_vkResetDescriptorPool glad_vkResetDescriptorPool = NULL;
+PFN_vkResetEvent glad_vkResetEvent = NULL;
+PFN_vkResetFences glad_vkResetFences = NULL;
+PFN_vkSetEvent glad_vkSetEvent = NULL;
+PFN_vkTrimCommandPool glad_vkTrimCommandPool = NULL;
+PFN_vkUnmapMemory glad_vkUnmapMemory = NULL;
+PFN_vkUpdateDescriptorSetWithTemplate glad_vkUpdateDescriptorSetWithTemplate = NULL;
+PFN_vkUpdateDescriptorSets glad_vkUpdateDescriptorSets = NULL;
+PFN_vkWaitForFences glad_vkWaitForFences = NULL;
+
+
+static void glad_vk_load_VK_VERSION_1_0( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_VK_VERSION_1_0) return;
+    vkAllocateCommandBuffers = (PFN_vkAllocateCommandBuffers) load("vkAllocateCommandBuffers", userptr);
+    vkAllocateDescriptorSets = (PFN_vkAllocateDescriptorSets) load("vkAllocateDescriptorSets", userptr);
+    vkAllocateMemory = (PFN_vkAllocateMemory) load("vkAllocateMemory", userptr);
+    vkBeginCommandBuffer = (PFN_vkBeginCommandBuffer) load("vkBeginCommandBuffer", userptr);
+    vkBindBufferMemory = (PFN_vkBindBufferMemory) load("vkBindBufferMemory", userptr);
+    vkBindImageMemory = (PFN_vkBindImageMemory) load("vkBindImageMemory", userptr);
+    vkCmdBeginQuery = (PFN_vkCmdBeginQuery) load("vkCmdBeginQuery", userptr);
+    vkCmdBeginRenderPass = (PFN_vkCmdBeginRenderPass) load("vkCmdBeginRenderPass", userptr);
+    vkCmdBindDescriptorSets = (PFN_vkCmdBindDescriptorSets) load("vkCmdBindDescriptorSets", userptr);
+    vkCmdBindIndexBuffer = (PFN_vkCmdBindIndexBuffer) load("vkCmdBindIndexBuffer", userptr);
+    vkCmdBindPipeline = (PFN_vkCmdBindPipeline) load("vkCmdBindPipeline", userptr);
+    vkCmdBindVertexBuffers = (PFN_vkCmdBindVertexBuffers) load("vkCmdBindVertexBuffers", userptr);
+    vkCmdBlitImage = (PFN_vkCmdBlitImage) load("vkCmdBlitImage", userptr);
+    vkCmdClearAttachments = (PFN_vkCmdClearAttachments) load("vkCmdClearAttachments", userptr);
+    vkCmdClearColorImage = (PFN_vkCmdClearColorImage) load("vkCmdClearColorImage", userptr);
+    vkCmdClearDepthStencilImage = (PFN_vkCmdClearDepthStencilImage) load("vkCmdClearDepthStencilImage", userptr);
+    vkCmdCopyBuffer = (PFN_vkCmdCopyBuffer) load("vkCmdCopyBuffer", userptr);
+    vkCmdCopyBufferToImage = (PFN_vkCmdCopyBufferToImage) load("vkCmdCopyBufferToImage", userptr);
+    vkCmdCopyImage = (PFN_vkCmdCopyImage) load("vkCmdCopyImage", userptr);
+    vkCmdCopyImageToBuffer = (PFN_vkCmdCopyImageToBuffer) load("vkCmdCopyImageToBuffer", userptr);
+    vkCmdCopyQueryPoolResults = (PFN_vkCmdCopyQueryPoolResults) load("vkCmdCopyQueryPoolResults", userptr);
+    vkCmdDispatch = (PFN_vkCmdDispatch) load("vkCmdDispatch", userptr);
+    vkCmdDispatchIndirect = (PFN_vkCmdDispatchIndirect) load("vkCmdDispatchIndirect", userptr);
+    vkCmdDraw = (PFN_vkCmdDraw) load("vkCmdDraw", userptr);
+    vkCmdDrawIndexed = (PFN_vkCmdDrawIndexed) load("vkCmdDrawIndexed", userptr);
+    vkCmdDrawIndexedIndirect = (PFN_vkCmdDrawIndexedIndirect) load("vkCmdDrawIndexedIndirect", userptr);
+    vkCmdDrawIndirect = (PFN_vkCmdDrawIndirect) load("vkCmdDrawIndirect", userptr);
+    vkCmdEndQuery = (PFN_vkCmdEndQuery) load("vkCmdEndQuery", userptr);
+    vkCmdEndRenderPass = (PFN_vkCmdEndRenderPass) load("vkCmdEndRenderPass", userptr);
+    vkCmdExecuteCommands = (PFN_vkCmdExecuteCommands) load("vkCmdExecuteCommands", userptr);
+    vkCmdFillBuffer = (PFN_vkCmdFillBuffer) load("vkCmdFillBuffer", userptr);
+    vkCmdNextSubpass = (PFN_vkCmdNextSubpass) load("vkCmdNextSubpass", userptr);
+    vkCmdPipelineBarrier = (PFN_vkCmdPipelineBarrier) load("vkCmdPipelineBarrier", userptr);
+    vkCmdPushConstants = (PFN_vkCmdPushConstants) load("vkCmdPushConstants", userptr);
+    vkCmdResetEvent = (PFN_vkCmdResetEvent) load("vkCmdResetEvent", userptr);
+    vkCmdResetQueryPool = (PFN_vkCmdResetQueryPool) load("vkCmdResetQueryPool", userptr);
+    vkCmdResolveImage = (PFN_vkCmdResolveImage) load("vkCmdResolveImage", userptr);
+    vkCmdSetBlendConstants = (PFN_vkCmdSetBlendConstants) load("vkCmdSetBlendConstants", userptr);
+    vkCmdSetDepthBias = (PFN_vkCmdSetDepthBias) load("vkCmdSetDepthBias", userptr);
+    vkCmdSetDepthBounds = (PFN_vkCmdSetDepthBounds) load("vkCmdSetDepthBounds", userptr);
+    vkCmdSetEvent = (PFN_vkCmdSetEvent) load("vkCmdSetEvent", userptr);
+    vkCmdSetLineWidth = (PFN_vkCmdSetLineWidth) load("vkCmdSetLineWidth", userptr);
+    vkCmdSetScissor = (PFN_vkCmdSetScissor) load("vkCmdSetScissor", userptr);
+    vkCmdSetStencilCompareMask = (PFN_vkCmdSetStencilCompareMask) load("vkCmdSetStencilCompareMask", userptr);
+    vkCmdSetStencilReference = (PFN_vkCmdSetStencilReference) load("vkCmdSetStencilReference", userptr);
+    vkCmdSetStencilWriteMask = (PFN_vkCmdSetStencilWriteMask) load("vkCmdSetStencilWriteMask", userptr);
+    vkCmdSetViewport = (PFN_vkCmdSetViewport) load("vkCmdSetViewport", userptr);
+    vkCmdUpdateBuffer = (PFN_vkCmdUpdateBuffer) load("vkCmdUpdateBuffer", userptr);
+    vkCmdWaitEvents = (PFN_vkCmdWaitEvents) load("vkCmdWaitEvents", userptr);
+    vkCmdWriteTimestamp = (PFN_vkCmdWriteTimestamp) load("vkCmdWriteTimestamp", userptr);
+    vkCreateBuffer = (PFN_vkCreateBuffer) load("vkCreateBuffer", userptr);
+    vkCreateBufferView = (PFN_vkCreateBufferView) load("vkCreateBufferView", userptr);
+    vkCreateCommandPool = (PFN_vkCreateCommandPool) load("vkCreateCommandPool", userptr);
+    vkCreateComputePipelines = (PFN_vkCreateComputePipelines) load("vkCreateComputePipelines", userptr);
+    vkCreateDescriptorPool = (PFN_vkCreateDescriptorPool) load("vkCreateDescriptorPool", userptr);
+    vkCreateDescriptorSetLayout = (PFN_vkCreateDescriptorSetLayout) load("vkCreateDescriptorSetLayout", userptr);
+    vkCreateDevice = (PFN_vkCreateDevice) load("vkCreateDevice", userptr);
+    vkCreateEvent = (PFN_vkCreateEvent) load("vkCreateEvent", userptr);
+    vkCreateFence = (PFN_vkCreateFence) load("vkCreateFence", userptr);
+    vkCreateFramebuffer = (PFN_vkCreateFramebuffer) load("vkCreateFramebuffer", userptr);
+    vkCreateGraphicsPipelines = (PFN_vkCreateGraphicsPipelines) load("vkCreateGraphicsPipelines", userptr);
+    vkCreateImage = (PFN_vkCreateImage) load("vkCreateImage", userptr);
+    vkCreateImageView = (PFN_vkCreateImageView) load("vkCreateImageView", userptr);
+    vkCreateInstance = (PFN_vkCreateInstance) load("vkCreateInstance", userptr);
+    vkCreatePipelineCache = (PFN_vkCreatePipelineCache) load("vkCreatePipelineCache", userptr);
+    vkCreatePipelineLayout = (PFN_vkCreatePipelineLayout) load("vkCreatePipelineLayout", userptr);
+    vkCreateQueryPool = (PFN_vkCreateQueryPool) load("vkCreateQueryPool", userptr);
+    vkCreateRenderPass = (PFN_vkCreateRenderPass) load("vkCreateRenderPass", userptr);
+    vkCreateSampler = (PFN_vkCreateSampler) load("vkCreateSampler", userptr);
+    vkCreateSemaphore = (PFN_vkCreateSemaphore) load("vkCreateSemaphore", userptr);
+    vkCreateShaderModule = (PFN_vkCreateShaderModule) load("vkCreateShaderModule", userptr);
+    vkDestroyBuffer = (PFN_vkDestroyBuffer) load("vkDestroyBuffer", userptr);
+    vkDestroyBufferView = (PFN_vkDestroyBufferView) load("vkDestroyBufferView", userptr);
+    vkDestroyCommandPool = (PFN_vkDestroyCommandPool) load("vkDestroyCommandPool", userptr);
+    vkDestroyDescriptorPool = (PFN_vkDestroyDescriptorPool) load("vkDestroyDescriptorPool", userptr);
+    vkDestroyDescriptorSetLayout = (PFN_vkDestroyDescriptorSetLayout) load("vkDestroyDescriptorSetLayout", userptr);
+    vkDestroyDevice = (PFN_vkDestroyDevice) load("vkDestroyDevice", userptr);
+    vkDestroyEvent = (PFN_vkDestroyEvent) load("vkDestroyEvent", userptr);
+    vkDestroyFence = (PFN_vkDestroyFence) load("vkDestroyFence", userptr);
+    vkDestroyFramebuffer = (PFN_vkDestroyFramebuffer) load("vkDestroyFramebuffer", userptr);
+    vkDestroyImage = (PFN_vkDestroyImage) load("vkDestroyImage", userptr);
+    vkDestroyImageView = (PFN_vkDestroyImageView) load("vkDestroyImageView", userptr);
+    vkDestroyInstance = (PFN_vkDestroyInstance) load("vkDestroyInstance", userptr);
+    vkDestroyPipeline = (PFN_vkDestroyPipeline) load("vkDestroyPipeline", userptr);
+    vkDestroyPipelineCache = (PFN_vkDestroyPipelineCache) load("vkDestroyPipelineCache", userptr);
+    vkDestroyPipelineLayout = (PFN_vkDestroyPipelineLayout) load("vkDestroyPipelineLayout", userptr);
+    vkDestroyQueryPool = (PFN_vkDestroyQueryPool) load("vkDestroyQueryPool", userptr);
+    vkDestroyRenderPass = (PFN_vkDestroyRenderPass) load("vkDestroyRenderPass", userptr);
+    vkDestroySampler = (PFN_vkDestroySampler) load("vkDestroySampler", userptr);
+    vkDestroySemaphore = (PFN_vkDestroySemaphore) load("vkDestroySemaphore", userptr);
+    vkDestroyShaderModule = (PFN_vkDestroyShaderModule) load("vkDestroyShaderModule", userptr);
+    vkDeviceWaitIdle = (PFN_vkDeviceWaitIdle) load("vkDeviceWaitIdle", userptr);
+    vkEndCommandBuffer = (PFN_vkEndCommandBuffer) load("vkEndCommandBuffer", userptr);
+    vkEnumerateDeviceExtensionProperties = (PFN_vkEnumerateDeviceExtensionProperties) load("vkEnumerateDeviceExtensionProperties", userptr);
+    vkEnumerateDeviceLayerProperties = (PFN_vkEnumerateDeviceLayerProperties) load("vkEnumerateDeviceLayerProperties", userptr);
+    vkEnumerateInstanceExtensionProperties = (PFN_vkEnumerateInstanceExtensionProperties) load("vkEnumerateInstanceExtensionProperties", userptr);
+    vkEnumerateInstanceLayerProperties = (PFN_vkEnumerateInstanceLayerProperties) load("vkEnumerateInstanceLayerProperties", userptr);
+    vkEnumeratePhysicalDevices = (PFN_vkEnumeratePhysicalDevices) load("vkEnumeratePhysicalDevices", userptr);
+    vkFlushMappedMemoryRanges = (PFN_vkFlushMappedMemoryRanges) load("vkFlushMappedMemoryRanges", userptr);
+    vkFreeCommandBuffers = (PFN_vkFreeCommandBuffers) load("vkFreeCommandBuffers", userptr);
+    vkFreeDescriptorSets = (PFN_vkFreeDescriptorSets) load("vkFreeDescriptorSets", userptr);
+    vkFreeMemory = (PFN_vkFreeMemory) load("vkFreeMemory", userptr);
+    vkGetBufferMemoryRequirements = (PFN_vkGetBufferMemoryRequirements) load("vkGetBufferMemoryRequirements", userptr);
+    vkGetDeviceMemoryCommitment = (PFN_vkGetDeviceMemoryCommitment) load("vkGetDeviceMemoryCommitment", userptr);
+    vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr) load("vkGetDeviceProcAddr", userptr);
+    vkGetDeviceQueue = (PFN_vkGetDeviceQueue) load("vkGetDeviceQueue", userptr);
+    vkGetEventStatus = (PFN_vkGetEventStatus) load("vkGetEventStatus", userptr);
+    vkGetFenceStatus = (PFN_vkGetFenceStatus) load("vkGetFenceStatus", userptr);
+    vkGetImageMemoryRequirements = (PFN_vkGetImageMemoryRequirements) load("vkGetImageMemoryRequirements", userptr);
+    vkGetImageSparseMemoryRequirements = (PFN_vkGetImageSparseMemoryRequirements) load("vkGetImageSparseMemoryRequirements", userptr);
+    vkGetImageSubresourceLayout = (PFN_vkGetImageSubresourceLayout) load("vkGetImageSubresourceLayout", userptr);
+    vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr) load("vkGetInstanceProcAddr", userptr);
+    vkGetPhysicalDeviceFeatures = (PFN_vkGetPhysicalDeviceFeatures) load("vkGetPhysicalDeviceFeatures", userptr);
+    vkGetPhysicalDeviceFormatProperties = (PFN_vkGetPhysicalDeviceFormatProperties) load("vkGetPhysicalDeviceFormatProperties", userptr);
+    vkGetPhysicalDeviceImageFormatProperties = (PFN_vkGetPhysicalDeviceImageFormatProperties) load("vkGetPhysicalDeviceImageFormatProperties", userptr);
+    vkGetPhysicalDeviceMemoryProperties = (PFN_vkGetPhysicalDeviceMemoryProperties) load("vkGetPhysicalDeviceMemoryProperties", userptr);
+    vkGetPhysicalDeviceProperties = (PFN_vkGetPhysicalDeviceProperties) load("vkGetPhysicalDeviceProperties", userptr);
+    vkGetPhysicalDeviceQueueFamilyProperties = (PFN_vkGetPhysicalDeviceQueueFamilyProperties) load("vkGetPhysicalDeviceQueueFamilyProperties", userptr);
+    vkGetPhysicalDeviceSparseImageFormatProperties = (PFN_vkGetPhysicalDeviceSparseImageFormatProperties) load("vkGetPhysicalDeviceSparseImageFormatProperties", userptr);
+    vkGetPipelineCacheData = (PFN_vkGetPipelineCacheData) load("vkGetPipelineCacheData", userptr);
+    vkGetQueryPoolResults = (PFN_vkGetQueryPoolResults) load("vkGetQueryPoolResults", userptr);
+    vkGetRenderAreaGranularity = (PFN_vkGetRenderAreaGranularity) load("vkGetRenderAreaGranularity", userptr);
+    vkInvalidateMappedMemoryRanges = (PFN_vkInvalidateMappedMemoryRanges) load("vkInvalidateMappedMemoryRanges", userptr);
+    vkMapMemory = (PFN_vkMapMemory) load("vkMapMemory", userptr);
+    vkMergePipelineCaches = (PFN_vkMergePipelineCaches) load("vkMergePipelineCaches", userptr);
+    vkQueueBindSparse = (PFN_vkQueueBindSparse) load("vkQueueBindSparse", userptr);
+    vkQueueSubmit = (PFN_vkQueueSubmit) load("vkQueueSubmit", userptr);
+    vkQueueWaitIdle = (PFN_vkQueueWaitIdle) load("vkQueueWaitIdle", userptr);
+    vkResetCommandBuffer = (PFN_vkResetCommandBuffer) load("vkResetCommandBuffer", userptr);
+    vkResetCommandPool = (PFN_vkResetCommandPool) load("vkResetCommandPool", userptr);
+    vkResetDescriptorPool = (PFN_vkResetDescriptorPool) load("vkResetDescriptorPool", userptr);
+    vkResetEvent = (PFN_vkResetEvent) load("vkResetEvent", userptr);
+    vkResetFences = (PFN_vkResetFences) load("vkResetFences", userptr);
+    vkSetEvent = (PFN_vkSetEvent) load("vkSetEvent", userptr);
+    vkUnmapMemory = (PFN_vkUnmapMemory) load("vkUnmapMemory", userptr);
+    vkUpdateDescriptorSets = (PFN_vkUpdateDescriptorSets) load("vkUpdateDescriptorSets", userptr);
+    vkWaitForFences = (PFN_vkWaitForFences) load("vkWaitForFences", userptr);
+}
+static void glad_vk_load_VK_VERSION_1_1( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_VK_VERSION_1_1) return;
+    vkBindBufferMemory2 = (PFN_vkBindBufferMemory2) load("vkBindBufferMemory2", userptr);
+    vkBindImageMemory2 = (PFN_vkBindImageMemory2) load("vkBindImageMemory2", userptr);
+    vkCmdDispatchBase = (PFN_vkCmdDispatchBase) load("vkCmdDispatchBase", userptr);
+    vkCmdSetDeviceMask = (PFN_vkCmdSetDeviceMask) load("vkCmdSetDeviceMask", userptr);
+    vkCreateDescriptorUpdateTemplate = (PFN_vkCreateDescriptorUpdateTemplate) load("vkCreateDescriptorUpdateTemplate", userptr);
+    vkCreateSamplerYcbcrConversion = (PFN_vkCreateSamplerYcbcrConversion) load("vkCreateSamplerYcbcrConversion", userptr);
+    vkDestroyDescriptorUpdateTemplate = (PFN_vkDestroyDescriptorUpdateTemplate) load("vkDestroyDescriptorUpdateTemplate", userptr);
+    vkDestroySamplerYcbcrConversion = (PFN_vkDestroySamplerYcbcrConversion) load("vkDestroySamplerYcbcrConversion", userptr);
+    vkEnumerateInstanceVersion = (PFN_vkEnumerateInstanceVersion) load("vkEnumerateInstanceVersion", userptr);
+    vkEnumeratePhysicalDeviceGroups = (PFN_vkEnumeratePhysicalDeviceGroups) load("vkEnumeratePhysicalDeviceGroups", userptr);
+    vkGetBufferMemoryRequirements2 = (PFN_vkGetBufferMemoryRequirements2) load("vkGetBufferMemoryRequirements2", userptr);
+    vkGetDescriptorSetLayoutSupport = (PFN_vkGetDescriptorSetLayoutSupport) load("vkGetDescriptorSetLayoutSupport", userptr);
+    vkGetDeviceGroupPeerMemoryFeatures = (PFN_vkGetDeviceGroupPeerMemoryFeatures) load("vkGetDeviceGroupPeerMemoryFeatures", userptr);
+    vkGetDeviceQueue2 = (PFN_vkGetDeviceQueue2) load("vkGetDeviceQueue2", userptr);
+    vkGetImageMemoryRequirements2 = (PFN_vkGetImageMemoryRequirements2) load("vkGetImageMemoryRequirements2", userptr);
+    vkGetImageSparseMemoryRequirements2 = (PFN_vkGetImageSparseMemoryRequirements2) load("vkGetImageSparseMemoryRequirements2", userptr);
+    vkGetPhysicalDeviceExternalBufferProperties = (PFN_vkGetPhysicalDeviceExternalBufferProperties) load("vkGetPhysicalDeviceExternalBufferProperties", userptr);
+    vkGetPhysicalDeviceExternalFenceProperties = (PFN_vkGetPhysicalDeviceExternalFenceProperties) load("vkGetPhysicalDeviceExternalFenceProperties", userptr);
+    vkGetPhysicalDeviceExternalSemaphoreProperties = (PFN_vkGetPhysicalDeviceExternalSemaphoreProperties) load("vkGetPhysicalDeviceExternalSemaphoreProperties", userptr);
+    vkGetPhysicalDeviceFeatures2 = (PFN_vkGetPhysicalDeviceFeatures2) load("vkGetPhysicalDeviceFeatures2", userptr);
+    vkGetPhysicalDeviceFormatProperties2 = (PFN_vkGetPhysicalDeviceFormatProperties2) load("vkGetPhysicalDeviceFormatProperties2", userptr);
+    vkGetPhysicalDeviceImageFormatProperties2 = (PFN_vkGetPhysicalDeviceImageFormatProperties2) load("vkGetPhysicalDeviceImageFormatProperties2", userptr);
+    vkGetPhysicalDeviceMemoryProperties2 = (PFN_vkGetPhysicalDeviceMemoryProperties2) load("vkGetPhysicalDeviceMemoryProperties2", userptr);
+    vkGetPhysicalDeviceProperties2 = (PFN_vkGetPhysicalDeviceProperties2) load("vkGetPhysicalDeviceProperties2", userptr);
+    vkGetPhysicalDeviceQueueFamilyProperties2 = (PFN_vkGetPhysicalDeviceQueueFamilyProperties2) load("vkGetPhysicalDeviceQueueFamilyProperties2", userptr);
+    vkGetPhysicalDeviceSparseImageFormatProperties2 = (PFN_vkGetPhysicalDeviceSparseImageFormatProperties2) load("vkGetPhysicalDeviceSparseImageFormatProperties2", userptr);
+    vkTrimCommandPool = (PFN_vkTrimCommandPool) load("vkTrimCommandPool", userptr);
+    vkUpdateDescriptorSetWithTemplate = (PFN_vkUpdateDescriptorSetWithTemplate) load("vkUpdateDescriptorSetWithTemplate", userptr);
+}
+static void glad_vk_load_VK_EXT_debug_report( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_VK_EXT_debug_report) return;
+    vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT) load("vkCreateDebugReportCallbackEXT", userptr);
+    vkDebugReportMessageEXT = (PFN_vkDebugReportMessageEXT) load("vkDebugReportMessageEXT", userptr);
+    vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT) load("vkDestroyDebugReportCallbackEXT", userptr);
+}
+static void glad_vk_load_VK_KHR_surface( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_VK_KHR_surface) return;
+    vkDestroySurfaceKHR = (PFN_vkDestroySurfaceKHR) load("vkDestroySurfaceKHR", userptr);
+    vkGetPhysicalDeviceSurfaceCapabilitiesKHR = (PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR) load("vkGetPhysicalDeviceSurfaceCapabilitiesKHR", userptr);
+    vkGetPhysicalDeviceSurfaceFormatsKHR = (PFN_vkGetPhysicalDeviceSurfaceFormatsKHR) load("vkGetPhysicalDeviceSurfaceFormatsKHR", userptr);
+    vkGetPhysicalDeviceSurfacePresentModesKHR = (PFN_vkGetPhysicalDeviceSurfacePresentModesKHR) load("vkGetPhysicalDeviceSurfacePresentModesKHR", userptr);
+    vkGetPhysicalDeviceSurfaceSupportKHR = (PFN_vkGetPhysicalDeviceSurfaceSupportKHR) load("vkGetPhysicalDeviceSurfaceSupportKHR", userptr);
+}
+static void glad_vk_load_VK_KHR_swapchain( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_VK_KHR_swapchain) return;
+    vkAcquireNextImage2KHR = (PFN_vkAcquireNextImage2KHR) load("vkAcquireNextImage2KHR", userptr);
+    vkAcquireNextImageKHR = (PFN_vkAcquireNextImageKHR) load("vkAcquireNextImageKHR", userptr);
+    vkCreateSwapchainKHR = (PFN_vkCreateSwapchainKHR) load("vkCreateSwapchainKHR", userptr);
+    vkDestroySwapchainKHR = (PFN_vkDestroySwapchainKHR) load("vkDestroySwapchainKHR", userptr);
+    vkGetDeviceGroupPresentCapabilitiesKHR = (PFN_vkGetDeviceGroupPresentCapabilitiesKHR) load("vkGetDeviceGroupPresentCapabilitiesKHR", userptr);
+    vkGetDeviceGroupSurfacePresentModesKHR = (PFN_vkGetDeviceGroupSurfacePresentModesKHR) load("vkGetDeviceGroupSurfacePresentModesKHR", userptr);
+    vkGetPhysicalDevicePresentRectanglesKHR = (PFN_vkGetPhysicalDevicePresentRectanglesKHR) load("vkGetPhysicalDevicePresentRectanglesKHR", userptr);
+    vkGetSwapchainImagesKHR = (PFN_vkGetSwapchainImagesKHR) load("vkGetSwapchainImagesKHR", userptr);
+    vkQueuePresentKHR = (PFN_vkQueuePresentKHR) load("vkQueuePresentKHR", userptr);
+}
+
+
+
+static int glad_vk_get_extensions( VkPhysicalDevice physical_device, uint32_t *out_extension_count, char ***out_extensions) {
+    uint32_t i;
+    uint32_t instance_extension_count = 0;
+    uint32_t device_extension_count = 0;
+    uint32_t max_extension_count;
+    uint32_t total_extension_count;
+    char **extensions;
+    VkExtensionProperties *ext_properties;
+    VkResult result;
+
+    if (vkEnumerateInstanceExtensionProperties == NULL || (physical_device != NULL && vkEnumerateDeviceExtensionProperties == NULL)) {
+        return 0;
+    }
+
+    result = vkEnumerateInstanceExtensionProperties(NULL, &instance_extension_count, NULL);
+    if (result != VK_SUCCESS) {
+        return 0;
+    }
+
+    if (physical_device != NULL) {
+        result = vkEnumerateDeviceExtensionProperties(physical_device, NULL, &device_extension_count, NULL);
+        if (result != VK_SUCCESS) {
+            return 0;
+        }
+    }
+
+    total_extension_count = instance_extension_count + device_extension_count;
+    max_extension_count = instance_extension_count > device_extension_count
+        ? instance_extension_count : device_extension_count;
+
+    ext_properties = (VkExtensionProperties*) malloc(max_extension_count * sizeof(VkExtensionProperties));
+    if (ext_properties == NULL) {
+        return 0;
+    }
+
+    result = vkEnumerateInstanceExtensionProperties(NULL, &instance_extension_count, ext_properties);
+    if (result != VK_SUCCESS) {
+        free((void*) ext_properties);
+        return 0;
+    }
+
+    extensions = (char**) calloc(total_extension_count, sizeof(char*));
+    if (extensions == NULL) {
+        free((void*) ext_properties);
+        return 0;
+    }
+
+    for (i = 0; i < instance_extension_count; ++i) {
+        VkExtensionProperties ext = ext_properties[i];
+
+        size_t extension_name_length = strlen(ext.extensionName) + 1;
+        extensions[i] = (char*) malloc(extension_name_length * sizeof(char));
+        memcpy(extensions[i], ext.extensionName, extension_name_length * sizeof(char));
+    }
+
+    if (physical_device != NULL) {
+        result = vkEnumerateDeviceExtensionProperties(physical_device, NULL, &device_extension_count, ext_properties);
+        if (result != VK_SUCCESS) {
+            for (i = 0; i < instance_extension_count; ++i) {
+                free((void*) extensions[i]);
+            }
+            free(extensions);
+            return 0;
+        }
+
+        for (i = 0; i < device_extension_count; ++i) {
+            VkExtensionProperties ext = ext_properties[i];
+
+            size_t extension_name_length = strlen(ext.extensionName) + 1;
+            extensions[instance_extension_count + i] = (char*) malloc(extension_name_length * sizeof(char));
+            memcpy(extensions[instance_extension_count + i], ext.extensionName, extension_name_length * sizeof(char));
+        }
+    }
+
+    free((void*) ext_properties);
+
+    *out_extension_count = total_extension_count;
+    *out_extensions = extensions;
+
+    return 1;
+}
+
+static void glad_vk_free_extensions(uint32_t extension_count, char **extensions) {
+    uint32_t i;
+
+    for(i = 0; i < extension_count ; ++i) {
+        free((void*) (extensions[i]));
+    }
+
+    free((void*) extensions);
+}
+
+static int glad_vk_has_extension(const char *name, uint32_t extension_count, char **extensions) {
+    uint32_t i;
+
+    for (i = 0; i < extension_count; ++i) {
+        if(strcmp(name, extensions[i]) == 0) {
+            return 1;
+        }
+    }
+
+    return 0;
+}
+
+static GLADapiproc glad_vk_get_proc_from_userptr(const char* name, void *userptr) {
+    return (GLAD_GNUC_EXTENSION (GLADapiproc (*)(const char *name)) userptr)(name);
+}
+
+static int glad_vk_find_extensions_vulkan( VkPhysicalDevice physical_device) {
+    uint32_t extension_count = 0;
+    char **extensions = NULL;
+    if (!glad_vk_get_extensions(physical_device, &extension_count, &extensions)) return 0;
+
+    GLAD_VK_EXT_debug_report = glad_vk_has_extension("VK_EXT_debug_report", extension_count, extensions);
+    GLAD_VK_KHR_surface = glad_vk_has_extension("VK_KHR_surface", extension_count, extensions);
+    GLAD_VK_KHR_swapchain = glad_vk_has_extension("VK_KHR_swapchain", extension_count, extensions);
+
+    glad_vk_free_extensions(extension_count, extensions);
+
+    return 1;
+}
+
+static int glad_vk_find_core_vulkan( VkPhysicalDevice physical_device) {
+    int major = 1;
+    int minor = 0;
+
+#ifdef VK_VERSION_1_1
+    if (vkEnumerateInstanceVersion  != NULL) {
+        uint32_t version;
+        VkResult result;
+
+        result = vkEnumerateInstanceVersion(&version);
+        if (result == VK_SUCCESS) {
+            major = (int) VK_VERSION_MAJOR(version);
+            minor = (int) VK_VERSION_MINOR(version);
+        }
+    }
+#endif
+
+    if (physical_device != NULL && vkGetPhysicalDeviceProperties  != NULL) {
+        VkPhysicalDeviceProperties properties;
+        vkGetPhysicalDeviceProperties(physical_device, &properties);
+
+        major = (int) VK_VERSION_MAJOR(properties.apiVersion);
+        minor = (int) VK_VERSION_MINOR(properties.apiVersion);
+    }
+
+    GLAD_VK_VERSION_1_0 = (major == 1 && minor >= 0) || major > 1;
+    GLAD_VK_VERSION_1_1 = (major == 1 && minor >= 1) || major > 1;
+
+    return GLAD_MAKE_VERSION(major, minor);
+}
+
+int gladLoadVulkanUserPtr( VkPhysicalDevice physical_device, GLADuserptrloadfunc load, void *userptr) {
+    int version;
+
+#ifdef VK_VERSION_1_1
+    vkEnumerateInstanceVersion  = (PFN_vkEnumerateInstanceVersion) load("vkEnumerateInstanceVersion", userptr);
+#endif
+    version = glad_vk_find_core_vulkan( physical_device);
+    if (!version) {
+        return 0;
+    }
+
+    glad_vk_load_VK_VERSION_1_0(load, userptr);
+    glad_vk_load_VK_VERSION_1_1(load, userptr);
+
+    if (!glad_vk_find_extensions_vulkan( physical_device)) return 0;
+    glad_vk_load_VK_EXT_debug_report(load, userptr);
+    glad_vk_load_VK_KHR_surface(load, userptr);
+    glad_vk_load_VK_KHR_swapchain(load, userptr);
+
+
+    return version;
+}
+
+
+int gladLoadVulkan( VkPhysicalDevice physical_device, GLADloadfunc load) {
+    return gladLoadVulkanUserPtr( physical_device, glad_vk_get_proc_from_userptr, GLAD_GNUC_EXTENSION (void*) load);
+}
+
+
+
+

+ 574 - 0
samples/third_party/glfw/deps/linmath.h

@@ -0,0 +1,574 @@
+#ifndef LINMATH_H
+#define LINMATH_H
+
+#include <math.h>
+
+#ifdef _MSC_VER
+#define inline __inline
+#endif
+
+#define LINMATH_H_DEFINE_VEC(n) \
+typedef float vec##n[n]; \
+static inline void vec##n##_add(vec##n r, vec##n const a, vec##n const b) \
+{ \
+	int i; \
+	for(i=0; i<n; ++i) \
+		r[i] = a[i] + b[i]; \
+} \
+static inline void vec##n##_sub(vec##n r, vec##n const a, vec##n const b) \
+{ \
+	int i; \
+	for(i=0; i<n; ++i) \
+		r[i] = a[i] - b[i]; \
+} \
+static inline void vec##n##_scale(vec##n r, vec##n const v, float const s) \
+{ \
+	int i; \
+	for(i=0; i<n; ++i) \
+		r[i] = v[i] * s; \
+} \
+static inline float vec##n##_mul_inner(vec##n const a, vec##n const b) \
+{ \
+	float p = 0.; \
+	int i; \
+	for(i=0; i<n; ++i) \
+		p += b[i]*a[i]; \
+	return p; \
+} \
+static inline float vec##n##_len(vec##n const v) \
+{ \
+	return (float) sqrt(vec##n##_mul_inner(v,v)); \
+} \
+static inline void vec##n##_norm(vec##n r, vec##n const v) \
+{ \
+	float k = 1.f / vec##n##_len(v); \
+	vec##n##_scale(r, v, k); \
+}
+
+LINMATH_H_DEFINE_VEC(2)
+LINMATH_H_DEFINE_VEC(3)
+LINMATH_H_DEFINE_VEC(4)
+
+static inline void vec3_mul_cross(vec3 r, vec3 const a, vec3 const b)
+{
+	r[0] = a[1]*b[2] - a[2]*b[1];
+	r[1] = a[2]*b[0] - a[0]*b[2];
+	r[2] = a[0]*b[1] - a[1]*b[0];
+}
+
+static inline void vec3_reflect(vec3 r, vec3 const v, vec3 const n)
+{
+	float p  = 2.f*vec3_mul_inner(v, n);
+	int i;
+	for(i=0;i<3;++i)
+		r[i] = v[i] - p*n[i];
+}
+
+static inline void vec4_mul_cross(vec4 r, vec4 a, vec4 b)
+{
+	r[0] = a[1]*b[2] - a[2]*b[1];
+	r[1] = a[2]*b[0] - a[0]*b[2];
+	r[2] = a[0]*b[1] - a[1]*b[0];
+	r[3] = 1.f;
+}
+
+static inline void vec4_reflect(vec4 r, vec4 v, vec4 n)
+{
+	float p  = 2.f*vec4_mul_inner(v, n);
+	int i;
+	for(i=0;i<4;++i)
+		r[i] = v[i] - p*n[i];
+}
+
+typedef vec4 mat4x4[4];
+static inline void mat4x4_identity(mat4x4 M)
+{
+	int i, j;
+	for(i=0; i<4; ++i)
+		for(j=0; j<4; ++j)
+			M[i][j] = i==j ? 1.f : 0.f;
+}
+static inline void mat4x4_dup(mat4x4 M, mat4x4 N)
+{
+	int i, j;
+	for(i=0; i<4; ++i)
+		for(j=0; j<4; ++j)
+			M[i][j] = N[i][j];
+}
+static inline void mat4x4_row(vec4 r, mat4x4 M, int i)
+{
+	int k;
+	for(k=0; k<4; ++k)
+		r[k] = M[k][i];
+}
+static inline void mat4x4_col(vec4 r, mat4x4 M, int i)
+{
+	int k;
+	for(k=0; k<4; ++k)
+		r[k] = M[i][k];
+}
+static inline void mat4x4_transpose(mat4x4 M, mat4x4 N)
+{
+	int i, j;
+	for(j=0; j<4; ++j)
+		for(i=0; i<4; ++i)
+			M[i][j] = N[j][i];
+}
+static inline void mat4x4_add(mat4x4 M, mat4x4 a, mat4x4 b)
+{
+	int i;
+	for(i=0; i<4; ++i)
+		vec4_add(M[i], a[i], b[i]);
+}
+static inline void mat4x4_sub(mat4x4 M, mat4x4 a, mat4x4 b)
+{
+	int i;
+	for(i=0; i<4; ++i)
+		vec4_sub(M[i], a[i], b[i]);
+}
+static inline void mat4x4_scale(mat4x4 M, mat4x4 a, float k)
+{
+	int i;
+	for(i=0; i<4; ++i)
+		vec4_scale(M[i], a[i], k);
+}
+static inline void mat4x4_scale_aniso(mat4x4 M, mat4x4 a, float x, float y, float z)
+{
+	int i;
+	vec4_scale(M[0], a[0], x);
+	vec4_scale(M[1], a[1], y);
+	vec4_scale(M[2], a[2], z);
+	for(i = 0; i < 4; ++i) {
+		M[3][i] = a[3][i];
+	}
+}
+static inline void mat4x4_mul(mat4x4 M, mat4x4 a, mat4x4 b)
+{
+	mat4x4 temp;
+	int k, r, c;
+	for(c=0; c<4; ++c) for(r=0; r<4; ++r) {
+		temp[c][r] = 0.f;
+		for(k=0; k<4; ++k)
+			temp[c][r] += a[k][r] * b[c][k];
+	}
+	mat4x4_dup(M, temp);
+}
+static inline void mat4x4_mul_vec4(vec4 r, mat4x4 M, vec4 v)
+{
+	int i, j;
+	for(j=0; j<4; ++j) {
+		r[j] = 0.f;
+		for(i=0; i<4; ++i)
+			r[j] += M[i][j] * v[i];
+	}
+}
+static inline void mat4x4_translate(mat4x4 T, float x, float y, float z)
+{
+	mat4x4_identity(T);
+	T[3][0] = x;
+	T[3][1] = y;
+	T[3][2] = z;
+}
+static inline void mat4x4_translate_in_place(mat4x4 M, float x, float y, float z)
+{
+	vec4 t = {x, y, z, 0};
+	vec4 r;
+	int i;
+	for (i = 0; i < 4; ++i) {
+		mat4x4_row(r, M, i);
+		M[3][i] += vec4_mul_inner(r, t);
+	}
+}
+static inline void mat4x4_from_vec3_mul_outer(mat4x4 M, vec3 a, vec3 b)
+{
+	int i, j;
+	for(i=0; i<4; ++i) for(j=0; j<4; ++j)
+		M[i][j] = i<3 && j<3 ? a[i] * b[j] : 0.f;
+}
+static inline void mat4x4_rotate(mat4x4 R, mat4x4 M, float x, float y, float z, float angle)
+{
+	float s = sinf(angle);
+	float c = cosf(angle);
+	vec3 u = {x, y, z};
+
+	if(vec3_len(u) > 1e-4) {
+		mat4x4 T, C, S = {{0}};
+
+		vec3_norm(u, u);
+		mat4x4_from_vec3_mul_outer(T, u, u);
+
+		S[1][2] =  u[0];
+		S[2][1] = -u[0];
+		S[2][0] =  u[1];
+		S[0][2] = -u[1];
+		S[0][1] =  u[2];
+		S[1][0] = -u[2];
+
+		mat4x4_scale(S, S, s);
+
+		mat4x4_identity(C);
+		mat4x4_sub(C, C, T);
+
+		mat4x4_scale(C, C, c);
+
+		mat4x4_add(T, T, C);
+		mat4x4_add(T, T, S);
+
+		T[3][3] = 1.;
+		mat4x4_mul(R, M, T);
+	} else {
+		mat4x4_dup(R, M);
+	}
+}
+static inline void mat4x4_rotate_X(mat4x4 Q, mat4x4 M, float angle)
+{
+	float s = sinf(angle);
+	float c = cosf(angle);
+	mat4x4 R = {
+		{1.f, 0.f, 0.f, 0.f},
+		{0.f,   c,   s, 0.f},
+		{0.f,  -s,   c, 0.f},
+		{0.f, 0.f, 0.f, 1.f}
+	};
+	mat4x4_mul(Q, M, R);
+}
+static inline void mat4x4_rotate_Y(mat4x4 Q, mat4x4 M, float angle)
+{
+	float s = sinf(angle);
+	float c = cosf(angle);
+	mat4x4 R = {
+		{   c, 0.f,  -s, 0.f},
+		{ 0.f, 1.f, 0.f, 0.f},
+		{   s, 0.f,   c, 0.f},
+		{ 0.f, 0.f, 0.f, 1.f}
+	};
+	mat4x4_mul(Q, M, R);
+}
+static inline void mat4x4_rotate_Z(mat4x4 Q, mat4x4 M, float angle)
+{
+	float s = sinf(angle);
+	float c = cosf(angle);
+	mat4x4 R = {
+		{   c,   s, 0.f, 0.f},
+		{  -s,   c, 0.f, 0.f},
+		{ 0.f, 0.f, 1.f, 0.f},
+		{ 0.f, 0.f, 0.f, 1.f}
+	};
+	mat4x4_mul(Q, M, R);
+}
+static inline void mat4x4_invert(mat4x4 T, mat4x4 M)
+{
+	float idet;
+	float s[6];
+	float c[6];
+	s[0] = M[0][0]*M[1][1] - M[1][0]*M[0][1];
+	s[1] = M[0][0]*M[1][2] - M[1][0]*M[0][2];
+	s[2] = M[0][0]*M[1][3] - M[1][0]*M[0][3];
+	s[3] = M[0][1]*M[1][2] - M[1][1]*M[0][2];
+	s[4] = M[0][1]*M[1][3] - M[1][1]*M[0][3];
+	s[5] = M[0][2]*M[1][3] - M[1][2]*M[0][3];
+
+	c[0] = M[2][0]*M[3][1] - M[3][0]*M[2][1];
+	c[1] = M[2][0]*M[3][2] - M[3][0]*M[2][2];
+	c[2] = M[2][0]*M[3][3] - M[3][0]*M[2][3];
+	c[3] = M[2][1]*M[3][2] - M[3][1]*M[2][2];
+	c[4] = M[2][1]*M[3][3] - M[3][1]*M[2][3];
+	c[5] = M[2][2]*M[3][3] - M[3][2]*M[2][3];
+
+	/* Assumes it is invertible */
+	idet = 1.0f/( s[0]*c[5]-s[1]*c[4]+s[2]*c[3]+s[3]*c[2]-s[4]*c[1]+s[5]*c[0] );
+
+	T[0][0] = ( M[1][1] * c[5] - M[1][2] * c[4] + M[1][3] * c[3]) * idet;
+	T[0][1] = (-M[0][1] * c[5] + M[0][2] * c[4] - M[0][3] * c[3]) * idet;
+	T[0][2] = ( M[3][1] * s[5] - M[3][2] * s[4] + M[3][3] * s[3]) * idet;
+	T[0][3] = (-M[2][1] * s[5] + M[2][2] * s[4] - M[2][3] * s[3]) * idet;
+
+	T[1][0] = (-M[1][0] * c[5] + M[1][2] * c[2] - M[1][3] * c[1]) * idet;
+	T[1][1] = ( M[0][0] * c[5] - M[0][2] * c[2] + M[0][3] * c[1]) * idet;
+	T[1][2] = (-M[3][0] * s[5] + M[3][2] * s[2] - M[3][3] * s[1]) * idet;
+	T[1][3] = ( M[2][0] * s[5] - M[2][2] * s[2] + M[2][3] * s[1]) * idet;
+
+	T[2][0] = ( M[1][0] * c[4] - M[1][1] * c[2] + M[1][3] * c[0]) * idet;
+	T[2][1] = (-M[0][0] * c[4] + M[0][1] * c[2] - M[0][3] * c[0]) * idet;
+	T[2][2] = ( M[3][0] * s[4] - M[3][1] * s[2] + M[3][3] * s[0]) * idet;
+	T[2][3] = (-M[2][0] * s[4] + M[2][1] * s[2] - M[2][3] * s[0]) * idet;
+
+	T[3][0] = (-M[1][0] * c[3] + M[1][1] * c[1] - M[1][2] * c[0]) * idet;
+	T[3][1] = ( M[0][0] * c[3] - M[0][1] * c[1] + M[0][2] * c[0]) * idet;
+	T[3][2] = (-M[3][0] * s[3] + M[3][1] * s[1] - M[3][2] * s[0]) * idet;
+	T[3][3] = ( M[2][0] * s[3] - M[2][1] * s[1] + M[2][2] * s[0]) * idet;
+}
+static inline void mat4x4_orthonormalize(mat4x4 R, mat4x4 M)
+{
+	float s = 1.;
+	vec3 h;
+
+	mat4x4_dup(R, M);
+	vec3_norm(R[2], R[2]);
+
+	s = vec3_mul_inner(R[1], R[2]);
+	vec3_scale(h, R[2], s);
+	vec3_sub(R[1], R[1], h);
+	vec3_norm(R[2], R[2]);
+
+	s = vec3_mul_inner(R[1], R[2]);
+	vec3_scale(h, R[2], s);
+	vec3_sub(R[1], R[1], h);
+	vec3_norm(R[1], R[1]);
+
+	s = vec3_mul_inner(R[0], R[1]);
+	vec3_scale(h, R[1], s);
+	vec3_sub(R[0], R[0], h);
+	vec3_norm(R[0], R[0]);
+}
+
+static inline void mat4x4_frustum(mat4x4 M, float l, float r, float b, float t, float n, float f)
+{
+	M[0][0] = 2.f*n/(r-l);
+	M[0][1] = M[0][2] = M[0][3] = 0.f;
+
+	M[1][1] = 2.f*n/(t-b);
+	M[1][0] = M[1][2] = M[1][3] = 0.f;
+
+	M[2][0] = (r+l)/(r-l);
+	M[2][1] = (t+b)/(t-b);
+	M[2][2] = -(f+n)/(f-n);
+	M[2][3] = -1.f;
+
+	M[3][2] = -2.f*(f*n)/(f-n);
+	M[3][0] = M[3][1] = M[3][3] = 0.f;
+}
+static inline void mat4x4_ortho(mat4x4 M, float l, float r, float b, float t, float n, float f)
+{
+	M[0][0] = 2.f/(r-l);
+	M[0][1] = M[0][2] = M[0][3] = 0.f;
+
+	M[1][1] = 2.f/(t-b);
+	M[1][0] = M[1][2] = M[1][3] = 0.f;
+
+	M[2][2] = -2.f/(f-n);
+	M[2][0] = M[2][1] = M[2][3] = 0.f;
+
+	M[3][0] = -(r+l)/(r-l);
+	M[3][1] = -(t+b)/(t-b);
+	M[3][2] = -(f+n)/(f-n);
+	M[3][3] = 1.f;
+}
+static inline void mat4x4_perspective(mat4x4 m, float y_fov, float aspect, float n, float f)
+{
+	/* NOTE: Degrees are an unhandy unit to work with.
+	 * linmath.h uses radians for everything! */
+	float const a = 1.f / (float) tan(y_fov / 2.f);
+
+	m[0][0] = a / aspect;
+	m[0][1] = 0.f;
+	m[0][2] = 0.f;
+	m[0][3] = 0.f;
+
+	m[1][0] = 0.f;
+	m[1][1] = a;
+	m[1][2] = 0.f;
+	m[1][3] = 0.f;
+
+	m[2][0] = 0.f;
+	m[2][1] = 0.f;
+	m[2][2] = -((f + n) / (f - n));
+	m[2][3] = -1.f;
+
+	m[3][0] = 0.f;
+	m[3][1] = 0.f;
+	m[3][2] = -((2.f * f * n) / (f - n));
+	m[3][3] = 0.f;
+}
+static inline void mat4x4_look_at(mat4x4 m, vec3 eye, vec3 center, vec3 up)
+{
+	/* Adapted from Android's OpenGL Matrix.java.                        */
+	/* See the OpenGL GLUT documentation for gluLookAt for a description */
+	/* of the algorithm. We implement it in a straightforward way:       */
+
+	/* TODO: The negation of of can be spared by swapping the order of
+	 *       operands in the following cross products in the right way. */
+	vec3 f;
+	vec3 s;
+	vec3 t;
+
+	vec3_sub(f, center, eye);
+	vec3_norm(f, f);
+
+	vec3_mul_cross(s, f, up);
+	vec3_norm(s, s);
+
+	vec3_mul_cross(t, s, f);
+
+	m[0][0] =  s[0];
+	m[0][1] =  t[0];
+	m[0][2] = -f[0];
+	m[0][3] =   0.f;
+
+	m[1][0] =  s[1];
+	m[1][1] =  t[1];
+	m[1][2] = -f[1];
+	m[1][3] =   0.f;
+
+	m[2][0] =  s[2];
+	m[2][1] =  t[2];
+	m[2][2] = -f[2];
+	m[2][3] =   0.f;
+
+	m[3][0] =  0.f;
+	m[3][1] =  0.f;
+	m[3][2] =  0.f;
+	m[3][3] =  1.f;
+
+	mat4x4_translate_in_place(m, -eye[0], -eye[1], -eye[2]);
+}
+
+typedef float quat[4];
+static inline void quat_identity(quat q)
+{
+	q[0] = q[1] = q[2] = 0.f;
+	q[3] = 1.f;
+}
+static inline void quat_add(quat r, quat a, quat b)
+{
+	int i;
+	for(i=0; i<4; ++i)
+		r[i] = a[i] + b[i];
+}
+static inline void quat_sub(quat r, quat a, quat b)
+{
+	int i;
+	for(i=0; i<4; ++i)
+		r[i] = a[i] - b[i];
+}
+static inline void quat_mul(quat r, quat p, quat q)
+{
+	vec3 w;
+	vec3_mul_cross(r, p, q);
+	vec3_scale(w, p, q[3]);
+	vec3_add(r, r, w);
+	vec3_scale(w, q, p[3]);
+	vec3_add(r, r, w);
+	r[3] = p[3]*q[3] - vec3_mul_inner(p, q);
+}
+static inline void quat_scale(quat r, quat v, float s)
+{
+	int i;
+	for(i=0; i<4; ++i)
+		r[i] = v[i] * s;
+}
+static inline float quat_inner_product(quat a, quat b)
+{
+	float p = 0.f;
+	int i;
+	for(i=0; i<4; ++i)
+		p += b[i]*a[i];
+	return p;
+}
+static inline void quat_conj(quat r, quat q)
+{
+	int i;
+	for(i=0; i<3; ++i)
+		r[i] = -q[i];
+	r[3] = q[3];
+}
+static inline void quat_rotate(quat r, float angle, vec3 axis) {
+	int i;
+	vec3 v;
+	vec3_scale(v, axis, sinf(angle / 2));
+	for(i=0; i<3; ++i)
+		r[i] = v[i];
+	r[3] = cosf(angle / 2);
+}
+#define quat_norm vec4_norm
+static inline void quat_mul_vec3(vec3 r, quat q, vec3 v)
+{
+/*
+ * Method by Fabian 'ryg' Giessen (of Farbrausch)
+t = 2 * cross(q.xyz, v)
+v' = v + q.w * t + cross(q.xyz, t)
+ */
+	vec3 t = {q[0], q[1], q[2]};
+	vec3 u = {q[0], q[1], q[2]};
+
+	vec3_mul_cross(t, t, v);
+	vec3_scale(t, t, 2);
+
+	vec3_mul_cross(u, u, t);
+	vec3_scale(t, t, q[3]);
+
+	vec3_add(r, v, t);
+	vec3_add(r, r, u);
+}
+static inline void mat4x4_from_quat(mat4x4 M, quat q)
+{
+	float a = q[3];
+	float b = q[0];
+	float c = q[1];
+	float d = q[2];
+	float a2 = a*a;
+	float b2 = b*b;
+	float c2 = c*c;
+	float d2 = d*d;
+
+	M[0][0] = a2 + b2 - c2 - d2;
+	M[0][1] = 2.f*(b*c + a*d);
+	M[0][2] = 2.f*(b*d - a*c);
+	M[0][3] = 0.f;
+
+	M[1][0] = 2*(b*c - a*d);
+	M[1][1] = a2 - b2 + c2 - d2;
+	M[1][2] = 2.f*(c*d + a*b);
+	M[1][3] = 0.f;
+
+	M[2][0] = 2.f*(b*d + a*c);
+	M[2][1] = 2.f*(c*d - a*b);
+	M[2][2] = a2 - b2 - c2 + d2;
+	M[2][3] = 0.f;
+
+	M[3][0] = M[3][1] = M[3][2] = 0.f;
+	M[3][3] = 1.f;
+}
+
+static inline void mat4x4o_mul_quat(mat4x4 R, mat4x4 M, quat q)
+{
+/*  XXX: The way this is written only works for othogonal matrices. */
+/* TODO: Take care of non-orthogonal case. */
+	quat_mul_vec3(R[0], q, M[0]);
+	quat_mul_vec3(R[1], q, M[1]);
+	quat_mul_vec3(R[2], q, M[2]);
+
+	R[3][0] = R[3][1] = R[3][2] = 0.f;
+	R[3][3] = 1.f;
+}
+static inline void quat_from_mat4x4(quat q, mat4x4 M)
+{
+	float r=0.f;
+	int i;
+
+	int perm[] = { 0, 1, 2, 0, 1 };
+	int *p = perm;
+
+	for(i = 0; i<3; i++) {
+		float m = M[i][i];
+		if( m < r )
+			continue;
+		m = r;
+		p = &perm[i];
+	}
+
+	r = (float) sqrt(1.f + M[p[0]][p[0]] - M[p[1]][p[1]] - M[p[2]][p[2]] );
+
+	if(r < 1e-6) {
+		q[0] = 1.f;
+		q[1] = q[2] = q[3] = 0.f;
+		return;
+	}
+
+	q[0] = r/2.f;
+	q[1] = (M[p[0]][p[1]] - M[p[1]][p[0]])/(2.f*r);
+	q[2] = (M[p[2]][p[0]] - M[p[0]][p[2]])/(2.f*r);
+	q[3] = (M[p[2]][p[1]] - M[p[1]][p[2]])/(2.f*r);
+}
+
+#endif

+ 117 - 0
samples/third_party/glfw/deps/mingw/_mingw_dxhelper.h

@@ -0,0 +1,117 @@
+/**
+ * This file has no copyright assigned and is placed in the Public Domain.
+ * This file is part of the mingw-w64 runtime package.
+ * No warranty is given; refer to the file DISCLAIMER within this package.
+ */
+
+#if defined(_MSC_VER) && !defined(_MSC_EXTENSIONS)
+#define NONAMELESSUNION		1
+#endif
+#if defined(NONAMELESSSTRUCT) && \
+   !defined(NONAMELESSUNION)
+#define NONAMELESSUNION		1
+#endif
+#if defined(NONAMELESSUNION)  && \
+   !defined(NONAMELESSSTRUCT)
+#define NONAMELESSSTRUCT	1
+#endif
+#if !defined(__GNU_EXTENSION)
+#if defined(__GNUC__) || defined(__GNUG__)
+#define __GNU_EXTENSION		__extension__
+#else
+#define __GNU_EXTENSION
+#endif
+#endif /* __extension__ */
+
+#ifndef __ANONYMOUS_DEFINED
+#define __ANONYMOUS_DEFINED
+#if defined(__GNUC__) || defined(__GNUG__)
+#define _ANONYMOUS_UNION	__extension__
+#define _ANONYMOUS_STRUCT	__extension__
+#else
+#define _ANONYMOUS_UNION
+#define _ANONYMOUS_STRUCT
+#endif
+#ifndef NONAMELESSUNION
+#define _UNION_NAME(x)
+#define _STRUCT_NAME(x)
+#else /* NONAMELESSUNION */
+#define _UNION_NAME(x)  x
+#define _STRUCT_NAME(x) x
+#endif
+#endif	/* __ANONYMOUS_DEFINED */
+
+#ifndef DUMMYUNIONNAME
+# ifdef NONAMELESSUNION
+#  define DUMMYUNIONNAME  u
+#  define DUMMYUNIONNAME1 u1	/* Wine uses this variant */
+#  define DUMMYUNIONNAME2 u2
+#  define DUMMYUNIONNAME3 u3
+#  define DUMMYUNIONNAME4 u4
+#  define DUMMYUNIONNAME5 u5
+#  define DUMMYUNIONNAME6 u6
+#  define DUMMYUNIONNAME7 u7
+#  define DUMMYUNIONNAME8 u8
+#  define DUMMYUNIONNAME9 u9
+# else /* NONAMELESSUNION */
+#  define DUMMYUNIONNAME
+#  define DUMMYUNIONNAME1	/* Wine uses this variant */
+#  define DUMMYUNIONNAME2
+#  define DUMMYUNIONNAME3
+#  define DUMMYUNIONNAME4
+#  define DUMMYUNIONNAME5
+#  define DUMMYUNIONNAME6
+#  define DUMMYUNIONNAME7
+#  define DUMMYUNIONNAME8
+#  define DUMMYUNIONNAME9
+# endif
+#endif	/* DUMMYUNIONNAME */
+
+#if !defined(DUMMYUNIONNAME1)	/* MinGW does not define this one */
+# ifdef NONAMELESSUNION
+#  define DUMMYUNIONNAME1 u1	/* Wine uses this variant */
+# else
+#  define DUMMYUNIONNAME1	/* Wine uses this variant */
+# endif
+#endif	/* DUMMYUNIONNAME1 */
+
+#ifndef DUMMYSTRUCTNAME
+# ifdef NONAMELESSUNION
+#  define DUMMYSTRUCTNAME  s
+#  define DUMMYSTRUCTNAME1 s1	/* Wine uses this variant */
+#  define DUMMYSTRUCTNAME2 s2
+#  define DUMMYSTRUCTNAME3 s3
+#  define DUMMYSTRUCTNAME4 s4
+#  define DUMMYSTRUCTNAME5 s5
+# else
+#  define DUMMYSTRUCTNAME
+#  define DUMMYSTRUCTNAME1	/* Wine uses this variant */
+#  define DUMMYSTRUCTNAME2
+#  define DUMMYSTRUCTNAME3
+#  define DUMMYSTRUCTNAME4
+#  define DUMMYSTRUCTNAME5
+# endif
+#endif /* DUMMYSTRUCTNAME */
+
+/* These are for compatibility with the Wine source tree */
+
+#ifndef WINELIB_NAME_AW
+# ifdef __MINGW_NAME_AW
+#   define WINELIB_NAME_AW  __MINGW_NAME_AW
+# else
+#  ifdef UNICODE
+#   define WINELIB_NAME_AW(func) func##W
+#  else
+#   define WINELIB_NAME_AW(func) func##A
+#  endif
+# endif
+#endif	/* WINELIB_NAME_AW */
+
+#ifndef DECL_WINELIB_TYPE_AW
+# ifdef __MINGW_TYPEDEF_AW
+#  define DECL_WINELIB_TYPE_AW  __MINGW_TYPEDEF_AW
+# else
+#  define DECL_WINELIB_TYPE_AW(type)  typedef WINELIB_NAME_AW(type) type;
+# endif
+#endif	/* DECL_WINELIB_TYPE_AW */
+

ファイルの差分が大きいため隠しています
+ 2467 - 0
samples/third_party/glfw/deps/mingw/dinput.h


+ 239 - 0
samples/third_party/glfw/deps/mingw/xinput.h

@@ -0,0 +1,239 @@
+/*
+ * The Wine project - Xinput Joystick Library
+ * Copyright 2008 Andrew Fenn
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef __WINE_XINPUT_H
+#define __WINE_XINPUT_H
+
+#include <windef.h>
+
+/*
+ * Bitmasks for the joysticks buttons, determines what has
+ * been pressed on the joystick, these need to be mapped
+ * to whatever device you're using instead of an xbox 360
+ * joystick
+ */
+
+#define XINPUT_GAMEPAD_DPAD_UP          0x0001
+#define XINPUT_GAMEPAD_DPAD_DOWN        0x0002
+#define XINPUT_GAMEPAD_DPAD_LEFT        0x0004
+#define XINPUT_GAMEPAD_DPAD_RIGHT       0x0008
+#define XINPUT_GAMEPAD_START            0x0010
+#define XINPUT_GAMEPAD_BACK             0x0020
+#define XINPUT_GAMEPAD_LEFT_THUMB       0x0040
+#define XINPUT_GAMEPAD_RIGHT_THUMB      0x0080
+#define XINPUT_GAMEPAD_LEFT_SHOULDER    0x0100
+#define XINPUT_GAMEPAD_RIGHT_SHOULDER   0x0200
+#define XINPUT_GAMEPAD_A                0x1000
+#define XINPUT_GAMEPAD_B                0x2000
+#define XINPUT_GAMEPAD_X                0x4000
+#define XINPUT_GAMEPAD_Y                0x8000
+
+/*
+ * Defines the flags used to determine if the user is pushing
+ * down on a button, not holding a button, etc
+ */
+
+#define XINPUT_KEYSTROKE_KEYDOWN        0x0001
+#define XINPUT_KEYSTROKE_KEYUP          0x0002
+#define XINPUT_KEYSTROKE_REPEAT         0x0004
+
+/*
+ * Defines the codes which are returned by XInputGetKeystroke
+ */
+
+#define VK_PAD_A                        0x5800
+#define VK_PAD_B                        0x5801
+#define VK_PAD_X                        0x5802
+#define VK_PAD_Y                        0x5803
+#define VK_PAD_RSHOULDER                0x5804
+#define VK_PAD_LSHOULDER                0x5805
+#define VK_PAD_LTRIGGER                 0x5806
+#define VK_PAD_RTRIGGER                 0x5807
+#define VK_PAD_DPAD_UP                  0x5810
+#define VK_PAD_DPAD_DOWN                0x5811
+#define VK_PAD_DPAD_LEFT                0x5812
+#define VK_PAD_DPAD_RIGHT               0x5813
+#define VK_PAD_START                    0x5814
+#define VK_PAD_BACK                     0x5815
+#define VK_PAD_LTHUMB_PRESS             0x5816
+#define VK_PAD_RTHUMB_PRESS             0x5817
+#define VK_PAD_LTHUMB_UP                0x5820
+#define VK_PAD_LTHUMB_DOWN              0x5821
+#define VK_PAD_LTHUMB_RIGHT             0x5822
+#define VK_PAD_LTHUMB_LEFT              0x5823
+#define VK_PAD_LTHUMB_UPLEFT            0x5824
+#define VK_PAD_LTHUMB_UPRIGHT           0x5825
+#define VK_PAD_LTHUMB_DOWNRIGHT         0x5826
+#define VK_PAD_LTHUMB_DOWNLEFT          0x5827
+#define VK_PAD_RTHUMB_UP                0x5830
+#define VK_PAD_RTHUMB_DOWN              0x5831
+#define VK_PAD_RTHUMB_RIGHT             0x5832
+#define VK_PAD_RTHUMB_LEFT              0x5833
+#define VK_PAD_RTHUMB_UPLEFT            0x5834
+#define VK_PAD_RTHUMB_UPRIGHT           0x5835
+#define VK_PAD_RTHUMB_DOWNRIGHT         0x5836
+#define VK_PAD_RTHUMB_DOWNLEFT          0x5837
+
+/*
+ * Deadzones are for analogue joystick controls on the joypad
+ * which determine when input should be assumed to be in the
+ * middle of the pad. This is a threshold to stop a joypad
+ * controlling the game when the player isn't touching the
+ * controls.
+ */
+
+#define XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE  7849
+#define XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE 8689
+#define XINPUT_GAMEPAD_TRIGGER_THRESHOLD    30
+
+
+/*
+ * Defines what type of abilities the type of joystick has
+ * DEVTYPE_GAMEPAD is available for all joysticks, however
+ * there may be more specific identifiers for other joysticks
+ * which are being used.
+ */
+
+#define XINPUT_DEVTYPE_GAMEPAD          0x01
+#define XINPUT_DEVSUBTYPE_GAMEPAD       0x01
+#define XINPUT_DEVSUBTYPE_WHEEL         0x02
+#define XINPUT_DEVSUBTYPE_ARCADE_STICK  0x03
+#define XINPUT_DEVSUBTYPE_FLIGHT_SICK   0x04
+#define XINPUT_DEVSUBTYPE_DANCE_PAD     0x05
+#define XINPUT_DEVSUBTYPE_GUITAR        0x06
+#define XINPUT_DEVSUBTYPE_DRUM_KIT      0x08
+
+/*
+ * These are used with the XInputGetCapabilities function to
+ * determine the abilities to the joystick which has been
+ * plugged in.
+ */
+
+#define XINPUT_CAPS_VOICE_SUPPORTED     0x0004
+#define XINPUT_FLAG_GAMEPAD             0x00000001
+
+/*
+ * Defines the status of the battery if one is used in the
+ * attached joystick. The first two define if the joystick
+ * supports a battery. Disconnected means that the joystick
+ * isn't connected. Wired shows that the joystick is a wired
+ * joystick.
+ */
+
+#define BATTERY_DEVTYPE_GAMEPAD         0x00
+#define BATTERY_DEVTYPE_HEADSET         0x01
+#define BATTERY_TYPE_DISCONNECTED       0x00
+#define BATTERY_TYPE_WIRED              0x01
+#define BATTERY_TYPE_ALKALINE           0x02
+#define BATTERY_TYPE_NIMH               0x03
+#define BATTERY_TYPE_UNKNOWN            0xFF
+#define BATTERY_LEVEL_EMPTY             0x00
+#define BATTERY_LEVEL_LOW               0x01
+#define BATTERY_LEVEL_MEDIUM            0x02
+#define BATTERY_LEVEL_FULL              0x03
+
+/*
+ * How many joysticks can be used with this library. Games that
+ * use the xinput library will not go over this number.
+ */
+
+#define XUSER_MAX_COUNT                 4
+#define XUSER_INDEX_ANY                 0x000000FF
+
+/*
+ * Defines the structure of an xbox 360 joystick.
+ */
+
+typedef struct _XINPUT_GAMEPAD {
+    WORD wButtons;
+    BYTE bLeftTrigger;
+    BYTE bRightTrigger;
+    SHORT sThumbLX;
+    SHORT sThumbLY;
+    SHORT sThumbRX;
+    SHORT sThumbRY;
+} XINPUT_GAMEPAD, *PXINPUT_GAMEPAD;
+
+typedef struct _XINPUT_STATE {
+    DWORD dwPacketNumber;
+    XINPUT_GAMEPAD Gamepad;
+} XINPUT_STATE, *PXINPUT_STATE;
+
+/*
+ * Defines the structure of how much vibration is set on both the
+ * right and left motors in a joystick. If you're not using a 360
+ * joystick you will have to map these to your device.
+ */
+
+typedef struct _XINPUT_VIBRATION {
+    WORD wLeftMotorSpeed;
+    WORD wRightMotorSpeed;
+} XINPUT_VIBRATION, *PXINPUT_VIBRATION;
+
+/*
+ * Defines the structure for what kind of abilities the joystick has
+ * such abilities are things such as if the joystick has the ability
+ * to send and receive audio, if the joystick is in fact a driving
+ * wheel or perhaps if the joystick is some kind of dance pad or
+ * guitar.
+ */
+
+typedef struct _XINPUT_CAPABILITIES {
+    BYTE Type;
+    BYTE SubType;
+    WORD Flags;
+    XINPUT_GAMEPAD Gamepad;
+    XINPUT_VIBRATION Vibration;
+} XINPUT_CAPABILITIES, *PXINPUT_CAPABILITIES;
+
+/*
+ * Defines the structure for a joystick input event which is
+ * retrieved using the function XInputGetKeystroke
+ */
+typedef struct _XINPUT_KEYSTROKE {
+    WORD VirtualKey;
+    WCHAR Unicode;
+    WORD Flags;
+    BYTE UserIndex;
+    BYTE HidCode;
+} XINPUT_KEYSTROKE, *PXINPUT_KEYSTROKE;
+
+typedef struct _XINPUT_BATTERY_INFORMATION
+{
+    BYTE BatteryType;
+    BYTE BatteryLevel;
+} XINPUT_BATTERY_INFORMATION, *PXINPUT_BATTERY_INFORMATION;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void WINAPI XInputEnable(WINBOOL);
+DWORD WINAPI XInputSetState(DWORD, XINPUT_VIBRATION*);
+DWORD WINAPI XInputGetState(DWORD, XINPUT_STATE*);
+DWORD WINAPI XInputGetKeystroke(DWORD, DWORD, PXINPUT_KEYSTROKE);
+DWORD WINAPI XInputGetCapabilities(DWORD, DWORD, XINPUT_CAPABILITIES*);
+DWORD WINAPI XInputGetDSoundAudioDeviceGuids(DWORD, GUID*, GUID*);
+DWORD WINAPI XInputGetBatteryInformation(DWORD, BYTE, XINPUT_BATTERY_INFORMATION*);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __WINE_XINPUT_H */

ファイルの差分が大きいため隠しています
+ 25539 - 0
samples/third_party/glfw/deps/nuklear.h


+ 381 - 0
samples/third_party/glfw/deps/nuklear_glfw_gl2.h

@@ -0,0 +1,381 @@
+/*
+ * Nuklear - v1.32.0 - public domain
+ * no warrenty implied; use at your own risk.
+ * authored from 2015-2017 by Micha Mettke
+ */
+/*
+ * ==============================================================
+ *
+ *                              API
+ *
+ * ===============================================================
+ */
+#ifndef NK_GLFW_GL2_H_
+#define NK_GLFW_GL2_H_
+
+#include <GLFW/glfw3.h>
+
+enum nk_glfw_init_state{
+    NK_GLFW3_DEFAULT = 0,
+    NK_GLFW3_INSTALL_CALLBACKS
+};
+NK_API struct nk_context*   nk_glfw3_init(GLFWwindow *win, enum nk_glfw_init_state);
+NK_API void                 nk_glfw3_font_stash_begin(struct nk_font_atlas **atlas);
+NK_API void                 nk_glfw3_font_stash_end(void);
+
+NK_API void                 nk_glfw3_new_frame(void);
+NK_API void                 nk_glfw3_render(enum nk_anti_aliasing);
+NK_API void                 nk_glfw3_shutdown(void);
+
+NK_API void                 nk_glfw3_char_callback(GLFWwindow *win, unsigned int codepoint);
+NK_API void                 nk_gflw3_scroll_callback(GLFWwindow *win, double xoff, double yoff);
+
+#endif
+
+/*
+ * ==============================================================
+ *
+ *                          IMPLEMENTATION
+ *
+ * ===============================================================
+ */
+#ifdef NK_GLFW_GL2_IMPLEMENTATION
+
+#ifndef NK_GLFW_TEXT_MAX
+#define NK_GLFW_TEXT_MAX 256
+#endif
+#ifndef NK_GLFW_DOUBLE_CLICK_LO
+#define NK_GLFW_DOUBLE_CLICK_LO 0.02
+#endif
+#ifndef NK_GLFW_DOUBLE_CLICK_HI
+#define NK_GLFW_DOUBLE_CLICK_HI 0.2
+#endif
+
+struct nk_glfw_device {
+    struct nk_buffer cmds;
+    struct nk_draw_null_texture null;
+    GLuint font_tex;
+};
+
+struct nk_glfw_vertex {
+    float position[2];
+    float uv[2];
+    nk_byte col[4];
+};
+
+static struct nk_glfw {
+    GLFWwindow *win;
+    int width, height;
+    int display_width, display_height;
+    struct nk_glfw_device ogl;
+    struct nk_context ctx;
+    struct nk_font_atlas atlas;
+    struct nk_vec2 fb_scale;
+    unsigned int text[NK_GLFW_TEXT_MAX];
+    int text_len;
+    struct nk_vec2 scroll;
+    double last_button_click;
+    int is_double_click_down;
+    struct nk_vec2 double_click_pos;
+} glfw;
+
+NK_INTERN void
+nk_glfw3_device_upload_atlas(const void *image, int width, int height)
+{
+    struct nk_glfw_device *dev = &glfw.ogl;
+    glGenTextures(1, &dev->font_tex);
+    glBindTexture(GL_TEXTURE_2D, dev->font_tex);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)width, (GLsizei)height, 0,
+                GL_RGBA, GL_UNSIGNED_BYTE, image);
+}
+
+NK_API void
+nk_glfw3_render(enum nk_anti_aliasing AA)
+{
+    /* setup global state */
+    struct nk_glfw_device *dev = &glfw.ogl;
+    glPushAttrib(GL_ENABLE_BIT|GL_COLOR_BUFFER_BIT|GL_TRANSFORM_BIT);
+    glDisable(GL_CULL_FACE);
+    glDisable(GL_DEPTH_TEST);
+    glEnable(GL_SCISSOR_TEST);
+    glEnable(GL_BLEND);
+    glEnable(GL_TEXTURE_2D);
+    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+    /* setup viewport/project */
+    glViewport(0,0,(GLsizei)glfw.display_width,(GLsizei)glfw.display_height);
+    glMatrixMode(GL_PROJECTION);
+    glPushMatrix();
+    glLoadIdentity();
+    glOrtho(0.0f, glfw.width, glfw.height, 0.0f, -1.0f, 1.0f);
+    glMatrixMode(GL_MODELVIEW);
+    glPushMatrix();
+    glLoadIdentity();
+
+    glEnableClientState(GL_VERTEX_ARRAY);
+    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+    glEnableClientState(GL_COLOR_ARRAY);
+    {
+        GLsizei vs = sizeof(struct nk_glfw_vertex);
+        size_t vp = offsetof(struct nk_glfw_vertex, position);
+        size_t vt = offsetof(struct nk_glfw_vertex, uv);
+        size_t vc = offsetof(struct nk_glfw_vertex, col);
+
+        /* convert from command queue into draw list and draw to screen */
+        const struct nk_draw_command *cmd;
+        const nk_draw_index *offset = NULL;
+        struct nk_buffer vbuf, ebuf;
+
+        /* fill convert configuration */
+        struct nk_convert_config config;
+        static const struct nk_draw_vertex_layout_element vertex_layout[] = {
+            {NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_glfw_vertex, position)},
+            {NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_glfw_vertex, uv)},
+            {NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, NK_OFFSETOF(struct nk_glfw_vertex, col)},
+            {NK_VERTEX_LAYOUT_END}
+        };
+        NK_MEMSET(&config, 0, sizeof(config));
+        config.vertex_layout = vertex_layout;
+        config.vertex_size = sizeof(struct nk_glfw_vertex);
+        config.vertex_alignment = NK_ALIGNOF(struct nk_glfw_vertex);
+        config.null = dev->null;
+        config.circle_segment_count = 22;
+        config.curve_segment_count = 22;
+        config.arc_segment_count = 22;
+        config.global_alpha = 1.0f;
+        config.shape_AA = AA;
+        config.line_AA = AA;
+
+        /* convert shapes into vertexes */
+        nk_buffer_init_default(&vbuf);
+        nk_buffer_init_default(&ebuf);
+        nk_convert(&glfw.ctx, &dev->cmds, &vbuf, &ebuf, &config);
+
+        /* setup vertex buffer pointer */
+        {const void *vertices = nk_buffer_memory_const(&vbuf);
+        glVertexPointer(2, GL_FLOAT, vs, (const void*)((const nk_byte*)vertices + vp));
+        glTexCoordPointer(2, GL_FLOAT, vs, (const void*)((const nk_byte*)vertices + vt));
+        glColorPointer(4, GL_UNSIGNED_BYTE, vs, (const void*)((const nk_byte*)vertices + vc));}
+
+        /* iterate over and execute each draw command */
+        offset = (const nk_draw_index*)nk_buffer_memory_const(&ebuf);
+        nk_draw_foreach(cmd, &glfw.ctx, &dev->cmds)
+        {
+            if (!cmd->elem_count) continue;
+            glBindTexture(GL_TEXTURE_2D, (GLuint)cmd->texture.id);
+            glScissor(
+                (GLint)(cmd->clip_rect.x * glfw.fb_scale.x),
+                (GLint)((glfw.height - (GLint)(cmd->clip_rect.y + cmd->clip_rect.h)) * glfw.fb_scale.y),
+                (GLint)(cmd->clip_rect.w * glfw.fb_scale.x),
+                (GLint)(cmd->clip_rect.h * glfw.fb_scale.y));
+            glDrawElements(GL_TRIANGLES, (GLsizei)cmd->elem_count, GL_UNSIGNED_SHORT, offset);
+            offset += cmd->elem_count;
+        }
+        nk_clear(&glfw.ctx);
+        nk_buffer_free(&vbuf);
+        nk_buffer_free(&ebuf);
+    }
+
+    /* default OpenGL state */
+    glDisableClientState(GL_VERTEX_ARRAY);
+    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+    glDisableClientState(GL_COLOR_ARRAY);
+
+    glDisable(GL_CULL_FACE);
+    glDisable(GL_DEPTH_TEST);
+    glDisable(GL_SCISSOR_TEST);
+    glDisable(GL_BLEND);
+    glDisable(GL_TEXTURE_2D);
+
+    glBindTexture(GL_TEXTURE_2D, 0);
+    glMatrixMode(GL_MODELVIEW);
+    glPopMatrix();
+    glMatrixMode(GL_PROJECTION);
+    glPopMatrix();
+    glPopAttrib();
+}
+
+NK_API void
+nk_glfw3_char_callback(GLFWwindow *win, unsigned int codepoint)
+{
+    (void)win;
+    if (glfw.text_len < NK_GLFW_TEXT_MAX)
+        glfw.text[glfw.text_len++] = codepoint;
+}
+
+NK_API void
+nk_gflw3_scroll_callback(GLFWwindow *win, double xoff, double yoff)
+{
+    (void)win; (void)xoff;
+    glfw.scroll.x += (float)xoff;
+    glfw.scroll.y += (float)yoff;
+}
+
+NK_API void
+nk_glfw3_mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
+{
+    double x, y;
+    if (button != GLFW_MOUSE_BUTTON_LEFT) return;
+    glfwGetCursorPos(window, &x, &y);
+    if (action == GLFW_PRESS)  {
+        double dt = glfwGetTime() - glfw.last_button_click;
+        if (dt > NK_GLFW_DOUBLE_CLICK_LO && dt < NK_GLFW_DOUBLE_CLICK_HI) {
+            glfw.is_double_click_down = nk_true;
+            glfw.double_click_pos = nk_vec2((float)x, (float)y);
+        }
+        glfw.last_button_click = glfwGetTime();
+    } else glfw.is_double_click_down = nk_false;
+}
+
+NK_INTERN void
+nk_glfw3_clipbard_paste(nk_handle usr, struct nk_text_edit *edit)
+{
+    const char *text = glfwGetClipboardString(glfw.win);
+    if (text) nk_textedit_paste(edit, text, nk_strlen(text));
+    (void)usr;
+}
+
+NK_INTERN void
+nk_glfw3_clipbard_copy(nk_handle usr, const char *text, int len)
+{
+    char *str = 0;
+    (void)usr;
+    if (!len) return;
+    str = (char*)malloc((size_t)len+1);
+    if (!str) return;
+    NK_MEMCPY(str, text, (size_t)len);
+    str[len] = '\0';
+    glfwSetClipboardString(glfw.win, str);
+    free(str);
+}
+
+NK_API struct nk_context*
+nk_glfw3_init(GLFWwindow *win, enum nk_glfw_init_state init_state)
+{
+    glfw.win = win;
+    if (init_state == NK_GLFW3_INSTALL_CALLBACKS) {
+        glfwSetScrollCallback(win, nk_gflw3_scroll_callback);
+        glfwSetCharCallback(win, nk_glfw3_char_callback);
+        glfwSetMouseButtonCallback(win, nk_glfw3_mouse_button_callback);
+    }
+    nk_init_default(&glfw.ctx, 0);
+    glfw.ctx.clip.copy = nk_glfw3_clipbard_copy;
+    glfw.ctx.clip.paste = nk_glfw3_clipbard_paste;
+    glfw.ctx.clip.userdata = nk_handle_ptr(0);
+    nk_buffer_init_default(&glfw.ogl.cmds);
+
+    glfw.is_double_click_down = nk_false;
+    glfw.double_click_pos = nk_vec2(0, 0);
+
+    return &glfw.ctx;
+}
+
+NK_API void
+nk_glfw3_font_stash_begin(struct nk_font_atlas **atlas)
+{
+    nk_font_atlas_init_default(&glfw.atlas);
+    nk_font_atlas_begin(&glfw.atlas);
+    *atlas = &glfw.atlas;
+}
+
+NK_API void
+nk_glfw3_font_stash_end(void)
+{
+    const void *image; int w, h;
+    image = nk_font_atlas_bake(&glfw.atlas, &w, &h, NK_FONT_ATLAS_RGBA32);
+    nk_glfw3_device_upload_atlas(image, w, h);
+    nk_font_atlas_end(&glfw.atlas, nk_handle_id((int)glfw.ogl.font_tex), &glfw.ogl.null);
+    if (glfw.atlas.default_font)
+        nk_style_set_font(&glfw.ctx, &glfw.atlas.default_font->handle);
+}
+
+NK_API void
+nk_glfw3_new_frame(void)
+{
+    int i;
+    double x, y;
+    struct nk_context *ctx = &glfw.ctx;
+    struct GLFWwindow *win = glfw.win;
+
+    glfwGetWindowSize(win, &glfw.width, &glfw.height);
+    glfwGetFramebufferSize(win, &glfw.display_width, &glfw.display_height);
+    glfw.fb_scale.x = (float)glfw.display_width/(float)glfw.width;
+    glfw.fb_scale.y = (float)glfw.display_height/(float)glfw.height;
+
+    nk_input_begin(ctx);
+    for (i = 0; i < glfw.text_len; ++i)
+        nk_input_unicode(ctx, glfw.text[i]);
+
+    /* optional grabbing behavior */
+    if (ctx->input.mouse.grab)
+        glfwSetInputMode(glfw.win, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
+    else if (ctx->input.mouse.ungrab)
+        glfwSetInputMode(glfw.win, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
+
+    nk_input_key(ctx, NK_KEY_DEL, glfwGetKey(win, GLFW_KEY_DELETE) == GLFW_PRESS);
+    nk_input_key(ctx, NK_KEY_ENTER, glfwGetKey(win, GLFW_KEY_ENTER) == GLFW_PRESS);
+    nk_input_key(ctx, NK_KEY_TAB, glfwGetKey(win, GLFW_KEY_TAB) == GLFW_PRESS);
+    nk_input_key(ctx, NK_KEY_BACKSPACE, glfwGetKey(win, GLFW_KEY_BACKSPACE) == GLFW_PRESS);
+    nk_input_key(ctx, NK_KEY_UP, glfwGetKey(win, GLFW_KEY_UP) == GLFW_PRESS);
+    nk_input_key(ctx, NK_KEY_DOWN, glfwGetKey(win, GLFW_KEY_DOWN) == GLFW_PRESS);
+    nk_input_key(ctx, NK_KEY_TEXT_START, glfwGetKey(win, GLFW_KEY_HOME) == GLFW_PRESS);
+    nk_input_key(ctx, NK_KEY_TEXT_END, glfwGetKey(win, GLFW_KEY_END) == GLFW_PRESS);
+    nk_input_key(ctx, NK_KEY_SCROLL_START, glfwGetKey(win, GLFW_KEY_HOME) == GLFW_PRESS);
+    nk_input_key(ctx, NK_KEY_SCROLL_END, glfwGetKey(win, GLFW_KEY_END) == GLFW_PRESS);
+    nk_input_key(ctx, NK_KEY_SCROLL_DOWN, glfwGetKey(win, GLFW_KEY_PAGE_DOWN) == GLFW_PRESS);
+    nk_input_key(ctx, NK_KEY_SCROLL_UP, glfwGetKey(win, GLFW_KEY_PAGE_UP) == GLFW_PRESS);
+    nk_input_key(ctx, NK_KEY_SHIFT, glfwGetKey(win, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS||
+                                    glfwGetKey(win, GLFW_KEY_RIGHT_SHIFT) == GLFW_PRESS);
+
+    if (glfwGetKey(win, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS ||
+        glfwGetKey(win, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS) {
+        nk_input_key(ctx, NK_KEY_COPY, glfwGetKey(win, GLFW_KEY_C) == GLFW_PRESS);
+        nk_input_key(ctx, NK_KEY_PASTE, glfwGetKey(win, GLFW_KEY_V) == GLFW_PRESS);
+        nk_input_key(ctx, NK_KEY_CUT, glfwGetKey(win, GLFW_KEY_X) == GLFW_PRESS);
+        nk_input_key(ctx, NK_KEY_TEXT_UNDO, glfwGetKey(win, GLFW_KEY_Z) == GLFW_PRESS);
+        nk_input_key(ctx, NK_KEY_TEXT_REDO, glfwGetKey(win, GLFW_KEY_R) == GLFW_PRESS);
+        nk_input_key(ctx, NK_KEY_TEXT_WORD_LEFT, glfwGetKey(win, GLFW_KEY_LEFT) == GLFW_PRESS);
+        nk_input_key(ctx, NK_KEY_TEXT_WORD_RIGHT, glfwGetKey(win, GLFW_KEY_RIGHT) == GLFW_PRESS);
+        nk_input_key(ctx, NK_KEY_TEXT_LINE_START, glfwGetKey(win, GLFW_KEY_B) == GLFW_PRESS);
+        nk_input_key(ctx, NK_KEY_TEXT_LINE_END, glfwGetKey(win, GLFW_KEY_E) == GLFW_PRESS);
+    } else {
+        nk_input_key(ctx, NK_KEY_LEFT, glfwGetKey(win, GLFW_KEY_LEFT) == GLFW_PRESS);
+        nk_input_key(ctx, NK_KEY_RIGHT, glfwGetKey(win, GLFW_KEY_RIGHT) == GLFW_PRESS);
+        nk_input_key(ctx, NK_KEY_COPY, 0);
+        nk_input_key(ctx, NK_KEY_PASTE, 0);
+        nk_input_key(ctx, NK_KEY_CUT, 0);
+        nk_input_key(ctx, NK_KEY_SHIFT, 0);
+    }
+
+    glfwGetCursorPos(win, &x, &y);
+    nk_input_motion(ctx, (int)x, (int)y);
+    if (ctx->input.mouse.grabbed) {
+        glfwSetCursorPos(glfw.win, (double)ctx->input.mouse.prev.x, (double)ctx->input.mouse.prev.y);
+        ctx->input.mouse.pos.x = ctx->input.mouse.prev.x;
+        ctx->input.mouse.pos.y = ctx->input.mouse.prev.y;
+    }
+
+    nk_input_button(ctx, NK_BUTTON_LEFT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS);
+    nk_input_button(ctx, NK_BUTTON_MIDDLE, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_MIDDLE) == GLFW_PRESS);
+    nk_input_button(ctx, NK_BUTTON_RIGHT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS);
+    nk_input_button(ctx, NK_BUTTON_DOUBLE, (int)glfw.double_click_pos.x, (int)glfw.double_click_pos.y, glfw.is_double_click_down);
+    nk_input_scroll(ctx, glfw.scroll);
+    nk_input_end(&glfw.ctx);
+    glfw.text_len = 0;
+    glfw.scroll = nk_vec2(0,0);
+}
+
+NK_API
+void nk_glfw3_shutdown(void)
+{
+    struct nk_glfw_device *dev = &glfw.ogl;
+    nk_font_atlas_clear(&glfw.atlas);
+    nk_free(&glfw.ctx);
+    glDeleteTextures(1, &dev->font_tex);
+    nk_buffer_free(&dev->cmds);
+    NK_MEMSET(&glfw, 0, sizeof(glfw));
+}
+
+#endif

ファイルの差分が大きいため隠しています
+ 1048 - 0
samples/third_party/glfw/deps/stb_image_write.h


+ 594 - 0
samples/third_party/glfw/deps/tinycthread.c

@@ -0,0 +1,594 @@
+/* -*- mode: c; tab-width: 2; indent-tabs-mode: nil; -*-
+Copyright (c) 2012 Marcus Geelnard
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not
+    claim that you wrote the original software. If you use this software
+    in a product, an acknowledgment in the product documentation would be
+    appreciated but is not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be
+    misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source
+    distribution.
+*/
+
+/* 2013-01-06 Camilla Löwy <elmindreda@glfw.org>
+ *
+ * Added casts from time_t to DWORD to avoid warnings on VC++.
+ * Fixed time retrieval on POSIX systems.
+ */
+
+#include "tinycthread.h"
+#include <stdlib.h>
+
+/* Platform specific includes */
+#if defined(_TTHREAD_POSIX_)
+  #include <signal.h>
+  #include <sched.h>
+  #include <unistd.h>
+  #include <sys/time.h>
+  #include <errno.h>
+#elif defined(_TTHREAD_WIN32_)
+  #include <process.h>
+  #include <sys/timeb.h>
+#endif
+
+/* Standard, good-to-have defines */
+#ifndef NULL
+  #define NULL (void*)0
+#endif
+#ifndef TRUE
+  #define TRUE 1
+#endif
+#ifndef FALSE
+  #define FALSE 0
+#endif
+
+int mtx_init(mtx_t *mtx, int type)
+{
+#if defined(_TTHREAD_WIN32_)
+  mtx->mAlreadyLocked = FALSE;
+  mtx->mRecursive = type & mtx_recursive;
+  InitializeCriticalSection(&mtx->mHandle);
+  return thrd_success;
+#else
+  int ret;
+  pthread_mutexattr_t attr;
+  pthread_mutexattr_init(&attr);
+  if (type & mtx_recursive)
+  {
+    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+  }
+  ret = pthread_mutex_init(mtx, &attr);
+  pthread_mutexattr_destroy(&attr);
+  return ret == 0 ? thrd_success : thrd_error;
+#endif
+}
+
+void mtx_destroy(mtx_t *mtx)
+{
+#if defined(_TTHREAD_WIN32_)
+  DeleteCriticalSection(&mtx->mHandle);
+#else
+  pthread_mutex_destroy(mtx);
+#endif
+}
+
+int mtx_lock(mtx_t *mtx)
+{
+#if defined(_TTHREAD_WIN32_)
+  EnterCriticalSection(&mtx->mHandle);
+  if (!mtx->mRecursive)
+  {
+    while(mtx->mAlreadyLocked) Sleep(1000); /* Simulate deadlock... */
+    mtx->mAlreadyLocked = TRUE;
+  }
+  return thrd_success;
+#else
+  return pthread_mutex_lock(mtx) == 0 ? thrd_success : thrd_error;
+#endif
+}
+
+int mtx_timedlock(mtx_t *mtx, const struct timespec *ts)
+{
+  /* FIXME! */
+  (void)mtx;
+  (void)ts;
+  return thrd_error;
+}
+
+int mtx_trylock(mtx_t *mtx)
+{
+#if defined(_TTHREAD_WIN32_)
+  int ret = TryEnterCriticalSection(&mtx->mHandle) ? thrd_success : thrd_busy;
+  if ((!mtx->mRecursive) && (ret == thrd_success) && mtx->mAlreadyLocked)
+  {
+    LeaveCriticalSection(&mtx->mHandle);
+    ret = thrd_busy;
+  }
+  return ret;
+#else
+  return (pthread_mutex_trylock(mtx) == 0) ? thrd_success : thrd_busy;
+#endif
+}
+
+int mtx_unlock(mtx_t *mtx)
+{
+#if defined(_TTHREAD_WIN32_)
+  mtx->mAlreadyLocked = FALSE;
+  LeaveCriticalSection(&mtx->mHandle);
+  return thrd_success;
+#else
+  return pthread_mutex_unlock(mtx) == 0 ? thrd_success : thrd_error;;
+#endif
+}
+
+#if defined(_TTHREAD_WIN32_)
+#define _CONDITION_EVENT_ONE 0
+#define _CONDITION_EVENT_ALL 1
+#endif
+
+int cnd_init(cnd_t *cond)
+{
+#if defined(_TTHREAD_WIN32_)
+  cond->mWaitersCount = 0;
+
+  /* Init critical section */
+  InitializeCriticalSection(&cond->mWaitersCountLock);
+
+  /* Init events */
+  cond->mEvents[_CONDITION_EVENT_ONE] = CreateEvent(NULL, FALSE, FALSE, NULL);
+  if (cond->mEvents[_CONDITION_EVENT_ONE] == NULL)
+  {
+    cond->mEvents[_CONDITION_EVENT_ALL] = NULL;
+    return thrd_error;
+  }
+  cond->mEvents[_CONDITION_EVENT_ALL] = CreateEvent(NULL, TRUE, FALSE, NULL);
+  if (cond->mEvents[_CONDITION_EVENT_ALL] == NULL)
+  {
+    CloseHandle(cond->mEvents[_CONDITION_EVENT_ONE]);
+    cond->mEvents[_CONDITION_EVENT_ONE] = NULL;
+    return thrd_error;
+  }
+
+  return thrd_success;
+#else
+  return pthread_cond_init(cond, NULL) == 0 ? thrd_success : thrd_error;
+#endif
+}
+
+void cnd_destroy(cnd_t *cond)
+{
+#if defined(_TTHREAD_WIN32_)
+  if (cond->mEvents[_CONDITION_EVENT_ONE] != NULL)
+  {
+    CloseHandle(cond->mEvents[_CONDITION_EVENT_ONE]);
+  }
+  if (cond->mEvents[_CONDITION_EVENT_ALL] != NULL)
+  {
+    CloseHandle(cond->mEvents[_CONDITION_EVENT_ALL]);
+  }
+  DeleteCriticalSection(&cond->mWaitersCountLock);
+#else
+  pthread_cond_destroy(cond);
+#endif
+}
+
+int cnd_signal(cnd_t *cond)
+{
+#if defined(_TTHREAD_WIN32_)
+  int haveWaiters;
+
+  /* Are there any waiters? */
+  EnterCriticalSection(&cond->mWaitersCountLock);
+  haveWaiters = (cond->mWaitersCount > 0);
+  LeaveCriticalSection(&cond->mWaitersCountLock);
+
+  /* If we have any waiting threads, send them a signal */
+  if(haveWaiters)
+  {
+    if (SetEvent(cond->mEvents[_CONDITION_EVENT_ONE]) == 0)
+    {
+      return thrd_error;
+    }
+  }
+
+  return thrd_success;
+#else
+  return pthread_cond_signal(cond) == 0 ? thrd_success : thrd_error;
+#endif
+}
+
+int cnd_broadcast(cnd_t *cond)
+{
+#if defined(_TTHREAD_WIN32_)
+  int haveWaiters;
+
+  /* Are there any waiters? */
+  EnterCriticalSection(&cond->mWaitersCountLock);
+  haveWaiters = (cond->mWaitersCount > 0);
+  LeaveCriticalSection(&cond->mWaitersCountLock);
+
+  /* If we have any waiting threads, send them a signal */
+  if(haveWaiters)
+  {
+    if (SetEvent(cond->mEvents[_CONDITION_EVENT_ALL]) == 0)
+    {
+      return thrd_error;
+    }
+  }
+
+  return thrd_success;
+#else
+  return pthread_cond_signal(cond) == 0 ? thrd_success : thrd_error;
+#endif
+}
+
+#if defined(_TTHREAD_WIN32_)
+static int _cnd_timedwait_win32(cnd_t *cond, mtx_t *mtx, DWORD timeout)
+{
+  int result, lastWaiter;
+
+  /* Increment number of waiters */
+  EnterCriticalSection(&cond->mWaitersCountLock);
+  ++ cond->mWaitersCount;
+  LeaveCriticalSection(&cond->mWaitersCountLock);
+
+  /* Release the mutex while waiting for the condition (will decrease
+     the number of waiters when done)... */
+  mtx_unlock(mtx);
+
+  /* Wait for either event to become signaled due to cnd_signal() or
+     cnd_broadcast() being called */
+  result = WaitForMultipleObjects(2, cond->mEvents, FALSE, timeout);
+  if (result == WAIT_TIMEOUT)
+  {
+    return thrd_timeout;
+  }
+  else if (result == (int)WAIT_FAILED)
+  {
+    return thrd_error;
+  }
+
+  /* Check if we are the last waiter */
+  EnterCriticalSection(&cond->mWaitersCountLock);
+  -- cond->mWaitersCount;
+  lastWaiter = (result == (WAIT_OBJECT_0 + _CONDITION_EVENT_ALL)) &&
+               (cond->mWaitersCount == 0);
+  LeaveCriticalSection(&cond->mWaitersCountLock);
+
+  /* If we are the last waiter to be notified to stop waiting, reset the event */
+  if (lastWaiter)
+  {
+    if (ResetEvent(cond->mEvents[_CONDITION_EVENT_ALL]) == 0)
+    {
+      return thrd_error;
+    }
+  }
+
+  /* Re-acquire the mutex */
+  mtx_lock(mtx);
+
+  return thrd_success;
+}
+#endif
+
+int cnd_wait(cnd_t *cond, mtx_t *mtx)
+{
+#if defined(_TTHREAD_WIN32_)
+  return _cnd_timedwait_win32(cond, mtx, INFINITE);
+#else
+  return pthread_cond_wait(cond, mtx) == 0 ? thrd_success : thrd_error;
+#endif
+}
+
+int cnd_timedwait(cnd_t *cond, mtx_t *mtx, const struct timespec *ts)
+{
+#if defined(_TTHREAD_WIN32_)
+  struct timespec now;
+  if (clock_gettime(CLOCK_REALTIME, &now) == 0)
+  {
+    DWORD delta = (DWORD) ((ts->tv_sec - now.tv_sec) * 1000 +
+                           (ts->tv_nsec - now.tv_nsec + 500000) / 1000000);
+    return _cnd_timedwait_win32(cond, mtx, delta);
+  }
+  else
+    return thrd_error;
+#else
+  int ret;
+  ret = pthread_cond_timedwait(cond, mtx, ts);
+  if (ret == ETIMEDOUT)
+  {
+    return thrd_timeout;
+  }
+  return ret == 0 ? thrd_success : thrd_error;
+#endif
+}
+
+
+/** Information to pass to the new thread (what to run). */
+typedef struct {
+  thrd_start_t mFunction; /**< Pointer to the function to be executed. */
+  void * mArg;            /**< Function argument for the thread function. */
+} _thread_start_info;
+
+/* Thread wrapper function. */
+#if defined(_TTHREAD_WIN32_)
+static unsigned WINAPI _thrd_wrapper_function(void * aArg)
+#elif defined(_TTHREAD_POSIX_)
+static void * _thrd_wrapper_function(void * aArg)
+#endif
+{
+  thrd_start_t fun;
+  void *arg;
+  int  res;
+#if defined(_TTHREAD_POSIX_)
+  void *pres;
+#endif
+
+  /* Get thread startup information */
+  _thread_start_info *ti = (_thread_start_info *) aArg;
+  fun = ti->mFunction;
+  arg = ti->mArg;
+
+  /* The thread is responsible for freeing the startup information */
+  free((void *)ti);
+
+  /* Call the actual client thread function */
+  res = fun(arg);
+
+#if defined(_TTHREAD_WIN32_)
+  return res;
+#else
+  pres = malloc(sizeof(int));
+  if (pres != NULL)
+  {
+    *(int*)pres = res;
+  }
+  return pres;
+#endif
+}
+
+int thrd_create(thrd_t *thr, thrd_start_t func, void *arg)
+{
+  /* Fill out the thread startup information (passed to the thread wrapper,
+     which will eventually free it) */
+  _thread_start_info* ti = (_thread_start_info*)malloc(sizeof(_thread_start_info));
+  if (ti == NULL)
+  {
+    return thrd_nomem;
+  }
+  ti->mFunction = func;
+  ti->mArg = arg;
+
+  /* Create the thread */
+#if defined(_TTHREAD_WIN32_)
+  *thr = (HANDLE)_beginthreadex(NULL, 0, _thrd_wrapper_function, (void *)ti, 0, NULL);
+#elif defined(_TTHREAD_POSIX_)
+  if(pthread_create(thr, NULL, _thrd_wrapper_function, (void *)ti) != 0)
+  {
+    *thr = 0;
+  }
+#endif
+
+  /* Did we fail to create the thread? */
+  if(!*thr)
+  {
+    free(ti);
+    return thrd_error;
+  }
+
+  return thrd_success;
+}
+
+thrd_t thrd_current(void)
+{
+#if defined(_TTHREAD_WIN32_)
+  return GetCurrentThread();
+#else
+  return pthread_self();
+#endif
+}
+
+int thrd_detach(thrd_t thr)
+{
+  /* FIXME! */
+  (void)thr;
+  return thrd_error;
+}
+
+int thrd_equal(thrd_t thr0, thrd_t thr1)
+{
+#if defined(_TTHREAD_WIN32_)
+  return thr0 == thr1;
+#else
+  return pthread_equal(thr0, thr1);
+#endif
+}
+
+void thrd_exit(int res)
+{
+#if defined(_TTHREAD_WIN32_)
+  ExitThread(res);
+#else
+  void *pres = malloc(sizeof(int));
+  if (pres != NULL)
+  {
+    *(int*)pres = res;
+  }
+  pthread_exit(pres);
+#endif
+}
+
+int thrd_join(thrd_t thr, int *res)
+{
+#if defined(_TTHREAD_WIN32_)
+  if (WaitForSingleObject(thr, INFINITE) == WAIT_FAILED)
+  {
+    return thrd_error;
+  }
+  if (res != NULL)
+  {
+    DWORD dwRes;
+    GetExitCodeThread(thr, &dwRes);
+    *res = dwRes;
+  }
+#elif defined(_TTHREAD_POSIX_)
+  void *pres;
+  int ires = 0;
+  if (pthread_join(thr, &pres) != 0)
+  {
+    return thrd_error;
+  }
+  if (pres != NULL)
+  {
+    ires = *(int*)pres;
+    free(pres);
+  }
+  if (res != NULL)
+  {
+    *res = ires;
+  }
+#endif
+  return thrd_success;
+}
+
+int thrd_sleep(const struct timespec *time_point, struct timespec *remaining)
+{
+  struct timespec now;
+#if defined(_TTHREAD_WIN32_)
+  DWORD delta;
+#else
+  long delta;
+#endif
+
+  /* Get the current time */
+  if (clock_gettime(CLOCK_REALTIME, &now) != 0)
+    return -2;  // FIXME: Some specific error code?
+
+#if defined(_TTHREAD_WIN32_)
+  /* Delta in milliseconds */
+  delta = (DWORD) ((time_point->tv_sec - now.tv_sec) * 1000 +
+                   (time_point->tv_nsec - now.tv_nsec + 500000) / 1000000);
+  if (delta > 0)
+  {
+    Sleep(delta);
+  }
+#else
+  /* Delta in microseconds */
+  delta = (time_point->tv_sec - now.tv_sec) * 1000000L +
+          (time_point->tv_nsec - now.tv_nsec + 500L) / 1000L;
+
+  /* On some systems, the usleep argument must be < 1000000 */
+  while (delta > 999999L)
+  {
+    usleep(999999);
+    delta -= 999999L;
+  }
+  if (delta > 0L)
+  {
+    usleep((useconds_t)delta);
+  }
+#endif
+
+  /* We don't support waking up prematurely (yet) */
+  if (remaining)
+  {
+    remaining->tv_sec = 0;
+    remaining->tv_nsec = 0;
+  }
+  return 0;
+}
+
+void thrd_yield(void)
+{
+#if defined(_TTHREAD_WIN32_)
+  Sleep(0);
+#else
+  sched_yield();
+#endif
+}
+
+int tss_create(tss_t *key, tss_dtor_t dtor)
+{
+#if defined(_TTHREAD_WIN32_)
+  /* FIXME: The destructor function is not supported yet... */
+  if (dtor != NULL)
+  {
+    return thrd_error;
+  }
+  *key = TlsAlloc();
+  if (*key == TLS_OUT_OF_INDEXES)
+  {
+    return thrd_error;
+  }
+#else
+  if (pthread_key_create(key, dtor) != 0)
+  {
+    return thrd_error;
+  }
+#endif
+  return thrd_success;
+}
+
+void tss_delete(tss_t key)
+{
+#if defined(_TTHREAD_WIN32_)
+  TlsFree(key);
+#else
+  pthread_key_delete(key);
+#endif
+}
+
+void *tss_get(tss_t key)
+{
+#if defined(_TTHREAD_WIN32_)
+  return TlsGetValue(key);
+#else
+  return pthread_getspecific(key);
+#endif
+}
+
+int tss_set(tss_t key, void *val)
+{
+#if defined(_TTHREAD_WIN32_)
+  if (TlsSetValue(key, val) == 0)
+  {
+    return thrd_error;
+  }
+#else
+  if (pthread_setspecific(key, val) != 0)
+  {
+    return thrd_error;
+  }
+#endif
+  return thrd_success;
+}
+
+#if defined(_TTHREAD_EMULATE_CLOCK_GETTIME_)
+int _tthread_clock_gettime(clockid_t clk_id, struct timespec *ts)
+{
+#if defined(_TTHREAD_WIN32_)
+  struct _timeb tb;
+  _ftime(&tb);
+  ts->tv_sec = (time_t)tb.time;
+  ts->tv_nsec = 1000000L * (long)tb.millitm;
+#else
+  struct timeval tv;
+  gettimeofday(&tv, NULL);
+  ts->tv_sec = (time_t)tv.tv_sec;
+  ts->tv_nsec = 1000L * (long)tv.tv_usec;
+#endif
+  return 0;
+}
+#endif // _TTHREAD_EMULATE_CLOCK_GETTIME_
+

+ 443 - 0
samples/third_party/glfw/deps/tinycthread.h

@@ -0,0 +1,443 @@
+/* -*- mode: c; tab-width: 2; indent-tabs-mode: nil; -*-
+Copyright (c) 2012 Marcus Geelnard
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not
+    claim that you wrote the original software. If you use this software
+    in a product, an acknowledgment in the product documentation would be
+    appreciated but is not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be
+    misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source
+    distribution.
+*/
+
+#ifndef _TINYCTHREAD_H_
+#define _TINYCTHREAD_H_
+
+/**
+* @file
+* @mainpage TinyCThread API Reference
+*
+* @section intro_sec Introduction
+* TinyCThread is a minimal, portable implementation of basic threading
+* classes for C.
+*
+* They closely mimic the functionality and naming of the C11 standard, and
+* should be easily replaceable with the corresponding standard variants.
+*
+* @section port_sec Portability
+* The Win32 variant uses the native Win32 API for implementing the thread
+* classes, while for other systems, the POSIX threads API (pthread) is used.
+*
+* @section misc_sec Miscellaneous
+* The following special keywords are available: #_Thread_local.
+*
+* For more detailed information, browse the different sections of this
+* documentation. A good place to start is:
+* tinycthread.h.
+*/
+
+/* Which platform are we on? */
+#if !defined(_TTHREAD_PLATFORM_DEFINED_)
+  #if defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__)
+    #define _TTHREAD_WIN32_
+  #else
+    #define _TTHREAD_POSIX_
+  #endif
+  #define _TTHREAD_PLATFORM_DEFINED_
+#endif
+
+/* Activate some POSIX functionality (e.g. clock_gettime and recursive mutexes) */
+#if defined(_TTHREAD_POSIX_)
+  #undef _FEATURES_H
+  #if !defined(_GNU_SOURCE)
+    #define _GNU_SOURCE
+  #endif
+  #if !defined(_POSIX_C_SOURCE) || ((_POSIX_C_SOURCE - 0) < 199309L)
+    #undef _POSIX_C_SOURCE
+    #define _POSIX_C_SOURCE 199309L
+  #endif
+  #if !defined(_XOPEN_SOURCE) || ((_XOPEN_SOURCE - 0) < 500)
+    #undef _XOPEN_SOURCE
+    #define _XOPEN_SOURCE 500
+  #endif
+#endif
+
+/* Generic includes */
+#include <time.h>
+
+/* Platform specific includes */
+#if defined(_TTHREAD_POSIX_)
+  #include <sys/time.h>
+  #include <pthread.h>
+#elif defined(_TTHREAD_WIN32_)
+  #ifndef WIN32_LEAN_AND_MEAN
+    #define WIN32_LEAN_AND_MEAN
+    #define __UNDEF_LEAN_AND_MEAN
+  #endif
+  #include <windows.h>
+  #ifdef __UNDEF_LEAN_AND_MEAN
+    #undef WIN32_LEAN_AND_MEAN
+    #undef __UNDEF_LEAN_AND_MEAN
+  #endif
+#endif
+
+/* Workaround for missing TIME_UTC: If time.h doesn't provide TIME_UTC,
+   it's quite likely that libc does not support it either. Hence, fall back to
+   the only other supported time specifier: CLOCK_REALTIME (and if that fails,
+   we're probably emulating clock_gettime anyway, so anything goes). */
+#ifndef TIME_UTC
+  #ifdef CLOCK_REALTIME
+    #define TIME_UTC CLOCK_REALTIME
+  #else
+    #define TIME_UTC 0
+  #endif
+#endif
+
+/* Workaround for missing clock_gettime (most Windows compilers, afaik) */
+#if defined(_TTHREAD_WIN32_) || defined(__APPLE_CC__)
+#define _TTHREAD_EMULATE_CLOCK_GETTIME_
+/* Emulate struct timespec */
+#if defined(_TTHREAD_WIN32_)
+struct _ttherad_timespec {
+  time_t tv_sec;
+  long   tv_nsec;
+};
+#define timespec _ttherad_timespec
+#endif
+
+/* Emulate clockid_t */
+typedef int _tthread_clockid_t;
+#define clockid_t _tthread_clockid_t
+
+/* Emulate clock_gettime */
+int _tthread_clock_gettime(clockid_t clk_id, struct timespec *ts);
+#define clock_gettime _tthread_clock_gettime
+#ifndef CLOCK_REALTIME
+  #define CLOCK_REALTIME 0
+#endif
+#endif
+
+
+/** TinyCThread version (major number). */
+#define TINYCTHREAD_VERSION_MAJOR 1
+/** TinyCThread version (minor number). */
+#define TINYCTHREAD_VERSION_MINOR 1
+/** TinyCThread version (full version). */
+#define TINYCTHREAD_VERSION (TINYCTHREAD_VERSION_MAJOR * 100 + TINYCTHREAD_VERSION_MINOR)
+
+/**
+* @def _Thread_local
+* Thread local storage keyword.
+* A variable that is declared with the @c _Thread_local keyword makes the
+* value of the variable local to each thread (known as thread-local storage,
+* or TLS). Example usage:
+* @code
+* // This variable is local to each thread.
+* _Thread_local int variable;
+* @endcode
+* @note The @c _Thread_local keyword is a macro that maps to the corresponding
+* compiler directive (e.g. @c __declspec(thread)).
+* @note This directive is currently not supported on Mac OS X (it will give
+* a compiler error), since compile-time TLS is not supported in the Mac OS X
+* executable format. Also, some older versions of MinGW (before GCC 4.x) do
+* not support this directive.
+* @hideinitializer
+*/
+
+/* FIXME: Check for a PROPER value of __STDC_VERSION__ to know if we have C11 */
+#if !(defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201102L)) && !defined(_Thread_local)
+ #if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_CC) || defined(__IBMCPP__)
+  #define _Thread_local __thread
+ #else
+  #define _Thread_local __declspec(thread)
+ #endif
+#endif
+
+/* Macros */
+#define TSS_DTOR_ITERATIONS 0
+
+/* Function return values */
+#define thrd_error    0 /**< The requested operation failed */
+#define thrd_success  1 /**< The requested operation succeeded */
+#define thrd_timeout  2 /**< The time specified in the call was reached without acquiring the requested resource */
+#define thrd_busy     3 /**< The requested operation failed because a tesource requested by a test and return function is already in use */
+#define thrd_nomem    4 /**< The requested operation failed because it was unable to allocate memory */
+
+/* Mutex types */
+#define mtx_plain     1
+#define mtx_timed     2
+#define mtx_try       4
+#define mtx_recursive 8
+
+/* Mutex */
+#if defined(_TTHREAD_WIN32_)
+typedef struct {
+  CRITICAL_SECTION mHandle;   /* Critical section handle */
+  int mAlreadyLocked;         /* TRUE if the mutex is already locked */
+  int mRecursive;             /* TRUE if the mutex is recursive */
+} mtx_t;
+#else
+typedef pthread_mutex_t mtx_t;
+#endif
+
+/** Create a mutex object.
+* @param mtx A mutex object.
+* @param type Bit-mask that must have one of the following six values:
+*   @li @c mtx_plain for a simple non-recursive mutex
+*   @li @c mtx_timed for a non-recursive mutex that supports timeout
+*   @li @c mtx_try for a non-recursive mutex that supports test and return
+*   @li @c mtx_plain | @c mtx_recursive (same as @c mtx_plain, but recursive)
+*   @li @c mtx_timed | @c mtx_recursive (same as @c mtx_timed, but recursive)
+*   @li @c mtx_try | @c mtx_recursive (same as @c mtx_try, but recursive)
+* @return @ref thrd_success on success, or @ref thrd_error if the request could
+* not be honored.
+*/
+int mtx_init(mtx_t *mtx, int type);
+
+/** Release any resources used by the given mutex.
+* @param mtx A mutex object.
+*/
+void mtx_destroy(mtx_t *mtx);
+
+/** Lock the given mutex.
+* Blocks until the given mutex can be locked. If the mutex is non-recursive, and
+* the calling thread already has a lock on the mutex, this call will block
+* forever.
+* @param mtx A mutex object.
+* @return @ref thrd_success on success, or @ref thrd_error if the request could
+* not be honored.
+*/
+int mtx_lock(mtx_t *mtx);
+
+/** NOT YET IMPLEMENTED.
+*/
+int mtx_timedlock(mtx_t *mtx, const struct timespec *ts);
+
+/** Try to lock the given mutex.
+* The specified mutex shall support either test and return or timeout. If the
+* mutex is already locked, the function returns without blocking.
+* @param mtx A mutex object.
+* @return @ref thrd_success on success, or @ref thrd_busy if the resource
+* requested is already in use, or @ref thrd_error if the request could not be
+* honored.
+*/
+int mtx_trylock(mtx_t *mtx);
+
+/** Unlock the given mutex.
+* @param mtx A mutex object.
+* @return @ref thrd_success on success, or @ref thrd_error if the request could
+* not be honored.
+*/
+int mtx_unlock(mtx_t *mtx);
+
+/* Condition variable */
+#if defined(_TTHREAD_WIN32_)
+typedef struct {
+  HANDLE mEvents[2];                  /* Signal and broadcast event HANDLEs. */
+  unsigned int mWaitersCount;         /* Count of the number of waiters. */
+  CRITICAL_SECTION mWaitersCountLock; /* Serialize access to mWaitersCount. */
+} cnd_t;
+#else
+typedef pthread_cond_t cnd_t;
+#endif
+
+/** Create a condition variable object.
+* @param cond A condition variable object.
+* @return @ref thrd_success on success, or @ref thrd_error if the request could
+* not be honored.
+*/
+int cnd_init(cnd_t *cond);
+
+/** Release any resources used by the given condition variable.
+* @param cond A condition variable object.
+*/
+void cnd_destroy(cnd_t *cond);
+
+/** Signal a condition variable.
+* Unblocks one of the threads that are blocked on the given condition variable
+* at the time of the call. If no threads are blocked on the condition variable
+* at the time of the call, the function does nothing and return success.
+* @param cond A condition variable object.
+* @return @ref thrd_success on success, or @ref thrd_error if the request could
+* not be honored.
+*/
+int cnd_signal(cnd_t *cond);
+
+/** Broadcast a condition variable.
+* Unblocks all of the threads that are blocked on the given condition variable
+* at the time of the call. If no threads are blocked on the condition variable
+* at the time of the call, the function does nothing and return success.
+* @param cond A condition variable object.
+* @return @ref thrd_success on success, or @ref thrd_error if the request could
+* not be honored.
+*/
+int cnd_broadcast(cnd_t *cond);
+
+/** Wait for a condition variable to become signaled.
+* The function atomically unlocks the given mutex and endeavors to block until
+* the given condition variable is signaled by a call to cnd_signal or to
+* cnd_broadcast. When the calling thread becomes unblocked it locks the mutex
+* before it returns.
+* @param cond A condition variable object.
+* @param mtx A mutex object.
+* @return @ref thrd_success on success, or @ref thrd_error if the request could
+* not be honored.
+*/
+int cnd_wait(cnd_t *cond, mtx_t *mtx);
+
+/** Wait for a condition variable to become signaled.
+* The function atomically unlocks the given mutex and endeavors to block until
+* the given condition variable is signaled by a call to cnd_signal or to
+* cnd_broadcast, or until after the specified time. When the calling thread
+* becomes unblocked it locks the mutex before it returns.
+* @param cond A condition variable object.
+* @param mtx A mutex object.
+* @param xt A point in time at which the request will time out (absolute time).
+* @return @ref thrd_success upon success, or @ref thrd_timeout if the time
+* specified in the call was reached without acquiring the requested resource, or
+* @ref thrd_error if the request could not be honored.
+*/
+int cnd_timedwait(cnd_t *cond, mtx_t *mtx, const struct timespec *ts);
+
+/* Thread */
+#if defined(_TTHREAD_WIN32_)
+typedef HANDLE thrd_t;
+#else
+typedef pthread_t thrd_t;
+#endif
+
+/** Thread start function.
+* Any thread that is started with the @ref thrd_create() function must be
+* started through a function of this type.
+* @param arg The thread argument (the @c arg argument of the corresponding
+*        @ref thrd_create() call).
+* @return The thread return value, which can be obtained by another thread
+* by using the @ref thrd_join() function.
+*/
+typedef int (*thrd_start_t)(void *arg);
+
+/** Create a new thread.
+* @param thr Identifier of the newly created thread.
+* @param func A function pointer to the function that will be executed in
+*        the new thread.
+* @param arg An argument to the thread function.
+* @return @ref thrd_success on success, or @ref thrd_nomem if no memory could
+* be allocated for the thread requested, or @ref thrd_error if the request
+* could not be honored.
+* @note A thread’s identifier may be reused for a different thread once the
+* original thread has exited and either been detached or joined to another
+* thread.
+*/
+int thrd_create(thrd_t *thr, thrd_start_t func, void *arg);
+
+/** Identify the calling thread.
+* @return The identifier of the calling thread.
+*/
+thrd_t thrd_current(void);
+
+/** NOT YET IMPLEMENTED.
+*/
+int thrd_detach(thrd_t thr);
+
+/** Compare two thread identifiers.
+* The function determines if two thread identifiers refer to the same thread.
+* @return Zero if the two thread identifiers refer to different threads.
+* Otherwise a nonzero value is returned.
+*/
+int thrd_equal(thrd_t thr0, thrd_t thr1);
+
+/** Terminate execution of the calling thread.
+* @param res Result code of the calling thread.
+*/
+void thrd_exit(int res);
+
+/** Wait for a thread to terminate.
+* The function joins the given thread with the current thread by blocking
+* until the other thread has terminated.
+* @param thr The thread to join with.
+* @param res If this pointer is not NULL, the function will store the result
+*        code of the given thread in the integer pointed to by @c res.
+* @return @ref thrd_success on success, or @ref thrd_error if the request could
+* not be honored.
+*/
+int thrd_join(thrd_t thr, int *res);
+
+/** Put the calling thread to sleep.
+* Suspend execution of the calling thread.
+* @param time_point A point in time at which the thread will resume (absolute time).
+* @param remaining If non-NULL, this parameter will hold the remaining time until
+*                  time_point upon return. This will typically be zero, but if
+*                  the thread was woken up by a signal that is not ignored before
+*                  time_point was reached @c remaining will hold a positive
+*                  time.
+* @return 0 (zero) on successful sleep, or -1 if an interrupt occurred.
+*/
+int thrd_sleep(const struct timespec *time_point, struct timespec *remaining);
+
+/** Yield execution to another thread.
+* Permit other threads to run, even if the current thread would ordinarily
+* continue to run.
+*/
+void thrd_yield(void);
+
+/* Thread local storage */
+#if defined(_TTHREAD_WIN32_)
+typedef DWORD tss_t;
+#else
+typedef pthread_key_t tss_t;
+#endif
+
+/** Destructor function for a thread-specific storage.
+* @param val The value of the destructed thread-specific storage.
+*/
+typedef void (*tss_dtor_t)(void *val);
+
+/** Create a thread-specific storage.
+* @param key The unique key identifier that will be set if the function is
+*        successful.
+* @param dtor Destructor function. This can be NULL.
+* @return @ref thrd_success on success, or @ref thrd_error if the request could
+* not be honored.
+* @note The destructor function is not supported under Windows. If @c dtor is
+* not NULL when calling this function under Windows, the function will fail
+* and return @ref thrd_error.
+*/
+int tss_create(tss_t *key, tss_dtor_t dtor);
+
+/** Delete a thread-specific storage.
+* The function releases any resources used by the given thread-specific
+* storage.
+* @param key The key that shall be deleted.
+*/
+void tss_delete(tss_t key);
+
+/** Get the value for a thread-specific storage.
+* @param key The thread-specific storage identifier.
+* @return The value for the current thread held in the given thread-specific
+* storage.
+*/
+void *tss_get(tss_t key);
+
+/** Set the value for a thread-specific storage.
+* @param key The thread-specific storage identifier.
+* @param val The value of the thread-specific storage to set for the current
+*        thread.
+* @return @ref thrd_success on success, or @ref thrd_error if the request could
+* not be honored.
+*/
+int tss_set(tss_t key, void *val);
+
+
+#endif /* _TINYTHREAD_H_ */
+

+ 247 - 0
samples/third_party/glfw/deps/vs2008/stdint.h

@@ -0,0 +1,247 @@
+// ISO C9x  compliant stdint.h for Microsoft Visual Studio
+// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 
+// 
+//  Copyright (c) 2006-2008 Alexander Chemeris
+// 
+// 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.
+// 
+//   3. The name of the author may be used to endorse or promote products
+//      derived from this software without specific prior written permission.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 _MSC_VER // [
+#error "Use this header only with Microsoft Visual C++ compilers!"
+#endif // _MSC_VER ]
+
+#ifndef _MSC_STDINT_H_ // [
+#define _MSC_STDINT_H_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif
+
+#include <limits.h>
+
+// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
+// compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}'
+// or compiler give many errors like this:
+//   error C2733: second C linkage of overloaded function 'wmemchr' not allowed
+#ifdef __cplusplus
+extern "C" {
+#endif
+#  include <wchar.h>
+#ifdef __cplusplus
+}
+#endif
+
+// Define _W64 macros to mark types changing their size, like intptr_t.
+#ifndef _W64
+#  if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
+#     define _W64 __w64
+#  else
+#     define _W64
+#  endif
+#endif
+
+
+// 7.18.1 Integer types
+
+// 7.18.1.1 Exact-width integer types
+
+// Visual Studio 6 and Embedded Visual C++ 4 doesn't
+// realize that, e.g. char has the same size as __int8
+// so we give up on __intX for them.
+#if (_MSC_VER < 1300)
+   typedef signed char       int8_t;
+   typedef signed short      int16_t;
+   typedef signed int        int32_t;
+   typedef unsigned char     uint8_t;
+   typedef unsigned short    uint16_t;
+   typedef unsigned int      uint32_t;
+#else
+   typedef signed __int8     int8_t;
+   typedef signed __int16    int16_t;
+   typedef signed __int32    int32_t;
+   typedef unsigned __int8   uint8_t;
+   typedef unsigned __int16  uint16_t;
+   typedef unsigned __int32  uint32_t;
+#endif
+typedef signed __int64       int64_t;
+typedef unsigned __int64     uint64_t;
+
+
+// 7.18.1.2 Minimum-width integer types
+typedef int8_t    int_least8_t;
+typedef int16_t   int_least16_t;
+typedef int32_t   int_least32_t;
+typedef int64_t   int_least64_t;
+typedef uint8_t   uint_least8_t;
+typedef uint16_t  uint_least16_t;
+typedef uint32_t  uint_least32_t;
+typedef uint64_t  uint_least64_t;
+
+// 7.18.1.3 Fastest minimum-width integer types
+typedef int8_t    int_fast8_t;
+typedef int16_t   int_fast16_t;
+typedef int32_t   int_fast32_t;
+typedef int64_t   int_fast64_t;
+typedef uint8_t   uint_fast8_t;
+typedef uint16_t  uint_fast16_t;
+typedef uint32_t  uint_fast32_t;
+typedef uint64_t  uint_fast64_t;
+
+// 7.18.1.4 Integer types capable of holding object pointers
+#ifdef _WIN64 // [
+   typedef signed __int64    intptr_t;
+   typedef unsigned __int64  uintptr_t;
+#else // _WIN64 ][
+   typedef _W64 signed int   intptr_t;
+   typedef _W64 unsigned int uintptr_t;
+#endif // _WIN64 ]
+
+// 7.18.1.5 Greatest-width integer types
+typedef int64_t   intmax_t;
+typedef uint64_t  uintmax_t;
+
+
+// 7.18.2 Limits of specified-width integer types
+
+#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [   See footnote 220 at page 257 and footnote 221 at page 259
+
+// 7.18.2.1 Limits of exact-width integer types
+#define INT8_MIN     ((int8_t)_I8_MIN)
+#define INT8_MAX     _I8_MAX
+#define INT16_MIN    ((int16_t)_I16_MIN)
+#define INT16_MAX    _I16_MAX
+#define INT32_MIN    ((int32_t)_I32_MIN)
+#define INT32_MAX    _I32_MAX
+#define INT64_MIN    ((int64_t)_I64_MIN)
+#define INT64_MAX    _I64_MAX
+#define UINT8_MAX    _UI8_MAX
+#define UINT16_MAX   _UI16_MAX
+#define UINT32_MAX   _UI32_MAX
+#define UINT64_MAX   _UI64_MAX
+
+// 7.18.2.2 Limits of minimum-width integer types
+#define INT_LEAST8_MIN    INT8_MIN
+#define INT_LEAST8_MAX    INT8_MAX
+#define INT_LEAST16_MIN   INT16_MIN
+#define INT_LEAST16_MAX   INT16_MAX
+#define INT_LEAST32_MIN   INT32_MIN
+#define INT_LEAST32_MAX   INT32_MAX
+#define INT_LEAST64_MIN   INT64_MIN
+#define INT_LEAST64_MAX   INT64_MAX
+#define UINT_LEAST8_MAX   UINT8_MAX
+#define UINT_LEAST16_MAX  UINT16_MAX
+#define UINT_LEAST32_MAX  UINT32_MAX
+#define UINT_LEAST64_MAX  UINT64_MAX
+
+// 7.18.2.3 Limits of fastest minimum-width integer types
+#define INT_FAST8_MIN    INT8_MIN
+#define INT_FAST8_MAX    INT8_MAX
+#define INT_FAST16_MIN   INT16_MIN
+#define INT_FAST16_MAX   INT16_MAX
+#define INT_FAST32_MIN   INT32_MIN
+#define INT_FAST32_MAX   INT32_MAX
+#define INT_FAST64_MIN   INT64_MIN
+#define INT_FAST64_MAX   INT64_MAX
+#define UINT_FAST8_MAX   UINT8_MAX
+#define UINT_FAST16_MAX  UINT16_MAX
+#define UINT_FAST32_MAX  UINT32_MAX
+#define UINT_FAST64_MAX  UINT64_MAX
+
+// 7.18.2.4 Limits of integer types capable of holding object pointers
+#ifdef _WIN64 // [
+#  define INTPTR_MIN   INT64_MIN
+#  define INTPTR_MAX   INT64_MAX
+#  define UINTPTR_MAX  UINT64_MAX
+#else // _WIN64 ][
+#  define INTPTR_MIN   INT32_MIN
+#  define INTPTR_MAX   INT32_MAX
+#  define UINTPTR_MAX  UINT32_MAX
+#endif // _WIN64 ]
+
+// 7.18.2.5 Limits of greatest-width integer types
+#define INTMAX_MIN   INT64_MIN
+#define INTMAX_MAX   INT64_MAX
+#define UINTMAX_MAX  UINT64_MAX
+
+// 7.18.3 Limits of other integer types
+
+#ifdef _WIN64 // [
+#  define PTRDIFF_MIN  _I64_MIN
+#  define PTRDIFF_MAX  _I64_MAX
+#else  // _WIN64 ][
+#  define PTRDIFF_MIN  _I32_MIN
+#  define PTRDIFF_MAX  _I32_MAX
+#endif  // _WIN64 ]
+
+#define SIG_ATOMIC_MIN  INT_MIN
+#define SIG_ATOMIC_MAX  INT_MAX
+
+#ifndef SIZE_MAX // [
+#  ifdef _WIN64 // [
+#     define SIZE_MAX  _UI64_MAX
+#  else // _WIN64 ][
+#     define SIZE_MAX  _UI32_MAX
+#  endif // _WIN64 ]
+#endif // SIZE_MAX ]
+
+// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
+#ifndef WCHAR_MIN // [
+#  define WCHAR_MIN  0
+#endif  // WCHAR_MIN ]
+#ifndef WCHAR_MAX // [
+#  define WCHAR_MAX  _UI16_MAX
+#endif  // WCHAR_MAX ]
+
+#define WINT_MIN  0
+#define WINT_MAX  _UI16_MAX
+
+#endif // __STDC_LIMIT_MACROS ]
+
+
+// 7.18.4 Limits of other integer types
+
+#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [   See footnote 224 at page 260
+
+// 7.18.4.1 Macros for minimum-width integer constants
+
+#define INT8_C(val)  val##i8
+#define INT16_C(val) val##i16
+#define INT32_C(val) val##i32
+#define INT64_C(val) val##i64
+
+#define UINT8_C(val)  val##ui8
+#define UINT16_C(val) val##ui16
+#define UINT32_C(val) val##ui32
+#define UINT64_C(val) val##ui64
+
+// 7.18.4.2 Macros for greatest-width integer constants
+#define INTMAX_C   INT64_C
+#define UINTMAX_C  UINT64_C
+
+#endif // __STDC_CONSTANT_MACROS ]
+
+
+#endif // _MSC_STDINT_H_ ]

+ 34 - 0
samples/third_party/glfw/docs/CMakeLists.txt

@@ -0,0 +1,34 @@
+
+# NOTE: The order of this list determines the order of items in the Guides
+#       (i.e. Pages) list in the generated documentation
+set(GLFW_DOXYGEN_SOURCES
+    "include/GLFW/glfw3.h"
+    "include/GLFW/glfw3native.h"
+    "docs/main.dox"
+    "docs/news.dox"
+    "docs/quick.dox"
+    "docs/moving.dox"
+    "docs/compile.dox"
+    "docs/build.dox"
+    "docs/intro.dox"
+    "docs/context.dox"
+    "docs/monitor.dox"
+    "docs/window.dox"
+    "docs/input.dox"
+    "docs/vulkan.dox"
+    "docs/compat.dox"
+    "docs/internal.dox")
+
+# Format the source list into a Doxyfile INPUT value that Doxygen can parse
+foreach(path IN LISTS GLFW_DOXYGEN_SOURCES)
+    set(GLFW_DOXYGEN_INPUT "${GLFW_DOXYGEN_INPUT} \\\n\"${GLFW_SOURCE_DIR}/${path}\"")
+endforeach()
+
+configure_file(Doxyfile.in Doxyfile @ONLY)
+
+add_custom_target(docs ALL "${DOXYGEN_EXECUTABLE}"
+                  WORKING_DIRECTORY "${GLFW_BINARY_DIR}/docs"
+                  COMMENT "Generating HTML documentation" VERBATIM)
+
+set_target_properties(docs PROPERTIES FOLDER "GLFW3")
+

+ 10 - 0
samples/third_party/glfw/docs/CODEOWNERS

@@ -0,0 +1,10 @@
+
+*               @elmindreda
+
+src/wl_*        @linkmauve
+
+docs/*.css      @glfw/webdev
+docs/*.scss     @glfw/webdev
+docs/*.html     @glfw/webdev
+docs/*.xml      @glfw/webdev
+

+ 391 - 0
samples/third_party/glfw/docs/CONTRIBUTING.md

@@ -0,0 +1,391 @@
+# Contribution Guide
+
+## Contents
+
+- [Asking a question](#asking-a-question)
+- [Reporting a bug](#reporting-a-bug)
+    - [Reporting a compile or link bug](#reporting-a-compile-or-link-bug)
+    - [Reporting a segfault or other crash bug](#reporting-a-segfault-or-other-crash-bug)
+    - [Reporting a context creation bug](#reporting-a-context-creation-bug)
+    - [Reporting a monitor or video mode bug](#reporting-a-monitor-or-video-mode-bug)
+    - [Reporting a window, input or event bug](#reporting-a-window-input-or-event-bug)
+    - [Reporting some other library bug](#reporting-some-other-library-bug)
+    - [Reporting a documentation bug](#reporting-a-documentation-bug)
+    - [Reporting a website bug](#reporting-a-website-bug)
+- [Requesting a feature](#requesting-a-feature)
+- [Contributing a bug fix](#contributing-a-bug-fix)
+- [Contributing a feature](#contributing-a-feature)
+
+
+## Asking a question
+
+Questions about how to use GLFW should be asked either in the [support
+section](https://discourse.glfw.org/c/support) of the forum, under the [Stack
+Overflow tag](https://stackoverflow.com/questions/tagged/glfw) or [Game
+Development tag](https://gamedev.stackexchange.com/questions/tagged/glfw) on
+Stack Exchange or in the IRC channel `#glfw` on
+[Libera.Chat](https://libera.chat/).
+
+Questions about the design or implementation of GLFW or about future plans
+should be asked in the [dev section](https://discourse.glfw.org/c/dev) of the
+forum or in the IRC channel.  Please don't open a GitHub issue to discuss design
+questions without first checking with a maintainer.
+
+
+## Reporting a bug
+
+If GLFW is behaving unexpectedly at run-time, start by setting an [error
+callback](https://www.glfw.org/docs/latest/intro_guide.html#error_handling).
+GLFW will often tell you the cause of an error via this callback.  If it
+doesn't, that might be a separate bug.
+
+If GLFW is crashing or triggering asserts, make sure that all your object
+handles and other pointers are valid.
+
+For bugs where it makes sense, a short, self contained example is absolutely
+invaluable.  Just put it inline in the body text.  Note that if the bug is
+reproducible with one of the test programs that come with GLFW, just mention
+that instead.
+
+__Don't worry about adding too much information__.  Unimportant information can
+be abbreviated or removed later, but missing information can stall bug fixing,
+especially when your schedule doesn't align with that of the maintainer.
+
+__Please provide text as text, not as images__.  This includes code, error
+messages and any other text.  Text in images cannot be found by other users
+searching for the same problem and may have to be re-typed by maintainers when
+debugging.
+
+You don't need to manually indent your code or other text to quote it with
+GitHub Markdown; just surround it with triple backticks:
+
+    ```
+    Some quoted text.
+    ```
+
+You can also add syntax highlighting by appending the common file extension:
+
+    ```c
+    int five(void)
+    {
+        return 5;
+    }
+    ```
+
+There are issue labels for both platforms and GPU manufacturers, so there is no
+need to mention these in the subject line.  If you do, it will be removed when
+the issue is labeled.
+
+If your bug is already reported, please add any new information you have, or if
+it already has everything, give it a :+1:.
+
+
+### Reporting a compile or link bug
+
+__Note:__ GLFW needs many system APIs to do its job, which on some platforms
+means linking to many system libraries.  If you are using GLFW as a static
+library, that means your application needs to link to these in addition to GLFW.
+
+__Note:__ Check the [Compiling
+GLFW](https://www.glfw.org/docs/latest/compile.html) guide and or [Building
+applications](https://www.glfw.org/docs/latest/build.html) guide for before
+opening an issue of this kind.  Most issues are caused by a missing package or
+linker flag.
+
+Always include the __operating system name and version__ (e.g. `Windows
+7 64-bit` or `Ubuntu 15.10`) and the __compiler name and version__ (e.g. `Visual
+C++ 2015 Update 2`).  If you are using an official release of GLFW,
+include the __GLFW release version__ (e.g. `3.1.2`), otherwise include the
+__GLFW commit ID__ (e.g.  `3795d78b14ef06008889cc422a1fb8d642597751`) from Git.
+
+Please also include the __complete build log__ from your compiler and linker,
+even if it's long.  It can always be shortened later, if necessary.
+
+
+#### Quick template
+
+```
+OS and version:
+Compiler version:
+Release or commit:
+Build log:
+```
+
+
+### Reporting a segfault or other crash bug
+
+Always include the __operating system name and version__ (e.g. `Windows
+7 64-bit` or `Ubuntu 15.10`).  If you are using an official release of GLFW,
+include the __GLFW release version__ (e.g. `3.1.2`), otherwise include the
+__GLFW commit ID__ (e.g.  `3795d78b14ef06008889cc422a1fb8d642597751`) from Git.
+
+Please also include any __error messages__ provided to your application via the
+[error
+callback](https://www.glfw.org/docs/latest/intro_guide.html#error_handling) and
+the __full call stack__ of the crash, or if the crash does not occur in debug
+mode, mention that instead.
+
+
+#### Quick template
+
+```
+OS and version:
+Release or commit:
+Error messages:
+Call stack:
+```
+
+
+### Reporting a context creation bug
+
+__Note:__ Windows ships with graphics drivers that do not support OpenGL.  If
+GLFW says that your machine lacks support for OpenGL, it very likely does.
+Install drivers from the computer manufacturer or graphics card manufacturer
+([Nvidia](https://www.geforce.com/drivers),
+[AMD](https://www.amd.com/en/support),
+[Intel](https://www-ssl.intel.com/content/www/us/en/support/detect.html)) to
+fix this.
+
+__Note:__ AMD only supports OpenGL ES on Windows via EGL.  See the
+[GLFW\_CONTEXT\_CREATION\_API](https://www.glfw.org/docs/latest/window_guide.html#window_hints_ctx)
+hint for how to select EGL.
+
+Please verify that context creation also fails with the `glfwinfo` tool before
+reporting it as a bug.  This tool is included in the GLFW source tree as
+`tests/glfwinfo.c` and is built along with the library.  It has switches for all
+GLFW context and framebuffer hints.  Run `glfwinfo -h` for a complete list.
+
+Always include the __operating system name and version__ (e.g. `Windows
+7 64-bit` or `Ubuntu 15.10`).  If you are using an official release of GLFW,
+include the __GLFW release version__ (e.g. `3.1.2`), otherwise include the
+__GLFW commit ID__ (e.g.  `3795d78b14ef06008889cc422a1fb8d642597751`) from Git.
+
+If you are running your program in a virtual machine, please mention this and
+include the __VM name and version__ (e.g. `VirtualBox 5.1`).
+
+Please also include the __GLFW version string__ (`3.2.0 X11 EGL clock_gettime
+/dev/js`), as described
+[here](https://www.glfw.org/docs/latest/intro.html#intro_version_string), the
+__GPU model and driver version__ (e.g. `GeForce GTX660 with 352.79`), and the
+__output of `glfwinfo`__ (with switches matching any hints you set in your
+code) when reporting this kind of bug.  If this tool doesn't run on the machine,
+mention that instead.
+
+
+#### Quick template
+
+```
+OS and version:
+GPU and driver:
+Release or commit:
+Version string:
+glfwinfo output:
+```
+
+
+### Reporting a monitor or video mode bug
+
+__Note:__ On headless systems on some platforms, no monitors are reported.  This
+causes glfwGetPrimaryMonitor to return `NULL`, which not all applications are
+prepared for.
+
+__Note:__ Some third-party tools report more video modes than are approved of
+by the OS.  For safety and compatibility, GLFW only reports video modes the OS
+wants programs to use.  This is not a bug.
+
+The `monitors` tool is included in the GLFW source tree as `tests/monitors.c`
+and is built along with the library.  It lists all information GLFW provides
+about monitors it detects.
+
+Always include the __operating system name and version__ (e.g. `Windows
+7 64-bit` or `Ubuntu 15.10`).  If you are using an official release of GLFW,
+include the __GLFW release version__ (e.g. `3.1.2`), otherwise include the
+__GLFW commit ID__ (e.g.  `3795d78b14ef06008889cc422a1fb8d642597751`) from Git.
+
+If you are running your program in a virtual machine, please mention this and
+include the __VM name and version__ (e.g. `VirtualBox 5.1`).
+
+Please also include any __error messages__ provided to your application via the
+[error
+callback](https://www.glfw.org/docs/latest/intro_guide.html#error_handling) and
+the __output of `monitors`__ when reporting this kind of bug.  If this tool
+doesn't run on the machine, mention this instead.
+
+
+#### Quick template
+
+```
+OS and version:
+Release or commit:
+Error messages:
+monitors output:
+```
+
+
+### Reporting a window, input or event bug
+
+__Note:__ The exact ordering of related window events will sometimes differ.
+
+__Note:__ Window moving and resizing (by the user) will block the main thread on
+some platforms.  This is not a bug.  Set a [refresh
+callback](https://www.glfw.org/docs/latest/window.html#window_refresh) if you
+want to keep the window contents updated during a move or size operation.
+
+The `events` tool is included in the GLFW source tree as `tests/events.c` and is
+built along with the library.  It prints all information provided to every
+callback supported by GLFW as events occur.  Each event is listed with the time
+and a unique number to make discussions about event logs easier.  The tool has
+command-line options for creating multiple windows and full screen windows.
+
+Always include the __operating system name and version__ (e.g. `Windows
+7 64-bit` or `Ubuntu 15.10`).  If you are using an official release of GLFW,
+include the __GLFW release version__ (e.g. `3.1.2`), otherwise include the
+__GLFW commit ID__ (e.g.  `3795d78b14ef06008889cc422a1fb8d642597751`) from Git.
+
+If you are running your program in a virtual machine, please mention this and
+include the __VM name and version__ (e.g. `VirtualBox 5.1`).
+
+Please also include any __error messages__ provided to your application via the
+[error
+callback](https://www.glfw.org/docs/latest/intro_guide.html#error_handling) and
+if relevant, the __output of `events`__ when reporting this kind of bug.  If
+this tool doesn't run on the machine, mention this instead.
+
+__X11:__ If possible, please include what desktop environment (e.g. GNOME,
+Unity, KDE) and/or window manager (e.g. Openbox, dwm, Window Maker) you are
+running.  If the bug is related to keyboard input, please include any input
+method (e.g. ibus, SCIM) you are using.
+
+
+#### Quick template
+
+```
+OS and version:
+Release or commit:
+Error messages:
+events output:
+```
+
+
+### Reporting some other library bug
+
+Always include the __operating system name and version__ (e.g. `Windows
+7 64-bit` or `Ubuntu 15.10`).  If you are using an official release of GLFW,
+include the __GLFW release version__ (e.g. `3.1.2`), otherwise include the
+__GLFW commit ID__ (e.g.  `3795d78b14ef06008889cc422a1fb8d642597751`) from Git.
+
+Please also include any __error messages__ provided to your application via the
+[error
+callback](https://www.glfw.org/docs/latest/intro_guide.html#error_handling), if
+relevant.
+
+
+#### Quick template
+
+```
+OS and version:
+Release or commit:
+Error messages:
+```
+
+
+### Reporting a documentation bug
+
+If you found a bug in the documentation, including this file, then it's fine to
+just link to that web page or mention that source file.  You don't need to match
+the source to the output or vice versa.
+
+
+### Reporting a website bug
+
+If the bug is in the documentation (anything under `/docs/`) then please see the
+section above.  Bugs in the rest of the site are reported to the [website
+source repository](https://github.com/glfw/website/issues).
+
+
+## Requesting a feature
+
+Please explain why you need the feature and how you intend to use it.  If you
+have a specific API design in mind, please add that as well.  If you have or are
+planning to write code for the feature, see the section below.
+
+If there already is a request for the feature you need, add your specific use
+case unless it is already mentioned.  If it is, give it a :+1:.
+
+
+## Contributing a bug fix
+
+__Note:__ You must have all necessary [intellectual
+property rights](https://en.wikipedia.org/wiki/Intellectual_property) to any
+code you contribute.  If you did not write the code yourself, you must explain
+where it came from and under what license you received it.  Even code using the
+same license as GLFW may not be copied without attribution.
+
+__There is no preferred patch size__.  A one character fix is just as welcome as
+a thousand line one, if that is the appropriate size for the fix.
+
+In addition to the code, a complete bug fix includes:
+
+- Change log entry in `README.md`, describing the incorrect behavior
+- Credits entries for all authors of the bug fix
+
+Bug fixes will not be rejected because they don't include all the above parts,
+but please keep in mind that maintainer time is finite and that there are many
+other bugs and features to work on.
+
+If the patch fixes a bug introduced after the last release, it should not get
+a change log entry.
+
+If you haven't already, read the excellent article [How to Write a Git Commit
+Message](https://chris.beams.io/posts/git-commit/).
+
+
+## Contributing a feature
+
+__Note:__ You must have all necessary rights to any code you contribute.  If you
+did not write the code yourself, you must explain where it came from and under
+what license.  Even code using the same license as GLFW may not be copied
+without attribution.
+
+__Note:__ If you haven't already implemented the feature, check first if there
+already is an open issue for it and if it's already being developed in an
+[experimental branch](https://github.com/glfw/glfw/branches/all).
+
+__There is no preferred patch size__.  A one character change is just as welcome
+as one adding a thousand line one, if that is the appropriate size for the
+feature.
+
+In addition to the code, a complete feature includes:
+
+- Change log entry in `README.md`, listing all new symbols
+- News page entry, briefly describing the feature
+- Guide documentation, with minimal examples, in the relevant guide
+- Reference documentation, with all applicable tags
+- Cross-references and mentions in appropriate places
+- Credits entries for all authors of the feature
+
+If the feature requires platform-specific code, at minimum stubs must be added
+for the new platform function to all supported and experimental platforms.
+
+If it adds a new callback, support for it must be added to `tests/event.c`.
+
+If it adds a new monitor property, support for it must be added to
+`tests/monitor.c`.
+
+If it adds a new OpenGL, OpenGL ES or Vulkan option or extension, support
+for it must be added to `tests/glfwinfo.c` and the behavior of the library when
+the extension is missing documented in `docs/compat.dox`.
+
+If you haven't already, read the excellent article [How to Write a Git Commit
+Message](https://chris.beams.io/posts/git-commit/).
+
+Features will not be rejected because they don't include all the above parts,
+but please keep in mind that maintainer time is finite and that there are many
+other features and bugs to work on.
+
+Please also keep in mind that any part of the public API that has been included
+in a release cannot be changed until the next _major_ version.  Features can be
+added and existing parts can sometimes be overloaded (in the general sense of
+doing more things, not in the C++ sense), but code written to the API of one
+minor release should both compile and run on subsequent minor releases.
+

ファイルの差分が大きいため隠しています
+ 1828 - 0
samples/third_party/glfw/docs/Doxyfile.in


+ 71 - 0
samples/third_party/glfw/docs/DoxygenLayout.xml

@@ -0,0 +1,71 @@
+<doxygenlayout version="1.0">
+  <!-- Generated by doxygen 1.8.14 -->
+  <!-- Navigation index tabs for HTML output -->
+  <navindex>
+    <tab type="mainpage" visible="yes" title="Introduction"/>
+    <tab type="user" url="quick_guide.html" title="Tutorial"/>
+    <tab type="pages" visible="yes" title="Guides" intro=""/>
+    <tab type="modules" visible="yes" title="Reference" intro=""/>
+    <tab type="filelist" visible="yes" title="Files"/>
+  </navindex>
+
+  <!-- Layout definition for a file page -->
+  <file>
+    <detaileddescription title="Description"/>
+    <includes visible="$SHOW_INCLUDE_FILES"/>
+    <sourcelink visible="yes"/>
+    <memberdecl>
+      <constantgroups visible="yes" title=""/>
+      <defines title=""/>
+      <typedefs title=""/>
+      <enums title=""/>
+      <functions title=""/>
+      <variables title=""/>
+      <membergroups visible="yes"/>
+    </memberdecl>
+    <memberdef>
+      <defines title=""/>
+      <typedefs title=""/>
+      <enums title=""/>
+      <functions title=""/>
+      <variables title=""/>
+    </memberdef>
+    <authorsection/>
+  </file>
+
+  <!-- Layout definition for a group page -->
+  <group>
+    <detaileddescription title="Description"/>
+    <memberdecl>
+      <nestedgroups visible="yes" title=""/>
+      <dirs visible="yes" title=""/>
+      <files visible="yes" title=""/>
+      <defines title=""/>
+      <typedefs title=""/>
+      <enums title=""/>
+      <enumvalues title=""/>
+      <functions title=""/>
+      <variables title=""/>
+    </memberdecl>
+    <memberdef>
+      <pagedocs/>
+      <defines title=""/>
+      <typedefs title=""/>
+      <enums title=""/>
+      <enumvalues title=""/>
+      <functions title=""/>
+      <variables title=""/>
+    </memberdef>
+    <authorsection visible="yes"/>
+  </group>
+
+  <!-- Layout definition for a directory page -->
+  <directory>
+    <briefdescription visible="yes"/>
+    <memberdecl>
+      <dirs visible="yes"/>
+      <files visible="yes"/>
+    </memberdecl>
+    <detaileddescription title=""/>
+  </directory>
+</doxygenlayout>

+ 14 - 0
samples/third_party/glfw/docs/SUPPORT.md

@@ -0,0 +1,14 @@
+# Support resources
+
+See the [latest documentation](https://www.glfw.org/docs/latest/) for tutorials,
+guides and the API reference.
+
+If you have questions about using GLFW, we have a
+[forum](https://discourse.glfw.org/), and the `#glfw` IRC channel on
+[Libera.Chat](https://libera.chat/).
+
+Bugs are reported to our [issue tracker](https://github.com/glfw/glfw/issues).
+Please check the [contribution
+guide](https://github.com/glfw/glfw/blob/master/docs/CONTRIBUTING.md) for
+information on what to include when reporting a bug.
+

+ 348 - 0
samples/third_party/glfw/docs/build.dox

@@ -0,0 +1,348 @@
+/*!
+
+@page build_guide Building applications
+
+@tableofcontents
+
+This is about compiling and linking applications that use GLFW.  For information on
+how to write such applications, start with the
+[introductory tutorial](@ref quick_guide).  For information on how to compile
+the GLFW library itself, see @ref compile_guide.
+
+This is not a tutorial on compilation or linking.  It assumes basic
+understanding of how to compile and link a C program as well as how to use the
+specific compiler of your chosen development environment.  The compilation
+and linking process should be explained in your C programming material and in
+the documentation for your development environment.
+
+
+@section build_include Including the GLFW header file
+
+You should include the GLFW header in the source files where you use OpenGL or
+GLFW.
+
+@code
+#include <GLFW/glfw3.h>
+@endcode
+
+This header defines all the constants and declares all the types and function
+prototypes of the GLFW API.  By default it also includes the OpenGL header from
+your development environment.  See [option macros](@ref build_macros) below for
+how to select OpenGL ES headers and more.
+
+The GLFW header also defines any platform-specific macros needed by your OpenGL
+header, so that it can be included without needing any window system headers.
+
+It does this only when needed, so if window system headers are included, the
+GLFW header does not try to redefine those symbols.  The reverse is not true,
+i.e. `windows.h` cannot cope if any Win32 symbols have already been defined.
+
+In other words:
+
+ - Use the GLFW header to include OpenGL or OpenGL ES headers portably
+ - Do not include window system headers unless you will use those APIs directly
+ - If you do need such headers, include them before the GLFW header
+
+If you are using an OpenGL extension loading library such as
+[glad](https://github.com/Dav1dde/glad), the extension loader header should
+be included before the GLFW one.  GLFW attempts to detect any OpenGL or OpenGL
+ES header or extension loader header included before it and will then disable
+the inclusion of the default OpenGL header.  Most extension loaders also define
+macros that disable similar headers below it.
+
+@code
+#include <glad/gl.h>
+#include <GLFW/glfw3.h>
+@endcode
+
+Both of these mechanisms depend on the extension loader header defining a known
+macro.  If yours doesn't or you don't know which one your users will pick, the
+@ref GLFW_INCLUDE_NONE macro will explicitly to prevent the GLFW header from
+including the OpenGL header.  This will also allow you to include the two
+headers in any order.
+
+@code
+#define GLFW_INCLUDE_NONE
+#include <GLFW/glfw3.h>
+#include <glad/gl.h>
+@endcode
+
+
+@subsection build_macros GLFW header option macros
+
+These macros may be defined before the inclusion of the GLFW header and affect
+its behavior.
+
+@anchor GLFW_DLL
+__GLFW_DLL__ is required on Windows when using the GLFW DLL, to tell the
+compiler that the GLFW functions are defined in a DLL.
+
+The following macros control which OpenGL or OpenGL ES API header is included.
+Only one of these may be defined at a time.
+
+@note GLFW does not provide any of the API headers mentioned below.  They are
+provided by your development environment or your OpenGL, OpenGL ES or Vulkan
+SDK, and most of them can be downloaded from the
+[Khronos Registry](https://www.khronos.org/registry/).
+
+@anchor GLFW_INCLUDE_GLCOREARB
+__GLFW_INCLUDE_GLCOREARB__ makes the GLFW header include the modern
+`GL/glcorearb.h` header (`OpenGL/gl3.h` on macOS) instead of the regular OpenGL
+header.
+
+@anchor GLFW_INCLUDE_ES1
+__GLFW_INCLUDE_ES1__ makes the GLFW header include the OpenGL ES 1.x `GLES/gl.h`
+header instead of the regular OpenGL header.
+
+@anchor GLFW_INCLUDE_ES2
+__GLFW_INCLUDE_ES2__ makes the GLFW header include the OpenGL ES 2.0
+`GLES2/gl2.h` header instead of the regular OpenGL header.
+
+@anchor GLFW_INCLUDE_ES3
+__GLFW_INCLUDE_ES3__ makes the GLFW header include the OpenGL ES 3.0
+`GLES3/gl3.h` header instead of the regular OpenGL header.
+
+@anchor GLFW_INCLUDE_ES31
+__GLFW_INCLUDE_ES31__ makes the GLFW header include the OpenGL ES 3.1
+`GLES3/gl31.h` header instead of the regular OpenGL header.
+
+@anchor GLFW_INCLUDE_ES32
+__GLFW_INCLUDE_ES32__ makes the GLFW header include the OpenGL ES 3.2
+`GLES3/gl32.h` header instead of the regular OpenGL header.
+
+@anchor GLFW_INCLUDE_NONE
+__GLFW_INCLUDE_NONE__ makes the GLFW header not include any OpenGL or OpenGL ES
+API header.  This is useful in combination with an extension loading library.
+
+If none of the above inclusion macros are defined, the standard OpenGL `GL/gl.h`
+header (`OpenGL/gl.h` on macOS) is included, unless GLFW detects the inclusion
+guards of any OpenGL, OpenGL ES or extension loader header it knows about.
+
+The following macros control the inclusion of additional API headers.  Any
+number of these may be defined simultaneously, and/or together with one of the
+above macros.
+
+@anchor GLFW_INCLUDE_VULKAN
+__GLFW_INCLUDE_VULKAN__ makes the GLFW header include the Vulkan
+`vulkan/vulkan.h` header in addition to any selected OpenGL or OpenGL ES header.
+
+@anchor GLFW_INCLUDE_GLEXT
+__GLFW_INCLUDE_GLEXT__ makes the GLFW header include the appropriate extension
+header for the OpenGL or OpenGL ES header selected above after and in addition
+to that header.
+
+@anchor GLFW_INCLUDE_GLU
+__GLFW_INCLUDE_GLU__ makes the header include the GLU header in addition to the
+header selected above.  This should only be used with the standard OpenGL header
+and only for compatibility with legacy code.  GLU has been deprecated and should
+not be used in new code.
+
+@note None of these macros may be defined during the compilation of GLFW itself.
+If your build includes GLFW and you define any these in your build files, make
+sure they are not applied to the GLFW sources.
+
+
+@section build_link Link with the right libraries
+
+GLFW is essentially a wrapper of various platform-specific APIs and therefore
+needs to link against many different system libraries.  If you are using GLFW as
+a shared library / dynamic library / DLL then it takes care of these links.
+However, if you are using GLFW as a static library then your executable will
+need to link against these libraries.
+
+On Windows and macOS, the list of system libraries is static and can be
+hard-coded into your build environment.  See the section for your development
+environment below.  On Linux and other Unix-like operating systems, the list
+varies but can be retrieved in various ways as described below.
+
+A good general introduction to linking is
+[Beginner's Guide to Linkers](https://www.lurklurk.org/linkers/linkers.html) by
+David Drysdale.
+
+
+@subsection build_link_win32 With MinGW or Visual C++ on Windows
+
+The static version of the GLFW library is named `glfw3`.  When using this
+version, it is also necessary to link with some libraries that GLFW uses.
+
+When using MinGW to link an application with the static version of GLFW, you
+must also explicitly link with `gdi32`. Other toolchains including MinGW-w64
+include it in the set of default libraries along with other dependencies like
+`user32` and `kernel32`.
+
+The link library for the GLFW DLL is named `glfw3dll`.  When compiling an
+application that uses the DLL version of GLFW, you need to define the @ref
+GLFW_DLL macro _before_ any inclusion of the GLFW header.  This can be done
+either with a compiler switch or by defining it in your source code.
+
+
+@subsection build_link_cmake_source With CMake and GLFW source
+
+This section is about using CMake to compile and link GLFW along with your
+application.  If you want to use an installed binary instead, see @ref
+build_link_cmake_package.
+
+With a few changes to your `CMakeLists.txt` you can have the GLFW source tree
+built along with your application.
+
+When including GLFW as part of your build, you probably don't want to build the
+GLFW tests, examples and documentation.  To disable these, set the corresponding
+cache variables before adding the GLFW source tree.
+
+@code
+set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE)
+set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE)
+set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
+@endcode
+
+Add the root directory of the GLFW source tree to your project.  This will add
+the `glfw` target to your project.
+
+@code{.cmake}
+add_subdirectory(path/to/glfw)
+@endcode
+
+Once GLFW has been added, link your application against the `glfw` target.
+This adds the GLFW library and its link-time dependencies as it is currently
+configured, the include directory for the GLFW header and, when applicable, the
+@ref GLFW_DLL macro.
+
+@code{.cmake}
+target_link_libraries(myapp glfw)
+@endcode
+
+Note that the `glfw` target does not depend on OpenGL, as GLFW loads any OpenGL,
+OpenGL ES or Vulkan libraries it needs at runtime.  If your application calls
+OpenGL directly, instead of using a modern
+[extension loader library](@ref context_glext_auto), use the OpenGL CMake
+package.
+
+@code{.cmake}
+find_package(OpenGL REQUIRED)
+@endcode
+
+If OpenGL is found, the `OpenGL::GL` target is added to your project, containing
+library and include directory paths.  Link against this like any other library.
+
+@code{.cmake}
+target_link_libraries(myapp OpenGL::GL)
+@endcode
+
+For a minimal example of a program and GLFW sources built with CMake, see the
+[GLFW CMake Starter](https://github.com/juliettef/GLFW-CMake-starter) on GitHub.
+
+
+@subsection build_link_cmake_package With CMake and installed GLFW binaries
+
+This section is about using CMake to link GLFW after it has been built and
+installed.  If you want to build it along with your application instead, see
+@ref build_link_cmake_source.
+
+With a few changes to your `CMakeLists.txt` you can locate the package and
+target files generated when GLFW is installed.
+
+@code{.cmake}
+find_package(glfw3 3.3 REQUIRED)
+@endcode
+
+Once GLFW has been added to the project, link against it with the `glfw` target.
+This adds the GLFW library and its link-time dependencies, the include directory
+for the GLFW header and, when applicable, the @ref GLFW_DLL macro.
+
+@code{.cmake}
+target_link_libraries(myapp glfw)
+@endcode
+
+Note that the `glfw` target does not depend on OpenGL, as GLFW loads any OpenGL,
+OpenGL ES or Vulkan libraries it needs at runtime.  If your application calls
+OpenGL directly, instead of using a modern
+[extension loader library](@ref context_glext_auto), use the OpenGL CMake
+package.
+
+@code{.cmake}
+find_package(OpenGL REQUIRED)
+@endcode
+
+If OpenGL is found, the `OpenGL::GL` target is added to your project, containing
+library and include directory paths.  Link against this like any other library.
+
+@code{.cmake}
+target_link_libraries(myapp OpenGL::GL)
+@endcode
+
+
+@subsection build_link_pkgconfig With makefiles and pkg-config on Unix
+
+GLFW supports [pkg-config](https://www.freedesktop.org/wiki/Software/pkg-config/),
+and the `glfw3.pc` pkg-config file is generated when the GLFW library is built
+and is installed along with it.  A pkg-config file describes all necessary
+compile-time and link-time flags and dependencies needed to use a library.  When
+they are updated or if they differ between systems, you will get the correct
+ones automatically.
+
+A typical compile and link command-line when using the static version of the
+GLFW library may look like this:
+
+@code{.sh}
+cc $(pkg-config --cflags glfw3) -o myprog myprog.c $(pkg-config --static --libs glfw3)
+@endcode
+
+If you are using the shared version of the GLFW library, omit the `--static`
+flag.
+
+@code{.sh}
+cc $(pkg-config --cflags glfw3) -o myprog myprog.c $(pkg-config --libs glfw3)
+@endcode
+
+You can also use the `glfw3.pc` file without installing it first, by using the
+`PKG_CONFIG_PATH` environment variable.
+
+@code{.sh}
+env PKG_CONFIG_PATH=path/to/glfw/src cc $(pkg-config --cflags glfw3) -o myprog myprog.c $(pkg-config --libs glfw3)
+@endcode
+
+The dependencies do not include OpenGL, as GLFW loads any OpenGL, OpenGL ES or
+Vulkan libraries it needs at runtime.  If your application calls OpenGL
+directly, instead of using a modern
+[extension loader library](@ref context_glext_auto), you should add the `gl`
+pkg-config package.
+
+@code{.sh}
+cc $(pkg-config --cflags glfw3 gl) -o myprog myprog.c $(pkg-config --libs glfw3 gl)
+@endcode
+
+
+@subsection build_link_xcode With Xcode on macOS
+
+If you are using the dynamic library version of GLFW, add it to the project
+dependencies.
+
+If you are using the static library version of GLFW, add it and the Cocoa,
+OpenGL and IOKit frameworks to the project as dependencies.  They can all be
+found in `/System/Library/Frameworks`.
+
+
+@subsection build_link_osx With command-line on macOS
+
+It is recommended that you use [pkg-config](@ref build_link_pkgconfig) when
+building from the command line on macOS.  That way you will get any new
+dependencies added automatically.  If you still wish to build manually, you need
+to add the required frameworks and libraries to your command-line yourself using
+the `-l` and `-framework` switches.
+
+If you are using the dynamic GLFW library, which is named `libglfw.3.dylib`, do:
+
+@code{.sh}
+cc -o myprog myprog.c -lglfw -framework Cocoa -framework OpenGL -framework IOKit
+@endcode
+
+If you are using the static library, named `libglfw3.a`, substitute `-lglfw3`
+for `-lglfw`.
+
+Note that you do not add the `.framework` extension to a framework when linking
+against it from the command-line.
+
+@note Your machine may have `libGL.*.dylib` style OpenGL library, but that is
+for the X Window System and will not work with the macOS native version of GLFW.
+
+*/

+ 285 - 0
samples/third_party/glfw/docs/compat.dox

@@ -0,0 +1,285 @@
+/*!
+
+@page compat_guide Standards conformance
+
+@tableofcontents
+
+This guide describes the various API extensions used by this version of GLFW.
+It lists what are essentially implementation details, but which are nonetheless
+vital knowledge for developers intending to deploy their applications on a wide
+range of machines.
+
+The information in this guide is not a part of GLFW API, but merely
+preconditions for some parts of the library to function on a given machine.  Any
+part of this information may change in future versions of GLFW and that will not
+be considered a breaking API change.
+
+
+@section compat_x11 X11 extensions, protocols and IPC standards
+
+As GLFW uses Xlib directly, without any intervening toolkit
+library, it has sole responsibility for interacting well with the many and
+varied window managers in use on Unix-like systems.  In order for applications
+and window managers to work well together, a number of standards and
+conventions have been developed that regulate behavior outside the scope of the
+X11 API; most importantly the
+[Inter-Client Communication Conventions Manual](https://www.tronche.com/gui/x/icccm/)
+(ICCCM) and
+[Extended Window Manager Hints](https://standards.freedesktop.org/wm-spec/wm-spec-latest.html)
+(EWMH) standards.
+
+GLFW uses the `_MOTIF_WM_HINTS` window property to support borderless windows.
+If the running window manager does not support this property, the
+`GLFW_DECORATED` hint will have no effect.
+
+GLFW uses the ICCCM `WM_DELETE_WINDOW` protocol to intercept the user
+attempting to close the GLFW window.  If the running window manager does not
+support this protocol, the close callback will never be called.
+
+GLFW uses the EWMH `_NET_WM_PING` protocol, allowing the window manager notify
+the user when the application has stopped responding, i.e. when it has ceased to
+process events.  If the running window manager does not support this protocol,
+the user will not be notified if the application locks up.
+
+GLFW uses the EWMH `_NET_WM_STATE_FULLSCREEN` window state to tell the window
+manager to make the GLFW window full screen.  If the running window manager does
+not support this state, full screen windows may not work properly.  GLFW has
+a fallback code path in case this state is unavailable, but every window manager
+behaves slightly differently in this regard.
+
+GLFW uses the EWMH `_NET_WM_BYPASS_COMPOSITOR` window property to tell a
+compositing window manager to un-redirect full screen GLFW windows.  If the
+running window manager uses compositing but does not support this property then
+additional copying may be performed for each buffer swap of full screen windows.
+
+GLFW uses the
+[clipboard manager protocol](https://www.freedesktop.org/wiki/ClipboardManager/)
+to push a clipboard string (i.e. selection) owned by a GLFW window about to be
+destroyed to the clipboard manager.  If there is no running clipboard manager,
+the clipboard string will be unavailable once the window has been destroyed.
+
+GLFW uses the
+[X drag-and-drop protocol](https://www.freedesktop.org/wiki/Specifications/XDND/)
+to provide file drop events.  If the application originating the drag does not
+support this protocol, drag and drop will not work.
+
+GLFW uses the XRandR 1.3 extension to provide multi-monitor support.  If the
+running X server does not support this version of this extension, multi-monitor
+support will not function and only a single, desktop-spanning monitor will be
+reported.
+
+GLFW uses the XRandR 1.3 and Xf86vidmode extensions to provide gamma ramp
+support.  If the running X server does not support either or both of these
+extensions, gamma ramp support will not function.
+
+GLFW uses the Xkb extension and detectable auto-repeat to provide keyboard
+input.  If the running X server does not support this extension, a non-Xkb
+fallback path is used.
+
+GLFW uses the XInput2 extension to provide raw, non-accelerated mouse motion
+when the cursor is disabled.  If the running X server does not support this
+extension, regular accelerated mouse motion will be used.
+
+GLFW uses both the XRender extension and the compositing manager to support
+transparent window framebuffers.  If the running X server does not support this
+extension or there is no running compositing manager, the
+`GLFW_TRANSPARENT_FRAMEBUFFER` framebuffer hint will have no effect.
+
+
+@section compat_wayland Wayland protocols and IPC standards
+
+As GLFW uses libwayland directly, without any intervening toolkit library, it
+has sole responsibility for interacting well with every compositor in use on
+Unix-like systems.  Most of the features are provided by the core protocol,
+while cursor support is provided by the libwayland-cursor helper library, EGL
+integration by libwayland-egl, and keyboard handling by
+[libxkbcommon](https://xkbcommon.org/).  In addition, GLFW uses some protocols
+from wayland-protocols to provide additional features if the compositor
+supports them.
+
+GLFW uses xkbcommon 0.5.0 to provide compose key support.  When it has been
+built against an older xkbcommon, the compose key will be disabled even if it
+has been configured in the compositor.
+
+GLFW uses the [xdg-shell
+protocol](https://cgit.freedesktop.org/wayland/wayland-protocols/tree/stable/xdg-shell/xdg-shell.xml)
+to provide better window management.  This protocol is part of
+wayland-protocols 1.12, and mandatory at build time.  If the running compositor
+does not support this protocol, the older [wl_shell
+interface](https://cgit.freedesktop.org/wayland/wayland/tree/protocol/wayland.xml#n972)
+will be used instead.  This will result in a worse integration with the
+desktop, especially on tiling compositors.
+
+GLFW uses the [relative pointer
+protocol](https://cgit.freedesktop.org/wayland/wayland-protocols/tree/unstable/relative-pointer/relative-pointer-unstable-v1.xml)
+alongside the [pointer constraints
+protocol](https://cgit.freedesktop.org/wayland/wayland-protocols/tree/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml)
+to implement disabled cursor.  These two protocols are part of
+wayland-protocols 1.1, and mandatory at build time.  If the running compositor
+does not support both of these protocols, disabling the cursor will have no
+effect.
+
+GLFW uses the [idle inhibit
+protocol](https://cgit.freedesktop.org/wayland/wayland-protocols/tree/unstable/idle-inhibit/idle-inhibit-unstable-v1.xml)
+to prohibit the screensaver from starting.  This protocol is part of
+wayland-protocols 1.6, and mandatory at build time.  If the running compositor
+does not support this protocol, the screensaver may start even for full screen
+windows.
+
+GLFW uses the [xdg-decoration
+protocol](https://cgit.freedesktop.org/wayland/wayland-protocols/tree/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml)
+to request decorations to be drawn around its windows.  This protocol is part
+of wayland-protocols 1.15, and mandatory at build time.  If the running
+compositor does not support this protocol, a very simple frame will be drawn by
+GLFW itself, using the [viewporter
+protocol](https://cgit.freedesktop.org/wayland/wayland-protocols/tree/stable/viewporter/viewporter.xml)
+alongside
+[subsurfaces](https://cgit.freedesktop.org/wayland/wayland/tree/protocol/wayland.xml#n2598).
+This protocol is part of wayland-protocols 1.4, and mandatory at build time.
+If the running compositor does not support this protocol either, no decorations
+will be drawn around windows.
+
+
+@section compat_glx GLX extensions
+
+The GLX API is the default API used to create OpenGL contexts on Unix-like
+systems using the X Window System.
+
+GLFW uses the GLX 1.3 `GLXFBConfig` functions to enumerate and select framebuffer pixel
+formats.  If GLX 1.3 is not supported, @ref glfwInit will fail.
+
+GLFW uses the `GLX_MESA_swap_control,` `GLX_EXT_swap_control` and
+`GLX_SGI_swap_control` extensions to provide vertical retrace synchronization
+(or _vsync_), in that order of preference.  Where none of these extension are
+available, calling @ref glfwSwapInterval will have no effect.
+
+GLFW uses the `GLX_ARB_multisample` extension to create contexts with
+multisampling anti-aliasing.  Where this extension is unavailable, the
+`GLFW_SAMPLES` hint will have no effect.
+
+GLFW uses the `GLX_ARB_create_context` extension when available, even when
+creating OpenGL contexts of version 2.1 and below.  Where this extension is
+unavailable, the `GLFW_CONTEXT_VERSION_MAJOR` and `GLFW_CONTEXT_VERSION_MINOR`
+hints will only be partially supported, the `GLFW_OPENGL_DEBUG_CONTEXT` hint
+will have no effect, and setting the `GLFW_OPENGL_PROFILE` or
+`GLFW_OPENGL_FORWARD_COMPAT` hints to `GLFW_TRUE` will cause @ref
+glfwCreateWindow to fail.
+
+GLFW uses the `GLX_ARB_create_context_profile` extension to provide support for
+context profiles.  Where this extension is unavailable, setting the
+`GLFW_OPENGL_PROFILE` hint to anything but `GLFW_OPENGL_ANY_PROFILE`, or setting
+`GLFW_CLIENT_API` to anything but `GLFW_OPENGL_API` or `GLFW_NO_API` will cause
+@ref glfwCreateWindow to fail.
+
+GLFW uses the `GLX_ARB_context_flush_control` extension to provide control over
+whether a context is flushed when it is released (made non-current).  Where this
+extension is unavailable, the `GLFW_CONTEXT_RELEASE_BEHAVIOR` hint will have no
+effect and the context will always be flushed when released.
+
+GLFW uses the `GLX_ARB_framebuffer_sRGB` and `GLX_EXT_framebuffer_sRGB`
+extensions to provide support for sRGB framebuffers.  Where both of these
+extensions are unavailable, the `GLFW_SRGB_CAPABLE` hint will have no effect.
+
+
+@section compat_wgl WGL extensions
+
+The WGL API is used to create OpenGL contexts on Microsoft Windows and other
+implementations of the Win32 API, such as Wine.
+
+GLFW uses either the `WGL_EXT_extension_string` or the
+`WGL_ARB_extension_string` extension to check for the presence of all other WGL
+extensions listed below.  If both are available, the EXT one is preferred.  If
+neither is available, no other extensions are used and many GLFW features
+related to context creation will have no effect or cause errors when used.
+
+GLFW uses the `WGL_EXT_swap_control` extension to provide vertical retrace
+synchronization (or _vsync_).  Where this extension is unavailable, calling @ref
+glfwSwapInterval will have no effect.
+
+GLFW uses the `WGL_ARB_pixel_format` and `WGL_ARB_multisample` extensions to
+create contexts with multisampling anti-aliasing.  Where these extensions are
+unavailable, the `GLFW_SAMPLES` hint will have no effect.
+
+GLFW uses the `WGL_ARB_create_context` extension when available, even when
+creating OpenGL contexts of version 2.1 and below.  Where this extension is
+unavailable, the `GLFW_CONTEXT_VERSION_MAJOR` and `GLFW_CONTEXT_VERSION_MINOR`
+hints will only be partially supported, the `GLFW_OPENGL_DEBUG_CONTEXT` hint
+will have no effect, and setting the `GLFW_OPENGL_PROFILE` or
+`GLFW_OPENGL_FORWARD_COMPAT` hints to `GLFW_TRUE` will cause @ref
+glfwCreateWindow to fail.
+
+GLFW uses the `WGL_ARB_create_context_profile` extension to provide support for
+context profiles.  Where this extension is unavailable, setting the
+`GLFW_OPENGL_PROFILE` hint to anything but `GLFW_OPENGL_ANY_PROFILE` will cause
+@ref glfwCreateWindow to fail.
+
+GLFW uses the `WGL_ARB_context_flush_control` extension to provide control over
+whether a context is flushed when it is released (made non-current).  Where this
+extension is unavailable, the `GLFW_CONTEXT_RELEASE_BEHAVIOR` hint will have no
+effect and the context will always be flushed when released.
+
+GLFW uses the `WGL_ARB_framebuffer_sRGB` and `WGL_EXT_framebuffer_sRGB`
+extensions to provide support for sRGB framebuffers.  Where both of these
+extension are unavailable, the `GLFW_SRGB_CAPABLE` hint will have no effect.
+
+
+@section compat_osx OpenGL on macOS
+
+Support for OpenGL 3.2 and above was introduced with OS X 10.7 and even then
+only forward-compatible, core profile contexts are supported.  Support for
+OpenGL 4.1 was introduced with OS X 10.9, also limited to forward-compatible,
+core profile contexts.  There is also still no mechanism for requesting debug
+contexts or no-error contexts.  Versions of Mac OS X earlier than 10.7 support
+at most OpenGL version 2.1.
+
+Because of this, on OS X 10.7 and later, the `GLFW_CONTEXT_VERSION_MAJOR` and
+`GLFW_CONTEXT_VERSION_MINOR` hints will cause @ref glfwCreateWindow to fail if
+given version 3.0 or 3.1.  The `GLFW_OPENGL_FORWARD_COMPAT` hint must be set to
+`GLFW_TRUE` and the `GLFW_OPENGL_PROFILE` hint must be set to
+`GLFW_OPENGL_CORE_PROFILE` when creating OpenGL 3.2 and later contexts.  The
+`GLFW_OPENGL_DEBUG_CONTEXT` and `GLFW_CONTEXT_NO_ERROR` hints are ignored.
+
+Also, on Mac OS X 10.6 and below, the `GLFW_CONTEXT_VERSION_MAJOR` and
+`GLFW_CONTEXT_VERSION_MINOR` hints will fail if given a version above 2.1,
+setting the `GLFW_OPENGL_PROFILE` or `GLFW_OPENGL_FORWARD_COMPAT` hints to
+a non-default value will cause @ref glfwCreateWindow to fail and the
+`GLFW_OPENGL_DEBUG_CONTEXT` hint is ignored.
+
+
+@section compat_vulkan Vulkan loader and API
+
+By default, GLFW uses the standard system-wide Vulkan loader to access the
+Vulkan API on all platforms except macOS.  This is installed by both graphics
+drivers and Vulkan SDKs.  If either the loader or at least one minimally
+functional ICD is missing, @ref glfwVulkanSupported will return `GLFW_FALSE` and
+all other Vulkan-related functions will fail with an @ref GLFW_API_UNAVAILABLE
+error.
+
+
+@section compat_wsi Vulkan WSI extensions
+
+The Vulkan WSI extensions are used to create Vulkan surfaces for GLFW windows on
+all supported platforms.
+
+GLFW uses the `VK_KHR_surface` and `VK_KHR_win32_surface` extensions to create
+surfaces on Microsoft Windows.  If any of these extensions are not available,
+@ref glfwGetRequiredInstanceExtensions will return an empty list and window
+surface creation will fail.
+
+GLFW uses the `VK_KHR_surface` and either the `VK_MVK_macos_surface` or
+`VK_EXT_metal_surface` extensions to create surfaces on macOS.  If any of these
+extensions are not available, @ref glfwGetRequiredInstanceExtensions will
+return an empty list and window surface creation will fail.
+
+GLFW uses the `VK_KHR_surface` and either the `VK_KHR_xlib_surface` or
+`VK_KHR_xcb_surface` extensions to create surfaces on X11.  If `VK_KHR_surface`
+or both `VK_KHR_xlib_surface` and `VK_KHR_xcb_surface` are not available, @ref
+glfwGetRequiredInstanceExtensions will return an empty list and window surface
+creation will fail.
+
+GLFW uses the `VK_KHR_surface` and `VK_KHR_wayland_surface` extensions to create
+surfaces on Wayland.  If any of these extensions are not available, @ref
+glfwGetRequiredInstanceExtensions will return an empty list and window surface
+creation will fail.
+
+*/

+ 365 - 0
samples/third_party/glfw/docs/compile.dox

@@ -0,0 +1,365 @@
+/*!
+
+@page compile_guide Compiling GLFW
+
+@tableofcontents
+
+This is about compiling the GLFW library itself.  For information on how to
+build applications that use GLFW, see @ref build_guide.
+
+
+@section compile_cmake Using CMake
+
+@note GLFW behaves like most other libraries that use CMake so this guide mostly
+describes the basic configure/generate/compile sequence.  If you are already
+familiar with this from other projects, you may want to focus on the @ref
+compile_deps and @ref compile_options sections for GLFW-specific information.
+
+GLFW uses [CMake](https://cmake.org/) to generate project files or makefiles
+for your chosen development environment.  To compile GLFW, first generate these
+files with CMake and then use them to compile the GLFW library. 
+
+If you are on Windows and macOS you can
+[download CMake](https://cmake.org/download/) from their site.
+
+If you are on a Unix-like system such as Linux, FreeBSD or Cygwin or have
+a package system like Fink, MacPorts or Homebrew, you can install its CMake
+package.
+
+CMake is a complex tool and this guide will only show a few of the possible ways
+to set up and compile GLFW.  The CMake project has their own much more detailed
+[CMake user guide](https://cmake.org/cmake/help/latest/guide/user-interaction/)
+that includes everything in this guide not specific to GLFW.  It may be a useful
+companion to this one.
+
+
+@subsection compile_deps Installing dependencies
+
+The C/C++ development environments in Visual Studio, Xcode and MinGW come with
+all necessary dependencies for compiling GLFW, but on Unix-like systems like
+Linux and FreeBSD you will need a few extra packages.
+
+
+@subsubsection compile_deps_x11 Dependencies for X11 on Unix-like systems
+
+To compile GLFW for X11, you need to have the X11 development packages
+installed.  They are not needed to build or run programs that use GLFW.
+
+On Debian and derivates like Ubuntu and Linux Mint the `xorg-dev` meta-package
+pulls in the development packages for all of X11.
+
+@code{.sh}
+sudo apt install xorg-dev
+@endcode
+
+On Fedora and derivatives like Red Hat the X11 extension packages
+`libXcursor-devel`, `libXi-devel`, `libXinerama-devel` and `libXrandr-devel`
+required by GLFW pull in all its other dependencies.
+
+@code{.sh}
+sudo dnf install libXcursor-devel libXi-devel libXinerama-devel libXrandr-devel
+@endcode
+
+On FreeBSD the X11 headers are installed along the end-user X11 packages, so if
+you have an X server running you should have the headers as well.  If not,
+install the `xorgproto` package.
+
+@code{.sh}
+pkg install xorgproto
+@endcode
+
+On Cygwin the `xorgproto` package in the Devel section of the GUI installer will
+install the headers and other development related files for all of X11.
+
+Once you have the required depdendencies, move on to @ref compile_generate.
+
+
+@subsubsection compile_deps_wayland Dependencies for Wayland on Unix-like systems
+
+To compile GLFW for Wayland, you need to have the Wayland and xkbcommon
+development packages installed.  They are not needed to build or run programs
+that use GLFW.
+
+On Debian and derivates like Ubuntu and Linux Mint you will need the `libwayland-dev`,
+`libxkbcommon-dev`, `wayland-protocols` and `extra-cmake-modules` packages.
+
+@code{.sh}
+sudo apt install libwayland-dev libxkbcommon-dev wayland-protocols extra-cmake-modules
+@endcode
+
+On Fedora and derivatives like Red Hat you will need the `wayland-devel`,
+`libxkbcommon-devel`, `wayland-protocols-devel` and `extra-cmake-modules` packages.
+
+@code{.sh}
+sudo dnf install wayland-devel libxkbcommon-devel wayland-protocols-devel extra-cmake-modules
+@endcode
+
+On FreeBSD you will need the `wayland`, `libxkbcommon`, `wayland-protocols` and
+`kf5-extra-cmake-modules` packages.
+
+@code{.sh}
+pkg install wayland libxkbcommon wayland-protocols kf5-extra-cmake-modules
+@endcode
+
+Once you have the required depdendencies, move on to @ref compile_generate.
+
+
+@subsection compile_generate Generating build files with CMake
+
+Once you have all necessary dependencies it is time to generate the project
+files or makefiles for your development environment.  CMake needs two paths for
+this:
+
+ - the path to the root directory of the GLFW source tree (not its `src`
+   subdirectory)
+ - the path to the directory where the generated build files and compiled
+   binaries will be placed
+
+If these are the same, it is called an in-tree build, otherwise it is called an
+out-of-tree build.
+
+Out-of-tree builds are recommended as they avoid cluttering up the source tree.
+They also allow you to have several build directories for different
+configurations all using the same source tree.
+
+A common pattern when building a single configuration is to have a build
+directory named `build` in the root of the source tree.
+
+
+@subsubsection compile_generate_gui Generating files with the CMake GUI
+
+Start the CMake GUI and set the paths to the source and build directories
+described above.  Then press _Configure_ and _Generate_.
+
+If you wish change any CMake variables in the list, press _Configure_ and then
+_Generate_ to have the new values take effect.  The variable list will be
+populated after the first configure step.
+
+By default GLFW will use X11 on Linux and other Unix-like systems other
+than macOS.  To use Wayland instead, set the `GLFW_USE_WAYLAND` option in the
+GLFW section of the variable list, then apply the new value as described above.
+
+Once you have generated the project files or makefiles for your chosen
+development environment, move on to @ref compile_compile.
+
+
+@subsubsection compile_generate_cli Generating files with the CMake command-line tool
+
+To make a build directory, pass the source and build directories to the `cmake`
+command.  These can be relative or absolute paths.  The build directory is
+created if it doesn't already exist.
+
+@code{.sh}
+cmake -S path/to/glfw -B path/to/build
+@endcode
+
+It is common to name the build directory `build` and place it in the root of the
+source tree when only planning to build a single configuration.
+
+@code{.sh}
+cd path/to/glfw
+cmake -S . -B build
+@endcode
+
+Without other flags these will generate Visual Studio project files on Windows
+and makefiles on other platforms.  You can choose other targets using the `-G`
+flag.
+
+@code{.sh}
+cmake -S path/to/glfw -B path/to/build -G Xcode
+@endcode
+
+By default GLFW will use X11 on Linux and other Unix-like systems other
+than macOS.  To use Wayland instead, set the `GLFW_USE_WAYLAND` CMake option.
+
+@code{.sh}
+cmake -S path/to/glfw -B path/to/build -D GLFW_USE_WAYLAND=1
+@endcode
+
+Once you have generated the project files or makefiles for your chosen
+development environment, move on to @ref compile_compile.
+
+
+@subsection compile_compile Compiling the library
+
+You should now have all required dependencies and the project files or makefiles
+necessary to compile GLFW.  Go ahead and compile the actual GLFW library with
+these files as you would with any other project.
+
+With Visual Studio open `GLFW.sln` and use the Build menu.  With Xcode open
+`GLFW.xcodeproj` and use the Project menu.
+
+With Linux, macOS and other forms of Unix, run `make`.
+
+@code{.sh}
+cd path/to/build
+make
+@endcode
+
+With MinGW, it is `mingw32-make`.
+
+@code{.sh}
+cd path/to/build
+mingw32-make
+@endcode
+
+Any CMake build directory can also be built with the `cmake` command and the
+`--build` flag.
+
+@code{.sh}
+cmake --build path/to/build
+@endcode
+
+This will run the platform specific build tool the directory was generated for.
+
+Once the GLFW library is compiled you are ready to build your application,
+linking it to the GLFW library.  See @ref build_guide for more information.
+
+
+@section compile_options CMake options
+
+The CMake files for GLFW provide a number of options, although not all are
+available on all supported platforms.  Some of these are de facto standards
+among projects using CMake and so have no `GLFW_` prefix.
+
+If you are using the GUI version of CMake, these are listed and can be changed
+from there.  If you are using the command-line version of CMake you can use the
+`ccmake` ncurses GUI to set options.  Some package systems like Ubuntu and other
+distributions based on Debian GNU/Linux have this tool in a separate
+`cmake-curses-gui` package.
+
+Finally, if you don't want to use any GUI, you can set options from the `cmake`
+command-line with the `-D` flag.
+
+@code{.sh}
+cmake -S path/to/glfw -B path/to/build -D BUILD_SHARED_LIBS=ON
+@endcode
+
+
+@subsection compile_options_shared Shared CMake options
+
+@anchor BUILD_SHARED_LIBS
+__BUILD_SHARED_LIBS__ determines whether GLFW is built as a static
+library or as a DLL / shared library / dynamic library.  This is disabled by
+default, producing a static GLFW library.
+
+@anchor GLFW_BUILD_EXAMPLES
+__GLFW_BUILD_EXAMPLES__ determines whether the GLFW examples are built
+along with the library.
+
+@anchor GLFW_BUILD_TESTS
+__GLFW_BUILD_TESTS__ determines whether the GLFW test programs are
+built along with the library.
+
+@anchor GLFW_BUILD_DOCS
+__GLFW_BUILD_DOCS__ determines whether the GLFW documentation is built along
+with the library.  This is enabled by default if
+[Doxygen](https://www.doxygen.nl/) is found by CMake during configuration.
+
+@anchor GLFW_VULKAN_STATIC
+__GLFW_VULKAN_STATIC__ determines whether to use the Vulkan loader linked
+directly with the application.  This is disabled by default.
+
+
+@subsection compile_options_win32 Windows specific CMake options
+
+@anchor USE_MSVC_RUNTIME_LIBRARY_DLL
+__USE_MSVC_RUNTIME_LIBRARY_DLL__ determines whether to use the DLL version or the
+static library version of the Visual C++ runtime library.  When enabled, the
+DLL version of the Visual C++ library is used.  This is enabled by default.
+
+On CMake 3.15 and later you can set the standard CMake
+[CMAKE_MSVC_RUNTIME_LIBRARY](https://cmake.org/cmake/help/latest/variable/CMAKE_MSVC_RUNTIME_LIBRARY.html)
+variable instead of this GLFW-specific option.
+
+@anchor GLFW_USE_HYBRID_HPG
+__GLFW_USE_HYBRID_HPG__ determines whether to export the `NvOptimusEnablement` and
+`AmdPowerXpressRequestHighPerformance` symbols, which force the use of the
+high-performance GPU on Nvidia Optimus and AMD PowerXpress systems.  These symbols
+need to be exported by the EXE to be detected by the driver, so the override
+will not work if GLFW is built as a DLL.  This is disabled by default, letting
+the operating system and driver decide.
+
+
+@subsection compile_options_wayland Wayland specific CMake options
+
+@anchor GLFW_USE_WAYLAND
+__GLFW_USE_WAYLAND__ determines whether to compile the library for Wayland.
+This option is only available on Linux and other Unix-like systems other than
+macOS.  This is disabled by default.
+
+
+@section compile_mingw_cross Cross-compilation with CMake and MinGW
+
+Both Cygwin and many Linux distributions have MinGW or MinGW-w64 packages.  For
+example, Cygwin has the `mingw64-i686-gcc` and `mingw64-x86_64-gcc` packages
+for 32- and 64-bit version of MinGW-w64, while Debian GNU/Linux and derivatives
+like Ubuntu have the `mingw-w64` package for both.
+
+GLFW has CMake toolchain files in the `CMake` subdirectory that set up
+cross-compilation of Windows binaries.  To use these files you set the
+`CMAKE_TOOLCHAIN_FILE` CMake variable with the `-D` flag add an option when
+configuring and generating the build files.
+
+@code{.sh}
+cmake -S path/to/glfw -B path/to/build -D CMAKE_TOOLCHAIN_FILE=path/to/file
+@endcode
+
+The exact toolchain file to use depends on the prefix used by the MinGW or
+MinGW-w64 binaries on your system.  You can usually see this in the /usr
+directory.  For example, both the Ubuntu and Cygwin MinGW-w64 packages have
+`/usr/x86_64-w64-mingw32` for the 64-bit compilers, so the correct invocation
+would be:
+
+@code{.sh}
+cmake -S path/to/glfw -B path/to/build -D CMAKE_TOOLCHAIN_FILE=CMake/x86_64-w64-mingw32.cmake
+@endcode
+
+The path to the toolchain file is relative to the path to the GLFW source tree
+passed to the `-S` flag, not to the current directory.
+
+For more details see the
+[CMake toolchain guide](https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html).
+
+
+@section compile_manual Compiling GLFW manually
+
+If you wish to compile GLFW without its CMake build environment then you will
+have to do at least some of the platform detection yourself.  GLFW needs
+a configuration macro to be defined in order to know what window system it is
+being compiled for and also has optional, platform-specific ones for various
+features.
+
+When building with CMake, the `glfw_config.h` configuration header is generated
+based on the current platform and CMake options.  The GLFW CMake environment
+defines @b GLFW_USE_CONFIG_H, which causes this header to be included by
+`internal.h`.  Without this macro, GLFW will expect the necessary configuration
+macros to be defined on the command-line.
+
+The window creation API is used to create windows, handle input, monitors, gamma
+ramps and clipboard.  The options are:
+
+ - @b _GLFW_COCOA to use the Cocoa frameworks
+ - @b _GLFW_WIN32 to use the Win32 API
+ - @b _GLFW_X11 to use the X Window System
+ - @b _GLFW_WAYLAND to use the Wayland API (experimental and incomplete)
+ - @b _GLFW_OSMESA to use the OSMesa API (headless and non-interactive)
+
+If you are building GLFW as a shared library / dynamic library / DLL then you
+must also define @b _GLFW_BUILD_DLL.  Otherwise, you must not define it.
+
+If you are linking the Vulkan loader directly with your application then you
+must also define @b _GLFW_VULKAN_STATIC.  Otherwise, GLFW will attempt to use the
+external version.
+
+If you are using a custom name for the Vulkan, EGL, GLX, OSMesa, OpenGL, GLESv1
+or GLESv2 library, you can override the default names by defining those you need
+of @b _GLFW_VULKAN_LIBRARY, @b _GLFW_EGL_LIBRARY, @b _GLFW_GLX_LIBRARY, @b
+_GLFW_OSMESA_LIBRARY, @b _GLFW_OPENGL_LIBRARY, @b _GLFW_GLESV1_LIBRARY and @b
+_GLFW_GLESV2_LIBRARY.  Otherwise, GLFW will use the built-in default names.
+
+@note None of the @ref build_macros may be defined during the compilation of
+GLFW.  If you define any of these in your build files, make sure they are not
+applied to the GLFW sources.
+
+*/

+ 346 - 0
samples/third_party/glfw/docs/context.dox

@@ -0,0 +1,346 @@
+/*!
+
+@page context_guide Context guide
+
+@tableofcontents
+
+This guide introduces the OpenGL and OpenGL ES context related functions of
+GLFW.  For details on a specific function in this category, see the @ref
+context.  There are also guides for the other areas of the GLFW API.
+
+ - @ref intro_guide
+ - @ref window_guide
+ - @ref vulkan_guide
+ - @ref monitor_guide
+ - @ref input_guide
+
+
+@section context_object Context objects
+
+A window object encapsulates both a top-level window and an OpenGL or OpenGL ES
+context.  It is created with @ref glfwCreateWindow and destroyed with @ref
+glfwDestroyWindow or @ref glfwTerminate.  See @ref window_creation for more
+information.
+
+As the window and context are inseparably linked, the window object also serves
+as the context handle.
+
+To test the creation of various kinds of contexts and see their properties, run
+the `glfwinfo` test program.
+
+@note Vulkan does not have a context and the Vulkan instance is created via the
+Vulkan API itself.  If you will be using Vulkan to render to a window, disable
+context creation by setting the [GLFW_CLIENT_API](@ref GLFW_CLIENT_API_hint)
+hint to `GLFW_NO_API`.  For more information, see the @ref vulkan_guide.
+
+
+@subsection context_hints Context creation hints
+
+There are a number of hints, specified using @ref glfwWindowHint, related to
+what kind of context is created.  See
+[context related hints](@ref window_hints_ctx) in the window guide.
+
+
+@subsection context_sharing Context object sharing
+
+When creating a window and its OpenGL or OpenGL ES context with @ref
+glfwCreateWindow, you can specify another window whose context the new one
+should share its objects (textures, vertex and element buffers, etc.) with.
+
+@code
+GLFWwindow* second_window = glfwCreateWindow(640, 480, "Second Window", NULL, first_window);
+@endcode
+
+Object sharing is implemented by the operating system and graphics driver.  On
+platforms where it is possible to choose which types of objects are shared, GLFW
+requests that all types are shared.
+
+See the relevant chapter of the [OpenGL](https://www.opengl.org/registry/) or
+[OpenGL ES](https://www.khronos.org/opengles/) reference documents for more
+information.  The name and number of this chapter unfortunately varies between
+versions and APIs, but has at times been named _Shared Objects and Multiple
+Contexts_.
+
+GLFW comes with a barebones object sharing example program called `sharing`.
+
+
+@subsection context_offscreen Offscreen contexts
+
+GLFW doesn't support creating contexts without an associated window.  However,
+contexts with hidden windows can be created with the
+[GLFW_VISIBLE](@ref GLFW_VISIBLE_hint) window hint.
+
+@code
+glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
+
+GLFWwindow* offscreen_context = glfwCreateWindow(640, 480, "", NULL, NULL);
+@endcode
+
+The window never needs to be shown and its context can be used as a plain
+offscreen context.  Depending on the window manager, the size of a hidden
+window's framebuffer may not be usable or modifiable, so framebuffer
+objects are recommended for rendering with such contexts.
+
+You should still [process events](@ref events) as long as you have at least one
+window, even if none of them are visible.
+
+@macos The first time a window is created the menu bar is created.  This is not
+desirable for example when writing a command-line only application.  Menu bar
+creation can be disabled with the @ref GLFW_COCOA_MENUBAR init hint.
+
+
+@subsection context_less Windows without contexts
+
+You can disable context creation by setting the
+[GLFW_CLIENT_API](@ref GLFW_CLIENT_API_hint) hint to `GLFW_NO_API`.  Windows
+without contexts must not be passed to @ref glfwMakeContextCurrent or @ref
+glfwSwapBuffers.
+
+
+@section context_current Current context
+
+Before you can make OpenGL or OpenGL ES calls, you need to have a current
+context of the correct type.  A context can only be current for a single thread
+at a time, and a thread can only have a single context current at a time.
+
+When moving a context between threads, you must make it non-current on the old
+thread before making it current on the new one.
+
+The context of a window is made current with @ref glfwMakeContextCurrent.
+
+@code
+glfwMakeContextCurrent(window);
+@endcode
+
+The window of the current context is returned by @ref glfwGetCurrentContext.
+
+@code
+GLFWwindow* window = glfwGetCurrentContext();
+@endcode
+
+The following GLFW functions require a context to be current.  Calling any these
+functions without a current context will generate a @ref GLFW_NO_CURRENT_CONTEXT
+error.
+
+ - @ref glfwSwapInterval
+ - @ref glfwExtensionSupported
+ - @ref glfwGetProcAddress
+
+
+@section context_swap Buffer swapping
+
+See @ref buffer_swap in the window guide.
+
+
+@section context_glext OpenGL and OpenGL ES extensions
+
+One of the benefits of OpenGL and OpenGL ES is their extensibility.
+Hardware vendors may include extensions in their implementations that extend the
+API before that functionality is included in a new version of the OpenGL or
+OpenGL ES specification, and some extensions are never included and remain
+as extensions until they become obsolete.
+
+An extension is defined by:
+
+- An extension name (e.g. `GL_ARB_gl_spirv`)
+- New OpenGL tokens (e.g. `GL_SPIR_V_BINARY_ARB`)
+- New OpenGL functions (e.g. `glSpecializeShaderARB`)
+
+Note the `ARB` affix, which stands for Architecture Review Board and is used
+for official extensions.  The extension above was created by the ARB, but there
+are many different affixes, like `NV` for Nvidia and `AMD` for, well, AMD.  Any
+group may also use the generic `EXT` affix.  Lists of extensions, together with
+their specifications, can be found at the
+[OpenGL Registry](https://www.opengl.org/registry/) and
+[OpenGL ES Registry](https://www.khronos.org/registry/gles/).
+
+
+@subsection context_glext_auto Loading extension with a loader library
+
+An extension loader library is the easiest and best way to access both OpenGL and
+OpenGL ES extensions and modern versions of the core OpenGL or OpenGL ES APIs.
+They will take care of all the details of declaring and loading everything you
+need.  One such library is [glad](https://github.com/Dav1dde/glad) and there are
+several others.
+
+The following example will use glad but all extension loader libraries work
+similarly.
+
+First you need to generate the source files using the glad Python script.  This
+example generates a loader for any version of OpenGL, which is the default for
+both GLFW and glad, but loaders for OpenGL ES, as well as loaders for specific
+API versions and extension sets can be generated.  The generated files are
+written to the `output` directory.
+
+@code{.sh}
+python main.py --generator c --no-loader --out-path output
+@endcode
+
+The `--no-loader` option is added because GLFW already provides a function for
+loading OpenGL and OpenGL ES function pointers, one that automatically uses the
+selected context creation API, and glad can call this instead of having to
+implement its own.  There are several other command-line options as well.  See
+the glad documentation for details.
+
+Add the generated `output/src/glad.c`, `output/include/glad/glad.h` and
+`output/include/KHR/khrplatform.h` files to your build.  Then you need to
+include the glad header file, which will replace the OpenGL header of your
+development environment.  By including the glad header before the GLFW header,
+it suppresses the development environment's OpenGL or OpenGL ES header.
+
+@code
+#include <glad/glad.h>
+#include <GLFW/glfw3.h>
+@endcode
+
+Finally you need to initialize glad once you have a suitable current context.
+
+@code
+window = glfwCreateWindow(640, 480, "My Window", NULL, NULL);
+if (!window)
+{
+    ...
+}
+
+glfwMakeContextCurrent(window);
+
+gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);
+@endcode
+
+Once glad has been loaded, you have access to all OpenGL core and extension
+functions supported by both the context you created and the glad loader you
+generated and you are ready to start rendering.
+
+You can specify a minimum required OpenGL or OpenGL ES version with
+[context hints](@ref window_hints_ctx).  If your needs are more complex, you can
+check the actual OpenGL or OpenGL ES version with
+[context attributes](@ref window_attribs_ctx), or you can check whether
+a specific version is supported by the current context with the
+`GLAD_GL_VERSION_x_x` booleans.
+
+@code
+if (GLAD_GL_VERSION_3_2)
+{
+    // Call OpenGL 3.2+ specific code
+}
+@endcode
+
+To check whether a specific extension is supported, use the `GLAD_GL_xxx`
+booleans.
+
+@code
+if (GLAD_GL_ARB_gl_spirv)
+{
+    // Use GL_ARB_gl_spirv
+}
+@endcode
+
+
+@subsection context_glext_manual Loading extensions manually
+
+__Do not use this technique__ unless it is absolutely necessary.  An
+[extension loader library](@ref context_glext_auto) will save you a ton of
+tedious, repetitive, error prone work.
+
+To use a certain extension, you must first check whether the context supports
+that extension and then, if it introduces new functions, retrieve the pointers
+to those functions.  GLFW provides @ref glfwExtensionSupported and @ref
+glfwGetProcAddress for manual loading of extensions and new API functions.
+
+This section will demonstrate manual loading of OpenGL extensions.  The loading
+of OpenGL ES extensions is identical except for the name of the extension header.
+
+
+@subsubsection context_glext_header The glext.h header
+
+The `glext.h` extension header is a continually updated file that defines the
+interfaces for all OpenGL extensions.  The latest version of this can always be
+found at the [OpenGL Registry](https://www.opengl.org/registry/).  There are also
+extension headers for the various versions of OpenGL ES at the
+[OpenGL ES Registry](https://www.khronos.org/registry/gles/).  It it strongly
+recommended that you use your own copy of the extension header, as the one
+included in your development environment may be several years out of date and
+may not include the extensions you wish to use.
+
+The header defines function pointer types for all functions of all extensions it
+supports.  These have names like `PFNGLSPECIALIZESHADERARBPROC` (for
+`glSpecializeShaderARB`), i.e. the name is made uppercase and `PFN` (pointer
+to function) and `PROC` (procedure) are added to the ends.
+
+To include the extension header, define @ref GLFW_INCLUDE_GLEXT before including
+the GLFW header.
+
+@code
+#define GLFW_INCLUDE_GLEXT
+#include <GLFW/glfw3.h>
+@endcode
+
+
+@subsubsection context_glext_string Checking for extensions
+
+A given machine may not actually support the extension (it may have older
+drivers or a graphics card that lacks the necessary hardware features), so it
+is necessary to check at run-time whether the context supports the extension.
+This is done with @ref glfwExtensionSupported.
+
+@code
+if (glfwExtensionSupported("GL_ARB_gl_spirv"))
+{
+    // The extension is supported by the current context
+}
+@endcode
+
+The argument is a null terminated ASCII string with the extension name.  If the
+extension is supported, @ref glfwExtensionSupported returns `GLFW_TRUE`,
+otherwise it returns `GLFW_FALSE`.
+
+
+@subsubsection context_glext_proc Fetching function pointers
+
+Many extensions, though not all, require the use of new OpenGL functions.
+These functions often do not have entry points in the client API libraries of
+your operating system, making it necessary to fetch them at run time.  You can
+retrieve pointers to these functions with @ref glfwGetProcAddress.
+
+@code
+PFNGLSPECIALIZESHADERARBPROC pfnSpecializeShaderARB = glfwGetProcAddress("glSpecializeShaderARB");
+@endcode
+
+In general, you should avoid giving the function pointer variables the (exact)
+same name as the function, as this may confuse your linker.  Instead, you can
+use a different prefix, like above, or some other naming scheme.
+
+Now that all the pieces have been introduced, here is what they might look like
+when used together.
+
+@code
+#define GLFW_INCLUDE_GLEXT
+#include <GLFW/glfw3.h>
+
+#define glSpecializeShaderARB pfnSpecializeShaderARB
+PFNGLSPECIALIZESHADERARBPROC pfnSpecializeShaderARB;
+
+// Flag indicating whether the extension is supported
+int has_ARB_gl_spirv = 0;
+
+void load_extensions(void)
+{
+    if (glfwExtensionSupported("GL_ARB_gl_spirv"))
+    {
+        pfnSpecializeShaderARB = (PFNGLSPECIALIZESHADERARBPROC)
+            glfwGetProcAddress("glSpecializeShaderARB");
+        has_ARB_gl_spirv = 1;
+    }
+}
+
+void some_function(void)
+{
+    if (has_ARB_gl_spirv)
+    {
+        // Now the extension function can be called as usual
+        glSpecializeShaderARB(...);
+    }
+}
+@endcode
+
+*/

ファイルの差分が大きいため隠しています
+ 1 - 0
samples/third_party/glfw/docs/extra.css


ファイルの差分が大きいため隠しています
+ 1 - 0
samples/third_party/glfw/docs/extra.css.map


+ 430 - 0
samples/third_party/glfw/docs/extra.scss

@@ -0,0 +1,430 @@
+// NOTE: Please use this file to perform modifications on default style sheets.
+//
+// You need to install the official Sass CLI tool:
+// npm install -g sass
+//
+// Run this command to regenerate extra.css after you're finished with changes:
+// sass --style=compressed extra.scss extra.css
+//
+// Alternatively you can use online services to regenerate extra.css.
+
+
+// Default text color for page contents
+$default-text-color: hsl(0,0%,30%);
+
+// Page header, footer, table rows, inline codes and definition lists
+$header-footer-background-color: hsl(0,0%,95%);
+
+// Page header, footer links and navigation bar background
+$header-footer-link-color: hsl(0,0%,40%);
+
+// Doxygen navigation bar links
+$navbar-link-color: $header-footer-background-color;
+
+// Page content background color
+$content-background-color: hsl(0,0%,100%);
+
+// Bold, italic, h1, h2, ... and table of contents
+$heading-color: hsl(0,0%,10%);
+
+// Function, enum and macro definition separator
+$def-separator-color: $header-footer-background-color;
+
+// Base color hue
+$base-hue: 24;
+
+// Default color used for links
+$default-link-color: hsl($base-hue,100%,50%);
+
+// Doxygen navigation bar active tab
+$tab-text-color: hsl(0,0%,100%);
+$tab-background-color1: $default-link-color;
+$tab-background-color2: lighten(adjust-hue($tab-background-color1, 10), 10%);
+
+// Table borders
+$default-border-color: $default-link-color;
+
+// Table header
+$table-text-color: $tab-text-color;
+$table-background-color1: $tab-background-color1;
+$table-background-color2: $tab-background-color2;
+
+// Table of contents, data structure index and prototypes
+$toc-background-color1: hsl(0,0%,90%);
+$toc-background-color2: lighten($toc-background-color1, 5%);
+
+// Function prototype parameters color
+$prototype-param-color: darken($default-link-color, 25%);
+
+// Message box color: note, pre, post and invariant
+$box-note-color: hsl(103,80%,85%);
+
+// Message box color: warning and attention
+$box-warning-color: hsl(34,80%,85%);
+
+// Message box color: deprecated and bug
+$box-bug-color: hsl(333,80%,85%);
+
+// Message box color: todo and test
+$box-todo-color: hsl(200,80%,85%);
+
+// Message box helper function
+@mixin message-box($base-color){
+	background:linear-gradient(to bottom,lighten($base-color, 5%) 0%,$base-color 100%);
+	box-shadow:inset 0 0 32px darken($base-color, 5%);
+	color:darken($base-color, 67%);
+	border:2px solid desaturate(darken($base-color, 10%), 20%);
+}
+
+.sm-dox,.sm-dox a,.sm-dox a:focus,.sm-dox a:active,.sm-dox a:hover,.sm-dox a.highlighted,.sm-dox ul a:hover {
+	background:none;
+	text-shadow:none;
+}
+
+.sm-dox a span.sub-arrow {
+	border-color:$navbar-link-color transparent transparent transparent;
+}
+
+.sm-dox a span.sub-arrow:active,.sm-dox a span.sub-arrow:focus,.sm-dox a span.sub-arrow:hover,.sm-dox a:hover span.sub-arrow {
+	border-color:$default-link-color transparent transparent transparent;
+}
+
+.sm-dox ul a span.sub-arrow:active,.sm-dox ul a span.sub-arrow:focus,.sm-dox ul a span.sub-arrow:hover,.sm-dox ul a:hover span.sub-arrow {
+	border-color:transparent transparent transparent $default-link-color;
+}
+
+.sm-dox ul a:hover {
+	background:$header-footer-link-color;
+	text-shadow:none;
+}
+
+.sm-dox ul.sm-nowrap a {
+	color:$default-text-color;
+	text-shadow:none;
+}
+
+#main-nav,#main-menu,#main-menu a,#main-menu a:visited,#main-menu a:hover,#main-menu li,.memdoc,dl.reflist dd,div.toc li,.ah,span.lineno,span.lineno a,span.lineno a:hover,.note code,.pre code,.post code,.invariant code,.warning code,.attention code,.deprecated code,.bug code,.todo code,.test code,.doxtable code,.markdownTable code {
+	background:none;
+}
+
+#titlearea,.footer,.contents,div.header,.memdoc,table.doxtable td,table.doxtable th,table.markdownTable td,table.markdownTable th,hr,.memSeparator {
+	border:none;
+}
+
+#main-menu a,#main-menu a:visited,#main-menu a:hover,#main-menu li,.reflist dt a.el,.levels span,.directory .levels span {
+	text-shadow:none;
+}
+
+.memdoc,dl.reflist dd {
+	box-shadow:none;
+}
+
+div.headertitle,.note code,.pre code,.post code,.invariant code,.warning code,.attention code,.deprecated code,.bug code,.todo code,.test code,table.doxtable code,table.markdownTable code {
+	padding:0;
+}
+
+#nav-path,.directory .levels,span.lineno {
+	display:none;
+}
+
+html,#titlearea,.footer,tr.even,.directory tr.even,.doxtable tr:nth-child(even),tr.markdownTableBody:nth-child(even),.mdescLeft,.mdescRight,.memItemLeft,.memItemRight,code,.markdownTableRowEven {
+	background:$header-footer-background-color;
+}
+
+body {
+	color:$default-text-color;
+}
+
+h1,h2,h2.groupheader,h3,div.toc h3,h4,h5,h6,strong,em {
+	color:$heading-color;
+	border-bottom:none;
+}
+
+h1 {
+	padding-top:0.5em;
+	font-size:180%;
+}
+
+h2 {
+	padding-top:0.5em;
+	margin-bottom:0;
+	font-size:140%;
+}
+
+h3 {
+	padding-top:0.5em;
+	margin-bottom:0;
+	font-size:110%;
+}
+
+.glfwheader {
+	font-size:16px;
+	min-height:64px;
+	max-width:920px;
+	padding:0 32px;
+	margin:0 auto;
+
+	display: flex;
+	flex-direction: row;
+	flex-wrap: wrap;
+	justify-content: flex-start;
+	align-items: center;
+	align-content: stretch;
+}
+
+#glfwhome {
+	line-height:64px;
+	padding-right:48px;
+	color:$header-footer-link-color;
+	font-size:2.5em;
+	background:url("https://www.glfw.org/css/arrow.png") no-repeat right;
+}
+
+.glfwnavbar {
+	list-style-type:none;
+	margin:0 0 0 auto;
+	float:right;
+}
+
+#glfwhome,.glfwnavbar li {
+	float:left;
+}
+
+.glfwnavbar a,.glfwnavbar a:visited {
+	line-height:64px;
+	margin-left:2em;
+	display:block;
+	color:$header-footer-link-color;
+}
+
+.glfwnavbar {
+	padding-left: 0;
+}
+
+#glfwhome,.glfwnavbar a,.glfwnavbar a:visited {
+	transition:.35s ease;
+}
+
+#titlearea,.footer {
+	color:$header-footer-link-color;
+}
+
+address.footer {
+	text-align:center;
+	padding:2em;
+	margin-top:3em;
+}
+
+#top {
+	background:$header-footer-link-color;
+}
+
+#main-nav {
+	max-width:960px;
+	margin:0 auto;
+	font-size:13px;
+}
+
+#main-menu {
+	max-width:920px;
+	margin:0 auto;
+	font-size:13px;
+}
+
+.memtitle {
+	display:none;
+}
+
+.memproto,.memname {
+	font-weight:bold;
+	text-shadow:none;
+}
+
+#main-menu {
+	min-height:36px;
+	display: flex;
+	flex-direction: row;
+	flex-wrap: wrap;
+	justify-content: flex-start;
+	align-items: center;
+	align-content: stretch;
+}
+
+#main-menu a,#main-menu a:visited,#main-menu a:hover,#main-menu li {
+	color:$navbar-link-color;
+}
+
+#main-menu li ul.sm-nowrap li a {
+	color:$default-text-color;
+}
+
+#main-menu li ul.sm-nowrap li a:hover {
+	color:$default-link-color;
+}
+
+#main-menu > li:last-child {
+	margin: 0 0 0 auto;
+}
+
+.contents {
+	min-height:590px;
+}
+
+div.contents,div.header {
+	max-width:920px;
+	margin:0 auto;
+	padding:0 32px;
+	background:$content-background-color none;
+}
+
+table.doxtable th,table.markdownTable th,dl.reflist dt {
+	background:linear-gradient(to bottom,$table-background-color2 0%,$table-background-color1 100%);
+	box-shadow:inset 0 0 32px $table-background-color1;
+	text-shadow:0 -1px 1px darken($table-background-color1, 15%);
+	text-align:left;
+	color:$table-text-color;
+}
+
+dl.reflist dt a.el {
+	color:$default-link-color;
+	padding:.2em;
+	border-radius:4px;
+	background-color:lighten($default-link-color, 40%);
+}
+
+div.toc {
+	float:none;
+	width:auto;
+}
+
+div.toc h3 {
+	font-size:1.17em;
+}
+
+div.toc ul {
+	padding-left:1.5em;
+}
+
+div.toc li {
+	font-size:1em;
+	padding-left:0;
+	list-style-type:disc;
+}
+
+div.toc,.memproto,div.qindex,div.ah {
+	background:linear-gradient(to bottom,$toc-background-color2 0%,$toc-background-color1 100%);
+	box-shadow:inset 0 0 32px $toc-background-color1;
+	text-shadow:0 1px 1px lighten($toc-background-color2, 10%);
+	color:$heading-color;
+	border:2px solid $toc-background-color1;
+	border-radius:4px;
+}
+
+.paramname {
+	color:$prototype-param-color;
+}
+
+dl.reflist dt {
+	border:2px solid $default-border-color;
+	border-top-left-radius:4px;
+	border-top-right-radius:4px;
+	border-bottom:none;
+}
+
+dl.reflist dd {
+	border:2px solid $default-border-color;
+	border-bottom-right-radius:4px;
+	border-bottom-left-radius:4px;
+	border-top:none;
+}
+
+table.doxtable,table.markdownTable {
+	border-collapse:inherit;
+	border-spacing:0;
+	border:2px solid $default-border-color;
+	border-radius:4px;
+}
+
+a,a:hover,a:visited,a:visited:hover,.contents a:visited,.el,a.el:visited,#glfwhome:hover,#main-menu a:hover,span.lineno a:hover {
+	color:$default-link-color;
+	text-decoration:none;
+}
+
+div.directory {
+	border-collapse:inherit;
+	border-spacing:0;
+	border:2px solid $default-border-color;
+	border-radius:4px;
+}
+
+hr,.memSeparator {
+	height:2px;
+	background:linear-gradient(to right,$def-separator-color 0%,darken($def-separator-color, 10%) 50%,$def-separator-color 100%);
+}
+
+dl.note,dl.pre,dl.post,dl.invariant {
+	@include message-box($box-note-color);
+}
+
+dl.warning,dl.attention {
+	@include message-box($box-warning-color);
+}
+
+dl.deprecated,dl.bug {
+	@include message-box($box-bug-color);
+}
+
+dl.todo,dl.test {
+	@include message-box($box-todo-color);
+}
+
+dl.note,dl.pre,dl.post,dl.invariant,dl.warning,dl.attention,dl.deprecated,dl.bug,dl.todo,dl.test {
+	border-radius:4px;
+	padding:1em;
+	text-shadow:0 1px 1px hsl(0,0%,100%);
+	margin:1em 0;
+}
+
+.note a,.pre a,.post a,.invariant a,.warning a,.attention a,.deprecated a,.bug a,.todo a,.test a,.note a:visited,.pre a:visited,.post a:visited,.invariant a:visited,.warning a:visited,.attention a:visited,.deprecated a:visited,.bug a:visited,.todo a:visited,.test a:visited {
+	color:inherit;
+}
+
+div.line {
+	line-height:inherit;
+}
+
+div.fragment,pre.fragment {
+	background:hsl(0,0%,95%);
+	border-radius:4px;
+	border:none;
+	padding:1em;
+	overflow:auto;
+	border-left:4px solid hsl(0,0%,80%);
+	margin:1em 0;
+}
+
+.lineno a,.lineno a:visited,.line,pre.fragment {
+	color:$default-text-color;
+}
+
+span.preprocessor,span.comment {
+	color:hsl(193,100%,30%);
+}
+
+a.code,a.code:visited {
+	color:hsl(18,100%,45%);
+}
+
+span.keyword,span.keywordtype,span.keywordflow {
+	color:darken($default-text-color, 5%);
+	font-weight:bold;
+}
+
+span.stringliteral {
+	color:hsl(261,100%,30%);
+}
+
+code {
+	padding:.1em;
+	border-radius:4px;
+}

+ 7 - 0
samples/third_party/glfw/docs/footer.html

@@ -0,0 +1,7 @@
+<address class="footer">
+<p>
+Last update on $date for $projectname $projectnumber
+</p>
+</address>
+</body>
+</html>

+ 34 - 0
samples/third_party/glfw/docs/header.html

@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen $doxygenversion"/>
+<!--BEGIN PROJECT_NAME--><title>$projectname: $title</title><!--END PROJECT_NAME-->
+<!--BEGIN !PROJECT_NAME--><title>$title</title><!--END !PROJECT_NAME-->
+<link href="$relpath^tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="$relpath^jquery.js"></script>
+<script type="text/javascript" src="$relpath^dynsections.js"></script>
+$treeview
+$search
+$mathjax
+<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" />
+$extrastylesheet
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+
+<!--BEGIN TITLEAREA-->
+<div id="titlearea">
+	<div class="glfwheader">
+		<a href="https://www.glfw.org/" id="glfwhome">GLFW</a>
+		<ul class="glfwnavbar">
+			<li><a href="https://www.glfw.org/documentation.html">Documentation</a></li>
+			<li><a href="https://www.glfw.org/download.html">Download</a></li>
+			<li><a href="https://www.glfw.org/community.html">Community</a></li>
+		</ul>
+	</div>
+</div>
+<!--END TITLEAREA-->
+<!-- end header part -->

+ 950 - 0
samples/third_party/glfw/docs/input.dox

@@ -0,0 +1,950 @@
+/*!
+
+@page input_guide Input guide
+
+@tableofcontents
+
+This guide introduces the input related functions of GLFW.  For details on
+a specific function in this category, see the @ref input.  There are also guides
+for the other areas of GLFW.
+
+ - @ref intro_guide
+ - @ref window_guide
+ - @ref context_guide
+ - @ref vulkan_guide
+ - @ref monitor_guide
+
+GLFW provides many kinds of input.  While some can only be polled, like time, or
+only received via callbacks, like scrolling, many provide both callbacks and
+polling.  Callbacks are more work to use than polling but is less CPU intensive
+and guarantees that you do not miss state changes.
+
+All input callbacks receive a window handle.  By using the
+[window user pointer](@ref window_userptr), you can access non-global structures
+or objects from your callbacks.
+
+To get a better feel for how the various events callbacks behave, run the
+`events` test program.  It register every callback supported by GLFW and prints
+out all arguments provided for every event, along with time and sequence
+information.
+
+
+@section events Event processing
+
+GLFW needs to poll the window system for events both to provide input to the
+application and to prove to the window system that the application hasn't locked
+up.  Event processing is normally done each frame after
+[buffer swapping](@ref buffer_swap).  Even when you have no windows, event
+polling needs to be done in order to receive monitor and joystick connection
+events.
+
+There are three functions for processing pending events.  @ref glfwPollEvents,
+processes only those events that have already been received and then returns
+immediately.
+
+@code
+glfwPollEvents();
+@endcode
+
+This is the best choice when rendering continuously, like most games do.
+
+If you only need to update the contents of the window when you receive new
+input, @ref glfwWaitEvents is a better choice.
+
+@code
+glfwWaitEvents();
+@endcode
+
+It puts the thread to sleep until at least one event has been received and then
+processes all received events.  This saves a great deal of CPU cycles and is
+useful for, for example, editing tools.
+
+If you want to wait for events but have UI elements or other tasks that need
+periodic updates, @ref glfwWaitEventsTimeout lets you specify a timeout.
+
+@code
+glfwWaitEventsTimeout(0.7);
+@endcode
+
+It puts the thread to sleep until at least one event has been received, or until
+the specified number of seconds have elapsed.  It then processes any received
+events.
+
+If the main thread is sleeping in @ref glfwWaitEvents, you can wake it from
+another thread by posting an empty event to the event queue with @ref
+glfwPostEmptyEvent.
+
+@code
+glfwPostEmptyEvent();
+@endcode
+
+Do not assume that callbacks will _only_ be called in response to the above
+functions.  While it is necessary to process events in one or more of the ways
+above, window systems that require GLFW to register callbacks of its own can
+pass events to GLFW in response to many window system function calls.  GLFW will
+pass those events on to the application callbacks before returning.
+
+For example, on Windows the system function that @ref glfwSetWindowSize is
+implemented with will send window size events directly to the event callback
+that every window has and that GLFW implements for its windows.  If you have set
+a [window size callback](@ref window_size) GLFW will call it in turn with the
+new size before everything returns back out of the @ref glfwSetWindowSize call.
+
+
+@section input_keyboard Keyboard input
+
+GLFW divides keyboard input into two categories; key events and character
+events.  Key events relate to actual physical keyboard keys, whereas character
+events relate to the Unicode code points generated by pressing some of them.
+
+Keys and characters do not map 1:1.  A single key press may produce several
+characters, and a single character may require several keys to produce.  This
+may not be the case on your machine, but your users are likely not all using the
+same keyboard layout, input method or even operating system as you.
+
+
+@subsection input_key Key input
+
+If you wish to be notified when a physical key is pressed or released or when it
+repeats, set a key callback.
+
+@code
+glfwSetKeyCallback(window, key_callback);
+@endcode
+
+The callback function receives the [keyboard key](@ref keys), platform-specific
+scancode, key action and [modifier bits](@ref mods).
+
+@code
+void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
+{
+    if (key == GLFW_KEY_E && action == GLFW_PRESS)
+        activate_airship();
+}
+@endcode
+
+The action is one of `GLFW_PRESS`, `GLFW_REPEAT` or `GLFW_RELEASE`.  The key
+will be `GLFW_KEY_UNKNOWN` if GLFW lacks a key token for it, for example
+_E-mail_ and _Play_ keys.
+
+The scancode is unique for every key, regardless of whether it has a key token.
+Scancodes are platform-specific but consistent over time, so keys will have
+different scancodes depending on the platform but they are safe to save to disk.
+You can query the scancode for any [named key](@ref keys) on the current
+platform with @ref glfwGetKeyScancode.
+
+@code
+const int scancode = glfwGetKeyScancode(GLFW_KEY_X);
+set_key_mapping(scancode, swap_weapons);
+@endcode
+
+The last reported state for every [named key](@ref keys) is also saved in
+per-window state arrays that can be polled with @ref glfwGetKey.
+
+@code
+int state = glfwGetKey(window, GLFW_KEY_E);
+if (state == GLFW_PRESS)
+{
+    activate_airship();
+}
+@endcode
+
+The returned state is one of `GLFW_PRESS` or `GLFW_RELEASE`.
+
+This function only returns cached key event state.  It does not poll the
+system for the current physical state of the key.
+
+@anchor GLFW_STICKY_KEYS
+Whenever you poll state, you risk missing the state change you are looking for.
+If a pressed key is released again before you poll its state, you will have
+missed the key press.  The recommended solution for this is to use a
+key callback, but there is also the `GLFW_STICKY_KEYS` input mode.
+
+@code
+glfwSetInputMode(window, GLFW_STICKY_KEYS, GLFW_TRUE);
+@endcode
+
+When sticky keys mode is enabled, the pollable state of a key will remain
+`GLFW_PRESS` until the state of that key is polled with @ref glfwGetKey.  Once
+it has been polled, if a key release event had been processed in the meantime,
+the state will reset to `GLFW_RELEASE`, otherwise it will remain `GLFW_PRESS`.
+
+@anchor GLFW_LOCK_KEY_MODS
+If you wish to know what the state of the Caps Lock and Num Lock keys was when
+input events were generated, set the `GLFW_LOCK_KEY_MODS` input mode.
+
+@code
+glfwSetInputMode(window, GLFW_LOCK_KEY_MODS, GLFW_TRUE);
+@endcode
+
+When this input mode is enabled, any callback that receives
+[modifier bits](@ref mods) will have the @ref GLFW_MOD_CAPS_LOCK bit set if Caps
+Lock was on when the event occurred and the @ref GLFW_MOD_NUM_LOCK bit set if
+Num Lock was on.
+
+The `GLFW_KEY_LAST` constant holds the highest value of any
+[named key](@ref keys).
+
+
+@subsection input_char Text input
+
+GLFW supports text input in the form of a stream of
+[Unicode code points](https://en.wikipedia.org/wiki/Unicode), as produced by the
+operating system text input system.  Unlike key input, text input obeys keyboard
+layouts and modifier keys and supports composing characters using
+[dead keys](https://en.wikipedia.org/wiki/Dead_key).  Once received, you can
+encode the code points into UTF-8 or any other encoding you prefer.
+
+Because an `unsigned int` is 32 bits long on all platforms supported by GLFW,
+you can treat the code point argument as native endian UTF-32.
+
+If you wish to offer regular text input, set a character callback.
+
+@code
+glfwSetCharCallback(window, character_callback);
+@endcode
+
+The callback function receives Unicode code points for key events that would
+have led to regular text input and generally behaves as a standard text field on
+that platform.
+
+@code
+void character_callback(GLFWwindow* window, unsigned int codepoint)
+{
+}
+@endcode
+
+
+@subsection input_key_name Key names
+
+If you wish to refer to keys by name, you can query the keyboard layout
+dependent name of printable keys with @ref glfwGetKeyName.
+
+@code
+const char* key_name = glfwGetKeyName(GLFW_KEY_W, 0);
+show_tutorial_hint("Press %s to move forward", key_name);
+@endcode
+
+This function can handle both [keys and scancodes](@ref input_key).  If the
+specified key is `GLFW_KEY_UNKNOWN` then the scancode is used, otherwise it is
+ignored.  This matches the behavior of the key callback, meaning the callback
+arguments can always be passed unmodified to this function.
+
+
+@section input_mouse Mouse input
+
+Mouse input comes in many forms, including mouse motion, button presses and
+scrolling offsets.  The cursor appearance can also be changed, either to
+a custom image or a standard cursor shape from the system theme.
+
+
+@subsection cursor_pos Cursor position
+
+If you wish to be notified when the cursor moves over the window, set a cursor
+position callback.
+
+@code
+glfwSetCursorPosCallback(window, cursor_position_callback);
+@endcode
+
+The callback functions receives the cursor position, measured in screen
+coordinates but relative to the top-left corner of the window content area.  On
+platforms that provide it, the full sub-pixel cursor position is passed on.
+
+@code
+static void cursor_position_callback(GLFWwindow* window, double xpos, double ypos)
+{
+}
+@endcode
+
+The cursor position is also saved per-window and can be polled with @ref
+glfwGetCursorPos.
+
+@code
+double xpos, ypos;
+glfwGetCursorPos(window, &xpos, &ypos);
+@endcode
+
+
+@subsection cursor_mode Cursor mode
+
+@anchor GLFW_CURSOR
+The `GLFW_CURSOR` input mode provides several cursor modes for special forms of
+mouse motion input.  By default, the cursor mode is `GLFW_CURSOR_NORMAL`,
+meaning the regular arrow cursor (or another cursor set with @ref glfwSetCursor)
+is used and cursor motion is not limited.
+
+If you wish to implement mouse motion based camera controls or other input
+schemes that require unlimited mouse movement, set the cursor mode to
+`GLFW_CURSOR_DISABLED`.
+
+@code
+glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
+@endcode
+
+This will hide the cursor and lock it to the specified window.  GLFW will then
+take care of all the details of cursor re-centering and offset calculation and
+providing the application with a virtual cursor position.  This virtual position
+is provided normally via both the cursor position callback and through polling.
+
+@note You should not implement your own version of this functionality using
+other features of GLFW.  It is not supported and will not work as robustly as
+`GLFW_CURSOR_DISABLED`.
+
+If you only wish the cursor to become hidden when it is over a window but still
+want it to behave normally, set the cursor mode to `GLFW_CURSOR_HIDDEN`.
+
+@code
+glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
+@endcode
+
+This mode puts no limit on the motion of the cursor.
+
+To exit out of either of these special modes, restore the `GLFW_CURSOR_NORMAL`
+cursor mode.
+
+@code
+glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
+@endcode
+
+
+@anchor GLFW_RAW_MOUSE_MOTION
+@subsection raw_mouse_motion Raw mouse motion
+
+When the cursor is disabled, raw (unscaled and unaccelerated) mouse motion can
+be enabled if available.
+
+Raw mouse motion is closer to the actual motion of the mouse across a surface.
+It is not affected by the scaling and acceleration applied to the motion of the
+desktop cursor.  That processing is suitable for a cursor while raw motion is
+better for controlling for example a 3D camera.  Because of this, raw mouse
+motion is only provided when the cursor is disabled.
+
+Call @ref glfwRawMouseMotionSupported to check if the current machine provides
+raw motion and set the `GLFW_RAW_MOUSE_MOTION` input mode to enable it.  It is
+disabled by default.
+
+@code
+if (glfwRawMouseMotionSupported())
+    glfwSetInputMode(window, GLFW_RAW_MOUSE_MOTION, GLFW_TRUE);
+@endcode
+
+If supported, raw mouse motion can be enabled or disabled per-window and at any
+time but it will only be provided when the cursor is disabled.
+
+
+@subsection cursor_object Cursor objects
+
+GLFW supports creating both custom and system theme cursor images, encapsulated
+as @ref GLFWcursor objects.  They are created with @ref glfwCreateCursor or @ref
+glfwCreateStandardCursor and destroyed with @ref glfwDestroyCursor, or @ref
+glfwTerminate, if any remain.
+
+
+@subsubsection cursor_custom Custom cursor creation
+
+A custom cursor is created with @ref glfwCreateCursor, which returns a handle to
+the created cursor object.  For example, this creates a 16x16 white square
+cursor with the hot-spot in the upper-left corner:
+
+@code
+unsigned char pixels[16 * 16 * 4];
+memset(pixels, 0xff, sizeof(pixels));
+
+GLFWimage image;
+image.width = 16;
+image.height = 16;
+image.pixels = pixels;
+
+GLFWcursor* cursor = glfwCreateCursor(&image, 0, 0);
+@endcode
+
+If cursor creation fails, `NULL` will be returned, so it is necessary to check
+the return value.
+
+The image data is 32-bit, little-endian, non-premultiplied RGBA, i.e. eight bits
+per channel with the red channel first.  The pixels are arranged canonically as
+sequential rows, starting from the top-left corner.
+
+
+@subsubsection cursor_standard Standard cursor creation
+
+A cursor with a [standard shape](@ref shapes) from the current system cursor
+theme can be can be created with @ref glfwCreateStandardCursor.
+
+@code
+GLFWcursor* cursor = glfwCreateStandardCursor(GLFW_HRESIZE_CURSOR);
+@endcode
+
+These cursor objects behave in the exact same way as those created with @ref
+glfwCreateCursor except that the system cursor theme provides the actual image.
+
+
+@subsubsection cursor_destruction Cursor destruction
+
+When a cursor is no longer needed, destroy it with @ref glfwDestroyCursor.
+
+@code
+glfwDestroyCursor(cursor);
+@endcode
+
+Cursor destruction always succeeds.  If the cursor is current for any window,
+that window will revert to the default cursor.  This does not affect the cursor
+mode.  All remaining cursors are destroyed when @ref glfwTerminate is called.
+
+
+@subsubsection cursor_set Cursor setting
+
+A cursor can be set as current for a window with @ref glfwSetCursor.
+
+@code
+glfwSetCursor(window, cursor);
+@endcode
+
+Once set, the cursor image will be used as long as the system cursor is over the
+content area of the window and the [cursor mode](@ref cursor_mode) is set
+to `GLFW_CURSOR_NORMAL`.
+
+A single cursor may be set for any number of windows.
+
+To revert to the default cursor, set the cursor of that window to `NULL`.
+
+@code
+glfwSetCursor(window, NULL);
+@endcode
+
+When a cursor is destroyed, any window that has it set will revert to the
+default cursor.  This does not affect the cursor mode.
+
+
+@subsection cursor_enter Cursor enter/leave events
+
+If you wish to be notified when the cursor enters or leaves the content area of
+a window, set a cursor enter/leave callback.
+
+@code
+glfwSetCursorEnterCallback(window, cursor_enter_callback);
+@endcode
+
+The callback function receives the new classification of the cursor.
+
+@code
+void cursor_enter_callback(GLFWwindow* window, int entered)
+{
+    if (entered)
+    {
+        // The cursor entered the content area of the window
+    }
+    else
+    {
+        // The cursor left the content area of the window
+    }
+}
+@endcode
+
+You can query whether the cursor is currently inside the content area of the
+window with the [GLFW_HOVERED](@ref GLFW_HOVERED_attrib) window attribute.
+
+@code
+if (glfwGetWindowAttrib(window, GLFW_HOVERED))
+{
+    highlight_interface();
+}
+@endcode
+
+
+@subsection input_mouse_button Mouse button input
+
+If you wish to be notified when a mouse button is pressed or released, set
+a mouse button callback.
+
+@code
+glfwSetMouseButtonCallback(window, mouse_button_callback);
+@endcode
+
+The callback function receives the [mouse button](@ref buttons), button action
+and [modifier bits](@ref mods).
+
+@code
+void mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
+{
+    if (button == GLFW_MOUSE_BUTTON_RIGHT && action == GLFW_PRESS)
+        popup_menu();
+}
+@endcode
+
+The action is one of `GLFW_PRESS` or `GLFW_RELEASE`.
+
+Mouse button states for [named buttons](@ref buttons) are also saved in
+per-window state arrays that can be polled with @ref glfwGetMouseButton.
+
+@code
+int state = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT);
+if (state == GLFW_PRESS)
+{
+    upgrade_cow();
+}
+@endcode
+
+The returned state is one of `GLFW_PRESS` or `GLFW_RELEASE`.
+
+This function only returns cached mouse button event state.  It does not poll
+the system for the current state of the mouse button.
+
+@anchor GLFW_STICKY_MOUSE_BUTTONS
+Whenever you poll state, you risk missing the state change you are looking for.
+If a pressed mouse button is released again before you poll its state, you will have
+missed the button press.  The recommended solution for this is to use a
+mouse button callback, but there is also the `GLFW_STICKY_MOUSE_BUTTONS`
+input mode.
+
+@code
+glfwSetInputMode(window, GLFW_STICKY_MOUSE_BUTTONS, GLFW_TRUE);
+@endcode
+
+When sticky mouse buttons mode is enabled, the pollable state of a mouse button
+will remain `GLFW_PRESS` until the state of that button is polled with @ref
+glfwGetMouseButton.  Once it has been polled, if a mouse button release event
+had been processed in the meantime, the state will reset to `GLFW_RELEASE`,
+otherwise it will remain `GLFW_PRESS`.
+
+The `GLFW_MOUSE_BUTTON_LAST` constant holds the highest value of any
+[named button](@ref buttons).
+
+
+@subsection scrolling Scroll input
+
+If you wish to be notified when the user scrolls, whether with a mouse wheel or
+touchpad gesture, set a scroll callback.
+
+@code
+glfwSetScrollCallback(window, scroll_callback);
+@endcode
+
+The callback function receives two-dimensional scroll offsets.
+
+@code
+void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
+{
+}
+@endcode
+
+A normal mouse wheel, being vertical, provides offsets along the Y-axis.
+
+
+@section joystick Joystick input
+
+The joystick functions expose connected joysticks and controllers, with both
+referred to as joysticks.  It supports up to sixteen joysticks, ranging from
+`GLFW_JOYSTICK_1`, `GLFW_JOYSTICK_2` up to and including `GLFW_JOYSTICK_16` or
+`GLFW_JOYSTICK_LAST`.  You can test whether a [joystick](@ref joysticks) is
+present with @ref glfwJoystickPresent.
+
+@code
+int present = glfwJoystickPresent(GLFW_JOYSTICK_1);
+@endcode
+
+Each joystick has zero or more axes, zero or more buttons, zero or more hats,
+a human-readable name, a user pointer and an SDL compatible GUID.
+
+When GLFW is initialized, detected joysticks are added to the beginning of
+the array.  Once a joystick is detected, it keeps its assigned ID until it is
+disconnected or the library is terminated, so as joysticks are connected and
+disconnected, there may appear gaps in the IDs.
+
+Joystick axis, button and hat state is updated when polled and does not require
+a window to be created or events to be processed.  However, if you want joystick
+connection and disconnection events reliably delivered to the
+[joystick callback](@ref joystick_event) then you must
+[process events](@ref events).
+
+To see all the properties of all connected joysticks in real-time, run the
+`joysticks` test program.
+
+
+@subsection joystick_axis Joystick axis states
+
+The positions of all axes of a joystick are returned by @ref
+glfwGetJoystickAxes.  See the reference documentation for the lifetime of the
+returned array.
+
+@code
+int count;
+const float* axes = glfwGetJoystickAxes(GLFW_JOYSTICK_5, &count);
+@endcode
+
+Each element in the returned array is a value between -1.0 and 1.0.
+
+
+@subsection joystick_button Joystick button states
+
+The states of all buttons of a joystick are returned by @ref
+glfwGetJoystickButtons.  See the reference documentation for the lifetime of the
+returned array.
+
+@code
+int count;
+const unsigned char* buttons = glfwGetJoystickButtons(GLFW_JOYSTICK_3, &count);
+@endcode
+
+Each element in the returned array is either `GLFW_PRESS` or `GLFW_RELEASE`.
+
+For backward compatibility with earlier versions that did not have @ref
+glfwGetJoystickHats, the button array by default also includes all hats.  See
+the reference documentation for @ref glfwGetJoystickButtons for details.
+
+
+@subsection joystick_hat Joystick hat states
+
+The states of all hats are returned by @ref glfwGetJoystickHats.  See the
+reference documentation for the lifetime of the returned array.
+
+@code
+int count;
+const unsigned char* hats = glfwGetJoystickHats(GLFW_JOYSTICK_7, &count);
+@endcode
+
+Each element in the returned array is one of the following:
+
+Name                  | Value
+----                  | -----
+`GLFW_HAT_CENTERED`   | 0
+`GLFW_HAT_UP`         | 1
+`GLFW_HAT_RIGHT`      | 2
+`GLFW_HAT_DOWN`       | 4
+`GLFW_HAT_LEFT`       | 8
+`GLFW_HAT_RIGHT_UP`   | `GLFW_HAT_RIGHT` \| `GLFW_HAT_UP`
+`GLFW_HAT_RIGHT_DOWN` | `GLFW_HAT_RIGHT` \| `GLFW_HAT_DOWN`
+`GLFW_HAT_LEFT_UP`    | `GLFW_HAT_LEFT` \| `GLFW_HAT_UP`
+`GLFW_HAT_LEFT_DOWN`  | `GLFW_HAT_LEFT` \| `GLFW_HAT_DOWN`
+
+The diagonal directions are bitwise combinations of the primary (up, right, down
+and left) directions and you can test for these individually by ANDing it with
+the corresponding direction.
+
+@code
+if (hats[2] & GLFW_HAT_RIGHT)
+{
+    // State of hat 2 could be right-up, right or right-down
+}
+@endcode
+
+For backward compatibility with earlier versions that did not have @ref
+glfwGetJoystickHats, all hats are by default also included in the button array.
+See the reference documentation for @ref glfwGetJoystickButtons for details.
+
+
+@subsection joystick_name Joystick name
+
+The human-readable, UTF-8 encoded name of a joystick is returned by @ref
+glfwGetJoystickName.  See the reference documentation for the lifetime of the
+returned string.
+
+@code
+const char* name = glfwGetJoystickName(GLFW_JOYSTICK_4);
+@endcode
+
+Joystick names are not guaranteed to be unique.  Two joysticks of the same model
+and make may have the same name.  Only the [joystick ID](@ref joysticks) is
+guaranteed to be unique, and only until that joystick is disconnected.
+
+
+@subsection joystick_userptr Joystick user pointer
+
+Each joystick has a user pointer that can be set with @ref
+glfwSetJoystickUserPointer and queried with @ref glfwGetJoystickUserPointer.
+This can be used for any purpose you need and will not be modified by GLFW.  The
+value will be kept until the joystick is disconnected or until the library is
+terminated.
+
+The initial value of the pointer is `NULL`.
+
+
+@subsection joystick_event Joystick configuration changes
+
+If you wish to be notified when a joystick is connected or disconnected, set
+a joystick callback.
+
+@code
+glfwSetJoystickCallback(joystick_callback);
+@endcode
+
+The callback function receives the ID of the joystick that has been connected
+and disconnected and the event that occurred.
+
+@code
+void joystick_callback(int jid, int event)
+{
+    if (event == GLFW_CONNECTED)
+    {
+        // The joystick was connected
+    }
+    else if (event == GLFW_DISCONNECTED)
+    {
+        // The joystick was disconnected
+    }
+}
+@endcode
+
+For joystick connection and disconnection events to be delivered on all
+platforms, you need to call one of the [event processing](@ref events)
+functions.  Joystick disconnection may also be detected and the callback
+called by joystick functions.  The function will then return whatever it
+returns for a disconnected joystick.
+
+Only @ref glfwGetJoystickName and @ref glfwGetJoystickUserPointer will return
+useful values for a disconnected joystick and only before the monitor callback
+returns.
+
+
+@subsection gamepad Gamepad input
+
+The joystick functions provide unlabeled axes, buttons and hats, with no
+indication of where they are located on the device.  Their order may also vary
+between platforms even with the same device.
+
+To solve this problem the SDL community crowdsourced the
+[SDL_GameControllerDB](https://github.com/gabomdq/SDL_GameControllerDB) project,
+a database of mappings from many different devices to an Xbox-like gamepad.
+
+GLFW supports this mapping format and contains a copy of the mappings
+available at the time of release.  See @ref gamepad_mapping for how to update
+this at runtime.  Mappings will be assigned to joysticks automatically any time
+a joystick is connected or the mappings are updated.
+
+You can check whether a joystick is both present and has a gamepad mapping with
+@ref glfwJoystickIsGamepad.
+
+@code
+if (glfwJoystickIsGamepad(GLFW_JOYSTICK_2))
+{
+    // Use as gamepad
+}
+@endcode
+
+If you are only interested in gamepad input you can use this function instead of
+@ref glfwJoystickPresent.
+
+You can query the human-readable name provided by the gamepad mapping with @ref
+glfwGetGamepadName.  This may or may not be the same as the
+[joystick name](@ref joystick_name).
+
+@code
+const char* name = glfwGetGamepadName(GLFW_JOYSTICK_7);
+@endcode
+
+To retrieve the gamepad state of a joystick, call @ref glfwGetGamepadState.
+
+@code
+GLFWgamepadstate state;
+
+if (glfwGetGamepadState(GLFW_JOYSTICK_3, &state))
+{
+    if (state.buttons[GLFW_GAMEPAD_BUTTON_A])
+    {
+        input_jump();
+    }
+
+    input_speed(state.axes[GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER]);
+}
+@endcode
+
+The @ref GLFWgamepadstate struct has two arrays; one for button states and one
+for axis states.  The values for each button and axis are the same as for the
+@ref glfwGetJoystickButtons and @ref glfwGetJoystickAxes functions, i.e.
+`GLFW_PRESS` or `GLFW_RELEASE` for buttons and -1.0 to 1.0 inclusive for axes.
+
+The sizes of the arrays and the positions within each array are fixed.
+
+The [button indices](@ref gamepad_buttons) are `GLFW_GAMEPAD_BUTTON_A`,
+`GLFW_GAMEPAD_BUTTON_B`, `GLFW_GAMEPAD_BUTTON_X`, `GLFW_GAMEPAD_BUTTON_Y`,
+`GLFW_GAMEPAD_BUTTON_LEFT_BUMPER`, `GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER`,
+`GLFW_GAMEPAD_BUTTON_BACK`, `GLFW_GAMEPAD_BUTTON_START`,
+`GLFW_GAMEPAD_BUTTON_GUIDE`, `GLFW_GAMEPAD_BUTTON_LEFT_THUMB`,
+`GLFW_GAMEPAD_BUTTON_RIGHT_THUMB`, `GLFW_GAMEPAD_BUTTON_DPAD_UP`,
+`GLFW_GAMEPAD_BUTTON_DPAD_RIGHT`, `GLFW_GAMEPAD_BUTTON_DPAD_DOWN` and
+`GLFW_GAMEPAD_BUTTON_DPAD_LEFT`.
+
+For those who prefer, there are also the `GLFW_GAMEPAD_BUTTON_CROSS`,
+`GLFW_GAMEPAD_BUTTON_CIRCLE`, `GLFW_GAMEPAD_BUTTON_SQUARE` and
+`GLFW_GAMEPAD_BUTTON_TRIANGLE` aliases for the A, B, X and Y button indices.
+
+The [axis indices](@ref gamepad_axes) are `GLFW_GAMEPAD_AXIS_LEFT_X`,
+`GLFW_GAMEPAD_AXIS_LEFT_Y`, `GLFW_GAMEPAD_AXIS_RIGHT_X`,
+`GLFW_GAMEPAD_AXIS_RIGHT_Y`, `GLFW_GAMEPAD_AXIS_LEFT_TRIGGER` and
+`GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER`.
+
+The `GLFW_GAMEPAD_BUTTON_LAST` and `GLFW_GAMEPAD_AXIS_LAST` constants equal
+the largest available index for each array.
+
+
+@subsection gamepad_mapping Gamepad mappings
+
+GLFW contains a copy of the mappings available in
+[SDL_GameControllerDB](https://github.com/gabomdq/SDL_GameControllerDB) at the
+time of release.  Newer ones can be added at runtime with @ref
+glfwUpdateGamepadMappings.
+
+@code
+const char* mappings = load_file_contents("game/data/gamecontrollerdb.txt");
+
+glfwUpdateGamepadMappings(mappings);
+@endcode
+
+This function supports everything from single lines up to and including the
+unmodified contents of the whole `gamecontrollerdb.txt` file.
+
+If you are compiling GLFW from source with CMake you can update the built-in mappings by
+building the _update_mappings_ target.  This runs the `GenerateMappings.cmake` CMake
+script, which downloads `gamecontrollerdb.txt` and regenerates the `mappings.h` header
+file.
+
+Below is a description of the mapping format.  Please keep in mind that __this
+description is not authoritative__.  The format is defined by the SDL and
+SDL_GameControllerDB projects and their documentation and code takes precedence.
+
+Each mapping is a single line of comma-separated values describing the GUID,
+name and layout of the gamepad.  Lines that do not begin with a hexadecimal
+digit are ignored.
+
+The first value is always the gamepad GUID, a 32 character long hexadecimal
+string that typically identifies its make, model, revision and the type of
+connection to the computer.  When this information is not available, the GUID is
+generated using the gamepad name.  GLFW uses the SDL 2.0.5+ GUID format but can
+convert from the older formats.
+
+The second value is always the human-readable name of the gamepad.
+
+All subsequent values are in the form `<field>:<value>` and describe the layout
+of the mapping.  These fields may not all be present and may occur in any order.
+
+The button fields are `a`, `b`, `c`, `d`, `back`, `start`, `guide`, `dpup`,
+`dpright`, `dpdown`, `dpleft`, `leftshoulder`, `rightshoulder`, `leftstick` and
+`rightstick`.
+
+The axis fields are `leftx`, `lefty`, `rightx`, `righty`, `lefttrigger` and
+`righttrigger`.
+
+The value of an axis or button field can be a joystick button, a joystick axis,
+a hat bitmask or empty.  Joystick buttons are specified as `bN`, for example
+`b2` for the third button.  Joystick axes are specified as `aN`, for example
+`a7` for the eighth button.  Joystick hat bit masks are specified as `hN.N`, for
+example `h0.8` for left on the first hat.  More than one bit may be set in the
+mask.
+
+Before an axis there may be a `+` or `-` range modifier, for example `+a3` for
+the positive half of the fourth axis.  This restricts input to only the positive
+or negative halves of the joystick axis.  After an axis or half-axis there may
+be the `~` inversion modifier, for example `a2~` or `-a7~`.  This negates the
+values of the gamepad axis.
+
+The hat bit mask match the [hat states](@ref hat_state) in the joystick
+functions.
+
+There is also the special `platform` field that specifies which platform the
+mapping is valid for.  Possible values are `Windows`, `Mac OS X` and `Linux`.
+
+Below is an example of what a gamepad mapping might look like.  It is the
+one built into GLFW for Xbox controllers accessed via the XInput API on Windows.
+This example has been broken into several lines to fit on the page, but real
+gamepad mappings must be a single line.
+
+@code{.unparsed}
+78696e70757401000000000000000000,XInput Gamepad (GLFW),platform:Windows,a:b0,
+b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,
+rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,
+righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,
+@endcode
+
+@note GLFW does not yet support the output range and modifiers `+` and `-` that
+were recently added to SDL.  The input modifiers `+`, `-` and `~` are supported
+and described above.
+
+
+@section time Time input
+
+GLFW provides high-resolution time input, in seconds, with @ref glfwGetTime.
+
+@code
+double seconds = glfwGetTime();
+@endcode
+
+It returns the number of seconds since the library was initialized with @ref
+glfwInit.  The platform-specific time sources used typically have micro- or
+nanosecond resolution.
+
+You can modify the base time with @ref glfwSetTime.
+
+@code
+glfwSetTime(4.0);
+@endcode
+
+This sets the time to the specified time, in seconds, and it continues to count
+from there.
+
+You can also access the raw timer used to implement the functions above,
+with @ref glfwGetTimerValue.
+
+@code
+uint64_t value = glfwGetTimerValue();
+@endcode
+
+This value is in 1&nbsp;/&nbsp;frequency seconds.  The frequency of the raw
+timer varies depending on the operating system and hardware.  You can query the
+frequency, in Hz, with @ref glfwGetTimerFrequency.
+
+@code
+uint64_t frequency = glfwGetTimerFrequency();
+@endcode
+
+
+@section clipboard Clipboard input and output
+
+If the system clipboard contains a UTF-8 encoded string or if it can be
+converted to one, you can retrieve it with @ref glfwGetClipboardString.  See the
+reference documentation for the lifetime of the returned string.
+
+@code
+const char* text = glfwGetClipboardString(NULL);
+if (text)
+{
+    insert_text(text);
+}
+@endcode
+
+If the clipboard is empty or if its contents could not be converted, `NULL` is
+returned.
+
+The contents of the system clipboard can be set to a UTF-8 encoded string with
+@ref glfwSetClipboardString.
+
+@code
+glfwSetClipboardString(NULL, "A string with words in it");
+@endcode
+
+
+@section path_drop Path drop input
+
+If you wish to receive the paths of files and/or directories dropped on
+a window, set a file drop callback.
+
+@code
+glfwSetDropCallback(window, drop_callback);
+@endcode
+
+The callback function receives an array of paths encoded as UTF-8.
+
+@code
+void drop_callback(GLFWwindow* window, int count, const char** paths)
+{
+    int i;
+    for (i = 0;  i < count;  i++)
+        handle_dropped_file(paths[i]);
+}
+@endcode
+
+The path array and its strings are only valid until the file drop callback
+returns, as they may have been generated specifically for that event.  You need
+to make a deep copy of the array if you want to keep the paths.
+
+*/

+ 115 - 0
samples/third_party/glfw/docs/internal.dox

@@ -0,0 +1,115 @@
+/*!
+
+@page internals_guide Internal structure
+
+@tableofcontents
+
+There are several interfaces inside GLFW.  Each interface has its own area of
+responsibility and its own naming conventions.
+
+
+@section internals_public Public interface
+
+The most well-known is the public interface, described in the glfw3.h header
+file.  This is implemented in source files shared by all platforms and these
+files contain no platform-specific code.  This code usually ends up calling the
+platform and internal interfaces to do the actual work.
+
+The public interface uses the OpenGL naming conventions except with GLFW and
+glfw instead of GL and gl.  For struct members, where OpenGL sets no precedent,
+it use headless camel case.
+
+Examples: `glfwCreateWindow`, `GLFWwindow`, `GLFW_RED_BITS`
+
+
+@section internals_native Native interface
+
+The [native interface](@ref native) is a small set of publicly available
+but platform-specific functions, described in the glfw3native.h header file and
+used to gain access to the underlying window, context and (on some platforms)
+display handles used by the platform interface.
+
+The function names of the native interface are similar to those of the public
+interface, but embeds the name of the interface that the returned handle is
+from.
+
+Examples: `glfwGetX11Window`, `glfwGetWGLContext`
+
+
+@section internals_internal Internal interface
+
+The internal interface consists of utility functions used by all other
+interfaces.  It is shared code implemented in the same shared source files as
+the public and event interfaces.  The internal interface is described in the
+internal.h header file.
+
+The internal interface is in charge of GLFW's global data, which it stores in
+a `_GLFWlibrary` struct named `_glfw`.
+
+The internal interface uses the same style as the public interface, except all
+global names have a leading underscore.
+
+Examples: `_glfwIsValidContextConfig`, `_GLFWwindow`, `_glfw.monitorCount`
+
+
+@section internals_platform Platform interface
+
+The platform interface implements all platform-specific operations as a service
+to the public interface.  This includes event processing.  The platform
+interface is never directly called by application code and never directly calls
+application-provided callbacks.  It is also prohibited from modifying the
+platform-independent part of the internal structs.  Instead, it calls the event
+interface when events interesting to GLFW are received.
+
+The platform interface mirrors those parts of the public interface that needs to
+perform platform-specific operations on some or all platforms.  The are also
+named the same except that the glfw function prefix is replaced by
+_glfwPlatform.
+
+Examples: `_glfwPlatformCreateWindow`
+
+The platform interface also defines structs that contain platform-specific
+global and per-object state.  Their names mirror those of the internal
+interface, except that an interface-specific suffix is added.
+
+Examples: `_GLFWwindowX11`, `_GLFWcontextWGL`
+
+These structs are incorporated as members into the internal interface structs
+using special macros that name them after the specific interface used.  This
+prevents shared code from accidentally using these members.
+
+Examples: `window->win32.handle`, `_glfw.x11.display`
+
+
+@section internals_event Event interface
+
+The event interface is implemented in the same shared source files as the public
+interface and is responsible for delivering the events it receives to the
+application, either via callbacks, via window state changes or both.
+
+The function names of the event interface use a `_glfwInput` prefix and the
+ObjectEvent pattern.
+
+Examples: `_glfwInputWindowFocus`, `_glfwInputCursorPos`
+
+
+@section internals_static Static functions
+
+Static functions may be used by any interface and have no prefixes or suffixes.
+These use headless camel case.
+
+Examples: `isValidElementForJoystick`
+
+
+@section internals_config Configuration macros
+
+GLFW uses a number of configuration macros to select at compile time which
+interfaces and code paths to use.  They are defined in the glfw_config.h header file,
+which is generated from the `glfw_config.h.in` file by CMake.
+
+Configuration macros the same style as tokens in the public interface, except
+with a leading underscore.
+
+Examples: `_GLFW_WIN32`, `_GLFW_BUILD_DLL`
+
+*/

+ 454 - 0
samples/third_party/glfw/docs/intro.dox

@@ -0,0 +1,454 @@
+/*!
+
+@page intro_guide Introduction to the API
+
+@tableofcontents
+
+This guide introduces the basic concepts of GLFW and describes initialization,
+error handling and API guarantees and limitations.  For a broad but shallow
+tutorial, see @ref quick_guide instead.  For details on a specific function in
+this category, see the @ref init.
+
+There are also guides for the other areas of GLFW.
+
+ - @ref window_guide
+ - @ref context_guide
+ - @ref vulkan_guide
+ - @ref monitor_guide
+ - @ref input_guide
+
+
+@section intro_init Initialization and termination
+
+Before most GLFW functions may be called, the library must be initialized.
+This initialization checks what features are available on the machine,
+enumerates monitors and joysticks, initializes the timer and performs any
+required platform-specific initialization.
+
+Only the following functions may be called before the library has been
+successfully initialized, and only from the main thread.
+
+ - @ref glfwGetVersion
+ - @ref glfwGetVersionString
+ - @ref glfwGetError
+ - @ref glfwSetErrorCallback
+ - @ref glfwInitHint
+ - @ref glfwInit
+ - @ref glfwTerminate
+
+Calling any other function before successful initialization will cause a @ref
+GLFW_NOT_INITIALIZED error.
+
+
+@subsection intro_init_init Initializing GLFW
+
+The library is initialized with @ref glfwInit, which returns `GLFW_FALSE` if an
+error occurred.
+
+@code
+if (!glfwInit())
+{
+    // Handle initialization failure
+}
+@endcode
+
+If any part of initialization fails, any parts that succeeded are terminated as
+if @ref glfwTerminate had been called.  The library only needs to be initialized
+once and additional calls to an already initialized library will return
+`GLFW_TRUE` immediately.
+
+Once the library has been successfully initialized, it should be terminated
+before the application exits.  Modern systems are very good at freeing resources
+allocated by programs that exit, but GLFW sometimes has to change global system
+settings and these might not be restored without termination.
+
+
+@subsection init_hints Initialization hints
+
+Initialization hints are set before @ref glfwInit and affect how the library
+behaves until termination.  Hints are set with @ref glfwInitHint.
+
+@code
+glfwInitHint(GLFW_JOYSTICK_HAT_BUTTONS, GLFW_FALSE);
+@endcode
+
+The values you set hints to are never reset by GLFW, but they only take effect
+during initialization.  Once GLFW has been initialized, any values you set will
+be ignored until the library is terminated and initialized again.
+
+Some hints are platform specific.  These may be set on any platform but they
+will only affect their specific platform.  Other platforms will ignore them.
+Setting these hints requires no platform specific headers or functions.
+
+
+@subsubsection init_hints_shared Shared init hints
+
+@anchor GLFW_JOYSTICK_HAT_BUTTONS
+__GLFW_JOYSTICK_HAT_BUTTONS__ specifies whether to also expose joystick hats as
+buttons, for compatibility with earlier versions of GLFW that did not have @ref
+glfwGetJoystickHats.  Possible values are `GLFW_TRUE` and `GLFW_FALSE`.
+
+
+@subsubsection init_hints_osx macOS specific init hints
+
+@anchor GLFW_COCOA_CHDIR_RESOURCES_hint
+__GLFW_COCOA_CHDIR_RESOURCES__ specifies whether to set the current directory to
+the application to the `Contents/Resources` subdirectory of the application's
+bundle, if present.  Set this with @ref glfwInitHint.
+
+@anchor GLFW_COCOA_MENUBAR_hint
+__GLFW_COCOA_MENUBAR__ specifies whether to create a basic menu bar, either from
+a nib or manually, when the first window is created, which is when AppKit is
+initialized.  Set this with @ref glfwInitHint.
+
+
+@subsubsection init_hints_values Supported and default values
+
+Initialization hint             | Default value | Supported values
+------------------------------- | ------------- | ----------------
+@ref GLFW_JOYSTICK_HAT_BUTTONS  | `GLFW_TRUE`   | `GLFW_TRUE` or `GLFW_FALSE`
+@ref GLFW_COCOA_CHDIR_RESOURCES | `GLFW_TRUE`   | `GLFW_TRUE` or `GLFW_FALSE`
+@ref GLFW_COCOA_MENUBAR         | `GLFW_TRUE`   | `GLFW_TRUE` or `GLFW_FALSE`
+
+
+@subsection intro_init_terminate Terminating GLFW
+
+Before your application exits, you should terminate the GLFW library if it has
+been initialized.  This is done with @ref glfwTerminate.
+
+@code
+glfwTerminate();
+@endcode
+
+This will destroy any remaining window, monitor and cursor objects, restore any
+modified gamma ramps, re-enable the screensaver if it had been disabled and free
+any other resources allocated by GLFW.
+
+Once the library is terminated, it is as if it had never been initialized and
+you will need to initialize it again before being able to use GLFW.  If the
+library was not initialized or had already been terminated, it return
+immediately.
+
+
+@section error_handling Error handling
+
+Some GLFW functions have return values that indicate an error, but this is often
+not very helpful when trying to figure out what happened or why it occurred.
+Other functions have no return value reserved for errors, so error notification
+needs a separate channel.  Finally, far from all GLFW functions have return
+values.
+
+The last [error code](@ref errors) for the calling thread can be queried at any
+time with @ref glfwGetError.
+
+@code
+int code = glfwGetError(NULL);
+
+if (code != GLFW_NO_ERROR)
+    handle_error(code);
+@endcode
+
+If no error has occurred since the last call, @ref GLFW_NO_ERROR (zero) is
+returned.  The error is cleared before the function returns.
+
+The error code indicates the general category of the error.  Some error codes,
+such as @ref GLFW_NOT_INITIALIZED has only a single meaning, whereas others like
+@ref GLFW_PLATFORM_ERROR are used for many different errors.
+
+GLFW often has more information about an error than its general category.  You
+can retrieve a UTF-8 encoded human-readable description along with the error
+code.  If no error has occurred since the last call, the description is set to
+`NULL`.
+
+@code
+const char* description;
+int code = glfwGetError(&description);
+
+if (description)
+    display_error_message(code, description);
+@endcode
+
+The retrieved description string is only valid until the next error occurs.
+This means you must make a copy of it if you want to keep it.
+
+You can also set an error callback, which will be called each time an error
+occurs.  It is set with @ref glfwSetErrorCallback.
+
+@code
+glfwSetErrorCallback(error_callback);
+@endcode
+
+The error callback receives the same error code and human-readable description
+returned by @ref glfwGetError.
+
+@code
+void error_callback(int code, const char* description)
+{
+    display_error_message(code, description);
+}
+@endcode
+
+The error callback is called after the error is stored, so calling @ref
+glfwGetError from within the error callback returns the same values as the
+callback argument.
+
+The description string passed to the callback is only valid until the error
+callback returns.  This means you must make a copy of it if you want to keep it.
+
+__Reported errors are never fatal.__  As long as GLFW was successfully
+initialized, it will remain initialized and in a safe state until terminated
+regardless of how many errors occur.  If an error occurs during initialization
+that causes @ref glfwInit to fail, any part of the library that was initialized
+will be safely terminated.
+
+Do not rely on a currently invalid call to generate a specific error, as in the
+future that same call may generate a different error or become valid.
+
+
+@section coordinate_systems Coordinate systems
+
+GLFW has two primary coordinate systems: the _virtual screen_ and the window
+_content area_ or _content area_.  Both use the same unit: _virtual screen
+coordinates_, or just _screen coordinates_, which don't necessarily correspond
+to pixels.
+
+<img src="spaces.svg" width="90%" />
+
+Both the virtual screen and the content area coordinate systems have the X-axis
+pointing to the right and the Y-axis pointing down.
+
+Window and monitor positions are specified as the position of the upper-left
+corners of their content areas relative to the virtual screen, while cursor
+positions are specified relative to a window's content area.
+
+Because the origin of the window's content area coordinate system is also the
+point from which the window position is specified, you can translate content
+area coordinates to the virtual screen by adding the window position.  The
+window frame, when present, extends out from the content area but does not
+affect the window position.
+
+Almost all positions and sizes in GLFW are measured in screen coordinates
+relative to one of the two origins above.  This includes cursor positions,
+window positions and sizes, window frame sizes, monitor positions and video mode
+resolutions.
+
+Two exceptions are the [monitor physical size](@ref monitor_size), which is
+measured in millimetres, and [framebuffer size](@ref window_fbsize), which is
+measured in pixels.
+
+Pixels and screen coordinates may map 1:1 on your machine, but they won't on
+every other machine, for example on a Mac with a Retina display.  The ratio
+between screen coordinates and pixels may also change at run-time depending on
+which monitor the window is currently considered to be on.
+
+
+@section guarantees_limitations Guarantees and limitations
+
+This section describes the conditions under which GLFW can be expected to
+function, barring bugs in the operating system or drivers.  Use of GLFW outside
+of these limits may work on some platforms, or on some machines, or some of the
+time, or on some versions of GLFW, but it may break at any time and this will
+not be considered a bug.
+
+
+@subsection lifetime Pointer lifetimes
+
+GLFW will never free any pointer you provide to it and you must never free any
+pointer it provides to you.
+
+Many GLFW functions return pointers to dynamically allocated structures, strings
+or arrays, and some callbacks are provided with strings or arrays.  These are
+always managed by GLFW and should never be freed by the application.  The
+lifetime of these pointers is documented for each GLFW function and callback.
+If you need to keep this data, you must copy it before its lifetime expires.
+
+Many GLFW functions accept pointers to structures or strings allocated by the
+application.  These are never freed by GLFW and are always the responsibility of
+the application.  If GLFW needs to keep the data in these structures or strings,
+it is copied before the function returns.
+
+Pointer lifetimes are guaranteed not to be shortened in future minor or patch
+releases.
+
+
+@subsection reentrancy Reentrancy
+
+GLFW event processing and object destruction are not reentrant.  This means that
+the following functions must not be called from any callback function:
+
+ - @ref glfwDestroyWindow
+ - @ref glfwDestroyCursor
+ - @ref glfwPollEvents
+ - @ref glfwWaitEvents
+ - @ref glfwWaitEventsTimeout
+ - @ref glfwTerminate
+
+These functions may be made reentrant in future minor or patch releases, but
+functions not on this list will not be made non-reentrant.
+
+
+@subsection thread_safety Thread safety
+
+Most GLFW functions must only be called from the main thread (the thread that
+calls main), but some may be called from any thread once the library has been
+initialized.  Before initialization the whole library is thread-unsafe.
+
+The reference documentation for every GLFW function states whether it is limited
+to the main thread.
+
+Initialization, termination, event processing and the creation and
+destruction of windows, cursors and OpenGL and OpenGL ES contexts are all
+restricted to the main thread due to limitations of one or several platforms.
+
+Because event processing must be performed on the main thread, all callbacks
+except for the error callback will only be called on that thread.  The error
+callback may be called on any thread, as any GLFW function may generate errors.
+
+The error code and description may be queried from any thread.
+
+ - @ref glfwGetError
+
+Empty events may be posted from any thread.
+
+ - @ref glfwPostEmptyEvent
+
+The window user pointer and close flag may be read and written from any thread,
+but this is not synchronized by GLFW.
+
+ - @ref glfwGetWindowUserPointer
+ - @ref glfwSetWindowUserPointer
+ - @ref glfwWindowShouldClose
+ - @ref glfwSetWindowShouldClose
+
+These functions for working with OpenGL and OpenGL ES contexts may be called
+from any thread, but the window object is not synchronized by GLFW.
+
+ - @ref glfwMakeContextCurrent
+ - @ref glfwGetCurrentContext
+ - @ref glfwSwapBuffers
+ - @ref glfwSwapInterval
+ - @ref glfwExtensionSupported
+ - @ref glfwGetProcAddress
+
+The raw timer functions may be called from any thread.
+
+ - @ref glfwGetTimerFrequency
+ - @ref glfwGetTimerValue
+
+The regular timer may be used from any thread, but reading and writing the timer
+offset is not synchronized by GLFW.
+
+ - @ref glfwGetTime
+ - @ref glfwSetTime
+
+Library version information may be queried from any thread.
+
+ - @ref glfwGetVersion
+ - @ref glfwGetVersionString
+
+All Vulkan related functions may be called from any thread.
+
+ - @ref glfwVulkanSupported
+ - @ref glfwGetRequiredInstanceExtensions
+ - @ref glfwGetInstanceProcAddress
+ - @ref glfwGetPhysicalDevicePresentationSupport
+ - @ref glfwCreateWindowSurface
+
+GLFW uses synchronization objects internally only to manage the per-thread
+context and error states.  Additional synchronization is left to the
+application.
+
+Functions that may currently be called from any thread will always remain so,
+but functions that are currently limited to the main thread may be updated to
+allow calls from any thread in future releases.
+
+
+@subsection compatibility Version compatibility
+
+GLFW uses [Semantic Versioning](https://semver.org/).  This guarantees source
+and binary backward compatibility with earlier minor versions of the API.  This
+means that you can drop in a newer version of the library and existing programs
+will continue to compile and existing binaries will continue to run.
+
+Once a function or constant has been added, the signature of that function or
+value of that constant will remain unchanged until the next major version of
+GLFW.  No compatibility of any kind is guaranteed between major versions.
+
+Undocumented behavior, i.e. behavior that is not described in the documentation,
+may change at any time until it is documented.
+
+If the reference documentation and the implementation differ, the reference
+documentation will almost always take precedence and the implementation will be
+fixed in the next release.  The reference documentation will also take
+precedence over anything stated in a guide.
+
+
+@subsection event_order Event order
+
+The order of arrival of related events is not guaranteed to be consistent
+across platforms.  The exception is synthetic key and mouse button release
+events, which are always delivered after the window defocus event.
+
+
+@section intro_version Version management
+
+GLFW provides mechanisms for identifying what version of GLFW your application
+was compiled against as well as what version it is currently running against.
+If you are loading GLFW dynamically (not just linking dynamically), you can use
+this to verify that the library binary is compatible with your application.
+
+
+@subsection intro_version_compile Compile-time version
+
+The compile-time version of GLFW is provided by the GLFW header with the
+`GLFW_VERSION_MAJOR`, `GLFW_VERSION_MINOR` and `GLFW_VERSION_REVISION` macros.
+
+@code
+printf("Compiled against GLFW %i.%i.%i\n",
+       GLFW_VERSION_MAJOR,
+       GLFW_VERSION_MINOR,
+       GLFW_VERSION_REVISION);
+@endcode
+
+
+@subsection intro_version_runtime Run-time version
+
+The run-time version can be retrieved with @ref glfwGetVersion, a function that
+may be called regardless of whether GLFW is initialized.
+
+@code
+int major, minor, revision;
+glfwGetVersion(&major, &minor, &revision);
+
+printf("Running against GLFW %i.%i.%i\n", major, minor, revision);
+@endcode
+
+
+@subsection intro_version_string Version string
+
+GLFW 3 also provides a compile-time generated version string that describes the
+version, platform, compiler and any platform-specific compile-time options.
+This is primarily intended for submitting bug reports, to allow developers to
+see which code paths are enabled in a binary.
+
+The version string is returned by @ref glfwGetVersionString, a function that may
+be called regardless of whether GLFW is initialized.
+
+__Do not use the version string__ to parse the GLFW library version.  The @ref
+glfwGetVersion function already provides the version of the running library
+binary.
+
+The format of the string is as follows:
+ - The version of GLFW
+ - The name of the window system API
+ - The name of the context creation API
+ - Any additional options or APIs
+
+For example, when compiling GLFW 3.0 with MinGW using the Win32 and WGL
+back ends, the version string may look something like this:
+
+@code
+3.0.0 Win32 WGL MinGW
+@endcode
+
+*/

+ 46 - 0
samples/third_party/glfw/docs/main.dox

@@ -0,0 +1,46 @@
+/*!
+
+@mainpage notitle
+
+@section main_intro Introduction
+
+GLFW is a free, Open Source, multi-platform library for OpenGL, OpenGL ES and
+Vulkan application development.  It provides a simple, platform-independent API
+for creating windows, contexts and surfaces, reading input, handling events, etc.
+
+@ref news_33 list new features, caveats and deprecations.
+
+@ref quick_guide is a guide for users new to GLFW.  It takes you through how to
+write a small but complete program.
+
+There are guides for each section of the API:
+
+ - @ref intro_guide – initialization, error handling and high-level design
+ - @ref window_guide – creating and working with windows and framebuffers
+ - @ref context_guide – working with OpenGL and OpenGL ES contexts
+ - @ref vulkan_guide - working with Vulkan objects and extensions
+ - @ref monitor_guide – enumerating and working with monitors and video modes
+ - @ref input_guide – receiving events, polling and processing input
+
+Once you have written a program, see @ref compile_guide and @ref build_guide.
+
+The [reference documentation](modules.html) provides more detailed information
+about specific functions.
+
+@ref moving_guide explains what has changed and how to update existing code to
+use the new API.
+
+There is a section on @ref guarantees_limitations for pointer lifetimes,
+reentrancy, thread safety, event order and backward and forward compatibility.
+
+The [FAQ](https://www.glfw.org/faq.html) answers many common questions about the
+design, implementation and use of GLFW.
+
+Finally, @ref compat_guide explains what APIs, standards and protocols GLFW uses
+and what happens when they are not present on a given machine.
+
+This documentation was generated with Doxygen.  The sources for it are available
+in both the [source distribution](https://www.glfw.org/download.html) and
+[GitHub repository](https://github.com/glfw/glfw).
+
+*/

+ 268 - 0
samples/third_party/glfw/docs/monitor.dox

@@ -0,0 +1,268 @@
+/*!
+
+@page monitor_guide Monitor guide
+
+@tableofcontents
+
+This guide introduces the monitor related functions of GLFW.  For details on
+a specific function in this category, see the @ref monitor.  There are also
+guides for the other areas of GLFW.
+
+ - @ref intro_guide
+ - @ref window_guide
+ - @ref context_guide
+ - @ref vulkan_guide
+ - @ref input_guide
+
+
+@section monitor_object Monitor objects
+
+A monitor object represents a currently connected monitor and is represented as
+a pointer to the [opaque](https://en.wikipedia.org/wiki/Opaque_data_type) type
+@ref GLFWmonitor.  Monitor objects cannot be created or destroyed by the
+application and retain their addresses until the monitors they represent are
+disconnected or until the library is [terminated](@ref intro_init_terminate).
+
+Each monitor has a current video mode, a list of supported video modes,
+a virtual position, a human-readable name, an estimated physical size and
+a gamma ramp.  One of the monitors is the primary monitor.
+
+The virtual position of a monitor is in
+[screen coordinates](@ref coordinate_systems) and, together with the current
+video mode, describes the viewports that the connected monitors provide into the
+virtual desktop that spans them.
+
+To see how GLFW views your monitor setup and its available video modes, run the
+`monitors` test program.
+
+
+@subsection monitor_monitors Retrieving monitors
+
+The primary monitor is returned by @ref glfwGetPrimaryMonitor.  It is the user's
+preferred monitor and is usually the one with global UI elements like task bar
+or menu bar.
+
+@code
+GLFWmonitor* primary = glfwGetPrimaryMonitor();
+@endcode
+
+You can retrieve all currently connected monitors with @ref glfwGetMonitors.
+See the reference documentation for the lifetime of the returned array.
+
+@code
+int count;
+GLFWmonitor** monitors = glfwGetMonitors(&count);
+@endcode
+
+The primary monitor is always the first monitor in the returned array, but other
+monitors may be moved to a different index when a monitor is connected or
+disconnected.
+
+
+@subsection monitor_event Monitor configuration changes
+
+If you wish to be notified when a monitor is connected or disconnected, set
+a monitor callback.
+
+@code
+glfwSetMonitorCallback(monitor_callback);
+@endcode
+
+The callback function receives the handle for the monitor that has been
+connected or disconnected and the event that occurred.
+
+@code
+void monitor_callback(GLFWmonitor* monitor, int event)
+{
+    if (event == GLFW_CONNECTED)
+    {
+        // The monitor was connected
+    }
+    else if (event == GLFW_DISCONNECTED)
+    {
+        // The monitor was disconnected
+    }
+}
+@endcode
+
+If a monitor is disconnected, all windows that are full screen on it will be
+switched to windowed mode before the callback is called.  Only @ref
+glfwGetMonitorName and @ref glfwGetMonitorUserPointer will return useful values
+for a disconnected monitor and only before the monitor callback returns.
+
+
+@section monitor_properties Monitor properties
+
+Each monitor has a current video mode, a list of supported video modes,
+a virtual position, a content scale, a human-readable name, a user pointer, an
+estimated physical size and a gamma ramp.
+
+
+@subsection monitor_modes Video modes
+
+GLFW generally does a good job selecting a suitable video mode when you create
+a full screen window, change its video mode or make a windowed one full
+screen, but it is sometimes useful to know exactly which video modes are
+supported.
+
+Video modes are represented as @ref GLFWvidmode structures.  You can get an
+array of the video modes supported by a monitor with @ref glfwGetVideoModes.
+See the reference documentation for the lifetime of the returned array.
+
+@code
+int count;
+GLFWvidmode* modes = glfwGetVideoModes(monitor, &count);
+@endcode
+
+To get the current video mode of a monitor call @ref glfwGetVideoMode.  See the
+reference documentation for the lifetime of the returned pointer.
+
+@code
+const GLFWvidmode* mode = glfwGetVideoMode(monitor);
+@endcode
+
+The resolution of a video mode is specified in
+[screen coordinates](@ref coordinate_systems), not pixels.
+
+
+@subsection monitor_size Physical size
+
+The physical size of a monitor in millimetres, or an estimation of it, can be
+retrieved with @ref glfwGetMonitorPhysicalSize.  This has no relation to its
+current _resolution_, i.e. the width and height of its current
+[video mode](@ref monitor_modes).
+
+@code
+int width_mm, height_mm;
+glfwGetMonitorPhysicalSize(monitor, &width_mm, &height_mm);
+@endcode
+
+While this can be used to calculate the raw DPI of a monitor, this is often not
+useful.  Instead use the [monitor content scale](@ref monitor_scale) and
+[window content scale](@ref window_scale) to scale your content.
+
+
+@subsection monitor_scale Content scale
+
+The content scale for a monitor can be retrieved with @ref
+glfwGetMonitorContentScale.
+
+@code
+float xscale, yscale;
+glfwGetMonitorContentScale(monitor, &xscale, &yscale);
+@endcode
+
+The content scale is the ratio between the current DPI and the platform's
+default DPI.  This is especially important for text and any UI elements.  If the
+pixel dimensions of your UI scaled by this look appropriate on your machine then
+it should appear at a reasonable size on other machines regardless of their DPI
+and scaling settings.  This relies on the system DPI and scaling settings being
+somewhat correct.
+
+The content scale may depend on both the monitor resolution and pixel density
+and on user settings.  It may be very different from the raw DPI calculated from
+the physical size and current resolution.
+
+
+@subsection monitor_pos Virtual position
+
+The position of the monitor on the virtual desktop, in
+[screen coordinates](@ref coordinate_systems), can be retrieved with @ref
+glfwGetMonitorPos.
+
+@code
+int xpos, ypos;
+glfwGetMonitorPos(monitor, &xpos, &ypos);
+@endcode
+
+
+@subsection monitor_workarea Work area
+
+The area of a monitor not occupied by global task bars or menu bars is the work
+area.  This is specified in [screen coordinates](@ref coordinate_systems) and
+can be retrieved with @ref glfwGetMonitorWorkarea.
+
+@code
+int xpos, ypos, width, height;
+glfwGetMonitorWorkarea(monitor, &xpos, &ypos, &width, &height);
+@endcode
+
+
+@subsection monitor_name Human-readable name
+
+The human-readable, UTF-8 encoded name of a monitor is returned by @ref
+glfwGetMonitorName.  See the reference documentation for the lifetime of the
+returned string.
+
+@code
+const char* name = glfwGetMonitorName(monitor);
+@endcode
+
+Monitor names are not guaranteed to be unique.  Two monitors of the same model
+and make may have the same name.  Only the monitor handle is guaranteed to be
+unique, and only until that monitor is disconnected.
+
+
+@subsection monitor_userptr User pointer
+
+Each monitor has a user pointer that can be set with @ref
+glfwSetMonitorUserPointer and queried with @ref glfwGetMonitorUserPointer.  This
+can be used for any purpose you need and will not be modified by GLFW.  The
+value will be kept until the monitor is disconnected or until the library is
+terminated.
+
+The initial value of the pointer is `NULL`.
+
+
+@subsection monitor_gamma Gamma ramp
+
+The gamma ramp of a monitor can be set with @ref glfwSetGammaRamp, which accepts
+a monitor handle and a pointer to a @ref GLFWgammaramp structure.
+
+@code
+GLFWgammaramp ramp;
+unsigned short red[256], green[256], blue[256];
+
+ramp.size = 256;
+ramp.red = red;
+ramp.green = green;
+ramp.blue = blue;
+
+for (i = 0;  i < ramp.size;  i++)
+{
+    // Fill out gamma ramp arrays as desired
+}
+
+glfwSetGammaRamp(monitor, &ramp);
+@endcode
+
+The gamma ramp data is copied before the function returns, so there is no need
+to keep it around once the ramp has been set.
+
+It is recommended that your gamma ramp have the same size as the current gamma
+ramp for that monitor.
+
+The current gamma ramp for a monitor is returned by @ref glfwGetGammaRamp.  See
+the reference documentation for the lifetime of the returned structure.
+
+@code
+const GLFWgammaramp* ramp = glfwGetGammaRamp(monitor);
+@endcode
+
+If you wish to set a regular gamma ramp, you can have GLFW calculate it for you
+from the desired exponent with @ref glfwSetGamma, which in turn calls @ref
+glfwSetGammaRamp with the resulting ramp.
+
+@code
+glfwSetGamma(monitor, 1.0);
+@endcode
+
+To experiment with gamma correction via the @ref glfwSetGamma function, run the
+`gamma` test program.
+
+@note The software controlled gamma ramp is applied _in addition_ to the
+hardware gamma correction, which today is usually an approximation of sRGB
+gamma.  This means that setting a perfectly linear ramp, or gamma 1.0, will
+produce the default (usually sRGB-like) behavior.
+
+*/

+ 513 - 0
samples/third_party/glfw/docs/moving.dox

@@ -0,0 +1,513 @@
+/*!
+
+@page moving_guide Moving from GLFW 2 to 3
+
+@tableofcontents
+
+This is a transition guide for moving from GLFW 2 to 3.  It describes what has
+changed or been removed, but does _not_ include
+[new features](@ref news) unless they are required when moving an existing code
+base onto the new API.  For example, the new multi-monitor functions are
+required to create full screen windows with GLFW 3.
+
+
+@section moving_removed Changed and removed features
+
+@subsection moving_renamed_files Renamed library and header file
+
+The GLFW 3 header is named @ref glfw3.h and moved to the `GLFW` directory, to
+avoid collisions with the headers of other major versions.  Similarly, the GLFW
+3 library is named `glfw3,` except when it's installed as a shared library on
+Unix-like systems, where it uses the
+[soname](https://en.wikipedia.org/wiki/soname) `libglfw.so.3`.
+
+@par Old syntax
+@code
+#include <GL/glfw.h>
+@endcode
+
+@par New syntax
+@code
+#include <GLFW/glfw3.h>
+@endcode
+
+
+@subsection moving_threads Removal of threading functions
+
+The threading functions have been removed, including the per-thread sleep
+function.  They were fairly primitive, under-used, poorly integrated and took
+time away from the focus of GLFW (i.e.  context, input and window).  There are
+better threading libraries available and native threading support is available
+in both [C++11](https://en.cppreference.com/w/cpp/thread) and
+[C11](https://en.cppreference.com/w/c/thread), both of which are gaining
+traction.
+
+If you wish to use the C++11 or C11 facilities but your compiler doesn't yet
+support them, see the
+[TinyThread++](https://gitorious.org/tinythread/tinythreadpp) and
+[TinyCThread](https://github.com/tinycthread/tinycthread) projects created by
+the original author of GLFW.  These libraries implement a usable subset of the
+threading APIs in C++11 and C11, and in fact some GLFW 3 test programs use
+TinyCThread.
+
+However, GLFW 3 has better support for _use from multiple threads_ than GLFW
+2 had.  Contexts can be made current on any thread, although only a single
+thread at a time, and the documentation explicitly states which functions may be
+used from any thread and which must only be used from the main thread.
+
+@par Removed functions
+`glfwSleep`, `glfwCreateThread`, `glfwDestroyThread`, `glfwWaitThread`,
+`glfwGetThreadID`, `glfwCreateMutex`, `glfwDestroyMutex`, `glfwLockMutex`,
+`glfwUnlockMutex`, `glfwCreateCond`, `glfwDestroyCond`, `glfwWaitCond`,
+`glfwSignalCond`, `glfwBroadcastCond` and `glfwGetNumberOfProcessors`.
+
+@par Removed types
+`GLFWthreadfun`
+
+
+@subsection moving_image Removal of image and texture loading
+
+The image and texture loading functions have been removed.  They only supported
+the Targa image format, making them mostly useful for beginner level examples.
+To become of sufficiently high quality to warrant keeping them in GLFW 3, they
+would need not only to support other formats, but also modern extensions to
+OpenGL texturing.  This would either add a number of external
+dependencies (libjpeg, libpng, etc.), or force GLFW to ship with inline versions
+of these libraries.
+
+As there already are libraries doing this, it is unnecessary both to duplicate
+the work and to tie the duplicate to GLFW.  The resulting library would also be
+platform-independent, as both OpenGL and stdio are available wherever GLFW is.
+
+@par Removed functions
+`glfwReadImage`, `glfwReadMemoryImage`, `glfwFreeImage`, `glfwLoadTexture2D`,
+`glfwLoadMemoryTexture2D` and `glfwLoadTextureImage2D`.
+
+
+@subsection moving_stdcall Removal of GLFWCALL macro
+
+The `GLFWCALL` macro, which made callback functions use
+[__stdcall](https://msdn.microsoft.com/en-us/library/zxk0tw93.aspx) on Windows,
+has been removed.  GLFW is written in C, not Pascal.  Removing this macro means
+there's one less thing for application programmers to remember, i.e. the
+requirement to mark all callback functions with `GLFWCALL`.  It also simplifies
+the creation of DLLs and DLL link libraries, as there's no need to explicitly
+disable `@n` entry point suffixes.
+
+@par Old syntax
+@code
+void GLFWCALL callback_function(...);
+@endcode
+
+@par New syntax
+@code
+void callback_function(...);
+@endcode
+
+
+@subsection moving_window_handles Window handle parameters
+
+Because GLFW 3 supports multiple windows, window handle parameters have been
+added to all window-related GLFW functions and callbacks.  The handle of
+a newly created window is returned by @ref glfwCreateWindow (formerly
+`glfwOpenWindow`).  Window handles are pointers to the
+[opaque](https://en.wikipedia.org/wiki/Opaque_data_type) type @ref GLFWwindow.
+
+@par Old syntax
+@code
+glfwSetWindowTitle("New Window Title");
+@endcode
+
+@par New syntax
+@code
+glfwSetWindowTitle(window, "New Window Title");
+@endcode
+
+
+@subsection moving_monitor Explicit monitor selection
+
+GLFW 3 provides support for multiple monitors.  To request a full screen mode window,
+instead of passing `GLFW_FULLSCREEN` you specify which monitor you wish the
+window to use.  The @ref glfwGetPrimaryMonitor function returns the monitor that
+GLFW 2 would have selected, but there are many other
+[monitor functions](@ref monitor_guide).  Monitor handles are pointers to the
+[opaque](https://en.wikipedia.org/wiki/Opaque_data_type) type @ref GLFWmonitor.
+
+@par Old basic full screen
+@code
+glfwOpenWindow(640, 480, 8, 8, 8, 0, 24, 0, GLFW_FULLSCREEN);
+@endcode
+
+@par New basic full screen
+@code
+window = glfwCreateWindow(640, 480, "My Window", glfwGetPrimaryMonitor(), NULL);
+@endcode
+
+@note The framebuffer bit depth parameters of `glfwOpenWindow` have been turned
+into [window hints](@ref window_hints), but as they have been given
+[sane defaults](@ref window_hints_values) you rarely need to set these hints.
+
+
+@subsection moving_autopoll Removal of automatic event polling
+
+GLFW 3 does not automatically poll for events in @ref glfwSwapBuffers, meaning
+you need to call @ref glfwPollEvents or @ref glfwWaitEvents yourself.  Unlike
+buffer swap, which acts on a single window, the event processing functions act
+on all windows at once.
+
+@par Old basic main loop
+@code
+while (...)
+{
+    // Process input
+    // Render output
+    glfwSwapBuffers();
+}
+@endcode
+
+@par New basic main loop
+@code
+while (...)
+{
+    // Process input
+    // Render output
+    glfwSwapBuffers(window);
+    glfwPollEvents();
+}
+@endcode
+
+
+@subsection moving_context Explicit context management
+
+Each GLFW 3 window has its own OpenGL context and only you, the application
+programmer, can know which context should be current on which thread at any
+given time.  Therefore, GLFW 3 leaves that decision to you.
+
+This means that you need to call @ref glfwMakeContextCurrent after creating
+a window before you can call any OpenGL functions.
+
+
+@subsection moving_hidpi Separation of window and framebuffer sizes
+
+Window positions and sizes now use screen coordinates, which may not be the same
+as pixels on machines with high-DPI monitors.  This is important as OpenGL uses
+pixels, not screen coordinates.  For example, the rectangle specified with
+`glViewport` needs to use pixels.  Therefore, framebuffer size functions have
+been added.  You can retrieve the size of the framebuffer of a window with @ref
+glfwGetFramebufferSize function.  A framebuffer size callback has also been
+added, which can be set with @ref glfwSetFramebufferSizeCallback.
+
+@par Old basic viewport setup
+@code
+glfwGetWindowSize(&width, &height);
+glViewport(0, 0, width, height);
+@endcode
+
+@par New basic viewport setup
+@code
+glfwGetFramebufferSize(window, &width, &height);
+glViewport(0, 0, width, height);
+@endcode
+
+
+@subsection moving_window_close Window closing changes
+
+The `GLFW_OPENED` window parameter has been removed.  As long as the window has
+not been destroyed, whether through @ref glfwDestroyWindow or @ref
+glfwTerminate, the window is "open".
+
+A user attempting to close a window is now just an event like any other.  Unlike
+GLFW 2, windows and contexts created with GLFW 3 will never be destroyed unless
+you choose them to be.  Each window now has a close flag that is set to
+`GLFW_TRUE` when the user attempts to close that window.  By default, nothing else
+happens and the window stays visible.  It is then up to you to either destroy
+the window, take some other action or ignore the request.
+
+You can query the close flag at any time with @ref glfwWindowShouldClose and set
+it at any time with @ref glfwSetWindowShouldClose.
+
+@par Old basic main loop
+@code
+while (glfwGetWindowParam(GLFW_OPENED))
+{
+    ...
+}
+@endcode
+
+@par New basic main loop
+@code
+while (!glfwWindowShouldClose(window))
+{
+    ...
+}
+@endcode
+
+The close callback no longer returns a value.  Instead, it is called after the
+close flag has been set so it can override its value, if it chooses to, before
+event processing completes.  You may however not call @ref glfwDestroyWindow
+from the close callback (or any other window related callback).
+
+@par Old syntax
+@code
+int GLFWCALL window_close_callback(void);
+@endcode
+
+@par New syntax
+@code
+void window_close_callback(GLFWwindow* window);
+@endcode
+
+@note GLFW never clears the close flag to `GLFW_FALSE`, meaning you can use it
+for other reasons to close the window as well, for example the user choosing
+Quit from an in-game menu.
+
+
+@subsection moving_hints Persistent window hints
+
+The `glfwOpenWindowHint` function has been renamed to @ref glfwWindowHint.
+
+Window hints are no longer reset to their default values on window creation, but
+instead retain their values until modified by @ref glfwWindowHint or @ref
+glfwDefaultWindowHints, or until the library is terminated and re-initialized.
+
+
+@subsection moving_video_modes Video mode enumeration
+
+Video mode enumeration is now per-monitor.  The @ref glfwGetVideoModes function
+now returns all available modes for a specific monitor instead of requiring you
+to guess how large an array you need.  The `glfwGetDesktopMode` function, which
+had poorly defined behavior, has been replaced by @ref glfwGetVideoMode, which
+returns the current mode of a monitor.
+
+
+@subsection moving_char_up Removal of character actions
+
+The action parameter of the [character callback](@ref GLFWcharfun) has been
+removed.  This was an artefact of the origin of GLFW, i.e. being developed in
+English by a Swede.  However, many keyboard layouts require more than one key to
+produce characters with diacritical marks. Even the Swedish keyboard layout
+requires this for uncommon cases like ü.
+
+@par Old syntax
+@code
+void GLFWCALL character_callback(int character, int action);
+@endcode
+
+@par New syntax
+@code
+void character_callback(GLFWwindow* window, int character);
+@endcode
+
+
+@subsection moving_cursorpos Cursor position changes
+
+The `glfwGetMousePos` function has been renamed to @ref glfwGetCursorPos,
+`glfwSetMousePos` to @ref glfwSetCursorPos and `glfwSetMousePosCallback` to @ref
+glfwSetCursorPosCallback.
+
+The cursor position is now `double` instead of `int`, both for the direct
+functions and for the callback.  Some platforms can provide sub-pixel cursor
+movement and this data is now passed on to the application where available.  On
+platforms where this is not provided, the decimal part is zero.
+
+GLFW 3 only allows you to position the cursor within a window using @ref
+glfwSetCursorPos (formerly `glfwSetMousePos`) when that window is active.
+Unless the window is active, the function fails silently.
+
+
+@subsection moving_wheel Wheel position replaced by scroll offsets
+
+The `glfwGetMouseWheel` function has been removed.  Scrolling is the input of
+offsets and has no absolute position.  The mouse wheel callback has been
+replaced by a [scroll callback](@ref GLFWscrollfun) that receives
+two-dimensional floating point scroll offsets.  This allows you to receive
+precise scroll data from for example modern touchpads.
+
+@par Old syntax
+@code
+void GLFWCALL mouse_wheel_callback(int position);
+@endcode
+
+@par New syntax
+@code
+void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
+@endcode
+
+@par Removed functions
+`glfwGetMouseWheel`
+
+
+@subsection moving_repeat Key repeat action
+
+The `GLFW_KEY_REPEAT` enable has been removed and key repeat is always enabled
+for both keys and characters.  A new key action, `GLFW_REPEAT`, has been added
+to allow the [key callback](@ref GLFWkeyfun) to distinguish an initial key press
+from a repeat.  Note that @ref glfwGetKey still returns only `GLFW_PRESS` or
+`GLFW_RELEASE`.
+
+
+@subsection moving_keys Physical key input
+
+GLFW 3 key tokens map to physical keys, unlike in GLFW 2 where they mapped to
+the values generated by the current keyboard layout.  The tokens are named
+according to the values they would have using the standard US layout, but this
+is only a convenience, as most programmers are assumed to know that layout.
+This means that (for example) `GLFW_KEY_LEFT_BRACKET` is always a single key and
+is the same key in the same place regardless of what keyboard layouts the users
+of your program has.
+
+The key input facility was never meant for text input, although using it that
+way worked slightly better in GLFW 2.  If you were using it to input text, you
+should be using the character callback instead, on both GLFW 2 and 3.  This will
+give you the characters being input, as opposed to the keys being pressed.
+
+GLFW 3 has key tokens for all keys on a standard 105 key keyboard, so instead of
+having to remember whether to check for `a` or `A`, you now check for
+@ref GLFW_KEY_A.
+
+
+@subsection moving_joystick Joystick function changes
+
+The `glfwGetJoystickPos` function has been renamed to @ref glfwGetJoystickAxes.
+
+The `glfwGetJoystickParam` function and the `GLFW_PRESENT`, `GLFW_AXES` and
+`GLFW_BUTTONS` tokens have been replaced by the @ref glfwJoystickPresent
+function as well as axis and button counts returned by the @ref
+glfwGetJoystickAxes and @ref glfwGetJoystickButtons functions.
+
+
+@subsection moving_mbcs Win32 MBCS support
+
+The Win32 port of GLFW 3 will not compile in
+[MBCS mode](https://msdn.microsoft.com/en-us/library/5z097dxa.aspx).
+However, because the use of the Unicode version of the Win32 API doesn't affect
+the process as a whole, but only those windows created using it, it's perfectly
+possible to call MBCS functions from other parts of the same application.
+Therefore, even if an application using GLFW has MBCS mode code, there's no need
+for GLFW itself to support it.
+
+
+@subsection moving_windows Support for versions of Windows older than XP
+
+All explicit support for version of Windows older than XP has been removed.
+There is no code that actively prevents GLFW 3 from running on these earlier
+versions, but it uses Win32 functions that those versions lack.
+
+Windows XP was released in 2001, and by now (January 2015) it has not only
+replaced almost all earlier versions of Windows, but is itself rapidly being
+replaced by Windows 7 and 8.  The MSDN library doesn't even provide
+documentation for version older than Windows 2000, making it difficult to
+maintain compatibility with these versions even if it was deemed worth the
+effort.
+
+The Win32 API has also not stood still, and GLFW 3 uses many functions only
+present on Windows XP or later.  Even supporting an OS as new as XP (new
+from the perspective of GLFW 2, which still supports Windows 95) requires
+runtime checking for a number of functions that are present only on modern
+version of Windows.
+
+
+@subsection moving_syskeys Capture of system-wide hotkeys
+
+The ability to disable and capture system-wide hotkeys like Alt+Tab has been
+removed.  Modern applications, whether they're games, scientific visualisations
+or something else, are nowadays expected to be good desktop citizens and allow
+these hotkeys to function even when running in full screen mode.
+
+
+@subsection moving_terminate Automatic termination
+
+GLFW 3 does not register @ref glfwTerminate with `atexit` at initialization,
+because `exit` calls registered functions from the calling thread and while it
+is permitted to call `exit` from any thread, @ref glfwTerminate must only be
+called from the main thread.
+
+To release all resources allocated by GLFW, you should call @ref glfwTerminate
+yourself, from the main thread, before the program terminates.  Note that this
+destroys all windows not already destroyed with @ref glfwDestroyWindow,
+invalidating any window handles you may still have.
+
+
+@subsection moving_glu GLU header inclusion
+
+GLFW 3 does not by default include the GLU header and GLU itself has been
+deprecated by [Khronos](https://en.wikipedia.org/wiki/Khronos_Group).  __New
+projects should not use GLU__, but if you need it for legacy code that
+has been moved to GLFW 3, you can request that the GLFW header includes it by
+defining @ref GLFW_INCLUDE_GLU before the inclusion of the GLFW header.
+
+@par Old syntax
+@code
+#include <GL/glfw.h>
+@endcode
+
+@par New syntax
+@code
+#define GLFW_INCLUDE_GLU
+#include <GLFW/glfw3.h>
+@endcode
+
+There are many libraries that offer replacements for the functionality offered
+by GLU.  For the matrix helper functions, see math libraries like
+[GLM](https://github.com/g-truc/glm) (for C++),
+[linmath.h](https://github.com/datenwolf/linmath.h) (for C) and others.  For the
+tessellation functions, see for example
+[libtess2](https://github.com/memononen/libtess2).
+
+
+@section moving_tables Name change tables
+
+
+@subsection moving_renamed_functions Renamed functions
+
+| GLFW 2                      | GLFW 3                        | Notes |
+| --------------------------- | ----------------------------- | ----- |
+| `glfwOpenWindow`            | @ref glfwCreateWindow         | All channel bit depths are now hints
+| `glfwCloseWindow`           | @ref glfwDestroyWindow        |       |
+| `glfwOpenWindowHint`        | @ref glfwWindowHint           | Now accepts all `GLFW_*_BITS` tokens |
+| `glfwEnable`                | @ref glfwSetInputMode         |       |
+| `glfwDisable`               | @ref glfwSetInputMode         |       |
+| `glfwGetMousePos`           | @ref glfwGetCursorPos         |       |
+| `glfwSetMousePos`           | @ref glfwSetCursorPos         |       |
+| `glfwSetMousePosCallback`   | @ref glfwSetCursorPosCallback |       |
+| `glfwSetMouseWheelCallback` | @ref glfwSetScrollCallback    | Accepts two-dimensional scroll offsets as doubles |
+| `glfwGetJoystickPos`        | @ref glfwGetJoystickAxes      |       |
+| `glfwGetWindowParam`        | @ref glfwGetWindowAttrib      |       |
+| `glfwGetGLVersion`          | @ref glfwGetWindowAttrib      | Use `GLFW_CONTEXT_VERSION_MAJOR`, `GLFW_CONTEXT_VERSION_MINOR` and `GLFW_CONTEXT_REVISION` |
+| `glfwGetDesktopMode`        | @ref glfwGetVideoMode         | Returns the current mode of a monitor |
+| `glfwGetJoystickParam`      | @ref glfwJoystickPresent      | The axis and button counts are provided by @ref glfwGetJoystickAxes and @ref glfwGetJoystickButtons |
+
+
+@subsection moving_renamed_types Renamed types
+
+| GLFW 2              | GLFW 3                | Notes |
+| ------------------- | --------------------- |       |
+| `GLFWmousewheelfun` | @ref GLFWscrollfun    |       |
+| `GLFWmouseposfun`   | @ref GLFWcursorposfun |       |
+
+
+@subsection moving_renamed_tokens Renamed tokens
+
+| GLFW 2                      | GLFW 3                       | Notes |
+| --------------------------- | ---------------------------- | ----- |
+| `GLFW_OPENGL_VERSION_MAJOR` | `GLFW_CONTEXT_VERSION_MAJOR` | Renamed as it applies to OpenGL ES as well |
+| `GLFW_OPENGL_VERSION_MINOR` | `GLFW_CONTEXT_VERSION_MINOR` | Renamed as it applies to OpenGL ES as well |
+| `GLFW_FSAA_SAMPLES`         | `GLFW_SAMPLES`               | Renamed to match the OpenGL API |
+| `GLFW_ACTIVE`               | `GLFW_FOCUSED`               | Renamed to match the window focus callback |
+| `GLFW_WINDOW_NO_RESIZE`     | `GLFW_RESIZABLE`             | The default has been inverted |
+| `GLFW_MOUSE_CURSOR`         | `GLFW_CURSOR`                | Used with @ref glfwSetInputMode |
+| `GLFW_KEY_ESC`              | `GLFW_KEY_ESCAPE`            |       |
+| `GLFW_KEY_DEL`              | `GLFW_KEY_DELETE`            |       |
+| `GLFW_KEY_PAGEUP`           | `GLFW_KEY_PAGE_UP`           |       |
+| `GLFW_KEY_PAGEDOWN`         | `GLFW_KEY_PAGE_DOWN`         |       |
+| `GLFW_KEY_KP_NUM_LOCK`      | `GLFW_KEY_NUM_LOCK`          |       |
+| `GLFW_KEY_LCTRL`            | `GLFW_KEY_LEFT_CONTROL`      |       |
+| `GLFW_KEY_LSHIFT`           | `GLFW_KEY_LEFT_SHIFT`        |       |
+| `GLFW_KEY_LALT`             | `GLFW_KEY_LEFT_ALT`          |       |
+| `GLFW_KEY_LSUPER`           | `GLFW_KEY_LEFT_SUPER`        |       |
+| `GLFW_KEY_RCTRL`            | `GLFW_KEY_RIGHT_CONTROL`     |       |
+| `GLFW_KEY_RSHIFT`           | `GLFW_KEY_RIGHT_SHIFT`       |       |
+| `GLFW_KEY_RALT`             | `GLFW_KEY_RIGHT_ALT`         |       |
+| `GLFW_KEY_RSUPER`           | `GLFW_KEY_RIGHT_SUPER`       |       |
+
+*/

+ 863 - 0
samples/third_party/glfw/docs/news.dox

@@ -0,0 +1,863 @@
+/*!
+
+@page news Release notes
+
+@tableofcontents
+
+
+@section news_33 Release notes for version 3.3
+
+These are the release notes for version 3.3.  For a more detailed view including
+all fixed bugs see the [version history](https://www.glfw.org/changelog.html).
+
+Please review the caveats, deprecations and removals if your project was written
+against an earlier version of GLFW 3.
+
+
+@subsection features_33 New features in version 3.3
+
+@subsubsection gamepad_33 Gamepad input via SDL_GameControllerDB
+
+GLFW can now remap game controllers to a standard Xbox-like layout using
+a built-in copy of SDL_GameControllerDB.  Call @ref glfwJoystickIsGamepad to
+check if a joystick has a mapping, @ref glfwGetGamepadState to retrieve its
+input state, @ref glfwUpdateGamepadMappings to add newer mappings and @ref
+glfwGetGamepadName and @ref glfwGetJoystickGUID for mapping related information.
+
+For more information see @ref gamepad.
+
+
+@subsubsection moltenvk_33 Support for Vulkan on macOS via MoltenVK
+
+GLFW now supports [MoltenVK](https://moltengl.com/moltenvk/), a Vulkan
+implementation on top of the Metal API, and its `VK_MVK_macos_surface` window
+surface creation extension.  MoltenVK is included in the [macOS Vulkan
+SDK](https://vulkan.lunarg.com/).
+
+For more information see @ref vulkan_guide.
+
+
+@subsubsection content_scale_33 Content scale queries for DPI-aware rendering
+
+GLFW now provides content scales for windows and monitors, i.e. the ratio
+between their current DPI and the platform's default DPI, with @ref
+glfwGetWindowContentScale and @ref glfwGetMonitorContentScale.
+
+Changes of the content scale of a window can be received with the window content
+scale callback, set with @ref glfwSetWindowContentScaleCallback.
+
+The @ref GLFW_SCALE_TO_MONITOR window hint enables automatic resizing of a
+window by the content scale of the monitor it is placed, on platforms like
+Windows where this is necessary.  This takes effect both on creation and when
+the window is moved between monitors.  It is related to but different from
+[GLFW_COCOA_RETINA_FRAMEBUFFER](@ref GLFW_COCOA_RETINA_FRAMEBUFFER_hint).
+
+For more information see @ref window_scale.
+
+
+@subsubsection setwindowattrib_33 Support for updating window attributes
+
+GLFW now supports changing the [GLFW_DECORATED](@ref GLFW_DECORATED_attrib),
+[GLFW_RESIZABLE](@ref GLFW_RESIZABLE_attrib),
+[GLFW_FLOATING](@ref GLFW_FLOATING_attrib),
+[GLFW_AUTO_ICONIFY](@ref GLFW_AUTO_ICONIFY_attrib) and
+[GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_attrib) attributes for existing
+windows with @ref glfwSetWindowAttrib.
+
+For more information see @ref window_attribs.
+
+
+@subsubsection raw_motion_33 Support for raw mouse motion
+
+GLFW now supports raw (unscaled and unaccelerated) mouse motion in disabled
+cursor mode with the [GLFW_RAW_MOUSE_MOTION](@ref GLFW_RAW_MOUSE_MOTION) input
+mode.  Raw mouse motion input is not yet implemented on macOS.  Call @ref
+glfwRawMouseMotionSupported to check if GLFW can provide raw mouse motion on the
+current system.
+
+For more information see @ref raw_mouse_motion.
+
+
+@subsubsection joysticks_33 Joystick hats
+
+GLFW can now return the state of hats (i.e. POVs or D-pads) of a joystick with
+@ref glfwGetJoystickHats.  For compatibility, hats are also exposed as buttons.
+This can be disabled with the @ref GLFW_JOYSTICK_HAT_BUTTONS initialization
+hint.
+
+For more information see @ref joystick_hat.
+
+
+@subsubsection geterror_33 Error query
+
+GLFW now supports querying the last error code for the calling thread and its
+human-readable description with @ref glfwGetError.  This can be used instead of
+or together with the error callback.
+
+For more information see @ref error_handling.
+
+
+@subsubsection init_hints_33 Support for initialization hints
+
+GLFW now supports setting library initialization hints with @ref glfwInitHint.
+These must be set before initialization to take effect.  Some of these hints are
+platform specific but are safe to set on any platform.
+
+For more information see @ref init_hints.
+
+
+@subsubsection attention_33 User attention request
+
+GLFW now supports requesting user attention with @ref
+glfwRequestWindowAttention.  Where possible this calls attention to the
+specified window.  On platforms like macOS it calls attention to the whole
+application.
+
+For more information see @ref window_attention.
+
+
+@subsubsection maximize_33 Window maximization callback
+
+GLFW now supports notifying the application that the window has been maximized
+@ref glfwSetWindowMaximizeCallback.  This is called both when the window was
+maximized by the user and when it was done with @ref glfwMaximizeWindow.
+
+For more information see @ref window_maximize.
+
+
+@subsubsection workarea_33 Query for the monitor work area
+
+GLFW now supports querying the work area of a monitor, i.e. the area not
+occupied by task bars or global menu bars, with @ref glfwGetMonitorWorkarea.  On
+platforms that lack this concept, the whole area of the monitor is returned.
+
+For more information see @ref monitor_workarea.
+
+
+@subsubsection transparency_33 Transparent windows and framebuffers
+
+GLFW now supports the creation of windows with transparent framebuffers on
+systems with desktop compositing enabled with the @ref
+GLFW_TRANSPARENT_FRAMEBUFFER window hint and attribute.  This hint must be set
+before window creation and leaves any window decorations opaque.
+
+GLFW now also supports whole window transparency with @ref glfwGetWindowOpacity
+and @ref glfwSetWindowOpacity.  This value controls the opacity of the whole
+window including decorations and unlike framebuffer transparency can be changed
+at any time after window creation.
+
+For more information see @ref window_transparency.
+
+
+@subsubsection key_scancode_33 Query for the scancode of a key
+
+GLFW now supports querying the platform dependent scancode of any physical key
+with @ref glfwGetKeyScancode.
+
+For more information see @ref input_key.
+
+
+@subsubsection center_cursor_33 Cursor centering window hint
+
+GLFW now supports controlling whether the cursor is centered over newly created
+full screen windows with the [GLFW_CENTER_CURSOR](@ref GLFW_CENTER_CURSOR_hint)
+window hint.  It is enabled by default.
+
+
+@subsubsection cursor_hover_33 Mouse cursor hover window attribute
+
+GLFW now supports polling whether the cursor is hovering over the window content
+area with the [GLFW_HOVERED](@ref GLFW_HOVERED_attrib) window attribute.  This
+attribute corresponds to the [cursor enter/leave](@ref cursor_enter) event.
+
+
+@subsubsection focusonshow_33 Window hint and attribute for input focus on show
+
+GLFW now has the [GLFW_FOCUS_ON_SHOW](@ref GLFW_DECORATED_hint) window hint and
+attribute for controlling whether a window gets input focus when shown.  It is
+enabled by default.  It applies both when creating an visible window with @ref
+glfwCreateWindow and when showing it with @ref glfwShowWindow.
+
+This is a workaround for GLFW 3.0 lacking @ref glfwFocusWindow and will be
+corrected in the next major version.
+
+For more information see @ref window_hide.
+
+
+@subsubsection device_userptr_33 Monitor and joystick user pointers
+
+GLFW now supports setting and querying user pointers for connected monitors and
+joysticks with @ref glfwSetMonitorUserPointer, @ref glfwGetMonitorUserPointer,
+@ref glfwSetJoystickUserPointer and @ref glfwGetJoystickUserPointer.
+
+For more information see @ref monitor_userptr and @ref joystick_userptr.
+
+
+@subsubsection macos_nib_33 macOS menu bar from nib file
+
+GLFW will now load a `MainMenu.nib` file if found in the `Contents/Resources`
+directory of the application bundle, as a way to replace the GLFW menu bar
+without recompiling GLFW.  This behavior can be disabled with the
+[GLFW_COCOA_MENUBAR](@ref GLFW_COCOA_MENUBAR_hint) initialization hint.
+
+
+@subsubsection glext_33 Support for more context creation extensions
+
+The context hint @ref GLFW_SRGB_CAPABLE now supports OpenGL ES via
+`WGL_EXT_colorspace`, the context hint @ref GLFW_CONTEXT_NO_ERROR now supports
+`WGL_ARB_create_context_no_error` and `GLX_ARB_create_context_no_error`, the
+context hint @ref GLFW_CONTEXT_RELEASE_BEHAVIOR now supports
+`EGL_KHR_context_flush_control` and @ref glfwGetProcAddress now supports
+`EGL_KHR_get_all_proc_addresses`.
+
+
+@subsubsection osmesa_33 OSMesa off-screen context creation support
+
+GLFW now supports creating off-screen OpenGL contexts using
+[OSMesa](https://www.mesa3d.org/osmesa.html) by setting
+[GLFW_CONTEXT_CREATION_API](@ref GLFW_CONTEXT_CREATION_API_hint) to
+`GLFW_OSMESA_CONTEXT_API`.  Native access function have been added to retrieve
+the OSMesa color and depth buffers.
+
+There is also a new null backend that uses OSMesa as its native context
+creation API, intended for automated testing.  This backend does not provide
+input.
+
+
+@subsection caveats_33 Caveats for version 3.3
+
+@subsubsection joystick_layout_33 Layout of joysticks have changed
+
+The way joystick elements are arranged have changed to match SDL2 in order to
+support SDL_GameControllerDB mappings.  The layout of joysticks may
+change again if required for compatibility with SDL2.  If you need a known and
+stable layout for game controllers, see if you can switch to @ref gamepad.
+
+Existing code that depends on a specific joystick layout will likely have to be
+updated.
+
+
+@subsubsection wait_events_33 No window required to wait for events
+
+The @ref glfwWaitEvents and @ref glfwWaitEventsTimeout functions no longer need
+a window to be created to wait for events.  Before version 3.3 these functions
+would return immediately if there were no user-created windows.  On platforms
+where only windows can receive events, an internal helper window is used.
+
+Existing code that depends on the earlier behavior will likely have to be
+updated.
+
+
+@subsubsection gamma_ramp_size_33 Gamma ramp size of 256 may be rejected
+
+The documentation for versions before 3.3 stated that a gamma ramp size of 256
+would always be accepted.  This was never the case on X11 and could lead to
+artifacts on macOS.  The @ref glfwSetGamma function has been updated to always
+generate a ramp of the correct size.
+
+Existing code that hardcodes a size of 256 should be updated to use the size of
+the current ramp of a monitor when setting a new ramp for that monitor.
+
+
+@subsubsection xinput_deadzone_33 Windows XInput deadzone removed
+
+GLFW no longer applies any deadzone to the input state received from the XInput
+API.  This was never done for any other platform joystick API so this change
+makes the behavior more consistent but you will need to apply your own deadzone
+if desired.
+
+
+@subsubsection x11_clipboard_33 X11 clipboard transfer limits
+
+GLFW now supports reading clipboard text via the `INCR` method, which removes
+the limit on how much text can be read with @ref glfwGetClipboardString.
+However, writing via this method is not yet supported, so you may not be able to
+write a very large string with @ref glfwSetClipboardString even if you read it
+from the clipboard earlier.
+
+The exact size limit for writing to the clipboard is negotiated with each
+receiving application but is at least several tens of kilobytes.  Note that only
+the read limit has changed.  Any string that could be written before still can
+be.
+
+
+@subsubsection x11_linking_33 X11 extension libraries are loaded dynamically
+
+GLFW now loads all X11 extension libraries at initialization.  The only X11
+library you need to link against is `libX11`.  The header files for the
+extension libraries are still required for compilation.
+
+Existing projects and makefiles that link GLFW directly against the extension
+libraries should still build correctly but will add these libraries as load-time
+dependencies.
+
+
+@subsubsection cmake_version_33 CMake 3.0 or later is required
+
+The minimum CMake version has been raised from 2.8.12 to 3.0.  This is only
+a requirement of the GLFW CMake files.  The GLFW source files do not depend on
+CMake.
+
+
+@subsubsection caveat_fbtransparency_33 Framebuffer transparency requires DWM transparency
+
+GLFW no longer supports framebuffer transparency enabled via @ref
+GLFW_TRANSPARENT_FRAMEBUFFER on Windows 7 if DWM transparency is off
+(the Transparency setting under Personalization > Window Color).
+
+
+@subsection deprecations_33 Deprecations in version 3.3
+
+@subsubsection charmods_callback_33 Character with modifiers callback
+
+The character with modifiers callback set with @ref glfwSetCharModsCallback has
+been deprecated and should if possible not be used.
+
+Existing code should still work but further bug fixes will likely not be made.
+The callback will be removed in the next major version.
+
+
+@subsubsection clipboard_window_33 Window parameter to clipboard functions
+
+The window parameter of the clipboard functions @ref glfwGetClipboardString and
+@ref glfwSetClipboardString has been deprecated and is no longer used on any
+platform.  On platforms where the clipboard must be owned by a specific window,
+an internal helper window is used.
+
+Existing code should still work unless it depends on a specific window owning
+the clipboard.  New code may pass `NULL` as the window argument.  The parameter
+will be removed in a future release.
+
+
+@subsection removals_33 Removals in 3.3
+
+@subsubsection macos_options_33 macOS specific CMake options and macros
+
+The `GLFW_USE_RETINA`, `GLFW_USE_CHDIR` and `GLFW_USE_MENUBAR` CMake options and
+the `_GLFW_USE_RETINA`, `_GLFW_USE_CHDIR` and `_GLFW_USE_MENUBAR` compile-time
+macros have been removed.
+
+These options and macros are replaced by the window hint
+[GLFW_COCOA_RETINA_FRAMEBUFFER](@ref GLFW_COCOA_RETINA_FRAMEBUFFER_hint)
+and the init hints
+[GLFW_COCOA_CHDIR_RESOURCES](@ref GLFW_COCOA_CHDIR_RESOURCES_hint) and
+[GLFW_COCOA_MENUBAR](@ref GLFW_COCOA_MENUBAR_hint).
+
+Existing projects and makefiles that set these options or define these macros
+during compilation of GLFW will still build but it will have no effect and the
+default behaviors will be used.
+
+
+@subsubsection vulkan_sdk_33 LunarG Vulkan SDK dependency
+
+The GLFW test programs that previously depended on the LunarG Vulkan SDK now
+instead uses a Vulkan loader generated by
+[glad2](https://github.com/Dav1dde/glad).  This means the GLFW CMake files no
+longer look for the Vulkan SDK.
+
+Existing CMake projects that depended on the Vulkan SDK cache variables from
+GLFW will need to call `find_package(Vulkan)` themselves.  CMake 3.7 and later
+already comes with a
+[Vulkan find module](https://cmake.org/cmake/help/latest/module/FindVulkan.html)
+similar to the one GLFW previously included.
+
+
+@subsubsection lib_suffix_33 CMake option LIB_SUFFIX
+
+The `LIB_SUFFIX` CMake option has been removed.  GLFW now uses the
+GNUInstallDirs CMake package to handle platform specific details like the
+library directory suffix and the `LIB_SUFFIX` CMake option has been removed.
+
+Existing projects and makefiles that set the `LIB_SUFFIX` option will use the
+suffix chosen by the GNUInstallDirs package and the option will be ignored.
+
+
+@subsubsection mir_removed_33 Mir support
+
+The experimental Mir support has been completely removed as the Mir project has
+implemented support for the Wayland protocol and is recommending that
+applications use that instead.
+
+Existing projects and makefiles that select Mir when compiling GLFW will fail.
+Use Wayland or X11 instead.
+
+
+@subsection symbols_33 New symbols in version 3.3
+
+@subsubsection functions_33 New functions in version 3.3
+
+ - @ref glfwInitHint
+ - @ref glfwGetError
+ - @ref glfwGetMonitorWorkarea
+ - @ref glfwGetMonitorContentScale
+ - @ref glfwGetMonitorUserPointer
+ - @ref glfwSetMonitorUserPointer
+ - @ref glfwWindowHintString
+ - @ref glfwGetWindowContentScale
+ - @ref glfwGetWindowOpacity
+ - @ref glfwSetWindowOpacity
+ - @ref glfwRequestWindowAttention
+ - @ref glfwSetWindowAttrib
+ - @ref glfwSetWindowMaximizeCallback
+ - @ref glfwSetWindowContentScaleCallback
+ - @ref glfwRawMouseMotionSupported
+ - @ref glfwGetKeyScancode
+ - @ref glfwGetJoystickHats
+ - @ref glfwGetJoystickGUID
+ - @ref glfwGetJoystickUserPointer
+ - @ref glfwSetJoystickUserPointer
+ - @ref glfwJoystickIsGamepad
+ - @ref glfwUpdateGamepadMappings
+ - @ref glfwGetGamepadName
+ - @ref glfwGetGamepadState
+
+
+@subsubsection types_33 New types in version 3.3
+
+ - @ref GLFWwindowmaximizefun
+ - @ref GLFWwindowcontentscalefun
+ - @ref GLFWgamepadstate
+
+
+@subsubsection constants_33 New constants in version 3.3
+
+ - @ref GLFW_NO_ERROR
+ - @ref GLFW_JOYSTICK_HAT_BUTTONS
+ - @ref GLFW_COCOA_CHDIR_RESOURCES
+ - @ref GLFW_COCOA_MENUBAR
+ - @ref GLFW_CENTER_CURSOR
+ - @ref GLFW_TRANSPARENT_FRAMEBUFFER
+ - @ref GLFW_HOVERED
+ - @ref GLFW_FOCUS_ON_SHOW
+ - @ref GLFW_SCALE_TO_MONITOR
+ - @ref GLFW_COCOA_RETINA_FRAMEBUFFER
+ - @ref GLFW_COCOA_FRAME_NAME
+ - @ref GLFW_COCOA_GRAPHICS_SWITCHING
+ - @ref GLFW_X11_CLASS_NAME
+ - @ref GLFW_X11_INSTANCE_NAME
+ - @ref GLFW_OSMESA_CONTEXT_API
+ - @ref GLFW_HAT_CENTERED
+ - @ref GLFW_HAT_UP
+ - @ref GLFW_HAT_RIGHT
+ - @ref GLFW_HAT_DOWN
+ - @ref GLFW_HAT_LEFT
+ - @ref GLFW_HAT_RIGHT_UP
+ - @ref GLFW_HAT_RIGHT_DOWN
+ - @ref GLFW_HAT_LEFT_UP
+ - @ref GLFW_HAT_LEFT_DOWN
+ - @ref GLFW_MOD_CAPS_LOCK
+ - @ref GLFW_MOD_NUM_LOCK
+ - @ref GLFW_LOCK_KEY_MODS
+ - @ref GLFW_RAW_MOUSE_MOTION
+ - @ref GLFW_GAMEPAD_BUTTON_A
+ - @ref GLFW_GAMEPAD_BUTTON_B
+ - @ref GLFW_GAMEPAD_BUTTON_X
+ - @ref GLFW_GAMEPAD_BUTTON_Y
+ - @ref GLFW_GAMEPAD_BUTTON_LEFT_BUMPER
+ - @ref GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER
+ - @ref GLFW_GAMEPAD_BUTTON_BACK
+ - @ref GLFW_GAMEPAD_BUTTON_START
+ - @ref GLFW_GAMEPAD_BUTTON_GUIDE
+ - @ref GLFW_GAMEPAD_BUTTON_LEFT_THUMB
+ - @ref GLFW_GAMEPAD_BUTTON_RIGHT_THUMB
+ - @ref GLFW_GAMEPAD_BUTTON_DPAD_UP
+ - @ref GLFW_GAMEPAD_BUTTON_DPAD_RIGHT
+ - @ref GLFW_GAMEPAD_BUTTON_DPAD_DOWN
+ - @ref GLFW_GAMEPAD_BUTTON_DPAD_LEFT
+ - @ref GLFW_GAMEPAD_BUTTON_LAST
+ - @ref GLFW_GAMEPAD_BUTTON_CROSS
+ - @ref GLFW_GAMEPAD_BUTTON_CIRCLE
+ - @ref GLFW_GAMEPAD_BUTTON_SQUARE
+ - @ref GLFW_GAMEPAD_BUTTON_TRIANGLE
+ - @ref GLFW_GAMEPAD_AXIS_LEFT_X
+ - @ref GLFW_GAMEPAD_AXIS_LEFT_Y
+ - @ref GLFW_GAMEPAD_AXIS_RIGHT_X
+ - @ref GLFW_GAMEPAD_AXIS_RIGHT_Y
+ - @ref GLFW_GAMEPAD_AXIS_LEFT_TRIGGER
+ - @ref GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER
+ - @ref GLFW_GAMEPAD_AXIS_LAST
+
+
+@section news_32 Release notes for 3.2
+
+These are the release notes for version 3.2.  For a more detailed view including
+all fixed bugs see the [version history](https://www.glfw.org/changelog.html).
+
+
+@subsection features_32 New features in version 3.2
+
+@subsubsection news_32_vulkan Support for Vulkan
+
+GLFW now supports basic integration with Vulkan with @ref glfwVulkanSupported,
+@ref glfwGetRequiredInstanceExtensions, @ref glfwGetInstanceProcAddress, @ref
+glfwGetPhysicalDevicePresentationSupport and @ref glfwCreateWindowSurface.
+Vulkan header inclusion can be selected with
+@ref GLFW_INCLUDE_VULKAN.
+
+
+@subsubsection news_32_setwindowmonitor Window mode switching
+
+GLFW now supports switching between windowed and full screen modes and updating
+the monitor and desired resolution and refresh rate of full screen windows with
+@ref glfwSetWindowMonitor.
+
+
+@subsubsection news_32_maximize Window maxmimization support
+
+GLFW now supports window maximization with @ref glfwMaximizeWindow and the
+@ref GLFW_MAXIMIZED window hint and attribute.
+
+
+@subsubsection news_32_focus Window input focus control
+
+GLFW now supports giving windows input focus with @ref glfwFocusWindow.
+
+
+@subsubsection news_32_sizelimits Window size limit support
+
+GLFW now supports setting both absolute and relative window size limits with
+@ref glfwSetWindowSizeLimits and @ref glfwSetWindowAspectRatio.
+
+
+@subsubsection news_32_keyname Localized key names
+
+GLFW now supports querying the localized name of printable keys with @ref
+glfwGetKeyName, either by key token or by scancode.
+
+
+@subsubsection news_32_waittimeout Wait for events with timeout
+
+GLFW now supports waiting for events for a set amount of time with @ref
+glfwWaitEventsTimeout.
+
+
+@subsubsection news_32_icon Window icon support
+
+GLFW now supports setting the icon of windows with @ref glfwSetWindowIcon.
+
+
+@subsubsection news_32_timer Raw timer access
+
+GLFW now supports raw timer values with @ref glfwGetTimerValue and @ref
+glfwGetTimerFrequency.
+
+
+@subsubsection news_32_joystick Joystick connection callback
+
+GLFW now supports notifying when a joystick has been connected or disconnected
+with @ref glfwSetJoystickCallback.
+
+
+@subsubsection news_32_noapi Context-less windows
+
+GLFW now supports creating windows without a OpenGL or OpenGL ES context by
+setting the [GLFW_CLIENT_API](@ref GLFW_CLIENT_API_hint) hint to `GLFW_NO_API`.
+
+
+@subsubsection news_32_contextapi Run-time context creation API selection
+
+GLFW now supports selecting and querying the context creation API at run-time
+with the @ref GLFW_CONTEXT_CREATION_API hint and attribute.
+
+
+@subsubsection news_32_noerror Error-free context creation
+
+GLFW now supports creating and querying OpenGL and OpenGL ES contexts that do
+not emit errors with the @ref GLFW_CONTEXT_NO_ERROR hint, provided the machine
+supports the `GL_KHR_no_error` extension.
+
+
+@subsubsection news_32_cmake CMake config-file package support
+
+GLFW now supports being used as a
+[config-file package](@ref build_link_cmake_package) from other projects for
+easy linking with the library and its dependencies.
+
+
+@section news_31 Release notes for 3.1
+
+These are the release notes for version 3.1.  For a more detailed view including
+all fixed bugs see the [version history](https://www.glfw.org/changelog.html).
+
+
+@subsection features_31 New features in version 3.1
+
+@subsubsection news_31_cursor Custom mouse cursor images
+
+GLFW now supports creating and setting both custom cursor images and standard
+cursor shapes.  They are created with @ref glfwCreateCursor or @ref
+glfwCreateStandardCursor, set with @ref glfwSetCursor and destroyed with @ref
+glfwDestroyCursor.
+
+@see @ref cursor_object
+
+
+@subsubsection news_31_drop Path drop event
+
+GLFW now provides a callback for receiving the paths of files and directories
+dropped onto GLFW windows.  The callback is set with @ref glfwSetDropCallback.
+
+@see @ref path_drop
+
+
+@subsubsection news_31_emptyevent Main thread wake-up
+
+GLFW now provides the @ref glfwPostEmptyEvent function for posting an empty
+event from another thread to the main thread event queue, causing @ref
+glfwWaitEvents to return.
+
+@see @ref events
+
+
+@subsubsection news_31_framesize Window frame size query
+
+GLFW now supports querying the size, on each side, of the frame around the
+content area of a window, with @ref glfwGetWindowFrameSize.
+
+@see [Window size](@ref window_size)
+
+
+@subsubsection news_31_autoiconify Simultaneous multi-monitor rendering
+
+GLFW now supports disabling auto-iconification of full screen windows with
+the [GLFW_AUTO_ICONIFY](@ref GLFW_AUTO_ICONIFY_hint) window hint.  This is
+intended for people building multi-monitor installations, where you need windows
+to stay in full screen despite losing input focus.
+
+
+@subsubsection news_31_floating Floating windows
+
+GLFW now supports floating windows, also called topmost or always on top, for
+easier debugging with the @ref GLFW_FLOATING window hint and attribute.
+
+
+@subsubsection news_31_focused Initially unfocused windows
+
+GLFW now supports preventing a windowed mode window from gaining input focus on
+creation, with the [GLFW_FOCUSED](@ref GLFW_FOCUSED_hint) window hint.
+
+
+@subsubsection news_31_direct Direct access for window attributes and cursor position
+
+GLFW now queries the window input focus, visibility and iconification attributes
+and the cursor position directly instead of returning cached data.
+
+
+@subsubsection news_31_charmods Character with modifiers callback
+
+GLFW now provides a callback for character events with modifier key bits.  The
+callback is set with @ref glfwSetCharModsCallback.  Unlike the regular character
+callback, this will report character events that will not result in a character
+being input, for example if the Control key is held down.
+
+@see @ref input_char
+
+
+@subsubsection news_31_single Single buffered framebuffers
+
+GLFW now supports the creation of single buffered windows, with the @ref
+GLFW_DOUBLEBUFFER hint.
+
+
+@subsubsection news_31_glext Macro for including extension header
+
+GLFW now includes the extension header appropriate for the chosen OpenGL or
+OpenGL ES header when @ref GLFW_INCLUDE_GLEXT is defined.  GLFW does not provide
+these headers.  They must be provided by your development environment or your
+OpenGL or OpenGL ES SDK.
+
+
+@subsubsection news_31_release Context release behaviors
+
+GLFW now supports controlling and querying whether the pipeline is flushed when
+a context is made non-current, with the @ref GLFW_CONTEXT_RELEASE_BEHAVIOR hint
+and attribute, provided the machine supports the `GL_KHR_context_flush_control`
+extension.
+
+
+@subsubsection news_31_wayland (Experimental) Wayland support
+
+GLFW now has an _experimental_ Wayland display protocol backend that can be
+selected on Linux with a CMake option.
+
+
+@subsubsection news_31_mir (Experimental) Mir support
+
+GLFW now has an _experimental_ Mir display server backend that can be selected
+on Linux with a CMake option.
+
+
+@section news_30 Release notes for 3.0
+
+These are the release notes for version 3.0.  For a more detailed view including
+all fixed bugs see the [version history](https://www.glfw.org/changelog.html).
+
+
+@subsection features_30 New features in version 3.0
+
+@subsubsection news_30_cmake CMake build system
+
+GLFW now uses the CMake build system instead of the various makefiles and
+project files used by earlier versions.  CMake is available for all platforms
+supported by GLFW, is present in most package systems and can generate
+makefiles and/or project files for most popular development environments.
+
+For more information on how to use CMake, see the
+[CMake manual](https://cmake.org/cmake/help/documentation.html).
+
+
+@subsubsection news_30_multiwnd Multi-window support
+
+GLFW now supports the creation of multiple windows, each with their own OpenGL
+or OpenGL ES context, and all window functions now take a window handle.  Event
+callbacks are now per-window and are provided with the handle of the window that
+received the event.  The @ref glfwMakeContextCurrent function has been added to
+select which context is current on a given thread.
+
+
+@subsubsection news_30_multimon Multi-monitor support
+
+GLFW now explicitly supports multiple monitors.  They can be enumerated with
+@ref glfwGetMonitors, queried with @ref glfwGetVideoModes, @ref
+glfwGetMonitorPos, @ref glfwGetMonitorName and @ref glfwGetMonitorPhysicalSize,
+and specified at window creation to make the newly created window full screen on
+that specific monitor.
+
+
+@subsubsection news_30_unicode Unicode support
+
+All string arguments to GLFW functions and all strings returned by GLFW now use
+the UTF-8 encoding.  This includes the window title, error string, clipboard
+text, monitor and joystick names as well as the extension function arguments (as
+ASCII is a subset of UTF-8).
+
+
+@subsubsection news_30_clipboard Clipboard text I/O
+
+GLFW now supports reading and writing plain text to and from the system
+clipboard, with the @ref glfwGetClipboardString and @ref glfwSetClipboardString
+functions.
+
+
+@subsubsection news_30_gamma Gamma ramp support
+
+GLFW now supports setting and reading back the gamma ramp of monitors, with the
+@ref glfwGetGammaRamp and @ref glfwSetGammaRamp functions.  There is also @ref
+glfwSetGamma, which generates a ramp from a gamma value and then sets it.
+
+
+@subsubsection news_30_gles OpenGL ES support
+
+GLFW now supports the creation of OpenGL ES contexts, by setting the
+[GLFW_CLIENT_API](@ref GLFW_CLIENT_API_hint) hint to `GLFW_OPENGL_ES_API`, where
+creation of such contexts are supported.  Note that GLFW _does not implement_
+OpenGL ES, so your driver must provide support in a way usable by GLFW.  Modern
+Nvidia and Intel drivers support creation of OpenGL ES context using the GLX and
+WGL APIs, while AMD provides an EGL implementation instead.
+
+
+@subsubsection news_30_egl (Experimental) EGL support
+
+GLFW now has an experimental EGL context creation back end that can be selected
+through CMake options.
+
+
+@subsubsection news_30_hidpi High-DPI support
+
+GLFW now supports high-DPI monitors on both Windows and macOS, giving windows
+full resolution framebuffers where other UI elements are scaled up.  To achieve
+this, @ref glfwGetFramebufferSize and @ref glfwSetFramebufferSizeCallback have
+been added.  These work with pixels, while the rest of the GLFW API works with
+screen coordinates.  This is important as OpenGL uses pixels, not screen
+coordinates.
+
+
+@subsubsection news_30_error Error callback
+
+GLFW now has an error callback, which can provide your application with much
+more detailed diagnostics than was previously possible.  The callback is passed
+an error code and a description string.
+
+
+@subsubsection news_30_wndptr Per-window user pointer
+
+Each window now has a user-defined pointer, retrieved with @ref
+glfwGetWindowUserPointer and set with @ref glfwSetWindowUserPointer, to make it
+easier to integrate GLFW into C++ code.
+
+
+@subsubsection news_30_iconifyfun Window iconification callback
+
+Each window now has a callback for iconification and restoration events,
+which is set with @ref glfwSetWindowIconifyCallback.
+
+
+@subsubsection news_30_wndposfun Window position callback
+
+Each window now has a callback for position events, which is set with @ref
+glfwSetWindowPosCallback.
+
+
+@subsubsection news_30_wndpos Window position query
+
+The position of a window can now be retrieved using @ref glfwGetWindowPos.
+
+
+@subsubsection news_30_focusfun Window focus callback
+
+Each windows now has a callback for focus events, which is set with @ref
+glfwSetWindowFocusCallback.
+
+
+@subsubsection news_30_enterleave Cursor enter/leave callback
+
+Each window now has a callback for when the mouse cursor enters or leaves its
+content area, which is set with @ref glfwSetCursorEnterCallback.
+
+
+@subsubsection news_30_wndtitle Initial window title
+
+The title of a window is now specified at creation time, as one of the arguments
+to @ref glfwCreateWindow.
+
+
+@subsubsection news_30_hidden Hidden windows
+
+Windows can now be hidden with @ref glfwHideWindow, shown using @ref
+glfwShowWindow and created initially hidden with the @ref GLFW_VISIBLE window
+hint and attribute.  This allows for off-screen rendering in a way compatible
+with most drivers, as well as moving a window to a specific position before
+showing it.
+
+
+@subsubsection news_30_undecorated Undecorated windows
+
+Windowed mode windows can now be created without decorations, e.g. things like
+a frame, a title bar, with the @ref GLFW_DECORATED window hint and attribute.
+This allows for the creation of things like splash screens.
+
+
+@subsubsection news_30_keymods Modifier key bit masks
+
+[Modifier key bit mask](@ref mods) parameters have been added to the
+[mouse button](@ref GLFWmousebuttonfun) and [key](@ref GLFWkeyfun) callbacks.
+
+
+@subsubsection news_30_scancode Platform-specific scancodes
+
+A scancode parameter has been added to the [key callback](@ref GLFWkeyfun). Keys
+that don't have a [key token](@ref keys) still get passed on with the key
+parameter set to `GLFW_KEY_UNKNOWN`.  These scancodes will vary between machines
+and are intended to be used for key bindings.
+
+
+@subsubsection news_30_jsname Joystick names
+
+The name of a joystick can now be retrieved using @ref glfwGetJoystickName.
+
+
+@subsubsection news_30_doxygen Doxygen documentation
+
+You are reading it.
+
+*/

+ 365 - 0
samples/third_party/glfw/docs/quick.dox

@@ -0,0 +1,365 @@
+/*!
+
+@page quick_guide Getting started
+
+@tableofcontents
+
+This guide takes you through writing a simple application using GLFW 3.  The
+application will create a window and OpenGL context, render a rotating triangle
+and exit when the user closes the window or presses _Escape_.  This guide will
+introduce a few of the most commonly used functions, but there are many more.
+
+This guide assumes no experience with earlier versions of GLFW.  If you
+have used GLFW 2 in the past, read @ref moving_guide, as some functions
+behave differently in GLFW 3.
+
+
+@section quick_steps Step by step
+
+@subsection quick_include Including the GLFW header
+
+In the source files of your application where you use GLFW, you need to include
+its header file.
+
+@code
+#include <GLFW/glfw3.h>
+@endcode
+
+This header provides all the constants, types and function prototypes of the
+GLFW API.
+
+By default it also includes the OpenGL header from your development environment.
+On some platforms this header only supports older versions of OpenGL.  The most
+extreme case is Windows, where it typically only supports OpenGL 1.2.
+
+Most programs will instead use an
+[extension loader library](@ref context_glext_auto) and include its header.
+This example uses files generated by [glad](https://gen.glad.sh/).  The GLFW
+header can detect most such headers if they are included first and will then not
+include the one from your development environment.
+
+@code
+#include <glad/gl.h>
+#include <GLFW/glfw3.h>
+@endcode
+
+To make sure there will be no header conflicts, you can define @ref
+GLFW_INCLUDE_NONE before the GLFW header to explicitly disable inclusion of the
+development environment header.  This also allows the two headers to be included
+in any order.
+
+@code
+#define GLFW_INCLUDE_NONE
+#include <GLFW/glfw3.h>
+#include <glad/gl.h>
+@endcode
+
+
+@subsection quick_init_term Initializing and terminating GLFW
+
+Before you can use most GLFW functions, the library must be initialized.  On
+successful initialization, `GLFW_TRUE` is returned.  If an error occurred,
+`GLFW_FALSE` is returned.
+
+@code
+if (!glfwInit())
+{
+    // Initialization failed
+}
+@endcode
+
+Note that `GLFW_TRUE` and `GLFW_FALSE` are and will always be one and zero.
+
+When you are done using GLFW, typically just before the application exits, you
+need to terminate GLFW.
+
+@code
+glfwTerminate();
+@endcode
+
+This destroys any remaining windows and releases any other resources allocated by
+GLFW.  After this call, you must initialize GLFW again before using any GLFW
+functions that require it.
+
+
+@subsection quick_capture_error Setting an error callback
+
+Most events are reported through callbacks, whether it's a key being pressed,
+a GLFW window being moved, or an error occurring.  Callbacks are C functions (or
+C++ static methods) that are called by GLFW with arguments describing the event.
+
+In case a GLFW function fails, an error is reported to the GLFW error callback.
+You can receive these reports with an error callback.  This function must have
+the signature below but may do anything permitted in other callbacks.
+
+@code
+void error_callback(int error, const char* description)
+{
+    fprintf(stderr, "Error: %s\n", description);
+}
+@endcode
+
+Callback functions must be set, so GLFW knows to call them.  The function to set
+the error callback is one of the few GLFW functions that may be called before
+initialization, which lets you be notified of errors both during and after
+initialization.
+
+@code
+glfwSetErrorCallback(error_callback);
+@endcode
+
+
+@subsection quick_create_window Creating a window and context
+
+The window and its OpenGL context are created with a single call to @ref
+glfwCreateWindow, which returns a handle to the created combined window and
+context object
+
+@code
+GLFWwindow* window = glfwCreateWindow(640, 480, "My Title", NULL, NULL);
+if (!window)
+{
+    // Window or OpenGL context creation failed
+}
+@endcode
+
+This creates a 640 by 480 windowed mode window with an OpenGL context.  If
+window or OpenGL context creation fails, `NULL` will be returned.  You should
+always check the return value.  While window creation rarely fails, context
+creation depends on properly installed drivers and may fail even on machines
+with the necessary hardware.
+
+By default, the OpenGL context GLFW creates may have any version.  You can
+require a minimum OpenGL version by setting the `GLFW_CONTEXT_VERSION_MAJOR` and
+`GLFW_CONTEXT_VERSION_MINOR` hints _before_ creation.  If the required minimum
+version is not supported on the machine, context (and window) creation fails.
+
+@code
+glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
+glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
+GLFWwindow* window = glfwCreateWindow(640, 480, "My Title", NULL, NULL);
+if (!window)
+{
+    // Window or context creation failed
+}
+@endcode
+
+The window handle is passed to all window related functions and is provided to
+along to all window related callbacks, so they can tell which window received
+the event.
+
+When a window and context is no longer needed, destroy it.
+
+@code
+glfwDestroyWindow(window);
+@endcode
+
+Once this function is called, no more events will be delivered for that window
+and its handle becomes invalid.
+
+
+@subsection quick_context_current Making the OpenGL context current
+
+Before you can use the OpenGL API, you must have a current OpenGL context.
+
+@code
+glfwMakeContextCurrent(window);
+@endcode
+
+The context will remain current until you make another context current or until
+the window owning the current context is destroyed.
+
+If you are using an [extension loader library](@ref context_glext_auto) to
+access modern OpenGL then this is when to initialize it, as the loader needs
+a current context to load from.  This example uses
+[glad](https://github.com/Dav1dde/glad), but the same rule applies to all such
+libraries.
+
+@code
+gladLoadGL(glfwGetProcAddress);
+@endcode
+
+
+@subsection quick_window_close Checking the window close flag
+
+Each window has a flag indicating whether the window should be closed.
+
+When the user attempts to close the window, either by pressing the close widget
+in the title bar or using a key combination like Alt+F4, this flag is set to 1.
+Note that __the window isn't actually closed__, so you are expected to monitor
+this flag and either destroy the window or give some kind of feedback to the
+user.
+
+@code
+while (!glfwWindowShouldClose(window))
+{
+    // Keep running
+}
+@endcode
+
+You can be notified when the user is attempting to close the window by setting
+a close callback with @ref glfwSetWindowCloseCallback.  The callback will be
+called immediately after the close flag has been set.
+
+You can also set it yourself with @ref glfwSetWindowShouldClose.  This can be
+useful if you want to interpret other kinds of input as closing the window, like
+for example pressing the _Escape_ key.
+
+
+@subsection quick_key_input Receiving input events
+
+Each window has a large number of callbacks that can be set to receive all the
+various kinds of events.  To receive key press and release events, create a key
+callback function.
+
+@code
+static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
+{
+    if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
+        glfwSetWindowShouldClose(window, GLFW_TRUE);
+}
+@endcode
+
+The key callback, like other window related callbacks, are set per-window.
+
+@code
+glfwSetKeyCallback(window, key_callback);
+@endcode
+
+In order for event callbacks to be called when events occur, you need to process
+events as described below.
+
+
+@subsection quick_render Rendering with OpenGL
+
+Once you have a current OpenGL context, you can use OpenGL normally.  In this
+tutorial, a multi-colored rotating triangle will be rendered.  The framebuffer
+size needs to be retrieved for `glViewport`.
+
+@code
+int width, height;
+glfwGetFramebufferSize(window, &width, &height);
+glViewport(0, 0, width, height);
+@endcode
+
+You can also set a framebuffer size callback using @ref
+glfwSetFramebufferSizeCallback and be notified when the size changes.
+
+The details of how to render with OpenGL is outside the scope of this tutorial,
+but there are many excellent resources for learning modern OpenGL.  Here are
+a few of them:
+
+ - [Anton's OpenGL 4 Tutorials](https://antongerdelan.net/opengl/)
+ - [Learn OpenGL](https://learnopengl.com/)
+ - [Open.GL](https://open.gl/)
+
+These all happen to use GLFW, but OpenGL itself works the same whatever API you
+use to create the window and context.
+
+
+@subsection quick_timer Reading the timer
+
+To create smooth animation, a time source is needed.  GLFW provides a timer that
+returns the number of seconds since initialization.  The time source used is the
+most accurate on each platform and generally has micro- or nanosecond
+resolution.
+
+@code
+double time = glfwGetTime();
+@endcode
+
+
+@subsection quick_swap_buffers Swapping buffers
+
+GLFW windows by default use double buffering.  That means that each window has
+two rendering buffers; a front buffer and a back buffer.  The front buffer is
+the one being displayed and the back buffer the one you render to.
+
+When the entire frame has been rendered, the buffers need to be swapped with one
+another, so the back buffer becomes the front buffer and vice versa.
+
+@code
+glfwSwapBuffers(window);
+@endcode
+
+The swap interval indicates how many frames to wait until swapping the buffers,
+commonly known as _vsync_.  By default, the swap interval is zero, meaning
+buffer swapping will occur immediately.  On fast machines, many of those frames
+will never be seen, as the screen is still only updated typically 60-75 times
+per second, so this wastes a lot of CPU and GPU cycles.
+
+Also, because the buffers will be swapped in the middle the screen update,
+leading to [screen tearing](https://en.wikipedia.org/wiki/Screen_tearing).
+
+For these reasons, applications will typically want to set the swap interval to
+one.  It can be set to higher values, but this is usually not recommended,
+because of the input latency it leads to.
+
+@code
+glfwSwapInterval(1);
+@endcode
+
+This function acts on the current context and will fail unless a context is
+current.
+
+
+@subsection quick_process_events Processing events
+
+GLFW needs to communicate regularly with the window system both in order to
+receive events and to show that the application hasn't locked up.  Event
+processing must be done regularly while you have visible windows and is normally
+done each frame after buffer swapping.
+
+There are two methods for processing pending events; polling and waiting.  This
+example will use event polling, which processes only those events that have
+already been received and then returns immediately.
+
+@code
+glfwPollEvents();
+@endcode
+
+This is the best choice when rendering continually, like most games do.  If
+instead you only need to update your rendering once you have received new input,
+@ref glfwWaitEvents is a better choice.  It waits until at least one event has
+been received, putting the thread to sleep in the meantime, and then processes
+all received events.  This saves a great deal of CPU cycles and is useful for,
+for example, many kinds of editing tools.
+
+
+@section quick_example Putting it together
+
+Now that you know how to initialize GLFW, create a window and poll for
+keyboard input, it's possible to create a simple program.
+
+This program creates a 640 by 480 windowed mode window and starts a loop that
+clears the screen, renders a triangle and processes events until the user either
+presses _Escape_ or closes the window.
+
+@snippet simple.c code
+
+The program above can be found in the
+[source package](https://www.glfw.org/download.html) as `examples/simple.c`
+and is compiled along with all other examples when you build GLFW.  If you
+built GLFW from the source package then you already have this as `simple.exe` on
+Windows, `simple` on Linux or `simple.app` on macOS.
+
+This tutorial used only a few of the many functions GLFW provides.  There are
+guides for each of the areas covered by GLFW.  Each guide will introduce all the
+functions for that category.
+
+ - @ref intro_guide
+ - @ref window_guide
+ - @ref context_guide
+ - @ref monitor_guide
+ - @ref input_guide
+
+You can access reference documentation for any GLFW function by clicking it and
+the reference for each function links to related functions and guide sections.
+
+The tutorial ends here.  Once you have written a program that uses GLFW, you
+will need to compile and link it.  How to do that depends on the development
+environment you are using and is best explained by the documentation for that
+environment.  To learn about the details that are specific to GLFW, see
+@ref build_guide.
+
+*/

ファイルの差分が大きいため隠しています
+ 877 - 0
samples/third_party/glfw/docs/spaces.svg


+ 235 - 0
samples/third_party/glfw/docs/vulkan.dox

@@ -0,0 +1,235 @@
+/*!
+
+@page vulkan_guide Vulkan guide
+
+@tableofcontents
+
+This guide is intended to fill the gaps between the official [Vulkan
+resources](https://www.khronos.org/vulkan/) and the rest of the GLFW
+documentation and is not a replacement for either.  It assumes some familiarity
+with Vulkan concepts like loaders, devices, queues and surfaces and leaves it to
+the Vulkan documentation to explain the details of Vulkan functions.
+
+To develop for Vulkan you should download the [LunarG Vulkan
+SDK](https://vulkan.lunarg.com/) for your platform.  Apart from headers and link
+libraries, they also provide the validation layers necessary for development.
+
+The [Vulkan Tutorial](https://vulkan-tutorial.com/) has more information on how
+to use GLFW and Vulkan.  The [Khronos Vulkan
+Samples](https://github.com/KhronosGroup/Vulkan-Samples) also use GLFW, although
+with a small framework in between.
+
+For details on a specific Vulkan support function, see the @ref vulkan.  There
+are also guides for the other areas of the GLFW API.
+
+ - @ref intro_guide
+ - @ref window_guide
+ - @ref context_guide
+ - @ref monitor_guide
+ - @ref input_guide
+
+
+@section vulkan_loader Linking against the Vulkan loader
+
+By default, GLFW will look for the Vulkan loader on demand at runtime via its
+standard name (`vulkan-1.dll` on Windows, `libvulkan.so.1` on Linux and other
+Unix-like systems and `libvulkan.1.dylib` on macOS).  This means that GLFW does
+not need to be linked against the loader.  However, it also means that if you
+are using the static library form of the Vulkan loader GLFW will either fail to
+find it or (worse) use the wrong one.
+
+The @ref GLFW_VULKAN_STATIC CMake option makes GLFW call the Vulkan loader
+directly instead of dynamically loading it at runtime.  Not linking against the
+Vulkan loader will then be a compile-time error.
+
+@macos Because the Vulkan loader and ICD are not installed globally on macOS,
+you need to set up the application bundle according to the LunarG SDK
+documentation.  This is explained in more detail in the
+[SDK documentation for macOS](https://vulkan.lunarg.com/doc/sdk/latest/mac/getting_started.html).
+
+
+@section vulkan_include Including the Vulkan and GLFW header files
+
+To include the Vulkan header, define @ref GLFW_INCLUDE_VULKAN before including
+the GLFW header.
+
+@code
+#define GLFW_INCLUDE_VULKAN
+#include <GLFW/glfw3.h>
+@endcode
+
+If you instead want to include the Vulkan header from a custom location or use
+your own custom Vulkan header then do this before the GLFW header.
+
+@code
+#include <path/to/vulkan.h>
+#include <GLFW/glfw3.h>
+@endcode
+
+Unless a Vulkan header is included, either by the GLFW header or above it, any
+GLFW functions that take or return Vulkan types will not be declared.
+
+The `VK_USE_PLATFORM_*_KHR` macros do not need to be defined for the Vulkan part
+of GLFW to work.  Define them only if you are using these extensions directly.
+
+
+@section vulkan_support Querying for Vulkan support
+
+If you are linking directly against the Vulkan loader then you can skip this
+section.  The canonical desktop loader library exports all Vulkan core and
+Khronos extension functions, allowing them to be called directly.
+
+If you are loading the Vulkan loader dynamically instead of linking directly
+against it, you can check for the availability of a loader and ICD with @ref
+glfwVulkanSupported.
+
+@code
+if (glfwVulkanSupported())
+{
+    // Vulkan is available, at least for compute
+}
+@endcode
+
+This function returns `GLFW_TRUE` if the Vulkan loader and any minimally
+functional ICD was found.
+
+If one or both were not found, calling any other Vulkan related GLFW function
+will generate a @ref GLFW_API_UNAVAILABLE error.
+
+
+@subsection vulkan_proc Querying Vulkan function pointers
+
+To load any Vulkan core or extension function from the found loader, call @ref
+glfwGetInstanceProcAddress.  To load functions needed for instance creation,
+pass `NULL` as the instance.
+
+@code
+PFN_vkCreateInstance pfnCreateInstance = (PFN_vkCreateInstance)
+    glfwGetInstanceProcAddress(NULL, "vkCreateInstance");
+@endcode
+
+Once you have created an instance, you can load from it all other Vulkan core
+functions and functions from any instance extensions you enabled.
+
+@code
+PFN_vkCreateDevice pfnCreateDevice = (PFN_vkCreateDevice)
+    glfwGetInstanceProcAddress(instance, "vkCreateDevice");
+@endcode
+
+This function in turn calls `vkGetInstanceProcAddr`.  If that fails, the
+function falls back to a platform-specific query of the Vulkan loader (i.e.
+`dlsym` or `GetProcAddress`).  If that also fails, the function returns `NULL`.
+For more information about `vkGetInstanceProcAddr`, see the Vulkan
+documentation.
+
+Vulkan also provides `vkGetDeviceProcAddr` for loading device-specific versions
+of Vulkan function.  This function can be retrieved from an instance with @ref
+glfwGetInstanceProcAddress.
+
+@code
+PFN_vkGetDeviceProcAddr pfnGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)
+    glfwGetInstanceProcAddress(instance, "vkGetDeviceProcAddr");
+@endcode
+
+Device-specific functions may execute a little bit faster, due to not having to
+dispatch internally based on the device passed to them.  For more information
+about `vkGetDeviceProcAddr`, see the Vulkan documentation.
+
+
+@section vulkan_ext Querying required Vulkan extensions
+
+To do anything useful with Vulkan you need to create an instance.  If you want
+to use Vulkan to render to a window, you must enable the instance extensions
+GLFW requires to create Vulkan surfaces.
+
+To query the instance extensions required, call @ref
+glfwGetRequiredInstanceExtensions.
+
+@code
+uint32_t count;
+const char** extensions = glfwGetRequiredInstanceExtensions(&count);
+@endcode
+
+These extensions must all be enabled when creating instances that are going to
+be passed to @ref glfwGetPhysicalDevicePresentationSupport and @ref
+glfwCreateWindowSurface.  The set of extensions will vary depending on platform
+and may also vary depending on graphics drivers and other factors.
+
+If it fails it will return `NULL` and GLFW will not be able to create Vulkan
+window surfaces.  You can still use Vulkan for off-screen rendering and compute
+work.
+
+If successful the returned array will always include `VK_KHR_surface`, so if
+you don't require any additional extensions you can pass this list directly to
+the `VkInstanceCreateInfo` struct.
+
+@code
+VkInstanceCreateInfo ici;
+
+memset(&ici, 0, sizeof(ici));
+ici.enabledExtensionCount = count;
+ici.ppEnabledExtensionNames = extensions;
+...
+@endcode
+
+Additional extensions may be required by future versions of GLFW.  You should
+check whether any extensions you wish to enable are already in the returned
+array, as it is an error to specify an extension more than once in the
+`VkInstanceCreateInfo` struct.
+
+
+@section vulkan_present Querying for Vulkan presentation support
+
+Not every queue family of every Vulkan device can present images to surfaces.
+To check whether a specific queue family of a physical device supports image
+presentation without first having to create a window and surface, call @ref
+glfwGetPhysicalDevicePresentationSupport.
+
+@code
+if (glfwGetPhysicalDevicePresentationSupport(instance, physical_device, queue_family_index))
+{
+    // Queue family supports image presentation
+}
+@endcode
+
+The `VK_KHR_surface` extension additionally provides the
+`vkGetPhysicalDeviceSurfaceSupportKHR` function, which performs the same test on
+an existing Vulkan surface.
+
+
+@section vulkan_window Creating the window
+
+Unless you will be using OpenGL or OpenGL ES with the same window as Vulkan,
+there is no need to create a context.  You can disable context creation with the
+[GLFW_CLIENT_API](@ref GLFW_CLIENT_API_hint) hint.
+
+@code
+glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
+GLFWwindow* window = glfwCreateWindow(640, 480, "Window Title", NULL, NULL);
+@endcode
+
+See @ref context_less for more information.
+
+
+@section vulkan_surface Creating a Vulkan window surface
+
+You can create a Vulkan surface (as defined by the `VK_KHR_surface` extension)
+for a GLFW window with @ref glfwCreateWindowSurface.
+
+@code
+VkSurfaceKHR surface;
+VkResult err = glfwCreateWindowSurface(instance, window, NULL, &surface);
+if (err)
+{
+    // Window surface creation failed
+}
+@endcode
+
+If an OpenGL or OpenGL ES context was created on the window, the context has
+ownership of the presentation on the window and a Vulkan surface cannot be
+created.
+
+It is your responsibility to destroy the surface.  GLFW does not destroy it for
+you.  Call `vkDestroySurfaceKHR` function from the same extension to destroy it.
+
+*/

ファイルの差分が大きいため隠しています
+ 1412 - 0
samples/third_party/glfw/docs/window.dox


+ 93 - 0
samples/third_party/glfw/examples/CMakeLists.txt

@@ -0,0 +1,93 @@
+
+link_libraries(glfw)
+
+include_directories("${GLFW_SOURCE_DIR}/deps")
+
+if (MATH_LIBRARY)
+    link_libraries("${MATH_LIBRARY}")
+endif()
+
+# Workaround for the MS CRT deprecating parts of the standard library
+if (MSVC OR CMAKE_C_SIMULATE_ID STREQUAL "MSVC")
+    add_definitions(-D_CRT_SECURE_NO_WARNINGS)
+endif()
+
+if (WIN32)
+    set(ICON glfw.rc)
+elseif (APPLE)
+    set(ICON glfw.icns)
+endif()
+
+if (${CMAKE_VERSION} VERSION_EQUAL "3.1.0" OR
+    ${CMAKE_VERSION} VERSION_GREATER "3.1.0")
+    set(CMAKE_C_STANDARD 99)
+else()
+    # Remove this fallback when removing support for CMake version less than 3.1
+    add_compile_options("$<$<C_COMPILER_ID:AppleClang>:-std=c99>"
+                        "$<$<C_COMPILER_ID:Clang>:-std=c99>"
+                        "$<$<C_COMPILER_ID:GNU>:-std=c99>")
+
+endif()
+
+set(GLAD_GL "${GLFW_SOURCE_DIR}/deps/glad/gl.h"
+            "${GLFW_SOURCE_DIR}/deps/glad_gl.c")
+set(GETOPT "${GLFW_SOURCE_DIR}/deps/getopt.h"
+           "${GLFW_SOURCE_DIR}/deps/getopt.c")
+set(TINYCTHREAD "${GLFW_SOURCE_DIR}/deps/tinycthread.h"
+                "${GLFW_SOURCE_DIR}/deps/tinycthread.c")
+
+add_executable(boing WIN32 MACOSX_BUNDLE boing.c ${ICON} ${GLAD_GL})
+add_executable(gears WIN32 MACOSX_BUNDLE gears.c ${ICON} ${GLAD_GL})
+add_executable(heightmap WIN32 MACOSX_BUNDLE heightmap.c ${ICON} ${GLAD_GL})
+add_executable(offscreen offscreen.c ${ICON} ${GLAD_GL})
+add_executable(particles WIN32 MACOSX_BUNDLE particles.c ${ICON} ${TINYCTHREAD} ${GETOPT} ${GLAD_GL})
+add_executable(sharing WIN32 MACOSX_BUNDLE sharing.c ${ICON} ${GLAD_GL})
+add_executable(simple WIN32 MACOSX_BUNDLE simple.c ${ICON} ${GLAD_GL})
+add_executable(splitview WIN32 MACOSX_BUNDLE splitview.c ${ICON} ${GLAD_GL})
+add_executable(wave WIN32 MACOSX_BUNDLE wave.c ${ICON} ${GLAD_GL})
+
+target_link_libraries(particles "${CMAKE_THREAD_LIBS_INIT}")
+if (RT_LIBRARY)
+    target_link_libraries(particles "${RT_LIBRARY}")
+endif()
+
+set(GUI_ONLY_BINARIES boing gears heightmap particles sharing simple splitview
+    wave)
+set(CONSOLE_BINARIES offscreen)
+
+set_target_properties(${GUI_ONLY_BINARIES} ${CONSOLE_BINARIES} PROPERTIES
+                      FOLDER "GLFW3/Examples")
+
+if (GLFW_USE_OSMESA)
+    target_compile_definitions(offscreen PRIVATE USE_NATIVE_OSMESA)
+endif()
+
+if (MSVC)
+    # Tell MSVC to use main instead of WinMain
+    set_target_properties(${GUI_ONLY_BINARIES} PROPERTIES
+                          LINK_FLAGS "/ENTRY:mainCRTStartup")
+elseif (CMAKE_C_SIMULATE_ID STREQUAL "MSVC")
+    # Tell Clang using MS CRT to use main instead of WinMain
+    set_target_properties(${GUI_ONLY_BINARIES} PROPERTIES
+                          LINK_FLAGS "-Wl,/entry:mainCRTStartup")
+endif()
+
+if (APPLE)
+    set_target_properties(boing PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Boing")
+    set_target_properties(gears PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Gears")
+    set_target_properties(heightmap PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Heightmap")
+    set_target_properties(particles PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Particles")
+    set_target_properties(sharing PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Sharing")
+    set_target_properties(simple PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Simple")
+    set_target_properties(splitview PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "SplitView")
+    set_target_properties(wave PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Wave")
+
+    set_source_files_properties(glfw.icns PROPERTIES
+                                MACOSX_PACKAGE_LOCATION "Resources")
+    set_target_properties(${GUI_ONLY_BINARIES} PROPERTIES
+                          MACOSX_BUNDLE_SHORT_VERSION_STRING ${GLFW_VERSION}
+                          MACOSX_BUNDLE_LONG_VERSION_STRING ${GLFW_VERSION}
+                          MACOSX_BUNDLE_ICON_FILE glfw.icns
+                          MACOSX_BUNDLE_INFO_PLIST "${GLFW_SOURCE_DIR}/CMake/MacOSXBundleInfo.plist.in")
+endif()
+

+ 679 - 0
samples/third_party/glfw/examples/boing.c

@@ -0,0 +1,679 @@
+/*****************************************************************************
+ * Title:   GLBoing
+ * Desc:    Tribute to Amiga Boing.
+ * Author:  Jim Brooks  <gfx@jimbrooks.org>
+ *          Original Amiga authors were R.J. Mical and Dale Luck.
+ *          GLFW conversion by Marcus Geelnard
+ * Notes:   - 360' = 2*PI [radian]
+ *
+ *          - Distances between objects are created by doing a relative
+ *            Z translations.
+ *
+ *          - Although OpenGL enticingly supports alpha-blending,
+ *            the shadow of the original Boing didn't affect the color
+ *            of the grid.
+ *
+ *          - [Marcus] Changed timing scheme from interval driven to frame-
+ *            time based animation steps (which results in much smoother
+ *            movement)
+ *
+ * History of Amiga Boing:
+ *
+ * Boing was demonstrated on the prototype Amiga (codenamed "Lorraine") in
+ * 1985. According to legend, it was written ad-hoc in one night by
+ * R. J. Mical and Dale Luck. Because the bouncing ball animation was so fast
+ * and smooth, attendees did not believe the Amiga prototype was really doing
+ * the rendering. Suspecting a trick, they began looking around the booth for
+ * a hidden computer or VCR.
+ *****************************************************************************/
+
+#if defined(_MSC_VER)
+ // Make MS math.h define M_PI
+ #define _USE_MATH_DEFINES
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include <glad/gl.h>
+#define GLFW_INCLUDE_NONE
+#include <GLFW/glfw3.h>
+
+#include <linmath.h>
+
+
+/*****************************************************************************
+ * Various declarations and macros
+ *****************************************************************************/
+
+/* Prototypes */
+void init( void );
+void display( void );
+void reshape( GLFWwindow* window, int w, int h );
+void key_callback( GLFWwindow* window, int key, int scancode, int action, int mods );
+void mouse_button_callback( GLFWwindow* window, int button, int action, int mods );
+void cursor_position_callback( GLFWwindow* window, double x, double y );
+void DrawBoingBall( void );
+void BounceBall( double dt );
+void DrawBoingBallBand( GLfloat long_lo, GLfloat long_hi );
+void DrawGrid( void );
+
+#define RADIUS           70.f
+#define STEP_LONGITUDE   22.5f                   /* 22.5 makes 8 bands like original Boing */
+#define STEP_LATITUDE    22.5f
+
+#define DIST_BALL       (RADIUS * 2.f + RADIUS * 0.1f)
+
+#define VIEW_SCENE_DIST (DIST_BALL * 3.f + 200.f)/* distance from viewer to middle of boing area */
+#define GRID_SIZE       (RADIUS * 4.5f)          /* length (width) of grid */
+#define BOUNCE_HEIGHT   (RADIUS * 2.1f)
+#define BOUNCE_WIDTH    (RADIUS * 2.1f)
+
+#define SHADOW_OFFSET_X -20.f
+#define SHADOW_OFFSET_Y  10.f
+#define SHADOW_OFFSET_Z   0.f
+
+#define WALL_L_OFFSET   0.f
+#define WALL_R_OFFSET   5.f
+
+/* Animation speed (50.0 mimics the original GLUT demo speed) */
+#define ANIMATION_SPEED 50.f
+
+/* Maximum allowed delta time per physics iteration */
+#define MAX_DELTA_T 0.02f
+
+/* Draw ball, or its shadow */
+typedef enum { DRAW_BALL, DRAW_BALL_SHADOW } DRAW_BALL_ENUM;
+
+/* Vertex type */
+typedef struct {float x; float y; float z;} vertex_t;
+
+/* Global vars */
+int windowed_xpos, windowed_ypos, windowed_width, windowed_height;
+int width, height;
+GLfloat deg_rot_y       = 0.f;
+GLfloat deg_rot_y_inc   = 2.f;
+int override_pos        = GLFW_FALSE;
+GLfloat cursor_x        = 0.f;
+GLfloat cursor_y        = 0.f;
+GLfloat ball_x          = -RADIUS;
+GLfloat ball_y          = -RADIUS;
+GLfloat ball_x_inc      = 1.f;
+GLfloat ball_y_inc      = 2.f;
+DRAW_BALL_ENUM drawBallHow;
+double  t;
+double  t_old = 0.f;
+double  dt;
+
+/* Random number generator */
+#ifndef RAND_MAX
+ #define RAND_MAX 4095
+#endif
+
+
+/*****************************************************************************
+ * Truncate a degree.
+ *****************************************************************************/
+GLfloat TruncateDeg( GLfloat deg )
+{
+   if ( deg >= 360.f )
+      return (deg - 360.f);
+   else
+      return deg;
+}
+
+/*****************************************************************************
+ * Convert a degree (360-based) into a radian.
+ * 360' = 2 * PI
+ *****************************************************************************/
+double deg2rad( double deg )
+{
+   return deg / 360 * (2 * M_PI);
+}
+
+/*****************************************************************************
+ * 360' sin().
+ *****************************************************************************/
+double sin_deg( double deg )
+{
+   return sin( deg2rad( deg ) );
+}
+
+/*****************************************************************************
+ * 360' cos().
+ *****************************************************************************/
+double cos_deg( double deg )
+{
+   return cos( deg2rad( deg ) );
+}
+
+/*****************************************************************************
+ * Compute a cross product (for a normal vector).
+ *
+ * c = a x b
+ *****************************************************************************/
+void CrossProduct( vertex_t a, vertex_t b, vertex_t c, vertex_t *n )
+{
+   GLfloat u1, u2, u3;
+   GLfloat v1, v2, v3;
+
+   u1 = b.x - a.x;
+   u2 = b.y - a.y;
+   u3 = b.y - a.z;
+
+   v1 = c.x - a.x;
+   v2 = c.y - a.y;
+   v3 = c.z - a.z;
+
+   n->x = u2 * v3 - v2 * u3;
+   n->y = u3 * v1 - v3 * u1;
+   n->z = u1 * v2 - v1 * u2;
+}
+
+
+#define BOING_DEBUG 0
+
+
+/*****************************************************************************
+ * init()
+ *****************************************************************************/
+void init( void )
+{
+   /*
+    * Clear background.
+    */
+   glClearColor( 0.55f, 0.55f, 0.55f, 0.f );
+
+   glShadeModel( GL_FLAT );
+}
+
+
+/*****************************************************************************
+ * display()
+ *****************************************************************************/
+void display(void)
+{
+   glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+   glPushMatrix();
+
+   drawBallHow = DRAW_BALL_SHADOW;
+   DrawBoingBall();
+
+   DrawGrid();
+
+   drawBallHow = DRAW_BALL;
+   DrawBoingBall();
+
+   glPopMatrix();
+   glFlush();
+}
+
+
+/*****************************************************************************
+ * reshape()
+ *****************************************************************************/
+void reshape( GLFWwindow* window, int w, int h )
+{
+   mat4x4 projection, view;
+
+   glViewport( 0, 0, (GLsizei)w, (GLsizei)h );
+
+   glMatrixMode( GL_PROJECTION );
+   mat4x4_perspective( projection,
+                       2.f * (float) atan2( RADIUS, 200.f ),
+                       (float)w / (float)h,
+                       1.f, VIEW_SCENE_DIST );
+   glLoadMatrixf((const GLfloat*) projection);
+
+   glMatrixMode( GL_MODELVIEW );
+   {
+      vec3 eye = { 0.f, 0.f, VIEW_SCENE_DIST };
+      vec3 center = { 0.f, 0.f, 0.f };
+      vec3 up = { 0.f, -1.f, 0.f };
+      mat4x4_look_at( view, eye, center, up );
+   }
+   glLoadMatrixf((const GLfloat*) view);
+}
+
+void key_callback( GLFWwindow* window, int key, int scancode, int action, int mods )
+{
+    if (action != GLFW_PRESS)
+        return;
+
+    if (key == GLFW_KEY_ESCAPE && mods == 0)
+        glfwSetWindowShouldClose(window, GLFW_TRUE);
+    if ((key == GLFW_KEY_ENTER && mods == GLFW_MOD_ALT) ||
+        (key == GLFW_KEY_F11 && mods == GLFW_MOD_ALT))
+    {
+        if (glfwGetWindowMonitor(window))
+        {
+            glfwSetWindowMonitor(window, NULL,
+                                 windowed_xpos, windowed_ypos,
+                                 windowed_width, windowed_height, 0);
+        }
+        else
+        {
+            GLFWmonitor* monitor = glfwGetPrimaryMonitor();
+            if (monitor)
+            {
+                const GLFWvidmode* mode = glfwGetVideoMode(monitor);
+                glfwGetWindowPos(window, &windowed_xpos, &windowed_ypos);
+                glfwGetWindowSize(window, &windowed_width, &windowed_height);
+                glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height, mode->refreshRate);
+            }
+        }
+    }
+}
+
+static void set_ball_pos ( GLfloat x, GLfloat y )
+{
+   ball_x = (width / 2) - x;
+   ball_y = y - (height / 2);
+}
+
+void mouse_button_callback( GLFWwindow* window, int button, int action, int mods )
+{
+   if (button != GLFW_MOUSE_BUTTON_LEFT)
+      return;
+
+   if (action == GLFW_PRESS)
+   {
+      override_pos = GLFW_TRUE;
+      set_ball_pos(cursor_x, cursor_y);
+   }
+   else
+   {
+      override_pos = GLFW_FALSE;
+   }
+}
+
+void cursor_position_callback( GLFWwindow* window, double x, double y )
+{
+   cursor_x = (float) x;
+   cursor_y = (float) y;
+
+   if ( override_pos )
+      set_ball_pos(cursor_x, cursor_y);
+}
+
+/*****************************************************************************
+ * Draw the Boing ball.
+ *
+ * The Boing ball is sphere in which each facet is a rectangle.
+ * Facet colors alternate between red and white.
+ * The ball is built by stacking latitudinal circles.  Each circle is composed
+ * of a widely-separated set of points, so that each facet is noticeably large.
+ *****************************************************************************/
+void DrawBoingBall( void )
+{
+   GLfloat lon_deg;     /* degree of longitude */
+   double dt_total, dt2;
+
+   glPushMatrix();
+   glMatrixMode( GL_MODELVIEW );
+
+  /*
+   * Another relative Z translation to separate objects.
+   */
+   glTranslatef( 0.0, 0.0, DIST_BALL );
+
+   /* Update ball position and rotation (iterate if necessary) */
+   dt_total = dt;
+   while( dt_total > 0.0 )
+   {
+       dt2 = dt_total > MAX_DELTA_T ? MAX_DELTA_T : dt_total;
+       dt_total -= dt2;
+       BounceBall( dt2 );
+       deg_rot_y = TruncateDeg( deg_rot_y + deg_rot_y_inc*((float)dt2*ANIMATION_SPEED) );
+   }
+
+   /* Set ball position */
+   glTranslatef( ball_x, ball_y, 0.0 );
+
+  /*
+   * Offset the shadow.
+   */
+   if ( drawBallHow == DRAW_BALL_SHADOW )
+   {
+      glTranslatef( SHADOW_OFFSET_X,
+                    SHADOW_OFFSET_Y,
+                    SHADOW_OFFSET_Z );
+   }
+
+  /*
+   * Tilt the ball.
+   */
+   glRotatef( -20.0, 0.0, 0.0, 1.0 );
+
+  /*
+   * Continually rotate ball around Y axis.
+   */
+   glRotatef( deg_rot_y, 0.0, 1.0, 0.0 );
+
+  /*
+   * Set OpenGL state for Boing ball.
+   */
+   glCullFace( GL_FRONT );
+   glEnable( GL_CULL_FACE );
+   glEnable( GL_NORMALIZE );
+
+  /*
+   * Build a faceted latitude slice of the Boing ball,
+   * stepping same-sized vertical bands of the sphere.
+   */
+   for ( lon_deg = 0;
+         lon_deg < 180;
+         lon_deg += STEP_LONGITUDE )
+   {
+     /*
+      * Draw a latitude circle at this longitude.
+      */
+      DrawBoingBallBand( lon_deg,
+                         lon_deg + STEP_LONGITUDE );
+   }
+
+   glPopMatrix();
+
+   return;
+}
+
+
+/*****************************************************************************
+ * Bounce the ball.
+ *****************************************************************************/
+void BounceBall( double delta_t )
+{
+   GLfloat sign;
+   GLfloat deg;
+
+   if ( override_pos )
+     return;
+
+   /* Bounce on walls */
+   if ( ball_x >  (BOUNCE_WIDTH/2 + WALL_R_OFFSET ) )
+   {
+      ball_x_inc = -0.5f - 0.75f * (GLfloat)rand() / (GLfloat)RAND_MAX;
+      deg_rot_y_inc = -deg_rot_y_inc;
+   }
+   if ( ball_x < -(BOUNCE_HEIGHT/2 + WALL_L_OFFSET) )
+   {
+      ball_x_inc =  0.5f + 0.75f * (GLfloat)rand() / (GLfloat)RAND_MAX;
+      deg_rot_y_inc = -deg_rot_y_inc;
+   }
+
+   /* Bounce on floor / roof */
+   if ( ball_y >  BOUNCE_HEIGHT/2      )
+   {
+      ball_y_inc = -0.75f - 1.f * (GLfloat)rand() / (GLfloat)RAND_MAX;
+   }
+   if ( ball_y < -BOUNCE_HEIGHT/2*0.85 )
+   {
+      ball_y_inc =  0.75f + 1.f * (GLfloat)rand() / (GLfloat)RAND_MAX;
+   }
+
+   /* Update ball position */
+   ball_x += ball_x_inc * ((float)delta_t*ANIMATION_SPEED);
+   ball_y += ball_y_inc * ((float)delta_t*ANIMATION_SPEED);
+
+  /*
+   * Simulate the effects of gravity on Y movement.
+   */
+   if ( ball_y_inc < 0 ) sign = -1.0; else sign = 1.0;
+
+   deg = (ball_y + BOUNCE_HEIGHT/2) * 90 / BOUNCE_HEIGHT;
+   if ( deg > 80 ) deg = 80;
+   if ( deg < 10 ) deg = 10;
+
+   ball_y_inc = sign * 4.f * (float) sin_deg( deg );
+}
+
+
+/*****************************************************************************
+ * Draw a faceted latitude band of the Boing ball.
+ *
+ * Parms:   long_lo, long_hi
+ *          Low and high longitudes of slice, resp.
+ *****************************************************************************/
+void DrawBoingBallBand( GLfloat long_lo,
+                        GLfloat long_hi )
+{
+   vertex_t vert_ne;            /* "ne" means south-east, so on */
+   vertex_t vert_nw;
+   vertex_t vert_sw;
+   vertex_t vert_se;
+   vertex_t vert_norm;
+   GLfloat  lat_deg;
+   static int colorToggle = 0;
+
+  /*
+   * Iterate through the points of a latitude circle.
+   * A latitude circle is a 2D set of X,Z points.
+   */
+   for ( lat_deg = 0;
+         lat_deg <= (360 - STEP_LATITUDE);
+         lat_deg += STEP_LATITUDE )
+   {
+     /*
+      * Color this polygon with red or white.
+      */
+      if ( colorToggle )
+         glColor3f( 0.8f, 0.1f, 0.1f );
+      else
+         glColor3f( 0.95f, 0.95f, 0.95f );
+#if 0
+      if ( lat_deg >= 180 )
+         if ( colorToggle )
+            glColor3f( 0.1f, 0.8f, 0.1f );
+         else
+            glColor3f( 0.5f, 0.5f, 0.95f );
+#endif
+      colorToggle = ! colorToggle;
+
+     /*
+      * Change color if drawing shadow.
+      */
+      if ( drawBallHow == DRAW_BALL_SHADOW )
+         glColor3f( 0.35f, 0.35f, 0.35f );
+
+     /*
+      * Assign each Y.
+      */
+      vert_ne.y = vert_nw.y = (float) cos_deg(long_hi) * RADIUS;
+      vert_sw.y = vert_se.y = (float) cos_deg(long_lo) * RADIUS;
+
+     /*
+      * Assign each X,Z with sin,cos values scaled by latitude radius indexed by longitude.
+      * Eg, long=0 and long=180 are at the poles, so zero scale is sin(longitude),
+      * while long=90 (sin(90)=1) is at equator.
+      */
+      vert_ne.x = (float) cos_deg( lat_deg                 ) * (RADIUS * (float) sin_deg( long_lo + STEP_LONGITUDE ));
+      vert_se.x = (float) cos_deg( lat_deg                 ) * (RADIUS * (float) sin_deg( long_lo                  ));
+      vert_nw.x = (float) cos_deg( lat_deg + STEP_LATITUDE ) * (RADIUS * (float) sin_deg( long_lo + STEP_LONGITUDE ));
+      vert_sw.x = (float) cos_deg( lat_deg + STEP_LATITUDE ) * (RADIUS * (float) sin_deg( long_lo                  ));
+
+      vert_ne.z = (float) sin_deg( lat_deg                 ) * (RADIUS * (float) sin_deg( long_lo + STEP_LONGITUDE ));
+      vert_se.z = (float) sin_deg( lat_deg                 ) * (RADIUS * (float) sin_deg( long_lo                  ));
+      vert_nw.z = (float) sin_deg( lat_deg + STEP_LATITUDE ) * (RADIUS * (float) sin_deg( long_lo + STEP_LONGITUDE ));
+      vert_sw.z = (float) sin_deg( lat_deg + STEP_LATITUDE ) * (RADIUS * (float) sin_deg( long_lo                  ));
+
+     /*
+      * Draw the facet.
+      */
+      glBegin( GL_POLYGON );
+
+      CrossProduct( vert_ne, vert_nw, vert_sw, &vert_norm );
+      glNormal3f( vert_norm.x, vert_norm.y, vert_norm.z );
+
+      glVertex3f( vert_ne.x, vert_ne.y, vert_ne.z );
+      glVertex3f( vert_nw.x, vert_nw.y, vert_nw.z );
+      glVertex3f( vert_sw.x, vert_sw.y, vert_sw.z );
+      glVertex3f( vert_se.x, vert_se.y, vert_se.z );
+
+      glEnd();
+
+#if BOING_DEBUG
+      printf( "----------------------------------------------------------- \n" );
+      printf( "lat = %f  long_lo = %f  long_hi = %f \n", lat_deg, long_lo, long_hi );
+      printf( "vert_ne  x = %.8f  y = %.8f  z = %.8f \n", vert_ne.x, vert_ne.y, vert_ne.z );
+      printf( "vert_nw  x = %.8f  y = %.8f  z = %.8f \n", vert_nw.x, vert_nw.y, vert_nw.z );
+      printf( "vert_se  x = %.8f  y = %.8f  z = %.8f \n", vert_se.x, vert_se.y, vert_se.z );
+      printf( "vert_sw  x = %.8f  y = %.8f  z = %.8f \n", vert_sw.x, vert_sw.y, vert_sw.z );
+#endif
+
+   }
+
+  /*
+   * Toggle color so that next band will opposite red/white colors than this one.
+   */
+   colorToggle = ! colorToggle;
+
+  /*
+   * This circular band is done.
+   */
+   return;
+}
+
+
+/*****************************************************************************
+ * Draw the purple grid of lines, behind the Boing ball.
+ * When the Workbench is dropped to the bottom, Boing shows 12 rows.
+ *****************************************************************************/
+void DrawGrid( void )
+{
+   int              row, col;
+   const int        rowTotal    = 12;                   /* must be divisible by 2 */
+   const int        colTotal    = rowTotal;             /* must be same as rowTotal */
+   const GLfloat    widthLine   = 2.0;                  /* should be divisible by 2 */
+   const GLfloat    sizeCell    = GRID_SIZE / rowTotal;
+   const GLfloat    z_offset    = -40.0;
+   GLfloat          xl, xr;
+   GLfloat          yt, yb;
+
+   glPushMatrix();
+   glDisable( GL_CULL_FACE );
+
+  /*
+   * Another relative Z translation to separate objects.
+   */
+   glTranslatef( 0.0, 0.0, DIST_BALL );
+
+  /*
+   * Draw vertical lines (as skinny 3D rectangles).
+   */
+   for ( col = 0; col <= colTotal; col++ )
+   {
+     /*
+      * Compute co-ords of line.
+      */
+      xl = -GRID_SIZE / 2 + col * sizeCell;
+      xr = xl + widthLine;
+
+      yt =  GRID_SIZE / 2;
+      yb = -GRID_SIZE / 2 - widthLine;
+
+      glBegin( GL_POLYGON );
+
+      glColor3f( 0.6f, 0.1f, 0.6f );               /* purple */
+
+      glVertex3f( xr, yt, z_offset );       /* NE */
+      glVertex3f( xl, yt, z_offset );       /* NW */
+      glVertex3f( xl, yb, z_offset );       /* SW */
+      glVertex3f( xr, yb, z_offset );       /* SE */
+
+      glEnd();
+   }
+
+  /*
+   * Draw horizontal lines (as skinny 3D rectangles).
+   */
+   for ( row = 0; row <= rowTotal; row++ )
+   {
+     /*
+      * Compute co-ords of line.
+      */
+      yt = GRID_SIZE / 2 - row * sizeCell;
+      yb = yt - widthLine;
+
+      xl = -GRID_SIZE / 2;
+      xr =  GRID_SIZE / 2 + widthLine;
+
+      glBegin( GL_POLYGON );
+
+      glColor3f( 0.6f, 0.1f, 0.6f );               /* purple */
+
+      glVertex3f( xr, yt, z_offset );       /* NE */
+      glVertex3f( xl, yt, z_offset );       /* NW */
+      glVertex3f( xl, yb, z_offset );       /* SW */
+      glVertex3f( xr, yb, z_offset );       /* SE */
+
+      glEnd();
+   }
+
+   glPopMatrix();
+
+   return;
+}
+
+
+/*======================================================================*
+ * main()
+ *======================================================================*/
+
+int main( void )
+{
+   GLFWwindow* window;
+
+   /* Init GLFW */
+   if( !glfwInit() )
+      exit( EXIT_FAILURE );
+
+   window = glfwCreateWindow( 400, 400, "Boing (classic Amiga demo)", NULL, NULL );
+   if (!window)
+   {
+       glfwTerminate();
+       exit( EXIT_FAILURE );
+   }
+
+   glfwSetWindowAspectRatio(window, 1, 1);
+
+   glfwSetFramebufferSizeCallback(window, reshape);
+   glfwSetKeyCallback(window, key_callback);
+   glfwSetMouseButtonCallback(window, mouse_button_callback);
+   glfwSetCursorPosCallback(window, cursor_position_callback);
+
+   glfwMakeContextCurrent(window);
+   gladLoadGL(glfwGetProcAddress);
+   glfwSwapInterval( 1 );
+
+   glfwGetFramebufferSize(window, &width, &height);
+   reshape(window, width, height);
+
+   glfwSetTime( 0.0 );
+
+   init();
+
+   /* Main loop */
+   for (;;)
+   {
+       /* Timing */
+       t = glfwGetTime();
+       dt = t - t_old;
+       t_old = t;
+
+       /* Draw one frame */
+       display();
+
+       /* Swap buffers */
+       glfwSwapBuffers(window);
+       glfwPollEvents();
+
+       /* Check if we are still running */
+       if (glfwWindowShouldClose(window))
+           break;
+   }
+
+   glfwTerminate();
+   exit( EXIT_SUCCESS );
+}
+

+ 360 - 0
samples/third_party/glfw/examples/gears.c

@@ -0,0 +1,360 @@
+/*
+ * 3-D gear wheels.  This program is in the public domain.
+ *
+ * Command line options:
+ *    -info      print GL implementation information
+ *    -exit      automatically exit after 30 seconds
+ *
+ *
+ * Brian Paul
+ *
+ *
+ * Marcus Geelnard:
+ *   - Conversion to GLFW
+ *   - Time based rendering (frame rate independent)
+ *   - Slightly modified camera that should work better for stereo viewing
+ *
+ *
+ * Camilla Löwy:
+ *   - Removed FPS counter (this is not a benchmark)
+ *   - Added a few comments
+ *   - Enabled vsync
+ */
+
+#if defined(_MSC_VER)
+ // Make MS math.h define M_PI
+ #define _USE_MATH_DEFINES
+#endif
+
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <glad/gl.h>
+#define GLFW_INCLUDE_NONE
+#include <GLFW/glfw3.h>
+
+/**
+
+  Draw a gear wheel.  You'll probably want to call this function when
+  building a display list since we do a lot of trig here.
+
+  Input:  inner_radius - radius of hole at center
+          outer_radius - radius at center of teeth
+          width - width of gear teeth - number of teeth
+          tooth_depth - depth of tooth
+
+ **/
+
+static void
+gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
+  GLint teeth, GLfloat tooth_depth)
+{
+  GLint i;
+  GLfloat r0, r1, r2;
+  GLfloat angle, da;
+  GLfloat u, v, len;
+
+  r0 = inner_radius;
+  r1 = outer_radius - tooth_depth / 2.f;
+  r2 = outer_radius + tooth_depth / 2.f;
+
+  da = 2.f * (float) M_PI / teeth / 4.f;
+
+  glShadeModel(GL_FLAT);
+
+  glNormal3f(0.f, 0.f, 1.f);
+
+  /* draw front face */
+  glBegin(GL_QUAD_STRIP);
+  for (i = 0; i <= teeth; i++) {
+    angle = i * 2.f * (float) M_PI / teeth;
+    glVertex3f(r0 * (float) cos(angle), r0 * (float) sin(angle), width * 0.5f);
+    glVertex3f(r1 * (float) cos(angle), r1 * (float) sin(angle), width * 0.5f);
+    if (i < teeth) {
+      glVertex3f(r0 * (float) cos(angle), r0 * (float) sin(angle), width * 0.5f);
+      glVertex3f(r1 * (float) cos(angle + 3 * da), r1 * (float) sin(angle + 3 * da), width * 0.5f);
+    }
+  }
+  glEnd();
+
+  /* draw front sides of teeth */
+  glBegin(GL_QUADS);
+  da = 2.f * (float) M_PI / teeth / 4.f;
+  for (i = 0; i < teeth; i++) {
+    angle = i * 2.f * (float) M_PI / teeth;
+
+    glVertex3f(r1 * (float) cos(angle), r1 * (float) sin(angle), width * 0.5f);
+    glVertex3f(r2 * (float) cos(angle + da), r2 * (float) sin(angle + da), width * 0.5f);
+    glVertex3f(r2 * (float) cos(angle + 2 * da), r2 * (float) sin(angle + 2 * da), width * 0.5f);
+    glVertex3f(r1 * (float) cos(angle + 3 * da), r1 * (float) sin(angle + 3 * da), width * 0.5f);
+  }
+  glEnd();
+
+  glNormal3f(0.0, 0.0, -1.0);
+
+  /* draw back face */
+  glBegin(GL_QUAD_STRIP);
+  for (i = 0; i <= teeth; i++) {
+    angle = i * 2.f * (float) M_PI / teeth;
+    glVertex3f(r1 * (float) cos(angle), r1 * (float) sin(angle), -width * 0.5f);
+    glVertex3f(r0 * (float) cos(angle), r0 * (float) sin(angle), -width * 0.5f);
+    if (i < teeth) {
+      glVertex3f(r1 * (float) cos(angle + 3 * da), r1 * (float) sin(angle + 3 * da), -width * 0.5f);
+      glVertex3f(r0 * (float) cos(angle), r0 * (float) sin(angle), -width * 0.5f);
+    }
+  }
+  glEnd();
+
+  /* draw back sides of teeth */
+  glBegin(GL_QUADS);
+  da = 2.f * (float) M_PI / teeth / 4.f;
+  for (i = 0; i < teeth; i++) {
+    angle = i * 2.f * (float) M_PI / teeth;
+
+    glVertex3f(r1 * (float) cos(angle + 3 * da), r1 * (float) sin(angle + 3 * da), -width * 0.5f);
+    glVertex3f(r2 * (float) cos(angle + 2 * da), r2 * (float) sin(angle + 2 * da), -width * 0.5f);
+    glVertex3f(r2 * (float) cos(angle + da), r2 * (float) sin(angle + da), -width * 0.5f);
+    glVertex3f(r1 * (float) cos(angle), r1 * (float) sin(angle), -width * 0.5f);
+  }
+  glEnd();
+
+  /* draw outward faces of teeth */
+  glBegin(GL_QUAD_STRIP);
+  for (i = 0; i < teeth; i++) {
+    angle = i * 2.f * (float) M_PI / teeth;
+
+    glVertex3f(r1 * (float) cos(angle), r1 * (float) sin(angle), width * 0.5f);
+    glVertex3f(r1 * (float) cos(angle), r1 * (float) sin(angle), -width * 0.5f);
+    u = r2 * (float) cos(angle + da) - r1 * (float) cos(angle);
+    v = r2 * (float) sin(angle + da) - r1 * (float) sin(angle);
+    len = (float) sqrt(u * u + v * v);
+    u /= len;
+    v /= len;
+    glNormal3f(v, -u, 0.0);
+    glVertex3f(r2 * (float) cos(angle + da), r2 * (float) sin(angle + da), width * 0.5f);
+    glVertex3f(r2 * (float) cos(angle + da), r2 * (float) sin(angle + da), -width * 0.5f);
+    glNormal3f((float) cos(angle), (float) sin(angle), 0.f);
+    glVertex3f(r2 * (float) cos(angle + 2 * da), r2 * (float) sin(angle + 2 * da), width * 0.5f);
+    glVertex3f(r2 * (float) cos(angle + 2 * da), r2 * (float) sin(angle + 2 * da), -width * 0.5f);
+    u = r1 * (float) cos(angle + 3 * da) - r2 * (float) cos(angle + 2 * da);
+    v = r1 * (float) sin(angle + 3 * da) - r2 * (float) sin(angle + 2 * da);
+    glNormal3f(v, -u, 0.f);
+    glVertex3f(r1 * (float) cos(angle + 3 * da), r1 * (float) sin(angle + 3 * da), width * 0.5f);
+    glVertex3f(r1 * (float) cos(angle + 3 * da), r1 * (float) sin(angle + 3 * da), -width * 0.5f);
+    glNormal3f((float) cos(angle), (float) sin(angle), 0.f);
+  }
+
+  glVertex3f(r1 * (float) cos(0), r1 * (float) sin(0), width * 0.5f);
+  glVertex3f(r1 * (float) cos(0), r1 * (float) sin(0), -width * 0.5f);
+
+  glEnd();
+
+  glShadeModel(GL_SMOOTH);
+
+  /* draw inside radius cylinder */
+  glBegin(GL_QUAD_STRIP);
+  for (i = 0; i <= teeth; i++) {
+    angle = i * 2.f * (float) M_PI / teeth;
+    glNormal3f(-(float) cos(angle), -(float) sin(angle), 0.f);
+    glVertex3f(r0 * (float) cos(angle), r0 * (float) sin(angle), -width * 0.5f);
+    glVertex3f(r0 * (float) cos(angle), r0 * (float) sin(angle), width * 0.5f);
+  }
+  glEnd();
+
+}
+
+
+static GLfloat view_rotx = 20.f, view_roty = 30.f, view_rotz = 0.f;
+static GLint gear1, gear2, gear3;
+static GLfloat angle = 0.f;
+
+/* OpenGL draw function & timing */
+static void draw(void)
+{
+  glClearColor(0.0, 0.0, 0.0, 0.0);
+  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+  glPushMatrix();
+    glRotatef(view_rotx, 1.0, 0.0, 0.0);
+    glRotatef(view_roty, 0.0, 1.0, 0.0);
+    glRotatef(view_rotz, 0.0, 0.0, 1.0);
+
+    glPushMatrix();
+      glTranslatef(-3.0, -2.0, 0.0);
+      glRotatef(angle, 0.0, 0.0, 1.0);
+      glCallList(gear1);
+    glPopMatrix();
+
+    glPushMatrix();
+      glTranslatef(3.1f, -2.f, 0.f);
+      glRotatef(-2.f * angle - 9.f, 0.f, 0.f, 1.f);
+      glCallList(gear2);
+    glPopMatrix();
+
+    glPushMatrix();
+      glTranslatef(-3.1f, 4.2f, 0.f);
+      glRotatef(-2.f * angle - 25.f, 0.f, 0.f, 1.f);
+      glCallList(gear3);
+    glPopMatrix();
+
+  glPopMatrix();
+}
+
+
+/* update animation parameters */
+static void animate(void)
+{
+  angle = 100.f * (float) glfwGetTime();
+}
+
+
+/* change view angle, exit upon ESC */
+void key( GLFWwindow* window, int k, int s, int action, int mods )
+{
+  if( action != GLFW_PRESS ) return;
+
+  switch (k) {
+  case GLFW_KEY_Z:
+    if( mods & GLFW_MOD_SHIFT )
+      view_rotz -= 5.0;
+    else
+      view_rotz += 5.0;
+    break;
+  case GLFW_KEY_ESCAPE:
+    glfwSetWindowShouldClose(window, GLFW_TRUE);
+    break;
+  case GLFW_KEY_UP:
+    view_rotx += 5.0;
+    break;
+  case GLFW_KEY_DOWN:
+    view_rotx -= 5.0;
+    break;
+  case GLFW_KEY_LEFT:
+    view_roty += 5.0;
+    break;
+  case GLFW_KEY_RIGHT:
+    view_roty -= 5.0;
+    break;
+  default:
+    return;
+  }
+}
+
+
+/* new window size */
+void reshape( GLFWwindow* window, int width, int height )
+{
+  GLfloat h = (GLfloat) height / (GLfloat) width;
+  GLfloat xmax, znear, zfar;
+
+  znear = 5.0f;
+  zfar  = 30.0f;
+  xmax  = znear * 0.5f;
+
+  glViewport( 0, 0, (GLint) width, (GLint) height );
+  glMatrixMode( GL_PROJECTION );
+  glLoadIdentity();
+  glFrustum( -xmax, xmax, -xmax*h, xmax*h, znear, zfar );
+  glMatrixMode( GL_MODELVIEW );
+  glLoadIdentity();
+  glTranslatef( 0.0, 0.0, -20.0 );
+}
+
+
+/* program & OpenGL initialization */
+static void init(void)
+{
+  static GLfloat pos[4] = {5.f, 5.f, 10.f, 0.f};
+  static GLfloat red[4] = {0.8f, 0.1f, 0.f, 1.f};
+  static GLfloat green[4] = {0.f, 0.8f, 0.2f, 1.f};
+  static GLfloat blue[4] = {0.2f, 0.2f, 1.f, 1.f};
+
+  glLightfv(GL_LIGHT0, GL_POSITION, pos);
+  glEnable(GL_CULL_FACE);
+  glEnable(GL_LIGHTING);
+  glEnable(GL_LIGHT0);
+  glEnable(GL_DEPTH_TEST);
+
+  /* make the gears */
+  gear1 = glGenLists(1);
+  glNewList(gear1, GL_COMPILE);
+  glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
+  gear(1.f, 4.f, 1.f, 20, 0.7f);
+  glEndList();
+
+  gear2 = glGenLists(1);
+  glNewList(gear2, GL_COMPILE);
+  glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
+  gear(0.5f, 2.f, 2.f, 10, 0.7f);
+  glEndList();
+
+  gear3 = glGenLists(1);
+  glNewList(gear3, GL_COMPILE);
+  glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue);
+  gear(1.3f, 2.f, 0.5f, 10, 0.7f);
+  glEndList();
+
+  glEnable(GL_NORMALIZE);
+}
+
+
+/* program entry */
+int main(int argc, char *argv[])
+{
+    GLFWwindow* window;
+    int width, height;
+
+    if( !glfwInit() )
+    {
+        fprintf( stderr, "Failed to initialize GLFW\n" );
+        exit( EXIT_FAILURE );
+    }
+
+    glfwWindowHint(GLFW_DEPTH_BITS, 16);
+    glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE);
+
+    window = glfwCreateWindow( 300, 300, "Gears", NULL, NULL );
+    if (!window)
+    {
+        fprintf( stderr, "Failed to open GLFW window\n" );
+        glfwTerminate();
+        exit( EXIT_FAILURE );
+    }
+
+    // Set callback functions
+    glfwSetFramebufferSizeCallback(window, reshape);
+    glfwSetKeyCallback(window, key);
+
+    glfwMakeContextCurrent(window);
+    gladLoadGL(glfwGetProcAddress);
+    glfwSwapInterval( 1 );
+
+    glfwGetFramebufferSize(window, &width, &height);
+    reshape(window, width, height);
+
+    // Parse command-line options
+    init();
+
+    // Main loop
+    while( !glfwWindowShouldClose(window) )
+    {
+        // Draw gears
+        draw();
+
+        // Update animation
+        animate();
+
+        // Swap buffers
+        glfwSwapBuffers(window);
+        glfwPollEvents();
+    }
+
+    // Terminate GLFW
+    glfwTerminate();
+
+    // Exit program
+    exit( EXIT_SUCCESS );
+}
+

BIN
samples/third_party/glfw/examples/glfw.icns


BIN
samples/third_party/glfw/examples/glfw.ico


+ 0 - 0
samples/third_party/glfw/examples/glfw.rc


この差分においてかなりの量のファイルが変更されているため、一部のファイルを表示していません